Red Bear OS kernel baseline

From release 0.1.0 pre-patched archive.
This includes all Red Bear modifications previously maintained
as patches in local/patches/kernel/.
This commit is contained in:
Red Bear OS
2026-06-27 09:19:25 +03:00
commit 82feefbaee
234 changed files with 40494 additions and 0 deletions
+91
View File
@@ -0,0 +1,91 @@
use core::sync::{
atomic,
atomic::{AtomicU32, AtomicUsize, Ordering},
};
use rmm::{PageMapper, TableKind};
const NO_PROCESSOR: u32 = !0;
static LOCK_OWNER: AtomicU32 = AtomicU32::new(NO_PROCESSOR);
static LOCK_COUNT: AtomicUsize = AtomicUsize::new(0);
// TODO: Support, perhaps via const generics, embedding address checking in PageMapper, thereby
// statically enforcing that the kernel mapper can only map things in the kernel half, and vice
// versa.
/// A guard to the global lock protecting the upper 128 TiB of kernel address space.
///
/// NOTE: Use this with great care! Since heap allocations may also require this lock when the heap
/// needs to be expended, it must not be held while memory allocations are done!
// TODO: Make the lock finer-grained so that e.g. the heap part can be independent from e.g.
// PHYS_PML4?
pub struct KernelMapper<const RW: bool> {
mapper: crate::memory::PageMapper,
}
impl KernelMapper<false> {
pub fn lock_ro() -> Self {
KernelMapper::lock()
}
}
impl KernelMapper<true> {
pub fn lock_rw() -> Self {
KernelMapper::lock()
}
}
impl<const RW: bool> KernelMapper<RW> {
fn lock() -> Self {
let mapper =
unsafe { PageMapper::current(TableKind::Kernel, crate::memory::TheFrameAllocator) };
let current_processor = crate::cpu_id();
loop {
match LOCK_OWNER.compare_exchange_weak(
NO_PROCESSOR,
current_processor.get(),
Ordering::Acquire,
Ordering::Relaxed,
) {
Ok(_) => break,
// already owned by this hardware thread
Err(id) if id == current_processor.get() => break,
// either CAS failed, or some other hardware thread holds the lock
Err(_) => core::hint::spin_loop(),
}
}
let prev_count = LOCK_COUNT.fetch_add(1, Ordering::Relaxed);
atomic::compiler_fence(Ordering::Acquire);
let ro = prev_count > 0;
if RW && ro {
panic!("KernelMapper locked re-entrant when write access is requested");
}
Self { mapper }
}
}
impl<const RW: bool> core::ops::Deref for KernelMapper<RW> {
type Target = crate::memory::PageMapper;
fn deref(&self) -> &Self::Target {
&self.mapper
}
}
impl core::ops::DerefMut for KernelMapper<true> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.mapper
}
}
impl<const RW: bool> Drop for KernelMapper<RW> {
fn drop(&mut self) {
if LOCK_COUNT.fetch_sub(1, Ordering::Relaxed) == 1 {
LOCK_OWNER.store(NO_PROCESSOR, Ordering::Release);
}
atomic::compiler_fence(Ordering::Release);
}
}
+1090
View File
File diff suppressed because it is too large Load Diff
+85
View File
@@ -0,0 +1,85 @@
// Some code was borrowed from [Phil Opp's Blog](http://os.phil-opp.com/modifying-page-tables.html)
use core::fmt::Debug;
use rmm::{Arch, VirtualAddress};
use crate::memory::RmmA;
/// Size of pages
pub const PAGE_SIZE: usize = RmmA::PAGE_SIZE;
pub const PAGE_MASK: usize = RmmA::PAGE_OFFSET_MASK;
/// Page
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Page {
number: usize,
}
impl Page {
pub fn start_address(self) -> VirtualAddress {
VirtualAddress::new(self.number * PAGE_SIZE)
}
pub fn containing_address(address: VirtualAddress) -> Page {
//TODO assert!(address.data() < 0x0000_8000_0000_0000 || address.data() >= 0xffff_8000_0000_0000,
// "invalid address: 0x{:x}", address.data());
Page {
number: address.data() / PAGE_SIZE,
}
}
pub fn range_inclusive(start: Page, r#final: Page) -> PageIter {
PageIter {
start,
end: r#final.next(),
}
}
pub fn next(self) -> Page {
self.next_by(1)
}
pub fn next_by(self, n: usize) -> Page {
Self {
number: self.number + n,
}
}
pub fn offset_from(self, other: Self) -> usize {
self.number - other.number
}
}
impl Debug for Page {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"[page at {:p}]",
self.start_address().data() as *const u8
)
}
}
pub struct PageIter {
start: Page,
end: Page,
}
impl Iterator for PageIter {
type Item = Page;
fn next(&mut self) -> Option<Page> {
if self.start < self.end {
let page = self.start;
self.start = self.start.next();
Some(page)
} else {
None
}
}
}
/// Round down to the nearest multiple of page size
pub fn round_down_pages(number: usize) -> usize {
number.div_floor(PAGE_SIZE) * PAGE_SIZE
}
/// Round up to the nearest multiple of page size
pub fn round_up_pages(number: usize) -> usize {
number.next_multiple_of(PAGE_SIZE)
}