xref: /openbmc/qemu/cpu-target.c (revision d16cab541ab9217977e2a39abf3d79f914146741)
1fe0007f3SPhilippe Mathieu-Daudé /*
2fe0007f3SPhilippe Mathieu-Daudé  * Target-specific parts of the CPU object
3fe0007f3SPhilippe Mathieu-Daudé  *
4fe0007f3SPhilippe Mathieu-Daudé  *  Copyright (c) 2003 Fabrice Bellard
5fe0007f3SPhilippe Mathieu-Daudé  *
6fe0007f3SPhilippe Mathieu-Daudé  * This library is free software; you can redistribute it and/or
7fe0007f3SPhilippe Mathieu-Daudé  * modify it under the terms of the GNU Lesser General Public
8fe0007f3SPhilippe Mathieu-Daudé  * License as published by the Free Software Foundation; either
9fe0007f3SPhilippe Mathieu-Daudé  * version 2 of the License, or (at your option) any later version.
10fe0007f3SPhilippe Mathieu-Daudé  *
11fe0007f3SPhilippe Mathieu-Daudé  * This library is distributed in the hope that it will be useful,
12fe0007f3SPhilippe Mathieu-Daudé  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13fe0007f3SPhilippe Mathieu-Daudé  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14fe0007f3SPhilippe Mathieu-Daudé  * Lesser General Public License for more details.
15fe0007f3SPhilippe Mathieu-Daudé  *
16fe0007f3SPhilippe Mathieu-Daudé  * You should have received a copy of the GNU Lesser General Public
17fe0007f3SPhilippe Mathieu-Daudé  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18fe0007f3SPhilippe Mathieu-Daudé  */
19fe0007f3SPhilippe Mathieu-Daudé 
20fe0007f3SPhilippe Mathieu-Daudé #include "qemu/osdep.h"
21fe0007f3SPhilippe Mathieu-Daudé #include "qapi/error.h"
22fe0007f3SPhilippe Mathieu-Daudé 
23fe0007f3SPhilippe Mathieu-Daudé #include "exec/target_page.h"
24*74781c08SPhilippe Mathieu-Daudé #include "exec/page-protection.h"
25fe0007f3SPhilippe Mathieu-Daudé #include "hw/qdev-core.h"
26fe0007f3SPhilippe Mathieu-Daudé #include "hw/qdev-properties.h"
27fe0007f3SPhilippe Mathieu-Daudé #include "qemu/error-report.h"
28dfa47531SGavin Shan #include "qemu/qemu-print.h"
29fe0007f3SPhilippe Mathieu-Daudé #include "migration/vmstate.h"
30fe0007f3SPhilippe Mathieu-Daudé #ifdef CONFIG_USER_ONLY
31fe0007f3SPhilippe Mathieu-Daudé #include "qemu.h"
32fe0007f3SPhilippe Mathieu-Daudé #else
33fe0007f3SPhilippe Mathieu-Daudé #include "hw/core/sysemu-cpu-ops.h"
34fe0007f3SPhilippe Mathieu-Daudé #include "exec/address-spaces.h"
355f8d88bdSPhilippe Mathieu-Daudé #include "exec/memory.h"
36fe0007f3SPhilippe Mathieu-Daudé #endif
37fe0007f3SPhilippe Mathieu-Daudé #include "sysemu/cpus.h"
38fe0007f3SPhilippe Mathieu-Daudé #include "sysemu/tcg.h"
3942508261SPhilippe Mathieu-Daudé #include "exec/tswap.h"
40fe0007f3SPhilippe Mathieu-Daudé #include "exec/replay-core.h"
41fe0007f3SPhilippe Mathieu-Daudé #include "exec/cpu-common.h"
42fe0007f3SPhilippe Mathieu-Daudé #include "exec/exec-all.h"
43fe0007f3SPhilippe Mathieu-Daudé #include "exec/tb-flush.h"
44fe0007f3SPhilippe Mathieu-Daudé #include "exec/translate-all.h"
45fe0007f3SPhilippe Mathieu-Daudé #include "exec/log.h"
46fe0007f3SPhilippe Mathieu-Daudé #include "hw/core/accel-cpu.h"
47fe0007f3SPhilippe Mathieu-Daudé #include "trace/trace-root.h"
48fe0007f3SPhilippe Mathieu-Daudé #include "qemu/accel.h"
49fe0007f3SPhilippe Mathieu-Daudé 
50fe0007f3SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
cpu_common_post_load(void * opaque,int version_id)51fe0007f3SPhilippe Mathieu-Daudé static int cpu_common_post_load(void *opaque, int version_id)
52fe0007f3SPhilippe Mathieu-Daudé {
53fe0007f3SPhilippe Mathieu-Daudé     CPUState *cpu = opaque;
54fe0007f3SPhilippe Mathieu-Daudé 
55fe0007f3SPhilippe Mathieu-Daudé     /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
56fe0007f3SPhilippe Mathieu-Daudé        version_id is increased. */
57fe0007f3SPhilippe Mathieu-Daudé     cpu->interrupt_request &= ~0x01;
58fe0007f3SPhilippe Mathieu-Daudé     tlb_flush(cpu);
59fe0007f3SPhilippe Mathieu-Daudé 
60fe0007f3SPhilippe Mathieu-Daudé     /* loadvm has just updated the content of RAM, bypassing the
61fe0007f3SPhilippe Mathieu-Daudé      * usual mechanisms that ensure we flush TBs for writes to
62fe0007f3SPhilippe Mathieu-Daudé      * memory we've translated code from. So we must flush all TBs,
63fe0007f3SPhilippe Mathieu-Daudé      * which will now be stale.
64fe0007f3SPhilippe Mathieu-Daudé      */
65fe0007f3SPhilippe Mathieu-Daudé     tb_flush(cpu);
66fe0007f3SPhilippe Mathieu-Daudé 
67fe0007f3SPhilippe Mathieu-Daudé     return 0;
68fe0007f3SPhilippe Mathieu-Daudé }
69fe0007f3SPhilippe Mathieu-Daudé 
cpu_common_pre_load(void * opaque)70fe0007f3SPhilippe Mathieu-Daudé static int cpu_common_pre_load(void *opaque)
71fe0007f3SPhilippe Mathieu-Daudé {
72fe0007f3SPhilippe Mathieu-Daudé     CPUState *cpu = opaque;
73fe0007f3SPhilippe Mathieu-Daudé 
74fe0007f3SPhilippe Mathieu-Daudé     cpu->exception_index = -1;
75fe0007f3SPhilippe Mathieu-Daudé 
76fe0007f3SPhilippe Mathieu-Daudé     return 0;
77fe0007f3SPhilippe Mathieu-Daudé }
78fe0007f3SPhilippe Mathieu-Daudé 
cpu_common_exception_index_needed(void * opaque)79fe0007f3SPhilippe Mathieu-Daudé static bool cpu_common_exception_index_needed(void *opaque)
80fe0007f3SPhilippe Mathieu-Daudé {
81fe0007f3SPhilippe Mathieu-Daudé     CPUState *cpu = opaque;
82fe0007f3SPhilippe Mathieu-Daudé 
83fe0007f3SPhilippe Mathieu-Daudé     return tcg_enabled() && cpu->exception_index != -1;
84fe0007f3SPhilippe Mathieu-Daudé }
85fe0007f3SPhilippe Mathieu-Daudé 
86fe0007f3SPhilippe Mathieu-Daudé static const VMStateDescription vmstate_cpu_common_exception_index = {
87fe0007f3SPhilippe Mathieu-Daudé     .name = "cpu_common/exception_index",
88fe0007f3SPhilippe Mathieu-Daudé     .version_id = 1,
89fe0007f3SPhilippe Mathieu-Daudé     .minimum_version_id = 1,
90fe0007f3SPhilippe Mathieu-Daudé     .needed = cpu_common_exception_index_needed,
91ee1381ceSRichard Henderson     .fields = (const VMStateField[]) {
92fe0007f3SPhilippe Mathieu-Daudé         VMSTATE_INT32(exception_index, CPUState),
93fe0007f3SPhilippe Mathieu-Daudé         VMSTATE_END_OF_LIST()
94fe0007f3SPhilippe Mathieu-Daudé     }
95fe0007f3SPhilippe Mathieu-Daudé };
96fe0007f3SPhilippe Mathieu-Daudé 
cpu_common_crash_occurred_needed(void * opaque)97fe0007f3SPhilippe Mathieu-Daudé static bool cpu_common_crash_occurred_needed(void *opaque)
98fe0007f3SPhilippe Mathieu-Daudé {
99fe0007f3SPhilippe Mathieu-Daudé     CPUState *cpu = opaque;
100fe0007f3SPhilippe Mathieu-Daudé 
101fe0007f3SPhilippe Mathieu-Daudé     return cpu->crash_occurred;
102fe0007f3SPhilippe Mathieu-Daudé }
103fe0007f3SPhilippe Mathieu-Daudé 
104fe0007f3SPhilippe Mathieu-Daudé static const VMStateDescription vmstate_cpu_common_crash_occurred = {
105fe0007f3SPhilippe Mathieu-Daudé     .name = "cpu_common/crash_occurred",
106fe0007f3SPhilippe Mathieu-Daudé     .version_id = 1,
107fe0007f3SPhilippe Mathieu-Daudé     .minimum_version_id = 1,
108fe0007f3SPhilippe Mathieu-Daudé     .needed = cpu_common_crash_occurred_needed,
109ee1381ceSRichard Henderson     .fields = (const VMStateField[]) {
110fe0007f3SPhilippe Mathieu-Daudé         VMSTATE_BOOL(crash_occurred, CPUState),
111fe0007f3SPhilippe Mathieu-Daudé         VMSTATE_END_OF_LIST()
112fe0007f3SPhilippe Mathieu-Daudé     }
113fe0007f3SPhilippe Mathieu-Daudé };
114fe0007f3SPhilippe Mathieu-Daudé 
115fe0007f3SPhilippe Mathieu-Daudé const VMStateDescription vmstate_cpu_common = {
116fe0007f3SPhilippe Mathieu-Daudé     .name = "cpu_common",
117fe0007f3SPhilippe Mathieu-Daudé     .version_id = 1,
118fe0007f3SPhilippe Mathieu-Daudé     .minimum_version_id = 1,
119fe0007f3SPhilippe Mathieu-Daudé     .pre_load = cpu_common_pre_load,
120fe0007f3SPhilippe Mathieu-Daudé     .post_load = cpu_common_post_load,
121ee1381ceSRichard Henderson     .fields = (const VMStateField[]) {
122fe0007f3SPhilippe Mathieu-Daudé         VMSTATE_UINT32(halted, CPUState),
123fe0007f3SPhilippe Mathieu-Daudé         VMSTATE_UINT32(interrupt_request, CPUState),
124fe0007f3SPhilippe Mathieu-Daudé         VMSTATE_END_OF_LIST()
125fe0007f3SPhilippe Mathieu-Daudé     },
126ee1381ceSRichard Henderson     .subsections = (const VMStateDescription * const []) {
127fe0007f3SPhilippe Mathieu-Daudé         &vmstate_cpu_common_exception_index,
128fe0007f3SPhilippe Mathieu-Daudé         &vmstate_cpu_common_crash_occurred,
129fe0007f3SPhilippe Mathieu-Daudé         NULL
130fe0007f3SPhilippe Mathieu-Daudé     }
131fe0007f3SPhilippe Mathieu-Daudé };
132fe0007f3SPhilippe Mathieu-Daudé #endif
133fe0007f3SPhilippe Mathieu-Daudé 
cpu_exec_realizefn(CPUState * cpu,Error ** errp)13479a99091SPhilippe Mathieu-Daudé bool cpu_exec_realizefn(CPUState *cpu, Error **errp)
135fe0007f3SPhilippe Mathieu-Daudé {
136fe0007f3SPhilippe Mathieu-Daudé     /* cache the cpu class for the hotpath */
137fe0007f3SPhilippe Mathieu-Daudé     cpu->cc = CPU_GET_CLASS(cpu);
138fe0007f3SPhilippe Mathieu-Daudé 
139fe0007f3SPhilippe Mathieu-Daudé     if (!accel_cpu_common_realize(cpu, errp)) {
14079a99091SPhilippe Mathieu-Daudé         return false;
141fe0007f3SPhilippe Mathieu-Daudé     }
142fe0007f3SPhilippe Mathieu-Daudé 
143fe0007f3SPhilippe Mathieu-Daudé     /* Wait until cpu initialization complete before exposing cpu. */
144fe0007f3SPhilippe Mathieu-Daudé     cpu_list_add(cpu);
145fe0007f3SPhilippe Mathieu-Daudé 
146fe0007f3SPhilippe Mathieu-Daudé #ifdef CONFIG_USER_ONLY
147fe0007f3SPhilippe Mathieu-Daudé     assert(qdev_get_vmsd(DEVICE(cpu)) == NULL ||
148fe0007f3SPhilippe Mathieu-Daudé            qdev_get_vmsd(DEVICE(cpu))->unmigratable);
149fe0007f3SPhilippe Mathieu-Daudé #else
150fe0007f3SPhilippe Mathieu-Daudé     if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
151fe0007f3SPhilippe Mathieu-Daudé         vmstate_register(NULL, cpu->cpu_index, &vmstate_cpu_common, cpu);
152fe0007f3SPhilippe Mathieu-Daudé     }
153fe0007f3SPhilippe Mathieu-Daudé     if (cpu->cc->sysemu_ops->legacy_vmsd != NULL) {
154fe0007f3SPhilippe Mathieu-Daudé         vmstate_register(NULL, cpu->cpu_index, cpu->cc->sysemu_ops->legacy_vmsd, cpu);
155fe0007f3SPhilippe Mathieu-Daudé     }
156fe0007f3SPhilippe Mathieu-Daudé #endif /* CONFIG_USER_ONLY */
15779a99091SPhilippe Mathieu-Daudé 
15879a99091SPhilippe Mathieu-Daudé     return true;
159fe0007f3SPhilippe Mathieu-Daudé }
160fe0007f3SPhilippe Mathieu-Daudé 
cpu_exec_unrealizefn(CPUState * cpu)161fe0007f3SPhilippe Mathieu-Daudé void cpu_exec_unrealizefn(CPUState *cpu)
162fe0007f3SPhilippe Mathieu-Daudé {
163fe0007f3SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
164fe0007f3SPhilippe Mathieu-Daudé     CPUClass *cc = CPU_GET_CLASS(cpu);
165fe0007f3SPhilippe Mathieu-Daudé 
166fe0007f3SPhilippe Mathieu-Daudé     if (cc->sysemu_ops->legacy_vmsd != NULL) {
167fe0007f3SPhilippe Mathieu-Daudé         vmstate_unregister(NULL, cc->sysemu_ops->legacy_vmsd, cpu);
168fe0007f3SPhilippe Mathieu-Daudé     }
169fe0007f3SPhilippe Mathieu-Daudé     if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
170fe0007f3SPhilippe Mathieu-Daudé         vmstate_unregister(NULL, &vmstate_cpu_common, cpu);
171fe0007f3SPhilippe Mathieu-Daudé     }
172fe0007f3SPhilippe Mathieu-Daudé #endif
173fe0007f3SPhilippe Mathieu-Daudé 
174fe0007f3SPhilippe Mathieu-Daudé     cpu_list_remove(cpu);
175fe0007f3SPhilippe Mathieu-Daudé     /*
176fe0007f3SPhilippe Mathieu-Daudé      * Now that the vCPU has been removed from the RCU list, we can call
177fe0007f3SPhilippe Mathieu-Daudé      * accel_cpu_common_unrealize, which may free fields using call_rcu.
178fe0007f3SPhilippe Mathieu-Daudé      */
179fe0007f3SPhilippe Mathieu-Daudé     accel_cpu_common_unrealize(cpu);
180fe0007f3SPhilippe Mathieu-Daudé }
181fe0007f3SPhilippe Mathieu-Daudé 
182fe0007f3SPhilippe Mathieu-Daudé /*
183fe0007f3SPhilippe Mathieu-Daudé  * This can't go in hw/core/cpu.c because that file is compiled only
184fe0007f3SPhilippe Mathieu-Daudé  * once for both user-mode and system builds.
185fe0007f3SPhilippe Mathieu-Daudé  */
186fe0007f3SPhilippe Mathieu-Daudé static Property cpu_common_props[] = {
187fe0007f3SPhilippe Mathieu-Daudé #ifdef CONFIG_USER_ONLY
188fe0007f3SPhilippe Mathieu-Daudé     /*
189fe0007f3SPhilippe Mathieu-Daudé      * Create a property for the user-only object, so users can
190fe0007f3SPhilippe Mathieu-Daudé      * adjust prctl(PR_SET_UNALIGN) from the command-line.
191fe0007f3SPhilippe Mathieu-Daudé      * Has no effect if the target does not support the feature.
192fe0007f3SPhilippe Mathieu-Daudé      */
193fe0007f3SPhilippe Mathieu-Daudé     DEFINE_PROP_BOOL("prctl-unalign-sigbus", CPUState,
194fe0007f3SPhilippe Mathieu-Daudé                      prctl_unalign_sigbus, false),
195fe0007f3SPhilippe Mathieu-Daudé #else
196fe0007f3SPhilippe Mathieu-Daudé     /*
19754b99122SPhilippe Mathieu-Daudé      * Create a memory property for system CPU object, so users can
198fe0007f3SPhilippe Mathieu-Daudé      * wire up its memory.  The default if no link is set up is to use
199fe0007f3SPhilippe Mathieu-Daudé      * the system address space.
200fe0007f3SPhilippe Mathieu-Daudé      */
201fe0007f3SPhilippe Mathieu-Daudé     DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION,
202fe0007f3SPhilippe Mathieu-Daudé                      MemoryRegion *),
203fe0007f3SPhilippe Mathieu-Daudé #endif
204fe0007f3SPhilippe Mathieu-Daudé     DEFINE_PROP_END_OF_LIST(),
205fe0007f3SPhilippe Mathieu-Daudé };
206fe0007f3SPhilippe Mathieu-Daudé 
2070f9237f4SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
cpu_get_start_powered_off(Object * obj,Error ** errp)208fe0007f3SPhilippe Mathieu-Daudé static bool cpu_get_start_powered_off(Object *obj, Error **errp)
209fe0007f3SPhilippe Mathieu-Daudé {
210fe0007f3SPhilippe Mathieu-Daudé     CPUState *cpu = CPU(obj);
211fe0007f3SPhilippe Mathieu-Daudé     return cpu->start_powered_off;
212fe0007f3SPhilippe Mathieu-Daudé }
213fe0007f3SPhilippe Mathieu-Daudé 
cpu_set_start_powered_off(Object * obj,bool value,Error ** errp)214fe0007f3SPhilippe Mathieu-Daudé static void cpu_set_start_powered_off(Object *obj, bool value, Error **errp)
215fe0007f3SPhilippe Mathieu-Daudé {
216fe0007f3SPhilippe Mathieu-Daudé     CPUState *cpu = CPU(obj);
217fe0007f3SPhilippe Mathieu-Daudé     cpu->start_powered_off = value;
218fe0007f3SPhilippe Mathieu-Daudé }
2190f9237f4SPhilippe Mathieu-Daudé #endif
220fe0007f3SPhilippe Mathieu-Daudé 
cpu_class_init_props(DeviceClass * dc)221fe0007f3SPhilippe Mathieu-Daudé void cpu_class_init_props(DeviceClass *dc)
222fe0007f3SPhilippe Mathieu-Daudé {
2230f9237f4SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
224fe0007f3SPhilippe Mathieu-Daudé     ObjectClass *oc = OBJECT_CLASS(dc);
225fe0007f3SPhilippe Mathieu-Daudé 
226fe0007f3SPhilippe Mathieu-Daudé     /*
227fe0007f3SPhilippe Mathieu-Daudé      * We can't use DEFINE_PROP_BOOL in the Property array for this
228fe0007f3SPhilippe Mathieu-Daudé      * property, because we want this to be settable after realize.
229fe0007f3SPhilippe Mathieu-Daudé      */
230fe0007f3SPhilippe Mathieu-Daudé     object_class_property_add_bool(oc, "start-powered-off",
231fe0007f3SPhilippe Mathieu-Daudé                                    cpu_get_start_powered_off,
232fe0007f3SPhilippe Mathieu-Daudé                                    cpu_set_start_powered_off);
2330f9237f4SPhilippe Mathieu-Daudé #endif
2340f9237f4SPhilippe Mathieu-Daudé 
2350f9237f4SPhilippe Mathieu-Daudé     device_class_set_props(dc, cpu_common_props);
236fe0007f3SPhilippe Mathieu-Daudé }
237fe0007f3SPhilippe Mathieu-Daudé 
cpu_exec_initfn(CPUState * cpu)238fe0007f3SPhilippe Mathieu-Daudé void cpu_exec_initfn(CPUState *cpu)
239fe0007f3SPhilippe Mathieu-Daudé {
240fe0007f3SPhilippe Mathieu-Daudé     cpu->as = NULL;
241fe0007f3SPhilippe Mathieu-Daudé     cpu->num_ases = 0;
242fe0007f3SPhilippe Mathieu-Daudé 
243fe0007f3SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
244fe0007f3SPhilippe Mathieu-Daudé     cpu->memory = get_system_memory();
245fe0007f3SPhilippe Mathieu-Daudé     object_ref(OBJECT(cpu->memory));
246fe0007f3SPhilippe Mathieu-Daudé #endif
247fe0007f3SPhilippe Mathieu-Daudé }
248fe0007f3SPhilippe Mathieu-Daudé 
cpu_model_from_type(const char * typename)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 
parse_cpu_option(const char * cpu_option)264fe0007f3SPhilippe Mathieu-Daudé const char *parse_cpu_option(const char *cpu_option)
265fe0007f3SPhilippe Mathieu-Daudé {
266fe0007f3SPhilippe Mathieu-Daudé     ObjectClass *oc;
267fe0007f3SPhilippe Mathieu-Daudé     CPUClass *cc;
268fe0007f3SPhilippe Mathieu-Daudé     gchar **model_pieces;
269fe0007f3SPhilippe Mathieu-Daudé     const char *cpu_type;
270fe0007f3SPhilippe Mathieu-Daudé 
271fe0007f3SPhilippe Mathieu-Daudé     model_pieces = g_strsplit(cpu_option, ",", 2);
272fe0007f3SPhilippe Mathieu-Daudé     if (!model_pieces[0]) {
273fe0007f3SPhilippe Mathieu-Daudé         error_report("-cpu option cannot be empty");
274fe0007f3SPhilippe Mathieu-Daudé         exit(1);
275fe0007f3SPhilippe Mathieu-Daudé     }
276fe0007f3SPhilippe Mathieu-Daudé 
277fe0007f3SPhilippe Mathieu-Daudé     oc = cpu_class_by_name(CPU_RESOLVING_TYPE, model_pieces[0]);
278fe0007f3SPhilippe Mathieu-Daudé     if (oc == NULL) {
279fe0007f3SPhilippe Mathieu-Daudé         error_report("unable to find CPU model '%s'", model_pieces[0]);
280fe0007f3SPhilippe Mathieu-Daudé         g_strfreev(model_pieces);
281fe0007f3SPhilippe Mathieu-Daudé         exit(EXIT_FAILURE);
282fe0007f3SPhilippe Mathieu-Daudé     }
283fe0007f3SPhilippe Mathieu-Daudé 
284fe0007f3SPhilippe Mathieu-Daudé     cpu_type = object_class_get_name(oc);
285fe0007f3SPhilippe Mathieu-Daudé     cc = CPU_CLASS(oc);
286fe0007f3SPhilippe Mathieu-Daudé     cc->parse_features(cpu_type, model_pieces[1], &error_fatal);
287fe0007f3SPhilippe Mathieu-Daudé     g_strfreev(model_pieces);
288fe0007f3SPhilippe Mathieu-Daudé     return cpu_type;
289fe0007f3SPhilippe Mathieu-Daudé }
290fe0007f3SPhilippe Mathieu-Daudé 
291dfa47531SGavin Shan #ifndef cpu_list
cpu_list_entry(gpointer data,gpointer user_data)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 
cpu_list(void)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 
list_cpus(void)316fe0007f3SPhilippe Mathieu-Daudé void list_cpus(void)
317fe0007f3SPhilippe Mathieu-Daudé {
318fe0007f3SPhilippe Mathieu-Daudé     cpu_list();
319fe0007f3SPhilippe Mathieu-Daudé }
320fe0007f3SPhilippe Mathieu-Daudé 
321fe0007f3SPhilippe Mathieu-Daudé /* enable or disable single step mode. EXCP_DEBUG is returned by the
322fe0007f3SPhilippe Mathieu-Daudé    CPU loop after each instruction */
cpu_single_step(CPUState * cpu,int enabled)323fe0007f3SPhilippe Mathieu-Daudé void cpu_single_step(CPUState *cpu, int enabled)
324fe0007f3SPhilippe Mathieu-Daudé {
325fe0007f3SPhilippe Mathieu-Daudé     if (cpu->singlestep_enabled != enabled) {
326fe0007f3SPhilippe Mathieu-Daudé         cpu->singlestep_enabled = enabled;
327fe0007f3SPhilippe Mathieu-Daudé 
328fe0007f3SPhilippe Mathieu-Daudé #if !defined(CONFIG_USER_ONLY)
329fe0007f3SPhilippe Mathieu-Daudé         const AccelOpsClass *ops = cpus_get_accel();
330fe0007f3SPhilippe Mathieu-Daudé         if (ops->update_guest_debug) {
331fe0007f3SPhilippe Mathieu-Daudé             ops->update_guest_debug(cpu);
332fe0007f3SPhilippe Mathieu-Daudé         }
333fe0007f3SPhilippe Mathieu-Daudé #endif
334fe0007f3SPhilippe Mathieu-Daudé 
335fe0007f3SPhilippe Mathieu-Daudé         trace_breakpoint_singlestep(cpu->cpu_index, enabled);
336fe0007f3SPhilippe Mathieu-Daudé     }
337fe0007f3SPhilippe Mathieu-Daudé }
338fe0007f3SPhilippe Mathieu-Daudé 
cpu_abort(CPUState * cpu,const char * fmt,...)339fe0007f3SPhilippe Mathieu-Daudé void cpu_abort(CPUState *cpu, const char *fmt, ...)
340fe0007f3SPhilippe Mathieu-Daudé {
341fe0007f3SPhilippe Mathieu-Daudé     va_list ap;
342fe0007f3SPhilippe Mathieu-Daudé     va_list ap2;
343fe0007f3SPhilippe Mathieu-Daudé 
344fe0007f3SPhilippe Mathieu-Daudé     va_start(ap, fmt);
345fe0007f3SPhilippe Mathieu-Daudé     va_copy(ap2, ap);
346fe0007f3SPhilippe Mathieu-Daudé     fprintf(stderr, "qemu: fatal: ");
347fe0007f3SPhilippe Mathieu-Daudé     vfprintf(stderr, fmt, ap);
348fe0007f3SPhilippe Mathieu-Daudé     fprintf(stderr, "\n");
349fe0007f3SPhilippe Mathieu-Daudé     cpu_dump_state(cpu, stderr, CPU_DUMP_FPU | CPU_DUMP_CCOP);
350fe0007f3SPhilippe Mathieu-Daudé     if (qemu_log_separate()) {
351fe0007f3SPhilippe Mathieu-Daudé         FILE *logfile = qemu_log_trylock();
352fe0007f3SPhilippe Mathieu-Daudé         if (logfile) {
353fe0007f3SPhilippe Mathieu-Daudé             fprintf(logfile, "qemu: fatal: ");
354fe0007f3SPhilippe Mathieu-Daudé             vfprintf(logfile, fmt, ap2);
355fe0007f3SPhilippe Mathieu-Daudé             fprintf(logfile, "\n");
356fe0007f3SPhilippe Mathieu-Daudé             cpu_dump_state(cpu, logfile, CPU_DUMP_FPU | CPU_DUMP_CCOP);
357fe0007f3SPhilippe Mathieu-Daudé             qemu_log_unlock(logfile);
358fe0007f3SPhilippe Mathieu-Daudé         }
359fe0007f3SPhilippe Mathieu-Daudé     }
360fe0007f3SPhilippe Mathieu-Daudé     va_end(ap2);
361fe0007f3SPhilippe Mathieu-Daudé     va_end(ap);
362fe0007f3SPhilippe Mathieu-Daudé     replay_finish();
363fe0007f3SPhilippe Mathieu-Daudé #if defined(CONFIG_USER_ONLY)
364fe0007f3SPhilippe Mathieu-Daudé     {
365fe0007f3SPhilippe Mathieu-Daudé         struct sigaction act;
366fe0007f3SPhilippe Mathieu-Daudé         sigfillset(&act.sa_mask);
367fe0007f3SPhilippe Mathieu-Daudé         act.sa_handler = SIG_DFL;
368fe0007f3SPhilippe Mathieu-Daudé         act.sa_flags = 0;
369fe0007f3SPhilippe Mathieu-Daudé         sigaction(SIGABRT, &act, NULL);
370fe0007f3SPhilippe Mathieu-Daudé     }
371fe0007f3SPhilippe Mathieu-Daudé #endif
372fe0007f3SPhilippe Mathieu-Daudé     abort();
373fe0007f3SPhilippe Mathieu-Daudé }
374fe0007f3SPhilippe Mathieu-Daudé 
375fe0007f3SPhilippe Mathieu-Daudé /* physical memory access (slow version, mainly for debug) */
376fe0007f3SPhilippe Mathieu-Daudé #if defined(CONFIG_USER_ONLY)
cpu_memory_rw_debug(CPUState * cpu,vaddr addr,void * ptr,size_t len,bool is_write)377fe0007f3SPhilippe Mathieu-Daudé int cpu_memory_rw_debug(CPUState *cpu, vaddr addr,
378fe0007f3SPhilippe Mathieu-Daudé                         void *ptr, size_t len, bool is_write)
379fe0007f3SPhilippe Mathieu-Daudé {
380fe0007f3SPhilippe Mathieu-Daudé     int flags;
381fe0007f3SPhilippe Mathieu-Daudé     vaddr l, page;
382fe0007f3SPhilippe Mathieu-Daudé     void * p;
383fe0007f3SPhilippe Mathieu-Daudé     uint8_t *buf = ptr;
38487ab2704SIlya Leoshkevich     ssize_t written;
38587ab2704SIlya Leoshkevich     int ret = -1;
38687ab2704SIlya Leoshkevich     int fd = -1;
387fe0007f3SPhilippe Mathieu-Daudé 
388fe0007f3SPhilippe Mathieu-Daudé     while (len > 0) {
389fe0007f3SPhilippe Mathieu-Daudé         page = addr & TARGET_PAGE_MASK;
390fe0007f3SPhilippe Mathieu-Daudé         l = (page + TARGET_PAGE_SIZE) - addr;
391fe0007f3SPhilippe Mathieu-Daudé         if (l > len)
392fe0007f3SPhilippe Mathieu-Daudé             l = len;
393fe0007f3SPhilippe Mathieu-Daudé         flags = page_get_flags(page);
39487ab2704SIlya Leoshkevich         if (!(flags & PAGE_VALID)) {
39587ab2704SIlya Leoshkevich             goto out_close;
39687ab2704SIlya Leoshkevich         }
397fe0007f3SPhilippe Mathieu-Daudé         if (is_write) {
39887ab2704SIlya Leoshkevich             if (flags & PAGE_WRITE) {
399fe0007f3SPhilippe Mathieu-Daudé                 /* 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                 }
404fe0007f3SPhilippe Mathieu-Daudé                 memcpy(p, buf, l);
405fe0007f3SPhilippe Mathieu-Daudé                 unlock_user(p, addr, l);
406fe0007f3SPhilippe Mathieu-Daudé             } 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) {
432fe0007f3SPhilippe Mathieu-Daudé             /* 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             }
437fe0007f3SPhilippe Mathieu-Daudé             memcpy(buf, p, l);
438fe0007f3SPhilippe Mathieu-Daudé             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             }
451fe0007f3SPhilippe Mathieu-Daudé         }
452fe0007f3SPhilippe Mathieu-Daudé         len -= l;
453fe0007f3SPhilippe Mathieu-Daudé         buf += l;
454fe0007f3SPhilippe Mathieu-Daudé         addr += l;
455fe0007f3SPhilippe Mathieu-Daudé     }
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;
463fe0007f3SPhilippe Mathieu-Daudé }
464fe0007f3SPhilippe Mathieu-Daudé #endif
465fe0007f3SPhilippe Mathieu-Daudé 
target_words_bigendian(void)466fe0007f3SPhilippe Mathieu-Daudé bool target_words_bigendian(void)
467fe0007f3SPhilippe Mathieu-Daudé {
468fe0007f3SPhilippe Mathieu-Daudé     return TARGET_BIG_ENDIAN;
469fe0007f3SPhilippe Mathieu-Daudé }
470fe0007f3SPhilippe Mathieu-Daudé 
target_name(void)471fe0007f3SPhilippe Mathieu-Daudé const char *target_name(void)
472fe0007f3SPhilippe Mathieu-Daudé {
473fe0007f3SPhilippe Mathieu-Daudé     return TARGET_NAME;
474fe0007f3SPhilippe Mathieu-Daudé }
475