summaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/mca_asm.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/kernel/mca_asm.S')
-rw-r--r--arch/ia64/kernel/mca_asm.S176
1 files changed, 174 insertions, 2 deletions
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
index 3d49ac06e..81966bb99 100644
--- a/arch/ia64/kernel/mca_asm.S
+++ b/arch/ia64/kernel/mca_asm.S
@@ -1,7 +1,31 @@
+//
+// assembly portion of the IA64 MCA handling
+//
+// Mods by cfleck to integrate into kernel build
+// 00/03/15 davidm Added various stop bits to get a clean compile
+// 00/03/29 cfleck Added code to save INIT handoff state in pt_regs format, switch to temp kstack,
+// switch modes, jump to C INIT handler
+//
+#include <asm/offsets.h>
+#include <asm/pgtable.h>
#include <asm/processor.h>
-#include <asm/mcaasm.h>
-#include <asm/page.h>
+#include <asm/mca_asm.h>
#include <asm/mca.h>
+
+/*
+ * When we get an machine check, the kernel stack pointer is no longer
+ * valid, so we need to set a new stack pointer.
+ */
+#define MINSTATE_START_SAVE_MIN \
+(pKern) movl sp=ia64_init_stack+IA64_STK_OFFSET-IA64_PT_REGS_SIZE; \
+ ;;
+
+#define MINSTATE_END_SAVE_MIN \
+ or r12=r12,r14; /* make sp a kernel virtual address */ \
+ or r13=r13,r14; /* make `current' a kernel virtual address */ \
+ ;;
+
+#include "minstate.h"
.psr abi64
.psr lsb
@@ -54,7 +78,9 @@
100: (p) mov temp=ip; \
;; \
(p) adds temp=to_label-100b,temp;\
+ ;; \
(p) adds temp=adjust,temp; \
+ ;; \
(p) mov b1=temp ; \
(p) br b1
@@ -68,6 +94,7 @@
.global ia64_mca_stack
.global ia64_mca_stackframe
.global ia64_mca_bspstore
+ .global ia64_init_stack
.text
.align 16
@@ -341,6 +368,7 @@ cSaveARs:
mov r3=ar16 // ar.rsc
mov ar16=r0 // put RSE in enforced lazy mode
mov r5=ar17 // ar.bsp
+ ;;
mov r7=ar18;; // ar.bspstore
st8 [r2]=r3,3*8
st8 [r4]=r5,3*8
@@ -575,6 +603,7 @@ restore_ARs:
// mov ar16=r3 // ar.rsc
// mov ar17=r5 // ar.bsp is read only
mov ar16=r0 // make sure that RSE is in enforced lazy mode
+ ;;
mov ar18=r7;; // ar.bspstore
ld8 r9=[r2],8*13;;
@@ -619,3 +648,146 @@ end_os_mca_restore:
BRANCH(ia64_os_mca_done_restore, r2, p0, -0x20)
;;
//EndStub//////////////////////////////////////////////////////////////////////
+
+// ok, the issue here is that we need to save state information so
+// it can be useable by the kernel debugger and show regs routines.
+// In order to do this, our best bet is save the current state (plus
+// the state information obtain from the MIN_STATE_AREA) into a pt_regs
+// format. This way we can pass it on in a useable format.
+//
+
+//
+// SAL to OS entry point for INIT on the monarch processor
+// This has been defined for registration purposes with SAL
+// as a part of ia64_mca_init.
+//
+// When we get here, the follow registers have been
+// set by the SAL for our use
+//
+// 1. GR1 = OS INIT GP
+// 2. GR8 = PAL_PROC physical address
+// 3. GR9 = SAL_PROC physical address
+// 4. GR10 = SAL GP (physical)
+// 5. GR11 = Init Reason
+// 0 = Received INIT for event other than crash dump switch
+// 1 = Received wakeup at the end of an OS_MCA corrected machine check
+// 2 = Received INIT dude to CrashDump switch assertion
+//
+// 6. GR12 = Return address to location within SAL_INIT procedure
+
+
+ .text
+ .align 16
+.global ia64_monarch_init_handler
+.proc ia64_monarch_init_handler
+ia64_monarch_init_handler:
+
+#if defined(SAL_MPINIT_WORKAROUND)
+ //
+ // work around SAL bug that sends all processors to monarch entry
+ //
+ .global bootstrap_processor
+
+ movl r21=24
+ movl r20=16
+ mov r17=cr.lid
+ movl r18=bootstrap_processor
+ ;;
+ dep r18=0,r18,61,3 // convert bsp to physical address
+ ;;
+ shr r19=r17,r20
+ shr r22=r17,r21
+ ld4 r18=[r18] // get the BSP ID
+ ;;
+ and r19=0xf, r19
+ and r22=0xf, r22
+ ;;
+ shl r19=r19,8 // get them in the right order
+ ;;
+ or r22=r22,r19 // combine EID and LID
+ ;;
+ cmp.eq p6,p7=r22,r18 // Am I the BSP ?
+(p7) br.cond.spnt slave_init_spin_me
+ ;;
+#endif
+
+
+//
+// ok, the first thing we do is stash the information
+// the SAL passed to os
+//
+_tmp = r2
+ movl _tmp=ia64_sal_to_os_handoff_state
+ ;;
+ dep _tmp=0,_tmp, 61, 3 // get physical address
+ ;;
+ st8 [_tmp]=r1,0x08;;
+ st8 [_tmp]=r8,0x08;;
+ st8 [_tmp]=r9,0x08;;
+ st8 [_tmp]=r10,0x08;;
+ st8 [_tmp]=r11,0x08;;
+ st8 [_tmp]=r12,0x08;;
+
+// now we want to save information so we can dump registers
+ SAVE_MIN_WITH_COVER
+ ;;
+ mov r8=cr.ifa
+ mov r9=cr.isr
+ adds r3=8,r2 // set up second base pointer
+ ;;
+ SAVE_REST
+
+// ok, enough should be saved at this point to be dangerous, and supply
+// information for a dump
+// We need to switch to Virtual mode before hitting the C functions.
+//
+//
+//
+ movl r2=IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN
+ mov r3=psr // get the current psr, minimum enabled at this point
+ ;;
+ or r2=r2,r3
+ ;;
+ movl r3=IVirtual_Switch
+ ;;
+ mov cr.iip=r3 // short return to set the appropriate bits
+ mov cr.ipsr=r2 // need to do an rfi to set appropriate bits
+ ;;
+ rfi
+ ;;
+IVirtual_Switch:
+ //
+ // We should now be running virtual
+ //
+ // Lets call the C handler to get the rest of the state info
+ //
+ alloc r14=ar.pfs,0,0,1,0 // now it's safe (must be first in insn group!)
+ ;; //
+ adds out0=16,sp // out0 = pointer to pt_regs
+ ;;
+
+ br.call.sptk.few rp=ia64_init_handler
+ ;;
+
+return_from_init:
+ br.sptk return_from_init
+
+ .endp
+
+//
+// SAL to OS entry point for INIT on the slave processor
+// This has been defined for registration purposes with SAL
+// as a part of ia64_mca_init.
+//
+
+ .text
+ .align 16
+.global ia64_slave_init_handler
+.proc ia64_slave_init_handler
+ia64_slave_init_handler:
+
+
+slave_init_spin_me:
+ br.sptk slave_init_spin_me
+ ;;
+ .endp