root / target-arm / machine.c @ 14a10fc3
History | View | Annotate | Download (7.8 kB)
1 |
#include "hw/hw.h" |
---|---|
2 |
#include "hw/boards.h" |
3 |
#include "sysemu/kvm.h" |
4 |
#include "kvm_arm.h" |
5 |
|
6 |
static bool vfp_needed(void *opaque) |
7 |
{ |
8 |
ARMCPU *cpu = opaque; |
9 |
CPUARMState *env = &cpu->env; |
10 |
|
11 |
return arm_feature(env, ARM_FEATURE_VFP);
|
12 |
} |
13 |
|
14 |
static int get_fpscr(QEMUFile *f, void *opaque, size_t size) |
15 |
{ |
16 |
ARMCPU *cpu = opaque; |
17 |
CPUARMState *env = &cpu->env; |
18 |
uint32_t val = qemu_get_be32(f); |
19 |
|
20 |
vfp_set_fpscr(env, val); |
21 |
return 0; |
22 |
} |
23 |
|
24 |
static void put_fpscr(QEMUFile *f, void *opaque, size_t size) |
25 |
{ |
26 |
ARMCPU *cpu = opaque; |
27 |
CPUARMState *env = &cpu->env; |
28 |
|
29 |
qemu_put_be32(f, vfp_get_fpscr(env)); |
30 |
} |
31 |
|
32 |
static const VMStateInfo vmstate_fpscr = { |
33 |
.name = "fpscr",
|
34 |
.get = get_fpscr, |
35 |
.put = put_fpscr, |
36 |
}; |
37 |
|
38 |
static const VMStateDescription vmstate_vfp = { |
39 |
.name = "cpu/vfp",
|
40 |
.version_id = 2,
|
41 |
.minimum_version_id = 2,
|
42 |
.minimum_version_id_old = 2,
|
43 |
.fields = (VMStateField[]) { |
44 |
VMSTATE_FLOAT64_ARRAY(env.vfp.regs, ARMCPU, 32),
|
45 |
/* The xregs array is a little awkward because element 1 (FPSCR)
|
46 |
* requires a specific accessor, so we have to split it up in
|
47 |
* the vmstate:
|
48 |
*/
|
49 |
VMSTATE_UINT32(env.vfp.xregs[0], ARMCPU),
|
50 |
VMSTATE_UINT32_SUB_ARRAY(env.vfp.xregs, ARMCPU, 2, 14), |
51 |
{ |
52 |
.name = "fpscr",
|
53 |
.version_id = 0,
|
54 |
.size = sizeof(uint32_t),
|
55 |
.info = &vmstate_fpscr, |
56 |
.flags = VMS_SINGLE, |
57 |
.offset = 0,
|
58 |
}, |
59 |
VMSTATE_END_OF_LIST() |
60 |
} |
61 |
}; |
62 |
|
63 |
static bool iwmmxt_needed(void *opaque) |
64 |
{ |
65 |
ARMCPU *cpu = opaque; |
66 |
CPUARMState *env = &cpu->env; |
67 |
|
68 |
return arm_feature(env, ARM_FEATURE_IWMMXT);
|
69 |
} |
70 |
|
71 |
static const VMStateDescription vmstate_iwmmxt = { |
72 |
.name = "cpu/iwmmxt",
|
73 |
.version_id = 1,
|
74 |
.minimum_version_id = 1,
|
75 |
.minimum_version_id_old = 1,
|
76 |
.fields = (VMStateField[]) { |
77 |
VMSTATE_UINT64_ARRAY(env.iwmmxt.regs, ARMCPU, 16),
|
78 |
VMSTATE_UINT32_ARRAY(env.iwmmxt.cregs, ARMCPU, 16),
|
79 |
VMSTATE_END_OF_LIST() |
80 |
} |
81 |
}; |
82 |
|
83 |
static bool m_needed(void *opaque) |
84 |
{ |
85 |
ARMCPU *cpu = opaque; |
86 |
CPUARMState *env = &cpu->env; |
87 |
|
88 |
return arm_feature(env, ARM_FEATURE_M);
|
89 |
} |
90 |
|
91 |
const VMStateDescription vmstate_m = {
|
92 |
.name = "cpu/m",
|
93 |
.version_id = 1,
|
94 |
.minimum_version_id = 1,
|
95 |
.minimum_version_id_old = 1,
|
96 |
.fields = (VMStateField[]) { |
97 |
VMSTATE_UINT32(env.v7m.other_sp, ARMCPU), |
98 |
VMSTATE_UINT32(env.v7m.vecbase, ARMCPU), |
99 |
VMSTATE_UINT32(env.v7m.basepri, ARMCPU), |
100 |
VMSTATE_UINT32(env.v7m.control, ARMCPU), |
101 |
VMSTATE_INT32(env.v7m.current_sp, ARMCPU), |
102 |
VMSTATE_INT32(env.v7m.exception, ARMCPU), |
103 |
VMSTATE_END_OF_LIST() |
104 |
} |
105 |
}; |
106 |
|
107 |
static bool thumb2ee_needed(void *opaque) |
108 |
{ |
109 |
ARMCPU *cpu = opaque; |
110 |
CPUARMState *env = &cpu->env; |
111 |
|
112 |
return arm_feature(env, ARM_FEATURE_THUMB2EE);
|
113 |
} |
114 |
|
115 |
static const VMStateDescription vmstate_thumb2ee = { |
116 |
.name = "cpu/thumb2ee",
|
117 |
.version_id = 1,
|
118 |
.minimum_version_id = 1,
|
119 |
.minimum_version_id_old = 1,
|
120 |
.fields = (VMStateField[]) { |
121 |
VMSTATE_UINT32(env.teecr, ARMCPU), |
122 |
VMSTATE_UINT32(env.teehbr, ARMCPU), |
123 |
VMSTATE_END_OF_LIST() |
124 |
} |
125 |
}; |
126 |
|
127 |
static int get_cpsr(QEMUFile *f, void *opaque, size_t size) |
128 |
{ |
129 |
ARMCPU *cpu = opaque; |
130 |
CPUARMState *env = &cpu->env; |
131 |
uint32_t val = qemu_get_be32(f); |
132 |
|
133 |
/* Avoid mode switch when restoring CPSR */
|
134 |
env->uncached_cpsr = val & CPSR_M; |
135 |
cpsr_write(env, val, 0xffffffff);
|
136 |
return 0; |
137 |
} |
138 |
|
139 |
static void put_cpsr(QEMUFile *f, void *opaque, size_t size) |
140 |
{ |
141 |
ARMCPU *cpu = opaque; |
142 |
CPUARMState *env = &cpu->env; |
143 |
|
144 |
qemu_put_be32(f, cpsr_read(env)); |
145 |
} |
146 |
|
147 |
static const VMStateInfo vmstate_cpsr = { |
148 |
.name = "cpsr",
|
149 |
.get = get_cpsr, |
150 |
.put = put_cpsr, |
151 |
}; |
152 |
|
153 |
static void cpu_pre_save(void *opaque) |
154 |
{ |
155 |
ARMCPU *cpu = opaque; |
156 |
|
157 |
if (kvm_enabled()) {
|
158 |
if (!write_kvmstate_to_list(cpu)) {
|
159 |
/* This should never fail */
|
160 |
abort(); |
161 |
} |
162 |
} else {
|
163 |
if (!write_cpustate_to_list(cpu)) {
|
164 |
/* This should never fail. */
|
165 |
abort(); |
166 |
} |
167 |
} |
168 |
|
169 |
cpu->cpreg_vmstate_array_len = cpu->cpreg_array_len; |
170 |
memcpy(cpu->cpreg_vmstate_indexes, cpu->cpreg_indexes, |
171 |
cpu->cpreg_array_len * sizeof(uint64_t));
|
172 |
memcpy(cpu->cpreg_vmstate_values, cpu->cpreg_values, |
173 |
cpu->cpreg_array_len * sizeof(uint64_t));
|
174 |
} |
175 |
|
176 |
static int cpu_post_load(void *opaque, int version_id) |
177 |
{ |
178 |
ARMCPU *cpu = opaque; |
179 |
int i, v;
|
180 |
|
181 |
/* Update the values list from the incoming migration data.
|
182 |
* Anything in the incoming data which we don't know about is
|
183 |
* a migration failure; anything we know about but the incoming
|
184 |
* data doesn't specify retains its current (reset) value.
|
185 |
* The indexes list remains untouched -- we only inspect the
|
186 |
* incoming migration index list so we can match the values array
|
187 |
* entries with the right slots in our own values array.
|
188 |
*/
|
189 |
|
190 |
for (i = 0, v = 0; i < cpu->cpreg_array_len |
191 |
&& v < cpu->cpreg_vmstate_array_len; i++) { |
192 |
if (cpu->cpreg_vmstate_indexes[v] > cpu->cpreg_indexes[i]) {
|
193 |
/* register in our list but not incoming : skip it */
|
194 |
continue;
|
195 |
} |
196 |
if (cpu->cpreg_vmstate_indexes[v] < cpu->cpreg_indexes[i]) {
|
197 |
/* register in their list but not ours: fail migration */
|
198 |
return -1; |
199 |
} |
200 |
/* matching register, copy the value over */
|
201 |
cpu->cpreg_values[i] = cpu->cpreg_vmstate_values[v]; |
202 |
v++; |
203 |
} |
204 |
|
205 |
if (kvm_enabled()) {
|
206 |
if (!write_list_to_kvmstate(cpu)) {
|
207 |
return -1; |
208 |
} |
209 |
/* Note that it's OK for the TCG side not to know about
|
210 |
* every register in the list; KVM is authoritative if
|
211 |
* we're using it.
|
212 |
*/
|
213 |
write_list_to_cpustate(cpu); |
214 |
} else {
|
215 |
if (!write_list_to_cpustate(cpu)) {
|
216 |
return -1; |
217 |
} |
218 |
} |
219 |
|
220 |
return 0; |
221 |
} |
222 |
|
223 |
const VMStateDescription vmstate_arm_cpu = {
|
224 |
.name = "cpu",
|
225 |
.version_id = 12,
|
226 |
.minimum_version_id = 12,
|
227 |
.minimum_version_id_old = 12,
|
228 |
.pre_save = cpu_pre_save, |
229 |
.post_load = cpu_post_load, |
230 |
.fields = (VMStateField[]) { |
231 |
VMSTATE_UINT32_ARRAY(env.regs, ARMCPU, 16),
|
232 |
{ |
233 |
.name = "cpsr",
|
234 |
.version_id = 0,
|
235 |
.size = sizeof(uint32_t),
|
236 |
.info = &vmstate_cpsr, |
237 |
.flags = VMS_SINGLE, |
238 |
.offset = 0,
|
239 |
}, |
240 |
VMSTATE_UINT32(env.spsr, ARMCPU), |
241 |
VMSTATE_UINT32_ARRAY(env.banked_spsr, ARMCPU, 6),
|
242 |
VMSTATE_UINT32_ARRAY(env.banked_r13, ARMCPU, 6),
|
243 |
VMSTATE_UINT32_ARRAY(env.banked_r14, ARMCPU, 6),
|
244 |
VMSTATE_UINT32_ARRAY(env.usr_regs, ARMCPU, 5),
|
245 |
VMSTATE_UINT32_ARRAY(env.fiq_regs, ARMCPU, 5),
|
246 |
/* The length-check must come before the arrays to avoid
|
247 |
* incoming data possibly overflowing the array.
|
248 |
*/
|
249 |
VMSTATE_INT32_LE(cpreg_vmstate_array_len, ARMCPU), |
250 |
VMSTATE_VARRAY_INT32(cpreg_vmstate_indexes, ARMCPU, |
251 |
cpreg_vmstate_array_len, |
252 |
0, vmstate_info_uint64, uint64_t),
|
253 |
VMSTATE_VARRAY_INT32(cpreg_vmstate_values, ARMCPU, |
254 |
cpreg_vmstate_array_len, |
255 |
0, vmstate_info_uint64, uint64_t),
|
256 |
VMSTATE_UINT32(env.exclusive_addr, ARMCPU), |
257 |
VMSTATE_UINT32(env.exclusive_val, ARMCPU), |
258 |
VMSTATE_UINT32(env.exclusive_high, ARMCPU), |
259 |
VMSTATE_UINT64(env.features, ARMCPU), |
260 |
VMSTATE_END_OF_LIST() |
261 |
}, |
262 |
.subsections = (VMStateSubsection[]) { |
263 |
{ |
264 |
.vmsd = &vmstate_vfp, |
265 |
.needed = vfp_needed, |
266 |
} , { |
267 |
.vmsd = &vmstate_iwmmxt, |
268 |
.needed = iwmmxt_needed, |
269 |
} , { |
270 |
.vmsd = &vmstate_m, |
271 |
.needed = m_needed, |
272 |
} , { |
273 |
.vmsd = &vmstate_thumb2ee, |
274 |
.needed = thumb2ee_needed, |
275 |
} , { |
276 |
/* empty */
|
277 |
} |
278 |
} |
279 |
}; |