Skip to content

Commit da58023

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 956c132 commit da58023

File tree

3 files changed

+233
-0
lines changed

3 files changed

+233
-0
lines changed
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
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/tree/dev/src/kernel/src/hal/arch/x86
19+
20+
use core::arch::global_asm;
21+
use crate::interrupt_handlers::hl_exception_handler;
22+
23+
extern "sysv64" {
24+
// Exception handlers
25+
pub(crate) fn _do_excp0();
26+
pub(crate) fn _do_excp1();
27+
pub(crate) fn _do_excp2();
28+
pub(crate) fn _do_excp3();
29+
pub(crate) fn _do_excp4();
30+
pub(crate) fn _do_excp5();
31+
pub(crate) fn _do_excp6();
32+
pub(crate) fn _do_excp7();
33+
pub(crate) fn _do_excp8();
34+
pub(crate) fn _do_excp9();
35+
pub(crate) fn _do_excp10();
36+
pub(crate) fn _do_excp11();
37+
pub(crate) fn _do_excp12();
38+
pub(crate) fn _do_excp13();
39+
pub(crate) fn _do_excp14();
40+
pub(crate) fn _do_excp15();
41+
pub(crate) fn _do_excp16();
42+
pub(crate) fn _do_excp17();
43+
pub(crate) fn _do_excp18();
44+
pub(crate) fn _do_excp19();
45+
pub(crate) fn _do_excp20();
46+
pub(crate) fn _do_excp30();
47+
}
48+
49+
// Defines `context_save` and `context_restore`
50+
macro_rules! context_save {
51+
() => {
52+
concat!(
53+
// Save general-purpose registers
54+
" push rax\n",
55+
" push rbx\n",
56+
" push rcx\n",
57+
" push rdx\n",
58+
" push rsi\n",
59+
" push rdi\n",
60+
" push rbp\n",
61+
" push r8\n",
62+
" push r9\n",
63+
" push r10\n",
64+
" push r11\n",
65+
" push r12\n",
66+
" push r13\n",
67+
" push r14\n",
68+
" push r15\n",
69+
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+
96+
// Restore general-purpose registers
97+
" pop r15\n",
98+
" pop r14\n",
99+
" pop r13\n",
100+
" pop r12\n",
101+
" pop r11\n",
102+
" pop r10\n",
103+
" pop r9\n",
104+
" pop r8\n",
105+
" pop rbp\n",
106+
" pop rdi\n",
107+
" pop rsi\n",
108+
" pop rdx\n",
109+
" pop rcx\n",
110+
" pop rbx\n",
111+
" pop rax\n",
112+
)
113+
};
114+
}
115+
116+
// Generates exception handlers
117+
macro_rules! generate_exceptions {
118+
() => {
119+
concat!(
120+
// Common exception handler
121+
".global _do_excp_common\n",
122+
"_do_excp_common:\n",
123+
// In SysV ABI, the first argument is passed in rdi
124+
// rdi is the stack pointer.
125+
" mov rdi, rsp\n",
126+
" call {hl_exception_handler}\n",
127+
context_restore!(),
128+
" mov r14, 495\n",
129+
" iretq\n", // iretq is used to return from exception in x86_64
130+
generate_excp!(0),
131+
generate_excp!(1),
132+
generate_excp!(2),
133+
generate_excp!(3),
134+
generate_excp!(4),
135+
generate_excp!(5),
136+
generate_excp!(6),
137+
generate_excp!(7),
138+
generate_excp!(8),
139+
generate_excp!(9),
140+
generate_excp!(10),
141+
generate_excp!(11),
142+
generate_excp!(12),
143+
generate_excp!(13),
144+
generate_excp!(14, pagefault),
145+
generate_excp!(15),
146+
generate_excp!(16),
147+
generate_excp!(17),
148+
generate_excp!(18),
149+
generate_excp!(19),
150+
generate_excp!(20),
151+
generate_excp!(30),
152+
)
153+
};
154+
}
155+
156+
// Macro to generate exception handlers
157+
// that satisfy the `extern`s at the top of the file.
158+
//
159+
// - Example output from this macro for generate_excp!(0) call:
160+
// ```assembly
161+
// .global _do_excp0
162+
// _do_excp0:
163+
// context_save!()
164+
// mov rsi, 0
165+
// mov rdx, 0
166+
// jmp _do_excp_common
167+
// ```
168+
macro_rules! generate_excp {
169+
($num:expr) => {
170+
concat!(
171+
".global _do_excp", stringify!($num), "\n",
172+
"_do_excp", stringify!($num), ":\n",
173+
context_save!(),
174+
// In SysV ABI, the second argument is passed in rsi
175+
// rsi is the exception number.
176+
" mov rsi, ", stringify!($num), "\n",
177+
// In SysV ABI, the third argument is passed in rdx
178+
// rdx is only used for pagefault exception and
179+
// contains the address that caused the pagefault.
180+
" mov rdx, 0\n",
181+
" jmp _do_excp_common\n"
182+
)
183+
};
184+
($num:expr, pagefault) => {
185+
concat!(
186+
".global _do_excp", stringify!($num), "\n",
187+
"_do_excp", stringify!($num), ":\n",
188+
context_save!(),
189+
" mov rsi, ", stringify!($num), "\n",
190+
// In a page fault exception, the cr2 register
191+
// contains the address that caused the page fault.
192+
" mov rdx, cr2\n",
193+
" jmp _do_excp_common\n"
194+
)
195+
};
196+
}
197+
198+
// Output the assembly code
199+
global_asm!(
200+
generate_exceptions!(),
201+
hl_exception_handler = sym hl_exception_handler,
202+
);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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/tree/dev/src/kernel/src/hal/arch/x86
19+
20+
/// Exception handler
21+
#[no_mangle]
22+
pub extern "sysv64" fn hl_exception_handler(stack_pointer: u64, exception_number: u64, page_fault_address: u64) {
23+
panic!(
24+
"EXCEPTION: {:#x}\n\
25+
Page Fault Address: {:#x}\n\
26+
Stack Pointer: {:#x}",
27+
exception_number, page_fault_address, stack_pointer
28+
);
29+
}

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)