feat(kernel): console cap gates DebugPutchar, no uart fast path; spawn start arg in a0; delegate returns slot
This commit is contained in:
@@ -105,3 +105,18 @@ pub fn grant_all(
|
||||
|
||||
uart.write_str("k-os: capabilities granted\n");
|
||||
}
|
||||
|
||||
/// Until the log server owns the console, the servers loaded here print
|
||||
/// through a console cap of their own, its slot passed in `a0`.
|
||||
pub fn grant_console(uart: &Uart, servers: &[super::loader::LoadedProcess]) {
|
||||
let write =
|
||||
types::permission::PermissionSet::empty().with(types::permission::Permission::Write);
|
||||
for server in servers {
|
||||
let slot = kern()
|
||||
.grant_capability(server.pid, domain::resource::Resource::Console, write)
|
||||
.unwrap_or_else(|_| crate::halt(uart, "console grant failed"));
|
||||
if let Some(ctx) = kern().thread_context_mut(server.tid) {
|
||||
ctx.registers_mut()[10] = types::start_arg::encode(Some(slot), None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,10 @@ const USER_VA_BASE: usize = 0x10000;
|
||||
const USER_STACK_PAGES: usize = USER_VA_BASE / PAGE_SIZE - 1;
|
||||
const MAX_FILE_SIZE: usize = 64 * 1024;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct LoadedProcess {
|
||||
pub pid: ProcessId,
|
||||
pub tid: ThreadId,
|
||||
}
|
||||
|
||||
fn kern() -> &'static mut kernel::Kernel<crate::platform::RiscVPlatform> {
|
||||
@@ -35,7 +37,7 @@ fn elf_buffer() -> &'static mut [u8] {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_init(uart: &Uart, blk: &mut VirtioBlk) -> (LoadedProcess, ThreadId) {
|
||||
pub fn load_init(uart: &Uart, blk: &mut VirtioBlk) -> LoadedProcess {
|
||||
let (pid, tid) = kern()
|
||||
.boot(
|
||||
types::bounded::Priority::DEFAULT,
|
||||
@@ -47,7 +49,7 @@ pub fn load_init(uart: &Uart, blk: &mut VirtioBlk) -> (LoadedProcess, ThreadId)
|
||||
setup_thread(tid, entry);
|
||||
uart.write_str("k-os: init loaded\n");
|
||||
|
||||
(LoadedProcess { pid }, tid)
|
||||
LoadedProcess { pid, tid }
|
||||
}
|
||||
|
||||
pub fn load_server(
|
||||
@@ -68,7 +70,7 @@ pub fn load_server(
|
||||
uart.write_str(label);
|
||||
uart.write_str(" loaded\n");
|
||||
|
||||
LoadedProcess { pid }
|
||||
LoadedProcess { pid, tid }
|
||||
}
|
||||
|
||||
fn setup_thread(tid: ThreadId, entry: usize) {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
use crate::hw::uart::Uart;
|
||||
use types::address::VirtualAddress;
|
||||
use types::bootinfo::{BOOT_INFO_VA, BootDevice, BootInfo, MAGIC, MAX_BOOT_DEVICES, NO_SLOT};
|
||||
use types::bounded::CapSlot;
|
||||
use types::id::ProcessId;
|
||||
use types::mapping::PagePerms;
|
||||
|
||||
@@ -29,7 +28,7 @@ pub(crate) fn boot_info(
|
||||
board: &[kernel::BoardDevice],
|
||||
kinds: &[u64],
|
||||
placed: &[Option<kernel::BoardCaps>],
|
||||
system_control: CapSlot,
|
||||
boot_caps: kernel::BootCaps,
|
||||
) {
|
||||
let empty = BootDevice {
|
||||
kind: 0,
|
||||
@@ -42,7 +41,8 @@ pub(crate) fn boot_info(
|
||||
let mut info = BootInfo {
|
||||
magic: MAGIC,
|
||||
device_count: 0,
|
||||
system_control_slot: system_control.value() as u64,
|
||||
system_control_slot: boot_caps.system_control.value() as u64,
|
||||
console_slot: boot_caps.console.value() as u64,
|
||||
devices: [empty; MAX_BOOT_DEVICES],
|
||||
};
|
||||
for (((d, kind), caps), out) in board
|
||||
|
||||
@@ -39,7 +39,7 @@ extern "C" fn kmain(hart: usize) -> ! {
|
||||
let mut blk =
|
||||
boot::hardware::probe_block_device(&uart).unwrap_or_else(|| halt(&uart, "no block device"));
|
||||
|
||||
let (init, _) = boot::loader::load_init(&uart, &mut blk);
|
||||
let init = boot::loader::load_init(&uart, &mut blk);
|
||||
let storage = boot::loader::load_server(&uart, &mut blk, b"storage.elf", "storage");
|
||||
let display = boot::loader::load_server(&uart, &mut blk, b"display.elf", "display");
|
||||
let input = boot::loader::load_server(&uart, &mut blk, b"input.elf", "input");
|
||||
@@ -50,19 +50,14 @@ extern "C" fn kmain(hart: usize) -> ! {
|
||||
.unwrap_or_else(|_| halt(&uart, "board registration failed"));
|
||||
devices::display_quota(&uart, display.pid);
|
||||
boot::caps::grant_all(&uart, init.pid, storage.pid, display.pid, input.pid);
|
||||
// Last, so the servers' fixed slots stay where they expect them.
|
||||
boot::caps::grant_console(&uart, &[storage, display, input]);
|
||||
// After grant_all: init already relies on those slots.
|
||||
let mut placed = [None; board::BOARD_DEVICES];
|
||||
let system_control = kern_mut()
|
||||
let boot_caps = kern_mut()
|
||||
.grant_boot_authority(init.pid, &board, &mut placed)
|
||||
.unwrap_or_else(|_| halt(&uart, "boot authority failed"));
|
||||
devices::boot_info(
|
||||
&uart,
|
||||
init.pid,
|
||||
&board,
|
||||
&board::kinds(),
|
||||
&placed,
|
||||
system_control,
|
||||
);
|
||||
devices::boot_info(&uart, init.pid, &board, &board::kinds(), &placed, boot_caps);
|
||||
|
||||
start_other_harts(&uart, hart);
|
||||
uart.write_str("k-os: entering userspace\n");
|
||||
|
||||
@@ -3,7 +3,7 @@ use super::{TrapFrame, write_result};
|
||||
/// Syscalls answered without the kernel lock because they touch nothing it
|
||||
/// guards. A pending IPI or reschedule request forces the slow path.
|
||||
pub(super) fn fast_syscall(frame: &mut TrapFrame) -> bool {
|
||||
use types::syscall_abi::{SYS_DEBUG_PUTCHAR, SYS_GET_PROCESS_ID, SYS_GET_TIME, SYS_YIELD};
|
||||
use types::syscall_abi::{SYS_GET_PROCESS_ID, SYS_GET_TIME, SYS_YIELD};
|
||||
if crate::smp::has_pending_request() {
|
||||
return false;
|
||||
}
|
||||
@@ -13,10 +13,6 @@ pub(super) fn fast_syscall(frame: &mut TrapFrame) -> bool {
|
||||
Some(pid) => kernel::SyscallResult::Value(pid),
|
||||
None => return false,
|
||||
},
|
||||
SYS_DEBUG_PUTCHAR => {
|
||||
crate::hw::uart::Uart::new().put_char(frame.regs[10] as u8);
|
||||
kernel::SyscallResult::Ok
|
||||
}
|
||||
SYS_YIELD if crate::smp::yield_is_noop() => kernel::SyscallResult::Ok,
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user