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