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