1537ba9daSTianrui Zhao /* SPDX-License-Identifier: GPL-2.0-or-later */
2537ba9daSTianrui Zhao /*
3537ba9daSTianrui Zhao * QEMU LoongArch KVM
4537ba9daSTianrui Zhao *
5537ba9daSTianrui Zhao * Copyright (c) 2023 Loongson Technology Corporation Limited
6537ba9daSTianrui Zhao */
7537ba9daSTianrui Zhao
8537ba9daSTianrui Zhao #include "qemu/osdep.h"
9537ba9daSTianrui Zhao #include <sys/ioctl.h>
10537ba9daSTianrui Zhao #include <linux/kvm.h>
11620d9bd0SBibo Mao #include "asm-loongarch/kvm_para.h"
12c23a53d8SBibo Mao #include "qapi/error.h"
13537ba9daSTianrui Zhao #include "qemu/timer.h"
14537ba9daSTianrui Zhao #include "qemu/error-report.h"
15537ba9daSTianrui Zhao #include "qemu/main-loop.h"
1632cad1ffSPhilippe Mathieu-Daudé #include "system/system.h"
1732cad1ffSPhilippe Mathieu-Daudé #include "system/kvm.h"
1832cad1ffSPhilippe Mathieu-Daudé #include "system/kvm_int.h"
19537ba9daSTianrui Zhao #include "hw/pci/pci.h"
20537ba9daSTianrui Zhao #include "exec/memattrs.h"
21dfc56946SRichard Henderson #include "system/address-spaces.h"
22537ba9daSTianrui Zhao #include "hw/boards.h"
23537ba9daSTianrui Zhao #include "hw/irq.h"
24db369c11SBibo Mao #include "hw/loongarch/virt.h"
25537ba9daSTianrui Zhao #include "qemu/log.h"
26537ba9daSTianrui Zhao #include "hw/loader.h"
2732cad1ffSPhilippe Mathieu-Daudé #include "system/runstate.h"
28537ba9daSTianrui Zhao #include "cpu-csr.h"
29537ba9daSTianrui Zhao #include "kvm_loongarch.h"
30f8447436STianrui Zhao #include "trace.h"
31537ba9daSTianrui Zhao
32537ba9daSTianrui Zhao static bool cap_has_mp_state;
33d38e31efSBibo Mao static unsigned int brk_insn;
34537ba9daSTianrui Zhao const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
35537ba9daSTianrui Zhao KVM_CAP_LAST_INFO
36537ba9daSTianrui Zhao };
37537ba9daSTianrui Zhao
kvm_get_stealtime(CPUState * cs)3847b54e15SBibo Mao static int kvm_get_stealtime(CPUState *cs)
3947b54e15SBibo Mao {
4047b54e15SBibo Mao CPULoongArchState *env = cpu_env(cs);
4147b54e15SBibo Mao int err;
4247b54e15SBibo Mao struct kvm_device_attr attr = {
4347b54e15SBibo Mao .group = KVM_LOONGARCH_VCPU_PVTIME_CTRL,
4447b54e15SBibo Mao .attr = KVM_LOONGARCH_VCPU_PVTIME_GPA,
4547b54e15SBibo Mao .addr = (uint64_t)&env->stealtime.guest_addr,
4647b54e15SBibo Mao };
4747b54e15SBibo Mao
4847b54e15SBibo Mao err = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr);
4947b54e15SBibo Mao if (err) {
5047b54e15SBibo Mao return 0;
5147b54e15SBibo Mao }
5247b54e15SBibo Mao
5347b54e15SBibo Mao err = kvm_vcpu_ioctl(cs, KVM_GET_DEVICE_ATTR, attr);
5447b54e15SBibo Mao if (err) {
5547b54e15SBibo Mao error_report("PVTIME: KVM_GET_DEVICE_ATTR: %s", strerror(errno));
5647b54e15SBibo Mao return err;
5747b54e15SBibo Mao }
5847b54e15SBibo Mao
5947b54e15SBibo Mao return 0;
6047b54e15SBibo Mao }
6147b54e15SBibo Mao
kvm_set_stealtime(CPUState * cs)6247b54e15SBibo Mao static int kvm_set_stealtime(CPUState *cs)
6347b54e15SBibo Mao {
6447b54e15SBibo Mao CPULoongArchState *env = cpu_env(cs);
6547b54e15SBibo Mao int err;
6647b54e15SBibo Mao struct kvm_device_attr attr = {
6747b54e15SBibo Mao .group = KVM_LOONGARCH_VCPU_PVTIME_CTRL,
6847b54e15SBibo Mao .attr = KVM_LOONGARCH_VCPU_PVTIME_GPA,
6947b54e15SBibo Mao .addr = (uint64_t)&env->stealtime.guest_addr,
7047b54e15SBibo Mao };
7147b54e15SBibo Mao
7247b54e15SBibo Mao err = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr);
7347b54e15SBibo Mao if (err) {
7447b54e15SBibo Mao return 0;
7547b54e15SBibo Mao }
7647b54e15SBibo Mao
7747b54e15SBibo Mao err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, attr);
7847b54e15SBibo Mao if (err) {
7947b54e15SBibo Mao error_report("PVTIME: KVM_SET_DEVICE_ATTR %s with gpa "TARGET_FMT_lx,
8047b54e15SBibo Mao strerror(errno), env->stealtime.guest_addr);
8147b54e15SBibo Mao return err;
8247b54e15SBibo Mao }
8347b54e15SBibo Mao
8447b54e15SBibo Mao return 0;
8547b54e15SBibo Mao }
8647b54e15SBibo Mao
kvm_set_pv_features(CPUState * cs)872698cc7cSBibo Mao static int kvm_set_pv_features(CPUState *cs)
882698cc7cSBibo Mao {
892698cc7cSBibo Mao CPULoongArchState *env = cpu_env(cs);
902698cc7cSBibo Mao int err;
912698cc7cSBibo Mao uint64_t val;
922698cc7cSBibo Mao struct kvm_device_attr attr = {
932698cc7cSBibo Mao .group = KVM_LOONGARCH_VCPU_CPUCFG,
942698cc7cSBibo Mao .attr = CPUCFG_KVM_FEATURE,
952698cc7cSBibo Mao .addr = (uint64_t)&val,
962698cc7cSBibo Mao };
972698cc7cSBibo Mao
982698cc7cSBibo Mao err = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr);
992698cc7cSBibo Mao if (err) {
1002698cc7cSBibo Mao return 0;
1012698cc7cSBibo Mao }
1022698cc7cSBibo Mao
1032698cc7cSBibo Mao val = env->pv_features;
1042698cc7cSBibo Mao err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, attr);
1052698cc7cSBibo Mao if (err) {
1062698cc7cSBibo Mao error_report("Fail to set pv feature "TARGET_FMT_lx " with error %s",
1072698cc7cSBibo Mao val, strerror(errno));
1082698cc7cSBibo Mao return err;
1092698cc7cSBibo Mao }
1102698cc7cSBibo Mao
1112698cc7cSBibo Mao return 0;
1122698cc7cSBibo Mao }
1132698cc7cSBibo Mao
kvm_loongarch_get_regs_core(CPUState * cs)114f8447436STianrui Zhao static int kvm_loongarch_get_regs_core(CPUState *cs)
115f8447436STianrui Zhao {
116f8447436STianrui Zhao int ret = 0;
117f8447436STianrui Zhao int i;
118f8447436STianrui Zhao struct kvm_regs regs;
119f3b603b9SPhilippe Mathieu-Daudé CPULoongArchState *env = cpu_env(cs);
120f8447436STianrui Zhao
121f8447436STianrui Zhao /* Get the current register set as KVM seems it */
122f8447436STianrui Zhao ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s);
123f8447436STianrui Zhao if (ret < 0) {
124f8447436STianrui Zhao trace_kvm_failed_get_regs_core(strerror(errno));
125f8447436STianrui Zhao return ret;
126f8447436STianrui Zhao }
127f8447436STianrui Zhao /* gpr[0] value is always 0 */
128f8447436STianrui Zhao env->gpr[0] = 0;
129f8447436STianrui Zhao for (i = 1; i < 32; i++) {
130f8447436STianrui Zhao env->gpr[i] = regs.gpr[i];
131f8447436STianrui Zhao }
132f8447436STianrui Zhao
133f8447436STianrui Zhao env->pc = regs.pc;
134f8447436STianrui Zhao return ret;
135f8447436STianrui Zhao }
136f8447436STianrui Zhao
kvm_loongarch_put_regs_core(CPUState * cs)137f8447436STianrui Zhao static int kvm_loongarch_put_regs_core(CPUState *cs)
138f8447436STianrui Zhao {
139f8447436STianrui Zhao int ret = 0;
140f8447436STianrui Zhao int i;
141f8447436STianrui Zhao struct kvm_regs regs;
142f3b603b9SPhilippe Mathieu-Daudé CPULoongArchState *env = cpu_env(cs);
143f8447436STianrui Zhao
144f8447436STianrui Zhao /* Set the registers based on QEMU's view of things */
145f8447436STianrui Zhao for (i = 0; i < 32; i++) {
146f8447436STianrui Zhao regs.gpr[i] = env->gpr[i];
147f8447436STianrui Zhao }
148f8447436STianrui Zhao
149f8447436STianrui Zhao regs.pc = env->pc;
150f8447436STianrui Zhao ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s);
151f8447436STianrui Zhao if (ret < 0) {
152f8447436STianrui Zhao trace_kvm_failed_put_regs_core(strerror(errno));
153f8447436STianrui Zhao }
154f8447436STianrui Zhao
155f8447436STianrui Zhao return ret;
156f8447436STianrui Zhao }
157f8447436STianrui Zhao
kvm_loongarch_get_csr(CPUState * cs)158f8447436STianrui Zhao static int kvm_loongarch_get_csr(CPUState *cs)
159f8447436STianrui Zhao {
160f8447436STianrui Zhao int ret = 0;
161f3b603b9SPhilippe Mathieu-Daudé CPULoongArchState *env = cpu_env(cs);
162f8447436STianrui Zhao
163f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CRMD),
164f8447436STianrui Zhao &env->CSR_CRMD);
165f8447436STianrui Zhao
166f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRMD),
167f8447436STianrui Zhao &env->CSR_PRMD);
168f8447436STianrui Zhao
169f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EUEN),
170f8447436STianrui Zhao &env->CSR_EUEN);
171f8447436STianrui Zhao
172f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MISC),
173f8447436STianrui Zhao &env->CSR_MISC);
174f8447436STianrui Zhao
175f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ECFG),
176f8447436STianrui Zhao &env->CSR_ECFG);
177f8447436STianrui Zhao
178f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ESTAT),
179f8447436STianrui Zhao &env->CSR_ESTAT);
180f8447436STianrui Zhao
181f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ERA),
182f8447436STianrui Zhao &env->CSR_ERA);
183f8447436STianrui Zhao
184f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADV),
185f8447436STianrui Zhao &env->CSR_BADV);
186f8447436STianrui Zhao
187f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADI),
188f8447436STianrui Zhao &env->CSR_BADI);
189f8447436STianrui Zhao
190f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EENTRY),
191f8447436STianrui Zhao &env->CSR_EENTRY);
192f8447436STianrui Zhao
193f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBIDX),
194f8447436STianrui Zhao &env->CSR_TLBIDX);
195f8447436STianrui Zhao
196f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBEHI),
197f8447436STianrui Zhao &env->CSR_TLBEHI);
198f8447436STianrui Zhao
199f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO0),
200f8447436STianrui Zhao &env->CSR_TLBELO0);
201f8447436STianrui Zhao
202f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO1),
203f8447436STianrui Zhao &env->CSR_TLBELO1);
204f8447436STianrui Zhao
205f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ASID),
206f8447436STianrui Zhao &env->CSR_ASID);
207f8447436STianrui Zhao
208f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDL),
209f8447436STianrui Zhao &env->CSR_PGDL);
210f8447436STianrui Zhao
211f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDH),
212f8447436STianrui Zhao &env->CSR_PGDH);
213f8447436STianrui Zhao
214f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGD),
215f8447436STianrui Zhao &env->CSR_PGD);
216f8447436STianrui Zhao
217f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCL),
218f8447436STianrui Zhao &env->CSR_PWCL);
219f8447436STianrui Zhao
220f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCH),
221f8447436STianrui Zhao &env->CSR_PWCH);
222f8447436STianrui Zhao
223f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_STLBPS),
224f8447436STianrui Zhao &env->CSR_STLBPS);
225f8447436STianrui Zhao
226f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_RVACFG),
227f8447436STianrui Zhao &env->CSR_RVACFG);
228f8447436STianrui Zhao
229f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CPUID),
230f8447436STianrui Zhao &env->CSR_CPUID);
231f8447436STianrui Zhao
232f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG1),
233f8447436STianrui Zhao &env->CSR_PRCFG1);
234f8447436STianrui Zhao
235f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG2),
236f8447436STianrui Zhao &env->CSR_PRCFG2);
237f8447436STianrui Zhao
238f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG3),
239f8447436STianrui Zhao &env->CSR_PRCFG3);
240f8447436STianrui Zhao
241f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(0)),
242f8447436STianrui Zhao &env->CSR_SAVE[0]);
243f8447436STianrui Zhao
244f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(1)),
245f8447436STianrui Zhao &env->CSR_SAVE[1]);
246f8447436STianrui Zhao
247f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(2)),
248f8447436STianrui Zhao &env->CSR_SAVE[2]);
249f8447436STianrui Zhao
250f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(3)),
251f8447436STianrui Zhao &env->CSR_SAVE[3]);
252f8447436STianrui Zhao
253f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(4)),
254f8447436STianrui Zhao &env->CSR_SAVE[4]);
255f8447436STianrui Zhao
256f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(5)),
257f8447436STianrui Zhao &env->CSR_SAVE[5]);
258f8447436STianrui Zhao
259f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(6)),
260f8447436STianrui Zhao &env->CSR_SAVE[6]);
261f8447436STianrui Zhao
262f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(7)),
263f8447436STianrui Zhao &env->CSR_SAVE[7]);
264f8447436STianrui Zhao
265f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TID),
266f8447436STianrui Zhao &env->CSR_TID);
267f8447436STianrui Zhao
268f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CNTC),
269f8447436STianrui Zhao &env->CSR_CNTC);
270f8447436STianrui Zhao
271f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TICLR),
272f8447436STianrui Zhao &env->CSR_TICLR);
273f8447436STianrui Zhao
274f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_LLBCTL),
275f8447436STianrui Zhao &env->CSR_LLBCTL);
276f8447436STianrui Zhao
277f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL1),
278f8447436STianrui Zhao &env->CSR_IMPCTL1);
279f8447436STianrui Zhao
280f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL2),
281f8447436STianrui Zhao &env->CSR_IMPCTL2);
282f8447436STianrui Zhao
283f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRENTRY),
284f8447436STianrui Zhao &env->CSR_TLBRENTRY);
285f8447436STianrui Zhao
286f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRBADV),
287f8447436STianrui Zhao &env->CSR_TLBRBADV);
288f8447436STianrui Zhao
289f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRERA),
290f8447436STianrui Zhao &env->CSR_TLBRERA);
291f8447436STianrui Zhao
292f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRSAVE),
293f8447436STianrui Zhao &env->CSR_TLBRSAVE);
294f8447436STianrui Zhao
295f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO0),
296f8447436STianrui Zhao &env->CSR_TLBRELO0);
297f8447436STianrui Zhao
298f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO1),
299f8447436STianrui Zhao &env->CSR_TLBRELO1);
300f8447436STianrui Zhao
301f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBREHI),
302f8447436STianrui Zhao &env->CSR_TLBREHI);
303f8447436STianrui Zhao
304f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRPRMD),
305f8447436STianrui Zhao &env->CSR_TLBRPRMD);
306f8447436STianrui Zhao
307f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(0)),
308f8447436STianrui Zhao &env->CSR_DMW[0]);
309f8447436STianrui Zhao
310f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(1)),
311f8447436STianrui Zhao &env->CSR_DMW[1]);
312f8447436STianrui Zhao
313f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(2)),
314f8447436STianrui Zhao &env->CSR_DMW[2]);
315f8447436STianrui Zhao
316f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(3)),
317f8447436STianrui Zhao &env->CSR_DMW[3]);
318f8447436STianrui Zhao
319f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TVAL),
320f8447436STianrui Zhao &env->CSR_TVAL);
321f8447436STianrui Zhao
322f8447436STianrui Zhao ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TCFG),
323f8447436STianrui Zhao &env->CSR_TCFG);
324f8447436STianrui Zhao
325f8447436STianrui Zhao return ret;
326f8447436STianrui Zhao }
327f8447436STianrui Zhao
kvm_loongarch_put_csr(CPUState * cs,int level)32861f6e150SBibo Mao static int kvm_loongarch_put_csr(CPUState *cs, int level)
329f8447436STianrui Zhao {
330f8447436STianrui Zhao int ret = 0;
331f3b603b9SPhilippe Mathieu-Daudé CPULoongArchState *env = cpu_env(cs);
332f8447436STianrui Zhao
333f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CRMD),
334f8447436STianrui Zhao &env->CSR_CRMD);
335f8447436STianrui Zhao
336f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRMD),
337f8447436STianrui Zhao &env->CSR_PRMD);
338f8447436STianrui Zhao
339f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EUEN),
340f8447436STianrui Zhao &env->CSR_EUEN);
341f8447436STianrui Zhao
342f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MISC),
343f8447436STianrui Zhao &env->CSR_MISC);
344f8447436STianrui Zhao
345f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ECFG),
346f8447436STianrui Zhao &env->CSR_ECFG);
347f8447436STianrui Zhao
348f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ESTAT),
349f8447436STianrui Zhao &env->CSR_ESTAT);
350f8447436STianrui Zhao
351f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ERA),
352f8447436STianrui Zhao &env->CSR_ERA);
353f8447436STianrui Zhao
354f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADV),
355f8447436STianrui Zhao &env->CSR_BADV);
356f8447436STianrui Zhao
357f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADI),
358f8447436STianrui Zhao &env->CSR_BADI);
359f8447436STianrui Zhao
360f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EENTRY),
361f8447436STianrui Zhao &env->CSR_EENTRY);
362f8447436STianrui Zhao
363f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBIDX),
364f8447436STianrui Zhao &env->CSR_TLBIDX);
365f8447436STianrui Zhao
366f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBEHI),
367f8447436STianrui Zhao &env->CSR_TLBEHI);
368f8447436STianrui Zhao
369f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO0),
370f8447436STianrui Zhao &env->CSR_TLBELO0);
371f8447436STianrui Zhao
372f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO1),
373f8447436STianrui Zhao &env->CSR_TLBELO1);
374f8447436STianrui Zhao
375f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ASID),
376f8447436STianrui Zhao &env->CSR_ASID);
377f8447436STianrui Zhao
378f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDL),
379f8447436STianrui Zhao &env->CSR_PGDL);
380f8447436STianrui Zhao
381f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDH),
382f8447436STianrui Zhao &env->CSR_PGDH);
383f8447436STianrui Zhao
384f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGD),
385f8447436STianrui Zhao &env->CSR_PGD);
386f8447436STianrui Zhao
387f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCL),
388f8447436STianrui Zhao &env->CSR_PWCL);
389f8447436STianrui Zhao
390f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCH),
391f8447436STianrui Zhao &env->CSR_PWCH);
392f8447436STianrui Zhao
393f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_STLBPS),
394f8447436STianrui Zhao &env->CSR_STLBPS);
395f8447436STianrui Zhao
396f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_RVACFG),
397f8447436STianrui Zhao &env->CSR_RVACFG);
398f8447436STianrui Zhao
39961f6e150SBibo Mao /* CPUID is constant after poweron, it should be set only once */
40061f6e150SBibo Mao if (level >= KVM_PUT_FULL_STATE) {
401f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CPUID),
402f8447436STianrui Zhao &env->CSR_CPUID);
40361f6e150SBibo Mao }
404f8447436STianrui Zhao
405f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG1),
406f8447436STianrui Zhao &env->CSR_PRCFG1);
407f8447436STianrui Zhao
408f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG2),
409f8447436STianrui Zhao &env->CSR_PRCFG2);
410f8447436STianrui Zhao
411f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG3),
412f8447436STianrui Zhao &env->CSR_PRCFG3);
413f8447436STianrui Zhao
414f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(0)),
415f8447436STianrui Zhao &env->CSR_SAVE[0]);
416f8447436STianrui Zhao
417f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(1)),
418f8447436STianrui Zhao &env->CSR_SAVE[1]);
419f8447436STianrui Zhao
420f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(2)),
421f8447436STianrui Zhao &env->CSR_SAVE[2]);
422f8447436STianrui Zhao
423f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(3)),
424f8447436STianrui Zhao &env->CSR_SAVE[3]);
425f8447436STianrui Zhao
426f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(4)),
427f8447436STianrui Zhao &env->CSR_SAVE[4]);
428f8447436STianrui Zhao
429f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(5)),
430f8447436STianrui Zhao &env->CSR_SAVE[5]);
431f8447436STianrui Zhao
432f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(6)),
433f8447436STianrui Zhao &env->CSR_SAVE[6]);
434f8447436STianrui Zhao
435f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(7)),
436f8447436STianrui Zhao &env->CSR_SAVE[7]);
437f8447436STianrui Zhao
438f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TID),
439f8447436STianrui Zhao &env->CSR_TID);
440f8447436STianrui Zhao
441f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CNTC),
442f8447436STianrui Zhao &env->CSR_CNTC);
443f8447436STianrui Zhao
444f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TICLR),
445f8447436STianrui Zhao &env->CSR_TICLR);
446f8447436STianrui Zhao
447f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_LLBCTL),
448f8447436STianrui Zhao &env->CSR_LLBCTL);
449f8447436STianrui Zhao
450f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL1),
451f8447436STianrui Zhao &env->CSR_IMPCTL1);
452f8447436STianrui Zhao
453f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL2),
454f8447436STianrui Zhao &env->CSR_IMPCTL2);
455f8447436STianrui Zhao
456f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRENTRY),
457f8447436STianrui Zhao &env->CSR_TLBRENTRY);
458f8447436STianrui Zhao
459f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRBADV),
460f8447436STianrui Zhao &env->CSR_TLBRBADV);
461f8447436STianrui Zhao
462f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRERA),
463f8447436STianrui Zhao &env->CSR_TLBRERA);
464f8447436STianrui Zhao
465f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRSAVE),
466f8447436STianrui Zhao &env->CSR_TLBRSAVE);
467f8447436STianrui Zhao
468f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO0),
469f8447436STianrui Zhao &env->CSR_TLBRELO0);
470f8447436STianrui Zhao
471f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO1),
472f8447436STianrui Zhao &env->CSR_TLBRELO1);
473f8447436STianrui Zhao
474f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBREHI),
475f8447436STianrui Zhao &env->CSR_TLBREHI);
476f8447436STianrui Zhao
477f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRPRMD),
478f8447436STianrui Zhao &env->CSR_TLBRPRMD);
479f8447436STianrui Zhao
480f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(0)),
481f8447436STianrui Zhao &env->CSR_DMW[0]);
482f8447436STianrui Zhao
483f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(1)),
484f8447436STianrui Zhao &env->CSR_DMW[1]);
485f8447436STianrui Zhao
486f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(2)),
487f8447436STianrui Zhao &env->CSR_DMW[2]);
488f8447436STianrui Zhao
489f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(3)),
490f8447436STianrui Zhao &env->CSR_DMW[3]);
491f8447436STianrui Zhao /*
492f8447436STianrui Zhao * timer cfg must be put at last since it is used to enable
493f8447436STianrui Zhao * guest timer
494f8447436STianrui Zhao */
495f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TVAL),
496f8447436STianrui Zhao &env->CSR_TVAL);
497f8447436STianrui Zhao
498f8447436STianrui Zhao ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TCFG),
499f8447436STianrui Zhao &env->CSR_TCFG);
500f8447436STianrui Zhao return ret;
501f8447436STianrui Zhao }
502f8447436STianrui Zhao
kvm_loongarch_get_regs_fp(CPUState * cs)503f8447436STianrui Zhao static int kvm_loongarch_get_regs_fp(CPUState *cs)
504f8447436STianrui Zhao {
505f8447436STianrui Zhao int ret, i;
506f8447436STianrui Zhao struct kvm_fpu fpu;
507f3b603b9SPhilippe Mathieu-Daudé CPULoongArchState *env = cpu_env(cs);
508f8447436STianrui Zhao
509f8447436STianrui Zhao ret = kvm_vcpu_ioctl(cs, KVM_GET_FPU, &fpu);
510f8447436STianrui Zhao if (ret < 0) {
511f8447436STianrui Zhao trace_kvm_failed_get_fpu(strerror(errno));
512f8447436STianrui Zhao return ret;
513f8447436STianrui Zhao }
514f8447436STianrui Zhao
515f8447436STianrui Zhao env->fcsr0 = fpu.fcsr;
516f8447436STianrui Zhao for (i = 0; i < 32; i++) {
517f8447436STianrui Zhao env->fpr[i].vreg.UD[0] = fpu.fpr[i].val64[0];
51807c08661SSong Gao env->fpr[i].vreg.UD[1] = fpu.fpr[i].val64[1];
51907c08661SSong Gao env->fpr[i].vreg.UD[2] = fpu.fpr[i].val64[2];
52007c08661SSong Gao env->fpr[i].vreg.UD[3] = fpu.fpr[i].val64[3];
521f8447436STianrui Zhao }
522f8447436STianrui Zhao for (i = 0; i < 8; i++) {
523f8447436STianrui Zhao env->cf[i] = fpu.fcc & 0xFF;
524f8447436STianrui Zhao fpu.fcc = fpu.fcc >> 8;
525f8447436STianrui Zhao }
526f8447436STianrui Zhao
527f8447436STianrui Zhao return ret;
528f8447436STianrui Zhao }
529f8447436STianrui Zhao
kvm_loongarch_put_regs_fp(CPUState * cs)530f8447436STianrui Zhao static int kvm_loongarch_put_regs_fp(CPUState *cs)
531f8447436STianrui Zhao {
532f8447436STianrui Zhao int ret, i;
533f8447436STianrui Zhao struct kvm_fpu fpu;
534f3b603b9SPhilippe Mathieu-Daudé CPULoongArchState *env = cpu_env(cs);
535f8447436STianrui Zhao
536f8447436STianrui Zhao fpu.fcsr = env->fcsr0;
537f8447436STianrui Zhao fpu.fcc = 0;
538f8447436STianrui Zhao for (i = 0; i < 32; i++) {
539f8447436STianrui Zhao fpu.fpr[i].val64[0] = env->fpr[i].vreg.UD[0];
54007c08661SSong Gao fpu.fpr[i].val64[1] = env->fpr[i].vreg.UD[1];
54107c08661SSong Gao fpu.fpr[i].val64[2] = env->fpr[i].vreg.UD[2];
54207c08661SSong Gao fpu.fpr[i].val64[3] = env->fpr[i].vreg.UD[3];
543f8447436STianrui Zhao }
544f8447436STianrui Zhao
545f8447436STianrui Zhao for (i = 0; i < 8; i++) {
546f8447436STianrui Zhao fpu.fcc |= env->cf[i] << (8 * i);
547f8447436STianrui Zhao }
548f8447436STianrui Zhao
549f8447436STianrui Zhao ret = kvm_vcpu_ioctl(cs, KVM_SET_FPU, &fpu);
550f8447436STianrui Zhao if (ret < 0) {
551f8447436STianrui Zhao trace_kvm_failed_put_fpu(strerror(errno));
552f8447436STianrui Zhao }
553f8447436STianrui Zhao
554f8447436STianrui Zhao return ret;
555f8447436STianrui Zhao }
556f8447436STianrui Zhao
kvm_loongarch_put_lbt(CPUState * cs)557a45df286SBibo Mao static int kvm_loongarch_put_lbt(CPUState *cs)
558a45df286SBibo Mao {
559a45df286SBibo Mao CPULoongArchState *env = cpu_env(cs);
560a45df286SBibo Mao uint64_t val;
561a45df286SBibo Mao int ret;
562a45df286SBibo Mao
563a45df286SBibo Mao /* check whether vm support LBT firstly */
564a45df286SBibo Mao if (FIELD_EX32(env->cpucfg[2], CPUCFG2, LBT_ALL) != 7) {
565a45df286SBibo Mao return 0;
566a45df286SBibo Mao }
567a45df286SBibo Mao
568a45df286SBibo Mao /* set six LBT registers including scr0-scr3, eflags, ftop */
569a45df286SBibo Mao ret = kvm_set_one_reg(cs, KVM_REG_LOONGARCH_LBT_SCR0, &env->lbt.scr0);
570a45df286SBibo Mao ret |= kvm_set_one_reg(cs, KVM_REG_LOONGARCH_LBT_SCR1, &env->lbt.scr1);
571a45df286SBibo Mao ret |= kvm_set_one_reg(cs, KVM_REG_LOONGARCH_LBT_SCR2, &env->lbt.scr2);
572a45df286SBibo Mao ret |= kvm_set_one_reg(cs, KVM_REG_LOONGARCH_LBT_SCR3, &env->lbt.scr3);
573a45df286SBibo Mao /*
574a45df286SBibo Mao * Be cautious, KVM_REG_LOONGARCH_LBT_FTOP is defined as 64-bit however
575a45df286SBibo Mao * lbt.ftop is 32-bit; the same with KVM_REG_LOONGARCH_LBT_EFLAGS register
576a45df286SBibo Mao */
577a45df286SBibo Mao val = env->lbt.eflags;
578a45df286SBibo Mao ret |= kvm_set_one_reg(cs, KVM_REG_LOONGARCH_LBT_EFLAGS, &val);
579a45df286SBibo Mao val = env->lbt.ftop;
580a45df286SBibo Mao ret |= kvm_set_one_reg(cs, KVM_REG_LOONGARCH_LBT_FTOP, &val);
581a45df286SBibo Mao
582a45df286SBibo Mao return ret;
583a45df286SBibo Mao }
584a45df286SBibo Mao
kvm_loongarch_get_lbt(CPUState * cs)585a45df286SBibo Mao static int kvm_loongarch_get_lbt(CPUState *cs)
586a45df286SBibo Mao {
587a45df286SBibo Mao CPULoongArchState *env = cpu_env(cs);
588a45df286SBibo Mao uint64_t val;
589a45df286SBibo Mao int ret;
590a45df286SBibo Mao
591a45df286SBibo Mao /* check whether vm support LBT firstly */
592a45df286SBibo Mao if (FIELD_EX32(env->cpucfg[2], CPUCFG2, LBT_ALL) != 7) {
593a45df286SBibo Mao return 0;
594a45df286SBibo Mao }
595a45df286SBibo Mao
596a45df286SBibo Mao /* get six LBT registers including scr0-scr3, eflags, ftop */
597a45df286SBibo Mao ret = kvm_get_one_reg(cs, KVM_REG_LOONGARCH_LBT_SCR0, &env->lbt.scr0);
598a45df286SBibo Mao ret |= kvm_get_one_reg(cs, KVM_REG_LOONGARCH_LBT_SCR1, &env->lbt.scr1);
599a45df286SBibo Mao ret |= kvm_get_one_reg(cs, KVM_REG_LOONGARCH_LBT_SCR2, &env->lbt.scr2);
600a45df286SBibo Mao ret |= kvm_get_one_reg(cs, KVM_REG_LOONGARCH_LBT_SCR3, &env->lbt.scr3);
601a45df286SBibo Mao ret |= kvm_get_one_reg(cs, KVM_REG_LOONGARCH_LBT_EFLAGS, &val);
602a45df286SBibo Mao env->lbt.eflags = (uint32_t)val;
603a45df286SBibo Mao ret |= kvm_get_one_reg(cs, KVM_REG_LOONGARCH_LBT_FTOP, &val);
604a45df286SBibo Mao env->lbt.ftop = (uint32_t)val;
605a45df286SBibo Mao
606a45df286SBibo Mao return ret;
607a45df286SBibo Mao }
608a45df286SBibo Mao
kvm_arch_reset_vcpu(CPUState * cs)609a724f5a8SBibo Mao void kvm_arch_reset_vcpu(CPUState *cs)
610f8447436STianrui Zhao {
611a724f5a8SBibo Mao CPULoongArchState *env = cpu_env(cs);
612b61b9d89SXianglai Li int ret = 0;
613b61b9d89SXianglai Li uint64_t unused = 0;
614a724f5a8SBibo Mao
615f8447436STianrui Zhao env->mp_state = KVM_MP_STATE_RUNNABLE;
616b61b9d89SXianglai Li ret = kvm_set_one_reg(cs, KVM_REG_LOONGARCH_VCPU_RESET, &unused);
617b61b9d89SXianglai Li if (ret) {
618b61b9d89SXianglai Li error_report("Failed to set KVM_REG_LOONGARCH_VCPU_RESET: %s",
619b61b9d89SXianglai Li strerror(errno));
620b61b9d89SXianglai Li exit(EXIT_FAILURE);
621b61b9d89SXianglai Li }
622f8447436STianrui Zhao }
623f8447436STianrui Zhao
kvm_loongarch_get_mpstate(CPUState * cs)624f8447436STianrui Zhao static int kvm_loongarch_get_mpstate(CPUState *cs)
625f8447436STianrui Zhao {
626f8447436STianrui Zhao int ret = 0;
627f8447436STianrui Zhao struct kvm_mp_state mp_state;
628f3b603b9SPhilippe Mathieu-Daudé CPULoongArchState *env = cpu_env(cs);
629f8447436STianrui Zhao
630f8447436STianrui Zhao if (cap_has_mp_state) {
631f8447436STianrui Zhao ret = kvm_vcpu_ioctl(cs, KVM_GET_MP_STATE, &mp_state);
632f8447436STianrui Zhao if (ret) {
633f8447436STianrui Zhao trace_kvm_failed_get_mpstate(strerror(errno));
634f8447436STianrui Zhao return ret;
635f8447436STianrui Zhao }
636f8447436STianrui Zhao env->mp_state = mp_state.mp_state;
637f8447436STianrui Zhao }
638f8447436STianrui Zhao
639f8447436STianrui Zhao return ret;
640f8447436STianrui Zhao }
641f8447436STianrui Zhao
kvm_loongarch_put_mpstate(CPUState * cs)642f8447436STianrui Zhao static int kvm_loongarch_put_mpstate(CPUState *cs)
643f8447436STianrui Zhao {
644f8447436STianrui Zhao int ret = 0;
645f8447436STianrui Zhao struct kvm_mp_state mp_state = {
646f3b603b9SPhilippe Mathieu-Daudé .mp_state = cpu_env(cs)->mp_state
647f8447436STianrui Zhao };
648f8447436STianrui Zhao
649f8447436STianrui Zhao if (cap_has_mp_state) {
650f8447436STianrui Zhao ret = kvm_vcpu_ioctl(cs, KVM_SET_MP_STATE, &mp_state);
651f8447436STianrui Zhao if (ret) {
652f8447436STianrui Zhao trace_kvm_failed_put_mpstate(strerror(errno));
653f8447436STianrui Zhao }
654f8447436STianrui Zhao }
655f8447436STianrui Zhao
656f8447436STianrui Zhao return ret;
657f8447436STianrui Zhao }
658f8447436STianrui Zhao
kvm_loongarch_get_cpucfg(CPUState * cs)659f8447436STianrui Zhao static int kvm_loongarch_get_cpucfg(CPUState *cs)
660f8447436STianrui Zhao {
661f8447436STianrui Zhao int i, ret = 0;
662f8447436STianrui Zhao uint64_t val;
663f3b603b9SPhilippe Mathieu-Daudé CPULoongArchState *env = cpu_env(cs);
664f8447436STianrui Zhao
665f8447436STianrui Zhao for (i = 0; i < 21; i++) {
666f8447436STianrui Zhao ret = kvm_get_one_reg(cs, KVM_IOC_CPUCFG(i), &val);
667f8447436STianrui Zhao if (ret < 0) {
668f8447436STianrui Zhao trace_kvm_failed_get_cpucfg(strerror(errno));
669f8447436STianrui Zhao }
670f8447436STianrui Zhao env->cpucfg[i] = (uint32_t)val;
671f8447436STianrui Zhao }
672f8447436STianrui Zhao return ret;
673f8447436STianrui Zhao }
674f8447436STianrui Zhao
kvm_check_cpucfg2(CPUState * cs)675fc700996SSong Gao static int kvm_check_cpucfg2(CPUState *cs)
676fc700996SSong Gao {
677fc700996SSong Gao int ret;
678fc700996SSong Gao uint64_t val;
679fc700996SSong Gao struct kvm_device_attr attr = {
680fc700996SSong Gao .group = KVM_LOONGARCH_VCPU_CPUCFG,
681fc700996SSong Gao .attr = 2,
682fc700996SSong Gao .addr = (uint64_t)&val,
683fc700996SSong Gao };
684f3b603b9SPhilippe Mathieu-Daudé CPULoongArchState *env = cpu_env(cs);
685fc700996SSong Gao
686fc700996SSong Gao ret = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, &attr);
687fc700996SSong Gao
688fc700996SSong Gao if (!ret) {
689fc700996SSong Gao kvm_vcpu_ioctl(cs, KVM_GET_DEVICE_ATTR, &attr);
690fc700996SSong Gao env->cpucfg[2] &= val;
691fc700996SSong Gao
692fc700996SSong Gao if (FIELD_EX32(env->cpucfg[2], CPUCFG2, FP)) {
693fc700996SSong Gao /* The FP minimal version is 1. */
694fc700996SSong Gao env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, FP_VER, 1);
695fc700996SSong Gao }
696fc700996SSong Gao
697fc700996SSong Gao if (FIELD_EX32(env->cpucfg[2], CPUCFG2, LLFTP)) {
698fc700996SSong Gao /* The LLFTP minimal version is 1. */
699fc700996SSong Gao env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LLFTP_VER, 1);
700fc700996SSong Gao }
701fc700996SSong Gao }
702fc700996SSong Gao
703fc700996SSong Gao return ret;
704fc700996SSong Gao }
705fc700996SSong Gao
kvm_loongarch_put_cpucfg(CPUState * cs)706f8447436STianrui Zhao static int kvm_loongarch_put_cpucfg(CPUState *cs)
707f8447436STianrui Zhao {
708f8447436STianrui Zhao int i, ret = 0;
709f3b603b9SPhilippe Mathieu-Daudé CPULoongArchState *env = cpu_env(cs);
710f8447436STianrui Zhao uint64_t val;
711f8447436STianrui Zhao
712f8447436STianrui Zhao for (i = 0; i < 21; i++) {
713f8447436STianrui Zhao if (i == 2) {
714fc700996SSong Gao ret = kvm_check_cpucfg2(cs);
715fc700996SSong Gao if (ret) {
716fc700996SSong Gao return ret;
717f8447436STianrui Zhao }
718fc700996SSong Gao }
719fc700996SSong Gao val = env->cpucfg[i];
720f8447436STianrui Zhao ret = kvm_set_one_reg(cs, KVM_IOC_CPUCFG(i), &val);
721f8447436STianrui Zhao if (ret < 0) {
722f8447436STianrui Zhao trace_kvm_failed_put_cpucfg(strerror(errno));
723f8447436STianrui Zhao }
724f8447436STianrui Zhao }
725f8447436STianrui Zhao return ret;
726f8447436STianrui Zhao }
727f8447436STianrui Zhao
kvm_arch_get_registers(CPUState * cs,Error ** errp)728a1676bb3SJulia Suvorova int kvm_arch_get_registers(CPUState *cs, Error **errp)
729537ba9daSTianrui Zhao {
730f8447436STianrui Zhao int ret;
731f8447436STianrui Zhao
732f8447436STianrui Zhao ret = kvm_loongarch_get_regs_core(cs);
733f8447436STianrui Zhao if (ret) {
734f8447436STianrui Zhao return ret;
735537ba9daSTianrui Zhao }
736f8447436STianrui Zhao
7375872966dSBibo Mao ret = kvm_loongarch_get_cpucfg(cs);
7385872966dSBibo Mao if (ret) {
7395872966dSBibo Mao return ret;
7405872966dSBibo Mao }
7415872966dSBibo Mao
742f8447436STianrui Zhao ret = kvm_loongarch_get_csr(cs);
743f8447436STianrui Zhao if (ret) {
744f8447436STianrui Zhao return ret;
745f8447436STianrui Zhao }
746f8447436STianrui Zhao
747f8447436STianrui Zhao ret = kvm_loongarch_get_regs_fp(cs);
748f8447436STianrui Zhao if (ret) {
749f8447436STianrui Zhao return ret;
750f8447436STianrui Zhao }
751f8447436STianrui Zhao
752a45df286SBibo Mao ret = kvm_loongarch_get_lbt(cs);
753a45df286SBibo Mao if (ret) {
754a45df286SBibo Mao return ret;
755a45df286SBibo Mao }
756a45df286SBibo Mao
75747b54e15SBibo Mao ret = kvm_get_stealtime(cs);
75847b54e15SBibo Mao if (ret) {
75947b54e15SBibo Mao return ret;
76047b54e15SBibo Mao }
76147b54e15SBibo Mao
762f8447436STianrui Zhao ret = kvm_loongarch_get_mpstate(cs);
763f8447436STianrui Zhao return ret;
764f8447436STianrui Zhao }
765f8447436STianrui Zhao
kvm_arch_put_registers(CPUState * cs,int level,Error ** errp)766a1676bb3SJulia Suvorova int kvm_arch_put_registers(CPUState *cs, int level, Error **errp)
767537ba9daSTianrui Zhao {
768f8447436STianrui Zhao int ret;
7692698cc7cSBibo Mao static int once;
770f8447436STianrui Zhao
771f8447436STianrui Zhao ret = kvm_loongarch_put_regs_core(cs);
772f8447436STianrui Zhao if (ret) {
773f8447436STianrui Zhao return ret;
774f8447436STianrui Zhao }
775f8447436STianrui Zhao
7765872966dSBibo Mao ret = kvm_loongarch_put_cpucfg(cs);
7775872966dSBibo Mao if (ret) {
7785872966dSBibo Mao return ret;
7795872966dSBibo Mao }
7805872966dSBibo Mao
78161f6e150SBibo Mao ret = kvm_loongarch_put_csr(cs, level);
782f8447436STianrui Zhao if (ret) {
783f8447436STianrui Zhao return ret;
784f8447436STianrui Zhao }
785f8447436STianrui Zhao
786f8447436STianrui Zhao ret = kvm_loongarch_put_regs_fp(cs);
787f8447436STianrui Zhao if (ret) {
788f8447436STianrui Zhao return ret;
789f8447436STianrui Zhao }
790f8447436STianrui Zhao
791a45df286SBibo Mao ret = kvm_loongarch_put_lbt(cs);
792a45df286SBibo Mao if (ret) {
793a45df286SBibo Mao return ret;
794a45df286SBibo Mao }
795a45df286SBibo Mao
7962698cc7cSBibo Mao if (!once) {
7972698cc7cSBibo Mao ret = kvm_set_pv_features(cs);
7982698cc7cSBibo Mao if (ret) {
7992698cc7cSBibo Mao return ret;
8002698cc7cSBibo Mao }
8012698cc7cSBibo Mao once = 1;
8022698cc7cSBibo Mao }
8032698cc7cSBibo Mao
80447b54e15SBibo Mao if (level >= KVM_PUT_FULL_STATE) {
80547b54e15SBibo Mao /*
80647b54e15SBibo Mao * only KVM_PUT_FULL_STATE is required, kvm kernel will clear
80747b54e15SBibo Mao * guest_addr for KVM_PUT_RESET_STATE
80847b54e15SBibo Mao */
80947b54e15SBibo Mao ret = kvm_set_stealtime(cs);
81047b54e15SBibo Mao if (ret) {
81147b54e15SBibo Mao return ret;
81247b54e15SBibo Mao }
81347b54e15SBibo Mao }
81447b54e15SBibo Mao
815f8447436STianrui Zhao ret = kvm_loongarch_put_mpstate(cs);
816f8447436STianrui Zhao return ret;
817537ba9daSTianrui Zhao }
818537ba9daSTianrui Zhao
kvm_loongarch_vm_stage_change(void * opaque,bool running,RunState state)819d11681c9STianrui Zhao static void kvm_loongarch_vm_stage_change(void *opaque, bool running,
820d11681c9STianrui Zhao RunState state)
821d11681c9STianrui Zhao {
822d11681c9STianrui Zhao int ret;
823d11681c9STianrui Zhao CPUState *cs = opaque;
824d11681c9STianrui Zhao LoongArchCPU *cpu = LOONGARCH_CPU(cs);
825d11681c9STianrui Zhao
826d11681c9STianrui Zhao if (running) {
827d11681c9STianrui Zhao ret = kvm_set_one_reg(cs, KVM_REG_LOONGARCH_COUNTER,
828d11681c9STianrui Zhao &cpu->kvm_state_counter);
829d11681c9STianrui Zhao if (ret < 0) {
830d11681c9STianrui Zhao trace_kvm_failed_put_counter(strerror(errno));
831d11681c9STianrui Zhao }
832d11681c9STianrui Zhao } else {
833d11681c9STianrui Zhao ret = kvm_get_one_reg(cs, KVM_REG_LOONGARCH_COUNTER,
834d11681c9STianrui Zhao &cpu->kvm_state_counter);
835d11681c9STianrui Zhao if (ret < 0) {
836d11681c9STianrui Zhao trace_kvm_failed_get_counter(strerror(errno));
837d11681c9STianrui Zhao }
838d11681c9STianrui Zhao }
839d11681c9STianrui Zhao }
840d11681c9STianrui Zhao
kvm_feature_supported(CPUState * cs,enum loongarch_features feature)841c23a53d8SBibo Mao static bool kvm_feature_supported(CPUState *cs, enum loongarch_features feature)
842c23a53d8SBibo Mao {
843c23a53d8SBibo Mao int ret;
844c23a53d8SBibo Mao struct kvm_device_attr attr;
845936c3f4dSBibo Mao uint64_t val;
846c23a53d8SBibo Mao
847c23a53d8SBibo Mao switch (feature) {
848936c3f4dSBibo Mao case LOONGARCH_FEATURE_LSX:
849936c3f4dSBibo Mao attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
850936c3f4dSBibo Mao attr.attr = KVM_LOONGARCH_VM_FEAT_LSX;
851936c3f4dSBibo Mao ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
852936c3f4dSBibo Mao if (ret == 0) {
853936c3f4dSBibo Mao return true;
854936c3f4dSBibo Mao }
855936c3f4dSBibo Mao
856936c3f4dSBibo Mao /* Fallback to old kernel detect interface */
857936c3f4dSBibo Mao val = 0;
858936c3f4dSBibo Mao attr.group = KVM_LOONGARCH_VCPU_CPUCFG;
859936c3f4dSBibo Mao /* Cpucfg2 */
860936c3f4dSBibo Mao attr.attr = 2;
861936c3f4dSBibo Mao attr.addr = (uint64_t)&val;
862936c3f4dSBibo Mao ret = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, &attr);
863936c3f4dSBibo Mao if (!ret) {
864936c3f4dSBibo Mao ret = kvm_vcpu_ioctl(cs, KVM_GET_DEVICE_ATTR, &attr);
865936c3f4dSBibo Mao if (ret) {
866936c3f4dSBibo Mao return false;
867936c3f4dSBibo Mao }
868936c3f4dSBibo Mao
869936c3f4dSBibo Mao ret = FIELD_EX32((uint32_t)val, CPUCFG2, LSX);
870936c3f4dSBibo Mao return (ret != 0);
871936c3f4dSBibo Mao }
872936c3f4dSBibo Mao return false;
873936c3f4dSBibo Mao
8745e360dabSBibo Mao case LOONGARCH_FEATURE_LASX:
8755e360dabSBibo Mao attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
8765e360dabSBibo Mao attr.attr = KVM_LOONGARCH_VM_FEAT_LASX;
8775e360dabSBibo Mao ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
8785e360dabSBibo Mao if (ret == 0) {
8795e360dabSBibo Mao return true;
8805e360dabSBibo Mao }
8815e360dabSBibo Mao
8825e360dabSBibo Mao /* Fallback to old kernel detect interface */
8835e360dabSBibo Mao val = 0;
8845e360dabSBibo Mao attr.group = KVM_LOONGARCH_VCPU_CPUCFG;
8855e360dabSBibo Mao /* Cpucfg2 */
8865e360dabSBibo Mao attr.attr = 2;
8875e360dabSBibo Mao attr.addr = (uint64_t)&val;
8885e360dabSBibo Mao ret = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, &attr);
8895e360dabSBibo Mao if (!ret) {
8905e360dabSBibo Mao ret = kvm_vcpu_ioctl(cs, KVM_GET_DEVICE_ATTR, &attr);
8915e360dabSBibo Mao if (ret) {
8925e360dabSBibo Mao return false;
8935e360dabSBibo Mao }
8945e360dabSBibo Mao
8955e360dabSBibo Mao ret = FIELD_EX32((uint32_t)val, CPUCFG2, LASX);
8965e360dabSBibo Mao return (ret != 0);
8975e360dabSBibo Mao }
8985e360dabSBibo Mao return false;
8995e360dabSBibo Mao
900c23a53d8SBibo Mao case LOONGARCH_FEATURE_LBT:
901c23a53d8SBibo Mao /*
902c23a53d8SBibo Mao * Return all if all the LBT features are supported such as:
903c23a53d8SBibo Mao * KVM_LOONGARCH_VM_FEAT_X86BT
904c23a53d8SBibo Mao * KVM_LOONGARCH_VM_FEAT_ARMBT
905c23a53d8SBibo Mao * KVM_LOONGARCH_VM_FEAT_MIPSBT
906c23a53d8SBibo Mao */
907c23a53d8SBibo Mao attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
908c23a53d8SBibo Mao attr.attr = KVM_LOONGARCH_VM_FEAT_X86BT;
909c23a53d8SBibo Mao ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
910c23a53d8SBibo Mao attr.attr = KVM_LOONGARCH_VM_FEAT_ARMBT;
911c23a53d8SBibo Mao ret |= kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
912c23a53d8SBibo Mao attr.attr = KVM_LOONGARCH_VM_FEAT_MIPSBT;
913c23a53d8SBibo Mao ret |= kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
914c23a53d8SBibo Mao return (ret == 0);
9156edd2a9bSBibo Mao
9166edd2a9bSBibo Mao case LOONGARCH_FEATURE_PMU:
9176edd2a9bSBibo Mao attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
9186edd2a9bSBibo Mao attr.attr = KVM_LOONGARCH_VM_FEAT_PMU;
9196edd2a9bSBibo Mao ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
9206edd2a9bSBibo Mao return (ret == 0);
9216edd2a9bSBibo Mao
922620d9bd0SBibo Mao case LOONGARCH_FEATURE_PV_IPI:
923620d9bd0SBibo Mao attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
924620d9bd0SBibo Mao attr.attr = KVM_LOONGARCH_VM_FEAT_PV_IPI;
925620d9bd0SBibo Mao ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
926620d9bd0SBibo Mao return (ret == 0);
927620d9bd0SBibo Mao
928954cc5c3SBibo Mao case LOONGARCH_FEATURE_STEALTIME:
929954cc5c3SBibo Mao attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
930954cc5c3SBibo Mao attr.attr = KVM_LOONGARCH_VM_FEAT_PV_STEALTIME;
931954cc5c3SBibo Mao ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
932954cc5c3SBibo Mao return (ret == 0);
933954cc5c3SBibo Mao
934c23a53d8SBibo Mao default:
935c23a53d8SBibo Mao return false;
936c23a53d8SBibo Mao }
9376edd2a9bSBibo Mao
9386edd2a9bSBibo Mao return false;
939c23a53d8SBibo Mao }
940c23a53d8SBibo Mao
kvm_cpu_check_lsx(CPUState * cs,Error ** errp)941936c3f4dSBibo Mao static int kvm_cpu_check_lsx(CPUState *cs, Error **errp)
942936c3f4dSBibo Mao {
943936c3f4dSBibo Mao CPULoongArchState *env = cpu_env(cs);
944936c3f4dSBibo Mao LoongArchCPU *cpu = LOONGARCH_CPU(cs);
945936c3f4dSBibo Mao bool kvm_supported;
946936c3f4dSBibo Mao
947936c3f4dSBibo Mao kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_LSX);
948936c3f4dSBibo Mao env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LSX, 0);
949936c3f4dSBibo Mao if (cpu->lsx == ON_OFF_AUTO_ON) {
950936c3f4dSBibo Mao if (kvm_supported) {
951936c3f4dSBibo Mao env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LSX, 1);
952936c3f4dSBibo Mao } else {
953936c3f4dSBibo Mao error_setg(errp, "'lsx' feature not supported by KVM on this host");
954936c3f4dSBibo Mao return -ENOTSUP;
955936c3f4dSBibo Mao }
956936c3f4dSBibo Mao } else if ((cpu->lsx == ON_OFF_AUTO_AUTO) && kvm_supported) {
957936c3f4dSBibo Mao env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LSX, 1);
958936c3f4dSBibo Mao }
959936c3f4dSBibo Mao
960936c3f4dSBibo Mao return 0;
961936c3f4dSBibo Mao }
962936c3f4dSBibo Mao
kvm_cpu_check_lasx(CPUState * cs,Error ** errp)9635e360dabSBibo Mao static int kvm_cpu_check_lasx(CPUState *cs, Error **errp)
9645e360dabSBibo Mao {
9655e360dabSBibo Mao CPULoongArchState *env = cpu_env(cs);
9665e360dabSBibo Mao LoongArchCPU *cpu = LOONGARCH_CPU(cs);
9675e360dabSBibo Mao bool kvm_supported;
9685e360dabSBibo Mao
9695e360dabSBibo Mao kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_LASX);
9705e360dabSBibo Mao env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LASX, 0);
9715e360dabSBibo Mao if (cpu->lasx == ON_OFF_AUTO_ON) {
9725e360dabSBibo Mao if (kvm_supported) {
9735e360dabSBibo Mao env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LASX, 1);
9745e360dabSBibo Mao } else {
9755e360dabSBibo Mao error_setg(errp, "'lasx' feature not supported by KVM on host");
9765e360dabSBibo Mao return -ENOTSUP;
9775e360dabSBibo Mao }
9785e360dabSBibo Mao } else if ((cpu->lasx == ON_OFF_AUTO_AUTO) && kvm_supported) {
9795e360dabSBibo Mao env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LASX, 1);
9805e360dabSBibo Mao }
9815e360dabSBibo Mao
9825e360dabSBibo Mao return 0;
9835e360dabSBibo Mao }
9845e360dabSBibo Mao
kvm_cpu_check_lbt(CPUState * cs,Error ** errp)985c23a53d8SBibo Mao static int kvm_cpu_check_lbt(CPUState *cs, Error **errp)
986c23a53d8SBibo Mao {
987c23a53d8SBibo Mao CPULoongArchState *env = cpu_env(cs);
988c23a53d8SBibo Mao LoongArchCPU *cpu = LOONGARCH_CPU(cs);
989c23a53d8SBibo Mao bool kvm_supported;
990c23a53d8SBibo Mao
991c23a53d8SBibo Mao kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_LBT);
992c23a53d8SBibo Mao if (cpu->lbt == ON_OFF_AUTO_ON) {
993c23a53d8SBibo Mao if (kvm_supported) {
994c23a53d8SBibo Mao env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LBT_ALL, 7);
995c23a53d8SBibo Mao } else {
996c23a53d8SBibo Mao error_setg(errp, "'lbt' feature not supported by KVM on this host");
997c23a53d8SBibo Mao return -ENOTSUP;
998c23a53d8SBibo Mao }
999c23a53d8SBibo Mao } else if ((cpu->lbt == ON_OFF_AUTO_AUTO) && kvm_supported) {
1000c23a53d8SBibo Mao env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LBT_ALL, 7);
1001c23a53d8SBibo Mao }
1002c23a53d8SBibo Mao
1003c23a53d8SBibo Mao return 0;
1004c23a53d8SBibo Mao }
1005c23a53d8SBibo Mao
kvm_cpu_check_pmu(CPUState * cs,Error ** errp)10066edd2a9bSBibo Mao static int kvm_cpu_check_pmu(CPUState *cs, Error **errp)
10076edd2a9bSBibo Mao {
10086edd2a9bSBibo Mao LoongArchCPU *cpu = LOONGARCH_CPU(cs);
10096edd2a9bSBibo Mao CPULoongArchState *env = cpu_env(cs);
10106edd2a9bSBibo Mao bool kvm_supported;
10116edd2a9bSBibo Mao
10126edd2a9bSBibo Mao kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_PMU);
10136edd2a9bSBibo Mao if (cpu->pmu == ON_OFF_AUTO_ON) {
10146edd2a9bSBibo Mao if (!kvm_supported) {
10156edd2a9bSBibo Mao error_setg(errp, "'pmu' feature not supported by KVM on the host");
10166edd2a9bSBibo Mao return -ENOTSUP;
10176edd2a9bSBibo Mao }
10186edd2a9bSBibo Mao } else if (cpu->pmu != ON_OFF_AUTO_AUTO) {
10196edd2a9bSBibo Mao /* disable pmu if ON_OFF_AUTO_OFF is set */
10206edd2a9bSBibo Mao kvm_supported = false;
10216edd2a9bSBibo Mao }
10226edd2a9bSBibo Mao
10236edd2a9bSBibo Mao if (kvm_supported) {
10246edd2a9bSBibo Mao env->cpucfg[6] = FIELD_DP32(env->cpucfg[6], CPUCFG6, PMP, 1);
10256edd2a9bSBibo Mao env->cpucfg[6] = FIELD_DP32(env->cpucfg[6], CPUCFG6, PMNUM, 3);
10266edd2a9bSBibo Mao env->cpucfg[6] = FIELD_DP32(env->cpucfg[6], CPUCFG6, PMBITS, 63);
10276edd2a9bSBibo Mao env->cpucfg[6] = FIELD_DP32(env->cpucfg[6], CPUCFG6, UPM, 1);
10286edd2a9bSBibo Mao }
10296edd2a9bSBibo Mao return 0;
10306edd2a9bSBibo Mao }
10316edd2a9bSBibo Mao
kvm_cpu_check_pv_features(CPUState * cs,Error ** errp)1032620d9bd0SBibo Mao static int kvm_cpu_check_pv_features(CPUState *cs, Error **errp)
1033620d9bd0SBibo Mao {
1034db369c11SBibo Mao MachineState *ms = MACHINE(qdev_get_machine());
1035620d9bd0SBibo Mao LoongArchCPU *cpu = LOONGARCH_CPU(cs);
1036620d9bd0SBibo Mao CPULoongArchState *env = cpu_env(cs);
1037620d9bd0SBibo Mao bool kvm_supported;
1038620d9bd0SBibo Mao
1039620d9bd0SBibo Mao kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_PV_IPI);
1040620d9bd0SBibo Mao if (cpu->kvm_pv_ipi == ON_OFF_AUTO_ON) {
1041620d9bd0SBibo Mao if (!kvm_supported) {
1042620d9bd0SBibo Mao error_setg(errp, "'pv_ipi' feature not supported by KVM host");
1043620d9bd0SBibo Mao return -ENOTSUP;
1044620d9bd0SBibo Mao }
1045620d9bd0SBibo Mao } else if (cpu->kvm_pv_ipi != ON_OFF_AUTO_AUTO) {
1046620d9bd0SBibo Mao kvm_supported = false;
1047620d9bd0SBibo Mao }
1048620d9bd0SBibo Mao
1049620d9bd0SBibo Mao if (kvm_supported) {
1050620d9bd0SBibo Mao env->pv_features |= BIT(KVM_FEATURE_IPI);
1051620d9bd0SBibo Mao }
1052620d9bd0SBibo Mao
1053954cc5c3SBibo Mao kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_STEALTIME);
1054954cc5c3SBibo Mao if (cpu->kvm_steal_time == ON_OFF_AUTO_ON) {
1055954cc5c3SBibo Mao if (!kvm_supported) {
1056954cc5c3SBibo Mao error_setg(errp, "'kvm stealtime' feature not supported by KVM host");
1057954cc5c3SBibo Mao return -ENOTSUP;
1058954cc5c3SBibo Mao }
1059954cc5c3SBibo Mao } else if (cpu->kvm_steal_time != ON_OFF_AUTO_AUTO) {
1060954cc5c3SBibo Mao kvm_supported = false;
1061954cc5c3SBibo Mao }
1062954cc5c3SBibo Mao
1063954cc5c3SBibo Mao if (kvm_supported) {
1064954cc5c3SBibo Mao env->pv_features |= BIT(KVM_FEATURE_STEAL_TIME);
1065954cc5c3SBibo Mao }
1066954cc5c3SBibo Mao
1067db369c11SBibo Mao if (object_dynamic_cast(OBJECT(ms), TYPE_LOONGARCH_VIRT_MACHINE)) {
1068db369c11SBibo Mao LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(ms);
1069db369c11SBibo Mao
1070db369c11SBibo Mao if (virt_is_veiointc_enabled(lvms)) {
1071db369c11SBibo Mao env->pv_features |= BIT(KVM_FEATURE_VIRT_EXTIOI);
1072db369c11SBibo Mao }
1073db369c11SBibo Mao }
1074*a668268dSXiaoyao Li return 0;
1075*a668268dSXiaoyao Li }
1076db369c11SBibo Mao
kvm_arch_pre_create_vcpu(CPUState * cpu,Error ** errp)1077*a668268dSXiaoyao Li int kvm_arch_pre_create_vcpu(CPUState *cpu, Error **errp)
1078*a668268dSXiaoyao Li {
1079620d9bd0SBibo Mao return 0;
1080620d9bd0SBibo Mao }
1081620d9bd0SBibo Mao
kvm_arch_init_vcpu(CPUState * cs)1082537ba9daSTianrui Zhao int kvm_arch_init_vcpu(CPUState *cs)
1083537ba9daSTianrui Zhao {
1084d38e31efSBibo Mao uint64_t val;
1085c23a53d8SBibo Mao int ret;
1086c23a53d8SBibo Mao Error *local_err = NULL;
10870c346576SXianglai Li LoongArchCPU *cpu = LOONGARCH_CPU(cs);
1088d38e31efSBibo Mao
10890c346576SXianglai Li cpu->vmsentry = qemu_add_vm_change_state_handler(
10900c346576SXianglai Li kvm_loongarch_vm_stage_change, cs);
1091d38e31efSBibo Mao
1092d38e31efSBibo Mao if (!kvm_get_one_reg(cs, KVM_REG_LOONGARCH_DEBUG_INST, &val)) {
1093d38e31efSBibo Mao brk_insn = val;
1094d38e31efSBibo Mao }
1095d38e31efSBibo Mao
1096936c3f4dSBibo Mao ret = kvm_cpu_check_lsx(cs, &local_err);
1097936c3f4dSBibo Mao if (ret < 0) {
1098936c3f4dSBibo Mao error_report_err(local_err);
1099d7ffc17dSBibo Mao return ret;
1100936c3f4dSBibo Mao }
1101936c3f4dSBibo Mao
11025e360dabSBibo Mao ret = kvm_cpu_check_lasx(cs, &local_err);
11035e360dabSBibo Mao if (ret < 0) {
11045e360dabSBibo Mao error_report_err(local_err);
1105d7ffc17dSBibo Mao return ret;
11065e360dabSBibo Mao }
11075e360dabSBibo Mao
1108c23a53d8SBibo Mao ret = kvm_cpu_check_lbt(cs, &local_err);
1109c23a53d8SBibo Mao if (ret < 0) {
1110c23a53d8SBibo Mao error_report_err(local_err);
1111d7ffc17dSBibo Mao return ret;
1112c23a53d8SBibo Mao }
11136edd2a9bSBibo Mao
11146edd2a9bSBibo Mao ret = kvm_cpu_check_pmu(cs, &local_err);
11156edd2a9bSBibo Mao if (ret < 0) {
11166edd2a9bSBibo Mao error_report_err(local_err);
1117d7ffc17dSBibo Mao return ret;
11186edd2a9bSBibo Mao }
11196edd2a9bSBibo Mao
1120620d9bd0SBibo Mao ret = kvm_cpu_check_pv_features(cs, &local_err);
1121620d9bd0SBibo Mao if (ret < 0) {
1122620d9bd0SBibo Mao error_report_err(local_err);
1123d7ffc17dSBibo Mao return ret;
1124620d9bd0SBibo Mao }
1125620d9bd0SBibo Mao
1126d7ffc17dSBibo Mao return 0;
1127537ba9daSTianrui Zhao }
1128537ba9daSTianrui Zhao
loongarch_get_lbt(Object * obj,Error ** errp)1129780a65bdSBibo Mao static bool loongarch_get_lbt(Object *obj, Error **errp)
1130780a65bdSBibo Mao {
1131780a65bdSBibo Mao return LOONGARCH_CPU(obj)->lbt != ON_OFF_AUTO_OFF;
1132780a65bdSBibo Mao }
1133780a65bdSBibo Mao
loongarch_set_lbt(Object * obj,bool value,Error ** errp)1134780a65bdSBibo Mao static void loongarch_set_lbt(Object *obj, bool value, Error **errp)
1135780a65bdSBibo Mao {
1136780a65bdSBibo Mao LoongArchCPU *cpu = LOONGARCH_CPU(obj);
1137780a65bdSBibo Mao
1138780a65bdSBibo Mao cpu->lbt = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
1139780a65bdSBibo Mao }
1140780a65bdSBibo Mao
loongarch_get_pmu(Object * obj,Error ** errp)1141780a65bdSBibo Mao static bool loongarch_get_pmu(Object *obj, Error **errp)
1142780a65bdSBibo Mao {
1143780a65bdSBibo Mao return LOONGARCH_CPU(obj)->pmu != ON_OFF_AUTO_OFF;
1144780a65bdSBibo Mao }
1145780a65bdSBibo Mao
loongarch_set_pmu(Object * obj,bool value,Error ** errp)1146780a65bdSBibo Mao static void loongarch_set_pmu(Object *obj, bool value, Error **errp)
1147780a65bdSBibo Mao {
1148780a65bdSBibo Mao LoongArchCPU *cpu = LOONGARCH_CPU(obj);
1149780a65bdSBibo Mao
1150780a65bdSBibo Mao cpu->pmu = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
1151780a65bdSBibo Mao }
1152780a65bdSBibo Mao
kvm_pv_ipi_get(Object * obj,Error ** errp)11535b0502c5SBibo Mao static bool kvm_pv_ipi_get(Object *obj, Error **errp)
11545b0502c5SBibo Mao {
11555b0502c5SBibo Mao return LOONGARCH_CPU(obj)->kvm_pv_ipi != ON_OFF_AUTO_OFF;
11565b0502c5SBibo Mao }
11575b0502c5SBibo Mao
kvm_pv_ipi_set(Object * obj,bool value,Error ** errp)11585b0502c5SBibo Mao static void kvm_pv_ipi_set(Object *obj, bool value, Error **errp)
11595b0502c5SBibo Mao {
11605b0502c5SBibo Mao LoongArchCPU *cpu = LOONGARCH_CPU(obj);
11615b0502c5SBibo Mao
11625b0502c5SBibo Mao cpu->kvm_pv_ipi = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
11635b0502c5SBibo Mao }
11645b0502c5SBibo Mao
kvm_steal_time_get(Object * obj,Error ** errp)1165610babceSBibo Mao static bool kvm_steal_time_get(Object *obj, Error **errp)
1166610babceSBibo Mao {
1167610babceSBibo Mao return LOONGARCH_CPU(obj)->kvm_steal_time != ON_OFF_AUTO_OFF;
1168610babceSBibo Mao }
1169610babceSBibo Mao
kvm_steal_time_set(Object * obj,bool value,Error ** errp)1170610babceSBibo Mao static void kvm_steal_time_set(Object *obj, bool value, Error **errp)
1171610babceSBibo Mao {
1172610babceSBibo Mao LoongArchCPU *cpu = LOONGARCH_CPU(obj);
1173610babceSBibo Mao
1174610babceSBibo Mao cpu->kvm_steal_time = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
1175610babceSBibo Mao }
1176610babceSBibo Mao
kvm_loongarch_cpu_post_init(LoongArchCPU * cpu)11773406b001SBibo Mao void kvm_loongarch_cpu_post_init(LoongArchCPU *cpu)
11783406b001SBibo Mao {
1179780a65bdSBibo Mao cpu->lbt = ON_OFF_AUTO_AUTO;
1180780a65bdSBibo Mao object_property_add_bool(OBJECT(cpu), "lbt", loongarch_get_lbt,
1181780a65bdSBibo Mao loongarch_set_lbt);
1182780a65bdSBibo Mao object_property_set_description(OBJECT(cpu), "lbt",
1183780a65bdSBibo Mao "Set off to disable Binary Tranlation.");
1184780a65bdSBibo Mao
1185780a65bdSBibo Mao cpu->pmu = ON_OFF_AUTO_AUTO;
1186780a65bdSBibo Mao object_property_add_bool(OBJECT(cpu), "pmu", loongarch_get_pmu,
1187780a65bdSBibo Mao loongarch_set_pmu);
1188780a65bdSBibo Mao object_property_set_description(OBJECT(cpu), "pmu",
1189780a65bdSBibo Mao "Set off to disable performance monitor unit.");
11905b0502c5SBibo Mao
11915b0502c5SBibo Mao cpu->kvm_pv_ipi = ON_OFF_AUTO_AUTO;
11925b0502c5SBibo Mao object_property_add_bool(OBJECT(cpu), "kvm-pv-ipi", kvm_pv_ipi_get,
11935b0502c5SBibo Mao kvm_pv_ipi_set);
11945b0502c5SBibo Mao object_property_set_description(OBJECT(cpu), "kvm-pv-ipi",
11955b0502c5SBibo Mao "Set off to disable KVM paravirt IPI.");
1196610babceSBibo Mao
1197610babceSBibo Mao cpu->kvm_steal_time = ON_OFF_AUTO_AUTO;
1198610babceSBibo Mao object_property_add_bool(OBJECT(cpu), "kvm-steal-time", kvm_steal_time_get,
1199610babceSBibo Mao kvm_steal_time_set);
1200610babceSBibo Mao object_property_set_description(OBJECT(cpu), "kvm-steal-time",
1201610babceSBibo Mao "Set off to disable KVM steal time.");
12023406b001SBibo Mao }
12033406b001SBibo Mao
kvm_arch_destroy_vcpu(CPUState * cs)1204537ba9daSTianrui Zhao int kvm_arch_destroy_vcpu(CPUState *cs)
1205537ba9daSTianrui Zhao {
12060c346576SXianglai Li LoongArchCPU *cpu = LOONGARCH_CPU(cs);
12070c346576SXianglai Li
12080c346576SXianglai Li qemu_del_vm_change_state_handler(cpu->vmsentry);
1209537ba9daSTianrui Zhao return 0;
1210537ba9daSTianrui Zhao }
1211537ba9daSTianrui Zhao
kvm_arch_vcpu_id(CPUState * cs)1212537ba9daSTianrui Zhao unsigned long kvm_arch_vcpu_id(CPUState *cs)
1213537ba9daSTianrui Zhao {
1214537ba9daSTianrui Zhao return cs->cpu_index;
1215537ba9daSTianrui Zhao }
1216537ba9daSTianrui Zhao
kvm_arch_release_virq_post(int virq)1217537ba9daSTianrui Zhao int kvm_arch_release_virq_post(int virq)
1218537ba9daSTianrui Zhao {
1219537ba9daSTianrui Zhao return 0;
1220537ba9daSTianrui Zhao }
1221537ba9daSTianrui Zhao
kvm_arch_msi_data_to_gsi(uint32_t data)1222537ba9daSTianrui Zhao int kvm_arch_msi_data_to_gsi(uint32_t data)
1223537ba9daSTianrui Zhao {
1224537ba9daSTianrui Zhao abort();
1225537ba9daSTianrui Zhao }
1226537ba9daSTianrui Zhao
kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry * route,uint64_t address,uint32_t data,PCIDevice * dev)1227537ba9daSTianrui Zhao int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
1228537ba9daSTianrui Zhao uint64_t address, uint32_t data, PCIDevice *dev)
1229537ba9daSTianrui Zhao {
1230537ba9daSTianrui Zhao return 0;
1231537ba9daSTianrui Zhao }
1232537ba9daSTianrui Zhao
kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry * route,int vector,PCIDevice * dev)1233537ba9daSTianrui Zhao int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
1234537ba9daSTianrui Zhao int vector, PCIDevice *dev)
1235537ba9daSTianrui Zhao {
1236537ba9daSTianrui Zhao return 0;
1237537ba9daSTianrui Zhao }
1238537ba9daSTianrui Zhao
kvm_arch_init_irq_routing(KVMState * s)1239537ba9daSTianrui Zhao void kvm_arch_init_irq_routing(KVMState *s)
1240537ba9daSTianrui Zhao {
1241537ba9daSTianrui Zhao }
1242537ba9daSTianrui Zhao
kvm_arch_get_default_type(MachineState * ms)1243537ba9daSTianrui Zhao int kvm_arch_get_default_type(MachineState *ms)
1244537ba9daSTianrui Zhao {
1245537ba9daSTianrui Zhao return 0;
1246537ba9daSTianrui Zhao }
1247537ba9daSTianrui Zhao
kvm_arch_init(MachineState * ms,KVMState * s)1248537ba9daSTianrui Zhao int kvm_arch_init(MachineState *ms, KVMState *s)
1249537ba9daSTianrui Zhao {
125041958c99STianrui Zhao cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
1251537ba9daSTianrui Zhao return 0;
1252537ba9daSTianrui Zhao }
1253537ba9daSTianrui Zhao
kvm_arch_irqchip_create(KVMState * s)1254537ba9daSTianrui Zhao int kvm_arch_irqchip_create(KVMState *s)
1255537ba9daSTianrui Zhao {
1256537ba9daSTianrui Zhao return 0;
1257537ba9daSTianrui Zhao }
1258537ba9daSTianrui Zhao
kvm_arch_pre_run(CPUState * cs,struct kvm_run * run)1259537ba9daSTianrui Zhao void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
1260537ba9daSTianrui Zhao {
1261537ba9daSTianrui Zhao }
1262537ba9daSTianrui Zhao
kvm_arch_post_run(CPUState * cs,struct kvm_run * run)1263537ba9daSTianrui Zhao MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
1264537ba9daSTianrui Zhao {
1265537ba9daSTianrui Zhao return MEMTXATTRS_UNSPECIFIED;
1266537ba9daSTianrui Zhao }
1267537ba9daSTianrui Zhao
kvm_arch_process_async_events(CPUState * cs)1268537ba9daSTianrui Zhao int kvm_arch_process_async_events(CPUState *cs)
1269537ba9daSTianrui Zhao {
1270537ba9daSTianrui Zhao return cs->halted;
1271537ba9daSTianrui Zhao }
1272537ba9daSTianrui Zhao
kvm_arch_stop_on_emulation_error(CPUState * cs)1273537ba9daSTianrui Zhao bool kvm_arch_stop_on_emulation_error(CPUState *cs)
1274537ba9daSTianrui Zhao {
1275537ba9daSTianrui Zhao return true;
1276537ba9daSTianrui Zhao }
1277537ba9daSTianrui Zhao
kvm_arch_update_guest_debug(CPUState * cpu,struct kvm_guest_debug * dbg)1278d38e31efSBibo Mao void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg)
1279d38e31efSBibo Mao {
1280d38e31efSBibo Mao if (kvm_sw_breakpoints_active(cpu)) {
1281d38e31efSBibo Mao dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
1282d38e31efSBibo Mao }
1283d38e31efSBibo Mao }
1284d38e31efSBibo Mao
kvm_arch_insert_sw_breakpoint(CPUState * cs,struct kvm_sw_breakpoint * bp)1285d38e31efSBibo Mao int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
1286d38e31efSBibo Mao {
1287d38e31efSBibo Mao if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 4, 0) ||
1288d38e31efSBibo Mao cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&brk_insn, 4, 1)) {
1289d38e31efSBibo Mao error_report("%s failed", __func__);
1290d38e31efSBibo Mao return -EINVAL;
1291d38e31efSBibo Mao }
1292d38e31efSBibo Mao return 0;
1293d38e31efSBibo Mao }
1294d38e31efSBibo Mao
kvm_arch_remove_sw_breakpoint(CPUState * cs,struct kvm_sw_breakpoint * bp)1295d38e31efSBibo Mao int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
1296d38e31efSBibo Mao {
1297d38e31efSBibo Mao static uint32_t brk;
1298d38e31efSBibo Mao
1299d38e31efSBibo Mao if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&brk, 4, 0) ||
1300d38e31efSBibo Mao brk != brk_insn ||
1301d38e31efSBibo Mao cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 4, 1)) {
1302d38e31efSBibo Mao error_report("%s failed", __func__);
1303d38e31efSBibo Mao return -EINVAL;
1304d38e31efSBibo Mao }
1305d38e31efSBibo Mao return 0;
1306d38e31efSBibo Mao }
1307d38e31efSBibo Mao
kvm_arch_insert_hw_breakpoint(vaddr addr,vaddr len,int type)1308d38e31efSBibo Mao int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type)
1309d38e31efSBibo Mao {
1310d38e31efSBibo Mao return -ENOSYS;
1311d38e31efSBibo Mao }
1312d38e31efSBibo Mao
kvm_arch_remove_hw_breakpoint(vaddr addr,vaddr len,int type)1313d38e31efSBibo Mao int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type)
1314d38e31efSBibo Mao {
1315d38e31efSBibo Mao return -ENOSYS;
1316d38e31efSBibo Mao }
1317d38e31efSBibo Mao
kvm_arch_remove_all_hw_breakpoints(void)1318d38e31efSBibo Mao void kvm_arch_remove_all_hw_breakpoints(void)
1319d38e31efSBibo Mao {
1320d38e31efSBibo Mao }
1321d38e31efSBibo Mao
kvm_loongarch_handle_debug(CPUState * cs,struct kvm_run * run)1322d38e31efSBibo Mao static bool kvm_loongarch_handle_debug(CPUState *cs, struct kvm_run *run)
1323d38e31efSBibo Mao {
1324d38e31efSBibo Mao LoongArchCPU *cpu = LOONGARCH_CPU(cs);
1325d38e31efSBibo Mao CPULoongArchState *env = &cpu->env;
1326d38e31efSBibo Mao
1327d38e31efSBibo Mao kvm_cpu_synchronize_state(cs);
1328d38e31efSBibo Mao if (cs->singlestep_enabled) {
1329d38e31efSBibo Mao return true;
1330d38e31efSBibo Mao }
1331d38e31efSBibo Mao
1332d38e31efSBibo Mao if (kvm_find_sw_breakpoint(cs, env->pc)) {
1333d38e31efSBibo Mao return true;
1334d38e31efSBibo Mao }
1335d38e31efSBibo Mao
1336d38e31efSBibo Mao return false;
1337d38e31efSBibo Mao }
1338d38e31efSBibo Mao
kvm_arch_handle_exit(CPUState * cs,struct kvm_run * run)1339537ba9daSTianrui Zhao int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
1340537ba9daSTianrui Zhao {
1341a05a950fSTianrui Zhao int ret = 0;
1342f3b603b9SPhilippe Mathieu-Daudé CPULoongArchState *env = cpu_env(cs);
1343a05a950fSTianrui Zhao MemTxAttrs attrs = {};
1344a05a950fSTianrui Zhao
1345a05a950fSTianrui Zhao attrs.requester_id = env_cpu(env)->cpu_index;
1346a05a950fSTianrui Zhao
1347a05a950fSTianrui Zhao trace_kvm_arch_handle_exit(run->exit_reason);
1348a05a950fSTianrui Zhao switch (run->exit_reason) {
1349a05a950fSTianrui Zhao case KVM_EXIT_LOONGARCH_IOCSR:
13505e90b8dbSBibo Mao address_space_rw(env->address_space_iocsr,
1351a05a950fSTianrui Zhao run->iocsr_io.phys_addr,
1352a05a950fSTianrui Zhao attrs,
1353a05a950fSTianrui Zhao run->iocsr_io.data,
1354a05a950fSTianrui Zhao run->iocsr_io.len,
1355a05a950fSTianrui Zhao run->iocsr_io.is_write);
1356a05a950fSTianrui Zhao break;
1357d38e31efSBibo Mao
1358d38e31efSBibo Mao case KVM_EXIT_DEBUG:
1359d38e31efSBibo Mao if (kvm_loongarch_handle_debug(cs, run)) {
1360d38e31efSBibo Mao ret = EXCP_DEBUG;
1361d38e31efSBibo Mao }
1362d38e31efSBibo Mao break;
1363d38e31efSBibo Mao
1364a05a950fSTianrui Zhao default:
1365a05a950fSTianrui Zhao ret = -1;
1366a05a950fSTianrui Zhao warn_report("KVM: unknown exit reason %d", run->exit_reason);
1367a05a950fSTianrui Zhao break;
1368a05a950fSTianrui Zhao }
1369a05a950fSTianrui Zhao return ret;
1370537ba9daSTianrui Zhao }
1371537ba9daSTianrui Zhao
kvm_loongarch_set_interrupt(LoongArchCPU * cpu,int irq,int level)13728dcbad51STianrui Zhao int kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level)
13738dcbad51STianrui Zhao {
13748dcbad51STianrui Zhao struct kvm_interrupt intr;
13758dcbad51STianrui Zhao CPUState *cs = CPU(cpu);
13768dcbad51STianrui Zhao
13778dcbad51STianrui Zhao if (level) {
13788dcbad51STianrui Zhao intr.irq = irq;
13798dcbad51STianrui Zhao } else {
13808dcbad51STianrui Zhao intr.irq = -irq;
13818dcbad51STianrui Zhao }
13828dcbad51STianrui Zhao
13838dcbad51STianrui Zhao trace_kvm_set_intr(irq, level);
13848dcbad51STianrui Zhao return kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
13858dcbad51STianrui Zhao }
13868dcbad51STianrui Zhao
kvm_arch_accel_class_init(ObjectClass * oc)1387537ba9daSTianrui Zhao void kvm_arch_accel_class_init(ObjectClass *oc)
1388537ba9daSTianrui Zhao {
1389537ba9daSTianrui Zhao }
1390