* [PATCH 0/9][v6] Enable MSI for KVM
@ 2008-11-24 6:32 Sheng Yang
2008-11-24 6:32 ` [PATCH 1/9] KVM: Move ack notifier register and IRQ sourcd ID request Sheng Yang
` (9 more replies)
0 siblings, 10 replies; 11+ messages in thread
From: Sheng Yang @ 2008-11-24 6:32 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm
Hi
MSI patchset v6 is coming...
v5->v6
Addressed all comments from Avi on v5. I also set msi2intx=0 in non-x86
architecture machines.
And the TODO list after this patchset:
1. A independence IOCTL to deliver MSI message data/address and related info,
so that kvm_set_irq() can deliver MSI message directly.
2. Merge MSI parsing process with IOAPIC. Also speed it up with bit ops.
3. Separate lock for IOAPIC, maybe also LAPIC.
Thanks!
--
regards
Yang, Sheng
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/9] KVM: Move ack notifier register and IRQ sourcd ID request
2008-11-24 6:32 [PATCH 0/9][v6] Enable MSI for KVM Sheng Yang
@ 2008-11-24 6:32 ` Sheng Yang
2008-11-24 6:32 ` [PATCH 2/9] KVM: Separate update irq to a single function Sheng Yang
` (8 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Sheng Yang @ 2008-11-24 6:32 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm, Sheng Yang
Distinguish common part for device assignment and INTx part, perparing for
refactor later.
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
virt/kvm/kvm_main.c | 30 +++++++++++++++++++-----------
1 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 4727c08..8966fd1 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -192,16 +192,31 @@ static int kvm_vm_ioctl_assign_irq(struct kvm *kvm,
return -EINVAL;
}
- if (match->irq_requested) {
+ if (!match->irq_requested) {
+ INIT_WORK(&match->interrupt_work,
+ kvm_assigned_dev_interrupt_work_handler);
+ if (irqchip_in_kernel(kvm)) {
+ /* Register ack nofitier */
+ match->ack_notifier.gsi = -1;
+ match->ack_notifier.irq_acked =
+ kvm_assigned_dev_ack_irq;
+ kvm_register_irq_ack_notifier(kvm,
+ &match->ack_notifier);
+
+ /* Request IRQ source ID */
+ r = kvm_request_irq_source_id(kvm);
+ if (r < 0)
+ goto out_release;
+ else
+ match->irq_source_id = r;
+ }
+ } else {
match->guest_irq = assigned_irq->guest_irq;
match->ack_notifier.gsi = assigned_irq->guest_irq;
mutex_unlock(&kvm->lock);
return 0;
}
- INIT_WORK(&match->interrupt_work,
- kvm_assigned_dev_interrupt_work_handler);
-
if (irqchip_in_kernel(kvm)) {
if (!capable(CAP_SYS_RAWIO)) {
r = -EPERM;
@@ -214,13 +229,6 @@ static int kvm_vm_ioctl_assign_irq(struct kvm *kvm,
match->host_irq = match->dev->irq;
match->guest_irq = assigned_irq->guest_irq;
match->ack_notifier.gsi = assigned_irq->guest_irq;
- match->ack_notifier.irq_acked = kvm_assigned_dev_ack_irq;
- kvm_register_irq_ack_notifier(kvm, &match->ack_notifier);
- r = kvm_request_irq_source_id(kvm);
- if (r < 0)
- goto out_release;
- else
- match->irq_source_id = r;
/* Even though this is PCI, we don't want to use shared
* interrupts. Sharing host devices with guest-assigned devices
--
1.5.4.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/9] KVM: Separate update irq to a single function
2008-11-24 6:32 [PATCH 0/9][v6] Enable MSI for KVM Sheng Yang
2008-11-24 6:32 ` [PATCH 1/9] KVM: Move ack notifier register and IRQ sourcd ID request Sheng Yang
@ 2008-11-24 6:32 ` Sheng Yang
2008-11-24 6:32 ` [PATCH 3/9] KVM: Replace irq_requested with more generic irq_requested_type Sheng Yang
` (7 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Sheng Yang @ 2008-11-24 6:32 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm, Sheng Yang
Separate INTx enabling part to a independence function, so that we can add MSI
enabling part easily.
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
virt/kvm/kvm_main.c | 68 ++++++++++++++++++++++++++++----------------------
1 files changed, 38 insertions(+), 30 deletions(-)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 8966fd1..ef2f03c 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -176,6 +176,41 @@ void kvm_free_all_assigned_devices(struct kvm *kvm)
}
}
+static int assigned_device_update_intx(struct kvm *kvm,
+ struct kvm_assigned_dev_kernel *adev,
+ struct kvm_assigned_irq *airq)
+{
+ if (adev->irq_requested) {
+ adev->guest_irq = airq->guest_irq;
+ adev->ack_notifier.gsi = airq->guest_irq;
+ return 0;
+ }
+
+ if (irqchip_in_kernel(kvm)) {
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ if (airq->host_irq)
+ adev->host_irq = airq->host_irq;
+ else
+ adev->host_irq = adev->dev->irq;
+ adev->guest_irq = airq->guest_irq;
+ adev->ack_notifier.gsi = airq->guest_irq;
+
+ /* Even though this is PCI, we don't want to use shared
+ * interrupts. Sharing host devices with guest-assigned devices
+ * on the same interrupt line is not a happy situation: there
+ * are going to be long delays in accepting, acking, etc.
+ */
+ if (request_irq(adev->host_irq, kvm_assigned_dev_intr,
+ 0, "kvm_assigned_intx_device", (void *)adev))
+ return -EIO;
+ }
+
+ adev->irq_requested = true;
+ return 0;
+}
+
static int kvm_vm_ioctl_assign_irq(struct kvm *kvm,
struct kvm_assigned_irq
*assigned_irq)
@@ -210,39 +245,12 @@ static int kvm_vm_ioctl_assign_irq(struct kvm *kvm,
else
match->irq_source_id = r;
}
- } else {
- match->guest_irq = assigned_irq->guest_irq;
- match->ack_notifier.gsi = assigned_irq->guest_irq;
- mutex_unlock(&kvm->lock);
- return 0;
}
- if (irqchip_in_kernel(kvm)) {
- if (!capable(CAP_SYS_RAWIO)) {
- r = -EPERM;
- goto out_release;
- }
-
- if (assigned_irq->host_irq)
- match->host_irq = assigned_irq->host_irq;
- else
- match->host_irq = match->dev->irq;
- match->guest_irq = assigned_irq->guest_irq;
- match->ack_notifier.gsi = assigned_irq->guest_irq;
-
- /* Even though this is PCI, we don't want to use shared
- * interrupts. Sharing host devices with guest-assigned devices
- * on the same interrupt line is not a happy situation: there
- * are going to be long delays in accepting, acking, etc.
- */
- if (request_irq(match->host_irq, kvm_assigned_dev_intr, 0,
- "kvm_assigned_device", (void *)match)) {
- r = -EIO;
- goto out_release;
- }
- }
+ r = assigned_device_update_intx(kvm, match, assigned_irq);
+ if (r)
+ goto out_release;
- match->irq_requested = true;
mutex_unlock(&kvm->lock);
return r;
out_release:
--
1.5.4.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 3/9] KVM: Replace irq_requested with more generic irq_requested_type
2008-11-24 6:32 [PATCH 0/9][v6] Enable MSI for KVM Sheng Yang
2008-11-24 6:32 ` [PATCH 1/9] KVM: Move ack notifier register and IRQ sourcd ID request Sheng Yang
2008-11-24 6:32 ` [PATCH 2/9] KVM: Separate update irq to a single function Sheng Yang
@ 2008-11-24 6:32 ` Sheng Yang
2008-11-24 6:32 ` [PATCH 4/9] KVM: Clean up assigned_device_update_irq Sheng Yang
` (6 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Sheng Yang @ 2008-11-24 6:32 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm, Sheng Yang
Separate guest irq type and host irq type, for we can support guest using INTx
with host using MSI (but not opposite combination).
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
include/linux/kvm_host.h | 4 +++-
virt/kvm/kvm_main.c | 9 +++++----
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 3a0fb77..c3d4b96 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -307,7 +307,9 @@ struct kvm_assigned_dev_kernel {
int host_devfn;
int host_irq;
int guest_irq;
- int irq_requested;
+#define KVM_ASSIGNED_DEV_GUEST_INTX (1 << 0)
+#define KVM_ASSIGNED_DEV_HOST_INTX (1 << 8)
+ unsigned long irq_requested_type;
int irq_source_id;
struct pci_dev *dev;
struct kvm *kvm;
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index ef2f03c..638de47 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -140,7 +140,7 @@ static void kvm_free_assigned_device(struct kvm *kvm,
struct kvm_assigned_dev_kernel
*assigned_dev)
{
- if (irqchip_in_kernel(kvm) && assigned_dev->irq_requested)
+ if (irqchip_in_kernel(kvm) && assigned_dev->irq_requested_type)
free_irq(assigned_dev->host_irq, (void *)assigned_dev);
kvm_unregister_irq_ack_notifier(&assigned_dev->ack_notifier);
@@ -180,7 +180,7 @@ static int assigned_device_update_intx(struct kvm *kvm,
struct kvm_assigned_dev_kernel *adev,
struct kvm_assigned_irq *airq)
{
- if (adev->irq_requested) {
+ if (adev->irq_requested_type & KVM_ASSIGNED_DEV_GUEST_INTX) {
adev->guest_irq = airq->guest_irq;
adev->ack_notifier.gsi = airq->guest_irq;
return 0;
@@ -207,7 +207,8 @@ static int assigned_device_update_intx(struct kvm *kvm,
return -EIO;
}
- adev->irq_requested = true;
+ adev->irq_requested_type = KVM_ASSIGNED_DEV_GUEST_INTX |
+ KVM_ASSIGNED_DEV_HOST_INTX;
return 0;
}
@@ -227,7 +228,7 @@ static int kvm_vm_ioctl_assign_irq(struct kvm *kvm,
return -EINVAL;
}
- if (!match->irq_requested) {
+ if (!match->irq_requested_type) {
INIT_WORK(&match->interrupt_work,
kvm_assigned_dev_interrupt_work_handler);
if (irqchip_in_kernel(kvm)) {
--
1.5.4.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 4/9] KVM: Clean up assigned_device_update_irq
2008-11-24 6:32 [PATCH 0/9][v6] Enable MSI for KVM Sheng Yang
` (2 preceding siblings ...)
2008-11-24 6:32 ` [PATCH 3/9] KVM: Replace irq_requested with more generic irq_requested_type Sheng Yang
@ 2008-11-24 6:32 ` Sheng Yang
2008-11-24 6:32 ` [PATCH 5/9] KVM: Add fields for MSI device assignment Sheng Yang
` (5 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Sheng Yang @ 2008-11-24 6:32 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm, Sheng Yang
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
virt/kvm/kvm_main.c | 10 ++++------
1 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 638de47..2089f8b 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -180,11 +180,11 @@ static int assigned_device_update_intx(struct kvm *kvm,
struct kvm_assigned_dev_kernel *adev,
struct kvm_assigned_irq *airq)
{
- if (adev->irq_requested_type & KVM_ASSIGNED_DEV_GUEST_INTX) {
- adev->guest_irq = airq->guest_irq;
- adev->ack_notifier.gsi = airq->guest_irq;
+ adev->guest_irq = airq->guest_irq;
+ adev->ack_notifier.gsi = airq->guest_irq;
+
+ if (adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_INTX)
return 0;
- }
if (irqchip_in_kernel(kvm)) {
if (!capable(CAP_SYS_RAWIO))
@@ -194,8 +194,6 @@ static int assigned_device_update_intx(struct kvm *kvm,
adev->host_irq = airq->host_irq;
else
adev->host_irq = adev->dev->irq;
- adev->guest_irq = airq->guest_irq;
- adev->ack_notifier.gsi = airq->guest_irq;
/* Even though this is PCI, we don't want to use shared
* interrupts. Sharing host devices with guest-assigned devices
--
1.5.4.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 5/9] KVM: Add fields for MSI device assignment
2008-11-24 6:32 [PATCH 0/9][v6] Enable MSI for KVM Sheng Yang
` (3 preceding siblings ...)
2008-11-24 6:32 ` [PATCH 4/9] KVM: Clean up assigned_device_update_irq Sheng Yang
@ 2008-11-24 6:32 ` Sheng Yang
2008-11-24 6:32 ` [PATCH 6/9] KVM: Export ioapic_get_delivery_bitmask Sheng Yang
` (4 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Sheng Yang @ 2008-11-24 6:32 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm, Sheng Yang
Prepared for kvm_arch_assigned_device_msi_dispatch().
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
include/linux/kvm.h | 7 +++++++
include/linux/kvm_host.h | 4 ++++
2 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 44fd7fa..bb283c3 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -507,10 +507,17 @@ struct kvm_assigned_irq {
__u32 guest_irq;
__u32 flags;
union {
+ struct {
+ __u32 addr_lo;
+ __u32 addr_hi;
+ __u32 data;
+ } guest_msi;
__u32 reserved[12];
};
};
#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
+#define KVM_DEV_IRQ_ASSIGN_ENABLE_MSI (1 << 0)
+
#endif
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index c3d4b96..8091a4d 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -16,6 +16,7 @@
#include <linux/mm.h>
#include <linux/preempt.h>
#include <linux/marker.h>
+#include <linux/msi.h>
#include <asm/signal.h>
#include <linux/kvm.h>
@@ -307,8 +308,11 @@ struct kvm_assigned_dev_kernel {
int host_devfn;
int host_irq;
int guest_irq;
+ struct msi_msg guest_msi;
#define KVM_ASSIGNED_DEV_GUEST_INTX (1 << 0)
+#define KVM_ASSIGNED_DEV_GUEST_MSI (1 << 1)
#define KVM_ASSIGNED_DEV_HOST_INTX (1 << 8)
+#define KVM_ASSIGNED_DEV_HOST_MSI (1 << 9)
unsigned long irq_requested_type;
int irq_source_id;
struct pci_dev *dev;
--
1.5.4.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 6/9] KVM: Export ioapic_get_delivery_bitmask
2008-11-24 6:32 [PATCH 0/9][v6] Enable MSI for KVM Sheng Yang
` (4 preceding siblings ...)
2008-11-24 6:32 ` [PATCH 5/9] KVM: Add fields for MSI device assignment Sheng Yang
@ 2008-11-24 6:32 ` Sheng Yang
2008-11-24 6:32 ` [PATCH 7/9] KVM: Add assigned_device_msi_dispatch() Sheng Yang
` (3 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Sheng Yang @ 2008-11-24 6:32 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm, Sheng Yang
It would be used for MSI in device assignment, for MSI dispatch.
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
virt/kvm/ioapic.c | 7 ++++---
virt/kvm/ioapic.h | 2 ++
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index c8f939c..23b81cf 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -153,8 +153,8 @@ static void ioapic_inj_nmi(struct kvm_vcpu *vcpu)
kvm_vcpu_kick(vcpu);
}
-static u32 ioapic_get_delivery_bitmask(struct kvm_ioapic *ioapic, u8 dest,
- u8 dest_mode)
+u32 kvm_ioapic_get_delivery_bitmask(struct kvm_ioapic *ioapic, u8 dest,
+ u8 dest_mode)
{
u32 mask = 0;
int i;
@@ -208,7 +208,8 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
"vector=%x trig_mode=%x\n",
dest, dest_mode, delivery_mode, vector, trig_mode);
- deliver_bitmask = ioapic_get_delivery_bitmask(ioapic, dest, dest_mode);
+ deliver_bitmask = kvm_ioapic_get_delivery_bitmask(ioapic, dest,
+ dest_mode);
if (!deliver_bitmask) {
ioapic_debug("no target on destination\n");
return 0;
diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h
index cd7ae76..49c9581 100644
--- a/virt/kvm/ioapic.h
+++ b/virt/kvm/ioapic.h
@@ -85,5 +85,7 @@ void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode);
int kvm_ioapic_init(struct kvm *kvm);
void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
void kvm_ioapic_reset(struct kvm_ioapic *ioapic);
+u32 kvm_ioapic_get_delivery_bitmask(struct kvm_ioapic *ioapic, u8 dest,
+ u8 dest_mode);
#endif
--
1.5.4.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 7/9] KVM: Add assigned_device_msi_dispatch()
2008-11-24 6:32 [PATCH 0/9][v6] Enable MSI for KVM Sheng Yang
` (5 preceding siblings ...)
2008-11-24 6:32 ` [PATCH 6/9] KVM: Export ioapic_get_delivery_bitmask Sheng Yang
@ 2008-11-24 6:32 ` Sheng Yang
2008-11-24 6:32 ` [PATCH 8/9] KVM: Enable MSI for device assignment Sheng Yang
` (2 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Sheng Yang @ 2008-11-24 6:32 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm, Sheng Yang
The function is used to dispatch MSI to lapic according to MSI message
address and message data.
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
virt/kvm/kvm_main.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 55 insertions(+), 0 deletions(-)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 2089f8b..228c1d1 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -47,6 +47,10 @@
#include <asm/uaccess.h>
#include <asm/pgtable.h>
+#ifdef CONFIG_X86
+#include <asm/msidef.h>
+#endif
+
#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
#include "coalesced_mmio.h"
#endif
@@ -78,6 +82,57 @@ static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
bool kvm_rebooting;
#ifdef KVM_CAP_DEVICE_ASSIGNMENT
+
+#ifdef CONFIG_X86
+static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev)
+{
+ int vcpu_id;
+ struct kvm_vcpu *vcpu;
+ struct kvm_ioapic *ioapic = ioapic_irqchip(dev->kvm);
+ int dest_id = (dev->guest_msi.address_lo & MSI_ADDR_DEST_ID_MASK)
+ >> MSI_ADDR_DEST_ID_SHIFT;
+ int vector = (dev->guest_msi.data & MSI_DATA_VECTOR_MASK)
+ >> MSI_DATA_VECTOR_SHIFT;
+ int dest_mode = test_bit(MSI_ADDR_DEST_MODE_SHIFT,
+ (unsigned long *)&dev->guest_msi.address_lo);
+ int trig_mode = test_bit(MSI_DATA_TRIGGER_SHIFT,
+ (unsigned long *)&dev->guest_msi.data);
+ int delivery_mode = test_bit(MSI_DATA_DELIVERY_MODE_SHIFT,
+ (unsigned long *)&dev->guest_msi.data);
+ u32 deliver_bitmask;
+
+ BUG_ON(!ioapic);
+
+ deliver_bitmask = kvm_ioapic_get_delivery_bitmask(ioapic,
+ dest_id, dest_mode);
+ /* IOAPIC delivery mode value is the same as MSI here */
+ switch (delivery_mode) {
+ case IOAPIC_LOWEST_PRIORITY:
+ vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, vector,
+ deliver_bitmask);
+ if (vcpu != NULL)
+ kvm_apic_set_irq(vcpu, vector, trig_mode);
+ else
+ printk(KERN_INFO "kvm: null lowest priority vcpu!\n");
+ break;
+ case IOAPIC_FIXED:
+ for (vcpu_id = 0; deliver_bitmask != 0; vcpu_id++) {
+ if (!(deliver_bitmask & (1 << vcpu_id)))
+ continue;
+ deliver_bitmask &= ~(1 << vcpu_id);
+ vcpu = ioapic->kvm->vcpus[vcpu_id];
+ if (vcpu)
+ kvm_apic_set_irq(vcpu, vector, trig_mode);
+ }
+ break;
+ default:
+ printk(KERN_INFO "kvm: unsupported MSI delivery mode\n");
+ }
+}
+#else
+static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev) {}
+#endif
+
static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *head,
int assigned_dev_id)
{
--
1.5.4.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 8/9] KVM: Enable MSI for device assignment
2008-11-24 6:32 [PATCH 0/9][v6] Enable MSI for KVM Sheng Yang
` (6 preceding siblings ...)
2008-11-24 6:32 ` [PATCH 7/9] KVM: Add assigned_device_msi_dispatch() Sheng Yang
@ 2008-11-24 6:32 ` Sheng Yang
2008-11-24 6:32 ` [PATCH 9/9] KVM: MSI to INTx translate Sheng Yang
2008-11-26 10:14 ` [PATCH 0/9][v6] Enable MSI for KVM Avi Kivity
9 siblings, 0 replies; 11+ messages in thread
From: Sheng Yang @ 2008-11-24 6:32 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm, Sheng Yang
We enable guest MSI and host MSI support in this patch. The userspace want to
enable MSI should set KVM_DEV_IRQ_ASSIGN_ENABLE_MSI in the assigned_irq's flag.
Function would return -ENOTTY if can't enable MSI, userspace shouldn't set MSI
Enable bit when KVM_ASSIGN_IRQ return -ENOTTY with
KVM_DEV_IRQ_ASSIGN_ENABLE_MSI.
Userspace can tell the support of MSI device from #ifdef KVM_CAP_DEVICE_MSI.
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
include/linux/kvm.h | 3 ++
virt/kvm/kvm_main.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 78 insertions(+), 6 deletions(-)
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index bb283c3..0997e6f 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -392,6 +392,9 @@ struct kvm_trace_rec {
#endif
#define KVM_CAP_IOMMU 18
#define KVM_CAP_NMI 19
+#if defined(CONFIG_X86)
+#define KVM_CAP_DEVICE_MSI 20
+#endif
/*
* ioctls for VM fds
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 228c1d1..bf36ae9 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -159,9 +159,15 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work)
* finer-grained lock, update this
*/
mutex_lock(&assigned_dev->kvm->lock);
- kvm_set_irq(assigned_dev->kvm,
- assigned_dev->irq_source_id,
- assigned_dev->guest_irq, 1);
+ if (assigned_dev->irq_requested_type & KVM_ASSIGNED_DEV_GUEST_INTX)
+ kvm_set_irq(assigned_dev->kvm,
+ assigned_dev->irq_source_id,
+ assigned_dev->guest_irq, 1);
+ else if (assigned_dev->irq_requested_type &
+ KVM_ASSIGNED_DEV_GUEST_MSI) {
+ assigned_device_msi_dispatch(assigned_dev);
+ enable_irq(assigned_dev->host_irq);
+ }
mutex_unlock(&assigned_dev->kvm->lock);
kvm_put_kvm(assigned_dev->kvm);
}
@@ -197,6 +203,8 @@ static void kvm_free_assigned_device(struct kvm *kvm,
{
if (irqchip_in_kernel(kvm) && assigned_dev->irq_requested_type)
free_irq(assigned_dev->host_irq, (void *)assigned_dev);
+ if (assigned_dev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI)
+ pci_disable_msi(assigned_dev->dev);
kvm_unregister_irq_ack_notifier(&assigned_dev->ack_notifier);
kvm_free_irq_source_id(kvm, assigned_dev->irq_source_id);
@@ -242,6 +250,11 @@ static int assigned_device_update_intx(struct kvm *kvm,
return 0;
if (irqchip_in_kernel(kvm)) {
+ if (adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI) {
+ free_irq(adev->host_irq, (void *)kvm);
+ pci_disable_msi(adev->dev);
+ }
+
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
@@ -265,6 +278,41 @@ static int assigned_device_update_intx(struct kvm *kvm,
return 0;
}
+#ifdef CONFIG_X86
+static int assigned_device_update_msi(struct kvm *kvm,
+ struct kvm_assigned_dev_kernel *adev,
+ struct kvm_assigned_irq *airq)
+{
+ int r;
+
+ /* x86 don't care upper address of guest msi message addr */
+ adev->guest_msi.address_lo = airq->guest_msi.addr_lo;
+ adev->guest_msi.data = airq->guest_msi.data;
+ adev->ack_notifier.gsi = -1;
+
+ if (adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI)
+ return 0;
+
+ if (irqchip_in_kernel(kvm)) {
+ if (adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_INTX)
+ free_irq(adev->host_irq, (void *)adev);
+
+ r = pci_enable_msi(adev->dev);
+ if (r)
+ return r;
+
+ adev->host_irq = adev->dev->irq;
+ if (request_irq(adev->host_irq, kvm_assigned_dev_intr, 0,
+ "kvm_assigned_msi_device", (void *)adev))
+ return -EIO;
+ }
+
+ adev->irq_requested_type = KVM_ASSIGNED_DEV_GUEST_MSI |
+ KVM_ASSIGNED_DEV_HOST_MSI;
+ return 0;
+}
+#endif
+
static int kvm_vm_ioctl_assign_irq(struct kvm *kvm,
struct kvm_assigned_irq
*assigned_irq)
@@ -301,9 +349,30 @@ static int kvm_vm_ioctl_assign_irq(struct kvm *kvm,
}
}
- r = assigned_device_update_intx(kvm, match, assigned_irq);
- if (r)
- goto out_release;
+ if (assigned_irq->flags & KVM_DEV_IRQ_ASSIGN_ENABLE_MSI) {
+#ifdef CONFIG_X86
+ r = assigned_device_update_msi(kvm, match, assigned_irq);
+ if (r) {
+ printk(KERN_WARNING "kvm: failed to enable "
+ "MSI device!\n");
+ goto out_release;
+ }
+#else
+ r = -ENOTTY;
+#endif
+ } else if (assigned_irq->host_irq == 0 && match->dev->irq == 0) {
+ /* Host device IRQ 0 means don't support INTx */
+ printk(KERN_WARNING "kvm: wait device to enable MSI!\n");
+ r = 0;
+ } else {
+ /* Non-sharing INTx mode */
+ r = assigned_device_update_intx(kvm, match, assigned_irq);
+ if (r) {
+ printk(KERN_WARNING "kvm: failed to enable "
+ "INTx device!\n");
+ goto out_release;
+ }
+ }
mutex_unlock(&kvm->lock);
return r;
--
1.5.4.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 9/9] KVM: MSI to INTx translate
2008-11-24 6:32 [PATCH 0/9][v6] Enable MSI for KVM Sheng Yang
` (7 preceding siblings ...)
2008-11-24 6:32 ` [PATCH 8/9] KVM: Enable MSI for device assignment Sheng Yang
@ 2008-11-24 6:32 ` Sheng Yang
2008-11-26 10:14 ` [PATCH 0/9][v6] Enable MSI for KVM Avi Kivity
9 siblings, 0 replies; 11+ messages in thread
From: Sheng Yang @ 2008-11-24 6:32 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm, Sheng Yang
Now we use MSI as default one, and translate MSI to INTx when guest need
INTx rather than MSI. For legacy device, we provide support for non-sharing
host IRQ.
Provide a parameter msi2intx for this method. The value is true by default in
x86 architecture.
We can't guarantee this mode can work on every device, but for most of us
tested, it works. If your device encounter some trouble with this mode, you can
try set msi2intx modules parameter to 0. If the device is OK with msi2intx=0,
then please report it to KVM mailing list or me. We may prepare a blacklist for
the device that can't work in this mode.
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
virt/kvm/kvm_main.c | 70 +++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 54 insertions(+), 16 deletions(-)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index bf36ae9..54d25e6 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -64,6 +64,9 @@
MODULE_AUTHOR("Qumranet");
MODULE_LICENSE("GPL");
+static int msi2intx = 1;
+module_param(msi2intx, bool, 0);
+
DEFINE_SPINLOCK(kvm_lock);
LIST_HEAD(vm_list);
@@ -250,7 +253,8 @@ static int assigned_device_update_intx(struct kvm *kvm,
return 0;
if (irqchip_in_kernel(kvm)) {
- if (adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI) {
+ if (!msi2intx &&
+ adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI) {
free_irq(adev->host_irq, (void *)kvm);
pci_disable_msi(adev->dev);
}
@@ -285,21 +289,33 @@ static int assigned_device_update_msi(struct kvm *kvm,
{
int r;
- /* x86 don't care upper address of guest msi message addr */
- adev->guest_msi.address_lo = airq->guest_msi.addr_lo;
- adev->guest_msi.data = airq->guest_msi.data;
- adev->ack_notifier.gsi = -1;
+ if (airq->flags & KVM_DEV_IRQ_ASSIGN_ENABLE_MSI) {
+ /* x86 don't care upper address of guest msi message addr */
+ adev->irq_requested_type |= KVM_ASSIGNED_DEV_GUEST_MSI;
+ adev->irq_requested_type &= ~KVM_ASSIGNED_DEV_GUEST_INTX;
+ adev->guest_msi.address_lo = airq->guest_msi.addr_lo;
+ adev->guest_msi.data = airq->guest_msi.data;
+ adev->ack_notifier.gsi = -1;
+ } else if (msi2intx) {
+ adev->irq_requested_type |= KVM_ASSIGNED_DEV_GUEST_INTX;
+ adev->irq_requested_type &= ~KVM_ASSIGNED_DEV_GUEST_MSI;
+ adev->guest_irq = airq->guest_irq;
+ adev->ack_notifier.gsi = airq->guest_irq;
+ }
if (adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI)
return 0;
if (irqchip_in_kernel(kvm)) {
- if (adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_INTX)
- free_irq(adev->host_irq, (void *)adev);
-
- r = pci_enable_msi(adev->dev);
- if (r)
- return r;
+ if (!msi2intx) {
+ if (adev->irq_requested_type &
+ KVM_ASSIGNED_DEV_HOST_INTX)
+ free_irq(adev->host_irq, (void *)adev);
+
+ r = pci_enable_msi(adev->dev);
+ if (r)
+ return r;
+ }
adev->host_irq = adev->dev->irq;
if (request_irq(adev->host_irq, kvm_assigned_dev_intr, 0,
@@ -307,8 +323,10 @@ static int assigned_device_update_msi(struct kvm *kvm,
return -EIO;
}
- adev->irq_requested_type = KVM_ASSIGNED_DEV_GUEST_MSI |
- KVM_ASSIGNED_DEV_HOST_MSI;
+ if (!msi2intx)
+ adev->irq_requested_type = KVM_ASSIGNED_DEV_GUEST_MSI;
+
+ adev->irq_requested_type |= KVM_ASSIGNED_DEV_HOST_MSI;
return 0;
}
#endif
@@ -346,10 +364,19 @@ static int kvm_vm_ioctl_assign_irq(struct kvm *kvm,
goto out_release;
else
match->irq_source_id = r;
+
+#ifdef CONFIG_X86
+ /* Determine host device irq type, we can know the
+ * result from dev->msi_enabled */
+ if (msi2intx)
+ pci_enable_msi(match->dev);
+#endif
}
}
- if (assigned_irq->flags & KVM_DEV_IRQ_ASSIGN_ENABLE_MSI) {
+ if ((!msi2intx &&
+ (assigned_irq->flags & KVM_DEV_IRQ_ASSIGN_ENABLE_MSI)) ||
+ (msi2intx && match->dev->msi_enabled)) {
#ifdef CONFIG_X86
r = assigned_device_update_msi(kvm, match, assigned_irq);
if (r) {
@@ -362,8 +389,16 @@ static int kvm_vm_ioctl_assign_irq(struct kvm *kvm,
#endif
} else if (assigned_irq->host_irq == 0 && match->dev->irq == 0) {
/* Host device IRQ 0 means don't support INTx */
- printk(KERN_WARNING "kvm: wait device to enable MSI!\n");
- r = 0;
+ if (!msi2intx) {
+ printk(KERN_WARNING
+ "kvm: wait device to enable MSI!\n");
+ r = 0;
+ } else {
+ printk(KERN_WARNING
+ "kvm: failed to enable MSI device!\n");
+ r = -ENOTTY;
+ goto out_release;
+ }
} else {
/* Non-sharing INTx mode */
r = assigned_device_update_intx(kvm, match, assigned_irq);
@@ -2209,6 +2244,9 @@ int kvm_init(void *opaque, unsigned int vcpu_size,
kvm_preempt_ops.sched_in = kvm_sched_in;
kvm_preempt_ops.sched_out = kvm_sched_out;
+#ifndef CONFIG_X86
+ msi2intx = 0;
+#endif
return 0;
--
1.5.4.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 0/9][v6] Enable MSI for KVM
2008-11-24 6:32 [PATCH 0/9][v6] Enable MSI for KVM Sheng Yang
` (8 preceding siblings ...)
2008-11-24 6:32 ` [PATCH 9/9] KVM: MSI to INTx translate Sheng Yang
@ 2008-11-26 10:14 ` Avi Kivity
9 siblings, 0 replies; 11+ messages in thread
From: Avi Kivity @ 2008-11-26 10:14 UTC (permalink / raw)
To: Sheng Yang; +Cc: kvm
Sheng Yang wrote:
> Hi
>
> MSI patchset v6 is coming...
>
> v5->v6
>
> Addressed all comments from Avi on v5. I also set msi2intx=0 in non-x86
> architecture machines.
>
Applied all, thanks.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2008-11-26 10:15 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-11-24 6:32 [PATCH 0/9][v6] Enable MSI for KVM Sheng Yang
2008-11-24 6:32 ` [PATCH 1/9] KVM: Move ack notifier register and IRQ sourcd ID request Sheng Yang
2008-11-24 6:32 ` [PATCH 2/9] KVM: Separate update irq to a single function Sheng Yang
2008-11-24 6:32 ` [PATCH 3/9] KVM: Replace irq_requested with more generic irq_requested_type Sheng Yang
2008-11-24 6:32 ` [PATCH 4/9] KVM: Clean up assigned_device_update_irq Sheng Yang
2008-11-24 6:32 ` [PATCH 5/9] KVM: Add fields for MSI device assignment Sheng Yang
2008-11-24 6:32 ` [PATCH 6/9] KVM: Export ioapic_get_delivery_bitmask Sheng Yang
2008-11-24 6:32 ` [PATCH 7/9] KVM: Add assigned_device_msi_dispatch() Sheng Yang
2008-11-24 6:32 ` [PATCH 8/9] KVM: Enable MSI for device assignment Sheng Yang
2008-11-24 6:32 ` [PATCH 9/9] KVM: MSI to INTx translate Sheng Yang
2008-11-26 10:14 ` [PATCH 0/9][v6] Enable MSI for KVM Avi Kivity
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox