xref: /qemu/hw/core/cpu-system.c (revision ca05578fc80f4253ed19f4c4128a4cbd5b83f0b5)
1df4fd7d5SPhilippe Mathieu-Daudé /*
232cad1ffSPhilippe Mathieu-Daudé  * QEMU CPU model (system specific)
3df4fd7d5SPhilippe Mathieu-Daudé  *
4df4fd7d5SPhilippe Mathieu-Daudé  * Copyright (c) 2012-2014 SUSE LINUX Products GmbH
5df4fd7d5SPhilippe Mathieu-Daudé  *
6df4fd7d5SPhilippe Mathieu-Daudé  * This program is free software; you can redistribute it and/or
7df4fd7d5SPhilippe Mathieu-Daudé  * modify it under the terms of the GNU General Public License
8df4fd7d5SPhilippe Mathieu-Daudé  * as published by the Free Software Foundation; either version 2
9df4fd7d5SPhilippe Mathieu-Daudé  * of the License, or (at your option) any later version.
10df4fd7d5SPhilippe Mathieu-Daudé  *
11df4fd7d5SPhilippe Mathieu-Daudé  * This program is distributed in the hope that it will be useful,
12df4fd7d5SPhilippe Mathieu-Daudé  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13df4fd7d5SPhilippe Mathieu-Daudé  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14df4fd7d5SPhilippe Mathieu-Daudé  * GNU General Public License for more details.
15df4fd7d5SPhilippe Mathieu-Daudé  *
16df4fd7d5SPhilippe Mathieu-Daudé  * You should have received a copy of the GNU General Public License
17df4fd7d5SPhilippe Mathieu-Daudé  * along with this program; if not, see
18df4fd7d5SPhilippe Mathieu-Daudé  * <http://www.gnu.org/licenses/gpl-2.0.html>
19df4fd7d5SPhilippe Mathieu-Daudé  */
20df4fd7d5SPhilippe Mathieu-Daudé 
21df4fd7d5SPhilippe Mathieu-Daudé #include "qemu/osdep.h"
22df4fd7d5SPhilippe Mathieu-Daudé #include "qapi/error.h"
23a86cf967SPhilippe Mathieu-Daudé #include "exec/address-spaces.h"
24*ca05578fSPhilippe Mathieu-Daudé #include "exec/cputlb.h"
25e3a575f5SPhilippe Mathieu-Daudé #include "exec/memory.h"
26*ca05578fSPhilippe Mathieu-Daudé #include "exec/tb-flush.h"
2742508261SPhilippe Mathieu-Daudé #include "exec/tswap.h"
28e3a575f5SPhilippe Mathieu-Daudé #include "hw/qdev-core.h"
29e3a575f5SPhilippe Mathieu-Daudé #include "hw/qdev-properties.h"
30da383e02SPhilippe Mathieu-Daudé #include "hw/core/sysemu-cpu-ops.h"
31*ca05578fSPhilippe Mathieu-Daudé #include "migration/vmstate.h"
32*ca05578fSPhilippe Mathieu-Daudé #include "system/tcg.h"
33df4fd7d5SPhilippe Mathieu-Daudé 
3477ba5d50SPhilippe Mathieu-Daudé bool cpu_paging_enabled(const CPUState *cpu)
3577ba5d50SPhilippe Mathieu-Daudé {
3677ba5d50SPhilippe Mathieu-Daudé     CPUClass *cc = CPU_GET_CLASS(cpu);
3777ba5d50SPhilippe Mathieu-Daudé 
386bc0d6a0SPhilippe Mathieu-Daudé     if (cc->sysemu_ops->get_paging_enabled) {
396bc0d6a0SPhilippe Mathieu-Daudé         return cc->sysemu_ops->get_paging_enabled(cpu);
4077ba5d50SPhilippe Mathieu-Daudé     }
4177ba5d50SPhilippe Mathieu-Daudé 
4277ba5d50SPhilippe Mathieu-Daudé     return false;
4377ba5d50SPhilippe Mathieu-Daudé }
4477ba5d50SPhilippe Mathieu-Daudé 
458a5b974bSMarc-André Lureau bool cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
4665c57115SPhilippe Mathieu-Daudé                             Error **errp)
4765c57115SPhilippe Mathieu-Daudé {
4865c57115SPhilippe Mathieu-Daudé     CPUClass *cc = CPU_GET_CLASS(cpu);
4965c57115SPhilippe Mathieu-Daudé 
502b60b62eSPhilippe Mathieu-Daudé     if (cc->sysemu_ops->get_memory_mapping) {
518a5b974bSMarc-André Lureau         return cc->sysemu_ops->get_memory_mapping(cpu, list, errp);
5265c57115SPhilippe Mathieu-Daudé     }
5365c57115SPhilippe Mathieu-Daudé 
5465c57115SPhilippe Mathieu-Daudé     error_setg(errp, "Obtaining memory mappings is unsupported on this CPU.");
558a5b974bSMarc-André Lureau     return false;
5665c57115SPhilippe Mathieu-Daudé }
5765c57115SPhilippe Mathieu-Daudé 
58a41d3aaeSPhilippe Mathieu-Daudé hwaddr cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
59a41d3aaeSPhilippe Mathieu-Daudé                                      MemTxAttrs *attrs)
60a41d3aaeSPhilippe Mathieu-Daudé {
61a41d3aaeSPhilippe Mathieu-Daudé     CPUClass *cc = CPU_GET_CLASS(cpu);
621cceedd7SDavid Hildenbrand     hwaddr paddr;
63a41d3aaeSPhilippe Mathieu-Daudé 
6408928c6dSPhilippe Mathieu-Daudé     if (cc->sysemu_ops->get_phys_page_attrs_debug) {
651cceedd7SDavid Hildenbrand         paddr = cc->sysemu_ops->get_phys_page_attrs_debug(cpu, addr, attrs);
661cceedd7SDavid Hildenbrand     } else {
67a41d3aaeSPhilippe Mathieu-Daudé         /* Fallback for CPUs which don't implement the _attrs_ hook */
68a41d3aaeSPhilippe Mathieu-Daudé         *attrs = MEMTXATTRS_UNSPECIFIED;
691cceedd7SDavid Hildenbrand         paddr = cc->sysemu_ops->get_phys_page_debug(cpu, addr);
701cceedd7SDavid Hildenbrand     }
711cceedd7SDavid Hildenbrand     /* Indicate that this is a debug access. */
721cceedd7SDavid Hildenbrand     attrs->debug = 1;
731cceedd7SDavid Hildenbrand     return paddr;
74a41d3aaeSPhilippe Mathieu-Daudé }
75a41d3aaeSPhilippe Mathieu-Daudé 
76a41d3aaeSPhilippe Mathieu-Daudé hwaddr cpu_get_phys_page_debug(CPUState *cpu, vaddr addr)
77a41d3aaeSPhilippe Mathieu-Daudé {
78a41d3aaeSPhilippe Mathieu-Daudé     MemTxAttrs attrs = {};
79a41d3aaeSPhilippe Mathieu-Daudé 
80a41d3aaeSPhilippe Mathieu-Daudé     return cpu_get_phys_page_attrs_debug(cpu, addr, &attrs);
81a41d3aaeSPhilippe Mathieu-Daudé }
82a41d3aaeSPhilippe Mathieu-Daudé 
83a41d3aaeSPhilippe Mathieu-Daudé int cpu_asidx_from_attrs(CPUState *cpu, MemTxAttrs attrs)
84a41d3aaeSPhilippe Mathieu-Daudé {
85a41d3aaeSPhilippe Mathieu-Daudé     int ret = 0;
86a41d3aaeSPhilippe Mathieu-Daudé 
87b404ca37SAlex Bennée     if (cpu->cc->sysemu_ops->asidx_from_attrs) {
88b404ca37SAlex Bennée         ret = cpu->cc->sysemu_ops->asidx_from_attrs(cpu, attrs);
89a41d3aaeSPhilippe Mathieu-Daudé         assert(ret < cpu->num_ases && ret >= 0);
90a41d3aaeSPhilippe Mathieu-Daudé     }
91a41d3aaeSPhilippe Mathieu-Daudé     return ret;
92a41d3aaeSPhilippe Mathieu-Daudé }
93a41d3aaeSPhilippe Mathieu-Daudé 
945ef2d5a4SPhilippe Mathieu-Daudé int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
955ef2d5a4SPhilippe Mathieu-Daudé                              void *opaque)
965ef2d5a4SPhilippe Mathieu-Daudé {
975ef2d5a4SPhilippe Mathieu-Daudé     CPUClass *cc = CPU_GET_CLASS(cpu);
985ef2d5a4SPhilippe Mathieu-Daudé 
99715e3c1aSPhilippe Mathieu-Daudé     if (!cc->sysemu_ops->write_elf32_qemunote) {
1005ef2d5a4SPhilippe Mathieu-Daudé         return 0;
1015ef2d5a4SPhilippe Mathieu-Daudé     }
102715e3c1aSPhilippe Mathieu-Daudé     return (*cc->sysemu_ops->write_elf32_qemunote)(f, cpu, opaque);
1035ef2d5a4SPhilippe Mathieu-Daudé }
1045ef2d5a4SPhilippe Mathieu-Daudé 
1055ef2d5a4SPhilippe Mathieu-Daudé int cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu,
1065ef2d5a4SPhilippe Mathieu-Daudé                          int cpuid, void *opaque)
1075ef2d5a4SPhilippe Mathieu-Daudé {
1085ef2d5a4SPhilippe Mathieu-Daudé     CPUClass *cc = CPU_GET_CLASS(cpu);
1095ef2d5a4SPhilippe Mathieu-Daudé 
110715e3c1aSPhilippe Mathieu-Daudé     if (!cc->sysemu_ops->write_elf32_note) {
1115ef2d5a4SPhilippe Mathieu-Daudé         return -1;
1125ef2d5a4SPhilippe Mathieu-Daudé     }
113715e3c1aSPhilippe Mathieu-Daudé     return (*cc->sysemu_ops->write_elf32_note)(f, cpu, cpuid, opaque);
1145ef2d5a4SPhilippe Mathieu-Daudé }
1155ef2d5a4SPhilippe Mathieu-Daudé 
1165ef2d5a4SPhilippe Mathieu-Daudé int cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
1175ef2d5a4SPhilippe Mathieu-Daudé                              void *opaque)
1185ef2d5a4SPhilippe Mathieu-Daudé {
1195ef2d5a4SPhilippe Mathieu-Daudé     CPUClass *cc = CPU_GET_CLASS(cpu);
1205ef2d5a4SPhilippe Mathieu-Daudé 
121715e3c1aSPhilippe Mathieu-Daudé     if (!cc->sysemu_ops->write_elf64_qemunote) {
1225ef2d5a4SPhilippe Mathieu-Daudé         return 0;
1235ef2d5a4SPhilippe Mathieu-Daudé     }
124715e3c1aSPhilippe Mathieu-Daudé     return (*cc->sysemu_ops->write_elf64_qemunote)(f, cpu, opaque);
1255ef2d5a4SPhilippe Mathieu-Daudé }
1265ef2d5a4SPhilippe Mathieu-Daudé 
1275ef2d5a4SPhilippe Mathieu-Daudé int cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
1285ef2d5a4SPhilippe Mathieu-Daudé                          int cpuid, void *opaque)
1295ef2d5a4SPhilippe Mathieu-Daudé {
1305ef2d5a4SPhilippe Mathieu-Daudé     CPUClass *cc = CPU_GET_CLASS(cpu);
1315ef2d5a4SPhilippe Mathieu-Daudé 
132715e3c1aSPhilippe Mathieu-Daudé     if (!cc->sysemu_ops->write_elf64_note) {
1335ef2d5a4SPhilippe Mathieu-Daudé         return -1;
1345ef2d5a4SPhilippe Mathieu-Daudé     }
135715e3c1aSPhilippe Mathieu-Daudé     return (*cc->sysemu_ops->write_elf64_note)(f, cpu, cpuid, opaque);
1365ef2d5a4SPhilippe Mathieu-Daudé }
1375ef2d5a4SPhilippe Mathieu-Daudé 
138cdba7e2fSPhilippe Mathieu-Daudé bool cpu_virtio_is_big_endian(CPUState *cpu)
139cdba7e2fSPhilippe Mathieu-Daudé {
140cdba7e2fSPhilippe Mathieu-Daudé     CPUClass *cc = CPU_GET_CLASS(cpu);
141cdba7e2fSPhilippe Mathieu-Daudé 
142da383e02SPhilippe Mathieu-Daudé     if (cc->sysemu_ops->virtio_is_big_endian) {
143da383e02SPhilippe Mathieu-Daudé         return cc->sysemu_ops->virtio_is_big_endian(cpu);
144cdba7e2fSPhilippe Mathieu-Daudé     }
145cdba7e2fSPhilippe Mathieu-Daudé     return target_words_bigendian();
146cdba7e2fSPhilippe Mathieu-Daudé }
147cdba7e2fSPhilippe Mathieu-Daudé 
148df4fd7d5SPhilippe Mathieu-Daudé GuestPanicInformation *cpu_get_crash_info(CPUState *cpu)
149df4fd7d5SPhilippe Mathieu-Daudé {
150df4fd7d5SPhilippe Mathieu-Daudé     CPUClass *cc = CPU_GET_CLASS(cpu);
151df4fd7d5SPhilippe Mathieu-Daudé     GuestPanicInformation *res = NULL;
152df4fd7d5SPhilippe Mathieu-Daudé 
15383ec01b6SPhilippe Mathieu-Daudé     if (cc->sysemu_ops->get_crash_info) {
15483ec01b6SPhilippe Mathieu-Daudé         res = cc->sysemu_ops->get_crash_info(cpu);
155df4fd7d5SPhilippe Mathieu-Daudé     }
156df4fd7d5SPhilippe Mathieu-Daudé     return res;
157df4fd7d5SPhilippe Mathieu-Daudé }
158e3a575f5SPhilippe Mathieu-Daudé 
159e3a575f5SPhilippe Mathieu-Daudé static const Property cpu_system_props[] = {
160e3a575f5SPhilippe Mathieu-Daudé     /*
161e3a575f5SPhilippe Mathieu-Daudé      * Create a memory property for system CPU object, so users can
162e3a575f5SPhilippe Mathieu-Daudé      * wire up its memory.  The default if no link is set up is to use
163e3a575f5SPhilippe Mathieu-Daudé      * the system address space.
164e3a575f5SPhilippe Mathieu-Daudé      */
165e3a575f5SPhilippe Mathieu-Daudé     DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION,
166e3a575f5SPhilippe Mathieu-Daudé                      MemoryRegion *),
167e3a575f5SPhilippe Mathieu-Daudé };
168e3a575f5SPhilippe Mathieu-Daudé 
169e3a575f5SPhilippe Mathieu-Daudé static bool cpu_get_start_powered_off(Object *obj, Error **errp)
170e3a575f5SPhilippe Mathieu-Daudé {
171e3a575f5SPhilippe Mathieu-Daudé     CPUState *cpu = CPU(obj);
172e3a575f5SPhilippe Mathieu-Daudé     return cpu->start_powered_off;
173e3a575f5SPhilippe Mathieu-Daudé }
174e3a575f5SPhilippe Mathieu-Daudé 
175e3a575f5SPhilippe Mathieu-Daudé static void cpu_set_start_powered_off(Object *obj, bool value, Error **errp)
176e3a575f5SPhilippe Mathieu-Daudé {
177e3a575f5SPhilippe Mathieu-Daudé     CPUState *cpu = CPU(obj);
178e3a575f5SPhilippe Mathieu-Daudé     cpu->start_powered_off = value;
179e3a575f5SPhilippe Mathieu-Daudé }
180e3a575f5SPhilippe Mathieu-Daudé 
181e3a575f5SPhilippe Mathieu-Daudé void cpu_class_init_props(DeviceClass *dc)
182e3a575f5SPhilippe Mathieu-Daudé {
183e3a575f5SPhilippe Mathieu-Daudé     ObjectClass *oc = OBJECT_CLASS(dc);
184e3a575f5SPhilippe Mathieu-Daudé 
185e3a575f5SPhilippe Mathieu-Daudé     /*
186e3a575f5SPhilippe Mathieu-Daudé      * We can't use DEFINE_PROP_BOOL in the Property array for this
187e3a575f5SPhilippe Mathieu-Daudé      * property, because we want this to be settable after realize.
188e3a575f5SPhilippe Mathieu-Daudé      */
189e3a575f5SPhilippe Mathieu-Daudé     object_class_property_add_bool(oc, "start-powered-off",
190e3a575f5SPhilippe Mathieu-Daudé                                    cpu_get_start_powered_off,
191e3a575f5SPhilippe Mathieu-Daudé                                    cpu_set_start_powered_off);
192e3a575f5SPhilippe Mathieu-Daudé 
193e3a575f5SPhilippe Mathieu-Daudé     device_class_set_props(dc, cpu_system_props);
194e3a575f5SPhilippe Mathieu-Daudé }
195a86cf967SPhilippe Mathieu-Daudé 
196a86cf967SPhilippe Mathieu-Daudé void cpu_exec_initfn(CPUState *cpu)
197a86cf967SPhilippe Mathieu-Daudé {
198a86cf967SPhilippe Mathieu-Daudé     cpu->memory = get_system_memory();
199a86cf967SPhilippe Mathieu-Daudé     object_ref(OBJECT(cpu->memory));
200a86cf967SPhilippe Mathieu-Daudé }
201*ca05578fSPhilippe Mathieu-Daudé 
202*ca05578fSPhilippe Mathieu-Daudé static int cpu_common_post_load(void *opaque, int version_id)
203*ca05578fSPhilippe Mathieu-Daudé {
204*ca05578fSPhilippe Mathieu-Daudé     if (tcg_enabled()) {
205*ca05578fSPhilippe Mathieu-Daudé         CPUState *cpu = opaque;
206*ca05578fSPhilippe Mathieu-Daudé 
207*ca05578fSPhilippe Mathieu-Daudé         /*
208*ca05578fSPhilippe Mathieu-Daudé          * 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
209*ca05578fSPhilippe Mathieu-Daudé          * version_id is increased.
210*ca05578fSPhilippe Mathieu-Daudé          */
211*ca05578fSPhilippe Mathieu-Daudé         cpu->interrupt_request &= ~0x01;
212*ca05578fSPhilippe Mathieu-Daudé 
213*ca05578fSPhilippe Mathieu-Daudé         tlb_flush(cpu);
214*ca05578fSPhilippe Mathieu-Daudé 
215*ca05578fSPhilippe Mathieu-Daudé         /*
216*ca05578fSPhilippe Mathieu-Daudé          * loadvm has just updated the content of RAM, bypassing the
217*ca05578fSPhilippe Mathieu-Daudé          * usual mechanisms that ensure we flush TBs for writes to
218*ca05578fSPhilippe Mathieu-Daudé          * memory we've translated code from. So we must flush all TBs,
219*ca05578fSPhilippe Mathieu-Daudé          * which will now be stale.
220*ca05578fSPhilippe Mathieu-Daudé          */
221*ca05578fSPhilippe Mathieu-Daudé         tb_flush(cpu);
222*ca05578fSPhilippe Mathieu-Daudé     }
223*ca05578fSPhilippe Mathieu-Daudé 
224*ca05578fSPhilippe Mathieu-Daudé     return 0;
225*ca05578fSPhilippe Mathieu-Daudé }
226*ca05578fSPhilippe Mathieu-Daudé 
227*ca05578fSPhilippe Mathieu-Daudé static int cpu_common_pre_load(void *opaque)
228*ca05578fSPhilippe Mathieu-Daudé {
229*ca05578fSPhilippe Mathieu-Daudé     CPUState *cpu = opaque;
230*ca05578fSPhilippe Mathieu-Daudé 
231*ca05578fSPhilippe Mathieu-Daudé     cpu->exception_index = -1;
232*ca05578fSPhilippe Mathieu-Daudé 
233*ca05578fSPhilippe Mathieu-Daudé     return 0;
234*ca05578fSPhilippe Mathieu-Daudé }
235*ca05578fSPhilippe Mathieu-Daudé 
236*ca05578fSPhilippe Mathieu-Daudé static bool cpu_common_exception_index_needed(void *opaque)
237*ca05578fSPhilippe Mathieu-Daudé {
238*ca05578fSPhilippe Mathieu-Daudé     CPUState *cpu = opaque;
239*ca05578fSPhilippe Mathieu-Daudé 
240*ca05578fSPhilippe Mathieu-Daudé     return tcg_enabled() && cpu->exception_index != -1;
241*ca05578fSPhilippe Mathieu-Daudé }
242*ca05578fSPhilippe Mathieu-Daudé 
243*ca05578fSPhilippe Mathieu-Daudé static const VMStateDescription vmstate_cpu_common_exception_index = {
244*ca05578fSPhilippe Mathieu-Daudé     .name = "cpu_common/exception_index",
245*ca05578fSPhilippe Mathieu-Daudé     .version_id = 1,
246*ca05578fSPhilippe Mathieu-Daudé     .minimum_version_id = 1,
247*ca05578fSPhilippe Mathieu-Daudé     .needed = cpu_common_exception_index_needed,
248*ca05578fSPhilippe Mathieu-Daudé     .fields = (const VMStateField[]) {
249*ca05578fSPhilippe Mathieu-Daudé         VMSTATE_INT32(exception_index, CPUState),
250*ca05578fSPhilippe Mathieu-Daudé         VMSTATE_END_OF_LIST()
251*ca05578fSPhilippe Mathieu-Daudé     }
252*ca05578fSPhilippe Mathieu-Daudé };
253*ca05578fSPhilippe Mathieu-Daudé 
254*ca05578fSPhilippe Mathieu-Daudé static bool cpu_common_crash_occurred_needed(void *opaque)
255*ca05578fSPhilippe Mathieu-Daudé {
256*ca05578fSPhilippe Mathieu-Daudé     CPUState *cpu = opaque;
257*ca05578fSPhilippe Mathieu-Daudé 
258*ca05578fSPhilippe Mathieu-Daudé     return cpu->crash_occurred;
259*ca05578fSPhilippe Mathieu-Daudé }
260*ca05578fSPhilippe Mathieu-Daudé 
261*ca05578fSPhilippe Mathieu-Daudé static const VMStateDescription vmstate_cpu_common_crash_occurred = {
262*ca05578fSPhilippe Mathieu-Daudé     .name = "cpu_common/crash_occurred",
263*ca05578fSPhilippe Mathieu-Daudé     .version_id = 1,
264*ca05578fSPhilippe Mathieu-Daudé     .minimum_version_id = 1,
265*ca05578fSPhilippe Mathieu-Daudé     .needed = cpu_common_crash_occurred_needed,
266*ca05578fSPhilippe Mathieu-Daudé     .fields = (const VMStateField[]) {
267*ca05578fSPhilippe Mathieu-Daudé         VMSTATE_BOOL(crash_occurred, CPUState),
268*ca05578fSPhilippe Mathieu-Daudé         VMSTATE_END_OF_LIST()
269*ca05578fSPhilippe Mathieu-Daudé     }
270*ca05578fSPhilippe Mathieu-Daudé };
271*ca05578fSPhilippe Mathieu-Daudé 
272*ca05578fSPhilippe Mathieu-Daudé const VMStateDescription vmstate_cpu_common = {
273*ca05578fSPhilippe Mathieu-Daudé     .name = "cpu_common",
274*ca05578fSPhilippe Mathieu-Daudé     .version_id = 1,
275*ca05578fSPhilippe Mathieu-Daudé     .minimum_version_id = 1,
276*ca05578fSPhilippe Mathieu-Daudé     .pre_load = cpu_common_pre_load,
277*ca05578fSPhilippe Mathieu-Daudé     .post_load = cpu_common_post_load,
278*ca05578fSPhilippe Mathieu-Daudé     .fields = (const VMStateField[]) {
279*ca05578fSPhilippe Mathieu-Daudé         VMSTATE_UINT32(halted, CPUState),
280*ca05578fSPhilippe Mathieu-Daudé         VMSTATE_UINT32(interrupt_request, CPUState),
281*ca05578fSPhilippe Mathieu-Daudé         VMSTATE_END_OF_LIST()
282*ca05578fSPhilippe Mathieu-Daudé     },
283*ca05578fSPhilippe Mathieu-Daudé     .subsections = (const VMStateDescription * const []) {
284*ca05578fSPhilippe Mathieu-Daudé         &vmstate_cpu_common_exception_index,
285*ca05578fSPhilippe Mathieu-Daudé         &vmstate_cpu_common_crash_occurred,
286*ca05578fSPhilippe Mathieu-Daudé         NULL
287*ca05578fSPhilippe Mathieu-Daudé     }
288*ca05578fSPhilippe Mathieu-Daudé };
289*ca05578fSPhilippe Mathieu-Daudé 
290*ca05578fSPhilippe Mathieu-Daudé void cpu_vmstate_register(CPUState *cpu)
291*ca05578fSPhilippe Mathieu-Daudé {
292*ca05578fSPhilippe Mathieu-Daudé     if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
293*ca05578fSPhilippe Mathieu-Daudé         vmstate_register(NULL, cpu->cpu_index, &vmstate_cpu_common, cpu);
294*ca05578fSPhilippe Mathieu-Daudé     }
295*ca05578fSPhilippe Mathieu-Daudé     if (cpu->cc->sysemu_ops->legacy_vmsd != NULL) {
296*ca05578fSPhilippe Mathieu-Daudé         vmstate_register(NULL, cpu->cpu_index,
297*ca05578fSPhilippe Mathieu-Daudé                          cpu->cc->sysemu_ops->legacy_vmsd, cpu);
298*ca05578fSPhilippe Mathieu-Daudé     }
299*ca05578fSPhilippe Mathieu-Daudé }
300*ca05578fSPhilippe Mathieu-Daudé 
301*ca05578fSPhilippe Mathieu-Daudé void cpu_vmstate_unregister(CPUState *cpu)
302*ca05578fSPhilippe Mathieu-Daudé {
303*ca05578fSPhilippe Mathieu-Daudé     CPUClass *cc = CPU_GET_CLASS(cpu);
304*ca05578fSPhilippe Mathieu-Daudé 
305*ca05578fSPhilippe Mathieu-Daudé     if (cc->sysemu_ops->legacy_vmsd != NULL) {
306*ca05578fSPhilippe Mathieu-Daudé         vmstate_unregister(NULL, cc->sysemu_ops->legacy_vmsd, cpu);
307*ca05578fSPhilippe Mathieu-Daudé     }
308*ca05578fSPhilippe Mathieu-Daudé     if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
309*ca05578fSPhilippe Mathieu-Daudé         vmstate_unregister(NULL, &vmstate_cpu_common, cpu);
310*ca05578fSPhilippe Mathieu-Daudé     }
311*ca05578fSPhilippe Mathieu-Daudé }
312