xref: /openbmc/qemu/target/arm/machine.c (revision cd208a1c3923bc097ec55c5b207d79294ab0e719)
1fcf5ef2aSThomas Huth #include "qemu/osdep.h"
2fcf5ef2aSThomas Huth #include "qemu-common.h"
3fcf5ef2aSThomas Huth #include "cpu.h"
4fcf5ef2aSThomas Huth #include "hw/hw.h"
5fcf5ef2aSThomas Huth #include "hw/boards.h"
6fcf5ef2aSThomas Huth #include "qemu/error-report.h"
7fcf5ef2aSThomas Huth #include "sysemu/kvm.h"
8fcf5ef2aSThomas Huth #include "kvm_arm.h"
9fcf5ef2aSThomas Huth #include "internals.h"
10fcf5ef2aSThomas Huth #include "migration/cpu.h"
11fcf5ef2aSThomas Huth 
12fcf5ef2aSThomas Huth static bool vfp_needed(void *opaque)
13fcf5ef2aSThomas Huth {
14fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
15fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
16fcf5ef2aSThomas Huth 
17fcf5ef2aSThomas Huth     return arm_feature(env, ARM_FEATURE_VFP);
18fcf5ef2aSThomas Huth }
19fcf5ef2aSThomas Huth 
202c21ee76SJianjun Duan static int get_fpscr(QEMUFile *f, void *opaque, size_t size,
212c21ee76SJianjun Duan                      VMStateField *field)
22fcf5ef2aSThomas Huth {
23fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
24fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
25fcf5ef2aSThomas Huth     uint32_t val = qemu_get_be32(f);
26fcf5ef2aSThomas Huth 
27fcf5ef2aSThomas Huth     vfp_set_fpscr(env, val);
28fcf5ef2aSThomas Huth     return 0;
29fcf5ef2aSThomas Huth }
30fcf5ef2aSThomas Huth 
312c21ee76SJianjun Duan static int put_fpscr(QEMUFile *f, void *opaque, size_t size,
322c21ee76SJianjun Duan                      VMStateField *field, QJSON *vmdesc)
33fcf5ef2aSThomas Huth {
34fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
35fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
36fcf5ef2aSThomas Huth 
37fcf5ef2aSThomas Huth     qemu_put_be32(f, vfp_get_fpscr(env));
382c21ee76SJianjun Duan     return 0;
39fcf5ef2aSThomas Huth }
40fcf5ef2aSThomas Huth 
41fcf5ef2aSThomas Huth static const VMStateInfo vmstate_fpscr = {
42fcf5ef2aSThomas Huth     .name = "fpscr",
43fcf5ef2aSThomas Huth     .get = get_fpscr,
44fcf5ef2aSThomas Huth     .put = put_fpscr,
45fcf5ef2aSThomas Huth };
46fcf5ef2aSThomas Huth 
47fcf5ef2aSThomas Huth static const VMStateDescription vmstate_vfp = {
48fcf5ef2aSThomas Huth     .name = "cpu/vfp",
49fcf5ef2aSThomas Huth     .version_id = 3,
50fcf5ef2aSThomas Huth     .minimum_version_id = 3,
51fcf5ef2aSThomas Huth     .needed = vfp_needed,
52fcf5ef2aSThomas Huth     .fields = (VMStateField[]) {
53c39c2b90SRichard Henderson         /* For compatibility, store Qn out of Zn here.  */
54c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[0].d, ARMCPU, 0, 2),
55c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[1].d, ARMCPU, 0, 2),
56c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[2].d, ARMCPU, 0, 2),
57c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[3].d, ARMCPU, 0, 2),
58c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[4].d, ARMCPU, 0, 2),
59c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[5].d, ARMCPU, 0, 2),
60c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[6].d, ARMCPU, 0, 2),
61c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[7].d, ARMCPU, 0, 2),
62c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[8].d, ARMCPU, 0, 2),
63c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[9].d, ARMCPU, 0, 2),
64c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[10].d, ARMCPU, 0, 2),
65c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[11].d, ARMCPU, 0, 2),
66c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[12].d, ARMCPU, 0, 2),
67c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[13].d, ARMCPU, 0, 2),
68c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[14].d, ARMCPU, 0, 2),
69c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[15].d, ARMCPU, 0, 2),
70c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[16].d, ARMCPU, 0, 2),
71c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[17].d, ARMCPU, 0, 2),
72c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[18].d, ARMCPU, 0, 2),
73c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[19].d, ARMCPU, 0, 2),
74c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[20].d, ARMCPU, 0, 2),
75c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[21].d, ARMCPU, 0, 2),
76c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[22].d, ARMCPU, 0, 2),
77c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[23].d, ARMCPU, 0, 2),
78c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[24].d, ARMCPU, 0, 2),
79c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[25].d, ARMCPU, 0, 2),
80c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[26].d, ARMCPU, 0, 2),
81c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[27].d, ARMCPU, 0, 2),
82c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[28].d, ARMCPU, 0, 2),
83c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[29].d, ARMCPU, 0, 2),
84c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[30].d, ARMCPU, 0, 2),
85c39c2b90SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(env.vfp.zregs[31].d, ARMCPU, 0, 2),
86c39c2b90SRichard Henderson 
87fcf5ef2aSThomas Huth         /* The xregs array is a little awkward because element 1 (FPSCR)
88fcf5ef2aSThomas Huth          * requires a specific accessor, so we have to split it up in
89fcf5ef2aSThomas Huth          * the vmstate:
90fcf5ef2aSThomas Huth          */
91fcf5ef2aSThomas Huth         VMSTATE_UINT32(env.vfp.xregs[0], ARMCPU),
92fcf5ef2aSThomas Huth         VMSTATE_UINT32_SUB_ARRAY(env.vfp.xregs, ARMCPU, 2, 14),
93fcf5ef2aSThomas Huth         {
94fcf5ef2aSThomas Huth             .name = "fpscr",
95fcf5ef2aSThomas Huth             .version_id = 0,
96fcf5ef2aSThomas Huth             .size = sizeof(uint32_t),
97fcf5ef2aSThomas Huth             .info = &vmstate_fpscr,
98fcf5ef2aSThomas Huth             .flags = VMS_SINGLE,
99fcf5ef2aSThomas Huth             .offset = 0,
100fcf5ef2aSThomas Huth         },
101fcf5ef2aSThomas Huth         VMSTATE_END_OF_LIST()
102fcf5ef2aSThomas Huth     }
103fcf5ef2aSThomas Huth };
104fcf5ef2aSThomas Huth 
105fcf5ef2aSThomas Huth static bool iwmmxt_needed(void *opaque)
106fcf5ef2aSThomas Huth {
107fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
108fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
109fcf5ef2aSThomas Huth 
110fcf5ef2aSThomas Huth     return arm_feature(env, ARM_FEATURE_IWMMXT);
111fcf5ef2aSThomas Huth }
112fcf5ef2aSThomas Huth 
113fcf5ef2aSThomas Huth static const VMStateDescription vmstate_iwmmxt = {
114fcf5ef2aSThomas Huth     .name = "cpu/iwmmxt",
115fcf5ef2aSThomas Huth     .version_id = 1,
116fcf5ef2aSThomas Huth     .minimum_version_id = 1,
117fcf5ef2aSThomas Huth     .needed = iwmmxt_needed,
118fcf5ef2aSThomas Huth     .fields = (VMStateField[]) {
119fcf5ef2aSThomas Huth         VMSTATE_UINT64_ARRAY(env.iwmmxt.regs, ARMCPU, 16),
120fcf5ef2aSThomas Huth         VMSTATE_UINT32_ARRAY(env.iwmmxt.cregs, ARMCPU, 16),
121fcf5ef2aSThomas Huth         VMSTATE_END_OF_LIST()
122fcf5ef2aSThomas Huth     }
123fcf5ef2aSThomas Huth };
124fcf5ef2aSThomas Huth 
125ef401601SRichard Henderson #ifdef TARGET_AARCH64
126ef401601SRichard Henderson /* The expression ARM_MAX_VQ - 2 is 0 for pure AArch32 build,
127ef401601SRichard Henderson  * and ARMPredicateReg is actively empty.  This triggers errors
128ef401601SRichard Henderson  * in the expansion of the VMSTATE macros.
129ef401601SRichard Henderson  */
130ef401601SRichard Henderson 
131ef401601SRichard Henderson static bool sve_needed(void *opaque)
132ef401601SRichard Henderson {
133ef401601SRichard Henderson     ARMCPU *cpu = opaque;
134ef401601SRichard Henderson 
135*cd208a1cSRichard Henderson     return cpu_isar_feature(aa64_sve, cpu);
136ef401601SRichard Henderson }
137ef401601SRichard Henderson 
138ef401601SRichard Henderson /* The first two words of each Zreg is stored in VFP state.  */
139ef401601SRichard Henderson static const VMStateDescription vmstate_zreg_hi_reg = {
140ef401601SRichard Henderson     .name = "cpu/sve/zreg_hi",
141ef401601SRichard Henderson     .version_id = 1,
142ef401601SRichard Henderson     .minimum_version_id = 1,
143ef401601SRichard Henderson     .fields = (VMStateField[]) {
144ef401601SRichard Henderson         VMSTATE_UINT64_SUB_ARRAY(d, ARMVectorReg, 2, ARM_MAX_VQ - 2),
145ef401601SRichard Henderson         VMSTATE_END_OF_LIST()
146ef401601SRichard Henderson     }
147ef401601SRichard Henderson };
148ef401601SRichard Henderson 
149ef401601SRichard Henderson static const VMStateDescription vmstate_preg_reg = {
150ef401601SRichard Henderson     .name = "cpu/sve/preg",
151ef401601SRichard Henderson     .version_id = 1,
152ef401601SRichard Henderson     .minimum_version_id = 1,
153ef401601SRichard Henderson     .fields = (VMStateField[]) {
154ef401601SRichard Henderson         VMSTATE_UINT64_ARRAY(p, ARMPredicateReg, 2 * ARM_MAX_VQ / 8),
155ef401601SRichard Henderson         VMSTATE_END_OF_LIST()
156ef401601SRichard Henderson     }
157ef401601SRichard Henderson };
158ef401601SRichard Henderson 
159ef401601SRichard Henderson static const VMStateDescription vmstate_sve = {
160ef401601SRichard Henderson     .name = "cpu/sve",
161ef401601SRichard Henderson     .version_id = 1,
162ef401601SRichard Henderson     .minimum_version_id = 1,
163ef401601SRichard Henderson     .needed = sve_needed,
164ef401601SRichard Henderson     .fields = (VMStateField[]) {
165ef401601SRichard Henderson         VMSTATE_STRUCT_ARRAY(env.vfp.zregs, ARMCPU, 32, 0,
166ef401601SRichard Henderson                              vmstate_zreg_hi_reg, ARMVectorReg),
167ef401601SRichard Henderson         VMSTATE_STRUCT_ARRAY(env.vfp.pregs, ARMCPU, 17, 0,
168ef401601SRichard Henderson                              vmstate_preg_reg, ARMPredicateReg),
169ef401601SRichard Henderson         VMSTATE_END_OF_LIST()
170ef401601SRichard Henderson     }
171ef401601SRichard Henderson };
172ef401601SRichard Henderson #endif /* AARCH64 */
173ef401601SRichard Henderson 
174202ccb6bSDongjiu Geng static bool serror_needed(void *opaque)
175202ccb6bSDongjiu Geng {
176202ccb6bSDongjiu Geng     ARMCPU *cpu = opaque;
177202ccb6bSDongjiu Geng     CPUARMState *env = &cpu->env;
178202ccb6bSDongjiu Geng 
179202ccb6bSDongjiu Geng     return env->serror.pending != 0;
180202ccb6bSDongjiu Geng }
181202ccb6bSDongjiu Geng 
182202ccb6bSDongjiu Geng static const VMStateDescription vmstate_serror = {
183202ccb6bSDongjiu Geng     .name = "cpu/serror",
184202ccb6bSDongjiu Geng     .version_id = 1,
185202ccb6bSDongjiu Geng     .minimum_version_id = 1,
186202ccb6bSDongjiu Geng     .needed = serror_needed,
187202ccb6bSDongjiu Geng     .fields = (VMStateField[]) {
188202ccb6bSDongjiu Geng         VMSTATE_UINT8(env.serror.pending, ARMCPU),
189202ccb6bSDongjiu Geng         VMSTATE_UINT8(env.serror.has_esr, ARMCPU),
190202ccb6bSDongjiu Geng         VMSTATE_UINT64(env.serror.esr, ARMCPU),
191202ccb6bSDongjiu Geng         VMSTATE_END_OF_LIST()
192202ccb6bSDongjiu Geng     }
193202ccb6bSDongjiu Geng };
194202ccb6bSDongjiu Geng 
195fcf5ef2aSThomas Huth static bool m_needed(void *opaque)
196fcf5ef2aSThomas Huth {
197fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
198fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
199fcf5ef2aSThomas Huth 
200fcf5ef2aSThomas Huth     return arm_feature(env, ARM_FEATURE_M);
201fcf5ef2aSThomas Huth }
202fcf5ef2aSThomas Huth 
203e6ae5981SPeter Maydell static const VMStateDescription vmstate_m_faultmask_primask = {
204e6ae5981SPeter Maydell     .name = "cpu/m/faultmask-primask",
205e6ae5981SPeter Maydell     .version_id = 1,
206e6ae5981SPeter Maydell     .minimum_version_id = 1,
2077b69454aSPeter Maydell     .needed = m_needed,
208e6ae5981SPeter Maydell     .fields = (VMStateField[]) {
20942a6686bSPeter Maydell         VMSTATE_UINT32(env.v7m.faultmask[M_REG_NS], ARMCPU),
2106d804834SPeter Maydell         VMSTATE_UINT32(env.v7m.primask[M_REG_NS], ARMCPU),
211e6ae5981SPeter Maydell         VMSTATE_END_OF_LIST()
212e6ae5981SPeter Maydell     }
213e6ae5981SPeter Maydell };
214e6ae5981SPeter Maydell 
21543bbce7fSPeter Maydell /* CSSELR is in a subsection because we didn't implement it previously.
21643bbce7fSPeter Maydell  * Migration from an old implementation will leave it at zero, which
21743bbce7fSPeter Maydell  * is OK since the only CPUs in the old implementation make the
21843bbce7fSPeter Maydell  * register RAZ/WI.
21943bbce7fSPeter Maydell  * Since there was no version of QEMU which implemented the CSSELR for
22043bbce7fSPeter Maydell  * just non-secure, we transfer both banks here rather than putting
22143bbce7fSPeter Maydell  * the secure banked version in the m-security subsection.
22243bbce7fSPeter Maydell  */
22343bbce7fSPeter Maydell static bool csselr_vmstate_validate(void *opaque, int version_id)
22443bbce7fSPeter Maydell {
22543bbce7fSPeter Maydell     ARMCPU *cpu = opaque;
22643bbce7fSPeter Maydell 
22743bbce7fSPeter Maydell     return cpu->env.v7m.csselr[M_REG_NS] <= R_V7M_CSSELR_INDEX_MASK
22843bbce7fSPeter Maydell         && cpu->env.v7m.csselr[M_REG_S] <= R_V7M_CSSELR_INDEX_MASK;
22943bbce7fSPeter Maydell }
23043bbce7fSPeter Maydell 
23143bbce7fSPeter Maydell static bool m_csselr_needed(void *opaque)
23243bbce7fSPeter Maydell {
23343bbce7fSPeter Maydell     ARMCPU *cpu = opaque;
23443bbce7fSPeter Maydell 
23543bbce7fSPeter Maydell     return !arm_v7m_csselr_razwi(cpu);
23643bbce7fSPeter Maydell }
23743bbce7fSPeter Maydell 
23843bbce7fSPeter Maydell static const VMStateDescription vmstate_m_csselr = {
23943bbce7fSPeter Maydell     .name = "cpu/m/csselr",
24043bbce7fSPeter Maydell     .version_id = 1,
24143bbce7fSPeter Maydell     .minimum_version_id = 1,
24243bbce7fSPeter Maydell     .needed = m_csselr_needed,
24343bbce7fSPeter Maydell     .fields = (VMStateField[]) {
24443bbce7fSPeter Maydell         VMSTATE_UINT32_ARRAY(env.v7m.csselr, ARMCPU, M_REG_NUM_BANKS),
24543bbce7fSPeter Maydell         VMSTATE_VALIDATE("CSSELR is valid", csselr_vmstate_validate),
24643bbce7fSPeter Maydell         VMSTATE_END_OF_LIST()
24743bbce7fSPeter Maydell     }
24843bbce7fSPeter Maydell };
24943bbce7fSPeter Maydell 
25024ac0fb1SPeter Maydell static const VMStateDescription vmstate_m_scr = {
25124ac0fb1SPeter Maydell     .name = "cpu/m/scr",
25224ac0fb1SPeter Maydell     .version_id = 1,
25324ac0fb1SPeter Maydell     .minimum_version_id = 1,
2547b69454aSPeter Maydell     .needed = m_needed,
25524ac0fb1SPeter Maydell     .fields = (VMStateField[]) {
25624ac0fb1SPeter Maydell         VMSTATE_UINT32(env.v7m.scr[M_REG_NS], ARMCPU),
25724ac0fb1SPeter Maydell         VMSTATE_END_OF_LIST()
25824ac0fb1SPeter Maydell     }
25924ac0fb1SPeter Maydell };
26024ac0fb1SPeter Maydell 
261e1e7cbc9SPeter Maydell static const VMStateDescription vmstate_m_other_sp = {
262e1e7cbc9SPeter Maydell     .name = "cpu/m/other-sp",
263e1e7cbc9SPeter Maydell     .version_id = 1,
264e1e7cbc9SPeter Maydell     .minimum_version_id = 1,
2657b69454aSPeter Maydell     .needed = m_needed,
266e1e7cbc9SPeter Maydell     .fields = (VMStateField[]) {
267e1e7cbc9SPeter Maydell         VMSTATE_UINT32(env.v7m.other_sp, ARMCPU),
268e1e7cbc9SPeter Maydell         VMSTATE_END_OF_LIST()
269e1e7cbc9SPeter Maydell     }
270e1e7cbc9SPeter Maydell };
271e1e7cbc9SPeter Maydell 
27257bb3156SPeter Maydell static bool m_v8m_needed(void *opaque)
27357bb3156SPeter Maydell {
27457bb3156SPeter Maydell     ARMCPU *cpu = opaque;
27557bb3156SPeter Maydell     CPUARMState *env = &cpu->env;
27657bb3156SPeter Maydell 
27757bb3156SPeter Maydell     return arm_feature(env, ARM_FEATURE_M) && arm_feature(env, ARM_FEATURE_V8);
27857bb3156SPeter Maydell }
27957bb3156SPeter Maydell 
28057bb3156SPeter Maydell static const VMStateDescription vmstate_m_v8m = {
28157bb3156SPeter Maydell     .name = "cpu/m/v8m",
28257bb3156SPeter Maydell     .version_id = 1,
28357bb3156SPeter Maydell     .minimum_version_id = 1,
28457bb3156SPeter Maydell     .needed = m_v8m_needed,
28557bb3156SPeter Maydell     .fields = (VMStateField[]) {
28657bb3156SPeter Maydell         VMSTATE_UINT32_ARRAY(env.v7m.msplim, ARMCPU, M_REG_NUM_BANKS),
28757bb3156SPeter Maydell         VMSTATE_UINT32_ARRAY(env.v7m.psplim, ARMCPU, M_REG_NUM_BANKS),
28857bb3156SPeter Maydell         VMSTATE_END_OF_LIST()
28957bb3156SPeter Maydell     }
29057bb3156SPeter Maydell };
29157bb3156SPeter Maydell 
292fcf5ef2aSThomas Huth static const VMStateDescription vmstate_m = {
293fcf5ef2aSThomas Huth     .name = "cpu/m",
29429c483a5SMichael Davidsaver     .version_id = 4,
29529c483a5SMichael Davidsaver     .minimum_version_id = 4,
296fcf5ef2aSThomas Huth     .needed = m_needed,
297fcf5ef2aSThomas Huth     .fields = (VMStateField[]) {
29845db7ba6SPeter Maydell         VMSTATE_UINT32(env.v7m.vecbase[M_REG_NS], ARMCPU),
299acf94941SPeter Maydell         VMSTATE_UINT32(env.v7m.basepri[M_REG_NS], ARMCPU),
3008bfc26eaSPeter Maydell         VMSTATE_UINT32(env.v7m.control[M_REG_NS], ARMCPU),
3019d40cd8aSPeter Maydell         VMSTATE_UINT32(env.v7m.ccr[M_REG_NS], ARMCPU),
302334e8dadSPeter Maydell         VMSTATE_UINT32(env.v7m.cfsr[M_REG_NS], ARMCPU),
3032c4da50dSPeter Maydell         VMSTATE_UINT32(env.v7m.hfsr, ARMCPU),
3042c4da50dSPeter Maydell         VMSTATE_UINT32(env.v7m.dfsr, ARMCPU),
305c51a5cfcSPeter Maydell         VMSTATE_UINT32(env.v7m.mmfar[M_REG_NS], ARMCPU),
3062c4da50dSPeter Maydell         VMSTATE_UINT32(env.v7m.bfar, ARMCPU),
307ecf5e8eaSPeter Maydell         VMSTATE_UINT32(env.v7m.mpu_ctrl[M_REG_NS], ARMCPU),
308fcf5ef2aSThomas Huth         VMSTATE_INT32(env.v7m.exception, ARMCPU),
309fcf5ef2aSThomas Huth         VMSTATE_END_OF_LIST()
310e6ae5981SPeter Maydell     },
311e6ae5981SPeter Maydell     .subsections = (const VMStateDescription*[]) {
312e6ae5981SPeter Maydell         &vmstate_m_faultmask_primask,
31343bbce7fSPeter Maydell         &vmstate_m_csselr,
31424ac0fb1SPeter Maydell         &vmstate_m_scr,
315e1e7cbc9SPeter Maydell         &vmstate_m_other_sp,
31657bb3156SPeter Maydell         &vmstate_m_v8m,
317e6ae5981SPeter Maydell         NULL
318fcf5ef2aSThomas Huth     }
319fcf5ef2aSThomas Huth };
320fcf5ef2aSThomas Huth 
321fcf5ef2aSThomas Huth static bool thumb2ee_needed(void *opaque)
322fcf5ef2aSThomas Huth {
323fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
324fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
325fcf5ef2aSThomas Huth 
326fcf5ef2aSThomas Huth     return arm_feature(env, ARM_FEATURE_THUMB2EE);
327fcf5ef2aSThomas Huth }
328fcf5ef2aSThomas Huth 
329fcf5ef2aSThomas Huth static const VMStateDescription vmstate_thumb2ee = {
330fcf5ef2aSThomas Huth     .name = "cpu/thumb2ee",
331fcf5ef2aSThomas Huth     .version_id = 1,
332fcf5ef2aSThomas Huth     .minimum_version_id = 1,
333fcf5ef2aSThomas Huth     .needed = thumb2ee_needed,
334fcf5ef2aSThomas Huth     .fields = (VMStateField[]) {
335fcf5ef2aSThomas Huth         VMSTATE_UINT32(env.teecr, ARMCPU),
336fcf5ef2aSThomas Huth         VMSTATE_UINT32(env.teehbr, ARMCPU),
337fcf5ef2aSThomas Huth         VMSTATE_END_OF_LIST()
338fcf5ef2aSThomas Huth     }
339fcf5ef2aSThomas Huth };
340fcf5ef2aSThomas Huth 
341fcf5ef2aSThomas Huth static bool pmsav7_needed(void *opaque)
342fcf5ef2aSThomas Huth {
343fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
344fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
345fcf5ef2aSThomas Huth 
346452a0955SPeter Maydell     return arm_feature(env, ARM_FEATURE_PMSA) &&
3470e1a46bbSPeter Maydell            arm_feature(env, ARM_FEATURE_V7) &&
3480e1a46bbSPeter Maydell            !arm_feature(env, ARM_FEATURE_V8);
349fcf5ef2aSThomas Huth }
350fcf5ef2aSThomas Huth 
351fcf5ef2aSThomas Huth static bool pmsav7_rgnr_vmstate_validate(void *opaque, int version_id)
352fcf5ef2aSThomas Huth {
353fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
354fcf5ef2aSThomas Huth 
3551bc04a88SPeter Maydell     return cpu->env.pmsav7.rnr[M_REG_NS] < cpu->pmsav7_dregion;
356fcf5ef2aSThomas Huth }
357fcf5ef2aSThomas Huth 
358fcf5ef2aSThomas Huth static const VMStateDescription vmstate_pmsav7 = {
359fcf5ef2aSThomas Huth     .name = "cpu/pmsav7",
360fcf5ef2aSThomas Huth     .version_id = 1,
361fcf5ef2aSThomas Huth     .minimum_version_id = 1,
362fcf5ef2aSThomas Huth     .needed = pmsav7_needed,
363fcf5ef2aSThomas Huth     .fields = (VMStateField[]) {
364fcf5ef2aSThomas Huth         VMSTATE_VARRAY_UINT32(env.pmsav7.drbar, ARMCPU, pmsav7_dregion, 0,
365fcf5ef2aSThomas Huth                               vmstate_info_uint32, uint32_t),
366fcf5ef2aSThomas Huth         VMSTATE_VARRAY_UINT32(env.pmsav7.drsr, ARMCPU, pmsav7_dregion, 0,
367fcf5ef2aSThomas Huth                               vmstate_info_uint32, uint32_t),
368fcf5ef2aSThomas Huth         VMSTATE_VARRAY_UINT32(env.pmsav7.dracr, ARMCPU, pmsav7_dregion, 0,
369fcf5ef2aSThomas Huth                               vmstate_info_uint32, uint32_t),
370fcf5ef2aSThomas Huth         VMSTATE_VALIDATE("rgnr is valid", pmsav7_rgnr_vmstate_validate),
371fcf5ef2aSThomas Huth         VMSTATE_END_OF_LIST()
372fcf5ef2aSThomas Huth     }
373fcf5ef2aSThomas Huth };
374fcf5ef2aSThomas Huth 
375f1a46940SPeter Maydell static bool pmsav7_rnr_needed(void *opaque)
376f1a46940SPeter Maydell {
377f1a46940SPeter Maydell     ARMCPU *cpu = opaque;
378f1a46940SPeter Maydell     CPUARMState *env = &cpu->env;
379f1a46940SPeter Maydell 
380f1a46940SPeter Maydell     /* For R profile cores pmsav7.rnr is migrated via the cpreg
381f1a46940SPeter Maydell      * "RGNR" definition in helper.h. For M profile we have to
382f1a46940SPeter Maydell      * migrate it separately.
383f1a46940SPeter Maydell      */
384f1a46940SPeter Maydell     return arm_feature(env, ARM_FEATURE_M);
385f1a46940SPeter Maydell }
386f1a46940SPeter Maydell 
387f1a46940SPeter Maydell static const VMStateDescription vmstate_pmsav7_rnr = {
388f1a46940SPeter Maydell     .name = "cpu/pmsav7-rnr",
389f1a46940SPeter Maydell     .version_id = 1,
390f1a46940SPeter Maydell     .minimum_version_id = 1,
391f1a46940SPeter Maydell     .needed = pmsav7_rnr_needed,
392f1a46940SPeter Maydell     .fields = (VMStateField[]) {
3931bc04a88SPeter Maydell         VMSTATE_UINT32(env.pmsav7.rnr[M_REG_NS], ARMCPU),
394f1a46940SPeter Maydell         VMSTATE_END_OF_LIST()
395f1a46940SPeter Maydell     }
396f1a46940SPeter Maydell };
397f1a46940SPeter Maydell 
3980e1a46bbSPeter Maydell static bool pmsav8_needed(void *opaque)
3990e1a46bbSPeter Maydell {
4000e1a46bbSPeter Maydell     ARMCPU *cpu = opaque;
4010e1a46bbSPeter Maydell     CPUARMState *env = &cpu->env;
4020e1a46bbSPeter Maydell 
4030e1a46bbSPeter Maydell     return arm_feature(env, ARM_FEATURE_PMSA) &&
4040e1a46bbSPeter Maydell         arm_feature(env, ARM_FEATURE_V8);
4050e1a46bbSPeter Maydell }
4060e1a46bbSPeter Maydell 
4070e1a46bbSPeter Maydell static const VMStateDescription vmstate_pmsav8 = {
4080e1a46bbSPeter Maydell     .name = "cpu/pmsav8",
4090e1a46bbSPeter Maydell     .version_id = 1,
4100e1a46bbSPeter Maydell     .minimum_version_id = 1,
4110e1a46bbSPeter Maydell     .needed = pmsav8_needed,
4120e1a46bbSPeter Maydell     .fields = (VMStateField[]) {
41362c58ee0SPeter Maydell         VMSTATE_VARRAY_UINT32(env.pmsav8.rbar[M_REG_NS], ARMCPU, pmsav7_dregion,
41462c58ee0SPeter Maydell                               0, vmstate_info_uint32, uint32_t),
41562c58ee0SPeter Maydell         VMSTATE_VARRAY_UINT32(env.pmsav8.rlar[M_REG_NS], ARMCPU, pmsav7_dregion,
41662c58ee0SPeter Maydell                               0, vmstate_info_uint32, uint32_t),
4174125e6feSPeter Maydell         VMSTATE_UINT32(env.pmsav8.mair0[M_REG_NS], ARMCPU),
4184125e6feSPeter Maydell         VMSTATE_UINT32(env.pmsav8.mair1[M_REG_NS], ARMCPU),
4190e1a46bbSPeter Maydell         VMSTATE_END_OF_LIST()
4200e1a46bbSPeter Maydell     }
4210e1a46bbSPeter Maydell };
4220e1a46bbSPeter Maydell 
4231bc04a88SPeter Maydell static bool s_rnr_vmstate_validate(void *opaque, int version_id)
4241bc04a88SPeter Maydell {
4251bc04a88SPeter Maydell     ARMCPU *cpu = opaque;
4261bc04a88SPeter Maydell 
4271bc04a88SPeter Maydell     return cpu->env.pmsav7.rnr[M_REG_S] < cpu->pmsav7_dregion;
4281bc04a88SPeter Maydell }
4291bc04a88SPeter Maydell 
4309901c576SPeter Maydell static bool sau_rnr_vmstate_validate(void *opaque, int version_id)
4319901c576SPeter Maydell {
4329901c576SPeter Maydell     ARMCPU *cpu = opaque;
4339901c576SPeter Maydell 
4349901c576SPeter Maydell     return cpu->env.sau.rnr < cpu->sau_sregion;
4359901c576SPeter Maydell }
4369901c576SPeter Maydell 
4371e577cc7SPeter Maydell static bool m_security_needed(void *opaque)
4381e577cc7SPeter Maydell {
4391e577cc7SPeter Maydell     ARMCPU *cpu = opaque;
4401e577cc7SPeter Maydell     CPUARMState *env = &cpu->env;
4411e577cc7SPeter Maydell 
4421e577cc7SPeter Maydell     return arm_feature(env, ARM_FEATURE_M_SECURITY);
4431e577cc7SPeter Maydell }
4441e577cc7SPeter Maydell 
4451e577cc7SPeter Maydell static const VMStateDescription vmstate_m_security = {
4461e577cc7SPeter Maydell     .name = "cpu/m-security",
4471e577cc7SPeter Maydell     .version_id = 1,
4481e577cc7SPeter Maydell     .minimum_version_id = 1,
4491e577cc7SPeter Maydell     .needed = m_security_needed,
4501e577cc7SPeter Maydell     .fields = (VMStateField[]) {
4511e577cc7SPeter Maydell         VMSTATE_UINT32(env.v7m.secure, ARMCPU),
452fb602cb7SPeter Maydell         VMSTATE_UINT32(env.v7m.other_ss_msp, ARMCPU),
453fb602cb7SPeter Maydell         VMSTATE_UINT32(env.v7m.other_ss_psp, ARMCPU),
454acf94941SPeter Maydell         VMSTATE_UINT32(env.v7m.basepri[M_REG_S], ARMCPU),
4556d804834SPeter Maydell         VMSTATE_UINT32(env.v7m.primask[M_REG_S], ARMCPU),
45642a6686bSPeter Maydell         VMSTATE_UINT32(env.v7m.faultmask[M_REG_S], ARMCPU),
4578bfc26eaSPeter Maydell         VMSTATE_UINT32(env.v7m.control[M_REG_S], ARMCPU),
45845db7ba6SPeter Maydell         VMSTATE_UINT32(env.v7m.vecbase[M_REG_S], ARMCPU),
4594125e6feSPeter Maydell         VMSTATE_UINT32(env.pmsav8.mair0[M_REG_S], ARMCPU),
4604125e6feSPeter Maydell         VMSTATE_UINT32(env.pmsav8.mair1[M_REG_S], ARMCPU),
46162c58ee0SPeter Maydell         VMSTATE_VARRAY_UINT32(env.pmsav8.rbar[M_REG_S], ARMCPU, pmsav7_dregion,
46262c58ee0SPeter Maydell                               0, vmstate_info_uint32, uint32_t),
46362c58ee0SPeter Maydell         VMSTATE_VARRAY_UINT32(env.pmsav8.rlar[M_REG_S], ARMCPU, pmsav7_dregion,
46462c58ee0SPeter Maydell                               0, vmstate_info_uint32, uint32_t),
4651bc04a88SPeter Maydell         VMSTATE_UINT32(env.pmsav7.rnr[M_REG_S], ARMCPU),
4661bc04a88SPeter Maydell         VMSTATE_VALIDATE("secure MPU_RNR is valid", s_rnr_vmstate_validate),
467ecf5e8eaSPeter Maydell         VMSTATE_UINT32(env.v7m.mpu_ctrl[M_REG_S], ARMCPU),
4689d40cd8aSPeter Maydell         VMSTATE_UINT32(env.v7m.ccr[M_REG_S], ARMCPU),
469c51a5cfcSPeter Maydell         VMSTATE_UINT32(env.v7m.mmfar[M_REG_S], ARMCPU),
470334e8dadSPeter Maydell         VMSTATE_UINT32(env.v7m.cfsr[M_REG_S], ARMCPU),
471bed079daSPeter Maydell         VMSTATE_UINT32(env.v7m.sfsr, ARMCPU),
472bed079daSPeter Maydell         VMSTATE_UINT32(env.v7m.sfar, ARMCPU),
4739901c576SPeter Maydell         VMSTATE_VARRAY_UINT32(env.sau.rbar, ARMCPU, sau_sregion, 0,
4749901c576SPeter Maydell                               vmstate_info_uint32, uint32_t),
4759901c576SPeter Maydell         VMSTATE_VARRAY_UINT32(env.sau.rlar, ARMCPU, sau_sregion, 0,
4769901c576SPeter Maydell                               vmstate_info_uint32, uint32_t),
4779901c576SPeter Maydell         VMSTATE_UINT32(env.sau.rnr, ARMCPU),
4789901c576SPeter Maydell         VMSTATE_VALIDATE("SAU_RNR is valid", sau_rnr_vmstate_validate),
4799901c576SPeter Maydell         VMSTATE_UINT32(env.sau.ctrl, ARMCPU),
48024ac0fb1SPeter Maydell         VMSTATE_UINT32(env.v7m.scr[M_REG_S], ARMCPU),
48147825770SPeter Maydell         /* AIRCR is not secure-only, but our implementation is R/O if the
48247825770SPeter Maydell          * security extension is unimplemented, so we migrate it here.
48347825770SPeter Maydell          */
48447825770SPeter Maydell         VMSTATE_UINT32(env.v7m.aircr, ARMCPU),
4851e577cc7SPeter Maydell         VMSTATE_END_OF_LIST()
4861e577cc7SPeter Maydell     }
4871e577cc7SPeter Maydell };
4881e577cc7SPeter Maydell 
4892c21ee76SJianjun Duan static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
4902c21ee76SJianjun Duan                     VMStateField *field)
491fcf5ef2aSThomas Huth {
492fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
493fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
494fcf5ef2aSThomas Huth     uint32_t val = qemu_get_be32(f);
495fcf5ef2aSThomas Huth 
496e6ae5981SPeter Maydell     if (arm_feature(env, ARM_FEATURE_M)) {
497eeade001SPeter Maydell         if (val & XPSR_EXCP) {
498eeade001SPeter Maydell             /* This is a CPSR format value from an older QEMU. (We can tell
499eeade001SPeter Maydell              * because values transferred in XPSR format always have zero
500eeade001SPeter Maydell              * for the EXCP field, and CPSR format will always have bit 4
501eeade001SPeter Maydell              * set in CPSR_M.) Rearrange it into XPSR format. The significant
502eeade001SPeter Maydell              * differences are that the T bit is not in the same place, the
503eeade001SPeter Maydell              * primask/faultmask info may be in the CPSR I and F bits, and
504eeade001SPeter Maydell              * we do not want the mode bits.
5056d804834SPeter Maydell              * We know that this cleanup happened before v8M, so there
5066d804834SPeter Maydell              * is no complication with banked primask/faultmask.
507eeade001SPeter Maydell              */
508eeade001SPeter Maydell             uint32_t newval = val;
509eeade001SPeter Maydell 
5106d804834SPeter Maydell             assert(!arm_feature(env, ARM_FEATURE_M_SECURITY));
5116d804834SPeter Maydell 
512eeade001SPeter Maydell             newval &= (CPSR_NZCV | CPSR_Q | CPSR_IT | CPSR_GE);
513eeade001SPeter Maydell             if (val & CPSR_T) {
514eeade001SPeter Maydell                 newval |= XPSR_T;
515eeade001SPeter Maydell             }
516e6ae5981SPeter Maydell             /* If the I or F bits are set then this is a migration from
517e6ae5981SPeter Maydell              * an old QEMU which still stored the M profile FAULTMASK
518eeade001SPeter Maydell              * and PRIMASK in env->daif. For a new QEMU, the data is
519eeade001SPeter Maydell              * transferred using the vmstate_m_faultmask_primask subsection.
520e6ae5981SPeter Maydell              */
521e6ae5981SPeter Maydell             if (val & CPSR_F) {
52242a6686bSPeter Maydell                 env->v7m.faultmask[M_REG_NS] = 1;
523e6ae5981SPeter Maydell             }
524e6ae5981SPeter Maydell             if (val & CPSR_I) {
5256d804834SPeter Maydell                 env->v7m.primask[M_REG_NS] = 1;
526e6ae5981SPeter Maydell             }
527eeade001SPeter Maydell             val = newval;
528eeade001SPeter Maydell         }
529eeade001SPeter Maydell         /* Ignore the low bits, they are handled by vmstate_m. */
530eeade001SPeter Maydell         xpsr_write(env, val, ~XPSR_EXCP);
531eeade001SPeter Maydell         return 0;
532e6ae5981SPeter Maydell     }
533e6ae5981SPeter Maydell 
534fcf5ef2aSThomas Huth     env->aarch64 = ((val & PSTATE_nRW) == 0);
535fcf5ef2aSThomas Huth 
536fcf5ef2aSThomas Huth     if (is_a64(env)) {
537fcf5ef2aSThomas Huth         pstate_write(env, val);
538fcf5ef2aSThomas Huth         return 0;
539fcf5ef2aSThomas Huth     }
540fcf5ef2aSThomas Huth 
541fcf5ef2aSThomas Huth     cpsr_write(env, val, 0xffffffff, CPSRWriteRaw);
542fcf5ef2aSThomas Huth     return 0;
543fcf5ef2aSThomas Huth }
544fcf5ef2aSThomas Huth 
5452c21ee76SJianjun Duan static int put_cpsr(QEMUFile *f, void *opaque, size_t size,
5462c21ee76SJianjun Duan                     VMStateField *field, QJSON *vmdesc)
547fcf5ef2aSThomas Huth {
548fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
549fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
550fcf5ef2aSThomas Huth     uint32_t val;
551fcf5ef2aSThomas Huth 
552eeade001SPeter Maydell     if (arm_feature(env, ARM_FEATURE_M)) {
553eeade001SPeter Maydell         /* The low 9 bits are v7m.exception, which is handled by vmstate_m. */
554eeade001SPeter Maydell         val = xpsr_read(env) & ~XPSR_EXCP;
555eeade001SPeter Maydell     } else if (is_a64(env)) {
556fcf5ef2aSThomas Huth         val = pstate_read(env);
557fcf5ef2aSThomas Huth     } else {
558fcf5ef2aSThomas Huth         val = cpsr_read(env);
559fcf5ef2aSThomas Huth     }
560fcf5ef2aSThomas Huth 
561fcf5ef2aSThomas Huth     qemu_put_be32(f, val);
5622c21ee76SJianjun Duan     return 0;
563fcf5ef2aSThomas Huth }
564fcf5ef2aSThomas Huth 
565fcf5ef2aSThomas Huth static const VMStateInfo vmstate_cpsr = {
566fcf5ef2aSThomas Huth     .name = "cpsr",
567fcf5ef2aSThomas Huth     .get = get_cpsr,
568fcf5ef2aSThomas Huth     .put = put_cpsr,
569fcf5ef2aSThomas Huth };
570fcf5ef2aSThomas Huth 
571062ba099SAlex Bennée static int get_power(QEMUFile *f, void *opaque, size_t size,
572062ba099SAlex Bennée                     VMStateField *field)
573062ba099SAlex Bennée {
574062ba099SAlex Bennée     ARMCPU *cpu = opaque;
575062ba099SAlex Bennée     bool powered_off = qemu_get_byte(f);
576062ba099SAlex Bennée     cpu->power_state = powered_off ? PSCI_OFF : PSCI_ON;
577062ba099SAlex Bennée     return 0;
578062ba099SAlex Bennée }
579062ba099SAlex Bennée 
580062ba099SAlex Bennée static int put_power(QEMUFile *f, void *opaque, size_t size,
581062ba099SAlex Bennée                     VMStateField *field, QJSON *vmdesc)
582062ba099SAlex Bennée {
583062ba099SAlex Bennée     ARMCPU *cpu = opaque;
584062ba099SAlex Bennée 
585062ba099SAlex Bennée     /* Migration should never happen while we transition power states */
586062ba099SAlex Bennée 
587062ba099SAlex Bennée     if (cpu->power_state == PSCI_ON ||
588062ba099SAlex Bennée         cpu->power_state == PSCI_OFF) {
589062ba099SAlex Bennée         bool powered_off = (cpu->power_state == PSCI_OFF) ? true : false;
590062ba099SAlex Bennée         qemu_put_byte(f, powered_off);
591062ba099SAlex Bennée         return 0;
592062ba099SAlex Bennée     } else {
593062ba099SAlex Bennée         return 1;
594062ba099SAlex Bennée     }
595062ba099SAlex Bennée }
596062ba099SAlex Bennée 
597062ba099SAlex Bennée static const VMStateInfo vmstate_powered_off = {
598062ba099SAlex Bennée     .name = "powered_off",
599062ba099SAlex Bennée     .get = get_power,
600062ba099SAlex Bennée     .put = put_power,
601062ba099SAlex Bennée };
602062ba099SAlex Bennée 
60344b1ff31SDr. David Alan Gilbert static int cpu_pre_save(void *opaque)
604fcf5ef2aSThomas Huth {
605fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
606fcf5ef2aSThomas Huth 
607fcf5ef2aSThomas Huth     if (kvm_enabled()) {
608fcf5ef2aSThomas Huth         if (!write_kvmstate_to_list(cpu)) {
609fcf5ef2aSThomas Huth             /* This should never fail */
610fcf5ef2aSThomas Huth             abort();
611fcf5ef2aSThomas Huth         }
612fcf5ef2aSThomas Huth     } else {
613fcf5ef2aSThomas Huth         if (!write_cpustate_to_list(cpu)) {
614fcf5ef2aSThomas Huth             /* This should never fail. */
615fcf5ef2aSThomas Huth             abort();
616fcf5ef2aSThomas Huth         }
617fcf5ef2aSThomas Huth     }
618fcf5ef2aSThomas Huth 
619fcf5ef2aSThomas Huth     cpu->cpreg_vmstate_array_len = cpu->cpreg_array_len;
620fcf5ef2aSThomas Huth     memcpy(cpu->cpreg_vmstate_indexes, cpu->cpreg_indexes,
621fcf5ef2aSThomas Huth            cpu->cpreg_array_len * sizeof(uint64_t));
622fcf5ef2aSThomas Huth     memcpy(cpu->cpreg_vmstate_values, cpu->cpreg_values,
623fcf5ef2aSThomas Huth            cpu->cpreg_array_len * sizeof(uint64_t));
62444b1ff31SDr. David Alan Gilbert 
62544b1ff31SDr. David Alan Gilbert     return 0;
626fcf5ef2aSThomas Huth }
627fcf5ef2aSThomas Huth 
628fcf5ef2aSThomas Huth static int cpu_post_load(void *opaque, int version_id)
629fcf5ef2aSThomas Huth {
630fcf5ef2aSThomas Huth     ARMCPU *cpu = opaque;
631fcf5ef2aSThomas Huth     int i, v;
632fcf5ef2aSThomas Huth 
633fcf5ef2aSThomas Huth     /* Update the values list from the incoming migration data.
634fcf5ef2aSThomas Huth      * Anything in the incoming data which we don't know about is
635fcf5ef2aSThomas Huth      * a migration failure; anything we know about but the incoming
636fcf5ef2aSThomas Huth      * data doesn't specify retains its current (reset) value.
637fcf5ef2aSThomas Huth      * The indexes list remains untouched -- we only inspect the
638fcf5ef2aSThomas Huth      * incoming migration index list so we can match the values array
639fcf5ef2aSThomas Huth      * entries with the right slots in our own values array.
640fcf5ef2aSThomas Huth      */
641fcf5ef2aSThomas Huth 
642fcf5ef2aSThomas Huth     for (i = 0, v = 0; i < cpu->cpreg_array_len
643fcf5ef2aSThomas Huth              && v < cpu->cpreg_vmstate_array_len; i++) {
644fcf5ef2aSThomas Huth         if (cpu->cpreg_vmstate_indexes[v] > cpu->cpreg_indexes[i]) {
645fcf5ef2aSThomas Huth             /* register in our list but not incoming : skip it */
646fcf5ef2aSThomas Huth             continue;
647fcf5ef2aSThomas Huth         }
648fcf5ef2aSThomas Huth         if (cpu->cpreg_vmstate_indexes[v] < cpu->cpreg_indexes[i]) {
649fcf5ef2aSThomas Huth             /* register in their list but not ours: fail migration */
650fcf5ef2aSThomas Huth             return -1;
651fcf5ef2aSThomas Huth         }
652fcf5ef2aSThomas Huth         /* matching register, copy the value over */
653fcf5ef2aSThomas Huth         cpu->cpreg_values[i] = cpu->cpreg_vmstate_values[v];
654fcf5ef2aSThomas Huth         v++;
655fcf5ef2aSThomas Huth     }
656fcf5ef2aSThomas Huth 
657fcf5ef2aSThomas Huth     if (kvm_enabled()) {
658fcf5ef2aSThomas Huth         if (!write_list_to_kvmstate(cpu, KVM_PUT_FULL_STATE)) {
659fcf5ef2aSThomas Huth             return -1;
660fcf5ef2aSThomas Huth         }
661fcf5ef2aSThomas Huth         /* Note that it's OK for the TCG side not to know about
662fcf5ef2aSThomas Huth          * every register in the list; KVM is authoritative if
663fcf5ef2aSThomas Huth          * we're using it.
664fcf5ef2aSThomas Huth          */
665fcf5ef2aSThomas Huth         write_list_to_cpustate(cpu);
666fcf5ef2aSThomas Huth     } else {
667fcf5ef2aSThomas Huth         if (!write_list_to_cpustate(cpu)) {
668fcf5ef2aSThomas Huth             return -1;
669fcf5ef2aSThomas Huth         }
670fcf5ef2aSThomas Huth     }
671fcf5ef2aSThomas Huth 
672fcf5ef2aSThomas Huth     hw_breakpoint_update_all(cpu);
673fcf5ef2aSThomas Huth     hw_watchpoint_update_all(cpu);
674fcf5ef2aSThomas Huth 
675fcf5ef2aSThomas Huth     return 0;
676fcf5ef2aSThomas Huth }
677fcf5ef2aSThomas Huth 
678fcf5ef2aSThomas Huth const VMStateDescription vmstate_arm_cpu = {
679fcf5ef2aSThomas Huth     .name = "cpu",
680fcf5ef2aSThomas Huth     .version_id = 22,
681fcf5ef2aSThomas Huth     .minimum_version_id = 22,
682fcf5ef2aSThomas Huth     .pre_save = cpu_pre_save,
683fcf5ef2aSThomas Huth     .post_load = cpu_post_load,
684fcf5ef2aSThomas Huth     .fields = (VMStateField[]) {
685fcf5ef2aSThomas Huth         VMSTATE_UINT32_ARRAY(env.regs, ARMCPU, 16),
686fcf5ef2aSThomas Huth         VMSTATE_UINT64_ARRAY(env.xregs, ARMCPU, 32),
687fcf5ef2aSThomas Huth         VMSTATE_UINT64(env.pc, ARMCPU),
688fcf5ef2aSThomas Huth         {
689fcf5ef2aSThomas Huth             .name = "cpsr",
690fcf5ef2aSThomas Huth             .version_id = 0,
691fcf5ef2aSThomas Huth             .size = sizeof(uint32_t),
692fcf5ef2aSThomas Huth             .info = &vmstate_cpsr,
693fcf5ef2aSThomas Huth             .flags = VMS_SINGLE,
694fcf5ef2aSThomas Huth             .offset = 0,
695fcf5ef2aSThomas Huth         },
696fcf5ef2aSThomas Huth         VMSTATE_UINT32(env.spsr, ARMCPU),
697fcf5ef2aSThomas Huth         VMSTATE_UINT64_ARRAY(env.banked_spsr, ARMCPU, 8),
698fcf5ef2aSThomas Huth         VMSTATE_UINT32_ARRAY(env.banked_r13, ARMCPU, 8),
699fcf5ef2aSThomas Huth         VMSTATE_UINT32_ARRAY(env.banked_r14, ARMCPU, 8),
700fcf5ef2aSThomas Huth         VMSTATE_UINT32_ARRAY(env.usr_regs, ARMCPU, 5),
701fcf5ef2aSThomas Huth         VMSTATE_UINT32_ARRAY(env.fiq_regs, ARMCPU, 5),
702fcf5ef2aSThomas Huth         VMSTATE_UINT64_ARRAY(env.elr_el, ARMCPU, 4),
703fcf5ef2aSThomas Huth         VMSTATE_UINT64_ARRAY(env.sp_el, ARMCPU, 4),
704fcf5ef2aSThomas Huth         /* The length-check must come before the arrays to avoid
705fcf5ef2aSThomas Huth          * incoming data possibly overflowing the array.
706fcf5ef2aSThomas Huth          */
707fcf5ef2aSThomas Huth         VMSTATE_INT32_POSITIVE_LE(cpreg_vmstate_array_len, ARMCPU),
708fcf5ef2aSThomas Huth         VMSTATE_VARRAY_INT32(cpreg_vmstate_indexes, ARMCPU,
709fcf5ef2aSThomas Huth                              cpreg_vmstate_array_len,
710fcf5ef2aSThomas Huth                              0, vmstate_info_uint64, uint64_t),
711fcf5ef2aSThomas Huth         VMSTATE_VARRAY_INT32(cpreg_vmstate_values, ARMCPU,
712fcf5ef2aSThomas Huth                              cpreg_vmstate_array_len,
713fcf5ef2aSThomas Huth                              0, vmstate_info_uint64, uint64_t),
714fcf5ef2aSThomas Huth         VMSTATE_UINT64(env.exclusive_addr, ARMCPU),
715fcf5ef2aSThomas Huth         VMSTATE_UINT64(env.exclusive_val, ARMCPU),
716fcf5ef2aSThomas Huth         VMSTATE_UINT64(env.exclusive_high, ARMCPU),
717fcf5ef2aSThomas Huth         VMSTATE_UINT64(env.features, ARMCPU),
718fcf5ef2aSThomas Huth         VMSTATE_UINT32(env.exception.syndrome, ARMCPU),
719fcf5ef2aSThomas Huth         VMSTATE_UINT32(env.exception.fsr, ARMCPU),
720fcf5ef2aSThomas Huth         VMSTATE_UINT64(env.exception.vaddress, ARMCPU),
721fcf5ef2aSThomas Huth         VMSTATE_TIMER_PTR(gt_timer[GTIMER_PHYS], ARMCPU),
722fcf5ef2aSThomas Huth         VMSTATE_TIMER_PTR(gt_timer[GTIMER_VIRT], ARMCPU),
723062ba099SAlex Bennée         {
724062ba099SAlex Bennée             .name = "power_state",
725062ba099SAlex Bennée             .version_id = 0,
726062ba099SAlex Bennée             .size = sizeof(bool),
727062ba099SAlex Bennée             .info = &vmstate_powered_off,
728062ba099SAlex Bennée             .flags = VMS_SINGLE,
729062ba099SAlex Bennée             .offset = 0,
730062ba099SAlex Bennée         },
731fcf5ef2aSThomas Huth         VMSTATE_END_OF_LIST()
732fcf5ef2aSThomas Huth     },
733fcf5ef2aSThomas Huth     .subsections = (const VMStateDescription*[]) {
734fcf5ef2aSThomas Huth         &vmstate_vfp,
735fcf5ef2aSThomas Huth         &vmstate_iwmmxt,
736fcf5ef2aSThomas Huth         &vmstate_m,
737fcf5ef2aSThomas Huth         &vmstate_thumb2ee,
738f1a46940SPeter Maydell         /* pmsav7_rnr must come before pmsav7 so that we have the
739f1a46940SPeter Maydell          * region number before we test it in the VMSTATE_VALIDATE
740f1a46940SPeter Maydell          * in vmstate_pmsav7.
741f1a46940SPeter Maydell          */
742f1a46940SPeter Maydell         &vmstate_pmsav7_rnr,
743fcf5ef2aSThomas Huth         &vmstate_pmsav7,
7440e1a46bbSPeter Maydell         &vmstate_pmsav8,
7451e577cc7SPeter Maydell         &vmstate_m_security,
746ef401601SRichard Henderson #ifdef TARGET_AARCH64
747ef401601SRichard Henderson         &vmstate_sve,
748ef401601SRichard Henderson #endif
749202ccb6bSDongjiu Geng         &vmstate_serror,
750fcf5ef2aSThomas Huth         NULL
751fcf5ef2aSThomas Huth     }
752fcf5ef2aSThomas Huth };
753