]> Git Repo - qemu.git/blob - target-arm/machine.c
spapr_vscsi: Fix REPORT_LUNS handling
[qemu.git] / target-arm / machine.c
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 = 3,
41     .minimum_version_id = 3,
42     .minimum_version_id_old = 3,
43     .fields = (VMStateField[]) {
44         VMSTATE_FLOAT64_ARRAY(env.vfp.regs, ARMCPU, 64),
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 = 14,
226     .minimum_version_id = 14,
227     .minimum_version_id_old = 14,
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_UINT64(env.exclusive_addr, ARMCPU),
257         VMSTATE_UINT64(env.exclusive_val, ARMCPU),
258         VMSTATE_UINT64(env.exclusive_high, ARMCPU),
259         VMSTATE_UINT64(env.features, ARMCPU),
260         VMSTATE_TIMER(gt_timer[GTIMER_PHYS], ARMCPU),
261         VMSTATE_TIMER(gt_timer[GTIMER_VIRT], ARMCPU),
262         VMSTATE_END_OF_LIST()
263     },
264     .subsections = (VMStateSubsection[]) {
265         {
266             .vmsd = &vmstate_vfp,
267             .needed = vfp_needed,
268         } , {
269             .vmsd = &vmstate_iwmmxt,
270             .needed = iwmmxt_needed,
271         } , {
272             .vmsd = &vmstate_m,
273             .needed = m_needed,
274         } , {
275             .vmsd = &vmstate_thumb2ee,
276             .needed = thumb2ee_needed,
277         } , {
278             /* empty */
279         }
280     }
281 };
This page took 0.040462 seconds and 4 git commands to generate.