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;