X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=memory_mapping.c;h=ff45b3a2393f28d326feeeaf962ec387a2e917ab;hb=110db9b48c0a6379fca122801c3ae48e349aa6d4;hp=718f271849da2e3e3f22a4d9c88038d72ce63c57;hpb=80167a8a31d7c42e3e33ec23592eb14938c88098;p=qemu.git diff --git a/memory_mapping.c b/memory_mapping.c index 718f27184..ff45b3a23 100644 --- a/memory_mapping.c +++ b/memory_mapping.c @@ -6,14 +6,14 @@ * Authors: * Wen Congyang * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. * */ #include "cpu.h" -#include "cpu-all.h" -#include "memory_mapping.h" +#include "exec/cpu-all.h" +#include "sysemu/memory_mapping.h" static void memory_mapping_list_add_mapping_sorted(MemoryMappingList *list, MemoryMapping *mapping) @@ -30,8 +30,8 @@ static void memory_mapping_list_add_mapping_sorted(MemoryMappingList *list, } static void create_new_memory_mapping(MemoryMappingList *list, - target_phys_addr_t phys_addr, - target_phys_addr_t virt_addr, + hwaddr phys_addr, + hwaddr virt_addr, ram_addr_t length) { MemoryMapping *memory_mapping; @@ -46,8 +46,8 @@ static void create_new_memory_mapping(MemoryMappingList *list, } static inline bool mapping_contiguous(MemoryMapping *map, - target_phys_addr_t phys_addr, - target_phys_addr_t virt_addr) + hwaddr phys_addr, + hwaddr virt_addr) { return phys_addr == map->phys_addr + map->length && virt_addr == map->virt_addr + map->length; @@ -58,7 +58,7 @@ static inline bool mapping_contiguous(MemoryMapping *map, * [phys_addr, phys_addr + length) have intersection? */ static inline bool mapping_have_same_region(MemoryMapping *map, - target_phys_addr_t phys_addr, + hwaddr phys_addr, ram_addr_t length) { return !(phys_addr + length < map->phys_addr || @@ -71,8 +71,8 @@ static inline bool mapping_have_same_region(MemoryMapping *map, * intersection are the same? */ static inline bool mapping_conflict(MemoryMapping *map, - target_phys_addr_t phys_addr, - target_phys_addr_t virt_addr) + hwaddr phys_addr, + hwaddr virt_addr) { return virt_addr - map->virt_addr != phys_addr - map->phys_addr; } @@ -83,7 +83,7 @@ static inline bool mapping_conflict(MemoryMapping *map, * in the intersection are the same. */ static inline void mapping_merge(MemoryMapping *map, - target_phys_addr_t virt_addr, + hwaddr virt_addr, ram_addr_t length) { if (virt_addr < map->virt_addr) { @@ -98,8 +98,8 @@ static inline void mapping_merge(MemoryMapping *map, } void memory_mapping_list_add_merge_sorted(MemoryMappingList *list, - target_phys_addr_t phys_addr, - target_phys_addr_t virt_addr, + hwaddr phys_addr, + hwaddr virt_addr, ram_addr_t length) { MemoryMapping *memory_mapping, *last_mapping; @@ -164,3 +164,83 @@ void memory_mapping_list_init(MemoryMappingList *list) list->last_mapping = NULL; QTAILQ_INIT(&list->head); } + +static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu) +{ + CPUArchState *env; + + for (env = start_cpu; env != NULL; env = env->next_cpu) { + if (cpu_paging_enabled(env)) { + return env; + } + } + + return NULL; +} + +int qemu_get_guest_memory_mapping(MemoryMappingList *list) +{ + CPUArchState *env, *first_paging_enabled_cpu; + RAMBlock *block; + ram_addr_t offset, length; + int ret; + + first_paging_enabled_cpu = find_paging_enabled_cpu(first_cpu); + if (first_paging_enabled_cpu) { + for (env = first_paging_enabled_cpu; env != NULL; env = env->next_cpu) { + ret = cpu_get_memory_mapping(list, env); + if (ret < 0) { + return -1; + } + } + return 0; + } + + /* + * If the guest doesn't use paging, the virtual address is equal to physical + * address. + */ + QTAILQ_FOREACH(block, &ram_list.blocks, next) { + offset = block->offset; + length = block->length; + create_new_memory_mapping(list, offset, offset, length); + } + + return 0; +} + +void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list) +{ + RAMBlock *block; + + QTAILQ_FOREACH(block, &ram_list.blocks, next) { + create_new_memory_mapping(list, block->offset, 0, block->length); + } +} + +void memory_mapping_filter(MemoryMappingList *list, int64_t begin, + int64_t length) +{ + MemoryMapping *cur, *next; + + QTAILQ_FOREACH_SAFE(cur, &list->head, next, next) { + if (cur->phys_addr >= begin + length || + cur->phys_addr + cur->length <= begin) { + QTAILQ_REMOVE(&list->head, cur, next); + list->num--; + continue; + } + + if (cur->phys_addr < begin) { + cur->length -= begin - cur->phys_addr; + if (cur->virt_addr) { + cur->virt_addr += begin - cur->phys_addr; + } + cur->phys_addr = begin; + } + + if (cur->phys_addr + cur->length > begin + length) { + cur->length -= cur->phys_addr + cur->length - begin - length; + } + } +}