8000 Seperate API and internal ProcessCreateInfos by andrew-pa · Pull Request #53 · andrew-pa/cavern · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Seperate API and internal ProcessCreateInfos #53

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions kernel/src/process/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
//! Mechanisms for user-space processes/threads.
use alloc::sync::Arc;
use kernel_api::{ExitMessage, ExitReason, ProcessCreateInfo};
use kernel_api::{ExitMessage, ExitReason};
use kernel_core::{
collections::HandleMap,
platform::cpu::CoreInfo,
process::{
system_calls::SystemCalls, Id, ManagerError, OutOfHandlesSnafu, Process, ProcessManager,
Properties, MAX_PROCESS_ID,
system_calls::SystemCalls, Id, ManagerError, OutOfHandlesSnafu, Process, ProcessCreateInfo,
ProcessManager, Properties, MAX_PROCESS_ID,
},
};
use log::{debug, info, warn};
Expand Down Expand Up @@ -52,7 +52,7 @@ impl ProcessManager for SystemProcessManager {
.or_else(|| parent.as_ref().and_then(|p| p.props.registry_queue)),
privilege: info.privilege_level,
},
unsafe { core::slice::from_raw_parts(info.sections, info.num_sections) },
info.sections,
info.inbox_size,
)?);
self.processes.insert_with_handle(id, proc.clone());
Expand Down
21 changes: 11 additions & 10 deletions kernel_core/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@

use alloc::vec::Vec;
use bytemuck::{Pod, Zeroable};
use kernel_api::{ImageSection, ImageSectionKind, PrivilegeLevel, ProcessCreateInfo};
use kernel_api::{ImageSectionKind, PrivilegeLevel};
use log::{debug, trace};
use snafu::{ResultExt, Snafu};
use tar_no_std::TarArchiveRef;

use crate::{
memory::{page_table::MemoryProperties, PageSize, PhysicalAddress, PhysicalPointer},
process::{queue::QueueManager, thread::ThreadManager, ManagerError, ProcessManager},
process::{
queue::QueueManager, thread::ThreadManager, ImageSection, ManagerError, ProcessCreateInfo,
ProcessManager,
},
};

/// Errors that can occur while spawning the `init` process.
Expand Down Expand Up @@ -90,23 +93,20 @@ pub fn spawn_init_process(
0b101 | 0b001 => ImageSectionKind::Executable,
x => panic!("unexpected flags for program header: {x}"),
},
base_address,
base_address: base_address.into(),
data_offset,
total_size: data_offset + segment.p_memsz as usize,
data: data.as_ptr(),
data_size: data.len(),
data,
})
})
.collect::<Result<Vec<_>, _>>()?;

let info = ProcessCreateInfo {
entry_point: bin.ehdr.e_entry as usize,
num_sections: sections.len(),
sections: sections.as_ptr(),
sections: &sections,
supervisor: None,
registry: None,
privilege_level: PrivilegeLevel::Driver,
notify_on_exit: false,
notify_on_exit: None,
inbox_size: 256,
};
debug!("init image = {info:?}");
Expand Down Expand Up @@ -152,10 +152,11 @@ pub fn spawn_init_process(
.context(ProcessSnafu)?;

// spawn the main init thread
let entry_point = (bin.ehdr.e_entry as usize).into();
thread_man
.spawn_thread(
init_process.clone(),
info.entry_point.into(),
entry_point,
8 * 1024 * 1024 / page_size,
init_queue.id.get() as usize,
)
Expand Down
93 changes: 66 additions & 27 deletions kernel_core/src/process/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
//! Processes (and threads).

use core::fmt::Debug;

use alloc::{string::String, sync::Arc, vec::Vec};

use kernel_api::{
flags::SharedBufferFlags, ExitReason, ImageSection, ImageSectionKind, MessageHeader,
PrivilegeLevel, ProcessCreateInfo, SharedBufferInfo, MESSAGE_BLOCK_SIZE,
flags::SharedBufferFlags, ExitReason, ImageSectionKind, MessageHeader, PrivilegeLevel,
SharedBufferInfo, MESSAGE_BLOCK_SIZE,
};
use log::trace;
use queue::{PendingMessage, QueueManager};
Expand Down Expand Up @@ -39,6 +41,52 @@ pub type SharedBufferId = crate::collections::Handle;
/// The largest possible shared buffer ID in the system.
pub const MAX_SHARED_BUFFER_ID: Id = Id::new(0xffff).unwrap();

/// A section of memory in a process image.
#[derive(Clone)]
pub struct ImageSection<'a> {
/// The base address in the process' address space. This must be page aligned.
pub base_address: VirtualAddress,
/// Offset from the base address where the `data` will be copied to. Any bytes between the
/// start and the offset will be zeroed.
pub data_offset: usize,
/// The total size of the section in bytes (including the `data_offset` bytes).
/// Any bytes past the size of `data` will be zeroed.
pub total_size: usize,
/// The data that will be copied into the section.
pub data: &'a [u8],
/// The type of section this is.
pub kind: ImageSectionKind,
}

impl Debug for ImageSection<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("ImageSection")
.field("base_address", &self.base_address)
.field("data_offset", &self.data_offset)
.field("total_size", &self.total_size)
.field("data.len()", &self.data.len())
.field("kind", &self.kind)
.finish()
}
}

/// Parameters for creating a new process.
#[derive(Debug, Clone)]
pub struct ProcessCreateInfo<'a> {
/// The process image sections that will be loaded into the new process.
pub sections: &'a [ImageSection<'a>],
/// The new process' supervisor queue, or None to inherit.
pub supervisor: Option<QueueId>,
/// The new process' registry queue, or None to inherit.
pub registry: Option<QueueId>,
/// The new process' privilege level (must be less than or equal to the current privilege level).
pub privilege_level: PrivilegeLevel,
/// An optional queue to notify with an exit message when the spawned process exits (same as [`exit_notification_subscription`]).
pub notify_on_exit: Option<Arc<MessageQueue>>,
/// The size of this process' message inbox, in message blocks.
pub inbox_size: usize,
}

/// Convert an image section kind into the necessary memory properties to map the pages of that section.
#[must_use]
pub fn image_section_kind_as_properties(this: &ImageSectionKind) -> MemoryProperties {
Expand Down Expand Up @@ -79,15 +127,15 @@ unsafe fn copy_image_section_data_to_process_memory(
core::ptr::write_bytes(dest_ptr, 0, section.data_offset);
}
core::ptr::copy_nonoverlapping(
section.data,
section.data.as_ptr(),
dest_ptr.byte_add(section.data_offset),
section.data_size,
section.data.len(),
);
if section.data_size + section.data_offset < section.total_size {
if section.data.len() + section.data_offset < section.total_size {
core::ptr::write_bytes(
dest_ptr.byte_add(section.data_offset + section.data_size),
dest_ptr.byte_add(section.data_offset + section.data.len()),
0,
section.total_size - (section.data_size + section.data_offset),
section.total_size - (section.data.len() + section.data_offset),
);
}
}
Expand Down Expand Up @@ -279,7 +327,7 @@ impl Process {
trace!("mapping setion {section:x?} to {memory:?}, # pages = {size_in_pages}, properties = {props:?}");
page_tables
.map(
section.base_address.into(),
section.base_address,
memory,
size_in_pages,
MapBlockSize::Page,
Expand All @@ -289,7 +337,7 @@ impl Process {
// trace!("process page tables after map: {page_tables:?}");
// reserve the range with the allocator as well
virt_alloc
.reserve_range(section.base_address.into(), size_in_pages)
.reserve_range(section.base_address, size_in_pages)
.context(MemorySnafu {
cause: "reserve image section in process virtual address space allocator",
})?;
Expand Down Expand Up @@ -650,10 +698,11 @@ pub trait ProcessManager {
/// # Errors
/// Returns an error if the process could not be spawned due to resource requirements or
/// invalid inputs.
fn spawn_process(
#[allow(clippy::elidable_lifetime_names)]
fn spawn_process<'a>(
&self,
parent: Option<Arc<Process>>,
info: &ProcessCreateInfo,
info: &ProcessCreateInfo<'a>,
) -> Result<Arc<Process>, ManagerError>;

/// Kill a process.
Expand Down Expand Up @@ -693,7 +742,7 @@ pub fn kill_thread_entirely(
#[cfg(test)]
pub mod tests {
use core::ptr;
use kernel_api::{ImageSection, ImageSectionKind, MessageHeader, ProcessId};
use kernel_api::{ImageSectionKind, MessageHeader, ProcessId};
use std::{
sync::{Arc, LazyLock},
vec::Vec,
Expand All @@ -703,7 +752,7 @@ pub mod tests {

use crate::{
memory::{tests::MockPageAllocator, PageAllocator as _, PageSize, VirtualAddress},
process::{MessageQueue, QueueId},
process::{ImageSection, MessageQueue, QueueId},
};

use super::{
Expand Down Expand Up @@ -816,15 +865,10 @@ pub mod tests {

// Construct an ImageSection for testing.
let section = ImageSection {
base_address: 0, // Not used in the copy function.
base_address: VirtualAddress::null(), // Not used in the copy function.
data_offset,
total_size,
data_size,
data: if data_size > 0 {
test_data.as_ptr()
} else {
ptr::null()
},
data: &test_data,
kind: ImageSectionKind::ReadOnly,
};

Expand Down Expand Up @@ -881,15 +925,10 @@ pub mod tests {
}

let section = ImageSection {
base_address: 0,
base_address: VirtualAddress::null(),
data_offset,
total_size,
data_size,
data: if data_size > 0 {
test_data.as_ptr()
} else {
ptr::null()
},
data: &test_data,
kind: ImageSectionKind::ReadOnly,
};

Expand Down
13 changes: 12 additions & 1 deletion kernel_core/src/process/queue.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! User space message queues.

use core::sync::atomic::AtomicBool;
use core::{fmt::Debug, sync::atomic::AtomicBool};

use alloc::sync::{Arc, Weak};
use crossbeam::queue::SegQueue;
Expand Down Expand Up @@ -80,6 +80,17 @@ impl MessageQueue {
}
}

impl Debug for MessageQueue {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"<Queue #{} (owned by process #{})>",
self.id,
self.owner.upgrade().map(|p| p.id.get()).unwrap_or_default()
)
}
}

/// An interface for managing message queues.
#[cfg_attr(test, mockall::automock)]
pub trait QueueManager {
Expand Down
50 changes: 41 additions & 9 deletions kernel_core/src/process/system_calls/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! System calls from user space.
#![allow(clippy::needless_pass_by_value)]

use alloc::{string::String, sync::Arc};
use alloc::{string::String, sync::Arc, vec::Vec};
use bytemuck::Contiguous;
use kernel_api::{
flags::{ExitNotificationSubscriptionFlags, FreeMessageFlags, ReceiveFlags},
Expand Down Expand Up @@ -384,12 +384,11 @@ impl<'pa, 'm, PA: PageAllocator, PM: ProcessManager, TM: ThreadManager, QM: Queu
registers: &Registers,
user_space_memory: ActiveUserSpaceTablesChecker<'_, T>,
) -> Result<(), Error> {
let info =
user_space_memory
.check_ref(registers.x[0].into())
.context(InvalidAddressSnafu {
cause: "process info",
})?;
let uinfo: &kernel_api::ProcessCreateInfo = user_space_memory
.check_ref(registers.x[0].into())
.context(InvalidAddressSnafu {
cause: "process info",
})?;

let out_process_id = user_space_memory
.check_mut_ref(registers.x[1].into())
Expand All @@ -409,10 +408,43 @@ impl<'pa, 'm, PA: PageAllocator, PM: ProcessManager, TM: ThreadManager, QM: Queu
None
};

let user_sections = user_space_memory
.check_slice(uinfo.sections.into(), uinfo.num_sections)
.context(InvalidAddressSnafu {
cause: "process image sections slice",
})?;

// check each section's data slice
let sections = user_sections
.iter()
.map(|s| {
Ok(crate::process::ImageSection {
base_address: s.base_address.into(),
data_offset: s.data_offset,
total_size: s.total_size,
data: user_space_memory
.check_slice(s.data.into(), s.data_size)
.context(InvalidAddressSnafu {
cause: "process image section data slice",
})?,
kind: s.kind,
})
})
.collect::<Result<Vec<_>, _>>()?;

let info = crate::process::ProcessCreateInfo {
sections: &sections,
supervisor: uinfo.supervisor,
registry: uinfo.registry,
privilege_level: uinfo.privilege_level,
notify_on_exit: None,
inbox_size: uinfo.inbox_size,
};

debug!("spawning process {info:?}, parent #{}", parent.id);
let proc = self
.process_manager
.spawn_process(Some(parent), info)
.spawn_process(Some(parent), &info)
.context(ManagerSnafu)?;

// create the initial queue
Expand All @@ -425,7 +457,7 @@ impl<'pa, 'm, PA: PageAllocator, PM: ProcessManager, TM: ThreadManager, QM: Queu
self.thread_manager
.spawn_thread(
proc.clone(),
info.entry_point.into(),
uinfo.entry_point.into(),
8 * 1024 * 1024 / self.page_allocator.page_size(),
qu.id.get() as usize,
)
Expand Down
0