X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/c4e9f845f6248885ff73a9e1ecb74052a1c3dcd4..319bd5edb92addc725b2701d73381c415146c287:/exec.c diff --git a/exec.c b/exec.c index 2646207661..4aaa14b075 100644 --- a/exec.c +++ b/exec.c @@ -16,7 +16,9 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ + #include "qemu/osdep.h" +#include "qemu-common.h" #include "qapi/error.h" #include "qemu/cutils.h" @@ -32,6 +34,7 @@ #endif #include "sysemu/kvm.h" #include "sysemu/sysemu.h" +#include "sysemu/tcg.h" #include "qemu/timer.h" #include "qemu/config-file.h" #include "qemu/error-report.h" @@ -39,11 +42,10 @@ #if defined(CONFIG_USER_ONLY) #include "qemu.h" #else /* !CONFIG_USER_ONLY */ -#include "hw/hw.h" #include "exec/memory.h" #include "exec/ioport.h" #include "sysemu/dma.h" -#include "sysemu/numa.h" +#include "sysemu/hostmem.h" #include "sysemu/hw_accel.h" #include "exec/address-spaces.h" #include "sysemu/xen-mapcache.h" @@ -983,14 +985,18 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp) #endif } -const char *parse_cpu_model(const char *cpu_model) +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_model, ",", 2); + 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) { @@ -1351,6 +1357,8 @@ bool cpu_physical_memory_test_and_clear_dirty(ram_addr_t start, DirtyMemoryBlocks *blocks; unsigned long end, page; bool dirty = false; + RAMBlock *ramblock; + uint64_t mr_offset, mr_size; if (length == 0) { return false; @@ -1362,6 +1370,10 @@ bool cpu_physical_memory_test_and_clear_dirty(ram_addr_t start, rcu_read_lock(); blocks = atomic_rcu_read(&ram_list.dirty_memory[client]); + ramblock = qemu_get_ram_block(start); + /* Range sanity check on the ramblock */ + assert(start >= ramblock->offset && + start + length <= ramblock->offset + ramblock->used_length); while (page < end) { unsigned long idx = page / DIRTY_MEMORY_BLOCK_SIZE; @@ -1373,6 +1385,10 @@ bool cpu_physical_memory_test_and_clear_dirty(ram_addr_t start, page += num; } + mr_offset = (ram_addr_t)(page << TARGET_PAGE_BITS) - ramblock->offset; + mr_size = (end - page) << TARGET_PAGE_BITS; + memory_region_clear_dirty_bitmap(ramblock->mr, mr_offset, mr_size); + rcu_read_unlock(); if (dirty && tcg_enabled()) { @@ -1383,9 +1399,10 @@ bool cpu_physical_memory_test_and_clear_dirty(ram_addr_t start, } DirtyBitmapSnapshot *cpu_physical_memory_snapshot_and_clear_dirty - (ram_addr_t start, ram_addr_t length, unsigned client) + (MemoryRegion *mr, hwaddr offset, hwaddr length, unsigned client) { DirtyMemoryBlocks *blocks; + ram_addr_t start = memory_region_get_ram_addr(mr) + offset; unsigned long align = 1UL << (TARGET_PAGE_BITS + BITS_PER_LEVEL); ram_addr_t first = QEMU_ALIGN_DOWN(start, align); ram_addr_t last = QEMU_ALIGN_UP(start + length, align); @@ -1427,6 +1444,8 @@ DirtyBitmapSnapshot *cpu_physical_memory_snapshot_and_clear_dirty tlb_reset_dirty_range_all(start, length); } + memory_region_clear_dirty_bitmap(mr, offset, length); + return snap; } @@ -1688,7 +1707,7 @@ void ram_block_dump(Monitor *mon) * when we actually open and map them. Iterate over the file * descriptors instead, and use qemu_fd_getpagesize(). */ -static int find_max_supported_pagesize(Object *obj, void *opaque) +static int find_min_backend_pagesize(Object *obj, void *opaque) { long *hpsize_min = opaque; @@ -1704,7 +1723,27 @@ static int find_max_supported_pagesize(Object *obj, void *opaque) return 0; } -long qemu_getrampagesize(void) +static int find_max_backend_pagesize(Object *obj, void *opaque) +{ + long *hpsize_max = opaque; + + if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) { + HostMemoryBackend *backend = MEMORY_BACKEND(obj); + long hpsize = host_memory_backend_pagesize(backend); + + if (host_memory_backend_is_mapped(backend) && (hpsize > *hpsize_max)) { + *hpsize_max = hpsize; + } + } + + return 0; +} + +/* + * TODO: We assume right now that all mapped host memory backends are + * used as RAM, however some might be used for different purposes. + */ +long qemu_minrampagesize(void) { long hpsize = LONG_MAX; long mainrampagesize; @@ -1724,7 +1763,7 @@ long qemu_getrampagesize(void) */ memdev_root = object_resolve_path("/objects", NULL); if (memdev_root) { - object_child_foreach(memdev_root, find_max_supported_pagesize, &hpsize); + object_child_foreach(memdev_root, find_min_backend_pagesize, &hpsize); } if (hpsize == LONG_MAX) { /* No additional memory regions found ==> Report main RAM page size */ @@ -1747,8 +1786,24 @@ long qemu_getrampagesize(void) return hpsize; } + +long qemu_maxrampagesize(void) +{ + long pagesize = qemu_mempath_getpagesize(mem_path); + Object *memdev_root = object_resolve_path("/objects", NULL); + + if (memdev_root) { + object_child_foreach(memdev_root, find_max_backend_pagesize, + &pagesize); + } + return pagesize; +} #else -long qemu_getrampagesize(void) +long qemu_minrampagesize(void) +{ + return getpagesize(); +} +long qemu_maxrampagesize(void) { return getpagesize(); } @@ -1831,6 +1886,7 @@ static void *file_ram_alloc(RAMBlock *block, bool truncate, Error **errp) { + MachineState *ms = MACHINE(qdev_get_machine()); void *area; block->page_size = qemu_fd_getpagesize(fd); @@ -1879,7 +1935,7 @@ static void *file_ram_alloc(RAMBlock *block, } area = qemu_ram_mmap(fd, memory, block->mr->align, - block->flags & RAM_SHARED); + block->flags & RAM_SHARED, block->flags & RAM_PMEM); if (area == MAP_FAILED) { error_setg_errno(errp, errno, "unable to map backing store for guest RAM"); @@ -1887,7 +1943,7 @@ static void *file_ram_alloc(RAMBlock *block, } if (mem_prealloc) { - os_mem_prealloc(fd, area, memory, smp_cpus, errp); + os_mem_prealloc(fd, area, memory, ms->smp.cpus, errp); if (errp && *errp) { qemu_ram_munmap(fd, area, memory); return NULL;