1*c62a7685SAtish Patra // SPDX-License-Identifier: GPL-2.0 2*c62a7685SAtish Patra /* 3*c62a7685SAtish Patra * Copyright (c) 2021 Western Digital Corporation or its affiliates. 4*c62a7685SAtish Patra * 5*c62a7685SAtish Patra * Authors: 6*c62a7685SAtish Patra * Atish Patra <atish.patra@wdc.com> 7*c62a7685SAtish Patra */ 8*c62a7685SAtish Patra 9*c62a7685SAtish Patra #include <linux/errno.h> 10*c62a7685SAtish Patra #include <linux/err.h> 11*c62a7685SAtish Patra #include <linux/kvm_host.h> 12*c62a7685SAtish Patra #include <asm/csr.h> 13*c62a7685SAtish Patra #include <asm/sbi.h> 14*c62a7685SAtish Patra #include <asm/kvm_vcpu_timer.h> 15*c62a7685SAtish Patra #include <asm/kvm_vcpu_sbi.h> 16*c62a7685SAtish Patra 17*c62a7685SAtish Patra static int kvm_sbi_ext_base_handler(struct kvm_vcpu *vcpu, struct kvm_run *run, 18*c62a7685SAtish Patra unsigned long *out_val, 19*c62a7685SAtish Patra struct kvm_cpu_trap *trap, bool *exit) 20*c62a7685SAtish Patra { 21*c62a7685SAtish Patra int ret = 0; 22*c62a7685SAtish Patra struct kvm_cpu_context *cp = &vcpu->arch.guest_context; 23*c62a7685SAtish Patra struct sbiret ecall_ret; 24*c62a7685SAtish Patra 25*c62a7685SAtish Patra switch (cp->a6) { 26*c62a7685SAtish Patra case SBI_EXT_BASE_GET_SPEC_VERSION: 27*c62a7685SAtish Patra *out_val = (KVM_SBI_VERSION_MAJOR << 28*c62a7685SAtish Patra SBI_SPEC_VERSION_MAJOR_SHIFT) | 29*c62a7685SAtish Patra KVM_SBI_VERSION_MINOR; 30*c62a7685SAtish Patra break; 31*c62a7685SAtish Patra case SBI_EXT_BASE_GET_IMP_ID: 32*c62a7685SAtish Patra *out_val = KVM_SBI_IMPID; 33*c62a7685SAtish Patra break; 34*c62a7685SAtish Patra case SBI_EXT_BASE_GET_IMP_VERSION: 35*c62a7685SAtish Patra *out_val = 0; 36*c62a7685SAtish Patra break; 37*c62a7685SAtish Patra case SBI_EXT_BASE_PROBE_EXT: 38*c62a7685SAtish Patra if ((cp->a0 >= SBI_EXT_EXPERIMENTAL_START && 39*c62a7685SAtish Patra cp->a0 <= SBI_EXT_EXPERIMENTAL_END) || 40*c62a7685SAtish Patra (cp->a0 >= SBI_EXT_VENDOR_START && 41*c62a7685SAtish Patra cp->a0 <= SBI_EXT_VENDOR_END)) { 42*c62a7685SAtish Patra /* 43*c62a7685SAtish Patra * For experimental/vendor extensions 44*c62a7685SAtish Patra * forward it to the userspace 45*c62a7685SAtish Patra */ 46*c62a7685SAtish Patra kvm_riscv_vcpu_sbi_forward(vcpu, run); 47*c62a7685SAtish Patra *exit = true; 48*c62a7685SAtish Patra } else 49*c62a7685SAtish Patra *out_val = kvm_vcpu_sbi_find_ext(cp->a0) ? 1 : 0; 50*c62a7685SAtish Patra break; 51*c62a7685SAtish Patra case SBI_EXT_BASE_GET_MVENDORID: 52*c62a7685SAtish Patra case SBI_EXT_BASE_GET_MARCHID: 53*c62a7685SAtish Patra case SBI_EXT_BASE_GET_MIMPID: 54*c62a7685SAtish Patra ecall_ret = sbi_ecall(SBI_EXT_BASE, cp->a6, 0, 0, 0, 0, 0, 0); 55*c62a7685SAtish Patra if (!ecall_ret.error) 56*c62a7685SAtish Patra *out_val = ecall_ret.value; 57*c62a7685SAtish Patra /*TODO: We are unnecessarily converting the error twice */ 58*c62a7685SAtish Patra ret = sbi_err_map_linux_errno(ecall_ret.error); 59*c62a7685SAtish Patra break; 60*c62a7685SAtish Patra default: 61*c62a7685SAtish Patra ret = -EOPNOTSUPP; 62*c62a7685SAtish Patra break; 63*c62a7685SAtish Patra } 64*c62a7685SAtish Patra 65*c62a7685SAtish Patra return ret; 66*c62a7685SAtish Patra } 67*c62a7685SAtish Patra 68*c62a7685SAtish Patra const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_base = { 69*c62a7685SAtish Patra .extid_start = SBI_EXT_BASE, 70*c62a7685SAtish Patra .extid_end = SBI_EXT_BASE, 71*c62a7685SAtish Patra .handler = kvm_sbi_ext_base_handler, 72*c62a7685SAtish Patra }; 73