aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm/interrupt.c
diff options
context:
space:
mode:
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>2015-11-04 10:33:33 -0500
committerChristian Borntraeger <borntraeger@de.ibm.com>2016-02-10 07:12:50 -0500
commit634790b82759c98ee57c80966d859083fa2fcd8c (patch)
tree4b97fd83e565d6e9d6a1772fb11f1c54ce26f920 /arch/s390/kvm/interrupt.c
parent0e8bc06a2fbb4d6b688baa8e2416cd07f9453595 (diff)
KVM: s390: migration / injection of prog irq ilc
We have to migrate the program irq ilc and someday we will have to specify the ilc without KVM trying to autodetect the value. Let's reuse one of the spare fields in our program irq that should always be set to 0 by user space. Because we also want to make use of 0 ilcs ("not available"), we need a validity indicator. If no valid ilc is given, we try to autodetect the ilc via the current icptcode and icptstatus + parameter and store the valid ilc in the irq structure. This has a nice effect: QEMU's making use of KVM_S390_IRQ / KVM_S390_SET_IRQ_STATE / KVM_S390_GET_IRQ_STATE for migration will directly migrate the ilc without any changes. Please note that we use bit 0 as validity and bit 1,2 for the ilc, so by applying the ilc mask we directly get the ilen which is usually what we work with. 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.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index daa4fdbcc91c..e594a7830022 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -571,7 +571,7 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
571 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; 571 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
572 struct kvm_s390_pgm_info pgm_info; 572 struct kvm_s390_pgm_info pgm_info;
573 int rc = 0, nullifying = false; 573 int rc = 0, nullifying = false;
574 u16 ilen = kvm_s390_get_ilen(vcpu); 574 u16 ilen;
575 575
576 spin_lock(&li->lock); 576 spin_lock(&li->lock);
577 pgm_info = li->irq.pgm; 577 pgm_info = li->irq.pgm;
@@ -579,6 +579,7 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
579 memset(&li->irq.pgm, 0, sizeof(pgm_info)); 579 memset(&li->irq.pgm, 0, sizeof(pgm_info));
580 spin_unlock(&li->lock); 580 spin_unlock(&li->lock);
581 581
582 ilen = pgm_info.flags & KVM_S390_PGM_FLAGS_ILC_MASK;
582 VCPU_EVENT(vcpu, 3, "deliver: program irq code 0x%x, ilen:%d", 583 VCPU_EVENT(vcpu, 3, "deliver: program irq code 0x%x, ilen:%d",
583 pgm_info.code, ilen); 584 pgm_info.code, ilen);
584 vcpu->stat.deliver_program_int++; 585 vcpu->stat.deliver_program_int++;
@@ -1043,8 +1044,16 @@ static int __inject_prog(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)
1043 trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_PROGRAM_INT, 1044 trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_PROGRAM_INT,
1044 irq->u.pgm.code, 0); 1045 irq->u.pgm.code, 0);
1045 1046
1047 if (!(irq->u.pgm.flags & KVM_S390_PGM_FLAGS_ILC_VALID)) {
1048 /* auto detection if no valid ILC was given */
1049 irq->u.pgm.flags &= ~KVM_S390_PGM_FLAGS_ILC_MASK;
1050 irq->u.pgm.flags |= kvm_s390_get_ilen(vcpu);
1051 irq->u.pgm.flags |= KVM_S390_PGM_FLAGS_ILC_VALID;
1052 }
1053
1046 if (irq->u.pgm.code == PGM_PER) { 1054 if (irq->u.pgm.code == PGM_PER) {
1047 li->irq.pgm.code |= PGM_PER; 1055 li->irq.pgm.code |= PGM_PER;
1056 li->irq.pgm.flags = irq->u.pgm.flags;
1048 /* only modify PER related information */ 1057 /* only modify PER related information */
1049 li->irq.pgm.per_address = irq->u.pgm.per_address; 1058 li->irq.pgm.per_address = irq->u.pgm.per_address;
1050 li->irq.pgm.per_code = irq->u.pgm.per_code; 1059 li->irq.pgm.per_code = irq->u.pgm.per_code;
@@ -1053,6 +1062,7 @@ static int __inject_prog(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)
1053 } else if (!(irq->u.pgm.code & PGM_PER)) { 1062 } else if (!(irq->u.pgm.code & PGM_PER)) {
1054 li->irq.pgm.code = (li->irq.pgm.code & PGM_PER) | 1063 li->irq.pgm.code = (li->irq.pgm.code & PGM_PER) |
1055 irq->u.pgm.code; 1064 irq->u.pgm.code;
1065 li->irq.pgm.flags = irq->u.pgm.flags;
1056 /* only modify non-PER information */ 1066 /* only modify non-PER information */
1057 li->irq.pgm.trans_exc_code = irq->u.pgm.trans_exc_code; 1067 li->irq.pgm.trans_exc_code = irq->u.pgm.trans_exc_code;
1058 li->irq.pgm.mon_code = irq->u.pgm.mon_code; 1068 li->irq.pgm.mon_code = irq->u.pgm.mon_code;