mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 19:36:47 +00:00
fix: (riscv/timer): 修复riscv下没有更新墙上时钟以及没有处理软中断的bug (#783)
This commit is contained in:
parent
ab53b2eb75
commit
0722a06a09
@ -19,7 +19,6 @@ use crate::{
|
|||||||
irqdata::IrqHandlerData,
|
irqdata::IrqHandlerData,
|
||||||
irqdesc::{IrqHandleFlags, IrqHandler, IrqReturn},
|
irqdesc::{IrqHandleFlags, IrqHandler, IrqReturn},
|
||||||
manage::irq_manager,
|
manage::irq_manager,
|
||||||
softirq::{softirq_vectors, SoftirqNumber},
|
|
||||||
InterruptArch, IrqNumber,
|
InterruptArch, IrqNumber,
|
||||||
},
|
},
|
||||||
kdebug, kerror, kinfo,
|
kdebug, kerror, kinfo,
|
||||||
@ -33,7 +32,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
time::{
|
time::{
|
||||||
jiffies::NSEC_PER_JIFFY,
|
jiffies::NSEC_PER_JIFFY,
|
||||||
timer::{clock, timer_get_first_expire, update_timer_jiffies},
|
timer::{try_raise_timer_softirq, update_timer_jiffies},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -252,11 +251,7 @@ impl Hpet {
|
|||||||
assert!(!CurrentIrqArch::is_irq_enabled());
|
assert!(!CurrentIrqArch::is_irq_enabled());
|
||||||
update_timer_jiffies(1, Self::HPET0_INTERVAL_USEC as i64);
|
update_timer_jiffies(1, Self::HPET0_INTERVAL_USEC as i64);
|
||||||
|
|
||||||
if let Ok(first_expire) = timer_get_first_expire() {
|
try_raise_timer_softirq();
|
||||||
if first_expire <= clock() {
|
|
||||||
softirq_vectors().raise_softirq(SoftirqNumber::TIMER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 alloc::{string::ToString, sync::Arc};
|
||||||
use bitmap::{traits::BitMapOps, StaticBitmap};
|
use bitmap::{traits::BitMapOps, StaticBitmap};
|
||||||
@ -19,7 +19,12 @@ use crate::{
|
|||||||
mm::percpu::PerCpu,
|
mm::percpu::PerCpu,
|
||||||
process::ProcessManager,
|
process::ProcessManager,
|
||||||
smp::core::smp_get_processor_id,
|
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;
|
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;
|
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 {
|
impl RiscVSbiTimer {
|
||||||
pub const TIMER_IRQ: IrqNumber = IrqNumber::from(5);
|
pub const TIMER_IRQ: IrqNumber = IrqNumber::from(5);
|
||||||
|
|
||||||
@ -39,8 +51,9 @@ impl RiscVSbiTimer {
|
|||||||
// smp_get_processor_id().data(),
|
// smp_get_processor_id().data(),
|
||||||
// CurrentTimeArch::get_cycles() as u64
|
// 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());
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,6 +65,30 @@ impl RiscVSbiTimer {
|
|||||||
fn disable() {
|
fn disable() {
|
||||||
unsafe { riscv::register::sie::clear_stimer() };
|
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 初始化本地调度时钟源
|
/// riscv 初始化本地调度时钟源
|
||||||
|
@ -10,6 +10,7 @@ use crate::{
|
|||||||
irqdata::IrqData,
|
irqdata::IrqData,
|
||||||
irqdesc::{irq_desc_manager, GenericIrqHandler},
|
irqdesc::{irq_desc_manager, GenericIrqHandler},
|
||||||
irqdomain::{irq_domain_manager, IrqDomain, IrqDomainOps},
|
irqdomain::{irq_domain_manager, IrqDomain, IrqDomainOps},
|
||||||
|
softirq::do_softirq,
|
||||||
HardwareIrqNumber, IrqNumber,
|
HardwareIrqNumber, IrqNumber,
|
||||||
},
|
},
|
||||||
libs::spinlock::{SpinLock, SpinLockGuard},
|
libs::spinlock::{SpinLock, SpinLockGuard},
|
||||||
@ -165,6 +166,7 @@ pub fn riscv_intc_irq(trap_frame: &mut TrapFrame) {
|
|||||||
// kdebug!("riscv64_do_irq: interrupt {hwirq:?}");
|
// kdebug!("riscv64_do_irq: interrupt {hwirq:?}");
|
||||||
GenericIrqHandler::handle_domain_irq(riscv_intc_domain().clone().unwrap(), hwirq, trap_frame)
|
GenericIrqHandler::handle_domain_irq(riscv_intc_domain().clone().unwrap(), hwirq, trap_frame)
|
||||||
.ok();
|
.ok();
|
||||||
|
do_softirq();
|
||||||
if hwirq.data() == RiscVSbiTimer::TIMER_IRQ.data() {
|
if hwirq.data() == RiscVSbiTimer::TIMER_IRQ.data() {
|
||||||
__schedule(SchedMode::SM_PREEMPT);
|
__schedule(SchedMode::SM_PREEMPT);
|
||||||
}
|
}
|
||||||
|
@ -357,6 +357,15 @@ pub fn timer_get_first_expire() -> Result<u64, SystemError> {
|
|||||||
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
|
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 检查是否需要触发定时器软中断,如果需要则触发
|
||||||
|
pub fn try_raise_timer_softirq() {
|
||||||
|
if let Ok(first_expire) = timer_get_first_expire() {
|
||||||
|
if first_expire <= clock() {
|
||||||
|
softirq_vectors().raise_softirq(SoftirqNumber::TIMER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 更新系统时间片
|
/// 更新系统时间片
|
||||||
pub fn update_timer_jiffies(add_jiffies: u64, time_us: i64) -> u64 {
|
pub fn update_timer_jiffies(add_jiffies: u64, time_us: i64) -> u64 {
|
||||||
let prev = TIMER_JIFFIES.fetch_add(add_jiffies, Ordering::SeqCst);
|
let prev = TIMER_JIFFIES.fetch_add(add_jiffies, Ordering::SeqCst);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user