[platform][qemu-virt] read the memory size out of the FDT using libfdt

-Bump the kernel forward by 64K
-Look for the FDT that qemu leaves around in the space just before the kernel
-Pick out the 'memory' node, parse the base/length values and patch the main
    pmm arena before adding it
This commit is contained in:
Travis Geiselbrecht
2015-10-09 17:19:51 -07:00
parent d9753ad81d
commit 31de0ff388
3 changed files with 56 additions and 4 deletions

View File

@@ -36,13 +36,14 @@
#include <platform/gic.h>
#include <platform/interrupts.h>
#include <platform/qemu-virt.h>
#include <libfdt.h>
#include "platform_p.h"
#if WITH_LIB_MINIP
#include <lib/minip.h>
#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)

View File

@@ -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 \

View File

@@ -7,6 +7,7 @@ function HELP {
echo "-t a virtio tap network device"
echo "-d a virtio display"
echo "-6 64bit arm"
echo "-m <memory in MB>"
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"