fix: (riscv/timer): 修复riscv下没有更新墙上时钟以及没有处理软中断的bug (#783)

This commit is contained in:
LoGin
2024-04-28 19:40:09 +08:00
committed by GitHub
parent ab53b2eb75
commit 0722a06a09
4 changed files with 53 additions and 10 deletions

View File

@ -1,4 +1,4 @@
use core::sync::atomic::{fence, Ordering};
use core::sync::atomic::{compiler_fence, fence, Ordering};
use alloc::{string::ToString, sync::Arc};
use bitmap::{traits::BitMapOps, StaticBitmap};
@ -19,7 +19,12 @@ use crate::{
mm::percpu::PerCpu,
process::ProcessManager,
smp::core::smp_get_processor_id,
time::{clocksource::HZ, TimeArch},
time::{
clocksource::HZ,
jiffies::NSEC_PER_JIFFY,
timer::{try_raise_timer_softirq, update_timer_jiffies},
TimeArch,
},
};
pub struct RiscVSbiTimer;
@ -29,6 +34,13 @@ static SBI_TIMER_INIT_BMP: SpinLock<StaticBitmap<{ PerCpu::MAX_CPU_NUM as usize
static mut INTERVAL_CNT: usize = 0;
/// 已经过去的纳秒数
///
/// 0号核心用这个值来更新墙上时钟他只能被0号核心访问
static mut HART0_NSEC_PASSED: usize = 0;
/// hart0上一次更新墙上时钟的时间
static mut HART0_LAST_UPDATED: u64 = 0;
impl RiscVSbiTimer {
pub const TIMER_IRQ: IrqNumber = IrqNumber::from(5);
@ -39,8 +51,9 @@ impl RiscVSbiTimer {
// smp_get_processor_id().data(),
// CurrentTimeArch::get_cycles() as u64
// );
sbi_rt::set_timer(CurrentTimeArch::get_cycles() as u64 + unsafe { INTERVAL_CNT } as u64);
ProcessManager::update_process_times(trap_frame.is_from_user());
Self::update_nsec_passed_and_walltime();
sbi_rt::set_timer(CurrentTimeArch::get_cycles() as u64 + unsafe { INTERVAL_CNT } as u64);
Ok(())
}
@ -52,6 +65,30 @@ impl RiscVSbiTimer {
fn disable() {
unsafe { riscv::register::sie::clear_stimer() };
}
fn update_nsec_passed_and_walltime() {
if smp_get_processor_id().data() != 0 {
return;
}
let cycles = CurrentTimeArch::get_cycles() as u64;
let nsec_passed =
CurrentTimeArch::cycles2ns((cycles - unsafe { HART0_LAST_UPDATED }) as usize);
unsafe {
HART0_LAST_UPDATED = cycles;
HART0_NSEC_PASSED += nsec_passed;
}
let jiffies = unsafe { HART0_NSEC_PASSED } / NSEC_PER_JIFFY as usize;
unsafe { HART0_NSEC_PASSED %= NSEC_PER_JIFFY as usize };
update_timer_jiffies(
jiffies as u64,
(jiffies * NSEC_PER_JIFFY as usize / 1000) as i64,
);
try_raise_timer_softirq();
compiler_fence(Ordering::SeqCst);
}
}
/// riscv 初始化本地调度时钟源

View File

@ -10,6 +10,7 @@ use crate::{
irqdata::IrqData,
irqdesc::{irq_desc_manager, GenericIrqHandler},
irqdomain::{irq_domain_manager, IrqDomain, IrqDomainOps},
softirq::do_softirq,
HardwareIrqNumber, IrqNumber,
},
libs::spinlock::{SpinLock, SpinLockGuard},
@ -165,6 +166,7 @@ pub fn riscv_intc_irq(trap_frame: &mut TrapFrame) {
// kdebug!("riscv64_do_irq: interrupt {hwirq:?}");
GenericIrqHandler::handle_domain_irq(riscv_intc_domain().clone().unwrap(), hwirq, trap_frame)
.ok();
do_softirq();
if hwirq.data() == RiscVSbiTimer::TIMER_IRQ.data() {
__schedule(SchedMode::SM_PREEMPT);
}