|
1 | 1 | //! Process management syscalls |
2 | | -use crate::task::{change_program_brk, exit_current_and_run_next, suspend_current_and_run_next}; |
| 2 | +use crate::{mm::{translated_physaddr, MapPermission, PTEFlags, PageTable, VirtAddr}, task::{change_program_brk, current_user_token, exit_current_and_run_next, suspend_current_and_run_next, TASK_MANAGER}, timer::get_time_us}; |
3 | 3 |
|
4 | 4 | #[repr(C)] |
5 | 5 | #[derive(Debug)] |
@@ -27,26 +27,126 @@ pub fn sys_yield() -> isize { |
27 | 27 | /// HINT: What if [`TimeVal`] is splitted by two pages ? |
28 | 28 | pub fn sys_get_time(_ts: *mut TimeVal, _tz: usize) -> isize { |
29 | 29 | trace!("kernel: sys_get_time"); |
30 | | - -1 |
| 30 | + let pa = translated_physaddr(current_user_token(), _ts as *const u8); |
| 31 | + let phy_ts = pa.0 as *mut TimeVal; |
| 32 | + |
| 33 | + let us = get_time_us(); |
| 34 | + let time_val = TimeVal { |
| 35 | + sec : us / 1_000_000, |
| 36 | + usec: us % 1_000_000, |
| 37 | + }; |
| 38 | + |
| 39 | + unsafe { *phy_ts = time_val }; |
| 40 | + 0 |
| 41 | +} |
| 42 | + |
| 43 | +fn is_readable(va: usize) -> bool { |
| 44 | + let vpn = VirtAddr::from(va).floor(); |
| 45 | + if let Some(pte) = PageTable::from_token(current_user_token()).translate(vpn) { |
| 46 | + pte.flags().contains(PTEFlags::U | PTEFlags::R) |
| 47 | + } else { |
| 48 | + false |
| 49 | + } |
| 50 | +} |
| 51 | + |
| 52 | +fn is_writeable(va: usize) -> bool { |
| 53 | + let vpn = VirtAddr::from(va).floor(); |
| 54 | + if let Some(pte) = PageTable::from_token(current_user_token()).translate(vpn) { |
| 55 | + pte.flags().contains(PTEFlags::U | PTEFlags::W) |
| 56 | + } else { |
| 57 | + false |
| 58 | + } |
31 | 59 | } |
32 | 60 |
|
33 | 61 | /// TODO: Finish sys_trace to pass testcases |
34 | 62 | /// HINT: You might reimplement it with virtual memory management. |
35 | 63 | pub fn sys_trace(_trace_request: usize, _id: usize, _data: usize) -> isize { |
36 | 64 | trace!("kernel: sys_trace"); |
37 | | - -1 |
| 65 | + match _trace_request { |
| 66 | + 0 => { |
| 67 | + if !is_readable(_id) { |
| 68 | + return -1; |
| 69 | + } |
| 70 | + let pa = translated_physaddr(current_user_token(), _id as *const u8); |
| 71 | + let phy_data = pa.0 as *mut u8; |
| 72 | + unsafe { (*phy_data).into() } |
| 73 | + }, |
| 74 | + 1 => { |
| 75 | + if !is_writeable(_id) { |
| 76 | + return -1; |
| 77 | + } |
| 78 | + let pa = translated_physaddr(current_user_token(), _id as *const u8); |
| 79 | + let phy_data = pa.0 as *mut u8; |
| 80 | + unsafe { *phy_data = _data as u8 ; }; |
| 81 | + return 0; |
| 82 | + }, |
| 83 | + 2 => TASK_MANAGER.get_syscall_counter(_id).try_into().unwrap(), |
| 84 | + _ => -1 |
| 85 | + } |
| 86 | +} |
| 87 | + |
| 88 | +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] |
| 89 | +pub struct Flag(pub usize); |
| 90 | + |
| 91 | +impl Flag { |
| 92 | + pub fn is_readable(&self) -> bool { |
| 93 | + self.0 & 0x1 == 0x1 |
| 94 | + } |
| 95 | + |
| 96 | + pub fn is_writeable(&self) -> bool { |
| 97 | + self.0 & 0x2 == 0x2 |
| 98 | + } |
| 99 | + |
| 100 | + pub fn is_execute(&self) -> bool { |
| 101 | + self.0 & 0x4 == 0x4 |
| 102 | + } |
38 | 103 | } |
39 | 104 |
|
40 | 105 | // YOUR JOB: Implement mmap. |
41 | 106 | pub fn sys_mmap(_start: usize, _len: usize, _port: usize) -> isize { |
42 | | - trace!("kernel: sys_mmap NOT IMPLEMENTED YET!"); |
43 | | - -1 |
| 107 | + trace!("kernel: sys_mmap "); |
| 108 | + |
| 109 | + debug!("mmap start: {}, len: {}, port: {}", _start, _len, _port); |
| 110 | + |
| 111 | + let start_va = VirtAddr::from(_start); |
| 112 | + if !start_va.aligned() { |
| 113 | + return -1; |
| 114 | + } |
| 115 | + let end_va: VirtAddr = (_start + _len).into(); |
| 116 | + if _port & !0x7 != 0 || _port & 0x7 == 0 { |
| 117 | + return -1; |
| 118 | + } |
| 119 | + |
| 120 | + let mut map_perm: MapPermission = MapPermission::U; |
| 121 | + let pte_flag = Flag(_port); |
| 122 | + if pte_flag.is_readable() { |
| 123 | + map_perm |= MapPermission::R; |
| 124 | + } |
| 125 | + if pte_flag.is_writeable() { |
| 126 | + map_perm |= MapPermission::W; |
| 127 | + } |
| 128 | + if pte_flag.is_execute() { |
| 129 | + map_perm |= MapPermission::X; |
| 130 | + } |
| 131 | + |
| 132 | + if !TASK_MANAGER.find_area_insert(start_va, end_va, map_perm) { |
| 133 | + return -1; |
| 134 | + } |
| 135 | + return 0; |
44 | 136 | } |
45 | 137 |
|
46 | 138 | // YOUR JOB: Implement munmap. |
47 | 139 | pub fn sys_munmap(_start: usize, _len: usize) -> isize { |
48 | | - trace!("kernel: sys_munmap NOT IMPLEMENTED YET!"); |
49 | | - -1 |
| 140 | + trace!("kernel: sys_munmap "); |
| 141 | + let start_va = VirtAddr::from(_start); |
| 142 | + if !start_va.aligned() { |
| 143 | + return -1; |
| 144 | + } |
| 145 | + let end_va: VirtAddr = (_start + _len).into(); |
| 146 | + if !TASK_MANAGER.find_area_remove(start_va, end_va) { |
| 147 | + return -1; |
| 148 | + } |
| 149 | + return 0; |
50 | 150 | } |
51 | 151 | /// change data segment size |
52 | 152 | pub fn sys_sbrk(size: i32) -> isize { |
|
0 commit comments