diff options
Diffstat (limited to 'arch/s390/kvm/interrupt.c')
-rw-r--r-- | arch/s390/kvm/interrupt.c | 1044 |
1 files changed, 697 insertions, 347 deletions
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index a39838457f01..f00f31e66cd8 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/mmu_context.h> | 16 | #include <linux/mmu_context.h> |
17 | #include <linux/signal.h> | 17 | #include <linux/signal.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/bitmap.h> | ||
19 | #include <asm/asm-offsets.h> | 20 | #include <asm/asm-offsets.h> |
20 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
21 | #include "kvm-s390.h" | 22 | #include "kvm-s390.h" |
@@ -27,8 +28,8 @@ | |||
27 | #define IOINT_CSSID_MASK 0x03fc0000 | 28 | #define IOINT_CSSID_MASK 0x03fc0000 |
28 | #define IOINT_AI_MASK 0x04000000 | 29 | #define IOINT_AI_MASK 0x04000000 |
29 | #define PFAULT_INIT 0x0600 | 30 | #define PFAULT_INIT 0x0600 |
30 | 31 | #define PFAULT_DONE 0x0680 | |
31 | static int __must_check deliver_ckc_interrupt(struct kvm_vcpu *vcpu); | 32 | #define VIRTIO_PARAM 0x0d00 |
32 | 33 | ||
33 | static int is_ioint(u64 type) | 34 | static int is_ioint(u64 type) |
34 | { | 35 | { |
@@ -136,6 +137,31 @@ static int __must_check __interrupt_is_deliverable(struct kvm_vcpu *vcpu, | |||
136 | return 0; | 137 | return 0; |
137 | } | 138 | } |
138 | 139 | ||
140 | static inline unsigned long pending_local_irqs(struct kvm_vcpu *vcpu) | ||
141 | { | ||
142 | return vcpu->arch.local_int.pending_irqs; | ||
143 | } | ||
144 | |||
145 | static unsigned long deliverable_local_irqs(struct kvm_vcpu *vcpu) | ||
146 | { | ||
147 | unsigned long active_mask = pending_local_irqs(vcpu); | ||
148 | |||
149 | if (psw_extint_disabled(vcpu)) | ||
150 | active_mask &= ~IRQ_PEND_EXT_MASK; | ||
151 | if (!(vcpu->arch.sie_block->gcr[0] & 0x2000ul)) | ||
152 | __clear_bit(IRQ_PEND_EXT_EXTERNAL, &active_mask); | ||
153 | if (!(vcpu->arch.sie_block->gcr[0] & 0x4000ul)) | ||
154 | __clear_bit(IRQ_PEND_EXT_EMERGENCY, &active_mask); | ||
155 | if (!(vcpu->arch.sie_block->gcr[0] & 0x800ul)) | ||
156 | __clear_bit(IRQ_PEND_EXT_CLOCK_COMP, &active_mask); | ||
157 | if (!(vcpu->arch.sie_block->gcr[0] & 0x400ul)) | ||
158 | __clear_bit(IRQ_PEND_EXT_CPU_TIMER, &active_mask); | ||
159 | if (psw_mchk_disabled(vcpu)) | ||
160 | active_mask &= ~IRQ_PEND_MCHK_MASK; | ||
161 | |||
162 | return active_mask; | ||
163 | } | ||
164 | |||
139 | static void __set_cpu_idle(struct kvm_vcpu *vcpu) | 165 | static void __set_cpu_idle(struct kvm_vcpu *vcpu) |
140 | { | 166 | { |
141 | atomic_set_mask(CPUSTAT_WAIT, &vcpu->arch.sie_block->cpuflags); | 167 | atomic_set_mask(CPUSTAT_WAIT, &vcpu->arch.sie_block->cpuflags); |
@@ -170,26 +196,45 @@ static void __set_cpuflag(struct kvm_vcpu *vcpu, u32 flag) | |||
170 | atomic_set_mask(flag, &vcpu->arch.sie_block->cpuflags); | 196 | atomic_set_mask(flag, &vcpu->arch.sie_block->cpuflags); |
171 | } | 197 | } |
172 | 198 | ||
199 | static void set_intercept_indicators_ext(struct kvm_vcpu *vcpu) | ||
200 | { | ||
201 | if (!(pending_local_irqs(vcpu) & IRQ_PEND_EXT_MASK)) | ||
202 | return; | ||
203 | if (psw_extint_disabled(vcpu)) | ||
204 | __set_cpuflag(vcpu, CPUSTAT_EXT_INT); | ||
205 | else | ||
206 | vcpu->arch.sie_block->lctl |= LCTL_CR0; | ||
207 | } | ||
208 | |||
209 | static void set_intercept_indicators_mchk(struct kvm_vcpu *vcpu) | ||
210 | { | ||
211 | if (!(pending_local_irqs(vcpu) & IRQ_PEND_MCHK_MASK)) | ||
212 | return; | ||
213 | if (psw_mchk_disabled(vcpu)) | ||
214 | vcpu->arch.sie_block->ictl |= ICTL_LPSW; | ||
215 | else | ||
216 | vcpu->arch.sie_block->lctl |= LCTL_CR14; | ||
217 | } | ||
218 | |||
219 | /* Set interception request for non-deliverable local interrupts */ | ||
220 | static void set_intercept_indicators_local(struct kvm_vcpu *vcpu) | ||
221 | { | ||
222 | set_intercept_indicators_ext(vcpu); | ||
223 | set_intercept_indicators_mchk(vcpu); | ||
224 | } | ||
225 | |||
173 | static void __set_intercept_indicator(struct kvm_vcpu *vcpu, | 226 | static void __set_intercept_indicator(struct kvm_vcpu *vcpu, |
174 | struct kvm_s390_interrupt_info *inti) | 227 | struct kvm_s390_interrupt_info *inti) |
175 | { | 228 | { |
176 | switch (inti->type) { | 229 | switch (inti->type) { |
177 | case KVM_S390_INT_EXTERNAL_CALL: | ||
178 | case KVM_S390_INT_EMERGENCY: | ||
179 | case KVM_S390_INT_SERVICE: | 230 | case KVM_S390_INT_SERVICE: |
180 | case KVM_S390_INT_PFAULT_INIT: | ||
181 | case KVM_S390_INT_PFAULT_DONE: | 231 | case KVM_S390_INT_PFAULT_DONE: |
182 | case KVM_S390_INT_VIRTIO: | 232 | case KVM_S390_INT_VIRTIO: |
183 | case KVM_S390_INT_CLOCK_COMP: | ||
184 | case KVM_S390_INT_CPU_TIMER: | ||
185 | if (psw_extint_disabled(vcpu)) | 233 | if (psw_extint_disabled(vcpu)) |
186 | __set_cpuflag(vcpu, CPUSTAT_EXT_INT); | 234 | __set_cpuflag(vcpu, CPUSTAT_EXT_INT); |
187 | else | 235 | else |
188 | vcpu->arch.sie_block->lctl |= LCTL_CR0; | 236 | vcpu->arch.sie_block->lctl |= LCTL_CR0; |
189 | break; | 237 | break; |
190 | case KVM_S390_SIGP_STOP: | ||
191 | __set_cpuflag(vcpu, CPUSTAT_STOP_INT); | ||
192 | break; | ||
193 | case KVM_S390_MCHK: | 238 | case KVM_S390_MCHK: |
194 | if (psw_mchk_disabled(vcpu)) | 239 | if (psw_mchk_disabled(vcpu)) |
195 | vcpu->arch.sie_block->ictl |= ICTL_LPSW; | 240 | vcpu->arch.sie_block->ictl |= ICTL_LPSW; |
@@ -226,13 +271,236 @@ static u16 get_ilc(struct kvm_vcpu *vcpu) | |||
226 | } | 271 | } |
227 | } | 272 | } |
228 | 273 | ||
229 | static int __must_check __deliver_prog_irq(struct kvm_vcpu *vcpu, | 274 | static int __must_check __deliver_cpu_timer(struct kvm_vcpu *vcpu) |
230 | struct kvm_s390_pgm_info *pgm_info) | 275 | { |
276 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
277 | int rc; | ||
278 | |||
279 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_INT_CPU_TIMER, | ||
280 | 0, 0); | ||
281 | |||
282 | rc = put_guest_lc(vcpu, EXT_IRQ_CPU_TIMER, | ||
283 | (u16 *)__LC_EXT_INT_CODE); | ||
284 | rc |= put_guest_lc(vcpu, 0, (u16 *)__LC_EXT_CPU_ADDR); | ||
285 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
286 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
287 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
288 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
289 | clear_bit(IRQ_PEND_EXT_CPU_TIMER, &li->pending_irqs); | ||
290 | return rc ? -EFAULT : 0; | ||
291 | } | ||
292 | |||
293 | static int __must_check __deliver_ckc(struct kvm_vcpu *vcpu) | ||
294 | { | ||
295 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
296 | int rc; | ||
297 | |||
298 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_INT_CLOCK_COMP, | ||
299 | 0, 0); | ||
300 | |||
301 | rc = put_guest_lc(vcpu, EXT_IRQ_CLK_COMP, | ||
302 | (u16 __user *)__LC_EXT_INT_CODE); | ||
303 | rc |= put_guest_lc(vcpu, 0, (u16 *)__LC_EXT_CPU_ADDR); | ||
304 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
305 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
306 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
307 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
308 | clear_bit(IRQ_PEND_EXT_CLOCK_COMP, &li->pending_irqs); | ||
309 | return rc ? -EFAULT : 0; | ||
310 | } | ||
311 | |||
312 | static int __must_check __deliver_pfault_init(struct kvm_vcpu *vcpu) | ||
313 | { | ||
314 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
315 | struct kvm_s390_ext_info ext; | ||
316 | int rc; | ||
317 | |||
318 | spin_lock(&li->lock); | ||
319 | ext = li->irq.ext; | ||
320 | clear_bit(IRQ_PEND_PFAULT_INIT, &li->pending_irqs); | ||
321 | li->irq.ext.ext_params2 = 0; | ||
322 | spin_unlock(&li->lock); | ||
323 | |||
324 | VCPU_EVENT(vcpu, 4, "interrupt: pfault init parm:%x,parm64:%llx", | ||
325 | 0, ext.ext_params2); | ||
326 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, | ||
327 | KVM_S390_INT_PFAULT_INIT, | ||
328 | 0, ext.ext_params2); | ||
329 | |||
330 | rc = put_guest_lc(vcpu, EXT_IRQ_CP_SERVICE, (u16 *) __LC_EXT_INT_CODE); | ||
331 | rc |= put_guest_lc(vcpu, PFAULT_INIT, (u16 *) __LC_EXT_CPU_ADDR); | ||
332 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
333 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
334 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
335 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
336 | rc |= put_guest_lc(vcpu, ext.ext_params2, (u64 *) __LC_EXT_PARAMS2); | ||
337 | return rc ? -EFAULT : 0; | ||
338 | } | ||
339 | |||
340 | static int __must_check __deliver_machine_check(struct kvm_vcpu *vcpu) | ||
341 | { | ||
342 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
343 | struct kvm_s390_mchk_info mchk; | ||
344 | int rc; | ||
345 | |||
346 | spin_lock(&li->lock); | ||
347 | mchk = li->irq.mchk; | ||
348 | /* | ||
349 | * If there was an exigent machine check pending, then any repressible | ||
350 | * machine checks that might have been pending are indicated along | ||
351 | * with it, so always clear both bits | ||
352 | */ | ||
353 | clear_bit(IRQ_PEND_MCHK_EX, &li->pending_irqs); | ||
354 | clear_bit(IRQ_PEND_MCHK_REP, &li->pending_irqs); | ||
355 | memset(&li->irq.mchk, 0, sizeof(mchk)); | ||
356 | spin_unlock(&li->lock); | ||
357 | |||
358 | VCPU_EVENT(vcpu, 4, "interrupt: machine check mcic=%llx", | ||
359 | mchk.mcic); | ||
360 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_MCHK, | ||
361 | mchk.cr14, mchk.mcic); | ||
362 | |||
363 | rc = kvm_s390_vcpu_store_status(vcpu, KVM_S390_STORE_STATUS_PREFIXED); | ||
364 | rc |= put_guest_lc(vcpu, mchk.mcic, | ||
365 | (u64 __user *) __LC_MCCK_CODE); | ||
366 | rc |= put_guest_lc(vcpu, mchk.failing_storage_address, | ||
367 | (u64 __user *) __LC_MCCK_FAIL_STOR_ADDR); | ||
368 | rc |= write_guest_lc(vcpu, __LC_PSW_SAVE_AREA, | ||
369 | &mchk.fixed_logout, sizeof(mchk.fixed_logout)); | ||
370 | rc |= write_guest_lc(vcpu, __LC_MCK_OLD_PSW, | ||
371 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
372 | rc |= read_guest_lc(vcpu, __LC_MCK_NEW_PSW, | ||
373 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
374 | return rc ? -EFAULT : 0; | ||
375 | } | ||
376 | |||
377 | static int __must_check __deliver_restart(struct kvm_vcpu *vcpu) | ||
378 | { | ||
379 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
380 | int rc; | ||
381 | |||
382 | VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu restart"); | ||
383 | vcpu->stat.deliver_restart_signal++; | ||
384 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_RESTART, 0, 0); | ||
385 | |||
386 | rc = write_guest_lc(vcpu, | ||
387 | offsetof(struct _lowcore, restart_old_psw), | ||
388 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
389 | rc |= read_guest_lc(vcpu, offsetof(struct _lowcore, restart_psw), | ||
390 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
391 | clear_bit(IRQ_PEND_RESTART, &li->pending_irqs); | ||
392 | return rc ? -EFAULT : 0; | ||
393 | } | ||
394 | |||
395 | static int __must_check __deliver_stop(struct kvm_vcpu *vcpu) | ||
396 | { | ||
397 | VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu stop"); | ||
398 | vcpu->stat.deliver_stop_signal++; | ||
399 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_SIGP_STOP, | ||
400 | 0, 0); | ||
401 | |||
402 | __set_cpuflag(vcpu, CPUSTAT_STOP_INT); | ||
403 | clear_bit(IRQ_PEND_SIGP_STOP, &vcpu->arch.local_int.pending_irqs); | ||
404 | return 0; | ||
405 | } | ||
406 | |||
407 | static int __must_check __deliver_set_prefix(struct kvm_vcpu *vcpu) | ||
408 | { | ||
409 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
410 | struct kvm_s390_prefix_info prefix; | ||
411 | |||
412 | spin_lock(&li->lock); | ||
413 | prefix = li->irq.prefix; | ||
414 | li->irq.prefix.address = 0; | ||
415 | clear_bit(IRQ_PEND_SET_PREFIX, &li->pending_irqs); | ||
416 | spin_unlock(&li->lock); | ||
417 | |||
418 | VCPU_EVENT(vcpu, 4, "interrupt: set prefix to %x", prefix.address); | ||
419 | vcpu->stat.deliver_prefix_signal++; | ||
420 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, | ||
421 | KVM_S390_SIGP_SET_PREFIX, | ||
422 | prefix.address, 0); | ||
423 | |||
424 | kvm_s390_set_prefix(vcpu, prefix.address); | ||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | static int __must_check __deliver_emergency_signal(struct kvm_vcpu *vcpu) | ||
429 | { | ||
430 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
431 | int rc; | ||
432 | int cpu_addr; | ||
433 | |||
434 | spin_lock(&li->lock); | ||
435 | cpu_addr = find_first_bit(li->sigp_emerg_pending, KVM_MAX_VCPUS); | ||
436 | clear_bit(cpu_addr, li->sigp_emerg_pending); | ||
437 | if (bitmap_empty(li->sigp_emerg_pending, KVM_MAX_VCPUS)) | ||
438 | clear_bit(IRQ_PEND_EXT_EMERGENCY, &li->pending_irqs); | ||
439 | spin_unlock(&li->lock); | ||
440 | |||
441 | VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp emerg"); | ||
442 | vcpu->stat.deliver_emergency_signal++; | ||
443 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_INT_EMERGENCY, | ||
444 | cpu_addr, 0); | ||
445 | |||
446 | rc = put_guest_lc(vcpu, EXT_IRQ_EMERGENCY_SIG, | ||
447 | (u16 *)__LC_EXT_INT_CODE); | ||
448 | rc |= put_guest_lc(vcpu, cpu_addr, (u16 *)__LC_EXT_CPU_ADDR); | ||
449 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
450 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
451 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
452 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
453 | return rc ? -EFAULT : 0; | ||
454 | } | ||
455 | |||
456 | static int __must_check __deliver_external_call(struct kvm_vcpu *vcpu) | ||
457 | { | ||
458 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
459 | struct kvm_s390_extcall_info extcall; | ||
460 | int rc; | ||
461 | |||
462 | spin_lock(&li->lock); | ||
463 | extcall = li->irq.extcall; | ||
464 | li->irq.extcall.code = 0; | ||
465 | clear_bit(IRQ_PEND_EXT_EXTERNAL, &li->pending_irqs); | ||
466 | spin_unlock(&li->lock); | ||
467 | |||
468 | VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp ext call"); | ||
469 | vcpu->stat.deliver_external_call++; | ||
470 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, | ||
471 | KVM_S390_INT_EXTERNAL_CALL, | ||
472 | extcall.code, 0); | ||
473 | |||
474 | rc = put_guest_lc(vcpu, EXT_IRQ_EXTERNAL_CALL, | ||
475 | (u16 *)__LC_EXT_INT_CODE); | ||
476 | rc |= put_guest_lc(vcpu, extcall.code, (u16 *)__LC_EXT_CPU_ADDR); | ||
477 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
478 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
479 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, &vcpu->arch.sie_block->gpsw, | ||
480 | sizeof(psw_t)); | ||
481 | return rc ? -EFAULT : 0; | ||
482 | } | ||
483 | |||
484 | static int __must_check __deliver_prog(struct kvm_vcpu *vcpu) | ||
231 | { | 485 | { |
486 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
487 | struct kvm_s390_pgm_info pgm_info; | ||
232 | int rc = 0; | 488 | int rc = 0; |
233 | u16 ilc = get_ilc(vcpu); | 489 | u16 ilc = get_ilc(vcpu); |
234 | 490 | ||
235 | switch (pgm_info->code & ~PGM_PER) { | 491 | spin_lock(&li->lock); |
492 | pgm_info = li->irq.pgm; | ||
493 | clear_bit(IRQ_PEND_PROG, &li->pending_irqs); | ||
494 | memset(&li->irq.pgm, 0, sizeof(pgm_info)); | ||
495 | spin_unlock(&li->lock); | ||
496 | |||
497 | VCPU_EVENT(vcpu, 4, "interrupt: pgm check code:%x, ilc:%x", | ||
498 | pgm_info.code, ilc); | ||
499 | vcpu->stat.deliver_program_int++; | ||
500 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_PROGRAM_INT, | ||
501 | pgm_info.code, 0); | ||
502 | |||
503 | switch (pgm_info.code & ~PGM_PER) { | ||
236 | case PGM_AFX_TRANSLATION: | 504 | case PGM_AFX_TRANSLATION: |
237 | case PGM_ASX_TRANSLATION: | 505 | case PGM_ASX_TRANSLATION: |
238 | case PGM_EX_TRANSLATION: | 506 | case PGM_EX_TRANSLATION: |
@@ -243,7 +511,7 @@ static int __must_check __deliver_prog_irq(struct kvm_vcpu *vcpu, | |||
243 | case PGM_PRIMARY_AUTHORITY: | 511 | case PGM_PRIMARY_AUTHORITY: |
244 | case PGM_SECONDARY_AUTHORITY: | 512 | case PGM_SECONDARY_AUTHORITY: |
245 | case PGM_SPACE_SWITCH: | 513 | case PGM_SPACE_SWITCH: |
246 | rc = put_guest_lc(vcpu, pgm_info->trans_exc_code, | 514 | rc = put_guest_lc(vcpu, pgm_info.trans_exc_code, |
247 | (u64 *)__LC_TRANS_EXC_CODE); | 515 | (u64 *)__LC_TRANS_EXC_CODE); |
248 | break; | 516 | break; |
249 | case PGM_ALEN_TRANSLATION: | 517 | case PGM_ALEN_TRANSLATION: |
@@ -252,7 +520,7 @@ static int __must_check __deliver_prog_irq(struct kvm_vcpu *vcpu, | |||
252 | case PGM_ASTE_SEQUENCE: | 520 | case PGM_ASTE_SEQUENCE: |
253 | case PGM_ASTE_VALIDITY: | 521 | case PGM_ASTE_VALIDITY: |
254 | case PGM_EXTENDED_AUTHORITY: | 522 | case PGM_EXTENDED_AUTHORITY: |
255 | rc = put_guest_lc(vcpu, pgm_info->exc_access_id, | 523 | rc = put_guest_lc(vcpu, pgm_info.exc_access_id, |
256 | (u8 *)__LC_EXC_ACCESS_ID); | 524 | (u8 *)__LC_EXC_ACCESS_ID); |
257 | break; | 525 | break; |
258 | case PGM_ASCE_TYPE: | 526 | case PGM_ASCE_TYPE: |
@@ -261,247 +529,208 @@ static int __must_check __deliver_prog_irq(struct kvm_vcpu *vcpu, | |||
261 | case PGM_REGION_SECOND_TRANS: | 529 | case PGM_REGION_SECOND_TRANS: |
262 | case PGM_REGION_THIRD_TRANS: | 530 | case PGM_REGION_THIRD_TRANS: |
263 | case PGM_SEGMENT_TRANSLATION: | 531 | case PGM_SEGMENT_TRANSLATION: |
264 | rc = put_guest_lc(vcpu, pgm_info->trans_exc_code, | 532 | rc = put_guest_lc(vcpu, pgm_info.trans_exc_code, |
265 | (u64 *)__LC_TRANS_EXC_CODE); | 533 | (u64 *)__LC_TRANS_EXC_CODE); |
266 | rc |= put_guest_lc(vcpu, pgm_info->exc_access_id, | 534 | rc |= put_guest_lc(vcpu, pgm_info.exc_access_id, |
267 | (u8 *)__LC_EXC_ACCESS_ID); | 535 | (u8 *)__LC_EXC_ACCESS_ID); |
268 | rc |= put_guest_lc(vcpu, pgm_info->op_access_id, | 536 | rc |= put_guest_lc(vcpu, pgm_info.op_access_id, |
269 | (u8 *)__LC_OP_ACCESS_ID); | 537 | (u8 *)__LC_OP_ACCESS_ID); |
270 | break; | 538 | break; |
271 | case PGM_MONITOR: | 539 | case PGM_MONITOR: |
272 | rc = put_guest_lc(vcpu, pgm_info->mon_class_nr, | 540 | rc = put_guest_lc(vcpu, pgm_info.mon_class_nr, |
273 | (u64 *)__LC_MON_CLASS_NR); | 541 | (u16 *)__LC_MON_CLASS_NR); |
274 | rc |= put_guest_lc(vcpu, pgm_info->mon_code, | 542 | rc |= put_guest_lc(vcpu, pgm_info.mon_code, |
275 | (u64 *)__LC_MON_CODE); | 543 | (u64 *)__LC_MON_CODE); |
276 | break; | 544 | break; |
277 | case PGM_DATA: | 545 | case PGM_DATA: |
278 | rc = put_guest_lc(vcpu, pgm_info->data_exc_code, | 546 | rc = put_guest_lc(vcpu, pgm_info.data_exc_code, |
279 | (u32 *)__LC_DATA_EXC_CODE); | 547 | (u32 *)__LC_DATA_EXC_CODE); |
280 | break; | 548 | break; |
281 | case PGM_PROTECTION: | 549 | case PGM_PROTECTION: |
282 | rc = put_guest_lc(vcpu, pgm_info->trans_exc_code, | 550 | rc = put_guest_lc(vcpu, pgm_info.trans_exc_code, |
283 | (u64 *)__LC_TRANS_EXC_CODE); | 551 | (u64 *)__LC_TRANS_EXC_CODE); |
284 | rc |= put_guest_lc(vcpu, pgm_info->exc_access_id, | 552 | rc |= put_guest_lc(vcpu, pgm_info.exc_access_id, |
285 | (u8 *)__LC_EXC_ACCESS_ID); | 553 | (u8 *)__LC_EXC_ACCESS_ID); |
286 | break; | 554 | break; |
287 | } | 555 | } |
288 | 556 | ||
289 | if (pgm_info->code & PGM_PER) { | 557 | if (pgm_info.code & PGM_PER) { |
290 | rc |= put_guest_lc(vcpu, pgm_info->per_code, | 558 | rc |= put_guest_lc(vcpu, pgm_info.per_code, |
291 | (u8 *) __LC_PER_CODE); | 559 | (u8 *) __LC_PER_CODE); |
292 | rc |= put_guest_lc(vcpu, pgm_info->per_atmid, | 560 | rc |= put_guest_lc(vcpu, pgm_info.per_atmid, |
293 | (u8 *)__LC_PER_ATMID); | 561 | (u8 *)__LC_PER_ATMID); |
294 | rc |= put_guest_lc(vcpu, pgm_info->per_address, | 562 | rc |= put_guest_lc(vcpu, pgm_info.per_address, |
295 | (u64 *) __LC_PER_ADDRESS); | 563 | (u64 *) __LC_PER_ADDRESS); |
296 | rc |= put_guest_lc(vcpu, pgm_info->per_access_id, | 564 | rc |= put_guest_lc(vcpu, pgm_info.per_access_id, |
297 | (u8 *) __LC_PER_ACCESS_ID); | 565 | (u8 *) __LC_PER_ACCESS_ID); |
298 | } | 566 | } |
299 | 567 | ||
300 | rc |= put_guest_lc(vcpu, ilc, (u16 *) __LC_PGM_ILC); | 568 | rc |= put_guest_lc(vcpu, ilc, (u16 *) __LC_PGM_ILC); |
301 | rc |= put_guest_lc(vcpu, pgm_info->code, | 569 | rc |= put_guest_lc(vcpu, pgm_info.code, |
302 | (u16 *)__LC_PGM_INT_CODE); | 570 | (u16 *)__LC_PGM_INT_CODE); |
303 | rc |= write_guest_lc(vcpu, __LC_PGM_OLD_PSW, | 571 | rc |= write_guest_lc(vcpu, __LC_PGM_OLD_PSW, |
304 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | 572 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); |
305 | rc |= read_guest_lc(vcpu, __LC_PGM_NEW_PSW, | 573 | rc |= read_guest_lc(vcpu, __LC_PGM_NEW_PSW, |
306 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | 574 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); |
575 | return rc ? -EFAULT : 0; | ||
576 | } | ||
307 | 577 | ||
308 | return rc; | 578 | static int __must_check __deliver_service(struct kvm_vcpu *vcpu, |
579 | struct kvm_s390_interrupt_info *inti) | ||
580 | { | ||
581 | int rc; | ||
582 | |||
583 | VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x", | ||
584 | inti->ext.ext_params); | ||
585 | vcpu->stat.deliver_service_signal++; | ||
586 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
587 | inti->ext.ext_params, 0); | ||
588 | |||
589 | rc = put_guest_lc(vcpu, EXT_IRQ_SERVICE_SIG, (u16 *)__LC_EXT_INT_CODE); | ||
590 | rc |= put_guest_lc(vcpu, 0, (u16 *)__LC_EXT_CPU_ADDR); | ||
591 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
592 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
593 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
594 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
595 | rc |= put_guest_lc(vcpu, inti->ext.ext_params, | ||
596 | (u32 *)__LC_EXT_PARAMS); | ||
597 | return rc ? -EFAULT : 0; | ||
309 | } | 598 | } |
310 | 599 | ||
311 | static int __must_check __do_deliver_interrupt(struct kvm_vcpu *vcpu, | 600 | static int __must_check __deliver_pfault_done(struct kvm_vcpu *vcpu, |
312 | struct kvm_s390_interrupt_info *inti) | 601 | struct kvm_s390_interrupt_info *inti) |
313 | { | 602 | { |
314 | const unsigned short table[] = { 2, 4, 4, 6 }; | 603 | int rc; |
315 | int rc = 0; | 604 | |
605 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, | ||
606 | KVM_S390_INT_PFAULT_DONE, 0, | ||
607 | inti->ext.ext_params2); | ||
608 | |||
609 | rc = put_guest_lc(vcpu, EXT_IRQ_CP_SERVICE, (u16 *)__LC_EXT_INT_CODE); | ||
610 | rc |= put_guest_lc(vcpu, PFAULT_DONE, (u16 *)__LC_EXT_CPU_ADDR); | ||
611 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
612 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
613 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
614 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
615 | rc |= put_guest_lc(vcpu, inti->ext.ext_params2, | ||
616 | (u64 *)__LC_EXT_PARAMS2); | ||
617 | return rc ? -EFAULT : 0; | ||
618 | } | ||
619 | |||
620 | static int __must_check __deliver_virtio(struct kvm_vcpu *vcpu, | ||
621 | struct kvm_s390_interrupt_info *inti) | ||
622 | { | ||
623 | int rc; | ||
624 | |||
625 | VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%llx", | ||
626 | inti->ext.ext_params, inti->ext.ext_params2); | ||
627 | vcpu->stat.deliver_virtio_interrupt++; | ||
628 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
629 | inti->ext.ext_params, | ||
630 | inti->ext.ext_params2); | ||
631 | |||
632 | rc = put_guest_lc(vcpu, EXT_IRQ_CP_SERVICE, (u16 *)__LC_EXT_INT_CODE); | ||
633 | rc |= put_guest_lc(vcpu, VIRTIO_PARAM, (u16 *)__LC_EXT_CPU_ADDR); | ||
634 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
635 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
636 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
637 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
638 | rc |= put_guest_lc(vcpu, inti->ext.ext_params, | ||
639 | (u32 *)__LC_EXT_PARAMS); | ||
640 | rc |= put_guest_lc(vcpu, inti->ext.ext_params2, | ||
641 | (u64 *)__LC_EXT_PARAMS2); | ||
642 | return rc ? -EFAULT : 0; | ||
643 | } | ||
644 | |||
645 | static int __must_check __deliver_io(struct kvm_vcpu *vcpu, | ||
646 | struct kvm_s390_interrupt_info *inti) | ||
647 | { | ||
648 | int rc; | ||
649 | |||
650 | VCPU_EVENT(vcpu, 4, "interrupt: I/O %llx", inti->type); | ||
651 | vcpu->stat.deliver_io_int++; | ||
652 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
653 | ((__u32)inti->io.subchannel_id << 16) | | ||
654 | inti->io.subchannel_nr, | ||
655 | ((__u64)inti->io.io_int_parm << 32) | | ||
656 | inti->io.io_int_word); | ||
657 | |||
658 | rc = put_guest_lc(vcpu, inti->io.subchannel_id, | ||
659 | (u16 *)__LC_SUBCHANNEL_ID); | ||
660 | rc |= put_guest_lc(vcpu, inti->io.subchannel_nr, | ||
661 | (u16 *)__LC_SUBCHANNEL_NR); | ||
662 | rc |= put_guest_lc(vcpu, inti->io.io_int_parm, | ||
663 | (u32 *)__LC_IO_INT_PARM); | ||
664 | rc |= put_guest_lc(vcpu, inti->io.io_int_word, | ||
665 | (u32 *)__LC_IO_INT_WORD); | ||
666 | rc |= write_guest_lc(vcpu, __LC_IO_OLD_PSW, | ||
667 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
668 | rc |= read_guest_lc(vcpu, __LC_IO_NEW_PSW, | ||
669 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
670 | return rc ? -EFAULT : 0; | ||
671 | } | ||
672 | |||
673 | static int __must_check __deliver_mchk_floating(struct kvm_vcpu *vcpu, | ||
674 | struct kvm_s390_interrupt_info *inti) | ||
675 | { | ||
676 | struct kvm_s390_mchk_info *mchk = &inti->mchk; | ||
677 | int rc; | ||
678 | |||
679 | VCPU_EVENT(vcpu, 4, "interrupt: machine check mcic=%llx", | ||
680 | mchk->mcic); | ||
681 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_MCHK, | ||
682 | mchk->cr14, mchk->mcic); | ||
683 | |||
684 | rc = kvm_s390_vcpu_store_status(vcpu, KVM_S390_STORE_STATUS_PREFIXED); | ||
685 | rc |= put_guest_lc(vcpu, mchk->mcic, | ||
686 | (u64 __user *) __LC_MCCK_CODE); | ||
687 | rc |= put_guest_lc(vcpu, mchk->failing_storage_address, | ||
688 | (u64 __user *) __LC_MCCK_FAIL_STOR_ADDR); | ||
689 | rc |= write_guest_lc(vcpu, __LC_PSW_SAVE_AREA, | ||
690 | &mchk->fixed_logout, sizeof(mchk->fixed_logout)); | ||
691 | rc |= write_guest_lc(vcpu, __LC_MCK_OLD_PSW, | ||
692 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
693 | rc |= read_guest_lc(vcpu, __LC_MCK_NEW_PSW, | ||
694 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
695 | return rc ? -EFAULT : 0; | ||
696 | } | ||
697 | |||
698 | typedef int (*deliver_irq_t)(struct kvm_vcpu *vcpu); | ||
699 | |||
700 | static const deliver_irq_t deliver_irq_funcs[] = { | ||
701 | [IRQ_PEND_MCHK_EX] = __deliver_machine_check, | ||
702 | [IRQ_PEND_PROG] = __deliver_prog, | ||
703 | [IRQ_PEND_EXT_EMERGENCY] = __deliver_emergency_signal, | ||
704 | [IRQ_PEND_EXT_EXTERNAL] = __deliver_external_call, | ||
705 | [IRQ_PEND_EXT_CLOCK_COMP] = __deliver_ckc, | ||
706 | [IRQ_PEND_EXT_CPU_TIMER] = __deliver_cpu_timer, | ||
707 | [IRQ_PEND_RESTART] = __deliver_restart, | ||
708 | [IRQ_PEND_SIGP_STOP] = __deliver_stop, | ||
709 | [IRQ_PEND_SET_PREFIX] = __deliver_set_prefix, | ||
710 | [IRQ_PEND_PFAULT_INIT] = __deliver_pfault_init, | ||
711 | }; | ||
712 | |||
713 | static int __must_check __deliver_floating_interrupt(struct kvm_vcpu *vcpu, | ||
714 | struct kvm_s390_interrupt_info *inti) | ||
715 | { | ||
716 | int rc; | ||
316 | 717 | ||
317 | switch (inti->type) { | 718 | switch (inti->type) { |
318 | case KVM_S390_INT_EMERGENCY: | ||
319 | VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp emerg"); | ||
320 | vcpu->stat.deliver_emergency_signal++; | ||
321 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
322 | inti->emerg.code, 0); | ||
323 | rc = put_guest_lc(vcpu, 0x1201, (u16 *)__LC_EXT_INT_CODE); | ||
324 | rc |= put_guest_lc(vcpu, inti->emerg.code, | ||
325 | (u16 *)__LC_EXT_CPU_ADDR); | ||
326 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
327 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
328 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
329 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
330 | break; | ||
331 | case KVM_S390_INT_EXTERNAL_CALL: | ||
332 | VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp ext call"); | ||
333 | vcpu->stat.deliver_external_call++; | ||
334 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
335 | inti->extcall.code, 0); | ||
336 | rc = put_guest_lc(vcpu, 0x1202, (u16 *)__LC_EXT_INT_CODE); | ||
337 | rc |= put_guest_lc(vcpu, inti->extcall.code, | ||
338 | (u16 *)__LC_EXT_CPU_ADDR); | ||
339 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
340 | &vcpu->arch.sie_block->gpsw, | ||
341 | sizeof(psw_t)); | ||
342 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
343 | &vcpu->arch.sie_block->gpsw, | ||
344 | sizeof(psw_t)); | ||
345 | break; | ||
346 | case KVM_S390_INT_CLOCK_COMP: | ||
347 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
348 | inti->ext.ext_params, 0); | ||
349 | rc = deliver_ckc_interrupt(vcpu); | ||
350 | break; | ||
351 | case KVM_S390_INT_CPU_TIMER: | ||
352 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
353 | inti->ext.ext_params, 0); | ||
354 | rc = put_guest_lc(vcpu, EXT_IRQ_CPU_TIMER, | ||
355 | (u16 *)__LC_EXT_INT_CODE); | ||
356 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
357 | &vcpu->arch.sie_block->gpsw, | ||
358 | sizeof(psw_t)); | ||
359 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
360 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
361 | rc |= put_guest_lc(vcpu, inti->ext.ext_params, | ||
362 | (u32 *)__LC_EXT_PARAMS); | ||
363 | break; | ||
364 | case KVM_S390_INT_SERVICE: | 719 | case KVM_S390_INT_SERVICE: |
365 | VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x", | 720 | rc = __deliver_service(vcpu, inti); |
366 | inti->ext.ext_params); | ||
367 | vcpu->stat.deliver_service_signal++; | ||
368 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
369 | inti->ext.ext_params, 0); | ||
370 | rc = put_guest_lc(vcpu, 0x2401, (u16 *)__LC_EXT_INT_CODE); | ||
371 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
372 | &vcpu->arch.sie_block->gpsw, | ||
373 | sizeof(psw_t)); | ||
374 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
375 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
376 | rc |= put_guest_lc(vcpu, inti->ext.ext_params, | ||
377 | (u32 *)__LC_EXT_PARAMS); | ||
378 | break; | ||
379 | case KVM_S390_INT_PFAULT_INIT: | ||
380 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, 0, | ||
381 | inti->ext.ext_params2); | ||
382 | rc = put_guest_lc(vcpu, EXT_IRQ_CP_SERVICE, | ||
383 | (u16 *) __LC_EXT_INT_CODE); | ||
384 | rc |= put_guest_lc(vcpu, PFAULT_INIT, (u16 *) __LC_EXT_CPU_ADDR); | ||
385 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
386 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
387 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
388 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
389 | rc |= put_guest_lc(vcpu, inti->ext.ext_params2, | ||
390 | (u64 *) __LC_EXT_PARAMS2); | ||
391 | break; | 721 | break; |
392 | case KVM_S390_INT_PFAULT_DONE: | 722 | case KVM_S390_INT_PFAULT_DONE: |
393 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, 0, | 723 | rc = __deliver_pfault_done(vcpu, inti); |
394 | inti->ext.ext_params2); | ||
395 | rc = put_guest_lc(vcpu, 0x2603, (u16 *)__LC_EXT_INT_CODE); | ||
396 | rc |= put_guest_lc(vcpu, 0x0680, (u16 *)__LC_EXT_CPU_ADDR); | ||
397 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
398 | &vcpu->arch.sie_block->gpsw, | ||
399 | sizeof(psw_t)); | ||
400 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
401 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
402 | rc |= put_guest_lc(vcpu, inti->ext.ext_params2, | ||
403 | (u64 *)__LC_EXT_PARAMS2); | ||
404 | break; | 724 | break; |
405 | case KVM_S390_INT_VIRTIO: | 725 | case KVM_S390_INT_VIRTIO: |
406 | VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%llx", | 726 | rc = __deliver_virtio(vcpu, inti); |
407 | inti->ext.ext_params, inti->ext.ext_params2); | ||
408 | vcpu->stat.deliver_virtio_interrupt++; | ||
409 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
410 | inti->ext.ext_params, | ||
411 | inti->ext.ext_params2); | ||
412 | rc = put_guest_lc(vcpu, 0x2603, (u16 *)__LC_EXT_INT_CODE); | ||
413 | rc |= put_guest_lc(vcpu, 0x0d00, (u16 *)__LC_EXT_CPU_ADDR); | ||
414 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
415 | &vcpu->arch.sie_block->gpsw, | ||
416 | sizeof(psw_t)); | ||
417 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
418 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
419 | rc |= put_guest_lc(vcpu, inti->ext.ext_params, | ||
420 | (u32 *)__LC_EXT_PARAMS); | ||
421 | rc |= put_guest_lc(vcpu, inti->ext.ext_params2, | ||
422 | (u64 *)__LC_EXT_PARAMS2); | ||
423 | break; | ||
424 | case KVM_S390_SIGP_STOP: | ||
425 | VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu stop"); | ||
426 | vcpu->stat.deliver_stop_signal++; | ||
427 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
428 | 0, 0); | ||
429 | __set_intercept_indicator(vcpu, inti); | ||
430 | break; | ||
431 | |||
432 | case KVM_S390_SIGP_SET_PREFIX: | ||
433 | VCPU_EVENT(vcpu, 4, "interrupt: set prefix to %x", | ||
434 | inti->prefix.address); | ||
435 | vcpu->stat.deliver_prefix_signal++; | ||
436 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
437 | inti->prefix.address, 0); | ||
438 | kvm_s390_set_prefix(vcpu, inti->prefix.address); | ||
439 | break; | ||
440 | |||
441 | case KVM_S390_RESTART: | ||
442 | VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu restart"); | ||
443 | vcpu->stat.deliver_restart_signal++; | ||
444 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
445 | 0, 0); | ||
446 | rc = write_guest_lc(vcpu, | ||
447 | offsetof(struct _lowcore, restart_old_psw), | ||
448 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
449 | rc |= read_guest_lc(vcpu, offsetof(struct _lowcore, restart_psw), | ||
450 | &vcpu->arch.sie_block->gpsw, | ||
451 | sizeof(psw_t)); | ||
452 | break; | 727 | break; |
453 | case KVM_S390_PROGRAM_INT: | ||
454 | VCPU_EVENT(vcpu, 4, "interrupt: pgm check code:%x, ilc:%x", | ||
455 | inti->pgm.code, | ||
456 | table[vcpu->arch.sie_block->ipa >> 14]); | ||
457 | vcpu->stat.deliver_program_int++; | ||
458 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
459 | inti->pgm.code, 0); | ||
460 | rc = __deliver_prog_irq(vcpu, &inti->pgm); | ||
461 | break; | ||
462 | |||
463 | case KVM_S390_MCHK: | 728 | case KVM_S390_MCHK: |
464 | VCPU_EVENT(vcpu, 4, "interrupt: machine check mcic=%llx", | 729 | rc = __deliver_mchk_floating(vcpu, inti); |
465 | inti->mchk.mcic); | ||
466 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
467 | inti->mchk.cr14, | ||
468 | inti->mchk.mcic); | ||
469 | rc = kvm_s390_vcpu_store_status(vcpu, | ||
470 | KVM_S390_STORE_STATUS_PREFIXED); | ||
471 | rc |= put_guest_lc(vcpu, inti->mchk.mcic, (u64 *)__LC_MCCK_CODE); | ||
472 | rc |= write_guest_lc(vcpu, __LC_MCK_OLD_PSW, | ||
473 | &vcpu->arch.sie_block->gpsw, | ||
474 | sizeof(psw_t)); | ||
475 | rc |= read_guest_lc(vcpu, __LC_MCK_NEW_PSW, | ||
476 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
477 | break; | 730 | break; |
478 | |||
479 | case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: | 731 | case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: |
480 | { | 732 | rc = __deliver_io(vcpu, inti); |
481 | __u32 param0 = ((__u32)inti->io.subchannel_id << 16) | | ||
482 | inti->io.subchannel_nr; | ||
483 | __u64 param1 = ((__u64)inti->io.io_int_parm << 32) | | ||
484 | inti->io.io_int_word; | ||
485 | VCPU_EVENT(vcpu, 4, "interrupt: I/O %llx", inti->type); | ||
486 | vcpu->stat.deliver_io_int++; | ||
487 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
488 | param0, param1); | ||
489 | rc = put_guest_lc(vcpu, inti->io.subchannel_id, | ||
490 | (u16 *)__LC_SUBCHANNEL_ID); | ||
491 | rc |= put_guest_lc(vcpu, inti->io.subchannel_nr, | ||
492 | (u16 *)__LC_SUBCHANNEL_NR); | ||
493 | rc |= put_guest_lc(vcpu, inti->io.io_int_parm, | ||
494 | (u32 *)__LC_IO_INT_PARM); | ||
495 | rc |= put_guest_lc(vcpu, inti->io.io_int_word, | ||
496 | (u32 *)__LC_IO_INT_WORD); | ||
497 | rc |= write_guest_lc(vcpu, __LC_IO_OLD_PSW, | ||
498 | &vcpu->arch.sie_block->gpsw, | ||
499 | sizeof(psw_t)); | ||
500 | rc |= read_guest_lc(vcpu, __LC_IO_NEW_PSW, | ||
501 | &vcpu->arch.sie_block->gpsw, | ||
502 | sizeof(psw_t)); | ||
503 | break; | 733 | break; |
504 | } | ||
505 | default: | 734 | default: |
506 | BUG(); | 735 | BUG(); |
507 | } | 736 | } |
@@ -509,19 +738,6 @@ static int __must_check __do_deliver_interrupt(struct kvm_vcpu *vcpu, | |||
509 | return rc; | 738 | return rc; |
510 | } | 739 | } |
511 | 740 | ||
512 | static int __must_check deliver_ckc_interrupt(struct kvm_vcpu *vcpu) | ||
513 | { | ||
514 | int rc; | ||
515 | |||
516 | rc = put_guest_lc(vcpu, 0x1004, (u16 __user *)__LC_EXT_INT_CODE); | ||
517 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
518 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
519 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
520 | &vcpu->arch.sie_block->gpsw, | ||
521 | sizeof(psw_t)); | ||
522 | return rc; | ||
523 | } | ||
524 | |||
525 | /* Check whether SIGP interpretation facility has an external call pending */ | 741 | /* Check whether SIGP interpretation facility has an external call pending */ |
526 | int kvm_s390_si_ext_call_pending(struct kvm_vcpu *vcpu) | 742 | int kvm_s390_si_ext_call_pending(struct kvm_vcpu *vcpu) |
527 | { | 743 | { |
@@ -538,20 +754,11 @@ int kvm_s390_si_ext_call_pending(struct kvm_vcpu *vcpu) | |||
538 | 754 | ||
539 | int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu) | 755 | int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu) |
540 | { | 756 | { |
541 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
542 | struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int; | 757 | struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int; |
543 | struct kvm_s390_interrupt_info *inti; | 758 | struct kvm_s390_interrupt_info *inti; |
544 | int rc = 0; | 759 | int rc; |
545 | 760 | ||
546 | if (atomic_read(&li->active)) { | 761 | rc = !!deliverable_local_irqs(vcpu); |
547 | spin_lock(&li->lock); | ||
548 | list_for_each_entry(inti, &li->list, list) | ||
549 | if (__interrupt_is_deliverable(vcpu, inti)) { | ||
550 | rc = 1; | ||
551 | break; | ||
552 | } | ||
553 | spin_unlock(&li->lock); | ||
554 | } | ||
555 | 762 | ||
556 | if ((!rc) && atomic_read(&fi->active)) { | 763 | if ((!rc) && atomic_read(&fi->active)) { |
557 | spin_lock(&fi->lock); | 764 | spin_lock(&fi->lock); |
@@ -643,18 +850,15 @@ enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer) | |||
643 | void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu) | 850 | void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu) |
644 | { | 851 | { |
645 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | 852 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; |
646 | struct kvm_s390_interrupt_info *n, *inti = NULL; | ||
647 | 853 | ||
648 | spin_lock(&li->lock); | 854 | spin_lock(&li->lock); |
649 | list_for_each_entry_safe(inti, n, &li->list, list) { | 855 | li->pending_irqs = 0; |
650 | list_del(&inti->list); | 856 | bitmap_zero(li->sigp_emerg_pending, KVM_MAX_VCPUS); |
651 | kfree(inti); | 857 | memset(&li->irq, 0, sizeof(li->irq)); |
652 | } | ||
653 | atomic_set(&li->active, 0); | ||
654 | spin_unlock(&li->lock); | 858 | spin_unlock(&li->lock); |
655 | 859 | ||
656 | /* clear pending external calls set by sigp interpretation facility */ | 860 | /* clear pending external calls set by sigp interpretation facility */ |
657 | atomic_clear_mask(CPUSTAT_ECALL_PEND, &vcpu->arch.sie_block->cpuflags); | 861 | atomic_clear_mask(CPUSTAT_ECALL_PEND, li->cpuflags); |
658 | atomic_clear_mask(SIGP_CTRL_C, | 862 | atomic_clear_mask(SIGP_CTRL_C, |
659 | &vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].ctrl); | 863 | &vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].ctrl); |
660 | } | 864 | } |
@@ -664,34 +868,35 @@ int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu) | |||
664 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | 868 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; |
665 | struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int; | 869 | struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int; |
666 | struct kvm_s390_interrupt_info *n, *inti = NULL; | 870 | struct kvm_s390_interrupt_info *n, *inti = NULL; |
871 | deliver_irq_t func; | ||
667 | int deliver; | 872 | int deliver; |
668 | int rc = 0; | 873 | int rc = 0; |
874 | unsigned long irq_type; | ||
875 | unsigned long deliverable_irqs; | ||
669 | 876 | ||
670 | __reset_intercept_indicators(vcpu); | 877 | __reset_intercept_indicators(vcpu); |
671 | if (atomic_read(&li->active)) { | ||
672 | do { | ||
673 | deliver = 0; | ||
674 | spin_lock(&li->lock); | ||
675 | list_for_each_entry_safe(inti, n, &li->list, list) { | ||
676 | if (__interrupt_is_deliverable(vcpu, inti)) { | ||
677 | list_del(&inti->list); | ||
678 | deliver = 1; | ||
679 | break; | ||
680 | } | ||
681 | __set_intercept_indicator(vcpu, inti); | ||
682 | } | ||
683 | if (list_empty(&li->list)) | ||
684 | atomic_set(&li->active, 0); | ||
685 | spin_unlock(&li->lock); | ||
686 | if (deliver) { | ||
687 | rc = __do_deliver_interrupt(vcpu, inti); | ||
688 | kfree(inti); | ||
689 | } | ||
690 | } while (!rc && deliver); | ||
691 | } | ||
692 | 878 | ||
693 | if (!rc && kvm_cpu_has_pending_timer(vcpu)) | 879 | /* pending ckc conditions might have been invalidated */ |
694 | rc = deliver_ckc_interrupt(vcpu); | 880 | clear_bit(IRQ_PEND_EXT_CLOCK_COMP, &li->pending_irqs); |
881 | if (kvm_cpu_has_pending_timer(vcpu)) | ||
882 | set_bit(IRQ_PEND_EXT_CLOCK_COMP, &li->pending_irqs); | ||
883 | |||
884 | do { | ||
885 | deliverable_irqs = deliverable_local_irqs(vcpu); | ||
886 | /* bits are in the order of interrupt priority */ | ||
887 | irq_type = find_first_bit(&deliverable_irqs, IRQ_PEND_COUNT); | ||
888 | if (irq_type == IRQ_PEND_COUNT) | ||
889 | break; | ||
890 | func = deliver_irq_funcs[irq_type]; | ||
891 | if (!func) { | ||
892 | WARN_ON_ONCE(func == NULL); | ||
893 | clear_bit(irq_type, &li->pending_irqs); | ||
894 | continue; | ||
895 | } | ||
896 | rc = func(vcpu); | ||
897 | } while (!rc && irq_type != IRQ_PEND_COUNT); | ||
898 | |||
899 | set_intercept_indicators_local(vcpu); | ||
695 | 900 | ||
696 | if (!rc && atomic_read(&fi->active)) { | 901 | if (!rc && atomic_read(&fi->active)) { |
697 | do { | 902 | do { |
@@ -710,7 +915,7 @@ int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu) | |||
710 | atomic_set(&fi->active, 0); | 915 | atomic_set(&fi->active, 0); |
711 | spin_unlock(&fi->lock); | 916 | spin_unlock(&fi->lock); |
712 | if (deliver) { | 917 | if (deliver) { |
713 | rc = __do_deliver_interrupt(vcpu, inti); | 918 | rc = __deliver_floating_interrupt(vcpu, inti); |
714 | kfree(inti); | 919 | kfree(inti); |
715 | } | 920 | } |
716 | } while (!rc && deliver); | 921 | } while (!rc && deliver); |
@@ -719,23 +924,26 @@ int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu) | |||
719 | return rc; | 924 | return rc; |
720 | } | 925 | } |
721 | 926 | ||
722 | int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code) | 927 | static int __inject_prog(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq) |
723 | { | 928 | { |
724 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | 929 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; |
725 | struct kvm_s390_interrupt_info *inti; | ||
726 | 930 | ||
727 | inti = kzalloc(sizeof(*inti), GFP_KERNEL); | 931 | li->irq.pgm = irq->u.pgm; |
728 | if (!inti) | 932 | set_bit(IRQ_PEND_PROG, &li->pending_irqs); |
729 | return -ENOMEM; | 933 | return 0; |
934 | } | ||
730 | 935 | ||
731 | inti->type = KVM_S390_PROGRAM_INT; | 936 | int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code) |
732 | inti->pgm.code = code; | 937 | { |
938 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
939 | struct kvm_s390_irq irq; | ||
733 | 940 | ||
734 | VCPU_EVENT(vcpu, 3, "inject: program check %d (from kernel)", code); | 941 | VCPU_EVENT(vcpu, 3, "inject: program check %d (from kernel)", code); |
735 | trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, inti->type, code, 0, 1); | 942 | trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_PROGRAM_INT, code, |
943 | 0, 1); | ||
736 | spin_lock(&li->lock); | 944 | spin_lock(&li->lock); |
737 | list_add(&inti->list, &li->list); | 945 | irq.u.pgm.code = code; |
738 | atomic_set(&li->active, 1); | 946 | __inject_prog(vcpu, &irq); |
739 | BUG_ON(waitqueue_active(li->wq)); | 947 | BUG_ON(waitqueue_active(li->wq)); |
740 | spin_unlock(&li->lock); | 948 | spin_unlock(&li->lock); |
741 | return 0; | 949 | return 0; |
@@ -745,27 +953,166 @@ int kvm_s390_inject_prog_irq(struct kvm_vcpu *vcpu, | |||
745 | struct kvm_s390_pgm_info *pgm_info) | 953 | struct kvm_s390_pgm_info *pgm_info) |
746 | { | 954 | { |
747 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | 955 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; |
748 | struct kvm_s390_interrupt_info *inti; | 956 | struct kvm_s390_irq irq; |
749 | 957 | int rc; | |
750 | inti = kzalloc(sizeof(*inti), GFP_KERNEL); | ||
751 | if (!inti) | ||
752 | return -ENOMEM; | ||
753 | 958 | ||
754 | VCPU_EVENT(vcpu, 3, "inject: prog irq %d (from kernel)", | 959 | VCPU_EVENT(vcpu, 3, "inject: prog irq %d (from kernel)", |
755 | pgm_info->code); | 960 | pgm_info->code); |
756 | trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_PROGRAM_INT, | 961 | trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_PROGRAM_INT, |
757 | pgm_info->code, 0, 1); | 962 | pgm_info->code, 0, 1); |
758 | |||
759 | inti->type = KVM_S390_PROGRAM_INT; | ||
760 | memcpy(&inti->pgm, pgm_info, sizeof(inti->pgm)); | ||
761 | spin_lock(&li->lock); | 963 | spin_lock(&li->lock); |
762 | list_add(&inti->list, &li->list); | 964 | irq.u.pgm = *pgm_info; |
763 | atomic_set(&li->active, 1); | 965 | rc = __inject_prog(vcpu, &irq); |
764 | BUG_ON(waitqueue_active(li->wq)); | 966 | BUG_ON(waitqueue_active(li->wq)); |
765 | spin_unlock(&li->lock); | 967 | spin_unlock(&li->lock); |
968 | return rc; | ||
969 | } | ||
970 | |||
971 | static int __inject_pfault_init(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq) | ||
972 | { | ||
973 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
974 | |||
975 | VCPU_EVENT(vcpu, 3, "inject: external irq params:%x, params2:%llx", | ||
976 | irq->u.ext.ext_params, irq->u.ext.ext_params2); | ||
977 | trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_INT_PFAULT_INIT, | ||
978 | irq->u.ext.ext_params, | ||
979 | irq->u.ext.ext_params2, 2); | ||
980 | |||
981 | li->irq.ext = irq->u.ext; | ||
982 | set_bit(IRQ_PEND_PFAULT_INIT, &li->pending_irqs); | ||
983 | atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); | ||
766 | return 0; | 984 | return 0; |
767 | } | 985 | } |
768 | 986 | ||
987 | int __inject_extcall(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq) | ||
988 | { | ||
989 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
990 | struct kvm_s390_extcall_info *extcall = &li->irq.extcall; | ||
991 | |||
992 | VCPU_EVENT(vcpu, 3, "inject: external call source-cpu:%u", | ||
993 | irq->u.extcall.code); | ||
994 | trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_INT_EXTERNAL_CALL, | ||
995 | irq->u.extcall.code, 0, 2); | ||
996 | |||
997 | *extcall = irq->u.extcall; | ||
998 | set_bit(IRQ_PEND_EXT_EXTERNAL, &li->pending_irqs); | ||
999 | atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); | ||
1000 | return 0; | ||
1001 | } | ||
1002 | |||
1003 | static int __inject_set_prefix(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq) | ||
1004 | { | ||
1005 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
1006 | struct kvm_s390_prefix_info *prefix = &li->irq.prefix; | ||
1007 | |||
1008 | VCPU_EVENT(vcpu, 3, "inject: set prefix to %x (from user)", | ||
1009 | prefix->address); | ||
1010 | trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_SIGP_SET_PREFIX, | ||
1011 | prefix->address, 0, 2); | ||
1012 | |||
1013 | *prefix = irq->u.prefix; | ||
1014 | set_bit(IRQ_PEND_SET_PREFIX, &li->pending_irqs); | ||
1015 | return 0; | ||
1016 | } | ||
1017 | |||
1018 | static int __inject_sigp_stop(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq) | ||
1019 | { | ||
1020 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
1021 | |||
1022 | trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_SIGP_STOP, 0, 0, 2); | ||
1023 | |||
1024 | li->action_bits |= ACTION_STOP_ON_STOP; | ||
1025 | set_bit(IRQ_PEND_SIGP_STOP, &li->pending_irqs); | ||
1026 | return 0; | ||
1027 | } | ||
1028 | |||
1029 | static int __inject_sigp_restart(struct kvm_vcpu *vcpu, | ||
1030 | struct kvm_s390_irq *irq) | ||
1031 | { | ||
1032 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
1033 | |||
1034 | VCPU_EVENT(vcpu, 3, "inject: restart type %llx", irq->type); | ||
1035 | trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_RESTART, 0, 0, 2); | ||
1036 | |||
1037 | set_bit(IRQ_PEND_RESTART, &li->pending_irqs); | ||
1038 | return 0; | ||
1039 | } | ||
1040 | |||
1041 | static int __inject_sigp_emergency(struct kvm_vcpu *vcpu, | ||
1042 | struct kvm_s390_irq *irq) | ||
1043 | { | ||
1044 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
1045 | struct kvm_s390_emerg_info *emerg = &li->irq.emerg; | ||
1046 | |||
1047 | VCPU_EVENT(vcpu, 3, "inject: emergency %u\n", | ||
1048 | irq->u.emerg.code); | ||
1049 | trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_INT_EMERGENCY, | ||
1050 | emerg->code, 0, 2); | ||
1051 | |||
1052 | set_bit(emerg->code, li->sigp_emerg_pending); | ||
1053 | set_bit(IRQ_PEND_EXT_EMERGENCY, &li->pending_irqs); | ||
1054 | atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); | ||
1055 | return 0; | ||
1056 | } | ||
1057 | |||
1058 | static int __inject_mchk(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq) | ||
1059 | { | ||
1060 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
1061 | struct kvm_s390_mchk_info *mchk = &li->irq.mchk; | ||
1062 | |||
1063 | VCPU_EVENT(vcpu, 5, "inject: machine check parm64:%llx", | ||
1064 | mchk->mcic); | ||
1065 | trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_MCHK, 0, | ||
1066 | mchk->mcic, 2); | ||
1067 | |||
1068 | /* | ||
1069 | * Because repressible machine checks can be indicated along with | ||
1070 | * exigent machine checks (PoP, Chapter 11, Interruption action) | ||
1071 | * we need to combine cr14, mcic and external damage code. | ||
1072 | * Failing storage address and the logout area should not be or'ed | ||
1073 | * together, we just indicate the last occurrence of the corresponding | ||
1074 | * machine check | ||
1075 | */ | ||
1076 | mchk->cr14 |= irq->u.mchk.cr14; | ||
1077 | mchk->mcic |= irq->u.mchk.mcic; | ||
1078 | mchk->ext_damage_code |= irq->u.mchk.ext_damage_code; | ||
1079 | mchk->failing_storage_address = irq->u.mchk.failing_storage_address; | ||
1080 | memcpy(&mchk->fixed_logout, &irq->u.mchk.fixed_logout, | ||
1081 | sizeof(mchk->fixed_logout)); | ||
1082 | if (mchk->mcic & MCHK_EX_MASK) | ||
1083 | set_bit(IRQ_PEND_MCHK_EX, &li->pending_irqs); | ||
1084 | else if (mchk->mcic & MCHK_REP_MASK) | ||
1085 | set_bit(IRQ_PEND_MCHK_REP, &li->pending_irqs); | ||
1086 | return 0; | ||
1087 | } | ||
1088 | |||
1089 | static int __inject_ckc(struct kvm_vcpu *vcpu) | ||
1090 | { | ||
1091 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
1092 | |||
1093 | VCPU_EVENT(vcpu, 3, "inject: type %x", KVM_S390_INT_CLOCK_COMP); | ||
1094 | trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_INT_CLOCK_COMP, | ||
1095 | 0, 0, 2); | ||
1096 | |||
1097 | set_bit(IRQ_PEND_EXT_CLOCK_COMP, &li->pending_irqs); | ||
1098 | atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); | ||
1099 | return 0; | ||
1100 | } | ||
1101 | |||
1102 | static int __inject_cpu_timer(struct kvm_vcpu *vcpu) | ||
1103 | { | ||
1104 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
1105 | |||
1106 | VCPU_EVENT(vcpu, 3, "inject: type %x", KVM_S390_INT_CPU_TIMER); | ||
1107 | trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_INT_CPU_TIMER, | ||
1108 | 0, 0, 2); | ||
1109 | |||
1110 | set_bit(IRQ_PEND_EXT_CPU_TIMER, &li->pending_irqs); | ||
1111 | atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); | ||
1112 | return 0; | ||
1113 | } | ||
1114 | |||
1115 | |||
769 | struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm, | 1116 | struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm, |
770 | u64 cr6, u64 schid) | 1117 | u64 cr6, u64 schid) |
771 | { | 1118 | { |
@@ -851,7 +1198,17 @@ static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti) | |||
851 | dst_vcpu = kvm_get_vcpu(kvm, sigcpu); | 1198 | dst_vcpu = kvm_get_vcpu(kvm, sigcpu); |
852 | li = &dst_vcpu->arch.local_int; | 1199 | li = &dst_vcpu->arch.local_int; |
853 | spin_lock(&li->lock); | 1200 | spin_lock(&li->lock); |
854 | atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); | 1201 | switch (inti->type) { |
1202 | case KVM_S390_MCHK: | ||
1203 | atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags); | ||
1204 | break; | ||
1205 | case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: | ||
1206 | atomic_set_mask(CPUSTAT_IO_INT, li->cpuflags); | ||
1207 | break; | ||
1208 | default: | ||
1209 | atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); | ||
1210 | break; | ||
1211 | } | ||
855 | spin_unlock(&li->lock); | 1212 | spin_unlock(&li->lock); |
856 | kvm_s390_vcpu_wakeup(kvm_get_vcpu(kvm, sigcpu)); | 1213 | kvm_s390_vcpu_wakeup(kvm_get_vcpu(kvm, sigcpu)); |
857 | unlock_fi: | 1214 | unlock_fi: |
@@ -920,92 +1277,85 @@ void kvm_s390_reinject_io_int(struct kvm *kvm, | |||
920 | __inject_vm(kvm, inti); | 1277 | __inject_vm(kvm, inti); |
921 | } | 1278 | } |
922 | 1279 | ||
923 | int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, | 1280 | int s390int_to_s390irq(struct kvm_s390_interrupt *s390int, |
924 | struct kvm_s390_interrupt *s390int) | 1281 | struct kvm_s390_irq *irq) |
925 | { | 1282 | { |
926 | struct kvm_s390_local_interrupt *li; | 1283 | irq->type = s390int->type; |
927 | struct kvm_s390_interrupt_info *inti; | 1284 | switch (irq->type) { |
1285 | case KVM_S390_PROGRAM_INT: | ||
1286 | if (s390int->parm & 0xffff0000) | ||
1287 | return -EINVAL; | ||
1288 | irq->u.pgm.code = s390int->parm; | ||
1289 | break; | ||
1290 | case KVM_S390_SIGP_SET_PREFIX: | ||
1291 | irq->u.prefix.address = s390int->parm; | ||
1292 | break; | ||
1293 | case KVM_S390_INT_EXTERNAL_CALL: | ||
1294 | if (irq->u.extcall.code & 0xffff0000) | ||
1295 | return -EINVAL; | ||
1296 | irq->u.extcall.code = s390int->parm; | ||
1297 | break; | ||
1298 | case KVM_S390_INT_EMERGENCY: | ||
1299 | if (irq->u.emerg.code & 0xffff0000) | ||
1300 | return -EINVAL; | ||
1301 | irq->u.emerg.code = s390int->parm; | ||
1302 | break; | ||
1303 | case KVM_S390_MCHK: | ||
1304 | irq->u.mchk.mcic = s390int->parm64; | ||
1305 | break; | ||
1306 | } | ||
1307 | return 0; | ||
1308 | } | ||
928 | 1309 | ||
929 | inti = kzalloc(sizeof(*inti), GFP_KERNEL); | 1310 | int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq) |
930 | if (!inti) | 1311 | { |
931 | return -ENOMEM; | 1312 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; |
1313 | int rc; | ||
932 | 1314 | ||
933 | switch (s390int->type) { | 1315 | spin_lock(&li->lock); |
1316 | switch (irq->type) { | ||
934 | case KVM_S390_PROGRAM_INT: | 1317 | case KVM_S390_PROGRAM_INT: |
935 | if (s390int->parm & 0xffff0000) { | ||
936 | kfree(inti); | ||
937 | return -EINVAL; | ||
938 | } | ||
939 | inti->type = s390int->type; | ||
940 | inti->pgm.code = s390int->parm; | ||
941 | VCPU_EVENT(vcpu, 3, "inject: program check %d (from user)", | 1318 | VCPU_EVENT(vcpu, 3, "inject: program check %d (from user)", |
942 | s390int->parm); | 1319 | irq->u.pgm.code); |
1320 | rc = __inject_prog(vcpu, irq); | ||
943 | break; | 1321 | break; |
944 | case KVM_S390_SIGP_SET_PREFIX: | 1322 | case KVM_S390_SIGP_SET_PREFIX: |
945 | inti->prefix.address = s390int->parm; | 1323 | rc = __inject_set_prefix(vcpu, irq); |
946 | inti->type = s390int->type; | ||
947 | VCPU_EVENT(vcpu, 3, "inject: set prefix to %x (from user)", | ||
948 | s390int->parm); | ||
949 | break; | 1324 | break; |
950 | case KVM_S390_SIGP_STOP: | 1325 | case KVM_S390_SIGP_STOP: |
1326 | rc = __inject_sigp_stop(vcpu, irq); | ||
1327 | break; | ||
951 | case KVM_S390_RESTART: | 1328 | case KVM_S390_RESTART: |
1329 | rc = __inject_sigp_restart(vcpu, irq); | ||
1330 | break; | ||
952 | case KVM_S390_INT_CLOCK_COMP: | 1331 | case KVM_S390_INT_CLOCK_COMP: |
1332 | rc = __inject_ckc(vcpu); | ||
1333 | break; | ||
953 | case KVM_S390_INT_CPU_TIMER: | 1334 | case KVM_S390_INT_CPU_TIMER: |
954 | VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type); | 1335 | rc = __inject_cpu_timer(vcpu); |
955 | inti->type = s390int->type; | ||
956 | break; | 1336 | break; |
957 | case KVM_S390_INT_EXTERNAL_CALL: | 1337 | case KVM_S390_INT_EXTERNAL_CALL: |
958 | if (s390int->parm & 0xffff0000) { | 1338 | rc = __inject_extcall(vcpu, irq); |
959 | kfree(inti); | ||
960 | return -EINVAL; | ||
961 | } | ||
962 | VCPU_EVENT(vcpu, 3, "inject: external call source-cpu:%u", | ||
963 | s390int->parm); | ||
964 | inti->type = s390int->type; | ||
965 | inti->extcall.code = s390int->parm; | ||
966 | break; | 1339 | break; |
967 | case KVM_S390_INT_EMERGENCY: | 1340 | case KVM_S390_INT_EMERGENCY: |
968 | if (s390int->parm & 0xffff0000) { | 1341 | rc = __inject_sigp_emergency(vcpu, irq); |
969 | kfree(inti); | ||
970 | return -EINVAL; | ||
971 | } | ||
972 | VCPU_EVENT(vcpu, 3, "inject: emergency %u\n", s390int->parm); | ||
973 | inti->type = s390int->type; | ||
974 | inti->emerg.code = s390int->parm; | ||
975 | break; | 1342 | break; |
976 | case KVM_S390_MCHK: | 1343 | case KVM_S390_MCHK: |
977 | VCPU_EVENT(vcpu, 5, "inject: machine check parm64:%llx", | 1344 | rc = __inject_mchk(vcpu, irq); |
978 | s390int->parm64); | ||
979 | inti->type = s390int->type; | ||
980 | inti->mchk.mcic = s390int->parm64; | ||
981 | break; | 1345 | break; |
982 | case KVM_S390_INT_PFAULT_INIT: | 1346 | case KVM_S390_INT_PFAULT_INIT: |
983 | inti->type = s390int->type; | 1347 | rc = __inject_pfault_init(vcpu, irq); |
984 | inti->ext.ext_params2 = s390int->parm64; | ||
985 | break; | 1348 | break; |
986 | case KVM_S390_INT_VIRTIO: | 1349 | case KVM_S390_INT_VIRTIO: |
987 | case KVM_S390_INT_SERVICE: | 1350 | case KVM_S390_INT_SERVICE: |
988 | case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: | 1351 | case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: |
989 | default: | 1352 | default: |
990 | kfree(inti); | 1353 | rc = -EINVAL; |
991 | return -EINVAL; | ||
992 | } | 1354 | } |
993 | trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, s390int->type, s390int->parm, | ||
994 | s390int->parm64, 2); | ||
995 | |||
996 | li = &vcpu->arch.local_int; | ||
997 | spin_lock(&li->lock); | ||
998 | if (inti->type == KVM_S390_PROGRAM_INT) | ||
999 | list_add(&inti->list, &li->list); | ||
1000 | else | ||
1001 | list_add_tail(&inti->list, &li->list); | ||
1002 | atomic_set(&li->active, 1); | ||
1003 | if (inti->type == KVM_S390_SIGP_STOP) | ||
1004 | li->action_bits |= ACTION_STOP_ON_STOP; | ||
1005 | atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); | ||
1006 | spin_unlock(&li->lock); | 1355 | spin_unlock(&li->lock); |
1007 | kvm_s390_vcpu_wakeup(vcpu); | 1356 | if (!rc) |
1008 | return 0; | 1357 | kvm_s390_vcpu_wakeup(vcpu); |
1358 | return rc; | ||
1009 | } | 1359 | } |
1010 | 1360 | ||
1011 | void kvm_s390_clear_float_irqs(struct kvm *kvm) | 1361 | void kvm_s390_clear_float_irqs(struct kvm *kvm) |