aboutsummaryrefslogtreecommitdiffstats
path: root/virt/kvm/arm
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2015-07-24 06:30:43 -0400
committerMarc Zyngier <marc.zyngier@arm.com>2015-08-12 06:28:26 -0400
commit773299a570725d1f253d6046cd6475209b0dcd55 (patch)
treea9d54841a4a92de76dad049bea4db351e7d35f5a /virt/kvm/arm
parent6e84e0e0677281b4e7fc634c7e9d085fbcf41b10 (diff)
KVM: arm/arm64: vgic: Prevent userspace injection of a mapped interrupt
Virtual interrupts mapped to a HW interrupt should only be triggered from inside the kernel. Otherwise, you could end up confusing the kernel (and the GIC's) state machine. Rearrange the injection path so that kvm_vgic_inject_irq is used for non-mapped interrupts, and kvm_vgic_inject_mapped_irq is used for mapped interrupts. The latter should only be called from inside the kernel (timer, irqfd). Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'virt/kvm/arm')
-rw-r--r--virt/kvm/arm/vgic.c103
1 files changed, 70 insertions, 33 deletions
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index b553a8fa6430..9eb489a2c94c 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1555,7 +1555,8 @@ static int vgic_validate_injection(struct kvm_vcpu *vcpu, int irq, int level)
1555} 1555}
1556 1556
1557static int vgic_update_irq_pending(struct kvm *kvm, int cpuid, 1557static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
1558 unsigned int irq_num, bool level) 1558 struct irq_phys_map *map,
1559 unsigned int irq_num, bool level)
1559{ 1560{
1560 struct vgic_dist *dist = &kvm->arch.vgic; 1561 struct vgic_dist *dist = &kvm->arch.vgic;
1561 struct kvm_vcpu *vcpu; 1562 struct kvm_vcpu *vcpu;
@@ -1563,6 +1564,9 @@ static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
1563 int enabled; 1564 int enabled;
1564 bool ret = true, can_inject = true; 1565 bool ret = true, can_inject = true;
1565 1566
1567 if (irq_num >= min(kvm->arch.vgic.nr_irqs, 1020))
1568 return -EINVAL;
1569
1566 spin_lock(&dist->lock); 1570 spin_lock(&dist->lock);
1567 1571
1568 vcpu = kvm_get_vcpu(kvm, cpuid); 1572 vcpu = kvm_get_vcpu(kvm, cpuid);
@@ -1625,18 +1629,46 @@ static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
1625out: 1629out:
1626 spin_unlock(&dist->lock); 1630 spin_unlock(&dist->lock);
1627 1631
1628 return ret ? cpuid : -EINVAL; 1632 if (ret) {
1633 /* kick the specified vcpu */
1634 kvm_vcpu_kick(kvm_get_vcpu(kvm, cpuid));
1635 }
1636
1637 return 0;
1638}
1639
1640static int vgic_lazy_init(struct kvm *kvm)
1641{
1642 int ret = 0;
1643
1644 if (unlikely(!vgic_initialized(kvm))) {
1645 /*
1646 * We only provide the automatic initialization of the VGIC
1647 * for the legacy case of a GICv2. Any other type must
1648 * be explicitly initialized once setup with the respective
1649 * KVM device call.
1650 */
1651 if (kvm->arch.vgic.vgic_model != KVM_DEV_TYPE_ARM_VGIC_V2)
1652 return -EBUSY;
1653
1654 mutex_lock(&kvm->lock);
1655 ret = vgic_init(kvm);
1656 mutex_unlock(&kvm->lock);
1657 }
1658
1659 return ret;
1629} 1660}
1630 1661
1631/** 1662/**
1632 * kvm_vgic_inject_irq - Inject an IRQ from a device to the vgic 1663 * kvm_vgic_inject_irq - Inject an IRQ from a device to the vgic
1633 * @kvm: The VM structure pointer 1664 * @kvm: The VM structure pointer
1634 * @cpuid: The CPU for PPIs 1665 * @cpuid: The CPU for PPIs
1635 * @irq_num: The IRQ number that is assigned to the device 1666 * @irq_num: The IRQ number that is assigned to the device. This IRQ
1667 * must not be mapped to a HW interrupt.
1636 * @level: Edge-triggered: true: to trigger the interrupt 1668 * @level: Edge-triggered: true: to trigger the interrupt
1637 * false: to ignore the call 1669 * false: to ignore the call
1638 * Level-sensitive true: activates an interrupt 1670 * Level-sensitive true: raise the input signal
1639 * false: deactivates an interrupt 1671 * false: lower the input signal
1640 * 1672 *
1641 * The GIC is not concerned with devices being active-LOW or active-HIGH for 1673 * The GIC is not concerned with devices being active-LOW or active-HIGH for
1642 * level-sensitive interrupts. You can think of the level parameter as 1 1674 * level-sensitive interrupts. You can think of the level parameter as 1
@@ -1645,39 +1677,44 @@ out:
1645int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num, 1677int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
1646 bool level) 1678 bool level)
1647{ 1679{
1648 int ret = 0; 1680 struct irq_phys_map *map;
1649 int vcpu_id; 1681 int ret;
1650
1651 if (unlikely(!vgic_initialized(kvm))) {
1652 /*
1653 * We only provide the automatic initialization of the VGIC
1654 * for the legacy case of a GICv2. Any other type must
1655 * be explicitly initialized once setup with the respective
1656 * KVM device call.
1657 */
1658 if (kvm->arch.vgic.vgic_model != KVM_DEV_TYPE_ARM_VGIC_V2) {
1659 ret = -EBUSY;
1660 goto out;
1661 }
1662 mutex_lock(&kvm->lock);
1663 ret = vgic_init(kvm);
1664 mutex_unlock(&kvm->lock);
1665 1682
1666 if (ret) 1683 ret = vgic_lazy_init(kvm);
1667 goto out; 1684 if (ret)
1668 } 1685 return ret;
1669 1686
1670 if (irq_num >= min(kvm->arch.vgic.nr_irqs, 1020)) 1687 map = vgic_irq_map_search(kvm_get_vcpu(kvm, cpuid), irq_num);
1688 if (map)
1671 return -EINVAL; 1689 return -EINVAL;
1672 1690
1673 vcpu_id = vgic_update_irq_pending(kvm, cpuid, irq_num, level); 1691 return vgic_update_irq_pending(kvm, cpuid, NULL, irq_num, level);
1674 if (vcpu_id >= 0) { 1692}
1675 /* kick the specified vcpu */
1676 kvm_vcpu_kick(kvm_get_vcpu(kvm, vcpu_id));
1677 }
1678 1693
1679out: 1694/**
1680 return ret; 1695 * kvm_vgic_inject_mapped_irq - Inject a physically mapped IRQ to the vgic
1696 * @kvm: The VM structure pointer
1697 * @cpuid: The CPU for PPIs
1698 * @map: Pointer to a irq_phys_map structure describing the mapping
1699 * @level: Edge-triggered: true: to trigger the interrupt
1700 * false: to ignore the call
1701 * Level-sensitive true: raise the input signal
1702 * false: lower the input signal
1703 *
1704 * The GIC is not concerned with devices being active-LOW or active-HIGH for
1705 * level-sensitive interrupts. You can think of the level parameter as 1
1706 * being HIGH and 0 being LOW and all devices being active-HIGH.
1707 */
1708int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
1709 struct irq_phys_map *map, bool level)
1710{
1711 int ret;
1712
1713 ret = vgic_lazy_init(kvm);
1714 if (ret)
1715 return ret;
1716
1717 return vgic_update_irq_pending(kvm, cpuid, map, map->virt_irq, level);
1681} 1718}
1682 1719
1683static irqreturn_t vgic_maintenance_handler(int irq, void *data) 1720static irqreturn_t vgic_maintenance_handler(int irq, void *data)