* [RFC][PATCH 0/10][v3] Enable MSI for KVM assigned device
@ 2008-10-30 8:20 Sheng Yang
2008-10-30 8:20 ` [PATCH 01/10] KVM: Move ack notifier register and IRQ sourcd ID request Sheng Yang
` (9 more replies)
0 siblings, 10 replies; 12+ messages in thread
From: Sheng Yang @ 2008-10-30 8:20 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm
Hi, Avi
Here is v3 for MSI on assigned devices.
Still not conclude userspace patch, but the patchset changes a lot since v2.
After discuss with Xiantao, we decide to reuse MSI dispatch function for x86
and IA64. I am working on that now. After get it done, I will send out v4.
Another significant change is, this patchset not only enable MSI for MSI
capable guests(patch 1-9), also enable MSI by default for all guests(patch
10). I implement a MSI to INTx convert in patch 10, which is a little tricky,
but don't have much trouble in theory (the only thing we are worried is about
device would use different "register" to indicate interrupt reason for INTx
mode and MSI mode, but didn't find this kind of device yet). We may need a
black/white list for device which can work in this way. This also avoid host
sharing interrupt trouble, and provide better scalability for the guest which
lacks of MSI capablility. The patch also provide non-sharing host INTx support
for legacy devices. So we suggest this can be a default solution for current
KVM device assignment support.
Comments are welcome!
--
regards
Yang, Sheng
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 01/10] KVM: Move ack notifier register and IRQ sourcd ID request
2008-10-30 8:20 [RFC][PATCH 0/10][v3] Enable MSI for KVM assigned device Sheng Yang
@ 2008-10-30 8:20 ` Sheng Yang
2008-10-30 8:20 ` [PATCH 02/10] KVM: Separate update irq to a single function Sheng Yang
` (8 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Sheng Yang @ 2008-10-30 8:20 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm, Sheng Yang
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 43fea09..3ecc5a8 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] 12+ messages in thread
* [PATCH 02/10] KVM: Separate update irq to a single function
2008-10-30 8:20 [RFC][PATCH 0/10][v3] Enable MSI for KVM assigned device Sheng Yang
2008-10-30 8:20 ` [PATCH 01/10] KVM: Move ack notifier register and IRQ sourcd ID request Sheng Yang
@ 2008-10-30 8:20 ` Sheng Yang
2008-10-30 8:20 ` [PATCH 03/10] KVM: Replace irq_requested with more generic irq_requested_type Sheng Yang
` (7 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Sheng Yang @ 2008-10-30 8:20 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm, Sheng Yang
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 3ecc5a8..ac1d652 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] 12+ messages in thread
* [PATCH 03/10] KVM: Replace irq_requested with more generic irq_requested_type
2008-10-30 8:20 [RFC][PATCH 0/10][v3] Enable MSI for KVM assigned device Sheng Yang
2008-10-30 8:20 ` [PATCH 01/10] KVM: Move ack notifier register and IRQ sourcd ID request Sheng Yang
2008-10-30 8:20 ` [PATCH 02/10] KVM: Separate update irq to a single function Sheng Yang
@ 2008-10-30 8:20 ` Sheng Yang
2008-10-30 8:20 ` [PATCH 04/10] KVM: Clean up assigned_device_update_irq Sheng Yang
` (6 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Sheng Yang @ 2008-10-30 8:20 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 bb92be2..f002f9b 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 ac1d652..6ca04ce 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(kvm, &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] 12+ messages in thread
* [PATCH 04/10] KVM: Clean up assigned_device_update_irq
2008-10-30 8:20 [RFC][PATCH 0/10][v3] Enable MSI for KVM assigned device Sheng Yang
` (2 preceding siblings ...)
2008-10-30 8:20 ` [PATCH 03/10] KVM: Replace irq_requested with more generic irq_requested_type Sheng Yang
@ 2008-10-30 8:20 ` Sheng Yang
2008-10-30 8:20 ` [PATCH 05/10] KVM: Add fields for MSI device assignment Sheng Yang
` (5 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Sheng Yang @ 2008-10-30 8:20 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 6ca04ce..ddfd7ac 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] 12+ messages in thread
* [PATCH 05/10] KVM: Add fields for MSI device assignment
2008-10-30 8:20 [RFC][PATCH 0/10][v3] Enable MSI for KVM assigned device Sheng Yang
` (3 preceding siblings ...)
2008-10-30 8:20 ` [PATCH 04/10] KVM: Clean up assigned_device_update_irq Sheng Yang
@ 2008-10-30 8:20 ` Sheng Yang
2008-10-30 8:20 ` [PATCH 06/10] KVM: Export ioapic_get_delivery_bitmask Sheng Yang
` (4 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Sheng Yang @ 2008-10-30 8:20 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 | 6 +++++-
include/linux/kvm_host.h | 4 ++++
2 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 44fd7fa..8ec74b8 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -506,11 +506,15 @@ struct kvm_assigned_irq {
__u32 host_irq;
__u32 guest_irq;
__u32 flags;
+ __u32 guest_msi_data;
+ __u32 guest_msi_addr;
union {
- __u32 reserved[12];
+ __u32 reserved[10];
};
};
#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 f002f9b..1cae239 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -307,8 +307,12 @@ struct kvm_assigned_dev_kernel {
int host_devfn;
int host_irq;
int guest_irq;
+ u32 guest_msi_addr;
+ u32 guest_msi_data;
#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] 12+ messages in thread
* [PATCH 06/10] KVM: Export ioapic_get_delivery_bitmask
2008-10-30 8:20 [RFC][PATCH 0/10][v3] Enable MSI for KVM assigned device Sheng Yang
` (4 preceding siblings ...)
2008-10-30 8:20 ` [PATCH 05/10] KVM: Add fields for MSI device assignment Sheng Yang
@ 2008-10-30 8:20 ` Sheng Yang
2008-10-30 8:20 ` [PATCH 07/10] x86: Add MSI delivery mode mask Sheng Yang
` (3 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Sheng Yang @ 2008-10-30 8:20 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 | 4 ++--
virt/kvm/ioapic.h | 2 ++
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index c8f939c..1e0ff8c 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 ioapic_get_delivery_bitmask(struct kvm_ioapic *ioapic, u8 dest,
+ u8 dest_mode)
{
u32 mask = 0;
int i;
diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h
index cd7ae76..42972f5 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 ioapic_get_delivery_bitmask(struct kvm_ioapic *ioapic, u8 dest,
+ u8 dest_mode);
#endif
--
1.5.4.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 07/10] x86: Add MSI delivery mode mask
2008-10-30 8:20 [RFC][PATCH 0/10][v3] Enable MSI for KVM assigned device Sheng Yang
` (5 preceding siblings ...)
2008-10-30 8:20 ` [PATCH 06/10] KVM: Export ioapic_get_delivery_bitmask Sheng Yang
@ 2008-10-30 8:20 ` Sheng Yang
2008-10-30 8:20 ` [PATCH 08/10] KVM: Add assigned_device_msi_dispatch() Sheng Yang
` (2 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Sheng Yang @ 2008-10-30 8:20 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm, Sheng Yang
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
include/asm-x86/msidef.h | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/include/asm-x86/msidef.h b/include/asm-x86/msidef.h
index 296f29c..579b09d 100644
--- a/include/asm-x86/msidef.h
+++ b/include/asm-x86/msidef.h
@@ -17,6 +17,8 @@
#define MSI_DATA_DELIVERY_MODE_SHIFT 8
#define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_MODE_SHIFT)
#define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_MODE_SHIFT)
+#define MSI_DATA_DELIVERY_FIXED_VAL 0
+#define MSI_DATA_DELIVERY_LOWPRI_VAL 1
#define MSI_DATA_LEVEL_SHIFT 14
#define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT)
--
1.5.4.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 08/10] KVM: Add assigned_device_msi_dispatch()
2008-10-30 8:20 [RFC][PATCH 0/10][v3] Enable MSI for KVM assigned device Sheng Yang
` (6 preceding siblings ...)
2008-10-30 8:20 ` [PATCH 07/10] x86: Add MSI delivery mode mask Sheng Yang
@ 2008-10-30 8:20 ` Sheng Yang
2008-10-30 8:56 ` Sheng Yang
2008-10-30 8:20 ` [PATCH 09/10] KVM: Enable MSI for device assignment Sheng Yang
2008-10-30 8:20 ` [PATCH 10/10] KVM: MSI to INTx translate Sheng Yang
9 siblings, 1 reply; 12+ messages in thread
From: Sheng Yang @ 2008-10-30 8:20 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.
(Any way to replace macro GET_VAL_FROM_SHIFT()?)
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
virt/kvm/kvm_main.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 45 insertions(+), 0 deletions(-)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index ddfd7ac..be0f943 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -46,6 +46,7 @@
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
+#include <asm/msidef.h>
#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
#include "coalesced_mmio.h"
@@ -78,6 +79,50 @@ static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
bool kvm_rebooting;
#ifdef KVM_CAP_DEVICE_ASSIGNMENT
+static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev)
+{
+#define GET_VAL_FROM_SHIFT(v, s) (((v) & (1 << s)) >> s)
+ int vcpu_id;
+ struct kvm_vcpu *vcpu;
+ struct kvm_ioapic *ioapic = ioapic_irqchip(dev->kvm);
+ u8 dest_id = MSI_ADDR_DEST_ID(dev->guest_msi_addr);
+ u8 vector = MSI_DATA_VECTOR(dev->guest_msi_data);
+ u8 dest_mode = GET_VAL_FROM_SHIFT(dev->guest_msi_addr,
+ MSI_ADDR_DEST_MODE_SHIFT);
+ u8 trig_mode = GET_VAL_FROM_SHIFT(dev->guest_msi_data,
+ MSI_DATA_TRIGGER_SHIFT);
+ u8 delivery_mode = GET_VAL_FROM_SHIFT(dev->guest_msi_data,
+ MSI_DATA_DELIVERY_MODE_SHIFT);
+ u32 deliver_bitmask;
+
+ BUG_ON(!ioapic);
+
+ deliver_bitmask = ioapic_get_delivery_bitmask(ioapic,
+ dest_id, dest_mode);
+ switch (delivery_mode) {
+ case MSI_DATA_DELIVERY_LOWPRI_VAL:
+ 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 MSI_DATA_DELIVERY_FIXED_VAL:
+ 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");
+ }
+}
+
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] 12+ messages in thread
* [PATCH 09/10] KVM: Enable MSI for device assignment
2008-10-30 8:20 [RFC][PATCH 0/10][v3] Enable MSI for KVM assigned device Sheng Yang
` (7 preceding siblings ...)
2008-10-30 8:20 ` [PATCH 08/10] KVM: Add assigned_device_msi_dispatch() Sheng Yang
@ 2008-10-30 8:20 ` Sheng Yang
2008-10-30 8:20 ` [PATCH 10/10] KVM: MSI to INTx translate Sheng Yang
9 siblings, 0 replies; 12+ messages in thread
From: Sheng Yang @ 2008-10-30 8:20 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm, Sheng Yang
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
virt/kvm/kvm_main.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 68 insertions(+), 6 deletions(-)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index be0f943..0f851ef 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -149,9 +149,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);
}
@@ -187,6 +193,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(kvm, &assigned_dev->ack_notifier);
kvm_free_irq_source_id(kvm, assigned_dev->irq_source_id);
@@ -232,6 +240,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;
@@ -255,6 +268,38 @@ static int assigned_device_update_intx(struct kvm *kvm,
return 0;
}
+static int assigned_device_update_msi(struct kvm *kvm,
+ struct kvm_assigned_dev_kernel *adev,
+ struct kvm_assigned_irq *airq)
+{
+ int r;
+
+ adev->guest_msi_addr = airq->guest_msi_addr;
+ 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;
+}
+
static int kvm_vm_ioctl_assign_irq(struct kvm *kvm,
struct kvm_assigned_irq
*assigned_irq)
@@ -291,9 +336,26 @@ 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) {
+ 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 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] 12+ messages in thread
* [PATCH 10/10] KVM: MSI to INTx translate
2008-10-30 8:20 [RFC][PATCH 0/10][v3] Enable MSI for KVM assigned device Sheng Yang
` (8 preceding siblings ...)
2008-10-30 8:20 ` [PATCH 09/10] KVM: Enable MSI for device assignment Sheng Yang
@ 2008-10-30 8:20 ` Sheng Yang
9 siblings, 0 replies; 12+ messages in thread
From: Sheng Yang @ 2008-10-30 8:20 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm, Sheng Yang
Now we use MSI as default one
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
virt/kvm/kvm_main.c | 50 +++++++++++++++++++++++++++-----------------------
1 files changed, 27 insertions(+), 23 deletions(-)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 0f851ef..34b5d2f 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -233,6 +233,8 @@ static int assigned_device_update_intx(struct kvm *kvm,
struct kvm_assigned_dev_kernel *adev,
struct kvm_assigned_irq *airq)
{
+ BUG_ON(!!adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI);
+
adev->guest_irq = airq->guest_irq;
adev->ack_notifier.gsi = airq->guest_irq;
@@ -240,11 +242,6 @@ 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;
@@ -272,31 +269,32 @@ static int assigned_device_update_msi(struct kvm *kvm,
struct kvm_assigned_dev_kernel *adev,
struct kvm_assigned_irq *airq)
{
- int r;
+ BUG_ON(!!adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_INTX);
- adev->guest_msi_addr = airq->guest_msi_addr;
- adev->guest_msi_data = airq->guest_msi_data;
- adev->ack_notifier.gsi = -1;
+ if (airq->flags & KVM_DEV_IRQ_ASSIGN_ENABLE_MSI) {
+ adev->irq_requested_type |= KVM_ASSIGNED_DEV_GUEST_MSI;
+ adev->irq_requested_type &= ~KVM_ASSIGNED_DEV_GUEST_INTX;
+ adev->guest_msi_addr = airq->guest_msi_addr;
+ adev->guest_msi_data = airq->guest_msi_data;
+ adev->ack_notifier.gsi = -1;
+ } else {
+ 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;
-
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;
+ adev->irq_requested_type |= KVM_ASSIGNED_DEV_HOST_MSI;
return 0;
}
@@ -333,10 +331,15 @@ static int kvm_vm_ioctl_assign_irq(struct kvm *kvm,
goto out_release;
else
match->irq_source_id = r;
+
+ /* Determine host device irq type, we can know the
+ * result from dev->msi_enabled */
+ pci_enable_msi(match->dev);
}
}
- if (assigned_irq->flags & KVM_DEV_IRQ_ASSIGN_ENABLE_MSI) {
+ if (match->dev->msi_enabled) {
+ /* Device support MSI */
r = assigned_device_update_msi(kvm, match, assigned_irq);
if (r) {
printk(KERN_WARNING "kvm: failed to enable "
@@ -344,9 +347,10 @@ static int kvm_vm_ioctl_assign_irq(struct kvm *kvm,
goto out_release;
}
} 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;
+ /* Device only support MSI but can't enable */
+ 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);
--
1.5.4.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 08/10] KVM: Add assigned_device_msi_dispatch()
2008-10-30 8:20 ` [PATCH 08/10] KVM: Add assigned_device_msi_dispatch() Sheng Yang
@ 2008-10-30 8:56 ` Sheng Yang
0 siblings, 0 replies; 12+ messages in thread
From: Sheng Yang @ 2008-10-30 8:56 UTC (permalink / raw)
To: kvm; +Cc: Avi Kivity
On Thursday 30 October 2008 16:20:16 Sheng Yang wrote:
> The function is used to dispatch MSI to lapic according to MSI message
> address and message data.
>
> (Any way to replace macro GET_VAL_FROM_SHIFT()?)
>
> Signed-off-by: Sheng Yang <sheng@linux.intel.com>
> ---
> virt/kvm/kvm_main.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 45 insertions(+), 0 deletions(-)
>
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index ddfd7ac..be0f943 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -46,6 +46,7 @@
> #include <asm/io.h>
> #include <asm/uaccess.h>
> #include <asm/pgtable.h>
> +#include <asm/msidef.h>
>
> #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
> #include "coalesced_mmio.h"
> @@ -78,6 +79,50 @@ static long kvm_vcpu_ioctl(struct file *file, unsigned
> int ioctl, bool kvm_rebooting;
>
> #ifdef KVM_CAP_DEVICE_ASSIGNMENT
> +static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel
> *dev) +{
> +#define GET_VAL_FROM_SHIFT(v, s) (((v) & (1 << s)) >> s)
> + int vcpu_id;
> + struct kvm_vcpu *vcpu;
> + struct kvm_ioapic *ioapic = ioapic_irqchip(dev->kvm);
> + u8 dest_id = MSI_ADDR_DEST_ID(dev->guest_msi_addr);
> + u8 vector = MSI_DATA_VECTOR(dev->guest_msi_data);
Oops... These two macros are wrong used, would be fixed in next version.
--
regards
Yang, Sheng
> + u8 dest_mode = GET_VAL_FROM_SHIFT(dev->guest_msi_addr,
> + MSI_ADDR_DEST_MODE_SHIFT);
> + u8 trig_mode = GET_VAL_FROM_SHIFT(dev->guest_msi_data,
> + MSI_DATA_TRIGGER_SHIFT);
> + u8 delivery_mode = GET_VAL_FROM_SHIFT(dev->guest_msi_data,
> + MSI_DATA_DELIVERY_MODE_SHIFT);
> + u32 deliver_bitmask;
> +
> + BUG_ON(!ioapic);
> +
> + deliver_bitmask = ioapic_get_delivery_bitmask(ioapic,
> + dest_id, dest_mode);
> + switch (delivery_mode) {
> + case MSI_DATA_DELIVERY_LOWPRI_VAL:
> + 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 MSI_DATA_DELIVERY_FIXED_VAL:
> + 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");
> + }
> +}
> +
> static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct
> list_head *head, int assigned_dev_id)
> {
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2008-10-30 8:59 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-10-30 8:20 [RFC][PATCH 0/10][v3] Enable MSI for KVM assigned device Sheng Yang
2008-10-30 8:20 ` [PATCH 01/10] KVM: Move ack notifier register and IRQ sourcd ID request Sheng Yang
2008-10-30 8:20 ` [PATCH 02/10] KVM: Separate update irq to a single function Sheng Yang
2008-10-30 8:20 ` [PATCH 03/10] KVM: Replace irq_requested with more generic irq_requested_type Sheng Yang
2008-10-30 8:20 ` [PATCH 04/10] KVM: Clean up assigned_device_update_irq Sheng Yang
2008-10-30 8:20 ` [PATCH 05/10] KVM: Add fields for MSI device assignment Sheng Yang
2008-10-30 8:20 ` [PATCH 06/10] KVM: Export ioapic_get_delivery_bitmask Sheng Yang
2008-10-30 8:20 ` [PATCH 07/10] x86: Add MSI delivery mode mask Sheng Yang
2008-10-30 8:20 ` [PATCH 08/10] KVM: Add assigned_device_msi_dispatch() Sheng Yang
2008-10-30 8:56 ` Sheng Yang
2008-10-30 8:20 ` [PATCH 09/10] KVM: Enable MSI for device assignment Sheng Yang
2008-10-30 8:20 ` [PATCH 10/10] KVM: MSI to INTx translate Sheng Yang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox