feat(adapter): higher-half kernel (linked at PHYS_OFFSET, boot trampoline, no low mappings), fix SBI ecall clobbers
This commit is contained in:
@@ -27,16 +27,52 @@ pub fn kernel_ptr() -> *mut kernel::Kernel<platform::RiscVPlatform> {
|
||||
KERNEL.as_ptr()
|
||||
}
|
||||
|
||||
// Firmware enters `_start` at the physical load address with the MMU off,
|
||||
// but the kernel is linked in the upper half. Using only PC-relative code,
|
||||
// the stub turns on `boot_page_table`, which maps RAM twice (at its
|
||||
// physical address, just so the next instruction still exists, and in the
|
||||
// upper half) plus the MMIO window high, then jumps to its own high address.
|
||||
// kmain replaces this table with the real one, which maps nothing low.
|
||||
global_asm!(
|
||||
r#"
|
||||
.section .text.entry
|
||||
.globl _start
|
||||
_start:
|
||||
la sp, _stack_top
|
||||
lla t0, boot_page_table
|
||||
srli t0, t0, 12
|
||||
li t1, 8 << 60
|
||||
or t0, t0, t1
|
||||
csrw satp, t0
|
||||
sfence.vma
|
||||
ld t0, start_high_address
|
||||
jr t0
|
||||
start_high:
|
||||
lla sp, _stack_top
|
||||
call kmain
|
||||
spin:
|
||||
wfi
|
||||
j spin
|
||||
|
||||
.pushsection .rodata
|
||||
.balign 8
|
||||
start_high_address:
|
||||
.quad start_high
|
||||
.popsection
|
||||
|
||||
# Sv39 root of 1 GiB leaves; an entry is (PA >> 12) << 10 | flags, with
|
||||
# flags V|R|W|A|D = 0xc7, plus X = 0xcf.
|
||||
.pushsection .data
|
||||
.balign 4096
|
||||
boot_page_table:
|
||||
.quad 0
|
||||
.quad 0
|
||||
.quad 0x200000cf # [2] 0x8000_0000 -> RAM, for the jump only
|
||||
.fill 253, 8, 0
|
||||
.quad 0x000000c7 # [256] PHYS_OFFSET + 0 -> MMIO
|
||||
.quad 0
|
||||
.quad 0x200000cf # [258] PHYS_OFFSET + 0x8000_0000 -> RAM
|
||||
.fill 253, 8, 0
|
||||
.popsection
|
||||
"#
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user