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);
int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run);
void kvm_sal_emul(struct kvm_vcpu *vcpu);
static inline void kvm_inject_nmi(struct kvm_vcpu *vcpu) {}
#endif /* __ASSEMBLY__*/
#endif
......@@ -292,13 +292,13 @@ static void vcpu_deliver_ipi(struct kvm_vcpu *vcpu, uint64_t dm,
{
switch (dm) {
case SAPIC_FIXED:
kvm_apic_set_irq(vcpu, vector, 0);
kvm_apic_set_irq(vcpu, vector, dm, 0);
break;
case SAPIC_NMI:
kvm_apic_set_irq(vcpu, 2, 0);
kvm_apic_set_irq(vcpu, 2, dm, 0);
break;
case SAPIC_EXTINT:
kvm_apic_set_irq(vcpu, 0, 0);
kvm_apic_set_irq(vcpu, 0, dm, 0);
break;
case SAPIC_INIT:
case SAPIC_PMI:
......@@ -1813,7 +1813,7 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
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);
......
......@@ -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_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
......@@ -196,20 +196,30 @@ int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu)
}
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;
int lapic_dmode;
if (!apic_test_and_set_irr(vec, apic)) {
/* a new pending irq is set in IRR */
if (trig)
apic_set_vector(vec, apic->regs + APIC_TMR);
else
apic_clear_vector(vec, apic->regs + APIC_TMR);
kvm_vcpu_kick(apic->vcpu);
return 1;
switch (dmode) {
case IOAPIC_LOWEST_PRIORITY:
lapic_dmode = APIC_DM_LOWEST;
break;
case IOAPIC_FIXED:
lapic_dmode = APIC_DM_FIXED;
break;
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)
......@@ -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,
int vector, int level, int trig_mode)
{
int orig_irr, result = 0;
int result = 0;
struct kvm_vcpu *vcpu = apic->vcpu;
switch (delivery_mode) {
......@@ -337,10 +347,11 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
if (unlikely(!apic_enabled(apic)))
break;
orig_irr = apic_test_and_set_irr(vector, apic);
if (orig_irr && trig_mode) {
apic_debug("level trig mode repeatedly for vector %d",
vector);
result = !apic_test_and_set_irr(vector, apic);
if (!result) {
if (trig_mode)
apic_debug("level trig mode repeatedly for "
"vector %d", vector);
break;
}
......@@ -349,10 +360,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
apic_set_vector(vector, apic->regs + APIC_TMR);
} else
apic_clear_vector(vector, apic->regs + APIC_TMR);
kvm_vcpu_kick(vcpu);
result = (orig_irr == 0);
break;
case APIC_DM_REMRD:
......@@ -364,12 +372,14 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
break;
case APIC_DM_NMI:
result = 1;
kvm_inject_nmi(vcpu);
kvm_vcpu_kick(vcpu);
break;
case APIC_DM_INIT:
if (level) {
result = 1;
if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
printk(KERN_DEBUG
"INIT on a runnable vcpu %d\n",
......@@ -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",
vcpu->vcpu_id, vector);
if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
result = 1;
vcpu->arch.sipi_vector = vector;
vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED;
kvm_vcpu_kick(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_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);
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)
}
}
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)
{
union kvm_ioapic_redirect_entry entry = ioapic->redirtbl[irq];
......@@ -193,21 +174,12 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
__clear_bit(vcpu_id, deliver_bitmask);
vcpu = ioapic->kvm->vcpus[vcpu_id];
if (vcpu) {
if (entry.fields.delivery_mode ==
IOAPIC_LOWEST_PRIORITY ||
entry.fields.delivery_mode == IOAPIC_FIXED) {
if (r < 0)
r = 0;
r += ioapic_inj_irq(ioapic, vcpu,
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);
if (r < 0)
r = 0;
r += kvm_apic_set_irq(vcpu,
entry.fields.vector,
entry.fields.trig_mode,
entry.fields.delivery_mode);
} else
ioapic_debug("null destination vcpu: "
"mask=%x vector=%x delivery_mode=%x\n",
......
......@@ -148,6 +148,7 @@ static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
if (r < 0)
r = 0;
r += kvm_apic_set_irq(vcpu, entry.fields.vector,
entry.fields.dest_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