Commit 995a0ee9 authored by Eric Auger's avatar Eric Auger Committed by Marc Zyngier

KVM: arm/arm64: Enable MSI routing

Up to now, only irqchip routing entries could be set. This patch
adds the capability to insert MSI routing entries.

For ARM64, let's also increase KVM_MAX_IRQ_ROUTES to 4096: this
include SPI irqchip routes plus MSI routes. In the future this
might be extended.
Signed-off-by: default avatarEric Auger <eric.auger@redhat.com>
Reviewed-by: default avatarAndre Przywara <andre.przywara@arm.com>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
parent 180ae7b1
...@@ -2381,6 +2381,9 @@ On arm/arm64, gsi routing being supported, the following can happen: ...@@ -2381,6 +2381,9 @@ On arm/arm64, gsi routing being supported, the following can happen:
- in case no routing entry is associated to this gsi, injection fails - in case no routing entry is associated to this gsi, injection fails
- in case the gsi is associated to an irqchip routing entry, - in case the gsi is associated to an irqchip routing entry,
irqchip.pin + 32 corresponds to the injected SPI ID. irqchip.pin + 32 corresponds to the injected SPI ID.
- in case the gsi is associated to an MSI routing entry, the MSI
message and device ID are translated into an LPI (support restricted
to GICv3 ITS in-kernel emulation).
4.76 KVM_PPC_ALLOCATE_HTAB 4.76 KVM_PPC_ALLOCATE_HTAB
......
...@@ -1048,6 +1048,8 @@ static inline int mmu_notifier_retry(struct kvm *kvm, unsigned long mmu_seq) ...@@ -1048,6 +1048,8 @@ static inline int mmu_notifier_retry(struct kvm *kvm, unsigned long mmu_seq)
#ifdef CONFIG_S390 #ifdef CONFIG_S390
#define KVM_MAX_IRQ_ROUTES 4096 //FIXME: we can have more than that... #define KVM_MAX_IRQ_ROUTES 4096 //FIXME: we can have more than that...
#elif defined(CONFIG_ARM64)
#define KVM_MAX_IRQ_ROUTES 4096
#else #else
#define KVM_MAX_IRQ_ROUTES 1024 #define KVM_MAX_IRQ_ROUTES 1024
#endif #endif
......
...@@ -59,6 +59,14 @@ int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e, ...@@ -59,6 +59,14 @@ int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
(e->irqchip.irqchip >= KVM_NR_IRQCHIPS)) (e->irqchip.irqchip >= KVM_NR_IRQCHIPS))
goto out; goto out;
break; break;
case KVM_IRQ_ROUTING_MSI:
e->set = kvm_set_msi;
e->msi.address_lo = ue->u.msi.address_lo;
e->msi.address_hi = ue->u.msi.address_hi;
e->msi.data = ue->u.msi.data;
e->msi.flags = ue->flags;
e->msi.devid = ue->u.msi.devid;
break;
default: default:
goto out; goto out;
} }
......
...@@ -178,6 +178,7 @@ int kvm_set_irq_routing(struct kvm *kvm, ...@@ -178,6 +178,7 @@ int kvm_set_irq_routing(struct kvm *kvm,
unsigned flags) unsigned flags)
{ {
struct kvm_irq_routing_table *new, *old; struct kvm_irq_routing_table *new, *old;
struct kvm_kernel_irq_routing_entry *e;
u32 i, j, nr_rt_entries = 0; u32 i, j, nr_rt_entries = 0;
int r; int r;
...@@ -201,23 +202,25 @@ int kvm_set_irq_routing(struct kvm *kvm, ...@@ -201,23 +202,25 @@ int kvm_set_irq_routing(struct kvm *kvm,
new->chip[i][j] = -1; new->chip[i][j] = -1;
for (i = 0; i < nr; ++i) { for (i = 0; i < nr; ++i) {
struct kvm_kernel_irq_routing_entry *e;
r = -ENOMEM; r = -ENOMEM;
e = kzalloc(sizeof(*e), GFP_KERNEL); e = kzalloc(sizeof(*e), GFP_KERNEL);
if (!e) if (!e)
goto out; goto out;
r = -EINVAL; r = -EINVAL;
if (ue->flags) { switch (ue->type) {
kfree(e); case KVM_IRQ_ROUTING_MSI:
goto out; if (ue->flags & ~KVM_MSI_VALID_DEVID)
goto free_entry;
break;
default:
if (ue->flags)
goto free_entry;
break;
} }
r = setup_routing_entry(new, e, ue); r = setup_routing_entry(new, e, ue);
if (r) { if (r)
kfree(e); goto free_entry;
goto out;
}
++ue; ++ue;
} }
...@@ -234,7 +237,10 @@ int kvm_set_irq_routing(struct kvm *kvm, ...@@ -234,7 +237,10 @@ int kvm_set_irq_routing(struct kvm *kvm,
new = old; new = old;
r = 0; r = 0;
goto out;
free_entry:
kfree(e);
out: out:
free_irq_routing_table(new); free_irq_routing_table(new);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment