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 
kvm_ptp_get_time(struct kvm_vcpu * vcpu,u64 * val)12 static void kvm_ptp_get_time(struct kvm_vcpu *vcpu, u64 *val)
13 {
14 	struct system_time_snapshot systime_snapshot;
15 	u64 cycles = ~0UL;
16 	u32 feature;
17 
18 	/*
19 	 * system time and counter value must captured at the same
20 	 * time to keep consistency and precision.
21 	 */
22 	ktime_get_snapshot(&systime_snapshot);
23 
24 	/*
25 	 * This is only valid if the current clocksource is the
26 	 * architected counter, as this is the only one the guest
27 	 * can see.
28 	 */
29 	if (systime_snapshot.cs_id != CSID_ARM_ARCH_COUNTER)
30 		return;
31 
32 	/*
33 	 * The guest selects one of the two reference counters
34 	 * (virtual or physical) with the first argument of the SMCCC
35 	 * call. In case the identifier is not supported, error out.
36 	 */
37 	feature = smccc_get_arg1(vcpu);
38 	switch (feature) {
39 	case KVM_PTP_VIRT_COUNTER:
40 		cycles = systime_snapshot.cycles - vcpu_read_sys_reg(vcpu, CNTVOFF_EL2);
41 		break;
42 	case KVM_PTP_PHYS_COUNTER:
43 		cycles = systime_snapshot.cycles;
44 		break;
45 	default:
46 		return;
47 	}
48 
49 	/*
50 	 * This relies on the top bit of val[0] never being set for
51 	 * valid values of system time, because that is *really* far
52 	 * in the future (about 292 years from 1970, and at that stage
53 	 * nobody will give a damn about it).
54 	 */
55 	val[0] = upper_32_bits(systime_snapshot.real);
56 	val[1] = lower_32_bits(systime_snapshot.real);
57 	val[2] = upper_32_bits(cycles);
58 	val[3] = lower_32_bits(cycles);
59 }
60 
kvm_hvc_call_handler(struct kvm_vcpu * vcpu)61 int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
62 {
63 	u32 func_id = smccc_get_function(vcpu);
64 	u64 val[4] = {SMCCC_RET_NOT_SUPPORTED};
65 	u32 feature;
66 	gpa_t gpa;
67 
68 	switch (func_id) {
69 	case ARM_SMCCC_VERSION_FUNC_ID:
70 		val[0] = ARM_SMCCC_VERSION_1_1;
71 		break;
72 	case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
73 		feature = smccc_get_arg1(vcpu);
74 		switch (feature) {
75 		case ARM_SMCCC_ARCH_WORKAROUND_1:
76 			switch (arm64_get_spectre_v2_state()) {
77 			case SPECTRE_VULNERABLE:
78 				break;
79 			case SPECTRE_MITIGATED:
80 				val[0] = SMCCC_RET_SUCCESS;
81 				break;
82 			case SPECTRE_UNAFFECTED:
83 				val[0] = SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED;
84 				break;
85 			}
86 			break;
87 		case ARM_SMCCC_ARCH_WORKAROUND_2:
88 			switch (arm64_get_spectre_v4_state()) {
89 			case SPECTRE_VULNERABLE:
90 				break;
91 			case SPECTRE_MITIGATED:
92 				/*
93 				 * SSBS everywhere: Indicate no firmware
94 				 * support, as the SSBS support will be
95 				 * indicated to the guest and the default is
96 				 * safe.
97 				 *
98 				 * Otherwise, expose a permanent mitigation
99 				 * to the guest, and hide SSBS so that the
100 				 * guest stays protected.
101 				 */
102 				if (cpus_have_final_cap(ARM64_SSBS))
103 					break;
104 				fallthrough;
105 			case SPECTRE_UNAFFECTED:
106 				val[0] = SMCCC_RET_NOT_REQUIRED;
107 				break;
108 			}
109 			break;
110 		case ARM_SMCCC_HV_PV_TIME_FEATURES:
111 			val[0] = SMCCC_RET_SUCCESS;
112 			break;
113 		}
114 		break;
115 	case ARM_SMCCC_HV_PV_TIME_FEATURES:
116 		val[0] = kvm_hypercall_pv_features(vcpu);
117 		break;
118 	case ARM_SMCCC_HV_PV_TIME_ST:
119 		gpa = kvm_init_stolen_time(vcpu);
120 		if (gpa != GPA_INVALID)
121 			val[0] = gpa;
122 		break;
123 	case ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID:
124 		val[0] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0;
125 		val[1] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1;
126 		val[2] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2;
127 		val[3] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3;
128 		break;
129 	case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID:
130 		val[0] = BIT(ARM_SMCCC_KVM_FUNC_FEATURES);
131 		val[0] |= BIT(ARM_SMCCC_KVM_FUNC_PTP);
132 		break;
133 	case ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID:
134 		kvm_ptp_get_time(vcpu, val);
135 		break;
136 	case ARM_SMCCC_TRNG_VERSION:
137 	case ARM_SMCCC_TRNG_FEATURES:
138 	case ARM_SMCCC_TRNG_GET_UUID:
139 	case ARM_SMCCC_TRNG_RND32:
140 	case ARM_SMCCC_TRNG_RND64:
141 		return kvm_trng_call(vcpu);
142 	default:
143 		return kvm_psci_call(vcpu);
144 	}
145 
146 	smccc_set_retval(vcpu, val[0], val[1], val[2], val[3]);
147 	return 1;
148 }
149