strat9_kernel/syscall/
ipc_ring.rs1use super::error::SyscallError;
6use crate::{
7 capability::{get_capability_manager, CapId, CapPermissions, ResourceType},
8 ipc::shared_ring::{self, RingId},
9 memory::UserSliceWrite,
10 process::current_task_clone,
11};
12
13pub fn sys_ipc_ring_create(size: u64) -> Result<u64, SyscallError> {
15 let sz = usize::try_from(size).map_err(|_| SyscallError::InvalidArgument)?;
16 let ring_id = shared_ring::create_ring(sz).map_err(|e| match e {
17 shared_ring::RingError::InvalidSize => SyscallError::InvalidArgument,
18 shared_ring::RingError::Alloc => SyscallError::OutOfMemory,
19 shared_ring::RingError::NotFound => SyscallError::NotFound,
20 })?;
21
22 let task = current_task_clone().ok_or(SyscallError::PermissionDenied)?;
23 let cap = get_capability_manager().create_capability(
24 ResourceType::SharedRing,
25 ring_id.as_u64() as usize,
26 CapPermissions {
27 read: true,
28 write: true,
29 execute: false,
30 grant: true,
31 revoke: true,
32 },
33 );
34 let cap_id = unsafe { (&mut *task.process.capabilities.get()).insert(cap) };
35 Ok(cap_id.as_u64())
36}
37
38pub fn sys_ipc_ring_map(ring_handle: u64, out_ptr: u64) -> Result<u64, SyscallError> {
40 crate::silo::enforce_cap_for_current_task(ring_handle)?;
41 if out_ptr == 0 {
42 return Err(SyscallError::Fault);
43 }
44
45 let task = current_task_clone().ok_or(SyscallError::PermissionDenied)?;
46 let caps = unsafe { &*task.process.capabilities.get() };
47 let required = CapPermissions {
48 read: true,
49 write: true,
50 execute: false,
51 grant: false,
52 revoke: false,
53 };
54 let cap = caps
55 .get_with_permissions(CapId::from_raw(ring_handle), required)
56 .ok_or(SyscallError::PermissionDenied)?;
57 if cap.resource_type != ResourceType::SharedRing {
58 return Err(SyscallError::BadHandle);
59 }
60
61 let ring_id = RingId::from_u64(cap.resource as u64);
62 let ring_obj = shared_ring::get_ring(ring_id).ok_or(SyscallError::BadHandle)?;
63 let frame_phys_addrs = ring_obj.frame_phys_addrs();
64 let mapping_cap_ids = ring_obj.mapping_cap_ids().to_vec();
65 let page_count = ring_obj.page_count();
66 let map_size = page_count
67 .checked_mul(4096)
68 .ok_or(SyscallError::InvalidArgument)? as u64;
69
70 let addr_space = task.process.address_space_arc();
71 let base = addr_space
72 .find_free_vma_range(
73 super::mmap::MMAP_BASE,
74 page_count,
75 crate::memory::address_space::VmaPageSize::Small,
76 )
77 .ok_or(SyscallError::OutOfMemory)?;
78
79 addr_space
80 .map_shared_frames_with_cap_ids(
81 base,
82 &frame_phys_addrs,
83 Some(&mapping_cap_ids),
84 crate::memory::address_space::VmaFlags {
85 readable: true,
86 writable: true,
87 executable: false,
88 user_accessible: true,
89 },
90 crate::memory::address_space::VmaType::Anonymous,
91 )
92 .map_err(|_| SyscallError::OutOfMemory)?;
93
94 let out = UserSliceWrite::new(out_ptr, core::mem::size_of::<u64>())?;
95 out.copy_from(&base.to_ne_bytes());
96 Ok(map_size)
97}