refactor: apply newtypes throughout userspace API and display types
Every syscall stub now uses proper types from types/ — CapSlot,
EntryPoint, StackPointer, VirtualAddress, PageCount, ProcessId,
PermissionSet, Ticks. The compiler prevents swapping entry/stack,
passing a ProcessId where a CapSlot is expected, or using an
address as a page count.
New display types in types/display.rs:
- Color(u32) with rgb() constructor
- ScreenCoord(u16) for x/y positions
- Dimension(u16) for width/height
Updated throughout:
- userspace/syscall.rs: all params typed, returns Option instead
of sentinel usize::MAX
- server-framework: endpoint param is CapSlot
- port-framebuffer: trait uses Color, ScreenCoord, Dimension
- hw-virtio: DmaAddrs uses PhysicalAddress/VirtualAddress,
GPU commands use Dimension
- All servers, drivers, bins, apps updated for new signatures
- permission-manager: process field uses ProcessId
- PermissionSet: added bits() accessor
89 tests pass, full QEMU boot verified.
This commit is contained in:
@@ -1,15 +1,18 @@
|
||||
#![no_std]
|
||||
|
||||
use types::address::{EntryPoint, StackPointer, VirtualAddress};
|
||||
use types::bounded::{CapSlot, PageCount};
|
||||
use types::permission::{Permission, PermissionSet};
|
||||
use userspace::syscall;
|
||||
|
||||
const PAGE_SIZE: usize = 4096;
|
||||
const USER_CODE_BASE: usize = 0x10000;
|
||||
const USER_STACK_TOP: usize = USER_CODE_BASE;
|
||||
const USER_STACK_TOP: StackPointer = StackPointer::from_raw(USER_CODE_BASE);
|
||||
const USER_STACK_PAGES: usize = 4;
|
||||
const CMD_READ_FILE: usize = 1;
|
||||
|
||||
const CREATE_CAP: usize = 0;
|
||||
const STORAGE_EP_CAP: usize = 2;
|
||||
fn create_cap() -> CapSlot { CapSlot::new(0).unwrap() }
|
||||
fn storage_ep() -> CapSlot { CapSlot::new(2).unwrap() }
|
||||
|
||||
fn debug_print(s: &[u8]) {
|
||||
for &b in s {
|
||||
@@ -43,14 +46,14 @@ fn request_file(shared_buf: *mut u8, filename: &[u8]) -> usize {
|
||||
core::ptr::write_volatile(shared_buf.add(i), b);
|
||||
}
|
||||
}
|
||||
syscall::send(STORAGE_EP_CAP, CMD_READ_FILE, filename.len(), 0, 0);
|
||||
let (file_size, _, _, _) = syscall::receive(STORAGE_EP_CAP);
|
||||
syscall::send(storage_ep(), CMD_READ_FILE, filename.len(), 0, 0);
|
||||
let (file_size, _, _, _) = syscall::receive(storage_ep());
|
||||
file_size
|
||||
}
|
||||
|
||||
struct LoadedProcess {
|
||||
process_cap: usize,
|
||||
entry_point: usize,
|
||||
process_cap: CapSlot,
|
||||
entry_point: EntryPoint,
|
||||
}
|
||||
|
||||
fn load_binary(shared_buf: *mut u8, filename: &[u8]) -> Option<LoadedProcess> {
|
||||
@@ -65,11 +68,7 @@ fn load_binary(shared_buf: *mut u8, filename: &[u8]) -> Option<LoadedProcess> {
|
||||
Err(_) => return None,
|
||||
};
|
||||
|
||||
let process_cap = syscall::create_process(CREATE_CAP);
|
||||
if process_cap == usize::MAX {
|
||||
debug_print(b"create_process failed\n");
|
||||
return None;
|
||||
}
|
||||
let process_cap = syscall::create_process(create_cap())?;
|
||||
|
||||
for segment in elf_info.segments() {
|
||||
let page_start = segment.vaddr & !0xFFF;
|
||||
@@ -77,13 +76,10 @@ fn load_binary(shared_buf: *mut u8, filename: &[u8]) -> Option<LoadedProcess> {
|
||||
let total_size = offset_in_page + segment.mem_size;
|
||||
let seg_pages = (total_size + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
|
||||
let local_va = syscall::request_pages(seg_pages);
|
||||
if local_va == usize::MAX {
|
||||
debug_print(b"request_pages failed\n");
|
||||
return None;
|
||||
}
|
||||
let page_count = PageCount::new(seg_pages as u16)?;
|
||||
let local_va = syscall::request_pages(page_count)?;
|
||||
|
||||
let local_ptr = local_va as *mut u8;
|
||||
let local_ptr = local_va.raw() as *mut u8;
|
||||
unsafe {
|
||||
core::ptr::write_bytes(local_ptr, 0, seg_pages * PAGE_SIZE);
|
||||
}
|
||||
@@ -103,22 +99,22 @@ fn load_binary(shared_buf: *mut u8, filename: &[u8]) -> Option<LoadedProcess> {
|
||||
}
|
||||
|
||||
for p in 0..seg_pages {
|
||||
let src_page = local_va + p * PAGE_SIZE;
|
||||
let dst_page = page_start + p * PAGE_SIZE;
|
||||
let src_page = VirtualAddress::from_raw(local_va.raw() + p * PAGE_SIZE);
|
||||
let dst_page = VirtualAddress::from_raw(page_start + p * PAGE_SIZE);
|
||||
syscall::map_page(process_cap, src_page, dst_page, segment.flags.execute);
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0..USER_STACK_PAGES {
|
||||
let stack_va = syscall::request_pages(1);
|
||||
if stack_va == usize::MAX { return None; }
|
||||
let dst = USER_STACK_TOP - (USER_STACK_PAGES - i) * PAGE_SIZE;
|
||||
let page_count = PageCount::new(1)?;
|
||||
let stack_va = syscall::request_pages(page_count)?;
|
||||
let dst = VirtualAddress::from_raw(USER_CODE_BASE - (USER_STACK_PAGES - i) * PAGE_SIZE);
|
||||
syscall::map_page(process_cap, stack_va, dst, false);
|
||||
}
|
||||
|
||||
Some(LoadedProcess {
|
||||
process_cap,
|
||||
entry_point: elf_info.entry_point,
|
||||
entry_point: EntryPoint::from_raw(elf_info.entry_point),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -127,7 +123,6 @@ struct ServerInfo {
|
||||
name: &'static [u8],
|
||||
}
|
||||
|
||||
// display is loaded by the adapter (needs GPU MMIO access)
|
||||
const SERVERS: &[ServerInfo] = &[
|
||||
ServerInfo { filename: b"input.elf", name: b"input" },
|
||||
ServerInfo { filename: b"log.elf", name: b"log" },
|
||||
@@ -140,9 +135,13 @@ pub fn run(shared_buf_va: usize) -> ! {
|
||||
let shared_buf = shared_buf_va as *mut u8;
|
||||
|
||||
debug_print(b"init: started (pid=");
|
||||
debug_hex(syscall::get_process_id());
|
||||
debug_hex(syscall::get_process_id().raw() as usize);
|
||||
debug_print(b")\n");
|
||||
|
||||
let ipc_perms = PermissionSet::empty()
|
||||
.with(Permission::Read)
|
||||
.with(Permission::Execute);
|
||||
|
||||
for server in SERVERS {
|
||||
debug_print(b"init: loading ");
|
||||
debug_print(server.name);
|
||||
@@ -156,13 +155,13 @@ pub fn run(shared_buf_va: usize) -> ! {
|
||||
}
|
||||
};
|
||||
|
||||
let ep_cap = syscall::create_endpoint();
|
||||
let read_execute: usize = (1 << 0) | (1 << 2);
|
||||
syscall::delegate(ep_cap, loaded.process_cap, read_execute);
|
||||
syscall::spawn_thread_in(loaded.process_cap, loaded.entry_point, USER_STACK_TOP);
|
||||
if let Some(ep_cap) = syscall::create_endpoint() {
|
||||
syscall::delegate(ep_cap, loaded.process_cap, ipc_perms);
|
||||
syscall::spawn_thread_in(loaded.process_cap, loaded.entry_point, USER_STACK_TOP);
|
||||
}
|
||||
|
||||
debug_print(b"ok (entry=");
|
||||
debug_hex(loaded.entry_point);
|
||||
debug_hex(loaded.entry_point.raw());
|
||||
debug_print(b")\n");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user