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:
2026-10-18 13:45:40 +02:00
parent 3a0395453b
commit 7c7e3b8748
42 changed files with 416 additions and 307 deletions

View File

@@ -9,5 +9,6 @@ test = false
bench = false
[dependencies]
types = { workspace = true }
userspace = { workspace = true }
userspace-rt = { workspace = true }

View File

@@ -3,14 +3,13 @@
extern crate userspace_rt;
use types::bounded::CapSlot;
use userspace::syscall;
#[unsafe(no_mangle)]
extern "C" fn main() {
// Cap slot 0 = endpoint cap (granted by adapter at boot)
let ep: usize = 0;
let ep = CapSlot::new(0).unwrap();
// Receive a message, echo it back with word0 incremented
let (w0, w1, w2, w3) = syscall::receive(ep);
syscall::send(ep, w0.wrapping_add(1), w1, w2, w3);

View File

@@ -5,11 +5,13 @@ extern crate userspace_rt;
use snake::game::{Direction, GameState, Snake};
use snake::renderer::{render, RenderCommand};
use types::bounded::CapSlot;
use types::time::Ticks;
use userspace_rt::syscall;
const DISPLAY_EP: usize = 0;
const INPUT_EP: usize = 1;
const TICK_DELAY: usize = 2_000_000;
fn display_ep() -> CapSlot { CapSlot::new(0).unwrap() }
fn input_ep() -> CapSlot { CapSlot::new(1).unwrap() }
const TICK_DELAY: u64 = 2_000_000;
const MAX_RENDER_COMMANDS: usize = 192;
#[unsafe(no_mangle)]
@@ -33,8 +35,8 @@ extern "C" fn main() {
}
fn handle_input(snake: &mut Snake) {
let _ = syscall::send(INPUT_EP, 0, 0, 0, 0);
let (tag, kind, _, _) = syscall::receive(INPUT_EP);
let _ = syscall::send(input_ep(), 0, 0, 0, 0);
let (tag, kind, _, _) = syscall::receive(input_ep());
if tag == 1 {
match kind {
@@ -48,25 +50,25 @@ fn handle_input(snake: &mut Snake) {
}
fn send_render_commands(commands: &[RenderCommand], count: usize) {
let _ = syscall::send(DISPLAY_EP, 1, 0, 0, 0);
let _ = syscall::receive(DISPLAY_EP);
let _ = syscall::send(display_ep(), 1, 0, 0, 0);
let _ = syscall::receive(display_ep());
for i in 0..count {
let cmd = &commands[i];
let xy = cmd.x as usize | ((cmd.y as usize) << 16);
let wh = cmd.w as usize | ((cmd.h as usize) << 16);
let _ = syscall::send(DISPLAY_EP, 0, xy, wh, cmd.color as usize);
let _ = syscall::receive(DISPLAY_EP);
let _ = syscall::send(display_ep(), 0, xy, wh, cmd.color as usize);
let _ = syscall::receive(display_ep());
}
let _ = syscall::send(DISPLAY_EP, 2, 0, 0, 0);
let _ = syscall::receive(DISPLAY_EP);
let _ = syscall::send(display_ep(), 2, 0, 0, 0);
let _ = syscall::receive(display_ep());
}
fn wait_tick() {
let start = syscall::get_time();
let deadline = start + TICK_DELAY;
while syscall::get_time() < deadline {
let deadline = Ticks::from_raw(start.raw() + TICK_DELAY);
while syscall::get_time().raw() < deadline.raw() {
syscall::yield_now();
}
}