| From foo@baz Thu Feb 1 13:58:04 CET 2018 |
| From: Nikita Leshenko <nikita.leshchenko@oracle.com> |
| Date: Sun, 5 Nov 2017 15:52:32 +0200 |
| Subject: KVM: x86: ioapic: Clear Remote IRR when entry is switched to edge-triggered |
| |
| From: Nikita Leshenko <nikita.leshchenko@oracle.com> |
| |
| |
| [ Upstream commit a8bfec2930525808c01f038825d1df3904638631 ] |
| |
| 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@oracle.com> |
| Reviewed-by: Liran Alon <liran.alon@oracle.com> |
| Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> |
| Reviewed-by: Wanpeng Li <wanpeng.li@hotmail.com> |
| Reviewed-by: Steve Rutherford <srutherford@google.com> |
| Signed-off-by: Radim Krčmář <rkrcmar@redhat.com> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| 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 a7ac8688bba8..4b573c8694ac 100644 |
| --- a/arch/x86/kvm/ioapic.c |
| +++ b/arch/x86/kvm/ioapic.c |
| @@ -306,8 +306,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.16.1 |
| |