aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r--arch/s390/kernel/asm-offsets.c4
-rw-r--r--arch/s390/kernel/entry.S12
-rw-r--r--arch/s390/kernel/entry.h2
-rw-r--r--arch/s390/kernel/entry64.S97
-rw-r--r--arch/s390/kernel/irq.c8
-rw-r--r--arch/s390/kernel/perf_event.c52
-rw-r--r--arch/s390/kernel/s390_ksyms.c1
-rw-r--r--arch/s390/kernel/smp.c5
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)
435io_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
437io_return: 445io_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,
54void do_notify_resume(struct pt_regs *regs); 54void do_notify_resume(struct pt_regs *regs);
55 55
56struct ext_code; 56struct ext_code;
57void do_extint(struct pt_regs *regs, struct ext_code, unsigned int, unsigned long); 57void do_extint(struct pt_regs *regs);
58void do_restart(void); 58void do_restart(void);
59void __init startup_init(void); 59void __init startup_init(void);
60void die(struct pt_regs *regs, const char *str); 60void 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)
469io_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
467io_return: 478io_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
947rewind_pad:
948 nop 0
949sie_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
957sie_gmap: 957sie_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)
961sie_done: 964sie_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
964sie_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
973rewind_pad:
974 nop 0
975 .globl sie_exit
976sie_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
971sie_fault: 982sie_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}
235EXPORT_SYMBOL(unregister_external_interrupt); 235EXPORT_SYMBOL(unregister_external_interrupt);
236 236
237void __irq_entry do_extint(struct pt_regs *regs, struct ext_code ext_code, 237void __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 *) &regs->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}
40EXPORT_SYMBOL(perf_num_counters); 41EXPORT_SYMBOL(perf_num_counters);
41 42
43static 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
53static 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
63static unsigned long guest_is_user_mode(struct pt_regs *regs)
64{
65 return sie_block(regs)->gpsw.mask & PSW_MASK_PSTATE;
66}
67
68static unsigned long instruction_pointer_guest(struct pt_regs *regs)
69{
70 return sie_block(regs)->gpsw.addr & PSW_ADDR_INSN;
71}
72
73unsigned 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
79static 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
85unsigned 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
42void perf_event_print_debug(void) 94void 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)
9EXPORT_SYMBOL(sie64a); 9EXPORT_SYMBOL(sie64a);
10EXPORT_SYMBOL(sie_exit);
10#endif 11#endif
11EXPORT_SYMBOL(memcpy); 12EXPORT_SYMBOL(memcpy);
12EXPORT_SYMBOL(memset); 13EXPORT_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
50enum { 50enum {
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
462void arch_send_call_function_single_ipi(int cpu) 459void arch_send_call_function_single_ipi(int cpu)