mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-21 23:56:18 +04:00
Added virtual memory support for aarch64 and x86_64.
1. Memory mapping at KSEG2_START(0xffff_fe80_0000_0000) will now be visible to all processes. This feature is required by Loadable Kernel Module when mapping kernel module into memory. 2. Wrapping PageTableImpl::active() into ManuallyDrop, so that no extra "mem::forget" is required. 3. Added PageTableImpl::kernel_table(). This function is the same as active() on x86_64, but not the same on aarch64.
This commit is contained in:
parent
8e5e798d78
commit
da028c1f10
3
.gitignore
vendored
3
.gitignore
vendored
@ -20,3 +20,6 @@ Cargo.lock
|
||||
|
||||
# for vim
|
||||
*.swp
|
||||
|
||||
# for idea
|
||||
.idea
|
||||
|
@ -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;
|
||||
|
@ -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<Self> {
|
||||
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<Self> {
|
||||
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(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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<Self> {
|
||||
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> {
|
||||
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 {
|
||||
|
Loading…
Reference in New Issue
Block a user