Commit 5b06d167 authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Michael Ellerman

powerpc/pseries: Use doorbells even if XIVE is available

KVM supports msgsndp in guests by trapping and emulating the
instruction, so it was decided to always use XIVE for IPIs if it is
available. However on PowerVM systems, msgsndp can be used and gives
better performance. On large systems, high XIVE interrupt rates can
have sub-linear scaling, and using msgsndp can reduce the load on
the interrupt controller.

So switch to using core local doorbells even if XIVE is available.
This reduces performance for KVM guests with an SMT topology by
about 50% for ping-pong context switching between SMT vCPUs. An
option vector (or dt-cpu-ftrs) could be defined to disable msgsndp
to get KVM performance back.
Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
Tested-by: default avatarCédric Le Goater <clg@kaod.org>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200726035155.1424103-3-npiggin@gmail.com
parent 1f0ce497
...@@ -162,13 +162,16 @@ static int pseries_smp_prepare_cpu(int cpu) ...@@ -162,13 +162,16 @@ static int pseries_smp_prepare_cpu(int cpu)
return 0; return 0;
} }
static void smp_pseries_cause_ipi(int cpu) /* Cause IPI as setup by the interrupt controller (xics or xive) */
static void (*ic_cause_ipi)(int cpu) __ro_after_init;
/* Use msgsndp doorbells target is a sibling, else use interrupt controller */
static void dbell_or_ic_cause_ipi(int cpu)
{ {
/* POWER9 should not use this handler */
if (doorbell_try_core_ipi(cpu)) if (doorbell_try_core_ipi(cpu))
return; return;
icp_ops->cause_ipi(cpu); ic_cause_ipi(cpu);
} }
static int pseries_cause_nmi_ipi(int cpu) static int pseries_cause_nmi_ipi(int cpu)
...@@ -192,26 +195,41 @@ static int pseries_cause_nmi_ipi(int cpu) ...@@ -192,26 +195,41 @@ static int pseries_cause_nmi_ipi(int cpu)
return 0; return 0;
} }
static __init void pSeries_smp_probe_xics(void)
{
xics_smp_probe();
if (cpu_has_feature(CPU_FTR_DBELL) && !is_secure_guest())
smp_ops->cause_ipi = smp_pseries_cause_ipi;
else
smp_ops->cause_ipi = icp_ops->cause_ipi;
}
static __init void pSeries_smp_probe(void) static __init void pSeries_smp_probe(void)
{ {
if (xive_enabled()) if (xive_enabled())
/*
* Don't use P9 doorbells when XIVE is enabled. IPIs
* using MMIOs should be faster
*/
xive_smp_probe(); xive_smp_probe();
else else
pSeries_smp_probe_xics(); xics_smp_probe();
/* No doorbell facility, must use the interrupt controller for IPIs */
if (!cpu_has_feature(CPU_FTR_DBELL))
return;
/* Doorbells can only be used for IPIs between SMT siblings */
if (!cpu_has_feature(CPU_FTR_SMT))
return;
/*
* KVM emulates doorbells by disabling FSCR[MSGP] so msgsndp faults
* to the hypervisor which then reads the instruction from guest
* memory. This can't be done if the guest is secure, so don't use
* doorbells in secure guests.
*
* Under PowerVM, FSCR[MSGP] is enabled so doorbells could be used
* by secure guests if we distinguished this from KVM.
*/
if (is_secure_guest())
return;
/*
* The guest can use doobells for SMT sibling IPIs, which stay in
* the core rather than going to the interrupt controller. This
* tends to be slower under KVM where doorbells are emulated, but
* faster for PowerVM where they're enabled.
*/
ic_cause_ipi = smp_ops->cause_ipi;
smp_ops->cause_ipi = dbell_or_ic_cause_ipi;
} }
static struct smp_ops_t pseries_smp_ops = { static struct smp_ops_t pseries_smp_ops = {
......
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