summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/lib/feature-fixups.c
diff options
context:
space:
mode:
authorMichael Ellerman <mpe@ellerman.id.au>2016-07-26 14:29:18 +0200
committerMichael Ellerman <mpe@ellerman.id.au>2016-08-01 03:14:56 +0200
commita28e46f109c9637b2539b9995078d5df4f7f6c09 (patch)
tree954cdde1913d243e517596aab5718dfa65fcd800 /arch/powerpc/lib/feature-fixups.c
parentpowerpc/64: Do feature patching before MMU init (diff)
downloadlinux-a28e46f109c9637b2539b9995078d5df4f7f6c09.tar.xz
linux-a28e46f109c9637b2539b9995078d5df4f7f6c09.zip
powerpc/kernel: Check features don't change after patching
Early in boot we binary patch some sections of code based on the CPU and MMU feature bits. But it is a one-time patching, there is no facility for repatching the code later if the set of features change. It is a major bug if the set of features changes after we've done the code patching - so add a check for it. Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/lib/feature-fixups.c')
-rw-r--r--arch/powerpc/lib/feature-fixups.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index defb2998b818..59c7caee05b2 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -152,10 +152,19 @@ static void do_final_fixups(void)
#endif
}
-void apply_feature_fixups(void)
+static unsigned long __initdata saved_cpu_features;
+static unsigned int __initdata saved_mmu_features;
+#ifdef CONFIG_PPC64
+static unsigned long __initdata saved_firmware_features;
+#endif
+
+void __init apply_feature_fixups(void)
{
struct cpu_spec *spec = *PTRRELOC(&cur_cpu_spec);
+ *PTRRELOC(&saved_cpu_features) = spec->cpu_features;
+ *PTRRELOC(&saved_mmu_features) = spec->mmu_features;
+
/*
* Apply the CPU-specific and firmware specific fixups to kernel text
* (nop out sections not relevant to this CPU or this firmware).
@@ -173,12 +182,28 @@ void apply_feature_fixups(void)
PTRRELOC(&__stop___lwsync_fixup));
#ifdef CONFIG_PPC64
+ saved_firmware_features = powerpc_firmware_features;
do_feature_fixups(powerpc_firmware_features,
&__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
#endif
do_final_fixups();
}
+static int __init check_features(void)
+{
+ WARN(saved_cpu_features != cur_cpu_spec->cpu_features,
+ "CPU features changed after feature patching!\n");
+ WARN(saved_mmu_features != cur_cpu_spec->mmu_features,
+ "MMU features changed after feature patching!\n");
+#ifdef CONFIG_PPC64
+ WARN(saved_firmware_features != powerpc_firmware_features,
+ "Firmware features changed after feature patching!\n");
+#endif
+
+ return 0;
+}
+late_initcall(check_features);
+
#ifdef CONFIG_FTR_FIXUP_SELFTEST
#define check(x) \