Files
DragonOS/kernel/src/mm/syscall.rs
LoGin 1496ba7b24 进程管理模块重构完成 (#380)
* 添加新版pcb的数据结构 (#273)

* 将pcb中的内容分类,分别加锁 (#305)

* 进程管理重构:完成fork的主体逻辑 (#309)

1.完成fork的主体逻辑
2.将文件系统接到新的pcb上
3.经过思考,暂时弃用signal机制,待进程管理重构完成后,重写signal机制.原因是原本的signal机制太烂了

* chdir getcwd pid pgid ppid (#310)


---------

Co-authored-by: longjin <longjin@RinGoTek.cn>

* 删除旧的fork以及signal的代码,并调整fork/vfork/execve系统调用 (#325)

1.删除旧的fork
2.删除signal相关代码,等进程管理重构结束之后,再重新写.
3.调整了fork/vfork/execve系统调用

* 实现切换进程的代码 (#331)



* 实现切换进程的代码

* Patch modify preempt (#332)

* 修改设置preempt的代码

* 删除rust的list和refcount

* 为每个核心初始化idle进程 (#333)

* 为每个核心初始化idle进程

* 完成了新的内核线程机制 (#335)

* 调度器的pcb替换为新的Arc<ProcessControlBlock>,把调度器队列锁从 RwSpinLock 替换为了 SpinLock (#336)

* 把调度器的pcb替换为新的Arc<ProcessControlBlock>

* 把调度器队列锁从 RwSpinLock 替换为了 SpinLock ,修改了签名以通过编译

* 修正一些双重加锁、细节问题

---------

Co-authored-by: longjin <longjin@RinGoTek.cn>

* github workflow自动检查代码是否格式化

* cache toolchain yml

* 调整rust版本的waitqueue中的pcb为新版的pcb (#343)

* 解决设置rust workspace带来的“工具链不一致”的问题 (#344)


* 解决设置rust workspace带来的“工具链不一致”的问题

更改workflow

* 调整pcb的sched_info和rwlock,以避免调度器死锁问题 (#341)

* 调整pcb的sched_info和rwlock,以避免调度器死锁问题

* 修改为在 WriterGuard 中维护 Irq_guard

* 修正了 write_irqsave方法

* 优化了代码

* 把 set state 操作从 wakup 移动到 sched_enqueue 中

* 修正为在 wakeup 中设置 running ,以保留 set_state 的私有性

* 移除了 process_wakeup

* 实现进程退出的逻辑 (#340)

实现进程退出的逻辑

* 标志进程sleep

* 修复wakeup的问题

---------

Co-authored-by: longjin <longjin@RinGoTek.cn>

* rust 重构 completion (#350)

* 完成了completion的基本结构,待完善上级调用

* 用SpinLock保护结构体并发安全

* 修改原子变量为u32,修复符号错误

* irq guard

* 修改为具有内部可变性的结构体

* temp fix

* 修复了由于进程持有自旋锁导致的不被调度的问题

* 对 complete 系列方法上锁,保护 done 数据并发安全

* 移除了未使用的依赖

* 重写显示刷新驱动 (#363)

* 重构显示刷新驱动

* Patch refactor process management (#366)

* 维护进程树

* 维护进程树

* 更改代码结构

* 新建进程时,设置cwd

* 调整adopt childern函数,降低开销

---------

Co-authored-by: longjin <longjin@RinGoTek.cn>

* waitqueue兼容C部分 (#351)

* PATH

* safe init

* waitqueue兼容C部分

* waitqueue兼容C部分

* 删除semaphore.c,在ps2_keyboard中使用waitqueue

* 删除semaphore.c,在ps2_keyboard中使用waitqueue

* current_pcb的C兼容

* current_pcb的C兼容

* current_pcb的C兼容

* fmt

* current_pcb的兼容

* 针对修改

* 调整代码

* fmt

* 删除pcb的set flags

* 更改函数名

---------

Co-authored-by: longjin <longjin@RinGoTek.cn>

* merge master

* Patch debug process management refactor (#372)

* 能够调通,执行完textui_init

* 能跑到initial kernel thread

* fmt

* 能够正常初始化所有服务(尚未能切换到用户程序)

* 删除部分无用的extern

* 存在问题:ap处理器启动后,bsp的smp_init函数return之后就出错了,怀疑是栈损坏

* 解决smp启动由于未换栈导致的内存访问错误

* debug

* 1

* 1

* lock no preempt

* 调通

* 优化代码,删除一些调试日志

* fix

* 使用rust重写wait4 (#377)

* 维护进程树

* 维护进程树

* 更改代码结构

* 新建进程时,设置cwd

* 调整adopt childern函数,降低开销

* wait4

* 删除c_sys_wait4

* 使用userbuffer保护裸指针

---------

Co-authored-by: longjin <longjin@RinGoTek.cn>

* 消除warning

* 1. 修正未设置cpu executing的问题

* 修正kthread机制可能存在的内存泄露问题

* 删除pcb文档

* 删除C的tss struct

---------

Co-authored-by: Bullet <93781792+GP-Bullet@users.noreply.github.com>
Co-authored-by: Chiichen <39649411+Chiichen@users.noreply.github.com>
Co-authored-by: hanjiezhou <zhouhanjie@dragonos.org>
Co-authored-by: GnoCiYeH <118462160+GnoCiYeH@users.noreply.github.com>
Co-authored-by: houmkh <1119644616@qq.com>
2023-09-15 14:58:19 +08:00

225 lines
7.1 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::intrinsics::unlikely;
use alloc::sync::Arc;
use crate::{
arch::MMArch,
kerror,
libs::align::{check_aligned, page_align_up},
mm::MemoryManagementArch,
syscall::{Syscall, SystemError},
};
use super::{
allocator::page_frame::{PageFrameCount, VirtPageFrame},
ucontext::{AddressSpace, DEFAULT_MMAP_MIN_ADDR},
verify_area, VirtAddr,
};
bitflags! {
/// Memory protection flags
pub struct ProtFlags: u64 {
const PROT_NONE = 0x0;
const PROT_READ = 0x1;
const PROT_WRITE = 0x2;
const PROT_EXEC = 0x4;
}
/// Memory mapping flags
pub struct MapFlags: u64 {
const MAP_NONE = 0x0;
/// share changes
const MAP_SHARED = 0x1;
/// changes are private
const MAP_PRIVATE = 0x2;
/// Interpret addr exactly
const MAP_FIXED = 0x10;
/// don't use a file
const MAP_ANONYMOUS = 0x20;
// linux-6.1-rc5/include/uapi/asm-generic/mman.h#7
/// stack-like segment
const MAP_GROWSDOWN = 0x100;
/// ETXTBSY
const MAP_DENYWRITE = 0x800;
/// Mark it as an executable
const MAP_EXECUTABLE = 0x1000;
/// Pages are locked
const MAP_LOCKED = 0x2000;
/// don't check for reservations
const MAP_NORESERVE = 0x4000;
/// populate (prefault) pagetables
const MAP_POPULATE = 0x8000;
/// do not block on IO
const MAP_NONBLOCK = 0x10000;
/// give out an address that is best suited for process/thread stacks
const MAP_STACK = 0x20000;
/// create a huge page mapping
const MAP_HUGETLB = 0x40000;
/// perform synchronous page faults for the mapping
const MAP_SYNC = 0x80000;
/// MAP_FIXED which doesn't unmap underlying mapping
const MAP_FIXED_NOREPLACE = 0x100000;
/// For anonymous mmap, memory could be uninitialized
const MAP_UNINITIALIZED = 0x4000000;
}
}
impl Syscall {
pub fn brk(new_addr: VirtAddr) -> Result<VirtAddr, SystemError> {
// kdebug!("brk: new_addr={:?}", new_addr);
let address_space = AddressSpace::current()?;
let mut address_space = address_space.write();
if new_addr < address_space.brk_start || new_addr >= MMArch::USER_END_VADDR {
return Ok(address_space.brk);
}
if new_addr == address_space.brk {
return Ok(address_space.brk);
}
unsafe {
address_space
.set_brk(VirtAddr::new(page_align_up(new_addr.data())))
.ok();
return Ok(address_space.sbrk(0).unwrap());
}
}
pub fn sbrk(incr: isize) -> Result<VirtAddr, SystemError> {
let address_space = AddressSpace::current()?;
assert!(address_space.read().user_mapper.utable.is_current());
let mut address_space = address_space.write();
let r = unsafe { address_space.sbrk(incr) };
return r;
}
/// ## mmap系统调用
///
/// 该函数的实现参考了Linux内核的实现但是并不完全相同。因为有些功能咱们还没实现
///
/// ## 参数
///
/// - `start_vaddr`:映射的起始地址
/// - `len`:映射的长度
/// - `prot`:保护标志
/// - `flags`:映射标志
/// - `fd`:文件描述符(暂时不支持)
/// - `offset`:文件偏移量 (暂时不支持)
///
/// ## 返回值
///
/// 成功时返回映射的起始地址,失败时返回错误码
pub fn mmap(
start_vaddr: VirtAddr,
len: usize,
prot_flags: usize,
map_flags: usize,
_fd: i32,
_offset: usize,
) -> Result<usize, SystemError> {
let map_flags = MapFlags::from_bits_truncate(map_flags as u64);
let prot_flags = ProtFlags::from_bits_truncate(prot_flags as u64);
if start_vaddr < VirtAddr::new(DEFAULT_MMAP_MIN_ADDR)
&& map_flags.contains(MapFlags::MAP_FIXED)
{
kerror!(
"mmap: MAP_FIXED is not supported for address below {}",
DEFAULT_MMAP_MIN_ADDR
);
return Err(SystemError::EINVAL);
}
// 暂时不支持除匿名页以外的映射
if !map_flags.contains(MapFlags::MAP_ANONYMOUS) {
kerror!("mmap: not support file mapping");
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
// 暂时不支持巨页映射
if map_flags.contains(MapFlags::MAP_HUGETLB) {
kerror!("mmap: not support huge page mapping");
return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
}
let current_address_space = AddressSpace::current()?;
let start_page = current_address_space.write().map_anonymous(
start_vaddr,
len,
prot_flags,
map_flags,
true,
)?;
return Ok(start_page.virt_address().data());
}
/// ## munmap系统调用
///
/// ## 参数
///
/// - `start_vaddr`:取消映射的起始地址(已经对齐到页)
/// - `len`:取消映射的字节数(已经对齐到页)
///
/// ## 返回值
///
/// 成功时返回0失败时返回错误码
pub fn munmap(start_vaddr: VirtAddr, len: usize) -> Result<usize, SystemError> {
assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE));
assert!(check_aligned(len, MMArch::PAGE_SIZE));
if unlikely(verify_area(start_vaddr, len).is_err()) {
return Err(SystemError::EINVAL);
}
if unlikely(len == 0) {
return Err(SystemError::EINVAL);
}
let current_address_space: Arc<AddressSpace> = AddressSpace::current()?;
let start_frame = VirtPageFrame::new(start_vaddr);
let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE);
current_address_space
.write()
.munmap(start_frame, page_count)
.map_err(|_| SystemError::EINVAL)?;
return Ok(0);
}
/// ## mprotect系统调用
///
/// ## 参数
///
/// - `start_vaddr`:起始地址(已经对齐到页)
/// - `len`:长度(已经对齐到页)
/// - `prot_flags`:保护标志
pub fn mprotect(
start_vaddr: VirtAddr,
len: usize,
prot_flags: usize,
) -> Result<usize, SystemError> {
assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE));
assert!(check_aligned(len, MMArch::PAGE_SIZE));
if unlikely(verify_area(start_vaddr, len).is_err()) {
return Err(SystemError::EINVAL);
}
if unlikely(len == 0) {
return Err(SystemError::EINVAL);
}
let prot_flags = ProtFlags::from_bits(prot_flags as u64).ok_or(SystemError::EINVAL)?;
let current_address_space: Arc<AddressSpace> = AddressSpace::current()?;
let start_frame = VirtPageFrame::new(start_vaddr);
let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE);
current_address_space
.write()
.mprotect(start_frame, page_count, prot_flags)
.map_err(|_| SystemError::EINVAL)?;
return Ok(0);
}
}