diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/s390/kernel/entry64.S | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 7a2d22dda9ef..14eec6a9577e 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -80,14 +80,21 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) | |||
80 | #endif | 80 | #endif |
81 | .endm | 81 | .endm |
82 | 82 | ||
83 | .macro HANDLE_SIE_INTERCEPT scratch | 83 | .macro HANDLE_SIE_INTERCEPT scratch,pgmcheck |
84 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) | 84 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) |
85 | tmhh %r8,0x0001 # interrupting from user ? | 85 | tmhh %r8,0x0001 # interrupting from user ? |
86 | jnz .+42 | 86 | jnz .+42 |
87 | lgr \scratch,%r9 | 87 | lgr \scratch,%r9 |
88 | slg \scratch,BASED(.Lsie_loop) | 88 | slg \scratch,BASED(.Lsie_loop) |
89 | clg \scratch,BASED(.Lsie_length) | 89 | clg \scratch,BASED(.Lsie_length) |
90 | .if \pgmcheck | ||
91 | # Some program interrupts are suppressing (e.g. protection). | ||
92 | # We must also check the instruction after SIE in that case. | ||
93 | # do_protection_exception will rewind to rewind_pad | ||
94 | jh .+22 | ||
95 | .else | ||
90 | jhe .+22 | 96 | jhe .+22 |
97 | .endif | ||
91 | lg %r9,BASED(.Lsie_loop) | 98 | lg %r9,BASED(.Lsie_loop) |
92 | SPP BASED(.Lhost_id) # set host id | 99 | SPP BASED(.Lhost_id) # set host id |
93 | #endif | 100 | #endif |
@@ -390,7 +397,7 @@ ENTRY(pgm_check_handler) | |||
390 | lg %r12,__LC_THREAD_INFO | 397 | lg %r12,__LC_THREAD_INFO |
391 | larl %r13,system_call | 398 | larl %r13,system_call |
392 | lmg %r8,%r9,__LC_PGM_OLD_PSW | 399 | lmg %r8,%r9,__LC_PGM_OLD_PSW |
393 | HANDLE_SIE_INTERCEPT %r14 | 400 | HANDLE_SIE_INTERCEPT %r14,1 |
394 | tmhh %r8,0x0001 # test problem state bit | 401 | tmhh %r8,0x0001 # test problem state bit |
395 | jnz 1f # -> fault in user space | 402 | jnz 1f # -> fault in user space |
396 | tmhh %r8,0x4000 # PER bit set in old PSW ? | 403 | tmhh %r8,0x4000 # PER bit set in old PSW ? |
@@ -466,7 +473,7 @@ ENTRY(io_int_handler) | |||
466 | lg %r12,__LC_THREAD_INFO | 473 | lg %r12,__LC_THREAD_INFO |
467 | larl %r13,system_call | 474 | larl %r13,system_call |
468 | lmg %r8,%r9,__LC_IO_OLD_PSW | 475 | lmg %r8,%r9,__LC_IO_OLD_PSW |
469 | HANDLE_SIE_INTERCEPT %r14 | 476 | HANDLE_SIE_INTERCEPT %r14,0 |
470 | SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT | 477 | SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT |
471 | tmhh %r8,0x0001 # interrupting from user? | 478 | tmhh %r8,0x0001 # interrupting from user? |
472 | jz io_skip | 479 | jz io_skip |
@@ -612,7 +619,7 @@ ENTRY(ext_int_handler) | |||
612 | lg %r12,__LC_THREAD_INFO | 619 | lg %r12,__LC_THREAD_INFO |
613 | larl %r13,system_call | 620 | larl %r13,system_call |
614 | lmg %r8,%r9,__LC_EXT_OLD_PSW | 621 | lmg %r8,%r9,__LC_EXT_OLD_PSW |
615 | HANDLE_SIE_INTERCEPT %r14 | 622 | HANDLE_SIE_INTERCEPT %r14,0 |
616 | SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT | 623 | SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT |
617 | tmhh %r8,0x0001 # interrupting from user ? | 624 | tmhh %r8,0x0001 # interrupting from user ? |
618 | jz ext_skip | 625 | jz ext_skip |
@@ -660,7 +667,7 @@ ENTRY(mcck_int_handler) | |||
660 | lg %r12,__LC_THREAD_INFO | 667 | lg %r12,__LC_THREAD_INFO |
661 | larl %r13,system_call | 668 | larl %r13,system_call |
662 | lmg %r8,%r9,__LC_MCK_OLD_PSW | 669 | lmg %r8,%r9,__LC_MCK_OLD_PSW |
663 | HANDLE_SIE_INTERCEPT %r14 | 670 | HANDLE_SIE_INTERCEPT %r14,0 |
664 | tm __LC_MCCK_CODE,0x80 # system damage? | 671 | tm __LC_MCCK_CODE,0x80 # system damage? |
665 | jo mcck_panic # yes -> rest of mcck code invalid | 672 | jo mcck_panic # yes -> rest of mcck code invalid |
666 | lghi %r14,__LC_CPU_TIMER_SAVE_AREA | 673 | lghi %r14,__LC_CPU_TIMER_SAVE_AREA |
@@ -959,6 +966,13 @@ ENTRY(sie64a) | |||
959 | stg %r3,__SF_EMPTY+8(%r15) # save guest register save area | 966 | stg %r3,__SF_EMPTY+8(%r15) # save guest register save area |
960 | xc __SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # host id == 0 | 967 | xc __SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # host id == 0 |
961 | lmg %r0,%r13,0(%r3) # load guest gprs 0-13 | 968 | lmg %r0,%r13,0(%r3) # load guest gprs 0-13 |
969 | # some program checks are suppressing. C code (e.g. do_protection_exception) | ||
970 | # will rewind the PSW by the ILC, which is 4 bytes in case of SIE. Other | ||
971 | # instructions in the sie_loop should not cause program interrupts. So | ||
972 | # lets use a nop (47 00 00 00) as a landing pad. | ||
973 | # See also HANDLE_SIE_INTERCEPT | ||
974 | rewind_pad: | ||
975 | nop 0 | ||
962 | sie_loop: | 976 | sie_loop: |
963 | lg %r14,__LC_THREAD_INFO # pointer thread_info struct | 977 | lg %r14,__LC_THREAD_INFO # pointer thread_info struct |
964 | tm __TI_flags+7(%r14),_TIF_EXIT_SIE | 978 | tm __TI_flags+7(%r14),_TIF_EXIT_SIE |
@@ -998,6 +1012,7 @@ sie_fault: | |||
998 | .Lhost_id: | 1012 | .Lhost_id: |
999 | .quad 0 | 1013 | .quad 0 |
1000 | 1014 | ||
1015 | EX_TABLE(rewind_pad,sie_fault) | ||
1001 | EX_TABLE(sie_loop,sie_fault) | 1016 | EX_TABLE(sie_loop,sie_fault) |
1002 | #endif | 1017 | #endif |
1003 | 1018 | ||