Statistics
| Branch: | Revision:

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
};