| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- use crate::{
- kernel::task::{ProcessList, Signal},
- println_warn,
- };
- use arch::{ExtendedContext, InterruptContext};
- extern crate arch;
- mod file_rw;
- mod mm;
- mod net;
- mod procops;
- mod sysinfo;
- pub(self) struct MapArgumentImpl;
- pub(self) trait MapArgument<'a, T: 'a> {
- fn map_arg(value: u64) -> T;
- }
- pub(self) trait MapReturnValue {
- fn map_ret(self) -> usize;
- }
- impl MapReturnValue for () {
- fn map_ret(self) -> usize {
- 0
- }
- }
- impl MapReturnValue for u32 {
- fn map_ret(self) -> usize {
- self as usize
- }
- }
- impl MapReturnValue for usize {
- fn map_ret(self) -> usize {
- self
- }
- }
- impl MapArgument<'_, u64> for MapArgumentImpl {
- fn map_arg(value: u64) -> u64 {
- value as u64
- }
- }
- impl MapArgument<'_, u32> for MapArgumentImpl {
- fn map_arg(value: u64) -> u32 {
- value as u32
- }
- }
- impl MapArgument<'_, i32> for MapArgumentImpl {
- fn map_arg(value: u64) -> i32 {
- value as i32
- }
- }
- impl MapArgument<'_, usize> for MapArgumentImpl {
- fn map_arg(value: u64) -> usize {
- value as usize
- }
- }
- impl<'a, T: 'a> MapArgument<'a, *const T> for MapArgumentImpl {
- fn map_arg(value: u64) -> *const T {
- value as *const _
- }
- }
- impl<'a, T: 'a> MapArgument<'a, *mut T> for MapArgumentImpl {
- fn map_arg(value: u64) -> *mut T {
- value as *mut _
- }
- }
- macro_rules! arg_register {
- (0, $is:ident) => {
- $is.rbx
- };
- (1, $is:ident) => {
- $is.rcx
- };
- (2, $is:ident) => {
- $is.rdx
- };
- (3, $is:ident) => {
- $is.rsi
- };
- (4, $is:ident) => {
- $is.rdi
- };
- (5, $is:ident) => {
- $is.rbp
- };
- }
- #[allow(unused_macros)]
- macro_rules! format_expand {
- ($name:ident, $arg:tt) => {
- format_args!("{}: {:x?}", stringify!($name), $arg)
- };
- ($name1:ident, $arg1:tt, $($name:ident, $arg:tt),*) => {
- format_args!("{}: {:x?}, {}", stringify!($name1), $arg1, format_expand!($($name, $arg),*))
- }
- }
- macro_rules! syscall32_call {
- ($is:ident, $handler:ident, $($arg:ident: $type:ty),*) => {{
- use $crate::kernel::syscall::{MapArgument, MapArgumentImpl, arg_register};
- #[allow(unused_imports)]
- use $crate::kernel::syscall::{MapReturnValue, format_expand};
- #[allow(unused_imports)]
- use $crate::{kernel::task::Thread, println_trace};
- $(
- let $arg: $type =
- MapArgumentImpl::map_arg(arg_register!(${index()}, $is));
- )*
- println_trace!(
- "trace_syscall",
- "tid{}: {}({}) => {{",
- Thread::current().tid,
- stringify!($handler),
- format_expand!($($arg, $arg),*),
- );
- let result = $handler($($arg),*);
- println_trace!(
- "trace_syscall",
- "tid{}: {}({}) => }} = {:x?}",
- Thread::current().tid,
- stringify!($handler),
- format_expand!($($arg, $arg),*),
- result
- );
- match result {
- Ok(val) => MapReturnValue::map_ret(val),
- Err(err) => (-(err as i32)) as usize,
- }
- }};
- }
- macro_rules! define_syscall32 {
- ($name:ident, $handler:ident) => {
- fn $name(_int_stack: &mut $crate::kernel::syscall::arch::InterruptContext,
- _: &mut ::arch::ExtendedContext) -> usize {
- use $crate::kernel::syscall::MapReturnValue;
- match $handler() {
- Ok(val) => MapReturnValue::map_ret(val),
- Err(err) => (-(err as i32)) as usize,
- }
- }
- };
- ($name:ident, $handler:ident, $($arg:ident: $argt:ty),*) => {
- fn $name(
- int_stack: &mut $crate::kernel::syscall::arch::InterruptContext,
- _: &mut ::arch::ExtendedContext) -> usize {
- use $crate::kernel::syscall::syscall32_call;
- syscall32_call!(int_stack, $handler, $($arg: $argt),*)
- }
- };
- }
- macro_rules! register_syscall {
- ($no:expr, $name:ident) => {
- $crate::kernel::syscall::register_syscall_handler(
- $no,
- concat_idents!(sys_, $name),
- stringify!($name),
- );
- };
- }
- use super::task::Thread;
- pub(self) use {arg_register, define_syscall32, format_expand, register_syscall, syscall32_call};
- #[allow(dead_code)]
- pub(self) struct SyscallHandler {
- handler: fn(&mut InterruptContext, &mut ExtendedContext) -> usize,
- name: &'static str,
- }
- pub(self) fn register_syscall_handler(
- no: usize,
- handler: fn(&mut InterruptContext, &mut ExtendedContext) -> usize,
- name: &'static str,
- ) {
- // SAFETY: `SYSCALL_HANDLERS` is never modified after initialization.
- #[allow(static_mut_refs)]
- let syscall = unsafe { SYSCALL_HANDLERS.get_mut(no) }.unwrap();
- assert!(
- syscall.replace(SyscallHandler { handler, name }).is_none(),
- "Syscall {} is already registered",
- no
- );
- }
- pub fn register_syscalls() {
- file_rw::register();
- procops::register();
- mm::register();
- net::register();
- sysinfo::register();
- }
- const SYSCALL_HANDLERS_SIZE: usize = 404;
- static mut SYSCALL_HANDLERS: [Option<SyscallHandler>; SYSCALL_HANDLERS_SIZE] =
- [const { None }; SYSCALL_HANDLERS_SIZE];
- pub fn handle_syscall32(
- no: usize,
- int_stack: &mut InterruptContext,
- ext_ctx: &mut ExtendedContext,
- ) {
- // SAFETY: `SYSCALL_HANDLERS` are never modified after initialization.
- #[allow(static_mut_refs)]
- let syscall = unsafe { SYSCALL_HANDLERS.get(no) }.and_then(Option::as_ref);
- match syscall {
- None => {
- println_warn!("Syscall {no}({no:#x}) isn't implemented.");
- ProcessList::kill_current(Signal::SIGSYS);
- }
- Some(handler) => {
- arch::enable_irqs();
- let retval = (handler.handler)(int_stack, ext_ctx);
- // SAFETY: `int_stack` is always valid.
- int_stack.rax = retval as u64;
- int_stack.r8 = 0;
- int_stack.r9 = 0;
- int_stack.r10 = 0;
- int_stack.r11 = 0;
- int_stack.r12 = 0;
- int_stack.r13 = 0;
- int_stack.r14 = 0;
- int_stack.r15 = 0;
- }
- }
- if Thread::current().signal_list.has_pending_signal() {
- Thread::current().signal_list.handle(int_stack, ext_ctx);
- }
- }
|