1*9ed24f4bSMarc Zyngier // SPDX-License-Identifier: GPL-2.0 2*9ed24f4bSMarc Zyngier // Copyright (C) 2019 Arm Ltd. 3*9ed24f4bSMarc Zyngier 4*9ed24f4bSMarc Zyngier #include <linux/arm-smccc.h> 5*9ed24f4bSMarc Zyngier #include <linux/kvm_host.h> 6*9ed24f4bSMarc Zyngier 7*9ed24f4bSMarc Zyngier #include <asm/kvm_emulate.h> 8*9ed24f4bSMarc Zyngier 9*9ed24f4bSMarc Zyngier #include <kvm/arm_hypercalls.h> 10*9ed24f4bSMarc Zyngier #include <kvm/arm_psci.h> 11*9ed24f4bSMarc Zyngier 12*9ed24f4bSMarc Zyngier int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) 13*9ed24f4bSMarc Zyngier { 14*9ed24f4bSMarc Zyngier u32 func_id = smccc_get_function(vcpu); 15*9ed24f4bSMarc Zyngier long val = SMCCC_RET_NOT_SUPPORTED; 16*9ed24f4bSMarc Zyngier u32 feature; 17*9ed24f4bSMarc Zyngier gpa_t gpa; 18*9ed24f4bSMarc Zyngier 19*9ed24f4bSMarc Zyngier switch (func_id) { 20*9ed24f4bSMarc Zyngier case ARM_SMCCC_VERSION_FUNC_ID: 21*9ed24f4bSMarc Zyngier val = ARM_SMCCC_VERSION_1_1; 22*9ed24f4bSMarc Zyngier break; 23*9ed24f4bSMarc Zyngier case ARM_SMCCC_ARCH_FEATURES_FUNC_ID: 24*9ed24f4bSMarc Zyngier feature = smccc_get_arg1(vcpu); 25*9ed24f4bSMarc Zyngier switch (feature) { 26*9ed24f4bSMarc Zyngier case ARM_SMCCC_ARCH_WORKAROUND_1: 27*9ed24f4bSMarc Zyngier switch (kvm_arm_harden_branch_predictor()) { 28*9ed24f4bSMarc Zyngier case KVM_BP_HARDEN_UNKNOWN: 29*9ed24f4bSMarc Zyngier break; 30*9ed24f4bSMarc Zyngier case KVM_BP_HARDEN_WA_NEEDED: 31*9ed24f4bSMarc Zyngier val = SMCCC_RET_SUCCESS; 32*9ed24f4bSMarc Zyngier break; 33*9ed24f4bSMarc Zyngier case KVM_BP_HARDEN_NOT_REQUIRED: 34*9ed24f4bSMarc Zyngier val = SMCCC_RET_NOT_REQUIRED; 35*9ed24f4bSMarc Zyngier break; 36*9ed24f4bSMarc Zyngier } 37*9ed24f4bSMarc Zyngier break; 38*9ed24f4bSMarc Zyngier case ARM_SMCCC_ARCH_WORKAROUND_2: 39*9ed24f4bSMarc Zyngier switch (kvm_arm_have_ssbd()) { 40*9ed24f4bSMarc Zyngier case KVM_SSBD_FORCE_DISABLE: 41*9ed24f4bSMarc Zyngier case KVM_SSBD_UNKNOWN: 42*9ed24f4bSMarc Zyngier break; 43*9ed24f4bSMarc Zyngier case KVM_SSBD_KERNEL: 44*9ed24f4bSMarc Zyngier val = SMCCC_RET_SUCCESS; 45*9ed24f4bSMarc Zyngier break; 46*9ed24f4bSMarc Zyngier case KVM_SSBD_FORCE_ENABLE: 47*9ed24f4bSMarc Zyngier case KVM_SSBD_MITIGATED: 48*9ed24f4bSMarc Zyngier val = SMCCC_RET_NOT_REQUIRED; 49*9ed24f4bSMarc Zyngier break; 50*9ed24f4bSMarc Zyngier } 51*9ed24f4bSMarc Zyngier break; 52*9ed24f4bSMarc Zyngier case ARM_SMCCC_HV_PV_TIME_FEATURES: 53*9ed24f4bSMarc Zyngier val = SMCCC_RET_SUCCESS; 54*9ed24f4bSMarc Zyngier break; 55*9ed24f4bSMarc Zyngier } 56*9ed24f4bSMarc Zyngier break; 57*9ed24f4bSMarc Zyngier case ARM_SMCCC_HV_PV_TIME_FEATURES: 58*9ed24f4bSMarc Zyngier val = kvm_hypercall_pv_features(vcpu); 59*9ed24f4bSMarc Zyngier break; 60*9ed24f4bSMarc Zyngier case ARM_SMCCC_HV_PV_TIME_ST: 61*9ed24f4bSMarc Zyngier gpa = kvm_init_stolen_time(vcpu); 62*9ed24f4bSMarc Zyngier if (gpa != GPA_INVALID) 63*9ed24f4bSMarc Zyngier val = gpa; 64*9ed24f4bSMarc Zyngier break; 65*9ed24f4bSMarc Zyngier default: 66*9ed24f4bSMarc Zyngier return kvm_psci_call(vcpu); 67*9ed24f4bSMarc Zyngier } 68*9ed24f4bSMarc Zyngier 69*9ed24f4bSMarc Zyngier smccc_set_retval(vcpu, val, 0, 0, 0); 70*9ed24f4bSMarc Zyngier return 1; 71*9ed24f4bSMarc Zyngier } 72