xref: /openbmc/linux/arch/arm64/kvm/hypercalls.c (revision a5905d6af492ee6a4a2205f0d550b3f931b03d03)
19ed24f4bSMarc Zyngier // SPDX-License-Identifier: GPL-2.0
29ed24f4bSMarc Zyngier // Copyright (C) 2019 Arm Ltd.
39ed24f4bSMarc Zyngier 
49ed24f4bSMarc Zyngier #include <linux/arm-smccc.h>
59ed24f4bSMarc Zyngier #include <linux/kvm_host.h>
69ed24f4bSMarc Zyngier 
79ed24f4bSMarc Zyngier #include <asm/kvm_emulate.h>
89ed24f4bSMarc Zyngier 
99ed24f4bSMarc Zyngier #include <kvm/arm_hypercalls.h>
109ed24f4bSMarc Zyngier #include <kvm/arm_psci.h>
119ed24f4bSMarc Zyngier 
123bf72569SJianyong Wu static void kvm_ptp_get_time(struct kvm_vcpu *vcpu, u64 *val)
133bf72569SJianyong Wu {
143bf72569SJianyong Wu 	struct system_time_snapshot systime_snapshot;
153bf72569SJianyong Wu 	u64 cycles = ~0UL;
163bf72569SJianyong Wu 	u32 feature;
173bf72569SJianyong Wu 
183bf72569SJianyong Wu 	/*
193bf72569SJianyong Wu 	 * system time and counter value must captured at the same
203bf72569SJianyong Wu 	 * time to keep consistency and precision.
213bf72569SJianyong Wu 	 */
223bf72569SJianyong Wu 	ktime_get_snapshot(&systime_snapshot);
233bf72569SJianyong Wu 
243bf72569SJianyong Wu 	/*
253bf72569SJianyong Wu 	 * This is only valid if the current clocksource is the
263bf72569SJianyong Wu 	 * architected counter, as this is the only one the guest
273bf72569SJianyong Wu 	 * can see.
283bf72569SJianyong Wu 	 */
293bf72569SJianyong Wu 	if (systime_snapshot.cs_id != CSID_ARM_ARCH_COUNTER)
303bf72569SJianyong Wu 		return;
313bf72569SJianyong Wu 
323bf72569SJianyong Wu 	/*
333bf72569SJianyong Wu 	 * The guest selects one of the two reference counters
343bf72569SJianyong Wu 	 * (virtual or physical) with the first argument of the SMCCC
353bf72569SJianyong Wu 	 * call. In case the identifier is not supported, error out.
363bf72569SJianyong Wu 	 */
373bf72569SJianyong Wu 	feature = smccc_get_arg1(vcpu);
383bf72569SJianyong Wu 	switch (feature) {
393bf72569SJianyong Wu 	case KVM_PTP_VIRT_COUNTER:
403bf72569SJianyong Wu 		cycles = systime_snapshot.cycles - vcpu_read_sys_reg(vcpu, CNTVOFF_EL2);
413bf72569SJianyong Wu 		break;
423bf72569SJianyong Wu 	case KVM_PTP_PHYS_COUNTER:
433bf72569SJianyong Wu 		cycles = systime_snapshot.cycles;
443bf72569SJianyong Wu 		break;
453bf72569SJianyong Wu 	default:
463bf72569SJianyong Wu 		return;
473bf72569SJianyong Wu 	}
483bf72569SJianyong Wu 
493bf72569SJianyong Wu 	/*
503bf72569SJianyong Wu 	 * This relies on the top bit of val[0] never being set for
513bf72569SJianyong Wu 	 * valid values of system time, because that is *really* far
523bf72569SJianyong Wu 	 * in the future (about 292 years from 1970, and at that stage
533bf72569SJianyong Wu 	 * nobody will give a damn about it).
543bf72569SJianyong Wu 	 */
553bf72569SJianyong Wu 	val[0] = upper_32_bits(systime_snapshot.real);
563bf72569SJianyong Wu 	val[1] = lower_32_bits(systime_snapshot.real);
573bf72569SJianyong Wu 	val[2] = upper_32_bits(cycles);
583bf72569SJianyong Wu 	val[3] = lower_32_bits(cycles);
593bf72569SJianyong Wu }
603bf72569SJianyong Wu 
619ed24f4bSMarc Zyngier int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
629ed24f4bSMarc Zyngier {
639ed24f4bSMarc Zyngier 	u32 func_id = smccc_get_function(vcpu);
64923961a7SWill Deacon 	u64 val[4] = {SMCCC_RET_NOT_SUPPORTED};
659ed24f4bSMarc Zyngier 	u32 feature;
669ed24f4bSMarc Zyngier 	gpa_t gpa;
679ed24f4bSMarc Zyngier 
689ed24f4bSMarc Zyngier 	switch (func_id) {
699ed24f4bSMarc Zyngier 	case ARM_SMCCC_VERSION_FUNC_ID:
70923961a7SWill Deacon 		val[0] = ARM_SMCCC_VERSION_1_1;
719ed24f4bSMarc Zyngier 		break;
729ed24f4bSMarc Zyngier 	case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
739ed24f4bSMarc Zyngier 		feature = smccc_get_arg1(vcpu);
749ed24f4bSMarc Zyngier 		switch (feature) {
759ed24f4bSMarc Zyngier 		case ARM_SMCCC_ARCH_WORKAROUND_1:
76d4647f0aSWill Deacon 			switch (arm64_get_spectre_v2_state()) {
77d4647f0aSWill Deacon 			case SPECTRE_VULNERABLE:
789ed24f4bSMarc Zyngier 				break;
79d4647f0aSWill Deacon 			case SPECTRE_MITIGATED:
80923961a7SWill Deacon 				val[0] = SMCCC_RET_SUCCESS;
819ed24f4bSMarc Zyngier 				break;
82d4647f0aSWill Deacon 			case SPECTRE_UNAFFECTED:
83923961a7SWill Deacon 				val[0] = SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED;
849ed24f4bSMarc Zyngier 				break;
859ed24f4bSMarc Zyngier 			}
869ed24f4bSMarc Zyngier 			break;
879ed24f4bSMarc Zyngier 		case ARM_SMCCC_ARCH_WORKAROUND_2:
88d63d975aSMarc Zyngier 			switch (arm64_get_spectre_v4_state()) {
89d63d975aSMarc Zyngier 			case SPECTRE_VULNERABLE:
909ed24f4bSMarc Zyngier 				break;
91d63d975aSMarc Zyngier 			case SPECTRE_MITIGATED:
92d63d975aSMarc Zyngier 				/*
93d63d975aSMarc Zyngier 				 * SSBS everywhere: Indicate no firmware
94d63d975aSMarc Zyngier 				 * support, as the SSBS support will be
95d63d975aSMarc Zyngier 				 * indicated to the guest and the default is
96d63d975aSMarc Zyngier 				 * safe.
97d63d975aSMarc Zyngier 				 *
98d63d975aSMarc Zyngier 				 * Otherwise, expose a permanent mitigation
99d63d975aSMarc Zyngier 				 * to the guest, and hide SSBS so that the
100d63d975aSMarc Zyngier 				 * guest stays protected.
101d63d975aSMarc Zyngier 				 */
102d63d975aSMarc Zyngier 				if (cpus_have_final_cap(ARM64_SSBS))
103d63d975aSMarc Zyngier 					break;
104d63d975aSMarc Zyngier 				fallthrough;
105d63d975aSMarc Zyngier 			case SPECTRE_UNAFFECTED:
106923961a7SWill Deacon 				val[0] = SMCCC_RET_NOT_REQUIRED;
1079ed24f4bSMarc Zyngier 				break;
1089ed24f4bSMarc Zyngier 			}
1099ed24f4bSMarc Zyngier 			break;
110*a5905d6aSJames Morse 		case ARM_SMCCC_ARCH_WORKAROUND_3:
111*a5905d6aSJames Morse 			switch (arm64_get_spectre_bhb_state()) {
112*a5905d6aSJames Morse 			case SPECTRE_VULNERABLE:
113*a5905d6aSJames Morse 				break;
114*a5905d6aSJames Morse 			case SPECTRE_MITIGATED:
115*a5905d6aSJames Morse 				val[0] = SMCCC_RET_SUCCESS;
116*a5905d6aSJames Morse 				break;
117*a5905d6aSJames Morse 			case SPECTRE_UNAFFECTED:
118*a5905d6aSJames Morse 				val[0] = SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED;
119*a5905d6aSJames Morse 				break;
120*a5905d6aSJames Morse 			}
121*a5905d6aSJames Morse 			break;
1229ed24f4bSMarc Zyngier 		case ARM_SMCCC_HV_PV_TIME_FEATURES:
123923961a7SWill Deacon 			val[0] = SMCCC_RET_SUCCESS;
1249ed24f4bSMarc Zyngier 			break;
1259ed24f4bSMarc Zyngier 		}
1269ed24f4bSMarc Zyngier 		break;
1279ed24f4bSMarc Zyngier 	case ARM_SMCCC_HV_PV_TIME_FEATURES:
128923961a7SWill Deacon 		val[0] = kvm_hypercall_pv_features(vcpu);
1299ed24f4bSMarc Zyngier 		break;
1309ed24f4bSMarc Zyngier 	case ARM_SMCCC_HV_PV_TIME_ST:
1319ed24f4bSMarc Zyngier 		gpa = kvm_init_stolen_time(vcpu);
1329ed24f4bSMarc Zyngier 		if (gpa != GPA_INVALID)
133923961a7SWill Deacon 			val[0] = gpa;
134923961a7SWill Deacon 		break;
135923961a7SWill Deacon 	case ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID:
136923961a7SWill Deacon 		val[0] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0;
137923961a7SWill Deacon 		val[1] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1;
138923961a7SWill Deacon 		val[2] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2;
139923961a7SWill Deacon 		val[3] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3;
140923961a7SWill Deacon 		break;
141923961a7SWill Deacon 	case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID:
142923961a7SWill Deacon 		val[0] = BIT(ARM_SMCCC_KVM_FUNC_FEATURES);
1433bf72569SJianyong Wu 		val[0] |= BIT(ARM_SMCCC_KVM_FUNC_PTP);
1443bf72569SJianyong Wu 		break;
1453bf72569SJianyong Wu 	case ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID:
1463bf72569SJianyong Wu 		kvm_ptp_get_time(vcpu, val);
1479ed24f4bSMarc Zyngier 		break;
148a8e190cdSArd Biesheuvel 	case ARM_SMCCC_TRNG_VERSION:
149a8e190cdSArd Biesheuvel 	case ARM_SMCCC_TRNG_FEATURES:
150a8e190cdSArd Biesheuvel 	case ARM_SMCCC_TRNG_GET_UUID:
151a8e190cdSArd Biesheuvel 	case ARM_SMCCC_TRNG_RND32:
152a8e190cdSArd Biesheuvel 	case ARM_SMCCC_TRNG_RND64:
153a8e190cdSArd Biesheuvel 		return kvm_trng_call(vcpu);
1549ed24f4bSMarc Zyngier 	default:
1559ed24f4bSMarc Zyngier 		return kvm_psci_call(vcpu);
1569ed24f4bSMarc Zyngier 	}
1579ed24f4bSMarc Zyngier 
158923961a7SWill Deacon 	smccc_set_retval(vcpu, val[0], val[1], val[2], val[3]);
1599ed24f4bSMarc Zyngier 	return 1;
1609ed24f4bSMarc Zyngier }
161