Skip to content

Commit 98c5a18

Browse files
committed
[interrupt-handlers] added interrupt handler entry stubs and exception handler
- interrupt handler entry stubs = -- added macros to save/restore register context -- added defintions for different exceptions (_do_excp0-20+30), which save context, set params per SysV ABI, call handler, restore context, then iretq via macros. - added an exception handler that are used by the _do_excp* fxns. Note: this code is specific for x86_64 Signed-off-by: danbugs <[email protected]>
1 parent 757fb9b commit 98c5a18

File tree

3 files changed

+269
-0
lines changed

3 files changed

+269
-0
lines changed
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
/*
2+
Copyright 2024 The Hyperlight Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// Note: this code takes reference from
18+
// https://github.com/nanvix/nanvix/blob/dev/src/kernel/src/hal/arch/x86/hooks.S
19+
20+
use core::arch::global_asm;
21+
22+
use crate::interrupt_handlers::hl_exception_handler;
23+
24+
extern "sysv64" {
25+
// Exception handlers
26+
pub(crate) fn _do_excp0();
27+
pub(crate) fn _do_excp1();
28+
pub(crate) fn _do_excp2();
29+
pub(crate) fn _do_excp3();
30+
pub(crate) fn _do_excp4();
31+
pub(crate) fn _do_excp5();
32+
pub(crate) fn _do_excp6();
33+
pub(crate) fn _do_excp7();
34+
pub(crate) fn _do_excp8();
35+
pub(crate) fn _do_excp9();
36+
pub(crate) fn _do_excp10();
37+
pub(crate) fn _do_excp11();
38+
pub(crate) fn _do_excp12();
39+
pub(crate) fn _do_excp13();
40+
pub(crate) fn _do_excp14();
41+
pub(crate) fn _do_excp15();
42+
pub(crate) fn _do_excp16();
43+
pub(crate) fn _do_excp17();
44+
pub(crate) fn _do_excp18();
45+
pub(crate) fn _do_excp19();
46+
pub(crate) fn _do_excp20();
47+
pub(crate) fn _do_excp30();
48+
}
49+
50+
// Defines `context_save` and `context_restore`
51+
macro_rules! context_save {
52+
() => {
53+
concat!(
54+
// Save general-purpose registers
55+
" push rax\n",
56+
" push rbx\n",
57+
" push rcx\n",
58+
" push rdx\n",
59+
" push rsi\n",
60+
" push rdi\n",
61+
" push rbp\n",
62+
" push r8\n",
63+
" push r9\n",
64+
" push r10\n",
65+
" push r11\n",
66+
" push r12\n",
67+
" push r13\n",
68+
" push r14\n",
69+
" push r15\n",
70+
// Save segment registers
71+
" mov rax, ds\n",
72+
" push rax\n",
73+
" mov rax, es\n",
74+
" push rax\n",
75+
" mov rax, fs\n",
76+
" push rax\n",
77+
" mov rax, gs\n",
78+
" push rax\n",
79+
)
80+
};
81+
}
82+
83+
macro_rules! context_restore {
84+
() => {
85+
concat!(
86+
// Restore segment registers
87+
" pop rax\n",
88+
" mov gs, rax\n",
89+
" pop rax\n",
90+
" mov fs, rax\n",
91+
" pop rax\n",
92+
" mov es, rax\n",
93+
" pop rax\n",
94+
" mov ds, rax\n",
95+
// Restore general-purpose registers
96+
" pop r15\n",
97+
" pop r14\n",
98+
" pop r13\n",
99+
" pop r12\n",
100+
" pop r11\n",
101+
" pop r10\n",
102+
" pop r9\n",
103+
" pop r8\n",
104+
" pop rbp\n",
105+
" pop rdi\n",
106+
" pop rsi\n",
107+
" pop rdx\n",
108+
" pop rcx\n",
109+
" pop rbx\n",
110+
" pop rax\n",
111+
)
112+
};
113+
}
114+
115+
// Generates exception handlers
116+
macro_rules! generate_exceptions {
117+
() => {
118+
concat!(
119+
// Common exception handler
120+
".global _do_excp_common\n",
121+
"_do_excp_common:\n",
122+
// In SysV ABI, the first argument is passed in rdi
123+
// rdi is the stack pointer.
124+
" mov rdi, rsp\n",
125+
" call {hl_exception_handler}\n",
126+
context_restore!(),
127+
" iretq\n", // iretq is used to return from exception in x86_64
128+
generate_excp!(0, pusherrcode),
129+
generate_excp!(1, pusherrcode),
130+
generate_excp!(2, pusherrcode),
131+
generate_excp!(3, pusherrcode),
132+
generate_excp!(4, pusherrcode),
133+
generate_excp!(5, pusherrcode),
134+
generate_excp!(6, pusherrcode),
135+
generate_excp!(7, pusherrcode),
136+
generate_excp!(8),
137+
generate_excp!(9, pusherrcode),
138+
generate_excp!(10),
139+
generate_excp!(11),
140+
generate_excp!(12),
141+
generate_excp!(13),
142+
generate_excp!(14, pagefault),
143+
generate_excp!(15, pusherrcode),
144+
generate_excp!(16, pusherrcode),
145+
generate_excp!(17),
146+
generate_excp!(18, pusherrcode),
147+
generate_excp!(19, pusherrcode),
148+
generate_excp!(20, pusherrcode),
149+
generate_excp!(30),
150+
)
151+
};
152+
}
153+
154+
// Macro to generate exception handlers
155+
// that satisfy the `extern`s at the top of the file.
156+
//
157+
// - Example output from this macro for generate_excp!(0) call:
158+
// ```assembly
159+
// .global _do_excp0
160+
// _do_excp0:
161+
// context_save!()
162+
// mov rsi, 0
163+
// mov rdx, 0
164+
// jmp _do_excp_common
165+
// ```
166+
macro_rules! generate_excp {
167+
($num:expr) => {
168+
concat!(
169+
".global _do_excp",
170+
stringify!($num),
171+
"\n",
172+
"_do_excp",
173+
stringify!($num),
174+
":\n",
175+
context_save!(),
176+
// In SysV ABI, the second argument is passed in rsi
177+
// rsi is the exception number.
178+
" mov rsi, ",
179+
stringify!($num),
180+
"\n",
181+
// In SysV ABI, the third argument is passed in rdx
182+
// rdx is only used for pagefault exception and
183+
// contains the address that caused the pagefault.
184+
" mov rdx, 0\n",
185+
" jmp _do_excp_common\n"
186+
)
187+
};
188+
($num:expr, pusherrcode) => {
189+
concat!(
190+
".global _do_excp",
191+
stringify!($num),
192+
"\n",
193+
"_do_excp",
194+
stringify!($num),
195+
":\n",
196+
// Some exceptions push an error code onto the stack.
197+
// For the ones that don't, we push a 0 to keep the
198+
// stack aligned.
199+
" push 0\n",
200+
context_save!(),
201+
// In SysV ABI, the second argument is passed in rsi
202+
// rsi is the exception number.
203+
" mov rsi, ",
204+
stringify!($num),
205+
"\n",
206+
// In SysV ABI, the third argument is passed in rdx
207+
// rdx is only used for pagefault exception and
208+
// contains the address that caused the pagefault.
209+
" mov rdx, 0\n",
210+
" jmp _do_excp_common\n"
211+
)
212+
};
213+
($num:expr, pagefault) => {
214+
concat!(
215+
".global _do_excp",
216+
stringify!($num),
217+
"\n",
218+
"_do_excp",
219+
stringify!($num),
220+
":\n",
221+
context_save!(),
222+
" mov rsi, ",
223+
stringify!($num),
224+
"\n",
225+
// In a page fault exception, the cr2 register
226+
// contains the address that caused the page fault.
227+
" mov rdx, cr2\n",
228+
" jmp _do_excp_common\n"
229+
)
230+
};
231+
}
232+
233+
// Output the assembly code
234+
global_asm!(
235+
generate_exceptions!(),
236+
hl_exception_handler = sym hl_exception_handler,
237+
);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
Copyright 2024 The Hyperlight Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
/// Exception handler
18+
#[no_mangle]
19+
pub extern "sysv64" fn hl_exception_handler(
20+
stack_pointer: u64,
21+
exception_number: u64,
22+
page_fault_address: u64,
23+
) {
24+
panic!(
25+
"EXCEPTION: {:#x}\n\
26+
Page Fault Address: {:#x}\n\
27+
Stack Pointer: {:#x}",
28+
exception_number, page_fault_address, stack_pointer
29+
);
30+
}

src/hyperlight_guest/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ pub mod setjmp;
5151
pub mod chkstk;
5252
pub mod error;
5353
pub mod logging;
54+
pub mod interrupt_entry;
55+
pub mod interrupt_handlers;
5456

5557
// Unresolved symbols
5658
///cbindgen:ignore

0 commit comments

Comments
 (0)