0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/init.h>
0012 #include <linux/linkage.h>
0013 #include <asm/asm-extable.h>
0014 #include <asm/alternative-asm.h>
0015 #include <asm/processor.h>
0016 #include <asm/cache.h>
0017 #include <asm/dwarf.h>
0018 #include <asm/errno.h>
0019 #include <asm/ptrace.h>
0020 #include <asm/thread_info.h>
0021 #include <asm/asm-offsets.h>
0022 #include <asm/unistd.h>
0023 #include <asm/page.h>
0024 #include <asm/sigp.h>
0025 #include <asm/irq.h>
0026 #include <asm/vx-insn.h>
0027 #include <asm/setup.h>
0028 #include <asm/nmi.h>
0029 #include <asm/export.h>
0030 #include <asm/nospec-insn.h>
0031
0032 STACK_SHIFT = PAGE_SHIFT + THREAD_SIZE_ORDER
0033 STACK_SIZE = 1 << STACK_SHIFT
0034 STACK_INIT = STACK_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE
0035
0036 _LPP_OFFSET = __LC_LPP
0037
0038 .macro STBEAR address
0039 ALTERNATIVE "nop", ".insn s,0xb2010000,\address", 193
0040 .endm
0041
0042 .macro LBEAR address
0043 ALTERNATIVE "nop", ".insn s,0xb2000000,\address", 193
0044 .endm
0045
0046 .macro LPSWEY address,lpswe
0047 ALTERNATIVE "b \lpswe; nopr", ".insn siy,0xeb0000000071,\address,0", 193
0048 .endm
0049
0050 .macro MBEAR reg
0051 ALTERNATIVE "brcl 0,0", __stringify(mvc __PT_LAST_BREAK(8,\reg),__LC_LAST_BREAK), 193
0052 .endm
0053
0054 .macro CHECK_STACK savearea
0055 #ifdef CONFIG_CHECK_STACK
0056 tml %r15,STACK_SIZE - CONFIG_STACK_GUARD
0057 lghi %r14,\savearea
0058 jz stack_overflow
0059 #endif
0060 .endm
0061
0062 .macro CHECK_VMAP_STACK savearea,oklabel
0063 #ifdef CONFIG_VMAP_STACK
0064 lgr %r14,%r15
0065 nill %r14,0x10000 - STACK_SIZE
0066 oill %r14,STACK_INIT
0067 clg %r14,__LC_KERNEL_STACK
0068 je \oklabel
0069 clg %r14,__LC_ASYNC_STACK
0070 je \oklabel
0071 clg %r14,__LC_MCCK_STACK
0072 je \oklabel
0073 clg %r14,__LC_NODAT_STACK
0074 je \oklabel
0075 clg %r14,__LC_RESTART_STACK
0076 je \oklabel
0077 lghi %r14,\savearea
0078 j stack_overflow
0079 #else
0080 j \oklabel
0081 #endif
0082 .endm
0083
0084
0085
0086
0087
0088
0089
0090
0091 .macro TSTMSK addr, mask, size=8, bytepos=0
0092 .if (\bytepos < \size) && (\mask >> 8)
0093 .if (\mask & 0xff)
0094 .error "Mask exceeds byte boundary"
0095 .endif
0096 TSTMSK \addr, "(\mask >> 8)", \size, "(\bytepos + 1)"
0097 .exitm
0098 .endif
0099 .ifeq \mask
0100 .error "Mask must not be zero"
0101 .endif
0102 off = \size - \bytepos - 1
0103 tm off+\addr, \mask
0104 .endm
0105
0106 .macro BPOFF
0107 ALTERNATIVE "nop", ".insn rrf,0xb2e80000,0,0,12,0", 82
0108 .endm
0109
0110 .macro BPON
0111 ALTERNATIVE "nop", ".insn rrf,0xb2e80000,0,0,13,0", 82
0112 .endm
0113
0114 .macro BPENTER tif_ptr,tif_mask
0115 ALTERNATIVE "TSTMSK \tif_ptr,\tif_mask; jz .+8; .insn rrf,0xb2e80000,0,0,13,0", \
0116 "j .+12; nop; nop", 82
0117 .endm
0118
0119 .macro BPEXIT tif_ptr,tif_mask
0120 TSTMSK \tif_ptr,\tif_mask
0121 ALTERNATIVE "jz .+8; .insn rrf,0xb2e80000,0,0,12,0", \
0122 "jnz .+8; .insn rrf,0xb2e80000,0,0,13,0", 82
0123 .endm
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133 .macro CHKSTG errlabel
0134 TSTMSK __LC_MCCK_CODE,(MCCK_CODE_STG_ERROR|MCCK_CODE_STG_KEY_ERROR)
0135 jnz \errlabel
0136 TSTMSK __LC_MCCK_CODE,MCCK_CODE_STG_DEGRAD
0137 jz .Loklabel\@
0138 TSTMSK __LC_MCCK_CODE,MCCK_CODE_STG_FAIL_ADDR
0139 jnz \errlabel
0140 .Loklabel\@:
0141 .endm
0142
0143 #if IS_ENABLED(CONFIG_KVM)
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154 .macro OUTSIDE reg,start,end,outside_label
0155 lgr %r14,\reg
0156 larl %r13,\start
0157 slgr %r14,%r13
0158 #ifdef CONFIG_AS_IS_LLVM
0159 clgfrl %r14,.Lrange_size\@
0160 #else
0161 clgfi %r14,\end - \start
0162 #endif
0163 jhe \outside_label
0164 #ifdef CONFIG_AS_IS_LLVM
0165 .section .rodata, "a"
0166 .align 4
0167 .Lrange_size\@:
0168 .long \end - \start
0169 .previous
0170 #endif
0171 .endm
0172
0173 .macro SIEEXIT
0174 lg %r9,__SF_SIE_CONTROL(%r15) # get control block pointer
0175 ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE
0176 lctlg %c1,%c1,__LC_KERNEL_ASCE # load primary asce
0177 larl %r9,sie_exit # skip forward to sie_exit
0178 .endm
0179 #endif
0180
0181 GEN_BR_THUNK %r14
0182
0183 .section .kprobes.text, "ax"
0184 .Ldummy:
0185
0186
0187
0188
0189
0190
0191
0192
0193 nop 0
0194
0195 ENTRY(__bpon)
0196 .globl __bpon
0197 BPON
0198 BR_EX %r14
0199 ENDPROC(__bpon)
0200
0201
0202
0203
0204
0205
0206
0207
0208 ENTRY(__switch_to)
0209 stmg %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task
0210 lghi %r4,__TASK_stack
0211 lghi %r1,__TASK_thread
0212 llill %r5,STACK_INIT
0213 stg %r15,__THREAD_ksp(%r1,%r2) # store kernel stack of prev
0214 lg %r15,0(%r4,%r3) # start of kernel stack of next
0215 agr %r15,%r5 # end of kernel stack of next
0216 stg %r3,__LC_CURRENT # store task struct of next
0217 stg %r15,__LC_KERNEL_STACK # store end of kernel stack
0218 lg %r15,__THREAD_ksp(%r1,%r3) # load kernel stack of next
0219 aghi %r3,__TASK_pid
0220 mvc __LC_CURRENT_PID(4,%r0),0(%r3) # store pid of next
0221 lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task
0222 ALTERNATIVE "nop", "lpp _LPP_OFFSET", 40
0223 BR_EX %r14
0224 ENDPROC(__switch_to)
0225
0226 #if IS_ENABLED(CONFIG_KVM)
0227
0228
0229
0230
0231
0232 ENTRY(sie64a)
0233 stmg %r6,%r14,__SF_GPRS(%r15) # save kernel registers
0234 lg %r12,__LC_CURRENT
0235 stg %r2,__SF_SIE_CONTROL(%r15) # save control block pointer
0236 stg %r3,__SF_SIE_SAVEAREA(%r15) # save guest register save area
0237 xc __SF_SIE_REASON(8,%r15),__SF_SIE_REASON(%r15) # reason code = 0
0238 mvc __SF_SIE_FLAGS(8,%r15),__TI_flags(%r12) # copy thread flags
0239 lmg %r0,%r13,0(%r3) # load guest gprs 0-13
0240 lg %r14,__LC_GMAP # get gmap pointer
0241 ltgr %r14,%r14
0242 jz .Lsie_gmap
0243 lctlg %c1,%c1,__GMAP_ASCE(%r14) # load primary asce
0244 .Lsie_gmap:
0245 lg %r14,__SF_SIE_CONTROL(%r15) # get control block pointer
0246 oi __SIE_PROG0C+3(%r14),1 # we are going into SIE now
0247 tm __SIE_PROG20+3(%r14),3 # last exit...
0248 jnz .Lsie_skip
0249 TSTMSK __LC_CPU_FLAGS,_CIF_FPU
0250 jo .Lsie_skip # exit if fp/vx regs changed
0251 BPEXIT __SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
0252 .Lsie_entry:
0253 sie 0(%r14)
0254 # Let the next instruction be NOP to avoid triggering a machine check
0255 # and handling it in a guest as result of the instruction execution.
0256 nopr 7
0257 .Lsie_leave:
0258 BPOFF
0259 BPENTER __SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
0260 .Lsie_skip:
0261 ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE
0262 lctlg %c1,%c1,__LC_KERNEL_ASCE # load primary asce
0263 .Lsie_done:
0264 # some program checks are suppressing. C code (e.g. do_protection_exception)
0265 # will rewind the PSW by the ILC, which is often 4 bytes in case of SIE. There
0266 # are some corner cases (e.g. runtime instrumentation) where ILC is unpredictable.
0267 # Other instructions between sie64a and .Lsie_done should not cause program
0268 # interrupts. So lets use 3 nops as a landing pad for all possible rewinds.
0269 .Lrewind_pad6:
0270 nopr 7
0271 .Lrewind_pad4:
0272 nopr 7
0273 .Lrewind_pad2:
0274 nopr 7
0275 .globl sie_exit
0276 sie_exit:
0277 lg %r14,__SF_SIE_SAVEAREA(%r15) # load guest register save area
0278 stmg %r0,%r13,0(%r14) # save guest gprs 0-13
0279 xgr %r0,%r0 # clear guest registers to
0280 xgr %r1,%r1 # prevent speculative use
0281 xgr %r3,%r3
0282 xgr %r4,%r4
0283 xgr %r5,%r5
0284 lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
0285 lg %r2,__SF_SIE_REASON(%r15) # return exit reason code
0286 BR_EX %r14
0287 .Lsie_fault:
0288 lghi %r14,-EFAULT
0289 stg %r14,__SF_SIE_REASON(%r15) # set exit reason code
0290 j sie_exit
0291
0292 EX_TABLE(.Lrewind_pad6,.Lsie_fault)
0293 EX_TABLE(.Lrewind_pad4,.Lsie_fault)
0294 EX_TABLE(.Lrewind_pad2,.Lsie_fault)
0295 EX_TABLE(sie_exit,.Lsie_fault)
0296 ENDPROC(sie64a)
0297 EXPORT_SYMBOL(sie64a)
0298 EXPORT_SYMBOL(sie_exit)
0299 #endif
0300
0301
0302
0303
0304
0305
0306 ENTRY(system_call)
0307 stpt __LC_SYS_ENTER_TIMER
0308 stmg %r8,%r15,__LC_SAVE_AREA_SYNC
0309 BPOFF
0310 lghi %r14,0
0311 .Lsysc_per:
0312 STBEAR __LC_LAST_BREAK
0313 lctlg %c1,%c1,__LC_KERNEL_ASCE
0314 lg %r12,__LC_CURRENT
0315 lg %r15,__LC_KERNEL_STACK
0316 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
0317 stmg %r0,%r7,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
0318 BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
0319 # clear user controlled register to prevent speculative use
0320 xgr %r0,%r0
0321 xgr %r1,%r1
0322 xgr %r4,%r4
0323 xgr %r5,%r5
0324 xgr %r6,%r6
0325 xgr %r7,%r7
0326 xgr %r8,%r8
0327 xgr %r9,%r9
0328 xgr %r10,%r10
0329 xgr %r11,%r11
0330 la %r2,STACK_FRAME_OVERHEAD(%r15) # pointer to pt_regs
0331 mvc __PT_R8(64,%r2),__LC_SAVE_AREA_SYNC
0332 MBEAR %r2
0333 lgr %r3,%r14
0334 brasl %r14,__do_syscall
0335 lctlg %c1,%c1,__LC_USER_ASCE
0336 mvc __LC_RETURN_PSW(16),STACK_FRAME_OVERHEAD+__PT_PSW(%r15)
0337 BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP
0338 LBEAR STACK_FRAME_OVERHEAD+__PT_LAST_BREAK(%r15)
0339 lmg %r0,%r15,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
0340 stpt __LC_EXIT_TIMER
0341 LPSWEY __LC_RETURN_PSW,__LC_RETURN_LPSWE
0342 ENDPROC(system_call)
0343
0344 #
0345 # a new process exits the kernel with ret_from_fork
0346 #
0347 ENTRY(ret_from_fork)
0348 lgr %r3,%r11
0349 brasl %r14,__ret_from_fork
0350 lctlg %c1,%c1,__LC_USER_ASCE
0351 mvc __LC_RETURN_PSW(16),STACK_FRAME_OVERHEAD+__PT_PSW(%r15)
0352 BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP
0353 LBEAR STACK_FRAME_OVERHEAD+__PT_LAST_BREAK(%r15)
0354 lmg %r0,%r15,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
0355 stpt __LC_EXIT_TIMER
0356 LPSWEY __LC_RETURN_PSW,__LC_RETURN_LPSWE
0357 ENDPROC(ret_from_fork)
0358
0359
0360
0361
0362
0363 ENTRY(pgm_check_handler)
0364 stpt __LC_SYS_ENTER_TIMER
0365 BPOFF
0366 stmg %r8,%r15,__LC_SAVE_AREA_SYNC
0367 lg %r12,__LC_CURRENT
0368 lghi %r10,0
0369 lmg %r8,%r9,__LC_PGM_OLD_PSW
0370 tmhh %r8,0x0001 # coming from user space?
0371 jno .Lpgm_skip_asce
0372 lctlg %c1,%c1,__LC_KERNEL_ASCE
0373 j 3f # -> fault in user space
0374 .Lpgm_skip_asce:
0375 #if IS_ENABLED(CONFIG_KVM)
0376 # cleanup critical section for program checks in sie64a
0377 OUTSIDE %r9,.Lsie_gmap,.Lsie_done,1f
0378 SIEEXIT
0379 lghi %r10,_PIF_GUEST_FAULT
0380 #endif
0381 1: tmhh %r8,0x4000 # PER bit set in old PSW ?
0382 jnz 2f # -> enabled, can't be a double fault
0383 tm __LC_PGM_ILC+3,0x80 # check for per exception
0384 jnz .Lpgm_svcper # -> single stepped svc
0385 2: CHECK_STACK __LC_SAVE_AREA_SYNC
0386 aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
0387 # CHECK_VMAP_STACK branches to stack_overflow or 4f
0388 CHECK_VMAP_STACK __LC_SAVE_AREA_SYNC,4f
0389 3: BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
0390 lg %r15,__LC_KERNEL_STACK
0391 4: la %r11,STACK_FRAME_OVERHEAD(%r15)
0392 stg %r10,__PT_FLAGS(%r11)
0393 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
0394 stmg %r0,%r7,__PT_R0(%r11)
0395 mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC
0396 mvc __PT_LAST_BREAK(8,%r11),__LC_PGM_LAST_BREAK
0397 stmg %r8,%r9,__PT_PSW(%r11)
0398
0399 # clear user controlled registers to prevent speculative use
0400 xgr %r0,%r0
0401 xgr %r1,%r1
0402 xgr %r3,%r3
0403 xgr %r4,%r4
0404 xgr %r5,%r5
0405 xgr %r6,%r6
0406 xgr %r7,%r7
0407 lgr %r2,%r11
0408 brasl %r14,__do_pgm_check
0409 tmhh %r8,0x0001 # returning to user space?
0410 jno .Lpgm_exit_kernel
0411 lctlg %c1,%c1,__LC_USER_ASCE
0412 BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP
0413 stpt __LC_EXIT_TIMER
0414 .Lpgm_exit_kernel:
0415 mvc __LC_RETURN_PSW(16),STACK_FRAME_OVERHEAD+__PT_PSW(%r15)
0416 LBEAR STACK_FRAME_OVERHEAD+__PT_LAST_BREAK(%r15)
0417 lmg %r0,%r15,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
0418 LPSWEY __LC_RETURN_PSW,__LC_RETURN_LPSWE
0419
0420 #
0421 # single stepped system call
0422 #
0423 .Lpgm_svcper:
0424 mvc __LC_RETURN_PSW(8),__LC_SVC_NEW_PSW
0425 larl %r14,.Lsysc_per
0426 stg %r14,__LC_RETURN_PSW+8
0427 lghi %r14,1
0428 LBEAR __LC_PGM_LAST_BREAK
0429 LPSWEY __LC_RETURN_PSW,__LC_RETURN_LPSWE # branch to .Lsysc_per
0430 ENDPROC(pgm_check_handler)
0431
0432
0433
0434
0435 .macro INT_HANDLER name,lc_old_psw,handler
0436 ENTRY(\name)
0437 stckf __LC_INT_CLOCK
0438 stpt __LC_SYS_ENTER_TIMER
0439 STBEAR __LC_LAST_BREAK
0440 BPOFF
0441 stmg %r8,%r15,__LC_SAVE_AREA_ASYNC
0442 lg %r12,__LC_CURRENT
0443 lmg %r8,%r9,\lc_old_psw
0444 tmhh %r8,0x0001 # interrupting from user ?
0445 jnz 1f
0446 #if IS_ENABLED(CONFIG_KVM)
0447 OUTSIDE %r9,.Lsie_gmap,.Lsie_done,0f
0448 BPENTER __SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
0449 SIEEXIT
0450 #endif
0451 0: CHECK_STACK __LC_SAVE_AREA_ASYNC
0452 aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
0453 j 2f
0454 1: BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
0455 lctlg %c1,%c1,__LC_KERNEL_ASCE
0456 lg %r15,__LC_KERNEL_STACK
0457 2: xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
0458 la %r11,STACK_FRAME_OVERHEAD(%r15)
0459 stmg %r0,%r7,__PT_R0(%r11)
0460 # clear user controlled registers to prevent speculative use
0461 xgr %r0,%r0
0462 xgr %r1,%r1
0463 xgr %r3,%r3
0464 xgr %r4,%r4
0465 xgr %r5,%r5
0466 xgr %r6,%r6
0467 xgr %r7,%r7
0468 xgr %r10,%r10
0469 xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11)
0470 mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC
0471 MBEAR %r11
0472 stmg %r8,%r9,__PT_PSW(%r11)
0473 lgr %r2,%r11 # pass pointer to pt_regs
0474 brasl %r14,\handler
0475 mvc __LC_RETURN_PSW(16),__PT_PSW(%r11)
0476 tmhh %r8,0x0001 # returning to user ?
0477 jno 2f
0478 lctlg %c1,%c1,__LC_USER_ASCE
0479 BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP
0480 stpt __LC_EXIT_TIMER
0481 2: LBEAR __PT_LAST_BREAK(%r11)
0482 lmg %r0,%r15,__PT_R0(%r11)
0483 LPSWEY __LC_RETURN_PSW,__LC_RETURN_LPSWE
0484 ENDPROC(\name)
0485 .endm
0486
0487 INT_HANDLER ext_int_handler,__LC_EXT_OLD_PSW,do_ext_irq
0488 INT_HANDLER io_int_handler,__LC_IO_OLD_PSW,do_io_irq
0489
0490
0491
0492
0493 ENTRY(psw_idle)
0494 stg %r14,(__SF_GPRS+8*8)(%r15)
0495 stg %r3,__SF_EMPTY(%r15)
0496 larl %r1,psw_idle_exit
0497 stg %r1,__SF_EMPTY+8(%r15)
0498 larl %r1,smp_cpu_mtid
0499 llgf %r1,0(%r1)
0500 ltgr %r1,%r1
0501 jz .Lpsw_idle_stcctm
0502 .insn rsy,0xeb0000000017,%r1,5,__MT_CYCLES_ENTER(%r2)
0503 .Lpsw_idle_stcctm:
0504 oi __LC_CPU_FLAGS+7,_CIF_ENABLED_WAIT
0505 BPON
0506 stckf __CLOCK_IDLE_ENTER(%r2)
0507 stpt __TIMER_IDLE_ENTER(%r2)
0508 lpswe __SF_EMPTY(%r15)
0509 .globl psw_idle_exit
0510 psw_idle_exit:
0511 BR_EX %r14
0512 ENDPROC(psw_idle)
0513
0514
0515
0516
0517 ENTRY(mcck_int_handler)
0518 stckf __LC_MCCK_CLOCK
0519 BPOFF
0520 la %r1,4095 # validate r1
0521 spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # validate cpu timer
0522 LBEAR __LC_LAST_BREAK_SAVE_AREA-4095(%r1) # validate bear
0523 lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# validate gprs
0524 lg %r12,__LC_CURRENT
0525 lmg %r8,%r9,__LC_MCK_OLD_PSW
0526 TSTMSK __LC_MCCK_CODE,MCCK_CODE_SYSTEM_DAMAGE
0527 jo .Lmcck_panic # yes -> rest of mcck code invalid
0528 TSTMSK __LC_MCCK_CODE,MCCK_CODE_CR_VALID
0529 jno .Lmcck_panic # control registers invalid -> panic
0530 la %r14,4095
0531 lctlg %c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r14) # validate ctl regs
0532 ptlb
0533 lghi %r14,__LC_CPU_TIMER_SAVE_AREA
0534 mvc __LC_MCCK_ENTER_TIMER(8),0(%r14)
0535 TSTMSK __LC_MCCK_CODE,MCCK_CODE_CPU_TIMER_VALID
0536 jo 3f
0537 la %r14,__LC_SYS_ENTER_TIMER
0538 clc 0(8,%r14),__LC_EXIT_TIMER
0539 jl 1f
0540 la %r14,__LC_EXIT_TIMER
0541 1: clc 0(8,%r14),__LC_LAST_UPDATE_TIMER
0542 jl 2f
0543 la %r14,__LC_LAST_UPDATE_TIMER
0544 2: spt 0(%r14)
0545 mvc __LC_MCCK_ENTER_TIMER(8),0(%r14)
0546 3: TSTMSK __LC_MCCK_CODE,MCCK_CODE_PSW_MWP_VALID
0547 jno .Lmcck_panic
0548 tmhh %r8,0x0001 # interrupting from user ?
0549 jnz 6f
0550 TSTMSK __LC_MCCK_CODE,MCCK_CODE_PSW_IA_VALID
0551 jno .Lmcck_panic
0552 #if IS_ENABLED(CONFIG_KVM)
0553 OUTSIDE %r9,.Lsie_gmap,.Lsie_done,6f
0554 OUTSIDE %r9,.Lsie_entry,.Lsie_leave,4f
0555 oi __LC_CPU_FLAGS+7, _CIF_MCCK_GUEST
0556 j 5f
0557 4: CHKSTG .Lmcck_panic
0558 5: larl %r14,.Lstosm_tmp
0559 stosm 0(%r14),0x04 # turn dat on, keep irqs off
0560 BPENTER __SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
0561 SIEEXIT
0562 j .Lmcck_stack
0563 #endif
0564 6: CHKSTG .Lmcck_panic
0565 larl %r14,.Lstosm_tmp
0566 stosm 0(%r14),0x04 # turn dat on, keep irqs off
0567 tmhh %r8,0x0001 # interrupting from user ?
0568 jz .Lmcck_stack
0569 BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
0570 .Lmcck_stack:
0571 lg %r15,__LC_MCCK_STACK
0572 la %r11,STACK_FRAME_OVERHEAD(%r15)
0573 stctg %c1,%c1,__PT_CR1(%r11)
0574 lctlg %c1,%c1,__LC_KERNEL_ASCE
0575 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
0576 lghi %r14,__LC_GPREGS_SAVE_AREA+64
0577 stmg %r0,%r7,__PT_R0(%r11)
0578 # clear user controlled registers to prevent speculative use
0579 xgr %r0,%r0
0580 xgr %r1,%r1
0581 xgr %r3,%r3
0582 xgr %r4,%r4
0583 xgr %r5,%r5
0584 xgr %r6,%r6
0585 xgr %r7,%r7
0586 xgr %r10,%r10
0587 mvc __PT_R8(64,%r11),0(%r14)
0588 stmg %r8,%r9,__PT_PSW(%r11)
0589 xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11)
0590 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
0591 lgr %r2,%r11 # pass pointer to pt_regs
0592 brasl %r14,s390_do_machine_check
0593 cghi %r2,0
0594 je .Lmcck_return
0595 lg %r1,__LC_KERNEL_STACK # switch to kernel stack
0596 mvc STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11)
0597 xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1)
0598 la %r11,STACK_FRAME_OVERHEAD(%r1)
0599 lgr %r2,%r11
0600 lgr %r15,%r1
0601 brasl %r14,s390_handle_mcck
0602 .Lmcck_return:
0603 lctlg %c1,%c1,__PT_CR1(%r11)
0604 lmg %r0,%r10,__PT_R0(%r11)
0605 mvc __LC_RETURN_MCCK_PSW(16),__PT_PSW(%r11) # move return PSW
0606 tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ?
0607 jno 0f
0608 BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP
0609 stpt __LC_EXIT_TIMER
0610 0: ALTERNATIVE "nop", __stringify(lghi %r12,__LC_LAST_BREAK_SAVE_AREA),193
0611 LBEAR 0(%r12)
0612 lmg %r11,%r15,__PT_R11(%r11)
0613 LPSWEY __LC_RETURN_MCCK_PSW,__LC_RETURN_MCCK_LPSWE
0614
0615 .Lmcck_panic:
0616
0617
0618
0619
0620
0621
0622 lhi %r5,0
0623 lhi %r6,1
0624 larl %r7,.Lstop_lock
0625 cs %r5,%r6,0(%r7) # single CPU-stopper only
0626 jnz 4f
0627 larl %r7,.Lthis_cpu
0628 stap 0(%r7) # this CPU address
0629 lh %r4,0(%r7)
0630 nilh %r4,0
0631 lhi %r0,1
0632 sll %r0,16 # CPU counter
0633 lhi %r3,0 # next CPU address
0634 0: cr %r3,%r4
0635 je 2f
0636 1: sigp %r1,%r3,SIGP_STOP # stop next CPU
0637 brc SIGP_CC_BUSY,1b
0638 2: ahi %r3,1
0639 brct %r0,0b
0640 3: sigp %r1,%r4,SIGP_STOP # stop this CPU
0641 brc SIGP_CC_BUSY,3b
0642 4: j 4b
0643 ENDPROC(mcck_int_handler)
0644
0645 ENTRY(restart_int_handler)
0646 ALTERNATIVE "nop", "lpp _LPP_OFFSET", 40
0647 stg %r15,__LC_SAVE_AREA_RESTART
0648 TSTMSK __LC_RESTART_FLAGS,RESTART_FLAG_CTLREGS,4
0649 jz 0f
0650 la %r15,4095
0651 lctlg %c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r15)
0652 0: larl %r15,.Lstosm_tmp
0653 stosm 0(%r15),0x04 # turn dat on, keep irqs off
0654 lg %r15,__LC_RESTART_STACK
0655 xc STACK_FRAME_OVERHEAD(__PT_SIZE,%r15),STACK_FRAME_OVERHEAD(%r15)
0656 stmg %r0,%r14,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
0657 mvc STACK_FRAME_OVERHEAD+__PT_R15(8,%r15),__LC_SAVE_AREA_RESTART
0658 mvc STACK_FRAME_OVERHEAD+__PT_PSW(16,%r15),__LC_RST_OLD_PSW
0659 xc 0(STACK_FRAME_OVERHEAD,%r15),0(%r15)
0660 lg %r1,__LC_RESTART_FN # load fn, parm & source cpu
0661 lg %r2,__LC_RESTART_DATA
0662 lgf %r3,__LC_RESTART_SOURCE
0663 ltgr %r3,%r3 # test source cpu address
0664 jm 1f # negative -> skip source stop
0665 0: sigp %r4,%r3,SIGP_SENSE # sigp sense to source cpu
0666 brc 10,0b # wait for status stored
0667 1: basr %r14,%r1 # call function
0668 stap __SF_EMPTY(%r15) # store cpu address
0669 llgh %r3,__SF_EMPTY(%r15)
0670 2: sigp %r4,%r3,SIGP_STOP # sigp stop to current cpu
0671 brc 2,2b
0672 3: j 3b
0673 ENDPROC(restart_int_handler)
0674
0675 .section .kprobes.text, "ax"
0676
0677 #if defined(CONFIG_CHECK_STACK) || defined(CONFIG_VMAP_STACK)
0678
0679
0680
0681
0682
0683 ENTRY(stack_overflow)
0684 lg %r15,__LC_NODAT_STACK # change to panic stack
0685 la %r11,STACK_FRAME_OVERHEAD(%r15)
0686 stmg %r0,%r7,__PT_R0(%r11)
0687 stmg %r8,%r9,__PT_PSW(%r11)
0688 mvc __PT_R8(64,%r11),0(%r14)
0689 stg %r10,__PT_ORIG_GPR2(%r11) # store last break to orig_gpr2
0690 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
0691 lgr %r2,%r11 # pass pointer to pt_regs
0692 jg kernel_stack_overflow
0693 ENDPROC(stack_overflow)
0694 #endif
0695
0696 .section .data, "aw"
0697 .align 4
0698 .Lstop_lock: .long 0
0699 .Lthis_cpu: .short 0
0700 .Lstosm_tmp: .byte 0
0701 .section .rodata, "a"
0702 #define SYSCALL(esame,emu) .quad __s390x_ ## esame
0703 .globl sys_call_table
0704 sys_call_table:
0705 #include "asm/syscall_table.h"
0706 #undef SYSCALL
0707
0708 #ifdef CONFIG_COMPAT
0709
0710 #define SYSCALL(esame,emu) .quad __s390_ ## emu
0711 .globl sys_call_table_emu
0712 sys_call_table_emu:
0713 #include "asm/syscall_table.h"
0714 #undef SYSCALL
0715 #endif