diff options
author | Jens Freimann <jfrei@linux.vnet.ibm.com> | 2014-07-29 07:45:21 -0400 |
---|---|---|
committer | Christian Borntraeger <borntraeger@de.ibm.com> | 2014-11-28 07:59:03 -0500 |
commit | 0fb97abe050348bf3bc1796329e75ac522de6b14 (patch) | |
tree | fddac37a90921b842929a536e8b1ffd27847e28a /arch/s390 | |
parent | 60f90a14dd3e675adfa5c3e0a153696a0230e725 (diff) |
KVM: s390: refactor interrupt delivery code
Move delivery code for cpu-local interrupt from the huge do_deliver_interrupt()
to smaller functions which handle one type of interrupt.
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/kvm/interrupt.c | 459 |
1 files changed, 282 insertions, 177 deletions
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 481f1368c6eb..0d7f0a7be2fc 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c | |||
@@ -30,8 +30,6 @@ | |||
30 | #define PFAULT_DONE 0x0680 | 30 | #define PFAULT_DONE 0x0680 |
31 | #define VIRTIO_PARAM 0x0d00 | 31 | #define VIRTIO_PARAM 0x0d00 |
32 | 32 | ||
33 | static int __must_check deliver_ckc_interrupt(struct kvm_vcpu *vcpu); | ||
34 | |||
35 | static int is_ioint(u64 type) | 33 | static int is_ioint(u64 type) |
36 | { | 34 | { |
37 | return ((type & 0xfffe0000u) != 0xfffe0000u); | 35 | return ((type & 0xfffe0000u) != 0xfffe0000u); |
@@ -228,12 +226,183 @@ static u16 get_ilc(struct kvm_vcpu *vcpu) | |||
228 | } | 226 | } |
229 | } | 227 | } |
230 | 228 | ||
231 | static int __must_check __deliver_prog_irq(struct kvm_vcpu *vcpu, | 229 | static int __must_check __deliver_cpu_timer(struct kvm_vcpu *vcpu) |
232 | struct kvm_s390_pgm_info *pgm_info) | 230 | { |
231 | int rc; | ||
232 | |||
233 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_INT_CPU_TIMER, | ||
234 | 0, 0); | ||
235 | |||
236 | rc = put_guest_lc(vcpu, EXT_IRQ_CPU_TIMER, | ||
237 | (u16 *)__LC_EXT_INT_CODE); | ||
238 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
239 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
240 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
241 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
242 | return rc; | ||
243 | } | ||
244 | |||
245 | static int __must_check __deliver_ckc(struct kvm_vcpu *vcpu) | ||
246 | { | ||
247 | int rc; | ||
248 | |||
249 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_INT_CLOCK_COMP, | ||
250 | 0, 0); | ||
251 | |||
252 | rc = put_guest_lc(vcpu, EXT_IRQ_CLK_COMP, | ||
253 | (u16 __user *)__LC_EXT_INT_CODE); | ||
254 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
255 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
256 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
257 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
258 | return rc; | ||
259 | } | ||
260 | |||
261 | static int __must_check __deliver_pfault_init(struct kvm_vcpu *vcpu, | ||
262 | struct kvm_s390_interrupt_info *inti) | ||
263 | { | ||
264 | struct kvm_s390_ext_info *ext = &inti->ext; | ||
265 | int rc; | ||
266 | |||
267 | VCPU_EVENT(vcpu, 4, "interrupt: pfault init parm:%x,parm64:%llx", | ||
268 | 0, ext->ext_params2); | ||
269 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, | ||
270 | KVM_S390_INT_PFAULT_INIT, | ||
271 | 0, ext->ext_params2); | ||
272 | |||
273 | rc = put_guest_lc(vcpu, EXT_IRQ_CP_SERVICE, (u16 *) __LC_EXT_INT_CODE); | ||
274 | rc |= put_guest_lc(vcpu, PFAULT_INIT, (u16 *) __LC_EXT_CPU_ADDR); | ||
275 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
276 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
277 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
278 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
279 | rc |= put_guest_lc(vcpu, ext->ext_params2, (u64 *) __LC_EXT_PARAMS2); | ||
280 | return rc; | ||
281 | } | ||
282 | |||
283 | static int __must_check __deliver_machine_check(struct kvm_vcpu *vcpu, | ||
284 | struct kvm_s390_interrupt_info *inti) | ||
285 | { | ||
286 | struct kvm_s390_mchk_info *mchk = &inti->mchk; | ||
287 | int rc; | ||
288 | |||
289 | VCPU_EVENT(vcpu, 4, "interrupt: machine check mcic=%llx", | ||
290 | mchk->mcic); | ||
291 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_MCHK, | ||
292 | mchk->cr14, mchk->mcic); | ||
293 | |||
294 | rc = kvm_s390_vcpu_store_status(vcpu, KVM_S390_STORE_STATUS_PREFIXED); | ||
295 | rc |= put_guest_lc(vcpu, mchk->mcic, | ||
296 | (u64 __user *) __LC_MCCK_CODE); | ||
297 | rc |= put_guest_lc(vcpu, mchk->failing_storage_address, | ||
298 | (u64 __user *) __LC_MCCK_FAIL_STOR_ADDR); | ||
299 | rc |= write_guest_lc(vcpu, __LC_PSW_SAVE_AREA, | ||
300 | &mchk->fixed_logout, sizeof(mchk->fixed_logout)); | ||
301 | rc |= write_guest_lc(vcpu, __LC_MCK_OLD_PSW, | ||
302 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
303 | rc |= read_guest_lc(vcpu, __LC_MCK_NEW_PSW, | ||
304 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
305 | return rc; | ||
306 | } | ||
307 | |||
308 | static int __must_check __deliver_restart(struct kvm_vcpu *vcpu) | ||
309 | { | ||
310 | int rc; | ||
311 | |||
312 | VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu restart"); | ||
313 | vcpu->stat.deliver_restart_signal++; | ||
314 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_RESTART, 0, 0); | ||
315 | |||
316 | rc = write_guest_lc(vcpu, | ||
317 | offsetof(struct _lowcore, restart_old_psw), | ||
318 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
319 | rc |= read_guest_lc(vcpu, offsetof(struct _lowcore, restart_psw), | ||
320 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
321 | return rc; | ||
322 | } | ||
323 | |||
324 | static int __must_check __deliver_stop(struct kvm_vcpu *vcpu) | ||
325 | { | ||
326 | VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu stop"); | ||
327 | vcpu->stat.deliver_stop_signal++; | ||
328 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_SIGP_STOP, | ||
329 | 0, 0); | ||
330 | |||
331 | __set_cpuflag(vcpu, CPUSTAT_STOP_INT); | ||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | static int __must_check __deliver_set_prefix(struct kvm_vcpu *vcpu, | ||
336 | struct kvm_s390_interrupt_info *inti) | ||
337 | { | ||
338 | struct kvm_s390_prefix_info *prefix = &inti->prefix; | ||
339 | |||
340 | VCPU_EVENT(vcpu, 4, "interrupt: set prefix to %x", prefix->address); | ||
341 | vcpu->stat.deliver_prefix_signal++; | ||
342 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, | ||
343 | KVM_S390_SIGP_SET_PREFIX, | ||
344 | prefix->address, 0); | ||
345 | |||
346 | kvm_s390_set_prefix(vcpu, prefix->address); | ||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | static int __must_check __deliver_emergency_signal(struct kvm_vcpu *vcpu, | ||
351 | struct kvm_s390_interrupt_info *inti) | ||
352 | { | ||
353 | struct kvm_s390_emerg_info *emerg = &inti->emerg; | ||
354 | int rc; | ||
355 | |||
356 | VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp emerg"); | ||
357 | vcpu->stat.deliver_emergency_signal++; | ||
358 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
359 | inti->emerg.code, 0); | ||
360 | |||
361 | rc = put_guest_lc(vcpu, EXT_IRQ_EMERGENCY_SIG, | ||
362 | (u16 *)__LC_EXT_INT_CODE); | ||
363 | rc |= put_guest_lc(vcpu, emerg->code, (u16 *)__LC_EXT_CPU_ADDR); | ||
364 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
365 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
366 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
367 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
368 | return rc; | ||
369 | } | ||
370 | |||
371 | static int __must_check __deliver_external_call(struct kvm_vcpu *vcpu, | ||
372 | struct kvm_s390_interrupt_info *inti) | ||
373 | { | ||
374 | struct kvm_s390_extcall_info *extcall = &inti->extcall; | ||
375 | int rc; | ||
376 | |||
377 | VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp ext call"); | ||
378 | vcpu->stat.deliver_external_call++; | ||
379 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, | ||
380 | KVM_S390_INT_EXTERNAL_CALL, | ||
381 | extcall->code, 0); | ||
382 | |||
383 | rc = put_guest_lc(vcpu, EXT_IRQ_EXTERNAL_CALL, | ||
384 | (u16 *)__LC_EXT_INT_CODE); | ||
385 | rc |= put_guest_lc(vcpu, extcall->code, (u16 *)__LC_EXT_CPU_ADDR); | ||
386 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
387 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
388 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, &vcpu->arch.sie_block->gpsw, | ||
389 | sizeof(psw_t)); | ||
390 | return rc; | ||
391 | } | ||
392 | |||
393 | static int __must_check __deliver_prog(struct kvm_vcpu *vcpu, | ||
394 | struct kvm_s390_interrupt_info *inti) | ||
233 | { | 395 | { |
396 | struct kvm_s390_pgm_info *pgm_info = &inti->pgm; | ||
234 | int rc = 0; | 397 | int rc = 0; |
235 | u16 ilc = get_ilc(vcpu); | 398 | u16 ilc = get_ilc(vcpu); |
236 | 399 | ||
400 | VCPU_EVENT(vcpu, 4, "interrupt: pgm check code:%x, ilc:%x", | ||
401 | pgm_info->code, ilc); | ||
402 | vcpu->stat.deliver_program_int++; | ||
403 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_PROGRAM_INT, | ||
404 | pgm_info->code, 0); | ||
405 | |||
237 | switch (pgm_info->code & ~PGM_PER) { | 406 | switch (pgm_info->code & ~PGM_PER) { |
238 | case PGM_AFX_TRANSLATION: | 407 | case PGM_AFX_TRANSLATION: |
239 | case PGM_ASX_TRANSLATION: | 408 | case PGM_ASX_TRANSLATION: |
@@ -306,202 +475,151 @@ static int __must_check __deliver_prog_irq(struct kvm_vcpu *vcpu, | |||
306 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | 475 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); |
307 | rc |= read_guest_lc(vcpu, __LC_PGM_NEW_PSW, | 476 | rc |= read_guest_lc(vcpu, __LC_PGM_NEW_PSW, |
308 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | 477 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); |
478 | return rc; | ||
479 | } | ||
480 | |||
481 | static int __must_check __deliver_service(struct kvm_vcpu *vcpu, | ||
482 | struct kvm_s390_interrupt_info *inti) | ||
483 | { | ||
484 | int rc; | ||
485 | |||
486 | VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x", | ||
487 | inti->ext.ext_params); | ||
488 | vcpu->stat.deliver_service_signal++; | ||
489 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
490 | inti->ext.ext_params, 0); | ||
491 | |||
492 | rc = put_guest_lc(vcpu, EXT_IRQ_SERVICE_SIG, (u16 *)__LC_EXT_INT_CODE); | ||
493 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
494 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
495 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
496 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
497 | rc |= put_guest_lc(vcpu, inti->ext.ext_params, | ||
498 | (u32 *)__LC_EXT_PARAMS); | ||
499 | return rc; | ||
500 | } | ||
501 | |||
502 | static int __must_check __deliver_pfault_done(struct kvm_vcpu *vcpu, | ||
503 | struct kvm_s390_interrupt_info *inti) | ||
504 | { | ||
505 | int rc; | ||
506 | |||
507 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, | ||
508 | KVM_S390_INT_PFAULT_DONE, 0, | ||
509 | inti->ext.ext_params2); | ||
309 | 510 | ||
511 | rc = put_guest_lc(vcpu, EXT_IRQ_CP_SERVICE, (u16 *)__LC_EXT_INT_CODE); | ||
512 | rc |= put_guest_lc(vcpu, PFAULT_DONE, (u16 *)__LC_EXT_CPU_ADDR); | ||
513 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
514 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
515 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
516 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
517 | rc |= put_guest_lc(vcpu, inti->ext.ext_params2, | ||
518 | (u64 *)__LC_EXT_PARAMS2); | ||
519 | return rc; | ||
520 | } | ||
521 | |||
522 | static int __must_check __deliver_virtio(struct kvm_vcpu *vcpu, | ||
523 | struct kvm_s390_interrupt_info *inti) | ||
524 | { | ||
525 | int rc; | ||
526 | |||
527 | VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%llx", | ||
528 | inti->ext.ext_params, inti->ext.ext_params2); | ||
529 | vcpu->stat.deliver_virtio_interrupt++; | ||
530 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
531 | inti->ext.ext_params, | ||
532 | inti->ext.ext_params2); | ||
533 | |||
534 | rc = put_guest_lc(vcpu, EXT_IRQ_CP_SERVICE, (u16 *)__LC_EXT_INT_CODE); | ||
535 | rc |= put_guest_lc(vcpu, VIRTIO_PARAM, (u16 *)__LC_EXT_CPU_ADDR); | ||
536 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
537 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
538 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
539 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
540 | rc |= put_guest_lc(vcpu, inti->ext.ext_params, | ||
541 | (u32 *)__LC_EXT_PARAMS); | ||
542 | rc |= put_guest_lc(vcpu, inti->ext.ext_params2, | ||
543 | (u64 *)__LC_EXT_PARAMS2); | ||
544 | return rc; | ||
545 | } | ||
546 | |||
547 | static int __must_check __deliver_io(struct kvm_vcpu *vcpu, | ||
548 | struct kvm_s390_interrupt_info *inti) | ||
549 | { | ||
550 | int rc; | ||
551 | |||
552 | VCPU_EVENT(vcpu, 4, "interrupt: I/O %llx", inti->type); | ||
553 | vcpu->stat.deliver_io_int++; | ||
554 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
555 | ((__u32)inti->io.subchannel_id << 16) | | ||
556 | inti->io.subchannel_nr, | ||
557 | ((__u64)inti->io.io_int_parm << 32) | | ||
558 | inti->io.io_int_word); | ||
559 | |||
560 | rc = put_guest_lc(vcpu, inti->io.subchannel_id, | ||
561 | (u16 *)__LC_SUBCHANNEL_ID); | ||
562 | rc |= put_guest_lc(vcpu, inti->io.subchannel_nr, | ||
563 | (u16 *)__LC_SUBCHANNEL_NR); | ||
564 | rc |= put_guest_lc(vcpu, inti->io.io_int_parm, | ||
565 | (u32 *)__LC_IO_INT_PARM); | ||
566 | rc |= put_guest_lc(vcpu, inti->io.io_int_word, | ||
567 | (u32 *)__LC_IO_INT_WORD); | ||
568 | rc |= write_guest_lc(vcpu, __LC_IO_OLD_PSW, | ||
569 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
570 | rc |= read_guest_lc(vcpu, __LC_IO_NEW_PSW, | ||
571 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
310 | return rc; | 572 | return rc; |
311 | } | 573 | } |
312 | 574 | ||
313 | static int __must_check __do_deliver_interrupt(struct kvm_vcpu *vcpu, | 575 | static int __must_check __do_deliver_interrupt(struct kvm_vcpu *vcpu, |
314 | struct kvm_s390_interrupt_info *inti) | 576 | struct kvm_s390_interrupt_info *inti) |
315 | { | 577 | { |
316 | const unsigned short table[] = { 2, 4, 4, 6 }; | 578 | int rc; |
317 | int rc = 0; | ||
318 | 579 | ||
319 | switch (inti->type) { | 580 | switch (inti->type) { |
320 | case KVM_S390_INT_EMERGENCY: | 581 | case KVM_S390_INT_EMERGENCY: |
321 | VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp emerg"); | 582 | rc = __deliver_emergency_signal(vcpu, inti); |
322 | vcpu->stat.deliver_emergency_signal++; | ||
323 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
324 | inti->emerg.code, 0); | ||
325 | rc = put_guest_lc(vcpu, 0x1201, (u16 *)__LC_EXT_INT_CODE); | ||
326 | rc |= put_guest_lc(vcpu, inti->emerg.code, | ||
327 | (u16 *)__LC_EXT_CPU_ADDR); | ||
328 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
329 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
330 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
331 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
332 | break; | 583 | break; |
333 | case KVM_S390_INT_EXTERNAL_CALL: | 584 | case KVM_S390_INT_EXTERNAL_CALL: |
334 | VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp ext call"); | 585 | rc = __deliver_external_call(vcpu, inti); |
335 | vcpu->stat.deliver_external_call++; | ||
336 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
337 | inti->extcall.code, 0); | ||
338 | rc = put_guest_lc(vcpu, 0x1202, (u16 *)__LC_EXT_INT_CODE); | ||
339 | rc |= put_guest_lc(vcpu, inti->extcall.code, | ||
340 | (u16 *)__LC_EXT_CPU_ADDR); | ||
341 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
342 | &vcpu->arch.sie_block->gpsw, | ||
343 | sizeof(psw_t)); | ||
344 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
345 | &vcpu->arch.sie_block->gpsw, | ||
346 | sizeof(psw_t)); | ||
347 | break; | 586 | break; |
348 | case KVM_S390_INT_CLOCK_COMP: | 587 | case KVM_S390_INT_CLOCK_COMP: |
349 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | 588 | rc = __deliver_ckc(vcpu); |
350 | 0, 0); | ||
351 | rc = deliver_ckc_interrupt(vcpu); | ||
352 | break; | 589 | break; |
353 | case KVM_S390_INT_CPU_TIMER: | 590 | case KVM_S390_INT_CPU_TIMER: |
354 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | 591 | rc = __deliver_cpu_timer(vcpu); |
355 | 0, 0); | ||
356 | rc = put_guest_lc(vcpu, EXT_IRQ_CPU_TIMER, | ||
357 | (u16 *)__LC_EXT_INT_CODE); | ||
358 | rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, | ||
359 | &vcpu->arch.sie_block->gpsw, | ||
360 | sizeof(psw_t)); | ||
361 | rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, | ||
362 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
363 | break; | 592 | break; |
364 | case KVM_S390_INT_SERVICE: | 593 | case KVM_S390_INT_SERVICE: |
365 | VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x", | 594 | 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; | 595 | break; |
379 | case KVM_S390_INT_PFAULT_INIT: | 596 | case KVM_S390_INT_PFAULT_INIT: |
380 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, 0, | 597 | rc = __deliver_pfault_init(vcpu, inti); |
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; | 598 | break; |
392 | case KVM_S390_INT_PFAULT_DONE: | 599 | case KVM_S390_INT_PFAULT_DONE: |
393 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, 0, | 600 | 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, PFAULT_DONE, (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; | 601 | break; |
405 | case KVM_S390_INT_VIRTIO: | 602 | case KVM_S390_INT_VIRTIO: |
406 | VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%llx", | 603 | 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, VIRTIO_PARAM, (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; | 604 | break; |
424 | case KVM_S390_SIGP_STOP: | 605 | case KVM_S390_SIGP_STOP: |
425 | VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu stop"); | 606 | rc = __deliver_stop(vcpu); |
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; | 607 | break; |
431 | |||
432 | case KVM_S390_SIGP_SET_PREFIX: | 608 | case KVM_S390_SIGP_SET_PREFIX: |
433 | VCPU_EVENT(vcpu, 4, "interrupt: set prefix to %x", | 609 | rc = __deliver_set_prefix(vcpu, inti); |
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; | 610 | break; |
440 | |||
441 | case KVM_S390_RESTART: | 611 | case KVM_S390_RESTART: |
442 | VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu restart"); | 612 | rc = __deliver_restart(vcpu); |
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; | 613 | break; |
453 | case KVM_S390_PROGRAM_INT: | 614 | case KVM_S390_PROGRAM_INT: |
454 | VCPU_EVENT(vcpu, 4, "interrupt: pgm check code:%x, ilc:%x", | 615 | rc = __deliver_prog(vcpu, inti); |
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; | 616 | break; |
462 | |||
463 | case KVM_S390_MCHK: | 617 | case KVM_S390_MCHK: |
464 | VCPU_EVENT(vcpu, 4, "interrupt: machine check mcic=%llx", | 618 | rc = __deliver_machine_check(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; | 619 | break; |
478 | |||
479 | case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: | 620 | case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: |
480 | { | 621 | 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; | 622 | break; |
504 | } | ||
505 | default: | 623 | default: |
506 | BUG(); | 624 | BUG(); |
507 | } | 625 | } |
@@ -509,19 +627,6 @@ static int __must_check __do_deliver_interrupt(struct kvm_vcpu *vcpu, | |||
509 | return rc; | 627 | return rc; |
510 | } | 628 | } |
511 | 629 | ||
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 */ | 630 | /* Check whether SIGP interpretation facility has an external call pending */ |
526 | int kvm_s390_si_ext_call_pending(struct kvm_vcpu *vcpu) | 631 | int kvm_s390_si_ext_call_pending(struct kvm_vcpu *vcpu) |
527 | { | 632 | { |
@@ -691,7 +796,7 @@ int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu) | |||
691 | } | 796 | } |
692 | 797 | ||
693 | if (!rc && kvm_cpu_has_pending_timer(vcpu)) | 798 | if (!rc && kvm_cpu_has_pending_timer(vcpu)) |
694 | rc = deliver_ckc_interrupt(vcpu); | 799 | rc = __deliver_ckc(vcpu); |
695 | 800 | ||
696 | if (!rc && atomic_read(&fi->active)) { | 801 | if (!rc && atomic_read(&fi->active)) { |
697 | do { | 802 | do { |