Loading arch/ia64/kernel/ivt.S +42 −42 Original line number Diff line number Diff line Loading @@ -1076,48 +1076,6 @@ END(ia64_syscall_setup) DBG_FAULT(15) FAULT(15) /* * Squatting in this space ... * * This special case dispatcher for illegal operation faults allows preserved * registers to be modified through a callback function (asm only) that is handed * back from the fault handler in r8. Up to three arguments can be passed to the * callback function by returning an aggregate with the callback as its first * element, followed by the arguments. */ ENTRY(dispatch_illegal_op_fault) .prologue .body SAVE_MIN_WITH_COVER ssm psr.ic | PSR_DEFAULT_BITS ;; srlz.i // guarantee that interruption collection is on ;; (p15) ssm psr.i // restore psr.i adds r3=8,r2 // set up second base pointer for SAVE_REST ;; alloc r14=ar.pfs,0,0,1,0 // must be first in insn group mov out0=ar.ec ;; SAVE_REST PT_REGS_UNWIND_INFO(0) ;; br.call.sptk.many rp=ia64_illegal_op_fault .ret0: ;; alloc r14=ar.pfs,0,0,3,0 // must be first in insn group mov out0=r9 mov out1=r10 mov out2=r11 movl r15=ia64_leave_kernel ;; mov rp=r15 mov b6=r8 ;; cmp.ne p6,p0=0,r8 (p6) br.call.dpnt.many b6=b6 // call returns to ia64_leave_kernel br.sptk.many ia64_leave_kernel END(dispatch_illegal_op_fault) .org ia64_ivt+0x4000 ///////////////////////////////////////////////////////////////////////////////////////// // 0x4000 Entry 16 (size 64 bundles) Reserved Loading Loading @@ -1715,6 +1673,48 @@ END(ia32_interrupt) DBG_FAULT(67) FAULT(67) /* * Squatting in this space ... * * This special case dispatcher for illegal operation faults allows preserved * registers to be modified through a callback function (asm only) that is handed * back from the fault handler in r8. Up to three arguments can be passed to the * callback function by returning an aggregate with the callback as its first * element, followed by the arguments. */ ENTRY(dispatch_illegal_op_fault) .prologue .body SAVE_MIN_WITH_COVER ssm psr.ic | PSR_DEFAULT_BITS ;; srlz.i // guarantee that interruption collection is on ;; (p15) ssm psr.i // restore psr.i adds r3=8,r2 // set up second base pointer for SAVE_REST ;; alloc r14=ar.pfs,0,0,1,0 // must be first in insn group mov out0=ar.ec ;; SAVE_REST PT_REGS_UNWIND_INFO(0) ;; br.call.sptk.many rp=ia64_illegal_op_fault .ret0: ;; alloc r14=ar.pfs,0,0,3,0 // must be first in insn group mov out0=r9 mov out1=r10 mov out2=r11 movl r15=ia64_leave_kernel ;; mov rp=r15 mov b6=r8 ;; cmp.ne p6,p0=0,r8 (p6) br.call.dpnt.many b6=b6 // call returns to ia64_leave_kernel br.sptk.many ia64_leave_kernel END(dispatch_illegal_op_fault) #ifdef CONFIG_IA32_SUPPORT /* Loading arch/ia64/kernel/minstate.h +42 −4 Original line number Diff line number Diff line Loading @@ -15,6 +15,9 @@ #define ACCOUNT_SYS_ENTER #endif .section ".data.patch.rse", "a" .previous /* * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves * the minimum state necessary that allows us to turn psr.ic back Loading @@ -40,7 +43,7 @@ * Note that psr.ic is NOT turned on by this macro. This is so that * we can pass interruption state as arguments to a handler. */ #define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA) \ #define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA,WORKAROUND) \ mov r16=IA64_KR(CURRENT); /* M */ \ mov r27=ar.rsc; /* M */ \ mov r20=r1; /* A */ \ Loading Loading @@ -87,6 +90,7 @@ tbit.nz p15,p0=r29,IA64_PSR_I_BIT; \ mov r29=b0 \ ;; \ WORKAROUND; \ adds r16=PT(R8),r1; /* initialize first base pointer */ \ adds r17=PT(R9),r1; /* initialize second base pointer */ \ (pKStk) mov r18=r0; /* make sure r18 isn't NaT */ \ Loading Loading @@ -206,6 +210,40 @@ st8 [r25]=r10; /* ar.ssd */ \ ;; #define SAVE_MIN_WITH_COVER DO_SAVE_MIN(cover, mov r30=cr.ifs,) #define SAVE_MIN_WITH_COVER_R19 DO_SAVE_MIN(cover, mov r30=cr.ifs, mov r15=r19) #define SAVE_MIN DO_SAVE_MIN( , mov r30=r0, ) #define RSE_WORKAROUND \ (pUStk) extr.u r17=r18,3,6; \ (pUStk) sub r16=r18,r22; \ [1:](pKStk) br.cond.sptk.many 1f; \ .xdata4 ".data.patch.rse",1b-. \ ;; \ cmp.ge p6,p7 = 33,r17; \ ;; \ (p6) mov r17=0x310; \ (p7) mov r17=0x308; \ ;; \ cmp.leu p1,p0=r16,r17; \ (p1) br.cond.sptk.many 1f; \ dep.z r17=r26,0,62; \ movl r16=2f; \ ;; \ mov ar.pfs=r17; \ dep r27=r0,r27,16,14; \ mov b0=r16; \ ;; \ br.ret.sptk b0; \ ;; \ 2: \ mov ar.rsc=r0 \ ;; \ flushrs; \ ;; \ mov ar.bspstore=r22 \ ;; \ mov r18=ar.bsp; \ ;; \ 1: \ .pred.rel "mutex", pKStk, pUStk #define SAVE_MIN_WITH_COVER DO_SAVE_MIN(cover, mov r30=cr.ifs, , RSE_WORKAROUND) #define SAVE_MIN_WITH_COVER_R19 DO_SAVE_MIN(cover, mov r30=cr.ifs, mov r15=r19, RSE_WORKAROUND) #define SAVE_MIN DO_SAVE_MIN( , mov r30=r0, , ) arch/ia64/kernel/patch.c +23 −0 Original line number Diff line number Diff line Loading @@ -115,6 +115,29 @@ ia64_patch_vtop (unsigned long start, unsigned long end) ia64_srlz_i(); } /* * Disable the RSE workaround by turning the conditional branch * that we tagged in each place the workaround was used into an * unconditional branch. */ void __init ia64_patch_rse (unsigned long start, unsigned long end) { s32 *offp = (s32 *) start; u64 ip, *b; while (offp < (s32 *) end) { ip = (u64) offp + *offp; b = (u64 *)(ip & -16); b[1] &= ~0xf800000L; ia64_fc((void *) ip); ++offp; } ia64_sync_i(); ia64_srlz_i(); } void __init ia64_patch_mckinley_e9 (unsigned long start, unsigned long end) { Loading arch/ia64/kernel/setup.c +11 −0 Original line number Diff line number Diff line Loading @@ -560,6 +560,17 @@ setup_arch (char **cmdline_p) /* process SAL system table: */ ia64_sal_init(__va(efi.sal_systab)); #ifdef CONFIG_ITANIUM ia64_patch_rse((u64) __start___rse_patchlist, (u64) __end___rse_patchlist); #else { u64 num_phys_stacked; if (ia64_pal_rse_info(&num_phys_stacked, 0) == 0 && num_phys_stacked > 96) ia64_patch_rse((u64) __start___rse_patchlist, (u64) __end___rse_patchlist); } #endif #ifdef CONFIG_SMP cpu_physical_id(0) = hard_smp_processor_id(); #endif Loading arch/ia64/kernel/vmlinux.lds.S +7 −0 Original line number Diff line number Diff line Loading @@ -156,6 +156,13 @@ SECTIONS __end___vtop_patchlist = .; } .data.patch.rse : AT(ADDR(.data.patch.rse) - LOAD_OFFSET) { __start___rse_patchlist = .; *(.data.patch.rse) __end___rse_patchlist = .; } .data.patch.mckinley_e9 : AT(ADDR(.data.patch.mckinley_e9) - LOAD_OFFSET) { __start___mckinley_e9_bundles = .; Loading Loading
arch/ia64/kernel/ivt.S +42 −42 Original line number Diff line number Diff line Loading @@ -1076,48 +1076,6 @@ END(ia64_syscall_setup) DBG_FAULT(15) FAULT(15) /* * Squatting in this space ... * * This special case dispatcher for illegal operation faults allows preserved * registers to be modified through a callback function (asm only) that is handed * back from the fault handler in r8. Up to three arguments can be passed to the * callback function by returning an aggregate with the callback as its first * element, followed by the arguments. */ ENTRY(dispatch_illegal_op_fault) .prologue .body SAVE_MIN_WITH_COVER ssm psr.ic | PSR_DEFAULT_BITS ;; srlz.i // guarantee that interruption collection is on ;; (p15) ssm psr.i // restore psr.i adds r3=8,r2 // set up second base pointer for SAVE_REST ;; alloc r14=ar.pfs,0,0,1,0 // must be first in insn group mov out0=ar.ec ;; SAVE_REST PT_REGS_UNWIND_INFO(0) ;; br.call.sptk.many rp=ia64_illegal_op_fault .ret0: ;; alloc r14=ar.pfs,0,0,3,0 // must be first in insn group mov out0=r9 mov out1=r10 mov out2=r11 movl r15=ia64_leave_kernel ;; mov rp=r15 mov b6=r8 ;; cmp.ne p6,p0=0,r8 (p6) br.call.dpnt.many b6=b6 // call returns to ia64_leave_kernel br.sptk.many ia64_leave_kernel END(dispatch_illegal_op_fault) .org ia64_ivt+0x4000 ///////////////////////////////////////////////////////////////////////////////////////// // 0x4000 Entry 16 (size 64 bundles) Reserved Loading Loading @@ -1715,6 +1673,48 @@ END(ia32_interrupt) DBG_FAULT(67) FAULT(67) /* * Squatting in this space ... * * This special case dispatcher for illegal operation faults allows preserved * registers to be modified through a callback function (asm only) that is handed * back from the fault handler in r8. Up to three arguments can be passed to the * callback function by returning an aggregate with the callback as its first * element, followed by the arguments. */ ENTRY(dispatch_illegal_op_fault) .prologue .body SAVE_MIN_WITH_COVER ssm psr.ic | PSR_DEFAULT_BITS ;; srlz.i // guarantee that interruption collection is on ;; (p15) ssm psr.i // restore psr.i adds r3=8,r2 // set up second base pointer for SAVE_REST ;; alloc r14=ar.pfs,0,0,1,0 // must be first in insn group mov out0=ar.ec ;; SAVE_REST PT_REGS_UNWIND_INFO(0) ;; br.call.sptk.many rp=ia64_illegal_op_fault .ret0: ;; alloc r14=ar.pfs,0,0,3,0 // must be first in insn group mov out0=r9 mov out1=r10 mov out2=r11 movl r15=ia64_leave_kernel ;; mov rp=r15 mov b6=r8 ;; cmp.ne p6,p0=0,r8 (p6) br.call.dpnt.many b6=b6 // call returns to ia64_leave_kernel br.sptk.many ia64_leave_kernel END(dispatch_illegal_op_fault) #ifdef CONFIG_IA32_SUPPORT /* Loading
arch/ia64/kernel/minstate.h +42 −4 Original line number Diff line number Diff line Loading @@ -15,6 +15,9 @@ #define ACCOUNT_SYS_ENTER #endif .section ".data.patch.rse", "a" .previous /* * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves * the minimum state necessary that allows us to turn psr.ic back Loading @@ -40,7 +43,7 @@ * Note that psr.ic is NOT turned on by this macro. This is so that * we can pass interruption state as arguments to a handler. */ #define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA) \ #define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA,WORKAROUND) \ mov r16=IA64_KR(CURRENT); /* M */ \ mov r27=ar.rsc; /* M */ \ mov r20=r1; /* A */ \ Loading Loading @@ -87,6 +90,7 @@ tbit.nz p15,p0=r29,IA64_PSR_I_BIT; \ mov r29=b0 \ ;; \ WORKAROUND; \ adds r16=PT(R8),r1; /* initialize first base pointer */ \ adds r17=PT(R9),r1; /* initialize second base pointer */ \ (pKStk) mov r18=r0; /* make sure r18 isn't NaT */ \ Loading Loading @@ -206,6 +210,40 @@ st8 [r25]=r10; /* ar.ssd */ \ ;; #define SAVE_MIN_WITH_COVER DO_SAVE_MIN(cover, mov r30=cr.ifs,) #define SAVE_MIN_WITH_COVER_R19 DO_SAVE_MIN(cover, mov r30=cr.ifs, mov r15=r19) #define SAVE_MIN DO_SAVE_MIN( , mov r30=r0, ) #define RSE_WORKAROUND \ (pUStk) extr.u r17=r18,3,6; \ (pUStk) sub r16=r18,r22; \ [1:](pKStk) br.cond.sptk.many 1f; \ .xdata4 ".data.patch.rse",1b-. \ ;; \ cmp.ge p6,p7 = 33,r17; \ ;; \ (p6) mov r17=0x310; \ (p7) mov r17=0x308; \ ;; \ cmp.leu p1,p0=r16,r17; \ (p1) br.cond.sptk.many 1f; \ dep.z r17=r26,0,62; \ movl r16=2f; \ ;; \ mov ar.pfs=r17; \ dep r27=r0,r27,16,14; \ mov b0=r16; \ ;; \ br.ret.sptk b0; \ ;; \ 2: \ mov ar.rsc=r0 \ ;; \ flushrs; \ ;; \ mov ar.bspstore=r22 \ ;; \ mov r18=ar.bsp; \ ;; \ 1: \ .pred.rel "mutex", pKStk, pUStk #define SAVE_MIN_WITH_COVER DO_SAVE_MIN(cover, mov r30=cr.ifs, , RSE_WORKAROUND) #define SAVE_MIN_WITH_COVER_R19 DO_SAVE_MIN(cover, mov r30=cr.ifs, mov r15=r19, RSE_WORKAROUND) #define SAVE_MIN DO_SAVE_MIN( , mov r30=r0, , )
arch/ia64/kernel/patch.c +23 −0 Original line number Diff line number Diff line Loading @@ -115,6 +115,29 @@ ia64_patch_vtop (unsigned long start, unsigned long end) ia64_srlz_i(); } /* * Disable the RSE workaround by turning the conditional branch * that we tagged in each place the workaround was used into an * unconditional branch. */ void __init ia64_patch_rse (unsigned long start, unsigned long end) { s32 *offp = (s32 *) start; u64 ip, *b; while (offp < (s32 *) end) { ip = (u64) offp + *offp; b = (u64 *)(ip & -16); b[1] &= ~0xf800000L; ia64_fc((void *) ip); ++offp; } ia64_sync_i(); ia64_srlz_i(); } void __init ia64_patch_mckinley_e9 (unsigned long start, unsigned long end) { Loading
arch/ia64/kernel/setup.c +11 −0 Original line number Diff line number Diff line Loading @@ -560,6 +560,17 @@ setup_arch (char **cmdline_p) /* process SAL system table: */ ia64_sal_init(__va(efi.sal_systab)); #ifdef CONFIG_ITANIUM ia64_patch_rse((u64) __start___rse_patchlist, (u64) __end___rse_patchlist); #else { u64 num_phys_stacked; if (ia64_pal_rse_info(&num_phys_stacked, 0) == 0 && num_phys_stacked > 96) ia64_patch_rse((u64) __start___rse_patchlist, (u64) __end___rse_patchlist); } #endif #ifdef CONFIG_SMP cpu_physical_id(0) = hard_smp_processor_id(); #endif Loading
arch/ia64/kernel/vmlinux.lds.S +7 −0 Original line number Diff line number Diff line Loading @@ -156,6 +156,13 @@ SECTIONS __end___vtop_patchlist = .; } .data.patch.rse : AT(ADDR(.data.patch.rse) - LOAD_OFFSET) { __start___rse_patchlist = .; *(.data.patch.rse) __end___rse_patchlist = .; } .data.patch.mckinley_e9 : AT(ADDR(.data.patch.mckinley_e9) - LOAD_OFFSET) { __start___mckinley_e9_bundles = .; Loading