Message ID | 20191201122018.25808-4-maz@kernel.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | target/arm: More EL2 trapping fixes | expand |
On 12/1/19 12:20 PM, Marc Zyngier wrote: > HCR_EL2.TID3 requires that AArch32 reads of MVFR[012] are trapped to > EL2, and HCR_EL2.TID0 does the same for reads of FPSID. > In order to handle this, introduce a new TCG helper function that > checks for these control bits before executing the VMRC instruction. > > Tested with a hacked-up version of KVM/arm64 that sets the control > bits for 32bit guests. > > Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> > Signed-off-by: Marc Zyngier <maz@kernel.org> > --- > target/arm/helper-a64.h | 2 ++ > target/arm/translate-vfp.inc.c | 18 +++++++++++++++--- > target/arm/vfp_helper.c | 29 +++++++++++++++++++++++++++++ > 3 files changed, 46 insertions(+), 3 deletions(-) Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Annoying that there's a bug in the manual -- FPSID is listed as group 0 in plenty of places, except in the pseudo-code for Accessing the FPSID which uses TID3. r~
On 2019-12-02 15:35, Richard Henderson wrote: > On 12/1/19 12:20 PM, Marc Zyngier wrote: >> HCR_EL2.TID3 requires that AArch32 reads of MVFR[012] are trapped to >> EL2, and HCR_EL2.TID0 does the same for reads of FPSID. >> In order to handle this, introduce a new TCG helper function that >> checks for these control bits before executing the VMRC instruction. >> >> Tested with a hacked-up version of KVM/arm64 that sets the control >> bits for 32bit guests. >> >> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> >> Signed-off-by: Marc Zyngier <maz@kernel.org> >> --- >> target/arm/helper-a64.h | 2 ++ >> target/arm/translate-vfp.inc.c | 18 +++++++++++++++--- >> target/arm/vfp_helper.c | 29 +++++++++++++++++++++++++++++ >> 3 files changed, 46 insertions(+), 3 deletions(-) > > Reviewed-by: Richard Henderson <richard.henderson@linaro.org> > > Annoying that there's a bug in the manual -- FPSID is listed as group > 0 in > plenty of places, except in the pseudo-code for Accessing the FPSID > which uses TID3. Are you sure? I'm looking at DDI0487E_a, and the pseudo-code for AArch32.CheckAdvSIMDOrFPRegisterTraps has this check: <quote> if (tid0 == '1' && reg == '0000') // FPSID || (tid3 == '1' && reg IN {'0101', '0110', '0111'}) then // MVFRx if ELUsingAArch32(EL2) then AArch32.SystemAccessTrap(M32_Hyp, 0x8); // Exception_AdvSIMDFPAccessTrap else AArch64.AArch32SystemAccessTrap(EL2, 0x8); // Exception_AdvSIMDFPAccessTrap </quote> which seems to do the right thing. Or have you spotted a discrepancy somewhere else (which would be oh-so-surprising...)? Thanks, M.
On 12/2/19 4:45 PM, Marc Zyngier wrote: >> Annoying that there's a bug in the manual -- FPSID is listed as group 0 in >> plenty of places, except in the pseudo-code for Accessing the FPSID >> which uses TID3. > > Are you sure? I'm looking at DDI0487E_a, ... > Or have you spotted a discrepancy > somewhere else (which would be oh-so-surprising...)? In DDI0487E_a, page G8-6028: > elsif EL2Enabled() && !ELUsingAArch32(EL2) && HCR_EL2.TID3 == '1' then > AArch64.AArch32SystemAccessTrap(EL2, 0x08); > elsif EL2Enabled() && ELUsingAArch32(EL2) && HCR.TID3 == '1' then > AArch32.TakeHypTrapException(0x08); > else > return FPSID; within the summary documentation for FPSID. r~
On 2019-12-02 16:56, Richard Henderson wrote: > On 12/2/19 4:45 PM, Marc Zyngier wrote: >>> Annoying that there's a bug in the manual -- FPSID is listed as >>> group 0 in >>> plenty of places, except in the pseudo-code for Accessing the FPSID >>> which uses TID3. >> >> Are you sure? I'm looking at DDI0487E_a, > ... >> Or have you spotted a discrepancy >> somewhere else (which would be oh-so-surprising...)? > > In DDI0487E_a, page G8-6028: > >> elsif EL2Enabled() && !ELUsingAArch32(EL2) && HCR_EL2.TID3 == '1' >> then >> AArch64.AArch32SystemAccessTrap(EL2, 0x08); >> elsif EL2Enabled() && ELUsingAArch32(EL2) && HCR.TID3 == '1' then >> AArch32.TakeHypTrapException(0x08); >> else >> return FPSID; > > within the summary documentation for FPSID. Ah, that was too obvious for me to find ;-). Indeed, this looks totally bogus. I'll try and poke a few people... Thanks, M.
On Sun, 1 Dec 2019 at 12:20, Marc Zyngier <maz@kernel.org> wrote: > > HCR_EL2.TID3 requires that AArch32 reads of MVFR[012] are trapped to > EL2, and HCR_EL2.TID0 does the same for reads of FPSID. > In order to handle this, introduce a new TCG helper function that > checks for these control bits before executing the VMRC instruction. > > Tested with a hacked-up version of KVM/arm64 that sets the control > bits for 32bit guests. > > Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> > Signed-off-by: Marc Zyngier <maz@kernel.org> > --- > target/arm/helper-a64.h | 2 ++ > target/arm/translate-vfp.inc.c | 18 +++++++++++++++--- > target/arm/vfp_helper.c | 29 +++++++++++++++++++++++++++++ > 3 files changed, 46 insertions(+), 3 deletions(-) > > diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h > index a915c1247f..0af44dc814 100644 > --- a/target/arm/helper-a64.h > +++ b/target/arm/helper-a64.h > @@ -102,3 +102,5 @@ DEF_HELPER_FLAGS_3(autda, TCG_CALL_NO_WG, i64, env, i64, i64) > DEF_HELPER_FLAGS_3(autdb, TCG_CALL_NO_WG, i64, env, i64, i64) > DEF_HELPER_FLAGS_2(xpaci, TCG_CALL_NO_RWG_SE, i64, env, i64) > DEF_HELPER_FLAGS_2(xpacd, TCG_CALL_NO_RWG_SE, i64, env, i64) > + > +DEF_HELPER_3(check_hcr_el2_trap, void, env, i32, i32) This has to be in helper.h, not helper-a64.h, otherwise the arm-softmmu target won't build. helper-a64.h is for helper functions which only exist in the aarch64 binary. thanks -- PMM
On 2019-12-06 14:08, Peter Maydell wrote: > On Sun, 1 Dec 2019 at 12:20, Marc Zyngier <maz@kernel.org> wrote: >> >> HCR_EL2.TID3 requires that AArch32 reads of MVFR[012] are trapped to >> EL2, and HCR_EL2.TID0 does the same for reads of FPSID. >> In order to handle this, introduce a new TCG helper function that >> checks for these control bits before executing the VMRC instruction. >> >> Tested with a hacked-up version of KVM/arm64 that sets the control >> bits for 32bit guests. >> >> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> >> Signed-off-by: Marc Zyngier <maz@kernel.org> >> --- >> target/arm/helper-a64.h | 2 ++ >> target/arm/translate-vfp.inc.c | 18 +++++++++++++++--- >> target/arm/vfp_helper.c | 29 +++++++++++++++++++++++++++++ >> 3 files changed, 46 insertions(+), 3 deletions(-) >> >> diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h >> index a915c1247f..0af44dc814 100644 >> --- a/target/arm/helper-a64.h >> +++ b/target/arm/helper-a64.h >> @@ -102,3 +102,5 @@ DEF_HELPER_FLAGS_3(autda, TCG_CALL_NO_WG, i64, >> env, i64, i64) >> DEF_HELPER_FLAGS_3(autdb, TCG_CALL_NO_WG, i64, env, i64, i64) >> DEF_HELPER_FLAGS_2(xpaci, TCG_CALL_NO_RWG_SE, i64, env, i64) >> DEF_HELPER_FLAGS_2(xpacd, TCG_CALL_NO_RWG_SE, i64, env, i64) >> + >> +DEF_HELPER_3(check_hcr_el2_trap, void, env, i32, i32) > > This has to be in helper.h, not helper-a64.h, otherwise > the arm-softmmu target won't build. helper-a64.h is for > helper functions which only exist in the aarch64 binary. Ah, fair enough. I guess I should build all targets rather than limit myself to aarch64... I'll fix that and repost the series, having hopefully addressed Richard's comments. Thanks, M.
On 12/6/19 6:08 AM, Peter Maydell wrote: >> DEF_HELPER_FLAGS_3(autdb, TCG_CALL_NO_WG, i64, env, i64, i64) >> DEF_HELPER_FLAGS_2(xpaci, TCG_CALL_NO_RWG_SE, i64, env, i64) >> DEF_HELPER_FLAGS_2(xpacd, TCG_CALL_NO_RWG_SE, i64, env, i64) >> + >> +DEF_HELPER_3(check_hcr_el2_trap, void, env, i32, i32) > > This has to be in helper.h, not helper-a64.h, otherwise > the arm-softmmu target won't build. helper-a64.h is for > helper functions which only exist in the aarch64 binary. Oh, while we're at it, DEF_HELPER_FLAGS_3(..., TCG_CALL_NO_WG, ...) The helper does not modify tcg globals (on successful return). It does read globals (via the exception path), and of course it has side effects (the exception). r~
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h index a915c1247f..0af44dc814 100644 --- a/target/arm/helper-a64.h +++ b/target/arm/helper-a64.h @@ -102,3 +102,5 @@ DEF_HELPER_FLAGS_3(autda, TCG_CALL_NO_WG, i64, env, i64, i64) DEF_HELPER_FLAGS_3(autdb, TCG_CALL_NO_WG, i64, env, i64, i64) DEF_HELPER_FLAGS_2(xpaci, TCG_CALL_NO_RWG_SE, i64, env, i64) DEF_HELPER_FLAGS_2(xpacd, TCG_CALL_NO_RWG_SE, i64, env, i64) + +DEF_HELPER_3(check_hcr_el2_trap, void, env, i32, i32) diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c index 85c5ef897b..bf90ac0e5b 100644 --- a/target/arm/translate-vfp.inc.c +++ b/target/arm/translate-vfp.inc.c @@ -761,13 +761,25 @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a) if (a->l) { /* VMRS, move VFP special register to gp register */ switch (a->reg) { + case ARM_VFP_MVFR0: + case ARM_VFP_MVFR1: + case ARM_VFP_MVFR2: case ARM_VFP_FPSID: + if (s->current_el == 1) { + TCGv_i32 tcg_reg, tcg_rt; + + gen_set_condexec(s); + gen_set_pc_im(s, s->pc_curr); + tcg_reg = tcg_const_i32(a->reg); + tcg_rt = tcg_const_i32(a->rt); + gen_helper_check_hcr_el2_trap(cpu_env, tcg_rt, tcg_reg); + tcg_temp_free_i32(tcg_reg); + tcg_temp_free_i32(tcg_rt); + } + /* fall through */ case ARM_VFP_FPEXC: case ARM_VFP_FPINST: case ARM_VFP_FPINST2: - case ARM_VFP_MVFR0: - case ARM_VFP_MVFR1: - case ARM_VFP_MVFR2: tmp = load_cpu_field(vfp.xregs[a->reg]); break; case ARM_VFP_FPSCR: diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c index 9710ef1c3e..0ae7d4f34a 100644 --- a/target/arm/vfp_helper.c +++ b/target/arm/vfp_helper.c @@ -1322,4 +1322,33 @@ float64 HELPER(frint64_d)(float64 f, void *fpst) return frint_d(f, fpst, 64); } +void HELPER(check_hcr_el2_trap)(CPUARMState *env, uint32_t rt, uint32_t reg) +{ + uint32_t syndrome; + + switch (reg) { + case ARM_VFP_MVFR0: + case ARM_VFP_MVFR1: + case ARM_VFP_MVFR2: + if (!(arm_hcr_el2_eff(env) & HCR_TID3)) { + return; + } + break; + case ARM_VFP_FPSID: + if (!(arm_hcr_el2_eff(env) & HCR_TID0)) { + return; + } + break; + default: + g_assert_not_reached(); + } + + syndrome = ((EC_FPIDTRAP << ARM_EL_EC_SHIFT) + | ARM_EL_IL + | (1 << 24) | (0xe << 20) | (7 << 14) + | (reg << 10) | (rt << 5) | 1); + + raise_exception(env, EXCP_HYP_TRAP, syndrome, 2); +} + #endif