]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/x86/kvm/i8259.c
KVM: MMU: do not write-protect large mappings
[linux-2.6-omap-h63xx.git] / arch / x86 / kvm / i8259.c
index c31164e8aa46c498643b9fa953df3920d598a1d3..71e3eeeccae8f0d131c655c1b70d06d5c514fd1d 100644 (file)
 
 #include <linux/kvm_host.h>
 
+static void pic_clear_isr(struct kvm_kpic_state *s, int irq)
+{
+       s->isr &= ~(1 << irq);
+}
+
 /*
  * set irq level. If an edge is detected, then the IRR is set to 1
  */
@@ -141,11 +146,12 @@ void kvm_pic_set_irq(void *opaque, int irq, int level)
  */
 static inline void pic_intack(struct kvm_kpic_state *s, int irq)
 {
+       s->isr |= 1 << irq;
        if (s->auto_eoi) {
                if (s->rotate_on_auto_eoi)
                        s->priority_add = (irq + 1) & 7;
-       } else
-               s->isr |= (1 << irq);
+               pic_clear_isr(s, irq);
+       }
        /*
         * We don't clear a level sensitive interrupt here
         */
@@ -153,9 +159,10 @@ static inline void pic_intack(struct kvm_kpic_state *s, int irq)
                s->irr &= ~(1 << irq);
 }
 
-int kvm_pic_read_irq(struct kvm_pic *s)
+int kvm_pic_read_irq(struct kvm *kvm)
 {
        int irq, irq2, intno;
+       struct kvm_pic *s = pic_irqchip(kvm);
 
        irq = pic_get_irq(&s->pics[0]);
        if (irq >= 0) {
@@ -181,12 +188,27 @@ int kvm_pic_read_irq(struct kvm_pic *s)
                intno = s->pics[0].irq_base + irq;
        }
        pic_update_irq(s);
+       kvm_notify_acked_irq(kvm, irq);
 
        return intno;
 }
 
 void kvm_pic_reset(struct kvm_kpic_state *s)
 {
+       int irq, irqbase;
+       struct kvm *kvm = s->pics_state->irq_request_opaque;
+       struct kvm_vcpu *vcpu0 = kvm->vcpus[0];
+
+       if (s == &s->pics_state->pics[0])
+               irqbase = 0;
+       else
+               irqbase = 8;
+
+       for (irq = 0; irq < PIC_NUM_PINS/2; irq++) {
+               if (vcpu0 && kvm_apic_accept_pic_intr(vcpu0))
+                       if (s->irr & (1 << irq) || s->isr & (1 << irq))
+                               kvm_notify_acked_irq(kvm, irq+irqbase);
+       }
        s->last_irr = 0;
        s->irr = 0;
        s->imr = 0;
@@ -243,7 +265,7 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val)
                                priority = get_priority(s, s->isr);
                                if (priority != 8) {
                                        irq = (priority + s->priority_add) & 7;
-                                       s->isr &= ~(1 << irq);
+                                       pic_clear_isr(s, irq);
                                        if (cmd == 5)
                                                s->priority_add = (irq + 1) & 7;
                                        pic_update_irq(s->pics_state);
@@ -251,7 +273,7 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val)
                                break;
                        case 3:
                                irq = val & 7;
-                               s->isr &= ~(1 << irq);
+                               pic_clear_isr(s, irq);
                                pic_update_irq(s->pics_state);
                                break;
                        case 6:
@@ -260,8 +282,8 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val)
                                break;
                        case 7:
                                irq = val & 7;
-                               s->isr &= ~(1 << irq);
                                s->priority_add = (irq + 1) & 7;
+                               pic_clear_isr(s, irq);
                                pic_update_irq(s->pics_state);
                                break;
                        default:
@@ -303,7 +325,7 @@ static u32 pic_poll_read(struct kvm_kpic_state *s, u32 addr1)
                        s->pics_state->pics[0].irr &= ~(1 << 2);
                }
                s->irr &= ~(1 << ret);
-               s->isr &= ~(1 << ret);
+               pic_clear_isr(s, ret);
                if (addr1 >> 7 || ret != 2)
                        pic_update_irq(s->pics_state);
        } else {