summaryrefslogtreecommitdiffstats
path: root/arch/arm64/kernel/idreg-override.c
diff options
context:
space:
mode:
authorMarc Zyngier <maz@kernel.org>2021-04-08 14:10:09 +0100
committerCatalin Marinas <catalin.marinas@arm.com>2021-04-08 18:45:16 +0100
commit31a32b49b80f79cbb84a9c948c5609c6fc044443 (patch)
treee05bd1f6475ece8044c9d61a1b1a46e00c4c6996 /arch/arm64/kernel/idreg-override.c
parentcac642c12a805ae7565a263b59fb94ad19e81952 (diff)
downloadlinux-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.c13
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 },
{}
},
};