Reorganize mammoth lib in rust.

This commit is contained in:
Drew Galbraith 2024-07-28 19:26:23 -07:00
parent d5a5041c4b
commit d35e8d253f
12 changed files with 223 additions and 214 deletions

View File

@ -0,0 +1,42 @@
use crate::syscall;
use crate::zion;
use crate::zion::z_cap_t;
use core::ffi::c_void;
// From /zion/include/ztypes.h
const Z_INIT_SELF_PROC: u64 = 0x4000_0000;
const Z_INIT_SELF_VMAS: u64 = 0x4000_0001;
const Z_INIT_ENDPOINT: u64 = 0x4100_0000;
pub static mut SELF_PROC_CAP: z_cap_t = 0;
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) {
loop {
let mut num_bytes: u64 = 8;
let mut init_sig: u64 = 0;
let mut caps: [u64; 1] = [0];
let mut num_caps: u64 = 1;
let req = zion::ZPortPollReq {
port_cap,
num_bytes: &mut num_bytes as *mut u64,
data: &mut init_sig as *mut u64 as *mut c_void,
caps: &mut caps as *mut u64,
num_caps: &mut num_caps as *mut u64,
};
let resp = syscall::syscall(zion::kZionPortPoll, &req);
if let Err(_) = resp {
break;
}
unsafe {
match init_sig {
Z_INIT_SELF_PROC => SELF_PROC_CAP = caps[0],
Z_INIT_SELF_VMAS => SELF_VMAS_CAP = caps[0],
Z_INIT_ENDPOINT => INIT_ENDPOINT = caps[0],
_ => syscall::debug("Unknown Cap in Init"),
}
}
}
}

View File

@ -5,67 +5,11 @@
extern crate alloc;
use core::ffi::c_void;
pub mod mem;
#[macro_use]
pub mod macros;
pub mod init;
pub mod mem;
pub mod syscall;
pub mod thread;
// From /zion/include/ztypes.h
const Z_INIT_SELF_PROC: u64 = 0x4000_0000;
const Z_INIT_SELF_VMAS: u64 = 0x4000_0001;
const Z_INIT_ENDPOINT: u64 = 0x4100_0000;
static mut SELF_PROC_CAP: syscall::zcap = 0;
static mut SELF_VMAS_CAP: syscall::zcap = 0;
pub static mut INIT_ENDPOINT: syscall::zcap = 0;
pub fn parse_init_port(port_cap: syscall::zcap) {
loop {
let mut num_bytes: u64 = 8;
let mut init_sig: u64 = 0;
let mut caps: [u64; 1] = [0];
let mut num_caps: u64 = 1;
let req = syscall::ZPortPollReq {
port_cap,
num_bytes: &mut num_bytes as *mut u64,
data: &mut init_sig as *mut u64 as *mut c_void,
caps: &mut caps as *mut u64,
num_caps: &mut num_caps as *mut u64,
};
let resp = syscall::syscall(syscall::kZionPortPoll, &req);
if let Err(_) = resp {
break;
}
unsafe {
match init_sig {
Z_INIT_SELF_PROC => SELF_PROC_CAP = caps[0],
Z_INIT_SELF_VMAS => SELF_VMAS_CAP = caps[0],
Z_INIT_ENDPOINT => INIT_ENDPOINT = caps[0],
_ => syscall::debug("Unknown Cap in Init"),
}
}
}
}
#[macro_export]
macro_rules! define_entry {
() => {
#[no_mangle]
pub extern "C" fn _start(init_port: mammoth::syscall::zcap) -> ! {
extern "C" {
fn main() -> z_err_t;
}
mammoth::parse_init_port(init_port);
mammoth::mem::init_heap();
unsafe {
let err = main();
let req = mammoth::syscall::ZProcessExitReq { code: err };
let _ = mammoth::syscall::syscall(mammoth::syscall::kZionProcessExit, &req);
}
unreachable!()
}
};
}
pub mod zion;

View File

@ -0,0 +1,67 @@
use alloc::string::String;
use alloc::vec::Vec;
use core::fmt;
pub struct Writer {
int_vec: Vec<u8>,
}
impl Writer {
pub fn new() -> Self {
Self {
int_vec: Vec::new(),
}
}
}
impl Into<String> for Writer {
fn into(self) -> String {
String::from_utf8(self.int_vec).expect("Failed to convert")
}
}
impl fmt::Write for Writer {
fn write_str(&mut self, s: &str) -> fmt::Result {
for c in s.bytes() {
self.int_vec.push(c);
}
fmt::Result::Ok(())
}
}
#[macro_export]
macro_rules! debug {
() => {
$crate::syscall::debug("");
};
($fmt:literal) => {
$crate::syscall::debug($fmt);
};
($fmt:literal, $($val:expr),+) => {{
use core::fmt::Write as _;
let mut w = $crate::macros::Writer::new();
write!(&mut w, $fmt, $($val),*).expect("Failed to format");
let s: alloc::string::String = w.into();
$crate::syscall::debug(&s);
}};
}
#[macro_export]
macro_rules! define_entry {
() => {
#[no_mangle]
pub extern "C" fn _start(init_port: mammoth::zion::z_cap_t) -> ! {
extern "C" {
fn main() -> z_err_t;
}
mammoth::init::parse_init_port(init_port);
mammoth::mem::init_heap();
unsafe {
let err = main();
let req = mammoth::zion::ZProcessExitReq { code: err };
let _ = mammoth::syscall::syscall(mammoth::zion::kZionProcessExit, &req);
}
unreachable!()
}
};
}

View File

@ -1,5 +1,6 @@
use crate::init::SELF_VMAS_CAP;
use crate::syscall;
use crate::SELF_VMAS_CAP;
use crate::zion;
use linked_list_allocator::LockedHeap;
#[global_allocator]
@ -11,16 +12,16 @@ pub fn init_heap() {
// 1 MiB
let size = 0x10_0000;
let mut vmmo_cap = 0;
let obj_req = syscall::ZMemoryObjectCreateReq {
let obj_req = zion::ZMemoryObjectCreateReq {
size,
vmmo_cap: &mut vmmo_cap as *mut u64,
};
syscall::syscall(syscall::kZionMemoryObjectCreate, &obj_req)
syscall::syscall(zion::kZionMemoryObjectCreate, &obj_req)
.expect("Failed to create memory object");
unsafe {
let mut vaddr: u64 = 0;
let vmas_req = syscall::ZAddressSpaceMapReq {
let vmas_req = zion::ZAddressSpaceMapReq {
vmmo_cap,
vmas_cap: SELF_VMAS_CAP,
align: 0x2000,
@ -28,7 +29,7 @@ pub fn init_heap() {
vmas_offset: 0,
};
syscall::syscall(syscall::kZionAddressSpaceMap, &vmas_req)
syscall::syscall(zion::kZionAddressSpaceMap, &vmas_req)
.expect("Failed to map memory object");
ALLOCATOR.lock().init(vaddr as *mut u8, size as usize);
CAN_ALLOC = true;

View File

@ -1,85 +1,15 @@
extern crate alloc;
use alloc::string::String;
use alloc::vec::Vec;
use crate::zion;
use core::ffi::c_void;
use core::fmt;
use core::panic::PanicInfo;
include!("bindings.rs");
pub enum ZError {
UNKNOWN = 0x0,
// First set of error codes generally indicate user errors.
INVALID_ARGUMENT = 0x1,
NOT_FOUND = 0x2,
PERMISSION_DENIED = 0x3,
NULL_PTR = 0x4,
EMPTY = 0x5,
ALREADY_EXISTS = 0x6,
BUFFER_SIZE = 0x7,
FAILED_PRECONDITION = 0x8,
// Second set of error codes generally indicate service errors.
INTERNAL = 0x100,
UNIMPLEMENTED = 0x101,
EXHAUSTED = 0x102,
INVALID_RESPONSE = 0x103,
// Kernel specific error codes (relating to capabilities).
CAP_NOT_FOUND = 0x1000,
CAP_WRONG_TYPE = 0x1001,
CAP_PERMISSION_DENIED = 0x1002,
}
impl From<u64> for ZError {
fn from(value: u64) -> Self {
match value {
0x1 => ZError::INVALID_ARGUMENT,
0x2 => ZError::NOT_FOUND,
0x3 => ZError::PERMISSION_DENIED,
0x4 => ZError::NULL_PTR,
0x5 => ZError::EMPTY,
0x6 => ZError::ALREADY_EXISTS,
0x7 => ZError::BUFFER_SIZE,
0x8 => ZError::FAILED_PRECONDITION,
0x100 => ZError::INTERNAL,
0x101 => ZError::UNIMPLEMENTED,
0x102 => ZError::EXHAUSTED,
0x103 => ZError::INVALID_RESPONSE,
0x1000 => ZError::CAP_NOT_FOUND,
0x1001 => ZError::CAP_WRONG_TYPE,
0x1002 => ZError::CAP_PERMISSION_DENIED,
_ => ZError::UNKNOWN,
}
}
}
impl fmt::Debug for ZError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let str = match self {
ZError::INVALID_ARGUMENT => "INVALID_ARGUMENT",
ZError::BUFFER_SIZE => "BUFFER_SIZE",
ZError::INTERNAL => "INTERNAL",
ZError::UNIMPLEMENTED => "UNIMPLEMENTED",
ZError::INVALID_RESPONSE => "INVALID_RESPONSE",
ZError::CAP_NOT_FOUND => "CAP_NOT_FOUND",
ZError::CAP_WRONG_TYPE => "CAP_WRONG_TYPE",
ZError::CAP_PERMISSION_DENIED => "CAP_PERMISSION_DENIED",
_ => "ZError",
};
f.write_str(str)
}
}
#[must_use]
pub fn syscall<T>(id: u64, req: &T) -> Result<(), ZError> {
pub fn syscall<T>(id: u64, req: &T) -> Result<(), zion::ZError> {
unsafe {
let resp = SysCall1(id, req as *const T as *const c_void);
let resp = zion::SysCall1(id, req as *const T as *const c_void);
if resp != 0 {
return Err(ZError::from(resp));
return Err(zion::ZError::from(resp));
}
}
Ok(())
@ -95,60 +25,15 @@ fn panic(info: &PanicInfo) -> ! {
}
}
// Internal error.
let req = ZProcessExitReq { code: 0x100 };
let _ = syscall(kZionProcessExit, &req);
let req = zion::ZProcessExitReq { code: 0x100 };
let _ = syscall(zion::kZionProcessExit, &req);
unreachable!()
}
pub fn debug(msg: &str) {
let req = ZDebugReq {
let req = zion::ZDebugReq {
message: msg.as_ptr() as *const i8,
size: msg.len() as u64,
};
syscall(kZionDebug, &req).expect("Failed to write");
}
pub struct Writer {
int_vec: Vec<u8>,
}
impl Writer {
pub fn new() -> Self {
Self {
int_vec: Vec::new(),
}
}
}
impl Into<String> for Writer {
fn into(self) -> String {
String::from_utf8(self.int_vec).expect("Failed to convert")
}
}
impl fmt::Write for Writer {
fn write_str(&mut self, s: &str) -> fmt::Result {
for c in s.bytes() {
self.int_vec.push(c);
}
fmt::Result::Ok(())
}
}
#[macro_export]
macro_rules! debug {
() => {
$crate::syscall::debug("");
};
($fmt:literal) => {
$crate::syscall::debug($fmt);
};
($fmt:literal, $($val:expr),+) => {{
use core::fmt::Write as _;
use alloc::string::String;
let mut w = $crate::syscall::Writer::new();
write!(&mut w, $fmt, $($val),*).expect("Failed to format");
let s: String = w.into();
$crate::syscall::debug(&s);
}};
syscall(zion::kZionDebug, &req).expect("Failed to write");
}

View File

@ -1,5 +1,6 @@
use crate::syscall;
use crate::syscall::z_cap_t;
use crate::zion;
use crate::zion::z_cap_t;
use core::ffi::c_void;
@ -12,7 +13,7 @@ extern "C" fn entry_point(entry_ptr: *const ThreadEntry, arg1: *const c_void) ->
entry(arg1);
let _ = syscall::syscall(syscall::kZionThreadExit, &syscall::ZThreadExitReq {});
let _ = syscall::syscall(zion::kZionThreadExit, &zion::ZThreadExitReq {});
unreachable!();
}
@ -28,16 +29,16 @@ pub struct Thread<'a> {
impl<'a> Thread<'a> {
pub fn spawn(entry: &'a ThreadEntry, arg1: *const c_void) -> Self {
let mut cap: z_cap_t = 0;
let req = syscall::ZThreadCreateReq {
proc_cap: unsafe { crate::SELF_PROC_CAP },
let req = zion::ZThreadCreateReq {
proc_cap: unsafe { crate::init::SELF_PROC_CAP },
thread_cap: &mut cap as *mut z_cap_t,
};
syscall::syscall(syscall::kZionThreadCreate, &req).expect("Failed to create thread.");
syscall::syscall(zion::kZionThreadCreate, &req).expect("Failed to create thread.");
syscall::syscall(
syscall::kZionThreadStart,
&syscall::ZThreadStartReq {
zion::kZionThreadStart,
&zion::ZThreadStartReq {
thread_cap: cap,
entry: entry_point as u64,
arg1: entry as *const ThreadEntry as u64,
@ -49,10 +50,10 @@ impl<'a> Thread<'a> {
Self { cap, _entry: entry }
}
pub fn join(&self) -> Result<(), syscall::ZError> {
pub fn join(&self) -> Result<(), zion::ZError> {
syscall::syscall(
syscall::kZionThreadWait,
&syscall::ZThreadWaitReq {
zion::kZionThreadWait,
&zion::ZThreadWaitReq {
thread_cap: self.cap,
},
)

View File

@ -0,0 +1,69 @@
include!("bindings.rs");
use core::fmt;
pub enum ZError {
UNKNOWN = 0x0,
// First set of error codes generally indicate user errors.
INVALID_ARGUMENT = 0x1,
NOT_FOUND = 0x2,
PERMISSION_DENIED = 0x3,
NULL_PTR = 0x4,
EMPTY = 0x5,
ALREADY_EXISTS = 0x6,
BUFFER_SIZE = 0x7,
FAILED_PRECONDITION = 0x8,
// Second set of error codes generally indicate service errors.
INTERNAL = 0x100,
UNIMPLEMENTED = 0x101,
EXHAUSTED = 0x102,
INVALID_RESPONSE = 0x103,
// Kernel specific error codes (relating to capabilities).
CAP_NOT_FOUND = 0x1000,
CAP_WRONG_TYPE = 0x1001,
CAP_PERMISSION_DENIED = 0x1002,
}
impl From<u64> for ZError {
fn from(value: u64) -> Self {
match value {
0x1 => ZError::INVALID_ARGUMENT,
0x2 => ZError::NOT_FOUND,
0x3 => ZError::PERMISSION_DENIED,
0x4 => ZError::NULL_PTR,
0x5 => ZError::EMPTY,
0x6 => ZError::ALREADY_EXISTS,
0x7 => ZError::BUFFER_SIZE,
0x8 => ZError::FAILED_PRECONDITION,
0x100 => ZError::INTERNAL,
0x101 => ZError::UNIMPLEMENTED,
0x102 => ZError::EXHAUSTED,
0x103 => ZError::INVALID_RESPONSE,
0x1000 => ZError::CAP_NOT_FOUND,
0x1001 => ZError::CAP_WRONG_TYPE,
0x1002 => ZError::CAP_PERMISSION_DENIED,
_ => ZError::UNKNOWN,
}
}
}
impl fmt::Debug for ZError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let str = match self {
ZError::INVALID_ARGUMENT => "INVALID_ARGUMENT",
ZError::BUFFER_SIZE => "BUFFER_SIZE",
ZError::INTERNAL => "INTERNAL",
ZError::UNIMPLEMENTED => "UNIMPLEMENTED",
ZError::INVALID_RESPONSE => "INVALID_RESPONSE",
ZError::CAP_NOT_FOUND => "CAP_NOT_FOUND",
ZError::CAP_WRONG_TYPE => "CAP_WRONG_TYPE",
ZError::CAP_PERMISSION_DENIED => "CAP_PERMISSION_DENIED",
_ => "ZError",
};
f.write_str(str)
}
}

View File

@ -1,5 +1,5 @@
use alloc::boxed::Box;
use mammoth::syscall::ZError;
use mammoth::zion::ZError;
pub struct ByteBuffer<const N: usize> {
buffer: Box<[u8; N]>,

View File

@ -2,8 +2,8 @@ use crate::buffer::ByteBuffer;
use crate::message::YunqMessage;
use alloc::vec::Vec;
use core::ffi::c_void;
use mammoth::syscall::z_cap_t;
use mammoth::syscall::ZError;
use mammoth::zion::z_cap_t;
use mammoth::zion::ZError;
const SENTINEL: u32 = 0xBEEFDEAD;
@ -22,7 +22,7 @@ pub fn call_endpoint<Req: YunqMessage, Resp: YunqMessage, const N: usize>(
byte_buffer.write_at(4, (16 + length) as u32)?;
let mut reply_port_cap: u64 = 0;
let send_req = mammoth::syscall::ZEndpointSendReq {
let send_req = mammoth::zion::ZEndpointSendReq {
caps: cap_buffer.as_ptr(),
num_caps: cap_buffer.len() as u64,
endpoint_cap,
@ -31,13 +31,13 @@ pub fn call_endpoint<Req: YunqMessage, Resp: YunqMessage, const N: usize>(
reply_port_cap: &mut reply_port_cap as *mut z_cap_t,
};
mammoth::syscall::syscall(mammoth::syscall::kZionEndpointSend, &send_req)?;
mammoth::syscall::syscall(mammoth::zion::kZionEndpointSend, &send_req)?;
// FIXME: Add a way to zero out the byte buffer.
let mut buffer_size = byte_buffer.size();
let mut num_caps: u64 = 10;
cap_buffer = vec![0; num_caps as usize];
let recv_req = mammoth::syscall::ZReplyPortRecvReq {
let recv_req = mammoth::zion::ZReplyPortRecvReq {
reply_port_cap,
caps: cap_buffer.as_mut_ptr(),
num_caps: &mut num_caps as *mut u64,
@ -45,7 +45,7 @@ pub fn call_endpoint<Req: YunqMessage, Resp: YunqMessage, const N: usize>(
num_bytes: &mut buffer_size as *mut u64,
};
mammoth::syscall::syscall(mammoth::syscall::kZionReplyPortRecv, &recv_req)?;
mammoth::syscall::syscall(mammoth::zion::kZionReplyPortRecv, &recv_req)?;
if byte_buffer.at::<u32>(0)? != SENTINEL {
return Err(ZError::INVALID_RESPONSE);

View File

@ -1,7 +1,7 @@
use crate::buffer::ByteBuffer;
use alloc::vec::Vec;
use mammoth::syscall::z_cap_t;
use mammoth::syscall::ZError;
use mammoth::zion::z_cap_t;
use mammoth::zion::ZError;
pub const MESSAGE_IDENT: u32 = 0x33441122;
pub const MESSAGE_HEADER_SIZE: usize = 24; // 4x uint32, 1x uint64

View File

@ -8,8 +8,8 @@ use alloc::string::ToString;
use mammoth::debug;
use mammoth::define_entry;
use mammoth::syscall::debug;
use mammoth::syscall::z_err_t;
use mammoth::thread;
use mammoth::zion::z_err_t;
use yellowstone::GetEndpointRequest;
use yellowstone::YellowstoneClient;
@ -22,16 +22,16 @@ pub extern "C" fn main() -> z_err_t {
debug(&x);
debug!("Formatted {}", "string");
let mut vmmo_cap: u64 = 0;
let obj_req = mammoth::syscall::ZMemoryObjectCreateReq {
let obj_req = mammoth::zion::ZMemoryObjectCreateReq {
size: 0,
vmmo_cap: &mut vmmo_cap as *mut u64,
};
mammoth::syscall::syscall(mammoth::syscall::kZionMemoryObjectCreate, &obj_req)
mammoth::syscall::syscall(mammoth::zion::kZionMemoryObjectCreate, &obj_req)
.expect("Failed to create memory object");
let mut yellowstone;
unsafe {
yellowstone = YellowstoneClient::new(mammoth::INIT_ENDPOINT);
yellowstone = YellowstoneClient::new(mammoth::init::INIT_ENDPOINT);
}
let endpoint = yellowstone

View File

@ -79,8 +79,8 @@ pub fn generate_code(ast: &Vec<Decl>) -> String {
use alloc::string::String;
use alloc::string::ToString;
use mammoth::syscall::z_cap_t;
use mammoth::syscall::ZError;
use mammoth::zion::z_cap_t;
use mammoth::zion::ZError;
use yunq::ByteBuffer;
use yunq::YunqMessage;
use yunq_derive::YunqMessage;