Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
b5917a7
loader(aarch64): pass PTs to enable MMU assembler
midnightveil May 6, 2026
75b307c
loader(aarch64): dynamically allocate PTs
midnightveil May 18, 2026
e8ee048
loader(riscv64): apply the aarch64 treatment
midnightveil May 18, 2026
3aba572
[WIP] ram
midnightveil May 22, 2026
5417be0
loader: gc-sections
midnightveil Jul 28, 2026
0557f16
move the stuff to runtime (but it breaks it!! need fix!!)
midnightveil Jul 29, 2026
30cc89e
fixes
midnightveil Jul 29, 2026
aaaa69a
back to old style
midnightveil Jul 29, 2026
807aa03
FIX
midnightveil Jul 29, 2026
8a87d9d
minor makefile touchups
midnightveil Jul 31, 2026
0890270
tests + return struct
midnightveil Aug 18, 2026
62651ed
work again for qemu
midnightveil Aug 18, 2026
2ccf7c2
make it easier
midnightveil Aug 18, 2026
5577520
tests part of build
midnightveil Aug 18, 2026
ac001d0
clippy
midnightveil Aug 18, 2026
61604b1
clippy
midnightveil Aug 18, 2026
9716d32
rustfmt + cleanup make
midnightveil Aug 18, 2026
70fea7e
don't create large temporaries on the stack
midnightveil Aug 18, 2026
1fbf199
fix stack overflow
midnightveil Aug 18, 2026
9bb64fb
fix style
midnightveil Aug 18, 2026
9a1f22b
fix warnings
midnightveil Aug 18, 2026
396232e
add safety comment
midnightveil Aug 18, 2026
bae0a5e
test walker
midnightveil Aug 18, 2026
2a0a57b
almost working clean
midnightveil Aug 20, 2026
0018db9
truly works impl
midnightveil Aug 20, 2026
0799991
cleanup
midnightveil Aug 20, 2026
871db3a
reomve prints
midnightveil Aug 20, 2026
cc6be77
more helper fns
midnightveil Aug 20, 2026
a0bbb47
attempt (badly) to make risv64 also work
midnightveil Aug 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,17 @@ jobs:
- name: Run Clippy
# Make sure CI fails on all warnings, including Clippy lints
run: nix develop --ignore-environment -c bash -c "cd tool/microkit && cargo-clippy --all-targets --all-features -- -D warnings -Wclippy::get_unwrap"
- name: Run Clippy (loader)
run: nix develop --ignore-environment -c bash -c 'make -C loader clippy CLIPPY_FLAGS="-D warnings -Wclippy::get_unwrap" BUILD_DIR=$(mktemp -d) RUST_ONLY=True'

rustfmt_check:
runs-on: [self-hosted, macos, ARM64]
steps:
- uses: actions/checkout@v4
- name: Run rustfmt
run: nix develop --ignore-environment -c bash -c "cd tool/microkit && cargo-fmt --check"
- name: Run rustfmt (loader)
run: nix develop --ignore-environment -c bash -c 'make -C loader rustfmt-check BUILD_DIR=$(mktemp -d) RUST_ONLY=True'

code:
name: Freeze Code
Expand Down
22 changes: 22 additions & 0 deletions build_sdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,26 @@ def build_sel4(
json_dst.chmod(0o744)


def test_loader(build_dir: Path) -> None:
build_dir = build_dir / "loader"
build_dir.mkdir(exist_ok=True, parents=True)

make_args = f"BUILD_DIR={build_dir.absolute()} RUST_ONLY=True"

r = system(
f"make -C loader tests {make_args}"
)
if r != 0:
raise Exception(f"Tests failed: loader")

# We don't pass CLIPPYARGS, so this is warning-only
r = system(
f"make -C loader clippy {make_args}"
)
if r != 0:
raise Exception(f"Clippy failed: loader")


def build_elf_component(
component_name: str,
sdk_dir: Path,
Expand Down Expand Up @@ -1094,6 +1114,8 @@ def main() -> None:

if not args.skip_run_time:
build_dir = Path("build")
test_loader(build_dir)

for (board, configs) in build_goals:
for config in configs:
if not args.skip_sel4:
Expand Down
2 changes: 1 addition & 1 deletion example/hello/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ ifeq ($(ARCH),aarch64)
TARGET_TRIPLE := aarch64-none-elf
CFLAGS_ARCH := -mstrict-align
else ifeq ($(ARCH),riscv64)
TARGET_TRIPLE := riscv64-unknown-elf
TARGET_TRIPLE := riscv64-none-elf
CFLAGS_ARCH := -march=rv64imafdc_zicsr_zifencei -mabi=lp64d
else ifeq ($(ARCH),x86_64)
TARGET_TRIPLE := x86_64-linux-gnu
Expand Down
79 changes: 74 additions & 5 deletions loader/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@
#
# SPDX-License-Identifier: BSD-2-Clause
#

ifneq ($(strip $(RUST_ONLY)),)
ARCH := dummy
BOARD := dummy
LINK_ADDRESS := dummy
TARGET_TRIPLE := dummy
SEL4_SDK := dummy
endif

ifeq ($(strip $(BUILD_DIR)),)
$(error BUILD_DIR must be specified)
endif
Expand Down Expand Up @@ -35,34 +44,46 @@ else
LD = $(TARGET_TRIPLE)-ld
endif

RUSTC := rustc
CLIPPY := clippy-driver
RUSTFMT := rustfmt

ifeq ($(ARCH),aarch64)
CFLAGS_AARCH64 := -mcpu=$(GCC_CPU) -mgeneral-regs-only -mstrict-align -mno-outline-atomics
CFLAGS_ARCH := $(CFLAGS_AARCH64) -DARCH_aarch64
ASM_FLAGS_ARCH := -mcpu=$(GCC_CPU)
ARCH_DIR := aarch64
RUST_TARGET_TRIPLE := aarch64-unknown-none
else ifeq ($(ARCH),riscv64)
CFLAGS_RISCV64 := -mcmodel=medany -march=rv64imac_zicsr_zifencei -mabi=lp64
CFLAGS_RISCV64 := -mcmodel=medany -march=rv64gc -mabi=lp64d
CFLAGS_ARCH := $(CFLAGS_RISCV64) -DARCH_riscv64
ASM_FLAGS_ARCH := -march=rv64imac_zicsr_zifencei -mabi=lp64
ASM_FLAGS_ARCH := -march=rv64gc -mabi=lp64d
RUST_TARGET_TRIPLE := riscv64gc-unknown-none-elf
ARCH_DIR := riscv
endif

CFLAGS := -std=gnu11 -g -O3 -nostdlib -ffreestanding \
-MP -MD $(CFLAGS_ARCH) -DBOARD_$(BOARD) -I$(SEL4_SDK)/include \
-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations \
-Wundef -Wno-nonnull -Wnested-externs
-Wundef -Wno-nonnull -Wnested-externs -ffunction-sections -fdata-sections

ASM_FLAGS := $(ASM_FLAGS_ARCH) -g -MP -MD -I$(SEL4_SDK)/include

RUST_EDITION := 2024
RUSTFLAGS := --edition $(RUST_EDITION) -g -C opt-level=2
CLIPPY_FLAGS ?=

PROGS := loader.elf
OBJECTS := loader.o crt0.o uart.o cutil.o
OBJECTS := loader.o crt0.o uart.o cutil.o libpage_tables.a

ifeq ($(ARCH),aarch64)
OBJECTS += util64.o el.o exceptions.o init.o mmu.o cpus.o
else ifeq ($(ARCH),riscv64)
OBJECTS += exceptions.o init.o mmu.o cpus.o sbi.o
endif

RUST_CRATES := page_tables

LINKSCRIPT_INPUT := $(ARCH).ld
LINKSCRIPT := $(BUILD_DIR)/link.ld

Expand All @@ -80,6 +101,18 @@ $(BUILD_DIR)/%.o : src/$(ARCH_DIR)/%.c
$(BUILD_DIR)/%.o : src/%.c
$(CC) -c $(CFLAGS) $< -o $@

# Note: having multiple libs with staticlib will give duplicate linker symbol
# issues. Use "--crate-type rlib" instead, but then we need to link a single
# copy of the rust corelibs. For now this is fine.
$(BUILD_DIR)/lib%.a : src/%.rs
$(RUSTC) $(RUSTFLAGS) \
--emit dep-info,metadata,link \
--out-dir $(BUILD_DIR) -L dependency=$(BUILD_DIR) \
--target $(RUST_TARGET_TRIPLE) \
--crate-type staticlib \
--crate-name $(patsubst lib%.a,%,$(notdir $@)) \
$<

-include $(BUILD_DIR)/*.d

OBJPROG = $(addprefix $(BUILD_DIR)/, $(PROGS))
Expand All @@ -89,5 +122,41 @@ all: $(OBJPROG)
$(LINKSCRIPT): $(LINKSCRIPT_INPUT)
$(CPP) -DLINK_ADDRESS=$(LINK_ADDRESS) $< | grep -v "^#" > $@

LDFLAGS := -T$(LINKSCRIPT)

$(OBJPROG): $(addprefix $(BUILD_DIR)/, $(OBJECTS)) $(LINKSCRIPT)
$(LD) -T$(LINKSCRIPT) $(addprefix $(BUILD_DIR)/, $(OBJECTS)) -o $@
$(LD) $(LDFLAGS) --start-group $(addprefix $(BUILD_DIR)/, $(OBJECTS)) --end-group -o $@

rusttest_%: src/%.rs
$(RUSTC) $(RUSTFLAGS) \
--emit dep-info,metadata,link \
--out-dir $(BUILD_DIR) -L dependency=$(BUILD_DIR) \
-Awarnings \
--test \
--crate-name "$@" \
$<

tests: $(addprefix rusttest_, $(RUST_CRATES))
$(BUILD_DIR)/rusttest_page_tables

rustclippy_%: src/%.rs
$(CLIPPY) $(RUSTFLAGS) \
--emit dep-info,metadata,link \
--out-dir $(BUILD_DIR) -L dependency=$(BUILD_DIR) \
$(CLIPPYFLAGS) \
-Cpanic=abort \
--crate-type staticlib \
--crate-name "$@" \
$<

clippy: $(addprefix rustclippy_, $(RUST_CRATES))

rustfmt_%: src/%.rs
$(RUSTFMT) $(RUSTFMT_FLAGS) \
--edition $(RUST_EDITION) \
$<

rustfmt: $(addprefix rustfmt_, $(RUST_CRATES))

rustfmt-check: RUSTFMT_FLAGS += --check
rustfmt-check: rustfmt
25 changes: 21 additions & 4 deletions loader/aarch64.ld
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ PHDRS
all PT_LOAD AT (LINK_ADDRESS);
}


// text PT_LOAD FLAGS(5); /* RX */
// rodata PT_LOAD FLAGS(4); /* RO */
// data PT_LOAD FLAGS(6); /* RW */
// bss PT_LOAD FLAGS(6); /* RW */

SECTIONS
{
. = LINK_ADDRESS;
Expand All @@ -17,23 +23,34 @@ SECTIONS
.text :
{
_text = .;
*(.text.start)
*(.text*)
*(.rodata)

KEEP(*(.text.start))
*(.text .text.*)

_text_end = .;
} :all

.rodata :
{
*(.rodata .rodata.* .rodata..Lanon.*)
} :all

.data :
{
_data = .;
*(.data)
*(.data .data.*)
*(.data.*)

KEEP(*(.data.uart_addr))

_data_end = .;
} :all

.bss :
{
_bss = .;
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
_bss_end = .;
Expand Down
26 changes: 18 additions & 8 deletions loader/riscv64.ld
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,37 @@ SECTIONS
.text :
{
_text = .;
*(.text.start)
*(.text*)
*(.rodata)

KEEP(*(.text.start))
*(.text .text.*)

_text_end = .;
} :all

.rodata :
{
*(.rodata .rodata.* .rodata..Lanon.*)
} :all

.data :
{
_data = .;
*(.data)
*(.data .data.*)
*(.data.*)
__global_pointer$ = . + 0x800;
*(.srodata)
*(.sdata)
_data_end = .;
*(.srodata)
*(.sdata)

KEEP(*(.data.uart_addr))

_data_end = .;
} :all

.bss :
{
_bss = .;
*(.sbss)
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
_bss_end = .;
Expand Down
39 changes: 27 additions & 12 deletions loader/src/aarch64/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,42 @@
*/

#include <stdint.h>
#include <stdbool.h>

#include "el.h"
#include "../arch.h"
#include "../cutil.h"
#include "../uart.h"

void el1_mmu_enable(void);
void el2_mmu_enable(void);
void el1_mmu_enable(uintptr_t ttbr0_el1, uintptr_t ttbr1_el1);
void el2_mmu_enable(uintptr_t ttbr0_el2);

/* Paging structures for kernel mapping */
uint64_t boot_lvl0_upper[1 << 9] ALIGN(1 << 12);
uint64_t boot_lvl1_upper[1 << 9] ALIGN(1 << 12);
uint64_t boot_lvl2_upper[1 << 9] ALIGN(1 << 12);
struct AArch64ReturnValue {
uintptr_t ttbr0_el2;
uintptr_t ttbr0_el1;
uintptr_t ttbr1_el1;
};

/* Paging structures for identity mapping */
uint64_t boot_lvl0_lower[1 << 9] ALIGN(1 << 12);
uint64_t boot_lvl1_lower[1 << 9] ALIGN(1 << 12);
uint64_t boot_lvl2_lower[1 << 9] ALIGN(1 << 12);
struct Region regions[] = {
{ .start = 0x60000000, .top = 0xc0000000 - 1, .arch_attrs.is_ram = true },
{ .start = 0x9000000, .top = 0x9000000 + 0xfff, .arch_attrs.is_ram = false },
};

uint8_t page_table_bytes[PAGE_TABLE_SIZE][MAX_NUM_PAGE_TABLES] ALIGN(PAGE_TABLE_SIZE);

extern struct AArch64ReturnValue aarch64_setup_pagetables(
uint64_t kernel_first_vaddr, uint64_t kernel_first_paddr,
void *regions_ptr, uintptr_t regions_len,
uint8_t page_table_bytes[PAGE_TABLE_SIZE][MAX_NUM_PAGE_TABLES]);

int arch_mmu_enable(int logical_cpu)
{
struct AArch64ReturnValue pt = aarch64_setup_pagetables(
0x8060000000, 0x60000000,
&regions, ARRAY_SIZE(regions),
page_table_bytes
);

int r;
enum el el;
r = ensure_correct_el(logical_cpu);
Expand All @@ -37,9 +52,9 @@ int arch_mmu_enable(int logical_cpu)
LDR_PRINT("INFO", logical_cpu, "enabling MMU\n");
el = current_el();
if (el == EL1) {
el1_mmu_enable();
el1_mmu_enable(pt.ttbr0_el1, pt.ttbr1_el1);
} else if (el == EL2) {
el2_mmu_enable();
el2_mmu_enable(pt.ttbr0_el2);
} else {
LDR_PRINT("ERROR", logical_cpu, "unknown EL for MMU enable\n");
}
Expand Down
Loading
Loading