* [PULL 1/8] KVM: api: Pass the devid in the msi routing entry
2016-08-04 11:40 [PULL 0/8] KVM/ARM Changes for v4.8 - Take #2 Christoffer Dall
@ 2016-08-04 11:40 ` Christoffer Dall
2016-08-04 11:40 ` [PULL 2/8] KVM: Add devid in kvm_kernel_irq_routing_entry Christoffer Dall
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Christoffer Dall @ 2016-08-04 11:40 UTC (permalink / raw)
To: linux-arm-kernel
From: Eric Auger <eric.auger@redhat.com>
On ARM, the MSI msg (address and data) comes along with
out-of-band device ID information. The device ID encodes the
device that writes the MSI msg. Let's convey the device id in
kvm_irq_routing_msi and use KVM_MSI_VALID_DEVID flag value in
kvm_irq_routing_entry to indicate the msi devid is populated.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Acked-by: Radim Kr?m?? <rkrcmar@redhat.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
Documentation/virtual/kvm/api.txt | 19 +++++++++++++++++--
include/uapi/linux/kvm.h | 5 ++++-
2 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 07049ea..415cde1 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1468,7 +1468,11 @@ struct kvm_irq_routing_entry {
#define KVM_IRQ_ROUTING_S390_ADAPTER 3
#define KVM_IRQ_ROUTING_HV_SINT 4
-No flags are specified so far, the corresponding field must be set to zero.
+flags:
+- KVM_MSI_VALID_DEVID: used along with KVM_IRQ_ROUTING_MSI
+ routing entry type, specifies that the devid field contains
+ a valid value.
+- zero otherwise
struct kvm_irq_routing_irqchip {
__u32 irqchip;
@@ -1479,9 +1483,20 @@ struct kvm_irq_routing_msi {
__u32 address_lo;
__u32 address_hi;
__u32 data;
- __u32 pad;
+ union {
+ __u32 pad;
+ __u32 devid;
+ };
};
+devid: If KVM_MSI_VALID_DEVID is set, contains a unique device identifier
+ for the device that wrote the MSI message.
+ For PCI, this is usually a BFD identifier in the lower 16 bits.
+
+The per-VM KVM_CAP_MSI_DEVID capability advertises the requirement to
+provide the device ID. If this capability is not set, userland cannot
+rely on the kernel to allow the KVM_MSI_VALID_DEVID flag being set.
+
struct kvm_irq_routing_s390_adapter {
__u64 ind_addr;
__u64 summary_addr;
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index d8c4c32..eb22208 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -879,7 +879,10 @@ struct kvm_irq_routing_msi {
__u32 address_lo;
__u32 address_hi;
__u32 data;
- __u32 pad;
+ union {
+ __u32 pad;
+ __u32 devid;
+ };
};
struct kvm_irq_routing_s390_adapter {
--
1.9.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PULL 2/8] KVM: Add devid in kvm_kernel_irq_routing_entry
2016-08-04 11:40 [PULL 0/8] KVM/ARM Changes for v4.8 - Take #2 Christoffer Dall
2016-08-04 11:40 ` [PULL 1/8] KVM: api: Pass the devid in the msi routing entry Christoffer Dall
@ 2016-08-04 11:40 ` Christoffer Dall
2016-08-04 11:40 ` [PULL 3/8] KVM: irqchip: Convey devid to kvm_set_msi Christoffer Dall
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Christoffer Dall @ 2016-08-04 11:40 UTC (permalink / raw)
To: linux-arm-kernel
From: Eric Auger <eric.auger@redhat.com>
Enhance kvm_kernel_irq_routing_entry to transport the device id
field, devid. A new flags field makes possible to indicate the
devid is valid. Those additions are used for ARM GICv3 ITS MSI
injection. The original struct msi_msg msi field is replaced by
a new custom structure that embeds the new fields.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Suggested-by: Radim Kr?m?? <rkrcmar@redhat.com>
Acked-by: Radim Kr?m?? <rkrcmar@redhat.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
include/linux/kvm_host.h | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 614a981..a15828f 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -317,7 +317,13 @@ struct kvm_kernel_irq_routing_entry {
unsigned irqchip;
unsigned pin;
} irqchip;
- struct msi_msg msi;
+ struct {
+ u32 address_lo;
+ u32 address_hi;
+ u32 data;
+ u32 flags;
+ u32 devid;
+ } msi;
struct kvm_s390_adapter_int adapter;
struct kvm_hv_sint hv_sint;
};
--
1.9.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PULL 3/8] KVM: irqchip: Convey devid to kvm_set_msi
2016-08-04 11:40 [PULL 0/8] KVM/ARM Changes for v4.8 - Take #2 Christoffer Dall
2016-08-04 11:40 ` [PULL 1/8] KVM: api: Pass the devid in the msi routing entry Christoffer Dall
2016-08-04 11:40 ` [PULL 2/8] KVM: Add devid in kvm_kernel_irq_routing_entry Christoffer Dall
@ 2016-08-04 11:40 ` Christoffer Dall
2016-08-04 11:40 ` [PULL 4/8] KVM: Move kvm_setup_default/empty_irq_routing declaration in arch specific header Christoffer Dall
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Christoffer Dall @ 2016-08-04 11:40 UTC (permalink / raw)
To: linux-arm-kernel
From: Eric Auger <eric.auger@redhat.com>
on ARM, a devid field is populated in kvm_msi struct in case the
flag is set to KVM_MSI_VALID_DEVID. Let's propagate both flags and
devid field in kvm_kernel_irq_routing_entry.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Acked-by: Christoffer Dall <christoffer.dall@linaro.org>
Acked-by: Radim Kr?m?? <rkrcmar@redhat.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
virt/kvm/irqchip.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c
index 8db197b..0c00054 100644
--- a/virt/kvm/irqchip.c
+++ b/virt/kvm/irqchip.c
@@ -62,12 +62,14 @@ int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi)
{
struct kvm_kernel_irq_routing_entry route;
- if (!irqchip_in_kernel(kvm) || msi->flags != 0)
+ if (!irqchip_in_kernel(kvm) || (msi->flags & ~KVM_MSI_VALID_DEVID))
return -EINVAL;
route.msi.address_lo = msi->address_lo;
route.msi.address_hi = msi->address_hi;
route.msi.data = msi->data;
+ route.msi.flags = msi->flags;
+ route.msi.devid = msi->devid;
return kvm_set_msi(&route, kvm, KVM_USERSPACE_IRQ_SOURCE_ID, 1, false);
}
--
1.9.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PULL 4/8] KVM: Move kvm_setup_default/empty_irq_routing declaration in arch specific header
2016-08-04 11:40 [PULL 0/8] KVM/ARM Changes for v4.8 - Take #2 Christoffer Dall
` (2 preceding siblings ...)
2016-08-04 11:40 ` [PULL 3/8] KVM: irqchip: Convey devid to kvm_set_msi Christoffer Dall
@ 2016-08-04 11:40 ` Christoffer Dall
2016-08-04 11:40 ` [PULL 5/8] KVM: arm/arm64: Enable irqchip routing Christoffer Dall
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Christoffer Dall @ 2016-08-04 11:40 UTC (permalink / raw)
To: linux-arm-kernel
From: Eric Auger <eric.auger@redhat.com>
kvm_setup_default_irq_routing and kvm_setup_empty_irq_routing are
not used by generic code. So let's move the declarations in x86 irq.h
header instead of kvm_host.h.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Suggested-by: Andre Przywara <andre.przywara@arm.com>
Acked-by: Radim Kr?m?? <rkrcmar@redhat.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/x86/kvm/irq.h | 3 +++
include/linux/kvm_host.h | 2 --
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h
index 61ebdc1..035731e 100644
--- a/arch/x86/kvm/irq.h
+++ b/arch/x86/kvm/irq.h
@@ -120,4 +120,7 @@ void __kvm_migrate_timers(struct kvm_vcpu *vcpu);
int apic_has_pending_timer(struct kvm_vcpu *vcpu);
+int kvm_setup_default_irq_routing(struct kvm *kvm);
+int kvm_setup_empty_irq_routing(struct kvm *kvm);
+
#endif
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index a15828f..a7eb5c4 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1052,8 +1052,6 @@ static inline int mmu_notifier_retry(struct kvm *kvm, unsigned long mmu_seq)
#define KVM_MAX_IRQ_ROUTES 1024
#endif
-int kvm_setup_default_irq_routing(struct kvm *kvm);
-int kvm_setup_empty_irq_routing(struct kvm *kvm);
int kvm_set_irq_routing(struct kvm *kvm,
const struct kvm_irq_routing_entry *entries,
unsigned nr,
--
1.9.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PULL 5/8] KVM: arm/arm64: Enable irqchip routing
2016-08-04 11:40 [PULL 0/8] KVM/ARM Changes for v4.8 - Take #2 Christoffer Dall
` (3 preceding siblings ...)
2016-08-04 11:40 ` [PULL 4/8] KVM: Move kvm_setup_default/empty_irq_routing declaration in arch specific header Christoffer Dall
@ 2016-08-04 11:40 ` Christoffer Dall
2016-08-04 11:40 ` [PULL 6/8] KVM: arm/arm64: Enable MSI routing Christoffer Dall
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Christoffer Dall @ 2016-08-04 11:40 UTC (permalink / raw)
To: linux-arm-kernel
From: Eric Auger <eric.auger@redhat.com>
This patch adds compilation and link against irqchip.
Main motivation behind using irqchip code is to enable MSI
routing code. In the future irqchip routing may also be useful
when targeting multiple irqchips.
Routing standard callbacks now are implemented in vgic-irqfd:
- kvm_set_routing_entry
- kvm_set_irq
- kvm_set_msi
They only are supported with new_vgic code.
Both HAVE_KVM_IRQCHIP and HAVE_KVM_IRQ_ROUTING are defined.
KVM_CAP_IRQ_ROUTING is advertised and KVM_SET_GSI_ROUTING is allowed.
So from now on IRQCHIP routing is enabled and a routing table entry
must exist for irqfd injection to succeed for a given SPI. This patch
builds a default flat irqchip routing table (gsi=irqchip.pin) covering
all the VGIC SPI indexes. This routing table is overwritten by the
first first user-space call to KVM_SET_GSI_ROUTING ioctl.
MSI routing setup is not yet allowed.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
Documentation/virtual/kvm/api.txt | 12 +++--
arch/arm/kvm/Kconfig | 2 +
arch/arm/kvm/Makefile | 1 +
arch/arm/kvm/irq.h | 19 ++++++++
arch/arm64/kvm/Kconfig | 2 +
arch/arm64/kvm/Makefile | 1 +
arch/arm64/kvm/irq.h | 19 ++++++++
include/kvm/arm_vgic.h | 7 +++
virt/kvm/arm/vgic/vgic-init.c | 4 ++
virt/kvm/arm/vgic/vgic-irqfd.c | 100 +++++++++++++++++++++++++++++++-------
virt/kvm/arm/vgic/vgic.c | 7 ---
11 files changed, 145 insertions(+), 29 deletions(-)
create mode 100644 arch/arm/kvm/irq.h
create mode 100644 arch/arm64/kvm/irq.h
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 415cde1..7e5f9af 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1433,13 +1433,16 @@ KVM_ASSIGN_DEV_IRQ. Partial deassignment of host or guest IRQ is allowed.
4.52 KVM_SET_GSI_ROUTING
Capability: KVM_CAP_IRQ_ROUTING
-Architectures: x86 s390
+Architectures: x86 s390 arm arm64
Type: vm ioctl
Parameters: struct kvm_irq_routing (in)
Returns: 0 on success, -1 on error
Sets the GSI routing table entries, overwriting any previously set entries.
+On arm/arm64, GSI routing has the following limitation:
+- GSI routing does not apply to KVM_IRQ_LINE but only to KVM_IRQFD.
+
struct kvm_irq_routing {
__u32 nr;
__u32 flags;
@@ -2374,9 +2377,10 @@ Note that closing the resamplefd is not sufficient to disable the
irqfd. The KVM_IRQFD_FLAG_RESAMPLE is only necessary on assignment
and need not be specified with KVM_IRQFD_FLAG_DEASSIGN.
-On ARM/ARM64, the gsi field in the kvm_irqfd struct specifies the Shared
-Peripheral Interrupt (SPI) index, such that the GIC interrupt ID is
-given by gsi + 32.
+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 the gsi is associated to an irqchip routing entry,
+ irqchip.pin + 32 corresponds to the injected SPI ID.
4.76 KVM_PPC_ALLOCATE_HTAB
diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 95a0005..3e1cd04 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -32,6 +32,8 @@ config KVM
select KVM_VFIO
select HAVE_KVM_EVENTFD
select HAVE_KVM_IRQFD
+ select HAVE_KVM_IRQCHIP
+ select HAVE_KVM_IRQ_ROUTING
depends on ARM_VIRT_EXT && ARM_LPAE && ARM_ARCH_TIMER
---help---
Support hosting virtualized guest machines.
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index 5e28df8..10d77a6 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -29,4 +29,5 @@ obj-y += $(KVM)/arm/vgic/vgic-v2.o
obj-y += $(KVM)/arm/vgic/vgic-mmio.o
obj-y += $(KVM)/arm/vgic/vgic-mmio-v2.o
obj-y += $(KVM)/arm/vgic/vgic-kvm-device.o
+obj-y += $(KVM)/irqchip.o
obj-y += $(KVM)/arm/arch_timer.o
diff --git a/arch/arm/kvm/irq.h b/arch/arm/kvm/irq.h
new file mode 100644
index 0000000..b74099b
--- /dev/null
+++ b/arch/arm/kvm/irq.h
@@ -0,0 +1,19 @@
+/*
+ * irq.h: in kernel interrupt controller related definitions
+ * Copyright (c) 2016 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This header is included by irqchip.c. However, on ARM, interrupt
+ * controller declarations are located in include/kvm/arm_vgic.h since
+ * they are mostly shared between arm and arm64.
+ */
+
+#ifndef __IRQ_H
+#define __IRQ_H
+
+#include <kvm/arm_vgic.h>
+
+#endif
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index 9d2eff0..9c9edc9 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -37,6 +37,8 @@ config KVM
select KVM_ARM_VGIC_V3
select KVM_ARM_PMU if HW_PERF_EVENTS
select HAVE_KVM_MSI
+ select HAVE_KVM_IRQCHIP
+ select HAVE_KVM_IRQ_ROUTING
---help---
Support hosting virtualized guest machines.
We don't support KVM with 16K page tables yet, due to the multiple
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index a5b9664..695eb3c 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -30,5 +30,6 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v2.o
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-kvm-device.o
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-its.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/irqchip.o
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
kvm-$(CONFIG_KVM_ARM_PMU) += $(KVM)/arm/pmu.o
diff --git a/arch/arm64/kvm/irq.h b/arch/arm64/kvm/irq.h
new file mode 100644
index 0000000..b74099b
--- /dev/null
+++ b/arch/arm64/kvm/irq.h
@@ -0,0 +1,19 @@
+/*
+ * irq.h: in kernel interrupt controller related definitions
+ * Copyright (c) 2016 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This header is included by irqchip.c. However, on ARM, interrupt
+ * controller declarations are located in include/kvm/arm_vgic.h since
+ * they are mostly shared between arm and arm64.
+ */
+
+#ifndef __IRQ_H
+#define __IRQ_H
+
+#include <kvm/arm_vgic.h>
+
+#endif
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 540da51..19b698e 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -34,6 +34,7 @@
#define VGIC_MAX_SPI 1019
#define VGIC_MAX_RESERVED 1023
#define VGIC_MIN_LPI 8192
+#define KVM_IRQCHIP_NUM_PINS (1020 - 32)
enum vgic_type {
VGIC_V2, /* Good ol' GICv2 */
@@ -314,4 +315,10 @@ static inline int kvm_vgic_get_max_vcpus(void)
int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi);
+/**
+ * kvm_vgic_setup_default_irq_routing:
+ * Setup a default flat gsi routing table mapping all SPIs
+ */
+int kvm_vgic_setup_default_irq_routing(struct kvm *kvm);
+
#endif /* __KVM_ARM_VGIC_H */
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 01a60dc..1aba785 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -264,6 +264,10 @@ int vgic_init(struct kvm *kvm)
kvm_for_each_vcpu(i, vcpu, kvm)
kvm_vgic_vcpu_init(vcpu);
+ ret = kvm_vgic_setup_default_irq_routing(kvm);
+ if (ret)
+ goto out;
+
dist->initialized = true;
out:
return ret;
diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c b/virt/kvm/arm/vgic/vgic-irqfd.c
index c675513..6e84d53 100644
--- a/virt/kvm/arm/vgic/vgic-irqfd.c
+++ b/virt/kvm/arm/vgic/vgic-irqfd.c
@@ -17,36 +17,100 @@
#include <linux/kvm.h>
#include <linux/kvm_host.h>
#include <trace/events/kvm.h>
+#include <kvm/arm_vgic.h>
+#include "vgic.h"
-int kvm_irq_map_gsi(struct kvm *kvm,
- struct kvm_kernel_irq_routing_entry *entries,
- int gsi)
+/**
+ * vgic_irqfd_set_irq: inject the IRQ corresponding to the
+ * irqchip routing entry
+ *
+ * This is the entry point for irqfd IRQ injection
+ */
+static int vgic_irqfd_set_irq(struct kvm_kernel_irq_routing_entry *e,
+ struct kvm *kvm, int irq_source_id,
+ int level, bool line_status)
{
- return 0;
+ unsigned int spi_id = e->irqchip.pin + VGIC_NR_PRIVATE_IRQS;
+
+ if (!vgic_valid_spi(kvm, spi_id))
+ return -EINVAL;
+ return kvm_vgic_inject_irq(kvm, 0, spi_id, level);
}
-int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned int irqchip,
- unsigned int pin)
+/**
+ * kvm_set_routing_entry: populate a kvm routing entry
+ * from a user routing entry
+ *
+ * @e: kvm kernel routing entry handle
+ * @ue: user api routing entry handle
+ * return 0 on success, -EINVAL on errors.
+ */
+int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
+ const struct kvm_irq_routing_entry *ue)
{
- return pin;
+ int r = -EINVAL;
+
+ switch (ue->type) {
+ case KVM_IRQ_ROUTING_IRQCHIP:
+ e->set = vgic_irqfd_set_irq;
+ e->irqchip.irqchip = ue->u.irqchip.irqchip;
+ e->irqchip.pin = ue->u.irqchip.pin;
+ if ((e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS) ||
+ (e->irqchip.irqchip >= KVM_NR_IRQCHIPS))
+ goto out;
+ break;
+ default:
+ goto out;
+ }
+ r = 0;
+out:
+ return r;
}
-int kvm_set_irq(struct kvm *kvm, int irq_source_id,
- u32 irq, int level, bool line_status)
+/**
+ * kvm_set_msi: inject the MSI corresponding to the
+ * MSI routing entry
+ *
+ * This is the entry point for irqfd MSI injection
+ * and userspace MSI injection.
+ */
+int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
+ struct kvm *kvm, int irq_source_id,
+ int level, bool line_status)
{
- unsigned int spi = irq + VGIC_NR_PRIVATE_IRQS;
+ struct kvm_msi msi;
- trace_kvm_set_irq(irq, level, irq_source_id);
+ msi.address_lo = e->msi.address_lo;
+ msi.address_hi = e->msi.address_hi;
+ msi.data = e->msi.data;
+ msi.flags = e->msi.flags;
+ msi.devid = e->msi.devid;
- BUG_ON(!vgic_initialized(kvm));
+ if (!vgic_has_its(kvm))
+ return -ENODEV;
- return kvm_vgic_inject_irq(kvm, 0, spi, level);
+ return vgic_its_inject_msi(kvm, &msi);
}
-/* MSI not implemented yet */
-int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
- struct kvm *kvm, int irq_source_id,
- int level, bool line_status)
+int kvm_vgic_setup_default_irq_routing(struct kvm *kvm)
{
- return 0;
+ struct kvm_irq_routing_entry *entries;
+ struct vgic_dist *dist = &kvm->arch.vgic;
+ u32 nr = dist->nr_spis;
+ int i, ret;
+
+ entries = kcalloc(nr, sizeof(struct kvm_kernel_irq_routing_entry),
+ GFP_KERNEL);
+ if (!entries)
+ return -ENOMEM;
+
+ for (i = 0; i < nr; i++) {
+ entries[i].gsi = i;
+ entries[i].type = KVM_IRQ_ROUTING_IRQCHIP;
+ entries[i].u.irqchip.irqchip = 0;
+ entries[i].u.irqchip.pin = i;
+ }
+ ret = kvm_set_irq_routing(kvm, entries, nr, 0);
+ kfree(entries);
+ return ret;
}
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 39f3358..e7aeac7 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -711,10 +711,3 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
return map_is_active;
}
-int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi)
-{
- if (vgic_has_its(kvm))
- return vgic_its_inject_msi(kvm, msi);
- else
- return -ENODEV;
-}
--
1.9.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PULL 6/8] KVM: arm/arm64: Enable MSI routing
2016-08-04 11:40 [PULL 0/8] KVM/ARM Changes for v4.8 - Take #2 Christoffer Dall
` (4 preceding siblings ...)
2016-08-04 11:40 ` [PULL 5/8] KVM: arm/arm64: Enable irqchip routing Christoffer Dall
@ 2016-08-04 11:40 ` Christoffer Dall
2016-08-04 11:40 ` [PULL 7/8] KVM: arm: vgic-irqfd: Workaround changing kvm_set_routing_entry prototype Christoffer Dall
2016-08-04 11:40 ` [PULL 8/8] arm64: KVM: Set cpsr before spsr on fault injection Christoffer Dall
7 siblings, 0 replies; 9+ messages in thread
From: Christoffer Dall @ 2016-08-04 11:40 UTC (permalink / raw)
To: linux-arm-kernel
From: Eric Auger <eric.auger@redhat.com>
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: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
Documentation/virtual/kvm/api.txt | 3 +++
include/linux/kvm_host.h | 2 ++
virt/kvm/arm/vgic/vgic-irqfd.c | 8 ++++++++
virt/kvm/irqchip.c | 24 +++++++++++++++---------
4 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 7e5f9af..7a04216 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -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 the gsi is associated to an irqchip routing entry,
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
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index a7eb5c4..a318c3b 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1048,6 +1048,8 @@ static inline int mmu_notifier_retry(struct kvm *kvm, unsigned long mmu_seq)
#ifdef CONFIG_S390
#define KVM_MAX_IRQ_ROUTES 4096 //FIXME: we can have more than that...
+#elif defined(CONFIG_ARM64)
+#define KVM_MAX_IRQ_ROUTES 4096
#else
#define KVM_MAX_IRQ_ROUTES 1024
#endif
diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c b/virt/kvm/arm/vgic/vgic-irqfd.c
index 6e84d53..683a589 100644
--- a/virt/kvm/arm/vgic/vgic-irqfd.c
+++ b/virt/kvm/arm/vgic/vgic-irqfd.c
@@ -59,6 +59,14 @@ int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
(e->irqchip.irqchip >= KVM_NR_IRQCHIPS))
goto out;
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:
goto out;
}
diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c
index 0c00054..c620219 100644
--- a/virt/kvm/irqchip.c
+++ b/virt/kvm/irqchip.c
@@ -178,6 +178,7 @@ int kvm_set_irq_routing(struct kvm *kvm,
unsigned flags)
{
struct kvm_irq_routing_table *new, *old;
+ struct kvm_kernel_irq_routing_entry *e;
u32 i, j, nr_rt_entries = 0;
int r;
@@ -201,23 +202,25 @@ int kvm_set_irq_routing(struct kvm *kvm,
new->chip[i][j] = -1;
for (i = 0; i < nr; ++i) {
- struct kvm_kernel_irq_routing_entry *e;
-
r = -ENOMEM;
e = kzalloc(sizeof(*e), GFP_KERNEL);
if (!e)
goto out;
r = -EINVAL;
- if (ue->flags) {
- kfree(e);
- goto out;
+ switch (ue->type) {
+ case KVM_IRQ_ROUTING_MSI:
+ 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);
- if (r) {
- kfree(e);
- goto out;
- }
+ if (r)
+ goto free_entry;
++ue;
}
@@ -234,7 +237,10 @@ int kvm_set_irq_routing(struct kvm *kvm,
new = old;
r = 0;
+ goto out;
+free_entry:
+ kfree(e);
out:
free_irq_routing_table(new);
--
1.9.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PULL 7/8] KVM: arm: vgic-irqfd: Workaround changing kvm_set_routing_entry prototype
2016-08-04 11:40 [PULL 0/8] KVM/ARM Changes for v4.8 - Take #2 Christoffer Dall
` (5 preceding siblings ...)
2016-08-04 11:40 ` [PULL 6/8] KVM: arm/arm64: Enable MSI routing Christoffer Dall
@ 2016-08-04 11:40 ` Christoffer Dall
2016-08-04 11:40 ` [PULL 8/8] arm64: KVM: Set cpsr before spsr on fault injection Christoffer Dall
7 siblings, 0 replies; 9+ messages in thread
From: Christoffer Dall @ 2016-08-04 11:40 UTC (permalink / raw)
To: linux-arm-kernel
From: Marc Zyngier <marc.zyngier@arm.com>
kvm_set_routing_entry is changing in -next, and causes things to
explode. Add a temporary workaround that should be dropped when
we hit 4.8-rc1
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
virt/kvm/arm/vgic/vgic-irqfd.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c b/virt/kvm/arm/vgic/vgic-irqfd.c
index 683a589..b31a51a 100644
--- a/virt/kvm/arm/vgic/vgic-irqfd.c
+++ b/virt/kvm/arm/vgic/vgic-irqfd.c
@@ -41,12 +41,20 @@ static int vgic_irqfd_set_irq(struct kvm_kernel_irq_routing_entry *e,
* kvm_set_routing_entry: populate a kvm routing entry
* from a user routing entry
*
+ * @kvm: the VM this entry is applied to
* @e: kvm kernel routing entry handle
* @ue: user api routing entry handle
* return 0 on success, -EINVAL on errors.
*/
+#ifdef KVM_CAP_X2APIC_API
+int kvm_set_routing_entry(struct kvm *kvm,
+ struct kvm_kernel_irq_routing_entry *e,
+ const struct kvm_irq_routing_entry *ue)
+#else
+/* Remove this version and the ifdefery once merged into 4.8 */
int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
const struct kvm_irq_routing_entry *ue)
+#endif
{
int r = -EINVAL;
--
1.9.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PULL 8/8] arm64: KVM: Set cpsr before spsr on fault injection
2016-08-04 11:40 [PULL 0/8] KVM/ARM Changes for v4.8 - Take #2 Christoffer Dall
` (6 preceding siblings ...)
2016-08-04 11:40 ` [PULL 7/8] KVM: arm: vgic-irqfd: Workaround changing kvm_set_routing_entry prototype Christoffer Dall
@ 2016-08-04 11:40 ` Christoffer Dall
7 siblings, 0 replies; 9+ messages in thread
From: Christoffer Dall @ 2016-08-04 11:40 UTC (permalink / raw)
To: linux-arm-kernel
From: Andrew Jones <drjones@redhat.com>
We need to set cpsr before determining the spsr bank, as the bank
depends on the target exception level of the injection, not the
current mode of the vcpu. Normally this is one in the same (EL1),
but not when we manage to trap an EL0 fault. It still doesn't really
matter for the 64-bit EL0 case though, as vcpu_spsr() unconditionally
uses the EL1 bank for that. However the 32-bit EL0 case gets fun, as
that path will lead to the BUG() in vcpu_spsr32().
This patch fixes the assignment order and also modifies some white
space in order to better group pairs of lines that have strict order.
Cc: stable at vger.kernel.org # v4.5
Signed-off-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/kvm/inject_fault.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
index e9e0e6d..898c0e6 100644
--- a/arch/arm64/kvm/inject_fault.c
+++ b/arch/arm64/kvm/inject_fault.c
@@ -132,16 +132,14 @@ static u64 get_except_vector(struct kvm_vcpu *vcpu, enum exception_type type)
static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr)
{
unsigned long cpsr = *vcpu_cpsr(vcpu);
- bool is_aarch32;
+ bool is_aarch32 = vcpu_mode_is_32bit(vcpu);
u32 esr = 0;
- is_aarch32 = vcpu_mode_is_32bit(vcpu);
-
- *vcpu_spsr(vcpu) = cpsr;
*vcpu_elr_el1(vcpu) = *vcpu_pc(vcpu);
-
*vcpu_pc(vcpu) = get_except_vector(vcpu, except_type_sync);
+
*vcpu_cpsr(vcpu) = PSTATE_FAULT_BITS_64;
+ *vcpu_spsr(vcpu) = cpsr;
vcpu_sys_reg(vcpu, FAR_EL1) = addr;
@@ -172,11 +170,11 @@ static void inject_undef64(struct kvm_vcpu *vcpu)
unsigned long cpsr = *vcpu_cpsr(vcpu);
u32 esr = (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT);
- *vcpu_spsr(vcpu) = cpsr;
*vcpu_elr_el1(vcpu) = *vcpu_pc(vcpu);
-
*vcpu_pc(vcpu) = get_except_vector(vcpu, except_type_sync);
+
*vcpu_cpsr(vcpu) = PSTATE_FAULT_BITS_64;
+ *vcpu_spsr(vcpu) = cpsr;
/*
* Build an unknown exception, depending on the instruction
--
1.9.1
^ permalink raw reply related [flat|nested] 9+ messages in thread