aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith Owens <kaos@sgi.com>2005-09-22 04:49:15 -0400
committerTony Luck <tony.luck@intel.com>2005-09-22 16:24:19 -0400
commit20bb86852a6b7d9ca8c48ff921ff3904038959cf (patch)
tree7db40dee86256b322a1036a6187db2e189e0bd0a
parent83a78d9ba792660418d692fd6737871aefdbff36 (diff)
[IA64] Wire in the MCA/INIT handler stacks
Wire the MCA/INIT handler stacks into DTR[2] and track them in IA64_KR(CURRENT_STACK). This gives the MCA/INIT handler stacks the same TLB status as normal kernel stacks. Reload the old CURRENT_STACK data on return from OS to SAL. Signed-off-by: Keith Owens <kaos@sgi.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
-rw-r--r--arch/ia64/kernel/mca_asm.S96
-rw-r--r--include/asm-ia64/mca.h5
2 files changed, 90 insertions, 11 deletions
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
index 499a065f4e60..db32fc1d3935 100644
--- a/arch/ia64/kernel/mca_asm.S
+++ b/arch/ia64/kernel/mca_asm.S
@@ -489,24 +489,27 @@ ia64_state_save:
489 ;; 489 ;;
490 st8 [temp1]=r17,16 // pal_min_state 490 st8 [temp1]=r17,16 // pal_min_state
491 st8 [temp2]=r6,16 // prev_IA64_KR_CURRENT 491 st8 [temp2]=r6,16 // prev_IA64_KR_CURRENT
492 mov r6=IA64_KR(CURRENT_STACK)
493 ;;
494 st8 [temp1]=r6,16 // prev_IA64_KR_CURRENT_STACK
495 st8 [temp2]=r0,16 // prev_task, starts off as NULL
492 mov r6=cr.ifa 496 mov r6=cr.ifa
493 ;; 497 ;;
494 st8 [temp1]=r0,16 // prev_task, starts off as NULL 498 st8 [temp1]=r12,16 // cr.isr
495 st8 [temp2]=r12,16 // cr.isr 499 st8 [temp2]=r6,16 // cr.ifa
496 mov r12=cr.itir 500 mov r12=cr.itir
497 ;; 501 ;;
498 st8 [temp1]=r6,16 // cr.ifa 502 st8 [temp1]=r12,16 // cr.itir
499 st8 [temp2]=r12,16 // cr.itir 503 st8 [temp2]=r11,16 // cr.iipa
500 mov r12=cr.iim 504 mov r12=cr.iim
501 ;; 505 ;;
502 st8 [temp1]=r11,16 // cr.iipa 506 st8 [temp1]=r12,16 // cr.iim
503 st8 [temp2]=r12,16 // cr.iim
504 mov r6=cr.iha
505(p1) mov r12=IA64_MCA_COLD_BOOT 507(p1) mov r12=IA64_MCA_COLD_BOOT
506(p2) mov r12=IA64_INIT_WARM_BOOT 508(p2) mov r12=IA64_INIT_WARM_BOOT
509 mov r6=cr.iha
507 ;; 510 ;;
508 st8 [temp1]=r6,16 // cr.iha 511 st8 [temp2]=r6,16 // cr.iha
509 st8 [temp2]=r12 // os_status, default is cold boot 512 st8 [temp1]=r12 // os_status, default is cold boot
510 mov r6=IA64_MCA_SAME_CONTEXT 513 mov r6=IA64_MCA_SAME_CONTEXT
511 ;; 514 ;;
512 st8 [temp1]=r6 // context, default is same context 515 st8 [temp1]=r6 // context, default is same context
@@ -823,9 +826,12 @@ ia64_state_restore:
823 ld8 r12=[temp1],16 // sal_ra 826 ld8 r12=[temp1],16 // sal_ra
824 ld8 r9=[temp2],16 // sal_gp 827 ld8 r9=[temp2],16 // sal_gp
825 ;; 828 ;;
826 ld8 r22=[temp1],24 // pal_min_state, virtual. skip prev_task 829 ld8 r22=[temp1],16 // pal_min_state, virtual
827 ld8 r21=[temp2],16 // prev_IA64_KR_CURRENT 830 ld8 r21=[temp2],16 // prev_IA64_KR_CURRENT
828 ;; 831 ;;
832 ld8 r16=[temp1],16 // prev_IA64_KR_CURRENT_STACK
833 ld8 r20=[temp2],16 // prev_task
834 ;;
829 ld8 temp3=[temp1],16 // cr.isr 835 ld8 temp3=[temp1],16 // cr.isr
830 ld8 temp4=[temp2],16 // cr.ifa 836 ld8 temp4=[temp2],16 // cr.ifa
831 ;; 837 ;;
@@ -846,6 +852,45 @@ ia64_state_restore:
846 ld8 r8=[temp1] // os_status 852 ld8 r8=[temp1] // os_status
847 ld8 r10=[temp2] // context 853 ld8 r10=[temp2] // context
848 854
855 /* Wire IA64_TR_CURRENT_STACK to the stack that we are resuming to. To
856 * avoid any dependencies on the algorithm in ia64_switch_to(), just
857 * purge any existing CURRENT_STACK mapping and insert the new one.
858 *
859 * r16 contains prev_IA64_KR_CURRENT_STACK, r21 contains
860 * prev_IA64_KR_CURRENT, these values may have been changed by the C
861 * code. Do not use r8, r9, r10, r22, they contain values ready for
862 * the return to SAL.
863 */
864
865 mov r15=IA64_KR(CURRENT_STACK) // physical granule mapped by IA64_TR_CURRENT_STACK
866 ;;
867 shl r15=r15,IA64_GRANULE_SHIFT
868 ;;
869 dep r15=-1,r15,61,3 // virtual granule
870 mov r18=IA64_GRANULE_SHIFT<<2 // for cr.itir.ps
871 ;;
872 ptr.d r15,r18
873 ;;
874 srlz.d
875
876 extr.u r19=r21,61,3 // r21 = prev_IA64_KR_CURRENT
877 shl r20=r16,IA64_GRANULE_SHIFT // r16 = prev_IA64_KR_CURRENT_STACK
878 movl r21=PAGE_KERNEL // page properties
879 ;;
880 mov IA64_KR(CURRENT_STACK)=r16
881 cmp.ne p6,p0=RGN_KERNEL,r19 // new stack is in the kernel region?
882 or r21=r20,r21 // construct PA | page properties
883(p6) br.spnt 1f // the dreaded cpu 0 idle task in region 5:(
884 ;;
885 mov cr.itir=r18
886 mov cr.ifa=r21
887 mov r20=IA64_TR_CURRENT_STACK
888 ;;
889 itr.d dtr[r20]=r21
890 ;;
891 srlz.d
8921:
893
849 br.sptk b0 894 br.sptk b0
850 895
851//EndStub////////////////////////////////////////////////////////////////////// 896//EndStub//////////////////////////////////////////////////////////////////////
@@ -982,6 +1027,7 @@ ia64_set_kernel_registers:
982 add temp4=temp4, temp1 // &struct ia64_sal_os_state.os_gp 1027 add temp4=temp4, temp1 // &struct ia64_sal_os_state.os_gp
983 add r12=temp1, temp3 // kernel stack pointer on MCA/INIT stack 1028 add r12=temp1, temp3 // kernel stack pointer on MCA/INIT stack
984 add r13=temp1, r3 // set current to start of MCA/INIT stack 1029 add r13=temp1, r3 // set current to start of MCA/INIT stack
1030 add r20=temp1, r3 // physical start of MCA/INIT stack
985 ;; 1031 ;;
986 ld8 r1=[temp4] // OS GP from SAL OS state 1032 ld8 r1=[temp4] // OS GP from SAL OS state
987 ;; 1033 ;;
@@ -991,7 +1037,35 @@ ia64_set_kernel_registers:
991 ;; 1037 ;;
992 mov IA64_KR(CURRENT)=r13 1038 mov IA64_KR(CURRENT)=r13
993 1039
994 // FIXME: do I need to wire IA64_KR_CURRENT_STACK and IA64_TR_CURRENT_STACK? 1040 /* Wire IA64_TR_CURRENT_STACK to the MCA/INIT handler stack. To avoid
1041 * any dependencies on the algorithm in ia64_switch_to(), just purge
1042 * any existing CURRENT_STACK mapping and insert the new one.
1043 */
1044
1045 mov r16=IA64_KR(CURRENT_STACK) // physical granule mapped by IA64_TR_CURRENT_STACK
1046 ;;
1047 shl r16=r16,IA64_GRANULE_SHIFT
1048 ;;
1049 dep r16=-1,r16,61,3 // virtual granule
1050 mov r18=IA64_GRANULE_SHIFT<<2 // for cr.itir.ps
1051 ;;
1052 ptr.d r16,r18
1053 ;;
1054 srlz.d
1055
1056 shr.u r16=r20,IA64_GRANULE_SHIFT // r20 = physical start of MCA/INIT stack
1057 movl r21=PAGE_KERNEL // page properties
1058 ;;
1059 mov IA64_KR(CURRENT_STACK)=r16
1060 or r21=r20,r21 // construct PA | page properties
1061 ;;
1062 mov cr.itir=r18
1063 mov cr.ifa=r13
1064 mov r20=IA64_TR_CURRENT_STACK
1065 ;;
1066 itr.d dtr[r20]=r21
1067 ;;
1068 srlz.d
995 1069
996 br.sptk b0 1070 br.sptk b0
997 1071
diff --git a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h
index 97a28b8b2ddd..c7d9c9ed38ba 100644
--- a/include/asm-ia64/mca.h
+++ b/include/asm-ia64/mca.h
@@ -80,7 +80,12 @@ struct ia64_sal_os_state {
80 u64 sal_ra; /* Return address in SAL, physical */ 80 u64 sal_ra; /* Return address in SAL, physical */
81 u64 sal_gp; /* GP of the SAL - physical */ 81 u64 sal_gp; /* GP of the SAL - physical */
82 pal_min_state_area_t *pal_min_state; /* from R17. physical in asm, virtual in C */ 82 pal_min_state_area_t *pal_min_state; /* from R17. physical in asm, virtual in C */
83 /* Previous values of IA64_KR(CURRENT) and IA64_KR(CURRENT_STACK).
84 * Note: if the MCA/INIT recovery code wants to resume to a new context
85 * then it must change these values to reflect the new kernel stack.
86 */
83 u64 prev_IA64_KR_CURRENT; /* previous value of IA64_KR(CURRENT) */ 87 u64 prev_IA64_KR_CURRENT; /* previous value of IA64_KR(CURRENT) */
88 u64 prev_IA64_KR_CURRENT_STACK;
84 struct task_struct *prev_task; /* previous task, NULL if it is not useful */ 89 struct task_struct *prev_task; /* previous task, NULL if it is not useful */
85 /* Some interrupt registers are not saved in minstate, pt_regs or 90 /* Some interrupt registers are not saved in minstate, pt_regs or
86 * switch_stack. Because MCA/INIT can occur when interrupts are 91 * switch_stack. Because MCA/INIT can occur when interrupts are