diff mbox

[v2] target-ppc: ppc can be either endian

Message ID 20140429090715.25567.39632.stgit@bahia.lab.toulouse-stg.fr.ibm.com
State New
Headers show

Commit Message

Greg Kurz April 29, 2014, 9:15 a.m. UTC
POWER7, POWER7+ and POWER8 families use the ILE bit of the LPCR
special purpose register to decide the endianness to use when
entering interrupt handlers. When running a Linux guest, this
provides a hint on the endianness used by the kernel. From a
QEMU point of view, the information is needed for legacy virtio
support and crash dump support as well.

Suggested-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Suggested-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
---

Changes for v2:
- the interrupts_big_endian method now takes a PowerPCCPU * arg
- added the ppc_cpu_ prefix to the interrupts_big_endian_* functions
- added white line in ppc_cpu_interrupts_big_endian()
- s/qemu/QEMU and s/linux/Linux in the commit message

Andreas,

I did not lowercase ppc_cpu_interrupts_big_endian_POWER7 as most of the
recent additions for POWER8 and POWER7+ have uppercase in the function
names.

Regards.

--
Greg

 target-ppc/cpu-qom.h        |    2 ++
 target-ppc/misc_helper.c    |    8 ++++++++
 target-ppc/translate_init.c |   16 ++++++++++++++++
 3 files changed, 26 insertions(+)

Comments

Alexander Graf April 29, 2014, 9:22 a.m. UTC | #1
On 29.04.14 11:15, Greg Kurz wrote:
> POWER7, POWER7+ and POWER8 families use the ILE bit of the LPCR
> special purpose register to decide the endianness to use when
> entering interrupt handlers. When running a Linux guest, this
> provides a hint on the endianness used by the kernel. From a
> QEMU point of view, the information is needed for legacy virtio
> support and crash dump support as well.
>
> Suggested-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Suggested-by: Alexander Graf <agraf@suse.de>
> Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
> ---
>
> Changes for v2:
> - the interrupts_big_endian method now takes a PowerPCCPU * arg
> - added the ppc_cpu_ prefix to the interrupts_big_endian_* functions
> - added white line in ppc_cpu_interrupts_big_endian()
> - s/qemu/QEMU and s/linux/Linux in the commit message
>
> Andreas,
>
> I did not lowercase ppc_cpu_interrupts_big_endian_POWER7 as most of the
> recent additions for POWER8 and POWER7+ have uppercase in the function
> names.
>
> Regards.
>
> --
> Greg
>
>   target-ppc/cpu-qom.h        |    2 ++
>   target-ppc/misc_helper.c    |    8 ++++++++
>   target-ppc/translate_init.c |   16 ++++++++++++++++
>   3 files changed, 26 insertions(+)
>
> diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
> index 47dc8e6..beec3ab 100644
> --- a/target-ppc/cpu-qom.h
> +++ b/target-ppc/cpu-qom.h
> @@ -76,6 +76,7 @@ typedef struct PowerPCCPUClass {
>       int (*handle_mmu_fault)(PowerPCCPU *cpu, target_ulong eaddr, int rwx,
>                               int mmu_idx);
>   #endif
> +    bool (*interrupts_big_endian)(PowerPCCPU *cpu);
>   } PowerPCCPUClass;
>   
>   /**
> @@ -118,6 +119,7 @@ int ppc64_cpu_write_elf64_qemunote(WriteCoreDumpFunction f,
>                                      CPUState *cpu, void *opaque);
>   int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
>                                  int cpuid, void *opaque);
> +bool ppc_cpu_interrupts_big_endian(CPUState *cs);
>   #ifndef CONFIG_USER_ONLY
>   extern const struct VMStateDescription vmstate_ppc_cpu;
>   #endif
> diff --git a/target-ppc/misc_helper.c b/target-ppc/misc_helper.c
> index 2eb2fa6..2bc3ba3 100644
> --- a/target-ppc/misc_helper.c
> +++ b/target-ppc/misc_helper.c
> @@ -120,3 +120,11 @@ void ppc_store_msr(CPUPPCState *env, target_ulong value)
>   {
>       hreg_store_msr(env, value, 0);
>   }
> +
> +bool ppc_cpu_interrupts_big_endian(CPUState *cs)
> +{
> +    PowerPCCPU *cpu = POWERPC_CPU(cs);
> +    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
> +
> +    return pcc->interrupts_big_endian(cpu);

No need for this. Please open code this helper in the calling code.


Alex
Greg Kurz April 29, 2014, 2:30 p.m. UTC | #2
On Tue, 29 Apr 2014 11:22:38 +0200
Alexander Graf <agraf@suse.de> wrote:
> 
> On 29.04.14 11:15, Greg Kurz wrote:
> > POWER7, POWER7+ and POWER8 families use the ILE bit of the LPCR
> > special purpose register to decide the endianness to use when
> > entering interrupt handlers. When running a Linux guest, this
> > provides a hint on the endianness used by the kernel. From a
> > QEMU point of view, the information is needed for legacy virtio
> > support and crash dump support as well.
> >
> > Suggested-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> > Suggested-by: Alexander Graf <agraf@suse.de>
> > Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
> > ---
> >
> > Changes for v2:
> > - the interrupts_big_endian method now takes a PowerPCCPU * arg
> > - added the ppc_cpu_ prefix to the interrupts_big_endian_* functions
> > - added white line in ppc_cpu_interrupts_big_endian()
> > - s/qemu/QEMU and s/linux/Linux in the commit message
> >
> > Andreas,
> >
> > I did not lowercase ppc_cpu_interrupts_big_endian_POWER7 as most of the
> > recent additions for POWER8 and POWER7+ have uppercase in the function
> > names.
> >
> > Regards.
> >
> > --
> > Greg
> >
> >   target-ppc/cpu-qom.h        |    2 ++
> >   target-ppc/misc_helper.c    |    8 ++++++++
> >   target-ppc/translate_init.c |   16 ++++++++++++++++
> >   3 files changed, 26 insertions(+)
> >
> > diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
> > index 47dc8e6..beec3ab 100644
> > --- a/target-ppc/cpu-qom.h
> > +++ b/target-ppc/cpu-qom.h
> > @@ -76,6 +76,7 @@ typedef struct PowerPCCPUClass {
> >       int (*handle_mmu_fault)(PowerPCCPU *cpu, target_ulong eaddr, int rwx,
> >                               int mmu_idx);
> >   #endif
> > +    bool (*interrupts_big_endian)(PowerPCCPU *cpu);
> >   } PowerPCCPUClass;
> >   
> >   /**
> > @@ -118,6 +119,7 @@ int ppc64_cpu_write_elf64_qemunote(WriteCoreDumpFunction f,
> >                                      CPUState *cpu, void *opaque);
> >   int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
> >                                  int cpuid, void *opaque);
> > +bool ppc_cpu_interrupts_big_endian(CPUState *cs);
> >   #ifndef CONFIG_USER_ONLY
> >   extern const struct VMStateDescription vmstate_ppc_cpu;
> >   #endif
> > diff --git a/target-ppc/misc_helper.c b/target-ppc/misc_helper.c
> > index 2eb2fa6..2bc3ba3 100644
> > --- a/target-ppc/misc_helper.c
> > +++ b/target-ppc/misc_helper.c
> > @@ -120,3 +120,11 @@ void ppc_store_msr(CPUPPCState *env, target_ulong value)
> >   {
> >       hreg_store_msr(env, value, 0);
> >   }
> > +
> > +bool ppc_cpu_interrupts_big_endian(CPUState *cs)
> > +{
> > +    PowerPCCPU *cpu = POWERPC_CPU(cs);
> > +    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
> > +
> > +    return pcc->interrupts_big_endian(cpu);
> 
> No need for this. Please open code this helper in the calling code.
> 

You may know that I have another user for this in the virtio endian patch set...
of course, I understand that virtio may take some more time to mature and this
helper could sit there for a long time... So should I open code it anyway ?

> 
> Alex
> 
> 

Alex,
Alexander Graf April 29, 2014, 2:34 p.m. UTC | #3
On 29.04.14 16:30, Greg Kurz wrote:
> On Tue, 29 Apr 2014 11:22:38 +0200
> Alexander Graf <agraf@suse.de> wrote:
>> On 29.04.14 11:15, Greg Kurz wrote:
>>> POWER7, POWER7+ and POWER8 families use the ILE bit of the LPCR
>>> special purpose register to decide the endianness to use when
>>> entering interrupt handlers. When running a Linux guest, this
>>> provides a hint on the endianness used by the kernel. From a
>>> QEMU point of view, the information is needed for legacy virtio
>>> support and crash dump support as well.
>>>
>>> Suggested-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>>> Suggested-by: Alexander Graf <agraf@suse.de>
>>> Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
>>> ---
>>>
>>> Changes for v2:
>>> - the interrupts_big_endian method now takes a PowerPCCPU * arg
>>> - added the ppc_cpu_ prefix to the interrupts_big_endian_* functions
>>> - added white line in ppc_cpu_interrupts_big_endian()
>>> - s/qemu/QEMU and s/linux/Linux in the commit message
>>>
>>> Andreas,
>>>
>>> I did not lowercase ppc_cpu_interrupts_big_endian_POWER7 as most of the
>>> recent additions for POWER8 and POWER7+ have uppercase in the function
>>> names.
>>>
>>> Regards.
>>>
>>> --
>>> Greg
>>>
>>>    target-ppc/cpu-qom.h        |    2 ++
>>>    target-ppc/misc_helper.c    |    8 ++++++++
>>>    target-ppc/translate_init.c |   16 ++++++++++++++++
>>>    3 files changed, 26 insertions(+)
>>>
>>> diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
>>> index 47dc8e6..beec3ab 100644
>>> --- a/target-ppc/cpu-qom.h
>>> +++ b/target-ppc/cpu-qom.h
>>> @@ -76,6 +76,7 @@ typedef struct PowerPCCPUClass {
>>>        int (*handle_mmu_fault)(PowerPCCPU *cpu, target_ulong eaddr, int rwx,
>>>                                int mmu_idx);
>>>    #endif
>>> +    bool (*interrupts_big_endian)(PowerPCCPU *cpu);
>>>    } PowerPCCPUClass;
>>>    
>>>    /**
>>> @@ -118,6 +119,7 @@ int ppc64_cpu_write_elf64_qemunote(WriteCoreDumpFunction f,
>>>                                       CPUState *cpu, void *opaque);
>>>    int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
>>>                                   int cpuid, void *opaque);
>>> +bool ppc_cpu_interrupts_big_endian(CPUState *cs);
>>>    #ifndef CONFIG_USER_ONLY
>>>    extern const struct VMStateDescription vmstate_ppc_cpu;
>>>    #endif
>>> diff --git a/target-ppc/misc_helper.c b/target-ppc/misc_helper.c
>>> index 2eb2fa6..2bc3ba3 100644
>>> --- a/target-ppc/misc_helper.c
>>> +++ b/target-ppc/misc_helper.c
>>> @@ -120,3 +120,11 @@ void ppc_store_msr(CPUPPCState *env, target_ulong value)
>>>    {
>>>        hreg_store_msr(env, value, 0);
>>>    }
>>> +
>>> +bool ppc_cpu_interrupts_big_endian(CPUState *cs)
>>> +{
>>> +    PowerPCCPU *cpu = POWERPC_CPU(cs);
>>> +    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
>>> +
>>> +    return pcc->interrupts_big_endian(cpu);
>> No need for this. Please open code this helper in the calling code.
>>
> You may know that I have another user for this in the virtio endian patch set...
> of course, I understand that virtio may take some more time to mature and this
> helper could sit there for a long time... So should I open code it anyway ?

Yes, please. Recreate this as a static function when you do the virtio 
patch set.


Alex
diff mbox

Patch

diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index 47dc8e6..beec3ab 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -76,6 +76,7 @@  typedef struct PowerPCCPUClass {
     int (*handle_mmu_fault)(PowerPCCPU *cpu, target_ulong eaddr, int rwx,
                             int mmu_idx);
 #endif
+    bool (*interrupts_big_endian)(PowerPCCPU *cpu);
 } PowerPCCPUClass;
 
 /**
@@ -118,6 +119,7 @@  int ppc64_cpu_write_elf64_qemunote(WriteCoreDumpFunction f,
                                    CPUState *cpu, void *opaque);
 int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
                                int cpuid, void *opaque);
+bool ppc_cpu_interrupts_big_endian(CPUState *cs);
 #ifndef CONFIG_USER_ONLY
 extern const struct VMStateDescription vmstate_ppc_cpu;
 #endif
diff --git a/target-ppc/misc_helper.c b/target-ppc/misc_helper.c
index 2eb2fa6..2bc3ba3 100644
--- a/target-ppc/misc_helper.c
+++ b/target-ppc/misc_helper.c
@@ -120,3 +120,11 @@  void ppc_store_msr(CPUPPCState *env, target_ulong value)
 {
     hreg_store_msr(env, value, 0);
 }
+
+bool ppc_cpu_interrupts_big_endian(CPUState *cs)
+{
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+
+    return pcc->interrupts_big_endian(cpu);
+}
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 7f53c33..0355813 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -3102,6 +3102,18 @@  static int check_pow_hid0_74xx (CPUPPCState *env)
     return 0;
 }
 
+static bool ppc_cpu_interrupts_big_endian_always(PowerPCCPU *cpu)
+{
+    return true;
+}
+
+#ifdef TARGET_PPC64
+static bool ppc_cpu_interrupts_big_endian_POWER7(PowerPCCPU *cpu)
+{
+    return !(cpu->env.spr[SPR_LPCR] & LPCR_ILE);
+}
+#endif
+
 /*****************************************************************************/
 /* PowerPC implementations definitions                                       */
 
@@ -7089,6 +7101,7 @@  POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_VSX;
     pcc->l1_dcache_size = 0x8000;
     pcc->l1_icache_size = 0x8000;
+    pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_POWER7;
 }
 
 POWERPC_FAMILY(POWER7P)(ObjectClass *oc, void *data)
@@ -7132,6 +7145,7 @@  POWERPC_FAMILY(POWER7P)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_VSX;
     pcc->l1_dcache_size = 0x8000;
     pcc->l1_icache_size = 0x8000;
+    pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_POWER7;
 }
 
 static void init_proc_POWER8(CPUPPCState *env)
@@ -7189,6 +7203,7 @@  POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
                  POWERPC_FLAG_VSX;
     pcc->l1_dcache_size = 0x8000;
     pcc->l1_icache_size = 0x8000;
+    pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_POWER7;
 }
 #endif /* defined (TARGET_PPC64) */
 
@@ -8511,6 +8526,7 @@  static void ppc_cpu_class_init(ObjectClass *oc, void *data)
     pcc->parent_realize = dc->realize;
     pcc->pvr = CPU_POWERPC_DEFAULT_MASK;
     pcc->pvr_mask = CPU_POWERPC_DEFAULT_MASK;
+    pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_always;
     dc->realize = ppc_cpu_realizefn;
     dc->unrealize = ppc_cpu_unrealizefn;