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