Nothing to see here, move along
1use crate::cap::cnode;
2use crate::cap::object::ObjectTag;
3use crate::cap::pool::POOL;
4use crate::cap::table::Rights;
5use crate::error::KernelError;
6use crate::proc::PROCESSES;
7use crate::proc::context::CpuContext;
8use crate::ring;
9use crate::syscall::{SyscallResult, try_syscall};
10
11pub fn sys_ring_register(ctx: &mut CpuContext) {
12 let frame_cap_addr = ctx.rdi;
13 let pid = crate::arch::syscall::current_pid();
14
15 let mut ptable = PROCESSES.lock();
16
17 let cap = {
18 let pool = POOL.lock_after(&ptable);
19 match cnode::resolve_caller_validate(pid, frame_cap_addr, ObjectTag::Frame, Rights::READ, &ptable, &pool) {
20 Ok(c) => c,
21 Err(e) => {
22 ctx.rax = SyscallResult::error(e).raw();
23 return;
24 }
25 }
26 };
27
28 {
29 let pool = POOL.lock_after(&ptable);
30 match pool
31 .get(cap.object_id(), cap.generation())
32 .and_then(|d| d.as_frame())
33 {
34 Ok(_) => {
35 if 4096 < ring::ring_total_size() {
36 ctx.rax = SyscallResult::error(KernelError::InvalidParameter).raw();
37 return;
38 }
39 }
40 Err(e) => {
41 ctx.rax = SyscallResult::error(e).raw();
42 return;
43 }
44 }
45 }
46
47 if let Some(p) = ptable.get_mut(pid) {
48 p.ring_region_id = Some((cap.object_id(), cap.generation()));
49 }
50 ctx.rax = SyscallResult::ok().raw();
51}
52
53pub fn sys_ring_enter(ctx: &mut CpuContext) {
54 let min_complete = try_syscall!(ctx, super::u32_from_reg(ctx.rdi));
55 let pid = crate::arch::syscall::current_pid();
56
57 let ptable = PROCESSES.lock();
58 let proc = match ptable.get(pid) {
59 Some(p) => p,
60 None => {
61 ctx.rax = SyscallResult::error(KernelError::InvalidObject).raw();
62 return;
63 }
64 };
65
66 let (region_id, region_gen) = match proc.ring_region_id {
67 Some(pair) => pair,
68 None => {
69 ctx.rax = SyscallResult::error(KernelError::BadState).raw();
70 return;
71 }
72 };
73
74 let pool = POOL.lock_after(&ptable);
75 let phys_base = match pool
76 .get(region_id, region_gen)
77 .and_then(|d| d.as_frame())
78 {
79 Ok(f) => f.phys_addr,
80 Err(e) => {
81 ctx.rax = SyscallResult::error(e).raw();
82 return;
83 }
84 };
85
86 if crate::mem::refcount::increment(phys_base).is_err() {
87 ctx.rax = SyscallResult::error(KernelError::ResourceExhausted).raw();
88 return;
89 }
90
91 drop(pool);
92 drop(ptable);
93
94 let result = ring::process::ring_enter(phys_base, pid, min_complete);
95
96 let r = crate::mem::refcount::decrement(phys_base);
97 debug_assert!(r.is_ok());
98
99 ctx.rax = match result {
100 Ok(n) => SyscallResult::success(n as u64).raw(),
101 Err(e) => SyscallResult::error(e).raw(),
102 };
103}