diff --git a/Cargo.lock b/Cargo.lock index 35614fa766..1a65381e18 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -123,12 +123,15 @@ dependencies = [ name = "arceos-monolithic" version = "0.1.0" dependencies = [ + "arceos_posix_api", "axconfig", + "axerrno", "axhal", "axlog", "axruntime", "axstd", "axtask", + "crate_interface", "memory_addr", ] diff --git a/modules/axhal/src/arch/x86_64/context.rs b/modules/axhal/src/arch/x86_64/context.rs index bad85de9c2..b40f4c1ad6 100644 --- a/modules/axhal/src/arch/x86_64/context.rs +++ b/modules/axhal/src/arch/x86_64/context.rs @@ -40,6 +40,36 @@ pub struct TrapFrame { } impl TrapFrame { + /// Gets the 0th syscall argument. + pub const fn arg0(&self) -> usize { + self.rdi as _ + } + + /// Gets the 1st syscall argument. + pub const fn arg1(&self) -> usize { + self.rsi as _ + } + + /// Gets the 2nd syscall argument. + pub const fn arg2(&self) -> usize { + self.rdx as _ + } + + /// Gets the 3rd syscall argument. + pub const fn arg3(&self) -> usize { + self.r10 as _ + } + + /// Gets the 4th syscall argument. + pub const fn arg4(&self) -> usize { + self.r8 as _ + } + + /// Gets the 5th syscall argument. + pub const fn arg5(&self) -> usize { + self.r9 as _ + } + /// Whether the trap is from userspace. pub const fn is_user(&self) -> bool { self.cs & 0b11 == 3 diff --git a/modules/axhal/src/arch/x86_64/syscall.rs b/modules/axhal/src/arch/x86_64/syscall.rs index fb57432362..8d6a774812 100644 --- a/modules/axhal/src/arch/x86_64/syscall.rs +++ b/modules/axhal/src/arch/x86_64/syscall.rs @@ -16,10 +16,7 @@ core::arch::global_asm!( #[no_mangle] pub(super) fn x86_syscall_handler(tf: &mut TrapFrame) { - info!( - "syscall @ {:#x}: {} [{}, {}, {}, {}]", - tf.rip, tf.rax, tf.rdi, tf.rsi, tf.rdx, tf.rdx, - ); + tf.rax = crate::trap::handle_syscall(tf.rax as usize, tf) as u64; } /// Initializes syscall support and setups the syscall handler. diff --git a/modules/axhal/src/trap.rs b/modules/axhal/src/trap.rs index 5fc9f76dcc..14f4dcfb5c 100644 --- a/modules/axhal/src/trap.rs +++ b/modules/axhal/src/trap.rs @@ -2,6 +2,16 @@ use crate_interface::{call_interface, def_interface}; +use crate::arch::TrapFrame; + +/// Syscall handler interface. +#[def_interface] +pub trait SyscallHandler { + /// Handles a system call with the given number, arguments are stored in + /// [`TrapFrame`]. + fn handle_syscall(syscall_num: usize, tf: &TrapFrame) -> isize; +} + /// Trap handler interface. /// /// This trait is defined with the [`#[def_interface]`][1] attribute. Users @@ -21,3 +31,9 @@ pub trait TrapHandler { pub(crate) fn handle_irq_extern(irq_num: usize) { call_interface!(TrapHandler::handle_irq, irq_num); } + +/// Call the external syscall handler. +#[allow(dead_code)] +pub(crate) fn handle_syscall(syscall_num: usize, tf: &TrapFrame) -> isize { + call_interface!(SyscallHandler::handle_syscall, syscall_num, tf) +} diff --git a/variants/monolithic/Cargo.toml b/variants/monolithic/Cargo.toml index ae79bbc73d..acb02ab10a 100644 --- a/variants/monolithic/Cargo.toml +++ b/variants/monolithic/Cargo.toml @@ -5,9 +5,14 @@ edition = "2021" [dependencies] axstd = { path = "../../ulib/axstd", features = ["paging"] } +arceos_posix_api = { path = "../../api/arceos_posix_api" } + axhal = { path = "../../modules/axhal", features = ["uspace"] } axlog = { path = "../../modules/axlog" } axconfig = { path = "../../modules/axconfig" } axtask = { path = "../../modules/axtask" } axruntime = { path = "../../modules/axruntime", features = ["multitask"] } + +axerrno = { path = "../../crates/axerrno" } memory_addr = { path = "../../crates/memory_addr" } +crate_interface = { path = "../../crates/crate_interface" } diff --git a/variants/monolithic/src/main.rs b/variants/monolithic/src/main.rs index e06a472156..fb0a2dd9e7 100644 --- a/variants/monolithic/src/main.rs +++ b/variants/monolithic/src/main.rs @@ -6,11 +6,12 @@ extern crate axlog; extern crate alloc; extern crate axstd; +mod syscall; mod task; use memory_addr::{PhysAddr, VirtAddr}; -use axhal::arch::{TrapFrame, UspaceContext}; +use axhal::arch::UspaceContext; use axhal::mem::virt_to_phys; use axhal::paging::MappingFlags; use axruntime::KERNEL_PAGE_TABLE; @@ -24,14 +25,14 @@ fn app_main(arg0: usize) { core::arch::asm!( "2:", "int3", + "mov rax, r12", "syscall", - "add rax, 1", + "add r12, 1", "jmp 2b", - in("rax") arg0, + in("r12") arg0, in("rdi") 2, in("rsi") 3, in("rdx") 3, - in("rcx") 3, options(nostack, nomem) ) } @@ -59,15 +60,6 @@ fn spawn_user_task(page_table_root: PhysAddr, uctx: UspaceContext) -> AxTaskRef axtask::spawn_task(task) } -fn sys_clone(tf: &TrapFrame, newsp: usize) -> usize { - let page_table_root = axtask::current().task_ext().page_table_root; - let mut uctx = UspaceContext::from(tf); - uctx.set_sp(newsp); - uctx.set_ret_reg(0); - let new_task = spawn_user_task(page_table_root, uctx); - new_task.id().as_u64() as usize -} - fn run_apps() -> ! { let entry = VirtAddr::from(app_main as usize); let entry_paddr_align = virt_to_phys(entry.align_down_4k()); @@ -98,7 +90,7 @@ fn run_apps() -> ! { ustack_vaddr, ustack_paddr, 4096, - MappingFlags::READ | MappingFlags::EXECUTE | MappingFlags::USER, + MappingFlags::READ | MappingFlags::WRITE | MappingFlags::USER, false, ) .unwrap(); diff --git a/variants/monolithic/src/syscall.rs b/variants/monolithic/src/syscall.rs new file mode 100644 index 0000000000..c4be646990 --- /dev/null +++ b/variants/monolithic/src/syscall.rs @@ -0,0 +1,44 @@ +#![allow(dead_code)] + +use arceos_posix_api as api; +use axerrno::LinuxError; +use axhal::arch::{TrapFrame, UspaceContext}; +use axhal::trap::SyscallHandler; +use axtask::TaskExtRef; + +const SYS_READ: usize = 0; +const SYS_WRITE: usize = 1; +const SYS_SCHED_YIELD: usize = 24; +const SYS_GETPID: usize = 39; +const SYS_CLONE: usize = 56; +const SYS_FORK: usize = 57; +const SYS_EXECVE: usize = 59; +const SYS_EXIT: usize = 60; + +fn sys_clone(tf: &TrapFrame, newsp: usize) -> usize { + let page_table_root = axtask::current().task_ext().page_table_root; + let mut uctx = UspaceContext::from(tf); + uctx.set_sp(newsp); + uctx.set_ret_reg(0); + let new_task = super::spawn_user_task(page_table_root, uctx); + new_task.id().as_u64() as usize +} + +struct SyscallHandlerImpl; + +#[crate_interface::impl_interface] +impl SyscallHandler for SyscallHandlerImpl { + fn handle_syscall(syscall_num: usize, tf: &TrapFrame) -> isize { + let ret = match syscall_num { + SYS_READ => api::sys_read(tf.arg0() as _, tf.arg1() as _, tf.arg2() as _), + SYS_WRITE => api::sys_write(tf.arg0() as _, tf.arg1() as _, tf.arg2() as _), + SYS_SCHED_YIELD => api::sys_sched_yield() as isize, + SYS_GETPID => api::sys_getpid() as isize, + _ => { + warn!("Unimplemented syscall: {}", syscall_num); + -LinuxError::ENOSYS.code() as _ + } + }; + ret + } +}