master
c 324 lines 8.92 KB
Raw
1 /*
2 * QEMU CPU model (system specific)
3 *
4 * Copyright (c) 2012-2014 SUSE LINUX Products GmbH
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see
18 * <http://www.gnu.org/licenses/gpl-2.0.html>
19 */
20
21 #include "qemu/osdep.h"
22 #include "qapi/error.h"
23 #include "system/address-spaces.h"
24 #include "exec/cputlb.h"
25 #include "exec/target_page.h"
26 #include "system/memory.h"
27 #include "qemu/target-info.h"
28 #include "hw/core/boards.h"
29 #include "hw/core/qdev.h"
30 #include "hw/core/qdev-properties.h"
31 #include "hw/core/sysemu-cpu-ops.h"
32 #include "migration/vmstate.h"
33 #include "system/hw_accel.h"
34 #include "system/tcg.h"
35 #include "cpu-internal.h"
36
37 bool cpu_has_work(CPUState *cpu)
38 {
39 return cpu->cc->sysemu_ops->has_work(cpu);
40 }
41
42 bool cpu_paging_enabled(const CPUState *cpu)
43 {
44 if (cpu->cc->sysemu_ops->get_paging_enabled) {
45 return cpu->cc->sysemu_ops->get_paging_enabled(cpu);
46 }
47
48 return false;
49 }
50
51 bool cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
52 Error **errp)
53 {
54 if (cpu->cc->sysemu_ops->get_memory_mapping) {
55 return cpu->cc->sysemu_ops->get_memory_mapping(cpu, list, errp);
56 }
57
58 error_setg(errp, "Obtaining memory mappings is unsupported on this CPU.");
59 return false;
60 }
61
62 bool cpu_translate_for_debug(CPUState *cpu, vaddr addr,
63 TranslateForDebugResult *result)
64 {
65 if (cpu->cc->sysemu_ops->translate_for_debug) {
66 return cpu->cc->sysemu_ops->translate_for_debug(cpu, addr, result);
67 } else {
68 /* Fallbacks for CPUs which don't implement translate_for_debug */
69 result->physaddr = cpu->cc->sysemu_ops->get_phys_addr_debug(cpu, addr);
70 result->attrs = MEMTXATTRS_UNSPECIFIED;
71 if (result->physaddr == -1) {
72 return false;
73 }
74 /* Indicate that this is a debug access. */
75 result->attrs.debug = 1;
76 /*
77 * Assume memory access permissions are valid for the whole page.
78 * Targets where this isn't true should implement the
79 * translate_for_debug method.
80 */
81 result->lg_page_size = TARGET_PAGE_BITS;
82 return true;
83 }
84 }
85
86 int cpu_asidx_from_attrs(CPUState *cpu, MemTxAttrs attrs)
87 {
88 int ret = 0;
89
90 if (cpu->cc->sysemu_ops->asidx_from_attrs) {
91 ret = cpu->cc->sysemu_ops->asidx_from_attrs(cpu, attrs);
92 assert(ret <= cpu->cc->max_as && ret >= 0);
93 }
94 return ret;
95 }
96
97 int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
98 void *opaque)
99 {
100 if (!cpu->cc->sysemu_ops->write_elf32_qemunote) {
101 return 0;
102 }
103 return (*cpu->cc->sysemu_ops->write_elf32_qemunote)(f, cpu, opaque);
104 }
105
106 int cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu,
107 int cpuid, void *opaque)
108 {
109 if (!cpu->cc->sysemu_ops->write_elf32_note) {
110 return -1;
111 }
112 return (*cpu->cc->sysemu_ops->write_elf32_note)(f, cpu, cpuid, opaque);
113 }
114
115 int cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
116 void *opaque)
117 {
118 if (!cpu->cc->sysemu_ops->write_elf64_qemunote) {
119 return 0;
120 }
121 return (*cpu->cc->sysemu_ops->write_elf64_qemunote)(f, cpu, opaque);
122 }
123
124 int cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
125 int cpuid, void *opaque)
126 {
127 if (!cpu->cc->sysemu_ops->write_elf64_note) {
128 return -1;
129 }
130 return (*cpu->cc->sysemu_ops->write_elf64_note)(f, cpu, cpuid, opaque);
131 }
132
133 bool cpu_internal_is_big_endian(CPUState *cpu)
134 {
135 if (cpu->cc->sysemu_ops->internal_is_big_endian) {
136 return cpu->cc->sysemu_ops->internal_is_big_endian(cpu);
137 }
138 return target_big_endian();
139 }
140
141 GuestPanicInformation *cpu_get_crash_info(CPUState *cpu)
142 {
143 GuestPanicInformation *res = NULL;
144
145 if (cpu->cc->sysemu_ops->get_crash_info) {
146 res = cpu->cc->sysemu_ops->get_crash_info(cpu);
147 }
148 return res;
149 }
150
151 static const Property cpu_system_props[] = {
152 /*
153 * Create a memory property for system CPU object, so users can
154 * wire up its memory. The default if no link is set up is to use
155 * the system address space.
156 */
157 DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION,
158 MemoryRegion *),
159 };
160
161 static bool cpu_get_start_powered_off(Object *obj, Error **errp)
162 {
163 CPUState *cpu = CPU(obj);
164 return cpu->start_powered_off;
165 }
166
167 static void cpu_set_start_powered_off(Object *obj, bool value, Error **errp)
168 {
169 CPUState *cpu = CPU(obj);
170 cpu->start_powered_off = value;
171 }
172
173 void cpu_class_init_props(DeviceClass *dc)
174 {
175 ObjectClass *oc = OBJECT_CLASS(dc);
176
177 /*
178 * We can't use DEFINE_PROP_BOOL in the Property array for this
179 * property, because we want this to be settable after realize.
180 */
181 object_class_property_add_bool(oc, "start-powered-off",
182 cpu_get_start_powered_off,
183 cpu_set_start_powered_off);
184
185 device_class_set_props(dc, cpu_system_props);
186 }
187
188 void cpu_exec_class_post_init(CPUClass *cc)
189 {
190 /* Check mandatory SysemuCPUOps handlers */
191 g_assert(cc->sysemu_ops->has_work);
192 }
193
194 void cpu_exec_init(CPUState *cpu)
195 {
196 cpu->memory = get_system_memory();
197 object_ref(OBJECT(cpu->memory));
198 }
199
200 static int cpu_common_post_load(void *opaque, int version_id)
201 {
202 if (tcg_enabled()) {
203 CPUState *cpu = opaque;
204
205 /*
206 * 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
207 * version_id is increased.
208 */
209 cpu_reset_interrupt(cpu, 0x01);
210
211 tlb_flush(cpu);
212 }
213
214 return 0;
215 }
216
217 static int cpu_common_pre_load(void *opaque)
218 {
219 CPUState *cpu = opaque;
220
221 cpu->exception_index = -1;
222
223 return 0;
224 }
225
226 void cpu_exec_realize(CPUState *cpu, Error **errp)
227 {
228 Object *machine = qdev_get_machine();
229
230 /*
231 * qdev_get_machine() can return something that's not TYPE_MACHINE
232 * if this is one of the user-only emulators; in that case there's
233 * no need to check the ignore_memory_transaction_failures board flag.
234 */
235 if (object_dynamic_cast(machine, TYPE_MACHINE)) {
236 MachineClass *mc = MACHINE_GET_CLASS(machine);
237
238 if (mc) {
239 cpu->ignore_memory_transaction_failures =
240 mc->ignore_memory_transaction_failures;
241 }
242 }
243
244 if (DEVICE(cpu)->hotplugged) {
245 cpu_synchronize_post_init(cpu);
246 cpu_resume(cpu);
247 }
248
249 }
250
251 static bool cpu_common_exception_index_needed(void *opaque)
252 {
253 CPUState *cpu = opaque;
254
255 return tcg_enabled() && cpu->exception_index != -1;
256 }
257
258 static const VMStateDescription vmstate_cpu_common_exception_index = {
259 .name = "cpu_common/exception_index",
260 .version_id = 1,
261 .minimum_version_id = 1,
262 .needed = cpu_common_exception_index_needed,
263 .fields = (const VMStateField[]) {
264 VMSTATE_INT32(exception_index, CPUState),
265 VMSTATE_END_OF_LIST()
266 }
267 };
268
269 static bool cpu_common_crash_occurred_needed(void *opaque)
270 {
271 CPUState *cpu = opaque;
272
273 return cpu->crash_occurred;
274 }
275
276 static const VMStateDescription vmstate_cpu_common_crash_occurred = {
277 .name = "cpu_common/crash_occurred",
278 .version_id = 1,
279 .minimum_version_id = 1,
280 .needed = cpu_common_crash_occurred_needed,
281 .fields = (const VMStateField[]) {
282 VMSTATE_BOOL(crash_occurred, CPUState),
283 VMSTATE_END_OF_LIST()
284 }
285 };
286
287 const VMStateDescription vmstate_cpu_common = {
288 .name = "cpu_common",
289 .version_id = 1,
290 .minimum_version_id = 1,
291 .pre_load = cpu_common_pre_load,
292 .post_load = cpu_common_post_load,
293 .fields = (const VMStateField[]) {
294 VMSTATE_UINT32(halted, CPUState),
295 VMSTATE_UINT32(interrupt_request, CPUState),
296 VMSTATE_END_OF_LIST()
297 },
298 .subsections = (const VMStateDescription * const []) {
299 &vmstate_cpu_common_exception_index,
300 &vmstate_cpu_common_crash_occurred,
301 NULL
302 }
303 };
304
305 void cpu_vmstate_register(CPUState *cpu)
306 {
307 if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
308 vmstate_register(NULL, cpu->cpu_index, &vmstate_cpu_common, cpu);
309 }
310 if (cpu->cc->sysemu_ops->legacy_vmsd != NULL) {
311 vmstate_register(NULL, cpu->cpu_index,
312 cpu->cc->sysemu_ops->legacy_vmsd, cpu);
313 }
314 }
315
316 void cpu_vmstate_unregister(CPUState *cpu)
317 {
318 if (cpu->cc->sysemu_ops->legacy_vmsd != NULL) {
319 vmstate_unregister(NULL, cpu->cc->sysemu_ops->legacy_vmsd, cpu);
320 }
321 if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
322 vmstate_unregister(NULL, &vmstate_cpu_common, cpu);
323 }
324 }