Message ID | 20200319064439.1020571-1-npiggin@gmail.com |
---|---|
State | New |
Headers | show |
Series | [v2] target/ppc: Fix ISA v3.0 (POWER9) slbia implementation | expand |
On 3/19/20 7:44 AM, Nicholas Piggin wrote: > The new ISA v3.0 slbia variants have not been implemented for TCG, > which can lead to crashing when a POWER9 machine boots Linux using > the hash MMU, for example ("disable_radix" kernel command line). > > Add them. > > Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Reviewed-by: Cédric Le Goater <clg@kaod.org> > --- > Changes in v2: > - Rewrite changelog. > - Remove stray slbie hunk that crept in > > I don't think the slbie invalidation is necessary, as explained on the > list. > > target/ppc/helper.h | 2 +- > target/ppc/mmu-hash64.c | 56 +++++++++++++++++++++++++++++++++++------ > target/ppc/translate.c | 5 +++- > 3 files changed, 54 insertions(+), 9 deletions(-) > > diff --git a/target/ppc/helper.h b/target/ppc/helper.h > index ee1498050d..2dfa1c6942 100644 > --- a/target/ppc/helper.h > +++ b/target/ppc/helper.h > @@ -615,7 +615,7 @@ DEF_HELPER_FLAGS_3(store_slb, TCG_CALL_NO_RWG, void, env, tl, tl) > DEF_HELPER_2(load_slb_esid, tl, env, tl) > DEF_HELPER_2(load_slb_vsid, tl, env, tl) > DEF_HELPER_2(find_slb_vsid, tl, env, tl) > -DEF_HELPER_FLAGS_1(slbia, TCG_CALL_NO_RWG, void, env) > +DEF_HELPER_FLAGS_2(slbia, TCG_CALL_NO_RWG, void, env, i32) > DEF_HELPER_FLAGS_2(slbie, TCG_CALL_NO_RWG, void, env, tl) > DEF_HELPER_FLAGS_2(slbieg, TCG_CALL_NO_RWG, void, env, tl) > #endif > diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c > index 373d44de74..e5baabf0e1 100644 > --- a/target/ppc/mmu-hash64.c > +++ b/target/ppc/mmu-hash64.c > @@ -95,9 +95,10 @@ void dump_slb(PowerPCCPU *cpu) > } > } > > -void helper_slbia(CPUPPCState *env) > +void helper_slbia(CPUPPCState *env, uint32_t ih) > { > PowerPCCPU *cpu = env_archcpu(env); > + int starting_entry; > int n; > > /* > @@ -111,18 +112,59 @@ void helper_slbia(CPUPPCState *env) > * expected that slbmte is more common than slbia, and slbia is usually > * going to evict valid SLB entries, so that tradeoff is unlikely to be a > * good one. > + * > + * ISA v2.05 introduced IH field with values 0,1,2,6. These all invalidate > + * the same SLB entries (everything but entry 0), but differ in what > + * "lookaside information" is invalidated. TCG can ignore this and flush > + * everything. > + * > + * ISA v3.0 introduced additional values 3,4,7, which change what SLBs are > + * invalidated. > */ > > - /* XXX: Warning: slbia never invalidates the first segment */ > - for (n = 1; n < cpu->hash64_opts->slb_size; n++) { > - ppc_slb_t *slb = &env->slb[n]; > + env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH; > + > + starting_entry = 1; /* default for IH=0,1,2,6 */ > + > + if (env->mmu_model == POWERPC_MMU_3_00) { > + switch (ih) { > + case 0x7: > + /* invalidate no SLBs, but all lookaside information */ > + return; > > - if (slb->esid & SLB_ESID_V) { > - slb->esid &= ~SLB_ESID_V; > + case 0x3: > + case 0x4: > + /* also considers SLB entry 0 */ > + starting_entry = 0; > + break; > + > + case 0x5: > + /* treat undefined values as ih==0, and warn */ > + qemu_log_mask(LOG_GUEST_ERROR, > + "slbia undefined IH field %u.\n", ih); > + break; > + > + default: > + /* 0,1,2,6 */ > + break; > } > } > > - env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH; > + for (n = starting_entry; n < cpu->hash64_opts->slb_size; n++) { > + ppc_slb_t *slb = &env->slb[n]; > + > + if (!(slb->esid & SLB_ESID_V)) { > + continue; > + } > + if (env->mmu_model == POWERPC_MMU_3_00) { > + if (ih == 0x3 && (slb->vsid & SLB_VSID_C) == 0) { > + /* preserves entries with a class value of 0 */ > + continue; > + } > + } > + > + slb->esid &= ~SLB_ESID_V; > + } > } > > static void __helper_slbie(CPUPPCState *env, target_ulong addr, > diff --git a/target/ppc/translate.c b/target/ppc/translate.c > index eb0ddba850..e514732a09 100644 > --- a/target/ppc/translate.c > +++ b/target/ppc/translate.c > @@ -5027,12 +5027,15 @@ static void gen_tlbsync(DisasContext *ctx) > /* slbia */ > static void gen_slbia(DisasContext *ctx) > { > + uint32_t ih = (ctx->opcode >> 21) & 0x7; > + TCGv_i32 t0 = tcg_const_i32(ih); > + > #if defined(CONFIG_USER_ONLY) > GEN_PRIV; > #else > CHK_SV; > > - gen_helper_slbia(cpu_env); > + gen_helper_slbia(cpu_env, t0); > #endif /* defined(CONFIG_USER_ONLY) */ > } >
On Thu, Mar 19, 2020 at 04:44:39PM +1000, Nicholas Piggin wrote: > The new ISA v3.0 slbia variants have not been implemented for TCG, > which can lead to crashing when a POWER9 machine boots Linux using > the hash MMU, for example ("disable_radix" kernel command line). > > Add them. > > Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Applied to ppc-for-5.0. > --- > Changes in v2: > - Rewrite changelog. > - Remove stray slbie hunk that crept in > > I don't think the slbie invalidation is necessary, as explained on the > list. > > target/ppc/helper.h | 2 +- > target/ppc/mmu-hash64.c | 56 +++++++++++++++++++++++++++++++++++------ > target/ppc/translate.c | 5 +++- > 3 files changed, 54 insertions(+), 9 deletions(-) > > diff --git a/target/ppc/helper.h b/target/ppc/helper.h > index ee1498050d..2dfa1c6942 100644 > --- a/target/ppc/helper.h > +++ b/target/ppc/helper.h > @@ -615,7 +615,7 @@ DEF_HELPER_FLAGS_3(store_slb, TCG_CALL_NO_RWG, void, env, tl, tl) > DEF_HELPER_2(load_slb_esid, tl, env, tl) > DEF_HELPER_2(load_slb_vsid, tl, env, tl) > DEF_HELPER_2(find_slb_vsid, tl, env, tl) > -DEF_HELPER_FLAGS_1(slbia, TCG_CALL_NO_RWG, void, env) > +DEF_HELPER_FLAGS_2(slbia, TCG_CALL_NO_RWG, void, env, i32) > DEF_HELPER_FLAGS_2(slbie, TCG_CALL_NO_RWG, void, env, tl) > DEF_HELPER_FLAGS_2(slbieg, TCG_CALL_NO_RWG, void, env, tl) > #endif > diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c > index 373d44de74..e5baabf0e1 100644 > --- a/target/ppc/mmu-hash64.c > +++ b/target/ppc/mmu-hash64.c > @@ -95,9 +95,10 @@ void dump_slb(PowerPCCPU *cpu) > } > } > > -void helper_slbia(CPUPPCState *env) > +void helper_slbia(CPUPPCState *env, uint32_t ih) > { > PowerPCCPU *cpu = env_archcpu(env); > + int starting_entry; > int n; > > /* > @@ -111,18 +112,59 @@ void helper_slbia(CPUPPCState *env) > * expected that slbmte is more common than slbia, and slbia is usually > * going to evict valid SLB entries, so that tradeoff is unlikely to be a > * good one. > + * > + * ISA v2.05 introduced IH field with values 0,1,2,6. These all invalidate > + * the same SLB entries (everything but entry 0), but differ in what > + * "lookaside information" is invalidated. TCG can ignore this and flush > + * everything. > + * > + * ISA v3.0 introduced additional values 3,4,7, which change what SLBs are > + * invalidated. > */ > > - /* XXX: Warning: slbia never invalidates the first segment */ > - for (n = 1; n < cpu->hash64_opts->slb_size; n++) { > - ppc_slb_t *slb = &env->slb[n]; > + env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH; > + > + starting_entry = 1; /* default for IH=0,1,2,6 */ > + > + if (env->mmu_model == POWERPC_MMU_3_00) { > + switch (ih) { > + case 0x7: > + /* invalidate no SLBs, but all lookaside information */ > + return; > > - if (slb->esid & SLB_ESID_V) { > - slb->esid &= ~SLB_ESID_V; > + case 0x3: > + case 0x4: > + /* also considers SLB entry 0 */ > + starting_entry = 0; > + break; > + > + case 0x5: > + /* treat undefined values as ih==0, and warn */ > + qemu_log_mask(LOG_GUEST_ERROR, > + "slbia undefined IH field %u.\n", ih); > + break; > + > + default: > + /* 0,1,2,6 */ > + break; > } > } > > - env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH; > + for (n = starting_entry; n < cpu->hash64_opts->slb_size; n++) { > + ppc_slb_t *slb = &env->slb[n]; > + > + if (!(slb->esid & SLB_ESID_V)) { > + continue; > + } > + if (env->mmu_model == POWERPC_MMU_3_00) { > + if (ih == 0x3 && (slb->vsid & SLB_VSID_C) == 0) { > + /* preserves entries with a class value of 0 */ > + continue; > + } > + } > + > + slb->esid &= ~SLB_ESID_V; > + } > } > > static void __helper_slbie(CPUPPCState *env, target_ulong addr, > diff --git a/target/ppc/translate.c b/target/ppc/translate.c > index eb0ddba850..e514732a09 100644 > --- a/target/ppc/translate.c > +++ b/target/ppc/translate.c > @@ -5027,12 +5027,15 @@ static void gen_tlbsync(DisasContext *ctx) > /* slbia */ > static void gen_slbia(DisasContext *ctx) > { > + uint32_t ih = (ctx->opcode >> 21) & 0x7; > + TCGv_i32 t0 = tcg_const_i32(ih); > + > #if defined(CONFIG_USER_ONLY) > GEN_PRIV; > #else > CHK_SV; > > - gen_helper_slbia(cpu_env); > + gen_helper_slbia(cpu_env, t0); > #endif /* defined(CONFIG_USER_ONLY) */ > } >
diff --git a/target/ppc/helper.h b/target/ppc/helper.h index ee1498050d..2dfa1c6942 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -615,7 +615,7 @@ DEF_HELPER_FLAGS_3(store_slb, TCG_CALL_NO_RWG, void, env, tl, tl) DEF_HELPER_2(load_slb_esid, tl, env, tl) DEF_HELPER_2(load_slb_vsid, tl, env, tl) DEF_HELPER_2(find_slb_vsid, tl, env, tl) -DEF_HELPER_FLAGS_1(slbia, TCG_CALL_NO_RWG, void, env) +DEF_HELPER_FLAGS_2(slbia, TCG_CALL_NO_RWG, void, env, i32) DEF_HELPER_FLAGS_2(slbie, TCG_CALL_NO_RWG, void, env, tl) DEF_HELPER_FLAGS_2(slbieg, TCG_CALL_NO_RWG, void, env, tl) #endif diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c index 373d44de74..e5baabf0e1 100644 --- a/target/ppc/mmu-hash64.c +++ b/target/ppc/mmu-hash64.c @@ -95,9 +95,10 @@ void dump_slb(PowerPCCPU *cpu) } } -void helper_slbia(CPUPPCState *env) +void helper_slbia(CPUPPCState *env, uint32_t ih) { PowerPCCPU *cpu = env_archcpu(env); + int starting_entry; int n; /* @@ -111,18 +112,59 @@ void helper_slbia(CPUPPCState *env) * expected that slbmte is more common than slbia, and slbia is usually * going to evict valid SLB entries, so that tradeoff is unlikely to be a * good one. + * + * ISA v2.05 introduced IH field with values 0,1,2,6. These all invalidate + * the same SLB entries (everything but entry 0), but differ in what + * "lookaside information" is invalidated. TCG can ignore this and flush + * everything. + * + * ISA v3.0 introduced additional values 3,4,7, which change what SLBs are + * invalidated. */ - /* XXX: Warning: slbia never invalidates the first segment */ - for (n = 1; n < cpu->hash64_opts->slb_size; n++) { - ppc_slb_t *slb = &env->slb[n]; + env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH; + + starting_entry = 1; /* default for IH=0,1,2,6 */ + + if (env->mmu_model == POWERPC_MMU_3_00) { + switch (ih) { + case 0x7: + /* invalidate no SLBs, but all lookaside information */ + return; - if (slb->esid & SLB_ESID_V) { - slb->esid &= ~SLB_ESID_V; + case 0x3: + case 0x4: + /* also considers SLB entry 0 */ + starting_entry = 0; + break; + + case 0x5: + /* treat undefined values as ih==0, and warn */ + qemu_log_mask(LOG_GUEST_ERROR, + "slbia undefined IH field %u.\n", ih); + break; + + default: + /* 0,1,2,6 */ + break; } } - env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH; + for (n = starting_entry; n < cpu->hash64_opts->slb_size; n++) { + ppc_slb_t *slb = &env->slb[n]; + + if (!(slb->esid & SLB_ESID_V)) { + continue; + } + if (env->mmu_model == POWERPC_MMU_3_00) { + if (ih == 0x3 && (slb->vsid & SLB_VSID_C) == 0) { + /* preserves entries with a class value of 0 */ + continue; + } + } + + slb->esid &= ~SLB_ESID_V; + } } static void __helper_slbie(CPUPPCState *env, target_ulong addr, diff --git a/target/ppc/translate.c b/target/ppc/translate.c index eb0ddba850..e514732a09 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -5027,12 +5027,15 @@ static void gen_tlbsync(DisasContext *ctx) /* slbia */ static void gen_slbia(DisasContext *ctx) { + uint32_t ih = (ctx->opcode >> 21) & 0x7; + TCGv_i32 t0 = tcg_const_i32(ih); + #if defined(CONFIG_USER_ONLY) GEN_PRIV; #else CHK_SV; - gen_helper_slbia(cpu_env); + gen_helper_slbia(cpu_env, t0); #endif /* defined(CONFIG_USER_ONLY) */ }
The new ISA v3.0 slbia variants have not been implemented for TCG, which can lead to crashing when a POWER9 machine boots Linux using the hash MMU, for example ("disable_radix" kernel command line). Add them. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> --- Changes in v2: - Rewrite changelog. - Remove stray slbie hunk that crept in I don't think the slbie invalidation is necessary, as explained on the list. target/ppc/helper.h | 2 +- target/ppc/mmu-hash64.c | 56 +++++++++++++++++++++++++++++++++++------ target/ppc/translate.c | 5 +++- 3 files changed, 54 insertions(+), 9 deletions(-)