xref: /qemu/cpu-target.c (revision 425082612c012843d8b33fa0d35966adf5600c47)
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"
27dfa47531SGavin Shan #include "qemu/qemu-print.h"
28d9f24bf5SPaolo Bonzini #include "migration/vmstate.h"
29d9f24bf5SPaolo Bonzini #ifdef CONFIG_USER_ONLY
30d9f24bf5SPaolo Bonzini #include "qemu.h"
31d9f24bf5SPaolo Bonzini #else
328b80bd28SPhilippe Mathieu-Daudé #include "hw/core/sysemu-cpu-ops.h"
33d9f24bf5SPaolo Bonzini #include "exec/address-spaces.h"
345f8d88bdSPhilippe Mathieu-Daudé #include "exec/memory.h"
35d9f24bf5SPaolo Bonzini #endif
36412ae126SMads Ynddal #include "sysemu/cpus.h"
37d9f24bf5SPaolo Bonzini #include "sysemu/tcg.h"
38*42508261SPhilippe Mathieu-Daudé #include "exec/tswap.h"
395b5968c4SPhilippe Mathieu-Daudé #include "exec/replay-core.h"
40377bf6f3SPhilippe Mathieu-Daudé #include "exec/cpu-common.h"
413b04508cSPhilippe Mathieu-Daudé #include "exec/exec-all.h"
42548c9609SAlex Bennée #include "exec/tb-flush.h"
433b9bd3f4SPaolo Bonzini #include "exec/translate-all.h"
44d9f24bf5SPaolo Bonzini #include "exec/log.h"
4530565f10SClaudio Fontana #include "hw/core/accel-cpu.h"
46ad1a706fSRichard Henderson #include "trace/trace-root.h"
473b04508cSPhilippe Mathieu-Daudé #include "qemu/accel.h"
48d9f24bf5SPaolo Bonzini 
49d9f24bf5SPaolo Bonzini #ifndef CONFIG_USER_ONLY
50d9f24bf5SPaolo Bonzini static int cpu_common_post_load(void *opaque, int version_id)
51d9f24bf5SPaolo Bonzini {
52d9f24bf5SPaolo Bonzini     CPUState *cpu = opaque;
53d9f24bf5SPaolo Bonzini 
54d9f24bf5SPaolo Bonzini     /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
55d9f24bf5SPaolo Bonzini        version_id is increased. */
56d9f24bf5SPaolo Bonzini     cpu->interrupt_request &= ~0x01;
57d9f24bf5SPaolo Bonzini     tlb_flush(cpu);
58d9f24bf5SPaolo Bonzini 
59d9f24bf5SPaolo Bonzini     /* loadvm has just updated the content of RAM, bypassing the
60d9f24bf5SPaolo Bonzini      * usual mechanisms that ensure we flush TBs for writes to
61d9f24bf5SPaolo Bonzini      * memory we've translated code from. So we must flush all TBs,
62d9f24bf5SPaolo Bonzini      * which will now be stale.
63d9f24bf5SPaolo Bonzini      */
64d9f24bf5SPaolo Bonzini     tb_flush(cpu);
65d9f24bf5SPaolo Bonzini 
66d9f24bf5SPaolo Bonzini     return 0;
67d9f24bf5SPaolo Bonzini }
68d9f24bf5SPaolo Bonzini 
69d9f24bf5SPaolo Bonzini static int cpu_common_pre_load(void *opaque)
70d9f24bf5SPaolo Bonzini {
71d9f24bf5SPaolo Bonzini     CPUState *cpu = opaque;
72d9f24bf5SPaolo Bonzini 
73d9f24bf5SPaolo Bonzini     cpu->exception_index = -1;
74d9f24bf5SPaolo Bonzini 
75d9f24bf5SPaolo Bonzini     return 0;
76d9f24bf5SPaolo Bonzini }
77d9f24bf5SPaolo Bonzini 
78d9f24bf5SPaolo Bonzini static bool cpu_common_exception_index_needed(void *opaque)
79d9f24bf5SPaolo Bonzini {
80d9f24bf5SPaolo Bonzini     CPUState *cpu = opaque;
81d9f24bf5SPaolo Bonzini 
82d9f24bf5SPaolo Bonzini     return tcg_enabled() && cpu->exception_index != -1;
83d9f24bf5SPaolo Bonzini }
84d9f24bf5SPaolo Bonzini 
85d9f24bf5SPaolo Bonzini static const VMStateDescription vmstate_cpu_common_exception_index = {
86d9f24bf5SPaolo Bonzini     .name = "cpu_common/exception_index",
87d9f24bf5SPaolo Bonzini     .version_id = 1,
88d9f24bf5SPaolo Bonzini     .minimum_version_id = 1,
89d9f24bf5SPaolo Bonzini     .needed = cpu_common_exception_index_needed,
90ee1381ceSRichard Henderson     .fields = (const VMStateField[]) {
91d9f24bf5SPaolo Bonzini         VMSTATE_INT32(exception_index, CPUState),
92d9f24bf5SPaolo Bonzini         VMSTATE_END_OF_LIST()
93d9f24bf5SPaolo Bonzini     }
94d9f24bf5SPaolo Bonzini };
95d9f24bf5SPaolo Bonzini 
96d9f24bf5SPaolo Bonzini static bool cpu_common_crash_occurred_needed(void *opaque)
97d9f24bf5SPaolo Bonzini {
98d9f24bf5SPaolo Bonzini     CPUState *cpu = opaque;
99d9f24bf5SPaolo Bonzini 
100d9f24bf5SPaolo Bonzini     return cpu->crash_occurred;
101d9f24bf5SPaolo Bonzini }
102d9f24bf5SPaolo Bonzini 
103d9f24bf5SPaolo Bonzini static const VMStateDescription vmstate_cpu_common_crash_occurred = {
104d9f24bf5SPaolo Bonzini     .name = "cpu_common/crash_occurred",
105d9f24bf5SPaolo Bonzini     .version_id = 1,
106d9f24bf5SPaolo Bonzini     .minimum_version_id = 1,
107d9f24bf5SPaolo Bonzini     .needed = cpu_common_crash_occurred_needed,
108ee1381ceSRichard Henderson     .fields = (const VMStateField[]) {
109d9f24bf5SPaolo Bonzini         VMSTATE_BOOL(crash_occurred, CPUState),
110d9f24bf5SPaolo Bonzini         VMSTATE_END_OF_LIST()
111d9f24bf5SPaolo Bonzini     }
112d9f24bf5SPaolo Bonzini };
113d9f24bf5SPaolo Bonzini 
114d9f24bf5SPaolo Bonzini const VMStateDescription vmstate_cpu_common = {
115d9f24bf5SPaolo Bonzini     .name = "cpu_common",
116d9f24bf5SPaolo Bonzini     .version_id = 1,
117d9f24bf5SPaolo Bonzini     .minimum_version_id = 1,
118d9f24bf5SPaolo Bonzini     .pre_load = cpu_common_pre_load,
119d9f24bf5SPaolo Bonzini     .post_load = cpu_common_post_load,
120ee1381ceSRichard Henderson     .fields = (const VMStateField[]) {
121d9f24bf5SPaolo Bonzini         VMSTATE_UINT32(halted, CPUState),
122d9f24bf5SPaolo Bonzini         VMSTATE_UINT32(interrupt_request, CPUState),
123d9f24bf5SPaolo Bonzini         VMSTATE_END_OF_LIST()
124d9f24bf5SPaolo Bonzini     },
125ee1381ceSRichard Henderson     .subsections = (const VMStateDescription * const []) {
126d9f24bf5SPaolo Bonzini         &vmstate_cpu_common_exception_index,
127d9f24bf5SPaolo Bonzini         &vmstate_cpu_common_crash_occurred,
128d9f24bf5SPaolo Bonzini         NULL
129d9f24bf5SPaolo Bonzini     }
130d9f24bf5SPaolo Bonzini };
131d9f24bf5SPaolo Bonzini #endif
132d9f24bf5SPaolo Bonzini 
13379a99091SPhilippe Mathieu-Daudé bool cpu_exec_realizefn(CPUState *cpu, Error **errp)
134d9f24bf5SPaolo Bonzini {
1356fbdff87SAlex Bennée     /* cache the cpu class for the hotpath */
1366fbdff87SAlex Bennée     cpu->cc = CPU_GET_CLASS(cpu);
137d9f24bf5SPaolo Bonzini 
138bd684b2fSPhilippe Mathieu-Daudé     if (!accel_cpu_common_realize(cpu, errp)) {
13979a99091SPhilippe Mathieu-Daudé         return false;
1409ea057dcSClaudio Fontana     }
1414e4fa6c1SRichard Henderson 
1424e4fa6c1SRichard Henderson     /* Wait until cpu initialization complete before exposing cpu. */
1434e4fa6c1SRichard Henderson     cpu_list_add(cpu);
1444e4fa6c1SRichard Henderson 
1457df5e3d6SClaudio Fontana #ifdef CONFIG_USER_ONLY
1464336073bSPhilippe Mathieu-Daudé     assert(qdev_get_vmsd(DEVICE(cpu)) == NULL ||
1474336073bSPhilippe Mathieu-Daudé            qdev_get_vmsd(DEVICE(cpu))->unmigratable);
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     }
1526fbdff87SAlex Bennée     if (cpu->cc->sysemu_ops->legacy_vmsd != NULL) {
1536fbdff87SAlex Bennée         vmstate_register(NULL, cpu->cpu_index, cpu->cc->sysemu_ops->legacy_vmsd, cpu);
1547df5e3d6SClaudio Fontana     }
1557df5e3d6SClaudio Fontana #endif /* CONFIG_USER_ONLY */
15679a99091SPhilippe Mathieu-Daudé 
15779a99091SPhilippe Mathieu-Daudé     return true;
1587df5e3d6SClaudio Fontana }
1597df5e3d6SClaudio Fontana 
1607df5e3d6SClaudio Fontana void cpu_exec_unrealizefn(CPUState *cpu)
1617df5e3d6SClaudio Fontana {
162feece4d0SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
1637df5e3d6SClaudio Fontana     CPUClass *cc = CPU_GET_CLASS(cpu);
164d9f24bf5SPaolo Bonzini 
165feece4d0SPhilippe Mathieu-Daudé     if (cc->sysemu_ops->legacy_vmsd != NULL) {
166feece4d0SPhilippe Mathieu-Daudé         vmstate_unregister(NULL, cc->sysemu_ops->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
1724731f89bSEmilio Cota 
1737df5e3d6SClaudio Fontana     cpu_list_remove(cpu);
1744731f89bSEmilio Cota     /*
1754731f89bSEmilio Cota      * Now that the vCPU has been removed from the RCU list, we can call
1761aa1d830SPhilippe Mathieu-Daudé      * accel_cpu_common_unrealize, which may free fields using call_rcu.
1774731f89bSEmilio Cota      */
1781aa1d830SPhilippe Mathieu-Daudé     accel_cpu_common_unrealize(cpu);
179d9f24bf5SPaolo Bonzini }
180d9f24bf5SPaolo Bonzini 
181995b87deSRichard Henderson /*
1826e8dcacdSRichard Henderson  * This can't go in hw/core/cpu.c because that file is compiled only
1836e8dcacdSRichard Henderson  * once for both user-mode and system builds.
1846e8dcacdSRichard Henderson  */
1856e8dcacdSRichard Henderson static Property cpu_common_props[] = {
1866e8dcacdSRichard Henderson #ifdef CONFIG_USER_ONLY
1876e8dcacdSRichard Henderson     /*
1886e8dcacdSRichard Henderson      * Create a property for the user-only object, so users can
1896e8dcacdSRichard Henderson      * adjust prctl(PR_SET_UNALIGN) from the command-line.
1906e8dcacdSRichard Henderson      * Has no effect if the target does not support the feature.
1916e8dcacdSRichard Henderson      */
1926e8dcacdSRichard Henderson     DEFINE_PROP_BOOL("prctl-unalign-sigbus", CPUState,
1936e8dcacdSRichard Henderson                      prctl_unalign_sigbus, false),
1946e8dcacdSRichard Henderson #else
1956e8dcacdSRichard Henderson     /*
19654b99122SPhilippe Mathieu-Daudé      * Create a memory property for system CPU object, so users can
1976e8dcacdSRichard Henderson      * wire up its memory.  The default if no link is set up is to use
198995b87deSRichard Henderson      * the system address space.
199995b87deSRichard Henderson      */
200995b87deSRichard Henderson     DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION,
201995b87deSRichard Henderson                      MemoryRegion *),
202995b87deSRichard Henderson #endif
203995b87deSRichard Henderson     DEFINE_PROP_END_OF_LIST(),
204995b87deSRichard Henderson };
205995b87deSRichard Henderson 
2060f9237f4SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
2070c3c25fcSPeter Maydell static bool cpu_get_start_powered_off(Object *obj, Error **errp)
2080c3c25fcSPeter Maydell {
2090c3c25fcSPeter Maydell     CPUState *cpu = CPU(obj);
2100c3c25fcSPeter Maydell     return cpu->start_powered_off;
2110c3c25fcSPeter Maydell }
2120c3c25fcSPeter Maydell 
2130c3c25fcSPeter Maydell static void cpu_set_start_powered_off(Object *obj, bool value, Error **errp)
2140c3c25fcSPeter Maydell {
2150c3c25fcSPeter Maydell     CPUState *cpu = CPU(obj);
2160c3c25fcSPeter Maydell     cpu->start_powered_off = value;
2170c3c25fcSPeter Maydell }
2180f9237f4SPhilippe Mathieu-Daudé #endif
2190c3c25fcSPeter Maydell 
220995b87deSRichard Henderson void cpu_class_init_props(DeviceClass *dc)
221995b87deSRichard Henderson {
2220f9237f4SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
2230c3c25fcSPeter Maydell     ObjectClass *oc = OBJECT_CLASS(dc);
2240c3c25fcSPeter Maydell 
2250c3c25fcSPeter Maydell     /*
2260c3c25fcSPeter Maydell      * We can't use DEFINE_PROP_BOOL in the Property array for this
2270c3c25fcSPeter Maydell      * property, because we want this to be settable after realize.
2280c3c25fcSPeter Maydell      */
2290c3c25fcSPeter Maydell     object_class_property_add_bool(oc, "start-powered-off",
2300c3c25fcSPeter Maydell                                    cpu_get_start_powered_off,
2310c3c25fcSPeter Maydell                                    cpu_set_start_powered_off);
2320f9237f4SPhilippe Mathieu-Daudé #endif
2330f9237f4SPhilippe Mathieu-Daudé 
2340f9237f4SPhilippe Mathieu-Daudé     device_class_set_props(dc, cpu_common_props);
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 
249445946f4SGavin Shan char *cpu_model_from_type(const char *typename)
250445946f4SGavin Shan {
251445946f4SGavin Shan     const char *suffix = "-" CPU_RESOLVING_TYPE;
252445946f4SGavin Shan 
253445946f4SGavin Shan     if (!object_class_by_name(typename)) {
254445946f4SGavin Shan         return NULL;
255445946f4SGavin Shan     }
256445946f4SGavin Shan 
257445946f4SGavin Shan     if (g_str_has_suffix(typename, suffix)) {
258445946f4SGavin Shan         return g_strndup(typename, strlen(typename) - strlen(suffix));
259445946f4SGavin Shan     }
260445946f4SGavin Shan 
261445946f4SGavin Shan     return g_strdup(typename);
262445946f4SGavin Shan }
263445946f4SGavin Shan 
264d9f24bf5SPaolo Bonzini const char *parse_cpu_option(const char *cpu_option)
265d9f24bf5SPaolo Bonzini {
266d9f24bf5SPaolo Bonzini     ObjectClass *oc;
267d9f24bf5SPaolo Bonzini     CPUClass *cc;
268d9f24bf5SPaolo Bonzini     gchar **model_pieces;
269d9f24bf5SPaolo Bonzini     const char *cpu_type;
270d9f24bf5SPaolo Bonzini 
271d9f24bf5SPaolo Bonzini     model_pieces = g_strsplit(cpu_option, ",", 2);
272d9f24bf5SPaolo Bonzini     if (!model_pieces[0]) {
273d9f24bf5SPaolo Bonzini         error_report("-cpu option cannot be empty");
274d9f24bf5SPaolo Bonzini         exit(1);
275d9f24bf5SPaolo Bonzini     }
276d9f24bf5SPaolo Bonzini 
277d9f24bf5SPaolo Bonzini     oc = cpu_class_by_name(CPU_RESOLVING_TYPE, model_pieces[0]);
278d9f24bf5SPaolo Bonzini     if (oc == NULL) {
279d9f24bf5SPaolo Bonzini         error_report("unable to find CPU model '%s'", model_pieces[0]);
280d9f24bf5SPaolo Bonzini         g_strfreev(model_pieces);
281d9f24bf5SPaolo Bonzini         exit(EXIT_FAILURE);
282d9f24bf5SPaolo Bonzini     }
283d9f24bf5SPaolo Bonzini 
284d9f24bf5SPaolo Bonzini     cpu_type = object_class_get_name(oc);
285d9f24bf5SPaolo Bonzini     cc = CPU_CLASS(oc);
286d9f24bf5SPaolo Bonzini     cc->parse_features(cpu_type, model_pieces[1], &error_fatal);
287d9f24bf5SPaolo Bonzini     g_strfreev(model_pieces);
288d9f24bf5SPaolo Bonzini     return cpu_type;
289d9f24bf5SPaolo Bonzini }
290d9f24bf5SPaolo Bonzini 
291dfa47531SGavin Shan #ifndef cpu_list
292dfa47531SGavin Shan static void cpu_list_entry(gpointer data, gpointer user_data)
293dfa47531SGavin Shan {
294dfa47531SGavin Shan     CPUClass *cc = CPU_CLASS(OBJECT_CLASS(data));
295dfa47531SGavin Shan     const char *typename = object_class_get_name(OBJECT_CLASS(data));
296dfa47531SGavin Shan     g_autofree char *model = cpu_model_from_type(typename);
297dfa47531SGavin Shan 
298dfa47531SGavin Shan     if (cc->deprecation_note) {
299dfa47531SGavin Shan         qemu_printf("  %s (deprecated)\n", model);
300dfa47531SGavin Shan     } else {
301dfa47531SGavin Shan         qemu_printf("  %s\n", model);
302dfa47531SGavin Shan     }
303dfa47531SGavin Shan }
304dfa47531SGavin Shan 
305dfa47531SGavin Shan static void cpu_list(void)
306dfa47531SGavin Shan {
307dfa47531SGavin Shan     GSList *list;
308dfa47531SGavin Shan 
309dfa47531SGavin Shan     list = object_class_get_list_sorted(TYPE_CPU, false);
310dfa47531SGavin Shan     qemu_printf("Available CPUs:\n");
311dfa47531SGavin Shan     g_slist_foreach(list, cpu_list_entry, NULL);
312dfa47531SGavin Shan     g_slist_free(list);
313dfa47531SGavin Shan }
314dfa47531SGavin Shan #endif
315dfa47531SGavin Shan 
316c138c3b8SThomas Huth void list_cpus(void)
317377bf6f3SPhilippe Mathieu-Daudé {
318377bf6f3SPhilippe Mathieu-Daudé     cpu_list();
319377bf6f3SPhilippe Mathieu-Daudé }
320377bf6f3SPhilippe Mathieu-Daudé 
321d9f24bf5SPaolo Bonzini /* enable or disable single step mode. EXCP_DEBUG is returned by the
322d9f24bf5SPaolo Bonzini    CPU loop after each instruction */
323d9f24bf5SPaolo Bonzini void cpu_single_step(CPUState *cpu, int enabled)
324d9f24bf5SPaolo Bonzini {
325d9f24bf5SPaolo Bonzini     if (cpu->singlestep_enabled != enabled) {
326d9f24bf5SPaolo Bonzini         cpu->singlestep_enabled = enabled;
327412ae126SMads Ynddal 
328412ae126SMads Ynddal #if !defined(CONFIG_USER_ONLY)
329412ae126SMads Ynddal         const AccelOpsClass *ops = cpus_get_accel();
330412ae126SMads Ynddal         if (ops->update_guest_debug) {
331412ae126SMads Ynddal             ops->update_guest_debug(cpu);
332d9f24bf5SPaolo Bonzini         }
333412ae126SMads Ynddal #endif
334412ae126SMads Ynddal 
335ad1a706fSRichard Henderson         trace_breakpoint_singlestep(cpu->cpu_index, enabled);
336d9f24bf5SPaolo Bonzini     }
337d9f24bf5SPaolo Bonzini }
338d9f24bf5SPaolo Bonzini 
339d9f24bf5SPaolo Bonzini void cpu_abort(CPUState *cpu, const char *fmt, ...)
340d9f24bf5SPaolo Bonzini {
341d9f24bf5SPaolo Bonzini     va_list ap;
342d9f24bf5SPaolo Bonzini     va_list ap2;
343d9f24bf5SPaolo Bonzini 
344d9f24bf5SPaolo Bonzini     va_start(ap, fmt);
345d9f24bf5SPaolo Bonzini     va_copy(ap2, ap);
346d9f24bf5SPaolo Bonzini     fprintf(stderr, "qemu: fatal: ");
347d9f24bf5SPaolo Bonzini     vfprintf(stderr, fmt, ap);
348d9f24bf5SPaolo Bonzini     fprintf(stderr, "\n");
349d9f24bf5SPaolo Bonzini     cpu_dump_state(cpu, stderr, CPU_DUMP_FPU | CPU_DUMP_CCOP);
350d9f24bf5SPaolo Bonzini     if (qemu_log_separate()) {
351c60f599bSRichard Henderson         FILE *logfile = qemu_log_trylock();
35278b54858SRichard Henderson         if (logfile) {
35378b54858SRichard Henderson             fprintf(logfile, "qemu: fatal: ");
35478b54858SRichard Henderson             vfprintf(logfile, fmt, ap2);
35578b54858SRichard Henderson             fprintf(logfile, "\n");
35678b54858SRichard Henderson             cpu_dump_state(cpu, logfile, CPU_DUMP_FPU | CPU_DUMP_CCOP);
357d9f24bf5SPaolo Bonzini             qemu_log_unlock(logfile);
35878b54858SRichard Henderson         }
359d9f24bf5SPaolo Bonzini     }
360d9f24bf5SPaolo Bonzini     va_end(ap2);
361d9f24bf5SPaolo Bonzini     va_end(ap);
362d9f24bf5SPaolo Bonzini     replay_finish();
363d9f24bf5SPaolo Bonzini #if defined(CONFIG_USER_ONLY)
364d9f24bf5SPaolo Bonzini     {
365d9f24bf5SPaolo Bonzini         struct sigaction act;
366d9f24bf5SPaolo Bonzini         sigfillset(&act.sa_mask);
367d9f24bf5SPaolo Bonzini         act.sa_handler = SIG_DFL;
368d9f24bf5SPaolo Bonzini         act.sa_flags = 0;
369d9f24bf5SPaolo Bonzini         sigaction(SIGABRT, &act, NULL);
370d9f24bf5SPaolo Bonzini     }
371d9f24bf5SPaolo Bonzini #endif
372d9f24bf5SPaolo Bonzini     abort();
373d9f24bf5SPaolo Bonzini }
374d9f24bf5SPaolo Bonzini 
375d9f24bf5SPaolo Bonzini /* physical memory access (slow version, mainly for debug) */
376d9f24bf5SPaolo Bonzini #if defined(CONFIG_USER_ONLY)
37773842ef0SPhilippe Mathieu-Daudé int cpu_memory_rw_debug(CPUState *cpu, vaddr addr,
37873842ef0SPhilippe Mathieu-Daudé                         void *ptr, size_t len, bool is_write)
379d9f24bf5SPaolo Bonzini {
380d9f24bf5SPaolo Bonzini     int flags;
38173842ef0SPhilippe Mathieu-Daudé     vaddr l, page;
382d9f24bf5SPaolo Bonzini     void * p;
383d9f24bf5SPaolo Bonzini     uint8_t *buf = ptr;
38487ab2704SIlya Leoshkevich     ssize_t written;
38587ab2704SIlya Leoshkevich     int ret = -1;
38687ab2704SIlya Leoshkevich     int fd = -1;
387d9f24bf5SPaolo Bonzini 
388d9f24bf5SPaolo Bonzini     while (len > 0) {
389d9f24bf5SPaolo Bonzini         page = addr & TARGET_PAGE_MASK;
390d9f24bf5SPaolo Bonzini         l = (page + TARGET_PAGE_SIZE) - addr;
391d9f24bf5SPaolo Bonzini         if (l > len)
392d9f24bf5SPaolo Bonzini             l = len;
393d9f24bf5SPaolo Bonzini         flags = page_get_flags(page);
39487ab2704SIlya Leoshkevich         if (!(flags & PAGE_VALID)) {
39587ab2704SIlya Leoshkevich             goto out_close;
39687ab2704SIlya Leoshkevich         }
397d9f24bf5SPaolo Bonzini         if (is_write) {
39887ab2704SIlya Leoshkevich             if (flags & PAGE_WRITE) {
399d9f24bf5SPaolo Bonzini                 /* XXX: this code should not depend on lock_user */
40087ab2704SIlya Leoshkevich                 p = lock_user(VERIFY_WRITE, addr, l, 0);
40187ab2704SIlya Leoshkevich                 if (!p) {
40287ab2704SIlya Leoshkevich                     goto out_close;
40387ab2704SIlya Leoshkevich                 }
404d9f24bf5SPaolo Bonzini                 memcpy(p, buf, l);
405d9f24bf5SPaolo Bonzini                 unlock_user(p, addr, l);
406d9f24bf5SPaolo Bonzini             } else {
40787ab2704SIlya Leoshkevich                 /* Bypass the host page protection using ptrace. */
40887ab2704SIlya Leoshkevich                 if (fd == -1) {
40987ab2704SIlya Leoshkevich                     fd = open("/proc/self/mem", O_WRONLY);
41087ab2704SIlya Leoshkevich                     if (fd == -1) {
41187ab2704SIlya Leoshkevich                         goto out;
41287ab2704SIlya Leoshkevich                     }
41387ab2704SIlya Leoshkevich                 }
41487ab2704SIlya Leoshkevich                 /*
41587ab2704SIlya Leoshkevich                  * If there is a TranslationBlock and we weren't bypassing the
41687ab2704SIlya Leoshkevich                  * host page protection, the memcpy() above would SEGV,
41787ab2704SIlya Leoshkevich                  * ultimately leading to page_unprotect(). So invalidate the
41887ab2704SIlya Leoshkevich                  * translations manually. Both invalidation and pwrite() must
41987ab2704SIlya Leoshkevich                  * be under mmap_lock() in order to prevent the creation of
42087ab2704SIlya Leoshkevich                  * another TranslationBlock in between.
42187ab2704SIlya Leoshkevich                  */
42287ab2704SIlya Leoshkevich                 mmap_lock();
42387ab2704SIlya Leoshkevich                 tb_invalidate_phys_range(addr, addr + l - 1);
42487ab2704SIlya Leoshkevich                 written = pwrite(fd, buf, l,
42587ab2704SIlya Leoshkevich                                  (off_t)(uintptr_t)g2h_untagged(addr));
42687ab2704SIlya Leoshkevich                 mmap_unlock();
42787ab2704SIlya Leoshkevich                 if (written != l) {
42887ab2704SIlya Leoshkevich                     goto out_close;
42987ab2704SIlya Leoshkevich                 }
43087ab2704SIlya Leoshkevich             }
43187ab2704SIlya Leoshkevich         } else if (flags & PAGE_READ) {
432d9f24bf5SPaolo Bonzini             /* XXX: this code should not depend on lock_user */
43387ab2704SIlya Leoshkevich             p = lock_user(VERIFY_READ, addr, l, 1);
43487ab2704SIlya Leoshkevich             if (!p) {
43587ab2704SIlya Leoshkevich                 goto out_close;
43687ab2704SIlya Leoshkevich             }
437d9f24bf5SPaolo Bonzini             memcpy(buf, p, l);
438d9f24bf5SPaolo Bonzini             unlock_user(p, addr, 0);
43987ab2704SIlya Leoshkevich         } else {
44087ab2704SIlya Leoshkevich             /* Bypass the host page protection using ptrace. */
44187ab2704SIlya Leoshkevich             if (fd == -1) {
44287ab2704SIlya Leoshkevich                 fd = open("/proc/self/mem", O_RDONLY);
44387ab2704SIlya Leoshkevich                 if (fd == -1) {
44487ab2704SIlya Leoshkevich                     goto out;
44587ab2704SIlya Leoshkevich                 }
44687ab2704SIlya Leoshkevich             }
44787ab2704SIlya Leoshkevich             if (pread(fd, buf, l,
44887ab2704SIlya Leoshkevich                       (off_t)(uintptr_t)g2h_untagged(addr)) != l) {
44987ab2704SIlya Leoshkevich                 goto out_close;
45087ab2704SIlya Leoshkevich             }
451d9f24bf5SPaolo Bonzini         }
452d9f24bf5SPaolo Bonzini         len -= l;
453d9f24bf5SPaolo Bonzini         buf += l;
454d9f24bf5SPaolo Bonzini         addr += l;
455d9f24bf5SPaolo Bonzini     }
45687ab2704SIlya Leoshkevich     ret = 0;
45787ab2704SIlya Leoshkevich out_close:
45887ab2704SIlya Leoshkevich     if (fd != -1) {
45987ab2704SIlya Leoshkevich         close(fd);
46087ab2704SIlya Leoshkevich     }
46187ab2704SIlya Leoshkevich out:
46287ab2704SIlya Leoshkevich     return ret;
463d9f24bf5SPaolo Bonzini }
464d9f24bf5SPaolo Bonzini #endif
465d9f24bf5SPaolo Bonzini 
466d9f24bf5SPaolo Bonzini bool target_words_bigendian(void)
467d9f24bf5SPaolo Bonzini {
468ded625e7SThomas Huth     return TARGET_BIG_ENDIAN;
469d9f24bf5SPaolo Bonzini }
470d9f24bf5SPaolo Bonzini 
4711077f50bSThomas Huth const char *target_name(void)
4721077f50bSThomas Huth {
4731077f50bSThomas Huth     return TARGET_NAME;
4741077f50bSThomas Huth }
475