xref: /qemu/target/loongarch/kvm/kvm.c (revision a724f5a84ef027cd481a18eda67ea2de58282c3e)
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 
12537ba9daSTianrui Zhao #include "qemu/timer.h"
13537ba9daSTianrui Zhao #include "qemu/error-report.h"
14537ba9daSTianrui Zhao #include "qemu/main-loop.h"
15537ba9daSTianrui Zhao #include "sysemu/sysemu.h"
16537ba9daSTianrui Zhao #include "sysemu/kvm.h"
17537ba9daSTianrui Zhao #include "sysemu/kvm_int.h"
18537ba9daSTianrui Zhao #include "hw/pci/pci.h"
19537ba9daSTianrui Zhao #include "exec/memattrs.h"
20537ba9daSTianrui Zhao #include "exec/address-spaces.h"
21537ba9daSTianrui Zhao #include "hw/boards.h"
22537ba9daSTianrui Zhao #include "hw/irq.h"
23537ba9daSTianrui Zhao #include "qemu/log.h"
24537ba9daSTianrui Zhao #include "hw/loader.h"
25537ba9daSTianrui Zhao #include "sysemu/runstate.h"
26537ba9daSTianrui Zhao #include "cpu-csr.h"
27537ba9daSTianrui Zhao #include "kvm_loongarch.h"
28f8447436STianrui Zhao #include "trace.h"
29537ba9daSTianrui Zhao 
30537ba9daSTianrui Zhao static bool cap_has_mp_state;
31d38e31efSBibo Mao static unsigned int brk_insn;
32537ba9daSTianrui Zhao const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
33537ba9daSTianrui Zhao     KVM_CAP_LAST_INFO
34537ba9daSTianrui Zhao };
35537ba9daSTianrui Zhao 
36f8447436STianrui Zhao static int kvm_loongarch_get_regs_core(CPUState *cs)
37f8447436STianrui Zhao {
38f8447436STianrui Zhao     int ret = 0;
39f8447436STianrui Zhao     int i;
40f8447436STianrui Zhao     struct kvm_regs regs;
41f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
42f8447436STianrui Zhao 
43f8447436STianrui Zhao     /* Get the current register set as KVM seems it */
44f8447436STianrui Zhao     ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, &regs);
45f8447436STianrui Zhao     if (ret < 0) {
46f8447436STianrui Zhao         trace_kvm_failed_get_regs_core(strerror(errno));
47f8447436STianrui Zhao         return ret;
48f8447436STianrui Zhao     }
49f8447436STianrui Zhao     /* gpr[0] value is always 0 */
50f8447436STianrui Zhao     env->gpr[0] = 0;
51f8447436STianrui Zhao     for (i = 1; i < 32; i++) {
52f8447436STianrui Zhao         env->gpr[i] = regs.gpr[i];
53f8447436STianrui Zhao     }
54f8447436STianrui Zhao 
55f8447436STianrui Zhao     env->pc = regs.pc;
56f8447436STianrui Zhao     return ret;
57f8447436STianrui Zhao }
58f8447436STianrui Zhao 
59f8447436STianrui Zhao static int kvm_loongarch_put_regs_core(CPUState *cs)
60f8447436STianrui Zhao {
61f8447436STianrui Zhao     int ret = 0;
62f8447436STianrui Zhao     int i;
63f8447436STianrui Zhao     struct kvm_regs regs;
64f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
65f8447436STianrui Zhao 
66f8447436STianrui Zhao     /* Set the registers based on QEMU's view of things */
67f8447436STianrui Zhao     for (i = 0; i < 32; i++) {
68f8447436STianrui Zhao         regs.gpr[i] = env->gpr[i];
69f8447436STianrui Zhao     }
70f8447436STianrui Zhao 
71f8447436STianrui Zhao     regs.pc = env->pc;
72f8447436STianrui Zhao     ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, &regs);
73f8447436STianrui Zhao     if (ret < 0) {
74f8447436STianrui Zhao         trace_kvm_failed_put_regs_core(strerror(errno));
75f8447436STianrui Zhao     }
76f8447436STianrui Zhao 
77f8447436STianrui Zhao     return ret;
78f8447436STianrui Zhao }
79f8447436STianrui Zhao 
80f8447436STianrui Zhao static int kvm_loongarch_get_csr(CPUState *cs)
81f8447436STianrui Zhao {
82f8447436STianrui Zhao     int ret = 0;
83f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
84f8447436STianrui Zhao 
85f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CRMD),
86f8447436STianrui Zhao                            &env->CSR_CRMD);
87f8447436STianrui Zhao 
88f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRMD),
89f8447436STianrui Zhao                            &env->CSR_PRMD);
90f8447436STianrui Zhao 
91f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EUEN),
92f8447436STianrui Zhao                            &env->CSR_EUEN);
93f8447436STianrui Zhao 
94f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MISC),
95f8447436STianrui Zhao                            &env->CSR_MISC);
96f8447436STianrui Zhao 
97f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ECFG),
98f8447436STianrui Zhao                            &env->CSR_ECFG);
99f8447436STianrui Zhao 
100f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ESTAT),
101f8447436STianrui Zhao                            &env->CSR_ESTAT);
102f8447436STianrui Zhao 
103f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ERA),
104f8447436STianrui Zhao                            &env->CSR_ERA);
105f8447436STianrui Zhao 
106f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADV),
107f8447436STianrui Zhao                            &env->CSR_BADV);
108f8447436STianrui Zhao 
109f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADI),
110f8447436STianrui Zhao                            &env->CSR_BADI);
111f8447436STianrui Zhao 
112f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EENTRY),
113f8447436STianrui Zhao                            &env->CSR_EENTRY);
114f8447436STianrui Zhao 
115f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBIDX),
116f8447436STianrui Zhao                            &env->CSR_TLBIDX);
117f8447436STianrui Zhao 
118f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBEHI),
119f8447436STianrui Zhao                            &env->CSR_TLBEHI);
120f8447436STianrui Zhao 
121f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO0),
122f8447436STianrui Zhao                            &env->CSR_TLBELO0);
123f8447436STianrui Zhao 
124f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO1),
125f8447436STianrui Zhao                            &env->CSR_TLBELO1);
126f8447436STianrui Zhao 
127f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ASID),
128f8447436STianrui Zhao                            &env->CSR_ASID);
129f8447436STianrui Zhao 
130f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDL),
131f8447436STianrui Zhao                            &env->CSR_PGDL);
132f8447436STianrui Zhao 
133f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDH),
134f8447436STianrui Zhao                            &env->CSR_PGDH);
135f8447436STianrui Zhao 
136f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGD),
137f8447436STianrui Zhao                            &env->CSR_PGD);
138f8447436STianrui Zhao 
139f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCL),
140f8447436STianrui Zhao                            &env->CSR_PWCL);
141f8447436STianrui Zhao 
142f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCH),
143f8447436STianrui Zhao                            &env->CSR_PWCH);
144f8447436STianrui Zhao 
145f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_STLBPS),
146f8447436STianrui Zhao                            &env->CSR_STLBPS);
147f8447436STianrui Zhao 
148f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_RVACFG),
149f8447436STianrui Zhao                            &env->CSR_RVACFG);
150f8447436STianrui Zhao 
151f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CPUID),
152f8447436STianrui Zhao                            &env->CSR_CPUID);
153f8447436STianrui Zhao 
154f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG1),
155f8447436STianrui Zhao                            &env->CSR_PRCFG1);
156f8447436STianrui Zhao 
157f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG2),
158f8447436STianrui Zhao                            &env->CSR_PRCFG2);
159f8447436STianrui Zhao 
160f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG3),
161f8447436STianrui Zhao                            &env->CSR_PRCFG3);
162f8447436STianrui Zhao 
163f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(0)),
164f8447436STianrui Zhao                            &env->CSR_SAVE[0]);
165f8447436STianrui Zhao 
166f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(1)),
167f8447436STianrui Zhao                            &env->CSR_SAVE[1]);
168f8447436STianrui Zhao 
169f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(2)),
170f8447436STianrui Zhao                            &env->CSR_SAVE[2]);
171f8447436STianrui Zhao 
172f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(3)),
173f8447436STianrui Zhao                            &env->CSR_SAVE[3]);
174f8447436STianrui Zhao 
175f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(4)),
176f8447436STianrui Zhao                            &env->CSR_SAVE[4]);
177f8447436STianrui Zhao 
178f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(5)),
179f8447436STianrui Zhao                            &env->CSR_SAVE[5]);
180f8447436STianrui Zhao 
181f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(6)),
182f8447436STianrui Zhao                            &env->CSR_SAVE[6]);
183f8447436STianrui Zhao 
184f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(7)),
185f8447436STianrui Zhao                            &env->CSR_SAVE[7]);
186f8447436STianrui Zhao 
187f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TID),
188f8447436STianrui Zhao                            &env->CSR_TID);
189f8447436STianrui Zhao 
190f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CNTC),
191f8447436STianrui Zhao                            &env->CSR_CNTC);
192f8447436STianrui Zhao 
193f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TICLR),
194f8447436STianrui Zhao                            &env->CSR_TICLR);
195f8447436STianrui Zhao 
196f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_LLBCTL),
197f8447436STianrui Zhao                            &env->CSR_LLBCTL);
198f8447436STianrui Zhao 
199f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL1),
200f8447436STianrui Zhao                            &env->CSR_IMPCTL1);
201f8447436STianrui Zhao 
202f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL2),
203f8447436STianrui Zhao                            &env->CSR_IMPCTL2);
204f8447436STianrui Zhao 
205f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRENTRY),
206f8447436STianrui Zhao                            &env->CSR_TLBRENTRY);
207f8447436STianrui Zhao 
208f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRBADV),
209f8447436STianrui Zhao                            &env->CSR_TLBRBADV);
210f8447436STianrui Zhao 
211f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRERA),
212f8447436STianrui Zhao                            &env->CSR_TLBRERA);
213f8447436STianrui Zhao 
214f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRSAVE),
215f8447436STianrui Zhao                            &env->CSR_TLBRSAVE);
216f8447436STianrui Zhao 
217f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO0),
218f8447436STianrui Zhao                            &env->CSR_TLBRELO0);
219f8447436STianrui Zhao 
220f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO1),
221f8447436STianrui Zhao                            &env->CSR_TLBRELO1);
222f8447436STianrui Zhao 
223f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBREHI),
224f8447436STianrui Zhao                            &env->CSR_TLBREHI);
225f8447436STianrui Zhao 
226f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRPRMD),
227f8447436STianrui Zhao                            &env->CSR_TLBRPRMD);
228f8447436STianrui Zhao 
229f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(0)),
230f8447436STianrui Zhao                            &env->CSR_DMW[0]);
231f8447436STianrui Zhao 
232f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(1)),
233f8447436STianrui Zhao                            &env->CSR_DMW[1]);
234f8447436STianrui Zhao 
235f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(2)),
236f8447436STianrui Zhao                            &env->CSR_DMW[2]);
237f8447436STianrui Zhao 
238f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(3)),
239f8447436STianrui Zhao                            &env->CSR_DMW[3]);
240f8447436STianrui Zhao 
241f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TVAL),
242f8447436STianrui Zhao                            &env->CSR_TVAL);
243f8447436STianrui Zhao 
244f8447436STianrui Zhao     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TCFG),
245f8447436STianrui Zhao                            &env->CSR_TCFG);
246f8447436STianrui Zhao 
247f8447436STianrui Zhao     return ret;
248f8447436STianrui Zhao }
249f8447436STianrui Zhao 
25061f6e150SBibo Mao static int kvm_loongarch_put_csr(CPUState *cs, int level)
251f8447436STianrui Zhao {
252f8447436STianrui Zhao     int ret = 0;
253f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
254f8447436STianrui Zhao 
255f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CRMD),
256f8447436STianrui Zhao                            &env->CSR_CRMD);
257f8447436STianrui Zhao 
258f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRMD),
259f8447436STianrui Zhao                            &env->CSR_PRMD);
260f8447436STianrui Zhao 
261f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EUEN),
262f8447436STianrui Zhao                            &env->CSR_EUEN);
263f8447436STianrui Zhao 
264f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MISC),
265f8447436STianrui Zhao                            &env->CSR_MISC);
266f8447436STianrui Zhao 
267f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ECFG),
268f8447436STianrui Zhao                            &env->CSR_ECFG);
269f8447436STianrui Zhao 
270f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ESTAT),
271f8447436STianrui Zhao                            &env->CSR_ESTAT);
272f8447436STianrui Zhao 
273f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ERA),
274f8447436STianrui Zhao                            &env->CSR_ERA);
275f8447436STianrui Zhao 
276f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADV),
277f8447436STianrui Zhao                            &env->CSR_BADV);
278f8447436STianrui Zhao 
279f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADI),
280f8447436STianrui Zhao                            &env->CSR_BADI);
281f8447436STianrui Zhao 
282f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EENTRY),
283f8447436STianrui Zhao                            &env->CSR_EENTRY);
284f8447436STianrui Zhao 
285f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBIDX),
286f8447436STianrui Zhao                            &env->CSR_TLBIDX);
287f8447436STianrui Zhao 
288f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBEHI),
289f8447436STianrui Zhao                            &env->CSR_TLBEHI);
290f8447436STianrui Zhao 
291f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO0),
292f8447436STianrui Zhao                            &env->CSR_TLBELO0);
293f8447436STianrui Zhao 
294f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO1),
295f8447436STianrui Zhao                            &env->CSR_TLBELO1);
296f8447436STianrui Zhao 
297f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ASID),
298f8447436STianrui Zhao                            &env->CSR_ASID);
299f8447436STianrui Zhao 
300f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDL),
301f8447436STianrui Zhao                            &env->CSR_PGDL);
302f8447436STianrui Zhao 
303f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDH),
304f8447436STianrui Zhao                            &env->CSR_PGDH);
305f8447436STianrui Zhao 
306f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGD),
307f8447436STianrui Zhao                            &env->CSR_PGD);
308f8447436STianrui Zhao 
309f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCL),
310f8447436STianrui Zhao                            &env->CSR_PWCL);
311f8447436STianrui Zhao 
312f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCH),
313f8447436STianrui Zhao                            &env->CSR_PWCH);
314f8447436STianrui Zhao 
315f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_STLBPS),
316f8447436STianrui Zhao                            &env->CSR_STLBPS);
317f8447436STianrui Zhao 
318f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_RVACFG),
319f8447436STianrui Zhao                            &env->CSR_RVACFG);
320f8447436STianrui Zhao 
32161f6e150SBibo Mao     /* CPUID is constant after poweron, it should be set only once */
32261f6e150SBibo Mao     if (level >= KVM_PUT_FULL_STATE) {
323f8447436STianrui Zhao         ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CPUID),
324f8447436STianrui Zhao                            &env->CSR_CPUID);
32561f6e150SBibo Mao     }
326f8447436STianrui Zhao 
327f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG1),
328f8447436STianrui Zhao                            &env->CSR_PRCFG1);
329f8447436STianrui Zhao 
330f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG2),
331f8447436STianrui Zhao                            &env->CSR_PRCFG2);
332f8447436STianrui Zhao 
333f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG3),
334f8447436STianrui Zhao                            &env->CSR_PRCFG3);
335f8447436STianrui Zhao 
336f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(0)),
337f8447436STianrui Zhao                            &env->CSR_SAVE[0]);
338f8447436STianrui Zhao 
339f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(1)),
340f8447436STianrui Zhao                            &env->CSR_SAVE[1]);
341f8447436STianrui Zhao 
342f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(2)),
343f8447436STianrui Zhao                            &env->CSR_SAVE[2]);
344f8447436STianrui Zhao 
345f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(3)),
346f8447436STianrui Zhao                            &env->CSR_SAVE[3]);
347f8447436STianrui Zhao 
348f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(4)),
349f8447436STianrui Zhao                            &env->CSR_SAVE[4]);
350f8447436STianrui Zhao 
351f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(5)),
352f8447436STianrui Zhao                            &env->CSR_SAVE[5]);
353f8447436STianrui Zhao 
354f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(6)),
355f8447436STianrui Zhao                            &env->CSR_SAVE[6]);
356f8447436STianrui Zhao 
357f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(7)),
358f8447436STianrui Zhao                            &env->CSR_SAVE[7]);
359f8447436STianrui Zhao 
360f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TID),
361f8447436STianrui Zhao                            &env->CSR_TID);
362f8447436STianrui Zhao 
363f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CNTC),
364f8447436STianrui Zhao                            &env->CSR_CNTC);
365f8447436STianrui Zhao 
366f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TICLR),
367f8447436STianrui Zhao                            &env->CSR_TICLR);
368f8447436STianrui Zhao 
369f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_LLBCTL),
370f8447436STianrui Zhao                            &env->CSR_LLBCTL);
371f8447436STianrui Zhao 
372f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL1),
373f8447436STianrui Zhao                            &env->CSR_IMPCTL1);
374f8447436STianrui Zhao 
375f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL2),
376f8447436STianrui Zhao                            &env->CSR_IMPCTL2);
377f8447436STianrui Zhao 
378f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRENTRY),
379f8447436STianrui Zhao                            &env->CSR_TLBRENTRY);
380f8447436STianrui Zhao 
381f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRBADV),
382f8447436STianrui Zhao                            &env->CSR_TLBRBADV);
383f8447436STianrui Zhao 
384f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRERA),
385f8447436STianrui Zhao                            &env->CSR_TLBRERA);
386f8447436STianrui Zhao 
387f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRSAVE),
388f8447436STianrui Zhao                            &env->CSR_TLBRSAVE);
389f8447436STianrui Zhao 
390f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO0),
391f8447436STianrui Zhao                            &env->CSR_TLBRELO0);
392f8447436STianrui Zhao 
393f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO1),
394f8447436STianrui Zhao                            &env->CSR_TLBRELO1);
395f8447436STianrui Zhao 
396f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBREHI),
397f8447436STianrui Zhao                            &env->CSR_TLBREHI);
398f8447436STianrui Zhao 
399f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRPRMD),
400f8447436STianrui Zhao                            &env->CSR_TLBRPRMD);
401f8447436STianrui Zhao 
402f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(0)),
403f8447436STianrui Zhao                            &env->CSR_DMW[0]);
404f8447436STianrui Zhao 
405f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(1)),
406f8447436STianrui Zhao                            &env->CSR_DMW[1]);
407f8447436STianrui Zhao 
408f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(2)),
409f8447436STianrui Zhao                            &env->CSR_DMW[2]);
410f8447436STianrui Zhao 
411f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(3)),
412f8447436STianrui Zhao                            &env->CSR_DMW[3]);
413f8447436STianrui Zhao     /*
414f8447436STianrui Zhao      * timer cfg must be put at last since it is used to enable
415f8447436STianrui Zhao      * guest timer
416f8447436STianrui Zhao      */
417f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TVAL),
418f8447436STianrui Zhao                            &env->CSR_TVAL);
419f8447436STianrui Zhao 
420f8447436STianrui Zhao     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TCFG),
421f8447436STianrui Zhao                            &env->CSR_TCFG);
422f8447436STianrui Zhao     return ret;
423f8447436STianrui Zhao }
424f8447436STianrui Zhao 
425f8447436STianrui Zhao static int kvm_loongarch_get_regs_fp(CPUState *cs)
426f8447436STianrui Zhao {
427f8447436STianrui Zhao     int ret, i;
428f8447436STianrui Zhao     struct kvm_fpu fpu;
429f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
430f8447436STianrui Zhao 
431f8447436STianrui Zhao     ret = kvm_vcpu_ioctl(cs, KVM_GET_FPU, &fpu);
432f8447436STianrui Zhao     if (ret < 0) {
433f8447436STianrui Zhao         trace_kvm_failed_get_fpu(strerror(errno));
434f8447436STianrui Zhao         return ret;
435f8447436STianrui Zhao     }
436f8447436STianrui Zhao 
437f8447436STianrui Zhao     env->fcsr0 = fpu.fcsr;
438f8447436STianrui Zhao     for (i = 0; i < 32; i++) {
439f8447436STianrui Zhao         env->fpr[i].vreg.UD[0] = fpu.fpr[i].val64[0];
44007c08661SSong Gao         env->fpr[i].vreg.UD[1] = fpu.fpr[i].val64[1];
44107c08661SSong Gao         env->fpr[i].vreg.UD[2] = fpu.fpr[i].val64[2];
44207c08661SSong Gao         env->fpr[i].vreg.UD[3] = fpu.fpr[i].val64[3];
443f8447436STianrui Zhao     }
444f8447436STianrui Zhao     for (i = 0; i < 8; i++) {
445f8447436STianrui Zhao         env->cf[i] = fpu.fcc & 0xFF;
446f8447436STianrui Zhao         fpu.fcc = fpu.fcc >> 8;
447f8447436STianrui Zhao     }
448f8447436STianrui Zhao 
449f8447436STianrui Zhao     return ret;
450f8447436STianrui Zhao }
451f8447436STianrui Zhao 
452f8447436STianrui Zhao static int kvm_loongarch_put_regs_fp(CPUState *cs)
453f8447436STianrui Zhao {
454f8447436STianrui Zhao     int ret, i;
455f8447436STianrui Zhao     struct kvm_fpu fpu;
456f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
457f8447436STianrui Zhao 
458f8447436STianrui Zhao     fpu.fcsr = env->fcsr0;
459f8447436STianrui Zhao     fpu.fcc = 0;
460f8447436STianrui Zhao     for (i = 0; i < 32; i++) {
461f8447436STianrui Zhao         fpu.fpr[i].val64[0] = env->fpr[i].vreg.UD[0];
46207c08661SSong Gao         fpu.fpr[i].val64[1] = env->fpr[i].vreg.UD[1];
46307c08661SSong Gao         fpu.fpr[i].val64[2] = env->fpr[i].vreg.UD[2];
46407c08661SSong Gao         fpu.fpr[i].val64[3] = env->fpr[i].vreg.UD[3];
465f8447436STianrui Zhao     }
466f8447436STianrui Zhao 
467f8447436STianrui Zhao     for (i = 0; i < 8; i++) {
468f8447436STianrui Zhao         fpu.fcc |= env->cf[i] << (8 * i);
469f8447436STianrui Zhao     }
470f8447436STianrui Zhao 
471f8447436STianrui Zhao     ret = kvm_vcpu_ioctl(cs, KVM_SET_FPU, &fpu);
472f8447436STianrui Zhao     if (ret < 0) {
473f8447436STianrui Zhao         trace_kvm_failed_put_fpu(strerror(errno));
474f8447436STianrui Zhao     }
475f8447436STianrui Zhao 
476f8447436STianrui Zhao     return ret;
477f8447436STianrui Zhao }
478f8447436STianrui Zhao 
479*a724f5a8SBibo Mao void kvm_arch_reset_vcpu(CPUState *cs)
480f8447436STianrui Zhao {
481*a724f5a8SBibo Mao     CPULoongArchState *env = cpu_env(cs);
482*a724f5a8SBibo Mao 
483f8447436STianrui Zhao     env->mp_state = KVM_MP_STATE_RUNNABLE;
484*a724f5a8SBibo Mao     kvm_set_one_reg(cs, KVM_REG_LOONGARCH_VCPU_RESET, 0);
485f8447436STianrui Zhao }
486f8447436STianrui Zhao 
487f8447436STianrui Zhao static int kvm_loongarch_get_mpstate(CPUState *cs)
488f8447436STianrui Zhao {
489f8447436STianrui Zhao     int ret = 0;
490f8447436STianrui Zhao     struct kvm_mp_state mp_state;
491f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
492f8447436STianrui Zhao 
493f8447436STianrui Zhao     if (cap_has_mp_state) {
494f8447436STianrui Zhao         ret = kvm_vcpu_ioctl(cs, KVM_GET_MP_STATE, &mp_state);
495f8447436STianrui Zhao         if (ret) {
496f8447436STianrui Zhao             trace_kvm_failed_get_mpstate(strerror(errno));
497f8447436STianrui Zhao             return ret;
498f8447436STianrui Zhao         }
499f8447436STianrui Zhao         env->mp_state = mp_state.mp_state;
500f8447436STianrui Zhao     }
501f8447436STianrui Zhao 
502f8447436STianrui Zhao     return ret;
503f8447436STianrui Zhao }
504f8447436STianrui Zhao 
505f8447436STianrui Zhao static int kvm_loongarch_put_mpstate(CPUState *cs)
506f8447436STianrui Zhao {
507f8447436STianrui Zhao     int ret = 0;
508f8447436STianrui Zhao     struct kvm_mp_state mp_state = {
509f3b603b9SPhilippe Mathieu-Daudé         .mp_state = cpu_env(cs)->mp_state
510f8447436STianrui Zhao     };
511f8447436STianrui Zhao 
512f8447436STianrui Zhao     if (cap_has_mp_state) {
513f8447436STianrui Zhao         ret = kvm_vcpu_ioctl(cs, KVM_SET_MP_STATE, &mp_state);
514f8447436STianrui Zhao         if (ret) {
515f8447436STianrui Zhao             trace_kvm_failed_put_mpstate(strerror(errno));
516f8447436STianrui Zhao         }
517f8447436STianrui Zhao     }
518f8447436STianrui Zhao 
519f8447436STianrui Zhao     return ret;
520f8447436STianrui Zhao }
521f8447436STianrui Zhao 
522f8447436STianrui Zhao static int kvm_loongarch_get_cpucfg(CPUState *cs)
523f8447436STianrui Zhao {
524f8447436STianrui Zhao     int i, ret = 0;
525f8447436STianrui Zhao     uint64_t val;
526f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
527f8447436STianrui Zhao 
528f8447436STianrui Zhao     for (i = 0; i < 21; i++) {
529f8447436STianrui Zhao         ret = kvm_get_one_reg(cs, KVM_IOC_CPUCFG(i), &val);
530f8447436STianrui Zhao         if (ret < 0) {
531f8447436STianrui Zhao             trace_kvm_failed_get_cpucfg(strerror(errno));
532f8447436STianrui Zhao         }
533f8447436STianrui Zhao         env->cpucfg[i] = (uint32_t)val;
534f8447436STianrui Zhao     }
535f8447436STianrui Zhao     return ret;
536f8447436STianrui Zhao }
537f8447436STianrui Zhao 
538fc700996SSong Gao static int kvm_check_cpucfg2(CPUState *cs)
539fc700996SSong Gao {
540fc700996SSong Gao     int ret;
541fc700996SSong Gao     uint64_t val;
542fc700996SSong Gao     struct kvm_device_attr attr = {
543fc700996SSong Gao         .group = KVM_LOONGARCH_VCPU_CPUCFG,
544fc700996SSong Gao         .attr = 2,
545fc700996SSong Gao         .addr = (uint64_t)&val,
546fc700996SSong Gao     };
547f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
548fc700996SSong Gao 
549fc700996SSong Gao     ret = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, &attr);
550fc700996SSong Gao 
551fc700996SSong Gao     if (!ret) {
552fc700996SSong Gao         kvm_vcpu_ioctl(cs, KVM_GET_DEVICE_ATTR, &attr);
553fc700996SSong Gao         env->cpucfg[2] &= val;
554fc700996SSong Gao 
555fc700996SSong Gao         if (FIELD_EX32(env->cpucfg[2], CPUCFG2, FP)) {
556fc700996SSong Gao             /* The FP minimal version is 1. */
557fc700996SSong Gao             env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, FP_VER, 1);
558fc700996SSong Gao         }
559fc700996SSong Gao 
560fc700996SSong Gao         if (FIELD_EX32(env->cpucfg[2], CPUCFG2, LLFTP)) {
561fc700996SSong Gao             /* The LLFTP minimal version is 1. */
562fc700996SSong Gao             env->cpucfg[2] = FIELD_DP32(env->cpucfg[2], CPUCFG2, LLFTP_VER, 1);
563fc700996SSong Gao         }
564fc700996SSong Gao     }
565fc700996SSong Gao 
566fc700996SSong Gao     return ret;
567fc700996SSong Gao }
568fc700996SSong Gao 
569f8447436STianrui Zhao static int kvm_loongarch_put_cpucfg(CPUState *cs)
570f8447436STianrui Zhao {
571f8447436STianrui Zhao     int i, ret = 0;
572f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
573f8447436STianrui Zhao     uint64_t val;
574f8447436STianrui Zhao 
575f8447436STianrui Zhao     for (i = 0; i < 21; i++) {
576f8447436STianrui Zhao 	if (i == 2) {
577fc700996SSong Gao             ret = kvm_check_cpucfg2(cs);
578fc700996SSong Gao             if (ret) {
579fc700996SSong Gao                 return ret;
580f8447436STianrui Zhao             }
581fc700996SSong Gao 	}
582fc700996SSong Gao         val = env->cpucfg[i];
583f8447436STianrui Zhao         ret = kvm_set_one_reg(cs, KVM_IOC_CPUCFG(i), &val);
584f8447436STianrui Zhao         if (ret < 0) {
585f8447436STianrui Zhao             trace_kvm_failed_put_cpucfg(strerror(errno));
586f8447436STianrui Zhao         }
587f8447436STianrui Zhao     }
588f8447436STianrui Zhao     return ret;
589f8447436STianrui Zhao }
590f8447436STianrui Zhao 
591537ba9daSTianrui Zhao int kvm_arch_get_registers(CPUState *cs)
592537ba9daSTianrui Zhao {
593f8447436STianrui Zhao     int ret;
594f8447436STianrui Zhao 
595f8447436STianrui Zhao     ret = kvm_loongarch_get_regs_core(cs);
596f8447436STianrui Zhao     if (ret) {
597f8447436STianrui Zhao         return ret;
598537ba9daSTianrui Zhao     }
599f8447436STianrui Zhao 
6005872966dSBibo Mao     ret = kvm_loongarch_get_cpucfg(cs);
6015872966dSBibo Mao     if (ret) {
6025872966dSBibo Mao         return ret;
6035872966dSBibo Mao     }
6045872966dSBibo Mao 
605f8447436STianrui Zhao     ret = kvm_loongarch_get_csr(cs);
606f8447436STianrui Zhao     if (ret) {
607f8447436STianrui Zhao         return ret;
608f8447436STianrui Zhao     }
609f8447436STianrui Zhao 
610f8447436STianrui Zhao     ret = kvm_loongarch_get_regs_fp(cs);
611f8447436STianrui Zhao     if (ret) {
612f8447436STianrui Zhao         return ret;
613f8447436STianrui Zhao     }
614f8447436STianrui Zhao 
615f8447436STianrui Zhao     ret = kvm_loongarch_get_mpstate(cs);
616f8447436STianrui Zhao     return ret;
617f8447436STianrui Zhao }
618f8447436STianrui Zhao 
619537ba9daSTianrui Zhao int kvm_arch_put_registers(CPUState *cs, int level)
620537ba9daSTianrui Zhao {
621f8447436STianrui Zhao     int ret;
622f8447436STianrui Zhao 
623f8447436STianrui Zhao     ret = kvm_loongarch_put_regs_core(cs);
624f8447436STianrui Zhao     if (ret) {
625f8447436STianrui Zhao         return ret;
626f8447436STianrui Zhao     }
627f8447436STianrui Zhao 
6285872966dSBibo Mao     ret = kvm_loongarch_put_cpucfg(cs);
6295872966dSBibo Mao     if (ret) {
6305872966dSBibo Mao         return ret;
6315872966dSBibo Mao     }
6325872966dSBibo Mao 
63361f6e150SBibo Mao     ret = kvm_loongarch_put_csr(cs, level);
634f8447436STianrui Zhao     if (ret) {
635f8447436STianrui Zhao         return ret;
636f8447436STianrui Zhao     }
637f8447436STianrui Zhao 
638f8447436STianrui Zhao     ret = kvm_loongarch_put_regs_fp(cs);
639f8447436STianrui Zhao     if (ret) {
640f8447436STianrui Zhao         return ret;
641f8447436STianrui Zhao     }
642f8447436STianrui Zhao 
643f8447436STianrui Zhao     ret = kvm_loongarch_put_mpstate(cs);
644f8447436STianrui Zhao     return ret;
645537ba9daSTianrui Zhao }
646537ba9daSTianrui Zhao 
647d11681c9STianrui Zhao static void kvm_loongarch_vm_stage_change(void *opaque, bool running,
648d11681c9STianrui Zhao                                           RunState state)
649d11681c9STianrui Zhao {
650d11681c9STianrui Zhao     int ret;
651d11681c9STianrui Zhao     CPUState *cs = opaque;
652d11681c9STianrui Zhao     LoongArchCPU *cpu = LOONGARCH_CPU(cs);
653d11681c9STianrui Zhao 
654d11681c9STianrui Zhao     if (running) {
655d11681c9STianrui Zhao         ret = kvm_set_one_reg(cs, KVM_REG_LOONGARCH_COUNTER,
656d11681c9STianrui Zhao                               &cpu->kvm_state_counter);
657d11681c9STianrui Zhao         if (ret < 0) {
658d11681c9STianrui Zhao             trace_kvm_failed_put_counter(strerror(errno));
659d11681c9STianrui Zhao         }
660d11681c9STianrui Zhao     } else {
661d11681c9STianrui Zhao         ret = kvm_get_one_reg(cs, KVM_REG_LOONGARCH_COUNTER,
662d11681c9STianrui Zhao                               &cpu->kvm_state_counter);
663d11681c9STianrui Zhao         if (ret < 0) {
664d11681c9STianrui Zhao             trace_kvm_failed_get_counter(strerror(errno));
665d11681c9STianrui Zhao         }
666d11681c9STianrui Zhao     }
667d11681c9STianrui Zhao }
668d11681c9STianrui Zhao 
669537ba9daSTianrui Zhao int kvm_arch_init_vcpu(CPUState *cs)
670537ba9daSTianrui Zhao {
671d38e31efSBibo Mao     uint64_t val;
672d38e31efSBibo Mao 
673d11681c9STianrui Zhao     qemu_add_vm_change_state_handler(kvm_loongarch_vm_stage_change, cs);
674d38e31efSBibo Mao 
675d38e31efSBibo Mao     if (!kvm_get_one_reg(cs, KVM_REG_LOONGARCH_DEBUG_INST, &val)) {
676d38e31efSBibo Mao         brk_insn = val;
677d38e31efSBibo Mao     }
678d38e31efSBibo Mao 
679537ba9daSTianrui Zhao     return 0;
680537ba9daSTianrui Zhao }
681537ba9daSTianrui Zhao 
682537ba9daSTianrui Zhao int kvm_arch_destroy_vcpu(CPUState *cs)
683537ba9daSTianrui Zhao {
684537ba9daSTianrui Zhao     return 0;
685537ba9daSTianrui Zhao }
686537ba9daSTianrui Zhao 
687537ba9daSTianrui Zhao unsigned long kvm_arch_vcpu_id(CPUState *cs)
688537ba9daSTianrui Zhao {
689537ba9daSTianrui Zhao     return cs->cpu_index;
690537ba9daSTianrui Zhao }
691537ba9daSTianrui Zhao 
692537ba9daSTianrui Zhao int kvm_arch_release_virq_post(int virq)
693537ba9daSTianrui Zhao {
694537ba9daSTianrui Zhao     return 0;
695537ba9daSTianrui Zhao }
696537ba9daSTianrui Zhao 
697537ba9daSTianrui Zhao int kvm_arch_msi_data_to_gsi(uint32_t data)
698537ba9daSTianrui Zhao {
699537ba9daSTianrui Zhao     abort();
700537ba9daSTianrui Zhao }
701537ba9daSTianrui Zhao 
702537ba9daSTianrui Zhao int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
703537ba9daSTianrui Zhao                              uint64_t address, uint32_t data, PCIDevice *dev)
704537ba9daSTianrui Zhao {
705537ba9daSTianrui Zhao     return 0;
706537ba9daSTianrui Zhao }
707537ba9daSTianrui Zhao 
708537ba9daSTianrui Zhao int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
709537ba9daSTianrui Zhao                                 int vector, PCIDevice *dev)
710537ba9daSTianrui Zhao {
711537ba9daSTianrui Zhao     return 0;
712537ba9daSTianrui Zhao }
713537ba9daSTianrui Zhao 
714537ba9daSTianrui Zhao void kvm_arch_init_irq_routing(KVMState *s)
715537ba9daSTianrui Zhao {
716537ba9daSTianrui Zhao }
717537ba9daSTianrui Zhao 
718537ba9daSTianrui Zhao int kvm_arch_get_default_type(MachineState *ms)
719537ba9daSTianrui Zhao {
720537ba9daSTianrui Zhao     return 0;
721537ba9daSTianrui Zhao }
722537ba9daSTianrui Zhao 
723537ba9daSTianrui Zhao int kvm_arch_init(MachineState *ms, KVMState *s)
724537ba9daSTianrui Zhao {
72541958c99STianrui Zhao     cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
726537ba9daSTianrui Zhao     return 0;
727537ba9daSTianrui Zhao }
728537ba9daSTianrui Zhao 
729537ba9daSTianrui Zhao int kvm_arch_irqchip_create(KVMState *s)
730537ba9daSTianrui Zhao {
731537ba9daSTianrui Zhao     return 0;
732537ba9daSTianrui Zhao }
733537ba9daSTianrui Zhao 
734537ba9daSTianrui Zhao void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
735537ba9daSTianrui Zhao {
736537ba9daSTianrui Zhao }
737537ba9daSTianrui Zhao 
738537ba9daSTianrui Zhao MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
739537ba9daSTianrui Zhao {
740537ba9daSTianrui Zhao     return MEMTXATTRS_UNSPECIFIED;
741537ba9daSTianrui Zhao }
742537ba9daSTianrui Zhao 
743537ba9daSTianrui Zhao int kvm_arch_process_async_events(CPUState *cs)
744537ba9daSTianrui Zhao {
745537ba9daSTianrui Zhao     return cs->halted;
746537ba9daSTianrui Zhao }
747537ba9daSTianrui Zhao 
748537ba9daSTianrui Zhao bool kvm_arch_stop_on_emulation_error(CPUState *cs)
749537ba9daSTianrui Zhao {
750537ba9daSTianrui Zhao     return true;
751537ba9daSTianrui Zhao }
752537ba9daSTianrui Zhao 
753d38e31efSBibo Mao void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg)
754d38e31efSBibo Mao {
755d38e31efSBibo Mao     if (kvm_sw_breakpoints_active(cpu)) {
756d38e31efSBibo Mao         dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
757d38e31efSBibo Mao     }
758d38e31efSBibo Mao }
759d38e31efSBibo Mao 
760d38e31efSBibo Mao int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
761d38e31efSBibo Mao {
762d38e31efSBibo Mao     if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 4, 0) ||
763d38e31efSBibo Mao         cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&brk_insn, 4, 1)) {
764d38e31efSBibo Mao         error_report("%s failed", __func__);
765d38e31efSBibo Mao         return -EINVAL;
766d38e31efSBibo Mao     }
767d38e31efSBibo Mao     return 0;
768d38e31efSBibo Mao }
769d38e31efSBibo Mao 
770d38e31efSBibo Mao int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
771d38e31efSBibo Mao {
772d38e31efSBibo Mao     static uint32_t brk;
773d38e31efSBibo Mao 
774d38e31efSBibo Mao     if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&brk, 4, 0) ||
775d38e31efSBibo Mao         brk != brk_insn ||
776d38e31efSBibo Mao         cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 4, 1)) {
777d38e31efSBibo Mao         error_report("%s failed", __func__);
778d38e31efSBibo Mao         return -EINVAL;
779d38e31efSBibo Mao     }
780d38e31efSBibo Mao     return 0;
781d38e31efSBibo Mao }
782d38e31efSBibo Mao 
783d38e31efSBibo Mao int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type)
784d38e31efSBibo Mao {
785d38e31efSBibo Mao     return -ENOSYS;
786d38e31efSBibo Mao }
787d38e31efSBibo Mao 
788d38e31efSBibo Mao int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type)
789d38e31efSBibo Mao {
790d38e31efSBibo Mao     return -ENOSYS;
791d38e31efSBibo Mao }
792d38e31efSBibo Mao 
793d38e31efSBibo Mao void kvm_arch_remove_all_hw_breakpoints(void)
794d38e31efSBibo Mao {
795d38e31efSBibo Mao }
796d38e31efSBibo Mao 
797d38e31efSBibo Mao static bool kvm_loongarch_handle_debug(CPUState *cs, struct kvm_run *run)
798d38e31efSBibo Mao {
799d38e31efSBibo Mao     LoongArchCPU *cpu = LOONGARCH_CPU(cs);
800d38e31efSBibo Mao     CPULoongArchState *env = &cpu->env;
801d38e31efSBibo Mao 
802d38e31efSBibo Mao     kvm_cpu_synchronize_state(cs);
803d38e31efSBibo Mao     if (cs->singlestep_enabled) {
804d38e31efSBibo Mao         return true;
805d38e31efSBibo Mao     }
806d38e31efSBibo Mao 
807d38e31efSBibo Mao     if (kvm_find_sw_breakpoint(cs, env->pc)) {
808d38e31efSBibo Mao         return true;
809d38e31efSBibo Mao     }
810d38e31efSBibo Mao 
811d38e31efSBibo Mao     return false;
812d38e31efSBibo Mao }
813d38e31efSBibo Mao 
814537ba9daSTianrui Zhao int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
815537ba9daSTianrui Zhao {
816a05a950fSTianrui Zhao     int ret = 0;
817f3b603b9SPhilippe Mathieu-Daudé     CPULoongArchState *env = cpu_env(cs);
818a05a950fSTianrui Zhao     MemTxAttrs attrs = {};
819a05a950fSTianrui Zhao 
820a05a950fSTianrui Zhao     attrs.requester_id = env_cpu(env)->cpu_index;
821a05a950fSTianrui Zhao 
822a05a950fSTianrui Zhao     trace_kvm_arch_handle_exit(run->exit_reason);
823a05a950fSTianrui Zhao     switch (run->exit_reason) {
824a05a950fSTianrui Zhao     case KVM_EXIT_LOONGARCH_IOCSR:
8255e90b8dbSBibo Mao         address_space_rw(env->address_space_iocsr,
826a05a950fSTianrui Zhao                          run->iocsr_io.phys_addr,
827a05a950fSTianrui Zhao                          attrs,
828a05a950fSTianrui Zhao                          run->iocsr_io.data,
829a05a950fSTianrui Zhao                          run->iocsr_io.len,
830a05a950fSTianrui Zhao                          run->iocsr_io.is_write);
831a05a950fSTianrui Zhao         break;
832d38e31efSBibo Mao 
833d38e31efSBibo Mao     case KVM_EXIT_DEBUG:
834d38e31efSBibo Mao         if (kvm_loongarch_handle_debug(cs, run)) {
835d38e31efSBibo Mao             ret = EXCP_DEBUG;
836d38e31efSBibo Mao         }
837d38e31efSBibo Mao         break;
838d38e31efSBibo Mao 
839a05a950fSTianrui Zhao     default:
840a05a950fSTianrui Zhao         ret = -1;
841a05a950fSTianrui Zhao         warn_report("KVM: unknown exit reason %d", run->exit_reason);
842a05a950fSTianrui Zhao         break;
843a05a950fSTianrui Zhao     }
844a05a950fSTianrui Zhao     return ret;
845537ba9daSTianrui Zhao }
846537ba9daSTianrui Zhao 
8478dcbad51STianrui Zhao int kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level)
8488dcbad51STianrui Zhao {
8498dcbad51STianrui Zhao     struct kvm_interrupt intr;
8508dcbad51STianrui Zhao     CPUState *cs = CPU(cpu);
8518dcbad51STianrui Zhao 
8528dcbad51STianrui Zhao     if (level) {
8538dcbad51STianrui Zhao         intr.irq = irq;
8548dcbad51STianrui Zhao     } else {
8558dcbad51STianrui Zhao         intr.irq = -irq;
8568dcbad51STianrui Zhao     }
8578dcbad51STianrui Zhao 
8588dcbad51STianrui Zhao     trace_kvm_set_intr(irq, level);
8598dcbad51STianrui Zhao     return kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
8608dcbad51STianrui Zhao }
8618dcbad51STianrui Zhao 
862537ba9daSTianrui Zhao void kvm_arch_accel_class_init(ObjectClass *oc)
863537ba9daSTianrui Zhao {
864537ba9daSTianrui Zhao }
865