aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/entry.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/entry.S')
-rw-r--r--arch/s390/kernel/entry.S329
1 files changed, 149 insertions, 180 deletions
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index e8ef21c51bbe..bea9ee37ac9d 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -13,7 +13,6 @@
13#include <linux/linkage.h> 13#include <linux/linkage.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <asm/cache.h> 15#include <asm/cache.h>
16#include <asm/lowcore.h>
17#include <asm/errno.h> 16#include <asm/errno.h>
18#include <asm/ptrace.h> 17#include <asm/ptrace.h>
19#include <asm/thread_info.h> 18#include <asm/thread_info.h>
@@ -74,21 +73,24 @@ STACK_SIZE = 1 << STACK_SHIFT
74 basr %r14,%r1 73 basr %r14,%r1
75 .endm 74 .endm
76 75
77 .macro TRACE_IRQS_CHECK 76 .macro TRACE_IRQS_CHECK_ON
78 basr %r2,%r0
79 tm SP_PSW(%r15),0x03 # irqs enabled? 77 tm SP_PSW(%r15),0x03 # irqs enabled?
80 jz 0f 78 bz BASED(0f)
81 l %r1,BASED(.Ltrace_irq_on_caller) 79 TRACE_IRQS_ON
82 basr %r14,%r1 800:
83 j 1f 81 .endm
840: l %r1,BASED(.Ltrace_irq_off_caller) 82
85 basr %r14,%r1 83 .macro TRACE_IRQS_CHECK_OFF
861: 84 tm SP_PSW(%r15),0x03 # irqs enabled?
85 bz BASED(0f)
86 TRACE_IRQS_OFF
870:
87 .endm 88 .endm
88#else 89#else
89#define TRACE_IRQS_ON 90#define TRACE_IRQS_ON
90#define TRACE_IRQS_OFF 91#define TRACE_IRQS_OFF
91#define TRACE_IRQS_CHECK 92#define TRACE_IRQS_CHECK_ON
93#define TRACE_IRQS_CHECK_OFF
92#endif 94#endif
93 95
94#ifdef CONFIG_LOCKDEP 96#ifdef CONFIG_LOCKDEP
@@ -178,9 +180,9 @@ STACK_SIZE = 1 << STACK_SHIFT
178 s %r15,BASED(.Lc_spsize) # make room for registers & psw 180 s %r15,BASED(.Lc_spsize) # make room for registers & psw
179 mvc SP_PSW(8,%r15),0(%r12) # move user PSW to stack 181 mvc SP_PSW(8,%r15),0(%r12) # move user PSW to stack
180 st %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 182 st %r2,SP_ORIG_R2(%r15) # store original content of gpr 2
181 icm %r12,3,__LC_SVC_ILC 183 icm %r12,12,__LC_SVC_ILC
182 stm %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack 184 stm %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack
183 st %r12,SP_SVCNR(%r15) 185 st %r12,SP_ILC(%r15)
184 mvc SP_R12(16,%r15),\savearea # move %r12-%r15 to stack 186 mvc SP_R12(16,%r15),\savearea # move %r12-%r15 to stack
185 la %r12,0 187 la %r12,0
186 st %r12,__SF_BACKCHAIN(%r15) # clear back chain 188 st %r12,__SF_BACKCHAIN(%r15) # clear back chain
@@ -274,66 +276,45 @@ sysc_do_restart:
274 st %r2,SP_R2(%r15) # store return value (change R2 on stack) 276 st %r2,SP_R2(%r15) # store return value (change R2 on stack)
275 277
276sysc_return: 278sysc_return:
279 LOCKDEP_SYS_EXIT
280sysc_tif:
277 tm __TI_flags+3(%r9),_TIF_WORK_SVC 281 tm __TI_flags+3(%r9),_TIF_WORK_SVC
278 bnz BASED(sysc_work) # there is work to do (signals etc.) 282 bnz BASED(sysc_work) # there is work to do (signals etc.)
279sysc_restore: 283sysc_restore:
280#ifdef CONFIG_TRACE_IRQFLAGS
281 la %r1,BASED(sysc_restore_trace_psw_addr)
282 l %r1,0(%r1)
283 lpsw 0(%r1)
284sysc_restore_trace:
285 TRACE_IRQS_CHECK
286 LOCKDEP_SYS_EXIT
287#endif
288sysc_leave:
289 RESTORE_ALL __LC_RETURN_PSW,1 284 RESTORE_ALL __LC_RETURN_PSW,1
290sysc_done: 285sysc_done:
291 286
292#ifdef CONFIG_TRACE_IRQFLAGS
293sysc_restore_trace_psw_addr:
294 .long sysc_restore_trace_psw
295
296 .section .data,"aw",@progbits
297 .align 8
298 .globl sysc_restore_trace_psw
299sysc_restore_trace_psw:
300 .long 0, sysc_restore_trace + 0x80000000
301 .previous
302#endif
303
304# 287#
305# recheck if there is more work to do 288# There is work to do, but first we need to check if we return to userspace.
306#
307sysc_work_loop:
308 tm __TI_flags+3(%r9),_TIF_WORK_SVC
309 bz BASED(sysc_restore) # there is no work to do
310#
311# One of the work bits is on. Find out which one.
312# 289#
313sysc_work: 290sysc_work:
314 tm SP_PSW+1(%r15),0x01 # returning to user ? 291 tm SP_PSW+1(%r15),0x01 # returning to user ?
315 bno BASED(sysc_restore) 292 bno BASED(sysc_restore)
293
294#
295# One of the work bits is on. Find out which one.
296#
297sysc_work_tif:
316 tm __TI_flags+3(%r9),_TIF_MCCK_PENDING 298 tm __TI_flags+3(%r9),_TIF_MCCK_PENDING
317 bo BASED(sysc_mcck_pending) 299 bo BASED(sysc_mcck_pending)
318 tm __TI_flags+3(%r9),_TIF_NEED_RESCHED 300 tm __TI_flags+3(%r9),_TIF_NEED_RESCHED
319 bo BASED(sysc_reschedule) 301 bo BASED(sysc_reschedule)
320 tm __TI_flags+3(%r9),_TIF_SIGPENDING 302 tm __TI_flags+3(%r9),_TIF_SIGPENDING
321 bnz BASED(sysc_sigpending) 303 bo BASED(sysc_sigpending)
322 tm __TI_flags+3(%r9),_TIF_NOTIFY_RESUME 304 tm __TI_flags+3(%r9),_TIF_NOTIFY_RESUME
323 bnz BASED(sysc_notify_resume) 305 bo BASED(sysc_notify_resume)
324 tm __TI_flags+3(%r9),_TIF_RESTART_SVC 306 tm __TI_flags+3(%r9),_TIF_RESTART_SVC
325 bo BASED(sysc_restart) 307 bo BASED(sysc_restart)
326 tm __TI_flags+3(%r9),_TIF_SINGLE_STEP 308 tm __TI_flags+3(%r9),_TIF_SINGLE_STEP
327 bo BASED(sysc_singlestep) 309 bo BASED(sysc_singlestep)
328 b BASED(sysc_restore) 310 b BASED(sysc_return) # beware of critical section cleanup
329sysc_work_done:
330 311
331# 312#
332# _TIF_NEED_RESCHED is set, call schedule 313# _TIF_NEED_RESCHED is set, call schedule
333# 314#
334sysc_reschedule: 315sysc_reschedule:
335 l %r1,BASED(.Lschedule) 316 l %r1,BASED(.Lschedule)
336 la %r14,BASED(sysc_work_loop) 317 la %r14,BASED(sysc_return)
337 br %r1 # call scheduler 318 br %r1 # call scheduler
338 319
339# 320#
@@ -341,7 +322,7 @@ sysc_reschedule:
341# 322#
342sysc_mcck_pending: 323sysc_mcck_pending:
343 l %r1,BASED(.Ls390_handle_mcck) 324 l %r1,BASED(.Ls390_handle_mcck)
344 la %r14,BASED(sysc_work_loop) 325 la %r14,BASED(sysc_return)
345 br %r1 # TIF bit will be cleared by handler 326 br %r1 # TIF bit will be cleared by handler
346 327
347# 328#
@@ -356,7 +337,7 @@ sysc_sigpending:
356 bo BASED(sysc_restart) 337 bo BASED(sysc_restart)
357 tm __TI_flags+3(%r9),_TIF_SINGLE_STEP 338 tm __TI_flags+3(%r9),_TIF_SINGLE_STEP
358 bo BASED(sysc_singlestep) 339 bo BASED(sysc_singlestep)
359 b BASED(sysc_work_loop) 340 b BASED(sysc_return)
360 341
361# 342#
362# _TIF_NOTIFY_RESUME is set, call do_notify_resume 343# _TIF_NOTIFY_RESUME is set, call do_notify_resume
@@ -364,7 +345,7 @@ sysc_sigpending:
364sysc_notify_resume: 345sysc_notify_resume:
365 la %r2,SP_PTREGS(%r15) # load pt_regs 346 la %r2,SP_PTREGS(%r15) # load pt_regs
366 l %r1,BASED(.Ldo_notify_resume) 347 l %r1,BASED(.Ldo_notify_resume)
367 la %r14,BASED(sysc_work_loop) 348 la %r14,BASED(sysc_return)
368 br %r1 # call do_notify_resume 349 br %r1 # call do_notify_resume
369 350
370 351
@@ -459,11 +440,13 @@ kernel_execve:
459 br %r14 440 br %r14
460 # execve succeeded. 441 # execve succeeded.
4610: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts 4420: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts
443 TRACE_IRQS_OFF
462 l %r15,__LC_KERNEL_STACK # load ksp 444 l %r15,__LC_KERNEL_STACK # load ksp
463 s %r15,BASED(.Lc_spsize) # make room for registers & psw 445 s %r15,BASED(.Lc_spsize) # make room for registers & psw
464 l %r9,__LC_THREAD_INFO 446 l %r9,__LC_THREAD_INFO
465 mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs 447 mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs
466 xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) 448 xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
449 TRACE_IRQS_ON
467 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts 450 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
468 l %r1,BASED(.Lexecve_tail) 451 l %r1,BASED(.Lexecve_tail)
469 basr %r14,%r1 452 basr %r14,%r1
@@ -500,8 +483,8 @@ pgm_check_handler:
500 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 483 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
501 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER 484 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
502pgm_no_vtime: 485pgm_no_vtime:
486 TRACE_IRQS_CHECK_OFF
503 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct 487 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
504 TRACE_IRQS_OFF
505 l %r3,__LC_PGM_ILC # load program interruption code 488 l %r3,__LC_PGM_ILC # load program interruption code
506 la %r8,0x7f 489 la %r8,0x7f
507 nr %r8,%r3 490 nr %r8,%r3
@@ -510,8 +493,10 @@ pgm_do_call:
510 sll %r8,2 493 sll %r8,2
511 l %r7,0(%r8,%r7) # load address of handler routine 494 l %r7,0(%r8,%r7) # load address of handler routine
512 la %r2,SP_PTREGS(%r15) # address of register-save area 495 la %r2,SP_PTREGS(%r15) # address of register-save area
513 la %r14,BASED(sysc_return) 496 basr %r14,%r7 # branch to interrupt-handler
514 br %r7 # branch to interrupt-handler 497pgm_exit:
498 TRACE_IRQS_CHECK_ON
499 b BASED(sysc_return)
515 500
516# 501#
517# handle per exception 502# handle per exception
@@ -538,20 +523,28 @@ pgm_per_std:
538 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 523 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
539 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER 524 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
540pgm_no_vtime2: 525pgm_no_vtime2:
526 TRACE_IRQS_CHECK_OFF
541 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct 527 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
542 TRACE_IRQS_OFF
543 l %r1,__TI_task(%r9) 528 l %r1,__TI_task(%r9)
529 tm SP_PSW+1(%r15),0x01 # kernel per event ?
530 bz BASED(kernel_per)
544 mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID 531 mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
545 mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS 532 mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS
546 mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID 533 mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
547 oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP 534 oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
548 tm SP_PSW+1(%r15),0x01 # kernel per event ?
549 bz BASED(kernel_per)
550 l %r3,__LC_PGM_ILC # load program interruption code 535 l %r3,__LC_PGM_ILC # load program interruption code
551 la %r8,0x7f 536 la %r8,0x7f
552 nr %r8,%r3 # clear per-event-bit and ilc 537 nr %r8,%r3 # clear per-event-bit and ilc
553 be BASED(sysc_return) # only per or per+check ? 538 be BASED(pgm_exit2) # only per or per+check ?
554 b BASED(pgm_do_call) 539 l %r7,BASED(.Ljump_table)
540 sll %r8,2
541 l %r7,0(%r8,%r7) # load address of handler routine
542 la %r2,SP_PTREGS(%r15) # address of register-save area
543 basr %r14,%r7 # branch to interrupt-handler
544pgm_exit2:
545 TRACE_IRQS_ON
546 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
547 b BASED(sysc_return)
555 548
556# 549#
557# it was a single stepped SVC that is causing all the trouble 550# it was a single stepped SVC that is causing all the trouble
@@ -571,8 +564,8 @@ pgm_svcper:
571 mvc __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID 564 mvc __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID
572 oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP 565 oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
573 TRACE_IRQS_ON 566 TRACE_IRQS_ON
574 lm %r2,%r6,SP_R2(%r15) # load svc arguments
575 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts 567 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
568 lm %r2,%r6,SP_R2(%r15) # load svc arguments
576 b BASED(sysc_do_svc) 569 b BASED(sysc_do_svc)
577 570
578# 571#
@@ -583,8 +576,8 @@ kernel_per:
583 mvi SP_SVCNR+1(%r15),0xff 576 mvi SP_SVCNR+1(%r15),0xff
584 la %r2,SP_PTREGS(%r15) # address of register-save area 577 la %r2,SP_PTREGS(%r15) # address of register-save area
585 l %r1,BASED(.Lhandle_per) # load adr. of per handler 578 l %r1,BASED(.Lhandle_per) # load adr. of per handler
586 la %r14,BASED(sysc_restore)# load adr. of system return 579 basr %r14,%r1 # branch to do_single_step
587 br %r1 # branch to do_single_step 580 b BASED(pgm_exit)
588 581
589/* 582/*
590 * IO interrupt handler routine 583 * IO interrupt handler routine
@@ -603,134 +596,126 @@ io_int_handler:
603 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 596 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
604 mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER 597 mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
605io_no_vtime: 598io_no_vtime:
606 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
607 TRACE_IRQS_OFF 599 TRACE_IRQS_OFF
600 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
608 l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ 601 l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ
609 la %r2,SP_PTREGS(%r15) # address of register-save area 602 la %r2,SP_PTREGS(%r15) # address of register-save area
610 basr %r14,%r1 # branch to standard irq handler 603 basr %r14,%r1 # branch to standard irq handler
611io_return: 604io_return:
605 LOCKDEP_SYS_EXIT
606 TRACE_IRQS_ON
607io_tif:
612 tm __TI_flags+3(%r9),_TIF_WORK_INT 608 tm __TI_flags+3(%r9),_TIF_WORK_INT
613 bnz BASED(io_work) # there is work to do (signals etc.) 609 bnz BASED(io_work) # there is work to do (signals etc.)
614io_restore: 610io_restore:
615#ifdef CONFIG_TRACE_IRQFLAGS
616 la %r1,BASED(io_restore_trace_psw_addr)
617 l %r1,0(%r1)
618 lpsw 0(%r1)
619io_restore_trace:
620 TRACE_IRQS_CHECK
621 LOCKDEP_SYS_EXIT
622#endif
623io_leave:
624 RESTORE_ALL __LC_RETURN_PSW,0 611 RESTORE_ALL __LC_RETURN_PSW,0
625io_done: 612io_done:
626 613
627#ifdef CONFIG_TRACE_IRQFLAGS
628io_restore_trace_psw_addr:
629 .long io_restore_trace_psw
630
631 .section .data,"aw",@progbits
632 .align 8
633 .globl io_restore_trace_psw
634io_restore_trace_psw:
635 .long 0, io_restore_trace + 0x80000000
636 .previous
637#endif
638
639# 614#
640# switch to kernel stack, then check the TIF bits 615# There is work todo, find out in which context we have been interrupted:
616# 1) if we return to user space we can do all _TIF_WORK_INT work
617# 2) if we return to kernel code and preemptive scheduling is enabled check
618# the preemption counter and if it is zero call preempt_schedule_irq
619# Before any work can be done, a switch to the kernel stack is required.
641# 620#
642io_work: 621io_work:
643 tm SP_PSW+1(%r15),0x01 # returning to user ? 622 tm SP_PSW+1(%r15),0x01 # returning to user ?
644#ifndef CONFIG_PREEMPT 623 bo BASED(io_work_user) # yes -> do resched & signal
645 bno BASED(io_restore) # no-> skip resched & signal 624#ifdef CONFIG_PREEMPT
646#else
647 bnz BASED(io_work_user) # no -> check for preemptive scheduling
648 # check for preemptive scheduling 625 # check for preemptive scheduling
649 icm %r0,15,__TI_precount(%r9) 626 icm %r0,15,__TI_precount(%r9)
650 bnz BASED(io_restore) # preemption disabled 627 bnz BASED(io_restore) # preemption disabled
628 tm __TI_flags+3(%r9),_TIF_NEED_RESCHED
629 bno BASED(io_restore)
630 # switch to kernel stack
651 l %r1,SP_R15(%r15) 631 l %r1,SP_R15(%r15)
652 s %r1,BASED(.Lc_spsize) 632 s %r1,BASED(.Lc_spsize)
653 mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) 633 mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
654 xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain 634 xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
655 lr %r15,%r1 635 lr %r15,%r1
656io_resume_loop: 636 # TRACE_IRQS_ON already done at io_return, call
657 tm __TI_flags+3(%r9),_TIF_NEED_RESCHED 637 # TRACE_IRQS_OFF to keep things symmetrical
658 bno BASED(io_restore) 638 TRACE_IRQS_OFF
659 l %r1,BASED(.Lpreempt_schedule_irq) 639 l %r1,BASED(.Lpreempt_schedule_irq)
660 la %r14,BASED(io_resume_loop) 640 basr %r14,%r1 # call preempt_schedule_irq
661 br %r1 # call schedule 641 b BASED(io_return)
642#else
643 b BASED(io_restore)
662#endif 644#endif
663 645
646#
647# Need to do work before returning to userspace, switch to kernel stack
648#
664io_work_user: 649io_work_user:
665 l %r1,__LC_KERNEL_STACK 650 l %r1,__LC_KERNEL_STACK
666 s %r1,BASED(.Lc_spsize) 651 s %r1,BASED(.Lc_spsize)
667 mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) 652 mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
668 xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain 653 xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
669 lr %r15,%r1 654 lr %r15,%r1
655
670# 656#
671# One of the work bits is on. Find out which one. 657# One of the work bits is on. Find out which one.
672# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED 658# Checked are: _TIF_SIGPENDING, _TIF_NOTIFY_RESUME, _TIF_NEED_RESCHED
673# and _TIF_MCCK_PENDING 659# and _TIF_MCCK_PENDING
674# 660#
675io_work_loop: 661io_work_tif:
676 tm __TI_flags+3(%r9),_TIF_MCCK_PENDING 662 tm __TI_flags+3(%r9),_TIF_MCCK_PENDING
677 bo BASED(io_mcck_pending) 663 bo BASED(io_mcck_pending)
678 tm __TI_flags+3(%r9),_TIF_NEED_RESCHED 664 tm __TI_flags+3(%r9),_TIF_NEED_RESCHED
679 bo BASED(io_reschedule) 665 bo BASED(io_reschedule)
680 tm __TI_flags+3(%r9),_TIF_SIGPENDING 666 tm __TI_flags+3(%r9),_TIF_SIGPENDING
681 bnz BASED(io_sigpending) 667 bo BASED(io_sigpending)
682 tm __TI_flags+3(%r9),_TIF_NOTIFY_RESUME 668 tm __TI_flags+3(%r9),_TIF_NOTIFY_RESUME
683 bnz BASED(io_notify_resume) 669 bo BASED(io_notify_resume)
684 b BASED(io_restore) 670 b BASED(io_return) # beware of critical section cleanup
685io_work_done:
686 671
687# 672#
688# _TIF_MCCK_PENDING is set, call handler 673# _TIF_MCCK_PENDING is set, call handler
689# 674#
690io_mcck_pending: 675io_mcck_pending:
676 # TRACE_IRQS_ON already done at io_return
691 l %r1,BASED(.Ls390_handle_mcck) 677 l %r1,BASED(.Ls390_handle_mcck)
692 basr %r14,%r1 # TIF bit will be cleared by handler 678 basr %r14,%r1 # TIF bit will be cleared by handler
693 b BASED(io_work_loop) 679 TRACE_IRQS_OFF
680 b BASED(io_return)
694 681
695# 682#
696# _TIF_NEED_RESCHED is set, call schedule 683# _TIF_NEED_RESCHED is set, call schedule
697# 684#
698io_reschedule: 685io_reschedule:
699 TRACE_IRQS_ON 686 # TRACE_IRQS_ON already done at io_return
700 l %r1,BASED(.Lschedule) 687 l %r1,BASED(.Lschedule)
701 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts 688 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
702 basr %r14,%r1 # call scheduler 689 basr %r14,%r1 # call scheduler
703 stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts 690 stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
704 TRACE_IRQS_OFF 691 TRACE_IRQS_OFF
705 tm __TI_flags+3(%r9),_TIF_WORK_INT 692 b BASED(io_return)
706 bz BASED(io_restore) # there is no work to do
707 b BASED(io_work_loop)
708 693
709# 694#
710# _TIF_SIGPENDING is set, call do_signal 695# _TIF_SIGPENDING is set, call do_signal
711# 696#
712io_sigpending: 697io_sigpending:
713 TRACE_IRQS_ON 698 # TRACE_IRQS_ON already done at io_return
714 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts 699 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
715 la %r2,SP_PTREGS(%r15) # load pt_regs 700 la %r2,SP_PTREGS(%r15) # load pt_regs
716 l %r1,BASED(.Ldo_signal) 701 l %r1,BASED(.Ldo_signal)
717 basr %r14,%r1 # call do_signal 702 basr %r14,%r1 # call do_signal
718 stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts 703 stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
719 TRACE_IRQS_OFF 704 TRACE_IRQS_OFF
720 b BASED(io_work_loop) 705 b BASED(io_return)
721 706
722# 707#
723# _TIF_SIGPENDING is set, call do_signal 708# _TIF_SIGPENDING is set, call do_signal
724# 709#
725io_notify_resume: 710io_notify_resume:
726 TRACE_IRQS_ON 711 # TRACE_IRQS_ON already done at io_return
727 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts 712 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
728 la %r2,SP_PTREGS(%r15) # load pt_regs 713 la %r2,SP_PTREGS(%r15) # load pt_regs
729 l %r1,BASED(.Ldo_notify_resume) 714 l %r1,BASED(.Ldo_notify_resume)
730 basr %r14,%r1 # call do_signal 715 basr %r14,%r1 # call do_signal
731 stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts 716 stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
732 TRACE_IRQS_OFF 717 TRACE_IRQS_OFF
733 b BASED(io_work_loop) 718 b BASED(io_return)
734 719
735/* 720/*
736 * External interrupt handler routine 721 * External interrupt handler routine
@@ -765,15 +750,14 @@ __critical_end:
765 750
766 .globl mcck_int_handler 751 .globl mcck_int_handler
767mcck_int_handler: 752mcck_int_handler:
768 stck __LC_INT_CLOCK 753 stck __LC_MCCK_CLOCK
769 spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer 754 spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer
770 lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs 755 lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs
771 SAVE_ALL_BASE __LC_SAVE_AREA+32 756 SAVE_ALL_BASE __LC_SAVE_AREA+32
772 la %r12,__LC_MCK_OLD_PSW 757 la %r12,__LC_MCK_OLD_PSW
773 tm __LC_MCCK_CODE,0x80 # system damage? 758 tm __LC_MCCK_CODE,0x80 # system damage?
774 bo BASED(mcck_int_main) # yes -> rest of mcck code invalid 759 bo BASED(mcck_int_main) # yes -> rest of mcck code invalid
775 mvc __LC_SAVE_AREA+52(8),__LC_ASYNC_ENTER_TIMER 760 mvc __LC_MCCK_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA
776 mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA
777 tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? 761 tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid?
778 bo BASED(1f) 762 bo BASED(1f)
779 la %r14,__LC_SYNC_ENTER_TIMER 763 la %r14,__LC_SYNC_ENTER_TIMER
@@ -787,7 +771,7 @@ mcck_int_handler:
787 bl BASED(0f) 771 bl BASED(0f)
788 la %r14,__LC_LAST_UPDATE_TIMER 772 la %r14,__LC_LAST_UPDATE_TIMER
7890: spt 0(%r14) 7730: spt 0(%r14)
790 mvc __LC_ASYNC_ENTER_TIMER(8),0(%r14) 774 mvc __LC_MCCK_ENTER_TIMER(8),0(%r14)
7911: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? 7751: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid?
792 bno BASED(mcck_int_main) # no -> skip cleanup critical 776 bno BASED(mcck_int_main) # no -> skip cleanup critical
793 tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit 777 tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit
@@ -809,9 +793,9 @@ mcck_int_main:
809 bno BASED(mcck_no_vtime) # no -> skip cleanup critical 793 bno BASED(mcck_no_vtime) # no -> skip cleanup critical
810 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 794 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
811 bz BASED(mcck_no_vtime) 795 bz BASED(mcck_no_vtime)
812 UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER 796 UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER
813 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 797 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
814 mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER 798 mvc __LC_LAST_UPDATE_TIMER(8),__LC_MCCK_ENTER_TIMER
815mcck_no_vtime: 799mcck_no_vtime:
816 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct 800 l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
817 la %r2,SP_PTREGS(%r15) # load pt_regs 801 la %r2,SP_PTREGS(%r15) # load pt_regs
@@ -834,7 +818,6 @@ mcck_no_vtime:
834mcck_return: 818mcck_return:
835 mvc __LC_RETURN_MCCK_PSW(8),SP_PSW(%r15) # move return PSW 819 mvc __LC_RETURN_MCCK_PSW(8),SP_PSW(%r15) # move return PSW
836 ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit 820 ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit
837 mvc __LC_ASYNC_ENTER_TIMER(8),__LC_SAVE_AREA+52
838 tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? 821 tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ?
839 bno BASED(0f) 822 bno BASED(0f)
840 lm %r0,%r15,SP_R0(%r15) # load gprs 0-15 823 lm %r0,%r15,SP_R0(%r15) # load gprs 0-15
@@ -918,18 +901,14 @@ stack_overflow:
918 901
919cleanup_table_system_call: 902cleanup_table_system_call:
920 .long system_call + 0x80000000, sysc_do_svc + 0x80000000 903 .long system_call + 0x80000000, sysc_do_svc + 0x80000000
921cleanup_table_sysc_return: 904cleanup_table_sysc_tif:
922 .long sysc_return + 0x80000000, sysc_leave + 0x80000000 905 .long sysc_tif + 0x80000000, sysc_restore + 0x80000000
923cleanup_table_sysc_leave: 906cleanup_table_sysc_restore:
924 .long sysc_leave + 0x80000000, sysc_done + 0x80000000 907 .long sysc_restore + 0x80000000, sysc_done + 0x80000000
925cleanup_table_sysc_work_loop: 908cleanup_table_io_tif:
926 .long sysc_work_loop + 0x80000000, sysc_work_done + 0x80000000 909 .long io_tif + 0x80000000, io_restore + 0x80000000
927cleanup_table_io_return: 910cleanup_table_io_restore:
928 .long io_return + 0x80000000, io_leave + 0x80000000 911 .long io_restore + 0x80000000, io_done + 0x80000000
929cleanup_table_io_leave:
930 .long io_leave + 0x80000000, io_done + 0x80000000
931cleanup_table_io_work_loop:
932 .long io_work_loop + 0x80000000, io_work_done + 0x80000000
933 912
934cleanup_critical: 913cleanup_critical:
935 clc 4(4,%r12),BASED(cleanup_table_system_call) 914 clc 4(4,%r12),BASED(cleanup_table_system_call)
@@ -937,49 +916,40 @@ cleanup_critical:
937 clc 4(4,%r12),BASED(cleanup_table_system_call+4) 916 clc 4(4,%r12),BASED(cleanup_table_system_call+4)
938 bl BASED(cleanup_system_call) 917 bl BASED(cleanup_system_call)
9390: 9180:
940 clc 4(4,%r12),BASED(cleanup_table_sysc_return) 919 clc 4(4,%r12),BASED(cleanup_table_sysc_tif)
941 bl BASED(0f)
942 clc 4(4,%r12),BASED(cleanup_table_sysc_return+4)
943 bl BASED(cleanup_sysc_return)
9440:
945 clc 4(4,%r12),BASED(cleanup_table_sysc_leave)
946 bl BASED(0f) 920 bl BASED(0f)
947 clc 4(4,%r12),BASED(cleanup_table_sysc_leave+4) 921 clc 4(4,%r12),BASED(cleanup_table_sysc_tif+4)
948 bl BASED(cleanup_sysc_leave) 922 bl BASED(cleanup_sysc_tif)
9490: 9230:
950 clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop) 924 clc 4(4,%r12),BASED(cleanup_table_sysc_restore)
951 bl BASED(0f) 925 bl BASED(0f)
952 clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop+4) 926 clc 4(4,%r12),BASED(cleanup_table_sysc_restore+4)
953 bl BASED(cleanup_sysc_return) 927 bl BASED(cleanup_sysc_restore)
9540: 9280:
955 clc 4(4,%r12),BASED(cleanup_table_io_return) 929 clc 4(4,%r12),BASED(cleanup_table_io_tif)
956 bl BASED(0f) 930 bl BASED(0f)
957 clc 4(4,%r12),BASED(cleanup_table_io_return+4) 931 clc 4(4,%r12),BASED(cleanup_table_io_tif+4)
958 bl BASED(cleanup_io_return) 932 bl BASED(cleanup_io_tif)
9590: 9330:
960 clc 4(4,%r12),BASED(cleanup_table_io_leave) 934 clc 4(4,%r12),BASED(cleanup_table_io_restore)
961 bl BASED(0f) 935 bl BASED(0f)
962 clc 4(4,%r12),BASED(cleanup_table_io_leave+4) 936 clc 4(4,%r12),BASED(cleanup_table_io_restore+4)
963 bl BASED(cleanup_io_leave) 937 bl BASED(cleanup_io_restore)
9640:
965 clc 4(4,%r12),BASED(cleanup_table_io_work_loop)
966 bl BASED(0f)
967 clc 4(4,%r12),BASED(cleanup_table_io_work_loop+4)
968 bl BASED(cleanup_io_return)
9690: 9380:
970 br %r14 939 br %r14
971 940
972cleanup_system_call: 941cleanup_system_call:
973 mvc __LC_RETURN_PSW(8),0(%r12) 942 mvc __LC_RETURN_PSW(8),0(%r12)
974 c %r12,BASED(.Lmck_old_psw)
975 be BASED(0f)
976 la %r12,__LC_SAVE_AREA+16
977 b BASED(1f)
9780: la %r12,__LC_SAVE_AREA+32
9791:
980 clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+4) 943 clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+4)
981 bh BASED(0f) 944 bh BASED(0f)
945 mvc __LC_SYNC_ENTER_TIMER(8),__LC_MCCK_ENTER_TIMER
946 c %r12,BASED(.Lmck_old_psw)
947 be BASED(0f)
982 mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER 948 mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER
9490: c %r12,BASED(.Lmck_old_psw)
950 la %r12,__LC_SAVE_AREA+32
951 be BASED(0f)
952 la %r12,__LC_SAVE_AREA+16
9830: clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+8) 9530: clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+8)
984 bhe BASED(cleanup_vtime) 954 bhe BASED(cleanup_vtime)
985 clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn) 955 clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn)
@@ -1012,55 +982,54 @@ cleanup_system_call_insn:
1012 .long sysc_stime + 0x80000000 982 .long sysc_stime + 0x80000000
1013 .long sysc_update + 0x80000000 983 .long sysc_update + 0x80000000
1014 984
1015cleanup_sysc_return: 985cleanup_sysc_tif:
1016 mvc __LC_RETURN_PSW(4),0(%r12) 986 mvc __LC_RETURN_PSW(4),0(%r12)
1017 mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_sysc_return) 987 mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_sysc_tif)
1018 la %r12,__LC_RETURN_PSW 988 la %r12,__LC_RETURN_PSW
1019 br %r14 989 br %r14
1020 990
1021cleanup_sysc_leave: 991cleanup_sysc_restore:
1022 clc 4(4,%r12),BASED(cleanup_sysc_leave_insn) 992 clc 4(4,%r12),BASED(cleanup_sysc_restore_insn)
1023 be BASED(2f) 993 be BASED(2f)
994 mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER
995 c %r12,BASED(.Lmck_old_psw)
996 be BASED(0f)
1024 mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER 997 mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
1025 clc 4(4,%r12),BASED(cleanup_sysc_leave_insn+4) 9980: clc 4(4,%r12),BASED(cleanup_sysc_restore_insn+4)
1026 be BASED(2f) 999 be BASED(2f)
1027 mvc __LC_RETURN_PSW(8),SP_PSW(%r15) 1000 mvc __LC_RETURN_PSW(8),SP_PSW(%r15)
1028 c %r12,BASED(.Lmck_old_psw) 1001 c %r12,BASED(.Lmck_old_psw)
1029 bne BASED(0f) 1002 la %r12,__LC_SAVE_AREA+32
1030 mvc __LC_SAVE_AREA+32(16),SP_R12(%r15) 1003 be BASED(1f)
1031 b BASED(1f) 1004 la %r12,__LC_SAVE_AREA+16
10320: mvc __LC_SAVE_AREA+16(16),SP_R12(%r15) 10051: mvc 0(16,%r12),SP_R12(%r15)
10331: lm %r0,%r11,SP_R0(%r15) 1006 lm %r0,%r11,SP_R0(%r15)
1034 l %r15,SP_R15(%r15) 1007 l %r15,SP_R15(%r15)
10352: la %r12,__LC_RETURN_PSW 10082: la %r12,__LC_RETURN_PSW
1036 br %r14 1009 br %r14
1037cleanup_sysc_leave_insn: 1010cleanup_sysc_restore_insn:
1038 .long sysc_done - 4 + 0x80000000 1011 .long sysc_done - 4 + 0x80000000
1039 .long sysc_done - 8 + 0x80000000 1012 .long sysc_done - 8 + 0x80000000
1040 1013
1041cleanup_io_return: 1014cleanup_io_tif:
1042 mvc __LC_RETURN_PSW(4),0(%r12) 1015 mvc __LC_RETURN_PSW(4),0(%r12)
1043 mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_io_work_loop) 1016 mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_io_tif)
1044 la %r12,__LC_RETURN_PSW 1017 la %r12,__LC_RETURN_PSW
1045 br %r14 1018 br %r14
1046 1019
1047cleanup_io_leave: 1020cleanup_io_restore:
1048 clc 4(4,%r12),BASED(cleanup_io_leave_insn) 1021 clc 4(4,%r12),BASED(cleanup_io_restore_insn)
1049 be BASED(2f) 1022 be BASED(1f)
1050 mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER 1023 mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER
1051 clc 4(4,%r12),BASED(cleanup_io_leave_insn+4) 1024 clc 4(4,%r12),BASED(cleanup_io_restore_insn+4)
1052 be BASED(2f) 1025 be BASED(1f)
1053 mvc __LC_RETURN_PSW(8),SP_PSW(%r15) 1026 mvc __LC_RETURN_PSW(8),SP_PSW(%r15)
1054 c %r12,BASED(.Lmck_old_psw)
1055 bne BASED(0f)
1056 mvc __LC_SAVE_AREA+32(16),SP_R12(%r15) 1027 mvc __LC_SAVE_AREA+32(16),SP_R12(%r15)
1057 b BASED(1f) 1028 lm %r0,%r11,SP_R0(%r15)
10580: mvc __LC_SAVE_AREA+16(16),SP_R12(%r15)
10591: lm %r0,%r11,SP_R0(%r15)
1060 l %r15,SP_R15(%r15) 1029 l %r15,SP_R15(%r15)
10612: la %r12,__LC_RETURN_PSW 10301: la %r12,__LC_RETURN_PSW
1062 br %r14 1031 br %r14
1063cleanup_io_leave_insn: 1032cleanup_io_restore_insn:
1064 .long io_done - 4 + 0x80000000 1033 .long io_done - 4 + 0x80000000
1065 .long io_done - 8 + 0x80000000 1034 .long io_done - 8 + 0x80000000
1066 1035