xref: /qemu/target/riscv/kvm/kvm-cpu.c (revision ad40be27084536408b47a9209181f776ec2c54a5)
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"
40*ad40be27SYifei Jiang #include "kvm_riscv.h"
4191654e61SYifei Jiang 
420a312b85SYifei Jiang static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type,
430a312b85SYifei Jiang                                  uint64_t idx)
440a312b85SYifei Jiang {
450a312b85SYifei Jiang     uint64_t id = KVM_REG_RISCV | type | idx;
460a312b85SYifei Jiang 
470a312b85SYifei Jiang     switch (riscv_cpu_mxl(env)) {
480a312b85SYifei Jiang     case MXL_RV32:
490a312b85SYifei Jiang         id |= KVM_REG_SIZE_U32;
500a312b85SYifei Jiang         break;
510a312b85SYifei Jiang     case MXL_RV64:
520a312b85SYifei Jiang         id |= KVM_REG_SIZE_U64;
530a312b85SYifei Jiang         break;
540a312b85SYifei Jiang     default:
550a312b85SYifei Jiang         g_assert_not_reached();
560a312b85SYifei Jiang     }
570a312b85SYifei Jiang     return id;
580a312b85SYifei Jiang }
590a312b85SYifei Jiang 
60937f0b45SYifei Jiang #define RISCV_CORE_REG(env, name)  kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, \
61937f0b45SYifei Jiang                  KVM_REG_RISCV_CORE_REG(name))
62937f0b45SYifei Jiang 
63937f0b45SYifei Jiang #define RISCV_CSR_REG(env, name)  kvm_riscv_reg_id(env, KVM_REG_RISCV_CSR, \
64937f0b45SYifei Jiang                  KVM_REG_RISCV_CSR_REG(name))
65937f0b45SYifei Jiang 
66937f0b45SYifei Jiang #define RISCV_FP_F_REG(env, idx)  kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_F, idx)
67937f0b45SYifei Jiang 
68937f0b45SYifei Jiang #define RISCV_FP_D_REG(env, idx)  kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_D, idx)
69937f0b45SYifei Jiang 
70937f0b45SYifei Jiang #define KVM_RISCV_GET_CSR(cs, env, csr, reg) \
71937f0b45SYifei Jiang     do { \
72937f0b45SYifei Jiang         int ret = kvm_get_one_reg(cs, RISCV_CSR_REG(env, csr), &reg); \
73937f0b45SYifei Jiang         if (ret) { \
74937f0b45SYifei Jiang             return ret; \
75937f0b45SYifei Jiang         } \
76937f0b45SYifei Jiang     } while (0)
77937f0b45SYifei Jiang 
789997cc1eSYifei Jiang #define KVM_RISCV_SET_CSR(cs, env, csr, reg) \
799997cc1eSYifei Jiang     do { \
809997cc1eSYifei Jiang         int ret = kvm_set_one_reg(cs, RISCV_CSR_REG(env, csr), &reg); \
819997cc1eSYifei Jiang         if (ret) { \
829997cc1eSYifei Jiang             return ret; \
839997cc1eSYifei Jiang         } \
849997cc1eSYifei Jiang     } while (0)
859997cc1eSYifei Jiang 
86937f0b45SYifei Jiang static int kvm_riscv_get_regs_core(CPUState *cs)
87937f0b45SYifei Jiang {
88937f0b45SYifei Jiang     int ret = 0;
89937f0b45SYifei Jiang     int i;
90937f0b45SYifei Jiang     target_ulong reg;
91937f0b45SYifei Jiang     CPURISCVState *env = &RISCV_CPU(cs)->env;
92937f0b45SYifei Jiang 
93937f0b45SYifei Jiang     ret = kvm_get_one_reg(cs, RISCV_CORE_REG(env, regs.pc), &reg);
94937f0b45SYifei Jiang     if (ret) {
95937f0b45SYifei Jiang         return ret;
96937f0b45SYifei Jiang     }
97937f0b45SYifei Jiang     env->pc = reg;
98937f0b45SYifei Jiang 
99937f0b45SYifei Jiang     for (i = 1; i < 32; i++) {
100937f0b45SYifei Jiang         uint64_t id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, i);
101937f0b45SYifei Jiang         ret = kvm_get_one_reg(cs, id, &reg);
102937f0b45SYifei Jiang         if (ret) {
103937f0b45SYifei Jiang             return ret;
104937f0b45SYifei Jiang         }
105937f0b45SYifei Jiang         env->gpr[i] = reg;
106937f0b45SYifei Jiang     }
107937f0b45SYifei Jiang 
108937f0b45SYifei Jiang     return ret;
109937f0b45SYifei Jiang }
110937f0b45SYifei Jiang 
1119997cc1eSYifei Jiang static int kvm_riscv_put_regs_core(CPUState *cs)
1129997cc1eSYifei Jiang {
1139997cc1eSYifei Jiang     int ret = 0;
1149997cc1eSYifei Jiang     int i;
1159997cc1eSYifei Jiang     target_ulong reg;
1169997cc1eSYifei Jiang     CPURISCVState *env = &RISCV_CPU(cs)->env;
1179997cc1eSYifei Jiang 
1189997cc1eSYifei Jiang     reg = env->pc;
1199997cc1eSYifei Jiang     ret = kvm_set_one_reg(cs, RISCV_CORE_REG(env, regs.pc), &reg);
1209997cc1eSYifei Jiang     if (ret) {
1219997cc1eSYifei Jiang         return ret;
1229997cc1eSYifei Jiang     }
1239997cc1eSYifei Jiang 
1249997cc1eSYifei Jiang     for (i = 1; i < 32; i++) {
1259997cc1eSYifei Jiang         uint64_t id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, i);
1269997cc1eSYifei Jiang         reg = env->gpr[i];
1279997cc1eSYifei Jiang         ret = kvm_set_one_reg(cs, id, &reg);
1289997cc1eSYifei Jiang         if (ret) {
1299997cc1eSYifei Jiang             return ret;
1309997cc1eSYifei Jiang         }
1319997cc1eSYifei Jiang     }
1329997cc1eSYifei Jiang 
1339997cc1eSYifei Jiang     return ret;
1349997cc1eSYifei Jiang }
1359997cc1eSYifei Jiang 
136937f0b45SYifei Jiang static int kvm_riscv_get_regs_csr(CPUState *cs)
137937f0b45SYifei Jiang {
138937f0b45SYifei Jiang     int ret = 0;
139937f0b45SYifei Jiang     CPURISCVState *env = &RISCV_CPU(cs)->env;
140937f0b45SYifei Jiang 
141937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, sstatus, env->mstatus);
142937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, sie, env->mie);
143937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, stvec, env->stvec);
144937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, sscratch, env->sscratch);
145937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, sepc, env->sepc);
146937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, scause, env->scause);
147937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, stval, env->stval);
148937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, sip, env->mip);
149937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, satp, env->satp);
150937f0b45SYifei Jiang     return ret;
151937f0b45SYifei Jiang }
152937f0b45SYifei Jiang 
1539997cc1eSYifei Jiang static int kvm_riscv_put_regs_csr(CPUState *cs)
1549997cc1eSYifei Jiang {
1559997cc1eSYifei Jiang     int ret = 0;
1569997cc1eSYifei Jiang     CPURISCVState *env = &RISCV_CPU(cs)->env;
1579997cc1eSYifei Jiang 
1589997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, sstatus, env->mstatus);
1599997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, sie, env->mie);
1609997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, stvec, env->stvec);
1619997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, sscratch, env->sscratch);
1629997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, sepc, env->sepc);
1639997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, scause, env->scause);
1649997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, stval, env->stval);
1659997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, sip, env->mip);
1669997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, satp, env->satp);
1679997cc1eSYifei Jiang 
1689997cc1eSYifei Jiang     return ret;
1699997cc1eSYifei Jiang }
1709997cc1eSYifei Jiang 
171937f0b45SYifei Jiang static int kvm_riscv_get_regs_fp(CPUState *cs)
172937f0b45SYifei Jiang {
173937f0b45SYifei Jiang     int ret = 0;
174937f0b45SYifei Jiang     int i;
175937f0b45SYifei Jiang     CPURISCVState *env = &RISCV_CPU(cs)->env;
176937f0b45SYifei Jiang 
177937f0b45SYifei Jiang     if (riscv_has_ext(env, RVD)) {
178937f0b45SYifei Jiang         uint64_t reg;
179937f0b45SYifei Jiang         for (i = 0; i < 32; i++) {
180937f0b45SYifei Jiang             ret = kvm_get_one_reg(cs, RISCV_FP_D_REG(env, i), &reg);
181937f0b45SYifei Jiang             if (ret) {
182937f0b45SYifei Jiang                 return ret;
183937f0b45SYifei Jiang             }
184937f0b45SYifei Jiang             env->fpr[i] = reg;
185937f0b45SYifei Jiang         }
186937f0b45SYifei Jiang         return ret;
187937f0b45SYifei Jiang     }
188937f0b45SYifei Jiang 
189937f0b45SYifei Jiang     if (riscv_has_ext(env, RVF)) {
190937f0b45SYifei Jiang         uint32_t reg;
191937f0b45SYifei Jiang         for (i = 0; i < 32; i++) {
192937f0b45SYifei Jiang             ret = kvm_get_one_reg(cs, RISCV_FP_F_REG(env, i), &reg);
193937f0b45SYifei Jiang             if (ret) {
194937f0b45SYifei Jiang                 return ret;
195937f0b45SYifei Jiang             }
196937f0b45SYifei Jiang             env->fpr[i] = reg;
197937f0b45SYifei Jiang         }
198937f0b45SYifei Jiang         return ret;
199937f0b45SYifei Jiang     }
200937f0b45SYifei Jiang 
201937f0b45SYifei Jiang     return ret;
202937f0b45SYifei Jiang }
203937f0b45SYifei Jiang 
2049997cc1eSYifei Jiang static int kvm_riscv_put_regs_fp(CPUState *cs)
2059997cc1eSYifei Jiang {
2069997cc1eSYifei Jiang     int ret = 0;
2079997cc1eSYifei Jiang     int i;
2089997cc1eSYifei Jiang     CPURISCVState *env = &RISCV_CPU(cs)->env;
2099997cc1eSYifei Jiang 
2109997cc1eSYifei Jiang     if (riscv_has_ext(env, RVD)) {
2119997cc1eSYifei Jiang         uint64_t reg;
2129997cc1eSYifei Jiang         for (i = 0; i < 32; i++) {
2139997cc1eSYifei Jiang             reg = env->fpr[i];
2149997cc1eSYifei Jiang             ret = kvm_set_one_reg(cs, RISCV_FP_D_REG(env, i), &reg);
2159997cc1eSYifei Jiang             if (ret) {
2169997cc1eSYifei Jiang                 return ret;
2179997cc1eSYifei Jiang             }
2189997cc1eSYifei Jiang         }
2199997cc1eSYifei Jiang         return ret;
2209997cc1eSYifei Jiang     }
2219997cc1eSYifei Jiang 
2229997cc1eSYifei Jiang     if (riscv_has_ext(env, RVF)) {
2239997cc1eSYifei Jiang         uint32_t reg;
2249997cc1eSYifei Jiang         for (i = 0; i < 32; i++) {
2259997cc1eSYifei Jiang             reg = env->fpr[i];
2269997cc1eSYifei Jiang             ret = kvm_set_one_reg(cs, RISCV_FP_F_REG(env, i), &reg);
2279997cc1eSYifei Jiang             if (ret) {
2289997cc1eSYifei Jiang                 return ret;
2299997cc1eSYifei Jiang             }
2309997cc1eSYifei Jiang         }
2319997cc1eSYifei Jiang         return ret;
2329997cc1eSYifei Jiang     }
2339997cc1eSYifei Jiang 
2349997cc1eSYifei Jiang     return ret;
2359997cc1eSYifei Jiang }
2369997cc1eSYifei Jiang 
2379997cc1eSYifei Jiang 
23891654e61SYifei Jiang const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
23991654e61SYifei Jiang     KVM_CAP_LAST_INFO
24091654e61SYifei Jiang };
24191654e61SYifei Jiang 
24291654e61SYifei Jiang int kvm_arch_get_registers(CPUState *cs)
24391654e61SYifei Jiang {
244937f0b45SYifei Jiang     int ret = 0;
245937f0b45SYifei Jiang 
246937f0b45SYifei Jiang     ret = kvm_riscv_get_regs_core(cs);
247937f0b45SYifei Jiang     if (ret) {
248937f0b45SYifei Jiang         return ret;
249937f0b45SYifei Jiang     }
250937f0b45SYifei Jiang 
251937f0b45SYifei Jiang     ret = kvm_riscv_get_regs_csr(cs);
252937f0b45SYifei Jiang     if (ret) {
253937f0b45SYifei Jiang         return ret;
254937f0b45SYifei Jiang     }
255937f0b45SYifei Jiang 
256937f0b45SYifei Jiang     ret = kvm_riscv_get_regs_fp(cs);
257937f0b45SYifei Jiang     if (ret) {
258937f0b45SYifei Jiang         return ret;
259937f0b45SYifei Jiang     }
260937f0b45SYifei Jiang 
261937f0b45SYifei Jiang     return ret;
26291654e61SYifei Jiang }
26391654e61SYifei Jiang 
26491654e61SYifei Jiang int kvm_arch_put_registers(CPUState *cs, int level)
26591654e61SYifei Jiang {
2669997cc1eSYifei Jiang     int ret = 0;
2679997cc1eSYifei Jiang 
2689997cc1eSYifei Jiang     ret = kvm_riscv_put_regs_core(cs);
2699997cc1eSYifei Jiang     if (ret) {
2709997cc1eSYifei Jiang         return ret;
2719997cc1eSYifei Jiang     }
2729997cc1eSYifei Jiang 
2739997cc1eSYifei Jiang     ret = kvm_riscv_put_regs_csr(cs);
2749997cc1eSYifei Jiang     if (ret) {
2759997cc1eSYifei Jiang         return ret;
2769997cc1eSYifei Jiang     }
2779997cc1eSYifei Jiang 
2789997cc1eSYifei Jiang     ret = kvm_riscv_put_regs_fp(cs);
2799997cc1eSYifei Jiang     if (ret) {
2809997cc1eSYifei Jiang         return ret;
2819997cc1eSYifei Jiang     }
2829997cc1eSYifei Jiang 
2839997cc1eSYifei Jiang     return ret;
28491654e61SYifei Jiang }
28591654e61SYifei Jiang 
28691654e61SYifei Jiang int kvm_arch_release_virq_post(int virq)
28791654e61SYifei Jiang {
28891654e61SYifei Jiang     return 0;
28991654e61SYifei Jiang }
29091654e61SYifei Jiang 
29191654e61SYifei Jiang int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
29291654e61SYifei Jiang                              uint64_t address, uint32_t data, PCIDevice *dev)
29391654e61SYifei Jiang {
29491654e61SYifei Jiang     return 0;
29591654e61SYifei Jiang }
29691654e61SYifei Jiang 
29791654e61SYifei Jiang int kvm_arch_destroy_vcpu(CPUState *cs)
29891654e61SYifei Jiang {
29991654e61SYifei Jiang     return 0;
30091654e61SYifei Jiang }
30191654e61SYifei Jiang 
30291654e61SYifei Jiang unsigned long kvm_arch_vcpu_id(CPUState *cpu)
30391654e61SYifei Jiang {
30491654e61SYifei Jiang     return cpu->cpu_index;
30591654e61SYifei Jiang }
30691654e61SYifei Jiang 
30791654e61SYifei Jiang void kvm_arch_init_irq_routing(KVMState *s)
30891654e61SYifei Jiang {
30991654e61SYifei Jiang }
31091654e61SYifei Jiang 
31191654e61SYifei Jiang int kvm_arch_init_vcpu(CPUState *cs)
31291654e61SYifei Jiang {
3130a312b85SYifei Jiang     int ret = 0;
3140a312b85SYifei Jiang     target_ulong isa;
3150a312b85SYifei Jiang     RISCVCPU *cpu = RISCV_CPU(cs);
3160a312b85SYifei Jiang     CPURISCVState *env = &cpu->env;
3170a312b85SYifei Jiang     uint64_t id;
3180a312b85SYifei Jiang 
3190a312b85SYifei Jiang     id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CONFIG,
3200a312b85SYifei Jiang                           KVM_REG_RISCV_CONFIG_REG(isa));
3210a312b85SYifei Jiang     ret = kvm_get_one_reg(cs, id, &isa);
3220a312b85SYifei Jiang     if (ret) {
3230a312b85SYifei Jiang         return ret;
3240a312b85SYifei Jiang     }
3250a312b85SYifei Jiang     env->misa_ext = isa;
3260a312b85SYifei Jiang 
3270a312b85SYifei Jiang     return ret;
32891654e61SYifei Jiang }
32991654e61SYifei Jiang 
33091654e61SYifei Jiang int kvm_arch_msi_data_to_gsi(uint32_t data)
33191654e61SYifei Jiang {
33291654e61SYifei Jiang     abort();
33391654e61SYifei Jiang }
33491654e61SYifei Jiang 
33591654e61SYifei Jiang int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
33691654e61SYifei Jiang                                 int vector, PCIDevice *dev)
33791654e61SYifei Jiang {
33891654e61SYifei Jiang     return 0;
33991654e61SYifei Jiang }
34091654e61SYifei Jiang 
34191654e61SYifei Jiang int kvm_arch_init(MachineState *ms, KVMState *s)
34291654e61SYifei Jiang {
34391654e61SYifei Jiang     return 0;
34491654e61SYifei Jiang }
34591654e61SYifei Jiang 
34691654e61SYifei Jiang int kvm_arch_irqchip_create(KVMState *s)
34791654e61SYifei Jiang {
34891654e61SYifei Jiang     return 0;
34991654e61SYifei Jiang }
35091654e61SYifei Jiang 
35191654e61SYifei Jiang int kvm_arch_process_async_events(CPUState *cs)
35291654e61SYifei Jiang {
35391654e61SYifei Jiang     return 0;
35491654e61SYifei Jiang }
35591654e61SYifei Jiang 
35691654e61SYifei Jiang void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
35791654e61SYifei Jiang {
35891654e61SYifei Jiang }
35991654e61SYifei Jiang 
36091654e61SYifei Jiang MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
36191654e61SYifei Jiang {
36291654e61SYifei Jiang     return MEMTXATTRS_UNSPECIFIED;
36391654e61SYifei Jiang }
36491654e61SYifei Jiang 
36591654e61SYifei Jiang bool kvm_arch_stop_on_emulation_error(CPUState *cs)
36691654e61SYifei Jiang {
36791654e61SYifei Jiang     return true;
36891654e61SYifei Jiang }
36991654e61SYifei Jiang 
37091654e61SYifei Jiang int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
37191654e61SYifei Jiang {
37291654e61SYifei Jiang     return 0;
37391654e61SYifei Jiang }
37491654e61SYifei Jiang 
375*ad40be27SYifei Jiang void kvm_riscv_reset_vcpu(RISCVCPU *cpu)
376*ad40be27SYifei Jiang {
377*ad40be27SYifei Jiang     CPURISCVState *env = &cpu->env;
378*ad40be27SYifei Jiang 
379*ad40be27SYifei Jiang     if (!kvm_enabled()) {
380*ad40be27SYifei Jiang         return;
381*ad40be27SYifei Jiang     }
382*ad40be27SYifei Jiang     env->pc = cpu->env.kernel_addr;
383*ad40be27SYifei Jiang     env->gpr[10] = kvm_arch_vcpu_id(CPU(cpu)); /* a0 */
384*ad40be27SYifei Jiang     env->gpr[11] = cpu->env.fdt_addr;          /* a1 */
385*ad40be27SYifei Jiang     env->satp = 0;
386*ad40be27SYifei Jiang }
387*ad40be27SYifei Jiang 
38891654e61SYifei Jiang bool kvm_arch_cpu_check_are_resettable(void)
38991654e61SYifei Jiang {
39091654e61SYifei Jiang     return true;
39191654e61SYifei Jiang }
392