diff options
Diffstat (limited to 'arch/s390/kernel/entry64.S')
-rw-r--r-- | arch/s390/kernel/entry64.S | 97 |
1 files changed, 88 insertions, 9 deletions
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 51527ab8c8f9..57ca75d0ad7f 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -7,6 +7,7 @@ | |||
7 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), | 7 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), |
8 | * Hartmut Penner (hp@de.ibm.com), | 8 | * Hartmut Penner (hp@de.ibm.com), |
9 | * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), | 9 | * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), |
10 | * Heiko Carstens <heiko.carstens@de.ibm.com> | ||
10 | */ | 11 | */ |
11 | 12 | ||
12 | #include <linux/sys.h> | 13 | #include <linux/sys.h> |
@@ -52,9 +53,9 @@ SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE | |||
52 | STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER | 53 | STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER |
53 | STACK_SIZE = 1 << STACK_SHIFT | 54 | STACK_SIZE = 1 << STACK_SHIFT |
54 | 55 | ||
55 | _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ | 56 | _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING | \ |
56 | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) | 57 | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) |
57 | _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED) | 58 | _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) |
58 | 59 | ||
59 | #define BASED(name) name-system_call(%r13) | 60 | #define BASED(name) name-system_call(%r13) |
60 | 61 | ||
@@ -114,7 +115,11 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED) | |||
114 | jz stack_overflow | 115 | jz stack_overflow |
115 | 3: | 116 | 3: |
116 | #endif | 117 | #endif |
117 | 2: aghi %r15,-SP_SIZE # make room for registers & psw | 118 | 2: |
119 | .endm | ||
120 | |||
121 | .macro CREATE_STACK_FRAME psworg,savearea | ||
122 | aghi %r15,-SP_SIZE # make room for registers & psw | ||
118 | mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack | 123 | mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack |
119 | la %r12,\psworg | 124 | la %r12,\psworg |
120 | stg %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 | 125 | stg %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 |
@@ -152,6 +157,13 @@ __switch_to: | |||
152 | je __switch_to_noper # we got away without bashing TLB's | 157 | je __switch_to_noper # we got away without bashing TLB's |
153 | lctlg %c9,%c11,__THREAD_per(%r3) # Nope we didn't | 158 | lctlg %c9,%c11,__THREAD_per(%r3) # Nope we didn't |
154 | __switch_to_noper: | 159 | __switch_to_noper: |
160 | lg %r4,__THREAD_info(%r2) # get thread_info of prev | ||
161 | tm __TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending? | ||
162 | jz __switch_to_no_mcck | ||
163 | ni __TI_flags+7(%r4),255-_TIF_MCCK_PENDING # clear flag in prev | ||
164 | lg %r4,__THREAD_info(%r3) # get thread_info of next | ||
165 | oi __TI_flags+7(%r4),_TIF_MCCK_PENDING # set it in next | ||
166 | __switch_to_no_mcck: | ||
155 | stmg %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task | 167 | stmg %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task |
156 | stg %r15,__THREAD_ksp(%r2) # store kernel stack to prev->tss.ksp | 168 | stg %r15,__THREAD_ksp(%r2) # store kernel stack to prev->tss.ksp |
157 | lg %r15,__THREAD_ksp(%r3) # load kernel stack from next->tss.ksp | 169 | lg %r15,__THREAD_ksp(%r3) # load kernel stack from next->tss.ksp |
@@ -176,6 +188,7 @@ system_call: | |||
176 | sysc_saveall: | 188 | sysc_saveall: |
177 | SAVE_ALL_BASE __LC_SAVE_AREA | 189 | SAVE_ALL_BASE __LC_SAVE_AREA |
178 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 | 190 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 |
191 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | ||
179 | llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore | 192 | llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore |
180 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 193 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
181 | sysc_vtime: | 194 | sysc_vtime: |
@@ -232,6 +245,8 @@ sysc_work_loop: | |||
232 | # One of the work bits is on. Find out which one. | 245 | # One of the work bits is on. Find out which one. |
233 | # | 246 | # |
234 | sysc_work: | 247 | sysc_work: |
248 | tm __TI_flags+7(%r9),_TIF_MCCK_PENDING | ||
249 | jo sysc_mcck_pending | ||
235 | tm __TI_flags+7(%r9),_TIF_NEED_RESCHED | 250 | tm __TI_flags+7(%r9),_TIF_NEED_RESCHED |
236 | jo sysc_reschedule | 251 | jo sysc_reschedule |
237 | tm __TI_flags+7(%r9),_TIF_SIGPENDING | 252 | tm __TI_flags+7(%r9),_TIF_SIGPENDING |
@@ -250,6 +265,13 @@ sysc_reschedule: | |||
250 | jg schedule # return point is sysc_return | 265 | jg schedule # return point is sysc_return |
251 | 266 | ||
252 | # | 267 | # |
268 | # _TIF_MCCK_PENDING is set, call handler | ||
269 | # | ||
270 | sysc_mcck_pending: | ||
271 | larl %r14,sysc_work_loop | ||
272 | jg s390_handle_mcck # TIF bit will be cleared by handler | ||
273 | |||
274 | # | ||
253 | # _TIF_SIGPENDING is set, call do_signal | 275 | # _TIF_SIGPENDING is set, call do_signal |
254 | # | 276 | # |
255 | sysc_sigpending: | 277 | sysc_sigpending: |
@@ -474,6 +496,7 @@ pgm_check_handler: | |||
474 | tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception | 496 | tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception |
475 | jnz pgm_per # got per exception -> special case | 497 | jnz pgm_per # got per exception -> special case |
476 | SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 | 498 | SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 |
499 | CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA | ||
477 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 500 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
478 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 501 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
479 | jz pgm_no_vtime | 502 | jz pgm_no_vtime |
@@ -512,6 +535,7 @@ pgm_per: | |||
512 | # | 535 | # |
513 | pgm_per_std: | 536 | pgm_per_std: |
514 | SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 | 537 | SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 |
538 | CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA | ||
515 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 539 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
516 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 540 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
517 | jz pgm_no_vtime2 | 541 | jz pgm_no_vtime2 |
@@ -537,6 +561,7 @@ pgm_no_vtime2: | |||
537 | # | 561 | # |
538 | pgm_svcper: | 562 | pgm_svcper: |
539 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 | 563 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 |
564 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | ||
540 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 565 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
541 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 566 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
542 | jz pgm_no_vtime3 | 567 | jz pgm_no_vtime3 |
@@ -564,6 +589,7 @@ io_int_handler: | |||
564 | stck __LC_INT_CLOCK | 589 | stck __LC_INT_CLOCK |
565 | SAVE_ALL_BASE __LC_SAVE_AREA+32 | 590 | SAVE_ALL_BASE __LC_SAVE_AREA+32 |
566 | SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+32,0 | 591 | SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+32,0 |
592 | CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+32 | ||
567 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 593 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
568 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 594 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
569 | jz io_no_vtime | 595 | jz io_no_vtime |
@@ -621,9 +647,11 @@ io_work: | |||
621 | lgr %r15,%r1 | 647 | lgr %r15,%r1 |
622 | # | 648 | # |
623 | # One of the work bits is on. Find out which one. | 649 | # One of the work bits is on. Find out which one. |
624 | # Checked are: _TIF_SIGPENDING and _TIF_NEED_RESCHED | 650 | # Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED and _TIF_MCCK_PENDING |
625 | # | 651 | # |
626 | io_work_loop: | 652 | io_work_loop: |
653 | tm __TI_flags+7(%r9),_TIF_MCCK_PENDING | ||
654 | jo io_mcck_pending | ||
627 | tm __TI_flags+7(%r9),_TIF_NEED_RESCHED | 655 | tm __TI_flags+7(%r9),_TIF_NEED_RESCHED |
628 | jo io_reschedule | 656 | jo io_reschedule |
629 | tm __TI_flags+7(%r9),_TIF_SIGPENDING | 657 | tm __TI_flags+7(%r9),_TIF_SIGPENDING |
@@ -631,6 +659,13 @@ io_work_loop: | |||
631 | j io_leave | 659 | j io_leave |
632 | 660 | ||
633 | # | 661 | # |
662 | # _TIF_MCCK_PENDING is set, call handler | ||
663 | # | ||
664 | io_mcck_pending: | ||
665 | larl %r14,io_work_loop | ||
666 | jg s390_handle_mcck # TIF bit will be cleared by handler | ||
667 | |||
668 | # | ||
634 | # _TIF_NEED_RESCHED is set, call schedule | 669 | # _TIF_NEED_RESCHED is set, call schedule |
635 | # | 670 | # |
636 | io_reschedule: | 671 | io_reschedule: |
@@ -661,6 +696,7 @@ ext_int_handler: | |||
661 | stck __LC_INT_CLOCK | 696 | stck __LC_INT_CLOCK |
662 | SAVE_ALL_BASE __LC_SAVE_AREA+32 | 697 | SAVE_ALL_BASE __LC_SAVE_AREA+32 |
663 | SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32,0 | 698 | SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32,0 |
699 | CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32 | ||
664 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 700 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
665 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 701 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
666 | jz ext_no_vtime | 702 | jz ext_no_vtime |
@@ -680,18 +716,60 @@ ext_no_vtime: | |||
680 | */ | 716 | */ |
681 | .globl mcck_int_handler | 717 | .globl mcck_int_handler |
682 | mcck_int_handler: | 718 | mcck_int_handler: |
683 | STORE_TIMER __LC_ASYNC_ENTER_TIMER | 719 | la %r1,4095 # revalidate r1 |
720 | spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer | ||
721 | lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs | ||
684 | SAVE_ALL_BASE __LC_SAVE_AREA+64 | 722 | SAVE_ALL_BASE __LC_SAVE_AREA+64 |
685 | SAVE_ALL __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64,0 | 723 | la %r12,__LC_MCK_OLD_PSW |
724 | tm __LC_MCCK_CODE,0x80 # system damage? | ||
725 | jo mcck_int_main # yes -> rest of mcck code invalid | ||
726 | tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? | ||
727 | jo 0f | ||
728 | spt __LC_LAST_UPDATE_TIMER | ||
686 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 729 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
687 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 730 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER |
731 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER | ||
732 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_EXIT_TIMER | ||
733 | 0: tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? | ||
734 | jno mcck_no_vtime # no -> no timer update | ||
735 | tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ? | ||
688 | jz mcck_no_vtime | 736 | jz mcck_no_vtime |
689 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER | 737 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER |
690 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 738 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
691 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER | 739 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER |
692 | mcck_no_vtime: | 740 | mcck_no_vtime: |
693 | #endif | 741 | #endif |
694 | brasl %r14,s390_do_machine_check | 742 | 0: |
743 | tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? | ||
744 | jno mcck_int_main # no -> skip cleanup critical | ||
745 | tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit | ||
746 | jnz mcck_int_main # from user -> load kernel stack | ||
747 | clc __LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_end) | ||
748 | jhe mcck_int_main | ||
749 | clc __LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_start) | ||
750 | jl mcck_int_main | ||
751 | brasl %r14,cleanup_critical | ||
752 | mcck_int_main: | ||
753 | lg %r14,__LC_PANIC_STACK # are we already on the panic stack? | ||
754 | slgr %r14,%r15 | ||
755 | srag %r14,%r14,PAGE_SHIFT | ||
756 | jz 0f | ||
757 | lg %r15,__LC_PANIC_STACK # load panic stack | ||
758 | 0: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64 | ||
759 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct | ||
760 | la %r2,SP_PTREGS(%r15) # load pt_regs | ||
761 | brasl %r14,s390_do_machine_check | ||
762 | tm SP_PSW+1(%r15),0x01 # returning to user ? | ||
763 | jno mcck_return | ||
764 | lg %r1,__LC_KERNEL_STACK # switch to kernel stack | ||
765 | aghi %r1,-SP_SIZE | ||
766 | mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) | ||
767 | xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain | ||
768 | lgr %r15,%r1 | ||
769 | stosm __SF_EMPTY(%r15),0x04 # turn dat on | ||
770 | tm __TI_flags+7(%r9),_TIF_MCCK_PENDING | ||
771 | jno mcck_return | ||
772 | brasl %r14,s390_handle_mcck | ||
695 | mcck_return: | 773 | mcck_return: |
696 | RESTORE_ALL 0 | 774 | RESTORE_ALL 0 |
697 | 775 | ||
@@ -775,7 +853,7 @@ cleanup_critical: | |||
775 | clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop) | 853 | clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop) |
776 | jl 0f | 854 | jl 0f |
777 | clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop+8) | 855 | clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop+8) |
778 | jl cleanup_sysc_leave | 856 | jl cleanup_sysc_return |
779 | 0: | 857 | 0: |
780 | br %r14 | 858 | br %r14 |
781 | 859 | ||
@@ -793,6 +871,7 @@ cleanup_system_call: | |||
793 | mvc __LC_SAVE_AREA(32),__LC_SAVE_AREA+32 | 871 | mvc __LC_SAVE_AREA(32),__LC_SAVE_AREA+32 |
794 | 0: stg %r13,__LC_SAVE_AREA+40 | 872 | 0: stg %r13,__LC_SAVE_AREA+40 |
795 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 | 873 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 |
874 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | ||
796 | stg %r15,__LC_SAVE_AREA+56 | 875 | stg %r15,__LC_SAVE_AREA+56 |
797 | llgh %r7,__LC_SVC_INT_CODE | 876 | llgh %r7,__LC_SVC_INT_CODE |
798 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 877 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |