aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel
diff options
context:
space:
mode:
authorChristian Borntraeger <borntraeger@de.ibm.com>2011-09-20 11:07:28 -0400
committerHeiko Carstens <heiko.carstens@de.ibm.com>2011-09-20 11:07:34 -0400
commit480e5926ce3bb61ec229be2dab08bdce8abb8d2e (patch)
treeb252230da3bba55a8e4ebd747767257c781670d7 /arch/s390/kernel
parent9d037a777695993ec7437e5f451647dea7919d4c (diff)
[S390] kvm: fix address mode switching
598841ca9919d008b520114d8a4378c4ce4e40a1 ([S390] use gmap address spaces for kvm guest images) changed kvm to use a separate address space for kvm guests. This address space was switched in __vcpu_run In some cases (preemption, page fault) there is the possibility that this address space switch is lost. The typical symptom was a huge amount of validity intercepts or random guest addressing exceptions. Fix this by doing the switch in sie_loop and sie_exit and saving the address space in the gmap structure itself. Also use the preempt notifier. Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com> Acked-by: Avi Kivity <avi@redhat.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r--arch/s390/kernel/asm-offsets.c3
-rw-r--r--arch/s390/kernel/entry64.S6
2 files changed, 9 insertions, 0 deletions
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index 532fd4322156..2b45591e1582 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -10,6 +10,7 @@
10#include <linux/sched.h> 10#include <linux/sched.h>
11#include <asm/vdso.h> 11#include <asm/vdso.h>
12#include <asm/sigp.h> 12#include <asm/sigp.h>
13#include <asm/pgtable.h>
13 14
14/* 15/*
15 * Make sure that the compiler is new enough. We want a compiler that 16 * Make sure that the compiler is new enough. We want a compiler that
@@ -126,6 +127,7 @@ int main(void)
126 DEFINE(__LC_KERNEL_STACK, offsetof(struct _lowcore, kernel_stack)); 127 DEFINE(__LC_KERNEL_STACK, offsetof(struct _lowcore, kernel_stack));
127 DEFINE(__LC_ASYNC_STACK, offsetof(struct _lowcore, async_stack)); 128 DEFINE(__LC_ASYNC_STACK, offsetof(struct _lowcore, async_stack));
128 DEFINE(__LC_PANIC_STACK, offsetof(struct _lowcore, panic_stack)); 129 DEFINE(__LC_PANIC_STACK, offsetof(struct _lowcore, panic_stack));
130 DEFINE(__LC_USER_ASCE, offsetof(struct _lowcore, user_asce));
129 DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock)); 131 DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock));
130 DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock)); 132 DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock));
131 DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags)); 133 DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags));
@@ -151,6 +153,7 @@ int main(void)
151 DEFINE(__LC_VDSO_PER_CPU, offsetof(struct _lowcore, vdso_per_cpu_data)); 153 DEFINE(__LC_VDSO_PER_CPU, offsetof(struct _lowcore, vdso_per_cpu_data));
152 DEFINE(__LC_GMAP, offsetof(struct _lowcore, gmap)); 154 DEFINE(__LC_GMAP, offsetof(struct _lowcore, gmap));
153 DEFINE(__LC_CMF_HPP, offsetof(struct _lowcore, cmf_hpp)); 155 DEFINE(__LC_CMF_HPP, offsetof(struct _lowcore, cmf_hpp));
156 DEFINE(__GMAP_ASCE, offsetof(struct gmap, asce));
154#endif /* CONFIG_32BIT */ 157#endif /* CONFIG_32BIT */
155 return 0; 158 return 0;
156} 159}
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 5f729d627cef..713da0760538 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -1076,6 +1076,11 @@ sie_loop:
1076 lg %r14,__LC_THREAD_INFO # pointer thread_info struct 1076 lg %r14,__LC_THREAD_INFO # pointer thread_info struct
1077 tm __TI_flags+7(%r14),_TIF_EXIT_SIE 1077 tm __TI_flags+7(%r14),_TIF_EXIT_SIE
1078 jnz sie_exit 1078 jnz sie_exit
1079 lg %r14,__LC_GMAP # get gmap pointer
1080 ltgr %r14,%r14
1081 jz sie_gmap
1082 lctlg %c1,%c1,__GMAP_ASCE(%r14) # load primary asce
1083sie_gmap:
1079 lg %r14,__SF_EMPTY(%r15) # get control block pointer 1084 lg %r14,__SF_EMPTY(%r15) # get control block pointer
1080 SPP __SF_EMPTY(%r15) # set guest id 1085 SPP __SF_EMPTY(%r15) # set guest id
1081 sie 0(%r14) 1086 sie 0(%r14)
@@ -1083,6 +1088,7 @@ sie_done:
1083 SPP __LC_CMF_HPP # set host id 1088 SPP __LC_CMF_HPP # set host id
1084 lg %r14,__LC_THREAD_INFO # pointer thread_info struct 1089 lg %r14,__LC_THREAD_INFO # pointer thread_info struct
1085sie_exit: 1090sie_exit:
1091 lctlg %c1,%c1,__LC_USER_ASCE # load primary asce
1086 ni __TI_flags+6(%r14),255-(_TIF_SIE>>8) 1092 ni __TI_flags+6(%r14),255-(_TIF_SIE>>8)
1087 lg %r14,__SF_EMPTY+8(%r15) # load guest register save area 1093 lg %r14,__SF_EMPTY+8(%r15) # load guest register save area
1088 stmg %r0,%r13,0(%r14) # save guest gprs 0-13 1094 stmg %r0,%r13,0(%r14) # save guest gprs 0-13