diff options
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r-- | arch/s390/kernel/asm-offsets.c | 4 | ||||
-rw-r--r-- | arch/s390/kernel/entry.S | 12 | ||||
-rw-r--r-- | arch/s390/kernel/entry.h | 2 | ||||
-rw-r--r-- | arch/s390/kernel/entry64.S | 97 | ||||
-rw-r--r-- | arch/s390/kernel/irq.c | 8 | ||||
-rw-r--r-- | arch/s390/kernel/perf_event.c | 52 | ||||
-rw-r--r-- | arch/s390/kernel/s390_ksyms.c | 1 | ||||
-rw-r--r-- | arch/s390/kernel/smp.c | 5 |
8 files changed, 125 insertions, 56 deletions
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 7a82f9f70100..2416138ebd3e 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #define ASM_OFFSETS_C | 7 | #define ASM_OFFSETS_C |
8 | 8 | ||
9 | #include <linux/kbuild.h> | 9 | #include <linux/kbuild.h> |
10 | #include <linux/kvm_host.h> | ||
10 | #include <linux/sched.h> | 11 | #include <linux/sched.h> |
11 | #include <asm/cputime.h> | 12 | #include <asm/cputime.h> |
12 | #include <asm/vdso.h> | 13 | #include <asm/vdso.h> |
@@ -47,6 +48,7 @@ int main(void) | |||
47 | DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs)); | 48 | DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs)); |
48 | DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2)); | 49 | DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2)); |
49 | DEFINE(__PT_INT_CODE, offsetof(struct pt_regs, int_code)); | 50 | DEFINE(__PT_INT_CODE, offsetof(struct pt_regs, int_code)); |
51 | DEFINE(__PT_INT_PARM, offsetof(struct pt_regs, int_parm)); | ||
50 | DEFINE(__PT_INT_PARM_LONG, offsetof(struct pt_regs, int_parm_long)); | 52 | DEFINE(__PT_INT_PARM_LONG, offsetof(struct pt_regs, int_parm_long)); |
51 | DEFINE(__PT_SIZE, sizeof(struct pt_regs)); | 53 | DEFINE(__PT_SIZE, sizeof(struct pt_regs)); |
52 | BLANK(); | 54 | BLANK(); |
@@ -161,6 +163,8 @@ int main(void) | |||
161 | DEFINE(__LC_PGM_TDB, offsetof(struct _lowcore, pgm_tdb)); | 163 | DEFINE(__LC_PGM_TDB, offsetof(struct _lowcore, pgm_tdb)); |
162 | DEFINE(__THREAD_trap_tdb, offsetof(struct task_struct, thread.trap_tdb)); | 164 | DEFINE(__THREAD_trap_tdb, offsetof(struct task_struct, thread.trap_tdb)); |
163 | DEFINE(__GMAP_ASCE, offsetof(struct gmap, asce)); | 165 | DEFINE(__GMAP_ASCE, offsetof(struct gmap, asce)); |
166 | DEFINE(__SIE_PROG0C, offsetof(struct kvm_s390_sie_block, prog0c)); | ||
167 | DEFINE(__SIE_PROG20, offsetof(struct kvm_s390_sie_block, prog20)); | ||
164 | #endif /* CONFIG_32BIT */ | 168 | #endif /* CONFIG_32BIT */ |
165 | return 0; | 169 | return 0; |
166 | } | 170 | } |
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 4d5e6f8a7978..be7a408be7a1 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
@@ -429,11 +429,19 @@ io_skip: | |||
429 | stm %r0,%r7,__PT_R0(%r11) | 429 | stm %r0,%r7,__PT_R0(%r11) |
430 | mvc __PT_R8(32,%r11),__LC_SAVE_AREA_ASYNC | 430 | mvc __PT_R8(32,%r11),__LC_SAVE_AREA_ASYNC |
431 | stm %r8,%r9,__PT_PSW(%r11) | 431 | stm %r8,%r9,__PT_PSW(%r11) |
432 | mvc __PT_INT_CODE(12,%r11),__LC_SUBCHANNEL_ID | ||
432 | TRACE_IRQS_OFF | 433 | TRACE_IRQS_OFF |
433 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) | 434 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) |
435 | io_loop: | ||
434 | l %r1,BASED(.Ldo_IRQ) | 436 | l %r1,BASED(.Ldo_IRQ) |
435 | lr %r2,%r11 # pass pointer to pt_regs | 437 | lr %r2,%r11 # pass pointer to pt_regs |
436 | basr %r14,%r1 # call do_IRQ | 438 | basr %r14,%r1 # call do_IRQ |
439 | tm __LC_MACHINE_FLAGS+2,0x10 # MACHINE_FLAG_LPAR | ||
440 | jz io_return | ||
441 | tpi 0 | ||
442 | jz io_return | ||
443 | mvc __PT_INT_CODE(12,%r11),__LC_SUBCHANNEL_ID | ||
444 | j io_loop | ||
437 | io_return: | 445 | io_return: |
438 | LOCKDEP_SYS_EXIT | 446 | LOCKDEP_SYS_EXIT |
439 | TRACE_IRQS_ON | 447 | TRACE_IRQS_ON |
@@ -573,10 +581,10 @@ ext_skip: | |||
573 | stm %r0,%r7,__PT_R0(%r11) | 581 | stm %r0,%r7,__PT_R0(%r11) |
574 | mvc __PT_R8(32,%r11),__LC_SAVE_AREA_ASYNC | 582 | mvc __PT_R8(32,%r11),__LC_SAVE_AREA_ASYNC |
575 | stm %r8,%r9,__PT_PSW(%r11) | 583 | stm %r8,%r9,__PT_PSW(%r11) |
584 | mvc __PT_INT_CODE(4,%r11),__LC_EXT_CPU_ADDR | ||
585 | mvc __PT_INT_PARM(4,%r11),__LC_EXT_PARAMS | ||
576 | TRACE_IRQS_OFF | 586 | TRACE_IRQS_OFF |
577 | lr %r2,%r11 # pass pointer to pt_regs | 587 | lr %r2,%r11 # pass pointer to pt_regs |
578 | l %r3,__LC_EXT_CPU_ADDR # get cpu address + interruption code | ||
579 | l %r4,__LC_EXT_PARAMS # get external parameters | ||
580 | l %r1,BASED(.Ldo_extint) | 588 | l %r1,BASED(.Ldo_extint) |
581 | basr %r14,%r1 # call do_extint | 589 | basr %r14,%r1 # call do_extint |
582 | j io_return | 590 | j io_return |
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h index aa0ab02e9595..3ddbc26d246e 100644 --- a/arch/s390/kernel/entry.h +++ b/arch/s390/kernel/entry.h | |||
@@ -54,7 +54,7 @@ void handle_signal32(unsigned long sig, struct k_sigaction *ka, | |||
54 | void do_notify_resume(struct pt_regs *regs); | 54 | void do_notify_resume(struct pt_regs *regs); |
55 | 55 | ||
56 | struct ext_code; | 56 | struct ext_code; |
57 | void do_extint(struct pt_regs *regs, struct ext_code, unsigned int, unsigned long); | 57 | void do_extint(struct pt_regs *regs); |
58 | void do_restart(void); | 58 | void do_restart(void); |
59 | void __init startup_init(void); | 59 | void __init startup_init(void); |
60 | void die(struct pt_regs *regs, const char *str); | 60 | void die(struct pt_regs *regs, const char *str); |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 4c17eece707e..1c039d0c24c7 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -47,7 +47,6 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ | |||
47 | _TIF_MCCK_PENDING) | 47 | _TIF_MCCK_PENDING) |
48 | _TIF_TRACE = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \ | 48 | _TIF_TRACE = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \ |
49 | _TIF_SYSCALL_TRACEPOINT) | 49 | _TIF_SYSCALL_TRACEPOINT) |
50 | _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) | ||
51 | 50 | ||
52 | #define BASED(name) name-system_call(%r13) | 51 | #define BASED(name) name-system_call(%r13) |
53 | 52 | ||
@@ -81,23 +80,27 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) | |||
81 | #endif | 80 | #endif |
82 | .endm | 81 | .endm |
83 | 82 | ||
84 | .macro HANDLE_SIE_INTERCEPT scratch,pgmcheck | 83 | .macro HANDLE_SIE_INTERCEPT scratch,reason |
85 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) | 84 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) |
86 | tmhh %r8,0x0001 # interrupting from user ? | 85 | tmhh %r8,0x0001 # interrupting from user ? |
87 | jnz .+42 | 86 | jnz .+62 |
88 | lgr \scratch,%r9 | 87 | lgr \scratch,%r9 |
89 | slg \scratch,BASED(.Lsie_loop) | 88 | slg \scratch,BASED(.Lsie_critical) |
90 | clg \scratch,BASED(.Lsie_length) | 89 | clg \scratch,BASED(.Lsie_critical_length) |
91 | .if \pgmcheck | 90 | .if \reason==1 |
92 | # Some program interrupts are suppressing (e.g. protection). | 91 | # Some program interrupts are suppressing (e.g. protection). |
93 | # We must also check the instruction after SIE in that case. | 92 | # We must also check the instruction after SIE in that case. |
94 | # do_protection_exception will rewind to rewind_pad | 93 | # do_protection_exception will rewind to rewind_pad |
95 | jh .+22 | 94 | jh .+42 |
96 | .else | 95 | .else |
97 | jhe .+22 | 96 | jhe .+42 |
98 | .endif | 97 | .endif |
99 | lg %r9,BASED(.Lsie_loop) | 98 | lg %r14,__SF_EMPTY(%r15) # get control block pointer |
100 | LPP BASED(.Lhost_id) # set host id | 99 | LPP __SF_EMPTY+16(%r15) # set host id |
100 | ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE | ||
101 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce | ||
102 | larl %r9,sie_exit # skip forward to sie_exit | ||
103 | mvi __SF_EMPTY+31(%r15),\reason # set exit reason | ||
101 | #endif | 104 | #endif |
102 | .endm | 105 | .endm |
103 | 106 | ||
@@ -450,7 +453,7 @@ ENTRY(io_int_handler) | |||
450 | lg %r12,__LC_THREAD_INFO | 453 | lg %r12,__LC_THREAD_INFO |
451 | larl %r13,system_call | 454 | larl %r13,system_call |
452 | lmg %r8,%r9,__LC_IO_OLD_PSW | 455 | lmg %r8,%r9,__LC_IO_OLD_PSW |
453 | HANDLE_SIE_INTERCEPT %r14,0 | 456 | HANDLE_SIE_INTERCEPT %r14,2 |
454 | SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT | 457 | SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT |
455 | tmhh %r8,0x0001 # interrupting from user? | 458 | tmhh %r8,0x0001 # interrupting from user? |
456 | jz io_skip | 459 | jz io_skip |
@@ -460,10 +463,18 @@ io_skip: | |||
460 | stmg %r0,%r7,__PT_R0(%r11) | 463 | stmg %r0,%r7,__PT_R0(%r11) |
461 | mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC | 464 | mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC |
462 | stmg %r8,%r9,__PT_PSW(%r11) | 465 | stmg %r8,%r9,__PT_PSW(%r11) |
466 | mvc __PT_INT_CODE(12,%r11),__LC_SUBCHANNEL_ID | ||
463 | TRACE_IRQS_OFF | 467 | TRACE_IRQS_OFF |
464 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) | 468 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) |
469 | io_loop: | ||
465 | lgr %r2,%r11 # pass pointer to pt_regs | 470 | lgr %r2,%r11 # pass pointer to pt_regs |
466 | brasl %r14,do_IRQ | 471 | brasl %r14,do_IRQ |
472 | tm __LC_MACHINE_FLAGS+6,0x10 # MACHINE_FLAG_LPAR | ||
473 | jz io_return | ||
474 | tpi 0 | ||
475 | jz io_return | ||
476 | mvc __PT_INT_CODE(12,%r11),__LC_SUBCHANNEL_ID | ||
477 | j io_loop | ||
467 | io_return: | 478 | io_return: |
468 | LOCKDEP_SYS_EXIT | 479 | LOCKDEP_SYS_EXIT |
469 | TRACE_IRQS_ON | 480 | TRACE_IRQS_ON |
@@ -595,7 +606,7 @@ ENTRY(ext_int_handler) | |||
595 | lg %r12,__LC_THREAD_INFO | 606 | lg %r12,__LC_THREAD_INFO |
596 | larl %r13,system_call | 607 | larl %r13,system_call |
597 | lmg %r8,%r9,__LC_EXT_OLD_PSW | 608 | lmg %r8,%r9,__LC_EXT_OLD_PSW |
598 | HANDLE_SIE_INTERCEPT %r14,0 | 609 | HANDLE_SIE_INTERCEPT %r14,3 |
599 | SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT | 610 | SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT |
600 | tmhh %r8,0x0001 # interrupting from user ? | 611 | tmhh %r8,0x0001 # interrupting from user ? |
601 | jz ext_skip | 612 | jz ext_skip |
@@ -605,13 +616,13 @@ ext_skip: | |||
605 | stmg %r0,%r7,__PT_R0(%r11) | 616 | stmg %r0,%r7,__PT_R0(%r11) |
606 | mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC | 617 | mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC |
607 | stmg %r8,%r9,__PT_PSW(%r11) | 618 | stmg %r8,%r9,__PT_PSW(%r11) |
619 | lghi %r1,__LC_EXT_PARAMS2 | ||
620 | mvc __PT_INT_CODE(4,%r11),__LC_EXT_CPU_ADDR | ||
621 | mvc __PT_INT_PARM(4,%r11),__LC_EXT_PARAMS | ||
622 | mvc __PT_INT_PARM_LONG(8,%r11),0(%r1) | ||
608 | TRACE_IRQS_OFF | 623 | TRACE_IRQS_OFF |
609 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) | 624 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) |
610 | lghi %r1,4096 | ||
611 | lgr %r2,%r11 # pass pointer to pt_regs | 625 | lgr %r2,%r11 # pass pointer to pt_regs |
612 | llgf %r3,__LC_EXT_CPU_ADDR # get cpu address + interruption code | ||
613 | llgf %r4,__LC_EXT_PARAMS # get external parameter | ||
614 | lg %r5,__LC_EXT_PARAMS2-4096(%r1) # get 64 bit external parameter | ||
615 | brasl %r14,do_extint | 626 | brasl %r14,do_extint |
616 | j io_return | 627 | j io_return |
617 | 628 | ||
@@ -643,7 +654,7 @@ ENTRY(mcck_int_handler) | |||
643 | lg %r12,__LC_THREAD_INFO | 654 | lg %r12,__LC_THREAD_INFO |
644 | larl %r13,system_call | 655 | larl %r13,system_call |
645 | lmg %r8,%r9,__LC_MCK_OLD_PSW | 656 | lmg %r8,%r9,__LC_MCK_OLD_PSW |
646 | HANDLE_SIE_INTERCEPT %r14,0 | 657 | HANDLE_SIE_INTERCEPT %r14,4 |
647 | tm __LC_MCCK_CODE,0x80 # system damage? | 658 | tm __LC_MCCK_CODE,0x80 # system damage? |
648 | jo mcck_panic # yes -> rest of mcck code invalid | 659 | jo mcck_panic # yes -> rest of mcck code invalid |
649 | lghi %r14,__LC_CPU_TIMER_SAVE_AREA | 660 | lghi %r14,__LC_CPU_TIMER_SAVE_AREA |
@@ -937,56 +948,50 @@ ENTRY(sie64a) | |||
937 | stmg %r6,%r14,__SF_GPRS(%r15) # save kernel registers | 948 | stmg %r6,%r14,__SF_GPRS(%r15) # save kernel registers |
938 | stg %r2,__SF_EMPTY(%r15) # save control block pointer | 949 | stg %r2,__SF_EMPTY(%r15) # save control block pointer |
939 | stg %r3,__SF_EMPTY+8(%r15) # save guest register save area | 950 | stg %r3,__SF_EMPTY+8(%r15) # save guest register save area |
940 | xc __SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # host id == 0 | 951 | xc __SF_EMPTY+16(16,%r15),__SF_EMPTY+16(%r15) # host id & reason |
941 | lmg %r0,%r13,0(%r3) # load guest gprs 0-13 | 952 | lmg %r0,%r13,0(%r3) # load guest gprs 0-13 |
942 | # some program checks are suppressing. C code (e.g. do_protection_exception) | ||
943 | # will rewind the PSW by the ILC, which is 4 bytes in case of SIE. Other | ||
944 | # instructions in the sie_loop should not cause program interrupts. So | ||
945 | # lets use a nop (47 00 00 00) as a landing pad. | ||
946 | # See also HANDLE_SIE_INTERCEPT | ||
947 | rewind_pad: | ||
948 | nop 0 | ||
949 | sie_loop: | ||
950 | lg %r14,__LC_THREAD_INFO # pointer thread_info struct | ||
951 | tm __TI_flags+7(%r14),_TIF_EXIT_SIE | ||
952 | jnz sie_exit | ||
953 | lg %r14,__LC_GMAP # get gmap pointer | 953 | lg %r14,__LC_GMAP # get gmap pointer |
954 | ltgr %r14,%r14 | 954 | ltgr %r14,%r14 |
955 | jz sie_gmap | 955 | jz sie_gmap |
956 | lctlg %c1,%c1,__GMAP_ASCE(%r14) # load primary asce | 956 | lctlg %c1,%c1,__GMAP_ASCE(%r14) # load primary asce |
957 | sie_gmap: | 957 | sie_gmap: |
958 | lg %r14,__SF_EMPTY(%r15) # get control block pointer | 958 | lg %r14,__SF_EMPTY(%r15) # get control block pointer |
959 | oi __SIE_PROG0C+3(%r14),1 # we are going into SIE now | ||
960 | tm __SIE_PROG20+3(%r14),1 # last exit... | ||
961 | jnz sie_done | ||
959 | LPP __SF_EMPTY(%r15) # set guest id | 962 | LPP __SF_EMPTY(%r15) # set guest id |
960 | sie 0(%r14) | 963 | sie 0(%r14) |
961 | sie_done: | 964 | sie_done: |
962 | LPP __SF_EMPTY+16(%r15) # set host id | 965 | LPP __SF_EMPTY+16(%r15) # set host id |
963 | lg %r14,__LC_THREAD_INFO # pointer thread_info struct | 966 | ni __SIE_PROG0C+3(%r14),0xfe # no longer in SIE |
964 | sie_exit: | ||
965 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce | 967 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce |
968 | # some program checks are suppressing. C code (e.g. do_protection_exception) | ||
969 | # will rewind the PSW by the ILC, which is 4 bytes in case of SIE. Other | ||
970 | # instructions beween sie64a and sie_done should not cause program | ||
971 | # interrupts. So lets use a nop (47 00 00 00) as a landing pad. | ||
972 | # See also HANDLE_SIE_INTERCEPT | ||
973 | rewind_pad: | ||
974 | nop 0 | ||
975 | .globl sie_exit | ||
976 | sie_exit: | ||
966 | lg %r14,__SF_EMPTY+8(%r15) # load guest register save area | 977 | lg %r14,__SF_EMPTY+8(%r15) # load guest register save area |
967 | stmg %r0,%r13,0(%r14) # save guest gprs 0-13 | 978 | stmg %r0,%r13,0(%r14) # save guest gprs 0-13 |
968 | lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers | 979 | lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers |
969 | lghi %r2,0 | 980 | lg %r2,__SF_EMPTY+24(%r15) # return exit reason code |
970 | br %r14 | 981 | br %r14 |
971 | sie_fault: | 982 | sie_fault: |
972 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce | 983 | lghi %r14,-EFAULT |
973 | lg %r14,__LC_THREAD_INFO # pointer thread_info struct | 984 | stg %r14,__SF_EMPTY+24(%r15) # set exit reason code |
974 | lg %r14,__SF_EMPTY+8(%r15) # load guest register save area | 985 | j sie_exit |
975 | stmg %r0,%r13,0(%r14) # save guest gprs 0-13 | ||
976 | lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers | ||
977 | lghi %r2,-EFAULT | ||
978 | br %r14 | ||
979 | 986 | ||
980 | .align 8 | 987 | .align 8 |
981 | .Lsie_loop: | 988 | .Lsie_critical: |
982 | .quad sie_loop | 989 | .quad sie_gmap |
983 | .Lsie_length: | 990 | .Lsie_critical_length: |
984 | .quad sie_done - sie_loop | 991 | .quad sie_done - sie_gmap |
985 | .Lhost_id: | ||
986 | .quad 0 | ||
987 | 992 | ||
988 | EX_TABLE(rewind_pad,sie_fault) | 993 | EX_TABLE(rewind_pad,sie_fault) |
989 | EX_TABLE(sie_loop,sie_fault) | 994 | EX_TABLE(sie_exit,sie_fault) |
990 | #endif | 995 | #endif |
991 | 996 | ||
992 | .section .rodata, "a" | 997 | .section .rodata, "a" |
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index dd3c1994b8bd..54b0995514e8 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c | |||
@@ -234,9 +234,9 @@ int unregister_external_interrupt(u16 code, ext_int_handler_t handler) | |||
234 | } | 234 | } |
235 | EXPORT_SYMBOL(unregister_external_interrupt); | 235 | EXPORT_SYMBOL(unregister_external_interrupt); |
236 | 236 | ||
237 | void __irq_entry do_extint(struct pt_regs *regs, struct ext_code ext_code, | 237 | void __irq_entry do_extint(struct pt_regs *regs) |
238 | unsigned int param32, unsigned long param64) | ||
239 | { | 238 | { |
239 | struct ext_code ext_code; | ||
240 | struct pt_regs *old_regs; | 240 | struct pt_regs *old_regs; |
241 | struct ext_int_info *p; | 241 | struct ext_int_info *p; |
242 | int index; | 242 | int index; |
@@ -248,6 +248,7 @@ void __irq_entry do_extint(struct pt_regs *regs, struct ext_code ext_code, | |||
248 | clock_comparator_work(); | 248 | clock_comparator_work(); |
249 | } | 249 | } |
250 | kstat_incr_irqs_this_cpu(EXTERNAL_INTERRUPT, NULL); | 250 | kstat_incr_irqs_this_cpu(EXTERNAL_INTERRUPT, NULL); |
251 | ext_code = *(struct ext_code *) ®s->int_code; | ||
251 | if (ext_code.code != 0x1004) | 252 | if (ext_code.code != 0x1004) |
252 | __get_cpu_var(s390_idle).nohz_delay = 1; | 253 | __get_cpu_var(s390_idle).nohz_delay = 1; |
253 | 254 | ||
@@ -255,7 +256,8 @@ void __irq_entry do_extint(struct pt_regs *regs, struct ext_code ext_code, | |||
255 | rcu_read_lock(); | 256 | rcu_read_lock(); |
256 | list_for_each_entry_rcu(p, &ext_int_hash[index], entry) | 257 | list_for_each_entry_rcu(p, &ext_int_hash[index], entry) |
257 | if (likely(p->code == ext_code.code)) | 258 | if (likely(p->code == ext_code.code)) |
258 | p->handler(ext_code, param32, param64); | 259 | p->handler(ext_code, regs->int_parm, |
260 | regs->int_parm_long); | ||
259 | rcu_read_unlock(); | 261 | rcu_read_unlock(); |
260 | irq_exit(); | 262 | irq_exit(); |
261 | set_irq_regs(old_regs); | 263 | set_irq_regs(old_regs); |
diff --git a/arch/s390/kernel/perf_event.c b/arch/s390/kernel/perf_event.c index f58f37f66824..a6fc037671b1 100644 --- a/arch/s390/kernel/perf_event.c +++ b/arch/s390/kernel/perf_event.c | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/perf_event.h> | 15 | #include <linux/perf_event.h> |
16 | #include <linux/kvm_host.h> | ||
16 | #include <linux/percpu.h> | 17 | #include <linux/percpu.h> |
17 | #include <linux/export.h> | 18 | #include <linux/export.h> |
18 | #include <asm/irq.h> | 19 | #include <asm/irq.h> |
@@ -39,6 +40,57 @@ int perf_num_counters(void) | |||
39 | } | 40 | } |
40 | EXPORT_SYMBOL(perf_num_counters); | 41 | EXPORT_SYMBOL(perf_num_counters); |
41 | 42 | ||
43 | static struct kvm_s390_sie_block *sie_block(struct pt_regs *regs) | ||
44 | { | ||
45 | struct stack_frame *stack = (struct stack_frame *) regs->gprs[15]; | ||
46 | |||
47 | if (!stack) | ||
48 | return NULL; | ||
49 | |||
50 | return (struct kvm_s390_sie_block *) stack->empty1[0]; | ||
51 | } | ||
52 | |||
53 | static bool is_in_guest(struct pt_regs *regs) | ||
54 | { | ||
55 | unsigned long ip = instruction_pointer(regs); | ||
56 | |||
57 | if (user_mode(regs)) | ||
58 | return false; | ||
59 | |||
60 | return ip == (unsigned long) &sie_exit; | ||
61 | } | ||
62 | |||
63 | static unsigned long guest_is_user_mode(struct pt_regs *regs) | ||
64 | { | ||
65 | return sie_block(regs)->gpsw.mask & PSW_MASK_PSTATE; | ||
66 | } | ||
67 | |||
68 | static unsigned long instruction_pointer_guest(struct pt_regs *regs) | ||
69 | { | ||
70 | return sie_block(regs)->gpsw.addr & PSW_ADDR_INSN; | ||
71 | } | ||
72 | |||
73 | unsigned long perf_instruction_pointer(struct pt_regs *regs) | ||
74 | { | ||
75 | return is_in_guest(regs) ? instruction_pointer_guest(regs) | ||
76 | : instruction_pointer(regs); | ||
77 | } | ||
78 | |||
79 | static unsigned long perf_misc_guest_flags(struct pt_regs *regs) | ||
80 | { | ||
81 | return guest_is_user_mode(regs) ? PERF_RECORD_MISC_GUEST_USER | ||
82 | : PERF_RECORD_MISC_GUEST_KERNEL; | ||
83 | } | ||
84 | |||
85 | unsigned long perf_misc_flags(struct pt_regs *regs) | ||
86 | { | ||
87 | if (is_in_guest(regs)) | ||
88 | return perf_misc_guest_flags(regs); | ||
89 | |||
90 | return user_mode(regs) ? PERF_RECORD_MISC_USER | ||
91 | : PERF_RECORD_MISC_KERNEL; | ||
92 | } | ||
93 | |||
42 | void perf_event_print_debug(void) | 94 | void perf_event_print_debug(void) |
43 | { | 95 | { |
44 | struct cpumf_ctr_info cf_info; | 96 | struct cpumf_ctr_info cf_info; |
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c index 9bdbcef1da9e..3bac589844a7 100644 --- a/arch/s390/kernel/s390_ksyms.c +++ b/arch/s390/kernel/s390_ksyms.c | |||
@@ -7,6 +7,7 @@ EXPORT_SYMBOL(_mcount); | |||
7 | #endif | 7 | #endif |
8 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) | 8 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) |
9 | EXPORT_SYMBOL(sie64a); | 9 | EXPORT_SYMBOL(sie64a); |
10 | EXPORT_SYMBOL(sie_exit); | ||
10 | #endif | 11 | #endif |
11 | EXPORT_SYMBOL(memcpy); | 12 | EXPORT_SYMBOL(memcpy); |
12 | EXPORT_SYMBOL(memset); | 13 | EXPORT_SYMBOL(memset); |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 4f977d0d25c2..15a016c10563 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -49,7 +49,6 @@ | |||
49 | 49 | ||
50 | enum { | 50 | enum { |
51 | ec_schedule = 0, | 51 | ec_schedule = 0, |
52 | ec_call_function, | ||
53 | ec_call_function_single, | 52 | ec_call_function_single, |
54 | ec_stop_cpu, | 53 | ec_stop_cpu, |
55 | }; | 54 | }; |
@@ -438,8 +437,6 @@ static void smp_handle_ext_call(void) | |||
438 | smp_stop_cpu(); | 437 | smp_stop_cpu(); |
439 | if (test_bit(ec_schedule, &bits)) | 438 | if (test_bit(ec_schedule, &bits)) |
440 | scheduler_ipi(); | 439 | scheduler_ipi(); |
441 | if (test_bit(ec_call_function, &bits)) | ||
442 | generic_smp_call_function_interrupt(); | ||
443 | if (test_bit(ec_call_function_single, &bits)) | 440 | if (test_bit(ec_call_function_single, &bits)) |
444 | generic_smp_call_function_single_interrupt(); | 441 | generic_smp_call_function_single_interrupt(); |
445 | } | 442 | } |
@@ -456,7 +453,7 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask) | |||
456 | int cpu; | 453 | int cpu; |
457 | 454 | ||
458 | for_each_cpu(cpu, mask) | 455 | for_each_cpu(cpu, mask) |
459 | pcpu_ec_call(pcpu_devices + cpu, ec_call_function); | 456 | pcpu_ec_call(pcpu_devices + cpu, ec_call_function_single); |
460 | } | 457 | } |
461 | 458 | ||
462 | void arch_send_call_function_single_ipi(int cpu) | 459 | void arch_send_call_function_single_ipi(int cpu) |