Change IPC to have kernel keep track of source

This commit is contained in:
pjht 2024-11-25 10:32:08 -06:00
parent ef81ca1a6c
commit 87df5e76f2
Signed by: pjht
GPG Key ID: CA239FC6934E6F3A
2 changed files with 40 additions and 25 deletions

View File

@ -1,7 +1,7 @@
use crate::{
bootinfo::BOOTINFO,
print, println,
tasking::{InvalidPid, SleepReason},
tasking::{InvalidPid, IpcMessage, SleepReason},
virtual_memory::{ASpaceMutex, AddressSpace, PagingError, ACTIVE_SPACE, KERNEL_SPACE},
TASKING,
};
@ -163,7 +163,13 @@ pub fn send_ipc_to(
pid: usize,
buffer: Box<[u8], &'static ASpaceMutex>,
len: usize,
from_kernel: bool,
) -> Result<(), SendIpcError> {
let from = if from_kernel {
usize::MAX
} else {
TASKING.current_pid().unwrap()
};
#[cfg(feature = "log-rpc")]
{
#[expect(
@ -185,13 +191,14 @@ pub fn send_ipc_to(
clippy::arithmetic_side_effects,
reason = "Can't overflow, as padded_len is no more than 4096 and 4096+24 < u32::MAX"
)]
let total_len = padded_len + 8 + (4 * 4);
let total_len = padded_len + 16 + (4 * 4);
SECOND_PORT.write_u32s(&[
0x3, // SPB type
total_len, // Total block length
len.saturating_cast::<u32>().saturating_add(8), // Packet length
len.saturating_cast::<u32>().saturating_add(16), // Packet length
]);
SECOND_PORT.write_bytes(&pid.to_ne_bytes());
SECOND_PORT.write_bytes(&from.to_ne_bytes());
#[expect(
clippy::indexing_slicing,
reason = "The truncated length is always <= the buffer's length"
@ -225,7 +232,12 @@ pub fn send_ipc_to(
buffer
};
let new_buffer_key = process.data_buffers().lock().insert(dest_buffer);
process.message_queue().lock().push((new_buffer_key, len));
let message = IpcMessage {
buffer_idx: new_buffer_key,
len,
from,
};
process.message_queue().lock().push(message);
Ok::<_, PagingError>(())
})??;
#[expect(
@ -251,15 +263,13 @@ fn irq_handler(_stack_frame: InterruptStackFrame, index: u8, _error_code: Option
handler(irq_num, eoi_guard);
} else if let Some(handler_task) = IRQ_TASKS.read()[usize(irq_num)] {
let pid = handler_task;
let len: usize = 11;
let rounded_size = len.next_multiple_of(4096);
let mut buffer = Vec::with_capacity_in(rounded_size, &*ACTIVE_SPACE);
buffer.resize(rounded_size, 0);
let mut buffer = buffer.into_boxed_slice();
buffer[0..8].copy_from_slice(&u64::MAX.to_le_bytes());
buffer[8..10].copy_from_slice(&2u16.to_le_bytes());
buffer[10] = irq_num;
match send_ipc_to(pid, buffer, len) {
let mut buffer = Vec::new_in(&*ACTIVE_SPACE);
buffer.extend_from_slice(&2u16.to_le_bytes());
buffer.push(irq_num);
let len = buffer.len();
buffer.resize(len.next_multiple_of(4096), 0);
let buffer = buffer.into_boxed_slice();
match send_ipc_to(pid, buffer, len, true) {
Ok(()) => (),
Err(SendIpcError::InvalidPid) => {
IRQ_TASKS.write()[usize(irq_num)] = None;
@ -394,6 +404,7 @@ extern "C" fn syscall_handler() {
let mut retval = 0;
let mut retval2 = regs.rcx;
let mut retval3 = regs.rdx;
let mut retval4 = regs.rsi;
match regs.rax {
0 => {
let rval = if let Some(chr) = char::from_u32(regs.rcx.wrapping_cast()) {
@ -535,7 +546,7 @@ extern "C" fn syscall_handler() {
if let Some(buffer) = get_buffer(regs.rdx) {
let len = usize(regs.rsi);
assert!(len <= buffer.len());
match send_ipc_to(pid, buffer, len) {
match send_ipc_to(pid, buffer, len, false) {
Ok(()) => retval = 0,
Err(e) => {
println!("ipc_send: Error {e:?}");
@ -556,11 +567,12 @@ extern "C" fn syscall_handler() {
reason = "The message queue only contains valid buffer IDs"
)]
let buffer_addr = u64(TASKING
.current_process(|process| *process.data_buffers().lock().get(msg.0).unwrap())
.current_process(|process| *process.data_buffers().lock().get(msg.buffer_idx).unwrap())
.expose_provenance());
retval2 = u64(msg.1);
retval2 = u64(msg.len);
retval = buffer_addr;
retval3 = u64(msg.0);
retval3 = u64(msg.buffer_idx);
retval4 = u64(msg.from);
} else {
retval = 0;
}
@ -759,7 +771,6 @@ extern "C" fn syscall_handler() {
unsafe {
asm!(
"mov rbx, [rip+SYSCALL_REGS+8]",
"mov rsi, [rip+SYSCALL_REGS+32]",
"mov rdi, [rip+SYSCALL_REGS+40]",
"mov rsp, [rip+SYSCALL_REGS+48]",
"mov rbp, [rip+SYSCALL_REGS+56]",
@ -772,7 +783,7 @@ extern "C" fn syscall_handler() {
"mov r14, [rip+SYSCALL_REGS+112]",
"mov r15, [rip+SYSCALL_REGS+120]",
"iretq",
in("rax") retval, in("rcx") retval2, in("rdx") retval3, options(noreturn)
in("rax") retval, in("rcx") retval2, in("rdx") retval3, in("rsi") retval4, options(noreturn)
)
}
}

View File

@ -92,10 +92,16 @@ pub struct Process {
kernel_esp_top: VirtAddr,
address_spaces: Mutex<Slab<AddressSpace>>,
data_buffers: Mutex<Slab<*mut [u8]>>,
message_queue: Mutex<SegQueue<(usize, usize)>>,
message_queue: Mutex<SegQueue<IpcMessage>>,
sleeping: RwLock<Option<SleepReason>>,
}
pub struct IpcMessage {
pub buffer_idx: usize,
pub len: usize,
pub from: usize,
}
impl Process {
pub fn address_spaces(&self) -> &Mutex<Slab<AddressSpace>> {
&self.address_spaces
@ -105,7 +111,7 @@ impl Process {
&self.data_buffers
}
pub fn message_queue(&self) -> &Mutex<SegQueue<(usize, usize)>> {
pub fn message_queue(&self) -> &Mutex<SegQueue<IpcMessage>> {
&self.message_queue
}
@ -184,7 +190,6 @@ impl Tasking {
if let Some(&proc_man_pid) = REGISTERD_PIDS.read().get(&3) {
let mut varint_buf = unsigned_varint::encode::u64_buffer();
let mut buffer = Vec::new_in(&*ACTIVE_SPACE);
buffer.extend_from_slice(&u64::MAX.to_le_bytes());
buffer.extend_from_slice(&0u16.to_le_bytes());
buffer.push(0);
buffer.extend_from_slice(&0u64.to_le_bytes());
@ -207,7 +212,7 @@ impl Tasking {
clippy::expect_used,
reason = "The tasking code in the kernel and proc_man CANNOT lose sync. Failure to communicate is fatal."
)]
send_ipc_to(usize(proc_man_pid), buffer, len)
send_ipc_to(usize(proc_man_pid), buffer, len, true)
.expect("Failed to send exit message to proc_man");
} else {
println!("[TASKING] No process manager when creating PID {pid}");
@ -289,7 +294,6 @@ impl Tasking {
if let Some(&proc_man_pid) = REGISTERD_PIDS.read().get(&3) {
let mut varint_buf = unsigned_varint::encode::u64_buffer();
let mut buffer = Vec::new_in(&*ACTIVE_SPACE);
buffer.extend_from_slice(&u64::MAX.to_le_bytes());
buffer.extend_from_slice(&0u16.to_le_bytes());
buffer.push(0);
buffer.extend_from_slice(&0u64.to_le_bytes());
@ -307,7 +311,7 @@ impl Tasking {
clippy::expect_used,
reason = "The tasking code in the kernel and proc_man CANNOT lose sync. Failure to communicate is fatal."
)]
send_ipc_to(usize(proc_man_pid), buffer, len)
send_ipc_to(usize(proc_man_pid), buffer, len, true)
.expect("Failed to send exit message to proc_man");
} else {
println!(