Nothing to see here, move along meow
0

Configure Feed

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

at main 7.1 kB View raw
1use crate::cap::cnode; 2use crate::cap::pool::POOL; 3use crate::cap::table::Rights; 4use crate::mem::phys::BitmapFrameAllocator; 5use crate::proc::PROCESSES; 6use crate::proc::address_space::{self, PageAccess}; 7use crate::proc::context::CpuContext; 8use crate::syscall::{SyscallResult, try_syscall, validate_user_vaddr}; 9use lancer_core::object_layout::VRegionObject; 10use lancer_core::object_tag::ObjectTag; 11use lancer_core::types::{MAX_VREGION_PAGES, VRegionFlags}; 12use x86_64::PhysAddr; 13use x86_64::structures::paging::PhysFrame; 14 15use super::USER_ADDR_LIMIT; 16 17fn flags_to_access(flags: VRegionFlags) -> PageAccess { 18 match (flags.writable(), flags.executable()) { 19 (false, false) => PageAccess::ReadOnly, 20 (true, false) => PageAccess::ReadWrite, 21 (false, true) => PageAccess::ReadExecute, 22 (true, true) => PageAccess::ReadWriteExecute, 23 } 24} 25 26pub fn sys_vregion_create(ctx: &mut CpuContext) { 27 let untyped_slot = ctx.rdi; 28 let dest_slot = ctx.rsi; 29 let vaddr_raw = ctx.rdx; 30 let page_count_raw = ctx.r10; 31 let flags_raw = ctx.r8; 32 let pid = crate::arch::syscall::current_pid(); 33 34 let page_count = try_syscall!(ctx, super::u16_from_reg(page_count_raw)); 35 match page_count { 36 1..=MAX_VREGION_PAGES => {} 37 _ => { 38 ctx.rax = SyscallResult::error(crate::error::KernelError::InvalidParameter).raw(); 39 return; 40 } 41 } 42 43 let vaddr = try_syscall!(ctx, validate_user_vaddr(vaddr_raw)); 44 let vaddr_u64 = vaddr.as_u64(); 45 if vaddr_u64 % 4096 != 0 { 46 ctx.rax = SyscallResult::error(crate::error::KernelError::InvalidAddress).raw(); 47 return; 48 } 49 50 let region_size = page_count as u64 * 4096; 51 match vaddr_u64.checked_add(region_size) { 52 Some(e) if e <= USER_ADDR_LIMIT => {} 53 _ => { 54 ctx.rax = SyscallResult::error(crate::error::KernelError::InvalidAddress).raw(); 55 return; 56 } 57 } 58 59 let flags_u16 = try_syscall!(ctx, super::u16_from_reg(flags_raw)); 60 let flags = match VRegionFlags::try_new(flags_u16) { 61 Some(f) => f, 62 None => { 63 ctx.rax = SyscallResult::error(crate::error::KernelError::InvalidParameter).raw(); 64 return; 65 } 66 }; 67 68 let access = flags_to_access(flags); 69 70 let ptable = PROCESSES.lock(); 71 let (cnode_phys, cnode_gen, depth, gv, gb) = 72 try_syscall!(ctx, cnode::cnode_coords(pid, &ptable)); 73 74 let mut pool = POOL.lock_after(&ptable); 75 76 let untyped_cap = try_syscall!( 77 ctx, 78 cnode::resolve_and_validate( 79 &pool, 80 cnode_phys, 81 cnode_gen, 82 untyped_slot, 83 depth, 84 gv, 85 gb, 86 ObjectTag::Untyped, 87 Rights::REVOKE, 88 ) 89 ); 90 91 let untyped_phys = untyped_cap.phys(); 92 let untyped_gen = untyped_cap.generation(); 93 94 match crate::cap::retype::retype_vregion_from_untyped( 95 &mut pool, 96 untyped_phys, 97 untyped_gen, 98 page_count, 99 cnode_phys, 100 cnode_gen, 101 dest_slot, 102 depth, 103 gv, 104 gb, 105 ) { 106 Ok(()) => {} 107 Err(e) => { 108 ctx.rax = SyscallResult::error(e).raw(); 109 return; 110 } 111 } 112 113 let vr_cap = match cnode::resolve_and_validate( 114 &pool, 115 cnode_phys, 116 cnode_gen, 117 dest_slot, 118 depth, 119 gv, 120 gb, 121 ObjectTag::VRegion, 122 Rights::WRITE, 123 ) { 124 Ok(c) => c, 125 Err(_) => { 126 panic!("just-inserted VRegion cap unreadable: kernel invariant violated"); 127 } 128 }; 129 130 let vr_phys = vr_cap.phys(); 131 let vr_gen = vr_cap.generation(); 132 133 let teardown_cap = |pool: &mut crate::cap::pool::ObjectPool| { 134 crate::cap::derivation::unlink_child(pool, vr_phys); 135 let _ = cnode::resolve_and_clear( 136 pool, 137 cnode_phys, 138 cnode_gen, 139 dest_slot, 140 depth, 141 gv, 142 gb, 143 ); 144 let _ = pool.free_phys(vr_phys, vr_gen); 145 crate::cap::kernel_objects::free_slot(vr_phys.raw()); 146 }; 147 148 let backing_phys = match pool.read_as::<VRegionObject>(vr_phys, vr_gen) { 149 Ok(obj) => obj.phys_base, 150 Err(e) => { 151 teardown_cap(&mut pool); 152 ctx.rax = SyscallResult::error(e).raw(); 153 return; 154 } 155 }; 156 157 let pml4_phys = match ptable.exec(pid).map(|e| e.pml4_phys) { 158 Some(p) => p, 159 None => { 160 teardown_cap(&mut pool); 161 ctx.rax = 162 SyscallResult::error(crate::error::KernelError::InvalidObject).raw(); 163 return; 164 } 165 }; 166 167 let mut allocator = BitmapFrameAllocator; 168 169 let map_result = (0..page_count as u64).try_fold((), |(), i| { 170 let page_phys = PhysAddr::new(backing_phys + i * 4096); 171 crate::mem::addr::zero_frame(page_phys); 172 let phys_frame = PhysFrame::containing_address(page_phys); 173 let page_vaddr = x86_64::VirtAddr::new(vaddr_u64 + i * 4096); 174 address_space::map_user_page_inner( 175 pml4_phys, 176 page_vaddr, 177 phys_frame, 178 access, 179 &mut allocator, 180 ) 181 }); 182 183 match map_result { 184 Ok(()) => {} 185 Err(map_err) => { 186 crate::cap::ops::unmap_region(pml4_phys, vaddr_u64, page_count); 187 teardown_cap(&mut pool); 188 ctx.rax = SyscallResult::error(map_err).raw(); 189 return; 190 } 191 } 192 193 match pool.write_as::<VRegionObject>(vr_phys, vr_gen) { 194 Ok(vr) => { 195 vr.owner_pid = pid.raw(); 196 vr.owner_vaddr = vaddr_u64; 197 vr.flags = flags; 198 } 199 Err(e) => { 200 crate::cap::ops::unmap_region(pml4_phys, vaddr_u64, page_count); 201 teardown_cap(&mut pool); 202 ctx.rax = SyscallResult::error(e).raw(); 203 return; 204 } 205 } 206 207 ctx.rax = SyscallResult::ok().raw(); 208} 209 210pub fn sys_vregion_destroy(ctx: &mut CpuContext) { 211 let vregion_slot = ctx.rdi; 212 let pid = crate::arch::syscall::current_pid(); 213 214 let mut ptable = PROCESSES.lock(); 215 let (cnode_phys, cnode_gen, depth, gv, gb) = 216 try_syscall!(ctx, cnode::cnode_coords(pid, &ptable)); 217 218 let mut pool = POOL.lock_after(&ptable); 219 220 let cap = try_syscall!( 221 ctx, 222 cnode::resolve_and_validate( 223 &pool, 224 cnode_phys, 225 cnode_gen, 226 vregion_slot, 227 depth, 228 gv, 229 gb, 230 ObjectTag::VRegion, 231 Rights::WRITE, 232 ) 233 ); 234 235 let _ = cnode::resolve_and_clear( 236 &pool, 237 cnode_phys, 238 cnode_gen, 239 vregion_slot, 240 depth, 241 gv, 242 gb, 243 ); 244 245 let freed_phys = cap.phys(); 246 match pool.dec_ref_phys(cap.phys(), cap.generation()) { 247 Some((phys, tag)) => { 248 crate::cap::derivation::unlink_child(&mut pool, freed_phys); 249 drop(pool); 250 crate::cap::ops::cleanup_by_tag_with_ptable(tag, phys, &mut ptable); 251 } 252 None => {} 253 } 254 255 ctx.rax = SyscallResult::ok().raw(); 256}