Revert "新的内存管理模块 (#301)" (#302)

This reverts commit d8ad0a5e77.
This commit is contained in:
LoGin
2023-07-22 16:24:55 +08:00
committed by GitHub
parent d8ad0a5e77
commit bb5f098a86
124 changed files with 5151 additions and 8278 deletions

View File

@ -6,30 +6,27 @@ use core::{
use num_traits::{FromPrimitive, ToPrimitive};
use crate::{
arch::{cpu::cpu_reset, MMArch},
arch::cpu::cpu_reset,
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},
include::bindings::bindings::{mm_stat_t, 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},
syscall::{PosixTimeZone, PosixTimeval, SYS_TIMEZONE},
TimeSpec,
},
};
pub mod user_access;
#[repr(i32)]
#[derive(Debug, FromPrimitive, ToPrimitive, PartialEq, Eq, Clone)]
#[allow(dead_code, non_camel_case_types)]
pub enum SystemError {
/// 操作不被允许 Operation not permitted.
EPERM = 1,
/// 没有指定的文件或目录 No such file or directory.
ENOENT = 2,
@ -334,8 +331,9 @@ 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;
/// todo: 该系统调用不是符合POSIX标准的在将来需要删除
pub const SYS_MSTAT: usize = 21;
pub const SYS_UNLINK_AT: usize = 22;
pub const SYS_KILL: usize = 23;
pub const SYS_SIGACTION: usize = 24;
@ -360,9 +358,6 @@ 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;
@ -478,13 +473,13 @@ impl Syscall {
}
SYS_BRK => {
let new_brk = VirtAddr::new(args[0]);
Self::brk(new_brk).map(|vaddr| vaddr.data())
let new_brk = args[0];
Self::brk(new_brk)
}
SYS_SBRK => {
let increment = args[0] as isize;
Self::sbrk(increment).map(|vaddr| vaddr.data())
Self::sbrk(increment)
}
SYS_REBOOT => Self::reboot(),
@ -647,6 +642,18 @@ impl Syscall {
}
}
SYS_MSTAT => {
let dst = args[0] as *mut mm_stat_t;
if from_user
&& unsafe { !verify_area(dst as u64, core::mem::size_of::<mm_stat_t>() as u64) }
{
Err(SystemError::EFAULT)
} else if dst.is_null() {
Err(SystemError::EFAULT)
} else {
Self::mstat(dst, from_user)
}
}
SYS_UNLINK_AT => {
let dirfd = args[0] as i32;
let pathname = args[1] as *const c_char;
@ -866,7 +873,7 @@ impl Syscall {
}
SYS_GETTIMEOFDAY => {
let timeval = args[0] as *mut PosixTimeval;
let timezone_ptr = args[1] as *mut PosixTimeZone;
let timezone_ptr = args[1] as *const PosixTimeZone;
let security_check = || {
if unsafe {
verify_area(timeval as u64, core::mem::size_of::<PosixTimeval>() as u64)
@ -889,49 +896,18 @@ impl Syscall {
if r.is_err() {
Err(r.unwrap_err())
} else {
let timezone = if !timezone_ptr.is_null() {
&SYS_TIMEZONE
} else {
unsafe { timezone_ptr.as_ref().unwrap() }
};
if !timeval.is_null() {
Self::gettimeofday(timeval, timezone_ptr)
Self::gettimeofday(timeval, timezone)
} 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),
};

View File

@ -73,6 +73,102 @@ ul do_put_string(char *s, uint32_t front_color, uint32_t background_color)
return 0;
}
/**
* @brief 将堆内存调整为arg0
*
* @param arg0 新的堆区域的结束地址
* @return uint64_t 错误码
*
*/
uint64_t sys_do_brk(uint64_t newaddr)
{
uint64_t new_brk = PAGE_2M_ALIGN(newaddr);
// kdebug("sys_brk input= %#010lx , new_brk= %#010lx bytes current_pcb->mm->brk_start=%#018lx
// current->end_brk=%#018lx", regs->r8, new_brk, current_pcb->mm->brk_start, current_pcb->mm->brk_end);
struct mm_struct *mm = current_pcb->mm;
if (new_brk < mm->brk_start || new_brk > new_brk >= current_pcb->addr_limit)
return mm->brk_end;
if (mm->brk_end == new_brk)
return new_brk;
int64_t offset;
if (new_brk >= current_pcb->mm->brk_end)
offset = (int64_t)(new_brk - current_pcb->mm->brk_end);
else
offset = -(int64_t)(current_pcb->mm->brk_end - new_brk);
new_brk = mm_do_brk(current_pcb->mm->brk_end, offset); // 扩展堆内存空间
current_pcb->mm->brk_end = new_brk;
return mm->brk_end;
}
/**
* @brief 将堆内存空间加上offset注意该系统调用只应在普通进程中调用而不能是内核线程
*
* @param incr offset偏移量
* @return uint64_t the previous program break
*/
uint64_t sys_do_sbrk(int64_t incr)
{
uint64_t retval = current_pcb->mm->brk_end;
if ((int64_t)incr > 0)
{
uint64_t new_brk = PAGE_2M_ALIGN(retval + incr);
if (new_brk > current_pcb->addr_limit) // 堆地址空间超过限制
{
kdebug("exceed mem limit, new_brk = %#018lx", new_brk);
return -ENOMEM;
}
}
else
{
if ((__int128_t)current_pcb->mm->brk_end + (__int128_t)incr < current_pcb->mm->brk_start)
return retval;
}
// kdebug("do brk");
uint64_t new_brk = mm_do_brk(current_pcb->mm->brk_end, (int64_t)incr); // 调整堆内存空间
// kdebug("do brk done, new_brk = %#018lx", new_brk);
current_pcb->mm->brk_end = new_brk;
return retval;
}
/**
* @brief 执行新的程序
*
* @param user_path(r8寄存器) 文件路径
* @param argv(r9寄存器) 参数列表
* @return uint64_t
*/
uint64_t c_sys_execve(char *user_path, char **argv, char **envp, struct pt_regs *regs)
{
int path_len = strnlen_user(user_path, PAGE_4K_SIZE);
if (path_len >= PAGE_4K_SIZE)
return -ENAMETOOLONG;
else if (path_len <= 0)
return -EFAULT;
char *path = (char *)kmalloc(path_len + 1, 0);
if (path == NULL)
return -ENOMEM;
memset(path, 0, path_len + 1);
// 拷贝文件路径
strncpy_from_user(path, user_path, path_len);
path[path_len] = '\0';
// 执行新的程序
uint64_t retval = do_execve(regs, path, argv, NULL);
kfree(path);
return retval;
}
/**
* @brief 等待进程退出
*

View File

@ -30,6 +30,7 @@
#define SYS_CLOCK 19 // 获取当前cpu时间
#define SYS_PIPE 20 // 创建管道
#define SYS_MSTAT 21 // 获取系统的内存状态信息
#define SYS_UNLINK_AT 22 // 删除文件夹/删除文件链接
#define SYS_KILL 23 // kill一个进程(向这个进程发出信号)
#define SYS_SIGACTION 24 // 设置进程的信号处理动作
@ -40,20 +41,18 @@
#define SYS_DUP2 29
#define SYS_SOCKET 30 // 创建一个socket
#define SYS_SETSOCKOPT 31 // 设置socket的选项
#define SYS_GETSOCKOPT 32 // 获取socket的选项
#define SYS_CONNECT 33 // 连接到一个socket
#define SYS_BIND 34 // 绑定一个socket
#define SYS_SENDTO 35 // 向一个socket发送数据
#define SYS_RECVFROM 36 // 从一个socket接收数据
#define SYS_RECVMSG 37 // 从一个socket接收消息
#define SYS_LISTEN 38 // 监听一个socket
#define SYS_SHUTDOWN 39 // 关闭socket
#define SYS_ACCEPT 40 // 接受一个socket连接
#define SYS_GETSOCKNAME 41 // 获取socket的名字
#define SYS_GETPEERNAME 42 // 获取socket的对端名字
#define SYS_SETSOCKOPT 31 // 设置socket的选项
#define SYS_GETSOCKOPT 32 // 获取socket的选项
#define SYS_CONNECT 33 // 连接到一个socket
#define SYS_BIND 34 // 绑定一个socket
#define SYS_SENDTO 35 // 向一个socket发送数据
#define SYS_RECVFROM 36 // 从一个socket接收数据
#define SYS_RECVMSG 37 // 从一个socket接收消息
#define SYS_LISTEN 38 // 监听一个socket
#define SYS_SHUTDOWN 39 // 关闭socket
#define SYS_ACCEPT 40 // 接受一个socket连接
#define SYS_GETSOCKNAME 41 // 获取socket的名字
#define SYS_GETPEERNAME 42 // 获取socket的对端名字
#define SYS_GETTIMEOFDAY 43 // 获取当前时间
#define SYS_MMAP 44 // 内存映射
#define SYS_MUNMAP 45 // 内存解除映射
#define SYS_MPROTECT 46 // 内存保护
#define SYS_AHCI_END_REQ 255 // AHCI DMA请求结束end_request的系统调用

View File

@ -1,141 +0,0 @@
//! 这个文件用于放置一些内核态访问用户态数据的函数
use core::mem::size_of;
use alloc::{string::String, vec::Vec};
use crate::mm::{verify_area, VirtAddr};
use super::SystemError;
/// 清空用户空间指定范围内的数据
///
/// ## 参数
///
/// - `dest`:用户空间的目标地址
/// - `len`:要清空的数据长度
///
/// ## 返回值
///
/// 返回清空的数据长度
///
/// ## 错误
///
/// - `EFAULT`:目标地址不合法
pub unsafe fn clear_user(dest: VirtAddr, len: usize) -> Result<usize, SystemError> {
verify_area(dest, len).map_err(|_| SystemError::EFAULT)?;
let p = dest.data() as *mut u8;
// 清空用户空间的数据
p.write_bytes(0, len);
return Ok(len);
}
pub unsafe fn copy_to_user(dest: VirtAddr, src: &[u8]) -> Result<usize, SystemError> {
verify_area(dest, src.len()).map_err(|_| SystemError::EFAULT)?;
let p = dest.data() as *mut u8;
// 拷贝数据
p.copy_from_nonoverlapping(src.as_ptr(), src.len());
return Ok(src.len());
}
/// 从用户空间拷贝数据到内核空间
pub unsafe fn copy_from_user(dst: &mut [u8], src: VirtAddr) -> Result<usize, SystemError> {
verify_area(src, dst.len()).map_err(|_| SystemError::EFAULT)?;
let src: &[u8] = core::slice::from_raw_parts(src.data() as *const u8, dst.len());
// 拷贝数据
dst.copy_from_slice(&src);
return Ok(dst.len());
}
/// 检查并从用户态拷贝一个 C 字符串。
///
/// 一旦遇到非法地址,就会返回错误
///
/// ## 参数
///
/// - `user`:用户态的 C 字符串指针
/// - `max_length`:最大拷贝长度
///
/// ## 返回值
///
/// 返回拷贝的 C 字符串
///
/// ## 错误
///
/// - `EFAULT`:用户态地址不合法
pub fn check_and_clone_cstr(
user: *const u8,
max_length: Option<usize>,
) -> Result<String, SystemError> {
if user.is_null() {
return Ok(String::new());
}
// 从用户态读取,直到遇到空字符 '\0' 或者达到最大长度
let mut buffer = Vec::new();
for i in 0.. {
if max_length.is_some() && max_length.as_ref().unwrap() <= &i {
break;
}
let addr = unsafe { user.add(i) };
let mut c = [0u8; 1];
unsafe {
copy_from_user(&mut c, VirtAddr::new(addr as usize))?;
}
if c[0] == 0 {
break;
}
buffer.push(c[0]);
}
return Ok(String::from_utf8(buffer).map_err(|_| SystemError::EFAULT)?);
}
/// 检查并从用户态拷贝一个 C 字符串数组
///
/// 一旦遇到空指针,就会停止拷贝. 一旦遇到非法地址,就会返回错误
/// ## 参数
///
/// - `user`:用户态的 C 字符串指针数组
///
/// ## 返回值
///
/// 返回拷贝的 C 字符串数组
///
/// ## 错误
///
/// - `EFAULT`:用户态地址不合法
pub fn check_and_clone_cstr_array(user: *const *const u8) -> Result<Vec<String>, SystemError> {
if user.is_null() {
Ok(Vec::new())
} else {
// kdebug!("check_and_clone_cstr_array: {:p}\n", user);
let mut buffer = Vec::new();
for i in 0.. {
let addr = unsafe { user.add(i) };
let str_ptr: *const u8;
// 读取这个地址的值(这个值也是一个指针)
unsafe {
let dst = [0usize; 1];
let mut dst = core::mem::transmute::<[usize; 1], [u8; size_of::<usize>()]>(dst);
copy_from_user(&mut dst, VirtAddr::new(addr as usize))?;
let dst = core::mem::transmute::<[u8; size_of::<usize>()], [usize; 1]>(dst);
str_ptr = dst[0] as *const u8;
// kdebug!("str_ptr: {:p}, addr:{addr:?}\n", str_ptr);
}
if str_ptr.is_null() {
break;
}
// 读取这个指针指向的字符串
let string = check_and_clone_cstr(str_ptr, None)?;
// 将字符串放入 buffer 中
buffer.push(string);
}
return Ok(buffer);
}
}