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).
This commit is contained in:
2026-07-12 01:28:23 +03:00
parent 98a8457450
commit 0f3840a5b5
10 changed files with 435 additions and 27 deletions
+1
View File
@@ -1,3 +1,4 @@
# Red Bear OS kernel patches applied via individual patch files
.PHONY: all check .PHONY: all check
SOURCE:=$(dir $(realpath $(lastword $(MAKEFILE_LIST)))) SOURCE:=$(dir $(realpath $(lastword $(MAKEFILE_LIST))))
+2
View File
@@ -4,9 +4,11 @@ pub mod cpu;
pub mod hpet; pub mod hpet;
pub mod ioapic; pub mod ioapic;
pub mod local_apic; pub mod local_apic;
pub mod msi;
pub mod pic; pub mod pic;
pub mod pit; pub mod pit;
pub mod serial; pub mod serial;
pub mod vector;
#[cfg(feature = "system76_ec_debug")] #[cfg(feature = "system76_ec_debug")]
pub mod system76_ec; pub mod system76_ec;
+66
View File
@@ -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<Self> {
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<Self> {
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,
})
}
}
+53
View File
@@ -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<u8> {
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);
}
+1 -1
View File
@@ -22,7 +22,7 @@ use crate::{
use self::context::Kstack; use self::context::Kstack;
pub use self::{ pub use self::{
context::{BorrowedHtBuf, Context, Status}, context::{BorrowedHtBuf, Context, SchedPolicy, Status},
switch::switch, switch::switch,
}; };
+151 -4
View File
@@ -8,13 +8,14 @@ use crate::{
context, context,
scheme::{self, SchemeExt, SchemeId}, scheme::{self, SchemeExt, SchemeId},
sync::{ sync::{
CleanLockToken, LockToken, RwLock, RwLockReadGuard, RwLockWriteGuard, WaitQueue, L0, L1, L2, CleanLockToken, LockToken, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard,
WaitCondition, WaitQueue, L0, L1, L2,
}, },
syscall::{ syscall::{
data::Event, data::Event,
error::{Error, Result, EBADF}, error::{Error, Result, EAGAIN, EBADF, EINVAL, EINTR},
flag::EventFlags, flag::{EVENT_READ, EVENT_WRITE, EventFlags},
usercopy::UserSliceWo, usercopy::{UserSliceRo, UserSliceWo},
}, },
}; };
@@ -25,6 +26,17 @@ pub struct EventQueue {
queue: WaitQueue<Event>, queue: WaitQueue<Event>,
} }
const EVENTFD_COUNTER_MAX: u64 = u64::MAX - 1;
const EVENTFD_TAG_BIT: usize = 1usize << (usize::BITS - 1);
pub struct EventCounter {
id: usize,
counter: Mutex<L1, u64>,
read_condition: WaitCondition,
write_condition: WaitCondition,
semaphore: bool,
}
impl EventQueue { impl EventQueue {
pub fn new(id: EventQueueId) -> EventQueue { pub fn new(id: EventQueueId) -> EventQueue {
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<usize> {
if buf.len() < core::mem::size_of::<u64>() {
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::<u64>())
.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::<u64>());
}
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<usize> {
if buf.len() != core::mem::size_of::<u64>() {
return Err(Error::new(EINVAL));
}
let value = unsafe { buf.read_exact::<u64>()? };
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::<u64>());
}
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<EventQueueId, Arc<EventQueue>>; pub type EventQueueList = HashMap<EventQueueId, Arc<EventQueue>>;
pub type EventCounterList = HashMap<usize, Arc<EventCounter>>;
// Next queue id // Next queue id
static NEXT_QUEUE_ID: AtomicUsize = AtomicUsize::new(0); static NEXT_QUEUE_ID: AtomicUsize = AtomicUsize::new(0);
static NEXT_COUNTER_ID: AtomicUsize = AtomicUsize::new(0);
/// Get next queue id /// Get next queue id
pub fn next_queue_id() -> EventQueueId { pub fn next_queue_id() -> EventQueueId {
EventQueueId::from(NEXT_QUEUE_ID.fetch_add(1, Ordering::SeqCst)) 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 // Current event queues
static QUEUES: RwLock<L2, EventQueueList> = static QUEUES: RwLock<L2, EventQueueList> =
RwLock::new(EventQueueList::with_hasher(DefaultHashBuilder::new())); RwLock::new(EventQueueList::with_hasher(DefaultHashBuilder::new()));
static COUNTERS: RwLock<L2, EventCounterList> =
RwLock::new(EventCounterList::with_hasher(DefaultHashBuilder::new()));
/// Get the event queues list, const /// Get the event queues list, const
pub fn queues(token: LockToken<'_, L0>) -> RwLockReadGuard<'_, L2, EventQueueList> { 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) 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)] #[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct RegKey { pub struct RegKey {
pub scheme: SchemeId, pub scheme: SchemeId,
+91 -9
View File
@@ -1,9 +1,12 @@
use alloc::sync::Arc; use alloc::{sync::Arc, vec::Vec};
use syscall::{EventFlags, O_NONBLOCK}; use syscall::{EventFlags, O_NONBLOCK};
use crate::{ use crate::{
context::file::InternalFlags, 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, sync::CleanLockToken,
syscall::{ syscall::{
data::Event, data::Event,
@@ -25,7 +28,7 @@ impl KernelScheme for EventScheme {
fn kopenat( fn kopenat(
&self, &self,
id: usize, id: usize,
_user_buf: StrOrBytes, user_buf: StrOrBytes,
_flags: usize, _flags: usize,
_fcntl_flags: u32, _fcntl_flags: u32,
_ctx: CallerCtx, _ctx: CallerCtx,
@@ -34,13 +37,53 @@ impl KernelScheme for EventScheme {
if id != SCHEME_ROOT_ID { if id != SCHEME_ROOT_ID {
return Err(Error::new(EACCES)); 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::<u64>().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<()> { 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 id = EventQueueId::from(id);
let queue = queues_mut(token.token()) let queue = queues_mut(token.token())
.remove(&id) .remove(&id)
@@ -59,6 +102,15 @@ impl KernelScheme for EventScheme {
_stored_flags: u32, _stored_flags: u32,
token: &mut CleanLockToken, token: &mut CleanLockToken,
) -> Result<usize> { ) -> Result<usize> {
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 id = EventQueueId::from(id);
let queue = { let queue = {
@@ -74,10 +126,19 @@ impl KernelScheme for EventScheme {
&self, &self,
id: usize, id: usize,
buf: UserSliceRo, buf: UserSliceRo,
_flags: u32, flags: u32,
_stored_flags: u32, _stored_flags: u32,
token: &mut CleanLockToken, token: &mut CleanLockToken,
) -> Result<usize> { ) -> Result<usize> {
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 id = EventQueueId::from(id);
let queue = { let queue = {
@@ -98,8 +159,12 @@ impl KernelScheme for EventScheme {
Ok(events_written * size_of::<Event>()) Ok(events_written * size_of::<Event>())
} }
fn kfpath(&self, _id: usize, buf: UserSliceWo, _token: &mut CleanLockToken) -> Result<usize> { fn kfpath(&self, id: usize, buf: UserSliceWo, _token: &mut CleanLockToken) -> Result<usize> {
buf.copy_common_bytes_from_slice(b"/scheme/event/") 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( fn fevent(
@@ -108,6 +173,23 @@ impl KernelScheme for EventScheme {
flags: EventFlags, flags: EventFlags,
token: &mut CleanLockToken, token: &mut CleanLockToken,
) -> Result<EventFlags> { ) -> Result<EventFlags> {
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 id = EventQueueId::from(id);
let queue = { let queue = {
+61 -4
View File
@@ -56,8 +56,11 @@ const INO_AVAIL: u64 = 0x8000_0000_0000_0000;
const INO_BSP: u64 = 0x8001_0000_0000_0000; const INO_BSP: u64 = 0x8001_0000_0000_0000;
const INO_PHANDLE: u64 = 0x8003_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) { pub fn irq_trigger(irq: u8, token: &mut CleanLockToken) {
if irq >= 16 && !iommu_validate_msi_irq(irq) {
return;
}
COUNTS.lock()[irq as usize] += 1; COUNTS.lock()[irq as usize] += 1;
let fds: SmallVec<[usize; 8]> = { let fds: SmallVec<[usize; 8]> = {
HANDLES HANDLES
@@ -82,6 +85,7 @@ enum Handle {
TopLevel, TopLevel,
Phandle(u8, Vec<u8>), Phandle(u8, Vec<u8>),
Bsp, Bsp,
IrqAffinity { irq: u8, mask: AtomicUsize },
} }
impl Handle { impl Handle {
fn as_irq_handle(&self) -> Option<(&AtomicUsize, u8)> { fn as_irq_handle(&self) -> Option<(&AtomicUsize, u8)> {
@@ -214,6 +218,14 @@ const fn vector_to_irq(vector: u8) -> u8 {
vector - 32 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 { impl crate::scheme::KernelScheme for IrqScheme {
fn scheme_root(&self, token: &mut CleanLockToken) -> Result<usize> { fn scheme_root(&self, token: &mut CleanLockToken) -> Result<usize> {
let id = HANDLES.write(token.token()).insert(Handle::SchemeRoot); let id = HANDLES.write(token.token()).insert(Handle::SchemeRoot);
@@ -280,7 +292,21 @@ impl crate::scheme::KernelScheme for IrqScheme {
InternalFlags::POSITIONED, InternalFlags::POSITIONED,
) )
} else if let Some(path_str) = path_str.strip_prefix('/') { } 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 { } else {
return Err(Error::new(ENOENT)); return Err(Error::new(ENOENT));
} }
@@ -307,6 +333,13 @@ impl crate::scheme::KernelScheme for IrqScheme {
} }
#[cfg(not(dtb))] #[cfg(not(dtb))]
panic!("") 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) { } else if let Ok(plain_irq_number) = u8::from_str(path_str) {
if plain_irq_number < BASE_IRQ_COUNT { if plain_irq_number < BASE_IRQ_COUNT {
( (
@@ -436,6 +469,20 @@ impl crate::scheme::KernelScheme for IrqScheme {
let handle = handles_guard.get(file)?; let handle = handles_guard.get(file)?;
match handle { match handle {
&Handle::IrqAffinity { irq: _handle_irq, ref mask } => {
if buffer.len() < size_of::<u32>() {
return Err(Error::new(EINVAL));
}
let mut raw = [0u8; size_of::<u32>()];
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::<u32>())
}
&Handle::Irq { &Handle::Irq {
irq: handle_irq, irq: handle_irq,
ack: ref handle_ack, ack: ref handle_ack,
@@ -475,6 +522,15 @@ impl crate::scheme::KernelScheme for IrqScheme {
st_nlink: 1, st_nlink: 1,
..Default::default() ..Default::default()
}, },
Handle::IrqAffinity { irq, .. } => Stat {
st_mode: MODE_CHR | 0o200,
st_size: size_of::<u32>() as u64,
st_blocks: 1,
st_blksize: size_of::<u32>() as u32,
st_ino: (irq as u64) | 0x8000_0000_0000_0000,
st_nlink: 1,
..Default::default()
},
Handle::Bsp => Stat { Handle::Bsp => Stat {
st_mode: MODE_CHR | 0o400, st_mode: MODE_CHR | 0o400,
st_size: size_of::<usize>() as u64, st_size: size_of::<usize>() as u64,
@@ -516,8 +572,9 @@ impl crate::scheme::KernelScheme for IrqScheme {
let scheme_path = match handle { let scheme_path = match handle {
Handle::Irq { irq, .. } => format!("irq:{}", irq), Handle::Irq { irq, .. } => format!("irq:{}", irq),
Handle::IrqAffinity { irq, .. } => format!("irq:{}/affinity", irq),
Handle::Bsp => "irq:bsp".to_owned(), 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::Phandle(phandle, _) => format!("irq:phandle-{}", phandle),
Handle::TopLevel => "irq:".to_owned(), Handle::TopLevel => "irq:".to_owned(),
_ => return Err(Error::new(EBADF)), _ => return Err(Error::new(EBADF)),
@@ -562,7 +619,7 @@ impl crate::scheme::KernelScheme for IrqScheme {
buffer.write_u32(LogicalCpuId::BSP.get())?; buffer.write_u32(LogicalCpuId::BSP.get())?;
Ok(size_of::<usize>()) Ok(size_of::<usize>())
} }
Handle::Avail(_) | Handle::TopLevel | Handle::Phandle(_, _) | Handle::SchemeRoot => { Handle::Avail(_) | Handle::TopLevel | Handle::Phandle(_, _) | Handle::SchemeRoot | Handle::IrqAffinity { .. } => {
Err(Error::new(EISDIR)) Err(Error::new(EISDIR))
} }
} }
+4 -6
View File
@@ -712,6 +712,7 @@ impl KernelScheme for ProcScheme {
} }
fn close(&self, id: usize, token: &mut CleanLockToken) -> Result<()> { fn close(&self, id: usize, token: &mut CleanLockToken) -> Result<()> {
let mut inner_token = unsafe { CleanLockToken::new() };
let handle = HANDLES let handle = HANDLES
.write(token.token()) .write(token.token())
.remove(&id) .remove(&id)
@@ -739,9 +740,7 @@ impl KernelScheme for ProcScheme {
))] ))]
regs.set_arg1(arg1); regs.set_arg1(arg1);
// TODO: Lock ordering violation Ok(context.set_addr_space(Some(new), inner_token.downgrade()))
let mut token = unsafe { CleanLockToken::new() };
Ok(context.set_addr_space(Some(new), token.downgrade()))
})?; })?;
if let Some(old_ctx) = old_ctx if let Some(old_ctx) = old_ctx
&& let Some(addrspace) = Arc::into_inner(old_ctx) && let Some(addrspace) = Arc::into_inner(old_ctx)
@@ -805,6 +804,7 @@ impl KernelScheme for ProcScheme {
consume: bool, consume: bool,
token: &mut CleanLockToken, token: &mut CleanLockToken,
) -> Result<usize> { ) -> Result<usize> {
let mut inner_token = unsafe { CleanLockToken::new() };
let handle = HANDLES let handle = HANDLES
.read(token.token()) .read(token.token())
.get(&id) .get(&id)
@@ -895,9 +895,7 @@ impl KernelScheme for ProcScheme {
}; };
// TODO: Allocated or AllocatedShared? // TODO: Allocated or AllocatedShared?
let addrsp = AddrSpace::current()?; let addrsp = AddrSpace::current()?;
// TODO: Lock ordering violation let page = addrsp.acquire_write(inner_token.downgrade()).mmap_anywhere(
let mut token = unsafe { CleanLockToken::new() };
let page = addrsp.acquire_write(token.downgrade()).mmap_anywhere(
&addrsp, &addrsp,
NonZeroUsize::new(1).unwrap(), NonZeroUsize::new(1).unwrap(),
MapFlags::PROT_READ | MapFlags::PROT_WRITE, MapFlags::PROT_READ | MapFlags::PROT_WRITE,
+5 -3
View File
@@ -74,14 +74,16 @@ impl MemoryEntry {
} }
struct MemoryMap { struct MemoryMap {
entries: [MemoryEntry; 512], entries: [MemoryEntry; 1024],
size: usize, size: usize,
} }
impl MemoryMap { impl MemoryMap {
fn register(&mut self, base: usize, size: usize, kind: BootloaderMemoryKind) { fn register(&mut self, base: usize, size: usize, kind: BootloaderMemoryKind) {
if self.size >= self.entries.len() { 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 { let start = if kind == BootloaderMemoryKind::Free {
align_up(base) align_up(base)
@@ -134,7 +136,7 @@ static MEMORY_MAP: SyncUnsafeCell<MemoryMap> = SyncUnsafeCell::new(MemoryMap {
start: 0, start: 0,
end: 0, end: 0,
kind: BootloaderMemoryKind::Null, kind: BootloaderMemoryKind::Null,
}; 512], }; 1024],
size: 0, size: 0,
}); });