]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
powerpc: Copy down exception vectors after feature fixups
authorAnton Blanchard <anton@samba.org>
Mon, 14 Nov 2011 12:54:47 +0000 (12:54 +0000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Wed, 16 Nov 2011 03:47:54 +0000 (14:47 +1100)
kdump fails because we try to execute an HV only instruction. Feature
fixups are being applied after we copy the exception vectors down to 0
so they miss out on any updates.

We have always had this issue but it only became critical in v3.0
when we added CFAR support (breaks POWER5) and v3.1 when we added
POWERNV (breaks everyone).

Signed-off-by: Anton Blanchard <anton@samba.org>
Cc: <stable@kernel.org> [v3.0+]
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/include/asm/sections.h
arch/powerpc/include/asm/synch.h
arch/powerpc/kernel/kvm.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/lib/feature-fixups.c

index 6fbce725c710f97453079205e190c02c7365cd0b..a0f358d4a00cd57ba3b22fbbf1024c7daba65fa4 100644 (file)
@@ -8,7 +8,7 @@
 
 #ifdef __powerpc64__
 
-extern char _end[];
+extern char __end_interrupts[];
 
 static inline int in_kernel_text(unsigned long addr)
 {
index d7cab44643c51d90f1f79509939e3c734b735eba..87878c68d1c2048bbac490c65a81030bfae317c7 100644 (file)
@@ -13,6 +13,7 @@
 extern unsigned int __start___lwsync_fixup, __stop___lwsync_fixup;
 extern void do_lwsync_fixups(unsigned long value, void *fixup_start,
                             void *fixup_end);
+extern void do_final_fixups(void);
 
 static inline void eieio(void)
 {
index 35f27646c4ff5af053313054c953000d0be64031..2985338d0e10164e3b77ab12fcc3bb755a1a6fb3 100644 (file)
@@ -132,7 +132,6 @@ static void kvm_patch_ins_b(u32 *inst, int addr)
        /* On relocatable kernels interrupts handlers and our code
           can be in different regions, so we don't patch them */
 
-       extern u32 __end_interrupts;
        if ((ulong)inst < (ulong)&__end_interrupts)
                return;
 #endif
index c1ce86357ecb4a3a47411c18e6fe88cfd5c07d8b..ac761081511355ee68854ee02ade12f17ef93e18 100644 (file)
@@ -107,6 +107,8 @@ notrace unsigned long __init early_init(unsigned long dt_ptr)
                         PTRRELOC(&__start___lwsync_fixup),
                         PTRRELOC(&__stop___lwsync_fixup));
 
+       do_final_fixups();
+
        return KERNELBASE + offset;
 }
 
index 1a9dea80a69b46a42b9df6ed4ce4d45f385abb85..fb9bb46e7e881a584c1532a6768622395a5045be 100644 (file)
@@ -359,6 +359,7 @@ void __init setup_system(void)
                          &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
        do_lwsync_fixups(cur_cpu_spec->cpu_features,
                         &__start___lwsync_fixup, &__stop___lwsync_fixup);
+       do_final_fixups();
 
        /*
         * Unflatten the device-tree passed by prom_init or kexec
index 0d08d0171392a4e7ec72e21226737cc458e3a98f..7a8a7487cee8dde9d06aa86fff3bd32bdd54433e 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/init.h>
 #include <asm/cputable.h>
 #include <asm/code-patching.h>
+#include <asm/page.h>
+#include <asm/sections.h>
 
 
 struct fixup_entry {
@@ -128,6 +130,27 @@ void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
        }
 }
 
+void do_final_fixups(void)
+{
+#if defined(CONFIG_PPC64) && defined(CONFIG_RELOCATABLE)
+       int *src, *dest;
+       unsigned long length;
+
+       if (PHYSICAL_START == 0)
+               return;
+
+       src = (int *)(KERNELBASE + PHYSICAL_START);
+       dest = (int *)KERNELBASE;
+       length = (__end_interrupts - _stext) / sizeof(int);
+
+       while (length--) {
+               patch_instruction(dest, *src);
+               src++;
+               dest++;
+       }
+#endif
+}
+
 #ifdef CONFIG_FTR_FIXUP_SELFTEST
 
 #define check(x)       \