xref: /openbmc/qemu/target/arm/machine.c (revision 23901b2b721c0576007ab7580da8aa855d6042a9)
1fcf5ef2aSThomas Huth #include "qemu/osdep.h"
2fcf5ef2aSThomas Huth #include "cpu.h"
3fcf5ef2aSThomas Huth #include "qemu/error-report.h"
4fcf5ef2aSThomas Huth #include "sysemu/kvm.h"
5fa05d1abSFabiano Rosas #include "sysemu/tcg.h"
6fcf5ef2aSThomas Huth #include "kvm_arm.h"
7fcf5ef2aSThomas Huth #include "internals.h"
85a534314SPeter Maydell #include "cpu-features.h"
9fcf5ef2aSThomas Huth #include "migration/cpu.h"
10f4f318b4SPhilippe Mathieu-Daudé #include "target/arm/gtimer.h"
11fcf5ef2aSThomas Huth 
vfp_needed(void * opaque)12fcf5ef2aSThomas Huth static bool vfp_needed(void *opaque)
13fcf5ef2aSThomas Huth {
14fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
15fcf5ef2aSThomas Huth 
167d63183fSRichard Henderson     return (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)
177d63183fSRichard Henderson             ? cpu_isar_feature(aa64_fp_simd, cpu)
187d63183fSRichard Henderson             : cpu_isar_feature(aa32_vfp_simd, cpu));
19fcf5ef2aSThomas Huth }
20fcf5ef2aSThomas Huth 
vfp_fpcr_fpsr_needed(void * opaque)21abf1046aSPeter Maydell static bool vfp_fpcr_fpsr_needed(void *opaque)
22abf1046aSPeter Maydell {
23abf1046aSPeter Maydell     /*
24abf1046aSPeter Maydell      * If either the FPCR or the FPSR include set bits that are not
25abf1046aSPeter Maydell      * visible in the AArch32 FPSCR view of floating point control/status
26abf1046aSPeter Maydell      * then we must send the FPCR and FPSR as two separate fields in the
27abf1046aSPeter Maydell      * cpu/vfp/fpcr_fpsr subsection, and we will send a 0 for the old
28abf1046aSPeter Maydell      * FPSCR field in cpu/vfp.
29abf1046aSPeter Maydell      *
30abf1046aSPeter Maydell      * If all the set bits are representable in an AArch32 FPSCR then we
31abf1046aSPeter Maydell      * send that value as the cpu/vfp FPSCR field, and don't send the
32abf1046aSPeter Maydell      * cpu/vfp/fpcr_fpsr subsection.
33abf1046aSPeter Maydell      *
34abf1046aSPeter Maydell      * On incoming migration, if the cpu/vfp FPSCR field is non-zero we
35abf1046aSPeter Maydell      * use it, and if the fpcr_fpsr subsection is present we use that.
36abf1046aSPeter Maydell      * (The subsection will never be present with a non-zero FPSCR field,
37abf1046aSPeter Maydell      * and if FPSCR is zero and the subsection is not present that means
38abf1046aSPeter Maydell      * that FPSCR/FPSR/FPCR are zero.)
39abf1046aSPeter Maydell      *
40abf1046aSPeter Maydell      * This preserves migration compatibility with older QEMU versions,
41abf1046aSPeter Maydell      * in both directions.
42abf1046aSPeter Maydell      */
43abf1046aSPeter Maydell     ARMCPU *cpu = opaque;
44abf1046aSPeter Maydell     CPUARMState *env = &cpu->env;
45abf1046aSPeter Maydell 
46*db397a81SPeter Maydell     return (vfp_get_fpcr(env) & ~FPSCR_FPCR_MASK) ||
47*db397a81SPeter Maydell         (vfp_get_fpsr(env) & ~FPSCR_FPSR_MASK);
48abf1046aSPeter Maydell }
49abf1046aSPeter Maydell 
get_fpscr(QEMUFile * f,void * opaque,size_t size,const VMStateField * field)502c21ee76SJianjun Duan static int get_fpscr(QEMUFile *f, void *opaque, size_t size,
5103fee66fSMarc-André Lureau                      const VMStateField *field)
52fcf5ef2aSThomas Huth {
53fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
54fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
55fcf5ef2aSThomas Huth     uint32_t val = qemu_get_be32(f);
56fcf5ef2aSThomas Huth 
57abf1046aSPeter Maydell     if (val) {
58abf1046aSPeter Maydell         /* 0 means we might have the data in the fpcr_fpsr subsection */
59fcf5ef2aSThomas Huth         vfp_set_fpscr(env, val);
60abf1046aSPeter Maydell     }
61fcf5ef2aSThomas Huth     return 0;
62fcf5ef2aSThomas Huth }
63fcf5ef2aSThomas Huth 
put_fpscr(QEMUFile * f,void * opaque,size_t size,const VMStateField * field,JSONWriter * vmdesc)642c21ee76SJianjun Duan static int put_fpscr(QEMUFile *f, void *opaque, size_t size,
653ddba9a9SMarkus Armbruster                      const VMStateField *field, JSONWriter *vmdesc)
66fcf5ef2aSThomas Huth {
67fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
68fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
69abf1046aSPeter Maydell     uint32_t fpscr = vfp_fpcr_fpsr_needed(opaque) ? 0 : vfp_get_fpscr(env);
70fcf5ef2aSThomas Huth 
71abf1046aSPeter Maydell     qemu_put_be32(f, fpscr);
722c21ee76SJianjun Duan     return 0;
73fcf5ef2aSThomas Huth }
74fcf5ef2aSThomas Huth 
75fcf5ef2aSThomas Huth static const VMStateInfo vmstate_fpscr = {
76fcf5ef2aSThomas Huth     .name = "fpscr",
77fcf5ef2aSThomas Huth     .get = get_fpscr,
78fcf5ef2aSThomas Huth     .put = put_fpscr,
79fcf5ef2aSThomas Huth };
80fcf5ef2aSThomas Huth 
get_fpcr(QEMUFile * f,void * opaque,size_t size,const VMStateField * field)81abf1046aSPeter Maydell static int get_fpcr(QEMUFile *f, void *opaque, size_t size,
82abf1046aSPeter Maydell                      const VMStateField *field)
83abf1046aSPeter Maydell {
84abf1046aSPeter Maydell     ARMCPU *cpu = opaque;
85abf1046aSPeter Maydell     CPUARMState *env = &cpu->env;
86abf1046aSPeter Maydell     uint64_t val = qemu_get_be64(f);
87abf1046aSPeter Maydell 
88abf1046aSPeter Maydell     vfp_set_fpcr(env, val);
89abf1046aSPeter Maydell     return 0;
90abf1046aSPeter Maydell }
91abf1046aSPeter Maydell 
put_fpcr(QEMUFile * f,void * opaque,size_t size,const VMStateField * field,JSONWriter * vmdesc)92abf1046aSPeter Maydell static int put_fpcr(QEMUFile *f, void *opaque, size_t size,
93abf1046aSPeter Maydell                      const VMStateField *field, JSONWriter *vmdesc)
94abf1046aSPeter Maydell {
95abf1046aSPeter Maydell     ARMCPU *cpu = opaque;
96abf1046aSPeter Maydell     CPUARMState *env = &cpu->env;
97abf1046aSPeter Maydell 
98abf1046aSPeter Maydell     qemu_put_be64(f, vfp_get_fpcr(env));
99abf1046aSPeter Maydell     return 0;
100abf1046aSPeter Maydell }
101abf1046aSPeter Maydell 
102abf1046aSPeter Maydell static const VMStateInfo vmstate_fpcr = {
103abf1046aSPeter Maydell     .name = "fpcr",
104abf1046aSPeter Maydell     .get = get_fpcr,
105abf1046aSPeter Maydell     .put = put_fpcr,
106abf1046aSPeter Maydell };
107abf1046aSPeter Maydell 
get_fpsr(QEMUFile * f,void * opaque,size_t size,const VMStateField * field)108abf1046aSPeter Maydell static int get_fpsr(QEMUFile *f, void *opaque, size_t size,
109abf1046aSPeter Maydell                      const VMStateField *field)
110abf1046aSPeter Maydell {
111abf1046aSPeter Maydell     ARMCPU *cpu = opaque;
112abf1046aSPeter Maydell     CPUARMState *env = &cpu->env;
113abf1046aSPeter Maydell     uint64_t val = qemu_get_be64(f);
114abf1046aSPeter Maydell 
115abf1046aSPeter Maydell     vfp_set_fpsr(env, val);
116abf1046aSPeter Maydell     return 0;
117abf1046aSPeter Maydell }
118abf1046aSPeter Maydell 
put_fpsr(QEMUFile * f,void * opaque,size_t size,const VMStateField * field,JSONWriter * vmdesc)119abf1046aSPeter Maydell static int put_fpsr(QEMUFile *f, void *opaque, size_t size,
120abf1046aSPeter Maydell                      const VMStateField *field, JSONWriter *vmdesc)
121abf1046aSPeter Maydell {
122abf1046aSPeter Maydell     ARMCPU *cpu = opaque;
123abf1046aSPeter Maydell     CPUARMState *env = &cpu->env;
124abf1046aSPeter Maydell 
125abf1046aSPeter Maydell     qemu_put_be64(f, vfp_get_fpsr(env));
126abf1046aSPeter Maydell     return 0;
127abf1046aSPeter Maydell }
128abf1046aSPeter Maydell 
129abf1046aSPeter Maydell static const VMStateInfo vmstate_fpsr = {
130abf1046aSPeter Maydell     .name = "fpsr",
131abf1046aSPeter Maydell     .get = get_fpsr,
132abf1046aSPeter Maydell     .put = put_fpsr,
133abf1046aSPeter Maydell };
134abf1046aSPeter Maydell 
135abf1046aSPeter Maydell static const VMStateDescription vmstate_vfp_fpcr_fpsr = {
136abf1046aSPeter Maydell     .name = "cpu/vfp/fpcr_fpsr",
137abf1046aSPeter Maydell     .version_id = 1,
138abf1046aSPeter Maydell     .minimum_version_id = 1,
139abf1046aSPeter Maydell     .needed = vfp_fpcr_fpsr_needed,
140abf1046aSPeter Maydell     .fields = (const VMStateField[]) {
141abf1046aSPeter Maydell         {
142abf1046aSPeter Maydell             .name = "fpcr",
143abf1046aSPeter Maydell             .version_id = 0,
144abf1046aSPeter Maydell             .size = sizeof(uint64_t),
145abf1046aSPeter Maydell             .info = &vmstate_fpcr,
146abf1046aSPeter Maydell             .flags = VMS_SINGLE,
147abf1046aSPeter Maydell             .offset = 0,
148abf1046aSPeter Maydell         },
149abf1046aSPeter Maydell         {
150abf1046aSPeter Maydell             .name = "fpsr",
151abf1046aSPeter Maydell             .version_id = 0,
152abf1046aSPeter Maydell             .size = sizeof(uint64_t),
153abf1046aSPeter Maydell             .info = &vmstate_fpsr,
154abf1046aSPeter Maydell             .flags = VMS_SINGLE,
155abf1046aSPeter Maydell             .offset = 0,
156abf1046aSPeter Maydell         },
157abf1046aSPeter Maydell         VMSTATE_END_OF_LIST()
158abf1046aSPeter Maydell     },
159abf1046aSPeter Maydell };
160abf1046aSPeter Maydell 
161fcf5ef2aSThomas Huth static const VMStateDescription vmstate_vfp = {
162fcf5ef2aSThomas Huth     .name = "cpu/vfp",
163fcf5ef2aSThomas Huth     .version_id = 3,
164fcf5ef2aSThomas Huth     .minimum_version_id = 3,
165fcf5ef2aSThomas Huth     .needed = vfp_needed,
166e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
167c39c2b90SRichard Henderson         /* For compatibility, store Qn out of Zn here.  */
168c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[0].d, ARMCPU, 0, 2),
169c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[1].d, ARMCPU, 0, 2),
170c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[2].d, ARMCPU, 0, 2),
171c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[3].d, ARMCPU, 0, 2),
172c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[4].d, ARMCPU, 0, 2),
173c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[5].d, ARMCPU, 0, 2),
174c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[6].d, ARMCPU, 0, 2),
175c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[7].d, ARMCPU, 0, 2),
176c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[8].d, ARMCPU, 0, 2),
177c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[9].d, ARMCPU, 0, 2),
178c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[10].d, ARMCPU, 0, 2),
179c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[11].d, ARMCPU, 0, 2),
180c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[12].d, ARMCPU, 0, 2),
181c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[13].d, ARMCPU, 0, 2),
182c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[14].d, ARMCPU, 0, 2),
183c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[15].d, ARMCPU, 0, 2),
184c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[16].d, ARMCPU, 0, 2),
185c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[17].d, ARMCPU, 0, 2),
186c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[18].d, ARMCPU, 0, 2),
187c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[19].d, ARMCPU, 0, 2),
188c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[20].d, ARMCPU, 0, 2),
189c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[21].d, ARMCPU, 0, 2),
190c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[22].d, ARMCPU, 0, 2),
191c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[23].d, ARMCPU, 0, 2),
192c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[24].d, ARMCPU, 0, 2),
193c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[25].d, ARMCPU, 0, 2),
194c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[26].d, ARMCPU, 0, 2),
195c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[27].d, ARMCPU, 0, 2),
196c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[28].d, ARMCPU, 0, 2),
197c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[29].d, ARMCPU, 0, 2),
198c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[30].d, ARMCPU, 0, 2),
199c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[31].d, ARMCPU, 0, 2),
200c39c2b90SRichard Henderson 
201fcf5ef2aSThomas Huth         /* The xregs array is a little awkward because element 1 (FPSCR)
202fcf5ef2aSThomas Huth          * requires a specific accessor, so we have to split it up in
203fcf5ef2aSThomas Huth          * the vmstate:
204fcf5ef2aSThomas Huth          */
205fcf5ef2aSThomas Huth         VMSTATE_UINT32(env.vfp.xregs[0], ARMCPU),
206fcf5ef2aSThomas Huth         VMSTATE_UINT32_SUB_ARRAY(env.vfp.xregs, ARMCPU, 2, 14),
207fcf5ef2aSThomas Huth         {
208fcf5ef2aSThomas Huth             .name = "fpscr",
209fcf5ef2aSThomas Huth             .version_id = 0,
210fcf5ef2aSThomas Huth             .size = sizeof(uint32_t),
211fcf5ef2aSThomas Huth             .info = &vmstate_fpscr,
212fcf5ef2aSThomas Huth             .flags = VMS_SINGLE,
213fcf5ef2aSThomas Huth             .offset = 0,
214fcf5ef2aSThomas Huth         },
215fcf5ef2aSThomas Huth         VMSTATE_END_OF_LIST()
216abf1046aSPeter Maydell     },
217abf1046aSPeter Maydell     .subsections = (const VMStateDescription * const []) {
218abf1046aSPeter Maydell         &vmstate_vfp_fpcr_fpsr,
219abf1046aSPeter Maydell         NULL
220fcf5ef2aSThomas Huth     }
221fcf5ef2aSThomas Huth };
222fcf5ef2aSThomas Huth 
iwmmxt_needed(void * opaque)223fcf5ef2aSThomas Huth static bool iwmmxt_needed(void *opaque)
224fcf5ef2aSThomas Huth {
225fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
226fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
227fcf5ef2aSThomas Huth 
228fcf5ef2aSThomas Huth     return arm_feature(env, ARM_FEATURE_IWMMXT);
229fcf5ef2aSThomas Huth }
230fcf5ef2aSThomas Huth 
231fcf5ef2aSThomas Huth static const VMStateDescription vmstate_iwmmxt = {
232fcf5ef2aSThomas Huth     .name = "cpu/iwmmxt",
233fcf5ef2aSThomas Huth     .version_id = 1,
234fcf5ef2aSThomas Huth     .minimum_version_id = 1,
235fcf5ef2aSThomas Huth     .needed = iwmmxt_needed,
236e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
237fcf5ef2aSThomas Huth         VMSTATE_UINT64_ARRAY(env.iwmmxt.regs, ARMCPU, 16),
238fcf5ef2aSThomas Huth         VMSTATE_UINT32_ARRAY(env.iwmmxt.cregs, ARMCPU, 16),
239fcf5ef2aSThomas Huth         VMSTATE_END_OF_LIST()
240fcf5ef2aSThomas Huth     }
241fcf5ef2aSThomas Huth };
242fcf5ef2aSThomas Huth 
243ef401601SRichard Henderson #ifdef TARGET_AARCH64
244ef401601SRichard Henderson /* The expression ARM_MAX_VQ - 2 is 0 for pure AArch32 build,
245ef401601SRichard Henderson  * and ARMPredicateReg is actively empty.  This triggers errors
246ef401601SRichard Henderson  * in the expansion of the VMSTATE macros.
247ef401601SRichard Henderson  */
248ef401601SRichard Henderson 
sve_needed(void * opaque)249ef401601SRichard Henderson static bool sve_needed(void *opaque)
250ef401601SRichard Henderson {
251ef401601SRichard Henderson     ARMCPU *cpu = opaque;
252ef401601SRichard Henderson 
253cd208a1cSRichard Henderson     return cpu_isar_feature(aa64_sve, cpu);
254ef401601SRichard Henderson }
255ef401601SRichard Henderson 
256ef401601SRichard Henderson /* The first two words of each Zreg is stored in VFP state.  */
257ef401601SRichard Henderson static const VMStateDescription vmstate_zreg_hi_reg = {
258ef401601SRichard Henderson     .name = "cpu/sve/zreg_hi",
259ef401601SRichard Henderson     .version_id = 1,
260ef401601SRichard Henderson     .minimum_version_id = 1,
261e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
262ef401601SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(d, ARMVectorReg, 2, ARM_MAX_VQ - 2),
263ef401601SRichard Henderson         VMSTATE_END_OF_LIST()
264ef401601SRichard Henderson     }
265ef401601SRichard Henderson };
266ef401601SRichard Henderson 
267ef401601SRichard Henderson static const VMStateDescription vmstate_preg_reg = {
268ef401601SRichard Henderson     .name = "cpu/sve/preg",
269ef401601SRichard Henderson     .version_id = 1,
270ef401601SRichard Henderson     .minimum_version_id = 1,
271e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
272ef401601SRichard Henderson         VMSTATE_UINT64_ARRAY(p, ARMPredicateReg, 2 * ARM_MAX_VQ / 8),
273ef401601SRichard Henderson         VMSTATE_END_OF_LIST()
274ef401601SRichard Henderson     }
275ef401601SRichard Henderson };
276ef401601SRichard Henderson 
277ef401601SRichard Henderson static const VMStateDescription vmstate_sve = {
278ef401601SRichard Henderson     .name = "cpu/sve",
279ef401601SRichard Henderson     .version_id = 1,
280ef401601SRichard Henderson     .minimum_version_id = 1,
281ef401601SRichard Henderson     .needed = sve_needed,
282e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
283ef401601SRichard Henderson         VMSTATE_STRUCT_ARRAY(env.vfp.zregs, ARMCPU, 32, 0,
284ef401601SRichard Henderson                              vmstate_zreg_hi_reg, ARMVectorReg),
285ef401601SRichard Henderson         VMSTATE_STRUCT_ARRAY(env.vfp.pregs, ARMCPU, 17, 0,
286ef401601SRichard Henderson                              vmstate_preg_reg, ARMPredicateReg),
287ef401601SRichard Henderson         VMSTATE_END_OF_LIST()
288ef401601SRichard Henderson     }
289ef401601SRichard Henderson };
290dc993a01SRichard Henderson 
291dc993a01SRichard Henderson static const VMStateDescription vmstate_vreg = {
292dc993a01SRichard Henderson     .name = "vreg",
293dc993a01SRichard Henderson     .version_id = 1,
294dc993a01SRichard Henderson     .minimum_version_id = 1,
295e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
296dc993a01SRichard Henderson         VMSTATE_UINT64_ARRAY(d, ARMVectorReg, ARM_MAX_VQ * 2),
297dc993a01SRichard Henderson         VMSTATE_END_OF_LIST()
298dc993a01SRichard Henderson     }
299dc993a01SRichard Henderson };
300dc993a01SRichard Henderson 
za_needed(void * opaque)301dc993a01SRichard Henderson static bool za_needed(void *opaque)
302dc993a01SRichard Henderson {
303dc993a01SRichard Henderson     ARMCPU *cpu = opaque;
304dc993a01SRichard Henderson 
305dc993a01SRichard Henderson     /*
306dc993a01SRichard Henderson      * When ZA storage is disabled, its contents are discarded.
307dc993a01SRichard Henderson      * It will be zeroed when ZA storage is re-enabled.
308dc993a01SRichard Henderson      */
309dc993a01SRichard Henderson     return FIELD_EX64(cpu->env.svcr, SVCR, ZA);
310dc993a01SRichard Henderson }
311dc993a01SRichard Henderson 
312dc993a01SRichard Henderson static const VMStateDescription vmstate_za = {
313dc993a01SRichard Henderson     .name = "cpu/sme",
314dc993a01SRichard Henderson     .version_id = 1,
315dc993a01SRichard Henderson     .minimum_version_id = 1,
316dc993a01SRichard Henderson     .needed = za_needed,
317e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
318dc993a01SRichard Henderson         VMSTATE_STRUCT_ARRAY(env.zarray, ARMCPU, ARM_MAX_VQ * 16, 0,
319dc993a01SRichard Henderson                              vmstate_vreg, ARMVectorReg),
320dc993a01SRichard Henderson         VMSTATE_END_OF_LIST()
321dc993a01SRichard Henderson     }
322dc993a01SRichard Henderson };
323ef401601SRichard Henderson #endif /* AARCH64 */
324ef401601SRichard Henderson 
serror_needed(void * opaque)325202ccb6bSDongjiu Geng static bool serror_needed(void *opaque)
326202ccb6bSDongjiu Geng {
327202ccb6bSDongjiu Geng     ARMCPU *cpu = opaque;
328202ccb6bSDongjiu Geng     CPUARMState *env = &cpu->env;
329202ccb6bSDongjiu Geng 
330202ccb6bSDongjiu Geng     return env->serror.pending != 0;
331202ccb6bSDongjiu Geng }
332202ccb6bSDongjiu Geng 
333202ccb6bSDongjiu Geng static const VMStateDescription vmstate_serror = {
334202ccb6bSDongjiu Geng     .name = "cpu/serror",
335202ccb6bSDongjiu Geng     .version_id = 1,
336202ccb6bSDongjiu Geng     .minimum_version_id = 1,
337202ccb6bSDongjiu Geng     .needed = serror_needed,
338e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
339202ccb6bSDongjiu Geng         VMSTATE_UINT8(env.serror.pending, ARMCPU),
340202ccb6bSDongjiu Geng         VMSTATE_UINT8(env.serror.has_esr, ARMCPU),
341202ccb6bSDongjiu Geng         VMSTATE_UINT64(env.serror.esr, ARMCPU),
342202ccb6bSDongjiu Geng         VMSTATE_END_OF_LIST()
343202ccb6bSDongjiu Geng     }
344202ccb6bSDongjiu Geng };
345202ccb6bSDongjiu Geng 
irq_line_state_needed(void * opaque)346ed89f078SPeter Maydell static bool irq_line_state_needed(void *opaque)
347ed89f078SPeter Maydell {
348ed89f078SPeter Maydell     return true;
349ed89f078SPeter Maydell }
350ed89f078SPeter Maydell 
351ed89f078SPeter Maydell static const VMStateDescription vmstate_irq_line_state = {
352ed89f078SPeter Maydell     .name = "cpu/irq-line-state",
353ed89f078SPeter Maydell     .version_id = 1,
354ed89f078SPeter Maydell     .minimum_version_id = 1,
355ed89f078SPeter Maydell     .needed = irq_line_state_needed,
356e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
357ed89f078SPeter Maydell         VMSTATE_UINT32(env.irq_line_state, ARMCPU),
358ed89f078SPeter Maydell         VMSTATE_END_OF_LIST()
359ed89f078SPeter Maydell     }
360ed89f078SPeter Maydell };
361ed89f078SPeter Maydell 
wfxt_timer_needed(void * opaque)362a96edb68SPeter Maydell static bool wfxt_timer_needed(void *opaque)
363a96edb68SPeter Maydell {
364a96edb68SPeter Maydell     ARMCPU *cpu = opaque;
365a96edb68SPeter Maydell 
366a96edb68SPeter Maydell     /* We'll only have the timer object if FEAT_WFxT is implemented */
367a96edb68SPeter Maydell     return cpu->wfxt_timer;
368a96edb68SPeter Maydell }
369a96edb68SPeter Maydell 
370a96edb68SPeter Maydell static const VMStateDescription vmstate_wfxt_timer = {
371a96edb68SPeter Maydell     .name = "cpu/wfxt-timer",
372a96edb68SPeter Maydell     .version_id = 1,
373a96edb68SPeter Maydell     .minimum_version_id = 1,
374a96edb68SPeter Maydell     .needed = wfxt_timer_needed,
375a96edb68SPeter Maydell     .fields = (const VMStateField[]) {
376a96edb68SPeter Maydell         VMSTATE_TIMER_PTR(wfxt_timer, ARMCPU),
377a96edb68SPeter Maydell         VMSTATE_END_OF_LIST()
378a96edb68SPeter Maydell     }
379a96edb68SPeter Maydell };
380a96edb68SPeter Maydell 
m_needed(void * opaque)381fcf5ef2aSThomas Huth static bool m_needed(void *opaque)
382fcf5ef2aSThomas Huth {
383fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
384fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
385fcf5ef2aSThomas Huth 
386fcf5ef2aSThomas Huth     return arm_feature(env, ARM_FEATURE_M);
387fcf5ef2aSThomas Huth }
388fcf5ef2aSThomas Huth 
389e6ae5981SPeter Maydell static const VMStateDescription vmstate_m_faultmask_primask = {
390e6ae5981SPeter Maydell     .name = "cpu/m/faultmask-primask",
391e6ae5981SPeter Maydell     .version_id = 1,
392e6ae5981SPeter Maydell     .minimum_version_id = 1,
3937b69454aSPeter Maydell     .needed = m_needed,
394e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
39542a6686bSPeter Maydell         VMSTATE_UINT32(env.v7m.faultmask[M_REG_NS], ARMCPU),
3966d804834SPeter Maydell         VMSTATE_UINT32(env.v7m.primask[M_REG_NS], ARMCPU),
397e6ae5981SPeter Maydell         VMSTATE_END_OF_LIST()
398e6ae5981SPeter Maydell     }
399e6ae5981SPeter Maydell };
400e6ae5981SPeter Maydell 
40143bbce7fSPeter Maydell /* CSSELR is in a subsection because we didn't implement it previously.
40243bbce7fSPeter Maydell  * Migration from an old implementation will leave it at zero, which
40343bbce7fSPeter Maydell  * is OK since the only CPUs in the old implementation make the
40443bbce7fSPeter Maydell  * register RAZ/WI.
40543bbce7fSPeter Maydell  * Since there was no version of QEMU which implemented the CSSELR for
40643bbce7fSPeter Maydell  * just non-secure, we transfer both banks here rather than putting
40743bbce7fSPeter Maydell  * the secure banked version in the m-security subsection.
40843bbce7fSPeter Maydell  */
csselr_vmstate_validate(void * opaque,int version_id)40943bbce7fSPeter Maydell static bool csselr_vmstate_validate(void *opaque, int version_id)
41043bbce7fSPeter Maydell {
41143bbce7fSPeter Maydell     ARMCPU *cpu = opaque;
41243bbce7fSPeter Maydell 
41343bbce7fSPeter Maydell     return cpu->env.v7m.csselr[M_REG_NS] <= R_V7M_CSSELR_INDEX_MASK
41443bbce7fSPeter Maydell         && cpu->env.v7m.csselr[M_REG_S] <= R_V7M_CSSELR_INDEX_MASK;
41543bbce7fSPeter Maydell }
41643bbce7fSPeter Maydell 
m_csselr_needed(void * opaque)41743bbce7fSPeter Maydell static bool m_csselr_needed(void *opaque)
41843bbce7fSPeter Maydell {
41943bbce7fSPeter Maydell     ARMCPU *cpu = opaque;
42043bbce7fSPeter Maydell 
42143bbce7fSPeter Maydell     return !arm_v7m_csselr_razwi(cpu);
42243bbce7fSPeter Maydell }
42343bbce7fSPeter Maydell 
42443bbce7fSPeter Maydell static const VMStateDescription vmstate_m_csselr = {
42543bbce7fSPeter Maydell     .name = "cpu/m/csselr",
42643bbce7fSPeter Maydell     .version_id = 1,
42743bbce7fSPeter Maydell     .minimum_version_id = 1,
42843bbce7fSPeter Maydell     .needed = m_csselr_needed,
429e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
43043bbce7fSPeter Maydell         VMSTATE_UINT32_ARRAY(env.v7m.csselr, ARMCPU, M_REG_NUM_BANKS),
43143bbce7fSPeter Maydell         VMSTATE_VALIDATE("CSSELR is valid", csselr_vmstate_validate),
43243bbce7fSPeter Maydell         VMSTATE_END_OF_LIST()
43343bbce7fSPeter Maydell     }
43443bbce7fSPeter Maydell };
43543bbce7fSPeter Maydell 
43624ac0fb1SPeter Maydell static const VMStateDescription vmstate_m_scr = {
43724ac0fb1SPeter Maydell     .name = "cpu/m/scr",
43824ac0fb1SPeter Maydell     .version_id = 1,
43924ac0fb1SPeter Maydell     .minimum_version_id = 1,
4407b69454aSPeter Maydell     .needed = m_needed,
441e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
44224ac0fb1SPeter Maydell         VMSTATE_UINT32(env.v7m.scr[M_REG_NS], ARMCPU),
44324ac0fb1SPeter Maydell         VMSTATE_END_OF_LIST()
44424ac0fb1SPeter Maydell     }
44524ac0fb1SPeter Maydell };
44624ac0fb1SPeter Maydell 
447e1e7cbc9SPeter Maydell static const VMStateDescription vmstate_m_other_sp = {
448e1e7cbc9SPeter Maydell     .name = "cpu/m/other-sp",
449e1e7cbc9SPeter Maydell     .version_id = 1,
450e1e7cbc9SPeter Maydell     .minimum_version_id = 1,
4517b69454aSPeter Maydell     .needed = m_needed,
452e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
453e1e7cbc9SPeter Maydell         VMSTATE_UINT32(env.v7m.other_sp, ARMCPU),
454e1e7cbc9SPeter Maydell         VMSTATE_END_OF_LIST()
455e1e7cbc9SPeter Maydell     }
456e1e7cbc9SPeter Maydell };
457e1e7cbc9SPeter Maydell 
m_v8m_needed(void * opaque)45857bb3156SPeter Maydell static bool m_v8m_needed(void *opaque)
45957bb3156SPeter Maydell {
46057bb3156SPeter Maydell     ARMCPU *cpu = opaque;
46157bb3156SPeter Maydell     CPUARMState *env = &cpu->env;
46257bb3156SPeter Maydell 
46357bb3156SPeter Maydell     return arm_feature(env, ARM_FEATURE_M) && arm_feature(env, ARM_FEATURE_V8);
46457bb3156SPeter Maydell }
46557bb3156SPeter Maydell 
46657bb3156SPeter Maydell static const VMStateDescription vmstate_m_v8m = {
46757bb3156SPeter Maydell     .name = "cpu/m/v8m",
46857bb3156SPeter Maydell     .version_id = 1,
46957bb3156SPeter Maydell     .minimum_version_id = 1,
47057bb3156SPeter Maydell     .needed = m_v8m_needed,
471e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
47257bb3156SPeter Maydell         VMSTATE_UINT32_ARRAY(env.v7m.msplim, ARMCPU, M_REG_NUM_BANKS),
47357bb3156SPeter Maydell         VMSTATE_UINT32_ARRAY(env.v7m.psplim, ARMCPU, M_REG_NUM_BANKS),
47457bb3156SPeter Maydell         VMSTATE_END_OF_LIST()
47557bb3156SPeter Maydell     }
47657bb3156SPeter Maydell };
47757bb3156SPeter Maydell 
478d33abe82SPeter Maydell static const VMStateDescription vmstate_m_fp = {
479d33abe82SPeter Maydell     .name = "cpu/m/fp",
480d33abe82SPeter Maydell     .version_id = 1,
481d33abe82SPeter Maydell     .minimum_version_id = 1,
482d33abe82SPeter Maydell     .needed = vfp_needed,
483e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
484d33abe82SPeter Maydell         VMSTATE_UINT32_ARRAY(env.v7m.fpcar, ARMCPU, M_REG_NUM_BANKS),
485d33abe82SPeter Maydell         VMSTATE_UINT32_ARRAY(env.v7m.fpccr, ARMCPU, M_REG_NUM_BANKS),
486d33abe82SPeter Maydell         VMSTATE_UINT32_ARRAY(env.v7m.fpdscr, ARMCPU, M_REG_NUM_BANKS),
487d33abe82SPeter Maydell         VMSTATE_UINT32_ARRAY(env.v7m.cpacr, ARMCPU, M_REG_NUM_BANKS),
488d33abe82SPeter Maydell         VMSTATE_UINT32(env.v7m.nsacr, ARMCPU),
489d33abe82SPeter Maydell         VMSTATE_END_OF_LIST()
490d33abe82SPeter Maydell     }
491d33abe82SPeter Maydell };
492d33abe82SPeter Maydell 
mve_needed(void * opaque)4937c3d47daSPeter Maydell static bool mve_needed(void *opaque)
4947c3d47daSPeter Maydell {
4957c3d47daSPeter Maydell     ARMCPU *cpu = opaque;
4967c3d47daSPeter Maydell 
4977c3d47daSPeter Maydell     return cpu_isar_feature(aa32_mve, cpu);
4987c3d47daSPeter Maydell }
4997c3d47daSPeter Maydell 
5007c3d47daSPeter Maydell static const VMStateDescription vmstate_m_mve = {
5017c3d47daSPeter Maydell     .name = "cpu/m/mve",
5027c3d47daSPeter Maydell     .version_id = 1,
5037c3d47daSPeter Maydell     .minimum_version_id = 1,
5047c3d47daSPeter Maydell     .needed = mve_needed,
505e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
5067c3d47daSPeter Maydell         VMSTATE_UINT32(env.v7m.vpr, ARMCPU),
507b26b5629SPeter Maydell         VMSTATE_UINT32(env.v7m.ltpsize, ARMCPU),
5087c3d47daSPeter Maydell         VMSTATE_END_OF_LIST()
5097c3d47daSPeter Maydell     },
5107c3d47daSPeter Maydell };
5117c3d47daSPeter Maydell 
512fcf5ef2aSThomas Huth static const VMStateDescription vmstate_m = {
513fcf5ef2aSThomas Huth     .name = "cpu/m",
51429c483a5SMichael Davidsaver     .version_id = 4,
51529c483a5SMichael Davidsaver     .minimum_version_id = 4,
516fcf5ef2aSThomas Huth     .needed = m_needed,
517e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
51845db7ba6SPeter Maydell         VMSTATE_UINT32(env.v7m.vecbase[M_REG_NS], ARMCPU),
519acf94941SPeter Maydell         VMSTATE_UINT32(env.v7m.basepri[M_REG_NS], ARMCPU),
5208bfc26eaSPeter Maydell         VMSTATE_UINT32(env.v7m.control[M_REG_NS], ARMCPU),
5219d40cd8aSPeter Maydell         VMSTATE_UINT32(env.v7m.ccr[M_REG_NS], ARMCPU),
522334e8dadSPeter Maydell         VMSTATE_UINT32(env.v7m.cfsr[M_REG_NS], ARMCPU),
5232c4da50dSPeter Maydell         VMSTATE_UINT32(env.v7m.hfsr, ARMCPU),
5242c4da50dSPeter Maydell         VMSTATE_UINT32(env.v7m.dfsr, ARMCPU),
525c51a5cfcSPeter Maydell         VMSTATE_UINT32(env.v7m.mmfar[M_REG_NS], ARMCPU),
5262c4da50dSPeter Maydell         VMSTATE_UINT32(env.v7m.bfar, ARMCPU),
527ecf5e8eaSPeter Maydell         VMSTATE_UINT32(env.v7m.mpu_ctrl[M_REG_NS], ARMCPU),
528fcf5ef2aSThomas Huth         VMSTATE_INT32(env.v7m.exception, ARMCPU),
529fcf5ef2aSThomas Huth         VMSTATE_END_OF_LIST()
530e6ae5981SPeter Maydell     },
531e3fe0bc6SRichard Henderson     .subsections = (const VMStateDescription * const []) {
532e6ae5981SPeter Maydell         &vmstate_m_faultmask_primask,
53343bbce7fSPeter Maydell         &vmstate_m_csselr,
53424ac0fb1SPeter Maydell         &vmstate_m_scr,
535e1e7cbc9SPeter Maydell         &vmstate_m_other_sp,
53657bb3156SPeter Maydell         &vmstate_m_v8m,
537d33abe82SPeter Maydell         &vmstate_m_fp,
5387c3d47daSPeter Maydell         &vmstate_m_mve,
539e6ae5981SPeter Maydell         NULL
540fcf5ef2aSThomas Huth     }
541fcf5ef2aSThomas Huth };
542fcf5ef2aSThomas Huth 
thumb2ee_needed(void * opaque)543fcf5ef2aSThomas Huth static bool thumb2ee_needed(void *opaque)
544fcf5ef2aSThomas Huth {
545fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
546fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
547fcf5ef2aSThomas Huth 
548fcf5ef2aSThomas Huth     return arm_feature(env, ARM_FEATURE_THUMB2EE);
549fcf5ef2aSThomas Huth }
550fcf5ef2aSThomas Huth 
551fcf5ef2aSThomas Huth static const VMStateDescription vmstate_thumb2ee = {
552fcf5ef2aSThomas Huth     .name = "cpu/thumb2ee",
553fcf5ef2aSThomas Huth     .version_id = 1,
554fcf5ef2aSThomas Huth     .minimum_version_id = 1,
555fcf5ef2aSThomas Huth     .needed = thumb2ee_needed,
556e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
557fcf5ef2aSThomas Huth         VMSTATE_UINT32(env.teecr, ARMCPU),
558fcf5ef2aSThomas Huth         VMSTATE_UINT32(env.teehbr, ARMCPU),
559fcf5ef2aSThomas Huth         VMSTATE_END_OF_LIST()
560fcf5ef2aSThomas Huth     }
561fcf5ef2aSThomas Huth };
562fcf5ef2aSThomas Huth 
pmsav7_needed(void * opaque)563fcf5ef2aSThomas Huth static bool pmsav7_needed(void *opaque)
564fcf5ef2aSThomas Huth {
565fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
566fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
567fcf5ef2aSThomas Huth 
568452a0955SPeter Maydell     return arm_feature(env, ARM_FEATURE_PMSA) &&
5690e1a46bbSPeter Maydell            arm_feature(env, ARM_FEATURE_V7) &&
5700e1a46bbSPeter Maydell            !arm_feature(env, ARM_FEATURE_V8);
571fcf5ef2aSThomas Huth }
572fcf5ef2aSThomas Huth 
pmsav7_rgnr_vmstate_validate(void * opaque,int version_id)573fcf5ef2aSThomas Huth static bool pmsav7_rgnr_vmstate_validate(void *opaque, int version_id)
574fcf5ef2aSThomas Huth {
575fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
576fcf5ef2aSThomas Huth 
5771bc04a88SPeter Maydell     return cpu->env.pmsav7.rnr[M_REG_NS] < cpu->pmsav7_dregion;
578fcf5ef2aSThomas Huth }
579fcf5ef2aSThomas Huth 
580fcf5ef2aSThomas Huth static const VMStateDescription vmstate_pmsav7 = {
581fcf5ef2aSThomas Huth     .name = "cpu/pmsav7",
582fcf5ef2aSThomas Huth     .version_id = 1,
583fcf5ef2aSThomas Huth     .minimum_version_id = 1,
584fcf5ef2aSThomas Huth     .needed = pmsav7_needed,
585e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
586fcf5ef2aSThomas Huth         VMSTATE_VARRAY_UINT32(env.pmsav7.drbar, ARMCPU, pmsav7_dregion, 0,
587fcf5ef2aSThomas Huth                               vmstate_info_uint32, uint32_t),
588fcf5ef2aSThomas Huth         VMSTATE_VARRAY_UINT32(env.pmsav7.drsr, ARMCPU, pmsav7_dregion, 0,
589fcf5ef2aSThomas Huth                               vmstate_info_uint32, uint32_t),
590fcf5ef2aSThomas Huth         VMSTATE_VARRAY_UINT32(env.pmsav7.dracr, ARMCPU, pmsav7_dregion, 0,
591fcf5ef2aSThomas Huth                               vmstate_info_uint32, uint32_t),
592fcf5ef2aSThomas Huth         VMSTATE_VALIDATE("rgnr is valid", pmsav7_rgnr_vmstate_validate),
593fcf5ef2aSThomas Huth         VMSTATE_END_OF_LIST()
594fcf5ef2aSThomas Huth     }
595fcf5ef2aSThomas Huth };
596fcf5ef2aSThomas Huth 
pmsav7_rnr_needed(void * opaque)597f1a46940SPeter Maydell static bool pmsav7_rnr_needed(void *opaque)
598f1a46940SPeter Maydell {
599f1a46940SPeter Maydell     ARMCPU *cpu = opaque;
600f1a46940SPeter Maydell     CPUARMState *env = &cpu->env;
601f1a46940SPeter Maydell 
602f1a46940SPeter Maydell     /* For R profile cores pmsav7.rnr is migrated via the cpreg
603f1a46940SPeter Maydell      * "RGNR" definition in helper.h. For M profile we have to
604f1a46940SPeter Maydell      * migrate it separately.
605f1a46940SPeter Maydell      */
606f1a46940SPeter Maydell     return arm_feature(env, ARM_FEATURE_M);
607f1a46940SPeter Maydell }
608f1a46940SPeter Maydell 
609f1a46940SPeter Maydell static const VMStateDescription vmstate_pmsav7_rnr = {
610f1a46940SPeter Maydell     .name = "cpu/pmsav7-rnr",
611f1a46940SPeter Maydell     .version_id = 1,
612f1a46940SPeter Maydell     .minimum_version_id = 1,
613f1a46940SPeter Maydell     .needed = pmsav7_rnr_needed,
614e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
6151bc04a88SPeter Maydell         VMSTATE_UINT32(env.pmsav7.rnr[M_REG_NS], ARMCPU),
616f1a46940SPeter Maydell         VMSTATE_END_OF_LIST()
617f1a46940SPeter Maydell     }
618f1a46940SPeter Maydell };
619f1a46940SPeter Maydell 
pmsav8_needed(void * opaque)6200e1a46bbSPeter Maydell static bool pmsav8_needed(void *opaque)
6210e1a46bbSPeter Maydell {
6220e1a46bbSPeter Maydell     ARMCPU *cpu = opaque;
6230e1a46bbSPeter Maydell     CPUARMState *env = &cpu->env;
6240e1a46bbSPeter Maydell 
6250e1a46bbSPeter Maydell     return arm_feature(env, ARM_FEATURE_PMSA) &&
6260e1a46bbSPeter Maydell         arm_feature(env, ARM_FEATURE_V8);
6270e1a46bbSPeter Maydell }
6280e1a46bbSPeter Maydell 
pmsav8r_needed(void * opaque)629761c4642STobias Röhmel static bool pmsav8r_needed(void *opaque)
630761c4642STobias Röhmel {
631761c4642STobias Röhmel     ARMCPU *cpu = opaque;
632761c4642STobias Röhmel     CPUARMState *env = &cpu->env;
633761c4642STobias Röhmel 
634761c4642STobias Röhmel     return arm_feature(env, ARM_FEATURE_PMSA) &&
635761c4642STobias Röhmel         arm_feature(env, ARM_FEATURE_V8) &&
636761c4642STobias Röhmel         !arm_feature(env, ARM_FEATURE_M);
637761c4642STobias Röhmel }
638761c4642STobias Röhmel 
639761c4642STobias Röhmel static const VMStateDescription vmstate_pmsav8r = {
640761c4642STobias Röhmel     .name = "cpu/pmsav8/pmsav8r",
641761c4642STobias Röhmel     .version_id = 1,
642761c4642STobias Röhmel     .minimum_version_id = 1,
643761c4642STobias Röhmel     .needed = pmsav8r_needed,
644e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
645761c4642STobias Röhmel         VMSTATE_VARRAY_UINT32(env.pmsav8.hprbar, ARMCPU,
646761c4642STobias Röhmel                         pmsav8r_hdregion, 0, vmstate_info_uint32, uint32_t),
647761c4642STobias Röhmel         VMSTATE_VARRAY_UINT32(env.pmsav8.hprlar, ARMCPU,
648761c4642STobias Röhmel                         pmsav8r_hdregion, 0, vmstate_info_uint32, uint32_t),
649761c4642STobias Röhmel         VMSTATE_END_OF_LIST()
650761c4642STobias Röhmel     },
651761c4642STobias Röhmel };
652761c4642STobias Röhmel 
6530e1a46bbSPeter Maydell static const VMStateDescription vmstate_pmsav8 = {
6540e1a46bbSPeter Maydell     .name = "cpu/pmsav8",
6550e1a46bbSPeter Maydell     .version_id = 1,
6560e1a46bbSPeter Maydell     .minimum_version_id = 1,
6570e1a46bbSPeter Maydell     .needed = pmsav8_needed,
658e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
65962c58ee0SPeter Maydell         VMSTATE_VARRAY_UINT32(env.pmsav8.rbar[M_REG_NS], ARMCPU, pmsav7_dregion,
66062c58ee0SPeter Maydell                               0, vmstate_info_uint32, uint32_t),
66162c58ee0SPeter Maydell         VMSTATE_VARRAY_UINT32(env.pmsav8.rlar[M_REG_NS], ARMCPU, pmsav7_dregion,
66262c58ee0SPeter Maydell                               0, vmstate_info_uint32, uint32_t),
6634125e6feSPeter Maydell         VMSTATE_UINT32(env.pmsav8.mair0[M_REG_NS], ARMCPU),
6644125e6feSPeter Maydell         VMSTATE_UINT32(env.pmsav8.mair1[M_REG_NS], ARMCPU),
6650e1a46bbSPeter Maydell         VMSTATE_END_OF_LIST()
666761c4642STobias Röhmel     },
667e3fe0bc6SRichard Henderson     .subsections = (const VMStateDescription * const []) {
668761c4642STobias Röhmel         &vmstate_pmsav8r,
669761c4642STobias Röhmel         NULL
6700e1a46bbSPeter Maydell     }
6710e1a46bbSPeter Maydell };
6720e1a46bbSPeter Maydell 
s_rnr_vmstate_validate(void * opaque,int version_id)6731bc04a88SPeter Maydell static bool s_rnr_vmstate_validate(void *opaque, int version_id)
6741bc04a88SPeter Maydell {
6751bc04a88SPeter Maydell     ARMCPU *cpu = opaque;
6761bc04a88SPeter Maydell 
6771bc04a88SPeter Maydell     return cpu->env.pmsav7.rnr[M_REG_S] < cpu->pmsav7_dregion;
6781bc04a88SPeter Maydell }
6791bc04a88SPeter Maydell 
sau_rnr_vmstate_validate(void * opaque,int version_id)6809901c576SPeter Maydell static bool sau_rnr_vmstate_validate(void *opaque, int version_id)
6819901c576SPeter Maydell {
6829901c576SPeter Maydell     ARMCPU *cpu = opaque;
6839901c576SPeter Maydell 
6849901c576SPeter Maydell     return cpu->env.sau.rnr < cpu->sau_sregion;
6859901c576SPeter Maydell }
6869901c576SPeter Maydell 
m_security_needed(void * opaque)6871e577cc7SPeter Maydell static bool m_security_needed(void *opaque)
6881e577cc7SPeter Maydell {
6891e577cc7SPeter Maydell     ARMCPU *cpu = opaque;
6901e577cc7SPeter Maydell     CPUARMState *env = &cpu->env;
6911e577cc7SPeter Maydell 
6921e577cc7SPeter Maydell     return arm_feature(env, ARM_FEATURE_M_SECURITY);
6931e577cc7SPeter Maydell }
6941e577cc7SPeter Maydell 
6951e577cc7SPeter Maydell static const VMStateDescription vmstate_m_security = {
6961e577cc7SPeter Maydell     .name = "cpu/m-security",
6971e577cc7SPeter Maydell     .version_id = 1,
6981e577cc7SPeter Maydell     .minimum_version_id = 1,
6991e577cc7SPeter Maydell     .needed = m_security_needed,
700e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
7011e577cc7SPeter Maydell         VMSTATE_UINT32(env.v7m.secure, ARMCPU),
702fb602cb7SPeter Maydell         VMSTATE_UINT32(env.v7m.other_ss_msp, ARMCPU),
703fb602cb7SPeter Maydell         VMSTATE_UINT32(env.v7m.other_ss_psp, ARMCPU),
704acf94941SPeter Maydell         VMSTATE_UINT32(env.v7m.basepri[M_REG_S], ARMCPU),
7056d804834SPeter Maydell         VMSTATE_UINT32(env.v7m.primask[M_REG_S], ARMCPU),
70642a6686bSPeter Maydell         VMSTATE_UINT32(env.v7m.faultmask[M_REG_S], ARMCPU),
7078bfc26eaSPeter Maydell         VMSTATE_UINT32(env.v7m.control[M_REG_S], ARMCPU),
70845db7ba6SPeter Maydell         VMSTATE_UINT32(env.v7m.vecbase[M_REG_S], ARMCPU),
7094125e6feSPeter Maydell         VMSTATE_UINT32(env.pmsav8.mair0[M_REG_S], ARMCPU),
7104125e6feSPeter Maydell         VMSTATE_UINT32(env.pmsav8.mair1[M_REG_S], ARMCPU),
71162c58ee0SPeter Maydell         VMSTATE_VARRAY_UINT32(env.pmsav8.rbar[M_REG_S], ARMCPU, pmsav7_dregion,
71262c58ee0SPeter Maydell                               0, vmstate_info_uint32, uint32_t),
71362c58ee0SPeter Maydell         VMSTATE_VARRAY_UINT32(env.pmsav8.rlar[M_REG_S], ARMCPU, pmsav7_dregion,
71462c58ee0SPeter Maydell                               0, vmstate_info_uint32, uint32_t),
7151bc04a88SPeter Maydell         VMSTATE_UINT32(env.pmsav7.rnr[M_REG_S], ARMCPU),
7161bc04a88SPeter Maydell         VMSTATE_VALIDATE("secure MPU_RNR is valid", s_rnr_vmstate_validate),
717ecf5e8eaSPeter Maydell         VMSTATE_UINT32(env.v7m.mpu_ctrl[M_REG_S], ARMCPU),
7189d40cd8aSPeter Maydell         VMSTATE_UINT32(env.v7m.ccr[M_REG_S], ARMCPU),
719c51a5cfcSPeter Maydell         VMSTATE_UINT32(env.v7m.mmfar[M_REG_S], ARMCPU),
720334e8dadSPeter Maydell         VMSTATE_UINT32(env.v7m.cfsr[M_REG_S], ARMCPU),
721bed079daSPeter Maydell         VMSTATE_UINT32(env.v7m.sfsr, ARMCPU),
722bed079daSPeter Maydell         VMSTATE_UINT32(env.v7m.sfar, ARMCPU),
7239901c576SPeter Maydell         VMSTATE_VARRAY_UINT32(env.sau.rbar, ARMCPU, sau_sregion, 0,
7249901c576SPeter Maydell                               vmstate_info_uint32, uint32_t),
7259901c576SPeter Maydell         VMSTATE_VARRAY_UINT32(env.sau.rlar, ARMCPU, sau_sregion, 0,
7269901c576SPeter Maydell                               vmstate_info_uint32, uint32_t),
7279901c576SPeter Maydell         VMSTATE_UINT32(env.sau.rnr, ARMCPU),
7289901c576SPeter Maydell         VMSTATE_VALIDATE("SAU_RNR is valid", sau_rnr_vmstate_validate),
7299901c576SPeter Maydell         VMSTATE_UINT32(env.sau.ctrl, ARMCPU),
73024ac0fb1SPeter Maydell         VMSTATE_UINT32(env.v7m.scr[M_REG_S], ARMCPU),
73147825770SPeter Maydell         /* AIRCR is not secure-only, but our implementation is R/O if the
73247825770SPeter Maydell          * security extension is unimplemented, so we migrate it here.
73347825770SPeter Maydell          */
73447825770SPeter Maydell         VMSTATE_UINT32(env.v7m.aircr, ARMCPU),
7351e577cc7SPeter Maydell         VMSTATE_END_OF_LIST()
7361e577cc7SPeter Maydell     }
7371e577cc7SPeter Maydell };
7381e577cc7SPeter Maydell 
get_cpsr(QEMUFile * f,void * opaque,size_t size,const VMStateField * field)7392c21ee76SJianjun Duan static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
74003fee66fSMarc-André Lureau                     const VMStateField *field)
741fcf5ef2aSThomas Huth {
742fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
743fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
744fcf5ef2aSThomas Huth     uint32_t val = qemu_get_be32(f);
745fcf5ef2aSThomas Huth 
746e6ae5981SPeter Maydell     if (arm_feature(env, ARM_FEATURE_M)) {
747eeade001SPeter Maydell         if (val & XPSR_EXCP) {
748eeade001SPeter Maydell             /* This is a CPSR format value from an older QEMU. (We can tell
749eeade001SPeter Maydell              * because values transferred in XPSR format always have zero
750eeade001SPeter Maydell              * for the EXCP field, and CPSR format will always have bit 4
751eeade001SPeter Maydell              * set in CPSR_M.) Rearrange it into XPSR format. The significant
752eeade001SPeter Maydell              * differences are that the T bit is not in the same place, the
753eeade001SPeter Maydell              * primask/faultmask info may be in the CPSR I and F bits, and
754eeade001SPeter Maydell              * we do not want the mode bits.
7556d804834SPeter Maydell              * We know that this cleanup happened before v8M, so there
7566d804834SPeter Maydell              * is no complication with banked primask/faultmask.
757eeade001SPeter Maydell              */
758eeade001SPeter Maydell             uint32_t newval = val;
759eeade001SPeter Maydell 
7606d804834SPeter Maydell             assert(!arm_feature(env, ARM_FEATURE_M_SECURITY));
7616d804834SPeter Maydell 
762eeade001SPeter Maydell             newval &= (CPSR_NZCV | CPSR_Q | CPSR_IT | CPSR_GE);
763eeade001SPeter Maydell             if (val & CPSR_T) {
764eeade001SPeter Maydell                 newval |= XPSR_T;
765eeade001SPeter Maydell             }
766e6ae5981SPeter Maydell             /* If the I or F bits are set then this is a migration from
767e6ae5981SPeter Maydell              * an old QEMU which still stored the M profile FAULTMASK
768eeade001SPeter Maydell              * and PRIMASK in env->daif. For a new QEMU, the data is
769eeade001SPeter Maydell              * transferred using the vmstate_m_faultmask_primask subsection.
770e6ae5981SPeter Maydell              */
771e6ae5981SPeter Maydell             if (val & CPSR_F) {
77242a6686bSPeter Maydell                 env->v7m.faultmask[M_REG_NS] = 1;
773e6ae5981SPeter Maydell             }
774e6ae5981SPeter Maydell             if (val & CPSR_I) {
7756d804834SPeter Maydell                 env->v7m.primask[M_REG_NS] = 1;
776e6ae5981SPeter Maydell             }
777eeade001SPeter Maydell             val = newval;
778eeade001SPeter Maydell         }
779eeade001SPeter Maydell         /* Ignore the low bits, they are handled by vmstate_m. */
780eeade001SPeter Maydell         xpsr_write(env, val, ~XPSR_EXCP);
781eeade001SPeter Maydell         return 0;
782e6ae5981SPeter Maydell     }
783e6ae5981SPeter Maydell 
784fcf5ef2aSThomas Huth     env->aarch64 = ((val & PSTATE_nRW) == 0);
785fcf5ef2aSThomas Huth 
786fcf5ef2aSThomas Huth     if (is_a64(env)) {
787fcf5ef2aSThomas Huth         pstate_write(env, val);
788fcf5ef2aSThomas Huth         return 0;
789fcf5ef2aSThomas Huth     }
790fcf5ef2aSThomas Huth 
791fcf5ef2aSThomas Huth     cpsr_write(env, val, 0xffffffff, CPSRWriteRaw);
792fcf5ef2aSThomas Huth     return 0;
793fcf5ef2aSThomas Huth }
794fcf5ef2aSThomas Huth 
put_cpsr(QEMUFile * f,void * opaque,size_t size,const VMStateField * field,JSONWriter * vmdesc)7952c21ee76SJianjun Duan static int put_cpsr(QEMUFile *f, void *opaque, size_t size,
7963ddba9a9SMarkus Armbruster                     const VMStateField *field, JSONWriter *vmdesc)
797fcf5ef2aSThomas Huth {
798fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
799fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
800fcf5ef2aSThomas Huth     uint32_t val;
801fcf5ef2aSThomas Huth 
802eeade001SPeter Maydell     if (arm_feature(env, ARM_FEATURE_M)) {
803eeade001SPeter Maydell         /* The low 9 bits are v7m.exception, which is handled by vmstate_m. */
804eeade001SPeter Maydell         val = xpsr_read(env) & ~XPSR_EXCP;
805eeade001SPeter Maydell     } else if (is_a64(env)) {
806fcf5ef2aSThomas Huth         val = pstate_read(env);
807fcf5ef2aSThomas Huth     } else {
808fcf5ef2aSThomas Huth         val = cpsr_read(env);
809fcf5ef2aSThomas Huth     }
810fcf5ef2aSThomas Huth 
811fcf5ef2aSThomas Huth     qemu_put_be32(f, val);
8122c21ee76SJianjun Duan     return 0;
813fcf5ef2aSThomas Huth }
814fcf5ef2aSThomas Huth 
815fcf5ef2aSThomas Huth static const VMStateInfo vmstate_cpsr = {
816fcf5ef2aSThomas Huth     .name = "cpsr",
817fcf5ef2aSThomas Huth     .get = get_cpsr,
818fcf5ef2aSThomas Huth     .put = put_cpsr,
819fcf5ef2aSThomas Huth };
820fcf5ef2aSThomas Huth 
get_power(QEMUFile * f,void * opaque,size_t size,const VMStateField * field)821062ba099SAlex Bennée static int get_power(QEMUFile *f, void *opaque, size_t size,
82203fee66fSMarc-André Lureau                     const VMStateField *field)
823062ba099SAlex Bennée {
824062ba099SAlex Bennée     ARMCPU *cpu = opaque;
825062ba099SAlex Bennée     bool powered_off = qemu_get_byte(f);
826062ba099SAlex Bennée     cpu->power_state = powered_off ? PSCI_OFF : PSCI_ON;
827062ba099SAlex Bennée     return 0;
828062ba099SAlex Bennée }
829062ba099SAlex Bennée 
put_power(QEMUFile * f,void * opaque,size_t size,const VMStateField * field,JSONWriter * vmdesc)830062ba099SAlex Bennée static int put_power(QEMUFile *f, void *opaque, size_t size,
8313ddba9a9SMarkus Armbruster                     const VMStateField *field, JSONWriter *vmdesc)
832062ba099SAlex Bennée {
833062ba099SAlex Bennée     ARMCPU *cpu = opaque;
834062ba099SAlex Bennée 
835062ba099SAlex Bennée     /* Migration should never happen while we transition power states */
836062ba099SAlex Bennée 
837062ba099SAlex Bennée     if (cpu->power_state == PSCI_ON ||
838062ba099SAlex Bennée         cpu->power_state == PSCI_OFF) {
839062ba099SAlex Bennée         bool powered_off = (cpu->power_state == PSCI_OFF) ? true : false;
840062ba099SAlex Bennée         qemu_put_byte(f, powered_off);
841062ba099SAlex Bennée         return 0;
842062ba099SAlex Bennée     } else {
843062ba099SAlex Bennée         return 1;
844062ba099SAlex Bennée     }
845062ba099SAlex Bennée }
846062ba099SAlex Bennée 
847062ba099SAlex Bennée static const VMStateInfo vmstate_powered_off = {
848062ba099SAlex Bennée     .name = "powered_off",
849062ba099SAlex Bennée     .get = get_power,
850062ba099SAlex Bennée     .put = put_power,
851062ba099SAlex Bennée };
852062ba099SAlex Bennée 
cpu_pre_save(void * opaque)85344b1ff31SDr. David Alan Gilbert static int cpu_pre_save(void *opaque)
854fcf5ef2aSThomas Huth {
855fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
856fcf5ef2aSThomas Huth 
857980ebe87SAaron Lindsay     if (!kvm_enabled()) {
858980ebe87SAaron Lindsay         pmu_op_start(&cpu->env);
859980ebe87SAaron Lindsay     }
860980ebe87SAaron Lindsay 
861fcf5ef2aSThomas Huth     if (kvm_enabled()) {
862fcf5ef2aSThomas Huth         if (!write_kvmstate_to_list(cpu)) {
863fcf5ef2aSThomas Huth             /* This should never fail */
864d385a605SRichard Henderson             g_assert_not_reached();
865fcf5ef2aSThomas Huth         }
866e5ac4200SAndrew Jones 
867e5ac4200SAndrew Jones         /*
868e5ac4200SAndrew Jones          * kvm_arm_cpu_pre_save() must be called after
869e5ac4200SAndrew Jones          * write_kvmstate_to_list()
870e5ac4200SAndrew Jones          */
871e5ac4200SAndrew Jones         kvm_arm_cpu_pre_save(cpu);
872fcf5ef2aSThomas Huth     } else {
873b698e4eeSPeter Maydell         if (!write_cpustate_to_list(cpu, false)) {
874fcf5ef2aSThomas Huth             /* This should never fail. */
875d385a605SRichard Henderson             g_assert_not_reached();
876fcf5ef2aSThomas Huth         }
877fcf5ef2aSThomas Huth     }
878fcf5ef2aSThomas Huth 
879fcf5ef2aSThomas Huth     cpu->cpreg_vmstate_array_len = cpu->cpreg_array_len;
880fcf5ef2aSThomas Huth     memcpy(cpu->cpreg_vmstate_indexes, cpu->cpreg_indexes,
881fcf5ef2aSThomas Huth            cpu->cpreg_array_len * sizeof(uint64_t));
882fcf5ef2aSThomas Huth     memcpy(cpu->cpreg_vmstate_values, cpu->cpreg_values,
883fcf5ef2aSThomas Huth            cpu->cpreg_array_len * sizeof(uint64_t));
88444b1ff31SDr. David Alan Gilbert 
88544b1ff31SDr. David Alan Gilbert     return 0;
886fcf5ef2aSThomas Huth }
887fcf5ef2aSThomas Huth 
cpu_post_save(void * opaque)888980ebe87SAaron Lindsay static int cpu_post_save(void *opaque)
889980ebe87SAaron Lindsay {
890980ebe87SAaron Lindsay     ARMCPU *cpu = opaque;
891980ebe87SAaron Lindsay 
892980ebe87SAaron Lindsay     if (!kvm_enabled()) {
893980ebe87SAaron Lindsay         pmu_op_finish(&cpu->env);
894980ebe87SAaron Lindsay     }
895980ebe87SAaron Lindsay 
896980ebe87SAaron Lindsay     return 0;
897980ebe87SAaron Lindsay }
898980ebe87SAaron Lindsay 
cpu_pre_load(void * opaque)899ed89f078SPeter Maydell static int cpu_pre_load(void *opaque)
900ed89f078SPeter Maydell {
901ed89f078SPeter Maydell     ARMCPU *cpu = opaque;
902ed89f078SPeter Maydell     CPUARMState *env = &cpu->env;
903ed89f078SPeter Maydell 
904ed89f078SPeter Maydell     /*
905abf1046aSPeter Maydell      * In an inbound migration where on the source FPSCR/FPSR/FPCR are 0,
906abf1046aSPeter Maydell      * there will be no fpcr_fpsr subsection so we won't call vfp_set_fpcr()
907abf1046aSPeter Maydell      * and vfp_set_fpsr() from get_fpcr() and get_fpsr(); also the get_fpscr()
908abf1046aSPeter Maydell      * function will not call vfp_set_fpscr() because it will see a 0 in the
909abf1046aSPeter Maydell      * inbound data. Ensure that in this case we have a correctly set up
910abf1046aSPeter Maydell      * zero FPSCR/FPCR/FPSR.
911abf1046aSPeter Maydell      *
912abf1046aSPeter Maydell      * This is not strictly needed because FPSCR is zero out of reset, but
913abf1046aSPeter Maydell      * it avoids the possibility of future confusing migration bugs if some
914abf1046aSPeter Maydell      * future architecture change makes the reset value non-zero.
915abf1046aSPeter Maydell      */
916abf1046aSPeter Maydell     vfp_set_fpscr(env, 0);
917abf1046aSPeter Maydell 
918abf1046aSPeter Maydell     /*
919ed89f078SPeter Maydell      * Pre-initialize irq_line_state to a value that's never valid as
920ed89f078SPeter Maydell      * real data, so cpu_post_load() can tell whether we've seen the
921ed89f078SPeter Maydell      * irq-line-state subsection in the incoming migration state.
922ed89f078SPeter Maydell      */
923ed89f078SPeter Maydell     env->irq_line_state = UINT32_MAX;
924ed89f078SPeter Maydell 
925980ebe87SAaron Lindsay     if (!kvm_enabled()) {
926ee1004bbSPhilippe Mathieu-Daudé         pmu_op_start(env);
927980ebe87SAaron Lindsay     }
928980ebe87SAaron Lindsay 
929ed89f078SPeter Maydell     return 0;
930ed89f078SPeter Maydell }
931ed89f078SPeter Maydell 
cpu_post_load(void * opaque,int version_id)932fcf5ef2aSThomas Huth static int cpu_post_load(void *opaque, int version_id)
933fcf5ef2aSThomas Huth {
934fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
935ed89f078SPeter Maydell     CPUARMState *env = &cpu->env;
936fcf5ef2aSThomas Huth     int i, v;
937fcf5ef2aSThomas Huth 
938ed89f078SPeter Maydell     /*
939ed89f078SPeter Maydell      * Handle migration compatibility from old QEMU which didn't
940ed89f078SPeter Maydell      * send the irq-line-state subsection. A QEMU without it did not
941ed89f078SPeter Maydell      * implement the HCR_EL2.{VI,VF} bits as generating interrupts,
942ed89f078SPeter Maydell      * so for TCG the line state matches the bits set in cs->interrupt_request.
943ed89f078SPeter Maydell      * For KVM the line state is not stored in cs->interrupt_request
944ed89f078SPeter Maydell      * and so this will leave irq_line_state as 0, but this is OK because
945ed89f078SPeter Maydell      * we only need to care about it for TCG.
946ed89f078SPeter Maydell      */
947ed89f078SPeter Maydell     if (env->irq_line_state == UINT32_MAX) {
948ed89f078SPeter Maydell         CPUState *cs = CPU(cpu);
949ed89f078SPeter Maydell 
950ed89f078SPeter Maydell         env->irq_line_state = cs->interrupt_request &
951ed89f078SPeter Maydell             (CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIQ |
952ed89f078SPeter Maydell              CPU_INTERRUPT_VIRQ | CPU_INTERRUPT_VFIQ);
953ed89f078SPeter Maydell     }
954ed89f078SPeter Maydell 
955fcf5ef2aSThomas Huth     /* Update the values list from the incoming migration data.
956fcf5ef2aSThomas Huth      * Anything in the incoming data which we don't know about is
957fcf5ef2aSThomas Huth      * a migration failure; anything we know about but the incoming
958fcf5ef2aSThomas Huth      * data doesn't specify retains its current (reset) value.
959fcf5ef2aSThomas Huth      * The indexes list remains untouched -- we only inspect the
960fcf5ef2aSThomas Huth      * incoming migration index list so we can match the values array
961fcf5ef2aSThomas Huth      * entries with the right slots in our own values array.
962fcf5ef2aSThomas Huth      */
963fcf5ef2aSThomas Huth 
964fcf5ef2aSThomas Huth     for (i = 0, v = 0; i < cpu->cpreg_array_len
965fcf5ef2aSThomas Huth              && v < cpu->cpreg_vmstate_array_len; i++) {
966fcf5ef2aSThomas Huth         if (cpu->cpreg_vmstate_indexes[v] > cpu->cpreg_indexes[i]) {
967fcf5ef2aSThomas Huth             /* register in our list but not incoming : skip it */
968fcf5ef2aSThomas Huth             continue;
969fcf5ef2aSThomas Huth         }
970fcf5ef2aSThomas Huth         if (cpu->cpreg_vmstate_indexes[v] < cpu->cpreg_indexes[i]) {
971fcf5ef2aSThomas Huth             /* register in their list but not ours: fail migration */
972fcf5ef2aSThomas Huth             return -1;
973fcf5ef2aSThomas Huth         }
974fcf5ef2aSThomas Huth         /* matching register, copy the value over */
975fcf5ef2aSThomas Huth         cpu->cpreg_values[i] = cpu->cpreg_vmstate_values[v];
976fcf5ef2aSThomas Huth         v++;
977fcf5ef2aSThomas Huth     }
978fcf5ef2aSThomas Huth 
979fcf5ef2aSThomas Huth     if (kvm_enabled()) {
980fcf5ef2aSThomas Huth         if (!write_list_to_kvmstate(cpu, KVM_PUT_FULL_STATE)) {
981fcf5ef2aSThomas Huth             return -1;
982fcf5ef2aSThomas Huth         }
983fcf5ef2aSThomas Huth         /* Note that it's OK for the TCG side not to know about
984fcf5ef2aSThomas Huth          * every register in the list; KVM is authoritative if
985fcf5ef2aSThomas Huth          * we're using it.
986fcf5ef2aSThomas Huth          */
987fcf5ef2aSThomas Huth         write_list_to_cpustate(cpu);
988e5ac4200SAndrew Jones         kvm_arm_cpu_post_load(cpu);
989fcf5ef2aSThomas Huth     } else {
990fcf5ef2aSThomas Huth         if (!write_list_to_cpustate(cpu)) {
991fcf5ef2aSThomas Huth             return -1;
992fcf5ef2aSThomas Huth         }
993fcf5ef2aSThomas Huth     }
994fcf5ef2aSThomas Huth 
995501e6d1fSFabiano Rosas     /*
996501e6d1fSFabiano Rosas      * Misaligned thumb pc is architecturally impossible. Fail the
997501e6d1fSFabiano Rosas      * incoming migration. For TCG it would trigger the assert in
998501e6d1fSFabiano Rosas      * thumb_tr_translate_insn().
999501e6d1fSFabiano Rosas      */
1000501e6d1fSFabiano Rosas     if (!is_a64(env) && env->thumb && (env->regs[15] & 1)) {
1001501e6d1fSFabiano Rosas         return -1;
1002501e6d1fSFabiano Rosas     }
1003501e6d1fSFabiano Rosas 
1004fa05d1abSFabiano Rosas     if (tcg_enabled()) {
1005fcf5ef2aSThomas Huth         hw_breakpoint_update_all(cpu);
1006fcf5ef2aSThomas Huth         hw_watchpoint_update_all(cpu);
1007fa05d1abSFabiano Rosas     }
1008fcf5ef2aSThomas Huth 
100985e7d1e9SPeter Maydell     /*
101085e7d1e9SPeter Maydell      * TCG gen_update_fp_context() relies on the invariant that
101185e7d1e9SPeter Maydell      * FPDSCR.LTPSIZE is constant 4 for M-profile with the LOB extension;
101285e7d1e9SPeter Maydell      * forbid bogus incoming data with some other value.
101385e7d1e9SPeter Maydell      */
101485e7d1e9SPeter Maydell     if (arm_feature(env, ARM_FEATURE_M) && cpu_isar_feature(aa32_lob, cpu)) {
101585e7d1e9SPeter Maydell         if (extract32(env->v7m.fpdscr[M_REG_NS],
101685e7d1e9SPeter Maydell                       FPCR_LTPSIZE_SHIFT, FPCR_LTPSIZE_LENGTH) != 4 ||
101785e7d1e9SPeter Maydell             extract32(env->v7m.fpdscr[M_REG_S],
101885e7d1e9SPeter Maydell                       FPCR_LTPSIZE_SHIFT, FPCR_LTPSIZE_LENGTH) != 4) {
101985e7d1e9SPeter Maydell             return -1;
102085e7d1e9SPeter Maydell         }
102185e7d1e9SPeter Maydell     }
10227055fe4bSRichard Henderson 
1023980ebe87SAaron Lindsay     if (!kvm_enabled()) {
1024ee1004bbSPhilippe Mathieu-Daudé         pmu_op_finish(env);
1025980ebe87SAaron Lindsay     }
10262b77ad4dSFabiano Rosas 
10272b77ad4dSFabiano Rosas     if (tcg_enabled()) {
1028ee1004bbSPhilippe Mathieu-Daudé         arm_rebuild_hflags(env);
10292b77ad4dSFabiano Rosas     }
1030980ebe87SAaron Lindsay 
1031fcf5ef2aSThomas Huth     return 0;
1032fcf5ef2aSThomas Huth }
1033fcf5ef2aSThomas Huth 
1034fcf5ef2aSThomas Huth const VMStateDescription vmstate_arm_cpu = {
1035fcf5ef2aSThomas Huth     .name = "cpu",
1036fcf5ef2aSThomas Huth     .version_id = 22,
1037fcf5ef2aSThomas Huth     .minimum_version_id = 22,
1038fcf5ef2aSThomas Huth     .pre_save = cpu_pre_save,
1039980ebe87SAaron Lindsay     .post_save = cpu_post_save,
1040ed89f078SPeter Maydell     .pre_load = cpu_pre_load,
1041fcf5ef2aSThomas Huth     .post_load = cpu_post_load,
1042e3fe0bc6SRichard Henderson     .fields = (const VMStateField[]) {
1043fcf5ef2aSThomas Huth         VMSTATE_UINT32_ARRAY(env.regs, ARMCPU, 16),
1044fcf5ef2aSThomas Huth         VMSTATE_UINT64_ARRAY(env.xregs, ARMCPU, 32),
1045fcf5ef2aSThomas Huth         VMSTATE_UINT64(env.pc, ARMCPU),
1046fcf5ef2aSThomas Huth         {
1047fcf5ef2aSThomas Huth             .name = "cpsr",
1048fcf5ef2aSThomas Huth             .version_id = 0,
1049fcf5ef2aSThomas Huth             .size = sizeof(uint32_t),
1050fcf5ef2aSThomas Huth             .info = &vmstate_cpsr,
1051fcf5ef2aSThomas Huth             .flags = VMS_SINGLE,
1052fcf5ef2aSThomas Huth             .offset = 0,
1053fcf5ef2aSThomas Huth         },
1054fcf5ef2aSThomas Huth         VMSTATE_UINT32(env.spsr, ARMCPU),
1055fcf5ef2aSThomas Huth         VMSTATE_UINT64_ARRAY(env.banked_spsr, ARMCPU, 8),
1056fcf5ef2aSThomas Huth         VMSTATE_UINT32_ARRAY(env.banked_r13, ARMCPU, 8),
1057fcf5ef2aSThomas Huth         VMSTATE_UINT32_ARRAY(env.banked_r14, ARMCPU, 8),
1058fcf5ef2aSThomas Huth         VMSTATE_UINT32_ARRAY(env.usr_regs, ARMCPU, 5),
1059fcf5ef2aSThomas Huth         VMSTATE_UINT32_ARRAY(env.fiq_regs, ARMCPU, 5),
1060fcf5ef2aSThomas Huth         VMSTATE_UINT64_ARRAY(env.elr_el, ARMCPU, 4),
1061fcf5ef2aSThomas Huth         VMSTATE_UINT64_ARRAY(env.sp_el, ARMCPU, 4),
1062fcf5ef2aSThomas Huth         /* The length-check must come before the arrays to avoid
1063fcf5ef2aSThomas Huth          * incoming data possibly overflowing the array.
1064fcf5ef2aSThomas Huth          */
1065fcf5ef2aSThomas Huth         VMSTATE_INT32_POSITIVE_LE(cpreg_vmstate_array_len, ARMCPU),
1066fcf5ef2aSThomas Huth         VMSTATE_VARRAY_INT32(cpreg_vmstate_indexes, ARMCPU,
1067fcf5ef2aSThomas Huth                              cpreg_vmstate_array_len,
1068fcf5ef2aSThomas Huth                              0, vmstate_info_uint64, uint64_t),
1069fcf5ef2aSThomas Huth         VMSTATE_VARRAY_INT32(cpreg_vmstate_values, ARMCPU,
1070fcf5ef2aSThomas Huth                              cpreg_vmstate_array_len,
1071fcf5ef2aSThomas Huth                              0, vmstate_info_uint64, uint64_t),
1072fcf5ef2aSThomas Huth         VMSTATE_UINT64(env.exclusive_addr, ARMCPU),
1073fcf5ef2aSThomas Huth         VMSTATE_UINT64(env.exclusive_val, ARMCPU),
1074fcf5ef2aSThomas Huth         VMSTATE_UINT64(env.exclusive_high, ARMCPU),
1075af903caeSAaron Lindsay         VMSTATE_UNUSED(sizeof(uint64_t)),
1076fcf5ef2aSThomas Huth         VMSTATE_UINT32(env.exception.syndrome, ARMCPU),
1077fcf5ef2aSThomas Huth         VMSTATE_UINT32(env.exception.fsr, ARMCPU),
1078fcf5ef2aSThomas Huth         VMSTATE_UINT64(env.exception.vaddress, ARMCPU),
1079fcf5ef2aSThomas Huth         VMSTATE_TIMER_PTR(gt_timer[GTIMER_PHYS], ARMCPU),
1080fcf5ef2aSThomas Huth         VMSTATE_TIMER_PTR(gt_timer[GTIMER_VIRT], ARMCPU),
1081062ba099SAlex Bennée         {
1082062ba099SAlex Bennée             .name = "power_state",
1083062ba099SAlex Bennée             .version_id = 0,
1084062ba099SAlex Bennée             .size = sizeof(bool),
1085062ba099SAlex Bennée             .info = &vmstate_powered_off,
1086062ba099SAlex Bennée             .flags = VMS_SINGLE,
1087062ba099SAlex Bennée             .offset = 0,
1088062ba099SAlex Bennée         },
1089fcf5ef2aSThomas Huth         VMSTATE_END_OF_LIST()
1090fcf5ef2aSThomas Huth     },
1091e3fe0bc6SRichard Henderson     .subsections = (const VMStateDescription * const []) {
1092fcf5ef2aSThomas Huth         &vmstate_vfp,
1093fcf5ef2aSThomas Huth         &vmstate_iwmmxt,
1094fcf5ef2aSThomas Huth         &vmstate_m,
1095fcf5ef2aSThomas Huth         &vmstate_thumb2ee,
1096f1a46940SPeter Maydell         /* pmsav7_rnr must come before pmsav7 so that we have the
1097f1a46940SPeter Maydell          * region number before we test it in the VMSTATE_VALIDATE
1098f1a46940SPeter Maydell          * in vmstate_pmsav7.
1099f1a46940SPeter Maydell          */
1100f1a46940SPeter Maydell         &vmstate_pmsav7_rnr,
1101fcf5ef2aSThomas Huth         &vmstate_pmsav7,
11020e1a46bbSPeter Maydell         &vmstate_pmsav8,
11031e577cc7SPeter Maydell         &vmstate_m_security,
1104ef401601SRichard Henderson #ifdef TARGET_AARCH64
1105ef401601SRichard Henderson         &vmstate_sve,
1106dc993a01SRichard Henderson         &vmstate_za,
1107ef401601SRichard Henderson #endif
1108202ccb6bSDongjiu Geng         &vmstate_serror,
1109ed89f078SPeter Maydell         &vmstate_irq_line_state,
1110a96edb68SPeter Maydell         &vmstate_wfxt_timer,
1111fcf5ef2aSThomas Huth         NULL
1112fcf5ef2aSThomas Huth     }
1113fcf5ef2aSThomas Huth };
1114