diff options
Diffstat (limited to 'target/ppc/cpu_init.c')
| -rw-r--r-- | target/ppc/cpu_init.c | 260 |
1 files changed, 100 insertions, 160 deletions
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 23881d09e9..efcb80d1c2 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -52,6 +52,7 @@ #include "kvm_ppc.h" #endif +#include "cpu_init.h" /* #define PPC_DEBUG_SPR */ /* #define USE_APPLE_GDB */ @@ -6153,6 +6154,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data) dc->fw_name = "PowerPC,POWER7"; dc->desc = "POWER7"; + pcc->spapr_logical_pvr = CPU_POWERPC_LOGICAL_2_06_PLUS; pcc->pvr_match = ppc_pvr_match_power7; pcc->pcr_mask = PCR_VEC_DIS | PCR_VSX_DIS | PCR_COMPAT_2_05; pcc->pcr_supported = PCR_COMPAT_2_06 | PCR_COMPAT_2_05; @@ -6316,6 +6318,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data) dc->fw_name = "PowerPC,POWER8"; dc->desc = "POWER8"; + pcc->spapr_logical_pvr = CPU_POWERPC_LOGICAL_2_07; pcc->pvr_match = ppc_pvr_match_power8; pcc->pcr_mask = PCR_TM_DIS | PCR_COMPAT_2_06 | PCR_COMPAT_2_05; pcc->pcr_supported = PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_COMPAT_2_05; @@ -6407,7 +6410,7 @@ static struct ppc_radix_page_info POWER9_radix_page_info = { #endif /* CONFIG_USER_ONLY */ #define POWER9_BHRB_ENTRIES_LOG2 5 -static void init_proc_POWER9(CPUPPCState *env) +static void register_power9_common_sprs(CPUPPCState *env) { /* Common Registers */ init_proc_book3s_common(env); @@ -6426,7 +6429,6 @@ static void init_proc_POWER9(CPUPPCState *env) register_power5p_ear_sprs(env); register_power5p_tb_sprs(env); register_power6_common_sprs(env); - register_HEIR32_spr(env); register_power6_dbg_sprs(env); register_power7_common_sprs(env); register_power8_tce_address_control_sprs(env); @@ -6444,16 +6446,21 @@ static void init_proc_POWER9(CPUPPCState *env) register_power8_rpr_sprs(env); register_power9_mmu_sprs(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); +} + +static void init_proc_POWER9(CPUPPCState *env) +{ + register_power9_common_sprs(env); + register_HEIR32_spr(env); + /* POWER9 Specific registers */ + spr_register_kvm(env, SPR_TIDR, "TIDR", NULL, NULL, + spr_read_generic, spr_write_generic, + KVM_REG_PPC_TIDR, 0); /* env variables */ env->dcache_line_size = 128; env->icache_line_size = 128; @@ -6509,59 +6516,17 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data) dc->fw_name = "PowerPC,POWER9"; dc->desc = "POWER9"; + pcc->spapr_logical_pvr = CPU_POWERPC_LOGICAL_3_00; pcc->pvr_match = ppc_pvr_match_power9; - pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06 | PCR_COMPAT_2_07; - pcc->pcr_supported = PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | - PCR_COMPAT_2_05; + pcc->pcr_mask = PPC_PCR_MASK_POWER9; + pcc->pcr_supported = PPC_PCR_SUPPORTED_POWER9; pcc->init_proc = init_proc_POWER9; pcc->check_pow = check_pow_nocheck; pcc->check_attn = check_attn_hid0_power9; - 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_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 | PPC2_MEM_LWSYNC | - PPC2_BCDA_ISA206; - pcc->msr_mask = (1ull << MSR_SF) | - (1ull << MSR_HV) | - (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->lpcr_mask = LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD | - (LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL | - LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR | LPCR_LD | - (LPCR_PECE_L_MASK & (LPCR_PDEE | LPCR_HDEE | LPCR_EEE | - LPCR_DEE | LPCR_OEE)) - | LPCR_MER | LPCR_GTSE | LPCR_TC | - LPCR_HEIC | LPCR_LPES0 | LPCR_HVICE | LPCR_HDICE; + pcc->insns_flags = PPC_INSNS_FLAGS_POWER9; + pcc->insns_flags2 = PPC_INSNS_FLAGS2_POWER9; + pcc->msr_mask = PPC_MSR_MASK_POWER9; + pcc->lpcr_mask = PPC_LPCR_MASK_POWER9; pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE; pcc->mmu_model = POWERPC_MMU_3_00; #if !defined(CONFIG_USER_ONLY) @@ -6574,10 +6539,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data) 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 | POWERPC_FLAG_SCV; + pcc->flags = POWERPC_FLAGS_POWER9; pcc->l1_dcache_size = 0x8000; pcc->l1_icache_size = 0x8000; } @@ -6604,50 +6566,12 @@ static struct ppc_radix_page_info POWER10_radix_page_info = { #define POWER10_BHRB_ENTRIES_LOG2 5 static void init_proc_POWER10(CPUPPCState *env) { - /* Common Registers */ - init_proc_book3s_common(env); - register_book3s_207_dbg_sprs(env); - - /* Common TCG PMU */ - init_tcg_pmu_power8(env); - - /* POWER8 Specific Registers */ - register_book3s_ids_sprs(env); - register_amr_sprs(env); - register_iamr_sprs(env); - register_book3s_purr_sprs(env); - register_power5p_common_sprs(env); - register_power5p_lpar_sprs(env); - register_power5p_ear_sprs(env); - register_power5p_tb_sprs(env); - register_power6_common_sprs(env); + register_power9_common_sprs(env); register_HEIR64_spr(env); - register_power6_dbg_sprs(env); - register_power7_common_sprs(env); - register_power8_tce_address_control_sprs(env); - register_power8_ids_sprs(env); - register_power8_ebb_sprs(env); - register_power8_fscr_sprs(env); - register_power8_pmu_sup_sprs(env); - register_power8_pmu_user_sprs(env); - register_power8_tm_sprs(env); - register_power8_pspb_sprs(env); - register_power8_dpdes_sprs(env); - register_vtb_sprs(env); - register_power8_ic_sprs(env); - register_power9_book4_sprs(env); - register_power8_rpr_sprs(env); - register_power9_mmu_sprs(env); register_power10_hash_sprs(env); register_power10_dexcr_sprs(env); register_power10_pmu_sup_sprs(env); register_power10_pmu_user_sprs(env); - - /* 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; @@ -6689,61 +6613,17 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data) dc->fw_name = "PowerPC,POWER10"; dc->desc = "POWER10"; + pcc->spapr_logical_pvr = CPU_POWERPC_LOGICAL_3_10; 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->pcr_mask = PPC_PCR_MASK_POWER10; + pcc->pcr_supported = PPC_PCR_SUPPORTED_POWER10; pcc->init_proc = init_proc_POWER10; pcc->check_pow = check_pow_nocheck; pcc->check_attn = check_attn_hid0_power9; - 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_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_ISA300 | PPC2_PRCNTL | PPC2_ISA310 | - PPC2_MEM_LWSYNC | PPC2_BCDA_ISA206; - pcc->msr_mask = (1ull << MSR_SF) | - (1ull << MSR_HV) | - (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->lpcr_mask = LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD | - (LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL | - LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR | LPCR_LD | - (LPCR_PECE_L_MASK & (LPCR_PDEE | LPCR_HDEE | LPCR_EEE | - LPCR_DEE | LPCR_OEE)) - | LPCR_MER | LPCR_GTSE | LPCR_TC | - LPCR_HEIC | LPCR_LPES0 | LPCR_HVICE | LPCR_HDICE; - /* DD2 adds an extra HAIL bit */ - pcc->lpcr_mask |= LPCR_HAIL; + pcc->insns_flags = PPC_INSNS_FLAGS_POWER10; + pcc->insns_flags2 = PPC_INSNS_FLAGS2_POWER10; + pcc->msr_mask = PPC_MSR_MASK_POWER10; + pcc->lpcr_mask = PPC_LPCR_MASK_POWER10; pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE; pcc->mmu_model = POWERPC_MMU_3_00; @@ -6756,11 +6636,67 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data) pcc->excp_model = POWERPC_EXCP_POWER10; 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_SCV | - POWERPC_FLAG_BHRB; + pcc->flags = POWERPC_FLAGS_POWER10; + pcc->l1_dcache_size = 0x8000; + pcc->l1_icache_size = 0x8000; +} + +static void init_proc_POWER11(CPUPPCState *env) +{ + init_proc_POWER10(env); +} + +static bool ppc_pvr_match_power11(PowerPCCPUClass *pcc, uint32_t pvr, bool best) +{ + uint32_t base = pvr & CPU_POWERPC_POWER_SERVER_MASK; + uint32_t pcc_base = pcc->pvr & CPU_POWERPC_POWER_SERVER_MASK; + + if (!best && (base == CPU_POWERPC_POWER11_BASE)) { + return true; + } + + if (base != pcc_base) { + return false; + } + + if ((pvr & 0x0f00) == (pcc->pvr & 0x0f00)) { + return true; + } + + return false; +} + +POWERPC_FAMILY(POWER11)(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); + + dc->fw_name = "PowerPC,POWER11"; + dc->desc = "POWER11"; + pcc->spapr_logical_pvr = CPU_POWERPC_LOGICAL_3_10_P11; + pcc->pvr_match = ppc_pvr_match_power11; + pcc->pcr_mask = PPC_PCR_MASK_POWER11; + pcc->pcr_supported = PPC_PCR_SUPPORTED_POWER11; + pcc->init_proc = init_proc_POWER11; + pcc->check_pow = check_pow_nocheck; + pcc->check_attn = check_attn_hid0_power9; + pcc->insns_flags = PPC_INSNS_FLAGS_POWER11; + pcc->insns_flags2 = PPC_INSNS_FLAGS2_POWER11; + pcc->msr_mask = PPC_MSR_MASK_POWER11; + pcc->lpcr_mask = PPC_LPCR_MASK_POWER11; + + pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE; + pcc->mmu_model = POWERPC_MMU_3_00; +#if !defined(CONFIG_USER_ONLY) + /* 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_POWER11; + pcc->bus_model = PPC_FLAGS_INPUT_POWER9; + pcc->bfd_mach = bfd_mach_ppc64; + pcc->flags = POWERPC_FLAGS_POWER11; pcc->l1_dcache_size = 0x8000; pcc->l1_icache_size = 0x8000; } @@ -7326,6 +7262,14 @@ static void ppc_cpu_reset_hold(Object *obj, ResetType type) /* tininess for underflow is detected before rounding */ set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status); + /* + * PowerPC propagation rules: + * 1. A if it sNaN or qNaN + * 2. B if it sNaN or qNaN + * A signaling NaN is always silenced before returning it. + */ + set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status); + set_float_2nan_prop_rule(float_2nan_prop_ab, &env->vec_status); for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) { ppc_spr_t *spr = &env->spr_cb[i]; @@ -7452,11 +7396,7 @@ static void ppc_disas_set_info(CPUState *cs, disassemble_info *info) } static Property ppc_cpu_properties[] = { - DEFINE_PROP_BOOL("pre-2.8-migration", PowerPCCPU, pre_2_8_migration, false), - DEFINE_PROP_BOOL("pre-2.10-migration", PowerPCCPU, pre_2_10_migration, - false), - DEFINE_PROP_BOOL("pre-3.0-migration", PowerPCCPU, pre_3_0_migration, - false), + /* add default property here */ DEFINE_PROP_END_OF_LIST(), }; |