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