aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Mueller <mimu@linux.vnet.ibm.com>2017-07-07 09:27:31 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2018-01-26 08:13:55 -0500
commit4b35f65e67ee0e5bc4f394efa14a9fa3917cd2c1 (patch)
tree70115cbdcd048413163b169c9939d3423da3e248
parent24160af6cb289ace9bde980b33d11713c8fc8192 (diff)
KVM: s390: make kvm_s390_get_io_int() aware of GISA
The function returns a pending I/O interrupt with the highest priority defined by its ISC. Together with AIV activation, pending adapter interrupts are managed by the GISA IPM. Thus kvm_s390_get_io_int() needs to inspect the IPM as well when the interrupt with the highest priority has to be identified. In case classic and adapter interrupts with the same ISC are pending, the classic interrupt will be returned first. Signed-off-by: Michael Mueller <mimu@linux.vnet.ibm.com> Reviewed-by: Halil Pasic <pasic@linux.vnet.ibm.com> Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com> Reviewed-by: Cornelia Huck <cohuck@redhat.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
-rw-r--r--arch/s390/kvm/interrupt.c74
1 files changed, 70 insertions, 4 deletions
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index dd4c50b82a53..f2dc86884ea4 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -1471,20 +1471,86 @@ static struct kvm_s390_interrupt_info *get_io_int(struct kvm *kvm,
1471 return NULL; 1471 return NULL;
1472} 1472}
1473 1473
1474static struct kvm_s390_interrupt_info *get_top_io_int(struct kvm *kvm,
1475 u64 isc_mask, u32 schid)
1476{
1477 struct kvm_s390_interrupt_info *inti = NULL;
1478 int isc;
1479
1480 for (isc = 0; isc <= MAX_ISC && !inti; isc++) {
1481 if (isc_mask & isc_to_isc_bits(isc))
1482 inti = get_io_int(kvm, isc, schid);
1483 }
1484 return inti;
1485}
1486
1487static int get_top_gisa_isc(struct kvm *kvm, u64 isc_mask, u32 schid)
1488{
1489 unsigned long active_mask;
1490 int isc;
1491
1492 if (schid)
1493 goto out;
1494 if (!kvm->arch.gisa)
1495 goto out;
1496
1497 active_mask = (isc_mask & kvm_s390_gisa_get_ipm(kvm->arch.gisa) << 24) << 32;
1498 while (active_mask) {
1499 isc = __fls(active_mask) ^ (BITS_PER_LONG - 1);
1500 if (kvm_s390_gisa_tac_ipm_gisc(kvm->arch.gisa, isc))
1501 return isc;
1502 clear_bit_inv(isc, &active_mask);
1503 }
1504out:
1505 return -EINVAL;
1506}
1507
1474/* 1508/*
1475 * Dequeue and return an I/O interrupt matching any of the interruption 1509 * Dequeue and return an I/O interrupt matching any of the interruption
1476 * subclasses as designated by the isc mask in cr6 and the schid (if != 0). 1510 * subclasses as designated by the isc mask in cr6 and the schid (if != 0).
1511 * Take into account the interrupts pending in the interrupt list and in GISA.
1512 *
1513 * Note that for a guest that does not enable I/O interrupts
1514 * but relies on TPI, a flood of classic interrupts may starve
1515 * out adapter interrupts on the same isc. Linux does not do
1516 * that, and it is possible to work around the issue by configuring
1517 * different iscs for classic and adapter interrupts in the guest,
1518 * but we may want to revisit this in the future.
1477 */ 1519 */
1478struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm, 1520struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm,
1479 u64 isc_mask, u32 schid) 1521 u64 isc_mask, u32 schid)
1480{ 1522{
1481 struct kvm_s390_interrupt_info *inti = NULL; 1523 struct kvm_s390_interrupt_info *inti, *tmp_inti;
1482 int isc; 1524 int isc;
1483 1525
1484 for (isc = 0; isc <= MAX_ISC && !inti; isc++) { 1526 inti = get_top_io_int(kvm, isc_mask, schid);
1485 if (isc_mask & isc_to_isc_bits(isc)) 1527
1486 inti = get_io_int(kvm, isc, schid); 1528 isc = get_top_gisa_isc(kvm, isc_mask, schid);
1529 if (isc < 0)
1530 /* no AI in GISA */
1531 goto out;
1532
1533 if (!inti)
1534 /* AI in GISA but no classical IO int */
1535 goto gisa_out;
1536
1537 /* both types of interrupts present */
1538 if (int_word_to_isc(inti->io.io_int_word) <= isc) {
1539 /* classical IO int with higher priority */
1540 kvm_s390_gisa_set_ipm_gisc(kvm->arch.gisa, isc);
1541 goto out;
1487 } 1542 }
1543gisa_out:
1544 tmp_inti = kzalloc(sizeof(*inti), GFP_KERNEL);
1545 if (tmp_inti) {
1546 tmp_inti->type = KVM_S390_INT_IO(1, 0, 0, 0);
1547 tmp_inti->io.io_int_word = isc_to_int_word(isc);
1548 if (inti)
1549 kvm_s390_reinject_io_int(kvm, inti);
1550 inti = tmp_inti;
1551 } else
1552 kvm_s390_gisa_set_ipm_gisc(kvm->arch.gisa, isc);
1553out:
1488 return inti; 1554 return inti;
1489} 1555}
1490 1556