* [PATCH 0/7][v6] GSI route layer for MSI/MSI-X
@ 2009-01-13 9:58 Sheng Yang
2009-01-13 9:58 ` [PATCH 1/7] KVM: Add a route layer to convert MSI message to GSI Sheng Yang
` (6 more replies)
0 siblings, 7 replies; 9+ messages in thread
From: Sheng Yang @ 2009-01-13 9:58 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: kvm
Update from v5:
Addressed Marcelo and Avi's comments, also change ioctl back to add/delete
style one.
--
regards
Yang, Sheng
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/7] KVM: Add a route layer to convert MSI message to GSI
2009-01-13 9:58 [PATCH 0/7][v6] GSI route layer for MSI/MSI-X Sheng Yang
@ 2009-01-13 9:58 ` Sheng Yang
2009-01-13 9:58 ` [PATCH 2/7] KVM: Using gsi route for MSI device assignment Sheng Yang
` (5 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Sheng Yang @ 2009-01-13 9:58 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: kvm, Sheng Yang
Avi's purpose, to use single kvm_set_irq() to deal with all interrupt, including
MSI. So here is it.
struct gsi_route_entry is a mapping from a special gsi(with
KVM_GSI_MSG_ENTRY_MASK) to MSI/MSI-X message address/data. And the struct can
also be extended for other purpose.
Now we support up to 128 gsi_route_entry mapping, and gsi is allocated by kernel and
provide two ioctls to userspace, which is more flexiable.
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
include/linux/kvm.h | 24 +++++++++++++++
include/linux/kvm_host.h | 22 +++++++++++++
virt/kvm/irq_comm.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++
virt/kvm/kvm_main.c | 65 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 185 insertions(+), 0 deletions(-)
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 71c150f..ba8ab1c 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -399,6 +399,9 @@ struct kvm_trace_rec {
#if defined(CONFIG_X86)
#define KVM_CAP_REINJECT_CONTROL 24
#endif
+#if defined(CONFIG_X86)
+#define KVM_CAP_GSI_ROUTE 25
+#endif
/*
* ioctls for VM fds
@@ -433,6 +436,10 @@ struct kvm_trace_rec {
#define KVM_ASSIGN_IRQ _IOR(KVMIO, 0x70, \
struct kvm_assigned_irq)
#define KVM_REINJECT_CONTROL _IO(KVMIO, 0x71)
+#define KVM_REQUEST_GSI_ROUTE _IOWR(KVMIO, 0x72, \
+ struct kvm_gsi_route_entry)
+#define KVM_FREE_GSI_ROUTE _IOR(KVMIO, 0x73, \
+ struct kvm_gsi_route_entry)
/*
* ioctls for vcpu fds
@@ -553,4 +560,21 @@ struct kvm_assigned_irq {
#define KVM_DEV_IRQ_ASSIGN_MSI_ACTION KVM_DEV_IRQ_ASSIGN_ENABLE_MSI
#define KVM_DEV_IRQ_ASSIGN_ENABLE_MSI (1 << 0)
+#define KVM_GSI_ROUTE_TYPE_MSI 0x1
+
+struct kvm_gsi_route_entry {
+ __u32 gsi;
+ __u32 type;
+ __u32 flags;
+ __u32 reserved;
+ union {
+ struct {
+ __u32 addr_lo;
+ __u32 addr_hi;
+ __u32 data;
+ } msi;
+ __u32 padding[8];
+ };
+};
+
#endif
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index a8bcad0..647a6bc 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -136,6 +136,9 @@ struct kvm {
unsigned long mmu_notifier_seq;
long mmu_notifier_count;
#endif
+ struct hlist_head gsi_route_list;
+#define KVM_NR_GSI_ROUTE_ENTRIES 128
+ DECLARE_BITMAP(gsi_route_bitmap, KVM_NR_GSI_ROUTE_ENTRIES);
};
/* The guest did something we don't support. */
@@ -336,6 +339,18 @@ void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq,
struct kvm_irq_mask_notifier *kimn);
void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask);
+#define KVM_GSI_ROUTE_ENTRY_MASK 0x1000000ull
+struct kvm_gsi_route_kernel_entry {
+ u32 gsi;
+ u32 type;
+ u32 flags;
+ u32 reserved;
+ union {
+ struct msi_msg msi;
+ };
+ struct hlist_node link;
+};
+
void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level);
void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi);
void kvm_register_irq_ack_notifier(struct kvm *kvm,
@@ -343,6 +358,13 @@ void kvm_register_irq_ack_notifier(struct kvm *kvm,
void kvm_unregister_irq_ack_notifier(struct kvm_irq_ack_notifier *kian);
int kvm_request_irq_source_id(struct kvm *kvm);
void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id);
+int kvm_update_gsi_route(struct kvm *kvm,
+ struct kvm_gsi_route_kernel_entry *entry);
+struct kvm_gsi_route_kernel_entry *kvm_find_gsi_route_entry(struct kvm *kvm,
+ u32 gsi);
+void kvm_free_gsi_route(struct kvm *kvm,
+ struct kvm_gsi_route_kernel_entry *entry);
+void kvm_free_gsi_route_list(struct kvm *kvm);
#ifdef CONFIG_DMAR
int kvm_iommu_map_pages(struct kvm *kvm, gfn_t base_gfn,
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index 5162a41..8f49113 100644
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -123,3 +123,77 @@ void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask)
kimn->func(kimn, mask);
}
+int kvm_update_gsi_route(struct kvm *kvm,
+ struct kvm_gsi_route_kernel_entry *entry)
+{
+ struct kvm_gsi_route_kernel_entry *found_entry, *new_entry;
+ int r, gsi;
+
+ mutex_lock(&kvm->lock);
+ /* Find whether we need a update or a new entry */
+ found_entry = kvm_find_gsi_route_entry(kvm, entry->gsi);
+ if (found_entry)
+ *found_entry = *entry;
+ else {
+ gsi = find_first_zero_bit(kvm->gsi_route_bitmap,
+ KVM_NR_GSI_ROUTE_ENTRIES);
+ if (gsi >= KVM_NR_GSI_ROUTE_ENTRIES) {
+ r = -ENOSPC;
+ goto out;
+ }
+ new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL);
+ if (!new_entry) {
+ r = -ENOMEM;
+ goto out;
+ }
+ entry->gsi = gsi | KVM_GSI_ROUTE_ENTRY_MASK;
+ *new_entry = *entry;
+ __set_bit(gsi, kvm->gsi_route_bitmap);
+ hlist_add_head(&new_entry->link, &kvm->gsi_route_list);
+ }
+ r = 0;
+out:
+ mutex_unlock(&kvm->lock);
+ return r;
+}
+
+/* Call with kvm->lock hold */
+struct kvm_gsi_route_kernel_entry *kvm_find_gsi_route_entry(struct kvm *kvm,
+ u32 gsi)
+{
+ struct kvm_gsi_route_kernel_entry *entry;
+ struct hlist_node *n;
+
+ if (!(gsi & KVM_GSI_ROUTE_ENTRY_MASK))
+ return NULL;
+ hlist_for_each_entry(entry, n, &kvm->gsi_route_list, link)
+ if (entry->gsi == gsi)
+ goto out;
+ entry = NULL;
+out:
+ return entry;
+}
+
+/* Call with kvm->lock hold */
+void kvm_free_gsi_route(struct kvm *kvm,
+ struct kvm_gsi_route_kernel_entry *entry)
+{
+ if (!entry)
+ return;
+ __clear_bit(entry->gsi & ~KVM_GSI_ROUTE_ENTRY_MASK,
+ kvm->gsi_route_bitmap);
+ hlist_del(&entry->link);
+ kfree(entry);
+}
+
+void kvm_free_gsi_route_list(struct kvm *kvm)
+{
+ struct kvm_gsi_route_kernel_entry *entry;
+ struct hlist_node *pos, *n;
+
+ mutex_lock(&kvm->lock);
+ hlist_for_each_entry_safe(entry, pos, n, &kvm->gsi_route_list, link)
+ kvm_free_gsi_route(kvm, entry);
+ mutex_unlock(&kvm->lock);
+}
+
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 61688a6..7fe1e43 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -839,6 +839,7 @@ static struct kvm *kvm_create_vm(void)
#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
kvm_coalesced_mmio_init(kvm);
#endif
+ INIT_HLIST_HEAD(&kvm->gsi_route_list);
out:
return kvm;
}
@@ -877,6 +878,7 @@ static void kvm_destroy_vm(struct kvm *kvm)
struct mm_struct *mm = kvm->mm;
kvm_arch_sync_events(kvm);
+ kvm_free_gsi_route_list(kvm);
spin_lock(&kvm_lock);
list_del(&kvm->vm_list);
spin_unlock(&kvm_lock);
@@ -1605,6 +1607,44 @@ static int kvm_vcpu_ioctl_set_sigmask(struct kvm_vcpu *vcpu, sigset_t *sigset)
return 0;
}
+static int kvm_vm_ioctl_request_gsi_route(struct kvm *kvm,
+ struct kvm_gsi_route_entry *guest_entry)
+{
+ struct kvm_gsi_route_kernel_entry entry;
+ int r;
+
+ entry.gsi = guest_entry->gsi;
+ entry.type = guest_entry->type;
+ entry.flags = guest_entry->flags;
+ if (entry.type == KVM_GSI_ROUTE_TYPE_MSI) {
+ entry.msi.address_lo = guest_entry->msi.addr_lo;
+ entry.msi.address_hi = guest_entry->msi.addr_hi;
+ entry.msi.data = guest_entry->msi.data;
+ }
+ r = kvm_update_gsi_route(kvm, &entry);
+ if (r == 0)
+ guest_entry->gsi = entry.gsi;
+ return r;
+}
+
+static int kvm_vm_ioctl_free_gsi_route(struct kvm *kvm,
+ struct kvm_gsi_route_entry *guest_entry)
+{
+ struct kvm_gsi_route_kernel_entry *entry;
+ int r;
+
+ mutex_lock(&kvm->lock);
+ entry = kvm_find_gsi_route_entry(kvm, guest_entry->gsi);
+ if (!entry) {
+ r = -EINVAL;
+ goto out;
+ }
+ kvm_free_gsi_route(kvm, entry);
+out:
+ mutex_unlock(&kvm->lock);
+ return r;
+}
+
static long kvm_vcpu_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
{
@@ -1887,6 +1927,31 @@ static long kvm_vm_ioctl(struct file *filp,
break;
}
#endif
+ case KVM_REQUEST_GSI_ROUTE: {
+ struct kvm_gsi_route_entry guest_entry;
+ r = -EFAULT;
+ if (copy_from_user(&guest_entry, argp, sizeof guest_entry))
+ goto out;
+ r = kvm_vm_ioctl_request_gsi_route(kvm, &guest_entry);
+ if (r)
+ goto out;
+ r = -EFAULT;
+ if (copy_to_user(argp, &guest_entry,
+ sizeof(struct kvm_gsi_route_entry)))
+ goto out;
+ r = 0;
+ break;
+ }
+ case KVM_FREE_GSI_ROUTE: {
+ struct kvm_gsi_route_entry guest_entry;
+ r = -EFAULT;
+ if (copy_from_user(&guest_entry, argp, sizeof guest_entry))
+ goto out;
+ r = kvm_vm_ioctl_free_gsi_route(kvm, &guest_entry);
+ if (r)
+ goto out;
+ break;
+ }
default:
r = kvm_arch_vm_ioctl(filp, ioctl, arg);
}
--
1.5.4.5
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/7] KVM: Using gsi route for MSI device assignment
2009-01-13 9:58 [PATCH 0/7][v6] GSI route layer for MSI/MSI-X Sheng Yang
2009-01-13 9:58 ` [PATCH 1/7] KVM: Add a route layer to convert MSI message to GSI Sheng Yang
@ 2009-01-13 9:58 ` Sheng Yang
2009-01-13 9:58 ` [PATCH 3/7] KVM: Improve MSI dispatch function Sheng Yang
` (4 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Sheng Yang @ 2009-01-13 9:58 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: kvm, Sheng Yang
Convert MSI userspace interface to support gsi_msg mapping(and nobody should
be the user of the old interface...).
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
include/linux/kvm_host.h | 1 -
virt/kvm/kvm_main.c | 79 ++++++++++++++++++++++++++--------------------
2 files changed, 45 insertions(+), 35 deletions(-)
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 647a6bc..8ba7dcf 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -316,7 +316,6 @@ struct kvm_assigned_dev_kernel {
int host_irq;
bool host_irq_disabled;
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)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 7fe1e43..f3d5958 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -92,44 +92,56 @@ 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);
+ struct kvm_gsi_route_kernel_entry *gsi_entry;
+ int dest_id, vector, dest_mode, trig_mode, delivery_mode;
u32 deliver_bitmask;
BUG_ON(!ioapic);
- deliver_bitmask = kvm_ioapic_get_delivery_bitmask(ioapic,
+ gsi_entry = kvm_find_gsi_route_entry(dev->kvm, dev->guest_irq);
+ if (!gsi_entry) {
+ printk(KERN_WARNING "kvm: fail to find correlated gsi entry\n");
+ return;
+ }
+
+ if (gsi_entry->type == KVM_GSI_ROUTE_TYPE_MSI) {
+ dest_id = (gsi_entry->msi.address_lo & MSI_ADDR_DEST_ID_MASK)
+ >> MSI_ADDR_DEST_ID_SHIFT;
+ vector = (gsi_entry->msi.data & MSI_DATA_VECTOR_MASK)
+ >> MSI_DATA_VECTOR_SHIFT;
+ dest_mode = test_bit(MSI_ADDR_DEST_MODE_SHIFT,
+ (unsigned long *)&gsi_entry->msi.address_lo);
+ trig_mode = test_bit(MSI_DATA_TRIGGER_SHIFT,
+ (unsigned long *)&gsi_entry->msi.data);
+ delivery_mode = test_bit(MSI_DATA_DELIVERY_MODE_SHIFT,
+ (unsigned long *)&gsi_entry->msi.data);
+ 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)
+ /* 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:
+ break;
}
- break;
- default:
- printk(KERN_INFO "kvm: unsupported MSI delivery mode\n");
}
}
#else
@@ -331,17 +343,16 @@ static int assigned_device_update_msi(struct kvm *kvm,
{
int r;
+ adev->guest_irq = airq->guest_irq;
+
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;
} else {
/*
--
1.5.4.5
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/7] KVM: Improve MSI dispatch function
2009-01-13 9:58 [PATCH 0/7][v6] GSI route layer for MSI/MSI-X Sheng Yang
2009-01-13 9:58 ` [PATCH 1/7] KVM: Add a route layer to convert MSI message to GSI Sheng Yang
2009-01-13 9:58 ` [PATCH 2/7] KVM: Using gsi route for MSI device assignment Sheng Yang
@ 2009-01-13 9:58 ` Sheng Yang
2009-01-13 9:58 ` [PATCH 4/7] KVM: Using ioapic_irqchip() macro for kvm_set_irq Sheng Yang
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Sheng Yang @ 2009-01-13 9:58 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: kvm, Sheng Yang
Prepare to merge with kvm_set_irq().
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
virt/kvm/kvm_main.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index f3d5958..b0b97ba 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -87,7 +87,7 @@ static bool kvm_rebooting;
#ifdef KVM_CAP_DEVICE_ASSIGNMENT
#ifdef CONFIG_X86
-static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev)
+static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev, u32 gsi)
{
int vcpu_id;
struct kvm_vcpu *vcpu;
@@ -98,7 +98,7 @@ static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev)
BUG_ON(!ioapic);
- gsi_entry = kvm_find_gsi_route_entry(dev->kvm, dev->guest_irq);
+ gsi_entry = kvm_find_gsi_route_entry(dev->kvm, gsi);
if (!gsi_entry) {
printk(KERN_WARNING "kvm: fail to find correlated gsi entry\n");
return;
@@ -145,7 +145,7 @@ static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev)
}
}
#else
-static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev) {}
+static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev, u32 gsi) {}
#endif
static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *head,
@@ -180,7 +180,7 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work)
assigned_dev->guest_irq, 1);
else if (assigned_dev->irq_requested_type &
KVM_ASSIGNED_DEV_GUEST_MSI) {
- assigned_device_msi_dispatch(assigned_dev);
+ assigned_device_msi_dispatch(assigned_dev, assigned_dev->guest_irq);
enable_irq(assigned_dev->host_irq);
assigned_dev->host_irq_disabled = false;
}
--
1.5.4.5
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/7] KVM: Using ioapic_irqchip() macro for kvm_set_irq
2009-01-13 9:58 [PATCH 0/7][v6] GSI route layer for MSI/MSI-X Sheng Yang
` (2 preceding siblings ...)
2009-01-13 9:58 ` [PATCH 3/7] KVM: Improve MSI dispatch function Sheng Yang
@ 2009-01-13 9:58 ` Sheng Yang
2009-01-13 9:58 ` [PATCH 5/7] KVM: Merge MSI handling to kvm_set_irq Sheng Yang
` (2 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Sheng Yang @ 2009-01-13 9:58 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: kvm, Sheng Yang
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
virt/kvm/irq_comm.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index 8f49113..0c3266a 100644
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -39,7 +39,7 @@ void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level)
* IOAPIC. So set the bit in both. The guest will ignore
* writes to the unused one.
*/
- kvm_ioapic_set_irq(kvm->arch.vioapic, irq, !!(*irq_state));
+ kvm_ioapic_set_irq(ioapic_irqchip(kvm), irq, !!(*irq_state));
#ifdef CONFIG_X86
kvm_pic_set_irq(pic_irqchip(kvm), irq, !!(*irq_state));
#endif
--
1.5.4.5
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 5/7] KVM: Merge MSI handling to kvm_set_irq
2009-01-13 9:58 [PATCH 0/7][v6] GSI route layer for MSI/MSI-X Sheng Yang
` (3 preceding siblings ...)
2009-01-13 9:58 ` [PATCH 4/7] KVM: Using ioapic_irqchip() macro for kvm_set_irq Sheng Yang
@ 2009-01-13 9:58 ` Sheng Yang
2009-01-13 9:58 ` [PATCH 6/7] KVM: Split IOAPIC structure Sheng Yang
2009-01-13 9:58 ` [PATCH 7/7] KVM: Unified the delivery of IOAPIC and MSI Sheng Yang
6 siblings, 0 replies; 9+ messages in thread
From: Sheng Yang @ 2009-01-13 9:58 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: kvm, Sheng Yang
Using kvm_set_irq to handle all interrupt injection.
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
include/linux/kvm_host.h | 2 +-
virt/kvm/irq_comm.c | 79 +++++++++++++++++++++++++++++++++++++++++++--
virt/kvm/kvm_main.c | 78 +++------------------------------------------
3 files changed, 81 insertions(+), 78 deletions(-)
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 8ba7dcf..440409f 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -350,7 +350,7 @@ struct kvm_gsi_route_kernel_entry {
struct hlist_node link;
};
-void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level);
+void kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 gsi, int level);
void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi);
void kvm_register_irq_ack_notifier(struct kvm *kvm,
struct kvm_irq_ack_notifier *kian);
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index 0c3266a..9e6c622 100644
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -24,10 +24,81 @@
#include "ioapic.h"
+#ifdef CONFIG_X86
+#include <asm/msidef.h>
+#endif
+
+static void gsi_dispatch(struct kvm *kvm, u32 gsi)
+{
+ int vcpu_id;
+ struct kvm_vcpu *vcpu;
+ struct kvm_ioapic *ioapic = ioapic_irqchip(kvm);
+ struct kvm_gsi_route_kernel_entry *gsi_entry;
+ int dest_id, vector, dest_mode, trig_mode, delivery_mode;
+ u32 deliver_bitmask;
+
+ BUG_ON(!ioapic);
+
+ gsi_entry = kvm_find_gsi_route_entry(kvm, gsi);
+ if (!gsi_entry) {
+ printk(KERN_WARNING "kvm: fail to find correlated gsi entry\n");
+ return;
+ }
+
+#ifdef CONFIG_X86
+ if (gsi_entry->type == KVM_GSI_ROUTE_TYPE_MSI) {
+ dest_id = (gsi_entry->msi.address_lo & MSI_ADDR_DEST_ID_MASK)
+ >> MSI_ADDR_DEST_ID_SHIFT;
+ vector = (gsi_entry->msi.data & MSI_DATA_VECTOR_MASK)
+ >> MSI_DATA_VECTOR_SHIFT;
+ dest_mode = test_bit(MSI_ADDR_DEST_MODE_SHIFT,
+ (unsigned long *)&gsi_entry->msi.address_lo);
+ trig_mode = test_bit(MSI_DATA_TRIGGER_SHIFT,
+ (unsigned long *)&gsi_entry->msi.data);
+ delivery_mode = test_bit(MSI_DATA_DELIVERY_MODE_SHIFT,
+ (unsigned long *)&gsi_entry->msi.data);
+ 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:
+ break;
+ }
+ }
+#endif /* CONFIG_X86 */
+}
+
/* This should be called with the kvm->lock mutex held */
-void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level)
+void kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 gsi, int level)
{
- unsigned long *irq_state = (unsigned long *)&kvm->arch.irq_states[irq];
+ unsigned long *irq_state;
+
+ if (gsi & KVM_GSI_ROUTE_ENTRY_MASK) {
+ gsi_dispatch(kvm, gsi);
+ return;
+ }
+
+ irq_state = (unsigned long *)&kvm->arch.irq_states[gsi];
/* Logical OR for level trig interrupt */
if (level)
@@ -39,9 +110,9 @@ void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level)
* IOAPIC. So set the bit in both. The guest will ignore
* writes to the unused one.
*/
- kvm_ioapic_set_irq(ioapic_irqchip(kvm), irq, !!(*irq_state));
+ kvm_ioapic_set_irq(ioapic_irqchip(kvm), gsi, !!(*irq_state));
#ifdef CONFIG_X86
- kvm_pic_set_irq(pic_irqchip(kvm), irq, !!(*irq_state));
+ kvm_pic_set_irq(pic_irqchip(kvm), gsi, !!(*irq_state));
#endif
}
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index b0b97ba..8dba0b2 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -47,10 +47,6 @@
#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
@@ -86,68 +82,6 @@ static bool kvm_rebooting;
#ifdef KVM_CAP_DEVICE_ASSIGNMENT
-#ifdef CONFIG_X86
-static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev, u32 gsi)
-{
- int vcpu_id;
- struct kvm_vcpu *vcpu;
- struct kvm_ioapic *ioapic = ioapic_irqchip(dev->kvm);
- struct kvm_gsi_route_kernel_entry *gsi_entry;
- int dest_id, vector, dest_mode, trig_mode, delivery_mode;
- u32 deliver_bitmask;
-
- BUG_ON(!ioapic);
-
- gsi_entry = kvm_find_gsi_route_entry(dev->kvm, gsi);
- if (!gsi_entry) {
- printk(KERN_WARNING "kvm: fail to find correlated gsi entry\n");
- return;
- }
-
- if (gsi_entry->type == KVM_GSI_ROUTE_TYPE_MSI) {
- dest_id = (gsi_entry->msi.address_lo & MSI_ADDR_DEST_ID_MASK)
- >> MSI_ADDR_DEST_ID_SHIFT;
- vector = (gsi_entry->msi.data & MSI_DATA_VECTOR_MASK)
- >> MSI_DATA_VECTOR_SHIFT;
- dest_mode = test_bit(MSI_ADDR_DEST_MODE_SHIFT,
- (unsigned long *)&gsi_entry->msi.address_lo);
- trig_mode = test_bit(MSI_DATA_TRIGGER_SHIFT,
- (unsigned long *)&gsi_entry->msi.data);
- delivery_mode = test_bit(MSI_DATA_DELIVERY_MODE_SHIFT,
- (unsigned long *)&gsi_entry->msi.data);
- 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:
- break;
- }
- }
-}
-#else
-static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev, u32 gsi) {}
-#endif
-
static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *head,
int assigned_dev_id)
{
@@ -174,13 +108,11 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work)
* finer-grained lock, update this
*/
mutex_lock(&assigned_dev->kvm->lock);
- 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, assigned_dev->guest_irq);
+
+ 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_MSI) {
enable_irq(assigned_dev->host_irq);
assigned_dev->host_irq_disabled = false;
}
--
1.5.4.5
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 6/7] KVM: Split IOAPIC structure
2009-01-13 9:58 [PATCH 0/7][v6] GSI route layer for MSI/MSI-X Sheng Yang
` (4 preceding siblings ...)
2009-01-13 9:58 ` [PATCH 5/7] KVM: Merge MSI handling to kvm_set_irq Sheng Yang
@ 2009-01-13 9:58 ` Sheng Yang
2009-01-13 9:58 ` [PATCH 7/7] KVM: Unified the delivery of IOAPIC and MSI Sheng Yang
6 siblings, 0 replies; 9+ messages in thread
From: Sheng Yang @ 2009-01-13 9:58 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: kvm, Sheng Yang
Prepared for reuse ioapic_redir_entry for MSI.
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
include/linux/kvm_types.h | 17 +++++++++++++++++
virt/kvm/ioapic.c | 6 +++---
virt/kvm/ioapic.h | 17 +----------------
3 files changed, 21 insertions(+), 19 deletions(-)
diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
index 5f4a18c..46e3d8d 100644
--- a/include/linux/kvm_types.h
+++ b/include/linux/kvm_types.h
@@ -52,4 +52,21 @@ struct kvm_pio_request {
int rep;
};
+union kvm_ioapic_redirect_entry {
+ u64 bits;
+ struct {
+ u8 vector;
+ u8 delivery_mode:3;
+ u8 dest_mode:1;
+ u8 delivery_status:1;
+ u8 polarity:1;
+ u8 remote_irr:1;
+ u8 trig_mode:1;
+ u8 mask:1;
+ u8 reserve:7;
+ u8 reserved[4];
+ u8 dest_id;
+ } fields;
+};
+
#endif /* __KVM_TYPES_H__ */
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index e85a2bc..b6530e9 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -85,7 +85,7 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic,
static void ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx)
{
- union ioapic_redir_entry *pent;
+ union kvm_ioapic_redirect_entry *pent;
pent = &ioapic->redirtbl[idx];
@@ -277,7 +277,7 @@ void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
{
u32 old_irr = ioapic->irr;
u32 mask = 1 << irq;
- union ioapic_redir_entry entry;
+ union kvm_ioapic_redirect_entry entry;
if (irq >= 0 && irq < IOAPIC_NUM_PINS) {
entry = ioapic->redirtbl[irq];
@@ -296,7 +296,7 @@ void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int gsi,
int trigger_mode)
{
- union ioapic_redir_entry *ent;
+ union kvm_ioapic_redirect_entry *ent;
ent = &ioapic->redirtbl[gsi];
diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h
index 49c9581..ee5b0bd 100644
--- a/virt/kvm/ioapic.h
+++ b/virt/kvm/ioapic.h
@@ -40,22 +40,7 @@ struct kvm_ioapic {
u32 id;
u32 irr;
u32 pad;
- union ioapic_redir_entry {
- u64 bits;
- struct {
- u8 vector;
- u8 delivery_mode:3;
- u8 dest_mode:1;
- u8 delivery_status:1;
- u8 polarity:1;
- u8 remote_irr:1;
- u8 trig_mode:1;
- u8 mask:1;
- u8 reserve:7;
- u8 reserved[4];
- u8 dest_id;
- } fields;
- } redirtbl[IOAPIC_NUM_PINS];
+ union kvm_ioapic_redirect_entry redirtbl[IOAPIC_NUM_PINS];
struct kvm_io_device dev;
struct kvm *kvm;
void (*ack_notifier)(void *opaque, int irq);
--
1.5.4.5
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 7/7] KVM: Unified the delivery of IOAPIC and MSI
2009-01-13 9:58 [PATCH 0/7][v6] GSI route layer for MSI/MSI-X Sheng Yang
` (5 preceding siblings ...)
2009-01-13 9:58 ` [PATCH 6/7] KVM: Split IOAPIC structure Sheng Yang
@ 2009-01-13 9:58 ` Sheng Yang
6 siblings, 0 replies; 9+ messages in thread
From: Sheng Yang @ 2009-01-13 9:58 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: kvm, Sheng Yang
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
include/linux/kvm_host.h | 3 ++
virt/kvm/ioapic.c | 84 ++++++++++++++++----------------------------
virt/kvm/irq_comm.c | 87 ++++++++++++++++++++++++++++------------------
3 files changed, 87 insertions(+), 87 deletions(-)
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 440409f..b0d5a95 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -350,6 +350,9 @@ struct kvm_gsi_route_kernel_entry {
struct hlist_node link;
};
+void kvm_get_intr_delivery_bitmask(struct kvm_ioapic *ioapic,
+ union kvm_ioapic_redirect_entry *entry,
+ u32 *deliver_bitmask);
void kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 gsi, int level);
void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi);
void kvm_register_irq_ack_notifier(struct kvm *kvm,
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index b6530e9..951df12 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -200,75 +200,53 @@ u32 kvm_ioapic_get_delivery_bitmask(struct kvm_ioapic *ioapic, u8 dest,
static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
{
- u8 dest = ioapic->redirtbl[irq].fields.dest_id;
- u8 dest_mode = ioapic->redirtbl[irq].fields.dest_mode;
- u8 delivery_mode = ioapic->redirtbl[irq].fields.delivery_mode;
- u8 vector = ioapic->redirtbl[irq].fields.vector;
- u8 trig_mode = ioapic->redirtbl[irq].fields.trig_mode;
+ union kvm_ioapic_redirect_entry entry = ioapic->redirtbl[irq];
u32 deliver_bitmask;
struct kvm_vcpu *vcpu;
int vcpu_id, r = 0;
ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x "
"vector=%x trig_mode=%x\n",
- dest, dest_mode, delivery_mode, vector, trig_mode);
+ entry.fields.dest, entry.fields.dest_mode,
+ entry.fields.delivery_mode, entry.fields.vector,
+ entry.fields.trig_mode);
- deliver_bitmask = kvm_ioapic_get_delivery_bitmask(ioapic, dest,
- dest_mode);
+ kvm_get_intr_delivery_bitmask(ioapic, &entry, &deliver_bitmask);
if (!deliver_bitmask) {
ioapic_debug("no target on destination\n");
return 0;
}
- switch (delivery_mode) {
- case IOAPIC_LOWEST_PRIORITY:
- vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, vector,
- deliver_bitmask);
+ /* Always delivery PIT interrupt to vcpu 0 */
#ifdef CONFIG_X86
- if (irq == 0)
- vcpu = ioapic->kvm->vcpus[0];
+ if (irq == 0)
+ deliver_bitmask = 1 << 0;
#endif
- if (vcpu != NULL)
- r = ioapic_inj_irq(ioapic, vcpu, vector,
- trig_mode, delivery_mode);
- else
- ioapic_debug("null lowest prio vcpu: "
- "mask=%x vector=%x delivery_mode=%x\n",
- deliver_bitmask, vector, IOAPIC_LOWEST_PRIORITY);
- break;
- case IOAPIC_FIXED:
-#ifdef CONFIG_X86
- if (irq == 0)
- deliver_bitmask = 1;
-#endif
- 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) {
- r = ioapic_inj_irq(ioapic, vcpu, vector,
- trig_mode, delivery_mode);
- }
- }
- break;
- case IOAPIC_NMI:
- 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)
+
+ 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) {
+ if (entry.fields.delivery_mode ==
+ IOAPIC_LOWEST_PRIORITY ||
+ entry.fields.delivery_mode == IOAPIC_FIXED)
+ r = ioapic_inj_irq(ioapic, vcpu,
+ entry.fields.vector,
+ entry.fields.trig_mode,
+ entry.fields.delivery_mode);
+ else if (entry.fields.delivery_mode == IOAPIC_NMI)
ioapic_inj_nmi(vcpu);
else
- ioapic_debug("NMI to vcpu %d failed\n",
- vcpu->vcpu_id);
- }
- break;
- default:
- printk(KERN_WARNING "Unsupported delivery mode %d\n",
- delivery_mode);
- break;
+ ioapic_debug("unsupported delivery mode %x!\n",
+ entry.fields.delivery_mode);
+ } else
+ ioapic_debug("null destination vcpu: "
+ "mask=%x vector=%x delivery_mode=%x\n",
+ entry.fields.deliver_bitmask,
+ entry.fields.vector,
+ entry.fields.delivery_mode);
}
return r;
}
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index 9e6c622..6848d03 100644
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -28,13 +28,39 @@
#include <asm/msidef.h>
#endif
+void kvm_get_intr_delivery_bitmask(struct kvm_ioapic *ioapic,
+ union kvm_ioapic_redirect_entry *entry,
+ u32 *deliver_bitmask)
+{
+ struct kvm_vcpu *vcpu;
+
+ *deliver_bitmask = kvm_ioapic_get_delivery_bitmask(ioapic,
+ entry->fields.dest_id, entry->fields.dest_mode);
+ switch (entry->fields.delivery_mode) {
+ case IOAPIC_LOWEST_PRIORITY:
+ vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm,
+ entry->fields.vector, *deliver_bitmask);
+ *deliver_bitmask = 1 << vcpu->vcpu_id;
+ break;
+ case IOAPIC_FIXED:
+ case IOAPIC_NMI:
+ break;
+ default:
+ if (printk_ratelimit())
+ printk(KERN_INFO "kvm: unsupported delivery mode %d\n",
+ entry->fields.delivery_mode);
+ *deliver_bitmask = 0;
+ }
+}
+
+
static void gsi_dispatch(struct kvm *kvm, u32 gsi)
{
int vcpu_id;
struct kvm_vcpu *vcpu;
struct kvm_ioapic *ioapic = ioapic_irqchip(kvm);
struct kvm_gsi_route_kernel_entry *gsi_entry;
- int dest_id, vector, dest_mode, trig_mode, delivery_mode;
+ union kvm_ioapic_redirect_entry entry;
u32 deliver_bitmask;
BUG_ON(!ioapic);
@@ -47,42 +73,35 @@ static void gsi_dispatch(struct kvm *kvm, u32 gsi)
#ifdef CONFIG_X86
if (gsi_entry->type == KVM_GSI_ROUTE_TYPE_MSI) {
- dest_id = (gsi_entry->msi.address_lo & MSI_ADDR_DEST_ID_MASK)
- >> MSI_ADDR_DEST_ID_SHIFT;
- vector = (gsi_entry->msi.data & MSI_DATA_VECTOR_MASK)
- >> MSI_DATA_VECTOR_SHIFT;
- dest_mode = test_bit(MSI_ADDR_DEST_MODE_SHIFT,
+ entry.bits = 0;
+ entry.fields.dest_id = (gsi_entry->msi.address_lo &
+ MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
+ entry.fields.vector = (gsi_entry->msi.data &
+ MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT;
+ entry.fields.dest_mode = test_bit(MSI_ADDR_DEST_MODE_SHIFT,
(unsigned long *)&gsi_entry->msi.address_lo);
- trig_mode = test_bit(MSI_DATA_TRIGGER_SHIFT,
+ entry.fields.trig_mode = test_bit(MSI_DATA_TRIGGER_SHIFT,
(unsigned long *)&gsi_entry->msi.data);
- delivery_mode = test_bit(MSI_DATA_DELIVERY_MODE_SHIFT,
+ entry.fields.delivery_mode = test_bit(
+ MSI_DATA_DELIVERY_MODE_SHIFT,
(unsigned long *)&gsi_entry->msi.data);
- 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:
- break;
+ /* TODO Deal with RH bit of MSI message address */
+
+ kvm_get_intr_delivery_bitmask(ioapic, &entry, &deliver_bitmask);
+
+ if (!deliver_bitmask) {
+ printk(KERN_WARNING
+ "kvm: no destination for MSI delivery!");
+ return;
+ }
+ 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, entry.fields.vector,
+ entry.fields.trig_mode);
}
}
#endif /* CONFIG_X86 */
--
1.5.4.5
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/7] KVM: Improve MSI dispatch function
2009-01-08 10:45 [PATCH 0/7][v5] GSI route layer for MSI/MSI-X Sheng Yang
@ 2009-01-08 10:45 ` Sheng Yang
0 siblings, 0 replies; 9+ messages in thread
From: Sheng Yang @ 2009-01-08 10:45 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: kvm, Sheng Yang
Prepare to merge with kvm_set_irq().
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
virt/kvm/kvm_main.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 3bbb59f..fb2d639 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -87,7 +87,7 @@ static bool kvm_rebooting;
#ifdef KVM_CAP_DEVICE_ASSIGNMENT
#ifdef CONFIG_X86
-static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev)
+static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev, u32 gsi)
{
int vcpu_id;
struct kvm_vcpu *vcpu;
@@ -98,7 +98,7 @@ static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev)
BUG_ON(!ioapic);
- gsi_entry = kvm_find_gsi_route_entry(dev->kvm, dev->guest_irq);
+ gsi_entry = kvm_find_gsi_route_entry(dev->kvm, gsi);
if (!gsi_entry) {
printk(KERN_WARNING "kvm: fail to find correlated gsi entry\n");
return;
@@ -145,7 +145,7 @@ static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev)
}
}
#else
-static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev) {}
+static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev, u32 gsi) {}
#endif
static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *head,
@@ -180,7 +180,7 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work)
assigned_dev->guest_irq, 1);
else if (assigned_dev->irq_requested_type &
KVM_ASSIGNED_DEV_GUEST_MSI) {
- assigned_device_msi_dispatch(assigned_dev);
+ assigned_device_msi_dispatch(assigned_dev, assigned_dev->guest_irq);
enable_irq(assigned_dev->host_irq);
assigned_dev->host_irq_disabled = false;
}
--
1.5.4.5
^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2009-01-13 9:58 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-01-13 9:58 [PATCH 0/7][v6] GSI route layer for MSI/MSI-X Sheng Yang
2009-01-13 9:58 ` [PATCH 1/7] KVM: Add a route layer to convert MSI message to GSI Sheng Yang
2009-01-13 9:58 ` [PATCH 2/7] KVM: Using gsi route for MSI device assignment Sheng Yang
2009-01-13 9:58 ` [PATCH 3/7] KVM: Improve MSI dispatch function Sheng Yang
2009-01-13 9:58 ` [PATCH 4/7] KVM: Using ioapic_irqchip() macro for kvm_set_irq Sheng Yang
2009-01-13 9:58 ` [PATCH 5/7] KVM: Merge MSI handling to kvm_set_irq Sheng Yang
2009-01-13 9:58 ` [PATCH 6/7] KVM: Split IOAPIC structure Sheng Yang
2009-01-13 9:58 ` [PATCH 7/7] KVM: Unified the delivery of IOAPIC and MSI Sheng Yang
-- strict thread matches above, loose matches on Subject: below --
2009-01-08 10:45 [PATCH 0/7][v5] GSI route layer for MSI/MSI-X Sheng Yang
2009-01-08 10:45 ` [PATCH 3/7] KVM: Improve MSI dispatch function Sheng Yang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).