xref: /qemu/target/riscv/kvm/kvm-cpu.c (revision 9997cc1e19d1f909551783c280cfe441a0838943)
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"
4091654e61SYifei Jiang 
410a312b85SYifei Jiang static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type,
420a312b85SYifei Jiang                                  uint64_t idx)
430a312b85SYifei Jiang {
440a312b85SYifei Jiang     uint64_t id = KVM_REG_RISCV | type | idx;
450a312b85SYifei Jiang 
460a312b85SYifei Jiang     switch (riscv_cpu_mxl(env)) {
470a312b85SYifei Jiang     case MXL_RV32:
480a312b85SYifei Jiang         id |= KVM_REG_SIZE_U32;
490a312b85SYifei Jiang         break;
500a312b85SYifei Jiang     case MXL_RV64:
510a312b85SYifei Jiang         id |= KVM_REG_SIZE_U64;
520a312b85SYifei Jiang         break;
530a312b85SYifei Jiang     default:
540a312b85SYifei Jiang         g_assert_not_reached();
550a312b85SYifei Jiang     }
560a312b85SYifei Jiang     return id;
570a312b85SYifei Jiang }
580a312b85SYifei Jiang 
59937f0b45SYifei Jiang #define RISCV_CORE_REG(env, name)  kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, \
60937f0b45SYifei Jiang                  KVM_REG_RISCV_CORE_REG(name))
61937f0b45SYifei Jiang 
62937f0b45SYifei Jiang #define RISCV_CSR_REG(env, name)  kvm_riscv_reg_id(env, KVM_REG_RISCV_CSR, \
63937f0b45SYifei Jiang                  KVM_REG_RISCV_CSR_REG(name))
64937f0b45SYifei Jiang 
65937f0b45SYifei Jiang #define RISCV_FP_F_REG(env, idx)  kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_F, idx)
66937f0b45SYifei Jiang 
67937f0b45SYifei Jiang #define RISCV_FP_D_REG(env, idx)  kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_D, idx)
68937f0b45SYifei Jiang 
69937f0b45SYifei Jiang #define KVM_RISCV_GET_CSR(cs, env, csr, reg) \
70937f0b45SYifei Jiang     do { \
71937f0b45SYifei Jiang         int ret = kvm_get_one_reg(cs, RISCV_CSR_REG(env, csr), &reg); \
72937f0b45SYifei Jiang         if (ret) { \
73937f0b45SYifei Jiang             return ret; \
74937f0b45SYifei Jiang         } \
75937f0b45SYifei Jiang     } while (0)
76937f0b45SYifei Jiang 
77*9997cc1eSYifei Jiang #define KVM_RISCV_SET_CSR(cs, env, csr, reg) \
78*9997cc1eSYifei Jiang     do { \
79*9997cc1eSYifei Jiang         int ret = kvm_set_one_reg(cs, RISCV_CSR_REG(env, csr), &reg); \
80*9997cc1eSYifei Jiang         if (ret) { \
81*9997cc1eSYifei Jiang             return ret; \
82*9997cc1eSYifei Jiang         } \
83*9997cc1eSYifei Jiang     } while (0)
84*9997cc1eSYifei Jiang 
85937f0b45SYifei Jiang static int kvm_riscv_get_regs_core(CPUState *cs)
86937f0b45SYifei Jiang {
87937f0b45SYifei Jiang     int ret = 0;
88937f0b45SYifei Jiang     int i;
89937f0b45SYifei Jiang     target_ulong reg;
90937f0b45SYifei Jiang     CPURISCVState *env = &RISCV_CPU(cs)->env;
91937f0b45SYifei Jiang 
92937f0b45SYifei Jiang     ret = kvm_get_one_reg(cs, RISCV_CORE_REG(env, regs.pc), &reg);
93937f0b45SYifei Jiang     if (ret) {
94937f0b45SYifei Jiang         return ret;
95937f0b45SYifei Jiang     }
96937f0b45SYifei Jiang     env->pc = reg;
97937f0b45SYifei Jiang 
98937f0b45SYifei Jiang     for (i = 1; i < 32; i++) {
99937f0b45SYifei Jiang         uint64_t id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, i);
100937f0b45SYifei Jiang         ret = kvm_get_one_reg(cs, id, &reg);
101937f0b45SYifei Jiang         if (ret) {
102937f0b45SYifei Jiang             return ret;
103937f0b45SYifei Jiang         }
104937f0b45SYifei Jiang         env->gpr[i] = reg;
105937f0b45SYifei Jiang     }
106937f0b45SYifei Jiang 
107937f0b45SYifei Jiang     return ret;
108937f0b45SYifei Jiang }
109937f0b45SYifei Jiang 
110*9997cc1eSYifei Jiang static int kvm_riscv_put_regs_core(CPUState *cs)
111*9997cc1eSYifei Jiang {
112*9997cc1eSYifei Jiang     int ret = 0;
113*9997cc1eSYifei Jiang     int i;
114*9997cc1eSYifei Jiang     target_ulong reg;
115*9997cc1eSYifei Jiang     CPURISCVState *env = &RISCV_CPU(cs)->env;
116*9997cc1eSYifei Jiang 
117*9997cc1eSYifei Jiang     reg = env->pc;
118*9997cc1eSYifei Jiang     ret = kvm_set_one_reg(cs, RISCV_CORE_REG(env, regs.pc), &reg);
119*9997cc1eSYifei Jiang     if (ret) {
120*9997cc1eSYifei Jiang         return ret;
121*9997cc1eSYifei Jiang     }
122*9997cc1eSYifei Jiang 
123*9997cc1eSYifei Jiang     for (i = 1; i < 32; i++) {
124*9997cc1eSYifei Jiang         uint64_t id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, i);
125*9997cc1eSYifei Jiang         reg = env->gpr[i];
126*9997cc1eSYifei Jiang         ret = kvm_set_one_reg(cs, id, &reg);
127*9997cc1eSYifei Jiang         if (ret) {
128*9997cc1eSYifei Jiang             return ret;
129*9997cc1eSYifei Jiang         }
130*9997cc1eSYifei Jiang     }
131*9997cc1eSYifei Jiang 
132*9997cc1eSYifei Jiang     return ret;
133*9997cc1eSYifei Jiang }
134*9997cc1eSYifei Jiang 
135937f0b45SYifei Jiang static int kvm_riscv_get_regs_csr(CPUState *cs)
136937f0b45SYifei Jiang {
137937f0b45SYifei Jiang     int ret = 0;
138937f0b45SYifei Jiang     CPURISCVState *env = &RISCV_CPU(cs)->env;
139937f0b45SYifei Jiang 
140937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, sstatus, env->mstatus);
141937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, sie, env->mie);
142937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, stvec, env->stvec);
143937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, sscratch, env->sscratch);
144937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, sepc, env->sepc);
145937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, scause, env->scause);
146937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, stval, env->stval);
147937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, sip, env->mip);
148937f0b45SYifei Jiang     KVM_RISCV_GET_CSR(cs, env, satp, env->satp);
149937f0b45SYifei Jiang     return ret;
150937f0b45SYifei Jiang }
151937f0b45SYifei Jiang 
152*9997cc1eSYifei Jiang static int kvm_riscv_put_regs_csr(CPUState *cs)
153*9997cc1eSYifei Jiang {
154*9997cc1eSYifei Jiang     int ret = 0;
155*9997cc1eSYifei Jiang     CPURISCVState *env = &RISCV_CPU(cs)->env;
156*9997cc1eSYifei Jiang 
157*9997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, sstatus, env->mstatus);
158*9997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, sie, env->mie);
159*9997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, stvec, env->stvec);
160*9997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, sscratch, env->sscratch);
161*9997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, sepc, env->sepc);
162*9997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, scause, env->scause);
163*9997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, stval, env->stval);
164*9997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, sip, env->mip);
165*9997cc1eSYifei Jiang     KVM_RISCV_SET_CSR(cs, env, satp, env->satp);
166*9997cc1eSYifei Jiang 
167*9997cc1eSYifei Jiang     return ret;
168*9997cc1eSYifei Jiang }
169*9997cc1eSYifei Jiang 
170937f0b45SYifei Jiang static int kvm_riscv_get_regs_fp(CPUState *cs)
171937f0b45SYifei Jiang {
172937f0b45SYifei Jiang     int ret = 0;
173937f0b45SYifei Jiang     int i;
174937f0b45SYifei Jiang     CPURISCVState *env = &RISCV_CPU(cs)->env;
175937f0b45SYifei Jiang 
176937f0b45SYifei Jiang     if (riscv_has_ext(env, RVD)) {
177937f0b45SYifei Jiang         uint64_t reg;
178937f0b45SYifei Jiang         for (i = 0; i < 32; i++) {
179937f0b45SYifei Jiang             ret = kvm_get_one_reg(cs, RISCV_FP_D_REG(env, i), &reg);
180937f0b45SYifei Jiang             if (ret) {
181937f0b45SYifei Jiang                 return ret;
182937f0b45SYifei Jiang             }
183937f0b45SYifei Jiang             env->fpr[i] = reg;
184937f0b45SYifei Jiang         }
185937f0b45SYifei Jiang         return ret;
186937f0b45SYifei Jiang     }
187937f0b45SYifei Jiang 
188937f0b45SYifei Jiang     if (riscv_has_ext(env, RVF)) {
189937f0b45SYifei Jiang         uint32_t reg;
190937f0b45SYifei Jiang         for (i = 0; i < 32; i++) {
191937f0b45SYifei Jiang             ret = kvm_get_one_reg(cs, RISCV_FP_F_REG(env, i), &reg);
192937f0b45SYifei Jiang             if (ret) {
193937f0b45SYifei Jiang                 return ret;
194937f0b45SYifei Jiang             }
195937f0b45SYifei Jiang             env->fpr[i] = reg;
196937f0b45SYifei Jiang         }
197937f0b45SYifei Jiang         return ret;
198937f0b45SYifei Jiang     }
199937f0b45SYifei Jiang 
200937f0b45SYifei Jiang     return ret;
201937f0b45SYifei Jiang }
202937f0b45SYifei Jiang 
203*9997cc1eSYifei Jiang static int kvm_riscv_put_regs_fp(CPUState *cs)
204*9997cc1eSYifei Jiang {
205*9997cc1eSYifei Jiang     int ret = 0;
206*9997cc1eSYifei Jiang     int i;
207*9997cc1eSYifei Jiang     CPURISCVState *env = &RISCV_CPU(cs)->env;
208*9997cc1eSYifei Jiang 
209*9997cc1eSYifei Jiang     if (riscv_has_ext(env, RVD)) {
210*9997cc1eSYifei Jiang         uint64_t reg;
211*9997cc1eSYifei Jiang         for (i = 0; i < 32; i++) {
212*9997cc1eSYifei Jiang             reg = env->fpr[i];
213*9997cc1eSYifei Jiang             ret = kvm_set_one_reg(cs, RISCV_FP_D_REG(env, i), &reg);
214*9997cc1eSYifei Jiang             if (ret) {
215*9997cc1eSYifei Jiang                 return ret;
216*9997cc1eSYifei Jiang             }
217*9997cc1eSYifei Jiang         }
218*9997cc1eSYifei Jiang         return ret;
219*9997cc1eSYifei Jiang     }
220*9997cc1eSYifei Jiang 
221*9997cc1eSYifei Jiang     if (riscv_has_ext(env, RVF)) {
222*9997cc1eSYifei Jiang         uint32_t reg;
223*9997cc1eSYifei Jiang         for (i = 0; i < 32; i++) {
224*9997cc1eSYifei Jiang             reg = env->fpr[i];
225*9997cc1eSYifei Jiang             ret = kvm_set_one_reg(cs, RISCV_FP_F_REG(env, i), &reg);
226*9997cc1eSYifei Jiang             if (ret) {
227*9997cc1eSYifei Jiang                 return ret;
228*9997cc1eSYifei Jiang             }
229*9997cc1eSYifei Jiang         }
230*9997cc1eSYifei Jiang         return ret;
231*9997cc1eSYifei Jiang     }
232*9997cc1eSYifei Jiang 
233*9997cc1eSYifei Jiang     return ret;
234*9997cc1eSYifei Jiang }
235*9997cc1eSYifei Jiang 
236*9997cc1eSYifei Jiang 
23791654e61SYifei Jiang const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
23891654e61SYifei Jiang     KVM_CAP_LAST_INFO
23991654e61SYifei Jiang };
24091654e61SYifei Jiang 
24191654e61SYifei Jiang int kvm_arch_get_registers(CPUState *cs)
24291654e61SYifei Jiang {
243937f0b45SYifei Jiang     int ret = 0;
244937f0b45SYifei Jiang 
245937f0b45SYifei Jiang     ret = kvm_riscv_get_regs_core(cs);
246937f0b45SYifei Jiang     if (ret) {
247937f0b45SYifei Jiang         return ret;
248937f0b45SYifei Jiang     }
249937f0b45SYifei Jiang 
250937f0b45SYifei Jiang     ret = kvm_riscv_get_regs_csr(cs);
251937f0b45SYifei Jiang     if (ret) {
252937f0b45SYifei Jiang         return ret;
253937f0b45SYifei Jiang     }
254937f0b45SYifei Jiang 
255937f0b45SYifei Jiang     ret = kvm_riscv_get_regs_fp(cs);
256937f0b45SYifei Jiang     if (ret) {
257937f0b45SYifei Jiang         return ret;
258937f0b45SYifei Jiang     }
259937f0b45SYifei Jiang 
260937f0b45SYifei Jiang     return ret;
26191654e61SYifei Jiang }
26291654e61SYifei Jiang 
26391654e61SYifei Jiang int kvm_arch_put_registers(CPUState *cs, int level)
26491654e61SYifei Jiang {
265*9997cc1eSYifei Jiang     int ret = 0;
266*9997cc1eSYifei Jiang 
267*9997cc1eSYifei Jiang     ret = kvm_riscv_put_regs_core(cs);
268*9997cc1eSYifei Jiang     if (ret) {
269*9997cc1eSYifei Jiang         return ret;
270*9997cc1eSYifei Jiang     }
271*9997cc1eSYifei Jiang 
272*9997cc1eSYifei Jiang     ret = kvm_riscv_put_regs_csr(cs);
273*9997cc1eSYifei Jiang     if (ret) {
274*9997cc1eSYifei Jiang         return ret;
275*9997cc1eSYifei Jiang     }
276*9997cc1eSYifei Jiang 
277*9997cc1eSYifei Jiang     ret = kvm_riscv_put_regs_fp(cs);
278*9997cc1eSYifei Jiang     if (ret) {
279*9997cc1eSYifei Jiang         return ret;
280*9997cc1eSYifei Jiang     }
281*9997cc1eSYifei Jiang 
282*9997cc1eSYifei Jiang     return ret;
28391654e61SYifei Jiang }
28491654e61SYifei Jiang 
28591654e61SYifei Jiang int kvm_arch_release_virq_post(int virq)
28691654e61SYifei Jiang {
28791654e61SYifei Jiang     return 0;
28891654e61SYifei Jiang }
28991654e61SYifei Jiang 
29091654e61SYifei Jiang int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
29191654e61SYifei Jiang                              uint64_t address, uint32_t data, PCIDevice *dev)
29291654e61SYifei Jiang {
29391654e61SYifei Jiang     return 0;
29491654e61SYifei Jiang }
29591654e61SYifei Jiang 
29691654e61SYifei Jiang int kvm_arch_destroy_vcpu(CPUState *cs)
29791654e61SYifei Jiang {
29891654e61SYifei Jiang     return 0;
29991654e61SYifei Jiang }
30091654e61SYifei Jiang 
30191654e61SYifei Jiang unsigned long kvm_arch_vcpu_id(CPUState *cpu)
30291654e61SYifei Jiang {
30391654e61SYifei Jiang     return cpu->cpu_index;
30491654e61SYifei Jiang }
30591654e61SYifei Jiang 
30691654e61SYifei Jiang void kvm_arch_init_irq_routing(KVMState *s)
30791654e61SYifei Jiang {
30891654e61SYifei Jiang }
30991654e61SYifei Jiang 
31091654e61SYifei Jiang int kvm_arch_init_vcpu(CPUState *cs)
31191654e61SYifei Jiang {
3120a312b85SYifei Jiang     int ret = 0;
3130a312b85SYifei Jiang     target_ulong isa;
3140a312b85SYifei Jiang     RISCVCPU *cpu = RISCV_CPU(cs);
3150a312b85SYifei Jiang     CPURISCVState *env = &cpu->env;
3160a312b85SYifei Jiang     uint64_t id;
3170a312b85SYifei Jiang 
3180a312b85SYifei Jiang     id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CONFIG,
3190a312b85SYifei Jiang                           KVM_REG_RISCV_CONFIG_REG(isa));
3200a312b85SYifei Jiang     ret = kvm_get_one_reg(cs, id, &isa);
3210a312b85SYifei Jiang     if (ret) {
3220a312b85SYifei Jiang         return ret;
3230a312b85SYifei Jiang     }
3240a312b85SYifei Jiang     env->misa_ext = isa;
3250a312b85SYifei Jiang 
3260a312b85SYifei Jiang     return ret;
32791654e61SYifei Jiang }
32891654e61SYifei Jiang 
32991654e61SYifei Jiang int kvm_arch_msi_data_to_gsi(uint32_t data)
33091654e61SYifei Jiang {
33191654e61SYifei Jiang     abort();
33291654e61SYifei Jiang }
33391654e61SYifei Jiang 
33491654e61SYifei Jiang int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
33591654e61SYifei Jiang                                 int vector, PCIDevice *dev)
33691654e61SYifei Jiang {
33791654e61SYifei Jiang     return 0;
33891654e61SYifei Jiang }
33991654e61SYifei Jiang 
34091654e61SYifei Jiang int kvm_arch_init(MachineState *ms, KVMState *s)
34191654e61SYifei Jiang {
34291654e61SYifei Jiang     return 0;
34391654e61SYifei Jiang }
34491654e61SYifei Jiang 
34591654e61SYifei Jiang int kvm_arch_irqchip_create(KVMState *s)
34691654e61SYifei Jiang {
34791654e61SYifei Jiang     return 0;
34891654e61SYifei Jiang }
34991654e61SYifei Jiang 
35091654e61SYifei Jiang int kvm_arch_process_async_events(CPUState *cs)
35191654e61SYifei Jiang {
35291654e61SYifei Jiang     return 0;
35391654e61SYifei Jiang }
35491654e61SYifei Jiang 
35591654e61SYifei Jiang void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
35691654e61SYifei Jiang {
35791654e61SYifei Jiang }
35891654e61SYifei Jiang 
35991654e61SYifei Jiang MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
36091654e61SYifei Jiang {
36191654e61SYifei Jiang     return MEMTXATTRS_UNSPECIFIED;
36291654e61SYifei Jiang }
36391654e61SYifei Jiang 
36491654e61SYifei Jiang bool kvm_arch_stop_on_emulation_error(CPUState *cs)
36591654e61SYifei Jiang {
36691654e61SYifei Jiang     return true;
36791654e61SYifei Jiang }
36891654e61SYifei Jiang 
36991654e61SYifei Jiang int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
37091654e61SYifei Jiang {
37191654e61SYifei Jiang     return 0;
37291654e61SYifei Jiang }
37391654e61SYifei Jiang 
37491654e61SYifei Jiang bool kvm_arch_cpu_check_are_resettable(void)
37591654e61SYifei Jiang {
37691654e61SYifei Jiang     return true;
37791654e61SYifei Jiang }
378