From 0aec4d3341b470d9d82b0ba00efb8a68c1b5b04d Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sun, 17 Jul 2022 14:07:56 +0200 Subject: [PATCH] Partial: migrate ACPI to RMM. --- src/acpi/hpet.rs | 23 ++++++++++-------- src/acpi/madt.rs | 28 ++++++++++++++++------ src/acpi/mod.rs | 61 +++++++++++++++++++++++++---------------------- src/acpi/rsdp.rs | 14 ++++++----- src/acpi/rxsdt.rs | 9 ++++--- 5 files changed, 81 insertions(+), 54 deletions(-) diff --git a/src/acpi/hpet.rs b/src/acpi/hpet.rs index 498a668..18e9ee0 100644 --- a/src/acpi/hpet.rs +++ b/src/acpi/hpet.rs @@ -3,7 +3,7 @@ use core::{mem, ptr}; use core::intrinsics::{volatile_load, volatile_store}; use crate::memory::Frame; -use crate::paging::{ActivePageTable, PhysicalAddress, Page, PageFlags, VirtualAddress}; +use crate::paging::{KernelMapper, PhysicalAddress, PageFlags}; use super::sdt::Sdt; use super::{ACPI_TABLE, find_sdt}; @@ -35,10 +35,10 @@ pub struct Hpet { } impl Hpet { - pub fn init(active_table: &mut ActivePageTable) { + pub fn init() { let hpet_sdt = find_sdt("HPET"); let hpet = if hpet_sdt.len() == 1 { - Hpet::new(hpet_sdt[0], active_table) + Hpet::new(hpet_sdt[0]) } else { println!("Unable to find HPET"); return; @@ -52,10 +52,10 @@ impl Hpet { } } - pub fn new(sdt: &'static Sdt, active_table: &mut ActivePageTable) -> Option { + pub fn new(sdt: &'static Sdt) -> Option { if &sdt.signature == b"HPET" && sdt.length as usize >= mem::size_of::() { let s = unsafe { ptr::read((sdt as *const Sdt) as *const Hpet) }; - unsafe { s.base_address.init(active_table) }; + unsafe { s.base_address.init(&mut KernelMapper::lock()) }; Some(s) } else { None @@ -64,18 +64,21 @@ impl Hpet { } impl GenericAddressStructure { - pub unsafe fn init(&self, active_table: &mut ActivePageTable) { - let page = Page::containing_address(VirtualAddress::new(self.address as usize)); + pub unsafe fn init(&self, mapper: &mut KernelMapper) { let frame = Frame::containing_address(PhysicalAddress::new(self.address as usize)); - let result = active_table.map_to(page, frame, PageFlags::new().write(true)); + let (_, result) = mapper + .get_mut() + .expect("KernelMapper locked re-entrant while mapping memory for GenericAddressStructure") + .map_linearly(frame.start_address(), PageFlags::new().write(true)) + .expect("failed to map memory for GenericAddressStructure"); result.flush(); } pub unsafe fn read_u64(&self, offset: usize) -> u64{ - volatile_load((self.address as usize + offset) as *const u64) + volatile_load((self.address as usize + offset + crate::PHYS_OFFSET) as *const u64) } pub unsafe fn write_u64(&mut self, offset: usize, value: u64) { - volatile_store((self.address as usize + offset) as *mut u64, value); + volatile_store((self.address as usize + offset + crate::PHYS_OFFSET) as *mut u64, value); } } diff --git a/src/acpi/madt.rs b/src/acpi/madt.rs index f6dabb6..af8db07 100644 --- a/src/acpi/madt.rs +++ b/src/acpi/madt.rs @@ -1,7 +1,7 @@ use core::mem; use crate::memory::{allocate_frames, Frame}; -use crate::paging::{ActivePageTable, Page, PageFlags, PhysicalAddress, VirtualAddress}; +use crate::paging::{KernelMapper, Page, PageFlags, PhysicalAddress, RmmA, RmmArch, VirtualAddress}; use super::sdt::Sdt; use super::find_sdt; @@ -28,7 +28,7 @@ pub static mut MADT: Option = None; pub const FLAG_PCAT: u32 = 1; impl Madt { - pub fn init(active_table: &mut ActivePageTable) { + pub fn init() { let madt_sdt = find_sdt("APIC"); let madt = if madt_sdt.len() == 1 { Madt::new(madt_sdt[0]) @@ -53,10 +53,18 @@ impl Madt { } if cfg!(feature = "multi_core") { + let mut mapper = KernelMapper::lock(); // Map trampoline let trampoline_frame = Frame::containing_address(PhysicalAddress::new(TRAMPOLINE)); let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE)); - let result = active_table.map_to(trampoline_page, trampoline_frame, PageFlags::new().execute(true).write(true)); //TODO: do not have writable and executable! + let result = unsafe { + //TODO: do not have writable and executable! + mapper + .get_mut() + .expect("expected kernel page table not to be recursively locked while initializing MADT") + .map_phys(trampoline_page.start_address(), trampoline_frame.start_address(), PageFlags::new().execute(true).write(true)) + .expect("failed to map trampoline") + }; result.flush(); // Write trampoline, make sure TRAMPOLINE page is free for use @@ -90,7 +98,7 @@ impl Madt { // Set the ap_ready to 0, volatile unsafe { atomic_store(ap_ready, 0) }; unsafe { atomic_store(ap_cpu_id, ap_local_apic.id as u64) }; - unsafe { atomic_store(ap_page_table, active_table.address() as u64) }; + unsafe { atomic_store(ap_page_table, mapper.table().phys().data() as u64) }; unsafe { atomic_store(ap_stack_start, stack_start as u64) }; unsafe { atomic_store(ap_stack_end, stack_end as u64) }; unsafe { atomic_store(ap_code, kstart_ap as u64) }; @@ -137,7 +145,7 @@ impl Madt { } println!(" Ready"); - active_table.flush_all(); + unsafe { RmmA::invalidate_all(); } } else { println!(" CPU Disabled"); } @@ -147,8 +155,14 @@ impl Madt { } // Unmap trampoline - let (result, _frame) = active_table.unmap_return(trampoline_page, false); - result.flush(); + let (_frame, _, flush) = unsafe { + mapper + .get_mut() + .expect("expected kernel page table not to be recursively locked while initializing MADT") + .unmap_phys(trampoline_page.start_address()) + .expect("failed to unmap trampoline page") + }; + flush.flush(); } } } diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index d65696e..df8ee78 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -10,7 +10,7 @@ use spin::{Once, RwLock}; use crate::log::info; use crate::memory::Frame; -use crate::paging::{ActivePageTable, Page, PageFlags, PhysicalAddress, VirtualAddress}; +use crate::paging::{KernelMapper, Page, PageFlags, PhysicalAddress, RmmA, RmmArch, VirtualAddress}; use self::madt::Madt; use self::rsdt::Rsdt; @@ -28,31 +28,33 @@ mod xsdt; mod rxsdt; mod rsdp; -pub fn get_sdt(sdt_address: usize, active_table: &mut ActivePageTable) -> &'static Sdt { - { - let page = Page::containing_address(VirtualAddress::new(sdt_address + crate::PHYS_OFFSET)); - if active_table.translate_page(page).is_none() { - let frame = Frame::containing_address(PhysicalAddress::new(sdt_address)); - let result = active_table.map_to(page, frame, PageFlags::new()); - result.flush(); - } +unsafe fn map_linearly(addr: PhysicalAddress, len: usize, mapper: &mut crate::paging::PageMapper) { + let base = PhysicalAddress::new(crate::paging::round_down_pages(addr.data())); + let aligned_len = crate::paging::round_up_pages(len + (addr.data() - base.data())); + + for page_idx in 0..aligned_len / crate::memory::PAGE_SIZE { + let (_, flush) = mapper.map_linearly(base.add(page_idx * crate::memory::PAGE_SIZE), PageFlags::new()).expect("failed to linearly map SDT"); + flush.flush(); } +} - let sdt = unsafe { &*((sdt_address + crate::PHYS_OFFSET) as *const Sdt) }; +pub fn get_sdt(sdt_address: usize, mapper: &mut KernelMapper) -> &'static Sdt { + let mapper = mapper + .get_mut() + .expect("KernelMapper mapper locked re-entrant in get_sdt"); - // Map extra SDT frames if required - { - let start_page = Page::containing_address(VirtualAddress::new(sdt_address + 4096 + crate::PHYS_OFFSET)); - let end_page = Page::containing_address(VirtualAddress::new(sdt_address + sdt.length as usize + crate::PHYS_OFFSET)); - for page in Page::range_inclusive(start_page, end_page) { - if active_table.translate_page(page).is_none() { - let frame = Frame::containing_address(PhysicalAddress::new(page.start_address().data() - crate::PHYS_OFFSET)); - let result = active_table.map_to(page, frame, PageFlags::new()); - result.flush(); - } - } + let physaddr = PhysicalAddress::new(sdt_address); + + let sdt; + + unsafe { + const SDT_SIZE: usize = core::mem::size_of::(); + map_linearly(physaddr, SDT_SIZE, mapper); + + sdt = unsafe { &*(RmmA::phys_to_virt(physaddr).data() as *const Sdt) }; + + map_linearly(physaddr.add(SDT_SIZE), sdt.length as usize - SDT_SIZE, mapper); } - sdt } @@ -72,16 +74,19 @@ impl Rxsdt for RxsdtEnum { pub static RXSDT_ENUM: Once = Once::new(); /// Parse the ACPI tables to gather CPU, interrupt, and timer information -pub unsafe fn init(active_table: &mut ActivePageTable, already_supplied_rsdps: Option<(u64, u64)>) { +pub unsafe fn init(already_supplied_rsdps: Option<(u64, u64)>) { { let mut sdt_ptrs = SDT_POINTERS.write(); *sdt_ptrs = Some(BTreeMap::new()); } // Search for RSDP - if let Some(rsdp) = RSDP::get_rsdp(active_table, already_supplied_rsdps) { + let rsdp_opt = RSDP::get_rsdp(&mut KernelMapper::lock(), already_supplied_rsdps); + + if let Some(rsdp) = rsdp_opt { info!("RSDP: {:?}", rsdp); - let rxsdt = get_sdt(rsdp.sdt_address(), active_table); + let rxsdt = get_sdt(rsdp.sdt_address(), &mut KernelMapper::lock()); + dbg!(); for &c in rxsdt.signature.iter() { print!("{}", c as char); @@ -122,7 +127,7 @@ pub unsafe fn init(active_table: &mut ActivePageTable, already_supplied_rsdps: O // TODO: Don't touch ACPI tables in kernel? - rxsdt.map_all(active_table); + rxsdt.map_all(); for sdt_address in rxsdt.iter() { let sdt = &*((sdt_address + crate::PHYS_OFFSET) as *const Sdt); @@ -135,10 +140,10 @@ pub unsafe fn init(active_table: &mut ActivePageTable, already_supplied_rsdps: O // TODO: Enumerate processors in userspace, and then provide an ACPI-independent interface // to initialize enumerated processors to userspace? - Madt::init(active_table); + Madt::init(); // TODO: Let userspace setup HPET, and then provide an interface to specify which timer to // use? - Hpet::init(active_table); + Hpet::init(); } else { println!("NO RSDP FOUND"); } diff --git a/src/acpi/rsdp.rs b/src/acpi/rsdp.rs index d96214b..3d08186 100644 --- a/src/acpi/rsdp.rs +++ b/src/acpi/rsdp.rs @@ -2,7 +2,7 @@ use core::convert::TryFrom; use core::mem; use crate::memory::Frame; -use crate::paging::{ActivePageTable, Page, PageFlags, PhysicalAddress, VirtualAddress}; +use crate::paging::{KernelMapper, Page, PageFlags, PhysicalAddress, VirtualAddress}; /// RSDP #[derive(Copy, Clone, Debug)] @@ -71,16 +71,16 @@ impl RSDP { None } - pub fn get_rsdp(active_table: &mut ActivePageTable, already_supplied_rsdps: Option<(u64, u64)>) -> Option { + pub fn get_rsdp(mapper: &mut KernelMapper, already_supplied_rsdps: Option<(u64, u64)>) -> Option { if let Some((base, size)) = already_supplied_rsdps { let area = unsafe { core::slice::from_raw_parts(base as usize as *const u8, size as usize) }; - Self::get_already_supplied_rsdps(area).or_else(|| Self::get_rsdp_by_searching(active_table)) + Self::get_already_supplied_rsdps(area).or_else(|| Self::get_rsdp_by_searching(mapper)) } else { - Self::get_rsdp_by_searching(active_table) + Self::get_rsdp_by_searching(mapper) } } /// Search for the RSDP - pub fn get_rsdp_by_searching(active_table: &mut ActivePageTable) -> Option { + pub fn get_rsdp_by_searching(mapper: &mut KernelMapper) -> Option { let start_addr = 0xE_0000; let end_addr = 0xF_FFFF; @@ -90,7 +90,9 @@ impl RSDP { let end_frame = Frame::containing_address(PhysicalAddress::new(end_addr)); for frame in Frame::range_inclusive(start_frame, end_frame) { let page = Page::containing_address(VirtualAddress::new(frame.start_address().data())); - let result = active_table.map_to(page, frame, PageFlags::new()); + let result = unsafe { + mapper.get_mut().expect("KernelMapper locked re-entrant while locating RSDPs").map_phys(page.start_address(), frame.start_address(), PageFlags::new()).expect("failed to map page while searching for RSDP") + }; result.flush(); } } diff --git a/src/acpi/rxsdt.rs b/src/acpi/rxsdt.rs index db23880..1f17d79 100644 --- a/src/acpi/rxsdt.rs +++ b/src/acpi/rxsdt.rs @@ -1,6 +1,6 @@ use alloc::boxed::Box; -use crate::paging::ActivePageTable; +use crate::paging::KernelMapper; use super::sdt::Sdt; use super::get_sdt; @@ -8,9 +8,12 @@ use super::get_sdt; pub trait Rxsdt { fn iter(&self) -> Box>; - fn map_all(&self, active_table: &mut ActivePageTable) { + fn map_all(&self) { + let iter = self.iter(); + + let mut mapper = KernelMapper::lock(); for sdt in self.iter() { - get_sdt(sdt, active_table); + get_sdt(sdt, &mut mapper); } }