[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:
@@ -36,13 +36,14 @@
|
|||||||
#include <platform/gic.h>
|
#include <platform/gic.h>
|
||||||
#include <platform/interrupts.h>
|
#include <platform/interrupts.h>
|
||||||
#include <platform/qemu-virt.h>
|
#include <platform/qemu-virt.h>
|
||||||
|
#include <libfdt.h>
|
||||||
#include "platform_p.h"
|
#include "platform_p.h"
|
||||||
|
|
||||||
#if WITH_LIB_MINIP
|
#if WITH_LIB_MINIP
|
||||||
#include <lib/minip.h>
|
#include <lib/minip.h>
|
||||||
#endif
|
#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 */
|
/* initial memory mappings. parsed by start.S */
|
||||||
struct mmu_initial_mapping mmu_initial_mappings[] = {
|
struct mmu_initial_mapping mmu_initial_mappings[] = {
|
||||||
@@ -71,7 +72,7 @@ struct mmu_initial_mapping mmu_initial_mappings[] = {
|
|||||||
static pmm_arena_t arena = {
|
static pmm_arena_t arena = {
|
||||||
.name = "ram",
|
.name = "ram",
|
||||||
.base = MEMORY_BASE_PHYS,
|
.base = MEMORY_BASE_PHYS,
|
||||||
.size = MEMORY_SIZE,
|
.size = DEFAULT_MEMORY_SIZE,
|
||||||
.flags = PMM_ARENA_FLAG_KMAP,
|
.flags = PMM_ARENA_FLAG_KMAP,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -84,8 +85,53 @@ void platform_early_init(void)
|
|||||||
|
|
||||||
uart_init_early();
|
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 */
|
/* add the main memory arena */
|
||||||
pmm_add_arena(&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)
|
void platform_init(void)
|
||||||
|
|||||||
@@ -23,9 +23,11 @@ MODULE_SRCS += \
|
|||||||
|
|
||||||
MEMBASE := 0x40000000
|
MEMBASE := 0x40000000
|
||||||
MEMSIZE ?= 0x08000000 # 512MB
|
MEMSIZE ?= 0x08000000 # 512MB
|
||||||
|
KERNEL_LOAD_OFFSET := 0x10000 # 64k
|
||||||
|
|
||||||
MODULE_DEPS += \
|
MODULE_DEPS += \
|
||||||
lib/cbuf \
|
lib/cbuf \
|
||||||
|
lib/fdt \
|
||||||
dev/interrupt/arm_gic \
|
dev/interrupt/arm_gic \
|
||||||
dev/timer/arm_generic \
|
dev/timer/arm_generic \
|
||||||
dev/virtio/block \
|
dev/virtio/block \
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ function HELP {
|
|||||||
echo "-t a virtio tap network device"
|
echo "-t a virtio tap network device"
|
||||||
echo "-d a virtio display"
|
echo "-d a virtio display"
|
||||||
echo "-6 64bit arm"
|
echo "-6 64bit arm"
|
||||||
|
echo "-m <memory in MB>"
|
||||||
echo "-h for help"
|
echo "-h for help"
|
||||||
echo "all arguments after -- are passed to qemu directly"
|
echo "all arguments after -- are passed to qemu directly"
|
||||||
exit 1
|
exit 1
|
||||||
@@ -17,15 +18,18 @@ DO_NET_TAP=0
|
|||||||
DO_BLOCK=0
|
DO_BLOCK=0
|
||||||
DO_64BIT=0
|
DO_64BIT=0
|
||||||
DO_DISPLAY=0
|
DO_DISPLAY=0
|
||||||
|
MEMSIZE=512
|
||||||
SUDO=""
|
SUDO=""
|
||||||
|
|
||||||
while getopts bdhnt6 FLAG; do
|
while getopts bdhm:nt6 FLAG; do
|
||||||
case $FLAG in
|
case $FLAG in
|
||||||
b) DO_BLOCK=1;;
|
b) DO_BLOCK=1;;
|
||||||
d) DO_DISPLAY=1;;
|
d) DO_DISPLAY=1;;
|
||||||
n) DO_NET=1;;
|
n) DO_NET=1;;
|
||||||
t) DO_NET_TAP=1;;
|
t) DO_NET_TAP=1;;
|
||||||
6) DO_64BIT=1;;
|
6) DO_64BIT=1;;
|
||||||
|
6) DO_MEM=1;;
|
||||||
|
m) MEMSIZE=$OPTARG;;
|
||||||
h) HELP;;
|
h) HELP;;
|
||||||
\?)
|
\?)
|
||||||
echo unrecognized option
|
echo unrecognized option
|
||||||
@@ -43,7 +47,7 @@ else
|
|||||||
PROJECT="qemu-virt-a15-test"
|
PROJECT="qemu-virt-a15-test"
|
||||||
fi
|
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"
|
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_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"
|
NET_TAP_ARGS=" -netdev tap,id=vmnic -device virtio-net-device,netdev=vmnic"
|
||||||
|
|||||||
Reference in New Issue
Block a user