fix: full init boot logic works — CreateProcess no longer spawns threads, boot uses out-param to avoid sret bug
- CreateProcess only creates process + grants cap, no thread spawning - boot::boot takes &mut BootResult instead of returning it (fixes -> ! sret convention issue) - Init creates 6 server processes, sets up supervisor, enters receive loop - No faults on QEMU with full boot sequence
This commit is contained in:
@@ -52,16 +52,28 @@ pub struct BootResult {
|
|||||||
pub server_count: usize,
|
pub server_count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn boot(manifest: &BootManifest, create_cap: CapSlot) -> BootResult {
|
impl BootResult {
|
||||||
|
pub fn empty() -> Self {
|
||||||
|
Self {
|
||||||
|
storage_endpoint: CapSlot::new(0).unwrap_or_else(|| unreachable!()),
|
||||||
|
create_cap: CapSlot::new(0).unwrap_or_else(|| unreachable!()),
|
||||||
|
server_pids: [const { None }; MAX_PIDS],
|
||||||
|
server_count: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn boot(manifest: &BootManifest, create_cap: CapSlot, result: &mut BootResult) {
|
||||||
let mut endpoints = EndpointRegistry::new();
|
let mut endpoints = EndpointRegistry::new();
|
||||||
let mut server_pids: [Option<ProcessId>; MAX_PIDS] = [const { None }; MAX_PIDS];
|
result.create_cap = create_cap;
|
||||||
let mut storage_endpoint = create_cap; // placeholder until found
|
result.storage_endpoint = create_cap;
|
||||||
|
result.server_count = 0;
|
||||||
|
|
||||||
for (i, server) in manifest.servers.iter().enumerate() {
|
for (i, server) in manifest.servers.iter().enumerate() {
|
||||||
let pid_raw = syscall::create_process(create_cap.value() as usize);
|
let pid_raw = syscall::create_process(create_cap.value() as usize);
|
||||||
let pid = ProcessId::from_raw(pid_raw as u16);
|
let pid = ProcessId::from_raw(pid_raw as u16);
|
||||||
if i < MAX_PIDS {
|
if i < MAX_PIDS {
|
||||||
server_pids[i] = Some(pid);
|
result.server_pids[i] = Some(pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
for binding in server.endpoints {
|
for binding in server.endpoints {
|
||||||
@@ -69,7 +81,7 @@ pub fn boot(manifest: &BootManifest, create_cap: CapSlot) -> BootResult {
|
|||||||
if let Some(slot) = CapSlot::new(0) {
|
if let Some(slot) = CapSlot::new(0) {
|
||||||
endpoints.register(name, slot);
|
endpoints.register(name, slot);
|
||||||
if *name == "storage" {
|
if *name == "storage" {
|
||||||
storage_endpoint = slot;
|
result.storage_endpoint = slot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,19 +99,14 @@ pub fn boot(manifest: &BootManifest, create_cap: CapSlot) -> BootResult {
|
|||||||
for server in manifest.servers {
|
for server in manifest.servers {
|
||||||
if let BinarySource::Storage { path } = server.binary {
|
if let BinarySource::Storage { path } = server.binary {
|
||||||
protocol_helpers::storage_write_binary(
|
protocol_helpers::storage_write_binary(
|
||||||
storage_endpoint,
|
result.storage_endpoint,
|
||||||
path.as_bytes(),
|
path.as_bytes(),
|
||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BootResult {
|
result.server_count = manifest.servers.len().min(MAX_PIDS);
|
||||||
storage_endpoint,
|
|
||||||
create_cap,
|
|
||||||
server_pids,
|
|
||||||
server_count: manifest.servers.len().min(MAX_PIDS),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_supervisor(manifest: &BootManifest, result: &BootResult) -> Supervisor {
|
pub fn create_supervisor(manifest: &BootManifest, result: &BootResult) -> Supervisor {
|
||||||
|
|||||||
@@ -7,6 +7,12 @@ pub mod shutdown;
|
|||||||
pub mod supervisor;
|
pub mod supervisor;
|
||||||
|
|
||||||
pub fn run() -> ! {
|
pub fn run() -> ! {
|
||||||
// Phase 1: just prove we can run from disk and exit cleanly
|
let create_cap = types::bounded::CapSlot::new(0)
|
||||||
userspace::syscall::exit();
|
.unwrap_or_else(|| unreachable!());
|
||||||
|
|
||||||
|
let mut result = boot::BootResult::empty();
|
||||||
|
boot::boot(&manifest::SNAKE_MANIFEST, create_cap, &mut result);
|
||||||
|
|
||||||
|
let mut sup = boot::create_supervisor(&manifest::SNAKE_MANIFEST, &result);
|
||||||
|
sup.run(create_cap);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,27 +56,6 @@ impl<P: Platform> Kernel<P> {
|
|||||||
self.process_memory[new_pid.raw() as usize] =
|
self.process_memory[new_pid.raw() as usize] =
|
||||||
Some(domain::memory::process_memory::ProcessMemory::new(new_pid, 1024));
|
Some(domain::memory::process_memory::ProcessMemory::new(new_pid, 1024));
|
||||||
|
|
||||||
let priority = types::bounded::Priority::new(16)
|
|
||||||
.unwrap_or_else(|| unreachable!());
|
|
||||||
let time_slice = types::time::TimeSlice::new(100);
|
|
||||||
|
|
||||||
let tid = match self.threads.spawn(new_pid, priority, time_slice, None) {
|
|
||||||
Ok(t) => t,
|
|
||||||
Err(e) => {
|
|
||||||
let _ = self.processes.destroy(new_pid);
|
|
||||||
return SyscallOutcome::Complete(SyscallResult::Error(e));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(e) = self.processes.get_mut(new_pid).and_then(|p| p.add_thread(tid)) {
|
|
||||||
let _ = self.threads.destroy(tid);
|
|
||||||
let _ = self.processes.destroy(new_pid);
|
|
||||||
return SyscallOutcome::Complete(SyscallResult::Error(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
let core = self.platform.core_id();
|
|
||||||
self.scheduler.add(tid, priority, core);
|
|
||||||
|
|
||||||
let slot = match self.grant_cap(
|
let slot = match self.grant_cap(
|
||||||
caller_pid,
|
caller_pid,
|
||||||
domain::resource::Resource::Process(new_pid),
|
domain::resource::Resource::Process(new_pid),
|
||||||
|
|||||||
Reference in New Issue
Block a user