qemu-ppc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-ppc] [PATCH v2 2/2] target-ppc: add "compat" CPU option


From: Alexey Kardashevskiy
Subject: [Qemu-ppc] [PATCH v2 2/2] target-ppc: add "compat" CPU option
Date: Fri, 8 Nov 2013 19:22:43 +1100

To be able to boot on newer hardware that the software support,
PowerISA defines a logical PVR, one per every PowerISA specification
version from 2.04.

This adds the "compat" option which takes values 205 or 206 and forces
QEMU to boot the guest with a logical PVR (CPU_POWERPC_LOGICAL_2_05 or
CPU_POWERPC_LOGICAL_2_06).

The guest reads the logical PVR value from "cpu-version" property of
a CPU device node.

Cc: Nikunj A Dadhania <address@hidden>
Cc: Andreas Färber <address@hidden>
Signed-off-by: Alexey Kardashevskiy <address@hidden>
---
 hw/ppc/spapr.c              | 13 ++++++++-
 target-ppc/cpu-models.h     | 16 +++++++++++
 target-ppc/cpu.h            |  4 +++
 target-ppc/translate_init.c | 67 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 99 insertions(+), 1 deletion(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 7e53a5f..9fcbd96 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -206,6 +206,7 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment 
*spapr)
 
     CPU_FOREACH(cpu) {
         DeviceClass *dc = DEVICE_GET_CLASS(cpu);
+        CPUPPCState *env = &POWERPC_CPU(cpu)->env;
         uint32_t associativity[] = {cpu_to_be32(0x5),
                                     cpu_to_be32(0x0),
                                     cpu_to_be32(0x0),
@@ -238,6 +239,14 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment 
*spapr)
         if (ret < 0) {
             return ret;
         }
+
+        if (env->compat) {
+            ret = fdt_setprop(fdt, offset, "cpu-version",
+                              &env->compat, sizeof(env->compat));
+            if (ret < 0) {
+                return ret;
+            }
+        }
     }
     return ret;
 }
@@ -1101,7 +1110,7 @@ static SaveVMHandlers savevm_htab_handlers = {
 static void ppc_spapr_init(QEMUMachineInitArgs *args)
 {
     ram_addr_t ram_size = args->ram_size;
-    const char *cpu_model = args->cpu_model;
+    const char *cpu_model;
     const char *kernel_filename = args->kernel_filename;
     const char *kernel_cmdline = args->kernel_cmdline;
     const char *initrd_filename = args->initrd_filename;
@@ -1121,6 +1130,8 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
 
     msi_supported = true;
 
+    cpu_model = qemu_opt_get(qemu_get_cpu_opts(), "type");
+
     spapr = g_malloc0(sizeof(*spapr));
     QLIST_INIT(&spapr->phbs);
 
diff --git a/target-ppc/cpu-models.h b/target-ppc/cpu-models.h
index 49ba4a4..38f38d1 100644
--- a/target-ppc/cpu-models.h
+++ b/target-ppc/cpu-models.h
@@ -583,6 +583,16 @@ enum {
     CPU_POWERPC_RS64II             = 0x00340000,
     CPU_POWERPC_RS64III            = 0x00360000,
     CPU_POWERPC_RS64IV             = 0x00370000,
+
+    /* Logical CPUs */
+    CPU_POWERPC_LOGICAL_MASK       = 0xFFFFFFFF,
+    CPU_POWERPC_LOGICAL_2_04       = 0x0F000001,
+    CPU_POWERPC_LOGICAL_2_05       = 0x0F000002,
+    CPU_POWERPC_LOGICAL_2_06       = 0x0F000003,
+    CPU_POWERPC_LOGICAL_2_06_PLUS  = 0x0F100003,
+    CPU_POWERPC_LOGICAL_2_07       = 0x0F000004,
+    CPU_POWERPC_LOGICAL_2_08       = 0x0F000005,
+
 #endif /* defined(TARGET_PPC64) */
     /* Original POWER */
     /* XXX: should be POWER (RIOS), RSC3308, RSC4608,
@@ -745,4 +755,10 @@ enum {
     POWERPC_SVR_8641D              = 0x80900121,
 };
 
+/* Processor Compatibility Register (PCR) */
+enum {
+    POWERPC_ISA_COMPAT_2_05 = 1ULL << 62,
+    POWERPC_ISA_COMPAT_2_06 = 1ULL << 61,
+};
+
 #endif
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index bb84767..8e30518 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1006,6 +1006,9 @@ struct CPUPPCState {
     /* Device control registers */
     ppc_dcr_t *dcr_env;
 
+    /* Architecture compatibility mode PVR */
+    uint32_t compat;
+
     int dcache_line_size;
     int icache_line_size;
 
@@ -1330,6 +1333,7 @@ static inline int cpu_mmu_index (CPUPPCState *env)
 #define SPR_BOOKE_DVC1        (0x13E)
 #define SPR_BOOKE_DVC2        (0x13F)
 #define SPR_BOOKE_TSR         (0x150)
+#define SPR_PCR               (0x152)
 #define SPR_BOOKE_TCR         (0x154)
 #define SPR_BOOKE_TLB0PS      (0x158)
 #define SPR_BOOKE_TLB1PS      (0x159)
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index c030a20..b297fb3 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -28,6 +28,7 @@
 #include "mmu-hash32.h"
 #include "mmu-hash64.h"
 #include "qemu/error-report.h"
+#include "qapi/visitor.h"
 
 //#define PPC_DUMP_CPU
 //#define PPC_DEBUG_SPR
@@ -7201,6 +7202,10 @@ static void init_proc_POWER7 (CPUPPCState *env)
                  &spr_read_generic, &spr_write_generic,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
+    spr_register(env, SPR_PCR, "PCR",
+                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
 #if !defined(CONFIG_USER_ONLY)
     env->slb_nr = 32;
 #endif
@@ -7330,6 +7335,57 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
 }
 #endif /* defined (TARGET_PPC64) */
 
+static void powerpc_get_compat(Object *obj, Visitor *v,
+                               void *opaque, const char *name, Error **errp)
+{
+    PowerPCCPU *cpu = POWERPC_CPU(obj);
+    int64_t value = 0;
+
+    switch (cpu->env.compat) {
+    case CPU_POWERPC_LOGICAL_2_05:
+        value = 205;
+        break;
+    case CPU_POWERPC_LOGICAL_2_06:
+        value = 206;
+        break;
+    case 0:
+        break;
+    default:
+        perror("Unsupported mode, only are 205, 206 supported\n");
+        break;
+    }
+
+    visit_type_int(v, &value, name, errp);
+}
+
+static void powerpc_set_compat(Object *obj, Visitor *v,
+                               void *opaque, const char *name, Error **errp)
+{
+    PowerPCCPU *cpu = POWERPC_CPU(obj);
+    Error *error = NULL;
+    int64_t value;
+
+    visit_type_int(v, &value, name, &error);
+    if (error) {
+        error_propagate(errp, error);
+        return;
+    }
+
+    switch (value) {
+    case 0:
+        cpu->env.compat = 0;
+        break;
+    case 205:
+        cpu->env.compat = CPU_POWERPC_LOGICAL_2_05;
+        break;
+    case 206:
+        cpu->env.compat = CPU_POWERPC_LOGICAL_2_06;
+        break;
+    default:
+        perror("Unsupported mode, only are 205, 206 supported\n");
+        return;
+    }
+}
 
 /*****************************************************************************/
 /* Generic CPU instantiation routine                                         */
@@ -7497,6 +7553,12 @@ static void init_ppc_proc(PowerPCCPU *cpu)
                 "registered.\n"
                 " Attempt QEMU to crash very soon !\n");
     }
+
+    if (env->spr_cb[SPR_PCR].oea_read) {
+        object_property_add(OBJECT(cpu), "compat", "int",
+                            powerpc_get_compat, powerpc_set_compat,
+                            NULL, NULL, NULL);
+    }
 }
 
 #if defined(PPC_DUMP_CPU)
@@ -8376,6 +8438,10 @@ PowerPCCPU *cpu_ppc_init(const char *cpu_model)
         return NULL;
     }
 
+    if (cpu_parse_options(CPU(cpu))) {
+        return NULL;
+    }
+
     return cpu;
 }
 
@@ -8674,6 +8740,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void 
*data)
 #endif
 
     dc->fw_name = "PowerPC,UNKNOWN";
+    cc->parse_options = cpu_default_parse_options_func;
 }
 
 static const TypeInfo ppc_cpu_type_info = {
-- 
1.8.4.rc4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]