vectors.S

Commit: e6209518 Author: jokerz Raw Copy
1
// vectors.S — AArch64 Exception Vector Table
2
// Each entry is 128 bytes (32 instructions), aligned to 2KB (0x800)
3
//
4
// Vector table layout:
5
//   0x000  Current EL with SP0: sync, irq, fiq, serror
6
//   0x200  Current EL with SPx: sync, irq, fiq, serror
7
//   0x400  Lower EL AArch64:   sync, irq, fiq, serror
8
//   0x600  Lower EL AArch32:   sync, irq, fiq, serror
9
10
.section .text
11
.align 11  // 2KB alignment (2^11 = 2048 = 0x800)
12
13
.globl vector_table
14
vector_table:
15
    // ================================================================
16
    // 0x000: Current EL with SP0 (shouldn't happen in normal operation)
17
    // ================================================================
18
.org 0x000
19
    b .  // sync
20
.org 0x080
21
    b .  // irq
22
.org 0x100
23
    b .  // fiq
24
.org 0x180
25
    b .  // serror
26
27
    // ================================================================
28
    // 0x200: Current EL with SPx (kernel mode exceptions)
29
    // ================================================================
30
.org 0x200
31
    b el1_sync_handler      // sync (kernel faults, SVC from kernel)
32
.org 0x280
33
    b el1_irq_handler       // irq (timer, peripherals while in kernel)
34
.org 0x300
35
    b .  // fiq
36
.org 0x380
37
    b .  // serror
38
39
    // ================================================================
40
    // 0x400: Lower EL with AArch64 (userspace → kernel transitions)
41
    // ================================================================
42
.org 0x400
43
    b el0_sync_handler      // sync (SVC instruction, data abort, etc.)
44
.org 0x480
45
    b el0_irq_handler       // irq (timer interrupt from userspace)
46
.org 0x500
47
    b .  // fiq
48
.org 0x580
49
    b .  // serror
50
51
    // ================================================================
52
    // 0x600: Lower EL with AArch32 (unused — we're AArch64 only)
53
    // ================================================================
54
.org 0x600
55
    b .
56
.org 0x680
57
    b .
58
.org 0x700
59
    b .
60
.org 0x780
61
    b .
62
63
// ================================================================
64
// Helper: save all general-purpose registers
65
// ================================================================
66
.macro save_all_regs
67
    stp x0, x1, [sp, #-16]!
68
    stp x2, x3, [sp, #-16]!
69
    stp x4, x5, [sp, #-16]!
70
    stp x6, x7, [sp, #-16]!
71
    stp x8, x9, [sp, #-16]!
72
    stp x10, x11, [sp, #-16]!
73
    stp x12, x13, [sp, #-16]!
74
    stp x14, x15, [sp, #-16]!
75
    stp x16, x17, [sp, #-16]!
76
    stp x18, x19, [sp, #-16]!
77
    stp x20, x21, [sp, #-16]!
78
    stp x22, x23, [sp, #-16]!
79
    stp x24, x25, [sp, #-16]!
80
    stp x26, x27, [sp, #-16]!
81
    stp x28, x29, [sp, #-16]!
82
    stp x30, xzr, [sp, #-16]!  // LR + padding
83
.endm
84
85
.macro restore_all_regs
86
    ldp x30, xzr, [sp], #16
87
    ldp x28, x29, [sp], #16
88
    ldp x26, x27, [sp], #16
89
    ldp x24, x25, [sp], #16
90
    ldp x22, x23, [sp], #16
91
    ldp x20, x21, [sp], #16
92
    ldp x18, x19, [sp], #16
93
    ldp x16, x17, [sp], #16
94
    ldp x14, x15, [sp], #16
95
    ldp x12, x13, [sp], #16
96
    ldp x10, x11, [sp], #16
97
    ldp x8, x9, [sp], #16
98
    ldp x6, x7, [sp], #16
99
    ldp x4, x5, [sp], #16
100
    ldp x2, x3, [sp], #16
101
    ldp x0, x1, [sp], #16
102
.endm
103
104
// ================================================================
105
// EL1 Sync Handler (kernel mode synchronous exceptions)
106
// ================================================================
107
el1_sync_handler:
108
    save_all_regs
109
    mrs x0, esr_el1         // Exception Syndrome Register
110
    mrs x1, elr_el1         // Exception Link Register
111
    mov x2, sp
112
    bl el1_sync_dispatch
113
    restore_all_regs
114
    eret
115
116
// ================================================================
117
// EL1 IRQ Handler (kernel mode interrupts — timer, etc.)
118
// ================================================================
119
el1_irq_handler:
120
    save_all_regs
121
    bl gic_acknowledge      // returns IRQ number in x0
122
    mov x19, x0             // save IRQ number
123
    bl el1_irq_dispatch     // handle the IRQ
124
    mov x0, x19             // restore IRQ number
125
    bl gic_eoi              // end of interrupt
126
    restore_all_regs
127
    eret
128
129
// ================================================================
130
// EL0 Sync Handler (userspace synchronous — SVC instruction)
131
// ================================================================
132
el0_sync_handler:
133
    save_all_regs
134
    mrs x0, esr_el1         // Exception Syndrome Register
135
    mrs x1, elr_el1         // Exception Link Register (user PC)
136
    mrs x2, sp_el0          // User stack pointer
137
    mov x3, sp              // Kernel stack (for passing to C)
138
    bl el0_sync_dispatch
139
    restore_all_regs
140
    eret
141
142
// ================================================================
143
// EL0 IRQ Handler (userspace interrupts — timer from EL0)
144
// ================================================================
145
el0_irq_handler:
146
    save_all_regs
147
    bl gic_acknowledge      // returns IRQ number in x0
148
    mov x19, x0             // save IRQ number
149
    bl el0_irq_dispatch     // handle the IRQ
150
    mov x0, x19
151
    bl gic_eoi
152
    restore_all_regs
153
    eret
154
155
// ================================================================
156
// C dispatch functions (called from assembly)
157
// ================================================================
158
159
// el1_sync_dispatch(esr, elr, sp) — kernel sync exception
160
.globl el1_sync_dispatch
161
el1_sync_dispatch:
162
    // For now, just return. We'll handle faults later.
163
    ret
164
165
// el1_irq_dispatch(irq_num) — kernel IRQ
166
.globl el1_irq_dispatch
167
el1_irq_dispatch:
168
    // Check if timer IRQ
169
    cmp x0, #30             // IRQ_TIMER_CNTP
170
    b.ne .Lnot_timer_kern
171
    b timer_irq             // tail call to timer_irq()
172
.Lnot_timer_kern:
173
    ret
174
175
// el0_sync_dispatch(esr, elr, sp_el0, sp) — userspace sync
176
.globl el0_sync_dispatch
177
el0_sync_dispatch:
178
    // Check if SVC instruction (ESR bits [31:26] = 0x15)
179
    lsr x4, x0, #26
180
    and x4, x4, #0x3F
181
    cmp x4, #0x15           // SVC from AArch64
182
    b.ne .Lnot_svc
183
    // TODO: dispatch syscall based on x8 register
184
    // For now, just return
185
    ret
186
.Lnot_svc:
187
    ret
188
189
// el0_irq_dispatch(irq_num) — userspace IRQ
190
.globl el0_irq_dispatch
191
el0_irq_dispatch:
192
    cmp x0, #30
193
    b.ne .Lnot_timer_user
194
    b timer_irq
195
.Lnot_timer_user:
196
    ret
197