Skip to content

Commit 8903cd8

Browse files
authored
Merge pull request #1889 from hermit-os/feature-kernel_stack
feat: add kernel-stack feature to allow disabling switching stacks on syscalls
2 parents 0e5eb50 + 0f4d234 commit 8903cd8

File tree

8 files changed

+152
-152
lines changed

8 files changed

+152
-152
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ name = "measure_startup_time"
4545
harness = false
4646

4747
[features]
48-
default = ["pci", "pci-ids", "acpi", "fsgsbase", "smp", "tcp", "dhcpv4", "fuse", "virtio-net", "vsock"]
48+
default = ["kernel-stack", "pci", "pci-ids", "acpi", "fsgsbase", "smp", "tcp", "dhcpv4", "fuse", "virtio-net", "vsock"]
4949
acpi = []
5050
common-os = []
5151
console = ["virtio"]
@@ -56,6 +56,7 @@ fsgsbase = []
5656
fuse = ["virtio", "pci", "dep:fuse-abi", "fuse-abi/num_enum"]
5757
gem-net = ["tcp", "dep:tock-registers"]
5858
idle-poll = []
59+
kernel-stack = []
5960
log-target = []
6061
net = []
6162
mman = []

hermit-macro/src/system.rs

Lines changed: 40 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -174,17 +174,16 @@ fn emit_func(func: ItemFn, sig: &ParsedSig, errno: bool) -> Result<ItemFn> {
174174

175175
#kernel_func
176176

177-
#[cfg(not(any(
178-
target_arch = "riscv64",
179-
feature = "common-os"
180-
)))]
181-
unsafe { crate::arch::switch::#kernel_function_ident(#kernel_ident, #(#args),*) }
182-
183-
#[cfg(any(
184-
target_arch = "riscv64",
185-
feature = "common-os"
186-
))]
187-
#unsafety { #kernel_ident(#(#args),*) }
177+
cfg_if::cfg_if! {
178+
if #[cfg(all(
179+
feature = "kernel-stack",
180+
not(any(target_arch = "riscv64", feature = "common-os"))
181+
))] {
182+
unsafe { crate::arch::kernel::kernel_stack::#kernel_function_ident(#kernel_ident, #(#args),*) }
183+
} else {
184+
#unsafety { #kernel_ident(#(#args),*) }
185+
}
186+
}
188187
}},
189188
..func
190189
};
@@ -255,17 +254,16 @@ mod tests {
255254
ret
256255
}
257256

258-
#[cfg(not(any(
259-
target_arch = "riscv64",
260-
feature = "common-os"
261-
)))]
262-
unsafe { crate::arch::switch::kernel_function2(_sys_test, a, b) }
263-
264-
#[cfg(any(
265-
target_arch = "riscv64",
266-
feature = "common-os"
267-
))]
268-
{ _sys_test(a, b) }
257+
cfg_if::cfg_if! {
258+
if #[cfg(all(
259+
feature = "kernel-stack",
260+
not(any(target_arch = "riscv64", feature = "common-os"))
261+
))] {
262+
unsafe { crate::arch::kernel::kernel_stack::kernel_function2(_sys_test, a, b) }
263+
} else {
264+
{ _sys_test(a, b) }
265+
}
266+
}
269267
}
270268
};
271269

@@ -324,17 +322,16 @@ mod tests {
324322
ret
325323
}
326324

327-
#[cfg(not(any(
328-
target_arch = "riscv64",
329-
feature = "common-os"
330-
)))]
331-
unsafe { crate::arch::switch::kernel_function2(_sys_test, a, b) }
332-
333-
#[cfg(any(
334-
target_arch = "riscv64",
335-
feature = "common-os"
336-
))]
337-
unsafe { _sys_test(a, b) }
325+
cfg_if::cfg_if! {
326+
if #[cfg(all(
327+
feature = "kernel-stack",
328+
not(any(target_arch = "riscv64", feature = "common-os"))
329+
))] {
330+
unsafe { crate::arch::kernel::kernel_stack::kernel_function2(_sys_test, a, b) }
331+
} else {
332+
unsafe { _sys_test(a, b) }
333+
}
334+
}
338335
}
339336
};
340337

@@ -395,17 +392,16 @@ mod tests {
395392
ret
396393
}
397394

398-
#[cfg(not(any(
399-
target_arch = "riscv64",
400-
feature = "common-os"
401-
)))]
402-
unsafe { crate::arch::switch::kernel_function2(_sys_test, a, b) }
403-
404-
#[cfg(any(
405-
target_arch = "riscv64",
406-
feature = "common-os"
407-
))]
408-
{ _sys_test(a, b) }
395+
cfg_if::cfg_if! {
396+
if #[cfg(all(
397+
feature = "kernel-stack",
398+
not(any(target_arch = "riscv64", feature = "common-os"))
399+
))] {
400+
unsafe { crate::arch::kernel::kernel_stack::kernel_function2(_sys_test, a, b) }
401+
} else {
402+
{ _sys_test(a, b) }
403+
}
404+
}
409405
}
410406
};
411407

File renamed without changes.

src/arch/aarch64/kernel/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
pub mod core_local;
22
pub mod interrupts;
3+
#[cfg(feature = "kernel-stack")]
4+
pub mod kernel_stack;
35
#[cfg(all(
46
not(feature = "pci"),
57
any(
@@ -15,7 +17,6 @@ pub mod scheduler;
1517
pub mod serial;
1618
#[cfg(target_os = "none")]
1719
mod start;
18-
pub mod switch;
1920
pub mod systemtime;
2021

2122
use alloc::alloc::{Layout, alloc};

src/arch/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ cfg_if::cfg_if! {
1616
pub(crate) use self::aarch64::kernel::serial::SerialDevice;
1717
pub(crate) use self::aarch64::kernel::processor::set_oneshot_timer;
1818
pub(crate) use self::aarch64::kernel::scheduler;
19-
#[cfg(not(feature = "common-os"))]
20-
pub(crate) use self::aarch64::kernel::switch;
2119
#[cfg(feature = "smp")]
2220
pub(crate) use self::aarch64::kernel::application_processor_init;
2321
pub(crate) use self::aarch64::kernel::{
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
use core::arch::asm;
2+
use core::{mem, ptr};
3+
4+
use crate::core_local::CoreLocal;
5+
6+
macro_rules! kernel_function_impl {
7+
($kernel_function:ident($($arg:ident: $A:ident),*) { $($operands:tt)* }) => {
8+
/// Executes `f` on the kernel stack.
9+
#[allow(dead_code)]
10+
pub unsafe fn $kernel_function<R, $($A),*>(f: unsafe extern "C" fn($($A),*) -> R, $($arg: $A),*) -> R {
11+
unsafe {
12+
assert!(mem::size_of::<R>() <= mem::size_of::<usize>());
13+
14+
$(
15+
assert!(mem::size_of::<$A>() <= mem::size_of::<usize>());
16+
let $arg = {
17+
let mut reg = 0usize;
18+
// SAFETY: $A is smaller than usize and directly fits in a register
19+
// Since f takes $A as argument via C calling convention, any upper bytes do not matter.
20+
ptr::write(ptr::from_mut(&mut reg).cast(), $arg);
21+
reg
22+
};
23+
)*
24+
25+
let ret: u64;
26+
asm!(
27+
// Save user stack pointer and switch to kernel stack
28+
"cli",
29+
"mov r12, rsp",
30+
"mov rsp, {kernel_stack_ptr}",
31+
"sti",
32+
33+
// To make sure, Rust manages the stack in `f` correctly,
34+
// we keep all arguments and return values in registers
35+
// until we switch the stack back. Thus follows the sizing
36+
// requirements for arguments and return types.
37+
"call {f}",
38+
39+
// Switch back to user stack
40+
"cli",
41+
"mov rsp, r12",
42+
"sti",
43+
44+
f = in(reg) f,
45+
kernel_stack_ptr = in(reg) CoreLocal::get().kernel_stack.get(),
46+
47+
$($operands)*
48+
49+
// user_stack_ptr saved in r12
50+
out("r12") _,
51+
52+
// Return argument in rax
53+
out("rax") ret,
54+
55+
clobber_abi("C"),
56+
);
57+
58+
// SAFETY: R is smaller than usize and directly fits in rax
59+
// Since f returns R, we can safely convert ret to R
60+
mem::transmute_copy(&ret)
61+
}
62+
}
63+
};
64+
}
65+
66+
kernel_function_impl!(kernel_function0() {});
67+
68+
kernel_function_impl!(kernel_function1(arg1: A1) {
69+
in("rdi") arg1,
70+
});
71+
72+
kernel_function_impl!(kernel_function2(arg1: A1, arg2: A2) {
73+
in("rdi") arg1,
74+
in("rsi") arg2,
75+
});
76+
77+
kernel_function_impl!(kernel_function3(arg1: A1, arg2: A2, arg3: A3) {
78+
in("rdi") arg1,
79+
in("rsi") arg2,
80+
in("rdx") arg3,
81+
});
82+
83+
kernel_function_impl!(kernel_function4(arg1: A1, arg2: A2, arg3: A3, arg4: A4) {
84+
in("rdi") arg1,
85+
in("rsi") arg2,
86+
in("rdx") arg3,
87+
in("rcx") arg4,
88+
});
89+
90+
kernel_function_impl!(kernel_function5(arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5) {
91+
in("rdi") arg1,
92+
in("rsi") arg2,
93+
in("rdx") arg3,
94+
in("rcx") arg4,
95+
in("r8") arg5,
96+
});
97+
98+
kernel_function_impl!(kernel_function6(arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, arg6: A6) {
99+
in("rdi") arg1,
100+
in("rsi") arg2,
101+
in("rdx") arg3,
102+
in("rcx") arg4,
103+
in("r8") arg5,
104+
in("r9") arg6,
105+
});

src/arch/x86_64/kernel/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ pub mod apic;
1616
pub mod core_local;
1717
pub mod gdt;
1818
pub mod interrupts;
19+
#[cfg(feature = "kernel-stack")]
20+
pub mod kernel_stack;
1921
#[cfg(all(
2022
not(feature = "pci"),
2123
any(

src/arch/x86_64/kernel/switch.rs

Lines changed: 1 addition & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
use core::arch::{asm, naked_asm};
2-
use core::{mem, ptr};
1+
use core::arch::naked_asm;
32

4-
use crate::core_local::CoreLocal;
53
use crate::set_current_kernel_stack;
64

75
#[cfg(not(feature = "common-os"))]
@@ -209,104 +207,3 @@ pub(crate) unsafe extern "C" fn switch_to_fpu_owner(_old_stack: *mut usize, _new
209207
set_current_kernel_stack = sym set_current_kernel_stack,
210208
);
211209
}
212-
213-
macro_rules! kernel_function_impl {
214-
($kernel_function:ident($($arg:ident: $A:ident),*) { $($operands:tt)* }) => {
215-
/// Executes `f` on the kernel stack.
216-
#[allow(dead_code)]
217-
pub unsafe fn $kernel_function<R, $($A),*>(f: unsafe extern "C" fn($($A),*) -> R, $($arg: $A),*) -> R {
218-
unsafe {
219-
assert!(mem::size_of::<R>() <= mem::size_of::<usize>());
220-
221-
$(
222-
assert!(mem::size_of::<$A>() <= mem::size_of::<usize>());
223-
let $arg = {
224-
let mut reg = 0usize;
225-
// SAFETY: $A is smaller than usize and directly fits in a register
226-
// Since f takes $A as argument via C calling convention, any upper bytes do not matter.
227-
ptr::write(ptr::from_mut(&mut reg).cast(), $arg);
228-
reg
229-
};
230-
)*
231-
232-
let ret: u64;
233-
asm!(
234-
// Save user stack pointer and switch to kernel stack
235-
"cli",
236-
"mov r12, rsp",
237-
"mov rsp, {kernel_stack_ptr}",
238-
"sti",
239-
240-
// To make sure, Rust manages the stack in `f` correctly,
241-
// we keep all arguments and return values in registers
242-
// until we switch the stack back. Thus follows the sizing
243-
// requirements for arguments and return types.
244-
"call {f}",
245-
246-
// Switch back to user stack
247-
"cli",
248-
"mov rsp, r12",
249-
"sti",
250-
251-
f = in(reg) f,
252-
kernel_stack_ptr = in(reg) CoreLocal::get().kernel_stack.get(),
253-
254-
$($operands)*
255-
256-
// user_stack_ptr saved in r12
257-
out("r12") _,
258-
259-
// Return argument in rax
260-
out("rax") ret,
261-
262-
clobber_abi("C"),
263-
);
264-
265-
// SAFETY: R is smaller than usize and directly fits in rax
266-
// Since f returns R, we can safely convert ret to R
267-
mem::transmute_copy(&ret)
268-
}
269-
}
270-
};
271-
}
272-
273-
kernel_function_impl!(kernel_function0() {});
274-
275-
kernel_function_impl!(kernel_function1(arg1: A1) {
276-
in("rdi") arg1,
277-
});
278-
279-
kernel_function_impl!(kernel_function2(arg1: A1, arg2: A2) {
280-
in("rdi") arg1,
281-
in("rsi") arg2,
282-
});
283-
284-
kernel_function_impl!(kernel_function3(arg1: A1, arg2: A2, arg3: A3) {
285-
in("rdi") arg1,
286-
in("rsi") arg2,
287-
in("rdx") arg3,
288-
});
289-
290-
kernel_function_impl!(kernel_function4(arg1: A1, arg2: A2, arg3: A3, arg4: A4) {
291-
in("rdi") arg1,
292-
in("rsi") arg2,
293-
in("rdx") arg3,
294-
in("rcx") arg4,
295-
});
296-
297-
kernel_function_impl!(kernel_function5(arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5) {
298-
in("rdi") arg1,
299-
in("rsi") arg2,
300-
in("rdx") arg3,
301-
in("rcx") arg4,
302-
in("r8") arg5,
303-
});
304-
305-
kernel_function_impl!(kernel_function6(arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, arg6: A6) {
306-
in("rdi") arg1,
307-
in("rsi") arg2,
308-
in("rdx") arg3,
309-
in("rcx") arg4,
310-
in("r8") arg5,
311-
in("r9") arg6,
312-
});

0 commit comments

Comments
 (0)