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}; use lancer_core::object_layout::FrameObject; 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.read_as::(cap.phys(), cap.generation()) { 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(e) = ptable.exec_mut(pid) { e.ring_region_id = Some((cap.phys(), 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 exec = match ptable.exec(pid) { Some(e) => e, None => { ctx.rax = SyscallResult::error(KernelError::InvalidObject).raw(); return; } }; let (region_id, region_gen) = match exec.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.read_as::(region_id, region_gen) { Ok(f) => x86_64::PhysAddr::new(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(), }; }