Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Suchanek <msuchanek@suse.de>2018-10-31 12:36:54 +0100
committerMichal Suchanek <msuchanek@suse.de>2018-10-31 23:28:38 +0100
commite55ab8d0e85c64e238403af95974f7cea2b15d39 (patch)
tree124f647875f4de626ffe1d467acad3f6b9a173a9
parent4829860db990fce348bc32e349e20d62833314f8 (diff)
KVM: PPC: Book3S HV: XIVE: Resend re-routed interrupts on CPU
priority change (bsc#1061840).
-rw-r--r--patches.arch/KVM-PPC-Book3S-HV-XIVE-Resend-re-routed-interrupts-o.patch181
-rw-r--r--series.conf1
2 files changed, 182 insertions, 0 deletions
diff --git a/patches.arch/KVM-PPC-Book3S-HV-XIVE-Resend-re-routed-interrupts-o.patch b/patches.arch/KVM-PPC-Book3S-HV-XIVE-Resend-re-routed-interrupts-o.patch
new file mode 100644
index 0000000000..cefdc88b69
--- /dev/null
+++ b/patches.arch/KVM-PPC-Book3S-HV-XIVE-Resend-re-routed-interrupts-o.patch
@@ -0,0 +1,181 @@
+From 9dc81d6b0f1e3c40bdf97671dd26a24f128e1182 Mon Sep 17 00:00:00 2001
+From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Date: Thu, 10 May 2018 13:06:42 +1000
+Subject: [PATCH] KVM: PPC: Book3S HV: XIVE: Resend re-routed interrupts on CPU
+ priority change
+
+References: bsc#1061840
+Patch-mainline: v4.17-rc7
+Git-commit: 9dc81d6b0f1e3c40bdf97671dd26a24f128e1182
+
+When a vcpu priority (CPPR) is set to a lower value (masking more
+interrupts), we stop processing interrupts already in the queue
+for the priorities that have now been masked.
+
+If those interrupts were previously re-routed to a different
+CPU, they might still be stuck until the older one that has
+them in its queue processes them. In the case of guest CPU
+unplug, that can be never.
+
+To address that without creating additional overhead for
+the normal interrupt processing path, this changes H_CPPR
+handling so that when such a priority change occurs, we
+scan the interrupt queue for that vCPU, and for any
+interrupt in there that has been re-routed, we replace it
+with a dummy and force a re-trigger.
+
+Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Tested-by: Alexey Kardashevskiy <aik@ozlabs.ru>
+Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
+Acked-by: Michal Suchanek <msuchanek@suse.de>
+---
+ arch/powerpc/kvm/book3s_xive_template.c | 108 +++++++++++++++++++++++++++++---
+ 1 file changed, 101 insertions(+), 7 deletions(-)
+
+diff --git a/arch/powerpc/kvm/book3s_xive_template.c b/arch/powerpc/kvm/book3s_xive_template.c
+index c7a5deadd1cc..99c3620b40d9 100644
+--- a/arch/powerpc/kvm/book3s_xive_template.c
++++ b/arch/powerpc/kvm/book3s_xive_template.c
+@@ -11,6 +11,9 @@
+ #define XGLUE(a,b) a##b
+ #define GLUE(a,b) XGLUE(a,b)
+
++/* Dummy interrupt used when taking interrupts out of a queue in H_CPPR */
++#define XICS_DUMMY 1
++
+ static void GLUE(X_PFX,ack_pending)(struct kvmppc_xive_vcpu *xc)
+ {
+ u8 cppr;
+@@ -205,6 +208,10 @@ static u32 GLUE(X_PFX,scan_interrupts)(struct kvmppc_xive_vcpu *xc,
+ goto skip_ipi;
+ }
+
++ /* If it's the dummy interrupt, continue searching */
++ if (hirq == XICS_DUMMY)
++ goto skip_ipi;
++
+ /* If fetching, update queue pointers */
+ if (scan_type == scan_fetch) {
+ q->idx = idx;
+@@ -385,9 +392,76 @@ static void GLUE(X_PFX,push_pending_to_hw)(struct kvmppc_xive_vcpu *xc)
+ __x_writeb(prio, __x_tima + TM_SPC_SET_OS_PENDING);
+ }
+
++static void GLUE(X_PFX,scan_for_rerouted_irqs)(struct kvmppc_xive *xive,
++ struct kvmppc_xive_vcpu *xc)
++{
++ unsigned int prio;
++
++ /* For each priority that is now masked */
++ for (prio = xc->cppr; prio < KVMPPC_XIVE_Q_COUNT; prio++) {
++ struct xive_q *q = &xc->queues[prio];
++ struct kvmppc_xive_irq_state *state;
++ struct kvmppc_xive_src_block *sb;
++ u32 idx, toggle, entry, irq, hw_num;
++ struct xive_irq_data *xd;
++ __be32 *qpage;
++ u16 src;
++
++ idx = q->idx;
++ toggle = q->toggle;
++ qpage = READ_ONCE(q->qpage);
++ if (!qpage)
++ continue;
++
++ /* For each interrupt in the queue */
++ for (;;) {
++ entry = be32_to_cpup(qpage + idx);
++
++ /* No more ? */
++ if ((entry >> 31) == toggle)
++ break;
++ irq = entry & 0x7fffffff;
++
++ /* Skip dummies and IPIs */
++ if (irq == XICS_DUMMY || irq == XICS_IPI)
++ goto next;
++ sb = kvmppc_xive_find_source(xive, irq, &src);
++ if (!sb)
++ goto next;
++ state = &sb->irq_state[src];
++
++ /* Has it been rerouted ? */
++ if (xc->server_num == state->act_server)
++ goto next;
++
++ /*
++ * Allright, it *has* been re-routed, kill it from
++ * the queue.
++ */
++ qpage[idx] = cpu_to_be32((entry & 0x80000000) | XICS_DUMMY);
++
++ /* Find the HW interrupt */
++ kvmppc_xive_select_irq(state, &hw_num, &xd);
++
++ /* If it's not an LSI, set PQ to 11 the EOI will force a resend */
++ if (!(xd->flags & XIVE_IRQ_FLAG_LSI))
++ GLUE(X_PFX,esb_load)(xd, XIVE_ESB_SET_PQ_11);
++
++ /* EOI the source */
++ GLUE(X_PFX,source_eoi)(hw_num, xd);
++
++ next:
++ idx = (idx + 1) & q->msk;
++ if (idx == 0)
++ toggle ^= 1;
++ }
++ }
++}
++
+ X_STATIC int GLUE(X_PFX,h_cppr)(struct kvm_vcpu *vcpu, unsigned long cppr)
+ {
+ struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
++ struct kvmppc_xive *xive = vcpu->kvm->arch.xive;
+ u8 old_cppr;
+
+ pr_devel("H_CPPR(cppr=%ld)\n", cppr);
+@@ -407,14 +481,34 @@ X_STATIC int GLUE(X_PFX,h_cppr)(struct kvm_vcpu *vcpu, unsigned long cppr)
+ */
+ smp_mb();
+
+- /*
+- * We are masking less, we need to look for pending things
+- * to deliver and set VP pending bits accordingly to trigger
+- * a new interrupt otherwise we might miss MFRR changes for
+- * which we have optimized out sending an IPI signal.
+- */
+- if (cppr > old_cppr)
++ if (cppr > old_cppr) {
++ /*
++ * We are masking less, we need to look for pending things
++ * to deliver and set VP pending bits accordingly to trigger
++ * a new interrupt otherwise we might miss MFRR changes for
++ * which we have optimized out sending an IPI signal.
++ */
+ GLUE(X_PFX,push_pending_to_hw)(xc);
++ } else {
++ /*
++ * We are masking more, we need to check the queue for any
++ * interrupt that has been routed to another CPU, take
++ * it out (replace it with the dummy) and retrigger it.
++ *
++ * This is necessary since those interrupts may otherwise
++ * never be processed, at least not until this CPU restores
++ * its CPPR.
++ *
++ * This is in theory racy vs. HW adding new interrupts to
++ * the queue. In practice this works because the interesting
++ * cases are when the guest has done a set_xive() to move the
++ * interrupt away, which flushes the xive, followed by the
++ * target CPU doing a H_CPPR. So any new interrupt coming into
++ * the queue must still be routed to us and isn't a source
++ * of concern.
++ */
++ GLUE(X_PFX,scan_for_rerouted_irqs)(xive, xc);
++ }
+
+ /* Apply new CPPR */
+ xc->hw_cppr = cppr;
+--
+2.13.7
+
diff --git a/series.conf b/series.conf
index 49be9c6e79..2deb14097d 100644
--- a/series.conf
+++ b/series.conf
@@ -15766,6 +15766,7 @@
patches.arch/KVM-PPC-Book3S-HV-Snapshot-timebase-offset-on-guest-.patch
patches.arch/KVM-PPC-Book3S-HV-Make-radix-use-correct-tlbie-seque.patch
patches.arch/KVM-PPC-Book3S-HV-Make-radix-clear-pte-when-unmappin.patch
+ patches.arch/KVM-PPC-Book3S-HV-XIVE-Resend-re-routed-interrupts-o.patch
patches.arch/x86-kvm-fix-lapic-timer-drift-when-guest-uses-periodic-mode
patches.arch/kvm-x86-update-cpuid-properly-when-cr4-osxave-or-cr4-pke-is-changed
patches.arch/46-kvm-x86-ia32_arch_capabilities-is-always-supported.patch