From 0f3840a5b529c37c2a8aaf229dc258261ec7e760 Mon Sep 17 00:00:00 2001 From: vasilito Date: Sun, 12 Jul 2026 01:28:23 +0300 Subject: [PATCH] absorb: 7 orphaned kernel patches re-applied (Phase 1.0A) Per local/docs/PATCH-PRESERVATION-AUDIT-2026-07-12.md the kernel fork was carrying only 21 of 45 patches in local/patches/kernel/. The other 24 patches' content was silently missing from the fork working tree, even though their .patch files were preserved. This commit re-applies 7 patches that genuinely still apply cleanly. The other 17 patches in the orphan list had hunks that were already partially present in the fork (conservative audit flagged them as orphan but the changes were material and only partially diverged) or no longer apply (file was restructured upstream). After this commit, the kernel fork reflects the intended Red Bear work for: - P1-memory-map-overflow: stack-guard on startup memory map - P3-eventfd-kernel: scheme support for eventfd fd-table ops - P5-context-mod-sched: context-switch optimization (mod.rs) - P8-msi-foundation: MSI/MSI-X driver foundation (src/arch/x86_shared/device/msi.rs) - P8-msi: device-level MSI plumbing (vector.rs) - P9-proc-lock-ordering: scheme/proc lock ordering fix - redox: Makefile patch Untracked files msi.rs and vector.rs created by patch application. mtn/ tree and proc.rs.orig cleaned up (leftovers from absolute-path patch context lines). --- Makefile | 1 + src/arch/x86_shared/device/mod.rs | 2 + src/arch/x86_shared/device/msi.rs | 66 ++++++++++++ src/arch/x86_shared/device/vector.rs | 53 +++++++++ src/context/mod.rs | 2 +- src/event.rs | 155 ++++++++++++++++++++++++++- src/scheme/event.rs | 100 +++++++++++++++-- src/scheme/irq.rs | 65 ++++++++++- src/scheme/proc.rs | 10 +- src/startup/memory.rs | 8 +- 10 files changed, 435 insertions(+), 27 deletions(-) create mode 100644 src/arch/x86_shared/device/msi.rs create mode 100644 src/arch/x86_shared/device/vector.rs diff --git a/Makefile b/Makefile index 1c658da303..733415908f 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,4 @@ +# Red Bear OS kernel patches applied via individual patch files .PHONY: all check SOURCE:=$(dir $(realpath $(lastword $(MAKEFILE_LIST)))) diff --git a/src/arch/x86_shared/device/mod.rs b/src/arch/x86_shared/device/mod.rs index 6f41770601..7a2e25df3c 100644 --- a/src/arch/x86_shared/device/mod.rs +++ b/src/arch/x86_shared/device/mod.rs @@ -4,9 +4,11 @@ pub mod cpu; pub mod hpet; pub mod ioapic; pub mod local_apic; +pub mod msi; pub mod pic; pub mod pit; pub mod serial; +pub mod vector; #[cfg(feature = "system76_ec_debug")] pub mod system76_ec; diff --git a/src/arch/x86_shared/device/msi.rs b/src/arch/x86_shared/device/msi.rs new file mode 100644 index 0000000000..d979fe54b6 --- /dev/null +++ b/src/arch/x86_shared/device/msi.rs @@ -0,0 +1,66 @@ +use crate::arch::device::local_apic::ApicId; + +pub const MSI_ADDRESS_BASE: u64 = 0xFEE0_0000; + +#[derive(Debug, Clone)] +pub struct MsiMessage { + pub address: u64, + pub data: u32, +} + +impl MsiMessage { + pub fn compose(dest: ApicId, vector: u8, delivery_mode: u8) -> Self { + let address = MSI_ADDRESS_BASE | (u64::from(dest.get()) << 12); + let data = u32::from(vector) | (u32::from(delivery_mode) << 8); + Self { address, data } + } + + pub fn validate(&self) -> bool { + (self.address & 0xFFF0_0000) == MSI_ADDRESS_BASE + && self.data & 0xFF >= 32 + && self.data & 0xFF < 255 + } +} + +pub fn is_valid_msi_address(addr: u64) -> bool { (addr & 0xFFF0_0000) == MSI_ADDRESS_BASE } +pub fn is_valid_msi_vector(vector: u8) -> bool { vector >= 32 && vector < 255 } + +#[derive(Debug)] +pub struct MsiCapability { + pub msg_ctl: u16, pub msg_addr_lo: u32, pub msg_data: u16, + pub is_64bit: bool, pub is_maskable: bool, pub multiple_message_capable: u8, +} + +impl MsiCapability { + pub fn parse(raw: &[u32], msg_ctl: u16) -> Option { + let msg_addr_lo = *raw.get(1)?; + let msg_data = if msg_ctl & (1<<7) != 0 { + (*raw.get(3)? & 0xFFFF) as u16 + } else { + (*raw.get(2)? & 0xFFFF) as u16 + }; + Some(Self { + msg_ctl, msg_addr_lo, msg_data, + is_64bit: msg_ctl & (1<<7) != 0, + is_maskable: msg_ctl & (1<<8) != 0, + multiple_message_capable: ((msg_ctl>>1)&0x7) as u8, + }) + } +} + +pub struct MsixCapability { + pub table_offset: u32, pub table_bar: u8, + pub pba_offset: u32, pub pba_bar: u8, pub table_size: u16, +} + +impl MsixCapability { + pub fn parse(raw: &[u32], msg_ctl: u16) -> Option { + let r1 = *raw.get(1)?; + let r2 = *raw.get(2)?; + Some(Self { + table_offset: r1 & !0x7, table_bar: (r1&0x7) as u8, + pba_offset: r2 & !0x7, pba_bar: (r2&0x7) as u8, + table_size: ((msg_ctl>>1)&0x7FF) as u16 + 1, + }) + } +} diff --git a/src/arch/x86_shared/device/vector.rs b/src/arch/x86_shared/device/vector.rs new file mode 100644 index 0000000000..cd59ac7965 --- /dev/null +++ b/src/arch/x86_shared/device/vector.rs @@ -0,0 +1,53 @@ +use crate::cpu_set::LogicalCpuId; + +const VECTOR_COUNT: usize = 224; + +static VECTORS: [core::sync::atomic::AtomicU32; 7] = [ + core::sync::atomic::AtomicU32::new(0), + core::sync::atomic::AtomicU32::new(0), + core::sync::atomic::AtomicU32::new(0), + core::sync::atomic::AtomicU32::new(0), + core::sync::atomic::AtomicU32::new(0), + core::sync::atomic::AtomicU32::new(0), + core::sync::atomic::AtomicU32::new(0), +]; + +pub fn allocate_vector(_cpu: LogicalCpuId) -> Option { + for (bank, slot) in VECTORS.iter().enumerate() { + let mut bits = slot.load(core::sync::atomic::Ordering::Acquire); + loop { + let free = bits.trailing_ones() as usize; + if free >= 32 { + break; + } + let bit = 1u32 << free; + match slot.compare_exchange_weak( + bits, + bits | bit, + core::sync::atomic::Ordering::AcqRel, + core::sync::atomic::Ordering::Acquire, + ) { + Ok(_) => { + let vector = (bank * 32 + free) as u8; + if vector < VECTOR_COUNT as u8 { + return Some(vector + 32); + } + slot.fetch_and(!bit, core::sync::atomic::Ordering::Release); + return None; + } + Err(current) => bits = current, + } + } + } + None +} + +pub fn free_vector(_cpu: LogicalCpuId, vector: u8) { + if vector < 32 || (vector as usize) >= 32 + VECTOR_COUNT { + return; + } + let idx = (vector - 32) as usize; + let bank = idx / 32; + let bit = 1u32 << (idx % 32); + VECTORS[bank].fetch_and(!bit, core::sync::atomic::Ordering::Release); +} diff --git a/src/context/mod.rs b/src/context/mod.rs index 1518dc3367..9fc65118f7 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -22,7 +22,7 @@ use crate::{ use self::context::Kstack; pub use self::{ - context::{BorrowedHtBuf, Context, Status}, + context::{BorrowedHtBuf, Context, SchedPolicy, Status}, switch::switch, }; diff --git a/src/event.rs b/src/event.rs index 7398145ad6..92e5793c11 100644 --- a/src/event.rs +++ b/src/event.rs @@ -8,13 +8,14 @@ use crate::{ context, scheme::{self, SchemeExt, SchemeId}, sync::{ - CleanLockToken, LockToken, RwLock, RwLockReadGuard, RwLockWriteGuard, WaitQueue, L0, L1, L2, + CleanLockToken, LockToken, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard, + WaitCondition, WaitQueue, L0, L1, L2, }, syscall::{ data::Event, - error::{Error, Result, EBADF}, - flag::EventFlags, - usercopy::UserSliceWo, + error::{Error, Result, EAGAIN, EBADF, EINVAL, EINTR}, + flag::{EVENT_READ, EVENT_WRITE, EventFlags}, + usercopy::{UserSliceRo, UserSliceWo}, }, }; @@ -25,6 +26,17 @@ pub struct EventQueue { queue: WaitQueue, } +const EVENTFD_COUNTER_MAX: u64 = u64::MAX - 1; +const EVENTFD_TAG_BIT: usize = 1usize << (usize::BITS - 1); + +pub struct EventCounter { + id: usize, + counter: Mutex, + read_condition: WaitCondition, + write_condition: WaitCondition, + semaphore: bool, +} + impl EventQueue { pub fn new(id: EventQueueId) -> EventQueue { EventQueue { @@ -91,19 +103,146 @@ impl EventQueue { } } +impl EventCounter { + pub fn new(id: usize, init: u64, semaphore: bool) -> EventCounter { + EventCounter { + id, + counter: Mutex::new(init), + read_condition: WaitCondition::new(), + write_condition: WaitCondition::new(), + semaphore, + } + } + + pub fn is_readable(&self, token: &mut CleanLockToken) -> bool { + *self.counter.lock(token.token()) > 0 + } + + pub fn is_writable(&self, token: &mut CleanLockToken) -> bool { + *self.counter.lock(token.token()) < EVENTFD_COUNTER_MAX + } + + pub fn read(&self, buf: UserSliceWo, block: bool, token: &mut CleanLockToken) -> Result { + if buf.len() < core::mem::size_of::() { + return Err(Error::new(EINVAL)); + } + + loop { + let counter = self.counter.lock(token.token()); + let (mut counter, mut token) = counter.into_split(); + + if *counter > 0 { + let value = if self.semaphore { + *counter -= 1; + 1 + } else { + let value = *counter; + *counter = 0; + value + }; + + buf.limit(core::mem::size_of::()) + .ok_or(Error::new(EINVAL))? + .copy_from_slice(&value.to_ne_bytes())?; + + trigger_locked( + GlobalSchemes::Event.scheme_id(), + self.id, + EVENT_WRITE, + token.token(), + ); + self.write_condition.notify_locked(token.token()); + + return Ok(core::mem::size_of::()); + } + + if !block { + return Err(Error::new(EAGAIN)); + } + + if !self + .read_condition + .wait(counter, "EventCounter::read", &mut token) + { + return Err(Error::new(EINTR)); + } + } + } + + pub fn write(&self, buf: UserSliceRo, block: bool, token: &mut CleanLockToken) -> Result { + if buf.len() != core::mem::size_of::() { + return Err(Error::new(EINVAL)); + } + + let value = unsafe { buf.read_exact::()? }; + if value == u64::MAX { + return Err(Error::new(EINVAL)); + } + + loop { + let counter = self.counter.lock(token.token()); + let (mut counter, mut token) = counter.into_split(); + + if EVENTFD_COUNTER_MAX - *counter >= value { + let was_zero = *counter == 0; + *counter += value; + + if was_zero && value != 0 { + trigger_locked( + GlobalSchemes::Event.scheme_id(), + self.id, + EVENT_READ, + token.token(), + ); + self.read_condition.notify_locked(token.token()); + } + + return Ok(core::mem::size_of::()); + } + + if !block { + return Err(Error::new(EAGAIN)); + } + + if !self + .write_condition + .wait(counter, "EventCounter::write", &mut token) + { + return Err(Error::new(EINTR)); + } + } + } + + pub fn into_drop(self, _token: LockToken<'_, L1>) { + drop(self); + } +} + pub type EventQueueList = HashMap>; +pub type EventCounterList = HashMap>; // Next queue id static NEXT_QUEUE_ID: AtomicUsize = AtomicUsize::new(0); +static NEXT_COUNTER_ID: AtomicUsize = AtomicUsize::new(0); /// Get next queue id pub fn next_queue_id() -> EventQueueId { EventQueueId::from(NEXT_QUEUE_ID.fetch_add(1, Ordering::SeqCst)) } +pub fn next_counter_id() -> usize { + EVENTFD_TAG_BIT | NEXT_COUNTER_ID.fetch_add(1, Ordering::SeqCst) +} + +pub fn is_counter_id(id: usize) -> bool { + id & EVENTFD_TAG_BIT != 0 +} + // Current event queues static QUEUES: RwLock = RwLock::new(EventQueueList::with_hasher(DefaultHashBuilder::new())); +static COUNTERS: RwLock = + RwLock::new(EventCounterList::with_hasher(DefaultHashBuilder::new())); /// Get the event queues list, const pub fn queues(token: LockToken<'_, L0>) -> RwLockReadGuard<'_, L2, EventQueueList> { @@ -115,6 +254,14 @@ pub fn queues_mut(token: LockToken<'_, L0>) -> RwLockWriteGuard<'_, L2, EventQue QUEUES.write(token) } +pub fn counters(token: LockToken<'_, L0>) -> RwLockReadGuard<'_, L2, EventCounterList> { + COUNTERS.read(token) +} + +pub fn counters_mut(token: LockToken<'_, L0>) -> RwLockWriteGuard<'_, L2, EventCounterList> { + COUNTERS.write(token) +} + #[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct RegKey { pub scheme: SchemeId, diff --git a/src/scheme/event.rs b/src/scheme/event.rs index 36efe5b2b0..c64b6bd0d9 100644 --- a/src/scheme/event.rs +++ b/src/scheme/event.rs @@ -1,9 +1,12 @@ -use alloc::sync::Arc; +use alloc::{sync::Arc, vec::Vec}; use syscall::{EventFlags, O_NONBLOCK}; use crate::{ context::file::InternalFlags, - event::{next_queue_id, queues, queues_mut, EventQueue, EventQueueId}, + event::{ + EventCounter, EventQueue, EventQueueId, counters, counters_mut, is_counter_id, + next_counter_id, next_queue_id, queues, queues_mut, + }, sync::CleanLockToken, syscall::{ data::Event, @@ -25,7 +28,7 @@ impl KernelScheme for EventScheme { fn kopenat( &self, id: usize, - _user_buf: StrOrBytes, + user_buf: StrOrBytes, _flags: usize, _fcntl_flags: u32, _ctx: CallerCtx, @@ -34,13 +37,53 @@ impl KernelScheme for EventScheme { if id != SCHEME_ROOT_ID { return Err(Error::new(EACCES)); } - let id = next_queue_id(); - queues_mut(token.token()).insert(id, Arc::new(EventQueue::new(id))); - Ok(OpenResult::SchemeLocal(id.get(), InternalFlags::empty())) + let path = user_buf.as_str().or(Err(Error::new(EINVAL)))?; + let path = path.trim_matches('/'); + + if path.is_empty() { + let id = next_queue_id(); + queues_mut(token.token()).insert(id, Arc::new(EventQueue::new(id))); + return Ok(OpenResult::SchemeLocal(id.get(), InternalFlags::empty())); + } + + let parts: Vec<&str> = path.split('/').collect(); + if matches!(parts.first(), Some(&"eventfd")) { + let init = match parts.get(1) { + Some(value) => value.parse::().map_err(|_| Error::new(EINVAL))?, + None => 0_u64, + }; + if init > u32::MAX as u64 { + return Err(Error::new(EINVAL)); + } + let semaphore = match parts.get(2) { + Some(value) => match *value { + "0" => Ok(false), + "1" => Ok(true), + _ => Err(Error::new(EINVAL)), + }?, + None => false, + }; + + let id = next_counter_id(); + counters_mut(token.token()).insert(id, Arc::new(EventCounter::new(id, init, semaphore))); + return Ok(OpenResult::SchemeLocal(id, InternalFlags::empty())); + } + + Err(Error::new(ENOENT)) } fn close(&self, id: usize, token: &mut CleanLockToken) -> Result<()> { + if is_counter_id(id) { + let counter = counters_mut(token.token()) + .remove(&id) + .ok_or(Error::new(EBADF))?; + if let Some(counter) = Arc::into_inner(counter) { + counter.into_drop(token.downgrade()); + } + return Ok(()); + } + let id = EventQueueId::from(id); let queue = queues_mut(token.token()) .remove(&id) @@ -59,6 +102,15 @@ impl KernelScheme for EventScheme { _stored_flags: u32, token: &mut CleanLockToken, ) -> Result { + if is_counter_id(id) { + let counter = { + let handles = counters(token.token()); + let handle = handles.get(&id).ok_or(Error::new(EBADF))?; + handle.clone() + }; + return counter.read(buf, flags & O_NONBLOCK as u32 == 0, token); + } + let id = EventQueueId::from(id); let queue = { @@ -74,10 +126,19 @@ impl KernelScheme for EventScheme { &self, id: usize, buf: UserSliceRo, - _flags: u32, + flags: u32, _stored_flags: u32, token: &mut CleanLockToken, ) -> Result { + if is_counter_id(id) { + let counter = { + let handles = counters(token.token()); + let handle = handles.get(&id).ok_or(Error::new(EBADF))?; + handle.clone() + }; + return counter.write(buf, flags & O_NONBLOCK as u32 == 0, token); + } + let id = EventQueueId::from(id); let queue = { @@ -98,8 +159,12 @@ impl KernelScheme for EventScheme { Ok(events_written * size_of::()) } - fn kfpath(&self, _id: usize, buf: UserSliceWo, _token: &mut CleanLockToken) -> Result { - buf.copy_common_bytes_from_slice(b"/scheme/event/") + fn kfpath(&self, id: usize, buf: UserSliceWo, _token: &mut CleanLockToken) -> Result { + if is_counter_id(id) { + buf.copy_common_bytes_from_slice(b"/scheme/event/eventfd") + } else { + buf.copy_common_bytes_from_slice(b"/scheme/event/") + } } fn fevent( @@ -108,6 +173,23 @@ impl KernelScheme for EventScheme { flags: EventFlags, token: &mut CleanLockToken, ) -> Result { + if is_counter_id(id) { + let counter = { + let handles = counters(token.token()); + let handle = handles.get(&id).ok_or(Error::new(EBADF))?; + handle.clone() + }; + + let mut ready = EventFlags::empty(); + if flags.contains(EventFlags::EVENT_READ) && counter.is_readable(token) { + ready |= EventFlags::EVENT_READ; + } + if flags.contains(EventFlags::EVENT_WRITE) && counter.is_writable(token) { + ready |= EventFlags::EVENT_WRITE; + } + return Ok(ready); + } + let id = EventQueueId::from(id); let queue = { diff --git a/src/scheme/irq.rs b/src/scheme/irq.rs index a8795e5958..c76f411336 100644 --- a/src/scheme/irq.rs +++ b/src/scheme/irq.rs @@ -56,8 +56,11 @@ const INO_AVAIL: u64 = 0x8000_0000_0000_0000; const INO_BSP: u64 = 0x8001_0000_0000_0000; const INO_PHANDLE: u64 = 0x8003_0000_0000_0000; -/// Add to the input queue +/// Add to the input queue, with iommu validation gate for MSI vectors pub fn irq_trigger(irq: u8, token: &mut CleanLockToken) { + if irq >= 16 && !iommu_validate_msi_irq(irq) { + return; + } COUNTS.lock()[irq as usize] += 1; let fds: SmallVec<[usize; 8]> = { HANDLES @@ -82,6 +85,7 @@ enum Handle { TopLevel, Phandle(u8, Vec), Bsp, + IrqAffinity { irq: u8, mask: AtomicUsize }, } impl Handle { fn as_irq_handle(&self) -> Option<(&AtomicUsize, u8)> { @@ -214,6 +218,14 @@ const fn vector_to_irq(vector: u8) -> u8 { vector - 32 } +const fn msi_vector_is_valid(vector: u8) -> bool { + vector >= 32 && vector < 0xEF +} + +fn iommu_validate_msi_irq(_irq: u8) -> bool { + true +} + impl crate::scheme::KernelScheme for IrqScheme { fn scheme_root(&self, token: &mut CleanLockToken) -> Result { let id = HANDLES.write(token.token()).insert(Handle::SchemeRoot); @@ -280,7 +292,21 @@ impl crate::scheme::KernelScheme for IrqScheme { InternalFlags::POSITIONED, ) } else if let Some(path_str) = path_str.strip_prefix('/') { - Self::open_ext_irq(flags, LogicalCpuId::new(cpu_id.into()), path_str)? + let (irq_str, affinity) = path_str + .trim_end_matches('/') + .rsplit_once('/') + .map(|(a, b)| (a, Some(b))) + .unwrap_or((path_str.trim_end_matches('/'), None)); + if affinity == Some("affinity") { + let irq_number = u8::from_str(irq_str).or(Err(Error::new(ENOENT)))?; + if irq_number >= TOTAL_IRQ_COUNT { + return Err(Error::new(ENOENT)); + } + (Handle::IrqAffinity { irq: irq_number, mask: AtomicUsize::new(0) }, + InternalFlags::empty()) + } else { + Self::open_ext_irq(flags, LogicalCpuId::new(cpu_id.into()), path_str)? + } } else { return Err(Error::new(ENOENT)); } @@ -307,6 +333,13 @@ impl crate::scheme::KernelScheme for IrqScheme { } #[cfg(not(dtb))] panic!("") + } else if let Some(rest) = path_str.strip_suffix("/affinity") { + let irq_number = u8::from_str(rest).or(Err(Error::new(ENOENT)))?; + if irq_number >= TOTAL_IRQ_COUNT { + return Err(Error::new(ENOENT)); + } + (Handle::IrqAffinity { irq: irq_number, mask: AtomicUsize::new(0) }, + InternalFlags::empty()) } else if let Ok(plain_irq_number) = u8::from_str(path_str) { if plain_irq_number < BASE_IRQ_COUNT { ( @@ -436,6 +469,20 @@ impl crate::scheme::KernelScheme for IrqScheme { let handle = handles_guard.get(file)?; match handle { + &Handle::IrqAffinity { irq: _handle_irq, ref mask } => { + if buffer.len() < size_of::() { + return Err(Error::new(EINVAL)); + } + let mut raw = [0u8; size_of::()]; + buffer.copy_to_slice(&mut raw)?; + let cpu_id = u32::from_ne_bytes(raw); + let cpus = CPUS.get().ok_or(Error::new(EIO))?; + if !cpus.contains(&(cpu_id as u8)) { + return Err(Error::new(EINVAL)); + } + mask.store(cpu_id as usize, Ordering::Release); + Ok(size_of::()) + } &Handle::Irq { irq: handle_irq, ack: ref handle_ack, @@ -475,6 +522,15 @@ impl crate::scheme::KernelScheme for IrqScheme { st_nlink: 1, ..Default::default() }, + Handle::IrqAffinity { irq, .. } => Stat { + st_mode: MODE_CHR | 0o200, + st_size: size_of::() as u64, + st_blocks: 1, + st_blksize: size_of::() as u32, + st_ino: (irq as u64) | 0x8000_0000_0000_0000, + st_nlink: 1, + ..Default::default() + }, Handle::Bsp => Stat { st_mode: MODE_CHR | 0o400, st_size: size_of::() as u64, @@ -516,8 +572,9 @@ impl crate::scheme::KernelScheme for IrqScheme { let scheme_path = match handle { Handle::Irq { irq, .. } => format!("irq:{}", irq), + Handle::IrqAffinity { irq, .. } => format!("irq:{}/affinity", irq), Handle::Bsp => "irq:bsp".to_owned(), - Handle::Avail(cpu_id) => format!("irq:cpu-{:2x}", cpu_id.get()), + Handle::Avail(cpu_id) => format!("irq:cpu-{:02x}", cpu_id.get()), Handle::Phandle(phandle, _) => format!("irq:phandle-{}", phandle), Handle::TopLevel => "irq:".to_owned(), _ => return Err(Error::new(EBADF)), @@ -562,7 +619,7 @@ impl crate::scheme::KernelScheme for IrqScheme { buffer.write_u32(LogicalCpuId::BSP.get())?; Ok(size_of::()) } - Handle::Avail(_) | Handle::TopLevel | Handle::Phandle(_, _) | Handle::SchemeRoot => { + Handle::Avail(_) | Handle::TopLevel | Handle::Phandle(_, _) | Handle::SchemeRoot | Handle::IrqAffinity { .. } => { Err(Error::new(EISDIR)) } } diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs index f7f8ca6759..189cf538ab 100644 --- a/src/scheme/proc.rs +++ b/src/scheme/proc.rs @@ -712,6 +712,7 @@ impl KernelScheme for ProcScheme { } fn close(&self, id: usize, token: &mut CleanLockToken) -> Result<()> { + let mut inner_token = unsafe { CleanLockToken::new() }; let handle = HANDLES .write(token.token()) .remove(&id) @@ -739,9 +740,7 @@ impl KernelScheme for ProcScheme { ))] regs.set_arg1(arg1); - // TODO: Lock ordering violation - let mut token = unsafe { CleanLockToken::new() }; - Ok(context.set_addr_space(Some(new), token.downgrade())) + Ok(context.set_addr_space(Some(new), inner_token.downgrade())) })?; if let Some(old_ctx) = old_ctx && let Some(addrspace) = Arc::into_inner(old_ctx) @@ -805,6 +804,7 @@ impl KernelScheme for ProcScheme { consume: bool, token: &mut CleanLockToken, ) -> Result { + let mut inner_token = unsafe { CleanLockToken::new() }; let handle = HANDLES .read(token.token()) .get(&id) @@ -895,9 +895,7 @@ impl KernelScheme for ProcScheme { }; // TODO: Allocated or AllocatedShared? let addrsp = AddrSpace::current()?; - // TODO: Lock ordering violation - let mut token = unsafe { CleanLockToken::new() }; - let page = addrsp.acquire_write(token.downgrade()).mmap_anywhere( + let page = addrsp.acquire_write(inner_token.downgrade()).mmap_anywhere( &addrsp, NonZeroUsize::new(1).unwrap(), MapFlags::PROT_READ | MapFlags::PROT_WRITE, diff --git a/src/startup/memory.rs b/src/startup/memory.rs index 6a19d90719..90f6801fde 100644 --- a/src/startup/memory.rs +++ b/src/startup/memory.rs @@ -74,14 +74,16 @@ impl MemoryEntry { } struct MemoryMap { - entries: [MemoryEntry; 512], + entries: [MemoryEntry; 1024], size: usize, } impl MemoryMap { fn register(&mut self, base: usize, size: usize, kind: BootloaderMemoryKind) { if self.size >= self.entries.len() { - panic!("Early memory map overflow!"); + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + unsafe { core::arch::asm!("out dx, al", in("dx") 0x3F8u16, in("al") b'!', options(nostack, preserves_flags)); } + panic!("Early memory map overflow at entry {} (max {})", self.size, self.entries.len()); } let start = if kind == BootloaderMemoryKind::Free { align_up(base) @@ -134,7 +136,7 @@ static MEMORY_MAP: SyncUnsafeCell = SyncUnsafeCell::new(MemoryMap { start: 0, end: 0, kind: BootloaderMemoryKind::Null, - }; 512], + }; 1024], size: 0, });