diff --git a/cpu-common.h b/cpu-common.h index 6302372..6780506 100644 --- a/cpu-common.h +++ b/cpu-common.h @@ -30,6 +30,7 @@ static inline void cpu_register_physical_memory(target_phys_addr_t start_addr, ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr); ram_addr_t qemu_ram_alloc(ram_addr_t); +ram_addr_t qemu_ram_alloc_named(ram_addr_t, const char *); void qemu_ram_free(ram_addr_t addr); /* This should only be used for ram local to a device. */ void *qemu_get_ram_ptr(ram_addr_t addr); diff --git a/exec.c b/exec.c index c82e767..58c2a8e 100644 --- a/exec.c +++ b/exec.c @@ -2403,14 +2403,29 @@ void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size) kvm_uncoalesce_mmio_region(addr, size); } -ram_addr_t qemu_ram_alloc(ram_addr_t size) +extern const char *named_map_prefix; +extern const char *named_maps; + +ram_addr_t qemu_ram_alloc_named(ram_addr_t size, const char *name) { RAMBlock *new_block; + const char *p; size = TARGET_PAGE_ALIGN(size); new_block = qemu_malloc(sizeof(*new_block)); - - new_block->host = qemu_vmalloc(size); + + if (name && named_maps && + (p = strstr(named_maps, name)) && + (p == named_maps || p[-1] == ',')) { + char buffer[512]; + int fd; + snprintf(buffer, 512, "%s%s", named_map_prefix, name); + fd = open(buffer, O_CREAT | O_RDWR, 0640); + ftruncate(fd, 0); + ftruncate(fd, size); + new_block->host = mmap(NULL, size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + } else + new_block->host = qemu_vmalloc(size); new_block->offset = last_ram_offset; new_block->length = size; @@ -2430,6 +2445,11 @@ ram_addr_t qemu_ram_alloc(ram_addr_t size) return new_block->offset; } +ram_addr_t qemu_ram_alloc(ram_addr_t size) +{ + return qemu_ram_alloc_named(size, NULL); +} + void qemu_ram_free(ram_addr_t addr) { /* TODO: implement this. */ diff --git a/hw/pc.c b/hw/pc.c index 58de372..1dac0ca 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -1161,7 +1161,7 @@ static void pc_init1(ram_addr_t ram_size, vmport_init(); /* allocate RAM */ - ram_addr = qemu_ram_alloc(0xa0000); + ram_addr = qemu_ram_alloc_named(0xa0000, "640k"); cpu_register_physical_memory(0, 0xa0000, ram_addr); /* Allocate, even though we won't register, so we don't break the @@ -1169,7 +1169,7 @@ static void pc_init1(ram_addr_t ram_size, * and some bios areas, which will be registered later */ ram_addr = qemu_ram_alloc(0x100000 - 0xa0000); - ram_addr = qemu_ram_alloc(below_4g_mem_size - 0x100000); + ram_addr = qemu_ram_alloc_named(below_4g_mem_size - 0x100000, "below_4g"); cpu_register_physical_memory(0x100000, below_4g_mem_size - 0x100000, ram_addr); @@ -1179,7 +1179,7 @@ static void pc_init1(ram_addr_t ram_size, #if TARGET_PHYS_ADDR_BITS == 32 hw_error("To much RAM for 32-bit physical address"); #else - ram_addr = qemu_ram_alloc(above_4g_mem_size); + ram_addr = qemu_ram_alloc_named(above_4g_mem_size, "above_4g"); cpu_register_physical_memory(0x100000000ULL, above_4g_mem_size, ram_addr); @@ -1200,7 +1200,7 @@ static void pc_init1(ram_addr_t ram_size, (bios_size % 65536) != 0) { goto bios_error; } - bios_offset = qemu_ram_alloc(bios_size); + bios_offset = qemu_ram_alloc_named(bios_size, "bios"); ret = load_image(filename, qemu_get_ram_ptr(bios_offset)); if (ret != bios_size) { bios_error: @@ -1220,7 +1220,7 @@ static void pc_init1(ram_addr_t ram_size, - option_rom_offset = qemu_ram_alloc(0x20000); + option_rom_offset = qemu_ram_alloc_named(0x20000, "option_rom"); oprom_area_size = 0; cpu_register_physical_memory(0xc0000, 0x20000, option_rom_offset); diff --git a/hw/vga.c b/hw/vga.c index 514371c..feb0706 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -2238,7 +2238,7 @@ void vga_common_init(VGACommonState *s, int vga_ram_size) expand4to8[i] = v; } - s->vram_offset = qemu_ram_alloc(vga_ram_size); + s->vram_offset = qemu_ram_alloc_named(vga_ram_size, "vga"); s->vram_ptr = qemu_get_ram_ptr(s->vram_offset); s->vram_size = vga_ram_size; s->get_bpp = vga_get_bpp; diff --git a/qemu-options.hx b/qemu-options.hx index d3aa55b..6db8b9e 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -280,6 +280,10 @@ a suffix of ``M'' or ``G'' can be used to signify a value in megabytes or gigabytes respectively. ETEXI +DEF("sharedmaps", HAS_ARG, QEMU_OPTION_sharedmaps, + "-sharedmaps prefix:maps \ + Use files beginning with 'prefix' for memory allocations 'maps'\n") + DEF("k", HAS_ARG, QEMU_OPTION_k, "-k language use keyboard layout (for example 'fr' for French)\n") STEXI diff --git a/vl.c b/vl.c index eb01da7..8b9b9e0 100644 --- a/vl.c +++ b/vl.c @@ -270,6 +270,9 @@ uint8_t qemu_uuid[16]; static QEMUBootSetHandler *boot_set_handler; static void *boot_set_opaque; +char *named_map_prefix = NULL; +char *named_maps = NULL; + /***********************************************************/ /* x86 ISA bus support */ @@ -5010,6 +5013,18 @@ int main(int argc, char **argv, char **envp) version(); exit(0); break; + case QEMU_OPTION_sharedmaps: + if (!strcmp(optarg, "?")) { + fprintf(stderr, "supported named maps: "); + fprintf(stderr, "640k, below_4g, above_4g, vga, bios, option_rom\n"); + exit(0); + } else { + named_map_prefix = strdup(optarg); + named_maps = strchr(named_map_prefix, ':'); + if (named_maps) + *named_maps++ = '\0'; + } + break; case QEMU_OPTION_m: { uint64_t value; char *ptr;