aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2011-07-24 04:48:18 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2011-07-24 04:48:21 -0400
commit603d1a50acf252621a3598618b018b8123aaba64 (patch)
treef0f8e2d91b34d2cdb9d80b2146a6fdfd48f1d429 /arch/s390
parentbb25b9ba3e33e941dc48048d0a784e6a05e5648a (diff)
[S390] move sie code to entry.S
The entry to / exit from sie has subtle dependencies to the first level interrupt handler. Move the sie assembler code to entry64.S and replace the SIE_HOOK callback with a test and the new _TIF_SIE bit. In addition this patch fixes several problems in regard to the check for the_TIF_EXIT_SIE bits. The old code checked the TIF bits before executing the interrupt handler and it only modified the instruction address if it pointed directly to the sie instruction. In both cases it could miss a TIF bit that normally would cause an exit from the guest and would reenter the guest context. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/include/asm/thread_info.h2
-rw-r--r--arch/s390/kernel/entry64.S80
-rw-r--r--arch/s390/kernel/s390_ksyms.c4
-rw-r--r--arch/s390/kvm/Makefile2
-rw-r--r--arch/s390/kvm/sie64a.S98
5 files changed, 79 insertions, 107 deletions
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h
index ad1382f7932e..1a5dbb6f1495 100644
--- a/arch/s390/include/asm/thread_info.h
+++ b/arch/s390/include/asm/thread_info.h
@@ -94,6 +94,7 @@ static inline struct thread_info *current_thread_info(void)
94#define TIF_SYSCALL_AUDIT 9 /* syscall auditing active */ 94#define TIF_SYSCALL_AUDIT 9 /* syscall auditing active */
95#define TIF_SECCOMP 10 /* secure computing */ 95#define TIF_SECCOMP 10 /* secure computing */
96#define TIF_SYSCALL_TRACEPOINT 11 /* syscall tracepoint instrumentation */ 96#define TIF_SYSCALL_TRACEPOINT 11 /* syscall tracepoint instrumentation */
97#define TIF_SIE 12 /* guest execution active */
97#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling 98#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling
98 TIF_NEED_RESCHED */ 99 TIF_NEED_RESCHED */
99#define TIF_31BIT 17 /* 32bit process */ 100#define TIF_31BIT 17 /* 32bit process */
@@ -113,6 +114,7 @@ static inline struct thread_info *current_thread_info(void)
113#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) 114#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
114#define _TIF_SECCOMP (1<<TIF_SECCOMP) 115#define _TIF_SECCOMP (1<<TIF_SECCOMP)
115#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT) 116#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)
117#define _TIF_SIE (1<<TIF_SIE)
116#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) 118#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
117#define _TIF_31BIT (1<<TIF_31BIT) 119#define _TIF_31BIT (1<<TIF_31BIT)
118#define _TIF_SINGLE_STEP (1<<TIF_FREEZE) 120#define _TIF_SINGLE_STEP (1<<TIF_FREEZE)
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index d61967e2eab0..ab596a865300 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -56,15 +56,28 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
56 _TIF_MCCK_PENDING) 56 _TIF_MCCK_PENDING)
57_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ 57_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
58 _TIF_SECCOMP>>8 | _TIF_SYSCALL_TRACEPOINT>>8) 58 _TIF_SECCOMP>>8 | _TIF_SYSCALL_TRACEPOINT>>8)
59_TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
59 60
60#define BASED(name) name-system_call(%r13) 61#define BASED(name) name-system_call(%r13)
61 62
63 .macro SPP newpp
64#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
65 tm __LC_MACHINE_FLAGS+6,0x20 # MACHINE_FLAG_SPP
66 jz .+8
67 .insn s,0xb2800000,\newpp
68#endif
69 .endm
70
62 .macro HANDLE_SIE_INTERCEPT 71 .macro HANDLE_SIE_INTERCEPT
63#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) 72#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
64 lg %r3,__LC_SIE_HOOK 73 tm __TI_flags+6(%r12),_TIF_SIE>>8
65 ltgr %r3,%r3
66 jz 0f 74 jz 0f
67 basr %r14,%r3 75 SPP __LC_CMF_HPP # set host id
76 clc SP_PSW+8(8,%r15),BASED(.Lsie_loop)
77 jl 0f
78 clc SP_PSW+8(8,%r15),BASED(.Lsie_done)
79 jhe 0f
80 mvc SP_PSW+8(8,%r15),BASED(.Lsie_loop)
680: 810:
69#endif 82#endif
70 .endm 83 .endm
@@ -465,6 +478,7 @@ pgm_check_handler:
465 xc SP_ILC(4,%r15),SP_ILC(%r15) 478 xc SP_ILC(4,%r15),SP_ILC(%r15)
466 mvc SP_PSW(16,%r15),__LC_PGM_OLD_PSW 479 mvc SP_PSW(16,%r15),__LC_PGM_OLD_PSW
467 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct 480 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
481 HANDLE_SIE_INTERCEPT
468 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 482 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
469 jz pgm_no_vtime 483 jz pgm_no_vtime
470 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER 484 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -472,7 +486,6 @@ pgm_check_handler:
472 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER 486 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
473 LAST_BREAK 487 LAST_BREAK
474pgm_no_vtime: 488pgm_no_vtime:
475 HANDLE_SIE_INTERCEPT
476 stg %r11,SP_ARGS(%r15) 489 stg %r11,SP_ARGS(%r15)
477 lgf %r3,__LC_PGM_ILC # load program interruption code 490 lgf %r3,__LC_PGM_ILC # load program interruption code
478 lg %r4,__LC_TRANS_EXC_CODE 491 lg %r4,__LC_TRANS_EXC_CODE
@@ -507,6 +520,7 @@ pgm_per_std:
507 CREATE_STACK_FRAME __LC_SAVE_AREA 520 CREATE_STACK_FRAME __LC_SAVE_AREA
508 mvc SP_PSW(16,%r15),__LC_PGM_OLD_PSW 521 mvc SP_PSW(16,%r15),__LC_PGM_OLD_PSW
509 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct 522 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
523 HANDLE_SIE_INTERCEPT
510 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 524 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
511 jz pgm_no_vtime2 525 jz pgm_no_vtime2
512 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER 526 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -514,7 +528,6 @@ pgm_per_std:
514 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER 528 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
515 LAST_BREAK 529 LAST_BREAK
516pgm_no_vtime2: 530pgm_no_vtime2:
517 HANDLE_SIE_INTERCEPT
518 lg %r1,__TI_task(%r12) 531 lg %r1,__TI_task(%r12)
519 tm SP_PSW+1(%r15),0x01 # kernel per event ? 532 tm SP_PSW+1(%r15),0x01 # kernel per event ?
520 jz kernel_per 533 jz kernel_per
@@ -579,6 +592,7 @@ io_int_handler:
579 CREATE_STACK_FRAME __LC_SAVE_AREA+40 592 CREATE_STACK_FRAME __LC_SAVE_AREA+40
580 mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack 593 mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack
581 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct 594 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
595 HANDLE_SIE_INTERCEPT
582 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 596 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
583 jz io_no_vtime 597 jz io_no_vtime
584 UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER 598 UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -586,7 +600,6 @@ io_int_handler:
586 mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER 600 mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
587 LAST_BREAK 601 LAST_BREAK
588io_no_vtime: 602io_no_vtime:
589 HANDLE_SIE_INTERCEPT
590 TRACE_IRQS_OFF 603 TRACE_IRQS_OFF
591 la %r2,SP_PTREGS(%r15) # address of register-save area 604 la %r2,SP_PTREGS(%r15) # address of register-save area
592 brasl %r14,do_IRQ # call standard irq handler 605 brasl %r14,do_IRQ # call standard irq handler
@@ -714,6 +727,7 @@ ext_int_handler:
714 CREATE_STACK_FRAME __LC_SAVE_AREA+40 727 CREATE_STACK_FRAME __LC_SAVE_AREA+40
715 mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack 728 mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack
716 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct 729 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
730 HANDLE_SIE_INTERCEPT
717 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 731 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
718 jz ext_no_vtime 732 jz ext_no_vtime
719 UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER 733 UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -721,7 +735,6 @@ ext_int_handler:
721 mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER 735 mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
722 LAST_BREAK 736 LAST_BREAK
723ext_no_vtime: 737ext_no_vtime:
724 HANDLE_SIE_INTERCEPT
725 TRACE_IRQS_OFF 738 TRACE_IRQS_OFF
726 lghi %r1,4096 739 lghi %r1,4096
727 la %r2,SP_PTREGS(%r15) # address of register-save area 740 la %r2,SP_PTREGS(%r15) # address of register-save area
@@ -785,6 +798,7 @@ mcck_int_main:
785 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct 798 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
786 tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? 799 tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid?
787 jno mcck_no_vtime # no -> no timer update 800 jno mcck_no_vtime # no -> no timer update
801 HANDLE_SIE_INTERCEPT
788 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 802 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
789 jz mcck_no_vtime 803 jz mcck_no_vtime
790 UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER 804 UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER
@@ -804,7 +818,6 @@ mcck_no_vtime:
804 stosm __SF_EMPTY(%r15),0x04 # turn dat on 818 stosm __SF_EMPTY(%r15),0x04 # turn dat on
805 tm __TI_flags+7(%r12),_TIF_MCCK_PENDING 819 tm __TI_flags+7(%r12),_TIF_MCCK_PENDING
806 jno mcck_return 820 jno mcck_return
807 HANDLE_SIE_INTERCEPT
808 TRACE_IRQS_OFF 821 TRACE_IRQS_OFF
809 brasl %r14,s390_handle_mcck 822 brasl %r14,s390_handle_mcck
810 TRACE_IRQS_ON 823 TRACE_IRQS_ON
@@ -1036,6 +1049,57 @@ cleanup_io_restore_insn:
1036.Lcritical_end: 1049.Lcritical_end:
1037 .quad __critical_end 1050 .quad __critical_end
1038 1051
1052#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
1053/*
1054 * sie64a calling convention:
1055 * %r2 pointer to sie control block
1056 * %r3 guest register save area
1057 */
1058 .globl sie64a
1059sie64a:
1060 stmg %r6,%r14,__SF_GPRS(%r15) # save kernel registers
1061 stg %r2,__SF_EMPTY(%r15) # save control block pointer
1062 stg %r3,__SF_EMPTY+8(%r15) # save guest register save area
1063 lmg %r0,%r13,0(%r3) # load guest gprs 0-13
1064 lg %r14,__LC_THREAD_INFO # pointer thread_info struct
1065 oi __TI_flags+6(%r14),_TIF_SIE>>8
1066sie_loop:
1067 lg %r14,__LC_THREAD_INFO # pointer thread_info struct
1068 tm __TI_flags+7(%r14),_TIF_EXIT_SIE
1069 jnz sie_exit
1070 lg %r14,__SF_EMPTY(%r15) # get control block pointer
1071 SPP __SF_EMPTY(%r15) # set guest id
1072 sie 0(%r14)
1073sie_done:
1074 SPP __LC_CMF_HPP # set host id
1075 lg %r14,__LC_THREAD_INFO # pointer thread_info struct
1076sie_exit:
1077 ni __TI_flags+6(%r14),255-(_TIF_SIE>>8)
1078 lg %r14,__SF_EMPTY+8(%r15) # load guest register save area
1079 stmg %r0,%r13,0(%r14) # save guest gprs 0-13
1080 lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
1081 lghi %r2,0
1082 br %r14
1083sie_fault:
1084 lg %r14,__LC_THREAD_INFO # pointer thread_info struct
1085 ni __TI_flags+6(%r14),255-(_TIF_SIE>>8)
1086 lg %r14,__SF_EMPTY+8(%r15) # load guest register save area
1087 stmg %r0,%r13,0(%r14) # save guest gprs 0-13
1088 lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
1089 lghi %r2,-EFAULT
1090 br %r14
1091
1092 .align 8
1093.Lsie_loop:
1094 .quad sie_loop
1095.Lsie_done:
1096 .quad sie_done
1097
1098 .section __ex_table,"a"
1099 .quad sie_loop,sie_fault
1100 .previous
1101#endif
1102
1039 .section .rodata, "a" 1103 .section .rodata, "a"
1040#define SYSCALL(esa,esame,emu) .long esame 1104#define SYSCALL(esa,esame,emu) .long esame
1041 .globl sys_call_table 1105 .globl sys_call_table
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
index 656fcbb9bd83..57b536649b00 100644
--- a/arch/s390/kernel/s390_ksyms.c
+++ b/arch/s390/kernel/s390_ksyms.c
@@ -1,6 +1,10 @@
1#include <linux/module.h> 1#include <linux/module.h>
2#include <linux/kvm_host.h>
2#include <asm/ftrace.h> 3#include <asm/ftrace.h>
3 4
4#ifdef CONFIG_FUNCTION_TRACER 5#ifdef CONFIG_FUNCTION_TRACER
5EXPORT_SYMBOL(_mcount); 6EXPORT_SYMBOL(_mcount);
6#endif 7#endif
8#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
9EXPORT_SYMBOL(sie64a);
10#endif
diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile
index 860d26514c08..3975722bb19d 100644
--- a/arch/s390/kvm/Makefile
+++ b/arch/s390/kvm/Makefile
@@ -10,5 +10,5 @@ common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o)
10 10
11ccflags-y := -Ivirt/kvm -Iarch/s390/kvm 11ccflags-y := -Ivirt/kvm -Iarch/s390/kvm
12 12
13kvm-objs := $(common-objs) kvm-s390.o sie64a.o intercept.o interrupt.o priv.o sigp.o diag.o 13kvm-objs := $(common-objs) kvm-s390.o intercept.o interrupt.o priv.o sigp.o diag.o
14obj-$(CONFIG_KVM) += kvm.o 14obj-$(CONFIG_KVM) += kvm.o
diff --git a/arch/s390/kvm/sie64a.S b/arch/s390/kvm/sie64a.S
deleted file mode 100644
index 5faa1b1b23fa..000000000000
--- a/arch/s390/kvm/sie64a.S
+++ /dev/null
@@ -1,98 +0,0 @@
1/*
2 * sie64a.S - low level sie call
3 *
4 * Copyright IBM Corp. 2008,2010
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License (version 2 only)
8 * as published by the Free Software Foundation.
9 *
10 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
11 * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
12 */
13
14#include <linux/errno.h>
15#include <asm/asm-offsets.h>
16#include <asm/setup.h>
17#include <asm/asm-offsets.h>
18#include <asm/ptrace.h>
19#include <asm/thread_info.h>
20
21_TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
22
23/*
24 * offsets into stackframe
25 * SP_ = offsets into stack sie64 is called with
26 * SPI_ = offsets into irq stack
27 */
28SP_GREGS = __SF_EMPTY
29SP_HOOK = __SF_EMPTY+8
30SP_GPP = __SF_EMPTY+16
31SPI_PSW = STACK_FRAME_OVERHEAD + __PT_PSW
32
33
34 .macro SPP newpp
35 tm __LC_MACHINE_FLAGS+6,0x20 # MACHINE_FLAG_SPP
36 jz 0f
37 .insn s,0xb2800000,\newpp
380:
39 .endm
40
41sie_irq_handler:
42 SPP __LC_CMF_HPP # set host id
43 larl %r2,sie_inst
44 clg %r2,SPI_PSW+8(0,%r15) # intercepted sie
45 jne 1f
46 xc __LC_SIE_HOOK(8),__LC_SIE_HOOK
47 lg %r2,__LC_THREAD_INFO # pointer thread_info struct
48 tm __TI_flags+7(%r2),_TIF_EXIT_SIE
49 jz 0f
50 larl %r2,sie_exit # work pending, leave sie
51 stg %r2,SPI_PSW+8(0,%r15)
52 br %r14
530: larl %r2,sie_reenter # re-enter with guest id
54 stg %r2,SPI_PSW+8(0,%r15)
551: br %r14
56
57/*
58 * sie64a calling convention:
59 * %r2 pointer to sie control block
60 * %r3 guest register save area
61 */
62 .globl sie64a
63sie64a:
64 stg %r3,SP_GREGS(%r15) # save guest register save area
65 stmg %r6,%r14,__SF_GPRS(%r15) # save registers on entry
66 lgr %r14,%r2 # pointer to sie control block
67 larl %r5,sie_irq_handler
68 stg %r2,SP_GPP(%r15)
69 stg %r5,SP_HOOK(%r15) # save hook target
70 lmg %r0,%r13,0(%r3) # load guest gprs 0-13
71sie_reenter:
72 mvc __LC_SIE_HOOK(8),SP_HOOK(%r15)
73 SPP SP_GPP(%r15) # set guest id
74sie_inst:
75 sie 0(%r14)
76 xc __LC_SIE_HOOK(8),__LC_SIE_HOOK
77 SPP __LC_CMF_HPP # set host id
78sie_exit:
79 lg %r14,SP_GREGS(%r15)
80 stmg %r0,%r13,0(%r14) # save guest gprs 0-13
81 lghi %r2,0
82 lmg %r6,%r14,__SF_GPRS(%r15)
83 br %r14
84
85sie_err:
86 xc __LC_SIE_HOOK(8),__LC_SIE_HOOK
87 SPP __LC_CMF_HPP # set host id
88 lg %r14,SP_GREGS(%r15)
89 stmg %r0,%r13,0(%r14) # save guest gprs 0-13
90 lghi %r2,-EFAULT
91 lmg %r6,%r14,__SF_GPRS(%r15)
92 br %r14
93
94 .section __ex_table,"a"
95 .quad sie_inst,sie_err
96 .quad sie_exit,sie_err
97 .quad sie_reenter,sie_err
98 .previous