feat: kernel/objects/endpoint: wire up syscall

This commit is contained in:
Paul Pan 2024-09-04 20:51:10 +08:00
parent e6d6a2ee21
commit 86dbca7ef5
3 changed files with 70 additions and 44 deletions

View File

@ -1,10 +1,12 @@
use crate::{ use crate::objects::*;
objects::*, use crate::plat::{
plat::{irq::IRQ_NUM, trap::TrapContextOps}, irq::{IRQ_MANAGER, IRQ_NUM},
trap::TrapContextOps,
}; };
use core::{cmp::min, fmt::Debug}; use core::{cmp::min, fmt::Debug};
use tcb::{ThreadState, EP_QUEUE_LINK_ID}; use tcb::{ThreadState, EP_QUEUE_LINK_ID};
use uapi::{cap::ObjectType, syscall::*}; use uapi::{cap::ObjectType, syscall::*};
use utils::then::Then;
use utils::{addr::*, array::*, linked_list::Link}; use utils::{addr::*, array::*, linked_list::Link};
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
@ -35,8 +37,8 @@ impl KernelObject for EndpointObject {
* > | [63:0] | * > | [63:0] |
* *
* in our implementation, EndpointCap layout: * in our implementation, EndpointCap layout:
* > args[0]: badge * > args[0]: option<irq>
* > args[1]: none * > args[1]: badge
* > ptr: base_ptr * > ptr: base_ptr
* > cap_type: cap_tag * > cap_type: cap_tag
*/ */
@ -45,15 +47,16 @@ pub type EndpointCap<'a> = Cap<'a, EndpointObject>;
impl<'a> EndpointCap<'a> { impl<'a> EndpointCap<'a> {
pub fn mint(ptr: PhysAddr, badge: usize) -> RawCap { 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 { pub fn irqs(&self) -> Option<usize> {
self.cap().get().args[0] & 0x2 != 0 let irqs = self.cap().get().args[0];
(irqs != 0).then_some(irqs)
} }
pub fn can_recv(&self) -> bool { fn set_irq(&mut self, irqs: usize) {
self.cap().get().args[0] & 0x1 != 0 self.cap().get().args[0] |= 1 << irqs;
} }
pub fn badge(&self) -> usize { pub fn badge(&self) -> usize {
@ -64,8 +67,8 @@ impl<'a> EndpointCap<'a> {
self.as_object().signals self.as_object().signals
} }
pub fn set_signals(&mut self, signals: usize) { fn set_signals(&mut self, signals: usize) {
self.as_object_mut().signals = signals; self.as_object_mut().signals = signals & self.irqs().unwrap_or(0);
} }
pub fn state(&self) -> EndpointState { 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 { pub fn do_send(&mut self, send: &mut TcbObject) -> SysResult {
match self.state() { match self.state() {
EndpointState::Recv => { EndpointState::Recv => {
@ -148,8 +165,9 @@ impl<'a> EndpointCap<'a> {
let state = self.state(); let state = self.state();
self.set_signals(signals); 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 // do recv immediately
self.set_signals(0); self.set_signals(0);
@ -170,8 +188,8 @@ impl Debug for EndpointCap<'_> {
f.debug_struct("EndpointCap") f.debug_struct("EndpointCap")
.field("ptr", &self.cap().get().ptr) .field("ptr", &self.cap().get().ptr)
.field("badge", &self.badge()) .field("badge", &self.badge())
.field("can_send", &self.can_send()) .field("irqs", &self.irqs())
.field("can_recv", &self.can_recv()) .field("signals", &self.signals())
.field("state", &self.state()) .field("state", &self.state())
.finish() .finish()
} }

View File

@ -50,7 +50,6 @@ pub fn set_irq_driver(driver: IrqDriver) {
pub struct IrqManager { pub struct IrqManager {
handler: [CapEntry; IRQ_NUM], handler: [CapEntry; IRQ_NUM],
state: [IrqState; IRQ_NUM],
} }
pub static IRQ_MANAGER: Lazy<Mutex<IrqManager>> = Lazy::new(|| Mutex::new(IrqManager::new())); pub static IRQ_MANAGER: Lazy<Mutex<IrqManager>> = Lazy::new(|| Mutex::new(IrqManager::new()));
@ -59,10 +58,31 @@ impl IrqManager {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
handler: core::array::from_fn::<_, IRQ_NUM, _>(|_| CapEntry::new(NullCap::mint())), 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) { pub fn dispatch(&mut self) {
let irq = IRQ_DRIVER.lock().claim(); let irq = IRQ_DRIVER.lock().claim();
if irq.is_none() { if irq.is_none() {
@ -70,31 +90,16 @@ impl IrqManager {
return; return;
} }
let irq = irq.unwrap(); if let Some(irq) = irq
if irq >= IRQ_NUM { && irq < IRQ_NUM
error!("[IrqManager] Invalid IRQ number: {}", irq); && let Ok(mut cap) = EndpointCap::try_from(&self.handler[irq])
IRQ_DRIVER.lock().disable(irq); {
IRQ_DRIVER.lock().complete(irq); trace!("[IrqManager] Dispatching IRQ: {}", irq);
return; 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);
} }
} }

View File

@ -56,10 +56,13 @@ pub fn handle_syscall(tcb: &mut TcbObject) -> SysResult {
cap.do_recv(tcb) cap.do_recv(tcb)
}, },
Syscall::IrqSet => { 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 => { 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), _ => todo!("[Syscall] unhandled syscall: {:?}, {:?}", info.label(), cap),
} }