History

Merge branch kvm-arm64/hcall-selection into kvmarm-master/next

* kvm-arm64/hcall-selection: : . : Introduce a new set of virtual sysregs for userspace to : select the hypercalls it wants to see exposed to the guest. : : Patches courtesy of Raghavendra and Oliver. : . KVM: arm64: Fix hypercall bitmap writeback when vcpus have already run KVM: arm64: Hide KVM_REG_ARM_*_BMAP_BIT_COUNT from userspace Documentation: Fix index.rst after psci.rst renaming selftests: KVM: aarch64: Add the bitmap firmware registers to get-reg-list selftests: KVM: aarch64: Introduce hypercall ABI test selftests: KVM: Create helper for making SMCCC calls selftests: KVM: Rename psci_cpu_on_test to psci_test tools: Import ARM SMCCC definitions Docs: KVM: Add doc for the bitmap firmware registers Docs: KVM: Rename psci.rst to hypercalls.rst KVM: arm64: Add vendor hypervisor firmware register KVM: arm64: Add standard hypervisor firmware register KVM: arm64: Setup a framework for hypercall bitmap firmware registers KVM: arm64: Factor out firmware register handling from psci.c

Marc Zyngier committed 4 years ago

Commit 0586e282 parents d25f30f 528ada221 files · +1146 −303Browse files

Unified · Split

21 files
  1. Documentation/virt/kvm/api.rst +18 −0
  2. Documentation/virt/kvm/arm/hypercalls.rst +138 −0
  3. Documentation/virt/kvm/arm/index.rst +1 −1
  4. Documentation/virt/kvm/arm/psci.rst +0 −77
  5. arch/arm64/include/asm/kvm_host.h +16 −0
  6. arch/arm64/include/uapi/asm/kvm.h +34 −0
  7. arch/arm64/kvm/arm.c +1 −0
  8. arch/arm64/kvm/guest.c +7 −3
  9. arch/arm64/kvm/hypercalls.c +324 −3
  10. arch/arm64/kvm/psci.c +0 −183
  11. include/kvm/arm_hypercalls.h +8 −0
  12. include/kvm/arm_psci.h +0 −7
  13. tools/include/linux/arm-smccc.h +193 −0
  14. tools/testing/selftests/kvm/.gitignore +2 −1
  15. tools/testing/selftests/kvm/Makefile +2 −1
  16. tools/testing/selftests/kvm/aarch64/get-reg-list.c +8 −0
  17. tools/testing/selftests/kvm/aarch64/hypercalls.c +336 −0
  18. tools/testing/selftests/kvm/aarch64/psci_test.c +8 −17
  19. tools/testing/selftests/kvm/include/aarch64/processor.h +22 −0
  20. tools/testing/selftests/kvm/lib/aarch64/processor.c +25 −0
  21. tools/testing/selftests/kvm/steal_time.c +3 −10
Documentation/virt/kvm/api.rst+18−0
@@ -2601,6 +2601,24 @@ EINVAL. · 2600 unmodified lines
2601After the vcpu's SVE configuration is finalized, further attempts to2601After the vcpu's SVE configuration is finalized, further attempts to
2602write this register will fail with EPERM.2602write this register will fail with EPERM.
2603 2603
2604arm64 bitmap feature firmware pseudo-registers have the following bit pattern::
2605
2606 0x6030 0000 0016 <regno:16>
2607
2608The bitmap feature firmware registers exposes the hypercall services that
2609are available for userspace to configure. The set bits corresponds to the
2610services that are available for the guests to access. By default, KVM
2611sets all the supported bits during VM initialization. The userspace can
2612discover the available services via KVM_GET_ONE_REG, and write back the
2613bitmap corresponding to the features that it wishes guests to see via
2614KVM_SET_ONE_REG.
2615
2616Note: These registers are immutable once any of the vCPUs of the VM has
2617run at least once. A KVM_SET_ONE_REG in such a scenario will return
2618a -EBUSY to userspace.
2619
2620(See Documentation/virt/kvm/arm/hypercalls.rst for more details.)
2621
2604 2622
2605MIPS registers are mapped using the lower 32 bits. The upper 16 of that is2623MIPS registers are mapped using the lower 32 bits. The upper 16 of that is
2606the register group type:2624the register group type:
Documentation/virt/kvm/arm/hypercalls.rst+138−0
@@ -0,0 +1,138 @@
1.. SPDX-License-Identifier: GPL-2.0
2
3=======================
4ARM Hypercall Interface
5=======================
6
7KVM handles the hypercall services as requested by the guests. New hypercall
8services are regularly made available by the ARM specification or by KVM (as
9vendor services) if they make sense from a virtualization point of view.
10
11This means that a guest booted on two different versions of KVM can observe
12two different "firmware" revisions. This could cause issues if a given guest
13is tied to a particular version of a hypercall service, or if a migration
14causes a different version to be exposed out of the blue to an unsuspecting
15guest.
16
17In order to remedy this situation, KVM exposes a set of "firmware
18pseudo-registers" that can be manipulated using the GET/SET_ONE_REG
19interface. These registers can be saved/restored by userspace, and set
20to a convenient value as required.
21
22The following registers are defined:
23
24* KVM_REG_ARM_PSCI_VERSION:
25
26 KVM implements the PSCI (Power State Coordination Interface)
27 specification in order to provide services such as CPU on/off, reset
28 and power-off to the guest.
29
30 - Only valid if the vcpu has the KVM_ARM_VCPU_PSCI_0_2 feature set
31 (and thus has already been initialized)
32 - Returns the current PSCI version on GET_ONE_REG (defaulting to the
33 highest PSCI version implemented by KVM and compatible with v0.2)
34 - Allows any PSCI version implemented by KVM and compatible with
35 v0.2 to be set with SET_ONE_REG
36 - Affects the whole VM (even if the register view is per-vcpu)
37
38* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
39 Holds the state of the firmware support to mitigate CVE-2017-5715, as
40 offered by KVM to the guest via a HVC call. The workaround is described
41 under SMCCC_ARCH_WORKAROUND_1 in [1].
42
43 Accepted values are:
44
45 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL:
46 KVM does not offer
47 firmware support for the workaround. The mitigation status for the
48 guest is unknown.
49 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL:
50 The workaround HVC call is
51 available to the guest and required for the mitigation.
52 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED:
53 The workaround HVC call
54 is available to the guest, but it is not needed on this VCPU.
55
56* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2:
57 Holds the state of the firmware support to mitigate CVE-2018-3639, as
58 offered by KVM to the guest via a HVC call. The workaround is described
59 under SMCCC_ARCH_WORKAROUND_2 in [1]_.
60
61 Accepted values are:
62
63 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL:
64 A workaround is not
65 available. KVM does not offer firmware support for the workaround.
66 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN:
67 The workaround state is
68 unknown. KVM does not offer firmware support for the workaround.
69 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL:
70 The workaround is available,
71 and can be disabled by a vCPU. If
72 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED is set, it is active for
73 this vCPU.
74 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED:
75 The workaround is always active on this vCPU or it is not needed.
76
77
78Bitmap Feature Firmware Registers
79---------------------------------
80
81Contrary to the above registers, the following registers exposes the
82hypercall services in the form of a feature-bitmap to the userspace. This
83bitmap is translated to the services that are available to the guest.
84There is a register defined per service call owner and can be accessed via
85GET/SET_ONE_REG interface.
86
87By default, these registers are set with the upper limit of the features
88that are supported. This way userspace can discover all the usable
89hypercall services via GET_ONE_REG. The user-space can write-back the
90desired bitmap back via SET_ONE_REG. The features for the registers that
91are untouched, probably because userspace isn't aware of them, will be
92exposed as is to the guest.
93
94Note that KVM will not allow the userspace to configure the registers
95anymore once any of the vCPUs has run at least once. Instead, it will
96return a -EBUSY.
97
98The pseudo-firmware bitmap register are as follows:
99
100* KVM_REG_ARM_STD_BMAP:
101 Controls the bitmap of the ARM Standard Secure Service Calls.
102
103 The following bits are accepted:
104
105 Bit-0: KVM_REG_ARM_STD_BIT_TRNG_V1_0:
106 The bit represents the services offered under v1.0 of ARM True Random
107 Number Generator (TRNG) specification, ARM DEN0098.
108
109* KVM_REG_ARM_STD_HYP_BMAP:
110 Controls the bitmap of the ARM Standard Hypervisor Service Calls.
111
112 The following bits are accepted:
113
114 Bit-0: KVM_REG_ARM_STD_HYP_BIT_PV_TIME:
115 The bit represents the Paravirtualized Time service as represented by
116 ARM DEN0057A.
117
118* KVM_REG_ARM_VENDOR_HYP_BMAP:
119 Controls the bitmap of the Vendor specific Hypervisor Service Calls.
120
121 The following bits are accepted:
122
123 Bit-0: KVM_REG_ARM_VENDOR_HYP_BIT_FUNC_FEAT
124 The bit represents the ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID
125 and ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID function-ids.
126
127 Bit-1: KVM_REG_ARM_VENDOR_HYP_BIT_PTP:
128 The bit represents the Precision Time Protocol KVM service.
129
130Errors:
131
132 ======= =============================================================
133 -ENOENT Unknown register accessed.
134 -EBUSY Attempt a 'write' to the register after the VM has started.
135 -EINVAL Invalid bitmap written to the register.
136 ======= =============================================================
137
138.. [1] https://developer.arm.com/-/media/developer/pdf/ARM_DEN_0070A_Firmware_interfaces_for_mitigating_CVE-2017-5715.pdf
Documentation/virt/kvm/arm/index.rst+1−1
@@ -8,6 +8,6 @@ ARM · 7 unmodified lines
8 :maxdepth: 28 :maxdepth: 2
9 9
10 hyp-abi10 hyp-abi
11 psci11 hypercalls
12 pvtime12 pvtime
13 ptp_kvm13 ptp_kvm
Documentation/virt/kvm/arm/psci.rst+0−77
@@ -1,77 +0,0 @@
1.. SPDX-License-Identifier: GPL-2.0
2
3=========================================
4Power State Coordination Interface (PSCI)
5=========================================
6
7KVM implements the PSCI (Power State Coordination Interface)
8specification in order to provide services such as CPU on/off, reset
9and power-off to the guest.
10
11The PSCI specification is regularly updated to provide new features,
12and KVM implements these updates if they make sense from a virtualization
13point of view.
14
15This means that a guest booted on two different versions of KVM can
16observe two different "firmware" revisions. This could cause issues if
17a given guest is tied to a particular PSCI revision (unlikely), or if
18a migration causes a different PSCI version to be exposed out of the
19blue to an unsuspecting guest.
20
21In order to remedy this situation, KVM exposes a set of "firmware
22pseudo-registers" that can be manipulated using the GET/SET_ONE_REG
23interface. These registers can be saved/restored by userspace, and set
24to a convenient value if required.
25
26The following register is defined:
27
28* KVM_REG_ARM_PSCI_VERSION:
29
30 - Only valid if the vcpu has the KVM_ARM_VCPU_PSCI_0_2 feature set
31 (and thus has already been initialized)
32 - Returns the current PSCI version on GET_ONE_REG (defaulting to the
33 highest PSCI version implemented by KVM and compatible with v0.2)
34 - Allows any PSCI version implemented by KVM and compatible with
35 v0.2 to be set with SET_ONE_REG
36 - Affects the whole VM (even if the register view is per-vcpu)
37
38* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
39 Holds the state of the firmware support to mitigate CVE-2017-5715, as
40 offered by KVM to the guest via a HVC call. The workaround is described
41 under SMCCC_ARCH_WORKAROUND_1 in [1].
42
43 Accepted values are:
44
45 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL:
46 KVM does not offer
47 firmware support for the workaround. The mitigation status for the
48 guest is unknown.
49 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL:
50 The workaround HVC call is
51 available to the guest and required for the mitigation.
52 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED:
53 The workaround HVC call
54 is available to the guest, but it is not needed on this VCPU.
55
56* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2:
57 Holds the state of the firmware support to mitigate CVE-2018-3639, as
58 offered by KVM to the guest via a HVC call. The workaround is described
59 under SMCCC_ARCH_WORKAROUND_2 in [1]_.
60
61 Accepted values are:
62
63 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL:
64 A workaround is not
65 available. KVM does not offer firmware support for the workaround.
66 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN:
67 The workaround state is
68 unknown. KVM does not offer firmware support for the workaround.
69 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL:
70 The workaround is available,
71 and can be disabled by a vCPU. If
72 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED is set, it is active for
73 this vCPU.
74 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED:
75 The workaround is always active on this vCPU or it is not needed.
76
77.. [1] https://developer.arm.com/-/media/developer/pdf/ARM_DEN_0070A_Firmware_interfaces_for_mitigating_CVE-2017-5715.pdf
arch/arm64/include/asm/kvm_host.h+16−0
@@ -101,6 +101,19 @@ struct kvm_s2_mmu { · 100 unmodified lines
101struct kvm_arch_memory_slot {101struct kvm_arch_memory_slot {
102};102};
103 103
104/**
105 * struct kvm_smccc_features: Descriptor of the hypercall services exposed to the guests
106 *
107 * @std_bmap: Bitmap of standard secure service calls
108 * @std_hyp_bmap: Bitmap of standard hypervisor service calls
109 * @vendor_hyp_bmap: Bitmap of vendor specific hypervisor service calls
110 */
111struct kvm_smccc_features {
112 unsigned long std_bmap;
113 unsigned long std_hyp_bmap;
114 unsigned long vendor_hyp_bmap;
115};
116
104struct kvm_arch {117struct kvm_arch {
105 struct kvm_s2_mmu mmu;118 struct kvm_s2_mmu mmu;
106 119
@@ -150,6 +163,9 @@ struct kvm_arch { · 43 unmodified lines
150 163
151 u8 pfr0_csv2;164 u8 pfr0_csv2;
152 u8 pfr0_csv3;165 u8 pfr0_csv3;
166
167 /* Hypercall features firmware registers' descriptor */
168 struct kvm_smccc_features smccc_feat;
153};169};
154 170
155struct kvm_vcpu_fault_info {171struct kvm_vcpu_fault_info {
arch/arm64/include/uapi/asm/kvm.h+34−0
@@ -332,6 +332,40 @@ struct kvm_arm_copy_mte_tags { · 331 unmodified lines
332#define KVM_ARM64_SVE_VLS_WORDS \332#define KVM_ARM64_SVE_VLS_WORDS \
333 ((KVM_ARM64_SVE_VQ_MAX - KVM_ARM64_SVE_VQ_MIN) / 64 + 1)333 ((KVM_ARM64_SVE_VQ_MAX - KVM_ARM64_SVE_VQ_MIN) / 64 + 1)
334 334
335/* Bitmap feature firmware registers */
336#define KVM_REG_ARM_FW_FEAT_BMAP (0x0016 << KVM_REG_ARM_COPROC_SHIFT)
337#define KVM_REG_ARM_FW_FEAT_BMAP_REG(r) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
338 KVM_REG_ARM_FW_FEAT_BMAP | \
339 ((r) & 0xffff))
340
341#define KVM_REG_ARM_STD_BMAP KVM_REG_ARM_FW_FEAT_BMAP_REG(0)
342
343enum {
344 KVM_REG_ARM_STD_BIT_TRNG_V1_0 = 0,
345#ifdef __KERNEL__
346 KVM_REG_ARM_STD_BMAP_BIT_COUNT,
347#endif
348};
349
350#define KVM_REG_ARM_STD_HYP_BMAP KVM_REG_ARM_FW_FEAT_BMAP_REG(1)
351
352enum {
353 KVM_REG_ARM_STD_HYP_BIT_PV_TIME = 0,
354#ifdef __KERNEL__
355 KVM_REG_ARM_STD_HYP_BMAP_BIT_COUNT,
356#endif
357};
358
359#define KVM_REG_ARM_VENDOR_HYP_BMAP KVM_REG_ARM_FW_FEAT_BMAP_REG(2)
360
361enum {
362 KVM_REG_ARM_VENDOR_HYP_BIT_FUNC_FEAT = 0,
363 KVM_REG_ARM_VENDOR_HYP_BIT_PTP = 1,
364#ifdef __KERNEL__
365 KVM_REG_ARM_VENDOR_HYP_BMAP_BIT_COUNT,
366#endif
367};
368
335/* Device Control API: ARM VGIC */369/* Device Control API: ARM VGIC */
336#define KVM_DEV_ARM_VGIC_GRP_ADDR 0370#define KVM_DEV_ARM_VGIC_GRP_ADDR 0
337#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1371#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
arch/arm64/kvm/arm.c+1−0
@@ -156,6 +156,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) · 155 unmodified lines
156 kvm->arch.max_vcpus = kvm_arm_default_max_vcpus();156 kvm->arch.max_vcpus = kvm_arm_default_max_vcpus();
157 157
158 set_default_spectre(kvm);158 set_default_spectre(kvm);
159 kvm_arm_init_hypercalls(kvm);
159 160
160 return ret;161 return ret;
161out_free_stage2_pgd:162out_free_stage2_pgd:
arch/arm64/kvm/guest.c+7−3
@@ -18,7 +18,7 @@ · 17 unmodified lines
18#include <linux/string.h>18#include <linux/string.h>
19#include <linux/vmalloc.h>19#include <linux/vmalloc.h>
20#include <linux/fs.h>20#include <linux/fs.h>
21#include <kvm/arm_psci.h>21#include <kvm/arm_hypercalls.h>
22#include <asm/cputype.h>22#include <asm/cputype.h>
23#include <linux/uaccess.h>23#include <linux/uaccess.h>
24#include <asm/fpsimd.h>24#include <asm/fpsimd.h>
@@ -756,7 +756,9 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) · 731 unmodified lines
756 756
757 switch (reg->id & KVM_REG_ARM_COPROC_MASK) {757 switch (reg->id & KVM_REG_ARM_COPROC_MASK) {
758 case KVM_REG_ARM_CORE: return get_core_reg(vcpu, reg);758 case KVM_REG_ARM_CORE: return get_core_reg(vcpu, reg);
759 case KVM_REG_ARM_FW: return kvm_arm_get_fw_reg(vcpu, reg);759 case KVM_REG_ARM_FW:
760 case KVM_REG_ARM_FW_FEAT_BMAP:
761 return kvm_arm_get_fw_reg(vcpu, reg);
760 case KVM_REG_ARM64_SVE: return get_sve_reg(vcpu, reg);762 case KVM_REG_ARM64_SVE: return get_sve_reg(vcpu, reg);
761 }763 }
762 764
@@ -774,7 +776,9 @@ int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) · 11 unmodified lines
774 776
775 switch (reg->id & KVM_REG_ARM_COPROC_MASK) {777 switch (reg->id & KVM_REG_ARM_COPROC_MASK) {
776 case KVM_REG_ARM_CORE: return set_core_reg(vcpu, reg);778 case KVM_REG_ARM_CORE: return set_core_reg(vcpu, reg);
777 case KVM_REG_ARM_FW: return kvm_arm_set_fw_reg(vcpu, reg);779 case KVM_REG_ARM_FW:
780 case KVM_REG_ARM_FW_FEAT_BMAP:
781 return kvm_arm_set_fw_reg(vcpu, reg);
778 case KVM_REG_ARM64_SVE: return set_sve_reg(vcpu, reg);782 case KVM_REG_ARM64_SVE: return set_sve_reg(vcpu, reg);
779 }783 }
780 784
arch/arm64/kvm/hypercalls.c+324−3
@@ -9,6 +9,13 @@ · 8 unmodified lines
9#include <kvm/arm_hypercalls.h>9#include <kvm/arm_hypercalls.h>
10#include <kvm/arm_psci.h>10#include <kvm/arm_psci.h>
11 11
12#define KVM_ARM_SMCCC_STD_FEATURES \
13 GENMASK(KVM_REG_ARM_STD_BMAP_BIT_COUNT - 1, 0)
14#define KVM_ARM_SMCCC_STD_HYP_FEATURES \
15 GENMASK(KVM_REG_ARM_STD_HYP_BMAP_BIT_COUNT - 1, 0)
16#define KVM_ARM_SMCCC_VENDOR_HYP_FEATURES \
17 GENMASK(KVM_REG_ARM_VENDOR_HYP_BMAP_BIT_COUNT - 1, 0)
18
12static void kvm_ptp_get_time(struct kvm_vcpu *vcpu, u64 *val)19static void kvm_ptp_get_time(struct kvm_vcpu *vcpu, u64 *val)
13{20{
14 struct system_time_snapshot systime_snapshot;21 struct system_time_snapshot systime_snapshot;
@@ -58,13 +65,73 @@ static void kvm_ptp_get_time(struct kvm_vcpu *vcpu, u64 *val) · 43 unmodified lines
58 val[3] = lower_32_bits(cycles);65 val[3] = lower_32_bits(cycles);
59}66}
60 67
68static bool kvm_hvc_call_default_allowed(u32 func_id)
69{
70 switch (func_id) {
71 /*
72 * List of function-ids that are not gated with the bitmapped
73 * feature firmware registers, and are to be allowed for
74 * servicing the call by default.
75 */
76 case ARM_SMCCC_VERSION_FUNC_ID:
77 case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
78 return true;
79 default:
80 /* PSCI 0.2 and up is in the 0:0x1f range */
81 if (ARM_SMCCC_OWNER_NUM(func_id) == ARM_SMCCC_OWNER_STANDARD &&
82 ARM_SMCCC_FUNC_NUM(func_id) <= 0x1f)
83 return true;
84
85 /*
86 * KVM's PSCI 0.1 doesn't comply with SMCCC, and has
87 * its own function-id base and range
88 */
89 if (func_id >= KVM_PSCI_FN(0) && func_id <= KVM_PSCI_FN(3))
90 return true;
91
92 return false;
93 }
94}
95
96static bool kvm_hvc_call_allowed(struct kvm_vcpu *vcpu, u32 func_id)
97{
98 struct kvm_smccc_features *smccc_feat = &vcpu->kvm->arch.smccc_feat;
99
100 switch (func_id) {
101 case ARM_SMCCC_TRNG_VERSION:
102 case ARM_SMCCC_TRNG_FEATURES:
103 case ARM_SMCCC_TRNG_GET_UUID:
104 case ARM_SMCCC_TRNG_RND32:
105 case ARM_SMCCC_TRNG_RND64:
106 return test_bit(KVM_REG_ARM_STD_BIT_TRNG_V1_0,
107 &smccc_feat->std_bmap);
108 case ARM_SMCCC_HV_PV_TIME_FEATURES:
109 case ARM_SMCCC_HV_PV_TIME_ST:
110 return test_bit(KVM_REG_ARM_STD_HYP_BIT_PV_TIME,
111 &smccc_feat->std_hyp_bmap);
112 case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID:
113 case ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID:
114 return test_bit(KVM_REG_ARM_VENDOR_HYP_BIT_FUNC_FEAT,
115 &smccc_feat->vendor_hyp_bmap);
116 case ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID:
117 return test_bit(KVM_REG_ARM_VENDOR_HYP_BIT_PTP,
118 &smccc_feat->vendor_hyp_bmap);
119 default:
120 return kvm_hvc_call_default_allowed(func_id);
121 }
122}
123
61int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)124int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
62{125{
126 struct kvm_smccc_features *smccc_feat = &vcpu->kvm->arch.smccc_feat;
63 u32 func_id = smccc_get_function(vcpu);127 u32 func_id = smccc_get_function(vcpu);
64 u64 val[4] = {SMCCC_RET_NOT_SUPPORTED};128 u64 val[4] = {SMCCC_RET_NOT_SUPPORTED};
65 u32 feature;129 u32 feature;
66 gpa_t gpa;130 gpa_t gpa;
67 131
132 if (!kvm_hvc_call_allowed(vcpu, func_id))
133 goto out;
134
68 switch (func_id) {135 switch (func_id) {
69 case ARM_SMCCC_VERSION_FUNC_ID:136 case ARM_SMCCC_VERSION_FUNC_ID:
70 val[0] = ARM_SMCCC_VERSION_1_1;137 val[0] = ARM_SMCCC_VERSION_1_1;
@@ -120,7 +187,9 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) · 49 unmodified lines
120 }187 }
121 break;188 break;
122 case ARM_SMCCC_HV_PV_TIME_FEATURES:189 case ARM_SMCCC_HV_PV_TIME_FEATURES:
123 val[0] = SMCCC_RET_SUCCESS;190 if (test_bit(KVM_REG_ARM_STD_HYP_BIT_PV_TIME,
191 &smccc_feat->std_hyp_bmap))
192 val[0] = SMCCC_RET_SUCCESS;
124 break;193 break;
125 }194 }
126 break;195 break;
@@ -139,8 +208,7 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) · 12 unmodified lines
139 val[3] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3;208 val[3] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3;
140 break;209 break;
141 case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID:210 case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID:
142 val[0] = BIT(ARM_SMCCC_KVM_FUNC_FEATURES);211 val[0] = smccc_feat->vendor_hyp_bmap;
143 val[0] |= BIT(ARM_SMCCC_KVM_FUNC_PTP);
144 break;212 break;
145 case ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID:213 case ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID:
146 kvm_ptp_get_time(vcpu, val);214 kvm_ptp_get_time(vcpu, val);
@@ -155,6 +223,259 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) · 8 unmodified lines
155 return kvm_psci_call(vcpu);223 return kvm_psci_call(vcpu);
156 }224 }
157 225
226out:
158 smccc_set_retval(vcpu, val[0], val[1], val[2], val[3]);227 smccc_set_retval(vcpu, val[0], val[1], val[2], val[3]);
159 return 1;228 return 1;
160}229}
230
231static const u64 kvm_arm_fw_reg_ids[] = {
232 KVM_REG_ARM_PSCI_VERSION,
233 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1,
234 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2,
235 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3,
236 KVM_REG_ARM_STD_BMAP,
237 KVM_REG_ARM_STD_HYP_BMAP,
238 KVM_REG_ARM_VENDOR_HYP_BMAP,
239};
240
241void kvm_arm_init_hypercalls(struct kvm *kvm)
242{
243 struct kvm_smccc_features *smccc_feat = &kvm->arch.smccc_feat;
244
245 smccc_feat->std_bmap = KVM_ARM_SMCCC_STD_FEATURES;
246 smccc_feat->std_hyp_bmap = KVM_ARM_SMCCC_STD_HYP_FEATURES;
247 smccc_feat->vendor_hyp_bmap = KVM_ARM_SMCCC_VENDOR_HYP_FEATURES;
248}
249
250int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu)
251{
252 return ARRAY_SIZE(kvm_arm_fw_reg_ids);
253}
254
255int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
256{
257 int i;
258
259 for (i = 0; i < ARRAY_SIZE(kvm_arm_fw_reg_ids); i++) {
260 if (put_user(kvm_arm_fw_reg_ids[i], uindices++))
261 return -EFAULT;
262 }
263
264 return 0;
265}
266
267#define KVM_REG_FEATURE_LEVEL_MASK GENMASK(3, 0)
268
269/*
270 * Convert the workaround level into an easy-to-compare number, where higher
271 * values mean better protection.
272 */
273static int get_kernel_wa_level(u64 regid)
274{
275 switch (regid) {
276 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
277 switch (arm64_get_spectre_v2_state()) {
278 case SPECTRE_VULNERABLE:
279 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL;
280 case SPECTRE_MITIGATED:
281 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL;
282 case SPECTRE_UNAFFECTED:
283 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED;
284 }
285 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL;
286 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2:
287 switch (arm64_get_spectre_v4_state()) {
288 case SPECTRE_MITIGATED:
289 /*
290 * As for the hypercall discovery, we pretend we
291 * don't have any FW mitigation if SSBS is there at
292 * all times.
293 */
294 if (cpus_have_final_cap(ARM64_SSBS))
295 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL;
296 fallthrough;
297 case SPECTRE_UNAFFECTED:
298 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED;
299 case SPECTRE_VULNERABLE:
300 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL;
301 }
302 break;
303 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3:
304 switch (arm64_get_spectre_bhb_state()) {
305 case SPECTRE_VULNERABLE:
306 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL;
307 case SPECTRE_MITIGATED:
308 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_AVAIL;
309 case SPECTRE_UNAFFECTED:
310 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_REQUIRED;
311 }
312 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL;
313 }
314
315 return -EINVAL;
316}
317
318int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
319{
320 struct kvm_smccc_features *smccc_feat = &vcpu->kvm->arch.smccc_feat;
321 void __user *uaddr = (void __user *)(long)reg->addr;
322 u64 val;
323
324 switch (reg->id) {
325 case KVM_REG_ARM_PSCI_VERSION:
326 val = kvm_psci_version(vcpu);
327 break;
328 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
329 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2:
330 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3:
331 val = get_kernel_wa_level(reg->id) & KVM_REG_FEATURE_LEVEL_MASK;
332 break;
333 case KVM_REG_ARM_STD_BMAP:
334 val = READ_ONCE(smccc_feat->std_bmap);
335 break;
336 case KVM_REG_ARM_STD_HYP_BMAP:
337 val = READ_ONCE(smccc_feat->std_hyp_bmap);
338 break;
339 case KVM_REG_ARM_VENDOR_HYP_BMAP:
340 val = READ_ONCE(smccc_feat->vendor_hyp_bmap);
341 break;
342 default:
343 return -ENOENT;
344 }
345
346 if (copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)))
347 return -EFAULT;
348
349 return 0;
350}
351
352static int kvm_arm_set_fw_reg_bmap(struct kvm_vcpu *vcpu, u64 reg_id, u64 val)
353{
354 int ret = 0;
355 struct kvm *kvm = vcpu->kvm;
356 struct kvm_smccc_features *smccc_feat = &kvm->arch.smccc_feat;
357 unsigned long *fw_reg_bmap, fw_reg_features;
358
359 switch (reg_id) {
360 case KVM_REG_ARM_STD_BMAP:
361 fw_reg_bmap = &smccc_feat->std_bmap;
362 fw_reg_features = KVM_ARM_SMCCC_STD_FEATURES;
363 break;
364 case KVM_REG_ARM_STD_HYP_BMAP:
365 fw_reg_bmap = &smccc_feat->std_hyp_bmap;
366 fw_reg_features = KVM_ARM_SMCCC_STD_HYP_FEATURES;
367 break;
368 case KVM_REG_ARM_VENDOR_HYP_BMAP:
369 fw_reg_bmap = &smccc_feat->vendor_hyp_bmap;
370 fw_reg_features = KVM_ARM_SMCCC_VENDOR_HYP_FEATURES;
371 break;
372 default:
373 return -ENOENT;
374 }
375
376 /* Check for unsupported bit */
377 if (val & ~fw_reg_features)
378 return -EINVAL;
379
380 mutex_lock(&kvm->lock);
381
382 if (test_bit(KVM_ARCH_FLAG_HAS_RAN_ONCE, &kvm->arch.flags) &&
383 val != *fw_reg_bmap) {
384 ret = -EBUSY;
385 goto out;
386 }
387
388 WRITE_ONCE(*fw_reg_bmap, val);
389out:
390 mutex_unlock(&kvm->lock);
391 return ret;
392}
393
394int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
395{
396 void __user *uaddr = (void __user *)(long)reg->addr;
397 u64 val;
398 int wa_level;
399
400 if (copy_from_user(&val, uaddr, KVM_REG_SIZE(reg->id)))
401 return -EFAULT;
402
403 switch (reg->id) {
404 case KVM_REG_ARM_PSCI_VERSION:
405 {
406 bool wants_02;
407
408 wants_02 = test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features);
409
410 switch (val) {
411 case KVM_ARM_PSCI_0_1:
412 if (wants_02)
413 return -EINVAL;
414 vcpu->kvm->arch.psci_version = val;
415 return 0;
416 case KVM_ARM_PSCI_0_2:
417 case KVM_ARM_PSCI_1_0:
418 case KVM_ARM_PSCI_1_1:
419 if (!wants_02)
420 return -EINVAL;
421 vcpu->kvm->arch.psci_version = val;
422 return 0;
423 }
424 break;
425 }
426
427 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
428 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3:
429 if (val & ~KVM_REG_FEATURE_LEVEL_MASK)
430 return -EINVAL;
431
432 if (get_kernel_wa_level(reg->id) < val)
433 return -EINVAL;
434
435 return 0;
436
437 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2:
438 if (val & ~(KVM_REG_FEATURE_LEVEL_MASK |
439 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED))
440 return -EINVAL;
441
442 /* The enabled bit must not be set unless the level is AVAIL. */
443 if ((val & KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED) &&
444 (val & KVM_REG_FEATURE_LEVEL_MASK) != KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL)
445 return -EINVAL;
446
447 /*
448 * Map all the possible incoming states to the only two we
449 * really want to deal with.
450 */
451 switch (val & KVM_REG_FEATURE_LEVEL_MASK) {
452 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL:
453 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN:
454 wa_level = KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL;
455 break;
456 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL:
457 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED:
458 wa_level = KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED;
459 break;
460 default:
461 return -EINVAL;
462 }
463
464 /*
465 * We can deal with NOT_AVAIL on NOT_REQUIRED, but not the
466 * other way around.
467 */
468 if (get_kernel_wa_level(reg->id) < wa_level)
469 return -EINVAL;
470
471 return 0;
472 case KVM_REG_ARM_STD_BMAP:
473 case KVM_REG_ARM_STD_HYP_BMAP:
474 case KVM_REG_ARM_VENDOR_HYP_BMAP:
475 return kvm_arm_set_fw_reg_bmap(vcpu, reg->id, val);
476 default:
477 return -ENOENT;
478 }
479
480 return -EINVAL;
481}
arch/arm64/kvm/psci.c+0−183
@@ -437,186 +437,3 @@ int kvm_psci_call(struct kvm_vcpu *vcpu) · 436 unmodified lines
437 return -EINVAL;437 return -EINVAL;
438 }438 }
439}439}
440
441int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu)
442{
443 return 4; /* PSCI version and three workaround registers */
444}
445
446int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
447{
448 if (put_user(KVM_REG_ARM_PSCI_VERSION, uindices++))
449 return -EFAULT;
450
451 if (put_user(KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1, uindices++))
452 return -EFAULT;
453
454 if (put_user(KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2, uindices++))
455 return -EFAULT;
456
457 if (put_user(KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3, uindices++))
458 return -EFAULT;
459
460 return 0;
461}
462
463#define KVM_REG_FEATURE_LEVEL_WIDTH 4
464#define KVM_REG_FEATURE_LEVEL_MASK (BIT(KVM_REG_FEATURE_LEVEL_WIDTH) - 1)
465
466/*
467 * Convert the workaround level into an easy-to-compare number, where higher
468 * values mean better protection.
469 */
470static int get_kernel_wa_level(u64 regid)
471{
472 switch (regid) {
473 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
474 switch (arm64_get_spectre_v2_state()) {
475 case SPECTRE_VULNERABLE:
476 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL;
477 case SPECTRE_MITIGATED:
478 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL;
479 case SPECTRE_UNAFFECTED:
480 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED;
481 }
482 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL;
483 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2:
484 switch (arm64_get_spectre_v4_state()) {
485 case SPECTRE_MITIGATED:
486 /*
487 * As for the hypercall discovery, we pretend we
488 * don't have any FW mitigation if SSBS is there at
489 * all times.
490 */
491 if (cpus_have_final_cap(ARM64_SSBS))
492 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL;
493 fallthrough;
494 case SPECTRE_UNAFFECTED:
495 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED;
496 case SPECTRE_VULNERABLE:
497 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL;
498 }
499 break;
500 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3:
501 switch (arm64_get_spectre_bhb_state()) {
502 case SPECTRE_VULNERABLE:
503 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL;
504 case SPECTRE_MITIGATED:
505 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_AVAIL;
506 case SPECTRE_UNAFFECTED:
507 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_REQUIRED;
508 }
509 return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL;
510 }
511
512 return -EINVAL;
513}
514
515int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
516{
517 void __user *uaddr = (void __user *)(long)reg->addr;
518 u64 val;
519
520 switch (reg->id) {
521 case KVM_REG_ARM_PSCI_VERSION:
522 val = kvm_psci_version(vcpu);
523 break;
524 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
525 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2:
526 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3:
527 val = get_kernel_wa_level(reg->id) & KVM_REG_FEATURE_LEVEL_MASK;
528 break;
529 default:
530 return -ENOENT;
531 }
532
533 if (copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)))
534 return -EFAULT;
535
536 return 0;
537}
538
539int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
540{
541 void __user *uaddr = (void __user *)(long)reg->addr;
542 u64 val;
543 int wa_level;
544
545 if (copy_from_user(&val, uaddr, KVM_REG_SIZE(reg->id)))
546 return -EFAULT;
547
548 switch (reg->id) {
549 case KVM_REG_ARM_PSCI_VERSION:
550 {
551 bool wants_02;
552
553 wants_02 = test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features);
554
555 switch (val) {
556 case KVM_ARM_PSCI_0_1:
557 if (wants_02)
558 return -EINVAL;
559 vcpu->kvm->arch.psci_version = val;
560 return 0;
561 case KVM_ARM_PSCI_0_2:
562 case KVM_ARM_PSCI_1_0:
563 case KVM_ARM_PSCI_1_1:
564 if (!wants_02)
565 return -EINVAL;
566 vcpu->kvm->arch.psci_version = val;
567 return 0;
568 }
569 break;
570 }
571
572 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
573 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3:
574 if (val & ~KVM_REG_FEATURE_LEVEL_MASK)
575 return -EINVAL;
576
577 if (get_kernel_wa_level(reg->id) < val)
578 return -EINVAL;
579
580 return 0;
581
582 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2:
583 if (val & ~(KVM_REG_FEATURE_LEVEL_MASK |
584 KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED))
585 return -EINVAL;
586
587 /* The enabled bit must not be set unless the level is AVAIL. */
588 if ((val & KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED) &&
589 (val & KVM_REG_FEATURE_LEVEL_MASK) != KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL)
590 return -EINVAL;
591
592 /*
593 * Map all the possible incoming states to the only two we
594 * really want to deal with.
595 */
596 switch (val & KVM_REG_FEATURE_LEVEL_MASK) {
597 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL:
598 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN:
599 wa_level = KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL;
600 break;
601 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL:
602 case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED:
603 wa_level = KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED;
604 break;
605 default:
606 return -EINVAL;
607 }
608
609 /*
610 * We can deal with NOT_AVAIL on NOT_REQUIRED, but not the
611 * other way around.
612 */
613 if (get_kernel_wa_level(reg->id) < wa_level)
614 return -EINVAL;
615
616 return 0;
617 default:
618 return -ENOENT;
619 }
620
621 return -EINVAL;
622}
include/kvm/arm_hypercalls.h+8−0
@@ -40,4 +40,12 @@ static inline void smccc_set_retval(struct kvm_vcpu *vcpu, · 39 unmodified lines
40 vcpu_set_reg(vcpu, 3, a3);40 vcpu_set_reg(vcpu, 3, a3);
41}41}
42 42
43struct kvm_one_reg;
44
45void kvm_arm_init_hypercalls(struct kvm *kvm);
46int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu);
47int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
48int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
49int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
50
43#endif51#endif
include/kvm/arm_psci.h+0−7
@@ -39,11 +39,4 @@ static inline int kvm_psci_version(struct kvm_vcpu *vcpu) · 38 unmodified lines
39 39
40int kvm_psci_call(struct kvm_vcpu *vcpu);40int kvm_psci_call(struct kvm_vcpu *vcpu);
41 41
42struct kvm_one_reg;
43
44int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu);
45int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
46int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
47int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
48
49#endif /* __KVM_ARM_PSCI_H__ */42#endif /* __KVM_ARM_PSCI_H__ */
tools/include/linux/arm-smccc.h+193−0
@@ -0,0 +1,193 @@
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright (c) 2015, Linaro Limited
4 */
5#ifndef __LINUX_ARM_SMCCC_H
6#define __LINUX_ARM_SMCCC_H
7
8#include <linux/const.h>
9
10/*
11 * This file provides common defines for ARM SMC Calling Convention as
12 * specified in
13 * https://developer.arm.com/docs/den0028/latest
14 *
15 * This code is up-to-date with version DEN 0028 C
16 */
17
18#define ARM_SMCCC_STD_CALL _AC(0,U)
19#define ARM_SMCCC_FAST_CALL _AC(1,U)
20#define ARM_SMCCC_TYPE_SHIFT 31
21
22#define ARM_SMCCC_SMC_32 0
23#define ARM_SMCCC_SMC_64 1
24#define ARM_SMCCC_CALL_CONV_SHIFT 30
25
26#define ARM_SMCCC_OWNER_MASK 0x3F
27#define ARM_SMCCC_OWNER_SHIFT 24
28
29#define ARM_SMCCC_FUNC_MASK 0xFFFF
30
31#define ARM_SMCCC_IS_FAST_CALL(smc_val) \
32 ((smc_val) & (ARM_SMCCC_FAST_CALL << ARM_SMCCC_TYPE_SHIFT))
33#define ARM_SMCCC_IS_64(smc_val) \
34 ((smc_val) & (ARM_SMCCC_SMC_64 << ARM_SMCCC_CALL_CONV_SHIFT))
35#define ARM_SMCCC_FUNC_NUM(smc_val) ((smc_val) & ARM_SMCCC_FUNC_MASK)
36#define ARM_SMCCC_OWNER_NUM(smc_val) \
37 (((smc_val) >> ARM_SMCCC_OWNER_SHIFT) & ARM_SMCCC_OWNER_MASK)
38
39#define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \
40 (((type) << ARM_SMCCC_TYPE_SHIFT) | \
41 ((calling_convention) << ARM_SMCCC_CALL_CONV_SHIFT) | \
42 (((owner) & ARM_SMCCC_OWNER_MASK) << ARM_SMCCC_OWNER_SHIFT) | \
43 ((func_num) & ARM_SMCCC_FUNC_MASK))
44
45#define ARM_SMCCC_OWNER_ARCH 0
46#define ARM_SMCCC_OWNER_CPU 1
47#define ARM_SMCCC_OWNER_SIP 2
48#define ARM_SMCCC_OWNER_OEM 3
49#define ARM_SMCCC_OWNER_STANDARD 4
50#define ARM_SMCCC_OWNER_STANDARD_HYP 5
51#define ARM_SMCCC_OWNER_VENDOR_HYP 6
52#define ARM_SMCCC_OWNER_TRUSTED_APP 48
53#define ARM_SMCCC_OWNER_TRUSTED_APP_END 49
54#define ARM_SMCCC_OWNER_TRUSTED_OS 50
55#define ARM_SMCCC_OWNER_TRUSTED_OS_END 63
56
57#define ARM_SMCCC_FUNC_QUERY_CALL_UID 0xff01
58
59#define ARM_SMCCC_QUIRK_NONE 0
60#define ARM_SMCCC_QUIRK_QCOM_A6 1 /* Save/restore register a6 */
61
62#define ARM_SMCCC_VERSION_1_0 0x10000
63#define ARM_SMCCC_VERSION_1_1 0x10001
64#define ARM_SMCCC_VERSION_1_2 0x10002
65#define ARM_SMCCC_VERSION_1_3 0x10003
66
67#define ARM_SMCCC_1_3_SVE_HINT 0x10000
68
69#define ARM_SMCCC_VERSION_FUNC_ID \
70 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
71 ARM_SMCCC_SMC_32, \
72 0, 0)
73
74#define ARM_SMCCC_ARCH_FEATURES_FUNC_ID \
75 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
76 ARM_SMCCC_SMC_32, \
77 0, 1)
78
79#define ARM_SMCCC_ARCH_SOC_ID \
80 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
81 ARM_SMCCC_SMC_32, \
82 0, 2)
83
84#define ARM_SMCCC_ARCH_WORKAROUND_1 \
85 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
86 ARM_SMCCC_SMC_32, \
87 0, 0x8000)
88
89#define ARM_SMCCC_ARCH_WORKAROUND_2 \
90 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
91 ARM_SMCCC_SMC_32, \
92 0, 0x7fff)
93
94#define ARM_SMCCC_ARCH_WORKAROUND_3 \
95 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
96 ARM_SMCCC_SMC_32, \
97 0, 0x3fff)
98
99#define ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID \
100 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
101 ARM_SMCCC_SMC_32, \
102 ARM_SMCCC_OWNER_VENDOR_HYP, \
103 ARM_SMCCC_FUNC_QUERY_CALL_UID)
104
105/* KVM UID value: 28b46fb6-2ec5-11e9-a9ca-4b564d003a74 */
106#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0 0xb66fb428U
107#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1 0xe911c52eU
108#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2 0x564bcaa9U
109#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3 0x743a004dU
110
111/* KVM "vendor specific" services */
112#define ARM_SMCCC_KVM_FUNC_FEATURES 0
113#define ARM_SMCCC_KVM_FUNC_PTP 1
114#define ARM_SMCCC_KVM_FUNC_FEATURES_2 127
115#define ARM_SMCCC_KVM_NUM_FUNCS 128
116
117#define ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID \
118 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
119 ARM_SMCCC_SMC_32, \
120 ARM_SMCCC_OWNER_VENDOR_HYP, \
121 ARM_SMCCC_KVM_FUNC_FEATURES)
122
123#define SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED 1
124
125/*
126 * ptp_kvm is a feature used for time sync between vm and host.
127 * ptp_kvm module in guest kernel will get service from host using
128 * this hypercall ID.
129 */
130#define ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID \
131 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
132 ARM_SMCCC_SMC_32, \
133 ARM_SMCCC_OWNER_VENDOR_HYP, \
134 ARM_SMCCC_KVM_FUNC_PTP)
135
136/* ptp_kvm counter type ID */
137#define KVM_PTP_VIRT_COUNTER 0
138#define KVM_PTP_PHYS_COUNTER 1
139
140/* Paravirtualised time calls (defined by ARM DEN0057A) */
141#define ARM_SMCCC_HV_PV_TIME_FEATURES \
142 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
143 ARM_SMCCC_SMC_64, \
144 ARM_SMCCC_OWNER_STANDARD_HYP, \
145 0x20)
146
147#define ARM_SMCCC_HV_PV_TIME_ST \
148 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
149 ARM_SMCCC_SMC_64, \
150 ARM_SMCCC_OWNER_STANDARD_HYP, \
151 0x21)
152
153/* TRNG entropy source calls (defined by ARM DEN0098) */
154#define ARM_SMCCC_TRNG_VERSION \
155 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
156 ARM_SMCCC_SMC_32, \
157 ARM_SMCCC_OWNER_STANDARD, \
158 0x50)
159
160#define ARM_SMCCC_TRNG_FEATURES \
161 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
162 ARM_SMCCC_SMC_32, \
163 ARM_SMCCC_OWNER_STANDARD, \
164 0x51)
165
166#define ARM_SMCCC_TRNG_GET_UUID \
167 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
168 ARM_SMCCC_SMC_32, \
169 ARM_SMCCC_OWNER_STANDARD, \
170 0x52)
171
172#define ARM_SMCCC_TRNG_RND32 \
173 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
174 ARM_SMCCC_SMC_32, \
175 ARM_SMCCC_OWNER_STANDARD, \
176 0x53)
177
178#define ARM_SMCCC_TRNG_RND64 \
179 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
180 ARM_SMCCC_SMC_64, \
181 ARM_SMCCC_OWNER_STANDARD, \
182 0x53)
183
184/*
185 * Return codes defined in ARM DEN 0070A
186 * ARM DEN 0070A is now merged/consolidated into ARM DEN 0028 C
187 */
188#define SMCCC_RET_SUCCESS 0
189#define SMCCC_RET_NOT_SUPPORTED -1
190#define SMCCC_RET_NOT_REQUIRED -2
191#define SMCCC_RET_INVALID_PARAMETER -3
192
193#endif /*__LINUX_ARM_SMCCC_H*/
tools/testing/selftests/kvm/.gitignore+2−1
@@ -2,7 +2,8 @@ · 1 unmodified line
2/aarch64/arch_timer2/aarch64/arch_timer
3/aarch64/debug-exceptions3/aarch64/debug-exceptions
4/aarch64/get-reg-list4/aarch64/get-reg-list
5/aarch64/psci_cpu_on_test5/aarch64/hypercalls
6/aarch64/psci_test
6/aarch64/vcpu_width_config7/aarch64/vcpu_width_config
7/aarch64/vgic_init8/aarch64/vgic_init
8/aarch64/vgic_irq9/aarch64/vgic_irq
tools/testing/selftests/kvm/Makefile+2−1
@@ -105,7 +105,8 @@ TEST_GEN_PROGS_x86_64 += system_counter_offset_test · 104 unmodified lines
105TEST_GEN_PROGS_aarch64 += aarch64/arch_timer105TEST_GEN_PROGS_aarch64 += aarch64/arch_timer
106TEST_GEN_PROGS_aarch64 += aarch64/debug-exceptions106TEST_GEN_PROGS_aarch64 += aarch64/debug-exceptions
107TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list107TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list
108TEST_GEN_PROGS_aarch64 += aarch64/psci_cpu_on_test108TEST_GEN_PROGS_aarch64 += aarch64/hypercalls
109TEST_GEN_PROGS_aarch64 += aarch64/psci_test
109TEST_GEN_PROGS_aarch64 += aarch64/vcpu_width_config110TEST_GEN_PROGS_aarch64 += aarch64/vcpu_width_config
110TEST_GEN_PROGS_aarch64 += aarch64/vgic_init111TEST_GEN_PROGS_aarch64 += aarch64/vgic_init
111TEST_GEN_PROGS_aarch64 += aarch64/vgic_irq112TEST_GEN_PROGS_aarch64 += aarch64/vgic_irq
tools/testing/selftests/kvm/aarch64/get-reg-list.c+8−0
@@ -294,6 +294,11 @@ static void print_reg(struct vcpu_config *c, __u64 id) · 293 unmodified lines
294 "%s: Unexpected bits set in FW reg id: 0x%llx", config_name(c), id);294 "%s: Unexpected bits set in FW reg id: 0x%llx", config_name(c), id);
295 printf("\tKVM_REG_ARM_FW_REG(%lld),\n", id & 0xffff);295 printf("\tKVM_REG_ARM_FW_REG(%lld),\n", id & 0xffff);
296 break;296 break;
297 case KVM_REG_ARM_FW_FEAT_BMAP:
298 TEST_ASSERT(id == KVM_REG_ARM_FW_FEAT_BMAP_REG(id & 0xffff),
299 "%s: Unexpected bits set in the bitmap feature FW reg id: 0x%llx", config_name(c), id);
300 printf("\tKVM_REG_ARM_FW_FEAT_BMAP_REG(%lld),\n", id & 0xffff);
301 break;
297 case KVM_REG_ARM64_SVE:302 case KVM_REG_ARM64_SVE:
298 if (has_cap(c, KVM_CAP_ARM_SVE))303 if (has_cap(c, KVM_CAP_ARM_SVE))
299 printf("\t%s,\n", sve_id_to_str(c, id));304 printf("\t%s,\n", sve_id_to_str(c, id));
@@ -692,6 +697,9 @@ static __u64 base_regs[] = { · 392 unmodified lines
692 KVM_REG_ARM_FW_REG(1), /* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1 */697 KVM_REG_ARM_FW_REG(1), /* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1 */
693 KVM_REG_ARM_FW_REG(2), /* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2 */698 KVM_REG_ARM_FW_REG(2), /* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2 */
694 KVM_REG_ARM_FW_REG(3), /* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3 */699 KVM_REG_ARM_FW_REG(3), /* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3 */
700 KVM_REG_ARM_FW_FEAT_BMAP_REG(0), /* KVM_REG_ARM_STD_BMAP */
701 KVM_REG_ARM_FW_FEAT_BMAP_REG(1), /* KVM_REG_ARM_STD_HYP_BMAP */
702 KVM_REG_ARM_FW_FEAT_BMAP_REG(2), /* KVM_REG_ARM_VENDOR_HYP_BMAP */
695 ARM64_SYS_REG(3, 3, 14, 3, 1), /* CNTV_CTL_EL0 */703 ARM64_SYS_REG(3, 3, 14, 3, 1), /* CNTV_CTL_EL0 */
696 ARM64_SYS_REG(3, 3, 14, 3, 2), /* CNTV_CVAL_EL0 */704 ARM64_SYS_REG(3, 3, 14, 3, 2), /* CNTV_CVAL_EL0 */
697 ARM64_SYS_REG(3, 3, 14, 0, 2),705 ARM64_SYS_REG(3, 3, 14, 0, 2),
tools/testing/selftests/kvm/aarch64/hypercalls.c+336−0
@@ -0,0 +1,336 @@
1// SPDX-License-Identifier: GPL-2.0-only
2
3/* hypercalls: Check the ARM64's psuedo-firmware bitmap register interface.
4 *
5 * The test validates the basic hypercall functionalities that are exposed
6 * via the psuedo-firmware bitmap register. This includes the registers'
7 * read/write behavior before and after the VM has started, and if the
8 * hypercalls are properly masked or unmasked to the guest when disabled or
9 * enabled from the KVM userspace, respectively.
10 */
11
12#include <errno.h>
13#include <linux/arm-smccc.h>
14#include <asm/kvm.h>
15#include <kvm_util.h>
16
17#include "processor.h"
18
19#define FW_REG_ULIMIT_VAL(max_feat_bit) (GENMASK(max_feat_bit, 0))
20
21/* Last valid bits of the bitmapped firmware registers */
22#define KVM_REG_ARM_STD_BMAP_BIT_MAX 0
23#define KVM_REG_ARM_STD_HYP_BMAP_BIT_MAX 0
24#define KVM_REG_ARM_VENDOR_HYP_BMAP_BIT_MAX 1
25
26struct kvm_fw_reg_info {
27 uint64_t reg; /* Register definition */
28 uint64_t max_feat_bit; /* Bit that represents the upper limit of the feature-map */
29};
30
31#define FW_REG_INFO(r) \
32 { \
33 .reg = r, \
34 .max_feat_bit = r##_BIT_MAX, \
35 }
36
37static const struct kvm_fw_reg_info fw_reg_info[] = {
38 FW_REG_INFO(KVM_REG_ARM_STD_BMAP),
39 FW_REG_INFO(KVM_REG_ARM_STD_HYP_BMAP),
40 FW_REG_INFO(KVM_REG_ARM_VENDOR_HYP_BMAP),
41};
42
43enum test_stage {
44 TEST_STAGE_REG_IFACE,
45 TEST_STAGE_HVC_IFACE_FEAT_DISABLED,
46 TEST_STAGE_HVC_IFACE_FEAT_ENABLED,
47 TEST_STAGE_HVC_IFACE_FALSE_INFO,
48 TEST_STAGE_END,
49};
50
51static int stage = TEST_STAGE_REG_IFACE;
52
53struct test_hvc_info {
54 uint32_t func_id;
55 uint64_t arg1;
56};
57
58#define TEST_HVC_INFO(f, a1) \
59 { \
60 .func_id = f, \
61 .arg1 = a1, \
62 }
63
64static const struct test_hvc_info hvc_info[] = {
65 /* KVM_REG_ARM_STD_BMAP */
66 TEST_HVC_INFO(ARM_SMCCC_TRNG_VERSION, 0),
67 TEST_HVC_INFO(ARM_SMCCC_TRNG_FEATURES, ARM_SMCCC_TRNG_RND64),
68 TEST_HVC_INFO(ARM_SMCCC_TRNG_GET_UUID, 0),
69 TEST_HVC_INFO(ARM_SMCCC_TRNG_RND32, 0),
70 TEST_HVC_INFO(ARM_SMCCC_TRNG_RND64, 0),
71
72 /* KVM_REG_ARM_STD_HYP_BMAP */
73 TEST_HVC_INFO(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, ARM_SMCCC_HV_PV_TIME_FEATURES),
74 TEST_HVC_INFO(ARM_SMCCC_HV_PV_TIME_FEATURES, ARM_SMCCC_HV_PV_TIME_ST),
75 TEST_HVC_INFO(ARM_SMCCC_HV_PV_TIME_ST, 0),
76
77 /* KVM_REG_ARM_VENDOR_HYP_BMAP */
78 TEST_HVC_INFO(ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID,
79 ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID),
80 TEST_HVC_INFO(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, 0),
81 TEST_HVC_INFO(ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID, KVM_PTP_VIRT_COUNTER),
82};
83
84/* Feed false hypercall info to test the KVM behavior */
85static const struct test_hvc_info false_hvc_info[] = {
86 /* Feature support check against a different family of hypercalls */
87 TEST_HVC_INFO(ARM_SMCCC_TRNG_FEATURES, ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID),
88 TEST_HVC_INFO(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, ARM_SMCCC_TRNG_RND64),
89 TEST_HVC_INFO(ARM_SMCCC_HV_PV_TIME_FEATURES, ARM_SMCCC_TRNG_RND64),
90};
91
92static void guest_test_hvc(const struct test_hvc_info *hc_info)
93{
94 unsigned int i;
95 struct arm_smccc_res res;
96 unsigned int hvc_info_arr_sz;
97
98 hvc_info_arr_sz =
99 hc_info == hvc_info ? ARRAY_SIZE(hvc_info) : ARRAY_SIZE(false_hvc_info);
100
101 for (i = 0; i < hvc_info_arr_sz; i++, hc_info++) {
102 memset(&res, 0, sizeof(res));
103 smccc_hvc(hc_info->func_id, hc_info->arg1, 0, 0, 0, 0, 0, 0, &res);
104
105 switch (stage) {
106 case TEST_STAGE_HVC_IFACE_FEAT_DISABLED:
107 case TEST_STAGE_HVC_IFACE_FALSE_INFO:
108 GUEST_ASSERT_3(res.a0 == SMCCC_RET_NOT_SUPPORTED,
109 res.a0, hc_info->func_id, hc_info->arg1);
110 break;
111 case TEST_STAGE_HVC_IFACE_FEAT_ENABLED:
112 GUEST_ASSERT_3(res.a0 != SMCCC_RET_NOT_SUPPORTED,
113 res.a0, hc_info->func_id, hc_info->arg1);
114 break;
115 default:
116 GUEST_ASSERT_1(0, stage);
117 }
118 }
119}
120
121static void guest_code(void)
122{
123 while (stage != TEST_STAGE_END) {
124 switch (stage) {
125 case TEST_STAGE_REG_IFACE:
126 break;
127 case TEST_STAGE_HVC_IFACE_FEAT_DISABLED:
128 case TEST_STAGE_HVC_IFACE_FEAT_ENABLED:
129 guest_test_hvc(hvc_info);
130 break;
131 case TEST_STAGE_HVC_IFACE_FALSE_INFO:
132 guest_test_hvc(false_hvc_info);
133 break;
134 default:
135 GUEST_ASSERT_1(0, stage);
136 }
137
138 GUEST_SYNC(stage);
139 }
140
141 GUEST_DONE();
142}
143
144static int set_fw_reg(struct kvm_vm *vm, uint64_t id, uint64_t val)
145{
146 struct kvm_one_reg reg = {
147 .id = id,
148 .addr = (uint64_t)&val,
149 };
150
151 return _vcpu_ioctl(vm, 0, KVM_SET_ONE_REG, &reg);
152}
153
154static void get_fw_reg(struct kvm_vm *vm, uint64_t id, uint64_t *addr)
155{
156 struct kvm_one_reg reg = {
157 .id = id,
158 .addr = (uint64_t)addr,
159 };
160
161 vcpu_ioctl(vm, 0, KVM_GET_ONE_REG, &reg);
162}
163
164struct st_time {
165 uint32_t rev;
166 uint32_t attr;
167 uint64_t st_time;
168};
169
170#define STEAL_TIME_SIZE ((sizeof(struct st_time) + 63) & ~63)
171#define ST_GPA_BASE (1 << 30)
172
173static void steal_time_init(struct kvm_vm *vm)
174{
175 uint64_t st_ipa = (ulong)ST_GPA_BASE;
176 unsigned int gpages;
177 struct kvm_device_attr dev = {
178 .group = KVM_ARM_VCPU_PVTIME_CTRL,
179 .attr = KVM_ARM_VCPU_PVTIME_IPA,
180 .addr = (uint64_t)&st_ipa,
181 };
182
183 gpages = vm_calc_num_guest_pages(VM_MODE_DEFAULT, STEAL_TIME_SIZE);
184 vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, ST_GPA_BASE, 1, gpages, 0);
185
186 vcpu_ioctl(vm, 0, KVM_SET_DEVICE_ATTR, &dev);
187}
188
189static void test_fw_regs_before_vm_start(struct kvm_vm *vm)
190{
191 uint64_t val;
192 unsigned int i;
193 int ret;
194
195 for (i = 0; i < ARRAY_SIZE(fw_reg_info); i++) {
196 const struct kvm_fw_reg_info *reg_info = &fw_reg_info[i];
197
198 /* First 'read' should be an upper limit of the features supported */
199 get_fw_reg(vm, reg_info->reg, &val);
200 TEST_ASSERT(val == FW_REG_ULIMIT_VAL(reg_info->max_feat_bit),
201 "Expected all the features to be set for reg: 0x%lx; expected: 0x%lx; read: 0x%lx\n",
202 reg_info->reg, FW_REG_ULIMIT_VAL(reg_info->max_feat_bit), val);
203
204 /* Test a 'write' by disabling all the features of the register map */
205 ret = set_fw_reg(vm, reg_info->reg, 0);
206 TEST_ASSERT(ret == 0,
207 "Failed to clear all the features of reg: 0x%lx; ret: %d\n",
208 reg_info->reg, errno);
209
210 get_fw_reg(vm, reg_info->reg, &val);
211 TEST_ASSERT(val == 0,
212 "Expected all the features to be cleared for reg: 0x%lx\n", reg_info->reg);
213
214 /*
215 * Test enabling a feature that's not supported.
216 * Avoid this check if all the bits are occupied.
217 */
218 if (reg_info->max_feat_bit < 63) {
219 ret = set_fw_reg(vm, reg_info->reg, BIT(reg_info->max_feat_bit + 1));
220 TEST_ASSERT(ret != 0 && errno == EINVAL,
221 "Unexpected behavior or return value (%d) while setting an unsupported feature for reg: 0x%lx\n",
222 errno, reg_info->reg);
223 }
224 }
225}
226
227static void test_fw_regs_after_vm_start(struct kvm_vm *vm)
228{
229 uint64_t val;
230 unsigned int i;
231 int ret;
232
233 for (i = 0; i < ARRAY_SIZE(fw_reg_info); i++) {
234 const struct kvm_fw_reg_info *reg_info = &fw_reg_info[i];
235
236 /*
237 * Before starting the VM, the test clears all the bits.
238 * Check if that's still the case.
239 */
240 get_fw_reg(vm, reg_info->reg, &val);
241 TEST_ASSERT(val == 0,
242 "Expected all the features to be cleared for reg: 0x%lx\n",
243 reg_info->reg);
244
245 /*
246 * Since the VM has run at least once, KVM shouldn't allow modification of
247 * the registers and should return EBUSY. Set the registers and check for
248 * the expected errno.
249 */
250 ret = set_fw_reg(vm, reg_info->reg, FW_REG_ULIMIT_VAL(reg_info->max_feat_bit));
251 TEST_ASSERT(ret != 0 && errno == EBUSY,
252 "Unexpected behavior or return value (%d) while setting a feature while VM is running for reg: 0x%lx\n",
253 errno, reg_info->reg);
254 }
255}
256
257static struct kvm_vm *test_vm_create(void)
258{
259 struct kvm_vm *vm;
260
261 vm = vm_create_default(0, 0, guest_code);
262
263 ucall_init(vm, NULL);
264 steal_time_init(vm);
265
266 return vm;
267}
268
269static struct kvm_vm *test_guest_stage(struct kvm_vm *vm)
270{
271 struct kvm_vm *ret_vm = vm;
272
273 pr_debug("Stage: %d\n", stage);
274
275 switch (stage) {
276 case TEST_STAGE_REG_IFACE:
277 test_fw_regs_after_vm_start(vm);
278 break;
279 case TEST_STAGE_HVC_IFACE_FEAT_DISABLED:
280 /* Start a new VM so that all the features are now enabled by default */
281 kvm_vm_free(vm);
282 ret_vm = test_vm_create();
283 break;
284 case TEST_STAGE_HVC_IFACE_FEAT_ENABLED:
285 case TEST_STAGE_HVC_IFACE_FALSE_INFO:
286 break;
287 default:
288 TEST_FAIL("Unknown test stage: %d\n", stage);
289 }
290
291 stage++;
292 sync_global_to_guest(vm, stage);
293
294 return ret_vm;
295}
296
297static void test_run(void)
298{
299 struct kvm_vm *vm;
300 struct ucall uc;
301 bool guest_done = false;
302
303 vm = test_vm_create();
304
305 test_fw_regs_before_vm_start(vm);
306
307 while (!guest_done) {
308 vcpu_run(vm, 0);
309
310 switch (get_ucall(vm, 0, &uc)) {
311 case UCALL_SYNC:
312 vm = test_guest_stage(vm);
313 break;
314 case UCALL_DONE:
315 guest_done = true;
316 break;
317 case UCALL_ABORT:
318 TEST_FAIL("%s at %s:%ld\n\tvalues: 0x%lx, 0x%lx; 0x%lx, stage: %u",
319 (const char *)uc.args[0], __FILE__, uc.args[1],
320 uc.args[2], uc.args[3], uc.args[4], stage);
321 break;
322 default:
323 TEST_FAIL("Unexpected guest exit\n");
324 }
325 }
326
327 kvm_vm_free(vm);
328}
329
330int main(void)
331{
332 setbuf(stdout, NULL);
333
334 test_run();
335 return 0;
336}
tools/testing/selftests/kvm/aarch64/psci_test.crenamed from tools/testing/selftests/kvm/aarch64/psci_cpu_on_test.c+8−17
@@ -26,32 +26,23 @@ · 25 unmodified lines
26static uint64_t psci_cpu_on(uint64_t target_cpu, uint64_t entry_addr,26static uint64_t psci_cpu_on(uint64_t target_cpu, uint64_t entry_addr,
27 uint64_t context_id)27 uint64_t context_id)
28{28{
29 register uint64_t x0 asm("x0") = PSCI_0_2_FN64_CPU_ON;29 struct arm_smccc_res res;
30 register uint64_t x1 asm("x1") = target_cpu;
31 register uint64_t x2 asm("x2") = entry_addr;
32 register uint64_t x3 asm("x3") = context_id;
33 30
34 asm("hvc #0"31 smccc_hvc(PSCI_0_2_FN64_CPU_ON, target_cpu, entry_addr, context_id,
35 : "=r"(x0)32 0, 0, 0, 0, &res);
36 : "r"(x0), "r"(x1), "r"(x2), "r"(x3)
37 : "memory");
38 33
39 return x0;34 return res.a0;
40}35}
41 36
42static uint64_t psci_affinity_info(uint64_t target_affinity,37static uint64_t psci_affinity_info(uint64_t target_affinity,
43 uint64_t lowest_affinity_level)38 uint64_t lowest_affinity_level)
44{39{
45 register uint64_t x0 asm("x0") = PSCI_0_2_FN64_AFFINITY_INFO;40 struct arm_smccc_res res;
46 register uint64_t x1 asm("x1") = target_affinity;
47 register uint64_t x2 asm("x2") = lowest_affinity_level;
48 41
49 asm("hvc #0"42 smccc_hvc(PSCI_0_2_FN64_AFFINITY_INFO, target_affinity, lowest_affinity_level,
50 : "=r"(x0)43 0, 0, 0, 0, 0, &res);
51 : "r"(x0), "r"(x1), "r"(x2)
52 : "memory");
53 44
54 return x0;45 return res.a0;
55}46}
56 47
57static void guest_main(uint64_t target_cpu)48static void guest_main(uint64_t target_cpu)
tools/testing/selftests/kvm/include/aarch64/processor.h+22−0
@@ -185,4 +185,26 @@ static inline void local_irq_disable(void) · 184 unmodified lines
185 asm volatile("msr daifset, #3" : : : "memory");185 asm volatile("msr daifset, #3" : : : "memory");
186}186}
187 187
188/**
189 * struct arm_smccc_res - Result from SMC/HVC call
190 * @a0-a3 result values from registers 0 to 3
191 */
192struct arm_smccc_res {
193 unsigned long a0;
194 unsigned long a1;
195 unsigned long a2;
196 unsigned long a3;
197};
198
199/**
200 * smccc_hvc - Invoke a SMCCC function using the hvc conduit
201 * @function_id: the SMCCC function to be called
202 * @arg0-arg6: SMCCC function arguments, corresponding to registers x1-x7
203 * @res: pointer to write the return values from registers x0-x3
204 *
205 */
206void smccc_hvc(uint32_t function_id, uint64_t arg0, uint64_t arg1,
207 uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5,
208 uint64_t arg6, struct arm_smccc_res *res);
209
188#endif /* SELFTEST_KVM_PROCESSOR_H */210#endif /* SELFTEST_KVM_PROCESSOR_H */
tools/testing/selftests/kvm/lib/aarch64/processor.c+25−0
@@ -500,3 +500,28 @@ void __attribute__((constructor)) init_guest_modes(void) · 499 unmodified lines
500{500{
501 guest_modes_append_default();501 guest_modes_append_default();
502}502}
503
504void smccc_hvc(uint32_t function_id, uint64_t arg0, uint64_t arg1,
505 uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5,
506 uint64_t arg6, struct arm_smccc_res *res)
507{
508 asm volatile("mov w0, %w[function_id]\n"
509 "mov x1, %[arg0]\n"
510 "mov x2, %[arg1]\n"
511 "mov x3, %[arg2]\n"
512 "mov x4, %[arg3]\n"
513 "mov x5, %[arg4]\n"
514 "mov x6, %[arg5]\n"
515 "mov x7, %[arg6]\n"
516 "hvc #0\n"
517 "mov %[res0], x0\n"
518 "mov %[res1], x1\n"
519 "mov %[res2], x2\n"
520 "mov %[res3], x3\n"
521 : [res0] "=r"(res->a0), [res1] "=r"(res->a1),
522 [res2] "=r"(res->a2), [res3] "=r"(res->a3)
523 : [function_id] "r"(function_id), [arg0] "r"(arg0),
524 [arg1] "r"(arg1), [arg2] "r"(arg2), [arg3] "r"(arg3),
525 [arg4] "r"(arg4), [arg5] "r"(arg5), [arg6] "r"(arg6)
526 : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7");
527}
tools/testing/selftests/kvm/steal_time.c+3−10
@@ -118,17 +118,10 @@ struct st_time { · 117 unmodified lines
118 118
119static int64_t smccc(uint32_t func, uint64_t arg)119static int64_t smccc(uint32_t func, uint64_t arg)
120{120{
121 unsigned long ret;121 struct arm_smccc_res res;
122 122
123 asm volatile(123 smccc_hvc(func, arg, 0, 0, 0, 0, 0, 0, &res);
124 "mov w0, %w1\n"124 return res.a0;
125 "mov x1, %2\n"
126 "hvc #0\n"
127 "mov %0, x0\n"
128 : "=r" (ret) : "r" (func), "r" (arg) :
129 "x0", "x1", "x2", "x3");
130
131 return ret;
132}125}
133 126
134static void check_status(struct st_time *st)127static void check_status(struct st_time *st)