1bacd691cSlogin use core::{ 2bacd691cSlogin fmt::Debug, 3bacd691cSlogin intrinsics::unlikely, 4bacd691cSlogin mem::{self, MaybeUninit}, 5bacd691cSlogin ptr::null_mut, 6bacd691cSlogin sync::atomic::{compiler_fence, Ordering}, 7bacd691cSlogin }; 862e46139SGou Ngai 9bacd691cSlogin use alloc::{boxed::Box, sync::Arc}; 10bacd691cSlogin use num_traits::FromPrimitive; 11*91e9d4abSLoGin use system_error::SystemError; 1262e46139SGou Ngai 1362e46139SGou Ngai use crate::{ 1446e234aeSLoGin arch::CurrentIrqArch, exception::InterruptArch, kdebug, kinfo, libs::rwlock::RwLock, 1546e234aeSLoGin mm::percpu::PerCpu, process::ProcessManager, smp::core::smp_get_processor_id, 16*91e9d4abSLoGin time::timer::clock, 1762e46139SGou Ngai }; 1862e46139SGou Ngai 1962e46139SGou Ngai const MAX_SOFTIRQ_NUM: u64 = 64; 20bacd691cSlogin const MAX_SOFTIRQ_RESTART: i32 = 20; 21bacd691cSlogin 2246e234aeSLoGin static mut __CPU_PENDING: Option<Box<[VecStatus; PerCpu::MAX_CPU_NUM]>> = None; 23bacd691cSlogin static mut __SORTIRQ_VECTORS: *mut Softirq = null_mut(); 24bacd691cSlogin 25bacd691cSlogin #[no_mangle] 26bacd691cSlogin pub extern "C" fn rs_softirq_init() { 27bacd691cSlogin softirq_init().expect("softirq_init failed"); 28bacd691cSlogin } 29bacd691cSlogin 30bacd691cSlogin pub fn softirq_init() -> Result<(), SystemError> { 31bacd691cSlogin kinfo!("Initializing softirq..."); 32bacd691cSlogin unsafe { 33bacd691cSlogin __SORTIRQ_VECTORS = Box::leak(Box::new(Softirq::new())); 3446e234aeSLoGin __CPU_PENDING = Some(Box::new( 3546e234aeSLoGin [VecStatus::default(); PerCpu::MAX_CPU_NUM as usize], 3646e234aeSLoGin )); 37bacd691cSlogin let cpu_pending = __CPU_PENDING.as_mut().unwrap(); 3846e234aeSLoGin for i in 0..PerCpu::MAX_CPU_NUM { 39bacd691cSlogin cpu_pending[i as usize] = VecStatus::default(); 40bacd691cSlogin } 41bacd691cSlogin } 4240fe15e0SLoGin kinfo!("Softirq initialized."); 43bacd691cSlogin return Ok(()); 44bacd691cSlogin } 45bacd691cSlogin 46bacd691cSlogin #[inline(always)] 47bacd691cSlogin pub fn softirq_vectors() -> &'static mut Softirq { 48bacd691cSlogin unsafe { 49bacd691cSlogin return __SORTIRQ_VECTORS.as_mut().unwrap(); 50bacd691cSlogin } 51bacd691cSlogin } 52bacd691cSlogin 53bacd691cSlogin #[inline(always)] 54bacd691cSlogin fn cpu_pending(cpu_id: usize) -> &'static mut VecStatus { 55bacd691cSlogin unsafe { 56bacd691cSlogin return &mut __CPU_PENDING.as_mut().unwrap()[cpu_id]; 57bacd691cSlogin } 58bacd691cSlogin } 5962e46139SGou Ngai 6062e46139SGou Ngai /// 软中断向量号码 6162e46139SGou Ngai #[allow(dead_code)] 6262e46139SGou Ngai #[repr(u8)] 63bacd691cSlogin #[derive(FromPrimitive, Copy, Clone, Debug, PartialEq, Eq)] 6462e46139SGou Ngai pub enum SoftirqNumber { 65bacd691cSlogin /// 时钟软中断信号 66bacd691cSlogin TIMER = 0, 6762e46139SGou Ngai VideoRefresh = 1, //帧缓冲区刷新软中断 6862e46139SGou Ngai } 6962e46139SGou Ngai 70bacd691cSlogin impl From<u64> for SoftirqNumber { 71bacd691cSlogin fn from(value: u64) -> Self { 72bacd691cSlogin return <Self as FromPrimitive>::from_u64(value).unwrap(); 7362e46139SGou Ngai } 7462e46139SGou Ngai } 7562e46139SGou Ngai 76bacd691cSlogin bitflags! { 77bacd691cSlogin #[derive(Default)] 78bacd691cSlogin pub struct VecStatus: u64 { 79bacd691cSlogin const TIMER = 1 << 0; 80bacd691cSlogin const VIDEO_REFRESH = 1 << 1; 81bacd691cSlogin } 82bacd691cSlogin } 83bacd691cSlogin 84bacd691cSlogin impl From<SoftirqNumber> for VecStatus { 85bacd691cSlogin fn from(value: SoftirqNumber) -> Self { 86bacd691cSlogin return Self::from_bits_truncate(1 << (value as u64)); 87bacd691cSlogin } 88bacd691cSlogin } 89bacd691cSlogin 90bacd691cSlogin pub trait SoftirqVec: Send + Sync + Debug { 91bacd691cSlogin fn run(&self); 92bacd691cSlogin } 93bacd691cSlogin 94bacd691cSlogin #[derive(Debug)] 9562e46139SGou Ngai pub struct Softirq { 96bacd691cSlogin table: RwLock<[Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize]>, 9762e46139SGou Ngai } 9862e46139SGou Ngai impl Softirq { 99bacd691cSlogin fn new() -> Softirq { 100bacd691cSlogin let mut data: [MaybeUninit<Option<Arc<dyn SoftirqVec>>>; MAX_SOFTIRQ_NUM as usize] = 101bacd691cSlogin unsafe { MaybeUninit::uninit().assume_init() }; 102bacd691cSlogin 103bacd691cSlogin for i in 0..MAX_SOFTIRQ_NUM { 104bacd691cSlogin data[i as usize] = MaybeUninit::new(None); 10562e46139SGou Ngai } 10662e46139SGou Ngai 107bacd691cSlogin let data: [Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize] = unsafe { 108bacd691cSlogin mem::transmute::<_, [Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize]>(data) 109bacd691cSlogin }; 11062e46139SGou Ngai 111bacd691cSlogin return Softirq { 112bacd691cSlogin table: RwLock::new(data), 113bacd691cSlogin }; 11462e46139SGou Ngai } 11562e46139SGou Ngai 11662e46139SGou Ngai /// @brief 注册软中断向量 117bacd691cSlogin /// 118bacd691cSlogin /// @param softirq_num 中断向量号 119bacd691cSlogin /// 120bacd691cSlogin /// @param hanlder 中断函数对应的结构体 12162e46139SGou Ngai pub fn register_softirq( 122bacd691cSlogin &self, 123bacd691cSlogin softirq_num: SoftirqNumber, 124bacd691cSlogin handler: Arc<dyn SoftirqVec>, 125bacd691cSlogin ) -> Result<i32, SystemError> { 126bacd691cSlogin // kdebug!("register_softirq softirq_num = {:?}", softirq_num as u64); 12762e46139SGou Ngai 128bacd691cSlogin // let self = &mut SOFTIRQ_VECTORS.lock(); 129bacd691cSlogin // 判断该软中断向量是否已经被注册 130bacd691cSlogin let mut table_guard = self.table.write(); 131bacd691cSlogin if table_guard[softirq_num as usize].is_some() { 132bacd691cSlogin // kdebug!("register_softirq failed"); 133bacd691cSlogin 134bacd691cSlogin return Err(SystemError::EINVAL); 13562e46139SGou Ngai } 136bacd691cSlogin table_guard[softirq_num as usize] = Some(handler); 137bacd691cSlogin drop(table_guard); 138bacd691cSlogin 139bacd691cSlogin // kdebug!( 140bacd691cSlogin // "register_softirq successfully, softirq_num = {:?}", 141bacd691cSlogin // softirq_num as u64 142bacd691cSlogin // ); 143bacd691cSlogin compiler_fence(Ordering::SeqCst); 144bacd691cSlogin return Ok(0); 14562e46139SGou Ngai } 14662e46139SGou Ngai 14762e46139SGou Ngai /// @brief 解注册软中断向量 148bacd691cSlogin /// 14962e46139SGou Ngai /// @param irq_num 中断向量号码 150bacd691cSlogin pub fn unregister_softirq(&self, softirq_num: SoftirqNumber) { 151bacd691cSlogin // kdebug!("unregister_softirq softirq_num = {:?}", softirq_num as u64); 1521a72a751SLoGin let mut table_guard = self.table.write(); 153bacd691cSlogin // 将软中断向量清空 154bacd691cSlogin table_guard[softirq_num as usize] = None; 155bacd691cSlogin drop(table_guard); 156bacd691cSlogin // 将对应位置的pending和runing都置0 157bacd691cSlogin // self.running.lock().set(VecStatus::from(softirq_num), false); 158bacd691cSlogin // 将对应CPU的pending置0 159bacd691cSlogin compiler_fence(Ordering::SeqCst); 160bacd691cSlogin cpu_pending(smp_get_processor_id() as usize).set(VecStatus::from(softirq_num), false); 161bacd691cSlogin compiler_fence(Ordering::SeqCst); 16262e46139SGou Ngai } 163bacd691cSlogin 164bacd691cSlogin pub fn do_softirq(&self) { 165bacd691cSlogin // TODO pcb的flags未修改 166bacd691cSlogin // todo: 是否需要判断在当前cpu上面,该函数的嵌套层数?(防止爆栈) 167bacd691cSlogin let end = clock() + 500 * 2; 168bacd691cSlogin let cpu_id = smp_get_processor_id(); 169bacd691cSlogin let mut max_restart = MAX_SOFTIRQ_RESTART; 170bacd691cSlogin loop { 171bacd691cSlogin compiler_fence(Ordering::SeqCst); 172bacd691cSlogin let pending = cpu_pending(cpu_id as usize).bits; 173bacd691cSlogin cpu_pending(cpu_id as usize).bits = 0; 174bacd691cSlogin compiler_fence(Ordering::SeqCst); 175bacd691cSlogin 17646e234aeSLoGin unsafe { CurrentIrqArch::interrupt_enable() }; 177bacd691cSlogin if pending != 0 { 178bacd691cSlogin for i in 0..MAX_SOFTIRQ_NUM { 179bacd691cSlogin if pending & (1 << i) == 0 { 18062e46139SGou Ngai continue; 18162e46139SGou Ngai } 182bacd691cSlogin 183bacd691cSlogin let table_guard = self.table.read(); 184bacd691cSlogin let softirq_func = table_guard[i as usize].clone(); 185bacd691cSlogin drop(table_guard); 186bacd691cSlogin if softirq_func.is_none() { 187bacd691cSlogin continue; 188bacd691cSlogin } 189bacd691cSlogin 1901496ba7bSLoGin let prev_count: usize = ProcessManager::current_pcb().preempt_count(); 191bacd691cSlogin 192bacd691cSlogin softirq_func.as_ref().unwrap().run(); 1931496ba7bSLoGin if unlikely(prev_count != ProcessManager::current_pcb().preempt_count()) { 194bacd691cSlogin kdebug!( 195bacd691cSlogin "entered softirq {:?} with preempt_count {:?},exited with {:?}", 196bacd691cSlogin i, 197bacd691cSlogin prev_count, 1981496ba7bSLoGin ProcessManager::current_pcb().preempt_count() 199bacd691cSlogin ); 2001496ba7bSLoGin unsafe { ProcessManager::current_pcb().set_preempt_count(prev_count) }; 201bacd691cSlogin } 202bacd691cSlogin } 203bacd691cSlogin } 20446e234aeSLoGin unsafe { CurrentIrqArch::interrupt_disable() }; 205bacd691cSlogin max_restart -= 1; 206bacd691cSlogin compiler_fence(Ordering::SeqCst); 207bacd691cSlogin if cpu_pending(cpu_id as usize).is_empty() { 208bacd691cSlogin compiler_fence(Ordering::SeqCst); 209bacd691cSlogin if clock() < end && max_restart > 0 { 210bacd691cSlogin continue; 211bacd691cSlogin } else { 212bacd691cSlogin break; 213bacd691cSlogin } 214bacd691cSlogin } else { 215bacd691cSlogin // TODO:当有softirqd时 唤醒它 21662e46139SGou Ngai break; 21762e46139SGou Ngai } 21862e46139SGou Ngai } 21962e46139SGou Ngai } 22062e46139SGou Ngai 221bacd691cSlogin pub fn raise_softirq(&self, softirq_num: SoftirqNumber) { 2229550910aSChiichen let guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 223bacd691cSlogin let processor_id = smp_get_processor_id() as usize; 224bacd691cSlogin 225bacd691cSlogin cpu_pending(processor_id).insert(VecStatus::from(softirq_num)); 226bacd691cSlogin 227bacd691cSlogin compiler_fence(Ordering::SeqCst); 228bacd691cSlogin 2299550910aSChiichen drop(guard); 230bacd691cSlogin // kdebug!("raise_softirq exited"); 23162e46139SGou Ngai } 2328fd71f27Shoumkh pub unsafe fn clear_softirq_pending(&self, softirq_num: SoftirqNumber) { 233bacd691cSlogin compiler_fence(Ordering::SeqCst); 234bacd691cSlogin cpu_pending(smp_get_processor_id() as usize).remove(VecStatus::from(softirq_num)); 235bacd691cSlogin compiler_fence(Ordering::SeqCst); 23662e46139SGou Ngai } 23762e46139SGou Ngai } 238bacd691cSlogin 239bacd691cSlogin // ======= 以下为给C提供的接口 ======= 240bacd691cSlogin #[no_mangle] 241bacd691cSlogin pub extern "C" fn rs_raise_softirq(softirq_num: u32) { 242bacd691cSlogin softirq_vectors().raise_softirq(SoftirqNumber::from(softirq_num as u64)); 24362e46139SGou Ngai } 244bacd691cSlogin 245bacd691cSlogin #[no_mangle] 246bacd691cSlogin pub extern "C" fn rs_unregister_softirq(softirq_num: u32) { 247bacd691cSlogin softirq_vectors().unregister_softirq(SoftirqNumber::from(softirq_num as u64)); 24862e46139SGou Ngai } 249bacd691cSlogin 250bacd691cSlogin #[no_mangle] 251bacd691cSlogin pub extern "C" fn rs_do_softirq() { 252bacd691cSlogin softirq_vectors().do_softirq(); 253bacd691cSlogin } 254bacd691cSlogin 255bacd691cSlogin #[no_mangle] 256bacd691cSlogin pub extern "C" fn rs_clear_softirq_pending(softirq_num: u32) { 2578fd71f27Shoumkh unsafe { 258bacd691cSlogin softirq_vectors().clear_softirq_pending(SoftirqNumber::from(softirq_num as u64)); 25962e46139SGou Ngai } 2608fd71f27Shoumkh } 261