Nothing to see here, move along
at main 155 lines 5.3 kB view raw
1use crate::cap::cnode; 2use crate::cap::object::{ObjectData, ObjectTag}; 3use crate::cap::pool::POOL; 4use crate::cap::table::{CapRef, Rights}; 5use crate::error::KernelError; 6use crate::mem::phys::BitmapFrameAllocator; 7use crate::proc::PROCESSES; 8use crate::proc::context::CpuContext; 9use crate::syscall::{SyscallResult, try_syscall}; 10 11pub fn sys_cnode_create(ctx: &mut CpuContext) { 12 let size_bits = try_syscall!(ctx, super::u8_from_reg(ctx.rdi)); 13 let dest_addr = ctx.rsi; 14 let pid = crate::arch::syscall::current_pid(); 15 16 if !(cnode::MIN_CNODE_BITS..=cnode::MAX_CNODE_BITS).contains(&size_bits) { 17 ctx.rax = SyscallResult::error(KernelError::InvalidParameter).raw(); 18 return; 19 } 20 21 let allocator = &BitmapFrameAllocator; 22 let cnode_data = match cnode::create_cnode(size_bits, allocator) { 23 Ok(cd) => cd, 24 Err(e) => { 25 ctx.rax = SyscallResult::error(e).raw(); 26 return; 27 } 28 }; 29 let frame_count = cnode_data.frame_count; 30 31 let mut ptable = PROCESSES.lock(); 32 let mut pool = POOL.lock_after(&ptable); 33 34 let (cnode_id, cnode_gen) = match pool.allocate(ObjectData::CNode(cnode_data)) { 35 Ok(pair) => pair, 36 Err(e) => { 37 cnode::destroy_cnode(&cnode_data, allocator); 38 ctx.rax = SyscallResult::error(e).raw(); 39 return; 40 } 41 }; 42 43 let cap = CapRef::new(ObjectTag::CNode, cnode_id, Rights::ALL, cnode_gen); 44 45 let (caller_cnode_id, caller_cnode_gen, depth) = 46 match cnode::cnode_coords(pid, &ptable) { 47 Ok(c) => c, 48 Err(e) => { 49 let _ = pool.free(cnode_id, cnode_gen); 50 ctx.rax = SyscallResult::error(e).raw(); 51 return; 52 } 53 }; 54 55 if let Err(e) = 56 cnode::resolve_and_insert(&pool, caller_cnode_id, caller_cnode_gen, dest_addr, depth, cap) 57 { 58 let _ = pool.free(cnode_id, cnode_gen); 59 ctx.rax = SyscallResult::error(e).raw(); 60 return; 61 } 62 63 match ptable.get_mut(pid) { 64 Some(proc) => { 65 if let Err(e) = proc.charge_frames(frame_count as u16) { 66 let _ = cnode::resolve_and_clear( 67 &pool, caller_cnode_id, caller_cnode_gen, dest_addr, depth, 68 ); 69 let _ = pool.free(cnode_id, cnode_gen); 70 ctx.rax = SyscallResult::error(e).raw(); 71 return; 72 } 73 } 74 None => { 75 let _ = cnode::resolve_and_clear( 76 &pool, caller_cnode_id, caller_cnode_gen, dest_addr, depth, 77 ); 78 let _ = pool.free(cnode_id, cnode_gen); 79 ctx.rax = SyscallResult::error(KernelError::InvalidObject).raw(); 80 return; 81 } 82 } 83 84 ctx.rax = SyscallResult::ok().raw(); 85} 86 87pub fn sys_cnode_copy(ctx: &mut CpuContext) { 88 let src_addr = ctx.rdi; 89 let dest_addr = ctx.rsi; 90 let rights_raw = try_syscall!(ctx, super::u16_from_reg(ctx.rdx)); 91 let rights_mask = Rights::from_bits(rights_raw); 92 let pid = crate::arch::syscall::current_pid(); 93 94 let ptable = PROCESSES.lock(); 95 let (cnode_id, cnode_gen, depth) = try_syscall!(ctx, cnode::cnode_coords(pid, &ptable)); 96 let mut pool = POOL.lock_after(&ptable); 97 98 let src_cap = match cnode::resolve_and_read(&pool, cnode_id, cnode_gen, src_addr, depth) { 99 Ok(cap) => cap, 100 Err(e) => { 101 ctx.rax = SyscallResult::error(e).raw(); 102 return; 103 } 104 }; 105 106 if let Err(e) = pool.inc_ref(src_cap.object_id(), src_cap.generation()) { 107 ctx.rax = SyscallResult::error(e).raw(); 108 return; 109 } 110 111 let copied = src_cap.with_rights(src_cap.rights() & rights_mask); 112 113 ctx.rax = 114 match cnode::resolve_and_insert(&pool, cnode_id, cnode_gen, dest_addr, depth, copied) { 115 Ok(()) => SyscallResult::ok().raw(), 116 Err(e) => { 117 pool.dec_ref(src_cap.object_id(), src_cap.generation()); 118 SyscallResult::error(e).raw() 119 } 120 }; 121} 122 123pub fn sys_cnode_delete(ctx: &mut CpuContext) { 124 let address = ctx.rdi; 125 let pid = crate::arch::syscall::current_pid(); 126 127 let mut ptable = PROCESSES.lock(); 128 let (cnode_id, cnode_gen, depth) = try_syscall!(ctx, cnode::cnode_coords(pid, &ptable)); 129 let mut pool = POOL.lock_after(&ptable); 130 131 let cap = match cnode::resolve_and_clear(&pool, cnode_id, cnode_gen, address, depth) { 132 Ok(cap) => cap, 133 Err(e) => { 134 ctx.rax = SyscallResult::error(e).raw(); 135 return; 136 } 137 }; 138 139 match pool.dec_ref(cap.object_id(), cap.generation()) { 140 Some(crate::cap::object::ObjectData::CNode(ref cnode_data)) => { 141 cnode::drain_cnode_data(cnode_data, &mut pool, &mut |cap, pool| { 142 if let Some(ref data) = pool.dec_ref(cap.object_id(), cap.generation()) { 143 crate::cap::ops::cleanup_object_data_with_ptable(data, &mut ptable); 144 } 145 }); 146 cnode::destroy_cnode(cnode_data, &crate::mem::phys::BitmapFrameAllocator); 147 } 148 Some(ref data) => { 149 crate::cap::ops::cleanup_object_data(data); 150 } 151 None => {} 152 } 153 154 ctx.rax = SyscallResult::ok().raw(); 155}