diff options
Diffstat (limited to 'arch/powerpc/kvm/mpic.c')
-rw-r--r-- | arch/powerpc/kvm/mpic.c | 111 |
1 files changed, 110 insertions, 1 deletions
diff --git a/arch/powerpc/kvm/mpic.c b/arch/powerpc/kvm/mpic.c index 10bc08a246fd..89fe1d66a7fb 100644 --- a/arch/powerpc/kvm/mpic.c +++ b/arch/powerpc/kvm/mpic.c | |||
@@ -1076,7 +1076,9 @@ static int openpic_cpu_write_internal(void *opaque, gpa_t addr, | |||
1076 | case 0xA0: /* IACK */ | 1076 | case 0xA0: /* IACK */ |
1077 | /* Read-only register */ | 1077 | /* Read-only register */ |
1078 | break; | 1078 | break; |
1079 | case 0xB0: /* EOI */ | 1079 | case 0xB0: { /* EOI */ |
1080 | int notify_eoi; | ||
1081 | |||
1080 | pr_debug("EOI\n"); | 1082 | pr_debug("EOI\n"); |
1081 | s_IRQ = IRQ_get_next(opp, &dst->servicing); | 1083 | s_IRQ = IRQ_get_next(opp, &dst->servicing); |
1082 | 1084 | ||
@@ -1087,6 +1089,8 @@ static int openpic_cpu_write_internal(void *opaque, gpa_t addr, | |||
1087 | } | 1089 | } |
1088 | 1090 | ||
1089 | IRQ_resetbit(&dst->servicing, s_IRQ); | 1091 | IRQ_resetbit(&dst->servicing, s_IRQ); |
1092 | /* Notify listeners that the IRQ is over */ | ||
1093 | notify_eoi = s_IRQ; | ||
1090 | /* Set up next servicing IRQ */ | 1094 | /* Set up next servicing IRQ */ |
1091 | s_IRQ = IRQ_get_next(opp, &dst->servicing); | 1095 | s_IRQ = IRQ_get_next(opp, &dst->servicing); |
1092 | /* Check queued interrupts. */ | 1096 | /* Check queued interrupts. */ |
@@ -1099,7 +1103,13 @@ static int openpic_cpu_write_internal(void *opaque, gpa_t addr, | |||
1099 | idx, n_IRQ); | 1103 | idx, n_IRQ); |
1100 | mpic_irq_raise(opp, dst, ILR_INTTGT_INT); | 1104 | mpic_irq_raise(opp, dst, ILR_INTTGT_INT); |
1101 | } | 1105 | } |
1106 | |||
1107 | spin_unlock(&opp->lock); | ||
1108 | kvm_notify_acked_irq(opp->kvm, 0, notify_eoi); | ||
1109 | spin_lock(&opp->lock); | ||
1110 | |||
1102 | break; | 1111 | break; |
1112 | } | ||
1103 | default: | 1113 | default: |
1104 | break; | 1114 | break; |
1105 | } | 1115 | } |
@@ -1639,14 +1649,34 @@ static void mpic_destroy(struct kvm_device *dev) | |||
1639 | unmap_mmio(opp); | 1649 | unmap_mmio(opp); |
1640 | } | 1650 | } |
1641 | 1651 | ||
1652 | dev->kvm->arch.mpic = NULL; | ||
1642 | kfree(opp); | 1653 | kfree(opp); |
1643 | } | 1654 | } |
1644 | 1655 | ||
1656 | static int mpic_set_default_irq_routing(struct openpic *opp) | ||
1657 | { | ||
1658 | struct kvm_irq_routing_entry *routing; | ||
1659 | |||
1660 | /* Create a nop default map, so that dereferencing it still works */ | ||
1661 | routing = kzalloc((sizeof(*routing)), GFP_KERNEL); | ||
1662 | if (!routing) | ||
1663 | return -ENOMEM; | ||
1664 | |||
1665 | kvm_set_irq_routing(opp->kvm, routing, 0, 0); | ||
1666 | |||
1667 | kfree(routing); | ||
1668 | return 0; | ||
1669 | } | ||
1670 | |||
1645 | static int mpic_create(struct kvm_device *dev, u32 type) | 1671 | static int mpic_create(struct kvm_device *dev, u32 type) |
1646 | { | 1672 | { |
1647 | struct openpic *opp; | 1673 | struct openpic *opp; |
1648 | int ret; | 1674 | int ret; |
1649 | 1675 | ||
1676 | /* We only support one MPIC at a time for now */ | ||
1677 | if (dev->kvm->arch.mpic) | ||
1678 | return -EINVAL; | ||
1679 | |||
1650 | opp = kzalloc(sizeof(struct openpic), GFP_KERNEL); | 1680 | opp = kzalloc(sizeof(struct openpic), GFP_KERNEL); |
1651 | if (!opp) | 1681 | if (!opp) |
1652 | return -ENOMEM; | 1682 | return -ENOMEM; |
@@ -1691,7 +1721,15 @@ static int mpic_create(struct kvm_device *dev, u32 type) | |||
1691 | goto err; | 1721 | goto err; |
1692 | } | 1722 | } |
1693 | 1723 | ||
1724 | ret = mpic_set_default_irq_routing(opp); | ||
1725 | if (ret) | ||
1726 | goto err; | ||
1727 | |||
1694 | openpic_reset(opp); | 1728 | openpic_reset(opp); |
1729 | |||
1730 | smp_wmb(); | ||
1731 | dev->kvm->arch.mpic = opp; | ||
1732 | |||
1695 | return 0; | 1733 | return 0; |
1696 | 1734 | ||
1697 | err: | 1735 | err: |
@@ -1761,3 +1799,74 @@ void kvmppc_mpic_disconnect_vcpu(struct openpic *opp, struct kvm_vcpu *vcpu) | |||
1761 | opp->dst[vcpu->arch.irq_cpu_id].vcpu = NULL; | 1799 | opp->dst[vcpu->arch.irq_cpu_id].vcpu = NULL; |
1762 | kvm_device_put(opp->dev); | 1800 | kvm_device_put(opp->dev); |
1763 | } | 1801 | } |
1802 | |||
1803 | /* | ||
1804 | * Return value: | ||
1805 | * < 0 Interrupt was ignored (masked or not delivered for other reasons) | ||
1806 | * = 0 Interrupt was coalesced (previous irq is still pending) | ||
1807 | * > 0 Number of CPUs interrupt was delivered to | ||
1808 | */ | ||
1809 | static int mpic_set_irq(struct kvm_kernel_irq_routing_entry *e, | ||
1810 | struct kvm *kvm, int irq_source_id, int level, | ||
1811 | bool line_status) | ||
1812 | { | ||
1813 | u32 irq = e->irqchip.pin; | ||
1814 | struct openpic *opp = kvm->arch.mpic; | ||
1815 | unsigned long flags; | ||
1816 | |||
1817 | spin_lock_irqsave(&opp->lock, flags); | ||
1818 | openpic_set_irq(opp, irq, level); | ||
1819 | spin_unlock_irqrestore(&opp->lock, flags); | ||
1820 | |||
1821 | /* All code paths we care about don't check for the return value */ | ||
1822 | return 0; | ||
1823 | } | ||
1824 | |||
1825 | int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, | ||
1826 | struct kvm *kvm, int irq_source_id, int level, bool line_status) | ||
1827 | { | ||
1828 | struct openpic *opp = kvm->arch.mpic; | ||
1829 | unsigned long flags; | ||
1830 | |||
1831 | spin_lock_irqsave(&opp->lock, flags); | ||
1832 | |||
1833 | /* | ||
1834 | * XXX We ignore the target address for now, as we only support | ||
1835 | * a single MSI bank. | ||
1836 | */ | ||
1837 | openpic_msi_write(kvm->arch.mpic, MSIIR_OFFSET, e->msi.data); | ||
1838 | spin_unlock_irqrestore(&opp->lock, flags); | ||
1839 | |||
1840 | /* All code paths we care about don't check for the return value */ | ||
1841 | return 0; | ||
1842 | } | ||
1843 | |||
1844 | int kvm_set_routing_entry(struct kvm_irq_routing_table *rt, | ||
1845 | struct kvm_kernel_irq_routing_entry *e, | ||
1846 | const struct kvm_irq_routing_entry *ue) | ||
1847 | { | ||
1848 | int r = -EINVAL; | ||
1849 | |||
1850 | switch (ue->type) { | ||
1851 | case KVM_IRQ_ROUTING_IRQCHIP: | ||
1852 | e->set = mpic_set_irq; | ||
1853 | e->irqchip.irqchip = ue->u.irqchip.irqchip; | ||
1854 | e->irqchip.pin = ue->u.irqchip.pin; | ||
1855 | if (e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS) | ||
1856 | goto out; | ||
1857 | rt->chip[ue->u.irqchip.irqchip][e->irqchip.pin] = ue->gsi; | ||
1858 | break; | ||
1859 | case KVM_IRQ_ROUTING_MSI: | ||
1860 | e->set = kvm_set_msi; | ||
1861 | e->msi.address_lo = ue->u.msi.address_lo; | ||
1862 | e->msi.address_hi = ue->u.msi.address_hi; | ||
1863 | e->msi.data = ue->u.msi.data; | ||
1864 | break; | ||
1865 | default: | ||
1866 | goto out; | ||
1867 | } | ||
1868 | |||
1869 | r = 0; | ||
1870 | out: | ||
1871 | return r; | ||
1872 | } | ||