diff --git a/.gitignore b/.gitignore index b2b77488..cb5ce3f3 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,6 @@ Cargo.lock # for vim *.swp + +# for idea +.idea diff --git a/kernel/src/arch/aarch64/consts.rs b/kernel/src/arch/aarch64/consts.rs index 6b9e22d1..dc148df9 100644 --- a/kernel/src/arch/aarch64/consts.rs +++ b/kernel/src/arch/aarch64/consts.rs @@ -5,3 +5,4 @@ pub const KERNEL_HEAP_SIZE: usize = 8 * 1024 * 1024; pub const USER_STACK_OFFSET: usize = 0x0000_8000_0000_0000 - USER_STACK_SIZE; pub const USER_STACK_SIZE: usize = 1 * 1024 * 1024; +pub const KSEG2_START: usize = 0xffff_fe80_0000_0000; diff --git a/kernel/src/arch/aarch64/paging.rs b/kernel/src/arch/aarch64/paging.rs index 1d27b85d..e8664614 100644 --- a/kernel/src/arch/aarch64/paging.rs +++ b/kernel/src/arch/aarch64/paging.rs @@ -10,6 +10,7 @@ use aarch64::paging::{ FrameAllocator, FrameDeallocator, Page as PageAllSizes, Size4KiB, }; use aarch64::{PhysAddr, VirtAddr}; +use core::mem::ManuallyDrop; use log::*; use rcore_memory::paging::*; @@ -205,15 +206,26 @@ impl PageEntry { impl PageTableImpl { /// Unsafely get the current active page table. - /// WARN: You MUST call `core::mem::forget` for it after use! - pub unsafe fn active() -> Self { + /// Using ManuallyDrop to wrap the page table: this is how `core::mem::forget` is implemented now. + pub unsafe fn active() -> ManuallyDrop { let frame = Frame::of_addr(PageTableImpl::active_token() as u64); let table = &mut *frame_to_page_table(frame); - PageTableImpl { + ManuallyDrop::new(PageTableImpl { page_table: MappedPageTable::new(table, frame_to_page_table), root_frame: frame, entry: core::mem::MaybeUninit::uninitialized().into_initialized(), - } + }) + } + /// The method for getting the kernel page table. + /// In aarch64 case kernel page table and user page table are two different tables. + pub unsafe fn kernel_table() -> ManuallyDrop { + let frame = Frame::of_addr(ttbr_el1_read(1).start_address().as_u64()); + let table = &mut *frame_to_page_table(frame); + ManuallyDrop::new(PageTableImpl { + page_table: MappedPageTable::new(table, frame_to_page_table), + root_frame: frame, + entry: core::mem::MaybeUninit::uninitialized().into_initialized(), + }) } } diff --git a/kernel/src/arch/x86_64/consts.rs b/kernel/src/arch/x86_64/consts.rs index 0014edeb..d6c1db6d 100644 --- a/kernel/src/arch/x86_64/consts.rs +++ b/kernel/src/arch/x86_64/consts.rs @@ -5,3 +5,4 @@ pub const PHYSICAL_MEMORY_OFFSET: usize = 0xfffffc00_00000000; pub const USER_STACK_OFFSET: usize = 0x00008000_00000000 - USER_STACK_SIZE; pub const USER_STACK_SIZE: usize = 8 * 1024 * 1024; // 8 MB, the default config of Linux +pub const KSEG2_START: usize = 0xffff_fe80_0000_0000; diff --git a/kernel/src/arch/x86_64/memory.rs b/kernel/src/arch/x86_64/memory.rs index ca575159..c3a697a6 100644 --- a/kernel/src/arch/x86_64/memory.rs +++ b/kernel/src/arch/x86_64/memory.rs @@ -1,8 +1,8 @@ +use super::paging::PageTableImpl; use super::{BootInfo, MemoryRegionType}; use crate::memory::{init_heap, FRAME_ALLOCATOR}; use bitmap_allocator::BitAlloc; use rcore_memory::paging::*; - pub fn init(boot_info: &BootInfo) { init_frame_allocator(boot_info); init_heap(); @@ -20,3 +20,17 @@ fn init_frame_allocator(boot_info: &BootInfo) { } } } + +/// The method for initializing kernel virtual memory space, a memory space of 512 GiB. +/// The memory space is resided at the 509th item of the first-level page table. +/// After the initialization, mapping on this space will be "broadcast" to all page tables. +pub fn init_kernel_kseg2_map() { + let mut page_table = unsafe { PageTableImpl::kernel_table() }; + // Dirty hack here: + // We do not really need the mapping. Indeed, we only need the second-level page table. + // Second-level page table item can then be copied to all page tables safely. + // This hack requires the page table not to recycle the second level page table on unmap. + + page_table.map(0xfffffe8000000000, 0x0).update(); + page_table.unmap(0xfffffe8000000000); +} diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index 66914b8b..f2df8086 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -52,6 +52,8 @@ pub extern "C" fn _start(boot_info: &'static BootInfo) -> ! { // Init GDT gdt::init(); + // Init virtual space + memory::init_kernel_kseg2_map(); //get local apic id of cpu cpu::init(); // Use IOAPIC instead of PIC, use APIC Timer instead of PIT, init serial&keyboard in x86_64 diff --git a/kernel/src/arch/x86_64/paging.rs b/kernel/src/arch/x86_64/paging.rs index 2f8c26ec..761fb2f8 100644 --- a/kernel/src/arch/x86_64/paging.rs +++ b/kernel/src/arch/x86_64/paging.rs @@ -1,4 +1,5 @@ use crate::memory::{alloc_frame, dealloc_frame, phys_to_virt}; +use core::mem::ManuallyDrop; use core::sync::atomic::Ordering; use log::*; use rcore_memory::paging::*; @@ -196,15 +197,20 @@ impl PageEntry { impl PageTableImpl { /// Unsafely get the current active page table. - /// WARN: You MUST call `core::mem::forget` for it after use! - pub unsafe fn active() -> Self { + /// Using ManuallyDrop to wrap the page table: this is how `core::mem::forget` is implemented now. + pub unsafe fn active() -> ManuallyDrop { let frame = Cr3::read().0; let table = &mut *frame_to_page_table(frame); - PageTableImpl( + ManuallyDrop::new(PageTableImpl( MappedPageTable::new(table, frame_to_page_table), core::mem::MaybeUninit::uninitialized().into_initialized(), frame, - ) + )) + } + /// The method for getting the kernel page table. + /// In x86_64 case kernel page table and user page table are the same table. However you have to do the initialization. + pub unsafe fn kernel_table() -> ManuallyDrop { + Self::active() } } @@ -227,14 +233,16 @@ impl PageTableExt for PageTableImpl { let table = unsafe { &mut *frame_to_page_table(Cr3::read().0) }; // Kernel at 0xffff_ff00_0000_0000 // Kernel stack at 0x0000_57ac_0000_0000 (defined in bootloader crate) + // Kseg2 at 0xffff_fe80_0000_0000 let ekernel = table[510].clone(); let ephysical = table[0x1f8].clone(); let estack = table[175].clone(); - + let ekseg2 = table[509].clone(); let table = unsafe { &mut *frame_to_page_table(self.2) }; table[510].set_addr(ekernel.addr(), ekernel.flags() | EF::GLOBAL); table[0x1f8].set_addr(ephysical.addr(), ephysical.flags() | EF::GLOBAL); table[175].set_addr(estack.addr(), estack.flags() | EF::GLOBAL); + table[509].set_addr(ekseg2.addr(), ekseg2.flags() | EF::GLOBAL); } fn token(&self) -> usize {