.extern main .extern CONSOLE_STRICT_FLUSH .section .text.start .global _start .type _start, STT_FUNC _start: # Have harts other than 0 spin until hart0 wakes them up. As a side # effect, load every hart's thread pointer register with MHARTID. csrr tp, mhartid bnez tp, wait_for_hart0 # Set up console_strict_flush. la t0, console_strict_flush la t1, CONSOLE_STRICT_FLUSH sd t0, (t1) # Set up hart0's stack. la sp, hart0_initial_stack_top # Put the address of the DeviceTree into the first argument position # for hart0_boot. c.mv a0, a1 # The rest of this function is to get out of machine mode and into # supervisor mode by fictitiously returning from a trap. # First, set MSTATUS.MPP to Supervisor, so that when we execute mret, # the privilege level will lower to Supervisor. csrr t0, mstatus li t1, ~(0b11 << 11) and t0, t0, t1 li t1, (0b01 << 11) or t0, t0, t1 csrw mstatus, t0 # Next, set MEPC to the address of hart0_boot, so that when we execute # mret, execution will continue there. la t0, hart0_boot csrw mepc, t0 # Delegate all exceptions and interrupts to the Supervisor level. li t0, 0xffff csrw medeleg, t0 csrw mideleg, t0 # Set SATP.MODE to Bare, and clear the rest of the bits. This disables # paging in Supervisor mode. csrw satp, zero # Set PMP0CFG.{R, W, X} to 1, PMP0CFG.A to TOR, and PMP0ADDR to the # maximum value. This allows supervisor mode to access all of physical # memory. li t0, (0b01 << 3) | 0b111 csrw pmpcfg0, t0 li t0, -1 csrw pmpaddr0, t0 # Jump to supervisor mode. mret .size _start, . - _start .section .text .type wait_for_hart0, STT_FUNC wait_for_hart0: # TODO wfi j wait_for_hart0 .size wait_for_hart0, . - wait_for_hart0 .section .text .type console_strict_flush, STT_FUNC console_strict_flush: li t0, 0x10000000 1: c.beqz a1, 2f lb t1, (a0) sb t1, (t0) addi a0, a0, 1 addi a1, a1, -1 j 1b 2: ret .size console_strict_flush, . - console_strict_flush