2017-11-05 21:52 GMT+08:00 Nikita Leshenko <nikita.leshchenko@xxxxxxxxxx>: > Some OSes (Linux, Xen) use this behavior to clear the Remote IRR bit for > IOAPICs without an EOI register. They simulate the EOI message manually > by changing the trigger mode to edge and then back to level, with the > entry being masked during this. > > QEMU implements this feature in commit ed1263c363c9 > ("ioapic: clear remote irr bit for edge-triggered interrupts") > > As a side effect, this commit removes an incorrect behavior where Remote > IRR was cleared when the redirection table entry was rewritten. This is not > consistent with the manual and also opens an opportunity for a strange > behavior when a redirection table entry is modified from an interrupt > handler that handles the same entry: The modification will clear the > Remote IRR bit even though the interrupt handler is still running. > > Signed-off-by: Nikita Leshenko <nikita.leshchenko@xxxxxxxxxx> > Reviewed-by: Liran Alon <liran.alon@xxxxxxxxxx> > Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> Reviewed-by: Wanpeng Li <wanpeng.li@xxxxxxxxxxx> > --- > arch/x86/kvm/ioapic.c | 11 ++++++++++- > 1 file changed, 10 insertions(+), 1 deletion(-) > > diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c > index 6df150eaaa78..163d340ee5f8 100644 > --- a/arch/x86/kvm/ioapic.c > +++ b/arch/x86/kvm/ioapic.c > @@ -304,8 +304,17 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) > } else { > e->bits &= ~0xffffffffULL; > e->bits |= (u32) val; > - e->fields.remote_irr = 0; > } > + > + /* > + * Some OSes (Linux, Xen) assume that Remote IRR bit will > + * be cleared by IOAPIC hardware when the entry is configured > + * as edge-triggered. This behavior is used to simulate an > + * explicit EOI on IOAPICs that don't have the EOI register. > + */ > + if (e->fields.trig_mode == IOAPIC_EDGE_TRIG) > + e->fields.remote_irr = 0; > + > mask_after = e->fields.mask; > if (mask_before != mask_after) > kvm_fire_mask_notifiers(ioapic->kvm, KVM_IRQCHIP_IOAPIC, index, mask_after); > -- > 2.13.3 >