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