xref: /qemu/target/riscv/kvm/kvm-cpu.c (revision 4eb471258bd0e331678bece4c894c477928b3b0b)
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), &reg); \
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), &reg); \
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), &reg);
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, &reg);
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), &reg);
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, &reg);
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), &reg);
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), &reg);
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), &reg);
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), &reg);
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