diff mbox

[v2,1/2] target-mips: Rework ABIs to allow all required configurations

Message ID alpine.DEB.1.10.1412110007550.19155@tp.orcam.me.uk
State New
Headers show

Commit Message

Maciej W. Rozycki Dec. 11, 2014, 12:21 a.m. UTC
Rework the MIPS ABIs and CPU emulations available according to the 
following target list:

- mips|mipsel       -- 32-bit CPUs only, system and user emulation mode, 
                       o32 user ABI,

- mips64|mips64el   -- 32-bit and 64-bit CPUs, system and user emulation 
                       mode, o32 user ABI,

- mipsn32|mipsn32el -- 64-bit CPUs only, user emulation mode only, n32 
                       user ABI,

- mipsn64|mipsn64el -- 64-bit CPUs only, user emulation mode only, n64 
                       user ABI.

Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
Changes from v1:

- remove n32 and n64 system emulation mode configurations,

- fold 1/3 and 2/3 into 1/2.

qemu-mips64-abis.diff

Comments

Leon Alrae Feb. 9, 2015, 11:30 a.m. UTC | #1
On 11/12/2014 00:21, Maciej W. Rozycki wrote:
> Rework the MIPS ABIs and CPU emulations available according to the 
> following target list:
> 
> - mips|mipsel       -- 32-bit CPUs only, system and user emulation mode, 
>                        o32 user ABI,
> 
> - mips64|mips64el   -- 32-bit and 64-bit CPUs, system and user emulation 
>                        mode, o32 user ABI,

I'm not sure if it's a good idea to change the meaning of linux-user
qemu-mips64 and qemu-mips64el, this will cause unnecessary confusion in
my opinion. I think we’d be better off leaving it consistent across QEMU
versions.

Do we really need MIPS64 executables for o32 ABI for linux-user? They
would merely enable MIPS64 CPUs to run o32 programs. So far we've been
handling this by using 32-bit CPUs (artificial if the real CPU don't
exist), therefore I don't see an issue here. Also I'm concerned that
once we add new executables, it will be difficult to revert that change
later, thus we must be certain that this is the right way to go.

In general I would prefer to avoid changing the user interface and pain
related to breaking people's scripts whenever it's possible.

Regards,
Leon
Maciej W. Rozycki Feb. 9, 2015, 2:09 p.m. UTC | #2
On Mon, 9 Feb 2015, Leon Alrae wrote:

> > Rework the MIPS ABIs and CPU emulations available according to the 
> > following target list:
> > 
> > - mips|mipsel       -- 32-bit CPUs only, system and user emulation mode, 
> >                        o32 user ABI,
> > 
> > - mips64|mips64el   -- 32-bit and 64-bit CPUs, system and user emulation 
> >                        mode, o32 user ABI,
> 
> I'm not sure if it's a good idea to change the meaning of linux-user
> qemu-mips64 and qemu-mips64el, this will cause unnecessary confusion in
> my opinion. I think we’d be better off leaving it consistent across QEMU
> versions.

 Well, this is an example how the names could have been consistent from 
the beginning, and I actually agree we need to take a notion of what's 
already there.  So alternatively these could be called `mips64o32' and 
`mips64o32el' though I find these names somewhat ugly.  Although perhaps 
not anymore if we kept what we have now for backwards compatibility and 
added a set of uniform target names like this:

- mips32o32|mips32o32el (or maybe just mipso32|mipso32el),

- mips64o32|mips64o32el,

- mips64n64|mips64n64el,

- mips64n32|mips64n32el.

Or maybe just the three latters, leaving mips|mipsel as it is.  WDYT?

> Do we really need MIPS64 executables for o32 ABI for linux-user? They
> would merely enable MIPS64 CPUs to run o32 programs. So far we've been
> handling this by using 32-bit CPUs (artificial if the real CPU don't
> exist), therefore I don't see an issue here. Also I'm concerned that
> once we add new executables, it will be difficult to revert that change
> later, thus we must be certain that this is the right way to go.

 There is a slight difference for some processors that do not have 32-bit 
counterparts.  Think of an o32 program run on an R10000 processor, or, to 
pick a more modern example, a Loongson-2E CPU.  I think NetLogic or Cavium 
implementations qualify here as well.  I don't think hacking QEMU sources 
to add even more artificial silicon is a good way to address these cases.

  Maciej
Peter Maydell Feb. 9, 2015, 2:36 p.m. UTC | #3
Added RTH to cc because IIRC you did the last lot of rearranging how
we handle these "same CPU architecture, different ABI" variants of
linux-user...

On 9 February 2015 at 14:09, Maciej W. Rozycki <macro@linux-mips.org> wrote:
> On Mon, 9 Feb 2015, Leon Alrae wrote:
>
>> > Rework the MIPS ABIs and CPU emulations available according to the
>> > following target list:
>> >
>> > - mips|mipsel       -- 32-bit CPUs only, system and user emulation mode,
>> >                        o32 user ABI,
>> >
>> > - mips64|mips64el   -- 32-bit and 64-bit CPUs, system and user emulation
>> >                        mode, o32 user ABI,
>>
>> I'm not sure if it's a good idea to change the meaning of linux-user
>> qemu-mips64 and qemu-mips64el, this will cause unnecessary confusion in
>> my opinion. I think we’d be better off leaving it consistent across QEMU
>> versions.
>
>  Well, this is an example how the names could have been consistent from
> the beginning, and I actually agree we need to take a notion of what's
> already there.

I think "don't break executable names that are already present"
is a hard requirement. These get baked into binfmt-misc configurations
and effectively become part of QEMU's ABI to users.

> So alternatively these could be called `mips64o32' and
> `mips64o32el' though I find these names somewhat ugly.  Although perhaps
> not anymore if we kept what we have now for backwards compatibility and
> added a set of uniform target names like this:
>
> - mips32o32|mips32o32el (or maybe just mipso32|mipso32el),
>
> - mips64o32|mips64o32el,
>
> - mips64n64|mips64n64el,
>
> - mips64n32|mips64n32el.
>
> Or maybe just the three latters, leaving mips|mipsel as it is.  WDYT?

So which of these four does the current "mips64/mips64el" correspond
to? That's the third in the list, right? And the current mipsn32/mipsn32el
is the fourth? So this is adding alias names for our existing targets
and creating a new one? I think I'd just leave the current names and
define new target names where we need to.

If we could figure out and write down what the design principle
is for which targets to create to handle different ABIs in linux-user
that would be handy, because at some point I need to think about
this to handle the equivalent situation for ARM (a probable
upcoming ILP32 ABI, and what to do about running 32-bit code on
64-bit CPU definitions)...

thanks
-- PMM
Maciej W. Rozycki Feb. 11, 2015, 1:28 p.m. UTC | #4
On Mon, 9 Feb 2015, Peter Maydell wrote:

> >> I'm not sure if it's a good idea to change the meaning of linux-user
> >> qemu-mips64 and qemu-mips64el, this will cause unnecessary confusion in
> >> my opinion. I think we’d be better off leaving it consistent across QEMU
> >> versions.
> >
> >  Well, this is an example how the names could have been consistent from
> > the beginning, and I actually agree we need to take a notion of what's
> > already there.
> 
> I think "don't break executable names that are already present"
> is a hard requirement. These get baked into binfmt-misc configurations
> and effectively become part of QEMU's ABI to users.

 Acknowledged, I do recognise and accept the requirement.

> > So alternatively these could be called `mips64o32' and
> > `mips64o32el' though I find these names somewhat ugly.  Although perhaps
> > not anymore if we kept what we have now for backwards compatibility and
> > added a set of uniform target names like this:
> >
> > - mips32o32|mips32o32el (or maybe just mipso32|mipso32el),
> >
> > - mips64o32|mips64o32el,
> >
> > - mips64n64|mips64n64el,
> >
> > - mips64n32|mips64n32el.
> >
> > Or maybe just the three latters, leaving mips|mipsel as it is.  WDYT?
> 
> So which of these four does the current "mips64/mips64el" correspond
> to? That's the third in the list, right? And the current mipsn32/mipsn32el
> is the fourth?

 Correct.

> So this is adding alias names for our existing targets
> and creating a new one? I think I'd just leave the current names and
> define new target names where we need to.

 What I have been a bit concerned of is how the way these names were added 
(i.e. in an incremental manner and not really architected) results in what 
looks like a random selection of arbitrary names that are all but obvious 
to the user.

 Only "mipsn32/mipsn32el" have any notion of the selected ABI in the name, 
but then they lack any emphasis that this is a 64-bit ABI.  The remaining 
two pairs, "mips/mipsel" and "mips64/mips64el", respectively refer to 
architecture names rather than a particular ABI, in the traditional sense 
(such as used by the GNU config.guess/config.sub scripts or reported by 
uname(2) on Linux) merely meaning 32-bit or 64-bit MIPS processors without 
any further implication as to the ABI (of course in the context of Linux a 
32-bit CPU cannot support anything but o32, but that's an indirect 
implication only).

 Of course ideally we'd have a single executable supporting all the ABIs 
and selecting the right one on the fly.  Or maybe two, to account for the 
two endiannesses, although being able to switch that at the run time so 
that a single "interpreter" handles all MIPS executables would be a great 
feature too.  But that's a differenr matter, and if such a unified 
configuration is ever implemented, then we can simply alias all the 
individual configuration names invented until then to one another.

> If we could figure out and write down what the design principle
> is for which targets to create to handle different ABIs in linux-user
> that would be handy, because at some point I need to think about
> this to handle the equivalent situation for ARM (a probable
> upcoming ILP32 ABI, and what to do about running 32-bit code on
> 64-bit CPU definitions)...

 I think this is as simple as following what hardware offers, under the 
assumption that we want to be able to reproduce a simulated user-mode 
environment just as it would look like on actual hardware.  This could be 
for any reason, I think performance in the first place as QEMU run on a 
decent host machine can often be much, much faster than actual target 
hardware, and then the inability to reproduce target hardware beyond the 
CPU or to run a real Linux kernel on such hardware in the system emulation 
mode.

 So referring to the MIPS target -- as one I'm the most familiar with -- 
we have a choice of 3 Linux user ABIs in both endiannesses each.  And then 
we have a bunch of processors we already simulate or the simulation of 
which can be added, often in a straightforward manner as lots of 
documentation is available.  And now I expect to be able to pick any 
compatible CPU-ABI pair and simulate it.  It should correctly simulate all 
the instructions CPU implements and correctly trap with SIGILL on all the 
instructions CPU does not implement.  It can then be used for example for 
toolchain correctness validation.

 I don't know exactly how ARM architecture subsetting has been defined, 
but with the MIPS architecture it has been the case that 32-bit additions 
were added to a 64-bit architecture.  Specifically the MIPS IV 
architecture, a 64-bit one, added several features to the MIPS III 
architecture, also a 64-bit one.  These were conditional move operations, 
extra floating-point condition bits, the indexed addressing mode for 
floating-point load/store instructions and cache prefetch instructions. 
These were naturally available for 32-bit aka o32 programs run in the 
32-bit compatibility user mode.  This is unlike any 64-bit instructions as 
these are not allowed in the 32-bit compatibility user mode and trap with 
a Reserved Instruction exception as if they were unimplemented.

 More recently there have been vendor-specific architecture extensions 
added to 64-bit processors, that also affect o32 executable environment.  
At least one of them -- the Lemote Loongson-2E processor -- has been 
publicly documented and we already have support for its extensions in 
place.  Other extensions can follow if the respective vendors decide to 
either contribute their implementation or at least publish the specs.

 So I think as far as the MIPS target is concerned it makes sense to have 
64-bit processors enabled for o32 programs.  And I think for performance 
reasons it makes sense to keep a configuration with only 32-bit processors 
enabled as well.

 Does it make the design principles I have in mind any clearer to you?

  Maciej
diff mbox

Patch

Index: qemu-git-trunk/bsd-user/elfload.c
===================================================================
--- qemu-git-trunk.orig/bsd-user/elfload.c	2014-12-11 00:05:18.000000000 +0000
+++ qemu-git-trunk/bsd-user/elfload.c	2014-12-11 00:05:37.878938825 +0000
@@ -381,7 +381,7 @@  static inline void init_thread(struct ta
 
 #define elf_check_arch(x) ( (x) == EM_MIPS )
 
-#ifdef TARGET_MIPS64
+#ifdef TARGET_ABI_MIPSN64
 #define ELF_CLASS   ELFCLASS64
 #else
 #define ELF_CLASS   ELFCLASS32
Index: qemu-git-trunk/configure
===================================================================
--- qemu-git-trunk.orig/configure	2014-12-11 00:05:18.000000000 +0000
+++ qemu-git-trunk/configure	2014-12-11 00:05:37.878938825 +0000
@@ -4982,7 +4982,7 @@  target_name=`echo $target | cut -d '-' -
 target_bigendian="no"
 
 case "$target_name" in
-  armeb|lm32|m68k|microblaze|mips|mipsn32|mips64|moxie|or32|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
+  armeb|lm32|m68k|microblaze|mips|mips64|mipsn32|mipsn64|moxie|or32|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
   target_bigendian=yes
   ;;
 esac
@@ -5057,17 +5057,28 @@  case "$target_name" in
   ;;
   mips|mipsel)
     TARGET_ARCH=mips
+    echo "TARGET_MIPS32=y" >> $config_target_mak
     echo "TARGET_ABI_MIPSO32=y" >> $config_target_mak
   ;;
+  mips64|mips64el)
+    TARGET_ARCH=mips64
+    TARGET_BASE_ARCH=mips
+    TARGET_ABI_DIR=mips
+    echo "TARGET_MIPS32=y" >> $config_target_mak
+    echo "TARGET_ABI_MIPSO32=y" >> $config_target_mak
+    echo "TARGET_ABI32=y" >> $config_target_mak
+  ;;
   mipsn32|mipsn32el)
     TARGET_ARCH=mips64
     TARGET_BASE_ARCH=mips
+    TARGET_ABI_DIR=mips64
     echo "TARGET_ABI_MIPSN32=y" >> $config_target_mak
     echo "TARGET_ABI32=y" >> $config_target_mak
   ;;
-  mips64|mips64el)
+  mipsn64|mipsn64el)
     TARGET_ARCH=mips64
     TARGET_BASE_ARCH=mips
+    TARGET_ABI_DIR=mips64
     echo "TARGET_ABI_MIPSN64=y" >> $config_target_mak
   ;;
   tricore)
Index: qemu-git-trunk/default-configs/mipsn64-linux-user.mak
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ qemu-git-trunk/default-configs/mipsn64-linux-user.mak	2014-12-11 00:05:45.378923933 +0000
@@ -0,0 +1 @@ 
+# Default configuration for mipsn64-linux-user
Index: qemu-git-trunk/default-configs/mipsn64el-linux-user.mak
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ qemu-git-trunk/default-configs/mipsn64el-linux-user.mak	2014-12-11 00:05:45.378923933 +0000
@@ -0,0 +1 @@ 
+# Default configuration for mipsn64el-linux-user
Index: qemu-git-trunk/include/exec/poison.h
===================================================================
--- qemu-git-trunk.orig/include/exec/poison.h	2014-12-11 00:05:18.000000000 +0000
+++ qemu-git-trunk/include/exec/poison.h	2014-12-11 00:05:37.878938825 +0000
@@ -13,7 +13,11 @@ 
 #pragma GCC poison TARGET_LM32
 #pragma GCC poison TARGET_M68K
 #pragma GCC poison TARGET_MIPS
+#pragma GCC poison TARGET_MIPS32
 #pragma GCC poison TARGET_MIPS64
+#pragma GCC poison TARGET_ABI_MIPSO32
+#pragma GCC poison TARGET_ABI_MIPSN32
+#pragma GCC poison TARGET_ABI_MIPSN64
 #pragma GCC poison TARGET_OPENRISC
 #pragma GCC poison TARGET_PPC
 #pragma GCC poison TARGET_PPCEMB
Index: qemu-git-trunk/linux-user/elfload.c
===================================================================
--- qemu-git-trunk.orig/linux-user/elfload.c	2014-12-11 00:05:18.000000000 +0000
+++ qemu-git-trunk/linux-user/elfload.c	2014-12-11 00:05:37.878938825 +0000
@@ -875,7 +875,7 @@  static void elf_core_copy_regs(target_el
 
 #define elf_check_arch(x) ( (x) == EM_MIPS )
 
-#ifdef TARGET_MIPS64
+#ifdef TARGET_ABI_MIPSN64
 #define ELF_CLASS   ELFCLASS64
 #else
 #define ELF_CLASS   ELFCLASS32
@@ -896,10 +896,10 @@  typedef target_elf_greg_t target_elf_gre
 
 /* See linux kernel: arch/mips/include/asm/reg.h.  */
 enum {
-#ifdef TARGET_MIPS64
-    TARGET_EF_R0 = 0,
-#else
+#ifdef TARGET_ABI_MIPSO32
     TARGET_EF_R0 = 6,
+#else
+    TARGET_EF_R0 = 0,
 #endif
     TARGET_EF_R26 = TARGET_EF_R0 + 26,
     TARGET_EF_R27 = TARGET_EF_R0 + 27,
Index: qemu-git-trunk/linux-user/main.c
===================================================================
--- qemu-git-trunk.orig/linux-user/main.c	2014-12-11 00:05:18.000000000 +0000
+++ qemu-git-trunk/linux-user/main.c	2014-12-11 00:05:37.878938825 +0000
@@ -3928,7 +3928,7 @@  int main(int argc, char **argv, char **e
         cpu_model = "Fujitsu MB86904";
 #endif
 #elif defined(TARGET_MIPS)
-#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
+#ifdef TARGET_MIPS64
         cpu_model = "5KEf";
 #else
         cpu_model = "24Kf";
Index: qemu-git-trunk/target-mips/translate_init.c
===================================================================
--- qemu-git-trunk.orig/target-mips/translate_init.c	2014-12-11 00:05:18.000000000 +0000
+++ qemu-git-trunk/target-mips/translate_init.c	2014-12-11 00:05:37.878938825 +0000
@@ -107,6 +107,7 @@  struct mips_def_t {
 /* MIPS CPU definitions */
 static const mips_def_t mips_defs[] =
 {
+#if defined(TARGET_MIPS32)
     {
         .name = "4Kc",
         .CP0_PRid = 0x00018000,
@@ -421,6 +422,7 @@  static const mips_def_t mips_defs[] =
         .insn_flags = CPU_MIPS32R5 | ASE_MIPS16 | ASE_MSA,
         .mmu_type = MMU_TYPE_R4000,
     },
+#endif
 #if defined(TARGET_MIPS64)
     {
         .name = "R4000",