From 6ed38f5cb03a48d664e7597992cd8622a51707aa Mon Sep 17 00:00:00 2001 From: Zhang Junyang Date: Mon, 3 Mar 2025 22:13:54 +0800 Subject: [PATCH] Mark all physical memory metadata with memory region info --- ostd/src/boot/smp.rs | 5 ++++- ostd/src/mm/frame/meta.rs | 41 +++++++++++++++++++++++++++++++++++++++ ostd/src/mm/kspace/mod.rs | 11 +++-------- 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/ostd/src/boot/smp.rs b/ostd/src/boot/smp.rs index ab22093b..3a22cb25 100644 --- a/ostd/src/boot/smp.rs +++ b/ostd/src/boot/smp.rs @@ -10,7 +10,10 @@ use spin::Once; use crate::{ arch::boot::smp::{bringup_all_aps, get_num_processors}, cpu, - mm::{frame::Segment, kspace::KernelMeta, paddr_to_vaddr, FrameAllocOptions, PAGE_SIZE}, + mm::{ + frame::{meta::KernelMeta, Segment}, + paddr_to_vaddr, FrameAllocOptions, PAGE_SIZE, + }, task::Task, }; diff --git a/ostd/src/mm/frame/meta.rs b/ostd/src/mm/frame/meta.rs index 1c90a4fe..c7a4f7d7 100644 --- a/ostd/src/mm/frame/meta.rs +++ b/ostd/src/mm/frame/meta.rs @@ -492,6 +492,8 @@ pub(crate) unsafe fn init() -> Segment { let _ = ManuallyDrop::new(early_seg); } + mark_unusable_ranges(); + Segment::from_unused(meta_page_range, |_| MetaPageMeta {}).unwrap() } @@ -535,6 +537,45 @@ fn alloc_meta_frames(tot_nr_frames: usize) -> (usize, Paddr) { (nr_meta_pages, start_paddr) } +/// The metadata of physical pages that cannot be allocated for general use. +#[derive(Debug)] +pub struct UnusableMemoryMeta; +impl_frame_meta_for!(UnusableMemoryMeta); + +/// The metadata of physical pages that contains the kernel itself. +#[derive(Debug, Default)] +pub struct KernelMeta; +impl_frame_meta_for!(KernelMeta); + +macro_rules! mark_ranges { + ($region: expr, $typ: expr) => {{ + debug_assert!($region.base() % PAGE_SIZE == 0); + debug_assert!($region.len() % PAGE_SIZE == 0); + + let seg = Segment::from_unused($region.base()..$region.end(), |_| $typ).unwrap(); + let _ = ManuallyDrop::new(seg); + }}; +} + +fn mark_unusable_ranges() { + let regions = &crate::boot::EARLY_INFO.get().unwrap().memory_regions; + + for region in regions.iter() { + use crate::boot::memory_region::MemoryRegionType; + match region.typ() { + MemoryRegionType::BadMemory => mark_ranges!(region, UnusableMemoryMeta), + MemoryRegionType::Unknown => mark_ranges!(region, UnusableMemoryMeta), + MemoryRegionType::NonVolatileSleep => mark_ranges!(region, UnusableMemoryMeta), + MemoryRegionType::Reserved => mark_ranges!(region, UnusableMemoryMeta), + MemoryRegionType::Kernel => mark_ranges!(region, KernelMeta), + MemoryRegionType::Module => mark_ranges!(region, UnusableMemoryMeta), + MemoryRegionType::Framebuffer => mark_ranges!(region, UnusableMemoryMeta), + MemoryRegionType::Reclaimable => mark_ranges!(region, UnusableMemoryMeta), + MemoryRegionType::Usable => {} // By default it is initialized as usable. + } + } +} + /// Adds a temporary linear mapping for the metadata frames. /// /// We only assume boot page table to contain 4G linear mapping. Thus if the diff --git a/ostd/src/mm/kspace/mod.rs b/ostd/src/mm/kspace/mod.rs index c14d82b0..40875b49 100644 --- a/ostd/src/mm/kspace/mod.rs +++ b/ostd/src/mm/kspace/mod.rs @@ -48,7 +48,7 @@ use spin::Once; use super::{ frame::{ - meta::{impl_frame_meta_for, mapping, MetaPageMeta}, + meta::{mapping, KernelMeta, MetaPageMeta}, Frame, Segment, }, nr_subpage_per_huge, @@ -214,7 +214,8 @@ pub fn init_kernel_page_table(meta_pages: Segment) { }; let mut cursor = kpt.cursor_mut(&from).unwrap(); for frame_paddr in to.step_by(PAGE_SIZE) { - let page = Frame::::from_unused(frame_paddr, KernelMeta).unwrap(); + // SAFETY: They were initialized at `super::frame::meta::init`. + let page = unsafe { Frame::::from_raw(frame_paddr) }; // SAFETY: we are doing mappings for the kernel. unsafe { let _old = cursor.map(page.into(), prop); @@ -246,9 +247,3 @@ pub unsafe fn activate_kernel_page_table() { crate::mm::page_table::boot_pt::dismiss(); } } - -/// The metadata of pages that contains the kernel itself. -#[derive(Debug, Default)] -pub struct KernelMeta; - -impl_frame_meta_for!(KernelMeta);