forked from Imagelibrary/seL4
RISCV: Remove hartid and DTB parsing from the boot code.
This commit is contained in:
@@ -11,7 +11,5 @@ manual/figs/*
|
||||
*parsetab.py
|
||||
manual/*
|
||||
CHANGES
|
||||
src/plat/spike/machine/fdt.c
|
||||
include/plat/spike/plat/machine/fdt.h
|
||||
include/arch/riscv/arch/sbi.h
|
||||
include/arch/riscv/arch/encoding.h
|
||||
|
||||
@@ -28,9 +28,7 @@ void init_kernel(
|
||||
paddr_t ui_p_reg_start,
|
||||
paddr_t ui_p_reg_end,
|
||||
sword_t pv_offset,
|
||||
vptr_t v_entry,
|
||||
word_t hartid,
|
||||
paddr_t dtb_output
|
||||
vptr_t v_entry
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/* Copyright (c) 2010-2017, The Regents of the University of California
|
||||
* (Regents). All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Regents nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
* SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
* OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
* HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
/* This file is copied from RISC-V tools. It's modified to work with seL4 */
|
||||
|
||||
#ifndef FDT_H
|
||||
#define FDT_H
|
||||
|
||||
void parseFDT(void *fdt);
|
||||
uint32_t fdt_size(void *fdt);
|
||||
|
||||
#endif
|
||||
@@ -34,15 +34,10 @@ _start:
|
||||
addi gp, gp, %pcrel_lo(1b)
|
||||
.option pop
|
||||
|
||||
/* hartid is in a4 */
|
||||
li sp, BIT(CONFIG_KERNEL_STACK_BITS)
|
||||
mul sp, sp, a4
|
||||
la x1, (kernel_stack_alloc + (BIT(CONFIG_KERNEL_STACK_BITS)))
|
||||
add sp, sp, x1
|
||||
la sp, (kernel_stack_alloc + BIT(CONFIG_KERNEL_STACK_BITS))
|
||||
|
||||
csrrw x0, sscratch, a4 /* zero sscratch for the init task */
|
||||
csrw sscratch, x0 /* zero sscratch for the init task */
|
||||
|
||||
/* la sp, (kernel_stack_alloc + BIT(CONFIG_KERNEL_STACK_BITS)) */
|
||||
jal init_kernel
|
||||
|
||||
la ra, restore_user_context
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include <arch/benchmark.h>
|
||||
#include <linker.h>
|
||||
#include <plat/machine/hardware.h>
|
||||
#include <plat/machine/fdt.h>
|
||||
#include <machine.h>
|
||||
|
||||
/* pointer to the end of boot code/data in kernel image */
|
||||
@@ -120,22 +119,12 @@ insert_region_excluded(region_t mem_reg, region_t reserved_reg)
|
||||
}
|
||||
|
||||
BOOT_CODE static void
|
||||
init_freemem(region_t ui_reg, region_t dtb_reg)
|
||||
init_freemem(region_t ui_reg)
|
||||
{
|
||||
unsigned int i;
|
||||
bool_t result UNUSED;
|
||||
region_t cur_reg;
|
||||
region_t res_reg[] = {
|
||||
{
|
||||
// We ignore all physical memory before the dtb as the current riscv-pk (proxy kernel)
|
||||
// that we use for loading is broken and provides an incorrect memory map where
|
||||
// it claims that the memory that is used to provide the m-mode services are
|
||||
// free physical memory. As there is no interface to determine what the memory
|
||||
// reserved for this is we simply hope it placed the dtb after itself and exclude
|
||||
// all memory up until then.
|
||||
.start = 0,
|
||||
.end = dtb_reg.end
|
||||
},
|
||||
{
|
||||
// This looks a bit awkward as our symbols are a reference in the kernel image window, but
|
||||
// we want to do all allocations in terms of the main kernel window, so we do some translation
|
||||
@@ -155,10 +144,8 @@ init_freemem(region_t ui_reg, region_t dtb_reg)
|
||||
/* Force ordering and exclusivity of reserved regions. */
|
||||
assert(res_reg[0].start < res_reg[0].end);
|
||||
assert(res_reg[1].start < res_reg[1].end);
|
||||
assert(res_reg[2].start < res_reg[2].end);
|
||||
|
||||
assert(res_reg[0].end <= res_reg[1].start);
|
||||
assert(res_reg[1].end <= res_reg[2].start);
|
||||
|
||||
for (i = 0; i < get_num_avail_p_regs(); i++) {
|
||||
cur_reg = paddr_to_pptr_reg(get_avail_p_reg(i));
|
||||
@@ -174,7 +161,6 @@ init_freemem(region_t ui_reg, region_t dtb_reg)
|
||||
|
||||
cur_reg = insert_region_excluded(cur_reg, res_reg[0]);
|
||||
cur_reg = insert_region_excluded(cur_reg, res_reg[1]);
|
||||
cur_reg = insert_region_excluded(cur_reg, res_reg[2]);
|
||||
|
||||
if (cur_reg.start != cur_reg.end) {
|
||||
result = insert_region(cur_reg);
|
||||
@@ -213,9 +199,8 @@ init_cpu(void)
|
||||
/* This and only this function initialises the platform. It does NOT initialise any kernel state. */
|
||||
|
||||
BOOT_CODE static void
|
||||
init_plat(region_t dtb)
|
||||
init_plat(void)
|
||||
{
|
||||
parseFDT((void*)dtb.start);
|
||||
initIRQController();
|
||||
initTimer();
|
||||
}
|
||||
@@ -226,8 +211,6 @@ static BOOT_CODE bool_t
|
||||
try_init_kernel(
|
||||
paddr_t ui_p_reg_start,
|
||||
paddr_t ui_p_reg_end,
|
||||
paddr_t dtb_p_reg_start,
|
||||
paddr_t dtb_p_reg_end,
|
||||
uint32_t pv_offset,
|
||||
vptr_t v_entry
|
||||
)
|
||||
@@ -243,9 +226,6 @@ try_init_kernel(
|
||||
region_t ui_reg = paddr_to_pptr_reg((p_region_t) {
|
||||
ui_p_reg_start, ui_p_reg_end
|
||||
});
|
||||
region_t dtb_reg = paddr_to_pptr_reg((p_region_t) {
|
||||
dtb_p_reg_start, dtb_p_reg_end
|
||||
});
|
||||
pptr_t bi_frame_pptr;
|
||||
vptr_t bi_frame_vptr;
|
||||
vptr_t ipcbuf_vptr;
|
||||
@@ -270,10 +250,10 @@ try_init_kernel(
|
||||
init_cpu();
|
||||
|
||||
/* initialize the platform */
|
||||
init_plat(dtb_reg);
|
||||
init_plat();
|
||||
|
||||
/* make the free memory available to alloc_region() */
|
||||
init_freemem(ui_reg, dtb_reg);
|
||||
init_freemem(ui_reg);
|
||||
|
||||
/* create the root cnode */
|
||||
root_cnode_cap = create_root_cnode();
|
||||
@@ -386,20 +366,13 @@ init_kernel(
|
||||
paddr_t ui_p_reg_start,
|
||||
paddr_t ui_p_reg_end,
|
||||
sword_t pv_offset,
|
||||
vptr_t v_entry,
|
||||
word_t hartid,
|
||||
paddr_t dtb_output_p
|
||||
vptr_t v_entry
|
||||
)
|
||||
{
|
||||
pptr_t dtb_output = (pptr_t)paddr_to_pptr(dtb_output_p);
|
||||
|
||||
bool_t result = try_init_kernel(ui_p_reg_start,
|
||||
ui_p_reg_end,
|
||||
dtb_output_p,
|
||||
dtb_output_p + fdt_size((void*)dtb_output),
|
||||
pv_offset,
|
||||
v_entry
|
||||
);
|
||||
v_entry);
|
||||
|
||||
if (!result) {
|
||||
fail ("Kernel init failed for some reason :(");
|
||||
|
||||
@@ -38,6 +38,5 @@ include(src/plat/spike/instance/freedom/config.cmake)
|
||||
add_sources(
|
||||
DEP "KernelPlatformSpike"
|
||||
CFILES
|
||||
src/plat/spike/machine/fdt.c
|
||||
src/plat/spike/machine/hardware.c
|
||||
)
|
||||
|
||||
@@ -1,223 +0,0 @@
|
||||
/* Copyright (c) 2010-2017, The Regents of the University of California
|
||||
* (Regents). All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Regents nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
* SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
* OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
* HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
/* This file is copied from RISC-V tools. It's modified to work with seL4 */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <plat/machine/fdt.h>
|
||||
#include <config.h>
|
||||
#include <util.h>
|
||||
|
||||
#define FDT_MAGIC 0xd00dfeed
|
||||
#define FDT_VERSION 17
|
||||
|
||||
#define FDT_BEGIN_NODE 1
|
||||
#define FDT_END_NODE 2
|
||||
#define FDT_PROP 3
|
||||
#define FDT_NOP 4
|
||||
#define FDT_END 9
|
||||
|
||||
struct fdt_header {
|
||||
uint32_t magic;
|
||||
uint32_t totalsize;
|
||||
uint32_t off_dt_struct;
|
||||
uint32_t off_dt_strings;
|
||||
uint32_t off_mem_rsvmap;
|
||||
uint32_t version;
|
||||
uint32_t last_comp_version; /* <= 17 */
|
||||
uint32_t boot_cpuid_phys;
|
||||
uint32_t size_dt_strings;
|
||||
uint32_t size_dt_struct;
|
||||
};
|
||||
|
||||
struct fdt_scan_node {
|
||||
const struct fdt_scan_node *parent;
|
||||
const char *name;
|
||||
int address_cells;
|
||||
int size_cells;
|
||||
};
|
||||
|
||||
struct fdt_scan_prop {
|
||||
const struct fdt_scan_node *node;
|
||||
const char *name;
|
||||
uint32_t *value;
|
||||
int len; // in bytes of value
|
||||
};
|
||||
|
||||
/* workaround because string literals are not supported by the C parser */
|
||||
const char fdt_address_cells[] = {'#', 'a', 'd', 'd', 'r', 'e', 's', 's', '-', 'c', 'e', 'l', 'l', 's', 0};
|
||||
const char fdt_size_cells[] = {'#', 's', 'i', 'z', 'e', '-', 'c', 'e', 'l', 'l', 's', 0};
|
||||
const char fdt_reg[] = {'r', 'e', 'g', 0};
|
||||
const char fdt_device_type[] = {'d', 'e', 'v', 'i', 'c', 'e', '_', 't', 'y', 'p', 'e', 0};
|
||||
const char fdt_memory[] = {'m', 'e', 'm', 'o', 'r', 'y', 0};
|
||||
|
||||
static inline uint32_t bswap(uint32_t x)
|
||||
{
|
||||
uint32_t y = (x & 0x00FF00FF) << 8 | (x & 0xFF00FF00) >> 8;
|
||||
uint32_t z = (y & 0x0000FFFF) << 16 | (y & 0xFFFF0000) >> 16;
|
||||
return z;
|
||||
}
|
||||
|
||||
struct scan_state {
|
||||
int found_memory;
|
||||
const uint32_t *reg_value;
|
||||
int reg_len;
|
||||
};
|
||||
|
||||
static const uint32_t *fdt_get_address(const struct fdt_scan_node *node, const uint32_t *value, uint64_t *result)
|
||||
{
|
||||
*result = 0;
|
||||
for (int cells = node->address_cells; cells > 0; cells--) {
|
||||
*result = (*result << 32) + bswap(*value);
|
||||
value++;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static const uint32_t *fdt_get_size(const struct fdt_scan_node *node, const uint32_t *value, uint64_t *result)
|
||||
{
|
||||
*result = 0;
|
||||
for (int cells = node->size_cells; cells > 0; cells--) {
|
||||
*result = (*result << 32) + bswap(*value);
|
||||
value++;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static uint32_t *fdt_scan_helper(
|
||||
uint32_t *lex,
|
||||
const char *strings,
|
||||
struct fdt_scan_node *node,
|
||||
struct scan_state *state)
|
||||
{
|
||||
struct fdt_scan_node child;
|
||||
struct fdt_scan_prop prop;
|
||||
int UNUSED last = 0;
|
||||
|
||||
child.parent = node;
|
||||
// these are the default cell counts, as per the FDT spec
|
||||
child.address_cells = 2;
|
||||
child.size_cells = 1;
|
||||
prop.node = node;
|
||||
|
||||
while (1) {
|
||||
switch (bswap(lex[0])) {
|
||||
case FDT_NOP: {
|
||||
lex += 1;
|
||||
break;
|
||||
}
|
||||
case FDT_PROP: {
|
||||
assert (!last);
|
||||
prop.name = strings + bswap(lex[2]);
|
||||
prop.len = bswap(lex[1]);
|
||||
prop.value = lex + 3;
|
||||
if (node && !strncmp(prop.name, fdt_address_cells, 14)) {
|
||||
node->address_cells = bswap(lex[3]);
|
||||
}
|
||||
if (node && !strncmp(prop.name, fdt_size_cells, 11)) {
|
||||
node->size_cells = bswap(lex[3]);
|
||||
}
|
||||
lex += 3 + (prop.len + 3) / 4;
|
||||
if (state->found_memory && strncmp(prop.name, fdt_reg, 3) == 0) {
|
||||
state->reg_value = prop.value;
|
||||
state->reg_len = prop.len;
|
||||
}
|
||||
if (strncmp(prop.name, fdt_device_type, 11) == 0 && strncmp((const char*)prop.value, fdt_memory, 6) == 0) {
|
||||
state->found_memory = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FDT_BEGIN_NODE: {
|
||||
uint32_t *lex_next;
|
||||
last = 1;
|
||||
child.name = (const char *)(lex + 1);
|
||||
lex_next = fdt_scan_helper(
|
||||
lex + 2 + strnlen(child.name, 1024) / 4,
|
||||
strings, &child, state);
|
||||
lex = lex_next;
|
||||
break;
|
||||
}
|
||||
case FDT_END_NODE: {
|
||||
if (state->found_memory) {
|
||||
const uint32_t *value = state->reg_value;
|
||||
const uint32_t *end = value + state->reg_len / 4;
|
||||
|
||||
assert (state->reg_value && state->reg_len % 4 == 0);
|
||||
|
||||
while (end - value > 0) {
|
||||
uint64_t base, size;
|
||||
value = fdt_get_address(node->parent, value, &base);
|
||||
value = fdt_get_size (node->parent, value, &size);
|
||||
if (!add_avail_p_reg((p_region_t) {
|
||||
base, base + size
|
||||
})) {
|
||||
printf("Failed to add physical memory region %llu-%llu\n", (unsigned long long)base, (unsigned long long)(base + size));
|
||||
}
|
||||
}
|
||||
state->found_memory = 0;
|
||||
}
|
||||
return lex + 1;
|
||||
}
|
||||
default: { // FDT_END
|
||||
return lex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void parseFDT(void *fdt)
|
||||
{
|
||||
struct fdt_header *header = (struct fdt_header *)fdt;
|
||||
|
||||
// Only process FDT that we understand
|
||||
if (bswap(header->magic) != FDT_MAGIC ||
|
||||
bswap(header->last_comp_version) > FDT_VERSION) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *strings = (const char *)((word_t)fdt + bswap(header->off_dt_strings));
|
||||
uint32_t *lex = (uint32_t *)((word_t)fdt + bswap(header->off_dt_struct));
|
||||
|
||||
struct scan_state state;
|
||||
state.found_memory = 0;
|
||||
|
||||
fdt_scan_helper(lex, strings, 0, &state);
|
||||
}
|
||||
|
||||
uint32_t fdt_size(void *fdt)
|
||||
{
|
||||
struct fdt_header *header = (struct fdt_header *)fdt;
|
||||
|
||||
// Only process FDT that we understand
|
||||
if (bswap(header->magic) != FDT_MAGIC ||
|
||||
bswap(header->last_comp_version) > FDT_VERSION) {
|
||||
return 0;
|
||||
}
|
||||
return bswap(header->totalsize);
|
||||
}
|
||||
@@ -35,12 +35,20 @@
|
||||
/* Available physical memory regions on platform (RAM minus kernel image). */
|
||||
/* NOTE: Regions are not allowed to be adjacent! */
|
||||
|
||||
static word_t BOOT_DATA num_avail_p_regs = 0;
|
||||
static p_region_t BOOT_DATA avail_p_regs[MAX_AVAIL_P_REGS];
|
||||
static p_region_t BOOT_DATA avail_p_regs[] = {
|
||||
/* The first 2MB are reserved for the SBI in the BBL */
|
||||
#if defined(CONFIG_BUILD_ROCKET_CHIP_ZEDBOARD)
|
||||
{ /*.start = */ 0x0, /* .end = */ 0x10000000}
|
||||
#elif defined(CONFIG_ARCH_RISCV64)
|
||||
{ /*.start = */ 0x80200000, /* .end = */ 0x17FF00000}
|
||||
#elif defined(CONFIG_ARCH_RISCV32)
|
||||
{ /*.start = */ 0x80200000, /* .end = */ 0xFD000000}
|
||||
#endif
|
||||
};
|
||||
|
||||
BOOT_CODE int get_num_avail_p_regs(void)
|
||||
{
|
||||
return num_avail_p_regs;
|
||||
return sizeof(avail_p_regs) / sizeof(p_region_t);
|
||||
}
|
||||
|
||||
BOOT_CODE p_region_t get_avail_p_reg(unsigned int i)
|
||||
@@ -48,16 +56,6 @@ BOOT_CODE p_region_t get_avail_p_reg(unsigned int i)
|
||||
return avail_p_regs[i];
|
||||
}
|
||||
|
||||
BOOT_CODE bool_t add_avail_p_reg(p_region_t reg)
|
||||
{
|
||||
if (num_avail_p_regs == MAX_AVAIL_P_REGS) {
|
||||
return false;
|
||||
}
|
||||
avail_p_regs[num_avail_p_regs] = reg;
|
||||
num_avail_p_regs++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
DONT_TRANSLATE
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user