18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// Copyright (C) 2019 Arm Ltd. 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include <linux/arm-smccc.h> 58c2ecf20Sopenharmony_ci#include <linux/kvm_host.h> 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <asm/kvm_emulate.h> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <kvm/arm_hypercalls.h> 108c2ecf20Sopenharmony_ci#include <kvm/arm_psci.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ciint kvm_hvc_call_handler(struct kvm_vcpu *vcpu) 138c2ecf20Sopenharmony_ci{ 148c2ecf20Sopenharmony_ci u32 func_id = smccc_get_function(vcpu); 158c2ecf20Sopenharmony_ci long val = SMCCC_RET_NOT_SUPPORTED; 168c2ecf20Sopenharmony_ci u32 feature; 178c2ecf20Sopenharmony_ci gpa_t gpa; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci switch (func_id) { 208c2ecf20Sopenharmony_ci case ARM_SMCCC_VERSION_FUNC_ID: 218c2ecf20Sopenharmony_ci val = ARM_SMCCC_VERSION_1_1; 228c2ecf20Sopenharmony_ci break; 238c2ecf20Sopenharmony_ci case ARM_SMCCC_ARCH_FEATURES_FUNC_ID: 248c2ecf20Sopenharmony_ci feature = smccc_get_arg1(vcpu); 258c2ecf20Sopenharmony_ci switch (feature) { 268c2ecf20Sopenharmony_ci case ARM_SMCCC_ARCH_WORKAROUND_1: 278c2ecf20Sopenharmony_ci switch (arm64_get_spectre_v2_state()) { 288c2ecf20Sopenharmony_ci case SPECTRE_VULNERABLE: 298c2ecf20Sopenharmony_ci break; 308c2ecf20Sopenharmony_ci case SPECTRE_MITIGATED: 318c2ecf20Sopenharmony_ci val = SMCCC_RET_SUCCESS; 328c2ecf20Sopenharmony_ci break; 338c2ecf20Sopenharmony_ci case SPECTRE_UNAFFECTED: 348c2ecf20Sopenharmony_ci val = SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED; 358c2ecf20Sopenharmony_ci break; 368c2ecf20Sopenharmony_ci } 378c2ecf20Sopenharmony_ci break; 388c2ecf20Sopenharmony_ci case ARM_SMCCC_ARCH_WORKAROUND_2: 398c2ecf20Sopenharmony_ci switch (arm64_get_spectre_v4_state()) { 408c2ecf20Sopenharmony_ci case SPECTRE_VULNERABLE: 418c2ecf20Sopenharmony_ci break; 428c2ecf20Sopenharmony_ci case SPECTRE_MITIGATED: 438c2ecf20Sopenharmony_ci /* 448c2ecf20Sopenharmony_ci * SSBS everywhere: Indicate no firmware 458c2ecf20Sopenharmony_ci * support, as the SSBS support will be 468c2ecf20Sopenharmony_ci * indicated to the guest and the default is 478c2ecf20Sopenharmony_ci * safe. 488c2ecf20Sopenharmony_ci * 498c2ecf20Sopenharmony_ci * Otherwise, expose a permanent mitigation 508c2ecf20Sopenharmony_ci * to the guest, and hide SSBS so that the 518c2ecf20Sopenharmony_ci * guest stays protected. 528c2ecf20Sopenharmony_ci */ 538c2ecf20Sopenharmony_ci if (cpus_have_final_cap(ARM64_SSBS)) 548c2ecf20Sopenharmony_ci break; 558c2ecf20Sopenharmony_ci fallthrough; 568c2ecf20Sopenharmony_ci case SPECTRE_UNAFFECTED: 578c2ecf20Sopenharmony_ci val = SMCCC_RET_NOT_REQUIRED; 588c2ecf20Sopenharmony_ci break; 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci break; 618c2ecf20Sopenharmony_ci case ARM_SMCCC_ARCH_WORKAROUND_3: 628c2ecf20Sopenharmony_ci switch (arm64_get_spectre_bhb_state()) { 638c2ecf20Sopenharmony_ci case SPECTRE_VULNERABLE: 648c2ecf20Sopenharmony_ci break; 658c2ecf20Sopenharmony_ci case SPECTRE_MITIGATED: 668c2ecf20Sopenharmony_ci val = SMCCC_RET_SUCCESS; 678c2ecf20Sopenharmony_ci break; 688c2ecf20Sopenharmony_ci case SPECTRE_UNAFFECTED: 698c2ecf20Sopenharmony_ci val = SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED; 708c2ecf20Sopenharmony_ci break; 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci break; 738c2ecf20Sopenharmony_ci case ARM_SMCCC_HV_PV_TIME_FEATURES: 748c2ecf20Sopenharmony_ci val = SMCCC_RET_SUCCESS; 758c2ecf20Sopenharmony_ci break; 768c2ecf20Sopenharmony_ci } 778c2ecf20Sopenharmony_ci break; 788c2ecf20Sopenharmony_ci case ARM_SMCCC_HV_PV_TIME_FEATURES: 798c2ecf20Sopenharmony_ci val = kvm_hypercall_pv_features(vcpu); 808c2ecf20Sopenharmony_ci break; 818c2ecf20Sopenharmony_ci case ARM_SMCCC_HV_PV_TIME_ST: 828c2ecf20Sopenharmony_ci gpa = kvm_init_stolen_time(vcpu); 838c2ecf20Sopenharmony_ci if (gpa != GPA_INVALID) 848c2ecf20Sopenharmony_ci val = gpa; 858c2ecf20Sopenharmony_ci break; 868c2ecf20Sopenharmony_ci default: 878c2ecf20Sopenharmony_ci return kvm_psci_call(vcpu); 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci smccc_set_retval(vcpu, val, 0, 0, 0); 918c2ecf20Sopenharmony_ci return 1; 928c2ecf20Sopenharmony_ci} 93