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 1205714cabSRaghavendra Rao Ananta #define KVM_ARM_SMCCC_STD_FEATURES \ 1305714cabSRaghavendra Rao Ananta GENMASK(KVM_REG_ARM_STD_BMAP_BIT_COUNT - 1, 0) 14428fd678SRaghavendra Rao Ananta #define KVM_ARM_SMCCC_STD_HYP_FEATURES \ 15428fd678SRaghavendra Rao Ananta GENMASK(KVM_REG_ARM_STD_HYP_BMAP_BIT_COUNT - 1, 0) 16b22216e1SRaghavendra Rao Ananta #define KVM_ARM_SMCCC_VENDOR_HYP_FEATURES \ 17b22216e1SRaghavendra Rao Ananta GENMASK(KVM_REG_ARM_VENDOR_HYP_BMAP_BIT_COUNT - 1, 0) 1805714cabSRaghavendra Rao Ananta 193bf72569SJianyong Wu static void kvm_ptp_get_time(struct kvm_vcpu *vcpu, u64 *val) 203bf72569SJianyong Wu { 213bf72569SJianyong Wu struct system_time_snapshot systime_snapshot; 223bf72569SJianyong Wu u64 cycles = ~0UL; 233bf72569SJianyong Wu u32 feature; 243bf72569SJianyong Wu 253bf72569SJianyong Wu /* 263bf72569SJianyong Wu * system time and counter value must captured at the same 273bf72569SJianyong Wu * time to keep consistency and precision. 283bf72569SJianyong Wu */ 293bf72569SJianyong Wu ktime_get_snapshot(&systime_snapshot); 303bf72569SJianyong Wu 313bf72569SJianyong Wu /* 323bf72569SJianyong Wu * This is only valid if the current clocksource is the 333bf72569SJianyong Wu * architected counter, as this is the only one the guest 343bf72569SJianyong Wu * can see. 353bf72569SJianyong Wu */ 363bf72569SJianyong Wu if (systime_snapshot.cs_id != CSID_ARM_ARCH_COUNTER) 373bf72569SJianyong Wu return; 383bf72569SJianyong Wu 393bf72569SJianyong Wu /* 403bf72569SJianyong Wu * The guest selects one of the two reference counters 413bf72569SJianyong Wu * (virtual or physical) with the first argument of the SMCCC 423bf72569SJianyong Wu * call. In case the identifier is not supported, error out. 433bf72569SJianyong Wu */ 443bf72569SJianyong Wu feature = smccc_get_arg1(vcpu); 453bf72569SJianyong Wu switch (feature) { 463bf72569SJianyong Wu case KVM_PTP_VIRT_COUNTER: 4747053904SMarc Zyngier cycles = systime_snapshot.cycles - vcpu->kvm->arch.timer_data.voffset; 483bf72569SJianyong Wu break; 493bf72569SJianyong Wu case KVM_PTP_PHYS_COUNTER: 503bf72569SJianyong Wu cycles = systime_snapshot.cycles; 513bf72569SJianyong Wu break; 523bf72569SJianyong Wu default: 533bf72569SJianyong Wu return; 543bf72569SJianyong Wu } 553bf72569SJianyong Wu 563bf72569SJianyong Wu /* 573bf72569SJianyong Wu * This relies on the top bit of val[0] never being set for 583bf72569SJianyong Wu * valid values of system time, because that is *really* far 593bf72569SJianyong Wu * in the future (about 292 years from 1970, and at that stage 603bf72569SJianyong Wu * nobody will give a damn about it). 613bf72569SJianyong Wu */ 623bf72569SJianyong Wu val[0] = upper_32_bits(systime_snapshot.real); 633bf72569SJianyong Wu val[1] = lower_32_bits(systime_snapshot.real); 643bf72569SJianyong Wu val[2] = upper_32_bits(cycles); 653bf72569SJianyong Wu val[3] = lower_32_bits(cycles); 663bf72569SJianyong Wu } 673bf72569SJianyong Wu 68a8308b3fSOliver Upton static bool kvm_smccc_default_allowed(u32 func_id) 6905714cabSRaghavendra Rao Ananta { 7005714cabSRaghavendra Rao Ananta switch (func_id) { 7105714cabSRaghavendra Rao Ananta /* 7205714cabSRaghavendra Rao Ananta * List of function-ids that are not gated with the bitmapped 7305714cabSRaghavendra Rao Ananta * feature firmware registers, and are to be allowed for 7405714cabSRaghavendra Rao Ananta * servicing the call by default. 7505714cabSRaghavendra Rao Ananta */ 7605714cabSRaghavendra Rao Ananta case ARM_SMCCC_VERSION_FUNC_ID: 7705714cabSRaghavendra Rao Ananta case ARM_SMCCC_ARCH_FEATURES_FUNC_ID: 7805714cabSRaghavendra Rao Ananta return true; 7905714cabSRaghavendra Rao Ananta default: 8005714cabSRaghavendra Rao Ananta /* PSCI 0.2 and up is in the 0:0x1f range */ 8105714cabSRaghavendra Rao Ananta if (ARM_SMCCC_OWNER_NUM(func_id) == ARM_SMCCC_OWNER_STANDARD && 8205714cabSRaghavendra Rao Ananta ARM_SMCCC_FUNC_NUM(func_id) <= 0x1f) 8305714cabSRaghavendra Rao Ananta return true; 8405714cabSRaghavendra Rao Ananta 8505714cabSRaghavendra Rao Ananta /* 8605714cabSRaghavendra Rao Ananta * KVM's PSCI 0.1 doesn't comply with SMCCC, and has 8705714cabSRaghavendra Rao Ananta * its own function-id base and range 8805714cabSRaghavendra Rao Ananta */ 8905714cabSRaghavendra Rao Ananta if (func_id >= KVM_PSCI_FN(0) && func_id <= KVM_PSCI_FN(3)) 9005714cabSRaghavendra Rao Ananta return true; 9105714cabSRaghavendra Rao Ananta 9205714cabSRaghavendra Rao Ananta return false; 9305714cabSRaghavendra Rao Ananta } 9405714cabSRaghavendra Rao Ananta } 9505714cabSRaghavendra Rao Ananta 96a8308b3fSOliver Upton static bool kvm_smccc_test_fw_bmap(struct kvm_vcpu *vcpu, u32 func_id) 9705714cabSRaghavendra Rao Ananta { 9805714cabSRaghavendra Rao Ananta struct kvm_smccc_features *smccc_feat = &vcpu->kvm->arch.smccc_feat; 9905714cabSRaghavendra Rao Ananta 10005714cabSRaghavendra Rao Ananta switch (func_id) { 10105714cabSRaghavendra Rao Ananta case ARM_SMCCC_TRNG_VERSION: 10205714cabSRaghavendra Rao Ananta case ARM_SMCCC_TRNG_FEATURES: 10305714cabSRaghavendra Rao Ananta case ARM_SMCCC_TRNG_GET_UUID: 10405714cabSRaghavendra Rao Ananta case ARM_SMCCC_TRNG_RND32: 10505714cabSRaghavendra Rao Ananta case ARM_SMCCC_TRNG_RND64: 10605714cabSRaghavendra Rao Ananta return test_bit(KVM_REG_ARM_STD_BIT_TRNG_V1_0, 10705714cabSRaghavendra Rao Ananta &smccc_feat->std_bmap); 108428fd678SRaghavendra Rao Ananta case ARM_SMCCC_HV_PV_TIME_FEATURES: 109428fd678SRaghavendra Rao Ananta case ARM_SMCCC_HV_PV_TIME_ST: 110428fd678SRaghavendra Rao Ananta return test_bit(KVM_REG_ARM_STD_HYP_BIT_PV_TIME, 111428fd678SRaghavendra Rao Ananta &smccc_feat->std_hyp_bmap); 112b22216e1SRaghavendra Rao Ananta case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID: 113b22216e1SRaghavendra Rao Ananta case ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID: 114b22216e1SRaghavendra Rao Ananta return test_bit(KVM_REG_ARM_VENDOR_HYP_BIT_FUNC_FEAT, 115b22216e1SRaghavendra Rao Ananta &smccc_feat->vendor_hyp_bmap); 116b22216e1SRaghavendra Rao Ananta case ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID: 117b22216e1SRaghavendra Rao Ananta return test_bit(KVM_REG_ARM_VENDOR_HYP_BIT_PTP, 118b22216e1SRaghavendra Rao Ananta &smccc_feat->vendor_hyp_bmap); 11905714cabSRaghavendra Rao Ananta default: 120a8308b3fSOliver Upton return false; 12105714cabSRaghavendra Rao Ananta } 12205714cabSRaghavendra Rao Ananta } 12305714cabSRaghavendra Rao Ananta 124fb88707dSOliver Upton #define SMCCC_ARCH_RANGE_BEGIN ARM_SMCCC_VERSION_FUNC_ID 125fb88707dSOliver Upton #define SMCCC_ARCH_RANGE_END \ 126fb88707dSOliver Upton ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ 127fb88707dSOliver Upton ARM_SMCCC_SMC_32, \ 128fb88707dSOliver Upton 0, ARM_SMCCC_FUNC_MASK) 129fb88707dSOliver Upton 130fb88707dSOliver Upton static void init_smccc_filter(struct kvm *kvm) 131fb88707dSOliver Upton { 132fb88707dSOliver Upton int r; 133fb88707dSOliver Upton 134fb88707dSOliver Upton mt_init(&kvm->arch.smccc_filter); 135fb88707dSOliver Upton 136fb88707dSOliver Upton /* 137fb88707dSOliver Upton * Prevent userspace from handling any SMCCC calls in the architecture 138fb88707dSOliver Upton * range, avoiding the risk of misrepresenting Spectre mitigation status 139fb88707dSOliver Upton * to the guest. 140fb88707dSOliver Upton */ 141fb88707dSOliver Upton r = mtree_insert_range(&kvm->arch.smccc_filter, 142fb88707dSOliver Upton SMCCC_ARCH_RANGE_BEGIN, SMCCC_ARCH_RANGE_END, 143fb88707dSOliver Upton xa_mk_value(KVM_SMCCC_FILTER_HANDLE), 144fb88707dSOliver Upton GFP_KERNEL_ACCOUNT); 145fb88707dSOliver Upton WARN_ON_ONCE(r); 146fb88707dSOliver Upton } 147fb88707dSOliver Upton 148821d935cSOliver Upton static int kvm_smccc_set_filter(struct kvm *kvm, struct kvm_smccc_filter __user *uaddr) 149821d935cSOliver Upton { 150821d935cSOliver Upton const void *zero_page = page_to_virt(ZERO_PAGE(0)); 151821d935cSOliver Upton struct kvm_smccc_filter filter; 152821d935cSOliver Upton u32 start, end; 153821d935cSOliver Upton int r; 154821d935cSOliver Upton 155821d935cSOliver Upton if (copy_from_user(&filter, uaddr, sizeof(filter))) 156821d935cSOliver Upton return -EFAULT; 157821d935cSOliver Upton 158821d935cSOliver Upton if (memcmp(filter.pad, zero_page, sizeof(filter.pad))) 159821d935cSOliver Upton return -EINVAL; 160821d935cSOliver Upton 161821d935cSOliver Upton start = filter.base; 162821d935cSOliver Upton end = start + filter.nr_functions - 1; 163821d935cSOliver Upton 164821d935cSOliver Upton if (end < start || filter.action >= NR_SMCCC_FILTER_ACTIONS) 165821d935cSOliver Upton return -EINVAL; 166821d935cSOliver Upton 167821d935cSOliver Upton mutex_lock(&kvm->lock); 168821d935cSOliver Upton 169821d935cSOliver Upton if (kvm_vm_has_ran_once(kvm)) { 170821d935cSOliver Upton r = -EBUSY; 171821d935cSOliver Upton goto out_unlock; 172821d935cSOliver Upton } 173821d935cSOliver Upton 174821d935cSOliver Upton r = mtree_insert_range(&kvm->arch.smccc_filter, start, end, 175821d935cSOliver Upton xa_mk_value(filter.action), GFP_KERNEL_ACCOUNT); 176821d935cSOliver Upton if (r) 177821d935cSOliver Upton goto out_unlock; 178821d935cSOliver Upton 179821d935cSOliver Upton set_bit(KVM_ARCH_FLAG_SMCCC_FILTER_CONFIGURED, &kvm->arch.flags); 180821d935cSOliver Upton 181821d935cSOliver Upton out_unlock: 182821d935cSOliver Upton mutex_unlock(&kvm->lock); 183821d935cSOliver Upton return r; 184821d935cSOliver Upton } 185821d935cSOliver Upton 186fb88707dSOliver Upton static u8 kvm_smccc_filter_get_action(struct kvm *kvm, u32 func_id) 187fb88707dSOliver Upton { 188fb88707dSOliver Upton unsigned long idx = func_id; 189fb88707dSOliver Upton void *val; 190fb88707dSOliver Upton 191fb88707dSOliver Upton if (!test_bit(KVM_ARCH_FLAG_SMCCC_FILTER_CONFIGURED, &kvm->arch.flags)) 192fb88707dSOliver Upton return KVM_SMCCC_FILTER_HANDLE; 193fb88707dSOliver Upton 194fb88707dSOliver Upton /* 195fb88707dSOliver Upton * But where's the error handling, you say? 196fb88707dSOliver Upton * 197fb88707dSOliver Upton * mt_find() returns NULL if no entry was found, which just so happens 198fb88707dSOliver Upton * to match KVM_SMCCC_FILTER_HANDLE. 199fb88707dSOliver Upton */ 200fb88707dSOliver Upton val = mt_find(&kvm->arch.smccc_filter, &idx, idx); 201fb88707dSOliver Upton return xa_to_value(val); 202fb88707dSOliver Upton } 203fb88707dSOliver Upton 204a8308b3fSOliver Upton static u8 kvm_smccc_get_action(struct kvm_vcpu *vcpu, u32 func_id) 205a8308b3fSOliver Upton { 206fb88707dSOliver Upton /* 207fb88707dSOliver Upton * Intervening actions in the SMCCC filter take precedence over the 208fb88707dSOliver Upton * pseudo-firmware register bitmaps. 209fb88707dSOliver Upton */ 210fb88707dSOliver Upton u8 action = kvm_smccc_filter_get_action(vcpu->kvm, func_id); 211fb88707dSOliver Upton if (action != KVM_SMCCC_FILTER_HANDLE) 212fb88707dSOliver Upton return action; 213fb88707dSOliver Upton 214a8308b3fSOliver Upton if (kvm_smccc_test_fw_bmap(vcpu, func_id) || 215a8308b3fSOliver Upton kvm_smccc_default_allowed(func_id)) 216a8308b3fSOliver Upton return KVM_SMCCC_FILTER_HANDLE; 217a8308b3fSOliver Upton 218a8308b3fSOliver Upton return KVM_SMCCC_FILTER_DENY; 219a8308b3fSOliver Upton } 220a8308b3fSOliver Upton 221d824dff1SOliver Upton static void kvm_prepare_hypercall_exit(struct kvm_vcpu *vcpu, u32 func_id) 222d824dff1SOliver Upton { 223d824dff1SOliver Upton u8 ec = ESR_ELx_EC(kvm_vcpu_get_esr(vcpu)); 224d824dff1SOliver Upton struct kvm_run *run = vcpu->run; 225*0e5c9a9dSMarc Zyngier u64 flags = 0; 226d824dff1SOliver Upton 227d824dff1SOliver Upton if (ec == ESR_ELx_EC_SMC32 || ec == ESR_ELx_EC_SMC64) 228*0e5c9a9dSMarc Zyngier flags |= KVM_HYPERCALL_EXIT_SMC; 229*0e5c9a9dSMarc Zyngier 230*0e5c9a9dSMarc Zyngier if (!kvm_vcpu_trap_il_is32bit(vcpu)) 231*0e5c9a9dSMarc Zyngier flags |= KVM_HYPERCALL_EXIT_16BIT; 232*0e5c9a9dSMarc Zyngier 233*0e5c9a9dSMarc Zyngier run->exit_reason = KVM_EXIT_HYPERCALL; 234*0e5c9a9dSMarc Zyngier run->hypercall = (typeof(run->hypercall)) { 235*0e5c9a9dSMarc Zyngier .nr = func_id, 236*0e5c9a9dSMarc Zyngier .flags = flags, 237*0e5c9a9dSMarc Zyngier }; 238d824dff1SOliver Upton } 239d824dff1SOliver Upton 240aac94968SOliver Upton int kvm_smccc_call_handler(struct kvm_vcpu *vcpu) 2419ed24f4bSMarc Zyngier { 242428fd678SRaghavendra Rao Ananta struct kvm_smccc_features *smccc_feat = &vcpu->kvm->arch.smccc_feat; 2439ed24f4bSMarc Zyngier u32 func_id = smccc_get_function(vcpu); 244923961a7SWill Deacon u64 val[4] = {SMCCC_RET_NOT_SUPPORTED}; 2459ed24f4bSMarc Zyngier u32 feature; 246a8308b3fSOliver Upton u8 action; 2479ed24f4bSMarc Zyngier gpa_t gpa; 2489ed24f4bSMarc Zyngier 249a8308b3fSOliver Upton action = kvm_smccc_get_action(vcpu, func_id); 250a8308b3fSOliver Upton switch (action) { 251a8308b3fSOliver Upton case KVM_SMCCC_FILTER_HANDLE: 252a8308b3fSOliver Upton break; 253a8308b3fSOliver Upton case KVM_SMCCC_FILTER_DENY: 25405714cabSRaghavendra Rao Ananta goto out; 255d824dff1SOliver Upton case KVM_SMCCC_FILTER_FWD_TO_USER: 256d824dff1SOliver Upton kvm_prepare_hypercall_exit(vcpu, func_id); 257d824dff1SOliver Upton return 0; 258a8308b3fSOliver Upton default: 259a8308b3fSOliver Upton WARN_RATELIMIT(1, "Unhandled SMCCC filter action: %d\n", action); 260a8308b3fSOliver Upton goto out; 261a8308b3fSOliver Upton } 26205714cabSRaghavendra Rao Ananta 2639ed24f4bSMarc Zyngier switch (func_id) { 2649ed24f4bSMarc Zyngier case ARM_SMCCC_VERSION_FUNC_ID: 265923961a7SWill Deacon val[0] = ARM_SMCCC_VERSION_1_1; 2669ed24f4bSMarc Zyngier break; 2679ed24f4bSMarc Zyngier case ARM_SMCCC_ARCH_FEATURES_FUNC_ID: 2689ed24f4bSMarc Zyngier feature = smccc_get_arg1(vcpu); 2699ed24f4bSMarc Zyngier switch (feature) { 2709ed24f4bSMarc Zyngier case ARM_SMCCC_ARCH_WORKAROUND_1: 271d4647f0aSWill Deacon switch (arm64_get_spectre_v2_state()) { 272d4647f0aSWill Deacon case SPECTRE_VULNERABLE: 2739ed24f4bSMarc Zyngier break; 274d4647f0aSWill Deacon case SPECTRE_MITIGATED: 275923961a7SWill Deacon val[0] = SMCCC_RET_SUCCESS; 2769ed24f4bSMarc Zyngier break; 277d4647f0aSWill Deacon case SPECTRE_UNAFFECTED: 278923961a7SWill Deacon val[0] = SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED; 2799ed24f4bSMarc Zyngier break; 2809ed24f4bSMarc Zyngier } 2819ed24f4bSMarc Zyngier break; 2829ed24f4bSMarc Zyngier case ARM_SMCCC_ARCH_WORKAROUND_2: 283d63d975aSMarc Zyngier switch (arm64_get_spectre_v4_state()) { 284d63d975aSMarc Zyngier case SPECTRE_VULNERABLE: 2859ed24f4bSMarc Zyngier break; 286d63d975aSMarc Zyngier case SPECTRE_MITIGATED: 287d63d975aSMarc Zyngier /* 288d63d975aSMarc Zyngier * SSBS everywhere: Indicate no firmware 289d63d975aSMarc Zyngier * support, as the SSBS support will be 290d63d975aSMarc Zyngier * indicated to the guest and the default is 291d63d975aSMarc Zyngier * safe. 292d63d975aSMarc Zyngier * 293d63d975aSMarc Zyngier * Otherwise, expose a permanent mitigation 294d63d975aSMarc Zyngier * to the guest, and hide SSBS so that the 295d63d975aSMarc Zyngier * guest stays protected. 296d63d975aSMarc Zyngier */ 297d63d975aSMarc Zyngier if (cpus_have_final_cap(ARM64_SSBS)) 298d63d975aSMarc Zyngier break; 299d63d975aSMarc Zyngier fallthrough; 300d63d975aSMarc Zyngier case SPECTRE_UNAFFECTED: 301923961a7SWill Deacon val[0] = SMCCC_RET_NOT_REQUIRED; 3029ed24f4bSMarc Zyngier break; 3039ed24f4bSMarc Zyngier } 3049ed24f4bSMarc Zyngier break; 305a5905d6aSJames Morse case ARM_SMCCC_ARCH_WORKAROUND_3: 306a5905d6aSJames Morse switch (arm64_get_spectre_bhb_state()) { 307a5905d6aSJames Morse case SPECTRE_VULNERABLE: 308a5905d6aSJames Morse break; 309a5905d6aSJames Morse case SPECTRE_MITIGATED: 310a5905d6aSJames Morse val[0] = SMCCC_RET_SUCCESS; 311a5905d6aSJames Morse break; 312a5905d6aSJames Morse case SPECTRE_UNAFFECTED: 313a5905d6aSJames Morse val[0] = SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED; 314a5905d6aSJames Morse break; 315a5905d6aSJames Morse } 316a5905d6aSJames Morse break; 3179ed24f4bSMarc Zyngier case ARM_SMCCC_HV_PV_TIME_FEATURES: 318428fd678SRaghavendra Rao Ananta if (test_bit(KVM_REG_ARM_STD_HYP_BIT_PV_TIME, 319428fd678SRaghavendra Rao Ananta &smccc_feat->std_hyp_bmap)) 320923961a7SWill Deacon val[0] = SMCCC_RET_SUCCESS; 3219ed24f4bSMarc Zyngier break; 3229ed24f4bSMarc Zyngier } 3239ed24f4bSMarc Zyngier break; 3249ed24f4bSMarc Zyngier case ARM_SMCCC_HV_PV_TIME_FEATURES: 325923961a7SWill Deacon val[0] = kvm_hypercall_pv_features(vcpu); 3269ed24f4bSMarc Zyngier break; 3279ed24f4bSMarc Zyngier case ARM_SMCCC_HV_PV_TIME_ST: 3289ed24f4bSMarc Zyngier gpa = kvm_init_stolen_time(vcpu); 329cecafc0aSYu Zhang if (gpa != INVALID_GPA) 330923961a7SWill Deacon val[0] = gpa; 331923961a7SWill Deacon break; 332923961a7SWill Deacon case ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID: 333923961a7SWill Deacon val[0] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0; 334923961a7SWill Deacon val[1] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1; 335923961a7SWill Deacon val[2] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2; 336923961a7SWill Deacon val[3] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3; 337923961a7SWill Deacon break; 338923961a7SWill Deacon case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID: 339b22216e1SRaghavendra Rao Ananta val[0] = smccc_feat->vendor_hyp_bmap; 3403bf72569SJianyong Wu break; 3413bf72569SJianyong Wu case ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID: 3423bf72569SJianyong Wu kvm_ptp_get_time(vcpu, val); 3439ed24f4bSMarc Zyngier break; 344a8e190cdSArd Biesheuvel case ARM_SMCCC_TRNG_VERSION: 345a8e190cdSArd Biesheuvel case ARM_SMCCC_TRNG_FEATURES: 346a8e190cdSArd Biesheuvel case ARM_SMCCC_TRNG_GET_UUID: 347a8e190cdSArd Biesheuvel case ARM_SMCCC_TRNG_RND32: 348a8e190cdSArd Biesheuvel case ARM_SMCCC_TRNG_RND64: 349a8e190cdSArd Biesheuvel return kvm_trng_call(vcpu); 3509ed24f4bSMarc Zyngier default: 3519ed24f4bSMarc Zyngier return kvm_psci_call(vcpu); 3529ed24f4bSMarc Zyngier } 3539ed24f4bSMarc Zyngier 35405714cabSRaghavendra Rao Ananta out: 355923961a7SWill Deacon smccc_set_retval(vcpu, val[0], val[1], val[2], val[3]); 3569ed24f4bSMarc Zyngier return 1; 3579ed24f4bSMarc Zyngier } 35885fbe08eSRaghavendra Rao Ananta 35985fbe08eSRaghavendra Rao Ananta static const u64 kvm_arm_fw_reg_ids[] = { 36085fbe08eSRaghavendra Rao Ananta KVM_REG_ARM_PSCI_VERSION, 36185fbe08eSRaghavendra Rao Ananta KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1, 36285fbe08eSRaghavendra Rao Ananta KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2, 36385fbe08eSRaghavendra Rao Ananta KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3, 36405714cabSRaghavendra Rao Ananta KVM_REG_ARM_STD_BMAP, 365428fd678SRaghavendra Rao Ananta KVM_REG_ARM_STD_HYP_BMAP, 366b22216e1SRaghavendra Rao Ananta KVM_REG_ARM_VENDOR_HYP_BMAP, 36785fbe08eSRaghavendra Rao Ananta }; 36885fbe08eSRaghavendra Rao Ananta 36905714cabSRaghavendra Rao Ananta void kvm_arm_init_hypercalls(struct kvm *kvm) 37005714cabSRaghavendra Rao Ananta { 37105714cabSRaghavendra Rao Ananta struct kvm_smccc_features *smccc_feat = &kvm->arch.smccc_feat; 37205714cabSRaghavendra Rao Ananta 37305714cabSRaghavendra Rao Ananta smccc_feat->std_bmap = KVM_ARM_SMCCC_STD_FEATURES; 374428fd678SRaghavendra Rao Ananta smccc_feat->std_hyp_bmap = KVM_ARM_SMCCC_STD_HYP_FEATURES; 375b22216e1SRaghavendra Rao Ananta smccc_feat->vendor_hyp_bmap = KVM_ARM_SMCCC_VENDOR_HYP_FEATURES; 376fb88707dSOliver Upton 377fb88707dSOliver Upton init_smccc_filter(kvm); 378fb88707dSOliver Upton } 379fb88707dSOliver Upton 380fb88707dSOliver Upton void kvm_arm_teardown_hypercalls(struct kvm *kvm) 381fb88707dSOliver Upton { 382fb88707dSOliver Upton mtree_destroy(&kvm->arch.smccc_filter); 38305714cabSRaghavendra Rao Ananta } 38405714cabSRaghavendra Rao Ananta 38585fbe08eSRaghavendra Rao Ananta int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu) 38685fbe08eSRaghavendra Rao Ananta { 38785fbe08eSRaghavendra Rao Ananta return ARRAY_SIZE(kvm_arm_fw_reg_ids); 38885fbe08eSRaghavendra Rao Ananta } 38985fbe08eSRaghavendra Rao Ananta 39085fbe08eSRaghavendra Rao Ananta int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) 39185fbe08eSRaghavendra Rao Ananta { 39285fbe08eSRaghavendra Rao Ananta int i; 39385fbe08eSRaghavendra Rao Ananta 39485fbe08eSRaghavendra Rao Ananta for (i = 0; i < ARRAY_SIZE(kvm_arm_fw_reg_ids); i++) { 39585fbe08eSRaghavendra Rao Ananta if (put_user(kvm_arm_fw_reg_ids[i], uindices++)) 39685fbe08eSRaghavendra Rao Ananta return -EFAULT; 39785fbe08eSRaghavendra Rao Ananta } 39885fbe08eSRaghavendra Rao Ananta 39985fbe08eSRaghavendra Rao Ananta return 0; 40085fbe08eSRaghavendra Rao Ananta } 40185fbe08eSRaghavendra Rao Ananta 40285fbe08eSRaghavendra Rao Ananta #define KVM_REG_FEATURE_LEVEL_MASK GENMASK(3, 0) 40385fbe08eSRaghavendra Rao Ananta 40485fbe08eSRaghavendra Rao Ananta /* 40585fbe08eSRaghavendra Rao Ananta * Convert the workaround level into an easy-to-compare number, where higher 40685fbe08eSRaghavendra Rao Ananta * values mean better protection. 40785fbe08eSRaghavendra Rao Ananta */ 40885fbe08eSRaghavendra Rao Ananta static int get_kernel_wa_level(u64 regid) 40985fbe08eSRaghavendra Rao Ananta { 41085fbe08eSRaghavendra Rao Ananta switch (regid) { 41185fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1: 41285fbe08eSRaghavendra Rao Ananta switch (arm64_get_spectre_v2_state()) { 41385fbe08eSRaghavendra Rao Ananta case SPECTRE_VULNERABLE: 41485fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL; 41585fbe08eSRaghavendra Rao Ananta case SPECTRE_MITIGATED: 41685fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL; 41785fbe08eSRaghavendra Rao Ananta case SPECTRE_UNAFFECTED: 41885fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED; 41985fbe08eSRaghavendra Rao Ananta } 42085fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL; 42185fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2: 42285fbe08eSRaghavendra Rao Ananta switch (arm64_get_spectre_v4_state()) { 42385fbe08eSRaghavendra Rao Ananta case SPECTRE_MITIGATED: 42485fbe08eSRaghavendra Rao Ananta /* 42585fbe08eSRaghavendra Rao Ananta * As for the hypercall discovery, we pretend we 42685fbe08eSRaghavendra Rao Ananta * don't have any FW mitigation if SSBS is there at 42785fbe08eSRaghavendra Rao Ananta * all times. 42885fbe08eSRaghavendra Rao Ananta */ 42985fbe08eSRaghavendra Rao Ananta if (cpus_have_final_cap(ARM64_SSBS)) 43085fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL; 43185fbe08eSRaghavendra Rao Ananta fallthrough; 43285fbe08eSRaghavendra Rao Ananta case SPECTRE_UNAFFECTED: 43385fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED; 43485fbe08eSRaghavendra Rao Ananta case SPECTRE_VULNERABLE: 43585fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL; 43685fbe08eSRaghavendra Rao Ananta } 43785fbe08eSRaghavendra Rao Ananta break; 43885fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3: 43985fbe08eSRaghavendra Rao Ananta switch (arm64_get_spectre_bhb_state()) { 44085fbe08eSRaghavendra Rao Ananta case SPECTRE_VULNERABLE: 44185fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL; 44285fbe08eSRaghavendra Rao Ananta case SPECTRE_MITIGATED: 44385fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_AVAIL; 44485fbe08eSRaghavendra Rao Ananta case SPECTRE_UNAFFECTED: 44585fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_REQUIRED; 44685fbe08eSRaghavendra Rao Ananta } 44785fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL; 44885fbe08eSRaghavendra Rao Ananta } 44985fbe08eSRaghavendra Rao Ananta 45085fbe08eSRaghavendra Rao Ananta return -EINVAL; 45185fbe08eSRaghavendra Rao Ananta } 45285fbe08eSRaghavendra Rao Ananta 45385fbe08eSRaghavendra Rao Ananta int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) 45485fbe08eSRaghavendra Rao Ananta { 45505714cabSRaghavendra Rao Ananta struct kvm_smccc_features *smccc_feat = &vcpu->kvm->arch.smccc_feat; 45685fbe08eSRaghavendra Rao Ananta void __user *uaddr = (void __user *)(long)reg->addr; 45785fbe08eSRaghavendra Rao Ananta u64 val; 45885fbe08eSRaghavendra Rao Ananta 45985fbe08eSRaghavendra Rao Ananta switch (reg->id) { 46085fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_PSCI_VERSION: 46185fbe08eSRaghavendra Rao Ananta val = kvm_psci_version(vcpu); 46285fbe08eSRaghavendra Rao Ananta break; 46385fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1: 46485fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2: 46585fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3: 46685fbe08eSRaghavendra Rao Ananta val = get_kernel_wa_level(reg->id) & KVM_REG_FEATURE_LEVEL_MASK; 46785fbe08eSRaghavendra Rao Ananta break; 46805714cabSRaghavendra Rao Ananta case KVM_REG_ARM_STD_BMAP: 46905714cabSRaghavendra Rao Ananta val = READ_ONCE(smccc_feat->std_bmap); 47005714cabSRaghavendra Rao Ananta break; 471428fd678SRaghavendra Rao Ananta case KVM_REG_ARM_STD_HYP_BMAP: 472428fd678SRaghavendra Rao Ananta val = READ_ONCE(smccc_feat->std_hyp_bmap); 473428fd678SRaghavendra Rao Ananta break; 474b22216e1SRaghavendra Rao Ananta case KVM_REG_ARM_VENDOR_HYP_BMAP: 475b22216e1SRaghavendra Rao Ananta val = READ_ONCE(smccc_feat->vendor_hyp_bmap); 476b22216e1SRaghavendra Rao Ananta break; 47785fbe08eSRaghavendra Rao Ananta default: 47885fbe08eSRaghavendra Rao Ananta return -ENOENT; 47985fbe08eSRaghavendra Rao Ananta } 48085fbe08eSRaghavendra Rao Ananta 48185fbe08eSRaghavendra Rao Ananta if (copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id))) 48285fbe08eSRaghavendra Rao Ananta return -EFAULT; 48385fbe08eSRaghavendra Rao Ananta 48485fbe08eSRaghavendra Rao Ananta return 0; 48585fbe08eSRaghavendra Rao Ananta } 48685fbe08eSRaghavendra Rao Ananta 48705714cabSRaghavendra Rao Ananta static int kvm_arm_set_fw_reg_bmap(struct kvm_vcpu *vcpu, u64 reg_id, u64 val) 48805714cabSRaghavendra Rao Ananta { 48905714cabSRaghavendra Rao Ananta int ret = 0; 49005714cabSRaghavendra Rao Ananta struct kvm *kvm = vcpu->kvm; 49105714cabSRaghavendra Rao Ananta struct kvm_smccc_features *smccc_feat = &kvm->arch.smccc_feat; 49205714cabSRaghavendra Rao Ananta unsigned long *fw_reg_bmap, fw_reg_features; 49305714cabSRaghavendra Rao Ananta 49405714cabSRaghavendra Rao Ananta switch (reg_id) { 49505714cabSRaghavendra Rao Ananta case KVM_REG_ARM_STD_BMAP: 49605714cabSRaghavendra Rao Ananta fw_reg_bmap = &smccc_feat->std_bmap; 49705714cabSRaghavendra Rao Ananta fw_reg_features = KVM_ARM_SMCCC_STD_FEATURES; 49805714cabSRaghavendra Rao Ananta break; 499428fd678SRaghavendra Rao Ananta case KVM_REG_ARM_STD_HYP_BMAP: 500428fd678SRaghavendra Rao Ananta fw_reg_bmap = &smccc_feat->std_hyp_bmap; 501428fd678SRaghavendra Rao Ananta fw_reg_features = KVM_ARM_SMCCC_STD_HYP_FEATURES; 502428fd678SRaghavendra Rao Ananta break; 503b22216e1SRaghavendra Rao Ananta case KVM_REG_ARM_VENDOR_HYP_BMAP: 504b22216e1SRaghavendra Rao Ananta fw_reg_bmap = &smccc_feat->vendor_hyp_bmap; 505b22216e1SRaghavendra Rao Ananta fw_reg_features = KVM_ARM_SMCCC_VENDOR_HYP_FEATURES; 506b22216e1SRaghavendra Rao Ananta break; 50705714cabSRaghavendra Rao Ananta default: 50805714cabSRaghavendra Rao Ananta return -ENOENT; 50905714cabSRaghavendra Rao Ananta } 51005714cabSRaghavendra Rao Ananta 51105714cabSRaghavendra Rao Ananta /* Check for unsupported bit */ 51205714cabSRaghavendra Rao Ananta if (val & ~fw_reg_features) 51305714cabSRaghavendra Rao Ananta return -EINVAL; 51405714cabSRaghavendra Rao Ananta 51505714cabSRaghavendra Rao Ananta mutex_lock(&kvm->lock); 51605714cabSRaghavendra Rao Ananta 517de40bb8aSOliver Upton if (kvm_vm_has_ran_once(kvm) && val != *fw_reg_bmap) { 51805714cabSRaghavendra Rao Ananta ret = -EBUSY; 51905714cabSRaghavendra Rao Ananta goto out; 52005714cabSRaghavendra Rao Ananta } 52105714cabSRaghavendra Rao Ananta 52205714cabSRaghavendra Rao Ananta WRITE_ONCE(*fw_reg_bmap, val); 52305714cabSRaghavendra Rao Ananta out: 52405714cabSRaghavendra Rao Ananta mutex_unlock(&kvm->lock); 52505714cabSRaghavendra Rao Ananta return ret; 52605714cabSRaghavendra Rao Ananta } 52705714cabSRaghavendra Rao Ananta 52885fbe08eSRaghavendra Rao Ananta int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) 52985fbe08eSRaghavendra Rao Ananta { 53085fbe08eSRaghavendra Rao Ananta void __user *uaddr = (void __user *)(long)reg->addr; 53185fbe08eSRaghavendra Rao Ananta u64 val; 53285fbe08eSRaghavendra Rao Ananta int wa_level; 53385fbe08eSRaghavendra Rao Ananta 53485fbe08eSRaghavendra Rao Ananta if (copy_from_user(&val, uaddr, KVM_REG_SIZE(reg->id))) 53585fbe08eSRaghavendra Rao Ananta return -EFAULT; 53685fbe08eSRaghavendra Rao Ananta 53785fbe08eSRaghavendra Rao Ananta switch (reg->id) { 53885fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_PSCI_VERSION: 53985fbe08eSRaghavendra Rao Ananta { 54085fbe08eSRaghavendra Rao Ananta bool wants_02; 54185fbe08eSRaghavendra Rao Ananta 54285fbe08eSRaghavendra Rao Ananta wants_02 = test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features); 54385fbe08eSRaghavendra Rao Ananta 54485fbe08eSRaghavendra Rao Ananta switch (val) { 54585fbe08eSRaghavendra Rao Ananta case KVM_ARM_PSCI_0_1: 54685fbe08eSRaghavendra Rao Ananta if (wants_02) 54785fbe08eSRaghavendra Rao Ananta return -EINVAL; 54885fbe08eSRaghavendra Rao Ananta vcpu->kvm->arch.psci_version = val; 54985fbe08eSRaghavendra Rao Ananta return 0; 55085fbe08eSRaghavendra Rao Ananta case KVM_ARM_PSCI_0_2: 55185fbe08eSRaghavendra Rao Ananta case KVM_ARM_PSCI_1_0: 55285fbe08eSRaghavendra Rao Ananta case KVM_ARM_PSCI_1_1: 55385fbe08eSRaghavendra Rao Ananta if (!wants_02) 55485fbe08eSRaghavendra Rao Ananta return -EINVAL; 55585fbe08eSRaghavendra Rao Ananta vcpu->kvm->arch.psci_version = val; 55685fbe08eSRaghavendra Rao Ananta return 0; 55785fbe08eSRaghavendra Rao Ananta } 55885fbe08eSRaghavendra Rao Ananta break; 55985fbe08eSRaghavendra Rao Ananta } 56085fbe08eSRaghavendra Rao Ananta 56185fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1: 56285fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3: 56385fbe08eSRaghavendra Rao Ananta if (val & ~KVM_REG_FEATURE_LEVEL_MASK) 56485fbe08eSRaghavendra Rao Ananta return -EINVAL; 56585fbe08eSRaghavendra Rao Ananta 56685fbe08eSRaghavendra Rao Ananta if (get_kernel_wa_level(reg->id) < val) 56785fbe08eSRaghavendra Rao Ananta return -EINVAL; 56885fbe08eSRaghavendra Rao Ananta 56985fbe08eSRaghavendra Rao Ananta return 0; 57085fbe08eSRaghavendra Rao Ananta 57185fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2: 57285fbe08eSRaghavendra Rao Ananta if (val & ~(KVM_REG_FEATURE_LEVEL_MASK | 57385fbe08eSRaghavendra Rao Ananta KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED)) 57485fbe08eSRaghavendra Rao Ananta return -EINVAL; 57585fbe08eSRaghavendra Rao Ananta 57685fbe08eSRaghavendra Rao Ananta /* The enabled bit must not be set unless the level is AVAIL. */ 57785fbe08eSRaghavendra Rao Ananta if ((val & KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED) && 57885fbe08eSRaghavendra Rao Ananta (val & KVM_REG_FEATURE_LEVEL_MASK) != KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL) 57985fbe08eSRaghavendra Rao Ananta return -EINVAL; 58085fbe08eSRaghavendra Rao Ananta 58185fbe08eSRaghavendra Rao Ananta /* 58285fbe08eSRaghavendra Rao Ananta * Map all the possible incoming states to the only two we 58385fbe08eSRaghavendra Rao Ananta * really want to deal with. 58485fbe08eSRaghavendra Rao Ananta */ 58585fbe08eSRaghavendra Rao Ananta switch (val & KVM_REG_FEATURE_LEVEL_MASK) { 58685fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL: 58785fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN: 58885fbe08eSRaghavendra Rao Ananta wa_level = KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL; 58985fbe08eSRaghavendra Rao Ananta break; 59085fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL: 59185fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED: 59285fbe08eSRaghavendra Rao Ananta wa_level = KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED; 59385fbe08eSRaghavendra Rao Ananta break; 59485fbe08eSRaghavendra Rao Ananta default: 59585fbe08eSRaghavendra Rao Ananta return -EINVAL; 59685fbe08eSRaghavendra Rao Ananta } 59785fbe08eSRaghavendra Rao Ananta 59885fbe08eSRaghavendra Rao Ananta /* 59985fbe08eSRaghavendra Rao Ananta * We can deal with NOT_AVAIL on NOT_REQUIRED, but not the 60085fbe08eSRaghavendra Rao Ananta * other way around. 60185fbe08eSRaghavendra Rao Ananta */ 60285fbe08eSRaghavendra Rao Ananta if (get_kernel_wa_level(reg->id) < wa_level) 60385fbe08eSRaghavendra Rao Ananta return -EINVAL; 60485fbe08eSRaghavendra Rao Ananta 60585fbe08eSRaghavendra Rao Ananta return 0; 60605714cabSRaghavendra Rao Ananta case KVM_REG_ARM_STD_BMAP: 607428fd678SRaghavendra Rao Ananta case KVM_REG_ARM_STD_HYP_BMAP: 608b22216e1SRaghavendra Rao Ananta case KVM_REG_ARM_VENDOR_HYP_BMAP: 60905714cabSRaghavendra Rao Ananta return kvm_arm_set_fw_reg_bmap(vcpu, reg->id, val); 61085fbe08eSRaghavendra Rao Ananta default: 61185fbe08eSRaghavendra Rao Ananta return -ENOENT; 61285fbe08eSRaghavendra Rao Ananta } 61385fbe08eSRaghavendra Rao Ananta 61485fbe08eSRaghavendra Rao Ananta return -EINVAL; 61585fbe08eSRaghavendra Rao Ananta } 616821d935cSOliver Upton 617821d935cSOliver Upton int kvm_vm_smccc_has_attr(struct kvm *kvm, struct kvm_device_attr *attr) 618821d935cSOliver Upton { 619821d935cSOliver Upton switch (attr->attr) { 620821d935cSOliver Upton case KVM_ARM_VM_SMCCC_FILTER: 621821d935cSOliver Upton return 0; 622821d935cSOliver Upton default: 623821d935cSOliver Upton return -ENXIO; 624821d935cSOliver Upton } 625821d935cSOliver Upton } 626821d935cSOliver Upton 627821d935cSOliver Upton int kvm_vm_smccc_set_attr(struct kvm *kvm, struct kvm_device_attr *attr) 628821d935cSOliver Upton { 629821d935cSOliver Upton void __user *uaddr = (void __user *)attr->addr; 630821d935cSOliver Upton 631821d935cSOliver Upton switch (attr->attr) { 632821d935cSOliver Upton case KVM_ARM_VM_SMCCC_FILTER: 633821d935cSOliver Upton return kvm_smccc_set_filter(kvm, uaddr); 634821d935cSOliver Upton default: 635821d935cSOliver Upton return -ENXIO; 636821d935cSOliver Upton } 637821d935cSOliver Upton } 638