Add a rust user-space Capability struct.

This is a thin wrapper around a capability ptr that releases the
capability when it is done and prevents copying/cloning it.

To get a copy a caller must explicitly use duplicate.
This commit is contained in:
Drew Galbraith 2024-08-17 17:15:33 -07:00
parent 19a8ab41d4
commit 7e68c1b641
18 changed files with 215 additions and 152 deletions

View File

@ -0,0 +1,48 @@
use crate::cap_syscall;
use crate::zion::{z_cap_t, ZError};
pub struct Capability {
cap: z_cap_t,
}
impl Capability {
pub fn take(cap: z_cap_t) -> Self {
Self { cap }
}
pub fn take_copy(cap: z_cap_t) -> Result<Self, ZError> {
Ok(Self::take(cap_syscall::cap_duplicate(
cap,
Self::PERMS_ALL,
)?))
}
pub fn raw(&self) -> z_cap_t {
self.cap
}
pub fn release(mut self) -> z_cap_t {
let cap = self.cap;
self.cap = 0;
cap
}
pub const PERMS_ALL: u64 = u64::MAX;
pub fn duplicate(&self, perm_mask: u64) -> Result<Self, ZError> {
Ok(Self::take(cap_syscall::cap_duplicate(self.cap, perm_mask)?))
}
}
impl Drop for Capability {
fn drop(&mut self) {
if self.cap != 0 {
if let Err(e) = cap_syscall::cap_release(self.cap) {
crate::debug!(
"WARN: error during cap release for cap {:#x}: {:?}",
self.cap,
e
);
}
}
}
}

View File

@ -0,0 +1,31 @@
use core::ffi::c_void;
use crate::zion::{self, z_cap_t, ZError};
#[must_use]
fn syscall<T>(id: u64, req: &T) -> Result<(), ZError> {
unsafe {
let resp = zion::SysCall1(id, req as *const T as *const c_void);
if resp != 0 {
return Err(zion::ZError::from(resp));
}
}
Ok(())
}
pub fn cap_duplicate(cap: z_cap_t, perm_mask: u64) -> Result<z_cap_t, ZError> {
let mut new_cap = 0;
syscall(
zion::kZionCapDuplicate,
&zion::ZCapDuplicateReq {
cap_in: cap,
perm_mask,
cap_out: &mut new_cap,
},
)?;
Ok(new_cap)
}
pub fn cap_release(cap: z_cap_t) -> Result<(), ZError> {
syscall(zion::kZionCapRelease, &zion::ZCapReleaseReq { cap })
}

View File

@ -1,7 +1,7 @@
use crate::cap::Capability;
use crate::debug; use crate::debug;
use crate::init; use crate::init;
use crate::syscall; use crate::syscall;
use crate::zion::z_cap_t;
use crate::zion::ZError; use crate::zion::ZError;
use alloc::fmt::Debug; use alloc::fmt::Debug;
@ -225,7 +225,7 @@ impl Debug for Elf64ProgramHeader {
fn load_program_segment( fn load_program_segment(
prog_header: &Elf64ProgramHeader, prog_header: &Elf64ProgramHeader,
file: &[u8], file: &[u8],
vmas: z_cap_t, vmas: &Capability,
) -> Result<(), ZError> { ) -> Result<(), ZError> {
debug!("{:?}", prog_header); debug!("{:?}", prog_header);
match prog_header.prog_type { match prog_header.prog_type {
@ -282,7 +282,7 @@ fn load_program_segment(
} }
} }
fn load_elf_program(elf_file: &[u8], vmas: z_cap_t) -> Result<u64, ZError> { fn load_elf_program(elf_file: &[u8], vmas: &Capability) -> Result<u64, ZError> {
assert!(elf_file.len() > size_of::<Elf64Header>()); assert!(elf_file.len() > size_of::<Elf64Header>());
let header: &Elf64Header = unsafe { let header: &Elf64Header = unsafe {
elf_file elf_file
@ -312,32 +312,28 @@ fn load_elf_program(elf_file: &[u8], vmas: z_cap_t) -> Result<u64, ZError> {
Ok(header.entry) Ok(header.entry)
} }
pub fn spawn_process_from_elf(elf_file: &[u8]) -> Result<z_cap_t, ZError> { pub fn spawn_process_from_elf(elf_file: &[u8]) -> Result<Capability, ZError> {
let self_cap = unsafe { init::SELF_PROC_CAP }; let self_cap = Capability::take_copy(unsafe { init::SELF_PROC_CAP })?;
let port_cap = syscall::port_create()?; let port_cap = syscall::port_create()?;
let port_cap_dup = syscall::cap_duplicate(port_cap, u64::MAX)?;
let (new_proc_cap, new_as_cap, foreign_port_id) = let (new_proc_cap, new_as_cap, foreign_port_id) =
syscall::process_spawn(self_cap, port_cap_dup)?; syscall::process_spawn(&self_cap, port_cap.duplicate(Capability::PERMS_ALL)?)?;
let entry_point = load_elf_program(elf_file, new_as_cap)?; let entry_point = load_elf_program(elf_file, &new_as_cap)?;
let port = crate::port::PortClient::take_from(port_cap); let port = crate::port::PortClient::take_from(port_cap);
port.write_u64_and_cap( port.write_u64_and_cap(
crate::init::Z_INIT_SELF_PROC, crate::init::Z_INIT_SELF_PROC,
syscall::cap_duplicate(new_proc_cap, u64::MAX)?, new_proc_cap.duplicate(Capability::PERMS_ALL)?,
)?; )?;
port.write_u64_and_cap(crate::init::Z_INIT_SELF_VMAS, new_as_cap)?; port.write_u64_and_cap(crate::init::Z_INIT_SELF_VMAS, new_as_cap)?;
port.write_u64_and_cap( let yellowstone = Capability::take_copy(unsafe { crate::init::INIT_ENDPOINT })?;
crate::init::Z_INIT_ENDPOINT, port.write_u64_and_cap(crate::init::Z_INIT_ENDPOINT, yellowstone)?;
self_cap.duplicate(Capability::PERMS_ALL)?,
)?;
let thread_cap = syscall::thread_create(new_proc_cap)?; let thread_cap = syscall::thread_create(&new_proc_cap)?;
syscall::thread_start(thread_cap, entry_point, foreign_port_id, 0)?;
syscall::cap_release(thread_cap)?; syscall::thread_start(&thread_cap, entry_point, foreign_port_id, 0)?;
Ok(new_proc_cap) Ok(new_proc_cap)
} }

View File

@ -1,3 +1,4 @@
use crate::cap::Capability;
use crate::syscall; use crate::syscall;
use crate::zion::z_cap_t; use crate::zion::z_cap_t;
@ -11,11 +12,12 @@ pub static mut SELF_VMAS_CAP: z_cap_t = 0;
pub static mut INIT_ENDPOINT: z_cap_t = 0; pub static mut INIT_ENDPOINT: z_cap_t = 0;
pub fn parse_init_port(port_cap: z_cap_t) { pub fn parse_init_port(port_cap: z_cap_t) {
let init_port = Capability::take(port_cap);
loop { loop {
let mut bytes: [u8; 8] = [0; 8]; let mut bytes: [u8; 8] = [0; 8];
let mut caps: [u64; 1] = [0]; let mut caps: [u64; 1] = [0];
let resp = syscall::port_poll(port_cap, &mut bytes, &mut caps); let resp = syscall::port_poll(&init_port, &mut bytes, &mut caps);
if let Err(_) = resp { if let Err(_) = resp {
break; break;
} }

View File

@ -8,6 +8,8 @@ extern crate alloc;
#[macro_use] #[macro_use]
pub mod macros; pub mod macros;
pub mod cap;
mod cap_syscall;
pub mod elf; pub mod elf;
pub mod init; pub mod init;
pub mod mem; pub mod mem;

View File

@ -1,5 +1,6 @@
use crate::cap::Capability;
use crate::syscall; use crate::syscall;
use crate::zion::{z_cap_t, ZError}; use crate::zion::ZError;
use alloc::slice; use alloc::slice;
use linked_list_allocator::LockedHeap; use linked_list_allocator::LockedHeap;
@ -12,7 +13,7 @@ pub fn init_heap() {
// 1 MiB // 1 MiB
let size = 0x10_0000; let size = 0x10_0000;
let vmmo_cap = syscall::memory_object_create(size).expect("Failed to create memory object"); let vmmo_cap = syscall::memory_object_create(size).expect("Failed to create memory object");
let vaddr = syscall::address_space_map(vmmo_cap).expect("Failed to map memory object"); let vaddr = syscall::address_space_map(&vmmo_cap).expect("Failed to map memory object");
unsafe { unsafe {
ALLOCATOR.lock().init(vaddr as *mut u8, size as usize); ALLOCATOR.lock().init(vaddr as *mut u8, size as usize);
CAN_ALLOC = true; CAN_ALLOC = true;
@ -20,7 +21,7 @@ pub fn init_heap() {
} }
pub struct MemoryRegion { pub struct MemoryRegion {
mem_cap: z_cap_t, mem_cap: Capability,
virt_addr: u64, virt_addr: u64,
size: u64, size: u64,
} }
@ -28,7 +29,7 @@ pub struct MemoryRegion {
impl MemoryRegion { impl MemoryRegion {
pub fn direct_physical(paddr: u64, size: u64) -> Result<Self, ZError> { pub fn direct_physical(paddr: u64, size: u64) -> Result<Self, ZError> {
let mem_cap = syscall::memory_object_direct_physical(paddr, size)?; let mem_cap = syscall::memory_object_direct_physical(paddr, size)?;
let virt_addr = syscall::address_space_map(mem_cap)?; let virt_addr = syscall::address_space_map(&mem_cap)?;
Ok(Self { Ok(Self {
mem_cap, mem_cap,
virt_addr, virt_addr,
@ -36,9 +37,9 @@ impl MemoryRegion {
}) })
} }
pub fn from_cap(mem_cap: z_cap_t) -> Result<Self, ZError> { pub fn from_cap(mem_cap: Capability) -> Result<Self, ZError> {
let virt_addr = syscall::address_space_map(mem_cap)?; let virt_addr = syscall::address_space_map(&mem_cap)?;
let size = syscall::memory_object_inspect(mem_cap)?; let size = syscall::memory_object_inspect(&mem_cap)?;
Ok(Self { Ok(Self {
mem_cap, mem_cap,
virt_addr, virt_addr,
@ -48,7 +49,7 @@ impl MemoryRegion {
pub fn new(size: u64) -> Result<Self, ZError> { pub fn new(size: u64) -> Result<Self, ZError> {
let mem_cap = syscall::memory_object_create(size)?; let mem_cap = syscall::memory_object_create(size)?;
let virt_addr = syscall::address_space_map(mem_cap)?; let virt_addr = syscall::address_space_map(&mem_cap)?;
Ok(Self { Ok(Self {
mem_cap, mem_cap,
virt_addr, virt_addr,
@ -74,8 +75,8 @@ impl MemoryRegion {
} }
} }
pub fn cap(&self) -> z_cap_t { pub fn cap(&self) -> &Capability {
self.mem_cap &self.mem_cap
} }
} }
@ -87,6 +88,5 @@ impl Drop for MemoryRegion {
max += 0x1000 - (max & 0xFFF); max += 0x1000 - (max & 0xFFF);
} }
syscall::address_space_unmap(self.virt_addr, max).expect("Failed to unmap memory"); syscall::address_space_unmap(self.virt_addr, max).expect("Failed to unmap memory");
syscall::cap_release(self.mem_cap).expect("Failed to release memory cap");
} }
} }

View File

@ -1,8 +1,9 @@
use crate::syscall::{cap_duplicate, cap_release, port_create, port_recv}; use crate::cap::Capability;
use crate::syscall::{port_create, port_recv};
use crate::zion::{kZionPerm_Read, z_cap_t, ZError}; use crate::zion::{kZionPerm_Read, z_cap_t, ZError};
pub struct PortServer { pub struct PortServer {
port_cap: z_cap_t, port_cap: Capability,
} }
impl PortServer { impl PortServer {
@ -13,14 +14,16 @@ impl PortServer {
} }
pub fn create_client_cap(&self) -> Result<z_cap_t, ZError> { pub fn create_client_cap(&self) -> Result<z_cap_t, ZError> {
cap_duplicate(self.port_cap, !kZionPerm_Read) self.port_cap
.duplicate(!kZionPerm_Read)
.map(|c| c.release())
} }
pub fn recv_byte(&self) -> Result<u8, ZError> { pub fn recv_byte(&self) -> Result<u8, ZError> {
let mut caps: [z_cap_t; 0] = []; let mut caps: [z_cap_t; 0] = [];
let mut bytes: [u8; 1] = [0]; let mut bytes: [u8; 1] = [0];
port_recv(self.port_cap, &mut bytes, &mut caps)?; port_recv(&self.port_cap, &mut bytes, &mut caps)?;
Ok(bytes[0]) Ok(bytes[0])
} }
@ -29,42 +32,24 @@ impl PortServer {
let mut caps: [z_cap_t; 0] = []; let mut caps: [z_cap_t; 0] = [];
let mut bytes: [u8; 2] = [0; 2]; let mut bytes: [u8; 2] = [0; 2];
port_recv(self.port_cap, &mut bytes, &mut caps)?; port_recv(&self.port_cap, &mut bytes, &mut caps)?;
Ok(u16::from_le_bytes(bytes)) Ok(u16::from_le_bytes(bytes))
} }
} }
impl Drop for PortServer {
fn drop(&mut self) {
cap_release(self.port_cap).expect("Failed to release port cap");
}
}
pub struct PortClient { pub struct PortClient {
port_cap: z_cap_t, port_cap: Capability,
} }
impl PortClient { impl PortClient {
pub fn take_from(port_cap: z_cap_t) -> Self { pub fn take_from(port_cap: Capability) -> Self {
Self { port_cap } Self { port_cap }
} }
pub fn copy_from(port_cap: z_cap_t) -> Result<Self, ZError> {
Ok(Self {
port_cap: cap_duplicate(port_cap, u64::MAX)?,
})
}
#[warn(unused_results)] #[warn(unused_results)]
pub fn write_u64_and_cap(&self, bytes: u64, cap: z_cap_t) -> Result<(), ZError> { pub fn write_u64_and_cap(&self, bytes: u64, cap: Capability) -> Result<(), ZError> {
let mut caps: [z_cap_t; 1] = [cap]; let mut caps: [z_cap_t; 1] = [cap.release()];
crate::syscall::port_send(self.port_cap, &bytes.to_le_bytes(), &mut caps) crate::syscall::port_send(&self.port_cap, &bytes.to_le_bytes(), &mut caps)
}
}
impl Drop for PortClient {
fn drop(&mut self) {
cap_release(self.port_cap).expect("Failed to release port cap");
} }
} }

View File

@ -1,5 +1,6 @@
extern crate alloc; extern crate alloc;
use crate::cap::Capability;
use crate::zion; use crate::zion;
use crate::zion::z_cap_t; use crate::zion::z_cap_t;
use crate::zion::ZError; use crate::zion::ZError;
@ -41,9 +42,9 @@ pub fn debug(msg: &str) {
} }
pub fn process_spawn( pub fn process_spawn(
proc_cap: z_cap_t, proc_cap: &Capability,
bootstrap_cap: z_cap_t, bootstrap_cap: Capability,
) -> Result<(z_cap_t, z_cap_t, z_cap_t), ZError> { ) -> Result<(Capability, Capability, u64), ZError> {
let mut new_proc_cap = 0; let mut new_proc_cap = 0;
let mut new_as_cap = 0; let mut new_as_cap = 0;
let mut new_bootstrap_cap = 0; let mut new_bootstrap_cap = 0;
@ -51,15 +52,19 @@ pub fn process_spawn(
syscall( syscall(
zion::kZionProcessSpawn, zion::kZionProcessSpawn,
&zion::ZProcessSpawnReq { &zion::ZProcessSpawnReq {
proc_cap, proc_cap: proc_cap.raw(),
bootstrap_cap, bootstrap_cap: bootstrap_cap.release(),
new_proc_cap: &mut new_proc_cap, new_proc_cap: &mut new_proc_cap,
new_vmas_cap: &mut new_as_cap, new_vmas_cap: &mut new_as_cap,
new_bootstrap_cap: &mut new_bootstrap_cap, new_bootstrap_cap: &mut new_bootstrap_cap,
}, },
)?; )?;
Ok((new_proc_cap, new_as_cap, new_bootstrap_cap)) Ok((
Capability::take(new_proc_cap),
Capability::take(new_as_cap),
new_bootstrap_cap,
))
} }
pub fn process_exit(code: u64) -> ! { pub fn process_exit(code: u64) -> ! {
@ -68,39 +73,44 @@ pub fn process_exit(code: u64) -> ! {
unreachable!() unreachable!()
} }
pub fn process_wait(proc_cap: z_cap_t) -> Result<u64, ZError> { pub fn process_wait(proc_cap: &Capability) -> Result<u64, ZError> {
let mut err_code = 0; let mut err_code = 0;
syscall( syscall(
zion::kZionProcessWait, zion::kZionProcessWait,
&zion::ZProcessWaitReq { &zion::ZProcessWaitReq {
proc_cap, proc_cap: proc_cap.raw(),
exit_code: &mut err_code, exit_code: &mut err_code,
}, },
)?; )?;
Ok(err_code) Ok(err_code)
} }
pub fn thread_create(proc_cap: z_cap_t) -> Result<z_cap_t, ZError> { pub fn thread_create(proc_cap: &Capability) -> Result<Capability, ZError> {
let mut cap = 0; let mut cap = 0;
syscall( syscall(
zion::kZionThreadCreate, zion::kZionThreadCreate,
&zion::ZThreadCreateReq { &zion::ZThreadCreateReq {
proc_cap, proc_cap: proc_cap.raw(),
thread_cap: &mut cap as *mut z_cap_t, thread_cap: &mut cap,
}, },
)?; )?;
Ok(cap) Ok(Capability::take(cap))
} }
pub fn thread_sleep(millis: u64) -> Result<(), ZError> { pub fn thread_sleep(millis: u64) -> Result<(), ZError> {
syscall(zion::kZionThreadSleep, &zion::ZThreadSleepReq { millis }) syscall(zion::kZionThreadSleep, &zion::ZThreadSleepReq { millis })
} }
pub fn thread_start(thread_cap: z_cap_t, entry: u64, arg1: u64, arg2: u64) -> Result<(), ZError> { pub fn thread_start(
thread_cap: &Capability,
entry: u64,
arg1: u64,
arg2: u64,
) -> Result<(), ZError> {
syscall( syscall(
zion::kZionThreadStart, zion::kZionThreadStart,
&zion::ZThreadStartReq { &zion::ZThreadStartReq {
thread_cap, thread_cap: thread_cap.raw(),
entry, entry,
arg1, arg1,
arg2, arg2,
@ -108,8 +118,13 @@ pub fn thread_start(thread_cap: z_cap_t, entry: u64, arg1: u64, arg2: u64) -> Re
) )
} }
pub fn thread_wait(thread_cap: z_cap_t) -> Result<(), ZError> { pub fn thread_wait(thread_cap: &Capability) -> Result<(), ZError> {
syscall(zion::kZionThreadWait, &zion::ZThreadWaitReq { thread_cap }) syscall(
zion::kZionThreadWait,
&zion::ZThreadWaitReq {
thread_cap: thread_cap.raw(),
},
)
} }
pub fn thread_exit() -> ! { pub fn thread_exit() -> ! {
@ -117,17 +132,17 @@ pub fn thread_exit() -> ! {
unreachable!(); unreachable!();
} }
pub fn memory_object_create(size: u64) -> Result<z_cap_t, ZError> { pub fn memory_object_create(size: u64) -> Result<Capability, ZError> {
let mut vmmo_cap = 0; let mut vmmo_cap = 0;
let obj_req = zion::ZMemoryObjectCreateReq { let obj_req = zion::ZMemoryObjectCreateReq {
size, size,
vmmo_cap: &mut vmmo_cap as *mut u64, vmmo_cap: &mut vmmo_cap as *mut u64,
}; };
syscall(zion::kZionMemoryObjectCreate, &obj_req)?; syscall(zion::kZionMemoryObjectCreate, &obj_req)?;
Ok(vmmo_cap) Ok(Capability::take(vmmo_cap))
} }
pub fn memory_object_direct_physical(paddr: u64, size: u64) -> Result<z_cap_t, ZError> { pub fn memory_object_direct_physical(paddr: u64, size: u64) -> Result<Capability, ZError> {
let mut vmmo_cap = 0; let mut vmmo_cap = 0;
syscall( syscall(
zion::kZionMemoryObjectCreatePhysical, zion::kZionMemoryObjectCreatePhysical,
@ -137,26 +152,26 @@ pub fn memory_object_direct_physical(paddr: u64, size: u64) -> Result<z_cap_t, Z
vmmo_cap: &mut vmmo_cap, vmmo_cap: &mut vmmo_cap,
}, },
)?; )?;
Ok(vmmo_cap) Ok(Capability::take(vmmo_cap))
} }
pub fn memory_object_inspect(mem_cap: z_cap_t) -> Result<u64, ZError> { pub fn memory_object_inspect(mem_cap: &Capability) -> Result<u64, ZError> {
let mut mem_size = 0; let mut mem_size = 0;
syscall( syscall(
zion::kZionMemoryObjectInspect, zion::kZionMemoryObjectInspect,
&zion::ZMemoryObjectInspectReq { &zion::ZMemoryObjectInspectReq {
vmmo_cap: mem_cap, vmmo_cap: mem_cap.raw(),
size: &mut mem_size, size: &mut mem_size,
}, },
)?; )?;
Ok(mem_size) Ok(mem_size)
} }
pub fn address_space_map(vmmo_cap: z_cap_t) -> Result<u64, ZError> { pub fn address_space_map(vmmo_cap: &Capability) -> Result<u64, ZError> {
let mut vaddr: u64 = 0; let mut vaddr: u64 = 0;
// FIXME: Allow caller to pass these options. // FIXME: Allow caller to pass these options.
let vmas_req = zion::ZAddressSpaceMapReq { let vmas_req = zion::ZAddressSpaceMapReq {
vmmo_cap, vmmo_cap: vmmo_cap.raw(),
vmas_cap: unsafe { crate::init::SELF_VMAS_CAP }, vmas_cap: unsafe { crate::init::SELF_VMAS_CAP },
align: 0x2000, align: 0x2000,
vaddr: &mut vaddr as *mut u64, vaddr: &mut vaddr as *mut u64,
@ -168,14 +183,14 @@ pub fn address_space_map(vmmo_cap: z_cap_t) -> Result<u64, ZError> {
} }
pub fn address_space_map_external( pub fn address_space_map_external(
vmas_cap: z_cap_t, vmas_cap: &Capability,
vmmo_cap: z_cap_t, vmmo_cap: &Capability,
vaddr: u64, vaddr: u64,
) -> Result<(), ZError> { ) -> Result<(), ZError> {
let mut vaddr_throw: u64 = 0; let mut vaddr_throw: u64 = 0;
let vmas_req = zion::ZAddressSpaceMapReq { let vmas_req = zion::ZAddressSpaceMapReq {
vmmo_cap, vmas_cap: vmas_cap.raw(),
vmas_cap, vmmo_cap: vmmo_cap.raw(),
align: 0, align: 0,
vaddr: &mut vaddr_throw as *mut u64, vaddr: &mut vaddr_throw as *mut u64,
vmas_offset: vaddr, vmas_offset: vaddr,
@ -196,7 +211,7 @@ pub fn address_space_unmap(lower_addr: u64, upper_addr: u64) -> Result<(), ZErro
) )
} }
pub fn port_create() -> Result<z_cap_t, ZError> { pub fn port_create() -> Result<Capability, ZError> {
let mut port_cap = 0; let mut port_cap = 0;
syscall( syscall(
zion::kZionPortCreate, zion::kZionPortCreate,
@ -204,14 +219,14 @@ pub fn port_create() -> Result<z_cap_t, ZError> {
port_cap: &mut port_cap, port_cap: &mut port_cap,
}, },
)?; )?;
Ok(port_cap) Ok(Capability::take(port_cap))
} }
pub fn port_send(port_cap: z_cap_t, bytes: &[u8], caps: &mut [z_cap_t]) -> Result<(), ZError> { pub fn port_send(port_cap: &Capability, bytes: &[u8], caps: &mut [z_cap_t]) -> Result<(), ZError> {
syscall( syscall(
zion::kZionPortSend, zion::kZionPortSend,
&zion::ZPortSendReq { &zion::ZPortSendReq {
port_cap, port_cap: port_cap.raw(),
num_bytes: bytes.len() as u64, num_bytes: bytes.len() as u64,
data: bytes.as_ptr() as *const c_void, data: bytes.as_ptr() as *const c_void,
num_caps: caps.len() as u64, num_caps: caps.len() as u64,
@ -222,7 +237,7 @@ pub fn port_send(port_cap: z_cap_t, bytes: &[u8], caps: &mut [z_cap_t]) -> Resul
} }
pub fn port_recv( pub fn port_recv(
port_cap: z_cap_t, port_cap: &Capability,
bytes: &mut [u8], bytes: &mut [u8],
caps: &mut [u64], caps: &mut [u64],
) -> Result<(u64, u64), ZError> { ) -> Result<(u64, u64), ZError> {
@ -231,7 +246,7 @@ pub fn port_recv(
syscall( syscall(
zion::kZionPortRecv, zion::kZionPortRecv,
&zion::ZPortRecvReq { &zion::ZPortRecvReq {
port_cap, port_cap: port_cap.raw(),
data: bytes.as_mut_ptr() as *mut c_void, data: bytes.as_mut_ptr() as *mut c_void,
num_bytes: &mut num_bytes as *mut u64, num_bytes: &mut num_bytes as *mut u64,
caps: caps.as_mut_ptr(), caps: caps.as_mut_ptr(),
@ -242,14 +257,14 @@ pub fn port_recv(
} }
pub fn port_poll( pub fn port_poll(
port_cap: z_cap_t, port_cap: &Capability,
bytes: &mut [u8], bytes: &mut [u8],
caps: &mut [u64], caps: &mut [u64],
) -> Result<(u64, u64), ZError> { ) -> Result<(u64, u64), ZError> {
let mut num_bytes = bytes.len() as u64; let mut num_bytes = bytes.len() as u64;
let mut num_caps = caps.len() as u64; let mut num_caps = caps.len() as u64;
let req = zion::ZPortPollReq { let req = zion::ZPortPollReq {
port_cap, port_cap: port_cap.raw(),
data: bytes.as_mut_ptr() as *mut c_void, data: bytes.as_mut_ptr() as *mut c_void,
num_bytes: &mut num_bytes as *mut u64, num_bytes: &mut num_bytes as *mut u64,
caps: caps.as_mut_ptr(), caps: caps.as_mut_ptr(),
@ -259,7 +274,7 @@ pub fn port_poll(
Ok((num_bytes, num_caps)) Ok((num_bytes, num_caps))
} }
pub fn endpoint_create() -> Result<z_cap_t, ZError> { pub fn endpoint_create() -> Result<Capability, ZError> {
let mut endpoint_cap: z_cap_t = 0; let mut endpoint_cap: z_cap_t = 0;
syscall( syscall(
zion::kZionEndpointCreate, zion::kZionEndpointCreate,
@ -267,19 +282,19 @@ pub fn endpoint_create() -> Result<z_cap_t, ZError> {
endpoint_cap: &mut endpoint_cap, endpoint_cap: &mut endpoint_cap,
}, },
)?; )?;
Ok(endpoint_cap) Ok(Capability::take(endpoint_cap))
} }
pub fn endpoint_send( pub fn endpoint_send(
endpoint_cap: z_cap_t, endpoint_cap: &Capability,
bytes: &[u8], bytes: &[u8],
caps: &[z_cap_t], caps: &[z_cap_t],
) -> Result<z_cap_t, ZError> { ) -> Result<Capability, ZError> {
let mut reply_port_cap: u64 = 0; let mut reply_port_cap: u64 = 0;
let send_req = zion::ZEndpointSendReq { let send_req = zion::ZEndpointSendReq {
caps: caps.as_ptr(), caps: caps.as_ptr(),
num_caps: caps.len() as u64, num_caps: caps.len() as u64,
endpoint_cap, endpoint_cap: endpoint_cap.raw(),
data: bytes.as_ptr() as *const c_void, data: bytes.as_ptr() as *const c_void,
num_bytes: bytes.len() as u64, num_bytes: bytes.len() as u64,
reply_port_cap: &mut reply_port_cap, reply_port_cap: &mut reply_port_cap,
@ -287,19 +302,19 @@ pub fn endpoint_send(
syscall(zion::kZionEndpointSend, &send_req)?; syscall(zion::kZionEndpointSend, &send_req)?;
Ok(reply_port_cap) Ok(Capability::take(reply_port_cap))
} }
pub fn endpoint_recv( pub fn endpoint_recv(
endpoint_cap: z_cap_t, endpoint_cap: &Capability,
bytes: &mut [u8], bytes: &mut [u8],
caps: &mut [z_cap_t], caps: &mut [z_cap_t],
) -> Result<(u64, u64, z_cap_t), ZError> { ) -> Result<(u64, u64, Capability), ZError> {
let mut num_bytes = bytes.len() as u64; let mut num_bytes = bytes.len() as u64;
let mut num_caps = caps.len() as u64; let mut num_caps = caps.len() as u64;
let mut reply_port_cap = 0; let mut reply_port_cap = 0;
let recv_req = zion::ZEndpointRecvReq { let recv_req = zion::ZEndpointRecvReq {
endpoint_cap, endpoint_cap: endpoint_cap.raw(),
data: bytes.as_mut_ptr() as *mut c_void, data: bytes.as_mut_ptr() as *mut c_void,
num_bytes: &mut num_bytes, num_bytes: &mut num_bytes,
caps: caps.as_mut_ptr(), caps: caps.as_mut_ptr(),
@ -309,18 +324,18 @@ pub fn endpoint_recv(
syscall(zion::kZionEndpointRecv, &recv_req)?; syscall(zion::kZionEndpointRecv, &recv_req)?;
Ok((num_bytes, num_caps, reply_port_cap)) Ok((num_bytes, num_caps, Capability::take(reply_port_cap)))
} }
pub fn reply_port_send( pub fn reply_port_send(
reply_port_cap: z_cap_t, reply_port_cap: Capability,
bytes: &[u8], bytes: &[u8],
caps: &[z_cap_t], caps: &[z_cap_t],
) -> Result<(), ZError> { ) -> Result<(), ZError> {
syscall( syscall(
zion::kZionReplyPortSend, zion::kZionReplyPortSend,
&zion::ZReplyPortSendReq { &zion::ZReplyPortSendReq {
reply_port_cap, reply_port_cap: reply_port_cap.raw(),
data: bytes.as_ptr() as *const c_void, data: bytes.as_ptr() as *const c_void,
num_bytes: bytes.len() as u64, num_bytes: bytes.len() as u64,
caps: caps.as_ptr(), caps: caps.as_ptr(),
@ -330,14 +345,14 @@ pub fn reply_port_send(
} }
pub fn reply_port_recv( pub fn reply_port_recv(
reply_port_cap: z_cap_t, reply_port_cap: Capability,
bytes: &mut [u8], bytes: &mut [u8],
caps: &mut [z_cap_t], caps: &mut [z_cap_t],
) -> Result<(u64, u64), ZError> { ) -> Result<(u64, u64), ZError> {
let mut num_bytes = bytes.len() as u64; let mut num_bytes = bytes.len() as u64;
let mut num_caps = caps.len() as u64; let mut num_caps = caps.len() as u64;
let recv_req = zion::ZReplyPortRecvReq { let recv_req = zion::ZReplyPortRecvReq {
reply_port_cap, reply_port_cap: reply_port_cap.raw(),
caps: caps.as_mut_ptr(), caps: caps.as_mut_ptr(),
num_caps: &mut num_caps, num_caps: &mut num_caps,
data: bytes.as_mut_ptr() as *mut c_void, data: bytes.as_mut_ptr() as *mut c_void,
@ -348,20 +363,3 @@ pub fn reply_port_recv(
Ok((num_bytes, num_caps)) Ok((num_bytes, num_caps))
} }
pub fn cap_duplicate(cap: z_cap_t, perm_mask: u64) -> Result<z_cap_t, ZError> {
let mut new_cap = 0;
syscall(
zion::kZionCapDuplicate,
&zion::ZCapDuplicateReq {
cap_in: cap,
perm_mask,
cap_out: &mut new_cap,
},
)?;
Ok(new_cap)
}
pub fn cap_release(cap: z_cap_t) -> Result<(), ZError> {
syscall(zion::kZionCapRelease, &zion::ZCapReleaseReq { cap })
}

View File

@ -1,6 +1,6 @@
use crate::cap::Capability;
use crate::syscall; use crate::syscall;
use crate::zion; use crate::zion;
use crate::zion::z_cap_t;
use alloc::boxed::Box; use alloc::boxed::Box;
use core::ffi::c_void; use core::ffi::c_void;
@ -17,7 +17,7 @@ extern "C" fn internal_entry_point(thread_ptr: *const Thread, arg1: *const c_voi
} }
// TODO: Add a Drop implementation that kills this thread and drops its capability. // TODO: Add a Drop implementation that kills this thread and drops its capability.
pub struct Thread { pub struct Thread {
cap: z_cap_t, cap: Capability,
// This field only exists to ensure that the entry reference will outlive the thread object // This field only exists to ensure that the entry reference will outlive the thread object
// itself. // itself.
entry: ThreadEntry, entry: ThreadEntry,
@ -25,11 +25,11 @@ pub struct Thread {
impl Thread { impl Thread {
pub fn spawn(entry: ThreadEntry, arg1: *const c_void) -> Result<Box<Self>, zion::ZError> { pub fn spawn(entry: ThreadEntry, arg1: *const c_void) -> Result<Box<Self>, zion::ZError> {
let proc_cap = unsafe { crate::init::SELF_PROC_CAP }; let proc_cap = Capability::take_copy(unsafe { crate::init::SELF_PROC_CAP })?;
let cap = syscall::thread_create(proc_cap)?; let cap = syscall::thread_create(&proc_cap)?;
let thread = Box::new(Self { cap, entry }); let thread = Box::new(Self { cap, entry });
syscall::thread_start( syscall::thread_start(
cap, &thread.cap,
internal_entry_point as u64, internal_entry_point as u64,
thread.as_ref() as *const Thread as u64, thread.as_ref() as *const Thread as u64,
arg1 as u64, arg1 as u64,
@ -39,6 +39,6 @@ impl Thread {
} }
pub fn join(&self) -> Result<(), zion::ZError> { pub fn join(&self) -> Result<(), zion::ZError> {
syscall::thread_wait(self.cap) syscall::thread_wait(&self.cap)
} }
} }

View File

@ -1,6 +1,6 @@
use crate::OpenFileRequest; use crate::OpenFileRequest;
use alloc::string::ToString; use alloc::string::ToString;
use mammoth::zion::ZError; use mammoth::{cap::Capability, zion::ZError};
pub struct File { pub struct File {
memory: mammoth::mem::MemoryRegion, memory: mammoth::mem::MemoryRegion,
@ -14,7 +14,7 @@ impl File {
})?; })?;
Ok(Self { Ok(Self {
memory: mammoth::mem::MemoryRegion::from_cap(resp.memory)?, memory: mammoth::mem::MemoryRegion::from_cap(Capability::take(resp.memory))?,
}) })
} }

View File

@ -18,7 +18,7 @@ fn get_client() -> &'static mut VFSClient {
}) })
.expect("Failed to get VFS endpoint"); .expect("Failed to get VFS endpoint");
VFS_CLIENT = Some(VFSClient::new(endpoint_cap.endpoint)); VFS_CLIENT = Some(VFSClient::new(Capability::take(endpoint_cap.endpoint)));
} }
VFS_CLIENT.as_mut().unwrap() VFS_CLIENT.as_mut().unwrap()
} }

View File

@ -3,6 +3,7 @@ use core::cell::RefCell;
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::rc::Rc; use alloc::rc::Rc;
use alloc::string::ToString; use alloc::string::ToString;
use mammoth::cap::Capability;
use mammoth::port::PortServer; use mammoth::port::PortServer;
use mammoth::thread::Thread; use mammoth::thread::Thread;
use mammoth::zion::ZError; use mammoth::zion::ZError;
@ -216,7 +217,7 @@ impl KeyboardListener {
})? })?
.endpoint; .endpoint;
let mut voyageur_client = crate::VoyageursClient::new(voyageur_endpoint); let mut voyageur_client = crate::VoyageursClient::new(Capability::take(voyageur_endpoint));
voyageur_client.register_keyboard_listener(&crate::KeyboardListener { voyageur_client.register_keyboard_listener(&crate::KeyboardListener {
port_capability: listnr.listen_port.create_client_cap()?, port_capability: listnr.listen_port.create_client_cap()?,

View File

@ -11,7 +11,7 @@ static mut YELLOWSTONE_INIT: Option<YellowstoneClient> = None;
pub fn from_init_endpoint() -> &'static mut YellowstoneClient { pub fn from_init_endpoint() -> &'static mut YellowstoneClient {
unsafe { unsafe {
if let None = YELLOWSTONE_INIT { if let None = YELLOWSTONE_INIT {
YELLOWSTONE_INIT = Some(YellowstoneClient::new(INIT_ENDPOINT)); YELLOWSTONE_INIT = Some(YellowstoneClient::new(Capability::take(INIT_ENDPOINT)));
} }
YELLOWSTONE_INIT.as_mut().unwrap() YELLOWSTONE_INIT.as_mut().unwrap()

View File

@ -1,14 +1,14 @@
use crate::buffer::ByteBuffer; use crate::buffer::ByteBuffer;
use crate::message::YunqMessage; use crate::message::YunqMessage;
use alloc::vec::Vec; use alloc::vec::Vec;
use mammoth::zion::z_cap_t; use mammoth::cap::Capability;
use mammoth::zion::ZError; use mammoth::zion::ZError;
pub fn call_endpoint<Req: YunqMessage, Resp: YunqMessage, const N: usize>( pub fn call_endpoint<Req: YunqMessage, Resp: YunqMessage, const N: usize>(
request_id: u64, request_id: u64,
req: &Req, req: &Req,
byte_buffer: &mut ByteBuffer<N>, byte_buffer: &mut ByteBuffer<N>,
endpoint_cap: z_cap_t, endpoint_cap: &Capability,
) -> Result<Resp, ZError> { ) -> Result<Resp, ZError> {
let mut cap_buffer = Vec::new(); let mut cap_buffer = Vec::new();
let length = req.serialize_as_request(request_id, byte_buffer, &mut cap_buffer)?; let length = req.serialize_as_request(request_id, byte_buffer, &mut cap_buffer)?;

View File

@ -1,5 +1,6 @@
use crate::buffer::ByteBuffer; use crate::buffer::ByteBuffer;
use alloc::vec::Vec; use alloc::vec::Vec;
use mammoth::cap::Capability;
use mammoth::syscall; use mammoth::syscall;
use mammoth::zion::z_cap_t; use mammoth::zion::z_cap_t;
use mammoth::zion::ZError; use mammoth::zion::ZError;
@ -36,7 +37,7 @@ pub trait YunqServer {
} }
} }
fn endpoint_cap(&self) -> z_cap_t; fn endpoint_cap(&self) -> &Capability;
fn handle_request( fn handle_request(
&self, &self,
method_number: u64, method_number: u64,

View File

@ -117,9 +117,9 @@ impl Terminal {
Some(prog) => { Some(prog) => {
let file = victoriafalls::file::File::open(prog).expect("Failed to open file"); let file = victoriafalls::file::File::open(prog).expect("Failed to open file");
let proc_cap = mammoth::elf::spawn_process_from_elf(file.slice()) let proc_cap = mammoth::elf::spawn_process_from_elf(file.slice())
.expect("Faield to spawn process"); .expect("Failed to spawn process");
let exit_code = mammoth::syscall::process_wait(proc_cap) let exit_code = mammoth::syscall::process_wait(&proc_cap)
.expect("Failed to wait on process."); .expect("Failed to wait on process.");
self.write_line(&format!("Process exit code: {}", exit_code)); self.write_line(&format!("Process exit code: {}", exit_code));

View File

@ -9,7 +9,6 @@ use mammoth::define_entry;
use mammoth::thread; use mammoth::thread;
use mammoth::zion::z_err_t; use mammoth::zion::z_err_t;
use yellowstone::GetEndpointRequest; use yellowstone::GetEndpointRequest;
use yellowstone::YellowstoneClient;
define_entry!(); define_entry!();
@ -17,10 +16,9 @@ define_entry!();
pub extern "C" fn main() -> z_err_t { pub extern "C" fn main() -> z_err_t {
debug!("Testing!"); debug!("Testing!");
let mut yellowstone; let yellowstone = yellowstone::from_init_endpoint();
unsafe {
yellowstone = YellowstoneClient::new(mammoth::init::INIT_ENDPOINT); debug!("Get endpoint");
}
let endpoint = yellowstone let endpoint = yellowstone
.get_endpoint(&GetEndpointRequest { .get_endpoint(&GetEndpointRequest {

View File

@ -33,17 +33,17 @@ fn generate_method(method: &Method) -> TokenStream {
match (maybe_req, maybe_resp) { match (maybe_req, maybe_resp) {
(Some(req), Some(resp)) => quote! { (Some(req), Some(resp)) => quote! {
pub fn #name (&mut self, req: & #req) -> Result<#resp, ZError> { pub fn #name (&mut self, req: & #req) -> Result<#resp, ZError> {
yunq::client::call_endpoint(#id, req, &mut self.byte_buffer, self.endpoint_cap) yunq::client::call_endpoint(#id, req, &mut self.byte_buffer, &self.endpoint_cap)
} }
}, },
(Some(req), None) => quote! { (Some(req), None) => quote! {
pub fn #name (&mut self, req: & #req) -> Result<yunq::message::Empty, ZError> { pub fn #name (&mut self, req: & #req) -> Result<yunq::message::Empty, ZError> {
yunq::client::call_endpoint(#id, req, &mut self.byte_buffer, self.endpoint_cap) yunq::client::call_endpoint(#id, req, &mut self.byte_buffer, &self.endpoint_cap)
} }
}, },
(None, Some(resp)) => quote! { (None, Some(resp)) => quote! {
pub fn #name (&mut self) -> Result<#resp, ZError> { pub fn #name (&mut self) -> Result<#resp, ZError> {
yunq::client::call_endpoint(#id, &yunq::message::Empty{}, &mut self.byte_buffer, self.endpoint_cap) yunq::client::call_endpoint(#id, &yunq::message::Empty{}, &mut self.byte_buffer, &self.endpoint_cap)
} }
}, },
_ => unreachable!(), _ => unreachable!(),
@ -56,12 +56,12 @@ fn generate_client(interface: &Interface) -> TokenStream {
let methods = interface.methods.iter().map(|m| generate_method(&m)); let methods = interface.methods.iter().map(|m| generate_method(&m));
quote! { quote! {
pub struct #name { pub struct #name {
endpoint_cap: z_cap_t, endpoint_cap: Capability,
byte_buffer: ByteBuffer<0x1000>, byte_buffer: ByteBuffer<0x1000>,
} }
impl #name { impl #name {
pub fn new(endpoint_cap: z_cap_t) -> Self { pub fn new(endpoint_cap: Capability) -> Self {
Self { Self {
endpoint_cap, endpoint_cap,
byte_buffer: ByteBuffer::new(), byte_buffer: ByteBuffer::new(),
@ -139,7 +139,7 @@ fn generate_server(interface: &Interface) -> TokenStream {
} }
pub struct #server_name<T: #server_trait> { pub struct #server_name<T: #server_trait> {
endpoint_cap: z_cap_t, endpoint_cap: Capability,
handler: T handler: T
} }
@ -164,8 +164,8 @@ fn generate_server(interface: &Interface) -> TokenStream {
} }
impl<T: #server_trait> yunq::server::YunqServer for #server_name<T> { impl<T: #server_trait> yunq::server::YunqServer for #server_name<T> {
fn endpoint_cap(&self) -> z_cap_t { fn endpoint_cap(&self) -> &Capability {
self.endpoint_cap &self.endpoint_cap
} }
fn handle_request( fn handle_request(
@ -206,6 +206,7 @@ pub fn generate_code(ast: &Vec<Decl>) -> String {
use core::ffi::c_void; use core::ffi::c_void;
use mammoth::syscall; use mammoth::syscall;
use mammoth::thread; use mammoth::thread;
use mammoth::cap::Capability;
use mammoth::zion::z_cap_t; use mammoth::zion::z_cap_t;
use mammoth::zion::ZError; use mammoth::zion::ZError;
use yunq::ByteBuffer; use yunq::ByteBuffer;