summaryrefslogtreecommitdiff
path: root/boards/qemu-virt/qemu-virt.s
diff options
context:
space:
mode:
Diffstat (limited to 'boards/qemu-virt/qemu-virt.s')
-rw-r--r--boards/qemu-virt/qemu-virt.s69
1 files changed, 42 insertions, 27 deletions
diff --git a/boards/qemu-virt/qemu-virt.s b/boards/qemu-virt/qemu-virt.s
index 063e67c..b9544be 100644
--- a/boards/qemu-virt/qemu-virt.s
+++ b/boards/qemu-virt/qemu-virt.s
@@ -6,58 +6,73 @@
.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.
+ ## Have harts other than hart0 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.
+ ## Set up console_strict_flush.
la t0, console_strict_flush
la t1, CONSOLE_STRICT_FLUSH
sd t0, (t1)
- # Set up hart0's stack.
+ ## 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.
+ ## 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.
+### Set up trap handling.
- # 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
+ ## Set MENVCFG.STCE, to enable the Sstc extension, which will allow us
+ ## to delegate timer interrupts to Supervisor mode.
+ li t0, 1<<63
+ csrs menvcfg, 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
+ ## Set MCOUNTEREN.{CY, TM, IR} to 1, enabling Supervisor mode accesses
+ ## to the cycle, time, stimecmp, and instret MSRs.
+ li t0, 0b111
+ csrs mcounteren, t0
- # Delegate all exceptions and interrupts to the Supervisor level.
+ ## Set MIE.{SSIE, STIE, SEIE} to 1, enabling software, timer, and
+ ## exception traps in Supervisor mode.
+ li t0, 0b1000100010
+ csrs mie, t0
+
+ ## Delegate all exceptions to Supervisor mode.
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.
+### Go from Machine mode to 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.
+ li t0, 0b11 << 11
+ csrc mstatus, t0
+ li t0, 0b01 << 11
+ csrs 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
+
+ ## 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.
+ ## 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.
+ ## Jump to supervisor mode.
mret
.size _start, . - _start