powerpc/pseries: Add KVM guest doorbell restrictions
authorNicholas Piggin <npiggin@gmail.com>
Sun, 26 Jul 2020 03:51:55 +0000 (13:51 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 29 Jul 2020 11:02:10 +0000 (21:02 +1000)
KVM guests have certain restrictions and performance quirks when using
doorbells. This patch moves the EPAPR KVM guest test so it can be shared
with PSERIES, and uses that in doorbell setup code to apply the KVM
guest quirks and  improves IPI performance for two cases:

 - PowerVM guests may now use doorbells even if they are secure.

 - KVM guests no longer use doorbells if XIVE is available.

There is a valid complaint that "KVM guest" is not a very reasonable
thing to test for, it's preferable for the hypervisor to advertise
particular behaviours to the guest so they could change if the
hypervisor implementation or configuration changes. However in this case
we were already assuming a KVM guest worst case, so this patch is about
containing those quirks. If KVM later advertises fast doorbells, we
should test for that and override the quirks.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Tested-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200726035155.1424103-4-npiggin@gmail.com
arch/powerpc/include/asm/firmware.h
arch/powerpc/include/asm/kvm_para.h
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/firmware.c
arch/powerpc/platforms/pseries/smp.c

index 6003c2e533a082d4d10a6c3ab10353b507f17720..f67efbaba17f54ea631a40b0b51414a25a80ff89 100644 (file)
@@ -132,6 +132,12 @@ extern int ibm_nmi_interlock_token;
 
 extern unsigned int __start___fw_ftr_fixup, __stop___fw_ftr_fixup;
 
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_KVM_GUEST)
+bool is_kvm_guest(void);
+#else
+static inline bool is_kvm_guest(void) { return false; }
+#endif
+
 #ifdef CONFIG_PPC_PSERIES
 void pseries_probe_fw_features(void);
 #else
index 9c1f6b4b9bbf478cd45645f97f8aaa09731338b2..744612054c94ca9e6266aaa8e919463074351d13 100644 (file)
@@ -8,35 +8,15 @@
 #ifndef __POWERPC_KVM_PARA_H__
 #define __POWERPC_KVM_PARA_H__
 
-#include <uapi/asm/kvm_para.h>
-
-#ifdef CONFIG_KVM_GUEST
-
-#include <linux/of.h>
-
-static inline int kvm_para_available(void)
-{
-       struct device_node *hyper_node;
-
-       hyper_node = of_find_node_by_path("/hypervisor");
-       if (!hyper_node)
-               return 0;
+#include <asm/firmware.h>
 
-       if (!of_device_is_compatible(hyper_node, "linux,kvm"))
-               return 0;
-
-       return 1;
-}
-
-#else
+#include <uapi/asm/kvm_para.h>
 
 static inline int kvm_para_available(void)
 {
-       return 0;
+       return IS_ENABLED(CONFIG_KVM_GUEST) && is_kvm_guest();
 }
 
-#endif
-
 static inline unsigned int kvm_arch_para_features(void)
 {
        unsigned long r;
index c5211bdcf1b627a0086bce2a9590348beaed2210..d4d5946224f8e50fa6085c93538b92ee5b6c2195 100644 (file)
@@ -45,11 +45,10 @@ obj-y                               := cputable.o syscalls.o \
                                   signal.o sysfs.o cacheinfo.o time.o \
                                   prom.o traps.o setup-common.o \
                                   udbg.o misc.o io.o misc_$(BITS).o \
-                                  of_platform.o prom_parse.o
+                                  of_platform.o prom_parse.o firmware.o
 obj-y                          += ptrace/
 obj-$(CONFIG_PPC64)            += setup_64.o \
-                                  paca.o nvram_64.o firmware.o note.o \
-                                  syscall_64.o
+                                  paca.o nvram_64.o note.o syscall_64.o
 obj-$(CONFIG_COMPAT)           += sys_ppc32.o signal_32.o
 obj-$(CONFIG_VDSO32)           += vdso32/
 obj-$(CONFIG_PPC_WATCHDOG)     += watchdog.o
index cc4a5e3f51f14bf2c3557e0971ab07d2d5c3e9f8..fe48d319d490e651b44c7806efd20fcbcc6b6001 100644 (file)
 
 #include <linux/export.h>
 #include <linux/cache.h>
+#include <linux/of.h>
 
 #include <asm/firmware.h>
 
+#ifdef CONFIG_PPC64
 unsigned long powerpc_firmware_features __read_mostly;
 EXPORT_SYMBOL_GPL(powerpc_firmware_features);
+#endif
+
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_KVM_GUEST)
+bool is_kvm_guest(void)
+{
+       struct device_node *hyper_node;
+
+       hyper_node = of_find_node_by_path("/hypervisor");
+       if (!hyper_node)
+               return 0;
+
+       if (!of_device_is_compatible(hyper_node, "linux,kvm"))
+               return 0;
+
+       return 1;
+}
+#endif
index a1cb861154e98e5ae3a09088aa98d6d8db93a2c9..92922491a81c6bd161f0e704529c4ada1d2edab0 100644 (file)
@@ -210,24 +210,32 @@ static __init void pSeries_smp_probe(void)
        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;
+       if (is_kvm_guest()) {
+               /*
+                * KVM emulates doorbells by disabling FSCR[MSGP] so msgsndp
+                * faults to the hypervisor which then reads the instruction
+                * from guest memory, which tends to be slower than using XIVE.
+                */
+               if (xive_enabled())
+                       return;
+
+               /*
+                * XICS hcalls aren't as fast, so we can use msgsndp (which
+                * also helps exercise KVM emulation), however KVM can't
+                * emulate secure guests because it can't read the instruction
+                * out of their memory.
+                */
+               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.
+        * Under PowerVM, FSCR[MSGP] is enabled as guest vCPU siblings are
+        * gang scheduled on the same physical core, so doorbells are always
+        * faster than the interrupt controller, and they can be used by
+        * secure guests.
         */
+
        ic_cause_ipi = smp_ops->cause_ipi;
        smp_ops->cause_ipi = dbell_or_ic_cause_ipi;
 }