use crate::cap::cnode; use crate::cap::object::ObjectTag; use crate::cap::pool::POOL; use crate::cap::table::Rights; use crate::error::KernelError; use crate::proc::PROCESSES; use crate::proc::context::CpuContext; use crate::ring; use crate::syscall::{SyscallResult, try_syscall}; pub fn sys_ring_register(ctx: &mut CpuContext) { let frame_cap_addr = ctx.rdi; let pid = crate::arch::syscall::current_pid(); let mut ptable = PROCESSES.lock(); let cap = { let pool = POOL.lock_after(&ptable); match cnode::resolve_caller_validate(pid, frame_cap_addr, ObjectTag::Frame, Rights::READ, &ptable, &pool) { Ok(c) => c, Err(e) => { ctx.rax = SyscallResult::error(e).raw(); return; } } }; { let pool = POOL.lock_after(&ptable); match pool .get(cap.object_id(), cap.generation()) .and_then(|d| d.as_frame()) { Ok(_) => { if 4096 < ring::ring_total_size() { ctx.rax = SyscallResult::error(KernelError::InvalidParameter).raw(); return; } } Err(e) => { ctx.rax = SyscallResult::error(e).raw(); return; } } } if let Some(p) = ptable.get_mut(pid) { p.ring_region_id = Some((cap.object_id(), cap.generation())); } ctx.rax = SyscallResult::ok().raw(); } pub fn sys_ring_enter(ctx: &mut CpuContext) { let min_complete = try_syscall!(ctx, super::u32_from_reg(ctx.rdi)); let pid = crate::arch::syscall::current_pid(); let ptable = PROCESSES.lock(); let proc = match ptable.get(pid) { Some(p) => p, None => { ctx.rax = SyscallResult::error(KernelError::InvalidObject).raw(); return; } }; let (region_id, region_gen) = match proc.ring_region_id { Some(pair) => pair, None => { ctx.rax = SyscallResult::error(KernelError::BadState).raw(); return; } }; let pool = POOL.lock_after(&ptable); let phys_base = match pool .get(region_id, region_gen) .and_then(|d| d.as_frame()) { Ok(f) => f.phys_addr, Err(e) => { ctx.rax = SyscallResult::error(e).raw(); return; } }; if crate::mem::refcount::increment(phys_base).is_err() { ctx.rax = SyscallResult::error(KernelError::ResourceExhausted).raw(); return; } drop(pool); drop(ptable); let result = ring::process::ring_enter(phys_base, pid, min_complete); let r = crate::mem::refcount::decrement(phys_base); debug_assert!(r.is_ok()); ctx.rax = match result { Ok(n) => SyscallResult::success(n as u64).raw(), Err(e) => SyscallResult::error(e).raw(), }; }