summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm64/include/asm/mmu_context.h2
-rw-r--r--arch/arm64/kernel/cpufeature.c12
-rw-r--r--arch/arm64/mm/context.c18
3 files changed, 32 insertions, 0 deletions
diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h
index a00f7cf35bbd..b1892a0dbcb0 100644
--- a/arch/arm64/include/asm/mmu_context.h
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -203,4 +203,6 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
#define deactivate_mm(tsk,mm) do { } while (0)
#define activate_mm(prev,next) switch_mm(prev, next, NULL)
+void verify_cpu_asid_bits(void);
+
#endif
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 282a4f852dd1..b7fa75fc0fa9 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -24,6 +24,7 @@
#include <asm/cpu.h>
#include <asm/cpufeature.h>
#include <asm/cpu_ops.h>
+#include <asm/mmu_context.h>
#include <asm/processor.h>
#include <asm/sysreg.h>
@@ -873,6 +874,15 @@ static u64 __raw_read_system_reg(u32 sys_id)
}
/*
+ * Check for CPU features that are used in early boot
+ * based on the Boot CPU value.
+ */
+static void check_early_cpu_features(void)
+{
+ verify_cpu_asid_bits();
+}
+
+/*
* Run through the enabled system capabilities and enable() it on this CPU.
* The capabilities were decided based on the available CPUs at the boot time.
* Any new CPU should match the system wide status of the capability. If the
@@ -885,6 +895,8 @@ void verify_local_cpu_capabilities(void)
int i;
const struct arm64_cpu_capabilities *caps;
+ check_early_cpu_features();
+
/*
* If we haven't computed the system capabilities, there is nothing
* to verify.
diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
index 21f9f1ea14f7..6b5783f6eb0e 100644
--- a/arch/arm64/mm/context.c
+++ b/arch/arm64/mm/context.c
@@ -24,6 +24,7 @@
#include <asm/cpufeature.h>
#include <asm/mmu_context.h>
+#include <asm/smp.h>
#include <asm/tlbflush.h>
static u32 asid_bits;
@@ -62,6 +63,23 @@ static u32 get_cpu_asid_bits(void)
return asid;
}
+/* Check if the current cpu's ASIDBits is compatible with asid_bits */
+void verify_cpu_asid_bits(void)
+{
+ u32 asid = get_cpu_asid_bits();
+
+ if (asid < asid_bits) {
+ /*
+ * We cannot decrease the ASID size at runtime, so panic if we support
+ * fewer ASID bits than the boot CPU.
+ */
+ pr_crit("CPU%d: smaller ASID size(%u) than boot CPU (%u)\n",
+ smp_processor_id(), asid, asid_bits);
+ update_cpu_boot_status(CPU_PANIC_KERNEL);
+ cpu_park_loop();
+ }
+}
+
static void flush_context(unsigned int cpu)
{
int i;