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