chore: move setup_arch_post timepoint to before clocksource_boot_finish (#820)

This commit adjusts the timing of the setup_arch_post event to occur before the clocksource_boot_finish event, allowing the time subsystem to properly register architecture-specific clock sources.
This commit is contained in:
LoGin 2024-05-16 14:06:23 +08:00 committed by GitHub
parent 236e88d5ef
commit 92deae638b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 28 additions and 29 deletions

View File

@ -12,7 +12,7 @@ pub const ACPI_PM_MASK: u64 = 0xffffff;
pub fn acpi_pm_read_early() -> u32 { pub fn acpi_pm_read_early() -> u32 {
use crate::driver::clocksource::acpi_pm::{acpi_pm_read_verified, PMTMR_IO_PORT}; use crate::driver::clocksource::acpi_pm::{acpi_pm_read_verified, PMTMR_IO_PORT};
use core::sync::atomic::Ordering; use core::sync::atomic::Ordering;
let port = unsafe { PMTMR_IO_PORT.load(Ordering::SeqCst) }; let port = PMTMR_IO_PORT.load(Ordering::SeqCst);
// 如果端口为零直接返回 // 如果端口为零直接返回
if port == 0 { if port == 0 {

View File

@ -20,7 +20,7 @@ use system_error::SystemError;
// 参考https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/clocksource/acpi_pm.c // 参考https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/clocksource/acpi_pm.c
/// acpi_pmtmr所在的I/O端口 /// acpi_pmtmr所在的I/O端口
pub static mut PMTMR_IO_PORT: AtomicU32 = AtomicU32::new(0); pub static PMTMR_IO_PORT: AtomicU32 = AtomicU32::new(0);
/// # 读取acpi_pmtmr当前值并对齐进行掩码操作 /// # 读取acpi_pmtmr当前值并对齐进行掩码操作
#[inline(always)] #[inline(always)]
@ -206,12 +206,13 @@ fn find_acpi_pm_clock() -> Result<(), SystemError> {
let pm_timer_block = fadt.pm_timer_block().map_err(|_| SystemError::ENODEV)?; let pm_timer_block = fadt.pm_timer_block().map_err(|_| SystemError::ENODEV)?;
let pm_timer_block = pm_timer_block.ok_or(SystemError::ENODEV)?; let pm_timer_block = pm_timer_block.ok_or(SystemError::ENODEV)?;
let pmtmr_addr = pm_timer_block.address; let pmtmr_addr = pm_timer_block.address;
unsafe {
PMTMR_IO_PORT.store(pmtmr_addr as u32, Ordering::SeqCst); PMTMR_IO_PORT.store(pmtmr_addr as u32, Ordering::SeqCst);
}
kinfo!("apic_pmtmr I/O port: {}", unsafe { kinfo!(
"apic_pmtmr I/O port: {}",
PMTMR_IO_PORT.load(Ordering::SeqCst) PMTMR_IO_PORT.load(Ordering::SeqCst)
}); );
return Ok(()); return Ok(());
} }
@ -222,18 +223,19 @@ fn find_acpi_pm_clock() -> Result<(), SystemError> {
#[allow(dead_code)] #[allow(dead_code)]
pub fn init_acpi_pm_clocksource() -> Result<(), SystemError> { pub fn init_acpi_pm_clocksource() -> Result<(), SystemError> {
let acpi_pm = Acpipm::new(); let acpi_pm = Acpipm::new();
unsafe {
CLOCKSOURCE_ACPI_PM = Some(acpi_pm);
}
// 解析fadt // 解析fadt
find_acpi_pm_clock()?; find_acpi_pm_clock()?;
// 检查pmtmr_io_port是否被设置 // 检查pmtmr_io_port是否被设置
if unsafe { PMTMR_IO_PORT.load(Ordering::SeqCst) } == 0 { if PMTMR_IO_PORT.load(Ordering::SeqCst) == 0 {
return Err(SystemError::ENODEV); return Err(SystemError::ENODEV);
} }
unsafe {
CLOCKSOURCE_ACPI_PM = Some(acpi_pm);
}
// 验证ACPI PM Timer作为时钟源的稳定性和一致性 // 验证ACPI PM Timer作为时钟源的稳定性和一致性
for j in 0..ACPI_PM_MONOTONIC_CHECKS { for j in 0..ACPI_PM_MONOTONIC_CHECKS {
let mut cnt = 100 * j; let mut cnt = 100 * j;
@ -256,25 +258,23 @@ pub fn init_acpi_pm_clocksource() -> Result<(), SystemError> {
break; break;
} }
kinfo!("PM Timer had inconsistens results: {} {}", value1, value2); kinfo!("PM Timer had inconsistens results: {} {}", value1, value2);
unsafe {
PMTMR_IO_PORT.store(0, Ordering::SeqCst); PMTMR_IO_PORT.store(0, Ordering::SeqCst);
}
return Err(SystemError::EINVAL); return Err(SystemError::EINVAL);
} }
if i == ACPI_PM_READ_CHECKS { if i == ACPI_PM_READ_CHECKS {
kinfo!("PM Timer failed consistency check: {}", value1); kinfo!("PM Timer failed consistency check: {}", value1);
unsafe {
PMTMR_IO_PORT.store(0, Ordering::SeqCst); PMTMR_IO_PORT.store(0, Ordering::SeqCst);
}
return Err(SystemError::EINVAL); return Err(SystemError::EINVAL);
} }
} }
// 检查ACPI PM Timer的频率是否正确 // 检查ACPI PM Timer的频率是否正确
if !verify_pmtmr_rate() { if !verify_pmtmr_rate() {
unsafe { PMTMR_IO_PORT.store(0, Ordering::SeqCst);
PMTMR_IO_PORT.store(0, Ordering::SeqCst);
}
} }
// 检查TSC时钟源的监视器是否被禁用如果被禁用则将时钟源的标志设置为CLOCK_SOURCE_MUST_VERIFY // 检查TSC时钟源的监视器是否被禁用如果被禁用则将时钟源的标志设置为CLOCK_SOURCE_MUST_VERIFY

View File

@ -75,12 +75,11 @@ fn do_start_kernel() {
time_init(); time_init();
timer_init(); timer_init();
kthread_init(); kthread_init();
setup_arch_post().expect("setup_arch_post failed");
clocksource_boot_finish(); clocksource_boot_finish();
Futex::init(); Futex::init();
setup_arch_post().expect("setup_arch_post failed");
#[cfg(all(target_arch = "x86_64", feature = "kvm"))] #[cfg(all(target_arch = "x86_64", feature = "kvm"))]
crate::virt::kvm::kvm_init(); crate::virt::kvm::kvm_init();
} }

View File

@ -53,7 +53,7 @@ static mut WATCHDOG_KTHREAD: Option<Arc<ProcessControlBlock>> = None;
/// 正在被使用时钟源 /// 正在被使用时钟源
pub static CUR_CLOCKSOURCE: SpinLock<Option<Arc<dyn Clocksource>>> = SpinLock::new(None); pub static CUR_CLOCKSOURCE: SpinLock<Option<Arc<dyn Clocksource>>> = SpinLock::new(None);
/// 是否完成加载 /// 是否完成加载
pub static mut FINISHED_BOOTING: AtomicBool = AtomicBool::new(false); pub static FINISHED_BOOTING: AtomicBool = AtomicBool::new(false);
/// Interval: 0.5sec Threshold: 0.0625s /// Interval: 0.5sec Threshold: 0.0625s
/// 系统节拍率 /// 系统节拍率
@ -487,7 +487,7 @@ impl dyn Clocksource {
self.update_clocksource_data(cs_data)?; self.update_clocksource_data(cs_data)?;
// 启动watchdog线程 进行后续处理 // 启动watchdog线程 进行后续处理
if unsafe { FINISHED_BOOTING.load(Ordering::Relaxed) } { if FINISHED_BOOTING.load(Ordering::Relaxed) {
// TODO 在实现了工作队列后将启动线程换成schedule work // TODO 在实现了工作队列后将启动线程换成schedule work
run_watchdog_kthread(); run_watchdog_kthread();
} }
@ -948,7 +948,7 @@ pub fn clocksource_resume_watchdog() {
/// # 根据精度选择最优的时钟源,或者接受用户指定的时间源 /// # 根据精度选择最优的时钟源,或者接受用户指定的时间源
pub fn clocksource_select() { pub fn clocksource_select() {
let list_guard = CLOCKSOURCE_LIST.lock(); let list_guard = CLOCKSOURCE_LIST.lock();
if unsafe { FINISHED_BOOTING.load(Ordering::Relaxed) } || list_guard.is_empty() { if FINISHED_BOOTING.load(Ordering::Relaxed) || list_guard.is_empty() {
return; return;
} }
let mut best = list_guard.front().unwrap().clone(); let mut best = list_guard.front().unwrap().clone();
@ -971,21 +971,21 @@ pub fn clocksource_select() {
if cur_clocksource.clocksource_data().name.ne(best_name) { if cur_clocksource.clocksource_data().name.ne(best_name) {
kinfo!("Switching to the clocksource {:?}\n", best_name); kinfo!("Switching to the clocksource {:?}\n", best_name);
drop(cur_clocksource); drop(cur_clocksource);
CUR_CLOCKSOURCE.lock().replace(best); CUR_CLOCKSOURCE.lock().replace(best.clone());
// TODO 通知timerkeeping 切换了时间源 // TODO 通知timerkeeping 切换了时间源
} }
} else { } else {
// 当前时钟源为空 // 当前时钟源为空
CUR_CLOCKSOURCE.lock().replace(best); CUR_CLOCKSOURCE.lock().replace(best.clone());
} }
kdebug!(" clocksource_select finish"); kdebug!("clocksource_select finish, CUR_CLOCKSOURCE = {best:?}");
} }
/// # clocksource模块加载完成 /// # clocksource模块加载完成
pub fn clocksource_boot_finish() { pub fn clocksource_boot_finish() {
let mut cur_clocksource = CUR_CLOCKSOURCE.lock(); let mut cur_clocksource = CUR_CLOCKSOURCE.lock();
cur_clocksource.replace(clocksource_default_clock()); cur_clocksource.replace(clocksource_default_clock());
unsafe { FINISHED_BOOTING.store(true, Ordering::Relaxed) }; FINISHED_BOOTING.store(true, Ordering::Relaxed);
// 清除不稳定的时钟源 // 清除不稳定的时钟源
__clocksource_watchdog_kthread(); __clocksource_watchdog_kthread();
kdebug!("clocksource_boot_finish"); kdebug!("clocksource_boot_finish");