1/* 2 * arch/s390/kernel/entry.S 3 * S390 low-level entry points. 4 * 5 * Copyright (C) IBM Corp. 1999,2012 6 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), 7 * Hartmut Penner (hp@de.ibm.com), 8 * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), 9 * Heiko Carstens <heiko.carstens@de.ibm.com> 10 */ 11 12#include <linux/init.h> 13#include <linux/linkage.h> 14#include <asm/cache.h> 15#include <asm/errno.h> 16#include <asm/ptrace.h> 17#include <asm/thread_info.h> 18#include <asm/asm-offsets.h> 19#include <asm/unistd.h> 20#include <asm/page.h> 21 22__PT_R0 = __PT_GPRS 23__PT_R1 = __PT_GPRS + 4 24__PT_R2 = __PT_GPRS + 8 25__PT_R3 = __PT_GPRS + 12 26__PT_R4 = __PT_GPRS + 16 27__PT_R5 = __PT_GPRS + 20 28__PT_R6 = __PT_GPRS + 24 29__PT_R7 = __PT_GPRS + 28 30__PT_R8 = __PT_GPRS + 32 31__PT_R9 = __PT_GPRS + 36 32__PT_R10 = __PT_GPRS + 40 33__PT_R11 = __PT_GPRS + 44 34__PT_R12 = __PT_GPRS + 48 35__PT_R13 = __PT_GPRS + 524 36__PT_R14 = __PT_GPRS + 56 37__PT_R15 = __PT_GPRS + 60 38 39_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ 40 _TIF_MCCK_PENDING | _TIF_PER_TRAP ) 41_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ 42 _TIF_MCCK_PENDING) 43_TIF_TRACE = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \ 44 _TIF_SYSCALL_TRACEPOINT) 45 46STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER 47STACK_SIZE = 1 << STACK_SHIFT 48 49#define BASED(name) name-system_call(%r13) 50 51 .macro TRACE_IRQS_ON 52#ifdef CONFIG_TRACE_IRQFLAGS 53 basr %r2,%r0 54 l %r1,BASED(.Lhardirqs_on) 55 basr %r14,%r1 # call trace_hardirqs_on_caller 56#endif 57 .endm 58 59 .macro TRACE_IRQS_OFF 60#ifdef CONFIG_TRACE_IRQFLAGS 61 basr %r2,%r0 62 l %r1,BASED(.Lhardirqs_off) 63 basr %r14,%r1 # call trace_hardirqs_off_caller 64#endif 65 .endm 66 67 .macro LOCKDEP_SYS_EXIT 68#ifdef CONFIG_LOCKDEP 69 tm __PT_PSW+1(%r11),0x01 # returning to user ? 70 jz .+10 71 l %r1,BASED(.Llockdep_sys_exit) 72 basr %r14,%r1 # call lockdep_sys_exit 73#endif 74 .endm 75 76 .macro CHECK_STACK stacksize,savearea 77#ifdef CONFIG_CHECK_STACK 78 tml %r15,\stacksize - CONFIG_STACK_GUARD 79 la %r14,\savearea 80 jz stack_overflow 81#endif 82 .endm 83 84 .macro SWITCH_ASYNC savearea,stack,shift 85 tmh %r8,0x0001 # interrupting from user ? 86 jnz 1f 87 lr %r14,%r9 88 sl %r14,BASED(.Lcritical_start) 89 cl %r14,BASED(.Lcritical_length) 90 jhe 0f 91 la %r11,\savearea # inside critical section, do cleanup 92 bras %r14,cleanup_critical 93 tmh %r8,0x0001 # retest problem state after cleanup 94 jnz 1f 950: l %r14,\stack # are we already on the target stack? 96 slr %r14,%r15 97 sra %r14,\shift 98 jnz 1f 99 CHECK_STACK 1<<\shift,\savearea 100 j 2f 1011: l %r15,\stack # load target stack 1022: ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) 103 la %r11,STACK_FRAME_OVERHEAD(%r15) 104 .endm 105 106 .macro ADD64 high,low,timer 107 al \high,\timer 108 al \low,4+\timer 109 brc 12,.+8 110 ahi \high,1 111 .endm 112 113 .macro SUB64 high,low,timer 114 sl \high,\timer 115 sl \low,4+\timer 116 brc 3,.+8 117 ahi \high,-1 118 .endm 119 120 .macro UPDATE_VTIME high,low,enter_timer 121 lm \high,\low,__LC_EXIT_TIMER 122 SUB64 \high,\low,\enter_timer 123 ADD64 \high,\low,__LC_USER_TIMER 124 stm \high,\low,__LC_USER_TIMER 125 lm \high,\low,__LC_LAST_UPDATE_TIMER 126 SUB64 \high,\low,__LC_EXIT_TIMER 127 ADD64 \high,\low,__LC_SYSTEM_TIMER 128 stm \high,\low,__LC_SYSTEM_TIMER 129 mvc __LC_LAST_UPDATE_TIMER(8),\enter_timer 130 .endm 131 132 .macro REENABLE_IRQS 133 st %r8,__LC_RETURN_PSW 134 ni __LC_RETURN_PSW,0xbf 135 ssm __LC_RETURN_PSW 136 .endm 137 138 .section .kprobes.text, "ax" 139 140/* 141 * Scheduler resume function, called by switch_to 142 * gpr2 = (task_struct *) prev 143 * gpr3 = (task_struct *) next 144 * Returns: 145 * gpr2 = prev 146 */ 147ENTRY(__switch_to) 148 l %r4,__THREAD_info(%r2) # get thread_info of prev 149 l %r5,__THREAD_info(%r3) # get thread_info of next 150 tm __TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending? 151 jz 0f 152 ni __TI_flags+3(%r4),255-_TIF_MCCK_PENDING # clear flag in prev 153 oi __TI_flags+3(%r5),_TIF_MCCK_PENDING # set it in next 1540: stm %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task 155 st %r15,__THREAD_ksp(%r2) # store kernel stack of prev 156 l %r15,__THREAD_ksp(%r3) # load kernel stack of next 157 lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4 158 lm %r6,%r15,__SF_GPRS(%r15) # load gprs of next task 159 st %r3,__LC_CURRENT # store task struct of next 160 mvc __LC_CURRENT_PID(4,%r0),__TASK_pid(%r3) # store pid of next 161 st %r5,__LC_THREAD_INFO # store thread info of next 162 ahi %r5,STACK_SIZE # end of kernel stack of next 163 st %r5,__LC_KERNEL_STACK # store end of kernel stack 164 br %r14 165 166__critical_start: 167/* 168 * SVC interrupt handler routine. System calls are synchronous events and 169 * are executed with interrupts enabled. 170 */ 171 172ENTRY(system_call) 173 stpt __LC_SYNC_ENTER_TIMER 174sysc_stm: 175 stm %r8,%r15,__LC_SAVE_AREA_SYNC 176 l %r12,__LC_THREAD_INFO 177 l %r13,__LC_SVC_NEW_PSW+4 178sysc_per: 179 l %r15,__LC_KERNEL_STACK 180 ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) 181 la %r11,STACK_FRAME_OVERHEAD(%r15) # pointer to pt_regs 182sysc_vtime: 183 UPDATE_VTIME %r8,%r9,__LC_SYNC_ENTER_TIMER 184 stm %r0,%r7,__PT_R0(%r11) 185 mvc __PT_R8(32,%r11),__LC_SAVE_AREA_SYNC 186 mvc __PT_PSW(8,%r11),__LC_SVC_OLD_PSW 187 mvc __PT_INT_CODE(4,%r11),__LC_SVC_ILC 188sysc_do_svc: 189 oi __TI_flags+3(%r12),_TIF_SYSCALL 190 lh %r8,__PT_INT_CODE+2(%r11) 191 sla %r8,2 # shift and test for svc0 192 jnz sysc_nr_ok 193 # svc 0: system call number in %r1 194 cl %r1,BASED(.Lnr_syscalls) 195 jnl sysc_nr_ok 196 sth %r1,__PT_INT_CODE+2(%r11) 197 lr %r8,%r1 198 sla %r8,2 199sysc_nr_ok: 200 l %r10,BASED(.Lsys_call_table) # 31 bit system call table 201 xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) 202 st %r2,__PT_ORIG_GPR2(%r11) 203 st %r7,STACK_FRAME_OVERHEAD(%r15) 204 l %r9,0(%r8,%r10) # get system call addr. 205 tm __TI_flags+2(%r12),_TIF_TRACE >> 8 206 jnz sysc_tracesys 207 basr %r14,%r9 # call sys_xxxx 208 st %r2,__PT_R2(%r11) # store return value 209 210sysc_return: 211 LOCKDEP_SYS_EXIT 212sysc_tif: 213 tm __PT_PSW+1(%r11),0x01 # returning to user ? 214 jno sysc_restore 215 tm __TI_flags+3(%r12),_TIF_WORK_SVC 216 jnz sysc_work # check for work 217 ni __TI_flags+3(%r12),255-_TIF_SYSCALL 218sysc_restore: 219 mvc __LC_RETURN_PSW(8),__PT_PSW(%r11) 220 stpt __LC_EXIT_TIMER 221 lm %r0,%r15,__PT_R0(%r11) 222 lpsw __LC_RETURN_PSW 223sysc_done: 224 225# 226# One of the work bits is on. Find out which one. 227# 228sysc_work: 229 tm __TI_flags+3(%r12),_TIF_MCCK_PENDING 230 jo sysc_mcck_pending 231 tm __TI_flags+3(%r12),_TIF_NEED_RESCHED 232 jo sysc_reschedule 233 tm __TI_flags+3(%r12),_TIF_SIGPENDING 234 jo sysc_sigpending 235 tm __TI_flags+3(%r12),_TIF_NOTIFY_RESUME 236 jo sysc_notify_resume 237 tm __TI_flags+3(%r12),_TIF_PER_TRAP 238 jo sysc_singlestep 239 j sysc_return # beware of critical section cleanup 240 241# 242# _TIF_NEED_RESCHED is set, call schedule 243# 244sysc_reschedule: 245 l %r1,BASED(.Lschedule) 246 la %r14,BASED(sysc_return) 247 br %r1 # call schedule 248 249# 250# _TIF_MCCK_PENDING is set, call handler 251# 252sysc_mcck_pending: 253 l %r1,BASED(.Lhandle_mcck) 254 la %r14,BASED(sysc_return) 255 br %r1 # TIF bit will be cleared by handler 256 257# 258# _TIF_SIGPENDING is set, call do_signal 259# 260sysc_sigpending: 261 ni __TI_flags+3(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP 262 lr %r2,%r11 # pass pointer to pt_regs 263 l %r1,BASED(.Ldo_signal) 264 basr %r14,%r1 # call do_signal 265 tm __TI_flags+3(%r12),_TIF_SYSCALL 266 jno sysc_return 267 lm %r2,%r7,__PT_R2(%r11) # load svc arguments 268 xr %r8,%r8 # svc 0 returns -ENOSYS 269 clc __PT_INT_CODE+2(2,%r11),BASED(.Lnr_syscalls+2) 270 jnl sysc_nr_ok # invalid svc number -> do svc 0 271 lh %r8,__PT_INT_CODE+2(%r11) # load new svc number 272 sla %r8,2 273 j sysc_nr_ok # restart svc 274 275# 276# _TIF_NOTIFY_RESUME is set, call do_notify_resume 277# 278sysc_notify_resume: 279 lr %r2,%r11 # pass pointer to pt_regs 280 l %r1,BASED(.Ldo_notify_resume) 281 la %r14,BASED(sysc_return) 282 br %r1 # call do_notify_resume 283 284# 285# _TIF_PER_TRAP is set, call do_per_trap 286# 287sysc_singlestep: 288 ni __TI_flags+3(%r12),255-(_TIF_SYSCALL | _TIF_PER_TRAP) 289 lr %r2,%r11 # pass pointer to pt_regs 290 l %r1,BASED(.Ldo_per_trap) 291 la %r14,BASED(sysc_return) 292 br %r1 # call do_per_trap 293 294# 295# call tracehook_report_syscall_entry/tracehook_report_syscall_exit before 296# and after the system call 297# 298sysc_tracesys: 299 l %r1,BASED(.Ltrace_enter) 300 lr %r2,%r11 # pass pointer to pt_regs 301 la %r3,0 302 xr %r0,%r0 303 icm %r0,3,__PT_INT_CODE+2(%r11) 304 st %r0,__PT_R2(%r11) 305 basr %r14,%r1 # call do_syscall_trace_enter 306 cl %r2,BASED(.Lnr_syscalls) 307 jnl sysc_tracenogo 308 lr %r8,%r2 309 sll %r8,2 310 l %r9,0(%r8,%r10) 311sysc_tracego: 312 lm %r3,%r7,__PT_R3(%r11) 313 st %r7,STACK_FRAME_OVERHEAD(%r15) 314 l %r2,__PT_ORIG_GPR2(%r11) 315 basr %r14,%r9 # call sys_xxx 316 st %r2,__PT_R2(%r11) # store return value 317sysc_tracenogo: 318 tm __TI_flags+2(%r12),_TIF_TRACE >> 8 319 jz sysc_return 320 l %r1,BASED(.Ltrace_exit) 321 lr %r2,%r11 # pass pointer to pt_regs 322 la %r14,BASED(sysc_return) 323 br %r1 # call do_syscall_trace_exit 324 325# 326# a new process exits the kernel with ret_from_fork 327# 328ENTRY(ret_from_fork) 329 la %r11,STACK_FRAME_OVERHEAD(%r15) 330 l %r12,__LC_THREAD_INFO 331 l %r13,__LC_SVC_NEW_PSW+4 332 tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? 333 jo 0f 334 st %r15,__PT_R15(%r11) # store stack pointer for new kthread 3350: l %r1,BASED(.Lschedule_tail) 336 basr %r14,%r1 # call schedule_tail 337 TRACE_IRQS_ON 338 ssm __LC_SVC_NEW_PSW # reenable interrupts 339 j sysc_tracenogo 340 341# 342# kernel_execve function needs to deal with pt_regs that is not 343# at the usual place 344# 345ENTRY(kernel_execve) 346 stm %r12,%r15,48(%r15) 347 lr %r14,%r15 348 l %r13,__LC_SVC_NEW_PSW+4 349 ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) 350 st %r14,__SF_BACKCHAIN(%r15) 351 la %r12,STACK_FRAME_OVERHEAD(%r15) 352 xc 0(__PT_SIZE,%r12),0(%r12) 353 l %r1,BASED(.Ldo_execve) 354 lr %r5,%r12 355 basr %r14,%r1 # call do_execve 356 ltr %r2,%r2 357 je 0f 358 ahi %r15,(STACK_FRAME_OVERHEAD + __PT_SIZE) 359 lm %r12,%r15,48(%r15) 360 br %r14 361 # execve succeeded. 3620: ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts 363 l %r15,__LC_KERNEL_STACK # load ksp 364 ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) 365 la %r11,STACK_FRAME_OVERHEAD(%r15) 366 mvc 0(__PT_SIZE,%r11),0(%r12) # copy pt_regs 367 l %r12,__LC_THREAD_INFO 368 xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) 369 ssm __LC_SVC_NEW_PSW # reenable interrupts 370 l %r1,BASED(.Lexecve_tail) 371 basr %r14,%r1 # call execve_tail 372 j sysc_return 373 374/* 375 * Program check handler routine 376 */ 377 378ENTRY(pgm_check_handler) 379 stpt __LC_SYNC_ENTER_TIMER 380 stm %r8,%r15,__LC_SAVE_AREA_SYNC 381 l %r12,__LC_THREAD_INFO 382 l %r13,__LC_SVC_NEW_PSW+4 383 lm %r8,%r9,__LC_PGM_OLD_PSW 384 tmh %r8,0x0001 # test problem state bit 385 jnz 1f # -> fault in user space 386 tmh %r8,0x4000 # PER bit set in old PSW ? 387 jnz 0f # -> enabled, can't be a double fault 388 tm __LC_PGM_ILC+3,0x80 # check for per exception 389 jnz pgm_svcper # -> single stepped svc 3900: CHECK_STACK STACK_SIZE,__LC_SAVE_AREA_SYNC 391 j 2f 3921: UPDATE_VTIME %r14,%r15,__LC_SYNC_ENTER_TIMER 393 l %r15,__LC_KERNEL_STACK 3942: ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) 395 la %r11,STACK_FRAME_OVERHEAD(%r15) 396 stm %r0,%r7,__PT_R0(%r11) 397 mvc __PT_R8(32,%r11),__LC_SAVE_AREA_SYNC 398 stm %r8,%r9,__PT_PSW(%r11) 399 mvc __PT_INT_CODE(4,%r11),__LC_PGM_ILC 400 mvc __PT_INT_PARM_LONG(4,%r11),__LC_TRANS_EXC_CODE 401 tm __LC_PGM_ILC+3,0x80 # check for per exception 402 jz 0f 403 l %r1,__TI_task(%r12) 404 tmh %r8,0x0001 # kernel per event ? 405 jz pgm_kprobe 406 oi __TI_flags+3(%r12),_TIF_PER_TRAP 407 mvc __THREAD_per_address(4,%r1),__LC_PER_ADDRESS 408 mvc __THREAD_per_cause(2,%r1),__LC_PER_CAUSE 409 mvc __THREAD_per_paid(1,%r1),__LC_PER_PAID 4100: REENABLE_IRQS 411 xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) 412 l %r1,BASED(.Ljump_table) 413 la %r10,0x7f 414 n %r10,__PT_INT_CODE(%r11) 415 je sysc_return 416 sll %r10,2 417 l %r1,0(%r10,%r1) # load address of handler routine 418 lr %r2,%r11 # pass pointer to pt_regs 419 basr %r14,%r1 # branch to interrupt-handler 420 j sysc_return 421 422# 423# PER event in supervisor state, must be kprobes 424# 425pgm_kprobe: 426 REENABLE_IRQS 427 xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) 428 l %r1,BASED(.Ldo_per_trap) 429 lr %r2,%r11 # pass pointer to pt_regs 430 basr %r14,%r1 # call do_per_trap 431 j sysc_return 432 433# 434# single stepped system call 435# 436pgm_svcper: 437 oi __TI_flags+3(%r12),_TIF_PER_TRAP 438 mvc __LC_RETURN_PSW(4),__LC_SVC_NEW_PSW 439 mvc __LC_RETURN_PSW+4(4),BASED(.Lsysc_per) 440 lpsw __LC_RETURN_PSW # branch to sysc_per and enable irqs 441 442/* 443 * IO interrupt handler routine 444 */ 445 446ENTRY(io_int_handler) 447 stck __LC_INT_CLOCK 448 stpt __LC_ASYNC_ENTER_TIMER 449 stm %r8,%r15,__LC_SAVE_AREA_ASYNC 450 l %r12,__LC_THREAD_INFO 451 l %r13,__LC_SVC_NEW_PSW+4 452 lm %r8,%r9,__LC_IO_OLD_PSW 453 tmh %r8,0x0001 # interrupting from user ? 454 jz io_skip 455 UPDATE_VTIME %r14,%r15,__LC_ASYNC_ENTER_TIMER 456io_skip: 457 SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT 458 stm %r0,%r7,__PT_R0(%r11) 459 mvc __PT_R8(32,%r11),__LC_SAVE_AREA_ASYNC 460 stm %r8,%r9,__PT_PSW(%r11) 461 TRACE_IRQS_OFF 462 xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) 463 l %r1,BASED(.Ldo_IRQ) 464 lr %r2,%r11 # pass pointer to pt_regs 465 basr %r14,%r1 # call do_IRQ 466io_return: 467 LOCKDEP_SYS_EXIT 468 TRACE_IRQS_ON 469io_tif: 470 tm __TI_flags+3(%r12),_TIF_WORK_INT 471 jnz io_work # there is work to do (signals etc.) 472io_restore: 473 mvc __LC_RETURN_PSW(8),__PT_PSW(%r11) 474 stpt __LC_EXIT_TIMER 475 lm %r0,%r15,__PT_R0(%r11) 476 lpsw __LC_RETURN_PSW 477io_done: 478 479# 480# There is work todo, find out in which context we have been interrupted: 481# 1) if we return to user space we can do all _TIF_WORK_INT work 482# 2) if we return to kernel code and preemptive scheduling is enabled check 483# the preemption counter and if it is zero call preempt_schedule_irq 484# Before any work can be done, a switch to the kernel stack is required. 485# 486io_work: 487 tm __PT_PSW+1(%r11),0x01 # returning to user ? 488 jo io_work_user # yes -> do resched & signal 489#ifdef CONFIG_PREEMPT 490 # check for preemptive scheduling 491 icm %r0,15,__TI_precount(%r12) 492 jnz io_restore # preemption disabled 493 tm __TI_flags+3(%r12),_TIF_NEED_RESCHED 494 jno io_restore 495 # switch to kernel stack 496 l %r1,__PT_R15(%r11) 497 ahi %r1,-(STACK_FRAME_OVERHEAD + __PT_SIZE) 498 mvc STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11) 499 xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) 500 la %r11,STACK_FRAME_OVERHEAD(%r1) 501 lr %r15,%r1 502 # TRACE_IRQS_ON already done at io_return, call 503 # TRACE_IRQS_OFF to keep things symmetrical 504 TRACE_IRQS_OFF 505 l %r1,BASED(.Lpreempt_irq) 506 basr %r14,%r1 # call preempt_schedule_irq 507 j io_return 508#else 509 j io_restore 510#endif 511 512# 513# Need to do work before returning to userspace, switch to kernel stack 514# 515io_work_user: 516 l %r1,__LC_KERNEL_STACK 517 ahi %r1,-(STACK_FRAME_OVERHEAD + __PT_SIZE) 518 mvc STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11) 519 xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) 520 la %r11,STACK_FRAME_OVERHEAD(%r1) 521 lr %r15,%r1 522 523# 524# One of the work bits is on. Find out which one. 525# Checked are: _TIF_SIGPENDING, _TIF_NOTIFY_RESUME, _TIF_NEED_RESCHED 526# and _TIF_MCCK_PENDING 527# 528io_work_tif: 529 tm __TI_flags+3(%r12),_TIF_MCCK_PENDING 530 jo io_mcck_pending 531 tm __TI_flags+3(%r12),_TIF_NEED_RESCHED 532 jo io_reschedule 533 tm __TI_flags+3(%r12),_TIF_SIGPENDING 534 jo io_sigpending 535 tm __TI_flags+3(%r12),_TIF_NOTIFY_RESUME 536 jo io_notify_resume 537 j io_return # beware of critical section cleanup 538 539# 540# _TIF_MCCK_PENDING is set, call handler 541# 542io_mcck_pending: 543 # TRACE_IRQS_ON already done at io_return 544 l %r1,BASED(.Lhandle_mcck) 545 basr %r14,%r1 # TIF bit will be cleared by handler 546 TRACE_IRQS_OFF 547 j io_return 548 549# 550# _TIF_NEED_RESCHED is set, call schedule 551# 552io_reschedule: 553 # TRACE_IRQS_ON already done at io_return 554 l %r1,BASED(.Lschedule) 555 ssm __LC_SVC_NEW_PSW # reenable interrupts 556 basr %r14,%r1 # call scheduler 557 ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts 558 TRACE_IRQS_OFF 559 j io_return 560 561# 562# _TIF_SIGPENDING is set, call do_signal 563# 564io_sigpending: 565 # TRACE_IRQS_ON already done at io_return 566 l %r1,BASED(.Ldo_signal) 567 ssm __LC_SVC_NEW_PSW # reenable interrupts 568 lr %r2,%r11 # pass pointer to pt_regs 569 basr %r14,%r1 # call do_signal 570 ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts 571 TRACE_IRQS_OFF 572 j io_return 573 574# 575# _TIF_SIGPENDING is set, call do_signal 576# 577io_notify_resume: 578 # TRACE_IRQS_ON already done at io_return 579 l %r1,BASED(.Ldo_notify_resume) 580 ssm __LC_SVC_NEW_PSW # reenable interrupts 581 lr %r2,%r11 # pass pointer to pt_regs 582 basr %r14,%r1 # call do_notify_resume 583 ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts 584 TRACE_IRQS_OFF 585 j io_return 586 587/* 588 * External interrupt handler routine 589 */ 590 591ENTRY(ext_int_handler) 592 stck __LC_INT_CLOCK 593 stpt __LC_ASYNC_ENTER_TIMER 594 stm %r8,%r15,__LC_SAVE_AREA_ASYNC 595 l %r12,__LC_THREAD_INFO 596 l %r13,__LC_SVC_NEW_PSW+4 597 lm %r8,%r9,__LC_EXT_OLD_PSW 598 tmh %r8,0x0001 # interrupting from user ? 599 jz ext_skip 600 UPDATE_VTIME %r14,%r15,__LC_ASYNC_ENTER_TIMER 601ext_skip: 602 SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT 603 stm %r0,%r7,__PT_R0(%r11) 604 mvc __PT_R8(32,%r11),__LC_SAVE_AREA_ASYNC 605 stm %r8,%r9,__PT_PSW(%r11) 606 TRACE_IRQS_OFF 607 lr %r2,%r11 # pass pointer to pt_regs 608 l %r3,__LC_EXT_CPU_ADDR # get cpu address + interruption code 609 l %r4,__LC_EXT_PARAMS # get external parameters 610 l %r1,BASED(.Ldo_extint) 611 basr %r14,%r1 # call do_extint 612 j io_return 613 614/* 615 * Load idle PSW. The second "half" of this function is in cleanup_idle. 616 */ 617ENTRY(psw_idle) 618 st %r4,__SF_EMPTY(%r15) 619 basr %r1,0 620 la %r1,psw_idle_lpsw+4-.(%r1) 621 st %r1,__SF_EMPTY+4(%r15) 622 oi __SF_EMPTY+4(%r15),0x80 623 la %r1,.Lvtimer_max-psw_idle_lpsw-4(%r1) 624 stck __IDLE_ENTER(%r2) 625 ltr %r5,%r5 626 stpt __VQ_IDLE_ENTER(%r3) 627 jz psw_idle_lpsw 628 spt 0(%r1) 629psw_idle_lpsw: 630 lpsw __SF_EMPTY(%r15) 631 br %r14 632psw_idle_end: 633 634__critical_end: 635 636/* 637 * Machine check handler routines 638 */ 639 640ENTRY(mcck_int_handler) 641 stck __LC_MCCK_CLOCK 642 spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer 643 lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs 644 l %r12,__LC_THREAD_INFO 645 l %r13,__LC_SVC_NEW_PSW+4 646 lm %r8,%r9,__LC_MCK_OLD_PSW 647 tm __LC_MCCK_CODE,0x80 # system damage? 648 jo mcck_panic # yes -> rest of mcck code invalid 649 la %r14,__LC_CPU_TIMER_SAVE_AREA 650 mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) 651 tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? 652 jo 3f 653 la %r14,__LC_SYNC_ENTER_TIMER 654 clc 0(8,%r14),__LC_ASYNC_ENTER_TIMER 655 jl 0f 656 la %r14,__LC_ASYNC_ENTER_TIMER 6570: clc 0(8,%r14),__LC_EXIT_TIMER 658 jl 1f 659 la %r14,__LC_EXIT_TIMER 6601: clc 0(8,%r14),__LC_LAST_UPDATE_TIMER 661 jl 2f 662 la %r14,__LC_LAST_UPDATE_TIMER 6632: spt 0(%r14) 664 mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) 6653: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? 666 jno mcck_panic # no -> skip cleanup critical 667 tm %r8,0x0001 # interrupting from user ? 668 jz mcck_skip 669 UPDATE_VTIME %r14,%r15,__LC_MCCK_ENTER_TIMER 670mcck_skip: 671 SWITCH_ASYNC __LC_GPREGS_SAVE_AREA+32,__LC_PANIC_STACK,PAGE_SHIFT 672 mvc __PT_R0(64,%r11),__LC_GPREGS_SAVE_AREA 673 stm %r8,%r9,__PT_PSW(%r11) 674 xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) 675 l %r1,BASED(.Ldo_machine_check) 676 lr %r2,%r11 # pass pointer to pt_regs 677 basr %r14,%r1 # call s390_do_machine_check 678 tm __PT_PSW+1(%r11),0x01 # returning to user ? 679 jno mcck_return 680 l %r1,__LC_KERNEL_STACK # switch to kernel stack 681 ahi %r1,-(STACK_FRAME_OVERHEAD + __PT_SIZE) 682 mvc STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11) 683 xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) 684 la %r11,STACK_FRAME_OVERHEAD(%r15) 685 lr %r15,%r1 686 ssm __LC_PGM_NEW_PSW # turn dat on, keep irqs off 687 tm __TI_flags+3(%r12),_TIF_MCCK_PENDING 688 jno mcck_return 689 TRACE_IRQS_OFF 690 l %r1,BASED(.Lhandle_mcck) 691 basr %r14,%r1 # call s390_handle_mcck 692 TRACE_IRQS_ON 693mcck_return: 694 mvc __LC_RETURN_MCCK_PSW(8),__PT_PSW(%r11) # move return PSW 695 tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? 696 jno 0f 697 lm %r0,%r15,__PT_R0(%r11) 698 stpt __LC_EXIT_TIMER 699 lpsw __LC_RETURN_MCCK_PSW 7000: lm %r0,%r15,__PT_R0(%r11) 701 lpsw __LC_RETURN_MCCK_PSW 702 703mcck_panic: 704 l %r14,__LC_PANIC_STACK 705 slr %r14,%r15 706 sra %r14,PAGE_SHIFT 707 jz 0f 708 l %r15,__LC_PANIC_STACK 7090: ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) 710 j mcck_skip 711 712# 713# PSW restart interrupt handler 714# 715ENTRY(restart_int_handler) 716 st %r15,__LC_SAVE_AREA_RESTART 717 l %r15,__LC_RESTART_STACK 718 ahi %r15,-__PT_SIZE # create pt_regs on stack 719 xc 0(__PT_SIZE,%r15),0(%r15) 720 stm %r0,%r14,__PT_R0(%r15) 721 mvc __PT_R15(4,%r15),__LC_SAVE_AREA_RESTART 722 mvc __PT_PSW(8,%r15),__LC_RST_OLD_PSW # store restart old psw 723 ahi %r15,-STACK_FRAME_OVERHEAD # create stack frame on stack 724 xc 0(STACK_FRAME_OVERHEAD,%r15),0(%r15) 725 lm %r1,%r3,__LC_RESTART_FN # load fn, parm & source cpu 726 ltr %r3,%r3 # test source cpu address 727 jm 1f # negative -> skip source stop 7280: sigp %r4,%r3,1 # sigp sense to source cpu 729 brc 10,0b # wait for status stored 7301: basr %r14,%r1 # call function 731 stap __SF_EMPTY(%r15) # store cpu address 732 lh %r3,__SF_EMPTY(%r15) 7332: sigp %r4,%r3,5 # sigp stop to current cpu 734 brc 2,2b 7353: j 3b 736 737 .section .kprobes.text, "ax" 738 739#ifdef CONFIG_CHECK_STACK 740/* 741 * The synchronous or the asynchronous stack overflowed. We are dead. 742 * No need to properly save the registers, we are going to panic anyway. 743 * Setup a pt_regs so that show_trace can provide a good call trace. 744 */ 745stack_overflow: 746 l %r15,__LC_PANIC_STACK # change to panic stack 747 ahi %r15,-__PT_SIZE # create pt_regs 748 stm %r0,%r7,__PT_R0(%r15) 749 stm %r8,%r9,__PT_PSW(%r15) 750 mvc __PT_R8(32,%r11),0(%r14) 751 lr %r15,%r11 752 ahi %r15,-STACK_FRAME_OVERHEAD 753 l %r1,BASED(1f) 754 xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) 755 lr %r2,%r11 # pass pointer to pt_regs 756 br %r1 # branch to kernel_stack_overflow 7571: .long kernel_stack_overflow 758#endif 759 760cleanup_table: 761 .long system_call + 0x80000000 762 .long sysc_do_svc + 0x80000000 763 .long sysc_tif + 0x80000000 764 .long sysc_restore + 0x80000000 765 .long sysc_done + 0x80000000 766 .long io_tif + 0x80000000 767 .long io_restore + 0x80000000 768 .long io_done + 0x80000000 769 .long psw_idle + 0x80000000 770 .long psw_idle_end + 0x80000000 771 772cleanup_critical: 773 cl %r9,BASED(cleanup_table) # system_call 774 jl 0f 775 cl %r9,BASED(cleanup_table+4) # sysc_do_svc 776 jl cleanup_system_call 777 cl %r9,BASED(cleanup_table+8) # sysc_tif 778 jl 0f 779 cl %r9,BASED(cleanup_table+12) # sysc_restore 780 jl cleanup_sysc_tif 781 cl %r9,BASED(cleanup_table+16) # sysc_done 782 jl cleanup_sysc_restore 783 cl %r9,BASED(cleanup_table+20) # io_tif 784 jl 0f 785 cl %r9,BASED(cleanup_table+24) # io_restore 786 jl cleanup_io_tif 787 cl %r9,BASED(cleanup_table+28) # io_done 788 jl cleanup_io_restore 789 cl %r9,BASED(cleanup_table+32) # psw_idle 790 jl 0f 791 cl %r9,BASED(cleanup_table+36) # psw_idle_end 792 jl cleanup_idle 7930: br %r14 794 795cleanup_system_call: 796 # check if stpt has been executed 797 cl %r9,BASED(cleanup_system_call_insn) 798 jh 0f 799 mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER 800 chi %r11,__LC_SAVE_AREA_ASYNC 801 je 0f 802 mvc __LC_SYNC_ENTER_TIMER(8),__LC_MCCK_ENTER_TIMER 8030: # check if stm has been executed 804 cl %r9,BASED(cleanup_system_call_insn+4) 805 jh 0f 806 mvc __LC_SAVE_AREA_SYNC(32),0(%r11) 8070: # set up saved registers r12, and r13 808 st %r12,16(%r11) # r12 thread-info pointer 809 st %r13,20(%r11) # r13 literal-pool pointer 810 # check if the user time calculation has been done 811 cl %r9,BASED(cleanup_system_call_insn+8) 812 jh 0f 813 l %r10,__LC_EXIT_TIMER 814 l %r15,__LC_EXIT_TIMER+4 815 SUB64 %r10,%r15,__LC_SYNC_ENTER_TIMER 816 ADD64 %r10,%r15,__LC_USER_TIMER 817 st %r10,__LC_USER_TIMER 818 st %r15,__LC_USER_TIMER+4 8190: # check if the system time calculation has been done 820 cl %r9,BASED(cleanup_system_call_insn+12) 821 jh 0f 822 l %r10,__LC_LAST_UPDATE_TIMER 823 l %r15,__LC_LAST_UPDATE_TIMER+4 824 SUB64 %r10,%r15,__LC_EXIT_TIMER 825 ADD64 %r10,%r15,__LC_SYSTEM_TIMER 826 st %r10,__LC_SYSTEM_TIMER 827 st %r15,__LC_SYSTEM_TIMER+4 8280: # update accounting time stamp 829 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER 830 # set up saved register 11 831 l %r15,__LC_KERNEL_STACK 832 ahi %r15,-__PT_SIZE 833 st %r15,12(%r11) # r11 pt_regs pointer 834 # fill pt_regs 835 mvc __PT_R8(32,%r15),__LC_SAVE_AREA_SYNC 836 stm %r0,%r7,__PT_R0(%r15) 837 mvc __PT_PSW(8,%r15),__LC_SVC_OLD_PSW 838 mvc __PT_INT_CODE(4,%r15),__LC_SVC_ILC 839 # setup saved register 15 840 ahi %r15,-STACK_FRAME_OVERHEAD 841 st %r15,28(%r11) # r15 stack pointer 842 # set new psw address and exit 843 l %r9,BASED(cleanup_table+4) # sysc_do_svc + 0x80000000 844 br %r14 845cleanup_system_call_insn: 846 .long system_call + 0x80000000 847 .long sysc_stm + 0x80000000 848 .long sysc_vtime + 0x80000000 + 36 849 .long sysc_vtime + 0x80000000 + 76 850 851cleanup_sysc_tif: 852 l %r9,BASED(cleanup_table+8) # sysc_tif + 0x80000000 853 br %r14 854 855cleanup_sysc_restore: 856 cl %r9,BASED(cleanup_sysc_restore_insn) 857 jhe 0f 858 l %r9,12(%r11) # get saved pointer to pt_regs 859 mvc __LC_RETURN_PSW(8),__PT_PSW(%r9) 860 mvc 0(32,%r11),__PT_R8(%r9) 861 lm %r0,%r7,__PT_R0(%r9) 8620: lm %r8,%r9,__LC_RETURN_PSW 863 br %r14 864cleanup_sysc_restore_insn: 865 .long sysc_done - 4 + 0x80000000 866 867cleanup_io_tif: 868 l %r9,BASED(cleanup_table+20) # io_tif + 0x80000000 869 br %r14 870 871cleanup_io_restore: 872 cl %r9,BASED(cleanup_io_restore_insn) 873 jhe 0f 874 l %r9,12(%r11) # get saved r11 pointer to pt_regs 875 mvc __LC_RETURN_PSW(8),__PT_PSW(%r9) 876 mvc 0(32,%r11),__PT_R8(%r9) 877 lm %r0,%r7,__PT_R0(%r9) 8780: lm %r8,%r9,__LC_RETURN_PSW 879 br %r14 880cleanup_io_restore_insn: 881 .long io_done - 4 + 0x80000000 882 883cleanup_idle: 884 # copy interrupt clock & cpu timer 885 mvc __IDLE_EXIT(8,%r2),__LC_INT_CLOCK 886 mvc __VQ_IDLE_EXIT(8,%r3),__LC_ASYNC_ENTER_TIMER 887 chi %r11,__LC_SAVE_AREA_ASYNC 888 je 0f 889 mvc __IDLE_EXIT(8,%r2),__LC_MCCK_CLOCK 890 mvc __VQ_IDLE_EXIT(8,%r3),__LC_MCCK_ENTER_TIMER 8910: # check if stck has been executed 892 cl %r9,BASED(cleanup_idle_insn) 893 jhe 1f 894 mvc __IDLE_ENTER(8,%r2),__IDLE_EXIT(%r2) 895 mvc __VQ_IDLE_ENTER(8,%r3),__VQ_IDLE_EXIT(%r3) 896 j 2f 8971: # check if the cpu timer has been reprogrammed 898 ltr %r5,%r5 899 jz 2f 900 spt __VQ_IDLE_ENTER(%r3) 9012: # account system time going idle 902 lm %r9,%r10,__LC_STEAL_TIMER 903 ADD64 %r9,%r10,__IDLE_ENTER(%r2) 904 SUB64 %r9,%r10,__LC_LAST_UPDATE_CLOCK 905 stm %r9,%r10,__LC_STEAL_TIMER 906 mvc __LC_LAST_UPDATE_CLOCK(8),__IDLE_EXIT(%r2) 907 lm %r9,%r10,__LC_SYSTEM_TIMER 908 ADD64 %r9,%r10,__LC_LAST_UPDATE_TIMER 909 SUB64 %r9,%r10,__VQ_IDLE_ENTER(%r3) 910 stm %r9,%r10,__LC_SYSTEM_TIMER 911 mvc __LC_LAST_UPDATE_TIMER(8),__VQ_IDLE_EXIT(%r3) 912 # prepare return psw 913 n %r8,BASED(cleanup_idle_wait) # clear wait state bit 914 l %r9,24(%r11) # return from psw_idle 915 br %r14 916cleanup_idle_insn: 917 .long psw_idle_lpsw + 0x80000000 918cleanup_idle_wait: 919 .long 0xfffdffff 920 921/* 922 * Integer constants 923 */ 924 .align 4 925.Lnr_syscalls: 926 .long NR_syscalls 927.Lvtimer_max: 928 .quad 0x7fffffffffffffff 929 930/* 931 * Symbol constants 932 */ 933.Ldo_machine_check: .long s390_do_machine_check 934.Lhandle_mcck: .long s390_handle_mcck 935.Ldo_IRQ: .long do_IRQ 936.Ldo_extint: .long do_extint 937.Ldo_signal: .long do_signal 938.Ldo_notify_resume: .long do_notify_resume 939.Ldo_per_trap: .long do_per_trap 940.Ldo_execve: .long do_execve 941.Lexecve_tail: .long execve_tail 942.Ljump_table: .long pgm_check_table 943.Lschedule: .long schedule 944#ifdef CONFIG_PREEMPT 945.Lpreempt_irq: .long preempt_schedule_irq 946#endif 947.Ltrace_enter: .long do_syscall_trace_enter 948.Ltrace_exit: .long do_syscall_trace_exit 949.Lschedule_tail: .long schedule_tail 950.Lsys_call_table: .long sys_call_table 951.Lsysc_per: .long sysc_per + 0x80000000 952#ifdef CONFIG_TRACE_IRQFLAGS 953.Lhardirqs_on: .long trace_hardirqs_on_caller 954.Lhardirqs_off: .long trace_hardirqs_off_caller 955#endif 956#ifdef CONFIG_LOCKDEP 957.Llockdep_sys_exit: .long lockdep_sys_exit 958#endif 959.Lcritical_start: .long __critical_start + 0x80000000 960.Lcritical_length: .long __critical_end - __critical_start 961 962 .section .rodata, "a" 963#define SYSCALL(esa,esame,emu) .long esa 964 .globl sys_call_table 965sys_call_table: 966#include "syscalls.S" 967#undef SYSCALL 968