diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-03 16:21:40 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-03 16:21:40 -0400 |
commit | fe489bf4505ae26d3c6d6a1f1d3064c2a9c5cd85 (patch) | |
tree | 46596fd7edf7c4da1dafdb2c62011841e71cf32d /arch/s390/kvm | |
parent | 3e34131a65127e73fbae68c82748f32c8af7e4a4 (diff) | |
parent | a3ff5fbc94a829680d4aa005cd17add1c1a1fb5b (diff) |
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull KVM fixes from Paolo Bonzini:
"On the x86 side, there are some optimizations and documentation
updates. The big ARM/KVM change for 3.11, support for AArch64, will
come through Catalin Marinas's tree. s390 and PPC have misc cleanups
and bugfixes"
* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (87 commits)
KVM: PPC: Ignore PIR writes
KVM: PPC: Book3S PR: Invalidate SLB entries properly
KVM: PPC: Book3S PR: Allow guest to use 1TB segments
KVM: PPC: Book3S PR: Don't keep scanning HPTEG after we find a match
KVM: PPC: Book3S PR: Fix invalidation of SLB entry 0 on guest entry
KVM: PPC: Book3S PR: Fix proto-VSID calculations
KVM: PPC: Guard doorbell exception with CONFIG_PPC_DOORBELL
KVM: Fix RTC interrupt coalescing tracking
kvm: Add a tracepoint write_tsc_offset
KVM: MMU: Inform users of mmio generation wraparound
KVM: MMU: document fast invalidate all mmio sptes
KVM: MMU: document fast invalidate all pages
KVM: MMU: document fast page fault
KVM: MMU: document mmio page fault
KVM: MMU: document write_flooding_count
KVM: MMU: document clear_spte_count
KVM: MMU: drop kvm_mmu_zap_mmio_sptes
KVM: MMU: init kvm generation close to mmio wrap-around value
KVM: MMU: add tracepoint for check_mmio_spte
KVM: MMU: fast invalidate all mmio sptes
...
Diffstat (limited to 'arch/s390/kvm')
-rw-r--r-- | arch/s390/kvm/Makefile | 3 | ||||
-rw-r--r-- | arch/s390/kvm/diag.c | 3 | ||||
-rw-r--r-- | arch/s390/kvm/intercept.c | 124 | ||||
-rw-r--r-- | arch/s390/kvm/interrupt.c | 18 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.c | 105 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.h | 14 | ||||
-rw-r--r-- | arch/s390/kvm/priv.c | 274 | ||||
-rw-r--r-- | arch/s390/kvm/sigp.c | 19 |
8 files changed, 367 insertions, 193 deletions
diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile index 8fe9d65a4585..40b4c6470f88 100644 --- a/arch/s390/kvm/Makefile +++ b/arch/s390/kvm/Makefile | |||
@@ -6,7 +6,8 @@ | |||
6 | # it under the terms of the GNU General Public License (version 2 only) | 6 | # it under the terms of the GNU General Public License (version 2 only) |
7 | # as published by the Free Software Foundation. | 7 | # as published by the Free Software Foundation. |
8 | 8 | ||
9 | common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o eventfd.o) | 9 | KVM := ../../../virt/kvm |
10 | common-objs = $(KVM)/kvm_main.o $(KVM)/eventfd.o | ||
10 | 11 | ||
11 | ccflags-y := -Ivirt/kvm -Iarch/s390/kvm | 12 | ccflags-y := -Ivirt/kvm -Iarch/s390/kvm |
12 | 13 | ||
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c index 1c01a9912989..3074475c8ae0 100644 --- a/arch/s390/kvm/diag.c +++ b/arch/s390/kvm/diag.c | |||
@@ -132,6 +132,9 @@ int kvm_s390_handle_diag(struct kvm_vcpu *vcpu) | |||
132 | { | 132 | { |
133 | int code = (vcpu->arch.sie_block->ipb & 0xfff0000) >> 16; | 133 | int code = (vcpu->arch.sie_block->ipb & 0xfff0000) >> 16; |
134 | 134 | ||
135 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | ||
136 | return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); | ||
137 | |||
135 | trace_kvm_s390_handle_diag(vcpu, code); | 138 | trace_kvm_s390_handle_diag(vcpu, code); |
136 | switch (code) { | 139 | switch (code) { |
137 | case 0x10: | 140 | case 0x10: |
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index b7d1b2edeeb3..5ee56e5acc23 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c | |||
@@ -22,87 +22,6 @@ | |||
22 | #include "trace.h" | 22 | #include "trace.h" |
23 | #include "trace-s390.h" | 23 | #include "trace-s390.h" |
24 | 24 | ||
25 | static int handle_lctlg(struct kvm_vcpu *vcpu) | ||
26 | { | ||
27 | int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; | ||
28 | int reg3 = vcpu->arch.sie_block->ipa & 0x000f; | ||
29 | u64 useraddr; | ||
30 | int reg, rc; | ||
31 | |||
32 | vcpu->stat.instruction_lctlg++; | ||
33 | |||
34 | useraddr = kvm_s390_get_base_disp_rsy(vcpu); | ||
35 | |||
36 | if (useraddr & 7) | ||
37 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
38 | |||
39 | reg = reg1; | ||
40 | |||
41 | VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x, addr:%llx", reg1, reg3, | ||
42 | useraddr); | ||
43 | trace_kvm_s390_handle_lctl(vcpu, 1, reg1, reg3, useraddr); | ||
44 | |||
45 | do { | ||
46 | rc = get_guest(vcpu, vcpu->arch.sie_block->gcr[reg], | ||
47 | (u64 __user *) useraddr); | ||
48 | if (rc) | ||
49 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | ||
50 | useraddr += 8; | ||
51 | if (reg == reg3) | ||
52 | break; | ||
53 | reg = (reg + 1) % 16; | ||
54 | } while (1); | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static int handle_lctl(struct kvm_vcpu *vcpu) | ||
59 | { | ||
60 | int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; | ||
61 | int reg3 = vcpu->arch.sie_block->ipa & 0x000f; | ||
62 | u64 useraddr; | ||
63 | u32 val = 0; | ||
64 | int reg, rc; | ||
65 | |||
66 | vcpu->stat.instruction_lctl++; | ||
67 | |||
68 | useraddr = kvm_s390_get_base_disp_rs(vcpu); | ||
69 | |||
70 | if (useraddr & 3) | ||
71 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
72 | |||
73 | VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x, addr:%llx", reg1, reg3, | ||
74 | useraddr); | ||
75 | trace_kvm_s390_handle_lctl(vcpu, 0, reg1, reg3, useraddr); | ||
76 | |||
77 | reg = reg1; | ||
78 | do { | ||
79 | rc = get_guest(vcpu, val, (u32 __user *) useraddr); | ||
80 | if (rc) | ||
81 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | ||
82 | vcpu->arch.sie_block->gcr[reg] &= 0xffffffff00000000ul; | ||
83 | vcpu->arch.sie_block->gcr[reg] |= val; | ||
84 | useraddr += 4; | ||
85 | if (reg == reg3) | ||
86 | break; | ||
87 | reg = (reg + 1) % 16; | ||
88 | } while (1); | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static const intercept_handler_t eb_handlers[256] = { | ||
93 | [0x2f] = handle_lctlg, | ||
94 | [0x8a] = kvm_s390_handle_priv_eb, | ||
95 | }; | ||
96 | |||
97 | static int handle_eb(struct kvm_vcpu *vcpu) | ||
98 | { | ||
99 | intercept_handler_t handler; | ||
100 | |||
101 | handler = eb_handlers[vcpu->arch.sie_block->ipb & 0xff]; | ||
102 | if (handler) | ||
103 | return handler(vcpu); | ||
104 | return -EOPNOTSUPP; | ||
105 | } | ||
106 | 25 | ||
107 | static const intercept_handler_t instruction_handlers[256] = { | 26 | static const intercept_handler_t instruction_handlers[256] = { |
108 | [0x01] = kvm_s390_handle_01, | 27 | [0x01] = kvm_s390_handle_01, |
@@ -110,10 +29,10 @@ static const intercept_handler_t instruction_handlers[256] = { | |||
110 | [0x83] = kvm_s390_handle_diag, | 29 | [0x83] = kvm_s390_handle_diag, |
111 | [0xae] = kvm_s390_handle_sigp, | 30 | [0xae] = kvm_s390_handle_sigp, |
112 | [0xb2] = kvm_s390_handle_b2, | 31 | [0xb2] = kvm_s390_handle_b2, |
113 | [0xb7] = handle_lctl, | 32 | [0xb7] = kvm_s390_handle_lctl, |
114 | [0xb9] = kvm_s390_handle_b9, | 33 | [0xb9] = kvm_s390_handle_b9, |
115 | [0xe5] = kvm_s390_handle_e5, | 34 | [0xe5] = kvm_s390_handle_e5, |
116 | [0xeb] = handle_eb, | 35 | [0xeb] = kvm_s390_handle_eb, |
117 | }; | 36 | }; |
118 | 37 | ||
119 | static int handle_noop(struct kvm_vcpu *vcpu) | 38 | static int handle_noop(struct kvm_vcpu *vcpu) |
@@ -174,47 +93,12 @@ static int handle_stop(struct kvm_vcpu *vcpu) | |||
174 | 93 | ||
175 | static int handle_validity(struct kvm_vcpu *vcpu) | 94 | static int handle_validity(struct kvm_vcpu *vcpu) |
176 | { | 95 | { |
177 | unsigned long vmaddr; | ||
178 | int viwhy = vcpu->arch.sie_block->ipb >> 16; | 96 | int viwhy = vcpu->arch.sie_block->ipb >> 16; |
179 | int rc; | ||
180 | 97 | ||
181 | vcpu->stat.exit_validity++; | 98 | vcpu->stat.exit_validity++; |
182 | trace_kvm_s390_intercept_validity(vcpu, viwhy); | 99 | trace_kvm_s390_intercept_validity(vcpu, viwhy); |
183 | if (viwhy == 0x37) { | 100 | WARN_ONCE(true, "kvm: unhandled validity intercept 0x%x\n", viwhy); |
184 | vmaddr = gmap_fault(vcpu->arch.sie_block->prefix, | 101 | return -EOPNOTSUPP; |
185 | vcpu->arch.gmap); | ||
186 | if (IS_ERR_VALUE(vmaddr)) { | ||
187 | rc = -EOPNOTSUPP; | ||
188 | goto out; | ||
189 | } | ||
190 | rc = fault_in_pages_writeable((char __user *) vmaddr, | ||
191 | PAGE_SIZE); | ||
192 | if (rc) { | ||
193 | /* user will receive sigsegv, exit to user */ | ||
194 | rc = -EOPNOTSUPP; | ||
195 | goto out; | ||
196 | } | ||
197 | vmaddr = gmap_fault(vcpu->arch.sie_block->prefix + PAGE_SIZE, | ||
198 | vcpu->arch.gmap); | ||
199 | if (IS_ERR_VALUE(vmaddr)) { | ||
200 | rc = -EOPNOTSUPP; | ||
201 | goto out; | ||
202 | } | ||
203 | rc = fault_in_pages_writeable((char __user *) vmaddr, | ||
204 | PAGE_SIZE); | ||
205 | if (rc) { | ||
206 | /* user will receive sigsegv, exit to user */ | ||
207 | rc = -EOPNOTSUPP; | ||
208 | goto out; | ||
209 | } | ||
210 | } else | ||
211 | rc = -EOPNOTSUPP; | ||
212 | |||
213 | out: | ||
214 | if (rc) | ||
215 | VCPU_EVENT(vcpu, 2, "unhandled validity intercept code %d", | ||
216 | viwhy); | ||
217 | return rc; | ||
218 | } | 102 | } |
219 | 103 | ||
220 | static int handle_instruction(struct kvm_vcpu *vcpu) | 104 | static int handle_instruction(struct kvm_vcpu *vcpu) |
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 5c948177529e..7f35cb33e510 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c | |||
@@ -438,7 +438,7 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu) | |||
438 | no_timer: | 438 | no_timer: |
439 | spin_lock(&vcpu->arch.local_int.float_int->lock); | 439 | spin_lock(&vcpu->arch.local_int.float_int->lock); |
440 | spin_lock_bh(&vcpu->arch.local_int.lock); | 440 | spin_lock_bh(&vcpu->arch.local_int.lock); |
441 | add_wait_queue(&vcpu->arch.local_int.wq, &wait); | 441 | add_wait_queue(&vcpu->wq, &wait); |
442 | while (list_empty(&vcpu->arch.local_int.list) && | 442 | while (list_empty(&vcpu->arch.local_int.list) && |
443 | list_empty(&vcpu->arch.local_int.float_int->list) && | 443 | list_empty(&vcpu->arch.local_int.float_int->list) && |
444 | (!vcpu->arch.local_int.timer_due) && | 444 | (!vcpu->arch.local_int.timer_due) && |
@@ -452,7 +452,7 @@ no_timer: | |||
452 | } | 452 | } |
453 | __unset_cpu_idle(vcpu); | 453 | __unset_cpu_idle(vcpu); |
454 | __set_current_state(TASK_RUNNING); | 454 | __set_current_state(TASK_RUNNING); |
455 | remove_wait_queue(&vcpu->arch.local_int.wq, &wait); | 455 | remove_wait_queue(&vcpu->wq, &wait); |
456 | spin_unlock_bh(&vcpu->arch.local_int.lock); | 456 | spin_unlock_bh(&vcpu->arch.local_int.lock); |
457 | spin_unlock(&vcpu->arch.local_int.float_int->lock); | 457 | spin_unlock(&vcpu->arch.local_int.float_int->lock); |
458 | hrtimer_try_to_cancel(&vcpu->arch.ckc_timer); | 458 | hrtimer_try_to_cancel(&vcpu->arch.ckc_timer); |
@@ -465,8 +465,8 @@ void kvm_s390_tasklet(unsigned long parm) | |||
465 | 465 | ||
466 | spin_lock(&vcpu->arch.local_int.lock); | 466 | spin_lock(&vcpu->arch.local_int.lock); |
467 | vcpu->arch.local_int.timer_due = 1; | 467 | vcpu->arch.local_int.timer_due = 1; |
468 | if (waitqueue_active(&vcpu->arch.local_int.wq)) | 468 | if (waitqueue_active(&vcpu->wq)) |
469 | wake_up_interruptible(&vcpu->arch.local_int.wq); | 469 | wake_up_interruptible(&vcpu->wq); |
470 | spin_unlock(&vcpu->arch.local_int.lock); | 470 | spin_unlock(&vcpu->arch.local_int.lock); |
471 | } | 471 | } |
472 | 472 | ||
@@ -613,7 +613,7 @@ int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code) | |||
613 | spin_lock_bh(&li->lock); | 613 | spin_lock_bh(&li->lock); |
614 | list_add(&inti->list, &li->list); | 614 | list_add(&inti->list, &li->list); |
615 | atomic_set(&li->active, 1); | 615 | atomic_set(&li->active, 1); |
616 | BUG_ON(waitqueue_active(&li->wq)); | 616 | BUG_ON(waitqueue_active(li->wq)); |
617 | spin_unlock_bh(&li->lock); | 617 | spin_unlock_bh(&li->lock); |
618 | return 0; | 618 | return 0; |
619 | } | 619 | } |
@@ -746,8 +746,8 @@ int kvm_s390_inject_vm(struct kvm *kvm, | |||
746 | li = fi->local_int[sigcpu]; | 746 | li = fi->local_int[sigcpu]; |
747 | spin_lock_bh(&li->lock); | 747 | spin_lock_bh(&li->lock); |
748 | atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); | 748 | atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); |
749 | if (waitqueue_active(&li->wq)) | 749 | if (waitqueue_active(li->wq)) |
750 | wake_up_interruptible(&li->wq); | 750 | wake_up_interruptible(li->wq); |
751 | spin_unlock_bh(&li->lock); | 751 | spin_unlock_bh(&li->lock); |
752 | spin_unlock(&fi->lock); | 752 | spin_unlock(&fi->lock); |
753 | mutex_unlock(&kvm->lock); | 753 | mutex_unlock(&kvm->lock); |
@@ -832,8 +832,8 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, | |||
832 | if (inti->type == KVM_S390_SIGP_STOP) | 832 | if (inti->type == KVM_S390_SIGP_STOP) |
833 | li->action_bits |= ACTION_STOP_ON_STOP; | 833 | li->action_bits |= ACTION_STOP_ON_STOP; |
834 | atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); | 834 | atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); |
835 | if (waitqueue_active(&li->wq)) | 835 | if (waitqueue_active(&vcpu->wq)) |
836 | wake_up_interruptible(&vcpu->arch.local_int.wq); | 836 | wake_up_interruptible(&vcpu->wq); |
837 | spin_unlock_bh(&li->lock); | 837 | spin_unlock_bh(&li->lock); |
838 | mutex_unlock(&vcpu->kvm->lock); | 838 | mutex_unlock(&vcpu->kvm->lock); |
839 | return 0; | 839 | return 0; |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index c1c7c683fa26..ba694d2ba51e 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -59,6 +59,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { | |||
59 | { "deliver_restart_signal", VCPU_STAT(deliver_restart_signal) }, | 59 | { "deliver_restart_signal", VCPU_STAT(deliver_restart_signal) }, |
60 | { "deliver_program_interruption", VCPU_STAT(deliver_program_int) }, | 60 | { "deliver_program_interruption", VCPU_STAT(deliver_program_int) }, |
61 | { "exit_wait_state", VCPU_STAT(exit_wait_state) }, | 61 | { "exit_wait_state", VCPU_STAT(exit_wait_state) }, |
62 | { "instruction_pfmf", VCPU_STAT(instruction_pfmf) }, | ||
62 | { "instruction_stidp", VCPU_STAT(instruction_stidp) }, | 63 | { "instruction_stidp", VCPU_STAT(instruction_stidp) }, |
63 | { "instruction_spx", VCPU_STAT(instruction_spx) }, | 64 | { "instruction_spx", VCPU_STAT(instruction_spx) }, |
64 | { "instruction_stpx", VCPU_STAT(instruction_stpx) }, | 65 | { "instruction_stpx", VCPU_STAT(instruction_stpx) }, |
@@ -84,6 +85,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { | |||
84 | }; | 85 | }; |
85 | 86 | ||
86 | static unsigned long long *facilities; | 87 | static unsigned long long *facilities; |
88 | static struct gmap_notifier gmap_notifier; | ||
87 | 89 | ||
88 | /* Section: not file related */ | 90 | /* Section: not file related */ |
89 | int kvm_arch_hardware_enable(void *garbage) | 91 | int kvm_arch_hardware_enable(void *garbage) |
@@ -96,13 +98,18 @@ void kvm_arch_hardware_disable(void *garbage) | |||
96 | { | 98 | { |
97 | } | 99 | } |
98 | 100 | ||
101 | static void kvm_gmap_notifier(struct gmap *gmap, unsigned long address); | ||
102 | |||
99 | int kvm_arch_hardware_setup(void) | 103 | int kvm_arch_hardware_setup(void) |
100 | { | 104 | { |
105 | gmap_notifier.notifier_call = kvm_gmap_notifier; | ||
106 | gmap_register_ipte_notifier(&gmap_notifier); | ||
101 | return 0; | 107 | return 0; |
102 | } | 108 | } |
103 | 109 | ||
104 | void kvm_arch_hardware_unsetup(void) | 110 | void kvm_arch_hardware_unsetup(void) |
105 | { | 111 | { |
112 | gmap_unregister_ipte_notifier(&gmap_notifier); | ||
106 | } | 113 | } |
107 | 114 | ||
108 | void kvm_arch_check_processor_compat(void *rtn) | 115 | void kvm_arch_check_processor_compat(void *rtn) |
@@ -239,6 +246,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) | |||
239 | kvm->arch.gmap = gmap_alloc(current->mm); | 246 | kvm->arch.gmap = gmap_alloc(current->mm); |
240 | if (!kvm->arch.gmap) | 247 | if (!kvm->arch.gmap) |
241 | goto out_nogmap; | 248 | goto out_nogmap; |
249 | kvm->arch.gmap->private = kvm; | ||
242 | } | 250 | } |
243 | 251 | ||
244 | kvm->arch.css_support = 0; | 252 | kvm->arch.css_support = 0; |
@@ -270,7 +278,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) | |||
270 | 278 | ||
271 | free_page((unsigned long)(vcpu->arch.sie_block)); | 279 | free_page((unsigned long)(vcpu->arch.sie_block)); |
272 | kvm_vcpu_uninit(vcpu); | 280 | kvm_vcpu_uninit(vcpu); |
273 | kfree(vcpu); | 281 | kmem_cache_free(kvm_vcpu_cache, vcpu); |
274 | } | 282 | } |
275 | 283 | ||
276 | static void kvm_free_vcpus(struct kvm *kvm) | 284 | static void kvm_free_vcpus(struct kvm *kvm) |
@@ -309,6 +317,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) | |||
309 | vcpu->arch.gmap = gmap_alloc(current->mm); | 317 | vcpu->arch.gmap = gmap_alloc(current->mm); |
310 | if (!vcpu->arch.gmap) | 318 | if (!vcpu->arch.gmap) |
311 | return -ENOMEM; | 319 | return -ENOMEM; |
320 | vcpu->arch.gmap->private = vcpu->kvm; | ||
312 | return 0; | 321 | return 0; |
313 | } | 322 | } |
314 | 323 | ||
@@ -373,8 +382,10 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) | |||
373 | { | 382 | { |
374 | atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH | | 383 | atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH | |
375 | CPUSTAT_SM | | 384 | CPUSTAT_SM | |
376 | CPUSTAT_STOPPED); | 385 | CPUSTAT_STOPPED | |
386 | CPUSTAT_GED); | ||
377 | vcpu->arch.sie_block->ecb = 6; | 387 | vcpu->arch.sie_block->ecb = 6; |
388 | vcpu->arch.sie_block->ecb2 = 8; | ||
378 | vcpu->arch.sie_block->eca = 0xC1002001U; | 389 | vcpu->arch.sie_block->eca = 0xC1002001U; |
379 | vcpu->arch.sie_block->fac = (int) (long) facilities; | 390 | vcpu->arch.sie_block->fac = (int) (long) facilities; |
380 | hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); | 391 | hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); |
@@ -397,7 +408,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, | |||
397 | 408 | ||
398 | rc = -ENOMEM; | 409 | rc = -ENOMEM; |
399 | 410 | ||
400 | vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL); | 411 | vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); |
401 | if (!vcpu) | 412 | if (!vcpu) |
402 | goto out; | 413 | goto out; |
403 | 414 | ||
@@ -427,7 +438,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, | |||
427 | vcpu->arch.local_int.float_int = &kvm->arch.float_int; | 438 | vcpu->arch.local_int.float_int = &kvm->arch.float_int; |
428 | spin_lock(&kvm->arch.float_int.lock); | 439 | spin_lock(&kvm->arch.float_int.lock); |
429 | kvm->arch.float_int.local_int[id] = &vcpu->arch.local_int; | 440 | kvm->arch.float_int.local_int[id] = &vcpu->arch.local_int; |
430 | init_waitqueue_head(&vcpu->arch.local_int.wq); | 441 | vcpu->arch.local_int.wq = &vcpu->wq; |
431 | vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags; | 442 | vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags; |
432 | spin_unlock(&kvm->arch.float_int.lock); | 443 | spin_unlock(&kvm->arch.float_int.lock); |
433 | 444 | ||
@@ -442,7 +453,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, | |||
442 | out_free_sie_block: | 453 | out_free_sie_block: |
443 | free_page((unsigned long)(vcpu->arch.sie_block)); | 454 | free_page((unsigned long)(vcpu->arch.sie_block)); |
444 | out_free_cpu: | 455 | out_free_cpu: |
445 | kfree(vcpu); | 456 | kmem_cache_free(kvm_vcpu_cache, vcpu); |
446 | out: | 457 | out: |
447 | return ERR_PTR(rc); | 458 | return ERR_PTR(rc); |
448 | } | 459 | } |
@@ -454,6 +465,50 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu) | |||
454 | return 0; | 465 | return 0; |
455 | } | 466 | } |
456 | 467 | ||
468 | void s390_vcpu_block(struct kvm_vcpu *vcpu) | ||
469 | { | ||
470 | atomic_set_mask(PROG_BLOCK_SIE, &vcpu->arch.sie_block->prog20); | ||
471 | } | ||
472 | |||
473 | void s390_vcpu_unblock(struct kvm_vcpu *vcpu) | ||
474 | { | ||
475 | atomic_clear_mask(PROG_BLOCK_SIE, &vcpu->arch.sie_block->prog20); | ||
476 | } | ||
477 | |||
478 | /* | ||
479 | * Kick a guest cpu out of SIE and wait until SIE is not running. | ||
480 | * If the CPU is not running (e.g. waiting as idle) the function will | ||
481 | * return immediately. */ | ||
482 | void exit_sie(struct kvm_vcpu *vcpu) | ||
483 | { | ||
484 | atomic_set_mask(CPUSTAT_STOP_INT, &vcpu->arch.sie_block->cpuflags); | ||
485 | while (vcpu->arch.sie_block->prog0c & PROG_IN_SIE) | ||
486 | cpu_relax(); | ||
487 | } | ||
488 | |||
489 | /* Kick a guest cpu out of SIE and prevent SIE-reentry */ | ||
490 | void exit_sie_sync(struct kvm_vcpu *vcpu) | ||
491 | { | ||
492 | s390_vcpu_block(vcpu); | ||
493 | exit_sie(vcpu); | ||
494 | } | ||
495 | |||
496 | static void kvm_gmap_notifier(struct gmap *gmap, unsigned long address) | ||
497 | { | ||
498 | int i; | ||
499 | struct kvm *kvm = gmap->private; | ||
500 | struct kvm_vcpu *vcpu; | ||
501 | |||
502 | kvm_for_each_vcpu(i, vcpu, kvm) { | ||
503 | /* match against both prefix pages */ | ||
504 | if (vcpu->arch.sie_block->prefix == (address & ~0x1000UL)) { | ||
505 | VCPU_EVENT(vcpu, 2, "gmap notifier for %lx", address); | ||
506 | kvm_make_request(KVM_REQ_MMU_RELOAD, vcpu); | ||
507 | exit_sie_sync(vcpu); | ||
508 | } | ||
509 | } | ||
510 | } | ||
511 | |||
457 | int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu) | 512 | int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu) |
458 | { | 513 | { |
459 | /* kvm common code refers to this, but never calls it */ | 514 | /* kvm common code refers to this, but never calls it */ |
@@ -606,6 +661,27 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, | |||
606 | return -EINVAL; /* not implemented yet */ | 661 | return -EINVAL; /* not implemented yet */ |
607 | } | 662 | } |
608 | 663 | ||
664 | static int kvm_s390_handle_requests(struct kvm_vcpu *vcpu) | ||
665 | { | ||
666 | /* | ||
667 | * We use MMU_RELOAD just to re-arm the ipte notifier for the | ||
668 | * guest prefix page. gmap_ipte_notify will wait on the ptl lock. | ||
669 | * This ensures that the ipte instruction for this request has | ||
670 | * already finished. We might race against a second unmapper that | ||
671 | * wants to set the blocking bit. Lets just retry the request loop. | ||
672 | */ | ||
673 | while (kvm_check_request(KVM_REQ_MMU_RELOAD, vcpu)) { | ||
674 | int rc; | ||
675 | rc = gmap_ipte_notify(vcpu->arch.gmap, | ||
676 | vcpu->arch.sie_block->prefix, | ||
677 | PAGE_SIZE * 2); | ||
678 | if (rc) | ||
679 | return rc; | ||
680 | s390_vcpu_unblock(vcpu); | ||
681 | } | ||
682 | return 0; | ||
683 | } | ||
684 | |||
609 | static int __vcpu_run(struct kvm_vcpu *vcpu) | 685 | static int __vcpu_run(struct kvm_vcpu *vcpu) |
610 | { | 686 | { |
611 | int rc; | 687 | int rc; |
@@ -621,6 +697,10 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) | |||
621 | if (!kvm_is_ucontrol(vcpu->kvm)) | 697 | if (!kvm_is_ucontrol(vcpu->kvm)) |
622 | kvm_s390_deliver_pending_interrupts(vcpu); | 698 | kvm_s390_deliver_pending_interrupts(vcpu); |
623 | 699 | ||
700 | rc = kvm_s390_handle_requests(vcpu); | ||
701 | if (rc) | ||
702 | return rc; | ||
703 | |||
624 | vcpu->arch.sie_block->icptcode = 0; | 704 | vcpu->arch.sie_block->icptcode = 0; |
625 | preempt_disable(); | 705 | preempt_disable(); |
626 | kvm_guest_enter(); | 706 | kvm_guest_enter(); |
@@ -630,7 +710,9 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) | |||
630 | trace_kvm_s390_sie_enter(vcpu, | 710 | trace_kvm_s390_sie_enter(vcpu, |
631 | atomic_read(&vcpu->arch.sie_block->cpuflags)); | 711 | atomic_read(&vcpu->arch.sie_block->cpuflags)); |
632 | rc = sie64a(vcpu->arch.sie_block, vcpu->run->s.regs.gprs); | 712 | rc = sie64a(vcpu->arch.sie_block, vcpu->run->s.regs.gprs); |
633 | if (rc) { | 713 | if (rc > 0) |
714 | rc = 0; | ||
715 | if (rc < 0) { | ||
634 | if (kvm_is_ucontrol(vcpu->kvm)) { | 716 | if (kvm_is_ucontrol(vcpu->kvm)) { |
635 | rc = SIE_INTERCEPT_UCONTROL; | 717 | rc = SIE_INTERCEPT_UCONTROL; |
636 | } else { | 718 | } else { |
@@ -1046,7 +1128,7 @@ static int __init kvm_s390_init(void) | |||
1046 | return -ENOMEM; | 1128 | return -ENOMEM; |
1047 | } | 1129 | } |
1048 | memcpy(facilities, S390_lowcore.stfle_fac_list, 16); | 1130 | memcpy(facilities, S390_lowcore.stfle_fac_list, 16); |
1049 | facilities[0] &= 0xff00fff3f47c0000ULL; | 1131 | facilities[0] &= 0xff82fff3f47c0000ULL; |
1050 | facilities[1] &= 0x001c000000000000ULL; | 1132 | facilities[1] &= 0x001c000000000000ULL; |
1051 | return 0; | 1133 | return 0; |
1052 | } | 1134 | } |
@@ -1059,3 +1141,12 @@ static void __exit kvm_s390_exit(void) | |||
1059 | 1141 | ||
1060 | module_init(kvm_s390_init); | 1142 | module_init(kvm_s390_init); |
1061 | module_exit(kvm_s390_exit); | 1143 | module_exit(kvm_s390_exit); |
1144 | |||
1145 | /* | ||
1146 | * Enable autoloading of the kvm module. | ||
1147 | * Note that we add the module alias here instead of virt/kvm/kvm_main.c | ||
1148 | * since x86 takes a different approach. | ||
1149 | */ | ||
1150 | #include <linux/miscdevice.h> | ||
1151 | MODULE_ALIAS_MISCDEV(KVM_MINOR); | ||
1152 | MODULE_ALIAS("devname:kvm"); | ||
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h index efc14f687265..028ca9fd2158 100644 --- a/arch/s390/kvm/kvm-s390.h +++ b/arch/s390/kvm/kvm-s390.h | |||
@@ -63,6 +63,7 @@ static inline void kvm_s390_set_prefix(struct kvm_vcpu *vcpu, u32 prefix) | |||
63 | { | 63 | { |
64 | vcpu->arch.sie_block->prefix = prefix & 0x7fffe000u; | 64 | vcpu->arch.sie_block->prefix = prefix & 0x7fffe000u; |
65 | vcpu->arch.sie_block->ihcpu = 0xffff; | 65 | vcpu->arch.sie_block->ihcpu = 0xffff; |
66 | kvm_make_request(KVM_REQ_MMU_RELOAD, vcpu); | ||
66 | } | 67 | } |
67 | 68 | ||
68 | static inline u64 kvm_s390_get_base_disp_s(struct kvm_vcpu *vcpu) | 69 | static inline u64 kvm_s390_get_base_disp_s(struct kvm_vcpu *vcpu) |
@@ -85,6 +86,12 @@ static inline void kvm_s390_get_base_disp_sse(struct kvm_vcpu *vcpu, | |||
85 | *address2 = (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2; | 86 | *address2 = (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2; |
86 | } | 87 | } |
87 | 88 | ||
89 | static inline void kvm_s390_get_regs_rre(struct kvm_vcpu *vcpu, int *r1, int *r2) | ||
90 | { | ||
91 | *r1 = (vcpu->arch.sie_block->ipb & 0x00f00000) >> 20; | ||
92 | *r2 = (vcpu->arch.sie_block->ipb & 0x000f0000) >> 16; | ||
93 | } | ||
94 | |||
88 | static inline u64 kvm_s390_get_base_disp_rsy(struct kvm_vcpu *vcpu) | 95 | static inline u64 kvm_s390_get_base_disp_rsy(struct kvm_vcpu *vcpu) |
89 | { | 96 | { |
90 | u32 base2 = vcpu->arch.sie_block->ipb >> 28; | 97 | u32 base2 = vcpu->arch.sie_block->ipb >> 28; |
@@ -125,7 +132,8 @@ int kvm_s390_handle_e5(struct kvm_vcpu *vcpu); | |||
125 | int kvm_s390_handle_01(struct kvm_vcpu *vcpu); | 132 | int kvm_s390_handle_01(struct kvm_vcpu *vcpu); |
126 | int kvm_s390_handle_b9(struct kvm_vcpu *vcpu); | 133 | int kvm_s390_handle_b9(struct kvm_vcpu *vcpu); |
127 | int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu); | 134 | int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu); |
128 | int kvm_s390_handle_priv_eb(struct kvm_vcpu *vcpu); | 135 | int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu); |
136 | int kvm_s390_handle_eb(struct kvm_vcpu *vcpu); | ||
129 | 137 | ||
130 | /* implemented in sigp.c */ | 138 | /* implemented in sigp.c */ |
131 | int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu); | 139 | int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu); |
@@ -133,6 +141,10 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu); | |||
133 | /* implemented in kvm-s390.c */ | 141 | /* implemented in kvm-s390.c */ |
134 | int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, | 142 | int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, |
135 | unsigned long addr); | 143 | unsigned long addr); |
144 | void s390_vcpu_block(struct kvm_vcpu *vcpu); | ||
145 | void s390_vcpu_unblock(struct kvm_vcpu *vcpu); | ||
146 | void exit_sie(struct kvm_vcpu *vcpu); | ||
147 | void exit_sie_sync(struct kvm_vcpu *vcpu); | ||
136 | /* implemented in diag.c */ | 148 | /* implemented in diag.c */ |
137 | int kvm_s390_handle_diag(struct kvm_vcpu *vcpu); | 149 | int kvm_s390_handle_diag(struct kvm_vcpu *vcpu); |
138 | 150 | ||
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 6bbd7b5a0bbe..0da3e6eb6be6 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * handling privileged instructions | 2 | * handling privileged instructions |
3 | * | 3 | * |
4 | * Copyright IBM Corp. 2008 | 4 | * Copyright IBM Corp. 2008, 2013 |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 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) | 7 | * it under the terms of the GNU General Public License (version 2 only) |
@@ -20,6 +20,9 @@ | |||
20 | #include <asm/debug.h> | 20 | #include <asm/debug.h> |
21 | #include <asm/ebcdic.h> | 21 | #include <asm/ebcdic.h> |
22 | #include <asm/sysinfo.h> | 22 | #include <asm/sysinfo.h> |
23 | #include <asm/pgtable.h> | ||
24 | #include <asm/pgalloc.h> | ||
25 | #include <asm/io.h> | ||
23 | #include <asm/ptrace.h> | 26 | #include <asm/ptrace.h> |
24 | #include <asm/compat.h> | 27 | #include <asm/compat.h> |
25 | #include "gaccess.h" | 28 | #include "gaccess.h" |
@@ -34,6 +37,9 @@ static int handle_set_prefix(struct kvm_vcpu *vcpu) | |||
34 | 37 | ||
35 | vcpu->stat.instruction_spx++; | 38 | vcpu->stat.instruction_spx++; |
36 | 39 | ||
40 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | ||
41 | return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); | ||
42 | |||
37 | operand2 = kvm_s390_get_base_disp_s(vcpu); | 43 | operand2 = kvm_s390_get_base_disp_s(vcpu); |
38 | 44 | ||
39 | /* must be word boundary */ | 45 | /* must be word boundary */ |
@@ -65,6 +71,9 @@ static int handle_store_prefix(struct kvm_vcpu *vcpu) | |||
65 | 71 | ||
66 | vcpu->stat.instruction_stpx++; | 72 | vcpu->stat.instruction_stpx++; |
67 | 73 | ||
74 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | ||
75 | return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); | ||
76 | |||
68 | operand2 = kvm_s390_get_base_disp_s(vcpu); | 77 | operand2 = kvm_s390_get_base_disp_s(vcpu); |
69 | 78 | ||
70 | /* must be word boundary */ | 79 | /* must be word boundary */ |
@@ -89,6 +98,9 @@ static int handle_store_cpu_address(struct kvm_vcpu *vcpu) | |||
89 | 98 | ||
90 | vcpu->stat.instruction_stap++; | 99 | vcpu->stat.instruction_stap++; |
91 | 100 | ||
101 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | ||
102 | return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); | ||
103 | |||
92 | useraddr = kvm_s390_get_base_disp_s(vcpu); | 104 | useraddr = kvm_s390_get_base_disp_s(vcpu); |
93 | 105 | ||
94 | if (useraddr & 1) | 106 | if (useraddr & 1) |
@@ -105,7 +117,12 @@ static int handle_store_cpu_address(struct kvm_vcpu *vcpu) | |||
105 | static int handle_skey(struct kvm_vcpu *vcpu) | 117 | static int handle_skey(struct kvm_vcpu *vcpu) |
106 | { | 118 | { |
107 | vcpu->stat.instruction_storage_key++; | 119 | vcpu->stat.instruction_storage_key++; |
108 | vcpu->arch.sie_block->gpsw.addr -= 4; | 120 | |
121 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | ||
122 | return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); | ||
123 | |||
124 | vcpu->arch.sie_block->gpsw.addr = | ||
125 | __rewind_psw(vcpu->arch.sie_block->gpsw, 4); | ||
109 | VCPU_EVENT(vcpu, 4, "%s", "retrying storage key operation"); | 126 | VCPU_EVENT(vcpu, 4, "%s", "retrying storage key operation"); |
110 | return 0; | 127 | return 0; |
111 | } | 128 | } |
@@ -129,9 +146,10 @@ static int handle_tpi(struct kvm_vcpu *vcpu) | |||
129 | * Store the two-word I/O interruption code into the | 146 | * Store the two-word I/O interruption code into the |
130 | * provided area. | 147 | * provided area. |
131 | */ | 148 | */ |
132 | put_guest(vcpu, inti->io.subchannel_id, (u16 __user *) addr); | 149 | if (put_guest(vcpu, inti->io.subchannel_id, (u16 __user *)addr) |
133 | put_guest(vcpu, inti->io.subchannel_nr, (u16 __user *) (addr + 2)); | 150 | || put_guest(vcpu, inti->io.subchannel_nr, (u16 __user *)(addr + 2)) |
134 | put_guest(vcpu, inti->io.io_int_parm, (u32 __user *) (addr + 4)); | 151 | || put_guest(vcpu, inti->io.io_int_parm, (u32 __user *)(addr + 4))) |
152 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | ||
135 | } else { | 153 | } else { |
136 | /* | 154 | /* |
137 | * Store the three-word I/O interruption code into | 155 | * Store the three-word I/O interruption code into |
@@ -182,6 +200,9 @@ static int handle_io_inst(struct kvm_vcpu *vcpu) | |||
182 | { | 200 | { |
183 | VCPU_EVENT(vcpu, 4, "%s", "I/O instruction"); | 201 | VCPU_EVENT(vcpu, 4, "%s", "I/O instruction"); |
184 | 202 | ||
203 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | ||
204 | return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); | ||
205 | |||
185 | if (vcpu->kvm->arch.css_support) { | 206 | if (vcpu->kvm->arch.css_support) { |
186 | /* | 207 | /* |
187 | * Most I/O instructions will be handled by userspace. | 208 | * Most I/O instructions will be handled by userspace. |
@@ -210,8 +231,12 @@ static int handle_stfl(struct kvm_vcpu *vcpu) | |||
210 | int rc; | 231 | int rc; |
211 | 232 | ||
212 | vcpu->stat.instruction_stfl++; | 233 | vcpu->stat.instruction_stfl++; |
234 | |||
235 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | ||
236 | return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); | ||
237 | |||
213 | /* only pass the facility bits, which we can handle */ | 238 | /* only pass the facility bits, which we can handle */ |
214 | facility_list = S390_lowcore.stfl_fac_list & 0xff00fff3; | 239 | facility_list = S390_lowcore.stfl_fac_list & 0xff82fff3; |
215 | 240 | ||
216 | rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list), | 241 | rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list), |
217 | &facility_list, sizeof(facility_list)); | 242 | &facility_list, sizeof(facility_list)); |
@@ -255,8 +280,8 @@ int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu) | |||
255 | u64 addr; | 280 | u64 addr; |
256 | 281 | ||
257 | if (gpsw->mask & PSW_MASK_PSTATE) | 282 | if (gpsw->mask & PSW_MASK_PSTATE) |
258 | return kvm_s390_inject_program_int(vcpu, | 283 | return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); |
259 | PGM_PRIVILEGED_OPERATION); | 284 | |
260 | addr = kvm_s390_get_base_disp_s(vcpu); | 285 | addr = kvm_s390_get_base_disp_s(vcpu); |
261 | if (addr & 7) | 286 | if (addr & 7) |
262 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | 287 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); |
@@ -278,6 +303,9 @@ static int handle_lpswe(struct kvm_vcpu *vcpu) | |||
278 | psw_t new_psw; | 303 | psw_t new_psw; |
279 | u64 addr; | 304 | u64 addr; |
280 | 305 | ||
306 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | ||
307 | return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); | ||
308 | |||
281 | addr = kvm_s390_get_base_disp_s(vcpu); | 309 | addr = kvm_s390_get_base_disp_s(vcpu); |
282 | if (addr & 7) | 310 | if (addr & 7) |
283 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | 311 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); |
@@ -296,6 +324,9 @@ static int handle_stidp(struct kvm_vcpu *vcpu) | |||
296 | 324 | ||
297 | vcpu->stat.instruction_stidp++; | 325 | vcpu->stat.instruction_stidp++; |
298 | 326 | ||
327 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | ||
328 | return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); | ||
329 | |||
299 | operand2 = kvm_s390_get_base_disp_s(vcpu); | 330 | operand2 = kvm_s390_get_base_disp_s(vcpu); |
300 | 331 | ||
301 | if (operand2 & 7) | 332 | if (operand2 & 7) |
@@ -351,16 +382,30 @@ static int handle_stsi(struct kvm_vcpu *vcpu) | |||
351 | vcpu->stat.instruction_stsi++; | 382 | vcpu->stat.instruction_stsi++; |
352 | VCPU_EVENT(vcpu, 4, "stsi: fc: %x sel1: %x sel2: %x", fc, sel1, sel2); | 383 | VCPU_EVENT(vcpu, 4, "stsi: fc: %x sel1: %x sel2: %x", fc, sel1, sel2); |
353 | 384 | ||
354 | operand2 = kvm_s390_get_base_disp_s(vcpu); | 385 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) |
386 | return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); | ||
387 | |||
388 | if (fc > 3) { | ||
389 | vcpu->arch.sie_block->gpsw.mask |= 3ul << 44; /* cc 3 */ | ||
390 | return 0; | ||
391 | } | ||
355 | 392 | ||
356 | if (operand2 & 0xfff && fc > 0) | 393 | if (vcpu->run->s.regs.gprs[0] & 0x0fffff00 |
394 | || vcpu->run->s.regs.gprs[1] & 0xffff0000) | ||
357 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | 395 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); |
358 | 396 | ||
359 | switch (fc) { | 397 | if (fc == 0) { |
360 | case 0: | ||
361 | vcpu->run->s.regs.gprs[0] = 3 << 28; | 398 | vcpu->run->s.regs.gprs[0] = 3 << 28; |
362 | vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); | 399 | vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); /* cc 0 */ |
363 | return 0; | 400 | return 0; |
401 | } | ||
402 | |||
403 | operand2 = kvm_s390_get_base_disp_s(vcpu); | ||
404 | |||
405 | if (operand2 & 0xfff) | ||
406 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
407 | |||
408 | switch (fc) { | ||
364 | case 1: /* same handling for 1 and 2 */ | 409 | case 1: /* same handling for 1 and 2 */ |
365 | case 2: | 410 | case 2: |
366 | mem = get_zeroed_page(GFP_KERNEL); | 411 | mem = get_zeroed_page(GFP_KERNEL); |
@@ -377,8 +422,6 @@ static int handle_stsi(struct kvm_vcpu *vcpu) | |||
377 | goto out_no_data; | 422 | goto out_no_data; |
378 | handle_stsi_3_2_2(vcpu, (void *) mem); | 423 | handle_stsi_3_2_2(vcpu, (void *) mem); |
379 | break; | 424 | break; |
380 | default: | ||
381 | goto out_no_data; | ||
382 | } | 425 | } |
383 | 426 | ||
384 | if (copy_to_guest_absolute(vcpu, operand2, (void *) mem, PAGE_SIZE)) { | 427 | if (copy_to_guest_absolute(vcpu, operand2, (void *) mem, PAGE_SIZE)) { |
@@ -432,20 +475,14 @@ int kvm_s390_handle_b2(struct kvm_vcpu *vcpu) | |||
432 | intercept_handler_t handler; | 475 | intercept_handler_t handler; |
433 | 476 | ||
434 | /* | 477 | /* |
435 | * a lot of B2 instructions are priviledged. We first check for | 478 | * A lot of B2 instructions are priviledged. Here we check for |
436 | * the privileged ones, that we can handle in the kernel. If the | 479 | * the privileged ones, that we can handle in the kernel. |
437 | * kernel can handle this instruction, we check for the problem | 480 | * Anything else goes to userspace. |
438 | * state bit and (a) handle the instruction or (b) send a code 2 | 481 | */ |
439 | * program check. | ||
440 | * Anything else goes to userspace.*/ | ||
441 | handler = b2_handlers[vcpu->arch.sie_block->ipa & 0x00ff]; | 482 | handler = b2_handlers[vcpu->arch.sie_block->ipa & 0x00ff]; |
442 | if (handler) { | 483 | if (handler) |
443 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | 484 | return handler(vcpu); |
444 | return kvm_s390_inject_program_int(vcpu, | 485 | |
445 | PGM_PRIVILEGED_OPERATION); | ||
446 | else | ||
447 | return handler(vcpu); | ||
448 | } | ||
449 | return -EOPNOTSUPP; | 486 | return -EOPNOTSUPP; |
450 | } | 487 | } |
451 | 488 | ||
@@ -453,8 +490,7 @@ static int handle_epsw(struct kvm_vcpu *vcpu) | |||
453 | { | 490 | { |
454 | int reg1, reg2; | 491 | int reg1, reg2; |
455 | 492 | ||
456 | reg1 = (vcpu->arch.sie_block->ipb & 0x00f00000) >> 24; | 493 | kvm_s390_get_regs_rre(vcpu, ®1, ®2); |
457 | reg2 = (vcpu->arch.sie_block->ipb & 0x000f0000) >> 16; | ||
458 | 494 | ||
459 | /* This basically extracts the mask half of the psw. */ | 495 | /* This basically extracts the mask half of the psw. */ |
460 | vcpu->run->s.regs.gprs[reg1] &= 0xffffffff00000000; | 496 | vcpu->run->s.regs.gprs[reg1] &= 0xffffffff00000000; |
@@ -467,9 +503,88 @@ static int handle_epsw(struct kvm_vcpu *vcpu) | |||
467 | return 0; | 503 | return 0; |
468 | } | 504 | } |
469 | 505 | ||
506 | #define PFMF_RESERVED 0xfffc0101UL | ||
507 | #define PFMF_SK 0x00020000UL | ||
508 | #define PFMF_CF 0x00010000UL | ||
509 | #define PFMF_UI 0x00008000UL | ||
510 | #define PFMF_FSC 0x00007000UL | ||
511 | #define PFMF_NQ 0x00000800UL | ||
512 | #define PFMF_MR 0x00000400UL | ||
513 | #define PFMF_MC 0x00000200UL | ||
514 | #define PFMF_KEY 0x000000feUL | ||
515 | |||
516 | static int handle_pfmf(struct kvm_vcpu *vcpu) | ||
517 | { | ||
518 | int reg1, reg2; | ||
519 | unsigned long start, end; | ||
520 | |||
521 | vcpu->stat.instruction_pfmf++; | ||
522 | |||
523 | kvm_s390_get_regs_rre(vcpu, ®1, ®2); | ||
524 | |||
525 | if (!MACHINE_HAS_PFMF) | ||
526 | return kvm_s390_inject_program_int(vcpu, PGM_OPERATION); | ||
527 | |||
528 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | ||
529 | return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); | ||
530 | |||
531 | if (vcpu->run->s.regs.gprs[reg1] & PFMF_RESERVED) | ||
532 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
533 | |||
534 | /* Only provide non-quiescing support if the host supports it */ | ||
535 | if (vcpu->run->s.regs.gprs[reg1] & PFMF_NQ && | ||
536 | S390_lowcore.stfl_fac_list & 0x00020000) | ||
537 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
538 | |||
539 | /* No support for conditional-SSKE */ | ||
540 | if (vcpu->run->s.regs.gprs[reg1] & (PFMF_MR | PFMF_MC)) | ||
541 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
542 | |||
543 | start = vcpu->run->s.regs.gprs[reg2] & PAGE_MASK; | ||
544 | switch (vcpu->run->s.regs.gprs[reg1] & PFMF_FSC) { | ||
545 | case 0x00000000: | ||
546 | end = (start + (1UL << 12)) & ~((1UL << 12) - 1); | ||
547 | break; | ||
548 | case 0x00001000: | ||
549 | end = (start + (1UL << 20)) & ~((1UL << 20) - 1); | ||
550 | break; | ||
551 | /* We dont support EDAT2 | ||
552 | case 0x00002000: | ||
553 | end = (start + (1UL << 31)) & ~((1UL << 31) - 1); | ||
554 | break;*/ | ||
555 | default: | ||
556 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
557 | } | ||
558 | while (start < end) { | ||
559 | unsigned long useraddr; | ||
560 | |||
561 | useraddr = gmap_translate(start, vcpu->arch.gmap); | ||
562 | if (IS_ERR((void *)useraddr)) | ||
563 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | ||
564 | |||
565 | if (vcpu->run->s.regs.gprs[reg1] & PFMF_CF) { | ||
566 | if (clear_user((void __user *)useraddr, PAGE_SIZE)) | ||
567 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | ||
568 | } | ||
569 | |||
570 | if (vcpu->run->s.regs.gprs[reg1] & PFMF_SK) { | ||
571 | if (set_guest_storage_key(current->mm, useraddr, | ||
572 | vcpu->run->s.regs.gprs[reg1] & PFMF_KEY, | ||
573 | vcpu->run->s.regs.gprs[reg1] & PFMF_NQ)) | ||
574 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | ||
575 | } | ||
576 | |||
577 | start += PAGE_SIZE; | ||
578 | } | ||
579 | if (vcpu->run->s.regs.gprs[reg1] & PFMF_FSC) | ||
580 | vcpu->run->s.regs.gprs[reg2] = end; | ||
581 | return 0; | ||
582 | } | ||
583 | |||
470 | static const intercept_handler_t b9_handlers[256] = { | 584 | static const intercept_handler_t b9_handlers[256] = { |
471 | [0x8d] = handle_epsw, | 585 | [0x8d] = handle_epsw, |
472 | [0x9c] = handle_io_inst, | 586 | [0x9c] = handle_io_inst, |
587 | [0xaf] = handle_pfmf, | ||
473 | }; | 588 | }; |
474 | 589 | ||
475 | int kvm_s390_handle_b9(struct kvm_vcpu *vcpu) | 590 | int kvm_s390_handle_b9(struct kvm_vcpu *vcpu) |
@@ -478,29 +593,96 @@ int kvm_s390_handle_b9(struct kvm_vcpu *vcpu) | |||
478 | 593 | ||
479 | /* This is handled just as for the B2 instructions. */ | 594 | /* This is handled just as for the B2 instructions. */ |
480 | handler = b9_handlers[vcpu->arch.sie_block->ipa & 0x00ff]; | 595 | handler = b9_handlers[vcpu->arch.sie_block->ipa & 0x00ff]; |
481 | if (handler) { | 596 | if (handler) |
482 | if ((handler != handle_epsw) && | 597 | return handler(vcpu); |
483 | (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)) | 598 | |
484 | return kvm_s390_inject_program_int(vcpu, | ||
485 | PGM_PRIVILEGED_OPERATION); | ||
486 | else | ||
487 | return handler(vcpu); | ||
488 | } | ||
489 | return -EOPNOTSUPP; | 599 | return -EOPNOTSUPP; |
490 | } | 600 | } |
491 | 601 | ||
602 | int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu) | ||
603 | { | ||
604 | int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; | ||
605 | int reg3 = vcpu->arch.sie_block->ipa & 0x000f; | ||
606 | u64 useraddr; | ||
607 | u32 val = 0; | ||
608 | int reg, rc; | ||
609 | |||
610 | vcpu->stat.instruction_lctl++; | ||
611 | |||
612 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | ||
613 | return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); | ||
614 | |||
615 | useraddr = kvm_s390_get_base_disp_rs(vcpu); | ||
616 | |||
617 | if (useraddr & 3) | ||
618 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
619 | |||
620 | VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x, addr:%llx", reg1, reg3, | ||
621 | useraddr); | ||
622 | trace_kvm_s390_handle_lctl(vcpu, 0, reg1, reg3, useraddr); | ||
623 | |||
624 | reg = reg1; | ||
625 | do { | ||
626 | rc = get_guest(vcpu, val, (u32 __user *) useraddr); | ||
627 | if (rc) | ||
628 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | ||
629 | vcpu->arch.sie_block->gcr[reg] &= 0xffffffff00000000ul; | ||
630 | vcpu->arch.sie_block->gcr[reg] |= val; | ||
631 | useraddr += 4; | ||
632 | if (reg == reg3) | ||
633 | break; | ||
634 | reg = (reg + 1) % 16; | ||
635 | } while (1); | ||
636 | |||
637 | return 0; | ||
638 | } | ||
639 | |||
640 | static int handle_lctlg(struct kvm_vcpu *vcpu) | ||
641 | { | ||
642 | int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; | ||
643 | int reg3 = vcpu->arch.sie_block->ipa & 0x000f; | ||
644 | u64 useraddr; | ||
645 | int reg, rc; | ||
646 | |||
647 | vcpu->stat.instruction_lctlg++; | ||
648 | |||
649 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | ||
650 | return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); | ||
651 | |||
652 | useraddr = kvm_s390_get_base_disp_rsy(vcpu); | ||
653 | |||
654 | if (useraddr & 7) | ||
655 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
656 | |||
657 | reg = reg1; | ||
658 | |||
659 | VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x, addr:%llx", reg1, reg3, | ||
660 | useraddr); | ||
661 | trace_kvm_s390_handle_lctl(vcpu, 1, reg1, reg3, useraddr); | ||
662 | |||
663 | do { | ||
664 | rc = get_guest(vcpu, vcpu->arch.sie_block->gcr[reg], | ||
665 | (u64 __user *) useraddr); | ||
666 | if (rc) | ||
667 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | ||
668 | useraddr += 8; | ||
669 | if (reg == reg3) | ||
670 | break; | ||
671 | reg = (reg + 1) % 16; | ||
672 | } while (1); | ||
673 | |||
674 | return 0; | ||
675 | } | ||
676 | |||
492 | static const intercept_handler_t eb_handlers[256] = { | 677 | static const intercept_handler_t eb_handlers[256] = { |
678 | [0x2f] = handle_lctlg, | ||
493 | [0x8a] = handle_io_inst, | 679 | [0x8a] = handle_io_inst, |
494 | }; | 680 | }; |
495 | 681 | ||
496 | int kvm_s390_handle_priv_eb(struct kvm_vcpu *vcpu) | 682 | int kvm_s390_handle_eb(struct kvm_vcpu *vcpu) |
497 | { | 683 | { |
498 | intercept_handler_t handler; | 684 | intercept_handler_t handler; |
499 | 685 | ||
500 | /* All eb instructions that end up here are privileged. */ | ||
501 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | ||
502 | return kvm_s390_inject_program_int(vcpu, | ||
503 | PGM_PRIVILEGED_OPERATION); | ||
504 | handler = eb_handlers[vcpu->arch.sie_block->ipb & 0xff]; | 686 | handler = eb_handlers[vcpu->arch.sie_block->ipb & 0xff]; |
505 | if (handler) | 687 | if (handler) |
506 | return handler(vcpu); | 688 | return handler(vcpu); |
@@ -515,6 +697,9 @@ static int handle_tprot(struct kvm_vcpu *vcpu) | |||
515 | 697 | ||
516 | vcpu->stat.instruction_tprot++; | 698 | vcpu->stat.instruction_tprot++; |
517 | 699 | ||
700 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | ||
701 | return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); | ||
702 | |||
518 | kvm_s390_get_base_disp_sse(vcpu, &address1, &address2); | 703 | kvm_s390_get_base_disp_sse(vcpu, &address1, &address2); |
519 | 704 | ||
520 | /* we only handle the Linux memory detection case: | 705 | /* we only handle the Linux memory detection case: |
@@ -560,8 +745,7 @@ static int handle_sckpf(struct kvm_vcpu *vcpu) | |||
560 | u32 value; | 745 | u32 value; |
561 | 746 | ||
562 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | 747 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) |
563 | return kvm_s390_inject_program_int(vcpu, | 748 | return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); |
564 | PGM_PRIVILEGED_OPERATION); | ||
565 | 749 | ||
566 | if (vcpu->run->s.regs.gprs[0] & 0x00000000ffff0000) | 750 | if (vcpu->run->s.regs.gprs[0] & 0x00000000ffff0000) |
567 | return kvm_s390_inject_program_int(vcpu, | 751 | return kvm_s390_inject_program_int(vcpu, |
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index 1c48ab2845e0..bec398c57acf 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c | |||
@@ -79,8 +79,8 @@ static int __sigp_emergency(struct kvm_vcpu *vcpu, u16 cpu_addr) | |||
79 | list_add_tail(&inti->list, &li->list); | 79 | list_add_tail(&inti->list, &li->list); |
80 | atomic_set(&li->active, 1); | 80 | atomic_set(&li->active, 1); |
81 | atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); | 81 | atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); |
82 | if (waitqueue_active(&li->wq)) | 82 | if (waitqueue_active(li->wq)) |
83 | wake_up_interruptible(&li->wq); | 83 | wake_up_interruptible(li->wq); |
84 | spin_unlock_bh(&li->lock); | 84 | spin_unlock_bh(&li->lock); |
85 | rc = SIGP_CC_ORDER_CODE_ACCEPTED; | 85 | rc = SIGP_CC_ORDER_CODE_ACCEPTED; |
86 | VCPU_EVENT(vcpu, 4, "sent sigp emerg to cpu %x", cpu_addr); | 86 | VCPU_EVENT(vcpu, 4, "sent sigp emerg to cpu %x", cpu_addr); |
@@ -117,8 +117,8 @@ static int __sigp_external_call(struct kvm_vcpu *vcpu, u16 cpu_addr) | |||
117 | list_add_tail(&inti->list, &li->list); | 117 | list_add_tail(&inti->list, &li->list); |
118 | atomic_set(&li->active, 1); | 118 | atomic_set(&li->active, 1); |
119 | atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); | 119 | atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); |
120 | if (waitqueue_active(&li->wq)) | 120 | if (waitqueue_active(li->wq)) |
121 | wake_up_interruptible(&li->wq); | 121 | wake_up_interruptible(li->wq); |
122 | spin_unlock_bh(&li->lock); | 122 | spin_unlock_bh(&li->lock); |
123 | rc = SIGP_CC_ORDER_CODE_ACCEPTED; | 123 | rc = SIGP_CC_ORDER_CODE_ACCEPTED; |
124 | VCPU_EVENT(vcpu, 4, "sent sigp ext call to cpu %x", cpu_addr); | 124 | VCPU_EVENT(vcpu, 4, "sent sigp ext call to cpu %x", cpu_addr); |
@@ -145,8 +145,8 @@ static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action) | |||
145 | atomic_set(&li->active, 1); | 145 | atomic_set(&li->active, 1); |
146 | atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags); | 146 | atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags); |
147 | li->action_bits |= action; | 147 | li->action_bits |= action; |
148 | if (waitqueue_active(&li->wq)) | 148 | if (waitqueue_active(li->wq)) |
149 | wake_up_interruptible(&li->wq); | 149 | wake_up_interruptible(li->wq); |
150 | out: | 150 | out: |
151 | spin_unlock_bh(&li->lock); | 151 | spin_unlock_bh(&li->lock); |
152 | 152 | ||
@@ -250,8 +250,8 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address, | |||
250 | 250 | ||
251 | list_add_tail(&inti->list, &li->list); | 251 | list_add_tail(&inti->list, &li->list); |
252 | atomic_set(&li->active, 1); | 252 | atomic_set(&li->active, 1); |
253 | if (waitqueue_active(&li->wq)) | 253 | if (waitqueue_active(li->wq)) |
254 | wake_up_interruptible(&li->wq); | 254 | wake_up_interruptible(li->wq); |
255 | rc = SIGP_CC_ORDER_CODE_ACCEPTED; | 255 | rc = SIGP_CC_ORDER_CODE_ACCEPTED; |
256 | 256 | ||
257 | VCPU_EVENT(vcpu, 4, "set prefix of cpu %02x to %x", cpu_addr, address); | 257 | VCPU_EVENT(vcpu, 4, "set prefix of cpu %02x to %x", cpu_addr, address); |
@@ -333,8 +333,7 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) | |||
333 | 333 | ||
334 | /* sigp in userspace can exit */ | 334 | /* sigp in userspace can exit */ |
335 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | 335 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) |
336 | return kvm_s390_inject_program_int(vcpu, | 336 | return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); |
337 | PGM_PRIVILEGED_OPERATION); | ||
338 | 337 | ||
339 | order_code = kvm_s390_get_base_disp_rs(vcpu); | 338 | order_code = kvm_s390_get_base_disp_rs(vcpu); |
340 | 339 | ||