Nothing to see here, move along meow
0

Configure Feed

Select the types of activity you want to include in your feed.

at main 8.9 kB View raw
1use crate::cap::cnode; 2use crate::cap::frame_table::FRAME_TABLE; 3use crate::cap::object::ObjectTag; 4use crate::cap::ops; 5use crate::cap::pool::POOL; 6use crate::cap::table::Rights; 7use crate::error::KernelError; 8use crate::mem::phys::BitmapFrameAllocator; 9use crate::proc::PROCESSES; 10use crate::proc::address_space::{self, PageAccess}; 11use crate::proc::context::CpuContext; 12use crate::syscall::{SyscallResult, try_syscall, validate_user_vaddr}; 13use lancer_core::object_layout::FrameObject; 14use x86_64::addr::PhysAddr; 15 16pub fn sys_frame_map(ctx: &mut CpuContext) { 17 let frame_slot = ctx.rdi; 18 let vaddr_raw = ctx.rsi; 19 let flags = ctx.rdx; 20 let pid = crate::arch::syscall::current_pid(); 21 22 let vaddr = try_syscall!(ctx, validate_user_vaddr(vaddr_raw)); 23 24 let writable = flags & 1 != 0; 25 let executable = flags & 2 != 0; 26 let required_rights = match writable { 27 true => Rights::WRITE, 28 false => Rights::READ, 29 }; 30 31 let access = match (writable, executable) { 32 (false, false) => PageAccess::ReadOnly, 33 (true, false) => PageAccess::ReadWrite, 34 (false, true) => PageAccess::ReadExecute, 35 (true, true) => PageAccess::ReadWriteExecute, 36 }; 37 38 let ptable = PROCESSES.lock(); 39 let cap = { 40 let pool = POOL.lock_after(&ptable); 41 try_syscall!( 42 ctx, 43 cnode::resolve_caller_validate( 44 pid, 45 frame_slot, 46 ObjectTag::Frame, 47 required_rights, 48 &ptable, 49 &pool, 50 ) 51 ) 52 }; 53 54 let pml4_phys = match ptable.exec(pid).map(|e| e.pml4_phys) { 55 Some(p) => p, 56 None => { 57 ctx.rax = SyscallResult::error(KernelError::InvalidObject).raw(); 58 return; 59 } 60 }; 61 62 let (phys_addr, ft_idx) = { 63 let pool = POOL.lock_after(&ptable); 64 match pool.read_as::<FrameObject>(cap.phys(), cap.generation()) { 65 Ok(f) => (PhysAddr::new(f.phys_addr), f.frame_table_idx), 66 Err(e) => { 67 ctx.rax = SyscallResult::error(e).raw(); 68 return; 69 } 70 } 71 }; 72 73 if ft_idx == lancer_core::header::NONE_SENTINEL as u16 { 74 ctx.rax = SyscallResult::error(KernelError::ResourceExhausted).raw(); 75 return; 76 } 77 78 let phys_frame = x86_64::structures::paging::PhysFrame::containing_address(phys_addr); 79 let mut allocator = BitmapFrameAllocator; 80 81 match address_space::map_user_page_inner( 82 pml4_phys, 83 vaddr.as_virt_addr(), 84 phys_frame, 85 access, 86 &mut allocator, 87 ) { 88 Ok(()) => {} 89 Err(e) => { 90 ctx.rax = SyscallResult::error(e).raw(); 91 return; 92 } 93 } 94 95 match crate::mem::refcount::increment(phys_addr) { 96 Ok(_) => {} 97 Err(_) => { 98 let _ = address_space::unmap_user_page(pml4_phys, vaddr.as_virt_addr()); 99 ctx.rax = SyscallResult::error(KernelError::ResourceExhausted).raw(); 100 return; 101 } 102 } 103 104 match FRAME_TABLE 105 .lock() 106 .get_mut(ft_idx) 107 .add_mapping(pid, vaddr.as_virt_addr()) 108 { 109 Ok(()) => { 110 ctx.rax = SyscallResult::ok().raw(); 111 } 112 Err(e) => { 113 let _ = crate::mem::refcount::decrement(phys_addr); 114 let _ = address_space::unmap_user_page(pml4_phys, vaddr.as_virt_addr()); 115 ctx.rax = SyscallResult::error(e).raw(); 116 } 117 } 118} 119 120pub fn sys_frame_unmap(ctx: &mut CpuContext) { 121 let frame_slot = ctx.rdi; 122 let vaddr_raw = ctx.rsi; 123 let pid = crate::arch::syscall::current_pid(); 124 125 let vaddr = try_syscall!(ctx, validate_user_vaddr(vaddr_raw)); 126 127 let ptable = PROCESSES.lock(); 128 let cap = { 129 let pool = POOL.lock_after(&ptable); 130 try_syscall!( 131 ctx, 132 cnode::resolve_caller_validate( 133 pid, 134 frame_slot, 135 ObjectTag::Frame, 136 Rights::WRITE, 137 &ptable, 138 &pool, 139 ) 140 ) 141 }; 142 143 let pml4_phys = match ptable.exec(pid).map(|e| e.pml4_phys) { 144 Some(p) => p, 145 None => { 146 ctx.rax = SyscallResult::error(KernelError::InvalidObject).raw(); 147 return; 148 } 149 }; 150 151 let (phys_addr, ft_idx) = { 152 let pool = POOL.lock_after(&ptable); 153 match pool.read_as::<FrameObject>(cap.phys(), cap.generation()) { 154 Ok(f) => (PhysAddr::new(f.phys_addr), f.frame_table_idx), 155 Err(e) => { 156 ctx.rax = SyscallResult::error(e).raw(); 157 return; 158 } 159 } 160 }; 161 162 if ft_idx == lancer_core::header::NONE_SENTINEL as u16 { 163 ctx.rax = SyscallResult::error(KernelError::InvalidParameter).raw(); 164 return; 165 } 166 167 match FRAME_TABLE 168 .lock() 169 .get_mut(ft_idx) 170 .remove_mapping(pid, vaddr.as_virt_addr()) 171 { 172 true => {} 173 false => { 174 ctx.rax = SyscallResult::error(KernelError::InvalidParameter).raw(); 175 return; 176 } 177 } 178 179 let _ = address_space::unmap_user_page(pml4_phys, vaddr.as_virt_addr()); 180 181 match crate::mem::refcount::decrement(phys_addr) { 182 Ok(_) => {} 183 Err(e) => crate::kprintln!( 184 "[frame] refcount decrement failed: {:#x} {:?}", 185 phys_addr.as_u64(), 186 e 187 ), 188 } 189 190 ctx.rax = SyscallResult::ok().raw(); 191} 192 193pub fn sys_frame_map_child(ctx: &mut CpuContext) { 194 let frame_slot = ctx.rdi; 195 let proc_slot = ctx.rsi; 196 let vaddr_raw = ctx.rdx; 197 let flags = ctx.r10; 198 let pid = crate::arch::syscall::current_pid(); 199 200 let vaddr = try_syscall!(ctx, validate_user_vaddr(vaddr_raw)); 201 202 let writable = flags & 1 != 0; 203 let executable = flags & 2 != 0; 204 let access = match (writable, executable) { 205 (false, false) => PageAccess::ReadOnly, 206 (true, false) => PageAccess::ReadWrite, 207 (false, true) => PageAccess::ReadExecute, 208 (true, true) => PageAccess::ReadWriteExecute, 209 }; 210 211 let ptable = PROCESSES.lock(); 212 213 let frame_cap = { 214 let pool = POOL.lock_after(&ptable); 215 try_syscall!( 216 ctx, 217 cnode::resolve_caller_validate( 218 pid, 219 frame_slot, 220 ObjectTag::Frame, 221 Rights::GRANT, 222 &ptable, 223 &pool, 224 ) 225 ) 226 }; 227 228 let proc_cap = { 229 let pool = POOL.lock_after(&ptable); 230 try_syscall!( 231 ctx, 232 cnode::resolve_caller_validate( 233 pid, 234 proc_slot, 235 ObjectTag::Process, 236 Rights::WRITE, 237 &ptable, 238 &pool, 239 ) 240 ) 241 }; 242 243 let child_pid = { 244 let pool = POOL.lock_after(&ptable); 245 try_syscall!(ctx, ops::resolve_process_cap(&proc_cap, &pool)) 246 }; 247 248 let child_pml4 = match ptable.exec(child_pid).map(|e| e.pml4_phys) { 249 Some(p) => p, 250 None => { 251 ctx.rax = SyscallResult::error(KernelError::InvalidObject).raw(); 252 return; 253 } 254 }; 255 256 let (phys_addr, ft_idx) = { 257 let pool = POOL.lock_after(&ptable); 258 match pool.read_as::<FrameObject>(frame_cap.phys(), frame_cap.generation()) { 259 Ok(f) => (PhysAddr::new(f.phys_addr), f.frame_table_idx), 260 Err(e) => { 261 ctx.rax = SyscallResult::error(e).raw(); 262 return; 263 } 264 } 265 }; 266 267 if ft_idx == lancer_core::header::NONE_SENTINEL as u16 { 268 ctx.rax = SyscallResult::error(KernelError::ResourceExhausted).raw(); 269 return; 270 } 271 272 let phys_frame = x86_64::structures::paging::PhysFrame::containing_address(phys_addr); 273 let mut allocator = BitmapFrameAllocator; 274 275 match address_space::map_user_page_inner( 276 child_pml4, 277 vaddr.as_virt_addr(), 278 phys_frame, 279 access, 280 &mut allocator, 281 ) { 282 Ok(()) => {} 283 Err(e) => { 284 ctx.rax = SyscallResult::error(e).raw(); 285 return; 286 } 287 } 288 289 match crate::mem::refcount::increment(phys_addr) { 290 Ok(_) => {} 291 Err(_) => { 292 let _ = address_space::unmap_user_page(child_pml4, vaddr.as_virt_addr()); 293 ctx.rax = SyscallResult::error(KernelError::ResourceExhausted).raw(); 294 return; 295 } 296 } 297 298 match FRAME_TABLE 299 .lock() 300 .get_mut(ft_idx) 301 .add_mapping(child_pid, vaddr.as_virt_addr()) 302 { 303 Ok(()) => { 304 ctx.rax = SyscallResult::ok().raw(); 305 } 306 Err(e) => { 307 let _ = crate::mem::refcount::decrement(phys_addr); 308 let _ = address_space::unmap_user_page(child_pml4, vaddr.as_virt_addr()); 309 ctx.rax = SyscallResult::error(e).raw(); 310 } 311 } 312}