WIP: Global page info structs.

This commit is contained in:
4lDO2
2023-06-22 18:00:41 +02:00
parent 593e21d95e
commit 760fc2ba5a
4 changed files with 116 additions and 17 deletions
+17 -7
View File
@@ -2,7 +2,7 @@ use core::{
cmp,
mem,
slice,
sync::atomic::{self, AtomicUsize, Ordering},
sync::atomic::{self, AtomicUsize, Ordering}, cell::SyncUnsafeCell,
};
use rmm::{
KILOBYTE,
@@ -102,7 +102,7 @@ unsafe fn inner<A: Arch>(
}
}
// Map kernel at KERNEL_OFFSET and identity map too
// Map kernel at KERNEL_OFFSET and map linearly too
for i in 0..kernel_size_aligned / A::PAGE_SIZE {
let phys = PhysicalAddress::new(kernel_base + i * A::PAGE_SIZE);
let virt = VirtualAddress::new(crate::KERNEL_OFFSET + i * A::PAGE_SIZE);
@@ -226,10 +226,18 @@ impl core::fmt::Debug for LockedAllocator {
}
}
static mut AREAS: [MemoryArea; 512] = [MemoryArea {
static AREAS: SyncUnsafeCell<[MemoryArea; 512]> = SyncUnsafeCell::new([MemoryArea {
base: PhysicalAddress::new(0),
size: 0,
}; 512];
}; 512]);
static AREA_COUNT: SyncUnsafeCell<u16> = SyncUnsafeCell::new(0);
pub fn areas() -> &'static [MemoryArea] {
// SAFETY: Both AREAS and AREA_COUNT are initialized once and then never changed.
//
// TODO: Memory hotplug?
unsafe { &(&*AREAS.get())[..AREA_COUNT.get().read().into()] }
}
pub static FRAME_ALLOCATOR: LockedAllocator = LockedAllocator;
@@ -420,13 +428,15 @@ pub unsafe fn init(
continue;
}
AREAS[area_i].base = PhysicalAddress::new(base);
AREAS[area_i].size = size;
let areas = &mut *AREAS.get();
areas[area_i].base = PhysicalAddress::new(base);
areas[area_i].size = size;
area_i += 1;
}
AREA_COUNT.get().write(area_i as u16);
let allocator = inner::<A>(
&AREAS,
areas(),
kernel_base, kernel_size_aligned,
stack_base, stack_size_aligned,
env_base, env_size_aligned,
+3 -1
View File
@@ -7,7 +7,7 @@ use core::cell::Cell;
use core::slice;
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use crate::allocator;
use crate::{allocator, memory};
#[cfg(feature = "acpi")]
use crate::acpi;
use crate::arch::pti;
@@ -263,6 +263,8 @@ pub unsafe extern fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
// Initialize devices (for AP)
device::init_ap();
memory::init_mm();
AP_READY.store(true, Ordering::SeqCst);
cpu_id
+2 -8
View File
@@ -529,17 +529,11 @@ pub struct GrantInfo {
pub(crate) provider: Provider,
}
/// The arch-specific user page tables are throwaway, and this enum contains all required
/// information to update lazy mappings in the event of page faults.
#[derive(Debug)]
pub enum Provider {
/// The grant was initialized with (lazy) zeroed memory, and any changes will make it owned by
/// the frame allocator.
//
// TODO: strong-count-only Arc?
//
// https://internals.rust-lang.org/t/pre-rfc-rc-and-arc-with-only-strong-count/5828
Allocated { pages: Box<[Option<PageInfo>]> },
Allocated,
/// The grant is not owned, but borrowed from physical memory frames that do not belong to the
/// frame allocator.
PhysBorrowed { base: Frame },
@@ -547,7 +541,7 @@ pub enum Provider {
///
/// All grants in the specified range must be of type Allocated.
// TODO: Vec?
External { address_space: Arc<RwLock<AddrSpace>>, src_base: Page, cow: bool, pages: Option<Box<[Option<PageInfo>]>> },
External { address_space: Arc<RwLock<AddrSpace>>, src_base: Page, cow: bool },
/// The memory is borrowed from another address space, but managed by a scheme via fmap.
// TODO: This is probably a very heavy way to keep track of fmap'd files, perhaps move to the
// ~~context~~ address space?
+94 -1
View File
@@ -3,14 +3,23 @@
use core::cmp;
use core::num::NonZeroUsize;
use core::ops::Deref;
use core::sync::atomic::AtomicUsize;
use crate::arch::rmm::LockedAllocator;
use crate::common::try_box_slice_new;
pub use crate::paging::{PAGE_SIZE, PhysicalAddress};
use crate::rmm::areas;
use alloc::boxed::Box;
use alloc::collections::BTreeMap;
use alloc::sync::Arc;
use alloc::vec::Vec;
use rmm::{
FrameAllocator,
FrameCount,
};
use spin::RwLock;
use crate::syscall::flag::{PartialAllocStrategy, PhysallocFlags};
use crate::syscall::error::{ENOMEM, Error};
@@ -112,11 +121,14 @@ impl Frame {
pub fn range_inclusive(start: Frame, end: Frame) -> FrameIter {
FrameIter { start, end }
}
pub fn next_by(&self, n: usize) -> Self {
pub fn next_by(self, n: usize) -> Self {
Self {
number: self.number.get().checked_add(n).and_then(NonZeroUsize::new).expect("overflow in Frame::next_by"),
}
}
pub fn offset_from(self, from: Self) -> usize {
from.number.get().checked_sub(self.number.get()).expect("overflow in Frame::offset_from")
}
}
pub struct FrameIter {
@@ -176,3 +188,84 @@ impl Drop for RaiiFrame {
crate::memory::deallocate_frames(self.inner, 1);
}
}
pub struct PageInfo {
refcount: AtomicUsize,
cow_refcount: AtomicUsize,
flags: FrameFlags,
_padding: usize,
}
bitflags::bitflags! {
struct FrameFlags: usize {
const NONE = 0;
}
}
// TODO: Very read-heavy RwLock?
pub static SECTIONS: RwLock<Box<[&'static Section]>> = RwLock::new(Box::new([]));
pub struct Section {
base: Frame,
frames: Box<[PageInfo]>,
}
pub const MAX_SECTION_SIZE_BITS: u32 = 27;
pub const MAX_SECTION_SIZE: usize = 1 << MAX_SECTION_SIZE_BITS;
pub const MAX_SECTION_PAGE_COUNT: usize = MAX_SECTION_SIZE / PAGE_SIZE;
#[cold]
pub fn init_mm() {
let mut guard = SECTIONS.write();
let mut sections = Vec::new();
for memory_map_area in areas().iter().filter(|area| area.size > 0) {
let mut pages_left = memory_map_area.size.div_floor(PAGE_SIZE);
let mut base = Frame::containing_address(memory_map_area.base);
while pages_left > 0 {
let section_page_count = core::cmp::min(pages_left, MAX_SECTION_PAGE_COUNT);
sections.push(Box::leak(Box::new(Section {
base,
// TODO: zeroed?
frames: try_box_slice_new(PageInfo::new, section_page_count).expect("failed to allocate pages array"),
})) as &'static Section);
pages_left -= section_page_count;
base = base.next_by(section_page_count);
}
}
sections.sort_unstable_by_key(|s| s.base);
*guard = sections.into_boxed_slice();
}
impl PageInfo {
pub fn new() -> Self {
Self {
refcount: AtomicUsize::new(0),
cow_refcount: AtomicUsize::new(0),
flags: FrameFlags::NONE,
_padding: 0,
}
}
}
pub fn get_page(frame: Frame) -> Option<&'static PageInfo> {
let sections = SECTIONS.read();
let idx = sections
.binary_search_by_key(&frame, |section| section.base)
.unwrap_or_else(|e| e);
let section = sections.get(idx)?;
section.frames.get(frame.offset_from(section.base))
/*
sections
.range(..=frame)
.next_back()
.filter(|(base, section)| frame <= base.next_by(section.frames.len()))
.map(|(base, section)| PageInfoHandle { section, idx: frame.offset_from(*base) })
*/
}