aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64
diff options
context:
space:
mode:
authorHidetoshi Seto <[seto.hidetoshi@jp.fujitsu.com]>2009-08-06 17:51:56 -0400
committerTony Luck <tony.luck@intel.com>2009-09-14 19:18:02 -0400
commit07a6a4ae827b54cec4c1b1d92bed1cc9176b45ec (patch)
tree2be2a4a567e0fbd672cac86ebd06d4411e583e67 /arch/ia64
parent4295ab34883d2070b1145e14f4619478e9788807 (diff)
[IA64] kexec: Make INIT safe while transition to
kdump/kexec kernel Summary: Asserting INIT on the beginning of kdump/kexec kernel will result in unexpected behavior because INIT handler for previous kernel is invoked on new kernel. Description: In panic situation, we can receive INIT while kernel transition, i.e. from beginning of panic to bootstrap of kdump kernel. Since we initialize registers on leave from current kernel, no longer monarch/slave handlers of current kernel in virtual mode are called safely. (In fact system goes hang as far as I confirmed) How to Reproduce: Start kdump # echo c > /proc/sysrq-trigger Then assert INIT while kdump kernel is booting, before new INIT handler for kdump kernel is registered. Expected(Desirable) result: kdump kernel boots without any problem, crashdump retrieved Actual result: INIT handler for previous kernel is invoked on kdump kernel => panic, hang etc. (unexpected) Proposed fix: We can unregister these init handlers from SAL before jumping into new kernel, however then the INIT will fallback to default behavior, result in warmboot by SAL (according to the SAL specification) and we cannot retrieve the crashdump. Therefore this patch introduces a NOP init handler and register it to SAL before leave from current kernel, to start kdump safely by preventing INITs from entering virtual mode and resulting in warmboot. On the other hand, in case of kexec that not for kdump, it also has same problem with INIT while kernel transition. This patch handles this case differently, because for kexec unregistering handlers will be preferred than registering NOP handler, since the situation "no handlers registered" is usual state for kernel's entry. Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Cc: Vivek Goyal <vgoyal@redhat.com> Cc: Haren Myneni <hbabu@us.ibm.com> Cc: kexec@lists.infradead.org Acked-by: Fenghua Yu <fenghua.yu@intel.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64')
-rw-r--r--arch/ia64/include/asm/mca.h1
-rw-r--r--arch/ia64/kernel/machine_kexec.c12
-rw-r--r--arch/ia64/kernel/mca_asm.S20
3 files changed, 33 insertions, 0 deletions
diff --git a/arch/ia64/include/asm/mca.h b/arch/ia64/include/asm/mca.h
index cb0952f51836..c171cdf0a789 100644
--- a/arch/ia64/include/asm/mca.h
+++ b/arch/ia64/include/asm/mca.h
@@ -145,6 +145,7 @@ extern void ia64_mca_ucmc_handler(struct pt_regs *, struct ia64_sal_os_state *);
145extern void ia64_init_handler(struct pt_regs *, 145extern void ia64_init_handler(struct pt_regs *,
146 struct switch_stack *, 146 struct switch_stack *,
147 struct ia64_sal_os_state *); 147 struct ia64_sal_os_state *);
148extern void ia64_os_init_on_kdump(void);
148extern void ia64_monarch_init_handler(void); 149extern void ia64_monarch_init_handler(void);
149extern void ia64_slave_init_handler(void); 150extern void ia64_slave_init_handler(void);
150extern void ia64_mca_cmc_vector_setup(void); 151extern void ia64_mca_cmc_vector_setup(void);
diff --git a/arch/ia64/kernel/machine_kexec.c b/arch/ia64/kernel/machine_kexec.c
index 0823de1f6ebe..571d66373e0a 100644
--- a/arch/ia64/kernel/machine_kexec.c
+++ b/arch/ia64/kernel/machine_kexec.c
@@ -24,6 +24,8 @@
24#include <asm/delay.h> 24#include <asm/delay.h>
25#include <asm/meminit.h> 25#include <asm/meminit.h>
26#include <asm/processor.h> 26#include <asm/processor.h>
27#include <asm/sal.h>
28#include <asm/mca.h>
27 29
28typedef NORET_TYPE void (*relocate_new_kernel_t)( 30typedef NORET_TYPE void (*relocate_new_kernel_t)(
29 unsigned long indirection_page, 31 unsigned long indirection_page,
@@ -85,11 +87,21 @@ static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)
85 void *pal_addr = efi_get_pal_addr(); 87 void *pal_addr = efi_get_pal_addr();
86 unsigned long code_addr = (unsigned long)page_address(image->control_code_page); 88 unsigned long code_addr = (unsigned long)page_address(image->control_code_page);
87 int ii; 89 int ii;
90 u64 fp, gp;
91 ia64_fptr_t *init_handler = (ia64_fptr_t *)ia64_os_init_on_kdump;
88 92
89 BUG_ON(!image); 93 BUG_ON(!image);
90 if (image->type == KEXEC_TYPE_CRASH) { 94 if (image->type == KEXEC_TYPE_CRASH) {
91 crash_save_this_cpu(); 95 crash_save_this_cpu();
92 current->thread.ksp = (__u64)info->sw - 16; 96 current->thread.ksp = (__u64)info->sw - 16;
97
98 /* Register noop init handler */
99 fp = ia64_tpa(init_handler->fp);
100 gp = ia64_tpa(ia64_getreg(_IA64_REG_GP));
101 ia64_sal_set_vectors(SAL_VECTOR_OS_INIT, fp, gp, 0, fp, gp, 0);
102 } else {
103 /* Unregister init handlers of current kernel */
104 ia64_sal_set_vectors(SAL_VECTOR_OS_INIT, 0, 0, 0, 0, 0, 0);
93 } 105 }
94 106
95 /* Interrupts aren't acceptable while we reboot */ 107 /* Interrupts aren't acceptable while we reboot */
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
index 8d2eabe3119f..7461d2573d41 100644
--- a/arch/ia64/kernel/mca_asm.S
+++ b/arch/ia64/kernel/mca_asm.S
@@ -40,6 +40,7 @@
40 40
41 .global ia64_do_tlb_purge 41 .global ia64_do_tlb_purge
42 .global ia64_os_mca_dispatch 42 .global ia64_os_mca_dispatch
43 .global ia64_os_init_on_kdump
43 .global ia64_os_init_dispatch_monarch 44 .global ia64_os_init_dispatch_monarch
44 .global ia64_os_init_dispatch_slave 45 .global ia64_os_init_dispatch_slave
45 46
@@ -299,6 +300,25 @@ END(ia64_os_mca_virtual_begin)
299//StartMain//////////////////////////////////////////////////////////////////// 300//StartMain////////////////////////////////////////////////////////////////////
300 301
301// 302//
303// NOP init handler for kdump. In panic situation, we may receive INIT
304// while kernel transition. Since we initialize registers on leave from
305// current kernel, no longer monarch/slave handlers of current kernel in
306// virtual mode are called safely.
307// We can unregister these init handlers from SAL, however then the INIT
308// will result in warmboot by SAL and we cannot retrieve the crashdump.
309// Therefore register this NOP function to SAL, to prevent entering virtual
310// mode and resulting warmboot by SAL.
311//
312ia64_os_init_on_kdump:
313 mov r8=r0 // IA64_INIT_RESUME
314 mov r9=r10 // SAL_GP
315 mov r22=r17 // *minstate
316 ;;
317 mov r10=r0 // return to same context
318 mov b0=r12 // SAL_CHECK return address
319 br b0
320
321//
302// SAL to OS entry point for INIT on all processors. This has been defined for 322// SAL to OS entry point for INIT on all processors. This has been defined for
303// registration purposes with SAL as a part of ia64_mca_init. Monarch and 323// registration purposes with SAL as a part of ia64_mca_init. Monarch and
304// slave INIT have identical processing, except for the value of the 324// slave INIT have identical processing, except for the value of the