diff options
author | Marc Zyngier <maz@kernel.org> | 2021-04-08 14:10:09 +0100 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2021-04-08 18:45:16 +0100 |
commit | 31a32b49b80f79cbb84a9c948c5609c6fc044443 (patch) | |
tree | e05bd1f6475ece8044c9d61a1b1a46e00c4c6996 /arch/arm64/kernel/idreg-override.c | |
parent | cac642c12a805ae7565a263b59fb94ad19e81952 (diff) | |
download | linux-31a32b49b80f79cbb84a9c948c5609c6fc044443.tar.gz linux-31a32b49b80f79cbb84a9c948c5609c6fc044443.tar.bz2 linux-31a32b49b80f79cbb84a9c948c5609c6fc044443.zip |
arm64: Cope with CPUs stuck in VHE mode
It seems that the CPUs part of the SoC known as Apple M1 have the
terrible habit of being stuck with HCR_EL2.E2H==1, in violation
of the architecture.
Try and work around this deplorable state of affairs by detecting
the stuck bit early and short-circuit the nVHE dance. Additional
filtering code ensures that attempts at switching to nVHE from
the command-line are also ignored.
It is still unknown whether there are many more such nuggets
to be found...
Reported-by: Hector Martin <marcan@marcan.st>
Acked-by: Will Deacon <will@kernel.org>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20210408131010.1109027-3-maz@kernel.org
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'arch/arm64/kernel/idreg-override.c')
-rw-r--r-- | arch/arm64/kernel/idreg-override.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/arch/arm64/kernel/idreg-override.c b/arch/arm64/kernel/idreg-override.c index be92fcd319a1..e628c8ce1ffe 100644 --- a/arch/arm64/kernel/idreg-override.c +++ b/arch/arm64/kernel/idreg-override.c @@ -29,11 +29,22 @@ struct ftr_set_desc { } fields[]; }; +static bool __init mmfr1_vh_filter(u64 val) +{ + /* + * If we ever reach this point while running VHE, we're + * guaranteed to be on one of these funky, VHE-stuck CPUs. If + * the user was trying to force nVHE on us, proceed with + * attitude adjustment. + */ + return !(is_kernel_in_hyp_mode() && val == 0); +} + static const struct ftr_set_desc mmfr1 __initconst = { .name = "id_aa64mmfr1", .override = &id_aa64mmfr1_override, .fields = { - { "vh", ID_AA64MMFR1_VHE_SHIFT }, + { "vh", ID_AA64MMFR1_VHE_SHIFT, mmfr1_vh_filter }, {} }, }; |