1bacd691cSlogin use core::{ 2bacd691cSlogin fmt::Debug, 3bacd691cSlogin intrinsics::unlikely, 4bacd691cSlogin mem::{self, MaybeUninit}, 5bacd691cSlogin ptr::null_mut, 6*f0c87a89SGnoCiYeH sync::atomic::{compiler_fence, fence, AtomicI16, Ordering}, 7bacd691cSlogin }; 862e46139SGou Ngai 90d6cf65aSLoGin use alloc::{boxed::Box, sync::Arc, vec::Vec}; 10bacd691cSlogin use num_traits::FromPrimitive; 1191e9d4abSLoGin use system_error::SystemError; 1262e46139SGou Ngai 1362e46139SGou Ngai use crate::{ 140d6cf65aSLoGin arch::CurrentIrqArch, 150d6cf65aSLoGin exception::InterruptArch, 160d6cf65aSLoGin kdebug, kinfo, 170d6cf65aSLoGin libs::rwlock::RwLock, 180d6cf65aSLoGin mm::percpu::{PerCpu, PerCpuVar}, 190d6cf65aSLoGin process::ProcessManager, 20*f0c87a89SGnoCiYeH sched::cputime::IrqTime, 21e2841179SLoGin smp::{core::smp_get_processor_id, cpu::ProcessorId}, 2291e9d4abSLoGin time::timer::clock, 2362e46139SGou Ngai }; 2462e46139SGou Ngai 2562e46139SGou Ngai const MAX_SOFTIRQ_NUM: u64 = 64; 26bacd691cSlogin const MAX_SOFTIRQ_RESTART: i32 = 20; 27bacd691cSlogin 28e2841179SLoGin static mut __CPU_PENDING: Option<Box<[VecStatus; PerCpu::MAX_CPU_NUM as usize]>> = None; 29bacd691cSlogin static mut __SORTIRQ_VECTORS: *mut Softirq = null_mut(); 30bacd691cSlogin 31bacd691cSlogin #[no_mangle] 32bacd691cSlogin pub extern "C" fn rs_softirq_init() { 33bacd691cSlogin softirq_init().expect("softirq_init failed"); 34bacd691cSlogin } 35bacd691cSlogin 365b59005fSLoGin #[inline(never)] 37bacd691cSlogin pub fn softirq_init() -> Result<(), SystemError> { 38bacd691cSlogin kinfo!("Initializing softirq..."); 39bacd691cSlogin unsafe { 40bacd691cSlogin __SORTIRQ_VECTORS = Box::leak(Box::new(Softirq::new())); 4146e234aeSLoGin __CPU_PENDING = Some(Box::new( 4246e234aeSLoGin [VecStatus::default(); PerCpu::MAX_CPU_NUM as usize], 4346e234aeSLoGin )); 44bacd691cSlogin let cpu_pending = __CPU_PENDING.as_mut().unwrap(); 4546e234aeSLoGin for i in 0..PerCpu::MAX_CPU_NUM { 46bacd691cSlogin cpu_pending[i as usize] = VecStatus::default(); 47bacd691cSlogin } 48bacd691cSlogin } 4940fe15e0SLoGin kinfo!("Softirq initialized."); 50bacd691cSlogin return Ok(()); 51bacd691cSlogin } 52bacd691cSlogin 53bacd691cSlogin #[inline(always)] 54bacd691cSlogin pub fn softirq_vectors() -> &'static mut Softirq { 55bacd691cSlogin unsafe { 56bacd691cSlogin return __SORTIRQ_VECTORS.as_mut().unwrap(); 57bacd691cSlogin } 58bacd691cSlogin } 59bacd691cSlogin 60bacd691cSlogin #[inline(always)] 61e2841179SLoGin fn cpu_pending(cpu_id: ProcessorId) -> &'static mut VecStatus { 62bacd691cSlogin unsafe { 63e2841179SLoGin return &mut __CPU_PENDING.as_mut().unwrap()[cpu_id.data() as usize]; 64bacd691cSlogin } 65bacd691cSlogin } 6662e46139SGou Ngai 6762e46139SGou Ngai /// 软中断向量号码 6862e46139SGou Ngai #[allow(dead_code)] 6962e46139SGou Ngai #[repr(u8)] 70bacd691cSlogin #[derive(FromPrimitive, Copy, Clone, Debug, PartialEq, Eq)] 7162e46139SGou Ngai pub enum SoftirqNumber { 72bacd691cSlogin /// 时钟软中断信号 73bacd691cSlogin TIMER = 0, 7462e46139SGou Ngai VideoRefresh = 1, //帧缓冲区刷新软中断 7562e46139SGou Ngai } 7662e46139SGou Ngai 77bacd691cSlogin impl From<u64> for SoftirqNumber { 78bacd691cSlogin fn from(value: u64) -> Self { 79bacd691cSlogin return <Self as FromPrimitive>::from_u64(value).unwrap(); 8062e46139SGou Ngai } 8162e46139SGou Ngai } 8262e46139SGou Ngai 83bacd691cSlogin bitflags! { 84bacd691cSlogin #[derive(Default)] 85bacd691cSlogin pub struct VecStatus: u64 { 86bacd691cSlogin const TIMER = 1 << 0; 87bacd691cSlogin const VIDEO_REFRESH = 1 << 1; 88bacd691cSlogin } 89bacd691cSlogin } 90bacd691cSlogin 91bacd691cSlogin impl From<SoftirqNumber> for VecStatus { 92bacd691cSlogin fn from(value: SoftirqNumber) -> Self { 93bacd691cSlogin return Self::from_bits_truncate(1 << (value as u64)); 94bacd691cSlogin } 95bacd691cSlogin } 96bacd691cSlogin 97bacd691cSlogin pub trait SoftirqVec: Send + Sync + Debug { 98bacd691cSlogin fn run(&self); 99bacd691cSlogin } 100bacd691cSlogin 101bacd691cSlogin #[derive(Debug)] 10262e46139SGou Ngai pub struct Softirq { 103bacd691cSlogin table: RwLock<[Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize]>, 1040d6cf65aSLoGin /// 软中断嵌套层数(per cpu) 1050d6cf65aSLoGin cpu_running_count: PerCpuVar<AtomicI16>, 10662e46139SGou Ngai } 10762e46139SGou Ngai impl Softirq { 1080d6cf65aSLoGin /// 每个CPU最大嵌套的软中断数量 1090d6cf65aSLoGin const MAX_RUNNING_PER_CPU: i16 = 3; 110bacd691cSlogin fn new() -> Softirq { 111bacd691cSlogin let mut data: [MaybeUninit<Option<Arc<dyn SoftirqVec>>>; MAX_SOFTIRQ_NUM as usize] = 112bacd691cSlogin unsafe { MaybeUninit::uninit().assume_init() }; 113bacd691cSlogin 114bacd691cSlogin for i in 0..MAX_SOFTIRQ_NUM { 115bacd691cSlogin data[i as usize] = MaybeUninit::new(None); 11662e46139SGou Ngai } 11762e46139SGou Ngai 118bacd691cSlogin let data: [Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize] = unsafe { 119bacd691cSlogin mem::transmute::<_, [Option<Arc<dyn SoftirqVec>>; MAX_SOFTIRQ_NUM as usize]>(data) 120bacd691cSlogin }; 12162e46139SGou Ngai 1220d6cf65aSLoGin let mut percpu_count = Vec::with_capacity(PerCpu::MAX_CPU_NUM as usize); 1230d6cf65aSLoGin percpu_count.resize_with(PerCpu::MAX_CPU_NUM as usize, || AtomicI16::new(0)); 1240d6cf65aSLoGin let cpu_running_count = PerCpuVar::new(percpu_count).unwrap(); 1250d6cf65aSLoGin 126bacd691cSlogin return Softirq { 127bacd691cSlogin table: RwLock::new(data), 1280d6cf65aSLoGin cpu_running_count, 129bacd691cSlogin }; 13062e46139SGou Ngai } 13162e46139SGou Ngai 1320d6cf65aSLoGin fn cpu_running_count(&self) -> &PerCpuVar<AtomicI16> { 1330d6cf65aSLoGin return &self.cpu_running_count; 1340d6cf65aSLoGin } 1350d6cf65aSLoGin 13662e46139SGou Ngai /// @brief 注册软中断向量 137bacd691cSlogin /// 138bacd691cSlogin /// @param softirq_num 中断向量号 139bacd691cSlogin /// 140bacd691cSlogin /// @param hanlder 中断函数对应的结构体 14162e46139SGou Ngai pub fn register_softirq( 142bacd691cSlogin &self, 143bacd691cSlogin softirq_num: SoftirqNumber, 144bacd691cSlogin handler: Arc<dyn SoftirqVec>, 145bacd691cSlogin ) -> Result<i32, SystemError> { 146bacd691cSlogin // kdebug!("register_softirq softirq_num = {:?}", softirq_num as u64); 14762e46139SGou Ngai 148bacd691cSlogin // let self = &mut SOFTIRQ_VECTORS.lock(); 149bacd691cSlogin // 判断该软中断向量是否已经被注册 1500d6cf65aSLoGin let mut table_guard = self.table.write_irqsave(); 151bacd691cSlogin if table_guard[softirq_num as usize].is_some() { 152bacd691cSlogin // kdebug!("register_softirq failed"); 153bacd691cSlogin 154bacd691cSlogin return Err(SystemError::EINVAL); 15562e46139SGou Ngai } 156bacd691cSlogin table_guard[softirq_num as usize] = Some(handler); 157bacd691cSlogin drop(table_guard); 158bacd691cSlogin 159bacd691cSlogin // kdebug!( 160bacd691cSlogin // "register_softirq successfully, softirq_num = {:?}", 161bacd691cSlogin // softirq_num as u64 162bacd691cSlogin // ); 163bacd691cSlogin compiler_fence(Ordering::SeqCst); 164bacd691cSlogin return Ok(0); 16562e46139SGou Ngai } 16662e46139SGou Ngai 16762e46139SGou Ngai /// @brief 解注册软中断向量 168bacd691cSlogin /// 16962e46139SGou Ngai /// @param irq_num 中断向量号码 170e2841179SLoGin #[allow(dead_code)] 171bacd691cSlogin pub fn unregister_softirq(&self, softirq_num: SoftirqNumber) { 172bacd691cSlogin // kdebug!("unregister_softirq softirq_num = {:?}", softirq_num as u64); 1730d6cf65aSLoGin let mut table_guard = self.table.write_irqsave(); 174bacd691cSlogin // 将软中断向量清空 175bacd691cSlogin table_guard[softirq_num as usize] = None; 176bacd691cSlogin drop(table_guard); 177bacd691cSlogin // 将对应位置的pending和runing都置0 178bacd691cSlogin // self.running.lock().set(VecStatus::from(softirq_num), false); 179bacd691cSlogin // 将对应CPU的pending置0 180bacd691cSlogin compiler_fence(Ordering::SeqCst); 181e2841179SLoGin cpu_pending(smp_get_processor_id()).set(VecStatus::from(softirq_num), false); 182bacd691cSlogin compiler_fence(Ordering::SeqCst); 18362e46139SGou Ngai } 184bacd691cSlogin 185e2841179SLoGin #[inline(never)] 186bacd691cSlogin pub fn do_softirq(&self) { 1870d6cf65aSLoGin if self.cpu_running_count().get().load(Ordering::SeqCst) >= Self::MAX_RUNNING_PER_CPU { 1880d6cf65aSLoGin // 当前CPU的软中断嵌套层数已经达到最大值,不再执行 1890d6cf65aSLoGin return; 1900d6cf65aSLoGin } 1910d6cf65aSLoGin // 创建一个RunningCountGuard,当退出作用域时,会自动将cpu_running_count减1 1920d6cf65aSLoGin let _count_guard = RunningCountGuard::new(self.cpu_running_count()); 1930d6cf65aSLoGin 194bacd691cSlogin // TODO pcb的flags未修改 195bacd691cSlogin let end = clock() + 500 * 2; 196bacd691cSlogin let cpu_id = smp_get_processor_id(); 197bacd691cSlogin let mut max_restart = MAX_SOFTIRQ_RESTART; 198bacd691cSlogin loop { 199bacd691cSlogin compiler_fence(Ordering::SeqCst); 200e2841179SLoGin let pending = cpu_pending(cpu_id).bits; 201e2841179SLoGin cpu_pending(cpu_id).bits = 0; 202bacd691cSlogin compiler_fence(Ordering::SeqCst); 203bacd691cSlogin 20446e234aeSLoGin unsafe { CurrentIrqArch::interrupt_enable() }; 205bacd691cSlogin if pending != 0 { 206bacd691cSlogin for i in 0..MAX_SOFTIRQ_NUM { 207bacd691cSlogin if pending & (1 << i) == 0 { 20862e46139SGou Ngai continue; 20962e46139SGou Ngai } 210bacd691cSlogin 2110d6cf65aSLoGin let table_guard = self.table.read_irqsave(); 212bacd691cSlogin let softirq_func = table_guard[i as usize].clone(); 213bacd691cSlogin drop(table_guard); 214bacd691cSlogin if softirq_func.is_none() { 215bacd691cSlogin continue; 216bacd691cSlogin } 217bacd691cSlogin 2181496ba7bSLoGin let prev_count: usize = ProcessManager::current_pcb().preempt_count(); 219bacd691cSlogin 220bacd691cSlogin softirq_func.as_ref().unwrap().run(); 2211496ba7bSLoGin if unlikely(prev_count != ProcessManager::current_pcb().preempt_count()) { 222bacd691cSlogin kdebug!( 223bacd691cSlogin "entered softirq {:?} with preempt_count {:?},exited with {:?}", 224bacd691cSlogin i, 225bacd691cSlogin prev_count, 2261496ba7bSLoGin ProcessManager::current_pcb().preempt_count() 227bacd691cSlogin ); 2281496ba7bSLoGin unsafe { ProcessManager::current_pcb().set_preempt_count(prev_count) }; 229bacd691cSlogin } 230bacd691cSlogin } 231bacd691cSlogin } 23246e234aeSLoGin unsafe { CurrentIrqArch::interrupt_disable() }; 233bacd691cSlogin max_restart -= 1; 234bacd691cSlogin compiler_fence(Ordering::SeqCst); 235e2841179SLoGin if cpu_pending(cpu_id).is_empty() { 236bacd691cSlogin compiler_fence(Ordering::SeqCst); 237bacd691cSlogin if clock() < end && max_restart > 0 { 238bacd691cSlogin continue; 239bacd691cSlogin } else { 240bacd691cSlogin break; 241bacd691cSlogin } 242bacd691cSlogin } else { 243bacd691cSlogin // TODO:当有softirqd时 唤醒它 24462e46139SGou Ngai break; 24562e46139SGou Ngai } 24662e46139SGou Ngai } 24762e46139SGou Ngai } 24862e46139SGou Ngai 249bacd691cSlogin pub fn raise_softirq(&self, softirq_num: SoftirqNumber) { 2509550910aSChiichen let guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 251e2841179SLoGin let processor_id = smp_get_processor_id(); 252bacd691cSlogin 253bacd691cSlogin cpu_pending(processor_id).insert(VecStatus::from(softirq_num)); 254bacd691cSlogin 255bacd691cSlogin compiler_fence(Ordering::SeqCst); 256bacd691cSlogin 2579550910aSChiichen drop(guard); 258bacd691cSlogin // kdebug!("raise_softirq exited"); 25962e46139SGou Ngai } 260e2841179SLoGin 261e2841179SLoGin #[allow(dead_code)] 2628fd71f27Shoumkh pub unsafe fn clear_softirq_pending(&self, softirq_num: SoftirqNumber) { 263bacd691cSlogin compiler_fence(Ordering::SeqCst); 264e2841179SLoGin cpu_pending(smp_get_processor_id()).remove(VecStatus::from(softirq_num)); 265bacd691cSlogin compiler_fence(Ordering::SeqCst); 26662e46139SGou Ngai } 26762e46139SGou Ngai } 268bacd691cSlogin 2690d6cf65aSLoGin /// 当前CPU的软中断嵌套层数的计数器守卫 2700d6cf65aSLoGin /// 2710d6cf65aSLoGin /// 当进入作用域时,会自动将cpu_running_count加1, 2720d6cf65aSLoGin /// 当退出作用域时,会自动将cpu_running_count减1 2730d6cf65aSLoGin struct RunningCountGuard<'a> { 2740d6cf65aSLoGin cpu_running_count: &'a PerCpuVar<AtomicI16>, 2750d6cf65aSLoGin } 2760d6cf65aSLoGin 2770d6cf65aSLoGin impl<'a> RunningCountGuard<'a> { 2780d6cf65aSLoGin fn new(cpu_running_count: &'a PerCpuVar<AtomicI16>) -> RunningCountGuard { 2790d6cf65aSLoGin cpu_running_count.get().fetch_add(1, Ordering::SeqCst); 2800d6cf65aSLoGin return RunningCountGuard { cpu_running_count }; 2810d6cf65aSLoGin } 2820d6cf65aSLoGin } 2830d6cf65aSLoGin 2840d6cf65aSLoGin impl<'a> Drop for RunningCountGuard<'a> { 2850d6cf65aSLoGin fn drop(&mut self) { 2860d6cf65aSLoGin self.cpu_running_count.get().fetch_sub(1, Ordering::SeqCst); 2870d6cf65aSLoGin } 2880d6cf65aSLoGin } 2890d6cf65aSLoGin 290*f0c87a89SGnoCiYeH #[inline(never)] 291e2841179SLoGin pub fn do_softirq() { 292*f0c87a89SGnoCiYeH fence(Ordering::SeqCst); 293*f0c87a89SGnoCiYeH IrqTime::irqtime_start(); 294bacd691cSlogin softirq_vectors().do_softirq(); 295*f0c87a89SGnoCiYeH IrqTime::irqtime_account_irq(ProcessManager::current_pcb()); 296*f0c87a89SGnoCiYeH fence(Ordering::SeqCst); 297bacd691cSlogin } 298