|
@@ -56,15 +56,28 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
|
|
_TIF_MCCK_PENDING)
|
|
_TIF_MCCK_PENDING)
|
|
_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
|
|
_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
|
|
_TIF_SECCOMP>>8 | _TIF_SYSCALL_TRACEPOINT>>8)
|
|
_TIF_SECCOMP>>8 | _TIF_SYSCALL_TRACEPOINT>>8)
|
|
|
|
+_TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
|
|
|
|
|
|
#define BASED(name) name-system_call(%r13)
|
|
#define BASED(name) name-system_call(%r13)
|
|
|
|
|
|
|
|
+ .macro SPP newpp
|
|
|
|
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
|
|
|
|
+ tm __LC_MACHINE_FLAGS+6,0x20 # MACHINE_FLAG_SPP
|
|
|
|
+ jz .+8
|
|
|
|
+ .insn s,0xb2800000,\newpp
|
|
|
|
+#endif
|
|
|
|
+ .endm
|
|
|
|
+
|
|
.macro HANDLE_SIE_INTERCEPT
|
|
.macro HANDLE_SIE_INTERCEPT
|
|
#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
|
|
#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
|
|
- lg %r3,__LC_SIE_HOOK
|
|
|
|
- ltgr %r3,%r3
|
|
|
|
|
|
+ tm __TI_flags+6(%r12),_TIF_SIE>>8
|
|
jz 0f
|
|
jz 0f
|
|
- basr %r14,%r3
|
|
|
|
|
|
+ SPP __LC_CMF_HPP # set host id
|
|
|
|
+ clc SP_PSW+8(8,%r15),BASED(.Lsie_loop)
|
|
|
|
+ jl 0f
|
|
|
|
+ clc SP_PSW+8(8,%r15),BASED(.Lsie_done)
|
|
|
|
+ jhe 0f
|
|
|
|
+ mvc SP_PSW+8(8,%r15),BASED(.Lsie_loop)
|
|
0:
|
|
0:
|
|
#endif
|
|
#endif
|
|
.endm
|
|
.endm
|
|
@@ -465,6 +478,7 @@ pgm_check_handler:
|
|
xc SP_ILC(4,%r15),SP_ILC(%r15)
|
|
xc SP_ILC(4,%r15),SP_ILC(%r15)
|
|
mvc SP_PSW(16,%r15),__LC_PGM_OLD_PSW
|
|
mvc SP_PSW(16,%r15),__LC_PGM_OLD_PSW
|
|
lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
|
|
lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
|
|
|
|
+ HANDLE_SIE_INTERCEPT
|
|
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
|
|
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
|
|
jz pgm_no_vtime
|
|
jz pgm_no_vtime
|
|
UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
|
|
UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
|
|
@@ -472,7 +486,6 @@ pgm_check_handler:
|
|
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
|
|
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
|
|
LAST_BREAK
|
|
LAST_BREAK
|
|
pgm_no_vtime:
|
|
pgm_no_vtime:
|
|
- HANDLE_SIE_INTERCEPT
|
|
|
|
stg %r11,SP_ARGS(%r15)
|
|
stg %r11,SP_ARGS(%r15)
|
|
lgf %r3,__LC_PGM_ILC # load program interruption code
|
|
lgf %r3,__LC_PGM_ILC # load program interruption code
|
|
lg %r4,__LC_TRANS_EXC_CODE
|
|
lg %r4,__LC_TRANS_EXC_CODE
|
|
@@ -507,6 +520,7 @@ pgm_per_std:
|
|
CREATE_STACK_FRAME __LC_SAVE_AREA
|
|
CREATE_STACK_FRAME __LC_SAVE_AREA
|
|
mvc SP_PSW(16,%r15),__LC_PGM_OLD_PSW
|
|
mvc SP_PSW(16,%r15),__LC_PGM_OLD_PSW
|
|
lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
|
|
lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
|
|
|
|
+ HANDLE_SIE_INTERCEPT
|
|
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
|
|
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
|
|
jz pgm_no_vtime2
|
|
jz pgm_no_vtime2
|
|
UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
|
|
UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
|
|
@@ -514,7 +528,6 @@ pgm_per_std:
|
|
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
|
|
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
|
|
LAST_BREAK
|
|
LAST_BREAK
|
|
pgm_no_vtime2:
|
|
pgm_no_vtime2:
|
|
- HANDLE_SIE_INTERCEPT
|
|
|
|
lg %r1,__TI_task(%r12)
|
|
lg %r1,__TI_task(%r12)
|
|
tm SP_PSW+1(%r15),0x01 # kernel per event ?
|
|
tm SP_PSW+1(%r15),0x01 # kernel per event ?
|
|
jz kernel_per
|
|
jz kernel_per
|
|
@@ -579,6 +592,7 @@ io_int_handler:
|
|
CREATE_STACK_FRAME __LC_SAVE_AREA+40
|
|
CREATE_STACK_FRAME __LC_SAVE_AREA+40
|
|
mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack
|
|
mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack
|
|
lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
|
|
lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
|
|
|
|
+ HANDLE_SIE_INTERCEPT
|
|
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
|
|
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
|
|
jz io_no_vtime
|
|
jz io_no_vtime
|
|
UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
|
|
UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
|
|
@@ -586,7 +600,6 @@ io_int_handler:
|
|
mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
|
|
mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
|
|
LAST_BREAK
|
|
LAST_BREAK
|
|
io_no_vtime:
|
|
io_no_vtime:
|
|
- HANDLE_SIE_INTERCEPT
|
|
|
|
TRACE_IRQS_OFF
|
|
TRACE_IRQS_OFF
|
|
la %r2,SP_PTREGS(%r15) # address of register-save area
|
|
la %r2,SP_PTREGS(%r15) # address of register-save area
|
|
brasl %r14,do_IRQ # call standard irq handler
|
|
brasl %r14,do_IRQ # call standard irq handler
|
|
@@ -714,6 +727,7 @@ ext_int_handler:
|
|
CREATE_STACK_FRAME __LC_SAVE_AREA+40
|
|
CREATE_STACK_FRAME __LC_SAVE_AREA+40
|
|
mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack
|
|
mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack
|
|
lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
|
|
lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
|
|
|
|
+ HANDLE_SIE_INTERCEPT
|
|
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
|
|
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
|
|
jz ext_no_vtime
|
|
jz ext_no_vtime
|
|
UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
|
|
UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
|
|
@@ -721,7 +735,6 @@ ext_int_handler:
|
|
mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
|
|
mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
|
|
LAST_BREAK
|
|
LAST_BREAK
|
|
ext_no_vtime:
|
|
ext_no_vtime:
|
|
- HANDLE_SIE_INTERCEPT
|
|
|
|
TRACE_IRQS_OFF
|
|
TRACE_IRQS_OFF
|
|
lghi %r1,4096
|
|
lghi %r1,4096
|
|
la %r2,SP_PTREGS(%r15) # address of register-save area
|
|
la %r2,SP_PTREGS(%r15) # address of register-save area
|
|
@@ -785,6 +798,7 @@ mcck_int_main:
|
|
lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
|
|
lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
|
|
tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid?
|
|
tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid?
|
|
jno mcck_no_vtime # no -> no timer update
|
|
jno mcck_no_vtime # no -> no timer update
|
|
|
|
+ HANDLE_SIE_INTERCEPT
|
|
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
|
|
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
|
|
jz mcck_no_vtime
|
|
jz mcck_no_vtime
|
|
UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER
|
|
UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER
|
|
@@ -804,7 +818,6 @@ mcck_no_vtime:
|
|
stosm __SF_EMPTY(%r15),0x04 # turn dat on
|
|
stosm __SF_EMPTY(%r15),0x04 # turn dat on
|
|
tm __TI_flags+7(%r12),_TIF_MCCK_PENDING
|
|
tm __TI_flags+7(%r12),_TIF_MCCK_PENDING
|
|
jno mcck_return
|
|
jno mcck_return
|
|
- HANDLE_SIE_INTERCEPT
|
|
|
|
TRACE_IRQS_OFF
|
|
TRACE_IRQS_OFF
|
|
brasl %r14,s390_handle_mcck
|
|
brasl %r14,s390_handle_mcck
|
|
TRACE_IRQS_ON
|
|
TRACE_IRQS_ON
|
|
@@ -1036,6 +1049,57 @@ cleanup_io_restore_insn:
|
|
.Lcritical_end:
|
|
.Lcritical_end:
|
|
.quad __critical_end
|
|
.quad __critical_end
|
|
|
|
|
|
|
|
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
|
|
|
|
+/*
|
|
|
|
+ * sie64a calling convention:
|
|
|
|
+ * %r2 pointer to sie control block
|
|
|
|
+ * %r3 guest register save area
|
|
|
|
+ */
|
|
|
|
+ .globl sie64a
|
|
|
|
+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
|
|
|
|
+ lmg %r0,%r13,0(%r3) # load guest gprs 0-13
|
|
|
|
+ lg %r14,__LC_THREAD_INFO # pointer thread_info struct
|
|
|
|
+ oi __TI_flags+6(%r14),_TIF_SIE>>8
|
|
|
|
+sie_loop:
|
|
|
|
+ lg %r14,__LC_THREAD_INFO # pointer thread_info struct
|
|
|
|
+ tm __TI_flags+7(%r14),_TIF_EXIT_SIE
|
|
|
|
+ jnz sie_exit
|
|
|
|
+ lg %r14,__SF_EMPTY(%r15) # get control block pointer
|
|
|
|
+ SPP __SF_EMPTY(%r15) # set guest id
|
|
|
|
+ sie 0(%r14)
|
|
|
|
+sie_done:
|
|
|
|
+ SPP __LC_CMF_HPP # set host id
|
|
|
|
+ lg %r14,__LC_THREAD_INFO # pointer thread_info struct
|
|
|
|
+sie_exit:
|
|
|
|
+ ni __TI_flags+6(%r14),255-(_TIF_SIE>>8)
|
|
|
|
+ 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
|
|
|
|
+ br %r14
|
|
|
|
+sie_fault:
|
|
|
|
+ lg %r14,__LC_THREAD_INFO # pointer thread_info struct
|
|
|
|
+ ni __TI_flags+6(%r14),255-(_TIF_SIE>>8)
|
|
|
|
+ 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
|
|
|
|
+
|
|
|
|
+ .align 8
|
|
|
|
+.Lsie_loop:
|
|
|
|
+ .quad sie_loop
|
|
|
|
+.Lsie_done:
|
|
|
|
+ .quad sie_done
|
|
|
|
+
|
|
|
|
+ .section __ex_table,"a"
|
|
|
|
+ .quad sie_loop,sie_fault
|
|
|
|
+ .previous
|
|
|
|
+#endif
|
|
|
|
+
|
|
.section .rodata, "a"
|
|
.section .rodata, "a"
|
|
#define SYSCALL(esa,esame,emu) .long esame
|
|
#define SYSCALL(esa,esame,emu) .long esame
|
|
.globl sys_call_table
|
|
.globl sys_call_table
|