summaryrefslogtreecommitdiff
path: root/boards/qemu-virt/qemu-virt.s
blob: b9544be6546b24896895c28950925e6095ff12e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
.extern main
.extern CONSOLE_STRICT_FLUSH

.section .text.start

.global _start
.type _start, STT_FUNC
_start:
	## 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.
	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

### Set up trap handling.

	## 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

	## 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

	## 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

### 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.
	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