From 86dbca7ef5e4c04dabd6abf056caf6fe08d88b7c Mon Sep 17 00:00:00 2001 From: Paul Pan Date: Wed, 4 Sep 2024 20:51:10 +0800 Subject: [PATCH] feat: kernel/objects/endpoint: wire up syscall --- kernel/src/objects/endpoint.rs | 48 ++++++++++++++++++--------- kernel/src/plat/irq.rs | 59 ++++++++++++++++++---------------- kernel/src/syscall.rs | 7 ++-- 3 files changed, 70 insertions(+), 44 deletions(-) diff --git a/kernel/src/objects/endpoint.rs b/kernel/src/objects/endpoint.rs index 16e507b..43844e5 100644 --- a/kernel/src/objects/endpoint.rs +++ b/kernel/src/objects/endpoint.rs @@ -1,10 +1,12 @@ -use crate::{ - objects::*, - plat::{irq::IRQ_NUM, trap::TrapContextOps}, +use crate::objects::*; +use crate::plat::{ + irq::{IRQ_MANAGER, IRQ_NUM}, + trap::TrapContextOps, }; use core::{cmp::min, fmt::Debug}; use tcb::{ThreadState, EP_QUEUE_LINK_ID}; use uapi::{cap::ObjectType, syscall::*}; +use utils::then::Then; use utils::{addr::*, array::*, linked_list::Link}; #[derive(Debug, Copy, Clone, PartialEq)] @@ -35,8 +37,8 @@ impl KernelObject for EndpointObject { * > | [63:0] | * * in our implementation, EndpointCap layout: - * > args[0]: badge - * > args[1]: none + * > args[0]: option + * > args[1]: badge * > ptr: base_ptr * > cap_type: cap_tag */ @@ -45,15 +47,16 @@ pub type EndpointCap<'a> = Cap<'a, EndpointObject>; impl<'a> EndpointCap<'a> { pub fn mint(ptr: PhysAddr, badge: usize) -> RawCap { - RawCap::new(badge, 0, ptr, ObjectType::Endpoint) + RawCap::new(0, badge, ptr, ObjectType::Endpoint) } - pub fn can_send(&self) -> bool { - self.cap().get().args[0] & 0x2 != 0 + pub fn irqs(&self) -> Option { + let irqs = self.cap().get().args[0]; + (irqs != 0).then_some(irqs) } - pub fn can_recv(&self) -> bool { - self.cap().get().args[0] & 0x1 != 0 + fn set_irq(&mut self, irqs: usize) { + self.cap().get().args[0] |= 1 << irqs; } pub fn badge(&self) -> usize { @@ -64,8 +67,8 @@ impl<'a> EndpointCap<'a> { self.as_object().signals } - pub fn set_signals(&mut self, signals: usize) { - self.as_object_mut().signals = signals; + fn set_signals(&mut self, signals: usize) { + self.as_object_mut().signals = signals & self.irqs().unwrap_or(0); } pub fn state(&self) -> EndpointState { @@ -84,6 +87,20 @@ impl<'a> EndpointCap<'a> { } } + pub fn do_set_irq(&mut self, tcb: &TcbObject) -> SysResult { + let irq = tcb.trapframe.get_reg(REG_ARG_0); + IRQ_MANAGER.lock().enable(irq, self.cte.clone()); + self.set_irq(irq); + Ok(()) + } + + pub fn do_ack_irq(&mut self, tcb: &TcbObject) -> SysResult { + let irq = tcb.trapframe.get_reg(REG_ARG_0); + (self.irqs().unwrap_or(0) & (1 << irq) != 0).else_err((), SysError::InvalidArgument)?; + IRQ_MANAGER.lock().complete(irq); + Ok(()) + } + pub fn do_send(&mut self, send: &mut TcbObject) -> SysResult { match self.state() { EndpointState::Recv => { @@ -148,8 +165,9 @@ impl<'a> EndpointCap<'a> { let state = self.state(); self.set_signals(signals); + let signals = self.signals(); // set_signals will filter out invalid signals - if state == EndpointState::Recv { + if state == EndpointState::Recv && signals != 0 { // do recv immediately self.set_signals(0); @@ -170,8 +188,8 @@ impl Debug for EndpointCap<'_> { f.debug_struct("EndpointCap") .field("ptr", &self.cap().get().ptr) .field("badge", &self.badge()) - .field("can_send", &self.can_send()) - .field("can_recv", &self.can_recv()) + .field("irqs", &self.irqs()) + .field("signals", &self.signals()) .field("state", &self.state()) .finish() } diff --git a/kernel/src/plat/irq.rs b/kernel/src/plat/irq.rs index b330467..0159b27 100644 --- a/kernel/src/plat/irq.rs +++ b/kernel/src/plat/irq.rs @@ -50,7 +50,6 @@ pub fn set_irq_driver(driver: IrqDriver) { pub struct IrqManager { handler: [CapEntry; IRQ_NUM], - state: [IrqState; IRQ_NUM], } pub static IRQ_MANAGER: Lazy> = Lazy::new(|| Mutex::new(IrqManager::new())); @@ -59,10 +58,31 @@ impl IrqManager { pub fn new() -> Self { Self { handler: core::array::from_fn::<_, IRQ_NUM, _>(|_| CapEntry::new(NullCap::mint())), - state: [IrqState::Inactive; IRQ_NUM], } } + pub fn enable(&mut self, irq: usize, cap: CapEntry) { + if irq >= IRQ_NUM { + error!("[IrqManager] Invalid IRQ number: {}", irq); + return; + } + + if NullCap::try_from(&self.handler[irq]).is_ok() { + self.handler[irq] = cap; + IRQ_DRIVER.lock().complete(irq); + IRQ_DRIVER.lock().enable(irq); + } + } + + pub fn complete(&mut self, irq: usize) { + if irq >= IRQ_NUM { + error!("[IrqManager] Invalid IRQ number: {}", irq); + return; + } + + IRQ_DRIVER.lock().complete(irq); + } + pub fn dispatch(&mut self) { let irq = IRQ_DRIVER.lock().claim(); if irq.is_none() { @@ -70,31 +90,16 @@ impl IrqManager { return; } - let irq = irq.unwrap(); - if irq >= IRQ_NUM { - error!("[IrqManager] Invalid IRQ number: {}", irq); - IRQ_DRIVER.lock().disable(irq); - IRQ_DRIVER.lock().complete(irq); - return; + if let Some(irq) = irq + && irq < IRQ_NUM + && let Ok(mut cap) = EndpointCap::try_from(&self.handler[irq]) + { + trace!("[IrqManager] Dispatching IRQ: {}", irq); + cap.do_signal(irq).unwrap(); + } else { + warn!("[IrqManager] Received invalid IRQ: {:?}", irq); + IRQ_DRIVER.lock().disable(irq.unwrap()); + IRQ_DRIVER.lock().complete(irq.unwrap()); } - - match self.state[irq] { - IrqState::Inactive => { - warn!("[IrqManager] Received disabled IRQ: {}", irq); - IRQ_DRIVER.lock().disable(irq); - }, - IrqState::Signal => { - trace!("[IrqManager] Dispatching IRQ: {}", irq); - let mut cap = EndpointCap::try_from(&self.handler[irq]).unwrap(); - cap.do_signal(irq).unwrap(); - return; - }, - IrqState::Ipi => { - todo!("Kernel: NO SMP support now"); - }, - IrqState::Reserved => error!("[IrqManager] Received unhandled reserved IRQ: {}", irq), - } - - IRQ_DRIVER.lock().complete(irq); } } diff --git a/kernel/src/syscall.rs b/kernel/src/syscall.rs index 8b9d675..3fce133 100644 --- a/kernel/src/syscall.rs +++ b/kernel/src/syscall.rs @@ -56,10 +56,13 @@ pub fn handle_syscall(tcb: &mut TcbObject) -> SysResult { cap.do_recv(tcb) }, Syscall::IrqSet => { - unimplemented!("[Syscall] IrqSet: {:?}", info.label()) + assert_length!(info, 3); + let mut cap = EndpointCap::try_from(cap)?; + cap.do_set_irq(tcb) }, Syscall::IrqAck => { - unimplemented!("[Syscall] IrqAck: {:?}", info.label()) + let mut cap = EndpointCap::try_from(cap)?; + cap.do_ack_irq(tcb) }, _ => todo!("[Syscall] unhandled syscall: {:?}, {:?}", info.label(), cap), }