Message ID | 20240321115414.3169115-1-maz@kernel.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | arm64: Fix early handling of FEAT_E2H0 not being implemented | expand |
On Thu, Mar 21, 2024 at 11:54:14AM +0000, Marc Zyngier wrote: > Commit 3944382fa6f2 introduced checks for the FEAT_E2H0 not being > implemented. However, the check is absolutely wrong and makes a > point it testing a bit that is guaranteed to be zero. > > On top of that, the detection happens way too late, after the > init_el2_state has done its job. > > This went undetected because the HW this was tested on has E2H being > RAO/WI, and not RES1. However, the bug shows up when run as a nested > guest, where HCR_EL2.E2H is not necessarily set to 1. As a result, > booting the kernel in hVHE mode fails with timer accesses being > cought in a trap loop (which was fun to debug). > > Fix the check for ID_AA64MMFR4_EL1.E2H0, and set the HCR_EL2.E2H bit > early so that it can be checked by the rest of the init sequence. > > With this, hVHE works again in a NV environment that doesn't have > FEAT_E2H0. > > Fixes: 3944382fa6f2 ("arm64: Treat HCR_EL2.E2H as RES1 when ID_AA64MMFR4_EL1.E2H0 is negative") > Signed-off-by: Marc Zyngier <maz@kernel.org> Acked-by: Catalin Marinas <catalin.marinas@arm.com> I assume Oliver will take it, otherwise I can pick it up after -rc1 since I don't have the fixed commit in my tree.
On Thu, Mar 21, 2024 at 08:16:15PM +0000, Catalin Marinas wrote: > On Thu, Mar 21, 2024 at 11:54:14AM +0000, Marc Zyngier wrote: > > Commit 3944382fa6f2 introduced checks for the FEAT_E2H0 not being > > implemented. However, the check is absolutely wrong and makes a > > point it testing a bit that is guaranteed to be zero. > > > > On top of that, the detection happens way too late, after the > > init_el2_state has done its job. > > > > This went undetected because the HW this was tested on has E2H being > > RAO/WI, and not RES1. However, the bug shows up when run as a nested > > guest, where HCR_EL2.E2H is not necessarily set to 1. As a result, > > booting the kernel in hVHE mode fails with timer accesses being > > cought in a trap loop (which was fun to debug). > > > > Fix the check for ID_AA64MMFR4_EL1.E2H0, and set the HCR_EL2.E2H bit > > early so that it can be checked by the rest of the init sequence. > > > > With this, hVHE works again in a NV environment that doesn't have > > FEAT_E2H0. > > > > Fixes: 3944382fa6f2 ("arm64: Treat HCR_EL2.E2H as RES1 when ID_AA64MMFR4_EL1.E2H0 is negative") > > Signed-off-by: Marc Zyngier <maz@kernel.org> > > Acked-by: Catalin Marinas <catalin.marinas@arm.com> Thanks! > I assume Oliver will take it, otherwise I can pick it up after -rc1 > since I don't have the fixed commit in my tree. I'll pick it up but wont be sending anything out until -rc1.
On Thu, 21 Mar 2024 11:54:14 +0000, Marc Zyngier wrote: > Commit 3944382fa6f2 introduced checks for the FEAT_E2H0 not being > implemented. However, the check is absolutely wrong and makes a > point it testing a bit that is guaranteed to be zero. > > On top of that, the detection happens way too late, after the > init_el2_state has done its job. > > [...] Applied, thanks! [1/1] arm64: Fix early handling of FEAT_E2H0 not being implemented commit: b3320142f3db9b3f2a23460abd3e22292e1530a5 Best regards,
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index ce08b744aaab..06234c3a15f3 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -291,6 +291,21 @@ SYM_INNER_LABEL(init_el2, SYM_L_LOCAL) blr x2 0: mov_q x0, HCR_HOST_NVHE_FLAGS + + /* + * Compliant CPUs advertise their VHE-onlyness with + * ID_AA64MMFR4_EL1.E2H0 < 0. HCR_EL2.E2H can be + * RES1 in that case. Publish the E2H bit early so that + * it can be picked up by the init_el2_state macro. + * + * Fruity CPUs seem to have HCR_EL2.E2H set to RAO/WI, but + * don't advertise it (they predate this relaxation). + */ + mrs_s x1, SYS_ID_AA64MMFR4_EL1 + tbz x1, #(ID_AA64MMFR4_EL1_E2H0_SHIFT + ID_AA64MMFR4_EL1_E2H0_WIDTH - 1), 1f + + orr x0, x0, #HCR_E2H +1: msr hcr_el2, x0 isb @@ -303,22 +318,10 @@ SYM_INNER_LABEL(init_el2, SYM_L_LOCAL) mov_q x1, INIT_SCTLR_EL1_MMU_OFF - /* - * Compliant CPUs advertise their VHE-onlyness with - * ID_AA64MMFR4_EL1.E2H0 < 0. HCR_EL2.E2H can be - * RES1 in that case. - * - * Fruity CPUs seem to have HCR_EL2.E2H set to RES1, but - * don't advertise it (they predate this relaxation). - */ - mrs_s x0, SYS_ID_AA64MMFR4_EL1 - ubfx x0, x0, #ID_AA64MMFR4_EL1_E2H0_SHIFT, #ID_AA64MMFR4_EL1_E2H0_WIDTH - tbnz x0, #(ID_AA64MMFR4_EL1_E2H0_SHIFT + ID_AA64MMFR4_EL1_E2H0_WIDTH - 1), 1f - mrs x0, hcr_el2 and x0, x0, #HCR_E2H cbz x0, 2f -1: + /* Set a sane SCTLR_EL1, the VHE way */ pre_disable_mmu_workaround msr_s SYS_SCTLR_EL12, x1
Commit 3944382fa6f2 introduced checks for the FEAT_E2H0 not being implemented. However, the check is absolutely wrong and makes a point it testing a bit that is guaranteed to be zero. On top of that, the detection happens way too late, after the init_el2_state has done its job. This went undetected because the HW this was tested on has E2H being RAO/WI, and not RES1. However, the bug shows up when run as a nested guest, where HCR_EL2.E2H is not necessarily set to 1. As a result, booting the kernel in hVHE mode fails with timer accesses being cought in a trap loop (which was fun to debug). Fix the check for ID_AA64MMFR4_EL1.E2H0, and set the HCR_EL2.E2H bit early so that it can be checked by the rest of the init sequence. With this, hVHE works again in a NV environment that doesn't have FEAT_E2H0. Fixes: 3944382fa6f2 ("arm64: Treat HCR_EL2.E2H as RES1 when ID_AA64MMFR4_EL1.E2H0 is negative") Signed-off-by: Marc Zyngier <maz@kernel.org> --- arch/arm64/kernel/head.S | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-)