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: 502b4825a8SMarc Zyngier cycles = systime_snapshot.cycles - vcpu->kvm->arch.timer_data.poffset; 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 1245a23ad65SOliver Upton #define SMC32_ARCH_RANGE_BEGIN ARM_SMCCC_VERSION_FUNC_ID 1255a23ad65SOliver Upton #define SMC32_ARCH_RANGE_END ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ 126fb88707dSOliver Upton ARM_SMCCC_SMC_32, \ 127fb88707dSOliver Upton 0, ARM_SMCCC_FUNC_MASK) 128fb88707dSOliver Upton 1295a23ad65SOliver Upton #define SMC64_ARCH_RANGE_BEGIN ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ 1305a23ad65SOliver Upton ARM_SMCCC_SMC_64, \ 1315a23ad65SOliver Upton 0, 0) 1325a23ad65SOliver Upton #define SMC64_ARCH_RANGE_END ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ 1335a23ad65SOliver Upton ARM_SMCCC_SMC_64, \ 1345a23ad65SOliver Upton 0, ARM_SMCCC_FUNC_MASK) 1355a23ad65SOliver Upton 136fb88707dSOliver Upton static void init_smccc_filter(struct kvm *kvm) 137fb88707dSOliver Upton { 138fb88707dSOliver Upton int r; 139fb88707dSOliver Upton 140fb88707dSOliver Upton mt_init(&kvm->arch.smccc_filter); 141fb88707dSOliver Upton 142fb88707dSOliver Upton /* 143fb88707dSOliver Upton * Prevent userspace from handling any SMCCC calls in the architecture 144fb88707dSOliver Upton * range, avoiding the risk of misrepresenting Spectre mitigation status 145fb88707dSOliver Upton * to the guest. 146fb88707dSOliver Upton */ 147fb88707dSOliver Upton r = mtree_insert_range(&kvm->arch.smccc_filter, 1485a23ad65SOliver Upton SMC32_ARCH_RANGE_BEGIN, SMC32_ARCH_RANGE_END, 149fb88707dSOliver Upton xa_mk_value(KVM_SMCCC_FILTER_HANDLE), 150fb88707dSOliver Upton GFP_KERNEL_ACCOUNT); 151fb88707dSOliver Upton WARN_ON_ONCE(r); 1525a23ad65SOliver Upton 1535a23ad65SOliver Upton r = mtree_insert_range(&kvm->arch.smccc_filter, 1545a23ad65SOliver Upton SMC64_ARCH_RANGE_BEGIN, SMC64_ARCH_RANGE_END, 1555a23ad65SOliver Upton xa_mk_value(KVM_SMCCC_FILTER_HANDLE), 1565a23ad65SOliver Upton GFP_KERNEL_ACCOUNT); 1575a23ad65SOliver Upton WARN_ON_ONCE(r); 1585a23ad65SOliver Upton 159fb88707dSOliver Upton } 160fb88707dSOliver Upton 161821d935cSOliver Upton static int kvm_smccc_set_filter(struct kvm *kvm, struct kvm_smccc_filter __user *uaddr) 162821d935cSOliver Upton { 163821d935cSOliver Upton const void *zero_page = page_to_virt(ZERO_PAGE(0)); 164821d935cSOliver Upton struct kvm_smccc_filter filter; 165821d935cSOliver Upton u32 start, end; 166821d935cSOliver Upton int r; 167821d935cSOliver Upton 168821d935cSOliver Upton if (copy_from_user(&filter, uaddr, sizeof(filter))) 169821d935cSOliver Upton return -EFAULT; 170821d935cSOliver Upton 171821d935cSOliver Upton if (memcmp(filter.pad, zero_page, sizeof(filter.pad))) 172821d935cSOliver Upton return -EINVAL; 173821d935cSOliver Upton 174821d935cSOliver Upton start = filter.base; 175821d935cSOliver Upton end = start + filter.nr_functions - 1; 176821d935cSOliver Upton 177821d935cSOliver Upton if (end < start || filter.action >= NR_SMCCC_FILTER_ACTIONS) 178821d935cSOliver Upton return -EINVAL; 179821d935cSOliver Upton 180*6dcf7316SMarc Zyngier mutex_lock(&kvm->arch.config_lock); 181821d935cSOliver Upton 182821d935cSOliver Upton if (kvm_vm_has_ran_once(kvm)) { 183821d935cSOliver Upton r = -EBUSY; 184821d935cSOliver Upton goto out_unlock; 185821d935cSOliver Upton } 186821d935cSOliver Upton 187821d935cSOliver Upton r = mtree_insert_range(&kvm->arch.smccc_filter, start, end, 188821d935cSOliver Upton xa_mk_value(filter.action), GFP_KERNEL_ACCOUNT); 189821d935cSOliver Upton if (r) 190821d935cSOliver Upton goto out_unlock; 191821d935cSOliver Upton 192821d935cSOliver Upton set_bit(KVM_ARCH_FLAG_SMCCC_FILTER_CONFIGURED, &kvm->arch.flags); 193821d935cSOliver Upton 194821d935cSOliver Upton out_unlock: 195*6dcf7316SMarc Zyngier mutex_unlock(&kvm->arch.config_lock); 196821d935cSOliver Upton return r; 197821d935cSOliver Upton } 198821d935cSOliver Upton 199fb88707dSOliver Upton static u8 kvm_smccc_filter_get_action(struct kvm *kvm, u32 func_id) 200fb88707dSOliver Upton { 201fb88707dSOliver Upton unsigned long idx = func_id; 202fb88707dSOliver Upton void *val; 203fb88707dSOliver Upton 204fb88707dSOliver Upton if (!test_bit(KVM_ARCH_FLAG_SMCCC_FILTER_CONFIGURED, &kvm->arch.flags)) 205fb88707dSOliver Upton return KVM_SMCCC_FILTER_HANDLE; 206fb88707dSOliver Upton 207fb88707dSOliver Upton /* 208fb88707dSOliver Upton * But where's the error handling, you say? 209fb88707dSOliver Upton * 210fb88707dSOliver Upton * mt_find() returns NULL if no entry was found, which just so happens 211fb88707dSOliver Upton * to match KVM_SMCCC_FILTER_HANDLE. 212fb88707dSOliver Upton */ 213fb88707dSOliver Upton val = mt_find(&kvm->arch.smccc_filter, &idx, idx); 214fb88707dSOliver Upton return xa_to_value(val); 215fb88707dSOliver Upton } 216fb88707dSOliver Upton 217a8308b3fSOliver Upton static u8 kvm_smccc_get_action(struct kvm_vcpu *vcpu, u32 func_id) 218a8308b3fSOliver Upton { 219fb88707dSOliver Upton /* 220fb88707dSOliver Upton * Intervening actions in the SMCCC filter take precedence over the 221fb88707dSOliver Upton * pseudo-firmware register bitmaps. 222fb88707dSOliver Upton */ 223fb88707dSOliver Upton u8 action = kvm_smccc_filter_get_action(vcpu->kvm, func_id); 224fb88707dSOliver Upton if (action != KVM_SMCCC_FILTER_HANDLE) 225fb88707dSOliver Upton return action; 226fb88707dSOliver Upton 227a8308b3fSOliver Upton if (kvm_smccc_test_fw_bmap(vcpu, func_id) || 228a8308b3fSOliver Upton kvm_smccc_default_allowed(func_id)) 229a8308b3fSOliver Upton return KVM_SMCCC_FILTER_HANDLE; 230a8308b3fSOliver Upton 231a8308b3fSOliver Upton return KVM_SMCCC_FILTER_DENY; 232a8308b3fSOliver Upton } 233a8308b3fSOliver Upton 234d824dff1SOliver Upton static void kvm_prepare_hypercall_exit(struct kvm_vcpu *vcpu, u32 func_id) 235d824dff1SOliver Upton { 236d824dff1SOliver Upton u8 ec = ESR_ELx_EC(kvm_vcpu_get_esr(vcpu)); 237d824dff1SOliver Upton struct kvm_run *run = vcpu->run; 2380e5c9a9dSMarc Zyngier u64 flags = 0; 239d824dff1SOliver Upton 240d824dff1SOliver Upton if (ec == ESR_ELx_EC_SMC32 || ec == ESR_ELx_EC_SMC64) 2410e5c9a9dSMarc Zyngier flags |= KVM_HYPERCALL_EXIT_SMC; 2420e5c9a9dSMarc Zyngier 2430e5c9a9dSMarc Zyngier if (!kvm_vcpu_trap_il_is32bit(vcpu)) 2440e5c9a9dSMarc Zyngier flags |= KVM_HYPERCALL_EXIT_16BIT; 2450e5c9a9dSMarc Zyngier 2460e5c9a9dSMarc Zyngier run->exit_reason = KVM_EXIT_HYPERCALL; 2470e5c9a9dSMarc Zyngier run->hypercall = (typeof(run->hypercall)) { 2480e5c9a9dSMarc Zyngier .nr = func_id, 2490e5c9a9dSMarc Zyngier .flags = flags, 2500e5c9a9dSMarc Zyngier }; 251d824dff1SOliver Upton } 252d824dff1SOliver Upton 253aac94968SOliver Upton int kvm_smccc_call_handler(struct kvm_vcpu *vcpu) 2549ed24f4bSMarc Zyngier { 255428fd678SRaghavendra Rao Ananta struct kvm_smccc_features *smccc_feat = &vcpu->kvm->arch.smccc_feat; 2569ed24f4bSMarc Zyngier u32 func_id = smccc_get_function(vcpu); 257923961a7SWill Deacon u64 val[4] = {SMCCC_RET_NOT_SUPPORTED}; 2589ed24f4bSMarc Zyngier u32 feature; 259a8308b3fSOliver Upton u8 action; 2609ed24f4bSMarc Zyngier gpa_t gpa; 2619ed24f4bSMarc Zyngier 262a8308b3fSOliver Upton action = kvm_smccc_get_action(vcpu, func_id); 263a8308b3fSOliver Upton switch (action) { 264a8308b3fSOliver Upton case KVM_SMCCC_FILTER_HANDLE: 265a8308b3fSOliver Upton break; 266a8308b3fSOliver Upton case KVM_SMCCC_FILTER_DENY: 26705714cabSRaghavendra Rao Ananta goto out; 268d824dff1SOliver Upton case KVM_SMCCC_FILTER_FWD_TO_USER: 269d824dff1SOliver Upton kvm_prepare_hypercall_exit(vcpu, func_id); 270d824dff1SOliver Upton return 0; 271a8308b3fSOliver Upton default: 272a8308b3fSOliver Upton WARN_RATELIMIT(1, "Unhandled SMCCC filter action: %d\n", action); 273a8308b3fSOliver Upton goto out; 274a8308b3fSOliver Upton } 27505714cabSRaghavendra Rao Ananta 2769ed24f4bSMarc Zyngier switch (func_id) { 2779ed24f4bSMarc Zyngier case ARM_SMCCC_VERSION_FUNC_ID: 278923961a7SWill Deacon val[0] = ARM_SMCCC_VERSION_1_1; 2799ed24f4bSMarc Zyngier break; 2809ed24f4bSMarc Zyngier case ARM_SMCCC_ARCH_FEATURES_FUNC_ID: 2819ed24f4bSMarc Zyngier feature = smccc_get_arg1(vcpu); 2829ed24f4bSMarc Zyngier switch (feature) { 2839ed24f4bSMarc Zyngier case ARM_SMCCC_ARCH_WORKAROUND_1: 284d4647f0aSWill Deacon switch (arm64_get_spectre_v2_state()) { 285d4647f0aSWill Deacon case SPECTRE_VULNERABLE: 2869ed24f4bSMarc Zyngier break; 287d4647f0aSWill Deacon case SPECTRE_MITIGATED: 288923961a7SWill Deacon val[0] = SMCCC_RET_SUCCESS; 2899ed24f4bSMarc Zyngier break; 290d4647f0aSWill Deacon case SPECTRE_UNAFFECTED: 291923961a7SWill Deacon val[0] = SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED; 2929ed24f4bSMarc Zyngier break; 2939ed24f4bSMarc Zyngier } 2949ed24f4bSMarc Zyngier break; 2959ed24f4bSMarc Zyngier case ARM_SMCCC_ARCH_WORKAROUND_2: 296d63d975aSMarc Zyngier switch (arm64_get_spectre_v4_state()) { 297d63d975aSMarc Zyngier case SPECTRE_VULNERABLE: 2989ed24f4bSMarc Zyngier break; 299d63d975aSMarc Zyngier case SPECTRE_MITIGATED: 300d63d975aSMarc Zyngier /* 301d63d975aSMarc Zyngier * SSBS everywhere: Indicate no firmware 302d63d975aSMarc Zyngier * support, as the SSBS support will be 303d63d975aSMarc Zyngier * indicated to the guest and the default is 304d63d975aSMarc Zyngier * safe. 305d63d975aSMarc Zyngier * 306d63d975aSMarc Zyngier * Otherwise, expose a permanent mitigation 307d63d975aSMarc Zyngier * to the guest, and hide SSBS so that the 308d63d975aSMarc Zyngier * guest stays protected. 309d63d975aSMarc Zyngier */ 310d63d975aSMarc Zyngier if (cpus_have_final_cap(ARM64_SSBS)) 311d63d975aSMarc Zyngier break; 312d63d975aSMarc Zyngier fallthrough; 313d63d975aSMarc Zyngier case SPECTRE_UNAFFECTED: 314923961a7SWill Deacon val[0] = SMCCC_RET_NOT_REQUIRED; 3159ed24f4bSMarc Zyngier break; 3169ed24f4bSMarc Zyngier } 3179ed24f4bSMarc Zyngier break; 318a5905d6aSJames Morse case ARM_SMCCC_ARCH_WORKAROUND_3: 319a5905d6aSJames Morse switch (arm64_get_spectre_bhb_state()) { 320a5905d6aSJames Morse case SPECTRE_VULNERABLE: 321a5905d6aSJames Morse break; 322a5905d6aSJames Morse case SPECTRE_MITIGATED: 323a5905d6aSJames Morse val[0] = SMCCC_RET_SUCCESS; 324a5905d6aSJames Morse break; 325a5905d6aSJames Morse case SPECTRE_UNAFFECTED: 326a5905d6aSJames Morse val[0] = SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED; 327a5905d6aSJames Morse break; 328a5905d6aSJames Morse } 329a5905d6aSJames Morse break; 3309ed24f4bSMarc Zyngier case ARM_SMCCC_HV_PV_TIME_FEATURES: 331428fd678SRaghavendra Rao Ananta if (test_bit(KVM_REG_ARM_STD_HYP_BIT_PV_TIME, 332428fd678SRaghavendra Rao Ananta &smccc_feat->std_hyp_bmap)) 333923961a7SWill Deacon val[0] = SMCCC_RET_SUCCESS; 3349ed24f4bSMarc Zyngier break; 3359ed24f4bSMarc Zyngier } 3369ed24f4bSMarc Zyngier break; 3379ed24f4bSMarc Zyngier case ARM_SMCCC_HV_PV_TIME_FEATURES: 338923961a7SWill Deacon val[0] = kvm_hypercall_pv_features(vcpu); 3399ed24f4bSMarc Zyngier break; 3409ed24f4bSMarc Zyngier case ARM_SMCCC_HV_PV_TIME_ST: 3419ed24f4bSMarc Zyngier gpa = kvm_init_stolen_time(vcpu); 342cecafc0aSYu Zhang if (gpa != INVALID_GPA) 343923961a7SWill Deacon val[0] = gpa; 344923961a7SWill Deacon break; 345923961a7SWill Deacon case ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID: 346923961a7SWill Deacon val[0] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0; 347923961a7SWill Deacon val[1] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1; 348923961a7SWill Deacon val[2] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2; 349923961a7SWill Deacon val[3] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3; 350923961a7SWill Deacon break; 351923961a7SWill Deacon case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID: 352b22216e1SRaghavendra Rao Ananta val[0] = smccc_feat->vendor_hyp_bmap; 3533bf72569SJianyong Wu break; 3543bf72569SJianyong Wu case ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID: 3553bf72569SJianyong Wu kvm_ptp_get_time(vcpu, val); 3569ed24f4bSMarc Zyngier break; 357a8e190cdSArd Biesheuvel case ARM_SMCCC_TRNG_VERSION: 358a8e190cdSArd Biesheuvel case ARM_SMCCC_TRNG_FEATURES: 359a8e190cdSArd Biesheuvel case ARM_SMCCC_TRNG_GET_UUID: 360a8e190cdSArd Biesheuvel case ARM_SMCCC_TRNG_RND32: 361a8e190cdSArd Biesheuvel case ARM_SMCCC_TRNG_RND64: 362a8e190cdSArd Biesheuvel return kvm_trng_call(vcpu); 3639ed24f4bSMarc Zyngier default: 3649ed24f4bSMarc Zyngier return kvm_psci_call(vcpu); 3659ed24f4bSMarc Zyngier } 3669ed24f4bSMarc Zyngier 36705714cabSRaghavendra Rao Ananta out: 368923961a7SWill Deacon smccc_set_retval(vcpu, val[0], val[1], val[2], val[3]); 3699ed24f4bSMarc Zyngier return 1; 3709ed24f4bSMarc Zyngier } 37185fbe08eSRaghavendra Rao Ananta 37285fbe08eSRaghavendra Rao Ananta static const u64 kvm_arm_fw_reg_ids[] = { 37385fbe08eSRaghavendra Rao Ananta KVM_REG_ARM_PSCI_VERSION, 37485fbe08eSRaghavendra Rao Ananta KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1, 37585fbe08eSRaghavendra Rao Ananta KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2, 37685fbe08eSRaghavendra Rao Ananta KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3, 37705714cabSRaghavendra Rao Ananta KVM_REG_ARM_STD_BMAP, 378428fd678SRaghavendra Rao Ananta KVM_REG_ARM_STD_HYP_BMAP, 379b22216e1SRaghavendra Rao Ananta KVM_REG_ARM_VENDOR_HYP_BMAP, 38085fbe08eSRaghavendra Rao Ananta }; 38185fbe08eSRaghavendra Rao Ananta 38205714cabSRaghavendra Rao Ananta void kvm_arm_init_hypercalls(struct kvm *kvm) 38305714cabSRaghavendra Rao Ananta { 38405714cabSRaghavendra Rao Ananta struct kvm_smccc_features *smccc_feat = &kvm->arch.smccc_feat; 38505714cabSRaghavendra Rao Ananta 38605714cabSRaghavendra Rao Ananta smccc_feat->std_bmap = KVM_ARM_SMCCC_STD_FEATURES; 387428fd678SRaghavendra Rao Ananta smccc_feat->std_hyp_bmap = KVM_ARM_SMCCC_STD_HYP_FEATURES; 388b22216e1SRaghavendra Rao Ananta smccc_feat->vendor_hyp_bmap = KVM_ARM_SMCCC_VENDOR_HYP_FEATURES; 389fb88707dSOliver Upton 390fb88707dSOliver Upton init_smccc_filter(kvm); 391fb88707dSOliver Upton } 392fb88707dSOliver Upton 393fb88707dSOliver Upton void kvm_arm_teardown_hypercalls(struct kvm *kvm) 394fb88707dSOliver Upton { 395fb88707dSOliver Upton mtree_destroy(&kvm->arch.smccc_filter); 39605714cabSRaghavendra Rao Ananta } 39705714cabSRaghavendra Rao Ananta 39885fbe08eSRaghavendra Rao Ananta int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu) 39985fbe08eSRaghavendra Rao Ananta { 40085fbe08eSRaghavendra Rao Ananta return ARRAY_SIZE(kvm_arm_fw_reg_ids); 40185fbe08eSRaghavendra Rao Ananta } 40285fbe08eSRaghavendra Rao Ananta 40385fbe08eSRaghavendra Rao Ananta int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) 40485fbe08eSRaghavendra Rao Ananta { 40585fbe08eSRaghavendra Rao Ananta int i; 40685fbe08eSRaghavendra Rao Ananta 40785fbe08eSRaghavendra Rao Ananta for (i = 0; i < ARRAY_SIZE(kvm_arm_fw_reg_ids); i++) { 40885fbe08eSRaghavendra Rao Ananta if (put_user(kvm_arm_fw_reg_ids[i], uindices++)) 40985fbe08eSRaghavendra Rao Ananta return -EFAULT; 41085fbe08eSRaghavendra Rao Ananta } 41185fbe08eSRaghavendra Rao Ananta 41285fbe08eSRaghavendra Rao Ananta return 0; 41385fbe08eSRaghavendra Rao Ananta } 41485fbe08eSRaghavendra Rao Ananta 41585fbe08eSRaghavendra Rao Ananta #define KVM_REG_FEATURE_LEVEL_MASK GENMASK(3, 0) 41685fbe08eSRaghavendra Rao Ananta 41785fbe08eSRaghavendra Rao Ananta /* 41885fbe08eSRaghavendra Rao Ananta * Convert the workaround level into an easy-to-compare number, where higher 41985fbe08eSRaghavendra Rao Ananta * values mean better protection. 42085fbe08eSRaghavendra Rao Ananta */ 42185fbe08eSRaghavendra Rao Ananta static int get_kernel_wa_level(u64 regid) 42285fbe08eSRaghavendra Rao Ananta { 42385fbe08eSRaghavendra Rao Ananta switch (regid) { 42485fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1: 42585fbe08eSRaghavendra Rao Ananta switch (arm64_get_spectre_v2_state()) { 42685fbe08eSRaghavendra Rao Ananta case SPECTRE_VULNERABLE: 42785fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL; 42885fbe08eSRaghavendra Rao Ananta case SPECTRE_MITIGATED: 42985fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL; 43085fbe08eSRaghavendra Rao Ananta case SPECTRE_UNAFFECTED: 43185fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED; 43285fbe08eSRaghavendra Rao Ananta } 43385fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL; 43485fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2: 43585fbe08eSRaghavendra Rao Ananta switch (arm64_get_spectre_v4_state()) { 43685fbe08eSRaghavendra Rao Ananta case SPECTRE_MITIGATED: 43785fbe08eSRaghavendra Rao Ananta /* 43885fbe08eSRaghavendra Rao Ananta * As for the hypercall discovery, we pretend we 43985fbe08eSRaghavendra Rao Ananta * don't have any FW mitigation if SSBS is there at 44085fbe08eSRaghavendra Rao Ananta * all times. 44185fbe08eSRaghavendra Rao Ananta */ 44285fbe08eSRaghavendra Rao Ananta if (cpus_have_final_cap(ARM64_SSBS)) 44385fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL; 44485fbe08eSRaghavendra Rao Ananta fallthrough; 44585fbe08eSRaghavendra Rao Ananta case SPECTRE_UNAFFECTED: 44685fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED; 44785fbe08eSRaghavendra Rao Ananta case SPECTRE_VULNERABLE: 44885fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL; 44985fbe08eSRaghavendra Rao Ananta } 45085fbe08eSRaghavendra Rao Ananta break; 45185fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3: 45285fbe08eSRaghavendra Rao Ananta switch (arm64_get_spectre_bhb_state()) { 45385fbe08eSRaghavendra Rao Ananta case SPECTRE_VULNERABLE: 45485fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL; 45585fbe08eSRaghavendra Rao Ananta case SPECTRE_MITIGATED: 45685fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_AVAIL; 45785fbe08eSRaghavendra Rao Ananta case SPECTRE_UNAFFECTED: 45885fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_REQUIRED; 45985fbe08eSRaghavendra Rao Ananta } 46085fbe08eSRaghavendra Rao Ananta return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL; 46185fbe08eSRaghavendra Rao Ananta } 46285fbe08eSRaghavendra Rao Ananta 46385fbe08eSRaghavendra Rao Ananta return -EINVAL; 46485fbe08eSRaghavendra Rao Ananta } 46585fbe08eSRaghavendra Rao Ananta 46685fbe08eSRaghavendra Rao Ananta int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) 46785fbe08eSRaghavendra Rao Ananta { 46805714cabSRaghavendra Rao Ananta struct kvm_smccc_features *smccc_feat = &vcpu->kvm->arch.smccc_feat; 46985fbe08eSRaghavendra Rao Ananta void __user *uaddr = (void __user *)(long)reg->addr; 47085fbe08eSRaghavendra Rao Ananta u64 val; 47185fbe08eSRaghavendra Rao Ananta 47285fbe08eSRaghavendra Rao Ananta switch (reg->id) { 47385fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_PSCI_VERSION: 47485fbe08eSRaghavendra Rao Ananta val = kvm_psci_version(vcpu); 47585fbe08eSRaghavendra Rao Ananta break; 47685fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1: 47785fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2: 47885fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3: 47985fbe08eSRaghavendra Rao Ananta val = get_kernel_wa_level(reg->id) & KVM_REG_FEATURE_LEVEL_MASK; 48085fbe08eSRaghavendra Rao Ananta break; 48105714cabSRaghavendra Rao Ananta case KVM_REG_ARM_STD_BMAP: 48205714cabSRaghavendra Rao Ananta val = READ_ONCE(smccc_feat->std_bmap); 48305714cabSRaghavendra Rao Ananta break; 484428fd678SRaghavendra Rao Ananta case KVM_REG_ARM_STD_HYP_BMAP: 485428fd678SRaghavendra Rao Ananta val = READ_ONCE(smccc_feat->std_hyp_bmap); 486428fd678SRaghavendra Rao Ananta break; 487b22216e1SRaghavendra Rao Ananta case KVM_REG_ARM_VENDOR_HYP_BMAP: 488b22216e1SRaghavendra Rao Ananta val = READ_ONCE(smccc_feat->vendor_hyp_bmap); 489b22216e1SRaghavendra Rao Ananta break; 49085fbe08eSRaghavendra Rao Ananta default: 49185fbe08eSRaghavendra Rao Ananta return -ENOENT; 49285fbe08eSRaghavendra Rao Ananta } 49385fbe08eSRaghavendra Rao Ananta 49485fbe08eSRaghavendra Rao Ananta if (copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id))) 49585fbe08eSRaghavendra Rao Ananta return -EFAULT; 49685fbe08eSRaghavendra Rao Ananta 49785fbe08eSRaghavendra Rao Ananta return 0; 49885fbe08eSRaghavendra Rao Ananta } 49985fbe08eSRaghavendra Rao Ananta 50005714cabSRaghavendra Rao Ananta static int kvm_arm_set_fw_reg_bmap(struct kvm_vcpu *vcpu, u64 reg_id, u64 val) 50105714cabSRaghavendra Rao Ananta { 50205714cabSRaghavendra Rao Ananta int ret = 0; 50305714cabSRaghavendra Rao Ananta struct kvm *kvm = vcpu->kvm; 50405714cabSRaghavendra Rao Ananta struct kvm_smccc_features *smccc_feat = &kvm->arch.smccc_feat; 50505714cabSRaghavendra Rao Ananta unsigned long *fw_reg_bmap, fw_reg_features; 50605714cabSRaghavendra Rao Ananta 50705714cabSRaghavendra Rao Ananta switch (reg_id) { 50805714cabSRaghavendra Rao Ananta case KVM_REG_ARM_STD_BMAP: 50905714cabSRaghavendra Rao Ananta fw_reg_bmap = &smccc_feat->std_bmap; 51005714cabSRaghavendra Rao Ananta fw_reg_features = KVM_ARM_SMCCC_STD_FEATURES; 51105714cabSRaghavendra Rao Ananta break; 512428fd678SRaghavendra Rao Ananta case KVM_REG_ARM_STD_HYP_BMAP: 513428fd678SRaghavendra Rao Ananta fw_reg_bmap = &smccc_feat->std_hyp_bmap; 514428fd678SRaghavendra Rao Ananta fw_reg_features = KVM_ARM_SMCCC_STD_HYP_FEATURES; 515428fd678SRaghavendra Rao Ananta break; 516b22216e1SRaghavendra Rao Ananta case KVM_REG_ARM_VENDOR_HYP_BMAP: 517b22216e1SRaghavendra Rao Ananta fw_reg_bmap = &smccc_feat->vendor_hyp_bmap; 518b22216e1SRaghavendra Rao Ananta fw_reg_features = KVM_ARM_SMCCC_VENDOR_HYP_FEATURES; 519b22216e1SRaghavendra Rao Ananta break; 52005714cabSRaghavendra Rao Ananta default: 52105714cabSRaghavendra Rao Ananta return -ENOENT; 52205714cabSRaghavendra Rao Ananta } 52305714cabSRaghavendra Rao Ananta 52405714cabSRaghavendra Rao Ananta /* Check for unsupported bit */ 52505714cabSRaghavendra Rao Ananta if (val & ~fw_reg_features) 52605714cabSRaghavendra Rao Ananta return -EINVAL; 52705714cabSRaghavendra Rao Ananta 5284bba7f7dSOliver Upton mutex_lock(&kvm->arch.config_lock); 52905714cabSRaghavendra Rao Ananta 530de40bb8aSOliver Upton if (kvm_vm_has_ran_once(kvm) && val != *fw_reg_bmap) { 53105714cabSRaghavendra Rao Ananta ret = -EBUSY; 53205714cabSRaghavendra Rao Ananta goto out; 53305714cabSRaghavendra Rao Ananta } 53405714cabSRaghavendra Rao Ananta 53505714cabSRaghavendra Rao Ananta WRITE_ONCE(*fw_reg_bmap, val); 53605714cabSRaghavendra Rao Ananta out: 5374bba7f7dSOliver Upton mutex_unlock(&kvm->arch.config_lock); 53805714cabSRaghavendra Rao Ananta return ret; 53905714cabSRaghavendra Rao Ananta } 54005714cabSRaghavendra Rao Ananta 54185fbe08eSRaghavendra Rao Ananta int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) 54285fbe08eSRaghavendra Rao Ananta { 54385fbe08eSRaghavendra Rao Ananta void __user *uaddr = (void __user *)(long)reg->addr; 54485fbe08eSRaghavendra Rao Ananta u64 val; 54585fbe08eSRaghavendra Rao Ananta int wa_level; 54685fbe08eSRaghavendra Rao Ananta 54785fbe08eSRaghavendra Rao Ananta if (copy_from_user(&val, uaddr, KVM_REG_SIZE(reg->id))) 54885fbe08eSRaghavendra Rao Ananta return -EFAULT; 54985fbe08eSRaghavendra Rao Ananta 55085fbe08eSRaghavendra Rao Ananta switch (reg->id) { 55185fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_PSCI_VERSION: 55285fbe08eSRaghavendra Rao Ananta { 55385fbe08eSRaghavendra Rao Ananta bool wants_02; 55485fbe08eSRaghavendra Rao Ananta 55585fbe08eSRaghavendra Rao Ananta wants_02 = test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features); 55685fbe08eSRaghavendra Rao Ananta 55785fbe08eSRaghavendra Rao Ananta switch (val) { 55885fbe08eSRaghavendra Rao Ananta case KVM_ARM_PSCI_0_1: 55985fbe08eSRaghavendra Rao Ananta if (wants_02) 56085fbe08eSRaghavendra Rao Ananta return -EINVAL; 56185fbe08eSRaghavendra Rao Ananta vcpu->kvm->arch.psci_version = val; 56285fbe08eSRaghavendra Rao Ananta return 0; 56385fbe08eSRaghavendra Rao Ananta case KVM_ARM_PSCI_0_2: 56485fbe08eSRaghavendra Rao Ananta case KVM_ARM_PSCI_1_0: 56585fbe08eSRaghavendra Rao Ananta case KVM_ARM_PSCI_1_1: 56685fbe08eSRaghavendra Rao Ananta if (!wants_02) 56785fbe08eSRaghavendra Rao Ananta return -EINVAL; 56885fbe08eSRaghavendra Rao Ananta vcpu->kvm->arch.psci_version = val; 56985fbe08eSRaghavendra Rao Ananta return 0; 57085fbe08eSRaghavendra Rao Ananta } 57185fbe08eSRaghavendra Rao Ananta break; 57285fbe08eSRaghavendra Rao Ananta } 57385fbe08eSRaghavendra Rao Ananta 57485fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1: 57585fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3: 57685fbe08eSRaghavendra Rao Ananta if (val & ~KVM_REG_FEATURE_LEVEL_MASK) 57785fbe08eSRaghavendra Rao Ananta return -EINVAL; 57885fbe08eSRaghavendra Rao Ananta 57985fbe08eSRaghavendra Rao Ananta if (get_kernel_wa_level(reg->id) < val) 58085fbe08eSRaghavendra Rao Ananta return -EINVAL; 58185fbe08eSRaghavendra Rao Ananta 58285fbe08eSRaghavendra Rao Ananta return 0; 58385fbe08eSRaghavendra Rao Ananta 58485fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2: 58585fbe08eSRaghavendra Rao Ananta if (val & ~(KVM_REG_FEATURE_LEVEL_MASK | 58685fbe08eSRaghavendra Rao Ananta KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED)) 58785fbe08eSRaghavendra Rao Ananta return -EINVAL; 58885fbe08eSRaghavendra Rao Ananta 58985fbe08eSRaghavendra Rao Ananta /* The enabled bit must not be set unless the level is AVAIL. */ 59085fbe08eSRaghavendra Rao Ananta if ((val & KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED) && 59185fbe08eSRaghavendra Rao Ananta (val & KVM_REG_FEATURE_LEVEL_MASK) != KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL) 59285fbe08eSRaghavendra Rao Ananta return -EINVAL; 59385fbe08eSRaghavendra Rao Ananta 59485fbe08eSRaghavendra Rao Ananta /* 59585fbe08eSRaghavendra Rao Ananta * Map all the possible incoming states to the only two we 59685fbe08eSRaghavendra Rao Ananta * really want to deal with. 59785fbe08eSRaghavendra Rao Ananta */ 59885fbe08eSRaghavendra Rao Ananta switch (val & KVM_REG_FEATURE_LEVEL_MASK) { 59985fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL: 60085fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN: 60185fbe08eSRaghavendra Rao Ananta wa_level = KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL; 60285fbe08eSRaghavendra Rao Ananta break; 60385fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL: 60485fbe08eSRaghavendra Rao Ananta case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED: 60585fbe08eSRaghavendra Rao Ananta wa_level = KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED; 60685fbe08eSRaghavendra Rao Ananta break; 60785fbe08eSRaghavendra Rao Ananta default: 60885fbe08eSRaghavendra Rao Ananta return -EINVAL; 60985fbe08eSRaghavendra Rao Ananta } 61085fbe08eSRaghavendra Rao Ananta 61185fbe08eSRaghavendra Rao Ananta /* 61285fbe08eSRaghavendra Rao Ananta * We can deal with NOT_AVAIL on NOT_REQUIRED, but not the 61385fbe08eSRaghavendra Rao Ananta * other way around. 61485fbe08eSRaghavendra Rao Ananta */ 61585fbe08eSRaghavendra Rao Ananta if (get_kernel_wa_level(reg->id) < wa_level) 61685fbe08eSRaghavendra Rao Ananta return -EINVAL; 61785fbe08eSRaghavendra Rao Ananta 61885fbe08eSRaghavendra Rao Ananta return 0; 61905714cabSRaghavendra Rao Ananta case KVM_REG_ARM_STD_BMAP: 620428fd678SRaghavendra Rao Ananta case KVM_REG_ARM_STD_HYP_BMAP: 621b22216e1SRaghavendra Rao Ananta case KVM_REG_ARM_VENDOR_HYP_BMAP: 62205714cabSRaghavendra Rao Ananta return kvm_arm_set_fw_reg_bmap(vcpu, reg->id, val); 62385fbe08eSRaghavendra Rao Ananta default: 62485fbe08eSRaghavendra Rao Ananta return -ENOENT; 62585fbe08eSRaghavendra Rao Ananta } 62685fbe08eSRaghavendra Rao Ananta 62785fbe08eSRaghavendra Rao Ananta return -EINVAL; 62885fbe08eSRaghavendra Rao Ananta } 629821d935cSOliver Upton 630821d935cSOliver Upton int kvm_vm_smccc_has_attr(struct kvm *kvm, struct kvm_device_attr *attr) 631821d935cSOliver Upton { 632821d935cSOliver Upton switch (attr->attr) { 633821d935cSOliver Upton case KVM_ARM_VM_SMCCC_FILTER: 634821d935cSOliver Upton return 0; 635821d935cSOliver Upton default: 636821d935cSOliver Upton return -ENXIO; 637821d935cSOliver Upton } 638821d935cSOliver Upton } 639821d935cSOliver Upton 640821d935cSOliver Upton int kvm_vm_smccc_set_attr(struct kvm *kvm, struct kvm_device_attr *attr) 641821d935cSOliver Upton { 642821d935cSOliver Upton void __user *uaddr = (void __user *)attr->addr; 643821d935cSOliver Upton 644821d935cSOliver Upton switch (attr->attr) { 645821d935cSOliver Upton case KVM_ARM_VM_SMCCC_FILTER: 646821d935cSOliver Upton return kvm_smccc_set_filter(kvm, uaddr); 647821d935cSOliver Upton default: 648821d935cSOliver Upton return -ENXIO; 649821d935cSOliver Upton } 650821d935cSOliver Upton } 651