Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc: Copy down exception vectors after feature fixups

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>

authored by

Anton Blanchard and committed by
Benjamin Herrenschmidt
d715e433 6d1e2c6c

+28 -2
+1 -1
arch/powerpc/include/asm/sections.h
··· 8 8 9 9 #ifdef __powerpc64__ 10 10 11 - extern char _end[]; 11 + extern char __end_interrupts[]; 12 12 13 13 static inline int in_kernel_text(unsigned long addr) 14 14 {
+1
arch/powerpc/include/asm/synch.h
··· 13 13 extern unsigned int __start___lwsync_fixup, __stop___lwsync_fixup; 14 14 extern void do_lwsync_fixups(unsigned long value, void *fixup_start, 15 15 void *fixup_end); 16 + extern void do_final_fixups(void); 16 17 17 18 static inline void eieio(void) 18 19 {
-1
arch/powerpc/kernel/kvm.c
··· 132 132 /* On relocatable kernels interrupts handlers and our code 133 133 can be in different regions, so we don't patch them */ 134 134 135 - extern u32 __end_interrupts; 136 135 if ((ulong)inst < (ulong)&__end_interrupts) 137 136 return; 138 137 #endif
+2
arch/powerpc/kernel/setup_32.c
··· 107 107 PTRRELOC(&__start___lwsync_fixup), 108 108 PTRRELOC(&__stop___lwsync_fixup)); 109 109 110 + do_final_fixups(); 111 + 110 112 return KERNELBASE + offset; 111 113 } 112 114
+1
arch/powerpc/kernel/setup_64.c
··· 359 359 &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup); 360 360 do_lwsync_fixups(cur_cpu_spec->cpu_features, 361 361 &__start___lwsync_fixup, &__stop___lwsync_fixup); 362 + do_final_fixups(); 362 363 363 364 /* 364 365 * Unflatten the device-tree passed by prom_init or kexec
+23
arch/powerpc/lib/feature-fixups.c
··· 18 18 #include <linux/init.h> 19 19 #include <asm/cputable.h> 20 20 #include <asm/code-patching.h> 21 + #include <asm/page.h> 22 + #include <asm/sections.h> 21 23 22 24 23 25 struct fixup_entry { ··· 128 126 dest = (void *)start + *start; 129 127 patch_instruction(dest, PPC_INST_LWSYNC); 130 128 } 129 + } 130 + 131 + void do_final_fixups(void) 132 + { 133 + #if defined(CONFIG_PPC64) && defined(CONFIG_RELOCATABLE) 134 + int *src, *dest; 135 + unsigned long length; 136 + 137 + if (PHYSICAL_START == 0) 138 + return; 139 + 140 + src = (int *)(KERNELBASE + PHYSICAL_START); 141 + dest = (int *)KERNELBASE; 142 + length = (__end_interrupts - _stext) / sizeof(int); 143 + 144 + while (length--) { 145 + patch_instruction(dest, *src); 146 + src++; 147 + dest++; 148 + } 149 + #endif 131 150 } 132 151 133 152 #ifdef CONFIG_FTR_FIXUP_SELFTEST