LoGin 40fe15e095
新的内存管理模块 (#303)
  实现了具有优秀架构设计的新的内存管理模块,对内核空间和用户空间的内存映射、分配、释放、管理等操作进行了封装,使得内核开发者可以更加方便地进行内存管理。

  内存管理模块主要由以下类型的组件组成:

- **硬件抽象层(MemoryManagementArch)** - 提供对具体处理器架构的抽象,使得内存管理模块可以在不同的处理器架构上运行
- **页面映射器(PageMapper)**- 提供对虚拟地址和物理地址的映射,以及页表的创建、填写、销毁、权限管理等操作。分为两种类型:内核页表映射器(KernelMapper)和用户页表映射器(位于具体的用户地址空间结构中)
- **页面刷新器(PageFlusher)** - 提供对页表的刷新操作(整表刷新、单页刷新、跨核心刷新)
- **页帧分配器(FrameAllocator)** - 提供对页帧的分配、释放、管理等操作。具体来说,包括BumpAllocator、BuddyAllocator
- **小对象分配器** - 提供对小内存对象的分配、释放、管理等操作。指的是内核里面的SlabAllocator (SlabAllocator的实现目前还没有完成)
- **MMIO空间管理器** - 提供对MMIO地址空间的分配、管理操作。(目前这个模块待进一步重构)
- **用户地址空间管理机制** - 提供对用户地址空间的管理。
    - VMA机制 - 提供对用户地址空间的管理,包括VMA的创建、销毁、权限管理等操作
    - 用户映射管理 - 与VMA机制共同作用,管理用户地址空间的映射
- **系统调用层** - 提供对用户空间的内存管理系统调用,包括mmap、munmap、mprotect、mremap等
- **C接口兼容层** - 提供对原有的C代码的接口,是的C代码能够正常运行。


除上面的新增内容以外,其它的更改内容:
- 新增二进制加载器,以及elf的解析器
- 解决由于local_irq_save、local_irq_restore函数的汇编不规范导致影响栈行为的bug。
- 解决local_irq_save未关中断的错误。
- 修复sys_gettimeofday对timezone参数的处理的bug

---------

Co-authored-by: kong <kongweichao@dragonos.org>
2023-07-22 16:27:02 +08:00

954 lines
35 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use core::{
ffi::{c_char, c_int, c_void, CStr},
sync::atomic::{AtomicBool, Ordering},
};
use num_traits::{FromPrimitive, ToPrimitive};
use crate::{
arch::{cpu::cpu_reset, MMArch},
filesystem::vfs::{
file::FileMode,
syscall::{SEEK_CUR, SEEK_END, SEEK_MAX, SEEK_SET},
MAX_PATHLEN,
},
include::bindings::bindings::{pid_t, verify_area, PAGE_2M_SIZE, PAGE_4K_SIZE},
io::SeekFrom,
kinfo,
libs::align::page_align_up,
mm::{MemoryManagementArch, VirtAddr},
net::syscall::SockAddr,
time::{
syscall::{PosixTimeZone, PosixTimeval},
TimeSpec,
},
};
pub mod user_access;
#[repr(i32)]
#[derive(Debug, FromPrimitive, ToPrimitive, PartialEq, Eq, Clone)]
#[allow(dead_code, non_camel_case_types)]
pub enum SystemError {
EPERM = 1,
/// 没有指定的文件或目录 No such file or directory.
ENOENT = 2,
/// 没有这样的进程 No such process.
ESRCH = 3,
/// 被中断的函数 Interrupted function.
EINTR = 4,
/// I/O错误 I/O error.
EIO = 5,
/// 没有这样的设备或地址 No such device or address.
ENXIO = 6,
/// 参数列表过长或者在输出buffer中缺少空间 或者参数比系统内建的最大值要大 Argument list too long.
E2BIG = 7,
/// 可执行文件格式错误 Executable file format error
ENOEXEC = 8,
/// 错误的文件描述符 Bad file descriptor.
EBADF = 9,
/// 没有子进程 No child processes.
ECHILD = 10,
/// 资源不可用,请重试。 Resource unavailable, try again.(may be the same value as [EWOULDBLOCK])
///
/// 操作将被禁止 Operation would block.(may be the same value as [EAGAIN]).
EAGAIN_OR_EWOULDBLOCK = 11,
/// 没有足够的空间 Not enough space.
ENOMEM = 12,
/// 访问被拒绝 Permission denied
EACCES = 13,
/// 错误的地址 Bad address
EFAULT = 14,
/// 需要块设备 Block device required
ENOTBLK = 15,
/// 设备或资源忙 Device or resource busy.
EBUSY = 16,
/// 文件已存在 File exists.
EEXIST = 17,
/// 跨设备连接 Cross-device link.
EXDEV = 18,
/// 没有指定的设备 No such device.
ENODEV = 19,
/// 不是目录 Not a directory.
ENOTDIR = 20,
/// 是一个目录 Is a directory
EISDIR = 21,
/// 不可用的参数 Invalid argument.
EINVAL = 22,
/// 系统中打开的文件过多 Too many files open in system.
ENFILE = 23,
/// 文件描述符的值过大 File descriptor value too large.
EMFILE = 24,
/// 不正确的I/O控制操作 Inappropriate I/O control operation.
ENOTTY = 25,
/// 文本文件忙 Text file busy.
ETXTBSY = 26,
/// 文件太大 File too large.
EFBIG = 27,
/// 设备上没有空间 No space left on device.
ENOSPC = 28,
/// 错误的寻道.当前文件是pipe不允许seek请求 Invalid seek.
ESPIPE = 29,
/// 只读的文件系统 Read-only file system.
EROFS = 30,
/// 链接数过多 Too many links.
EMLINK = 31,
/// 断开的管道 Broken pipe.
EPIPE = 32,
/// 数学参数超出作用域 Mathematics argument out of domain of function.
EDOM = 33,
/// 结果过大 Result too large.
ERANGE = 34,
/// 资源死锁将要发生 Resource deadlock would occur.
EDEADLK = 35,
/// 文件名过长 Filename too long.
ENAMETOOLONG = 36,
/// 没有可用的锁 No locks available.
ENOLCK = 37,
/// 功能不支持 Function not supported.
ENOSYS = 38,
/// 目录非空 Directory not empty.
ENOTEMPTY = 39,
/// 符号链接级别过多 Too many levels of symbolic links.
ELOOP = 40,
/// 没有期待类型的消息 No message of the desired type.
ENOMSG = 41,
/// 标志符被移除 Identifier removed.
EIDRM = 42,
/// 通道号超出范围 Channel number out of range
ECHRNG = 43,
/// 二级不同步 Level 2 not synchronized
EL2NSYNC = 44,
/// 三级暂停 Level 3 halted
EL3HLT = 45,
/// 三级重置 Level 3 reset
EL3RST = 46,
/// 链接号超出范围 Link number out of range
ELNRNG = 47,
/// 未连接协议驱动程序 Protocol driver not attached
EUNATCH = 48,
/// 没有可用的CSI结构 No CSI structure available
ENOCSI = 49,
/// 二级暂停 Level 2 halted
EL2HLT = 50,
/// 无效交换 Invalid exchange
EBADE = 51,
/// 无效的请求描述符 Invalid request descriptor
EBADR = 52,
/// 交换满 Exchange full
EXFULL = 53,
/// 无阳极 No anode
ENOANO = 54,
/// 请求码无效 Invalid request code
EBADRQC = 55,
/// 无效插槽 Invalid slot
EBADSLT = 56,
/// 资源死锁 Resource deadlock would occur
EDEADLOCK = 57,
/// 错误的字体文件格式 Bad font file format
EBFONT = 58,
/// 不是STREAM Not a STREAM
ENOSTR = 59,
/// 队列头没有可读取的消息 No message is available on the STREAM head read queue.
ENODATA = 60,
/// 流式ioctl()超时 Stream ioctl() timeout
ETIME = 61,
/// 没有STREAM资源 No STREAM resources.
ENOSR = 62,
/// 机器不在网络上 Machine is not on the network
ENONET = 63,
/// 未安装软件包 Package not installed
ENOPKG = 64,
/// 远程对象 Object is remote
EREMOTE = 65,
/// 保留 Reserved.
ENOLINK = 66,
/// 外设错误 Advertise error.
EADV = 67,
/// 安装错误 Srmount error
ESRMNT = 68,
/// 发送时发生通信错误 Communication error on send
ECOMM = 69,
/// 协议错误 Protocol error.
EPROTO = 70,
/// 保留使用 Reserved.
EMULTIHOP = 71,
/// RFS特定错误 RFS specific error
EDOTDOT = 72,
/// 错误的消息 Bad message.
EBADMSG = 73,
/// 数值过大,产生溢出 Value too large to be stored in data type.
EOVERFLOW = 74,
/// 名称在网络上不是唯一的 Name not unique on network
ENOTUNIQ = 75,
/// 处于不良状态的文件描述符 File descriptor in bad state
EBADFD = 76,
/// 远程地址已更改 Remote address changed
EREMCHG = 77,
/// 无法访问所需的共享库 Can not access a needed shared library
ELIBACC = 78,
/// 访问损坏的共享库 Accessing a corrupted shared library
ELIBBAD = 79,
/// a. out中的.lib部分已损坏 .lib section in a.out corrupted
ELIBSCN = 80,
/// 尝试链接太多共享库 Attempting to link in too many shared libraries
ELIBMAX = 81,
/// 无法直接执行共享库 Cannot exec a shared library directly
ELIBEXEC = 82,
/// 不合法的字符序列 Illegal byte sequence.
EILSEQ = 83,
/// 中断的系统调用应该重新启动 Interrupted system call should be restarted
ERESTART = 84,
/// 流管道错误 Streams pipe error
ESTRPIPE = 85,
/// 用户太多 Too many users
EUSERS = 86,
/// 不是一个套接字 Not a socket.
ENOTSOCK = 87,
/// 需要目标地址 Destination address required.
EDESTADDRREQ = 88,
/// 消息过大 Message too large.
EMSGSIZE = 89,
/// 对于套接字而言,错误的协议 Protocol wrong type for socket.
EPROTOTYPE = 90,
/// 协议不可用 Protocol not available.
ENOPROTOOPT = 91,
/// 协议不被支持 Protocol not supported.
EPROTONOSUPPORT = 92,
/// 不支持套接字类型 Socket type not supported
ESOCKTNOSUPPORT = 93,
/// 套接字不支持该操作 Operation not supported on socket (may be the same value as [ENOTSUP]).
///
/// 不被支持 Not supported (may be the same value as [EOPNOTSUPP]).
EOPNOTSUPP_OR_ENOTSUP = 94,
/// 不支持协议系列 Protocol family not supported
EPFNOSUPPORT = 95,
/// 地址family不支持 Address family not supported.
EAFNOSUPPORT = 96,
/// 地址正在被使用 Address in use.
EADDRINUSE = 97,
/// 地址不可用 Address not available.
EADDRNOTAVAIL = 98,
/// 网络已关闭 Network is down.
ENETDOWN = 99,
/// 网络不可达 Network unreachable.
ENETUNREACH = 100,
/// 网络连接已断开 Connection aborted by network.
ENETRESET = 101,
/// 连接已断开 Connection aborted.
ECONNABORTED = 102,
/// 连接被重置 Connection reset.
ECONNRESET = 103,
/// 缓冲区空间不足 No buffer space available.
ENOBUFS = 104,
/// 套接字已连接 Socket is connected.
EISCONN = 105,
/// 套接字未连接 The socket is not connected.
ENOTCONN = 106,
/// 传输端点关闭后无法发送 Cannot send after transport endpoint shutdown
ESHUTDOWN = 107,
/// 引用太多:无法拼接 Too many references: cannot splice
ETOOMANYREFS = 108,
/// 连接超时 Connection timed out.
ETIMEDOUT = 109,
/// 连接被拒绝 Connection refused.
ECONNREFUSED = 110,
/// 主机已关闭 Host is down
EHOSTDOWN = 111,
/// 主机不可达 Host is unreachable.
EHOSTUNREACH = 112,
/// 连接已经在处理 Connection already in progress.
EALREADY = 113,
/// 操作正在处理 Operation in progress.
EINPROGRESS = 114,
/// 保留 Reserved.
ESTALE = 115,
/// 结构需要清理 Structure needs cleaning
EUCLEAN = 116,
/// 不是XENIX命名类型文件 Not a XENIX named type file
ENOTNAM = 117,
/// 没有可用的XENIX信号量 No XENIX semaphores available
ENAVAIL = 118,
/// 是命名类型文件 Is a named type file
EISNAM = 119,
/// 远程I/O错误 Remote I/O error
EREMOTEIO = 120,
/// 保留使用 Reserved
EDQUOT = 121,
/// 没有找到媒介 No medium found
ENOMEDIUM = 122,
/// 介质类型错误 Wrong medium type
EMEDIUMTYPE = 123,
/// 操作被取消 Operation canceled.
ECANCELED = 124,
/// 所需的密钥不可用 Required key not available
ENOKEY = 125,
/// 密钥已过期 Key has expired
EKEYEXPIRED = 126,
/// 密钥已被撤销 Key has been revoked
EKEYREVOKED = 127,
/// 密钥被服务拒绝 Key has been revoked
EKEYREJECTED = 128,
/// 之前的拥有者挂了 Previous owner died.
EOWNERDEAD = 129,
/// 状态不可恢复 State not recoverable.
ENOTRECOVERABLE = 130,
}
impl SystemError {
/// @brief 把posix错误码转换为系统错误枚举类型。
pub fn from_posix_errno(errno: i32) -> Option<SystemError> {
// posix 错误码是小于0的
if errno >= 0 {
return None;
}
return <Self as FromPrimitive>::from_i32(-errno);
}
/// @brief 把系统错误枚举类型转换为负数posix错误码。
pub fn to_posix_errno(&self) -> i32 {
return -<Self as ToPrimitive>::to_i32(self).unwrap();
}
}
// 定义系统调用号
pub const SYS_PUT_STRING: usize = 1;
pub const SYS_OPEN: usize = 2;
pub const SYS_CLOSE: usize = 3;
pub const SYS_READ: usize = 4;
pub const SYS_WRITE: usize = 5;
pub const SYS_LSEEK: usize = 6;
pub const SYS_FORK: usize = 7;
pub const SYS_VFORK: usize = 8;
pub const SYS_BRK: usize = 9;
pub const SYS_SBRK: usize = 10;
pub const SYS_REBOOT: usize = 11;
pub const SYS_CHDIR: usize = 12;
pub const SYS_GET_DENTS: usize = 13;
pub const SYS_EXECVE: usize = 14;
pub const SYS_WAIT4: usize = 15;
pub const SYS_EXIT: usize = 16;
pub const SYS_MKDIR: usize = 17;
pub const SYS_NANOSLEEP: usize = 18;
/// todo: 该系统调用与Linux不一致将来需要删除该系统调用 删的时候记得改C版本的libc
pub const SYS_CLOCK: usize = 19;
pub const SYS_PIPE: usize = 20;
/// 系统调用21曾经是SYS_MSTAT但是现在已经废弃
pub const __NOT_USED: usize = 21;
pub const SYS_UNLINK_AT: usize = 22;
pub const SYS_KILL: usize = 23;
pub const SYS_SIGACTION: usize = 24;
pub const SYS_RT_SIGRETURN: usize = 25;
pub const SYS_GETPID: usize = 26;
pub const SYS_SCHED: usize = 27;
pub const SYS_DUP: usize = 28;
pub const SYS_DUP2: usize = 29;
pub const SYS_SOCKET: usize = 30;
pub const SYS_SETSOCKOPT: usize = 31;
pub const SYS_GETSOCKOPT: usize = 32;
pub const SYS_CONNECT: usize = 33;
pub const SYS_BIND: usize = 34;
pub const SYS_SENDTO: usize = 35;
pub const SYS_RECVFROM: usize = 36;
pub const SYS_RECVMSG: usize = 37;
pub const SYS_LISTEN: usize = 38;
pub const SYS_SHUTDOWN: usize = 39;
pub const SYS_ACCEPT: usize = 40;
pub const SYS_GETSOCKNAME: usize = 41;
pub const SYS_GETPEERNAME: usize = 42;
pub const SYS_GETTIMEOFDAY: usize = 43;
pub const SYS_MMAP: usize = 44;
pub const SYS_MUNMAP: usize = 45;
pub const SYS_MPROTECT: usize = 46;
#[derive(Debug)]
pub struct Syscall;
extern "C" {
fn do_put_string(s: *const u8, front_color: u32, back_color: u32) -> usize;
}
#[no_mangle]
pub extern "C" fn syscall_init() -> i32 {
kinfo!("Initializing syscall...");
Syscall::init().expect("syscall init failed");
kinfo!("Syscall init successfully!");
return 0;
}
impl Syscall {
/// 初始化系统调用
pub fn init() -> Result<(), SystemError> {
static INIT_FLAG: AtomicBool = AtomicBool::new(false);
let prev = INIT_FLAG.swap(true, Ordering::SeqCst);
if prev {
panic!("Cannot initialize syscall more than once!");
}
return crate::arch::syscall::arch_syscall_init();
}
/// @brief 系统调用分发器,用于分发系统调用。
///
/// 这个函数内,需要根据系统调用号,调用对应的系统调用处理函数。
/// 并且,对于用户态传入的指针参数,需要在本函数内进行越界检查,防止访问到内核空间。
pub fn handle(syscall_num: usize, args: &[usize], from_user: bool) -> usize {
let r = match syscall_num {
SYS_PUT_STRING => {
Self::put_string(args[0] as *const u8, args[1] as u32, args[2] as u32)
}
SYS_OPEN => {
let path: &CStr = unsafe { CStr::from_ptr(args[0] as *const c_char) };
let path: Result<&str, core::str::Utf8Error> = path.to_str();
let res = if path.is_err() {
Err(SystemError::EINVAL)
} else {
let path: &str = path.unwrap();
let flags = args[1];
let open_flags: FileMode = FileMode::from_bits_truncate(flags as u32);
Self::open(path, open_flags)
};
// kdebug!("open: {:?}, res: {:?}", path, res);
res
}
SYS_CLOSE => {
let fd = args[0];
Self::close(fd)
}
SYS_READ => {
let fd = args[0] as i32;
let buf_vaddr = args[1];
let len = args[2];
// 判断缓冲区是否来自用户态,进行权限校验
let res = if from_user && unsafe { !verify_area(buf_vaddr as u64, len as u64) } {
// 来自用户态而buffer在内核态这样的操作不被允许
Err(SystemError::EPERM)
} else {
let buf: &mut [u8] = unsafe {
core::slice::from_raw_parts_mut::<'static, u8>(buf_vaddr as *mut u8, len)
};
Self::read(fd, buf)
};
res
}
SYS_WRITE => {
let fd = args[0] as i32;
let buf_vaddr = args[1];
let len = args[2];
// 判断缓冲区是否来自用户态,进行权限校验
let res = if from_user && unsafe { !verify_area(buf_vaddr as u64, len as u64) } {
// 来自用户态而buffer在内核态这样的操作不被允许
Err(SystemError::EPERM)
} else {
let buf: &[u8] = unsafe {
core::slice::from_raw_parts::<'static, u8>(buf_vaddr as *const u8, len)
};
Self::write(fd, buf)
};
res
}
SYS_LSEEK => {
let fd = args[0] as i32;
let offset = args[1] as i64;
let whence = args[2] as u32;
let w = match whence {
SEEK_SET => Ok(SeekFrom::SeekSet(offset)),
SEEK_CUR => Ok(SeekFrom::SeekCurrent(offset)),
SEEK_END => Ok(SeekFrom::SeekEnd(offset)),
SEEK_MAX => Ok(SeekFrom::SeekEnd(0)),
_ => Err(SystemError::EINVAL),
};
let res = if w.is_err() {
Err(w.unwrap_err())
} else {
let w = w.unwrap();
Self::lseek(fd, w)
};
res
}
SYS_BRK => {
let new_brk = VirtAddr::new(args[0]);
Self::brk(new_brk).map(|vaddr| vaddr.data())
}
SYS_SBRK => {
let increment = args[0] as isize;
Self::sbrk(increment).map(|vaddr| vaddr.data())
}
SYS_REBOOT => Self::reboot(),
SYS_CHDIR => {
// Closure for checking arguments
let chdir_check = |arg0: usize| {
if arg0 == 0 {
return Err(SystemError::EFAULT);
}
let path_ptr = arg0 as *const c_char;
// 权限校验
if path_ptr.is_null()
|| (from_user
&& unsafe { !verify_area(path_ptr as u64, PAGE_2M_SIZE as u64) })
{
return Err(SystemError::EINVAL);
}
let dest_path: &CStr = unsafe { CStr::from_ptr(path_ptr) };
let dest_path: &str = dest_path.to_str().map_err(|_| SystemError::EINVAL)?;
if dest_path.len() == 0 {
return Err(SystemError::EINVAL);
} else if dest_path.len() > PAGE_4K_SIZE as usize {
return Err(SystemError::ENAMETOOLONG);
}
return Ok(dest_path);
};
let r: Result<&str, SystemError> = chdir_check(args[0]);
if r.is_err() {
Err(r.unwrap_err())
} else {
Self::chdir(r.unwrap())
}
}
SYS_GET_DENTS => {
let fd = args[0] as i32;
let buf_vaddr = args[1];
let len = args[2];
// 判断缓冲区是否来自用户态,进行权限校验
let res = if from_user && unsafe { !verify_area(buf_vaddr as u64, len as u64) } {
// 来自用户态而buffer在内核态这样的操作不被允许
Err(SystemError::EPERM)
} else if buf_vaddr == 0 {
Err(SystemError::EFAULT)
} else {
let buf: &mut [u8] = unsafe {
core::slice::from_raw_parts_mut::<'static, u8>(buf_vaddr as *mut u8, len)
};
Self::getdents(fd, buf)
};
res
}
SYS_EXECVE => {
let path_ptr = args[0];
let argv_ptr = args[1];
let env_ptr = args[2];
// 权限校验
if from_user
&& (unsafe { !verify_area(path_ptr as u64, PAGE_4K_SIZE as u64) }
|| unsafe { !verify_area(argv_ptr as u64, PAGE_4K_SIZE as u64) })
|| unsafe { !verify_area(env_ptr as u64, PAGE_4K_SIZE as u64) }
{
Err(SystemError::EFAULT)
} else {
Self::execve(
path_ptr as *const c_void,
argv_ptr as *const *const c_void,
env_ptr as *const *const c_void,
)
}
}
SYS_WAIT4 => {
let pid = args[0] as pid_t;
let wstatus = args[1] as *mut c_int;
let options = args[2] as c_int;
let rusage = args[3] as *mut c_void;
// 权限校验
// todo: 引入rusage之后更正以下权限校验代码中rusage的大小
if from_user
&& (unsafe {
!verify_area(wstatus as u64, core::mem::size_of::<c_int>() as u64)
} || unsafe { !verify_area(rusage as u64, PAGE_4K_SIZE as u64) })
{
Err(SystemError::EFAULT)
} else {
Self::wait4(pid, wstatus, options, rusage)
}
}
SYS_EXIT => {
let exit_code = args[0];
Self::exit(exit_code)
}
SYS_MKDIR => {
let path_ptr = args[0] as *const c_char;
let mode = args[1];
let security_check = || {
if path_ptr.is_null()
|| (from_user
&& unsafe { !verify_area(path_ptr as u64, PAGE_2M_SIZE as u64) })
{
return Err(SystemError::EINVAL);
}
let path: &CStr = unsafe { CStr::from_ptr(path_ptr) };
let path: &str = path.to_str().map_err(|_| SystemError::EINVAL)?.trim();
if path == "" {
return Err(SystemError::EINVAL);
}
return Ok(path);
};
let path = security_check();
if path.is_err() {
Err(path.unwrap_err())
} else {
Self::mkdir(path.unwrap(), mode)
}
}
SYS_NANOSLEEP => {
let req = args[0] as *const TimeSpec;
let rem = args[1] as *mut TimeSpec;
if from_user
&& (unsafe {
!verify_area(req as u64, core::mem::size_of::<TimeSpec>() as u64)
} || unsafe {
!verify_area(rem as u64, core::mem::size_of::<TimeSpec>() as u64)
})
{
Err(SystemError::EFAULT)
} else {
Self::nanosleep(req, rem)
}
}
SYS_CLOCK => Self::clock(),
SYS_PIPE => {
let pipefd = args[0] as *mut c_int;
if from_user
&& unsafe {
!verify_area(pipefd as u64, core::mem::size_of::<[c_int; 2]>() as u64)
}
{
Err(SystemError::EFAULT)
} else if pipefd.is_null() {
Err(SystemError::EFAULT)
} else {
let pipefd = unsafe { core::slice::from_raw_parts_mut(pipefd, 2) };
Self::pipe(pipefd)
}
}
SYS_UNLINK_AT => {
let dirfd = args[0] as i32;
let pathname = args[1] as *const c_char;
let flags = args[2] as u32;
if from_user && unsafe { !verify_area(pathname as u64, PAGE_4K_SIZE as u64) } {
Err(SystemError::EFAULT)
} else if pathname.is_null() {
Err(SystemError::EFAULT)
} else {
let get_path = || {
let pathname: &CStr = unsafe { CStr::from_ptr(pathname) };
let pathname: &str = pathname.to_str().map_err(|_| SystemError::EINVAL)?;
if pathname.len() >= MAX_PATHLEN {
return Err(SystemError::ENAMETOOLONG);
}
return Ok(pathname.trim());
};
let pathname = get_path();
if pathname.is_err() {
Err(pathname.unwrap_err())
} else {
Self::unlinkat(dirfd, pathname.unwrap(), flags)
}
}
}
SYS_KILL => {
let pid = args[0] as pid_t;
let sig = args[1] as c_int;
Self::kill(pid, sig)
}
SYS_SIGACTION => {
let sig = args[0] as c_int;
let act = args[1];
let old_act = args[2];
Self::sigaction(sig, act, old_act, from_user)
}
SYS_RT_SIGRETURN => {
// 由于目前signal机制的实现与x86_64强关联因此暂时在arch/x86_64/syscall.rs中调用
// todo: 未来需要将signal机制与平台解耦
todo!()
}
SYS_GETPID => Self::getpid(),
SYS_SCHED => Self::sched(from_user),
SYS_DUP => {
let oldfd: i32 = args[0] as c_int;
Self::dup(oldfd)
}
SYS_DUP2 => {
let oldfd: i32 = args[0] as c_int;
let newfd: i32 = args[1] as c_int;
Self::dup2(oldfd, newfd)
}
SYS_SOCKET => Self::socket(args[0], args[1], args[2]),
SYS_SETSOCKOPT => {
let optval = args[3] as *const u8;
let optlen = args[4] as usize;
// 验证optval的地址是否合法
if unsafe { verify_area(optval as u64, optlen as u64) } == false {
// 地址空间超出了用户空间的范围,不合法
Err(SystemError::EFAULT)
} else {
let data: &[u8] = unsafe { core::slice::from_raw_parts(optval, optlen) };
Self::setsockopt(args[0], args[1], args[2], data)
}
}
SYS_GETSOCKOPT => {
let optval = args[3] as *mut u8;
let optlen = args[4] as *mut usize;
let security_check = || {
// 验证optval的地址是否合法
if unsafe { verify_area(optval as u64, PAGE_4K_SIZE as u64) } == false {
// 地址空间超出了用户空间的范围,不合法
return Err(SystemError::EFAULT);
}
// 验证optlen的地址是否合法
if unsafe { verify_area(optlen as u64, core::mem::size_of::<u32>() as u64) }
== false
{
// 地址空间超出了用户空间的范围,不合法
return Err(SystemError::EFAULT);
}
return Ok(());
};
let r = security_check();
if r.is_err() {
Err(r.unwrap_err())
} else {
Self::getsockopt(args[0], args[1], args[2], optval, optlen as *mut u32)
}
}
SYS_CONNECT => {
let addr = args[1] as *const SockAddr;
let addrlen = args[2] as usize;
// 验证addr的地址是否合法
if unsafe { verify_area(addr as u64, addrlen as u64) } == false {
// 地址空间超出了用户空间的范围,不合法
Err(SystemError::EFAULT)
} else {
Self::connect(args[0], addr, addrlen)
}
}
SYS_BIND => {
let addr = args[1] as *const SockAddr;
let addrlen = args[2] as usize;
// 验证addr的地址是否合法
if unsafe { verify_area(addr as u64, addrlen as u64) } == false {
// 地址空间超出了用户空间的范围,不合法
Err(SystemError::EFAULT)
} else {
Self::bind(args[0], addr, addrlen)
}
}
SYS_SENDTO => {
let buf = args[1] as *const u8;
let len = args[2] as usize;
let flags = args[3] as u32;
let addr = args[4] as *const SockAddr;
let addrlen = args[5] as usize;
// 验证buf的地址是否合法
if unsafe { verify_area(buf as u64, len as u64) } == false {
// 地址空间超出了用户空间的范围,不合法
Err(SystemError::EFAULT)
} else if unsafe { verify_area(addr as u64, addrlen as u64) } == false {
// 地址空间超出了用户空间的范围,不合法
Err(SystemError::EFAULT)
} else {
let data: &[u8] = unsafe { core::slice::from_raw_parts(buf, len) };
Self::sendto(args[0], data, flags, addr, addrlen)
}
}
SYS_RECVFROM => {
let buf = args[1] as *mut u8;
let len = args[2] as usize;
let flags = args[3] as u32;
let addr = args[4] as *mut SockAddr;
let addrlen = args[5] as *mut usize;
let security_check = || {
// 验证buf的地址是否合法
if unsafe { verify_area(buf as u64, len as u64) } == false {
// 地址空间超出了用户空间的范围,不合法
return Err(SystemError::EFAULT);
}
// 验证addrlen的地址是否合法
if unsafe { verify_area(addrlen as u64, core::mem::size_of::<u32>() as u64) }
== false
{
// 地址空间超出了用户空间的范围,不合法
return Err(SystemError::EFAULT);
}
if unsafe { verify_area(addr as u64, core::mem::size_of::<SockAddr>() as u64) }
== false
{
// 地址空间超出了用户空间的范围,不合法
return Err(SystemError::EFAULT);
}
return Ok(());
};
let r = security_check();
if r.is_err() {
Err(r.unwrap_err())
} else {
let buf = unsafe { core::slice::from_raw_parts_mut(buf, len) };
Self::recvfrom(args[0], buf, flags, addr, addrlen as *mut u32)
}
}
SYS_RECVMSG => {
let msg = args[1] as *mut crate::net::syscall::MsgHdr;
let flags = args[2] as u32;
let security_check = || {
// 验证msg的地址是否合法
if unsafe {
verify_area(
msg as u64,
core::mem::size_of::<crate::net::syscall::MsgHdr>() as u64,
)
} == false
{
// 地址空间超出了用户空间的范围,不合法
return Err(SystemError::EFAULT);
}
let msg = unsafe { msg.as_mut() }.ok_or(SystemError::EFAULT)?;
return Ok(msg);
};
let r = security_check();
if r.is_err() {
Err(r.unwrap_err())
} else {
let msg = r.unwrap();
Self::recvmsg(args[0], msg, flags)
}
}
SYS_LISTEN => Self::listen(args[0], args[1]),
SYS_SHUTDOWN => Self::shutdown(args[0], args[1]),
SYS_ACCEPT => Self::accept(args[0], args[1] as *mut SockAddr, args[2] as *mut u32),
SYS_GETSOCKNAME => {
Self::getsockname(args[0], args[1] as *mut SockAddr, args[2] as *mut u32)
}
SYS_GETPEERNAME => {
Self::getpeername(args[0], args[1] as *mut SockAddr, args[2] as *mut u32)
}
SYS_GETTIMEOFDAY => {
let timeval = args[0] as *mut PosixTimeval;
let timezone_ptr = args[1] as *mut PosixTimeZone;
let security_check = || {
if unsafe {
verify_area(timeval as u64, core::mem::size_of::<PosixTimeval>() as u64)
} == false
{
return Err(SystemError::EFAULT);
}
if unsafe {
verify_area(
timezone_ptr as u64,
core::mem::size_of::<PosixTimeZone>() as u64,
)
} == false
{
return Err(SystemError::EFAULT);
}
return Ok(());
};
let r = security_check();
if r.is_err() {
Err(r.unwrap_err())
} else {
if !timeval.is_null() {
Self::gettimeofday(timeval, timezone_ptr)
} else {
Err(SystemError::EFAULT)
}
}
}
SYS_MMAP => {
let len = page_align_up(args[1]);
if unsafe { !verify_area(args[0] as u64, len as u64) } {
Err(SystemError::EFAULT)
} else {
Self::mmap(
VirtAddr::new(args[0]),
len,
args[2],
args[3],
args[4] as i32,
args[5],
)
}
}
SYS_MUNMAP => {
let addr = args[0];
let len = page_align_up(args[1]);
if addr & MMArch::PAGE_SIZE != 0 {
// The addr argument is not a multiple of the page size
Err(SystemError::EINVAL)
} else {
Self::munmap(VirtAddr::new(addr), len)
}
}
SYS_MPROTECT => {
let addr = args[0];
let len = page_align_up(args[1]);
if addr & MMArch::PAGE_SIZE != 0 {
// The addr argument is not a multiple of the page size
Err(SystemError::EINVAL)
} else {
Self::mprotect(VirtAddr::new(addr), len, args[2])
}
}
_ => panic!("Unsupported syscall ID: {}", syscall_num),
};
let r = r.unwrap_or_else(|e| e.to_posix_errno() as usize);
return r;
}
pub fn put_string(
s: *const u8,
front_color: u32,
back_color: u32,
) -> Result<usize, SystemError> {
return Ok(unsafe { do_put_string(s, front_color, back_color) });
}
pub fn reboot() -> Result<usize, SystemError> {
cpu_reset();
}
}