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, ®s); 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, ®s); 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