mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 09:45:19 +08:00
feat: kernel/objects/endpoint: wire up syscall
This commit is contained in:
parent
e6d6a2ee21
commit
86dbca7ef5
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user