/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * QEMU LoongArch Machine State * * Copyright (c) 2021 Loongson Technology Corporation Limited */ #include "qemu/osdep.h" #include "cpu.h" #include "migration/cpu.h" #include "sysemu/tcg.h" #include "vec.h" static const VMStateDescription vmstate_fpu_reg = { .name = "fpu_reg", .version_id = 1, .minimum_version_id = 1, .fields = (const VMStateField[]) { VMSTATE_UINT64(UD(0), VReg), VMSTATE_END_OF_LIST() } }; #define VMSTATE_FPU_REGS(_field, _state, _start) \ VMSTATE_STRUCT_SUB_ARRAY(_field, _state, _start, 32, 0, \ vmstate_fpu_reg, fpr_t) static bool fpu_needed(void *opaque) { LoongArchCPU *cpu = opaque; return FIELD_EX64(cpu->env.cpucfg[2], CPUCFG2, FP); } static const VMStateDescription vmstate_fpu = { .name = "cpu/fpu", .version_id = 1, .minimum_version_id = 1, .needed = fpu_needed, .fields = (const VMStateField[]) { VMSTATE_FPU_REGS(env.fpr, LoongArchCPU, 0), VMSTATE_UINT32(env.fcsr0, LoongArchCPU), VMSTATE_BOOL_ARRAY(env.cf, LoongArchCPU, 8), VMSTATE_END_OF_LIST() }, }; static const VMStateDescription vmstate_lsxh_reg = { .name = "lsxh_reg", .version_id = 1, .minimum_version_id = 1, .fields = (const VMStateField[]) { VMSTATE_UINT64(UD(1), VReg), VMSTATE_END_OF_LIST() } }; #define VMSTATE_LSXH_REGS(_field, _state, _start) \ VMSTATE_STRUCT_SUB_ARRAY(_field, _state, _start, 32, 0, \ vmstate_lsxh_reg, fpr_t) static bool lsx_needed(void *opaque) { LoongArchCPU *cpu = opaque; return FIELD_EX64(cpu->env.cpucfg[2], CPUCFG2, LSX); } static const VMStateDescription vmstate_lsx = { .name = "cpu/lsx", .version_id = 1, .minimum_version_id = 1, .needed = lsx_needed, .fields = (const VMStateField[]) { VMSTATE_LSXH_REGS(env.fpr, LoongArchCPU, 0), VMSTATE_END_OF_LIST() }, }; static const VMStateDescription vmstate_lasxh_reg = { .name = "lasxh_reg", .version_id = 1, .minimum_version_id = 1, .fields = (const VMStateField[]) { VMSTATE_UINT64(UD(2), VReg), VMSTATE_UINT64(UD(3), VReg), VMSTATE_END_OF_LIST() } }; #define VMSTATE_LASXH_REGS(_field, _state, _start) \ VMSTATE_STRUCT_SUB_ARRAY(_field, _state, _start, 32, 0, \ vmstate_lasxh_reg, fpr_t) static bool lasx_needed(void *opaque) { LoongArchCPU *cpu = opaque; return FIELD_EX64(cpu->env.cpucfg[2], CPUCFG2, LASX); } static const VMStateDescription vmstate_lasx = { .name = "cpu/lasx", .version_id = 1, .minimum_version_id = 1, .needed = lasx_needed, .fields = (const VMStateField[]) { VMSTATE_LASXH_REGS(env.fpr, LoongArchCPU, 0), VMSTATE_END_OF_LIST() }, }; static bool lbt_needed(void *opaque) { LoongArchCPU *cpu = opaque; return !!FIELD_EX64(cpu->env.cpucfg[2], CPUCFG2, LBT_ALL); } static const VMStateDescription vmstate_lbt = { .name = "cpu/lbt", .version_id = 0, .minimum_version_id = 0, .needed = lbt_needed, .fields = (const VMStateField[]) { VMSTATE_UINT64(env.lbt.scr0, LoongArchCPU), VMSTATE_UINT64(env.lbt.scr1, LoongArchCPU), VMSTATE_UINT64(env.lbt.scr2, LoongArchCPU), VMSTATE_UINT64(env.lbt.scr3, LoongArchCPU), VMSTATE_UINT32(env.lbt.eflags, LoongArchCPU), VMSTATE_UINT32(env.lbt.ftop, LoongArchCPU), VMSTATE_END_OF_LIST() }, }; #if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) static bool tlb_needed(void *opaque) { return tcg_enabled(); } /* TLB state */ static const VMStateDescription vmstate_tlb_entry = { .name = "cpu/tlb_entry", .version_id = 0, .minimum_version_id = 0, .fields = (const VMStateField[]) { VMSTATE_UINT64(tlb_misc, LoongArchTLB), VMSTATE_UINT64(tlb_entry0, LoongArchTLB), VMSTATE_UINT64(tlb_entry1, LoongArchTLB), VMSTATE_END_OF_LIST() } }; static const VMStateDescription vmstate_tlb = { .name = "cpu/tlb", .version_id = 0, .minimum_version_id = 0, .needed = tlb_needed, .fields = (const VMStateField[]) { VMSTATE_STRUCT_ARRAY(env.tlb, LoongArchCPU, LOONGARCH_TLB_MAX, 0, vmstate_tlb_entry, LoongArchTLB), VMSTATE_END_OF_LIST() } }; #endif /* LoongArch CPU state */ const VMStateDescription vmstate_loongarch_cpu = { .name = "cpu", .version_id = 3, .minimum_version_id = 3, .fields = (const VMStateField[]) { VMSTATE_UINTTL_ARRAY(env.gpr, LoongArchCPU, 32), VMSTATE_UINTTL(env.pc, LoongArchCPU), /* Remaining CSRs */ VMSTATE_UINT64(env.CSR_CRMD, LoongArchCPU), VMSTATE_UINT64(env.CSR_PRMD, LoongArchCPU), VMSTATE_UINT64(env.CSR_EUEN, LoongArchCPU), VMSTATE_UINT64(env.CSR_MISC, LoongArchCPU), VMSTATE_UINT64(env.CSR_ECFG, LoongArchCPU), VMSTATE_UINT64(env.CSR_ESTAT, LoongArchCPU), VMSTATE_UINT64(env.CSR_ERA, LoongArchCPU), VMSTATE_UINT64(env.CSR_BADV, LoongArchCPU), VMSTATE_UINT64(env.CSR_BADI, LoongArchCPU), VMSTATE_UINT64(env.CSR_EENTRY, LoongArchCPU), VMSTATE_UINT64(env.CSR_TLBIDX, LoongArchCPU), VMSTATE_UINT64(env.CSR_TLBEHI, LoongArchCPU), VMSTATE_UINT64(env.CSR_TLBELO0, LoongArchCPU), VMSTATE_UINT64(env.CSR_TLBELO1, LoongArchCPU), VMSTATE_UINT64(env.CSR_ASID, LoongArchCPU), VMSTATE_UINT64(env.CSR_PGDL, LoongArchCPU), VMSTATE_UINT64(env.CSR_PGDH, LoongArchCPU), VMSTATE_UINT64(env.CSR_PGD, LoongArchCPU), VMSTATE_UINT64(env.CSR_PWCL, LoongArchCPU), VMSTATE_UINT64(env.CSR_PWCH, LoongArchCPU), VMSTATE_UINT64(env.CSR_STLBPS, LoongArchCPU), VMSTATE_UINT64(env.CSR_RVACFG, LoongArchCPU), VMSTATE_UINT64(env.CSR_PRCFG1, LoongArchCPU), VMSTATE_UINT64(env.CSR_PRCFG2, LoongArchCPU), VMSTATE_UINT64(env.CSR_PRCFG3, LoongArchCPU), VMSTATE_UINT64_ARRAY(env.CSR_SAVE, LoongArchCPU, 16), VMSTATE_UINT64(env.CSR_TID, LoongArchCPU), VMSTATE_UINT64(env.CSR_TCFG, LoongArchCPU), VMSTATE_UINT64(env.CSR_TVAL, LoongArchCPU), VMSTATE_UINT64(env.CSR_CNTC, LoongArchCPU), VMSTATE_UINT64(env.CSR_TICLR, LoongArchCPU), VMSTATE_UINT64(env.CSR_LLBCTL, LoongArchCPU), VMSTATE_UINT64(env.CSR_IMPCTL1, LoongArchCPU), VMSTATE_UINT64(env.CSR_IMPCTL2, LoongArchCPU), VMSTATE_UINT64(env.CSR_TLBRENTRY, LoongArchCPU), VMSTATE_UINT64(env.CSR_TLBRBADV, LoongArchCPU), VMSTATE_UINT64(env.CSR_TLBRERA, LoongArchCPU), VMSTATE_UINT64(env.CSR_TLBRSAVE, LoongArchCPU), VMSTATE_UINT64(env.CSR_TLBRELO0, LoongArchCPU), VMSTATE_UINT64(env.CSR_TLBRELO1, LoongArchCPU), VMSTATE_UINT64(env.CSR_TLBREHI, LoongArchCPU), VMSTATE_UINT64(env.CSR_TLBRPRMD, LoongArchCPU), VMSTATE_UINT64(env.CSR_MERRCTL, LoongArchCPU), VMSTATE_UINT64(env.CSR_MERRINFO1, LoongArchCPU), VMSTATE_UINT64(env.CSR_MERRINFO2, LoongArchCPU), VMSTATE_UINT64(env.CSR_MERRENTRY, LoongArchCPU), VMSTATE_UINT64(env.CSR_MERRERA, LoongArchCPU), VMSTATE_UINT64(env.CSR_MERRSAVE, LoongArchCPU), VMSTATE_UINT64(env.CSR_CTAG, LoongArchCPU), VMSTATE_UINT64_ARRAY(env.CSR_DMW, LoongArchCPU, 4), /* Debug CSRs */ VMSTATE_UINT64(env.CSR_DBG, LoongArchCPU), VMSTATE_UINT64(env.CSR_DERA, LoongArchCPU), VMSTATE_UINT64(env.CSR_DSAVE, LoongArchCPU), VMSTATE_UINT64(kvm_state_counter, LoongArchCPU), /* PV steal time */ VMSTATE_UINT64(env.stealtime.guest_addr, LoongArchCPU), VMSTATE_END_OF_LIST() }, .subsections = (const VMStateDescription * const []) { &vmstate_fpu, &vmstate_lsx, &vmstate_lasx, #if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) &vmstate_tlb, #endif &vmstate_lbt, NULL } };