refactor syscall: move all context and functions to struct Syscall

toolchain_update
WangRunji 6 years ago
parent 08d10522ff
commit da58486be5

@ -15,7 +15,6 @@
use super::HEAP_ALLOCATOR;
pub use crate::arch::paging::*;
use crate::consts::{KERNEL_OFFSET, MEMORY_OFFSET};
use crate::process::process_unsafe;
use crate::sync::SpinNoIrqLock;
use alloc::boxed::Box;
use bitmap_allocator::BitAlloc;
@ -25,6 +24,7 @@ use log::*;
pub use rcore_memory::memory_set::{handler::*, MemoryArea, MemoryAttr};
use rcore_memory::paging::PageTable;
use rcore_memory::*;
use crate::process::current_thread;
pub type MemorySet = rcore_memory::memory_set::MemorySet<InactivePageTable0>;
@ -132,8 +132,12 @@ impl Drop for KernelStack {
pub fn handle_page_fault(addr: usize) -> bool {
debug!("page fault @ {:#x}", addr);
// This is safe as long as page fault never happens in page fault handler
unsafe { process_unsafe().vm.handle_page_fault(addr) }
// FIXME: fix racing caused by force_unlock
unsafe {
let thread = current_thread();
thread.proc.force_unlock();
thread.proc.lock().vm.handle_page_fault(addr)
}
}
pub fn init_heap() {

@ -109,25 +109,13 @@ static PROCESSORS: [Processor; MAX_CPU_NUM] = [
// Processor::new(), Processor::new(), Processor::new(), Processor::new(),
];
/// Get current process
pub fn process() -> MutexGuard<'static, Process, SpinNoIrq> {
current_thread().proc.lock()
}
/// Get current process, ignoring its lock
/// Only use this when necessary
pub unsafe fn process_unsafe() -> MutexGuard<'static, Process, SpinNoIrq> {
let thread = current_thread();
thread.proc.force_unlock();
thread.proc.lock()
}
/// Get current thread
///
/// FIXME: It's obviously unsafe to get &mut !
pub fn current_thread() -> &'static mut Thread {
use core::mem::transmute;
let (process, _): (&mut Thread, *const ()) = unsafe { transmute(processor().context()) };
/// `Thread` is a thread-local object.
/// It is safe to call this once, and pass `&mut Thread` as a function argument.
pub unsafe fn current_thread() -> &'static mut Thread {
// trick: force downcast from trait object
let (process, _): (&mut Thread, *const ()) = core::mem::transmute(processor().context());
process
}

@ -3,10 +3,11 @@ use super::*;
use rcore_memory::memory_set::handler::Linear;
use rcore_memory::memory_set::MemoryAttr;
/// Allocate this PCI device to user space
/// The kernel driver using the PCI device will be unloaded
#[cfg(target_arch = "x86_64")]
pub fn sys_map_pci_device(vendor: usize, product: usize) -> SysResult {
impl Syscall<'_> {
/// Allocate this PCI device to user space
/// The kernel driver using the PCI device will be unloaded
#[cfg(target_arch = "x86_64")]
pub fn sys_map_pci_device(&mut self, vendor: usize, product: usize) -> SysResult {
use crate::drivers::bus::pci;
info!(
"map_pci_device: vendor: {:x}, product: {:x}",
@ -21,7 +22,7 @@ pub fn sys_map_pci_device(vendor: usize, product: usize) -> SysResult {
// Get BAR0 memory
let (base, len) = pci::get_bar0_mem(tag).ok_or(SysError::ENOENT)?;
let mut proc = process();
let mut proc = self.process();
let virt_addr = proc.vm.find_free_area(0, len);
let attr = MemoryAttr::default().user();
proc.vm.push(
@ -32,17 +33,17 @@ pub fn sys_map_pci_device(vendor: usize, product: usize) -> SysResult {
"pci",
);
Ok(virt_addr)
}
}
#[cfg(not(target_arch = "x86_64"))]
pub fn sys_map_pci_device(vendor: usize, product: usize) -> SysResult {
#[cfg(not(target_arch = "x86_64"))]
pub fn sys_map_pci_device(&mut self, vendor: usize, product: usize) -> SysResult {
Err(SysError::ENOSYS)
}
}
/// Get start physical addresses of frames
/// mapped to a list of virtual addresses.
pub fn sys_get_paddr(vaddrs: *const u64, paddrs: *mut u64, count: usize) -> SysResult {
let mut proc = process();
/// Get start physical addresses of frames
/// mapped to a list of virtual addresses.
pub fn sys_get_paddr(&mut self, vaddrs: *const u64, paddrs: *mut u64, count: usize) -> SysResult {
let mut proc = self.process();
let vaddrs = unsafe { proc.vm.check_read_array(vaddrs, count)? };
let paddrs = unsafe { proc.vm.check_write_array(paddrs, count)? };
for i in 0..count {
@ -50,4 +51,5 @@ pub fn sys_get_paddr(vaddrs: *const u64, paddrs: *mut u64, count: usize) -> SysR
paddrs[i] = paddr as u64;
}
Ok(0)
}
}

@ -15,8 +15,9 @@ use bitvec::prelude::{BitSlice, BitVec, LittleEndian};
use super::*;
pub fn sys_read(fd: usize, base: *mut u8, len: usize) -> SysResult {
let mut proc = process();
impl Syscall<'_> {
pub fn sys_read(&mut self, fd: usize, base: *mut u8, len: usize) -> SysResult {
let mut proc = self.process();
if !proc.pid.is_init() {
// we trust pid 0 process
info!("read: fd: {}, base: {:?}, len: {:#x}", fd, base, len);
@ -25,10 +26,10 @@ pub fn sys_read(fd: usize, base: *mut u8, len: usize) -> SysResult {
let file_like = proc.get_file_like(fd)?;
let len = file_like.read(slice)?;
Ok(len)
}
}
pub fn sys_write(fd: usize, base: *const u8, len: usize) -> SysResult {
let mut proc = process();
pub fn sys_write(&mut self, fd: usize, base: *const u8, len: usize) -> SysResult {
let mut proc = self.process();
if !proc.pid.is_init() {
// we trust pid 0 process
info!("write: fd: {}, base: {:?}, len: {:#x}", fd, base, len);
@ -37,32 +38,32 @@ pub fn sys_write(fd: usize, base: *const u8, len: usize) -> SysResult {
let file_like = proc.get_file_like(fd)?;
let len = file_like.write(slice)?;
Ok(len)
}
}
pub fn sys_pread(fd: usize, base: *mut u8, len: usize, offset: usize) -> SysResult {
pub fn sys_pread(&mut self, fd: usize, base: *mut u8, len: usize, offset: usize) -> SysResult {
info!(
"pread: fd: {}, base: {:?}, len: {}, offset: {}",
fd, base, len, offset
);
let mut proc = process();
let mut proc = self.process();
let slice = unsafe { proc.vm.check_write_array(base, len)? };
let len = proc.get_file(fd)?.read_at(offset, slice)?;
Ok(len)
}
}
pub fn sys_pwrite(fd: usize, base: *const u8, len: usize, offset: usize) -> SysResult {
pub fn sys_pwrite(&mut self, fd: usize, base: *const u8, len: usize, offset: usize) -> SysResult {
info!(
"pwrite: fd: {}, base: {:?}, len: {}, offset: {}",
fd, base, len, offset
);
let mut proc = process();
let mut proc = self.process();
let slice = unsafe { proc.vm.check_read_array(base, len)? };
let len = proc.get_file(fd)?.write_at(offset, slice)?;
Ok(len)
}
}
pub fn sys_ppoll(ufds: *mut PollFd, nfds: usize, timeout: *const TimeSpec) -> SysResult {
let proc = process();
pub fn sys_ppoll(&mut self, ufds: *mut PollFd, nfds: usize, timeout: *const TimeSpec) -> SysResult {
let proc = self.process();
let timeout_msecs = if timeout.is_null() {
1 << 31 // infinity
} else {
@ -71,11 +72,11 @@ pub fn sys_ppoll(ufds: *mut PollFd, nfds: usize, timeout: *const TimeSpec) -> Sy
};
drop(proc);
sys_poll(ufds, nfds, timeout_msecs as usize)
}
self.sys_poll(ufds, nfds, timeout_msecs as usize)
}
pub fn sys_poll(ufds: *mut PollFd, nfds: usize, timeout_msecs: usize) -> SysResult {
let proc = process();
pub fn sys_poll(&mut self, ufds: *mut PollFd, nfds: usize, timeout_msecs: usize) -> SysResult {
let proc = self.process();
if !proc.pid.is_init() {
// we trust pid 0 process
info!(
@ -95,7 +96,7 @@ pub fn sys_poll(ufds: *mut PollFd, nfds: usize, timeout_msecs: usize) -> SysResu
let begin_time_ms = crate::trap::uptime_msec();
loop {
use PollEvents as PE;
let proc = process();
let proc = self.process();
let mut events = 0;
for poll in polls.iter_mut() {
poll.revents = PE::empty();
@ -131,21 +132,22 @@ pub fn sys_poll(ufds: *mut PollFd, nfds: usize, timeout_msecs: usize) -> SysResu
Condvar::wait_any(&[&STDIN.pushed, &(*SOCKET_ACTIVITY)]);
}
}
}
pub fn sys_select(
pub fn sys_select(
&mut self,
nfds: usize,
read: *mut u32,
write: *mut u32,
err: *mut u32,
timeout: *const TimeVal,
) -> SysResult {
) -> SysResult {
info!(
"select: nfds: {}, read: {:?}, write: {:?}, err: {:?}, timeout: {:?}",
nfds, read, write, err, timeout
);
let proc = process();
let proc = self.process();
let mut read_fds = FdSet::new(&proc.vm, read, nfds)?;
let mut write_fds = FdSet::new(&proc.vm, write, nfds)?;
let mut err_fds = FdSet::new(&proc.vm, err, nfds)?;
@ -165,7 +167,7 @@ pub fn sys_select(
let begin_time_ms = crate::trap::uptime_msec();
loop {
let proc = process();
let proc = self.process();
let mut events = 0;
for (&fd, file_like) in proc.files.iter() {
if fd >= nfds {
@ -207,14 +209,14 @@ pub fn sys_select(
Condvar::wait_any(&[&STDIN.pushed, &(*SOCKET_ACTIVITY)]);
}
}
}
pub fn sys_readv(fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResult {
pub fn sys_readv(&mut self, fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResult {
info!(
"readv: fd: {}, iov: {:?}, count: {}",
fd, iov_ptr, iov_count
);
let mut proc = process();
let mut proc = self.process();
let mut iovs = unsafe { IoVecs::check_and_new(iov_ptr, iov_count, &proc.vm, true)? };
// read all data to a buf
@ -224,10 +226,10 @@ pub fn sys_readv(fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResul
// copy data to user
iovs.write_all_from_slice(&buf[..len]);
Ok(len)
}
}
pub fn sys_writev(fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResult {
let mut proc = process();
pub fn sys_writev(&mut self, fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResult {
let mut proc = self.process();
if !proc.pid.is_init() {
// we trust pid 0 process
info!(
@ -243,14 +245,14 @@ pub fn sys_writev(fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResu
let file_like = proc.get_file_like(fd)?;
let len = file_like.write(buf.as_slice())?;
Ok(len)
}
}
pub fn sys_open(path: *const u8, flags: usize, mode: usize) -> SysResult {
sys_openat(AT_FDCWD, path, flags, mode)
}
pub fn sys_open(&mut self, path: *const u8, flags: usize, mode: usize) -> SysResult {
self.sys_openat(AT_FDCWD, path, flags, mode)
}
pub fn sys_openat(dir_fd: usize, path: *const u8, flags: usize, mode: usize) -> SysResult {
let mut proc = process();
pub fn sys_openat(&mut self, dir_fd: usize, path: *const u8, flags: usize, mode: usize) -> SysResult {
let mut proc = self.process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
let flags = OpenFlags::from_bits_truncate(flags);
info!(
@ -287,11 +289,11 @@ pub fn sys_openat(dir_fd: usize, path: *const u8, flags: usize, mode: usize) ->
let fd = proc.add_file(FileLike::File(file));
Ok(fd)
}
}
pub fn sys_close(fd: usize) -> SysResult {
pub fn sys_close(&mut self, fd: usize) -> SysResult {
info!("close: fd: {:?}", fd);
let mut proc = process();
let mut proc = self.process();
// for debugging
if cfg!(debug_assertions) {
@ -300,15 +302,15 @@ pub fn sys_close(fd: usize) -> SysResult {
proc.files.remove(&fd).ok_or(SysError::EBADF)?;
Ok(0)
}
}
pub fn sys_access(path: *const u8, mode: usize) -> SysResult {
sys_faccessat(AT_FDCWD, path, mode, 0)
}
pub fn sys_access(&mut self, path: *const u8, mode: usize) -> SysResult {
self.sys_faccessat(AT_FDCWD, path, mode, 0)
}
pub fn sys_faccessat(dirfd: usize, path: *const u8, mode: usize, flags: usize) -> SysResult {
pub fn sys_faccessat(&mut self, dirfd: usize, path: *const u8, mode: usize, flags: usize) -> SysResult {
// TODO: check permissions based on uid/gid
let proc = process();
let proc = self.process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
let flags = AtFlags::from_bits_truncate(flags);
if !proc.pid.is_init() {
@ -320,10 +322,10 @@ pub fn sys_faccessat(dirfd: usize, path: *const u8, mode: usize, flags: usize) -
}
let inode = proc.lookup_inode_at(dirfd, &path, !flags.contains(AtFlags::SYMLINK_NOFOLLOW))?;
Ok(0)
}
}
pub fn sys_getcwd(buf: *mut u8, len: usize) -> SysResult {
let proc = process();
pub fn sys_getcwd(&mut self, buf: *mut u8, len: usize) -> SysResult {
let proc = self.process();
if !proc.pid.is_init() {
// we trust pid 0 process
info!("getcwd: buf: {:?}, len: {:#x}", buf, len);
@ -334,24 +336,24 @@ pub fn sys_getcwd(buf: *mut u8, len: usize) -> SysResult {
}
unsafe { util::write_cstr(buf.as_mut_ptr(), &proc.cwd) }
Ok(buf.as_ptr() as usize)
}
}
pub fn sys_lstat(path: *const u8, stat_ptr: *mut Stat) -> SysResult {
sys_fstatat(AT_FDCWD, path, stat_ptr, AtFlags::SYMLINK_NOFOLLOW.bits())
}
pub fn sys_lstat(&mut self, path: *const u8, stat_ptr: *mut Stat) -> SysResult {
self.sys_fstatat(AT_FDCWD, path, stat_ptr, AtFlags::SYMLINK_NOFOLLOW.bits())
}
pub fn sys_fstat(fd: usize, stat_ptr: *mut Stat) -> SysResult {
pub fn sys_fstat(&mut self, fd: usize, stat_ptr: *mut Stat) -> SysResult {
info!("fstat: fd: {}, stat_ptr: {:?}", fd, stat_ptr);
let mut proc = process();
let mut proc = self.process();
let stat_ref = unsafe { proc.vm.check_write_ptr(stat_ptr)? };
let file = proc.get_file(fd)?;
let stat = Stat::from(file.metadata()?);
*stat_ref = stat;
Ok(0)
}
}
pub fn sys_fstatat(dirfd: usize, path: *const u8, stat_ptr: *mut Stat, flags: usize) -> SysResult {
let proc = process();
pub fn sys_fstatat(&mut self, dirfd: usize, path: *const u8, stat_ptr: *mut Stat, flags: usize) -> SysResult {
let proc = self.process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
let stat_ref = unsafe { proc.vm.check_write_ptr(stat_ptr)? };
let flags = AtFlags::from_bits_truncate(flags);
@ -364,18 +366,18 @@ pub fn sys_fstatat(dirfd: usize, path: *const u8, stat_ptr: *mut Stat, flags: us
let stat = Stat::from(inode.metadata()?);
*stat_ref = stat;
Ok(0)
}
}
pub fn sys_stat(path: *const u8, stat_ptr: *mut Stat) -> SysResult {
sys_fstatat(AT_FDCWD, path, stat_ptr, 0)
}
pub fn sys_stat(&mut self, path: *const u8, stat_ptr: *mut Stat) -> SysResult {
self.sys_fstatat(AT_FDCWD, path, stat_ptr, 0)
}
pub fn sys_readlink(path: *const u8, base: *mut u8, len: usize) -> SysResult {
sys_readlinkat(AT_FDCWD, path, base, len)
}
pub fn sys_readlink(&mut self, path: *const u8, base: *mut u8, len: usize) -> SysResult {
self.sys_readlinkat(AT_FDCWD, path, base, len)
}
pub fn sys_readlinkat(dirfd: usize, path: *const u8, base: *mut u8, len: usize) -> SysResult {
let proc = process();
pub fn sys_readlinkat(&mut self, dirfd: usize, path: *const u8, base: *mut u8, len: usize) -> SysResult {
let proc = self.process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
let slice = unsafe { proc.vm.check_write_array(base, len)? };
info!(
@ -391,9 +393,9 @@ pub fn sys_readlinkat(dirfd: usize, path: *const u8, base: *mut u8, len: usize)
} else {
Err(SysError::EINVAL)
}
}
}
pub fn sys_lseek(fd: usize, offset: i64, whence: u8) -> SysResult {
pub fn sys_lseek(&mut self, fd: usize, offset: i64, whence: u8) -> SysResult {
let pos = match whence {
SEEK_SET => SeekFrom::Start(offset as u64),
SEEK_END => SeekFrom::End(offset),
@ -402,44 +404,44 @@ pub fn sys_lseek(fd: usize, offset: i64, whence: u8) -> SysResult {
};
info!("lseek: fd: {}, pos: {:?}", fd, pos);
let mut proc = process();
let mut proc = self.process();
let file = proc.get_file(fd)?;
let offset = file.seek(pos)?;
Ok(offset as usize)
}
}
pub fn sys_fsync(fd: usize) -> SysResult {
pub fn sys_fsync(&mut self, fd: usize) -> SysResult {
info!("fsync: fd: {}", fd);
process().get_file(fd)?.sync_all()?;
self.process().get_file(fd)?.sync_all()?;
Ok(0)
}
}
pub fn sys_fdatasync(fd: usize) -> SysResult {
pub fn sys_fdatasync(&mut self, fd: usize) -> SysResult {
info!("fdatasync: fd: {}", fd);
process().get_file(fd)?.sync_data()?;
self.process().get_file(fd)?.sync_data()?;
Ok(0)
}
}
pub fn sys_truncate(path: *const u8, len: usize) -> SysResult {
let proc = process();
pub fn sys_truncate(&mut self, path: *const u8, len: usize) -> SysResult {
let proc = self.process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
info!("truncate: path: {:?}, len: {}", path, len);
proc.lookup_inode(&path)?.resize(len)?;
Ok(0)
}
}
pub fn sys_ftruncate(fd: usize, len: usize) -> SysResult {
pub fn sys_ftruncate(&mut self, fd: usize, len: usize) -> SysResult {
info!("ftruncate: fd: {}, len: {}", fd, len);
process().get_file(fd)?.set_len(len as u64)?;
self.process().get_file(fd)?.set_len(len as u64)?;
Ok(0)
}
}
pub fn sys_getdents64(fd: usize, buf: *mut LinuxDirent64, buf_size: usize) -> SysResult {
pub fn sys_getdents64(&mut self, fd: usize, buf: *mut LinuxDirent64, buf_size: usize) -> SysResult {
info!(
"getdents64: fd: {}, ptr: {:?}, buf_size: {}",
fd, buf, buf_size
);
let mut proc = process();
let mut proc = self.process();
let buf = unsafe { proc.vm.check_write_array(buf as *mut u8, buf_size)? };
let file = proc.get_file(fd)?;
let info = file.metadata()?;
@ -459,31 +461,31 @@ pub fn sys_getdents64(fd: usize, buf: *mut LinuxDirent64, buf_size: usize) -> Sy
}
}
Ok(writer.written_size)
}
}
pub fn sys_dup2(fd1: usize, fd2: usize) -> SysResult {
pub fn sys_dup2(&mut self, fd1: usize, fd2: usize) -> SysResult {
info!("dup2: from {} to {}", fd1, fd2);
let mut proc = process();
let mut proc = self.process();
// close fd2 first if it is opened
proc.files.remove(&fd2);
let file_like = proc.get_file_like(fd1)?.clone();
proc.files.insert(fd2, file_like);
Ok(fd2)
}
}
pub fn sys_ioctl(fd: usize, request: usize, arg1: usize, arg2: usize, arg3: usize) -> SysResult {
pub fn sys_ioctl(&mut self, fd: usize, request: usize, arg1: usize, arg2: usize, arg3: usize) -> SysResult {
info!(
"ioctl: fd: {}, request: {:x}, args: {} {} {}",
fd, request, arg1, arg2, arg3
);
let mut proc = process();
let mut proc = self.process();
let file_like = proc.get_file_like(fd)?;
file_like.ioctl(request, arg1, arg2, arg3)
}
}
pub fn sys_chdir(path: *const u8) -> SysResult {
let mut proc = process();
pub fn sys_chdir(&mut self, path: *const u8) -> SysResult {
let mut proc = self.process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
if !proc.pid.is_init() {
// we trust pid 0 process
@ -523,19 +525,20 @@ pub fn sys_chdir(path: *const u8) -> SysResult {
}
}
Ok(0)
}
}
pub fn sys_rename(oldpath: *const u8, newpath: *const u8) -> SysResult {
sys_renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath)
}
pub fn sys_rename(&mut self, oldpath: *const u8, newpath: *const u8) -> SysResult {
self.sys_renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath)
}
pub fn sys_renameat(
pub fn sys_renameat(
&mut self,
olddirfd: usize,
oldpath: *const u8,
newdirfd: usize,
newpath: *const u8,
) -> SysResult {
let mut proc = process();
) -> SysResult {
let mut proc = self.process();
let oldpath = unsafe { proc.vm.check_and_clone_cstr(oldpath)? };
let newpath = unsafe { proc.vm.check_and_clone_cstr(newpath)? };
info!(
@ -549,14 +552,14 @@ pub fn sys_renameat(
let new_dir_inode = proc.lookup_inode_at(newdirfd, new_dir_path, false)?;
old_dir_inode.move_(old_file_name, &new_dir_inode, new_file_name)?;
Ok(0)
}
}
pub fn sys_mkdir(path: *const u8, mode: usize) -> SysResult {
sys_mkdirat(AT_FDCWD, path, mode)
}
pub fn sys_mkdir(&mut self, path: *const u8, mode: usize) -> SysResult {
self.sys_mkdirat(AT_FDCWD, path, mode)
}
pub fn sys_mkdirat(dirfd: usize, path: *const u8, mode: usize) -> SysResult {
let proc = process();
pub fn sys_mkdirat(&mut self, dirfd: usize, path: *const u8, mode: usize) -> SysResult {
let proc = self.process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
// TODO: check pathname
info!(
@ -571,10 +574,10 @@ pub fn sys_mkdirat(dirfd: usize, path: *const u8, mode: usize) -> SysResult {
}
inode.create(file_name, FileType::Dir, mode as u32)?;
Ok(0)
}
}
pub fn sys_rmdir(path: *const u8) -> SysResult {
let proc = process();
pub fn sys_rmdir(&mut self, path: *const u8) -> SysResult {
let proc = self.process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
info!("rmdir: path: {:?}", path);
@ -586,20 +589,21 @@ pub fn sys_rmdir(path: *const u8) -> SysResult {
}
dir_inode.unlink(file_name)?;
Ok(0)
}
}
pub fn sys_link(oldpath: *const u8, newpath: *const u8) -> SysResult {
sys_linkat(AT_FDCWD, oldpath, AT_FDCWD, newpath, 0)
}
pub fn sys_link(&mut self, oldpath: *const u8, newpath: *const u8) -> SysResult {
self.sys_linkat(AT_FDCWD, oldpath, AT_FDCWD, newpath, 0)
}
pub fn sys_linkat(
pub fn sys_linkat(
&mut self,
olddirfd: usize,
oldpath: *const u8,
newdirfd: usize,
newpath: *const u8,
flags: usize,
) -> SysResult {
let proc = process();
) -> SysResult {
let proc = self.process();
let oldpath = unsafe { proc.vm.check_and_clone_cstr(oldpath)? };
let newpath = unsafe { proc.vm.check_and_clone_cstr(newpath)? };
let flags = AtFlags::from_bits_truncate(flags);
@ -613,14 +617,14 @@ pub fn sys_linkat(
let new_dir_inode = proc.lookup_inode_at(newdirfd, new_dir_path, true)?;
new_dir_inode.link(new_file_name, &inode)?;
Ok(0)
}
}
pub fn sys_unlink(path: *const u8) -> SysResult {
sys_unlinkat(AT_FDCWD, path, 0)
}
pub fn sys_unlink(&mut self, path: *const u8) -> SysResult {
self.sys_unlinkat(AT_FDCWD, path, 0)
}
pub fn sys_unlinkat(dirfd: usize, path: *const u8, flags: usize) -> SysResult {
let proc = process();
pub fn sys_unlinkat(&mut self, dirfd: usize, path: *const u8, flags: usize) -> SysResult {
let proc = self.process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
let flags = AtFlags::from_bits_truncate(flags);
info!(
@ -636,12 +640,12 @@ pub fn sys_unlinkat(dirfd: usize, path: *const u8, flags: usize) -> SysResult {
}
dir_inode.unlink(file_name)?;
Ok(0)
}
}
pub fn sys_pipe(fds: *mut u32) -> SysResult {
pub fn sys_pipe(&mut self, fds: *mut u32) -> SysResult {
info!("pipe: fds: {:?}", fds);
let mut proc = process();
let mut proc = self.process();
let fds = unsafe { proc.vm.check_write_array(fds, 2)? };
let (read, write) = Pipe::create_pair();
@ -671,24 +675,25 @@ pub fn sys_pipe(fds: *mut u32) -> SysResult {
info!("pipe: created rfd: {} wfd: {}", read_fd, write_fd);
Ok(0)
}
}
pub fn sys_sync() -> SysResult {
pub fn sys_sync(&mut self) -> SysResult {
ROOT_INODE.fs().sync()?;
Ok(0)
}
}
pub fn sys_sendfile(
pub fn sys_sendfile(
&mut self,
out_fd: usize,
in_fd: usize,
offset_ptr: *mut usize,
count: usize,
) -> SysResult {
) -> SysResult {
info!(
"sendfile:BEG out: {}, in: {}, offset_ptr: {:?}, count: {}",
out_fd, in_fd, offset_ptr, count
);
let proc = process();
let proc = self.process();
// We know it's save, pacify the borrow checker
let proc_cell = UnsafeCell::new(proc);
let in_file = unsafe { (*proc_cell.get()).get_file(in_fd)? };
@ -742,6 +747,7 @@ pub fn sys_sendfile(
out_fd, in_fd, offset_ptr, count, bytes_read, total_written
);
return Ok(total_written);
}
}
impl Process {

@ -8,14 +8,16 @@ use crate::memory::GlobalFrameAlloc;
use super::*;
pub fn sys_mmap(
impl Syscall<'_> {
pub fn sys_mmap(
&mut self,
mut addr: usize,
len: usize,
prot: usize,
flags: usize,
fd: usize,
offset: usize,
) -> SysResult {
) -> SysResult {
let prot = MmapProt::from_bits_truncate(prot);
let flags = MmapFlags::from_bits_truncate(flags);
info!(
@ -23,7 +25,7 @@ pub fn sys_mmap(
addr, len, prot, flags, fd, offset
);
let mut proc = process();
let mut proc = self.process();
if addr == 0 {
// although NULL can be a valid address
// but in C, NULL is regarded as allocation failure
@ -67,16 +69,16 @@ pub fn sys_mmap(
);
return Ok(addr);
}
}
}
pub fn sys_mprotect(addr: usize, len: usize, prot: usize) -> SysResult {
pub fn sys_mprotect(&mut self, addr: usize, len: usize, prot: usize) -> SysResult {
let prot = MmapProt::from_bits_truncate(prot);
info!(
"mprotect: addr={:#x}, size={:#x}, prot={:?}",
addr, len, prot
);
let mut proc = process();
let mut proc = self.process();
let attr = prot.to_attr();
// FIXME: properly set the attribute of the area
@ -89,15 +91,15 @@ pub fn sys_mprotect(addr: usize, len: usize, prot: usize) -> SysResult {
return Err(SysError::ENOMEM);
}
Ok(0)
}
}
pub fn sys_munmap(addr: usize, len: usize) -> SysResult {
pub fn sys_munmap(&mut self, addr: usize, len: usize) -> SysResult {
info!("munmap addr={:#x}, size={:#x}", addr, len);
let mut proc = process();
let mut proc = self.process();
proc.vm.pop_with_split(addr, addr + len);
Ok(0)
}
}
bitflags! {
pub struct MmapProt: usize {
/// Data cannot be accessed

@ -4,25 +4,26 @@ use crate::consts::USER_STACK_SIZE;
use core::mem::size_of;
use core::sync::atomic::{AtomicI32, Ordering};
pub fn sys_arch_prctl(code: i32, addr: usize, tf: &mut TrapFrame) -> SysResult {
impl Syscall<'_> {
#[cfg(target_arch = "x86_64")]
pub fn sys_arch_prctl(&mut self, code: i32, addr: usize) -> SysResult {
const ARCH_SET_FS: i32 = 0x1002;
match code {
#[cfg(target_arch = "x86_64")]
ARCH_SET_FS => {
info!("sys_arch_prctl: set FS to {:#x}", addr);
tf.fsbase = addr;
info!("sys_arch_prctl: set FSBASE to {:#x}", addr);
self.tf.fsbase = addr;
Ok(0)
}
_ => Err(SysError::EINVAL),
}
}
}
pub fn sys_uname(buf: *mut u8) -> SysResult {
pub fn sys_uname(&mut self, buf: *mut u8) -> SysResult {
info!("uname: buf: {:?}", buf);
let offset = 65;
let strings = ["rCore", "orz", "0.1.0", "1", "machine", "domain"];
let proc = process();
let proc = self.process();
let buf = unsafe { proc.vm.check_write_array(buf, strings.len() * offset)? };
for i in 0..strings.len() {
@ -31,32 +32,32 @@ pub fn sys_uname(buf: *mut u8) -> SysResult {
}
}
Ok(0)
}
}
pub fn sys_sched_getaffinity(pid: usize, size: usize, mask: *mut u32) -> SysResult {
pub fn sys_sched_getaffinity(&mut self, pid: usize, size: usize, mask: *mut u32) -> SysResult {
info!(
"sched_getaffinity: pid: {}, size: {}, mask: {:?}",
pid, size, mask
);
let proc = process();
let proc = self.process();
let mask = unsafe { proc.vm.check_write_array(mask, size / size_of::<u32>())? };
// we only have 4 cpu at most.
// so just set it.
mask[0] = 0b1111;
Ok(0)
}
}
pub fn sys_sysinfo(sys_info: *mut SysInfo) -> SysResult {
let proc = process();
pub fn sys_sysinfo(&mut self, sys_info: *mut SysInfo) -> SysResult {
let proc = self.process();
let sys_info = unsafe { proc.vm.check_write_ptr(sys_info)? };
let sysinfo = SysInfo::default();
*sys_info = sysinfo;
Ok(0)
}
}
pub fn sys_futex(uaddr: usize, op: u32, val: i32, timeout: *const TimeSpec) -> SysResult {
pub fn sys_futex(&mut self, uaddr: usize, op: u32, val: i32, timeout: *const TimeSpec) -> SysResult {
info!(
"futex: [{}] uaddr: {:#x}, op: {:#x}, val: {}, timeout_ptr: {:?}",
thread::current().id(),
@ -72,18 +73,18 @@ pub fn sys_futex(uaddr: usize, op: u32, val: i32, timeout: *const TimeSpec) -> S
if uaddr % size_of::<u32>() != 0 {
return Err(SysError::EINVAL);
}
let atomic = unsafe { process().vm.check_write_ptr(uaddr as *mut AtomicI32)? };
let atomic = unsafe { self.process().vm.check_write_ptr(uaddr as *mut AtomicI32)? };
let _timeout = if timeout.is_null() {
None
} else {
Some(unsafe { *process().vm.check_read_ptr(timeout)? })
Some(unsafe { *self.process().vm.check_read_ptr(timeout)? })
};
const OP_WAIT: u32 = 0;
const OP_WAKE: u32 = 1;
const OP_PRIVATE: u32 = 128;
let queue = process().get_futex(uaddr);
let queue = self.process().get_futex(uaddr);
match op & 0xf {
OP_WAIT => {
@ -104,10 +105,9 @@ pub fn sys_futex(uaddr: usize, op: u32, val: i32, timeout: *const TimeSpec) -> S
Err(SysError::ENOSYS)
}
}
}
}
const LINUX_REBOOT_CMD_HALT: u32 = 0xcdef0123;
pub fn sys_reboot(_magic: u32, magic2: u32, cmd: u32, _arg: *const u8) -> SysResult {
pub fn sys_reboot(&mut self, _magic: u32, magic2: u32, cmd: u32, _arg: *const u8) -> SysResult {
// we will skip verifying magic
if cmd == LINUX_REBOOT_CMD_HALT {
unsafe {
@ -115,37 +115,16 @@ pub fn sys_reboot(_magic: u32, magic2: u32, cmd: u32, _arg: *const u8) -> SysRes
}
}
Ok(0)
}
#[repr(C)]
#[derive(Debug, Default)]
pub struct SysInfo {
uptime: u64,
loads: [u64; 3],
totalram: u64,
freeram: u64,
sharedram: u64,
bufferram: u64,
totalswap: u64,
freeswap: u64,
procs: u16,
totalhigh: u64,
freehigh: u64,
mem_unit: u32,
}
const RLIMIT_STACK: usize = 3;
const RLIMIT_RSS: usize = 5;
const RLIMIT_NOFILE: usize = 7;
const RLIMIT_AS: usize = 9;
}
pub fn sys_prlimit64(
pub fn sys_prlimit64(
&mut self,
pid: usize,
resource: usize,
new_limit: *const RLimit,
old_limit: *mut RLimit,
) -> SysResult {
let proc = process();
) -> SysResult {
let proc = self.process();
info!(
"prlimit64: pid: {}, resource: {}, new_limit: {:x?}, old_limit: {:x?}",
pid, resource, new_limit, old_limit
@ -184,18 +163,11 @@ pub fn sys_prlimit64(
}
_ => Err(SysError::ENOSYS),
}
}
#[repr(C)]
#[derive(Debug, Default)]
pub struct RLimit {
cur: u64, // soft limit
max: u64, // hard limit
}
}
pub fn sys_getrandom(buf: *mut u8, len: usize, flag: u32) -> SysResult {
pub fn sys_getrandom(&mut self, buf: *mut u8, len: usize, flag: u32) -> SysResult {
//info!("getrandom: buf: {:?}, len: {:?}, falg {:?}", buf, len,flag);
let mut proc = process();
let mut proc = self.process();
let slice = unsafe { proc.vm.check_write_array(buf, len)? };
let mut i = 0;
for elm in slice {
@ -206,4 +178,36 @@ pub fn sys_getrandom(buf: *mut u8, len: usize, flag: u32) -> SysResult {
}
Ok(len)
}
}
const LINUX_REBOOT_CMD_HALT: u32 = 0xcdef0123;
#[repr(C)]
#[derive(Debug, Default)]
pub struct SysInfo {
uptime: u64,
loads: [u64; 3],
totalram: u64,
freeram: u64,
sharedram: u64,
bufferram: u64,
totalswap: u64,
freeswap: u64,
procs: u16,
totalhigh: u64,
freehigh: u64,
mem_unit: u32,
}
const RLIMIT_STACK: usize = 3;
const RLIMIT_RSS: usize = 5;
const RLIMIT_NOFILE: usize = 7;
const RLIMIT_AS: usize = 9;
#[repr(C)]
#[derive(Debug, Default)]
pub struct RLimit {
cur: u64, // soft limit
max: u64, // hard limit
}

@ -11,7 +11,7 @@ use crate::arch::cpu;
use crate::arch::interrupt::TrapFrame;
use crate::arch::syscall::*;
use crate::process::*;
use crate::sync::Condvar;
use crate::sync::{Condvar, SpinNoIrq, MutexGuard};
use crate::thread;
use crate::util;
@ -40,14 +40,33 @@ lazy_static! {
}
/// System call dispatcher
// This #[deny(unreachable_patterns)] checks if each match arm is defined
// See discussion in https://github.com/oscourse-tsinghua/rcore_plus/commit/17e644e54e494835f1a49b34b80c2c4f15ed0dbe.
#[deny(unreachable_patterns)]
pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
let thread = unsafe { current_thread() };
let mut syscall = Syscall { thread, tf };
syscall.syscall(id, args)
}
/// All context needed for syscall
struct Syscall<'a> {
thread: &'a mut Thread,
tf: &'a mut TrapFrame,
}
impl Syscall<'_> {
/// Get current process
pub fn process(&self) -> MutexGuard<'_, Process, SpinNoIrq> {
self.thread.proc.lock()
}
/// System call dispatcher
// This #[deny(unreachable_patterns)] checks if each match arm is defined
// See discussion in https://github.com/oscourse-tsinghua/rcore_plus/commit/17e644e54e494835f1a49b34b80c2c4f15ed0dbe.
#[deny(unreachable_patterns)]
fn syscall(&mut self, id: usize, args: [usize; 6]) -> isize {
#[cfg(feature = "profile")]
let begin_time = unsafe { core::arch::x86_64::_rdtsc() };
let cid = cpu::id();
let pid = process().pid.clone();
let pid = self.process().pid.clone();
let tid = processor().tid();
if !pid.is_init() {
// we trust pid 0 process
@ -59,85 +78,85 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
// And https://fedora.juszkiewicz.com.pl/syscalls.html.
let ret = match id {
// file
SYS_READ => sys_read(args[0], args[1] as *mut u8, args[2]),
SYS_WRITE => sys_write(args[0], args[1] as *const u8, args[2]),
SYS_OPENAT => sys_openat(args[0], args[1] as *const u8, args[2], args[3]),
SYS_CLOSE => sys_close(args[0]),
SYS_FSTAT => sys_fstat(args[0], args[1] as *mut Stat),
SYS_NEWFSTATAT => sys_fstatat(args[0], args[1] as *const u8, args[2] as *mut Stat, args[3]),
SYS_LSEEK => sys_lseek(args[0], args[1] as i64, args[2] as u8),
SYS_IOCTL => sys_ioctl(args[0], args[1], args[2], args[3], args[4]),
SYS_PREAD64 => sys_pread(args[0], args[1] as *mut u8, args[2], args[3]),
SYS_PWRITE64 => sys_pwrite(args[0], args[1] as *const u8, args[2], args[3]),
SYS_READV => sys_readv(args[0], args[1] as *const IoVec, args[2]),
SYS_WRITEV => sys_writev(args[0], args[1] as *const IoVec, args[2]),
SYS_SENDFILE => sys_sendfile(args[0], args[1], args[2] as *mut usize, args[3]),
SYS_FCNTL => unimplemented("fcntl", Ok(0)),
SYS_FLOCK => unimplemented("flock", Ok(0)),
SYS_FSYNC => sys_fsync(args[0]),
SYS_FDATASYNC => sys_fdatasync(args[0]),
SYS_TRUNCATE => sys_truncate(args[0] as *const u8, args[1]),
SYS_FTRUNCATE => sys_ftruncate(args[0], args[1]),
SYS_GETDENTS64 => sys_getdents64(args[0], args[1] as *mut LinuxDirent64, args[2]),
SYS_GETCWD => sys_getcwd(args[0] as *mut u8, args[1]),
SYS_CHDIR => sys_chdir(args[0] as *const u8),
SYS_RENAMEAT => sys_renameat(args[0], args[1] as *const u8, args[2], args[3] as *const u8),
SYS_MKDIRAT => sys_mkdirat(args[0], args[1] as *const u8, args[2]),
SYS_LINKAT => sys_linkat(
SYS_READ => self.sys_read(args[0], args[1] as *mut u8, args[2]),
SYS_WRITE => self.sys_write(args[0], args[1] as *const u8, args[2]),
SYS_OPENAT => self.sys_openat(args[0], args[1] as *const u8, args[2], args[3]),
SYS_CLOSE => self.sys_close(args[0]),
SYS_FSTAT => self.sys_fstat(args[0], args[1] as *mut Stat),
SYS_NEWFSTATAT => self.sys_fstatat(args[0], args[1] as *const u8, args[2] as *mut Stat, args[3]),
SYS_LSEEK => self.sys_lseek(args[0], args[1] as i64, args[2] as u8),
SYS_IOCTL => self.sys_ioctl(args[0], args[1], args[2], args[3], args[4]),
SYS_PREAD64 => self.sys_pread(args[0], args[1] as *mut u8, args[2], args[3]),
SYS_PWRITE64 => self.sys_pwrite(args[0], args[1] as *const u8, args[2], args[3]),
SYS_READV => self.sys_readv(args[0], args[1] as *const IoVec, args[2]),
SYS_WRITEV => self.sys_writev(args[0], args[1] as *const IoVec, args[2]),
SYS_SENDFILE => self.sys_sendfile(args[0], args[1], args[2] as *mut usize, args[3]),
SYS_FCNTL => self.unimplemented("fcntl", Ok(0)),
SYS_FLOCK => self.unimplemented("flock", Ok(0)),
SYS_FSYNC => self.sys_fsync(args[0]),
SYS_FDATASYNC => self.sys_fdatasync(args[0]),
SYS_TRUNCATE => self.sys_truncate(args[0] as *const u8, args[1]),
SYS_FTRUNCATE => self.sys_ftruncate(args[0], args[1]),
SYS_GETDENTS64 => self.sys_getdents64(args[0], args[1] as *mut LinuxDirent64, args[2]),
SYS_GETCWD => self.sys_getcwd(args[0] as *mut u8, args[1]),
SYS_CHDIR => self.sys_chdir(args[0] as *const u8),
SYS_RENAMEAT => self.sys_renameat(args[0], args[1] as *const u8, args[2], args[3] as *const u8),
SYS_MKDIRAT => self.sys_mkdirat(args[0], args[1] as *const u8, args[2]),
SYS_LINKAT => self.sys_linkat(
args[0],
args[1] as *const u8,
args[2],
args[3] as *const u8,
args[4],
),
SYS_UNLINKAT => sys_unlinkat(args[0], args[1] as *const u8, args[2]),
SYS_SYMLINKAT => unimplemented("symlinkat", Err(SysError::EACCES)),
SYS_UNLINKAT => self.sys_unlinkat(args[0], args[1] as *const u8, args[2]),
SYS_SYMLINKAT => self.unimplemented("symlinkat", Err(SysError::EACCES)),
SYS_READLINKAT => {
sys_readlinkat(args[0], args[1] as *const u8, args[2] as *mut u8, args[3])
self.sys_readlinkat(args[0], args[1] as *const u8, args[2] as *mut u8, args[3])
}
SYS_FCHMOD => unimplemented("fchmod", Ok(0)),
SYS_FCHMODAT => unimplemented("fchmodat", Ok(0)),
SYS_FCHOWN => unimplemented("fchown", Ok(0)),
SYS_FCHOWNAT => unimplemented("fchownat", Ok(0)),
SYS_FACCESSAT => sys_faccessat(args[0], args[1] as *const u8, args[2], args[3]),
SYS_DUP3 => sys_dup2(args[0], args[1]), // TODO: handle `flags`
SYS_PIPE2 => sys_pipe(args[0] as *mut u32), // TODO: handle `flags`
SYS_UTIMENSAT => unimplemented("utimensat", Ok(0)),
SYS_FCHMOD => self.unimplemented("fchmod", Ok(0)),
SYS_FCHMODAT => self.unimplemented("fchmodat", Ok(0)),
SYS_FCHOWN => self.unimplemented("fchown", Ok(0)),
SYS_FCHOWNAT => self.unimplemented("fchownat", Ok(0)),
SYS_FACCESSAT => self.sys_faccessat(args[0], args[1] as *const u8, args[2], args[3]),
SYS_DUP3 => self.sys_dup2(args[0], args[1]), // TODO: handle `flags`
SYS_PIPE2 => self.sys_pipe(args[0] as *mut u32), // TODO: handle `flags`
SYS_UTIMENSAT => self.unimplemented("utimensat", Ok(0)),
// io multiplexing
SYS_PPOLL => sys_ppoll(args[0] as *mut PollFd, args[1], args[2] as *const TimeSpec), // ignore sigmask
SYS_EPOLL_CREATE1 => unimplemented("epoll_create1", Err(SysError::ENOSYS)),
SYS_PPOLL => self.sys_ppoll(args[0] as *mut PollFd, args[1], args[2] as *const TimeSpec), // ignore sigmask
SYS_EPOLL_CREATE1 => self.unimplemented("epoll_create1", Err(SysError::ENOSYS)),
// file system
SYS_STATFS => unimplemented("statfs", Err(SysError::EACCES)),
SYS_FSTATFS => unimplemented("fstatfs", Err(SysError::EACCES)),
SYS_SYNC => sys_sync(),
SYS_MOUNT => unimplemented("mount", Err(SysError::EACCES)),
SYS_UMOUNT2 => unimplemented("umount2", Err(SysError::EACCES)),
SYS_STATFS => self.unimplemented("statfs", Err(SysError::EACCES)),
SYS_FSTATFS => self.unimplemented("fstatfs", Err(SysError::EACCES)),
SYS_SYNC => self.sys_sync(),
SYS_MOUNT => self.unimplemented("mount", Err(SysError::EACCES)),
SYS_UMOUNT2 => self.unimplemented("umount2", Err(SysError::EACCES)),
// memory
SYS_BRK => unimplemented("brk", Err(SysError::ENOMEM)),
SYS_MMAP => sys_mmap(args[0], args[1], args[2], args[3], args[4], args[5]),
SYS_MPROTECT => sys_mprotect(args[0], args[1], args[2]),
SYS_MUNMAP => sys_munmap(args[0], args[1]),
SYS_MADVISE => unimplemented("madvise", Ok(0)),
SYS_BRK => self.unimplemented("brk", Err(SysError::ENOMEM)),
SYS_MMAP => self.sys_mmap(args[0], args[1], args[2], args[3], args[4], args[5]),
SYS_MPROTECT => self.sys_mprotect(args[0], args[1], args[2]),
SYS_MUNMAP => self.sys_munmap(args[0], args[1]),
SYS_MADVISE => self.unimplemented("madvise", Ok(0)),
// signal
SYS_RT_SIGACTION => unimplemented("sigaction", Ok(0)),
SYS_RT_SIGPROCMASK => unimplemented("sigprocmask", Ok(0)),
SYS_SIGALTSTACK => unimplemented("sigaltstack", Ok(0)),
SYS_KILL => sys_kill(args[0], args[1]),
SYS_RT_SIGACTION => self.unimplemented("sigaction", Ok(0)),
SYS_RT_SIGPROCMASK => self.unimplemented("sigprocmask", Ok(0)),
SYS_SIGALTSTACK => self.unimplemented("sigaltstack", Ok(0)),
SYS_KILL => self.sys_kill(args[0], args[1]),
// schedule
SYS_SCHED_YIELD => sys_yield(),
SYS_SCHED_GETAFFINITY => sys_sched_getaffinity(args[0], args[1], args[2] as *mut u32),
SYS_SCHED_YIELD => self.sys_yield(),
SYS_SCHED_GETAFFINITY => self.sys_sched_getaffinity(args[0], args[1], args[2] as *mut u32),
// socket
SYS_SOCKET => sys_socket(args[0], args[1], args[2]),
SYS_CONNECT => sys_connect(args[0], args[1] as *const SockAddr, args[2]),
SYS_ACCEPT => sys_accept(args[0], args[1] as *mut SockAddr, args[2] as *mut u32),
SYS_ACCEPT4 => sys_accept(args[0], args[1] as *mut SockAddr, args[2] as *mut u32), // use accept for accept4
SYS_SENDTO => sys_sendto(
SYS_SOCKET => self.sys_socket(args[0], args[1], args[2]),
SYS_CONNECT => self.sys_connect(args[0], args[1] as *const SockAddr, args[2]),
SYS_ACCEPT => self.sys_accept(args[0], args[1] as *mut SockAddr, args[2] as *mut u32),
SYS_ACCEPT4 => self.sys_accept(args[0], args[1] as *mut SockAddr, args[2] as *mut u32), // use accept for accept4
SYS_SENDTO => self.sys_sendto(
args[0],
args[1] as *const u8,
args[2],
@ -145,7 +164,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
args[4] as *const SockAddr,
args[5],
),
SYS_RECVFROM => sys_recvfrom(
SYS_RECVFROM => self.sys_recvfrom(
args[0],
args[1] as *mut u8,
args[2],
@ -153,15 +172,15 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
args[4] as *mut SockAddr,
args[5] as *mut u32,
),
// SYS_SENDMSG => sys_sendmsg(),
SYS_RECVMSG => sys_recvmsg(args[0], args[1] as *mut MsgHdr, args[2]),
SYS_SHUTDOWN => sys_shutdown(args[0], args[1]),
SYS_BIND => sys_bind(args[0], args[1] as *const SockAddr, args[2]),
SYS_LISTEN => sys_listen(args[0], args[1]),
SYS_GETSOCKNAME => sys_getsockname(args[0], args[1] as *mut SockAddr, args[2] as *mut u32),
SYS_GETPEERNAME => sys_getpeername(args[0], args[1] as *mut SockAddr, args[2] as *mut u32),
SYS_SETSOCKOPT => sys_setsockopt(args[0], args[1], args[2], args[3] as *const u8, args[4]),
SYS_GETSOCKOPT => sys_getsockopt(
// SYS_SENDMSG => self.sys_sendmsg(),
SYS_RECVMSG => self.sys_recvmsg(args[0], args[1] as *mut MsgHdr, args[2]),
SYS_SHUTDOWN => self.sys_shutdown(args[0], args[1]),
SYS_BIND => self.sys_bind(args[0], args[1] as *const SockAddr, args[2]),
SYS_LISTEN => self.sys_listen(args[0], args[1]),
SYS_GETSOCKNAME => self.sys_getsockname(args[0], args[1] as *mut SockAddr, args[2] as *mut u32),
SYS_GETPEERNAME => self.sys_getpeername(args[0], args[1] as *mut SockAddr, args[2] as *mut u32),
SYS_SETSOCKOPT => self.sys_setsockopt(args[0], args[1], args[2], args[3] as *const u8, args[4]),
SYS_GETSOCKOPT => self.sys_getsockopt(
args[0],
args[1],
args[2],
@ -170,25 +189,23 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
),
// process
SYS_CLONE => sys_clone(
SYS_CLONE => self.sys_clone(
args[0],
args[1],
args[2] as *mut u32,
args[3] as *mut u32,
args[4],
tf,
),
SYS_EXECVE => sys_exec(
SYS_EXECVE => self.sys_exec(
args[0] as *const u8,
args[1] as *const *const u8,
args[2] as *const *const u8,
tf,
),
SYS_EXIT => sys_exit(args[0] as usize),
SYS_EXIT_GROUP => sys_exit_group(args[0]),
SYS_WAIT4 => sys_wait4(args[0] as isize, args[1] as *mut i32), // TODO: wait4
SYS_SET_TID_ADDRESS => sys_set_tid_address(args[0] as *mut u32),
SYS_FUTEX => sys_futex(
SYS_EXIT => self.sys_exit(args[0] as usize),
SYS_EXIT_GROUP => self.sys_exit_group(args[0]),
SYS_WAIT4 => self.sys_wait4(args[0] as isize, args[1] as *mut i32), // TODO: wait4
SYS_SET_TID_ADDRESS => self.sys_set_tid_address(args[0] as *mut u32),
SYS_FUTEX => self.sys_futex(
args[0],
args[1] as u32,
args[2] as i32,
@ -196,41 +213,41 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
),
// time
SYS_NANOSLEEP => sys_nanosleep(args[0] as *const TimeSpec),
SYS_SETITIMER => unimplemented("setitimer", Ok(0)),
SYS_GETTIMEOFDAY => sys_gettimeofday(args[0] as *mut TimeVal, args[1] as *const u8),
SYS_CLOCK_GETTIME => sys_clock_gettime(args[0], args[1] as *mut TimeSpec),
SYS_NANOSLEEP => self.sys_nanosleep(args[0] as *const TimeSpec),
SYS_SETITIMER => self.unimplemented("setitimer", Ok(0)),
SYS_GETTIMEOFDAY => self.sys_gettimeofday(args[0] as *mut TimeVal, args[1] as *const u8),
SYS_CLOCK_GETTIME => self.sys_clock_gettime(args[0], args[1] as *mut TimeSpec),
// system
SYS_GETPID => sys_getpid(),
SYS_GETTID => sys_gettid(),
SYS_UNAME => sys_uname(args[0] as *mut u8),
SYS_UMASK => unimplemented("umask", Ok(0o777)),
// SYS_GETRLIMIT => sys_getrlimit(),
// SYS_SETRLIMIT => sys_setrlimit(),
SYS_GETRUSAGE => sys_getrusage(args[0], args[1] as *mut RUsage),
SYS_SYSINFO => sys_sysinfo(args[0] as *mut SysInfo),
SYS_TIMES => sys_times(args[0] as *mut Tms),
SYS_GETUID => unimplemented("getuid", Ok(0)),
SYS_GETGID => unimplemented("getgid", Ok(0)),
SYS_SETUID => unimplemented("setuid", Ok(0)),
SYS_GETEUID => unimplemented("geteuid", Ok(0)),
SYS_GETEGID => unimplemented("getegid", Ok(0)),
SYS_SETPGID => unimplemented("setpgid", Ok(0)),
SYS_GETPPID => sys_getppid(),
SYS_SETSID => unimplemented("setsid", Ok(0)),
SYS_GETPGID => unimplemented("getpgid", Ok(0)),
SYS_GETGROUPS => unimplemented("getgroups", Ok(0)),
SYS_SETGROUPS => unimplemented("setgroups", Ok(0)),
SYS_SETPRIORITY => sys_set_priority(args[0]),
SYS_PRCTL => unimplemented("prctl", Ok(0)),
SYS_PRLIMIT64 => sys_prlimit64(
SYS_GETPID => self.sys_getpid(),
SYS_GETTID => self.sys_gettid(),
SYS_UNAME => self.sys_uname(args[0] as *mut u8),
SYS_UMASK => self.unimplemented("umask", Ok(0o777)),
// SYS_GETRLIMIT => self.sys_getrlimit(),
// SYS_SETRLIMIT => self.sys_setrlimit(),
SYS_GETRUSAGE => self.sys_getrusage(args[0], args[1] as *mut RUsage),
SYS_SYSINFO => self.sys_sysinfo(args[0] as *mut SysInfo),
SYS_TIMES => self.sys_times(args[0] as *mut Tms),
SYS_GETUID => self.unimplemented("getuid", Ok(0)),
SYS_GETGID => self.unimplemented("getgid", Ok(0)),
SYS_SETUID => self.unimplemented("setuid", Ok(0)),
SYS_GETEUID => self.unimplemented("geteuid", Ok(0)),
SYS_GETEGID => self.unimplemented("getegid", Ok(0)),
SYS_SETPGID => self.unimplemented("setpgid", Ok(0)),
SYS_GETPPID => self.sys_getppid(),
SYS_SETSID => self.unimplemented("setsid", Ok(0)),
SYS_GETPGID => self.unimplemented("getpgid", Ok(0)),
SYS_GETGROUPS => self.unimplemented("getgroups", Ok(0)),
SYS_SETGROUPS => self.unimplemented("setgroups", Ok(0)),
SYS_SETPRIORITY => self.sys_set_priority(args[0]),
SYS_PRCTL => self.unimplemented("prctl", Ok(0)),
SYS_PRLIMIT64 => self.sys_prlimit64(
args[0],
args[1],
args[2] as *const RLimit,
args[3] as *mut RLimit,
),
SYS_REBOOT => sys_reboot(
SYS_REBOOT => self.sys_reboot(
args[0] as u32,
args[1] as u32,
args[2] as u32,
@ -238,17 +255,17 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
),
// custom
SYS_MAP_PCI_DEVICE => sys_map_pci_device(args[0], args[1]),
SYS_GET_PADDR => sys_get_paddr(args[0] as *const u64, args[1] as *mut u64, args[2]),
//SYS_GETRANDOM => unimplemented("getrandom", Err(SysError::EINVAL)),
SYS_GETRANDOM => sys_getrandom(args[0] as *mut u8, args[1] as usize, args[2] as u32),
SYS_TKILL => unimplemented("tkill", Ok(0)),
SYS_MAP_PCI_DEVICE => self.sys_map_pci_device(args[0], args[1]),
SYS_GET_PADDR => self.sys_get_paddr(args[0] as *const u64, args[1] as *mut u64, args[2]),
//SYS_GETRANDOM => self.unimplemented("getrandom", Err(SysError::EINVAL)),
SYS_GETRANDOM => self.sys_getrandom(args[0] as *mut u8, args[1] as usize, args[2] as u32),
SYS_TKILL => self.unimplemented("tkill", Ok(0)),
_ => {
let ret = match () {
#[cfg(target_arch = "x86_64")]
() => x86_64_syscall(id, args, tf),
() => self.x86_64_syscall(id, args),
#[cfg(target_arch = "mips")]
() => mips_syscall(id, args, tf),
() => self.mips_syscall(id, args),
#[cfg(all(not(target_arch = "x86_64"), not(target_arch = "mips")))]
() => None,
};
@ -256,7 +273,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
ret
} else {
error!("unknown syscall id: {}, args: {:x?}", id, args);
crate::trap::error(tf);
crate::trap::error(self.tf);
}
}
};
@ -281,27 +298,27 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
Ok(code) => code as isize,
Err(err) => -(err as isize),
}
}
}
fn unimplemented(name: &str, ret: SysResult) -> SysResult {
fn unimplemented(&self, name: &str, ret: SysResult) -> SysResult {
warn!("{} is unimplemented", name);
ret
}
}
#[cfg(target_arch = "mips")]
fn mips_syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> Option<SysResult> {
#[cfg(target_arch = "mips")]
fn mips_syscall(&mut self, id: usize, args: [usize; 6],) -> Option<SysResult> {
let ret = match id {
SYS_OPEN => sys_open(args[0] as *const u8, args[1], args[2]),
SYS_POLL => sys_poll(args[0] as *mut PollFd, args[1], args[2]),
SYS_DUP2 => sys_dup2(args[0], args[1]),
SYS_FORK => sys_fork(tf),
SYS_MMAP2 => sys_mmap(args[0], args[1], args[2], args[3], args[4], args[5] * 4096),
SYS_FSTAT64 => sys_fstat(args[0], args[1] as *mut Stat),
SYS_LSTAT64 => sys_lstat(args[0] as *const u8, args[1] as *mut Stat),
SYS_STAT64 => sys_stat(args[0] as *const u8, args[1] as *mut Stat),
SYS_OPEN => self.sys_open(args[0] as *const u8, args[1], args[2]),
SYS_POLL => self.sys_poll(args[0] as *mut PollFd, args[1], args[2]),
SYS_DUP2 => self.sys_dup2(args[0], args[1]),
SYS_FORK => self.sys_fork(),
SYS_MMAP2 => self.sys_mmap(args[0], args[1], args[2], args[3], args[4], args[5] * 4096),
SYS_FSTAT64 => self.sys_fstat(args[0], args[1] as *mut Stat),
SYS_LSTAT64 => self.sys_lstat(args[0] as *const u8, args[1] as *mut Stat),
SYS_STAT64 => self.sys_stat(args[0] as *const u8, args[1] as *mut Stat),
SYS_PIPE => {
let fd_ptr = args[0] as *mut u32;
match sys_pipe(fd_ptr) {
match self.sys_pipe(fd_ptr) {
Ok(code) => {
unsafe {
tf.v0 = *fd_ptr as usize;
@ -312,7 +329,7 @@ fn mips_syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> Option<SysRe
Err(err) => Err(err),
}
}
SYS_FCNTL64 => unimplemented("fcntl64", Ok(0)),
SYS_FCNTL64 => self.unimplemented("fcntl64", Ok(0)),
SYS_SET_THREAD_AREA => {
info!("set_thread_area: tls: 0x{:x}", args[0]);
extern "C" {
@ -328,42 +345,43 @@ fn mips_syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> Option<SysRe
_ => return None,
};
Some(ret)
}
}
#[cfg(target_arch = "x86_64")]
fn x86_64_syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> Option<SysResult> {
#[cfg(target_arch = "x86_64")]
fn x86_64_syscall(&mut self, id: usize, args: [usize; 6]) -> Option<SysResult> {
let ret = match id {
SYS_OPEN => sys_open(args[0] as *const u8, args[1], args[2]),
SYS_STAT => sys_stat(args[0] as *const u8, args[1] as *mut Stat),
SYS_LSTAT => sys_lstat(args[0] as *const u8, args[1] as *mut Stat),
SYS_POLL => sys_poll(args[0] as *mut PollFd, args[1], args[2]),
SYS_ACCESS => sys_access(args[0] as *const u8, args[1]),
SYS_PIPE => sys_pipe(args[0] as *mut u32),
SYS_SELECT => sys_select(
SYS_OPEN => self.sys_open(args[0] as *const u8, args[1], args[2]),
SYS_STAT => self.sys_stat(args[0] as *const u8, args[1] as *mut Stat),
SYS_LSTAT => self.sys_lstat(args[0] as *const u8, args[1] as *mut Stat),
SYS_POLL => self.sys_poll(args[0] as *mut PollFd, args[1], args[2]),
SYS_ACCESS => self.sys_access(args[0] as *const u8, args[1]),
SYS_PIPE => self.sys_pipe(args[0] as *mut u32),
SYS_SELECT => self.sys_select(
args[0],
args[1] as *mut u32,
args[2] as *mut u32,
args[3] as *mut u32,
args[4] as *const TimeVal,
),
SYS_DUP2 => sys_dup2(args[0], args[1]),
SYS_ALARM => unimplemented("alarm", Ok(0)),
SYS_FORK => sys_fork(tf),
SYS_VFORK => sys_vfork(tf),
SYS_RENAME => sys_rename(args[0] as *const u8, args[1] as *const u8),
SYS_MKDIR => sys_mkdir(args[0] as *const u8, args[1]),
SYS_RMDIR => sys_rmdir(args[0] as *const u8),
SYS_LINK => sys_link(args[0] as *const u8, args[1] as *const u8),
SYS_UNLINK => sys_unlink(args[0] as *const u8),
SYS_READLINK => sys_readlink(args[0] as *const u8, args[1] as *mut u8, args[2]),
SYS_CHMOD => unimplemented("chmod", Ok(0)),
SYS_CHOWN => unimplemented("chown", Ok(0)),
SYS_ARCH_PRCTL => sys_arch_prctl(args[0] as i32, args[1], tf),
SYS_TIME => sys_time(args[0] as *mut u64),
SYS_EPOLL_CREATE => unimplemented("epoll_create", Err(SysError::ENOSYS)),
SYS_DUP2 => self.sys_dup2(args[0], args[1]),
SYS_ALARM => self.unimplemented("alarm", Ok(0)),
SYS_FORK => self.sys_fork(),
SYS_VFORK => self.sys_vfork(),
SYS_RENAME => self.sys_rename(args[0] as *const u8, args[1] as *const u8),
SYS_MKDIR => self.sys_mkdir(args[0] as *const u8, args[1]),
SYS_RMDIR => self.sys_rmdir(args[0] as *const u8),
SYS_LINK => self.sys_link(args[0] as *const u8, args[1] as *const u8),
SYS_UNLINK => self.sys_unlink(args[0] as *const u8),
SYS_READLINK => self.sys_readlink(args[0] as *const u8, args[1] as *mut u8, args[2]),
SYS_CHMOD => self.unimplemented("chmod", Ok(0)),
SYS_CHOWN => self.unimplemented("chown", Ok(0)),
SYS_ARCH_PRCTL => self.sys_arch_prctl(args[0] as i32, args[1]),
SYS_TIME => self.sys_time(args[0] as *mut u64),
SYS_EPOLL_CREATE => self.unimplemented("epoll_create", Err(SysError::ENOSYS)),
_ => return None,
};
Some(ret)
}
}
pub type SysResult = Result<usize, SysError>;

@ -12,15 +12,17 @@ use alloc::boxed::Box;
use core::cmp::min;
use core::mem::size_of;
use smoltcp::wire::*;
use crate::memory::MemorySet;
pub fn sys_socket(domain: usize, socket_type: usize, protocol: usize) -> SysResult {
impl Syscall<'_> {
pub fn sys_socket(&mut self, domain: usize, socket_type: usize, protocol: usize) -> SysResult {
let domain = AddressFamily::from(domain as u16);
let socket_type = SocketType::from(socket_type as u8 & SOCK_TYPE_MASK);
info!(
"socket: domain: {:?}, socket_type: {:?}, protocol: {}",
domain, socket_type, protocol
);
let mut proc = process();
let mut proc = self.process();
let socket: Box<dyn Socket> = match domain {
AddressFamily::Internet | AddressFamily::Unix => match socket_type {
SocketType::Stream => Box::new(TcpSocketState::new()),
@ -40,37 +42,39 @@ pub fn sys_socket(domain: usize, socket_type: usize, protocol: usize) -> SysResu
};
let fd = proc.add_file(FileLike::Socket(socket));
Ok(fd)
}
}
pub fn sys_setsockopt(
pub fn sys_setsockopt(
&mut self,
fd: usize,
level: usize,
optname: usize,
optval: *const u8,
optlen: usize,
) -> SysResult {
) -> SysResult {
info!(
"setsockopt: fd: {}, level: {}, optname: {}",
fd, level, optname
);
let mut proc = process();
let mut proc = self.process();
let data = unsafe { proc.vm.check_read_array(optval, optlen)? };
let socket = proc.get_socket(fd)?;
socket.setsockopt(level, optname, data)
}
}
pub fn sys_getsockopt(
pub fn sys_getsockopt(
&mut self,
fd: usize,
level: usize,
optname: usize,
optval: *mut u8,
optlen: *mut u32,
) -> SysResult {
) -> SysResult {
info!(
"getsockopt: fd: {}, level: {}, optname: {} optval: {:?} optlen: {:?}",
fd, level, optname, optval, optlen
);
let proc = process();
let proc = self.process();
let optlen = unsafe { proc.vm.check_write_ptr(optlen)? };
match level {
SOL_SOCKET => match optname {
@ -94,62 +98,64 @@ pub fn sys_getsockopt(
},
_ => Err(SysError::ENOPROTOOPT),
}
}
}
pub fn sys_connect(fd: usize, addr: *const SockAddr, addr_len: usize) -> SysResult {
pub fn sys_connect(&mut self, fd: usize, addr: *const SockAddr, addr_len: usize) -> SysResult {
info!(
"sys_connect: fd: {}, addr: {:?}, addr_len: {}",
fd, addr, addr_len
);
let mut proc = process();
let endpoint = sockaddr_to_endpoint(&mut proc, addr, addr_len)?;
let mut proc = self.process();
let endpoint = sockaddr_to_endpoint(&mut proc.vm, addr, addr_len)?;
let socket = proc.get_socket(fd)?;
socket.connect(endpoint)?;
Ok(0)
}
}
pub fn sys_sendto(
pub fn sys_sendto(
&mut self,
fd: usize,
base: *const u8,
len: usize,
_flags: usize,
addr: *const SockAddr,
addr_len: usize,
) -> SysResult {
) -> SysResult {
info!(
"sys_sendto: fd: {} base: {:?} len: {} addr: {:?} addr_len: {}",
fd, base, len, addr, addr_len
);
let mut proc = process();
let mut proc = self.process();
let slice = unsafe { proc.vm.check_read_array(base, len)? };
let endpoint = if addr.is_null() {
None
} else {
let endpoint = sockaddr_to_endpoint(&mut proc, addr, addr_len)?;
let endpoint = sockaddr_to_endpoint(&mut proc.vm, addr, addr_len)?;
info!("sys_sendto: sending to endpoint {:?}", endpoint);
Some(endpoint)
};
let socket = proc.get_socket(fd)?;
socket.write(&slice, endpoint)
}
}
pub fn sys_recvfrom(
pub fn sys_recvfrom(
&mut self,
fd: usize,
base: *mut u8,
len: usize,
flags: usize,
addr: *mut SockAddr,
addr_len: *mut u32,
) -> SysResult {
) -> SysResult {
info!(
"sys_recvfrom: fd: {} base: {:?} len: {} flags: {} addr: {:?} addr_len: {:?}",
fd, base, len, flags, addr, addr_len
);
let mut proc = process();
let mut proc = self.process();
let mut slice = unsafe { proc.vm.check_write_array(base, len)? };
let socket = proc.get_socket(fd)?;
@ -163,11 +169,11 @@ pub fn sys_recvfrom(
}
result
}
}
pub fn sys_recvmsg(fd: usize, msg: *mut MsgHdr, flags: usize) -> SysResult {
pub fn sys_recvmsg(&mut self, fd: usize, msg: *mut MsgHdr, flags: usize) -> SysResult {
info!("recvmsg: fd: {}, msg: {:?}, flags: {}", fd, msg, flags);
let mut proc = process();
let mut proc = self.process();
let hdr = unsafe { proc.vm.check_write_ptr(msg)? };
let mut iovs = unsafe { IoVecs::check_and_new(hdr.msg_iov, hdr.msg_iovlen, &proc.vm, true)? };
@ -184,45 +190,45 @@ pub fn sys_recvmsg(fd: usize, msg: *mut MsgHdr, flags: usize) -> SysResult {
}
}
result
}
}
pub fn sys_bind(fd: usize, addr: *const SockAddr, addr_len: usize) -> SysResult {
pub fn sys_bind(&mut self, fd: usize, addr: *const SockAddr, addr_len: usize) -> SysResult {
info!("sys_bind: fd: {} addr: {:?} len: {}", fd, addr, addr_len);
let mut proc = process();
let mut proc = self.process();
let mut endpoint = sockaddr_to_endpoint(&mut proc, addr, addr_len)?;
let mut endpoint = sockaddr_to_endpoint(&mut proc.vm, addr, addr_len)?;
info!("sys_bind: fd: {} bind to {:?}", fd, endpoint);
let socket = proc.get_socket(fd)?;
socket.bind(endpoint)
}
}
pub fn sys_listen(fd: usize, backlog: usize) -> SysResult {
pub fn sys_listen(&mut self, fd: usize, backlog: usize) -> SysResult {
info!("sys_listen: fd: {} backlog: {}", fd, backlog);
// smoltcp tcp sockets do not support backlog
// open multiple sockets for each connection
let mut proc = process();
let mut proc = self.process();
let socket = proc.get_socket(fd)?;
socket.listen()
}
}
pub fn sys_shutdown(fd: usize, how: usize) -> SysResult {
pub fn sys_shutdown(&mut self, fd: usize, how: usize) -> SysResult {
info!("sys_shutdown: fd: {} how: {}", fd, how);
let mut proc = process();
let mut proc = self.process();
let socket = proc.get_socket(fd)?;
socket.shutdown()
}
}
pub fn sys_accept(fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> SysResult {
pub fn sys_accept(&mut self, fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> SysResult {
info!(
"sys_accept: fd: {} addr: {:?} addr_len: {:?}",
fd, addr, addr_len
);
// smoltcp tcp sockets do not support backlog
// open multiple sockets for each connection
let mut proc = process();
let mut proc = self.process();
let socket = proc.get_socket(fd)?;
let (new_socket, remote_endpoint) = socket.accept()?;
@ -236,15 +242,15 @@ pub fn sys_accept(fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> SysResu
}
}
Ok(new_fd)
}
}
pub fn sys_getsockname(fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> SysResult {
pub fn sys_getsockname(&mut self, fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> SysResult {
info!(
"sys_getsockname: fd: {} addr: {:?} addr_len: {:?}",
fd, addr, addr_len
);
let mut proc = process();
let mut proc = self.process();
if addr.is_null() {
return Err(SysError::EINVAL);
@ -257,9 +263,9 @@ pub fn sys_getsockname(fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> Sy
sockaddr_in.write_to(&mut proc, addr, addr_len)?;
}
Ok(0)
}
}
pub fn sys_getpeername(fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> SysResult {
pub fn sys_getpeername(&mut self, fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> SysResult {
info!(
"sys_getpeername: fd: {} addr: {:?} addr_len: {:?}",
fd, addr, addr_len
@ -267,7 +273,7 @@ pub fn sys_getpeername(fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> Sy
// smoltcp tcp sockets do not support backlog
// open multiple sockets for each connection
let mut proc = process();
let mut proc = self.process();
if addr as usize == 0 {
return Err(SysError::EINVAL);
@ -280,6 +286,7 @@ pub fn sys_getpeername(fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> Sy
sockaddr_in.write_to(&mut proc, addr, addr_len)?;
}
Ok(0)
}
}
impl Process {
@ -390,14 +397,14 @@ impl From<Endpoint> for SockAddr {
/// Convert sockaddr to endpoint
// Check len is long enough
fn sockaddr_to_endpoint(
proc: &mut Process,
vm: &MemorySet,
addr: *const SockAddr,
len: usize,
) -> Result<Endpoint, SysError> {
if len < size_of::<u16>() {
return Err(SysError::EINVAL);
}
let addr = unsafe { proc.vm.check_read_ptr(addr)? };
let addr = unsafe { vm.check_read_ptr(addr)? };
unsafe {
match AddressFamily::from(addr.family) {
AddressFamily::Internet => {

@ -3,33 +3,34 @@
use super::*;
use crate::fs::INodeExt;
/// Fork the current process. Return the child's PID.
pub fn sys_fork(tf: &TrapFrame) -> SysResult {
let new_thread = current_thread().fork(tf);
impl Syscall<'_> {
/// Fork the current process. Return the child's PID.
pub fn sys_fork(&mut self) -> SysResult {
let new_thread = self.thread.fork(self.tf);
let pid = new_thread.proc.lock().pid.get();
let tid = processor().manager().add(new_thread);
processor().manager().detach(tid);
info!("fork: {} -> {}", thread::current().id(), pid);
Ok(pid)
}
}
pub fn sys_vfork(tf: &TrapFrame) -> SysResult {
sys_fork(tf)
}
pub fn sys_vfork(&mut self) -> SysResult {
self.sys_fork()
}
/// Create a new thread in the current process.
/// The new thread's stack pointer will be set to `newsp`,
/// and thread pointer will be set to `newtls`.
/// The child tid will be stored at both `parent_tid` and `child_tid`.
/// This is partially implemented for musl only.
pub fn sys_clone(
/// Create a new thread in the current process.
/// The new thread's stack pointer will be set to `newsp`,
/// and thread pointer will be set to `newtls`.
/// The child tid will be stored at both `parent_tid` and `child_tid`.
/// This is partially implemented for musl only.
pub fn sys_clone(
&mut self,
flags: usize,
newsp: usize,
parent_tid: *mut u32,
child_tid: *mut u32,
newtls: usize,
tf: &TrapFrame,
) -> SysResult {
) -> SysResult {
let clone_flags = CloneFlags::from_bits_truncate(flags);
info!(
"clone: flags: {:?} == {:#x}, newsp: {:#x}, parent_tid: {:?}, child_tid: {:?}, newtls: {:#x}",
@ -37,7 +38,7 @@ pub fn sys_clone(
);
if flags == 0x4111 || flags == 0x11 {
warn!("sys_clone is calling sys_fork instead, ignoring other args");
return sys_fork(tf);
return self.sys_fork();
}
if (flags != 0x7d0f00) && (flags != 0x5d0f00) {
//0x5d0f00 is the args from gcc of alpine linux
@ -48,9 +49,11 @@ pub fn sys_clone(
);
//return Err(SysError::ENOSYS);
}
let parent_tid_ref = unsafe { process().vm.check_write_ptr(parent_tid)? };
let child_tid_ref = unsafe { process().vm.check_write_ptr(child_tid)? };
let new_thread = current_thread().clone(tf, newsp, newtls, child_tid as usize);
let parent_tid_ref = unsafe { self.process().vm.check_write_ptr(parent_tid)? };
let child_tid_ref = unsafe { self.process().vm.check_write_ptr(child_tid)? };
let new_thread = self
.thread
.clone(self.tf, newsp, newtls, child_tid as usize);
// FIXME: parent pid
let tid = processor().manager().add(new_thread);
processor().manager().detach(tid);
@ -58,14 +61,14 @@ pub fn sys_clone(
*parent_tid_ref = tid as u32;
*child_tid_ref = tid as u32;
Ok(tid)
}
}
/// Wait for the process exit.
/// Return the PID. Store exit code to `wstatus` if it's not null.
pub fn sys_wait4(pid: isize, wstatus: *mut i32) -> SysResult {
/// Wait for the process exit.
/// Return the PID. Store exit code to `wstatus` if it's not null.
pub fn sys_wait4(&mut self, pid: isize, wstatus: *mut i32) -> SysResult {
//info!("wait4: pid: {}, code: {:?}", pid, wstatus);
let wstatus = if !wstatus.is_null() {
Some(unsafe { process().vm.check_write_ptr(wstatus)? })
Some(unsafe { self.process().vm.check_write_ptr(wstatus)? })
} else {
None
};
@ -80,7 +83,7 @@ pub fn sys_wait4(pid: isize, wstatus: *mut i32) -> SysResult {
_ => unimplemented!(),
};
loop {
let mut proc = process();
let mut proc = self.process();
// check child_exit_code
let find = match target {
WaitFor::AnyChild => proc
@ -122,31 +125,31 @@ pub fn sys_wait4(pid: isize, wstatus: *mut i32) -> SysResult {
let condvar = proc.child_exit.clone();
condvar.wait(proc);
}
}
}
/// Replaces the current ** process ** with a new process image
///
/// `argv` is an array of argument strings passed to the new program.
/// `envp` is an array of strings, conventionally of the form `key=value`,
/// which are passed as environment to the new program.
///
/// NOTICE: `argv` & `envp` can not be NULL (different from Linux)
///
/// NOTICE: for multi-thread programs
/// A call to any exec function from a process with more than one thread
/// shall result in all threads being terminated and the new executable image
/// being loaded and executed.
pub fn sys_exec(
/// Replaces the current ** process ** with a new process image
///
/// `argv` is an array of argument strings passed to the new program.
/// `envp` is an array of strings, conventionally of the form `key=value`,
/// which are passed as environment to the new program.
///
/// NOTICE: `argv` & `envp` can not be NULL (different from Linux)
///
/// NOTICE: for multi-thread programs
/// A call to any exec function from a process with more than one thread
/// shall result in all threads being terminated and the new executable image
/// being loaded and executed.
pub fn sys_exec(
&mut self,
path: *const u8,
argv: *const *const u8,
envp: *const *const u8,
tf: &mut TrapFrame,
) -> SysResult {
) -> SysResult {
info!(
"exec:BEG: path: {:?}, argv: {:?}, envp: {:?}",
path, argv, envp
);
let mut proc = process();
let mut proc = self.process();
let path = unsafe { proc.vm.check_and_clone_cstr(path)? };
let args = unsafe { proc.vm.check_and_clone_cstr_array(argv)? };
let envs = unsafe { proc.vm.check_and_clone_cstr_array(envp)? };
@ -184,31 +187,32 @@ pub fn sys_exec(
// Modify exec path
proc.exec_path = path.clone();
drop(proc);
// Modify the TrapFrame
*tf = TrapFrame::new_user_thread(entry_addr, ustack_top);
*self.tf = TrapFrame::new_user_thread(entry_addr, ustack_top);
info!("exec:END: path: {:?}", path);
Ok(0)
}
}
pub fn sys_yield() -> SysResult {
pub fn sys_yield(&mut self) -> SysResult {
thread::yield_now();
Ok(0)
}
}
/// Kill the process
pub fn sys_kill(pid: usize, sig: usize) -> SysResult {
/// Kill the process
pub fn sys_kill(&mut self, pid: usize, sig: usize) -> SysResult {
info!(
"kill: {} killed: {} with sig {}",
thread::current().id(),
pid,
sig
);
let current_pid = process().pid.get().clone();
let current_pid = self.process().pid.get().clone();
if current_pid == pid {
// killing myself
sys_exit_group(sig);
self.sys_exit_group(sig);
} else {
if let Some(proc_arc) = PROCESSES.read().get(&pid).and_then(|weak| weak.upgrade()) {
let proc = proc_arc.lock();
@ -231,35 +235,35 @@ pub fn sys_kill(pid: usize, sig: usize) -> SysResult {
Err(SysError::EINVAL)
}
}
}
}
/// Get the current process id
pub fn sys_getpid() -> SysResult {
/// Get the current process id
pub fn sys_getpid(&mut self) -> SysResult {
info!("getpid");
Ok(process().pid.get())
}
Ok(self.process().pid.get())
}
/// Get the current thread id
pub fn sys_gettid() -> SysResult {
/// Get the current thread id
pub fn sys_gettid(&mut self) -> SysResult {
info!("gettid");
// use pid as tid for now
Ok(thread::current().id())
}
}
/// Get the parent process id
pub fn sys_getppid() -> SysResult {
if let Some(ref parent) = process().parent.as_ref() {
/// Get the parent process id
pub fn sys_getppid(&mut self) -> SysResult {
if let Some(parent) = self.process().parent.as_ref() {
Ok(parent.lock().pid.get())
} else {
Ok(0)
}
}
}
/// Exit the current thread
pub fn sys_exit(exit_code: usize) -> ! {
/// Exit the current thread
pub fn sys_exit(&mut self, exit_code: usize) -> ! {
let tid = thread::current().id();
info!("exit: {}, code: {}", tid, exit_code);
let mut proc = process();
let mut proc = self.process();
proc.threads.retain(|&id| id != tid);
// for last thread,
@ -281,8 +285,8 @@ pub fn sys_exit(exit_code: usize) -> ! {
// ref: http://man7.org/linux/man-pages/man2/set_tid_address.2.html
// FIXME: do it in all possible ways a thread can exit
// it has memory access so we can't move it to Thread::drop?
let mut proc = process();
let clear_child_tid = current_thread().clear_child_tid as *mut u32;
let mut proc = self.process();
let clear_child_tid = self.thread.clear_child_tid as *mut u32;
if !clear_child_tid.is_null() {
info!("exit: futex {:#?} wake 1", clear_child_tid);
if let Ok(clear_child_tid_ref) = unsafe { proc.vm.check_write_ptr(clear_child_tid) } {
@ -296,11 +300,11 @@ pub fn sys_exit(exit_code: usize) -> ! {
processor().manager().exit(tid, exit_code as usize);
processor().yield_now();
unreachable!();
}
}
/// Exit the current thread group (i.e. process)
pub fn sys_exit_group(exit_code: usize) -> ! {
let proc = process();
/// Exit the current thread group (i.e. process)
pub fn sys_exit_group(&mut self, exit_code: usize) -> ! {
let proc = self.process();
info!("exit_group: {}, code: {}", proc.pid, exit_code);
// quit all threads
@ -321,26 +325,27 @@ pub fn sys_exit_group(exit_code: usize) -> ! {
processor().yield_now();
unreachable!();
}
}
pub fn sys_nanosleep(req: *const TimeSpec) -> SysResult {
let time = unsafe { *process().vm.check_read_ptr(req)? };
pub fn sys_nanosleep(&mut self, req: *const TimeSpec) -> SysResult {
let time = unsafe { *self.process().vm.check_read_ptr(req)? };
info!("nanosleep: time: {:#?}", time);
// TODO: handle spurious wakeup
thread::sleep(time.to_duration());
Ok(0)
}
}
pub fn sys_set_priority(priority: usize) -> SysResult {
pub fn sys_set_priority(&mut self, priority: usize) -> SysResult {
let pid = thread::current().id();
processor().manager().set_priority(pid, priority as u8);
Ok(0)
}
}
pub fn sys_set_tid_address(tidptr: *mut u32) -> SysResult {
pub fn sys_set_tid_address(&mut self, tidptr: *mut u32) -> SysResult {
info!("set_tid_address: {:?}", tidptr);
current_thread().clear_child_tid = tidptr as usize;
self.thread.clear_child_tid = tidptr as usize;
Ok(thread::current().id())
}
}
bitflags! {

@ -5,6 +5,85 @@ use crate::consts::USEC_PER_TICK;
use core::time::Duration;
use lazy_static::lazy_static;
impl Syscall<'_> {
pub fn sys_gettimeofday(&mut self, tv: *mut TimeVal, tz: *const u8) -> SysResult {
info!("gettimeofday: tv: {:?}, tz: {:?}", tv, tz);
if tz as usize != 0 {
return Err(SysError::EINVAL);
}
let proc = self.process();
let tv = unsafe { proc.vm.check_write_ptr(tv)? };
let timeval = TimeVal::get_epoch();
*tv = timeval;
Ok(0)
}
pub fn sys_clock_gettime(&mut self, clock: usize, ts: *mut TimeSpec) -> SysResult {
info!("clock_gettime: clock: {:?}, ts: {:?}", clock, ts);
let proc = self.process();
let ts = unsafe { proc.vm.check_write_ptr(ts)? };
let timespec = TimeSpec::get_epoch();
*ts = timespec;
Ok(0)
}
pub fn sys_time(&mut self, time: *mut u64) -> SysResult {
let sec = get_epoch_usec() / USEC_PER_SEC;
if time as usize != 0 {
let proc = self.process();
let time = unsafe { proc.vm.check_write_ptr(time)? };
*time = sec as u64;
}
Ok(sec as usize)
}
pub fn sys_getrusage(&mut self, who: usize, rusage: *mut RUsage) -> SysResult {
info!("getrusage: who: {}, rusage: {:?}", who, rusage);
let proc = self.process();
let rusage = unsafe { proc.vm.check_write_ptr(rusage)? };
let tick_base = *TICK_BASE;
let tick = unsafe { crate::trap::TICK as u64 };
let usec = (tick - tick_base) * USEC_PER_TICK as u64;
let new_rusage = RUsage {
utime: TimeVal {
sec: (usec / USEC_PER_SEC) as usize,
usec: (usec % USEC_PER_SEC) as usize,
},
stime: TimeVal {
sec: (usec / USEC_PER_SEC) as usize,
usec: (usec % USEC_PER_SEC) as usize,
},
};
*rusage = new_rusage;
Ok(0)
}
pub fn sys_times(&mut self, buf: *mut Tms) -> SysResult {
info!("times: buf: {:?}", buf);
let proc = self.process();
let buf = unsafe { proc.vm.check_write_ptr(buf)? };
let tick_base = *TICK_BASE;
let tick = unsafe { crate::trap::TICK as u64 };
let new_buf = Tms {
tms_utime: 0,
tms_stime: 0,
tms_cutime: 0,
tms_cstime: 0,
};
*buf = new_buf;
Ok(tick as usize)
}
}
/// should be initialized together
lazy_static! {
pub static ref EPOCH_BASE: u64 = crate::arch::timer::read_epoch();
@ -76,41 +155,6 @@ impl TimeSpec {
}
}
pub fn sys_gettimeofday(tv: *mut TimeVal, tz: *const u8) -> SysResult {
info!("gettimeofday: tv: {:?}, tz: {:?}", tv, tz);
if tz as usize != 0 {
return Err(SysError::EINVAL);
}
let proc = process();
let tv = unsafe { proc.vm.check_write_ptr(tv)? };
let timeval = TimeVal::get_epoch();
*tv = timeval;
Ok(0)
}
pub fn sys_clock_gettime(clock: usize, ts: *mut TimeSpec) -> SysResult {
info!("clock_gettime: clock: {:?}, ts: {:?}", clock, ts);
let proc = process();
let ts = unsafe { proc.vm.check_write_ptr(ts)? };
let timespec = TimeSpec::get_epoch();
*ts = timespec;
Ok(0)
}
pub fn sys_time(time: *mut u64) -> SysResult {
let sec = get_epoch_usec() / USEC_PER_SEC;
if time as usize != 0 {
let proc = process();
let time = unsafe { proc.vm.check_write_ptr(time)? };
*time = sec as u64;
}
Ok(sec as usize)
}
// ignore other fields for now
#[repr(C)]
pub struct RUsage {
@ -118,29 +162,6 @@ pub struct RUsage {
stime: TimeVal,
}
pub fn sys_getrusage(who: usize, rusage: *mut RUsage) -> SysResult {
info!("getrusage: who: {}, rusage: {:?}", who, rusage);
let proc = process();
let rusage = unsafe { proc.vm.check_write_ptr(rusage)? };
let tick_base = *TICK_BASE;
let tick = unsafe { crate::trap::TICK as u64 };
let usec = (tick - tick_base) * USEC_PER_TICK as u64;
let new_rusage = RUsage {
utime: TimeVal {
sec: (usec / USEC_PER_SEC) as usize,
usec: (usec % USEC_PER_SEC) as usize,
},
stime: TimeVal {
sec: (usec / USEC_PER_SEC) as usize,
usec: (usec % USEC_PER_SEC) as usize,
},
};
*rusage = new_rusage;
Ok(0)
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Tms {
@ -149,22 +170,3 @@ pub struct Tms {
tms_cutime: u64, /* user time of children */
tms_cstime: u64, /* system time of children */
}
pub fn sys_times(buf: *mut Tms) -> SysResult {
info!("times: buf: {:?}", buf);
let proc = process();
let buf = unsafe { proc.vm.check_write_ptr(buf)? };
let tick_base = *TICK_BASE;
let tick = unsafe { crate::trap::TICK as u64 };
let new_buf = Tms {
tms_utime: 0,
tms_stime: 0,
tms_cutime: 0,
tms_cstime: 0,
};
*buf = new_buf;
Ok(tick as usize)
}

Loading…
Cancel
Save