aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm/interrupt.c
diff options
context:
space:
mode:
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>2015-05-04 06:38:48 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2015-10-13 09:50:34 -0400
commit238293b14d9b1f5689e2aa68710000b0f25aa612 (patch)
treef67f8367b2c17e22d26e8a5617f868a1f9b1d81d /arch/s390/kvm/interrupt.c
parent66933b78e3204057bfc26343afcd0d463c0e8e55 (diff)
KVM: s390: correctly handle injection of pgm irqs and per events
PER events can always co-exist with other program interrupts. For now, we always overwrite all program interrupt parameters when injecting any type of program interrupt. Let's handle that correctly by only overwriting the relevant portion of the program interrupt parameters. Therefore we can now inject PER events and ordinary program interrupts concurrently, resulting in no loss of program interrupts. This will especially by helpful when manually detecting PER events later - as both types might be triggered during one SIE exit. Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'arch/s390/kvm/interrupt.c')
-rw-r--r--arch/s390/kvm/interrupt.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index f603bacf6ac9..a8be542b9cb0 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -972,7 +972,26 @@ static int __inject_prog(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)
972 trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_PROGRAM_INT, 972 trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_PROGRAM_INT,
973 irq->u.pgm.code, 0); 973 irq->u.pgm.code, 0);
974 974
975 li->irq.pgm = irq->u.pgm; 975 if (irq->u.pgm.code == PGM_PER) {
976 li->irq.pgm.code |= PGM_PER;
977 /* only modify PER related information */
978 li->irq.pgm.per_address = irq->u.pgm.per_address;
979 li->irq.pgm.per_code = irq->u.pgm.per_code;
980 li->irq.pgm.per_atmid = irq->u.pgm.per_atmid;
981 li->irq.pgm.per_access_id = irq->u.pgm.per_access_id;
982 } else if (!(irq->u.pgm.code & PGM_PER)) {
983 li->irq.pgm.code = (li->irq.pgm.code & PGM_PER) |
984 irq->u.pgm.code;
985 /* only modify non-PER information */
986 li->irq.pgm.trans_exc_code = irq->u.pgm.trans_exc_code;
987 li->irq.pgm.mon_code = irq->u.pgm.mon_code;
988 li->irq.pgm.data_exc_code = irq->u.pgm.data_exc_code;
989 li->irq.pgm.mon_class_nr = irq->u.pgm.mon_class_nr;
990 li->irq.pgm.exc_access_id = irq->u.pgm.exc_access_id;
991 li->irq.pgm.op_access_id = irq->u.pgm.op_access_id;
992 } else {
993 li->irq.pgm = irq->u.pgm;
994 }
976 set_bit(IRQ_PEND_PROG, &li->pending_irqs); 995 set_bit(IRQ_PEND_PROG, &li->pending_irqs);
977 return 0; 996 return 0;
978} 997}