diff options
| author | Gleb Natapov <gleb@redhat.com> | 2009-08-24 04:54:25 -0400 |
|---|---|---|
| committer | Avi Kivity <avi@redhat.com> | 2009-12-03 02:32:08 -0500 |
| commit | eba0226bdfffe262e72b8360e4d0d12070e9a0f0 (patch) | |
| tree | 93da785e3bba63a9232e529a2572541ef87c0615 /arch/x86/kvm | |
| parent | 280aa177dcd1edc718d8a92f17f235b783ec6307 (diff) | |
KVM: Move IO APIC to its own lock
The allows removal of irq_lock from the injection path.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
| -rw-r--r-- | arch/x86/kvm/i8259.c | 22 | ||||
| -rw-r--r-- | arch/x86/kvm/lapic.c | 5 | ||||
| -rw-r--r-- | arch/x86/kvm/x86.c | 10 |
3 files changed, 19 insertions, 18 deletions
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c index ccc941af4eaf..d057c0cbd245 100644 --- a/arch/x86/kvm/i8259.c +++ b/arch/x86/kvm/i8259.c | |||
| @@ -38,7 +38,15 @@ static void pic_clear_isr(struct kvm_kpic_state *s, int irq) | |||
| 38 | s->isr_ack |= (1 << irq); | 38 | s->isr_ack |= (1 << irq); |
| 39 | if (s != &s->pics_state->pics[0]) | 39 | if (s != &s->pics_state->pics[0]) |
| 40 | irq += 8; | 40 | irq += 8; |
| 41 | /* | ||
| 42 | * We are dropping lock while calling ack notifiers since ack | ||
| 43 | * notifier callbacks for assigned devices call into PIC recursively. | ||
| 44 | * Other interrupt may be delivered to PIC while lock is dropped but | ||
| 45 | * it should be safe since PIC state is already updated at this stage. | ||
| 46 | */ | ||
| 47 | spin_unlock(&s->pics_state->lock); | ||
| 41 | kvm_notify_acked_irq(s->pics_state->kvm, SELECT_PIC(irq), irq); | 48 | kvm_notify_acked_irq(s->pics_state->kvm, SELECT_PIC(irq), irq); |
| 49 | spin_lock(&s->pics_state->lock); | ||
| 42 | } | 50 | } |
| 43 | 51 | ||
| 44 | void kvm_pic_clear_isr_ack(struct kvm *kvm) | 52 | void kvm_pic_clear_isr_ack(struct kvm *kvm) |
| @@ -176,16 +184,18 @@ int kvm_pic_set_irq(void *opaque, int irq, int level) | |||
| 176 | static inline void pic_intack(struct kvm_kpic_state *s, int irq) | 184 | static inline void pic_intack(struct kvm_kpic_state *s, int irq) |
| 177 | { | 185 | { |
| 178 | s->isr |= 1 << irq; | 186 | 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 | /* | 187 | /* |
| 185 | * We don't clear a level sensitive interrupt here | 188 | * We don't clear a level sensitive interrupt here |
| 186 | */ | 189 | */ |
| 187 | if (!(s->elcr & (1 << irq))) | 190 | if (!(s->elcr & (1 << irq))) |
| 188 | s->irr &= ~(1 << irq); | 191 | s->irr &= ~(1 << irq); |
| 192 | |||
| 193 | if (s->auto_eoi) { | ||
| 194 | if (s->rotate_on_auto_eoi) | ||
| 195 | s->priority_add = (irq + 1) & 7; | ||
| 196 | pic_clear_isr(s, irq); | ||
| 197 | } | ||
| 198 | |||
| 189 | } | 199 | } |
| 190 | 200 | ||
| 191 | int kvm_pic_read_irq(struct kvm *kvm) | 201 | int kvm_pic_read_irq(struct kvm *kvm) |
| @@ -294,9 +304,9 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val) | |||
| 294 | priority = get_priority(s, s->isr); | 304 | priority = get_priority(s, s->isr); |
| 295 | if (priority != 8) { | 305 | if (priority != 8) { |
| 296 | irq = (priority + s->priority_add) & 7; | 306 | irq = (priority + s->priority_add) & 7; |
| 297 | pic_clear_isr(s, irq); | ||
| 298 | if (cmd == 5) | 307 | if (cmd == 5) |
| 299 | s->priority_add = (irq + 1) & 7; | 308 | s->priority_add = (irq + 1) & 7; |
| 309 | pic_clear_isr(s, irq); | ||
| 300 | pic_update_irq(s->pics_state); | 310 | pic_update_irq(s->pics_state); |
| 301 | } | 311 | } |
| 302 | break; | 312 | break; |
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 23c217692ea9..df8bcb0f66d8 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
| @@ -471,11 +471,8 @@ static void apic_set_eoi(struct kvm_lapic *apic) | |||
| 471 | trigger_mode = IOAPIC_LEVEL_TRIG; | 471 | trigger_mode = IOAPIC_LEVEL_TRIG; |
| 472 | else | 472 | else |
| 473 | trigger_mode = IOAPIC_EDGE_TRIG; | 473 | trigger_mode = IOAPIC_EDGE_TRIG; |
| 474 | if (!(apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI)) { | 474 | if (!(apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI)) |
| 475 | mutex_lock(&apic->vcpu->kvm->irq_lock); | ||
| 476 | kvm_ioapic_update_eoi(apic->vcpu->kvm, vector, trigger_mode); | 475 | kvm_ioapic_update_eoi(apic->vcpu->kvm, vector, trigger_mode); |
| 477 | mutex_unlock(&apic->vcpu->kvm->irq_lock); | ||
| 478 | } | ||
| 479 | } | 476 | } |
| 480 | 477 | ||
| 481 | static void apic_send_ipi(struct kvm_lapic *apic) | 478 | static void apic_send_ipi(struct kvm_lapic *apic) |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 1687d12b122a..fdf989f17a61 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
| @@ -2038,9 +2038,7 @@ static int kvm_vm_ioctl_get_irqchip(struct kvm *kvm, struct kvm_irqchip *chip) | |||
| 2038 | sizeof(struct kvm_pic_state)); | 2038 | sizeof(struct kvm_pic_state)); |
| 2039 | break; | 2039 | break; |
| 2040 | case KVM_IRQCHIP_IOAPIC: | 2040 | case KVM_IRQCHIP_IOAPIC: |
| 2041 | memcpy(&chip->chip.ioapic, | 2041 | r = kvm_get_ioapic(kvm, &chip->chip.ioapic); |
| 2042 | ioapic_irqchip(kvm), | ||
| 2043 | sizeof(struct kvm_ioapic_state)); | ||
| 2044 | break; | 2042 | break; |
| 2045 | default: | 2043 | default: |
| 2046 | r = -EINVAL; | 2044 | r = -EINVAL; |
| @@ -2070,11 +2068,7 @@ static int kvm_vm_ioctl_set_irqchip(struct kvm *kvm, struct kvm_irqchip *chip) | |||
| 2070 | spin_unlock(&pic_irqchip(kvm)->lock); | 2068 | spin_unlock(&pic_irqchip(kvm)->lock); |
| 2071 | break; | 2069 | break; |
| 2072 | case KVM_IRQCHIP_IOAPIC: | 2070 | case KVM_IRQCHIP_IOAPIC: |
| 2073 | mutex_lock(&kvm->irq_lock); | 2071 | r = kvm_set_ioapic(kvm, &chip->chip.ioapic); |
| 2074 | memcpy(ioapic_irqchip(kvm), | ||
| 2075 | &chip->chip.ioapic, | ||
| 2076 | sizeof(struct kvm_ioapic_state)); | ||
| 2077 | mutex_unlock(&kvm->irq_lock); | ||
| 2078 | break; | 2072 | break; |
| 2079 | default: | 2073 | default: |
| 2080 | r = -EINVAL; | 2074 | r = -EINVAL; |
