master
c 338 lines 9.76 KB
Raw
1 #include "qemu/osdep.h"
2 #include "cpu.h"
3 #include "qemu/target-info.h"
4 #include "qemu/timer.h"
5
6 #include "migration/cpu.h"
7 #include "migration/qemu-file-types.h"
8
9 #ifdef TARGET_SPARC64
10 static const VMStateDescription vmstate_cpu_timer = {
11 .name = "cpu_timer",
12 .version_id = 1,
13 .minimum_version_id = 1,
14 .fields = (const VMStateField[]) {
15 VMSTATE_UINT32(frequency, CPUTimer),
16 VMSTATE_UINT32(disabled, CPUTimer),
17 VMSTATE_UINT64(disabled_mask, CPUTimer),
18 VMSTATE_UINT32(npt, CPUTimer),
19 VMSTATE_UINT64(npt_mask, CPUTimer),
20 VMSTATE_INT64(clock_offset, CPUTimer),
21 VMSTATE_TIMER_PTR(qtimer, CPUTimer),
22 VMSTATE_END_OF_LIST()
23 }
24 };
25
26 #define VMSTATE_CPU_TIMER(_f, _s) \
27 VMSTATE_STRUCT_POINTER(_f, _s, vmstate_cpu_timer, CPUTimer)
28
29 static const VMStateDescription vmstate_trap_state = {
30 .name = "trap_state",
31 .version_id = 1,
32 .minimum_version_id = 1,
33 .fields = (const VMStateField[]) {
34 VMSTATE_UINT64(tpc, trap_state),
35 VMSTATE_UINT64(tnpc, trap_state),
36 VMSTATE_UINT64(tstate, trap_state),
37 VMSTATE_UINT32(tt, trap_state),
38 VMSTATE_END_OF_LIST()
39 }
40 };
41
42 static const VMStateDescription vmstate_tlb_entry = {
43 .name = "tlb_entry",
44 .version_id = 1,
45 .minimum_version_id = 1,
46 .fields = (const VMStateField[]) {
47 VMSTATE_UINT64(tag, SparcTLBEntry),
48 VMSTATE_UINT64(tte, SparcTLBEntry),
49 VMSTATE_END_OF_LIST()
50 }
51 };
52 #endif
53
54 static int get_psr(QEMUFile *f, void *opaque, size_t size,
55 const VMStateField *field)
56 {
57 SPARCCPU *cpu = opaque;
58 CPUSPARCState *env = &cpu->env;
59 uint32_t val = qemu_get_be32(f);
60
61 /* needed to ensure that the wrapping registers are correctly updated */
62 env->cwp = 0;
63 cpu_put_psr_raw(env, val);
64
65 return 0;
66 }
67
68 static int put_psr(QEMUFile *f, void *opaque, size_t size,
69 const VMStateField *field, JSONWriter *vmdesc)
70 {
71 SPARCCPU *cpu = opaque;
72 CPUSPARCState *env = &cpu->env;
73 uint32_t val;
74
75 val = cpu_get_psr(env);
76
77 qemu_put_be32(f, val);
78 return 0;
79 }
80
81 static const VMStateInfo vmstate_psr = {
82 .name = "psr",
83 .get = get_psr,
84 .put = put_psr,
85 };
86
87 static int get_fsr(QEMUFile *f, void *opaque, size_t size,
88 const VMStateField *field)
89 {
90 SPARCCPU *cpu = opaque;
91
92 if (target_long_bits() == 64) {
93 cpu_put_fsr(&cpu->env, qemu_get_be64(f));
94 } else {
95 cpu_put_fsr(&cpu->env, qemu_get_be32(f));
96 }
97
98 return 0;
99 }
100
101 static int put_fsr(QEMUFile *f, void *opaque, size_t size,
102 const VMStateField *field, JSONWriter *vmdesc)
103 {
104 SPARCCPU *cpu = opaque;
105
106 if (target_long_bits() == 64) {
107 qemu_put_be64(f, cpu_get_fsr(&cpu->env));
108 } else {
109 qemu_put_be32(f, cpu_get_fsr(&cpu->env));
110 }
111 return 0;
112 }
113
114 static const VMStateInfo vmstate_fsr = {
115 .name = "fsr",
116 .get = get_fsr,
117 .put = put_fsr,
118 };
119
120 #ifdef TARGET_SPARC64
121 static int get_xcc(QEMUFile *f, void *opaque, size_t size,
122 const VMStateField *field)
123 {
124 SPARCCPU *cpu = opaque;
125 CPUSPARCState *env = &cpu->env;
126 uint32_t val = qemu_get_be32(f);
127
128 /* Do not clobber icc.[NV] */
129 env->cc_N = deposit64(env->cc_N, 32, 32, -(val & PSR_NEG));
130 env->cc_V = deposit64(env->cc_V, 32, 32, -(val & PSR_OVF));
131 env->xcc_Z = ~val & PSR_ZERO;
132 env->xcc_C = (val >> PSR_CARRY_SHIFT) & 1;
133
134 return 0;
135 }
136
137 static int put_xcc(QEMUFile *f, void *opaque, size_t size,
138 const VMStateField *field, JSONWriter *vmdesc)
139 {
140 SPARCCPU *cpu = opaque;
141 CPUSPARCState *env = &cpu->env;
142 uint32_t val = cpu_get_ccr(env);
143
144 /* Extract just xcc out of ccr and shift into legacy position. */
145 qemu_put_be32(f, (val & 0xf0) << (20 - 4));
146 return 0;
147 }
148
149 static const VMStateInfo vmstate_xcc = {
150 .name = "xcc",
151 .get = get_xcc,
152 .put = put_xcc,
153 };
154
155 static int get_cwp(QEMUFile *f, void *opaque, size_t size,
156 const VMStateField *field)
157 {
158 SPARCCPU *cpu = opaque;
159 CPUSPARCState *env = &cpu->env;
160 uint32_t val = qemu_get_be32(f);
161
162 /* needed to ensure that the wrapping registers are correctly updated */
163 env->cwp = 0;
164 cpu_set_cwp(env, val);
165
166 return 0;
167 }
168
169 static int put_cwp(QEMUFile *f, void *opaque, size_t size,
170 const VMStateField *field, JSONWriter *vmdesc)
171 {
172 SPARCCPU *cpu = opaque;
173 CPUSPARCState *env = &cpu->env;
174 uint32_t val = env->cwp;
175
176 qemu_put_be32(f, val);
177 return 0;
178 }
179
180 static const VMStateInfo vmstate_cwp = {
181 .name = "uint32",
182 .get = get_cwp,
183 .put = put_cwp,
184 };
185 #else
186 static bool fq_needed(void *opaque)
187 {
188 SPARCCPU *cpu = opaque;
189 return cpu->env.fsr_qne;
190 }
191
192 static const VMStateDescription vmstate_fq = {
193 .name = "cpu/fq",
194 .version_id = 1,
195 .minimum_version_id = 1,
196 .needed = fq_needed,
197 .fields = (const VMStateField[]) {
198 VMSTATE_UINT32(env.fq.s.addr, SPARCCPU),
199 VMSTATE_UINT32(env.fq.s.insn, SPARCCPU),
200 VMSTATE_END_OF_LIST()
201 },
202 };
203 #endif
204
205 static int cpu_pre_save(void *opaque)
206 {
207 SPARCCPU *cpu = opaque;
208 CPUSPARCState *env = &cpu->env;
209
210 /* if env->cwp == env->nwindows - 1, this will set the ins of the last
211 * window as the outs of the first window
212 */
213 cpu_set_cwp(env, env->cwp);
214
215 return 0;
216 }
217
218 /* 32-bit SPARC retains migration compatibility with older versions
219 * of QEMU; 64-bit SPARC has had a migration break since then, so the
220 * versions are different.
221 */
222 #ifndef TARGET_SPARC64
223 #define SPARC_VMSTATE_VER 8
224 #else
225 #define SPARC_VMSTATE_VER 10
226 #endif
227
228 const VMStateDescription vmstate_sparc_cpu = {
229 .name = "cpu",
230 .version_id = SPARC_VMSTATE_VER,
231 .minimum_version_id = SPARC_VMSTATE_VER,
232 .pre_save = cpu_pre_save,
233 .fields = (const VMStateField[]) {
234 VMSTATE_UINTTL_ARRAY(env.gregs, SPARCCPU, 8),
235 VMSTATE_UINT32(env.nwindows, SPARCCPU),
236 VMSTATE_UINTTL_ARRAY(env.regbase, SPARCCPU, MAX_NWINDOWS * 16 + 8),
237 VMSTATE_CPUDOUBLE_ARRAY(env.fpr, SPARCCPU, TARGET_DPREGS),
238 VMSTATE_UINTTL(env.pc, SPARCCPU),
239 VMSTATE_UINTTL(env.npc, SPARCCPU),
240 VMSTATE_UINTTL(env.y, SPARCCPU),
241 {
242 .name = "psr",
243 .version_id = 0,
244 .size = sizeof(uint32_t),
245 .info = &vmstate_psr,
246 .flags = VMS_SINGLE,
247 .offset = 0,
248 },
249 {
250 .name = "fsr",
251 .version_id = 0,
252 .size = sizeof(target_ulong),
253 .info = &vmstate_fsr,
254 .flags = VMS_SINGLE,
255 .offset = 0,
256 },
257 VMSTATE_UINTTL(env.tbr, SPARCCPU),
258 VMSTATE_INT32(env.interrupt_index, SPARCCPU),
259 VMSTATE_UINT32(env.pil_in, SPARCCPU),
260 #ifndef TARGET_SPARC64
261 /* MMU */
262 VMSTATE_UINT32(env.wim, SPARCCPU),
263 VMSTATE_UINT32_ARRAY(env.mmuregs, SPARCCPU, 32),
264 VMSTATE_UINT64_ARRAY(env.mxccdata, SPARCCPU, 4),
265 VMSTATE_UINT64_ARRAY(env.mxccregs, SPARCCPU, 8),
266 VMSTATE_UINT32(env.mmubpctrv, SPARCCPU),
267 VMSTATE_UINT32(env.mmubpctrc, SPARCCPU),
268 VMSTATE_UINT32(env.mmubpctrs, SPARCCPU),
269 VMSTATE_UINT64(env.mmubpaction, SPARCCPU),
270 VMSTATE_UINT64_ARRAY(env.mmubpregs, SPARCCPU, 4),
271 #else
272 VMSTATE_UINT64(env.lsu, SPARCCPU),
273 VMSTATE_UINT64_ARRAY(env.immu.mmuregs, SPARCCPU, 16),
274 VMSTATE_UINT64_ARRAY(env.dmmu.mmuregs, SPARCCPU, 16),
275 VMSTATE_STRUCT_ARRAY(env.itlb, SPARCCPU, 64, 0,
276 vmstate_tlb_entry, SparcTLBEntry),
277 VMSTATE_STRUCT_ARRAY(env.dtlb, SPARCCPU, 64, 0,
278 vmstate_tlb_entry, SparcTLBEntry),
279 VMSTATE_UINT32(env.mmu_version, SPARCCPU),
280 VMSTATE_STRUCT_ARRAY(env.ts, SPARCCPU, MAXTL_MAX, 0,
281 vmstate_trap_state, trap_state),
282 {
283 .name = "xcc",
284 .version_id = 0,
285 .size = sizeof(uint32_t),
286 .info = &vmstate_xcc,
287 .flags = VMS_SINGLE,
288 .offset = 0,
289 },
290 VMSTATE_UINT32(env.asi, SPARCCPU),
291 VMSTATE_UINT32(env.pstate, SPARCCPU),
292 VMSTATE_UINT32(env.tl, SPARCCPU),
293 VMSTATE_UINT32(env.cansave, SPARCCPU),
294 VMSTATE_UINT32(env.canrestore, SPARCCPU),
295 VMSTATE_UINT32(env.otherwin, SPARCCPU),
296 VMSTATE_UINT32(env.wstate, SPARCCPU),
297 VMSTATE_UINT32(env.cleanwin, SPARCCPU),
298 VMSTATE_UINT64_ARRAY(env.agregs, SPARCCPU, 8),
299 VMSTATE_UINT64_ARRAY(env.bgregs, SPARCCPU, 8),
300 VMSTATE_UINT64_ARRAY(env.igregs, SPARCCPU, 8),
301 VMSTATE_UINT64_ARRAY(env.mgregs, SPARCCPU, 8),
302 VMSTATE_UNUSED(4), /* was unused high half of uint64_t fprs */
303 VMSTATE_UINT32(env.fprs, SPARCCPU),
304 VMSTATE_UINT64(env.tick_cmpr, SPARCCPU),
305 VMSTATE_UINT64(env.stick_cmpr, SPARCCPU),
306 VMSTATE_CPU_TIMER(env.tick, SPARCCPU),
307 VMSTATE_CPU_TIMER(env.stick, SPARCCPU),
308 VMSTATE_UINT64(env.gsr, SPARCCPU),
309 VMSTATE_UINT32(env.gl, SPARCCPU),
310 VMSTATE_UINT64(env.hpstate, SPARCCPU),
311 VMSTATE_UINT64_ARRAY(env.htstate, SPARCCPU, MAXTL_MAX),
312 VMSTATE_UINT64(env.hintp, SPARCCPU),
313 VMSTATE_UINT64(env.htba, SPARCCPU),
314 VMSTATE_UINT64(env.hver, SPARCCPU),
315 VMSTATE_UINT64(env.hstick_cmpr, SPARCCPU),
316 VMSTATE_UINT64(env.ssr, SPARCCPU),
317 VMSTATE_CPU_TIMER(env.hstick, SPARCCPU),
318 /* On SPARC32 env.psrpil and env.cwp are migrated as part of the PSR */
319 VMSTATE_UINT32(env.psrpil, SPARCCPU),
320 {
321 .name = "env.cwp",
322 .version_id = 0,
323 .size = sizeof(uint32_t),
324 .info = &vmstate_cwp,
325 .flags = VMS_SINGLE,
326 .offset = 0,
327 },
328 #endif
329 VMSTATE_END_OF_LIST()
330 },
331 #ifndef TARGET_SPARC64
332 .subsections = (const VMStateDescription * const []) {
333 &vmstate_fq,
334 NULL
335 },
336 #endif
337
338 };