~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to target/arm/machine.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "qemu/osdep.h"
 
2
#include "qemu-common.h"
 
3
#include "cpu.h"
 
4
#include "hw/hw.h"
 
5
#include "hw/boards.h"
 
6
#include "qemu/error-report.h"
 
7
#include "sysemu/kvm.h"
 
8
#include "kvm_arm.h"
 
9
#include "internals.h"
 
10
#include "migration/cpu.h"
 
11
 
 
12
static bool vfp_needed(void *opaque)
 
13
{
 
14
    ARMCPU *cpu = opaque;
 
15
    CPUARMState *env = &cpu->env;
 
16
 
 
17
    return arm_feature(env, ARM_FEATURE_VFP);
 
18
}
 
19
 
 
20
static int get_fpscr(QEMUFile *f, void *opaque, size_t size,
 
21
                     VMStateField *field)
 
22
{
 
23
    ARMCPU *cpu = opaque;
 
24
    CPUARMState *env = &cpu->env;
 
25
    uint32_t val = qemu_get_be32(f);
 
26
 
 
27
    vfp_set_fpscr(env, val);
 
28
    return 0;
 
29
}
 
30
 
 
31
static int put_fpscr(QEMUFile *f, void *opaque, size_t size,
 
32
                     VMStateField *field, QJSON *vmdesc)
 
33
{
 
34
    ARMCPU *cpu = opaque;
 
35
    CPUARMState *env = &cpu->env;
 
36
 
 
37
    qemu_put_be32(f, vfp_get_fpscr(env));
 
38
    return 0;
 
39
}
 
40
 
 
41
static const VMStateInfo vmstate_fpscr = {
 
42
    .name = "fpscr",
 
43
    .get = get_fpscr,
 
44
    .put = put_fpscr,
 
45
};
 
46
 
 
47
static const VMStateDescription vmstate_vfp = {
 
48
    .name = "cpu/vfp",
 
49
    .version_id = 3,
 
50
    .minimum_version_id = 3,
 
51
    .needed = vfp_needed,
 
52
    .fields = (VMStateField[]) {
 
53
        VMSTATE_FLOAT64_ARRAY(env.vfp.regs, ARMCPU, 64),
 
54
        /* The xregs array is a little awkward because element 1 (FPSCR)
 
55
         * requires a specific accessor, so we have to split it up in
 
56
         * the vmstate:
 
57
         */
 
58
        VMSTATE_UINT32(env.vfp.xregs[0], ARMCPU),
 
59
        VMSTATE_UINT32_SUB_ARRAY(env.vfp.xregs, ARMCPU, 2, 14),
 
60
        {
 
61
            .name = "fpscr",
 
62
            .version_id = 0,
 
63
            .size = sizeof(uint32_t),
 
64
            .info = &vmstate_fpscr,
 
65
            .flags = VMS_SINGLE,
 
66
            .offset = 0,
 
67
        },
 
68
        VMSTATE_END_OF_LIST()
 
69
    }
 
70
};
 
71
 
 
72
static bool iwmmxt_needed(void *opaque)
 
73
{
 
74
    ARMCPU *cpu = opaque;
 
75
    CPUARMState *env = &cpu->env;
 
76
 
 
77
    return arm_feature(env, ARM_FEATURE_IWMMXT);
 
78
}
 
79
 
 
80
static const VMStateDescription vmstate_iwmmxt = {
 
81
    .name = "cpu/iwmmxt",
 
82
    .version_id = 1,
 
83
    .minimum_version_id = 1,
 
84
    .needed = iwmmxt_needed,
 
85
    .fields = (VMStateField[]) {
 
86
        VMSTATE_UINT64_ARRAY(env.iwmmxt.regs, ARMCPU, 16),
 
87
        VMSTATE_UINT32_ARRAY(env.iwmmxt.cregs, ARMCPU, 16),
 
88
        VMSTATE_END_OF_LIST()
 
89
    }
 
90
};
 
91
 
 
92
static bool m_needed(void *opaque)
 
93
{
 
94
    ARMCPU *cpu = opaque;
 
95
    CPUARMState *env = &cpu->env;
 
96
 
 
97
    return arm_feature(env, ARM_FEATURE_M);
 
98
}
 
99
 
 
100
static const VMStateDescription vmstate_m = {
 
101
    .name = "cpu/m",
 
102
    .version_id = 3,
 
103
    .minimum_version_id = 3,
 
104
    .needed = m_needed,
 
105
    .fields = (VMStateField[]) {
 
106
        VMSTATE_UINT32(env.v7m.vecbase, ARMCPU),
 
107
        VMSTATE_UINT32(env.v7m.basepri, ARMCPU),
 
108
        VMSTATE_UINT32(env.v7m.control, ARMCPU),
 
109
        VMSTATE_UINT32(env.v7m.ccr, ARMCPU),
 
110
        VMSTATE_UINT32(env.v7m.cfsr, ARMCPU),
 
111
        VMSTATE_UINT32(env.v7m.hfsr, ARMCPU),
 
112
        VMSTATE_UINT32(env.v7m.dfsr, ARMCPU),
 
113
        VMSTATE_UINT32(env.v7m.mmfar, ARMCPU),
 
114
        VMSTATE_UINT32(env.v7m.bfar, ARMCPU),
 
115
        VMSTATE_INT32(env.v7m.exception, ARMCPU),
 
116
        VMSTATE_END_OF_LIST()
 
117
    }
 
118
};
 
119
 
 
120
static bool thumb2ee_needed(void *opaque)
 
121
{
 
122
    ARMCPU *cpu = opaque;
 
123
    CPUARMState *env = &cpu->env;
 
124
 
 
125
    return arm_feature(env, ARM_FEATURE_THUMB2EE);
 
126
}
 
127
 
 
128
static const VMStateDescription vmstate_thumb2ee = {
 
129
    .name = "cpu/thumb2ee",
 
130
    .version_id = 1,
 
131
    .minimum_version_id = 1,
 
132
    .needed = thumb2ee_needed,
 
133
    .fields = (VMStateField[]) {
 
134
        VMSTATE_UINT32(env.teecr, ARMCPU),
 
135
        VMSTATE_UINT32(env.teehbr, ARMCPU),
 
136
        VMSTATE_END_OF_LIST()
 
137
    }
 
138
};
 
139
 
 
140
static bool pmsav7_needed(void *opaque)
 
141
{
 
142
    ARMCPU *cpu = opaque;
 
143
    CPUARMState *env = &cpu->env;
 
144
 
 
145
    return arm_feature(env, ARM_FEATURE_MPU) &&
 
146
           arm_feature(env, ARM_FEATURE_V7);
 
147
}
 
148
 
 
149
static bool pmsav7_rgnr_vmstate_validate(void *opaque, int version_id)
 
150
{
 
151
    ARMCPU *cpu = opaque;
 
152
 
 
153
    return cpu->env.cp15.c6_rgnr < cpu->pmsav7_dregion;
 
154
}
 
155
 
 
156
static const VMStateDescription vmstate_pmsav7 = {
 
157
    .name = "cpu/pmsav7",
 
158
    .version_id = 1,
 
159
    .minimum_version_id = 1,
 
160
    .needed = pmsav7_needed,
 
161
    .fields = (VMStateField[]) {
 
162
        VMSTATE_VARRAY_UINT32(env.pmsav7.drbar, ARMCPU, pmsav7_dregion, 0,
 
163
                              vmstate_info_uint32, uint32_t),
 
164
        VMSTATE_VARRAY_UINT32(env.pmsav7.drsr, ARMCPU, pmsav7_dregion, 0,
 
165
                              vmstate_info_uint32, uint32_t),
 
166
        VMSTATE_VARRAY_UINT32(env.pmsav7.dracr, ARMCPU, pmsav7_dregion, 0,
 
167
                              vmstate_info_uint32, uint32_t),
 
168
        VMSTATE_VALIDATE("rgnr is valid", pmsav7_rgnr_vmstate_validate),
 
169
        VMSTATE_END_OF_LIST()
 
170
    }
 
171
};
 
172
 
 
173
static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
 
174
                    VMStateField *field)
 
175
{
 
176
    ARMCPU *cpu = opaque;
 
177
    CPUARMState *env = &cpu->env;
 
178
    uint32_t val = qemu_get_be32(f);
 
179
 
 
180
    env->aarch64 = ((val & PSTATE_nRW) == 0);
 
181
 
 
182
    if (is_a64(env)) {
 
183
        pstate_write(env, val);
 
184
        return 0;
 
185
    }
 
186
 
 
187
    cpsr_write(env, val, 0xffffffff, CPSRWriteRaw);
 
188
    return 0;
 
189
}
 
190
 
 
191
static int put_cpsr(QEMUFile *f, void *opaque, size_t size,
 
192
                    VMStateField *field, QJSON *vmdesc)
 
193
{
 
194
    ARMCPU *cpu = opaque;
 
195
    CPUARMState *env = &cpu->env;
 
196
    uint32_t val;
 
197
 
 
198
    if (is_a64(env)) {
 
199
        val = pstate_read(env);
 
200
    } else {
 
201
        val = cpsr_read(env);
 
202
    }
 
203
 
 
204
    qemu_put_be32(f, val);
 
205
    return 0;
 
206
}
 
207
 
 
208
static const VMStateInfo vmstate_cpsr = {
 
209
    .name = "cpsr",
 
210
    .get = get_cpsr,
 
211
    .put = put_cpsr,
 
212
};
 
213
 
 
214
static int get_power(QEMUFile *f, void *opaque, size_t size,
 
215
                    VMStateField *field)
 
216
{
 
217
    ARMCPU *cpu = opaque;
 
218
    bool powered_off = qemu_get_byte(f);
 
219
    cpu->power_state = powered_off ? PSCI_OFF : PSCI_ON;
 
220
    return 0;
 
221
}
 
222
 
 
223
static int put_power(QEMUFile *f, void *opaque, size_t size,
 
224
                    VMStateField *field, QJSON *vmdesc)
 
225
{
 
226
    ARMCPU *cpu = opaque;
 
227
 
 
228
    /* Migration should never happen while we transition power states */
 
229
 
 
230
    if (cpu->power_state == PSCI_ON ||
 
231
        cpu->power_state == PSCI_OFF) {
 
232
        bool powered_off = (cpu->power_state == PSCI_OFF) ? true : false;
 
233
        qemu_put_byte(f, powered_off);
 
234
        return 0;
 
235
    } else {
 
236
        return 1;
 
237
    }
 
238
}
 
239
 
 
240
static const VMStateInfo vmstate_powered_off = {
 
241
    .name = "powered_off",
 
242
    .get = get_power,
 
243
    .put = put_power,
 
244
};
 
245
 
 
246
static void cpu_pre_save(void *opaque)
 
247
{
 
248
    ARMCPU *cpu = opaque;
 
249
 
 
250
    if (kvm_enabled()) {
 
251
        if (!write_kvmstate_to_list(cpu)) {
 
252
            /* This should never fail */
 
253
            abort();
 
254
        }
 
255
    } else {
 
256
        if (!write_cpustate_to_list(cpu)) {
 
257
            /* This should never fail. */
 
258
            abort();
 
259
        }
 
260
    }
 
261
 
 
262
    cpu->cpreg_vmstate_array_len = cpu->cpreg_array_len;
 
263
    memcpy(cpu->cpreg_vmstate_indexes, cpu->cpreg_indexes,
 
264
           cpu->cpreg_array_len * sizeof(uint64_t));
 
265
    memcpy(cpu->cpreg_vmstate_values, cpu->cpreg_values,
 
266
           cpu->cpreg_array_len * sizeof(uint64_t));
 
267
}
 
268
 
 
269
static int cpu_post_load(void *opaque, int version_id)
 
270
{
 
271
    ARMCPU *cpu = opaque;
 
272
    int i, v;
 
273
 
 
274
    /* Update the values list from the incoming migration data.
 
275
     * Anything in the incoming data which we don't know about is
 
276
     * a migration failure; anything we know about but the incoming
 
277
     * data doesn't specify retains its current (reset) value.
 
278
     * The indexes list remains untouched -- we only inspect the
 
279
     * incoming migration index list so we can match the values array
 
280
     * entries with the right slots in our own values array.
 
281
     */
 
282
 
 
283
    for (i = 0, v = 0; i < cpu->cpreg_array_len
 
284
             && v < cpu->cpreg_vmstate_array_len; i++) {
 
285
        if (cpu->cpreg_vmstate_indexes[v] > cpu->cpreg_indexes[i]) {
 
286
            /* register in our list but not incoming : skip it */
 
287
            continue;
 
288
        }
 
289
        if (cpu->cpreg_vmstate_indexes[v] < cpu->cpreg_indexes[i]) {
 
290
            /* register in their list but not ours: fail migration */
 
291
            return -1;
 
292
        }
 
293
        /* matching register, copy the value over */
 
294
        cpu->cpreg_values[i] = cpu->cpreg_vmstate_values[v];
 
295
        v++;
 
296
    }
 
297
 
 
298
    if (kvm_enabled()) {
 
299
        if (!write_list_to_kvmstate(cpu, KVM_PUT_FULL_STATE)) {
 
300
            return -1;
 
301
        }
 
302
        /* Note that it's OK for the TCG side not to know about
 
303
         * every register in the list; KVM is authoritative if
 
304
         * we're using it.
 
305
         */
 
306
        write_list_to_cpustate(cpu);
 
307
    } else {
 
308
        if (!write_list_to_cpustate(cpu)) {
 
309
            return -1;
 
310
        }
 
311
    }
 
312
 
 
313
    hw_breakpoint_update_all(cpu);
 
314
    hw_watchpoint_update_all(cpu);
 
315
 
 
316
    return 0;
 
317
}
 
318
 
 
319
const VMStateDescription vmstate_arm_cpu = {
 
320
    .name = "cpu",
 
321
    .version_id = 22,
 
322
    .minimum_version_id = 22,
 
323
    .pre_save = cpu_pre_save,
 
324
    .post_load = cpu_post_load,
 
325
    .fields = (VMStateField[]) {
 
326
        VMSTATE_UINT32_ARRAY(env.regs, ARMCPU, 16),
 
327
        VMSTATE_UINT64_ARRAY(env.xregs, ARMCPU, 32),
 
328
        VMSTATE_UINT64(env.pc, ARMCPU),
 
329
        {
 
330
            .name = "cpsr",
 
331
            .version_id = 0,
 
332
            .size = sizeof(uint32_t),
 
333
            .info = &vmstate_cpsr,
 
334
            .flags = VMS_SINGLE,
 
335
            .offset = 0,
 
336
        },
 
337
        VMSTATE_UINT32(env.spsr, ARMCPU),
 
338
        VMSTATE_UINT64_ARRAY(env.banked_spsr, ARMCPU, 8),
 
339
        VMSTATE_UINT32_ARRAY(env.banked_r13, ARMCPU, 8),
 
340
        VMSTATE_UINT32_ARRAY(env.banked_r14, ARMCPU, 8),
 
341
        VMSTATE_UINT32_ARRAY(env.usr_regs, ARMCPU, 5),
 
342
        VMSTATE_UINT32_ARRAY(env.fiq_regs, ARMCPU, 5),
 
343
        VMSTATE_UINT64_ARRAY(env.elr_el, ARMCPU, 4),
 
344
        VMSTATE_UINT64_ARRAY(env.sp_el, ARMCPU, 4),
 
345
        /* The length-check must come before the arrays to avoid
 
346
         * incoming data possibly overflowing the array.
 
347
         */
 
348
        VMSTATE_INT32_POSITIVE_LE(cpreg_vmstate_array_len, ARMCPU),
 
349
        VMSTATE_VARRAY_INT32(cpreg_vmstate_indexes, ARMCPU,
 
350
                             cpreg_vmstate_array_len,
 
351
                             0, vmstate_info_uint64, uint64_t),
 
352
        VMSTATE_VARRAY_INT32(cpreg_vmstate_values, ARMCPU,
 
353
                             cpreg_vmstate_array_len,
 
354
                             0, vmstate_info_uint64, uint64_t),
 
355
        VMSTATE_UINT64(env.exclusive_addr, ARMCPU),
 
356
        VMSTATE_UINT64(env.exclusive_val, ARMCPU),
 
357
        VMSTATE_UINT64(env.exclusive_high, ARMCPU),
 
358
        VMSTATE_UINT64(env.features, ARMCPU),
 
359
        VMSTATE_UINT32(env.exception.syndrome, ARMCPU),
 
360
        VMSTATE_UINT32(env.exception.fsr, ARMCPU),
 
361
        VMSTATE_UINT64(env.exception.vaddress, ARMCPU),
 
362
        VMSTATE_TIMER_PTR(gt_timer[GTIMER_PHYS], ARMCPU),
 
363
        VMSTATE_TIMER_PTR(gt_timer[GTIMER_VIRT], ARMCPU),
 
364
        {
 
365
            .name = "power_state",
 
366
            .version_id = 0,
 
367
            .size = sizeof(bool),
 
368
            .info = &vmstate_powered_off,
 
369
            .flags = VMS_SINGLE,
 
370
            .offset = 0,
 
371
        },
 
372
        VMSTATE_END_OF_LIST()
 
373
    },
 
374
    .subsections = (const VMStateDescription*[]) {
 
375
        &vmstate_vfp,
 
376
        &vmstate_iwmmxt,
 
377
        &vmstate_m,
 
378
        &vmstate_thumb2ee,
 
379
        &vmstate_pmsav7,
 
380
        NULL
 
381
    }
 
382
};