diff --git a/platform/qemu-virt/platform.c b/platform/qemu-virt/platform.c index bc644f33..310db77e 100644 --- a/platform/qemu-virt/platform.c +++ b/platform/qemu-virt/platform.c @@ -36,13 +36,14 @@ #include #include #include +#include #include "platform_p.h" #if WITH_LIB_MINIP #include #endif -#define MEMORY_SIZE (MEMSIZE) // XXX get this from the emulator somehow +#define DEFAULT_MEMORY_SIZE (MEMSIZE) /* try to fetch from the emulator via the fdt */ /* initial memory mappings. parsed by start.S */ struct mmu_initial_mapping mmu_initial_mappings[] = { @@ -71,7 +72,7 @@ struct mmu_initial_mapping mmu_initial_mappings[] = { static pmm_arena_t arena = { .name = "ram", .base = MEMORY_BASE_PHYS, - .size = MEMORY_SIZE, + .size = DEFAULT_MEMORY_SIZE, .flags = PMM_ARENA_FLAG_KMAP, }; @@ -84,8 +85,53 @@ void platform_early_init(void) uart_init_early(); + /* look for a flattened device tree just before the kernel */ + const void *fdt = (void *)KERNEL_BASE; + int err = fdt_check_header(fdt); + if (err >= 0) { + /* walk the nodes, looking for 'memory' */ + int depth = 0; + int offset = 0; + for (;;) { + offset = fdt_next_node(fdt, offset, &depth); + if (offset < 0) + break; + + /* get the name */ + const char *name = fdt_get_name(fdt, offset, NULL); + if (!name) + continue; + + /* look for the 'memory' property */ + if (strcmp(name, "memory") == 0) { + int lenp; + const void *prop_ptr = fdt_getprop(fdt, offset, "reg", &lenp); + if (prop_ptr && lenp == 0x10) { + /* we're looking at a memory descriptor */ + //uint64_t base = fdt64_to_cpu(*(uint64_t *)prop_ptr); + uint64_t len = fdt64_to_cpu(*((const uint64_t *)prop_ptr + 1)); + + /* trim size on certain platforms */ +#if ARCH_ARM + if (len > 1024*1024*1024U) { + len = 1024*1024*1024; /* only use the first 1GB on ARM32 */ + printf("trimming memory to 1GB\n"); + } +#endif + + /* set the size in the pmm arena */ + arena.size = len; + } + } + } + } + /* add the main memory arena */ pmm_add_arena(&arena); + + /* reserve the first 64k of ram, which should be holding the fdt */ + struct list_node list = LIST_INITIAL_VALUE(list); + pmm_alloc_range(MEMBASE, 0x10000 / PAGE_SIZE, &list); } void platform_init(void) diff --git a/platform/qemu-virt/rules.mk b/platform/qemu-virt/rules.mk index b4fbc76b..8457dd5e 100644 --- a/platform/qemu-virt/rules.mk +++ b/platform/qemu-virt/rules.mk @@ -23,9 +23,11 @@ MODULE_SRCS += \ MEMBASE := 0x40000000 MEMSIZE ?= 0x08000000 # 512MB +KERNEL_LOAD_OFFSET := 0x10000 # 64k MODULE_DEPS += \ lib/cbuf \ + lib/fdt \ dev/interrupt/arm_gic \ dev/timer/arm_generic \ dev/virtio/block \ diff --git a/scripts/do-qemuarm b/scripts/do-qemuarm index a63ad526..cd166a36 100755 --- a/scripts/do-qemuarm +++ b/scripts/do-qemuarm @@ -7,6 +7,7 @@ function HELP { echo "-t a virtio tap network device" echo "-d a virtio display" echo "-6 64bit arm" + echo "-m " echo "-h for help" echo "all arguments after -- are passed to qemu directly" exit 1 @@ -17,15 +18,18 @@ DO_NET_TAP=0 DO_BLOCK=0 DO_64BIT=0 DO_DISPLAY=0 +MEMSIZE=512 SUDO="" -while getopts bdhnt6 FLAG; do +while getopts bdhm:nt6 FLAG; do case $FLAG in b) DO_BLOCK=1;; d) DO_DISPLAY=1;; n) DO_NET=1;; t) DO_NET_TAP=1;; 6) DO_64BIT=1;; + 6) DO_MEM=1;; + m) MEMSIZE=$OPTARG;; h) HELP;; \?) echo unrecognized option @@ -43,7 +47,7 @@ else PROJECT="qemu-virt-a15-test" fi -ARGS=" -m 512 -kernel build-${PROJECT}/lk.elf" +ARGS=" -m $MEMSIZE -kernel build-${PROJECT}/lk.elf" BLOCK_ARGS=" -drive if=none,file=blk.bin,id=blk,format=raw -device virtio-blk-device,drive=blk" NET_ARGS=" -netdev user,id=vmnic,hostname=qemu -device virtio-net-device,netdev=vmnic" NET_TAP_ARGS=" -netdev tap,id=vmnic -device virtio-net-device,netdev=vmnic"