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