Skip to content

Commit 55009c6

Browse files
christofferdall-armMarc Zyngier
authored andcommitted
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 <[email protected]> [[email protected]: rebased] Reviewed-by: Andrew Jones <[email protected]> Signed-off-by: Steven Price <[email protected]> Signed-off-by: Marc Zyngier <[email protected]>
1 parent 6a74584 commit 55009c6

File tree

9 files changed

+112
-87
lines changed

9 files changed

+112
-87
lines changed

arch/arm/kvm/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ obj-y += kvm-arm.o init.o interrupts.o
2424
obj-y += handle_exit.o guest.o emulate.o reset.o
2525
obj-y += coproc.o coproc_a15.o coproc_a7.o vgic-v3-coproc.o
2626
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
2828
obj-y += $(KVM)/arm/aarch32.o
2929

3030
obj-y += $(KVM)/arm/vgic/vgic.o

arch/arm/kvm/handle_exit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#include <asm/kvm_emulate.h>
1010
#include <asm/kvm_coproc.h>
1111
#include <asm/kvm_mmu.h>
12-
#include <kvm/arm_psci.h>
12+
#include <kvm/arm_hypercalls.h>
1313
#include <trace/events/kvm.h>
1414

1515
#include "trace.h"

arch/arm64/kvm/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ obj-$(CONFIG_KVM_ARM_HOST) += hyp/
1313
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o $(KVM)/vfio.o
1414
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arm.o $(KVM)/arm/mmu.o $(KVM)/arm/mmio.o
1515
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/psci.o $(KVM)/arm/perf.o
16+
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hypercalls.o
1617

1718
kvm-$(CONFIG_KVM_ARM_HOST) += inject_fault.o regmap.o va_layout.o
1819
kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o

arch/arm64/kvm/handle_exit.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
#include <linux/kvm.h>
1212
#include <linux/kvm_host.h>
1313

14-
#include <kvm/arm_psci.h>
15-
1614
#include <asm/esr.h>
1715
#include <asm/exception.h>
1816
#include <asm/kvm_asm.h>
@@ -22,6 +20,8 @@
2220
#include <asm/debug-monitors.h>
2321
#include <asm/traps.h>
2422

23+
#include <kvm/arm_hypercalls.h>
24+
2525
#define CREATE_TRACE_POINTS
2626
#include "trace.h"
2727

include/Kbuild

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ header-test- += keys/big_key-type.h
6767
header-test- += keys/request_key_auth-type.h
6868
header-test- += keys/trusted.h
6969
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
7072
header-test- += kvm/arm_pmu.h
7173
header-test-$(CONFIG_ARM) += kvm/arm_psci.h
7274
header-test-$(CONFIG_ARM64) += kvm/arm_psci.h

include/kvm/arm_hypercalls.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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

include/kvm/arm_psci.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ static inline int kvm_psci_version(struct kvm_vcpu *vcpu, struct kvm *kvm)
4040
}
4141

4242

43-
int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
43+
int kvm_psci_call(struct kvm_vcpu *vcpu);
4444

4545
struct kvm_one_reg;
4646

virt/kvm/arm/hypercalls.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
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+
}

virt/kvm/arm/psci.c

Lines changed: 2 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <asm/kvm_host.h>
1616

1717
#include <kvm/arm_psci.h>
18+
#include <kvm/arm_hypercalls.h>
1819

1920
/*
2021
* This is an implementation of the Power State Coordination Interface
@@ -23,38 +24,6 @@
2324

2425
#define AFFINITY_MASK(level) ~((0x1UL << ((level) * MPIDR_LEVEL_BITS)) - 1)
2526

26-
static u32 smccc_get_function(struct kvm_vcpu *vcpu)
27-
{
28-
return vcpu_get_reg(vcpu, 0);
29-
}
30-
31-
static unsigned long smccc_get_arg1(struct kvm_vcpu *vcpu)
32-
{
33-
return vcpu_get_reg(vcpu, 1);
34-
}
35-
36-
static unsigned long smccc_get_arg2(struct kvm_vcpu *vcpu)
37-
{
38-
return vcpu_get_reg(vcpu, 2);
39-
}
40-
41-
static unsigned long smccc_get_arg3(struct kvm_vcpu *vcpu)
42-
{
43-
return vcpu_get_reg(vcpu, 3);
44-
}
45-
46-
static void smccc_set_retval(struct kvm_vcpu *vcpu,
47-
unsigned long a0,
48-
unsigned long a1,
49-
unsigned long a2,
50-
unsigned long a3)
51-
{
52-
vcpu_set_reg(vcpu, 0, a0);
53-
vcpu_set_reg(vcpu, 1, a1);
54-
vcpu_set_reg(vcpu, 2, a2);
55-
vcpu_set_reg(vcpu, 3, a3);
56-
}
57-
5827
static unsigned long psci_affinity_mask(unsigned long affinity_level)
5928
{
6029
if (affinity_level <= 3)
@@ -373,7 +342,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
373342
* Errors:
374343
* -EINVAL: Unrecognized PSCI function
375344
*/
376-
static int kvm_psci_call(struct kvm_vcpu *vcpu)
345+
int kvm_psci_call(struct kvm_vcpu *vcpu)
377346
{
378347
switch (kvm_psci_version(vcpu, vcpu->kvm)) {
379348
case KVM_ARM_PSCI_1_0:
@@ -387,55 +356,6 @@ static int kvm_psci_call(struct kvm_vcpu *vcpu)
387356
};
388357
}
389358

390-
int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
391-
{
392-
u32 func_id = smccc_get_function(vcpu);
393-
u32 val = SMCCC_RET_NOT_SUPPORTED;
394-
u32 feature;
395-
396-
switch (func_id) {
397-
case ARM_SMCCC_VERSION_FUNC_ID:
398-
val = ARM_SMCCC_VERSION_1_1;
399-
break;
400-
case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
401-
feature = smccc_get_arg1(vcpu);
402-
switch(feature) {
403-
case ARM_SMCCC_ARCH_WORKAROUND_1:
404-
switch (kvm_arm_harden_branch_predictor()) {
405-
case KVM_BP_HARDEN_UNKNOWN:
406-
break;
407-
case KVM_BP_HARDEN_WA_NEEDED:
408-
val = SMCCC_RET_SUCCESS;
409-
break;
410-
case KVM_BP_HARDEN_NOT_REQUIRED:
411-
val = SMCCC_RET_NOT_REQUIRED;
412-
break;
413-
}
414-
break;
415-
case ARM_SMCCC_ARCH_WORKAROUND_2:
416-
switch (kvm_arm_have_ssbd()) {
417-
case KVM_SSBD_FORCE_DISABLE:
418-
case KVM_SSBD_UNKNOWN:
419-
break;
420-
case KVM_SSBD_KERNEL:
421-
val = SMCCC_RET_SUCCESS;
422-
break;
423-
case KVM_SSBD_FORCE_ENABLE:
424-
case KVM_SSBD_MITIGATED:
425-
val = SMCCC_RET_NOT_REQUIRED;
426-
break;
427-
}
428-
break;
429-
}
430-
break;
431-
default:
432-
return kvm_psci_call(vcpu);
433-
}
434-
435-
smccc_set_retval(vcpu, val, 0, 0, 0);
436-
return 1;
437-
}
438-
439359
int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu)
440360
{
441361
return 3; /* PSCI version and two workaround registers */

0 commit comments

Comments
 (0)