191654e61SYifei Jiang /* 291654e61SYifei Jiang * RISC-V implementation of KVM hooks 391654e61SYifei Jiang * 491654e61SYifei Jiang * Copyright (c) 2020 Huawei Technologies Co., Ltd 591654e61SYifei Jiang * 691654e61SYifei Jiang * This program is free software; you can redistribute it and/or modify it 791654e61SYifei Jiang * under the terms and conditions of the GNU General Public License, 891654e61SYifei Jiang * version 2 or later, as published by the Free Software Foundation. 991654e61SYifei Jiang * 1091654e61SYifei Jiang * This program is distributed in the hope it will be useful, but WITHOUT 1191654e61SYifei Jiang * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1291654e61SYifei Jiang * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 1391654e61SYifei Jiang * more details. 1491654e61SYifei Jiang * 1591654e61SYifei Jiang * You should have received a copy of the GNU General Public License along with 1691654e61SYifei Jiang * this program. If not, see <http://www.gnu.org/licenses/>. 1791654e61SYifei Jiang */ 1891654e61SYifei Jiang 1991654e61SYifei Jiang #include "qemu/osdep.h" 2091654e61SYifei Jiang #include <sys/ioctl.h> 2191654e61SYifei Jiang 2291654e61SYifei Jiang #include <linux/kvm.h> 2391654e61SYifei Jiang 2491654e61SYifei Jiang #include "qemu-common.h" 2591654e61SYifei Jiang #include "qemu/timer.h" 2691654e61SYifei Jiang #include "qemu/error-report.h" 2791654e61SYifei Jiang #include "qemu/main-loop.h" 2891654e61SYifei Jiang #include "sysemu/sysemu.h" 2991654e61SYifei Jiang #include "sysemu/kvm.h" 3091654e61SYifei Jiang #include "sysemu/kvm_int.h" 3191654e61SYifei Jiang #include "cpu.h" 3291654e61SYifei Jiang #include "trace.h" 3391654e61SYifei Jiang #include "hw/pci/pci.h" 3491654e61SYifei Jiang #include "exec/memattrs.h" 3591654e61SYifei Jiang #include "exec/address-spaces.h" 3691654e61SYifei Jiang #include "hw/boards.h" 3791654e61SYifei Jiang #include "hw/irq.h" 3891654e61SYifei Jiang #include "qemu/log.h" 3991654e61SYifei Jiang #include "hw/loader.h" 40ad40be27SYifei Jiang #include "kvm_riscv.h" 41*4eb47125SYifei Jiang #include "sbi_ecall_interface.h" 42*4eb47125SYifei Jiang #include "chardev/char-fe.h" 4391654e61SYifei Jiang 440a312b85SYifei Jiang static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type, 450a312b85SYifei Jiang uint64_t idx) 460a312b85SYifei Jiang { 470a312b85SYifei Jiang uint64_t id = KVM_REG_RISCV | type | idx; 480a312b85SYifei Jiang 490a312b85SYifei Jiang switch (riscv_cpu_mxl(env)) { 500a312b85SYifei Jiang case MXL_RV32: 510a312b85SYifei Jiang id |= KVM_REG_SIZE_U32; 520a312b85SYifei Jiang break; 530a312b85SYifei Jiang case MXL_RV64: 540a312b85SYifei Jiang id |= KVM_REG_SIZE_U64; 550a312b85SYifei Jiang break; 560a312b85SYifei Jiang default: 570a312b85SYifei Jiang g_assert_not_reached(); 580a312b85SYifei Jiang } 590a312b85SYifei Jiang return id; 600a312b85SYifei Jiang } 610a312b85SYifei Jiang 62937f0b45SYifei Jiang #define RISCV_CORE_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, \ 63937f0b45SYifei Jiang KVM_REG_RISCV_CORE_REG(name)) 64937f0b45SYifei Jiang 65937f0b45SYifei Jiang #define RISCV_CSR_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_CSR, \ 66937f0b45SYifei Jiang KVM_REG_RISCV_CSR_REG(name)) 67937f0b45SYifei Jiang 68937f0b45SYifei Jiang #define RISCV_FP_F_REG(env, idx) kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_F, idx) 69937f0b45SYifei Jiang 70937f0b45SYifei Jiang #define RISCV_FP_D_REG(env, idx) kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_D, idx) 71937f0b45SYifei Jiang 72937f0b45SYifei Jiang #define KVM_RISCV_GET_CSR(cs, env, csr, reg) \ 73937f0b45SYifei Jiang do { \ 74937f0b45SYifei Jiang int ret = kvm_get_one_reg(cs, RISCV_CSR_REG(env, csr), ®); \ 75937f0b45SYifei Jiang if (ret) { \ 76937f0b45SYifei Jiang return ret; \ 77937f0b45SYifei Jiang } \ 78937f0b45SYifei Jiang } while (0) 79937f0b45SYifei Jiang 809997cc1eSYifei Jiang #define KVM_RISCV_SET_CSR(cs, env, csr, reg) \ 819997cc1eSYifei Jiang do { \ 829997cc1eSYifei Jiang int ret = kvm_set_one_reg(cs, RISCV_CSR_REG(env, csr), ®); \ 839997cc1eSYifei Jiang if (ret) { \ 849997cc1eSYifei Jiang return ret; \ 859997cc1eSYifei Jiang } \ 869997cc1eSYifei Jiang } while (0) 879997cc1eSYifei Jiang 88937f0b45SYifei Jiang static int kvm_riscv_get_regs_core(CPUState *cs) 89937f0b45SYifei Jiang { 90937f0b45SYifei Jiang int ret = 0; 91937f0b45SYifei Jiang int i; 92937f0b45SYifei Jiang target_ulong reg; 93937f0b45SYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 94937f0b45SYifei Jiang 95937f0b45SYifei Jiang ret = kvm_get_one_reg(cs, RISCV_CORE_REG(env, regs.pc), ®); 96937f0b45SYifei Jiang if (ret) { 97937f0b45SYifei Jiang return ret; 98937f0b45SYifei Jiang } 99937f0b45SYifei Jiang env->pc = reg; 100937f0b45SYifei Jiang 101937f0b45SYifei Jiang for (i = 1; i < 32; i++) { 102937f0b45SYifei Jiang uint64_t id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, i); 103937f0b45SYifei Jiang ret = kvm_get_one_reg(cs, id, ®); 104937f0b45SYifei Jiang if (ret) { 105937f0b45SYifei Jiang return ret; 106937f0b45SYifei Jiang } 107937f0b45SYifei Jiang env->gpr[i] = reg; 108937f0b45SYifei Jiang } 109937f0b45SYifei Jiang 110937f0b45SYifei Jiang return ret; 111937f0b45SYifei Jiang } 112937f0b45SYifei Jiang 1139997cc1eSYifei Jiang static int kvm_riscv_put_regs_core(CPUState *cs) 1149997cc1eSYifei Jiang { 1159997cc1eSYifei Jiang int ret = 0; 1169997cc1eSYifei Jiang int i; 1179997cc1eSYifei Jiang target_ulong reg; 1189997cc1eSYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 1199997cc1eSYifei Jiang 1209997cc1eSYifei Jiang reg = env->pc; 1219997cc1eSYifei Jiang ret = kvm_set_one_reg(cs, RISCV_CORE_REG(env, regs.pc), ®); 1229997cc1eSYifei Jiang if (ret) { 1239997cc1eSYifei Jiang return ret; 1249997cc1eSYifei Jiang } 1259997cc1eSYifei Jiang 1269997cc1eSYifei Jiang for (i = 1; i < 32; i++) { 1279997cc1eSYifei Jiang uint64_t id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, i); 1289997cc1eSYifei Jiang reg = env->gpr[i]; 1299997cc1eSYifei Jiang ret = kvm_set_one_reg(cs, id, ®); 1309997cc1eSYifei Jiang if (ret) { 1319997cc1eSYifei Jiang return ret; 1329997cc1eSYifei Jiang } 1339997cc1eSYifei Jiang } 1349997cc1eSYifei Jiang 1359997cc1eSYifei Jiang return ret; 1369997cc1eSYifei Jiang } 1379997cc1eSYifei Jiang 138937f0b45SYifei Jiang static int kvm_riscv_get_regs_csr(CPUState *cs) 139937f0b45SYifei Jiang { 140937f0b45SYifei Jiang int ret = 0; 141937f0b45SYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 142937f0b45SYifei Jiang 143937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, sstatus, env->mstatus); 144937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, sie, env->mie); 145937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, stvec, env->stvec); 146937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, sscratch, env->sscratch); 147937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, sepc, env->sepc); 148937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, scause, env->scause); 149937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, stval, env->stval); 150937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, sip, env->mip); 151937f0b45SYifei Jiang KVM_RISCV_GET_CSR(cs, env, satp, env->satp); 152937f0b45SYifei Jiang return ret; 153937f0b45SYifei Jiang } 154937f0b45SYifei Jiang 1559997cc1eSYifei Jiang static int kvm_riscv_put_regs_csr(CPUState *cs) 1569997cc1eSYifei Jiang { 1579997cc1eSYifei Jiang int ret = 0; 1589997cc1eSYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 1599997cc1eSYifei Jiang 1609997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, sstatus, env->mstatus); 1619997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, sie, env->mie); 1629997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, stvec, env->stvec); 1639997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, sscratch, env->sscratch); 1649997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, sepc, env->sepc); 1659997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, scause, env->scause); 1669997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, stval, env->stval); 1679997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, sip, env->mip); 1689997cc1eSYifei Jiang KVM_RISCV_SET_CSR(cs, env, satp, env->satp); 1699997cc1eSYifei Jiang 1709997cc1eSYifei Jiang return ret; 1719997cc1eSYifei Jiang } 1729997cc1eSYifei Jiang 173937f0b45SYifei Jiang static int kvm_riscv_get_regs_fp(CPUState *cs) 174937f0b45SYifei Jiang { 175937f0b45SYifei Jiang int ret = 0; 176937f0b45SYifei Jiang int i; 177937f0b45SYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 178937f0b45SYifei Jiang 179937f0b45SYifei Jiang if (riscv_has_ext(env, RVD)) { 180937f0b45SYifei Jiang uint64_t reg; 181937f0b45SYifei Jiang for (i = 0; i < 32; i++) { 182937f0b45SYifei Jiang ret = kvm_get_one_reg(cs, RISCV_FP_D_REG(env, i), ®); 183937f0b45SYifei Jiang if (ret) { 184937f0b45SYifei Jiang return ret; 185937f0b45SYifei Jiang } 186937f0b45SYifei Jiang env->fpr[i] = reg; 187937f0b45SYifei Jiang } 188937f0b45SYifei Jiang return ret; 189937f0b45SYifei Jiang } 190937f0b45SYifei Jiang 191937f0b45SYifei Jiang if (riscv_has_ext(env, RVF)) { 192937f0b45SYifei Jiang uint32_t reg; 193937f0b45SYifei Jiang for (i = 0; i < 32; i++) { 194937f0b45SYifei Jiang ret = kvm_get_one_reg(cs, RISCV_FP_F_REG(env, i), ®); 195937f0b45SYifei Jiang if (ret) { 196937f0b45SYifei Jiang return ret; 197937f0b45SYifei Jiang } 198937f0b45SYifei Jiang env->fpr[i] = reg; 199937f0b45SYifei Jiang } 200937f0b45SYifei Jiang return ret; 201937f0b45SYifei Jiang } 202937f0b45SYifei Jiang 203937f0b45SYifei Jiang return ret; 204937f0b45SYifei Jiang } 205937f0b45SYifei Jiang 2069997cc1eSYifei Jiang static int kvm_riscv_put_regs_fp(CPUState *cs) 2079997cc1eSYifei Jiang { 2089997cc1eSYifei Jiang int ret = 0; 2099997cc1eSYifei Jiang int i; 2109997cc1eSYifei Jiang CPURISCVState *env = &RISCV_CPU(cs)->env; 2119997cc1eSYifei Jiang 2129997cc1eSYifei Jiang if (riscv_has_ext(env, RVD)) { 2139997cc1eSYifei Jiang uint64_t reg; 2149997cc1eSYifei Jiang for (i = 0; i < 32; i++) { 2159997cc1eSYifei Jiang reg = env->fpr[i]; 2169997cc1eSYifei Jiang ret = kvm_set_one_reg(cs, RISCV_FP_D_REG(env, i), ®); 2179997cc1eSYifei Jiang if (ret) { 2189997cc1eSYifei Jiang return ret; 2199997cc1eSYifei Jiang } 2209997cc1eSYifei Jiang } 2219997cc1eSYifei Jiang return ret; 2229997cc1eSYifei Jiang } 2239997cc1eSYifei Jiang 2249997cc1eSYifei Jiang if (riscv_has_ext(env, RVF)) { 2259997cc1eSYifei Jiang uint32_t reg; 2269997cc1eSYifei Jiang for (i = 0; i < 32; i++) { 2279997cc1eSYifei Jiang reg = env->fpr[i]; 2289997cc1eSYifei Jiang ret = kvm_set_one_reg(cs, RISCV_FP_F_REG(env, i), ®); 2299997cc1eSYifei Jiang if (ret) { 2309997cc1eSYifei Jiang return ret; 2319997cc1eSYifei Jiang } 2329997cc1eSYifei Jiang } 2339997cc1eSYifei Jiang return ret; 2349997cc1eSYifei Jiang } 2359997cc1eSYifei Jiang 2369997cc1eSYifei Jiang return ret; 2379997cc1eSYifei Jiang } 2389997cc1eSYifei Jiang 2399997cc1eSYifei Jiang 24091654e61SYifei Jiang const KVMCapabilityInfo kvm_arch_required_capabilities[] = { 24191654e61SYifei Jiang KVM_CAP_LAST_INFO 24291654e61SYifei Jiang }; 24391654e61SYifei Jiang 24491654e61SYifei Jiang int kvm_arch_get_registers(CPUState *cs) 24591654e61SYifei Jiang { 246937f0b45SYifei Jiang int ret = 0; 247937f0b45SYifei Jiang 248937f0b45SYifei Jiang ret = kvm_riscv_get_regs_core(cs); 249937f0b45SYifei Jiang if (ret) { 250937f0b45SYifei Jiang return ret; 251937f0b45SYifei Jiang } 252937f0b45SYifei Jiang 253937f0b45SYifei Jiang ret = kvm_riscv_get_regs_csr(cs); 254937f0b45SYifei Jiang if (ret) { 255937f0b45SYifei Jiang return ret; 256937f0b45SYifei Jiang } 257937f0b45SYifei Jiang 258937f0b45SYifei Jiang ret = kvm_riscv_get_regs_fp(cs); 259937f0b45SYifei Jiang if (ret) { 260937f0b45SYifei Jiang return ret; 261937f0b45SYifei Jiang } 262937f0b45SYifei Jiang 263937f0b45SYifei Jiang return ret; 26491654e61SYifei Jiang } 26591654e61SYifei Jiang 26691654e61SYifei Jiang int kvm_arch_put_registers(CPUState *cs, int level) 26791654e61SYifei Jiang { 2689997cc1eSYifei Jiang int ret = 0; 2699997cc1eSYifei Jiang 2709997cc1eSYifei Jiang ret = kvm_riscv_put_regs_core(cs); 2719997cc1eSYifei Jiang if (ret) { 2729997cc1eSYifei Jiang return ret; 2739997cc1eSYifei Jiang } 2749997cc1eSYifei Jiang 2759997cc1eSYifei Jiang ret = kvm_riscv_put_regs_csr(cs); 2769997cc1eSYifei Jiang if (ret) { 2779997cc1eSYifei Jiang return ret; 2789997cc1eSYifei Jiang } 2799997cc1eSYifei Jiang 2809997cc1eSYifei Jiang ret = kvm_riscv_put_regs_fp(cs); 2819997cc1eSYifei Jiang if (ret) { 2829997cc1eSYifei Jiang return ret; 2839997cc1eSYifei Jiang } 2849997cc1eSYifei Jiang 2859997cc1eSYifei Jiang return ret; 28691654e61SYifei Jiang } 28791654e61SYifei Jiang 28891654e61SYifei Jiang int kvm_arch_release_virq_post(int virq) 28991654e61SYifei Jiang { 29091654e61SYifei Jiang return 0; 29191654e61SYifei Jiang } 29291654e61SYifei Jiang 29391654e61SYifei Jiang int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, 29491654e61SYifei Jiang uint64_t address, uint32_t data, PCIDevice *dev) 29591654e61SYifei Jiang { 29691654e61SYifei Jiang return 0; 29791654e61SYifei Jiang } 29891654e61SYifei Jiang 29991654e61SYifei Jiang int kvm_arch_destroy_vcpu(CPUState *cs) 30091654e61SYifei Jiang { 30191654e61SYifei Jiang return 0; 30291654e61SYifei Jiang } 30391654e61SYifei Jiang 30491654e61SYifei Jiang unsigned long kvm_arch_vcpu_id(CPUState *cpu) 30591654e61SYifei Jiang { 30691654e61SYifei Jiang return cpu->cpu_index; 30791654e61SYifei Jiang } 30891654e61SYifei Jiang 30991654e61SYifei Jiang void kvm_arch_init_irq_routing(KVMState *s) 31091654e61SYifei Jiang { 31191654e61SYifei Jiang } 31291654e61SYifei Jiang 31391654e61SYifei Jiang int kvm_arch_init_vcpu(CPUState *cs) 31491654e61SYifei Jiang { 3150a312b85SYifei Jiang int ret = 0; 3160a312b85SYifei Jiang target_ulong isa; 3170a312b85SYifei Jiang RISCVCPU *cpu = RISCV_CPU(cs); 3180a312b85SYifei Jiang CPURISCVState *env = &cpu->env; 3190a312b85SYifei Jiang uint64_t id; 3200a312b85SYifei Jiang 3210a312b85SYifei Jiang id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CONFIG, 3220a312b85SYifei Jiang KVM_REG_RISCV_CONFIG_REG(isa)); 3230a312b85SYifei Jiang ret = kvm_get_one_reg(cs, id, &isa); 3240a312b85SYifei Jiang if (ret) { 3250a312b85SYifei Jiang return ret; 3260a312b85SYifei Jiang } 3270a312b85SYifei Jiang env->misa_ext = isa; 3280a312b85SYifei Jiang 3290a312b85SYifei Jiang return ret; 33091654e61SYifei Jiang } 33191654e61SYifei Jiang 33291654e61SYifei Jiang int kvm_arch_msi_data_to_gsi(uint32_t data) 33391654e61SYifei Jiang { 33491654e61SYifei Jiang abort(); 33591654e61SYifei Jiang } 33691654e61SYifei Jiang 33791654e61SYifei Jiang int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, 33891654e61SYifei Jiang int vector, PCIDevice *dev) 33991654e61SYifei Jiang { 34091654e61SYifei Jiang return 0; 34191654e61SYifei Jiang } 34291654e61SYifei Jiang 34391654e61SYifei Jiang int kvm_arch_init(MachineState *ms, KVMState *s) 34491654e61SYifei Jiang { 34591654e61SYifei Jiang return 0; 34691654e61SYifei Jiang } 34791654e61SYifei Jiang 34891654e61SYifei Jiang int kvm_arch_irqchip_create(KVMState *s) 34991654e61SYifei Jiang { 35091654e61SYifei Jiang return 0; 35191654e61SYifei Jiang } 35291654e61SYifei Jiang 35391654e61SYifei Jiang int kvm_arch_process_async_events(CPUState *cs) 35491654e61SYifei Jiang { 35591654e61SYifei Jiang return 0; 35691654e61SYifei Jiang } 35791654e61SYifei Jiang 35891654e61SYifei Jiang void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) 35991654e61SYifei Jiang { 36091654e61SYifei Jiang } 36191654e61SYifei Jiang 36291654e61SYifei Jiang MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) 36391654e61SYifei Jiang { 36491654e61SYifei Jiang return MEMTXATTRS_UNSPECIFIED; 36591654e61SYifei Jiang } 36691654e61SYifei Jiang 36791654e61SYifei Jiang bool kvm_arch_stop_on_emulation_error(CPUState *cs) 36891654e61SYifei Jiang { 36991654e61SYifei Jiang return true; 37091654e61SYifei Jiang } 37191654e61SYifei Jiang 372*4eb47125SYifei Jiang static int kvm_riscv_handle_sbi(CPUState *cs, struct kvm_run *run) 373*4eb47125SYifei Jiang { 374*4eb47125SYifei Jiang int ret = 0; 375*4eb47125SYifei Jiang unsigned char ch; 376*4eb47125SYifei Jiang switch (run->riscv_sbi.extension_id) { 377*4eb47125SYifei Jiang case SBI_EXT_0_1_CONSOLE_PUTCHAR: 378*4eb47125SYifei Jiang ch = run->riscv_sbi.args[0]; 379*4eb47125SYifei Jiang qemu_chr_fe_write(serial_hd(0)->be, &ch, sizeof(ch)); 380*4eb47125SYifei Jiang break; 381*4eb47125SYifei Jiang case SBI_EXT_0_1_CONSOLE_GETCHAR: 382*4eb47125SYifei Jiang ret = qemu_chr_fe_read_all(serial_hd(0)->be, &ch, sizeof(ch)); 383*4eb47125SYifei Jiang if (ret == sizeof(ch)) { 384*4eb47125SYifei Jiang run->riscv_sbi.args[0] = ch; 385*4eb47125SYifei Jiang } else { 386*4eb47125SYifei Jiang run->riscv_sbi.args[0] = -1; 387*4eb47125SYifei Jiang } 388*4eb47125SYifei Jiang break; 389*4eb47125SYifei Jiang default: 390*4eb47125SYifei Jiang qemu_log_mask(LOG_UNIMP, 391*4eb47125SYifei Jiang "%s: un-handled SBI EXIT, specific reasons is %lu\n", 392*4eb47125SYifei Jiang __func__, run->riscv_sbi.extension_id); 393*4eb47125SYifei Jiang ret = -1; 394*4eb47125SYifei Jiang break; 395*4eb47125SYifei Jiang } 396*4eb47125SYifei Jiang return ret; 397*4eb47125SYifei Jiang } 398*4eb47125SYifei Jiang 39991654e61SYifei Jiang int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) 40091654e61SYifei Jiang { 401*4eb47125SYifei Jiang int ret = 0; 402*4eb47125SYifei Jiang switch (run->exit_reason) { 403*4eb47125SYifei Jiang case KVM_EXIT_RISCV_SBI: 404*4eb47125SYifei Jiang ret = kvm_riscv_handle_sbi(cs, run); 405*4eb47125SYifei Jiang break; 406*4eb47125SYifei Jiang default: 407*4eb47125SYifei Jiang qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n", 408*4eb47125SYifei Jiang __func__, run->exit_reason); 409*4eb47125SYifei Jiang ret = -1; 410*4eb47125SYifei Jiang break; 411*4eb47125SYifei Jiang } 412*4eb47125SYifei Jiang return ret; 41391654e61SYifei Jiang } 41491654e61SYifei Jiang 415ad40be27SYifei Jiang void kvm_riscv_reset_vcpu(RISCVCPU *cpu) 416ad40be27SYifei Jiang { 417ad40be27SYifei Jiang CPURISCVState *env = &cpu->env; 418ad40be27SYifei Jiang 419ad40be27SYifei Jiang if (!kvm_enabled()) { 420ad40be27SYifei Jiang return; 421ad40be27SYifei Jiang } 422ad40be27SYifei Jiang env->pc = cpu->env.kernel_addr; 423ad40be27SYifei Jiang env->gpr[10] = kvm_arch_vcpu_id(CPU(cpu)); /* a0 */ 424ad40be27SYifei Jiang env->gpr[11] = cpu->env.fdt_addr; /* a1 */ 425ad40be27SYifei Jiang env->satp = 0; 426ad40be27SYifei Jiang } 427ad40be27SYifei Jiang 4282b650fbbSYifei Jiang void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level) 4292b650fbbSYifei Jiang { 4302b650fbbSYifei Jiang int ret; 4312b650fbbSYifei Jiang unsigned virq = level ? KVM_INTERRUPT_SET : KVM_INTERRUPT_UNSET; 4322b650fbbSYifei Jiang 4332b650fbbSYifei Jiang if (irq != IRQ_S_EXT) { 4342b650fbbSYifei Jiang perror("kvm riscv set irq != IRQ_S_EXT\n"); 4352b650fbbSYifei Jiang abort(); 4362b650fbbSYifei Jiang } 4372b650fbbSYifei Jiang 4382b650fbbSYifei Jiang ret = kvm_vcpu_ioctl(CPU(cpu), KVM_INTERRUPT, &virq); 4392b650fbbSYifei Jiang if (ret < 0) { 4402b650fbbSYifei Jiang perror("Set irq failed"); 4412b650fbbSYifei Jiang abort(); 4422b650fbbSYifei Jiang } 4432b650fbbSYifei Jiang } 4442b650fbbSYifei Jiang 44591654e61SYifei Jiang bool kvm_arch_cpu_check_are_resettable(void) 44691654e61SYifei Jiang { 44791654e61SYifei Jiang return true; 44891654e61SYifei Jiang } 449