xref: /qemu/cpu-target.c (revision 8b80bd28a5cf8d8af7d38abcf1c7d81a1b226ec3)
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 "qemu-common.h"
22d9f24bf5SPaolo Bonzini #include "qapi/error.h"
23d9f24bf5SPaolo Bonzini 
24d9f24bf5SPaolo Bonzini #include "exec/target_page.h"
25d9f24bf5SPaolo Bonzini #include "hw/qdev-core.h"
26d9f24bf5SPaolo Bonzini #include "hw/qdev-properties.h"
27d9f24bf5SPaolo Bonzini #include "qemu/error-report.h"
28d9f24bf5SPaolo Bonzini #include "migration/vmstate.h"
29d9f24bf5SPaolo Bonzini #ifdef CONFIG_USER_ONLY
30d9f24bf5SPaolo Bonzini #include "qemu.h"
31d9f24bf5SPaolo Bonzini #else
32*8b80bd28SPhilippe Mathieu-Daudé #include "hw/core/sysemu-cpu-ops.h"
33d9f24bf5SPaolo Bonzini #include "exec/address-spaces.h"
34d9f24bf5SPaolo Bonzini #endif
35d9f24bf5SPaolo Bonzini #include "sysemu/tcg.h"
36d9f24bf5SPaolo Bonzini #include "sysemu/kvm.h"
37d9f24bf5SPaolo Bonzini #include "sysemu/replay.h"
383b9bd3f4SPaolo Bonzini #include "exec/translate-all.h"
39d9f24bf5SPaolo Bonzini #include "exec/log.h"
4030565f10SClaudio Fontana #include "hw/core/accel-cpu.h"
41d9f24bf5SPaolo Bonzini 
42d9f24bf5SPaolo Bonzini uintptr_t qemu_host_page_size;
43d9f24bf5SPaolo Bonzini intptr_t qemu_host_page_mask;
44d9f24bf5SPaolo Bonzini 
45d9f24bf5SPaolo Bonzini #ifndef CONFIG_USER_ONLY
46d9f24bf5SPaolo Bonzini static int cpu_common_post_load(void *opaque, int version_id)
47d9f24bf5SPaolo Bonzini {
48d9f24bf5SPaolo Bonzini     CPUState *cpu = opaque;
49d9f24bf5SPaolo Bonzini 
50d9f24bf5SPaolo Bonzini     /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
51d9f24bf5SPaolo Bonzini        version_id is increased. */
52d9f24bf5SPaolo Bonzini     cpu->interrupt_request &= ~0x01;
53d9f24bf5SPaolo Bonzini     tlb_flush(cpu);
54d9f24bf5SPaolo Bonzini 
55d9f24bf5SPaolo Bonzini     /* loadvm has just updated the content of RAM, bypassing the
56d9f24bf5SPaolo Bonzini      * usual mechanisms that ensure we flush TBs for writes to
57d9f24bf5SPaolo Bonzini      * memory we've translated code from. So we must flush all TBs,
58d9f24bf5SPaolo Bonzini      * which will now be stale.
59d9f24bf5SPaolo Bonzini      */
60d9f24bf5SPaolo Bonzini     tb_flush(cpu);
61d9f24bf5SPaolo Bonzini 
62d9f24bf5SPaolo Bonzini     return 0;
63d9f24bf5SPaolo Bonzini }
64d9f24bf5SPaolo Bonzini 
65d9f24bf5SPaolo Bonzini static int cpu_common_pre_load(void *opaque)
66d9f24bf5SPaolo Bonzini {
67d9f24bf5SPaolo Bonzini     CPUState *cpu = opaque;
68d9f24bf5SPaolo Bonzini 
69d9f24bf5SPaolo Bonzini     cpu->exception_index = -1;
70d9f24bf5SPaolo Bonzini 
71d9f24bf5SPaolo Bonzini     return 0;
72d9f24bf5SPaolo Bonzini }
73d9f24bf5SPaolo Bonzini 
74d9f24bf5SPaolo Bonzini static bool cpu_common_exception_index_needed(void *opaque)
75d9f24bf5SPaolo Bonzini {
76d9f24bf5SPaolo Bonzini     CPUState *cpu = opaque;
77d9f24bf5SPaolo Bonzini 
78d9f24bf5SPaolo Bonzini     return tcg_enabled() && cpu->exception_index != -1;
79d9f24bf5SPaolo Bonzini }
80d9f24bf5SPaolo Bonzini 
81d9f24bf5SPaolo Bonzini static const VMStateDescription vmstate_cpu_common_exception_index = {
82d9f24bf5SPaolo Bonzini     .name = "cpu_common/exception_index",
83d9f24bf5SPaolo Bonzini     .version_id = 1,
84d9f24bf5SPaolo Bonzini     .minimum_version_id = 1,
85d9f24bf5SPaolo Bonzini     .needed = cpu_common_exception_index_needed,
86d9f24bf5SPaolo Bonzini     .fields = (VMStateField[]) {
87d9f24bf5SPaolo Bonzini         VMSTATE_INT32(exception_index, CPUState),
88d9f24bf5SPaolo Bonzini         VMSTATE_END_OF_LIST()
89d9f24bf5SPaolo Bonzini     }
90d9f24bf5SPaolo Bonzini };
91d9f24bf5SPaolo Bonzini 
92d9f24bf5SPaolo Bonzini static bool cpu_common_crash_occurred_needed(void *opaque)
93d9f24bf5SPaolo Bonzini {
94d9f24bf5SPaolo Bonzini     CPUState *cpu = opaque;
95d9f24bf5SPaolo Bonzini 
96d9f24bf5SPaolo Bonzini     return cpu->crash_occurred;
97d9f24bf5SPaolo Bonzini }
98d9f24bf5SPaolo Bonzini 
99d9f24bf5SPaolo Bonzini static const VMStateDescription vmstate_cpu_common_crash_occurred = {
100d9f24bf5SPaolo Bonzini     .name = "cpu_common/crash_occurred",
101d9f24bf5SPaolo Bonzini     .version_id = 1,
102d9f24bf5SPaolo Bonzini     .minimum_version_id = 1,
103d9f24bf5SPaolo Bonzini     .needed = cpu_common_crash_occurred_needed,
104d9f24bf5SPaolo Bonzini     .fields = (VMStateField[]) {
105d9f24bf5SPaolo Bonzini         VMSTATE_BOOL(crash_occurred, CPUState),
106d9f24bf5SPaolo Bonzini         VMSTATE_END_OF_LIST()
107d9f24bf5SPaolo Bonzini     }
108d9f24bf5SPaolo Bonzini };
109d9f24bf5SPaolo Bonzini 
110d9f24bf5SPaolo Bonzini const VMStateDescription vmstate_cpu_common = {
111d9f24bf5SPaolo Bonzini     .name = "cpu_common",
112d9f24bf5SPaolo Bonzini     .version_id = 1,
113d9f24bf5SPaolo Bonzini     .minimum_version_id = 1,
114d9f24bf5SPaolo Bonzini     .pre_load = cpu_common_pre_load,
115d9f24bf5SPaolo Bonzini     .post_load = cpu_common_post_load,
116d9f24bf5SPaolo Bonzini     .fields = (VMStateField[]) {
117d9f24bf5SPaolo Bonzini         VMSTATE_UINT32(halted, CPUState),
118d9f24bf5SPaolo Bonzini         VMSTATE_UINT32(interrupt_request, CPUState),
119d9f24bf5SPaolo Bonzini         VMSTATE_END_OF_LIST()
120d9f24bf5SPaolo Bonzini     },
121d9f24bf5SPaolo Bonzini     .subsections = (const VMStateDescription*[]) {
122d9f24bf5SPaolo Bonzini         &vmstate_cpu_common_exception_index,
123d9f24bf5SPaolo Bonzini         &vmstate_cpu_common_crash_occurred,
124d9f24bf5SPaolo Bonzini         NULL
125d9f24bf5SPaolo Bonzini     }
126d9f24bf5SPaolo Bonzini };
127d9f24bf5SPaolo Bonzini #endif
128d9f24bf5SPaolo Bonzini 
1297df5e3d6SClaudio Fontana void cpu_exec_realizefn(CPUState *cpu, Error **errp)
130d9f24bf5SPaolo Bonzini {
131d9f24bf5SPaolo Bonzini     CPUClass *cc = CPU_GET_CLASS(cpu);
132d9f24bf5SPaolo Bonzini 
1337df5e3d6SClaudio Fontana     cpu_list_add(cpu);
1349ea057dcSClaudio Fontana     if (!accel_cpu_realizefn(cpu, errp)) {
1359ea057dcSClaudio Fontana         return;
1369ea057dcSClaudio Fontana     }
1377df5e3d6SClaudio Fontana #ifdef CONFIG_TCG
1387df5e3d6SClaudio Fontana     /* NB: errp parameter is unused currently */
1397df5e3d6SClaudio Fontana     if (tcg_enabled()) {
1407df5e3d6SClaudio Fontana         tcg_exec_realizefn(cpu, errp);
1417df5e3d6SClaudio Fontana     }
1427df5e3d6SClaudio Fontana #endif /* CONFIG_TCG */
1437df5e3d6SClaudio Fontana 
1447df5e3d6SClaudio Fontana #ifdef CONFIG_USER_ONLY
1454336073bSPhilippe Mathieu-Daudé     assert(qdev_get_vmsd(DEVICE(cpu)) == NULL ||
1464336073bSPhilippe Mathieu-Daudé            qdev_get_vmsd(DEVICE(cpu))->unmigratable);
147744c72a8SPhilippe Mathieu-Daudé     assert(cc->legacy_vmsd == NULL);
1487df5e3d6SClaudio Fontana #else
1497df5e3d6SClaudio Fontana     if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
1507df5e3d6SClaudio Fontana         vmstate_register(NULL, cpu->cpu_index, &vmstate_cpu_common, cpu);
1517df5e3d6SClaudio Fontana     }
152744c72a8SPhilippe Mathieu-Daudé     if (cc->legacy_vmsd != NULL) {
153744c72a8SPhilippe Mathieu-Daudé         vmstate_register(NULL, cpu->cpu_index, cc->legacy_vmsd, cpu);
1547df5e3d6SClaudio Fontana     }
1557df5e3d6SClaudio Fontana #endif /* CONFIG_USER_ONLY */
1567df5e3d6SClaudio Fontana }
1577df5e3d6SClaudio Fontana 
1587df5e3d6SClaudio Fontana void cpu_exec_unrealizefn(CPUState *cpu)
1597df5e3d6SClaudio Fontana {
1607df5e3d6SClaudio Fontana     CPUClass *cc = CPU_GET_CLASS(cpu);
161d9f24bf5SPaolo Bonzini 
162d9f24bf5SPaolo Bonzini #ifdef CONFIG_USER_ONLY
163744c72a8SPhilippe Mathieu-Daudé     assert(cc->legacy_vmsd == NULL);
164d9f24bf5SPaolo Bonzini #else
165744c72a8SPhilippe Mathieu-Daudé     if (cc->legacy_vmsd != NULL) {
166744c72a8SPhilippe Mathieu-Daudé         vmstate_unregister(NULL, cc->legacy_vmsd, cpu);
167d9f24bf5SPaolo Bonzini     }
168d9f24bf5SPaolo Bonzini     if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
169d9f24bf5SPaolo Bonzini         vmstate_unregister(NULL, &vmstate_cpu_common, cpu);
170d9f24bf5SPaolo Bonzini     }
171d9f24bf5SPaolo Bonzini #endif
1727df5e3d6SClaudio Fontana #ifdef CONFIG_TCG
1737df5e3d6SClaudio Fontana     /* NB: errp parameter is unused currently */
1747df5e3d6SClaudio Fontana     if (tcg_enabled()) {
1757df5e3d6SClaudio Fontana         tcg_exec_unrealizefn(cpu);
1767df5e3d6SClaudio Fontana     }
1777df5e3d6SClaudio Fontana #endif /* CONFIG_TCG */
1787df5e3d6SClaudio Fontana 
1797df5e3d6SClaudio Fontana     cpu_list_remove(cpu);
180d9f24bf5SPaolo Bonzini }
181d9f24bf5SPaolo Bonzini 
182d9f24bf5SPaolo Bonzini void cpu_exec_initfn(CPUState *cpu)
183d9f24bf5SPaolo Bonzini {
184d9f24bf5SPaolo Bonzini     cpu->as = NULL;
185d9f24bf5SPaolo Bonzini     cpu->num_ases = 0;
186d9f24bf5SPaolo Bonzini 
187d9f24bf5SPaolo Bonzini #ifndef CONFIG_USER_ONLY
188d9f24bf5SPaolo Bonzini     cpu->thread_id = qemu_get_thread_id();
189d9f24bf5SPaolo Bonzini     cpu->memory = get_system_memory();
190d9f24bf5SPaolo Bonzini     object_ref(OBJECT(cpu->memory));
191d9f24bf5SPaolo Bonzini #endif
192d9f24bf5SPaolo Bonzini }
193d9f24bf5SPaolo Bonzini 
194d9f24bf5SPaolo Bonzini const char *parse_cpu_option(const char *cpu_option)
195d9f24bf5SPaolo Bonzini {
196d9f24bf5SPaolo Bonzini     ObjectClass *oc;
197d9f24bf5SPaolo Bonzini     CPUClass *cc;
198d9f24bf5SPaolo Bonzini     gchar **model_pieces;
199d9f24bf5SPaolo Bonzini     const char *cpu_type;
200d9f24bf5SPaolo Bonzini 
201d9f24bf5SPaolo Bonzini     model_pieces = g_strsplit(cpu_option, ",", 2);
202d9f24bf5SPaolo Bonzini     if (!model_pieces[0]) {
203d9f24bf5SPaolo Bonzini         error_report("-cpu option cannot be empty");
204d9f24bf5SPaolo Bonzini         exit(1);
205d9f24bf5SPaolo Bonzini     }
206d9f24bf5SPaolo Bonzini 
207d9f24bf5SPaolo Bonzini     oc = cpu_class_by_name(CPU_RESOLVING_TYPE, model_pieces[0]);
208d9f24bf5SPaolo Bonzini     if (oc == NULL) {
209d9f24bf5SPaolo Bonzini         error_report("unable to find CPU model '%s'", model_pieces[0]);
210d9f24bf5SPaolo Bonzini         g_strfreev(model_pieces);
211d9f24bf5SPaolo Bonzini         exit(EXIT_FAILURE);
212d9f24bf5SPaolo Bonzini     }
213d9f24bf5SPaolo Bonzini 
214d9f24bf5SPaolo Bonzini     cpu_type = object_class_get_name(oc);
215d9f24bf5SPaolo Bonzini     cc = CPU_CLASS(oc);
216d9f24bf5SPaolo Bonzini     cc->parse_features(cpu_type, model_pieces[1], &error_fatal);
217d9f24bf5SPaolo Bonzini     g_strfreev(model_pieces);
218d9f24bf5SPaolo Bonzini     return cpu_type;
219d9f24bf5SPaolo Bonzini }
220d9f24bf5SPaolo Bonzini 
221d9f24bf5SPaolo Bonzini #if defined(CONFIG_USER_ONLY)
222d9f24bf5SPaolo Bonzini void tb_invalidate_phys_addr(target_ulong addr)
223d9f24bf5SPaolo Bonzini {
224d9f24bf5SPaolo Bonzini     mmap_lock();
225d9f24bf5SPaolo Bonzini     tb_invalidate_phys_page_range(addr, addr + 1);
226d9f24bf5SPaolo Bonzini     mmap_unlock();
227d9f24bf5SPaolo Bonzini }
228d9f24bf5SPaolo Bonzini 
229d9f24bf5SPaolo Bonzini static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
230d9f24bf5SPaolo Bonzini {
231d9f24bf5SPaolo Bonzini     tb_invalidate_phys_addr(pc);
232d9f24bf5SPaolo Bonzini }
233d9f24bf5SPaolo Bonzini #else
234d9f24bf5SPaolo Bonzini void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs)
235d9f24bf5SPaolo Bonzini {
236d9f24bf5SPaolo Bonzini     ram_addr_t ram_addr;
237d9f24bf5SPaolo Bonzini     MemoryRegion *mr;
238d9f24bf5SPaolo Bonzini     hwaddr l = 1;
239d9f24bf5SPaolo Bonzini 
240d9f24bf5SPaolo Bonzini     if (!tcg_enabled()) {
241d9f24bf5SPaolo Bonzini         return;
242d9f24bf5SPaolo Bonzini     }
243d9f24bf5SPaolo Bonzini 
244d9f24bf5SPaolo Bonzini     RCU_READ_LOCK_GUARD();
245d9f24bf5SPaolo Bonzini     mr = address_space_translate(as, addr, &addr, &l, false, attrs);
246d9f24bf5SPaolo Bonzini     if (!(memory_region_is_ram(mr)
247d9f24bf5SPaolo Bonzini           || memory_region_is_romd(mr))) {
248d9f24bf5SPaolo Bonzini         return;
249d9f24bf5SPaolo Bonzini     }
250d9f24bf5SPaolo Bonzini     ram_addr = memory_region_get_ram_addr(mr) + addr;
251d9f24bf5SPaolo Bonzini     tb_invalidate_phys_page_range(ram_addr, ram_addr + 1);
252d9f24bf5SPaolo Bonzini }
253d9f24bf5SPaolo Bonzini 
254d9f24bf5SPaolo Bonzini static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
255d9f24bf5SPaolo Bonzini {
256d9f24bf5SPaolo Bonzini     /*
257d9f24bf5SPaolo Bonzini      * There may not be a virtual to physical translation for the pc
258d9f24bf5SPaolo Bonzini      * right now, but there may exist cached TB for this pc.
259d9f24bf5SPaolo Bonzini      * Flush the whole TB cache to force re-translation of such TBs.
260d9f24bf5SPaolo Bonzini      * This is heavyweight, but we're debugging anyway.
261d9f24bf5SPaolo Bonzini      */
262d9f24bf5SPaolo Bonzini     tb_flush(cpu);
263d9f24bf5SPaolo Bonzini }
264d9f24bf5SPaolo Bonzini #endif
265d9f24bf5SPaolo Bonzini 
266d9f24bf5SPaolo Bonzini /* Add a breakpoint.  */
267d9f24bf5SPaolo Bonzini int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags,
268d9f24bf5SPaolo Bonzini                           CPUBreakpoint **breakpoint)
269d9f24bf5SPaolo Bonzini {
270d9f24bf5SPaolo Bonzini     CPUBreakpoint *bp;
271d9f24bf5SPaolo Bonzini 
272d9f24bf5SPaolo Bonzini     bp = g_malloc(sizeof(*bp));
273d9f24bf5SPaolo Bonzini 
274d9f24bf5SPaolo Bonzini     bp->pc = pc;
275d9f24bf5SPaolo Bonzini     bp->flags = flags;
276d9f24bf5SPaolo Bonzini 
277d9f24bf5SPaolo Bonzini     /* keep all GDB-injected breakpoints in front */
278d9f24bf5SPaolo Bonzini     if (flags & BP_GDB) {
279d9f24bf5SPaolo Bonzini         QTAILQ_INSERT_HEAD(&cpu->breakpoints, bp, entry);
280d9f24bf5SPaolo Bonzini     } else {
281d9f24bf5SPaolo Bonzini         QTAILQ_INSERT_TAIL(&cpu->breakpoints, bp, entry);
282d9f24bf5SPaolo Bonzini     }
283d9f24bf5SPaolo Bonzini 
284d9f24bf5SPaolo Bonzini     breakpoint_invalidate(cpu, pc);
285d9f24bf5SPaolo Bonzini 
286d9f24bf5SPaolo Bonzini     if (breakpoint) {
287d9f24bf5SPaolo Bonzini         *breakpoint = bp;
288d9f24bf5SPaolo Bonzini     }
289d9f24bf5SPaolo Bonzini     return 0;
290d9f24bf5SPaolo Bonzini }
291d9f24bf5SPaolo Bonzini 
292d9f24bf5SPaolo Bonzini /* Remove a specific breakpoint.  */
293d9f24bf5SPaolo Bonzini int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags)
294d9f24bf5SPaolo Bonzini {
295d9f24bf5SPaolo Bonzini     CPUBreakpoint *bp;
296d9f24bf5SPaolo Bonzini 
297d9f24bf5SPaolo Bonzini     QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
298d9f24bf5SPaolo Bonzini         if (bp->pc == pc && bp->flags == flags) {
299d9f24bf5SPaolo Bonzini             cpu_breakpoint_remove_by_ref(cpu, bp);
300d9f24bf5SPaolo Bonzini             return 0;
301d9f24bf5SPaolo Bonzini         }
302d9f24bf5SPaolo Bonzini     }
303d9f24bf5SPaolo Bonzini     return -ENOENT;
304d9f24bf5SPaolo Bonzini }
305d9f24bf5SPaolo Bonzini 
306d9f24bf5SPaolo Bonzini /* Remove a specific breakpoint by reference.  */
307d9f24bf5SPaolo Bonzini void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *breakpoint)
308d9f24bf5SPaolo Bonzini {
309d9f24bf5SPaolo Bonzini     QTAILQ_REMOVE(&cpu->breakpoints, breakpoint, entry);
310d9f24bf5SPaolo Bonzini 
311d9f24bf5SPaolo Bonzini     breakpoint_invalidate(cpu, breakpoint->pc);
312d9f24bf5SPaolo Bonzini 
313d9f24bf5SPaolo Bonzini     g_free(breakpoint);
314d9f24bf5SPaolo Bonzini }
315d9f24bf5SPaolo Bonzini 
316d9f24bf5SPaolo Bonzini /* Remove all matching breakpoints. */
317d9f24bf5SPaolo Bonzini void cpu_breakpoint_remove_all(CPUState *cpu, int mask)
318d9f24bf5SPaolo Bonzini {
319d9f24bf5SPaolo Bonzini     CPUBreakpoint *bp, *next;
320d9f24bf5SPaolo Bonzini 
321d9f24bf5SPaolo Bonzini     QTAILQ_FOREACH_SAFE(bp, &cpu->breakpoints, entry, next) {
322d9f24bf5SPaolo Bonzini         if (bp->flags & mask) {
323d9f24bf5SPaolo Bonzini             cpu_breakpoint_remove_by_ref(cpu, bp);
324d9f24bf5SPaolo Bonzini         }
325d9f24bf5SPaolo Bonzini     }
326d9f24bf5SPaolo Bonzini }
327d9f24bf5SPaolo Bonzini 
328d9f24bf5SPaolo Bonzini /* enable or disable single step mode. EXCP_DEBUG is returned by the
329d9f24bf5SPaolo Bonzini    CPU loop after each instruction */
330d9f24bf5SPaolo Bonzini void cpu_single_step(CPUState *cpu, int enabled)
331d9f24bf5SPaolo Bonzini {
332d9f24bf5SPaolo Bonzini     if (cpu->singlestep_enabled != enabled) {
333d9f24bf5SPaolo Bonzini         cpu->singlestep_enabled = enabled;
334d9f24bf5SPaolo Bonzini         if (kvm_enabled()) {
335d9f24bf5SPaolo Bonzini             kvm_update_guest_debug(cpu, 0);
336d9f24bf5SPaolo Bonzini         } else {
337d9f24bf5SPaolo Bonzini             /* must flush all the translated code to avoid inconsistencies */
338d9f24bf5SPaolo Bonzini             /* XXX: only flush what is necessary */
339d9f24bf5SPaolo Bonzini             tb_flush(cpu);
340d9f24bf5SPaolo Bonzini         }
341d9f24bf5SPaolo Bonzini     }
342d9f24bf5SPaolo Bonzini }
343d9f24bf5SPaolo Bonzini 
344d9f24bf5SPaolo Bonzini void cpu_abort(CPUState *cpu, const char *fmt, ...)
345d9f24bf5SPaolo Bonzini {
346d9f24bf5SPaolo Bonzini     va_list ap;
347d9f24bf5SPaolo Bonzini     va_list ap2;
348d9f24bf5SPaolo Bonzini 
349d9f24bf5SPaolo Bonzini     va_start(ap, fmt);
350d9f24bf5SPaolo Bonzini     va_copy(ap2, ap);
351d9f24bf5SPaolo Bonzini     fprintf(stderr, "qemu: fatal: ");
352d9f24bf5SPaolo Bonzini     vfprintf(stderr, fmt, ap);
353d9f24bf5SPaolo Bonzini     fprintf(stderr, "\n");
354d9f24bf5SPaolo Bonzini     cpu_dump_state(cpu, stderr, CPU_DUMP_FPU | CPU_DUMP_CCOP);
355d9f24bf5SPaolo Bonzini     if (qemu_log_separate()) {
356d9f24bf5SPaolo Bonzini         FILE *logfile = qemu_log_lock();
357d9f24bf5SPaolo Bonzini         qemu_log("qemu: fatal: ");
358d9f24bf5SPaolo Bonzini         qemu_log_vprintf(fmt, ap2);
359d9f24bf5SPaolo Bonzini         qemu_log("\n");
360d9f24bf5SPaolo Bonzini         log_cpu_state(cpu, CPU_DUMP_FPU | CPU_DUMP_CCOP);
361d9f24bf5SPaolo Bonzini         qemu_log_flush();
362d9f24bf5SPaolo Bonzini         qemu_log_unlock(logfile);
363d9f24bf5SPaolo Bonzini         qemu_log_close();
364d9f24bf5SPaolo Bonzini     }
365d9f24bf5SPaolo Bonzini     va_end(ap2);
366d9f24bf5SPaolo Bonzini     va_end(ap);
367d9f24bf5SPaolo Bonzini     replay_finish();
368d9f24bf5SPaolo Bonzini #if defined(CONFIG_USER_ONLY)
369d9f24bf5SPaolo Bonzini     {
370d9f24bf5SPaolo Bonzini         struct sigaction act;
371d9f24bf5SPaolo Bonzini         sigfillset(&act.sa_mask);
372d9f24bf5SPaolo Bonzini         act.sa_handler = SIG_DFL;
373d9f24bf5SPaolo Bonzini         act.sa_flags = 0;
374d9f24bf5SPaolo Bonzini         sigaction(SIGABRT, &act, NULL);
375d9f24bf5SPaolo Bonzini     }
376d9f24bf5SPaolo Bonzini #endif
377d9f24bf5SPaolo Bonzini     abort();
378d9f24bf5SPaolo Bonzini }
379d9f24bf5SPaolo Bonzini 
380d9f24bf5SPaolo Bonzini /* physical memory access (slow version, mainly for debug) */
381d9f24bf5SPaolo Bonzini #if defined(CONFIG_USER_ONLY)
382d9f24bf5SPaolo Bonzini int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
383d9f24bf5SPaolo Bonzini                         void *ptr, target_ulong len, bool is_write)
384d9f24bf5SPaolo Bonzini {
385d9f24bf5SPaolo Bonzini     int flags;
386d9f24bf5SPaolo Bonzini     target_ulong l, page;
387d9f24bf5SPaolo Bonzini     void * p;
388d9f24bf5SPaolo Bonzini     uint8_t *buf = ptr;
389d9f24bf5SPaolo Bonzini 
390d9f24bf5SPaolo Bonzini     while (len > 0) {
391d9f24bf5SPaolo Bonzini         page = addr & TARGET_PAGE_MASK;
392d9f24bf5SPaolo Bonzini         l = (page + TARGET_PAGE_SIZE) - addr;
393d9f24bf5SPaolo Bonzini         if (l > len)
394d9f24bf5SPaolo Bonzini             l = len;
395d9f24bf5SPaolo Bonzini         flags = page_get_flags(page);
396d9f24bf5SPaolo Bonzini         if (!(flags & PAGE_VALID))
397d9f24bf5SPaolo Bonzini             return -1;
398d9f24bf5SPaolo Bonzini         if (is_write) {
399d9f24bf5SPaolo Bonzini             if (!(flags & PAGE_WRITE))
400d9f24bf5SPaolo Bonzini                 return -1;
401d9f24bf5SPaolo Bonzini             /* XXX: this code should not depend on lock_user */
402d9f24bf5SPaolo Bonzini             if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
403d9f24bf5SPaolo Bonzini                 return -1;
404d9f24bf5SPaolo Bonzini             memcpy(p, buf, l);
405d9f24bf5SPaolo Bonzini             unlock_user(p, addr, l);
406d9f24bf5SPaolo Bonzini         } else {
407d9f24bf5SPaolo Bonzini             if (!(flags & PAGE_READ))
408d9f24bf5SPaolo Bonzini                 return -1;
409d9f24bf5SPaolo Bonzini             /* XXX: this code should not depend on lock_user */
410d9f24bf5SPaolo Bonzini             if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
411d9f24bf5SPaolo Bonzini                 return -1;
412d9f24bf5SPaolo Bonzini             memcpy(buf, p, l);
413d9f24bf5SPaolo Bonzini             unlock_user(p, addr, 0);
414d9f24bf5SPaolo Bonzini         }
415d9f24bf5SPaolo Bonzini         len -= l;
416d9f24bf5SPaolo Bonzini         buf += l;
417d9f24bf5SPaolo Bonzini         addr += l;
418d9f24bf5SPaolo Bonzini     }
419d9f24bf5SPaolo Bonzini     return 0;
420d9f24bf5SPaolo Bonzini }
421d9f24bf5SPaolo Bonzini #endif
422d9f24bf5SPaolo Bonzini 
423d9f24bf5SPaolo Bonzini bool target_words_bigendian(void)
424d9f24bf5SPaolo Bonzini {
425d9f24bf5SPaolo Bonzini #if defined(TARGET_WORDS_BIGENDIAN)
426d9f24bf5SPaolo Bonzini     return true;
427d9f24bf5SPaolo Bonzini #else
428d9f24bf5SPaolo Bonzini     return false;
429d9f24bf5SPaolo Bonzini #endif
430d9f24bf5SPaolo Bonzini }
431d9f24bf5SPaolo Bonzini 
432d9f24bf5SPaolo Bonzini void page_size_init(void)
433d9f24bf5SPaolo Bonzini {
434d9f24bf5SPaolo Bonzini     /* NOTE: we can always suppose that qemu_host_page_size >=
435d9f24bf5SPaolo Bonzini        TARGET_PAGE_SIZE */
436d9f24bf5SPaolo Bonzini     if (qemu_host_page_size == 0) {
437d9f24bf5SPaolo Bonzini         qemu_host_page_size = qemu_real_host_page_size;
438d9f24bf5SPaolo Bonzini     }
439d9f24bf5SPaolo Bonzini     if (qemu_host_page_size < TARGET_PAGE_SIZE) {
440d9f24bf5SPaolo Bonzini         qemu_host_page_size = TARGET_PAGE_SIZE;
441d9f24bf5SPaolo Bonzini     }
442d9f24bf5SPaolo Bonzini     qemu_host_page_mask = -(intptr_t)qemu_host_page_size;
443d9f24bf5SPaolo Bonzini }
444