From 302e55098c20013d920c3f57533e86e7eebbc269 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sun, 17 Jul 2022 14:10:51 +0200 Subject: [PATCH] Migrate misc x86_64 parts to RMM. --- src/arch/x86_64/device/ioapic.rs | 18 ++++++++++------- src/arch/x86_64/device/local_apic.rs | 29 +++++++++++++++------------- src/arch/x86_64/device/mod.rs | 12 ++++++------ src/arch/x86_64/idt.rs | 28 +++------------------------ src/arch/x86_64/interrupt/trace.rs | 9 ++++++--- src/arch/x86_64/start.rs | 20 ++++++++++++------- 6 files changed, 55 insertions(+), 61 deletions(-) diff --git a/src/arch/x86_64/device/ioapic.rs b/src/arch/x86_64/device/ioapic.rs index e92d452..161f807 100644 --- a/src/arch/x86_64/device/ioapic.rs +++ b/src/arch/x86_64/device/ioapic.rs @@ -8,7 +8,7 @@ use crate::acpi::madt::{self, Madt, MadtEntry, MadtIoApic, MadtIntSrcOverride}; use crate::arch::interrupt::irq; use crate::memory::Frame; -use crate::paging::{ActivePageTable, Page, PageFlags, PhysicalAddress, VirtualAddress}; +use crate::paging::{KernelMapper, Page, PageFlags, PhysicalAddress, RmmA, RmmArch}; use crate::paging::entry::EntryFlags; use super::pic; @@ -229,16 +229,20 @@ pub fn src_overrides() -> &'static [Override] { } #[cfg(feature = "acpi")] -pub unsafe fn handle_ioapic(active_table: &mut ActivePageTable, madt_ioapic: &'static MadtIoApic) { +pub unsafe fn handle_ioapic(mapper: &mut KernelMapper, madt_ioapic: &'static MadtIoApic) { // map the I/O APIC registers let frame = Frame::containing_address(PhysicalAddress::new(madt_ioapic.address as usize)); - let page = Page::containing_address(VirtualAddress::new(madt_ioapic.address as usize + crate::PHYS_OFFSET)); + let page = Page::containing_address(RmmA::phys_to_virt(frame.start_address())); - assert_eq!(active_table.translate_page(page), None); + assert!(mapper.translate(page.start_address()).is_none()); - let result = active_table.map_to(page, frame, PageFlags::new().write(true).custom_flag(EntryFlags::NO_CACHE.bits(), true)); - result.flush(); + mapper + .get_mut() + .expect("expected KernelMapper not to be locked re-entrant while mapping I/O APIC memory") + .map_phys(page.start_address(), frame.start_address(), PageFlags::new().write(true).custom_flag(EntryFlags::NO_CACHE.bits(), true)) + .expect("failed to map I/O APIC") + .flush(); let ioapic_registers = page.start_address().data() as *const u32; let ioapic = IoApic::new(ioapic_registers, madt_ioapic.gsi_base); @@ -280,7 +284,7 @@ pub unsafe fn handle_src_override(src_override: &'static MadtIntSrcOverride) { SRC_OVERRIDES.get_or_insert_with(Vec::new).push(over); } -pub unsafe fn init(active_table: &mut ActivePageTable) { +pub unsafe fn init(active_table: &mut KernelMapper) { let bsp_apic_id = x86::cpuid::CpuId::new().get_feature_info().unwrap().initial_local_apic_id(); // TODO // search the madt for all IOAPICs. diff --git a/src/arch/x86_64/device/local_apic.rs b/src/arch/x86_64/device/local_apic.rs index 913781e..100341e 100644 --- a/src/arch/x86_64/device/local_apic.rs +++ b/src/arch/x86_64/device/local_apic.rs @@ -3,15 +3,14 @@ use core::intrinsics::{volatile_load, volatile_store}; use x86::cpuid::CpuId; use x86::msr::*; -use crate::memory::Frame; -use crate::paging::{ActivePageTable, PhysicalAddress, Page, PageFlags, VirtualAddress}; +use crate::paging::{KernelMapper, PhysicalAddress, PageFlags, RmmA, RmmArch}; pub static mut LOCAL_APIC: LocalApic = LocalApic { address: 0, x2: false }; -pub unsafe fn init(active_table: &mut ActivePageTable) { +pub unsafe fn init(active_table: &mut KernelMapper) { LOCAL_APIC.init(active_table); } @@ -41,21 +40,25 @@ pub fn bsp_apic_id() -> Option { } impl LocalApic { - unsafe fn init(&mut self, active_table: &mut ActivePageTable) { - self.address = (rdmsr(IA32_APIC_BASE) as usize & 0xFFFF_0000) + crate::PHYS_OFFSET; + unsafe fn init(&mut self, mapper: &mut KernelMapper) { + let mapper = mapper.get_mut().expect("expected KernelMapper not to be locked re-entrant while initializing LAPIC"); + + let physaddr = PhysicalAddress::new(rdmsr(IA32_APIC_BASE) as usize & 0xFFFF_0000); + let virtaddr = RmmA::phys_to_virt(physaddr); + + self.address = virtaddr.data(); self.x2 = CpuId::new().get_feature_info().unwrap().has_x2apic(); if ! self.x2 { - let page = Page::containing_address(VirtualAddress::new(self.address)); - let frame = Frame::containing_address(PhysicalAddress::new(self.address - crate::PHYS_OFFSET)); - log::info!("Detected xAPIC at {:#x}", frame.start_address().data()); - if active_table.translate_page(page).is_some() { + log::info!("Detected xAPIC at {:#x}", physaddr.data()); + if let Some((_entry, _, flush)) = mapper.unmap_phys(virtaddr) { // Unmap xAPIC page if already mapped - let (result, _frame) = active_table.unmap_return(page, true); - result.flush(); + flush.flush(); } - let result = active_table.map_to(page, frame, PageFlags::new().write(true)); - result.flush(); + mapper + .map_phys(virtaddr, physaddr, PageFlags::new().write(true)) + .expect("failed to map local APIC memory") + .flush(); } else { log::info!("Detected x2APIC"); } diff --git a/src/arch/x86_64/device/mod.rs b/src/arch/x86_64/device/mod.rs index 942d320..eafa245 100644 --- a/src/arch/x86_64/device/mod.rs +++ b/src/arch/x86_64/device/mod.rs @@ -1,5 +1,3 @@ -use crate::paging::ActivePageTable; - pub mod cpu; pub mod ioapic; pub mod local_apic; @@ -12,13 +10,15 @@ pub mod hpet; #[cfg(feature = "system76_ec_debug")] pub mod system76_ec; -pub unsafe fn init(active_table: &mut ActivePageTable) { +use crate::paging::KernelMapper; + +pub unsafe fn init() { pic::init(); - local_apic::init(active_table); + local_apic::init(&mut KernelMapper::lock()); } -pub unsafe fn init_after_acpi(_active_table: &mut ActivePageTable) { +pub unsafe fn init_after_acpi() { // this will disable the IOAPIC if needed. - //ioapic::init(active_table); + //ioapic::init(mapper); } #[cfg(feature = "acpi")] diff --git a/src/arch/x86_64/idt.rs b/src/arch/x86_64/idt.rs index 595b6a0..4a71269 100644 --- a/src/arch/x86_64/idt.rs +++ b/src/arch/x86_64/idt.rs @@ -10,7 +10,6 @@ use x86::dtables::{self, DescriptorTablePointer}; use crate::interrupt::*; use crate::ipi::IpiKind; -use crate::paging::PageFlags; use spin::RwLock; @@ -172,32 +171,11 @@ pub unsafe fn init_generic(is_bsp: bool, idt: &mut Idt) { let frames = crate::memory::allocate_frames(page_count) .expect("failed to allocate pages for backup interrupt stack"); - // Map them linearly, i.e. PHYS_OFFSET + physaddr. - let base_address = { - use crate::memory::{Frame, PhysicalAddress}; - use crate::paging::{ActivePageTable, Page, VirtualAddress}; + use crate::paging::{RmmA, RmmArch}; - let base_virtual_address = VirtualAddress::new(frames.start_address().data() + crate::PHYS_OFFSET); - let mut active_table = ActivePageTable::new(base_virtual_address.kind()); + // Physical pages are mapped linearly. So is the linearly mapped virtual memory. + let base_address = RmmA::phys_to_virt(frames.start_address()); - for i in 0..page_count { - let virtual_address = VirtualAddress::new(base_virtual_address.data() + i * crate::memory::PAGE_SIZE); - let physical_address = PhysicalAddress::new(frames.start_address().data() + i * crate::memory::PAGE_SIZE); - let page = Page::containing_address(virtual_address); - - let flags = PageFlags::new().write(true); - - let flusher = if let Some(already_mapped) = active_table.translate_page(page) { - assert_eq!(already_mapped.start_address(), physical_address, "address already mapped, but non-linearly"); - active_table.remap(page, flags) - } else { - active_table.map_to(page, Frame::containing_address(physical_address), flags) - }; - flusher.flush(); - } - - base_virtual_address - }; // Stack always grows downwards. let address = base_address.data() + BACKUP_STACK_SIZE; diff --git a/src/arch/x86_64/interrupt/trace.rs b/src/arch/x86_64/interrupt/trace.rs index 1b72260..ecff30e 100644 --- a/src/arch/x86_64/interrupt/trace.rs +++ b/src/arch/x86_64/interrupt/trace.rs @@ -1,8 +1,9 @@ use core::{mem, str}; + use goblin::elf::sym; use rustc_demangle::demangle; -use crate::paging::{ActivePageTable, TableKind, VirtualAddress}; +use crate::{context, paging::{KernelMapper, VirtualAddress}}; /// Get a stack trace //TODO: Check for stack being mapped before dereferencing @@ -13,12 +14,14 @@ pub unsafe fn stack_trace() { println!("TRACE: {:>016X}", rbp); //Maximum 64 frames - let active_table = ActivePageTable::new(TableKind::User); + + let mapper = KernelMapper::lock(); + for _frame in 0..64 { if let Some(rip_rbp) = rbp.checked_add(mem::size_of::()) { let rbp_virt = VirtualAddress::new(rbp); let rip_rbp_virt = VirtualAddress::new(rip_rbp); - if rbp_virt.is_canonical() && rip_rbp_virt.is_canonical() && active_table.translate(rbp_virt).is_some() && active_table.translate(rip_rbp_virt).is_some() { + if rbp_virt.is_canonical() && rip_rbp_virt.is_canonical() && mapper.translate(rbp_virt).is_some() && mapper.translate(rip_rbp_virt).is_some() { let rip = *(rip_rbp as *const usize); if rip == 0 { println!(" {:>016X}: EMPTY RETURN", rbp); diff --git a/src/arch/x86_64/start.rs b/src/arch/x86_64/start.rs index fb4c8a3..b8acccd 100644 --- a/src/arch/x86_64/start.rs +++ b/src/arch/x86_64/start.rs @@ -18,7 +18,7 @@ use crate::gdt; use crate::idt; use crate::interrupt; use crate::log::{self, info}; -use crate::paging; +use crate::paging::{self, KernelMapper}; /// Test of zero values in BSS. static BSS_TEST_ZERO: usize = 0; @@ -131,7 +131,7 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! { ); // Initialize paging - let (mut active_table, tcb_offset) = paging::init(0); + let tcb_offset = paging::init(0); // Set up GDT after paging with TLS gdt::init_paging(0, tcb_offset, args.stack_base + args.stack_size); @@ -158,7 +158,7 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! { BSP_READY.store(false, Ordering::SeqCst); // Setup kernel heap - allocator::init(&mut active_table); + allocator::init(); // Set up double buffer for grpahical debug now that heap is available #[cfg(feature = "graphical_debug")] @@ -170,17 +170,17 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! { log::init(); // Initialize devices - device::init(&mut active_table); + device::init(); // Read ACPI tables, starts APs #[cfg(feature = "acpi")] { - acpi::init(&mut active_table, if args.acpi_rsdps_base != 0 && args.acpi_rsdps_size > 0 { + acpi::init(if args.acpi_rsdps_base != 0 && args.acpi_rsdps_size > 0 { Some(((args.acpi_rsdps_base + crate::PHYS_OFFSET) as u64, args.acpi_rsdps_size as u64)) } else { None }); - device::init_after_acpi(&mut active_table); + device::init_after_acpi(); } // Initialize all of the non-core devices not otherwise needed to complete initialization @@ -230,7 +230,13 @@ pub unsafe extern fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! { idt::init(); // Initialize paging - let tcb_offset = paging::init_ap(cpu_id, bsp_table); + let tcb_offset = { + use crate::paging::{PageMapper, PhysicalAddress}; + use crate::rmm::FRAME_ALLOCATOR; + + let mut mapper = KernelMapper::lock_for_manual_mapper(cpu_id, PageMapper::new(PhysicalAddress::new(bsp_table), FRAME_ALLOCATOR)); + paging::init_ap(cpu_id, &mut mapper) + }; // Set up GDT with TLS gdt::init_paging(cpu_id as u32, tcb_offset, stack_end);