Commit 6da7e3f6 authored by Gleb Natapov's avatar Gleb Natapov Committed by Avi Kivity

KVM: APIC: kvm_apic_set_irq deliver all kinds of interrupts

Get rid of ioapic_inj_irq() and ioapic_inj_nmi() functions.
Signed-off-by: default avatarGleb Natapov <gleb@redhat.com>
Signed-off-by: default avatarMarcelo Tosatti <mtosatti@redhat.com>
parent f5a1e9f8
...@@ -585,7 +585,6 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu); ...@@ -585,7 +585,6 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu);
int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run); int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run);
void kvm_sal_emul(struct kvm_vcpu *vcpu); void kvm_sal_emul(struct kvm_vcpu *vcpu);
static inline void kvm_inject_nmi(struct kvm_vcpu *vcpu) {}
#endif /* __ASSEMBLY__*/ #endif /* __ASSEMBLY__*/
#endif #endif
...@@ -292,13 +292,13 @@ static void vcpu_deliver_ipi(struct kvm_vcpu *vcpu, uint64_t dm, ...@@ -292,13 +292,13 @@ static void vcpu_deliver_ipi(struct kvm_vcpu *vcpu, uint64_t dm,
{ {
switch (dm) { switch (dm) {
case SAPIC_FIXED: case SAPIC_FIXED:
kvm_apic_set_irq(vcpu, vector, 0); kvm_apic_set_irq(vcpu, vector, dm, 0);
break; break;
case SAPIC_NMI: case SAPIC_NMI:
kvm_apic_set_irq(vcpu, 2, 0); kvm_apic_set_irq(vcpu, 2, dm, 0);
break; break;
case SAPIC_EXTINT: case SAPIC_EXTINT:
kvm_apic_set_irq(vcpu, 0, 0); kvm_apic_set_irq(vcpu, 0, dm, 0);
break; break;
case SAPIC_INIT: case SAPIC_INIT:
case SAPIC_PMI: case SAPIC_PMI:
...@@ -1813,7 +1813,7 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu) ...@@ -1813,7 +1813,7 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
put_cpu(); put_cpu();
} }
int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig) int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig)
{ {
struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd); struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
......
...@@ -20,6 +20,6 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu); ...@@ -20,6 +20,6 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu);
int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest); int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda); int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig); int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig);
#endif #endif
...@@ -196,20 +196,30 @@ int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu) ...@@ -196,20 +196,30 @@ int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu)
} }
EXPORT_SYMBOL_GPL(kvm_lapic_find_highest_irr); EXPORT_SYMBOL_GPL(kvm_lapic_find_highest_irr);
int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig) static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
int vector, int level, int trig_mode);
int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig)
{ {
struct kvm_lapic *apic = vcpu->arch.apic; struct kvm_lapic *apic = vcpu->arch.apic;
int lapic_dmode;
if (!apic_test_and_set_irr(vec, apic)) { switch (dmode) {
/* a new pending irq is set in IRR */ case IOAPIC_LOWEST_PRIORITY:
if (trig) lapic_dmode = APIC_DM_LOWEST;
apic_set_vector(vec, apic->regs + APIC_TMR); break;
else case IOAPIC_FIXED:
apic_clear_vector(vec, apic->regs + APIC_TMR); lapic_dmode = APIC_DM_FIXED;
kvm_vcpu_kick(apic->vcpu); break;
return 1; case IOAPIC_NMI:
lapic_dmode = APIC_DM_NMI;
break;
default:
printk(KERN_DEBUG"Ignoring delivery mode %d\n", dmode);
return 0;
break;
} }
return 0; return __apic_accept_irq(apic, lapic_dmode, vec, 1, trig);
} }
static inline int apic_find_highest_isr(struct kvm_lapic *apic) static inline int apic_find_highest_isr(struct kvm_lapic *apic)
...@@ -327,7 +337,7 @@ static int apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, ...@@ -327,7 +337,7 @@ static int apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
int vector, int level, int trig_mode) int vector, int level, int trig_mode)
{ {
int orig_irr, result = 0; int result = 0;
struct kvm_vcpu *vcpu = apic->vcpu; struct kvm_vcpu *vcpu = apic->vcpu;
switch (delivery_mode) { switch (delivery_mode) {
...@@ -337,10 +347,11 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, ...@@ -337,10 +347,11 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
if (unlikely(!apic_enabled(apic))) if (unlikely(!apic_enabled(apic)))
break; break;
orig_irr = apic_test_and_set_irr(vector, apic); result = !apic_test_and_set_irr(vector, apic);
if (orig_irr && trig_mode) { if (!result) {
apic_debug("level trig mode repeatedly for vector %d", if (trig_mode)
vector); apic_debug("level trig mode repeatedly for "
"vector %d", vector);
break; break;
} }
...@@ -349,10 +360,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, ...@@ -349,10 +360,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
apic_set_vector(vector, apic->regs + APIC_TMR); apic_set_vector(vector, apic->regs + APIC_TMR);
} else } else
apic_clear_vector(vector, apic->regs + APIC_TMR); apic_clear_vector(vector, apic->regs + APIC_TMR);
kvm_vcpu_kick(vcpu); kvm_vcpu_kick(vcpu);
result = (orig_irr == 0);
break; break;
case APIC_DM_REMRD: case APIC_DM_REMRD:
...@@ -364,12 +372,14 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, ...@@ -364,12 +372,14 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
break; break;
case APIC_DM_NMI: case APIC_DM_NMI:
result = 1;
kvm_inject_nmi(vcpu); kvm_inject_nmi(vcpu);
kvm_vcpu_kick(vcpu); kvm_vcpu_kick(vcpu);
break; break;
case APIC_DM_INIT: case APIC_DM_INIT:
if (level) { if (level) {
result = 1;
if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE) if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
printk(KERN_DEBUG printk(KERN_DEBUG
"INIT on a runnable vcpu %d\n", "INIT on a runnable vcpu %d\n",
...@@ -386,6 +396,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, ...@@ -386,6 +396,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
apic_debug("SIPI to vcpu %d vector 0x%02x\n", apic_debug("SIPI to vcpu %d vector 0x%02x\n",
vcpu->vcpu_id, vector); vcpu->vcpu_id, vector);
if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) { if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
result = 1;
vcpu->arch.sipi_vector = vector; vcpu->arch.sipi_vector = vector;
vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED; vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED;
kvm_vcpu_kick(vcpu); kvm_vcpu_kick(vcpu);
......
...@@ -31,7 +31,7 @@ u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu); ...@@ -31,7 +31,7 @@ u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu);
int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest); int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda); int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig); int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 dmode, u8 trig);
u64 kvm_get_apic_base(struct kvm_vcpu *vcpu); u64 kvm_get_apic_base(struct kvm_vcpu *vcpu);
void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data); void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data);
......
...@@ -142,25 +142,6 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) ...@@ -142,25 +142,6 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
} }
} }
static int ioapic_inj_irq(struct kvm_ioapic *ioapic,
struct kvm_vcpu *vcpu,
u8 vector, u8 trig_mode, u8 delivery_mode)
{
ioapic_debug("irq %d trig %d deliv %d\n", vector, trig_mode,
delivery_mode);
ASSERT((delivery_mode == IOAPIC_FIXED) ||
(delivery_mode == IOAPIC_LOWEST_PRIORITY));
return kvm_apic_set_irq(vcpu, vector, trig_mode);
}
static void ioapic_inj_nmi(struct kvm_vcpu *vcpu)
{
kvm_inject_nmi(vcpu);
kvm_vcpu_kick(vcpu);
}
static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
{ {
union kvm_ioapic_redirect_entry entry = ioapic->redirtbl[irq]; union kvm_ioapic_redirect_entry entry = ioapic->redirtbl[irq];
...@@ -193,21 +174,12 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) ...@@ -193,21 +174,12 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
__clear_bit(vcpu_id, deliver_bitmask); __clear_bit(vcpu_id, deliver_bitmask);
vcpu = ioapic->kvm->vcpus[vcpu_id]; vcpu = ioapic->kvm->vcpus[vcpu_id];
if (vcpu) { if (vcpu) {
if (entry.fields.delivery_mode == if (r < 0)
IOAPIC_LOWEST_PRIORITY || r = 0;
entry.fields.delivery_mode == IOAPIC_FIXED) { r += kvm_apic_set_irq(vcpu,
if (r < 0) entry.fields.vector,
r = 0; entry.fields.trig_mode,
r += ioapic_inj_irq(ioapic, vcpu, entry.fields.delivery_mode);
entry.fields.vector,
entry.fields.trig_mode,
entry.fields.delivery_mode);
} else if (entry.fields.delivery_mode == IOAPIC_NMI) {
r = 1;
ioapic_inj_nmi(vcpu);
} else
ioapic_debug("unsupported delivery mode %x!\n",
entry.fields.delivery_mode);
} else } else
ioapic_debug("null destination vcpu: " ioapic_debug("null destination vcpu: "
"mask=%x vector=%x delivery_mode=%x\n", "mask=%x vector=%x delivery_mode=%x\n",
......
...@@ -148,6 +148,7 @@ static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, ...@@ -148,6 +148,7 @@ static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
if (r < 0) if (r < 0)
r = 0; r = 0;
r += kvm_apic_set_irq(vcpu, entry.fields.vector, r += kvm_apic_set_irq(vcpu, entry.fields.vector,
entry.fields.dest_mode,
entry.fields.trig_mode); entry.fields.trig_mode);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment