xref: /qemu/target/loongarch/kvm/kvm.c (revision 32cad1ffb81dcecf6f4a8af56d6e5892682839b1)
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>
11537ba9daSTianrui Zhao 
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"
16*32cad1ffSPhilippe Mathieu-Daudé #include "system/system.h"
17*32cad1ffSPhilippe Mathieu-Daudé #include "system/kvm.h"
18*32cad1ffSPhilippe Mathieu-Daudé #include "system/kvm_int.h"
19537ba9daSTianrui Zhao #include "hw/pci/pci.h"
20537ba9daSTianrui Zhao #include "exec/memattrs.h"
21537ba9daSTianrui Zhao #include "exec/address-spaces.h"
22537ba9daSTianrui Zhao #include "hw/boards.h"
23537ba9daSTianrui Zhao #include "hw/irq.h"
24537ba9daSTianrui Zhao #include "qemu/log.h"
25537ba9daSTianrui Zhao #include "hw/loader.h"
26*32cad1ffSPhilippe Mathieu-Daudé #include "system/runstate.h"
27537ba9daSTianrui Zhao #include "cpu-csr.h"
28537ba9daSTianrui Zhao #include "kvm_loongarch.h"
29f8447436STianrui Zhao #include "trace.h"
30537ba9daSTianrui Zhao 
31537ba9daSTianrui Zhao static bool cap_has_mp_state;
32d38e31efSBibo Mao static unsigned int brk_insn;
33537ba9daSTianrui Zhao const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
34537ba9daSTianrui Zhao     KVM_CAP_LAST_INFO
35537ba9daSTianrui Zhao };
36537ba9daSTianrui Zhao 
3747b54e15SBibo Mao static int kvm_get_stealtime(CPUState *cs)
3847b54e15SBibo Mao {
3947b54e15SBibo Mao     CPULoongArchState *env = cpu_env(cs);
4047b54e15SBibo Mao     int err;
4147b54e15SBibo Mao     struct kvm_device_attr attr = {
4247b54e15SBibo Mao         .group = KVM_LOONGARCH_VCPU_PVTIME_CTRL,
4347b54e15SBibo Mao         .attr = KVM_LOONGARCH_VCPU_PVTIME_GPA,
4447b54e15SBibo Mao         .addr = (uint64_t)&env->stealtime.guest_addr,
4547b54e15SBibo Mao     };
4647b54e15SBibo Mao 
4747b54e15SBibo Mao     err = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr);
4847b54e15SBibo Mao     if (err) {
4947b54e15SBibo Mao         return 0;
5047b54e15SBibo Mao     }
5147b54e15SBibo Mao 
5247b54e15SBibo Mao     err = kvm_vcpu_ioctl(cs, KVM_GET_DEVICE_ATTR, attr);
5347b54e15SBibo Mao     if (err) {
5447b54e15SBibo Mao         error_report("PVTIME: KVM_GET_DEVICE_ATTR: %s", strerror(errno));
5547b54e15SBibo Mao         return err;
5647b54e15SBibo Mao     }
5747b54e15SBibo Mao 
5847b54e15SBibo Mao     return 0;
5947b54e15SBibo Mao }
6047b54e15SBibo Mao 
6147b54e15SBibo Mao static int kvm_set_stealtime(CPUState *cs)
6247b54e15SBibo Mao {
6347b54e15SBibo Mao     CPULoongArchState *env = cpu_env(cs);
6447b54e15SBibo Mao     int err;
6547b54e15SBibo Mao     struct kvm_device_attr attr = {
6647b54e15SBibo Mao         .group = KVM_LOONGARCH_VCPU_PVTIME_CTRL,
6747b54e15SBibo Mao         .attr = KVM_LOONGARCH_VCPU_PVTIME_GPA,
6847b54e15SBibo Mao         .addr = (uint64_t)&env->stealtime.guest_addr,
6947b54e15SBibo Mao     };
7047b54e15SBibo Mao 
7147b54e15SBibo Mao     err = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr);
7247b54e15SBibo Mao     if (err) {
7347b54e15SBibo Mao         return 0;
7447b54e15SBibo Mao     }
7547b54e15SBibo Mao 
7647b54e15SBibo Mao     err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, attr);
7747b54e15SBibo Mao     if (err) {
7847b54e15SBibo Mao         error_report("PVTIME: KVM_SET_DEVICE_ATTR %s with gpa "TARGET_FMT_lx,
7947b54e15SBibo Mao                       strerror(errno), env->stealtime.guest_addr);
8047b54e15SBibo Mao         return err;
8147b54e15SBibo Mao     }
8247b54e15SBibo Mao 
8347b54e15SBibo Mao     return 0;
8447b54e15SBibo Mao }
8547b54e15SBibo Mao 
86f8447436STianrui Zhao static int kvm_loongarch_get_regs_core(CPUState *cs)
87f8447436STianrui Zhao {
88f8447436STianrui Zhao     int ret = 0;
89f8447436STianrui Zhao     int i;
90f8447436STianrui Zhao     struct kvm_regs regs;
91f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
92f8447436STianrui Zhao 
93f8447436STianrui Zhao     /* Get the current register set as KVM seems it */
94f8447436STianrui Zhao     ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, &regs);
95f8447436STianrui Zhao     if (ret < 0) {
96f8447436STianrui Zhao         trace_kvm_failed_get_regs_core(strerror(errno));
97f8447436STianrui Zhao         return ret;
98f8447436STianrui Zhao     }
99f8447436STianrui Zhao     /* gpr[0] value is always 0 */
100f8447436STianrui Zhao     env->gpr[0] = 0;
101f8447436STianrui Zhao     for (i = 1; i < 32; i++) {
102f8447436STianrui Zhao         env->gpr[i] = regs.gpr[i];
103f8447436STianrui Zhao     }
104f8447436STianrui Zhao 
105f8447436STianrui Zhao     env->pc = regs.pc;
106f8447436STianrui Zhao     return ret;
107f8447436STianrui Zhao }
108f8447436STianrui Zhao 
109f8447436STianrui Zhao static int kvm_loongarch_put_regs_core(CPUState *cs)
110f8447436STianrui Zhao {
111f8447436STianrui Zhao     int ret = 0;
112f8447436STianrui Zhao     int i;
113f8447436STianrui Zhao     struct kvm_regs regs;
114f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
115f8447436STianrui Zhao 
116f8447436STianrui Zhao     /* Set the registers based on QEMU's view of things */
117f8447436STianrui Zhao     for (i = 0; i < 32; i++) {
118f8447436STianrui Zhao         regs.gpr[i] = env->gpr[i];
119f8447436STianrui Zhao     }
120f8447436STianrui Zhao 
121f8447436STianrui Zhao     regs.pc = env->pc;
122f8447436STianrui Zhao     ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, &regs);
123f8447436STianrui Zhao     if (ret < 0) {
124f8447436STianrui Zhao         trace_kvm_failed_put_regs_core(strerror(errno));
125f8447436STianrui Zhao     }
126f8447436STianrui Zhao 
127f8447436STianrui Zhao     return ret;
128f8447436STianrui Zhao }
129f8447436STianrui Zhao 
130f8447436STianrui Zhao static int kvm_loongarch_get_csr(CPUState *cs)
131f8447436STianrui Zhao {
132f8447436STianrui Zhao     int ret = 0;
133f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
134f8447436STianrui Zhao 
135f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CRMD),
136f8447436STianrui Zhao                            &env->CSR_CRMD);
137f8447436STianrui Zhao 
138f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRMD),
139f8447436STianrui Zhao                            &env->CSR_PRMD);
140f8447436STianrui Zhao 
141f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EUEN),
142f8447436STianrui Zhao                            &env->CSR_EUEN);
143f8447436STianrui Zhao 
144f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MISC),
145f8447436STianrui Zhao                            &env->CSR_MISC);
146f8447436STianrui Zhao 
147f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ECFG),
148f8447436STianrui Zhao                            &env->CSR_ECFG);
149f8447436STianrui Zhao 
150f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ESTAT),
151f8447436STianrui Zhao                            &env->CSR_ESTAT);
152f8447436STianrui Zhao 
153f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ERA),
154f8447436STianrui Zhao                            &env->CSR_ERA);
155f8447436STianrui Zhao 
156f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADV),
157f8447436STianrui Zhao                            &env->CSR_BADV);
158f8447436STianrui Zhao 
159f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADI),
160f8447436STianrui Zhao                            &env->CSR_BADI);
161f8447436STianrui Zhao 
162f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EENTRY),
163f8447436STianrui Zhao                            &env->CSR_EENTRY);
164f8447436STianrui Zhao 
165f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBIDX),
166f8447436STianrui Zhao                            &env->CSR_TLBIDX);
167f8447436STianrui Zhao 
168f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBEHI),
169f8447436STianrui Zhao                            &env->CSR_TLBEHI);
170f8447436STianrui Zhao 
171f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO0),
172f8447436STianrui Zhao                            &env->CSR_TLBELO0);
173f8447436STianrui Zhao 
174f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO1),
175f8447436STianrui Zhao                            &env->CSR_TLBELO1);
176f8447436STianrui Zhao 
177f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ASID),
178f8447436STianrui Zhao                            &env->CSR_ASID);
179f8447436STianrui Zhao 
180f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDL),
181f8447436STianrui Zhao                            &env->CSR_PGDL);
182f8447436STianrui Zhao 
183f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDH),
184f8447436STianrui Zhao                            &env->CSR_PGDH);
185f8447436STianrui Zhao 
186f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGD),
187f8447436STianrui Zhao                            &env->CSR_PGD);
188f8447436STianrui Zhao 
189f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCL),
190f8447436STianrui Zhao                            &env->CSR_PWCL);
191f8447436STianrui Zhao 
192f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCH),
193f8447436STianrui Zhao                            &env->CSR_PWCH);
194f8447436STianrui Zhao 
195f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_STLBPS),
196f8447436STianrui Zhao                            &env->CSR_STLBPS);
197f8447436STianrui Zhao 
198f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_RVACFG),
199f8447436STianrui Zhao                            &env->CSR_RVACFG);
200f8447436STianrui Zhao 
201f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CPUID),
202f8447436STianrui Zhao                            &env->CSR_CPUID);
203f8447436STianrui Zhao 
204f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG1),
205f8447436STianrui Zhao                            &env->CSR_PRCFG1);
206f8447436STianrui Zhao 
207f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG2),
208f8447436STianrui Zhao                            &env->CSR_PRCFG2);
209f8447436STianrui Zhao 
210f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG3),
211f8447436STianrui Zhao                            &env->CSR_PRCFG3);
212f8447436STianrui Zhao 
213f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(0)),
214f8447436STianrui Zhao                            &env->CSR_SAVE[0]);
215f8447436STianrui Zhao 
216f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(1)),
217f8447436STianrui Zhao                            &env->CSR_SAVE[1]);
218f8447436STianrui Zhao 
219f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(2)),
220f8447436STianrui Zhao                            &env->CSR_SAVE[2]);
221f8447436STianrui Zhao 
222f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(3)),
223f8447436STianrui Zhao                            &env->CSR_SAVE[3]);
224f8447436STianrui Zhao 
225f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(4)),
226f8447436STianrui Zhao                            &env->CSR_SAVE[4]);
227f8447436STianrui Zhao 
228f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(5)),
229f8447436STianrui Zhao                            &env->CSR_SAVE[5]);
230f8447436STianrui Zhao 
231f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(6)),
232f8447436STianrui Zhao                            &env->CSR_SAVE[6]);
233f8447436STianrui Zhao 
234f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(7)),
235f8447436STianrui Zhao                            &env->CSR_SAVE[7]);
236f8447436STianrui Zhao 
237f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TID),
238f8447436STianrui Zhao                            &env->CSR_TID);
239f8447436STianrui Zhao 
240f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CNTC),
241f8447436STianrui Zhao                            &env->CSR_CNTC);
242f8447436STianrui Zhao 
243f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TICLR),
244f8447436STianrui Zhao                            &env->CSR_TICLR);
245f8447436STianrui Zhao 
246f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_LLBCTL),
247f8447436STianrui Zhao                            &env->CSR_LLBCTL);
248f8447436STianrui Zhao 
249f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL1),
250f8447436STianrui Zhao                            &env->CSR_IMPCTL1);
251f8447436STianrui Zhao 
252f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL2),
253f8447436STianrui Zhao                            &env->CSR_IMPCTL2);
254f8447436STianrui Zhao 
255f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRENTRY),
256f8447436STianrui Zhao                            &env->CSR_TLBRENTRY);
257f8447436STianrui Zhao 
258f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRBADV),
259f8447436STianrui Zhao                            &env->CSR_TLBRBADV);
260f8447436STianrui Zhao 
261f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRERA),
262f8447436STianrui Zhao                            &env->CSR_TLBRERA);
263f8447436STianrui Zhao 
264f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRSAVE),
265f8447436STianrui Zhao                            &env->CSR_TLBRSAVE);
266f8447436STianrui Zhao 
267f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO0),
268f8447436STianrui Zhao                            &env->CSR_TLBRELO0);
269f8447436STianrui Zhao 
270f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO1),
271f8447436STianrui Zhao                            &env->CSR_TLBRELO1);
272f8447436STianrui Zhao 
273f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBREHI),
274f8447436STianrui Zhao                            &env->CSR_TLBREHI);
275f8447436STianrui Zhao 
276f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRPRMD),
277f8447436STianrui Zhao                            &env->CSR_TLBRPRMD);
278f8447436STianrui Zhao 
279f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(0)),
280f8447436STianrui Zhao                            &env->CSR_DMW[0]);
281f8447436STianrui Zhao 
282f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(1)),
283f8447436STianrui Zhao                            &env->CSR_DMW[1]);
284f8447436STianrui Zhao 
285f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(2)),
286f8447436STianrui Zhao                            &env->CSR_DMW[2]);
287f8447436STianrui Zhao 
288f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(3)),
289f8447436STianrui Zhao                            &env->CSR_DMW[3]);
290f8447436STianrui Zhao 
291f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TVAL),
292f8447436STianrui Zhao                            &env->CSR_TVAL);
293f8447436STianrui Zhao 
294f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TCFG),
295f8447436STianrui Zhao                            &env->CSR_TCFG);
296f8447436STianrui Zhao 
297f8447436STianrui Zhao     return ret;
298f8447436STianrui Zhao }
299f8447436STianrui Zhao 
30061f6e150SBibo Mao static int kvm_loongarch_put_csr(CPUState *cs, int level)
301f8447436STianrui Zhao {
302f8447436STianrui Zhao     int ret = 0;
303f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
304f8447436STianrui Zhao 
305f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CRMD),
306f8447436STianrui Zhao                            &env->CSR_CRMD);
307f8447436STianrui Zhao 
308f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRMD),
309f8447436STianrui Zhao                            &env->CSR_PRMD);
310f8447436STianrui Zhao 
311f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EUEN),
312f8447436STianrui Zhao                            &env->CSR_EUEN);
313f8447436STianrui Zhao 
314f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MISC),
315f8447436STianrui Zhao                            &env->CSR_MISC);
316f8447436STianrui Zhao 
317f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ECFG),
318f8447436STianrui Zhao                            &env->CSR_ECFG);
319f8447436STianrui Zhao 
320f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ESTAT),
321f8447436STianrui Zhao                            &env->CSR_ESTAT);
322f8447436STianrui Zhao 
323f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ERA),
324f8447436STianrui Zhao                            &env->CSR_ERA);
325f8447436STianrui Zhao 
326f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADV),
327f8447436STianrui Zhao                            &env->CSR_BADV);
328f8447436STianrui Zhao 
329f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADI),
330f8447436STianrui Zhao                            &env->CSR_BADI);
331f8447436STianrui Zhao 
332f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EENTRY),
333f8447436STianrui Zhao                            &env->CSR_EENTRY);
334f8447436STianrui Zhao 
335f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBIDX),
336f8447436STianrui Zhao                            &env->CSR_TLBIDX);
337f8447436STianrui Zhao 
338f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBEHI),
339f8447436STianrui Zhao                            &env->CSR_TLBEHI);
340f8447436STianrui Zhao 
341f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO0),
342f8447436STianrui Zhao                            &env->CSR_TLBELO0);
343f8447436STianrui Zhao 
344f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO1),
345f8447436STianrui Zhao                            &env->CSR_TLBELO1);
346f8447436STianrui Zhao 
347f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ASID),
348f8447436STianrui Zhao                            &env->CSR_ASID);
349f8447436STianrui Zhao 
350f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDL),
351f8447436STianrui Zhao                            &env->CSR_PGDL);
352f8447436STianrui Zhao 
353f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDH),
354f8447436STianrui Zhao                            &env->CSR_PGDH);
355f8447436STianrui Zhao 
356f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGD),
357f8447436STianrui Zhao                            &env->CSR_PGD);
358f8447436STianrui Zhao 
359f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCL),
360f8447436STianrui Zhao                            &env->CSR_PWCL);
361f8447436STianrui Zhao 
362f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCH),
363f8447436STianrui Zhao                            &env->CSR_PWCH);
364f8447436STianrui Zhao 
365f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_STLBPS),
366f8447436STianrui Zhao                            &env->CSR_STLBPS);
367f8447436STianrui Zhao 
368f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_RVACFG),
369f8447436STianrui Zhao                            &env->CSR_RVACFG);
370f8447436STianrui Zhao 
37161f6e150SBibo Mao     /* CPUID is constant after poweron, it should be set only once */
37261f6e150SBibo Mao     if (level >= KVM_PUT_FULL_STATE) {
373f8447436STianrui Zhao         ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CPUID),
374f8447436STianrui Zhao                            &env->CSR_CPUID);
37561f6e150SBibo Mao     }
376f8447436STianrui Zhao 
377f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG1),
378f8447436STianrui Zhao                            &env->CSR_PRCFG1);
379f8447436STianrui Zhao 
380f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG2),
381f8447436STianrui Zhao                            &env->CSR_PRCFG2);
382f8447436STianrui Zhao 
383f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG3),
384f8447436STianrui Zhao                            &env->CSR_PRCFG3);
385f8447436STianrui Zhao 
386f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(0)),
387f8447436STianrui Zhao                            &env->CSR_SAVE[0]);
388f8447436STianrui Zhao 
389f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(1)),
390f8447436STianrui Zhao                            &env->CSR_SAVE[1]);
391f8447436STianrui Zhao 
392f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(2)),
393f8447436STianrui Zhao                            &env->CSR_SAVE[2]);
394f8447436STianrui Zhao 
395f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(3)),
396f8447436STianrui Zhao                            &env->CSR_SAVE[3]);
397f8447436STianrui Zhao 
398f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(4)),
399f8447436STianrui Zhao                            &env->CSR_SAVE[4]);
400f8447436STianrui Zhao 
401f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(5)),
402f8447436STianrui Zhao                            &env->CSR_SAVE[5]);
403f8447436STianrui Zhao 
404f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(6)),
405f8447436STianrui Zhao                            &env->CSR_SAVE[6]);
406f8447436STianrui Zhao 
407f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(7)),
408f8447436STianrui Zhao                            &env->CSR_SAVE[7]);
409f8447436STianrui Zhao 
410f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TID),
411f8447436STianrui Zhao                            &env->CSR_TID);
412f8447436STianrui Zhao 
413f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CNTC),
414f8447436STianrui Zhao                            &env->CSR_CNTC);
415f8447436STianrui Zhao 
416f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TICLR),
417f8447436STianrui Zhao                            &env->CSR_TICLR);
418f8447436STianrui Zhao 
419f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_LLBCTL),
420f8447436STianrui Zhao                            &env->CSR_LLBCTL);
421f8447436STianrui Zhao 
422f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL1),
423f8447436STianrui Zhao                            &env->CSR_IMPCTL1);
424f8447436STianrui Zhao 
425f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL2),
426f8447436STianrui Zhao                            &env->CSR_IMPCTL2);
427f8447436STianrui Zhao 
428f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRENTRY),
429f8447436STianrui Zhao                            &env->CSR_TLBRENTRY);
430f8447436STianrui Zhao 
431f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRBADV),
432f8447436STianrui Zhao                            &env->CSR_TLBRBADV);
433f8447436STianrui Zhao 
434f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRERA),
435f8447436STianrui Zhao                            &env->CSR_TLBRERA);
436f8447436STianrui Zhao 
437f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRSAVE),
438f8447436STianrui Zhao                            &env->CSR_TLBRSAVE);
439f8447436STianrui Zhao 
440f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO0),
441f8447436STianrui Zhao                            &env->CSR_TLBRELO0);
442f8447436STianrui Zhao 
443f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO1),
444f8447436STianrui Zhao                            &env->CSR_TLBRELO1);
445f8447436STianrui Zhao 
446f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBREHI),
447f8447436STianrui Zhao                            &env->CSR_TLBREHI);
448f8447436STianrui Zhao 
449f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRPRMD),
450f8447436STianrui Zhao                            &env->CSR_TLBRPRMD);
451f8447436STianrui Zhao 
452f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(0)),
453f8447436STianrui Zhao                            &env->CSR_DMW[0]);
454f8447436STianrui Zhao 
455f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(1)),
456f8447436STianrui Zhao                            &env->CSR_DMW[1]);
457f8447436STianrui Zhao 
458f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(2)),
459f8447436STianrui Zhao                            &env->CSR_DMW[2]);
460f8447436STianrui Zhao 
461f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(3)),
462f8447436STianrui Zhao                            &env->CSR_DMW[3]);
463f8447436STianrui Zhao     /*
464f8447436STianrui Zhao      * timer cfg must be put at last since it is used to enable
465f8447436STianrui Zhao      * guest timer
466f8447436STianrui Zhao      */
467f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TVAL),
468f8447436STianrui Zhao                            &env->CSR_TVAL);
469f8447436STianrui Zhao 
470f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TCFG),
471f8447436STianrui Zhao                            &env->CSR_TCFG);
472f8447436STianrui Zhao     return ret;
473f8447436STianrui Zhao }
474f8447436STianrui Zhao 
475f8447436STianrui Zhao static int kvm_loongarch_get_regs_fp(CPUState *cs)
476f8447436STianrui Zhao {
477f8447436STianrui Zhao     int ret, i;
478f8447436STianrui Zhao     struct kvm_fpu fpu;
479f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
480f8447436STianrui Zhao 
481f8447436STianrui Zhao     ret = kvm_vcpu_ioctl(cs, KVM_GET_FPU, &fpu);
482f8447436STianrui Zhao     if (ret < 0) {
483f8447436STianrui Zhao         trace_kvm_failed_get_fpu(strerror(errno));
484f8447436STianrui Zhao         return ret;
485f8447436STianrui Zhao     }
486f8447436STianrui Zhao 
487f8447436STianrui Zhao     env->fcsr0 = fpu.fcsr;
488f8447436STianrui Zhao     for (i = 0; i < 32; i++) {
489f8447436STianrui Zhao         env->fpr[i].vreg.UD[0] = fpu.fpr[i].val64[0];
49007c08661SSong Gao         env->fpr[i].vreg.UD[1] = fpu.fpr[i].val64[1];
49107c08661SSong Gao         env->fpr[i].vreg.UD[2] = fpu.fpr[i].val64[2];
49207c08661SSong Gao         env->fpr[i].vreg.UD[3] = fpu.fpr[i].val64[3];
493f8447436STianrui Zhao     }
494f8447436STianrui Zhao     for (i = 0; i < 8; i++) {
495f8447436STianrui Zhao         env->cf[i] = fpu.fcc & 0xFF;
496f8447436STianrui Zhao         fpu.fcc = fpu.fcc >> 8;
497f8447436STianrui Zhao     }
498f8447436STianrui Zhao 
499f8447436STianrui Zhao     return ret;
500f8447436STianrui Zhao }
501f8447436STianrui Zhao 
502f8447436STianrui Zhao static int kvm_loongarch_put_regs_fp(CPUState *cs)
503f8447436STianrui Zhao {
504f8447436STianrui Zhao     int ret, i;
505f8447436STianrui Zhao     struct kvm_fpu fpu;
506f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
507f8447436STianrui Zhao 
508f8447436STianrui Zhao     fpu.fcsr = env->fcsr0;
509f8447436STianrui Zhao     fpu.fcc = 0;
510f8447436STianrui Zhao     for (i = 0; i < 32; i++) {
511f8447436STianrui Zhao         fpu.fpr[i].val64[0] = env->fpr[i].vreg.UD[0];
51207c08661SSong Gao         fpu.fpr[i].val64[1] = env->fpr[i].vreg.UD[1];
51307c08661SSong Gao         fpu.fpr[i].val64[2] = env->fpr[i].vreg.UD[2];
51407c08661SSong Gao         fpu.fpr[i].val64[3] = env->fpr[i].vreg.UD[3];
515f8447436STianrui Zhao     }
516f8447436STianrui Zhao 
517f8447436STianrui Zhao     for (i = 0; i < 8; i++) {
518f8447436STianrui Zhao         fpu.fcc |= env->cf[i] << (8 * i);
519f8447436STianrui Zhao     }
520f8447436STianrui Zhao 
521f8447436STianrui Zhao     ret = kvm_vcpu_ioctl(cs, KVM_SET_FPU, &fpu);
522f8447436STianrui Zhao     if (ret < 0) {
523f8447436STianrui Zhao         trace_kvm_failed_put_fpu(strerror(errno));
524f8447436STianrui Zhao     }
525f8447436STianrui Zhao 
526f8447436STianrui Zhao     return ret;
527f8447436STianrui Zhao }
528f8447436STianrui Zhao 
529a45df286SBibo Mao static int kvm_loongarch_put_lbt(CPUState *cs)
530a45df286SBibo Mao {
531a45df286SBibo Mao     CPULoongArchState *env = cpu_env(cs);
532a45df286SBibo Mao     uint64_t val;
533a45df286SBibo Mao     int ret;
534a45df286SBibo Mao 
535a45df286SBibo Mao     /* check whether vm support LBT firstly */
536a45df286SBibo Mao     if (FIELD_EX32(env->cpucfg[2], CPUCFG2, LBT_ALL) != 7) {
537a45df286SBibo Mao         return 0;
538a45df286SBibo Mao     }
539a45df286SBibo Mao 
540a45df286SBibo Mao     /* set six LBT registers including scr0-scr3, eflags, ftop */
541a45df286SBibo Mao     ret = kvm_set_one_reg(cs, KVM_REG_LOONGARCH_LBT_SCR0, &env->lbt.scr0);
542a45df286SBibo Mao     ret |= kvm_set_one_reg(cs, KVM_REG_LOONGARCH_LBT_SCR1, &env->lbt.scr1);
543a45df286SBibo Mao     ret |= kvm_set_one_reg(cs, KVM_REG_LOONGARCH_LBT_SCR2, &env->lbt.scr2);
544a45df286SBibo Mao     ret |= kvm_set_one_reg(cs, KVM_REG_LOONGARCH_LBT_SCR3, &env->lbt.scr3);
545a45df286SBibo Mao     /*
546a45df286SBibo Mao      * Be cautious, KVM_REG_LOONGARCH_LBT_FTOP is defined as 64-bit however
547a45df286SBibo Mao      * lbt.ftop is 32-bit; the same with KVM_REG_LOONGARCH_LBT_EFLAGS register
548a45df286SBibo Mao      */
549a45df286SBibo Mao     val = env->lbt.eflags;
550a45df286SBibo Mao     ret |= kvm_set_one_reg(cs, KVM_REG_LOONGARCH_LBT_EFLAGS, &val);
551a45df286SBibo Mao     val = env->lbt.ftop;
552a45df286SBibo Mao     ret |= kvm_set_one_reg(cs, KVM_REG_LOONGARCH_LBT_FTOP, &val);
553a45df286SBibo Mao 
554a45df286SBibo Mao     return ret;
555a45df286SBibo Mao }
556a45df286SBibo Mao 
557a45df286SBibo Mao static int kvm_loongarch_get_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     /* get six LBT registers including scr0-scr3, eflags, ftop */
569a45df286SBibo Mao     ret = kvm_get_one_reg(cs, KVM_REG_LOONGARCH_LBT_SCR0, &env->lbt.scr0);
570a45df286SBibo Mao     ret |= kvm_get_one_reg(cs, KVM_REG_LOONGARCH_LBT_SCR1, &env->lbt.scr1);
571a45df286SBibo Mao     ret |= kvm_get_one_reg(cs, KVM_REG_LOONGARCH_LBT_SCR2, &env->lbt.scr2);
572a45df286SBibo Mao     ret |= kvm_get_one_reg(cs, KVM_REG_LOONGARCH_LBT_SCR3, &env->lbt.scr3);
573a45df286SBibo Mao     ret |= kvm_get_one_reg(cs, KVM_REG_LOONGARCH_LBT_EFLAGS, &val);
574a45df286SBibo Mao     env->lbt.eflags = (uint32_t)val;
575a45df286SBibo Mao     ret |= kvm_get_one_reg(cs, KVM_REG_LOONGARCH_LBT_FTOP, &val);
576a45df286SBibo Mao     env->lbt.ftop = (uint32_t)val;
577a45df286SBibo Mao 
578a45df286SBibo Mao     return ret;
579a45df286SBibo Mao }
580a45df286SBibo Mao 
581a724f5a8SBibo Mao void kvm_arch_reset_vcpu(CPUState *cs)
582f8447436STianrui Zhao {
583a724f5a8SBibo Mao     CPULoongArchState *env = cpu_env(cs);
584a724f5a8SBibo Mao 
585f8447436STianrui Zhao     env->mp_state = KVM_MP_STATE_RUNNABLE;
586a724f5a8SBibo Mao     kvm_set_one_reg(cs, KVM_REG_LOONGARCH_VCPU_RESET, 0);
587f8447436STianrui Zhao }
588f8447436STianrui Zhao 
589f8447436STianrui Zhao static int kvm_loongarch_get_mpstate(CPUState *cs)
590f8447436STianrui Zhao {
591f8447436STianrui Zhao     int ret = 0;
592f8447436STianrui Zhao     struct kvm_mp_state mp_state;
593f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
594f8447436STianrui Zhao 
595f8447436STianrui Zhao     if (cap_has_mp_state) {
596f8447436STianrui Zhao         ret = kvm_vcpu_ioctl(cs, KVM_GET_MP_STATE, &mp_state);
597f8447436STianrui Zhao         if (ret) {
598f8447436STianrui Zhao             trace_kvm_failed_get_mpstate(strerror(errno));
599f8447436STianrui Zhao             return ret;
600f8447436STianrui Zhao         }
601f8447436STianrui Zhao         env->mp_state = mp_state.mp_state;
602f8447436STianrui Zhao     }
603f8447436STianrui Zhao 
604f8447436STianrui Zhao     return ret;
605f8447436STianrui Zhao }
606f8447436STianrui Zhao 
607f8447436STianrui Zhao static int kvm_loongarch_put_mpstate(CPUState *cs)
608f8447436STianrui Zhao {
609f8447436STianrui Zhao     int ret = 0;
610f8447436STianrui Zhao     struct kvm_mp_state mp_state = {
611f3b603b9SPhilippe Mathieu-Daudé         .mp_state = cpu_env(cs)->mp_state
612f8447436STianrui Zhao     };
613f8447436STianrui Zhao 
614f8447436STianrui Zhao     if (cap_has_mp_state) {
615f8447436STianrui Zhao         ret = kvm_vcpu_ioctl(cs, KVM_SET_MP_STATE, &mp_state);
616f8447436STianrui Zhao         if (ret) {
617f8447436STianrui Zhao             trace_kvm_failed_put_mpstate(strerror(errno));
618f8447436STianrui Zhao         }
619f8447436STianrui Zhao     }
620f8447436STianrui Zhao 
621f8447436STianrui Zhao     return ret;
622f8447436STianrui Zhao }
623f8447436STianrui Zhao 
624f8447436STianrui Zhao static int kvm_loongarch_get_cpucfg(CPUState *cs)
625f8447436STianrui Zhao {
626f8447436STianrui Zhao     int i, ret = 0;
627f8447436STianrui Zhao     uint64_t val;
628f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
629f8447436STianrui Zhao 
630f8447436STianrui Zhao     for (i = 0; i < 21; i++) {
631f8447436STianrui Zhao         ret = kvm_get_one_reg(cs, KVM_IOC_CPUCFG(i), &val);
632f8447436STianrui Zhao         if (ret < 0) {
633f8447436STianrui Zhao             trace_kvm_failed_get_cpucfg(strerror(errno));
634f8447436STianrui Zhao         }
635f8447436STianrui Zhao         env->cpucfg[i] = (uint32_t)val;
636f8447436STianrui Zhao     }
637f8447436STianrui Zhao     return ret;
638f8447436STianrui Zhao }
639f8447436STianrui Zhao 
640fc700996SSong Gao static int kvm_check_cpucfg2(CPUState *cs)
641fc700996SSong Gao {
642fc700996SSong Gao     int ret;
643fc700996SSong Gao     uint64_t val;
644fc700996SSong Gao     struct kvm_device_attr attr = {
645fc700996SSong Gao         .group = KVM_LOONGARCH_VCPU_CPUCFG,
646fc700996SSong Gao         .attr = 2,
647fc700996SSong Gao         .addr = (uint64_t)&val,
648fc700996SSong Gao     };
649f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
650fc700996SSong Gao 
651fc700996SSong Gao     ret = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, &attr);
652fc700996SSong Gao 
653fc700996SSong Gao     if (!ret) {
654fc700996SSong Gao         kvm_vcpu_ioctl(cs, KVM_GET_DEVICE_ATTR, &attr);
655fc700996SSong Gao         env->cpucfg[2] &= val;
656fc700996SSong Gao 
657fc700996SSong Gao         if (FIELD_EX32(env->cpucfg[2], CPUCFG2, FP)) {
658fc700996SSong Gao             /* The FP minimal version is 1. */
659fc700996SSong Gao             env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, FP_VER, 1);
660fc700996SSong Gao         }
661fc700996SSong Gao 
662fc700996SSong Gao         if (FIELD_EX32(env->cpucfg[2], CPUCFG2, LLFTP)) {
663fc700996SSong Gao             /* The LLFTP minimal version is 1. */
664fc700996SSong Gao             env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LLFTP_VER, 1);
665fc700996SSong Gao         }
666fc700996SSong Gao     }
667fc700996SSong Gao 
668fc700996SSong Gao     return ret;
669fc700996SSong Gao }
670fc700996SSong Gao 
671f8447436STianrui Zhao static int kvm_loongarch_put_cpucfg(CPUState *cs)
672f8447436STianrui Zhao {
673f8447436STianrui Zhao     int i, ret = 0;
674f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
675f8447436STianrui Zhao     uint64_t val;
676f8447436STianrui Zhao 
677f8447436STianrui Zhao     for (i = 0; i < 21; i++) {
678f8447436STianrui Zhao 	if (i == 2) {
679fc700996SSong Gao             ret = kvm_check_cpucfg2(cs);
680fc700996SSong Gao             if (ret) {
681fc700996SSong Gao                 return ret;
682f8447436STianrui Zhao             }
683fc700996SSong Gao 	}
684fc700996SSong Gao         val = env->cpucfg[i];
685f8447436STianrui Zhao         ret = kvm_set_one_reg(cs, KVM_IOC_CPUCFG(i), &val);
686f8447436STianrui Zhao         if (ret < 0) {
687f8447436STianrui Zhao             trace_kvm_failed_put_cpucfg(strerror(errno));
688f8447436STianrui Zhao         }
689f8447436STianrui Zhao     }
690f8447436STianrui Zhao     return ret;
691f8447436STianrui Zhao }
692f8447436STianrui Zhao 
693a1676bb3SJulia Suvorova int kvm_arch_get_registers(CPUState *cs, Error **errp)
694537ba9daSTianrui Zhao {
695f8447436STianrui Zhao     int ret;
696f8447436STianrui Zhao 
697f8447436STianrui Zhao     ret = kvm_loongarch_get_regs_core(cs);
698f8447436STianrui Zhao     if (ret) {
699f8447436STianrui Zhao         return ret;
700537ba9daSTianrui Zhao     }
701f8447436STianrui Zhao 
7025872966dSBibo Mao     ret = kvm_loongarch_get_cpucfg(cs);
7035872966dSBibo Mao     if (ret) {
7045872966dSBibo Mao         return ret;
7055872966dSBibo Mao     }
7065872966dSBibo Mao 
707f8447436STianrui Zhao     ret = kvm_loongarch_get_csr(cs);
708f8447436STianrui Zhao     if (ret) {
709f8447436STianrui Zhao         return ret;
710f8447436STianrui Zhao     }
711f8447436STianrui Zhao 
712f8447436STianrui Zhao     ret = kvm_loongarch_get_regs_fp(cs);
713f8447436STianrui Zhao     if (ret) {
714f8447436STianrui Zhao         return ret;
715f8447436STianrui Zhao     }
716f8447436STianrui Zhao 
717a45df286SBibo Mao     ret = kvm_loongarch_get_lbt(cs);
718a45df286SBibo Mao     if (ret) {
719a45df286SBibo Mao         return ret;
720a45df286SBibo Mao     }
721a45df286SBibo Mao 
72247b54e15SBibo Mao     ret = kvm_get_stealtime(cs);
72347b54e15SBibo Mao     if (ret) {
72447b54e15SBibo Mao         return ret;
72547b54e15SBibo Mao     }
72647b54e15SBibo Mao 
727f8447436STianrui Zhao     ret = kvm_loongarch_get_mpstate(cs);
728f8447436STianrui Zhao     return ret;
729f8447436STianrui Zhao }
730f8447436STianrui Zhao 
731a1676bb3SJulia Suvorova int kvm_arch_put_registers(CPUState *cs, int level, Error **errp)
732537ba9daSTianrui Zhao {
733f8447436STianrui Zhao     int ret;
734f8447436STianrui Zhao 
735f8447436STianrui Zhao     ret = kvm_loongarch_put_regs_core(cs);
736f8447436STianrui Zhao     if (ret) {
737f8447436STianrui Zhao         return ret;
738f8447436STianrui Zhao     }
739f8447436STianrui Zhao 
7405872966dSBibo Mao     ret = kvm_loongarch_put_cpucfg(cs);
7415872966dSBibo Mao     if (ret) {
7425872966dSBibo Mao         return ret;
7435872966dSBibo Mao     }
7445872966dSBibo Mao 
74561f6e150SBibo Mao     ret = kvm_loongarch_put_csr(cs, level);
746f8447436STianrui Zhao     if (ret) {
747f8447436STianrui Zhao         return ret;
748f8447436STianrui Zhao     }
749f8447436STianrui Zhao 
750f8447436STianrui Zhao     ret = kvm_loongarch_put_regs_fp(cs);
751f8447436STianrui Zhao     if (ret) {
752f8447436STianrui Zhao         return ret;
753f8447436STianrui Zhao     }
754f8447436STianrui Zhao 
755a45df286SBibo Mao     ret = kvm_loongarch_put_lbt(cs);
756a45df286SBibo Mao     if (ret) {
757a45df286SBibo Mao         return ret;
758a45df286SBibo Mao     }
759a45df286SBibo Mao 
76047b54e15SBibo Mao     if (level >= KVM_PUT_FULL_STATE) {
76147b54e15SBibo Mao         /*
76247b54e15SBibo Mao          * only KVM_PUT_FULL_STATE is required, kvm kernel will clear
76347b54e15SBibo Mao          * guest_addr for KVM_PUT_RESET_STATE
76447b54e15SBibo Mao          */
76547b54e15SBibo Mao         ret = kvm_set_stealtime(cs);
76647b54e15SBibo Mao         if (ret) {
76747b54e15SBibo Mao             return ret;
76847b54e15SBibo Mao         }
76947b54e15SBibo Mao     }
77047b54e15SBibo Mao 
771f8447436STianrui Zhao     ret = kvm_loongarch_put_mpstate(cs);
772f8447436STianrui Zhao     return ret;
773537ba9daSTianrui Zhao }
774537ba9daSTianrui Zhao 
775d11681c9STianrui Zhao static void kvm_loongarch_vm_stage_change(void *opaque, bool running,
776d11681c9STianrui Zhao                                           RunState state)
777d11681c9STianrui Zhao {
778d11681c9STianrui Zhao     int ret;
779d11681c9STianrui Zhao     CPUState *cs = opaque;
780d11681c9STianrui Zhao     LoongArchCPU *cpu = LOONGARCH_CPU(cs);
781d11681c9STianrui Zhao 
782d11681c9STianrui Zhao     if (running) {
783d11681c9STianrui Zhao         ret = kvm_set_one_reg(cs, KVM_REG_LOONGARCH_COUNTER,
784d11681c9STianrui Zhao                               &cpu->kvm_state_counter);
785d11681c9STianrui Zhao         if (ret < 0) {
786d11681c9STianrui Zhao             trace_kvm_failed_put_counter(strerror(errno));
787d11681c9STianrui Zhao         }
788d11681c9STianrui Zhao     } else {
789d11681c9STianrui Zhao         ret = kvm_get_one_reg(cs, KVM_REG_LOONGARCH_COUNTER,
790d11681c9STianrui Zhao                               &cpu->kvm_state_counter);
791d11681c9STianrui Zhao         if (ret < 0) {
792d11681c9STianrui Zhao             trace_kvm_failed_get_counter(strerror(errno));
793d11681c9STianrui Zhao         }
794d11681c9STianrui Zhao     }
795d11681c9STianrui Zhao }
796d11681c9STianrui Zhao 
797c23a53d8SBibo Mao static bool kvm_feature_supported(CPUState *cs, enum loongarch_features feature)
798c23a53d8SBibo Mao {
799c23a53d8SBibo Mao     int ret;
800c23a53d8SBibo Mao     struct kvm_device_attr attr;
801c23a53d8SBibo Mao 
802c23a53d8SBibo Mao     switch (feature) {
803c23a53d8SBibo Mao     case LOONGARCH_FEATURE_LBT:
804c23a53d8SBibo Mao         /*
805c23a53d8SBibo Mao          * Return all if all the LBT features are supported such as:
806c23a53d8SBibo Mao          *  KVM_LOONGARCH_VM_FEAT_X86BT
807c23a53d8SBibo Mao          *  KVM_LOONGARCH_VM_FEAT_ARMBT
808c23a53d8SBibo Mao          *  KVM_LOONGARCH_VM_FEAT_MIPSBT
809c23a53d8SBibo Mao          */
810c23a53d8SBibo Mao         attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
811c23a53d8SBibo Mao         attr.attr = KVM_LOONGARCH_VM_FEAT_X86BT;
812c23a53d8SBibo Mao         ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
813c23a53d8SBibo Mao         attr.attr = KVM_LOONGARCH_VM_FEAT_ARMBT;
814c23a53d8SBibo Mao         ret |= kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
815c23a53d8SBibo Mao         attr.attr = KVM_LOONGARCH_VM_FEAT_MIPSBT;
816c23a53d8SBibo Mao         ret |= kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
817c23a53d8SBibo Mao         return (ret == 0);
8186edd2a9bSBibo Mao 
8196edd2a9bSBibo Mao     case LOONGARCH_FEATURE_PMU:
8206edd2a9bSBibo Mao         attr.group = KVM_LOONGARCH_VM_FEAT_CTRL;
8216edd2a9bSBibo Mao         attr.attr = KVM_LOONGARCH_VM_FEAT_PMU;
8226edd2a9bSBibo Mao         ret = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, &attr);
8236edd2a9bSBibo Mao         return (ret == 0);
8246edd2a9bSBibo Mao 
825c23a53d8SBibo Mao     default:
826c23a53d8SBibo Mao         return false;
827c23a53d8SBibo Mao     }
8286edd2a9bSBibo Mao 
8296edd2a9bSBibo Mao     return false;
830c23a53d8SBibo Mao }
831c23a53d8SBibo Mao 
832c23a53d8SBibo Mao static int kvm_cpu_check_lbt(CPUState *cs, Error **errp)
833c23a53d8SBibo Mao {
834c23a53d8SBibo Mao     CPULoongArchState *env = cpu_env(cs);
835c23a53d8SBibo Mao     LoongArchCPU *cpu = LOONGARCH_CPU(cs);
836c23a53d8SBibo Mao     bool kvm_supported;
837c23a53d8SBibo Mao 
838c23a53d8SBibo Mao     kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_LBT);
839c23a53d8SBibo Mao     if (cpu->lbt == ON_OFF_AUTO_ON) {
840c23a53d8SBibo Mao         if (kvm_supported) {
841c23a53d8SBibo Mao             env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LBT_ALL, 7);
842c23a53d8SBibo Mao         } else {
843c23a53d8SBibo Mao             error_setg(errp, "'lbt' feature not supported by KVM on this host");
844c23a53d8SBibo Mao             return -ENOTSUP;
845c23a53d8SBibo Mao         }
846c23a53d8SBibo Mao     } else if ((cpu->lbt == ON_OFF_AUTO_AUTO) && kvm_supported) {
847c23a53d8SBibo Mao         env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LBT_ALL, 7);
848c23a53d8SBibo Mao     }
849c23a53d8SBibo Mao 
850c23a53d8SBibo Mao     return 0;
851c23a53d8SBibo Mao }
852c23a53d8SBibo Mao 
8536edd2a9bSBibo Mao static int kvm_cpu_check_pmu(CPUState *cs, Error **errp)
8546edd2a9bSBibo Mao {
8556edd2a9bSBibo Mao     LoongArchCPU *cpu = LOONGARCH_CPU(cs);
8566edd2a9bSBibo Mao     CPULoongArchState *env = cpu_env(cs);
8576edd2a9bSBibo Mao     bool kvm_supported;
8586edd2a9bSBibo Mao 
8596edd2a9bSBibo Mao     kvm_supported = kvm_feature_supported(cs, LOONGARCH_FEATURE_PMU);
8606edd2a9bSBibo Mao     if (cpu->pmu == ON_OFF_AUTO_ON) {
8616edd2a9bSBibo Mao         if (!kvm_supported) {
8626edd2a9bSBibo Mao             error_setg(errp, "'pmu' feature not supported by KVM on the host");
8636edd2a9bSBibo Mao             return -ENOTSUP;
8646edd2a9bSBibo Mao         }
8656edd2a9bSBibo Mao     } else if (cpu->pmu != ON_OFF_AUTO_AUTO) {
8666edd2a9bSBibo Mao         /* disable pmu if ON_OFF_AUTO_OFF is set */
8676edd2a9bSBibo Mao         kvm_supported = false;
8686edd2a9bSBibo Mao     }
8696edd2a9bSBibo Mao 
8706edd2a9bSBibo Mao     if (kvm_supported) {
8716edd2a9bSBibo Mao         env->cpucfg[6] = FIELD_DP32(env->cpucfg[6], CPUCFG6, PMP, 1);
8726edd2a9bSBibo Mao         env->cpucfg[6] = FIELD_DP32(env->cpucfg[6], CPUCFG6, PMNUM, 3);
8736edd2a9bSBibo Mao         env->cpucfg[6] = FIELD_DP32(env->cpucfg[6], CPUCFG6, PMBITS, 63);
8746edd2a9bSBibo Mao         env->cpucfg[6] = FIELD_DP32(env->cpucfg[6], CPUCFG6, UPM, 1);
8756edd2a9bSBibo Mao     }
8766edd2a9bSBibo Mao     return 0;
8776edd2a9bSBibo Mao }
8786edd2a9bSBibo Mao 
879537ba9daSTianrui Zhao int kvm_arch_init_vcpu(CPUState *cs)
880537ba9daSTianrui Zhao {
881d38e31efSBibo Mao     uint64_t val;
882c23a53d8SBibo Mao     int ret;
883c23a53d8SBibo Mao     Error *local_err = NULL;
884d38e31efSBibo Mao 
885c23a53d8SBibo Mao     ret = 0;
886d11681c9STianrui Zhao     qemu_add_vm_change_state_handler(kvm_loongarch_vm_stage_change, cs);
887d38e31efSBibo Mao 
888d38e31efSBibo Mao     if (!kvm_get_one_reg(cs, KVM_REG_LOONGARCH_DEBUG_INST, &val)) {
889d38e31efSBibo Mao         brk_insn = val;
890d38e31efSBibo Mao     }
891d38e31efSBibo Mao 
892c23a53d8SBibo Mao     ret = kvm_cpu_check_lbt(cs, &local_err);
893c23a53d8SBibo Mao     if (ret < 0) {
894c23a53d8SBibo Mao         error_report_err(local_err);
895c23a53d8SBibo Mao     }
8966edd2a9bSBibo Mao 
8976edd2a9bSBibo Mao     ret = kvm_cpu_check_pmu(cs, &local_err);
8986edd2a9bSBibo Mao     if (ret < 0) {
8996edd2a9bSBibo Mao         error_report_err(local_err);
9006edd2a9bSBibo Mao     }
9016edd2a9bSBibo Mao 
902c23a53d8SBibo Mao     return ret;
903537ba9daSTianrui Zhao }
904537ba9daSTianrui Zhao 
905537ba9daSTianrui Zhao int kvm_arch_destroy_vcpu(CPUState *cs)
906537ba9daSTianrui Zhao {
907537ba9daSTianrui Zhao     return 0;
908537ba9daSTianrui Zhao }
909537ba9daSTianrui Zhao 
910537ba9daSTianrui Zhao unsigned long kvm_arch_vcpu_id(CPUState *cs)
911537ba9daSTianrui Zhao {
912537ba9daSTianrui Zhao     return cs->cpu_index;
913537ba9daSTianrui Zhao }
914537ba9daSTianrui Zhao 
915537ba9daSTianrui Zhao int kvm_arch_release_virq_post(int virq)
916537ba9daSTianrui Zhao {
917537ba9daSTianrui Zhao     return 0;
918537ba9daSTianrui Zhao }
919537ba9daSTianrui Zhao 
920537ba9daSTianrui Zhao int kvm_arch_msi_data_to_gsi(uint32_t data)
921537ba9daSTianrui Zhao {
922537ba9daSTianrui Zhao     abort();
923537ba9daSTianrui Zhao }
924537ba9daSTianrui Zhao 
925537ba9daSTianrui Zhao int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
926537ba9daSTianrui Zhao                              uint64_t address, uint32_t data, PCIDevice *dev)
927537ba9daSTianrui Zhao {
928537ba9daSTianrui Zhao     return 0;
929537ba9daSTianrui Zhao }
930537ba9daSTianrui Zhao 
931537ba9daSTianrui Zhao int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
932537ba9daSTianrui Zhao                                 int vector, PCIDevice *dev)
933537ba9daSTianrui Zhao {
934537ba9daSTianrui Zhao     return 0;
935537ba9daSTianrui Zhao }
936537ba9daSTianrui Zhao 
937537ba9daSTianrui Zhao void kvm_arch_init_irq_routing(KVMState *s)
938537ba9daSTianrui Zhao {
939537ba9daSTianrui Zhao }
940537ba9daSTianrui Zhao 
941537ba9daSTianrui Zhao int kvm_arch_get_default_type(MachineState *ms)
942537ba9daSTianrui Zhao {
943537ba9daSTianrui Zhao     return 0;
944537ba9daSTianrui Zhao }
945537ba9daSTianrui Zhao 
946537ba9daSTianrui Zhao int kvm_arch_init(MachineState *ms, KVMState *s)
947537ba9daSTianrui Zhao {
94841958c99STianrui Zhao     cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
949537ba9daSTianrui Zhao     return 0;
950537ba9daSTianrui Zhao }
951537ba9daSTianrui Zhao 
952537ba9daSTianrui Zhao int kvm_arch_irqchip_create(KVMState *s)
953537ba9daSTianrui Zhao {
954537ba9daSTianrui Zhao     return 0;
955537ba9daSTianrui Zhao }
956537ba9daSTianrui Zhao 
957537ba9daSTianrui Zhao void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
958537ba9daSTianrui Zhao {
959537ba9daSTianrui Zhao }
960537ba9daSTianrui Zhao 
961537ba9daSTianrui Zhao MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
962537ba9daSTianrui Zhao {
963537ba9daSTianrui Zhao     return MEMTXATTRS_UNSPECIFIED;
964537ba9daSTianrui Zhao }
965537ba9daSTianrui Zhao 
966537ba9daSTianrui Zhao int kvm_arch_process_async_events(CPUState *cs)
967537ba9daSTianrui Zhao {
968537ba9daSTianrui Zhao     return cs->halted;
969537ba9daSTianrui Zhao }
970537ba9daSTianrui Zhao 
971537ba9daSTianrui Zhao bool kvm_arch_stop_on_emulation_error(CPUState *cs)
972537ba9daSTianrui Zhao {
973537ba9daSTianrui Zhao     return true;
974537ba9daSTianrui Zhao }
975537ba9daSTianrui Zhao 
976d38e31efSBibo Mao void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg)
977d38e31efSBibo Mao {
978d38e31efSBibo Mao     if (kvm_sw_breakpoints_active(cpu)) {
979d38e31efSBibo Mao         dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
980d38e31efSBibo Mao     }
981d38e31efSBibo Mao }
982d38e31efSBibo Mao 
983d38e31efSBibo Mao int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
984d38e31efSBibo Mao {
985d38e31efSBibo Mao     if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 4, 0) ||
986d38e31efSBibo Mao         cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&brk_insn, 4, 1)) {
987d38e31efSBibo Mao         error_report("%s failed", __func__);
988d38e31efSBibo Mao         return -EINVAL;
989d38e31efSBibo Mao     }
990d38e31efSBibo Mao     return 0;
991d38e31efSBibo Mao }
992d38e31efSBibo Mao 
993d38e31efSBibo Mao int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
994d38e31efSBibo Mao {
995d38e31efSBibo Mao     static uint32_t brk;
996d38e31efSBibo Mao 
997d38e31efSBibo Mao     if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&brk, 4, 0) ||
998d38e31efSBibo Mao         brk != brk_insn ||
999d38e31efSBibo Mao         cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 4, 1)) {
1000d38e31efSBibo Mao         error_report("%s failed", __func__);
1001d38e31efSBibo Mao         return -EINVAL;
1002d38e31efSBibo Mao     }
1003d38e31efSBibo Mao     return 0;
1004d38e31efSBibo Mao }
1005d38e31efSBibo Mao 
1006d38e31efSBibo Mao int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type)
1007d38e31efSBibo Mao {
1008d38e31efSBibo Mao     return -ENOSYS;
1009d38e31efSBibo Mao }
1010d38e31efSBibo Mao 
1011d38e31efSBibo Mao int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type)
1012d38e31efSBibo Mao {
1013d38e31efSBibo Mao     return -ENOSYS;
1014d38e31efSBibo Mao }
1015d38e31efSBibo Mao 
1016d38e31efSBibo Mao void kvm_arch_remove_all_hw_breakpoints(void)
1017d38e31efSBibo Mao {
1018d38e31efSBibo Mao }
1019d38e31efSBibo Mao 
1020d38e31efSBibo Mao static bool kvm_loongarch_handle_debug(CPUState *cs, struct kvm_run *run)
1021d38e31efSBibo Mao {
1022d38e31efSBibo Mao     LoongArchCPU *cpu = LOONGARCH_CPU(cs);
1023d38e31efSBibo Mao     CPULoongArchState *env = &cpu->env;
1024d38e31efSBibo Mao 
1025d38e31efSBibo Mao     kvm_cpu_synchronize_state(cs);
1026d38e31efSBibo Mao     if (cs->singlestep_enabled) {
1027d38e31efSBibo Mao         return true;
1028d38e31efSBibo Mao     }
1029d38e31efSBibo Mao 
1030d38e31efSBibo Mao     if (kvm_find_sw_breakpoint(cs, env->pc)) {
1031d38e31efSBibo Mao         return true;
1032d38e31efSBibo Mao     }
1033d38e31efSBibo Mao 
1034d38e31efSBibo Mao     return false;
1035d38e31efSBibo Mao }
1036d38e31efSBibo Mao 
1037537ba9daSTianrui Zhao int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
1038537ba9daSTianrui Zhao {
1039a05a950fSTianrui Zhao     int ret = 0;
1040f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
1041a05a950fSTianrui Zhao     MemTxAttrs attrs = {};
1042a05a950fSTianrui Zhao 
1043a05a950fSTianrui Zhao     attrs.requester_id = env_cpu(env)->cpu_index;
1044a05a950fSTianrui Zhao 
1045a05a950fSTianrui Zhao     trace_kvm_arch_handle_exit(run->exit_reason);
1046a05a950fSTianrui Zhao     switch (run->exit_reason) {
1047a05a950fSTianrui Zhao     case KVM_EXIT_LOONGARCH_IOCSR:
10485e90b8dbSBibo Mao         address_space_rw(env->address_space_iocsr,
1049a05a950fSTianrui Zhao                          run->iocsr_io.phys_addr,
1050a05a950fSTianrui Zhao                          attrs,
1051a05a950fSTianrui Zhao                          run->iocsr_io.data,
1052a05a950fSTianrui Zhao                          run->iocsr_io.len,
1053a05a950fSTianrui Zhao                          run->iocsr_io.is_write);
1054a05a950fSTianrui Zhao         break;
1055d38e31efSBibo Mao 
1056d38e31efSBibo Mao     case KVM_EXIT_DEBUG:
1057d38e31efSBibo Mao         if (kvm_loongarch_handle_debug(cs, run)) {
1058d38e31efSBibo Mao             ret = EXCP_DEBUG;
1059d38e31efSBibo Mao         }
1060d38e31efSBibo Mao         break;
1061d38e31efSBibo Mao 
1062a05a950fSTianrui Zhao     default:
1063a05a950fSTianrui Zhao         ret = -1;
1064a05a950fSTianrui Zhao         warn_report("KVM: unknown exit reason %d", run->exit_reason);
1065a05a950fSTianrui Zhao         break;
1066a05a950fSTianrui Zhao     }
1067a05a950fSTianrui Zhao     return ret;
1068537ba9daSTianrui Zhao }
1069537ba9daSTianrui Zhao 
10708dcbad51STianrui Zhao int kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level)
10718dcbad51STianrui Zhao {
10728dcbad51STianrui Zhao     struct kvm_interrupt intr;
10738dcbad51STianrui Zhao     CPUState *cs = CPU(cpu);
10748dcbad51STianrui Zhao 
10758dcbad51STianrui Zhao     if (level) {
10768dcbad51STianrui Zhao         intr.irq = irq;
10778dcbad51STianrui Zhao     } else {
10788dcbad51STianrui Zhao         intr.irq = -irq;
10798dcbad51STianrui Zhao     }
10808dcbad51STianrui Zhao 
10818dcbad51STianrui Zhao     trace_kvm_set_intr(irq, level);
10828dcbad51STianrui Zhao     return kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
10838dcbad51STianrui Zhao }
10848dcbad51STianrui Zhao 
1085537ba9daSTianrui Zhao void kvm_arch_accel_class_init(ObjectClass *oc)
1086537ba9daSTianrui Zhao {
1087537ba9daSTianrui Zhao }
1088