diff options
Diffstat (limited to 'virt/kvm/ioapic.c')
-rw-r--r-- | virt/kvm/ioapic.c | 48 |
1 files changed, 39 insertions, 9 deletions
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index cfb7e4d52dc2..ce82b9401958 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/hrtimer.h> | 35 | #include <linux/hrtimer.h> |
36 | #include <linux/io.h> | 36 | #include <linux/io.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <linux/export.h> | ||
38 | #include <asm/processor.h> | 39 | #include <asm/processor.h> |
39 | #include <asm/page.h> | 40 | #include <asm/page.h> |
40 | #include <asm/current.h> | 41 | #include <asm/current.h> |
@@ -115,6 +116,42 @@ static void update_handled_vectors(struct kvm_ioapic *ioapic) | |||
115 | smp_wmb(); | 116 | smp_wmb(); |
116 | } | 117 | } |
117 | 118 | ||
119 | void kvm_ioapic_calculate_eoi_exitmap(struct kvm_vcpu *vcpu, | ||
120 | u64 *eoi_exit_bitmap) | ||
121 | { | ||
122 | struct kvm_ioapic *ioapic = vcpu->kvm->arch.vioapic; | ||
123 | union kvm_ioapic_redirect_entry *e; | ||
124 | struct kvm_lapic_irq irqe; | ||
125 | int index; | ||
126 | |||
127 | spin_lock(&ioapic->lock); | ||
128 | /* traverse ioapic entry to set eoi exit bitmap*/ | ||
129 | for (index = 0; index < IOAPIC_NUM_PINS; index++) { | ||
130 | e = &ioapic->redirtbl[index]; | ||
131 | if (!e->fields.mask && | ||
132 | (e->fields.trig_mode == IOAPIC_LEVEL_TRIG || | ||
133 | kvm_irq_has_notifier(ioapic->kvm, KVM_IRQCHIP_IOAPIC, | ||
134 | index))) { | ||
135 | irqe.dest_id = e->fields.dest_id; | ||
136 | irqe.vector = e->fields.vector; | ||
137 | irqe.dest_mode = e->fields.dest_mode; | ||
138 | irqe.delivery_mode = e->fields.delivery_mode << 8; | ||
139 | kvm_calculate_eoi_exitmap(vcpu, &irqe, eoi_exit_bitmap); | ||
140 | } | ||
141 | } | ||
142 | spin_unlock(&ioapic->lock); | ||
143 | } | ||
144 | EXPORT_SYMBOL_GPL(kvm_ioapic_calculate_eoi_exitmap); | ||
145 | |||
146 | void kvm_ioapic_make_eoibitmap_request(struct kvm *kvm) | ||
147 | { | ||
148 | struct kvm_ioapic *ioapic = kvm->arch.vioapic; | ||
149 | |||
150 | if (!kvm_apic_vid_enabled(kvm) || !ioapic) | ||
151 | return; | ||
152 | kvm_make_update_eoibitmap_request(kvm); | ||
153 | } | ||
154 | |||
118 | static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) | 155 | static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) |
119 | { | 156 | { |
120 | unsigned index; | 157 | unsigned index; |
@@ -156,6 +193,7 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) | |||
156 | if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG | 193 | if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG |
157 | && ioapic->irr & (1 << index)) | 194 | && ioapic->irr & (1 << index)) |
158 | ioapic_service(ioapic, index); | 195 | ioapic_service(ioapic, index); |
196 | kvm_ioapic_make_eoibitmap_request(ioapic->kvm); | ||
159 | break; | 197 | break; |
160 | } | 198 | } |
161 | } | 199 | } |
@@ -179,15 +217,6 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) | |||
179 | irqe.level = 1; | 217 | irqe.level = 1; |
180 | irqe.shorthand = 0; | 218 | irqe.shorthand = 0; |
181 | 219 | ||
182 | #ifdef CONFIG_X86 | ||
183 | /* Always delivery PIT interrupt to vcpu 0 */ | ||
184 | if (irq == 0) { | ||
185 | irqe.dest_mode = 0; /* Physical mode. */ | ||
186 | /* need to read apic_id from apic regiest since | ||
187 | * it can be rewritten */ | ||
188 | irqe.dest_id = ioapic->kvm->bsp_vcpu_id; | ||
189 | } | ||
190 | #endif | ||
191 | return kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe); | 220 | return kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe); |
192 | } | 221 | } |
193 | 222 | ||
@@ -464,6 +493,7 @@ int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state) | |||
464 | spin_lock(&ioapic->lock); | 493 | spin_lock(&ioapic->lock); |
465 | memcpy(ioapic, state, sizeof(struct kvm_ioapic_state)); | 494 | memcpy(ioapic, state, sizeof(struct kvm_ioapic_state)); |
466 | update_handled_vectors(ioapic); | 495 | update_handled_vectors(ioapic); |
496 | kvm_ioapic_make_eoibitmap_request(kvm); | ||
467 | spin_unlock(&ioapic->lock); | 497 | spin_unlock(&ioapic->lock); |
468 | return 0; | 498 | return 0; |
469 | } | 499 | } |