Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: arm/arm64: Factor out hypercall handling from PSCI code

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>

authored by

Christoffer Dall and committed by
Marc Zyngier
55009c6e 6a745848

+112 -87
+1 -1
arch/arm/kvm/Makefile
··· 24 24 obj-y += handle_exit.o guest.o emulate.o reset.o 25 25 obj-y += coproc.o coproc_a15.o coproc_a7.o vgic-v3-coproc.o 26 26 obj-y += $(KVM)/arm/arm.o $(KVM)/arm/mmu.o $(KVM)/arm/mmio.o 27 - obj-y += $(KVM)/arm/psci.o $(KVM)/arm/perf.o 27 + obj-y += $(KVM)/arm/psci.o $(KVM)/arm/perf.o $(KVM)/arm/hypercalls.o 28 28 obj-y += $(KVM)/arm/aarch32.o 29 29 30 30 obj-y += $(KVM)/arm/vgic/vgic.o
+1 -1
arch/arm/kvm/handle_exit.c
··· 9 9 #include <asm/kvm_emulate.h> 10 10 #include <asm/kvm_coproc.h> 11 11 #include <asm/kvm_mmu.h> 12 - #include <kvm/arm_psci.h> 12 + #include <kvm/arm_hypercalls.h> 13 13 #include <trace/events/kvm.h> 14 14 15 15 #include "trace.h"
+1
arch/arm64/kvm/Makefile
··· 13 13 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o $(KVM)/vfio.o 14 14 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arm.o $(KVM)/arm/mmu.o $(KVM)/arm/mmio.o 15 15 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/psci.o $(KVM)/arm/perf.o 16 + kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hypercalls.o 16 17 17 18 kvm-$(CONFIG_KVM_ARM_HOST) += inject_fault.o regmap.o va_layout.o 18 19 kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
+2 -2
arch/arm64/kvm/handle_exit.c
··· 11 11 #include <linux/kvm.h> 12 12 #include <linux/kvm_host.h> 13 13 14 - #include <kvm/arm_psci.h> 15 - 16 14 #include <asm/esr.h> 17 15 #include <asm/exception.h> 18 16 #include <asm/kvm_asm.h> ··· 19 21 #include <asm/kvm_mmu.h> 20 22 #include <asm/debug-monitors.h> 21 23 #include <asm/traps.h> 24 + 25 + #include <kvm/arm_hypercalls.h> 22 26 23 27 #define CREATE_TRACE_POINTS 24 28 #include "trace.h"
+2
include/Kbuild
··· 67 67 header-test- += keys/request_key_auth-type.h 68 68 header-test- += keys/trusted.h 69 69 header-test- += kvm/arm_arch_timer.h 70 + header-test-$(CONFIG_ARM) += kvm/arm_hypercalls.h 71 + header-test-$(CONFIG_ARM64) += kvm/arm_hypercalls.h 70 72 header-test- += kvm/arm_pmu.h 71 73 header-test-$(CONFIG_ARM) += kvm/arm_psci.h 72 74 header-test-$(CONFIG_ARM64) += kvm/arm_psci.h
+43
include/kvm/arm_hypercalls.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (C) 2019 Arm Ltd. */ 3 + 4 + #ifndef __KVM_ARM_HYPERCALLS_H 5 + #define __KVM_ARM_HYPERCALLS_H 6 + 7 + #include <asm/kvm_emulate.h> 8 + 9 + int kvm_hvc_call_handler(struct kvm_vcpu *vcpu); 10 + 11 + static inline u32 smccc_get_function(struct kvm_vcpu *vcpu) 12 + { 13 + return vcpu_get_reg(vcpu, 0); 14 + } 15 + 16 + static inline unsigned long smccc_get_arg1(struct kvm_vcpu *vcpu) 17 + { 18 + return vcpu_get_reg(vcpu, 1); 19 + } 20 + 21 + static inline unsigned long smccc_get_arg2(struct kvm_vcpu *vcpu) 22 + { 23 + return vcpu_get_reg(vcpu, 2); 24 + } 25 + 26 + static inline unsigned long smccc_get_arg3(struct kvm_vcpu *vcpu) 27 + { 28 + return vcpu_get_reg(vcpu, 3); 29 + } 30 + 31 + static inline void smccc_set_retval(struct kvm_vcpu *vcpu, 32 + unsigned long a0, 33 + unsigned long a1, 34 + unsigned long a2, 35 + unsigned long a3) 36 + { 37 + vcpu_set_reg(vcpu, 0, a0); 38 + vcpu_set_reg(vcpu, 1, a1); 39 + vcpu_set_reg(vcpu, 2, a2); 40 + vcpu_set_reg(vcpu, 3, a3); 41 + } 42 + 43 + #endif
+1 -1
include/kvm/arm_psci.h
··· 40 40 } 41 41 42 42 43 - int kvm_hvc_call_handler(struct kvm_vcpu *vcpu); 43 + int kvm_psci_call(struct kvm_vcpu *vcpu); 44 44 45 45 struct kvm_one_reg; 46 46
+59
virt/kvm/arm/hypercalls.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (C) 2019 Arm Ltd. 3 + 4 + #include <linux/arm-smccc.h> 5 + #include <linux/kvm_host.h> 6 + 7 + #include <asm/kvm_emulate.h> 8 + 9 + #include <kvm/arm_hypercalls.h> 10 + #include <kvm/arm_psci.h> 11 + 12 + int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) 13 + { 14 + u32 func_id = smccc_get_function(vcpu); 15 + u32 val = SMCCC_RET_NOT_SUPPORTED; 16 + u32 feature; 17 + 18 + switch (func_id) { 19 + case ARM_SMCCC_VERSION_FUNC_ID: 20 + val = ARM_SMCCC_VERSION_1_1; 21 + break; 22 + case ARM_SMCCC_ARCH_FEATURES_FUNC_ID: 23 + feature = smccc_get_arg1(vcpu); 24 + switch (feature) { 25 + case ARM_SMCCC_ARCH_WORKAROUND_1: 26 + switch (kvm_arm_harden_branch_predictor()) { 27 + case KVM_BP_HARDEN_UNKNOWN: 28 + break; 29 + case KVM_BP_HARDEN_WA_NEEDED: 30 + val = SMCCC_RET_SUCCESS; 31 + break; 32 + case KVM_BP_HARDEN_NOT_REQUIRED: 33 + val = SMCCC_RET_NOT_REQUIRED; 34 + break; 35 + } 36 + break; 37 + case ARM_SMCCC_ARCH_WORKAROUND_2: 38 + switch (kvm_arm_have_ssbd()) { 39 + case KVM_SSBD_FORCE_DISABLE: 40 + case KVM_SSBD_UNKNOWN: 41 + break; 42 + case KVM_SSBD_KERNEL: 43 + val = SMCCC_RET_SUCCESS; 44 + break; 45 + case KVM_SSBD_FORCE_ENABLE: 46 + case KVM_SSBD_MITIGATED: 47 + val = SMCCC_RET_NOT_REQUIRED; 48 + break; 49 + } 50 + break; 51 + } 52 + break; 53 + default: 54 + return kvm_psci_call(vcpu); 55 + } 56 + 57 + smccc_set_retval(vcpu, val, 0, 0, 0); 58 + return 1; 59 + }
+2 -82
virt/kvm/arm/psci.c
··· 15 15 #include <asm/kvm_host.h> 16 16 17 17 #include <kvm/arm_psci.h> 18 + #include <kvm/arm_hypercalls.h> 18 19 19 20 /* 20 21 * This is an implementation of the Power State Coordination Interface ··· 23 22 */ 24 23 25 24 #define AFFINITY_MASK(level) ~((0x1UL << ((level) * MPIDR_LEVEL_BITS)) - 1) 26 - 27 - static u32 smccc_get_function(struct kvm_vcpu *vcpu) 28 - { 29 - return vcpu_get_reg(vcpu, 0); 30 - } 31 - 32 - static unsigned long smccc_get_arg1(struct kvm_vcpu *vcpu) 33 - { 34 - return vcpu_get_reg(vcpu, 1); 35 - } 36 - 37 - static unsigned long smccc_get_arg2(struct kvm_vcpu *vcpu) 38 - { 39 - return vcpu_get_reg(vcpu, 2); 40 - } 41 - 42 - static unsigned long smccc_get_arg3(struct kvm_vcpu *vcpu) 43 - { 44 - return vcpu_get_reg(vcpu, 3); 45 - } 46 - 47 - static void smccc_set_retval(struct kvm_vcpu *vcpu, 48 - unsigned long a0, 49 - unsigned long a1, 50 - unsigned long a2, 51 - unsigned long a3) 52 - { 53 - vcpu_set_reg(vcpu, 0, a0); 54 - vcpu_set_reg(vcpu, 1, a1); 55 - vcpu_set_reg(vcpu, 2, a2); 56 - vcpu_set_reg(vcpu, 3, a3); 57 - } 58 25 59 26 static unsigned long psci_affinity_mask(unsigned long affinity_level) 60 27 { ··· 342 373 * Errors: 343 374 * -EINVAL: Unrecognized PSCI function 344 375 */ 345 - static int kvm_psci_call(struct kvm_vcpu *vcpu) 376 + int kvm_psci_call(struct kvm_vcpu *vcpu) 346 377 { 347 378 switch (kvm_psci_version(vcpu, vcpu->kvm)) { 348 379 case KVM_ARM_PSCI_1_0: ··· 354 385 default: 355 386 return -EINVAL; 356 387 }; 357 - } 358 - 359 - int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) 360 - { 361 - u32 func_id = smccc_get_function(vcpu); 362 - u32 val = SMCCC_RET_NOT_SUPPORTED; 363 - u32 feature; 364 - 365 - switch (func_id) { 366 - case ARM_SMCCC_VERSION_FUNC_ID: 367 - val = ARM_SMCCC_VERSION_1_1; 368 - break; 369 - case ARM_SMCCC_ARCH_FEATURES_FUNC_ID: 370 - feature = smccc_get_arg1(vcpu); 371 - switch(feature) { 372 - case ARM_SMCCC_ARCH_WORKAROUND_1: 373 - switch (kvm_arm_harden_branch_predictor()) { 374 - case KVM_BP_HARDEN_UNKNOWN: 375 - break; 376 - case KVM_BP_HARDEN_WA_NEEDED: 377 - val = SMCCC_RET_SUCCESS; 378 - break; 379 - case KVM_BP_HARDEN_NOT_REQUIRED: 380 - val = SMCCC_RET_NOT_REQUIRED; 381 - break; 382 - } 383 - break; 384 - case ARM_SMCCC_ARCH_WORKAROUND_2: 385 - switch (kvm_arm_have_ssbd()) { 386 - case KVM_SSBD_FORCE_DISABLE: 387 - case KVM_SSBD_UNKNOWN: 388 - break; 389 - case KVM_SSBD_KERNEL: 390 - val = SMCCC_RET_SUCCESS; 391 - break; 392 - case KVM_SSBD_FORCE_ENABLE: 393 - case KVM_SSBD_MITIGATED: 394 - val = SMCCC_RET_NOT_REQUIRED; 395 - break; 396 - } 397 - break; 398 - } 399 - break; 400 - default: 401 - return kvm_psci_call(vcpu); 402 - } 403 - 404 - smccc_set_retval(vcpu, val, 0, 0, 0); 405 - return 1; 406 388 } 407 389 408 390 int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu)