aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/i8259.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /arch/x86/kvm/i8259.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'arch/x86/kvm/i8259.c')
-rw-r--r--arch/x86/kvm/i8259.c87
1 files changed, 54 insertions, 33 deletions
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index 01f151682802..a790fa128a9f 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -26,6 +26,7 @@
26 * Port from Qemu. 26 * Port from Qemu.
27 */ 27 */
28#include <linux/mm.h> 28#include <linux/mm.h>
29#include <linux/slab.h>
29#include <linux/bitops.h> 30#include <linux/bitops.h>
30#include "irq.h" 31#include "irq.h"
31 32
@@ -38,16 +39,25 @@ static void pic_clear_isr(struct kvm_kpic_state *s, int irq)
38 s->isr_ack |= (1 << irq); 39 s->isr_ack |= (1 << irq);
39 if (s != &s->pics_state->pics[0]) 40 if (s != &s->pics_state->pics[0])
40 irq += 8; 41 irq += 8;
42 /*
43 * We are dropping lock while calling ack notifiers since ack
44 * notifier callbacks for assigned devices call into PIC recursively.
45 * Other interrupt may be delivered to PIC while lock is dropped but
46 * it should be safe since PIC state is already updated at this stage.
47 */
48 raw_spin_unlock(&s->pics_state->lock);
41 kvm_notify_acked_irq(s->pics_state->kvm, SELECT_PIC(irq), irq); 49 kvm_notify_acked_irq(s->pics_state->kvm, SELECT_PIC(irq), irq);
50 raw_spin_lock(&s->pics_state->lock);
42} 51}
43 52
44void kvm_pic_clear_isr_ack(struct kvm *kvm) 53void kvm_pic_clear_isr_ack(struct kvm *kvm)
45{ 54{
46 struct kvm_pic *s = pic_irqchip(kvm); 55 struct kvm_pic *s = pic_irqchip(kvm);
47 spin_lock(&s->lock); 56
57 raw_spin_lock(&s->lock);
48 s->pics[0].isr_ack = 0xff; 58 s->pics[0].isr_ack = 0xff;
49 s->pics[1].isr_ack = 0xff; 59 s->pics[1].isr_ack = 0xff;
50 spin_unlock(&s->lock); 60 raw_spin_unlock(&s->lock);
51} 61}
52 62
53/* 63/*
@@ -148,9 +158,9 @@ static void pic_update_irq(struct kvm_pic *s)
148 158
149void kvm_pic_update_irq(struct kvm_pic *s) 159void kvm_pic_update_irq(struct kvm_pic *s)
150{ 160{
151 spin_lock(&s->lock); 161 raw_spin_lock(&s->lock);
152 pic_update_irq(s); 162 pic_update_irq(s);
153 spin_unlock(&s->lock); 163 raw_spin_unlock(&s->lock);
154} 164}
155 165
156int kvm_pic_set_irq(void *opaque, int irq, int level) 166int kvm_pic_set_irq(void *opaque, int irq, int level)
@@ -158,14 +168,14 @@ int kvm_pic_set_irq(void *opaque, int irq, int level)
158 struct kvm_pic *s = opaque; 168 struct kvm_pic *s = opaque;
159 int ret = -1; 169 int ret = -1;
160 170
161 spin_lock(&s->lock); 171 raw_spin_lock(&s->lock);
162 if (irq >= 0 && irq < PIC_NUM_PINS) { 172 if (irq >= 0 && irq < PIC_NUM_PINS) {
163 ret = pic_set_irq1(&s->pics[irq >> 3], irq & 7, level); 173 ret = pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
164 pic_update_irq(s); 174 pic_update_irq(s);
165 trace_kvm_pic_set_irq(irq >> 3, irq & 7, s->pics[irq >> 3].elcr, 175 trace_kvm_pic_set_irq(irq >> 3, irq & 7, s->pics[irq >> 3].elcr,
166 s->pics[irq >> 3].imr, ret == 0); 176 s->pics[irq >> 3].imr, ret == 0);
167 } 177 }
168 spin_unlock(&s->lock); 178 raw_spin_unlock(&s->lock);
169 179
170 return ret; 180 return ret;
171} 181}
@@ -176,16 +186,18 @@ int kvm_pic_set_irq(void *opaque, int irq, int level)
176static inline void pic_intack(struct kvm_kpic_state *s, int irq) 186static inline void pic_intack(struct kvm_kpic_state *s, int irq)
177{ 187{
178 s->isr |= 1 << irq; 188 s->isr |= 1 << irq;
179 if (s->auto_eoi) {
180 if (s->rotate_on_auto_eoi)
181 s->priority_add = (irq + 1) & 7;
182 pic_clear_isr(s, irq);
183 }
184 /* 189 /*
185 * We don't clear a level sensitive interrupt here 190 * We don't clear a level sensitive interrupt here
186 */ 191 */
187 if (!(s->elcr & (1 << irq))) 192 if (!(s->elcr & (1 << irq)))
188 s->irr &= ~(1 << irq); 193 s->irr &= ~(1 << irq);
194
195 if (s->auto_eoi) {
196 if (s->rotate_on_auto_eoi)
197 s->priority_add = (irq + 1) & 7;
198 pic_clear_isr(s, irq);
199 }
200
189} 201}
190 202
191int kvm_pic_read_irq(struct kvm *kvm) 203int kvm_pic_read_irq(struct kvm *kvm)
@@ -193,7 +205,7 @@ int kvm_pic_read_irq(struct kvm *kvm)
193 int irq, irq2, intno; 205 int irq, irq2, intno;
194 struct kvm_pic *s = pic_irqchip(kvm); 206 struct kvm_pic *s = pic_irqchip(kvm);
195 207
196 spin_lock(&s->lock); 208 raw_spin_lock(&s->lock);
197 irq = pic_get_irq(&s->pics[0]); 209 irq = pic_get_irq(&s->pics[0]);
198 if (irq >= 0) { 210 if (irq >= 0) {
199 pic_intack(&s->pics[0], irq); 211 pic_intack(&s->pics[0], irq);
@@ -218,29 +230,18 @@ int kvm_pic_read_irq(struct kvm *kvm)
218 intno = s->pics[0].irq_base + irq; 230 intno = s->pics[0].irq_base + irq;
219 } 231 }
220 pic_update_irq(s); 232 pic_update_irq(s);
221 spin_unlock(&s->lock); 233 raw_spin_unlock(&s->lock);
222 234
223 return intno; 235 return intno;
224} 236}
225 237
226void kvm_pic_reset(struct kvm_kpic_state *s) 238void kvm_pic_reset(struct kvm_kpic_state *s)
227{ 239{
228 int irq, irqbase, n; 240 int irq;
229 struct kvm *kvm = s->pics_state->irq_request_opaque; 241 struct kvm *kvm = s->pics_state->irq_request_opaque;
230 struct kvm_vcpu *vcpu0 = kvm->bsp_vcpu; 242 struct kvm_vcpu *vcpu0 = kvm->bsp_vcpu;
243 u8 irr = s->irr, isr = s->imr;
231 244
232 if (s == &s->pics_state->pics[0])
233 irqbase = 0;
234 else
235 irqbase = 8;
236
237 for (irq = 0; irq < PIC_NUM_PINS/2; irq++) {
238 if (vcpu0 && kvm_apic_accept_pic_intr(vcpu0))
239 if (s->irr & (1 << irq) || s->isr & (1 << irq)) {
240 n = irq + irqbase;
241 kvm_notify_acked_irq(kvm, SELECT_PIC(n), n);
242 }
243 }
244 s->last_irr = 0; 245 s->last_irr = 0;
245 s->irr = 0; 246 s->irr = 0;
246 s->imr = 0; 247 s->imr = 0;
@@ -256,6 +257,13 @@ void kvm_pic_reset(struct kvm_kpic_state *s)
256 s->rotate_on_auto_eoi = 0; 257 s->rotate_on_auto_eoi = 0;
257 s->special_fully_nested_mode = 0; 258 s->special_fully_nested_mode = 0;
258 s->init4 = 0; 259 s->init4 = 0;
260
261 for (irq = 0; irq < PIC_NUM_PINS/2; irq++) {
262 if (vcpu0 && kvm_apic_accept_pic_intr(vcpu0))
263 if (irr & (1 << irq) || isr & (1 << irq)) {
264 pic_clear_isr(s, irq);
265 }
266 }
259} 267}
260 268
261static void pic_ioport_write(void *opaque, u32 addr, u32 val) 269static void pic_ioport_write(void *opaque, u32 addr, u32 val)
@@ -298,9 +306,9 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val)
298 priority = get_priority(s, s->isr); 306 priority = get_priority(s, s->isr);
299 if (priority != 8) { 307 if (priority != 8) {
300 irq = (priority + s->priority_add) & 7; 308 irq = (priority + s->priority_add) & 7;
301 pic_clear_isr(s, irq);
302 if (cmd == 5) 309 if (cmd == 5)
303 s->priority_add = (irq + 1) & 7; 310 s->priority_add = (irq + 1) & 7;
311 pic_clear_isr(s, irq);
304 pic_update_irq(s->pics_state); 312 pic_update_irq(s->pics_state);
305 } 313 }
306 break; 314 break;
@@ -436,7 +444,7 @@ static int picdev_write(struct kvm_io_device *this,
436 printk(KERN_ERR "PIC: non byte write\n"); 444 printk(KERN_ERR "PIC: non byte write\n");
437 return 0; 445 return 0;
438 } 446 }
439 spin_lock(&s->lock); 447 raw_spin_lock(&s->lock);
440 switch (addr) { 448 switch (addr) {
441 case 0x20: 449 case 0x20:
442 case 0x21: 450 case 0x21:
@@ -449,7 +457,7 @@ static int picdev_write(struct kvm_io_device *this,
449 elcr_ioport_write(&s->pics[addr & 1], addr, data); 457 elcr_ioport_write(&s->pics[addr & 1], addr, data);
450 break; 458 break;
451 } 459 }
452 spin_unlock(&s->lock); 460 raw_spin_unlock(&s->lock);
453 return 0; 461 return 0;
454} 462}
455 463
@@ -466,7 +474,7 @@ static int picdev_read(struct kvm_io_device *this,
466 printk(KERN_ERR "PIC: non byte read\n"); 474 printk(KERN_ERR "PIC: non byte read\n");
467 return 0; 475 return 0;
468 } 476 }
469 spin_lock(&s->lock); 477 raw_spin_lock(&s->lock);
470 switch (addr) { 478 switch (addr) {
471 case 0x20: 479 case 0x20:
472 case 0x21: 480 case 0x21:
@@ -480,7 +488,7 @@ static int picdev_read(struct kvm_io_device *this,
480 break; 488 break;
481 } 489 }
482 *(unsigned char *)val = data; 490 *(unsigned char *)val = data;
483 spin_unlock(&s->lock); 491 raw_spin_unlock(&s->lock);
484 return 0; 492 return 0;
485} 493}
486 494
@@ -514,7 +522,7 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm)
514 s = kzalloc(sizeof(struct kvm_pic), GFP_KERNEL); 522 s = kzalloc(sizeof(struct kvm_pic), GFP_KERNEL);
515 if (!s) 523 if (!s)
516 return NULL; 524 return NULL;
517 spin_lock_init(&s->lock); 525 raw_spin_lock_init(&s->lock);
518 s->kvm = kvm; 526 s->kvm = kvm;
519 s->pics[0].elcr_mask = 0xf8; 527 s->pics[0].elcr_mask = 0xf8;
520 s->pics[1].elcr_mask = 0xde; 528 s->pics[1].elcr_mask = 0xde;
@@ -527,7 +535,9 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm)
527 * Initialize PIO device 535 * Initialize PIO device
528 */ 536 */
529 kvm_iodevice_init(&s->dev, &picdev_ops); 537 kvm_iodevice_init(&s->dev, &picdev_ops);
530 ret = kvm_io_bus_register_dev(kvm, &kvm->pio_bus, &s->dev); 538 mutex_lock(&kvm->slots_lock);
539 ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, &s->dev);
540 mutex_unlock(&kvm->slots_lock);
531 if (ret < 0) { 541 if (ret < 0) {
532 kfree(s); 542 kfree(s);
533 return NULL; 543 return NULL;
@@ -535,3 +545,14 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm)
535 545
536 return s; 546 return s;
537} 547}
548
549void kvm_destroy_pic(struct kvm *kvm)
550{
551 struct kvm_pic *vpic = kvm->arch.vpic;
552
553 if (vpic) {
554 kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev);
555 kvm->arch.vpic = NULL;
556 kfree(vpic);
557 }
558}