On 10/6/20 11:19 AM, Paolo Bonzini wrote: > Over the years, most parts of exec.c that were not specific to softmmu > have been moved to accel/tcg; what's left is mostly the low-level part > of the memory API, which includes RAMBlock and AddressSpaceDispatch. > However exec.c also hosts 4-500 lines of code for the target specific > parts of the CPU QOM object, plus a few functions for user-mode > emulation that do not have a better place (they are not TCG-specific so > accel/tcg/user-exec.c is not a good place either). > > Move these parts to a new file, so that exec.c can be moved to > softmmu/physmem.c. > > Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
Hi Paolo, the comment does not talk about cpu.c, which is now created in the top source directory. What is the role of this new module? Also, could we find a more descriptive file name than cpu.c? Do you plan further renaming of this new module functions? Or its this basically a "leftovers" file for which we did not find a proper role yet? Ciao, CLaudio > --- > MAINTAINERS | 4 +- > cpu.c | 452 +++++++++++++++++++++++++++++++++++ > include/exec/cpu-common.h | 3 + > meson.build | 2 +- > softmmu/meson.build | 3 +- > exec.c => softmmu/physmem.c | 454 +----------------------------------- > 6 files changed, 467 insertions(+), 451 deletions(-) > create mode 100644 cpus.c > rename exec.c => softmmu/physmem.c (91%) > > diff --git a/MAINTAINERS b/MAINTAINERS > index e9d85cc873..ddd1490767 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -117,7 +117,6 @@ R: Paolo Bonzini <pbonz...@redhat.com> > S: Maintained > F: softmmu/cpus.c > F: cpus-common.c > -F: exec.c > F: accel/tcg/ > F: accel/stubs/tcg-stub.c > F: scripts/decodetree.py > @@ -1525,6 +1524,7 @@ Machine core > M: Eduardo Habkost <ehabk...@redhat.com> > M: Marcel Apfelbaum <marcel.apfelb...@gmail.com> > S: Supported > +F: cpu.c > F: hw/core/cpu.c > F: hw/core/machine-qmp-cmds.c > F: hw/core/machine.c > @@ -2283,8 +2283,8 @@ F: include/exec/ram_addr.h > F: include/exec/ramblock.h > F: softmmu/ioport.c > F: softmmu/memory.c > +F: softmmu/physmem.c > F: include/exec/memory-internal.h > -F: exec.c > F: scripts/coccinelle/memory-region-housekeeping.cocci > > SPICE > diff --git a/cpu.c b/cpu.c > new file mode 100644 > index 0000000000..0be5dcb6f3 > --- /dev/null > +++ b/cpu.c > @@ -0,0 +1,452 @@ > +/* > + * Target-specific parts of the CPU object > + * > + * Copyright (c) 2003 Fabrice Bellard > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, see > <http://www.gnu.org/licenses/>. > + */ > + > +#include "qemu/osdep.h" > +#include "qemu-common.h" > +#include "qapi/error.h" > + > +#include "exec/target_page.h" > +#include "hw/qdev-core.h" > +#include "hw/qdev-properties.h" > +#include "qemu/error-report.h" > +#include "migration/vmstate.h" > +#ifdef CONFIG_USER_ONLY > +#include "qemu.h" > +#else > +#include "exec/address-spaces.h" > +#endif > +#include "sysemu/tcg.h" > +#include "sysemu/kvm.h" > +#include "sysemu/replay.h" > +#include "translate-all.h" > +#include "exec/log.h" > + > +uintptr_t qemu_host_page_size; > +intptr_t qemu_host_page_mask; > + > +#ifndef CONFIG_USER_ONLY > +static int cpu_common_post_load(void *opaque, int version_id) > +{ > + CPUState *cpu = opaque; > + > + /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the > + version_id is increased. */ > + cpu->interrupt_request &= ~0x01; > + tlb_flush(cpu); > + > + /* loadvm has just updated the content of RAM, bypassing the > + * usual mechanisms that ensure we flush TBs for writes to > + * memory we've translated code from. So we must flush all TBs, > + * which will now be stale. > + */ > + tb_flush(cpu); > + > + return 0; > +} > + > +static int cpu_common_pre_load(void *opaque) > +{ > + CPUState *cpu = opaque; > + > + cpu->exception_index = -1; > + > + return 0; > +} > + > +static bool cpu_common_exception_index_needed(void *opaque) > +{ > + CPUState *cpu = opaque; > + > + return tcg_enabled() && cpu->exception_index != -1; > +} > + > +static const VMStateDescription vmstate_cpu_common_exception_index = { > + .name = "cpu_common/exception_index", > + .version_id = 1, > + .minimum_version_id = 1, > + .needed = cpu_common_exception_index_needed, > + .fields = (VMStateField[]) { > + VMSTATE_INT32(exception_index, CPUState), > + VMSTATE_END_OF_LIST() > + } > +}; > + > +static bool cpu_common_crash_occurred_needed(void *opaque) > +{ > + CPUState *cpu = opaque; > + > + return cpu->crash_occurred; > +} > + > +static const VMStateDescription vmstate_cpu_common_crash_occurred = { > + .name = "cpu_common/crash_occurred", > + .version_id = 1, > + .minimum_version_id = 1, > + .needed = cpu_common_crash_occurred_needed, > + .fields = (VMStateField[]) { > + VMSTATE_BOOL(crash_occurred, CPUState), > + VMSTATE_END_OF_LIST() > + } > +}; > + > +const VMStateDescription vmstate_cpu_common = { > + .name = "cpu_common", > + .version_id = 1, > + .minimum_version_id = 1, > + .pre_load = cpu_common_pre_load, > + .post_load = cpu_common_post_load, > + .fields = (VMStateField[]) { > + VMSTATE_UINT32(halted, CPUState), > + VMSTATE_UINT32(interrupt_request, CPUState), > + VMSTATE_END_OF_LIST() > + }, > + .subsections = (const VMStateDescription*[]) { > + &vmstate_cpu_common_exception_index, > + &vmstate_cpu_common_crash_occurred, > + NULL > + } > +}; > +#endif > + > +void cpu_exec_unrealizefn(CPUState *cpu) > +{ > + CPUClass *cc = CPU_GET_CLASS(cpu); > + > + tlb_destroy(cpu); > + cpu_list_remove(cpu); > + > +#ifdef CONFIG_USER_ONLY > + assert(cc->vmsd == NULL); > +#else > + if (cc->vmsd != NULL) { > + vmstate_unregister(NULL, cc->vmsd, cpu); > + } > + if (qdev_get_vmsd(DEVICE(cpu)) == NULL) { > + vmstate_unregister(NULL, &vmstate_cpu_common, cpu); > + } > + tcg_iommu_free_notifier_list(cpu); > +#endif > +} > + > +Property cpu_common_props[] = { > +#ifndef CONFIG_USER_ONLY > + /* Create a memory property for softmmu CPU object, > + * so users can wire up its memory. (This can't go in hw/core/cpu.c > + * because that file is compiled only once for both user-mode > + * and system builds.) The default if no link is set up is to use > + * the system address space. > + */ > + DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION, > + MemoryRegion *), > +#endif > + DEFINE_PROP_BOOL("start-powered-off", CPUState, start_powered_off, > false), > + DEFINE_PROP_END_OF_LIST(), > +}; > + > +void cpu_exec_initfn(CPUState *cpu) > +{ > + cpu->as = NULL; > + cpu->num_ases = 0; > + > +#ifndef CONFIG_USER_ONLY > + cpu->thread_id = qemu_get_thread_id(); > + cpu->memory = get_system_memory(); > + object_ref(OBJECT(cpu->memory)); > +#endif > +} > + > +void cpu_exec_realizefn(CPUState *cpu, Error **errp) > +{ > + CPUClass *cc = CPU_GET_CLASS(cpu); > + static bool tcg_target_initialized; > + > + cpu_list_add(cpu); > + > + if (tcg_enabled() && !tcg_target_initialized) { > + tcg_target_initialized = true; > + cc->tcg_initialize(); > + } > + tlb_init(cpu); > + > + qemu_plugin_vcpu_init_hook(cpu); > + > +#ifdef CONFIG_USER_ONLY > + assert(cc->vmsd == NULL); > +#else /* !CONFIG_USER_ONLY */ > + if (qdev_get_vmsd(DEVICE(cpu)) == NULL) { > + vmstate_register(NULL, cpu->cpu_index, &vmstate_cpu_common, cpu); > + } > + if (cc->vmsd != NULL) { > + vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu); > + } > + > + tcg_iommu_init_notifier_list(cpu); > +#endif > +} > + > +const char *parse_cpu_option(const char *cpu_option) > +{ > + ObjectClass *oc; > + CPUClass *cc; > + gchar **model_pieces; > + const char *cpu_type; > + > + model_pieces = g_strsplit(cpu_option, ",", 2); > + if (!model_pieces[0]) { > + error_report("-cpu option cannot be empty"); > + exit(1); > + } > + > + oc = cpu_class_by_name(CPU_RESOLVING_TYPE, model_pieces[0]); > + if (oc == NULL) { > + error_report("unable to find CPU model '%s'", model_pieces[0]); > + g_strfreev(model_pieces); > + exit(EXIT_FAILURE); > + } > + > + cpu_type = object_class_get_name(oc); > + cc = CPU_CLASS(oc); > + cc->parse_features(cpu_type, model_pieces[1], &error_fatal); > + g_strfreev(model_pieces); > + return cpu_type; > +} > + > +#if defined(CONFIG_USER_ONLY) > +void tb_invalidate_phys_addr(target_ulong addr) > +{ > + mmap_lock(); > + tb_invalidate_phys_page_range(addr, addr + 1); > + mmap_unlock(); > +} > + > +static void breakpoint_invalidate(CPUState *cpu, target_ulong pc) > +{ > + tb_invalidate_phys_addr(pc); > +} > +#else > +void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs) > +{ > + ram_addr_t ram_addr; > + MemoryRegion *mr; > + hwaddr l = 1; > + > + if (!tcg_enabled()) { > + return; > + } > + > + RCU_READ_LOCK_GUARD(); > + mr = address_space_translate(as, addr, &addr, &l, false, attrs); > + if (!(memory_region_is_ram(mr) > + || memory_region_is_romd(mr))) { > + return; > + } > + ram_addr = memory_region_get_ram_addr(mr) + addr; > + tb_invalidate_phys_page_range(ram_addr, ram_addr + 1); > +} > + > +static void breakpoint_invalidate(CPUState *cpu, target_ulong pc) > +{ > + /* > + * There may not be a virtual to physical translation for the pc > + * right now, but there may exist cached TB for this pc. > + * Flush the whole TB cache to force re-translation of such TBs. > + * This is heavyweight, but we're debugging anyway. > + */ > + tb_flush(cpu); > +} > +#endif > + > +/* Add a breakpoint. */ > +int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags, > + CPUBreakpoint **breakpoint) > +{ > + CPUBreakpoint *bp; > + > + bp = g_malloc(sizeof(*bp)); > + > + bp->pc = pc; > + bp->flags = flags; > + > + /* keep all GDB-injected breakpoints in front */ > + if (flags & BP_GDB) { > + QTAILQ_INSERT_HEAD(&cpu->breakpoints, bp, entry); > + } else { > + QTAILQ_INSERT_TAIL(&cpu->breakpoints, bp, entry); > + } > + > + breakpoint_invalidate(cpu, pc); > + > + if (breakpoint) { > + *breakpoint = bp; > + } > + return 0; > +} > + > +/* Remove a specific breakpoint. */ > +int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags) > +{ > + CPUBreakpoint *bp; > + > + QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { > + if (bp->pc == pc && bp->flags == flags) { > + cpu_breakpoint_remove_by_ref(cpu, bp); > + return 0; > + } > + } > + return -ENOENT; > +} > + > +/* Remove a specific breakpoint by reference. */ > +void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *breakpoint) > +{ > + QTAILQ_REMOVE(&cpu->breakpoints, breakpoint, entry); > + > + breakpoint_invalidate(cpu, breakpoint->pc); > + > + g_free(breakpoint); > +} > + > +/* Remove all matching breakpoints. */ > +void cpu_breakpoint_remove_all(CPUState *cpu, int mask) > +{ > + CPUBreakpoint *bp, *next; > + > + QTAILQ_FOREACH_SAFE(bp, &cpu->breakpoints, entry, next) { > + if (bp->flags & mask) { > + cpu_breakpoint_remove_by_ref(cpu, bp); > + } > + } > +} > + > +/* enable or disable single step mode. EXCP_DEBUG is returned by the > + CPU loop after each instruction */ > +void cpu_single_step(CPUState *cpu, int enabled) > +{ > + if (cpu->singlestep_enabled != enabled) { > + cpu->singlestep_enabled = enabled; > + if (kvm_enabled()) { > + kvm_update_guest_debug(cpu, 0); > + } else { > + /* must flush all the translated code to avoid inconsistencies */ > + /* XXX: only flush what is necessary */ > + tb_flush(cpu); > + } > + } > +} > + > +void cpu_abort(CPUState *cpu, const char *fmt, ...) > +{ > + va_list ap; > + va_list ap2; > + > + va_start(ap, fmt); > + va_copy(ap2, ap); > + fprintf(stderr, "qemu: fatal: "); > + vfprintf(stderr, fmt, ap); > + fprintf(stderr, "\n"); > + cpu_dump_state(cpu, stderr, CPU_DUMP_FPU | CPU_DUMP_CCOP); > + if (qemu_log_separate()) { > + FILE *logfile = qemu_log_lock(); > + qemu_log("qemu: fatal: "); > + qemu_log_vprintf(fmt, ap2); > + qemu_log("\n"); > + log_cpu_state(cpu, CPU_DUMP_FPU | CPU_DUMP_CCOP); > + qemu_log_flush(); > + qemu_log_unlock(logfile); > + qemu_log_close(); > + } > + va_end(ap2); > + va_end(ap); > + replay_finish(); > +#if defined(CONFIG_USER_ONLY) > + { > + struct sigaction act; > + sigfillset(&act.sa_mask); > + act.sa_handler = SIG_DFL; > + act.sa_flags = 0; > + sigaction(SIGABRT, &act, NULL); > + } > +#endif > + abort(); > +} > + > +/* physical memory access (slow version, mainly for debug) */ > +#if defined(CONFIG_USER_ONLY) > +int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr, > + void *ptr, target_ulong len, bool is_write) > +{ > + int flags; > + target_ulong l, page; > + void * p; > + uint8_t *buf = ptr; > + > + while (len > 0) { > + page = addr & TARGET_PAGE_MASK; > + l = (page + TARGET_PAGE_SIZE) - addr; > + if (l > len) > + l = len; > + flags = page_get_flags(page); > + if (!(flags & PAGE_VALID)) > + return -1; > + if (is_write) { > + if (!(flags & PAGE_WRITE)) > + return -1; > + /* XXX: this code should not depend on lock_user */ > + if (!(p = lock_user(VERIFY_WRITE, addr, l, 0))) > + return -1; > + memcpy(p, buf, l); > + unlock_user(p, addr, l); > + } else { > + if (!(flags & PAGE_READ)) > + return -1; > + /* XXX: this code should not depend on lock_user */ > + if (!(p = lock_user(VERIFY_READ, addr, l, 1))) > + return -1; > + memcpy(buf, p, l); > + unlock_user(p, addr, 0); > + } > + len -= l; > + buf += l; > + addr += l; > + } > + return 0; > +} > +#endif > + > +bool target_words_bigendian(void) > +{ > +#if defined(TARGET_WORDS_BIGENDIAN) > + return true; > +#else > + return false; > +#endif > +} > + > +void page_size_init(void) > +{ > + /* NOTE: we can always suppose that qemu_host_page_size >= > + TARGET_PAGE_SIZE */ > + if (qemu_host_page_size == 0) { > + qemu_host_page_size = qemu_real_host_page_size; > + } > + if (qemu_host_page_size < TARGET_PAGE_SIZE) { > + qemu_host_page_size = TARGET_PAGE_SIZE; > + } > + qemu_host_page_mask = -(intptr_t)qemu_host_page_size; > +} > diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h > index d5e285d2b5..19805ed6db 100644 > --- a/include/exec/cpu-common.h > +++ b/include/exec/cpu-common.h > @@ -14,6 +14,9 @@ void cpu_list_unlock(void); > > void tcg_flush_softmmu_tlb(CPUState *cs); > > +void tcg_iommu_init_notifier_list(CPUState *cpu); > +void tcg_iommu_free_notifier_list(CPUState *cpu); > + > #if !defined(CONFIG_USER_ONLY) > > enum device_endian { > diff --git a/meson.build b/meson.build > index 0e0577e81e..60df291b00 100644 > --- a/meson.build > +++ b/meson.build > @@ -1367,7 +1367,7 @@ common_ss.add(files('cpus-common.c')) > subdir('softmmu') > > common_ss.add(capstone) > -specific_ss.add(files('disas.c', 'exec.c', 'gdbstub.c'), capstone, libpmem, > libdaxctl) > +specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone) > specific_ss.add(files('exec-vary.c')) > specific_ss.add(when: 'CONFIG_TCG', if_true: files( > 'fpu/softfloat.c', > diff --git a/softmmu/meson.build b/softmmu/meson.build > index 862ab24878..8f7210b4f0 100644 > --- a/softmmu/meson.build > +++ b/softmmu/meson.build > @@ -3,6 +3,7 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files( > 'balloon.c', > 'cpus.c', > 'cpu-throttle.c', > + 'physmem.c', > 'ioport.c', > 'memory.c', > 'memory_mapping.c', > @@ -19,7 +20,7 @@ softmmu_ss.add(files( > 'bootdevice.c', > 'dma-helpers.c', > 'qdev-monitor.c', > -), sdl) > +), sdl, libpmem, libdaxctl) > > softmmu_ss.add(when: 'CONFIG_TPM', if_true: files('tpm.c')) > softmmu_ss.add(when: 'CONFIG_SECCOMP', if_true: [files('qemu-seccomp.c'), > seccomp]) > diff --git a/exec.c b/softmmu/physmem.c > similarity index 91% > rename from exec.c > rename to softmmu/physmem.c > index ec68f4a9ca..6acd220f53 100644 > --- a/exec.c > +++ b/softmmu/physmem.c > @@ -1,5 +1,5 @@ > /* > - * Virtual page mapping > + * RAM allocation and memory access > * > * Copyright (c) 2003 Fabrice Bellard > * > @@ -28,10 +28,8 @@ > #include "tcg/tcg.h" > #include "hw/qdev-core.h" > #include "hw/qdev-properties.h" > -#if !defined(CONFIG_USER_ONLY) > #include "hw/boards.h" > #include "hw/xen/xen.h" > -#endif > #include "sysemu/kvm.h" > #include "sysemu/sysemu.h" > #include "sysemu/tcg.h" > @@ -40,9 +38,6 @@ > #include "qemu/config-file.h" > #include "qemu/error-report.h" > #include "qemu/qemu-print.h" > -#if defined(CONFIG_USER_ONLY) > -#include "qemu.h" > -#else /* !CONFIG_USER_ONLY */ > #include "exec/memory.h" > #include "exec/ioport.h" > #include "sysemu/dma.h" > @@ -56,7 +51,6 @@ > #include <linux/falloc.h> > #endif > > -#endif > #include "qemu/rcu_queue.h" > #include "qemu/main-loop.h" > #include "translate-all.h" > @@ -83,7 +77,6 @@ > > //#define DEBUG_SUBPAGE > > -#if !defined(CONFIG_USER_ONLY) > /* ram_list is read under rcu_read_lock()/rcu_read_unlock(). Writes > * are protected by the ramlist lock. > */ > @@ -96,12 +89,6 @@ AddressSpace address_space_io; > AddressSpace address_space_memory; > > static MemoryRegion io_mem_unassigned; > -#endif > - > -uintptr_t qemu_host_page_size; > -intptr_t qemu_host_page_mask; > - > -#if !defined(CONFIG_USER_ONLY) > > typedef struct PhysPageEntry PhysPageEntry; > > @@ -179,10 +166,6 @@ struct DirtyBitmapSnapshot { > unsigned long dirty[]; > }; > > -#endif > - > -#if !defined(CONFIG_USER_ONLY) > - > static void phys_map_node_reserve(PhysPageMap *map, unsigned nodes) > { > static unsigned alloc_hint = 16; > @@ -666,7 +649,7 @@ static void tcg_register_iommu_notifier(CPUState *cpu, > } > } > > -static void tcg_iommu_free_notifier_list(CPUState *cpu) > +void tcg_iommu_free_notifier_list(CPUState *cpu) > { > /* Destroy the CPU's notifier list */ > int i; > @@ -680,6 +663,11 @@ static void tcg_iommu_free_notifier_list(CPUState *cpu) > g_array_free(cpu->iommu_notifiers, true); > } > > +void tcg_iommu_init_notifier_list(CPUState *cpu) > +{ > + cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier > *)); > +} > + > /* Called from RCU critical section */ > MemoryRegionSection * > address_space_translate_for_iotlb(CPUState *cpu, int asidx, hwaddr addr, > @@ -737,91 +725,6 @@ address_space_translate_for_iotlb(CPUState *cpu, int > asidx, hwaddr addr, > translate_fail: > return &d->map.sections[PHYS_SECTION_UNASSIGNED]; > } > -#endif > - > -#if !defined(CONFIG_USER_ONLY) > - > -static int cpu_common_post_load(void *opaque, int version_id) > -{ > - CPUState *cpu = opaque; > - > - /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the > - version_id is increased. */ > - cpu->interrupt_request &= ~0x01; > - tlb_flush(cpu); > - > - /* loadvm has just updated the content of RAM, bypassing the > - * usual mechanisms that ensure we flush TBs for writes to > - * memory we've translated code from. So we must flush all TBs, > - * which will now be stale. > - */ > - tb_flush(cpu); > - > - return 0; > -} > - > -static int cpu_common_pre_load(void *opaque) > -{ > - CPUState *cpu = opaque; > - > - cpu->exception_index = -1; > - > - return 0; > -} > - > -static bool cpu_common_exception_index_needed(void *opaque) > -{ > - CPUState *cpu = opaque; > - > - return tcg_enabled() && cpu->exception_index != -1; > -} > - > -static const VMStateDescription vmstate_cpu_common_exception_index = { > - .name = "cpu_common/exception_index", > - .version_id = 1, > - .minimum_version_id = 1, > - .needed = cpu_common_exception_index_needed, > - .fields = (VMStateField[]) { > - VMSTATE_INT32(exception_index, CPUState), > - VMSTATE_END_OF_LIST() > - } > -}; > - > -static bool cpu_common_crash_occurred_needed(void *opaque) > -{ > - CPUState *cpu = opaque; > - > - return cpu->crash_occurred; > -} > - > -static const VMStateDescription vmstate_cpu_common_crash_occurred = { > - .name = "cpu_common/crash_occurred", > - .version_id = 1, > - .minimum_version_id = 1, > - .needed = cpu_common_crash_occurred_needed, > - .fields = (VMStateField[]) { > - VMSTATE_BOOL(crash_occurred, CPUState), > - VMSTATE_END_OF_LIST() > - } > -}; > - > -const VMStateDescription vmstate_cpu_common = { > - .name = "cpu_common", > - .version_id = 1, > - .minimum_version_id = 1, > - .pre_load = cpu_common_pre_load, > - .post_load = cpu_common_post_load, > - .fields = (VMStateField[]) { > - VMSTATE_UINT32(halted, CPUState), > - VMSTATE_UINT32(interrupt_request, CPUState), > - VMSTATE_END_OF_LIST() > - }, > - .subsections = (const VMStateDescription*[]) { > - &vmstate_cpu_common_exception_index, > - &vmstate_cpu_common_crash_occurred, > - NULL > - } > -}; > > void cpu_address_space_init(CPUState *cpu, int asidx, > const char *prefix, MemoryRegion *mr) > @@ -865,155 +768,7 @@ AddressSpace *cpu_get_address_space(CPUState *cpu, int > asidx) > /* Return the AddressSpace corresponding to the specified index */ > return cpu->cpu_ases[asidx].as; > } > -#endif > - > -void cpu_exec_unrealizefn(CPUState *cpu) > -{ > - CPUClass *cc = CPU_GET_CLASS(cpu); > - > - tlb_destroy(cpu); > - cpu_list_remove(cpu); > - > - if (cc->vmsd != NULL) { > - vmstate_unregister(NULL, cc->vmsd, cpu); > - } > - if (qdev_get_vmsd(DEVICE(cpu)) == NULL) { > - vmstate_unregister(NULL, &vmstate_cpu_common, cpu); > - } > -#ifndef CONFIG_USER_ONLY > - tcg_iommu_free_notifier_list(cpu); > -#endif > -} > - > -Property cpu_common_props[] = { > -#ifndef CONFIG_USER_ONLY > - /* Create a memory property for softmmu CPU object, > - * so users can wire up its memory. (This can't go in hw/core/cpu.c > - * because that file is compiled only once for both user-mode > - * and system builds.) The default if no link is set up is to use > - * the system address space. > - */ > - DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION, > - MemoryRegion *), > -#endif > - DEFINE_PROP_BOOL("start-powered-off", CPUState, start_powered_off, > false), > - DEFINE_PROP_END_OF_LIST(), > -}; > - > -void cpu_exec_initfn(CPUState *cpu) > -{ > - cpu->as = NULL; > - cpu->num_ases = 0; > - > -#ifndef CONFIG_USER_ONLY > - cpu->thread_id = qemu_get_thread_id(); > - cpu->memory = system_memory; > - object_ref(OBJECT(cpu->memory)); > -#endif > -} > - > -void cpu_exec_realizefn(CPUState *cpu, Error **errp) > -{ > - CPUClass *cc = CPU_GET_CLASS(cpu); > - static bool tcg_target_initialized; > - > - cpu_list_add(cpu); > - > - if (tcg_enabled() && !tcg_target_initialized) { > - tcg_target_initialized = true; > - cc->tcg_initialize(); > - } > - tlb_init(cpu); > - > - qemu_plugin_vcpu_init_hook(cpu); > - > -#ifdef CONFIG_USER_ONLY > - assert(cc->vmsd == NULL); > -#else /* !CONFIG_USER_ONLY */ > - if (qdev_get_vmsd(DEVICE(cpu)) == NULL) { > - vmstate_register(NULL, cpu->cpu_index, &vmstate_cpu_common, cpu); > - } > - if (cc->vmsd != NULL) { > - vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu); > - } > - > - cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier > *)); > -#endif > -} > - > -const char *parse_cpu_option(const char *cpu_option) > -{ > - ObjectClass *oc; > - CPUClass *cc; > - gchar **model_pieces; > - const char *cpu_type; > - > - model_pieces = g_strsplit(cpu_option, ",", 2); > - if (!model_pieces[0]) { > - error_report("-cpu option cannot be empty"); > - exit(1); > - } > - > - oc = cpu_class_by_name(CPU_RESOLVING_TYPE, model_pieces[0]); > - if (oc == NULL) { > - error_report("unable to find CPU model '%s'", model_pieces[0]); > - g_strfreev(model_pieces); > - exit(EXIT_FAILURE); > - } > - > - cpu_type = object_class_get_name(oc); > - cc = CPU_CLASS(oc); > - cc->parse_features(cpu_type, model_pieces[1], &error_fatal); > - g_strfreev(model_pieces); > - return cpu_type; > -} > - > -#if defined(CONFIG_USER_ONLY) > -void tb_invalidate_phys_addr(target_ulong addr) > -{ > - mmap_lock(); > - tb_invalidate_phys_page_range(addr, addr + 1); > - mmap_unlock(); > -} > - > -static void breakpoint_invalidate(CPUState *cpu, target_ulong pc) > -{ > - tb_invalidate_phys_addr(pc); > -} > -#else > -void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs) > -{ > - ram_addr_t ram_addr; > - MemoryRegion *mr; > - hwaddr l = 1; > - > - if (!tcg_enabled()) { > - return; > - } > - > - RCU_READ_LOCK_GUARD(); > - mr = address_space_translate(as, addr, &addr, &l, false, attrs); > - if (!(memory_region_is_ram(mr) > - || memory_region_is_romd(mr))) { > - return; > - } > - ram_addr = memory_region_get_ram_addr(mr) + addr; > - tb_invalidate_phys_page_range(ram_addr, ram_addr + 1); > -} > > -static void breakpoint_invalidate(CPUState *cpu, target_ulong pc) > -{ > - /* > - * There may not be a virtual to physical translation for the pc > - * right now, but there may exist cached TB for this pc. > - * Flush the whole TB cache to force re-translation of such TBs. > - * This is heavyweight, but we're debugging anyway. > - */ > - tb_flush(cpu); > -} > -#endif > - > -#ifndef CONFIG_USER_ONLY > /* Add a watchpoint. */ > int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len, > int flags, CPUWatchpoint **watchpoint) > @@ -1122,123 +877,7 @@ int cpu_watchpoint_address_matches(CPUState *cpu, > vaddr addr, vaddr len) > } > return ret; > } > -#endif /* !CONFIG_USER_ONLY */ > - > -/* Add a breakpoint. */ > -int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags, > - CPUBreakpoint **breakpoint) > -{ > - CPUBreakpoint *bp; > - > - bp = g_malloc(sizeof(*bp)); > - > - bp->pc = pc; > - bp->flags = flags; > - > - /* keep all GDB-injected breakpoints in front */ > - if (flags & BP_GDB) { > - QTAILQ_INSERT_HEAD(&cpu->breakpoints, bp, entry); > - } else { > - QTAILQ_INSERT_TAIL(&cpu->breakpoints, bp, entry); > - } > - > - breakpoint_invalidate(cpu, pc); > - > - if (breakpoint) { > - *breakpoint = bp; > - } > - return 0; > -} > - > -/* Remove a specific breakpoint. */ > -int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags) > -{ > - CPUBreakpoint *bp; > - > - QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { > - if (bp->pc == pc && bp->flags == flags) { > - cpu_breakpoint_remove_by_ref(cpu, bp); > - return 0; > - } > - } > - return -ENOENT; > -} > > -/* Remove a specific breakpoint by reference. */ > -void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *breakpoint) > -{ > - QTAILQ_REMOVE(&cpu->breakpoints, breakpoint, entry); > - > - breakpoint_invalidate(cpu, breakpoint->pc); > - > - g_free(breakpoint); > -} > - > -/* Remove all matching breakpoints. */ > -void cpu_breakpoint_remove_all(CPUState *cpu, int mask) > -{ > - CPUBreakpoint *bp, *next; > - > - QTAILQ_FOREACH_SAFE(bp, &cpu->breakpoints, entry, next) { > - if (bp->flags & mask) { > - cpu_breakpoint_remove_by_ref(cpu, bp); > - } > - } > -} > - > -/* enable or disable single step mode. EXCP_DEBUG is returned by the > - CPU loop after each instruction */ > -void cpu_single_step(CPUState *cpu, int enabled) > -{ > - if (cpu->singlestep_enabled != enabled) { > - cpu->singlestep_enabled = enabled; > - if (kvm_enabled()) { > - kvm_update_guest_debug(cpu, 0); > - } else { > - /* must flush all the translated code to avoid inconsistencies */ > - /* XXX: only flush what is necessary */ > - tb_flush(cpu); > - } > - } > -} > - > -void cpu_abort(CPUState *cpu, const char *fmt, ...) > -{ > - va_list ap; > - va_list ap2; > - > - va_start(ap, fmt); > - va_copy(ap2, ap); > - fprintf(stderr, "qemu: fatal: "); > - vfprintf(stderr, fmt, ap); > - fprintf(stderr, "\n"); > - cpu_dump_state(cpu, stderr, CPU_DUMP_FPU | CPU_DUMP_CCOP); > - if (qemu_log_separate()) { > - FILE *logfile = qemu_log_lock(); > - qemu_log("qemu: fatal: "); > - qemu_log_vprintf(fmt, ap2); > - qemu_log("\n"); > - log_cpu_state(cpu, CPU_DUMP_FPU | CPU_DUMP_CCOP); > - qemu_log_flush(); > - qemu_log_unlock(logfile); > - qemu_log_close(); > - } > - va_end(ap2); > - va_end(ap); > - replay_finish(); > -#if defined(CONFIG_USER_ONLY) > - { > - struct sigaction act; > - sigfillset(&act.sa_mask); > - act.sa_handler = SIG_DFL; > - act.sa_flags = 0; > - sigaction(SIGABRT, &act, NULL); > - } > -#endif > - abort(); > -} > - > -#if !defined(CONFIG_USER_ONLY) > /* Called from RCU critical section */ > static RAMBlock *qemu_get_ram_block(ram_addr_t addr) > { > @@ -1425,9 +1064,6 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu, > AddressSpaceDispatch *d = flatview_to_dispatch(section->fv); > return section - d->map.sections; > } > -#endif /* defined(CONFIG_USER_ONLY) */ > - > -#if !defined(CONFIG_USER_ONLY) > > static int subpage_register(subpage_t *mmio, uint32_t start, uint32_t end, > uint16_t section); > @@ -3028,52 +2664,6 @@ MemoryRegion *get_system_io(void) > return system_io; > } > > -#endif /* !defined(CONFIG_USER_ONLY) */ > - > -/* physical memory access (slow version, mainly for debug) */ > -#if defined(CONFIG_USER_ONLY) > -int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr, > - void *ptr, target_ulong len, bool is_write) > -{ > - int flags; > - target_ulong l, page; > - void * p; > - uint8_t *buf = ptr; > - > - while (len > 0) { > - page = addr & TARGET_PAGE_MASK; > - l = (page + TARGET_PAGE_SIZE) - addr; > - if (l > len) > - l = len; > - flags = page_get_flags(page); > - if (!(flags & PAGE_VALID)) > - return -1; > - if (is_write) { > - if (!(flags & PAGE_WRITE)) > - return -1; > - /* XXX: this code should not depend on lock_user */ > - if (!(p = lock_user(VERIFY_WRITE, addr, l, 0))) > - return -1; > - memcpy(p, buf, l); > - unlock_user(p, addr, l); > - } else { > - if (!(flags & PAGE_READ)) > - return -1; > - /* XXX: this code should not depend on lock_user */ > - if (!(p = lock_user(VERIFY_READ, addr, l, 1))) > - return -1; > - memcpy(buf, p, l); > - unlock_user(p, addr, 0); > - } > - len -= l; > - buf += l; > - addr += l; > - } > - return 0; > -} > - > -#else > - > static void invalidate_and_set_dirty(MemoryRegion *mr, hwaddr addr, > hwaddr length) > { > @@ -3862,18 +3452,7 @@ int qemu_target_page_bits_min(void) > { > return TARGET_PAGE_BITS_MIN; > } > -#endif > - > -bool target_words_bigendian(void) > -{ > -#if defined(TARGET_WORDS_BIGENDIAN) > - return true; > -#else > - return false; > -#endif > -} > > -#ifndef CONFIG_USER_ONLY > bool cpu_physical_memory_is_io(hwaddr phys_addr) > { > MemoryRegion*mr; > @@ -4003,23 +3582,6 @@ bool ramblock_is_pmem(RAMBlock *rb) > return rb->flags & RAM_PMEM; > } > > -#endif > - > -void page_size_init(void) > -{ > - /* NOTE: we can always suppose that qemu_host_page_size >= > - TARGET_PAGE_SIZE */ > - if (qemu_host_page_size == 0) { > - qemu_host_page_size = qemu_real_host_page_size; > - } > - if (qemu_host_page_size < TARGET_PAGE_SIZE) { > - qemu_host_page_size = TARGET_PAGE_SIZE; > - } > - qemu_host_page_mask = -(intptr_t)qemu_host_page_size; > -} > - > -#if !defined(CONFIG_USER_ONLY) > - > static void mtree_print_phys_entries(int start, int end, int skip, int ptr) > { > if (start == end - 1) { > @@ -4152,5 +3714,3 @@ bool ram_block_discard_is_required(void) > { > return qatomic_read(&ram_block_discard_disabled) < 0; > } > - > -#endif >