-
Notifications
You must be signed in to change notification settings - Fork 0
/
exceptions.S
144 lines (120 loc) · 3.07 KB
/
exceptions.S
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
.macro set_reg_to_task_context, reg
// set sp to current task descriptor
ldr \reg, =current_task // current_task is a pointer to a pointer of the current task
ldr \reg, [\reg] // dereference
add \reg, \reg, #8 // offset to context within task descriptor
.endm
// x0 is pointer to trapframe struct
// store values currently in the registers in the
// trapframe.
.macro kern_enter
// temporarily store x3
str x3, [sp, #-16]!
set_reg_to_task_context x3
// save x0, x1 to context
stp x0, x1, [x3], #16
// restore x3 and use x0 to keep track of offset
// within context instead
mov x0, x3
ldr x3, [sp], #16
// save rest of pointers (x2-x30)
stp x2, x3, [x0], #16
stp x4, x5, [x0], #16
stp x6, x7, [x0], #16
stp x8, x9, [x0], #16
stp x10, x11, [x0], #16
stp x12, x13, [x0], #16
stp x14, x15, [x0], #16
stp x16, x17, [x0], #16
stp x18, x19, [x0], #16
stp x20, x21, [x0], #16
stp x22, x23, [x0], #16
stp x24, x25, [x0], #16
stp x26, x27, [x0], #16
stp x28, x29, [x0], #16
str x30, [x0], #8
// store sp register
mrs x1, SP_EL0
str x1, [x0], #8
// store lr register
mrs x1, ELR_EL1
str x1, [x0], #8
// store pstate
mrs x1, SPSR_EL1
str x1, [x0]
// reset kernel stack
ldr x1, =stackend
mov sp, x1
.endm
// restore registers and return to user mode (EL0)
.global kern_exit
kern_exit:
set_reg_to_task_context x0
// start from the end of the struct (restore backwards)
add x0, x0, #272 // total size of context
// restore pstate
ldr x1, [x0, #-8]!
msr SPSR_EL1, x1
// restore lr register
ldr x1, [x0, #-8]!
msr ELR_EL1, x1
// restore sp register
ldr x1, [x0, #-8]!
msr SP_EL0, x1
// restore x0-x30 from context
ldr x30, [x0, #-8]!
ldp x28, x29, [x0, #-16]!
ldp x26, x27, [x0, #-16]!
ldp x24, x25, [x0, #-16]!
ldp x22, x23, [x0, #-16]!
ldp x20, x21, [x0, #-16]!
ldp x18, x19, [x0, #-16]!
ldp x16, x17, [x0, #-16]!
ldp x14, x15, [x0, #-16]!
ldp x12, x13, [x0, #-16]!
ldp x10, x11, [x0, #-16]!
ldp x8, x9, [x0, #-16]!
ldp x6, x7, [x0, #-16]!
ldp x4, x5, [x0, #-16]!
ldp x2, x3, [x0, #-16]!
ldp x0, x1, [x0, #-16]
eret
.global init_exception_vector_table
init_exception_vector_table:
ldr x0, =exception_table
msr VBAR_EL1, x0
ret
.macro exception_handler
.balign 0x80
kern_enter
mrs x0, ESR_EL1 // ESR_EL1 as argument to handler
b handle_exception // handle_exception calls kern_exit
.endm
.macro irq_handler
.balign 0x80
kern_enter
b handle_irq // handle_irq calls kern_exit
.endm
.macro invalid_exception_handler
.balign 0x80
b handle_invalid_exception
.endm
.balign 0x800 // Table is 2048 bytes in total
exception_table:
// Current EL with SP0
invalid_exception_handler
invalid_exception_handler
invalid_exception_handler
invalid_exception_handler
invalid_exception_handler
invalid_exception_handler
invalid_exception_handler
invalid_exception_handler
exception_handler
irq_handler
invalid_exception_handler
invalid_exception_handler
invalid_exception_handler
invalid_exception_handler
invalid_exception_handler
invalid_exception_handler