aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/ppc/spapr.c14
-rw-r--r--target-ppc/cpu-qom.h2
-rw-r--r--target-ppc/cpu.h11
-rw-r--r--target-ppc/translate_init.c34
4 files changed, 61 insertions, 0 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 6c269312ab..9551c00176 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -210,6 +210,14 @@ static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu,
uint32_t gservers_prop[smt_threads * 2];
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));
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
/* Build interrupt servers and gservers properties */
for (i = 0; i < smt_threads; i++) {
servers_prop[i] = cpu_to_be32(index + i);
@@ -1275,6 +1283,12 @@ static void ppc_spapr_init(MachineState *machine)
kvmppc_set_papr(cpu);
}
+ if (cpu->max_compat) {
+ if (ppc_set_compat(cpu, cpu->max_compat) < 0) {
+ exit(1);
+ }
+ }
+
xics_cpu_setup(spapr->icp, cpu);
qemu_register_reset(spapr_cpu_reset, cpu);
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index 533de8fbd7..e88e1da2b9 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -84,6 +84,7 @@ typedef struct PowerPCCPUClass {
* @env: #CPUPPCState
* @cpu_dt_id: CPU index used in the device tree. KVM uses this index too
* @max_compat: Maximal supported logical PVR from the command line
+ * @cpu_version: Current logical PVR, zero if in "raw" mode
*
* A PowerPC CPU.
*/
@@ -95,6 +96,7 @@ struct PowerPCCPU {
CPUPPCState env;
int cpu_dt_id;
uint32_t max_compat;
+ uint32_t cpu_version;
};
static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env)
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index b035e91316..0d2253b53c 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1122,6 +1122,7 @@ void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
void ppc_store_msr (CPUPPCState *env, target_ulong value);
void ppc_cpu_list (FILE *f, fprintf_function cpu_fprintf);
+int ppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version);
/* Time-base and decrementer management */
#ifndef NO_CPU_IO_DEFS
@@ -1338,6 +1339,7 @@ static inline int cpu_mmu_index (CPUPPCState *env)
#define SPR_LPCR (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)
@@ -2061,6 +2063,15 @@ enum {
PPC_INTERRUPT_PERFM, /* Performance monitor interrupt */
};
+/* Processor Compatibility mask (PCR) */
+enum {
+ PCR_COMPAT_2_05 = 1ull << (63-62),
+ PCR_COMPAT_2_06 = 1ull << (63-61),
+ PCR_VEC_DIS = 1ull << (63-0), /* Vec. disable (bit NA since POWER8) */
+ PCR_VSX_DIS = 1ull << (63-1), /* VSX disable (bit NA since POWER8) */
+ PCR_TM_DIS = 1ull << (63-2), /* Trans. memory disable (POWER8) */
+};
+
/*****************************************************************************/
static inline target_ulong cpu_read_xer(CPUPPCState *env)
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 2e273dcf62..41afc5e3b9 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -7829,6 +7829,15 @@ static void init_proc_POWER7 (CPUPPCState *env)
/* Can't find information on what this should be on reset. This
* value is the one used by 74xx processors. */
vscr_init(env, 0x00010000);
+
+ /*
+ * Register PCR to report POWERPC_EXCP_PRIV_REG instead of
+ * POWERPC_EXCP_INVAL_SPR.
+ */
+ spr_register(env, SPR_PCR, "PCR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, SPR_NOACCESS,
+ 0x00000000);
}
POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
@@ -8909,6 +8918,31 @@ static void ppc_cpu_unrealizefn(DeviceState *dev, Error **errp)
}
}
+int ppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version)
+{
+ int ret = 0;
+ CPUPPCState *env = &cpu->env;
+
+ cpu->cpu_version = cpu_version;
+
+ switch (cpu_version) {
+ case CPU_POWERPC_LOGICAL_2_05:
+ env->spr[SPR_PCR] = PCR_COMPAT_2_05;
+ break;
+ case CPU_POWERPC_LOGICAL_2_06:
+ env->spr[SPR_PCR] = PCR_COMPAT_2_06;
+ break;
+ case CPU_POWERPC_LOGICAL_2_06_PLUS:
+ env->spr[SPR_PCR] = PCR_COMPAT_2_06;
+ break;
+ default:
+ env->spr[SPR_PCR] = 0;
+ break;
+ }
+
+ return ret;
+}
+
static gint ppc_cpu_compare_class_pvr(gconstpointer a, gconstpointer b)
{
ObjectClass *oc = (ObjectClass *)a;