1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3 * QEMU LoongArch Machine State
4 *
5 * Copyright (c) 2021 Loongson Technology Corporation Limited
6 */
7
8 #include "qemu/osdep.h"
9 #include "cpu.h"
10 #include "migration/cpu.h"
11 #include "sysemu/tcg.h"
12 #include "vec.h"
13
14 static const VMStateDescription vmstate_fpu_reg = {
15 .name = "fpu_reg",
16 .version_id = 1,
17 .minimum_version_id = 1,
18 .fields = (const VMStateField[]) {
19 VMSTATE_UINT64(UD(0), VReg),
20 VMSTATE_END_OF_LIST()
21 }
22 };
23
24 #define VMSTATE_FPU_REGS(_field, _state, _start) \
25 VMSTATE_STRUCT_SUB_ARRAY(_field, _state, _start, 32, 0, \
26 vmstate_fpu_reg, fpr_t)
27
fpu_needed(void * opaque)28 static bool fpu_needed(void *opaque)
29 {
30 LoongArchCPU *cpu = opaque;
31
32 return FIELD_EX64(cpu->env.cpucfg[2], CPUCFG2, FP);
33 }
34
35 static const VMStateDescription vmstate_fpu = {
36 .name = "cpu/fpu",
37 .version_id = 1,
38 .minimum_version_id = 1,
39 .needed = fpu_needed,
40 .fields = (const VMStateField[]) {
41 VMSTATE_FPU_REGS(env.fpr, LoongArchCPU, 0),
42 VMSTATE_UINT32(env.fcsr0, LoongArchCPU),
43 VMSTATE_BOOL_ARRAY(env.cf, LoongArchCPU, 8),
44 VMSTATE_END_OF_LIST()
45 },
46 };
47
48 static const VMStateDescription vmstate_lsxh_reg = {
49 .name = "lsxh_reg",
50 .version_id = 1,
51 .minimum_version_id = 1,
52 .fields = (const VMStateField[]) {
53 VMSTATE_UINT64(UD(1), VReg),
54 VMSTATE_END_OF_LIST()
55 }
56 };
57
58 #define VMSTATE_LSXH_REGS(_field, _state, _start) \
59 VMSTATE_STRUCT_SUB_ARRAY(_field, _state, _start, 32, 0, \
60 vmstate_lsxh_reg, fpr_t)
61
lsx_needed(void * opaque)62 static bool lsx_needed(void *opaque)
63 {
64 LoongArchCPU *cpu = opaque;
65
66 return FIELD_EX64(cpu->env.cpucfg[2], CPUCFG2, LSX);
67 }
68
69 static const VMStateDescription vmstate_lsx = {
70 .name = "cpu/lsx",
71 .version_id = 1,
72 .minimum_version_id = 1,
73 .needed = lsx_needed,
74 .fields = (const VMStateField[]) {
75 VMSTATE_LSXH_REGS(env.fpr, LoongArchCPU, 0),
76 VMSTATE_END_OF_LIST()
77 },
78 };
79
80 static const VMStateDescription vmstate_lasxh_reg = {
81 .name = "lasxh_reg",
82 .version_id = 1,
83 .minimum_version_id = 1,
84 .fields = (const VMStateField[]) {
85 VMSTATE_UINT64(UD(2), VReg),
86 VMSTATE_UINT64(UD(3), VReg),
87 VMSTATE_END_OF_LIST()
88 }
89 };
90
91 #define VMSTATE_LASXH_REGS(_field, _state, _start) \
92 VMSTATE_STRUCT_SUB_ARRAY(_field, _state, _start, 32, 0, \
93 vmstate_lasxh_reg, fpr_t)
94
lasx_needed(void * opaque)95 static bool lasx_needed(void *opaque)
96 {
97 LoongArchCPU *cpu = opaque;
98
99 return FIELD_EX64(cpu->env.cpucfg[2], CPUCFG2, LASX);
100 }
101
102 static const VMStateDescription vmstate_lasx = {
103 .name = "cpu/lasx",
104 .version_id = 1,
105 .minimum_version_id = 1,
106 .needed = lasx_needed,
107 .fields = (const VMStateField[]) {
108 VMSTATE_LASXH_REGS(env.fpr, LoongArchCPU, 0),
109 VMSTATE_END_OF_LIST()
110 },
111 };
112
lbt_needed(void * opaque)113 static bool lbt_needed(void *opaque)
114 {
115 LoongArchCPU *cpu = opaque;
116
117 return !!FIELD_EX64(cpu->env.cpucfg[2], CPUCFG2, LBT_ALL);
118 }
119
120 static const VMStateDescription vmstate_lbt = {
121 .name = "cpu/lbt",
122 .version_id = 0,
123 .minimum_version_id = 0,
124 .needed = lbt_needed,
125 .fields = (const VMStateField[]) {
126 VMSTATE_UINT64(env.lbt.scr0, LoongArchCPU),
127 VMSTATE_UINT64(env.lbt.scr1, LoongArchCPU),
128 VMSTATE_UINT64(env.lbt.scr2, LoongArchCPU),
129 VMSTATE_UINT64(env.lbt.scr3, LoongArchCPU),
130 VMSTATE_UINT32(env.lbt.eflags, LoongArchCPU),
131 VMSTATE_UINT32(env.lbt.ftop, LoongArchCPU),
132 VMSTATE_END_OF_LIST()
133 },
134 };
135
136 #if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY)
tlb_needed(void * opaque)137 static bool tlb_needed(void *opaque)
138 {
139 return tcg_enabled();
140 }
141
142 /* TLB state */
143 static const VMStateDescription vmstate_tlb_entry = {
144 .name = "cpu/tlb_entry",
145 .version_id = 0,
146 .minimum_version_id = 0,
147 .fields = (const VMStateField[]) {
148 VMSTATE_UINT64(tlb_misc, LoongArchTLB),
149 VMSTATE_UINT64(tlb_entry0, LoongArchTLB),
150 VMSTATE_UINT64(tlb_entry1, LoongArchTLB),
151 VMSTATE_END_OF_LIST()
152 }
153 };
154
155 static const VMStateDescription vmstate_tlb = {
156 .name = "cpu/tlb",
157 .version_id = 0,
158 .minimum_version_id = 0,
159 .needed = tlb_needed,
160 .fields = (const VMStateField[]) {
161 VMSTATE_STRUCT_ARRAY(env.tlb, LoongArchCPU, LOONGARCH_TLB_MAX,
162 0, vmstate_tlb_entry, LoongArchTLB),
163 VMSTATE_END_OF_LIST()
164 }
165 };
166 #endif
167
168 /* LoongArch CPU state */
169 const VMStateDescription vmstate_loongarch_cpu = {
170 .name = "cpu",
171 .version_id = 3,
172 .minimum_version_id = 3,
173 .fields = (const VMStateField[]) {
174 VMSTATE_UINTTL_ARRAY(env.gpr, LoongArchCPU, 32),
175 VMSTATE_UINTTL(env.pc, LoongArchCPU),
176
177 /* Remaining CSRs */
178 VMSTATE_UINT64(env.CSR_CRMD, LoongArchCPU),
179 VMSTATE_UINT64(env.CSR_PRMD, LoongArchCPU),
180 VMSTATE_UINT64(env.CSR_EUEN, LoongArchCPU),
181 VMSTATE_UINT64(env.CSR_MISC, LoongArchCPU),
182 VMSTATE_UINT64(env.CSR_ECFG, LoongArchCPU),
183 VMSTATE_UINT64(env.CSR_ESTAT, LoongArchCPU),
184 VMSTATE_UINT64(env.CSR_ERA, LoongArchCPU),
185 VMSTATE_UINT64(env.CSR_BADV, LoongArchCPU),
186 VMSTATE_UINT64(env.CSR_BADI, LoongArchCPU),
187 VMSTATE_UINT64(env.CSR_EENTRY, LoongArchCPU),
188 VMSTATE_UINT64(env.CSR_TLBIDX, LoongArchCPU),
189 VMSTATE_UINT64(env.CSR_TLBEHI, LoongArchCPU),
190 VMSTATE_UINT64(env.CSR_TLBELO0, LoongArchCPU),
191 VMSTATE_UINT64(env.CSR_TLBELO1, LoongArchCPU),
192 VMSTATE_UINT64(env.CSR_ASID, LoongArchCPU),
193 VMSTATE_UINT64(env.CSR_PGDL, LoongArchCPU),
194 VMSTATE_UINT64(env.CSR_PGDH, LoongArchCPU),
195 VMSTATE_UINT64(env.CSR_PGD, LoongArchCPU),
196 VMSTATE_UINT64(env.CSR_PWCL, LoongArchCPU),
197 VMSTATE_UINT64(env.CSR_PWCH, LoongArchCPU),
198 VMSTATE_UINT64(env.CSR_STLBPS, LoongArchCPU),
199 VMSTATE_UINT64(env.CSR_RVACFG, LoongArchCPU),
200 VMSTATE_UINT64(env.CSR_PRCFG1, LoongArchCPU),
201 VMSTATE_UINT64(env.CSR_PRCFG2, LoongArchCPU),
202 VMSTATE_UINT64(env.CSR_PRCFG3, LoongArchCPU),
203 VMSTATE_UINT64_ARRAY(env.CSR_SAVE, LoongArchCPU, 16),
204 VMSTATE_UINT64(env.CSR_TID, LoongArchCPU),
205 VMSTATE_UINT64(env.CSR_TCFG, LoongArchCPU),
206 VMSTATE_UINT64(env.CSR_TVAL, LoongArchCPU),
207 VMSTATE_UINT64(env.CSR_CNTC, LoongArchCPU),
208 VMSTATE_UINT64(env.CSR_TICLR, LoongArchCPU),
209 VMSTATE_UINT64(env.CSR_LLBCTL, LoongArchCPU),
210 VMSTATE_UINT64(env.CSR_IMPCTL1, LoongArchCPU),
211 VMSTATE_UINT64(env.CSR_IMPCTL2, LoongArchCPU),
212 VMSTATE_UINT64(env.CSR_TLBRENTRY, LoongArchCPU),
213 VMSTATE_UINT64(env.CSR_TLBRBADV, LoongArchCPU),
214 VMSTATE_UINT64(env.CSR_TLBRERA, LoongArchCPU),
215 VMSTATE_UINT64(env.CSR_TLBRSAVE, LoongArchCPU),
216 VMSTATE_UINT64(env.CSR_TLBRELO0, LoongArchCPU),
217 VMSTATE_UINT64(env.CSR_TLBRELO1, LoongArchCPU),
218 VMSTATE_UINT64(env.CSR_TLBREHI, LoongArchCPU),
219 VMSTATE_UINT64(env.CSR_TLBRPRMD, LoongArchCPU),
220 VMSTATE_UINT64(env.CSR_MERRCTL, LoongArchCPU),
221 VMSTATE_UINT64(env.CSR_MERRINFO1, LoongArchCPU),
222 VMSTATE_UINT64(env.CSR_MERRINFO2, LoongArchCPU),
223 VMSTATE_UINT64(env.CSR_MERRENTRY, LoongArchCPU),
224 VMSTATE_UINT64(env.CSR_MERRERA, LoongArchCPU),
225 VMSTATE_UINT64(env.CSR_MERRSAVE, LoongArchCPU),
226 VMSTATE_UINT64(env.CSR_CTAG, LoongArchCPU),
227 VMSTATE_UINT64_ARRAY(env.CSR_DMW, LoongArchCPU, 4),
228
229 /* Debug CSRs */
230 VMSTATE_UINT64(env.CSR_DBG, LoongArchCPU),
231 VMSTATE_UINT64(env.CSR_DERA, LoongArchCPU),
232 VMSTATE_UINT64(env.CSR_DSAVE, LoongArchCPU),
233
234 VMSTATE_UINT64(kvm_state_counter, LoongArchCPU),
235 /* PV steal time */
236 VMSTATE_UINT64(env.stealtime.guest_addr, LoongArchCPU),
237
238 VMSTATE_END_OF_LIST()
239 },
240 .subsections = (const VMStateDescription * const []) {
241 &vmstate_fpu,
242 &vmstate_lsx,
243 &vmstate_lasx,
244 #if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY)
245 &vmstate_tlb,
246 #endif
247 &vmstate_lbt,
248 NULL
249 }
250 };
251