|
@@ -47,7 +47,6 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
|
|
|
_TIF_MCCK_PENDING)
|
|
|
_TIF_TRACE = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \
|
|
|
_TIF_SYSCALL_TRACEPOINT)
|
|
|
-_TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
|
|
|
|
|
|
#define BASED(name) name-system_call(%r13)
|
|
|
|
|
@@ -81,25 +80,27 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
|
|
|
#endif
|
|
|
.endm
|
|
|
|
|
|
- .macro HANDLE_SIE_INTERCEPT scratch,pgmcheck
|
|
|
+ .macro HANDLE_SIE_INTERCEPT scratch,reason
|
|
|
#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
|
|
|
tmhh %r8,0x0001 # interrupting from user ?
|
|
|
- jnz .+52
|
|
|
+ jnz .+62
|
|
|
lgr \scratch,%r9
|
|
|
- slg \scratch,BASED(.Lsie_loop)
|
|
|
- clg \scratch,BASED(.Lsie_length)
|
|
|
- .if \pgmcheck
|
|
|
+ slg \scratch,BASED(.Lsie_critical)
|
|
|
+ clg \scratch,BASED(.Lsie_critical_length)
|
|
|
+ .if \reason==1
|
|
|
# Some program interrupts are suppressing (e.g. protection).
|
|
|
# We must also check the instruction after SIE in that case.
|
|
|
# do_protection_exception will rewind to rewind_pad
|
|
|
- jh .+32
|
|
|
+ jh .+42
|
|
|
.else
|
|
|
- jhe .+32
|
|
|
+ jhe .+42
|
|
|
.endif
|
|
|
- lg %r9,BASED(.Lsie_loop)
|
|
|
- LPP BASED(.Lhost_id) # set host id
|
|
|
- lg %r14,__SF_EMPTY(%r15) # get control block pointer
|
|
|
+ lg %r14,__SF_EMPTY(%r15) # get control block pointer
|
|
|
+ LPP __SF_EMPTY+16(%r15) # set host id
|
|
|
ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE
|
|
|
+ lctlg %c1,%c1,__LC_USER_ASCE # load primary asce
|
|
|
+ larl %r9,sie_exit # skip forward to sie_exit
|
|
|
+ mvi __SF_EMPTY+31(%r15),\reason # set exit reason
|
|
|
#endif
|
|
|
.endm
|
|
|
|
|
@@ -452,7 +453,7 @@ ENTRY(io_int_handler)
|
|
|
lg %r12,__LC_THREAD_INFO
|
|
|
larl %r13,system_call
|
|
|
lmg %r8,%r9,__LC_IO_OLD_PSW
|
|
|
- HANDLE_SIE_INTERCEPT %r14,0
|
|
|
+ HANDLE_SIE_INTERCEPT %r14,2
|
|
|
SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT
|
|
|
tmhh %r8,0x0001 # interrupting from user?
|
|
|
jz io_skip
|
|
@@ -597,7 +598,7 @@ ENTRY(ext_int_handler)
|
|
|
lg %r12,__LC_THREAD_INFO
|
|
|
larl %r13,system_call
|
|
|
lmg %r8,%r9,__LC_EXT_OLD_PSW
|
|
|
- HANDLE_SIE_INTERCEPT %r14,0
|
|
|
+ HANDLE_SIE_INTERCEPT %r14,3
|
|
|
SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT
|
|
|
tmhh %r8,0x0001 # interrupting from user ?
|
|
|
jz ext_skip
|
|
@@ -645,7 +646,7 @@ ENTRY(mcck_int_handler)
|
|
|
lg %r12,__LC_THREAD_INFO
|
|
|
larl %r13,system_call
|
|
|
lmg %r8,%r9,__LC_MCK_OLD_PSW
|
|
|
- HANDLE_SIE_INTERCEPT %r14,0
|
|
|
+ HANDLE_SIE_INTERCEPT %r14,4
|
|
|
tm __LC_MCCK_CODE,0x80 # system damage?
|
|
|
jo mcck_panic # yes -> rest of mcck code invalid
|
|
|
lghi %r14,__LC_CPU_TIMER_SAVE_AREA
|
|
@@ -939,19 +940,8 @@ ENTRY(sie64a)
|
|
|
stmg %r6,%r14,__SF_GPRS(%r15) # save kernel registers
|
|
|
stg %r2,__SF_EMPTY(%r15) # save control block pointer
|
|
|
stg %r3,__SF_EMPTY+8(%r15) # save guest register save area
|
|
|
- xc __SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # host id == 0
|
|
|
+ xc __SF_EMPTY+16(16,%r15),__SF_EMPTY+16(%r15) # host id & reason
|
|
|
lmg %r0,%r13,0(%r3) # load guest gprs 0-13
|
|
|
-# some program checks are suppressing. C code (e.g. do_protection_exception)
|
|
|
-# will rewind the PSW by the ILC, which is 4 bytes in case of SIE. Other
|
|
|
-# instructions in the sie_loop should not cause program interrupts. So
|
|
|
-# lets use a nop (47 00 00 00) as a landing pad.
|
|
|
-# See also HANDLE_SIE_INTERCEPT
|
|
|
-rewind_pad:
|
|
|
- nop 0
|
|
|
-sie_loop:
|
|
|
- lg %r14,__LC_THREAD_INFO # pointer thread_info struct
|
|
|
- tm __TI_flags+7(%r14),_TIF_EXIT_SIE
|
|
|
- jnz sie_exit
|
|
|
lg %r14,__LC_GMAP # get gmap pointer
|
|
|
ltgr %r14,%r14
|
|
|
jz sie_gmap
|
|
@@ -966,33 +956,33 @@ sie_gmap:
|
|
|
sie_done:
|
|
|
LPP __SF_EMPTY+16(%r15) # set host id
|
|
|
ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE
|
|
|
- lg %r14,__LC_THREAD_INFO # pointer thread_info struct
|
|
|
-sie_exit:
|
|
|
lctlg %c1,%c1,__LC_USER_ASCE # load primary asce
|
|
|
+# some program checks are suppressing. C code (e.g. do_protection_exception)
|
|
|
+# will rewind the PSW by the ILC, which is 4 bytes in case of SIE. Other
|
|
|
+# instructions beween sie64a and sie_done should not cause program
|
|
|
+# interrupts. So lets use a nop (47 00 00 00) as a landing pad.
|
|
|
+# See also HANDLE_SIE_INTERCEPT
|
|
|
+rewind_pad:
|
|
|
+ nop 0
|
|
|
+sie_exit:
|
|
|
lg %r14,__SF_EMPTY+8(%r15) # load guest register save area
|
|
|
stmg %r0,%r13,0(%r14) # save guest gprs 0-13
|
|
|
lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
|
|
|
- lghi %r2,0
|
|
|
+ lg %r2,__SF_EMPTY+24(%r15) # return exit reason code
|
|
|
br %r14
|
|
|
sie_fault:
|
|
|
- lctlg %c1,%c1,__LC_USER_ASCE # load primary asce
|
|
|
- lg %r14,__LC_THREAD_INFO # pointer thread_info struct
|
|
|
- lg %r14,__SF_EMPTY+8(%r15) # load guest register save area
|
|
|
- stmg %r0,%r13,0(%r14) # save guest gprs 0-13
|
|
|
- lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
|
|
|
- lghi %r2,-EFAULT
|
|
|
- br %r14
|
|
|
+ lghi %r14,-EFAULT
|
|
|
+ stg %r14,__SF_EMPTY+24(%r15) # set exit reason code
|
|
|
+ j sie_exit
|
|
|
|
|
|
.align 8
|
|
|
-.Lsie_loop:
|
|
|
- .quad sie_loop
|
|
|
-.Lsie_length:
|
|
|
- .quad sie_done - sie_loop
|
|
|
-.Lhost_id:
|
|
|
- .quad 0
|
|
|
+.Lsie_critical:
|
|
|
+ .quad sie_gmap
|
|
|
+.Lsie_critical_length:
|
|
|
+ .quad sie_done - sie_gmap
|
|
|
|
|
|
EX_TABLE(rewind_pad,sie_fault)
|
|
|
- EX_TABLE(sie_loop,sie_fault)
|
|
|
+ EX_TABLE(sie_exit,sie_fault)
|
|
|
#endif
|
|
|
|
|
|
.section .rodata, "a"
|