diff options
-rw-r--r-- | target/ppc/compat.c | 21 | ||||
-rw-r--r-- | target/ppc/cpu-models.c | 3 | ||||
-rw-r--r-- | target/ppc/cpu-models.h | 3 | ||||
-rw-r--r-- | target/ppc/cpu.h | 1 | ||||
-rw-r--r-- | target/ppc/translate_init.inc.c | 215 |
5 files changed, 237 insertions, 6 deletions
diff --git a/target/ppc/compat.c b/target/ppc/compat.c index 7de4bf3122..f48df25944 100644 --- a/target/ppc/compat.c +++ b/target/ppc/compat.c @@ -51,36 +51,38 @@ static const CompatInfo compat_table[] = { { /* POWER6, ISA2.05 */ .name = "power6", .pvr = CPU_POWERPC_LOGICAL_2_05, - .pcr = PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | - PCR_COMPAT_2_05 | PCR_TM_DIS | PCR_VSX_DIS, + .pcr = PCR_COMPAT_3_10 | PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | + PCR_COMPAT_2_06 | PCR_COMPAT_2_05 | PCR_TM_DIS | PCR_VSX_DIS, .pcr_level = PCR_COMPAT_2_05, .max_vthreads = 2, }, { /* POWER7, ISA2.06 */ .name = "power7", .pvr = CPU_POWERPC_LOGICAL_2_06, - .pcr = PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_TM_DIS, + .pcr = PCR_COMPAT_3_10 | PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | + PCR_COMPAT_2_06 | PCR_TM_DIS, .pcr_level = PCR_COMPAT_2_06, .max_vthreads = 4, }, { .name = "power7+", .pvr = CPU_POWERPC_LOGICAL_2_06_PLUS, - .pcr = PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_TM_DIS, + .pcr = PCR_COMPAT_3_10 | PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | + PCR_COMPAT_2_06 | PCR_TM_DIS, .pcr_level = PCR_COMPAT_2_06, .max_vthreads = 4, }, { /* POWER8, ISA2.07 */ .name = "power8", .pvr = CPU_POWERPC_LOGICAL_2_07, - .pcr = PCR_COMPAT_3_00 | PCR_COMPAT_2_07, + .pcr = PCR_COMPAT_3_10 | PCR_COMPAT_3_00 | PCR_COMPAT_2_07, .pcr_level = PCR_COMPAT_2_07, .max_vthreads = 8, }, { /* POWER9, ISA3.00 */ .name = "power9", .pvr = CPU_POWERPC_LOGICAL_3_00, - .pcr = PCR_COMPAT_3_00, + .pcr = PCR_COMPAT_3_10 | PCR_COMPAT_3_00, .pcr_level = PCR_COMPAT_3_00, /* * POWER9 hardware only supports 4 threads / core, but this @@ -91,6 +93,13 @@ static const CompatInfo compat_table[] = { */ .max_vthreads = 8, }, + { /* POWER10, ISA3.10 */ + .name = "power10", + .pvr = CPU_POWERPC_LOGICAL_3_10, + .pcr = PCR_COMPAT_3_10, + .pcr_level = PCR_COMPAT_3_10, + .max_vthreads = 8, + }, }; static const CompatInfo *compat_by_pvr(uint32_t pvr) diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c index 086548e9b9..4ad16863c0 100644 --- a/target/ppc/cpu-models.c +++ b/target/ppc/cpu-models.c @@ -774,6 +774,8 @@ "POWER9 v1.0") POWERPC_DEF("power9_v2.0", CPU_POWERPC_POWER9_DD20, POWER9, "POWER9 v2.0") + POWERPC_DEF("power10_v1.0", CPU_POWERPC_POWER10_DD1, POWER10, + "POWER10 v1.0") #endif /* defined (TARGET_PPC64) */ /***************************************************************************/ @@ -950,6 +952,7 @@ PowerPCCPUAlias ppc_cpu_aliases[] = { { "power8", "power8_v2.0" }, { "power8nvl", "power8nvl_v1.0" }, { "power9", "power9_v2.0" }, + { "power10", "power10_v1.0" }, #endif /* Generic PowerPCs */ diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h index 4fdb73034d..ce750b2d55 100644 --- a/target/ppc/cpu-models.h +++ b/target/ppc/cpu-models.h @@ -373,6 +373,8 @@ enum { CPU_POWERPC_POWER9_BASE = 0x004E0000, CPU_POWERPC_POWER9_DD1 = 0x004E0100, CPU_POWERPC_POWER9_DD20 = 0x004E1200, + CPU_POWERPC_POWER10_BASE = 0x00800000, + CPU_POWERPC_POWER10_DD1 = 0x00800100, CPU_POWERPC_970_v22 = 0x00390202, CPU_POWERPC_970FX_v10 = 0x00391100, CPU_POWERPC_970FX_v20 = 0x003C0200, @@ -409,6 +411,7 @@ enum { CPU_POWERPC_LOGICAL_2_06_PLUS = 0x0F100003, CPU_POWERPC_LOGICAL_2_07 = 0x0F000004, CPU_POWERPC_LOGICAL_3_00 = 0x0F000005, + CPU_POWERPC_LOGICAL_3_10 = 0x0F000006, }; /* System version register (used on MPC 8xxx) */ diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 60cf030ce6..fbec1b0cd5 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -2364,6 +2364,7 @@ enum { PCR_COMPAT_2_06 = PPC_BIT(61), PCR_COMPAT_2_07 = PPC_BIT(60), PCR_COMPAT_3_00 = PPC_BIT(59), + PCR_COMPAT_3_10 = PPC_BIT(58), PCR_VEC_DIS = PPC_BIT(0), /* Vec. disable (bit NA since POWER8) */ PCR_VSX_DIS = PPC_BIT(1), /* VSX disable (bit NA since POWER8) */ PCR_TM_DIS = PPC_BIT(2), /* Trans. memory disable (POWER8) */ diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c index 64a838095c..7364d36b07 100644 --- a/target/ppc/translate_init.inc.c +++ b/target/ppc/translate_init.inc.c @@ -3354,6 +3354,11 @@ static void init_excp_POWER9(CPUPPCState *env) #endif } +static void init_excp_POWER10(CPUPPCState *env) +{ + init_excp_POWER9(env); +} + #endif /*****************************************************************************/ @@ -8996,6 +9001,216 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data) pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE; } +#ifdef CONFIG_SOFTMMU +/* + * Radix pg sizes and AP encodings for dt node ibm,processor-radix-AP-encodings + * Encoded as array of int_32s in the form: + * 0bxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + * x -> AP encoding + * y -> radix mode supported page size (encoded as a shift) + */ +static struct ppc_radix_page_info POWER10_radix_page_info = { + .count = 4, + .entries = { + 0x0000000c, /* 4K - enc: 0x0 */ + 0xa0000010, /* 64K - enc: 0x5 */ + 0x20000015, /* 2M - enc: 0x1 */ + 0x4000001e /* 1G - enc: 0x2 */ + } +}; +#endif /* CONFIG_SOFTMMU */ + +static void init_proc_POWER10(CPUPPCState *env) +{ + /* Common Registers */ + init_proc_book3s_common(env); + gen_spr_book3s_207_dbg(env); + + /* POWER8 Specific Registers */ + gen_spr_book3s_ids(env); + gen_spr_amr(env); + gen_spr_iamr(env); + gen_spr_book3s_purr(env); + gen_spr_power5p_common(env); + gen_spr_power5p_lpar(env); + gen_spr_power5p_ear(env); + gen_spr_power6_common(env); + gen_spr_power6_dbg(env); + gen_spr_power8_tce_address_control(env); + gen_spr_power8_ids(env); + gen_spr_power8_ebb(env); + gen_spr_power8_fscr(env); + gen_spr_power8_pmu_sup(env); + gen_spr_power8_pmu_user(env); + gen_spr_power8_tm(env); + gen_spr_power8_pspb(env); + gen_spr_vtb(env); + gen_spr_power8_ic(env); + gen_spr_power8_book4(env); + gen_spr_power8_rpr(env); + gen_spr_power9_mmu(env); + + /* POWER9 Specific registers */ + spr_register_kvm(env, SPR_TIDR, "TIDR", NULL, NULL, + spr_read_generic, spr_write_generic, + KVM_REG_PPC_TIDR, 0); + + /* FIXME: Filter fields properly based on privilege level */ + spr_register_kvm_hv(env, SPR_PSSCR, "PSSCR", NULL, NULL, NULL, NULL, + spr_read_generic, spr_write_generic, + KVM_REG_PPC_PSSCR, 0); + + /* env variables */ + env->dcache_line_size = 128; + env->icache_line_size = 128; + + /* Allocate hardware IRQ controller */ + init_excp_POWER10(env); + ppcPOWER9_irq_init(env_archcpu(env)); +} + +static bool ppc_pvr_match_power10(PowerPCCPUClass *pcc, uint32_t pvr) +{ + if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER10_BASE) { + return true; + } + return false; +} + +static bool cpu_has_work_POWER10(CPUState *cs) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + + if (cs->halted) { + uint64_t psscr = env->spr[SPR_PSSCR]; + + if (!(cs->interrupt_request & CPU_INTERRUPT_HARD)) { + return false; + } + + /* If EC is clear, just return true on any pending interrupt */ + if (!(psscr & PSSCR_EC)) { + return true; + } + /* External Exception */ + if ((env->pending_interrupts & (1u << PPC_INTERRUPT_EXT)) && + (env->spr[SPR_LPCR] & LPCR_EEE)) { + bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); + if (heic == 0 || !msr_hv || msr_pr) { + return true; + } + } + /* Decrementer Exception */ + if ((env->pending_interrupts & (1u << PPC_INTERRUPT_DECR)) && + (env->spr[SPR_LPCR] & LPCR_DEE)) { + return true; + } + /* Machine Check or Hypervisor Maintenance Exception */ + if ((env->pending_interrupts & (1u << PPC_INTERRUPT_MCK | + 1u << PPC_INTERRUPT_HMI)) && (env->spr[SPR_LPCR] & LPCR_OEE)) { + return true; + } + /* Privileged Doorbell Exception */ + if ((env->pending_interrupts & (1u << PPC_INTERRUPT_DOORBELL)) && + (env->spr[SPR_LPCR] & LPCR_PDEE)) { + return true; + } + /* Hypervisor Doorbell Exception */ + if ((env->pending_interrupts & (1u << PPC_INTERRUPT_HDOORBELL)) && + (env->spr[SPR_LPCR] & LPCR_HDEE)) { + return true; + } + /* Hypervisor virtualization exception */ + if ((env->pending_interrupts & (1u << PPC_INTERRUPT_HVIRT)) && + (env->spr[SPR_LPCR] & LPCR_HVEE)) { + return true; + } + if (env->pending_interrupts & (1u << PPC_INTERRUPT_RESET)) { + return true; + } + return false; + } else { + return msr_ee && (cs->interrupt_request & CPU_INTERRUPT_HARD); + } +} + +POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); + CPUClass *cc = CPU_CLASS(oc); + + dc->fw_name = "PowerPC,POWER10"; + dc->desc = "POWER10"; + dc->props = powerpc_servercpu_properties; + pcc->pvr_match = ppc_pvr_match_power10; + pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06 | PCR_COMPAT_2_07 | + PCR_COMPAT_3_00; + pcc->pcr_supported = PCR_COMPAT_3_10 | PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | + PCR_COMPAT_2_06 | PCR_COMPAT_2_05; + pcc->init_proc = init_proc_POWER10; + pcc->check_pow = check_pow_nocheck; + cc->has_work = cpu_has_work_POWER10; + 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_TLBSYNC | + PPC_64B | PPC_64H | PPC_64BX | PPC_ALTIVEC | + PPC_SEGMENT_64B | PPC_SLBI | + PPC_POPCNTB | PPC_POPCNTWD | + PPC_CILDST; + pcc->insns_flags2 = PPC2_VSX | PPC2_VSX207 | PPC2_DFP | PPC2_DBRX | + PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 | + PPC2_ATOMIC_ISA206 | PPC2_FP_CVT_ISA206 | + PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 | + PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 | + PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 | + PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL; + pcc->msr_mask = (1ull << MSR_SF) | + (1ull << MSR_SHV) | + (1ull << MSR_TM) | + (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_3_00; +#if defined(CONFIG_SOFTMMU) + pcc->handle_mmu_fault = ppc64_v3_handle_mmu_fault; + /* segment page size remain the same */ + pcc->hash64_opts = &ppc_hash64_opts_POWER7; + pcc->radix_page_info = &POWER10_radix_page_info; + pcc->lrg_decr_bits = 56; +#endif + pcc->excp_model = POWERPC_EXCP_POWER9; + pcc->bus_model = PPC_FLAGS_INPUT_POWER9; + 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 | POWERPC_FLAG_TM; + pcc->l1_dcache_size = 0x8000; + pcc->l1_icache_size = 0x8000; + pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr; + pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE; +} + #if !defined(CONFIG_USER_ONLY) void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp) { |