1*62e46139SGou Ngai use core::{ffi::c_void, ptr::null_mut}; 2*62e46139SGou Ngai 3*62e46139SGou Ngai use alloc::boxed::Box; 4*62e46139SGou Ngai 5*62e46139SGou Ngai use crate::{ 6*62e46139SGou Ngai arch::interrupt::{cli, sti}, 7*62e46139SGou Ngai include::bindings::bindings::{verify_area, EBUSY, EEXIST, EPERM}, 8*62e46139SGou Ngai kBUG, 9*62e46139SGou Ngai libs::spinlock::RawSpinlock, 10*62e46139SGou Ngai }; 11*62e46139SGou Ngai 12*62e46139SGou Ngai const MAX_SOFTIRQ_NUM: u64 = 64; 13*62e46139SGou Ngai const MAX_LOCK_TRIAL_TIME: u64 = 50; 14*62e46139SGou Ngai pub static mut SOFTIRQ_HANDLER_PTR: *mut Softirq = null_mut(); 15*62e46139SGou Ngai 16*62e46139SGou Ngai /// 软中断向量号码 17*62e46139SGou Ngai #[allow(dead_code)] 18*62e46139SGou Ngai #[repr(u8)] 19*62e46139SGou Ngai pub enum SoftirqNumber { 20*62e46139SGou Ngai TIMER = 0, //时钟软中断信号 21*62e46139SGou Ngai VideoRefresh = 1, //帧缓冲区刷新软中断 22*62e46139SGou Ngai } 23*62e46139SGou Ngai 24*62e46139SGou Ngai #[repr(C)] 25*62e46139SGou Ngai #[derive(Clone, Copy)] 26*62e46139SGou Ngai pub struct SoftirqVector { 27*62e46139SGou Ngai pub action: Option<unsafe extern "C" fn(data: *mut ::core::ffi::c_void)>, //软中断处理函数 28*62e46139SGou Ngai pub data: *mut c_void, 29*62e46139SGou Ngai } 30*62e46139SGou Ngai 31*62e46139SGou Ngai impl Default for SoftirqVector { 32*62e46139SGou Ngai fn default() -> Self { 33*62e46139SGou Ngai Self { 34*62e46139SGou Ngai action: None, 35*62e46139SGou Ngai data: null_mut(), 36*62e46139SGou Ngai } 37*62e46139SGou Ngai } 38*62e46139SGou Ngai } 39*62e46139SGou Ngai 40*62e46139SGou Ngai pub struct Softirq { 41*62e46139SGou Ngai modify_lock: RawSpinlock, 42*62e46139SGou Ngai pending: u64, 43*62e46139SGou Ngai running: u64, 44*62e46139SGou Ngai table: [SoftirqVector; MAX_SOFTIRQ_NUM as usize], 45*62e46139SGou Ngai } 46*62e46139SGou Ngai 47*62e46139SGou Ngai #[no_mangle] 48*62e46139SGou Ngai #[allow(dead_code)] 49*62e46139SGou Ngai /// @brief 提供给c的接口函数,用于初始化静态指针 50*62e46139SGou Ngai pub extern "C" fn softirq_init() { 51*62e46139SGou Ngai if unsafe { SOFTIRQ_HANDLER_PTR.is_null() } { 52*62e46139SGou Ngai unsafe { 53*62e46139SGou Ngai SOFTIRQ_HANDLER_PTR = Box::leak(Box::new(Softirq::default())); 54*62e46139SGou Ngai } 55*62e46139SGou Ngai } else { 56*62e46139SGou Ngai kBUG!("Try to init SOFTIRQ_HANDLER_PTR twice."); 57*62e46139SGou Ngai panic!("Try to init SOFTIRQ_HANDLER_PTR twice."); 58*62e46139SGou Ngai } 59*62e46139SGou Ngai } 60*62e46139SGou Ngai 61*62e46139SGou Ngai /// @brief 将raw pointer转换为指针,减少unsafe块 62*62e46139SGou Ngai #[inline] 63*62e46139SGou Ngai pub fn __get_softirq_handler_mut() -> &'static mut Softirq { 64*62e46139SGou Ngai return unsafe { SOFTIRQ_HANDLER_PTR.as_mut().unwrap() }; 65*62e46139SGou Ngai } 66*62e46139SGou Ngai 67*62e46139SGou Ngai #[no_mangle] 68*62e46139SGou Ngai #[allow(dead_code)] 69*62e46139SGou Ngai pub extern "C" fn raise_softirq(sirq_num: u64) { 70*62e46139SGou Ngai let softirq_handler = __get_softirq_handler_mut(); 71*62e46139SGou Ngai softirq_handler.set_softirq_pending(1 << sirq_num); 72*62e46139SGou Ngai } 73*62e46139SGou Ngai 74*62e46139SGou Ngai /// @brief 软中断注册函数 75*62e46139SGou Ngai /// 76*62e46139SGou Ngai /// @param irq_num 软中断号 77*62e46139SGou Ngai /// @param action 响应函数 78*62e46139SGou Ngai /// @param data 响应数据结构体 79*62e46139SGou Ngai #[no_mangle] 80*62e46139SGou Ngai #[allow(dead_code)] 81*62e46139SGou Ngai pub extern "C" fn register_softirq( 82*62e46139SGou Ngai irq_num: u32, 83*62e46139SGou Ngai action: Option<unsafe extern "C" fn(data: *mut ::core::ffi::c_void)>, 84*62e46139SGou Ngai data: *mut c_void, 85*62e46139SGou Ngai ) { 86*62e46139SGou Ngai let softirq_handler = __get_softirq_handler_mut(); 87*62e46139SGou Ngai softirq_handler.register_softirq(irq_num, action, data); 88*62e46139SGou Ngai } 89*62e46139SGou Ngai 90*62e46139SGou Ngai /// @brief 卸载软中断 91*62e46139SGou Ngai /// @param irq_num 软中断号 92*62e46139SGou Ngai #[no_mangle] 93*62e46139SGou Ngai #[allow(dead_code)] 94*62e46139SGou Ngai pub extern "C" fn unregister_softirq(irq_num: u32) { 95*62e46139SGou Ngai let softirq_handler = __get_softirq_handler_mut(); 96*62e46139SGou Ngai softirq_handler.unregister_softirq(irq_num); 97*62e46139SGou Ngai } 98*62e46139SGou Ngai 99*62e46139SGou Ngai /// 设置软中断的运行状态(只应在do_softirq中调用此宏) 100*62e46139SGou Ngai #[no_mangle] 101*62e46139SGou Ngai #[allow(dead_code)] 102*62e46139SGou Ngai pub extern "C" fn set_softirq_pending(irq_num: u32) { 103*62e46139SGou Ngai let softirq_handler = __get_softirq_handler_mut(); 104*62e46139SGou Ngai softirq_handler.set_softirq_pending(irq_num); 105*62e46139SGou Ngai } 106*62e46139SGou Ngai 107*62e46139SGou Ngai /// @brief 设置软中断运行结束 108*62e46139SGou Ngai /// 109*62e46139SGou Ngai /// @param softirq_num 110*62e46139SGou Ngai #[no_mangle] 111*62e46139SGou Ngai #[allow(dead_code)] 112*62e46139SGou Ngai pub extern "C" fn clear_softirq_pending(irq_num: u32) { 113*62e46139SGou Ngai let softirq_handler = __get_softirq_handler_mut(); 114*62e46139SGou Ngai softirq_handler.clear_softirq_pending(irq_num); 115*62e46139SGou Ngai } 116*62e46139SGou Ngai 117*62e46139SGou Ngai /// @brief 软中断处理程序 118*62e46139SGou Ngai #[no_mangle] 119*62e46139SGou Ngai #[allow(dead_code)] 120*62e46139SGou Ngai pub extern "C" fn do_softirq() { 121*62e46139SGou Ngai let softirq_handler = __get_softirq_handler_mut(); 122*62e46139SGou Ngai softirq_handler.do_softirq(); 123*62e46139SGou Ngai } 124*62e46139SGou Ngai 125*62e46139SGou Ngai impl Default for Softirq { 126*62e46139SGou Ngai fn default() -> Self { 127*62e46139SGou Ngai Self { 128*62e46139SGou Ngai modify_lock: RawSpinlock::INIT, 129*62e46139SGou Ngai pending: (0), 130*62e46139SGou Ngai running: (0), 131*62e46139SGou Ngai table: [Default::default(); MAX_SOFTIRQ_NUM as usize], 132*62e46139SGou Ngai } 133*62e46139SGou Ngai } 134*62e46139SGou Ngai } 135*62e46139SGou Ngai 136*62e46139SGou Ngai impl Softirq { 137*62e46139SGou Ngai #[inline] 138*62e46139SGou Ngai #[allow(dead_code)] 139*62e46139SGou Ngai pub fn get_softirq_pending(&self) -> u64 { 140*62e46139SGou Ngai return self.pending; 141*62e46139SGou Ngai } 142*62e46139SGou Ngai 143*62e46139SGou Ngai #[inline] 144*62e46139SGou Ngai #[allow(dead_code)] 145*62e46139SGou Ngai pub fn get_softirq_running(&self) -> u64 { 146*62e46139SGou Ngai return self.running; 147*62e46139SGou Ngai } 148*62e46139SGou Ngai 149*62e46139SGou Ngai #[inline] 150*62e46139SGou Ngai pub fn set_softirq_pending(&mut self, softirq_num: u32) { 151*62e46139SGou Ngai self.pending |= 1 << softirq_num; 152*62e46139SGou Ngai } 153*62e46139SGou Ngai 154*62e46139SGou Ngai #[inline] 155*62e46139SGou Ngai pub fn set_softirq_running(&mut self, softirq_num: u32) { 156*62e46139SGou Ngai self.running |= 1 << softirq_num; 157*62e46139SGou Ngai } 158*62e46139SGou Ngai 159*62e46139SGou Ngai #[inline] 160*62e46139SGou Ngai pub fn clear_softirq_running(&mut self, softirq_num: u32) { 161*62e46139SGou Ngai self.running &= !(1 << softirq_num); 162*62e46139SGou Ngai } 163*62e46139SGou Ngai 164*62e46139SGou Ngai /// @brief 清除软中断pending标志位 165*62e46139SGou Ngai #[inline] 166*62e46139SGou Ngai pub fn clear_softirq_pending(&mut self, softirq_num: u32) { 167*62e46139SGou Ngai self.pending &= !(1 << softirq_num); 168*62e46139SGou Ngai } 169*62e46139SGou Ngai 170*62e46139SGou Ngai /// @brief 判断对应running标志位是否为0 171*62e46139SGou Ngai /// @return true: 标志位为1; false: 标志位为0 172*62e46139SGou Ngai #[inline] 173*62e46139SGou Ngai pub fn is_running(&mut self, softirq_num: u32) -> bool { 174*62e46139SGou Ngai return (self.running & (1 << softirq_num)).ne(&0); 175*62e46139SGou Ngai } 176*62e46139SGou Ngai 177*62e46139SGou Ngai /// @brief 判断对应pending标志位是否为0 178*62e46139SGou Ngai /// @return true: 标志位为1; false: 标志位为0 179*62e46139SGou Ngai #[inline] 180*62e46139SGou Ngai pub fn is_pending(&mut self, softirq_num: u32) -> bool { 181*62e46139SGou Ngai return (self.pending & (1 << softirq_num)).ne(&0); 182*62e46139SGou Ngai } 183*62e46139SGou Ngai 184*62e46139SGou Ngai /// @brief 注册软中断向量 185*62e46139SGou Ngai /// @param irq_num 中断向量号码 186*62e46139SGou Ngai /// @param action 中断函数的入口地址 187*62e46139SGou Ngai /// @param data 中断函数的操作数据 188*62e46139SGou Ngai pub fn register_softirq( 189*62e46139SGou Ngai &mut self, 190*62e46139SGou Ngai irq_num: u32, 191*62e46139SGou Ngai action: Option<unsafe extern "C" fn(data: *mut ::core::ffi::c_void)>, 192*62e46139SGou Ngai data: *mut c_void, 193*62e46139SGou Ngai ) -> i32 { 194*62e46139SGou Ngai if self.table[irq_num as usize].action.is_some() { 195*62e46139SGou Ngai return -(EEXIST as i32); 196*62e46139SGou Ngai } 197*62e46139SGou Ngai 198*62e46139SGou Ngai if unsafe { verify_area(action.unwrap() as u64, 1) } { 199*62e46139SGou Ngai return -(EPERM as i32); 200*62e46139SGou Ngai } 201*62e46139SGou Ngai self.modify_lock.lock(); 202*62e46139SGou Ngai self.table[irq_num as usize].action = action; 203*62e46139SGou Ngai self.table[irq_num as usize].data = data; 204*62e46139SGou Ngai self.modify_lock.unlock(); 205*62e46139SGou Ngai return 0; 206*62e46139SGou Ngai } 207*62e46139SGou Ngai 208*62e46139SGou Ngai /// @brief 解注册软中断向量 209*62e46139SGou Ngai /// @param irq_num 中断向量号码 210*62e46139SGou Ngai pub fn unregister_softirq(&mut self, irq_num: u32) -> i32 { 211*62e46139SGou Ngai for _trial_time in 0..MAX_LOCK_TRIAL_TIME { 212*62e46139SGou Ngai if self.is_running(irq_num) { 213*62e46139SGou Ngai continue; //running标志位为1 214*62e46139SGou Ngai } 215*62e46139SGou Ngai if self.modify_lock.try_lock() { 216*62e46139SGou Ngai if self.is_running(irq_num) { 217*62e46139SGou Ngai self.modify_lock.unlock(); 218*62e46139SGou Ngai continue; 219*62e46139SGou Ngai } 220*62e46139SGou Ngai break; 221*62e46139SGou Ngai } 222*62e46139SGou Ngai } 223*62e46139SGou Ngai // 存在尝试加锁规定次数后仍加锁失败的情况,报告错误并退出 224*62e46139SGou Ngai if !self.modify_lock.is_locked() { 225*62e46139SGou Ngai return -(EBUSY as i32); 226*62e46139SGou Ngai } 227*62e46139SGou Ngai self.clear_softirq_running(irq_num); 228*62e46139SGou Ngai self.clear_softirq_pending(irq_num); 229*62e46139SGou Ngai self.table[irq_num as usize].action = None; 230*62e46139SGou Ngai self.table[irq_num as usize].data = null_mut(); 231*62e46139SGou Ngai self.modify_lock.unlock(); 232*62e46139SGou Ngai return 0; 233*62e46139SGou Ngai } 234*62e46139SGou Ngai 235*62e46139SGou Ngai /// @brief 遍历执行软中断 236*62e46139SGou Ngai pub fn do_softirq(&mut self) { 237*62e46139SGou Ngai sti(); 238*62e46139SGou Ngai let mut softirq_index: u32 = 0; //软中断向量号码 239*62e46139SGou Ngai while (softirq_index as u64) < MAX_SOFTIRQ_NUM && self.pending != 0 { 240*62e46139SGou Ngai if self.is_pending(softirq_index) 241*62e46139SGou Ngai && self.table[softirq_index as usize].action.is_some() 242*62e46139SGou Ngai && !self.is_running(softirq_index) 243*62e46139SGou Ngai { 244*62e46139SGou Ngai if self.modify_lock.try_lock() { 245*62e46139SGou Ngai if self.is_running(softirq_index) 246*62e46139SGou Ngai || self.table[softirq_index as usize].action.is_none() 247*62e46139SGou Ngai { 248*62e46139SGou Ngai self.modify_lock.unlock(); 249*62e46139SGou Ngai continue; 250*62e46139SGou Ngai } 251*62e46139SGou Ngai self.clear_softirq_pending(softirq_index); 252*62e46139SGou Ngai self.set_softirq_running(softirq_index); 253*62e46139SGou Ngai self.modify_lock.unlock(); 254*62e46139SGou Ngai unsafe { 255*62e46139SGou Ngai (self.table[softirq_index as usize].action.unwrap())( 256*62e46139SGou Ngai self.table[softirq_index as usize].data, 257*62e46139SGou Ngai ); 258*62e46139SGou Ngai } 259*62e46139SGou Ngai self.clear_softirq_running(softirq_index); 260*62e46139SGou Ngai } 261*62e46139SGou Ngai } 262*62e46139SGou Ngai softirq_index += 1; 263*62e46139SGou Ngai } 264*62e46139SGou Ngai cli(); 265*62e46139SGou Ngai } 266*62e46139SGou Ngai } 267