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
SOURCE:=$(dir $(realpath $(lastword $(MAKEFILE_LIST))))
+2
View File
@@ -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;
+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;
pub use self::{
context::{BorrowedHtBuf, Context, Status},
context::{BorrowedHtBuf, Context, SchedPolicy, Status},
switch::switch,
};
+151 -4
View File
@@ -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<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 {
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<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 EventCounterList = HashMap<usize, Arc<EventCounter>>;
// 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<L2, EventQueueList> =
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
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,
+91 -9
View File
@@ -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::<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<()> {
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<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 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<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 queue = {
@@ -98,8 +159,12 @@ impl KernelScheme for EventScheme {
Ok(events_written * size_of::<Event>())
}
fn kfpath(&self, _id: usize, buf: UserSliceWo, _token: &mut CleanLockToken) -> Result<usize> {
buf.copy_common_bytes_from_slice(b"/scheme/event/")
fn kfpath(&self, id: usize, buf: UserSliceWo, _token: &mut CleanLockToken) -> Result<usize> {
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<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 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_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<u8>),
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<usize> {
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::<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 {
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::<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 {
st_mode: MODE_CHR | 0o400,
st_size: size_of::<usize>() 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::<usize>())
}
Handle::Avail(_) | Handle::TopLevel | Handle::Phandle(_, _) | Handle::SchemeRoot => {
Handle::Avail(_) | Handle::TopLevel | Handle::Phandle(_, _) | Handle::SchemeRoot | Handle::IrqAffinity { .. } => {
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<()> {
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<usize> {
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,
+5 -3
View File
@@ -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<MemoryMap> = SyncUnsafeCell::new(MemoryMap {
start: 0,
end: 0,
kind: BootloaderMemoryKind::Null,
}; 512],
}; 1024],
size: 0,
});