KVM: arm/arm64: Factor out hypercall handling from PSCI code
authorChristoffer Dall <christoffer.dall@arm.com>
Mon, 21 Oct 2019 15:28:15 +0000 (16:28 +0100)
committerMarc Zyngier <maz@kernel.org>
Mon, 21 Oct 2019 18:20:26 +0000 (19:20 +0100)
We currently intertwine the KVM PSCI implementation with the general
dispatch of hypercall handling, which makes perfect sense because PSCI
is the only category of hypercalls we support.

However, as we are about to support additional hypercalls, factor out
this functionality into a separate hypercall handler file.

Signed-off-by: Christoffer Dall <christoffer.dall@arm.com>
[steven.price@arm.com: rebased]
Reviewed-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Steven Price <steven.price@arm.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm/kvm/Makefile
arch/arm/kvm/handle_exit.c
arch/arm64/kvm/Makefile
arch/arm64/kvm/handle_exit.c
include/Kbuild
include/kvm/arm_hypercalls.h [new file with mode: 0644]
include/kvm/arm_psci.h
virt/kvm/arm/hypercalls.c [new file with mode: 0644]
virt/kvm/arm/psci.c

index b76b75bd9e00510570d69358c67940392ad6e067..e442d82821df50dbd35156ee2f0476f46f3e7d17 100644 (file)
@@ -24,7 +24,7 @@ obj-y += kvm-arm.o init.o interrupts.o
 obj-y += handle_exit.o guest.o emulate.o reset.o
 obj-y += coproc.o coproc_a15.o coproc_a7.o   vgic-v3-coproc.o
 obj-y += $(KVM)/arm/arm.o $(KVM)/arm/mmu.o $(KVM)/arm/mmio.o
-obj-y += $(KVM)/arm/psci.o $(KVM)/arm/perf.o
+obj-y += $(KVM)/arm/psci.o $(KVM)/arm/perf.o $(KVM)/arm/hypercalls.o
 obj-y += $(KVM)/arm/aarch32.o
 
 obj-y += $(KVM)/arm/vgic/vgic.o
index 2a6a1394d26ea3d1a1385fc7ece848599968d03f..e58a89d2f13ff72fae86b1e04578701b90669447 100644 (file)
@@ -9,7 +9,7 @@
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_coproc.h>
 #include <asm/kvm_mmu.h>
-#include <kvm/arm_psci.h>
+#include <kvm/arm_hypercalls.h>
 #include <trace/events/kvm.h>
 
 #include "trace.h"
index 3ac1a64d2fb9d736e5c2a2bfa778f450a13bee0b..73dce4d47d473dfbcf4399089d677f27a803d3ba 100644 (file)
@@ -13,6 +13,7 @@ obj-$(CONFIG_KVM_ARM_HOST) += hyp/
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o $(KVM)/vfio.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arm.o $(KVM)/arm/mmu.o $(KVM)/arm/mmio.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/psci.o $(KVM)/arm/perf.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hypercalls.o
 
 kvm-$(CONFIG_KVM_ARM_HOST) += inject_fault.o regmap.o va_layout.o
 kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
index 706cca23f0d2ecdac1aabb862b216966070fa135..aacfc55de44cb90cc641186bbc1512f2652a6faf 100644 (file)
@@ -11,8 +11,6 @@
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 
-#include <kvm/arm_psci.h>
-
 #include <asm/esr.h>
 #include <asm/exception.h>
 #include <asm/kvm_asm.h>
@@ -22,6 +20,8 @@
 #include <asm/debug-monitors.h>
 #include <asm/traps.h>
 
+#include <kvm/arm_hypercalls.h>
+
 #define CREATE_TRACE_POINTS
 #include "trace.h"
 
index ffba79483cc5edad5f3327a624bd0c1bba2aa822..e8154f8bcac5bedf0018876896f9d57ff941e06d 100644 (file)
@@ -67,6 +67,8 @@ header-test-                  += keys/big_key-type.h
 header-test-                   += keys/request_key_auth-type.h
 header-test-                   += keys/trusted.h
 header-test-                   += kvm/arm_arch_timer.h
+header-test-$(CONFIG_ARM)      += kvm/arm_hypercalls.h
+header-test-$(CONFIG_ARM64)    += kvm/arm_hypercalls.h
 header-test-                   += kvm/arm_pmu.h
 header-test-$(CONFIG_ARM)      += kvm/arm_psci.h
 header-test-$(CONFIG_ARM64)    += kvm/arm_psci.h
diff --git a/include/kvm/arm_hypercalls.h b/include/kvm/arm_hypercalls.h
new file mode 100644 (file)
index 0000000..0e2509d
--- /dev/null
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2019 Arm Ltd. */
+
+#ifndef __KVM_ARM_HYPERCALLS_H
+#define __KVM_ARM_HYPERCALLS_H
+
+#include <asm/kvm_emulate.h>
+
+int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
+
+static inline u32 smccc_get_function(struct kvm_vcpu *vcpu)
+{
+       return vcpu_get_reg(vcpu, 0);
+}
+
+static inline unsigned long smccc_get_arg1(struct kvm_vcpu *vcpu)
+{
+       return vcpu_get_reg(vcpu, 1);
+}
+
+static inline unsigned long smccc_get_arg2(struct kvm_vcpu *vcpu)
+{
+       return vcpu_get_reg(vcpu, 2);
+}
+
+static inline unsigned long smccc_get_arg3(struct kvm_vcpu *vcpu)
+{
+       return vcpu_get_reg(vcpu, 3);
+}
+
+static inline void smccc_set_retval(struct kvm_vcpu *vcpu,
+                                   unsigned long a0,
+                                   unsigned long a1,
+                                   unsigned long a2,
+                                   unsigned long a3)
+{
+       vcpu_set_reg(vcpu, 0, a0);
+       vcpu_set_reg(vcpu, 1, a1);
+       vcpu_set_reg(vcpu, 2, a2);
+       vcpu_set_reg(vcpu, 3, a3);
+}
+
+#endif
index 632e78bdef4dfdebc664daf1b2811a8f285ba212..5b58bd2fe088b1fc052e4c13c611abfbbd06773b 100644 (file)
@@ -40,7 +40,7 @@ static inline int kvm_psci_version(struct kvm_vcpu *vcpu, struct kvm *kvm)
 }
 
 
-int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
+int kvm_psci_call(struct kvm_vcpu *vcpu);
 
 struct kvm_one_reg;
 
diff --git a/virt/kvm/arm/hypercalls.c b/virt/kvm/arm/hypercalls.c
new file mode 100644 (file)
index 0000000..f875241
--- /dev/null
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2019 Arm Ltd.
+
+#include <linux/arm-smccc.h>
+#include <linux/kvm_host.h>
+
+#include <asm/kvm_emulate.h>
+
+#include <kvm/arm_hypercalls.h>
+#include <kvm/arm_psci.h>
+
+int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
+{
+       u32 func_id = smccc_get_function(vcpu);
+       u32 val = SMCCC_RET_NOT_SUPPORTED;
+       u32 feature;
+
+       switch (func_id) {
+       case ARM_SMCCC_VERSION_FUNC_ID:
+               val = ARM_SMCCC_VERSION_1_1;
+               break;
+       case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
+               feature = smccc_get_arg1(vcpu);
+               switch (feature) {
+               case ARM_SMCCC_ARCH_WORKAROUND_1:
+                       switch (kvm_arm_harden_branch_predictor()) {
+                       case KVM_BP_HARDEN_UNKNOWN:
+                               break;
+                       case KVM_BP_HARDEN_WA_NEEDED:
+                               val = SMCCC_RET_SUCCESS;
+                               break;
+                       case KVM_BP_HARDEN_NOT_REQUIRED:
+                               val = SMCCC_RET_NOT_REQUIRED;
+                               break;
+                       }
+                       break;
+               case ARM_SMCCC_ARCH_WORKAROUND_2:
+                       switch (kvm_arm_have_ssbd()) {
+                       case KVM_SSBD_FORCE_DISABLE:
+                       case KVM_SSBD_UNKNOWN:
+                               break;
+                       case KVM_SSBD_KERNEL:
+                               val = SMCCC_RET_SUCCESS;
+                               break;
+                       case KVM_SSBD_FORCE_ENABLE:
+                       case KVM_SSBD_MITIGATED:
+                               val = SMCCC_RET_NOT_REQUIRED;
+                               break;
+                       }
+                       break;
+               }
+               break;
+       default:
+               return kvm_psci_call(vcpu);
+       }
+
+       smccc_set_retval(vcpu, val, 0, 0, 0);
+       return 1;
+}
index 87927f7e1ee7072f714958ded4ff2da1126b8fa5..17e2bdd4b76f5e7bccc892ed41d746adc7bc9751 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/kvm_host.h>
 
 #include <kvm/arm_psci.h>
+#include <kvm/arm_hypercalls.h>
 
 /*
  * This is an implementation of the Power State Coordination Interface
 
 #define AFFINITY_MASK(level)   ~((0x1UL << ((level) * MPIDR_LEVEL_BITS)) - 1)
 
-static u32 smccc_get_function(struct kvm_vcpu *vcpu)
-{
-       return vcpu_get_reg(vcpu, 0);
-}
-
-static unsigned long smccc_get_arg1(struct kvm_vcpu *vcpu)
-{
-       return vcpu_get_reg(vcpu, 1);
-}
-
-static unsigned long smccc_get_arg2(struct kvm_vcpu *vcpu)
-{
-       return vcpu_get_reg(vcpu, 2);
-}
-
-static unsigned long smccc_get_arg3(struct kvm_vcpu *vcpu)
-{
-       return vcpu_get_reg(vcpu, 3);
-}
-
-static void smccc_set_retval(struct kvm_vcpu *vcpu,
-                            unsigned long a0,
-                            unsigned long a1,
-                            unsigned long a2,
-                            unsigned long a3)
-{
-       vcpu_set_reg(vcpu, 0, a0);
-       vcpu_set_reg(vcpu, 1, a1);
-       vcpu_set_reg(vcpu, 2, a2);
-       vcpu_set_reg(vcpu, 3, a3);
-}
-
 static unsigned long psci_affinity_mask(unsigned long affinity_level)
 {
        if (affinity_level <= 3)
@@ -373,7 +342,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
  * Errors:
  * -EINVAL: Unrecognized PSCI function
  */
-static int kvm_psci_call(struct kvm_vcpu *vcpu)
+int kvm_psci_call(struct kvm_vcpu *vcpu)
 {
        switch (kvm_psci_version(vcpu, vcpu->kvm)) {
        case KVM_ARM_PSCI_1_0:
@@ -387,55 +356,6 @@ static int kvm_psci_call(struct kvm_vcpu *vcpu)
        };
 }
 
-int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
-{
-       u32 func_id = smccc_get_function(vcpu);
-       u32 val = SMCCC_RET_NOT_SUPPORTED;
-       u32 feature;
-
-       switch (func_id) {
-       case ARM_SMCCC_VERSION_FUNC_ID:
-               val = ARM_SMCCC_VERSION_1_1;
-               break;
-       case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
-               feature = smccc_get_arg1(vcpu);
-               switch(feature) {
-               case ARM_SMCCC_ARCH_WORKAROUND_1:
-                       switch (kvm_arm_harden_branch_predictor()) {
-                       case KVM_BP_HARDEN_UNKNOWN:
-                               break;
-                       case KVM_BP_HARDEN_WA_NEEDED:
-                               val = SMCCC_RET_SUCCESS;
-                               break;
-                       case KVM_BP_HARDEN_NOT_REQUIRED:
-                               val = SMCCC_RET_NOT_REQUIRED;
-                               break;
-                       }
-                       break;
-               case ARM_SMCCC_ARCH_WORKAROUND_2:
-                       switch (kvm_arm_have_ssbd()) {
-                       case KVM_SSBD_FORCE_DISABLE:
-                       case KVM_SSBD_UNKNOWN:
-                               break;
-                       case KVM_SSBD_KERNEL:
-                               val = SMCCC_RET_SUCCESS;
-                               break;
-                       case KVM_SSBD_FORCE_ENABLE:
-                       case KVM_SSBD_MITIGATED:
-                               val = SMCCC_RET_NOT_REQUIRED;
-                               break;
-                       }
-                       break;
-               }
-               break;
-       default:
-               return kvm_psci_call(vcpu);
-       }
-
-       smccc_set_retval(vcpu, val, 0, 0, 0);
-       return 1;
-}
-
 int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu)
 {
        return 3;               /* PSCI version and two workaround registers */