xref: /DragonOS/kernel/src/mm/syscall.rs (revision 6d81180b3b7328466b976b69c5f7782aa66d8a89)
140fe15e0SLoGin use core::intrinsics::unlikely;
240fe15e0SLoGin 
340fe15e0SLoGin use alloc::sync::Arc;
440fe15e0SLoGin 
5ab5c8ca4Slogin use crate::{
640fe15e0SLoGin     arch::MMArch,
740fe15e0SLoGin     kerror,
840fe15e0SLoGin     libs::align::{check_aligned, page_align_up},
940fe15e0SLoGin     mm::MemoryManagementArch,
10ab5c8ca4Slogin     syscall::{Syscall, SystemError},
11ab5c8ca4Slogin };
12ab5c8ca4Slogin 
1340fe15e0SLoGin use super::{
1440fe15e0SLoGin     allocator::page_frame::{PageFrameCount, VirtPageFrame},
1540fe15e0SLoGin     ucontext::{AddressSpace, DEFAULT_MMAP_MIN_ADDR},
1640fe15e0SLoGin     verify_area, VirtAddr,
1740fe15e0SLoGin };
1840fe15e0SLoGin 
1940fe15e0SLoGin bitflags! {
2040fe15e0SLoGin     /// Memory protection flags
2140fe15e0SLoGin     pub struct ProtFlags: u64 {
2240fe15e0SLoGin         const PROT_NONE = 0x0;
2340fe15e0SLoGin         const PROT_READ = 0x1;
2440fe15e0SLoGin         const PROT_WRITE = 0x2;
2540fe15e0SLoGin         const PROT_EXEC = 0x4;
26ab5c8ca4Slogin     }
2740fe15e0SLoGin 
2840fe15e0SLoGin     /// Memory mapping flags
2940fe15e0SLoGin     pub struct MapFlags: u64 {
3040fe15e0SLoGin         const MAP_NONE = 0x0;
3140fe15e0SLoGin         /// share changes
3240fe15e0SLoGin         const MAP_SHARED = 0x1;
3340fe15e0SLoGin         /// changes are private
3440fe15e0SLoGin         const MAP_PRIVATE = 0x2;
3540fe15e0SLoGin         /// Interpret addr exactly
3640fe15e0SLoGin         const MAP_FIXED = 0x10;
3740fe15e0SLoGin         /// don't use a file
3840fe15e0SLoGin         const MAP_ANONYMOUS = 0x20;
3940fe15e0SLoGin         // linux-6.1-rc5/include/uapi/asm-generic/mman.h#7
4040fe15e0SLoGin         /// stack-like segment
4140fe15e0SLoGin         const MAP_GROWSDOWN = 0x100;
4240fe15e0SLoGin         /// ETXTBSY
4340fe15e0SLoGin         const MAP_DENYWRITE = 0x800;
4440fe15e0SLoGin         /// Mark it as an executable
4540fe15e0SLoGin         const MAP_EXECUTABLE = 0x1000;
4640fe15e0SLoGin         /// Pages are locked
4740fe15e0SLoGin         const MAP_LOCKED = 0x2000;
4840fe15e0SLoGin         /// don't check for reservations
4940fe15e0SLoGin         const MAP_NORESERVE = 0x4000;
5040fe15e0SLoGin         /// populate (prefault) pagetables
5140fe15e0SLoGin         const MAP_POPULATE = 0x8000;
5240fe15e0SLoGin         /// do not block on IO
5340fe15e0SLoGin         const MAP_NONBLOCK = 0x10000;
5440fe15e0SLoGin         /// give out an address that is best suited for process/thread stacks
5540fe15e0SLoGin         const MAP_STACK = 0x20000;
5640fe15e0SLoGin         /// create a huge page mapping
5740fe15e0SLoGin         const MAP_HUGETLB = 0x40000;
5840fe15e0SLoGin         /// perform synchronous page faults for the mapping
5940fe15e0SLoGin         const MAP_SYNC = 0x80000;
6040fe15e0SLoGin         /// MAP_FIXED which doesn't unmap underlying mapping
6140fe15e0SLoGin         const MAP_FIXED_NOREPLACE = 0x100000;
6240fe15e0SLoGin 
6340fe15e0SLoGin         /// For anonymous mmap, memory could be uninitialized
6440fe15e0SLoGin         const MAP_UNINITIALIZED = 0x4000000;
6540fe15e0SLoGin 
6640fe15e0SLoGin     }
6740fe15e0SLoGin }
6840fe15e0SLoGin 
69ab5c8ca4Slogin impl Syscall {
7040fe15e0SLoGin     pub fn brk(new_addr: VirtAddr) -> Result<VirtAddr, SystemError> {
7140fe15e0SLoGin         // kdebug!("brk: new_addr={:?}", new_addr);
7240fe15e0SLoGin         let address_space = AddressSpace::current()?;
7340fe15e0SLoGin         let mut address_space = address_space.write();
7440fe15e0SLoGin 
75*6d81180bSLoGin         if new_addr < address_space.brk_start || new_addr >= MMArch::USER_END_VADDR {
76*6d81180bSLoGin             return Ok(address_space.brk);
77*6d81180bSLoGin         }
78*6d81180bSLoGin         if new_addr == address_space.brk {
79*6d81180bSLoGin             return Ok(address_space.brk);
80*6d81180bSLoGin         }
81*6d81180bSLoGin 
8240fe15e0SLoGin         unsafe {
8340fe15e0SLoGin             address_space
8440fe15e0SLoGin                 .set_brk(VirtAddr::new(page_align_up(new_addr.data())))
8540fe15e0SLoGin                 .ok();
8640fe15e0SLoGin 
8740fe15e0SLoGin             return Ok(address_space.sbrk(0).unwrap());
88ab5c8ca4Slogin         }
89d8ad0a5eSLoGin     }
90d8ad0a5eSLoGin 
9140fe15e0SLoGin     pub fn sbrk(incr: isize) -> Result<VirtAddr, SystemError> {
9240fe15e0SLoGin         // kdebug!("pid:{}, sbrk: incr={}", current_pcb().pid, incr);
9340fe15e0SLoGin 
9440fe15e0SLoGin         let address_space = AddressSpace::current()?;
9540fe15e0SLoGin         let mut address_space = address_space.write();
9640fe15e0SLoGin         let r = unsafe { address_space.sbrk(incr) };
9740fe15e0SLoGin 
9840fe15e0SLoGin         // kdebug!("pid:{}, sbrk: r={:?}", current_pcb().pid, r);
9940fe15e0SLoGin         return r;
100d8ad0a5eSLoGin     }
101d8ad0a5eSLoGin 
10240fe15e0SLoGin     /// ## mmap系统调用
103d8ad0a5eSLoGin     ///
10440fe15e0SLoGin     /// 该函数的实现参考了Linux内核的实现,但是并不完全相同。因为有些功能咱们还没实现
10540fe15e0SLoGin     ///
10640fe15e0SLoGin     /// ## 参数
10740fe15e0SLoGin     ///
10840fe15e0SLoGin     /// - `start_vaddr`:映射的起始地址
10940fe15e0SLoGin     /// - `len`:映射的长度
11040fe15e0SLoGin     /// - `prot`:保护标志
11140fe15e0SLoGin     /// - `flags`:映射标志
11240fe15e0SLoGin     /// - `fd`:文件描述符(暂时不支持)
11340fe15e0SLoGin     /// - `offset`:文件偏移量 (暂时不支持)
11440fe15e0SLoGin     ///
11540fe15e0SLoGin     /// ## 返回值
11640fe15e0SLoGin     ///
11740fe15e0SLoGin     /// 成功时返回映射的起始地址,失败时返回错误码
11840fe15e0SLoGin     pub fn mmap(
11940fe15e0SLoGin         start_vaddr: VirtAddr,
12040fe15e0SLoGin         len: usize,
12140fe15e0SLoGin         prot_flags: usize,
12240fe15e0SLoGin         map_flags: usize,
12340fe15e0SLoGin         _fd: i32,
12440fe15e0SLoGin         _offset: usize,
12540fe15e0SLoGin     ) -> Result<usize, SystemError> {
12640fe15e0SLoGin         let map_flags = MapFlags::from_bits_truncate(map_flags as u64);
12740fe15e0SLoGin         let prot_flags = ProtFlags::from_bits_truncate(prot_flags as u64);
12840fe15e0SLoGin 
12940fe15e0SLoGin         if start_vaddr < VirtAddr::new(DEFAULT_MMAP_MIN_ADDR)
13040fe15e0SLoGin             && map_flags.contains(MapFlags::MAP_FIXED)
13140fe15e0SLoGin         {
13240fe15e0SLoGin             kerror!(
13340fe15e0SLoGin                 "mmap: MAP_FIXED is not supported for address below {}",
13440fe15e0SLoGin                 DEFAULT_MMAP_MIN_ADDR
13540fe15e0SLoGin             );
13640fe15e0SLoGin             return Err(SystemError::EINVAL);
137d8ad0a5eSLoGin         }
13840fe15e0SLoGin         // 暂时不支持除匿名页以外的映射
13940fe15e0SLoGin         if !map_flags.contains(MapFlags::MAP_ANONYMOUS) {
14040fe15e0SLoGin             kerror!("mmap: not support file mapping");
14140fe15e0SLoGin             return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
14240fe15e0SLoGin         }
14340fe15e0SLoGin 
14440fe15e0SLoGin         // 暂时不支持巨页映射
14540fe15e0SLoGin         if map_flags.contains(MapFlags::MAP_HUGETLB) {
14640fe15e0SLoGin             kerror!("mmap: not support huge page mapping");
14740fe15e0SLoGin             return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
14840fe15e0SLoGin         }
14940fe15e0SLoGin         let current_address_space = AddressSpace::current()?;
15040fe15e0SLoGin         let start_page = current_address_space.write().map_anonymous(
15140fe15e0SLoGin             start_vaddr,
15240fe15e0SLoGin             len,
15340fe15e0SLoGin             prot_flags,
15440fe15e0SLoGin             map_flags,
15540fe15e0SLoGin             true,
15640fe15e0SLoGin         )?;
15740fe15e0SLoGin         return Ok(start_page.virt_address().data());
15840fe15e0SLoGin     }
15940fe15e0SLoGin 
16040fe15e0SLoGin     /// ## munmap系统调用
16140fe15e0SLoGin     ///
16240fe15e0SLoGin     /// ## 参数
16340fe15e0SLoGin     ///
16440fe15e0SLoGin     /// - `start_vaddr`:取消映射的起始地址(已经对齐到页)
16540fe15e0SLoGin     /// - `len`:取消映射的字节数(已经对齐到页)
16640fe15e0SLoGin     ///
16740fe15e0SLoGin     /// ## 返回值
16840fe15e0SLoGin     ///
16940fe15e0SLoGin     /// 成功时返回0,失败时返回错误码
17040fe15e0SLoGin     pub fn munmap(start_vaddr: VirtAddr, len: usize) -> Result<usize, SystemError> {
17140fe15e0SLoGin         assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE));
17240fe15e0SLoGin         assert!(check_aligned(len, MMArch::PAGE_SIZE));
17340fe15e0SLoGin 
17440fe15e0SLoGin         if unlikely(verify_area(start_vaddr, len).is_err()) {
17540fe15e0SLoGin             return Err(SystemError::EINVAL);
17640fe15e0SLoGin         }
17740fe15e0SLoGin         if unlikely(len == 0) {
17840fe15e0SLoGin             return Err(SystemError::EINVAL);
17940fe15e0SLoGin         }
18040fe15e0SLoGin 
18140fe15e0SLoGin         let current_address_space: Arc<AddressSpace> = AddressSpace::current()?;
18240fe15e0SLoGin         let start_frame = VirtPageFrame::new(start_vaddr);
18340fe15e0SLoGin         let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE);
18440fe15e0SLoGin 
18540fe15e0SLoGin         current_address_space
18640fe15e0SLoGin             .write()
18740fe15e0SLoGin             .munmap(start_frame, page_count)
18840fe15e0SLoGin             .map_err(|_| SystemError::EINVAL)?;
18940fe15e0SLoGin         return Ok(0);
19040fe15e0SLoGin     }
19140fe15e0SLoGin 
19240fe15e0SLoGin     /// ## mprotect系统调用
19340fe15e0SLoGin     ///
19440fe15e0SLoGin     /// ## 参数
19540fe15e0SLoGin     ///
19640fe15e0SLoGin     /// - `start_vaddr`:起始地址(已经对齐到页)
19740fe15e0SLoGin     /// - `len`:长度(已经对齐到页)
19840fe15e0SLoGin     /// - `prot_flags`:保护标志
19940fe15e0SLoGin     pub fn mprotect(
20040fe15e0SLoGin         start_vaddr: VirtAddr,
20140fe15e0SLoGin         len: usize,
20240fe15e0SLoGin         prot_flags: usize,
20340fe15e0SLoGin     ) -> Result<usize, SystemError> {
20440fe15e0SLoGin         assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE));
20540fe15e0SLoGin         assert!(check_aligned(len, MMArch::PAGE_SIZE));
20640fe15e0SLoGin 
20740fe15e0SLoGin         if unlikely(verify_area(start_vaddr, len).is_err()) {
20840fe15e0SLoGin             return Err(SystemError::EINVAL);
20940fe15e0SLoGin         }
21040fe15e0SLoGin         if unlikely(len == 0) {
21140fe15e0SLoGin             return Err(SystemError::EINVAL);
21240fe15e0SLoGin         }
21340fe15e0SLoGin 
21440fe15e0SLoGin         let prot_flags = ProtFlags::from_bits(prot_flags as u64).ok_or(SystemError::EINVAL)?;
21540fe15e0SLoGin 
21640fe15e0SLoGin         let current_address_space: Arc<AddressSpace> = AddressSpace::current()?;
21740fe15e0SLoGin         let start_frame = VirtPageFrame::new(start_vaddr);
21840fe15e0SLoGin         let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE);
21940fe15e0SLoGin 
22040fe15e0SLoGin         current_address_space
22140fe15e0SLoGin             .write()
22240fe15e0SLoGin             .mprotect(start_frame, page_count, prot_flags)
22340fe15e0SLoGin             .map_err(|_| SystemError::EINVAL)?;
22440fe15e0SLoGin         return Ok(0);
225ab5c8ca4Slogin     }
226ab5c8ca4Slogin }
227