Nothing to see here, move along
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}