From 861e6f88d23e136dca13eae4a8f376b4238be4e2 Mon Sep 17 00:00:00 2001 From: Admin Pupkin Date: Tue, 19 May 2026 23:50:32 +0300 Subject: [PATCH] driver-manager: fix scheme collision and scheme availability check; redox-driver-sys: CPU affinity logging; redbear-hwutils: timer characterization --- .../redox-driver-sys/source/src/irq.rs | 15 ++++++++--- .../recipes/system/driver-manager/recipe.toml | 13 +++++++++- .../driver-manager/source/src/config.rs | 20 ++++++++++++--- .../system/driver-manager/source/src/main.rs | 25 ++++++++++++++----- .../driver-manager/source/src/scheme.rs | 18 ++++++++----- .../src/bin/redbear-phase-timer-check.rs | 25 +++++++++++++++++++ 6 files changed, 97 insertions(+), 19 deletions(-) diff --git a/local/recipes/drivers/redox-driver-sys/source/src/irq.rs b/local/recipes/drivers/redox-driver-sys/source/src/irq.rs index 2ff9d2de27..18b72ffc86 100644 --- a/local/recipes/drivers/redox-driver-sys/source/src/irq.rs +++ b/local/recipes/drivers/redox-driver-sys/source/src/irq.rs @@ -291,12 +291,21 @@ fn read_cpu_count() -> Result { #[cfg(target_os = "redox")] fn alloc_cpu_id() -> u8 { match read_cpu_count() { - Ok(n) if n > 0 => { + Ok(0) => { + log::warn!("redox-driver-sys: read_cpu_count returned 0, defaulting to BSP (cpu 0)"); + 0 + } + Ok(n) => { use std::sync::atomic::{AtomicU8, Ordering}; static NEXT: AtomicU8 = AtomicU8::new(0); - NEXT.fetch_add(1, Ordering::Relaxed) % n + let cpu_id = NEXT.fetch_add(1, Ordering::Relaxed) % n; + log::debug!("redox-driver-sys: alloc_cpu_id selected cpu {} (of {})", cpu_id, n); + cpu_id + } + Err(err) => { + log::warn!("redox-driver-sys: read_cpu_count failed ({}), defaulting to BSP (cpu 0)", err); + 0 } - _ => 0, } } diff --git a/local/recipes/system/driver-manager/recipe.toml b/local/recipes/system/driver-manager/recipe.toml index aa70b1f2ee..33011bc243 100644 --- a/local/recipes/system/driver-manager/recipe.toml +++ b/local/recipes/system/driver-manager/recipe.toml @@ -2,7 +2,18 @@ path = "source" [build] -template = "cargo" +template = "custom" +script = """ +# driver-manager runs in both rootfs and initfs; initfs has no dynamic linker, +# so we must build a statically linked binary. +export RUSTFLAGS="${RUSTFLAGS} -Ctarget-feature=+crt-static -L native=${COOKBOOK_SYSROOT}/lib" +"${COOKBOOK_CARGO}" build \ + --manifest-path "${COOKBOOK_SOURCE}/Cargo.toml" \ + --target "${TARGET}" \ + ${build_flags} +mkdir -pv "${COOKBOOK_STAGE}/usr/bin" +cp -v "target/${TARGET}/${build_type}/driver-manager" "${COOKBOOK_STAGE}/usr/bin/driver-manager" +""" [dependencies] redox-driver-core = {} diff --git a/local/recipes/system/driver-manager/source/src/config.rs b/local/recipes/system/driver-manager/source/src/config.rs index bba57a2585..83bcb52a7b 100644 --- a/local/recipes/system/driver-manager/source/src/config.rs +++ b/local/recipes/system/driver-manager/source/src/config.rs @@ -176,10 +176,24 @@ fn open_pcid_channel(device_path: &str) -> Result { } fn check_scheme_available(name: &str) -> bool { - if std::path::Path::new(&format!("/scheme/{}", name)).exists() { - return true; + let path = format!("/scheme/{}", name); + // Use read_dir instead of Path::exists() because Redox scheme paths + // may not respond correctly to exists()/metadata() while still being + // fully functional for directory enumeration and file open. + // This was the root cause of "dependency scheme not ready: pci" even + // though PciBus::enumerate_devices (which uses read_dir) succeeded. + match fs::read_dir(&path) { + Ok(_) => true, + Err(err) => { + log::debug!( + "driver-manager: scheme availability check failed for {}: {} (exists={})", + path, + err, + std::path::Path::new(&path).exists() + ); + false + } } - false } impl Driver for DriverConfig { diff --git a/local/recipes/system/driver-manager/source/src/main.rs b/local/recipes/system/driver-manager/source/src/main.rs index 4dd640ca03..1d1291f4a4 100644 --- a/local/recipes/system/driver-manager/source/src/main.rs +++ b/local/recipes/system/driver-manager/source/src/main.rs @@ -52,6 +52,7 @@ impl log::Log for StderrLogger { fn run_enumeration( manager: &Arc>, scheme: &DriverManagerScheme, + initfs: bool, ) -> (usize, usize) { let enum_start = Instant::now(); let events = match manager.lock() { @@ -92,7 +93,11 @@ fn run_enumeration( log::info!("bus {} enumerated {} device(s)", bus, device_count); } ProbeEvent::BusEnumerationFailed { bus, error } => { - log::error!("bus {} enumeration failed: {:?}", bus, error); + if initfs && *bus == "pci" { + log::warn!("bus {} enumeration not yet ready (initfs, pcid may still be starting): {:?}", bus, error); + } else { + log::error!("bus {} enumeration failed: {:?}", bus, error); + } } ProbeEvent::AlreadyBound { device, @@ -418,7 +423,7 @@ fn main() { if manager_config.async_probe { let handle = thread::spawn(move || { - let (bound, deferred) = run_enumeration(&mgr_clone, scheme_clone.as_ref()); + let (bound, deferred) = run_enumeration(&mgr_clone, scheme_clone.as_ref(), initfs); log::info!("async enum: {} bound, {} deferred", bound, deferred); }); if handle.join().is_err() { @@ -426,13 +431,21 @@ fn main() { process::exit(1); } } else { - let (bound, deferred) = run_enumeration(&manager, scheme.as_ref()); + let (bound, deferred) = run_enumeration(&manager, scheme.as_ref(), initfs); log::info!("enum complete: {} bound, {} deferred", bound, deferred); } - if let Err(err) = scheme::start_scheme_server(Arc::clone(&scheme)) { - log::error!("{err}"); - process::exit(1); + match scheme::start_scheme_server(Arc::clone(&scheme)) { + Ok(true) => { + log::info!("driver-manager: scheme server started successfully"); + } + Ok(false) => { + log::warn!("driver-manager: scheme already registered — another instance is active, continuing without scheme server"); + } + Err(err) => { + log::error!("{err}"); + process::exit(1); + } } if hotplug_mode { diff --git a/local/recipes/system/driver-manager/source/src/scheme.rs b/local/recipes/system/driver-manager/source/src/scheme.rs index 8b4beb2de9..2b15667857 100644 --- a/local/recipes/system/driver-manager/source/src/scheme.rs +++ b/local/recipes/system/driver-manager/source/src/scheme.rs @@ -425,13 +425,19 @@ pub fn notify_unbind(scheme: &DriverManagerScheme, pci_addr: &str) { } #[cfg(target_os = "redox")] -pub fn start_scheme_server(scheme: Arc) -> std::result::Result<(), String> { +pub fn start_scheme_server(scheme: Arc) -> std::result::Result { let socket = Socket::create() .map_err(|err| format!("driver-manager: failed to create scheme socket: {err}"))?; let mut server = SchemeServer::new(scheme); - register_sync_scheme(&socket, SCHEME_NAME, &mut server) - .map_err(|err| format!("driver-manager: failed to register scheme:{SCHEME_NAME}: {err}"))?; + if let Err(err) = register_sync_scheme(&socket, SCHEME_NAME, &mut server) { + let msg = format!("{err}"); + if msg.contains("File exists") { + log::warn!("driver-manager: scheme:{SCHEME_NAME} already registered (initfs instance active), returning gracefully"); + return Ok(false); + } + return Err(format!("driver-manager: failed to register scheme:{SCHEME_NAME}: {err}")); + } log::info!("driver-manager: registered scheme:{SCHEME_NAME}"); @@ -464,10 +470,10 @@ pub fn start_scheme_server(scheme: Arc) -> std::result::Res }) .map_err(|err| format!("driver-manager: failed to spawn scheme server thread: {err}"))?; - Ok(()) + Ok(true) } #[cfg(not(target_os = "redox"))] -pub fn start_scheme_server(_scheme: Arc) -> std::result::Result<(), String> { - Ok(()) +pub fn start_scheme_server(_scheme: Arc) -> std::result::Result { + Ok(true) } diff --git a/local/recipes/system/redbear-hwutils/source/src/bin/redbear-phase-timer-check.rs b/local/recipes/system/redbear-hwutils/source/src/bin/redbear-phase-timer-check.rs index cae1b75ecd..04dc2d288b 100644 --- a/local/recipes/system/redbear-hwutils/source/src/bin/redbear-phase-timer-check.rs +++ b/local/recipes/system/redbear-hwutils/source/src/bin/redbear-phase-timer-check.rs @@ -47,6 +47,16 @@ fn timespec_to_nanos(time: &TimeSpec) -> i128 { i128::from(time.tv_sec) * 1_000_000_000i128 + i128::from(time.tv_nsec) } +fn check_timer_source(name: &str, path: &str) -> &'static str { + if Path::new(path).exists() { + println!("timer_source={} path={} present=1", name, path); + "present" + } else { + println!("timer_source={} path={} present=0", name, path); + "missing" + } +} + fn run() -> Result<(), String> { parse_args(PROGRAM, USAGE, std::env::args()).map_err(|err| { if err.is_empty() { @@ -57,6 +67,10 @@ fn run() -> Result<(), String> { println!("=== Red Bear OS Timer Runtime Check ==="); + check_timer_source("hpet", "/scheme/sys/hpet"); + check_timer_source("pit", "/scheme/sys/pit"); + check_timer_source("lapic", "/scheme/sys/lapic"); + let time_path = monotonic_path()?; let time_fd = Fd::open(&time_path, flag::O_RDWR, 0) @@ -78,6 +92,17 @@ fn run() -> Result<(), String> { return Err("monotonic timer did not advance".to_string()); } + let expected_ns: i128 = 50_000_000; + let deviation_ns = (delta_ns - expected_ns).abs(); + println!("monotonic_expected_ns={expected_ns}"); + println!("monotonic_deviation_ns={deviation_ns}"); + + if deviation_ns > 20_000_000 { + println!("timer_precision=coarse deviation_ns={deviation_ns} (threshold=20000000)"); + } else { + println!("timer_precision=ok deviation_ns={deviation_ns} (threshold=20000000)"); + } + println!("monotonic_progress=ok"); Ok(()) }