diff options
author | Sheng Yang <sheng@linux.intel.com> | 2008-11-24 01:32:55 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2008-12-31 09:55:02 -0500 |
commit | f64769eb05565c74d7fce6fa75d65924f9cdaf79 (patch) | |
tree | e1f0ba42a24d2aa349da7da019fc2c8f516e25bf /virt/kvm | |
parent | 68b76f51675809c8ce200a86276c3c7266f17a64 (diff) |
KVM: Add assigned_device_msi_dispatch()
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>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'virt/kvm')
-rw-r--r-- | 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 2089f8b68a16..228c1d18a614 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -47,6 +47,10 @@ | |||
47 | #include <asm/uaccess.h> | 47 | #include <asm/uaccess.h> |
48 | #include <asm/pgtable.h> | 48 | #include <asm/pgtable.h> |
49 | 49 | ||
50 | #ifdef CONFIG_X86 | ||
51 | #include <asm/msidef.h> | ||
52 | #endif | ||
53 | |||
50 | #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET | 54 | #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET |
51 | #include "coalesced_mmio.h" | 55 | #include "coalesced_mmio.h" |
52 | #endif | 56 | #endif |
@@ -78,6 +82,57 @@ static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl, | |||
78 | bool kvm_rebooting; | 82 | bool kvm_rebooting; |
79 | 83 | ||
80 | #ifdef KVM_CAP_DEVICE_ASSIGNMENT | 84 | #ifdef KVM_CAP_DEVICE_ASSIGNMENT |
85 | |||
86 | #ifdef CONFIG_X86 | ||
87 | static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev) | ||
88 | { | ||
89 | int vcpu_id; | ||
90 | struct kvm_vcpu *vcpu; | ||
91 | struct kvm_ioapic *ioapic = ioapic_irqchip(dev->kvm); | ||
92 | int dest_id = (dev->guest_msi.address_lo & MSI_ADDR_DEST_ID_MASK) | ||
93 | >> MSI_ADDR_DEST_ID_SHIFT; | ||
94 | int vector = (dev->guest_msi.data & MSI_DATA_VECTOR_MASK) | ||
95 | >> MSI_DATA_VECTOR_SHIFT; | ||
96 | int dest_mode = test_bit(MSI_ADDR_DEST_MODE_SHIFT, | ||
97 | (unsigned long *)&dev->guest_msi.address_lo); | ||
98 | int trig_mode = test_bit(MSI_DATA_TRIGGER_SHIFT, | ||
99 | (unsigned long *)&dev->guest_msi.data); | ||
100 | int delivery_mode = test_bit(MSI_DATA_DELIVERY_MODE_SHIFT, | ||
101 | (unsigned long *)&dev->guest_msi.data); | ||
102 | u32 deliver_bitmask; | ||
103 | |||
104 | BUG_ON(!ioapic); | ||
105 | |||
106 | deliver_bitmask = kvm_ioapic_get_delivery_bitmask(ioapic, | ||
107 | dest_id, dest_mode); | ||
108 | /* IOAPIC delivery mode value is the same as MSI here */ | ||
109 | switch (delivery_mode) { | ||
110 | case IOAPIC_LOWEST_PRIORITY: | ||
111 | vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, vector, | ||
112 | deliver_bitmask); | ||
113 | if (vcpu != NULL) | ||
114 | kvm_apic_set_irq(vcpu, vector, trig_mode); | ||
115 | else | ||
116 | printk(KERN_INFO "kvm: null lowest priority vcpu!\n"); | ||
117 | break; | ||
118 | case IOAPIC_FIXED: | ||
119 | for (vcpu_id = 0; deliver_bitmask != 0; vcpu_id++) { | ||
120 | if (!(deliver_bitmask & (1 << vcpu_id))) | ||
121 | continue; | ||
122 | deliver_bitmask &= ~(1 << vcpu_id); | ||
123 | vcpu = ioapic->kvm->vcpus[vcpu_id]; | ||
124 | if (vcpu) | ||
125 | kvm_apic_set_irq(vcpu, vector, trig_mode); | ||
126 | } | ||
127 | break; | ||
128 | default: | ||
129 | printk(KERN_INFO "kvm: unsupported MSI delivery mode\n"); | ||
130 | } | ||
131 | } | ||
132 | #else | ||
133 | static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev) {} | ||
134 | #endif | ||
135 | |||
81 | static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *head, | 136 | static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *head, |
82 | int assigned_dev_id) | 137 | int assigned_dev_id) |
83 | { | 138 | { |