Files
lk/platform/qemu-virt-riscv/platform.c
Travis Geiselbrecht 9c71a0ec57 [platform][qemu-riscv] Fixup qemu-riscv target
-Fix plic driver to handle machine vs supervisor mode
-Add switch to scripts/do-qemuriscv to run in supervisor mode (with OpenSBI)
-Use the FDT to detect the number of cpus and size of memory
2020-01-19 14:48:25 -08:00

95 lines
2.7 KiB
C

/*
* Copyright (c) 2018 Travis Geiselbrecht
*
* Use of this source code is governed by a MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT
*/
#include <lk/reg.h>
#include <lk/trace.h>
#include <kernel/thread.h>
#include <kernel/novm.h>
#include <platform.h>
#include <platform/interrupts.h>
#include <platform/debug.h>
#include <platform/timer.h>
#include <platform/virt.h>
#include <sys/types.h>
#include <libfdt.h>
#include "platform_p.h"
#define LOCAL_TRACE 1
extern ulong lk_boot_args[4];
static int cpu_count = 0;
void platform_early_init(void) {
plic_early_init();
LTRACEF("starting FDT scan\n");
/* look for a flattened device tree in the second arg passed to us */
bool found_mem = false;
const void *fdt = (void *)lk_boot_args[1];
int err = fdt_check_header(fdt);
if (err >= 0) {
/* walk the nodes */
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;
LTRACEF_LEVEL(2, "name '%s', depth %d\n", name, depth);
/* look for the 'memory@*' property */
if (!found_mem && strncmp(name, "memory@", 7) == 0 && depth == 1) {
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(*(const uint64_t *)prop_ptr);
uint64_t len = fdt64_to_cpu(*((const uint64_t *)prop_ptr + 1));
/* add another novm arena */
printf("FDT: found memory arena, base %#llx size %#llx\n", base, len);
novm_add_arena("fdt", base, len);
found_mem = true; // stop searching after the first one
}
}
/* look for a cpu leaf and count the number of cpus */
if (strncmp(name, "cpu@", 4) == 0 && depth == 2) {
int lenp;
const void *prop_ptr = fdt_getprop(fdt, offset, "reg", &lenp);
if (prop_ptr && lenp == 0x4) {
uint32_t id = fdt32_to_cpu(*(const uint32_t *)prop_ptr);
printf("FDT: found cpu id %u\n", id);
cpu_count++;
}
}
}
}
if (cpu_count > 0) {
riscv_set_secondary_count(cpu_count - 1);
}
LTRACEF("done scanning FDT\n");
}
void platform_init(void) {
plic_init();
uart_init();
}