diff options
Diffstat (limited to 'arch/s390/kvm')
-rw-r--r-- | arch/s390/kvm/intercept.c | 12 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.c | 3 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.h | 12 | ||||
-rw-r--r-- | arch/s390/kvm/priv.c | 83 |
4 files changed, 37 insertions, 73 deletions
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index c6ba4dfd7f1e..b7d1b2edeeb3 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c | |||
@@ -45,10 +45,8 @@ static int handle_lctlg(struct kvm_vcpu *vcpu) | |||
45 | do { | 45 | do { |
46 | rc = get_guest(vcpu, vcpu->arch.sie_block->gcr[reg], | 46 | rc = get_guest(vcpu, vcpu->arch.sie_block->gcr[reg], |
47 | (u64 __user *) useraddr); | 47 | (u64 __user *) useraddr); |
48 | if (rc) { | 48 | if (rc) |
49 | kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | 49 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); |
50 | break; | ||
51 | } | ||
52 | useraddr += 8; | 50 | useraddr += 8; |
53 | if (reg == reg3) | 51 | if (reg == reg3) |
54 | break; | 52 | break; |
@@ -79,10 +77,8 @@ static int handle_lctl(struct kvm_vcpu *vcpu) | |||
79 | reg = reg1; | 77 | reg = reg1; |
80 | do { | 78 | do { |
81 | rc = get_guest(vcpu, val, (u32 __user *) useraddr); | 79 | rc = get_guest(vcpu, val, (u32 __user *) useraddr); |
82 | if (rc) { | 80 | if (rc) |
83 | kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | 81 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); |
84 | break; | ||
85 | } | ||
86 | vcpu->arch.sie_block->gcr[reg] &= 0xffffffff00000000ul; | 82 | vcpu->arch.sie_block->gcr[reg] &= 0xffffffff00000000ul; |
87 | vcpu->arch.sie_block->gcr[reg] |= val; | 83 | vcpu->arch.sie_block->gcr[reg] |= val; |
88 | useraddr += 4; | 84 | useraddr += 4; |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index f241e3315ebb..d05a59c1eea7 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -633,8 +633,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) | |||
633 | } else { | 633 | } else { |
634 | VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction"); | 634 | VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction"); |
635 | trace_kvm_s390_sie_fault(vcpu); | 635 | trace_kvm_s390_sie_fault(vcpu); |
636 | kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | 636 | rc = kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); |
637 | rc = 0; | ||
638 | } | 637 | } |
639 | } | 638 | } |
640 | VCPU_EVENT(vcpu, 6, "exit sie icptcode %d", | 639 | VCPU_EVENT(vcpu, 6, "exit sie icptcode %d", |
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h index 4d89d64a8161..efc14f687265 100644 --- a/arch/s390/kvm/kvm-s390.h +++ b/arch/s390/kvm/kvm-s390.h | |||
@@ -110,12 +110,12 @@ enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer); | |||
110 | void kvm_s390_tasklet(unsigned long parm); | 110 | void kvm_s390_tasklet(unsigned long parm); |
111 | void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu); | 111 | void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu); |
112 | void kvm_s390_deliver_pending_machine_checks(struct kvm_vcpu *vcpu); | 112 | void kvm_s390_deliver_pending_machine_checks(struct kvm_vcpu *vcpu); |
113 | int kvm_s390_inject_vm(struct kvm *kvm, | 113 | int __must_check kvm_s390_inject_vm(struct kvm *kvm, |
114 | struct kvm_s390_interrupt *s390int); | 114 | struct kvm_s390_interrupt *s390int); |
115 | int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, | 115 | int __must_check kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, |
116 | struct kvm_s390_interrupt *s390int); | 116 | struct kvm_s390_interrupt *s390int); |
117 | int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code); | 117 | int __must_check kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code); |
118 | int kvm_s390_inject_sigp_stop(struct kvm_vcpu *vcpu, int action); | 118 | int __must_check kvm_s390_inject_sigp_stop(struct kvm_vcpu *vcpu, int action); |
119 | struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm, | 119 | struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm, |
120 | u64 cr6, u64 schid); | 120 | u64 cr6, u64 schid); |
121 | 121 | ||
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 05d186c21eca..23a8370b1045 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c | |||
@@ -36,31 +36,24 @@ static int handle_set_prefix(struct kvm_vcpu *vcpu) | |||
36 | operand2 = kvm_s390_get_base_disp_s(vcpu); | 36 | operand2 = kvm_s390_get_base_disp_s(vcpu); |
37 | 37 | ||
38 | /* must be word boundary */ | 38 | /* must be word boundary */ |
39 | if (operand2 & 3) { | 39 | if (operand2 & 3) |
40 | kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | 40 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); |
41 | goto out; | ||
42 | } | ||
43 | 41 | ||
44 | /* get the value */ | 42 | /* get the value */ |
45 | if (get_guest(vcpu, address, (u32 __user *) operand2)) { | 43 | if (get_guest(vcpu, address, (u32 __user *) operand2)) |
46 | kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | 44 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); |
47 | goto out; | ||
48 | } | ||
49 | 45 | ||
50 | address = address & 0x7fffe000u; | 46 | address = address & 0x7fffe000u; |
51 | 47 | ||
52 | /* make sure that the new value is valid memory */ | 48 | /* make sure that the new value is valid memory */ |
53 | if (copy_from_guest_absolute(vcpu, &tmp, address, 1) || | 49 | if (copy_from_guest_absolute(vcpu, &tmp, address, 1) || |
54 | (copy_from_guest_absolute(vcpu, &tmp, address + PAGE_SIZE, 1))) { | 50 | (copy_from_guest_absolute(vcpu, &tmp, address + PAGE_SIZE, 1))) |
55 | kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | 51 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); |
56 | goto out; | ||
57 | } | ||
58 | 52 | ||
59 | kvm_s390_set_prefix(vcpu, address); | 53 | kvm_s390_set_prefix(vcpu, address); |
60 | 54 | ||
61 | VCPU_EVENT(vcpu, 5, "setting prefix to %x", address); | 55 | VCPU_EVENT(vcpu, 5, "setting prefix to %x", address); |
62 | trace_kvm_s390_handle_prefix(vcpu, 1, address); | 56 | trace_kvm_s390_handle_prefix(vcpu, 1, address); |
63 | out: | ||
64 | return 0; | 57 | return 0; |
65 | } | 58 | } |
66 | 59 | ||
@@ -74,49 +67,37 @@ static int handle_store_prefix(struct kvm_vcpu *vcpu) | |||
74 | operand2 = kvm_s390_get_base_disp_s(vcpu); | 67 | operand2 = kvm_s390_get_base_disp_s(vcpu); |
75 | 68 | ||
76 | /* must be word boundary */ | 69 | /* must be word boundary */ |
77 | if (operand2 & 3) { | 70 | if (operand2 & 3) |
78 | kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | 71 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); |
79 | goto out; | ||
80 | } | ||
81 | 72 | ||
82 | address = vcpu->arch.sie_block->prefix; | 73 | address = vcpu->arch.sie_block->prefix; |
83 | address = address & 0x7fffe000u; | 74 | address = address & 0x7fffe000u; |
84 | 75 | ||
85 | /* get the value */ | 76 | /* get the value */ |
86 | if (put_guest(vcpu, address, (u32 __user *)operand2)) { | 77 | if (put_guest(vcpu, address, (u32 __user *)operand2)) |
87 | kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | 78 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); |
88 | goto out; | ||
89 | } | ||
90 | 79 | ||
91 | VCPU_EVENT(vcpu, 5, "storing prefix to %x", address); | 80 | VCPU_EVENT(vcpu, 5, "storing prefix to %x", address); |
92 | trace_kvm_s390_handle_prefix(vcpu, 0, address); | 81 | trace_kvm_s390_handle_prefix(vcpu, 0, address); |
93 | out: | ||
94 | return 0; | 82 | return 0; |
95 | } | 83 | } |
96 | 84 | ||
97 | static int handle_store_cpu_address(struct kvm_vcpu *vcpu) | 85 | static int handle_store_cpu_address(struct kvm_vcpu *vcpu) |
98 | { | 86 | { |
99 | u64 useraddr; | 87 | u64 useraddr; |
100 | int rc; | ||
101 | 88 | ||
102 | vcpu->stat.instruction_stap++; | 89 | vcpu->stat.instruction_stap++; |
103 | 90 | ||
104 | useraddr = kvm_s390_get_base_disp_s(vcpu); | 91 | useraddr = kvm_s390_get_base_disp_s(vcpu); |
105 | 92 | ||
106 | if (useraddr & 1) { | 93 | if (useraddr & 1) |
107 | kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | 94 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); |
108 | goto out; | ||
109 | } | ||
110 | 95 | ||
111 | rc = put_guest(vcpu, vcpu->vcpu_id, (u16 __user *)useraddr); | 96 | if (put_guest(vcpu, vcpu->vcpu_id, (u16 __user *)useraddr)) |
112 | if (rc) { | 97 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); |
113 | kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | ||
114 | goto out; | ||
115 | } | ||
116 | 98 | ||
117 | VCPU_EVENT(vcpu, 5, "storing cpu address to %llx", useraddr); | 99 | VCPU_EVENT(vcpu, 5, "storing cpu address to %llx", useraddr); |
118 | trace_kvm_s390_handle_stap(vcpu, useraddr); | 100 | trace_kvm_s390_handle_stap(vcpu, useraddr); |
119 | out: | ||
120 | return 0; | 101 | return 0; |
121 | } | 102 | } |
122 | 103 | ||
@@ -135,10 +116,8 @@ static int handle_tpi(struct kvm_vcpu *vcpu) | |||
135 | int cc; | 116 | int cc; |
136 | 117 | ||
137 | addr = kvm_s390_get_base_disp_s(vcpu); | 118 | addr = kvm_s390_get_base_disp_s(vcpu); |
138 | if (addr & 3) { | 119 | if (addr & 3) |
139 | kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | 120 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); |
140 | goto out; | ||
141 | } | ||
142 | cc = 0; | 121 | cc = 0; |
143 | inti = kvm_s390_get_io_int(vcpu->kvm, vcpu->run->s.regs.crs[6], 0); | 122 | inti = kvm_s390_get_io_int(vcpu->kvm, vcpu->run->s.regs.crs[6], 0); |
144 | if (!inti) | 123 | if (!inti) |
@@ -167,7 +146,6 @@ no_interrupt: | |||
167 | /* Set condition code and we're done. */ | 146 | /* Set condition code and we're done. */ |
168 | vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); | 147 | vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); |
169 | vcpu->arch.sie_block->gpsw.mask |= (cc & 3ul) << 44; | 148 | vcpu->arch.sie_block->gpsw.mask |= (cc & 3ul) << 44; |
170 | out: | ||
171 | return 0; | 149 | return 0; |
172 | } | 150 | } |
173 | 151 | ||
@@ -237,12 +215,9 @@ static int handle_stfl(struct kvm_vcpu *vcpu) | |||
237 | rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list), | 215 | rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list), |
238 | &facility_list, sizeof(facility_list)); | 216 | &facility_list, sizeof(facility_list)); |
239 | if (rc) | 217 | if (rc) |
240 | kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | 218 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); |
241 | else { | 219 | VCPU_EVENT(vcpu, 5, "store facility list value %x", facility_list); |
242 | VCPU_EVENT(vcpu, 5, "store facility list value %x", | 220 | trace_kvm_s390_handle_stfl(vcpu, facility_list); |
243 | facility_list); | ||
244 | trace_kvm_s390_handle_stfl(vcpu, facility_list); | ||
245 | } | ||
246 | return 0; | 221 | return 0; |
247 | } | 222 | } |
248 | 223 | ||
@@ -317,25 +292,18 @@ static int handle_lpswe(struct kvm_vcpu *vcpu) | |||
317 | static int handle_stidp(struct kvm_vcpu *vcpu) | 292 | static int handle_stidp(struct kvm_vcpu *vcpu) |
318 | { | 293 | { |
319 | u64 operand2; | 294 | u64 operand2; |
320 | int rc; | ||
321 | 295 | ||
322 | vcpu->stat.instruction_stidp++; | 296 | vcpu->stat.instruction_stidp++; |
323 | 297 | ||
324 | operand2 = kvm_s390_get_base_disp_s(vcpu); | 298 | operand2 = kvm_s390_get_base_disp_s(vcpu); |
325 | 299 | ||
326 | if (operand2 & 7) { | 300 | if (operand2 & 7) |
327 | kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | 301 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); |
328 | goto out; | ||
329 | } | ||
330 | 302 | ||
331 | rc = put_guest(vcpu, vcpu->arch.stidp_data, (u64 __user *)operand2); | 303 | if (put_guest(vcpu, vcpu->arch.stidp_data, (u64 __user *)operand2)) |
332 | if (rc) { | 304 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); |
333 | kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | ||
334 | goto out; | ||
335 | } | ||
336 | 305 | ||
337 | VCPU_EVENT(vcpu, 5, "%s", "store cpu id"); | 306 | VCPU_EVENT(vcpu, 5, "%s", "store cpu id"); |
338 | out: | ||
339 | return 0; | 307 | return 0; |
340 | } | 308 | } |
341 | 309 | ||
@@ -377,6 +345,7 @@ static int handle_stsi(struct kvm_vcpu *vcpu) | |||
377 | int sel2 = vcpu->run->s.regs.gprs[1] & 0xffff; | 345 | int sel2 = vcpu->run->s.regs.gprs[1] & 0xffff; |
378 | u64 operand2; | 346 | u64 operand2; |
379 | unsigned long mem; | 347 | unsigned long mem; |
348 | int rc = 0; | ||
380 | 349 | ||
381 | vcpu->stat.instruction_stsi++; | 350 | vcpu->stat.instruction_stsi++; |
382 | VCPU_EVENT(vcpu, 4, "stsi: fc: %x sel1: %x sel2: %x", fc, sel1, sel2); | 351 | VCPU_EVENT(vcpu, 4, "stsi: fc: %x sel1: %x sel2: %x", fc, sel1, sel2); |
@@ -412,7 +381,7 @@ static int handle_stsi(struct kvm_vcpu *vcpu) | |||
412 | } | 381 | } |
413 | 382 | ||
414 | if (copy_to_guest_absolute(vcpu, operand2, (void *) mem, PAGE_SIZE)) { | 383 | if (copy_to_guest_absolute(vcpu, operand2, (void *) mem, PAGE_SIZE)) { |
415 | kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | 384 | rc = kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); |
416 | goto out_mem; | 385 | goto out_mem; |
417 | } | 386 | } |
418 | trace_kvm_s390_handle_stsi(vcpu, fc, sel1, sel2, operand2); | 387 | trace_kvm_s390_handle_stsi(vcpu, fc, sel1, sel2, operand2); |
@@ -425,7 +394,7 @@ out_mem: | |||
425 | out_fail: | 394 | out_fail: |
426 | /* condition code 3 */ | 395 | /* condition code 3 */ |
427 | vcpu->arch.sie_block->gpsw.mask |= 3ul << 44; | 396 | vcpu->arch.sie_block->gpsw.mask |= 3ul << 44; |
428 | return 0; | 397 | return rc; |
429 | } | 398 | } |
430 | 399 | ||
431 | static const intercept_handler_t b2_handlers[256] = { | 400 | static const intercept_handler_t b2_handlers[256] = { |