aboutsummaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/arm/vgic.c178
1 files changed, 178 insertions, 0 deletions
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index e2596f618281..88599b585362 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -589,6 +589,20 @@ static bool handle_mmio_sgi_reg(struct kvm_vcpu *vcpu,
589 return false; 589 return false;
590} 590}
591 591
592static bool handle_mmio_sgi_clear(struct kvm_vcpu *vcpu,
593 struct kvm_exit_mmio *mmio,
594 phys_addr_t offset)
595{
596 return false;
597}
598
599static bool handle_mmio_sgi_set(struct kvm_vcpu *vcpu,
600 struct kvm_exit_mmio *mmio,
601 phys_addr_t offset)
602{
603 return false;
604}
605
592/* 606/*
593 * I would have liked to use the kvm_bus_io_*() API instead, but it 607 * I would have liked to use the kvm_bus_io_*() API instead, but it
594 * cannot cope with banked registers (only the VM pointer is passed 608 * cannot cope with banked registers (only the VM pointer is passed
@@ -663,6 +677,16 @@ static const struct mmio_range vgic_dist_ranges[] = {
663 .len = 4, 677 .len = 4,
664 .handle_mmio = handle_mmio_sgi_reg, 678 .handle_mmio = handle_mmio_sgi_reg,
665 }, 679 },
680 {
681 .base = GIC_DIST_SGI_PENDING_CLEAR,
682 .len = VGIC_NR_SGIS,
683 .handle_mmio = handle_mmio_sgi_clear,
684 },
685 {
686 .base = GIC_DIST_SGI_PENDING_SET,
687 .len = VGIC_NR_SGIS,
688 .handle_mmio = handle_mmio_sgi_set,
689 },
666 {} 690 {}
667}; 691};
668 692
@@ -1557,6 +1581,114 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
1557 return r; 1581 return r;
1558} 1582}
1559 1583
1584static bool handle_cpu_mmio_misc(struct kvm_vcpu *vcpu,
1585 struct kvm_exit_mmio *mmio, phys_addr_t offset)
1586{
1587 return true;
1588}
1589
1590static const struct mmio_range vgic_cpu_ranges[] = {
1591 {
1592 .base = GIC_CPU_CTRL,
1593 .len = 12,
1594 .handle_mmio = handle_cpu_mmio_misc,
1595 },
1596 {
1597 .base = GIC_CPU_ALIAS_BINPOINT,
1598 .len = 4,
1599 .handle_mmio = handle_cpu_mmio_misc,
1600 },
1601 {
1602 .base = GIC_CPU_ACTIVEPRIO,
1603 .len = 16,
1604 .handle_mmio = handle_cpu_mmio_misc,
1605 },
1606 {
1607 .base = GIC_CPU_IDENT,
1608 .len = 4,
1609 .handle_mmio = handle_cpu_mmio_misc,
1610 },
1611};
1612
1613static int vgic_attr_regs_access(struct kvm_device *dev,
1614 struct kvm_device_attr *attr,
1615 u32 *reg, bool is_write)
1616{
1617 const struct mmio_range *r = NULL, *ranges;
1618 phys_addr_t offset;
1619 int ret, cpuid, c;
1620 struct kvm_vcpu *vcpu, *tmp_vcpu;
1621 struct vgic_dist *vgic;
1622 struct kvm_exit_mmio mmio;
1623
1624 offset = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
1625 cpuid = (attr->attr & KVM_DEV_ARM_VGIC_CPUID_MASK) >>
1626 KVM_DEV_ARM_VGIC_CPUID_SHIFT;
1627
1628 mutex_lock(&dev->kvm->lock);
1629
1630 if (cpuid >= atomic_read(&dev->kvm->online_vcpus)) {
1631 ret = -EINVAL;
1632 goto out;
1633 }
1634
1635 vcpu = kvm_get_vcpu(dev->kvm, cpuid);
1636 vgic = &dev->kvm->arch.vgic;
1637
1638 mmio.len = 4;
1639 mmio.is_write = is_write;
1640 if (is_write)
1641 mmio_data_write(&mmio, ~0, *reg);
1642 switch (attr->group) {
1643 case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
1644 mmio.phys_addr = vgic->vgic_dist_base + offset;
1645 ranges = vgic_dist_ranges;
1646 break;
1647 case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
1648 mmio.phys_addr = vgic->vgic_cpu_base + offset;
1649 ranges = vgic_cpu_ranges;
1650 break;
1651 default:
1652 BUG();
1653 }
1654 r = find_matching_range(ranges, &mmio, offset);
1655
1656 if (unlikely(!r || !r->handle_mmio)) {
1657 ret = -ENXIO;
1658 goto out;
1659 }
1660
1661
1662 spin_lock(&vgic->lock);
1663
1664 /*
1665 * Ensure that no other VCPU is running by checking the vcpu->cpu
1666 * field. If no other VPCUs are running we can safely access the VGIC
1667 * state, because even if another VPU is run after this point, that
1668 * VCPU will not touch the vgic state, because it will block on
1669 * getting the vgic->lock in kvm_vgic_sync_hwstate().
1670 */
1671 kvm_for_each_vcpu(c, tmp_vcpu, dev->kvm) {
1672 if (unlikely(tmp_vcpu->cpu != -1)) {
1673 ret = -EBUSY;
1674 goto out_vgic_unlock;
1675 }
1676 }
1677
1678 offset -= r->base;
1679 r->handle_mmio(vcpu, &mmio, offset);
1680
1681 if (!is_write)
1682 *reg = mmio_data_read(&mmio, ~0);
1683
1684 ret = 0;
1685out_vgic_unlock:
1686 spin_unlock(&vgic->lock);
1687out:
1688 mutex_unlock(&dev->kvm->lock);
1689 return ret;
1690}
1691
1560static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) 1692static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
1561{ 1693{
1562 int r; 1694 int r;
@@ -1573,6 +1705,18 @@ static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
1573 r = kvm_vgic_addr(dev->kvm, type, &addr, true); 1705 r = kvm_vgic_addr(dev->kvm, type, &addr, true);
1574 return (r == -ENODEV) ? -ENXIO : r; 1706 return (r == -ENODEV) ? -ENXIO : r;
1575 } 1707 }
1708
1709 case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
1710 case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
1711 u32 __user *uaddr = (u32 __user *)(long)attr->addr;
1712 u32 reg;
1713
1714 if (get_user(reg, uaddr))
1715 return -EFAULT;
1716
1717 return vgic_attr_regs_access(dev, attr, &reg, true);
1718 }
1719
1576 } 1720 }
1577 1721
1578 return -ENXIO; 1722 return -ENXIO;
@@ -1594,14 +1738,42 @@ static int vgic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
1594 1738
1595 if (copy_to_user(uaddr, &addr, sizeof(addr))) 1739 if (copy_to_user(uaddr, &addr, sizeof(addr)))
1596 return -EFAULT; 1740 return -EFAULT;
1741 break;
1742 }
1743
1744 case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
1745 case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
1746 u32 __user *uaddr = (u32 __user *)(long)attr->addr;
1747 u32 reg = 0;
1748
1749 r = vgic_attr_regs_access(dev, attr, &reg, false);
1750 if (r)
1751 return r;
1752 r = put_user(reg, uaddr);
1753 break;
1597 } 1754 }
1755
1598 } 1756 }
1599 1757
1600 return r; 1758 return r;
1601} 1759}
1602 1760
1761static int vgic_has_attr_regs(const struct mmio_range *ranges,
1762 phys_addr_t offset)
1763{
1764 struct kvm_exit_mmio dev_attr_mmio;
1765
1766 dev_attr_mmio.len = 4;
1767 if (find_matching_range(ranges, &dev_attr_mmio, offset))
1768 return 0;
1769 else
1770 return -ENXIO;
1771}
1772
1603static int vgic_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr) 1773static int vgic_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
1604{ 1774{
1775 phys_addr_t offset;
1776
1605 switch (attr->group) { 1777 switch (attr->group) {
1606 case KVM_DEV_ARM_VGIC_GRP_ADDR: 1778 case KVM_DEV_ARM_VGIC_GRP_ADDR:
1607 switch (attr->attr) { 1779 switch (attr->attr) {
@@ -1610,6 +1782,12 @@ static int vgic_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
1610 return 0; 1782 return 0;
1611 } 1783 }
1612 break; 1784 break;
1785 case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
1786 offset = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
1787 return vgic_has_attr_regs(vgic_dist_ranges, offset);
1788 case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
1789 offset = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
1790 return vgic_has_attr_regs(vgic_cpu_ranges, offset);
1613 } 1791 }
1614 return -ENXIO; 1792 return -ENXIO;
1615} 1793}