feat: build system transition to release fork + archive hardening
Release fork infrastructure: - REDBEAR_RELEASE=0.1.1 with offline enforcement (fetch/distclean/unfetch blocked) - 195 BLAKE3-verified source archives in standard format - Atomic provisioning via provision-release.sh (staging + .complete sentry) - 5-phase improvement plan: restore format auto-detection, source tree validation (validate-source-trees.py), archive-map.json, REPO_BINARY fallback Archive normalization: - Removed 87 duplicate/unversioned archives from shared pool - Regenerated all archives in consistent format with source/ + recipe.toml - BLAKE3SUMS and manifest.json generated from stable tarball set Patch management: - verify-patches.sh: pre-sync dry-run report (OK/REVERSED/CONFLICT) - 121 upstream-absorbed patches moved to absorbed/ directories - 43 active patches verified clean against rebased sources - Stress test: base updated to upstream HEAD, relibc reset and patched Compilation fixes: - relibc: Vec imports in redox-rt (proc.rs, lib.rs, sys.rs) - relibc: unsafe from_raw_parts in mod.rs (2024 edition) - fetch.rs: rev comparison handles short/full hash prefixes - kibi recipe: corrected rev mismatch New scripts: restore-sources.sh, provision-release.sh, verify-sources-archived.sh, check-upstream-releases.sh, validate-source-trees.py, verify-patches.sh, repair-archive-format.sh, generate-manifest.py Documentation: AGENTS.md, README.md, local/AGENTS.md updated for release fork model
This commit is contained in:
@@ -0,0 +1,224 @@
|
||||
diff --git a/drivers/acpid/src/aml_physmem.rs b/drivers/acpid/src/aml_physmem.rs
|
||||
index 2bdd667b..69b8c48b 100644
|
||||
--- a/drivers/acpid/src/aml_physmem.rs
|
||||
+++ b/drivers/acpid/src/aml_physmem.rs
|
||||
@@ -6,7 +6,10 @@ use rustc_hash::FxHashMap;
|
||||
use std::fmt::LowerHex;
|
||||
use std::mem::size_of;
|
||||
use std::ptr::NonNull;
|
||||
-use std::sync::{Arc, Mutex};
|
||||
+use std::sync::atomic::{AtomicU32, Ordering};
|
||||
+use std::sync::{Arc, Condvar, Mutex};
|
||||
+use std::thread::ThreadId;
|
||||
+use std::time::{Duration, Instant};
|
||||
use syscall::PAGE_SIZE;
|
||||
|
||||
const PAGE_MASK: usize = !(PAGE_SIZE - 1);
|
||||
@@ -141,6 +144,20 @@ impl AmlPageCache {
|
||||
pub struct AmlPhysMemHandler {
|
||||
page_cache: Arc<Mutex<AmlPageCache>>,
|
||||
pci_fd: Arc<Option<libredox::Fd>>,
|
||||
+ aml_mutexes: Arc<Mutex<FxHashMap<u32, Arc<AmlMutex>>>>,
|
||||
+ next_mutex_handle: Arc<AtomicU32>,
|
||||
+}
|
||||
+
|
||||
+#[derive(Debug, Default)]
|
||||
+struct AmlMutexState {
|
||||
+ owner: Option<ThreadId>,
|
||||
+ depth: u32,
|
||||
+}
|
||||
+
|
||||
+#[derive(Debug, Default)]
|
||||
+struct AmlMutex {
|
||||
+ state: Mutex<AmlMutexState>,
|
||||
+ condvar: Condvar,
|
||||
}
|
||||
|
||||
/// Read from a physical address.
|
||||
@@ -156,6 +173,30 @@ impl AmlPhysMemHandler {
|
||||
Self {
|
||||
page_cache,
|
||||
pci_fd: Arc::new(pci_fd),
|
||||
+ aml_mutexes: Arc::new(Mutex::new(FxHashMap::default())),
|
||||
+ next_mutex_handle: Arc::new(AtomicU32::new(1)),
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ fn aml_mutex(&self, handle: Handle) -> Option<Arc<AmlMutex>> {
|
||||
+ self.aml_mutexes
|
||||
+ .lock()
|
||||
+ .unwrap_or_else(|poisoned| poisoned.into_inner())
|
||||
+ .get(&handle.0)
|
||||
+ .cloned()
|
||||
+ }
|
||||
+
|
||||
+ fn read_phys_or_fault<T>(&self, address: usize) -> T
|
||||
+ where
|
||||
+ T: PrimInt + LowerHex,
|
||||
+ {
|
||||
+ let mut page_cache = self
|
||||
+ .page_cache
|
||||
+ .lock()
|
||||
+ .unwrap_or_else(|poisoned| poisoned.into_inner());
|
||||
+ match page_cache.read_from_phys::<T>(address) {
|
||||
+ Ok(value) => value,
|
||||
+ Err(error) => panic!("AML physmem read failed at {:#x}: {}", address, error),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,43 +281,19 @@ impl acpi::Handler for AmlPhysMemHandler {
|
||||
|
||||
fn read_u8(&self, address: usize) -> u8 {
|
||||
log::trace!("read u8 {:X}", address);
|
||||
- if let Ok(mut page_cache) = self.page_cache.lock() {
|
||||
- if let Ok(value) = page_cache.read_from_phys::<u8>(address) {
|
||||
- return value;
|
||||
- }
|
||||
- }
|
||||
- log::error!("failed to read u8 {:#x}", address);
|
||||
- 0
|
||||
+ self.read_phys_or_fault::<u8>(address)
|
||||
}
|
||||
fn read_u16(&self, address: usize) -> u16 {
|
||||
log::trace!("read u16 {:X}", address);
|
||||
- if let Ok(mut page_cache) = self.page_cache.lock() {
|
||||
- if let Ok(value) = page_cache.read_from_phys::<u16>(address) {
|
||||
- return value;
|
||||
- }
|
||||
- }
|
||||
- log::error!("failed to read u16 {:#x}", address);
|
||||
- 0
|
||||
+ self.read_phys_or_fault::<u16>(address)
|
||||
}
|
||||
fn read_u32(&self, address: usize) -> u32 {
|
||||
log::trace!("read u32 {:X}", address);
|
||||
- if let Ok(mut page_cache) = self.page_cache.lock() {
|
||||
- if let Ok(value) = page_cache.read_from_phys::<u32>(address) {
|
||||
- return value;
|
||||
- }
|
||||
- }
|
||||
- log::error!("failed to read u32 {:#x}", address);
|
||||
- 0
|
||||
+ self.read_phys_or_fault::<u32>(address)
|
||||
}
|
||||
fn read_u64(&self, address: usize) -> u64 {
|
||||
log::trace!("read u64 {:X}", address);
|
||||
- if let Ok(mut page_cache) = self.page_cache.lock() {
|
||||
- if let Ok(value) = page_cache.read_from_phys::<u64>(address) {
|
||||
- return value;
|
||||
- }
|
||||
- }
|
||||
- log::error!("failed to read u64 {:#x}", address);
|
||||
- 0
|
||||
+ self.read_phys_or_fault::<u64>(address)
|
||||
}
|
||||
|
||||
fn write_u8(&self, address: usize, value: u8) {
|
||||
@@ -415,16 +432,102 @@ impl acpi::Handler for AmlPhysMemHandler {
|
||||
}
|
||||
|
||||
fn create_mutex(&self) -> Handle {
|
||||
- log::debug!("TODO: Handler::create_mutex");
|
||||
- Handle(0)
|
||||
+ let handle = self.next_mutex_handle.fetch_add(1, Ordering::Relaxed);
|
||||
+ self.aml_mutexes
|
||||
+ .lock()
|
||||
+ .unwrap_or_else(|poisoned| poisoned.into_inner())
|
||||
+ .insert(handle, Arc::new(AmlMutex::default()));
|
||||
+ log::trace!("created AML mutex handle {handle}");
|
||||
+ Handle(handle)
|
||||
}
|
||||
|
||||
fn acquire(&self, mutex: Handle, timeout: u16) -> Result<(), AmlError> {
|
||||
- log::debug!("TODO: Handler::acquire");
|
||||
- Ok(())
|
||||
+ let Some(aml_mutex) = self.aml_mutex(mutex) else {
|
||||
+ log::error!("attempted to acquire unknown AML mutex handle {}", mutex.0);
|
||||
+ return Err(AmlError::MutexAcquireTimeout);
|
||||
+ };
|
||||
+
|
||||
+ let current_thread = std::thread::current().id();
|
||||
+ let deadline = (timeout != 0xffff).then(|| Instant::now() + Duration::from_millis(timeout.into()));
|
||||
+
|
||||
+ let mut state = aml_mutex
|
||||
+ .state
|
||||
+ .lock()
|
||||
+ .unwrap_or_else(|poisoned| poisoned.into_inner());
|
||||
+
|
||||
+ loop {
|
||||
+ match state.owner {
|
||||
+ None => {
|
||||
+ state.owner = Some(current_thread);
|
||||
+ state.depth = 1;
|
||||
+ return Ok(());
|
||||
+ }
|
||||
+ Some(owner) if owner == current_thread => {
|
||||
+ state.depth = state.depth.saturating_add(1);
|
||||
+ return Ok(());
|
||||
+ }
|
||||
+ Some(_) if timeout == 0 => return Err(AmlError::MutexAcquireTimeout),
|
||||
+ Some(_) if timeout == 0xffff => {
|
||||
+ state = aml_mutex
|
||||
+ .condvar
|
||||
+ .wait(state)
|
||||
+ .unwrap_or_else(|poisoned| poisoned.into_inner());
|
||||
+ }
|
||||
+ Some(_) => {
|
||||
+ let Some(deadline) = deadline else {
|
||||
+ return Err(AmlError::MutexAcquireTimeout);
|
||||
+ };
|
||||
+ let now = Instant::now();
|
||||
+ if now >= deadline {
|
||||
+ return Err(AmlError::MutexAcquireTimeout);
|
||||
+ }
|
||||
+
|
||||
+ let remaining = deadline.saturating_duration_since(now);
|
||||
+ let (next_state, wait_result) = aml_mutex
|
||||
+ .condvar
|
||||
+ .wait_timeout(state, remaining)
|
||||
+ .unwrap_or_else(|poisoned| poisoned.into_inner());
|
||||
+ state = next_state;
|
||||
+
|
||||
+ if wait_result.timed_out() && state.owner != Some(current_thread) {
|
||||
+ return Err(AmlError::MutexAcquireTimeout);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
fn release(&self, mutex: Handle) {
|
||||
- log::debug!("TODO: Handler::release");
|
||||
+ let Some(aml_mutex) = self.aml_mutex(mutex) else {
|
||||
+ log::error!("attempted to release unknown AML mutex handle {}", mutex.0);
|
||||
+ return;
|
||||
+ };
|
||||
+
|
||||
+ let current_thread = std::thread::current().id();
|
||||
+ let mut state = aml_mutex
|
||||
+ .state
|
||||
+ .lock()
|
||||
+ .unwrap_or_else(|poisoned| poisoned.into_inner());
|
||||
+
|
||||
+ match state.owner {
|
||||
+ Some(owner) if owner == current_thread => {
|
||||
+ if state.depth > 1 {
|
||||
+ state.depth -= 1;
|
||||
+ } else {
|
||||
+ state.owner = None;
|
||||
+ state.depth = 0;
|
||||
+ aml_mutex.condvar.notify_one();
|
||||
+ }
|
||||
+ }
|
||||
+ Some(_) => {
|
||||
+ log::warn!(
|
||||
+ "ignoring AML mutex release for handle {} from non-owner thread",
|
||||
+ mutex.0
|
||||
+ );
|
||||
+ }
|
||||
+ None => {
|
||||
+ log::warn!("ignoring AML mutex release for unlocked handle {}", mutex.0);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user