boot: fail boot if region configuration is invalid

Also make the output more verbose in case of errors, which is
helpful when porting the kernel to new platforms.

Signed-off-by: Axel Heider <axelheider@gmx.de>
This commit is contained in:
Axel Heider 2021-06-04 03:10:02 +02:00 committed by Kent McLeod
parent adbd374370
commit 938c1c9557
5 changed files with 74 additions and 33 deletions

View file

@ -47,9 +47,9 @@ static inline bool_t is_reg_empty(region_t reg)
return reg.start == reg.end;
}
void init_freemem(word_t n_available, const p_region_t *available,
word_t n_reserved, const region_t *reserved,
v_region_t it_v_reg, word_t extra_bi_size_bits);
bool_t init_freemem(word_t n_available, const p_region_t *available,
word_t n_reserved, const region_t *reserved,
v_region_t it_v_reg, word_t extra_bi_size_bits);
bool_t reserve_region(p_region_t reg);
bool_t insert_region(region_t reg);
void write_slot(slot_ptr_t slot_ptr, cap_t cap);

View file

@ -42,8 +42,10 @@ BOOT_BSS static volatile int node_boot_lock;
#define MAX_RESERVED (ARCH_RESERVED + MODE_RESERVED)
BOOT_BSS static region_t reserved[MAX_RESERVED];
BOOT_CODE static void arch_init_freemem(p_region_t ui_p_reg, p_region_t dtb_p_reg, v_region_t it_v_reg,
word_t extra_bi_size_bits)
BOOT_CODE static bool_t arch_init_freemem(p_region_t ui_p_reg,
p_region_t dtb_p_reg,
v_region_t it_v_reg,
word_t extra_bi_size_bits)
{
reserved[0].start = KERNEL_ELF_BASE;
reserved[0].end = (pptr_t)ki_end;
@ -57,8 +59,8 @@ BOOT_CODE static void arch_init_freemem(p_region_t ui_p_reg, p_region_t dtb_p_re
}
if (MODE_RESERVED > 1) {
printf("MODE_RESERVED > 1 unsupported!\n");
halt();
printf("ERROR: MODE_RESERVED > 1 unsupported!\n");
return false;
}
if (ui_p_reg.start < PADDR_TOP) {
@ -86,7 +88,8 @@ BOOT_CODE static void arch_init_freemem(p_region_t ui_p_reg, p_region_t dtb_p_re
index++;
}
init_freemem(get_num_avail_p_regs(), get_avail_p_regs(), index, reserved, it_v_reg, extra_bi_size_bits);
return init_freemem(get_num_avail_p_regs(), get_avail_p_regs(), index,
reserved, it_v_reg, extra_bi_size_bits);
}
@ -380,7 +383,10 @@ static BOOT_CODE bool_t try_init_kernel(
/* initialise the platform */
init_plat();
arch_init_freemem(ui_p_reg, dtb_p_reg, it_v_reg, extra_bi_size_bits);
if (!arch_init_freemem(ui_p_reg, dtb_p_reg, it_v_reg, extra_bi_size_bits)) {
printf("ERROR: free memory management initialization failed\n");
return false;
}
/* create the root cnode */
root_cnode_cap = create_root_cnode();

View file

@ -74,8 +74,9 @@ BOOT_CODE cap_t create_mapped_it_frame_cap(cap_t pd_cap, pptr_t pptr, vptr_t vpt
return cap;
}
BOOT_CODE static void arch_init_freemem(region_t ui_reg, v_region_t ui_v_reg,
region_t dtb_reg, word_t extra_bi_size_bits)
BOOT_CODE static bool_t arch_init_freemem(region_t ui_reg, v_region_t ui_v_reg,
region_t dtb_reg,
word_t extra_bi_size_bits)
{
// 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
@ -94,8 +95,8 @@ BOOT_CODE static void arch_init_freemem(region_t ui_reg, v_region_t ui_v_reg,
res_reg[index].end = ui_reg.end;
index += 1;
init_freemem(get_num_avail_p_regs(), get_avail_p_regs(), index, res_reg, ui_v_reg,
extra_bi_size_bits);
return init_freemem(get_num_avail_p_regs(), get_avail_p_regs(), index,
res_reg, ui_v_reg, extra_bi_size_bits);
}
BOOT_CODE static void init_irqs(cap_t root_cnode_cap)
@ -257,7 +258,10 @@ static BOOT_CODE bool_t try_init_kernel(
init_plat();
/* make the free memory available to alloc_region() */
arch_init_freemem(ui_reg, it_v_reg, dtb_reg, extra_bi_size_bits);
if (!arch_init_freemem(ui_reg, it_v_reg, dtb_reg, extra_bi_size_bits)) {
printf("ERROR: free memory management initialization failed\n");
return false;
}
/* create the root cnode */
root_cnode_cap = create_root_cnode();

View file

@ -85,12 +85,14 @@ BOOT_CODE static bool_t create_untypeds(
return true;
}
BOOT_CODE static void arch_init_freemem(p_region_t ui_p_reg, v_region_t v_reg,
mem_p_regs_t *mem_p_regs, word_t extra_bi_size_bits)
BOOT_CODE static bool_t arch_init_freemem(p_region_t ui_p_reg, v_region_t v_reg,
mem_p_regs_t *mem_p_regs,
word_t extra_bi_size_bits)
{
ui_p_reg.start = 0;
reserved[0] = paddr_to_pptr_reg(ui_p_reg);
init_freemem(mem_p_regs->count, mem_p_regs->list, MAX_RESERVED, reserved, v_reg, extra_bi_size_bits);
return init_freemem(mem_p_regs->count, mem_p_regs->list, MAX_RESERVED,
reserved, v_reg, extra_bi_size_bits);
}
/* This function initialises a node's kernel state. It does NOT initialise the CPU. */
@ -164,7 +166,10 @@ BOOT_CODE bool_t init_sys_state(
}
#endif /* CONFIG_IOMMU */
arch_init_freemem(ui_info.p_reg, it_v_reg, mem_p_regs, extra_bi_size_bits);
if (!arch_init_freemem(ui_info.p_reg, it_v_reg, mem_p_regs, extra_bi_size_bits)) {
printf("ERROR: free memory management initialization failed\n");
return false;
}
/* create the root cnode */
root_cnode_cap = create_root_cnode();

View file

@ -699,29 +699,53 @@ BOOT_BSS static region_t avail_reg[MAX_NUM_FREEMEM_REG];
* Dynamically initialise the available memory on the platform.
* A region represents an area of memory.
*/
BOOT_CODE void init_freemem(word_t n_available, const p_region_t *available,
word_t n_reserved, const region_t *reserved,
v_region_t it_v_reg, word_t extra_bi_size_bits)
BOOT_CODE bool_t init_freemem(word_t n_available, const p_region_t *available,
word_t n_reserved, const region_t *reserved,
v_region_t it_v_reg, word_t extra_bi_size_bits)
{
/* The system configuration is broken if no region is available */
if (0 == n_available) {
printf("ERROR: no memory regions available\n");
return false;
}
/* Force ordering and exclusivity of reserved regions */
for (word_t i = 0; i < n_reserved; i++) {
UNUSED const region_t *r = &reserved[i];
const region_t *r = &reserved[i];
/* Reserved regions must be sane, the size is allowed to be zero */
assert(r->start <= r->end);
if (i > 0) {
/* regions must be ordered and must not overlap */
assert(r->start >= reserved[i - 1].end);
if (r->start > r->end) {
printf("ERROR: reserved region %"SEL4_PRIu_word" has start > end\n", i);
return false;
}
/* regions must be ordered and must not overlap */
if ((i > 0) && (r->start < reserved[i - 1].end)) {
printf("ERROR: reserved region %"SEL4_PRIu_word" in wrong order\n", i);
return false;
}
}
/* Force ordering and exclusivity of available regions */
for (word_t i = 0; i < n_available; i++) {
UNUSED const p_region_t *r = &available[i];
/* Available regions must be sane and have a size greater zero */
assert(r->start < r->end);
if (i > 0) {
/* regions must be ordered and must not overlap */
assert(r->start >= available[i - 1].end);
const p_region_t *r = &available[i];
/* Available regions must be sane */
if (r->start > r->end) {
printf("ERROR: memory region %"SEL4_PRIu_word" has start > end\n", i);
return false;
}
/* Available regions can't be empty */
if (r->start == r->end) {
printf("ERROR: memory region %"SEL4_PRIu_word" empty\n", i);
return false;
}
/* regions must be ordered and must not overlap */
if ((i > 0) && (r->start < available[i - 1].end)) {
printf("ERROR: memory region %"SEL4_PRIu_word" in wrong order\n", i);
return false;
}
}
@ -797,7 +821,7 @@ BOOT_CODE void init_freemem(word_t n_available, const p_region_t *available,
word_t i = MAX_NUM_FREEMEM_REG - 1;
if (!is_reg_empty(ndks_boot.freemem[i])) {
printf("Insufficient MAX_NUM_FREEMEM_REG\n");
halt();
return false;
}
/* skip any empty regions */
for (; is_reg_empty(ndks_boot.freemem[i]) && i >= 0; i--);
@ -821,4 +845,6 @@ BOOT_CODE void init_freemem(word_t n_available, const p_region_t *available,
ndks_boot.freemem[next] = ndks_boot.freemem[i];
}
}
return true;
}