Skip to content

Commit

Permalink
feat(syscall): add sys_uname syscall
Browse files Browse the repository at this point in the history
  • Loading branch information
ChenRuiwei committed Apr 8, 2024
1 parent 7f1e368 commit c88bc4a
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 22 deletions.
1 change: 1 addition & 0 deletions kernel/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#![feature(sync_unsafe_cell)]
#![feature(stdsimd)]
#![feature(riscv_ext_intrinsics)]
#![allow(unused)]

use alloc::fmt;

Expand Down
3 changes: 3 additions & 0 deletions kernel/src/mm/memory_space/vm_area.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ impl Drop for VmArea {

impl VmArea {
/// Construct a new vma
///
/// [start_va, end_va)
pub fn new(
start_va: VirtAddr,
end_va: VirtAddr,
Expand All @@ -96,6 +98,7 @@ impl VmArea {
) -> Self {
let start_vpn: VirtPageNum = start_va.floor();
let end_vpn: VirtPageNum = end_va.ceil();
log::trace!("new vpn_range: {:?}, {:?}", start_vpn, end_vpn);
Self {
vpn_range: VPNRange::new(start_vpn, end_vpn),
frames: Vec::new(),
Expand Down
1 change: 1 addition & 0 deletions kernel/src/mm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub use memory::page_table::PageTable;
use memory::{frame, heap, VirtAddr};
pub use memory_space::{activate_kernel_space, MemorySpace};
pub use page::Page;
pub use user_ptr::{UserInOutPtr, UserReadPtr, UserWritePtr};

use self::memory_space::vm_area::MapPermission;
use crate::mm;
Expand Down
10 changes: 8 additions & 2 deletions kernel/src/mm/user_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,14 @@ impl Task {

match f(curr_vaddr, len) {
ControlFlow::Continue(_) => {}
ControlFlow::Break(None) => return Ok(()),
ControlFlow::Break(Some(e)) => return Err(e),
ControlFlow::Break(None) => {
set_kernel_trap_entry();
return Ok(());
}
ControlFlow::Break(Some(e)) => {
set_kernel_trap_entry();
return Err(e);
}
}

readable_len += len;
Expand Down
6 changes: 5 additions & 1 deletion kernel/src/syscall/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
use systype::SyscallResult;

use crate::{mm::UserWritePtr, processor::hart::current_task};

// copy from sys/utsname.h
#[derive(Debug, Clone, Copy)]
#[repr(C)]
Expand Down Expand Up @@ -44,5 +46,7 @@ impl UtsName {

/// uname() returns system information in the structure pointed to by buf.
pub fn sys_uname(buf: usize) -> SyscallResult {
todo!()
let uts = UserWritePtr::<UtsName>::from(buf);
uts.write(current_task(), UtsName::default())?;
Ok(0)
}
5 changes: 5 additions & 0 deletions kernel/src/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use log::error;
use process::*;
use systype::SyscallResult;

use self::misc::sys_uname;
use crate::processor::{
env::SumGuard,
hart::{current_task, current_trap_cx},
Expand All @@ -34,8 +35,12 @@ macro_rules! sys_handler {
/// Handle syscall exception with `syscall_id` and other arguments.
pub async fn syscall(syscall_id: usize, args: [usize; 6]) -> SyscallResult {
match syscall_id {
// Process
SYSCALL_EXIT => sys_handler!(sys_exit, (args[0] as i32)),
// Fs
SYSCALL_WRITE => sys_handler!(sys_write, (args[0], args[1], args[2]), await),
// Misc
SYSCALL_UNAME => sys_handler!(sys_uname, (args[0])),
_ => {
error!("Unsupported syscall_id: {}", syscall_id);
Ok(0)
Expand Down
60 changes: 49 additions & 11 deletions kernel/src/trap/kernel_trap.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use arch::interrupts::set_trap_handler_vector;
use irq_count::IRQ_COUNTER;
use riscv::register::{
scause::{self, Interrupt, Trap},
scause::{self, Exception, Interrupt, Scause, Trap},
sepc, stval, stvec,
};
use systype::SysError;

use crate::{processor::hart::local_hart, when_debug};

Expand Down Expand Up @@ -37,7 +38,6 @@ extern "C" {
fn __user_rw_trap_vector();
}

#[inline(always)]
pub fn set_kernel_user_rw_trap() {
let trap_vaddr = __user_rw_trap_vector as usize;
set_trap_handler_vector(trap_vaddr);
Expand All @@ -48,29 +48,67 @@ pub fn set_kernel_user_rw_trap() {
);
}

#[inline(always)]
pub fn will_read_fail(vaddr: usize) -> bool {
when_debug!({
let curr_stvec = stvec::read().address();
debug_assert!(curr_stvec == __user_rw_trap_vector as usize);
debug_assert_eq!(curr_stvec, __user_rw_trap_vector as usize);
});

extern "C" {
fn __try_read_user(vaddr: usize) -> bool;
fn __try_read_user(ptr: usize) -> TryOpRet;
}
let try_op_ret = unsafe { __try_read_user(vaddr) };
match try_op_ret.flag() {
0 => false,
_ => {
when_debug!({
let scause: Scause = try_op_ret.scause();
match scause.cause() {
scause::Trap::Interrupt(i) => unreachable!("{:?}", i),
scause::Trap::Exception(e) => assert_eq!(e, Exception::LoadPageFault),
};
});
true
}
}

unsafe { __try_read_user(vaddr) }
}

#[inline(always)]
pub fn will_write_fail(vaddr: usize) -> bool {
when_debug!({
let curr_stvec = stvec::read().address();
debug_assert!(curr_stvec == __user_rw_trap_vector as usize);
});

extern "C" {
fn __try_write_user(vaddr: usize) -> bool;
fn __try_write_user(vaddr: usize) -> TryOpRet;
}
let try_op_ret = unsafe { __try_write_user(vaddr) };
match try_op_ret.flag() {
0 => false,
_ => {
when_debug!({
let scause: Scause = try_op_ret.scause();
match scause.cause() {
scause::Trap::Interrupt(i) => unreachable!("{:?}", i),
scause::Trap::Exception(e) => assert_eq!(e, Exception::LoadPageFault),
};
});
true
}
}
}

#[repr(C)]
struct TryOpRet {
flag: usize,
scause: usize,
}

impl TryOpRet {
pub fn flag(&self) -> usize {
self.flag
}

pub fn scause(&self) -> Scause {
unsafe { core::mem::transmute(self.scause) }
}
unsafe { __try_write_user(vaddr) }
}
19 changes: 12 additions & 7 deletions kernel/src/trap/trap.asm
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
.globl __trap_from_user
.globl __return_to_user
.globl __trap_from_kernel
.globl __user_rw_trap_vector
.globl __user_rw_exception_entry
.globl __try_read_user
.globl __try_write_user
.align 2


Expand Down Expand Up @@ -141,19 +145,20 @@ __trap_from_kernel:
addi sp, sp, 17*8
sret


# arg: (user_ptr)
# return: (usize, usize)
# if a0 == 0, which means no exception happens
# if a0 == 1, which means exception happens, then we will treat a1 as scause
#
# Safety: need to set stvec to __user_rw_trap_vector and vector mode first
__try_read_user:
mv a1, a0
# 先将 a0 设置为 0
mv a0, zero
# 尝试读取用户空间的内存
# will trap into __user_rw_trap_vector if exception happens
# we don't care what value this lb will read
lb a1, 0(a1)
# 如果上条指令出现了缺页异常, 那么就会跳转到 __user_check_exception_entry
# 而后者会将 a0 设置为 1 并将 sepc + 4
# 于是在发生缺页异常时, a01, 否则为 0
ret

# 检查写入同理
__try_write_user:
mv a2, a0
mv a0, zero
Expand Down
2 changes: 1 addition & 1 deletion modules/memory/src/address/virt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ impl VirtAddr {
}
/// `VirtAddr`->`VirtPageNum`
pub fn ceil(&self) -> VirtPageNum {
(self.floor() + 1).into()
VirtPageNum((self.0 + PAGE_SIZE - 1) / PAGE_SIZE)
}
/// Get page offset
pub fn page_offset(&self) -> usize {
Expand Down
2 changes: 2 additions & 0 deletions user/src/bin/hello_world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

extern crate user_lib;

use alloc::string::String;

use user_lib::println;

#[no_mangle]
Expand Down

0 comments on commit c88bc4a

Please sign in to comment.