On Tue, 2021-01-19 at 18:32 +0000, porter.188(a)osu.edu wrote:
Is there any way around that? I can modify BBL to put
the payload at
a lower address than 0x80200000 still properly page aligned, just not
on the mega page size. Also, the elfloader in seL4 relies on this
alignment. I suppose that would need to be rewritten as well.
Or is that this is not possible at all?
A few contributing factors to what is going on here:
1) BBL Will always align an integrated payload to a large page (2MiB on
rv39 and rv48) with the next boundary after the start of BBL itself
2) The elfloader has a hardcoded base to start at 0x80400000, but is
actually loaded at 0x80200000, Due to risc-v being generally position
independent, this doesn't appear to break anything.
3) The generated memory regions for seL4 skip the first mega page
entirely, assuming it is only used for BBL (although the
hardware_gen.py script appears to assume that this size is always 2MiB
when it is actually 4MiB for rv32...)
4) The rv32 seL4 kernel requires that the kernel image falls entirely
within a single 2MiB page, for rv64 it must vall within a single 1GiB
region with the way that the self-mapping is implemented.
5) The kernel defines a KERNEL_ELF_PADDR_BASE and KERNEL_ELF_BASE which
indicate the start of the kernel image in physical and virtual memory
respectively. This is placed 64MiB after the start of physical memory
(and I am unsure as to why such a large region is left).
6) The elfloader requires that its own ELF is aligned to 2MiB (even for
7) The elfloader also requires that it falls within the boundary of a
single page table of large pages (i.e. in a single 4GiB region on 32bit
or 1GiB region on 64bit).
8) BBL enables PMP protection of its own image excluding its own
Given that the BBL itself only use and protect 76KiB at the start of
memory, we could be using everything immediately after that. BBL could
be modified to place its payload immediately after itself in physical
memory and if that payload is position-independent, as elfloader
actually appears to be, that would not be an issue.
The elfloader would still need to be modified such that when it maps
*itself* into virtual memory, it accounts for any misalignment rather
than simply throwing an error. This change would not be all that
The kernel ELF then either needs to be placed after the BBL payload
*OR* the elfloader needs to be architected such that the kernel
location overlapping with its own payload is not an issue. The latter
option also removes an apparent upper limit on the size of the initial
task image of about 64MiB.
Another alternative may be to allow the kernel not to have a statically
assigned physical base address.
Ultimately it seems that you would at least need to modify BBL to
prevent it from putting any payload at the 2MiB boundary. You'd then
need to at least modify the mapping routines in the elfloader to deal
with finer-grained alignment when remapping itself.
To then fit the kernel into that 2MiB region along with the boot loader
and the elf loader, you'd then need to modify the static physical
address the kernel assumes for itself or enable it to be set
dynamically. This former option would be straightforward but would also
limit the size of the user image as the entire elfloader payload needs
to fit below the base kernel ELF address.
I need to run something in less than 2 MB if possible.
If BBL doesn't
do it, then what is the alternative? Do I write my own bootloader?
From what I can see, with minimal patching to BBL, some modifications
to elfloader, and adjusting the constant definition in seL4, you should
be able to fit everything into 2MiB if your initial task is small
enough. The most difficult part there would be the elfloader
modifications. I'm not certain how much of that would be accepted
upstream for any of those repositories however.
Hope all of this helps.