xref: /qemu/target/riscv/kvm/kvm-cpu.c (revision 9ad3e016ae1ed2f30c39051bc20f1da327bd9400)
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"
414eb47125SYifei Jiang #include "sbi_ecall_interface.h"
424eb47125SYifei Jiang #include "chardev/char-fe.h"
4327abe66fSYifei Jiang #include "migration/migration.h"
44*9ad3e016SYifei Jiang #include "sysemu/runstate.h"
4591654e61SYifei Jiang 
460a312b85SYifei Jiang static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type,
470a312b85SYifei Jiang                                  uint64_t idx)
480a312b85SYifei Jiang {
490a312b85SYifei Jiang     uint64_t id = KVM_REG_RISCV | type | idx;
500a312b85SYifei Jiang 
510a312b85SYifei Jiang     switch (riscv_cpu_mxl(env)) {
520a312b85SYifei Jiang     case MXL_RV32:
530a312b85SYifei Jiang         id |= KVM_REG_SIZE_U32;
540a312b85SYifei Jiang         break;
550a312b85SYifei Jiang     case MXL_RV64:
560a312b85SYifei Jiang         id |= KVM_REG_SIZE_U64;
570a312b85SYifei Jiang         break;
580a312b85SYifei Jiang     default:
590a312b85SYifei Jiang         g_assert_not_reached();
600a312b85SYifei Jiang     }
610a312b85SYifei Jiang     return id;
620a312b85SYifei Jiang }
630a312b85SYifei Jiang 
64937f0b45SYifei Jiang #define RISCV_CORE_REG(env, name)  kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, \
65937f0b45SYifei Jiang                  KVM_REG_RISCV_CORE_REG(name))
66937f0b45SYifei Jiang 
67937f0b45SYifei Jiang #define RISCV_CSR_REG(env, name)  kvm_riscv_reg_id(env, KVM_REG_RISCV_CSR, \
68937f0b45SYifei Jiang                  KVM_REG_RISCV_CSR_REG(name))
69937f0b45SYifei Jiang 
7027abe66fSYifei Jiang #define RISCV_TIMER_REG(env, name)  kvm_riscv_reg_id(env, KVM_REG_RISCV_TIMER, \
7127abe66fSYifei Jiang                  KVM_REG_RISCV_TIMER_REG(name))
7227abe66fSYifei Jiang 
73937f0b45SYifei Jiang #define RISCV_FP_F_REG(env, idx)  kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_F, idx)
74937f0b45SYifei Jiang 
75937f0b45SYifei Jiang #define RISCV_FP_D_REG(env, idx)  kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_D, idx)
76937f0b45SYifei Jiang 
77937f0b45SYifei Jiang #define KVM_RISCV_GET_CSR(cs, env, csr, reg) \
78937f0b45SYifei Jiang     do { \
79937f0b45SYifei Jiang         int ret = kvm_get_one_reg(cs, RISCV_CSR_REG(env, csr), &reg); \
80937f0b45SYifei Jiang         if (ret) { \
81937f0b45SYifei Jiang             return ret; \
82937f0b45SYifei Jiang         } \
83937f0b45SYifei Jiang     } while (0)
84937f0b45SYifei Jiang 
859997cc1eSYifei Jiang #define KVM_RISCV_SET_CSR(cs, env, csr, reg) \
869997cc1eSYifei Jiang     do { \
879997cc1eSYifei Jiang         int ret = kvm_set_one_reg(cs, RISCV_CSR_REG(env, csr), &reg); \
889997cc1eSYifei Jiang         if (ret) { \
899997cc1eSYifei Jiang             return ret; \
909997cc1eSYifei Jiang         } \
919997cc1eSYifei Jiang     } while (0)
929997cc1eSYifei Jiang 
9327abe66fSYifei Jiang #define KVM_RISCV_GET_TIMER(cs, env, name, reg) \
9427abe66fSYifei Jiang     do { \
9527abe66fSYifei Jiang         int ret = kvm_get_one_reg(cs, RISCV_TIMER_REG(env, name), &reg); \
9627abe66fSYifei Jiang         if (ret) { \
9727abe66fSYifei Jiang             abort(); \
9827abe66fSYifei Jiang         } \
9927abe66fSYifei Jiang     } while (0)
10027abe66fSYifei Jiang 
10127abe66fSYifei Jiang #define KVM_RISCV_SET_TIMER(cs, env, name, reg) \
10227abe66fSYifei Jiang     do { \
10327abe66fSYifei Jiang         int ret = kvm_set_one_reg(cs, RISCV_TIMER_REG(env, time), &reg); \
10427abe66fSYifei Jiang         if (ret) { \
10527abe66fSYifei Jiang             abort(); \
10627abe66fSYifei Jiang         } \
10727abe66fSYifei Jiang     } while (0)
10827abe66fSYifei Jiang 
109937f0b45SYifei Jiang static int kvm_riscv_get_regs_core(CPUState *cs)
110937f0b45SYifei Jiang {
111937f0b45SYifei Jiang     int ret = 0;
112937f0b45SYifei Jiang     int i;
113937f0b45SYifei Jiang     target_ulong reg;
114937f0b45SYifei Jiang     CPURISCVState *env = &RISCV_CPU(cs)->env;
115937f0b45SYifei Jiang 
116937f0b45SYifei Jiang     ret = kvm_get_one_reg(cs, RISCV_CORE_REG(env, regs.pc), &reg);
117937f0b45SYifei Jiang     if (ret) {
118937f0b45SYifei Jiang         return ret;
119937f0b45SYifei Jiang     }
120937f0b45SYifei Jiang     env->pc = reg;
121937f0b45SYifei Jiang 
122937f0b45SYifei Jiang     for (i = 1; i < 32; i++) {
123937f0b45SYifei Jiang         uint64_t id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, i);
124937f0b45SYifei Jiang         ret = kvm_get_one_reg(cs, id, &reg);
125937f0b45SYifei Jiang         if (ret) {
126937f0b45SYifei Jiang             return ret;
127937f0b45SYifei Jiang         }
128937f0b45SYifei Jiang         env->gpr[i] = reg;
129937f0b45SYifei Jiang     }
130937f0b45SYifei Jiang 
131937f0b45SYifei Jiang     return ret;
132937f0b45SYifei Jiang }
133937f0b45SYifei Jiang 
1349997cc1eSYifei Jiang static int kvm_riscv_put_regs_core(CPUState *cs)
1359997cc1eSYifei Jiang {
1369997cc1eSYifei Jiang     int ret = 0;
1379997cc1eSYifei Jiang     int i;
1389997cc1eSYifei Jiang     target_ulong reg;
1399997cc1eSYifei Jiang     CPURISCVState *env = &RISCV_CPU(cs)->env;
1409997cc1eSYifei Jiang 
1419997cc1eSYifei Jiang     reg = env->pc;
1429997cc1eSYifei Jiang     ret = kvm_set_one_reg(cs, RISCV_CORE_REG(env, regs.pc), &reg);
1439997cc1eSYifei Jiang     if (ret) {
1449997cc1eSYifei Jiang         return ret;
1459997cc1eSYifei Jiang     }
1469997cc1eSYifei Jiang 
1479997cc1eSYifei Jiang     for (i = 1; i < 32; i++) {
1489997cc1eSYifei Jiang         uint64_t id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, i);
1499997cc1eSYifei Jiang         reg = env->gpr[i];
1509997cc1eSYifei Jiang         ret = kvm_set_one_reg(cs, id, &reg);
1519997cc1eSYifei Jiang         if (ret) {
1529997cc1eSYifei Jiang             return ret;
1539997cc1eSYifei Jiang         }
1549997cc1eSYifei Jiang     }
1559997cc1eSYifei Jiang 
1569997cc1eSYifei Jiang     return ret;
1579997cc1eSYifei Jiang }
1589997cc1eSYifei Jiang 
159937f0b45SYifei Jiang static int kvm_riscv_get_regs_csr(CPUState *cs)
160937f0b45SYifei Jiang {
161937f0b45SYifei Jiang     int ret = 0;
162937f0b45SYifei Jiang     CPURISCVState *env = &RISCV_CPU(cs)->env;
163937f0b45SYifei Jiang 
164937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, sstatus, env->mstatus);
165937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, sie, env->mie);
166937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, stvec, env->stvec);
167937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, sscratch, env->sscratch);
168937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, sepc, env->sepc);
169937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, scause, env->scause);
170937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, stval, env->stval);
171937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, sip, env->mip);
172937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, satp, env->satp);
173937f0b45SYifei Jiang     return ret;
174937f0b45SYifei Jiang }
175937f0b45SYifei Jiang 
1769997cc1eSYifei Jiang static int kvm_riscv_put_regs_csr(CPUState *cs)
1779997cc1eSYifei Jiang {
1789997cc1eSYifei Jiang     int ret = 0;
1799997cc1eSYifei Jiang     CPURISCVState *env = &RISCV_CPU(cs)->env;
1809997cc1eSYifei Jiang 
1819997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, sstatus, env->mstatus);
1829997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, sie, env->mie);
1839997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, stvec, env->stvec);
1849997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, sscratch, env->sscratch);
1859997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, sepc, env->sepc);
1869997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, scause, env->scause);
1879997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, stval, env->stval);
1889997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, sip, env->mip);
1899997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, satp, env->satp);
1909997cc1eSYifei Jiang 
1919997cc1eSYifei Jiang     return ret;
1929997cc1eSYifei Jiang }
1939997cc1eSYifei Jiang 
194937f0b45SYifei Jiang static int kvm_riscv_get_regs_fp(CPUState *cs)
195937f0b45SYifei Jiang {
196937f0b45SYifei Jiang     int ret = 0;
197937f0b45SYifei Jiang     int i;
198937f0b45SYifei Jiang     CPURISCVState *env = &RISCV_CPU(cs)->env;
199937f0b45SYifei Jiang 
200937f0b45SYifei Jiang     if (riscv_has_ext(env, RVD)) {
201937f0b45SYifei Jiang         uint64_t reg;
202937f0b45SYifei Jiang         for (i = 0; i < 32; i++) {
203937f0b45SYifei Jiang             ret = kvm_get_one_reg(cs, RISCV_FP_D_REG(env, i), &reg);
204937f0b45SYifei Jiang             if (ret) {
205937f0b45SYifei Jiang                 return ret;
206937f0b45SYifei Jiang             }
207937f0b45SYifei Jiang             env->fpr[i] = reg;
208937f0b45SYifei Jiang         }
209937f0b45SYifei Jiang         return ret;
210937f0b45SYifei Jiang     }
211937f0b45SYifei Jiang 
212937f0b45SYifei Jiang     if (riscv_has_ext(env, RVF)) {
213937f0b45SYifei Jiang         uint32_t reg;
214937f0b45SYifei Jiang         for (i = 0; i < 32; i++) {
215937f0b45SYifei Jiang             ret = kvm_get_one_reg(cs, RISCV_FP_F_REG(env, i), &reg);
216937f0b45SYifei Jiang             if (ret) {
217937f0b45SYifei Jiang                 return ret;
218937f0b45SYifei Jiang             }
219937f0b45SYifei Jiang             env->fpr[i] = reg;
220937f0b45SYifei Jiang         }
221937f0b45SYifei Jiang         return ret;
222937f0b45SYifei Jiang     }
223937f0b45SYifei Jiang 
224937f0b45SYifei Jiang     return ret;
225937f0b45SYifei Jiang }
226937f0b45SYifei Jiang 
2279997cc1eSYifei Jiang static int kvm_riscv_put_regs_fp(CPUState *cs)
2289997cc1eSYifei Jiang {
2299997cc1eSYifei Jiang     int ret = 0;
2309997cc1eSYifei Jiang     int i;
2319997cc1eSYifei Jiang     CPURISCVState *env = &RISCV_CPU(cs)->env;
2329997cc1eSYifei Jiang 
2339997cc1eSYifei Jiang     if (riscv_has_ext(env, RVD)) {
2349997cc1eSYifei Jiang         uint64_t reg;
2359997cc1eSYifei Jiang         for (i = 0; i < 32; i++) {
2369997cc1eSYifei Jiang             reg = env->fpr[i];
2379997cc1eSYifei Jiang             ret = kvm_set_one_reg(cs, RISCV_FP_D_REG(env, i), &reg);
2389997cc1eSYifei Jiang             if (ret) {
2399997cc1eSYifei Jiang                 return ret;
2409997cc1eSYifei Jiang             }
2419997cc1eSYifei Jiang         }
2429997cc1eSYifei Jiang         return ret;
2439997cc1eSYifei Jiang     }
2449997cc1eSYifei Jiang 
2459997cc1eSYifei Jiang     if (riscv_has_ext(env, RVF)) {
2469997cc1eSYifei Jiang         uint32_t reg;
2479997cc1eSYifei Jiang         for (i = 0; i < 32; i++) {
2489997cc1eSYifei Jiang             reg = env->fpr[i];
2499997cc1eSYifei Jiang             ret = kvm_set_one_reg(cs, RISCV_FP_F_REG(env, i), &reg);
2509997cc1eSYifei Jiang             if (ret) {
2519997cc1eSYifei Jiang                 return ret;
2529997cc1eSYifei Jiang             }
2539997cc1eSYifei Jiang         }
2549997cc1eSYifei Jiang         return ret;
2559997cc1eSYifei Jiang     }
2569997cc1eSYifei Jiang 
2579997cc1eSYifei Jiang     return ret;
2589997cc1eSYifei Jiang }
2599997cc1eSYifei Jiang 
26027abe66fSYifei Jiang static void kvm_riscv_get_regs_timer(CPUState *cs)
26127abe66fSYifei Jiang {
26227abe66fSYifei Jiang     CPURISCVState *env = &RISCV_CPU(cs)->env;
26327abe66fSYifei Jiang 
26427abe66fSYifei Jiang     if (env->kvm_timer_dirty) {
26527abe66fSYifei Jiang         return;
26627abe66fSYifei Jiang     }
26727abe66fSYifei Jiang 
26827abe66fSYifei Jiang     KVM_RISCV_GET_TIMER(cs, env, time, env->kvm_timer_time);
26927abe66fSYifei Jiang     KVM_RISCV_GET_TIMER(cs, env, compare, env->kvm_timer_compare);
27027abe66fSYifei Jiang     KVM_RISCV_GET_TIMER(cs, env, state, env->kvm_timer_state);
27127abe66fSYifei Jiang     KVM_RISCV_GET_TIMER(cs, env, frequency, env->kvm_timer_frequency);
27227abe66fSYifei Jiang 
27327abe66fSYifei Jiang     env->kvm_timer_dirty = true;
27427abe66fSYifei Jiang }
27527abe66fSYifei Jiang 
27627abe66fSYifei Jiang static void kvm_riscv_put_regs_timer(CPUState *cs)
27727abe66fSYifei Jiang {
27827abe66fSYifei Jiang     uint64_t reg;
27927abe66fSYifei Jiang     CPURISCVState *env = &RISCV_CPU(cs)->env;
28027abe66fSYifei Jiang 
28127abe66fSYifei Jiang     if (!env->kvm_timer_dirty) {
28227abe66fSYifei Jiang         return;
28327abe66fSYifei Jiang     }
28427abe66fSYifei Jiang 
28527abe66fSYifei Jiang     KVM_RISCV_SET_TIMER(cs, env, time, env->kvm_timer_time);
28627abe66fSYifei Jiang     KVM_RISCV_SET_TIMER(cs, env, compare, env->kvm_timer_compare);
28727abe66fSYifei Jiang 
28827abe66fSYifei Jiang     /*
28927abe66fSYifei Jiang      * To set register of RISCV_TIMER_REG(state) will occur a error from KVM
29027abe66fSYifei Jiang      * on env->kvm_timer_state == 0, It's better to adapt in KVM, but it
29127abe66fSYifei Jiang      * doesn't matter that adaping in QEMU now.
29227abe66fSYifei Jiang      * TODO If KVM changes, adapt here.
29327abe66fSYifei Jiang      */
29427abe66fSYifei Jiang     if (env->kvm_timer_state) {
29527abe66fSYifei Jiang         KVM_RISCV_SET_TIMER(cs, env, state, env->kvm_timer_state);
29627abe66fSYifei Jiang     }
29727abe66fSYifei Jiang 
29827abe66fSYifei Jiang     /*
29927abe66fSYifei Jiang      * For now, migration will not work between Hosts with different timer
30027abe66fSYifei Jiang      * frequency. Therefore, we should check whether they are the same here
30127abe66fSYifei Jiang      * during the migration.
30227abe66fSYifei Jiang      */
30327abe66fSYifei Jiang     if (migration_is_running(migrate_get_current()->state)) {
30427abe66fSYifei Jiang         KVM_RISCV_GET_TIMER(cs, env, frequency, reg);
30527abe66fSYifei Jiang         if (reg != env->kvm_timer_frequency) {
30627abe66fSYifei Jiang             error_report("Dst Hosts timer frequency != Src Hosts");
30727abe66fSYifei Jiang         }
30827abe66fSYifei Jiang     }
30927abe66fSYifei Jiang 
31027abe66fSYifei Jiang     env->kvm_timer_dirty = false;
31127abe66fSYifei Jiang }
3129997cc1eSYifei Jiang 
31391654e61SYifei Jiang const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
31491654e61SYifei Jiang     KVM_CAP_LAST_INFO
31591654e61SYifei Jiang };
31691654e61SYifei Jiang 
31791654e61SYifei Jiang int kvm_arch_get_registers(CPUState *cs)
31891654e61SYifei Jiang {
319937f0b45SYifei Jiang     int ret = 0;
320937f0b45SYifei Jiang 
321937f0b45SYifei Jiang     ret = kvm_riscv_get_regs_core(cs);
322937f0b45SYifei Jiang     if (ret) {
323937f0b45SYifei Jiang         return ret;
324937f0b45SYifei Jiang     }
325937f0b45SYifei Jiang 
326937f0b45SYifei Jiang     ret = kvm_riscv_get_regs_csr(cs);
327937f0b45SYifei Jiang     if (ret) {
328937f0b45SYifei Jiang         return ret;
329937f0b45SYifei Jiang     }
330937f0b45SYifei Jiang 
331937f0b45SYifei Jiang     ret = kvm_riscv_get_regs_fp(cs);
332937f0b45SYifei Jiang     if (ret) {
333937f0b45SYifei Jiang         return ret;
334937f0b45SYifei Jiang     }
335937f0b45SYifei Jiang 
336937f0b45SYifei Jiang     return ret;
33791654e61SYifei Jiang }
33891654e61SYifei Jiang 
33991654e61SYifei Jiang int kvm_arch_put_registers(CPUState *cs, int level)
34091654e61SYifei Jiang {
3419997cc1eSYifei Jiang     int ret = 0;
3429997cc1eSYifei Jiang 
3439997cc1eSYifei Jiang     ret = kvm_riscv_put_regs_core(cs);
3449997cc1eSYifei Jiang     if (ret) {
3459997cc1eSYifei Jiang         return ret;
3469997cc1eSYifei Jiang     }
3479997cc1eSYifei Jiang 
3489997cc1eSYifei Jiang     ret = kvm_riscv_put_regs_csr(cs);
3499997cc1eSYifei Jiang     if (ret) {
3509997cc1eSYifei Jiang         return ret;
3519997cc1eSYifei Jiang     }
3529997cc1eSYifei Jiang 
3539997cc1eSYifei Jiang     ret = kvm_riscv_put_regs_fp(cs);
3549997cc1eSYifei Jiang     if (ret) {
3559997cc1eSYifei Jiang         return ret;
3569997cc1eSYifei Jiang     }
3579997cc1eSYifei Jiang 
3589997cc1eSYifei Jiang     return ret;
35991654e61SYifei Jiang }
36091654e61SYifei Jiang 
36191654e61SYifei Jiang int kvm_arch_release_virq_post(int virq)
36291654e61SYifei Jiang {
36391654e61SYifei Jiang     return 0;
36491654e61SYifei Jiang }
36591654e61SYifei Jiang 
36691654e61SYifei Jiang int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
36791654e61SYifei Jiang                              uint64_t address, uint32_t data, PCIDevice *dev)
36891654e61SYifei Jiang {
36991654e61SYifei Jiang     return 0;
37091654e61SYifei Jiang }
37191654e61SYifei Jiang 
37291654e61SYifei Jiang int kvm_arch_destroy_vcpu(CPUState *cs)
37391654e61SYifei Jiang {
37491654e61SYifei Jiang     return 0;
37591654e61SYifei Jiang }
37691654e61SYifei Jiang 
37791654e61SYifei Jiang unsigned long kvm_arch_vcpu_id(CPUState *cpu)
37891654e61SYifei Jiang {
37991654e61SYifei Jiang     return cpu->cpu_index;
38091654e61SYifei Jiang }
38191654e61SYifei Jiang 
382*9ad3e016SYifei Jiang static void kvm_riscv_vm_state_change(void *opaque, bool running,
383*9ad3e016SYifei Jiang                                       RunState state)
384*9ad3e016SYifei Jiang {
385*9ad3e016SYifei Jiang     CPUState *cs = opaque;
386*9ad3e016SYifei Jiang 
387*9ad3e016SYifei Jiang     if (running) {
388*9ad3e016SYifei Jiang         kvm_riscv_put_regs_timer(cs);
389*9ad3e016SYifei Jiang     } else {
390*9ad3e016SYifei Jiang         kvm_riscv_get_regs_timer(cs);
391*9ad3e016SYifei Jiang     }
392*9ad3e016SYifei Jiang }
393*9ad3e016SYifei Jiang 
39491654e61SYifei Jiang void kvm_arch_init_irq_routing(KVMState *s)
39591654e61SYifei Jiang {
39691654e61SYifei Jiang }
39791654e61SYifei Jiang 
39891654e61SYifei Jiang int kvm_arch_init_vcpu(CPUState *cs)
39991654e61SYifei Jiang {
4000a312b85SYifei Jiang     int ret = 0;
4010a312b85SYifei Jiang     target_ulong isa;
4020a312b85SYifei Jiang     RISCVCPU *cpu = RISCV_CPU(cs);
4030a312b85SYifei Jiang     CPURISCVState *env = &cpu->env;
4040a312b85SYifei Jiang     uint64_t id;
4050a312b85SYifei Jiang 
406*9ad3e016SYifei Jiang     qemu_add_vm_change_state_handler(kvm_riscv_vm_state_change, cs);
407*9ad3e016SYifei Jiang 
4080a312b85SYifei Jiang     id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CONFIG,
4090a312b85SYifei Jiang                           KVM_REG_RISCV_CONFIG_REG(isa));
4100a312b85SYifei Jiang     ret = kvm_get_one_reg(cs, id, &isa);
4110a312b85SYifei Jiang     if (ret) {
4120a312b85SYifei Jiang         return ret;
4130a312b85SYifei Jiang     }
4140a312b85SYifei Jiang     env->misa_ext = isa;
4150a312b85SYifei Jiang 
4160a312b85SYifei Jiang     return ret;
41791654e61SYifei Jiang }
41891654e61SYifei Jiang 
41991654e61SYifei Jiang int kvm_arch_msi_data_to_gsi(uint32_t data)
42091654e61SYifei Jiang {
42191654e61SYifei Jiang     abort();
42291654e61SYifei Jiang }
42391654e61SYifei Jiang 
42491654e61SYifei Jiang int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
42591654e61SYifei Jiang                                 int vector, PCIDevice *dev)
42691654e61SYifei Jiang {
42791654e61SYifei Jiang     return 0;
42891654e61SYifei Jiang }
42991654e61SYifei Jiang 
43091654e61SYifei Jiang int kvm_arch_init(MachineState *ms, KVMState *s)
43191654e61SYifei Jiang {
43291654e61SYifei Jiang     return 0;
43391654e61SYifei Jiang }
43491654e61SYifei Jiang 
43591654e61SYifei Jiang int kvm_arch_irqchip_create(KVMState *s)
43691654e61SYifei Jiang {
43791654e61SYifei Jiang     return 0;
43891654e61SYifei Jiang }
43991654e61SYifei Jiang 
44091654e61SYifei Jiang int kvm_arch_process_async_events(CPUState *cs)
44191654e61SYifei Jiang {
44291654e61SYifei Jiang     return 0;
44391654e61SYifei Jiang }
44491654e61SYifei Jiang 
44591654e61SYifei Jiang void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
44691654e61SYifei Jiang {
44791654e61SYifei Jiang }
44891654e61SYifei Jiang 
44991654e61SYifei Jiang MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
45091654e61SYifei Jiang {
45191654e61SYifei Jiang     return MEMTXATTRS_UNSPECIFIED;
45291654e61SYifei Jiang }
45391654e61SYifei Jiang 
45491654e61SYifei Jiang bool kvm_arch_stop_on_emulation_error(CPUState *cs)
45591654e61SYifei Jiang {
45691654e61SYifei Jiang     return true;
45791654e61SYifei Jiang }
45891654e61SYifei Jiang 
4594eb47125SYifei Jiang static int kvm_riscv_handle_sbi(CPUState *cs, struct kvm_run *run)
4604eb47125SYifei Jiang {
4614eb47125SYifei Jiang     int ret = 0;
4624eb47125SYifei Jiang     unsigned char ch;
4634eb47125SYifei Jiang     switch (run->riscv_sbi.extension_id) {
4644eb47125SYifei Jiang     case SBI_EXT_0_1_CONSOLE_PUTCHAR:
4654eb47125SYifei Jiang         ch = run->riscv_sbi.args[0];
4664eb47125SYifei Jiang         qemu_chr_fe_write(serial_hd(0)->be, &ch, sizeof(ch));
4674eb47125SYifei Jiang         break;
4684eb47125SYifei Jiang     case SBI_EXT_0_1_CONSOLE_GETCHAR:
4694eb47125SYifei Jiang         ret = qemu_chr_fe_read_all(serial_hd(0)->be, &ch, sizeof(ch));
4704eb47125SYifei Jiang         if (ret == sizeof(ch)) {
4714eb47125SYifei Jiang             run->riscv_sbi.args[0] = ch;
4724eb47125SYifei Jiang         } else {
4734eb47125SYifei Jiang             run->riscv_sbi.args[0] = -1;
4744eb47125SYifei Jiang         }
4754eb47125SYifei Jiang         break;
4764eb47125SYifei Jiang     default:
4774eb47125SYifei Jiang         qemu_log_mask(LOG_UNIMP,
4784eb47125SYifei Jiang                       "%s: un-handled SBI EXIT, specific reasons is %lu\n",
4794eb47125SYifei Jiang                       __func__, run->riscv_sbi.extension_id);
4804eb47125SYifei Jiang         ret = -1;
4814eb47125SYifei Jiang         break;
4824eb47125SYifei Jiang     }
4834eb47125SYifei Jiang     return ret;
4844eb47125SYifei Jiang }
4854eb47125SYifei Jiang 
48691654e61SYifei Jiang int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
48791654e61SYifei Jiang {
4884eb47125SYifei Jiang     int ret = 0;
4894eb47125SYifei Jiang     switch (run->exit_reason) {
4904eb47125SYifei Jiang     case KVM_EXIT_RISCV_SBI:
4914eb47125SYifei Jiang         ret = kvm_riscv_handle_sbi(cs, run);
4924eb47125SYifei Jiang         break;
4934eb47125SYifei Jiang     default:
4944eb47125SYifei Jiang         qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n",
4954eb47125SYifei Jiang                       __func__, run->exit_reason);
4964eb47125SYifei Jiang         ret = -1;
4974eb47125SYifei Jiang         break;
4984eb47125SYifei Jiang     }
4994eb47125SYifei Jiang     return ret;
50091654e61SYifei Jiang }
50191654e61SYifei Jiang 
502ad40be27SYifei Jiang void kvm_riscv_reset_vcpu(RISCVCPU *cpu)
503ad40be27SYifei Jiang {
504ad40be27SYifei Jiang     CPURISCVState *env = &cpu->env;
505ad40be27SYifei Jiang 
506ad40be27SYifei Jiang     if (!kvm_enabled()) {
507ad40be27SYifei Jiang         return;
508ad40be27SYifei Jiang     }
509ad40be27SYifei Jiang     env->pc = cpu->env.kernel_addr;
510ad40be27SYifei Jiang     env->gpr[10] = kvm_arch_vcpu_id(CPU(cpu)); /* a0 */
511ad40be27SYifei Jiang     env->gpr[11] = cpu->env.fdt_addr;          /* a1 */
512ad40be27SYifei Jiang     env->satp = 0;
513ad40be27SYifei Jiang }
514ad40be27SYifei Jiang 
5152b650fbbSYifei Jiang void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level)
5162b650fbbSYifei Jiang {
5172b650fbbSYifei Jiang     int ret;
5182b650fbbSYifei Jiang     unsigned virq = level ? KVM_INTERRUPT_SET : KVM_INTERRUPT_UNSET;
5192b650fbbSYifei Jiang 
5202b650fbbSYifei Jiang     if (irq != IRQ_S_EXT) {
5212b650fbbSYifei Jiang         perror("kvm riscv set irq != IRQ_S_EXT\n");
5222b650fbbSYifei Jiang         abort();
5232b650fbbSYifei Jiang     }
5242b650fbbSYifei Jiang 
5252b650fbbSYifei Jiang     ret = kvm_vcpu_ioctl(CPU(cpu), KVM_INTERRUPT, &virq);
5262b650fbbSYifei Jiang     if (ret < 0) {
5272b650fbbSYifei Jiang         perror("Set irq failed");
5282b650fbbSYifei Jiang         abort();
5292b650fbbSYifei Jiang     }
5302b650fbbSYifei Jiang }
5312b650fbbSYifei Jiang 
53291654e61SYifei Jiang bool kvm_arch_cpu_check_are_resettable(void)
53391654e61SYifei Jiang {
53491654e61SYifei Jiang     return true;
53591654e61SYifei Jiang }
536