File size: 6,054 Bytes
829b19c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# SPDX-License-Identifier: AGPL-3.0-or-later
# Copyright 2025 Ahmad Ali Parr / SnapKitty οΏ½ https://github.com/SNAPKITTYWEST/phaser-ags
# ═══════════════════════════════════════════════════════════════════
#  PHASER AGS β€” RV32I boot assembly (complete, no stubs)
#
#  Full boot sequence + trap entry/exit with context switch.
#  Supports M-mode operation with per-process kernel stacks.
#  Context switch: trapDispatch returns the frame pointer to
#  restore (may differ from entry if a switch occurred).
# ═══════════════════════════════════════════════════════════════════

    .section .text.boot, "ax"
    .globl _start
    .type  _start, @function

_start:
    # ── M-mode entry: disable all interrupts ──
    csrw    mstatus, zero
    csrw    mie, zero
    csrw    mideleg, zero
    csrw    medeleg, zero

    # ── Install trap vector ──
    la      t0, trap_vector
    csrw    mtvec, t0

    # ── Kernel stack ──
    la      sp, __stack_top

    # ── Global pointer for linker relaxation ──
    .option push
    .option norelax
    la      gp, __global_pointer$
    .option pop

    # ── Zero BSS ──
    la      t0, __bss_start
    la      t1, __bss_end
1:  bgeu    t0, t1, 2f
    sd      zero, 0(t0)
    addi    t0, t0, 8
    j       1b
2:

    # ── Set initial mscratch to kernel stack top ──
    #    (first trap uses this as the context save area)
    csrw    mscratch, sp

    # ── Flush instruction cache ──
    fence.i

    # ── Enter Zig kernel ──
    call    kernelMain

    # ── kernelMain must not return; halt if it does ──
3:  wfi
    j       3b
    .size _start, . - _start

# ═══════════════════════════════════════════════════════════════════
#  TRAP VECTOR β€” Full context save/restore + context switch
#
#  Layout on kernel stack (264 bytes):
#    [0]     prev_ctx   β€” previous mscratch (for nested traps)
#    [8]     x1  ra       [16]  x5  t0       [24]  x6  t1
#    [32]    x7  t2       [40]  x10 a0       [48]  x11 a1
#    [56]    x12 a2       [64]  x13 a3       [72]  x14 a4
#    [80]    x15 a5       [88]  x16 a6       [96]  x17 a7
#    [104]   x8  s0/fp    [112] x9  s1       [120] x18 s2
#    [128]   x19 s3       [136] x20 s4       [144] x21 s5
#    [152]   x22 s6       [160] x23 s7       [168] x24 s8
#    [176]   x25 s9       [184] x26 s10      [192] x27 s11
#    [200]   x28 t3       [208] x29 t4       [216] x30 t5
#    [224]   x31 t6       [232] mepc         [240] mstatus
#    [248]   mcause       [256] mtval
# ═══════════════════════════════════════════════════════════════════

    .section .text.trap, "ax"
    .globl trap_vector
    .type  trap_vector, @function

trap_vector:
    # ── Swap sp with mscratch ──
    #    If trap from M-mode: sp was kernel sp, mscratch = same
    #    If first trap: mscratch = initial stack, sp = whatever
    csrrw   sp, mscratch, sp

    # ── Allocate trap frame on kernel stack ──
    addi    sp, sp, -264

    # ── Save all integer registers ──
    sd      x1,  8(sp)
    sd      x5,  16(sp)
    sd      x6,  24(sp)
    sd      x7,  32(sp)
    sd      x10, 40(sp)
    sd      x11, 48(sp)
    sd      x12, 56(sp)
    sd      x13, 64(sp)
    sd      x14, 72(sp)
    sd      x15, 80(sp)
    sd      x16, 88(sp)
    sd      x17, 96(sp)
    sd      x8,  104(sp)
    sd      x9,  112(sp)
    sd      x18, 120(sp)
    sd      x19, 128(sp)
    sd      x20, 136(sp)
    sd      x21, 144(sp)
    sd      x22, 152(sp)
    sd      x23, 160(sp)
    sd      x24, 168(sp)
    sd      x25, 176(sp)
    sd      x26, 184(sp)
    sd      x27, 192(sp)
    sd      x28, 200(sp)
    sd      x29, 208(sp)
    sd      x30, 216(sp)
    sd      x31, 224(sp)

    # ── Save CSRs ──
    csrr    t0, mepc
    sd      t0, 232(sp)
    csrr    t0, mstatus
    sd      t0, 240(sp)
    csrr    t0, mcause
    sd      t0, 248(sp)
    csrr    t0, mtval
    sd      t0, 256(sp)

    # ── Save previous mscratch (was in sp before csrrw) ──
    #    The old sp (pre-swap) is now in mscratch.
    csrr    t0, mscratch
    sd      t0, 0(sp)

    # ── Set mscratch to current kernel stack ──
    csrw    mscratch, sp

    # ── Call Zig trap handler ──
    mv      a0, sp
    call    trapDispatch

    # ── a0 = trap frame pointer to restore ──
    #    May differ from entry sp if context switch occurred
    mv      sp, a0

    # ── Restore CSRs ──
    ld      t0, 232(sp)
    csrw    mepc, t0
    ld      t0, 240(sp)
    csrw    mstatus, t0

    # ── Restore previous mscratch ──
    ld      t0, 0(sp)
    csrw    mscratch, t0

    # ── Restore all integer registers ──
    ld      x1,  8(sp)
    ld      x5,  16(sp)
    ld      x6,  24(sp)
    ld      x7,  32(sp)
    ld      x10, 40(sp)
    ld      x11, 48(sp)
    ld      x12, 56(sp)
    ld      x13, 64(sp)
    ld      x14, 72(sp)
    ld      x15, 80(sp)
    ld      x16, 88(sp)
    ld      x17, 96(sp)
    ld      x8,  104(sp)
    ld      x9,  112(sp)
    ld      x18, 120(sp)
    ld      x19, 128(sp)
    ld      x20, 136(sp)
    ld      x21, 144(sp)
    ld      x22, 152(sp)
    ld      x23, 160(sp)
    ld      x24, 168(sp)
    ld      x25, 176(sp)
    ld      x26, 184(sp)
    ld      x27, 192(sp)
    ld      x28, 200(sp)
    ld      x29, 208(sp)
    ld      x30, 216(sp)
    ld      x31, 224(sp)

    # ── Deallocate trap frame ──
    addi    sp, sp, 264

    # ── Return from trap ──
    mret

    .size trap_vector, . - trap_vector