kernel: merge-fix — restore upstream scheduler fields, NUMA init, ordered lock try_write_arc

Merge resolution artifacts fixed:
- context.rs: restore EEVDF scheduler fields (vtime, vd, rem_slice, is_active, queue_key)
- context.rs: restore Status::is_dead() method and cmp::Reverse import
- context.rs: restore pub const CONTEXT_NAME_CAPAC
- memory.rs: restore AddrSpaceSwitchReadGuard struct
- percpu.rs: restore new_addrsp_guard field
- ordered.rs: restore try_write_arc method
- startup/memory.rs: return BumpAllocator instead of calling init_mm internally
- acpi/mod.rs: restore fadt/facs module declarations, slit/srat from upstream
This commit is contained in:
2026-07-11 13:16:54 +03:00
parent 7aa2a165df
commit 9493db389a
10 changed files with 451 additions and 10 deletions
Generated
+3 -3
View File
@@ -104,7 +104,7 @@ dependencies = [
[[package]]
name = "kernel"
version = "0.5.12+rb0.3.0"
version = "0.5.12+rb0.3.1"
dependencies = [
"arrayvec",
"bitfield",
@@ -201,7 +201,7 @@ checksum = "64072665120942deff5fd5425d6c1811b854f4939e7f1c01ce755f64432bbea7"
[[package]]
name = "redox_syscall"
version = "0.9.0+rb0.3.0"
version = "0.9.0+rb0.3.1"
dependencies = [
"bitflags 2.13.0",
]
@@ -420,4 +420,4 @@ dependencies = [
[[patch.unused]]
name = "libredox"
version = "0.1.18+rb0.3.0"
version = "0.1.18+rb0.3.1"
+2
View File
@@ -17,6 +17,8 @@ use self::{hpet::Hpet, madt::Madt, rsdp::Rsdp, rsdt::Rsdt, rxsdt::Rxsdt, sdt::Sd
#[cfg(target_arch = "aarch64")]
mod gtdt;
pub mod fadt;
pub mod facs;
pub mod hpet;
pub mod madt;
mod rsdp;
+44
View File
@@ -0,0 +1,44 @@
use crate::{
acpi::{rxsdt::Rxsdt, sdt::Sdt, RXSDT_ENUM},
find_one_sdt,
memory::{round_up_pages, PAGE_SIZE},
numa::{self},
};
use core::{ops::Add, slice};
use hashbrown::HashMap;
use rmm::{Arch, BumpAllocator, FrameAllocator, FrameCount};
use spin::once::Once;
#[derive(Debug)]
pub struct Slit {
sdt: &'static Sdt,
no: u64,
address: *const u8,
}
impl Slit {
pub fn new(sdt: &'static Sdt) -> Self {
Self {
sdt,
no: unsafe { *(sdt.data_address() as *const u64) },
address: (sdt.data_address() + 8) as *const u8,
}
}
pub fn init<A: Arch>(&self, allocator: &mut BumpAllocator<A>) -> &'static mut [u8] {
unsafe { slice::from_raw_parts_mut(self.address as *mut u8, (self.no * self.no) as usize) }
}
}
pub fn init<A: Arch>(allocator: &mut BumpAllocator<A>, distances: &Once<&'static [u8]>) {
if let Some(rxsdt) = RXSDT_ENUM.get() {
for sdt_addr in rxsdt.iter() {
let sdt =
unsafe { &*(crate::memory::RmmA::phys_to_virt(sdt_addr).data() as *const Sdt) };
if &sdt.signature == b"SLIT" {
let slit = Slit::new(sdt);
distances.call_once(|| slit.init(allocator));
return;
}
}
}
}
+215
View File
@@ -0,0 +1,215 @@
//! See <https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/05_ACPI_Software_Programming_Model/ACPI_Software_Programming_Model.html#system-resource-affinity-table-srat>
use core::slice;
use hashbrown::HashMap;
use rmm::{Arch, BumpAllocator, FrameAllocator};
use spin::once::Once;
use crate::{
acpi::{find_sdt, get_sdt_signature, rxsdt::Rxsdt, sdt::Sdt, srat, RXSDT_ENUM},
cpu_set::MAX_CPU_COUNT,
find_one_sdt, memory,
numa::{self, NumaMemory},
};
#[cfg(target_arch = "aarch64")]
#[path = "aarch64.rs"]
mod arch;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[path = "x86.rs"]
mod arch;
#[repr(C, packed)]
pub struct Srat {
sdt: &'static Sdt,
entries: *const u8,
}
pub fn init<A: Arch>(
allocator: &mut BumpAllocator<A>,
map: &Once<&'static [u32]>,
once_cpus: &Once<&'static [u32]>,
mem: &Once<&'static [NumaMemory]>,
) {
let dom_node_map = allocator
.allocate(rmm::FrameCount::new(1))
.expect("Failed to allocate memory for storing NUMA info");
let dom_node_map_ptr =
unsafe { crate::memory::RmmA::phys_to_virt(dom_node_map).data() as *mut u32 };
// Occupies 512 bytes (1/8th of a page)
let dom_node_map: &'static mut [u32] =
unsafe { slice::from_raw_parts_mut(dom_node_map_ptr, numa::MAX_DOMAINS) };
// occupies 512 bytes (1/8th of a page)
let cpus: &'static mut [u32] = unsafe {
slice::from_raw_parts_mut(
dom_node_map_ptr.add(numa::MAX_DOMAINS) as *mut u32,
MAX_CPU_COUNT as usize,
)
};
// total occupied till now: 1024 bytes, remaining 3072 bytes, can accomodate 128 memory entries
let memories: &'static mut [NumaMemory] = unsafe {
slice::from_raw_parts_mut(
cpus.as_ptr().add(numa::MAX_DOMAINS) as *mut NumaMemory,
numa::MAX_DOMAINS,
)
};
dom_node_map.fill(u32::MAX);
cpus.fill(u32::MAX);
memories.fill(NumaMemory {
start: 0,
length: 0,
node_id: 0,
_pad: [0; 4],
});
if let Some(rxsdt) = RXSDT_ENUM.get() {
for sdt_addr in rxsdt.iter() {
let sdt = unsafe { &*(memory::RmmA::phys_to_virt(sdt_addr).data() as *const Sdt) };
if &sdt.signature == b"SRAT" {
arch::init_srat(dom_node_map, cpus, memories, &Srat::new(sdt));
map.call_once(|| dom_node_map);
once_cpus.call_once(|| cpus);
mem.call_once(|| memories);
return;
}
}
}
}
impl Srat {
pub fn new(sdt: &'static Sdt) -> Self {
Self {
sdt,
entries: (sdt.data_address() + 12) as *const u8,
}
}
}
impl<'a> IntoIterator for &'a Srat {
type Item = SratEntry;
type IntoIter = SratIter<'a>;
fn into_iter(self) -> Self::IntoIter {
SratIter { i: 0, srat: self }
}
}
pub struct SratIter<'a> {
i: u32,
srat: &'a Srat,
}
impl<'a> Iterator for SratIter<'a> {
type Item = SratEntry;
fn next(&mut self) -> Option<Self::Item> {
while self.i < self.srat.sdt.data_len() as u32 {
let entry = unsafe { self.srat.entries.add(self.i as usize) };
let entry_len = unsafe { *self.srat.entries.add(self.i as usize + 1) };
let entry = Some(match unsafe { *entry } {
0 => SratEntry::LegacyProcessorLocalAffinity(unsafe {
assert!(entry_len as usize == size_of::<LegacyProcessorLocalAffinity>() + 2);
*(entry.add(2) as *const LegacyProcessorLocalAffinity)
}),
1 => SratEntry::MemoryAffinity(unsafe {
assert!(entry_len as usize == size_of::<MemoryAffinity>() + 10);
*(entry.add(2) as *const MemoryAffinity)
}),
2 => SratEntry::ProcessorLocalAffinity(unsafe {
assert!(entry_len as usize == size_of::<ProcessorLocalAffinity>() + 8);
*(entry.add(4) as *const ProcessorLocalAffinity)
}),
3 => SratEntry::GiccAffinity(unsafe {
assert!(entry_len as usize == size_of::<GiccAffinity>() + 2);
*(entry.add(2) as *const GiccAffinity)
}),
// ignore GIC ITS Affinity and Generic Initiator Affinity
_ => {
self.i += entry_len as u32;
continue;
}
});
self.i += entry_len as u32;
return entry;
}
None
}
}
#[derive(Debug, Clone, Copy)]
pub enum SratEntry {
LegacyProcessorLocalAffinity(LegacyProcessorLocalAffinity),
MemoryAffinity(MemoryAffinity),
ProcessorLocalAffinity(ProcessorLocalAffinity),
GiccAffinity(GiccAffinity),
// unimplemented: Gic Its Affinity and Generic Initiator Affinity
// our current focus is only on memory and cpus
}
#[repr(C, packed)]
#[derive(Clone, Copy, Debug)]
/// For legacy xAPIC systems
struct LegacyProcessorLocalAffinity {
proximity_domain_low: u8,
apic_id: u8,
flags: u32,
sapic_id: u8,
proximity_domain_high: [u8; 3],
clock_domain: u32,
}
#[repr(C, packed)]
#[derive(Clone, Copy, Debug)]
struct MemoryAffinity {
proximity_domain: u32,
_reserved0: u16,
base_address_low: u32,
base_address_high: u32,
length_low: u32,
length_high: u32,
_reserved1: u32,
flags: u32,
}
#[repr(C, packed)]
#[derive(Clone, Copy, Debug)]
/// For x2APIC systems
struct ProcessorLocalAffinity {
proximity_domain: u32,
x2apic_id: u32,
flags: u32,
clock_domain: u32,
}
#[repr(C, packed)]
#[derive(Clone, Copy, Debug)]
struct GiccAffinity {
proximity_domain: u32,
processor_uid: u32,
flags: u32,
clock_domain: u32,
}
#[inline(always)]
pub(crate) fn to_usize(low: u32, high: u32) -> usize {
#[cfg(target_pointer_width = "32")]
return low as usize;
#[cfg(target_pointer_width = "64")]
{
let mut low_and_high = [0u8; 8];
low_and_high[0..=3].copy_from_slice(low.to_le_bytes().as_slice());
low_and_high[4..=7].copy_from_slice(high.to_le_bytes().as_slice());
usize::from_le_bytes(low_and_high)
}
}
+123
View File
@@ -0,0 +1,123 @@
use core::{iter, slice};
use hashbrown::HashMap;
use rmm::{Arch, BumpAllocator, FrameAllocator, PhysicalAddress};
use crate::{
acpi::srat::{to_usize, Srat, SratEntry},
cpu_set,
memory::{self, PAGE_SIZE},
numa::{self, assign_memory_id, NumaMemory},
};
#[inline(always)]
fn to_single_int(high: &[u8; 3], low: u8) -> u32 {
let mut high_and_low = [0u8; 4];
high_and_low[0] = low;
(high_and_low[1], high_and_low[2], high_and_low[3]) = (high[0], high[1], high[2]);
u32::from_le_bytes(high_and_low)
}
pub fn init_srat(
dom_node_map: &mut [u32],
cpus: &mut [u32],
memories: &mut [NumaMemory],
srat: &Srat,
) {
let mut cpu_count = 0;
let mut memory_count = 0;
srat.into_iter().for_each(|e| match e {
SratEntry::LegacyProcessorLocalAffinity(legacy_processor_local_affinity) => {
if legacy_processor_local_affinity.flags & 1 != 0 {
cpu_count += 1
}
}
SratEntry::MemoryAffinity(memory_affinity) => {
if memory_affinity.flags & 1 != 0 && memory_affinity.flags & (1 << 1) == 0 {
memory_count += 1
}
}
SratEntry::ProcessorLocalAffinity(processor_local_affinity) => {
if processor_local_affinity.flags & 1 != 0 {
cpu_count += 1
}
}
_ => (),
});
assert!(
memory_count <= numa::MAX_DOMAINS,
"Found {} memory blocks while only a maximum of {} are supported",
memory_count,
numa::MAX_DOMAINS
);
assert!(
cpu_count <= cpu_set::MAX_CPU_COUNT,
"Found more number of CPUs than supported"
);
for affinity in srat {
match affinity {
SratEntry::LegacyProcessorLocalAffinity(legacy_processor_local_affinity) => {
if legacy_processor_local_affinity.flags & 1 == 0 {
// processor disabled
continue;
}
let dom = to_single_int(
&legacy_processor_local_affinity.proximity_domain_high,
legacy_processor_local_affinity.proximity_domain_low,
);
if dom_node_map[dom as usize] == u32::MAX {
let node_id = numa::assign_node_id(true);
dom_node_map[dom as usize] = node_id as u32;
}
cpus[legacy_processor_local_affinity.apic_id as usize] = dom_node_map[dom as usize];
}
SratEntry::MemoryAffinity(memory_affinity) => {
if memory_affinity.flags & 1 == 0 {
// memory is not enabled
continue;
}
if memory_affinity.flags & (1 << 1) != 0 {
// memory is hot-pluggable
continue;
}
let dom = memory_affinity.proximity_domain;
if memory_affinity.length_low == 0 {
continue;
}
let start = to_usize(
memory_affinity.base_address_low,
memory_affinity.base_address_high,
);
let length = to_usize(memory_affinity.length_low, memory_affinity.length_high);
if dom_node_map[dom as usize] == u32::MAX {
let node_id = numa::assign_node_id(true);
dom_node_map[dom as usize] = node_id as u32;
}
let mem_id = assign_memory_id() as u32;
memories[mem_id as usize] = numa::NumaMemory {
start,
length,
node_id: dom_node_map[dom as usize],
_pad: [0u8; 4],
};
}
SratEntry::ProcessorLocalAffinity(processor_local_affinity) => {
if processor_local_affinity.flags & 1 == 0 {
// processor disabled
continue;
}
let dom = processor_local_affinity.proximity_domain;
if dom_node_map[dom as usize] == u32::MAX {
let node_id = numa::assign_node_id(true);
dom_node_map[dom as usize] = node_id as u32;
}
cpus[processor_local_affinity.x2apic_id as usize] = dom_node_map[dom as usize];
}
_ => continue,
}
}
}
+20 -1
View File
@@ -1,6 +1,7 @@
use alloc::{collections::BTreeSet, sync::Arc, vec::Vec};
use arrayvec::ArrayString;
use core::{
cmp::Reverse,
mem::{self, size_of, ManuallyDrop},
num::NonZeroUsize,
sync::atomic::{AtomicU32, Ordering},
@@ -60,6 +61,9 @@ impl Status {
pub fn is_soft_blocked(&self) -> bool {
matches!(self, Self::Blocked)
}
pub fn is_dead(&self) -> bool {
matches!(self, Self::Dead { .. })
}
}
#[derive(Clone, Debug)]
@@ -73,7 +77,7 @@ pub enum HardBlockedReason {
NotYetStarted,
}
const CONTEXT_NAME_CAPAC: usize = 32;
pub const CONTEXT_NAME_CAPAC: usize = 32;
#[derive(Debug)]
pub enum SyscallFrame {
@@ -146,6 +150,16 @@ pub struct Context {
pub fmap_ret: Option<Frame>,
/// Priority
pub prio: usize,
/// Virtual Run Time
pub vtime: u64,
/// Virtual Deadline
pub vd: u64,
/// Remaining Slice of allocated time
pub rem_slice: u64,
/// Is currently active?
pub is_active: bool,
/// Key for the RunQueue
pub queue_key: Option<(u64, Reverse<u64>, u32)>,
/// Process group ID.
pub pgrp: usize,
/// Session ID.
@@ -239,6 +253,11 @@ impl Context {
userspace: false,
fmap_ret: None,
prio: 20,
vtime: 0,
vd: 0,
rem_slice: 0,
is_active: false,
queue_key: None,
being_sigkilled: false,
owner_proc_id,
+20 -1
View File
@@ -5,7 +5,7 @@ use core::{
fmt::Debug,
mem::ManuallyDrop,
num::NonZeroUsize,
ops::Bound,
ops::{Bound, Deref},
sync::atomic::{AtomicU32, Ordering},
};
use rmm::{Arch as _, PageFlush};
@@ -768,6 +768,25 @@ impl AddrSpace {
}
}
pub struct AddrSpaceSwitchReadGuard {
pub lock: RwLockReadGuard<'static, L5, AddrSpace>,
}
impl AddrSpaceSwitchReadGuard {
pub fn new(guard: RwLockReadGuard<'_, L5, AddrSpace>) -> Self {
Self {
lock: unsafe { core::mem::transmute(guard) },
}
}
}
impl Deref for AddrSpaceSwitchReadGuard {
type Target = RwLockReadGuard<'static, L5, AddrSpace>;
fn deref(&self) -> &Self::Target {
&self.lock
}
}
#[derive(Debug)]
pub struct UserGrants {
// Using a BTreeMap for its range method.
+7 -1
View File
@@ -12,7 +12,11 @@ use syscall::PtraceFlags;
use crate::{
arch::device::ArchPercpuMisc,
context::{empty_cr3, memory::AddrSpaceWrapper, switch::ContextSwitchPercpu},
context::{
empty_cr3,
memory::{AddrSpaceSwitchReadGuard, AddrSpaceWrapper},
switch::ContextSwitchPercpu,
},
cpu_set::{LogicalCpuId, MAX_CPU_COUNT},
cpu_stats::{CpuStats, CpuStatsData},
ptrace::Session,
@@ -30,6 +34,7 @@ pub struct PercpuBlock {
pub current_addrsp: RefCell<Option<Arc<AddrSpaceWrapper>>>,
pub new_addrsp_tmp: Cell<Option<Arc<AddrSpaceWrapper>>>,
pub new_addrsp_guard: Cell<Option<AddrSpaceSwitchReadGuard>>,
pub wants_tlb_shootdown: AtomicBool,
pub balance: Cell<[usize; 40]>,
pub last_queue: Cell<usize>,
@@ -242,6 +247,7 @@ impl PercpuBlock {
switch_internals: ContextSwitchPercpu::default(),
current_addrsp: RefCell::new(None),
new_addrsp_tmp: Cell::new(None),
new_addrsp_guard: Cell::new(None),
wants_tlb_shootdown: AtomicBool::new(false),
balance: Cell::new([0; 40]),
last_queue: Cell::new(39),
+6 -4
View File
@@ -1,7 +1,6 @@
use crate::{
arch::CurrentRmmArch,
memory::PAGE_SIZE,
numa,
startup::{memory::BootloaderMemoryKind::Null, KernelArgs},
};
use core::{
@@ -395,7 +394,11 @@ unsafe fn map_memory<A: Arch>(areas: &[MemoryArea], mut bump_allocator: &mut Bum
}
}
pub unsafe fn init(args: &KernelArgs, low_limit: Option<usize>, high_limit: Option<usize>) {
pub unsafe fn init(
args: &KernelArgs,
low_limit: Option<usize>,
high_limit: Option<usize>,
) -> BumpAllocator<CurrentRmmArch> {
register_memory_from_kernel_args(args);
unsafe {
@@ -442,7 +445,6 @@ pub unsafe fn init(args: &KernelArgs, low_limit: Option<usize>, high_limit: Opti
// Create the physical memory map
let offset = bump_allocator.offset();
info!("Permanently used: {} KB", offset.div_ceil(KILOBYTE));
crate::memory::init_mm(bump_allocator);
bump_allocator
}
}
+11
View File
@@ -593,6 +593,17 @@ impl<L: Level, T> RwLock<L, T> {
RwLockUpgradableGuard { inner, lock_token }
}
// Unsafe due to not using token, currently required by context::switch
pub unsafe fn try_write_arc(self: &Arc<Self>) -> Option<ArcRwLockWriteGuard<L, T>> {
let Some(guard) = self.inner.try_write() else {
return None;
};
core::mem::forget(guard);
Some(ArcRwLockWriteGuard {
rwlock: self.clone(),
})
}
// Unsafe due to not using token, currently required by context::switch
pub unsafe fn write_arc(self: &Arc<Self>) -> ArcRwLockWriteGuard<L, T> {
core::mem::forget(self.inner.write());