xref: /qemu/cpu-target.c (revision 4e4fa6c12d97ee3ee87623c153009a5abd7b428e)
1d9f24bf5SPaolo Bonzini /*
2d9f24bf5SPaolo Bonzini  * Target-specific parts of the CPU object
3d9f24bf5SPaolo Bonzini  *
4d9f24bf5SPaolo Bonzini  *  Copyright (c) 2003 Fabrice Bellard
5d9f24bf5SPaolo Bonzini  *
6d9f24bf5SPaolo Bonzini  * This library is free software; you can redistribute it and/or
7d9f24bf5SPaolo Bonzini  * modify it under the terms of the GNU Lesser General Public
8d9f24bf5SPaolo Bonzini  * License as published by the Free Software Foundation; either
9d9f24bf5SPaolo Bonzini  * version 2 of the License, or (at your option) any later version.
10d9f24bf5SPaolo Bonzini  *
11d9f24bf5SPaolo Bonzini  * This library is distributed in the hope that it will be useful,
12d9f24bf5SPaolo Bonzini  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13d9f24bf5SPaolo Bonzini  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14d9f24bf5SPaolo Bonzini  * Lesser General Public License for more details.
15d9f24bf5SPaolo Bonzini  *
16d9f24bf5SPaolo Bonzini  * You should have received a copy of the GNU Lesser General Public
17d9f24bf5SPaolo Bonzini  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18d9f24bf5SPaolo Bonzini  */
19d9f24bf5SPaolo Bonzini 
20d9f24bf5SPaolo Bonzini #include "qemu/osdep.h"
21d9f24bf5SPaolo Bonzini #include "qapi/error.h"
22d9f24bf5SPaolo Bonzini 
23d9f24bf5SPaolo Bonzini #include "exec/target_page.h"
24d9f24bf5SPaolo Bonzini #include "hw/qdev-core.h"
25d9f24bf5SPaolo Bonzini #include "hw/qdev-properties.h"
26d9f24bf5SPaolo Bonzini #include "qemu/error-report.h"
27d9f24bf5SPaolo Bonzini #include "migration/vmstate.h"
28d9f24bf5SPaolo Bonzini #ifdef CONFIG_USER_ONLY
29d9f24bf5SPaolo Bonzini #include "qemu.h"
30d9f24bf5SPaolo Bonzini #else
318b80bd28SPhilippe Mathieu-Daudé #include "hw/core/sysemu-cpu-ops.h"
32d9f24bf5SPaolo Bonzini #include "exec/address-spaces.h"
33d9f24bf5SPaolo Bonzini #endif
34d9f24bf5SPaolo Bonzini #include "sysemu/tcg.h"
35d9f24bf5SPaolo Bonzini #include "sysemu/kvm.h"
36d9f24bf5SPaolo Bonzini #include "sysemu/replay.h"
37377bf6f3SPhilippe Mathieu-Daudé #include "exec/cpu-common.h"
383b04508cSPhilippe Mathieu-Daudé #include "exec/exec-all.h"
393b9bd3f4SPaolo Bonzini #include "exec/translate-all.h"
40d9f24bf5SPaolo Bonzini #include "exec/log.h"
4130565f10SClaudio Fontana #include "hw/core/accel-cpu.h"
42ad1a706fSRichard Henderson #include "trace/trace-root.h"
433b04508cSPhilippe Mathieu-Daudé #include "qemu/accel.h"
44d9f24bf5SPaolo Bonzini 
45d9f24bf5SPaolo Bonzini uintptr_t qemu_host_page_size;
46d9f24bf5SPaolo Bonzini intptr_t qemu_host_page_mask;
47d9f24bf5SPaolo Bonzini 
48d9f24bf5SPaolo Bonzini #ifndef CONFIG_USER_ONLY
49d9f24bf5SPaolo Bonzini static int cpu_common_post_load(void *opaque, int version_id)
50d9f24bf5SPaolo Bonzini {
51d9f24bf5SPaolo Bonzini     CPUState *cpu = opaque;
52d9f24bf5SPaolo Bonzini 
53d9f24bf5SPaolo Bonzini     /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
54d9f24bf5SPaolo Bonzini        version_id is increased. */
55d9f24bf5SPaolo Bonzini     cpu->interrupt_request &= ~0x01;
56d9f24bf5SPaolo Bonzini     tlb_flush(cpu);
57d9f24bf5SPaolo Bonzini 
58d9f24bf5SPaolo Bonzini     /* loadvm has just updated the content of RAM, bypassing the
59d9f24bf5SPaolo Bonzini      * usual mechanisms that ensure we flush TBs for writes to
60d9f24bf5SPaolo Bonzini      * memory we've translated code from. So we must flush all TBs,
61d9f24bf5SPaolo Bonzini      * which will now be stale.
62d9f24bf5SPaolo Bonzini      */
63d9f24bf5SPaolo Bonzini     tb_flush(cpu);
64d9f24bf5SPaolo Bonzini 
65d9f24bf5SPaolo Bonzini     return 0;
66d9f24bf5SPaolo Bonzini }
67d9f24bf5SPaolo Bonzini 
68d9f24bf5SPaolo Bonzini static int cpu_common_pre_load(void *opaque)
69d9f24bf5SPaolo Bonzini {
70d9f24bf5SPaolo Bonzini     CPUState *cpu = opaque;
71d9f24bf5SPaolo Bonzini 
72d9f24bf5SPaolo Bonzini     cpu->exception_index = -1;
73d9f24bf5SPaolo Bonzini 
74d9f24bf5SPaolo Bonzini     return 0;
75d9f24bf5SPaolo Bonzini }
76d9f24bf5SPaolo Bonzini 
77d9f24bf5SPaolo Bonzini static bool cpu_common_exception_index_needed(void *opaque)
78d9f24bf5SPaolo Bonzini {
79d9f24bf5SPaolo Bonzini     CPUState *cpu = opaque;
80d9f24bf5SPaolo Bonzini 
81d9f24bf5SPaolo Bonzini     return tcg_enabled() && cpu->exception_index != -1;
82d9f24bf5SPaolo Bonzini }
83d9f24bf5SPaolo Bonzini 
84d9f24bf5SPaolo Bonzini static const VMStateDescription vmstate_cpu_common_exception_index = {
85d9f24bf5SPaolo Bonzini     .name = "cpu_common/exception_index",
86d9f24bf5SPaolo Bonzini     .version_id = 1,
87d9f24bf5SPaolo Bonzini     .minimum_version_id = 1,
88d9f24bf5SPaolo Bonzini     .needed = cpu_common_exception_index_needed,
89d9f24bf5SPaolo Bonzini     .fields = (VMStateField[]) {
90d9f24bf5SPaolo Bonzini         VMSTATE_INT32(exception_index, CPUState),
91d9f24bf5SPaolo Bonzini         VMSTATE_END_OF_LIST()
92d9f24bf5SPaolo Bonzini     }
93d9f24bf5SPaolo Bonzini };
94d9f24bf5SPaolo Bonzini 
95d9f24bf5SPaolo Bonzini static bool cpu_common_crash_occurred_needed(void *opaque)
96d9f24bf5SPaolo Bonzini {
97d9f24bf5SPaolo Bonzini     CPUState *cpu = opaque;
98d9f24bf5SPaolo Bonzini 
99d9f24bf5SPaolo Bonzini     return cpu->crash_occurred;
100d9f24bf5SPaolo Bonzini }
101d9f24bf5SPaolo Bonzini 
102d9f24bf5SPaolo Bonzini static const VMStateDescription vmstate_cpu_common_crash_occurred = {
103d9f24bf5SPaolo Bonzini     .name = "cpu_common/crash_occurred",
104d9f24bf5SPaolo Bonzini     .version_id = 1,
105d9f24bf5SPaolo Bonzini     .minimum_version_id = 1,
106d9f24bf5SPaolo Bonzini     .needed = cpu_common_crash_occurred_needed,
107d9f24bf5SPaolo Bonzini     .fields = (VMStateField[]) {
108d9f24bf5SPaolo Bonzini         VMSTATE_BOOL(crash_occurred, CPUState),
109d9f24bf5SPaolo Bonzini         VMSTATE_END_OF_LIST()
110d9f24bf5SPaolo Bonzini     }
111d9f24bf5SPaolo Bonzini };
112d9f24bf5SPaolo Bonzini 
113d9f24bf5SPaolo Bonzini const VMStateDescription vmstate_cpu_common = {
114d9f24bf5SPaolo Bonzini     .name = "cpu_common",
115d9f24bf5SPaolo Bonzini     .version_id = 1,
116d9f24bf5SPaolo Bonzini     .minimum_version_id = 1,
117d9f24bf5SPaolo Bonzini     .pre_load = cpu_common_pre_load,
118d9f24bf5SPaolo Bonzini     .post_load = cpu_common_post_load,
119d9f24bf5SPaolo Bonzini     .fields = (VMStateField[]) {
120d9f24bf5SPaolo Bonzini         VMSTATE_UINT32(halted, CPUState),
121d9f24bf5SPaolo Bonzini         VMSTATE_UINT32(interrupt_request, CPUState),
122d9f24bf5SPaolo Bonzini         VMSTATE_END_OF_LIST()
123d9f24bf5SPaolo Bonzini     },
124d9f24bf5SPaolo Bonzini     .subsections = (const VMStateDescription*[]) {
125d9f24bf5SPaolo Bonzini         &vmstate_cpu_common_exception_index,
126d9f24bf5SPaolo Bonzini         &vmstate_cpu_common_crash_occurred,
127d9f24bf5SPaolo Bonzini         NULL
128d9f24bf5SPaolo Bonzini     }
129d9f24bf5SPaolo Bonzini };
130d9f24bf5SPaolo Bonzini #endif
131d9f24bf5SPaolo Bonzini 
1327df5e3d6SClaudio Fontana void cpu_exec_realizefn(CPUState *cpu, Error **errp)
133d9f24bf5SPaolo Bonzini {
1346fbdff87SAlex Bennée     /* cache the cpu class for the hotpath */
1356fbdff87SAlex Bennée     cpu->cc = CPU_GET_CLASS(cpu);
136d9f24bf5SPaolo Bonzini 
1379ea057dcSClaudio Fontana     if (!accel_cpu_realizefn(cpu, errp)) {
1389ea057dcSClaudio Fontana         return;
1399ea057dcSClaudio Fontana     }
140*4e4fa6c1SRichard Henderson 
1417df5e3d6SClaudio Fontana     /* NB: errp parameter is unused currently */
1427df5e3d6SClaudio Fontana     if (tcg_enabled()) {
1437df5e3d6SClaudio Fontana         tcg_exec_realizefn(cpu, errp);
1447df5e3d6SClaudio Fontana     }
1457df5e3d6SClaudio Fontana 
146*4e4fa6c1SRichard Henderson     /* Wait until cpu initialization complete before exposing cpu. */
147*4e4fa6c1SRichard Henderson     cpu_list_add(cpu);
148*4e4fa6c1SRichard Henderson 
149*4e4fa6c1SRichard Henderson     /* Plugin initialization must wait until cpu_index assigned. */
150*4e4fa6c1SRichard Henderson     if (tcg_enabled()) {
151*4e4fa6c1SRichard Henderson         qemu_plugin_vcpu_init_hook(cpu);
152*4e4fa6c1SRichard Henderson     }
153*4e4fa6c1SRichard Henderson 
1547df5e3d6SClaudio Fontana #ifdef CONFIG_USER_ONLY
1554336073bSPhilippe Mathieu-Daudé     assert(qdev_get_vmsd(DEVICE(cpu)) == NULL ||
1564336073bSPhilippe Mathieu-Daudé            qdev_get_vmsd(DEVICE(cpu))->unmigratable);
1577df5e3d6SClaudio Fontana #else
1587df5e3d6SClaudio Fontana     if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
1597df5e3d6SClaudio Fontana         vmstate_register(NULL, cpu->cpu_index, &vmstate_cpu_common, cpu);
1607df5e3d6SClaudio Fontana     }
1616fbdff87SAlex Bennée     if (cpu->cc->sysemu_ops->legacy_vmsd != NULL) {
1626fbdff87SAlex Bennée         vmstate_register(NULL, cpu->cpu_index, cpu->cc->sysemu_ops->legacy_vmsd, cpu);
1637df5e3d6SClaudio Fontana     }
1647df5e3d6SClaudio Fontana #endif /* CONFIG_USER_ONLY */
1657df5e3d6SClaudio Fontana }
1667df5e3d6SClaudio Fontana 
1677df5e3d6SClaudio Fontana void cpu_exec_unrealizefn(CPUState *cpu)
1687df5e3d6SClaudio Fontana {
169feece4d0SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
1707df5e3d6SClaudio Fontana     CPUClass *cc = CPU_GET_CLASS(cpu);
171d9f24bf5SPaolo Bonzini 
172feece4d0SPhilippe Mathieu-Daudé     if (cc->sysemu_ops->legacy_vmsd != NULL) {
173feece4d0SPhilippe Mathieu-Daudé         vmstate_unregister(NULL, cc->sysemu_ops->legacy_vmsd, cpu);
174d9f24bf5SPaolo Bonzini     }
175d9f24bf5SPaolo Bonzini     if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
176d9f24bf5SPaolo Bonzini         vmstate_unregister(NULL, &vmstate_cpu_common, cpu);
177d9f24bf5SPaolo Bonzini     }
178d9f24bf5SPaolo Bonzini #endif
1797df5e3d6SClaudio Fontana     if (tcg_enabled()) {
1807df5e3d6SClaudio Fontana         tcg_exec_unrealizefn(cpu);
1817df5e3d6SClaudio Fontana     }
1827df5e3d6SClaudio Fontana 
1837df5e3d6SClaudio Fontana     cpu_list_remove(cpu);
184d9f24bf5SPaolo Bonzini }
185d9f24bf5SPaolo Bonzini 
186995b87deSRichard Henderson /*
1876e8dcacdSRichard Henderson  * This can't go in hw/core/cpu.c because that file is compiled only
1886e8dcacdSRichard Henderson  * once for both user-mode and system builds.
1896e8dcacdSRichard Henderson  */
1906e8dcacdSRichard Henderson static Property cpu_common_props[] = {
1916e8dcacdSRichard Henderson #ifdef CONFIG_USER_ONLY
1926e8dcacdSRichard Henderson     /*
1936e8dcacdSRichard Henderson      * Create a property for the user-only object, so users can
1946e8dcacdSRichard Henderson      * adjust prctl(PR_SET_UNALIGN) from the command-line.
1956e8dcacdSRichard Henderson      * Has no effect if the target does not support the feature.
1966e8dcacdSRichard Henderson      */
1976e8dcacdSRichard Henderson     DEFINE_PROP_BOOL("prctl-unalign-sigbus", CPUState,
1986e8dcacdSRichard Henderson                      prctl_unalign_sigbus, false),
1996e8dcacdSRichard Henderson #else
2006e8dcacdSRichard Henderson     /*
2016e8dcacdSRichard Henderson      * Create a memory property for softmmu CPU object, so users can
2026e8dcacdSRichard Henderson      * wire up its memory.  The default if no link is set up is to use
203995b87deSRichard Henderson      * the system address space.
204995b87deSRichard Henderson      */
205995b87deSRichard Henderson     DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION,
206995b87deSRichard Henderson                      MemoryRegion *),
207995b87deSRichard Henderson #endif
208995b87deSRichard Henderson     DEFINE_PROP_END_OF_LIST(),
209995b87deSRichard Henderson };
210995b87deSRichard Henderson 
2110c3c25fcSPeter Maydell static bool cpu_get_start_powered_off(Object *obj, Error **errp)
2120c3c25fcSPeter Maydell {
2130c3c25fcSPeter Maydell     CPUState *cpu = CPU(obj);
2140c3c25fcSPeter Maydell     return cpu->start_powered_off;
2150c3c25fcSPeter Maydell }
2160c3c25fcSPeter Maydell 
2170c3c25fcSPeter Maydell static void cpu_set_start_powered_off(Object *obj, bool value, Error **errp)
2180c3c25fcSPeter Maydell {
2190c3c25fcSPeter Maydell     CPUState *cpu = CPU(obj);
2200c3c25fcSPeter Maydell     cpu->start_powered_off = value;
2210c3c25fcSPeter Maydell }
2220c3c25fcSPeter Maydell 
223995b87deSRichard Henderson void cpu_class_init_props(DeviceClass *dc)
224995b87deSRichard Henderson {
2250c3c25fcSPeter Maydell     ObjectClass *oc = OBJECT_CLASS(dc);
2260c3c25fcSPeter Maydell 
227995b87deSRichard Henderson     device_class_set_props(dc, cpu_common_props);
2280c3c25fcSPeter Maydell     /*
2290c3c25fcSPeter Maydell      * We can't use DEFINE_PROP_BOOL in the Property array for this
2300c3c25fcSPeter Maydell      * property, because we want this to be settable after realize.
2310c3c25fcSPeter Maydell      */
2320c3c25fcSPeter Maydell     object_class_property_add_bool(oc, "start-powered-off",
2330c3c25fcSPeter Maydell                                    cpu_get_start_powered_off,
2340c3c25fcSPeter Maydell                                    cpu_set_start_powered_off);
235995b87deSRichard Henderson }
236995b87deSRichard Henderson 
237d9f24bf5SPaolo Bonzini void cpu_exec_initfn(CPUState *cpu)
238d9f24bf5SPaolo Bonzini {
239d9f24bf5SPaolo Bonzini     cpu->as = NULL;
240d9f24bf5SPaolo Bonzini     cpu->num_ases = 0;
241d9f24bf5SPaolo Bonzini 
242d9f24bf5SPaolo Bonzini #ifndef CONFIG_USER_ONLY
243d9f24bf5SPaolo Bonzini     cpu->thread_id = qemu_get_thread_id();
244d9f24bf5SPaolo Bonzini     cpu->memory = get_system_memory();
245d9f24bf5SPaolo Bonzini     object_ref(OBJECT(cpu->memory));
246d9f24bf5SPaolo Bonzini #endif
247d9f24bf5SPaolo Bonzini }
248d9f24bf5SPaolo Bonzini 
249d9f24bf5SPaolo Bonzini const char *parse_cpu_option(const char *cpu_option)
250d9f24bf5SPaolo Bonzini {
251d9f24bf5SPaolo Bonzini     ObjectClass *oc;
252d9f24bf5SPaolo Bonzini     CPUClass *cc;
253d9f24bf5SPaolo Bonzini     gchar **model_pieces;
254d9f24bf5SPaolo Bonzini     const char *cpu_type;
255d9f24bf5SPaolo Bonzini 
256d9f24bf5SPaolo Bonzini     model_pieces = g_strsplit(cpu_option, ",", 2);
257d9f24bf5SPaolo Bonzini     if (!model_pieces[0]) {
258d9f24bf5SPaolo Bonzini         error_report("-cpu option cannot be empty");
259d9f24bf5SPaolo Bonzini         exit(1);
260d9f24bf5SPaolo Bonzini     }
261d9f24bf5SPaolo Bonzini 
262d9f24bf5SPaolo Bonzini     oc = cpu_class_by_name(CPU_RESOLVING_TYPE, model_pieces[0]);
263d9f24bf5SPaolo Bonzini     if (oc == NULL) {
264d9f24bf5SPaolo Bonzini         error_report("unable to find CPU model '%s'", model_pieces[0]);
265d9f24bf5SPaolo Bonzini         g_strfreev(model_pieces);
266d9f24bf5SPaolo Bonzini         exit(EXIT_FAILURE);
267d9f24bf5SPaolo Bonzini     }
268d9f24bf5SPaolo Bonzini 
269d9f24bf5SPaolo Bonzini     cpu_type = object_class_get_name(oc);
270d9f24bf5SPaolo Bonzini     cc = CPU_CLASS(oc);
271d9f24bf5SPaolo Bonzini     cc->parse_features(cpu_type, model_pieces[1], &error_fatal);
272d9f24bf5SPaolo Bonzini     g_strfreev(model_pieces);
273d9f24bf5SPaolo Bonzini     return cpu_type;
274d9f24bf5SPaolo Bonzini }
275d9f24bf5SPaolo Bonzini 
276377bf6f3SPhilippe Mathieu-Daudé void list_cpus(const char *optarg)
277377bf6f3SPhilippe Mathieu-Daudé {
278377bf6f3SPhilippe Mathieu-Daudé     /* XXX: implement xxx_cpu_list for targets that still miss it */
279377bf6f3SPhilippe Mathieu-Daudé #if defined(cpu_list)
280377bf6f3SPhilippe Mathieu-Daudé     cpu_list();
281377bf6f3SPhilippe Mathieu-Daudé #endif
282377bf6f3SPhilippe Mathieu-Daudé }
283377bf6f3SPhilippe Mathieu-Daudé 
284d9f24bf5SPaolo Bonzini #if defined(CONFIG_USER_ONLY)
285d9f24bf5SPaolo Bonzini void tb_invalidate_phys_addr(target_ulong addr)
286d9f24bf5SPaolo Bonzini {
287d9f24bf5SPaolo Bonzini     mmap_lock();
288d6d1fd29SRichard Henderson     tb_invalidate_phys_page(addr);
289d9f24bf5SPaolo Bonzini     mmap_unlock();
290d9f24bf5SPaolo Bonzini }
291d9f24bf5SPaolo Bonzini #else
292d9f24bf5SPaolo Bonzini void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs)
293d9f24bf5SPaolo Bonzini {
294d9f24bf5SPaolo Bonzini     ram_addr_t ram_addr;
295d9f24bf5SPaolo Bonzini     MemoryRegion *mr;
296d9f24bf5SPaolo Bonzini     hwaddr l = 1;
297d9f24bf5SPaolo Bonzini 
298d9f24bf5SPaolo Bonzini     if (!tcg_enabled()) {
299d9f24bf5SPaolo Bonzini         return;
300d9f24bf5SPaolo Bonzini     }
301d9f24bf5SPaolo Bonzini 
302d9f24bf5SPaolo Bonzini     RCU_READ_LOCK_GUARD();
303d9f24bf5SPaolo Bonzini     mr = address_space_translate(as, addr, &addr, &l, false, attrs);
304d9f24bf5SPaolo Bonzini     if (!(memory_region_is_ram(mr)
305d9f24bf5SPaolo Bonzini           || memory_region_is_romd(mr))) {
306d9f24bf5SPaolo Bonzini         return;
307d9f24bf5SPaolo Bonzini     }
308d9f24bf5SPaolo Bonzini     ram_addr = memory_region_get_ram_addr(mr) + addr;
309d6d1fd29SRichard Henderson     tb_invalidate_phys_page(ram_addr);
310d9f24bf5SPaolo Bonzini }
311d9f24bf5SPaolo Bonzini #endif
312d9f24bf5SPaolo Bonzini 
313d9f24bf5SPaolo Bonzini /* Add a breakpoint.  */
314d9f24bf5SPaolo Bonzini int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags,
315d9f24bf5SPaolo Bonzini                           CPUBreakpoint **breakpoint)
316d9f24bf5SPaolo Bonzini {
3175bc31e94SRichard Henderson     CPUClass *cc = CPU_GET_CLASS(cpu);
318d9f24bf5SPaolo Bonzini     CPUBreakpoint *bp;
319d9f24bf5SPaolo Bonzini 
3205bc31e94SRichard Henderson     if (cc->gdb_adjust_breakpoint) {
3215bc31e94SRichard Henderson         pc = cc->gdb_adjust_breakpoint(cpu, pc);
3225bc31e94SRichard Henderson     }
3235bc31e94SRichard Henderson 
324d9f24bf5SPaolo Bonzini     bp = g_malloc(sizeof(*bp));
325d9f24bf5SPaolo Bonzini 
326d9f24bf5SPaolo Bonzini     bp->pc = pc;
327d9f24bf5SPaolo Bonzini     bp->flags = flags;
328d9f24bf5SPaolo Bonzini 
329d9f24bf5SPaolo Bonzini     /* keep all GDB-injected breakpoints in front */
330d9f24bf5SPaolo Bonzini     if (flags & BP_GDB) {
331d9f24bf5SPaolo Bonzini         QTAILQ_INSERT_HEAD(&cpu->breakpoints, bp, entry);
332d9f24bf5SPaolo Bonzini     } else {
333d9f24bf5SPaolo Bonzini         QTAILQ_INSERT_TAIL(&cpu->breakpoints, bp, entry);
334d9f24bf5SPaolo Bonzini     }
335d9f24bf5SPaolo Bonzini 
336d9f24bf5SPaolo Bonzini     if (breakpoint) {
337d9f24bf5SPaolo Bonzini         *breakpoint = bp;
338d9f24bf5SPaolo Bonzini     }
339ad1a706fSRichard Henderson 
340ad1a706fSRichard Henderson     trace_breakpoint_insert(cpu->cpu_index, pc, flags);
341d9f24bf5SPaolo Bonzini     return 0;
342d9f24bf5SPaolo Bonzini }
343d9f24bf5SPaolo Bonzini 
344d9f24bf5SPaolo Bonzini /* Remove a specific breakpoint.  */
345d9f24bf5SPaolo Bonzini int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags)
346d9f24bf5SPaolo Bonzini {
3475bc31e94SRichard Henderson     CPUClass *cc = CPU_GET_CLASS(cpu);
348d9f24bf5SPaolo Bonzini     CPUBreakpoint *bp;
349d9f24bf5SPaolo Bonzini 
3505bc31e94SRichard Henderson     if (cc->gdb_adjust_breakpoint) {
3515bc31e94SRichard Henderson         pc = cc->gdb_adjust_breakpoint(cpu, pc);
3525bc31e94SRichard Henderson     }
3535bc31e94SRichard Henderson 
354d9f24bf5SPaolo Bonzini     QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
355d9f24bf5SPaolo Bonzini         if (bp->pc == pc && bp->flags == flags) {
356d9f24bf5SPaolo Bonzini             cpu_breakpoint_remove_by_ref(cpu, bp);
357d9f24bf5SPaolo Bonzini             return 0;
358d9f24bf5SPaolo Bonzini         }
359d9f24bf5SPaolo Bonzini     }
360d9f24bf5SPaolo Bonzini     return -ENOENT;
361d9f24bf5SPaolo Bonzini }
362d9f24bf5SPaolo Bonzini 
363d9f24bf5SPaolo Bonzini /* Remove a specific breakpoint by reference.  */
364ad1a706fSRichard Henderson void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *bp)
365d9f24bf5SPaolo Bonzini {
366ad1a706fSRichard Henderson     QTAILQ_REMOVE(&cpu->breakpoints, bp, entry);
367d9f24bf5SPaolo Bonzini 
368ad1a706fSRichard Henderson     trace_breakpoint_remove(cpu->cpu_index, bp->pc, bp->flags);
369ad1a706fSRichard Henderson     g_free(bp);
370d9f24bf5SPaolo Bonzini }
371d9f24bf5SPaolo Bonzini 
372d9f24bf5SPaolo Bonzini /* Remove all matching breakpoints. */
373d9f24bf5SPaolo Bonzini void cpu_breakpoint_remove_all(CPUState *cpu, int mask)
374d9f24bf5SPaolo Bonzini {
375d9f24bf5SPaolo Bonzini     CPUBreakpoint *bp, *next;
376d9f24bf5SPaolo Bonzini 
377d9f24bf5SPaolo Bonzini     QTAILQ_FOREACH_SAFE(bp, &cpu->breakpoints, entry, next) {
378d9f24bf5SPaolo Bonzini         if (bp->flags & mask) {
379d9f24bf5SPaolo Bonzini             cpu_breakpoint_remove_by_ref(cpu, bp);
380d9f24bf5SPaolo Bonzini         }
381d9f24bf5SPaolo Bonzini     }
382d9f24bf5SPaolo Bonzini }
383d9f24bf5SPaolo Bonzini 
384d9f24bf5SPaolo Bonzini /* enable or disable single step mode. EXCP_DEBUG is returned by the
385d9f24bf5SPaolo Bonzini    CPU loop after each instruction */
386d9f24bf5SPaolo Bonzini void cpu_single_step(CPUState *cpu, int enabled)
387d9f24bf5SPaolo Bonzini {
388d9f24bf5SPaolo Bonzini     if (cpu->singlestep_enabled != enabled) {
389d9f24bf5SPaolo Bonzini         cpu->singlestep_enabled = enabled;
390d9f24bf5SPaolo Bonzini         if (kvm_enabled()) {
391d9f24bf5SPaolo Bonzini             kvm_update_guest_debug(cpu, 0);
392d9f24bf5SPaolo Bonzini         }
393ad1a706fSRichard Henderson         trace_breakpoint_singlestep(cpu->cpu_index, enabled);
394d9f24bf5SPaolo Bonzini     }
395d9f24bf5SPaolo Bonzini }
396d9f24bf5SPaolo Bonzini 
397d9f24bf5SPaolo Bonzini void cpu_abort(CPUState *cpu, const char *fmt, ...)
398d9f24bf5SPaolo Bonzini {
399d9f24bf5SPaolo Bonzini     va_list ap;
400d9f24bf5SPaolo Bonzini     va_list ap2;
401d9f24bf5SPaolo Bonzini 
402d9f24bf5SPaolo Bonzini     va_start(ap, fmt);
403d9f24bf5SPaolo Bonzini     va_copy(ap2, ap);
404d9f24bf5SPaolo Bonzini     fprintf(stderr, "qemu: fatal: ");
405d9f24bf5SPaolo Bonzini     vfprintf(stderr, fmt, ap);
406d9f24bf5SPaolo Bonzini     fprintf(stderr, "\n");
407d9f24bf5SPaolo Bonzini     cpu_dump_state(cpu, stderr, CPU_DUMP_FPU | CPU_DUMP_CCOP);
408d9f24bf5SPaolo Bonzini     if (qemu_log_separate()) {
409c60f599bSRichard Henderson         FILE *logfile = qemu_log_trylock();
41078b54858SRichard Henderson         if (logfile) {
41178b54858SRichard Henderson             fprintf(logfile, "qemu: fatal: ");
41278b54858SRichard Henderson             vfprintf(logfile, fmt, ap2);
41378b54858SRichard Henderson             fprintf(logfile, "\n");
41478b54858SRichard Henderson             cpu_dump_state(cpu, logfile, CPU_DUMP_FPU | CPU_DUMP_CCOP);
415d9f24bf5SPaolo Bonzini             qemu_log_unlock(logfile);
41678b54858SRichard Henderson         }
417d9f24bf5SPaolo Bonzini     }
418d9f24bf5SPaolo Bonzini     va_end(ap2);
419d9f24bf5SPaolo Bonzini     va_end(ap);
420d9f24bf5SPaolo Bonzini     replay_finish();
421d9f24bf5SPaolo Bonzini #if defined(CONFIG_USER_ONLY)
422d9f24bf5SPaolo Bonzini     {
423d9f24bf5SPaolo Bonzini         struct sigaction act;
424d9f24bf5SPaolo Bonzini         sigfillset(&act.sa_mask);
425d9f24bf5SPaolo Bonzini         act.sa_handler = SIG_DFL;
426d9f24bf5SPaolo Bonzini         act.sa_flags = 0;
427d9f24bf5SPaolo Bonzini         sigaction(SIGABRT, &act, NULL);
428d9f24bf5SPaolo Bonzini     }
429d9f24bf5SPaolo Bonzini #endif
430d9f24bf5SPaolo Bonzini     abort();
431d9f24bf5SPaolo Bonzini }
432d9f24bf5SPaolo Bonzini 
433d9f24bf5SPaolo Bonzini /* physical memory access (slow version, mainly for debug) */
434d9f24bf5SPaolo Bonzini #if defined(CONFIG_USER_ONLY)
43573842ef0SPhilippe Mathieu-Daudé int cpu_memory_rw_debug(CPUState *cpu, vaddr addr,
43673842ef0SPhilippe Mathieu-Daudé                         void *ptr, size_t len, bool is_write)
437d9f24bf5SPaolo Bonzini {
438d9f24bf5SPaolo Bonzini     int flags;
43973842ef0SPhilippe Mathieu-Daudé     vaddr l, page;
440d9f24bf5SPaolo Bonzini     void * p;
441d9f24bf5SPaolo Bonzini     uint8_t *buf = ptr;
442d9f24bf5SPaolo Bonzini 
443d9f24bf5SPaolo Bonzini     while (len > 0) {
444d9f24bf5SPaolo Bonzini         page = addr & TARGET_PAGE_MASK;
445d9f24bf5SPaolo Bonzini         l = (page + TARGET_PAGE_SIZE) - addr;
446d9f24bf5SPaolo Bonzini         if (l > len)
447d9f24bf5SPaolo Bonzini             l = len;
448d9f24bf5SPaolo Bonzini         flags = page_get_flags(page);
449d9f24bf5SPaolo Bonzini         if (!(flags & PAGE_VALID))
450d9f24bf5SPaolo Bonzini             return -1;
451d9f24bf5SPaolo Bonzini         if (is_write) {
452d9f24bf5SPaolo Bonzini             if (!(flags & PAGE_WRITE))
453d9f24bf5SPaolo Bonzini                 return -1;
454d9f24bf5SPaolo Bonzini             /* XXX: this code should not depend on lock_user */
455d9f24bf5SPaolo Bonzini             if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
456d9f24bf5SPaolo Bonzini                 return -1;
457d9f24bf5SPaolo Bonzini             memcpy(p, buf, l);
458d9f24bf5SPaolo Bonzini             unlock_user(p, addr, l);
459d9f24bf5SPaolo Bonzini         } else {
460d9f24bf5SPaolo Bonzini             if (!(flags & PAGE_READ))
461d9f24bf5SPaolo Bonzini                 return -1;
462d9f24bf5SPaolo Bonzini             /* XXX: this code should not depend on lock_user */
463d9f24bf5SPaolo Bonzini             if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
464d9f24bf5SPaolo Bonzini                 return -1;
465d9f24bf5SPaolo Bonzini             memcpy(buf, p, l);
466d9f24bf5SPaolo Bonzini             unlock_user(p, addr, 0);
467d9f24bf5SPaolo Bonzini         }
468d9f24bf5SPaolo Bonzini         len -= l;
469d9f24bf5SPaolo Bonzini         buf += l;
470d9f24bf5SPaolo Bonzini         addr += l;
471d9f24bf5SPaolo Bonzini     }
472d9f24bf5SPaolo Bonzini     return 0;
473d9f24bf5SPaolo Bonzini }
474d9f24bf5SPaolo Bonzini #endif
475d9f24bf5SPaolo Bonzini 
476d9f24bf5SPaolo Bonzini bool target_words_bigendian(void)
477d9f24bf5SPaolo Bonzini {
478ee3eb3a7SMarc-André Lureau #if TARGET_BIG_ENDIAN
479d9f24bf5SPaolo Bonzini     return true;
480d9f24bf5SPaolo Bonzini #else
481d9f24bf5SPaolo Bonzini     return false;
482d9f24bf5SPaolo Bonzini #endif
483d9f24bf5SPaolo Bonzini }
484d9f24bf5SPaolo Bonzini 
485d9f24bf5SPaolo Bonzini void page_size_init(void)
486d9f24bf5SPaolo Bonzini {
487d9f24bf5SPaolo Bonzini     /* NOTE: we can always suppose that qemu_host_page_size >=
488d9f24bf5SPaolo Bonzini        TARGET_PAGE_SIZE */
489d9f24bf5SPaolo Bonzini     if (qemu_host_page_size == 0) {
4908e3b0cbbSMarc-André Lureau         qemu_host_page_size = qemu_real_host_page_size();
491d9f24bf5SPaolo Bonzini     }
492d9f24bf5SPaolo Bonzini     if (qemu_host_page_size < TARGET_PAGE_SIZE) {
493d9f24bf5SPaolo Bonzini         qemu_host_page_size = TARGET_PAGE_SIZE;
494d9f24bf5SPaolo Bonzini     }
495d9f24bf5SPaolo Bonzini     qemu_host_page_mask = -(intptr_t)qemu_host_page_size;
496d9f24bf5SPaolo Bonzini }
497