xref: /DragonOS/kernel/src/mm/syscall.rs (revision d8ad0a5e7724469abd5cc3cf271993538878033e)
1*d8ad0a5eSLoGin use core::intrinsics::unlikely;
2*d8ad0a5eSLoGin 
3*d8ad0a5eSLoGin use alloc::sync::Arc;
4*d8ad0a5eSLoGin 
5ab5c8ca4Slogin use crate::{
6*d8ad0a5eSLoGin     arch::MMArch,
7*d8ad0a5eSLoGin     kerror,
8*d8ad0a5eSLoGin     libs::align::{check_aligned, page_align_up},
9*d8ad0a5eSLoGin     mm::MemoryManagementArch,
10ab5c8ca4Slogin     syscall::{Syscall, SystemError},
11ab5c8ca4Slogin };
12ab5c8ca4Slogin 
13*d8ad0a5eSLoGin use super::{
14*d8ad0a5eSLoGin     allocator::page_frame::{PageFrameCount, VirtPageFrame},
15*d8ad0a5eSLoGin     ucontext::{AddressSpace, DEFAULT_MMAP_MIN_ADDR},
16*d8ad0a5eSLoGin     verify_area, VirtAddr,
17*d8ad0a5eSLoGin };
18*d8ad0a5eSLoGin 
19*d8ad0a5eSLoGin bitflags! {
20*d8ad0a5eSLoGin     /// Memory protection flags
21*d8ad0a5eSLoGin     pub struct ProtFlags: u64 {
22*d8ad0a5eSLoGin         const PROT_NONE = 0x0;
23*d8ad0a5eSLoGin         const PROT_READ = 0x1;
24*d8ad0a5eSLoGin         const PROT_WRITE = 0x2;
25*d8ad0a5eSLoGin         const PROT_EXEC = 0x4;
26ab5c8ca4Slogin     }
27*d8ad0a5eSLoGin 
28*d8ad0a5eSLoGin     /// Memory mapping flags
29*d8ad0a5eSLoGin     pub struct MapFlags: u64 {
30*d8ad0a5eSLoGin         const MAP_NONE = 0x0;
31*d8ad0a5eSLoGin         /// share changes
32*d8ad0a5eSLoGin         const MAP_SHARED = 0x1;
33*d8ad0a5eSLoGin         /// changes are private
34*d8ad0a5eSLoGin         const MAP_PRIVATE = 0x2;
35*d8ad0a5eSLoGin         /// Interpret addr exactly
36*d8ad0a5eSLoGin         const MAP_FIXED = 0x10;
37*d8ad0a5eSLoGin         /// don't use a file
38*d8ad0a5eSLoGin         const MAP_ANONYMOUS = 0x20;
39*d8ad0a5eSLoGin         // linux-6.1-rc5/include/uapi/asm-generic/mman.h#7
40*d8ad0a5eSLoGin         /// stack-like segment
41*d8ad0a5eSLoGin         const MAP_GROWSDOWN = 0x100;
42*d8ad0a5eSLoGin         /// ETXTBSY
43*d8ad0a5eSLoGin         const MAP_DENYWRITE = 0x800;
44*d8ad0a5eSLoGin         /// Mark it as an executable
45*d8ad0a5eSLoGin         const MAP_EXECUTABLE = 0x1000;
46*d8ad0a5eSLoGin         /// Pages are locked
47*d8ad0a5eSLoGin         const MAP_LOCKED = 0x2000;
48*d8ad0a5eSLoGin         /// don't check for reservations
49*d8ad0a5eSLoGin         const MAP_NORESERVE = 0x4000;
50*d8ad0a5eSLoGin         /// populate (prefault) pagetables
51*d8ad0a5eSLoGin         const MAP_POPULATE = 0x8000;
52*d8ad0a5eSLoGin         /// do not block on IO
53*d8ad0a5eSLoGin         const MAP_NONBLOCK = 0x10000;
54*d8ad0a5eSLoGin         /// give out an address that is best suited for process/thread stacks
55*d8ad0a5eSLoGin         const MAP_STACK = 0x20000;
56*d8ad0a5eSLoGin         /// create a huge page mapping
57*d8ad0a5eSLoGin         const MAP_HUGETLB = 0x40000;
58*d8ad0a5eSLoGin         /// perform synchronous page faults for the mapping
59*d8ad0a5eSLoGin         const MAP_SYNC = 0x80000;
60*d8ad0a5eSLoGin         /// MAP_FIXED which doesn't unmap underlying mapping
61*d8ad0a5eSLoGin         const MAP_FIXED_NOREPLACE = 0x100000;
62*d8ad0a5eSLoGin 
63*d8ad0a5eSLoGin         /// For anonymous mmap, memory could be uninitialized
64*d8ad0a5eSLoGin         const MAP_UNINITIALIZED = 0x4000000;
65*d8ad0a5eSLoGin 
66*d8ad0a5eSLoGin     }
67*d8ad0a5eSLoGin }
68*d8ad0a5eSLoGin 
69ab5c8ca4Slogin impl Syscall {
70*d8ad0a5eSLoGin     pub fn brk(new_addr: VirtAddr) -> Result<VirtAddr, SystemError> {
71*d8ad0a5eSLoGin         // kdebug!("brk: new_addr={:?}", new_addr);
72*d8ad0a5eSLoGin         let address_space = AddressSpace::current()?;
73*d8ad0a5eSLoGin         let mut address_space = address_space.write();
74*d8ad0a5eSLoGin 
75*d8ad0a5eSLoGin         unsafe {
76*d8ad0a5eSLoGin             address_space
77*d8ad0a5eSLoGin                 .set_brk(VirtAddr::new(page_align_up(new_addr.data())))
78*d8ad0a5eSLoGin                 .ok();
79*d8ad0a5eSLoGin 
80*d8ad0a5eSLoGin             return Ok(address_space.sbrk(0).unwrap());
81ab5c8ca4Slogin         }
82ab5c8ca4Slogin     }
83ab5c8ca4Slogin 
84*d8ad0a5eSLoGin     pub fn sbrk(incr: isize) -> Result<VirtAddr, SystemError> {
85*d8ad0a5eSLoGin         // kdebug!("pid:{}, sbrk: incr={}", current_pcb().pid, incr);
86*d8ad0a5eSLoGin 
87*d8ad0a5eSLoGin         let address_space = AddressSpace::current()?;
88*d8ad0a5eSLoGin         let mut address_space = address_space.write();
89*d8ad0a5eSLoGin         let r = unsafe { address_space.sbrk(incr) };
90*d8ad0a5eSLoGin 
91*d8ad0a5eSLoGin         // kdebug!("pid:{}, sbrk: r={:?}", current_pcb().pid, r);
92*d8ad0a5eSLoGin         return r;
93ab5c8ca4Slogin     }
94ab5c8ca4Slogin 
95*d8ad0a5eSLoGin     /// ## mmap系统调用
96ab5c8ca4Slogin     ///
97*d8ad0a5eSLoGin     /// 该函数的实现参考了Linux内核的实现,但是并不完全相同。因为有些功能咱们还没实现
98*d8ad0a5eSLoGin     ///
99*d8ad0a5eSLoGin     /// ## 参数
100*d8ad0a5eSLoGin     ///
101*d8ad0a5eSLoGin     /// - `start_vaddr`:映射的起始地址
102*d8ad0a5eSLoGin     /// - `len`:映射的长度
103*d8ad0a5eSLoGin     /// - `prot`:保护标志
104*d8ad0a5eSLoGin     /// - `flags`:映射标志
105*d8ad0a5eSLoGin     /// - `fd`:文件描述符(暂时不支持)
106*d8ad0a5eSLoGin     /// - `offset`:文件偏移量 (暂时不支持)
107*d8ad0a5eSLoGin     ///
108*d8ad0a5eSLoGin     /// ## 返回值
109*d8ad0a5eSLoGin     ///
110*d8ad0a5eSLoGin     /// 成功时返回映射的起始地址,失败时返回错误码
111*d8ad0a5eSLoGin     pub fn mmap(
112*d8ad0a5eSLoGin         start_vaddr: VirtAddr,
113*d8ad0a5eSLoGin         len: usize,
114*d8ad0a5eSLoGin         prot_flags: usize,
115*d8ad0a5eSLoGin         map_flags: usize,
116*d8ad0a5eSLoGin         _fd: i32,
117*d8ad0a5eSLoGin         _offset: usize,
118*d8ad0a5eSLoGin     ) -> Result<usize, SystemError> {
119*d8ad0a5eSLoGin         let map_flags = MapFlags::from_bits_truncate(map_flags as u64);
120*d8ad0a5eSLoGin         let prot_flags = ProtFlags::from_bits_truncate(prot_flags as u64);
121*d8ad0a5eSLoGin 
122*d8ad0a5eSLoGin         if start_vaddr < VirtAddr::new(DEFAULT_MMAP_MIN_ADDR)
123*d8ad0a5eSLoGin             && map_flags.contains(MapFlags::MAP_FIXED)
124*d8ad0a5eSLoGin         {
125*d8ad0a5eSLoGin             kerror!(
126*d8ad0a5eSLoGin                 "mmap: MAP_FIXED is not supported for address below {}",
127*d8ad0a5eSLoGin                 DEFAULT_MMAP_MIN_ADDR
128*d8ad0a5eSLoGin             );
129*d8ad0a5eSLoGin             return Err(SystemError::EINVAL);
130ab5c8ca4Slogin         }
131*d8ad0a5eSLoGin         // 暂时不支持除匿名页以外的映射
132*d8ad0a5eSLoGin         if !map_flags.contains(MapFlags::MAP_ANONYMOUS) {
133*d8ad0a5eSLoGin             kerror!("mmap: not support file mapping");
134*d8ad0a5eSLoGin             return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
135*d8ad0a5eSLoGin         }
136*d8ad0a5eSLoGin 
137*d8ad0a5eSLoGin         // 暂时不支持巨页映射
138*d8ad0a5eSLoGin         if map_flags.contains(MapFlags::MAP_HUGETLB) {
139*d8ad0a5eSLoGin             kerror!("mmap: not support huge page mapping");
140*d8ad0a5eSLoGin             return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
141*d8ad0a5eSLoGin         }
142*d8ad0a5eSLoGin         let current_address_space = AddressSpace::current()?;
143*d8ad0a5eSLoGin         let start_page = current_address_space.write().map_anonymous(
144*d8ad0a5eSLoGin             start_vaddr,
145*d8ad0a5eSLoGin             len,
146*d8ad0a5eSLoGin             prot_flags,
147*d8ad0a5eSLoGin             map_flags,
148*d8ad0a5eSLoGin             true,
149*d8ad0a5eSLoGin         )?;
150*d8ad0a5eSLoGin         return Ok(start_page.virt_address().data());
151*d8ad0a5eSLoGin     }
152*d8ad0a5eSLoGin 
153*d8ad0a5eSLoGin     /// ## munmap系统调用
154*d8ad0a5eSLoGin     ///
155*d8ad0a5eSLoGin     /// ## 参数
156*d8ad0a5eSLoGin     ///
157*d8ad0a5eSLoGin     /// - `start_vaddr`:取消映射的起始地址(已经对齐到页)
158*d8ad0a5eSLoGin     /// - `len`:取消映射的字节数(已经对齐到页)
159*d8ad0a5eSLoGin     ///
160*d8ad0a5eSLoGin     /// ## 返回值
161*d8ad0a5eSLoGin     ///
162*d8ad0a5eSLoGin     /// 成功时返回0,失败时返回错误码
163*d8ad0a5eSLoGin     pub fn munmap(start_vaddr: VirtAddr, len: usize) -> Result<usize, SystemError> {
164*d8ad0a5eSLoGin         assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE));
165*d8ad0a5eSLoGin         assert!(check_aligned(len, MMArch::PAGE_SIZE));
166*d8ad0a5eSLoGin 
167*d8ad0a5eSLoGin         if unlikely(verify_area(start_vaddr, len).is_err()) {
168*d8ad0a5eSLoGin             return Err(SystemError::EINVAL);
169*d8ad0a5eSLoGin         }
170*d8ad0a5eSLoGin         if unlikely(len == 0) {
171*d8ad0a5eSLoGin             return Err(SystemError::EINVAL);
172*d8ad0a5eSLoGin         }
173*d8ad0a5eSLoGin 
174*d8ad0a5eSLoGin         let current_address_space: Arc<AddressSpace> = AddressSpace::current()?;
175*d8ad0a5eSLoGin         let start_frame = VirtPageFrame::new(start_vaddr);
176*d8ad0a5eSLoGin         let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE);
177*d8ad0a5eSLoGin 
178*d8ad0a5eSLoGin         current_address_space
179*d8ad0a5eSLoGin             .write()
180*d8ad0a5eSLoGin             .munmap(start_frame, page_count)
181*d8ad0a5eSLoGin             .map_err(|_| SystemError::EINVAL)?;
182*d8ad0a5eSLoGin         return Ok(0);
183*d8ad0a5eSLoGin     }
184*d8ad0a5eSLoGin 
185*d8ad0a5eSLoGin     /// ## mprotect系统调用
186*d8ad0a5eSLoGin     ///
187*d8ad0a5eSLoGin     /// ## 参数
188*d8ad0a5eSLoGin     ///
189*d8ad0a5eSLoGin     /// - `start_vaddr`:起始地址(已经对齐到页)
190*d8ad0a5eSLoGin     /// - `len`:长度(已经对齐到页)
191*d8ad0a5eSLoGin     /// - `prot_flags`:保护标志
192*d8ad0a5eSLoGin     pub fn mprotect(
193*d8ad0a5eSLoGin         start_vaddr: VirtAddr,
194*d8ad0a5eSLoGin         len: usize,
195*d8ad0a5eSLoGin         prot_flags: usize,
196*d8ad0a5eSLoGin     ) -> Result<usize, SystemError> {
197*d8ad0a5eSLoGin         assert!(start_vaddr.check_aligned(MMArch::PAGE_SIZE));
198*d8ad0a5eSLoGin         assert!(check_aligned(len, MMArch::PAGE_SIZE));
199*d8ad0a5eSLoGin 
200*d8ad0a5eSLoGin         if unlikely(verify_area(start_vaddr, len).is_err()) {
201*d8ad0a5eSLoGin             return Err(SystemError::EINVAL);
202*d8ad0a5eSLoGin         }
203*d8ad0a5eSLoGin         if unlikely(len == 0) {
204*d8ad0a5eSLoGin             return Err(SystemError::EINVAL);
205*d8ad0a5eSLoGin         }
206*d8ad0a5eSLoGin 
207*d8ad0a5eSLoGin         let prot_flags = ProtFlags::from_bits(prot_flags as u64).ok_or(SystemError::EINVAL)?;
208*d8ad0a5eSLoGin 
209*d8ad0a5eSLoGin         let current_address_space: Arc<AddressSpace> = AddressSpace::current()?;
210*d8ad0a5eSLoGin         let start_frame = VirtPageFrame::new(start_vaddr);
211*d8ad0a5eSLoGin         let page_count = PageFrameCount::new(len / MMArch::PAGE_SIZE);
212*d8ad0a5eSLoGin 
213*d8ad0a5eSLoGin         current_address_space
214*d8ad0a5eSLoGin             .write()
215*d8ad0a5eSLoGin             .mprotect(start_frame, page_count, prot_flags)
216*d8ad0a5eSLoGin             .map_err(|_| SystemError::EINVAL)?;
217*d8ad0a5eSLoGin         return Ok(0);
218ab5c8ca4Slogin     }
219ab5c8ca4Slogin }
220