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::init;
use crate::syscall;
use crate::zion::z_cap_t;
use crate::zion::ZError;
use alloc::fmt::Debug;
@ -225,7 +225,7 @@ impl Debug for Elf64ProgramHeader {
fn load_program_segment(
prog_header: &Elf64ProgramHeader,
file: &[u8],
vmas: z_cap_t,
vmas: &Capability,
) -> Result<(), ZError> {
debug!("{:?}", prog_header);
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>());
let header: &Elf64Header = unsafe {
elf_file
@ -312,32 +312,28 @@ fn load_elf_program(elf_file: &[u8], vmas: z_cap_t) -> Result<u64, ZError> {
Ok(header.entry)
}
pub fn spawn_process_from_elf(elf_file: &[u8]) -> Result<z_cap_t, ZError> {
let self_cap = unsafe { init::SELF_PROC_CAP };
pub fn spawn_process_from_elf(elf_file: &[u8]) -> Result<Capability, ZError> {
let self_cap = Capability::take_copy(unsafe { init::SELF_PROC_CAP })?;
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) =
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);
port.write_u64_and_cap(
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_ENDPOINT,
self_cap.duplicate(Capability::PERMS_ALL)?,
)?;
let yellowstone = Capability::take_copy(unsafe { crate::init::INIT_ENDPOINT })?;
port.write_u64_and_cap(crate::init::Z_INIT_ENDPOINT, yellowstone)?;
let thread_cap = syscall::thread_create(new_proc_cap)?;
syscall::thread_start(thread_cap, entry_point, foreign_port_id, 0)?;
let thread_cap = syscall::thread_create(&new_proc_cap)?;
syscall::cap_release(thread_cap)?;
syscall::thread_start(&thread_cap, entry_point, foreign_port_id, 0)?;
Ok(new_proc_cap)
}

View File

@ -1,3 +1,4 @@
use crate::cap::Capability;
use crate::syscall;
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 fn parse_init_port(port_cap: z_cap_t) {
let init_port = Capability::take(port_cap);
loop {
let mut bytes: [u8; 8] = [0; 8];
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 {
break;
}

View File

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

View File

@ -1,5 +1,6 @@
use crate::cap::Capability;
use crate::syscall;
use crate::zion::{z_cap_t, ZError};
use crate::zion::ZError;
use alloc::slice;
use linked_list_allocator::LockedHeap;
@ -12,7 +13,7 @@ pub fn init_heap() {
// 1 MiB
let size = 0x10_0000;
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 {
ALLOCATOR.lock().init(vaddr as *mut u8, size as usize);
CAN_ALLOC = true;
@ -20,7 +21,7 @@ pub fn init_heap() {
}
pub struct MemoryRegion {
mem_cap: z_cap_t,
mem_cap: Capability,
virt_addr: u64,
size: u64,
}
@ -28,7 +29,7 @@ pub struct MemoryRegion {
impl MemoryRegion {
pub fn direct_physical(paddr: u64, size: u64) -> Result<Self, ZError> {
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 {
mem_cap,
virt_addr,
@ -36,9 +37,9 @@ impl MemoryRegion {
})
}
pub fn from_cap(mem_cap: z_cap_t) -> Result<Self, ZError> {
let virt_addr = syscall::address_space_map(mem_cap)?;
let size = syscall::memory_object_inspect(mem_cap)?;
pub fn from_cap(mem_cap: Capability) -> Result<Self, ZError> {
let virt_addr = syscall::address_space_map(&mem_cap)?;
let size = syscall::memory_object_inspect(&mem_cap)?;
Ok(Self {
mem_cap,
virt_addr,
@ -48,7 +49,7 @@ impl MemoryRegion {
pub fn new(size: u64) -> Result<Self, ZError> {
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 {
mem_cap,
virt_addr,
@ -74,8 +75,8 @@ impl MemoryRegion {
}
}
pub fn cap(&self) -> z_cap_t {
self.mem_cap
pub fn cap(&self) -> &Capability {
&self.mem_cap
}
}
@ -87,6 +88,5 @@ impl Drop for MemoryRegion {
max += 0x1000 - (max & 0xFFF);
}
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};
pub struct PortServer {
port_cap: z_cap_t,
port_cap: Capability,
}
impl PortServer {
@ -13,14 +14,16 @@ impl PortServer {
}
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> {
let mut caps: [z_cap_t; 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])
}
@ -29,42 +32,24 @@ impl PortServer {
let mut caps: [z_cap_t; 0] = [];
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))
}
}
impl Drop for PortServer {
fn drop(&mut self) {
cap_release(self.port_cap).expect("Failed to release port cap");
}
}
pub struct PortClient {
port_cap: z_cap_t,
port_cap: Capability,
}
impl PortClient {
pub fn take_from(port_cap: z_cap_t) -> Self {
pub fn take_from(port_cap: Capability) -> Self {
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)]
pub fn write_u64_and_cap(&self, bytes: u64, cap: z_cap_t) -> Result<(), ZError> {
let mut caps: [z_cap_t; 1] = [cap];
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");
pub fn write_u64_and_cap(&self, bytes: u64, cap: Capability) -> Result<(), ZError> {
let mut caps: [z_cap_t; 1] = [cap.release()];
crate::syscall::port_send(&self.port_cap, &bytes.to_le_bytes(), &mut caps)
}
}

View File

@ -1,5 +1,6 @@
extern crate alloc;
use crate::cap::Capability;
use crate::zion;
use crate::zion::z_cap_t;
use crate::zion::ZError;
@ -41,9 +42,9 @@ pub fn debug(msg: &str) {
}
pub fn process_spawn(
proc_cap: z_cap_t,
bootstrap_cap: z_cap_t,
) -> Result<(z_cap_t, z_cap_t, z_cap_t), ZError> {
proc_cap: &Capability,
bootstrap_cap: Capability,
) -> Result<(Capability, Capability, u64), ZError> {
let mut new_proc_cap = 0;
let mut new_as_cap = 0;
let mut new_bootstrap_cap = 0;
@ -51,15 +52,19 @@ pub fn process_spawn(
syscall(
zion::kZionProcessSpawn,
&zion::ZProcessSpawnReq {
proc_cap,
bootstrap_cap,
proc_cap: proc_cap.raw(),
bootstrap_cap: bootstrap_cap.release(),
new_proc_cap: &mut new_proc_cap,
new_vmas_cap: &mut new_as_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) -> ! {
@ -68,39 +73,44 @@ pub fn process_exit(code: u64) -> ! {
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;
syscall(
zion::kZionProcessWait,
&zion::ZProcessWaitReq {
proc_cap,
proc_cap: proc_cap.raw(),
exit_code: &mut 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;
syscall(
zion::kZionThreadCreate,
&zion::ZThreadCreateReq {
proc_cap,
thread_cap: &mut cap as *mut z_cap_t,
proc_cap: proc_cap.raw(),
thread_cap: &mut cap,
},
)?;
Ok(cap)
Ok(Capability::take(cap))
}
pub fn thread_sleep(millis: u64) -> Result<(), ZError> {
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(
zion::kZionThreadStart,
&zion::ZThreadStartReq {
thread_cap,
thread_cap: thread_cap.raw(),
entry,
arg1,
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> {
syscall(zion::kZionThreadWait, &zion::ZThreadWaitReq { thread_cap })
pub fn thread_wait(thread_cap: &Capability) -> Result<(), ZError> {
syscall(
zion::kZionThreadWait,
&zion::ZThreadWaitReq {
thread_cap: thread_cap.raw(),
},
)
}
pub fn thread_exit() -> ! {
@ -117,17 +132,17 @@ pub fn thread_exit() -> ! {
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 obj_req = zion::ZMemoryObjectCreateReq {
size,
vmmo_cap: &mut vmmo_cap as *mut u64,
};
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;
syscall(
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,
},
)?;
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;
syscall(
zion::kZionMemoryObjectInspect,
&zion::ZMemoryObjectInspectReq {
vmmo_cap: mem_cap,
vmmo_cap: mem_cap.raw(),
size: &mut 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;
// FIXME: Allow caller to pass these options.
let vmas_req = zion::ZAddressSpaceMapReq {
vmmo_cap,
vmmo_cap: vmmo_cap.raw(),
vmas_cap: unsafe { crate::init::SELF_VMAS_CAP },
align: 0x2000,
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(
vmas_cap: z_cap_t,
vmmo_cap: z_cap_t,
vmas_cap: &Capability,
vmmo_cap: &Capability,
vaddr: u64,
) -> Result<(), ZError> {
let mut vaddr_throw: u64 = 0;
let vmas_req = zion::ZAddressSpaceMapReq {
vmmo_cap,
vmas_cap,
vmas_cap: vmas_cap.raw(),
vmmo_cap: vmmo_cap.raw(),
align: 0,
vaddr: &mut vaddr_throw as *mut u64,
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;
syscall(
zion::kZionPortCreate,
@ -204,14 +219,14 @@ pub fn port_create() -> Result<z_cap_t, ZError> {
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(
zion::kZionPortSend,
&zion::ZPortSendReq {
port_cap,
port_cap: port_cap.raw(),
num_bytes: bytes.len() as u64,
data: bytes.as_ptr() as *const c_void,
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(
port_cap: z_cap_t,
port_cap: &Capability,
bytes: &mut [u8],
caps: &mut [u64],
) -> Result<(u64, u64), ZError> {
@ -231,7 +246,7 @@ pub fn port_recv(
syscall(
zion::kZionPortRecv,
&zion::ZPortRecvReq {
port_cap,
port_cap: port_cap.raw(),
data: bytes.as_mut_ptr() as *mut c_void,
num_bytes: &mut num_bytes as *mut u64,
caps: caps.as_mut_ptr(),
@ -242,14 +257,14 @@ pub fn port_recv(
}
pub fn port_poll(
port_cap: z_cap_t,
port_cap: &Capability,
bytes: &mut [u8],
caps: &mut [u64],
) -> Result<(u64, u64), ZError> {
let mut num_bytes = bytes.len() as u64;
let mut num_caps = caps.len() as u64;
let req = zion::ZPortPollReq {
port_cap,
port_cap: port_cap.raw(),
data: bytes.as_mut_ptr() as *mut c_void,
num_bytes: &mut num_bytes as *mut u64,
caps: caps.as_mut_ptr(),
@ -259,7 +274,7 @@ pub fn port_poll(
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;
syscall(
zion::kZionEndpointCreate,
@ -267,19 +282,19 @@ pub fn endpoint_create() -> Result<z_cap_t, ZError> {
endpoint_cap: &mut endpoint_cap,
},
)?;
Ok(endpoint_cap)
Ok(Capability::take(endpoint_cap))
}
pub fn endpoint_send(
endpoint_cap: z_cap_t,
endpoint_cap: &Capability,
bytes: &[u8],
caps: &[z_cap_t],
) -> Result<z_cap_t, ZError> {
) -> Result<Capability, ZError> {
let mut reply_port_cap: u64 = 0;
let send_req = zion::ZEndpointSendReq {
caps: caps.as_ptr(),
num_caps: caps.len() as u64,
endpoint_cap,
endpoint_cap: endpoint_cap.raw(),
data: bytes.as_ptr() as *const c_void,
num_bytes: bytes.len() as u64,
reply_port_cap: &mut reply_port_cap,
@ -287,19 +302,19 @@ pub fn endpoint_send(
syscall(zion::kZionEndpointSend, &send_req)?;
Ok(reply_port_cap)
Ok(Capability::take(reply_port_cap))
}
pub fn endpoint_recv(
endpoint_cap: z_cap_t,
endpoint_cap: &Capability,
bytes: &mut [u8],
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_caps = caps.len() as u64;
let mut reply_port_cap = 0;
let recv_req = zion::ZEndpointRecvReq {
endpoint_cap,
endpoint_cap: endpoint_cap.raw(),
data: bytes.as_mut_ptr() as *mut c_void,
num_bytes: &mut num_bytes,
caps: caps.as_mut_ptr(),
@ -309,18 +324,18 @@ pub fn endpoint_recv(
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(
reply_port_cap: z_cap_t,
reply_port_cap: Capability,
bytes: &[u8],
caps: &[z_cap_t],
) -> Result<(), ZError> {
syscall(
zion::kZionReplyPortSend,
&zion::ZReplyPortSendReq {
reply_port_cap,
reply_port_cap: reply_port_cap.raw(),
data: bytes.as_ptr() as *const c_void,
num_bytes: bytes.len() as u64,
caps: caps.as_ptr(),
@ -330,14 +345,14 @@ pub fn reply_port_send(
}
pub fn reply_port_recv(
reply_port_cap: z_cap_t,
reply_port_cap: Capability,
bytes: &mut [u8],
caps: &mut [z_cap_t],
) -> Result<(u64, u64), ZError> {
let mut num_bytes = bytes.len() as u64;
let mut num_caps = caps.len() as u64;
let recv_req = zion::ZReplyPortRecvReq {
reply_port_cap,
reply_port_cap: reply_port_cap.raw(),
caps: caps.as_mut_ptr(),
num_caps: &mut num_caps,
data: bytes.as_mut_ptr() as *mut c_void,
@ -348,20 +363,3 @@ pub fn reply_port_recv(
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::zion;
use crate::zion::z_cap_t;
use alloc::boxed::Box;
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.
pub struct Thread {
cap: z_cap_t,
cap: Capability,
// This field only exists to ensure that the entry reference will outlive the thread object
// itself.
entry: ThreadEntry,
@ -25,11 +25,11 @@ pub struct Thread {
impl Thread {
pub fn spawn(entry: ThreadEntry, arg1: *const c_void) -> Result<Box<Self>, zion::ZError> {
let proc_cap = unsafe { crate::init::SELF_PROC_CAP };
let cap = syscall::thread_create(proc_cap)?;
let proc_cap = Capability::take_copy(unsafe { crate::init::SELF_PROC_CAP })?;
let cap = syscall::thread_create(&proc_cap)?;
let thread = Box::new(Self { cap, entry });
syscall::thread_start(
cap,
&thread.cap,
internal_entry_point as u64,
thread.as_ref() as *const Thread as u64,
arg1 as u64,
@ -39,6 +39,6 @@ impl Thread {
}
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 alloc::string::ToString;
use mammoth::zion::ZError;
use mammoth::{cap::Capability, zion::ZError};
pub struct File {
memory: mammoth::mem::MemoryRegion,
@ -14,7 +14,7 @@ impl File {
})?;
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");
VFS_CLIENT = Some(VFSClient::new(endpoint_cap.endpoint));
VFS_CLIENT = Some(VFSClient::new(Capability::take(endpoint_cap.endpoint)));
}
VFS_CLIENT.as_mut().unwrap()
}

View File

@ -3,6 +3,7 @@ use core::cell::RefCell;
use alloc::boxed::Box;
use alloc::rc::Rc;
use alloc::string::ToString;
use mammoth::cap::Capability;
use mammoth::port::PortServer;
use mammoth::thread::Thread;
use mammoth::zion::ZError;
@ -216,7 +217,7 @@ impl KeyboardListener {
})?
.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 {
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 {
unsafe {
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()

View File

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

View File

@ -1,5 +1,6 @@
use crate::buffer::ByteBuffer;
use alloc::vec::Vec;
use mammoth::cap::Capability;
use mammoth::syscall;
use mammoth::zion::z_cap_t;
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(
&self,
method_number: u64,

View File

@ -117,9 +117,9 @@ impl Terminal {
Some(prog) => {
let file = victoriafalls::file::File::open(prog).expect("Failed to open file");
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.");
self.write_line(&format!("Process exit code: {}", exit_code));

View File

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

View File

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