summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-07-08 11:38:12 +0100
committerPeter Maydell <peter.maydell@linaro.org>2014-07-08 11:38:12 +0100
commiteaa4980185943da6e36f6f2e052d41924705e1ea (patch)
treebbe6af7da0d5c6371828225df193449eec1b82ce
parent128f0e66149afb2dfc325dfd183aac345f417763 (diff)
parent0c6ab8c988830d3fe01c4ee88100a95ea95c49fa (diff)
downloadfocaccia-qemu-eaa4980185943da6e36f6f2e052d41924705e1ea.tar.gz
focaccia-qemu-eaa4980185943da6e36f6f2e052d41924705e1ea.zip
Merge remote-tracking branch 'remotes/agraf/tags/signed-ppc-for-upstream' into staging
Patch queue for ppc - 2014-07-08

A few bug fixes for 2.1:

  - Fix e500* TLB emulation with qemu-system-ppc
  - Update SLOF to current upstream (good number of bugfixes)
  - Make POWER7 / POWER8 PVR match more agnostic (needed in 2.1 for cmdline compat)
  - Fix u-boot.e500 install (how did that happen?)
  - Fix H_CAS on LE hosts
  - ppc64le-linux-user fixes

# gpg: Signature made Tue 08 Jul 2014 11:18:58 BST using RSA key ID 03FEDC60
# gpg: Can't check signature: public key not found

* remotes/agraf/tags/signed-ppc-for-upstream:
  PPC: e500: Actually install u-boot.e500
  target-ppc: Remove POWER7+ and POWER8E families
  target-ppc: Add pvr_match() callback
  pseries: Update SLOF firmware image to qemu-slof-20140630
  PPC: Fix booke206 TLB with phys addrs > 32bit
  target-ppc: Fix gdbstub for ppc64le-linux-user
  target-ppc: Change default cpu for ppc64le-linux-user
  target-ppc: KVMPPC_H_CAS fix cpu-version endianess

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--Makefile3
-rw-r--r--hw/ppc/spapr.c3
-rw-r--r--linux-user/main.c8
-rw-r--r--pc-bios/README2
-rw-r--r--pc-bios/slof.binbin921720 -> 923896 bytes
m---------roms/SLOF0
-rw-r--r--target-ppc/cpu-models.c5
-rw-r--r--target-ppc/cpu-models.h6
-rw-r--r--target-ppc/cpu-qom.h2
-rw-r--r--target-ppc/gdbstub.c34
-rw-r--r--target-ppc/mmu_helper.c6
-rw-r--r--target-ppc/translate_init.c122
12 files changed, 69 insertions, 122 deletions
diff --git a/Makefile b/Makefile
index 1eea0c418f..d6b9dc1ebe 100644
--- a/Makefile
+++ b/Makefile
@@ -344,7 +344,8 @@ multiboot.bin linuxboot.bin kvmvapic.bin \
 s390-zipl.rom \
 s390-ccw.img \
 spapr-rtas.bin slof.bin \
-palcode-clipper
+palcode-clipper \
+u-boot.e500
 else
 BLOBS=
 endif
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index a8ba916970..a23c0f080e 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -160,8 +160,7 @@ static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu,
     int index = ppc_get_vcpu_dt_id(cpu);
 
     if (cpu->cpu_version) {
-        ret = fdt_setprop(fdt, offset, "cpu-version",
-                          &cpu->cpu_version, sizeof(cpu->cpu_version));
+        ret = fdt_setprop_cell(fdt, offset, "cpu-version", cpu->cpu_version);
         if (ret < 0) {
             return ret;
         }
diff --git a/linux-user/main.c b/linux-user/main.c
index 900a17fa33..b453a39853 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3901,11 +3901,11 @@ int main(int argc, char **argv, char **envp)
 #elif defined TARGET_OPENRISC
         cpu_model = "or1200";
 #elif defined(TARGET_PPC)
-#ifdef TARGET_PPC64
-        cpu_model = "970fx";
-#else
+# ifdef TARGET_PPC64
+        cpu_model = "POWER7";
+# else
         cpu_model = "750";
-#endif
+# endif
 #else
         cpu_model = "any";
 #endif
diff --git a/pc-bios/README b/pc-bios/README
index 49cdacfaa5..edfadd7d38 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -17,7 +17,7 @@
 - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
   implementation for certain IBM POWER hardware.  The sources are at
   https://github.com/aik/SLOF, and the image currently in qemu is
-  built from git tag qemu-slof-20140404.
+  built from git tag qemu-slof-20140630.
 
 - sgabios (the Serial Graphics Adapter option ROM) provides a means for
   legacy x86 software to communicate with an attached serial console as
diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin
index 972e012e51..69b0a5dbc3 100644
--- a/pc-bios/slof.bin
+++ b/pc-bios/slof.bin
Binary files differdiff --git a/roms/SLOF b/roms/SLOF
-Subproject c90b50b5055f976a0da3c032f26fb80157292ad
+Subproject f284ab3f03ae69a20e1ae966f6ddf76da33cbf7
diff --git a/target-ppc/cpu-models.c b/target-ppc/cpu-models.c
index 9a91af9dbf..52ac6ec156 100644
--- a/target-ppc/cpu-models.c
+++ b/target-ppc/cpu-models.c
@@ -44,7 +44,6 @@
         PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);                       \
                                                                             \
         pcc->pvr          = _pvr;                                           \
-        pcc->pvr_mask     = CPU_POWERPC_DEFAULT_MASK;                       \
         pcc->svr          = _svr;                                           \
         dc->desc          = _desc;                                          \
     }                                                                       \
@@ -1136,9 +1135,9 @@
 #endif
     POWERPC_DEF("POWER7_v2.3",   CPU_POWERPC_POWER7_v23,             POWER7,
                 "POWER7 v2.3")
-    POWERPC_DEF("POWER7+_v2.1",  CPU_POWERPC_POWER7P_v21,            POWER7P,
+    POWERPC_DEF("POWER7+_v2.1",  CPU_POWERPC_POWER7P_v21,            POWER7,
                 "POWER7+ v2.1")
-    POWERPC_DEF("POWER8E_v1.0",  CPU_POWERPC_POWER8E_v10,            POWER8E,
+    POWERPC_DEF("POWER8E_v1.0",  CPU_POWERPC_POWER8E_v10,            POWER8,
                 "POWER8E v1.0")
     POWERPC_DEF("POWER8_v1.0",   CPU_POWERPC_POWER8_v10,             POWER8,
                 "POWER8 v1.0")
diff --git a/target-ppc/cpu-models.h b/target-ppc/cpu-models.h
index c39d03a504..290a7597dc 100644
--- a/target-ppc/cpu-models.h
+++ b/target-ppc/cpu-models.h
@@ -39,7 +39,6 @@ extern PowerPCCPUAlias ppc_cpu_aliases[];
 /*****************************************************************************/
 /* PVR definitions for most known PowerPC                                    */
 enum {
-    CPU_POWERPC_DEFAULT_MASK       = 0xFFFFFFFF,
     /* PowerPC 401 family */
     /* Generic PowerPC 401 */
 #define CPU_POWERPC_401              CPU_POWERPC_401G2
@@ -553,17 +552,14 @@ enum {
     CPU_POWERPC_POWER6             = 0x003E0000,
     CPU_POWERPC_POWER6_5           = 0x0F000001, /* POWER6 in POWER5 mode */
     CPU_POWERPC_POWER6A            = 0x0F000002,
+    CPU_POWERPC_POWER_SERVER_MASK  = 0xFFFF0000,
     CPU_POWERPC_POWER7_BASE        = 0x003F0000,
-    CPU_POWERPC_POWER7_MASK        = 0xFFFF0000,
     CPU_POWERPC_POWER7_v23         = 0x003F0203,
     CPU_POWERPC_POWER7P_BASE       = 0x004A0000,
-    CPU_POWERPC_POWER7P_MASK       = 0xFFFF0000,
     CPU_POWERPC_POWER7P_v21        = 0x004A0201,
     CPU_POWERPC_POWER8E_BASE       = 0x004B0000,
-    CPU_POWERPC_POWER8E_MASK       = 0xFFFF0000,
     CPU_POWERPC_POWER8E_v10        = 0x004B0100,
     CPU_POWERPC_POWER8_BASE        = 0x004D0000,
-    CPU_POWERPC_POWER8_MASK        = 0xFFFF0000,
     CPU_POWERPC_POWER8_v10         = 0x004D0100,
     CPU_POWERPC_970                = 0x00390202,
     CPU_POWERPC_970FX_v10          = 0x00391100,
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index f1f0a52998..0fee36f06a 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -56,7 +56,7 @@ typedef struct PowerPCCPUClass {
     void (*parent_reset)(CPUState *cpu);
 
     uint32_t pvr;
-    uint32_t pvr_mask;
+    bool (*pvr_match)(struct PowerPCCPUClass *pcc, uint32_t pvr);
     uint64_t pcr_mask;
     uint32_t svr;
     uint64_t insns_flags;
diff --git a/target-ppc/gdbstub.c b/target-ppc/gdbstub.c
index 694d303e19..14675f4565 100644
--- a/target-ppc/gdbstub.c
+++ b/target-ppc/gdbstub.c
@@ -83,16 +83,24 @@ static int ppc_gdb_register_len(int n)
     }
 }
 
-
-static void ppc_gdb_swap_register(uint8_t *mem_buf, int n, int len)
+/* We need to present the registers to gdb in the "current" memory ordering.
+   For user-only mode we get this for free; TARGET_WORDS_BIGENDIAN is set to
+   the proper ordering for the binary, and cannot be changed.
+   For system mode, TARGET_WORDS_BIGENDIAN is always set, and we must check
+   the current mode of the chip to see if we're running in little-endian.  */
+static void maybe_bswap_register(CPUPPCState *env, uint8_t *mem_buf, int len)
 {
-    if (len == 4) {
+#ifndef CONFIG_USER_ONLY
+    if (!msr_le) {
+        /* do nothing */
+    } else if (len == 4) {
         bswap32s((uint32_t *)mem_buf);
     } else if (len == 8) {
         bswap64s((uint64_t *)mem_buf);
     } else {
         g_assert_not_reached();
     }
+#endif
 }
 
 /* Old gdb always expects FP registers.  Newer (xml-aware) gdb only
@@ -150,10 +158,7 @@ int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
             break;
         }
     }
-    if (msr_le) {
-        /* If cpu is in LE mode, convert memory contents to LE. */
-        ppc_gdb_swap_register(mem_buf, n, r);
-    }
+    maybe_bswap_register(env, mem_buf, r);
     return r;
 }
 
@@ -209,10 +214,7 @@ int ppc_cpu_gdb_read_register_apple(CPUState *cs, uint8_t *mem_buf, int n)
             break;
         }
     }
-    if (msr_le) {
-        /* If cpu is in LE mode, convert memory contents to LE. */
-        ppc_gdb_swap_register(mem_buf, n, r);
-    }
+    maybe_bswap_register(env, mem_buf, r);
     return r;
 }
 
@@ -225,10 +227,7 @@ int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
     if (!r) {
         return r;
     }
-    if (msr_le) {
-        /* If cpu is in LE mode, convert memory contents to LE. */
-        ppc_gdb_swap_register(mem_buf, n, r);
-    }
+    maybe_bswap_register(env, mem_buf, r);
     if (n < 32) {
         /* gprs */
         env->gpr[n] = ldtul_p(mem_buf);
@@ -278,10 +277,7 @@ int ppc_cpu_gdb_write_register_apple(CPUState *cs, uint8_t *mem_buf, int n)
     if (!r) {
         return r;
     }
-    if (msr_le) {
-        /* If cpu is in LE mode, convert memory contents to LE. */
-        ppc_gdb_swap_register(mem_buf, n, r);
-    }
+    maybe_bswap_register(env, mem_buf, r);
     if (n < 32) {
         /* gprs */
         env->gpr[n] = ldq_p(mem_buf);
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 4d6b1e20c0..4a34a73ad4 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -897,10 +897,10 @@ static hwaddr booke206_tlb_to_page_size(CPUPPCState *env,
 
 /* TLB check function for MAS based SoftTLBs */
 static int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
-                            hwaddr *raddrp,
-                     target_ulong address, uint32_t pid)
+                            hwaddr *raddrp, target_ulong address,
+                            uint32_t pid)
 {
-    target_ulong mask;
+    hwaddr mask;
     uint32_t tlb_pid;
 
     if (!msr_cm) {
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 2ab281069c..5eacd46a52 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -8062,6 +8062,17 @@ static void init_proc_POWER7 (CPUPPCState *env)
     init_proc_book3s_64(env, BOOK3S_CPU_POWER7);
 }
 
+static bool ppc_pvr_match_power7(PowerPCCPUClass *pcc, uint32_t pvr)
+{
+    if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER7P_BASE) {
+        return true;
+    }
+    if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER7_BASE) {
+        return true;
+    }
+    return false;
+}
+
 POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
@@ -8070,8 +8081,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
     dc->fw_name = "PowerPC,POWER7";
     dc->desc = "POWER7";
     dc->props = powerpc_servercpu_properties;
-    pcc->pvr = CPU_POWERPC_POWER7_BASE;
-    pcc->pvr_mask = CPU_POWERPC_POWER7_MASK;
+    pcc->pvr_match = ppc_pvr_match_power7;
     pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06;
     pcc->init_proc = init_proc_POWER7;
     pcc->check_pow = check_pow_nocheck;
@@ -8123,82 +8133,31 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
     pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
 }
 
-POWERPC_FAMILY(POWER7P)(ObjectClass *oc, void *data)
+static void init_proc_POWER8(CPUPPCState *env)
 {
-    DeviceClass *dc = DEVICE_CLASS(oc);
-    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
-
-    dc->fw_name = "PowerPC,POWER7+";
-    dc->desc = "POWER7+";
-    dc->props = powerpc_servercpu_properties;
-    pcc->pvr = CPU_POWERPC_POWER7P_BASE;
-    pcc->pvr_mask = CPU_POWERPC_POWER7P_MASK;
-    pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06;
-    pcc->init_proc = init_proc_POWER7;
-    pcc->check_pow = check_pow_nocheck;
-    pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
-                       PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
-                       PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
-                       PPC_FLOAT_FRSQRTES |
-                       PPC_FLOAT_STFIWX |
-                       PPC_FLOAT_EXT |
-                       PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
-                       PPC_MEM_SYNC | PPC_MEM_EIEIO |
-                       PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
-                       PPC_64B | PPC_ALTIVEC |
-                       PPC_SEGMENT_64B | PPC_SLBI |
-                       PPC_POPCNTB | PPC_POPCNTWD;
-    pcc->insns_flags2 = PPC2_VSX | PPC2_DFP | PPC2_DBRX | PPC2_ISA205 |
-                        PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 |
-                        PPC2_ATOMIC_ISA206 | PPC2_FP_CVT_ISA206 |
-                        PPC2_FP_TST_ISA206;
-    pcc->msr_mask = (1ull << MSR_SF) |
-                    (1ull << MSR_VR) |
-                    (1ull << MSR_VSX) |
-                    (1ull << MSR_EE) |
-                    (1ull << MSR_PR) |
-                    (1ull << MSR_FP) |
-                    (1ull << MSR_ME) |
-                    (1ull << MSR_FE0) |
-                    (1ull << MSR_SE) |
-                    (1ull << MSR_DE) |
-                    (1ull << MSR_FE1) |
-                    (1ull << MSR_IR) |
-                    (1ull << MSR_DR) |
-                    (1ull << MSR_PMM) |
-                    (1ull << MSR_RI) |
-                    (1ull << MSR_LE);
-    pcc->mmu_model = POWERPC_MMU_2_06;
-#if defined(CONFIG_SOFTMMU)
-    pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
-#endif
-    pcc->excp_model = POWERPC_EXCP_POWER7;
-    pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
-    pcc->bfd_mach = bfd_mach_ppc64;
-    pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
-                 POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
-                 POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR |
-                 POWERPC_FLAG_VSX;
-    pcc->l1_dcache_size = 0x8000;
-    pcc->l1_icache_size = 0x8000;
-    pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
+    init_proc_book3s_64(env, BOOK3S_CPU_POWER8);
 }
 
-static void init_proc_POWER8(CPUPPCState *env)
+static bool ppc_pvr_match_power8(PowerPCCPUClass *pcc, uint32_t pvr)
 {
-    init_proc_book3s_64(env, BOOK3S_CPU_POWER8);
+    if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER8E_BASE) {
+        return true;
+    }
+    if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER8_BASE) {
+        return true;
+    }
+    return false;
 }
 
-POWERPC_FAMILY(POWER8E)(ObjectClass *oc, void *data)
+POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
 
     dc->fw_name = "PowerPC,POWER8";
-    dc->desc = "POWER8E";
+    dc->desc = "POWER8";
     dc->props = powerpc_servercpu_properties;
-    pcc->pvr = CPU_POWERPC_POWER8E_BASE;
-    pcc->pvr_mask = CPU_POWERPC_POWER8E_MASK;
+    pcc->pvr_match = ppc_pvr_match_power8;
     pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06;
     pcc->init_proc = init_proc_POWER8;
     pcc->check_pow = check_pow_nocheck;
@@ -8252,18 +8211,6 @@ POWERPC_FAMILY(POWER8E)(ObjectClass *oc, void *data)
     pcc->l1_icache_size = 0x8000;
     pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
 }
-
-POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(oc);
-    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
-
-    ppc_POWER8E_cpu_family_class_init(oc, data);
-
-    dc->desc = "POWER8";
-    pcc->pvr = CPU_POWERPC_POWER8_BASE;
-    pcc->pvr_mask = CPU_POWERPC_POWER8_MASK;
-}
 #endif /* defined (TARGET_PPC64) */
 
 
@@ -9245,7 +9192,6 @@ static gint ppc_cpu_compare_class_pvr_mask(gconstpointer a, gconstpointer b)
     ObjectClass *oc = (ObjectClass *)a;
     uint32_t pvr = *(uint32_t *)b;
     PowerPCCPUClass *pcc = (PowerPCCPUClass *)a;
-    gint ret;
 
     /* -cpu host does a PVR lookup during construction */
     if (unlikely(strcmp(object_class_get_name(oc),
@@ -9257,9 +9203,11 @@ static gint ppc_cpu_compare_class_pvr_mask(gconstpointer a, gconstpointer b)
         return -1;
     }
 
-    ret = (((pcc->pvr & pcc->pvr_mask) == (pvr & pcc->pvr_mask)) ? 0 : -1);
+    if (pcc->pvr_match(pcc, pvr)) {
+        return 0;
+    }
 
-    return ret;
+    return -1;
 }
 
 PowerPCCPUClass *ppc_cpu_class_by_pvr_mask(uint32_t pvr)
@@ -9551,6 +9499,10 @@ static void ppc_cpu_reset(CPUState *s)
 #endif
 #if !defined(TARGET_WORDS_BIGENDIAN)
     msr |= (target_ulong)1 << MSR_LE; /* Little-endian user mode */
+    if (!((env->msr_mask >> MSR_LE) & 1)) {
+        fprintf(stderr, "Selected CPU does not support little-endian.\n");
+        exit(1);
+    }
 #endif
 #endif
 
@@ -9656,6 +9608,11 @@ static void ppc_cpu_initfn(Object *obj)
     }
 }
 
+static bool ppc_pvr_match_default(PowerPCCPUClass *pcc, uint32_t pvr)
+{
+    return pcc->pvr == pvr;
+}
+
 static void ppc_cpu_class_init(ObjectClass *oc, void *data)
 {
     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
@@ -9663,8 +9620,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
     DeviceClass *dc = DEVICE_CLASS(oc);
 
     pcc->parent_realize = dc->realize;
-    pcc->pvr = CPU_POWERPC_DEFAULT_MASK;
-    pcc->pvr_mask = CPU_POWERPC_DEFAULT_MASK;
+    pcc->pvr_match = ppc_pvr_match_default;
     pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_always;
     dc->realize = ppc_cpu_realizefn;
     dc->unrealize = ppc_cpu_unrealizefn;