From 063cb7cbc9f65ff4095df884cfcd7eaf3a160555 Mon Sep 17 00:00:00 2001 From: Sam Bobroff Date: Thu, 27 Apr 2017 16:31:53 +1000 Subject: ppc/xics: Fix stale irq->status bits after get ics_get_kvm_state() "or"s set bits into irq->status but does not mask out clear bits. Correct this by initializing the IRQ status to zero before adding bits to it. Signed-off-by: Sam Bobroff Signed-off-by: David Gibson --- hw/intc/xics_kvm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'hw/intc') diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c index 42e0e0e..03c1fc7 100644 --- a/hw/intc/xics_kvm.c +++ b/hw/intc/xics_kvm.c @@ -213,6 +213,7 @@ static void ics_get_kvm_state(ICSState *ics) irq->priority = irq->saved_priority; } + irq->status = 0; if (state & KVM_XICS_PENDING) { if (state & KVM_XICS_LEVEL_SENSITIVE) { irq->status |= XICS_STATUS_ASSERTED; -- cgit v1.1 From 229e16fd247c7d39822627916d18b52f733cbfa1 Mon Sep 17 00:00:00 2001 From: Sam Bobroff Date: Thu, 27 Apr 2017 16:32:03 +1000 Subject: ppc/xics: preserve P and Q bits for KVM IRQs Kernel commit 17d48610ae0f ("KVM: PPC: Book 3S: XICS: Implement ICS P/Q states") added new bits to the state used by KVM IRQs. Currently, QEMU does not preserve these bits, so migrating (or otherwise saving and restoring) the guest state causes the P and Q bits to be cleared. Clearing the P bit has no effect, because the kernel will set it based on other data, but the loss of a set Q bit will cause a lost interrupt. This patch preserves the P and Q bits, correcting the problem. Signed-off-by: Sam Bobroff Signed-off-by: David Gibson --- hw/intc/xics_kvm.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'hw/intc') diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c index 03c1fc7..dd93531 100644 --- a/hw/intc/xics_kvm.c +++ b/hw/intc/xics_kvm.c @@ -229,6 +229,12 @@ static void ics_get_kvm_state(ICSState *ics) | XICS_STATUS_REJECTED; } } + if (state & KVM_XICS_PRESENTED) { + irq->status |= XICS_STATUS_PRESENTED; + } + if (state & KVM_XICS_QUEUED) { + irq->status |= XICS_STATUS_QUEUED; + } } } @@ -266,6 +272,12 @@ static int ics_set_kvm_state(ICSState *ics, int version_id) state |= KVM_XICS_PENDING; } } + if (irq->status & XICS_STATUS_PRESENTED) { + state |= KVM_XICS_PRESENTED; + } + if (irq->status & XICS_STATUS_QUEUED) { + state |= KVM_XICS_QUEUED; + } ret = ioctl(kernel_xics_fd, KVM_SET_DEVICE_ATTR, &attr); if (ret != 0) { -- cgit v1.1