diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2005-06-25 17:55:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-25 19:24:37 -0400 |
commit | 77fa22450de00d535de2cc8be653983560828000 (patch) | |
tree | 61644edb2263c3d0db3ea9e9518c6f76a60039e0 /arch/s390 | |
parent | f901e5d1e06b3326c100c5d0df43656311befb81 (diff) |
[PATCH] s390: improved machine check handling
Improved machine check handling. Kernel is now able to receive machine checks
while in kernel mode (system call, interrupt and program check handling).
Also register validation is now performed.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/kernel/entry.S | 102 | ||||
-rw-r--r-- | arch/s390/kernel/entry64.S | 97 | ||||
-rw-r--r-- | arch/s390/kernel/process.c | 46 | ||||
-rw-r--r-- | arch/s390/kernel/setup.c | 13 | ||||
-rw-r--r-- | arch/s390/kernel/smp.c | 13 |
5 files changed, 215 insertions, 56 deletions
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index c0e09b33febe..5b262b5d869f 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.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> |
@@ -49,9 +50,9 @@ SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC | |||
49 | SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP | 50 | SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP |
50 | SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE | 51 | SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE |
51 | 52 | ||
52 | _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ | 53 | _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING | \ |
53 | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) | 54 | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) |
54 | _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED) | 55 | _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) |
55 | 56 | ||
56 | STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER | 57 | STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER |
57 | STACK_SIZE = 1 << STACK_SHIFT | 58 | STACK_SIZE = 1 << STACK_SHIFT |
@@ -121,7 +122,11 @@ STACK_SIZE = 1 << STACK_SHIFT | |||
121 | bz BASED(stack_overflow) | 122 | bz BASED(stack_overflow) |
122 | 3: | 123 | 3: |
123 | #endif | 124 | #endif |
124 | 2: s %r15,BASED(.Lc_spsize) # make room for registers & psw | 125 | 2: |
126 | .endm | ||
127 | |||
128 | .macro CREATE_STACK_FRAME psworg,savearea | ||
129 | s %r15,BASED(.Lc_spsize) # make room for registers & psw | ||
125 | mvc SP_PSW(8,%r15),0(%r12) # move user PSW to stack | 130 | mvc SP_PSW(8,%r15),0(%r12) # move user PSW to stack |
126 | la %r12,\psworg | 131 | la %r12,\psworg |
127 | st %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 | 132 | st %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 |
@@ -161,6 +166,13 @@ __switch_to_base: | |||
161 | be __switch_to_noper-__switch_to_base(%r1) # we got away w/o bashing TLB's | 166 | be __switch_to_noper-__switch_to_base(%r1) # we got away w/o bashing TLB's |
162 | lctl %c9,%c11,__THREAD_per(%r3) # Nope we didn't | 167 | lctl %c9,%c11,__THREAD_per(%r3) # Nope we didn't |
163 | __switch_to_noper: | 168 | __switch_to_noper: |
169 | l %r4,__THREAD_info(%r2) # get thread_info of prev | ||
170 | tm __TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending? | ||
171 | bz __switch_to_no_mcck-__switch_to_base(%r1) | ||
172 | ni __TI_flags+3(%r4),255-_TIF_MCCK_PENDING # clear flag in prev | ||
173 | l %r4,__THREAD_info(%r3) # get thread_info of next | ||
174 | oi __TI_flags+3(%r4),_TIF_MCCK_PENDING # set it in next | ||
175 | __switch_to_no_mcck: | ||
164 | stm %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task | 176 | stm %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task |
165 | st %r15,__THREAD_ksp(%r2) # store kernel stack to prev->tss.ksp | 177 | st %r15,__THREAD_ksp(%r2) # store kernel stack to prev->tss.ksp |
166 | l %r15,__THREAD_ksp(%r3) # load kernel stack from next->tss.ksp | 178 | l %r15,__THREAD_ksp(%r3) # load kernel stack from next->tss.ksp |
@@ -185,6 +197,7 @@ system_call: | |||
185 | sysc_saveall: | 197 | sysc_saveall: |
186 | SAVE_ALL_BASE __LC_SAVE_AREA | 198 | SAVE_ALL_BASE __LC_SAVE_AREA |
187 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 | 199 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 |
200 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | ||
188 | lh %r7,0x8a # get svc number from lowcore | 201 | lh %r7,0x8a # get svc number from lowcore |
189 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 202 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
190 | sysc_vtime: | 203 | sysc_vtime: |
@@ -234,6 +247,8 @@ sysc_work_loop: | |||
234 | # One of the work bits is on. Find out which one. | 247 | # One of the work bits is on. Find out which one. |
235 | # | 248 | # |
236 | sysc_work: | 249 | sysc_work: |
250 | tm __TI_flags+3(%r9),_TIF_MCCK_PENDING | ||
251 | bo BASED(sysc_mcck_pending) | ||
237 | tm __TI_flags+3(%r9),_TIF_NEED_RESCHED | 252 | tm __TI_flags+3(%r9),_TIF_NEED_RESCHED |
238 | bo BASED(sysc_reschedule) | 253 | bo BASED(sysc_reschedule) |
239 | tm __TI_flags+3(%r9),_TIF_SIGPENDING | 254 | tm __TI_flags+3(%r9),_TIF_SIGPENDING |
@@ -253,6 +268,14 @@ sysc_reschedule: | |||
253 | br %r1 # call scheduler | 268 | br %r1 # call scheduler |
254 | 269 | ||
255 | # | 270 | # |
271 | # _TIF_MCCK_PENDING is set, call handler | ||
272 | # | ||
273 | sysc_mcck_pending: | ||
274 | l %r1,BASED(.Ls390_handle_mcck) | ||
275 | la %r14,BASED(sysc_work_loop) | ||
276 | br %r1 # TIF bit will be cleared by handler | ||
277 | |||
278 | # | ||
256 | # _TIF_SIGPENDING is set, call do_signal | 279 | # _TIF_SIGPENDING is set, call do_signal |
257 | # | 280 | # |
258 | sysc_sigpending: | 281 | sysc_sigpending: |
@@ -430,6 +453,7 @@ pgm_check_handler: | |||
430 | tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception | 453 | tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception |
431 | bnz BASED(pgm_per) # got per exception -> special case | 454 | bnz BASED(pgm_per) # got per exception -> special case |
432 | SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 | 455 | SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 |
456 | CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA | ||
433 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 457 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
434 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 458 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
435 | bz BASED(pgm_no_vtime) | 459 | bz BASED(pgm_no_vtime) |
@@ -468,6 +492,7 @@ pgm_per: | |||
468 | # | 492 | # |
469 | pgm_per_std: | 493 | pgm_per_std: |
470 | SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 | 494 | SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 |
495 | CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA | ||
471 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 496 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
472 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 497 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
473 | bz BASED(pgm_no_vtime2) | 498 | bz BASED(pgm_no_vtime2) |
@@ -493,6 +518,7 @@ pgm_no_vtime2: | |||
493 | # | 518 | # |
494 | pgm_svcper: | 519 | pgm_svcper: |
495 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 | 520 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 |
521 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | ||
496 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 522 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
497 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 523 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
498 | bz BASED(pgm_no_vtime3) | 524 | bz BASED(pgm_no_vtime3) |
@@ -521,6 +547,7 @@ io_int_handler: | |||
521 | stck __LC_INT_CLOCK | 547 | stck __LC_INT_CLOCK |
522 | SAVE_ALL_BASE __LC_SAVE_AREA+16 | 548 | SAVE_ALL_BASE __LC_SAVE_AREA+16 |
523 | SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+16,0 | 549 | SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+16,0 |
550 | CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+16 | ||
524 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 551 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
525 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 552 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
526 | bz BASED(io_no_vtime) | 553 | bz BASED(io_no_vtime) |
@@ -578,9 +605,11 @@ io_work: | |||
578 | lr %r15,%r1 | 605 | lr %r15,%r1 |
579 | # | 606 | # |
580 | # One of the work bits is on. Find out which one. | 607 | # One of the work bits is on. Find out which one. |
581 | # Checked are: _TIF_SIGPENDING and _TIF_NEED_RESCHED | 608 | # Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED and _TIF_MCCK_PENDING |
582 | # | 609 | # |
583 | io_work_loop: | 610 | io_work_loop: |
611 | tm __TI_flags+3(%r9),_TIF_MCCK_PENDING | ||
612 | bo BASED(io_mcck_pending) | ||
584 | tm __TI_flags+3(%r9),_TIF_NEED_RESCHED | 613 | tm __TI_flags+3(%r9),_TIF_NEED_RESCHED |
585 | bo BASED(io_reschedule) | 614 | bo BASED(io_reschedule) |
586 | tm __TI_flags+3(%r9),_TIF_SIGPENDING | 615 | tm __TI_flags+3(%r9),_TIF_SIGPENDING |
@@ -588,6 +617,14 @@ io_work_loop: | |||
588 | b BASED(io_leave) | 617 | b BASED(io_leave) |
589 | 618 | ||
590 | # | 619 | # |
620 | # _TIF_MCCK_PENDING is set, call handler | ||
621 | # | ||
622 | io_mcck_pending: | ||
623 | l %r1,BASED(.Ls390_handle_mcck) | ||
624 | l %r14,BASED(io_work_loop) | ||
625 | br %r1 # TIF bit will be cleared by handler | ||
626 | |||
627 | # | ||
591 | # _TIF_NEED_RESCHED is set, call schedule | 628 | # _TIF_NEED_RESCHED is set, call schedule |
592 | # | 629 | # |
593 | io_reschedule: | 630 | io_reschedule: |
@@ -621,6 +658,7 @@ ext_int_handler: | |||
621 | stck __LC_INT_CLOCK | 658 | stck __LC_INT_CLOCK |
622 | SAVE_ALL_BASE __LC_SAVE_AREA+16 | 659 | SAVE_ALL_BASE __LC_SAVE_AREA+16 |
623 | SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16,0 | 660 | SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16,0 |
661 | CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16 | ||
624 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 662 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
625 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 663 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
626 | bz BASED(ext_no_vtime) | 664 | bz BASED(ext_no_vtime) |
@@ -642,19 +680,62 @@ ext_no_vtime: | |||
642 | 680 | ||
643 | .globl mcck_int_handler | 681 | .globl mcck_int_handler |
644 | mcck_int_handler: | 682 | mcck_int_handler: |
645 | STORE_TIMER __LC_ASYNC_ENTER_TIMER | 683 | spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer |
684 | lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs | ||
646 | SAVE_ALL_BASE __LC_SAVE_AREA+32 | 685 | SAVE_ALL_BASE __LC_SAVE_AREA+32 |
647 | SAVE_ALL __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32,0 | 686 | la %r12,__LC_MCK_OLD_PSW |
687 | tm __LC_MCCK_CODE,0x80 # system damage? | ||
688 | bo BASED(mcck_int_main) # yes -> rest of mcck code invalid | ||
689 | tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? | ||
690 | bo BASED(0f) | ||
691 | spt __LC_LAST_UPDATE_TIMER # revalidate cpu timer | ||
648 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 692 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
649 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 693 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER |
694 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER | ||
695 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_EXIT_TIMER | ||
696 | 0: tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? | ||
697 | bno BASED(mcck_no_vtime) # no -> skip cleanup critical | ||
698 | tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ? | ||
650 | bz BASED(mcck_no_vtime) | 699 | bz BASED(mcck_no_vtime) |
651 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER | 700 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER |
652 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 701 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
653 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER | 702 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER |
654 | mcck_no_vtime: | 703 | mcck_no_vtime: |
655 | #endif | 704 | #endif |
705 | 0: | ||
706 | tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? | ||
707 | bno BASED(mcck_int_main) # no -> skip cleanup critical | ||
708 | tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit | ||
709 | bnz BASED(mcck_int_main) # from user -> load async stack | ||
710 | clc __LC_MCK_OLD_PSW+4(4),BASED(.Lcritical_end) | ||
711 | bhe BASED(mcck_int_main) | ||
712 | clc __LC_MCK_OLD_PSW+4(4),BASED(.Lcritical_start) | ||
713 | bl BASED(mcck_int_main) | ||
714 | l %r14,BASED(.Lcleanup_critical) | ||
715 | basr %r14,%r14 | ||
716 | mcck_int_main: | ||
717 | l %r14,__LC_PANIC_STACK # are we already on the panic stack? | ||
718 | slr %r14,%r15 | ||
719 | sra %r14,PAGE_SHIFT | ||
720 | be BASED(0f) | ||
721 | l %r15,__LC_PANIC_STACK # load panic stack | ||
722 | 0: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32 | ||
723 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct | ||
724 | la %r2,SP_PTREGS(%r15) # load pt_regs | ||
656 | l %r1,BASED(.Ls390_mcck) | 725 | l %r1,BASED(.Ls390_mcck) |
657 | basr %r14,%r1 # call machine check handler | 726 | basr %r14,%r1 # call machine check handler |
727 | tm SP_PSW+1(%r15),0x01 # returning to user ? | ||
728 | bno BASED(mcck_return) | ||
729 | l %r1,__LC_KERNEL_STACK # switch to kernel stack | ||
730 | s %r1,BASED(.Lc_spsize) | ||
731 | mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) | ||
732 | xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain | ||
733 | lr %r15,%r1 | ||
734 | stosm __SF_EMPTY(%r15),0x04 # turn dat on | ||
735 | tm __TI_flags+3(%r9),_TIF_MCCK_PENDING | ||
736 | bno BASED(mcck_return) | ||
737 | l %r1,BASED(.Ls390_handle_mcck) | ||
738 | basr %r14,%r1 # call machine check handler | ||
658 | mcck_return: | 739 | mcck_return: |
659 | RESTORE_ALL 0 | 740 | RESTORE_ALL 0 |
660 | 741 | ||
@@ -742,7 +823,7 @@ cleanup_critical: | |||
742 | clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop) | 823 | clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop) |
743 | bl BASED(0f) | 824 | bl BASED(0f) |
744 | clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop+4) | 825 | clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop+4) |
745 | bl BASED(cleanup_sysc_leave) | 826 | bl BASED(cleanup_sysc_return) |
746 | 0: | 827 | 0: |
747 | br %r14 | 828 | br %r14 |
748 | 829 | ||
@@ -760,6 +841,7 @@ cleanup_system_call: | |||
760 | mvc __LC_SAVE_AREA(16),__LC_SAVE_AREA+16 | 841 | mvc __LC_SAVE_AREA(16),__LC_SAVE_AREA+16 |
761 | 0: st %r13,__LC_SAVE_AREA+20 | 842 | 0: st %r13,__LC_SAVE_AREA+20 |
762 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 | 843 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 |
844 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | ||
763 | st %r15,__LC_SAVE_AREA+28 | 845 | st %r15,__LC_SAVE_AREA+28 |
764 | lh %r7,0x8a | 846 | lh %r7,0x8a |
765 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 847 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
@@ -834,6 +916,8 @@ cleanup_sysc_leave_insn: | |||
834 | * Symbol constants | 916 | * Symbol constants |
835 | */ | 917 | */ |
836 | .Ls390_mcck: .long s390_do_machine_check | 918 | .Ls390_mcck: .long s390_do_machine_check |
919 | .Ls390_handle_mcck: | ||
920 | .long s390_handle_mcck | ||
837 | .Ldo_IRQ: .long do_IRQ | 921 | .Ldo_IRQ: .long do_IRQ |
838 | .Ldo_extint: .long do_extint | 922 | .Ldo_extint: .long do_extint |
839 | .Ldo_signal: .long do_signal | 923 | .Ldo_signal: .long do_signal |
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 |
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 7aea25d6e300..9f3dff6c0b72 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c | |||
@@ -91,13 +91,12 @@ void do_monitor_call(struct pt_regs *regs, long interruption_code) | |||
91 | (void *)(long) smp_processor_id()); | 91 | (void *)(long) smp_processor_id()); |
92 | } | 92 | } |
93 | 93 | ||
94 | extern void s390_handle_mcck(void); | ||
94 | /* | 95 | /* |
95 | * The idle loop on a S390... | 96 | * The idle loop on a S390... |
96 | */ | 97 | */ |
97 | void default_idle(void) | 98 | void default_idle(void) |
98 | { | 99 | { |
99 | psw_t wait_psw; | ||
100 | unsigned long reg; | ||
101 | int cpu, rc; | 100 | int cpu, rc; |
102 | 101 | ||
103 | local_irq_disable(); | 102 | local_irq_disable(); |
@@ -125,38 +124,17 @@ void default_idle(void) | |||
125 | cpu_die(); | 124 | cpu_die(); |
126 | #endif | 125 | #endif |
127 | 126 | ||
128 | /* | 127 | local_mcck_disable(); |
129 | * Wait for external, I/O or machine check interrupt and | 128 | if (test_thread_flag(TIF_MCCK_PENDING)) { |
130 | * switch off machine check bit after the wait has ended. | 129 | local_mcck_enable(); |
131 | */ | 130 | local_irq_enable(); |
132 | wait_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK | PSW_MASK_WAIT | | 131 | s390_handle_mcck(); |
133 | PSW_MASK_IO | PSW_MASK_EXT; | 132 | return; |
134 | #ifndef CONFIG_ARCH_S390X | 133 | } |
135 | asm volatile ( | 134 | |
136 | " basr %0,0\n" | 135 | /* Wait for external, I/O or machine check interrupt. */ |
137 | "0: la %0,1f-0b(%0)\n" | 136 | __load_psw_mask(PSW_KERNEL_BITS | PSW_MASK_WAIT | |
138 | " st %0,4(%1)\n" | 137 | PSW_MASK_IO | PSW_MASK_EXT); |
139 | " oi 4(%1),0x80\n" | ||
140 | " lpsw 0(%1)\n" | ||
141 | "1: la %0,2f-1b(%0)\n" | ||
142 | " st %0,4(%1)\n" | ||
143 | " oi 4(%1),0x80\n" | ||
144 | " ni 1(%1),0xf9\n" | ||
145 | " lpsw 0(%1)\n" | ||
146 | "2:" | ||
147 | : "=&a" (reg) : "a" (&wait_psw) : "memory", "cc" ); | ||
148 | #else /* CONFIG_ARCH_S390X */ | ||
149 | asm volatile ( | ||
150 | " larl %0,0f\n" | ||
151 | " stg %0,8(%1)\n" | ||
152 | " lpswe 0(%1)\n" | ||
153 | "0: larl %0,1f\n" | ||
154 | " stg %0,8(%1)\n" | ||
155 | " ni 1(%1),0xf9\n" | ||
156 | " lpswe 0(%1)\n" | ||
157 | "1:" | ||
158 | : "=&a" (reg) : "a" (&wait_psw) : "memory", "cc" ); | ||
159 | #endif /* CONFIG_ARCH_S390X */ | ||
160 | } | 138 | } |
161 | 139 | ||
162 | void cpu_idle(void) | 140 | void cpu_idle(void) |
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index df83215beac3..eb7be0ad7175 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -414,7 +414,8 @@ setup_lowcore(void) | |||
414 | lc->program_new_psw.mask = PSW_KERNEL_BITS; | 414 | lc->program_new_psw.mask = PSW_KERNEL_BITS; |
415 | lc->program_new_psw.addr = | 415 | lc->program_new_psw.addr = |
416 | PSW_ADDR_AMODE | (unsigned long)pgm_check_handler; | 416 | PSW_ADDR_AMODE | (unsigned long)pgm_check_handler; |
417 | lc->mcck_new_psw.mask = PSW_KERNEL_BITS; | 417 | lc->mcck_new_psw.mask = |
418 | PSW_KERNEL_BITS & ~PSW_MASK_MCHECK & ~PSW_MASK_DAT; | ||
418 | lc->mcck_new_psw.addr = | 419 | lc->mcck_new_psw.addr = |
419 | PSW_ADDR_AMODE | (unsigned long) mcck_int_handler; | 420 | PSW_ADDR_AMODE | (unsigned long) mcck_int_handler; |
420 | lc->io_new_psw.mask = PSW_KERNEL_BITS; | 421 | lc->io_new_psw.mask = PSW_KERNEL_BITS; |
@@ -424,12 +425,18 @@ setup_lowcore(void) | |||
424 | lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE; | 425 | lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE; |
425 | lc->async_stack = (unsigned long) | 426 | lc->async_stack = (unsigned long) |
426 | __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE; | 427 | __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE; |
427 | #ifdef CONFIG_CHECK_STACK | ||
428 | lc->panic_stack = (unsigned long) | 428 | lc->panic_stack = (unsigned long) |
429 | __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE; | 429 | __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE; |
430 | #endif | ||
431 | lc->current_task = (unsigned long) init_thread_union.thread_info.task; | 430 | lc->current_task = (unsigned long) init_thread_union.thread_info.task; |
432 | lc->thread_info = (unsigned long) &init_thread_union; | 431 | lc->thread_info = (unsigned long) &init_thread_union; |
432 | #ifndef CONFIG_ARCH_S390X | ||
433 | if (MACHINE_HAS_IEEE) { | ||
434 | lc->extended_save_area_addr = (__u32) | ||
435 | __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0); | ||
436 | /* enable extended save area */ | ||
437 | ctl_set_bit(14, 29); | ||
438 | } | ||
439 | #endif | ||
433 | #ifdef CONFIG_ARCH_S390X | 440 | #ifdef CONFIG_ARCH_S390X |
434 | if (MACHINE_HAS_DIAG44) | 441 | if (MACHINE_HAS_DIAG44) |
435 | lc->diag44_opcode = 0x83000044; | 442 | lc->diag44_opcode = 0x83000044; |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 93c71fef99dc..50c335067cfe 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -773,13 +773,24 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
773 | 773 | ||
774 | *(lowcore_ptr[i]) = S390_lowcore; | 774 | *(lowcore_ptr[i]) = S390_lowcore; |
775 | lowcore_ptr[i]->async_stack = stack + (ASYNC_SIZE); | 775 | lowcore_ptr[i]->async_stack = stack + (ASYNC_SIZE); |
776 | #ifdef CONFIG_CHECK_STACK | ||
777 | stack = __get_free_pages(GFP_KERNEL,0); | 776 | stack = __get_free_pages(GFP_KERNEL,0); |
778 | if (stack == 0ULL) | 777 | if (stack == 0ULL) |
779 | panic("smp_boot_cpus failed to allocate memory\n"); | 778 | panic("smp_boot_cpus failed to allocate memory\n"); |
780 | lowcore_ptr[i]->panic_stack = stack + (PAGE_SIZE); | 779 | lowcore_ptr[i]->panic_stack = stack + (PAGE_SIZE); |
780 | #ifndef __s390x__ | ||
781 | if (MACHINE_HAS_IEEE) { | ||
782 | lowcore_ptr[i]->extended_save_area_addr = | ||
783 | (__u32) __get_free_pages(GFP_KERNEL,0); | ||
784 | if (lowcore_ptr[i]->extended_save_area_addr == 0) | ||
785 | panic("smp_boot_cpus failed to " | ||
786 | "allocate memory\n"); | ||
787 | } | ||
781 | #endif | 788 | #endif |
782 | } | 789 | } |
790 | #ifndef __s390x__ | ||
791 | if (MACHINE_HAS_IEEE) | ||
792 | ctl_set_bit(14, 29); /* enable extended save area */ | ||
793 | #endif | ||
783 | set_prefix((u32)(unsigned long) lowcore_ptr[smp_processor_id()]); | 794 | set_prefix((u32)(unsigned long) lowcore_ptr[smp_processor_id()]); |
784 | 795 | ||
785 | for_each_cpu(cpu) | 796 | for_each_cpu(cpu) |