Add support for process command-line arguments
This commit is contained in:
parent
49e71b1555
commit
fcf672a969
@ -1,15 +1,10 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
bootinfo::BOOTINFO,
|
bootinfo::BOOTINFO, print, println, serial::SECOND_PORT, tasking::SleepReason, virtual_memory::{ASpaceMutex, AddressSpace, ACTIVE_SPACE, KERNEL_SPACE}, TASKING
|
||||||
print, println,
|
|
||||||
serial::SECOND_PORT,
|
|
||||||
tasking::SleepReason,
|
|
||||||
virtual_memory::{ASpaceMutex, AddressSpace, ACTIVE_SPACE, KERNEL_SPACE},
|
|
||||||
TASKING,
|
|
||||||
};
|
};
|
||||||
use alloc::{boxed::Box, vec::Vec};
|
use alloc::{boxed::Box, vec::Vec};
|
||||||
use az::WrappingCast;
|
use az::WrappingCast;
|
||||||
use cast::{u64, usize};
|
use cast::{u64, usize};
|
||||||
use core::{arch::asm, ptr, slice, str};
|
use core::{arch::asm, ffi::CStr, ptr, slice, str};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use pic8259::ChainedPics;
|
use pic8259::ChainedPics;
|
||||||
use saturating_cast::SaturatingCast;
|
use saturating_cast::SaturatingCast;
|
||||||
@ -364,13 +359,21 @@ extern "C" fn syscall_handler() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
8 => {
|
8 => {
|
||||||
|
let args = unsafe {
|
||||||
|
let argc = usize(regs.rsi);
|
||||||
|
let argv: &[&[u8]] = slice::from_raw_parts(ptr::with_exposed_provenance(usize(regs.rdi)), argc);
|
||||||
|
argv.iter().map(|arg| CStr::from_bytes_with_nul_unchecked(arg)).collect::<Vec<_>>()
|
||||||
|
};
|
||||||
#[warn(
|
#[warn(
|
||||||
clippy::arithmetic_side_effects,
|
clippy::arithmetic_side_effects,
|
||||||
reason = "FIXME: The current address space should be usize::MAX as that is an invalid index, instead of 0."
|
reason = "FIXME: The current address space should be usize::MAX as that is an invalid index, instead of 0."
|
||||||
)]
|
)]
|
||||||
let space = TASKING.lock().address_spaces_mut().remove(usize(regs.rdx - 1));
|
let space = TASKING.lock().address_spaces_mut().remove(usize(regs.rdx - 1));
|
||||||
let res =
|
let res = TASKING.lock().new_process(
|
||||||
TASKING.lock().new_process(ptr::with_exposed_provenance(usize(regs.rcx)), space);
|
ptr::with_exposed_provenance(usize(regs.rcx)),
|
||||||
|
space,
|
||||||
|
args.as_slice(),
|
||||||
|
);
|
||||||
if let Ok(pid) = res {
|
if let Ok(pid) = res {
|
||||||
retval = 0;
|
retval = 0;
|
||||||
retval2 = u64(pid);
|
retval2 = u64(pid);
|
||||||
@ -557,6 +560,12 @@ extern "C" fn syscall_handler() {
|
|||||||
tasking.sleep(SleepReason::WaitingForIPC);
|
tasking.sleep(SleepReason::WaitingForIPC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
19 => {
|
||||||
|
let tasking = TASKING.lock();
|
||||||
|
let args = tasking.arguments();
|
||||||
|
retval = u64(args.0.expose_provenance());
|
||||||
|
retval2 = u64(args.1);
|
||||||
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
};
|
};
|
||||||
unsafe { SYSCALL_REGS = regs };
|
unsafe { SYSCALL_REGS = regs };
|
||||||
|
11
src/main.rs
11
src/main.rs
@ -87,6 +87,7 @@ mod virtual_memory;
|
|||||||
|
|
||||||
use core::{ptr, slice};
|
use core::{ptr, slice};
|
||||||
|
|
||||||
|
use alloc::ffi::CString;
|
||||||
use bootinfo::BOOTINFO;
|
use bootinfo::BOOTINFO;
|
||||||
use cast::usize;
|
use cast::usize;
|
||||||
use elf::{
|
use elf::{
|
||||||
@ -280,11 +281,15 @@ pub fn main() {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
#[expect(
|
#[expect(
|
||||||
clippy::expect_used,
|
clippy::unwrap_used,
|
||||||
reason = "Boot cannot happen if the init process cannot be created"
|
reason = "Argument does not contain a null byte, thus this cannot panic"
|
||||||
)]
|
)]
|
||||||
TASKING
|
TASKING
|
||||||
.lock()
|
.lock()
|
||||||
.new_process(ptr::with_exposed_provenance(usize(init.ehdr.e_entry)), init_addr_space)
|
.new_process(
|
||||||
|
ptr::with_exposed_provenance(usize(init.ehdr.e_entry)),
|
||||||
|
init_addr_space,
|
||||||
|
&[&CString::new(b"init").unwrap()],
|
||||||
|
)
|
||||||
.expect("Failed to create init process");
|
.expect("Failed to create init process");
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
//#![allow(clippy::indexing_slicing, reason = "temp")]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
gdt, println, qemu_exit,
|
gdt, println, qemu_exit, virtual_memory::{ASpaceMutex, AddressSpace, PagingError, KERNEL_SPACE}
|
||||||
virtual_memory::{ASpaceMutex, AddressSpace, PagingError, KERNEL_SPACE},
|
|
||||||
};
|
};
|
||||||
use alloc::{boxed::Box, collections::VecDeque, vec::Vec};
|
use alloc::{borrow::ToOwned, boxed::Box, collections::VecDeque, ffi::CString, vec::Vec};
|
||||||
use core::{arch::asm, ptr::addr_of};
|
use core::{alloc::Layout, arch::asm, ptr::addr_of, ffi::CStr};
|
||||||
use crossbeam_queue::SegQueue;
|
use crossbeam_queue::SegQueue;
|
||||||
use slab::Slab;
|
use slab::Slab;
|
||||||
use spin::{Lazy, Mutex};
|
use spin::{Lazy, Mutex};
|
||||||
@ -98,6 +95,7 @@ struct Process {
|
|||||||
data_buffers: Slab<*mut [u8]>,
|
data_buffers: Slab<*mut [u8]>,
|
||||||
message_queue: SegQueue<(usize, usize)>,
|
message_queue: SegQueue<(usize, usize)>,
|
||||||
sleeping: Option<SleepReason>,
|
sleeping: Option<SleepReason>,
|
||||||
|
arguments: (*const *const u8, usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for Process {}
|
unsafe impl Send for Process {}
|
||||||
@ -127,6 +125,7 @@ impl Tasking {
|
|||||||
&mut self,
|
&mut self,
|
||||||
entry_point: *const extern "C" fn() -> !,
|
entry_point: *const extern "C" fn() -> !,
|
||||||
mut address_space: AddressSpace,
|
mut address_space: AddressSpace,
|
||||||
|
arguments: &[&CStr],
|
||||||
) -> Result<usize, PagingError> {
|
) -> Result<usize, PagingError> {
|
||||||
let mut kernel_stack = Vec::new_in(&*KERNEL_SPACE);
|
let mut kernel_stack = Vec::new_in(&*KERNEL_SPACE);
|
||||||
kernel_stack.resize(0x1_0000 - 0x4, 0);
|
kernel_stack.resize(0x1_0000 - 0x4, 0);
|
||||||
@ -147,6 +146,33 @@ impl Tasking {
|
|||||||
16,
|
16,
|
||||||
PageTableFlags::USER_ACCESSIBLE,
|
PageTableFlags::USER_ACCESSIBLE,
|
||||||
)?;
|
)?;
|
||||||
|
let arguments = arguments.iter().map(|arg| (*arg).to_owned()).collect::<Vec<CString>>();
|
||||||
|
#[expect(clippy::unwrap_used, reason = "This fails if the byte size of the array exceeds isize::MAX, which with 48-bit virtual addresses cannot happen")]
|
||||||
|
let mut args_layout = Layout::array::<*const u8>(arguments.len()).unwrap();
|
||||||
|
let mut arg_offsets = Vec::new();
|
||||||
|
for argument in &arguments {
|
||||||
|
#[expect(clippy::unwrap_used, reason = "This fails if the total size of the layout exceeds isize::MAX, which with 48-bit virtual addresses cannot happen")]
|
||||||
|
let (new_layout, offset) =
|
||||||
|
args_layout.extend(Layout::for_value(argument.to_bytes_with_nul())).unwrap();
|
||||||
|
args_layout = new_layout;
|
||||||
|
arg_offsets.push(offset);
|
||||||
|
}
|
||||||
|
args_layout = {
|
||||||
|
#[expect(clippy::unwrap_used, reason = "This fails if the aligned size of the layout exceeds isize::MAX, which with 48-bit virtual addresses cannot happen")]
|
||||||
|
args_layout.align_to(4096).unwrap().pad_to_align()
|
||||||
|
};
|
||||||
|
let user_arg_mem = address_space
|
||||||
|
.map_free(args_layout.size() / 4096, PageTableFlags::USER_ACCESSIBLE)?;
|
||||||
|
address_space.run(|| unsafe {
|
||||||
|
let mut ptr_ptr: *mut *const u8 = user_arg_mem.cast();
|
||||||
|
for (&offset, argument) in arg_offsets.iter().zip(arguments.iter()) {
|
||||||
|
let arg_ptr = user_arg_mem.add(offset);
|
||||||
|
#[expect(clippy::arithmetic_side_effects, reason = "This can never overflow as count_bytes is always one less than the bytes used for the string, which can be at most 2^64-1.")]
|
||||||
|
arg_ptr.copy_from(argument.as_ptr().cast(), argument.count_bytes() + 1);
|
||||||
|
ptr_ptr.write(arg_ptr);
|
||||||
|
ptr_ptr = ptr_ptr.add(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
let pid = self.processes.insert(Process {
|
let pid = self.processes.insert(Process {
|
||||||
#[expect(
|
#[expect(
|
||||||
clippy::indexing_slicing,
|
clippy::indexing_slicing,
|
||||||
@ -164,6 +190,7 @@ impl Tasking {
|
|||||||
data_buffers: Slab::new(),
|
data_buffers: Slab::new(),
|
||||||
message_queue: SegQueue::new(),
|
message_queue: SegQueue::new(),
|
||||||
sleeping: None,
|
sleeping: None,
|
||||||
|
arguments: (user_arg_mem.cast(), arguments.len()),
|
||||||
});
|
});
|
||||||
self.ready_to_run.push_back(pid);
|
self.ready_to_run.push_back(pid);
|
||||||
Ok(pid)
|
Ok(pid)
|
||||||
@ -291,4 +318,10 @@ impl Tasking {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn arguments(&self) -> (*const *const u8, usize) {
|
||||||
|
#[warn(clippy::unwrap_used, reason = "FIXME")]
|
||||||
|
#[warn(clippy::indexing_slicing, reason = "FIXME(?)")]
|
||||||
|
self.processes[self.current_process.unwrap()].arguments
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user