This handles filtering bits based on what is implemented by a given architecture version. We also use it to copy to LPCR some of the relevant 970 HID4 bits.
Signed-off-by: Benjamin Herrenschmidt <b...@kernel.crashing.org> --- target-ppc/helper.h | 1 + target-ppc/mmu-hash64.c | 58 +++++++++++++++++++++++++++++++++++++++++++++ target-ppc/translate_init.c | 56 ++++++++++++++++++++++++++++--------------- 3 files changed, 96 insertions(+), 19 deletions(-) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 8292dd8..23889fe 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -16,6 +16,7 @@ DEF_HELPER_1(rfmci, void, env) DEF_HELPER_2(pminsn, void, env, i32) DEF_HELPER_1(rfid, void, env) DEF_HELPER_1(hrfid, void, env) +DEF_HELPER_2(store_lpcr, void, env, tl) #endif DEF_HELPER_1(check_tlb_flush, void, env) #endif diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c index e489fa4..835245a 100644 --- a/target-ppc/mmu-hash64.c +++ b/target-ppc/mmu-hash64.c @@ -667,3 +667,61 @@ void ppc_hash64_store_hpte(CPUPPCState *env, stq_phys(cs->as, env->htab_base + pte_index + HASH_PTE_SIZE_64/2, pte1); } } + +void helper_store_lpcr(CPUPPCState *env, target_ulong val) +{ + uint64_t lpcr = 0; + + /* Filter out bits */ + switch(env->mmu_model) { + case POWERPC_MMU_64B: /* 970 */ + if (val & 0x40) { + lpcr |= LPCR_LPES0; + } + if (val & 0x8000000000000000ull) { + lpcr |= LPCR_LPES1; + } + if (val & 0x20) { + lpcr |= (0x4ull << LPCR_RMLS_SHIFT); + } + if (val & 0x4000000000000000ull) { + lpcr |= (0x2ull << LPCR_RMLS_SHIFT); + } + if (val & 0x2000000000000000ull) { + lpcr |= (0x1ull << LPCR_RMLS_SHIFT); + } + env->spr[SPR_RMOR] = ((lpcr >> 41) & 0xffffull) << 26; + + /* XXX We could also write LPID from HID4 here + * but since we don't tag any translation on it + * it doesn't actually matter + */ + /* XXX For proper emulation of 970 we also need + * to dig HRMOR out of HID5 + */ + break; + case POWERPC_MMU_2_03: /* P5p */ + lpcr = val & (LPCR_RMLS | LPCR_ILE | + LPCR_LPES0 | LPCR_LPES1 | + LPCR_RMI | LPCR_HDICE); + break; + case POWERPC_MMU_2_06: /* P7 */ + lpcr = val & (LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_DPFD | + LPCR_VRMASD | LPCR_RMLS | LPCR_ILE | + LPCR_P7_PECE0 | LPCR_P7_PECE1 | LPCR_P7_PECE2 | + LPCR_MER | LPCR_TC | + LPCR_LPES0 | LPCR_LPES1 | LPCR_HDICE); + break; + case POWERPC_MMU_2_07: /* P8 */ + lpcr = val & (LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV | + LPCR_DPFD | LPCR_VRMASD | LPCR_RMLS | LPCR_ILE | + LPCR_AIL | LPCR_ONL | LPCR_P8_PECE0 | LPCR_P8_PECE1 | + LPCR_P8_PECE2 | LPCR_P8_PECE3 | LPCR_P8_PECE4 | + LPCR_MER | LPCR_TC | LPCR_LPES0 | LPCR_HDICE); + break; + default: + ; + } + env->spr[SPR_LPCR] = lpcr; +} + diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 8a1ce85..853a084 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -7450,16 +7450,6 @@ static void gen_spr_970_hior(CPUPPCState *env) 0x00000000); } -static void gen_spr_970_lpar(CPUPPCState *env) -{ - /* Logical partitionning */ - /* PPC970: HID4 is effectively the LPCR */ - spr_register(env, SPR_970_HID4, "HID4", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); -} - static void gen_spr_book3s_common(CPUPPCState *env) { spr_register(env, SPR_CTRL, "SPR_CTRL", @@ -7679,15 +7669,6 @@ static void gen_spr_power5p_ear(CPUPPCState *env) 0x00000000); } -static void gen_spr_power5p_lpar(CPUPPCState *env) -{ - /* Logical partitionning */ - spr_register_kvm(env, SPR_LPCR, "LPCR", - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - KVM_REG_PPC_LPCR, LPCR_LPES0 | LPCR_LPES1); -} - #if !defined(CONFIG_USER_ONLY) static void spr_write_hmer(DisasContext *ctx, int sprn, int gprn) { @@ -7699,7 +7680,44 @@ static void spr_write_hmer(DisasContext *ctx, int sprn, int gprn) spr_store_dump_spr(sprn); tcg_temp_free(hmer); } + +static void spr_write_lpcr(DisasContext *ctx, int sprn, int gprn) +{ + gen_helper_store_lpcr(cpu_env, cpu_gpr[gprn]); +} + +static void spr_write_970_hid4(DisasContext *ctx, int sprn, int gprn) +{ +#if defined (TARGET_PPC64) + spr_write_generic(ctx, sprn, gprn); + gen_helper_store_lpcr(cpu_env, cpu_gpr[gprn]); +#endif +} + +#endif /* !defined(CONFIG_USER_ONLY) */ + +static void gen_spr_970_lpar(CPUPPCState *env) +{ +#if !defined(CONFIG_USER_ONLY) + /* Logical partitionning */ + /* PPC970: HID4 is effectively the LPCR */ + spr_register(env, SPR_970_HID4, "HID4", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_970_hid4, + 0x00000000); +#endif +} + +static void gen_spr_power5p_lpar(CPUPPCState *env) +{ +#if !defined(CONFIG_USER_ONLY) + /* Logical partitionning */ + spr_register_kvm(env, SPR_LPCR, "LPCR", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_lpcr, + KVM_REG_PPC_LPCR, LPCR_LPES0 | LPCR_LPES1); #endif +} static void gen_spr_book3s_ids(CPUPPCState *env) { -- 2.5.0