asdf
This commit is contained in:
parent
3e0698d24e
commit
ef5a9759b0
|
|
@ -10,6 +10,7 @@ pub mod registers;
|
||||||
|
|
||||||
use core::{arch::asm, fmt::Debug};
|
use core::{arch::asm, fmt::Debug};
|
||||||
|
|
||||||
|
use bit_field::BitField;
|
||||||
pub use instructions::hlt;
|
pub use instructions::hlt;
|
||||||
|
|
||||||
use crate::memory::VirtAddr;
|
use crate::memory::VirtAddr;
|
||||||
|
|
@ -110,6 +111,57 @@ pub trait VirtAddrExt {
|
||||||
fn into_parts<E: sealed::PageSize>(self) -> (E::Entries, E::Offset);
|
fn into_parts<E: sealed::PageSize>(self) -> (E::Entries, E::Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct PageTableIndexIter {
|
||||||
|
bits: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PageTableIndexIter {
|
||||||
|
pub fn from_ptr_bits_and_level(mut ptr_bits: u64, level: u8) -> Self {
|
||||||
|
ptr_bits.set_bits(0..3, level as u64);
|
||||||
|
ptr_bits.set_bits(3..6, 0); // min_level = 0
|
||||||
|
Self { bits: ptr_bits }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_min_level(mut self, min_level: u8) -> Self {
|
||||||
|
self.bits.set_bits(3..6, min_level as u64);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_ptr_bits_l4(ptr_bits: u64) -> Self {
|
||||||
|
Self::from_ptr_bits_and_level(ptr_bits, 4)
|
||||||
|
}
|
||||||
|
pub fn from_ptr_bits_l5(ptr_bits: u64) -> Self {
|
||||||
|
Self::from_ptr_bits_and_level(ptr_bits, 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn current_level(&self) -> u8 {
|
||||||
|
self.bits.get_bits(0..3) as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
fn min_level(&self) -> u8 {
|
||||||
|
self.bits.get_bits(3..6) as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
fn current_index(&self) -> u16 {
|
||||||
|
let shift = 12 + (self.current_level() * 9);
|
||||||
|
((self.bits >> shift) & 0x1FF) as u16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for PageTableIndexIter {
|
||||||
|
type Item = u16;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let level = self.current_level();
|
||||||
|
if level == self.min_level() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let index = self.current_index();
|
||||||
|
self.bits.set_bits(0..3, (level - 1) as u64);
|
||||||
|
Some(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct L4Entries4K;
|
pub struct L4Entries4K;
|
||||||
pub struct L4Entries2M;
|
pub struct L4Entries2M;
|
||||||
pub struct L4Entries1G;
|
pub struct L4Entries1G;
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,15 @@ use core::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use bit_field::BitField;
|
use bit_field::BitField;
|
||||||
use foundation::mem::{align_down, align_up, is_aligned};
|
use foundation::{
|
||||||
|
DropGuard,
|
||||||
|
mem::{align_down, align_up, is_aligned},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
boot::MemoryRegion,
|
boot::MemoryRegion,
|
||||||
memory::{PhyAddr, VirtAddr, VirtAddrTranslationExt},
|
memory::{PhyAddr, VirtAddr, VirtAddrTranslationExt},
|
||||||
x86_64::{PAGE_SIZE, VirtAddrExt, registers::Cr4},
|
x86_64::{PAGE_SIZE, PageTableIndexIter, VirtAddrExt, registers::Cr4},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[repr(C, align(4096))]
|
#[repr(C, align(4096))]
|
||||||
|
|
@ -94,7 +97,75 @@ impl RootPageTable {
|
||||||
const FOUR_KB: u64 = 4 * 1024;
|
const FOUR_KB: u64 = 4 * 1024;
|
||||||
const TWO_MB: u64 = 2 * 1024 * 1024;
|
const TWO_MB: u64 = 2 * 1024 * 1024;
|
||||||
const ONE_GB: u64 = 1024 * 1024 * 1024;
|
const ONE_GB: u64 = 1024 * 1024 * 1024;
|
||||||
unsafe fn map_to(&mut self, phy: Range<PhyAddr>, virt: VirtAddr, flags: PageFlags) {
|
|
||||||
|
unsafe fn map_to_inner(&mut self, phy: PhyAddr, size: u64, virt: VirtAddr, flags: PageFlags) {
|
||||||
|
assert!(virt.0.is_multiple_of(Self::FOUR_KB));
|
||||||
|
assert!(phy.0.is_multiple_of(Self::FOUR_KB));
|
||||||
|
assert!(size.is_multiple_of(Self::FOUR_KB));
|
||||||
|
|
||||||
|
/// Takes a size and a starting virtual address, and yields a tuple of a virtual address and a page size for each page until the size is exhausted such that each page is the largest possible page size (out of 1GB, 2MB, and 4KB) that is aligned to the virtual address.
|
||||||
|
struct SizeIter {
|
||||||
|
size: u64,
|
||||||
|
virt: VirtAddr,
|
||||||
|
phy: PhyAddr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for SizeIter {
|
||||||
|
type Item = (PhyAddr, VirtAddr, PageType);
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.size == 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.virt.0.is_multiple_of(RootPageTable::ONE_GB)
|
||||||
|
&& self.size >= RootPageTable::ONE_GB
|
||||||
|
{
|
||||||
|
let virt = self.virt;
|
||||||
|
let phy = self.phy;
|
||||||
|
self.virt.0 += RootPageTable::ONE_GB;
|
||||||
|
self.phy.0 += RootPageTable::ONE_GB;
|
||||||
|
self.size -= RootPageTable::ONE_GB;
|
||||||
|
|
||||||
|
Some((phy, virt, PageType::OneGb))
|
||||||
|
} else if self.virt.0.is_multiple_of(RootPageTable::TWO_MB)
|
||||||
|
&& self.size >= RootPageTable::TWO_MB
|
||||||
|
{
|
||||||
|
let virt = self.virt;
|
||||||
|
let phy = self.phy;
|
||||||
|
self.virt.0 += RootPageTable::TWO_MB;
|
||||||
|
self.phy.0 += RootPageTable::TWO_MB;
|
||||||
|
self.size -= RootPageTable::TWO_MB;
|
||||||
|
|
||||||
|
Some((phy, virt, PageType::TwoMb))
|
||||||
|
} else {
|
||||||
|
let virt = self.virt;
|
||||||
|
let phy = self.phy;
|
||||||
|
self.virt.0 += RootPageTable::FOUR_KB;
|
||||||
|
self.phy.0 += RootPageTable::FOUR_KB;
|
||||||
|
self.size -= RootPageTable::FOUR_KB;
|
||||||
|
|
||||||
|
Some((phy, virt, PageType::FourKb))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rec_insert_page(
|
||||||
|
root: *mut PageTable,
|
||||||
|
table: *mut PageTable,
|
||||||
|
remaining_pages: &mut SizeIter,
|
||||||
|
phy: PhyAddr,
|
||||||
|
page_type: PageType,
|
||||||
|
virt: PageTableIndexIter,
|
||||||
|
|
||||||
|
flags: PageFlags,
|
||||||
|
) {
|
||||||
|
// first, descend using the `virt` indices.
|
||||||
|
// when encountering an empty entry, allocate a new page table and insert it, then recurse.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn map_to(&mut self, phy: Range<PhyAddr>, virt: VirtAddr, flags: PageFlags) {
|
||||||
let start = align_down(phy.start.0, PAGE_SIZE as u64);
|
let start = align_down(phy.start.0, PAGE_SIZE as u64);
|
||||||
let end = align_up(phy.end.0, PAGE_SIZE as u64);
|
let end = align_up(phy.end.0, PAGE_SIZE as u64);
|
||||||
let size = end - start;
|
let size = end - start;
|
||||||
|
|
@ -148,8 +219,7 @@ impl RootPageTable {
|
||||||
.lock()
|
.lock()
|
||||||
.allocate_pages(1)
|
.allocate_pages(1)
|
||||||
.expect("Failed to allocate page for page table");
|
.expect("Failed to allocate page for page table");
|
||||||
entry.set_phy(page);
|
entry.insert(page);
|
||||||
entry.set_present(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let as_table = unsafe {
|
let as_table = unsafe {
|
||||||
|
|
@ -293,7 +363,24 @@ impl PageTableEntry {
|
||||||
pub fn present(&self) -> bool {
|
pub fn present(&self) -> bool {
|
||||||
self.contains(PageTableEntryFlags::PRESENT)
|
self.contains(PageTableEntryFlags::PRESENT)
|
||||||
}
|
}
|
||||||
pub fn set_present(&mut self, present: bool) {
|
pub fn insert(&mut self, addr: PhyAddr) {
|
||||||
|
unsafe {
|
||||||
|
self.set_phy(addr);
|
||||||
|
self.set_present(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn take(&mut self) -> Option<PhyAddr> {
|
||||||
|
if self.present() {
|
||||||
|
let phy = self.phy();
|
||||||
|
unsafe { self.set_present(false) };
|
||||||
|
Some(phy)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn set_present(&mut self, present: bool) {
|
||||||
if present {
|
if present {
|
||||||
self.0 |= PageTableEntryFlags::PRESENT;
|
self.0 |= PageTableEntryFlags::PRESENT;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -305,7 +392,7 @@ impl PageTableEntry {
|
||||||
PhyAddr(self.as_raw().get_bits(12..52) << 12)
|
PhyAddr(self.as_raw().get_bits(12..52) << 12)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_phy(&mut self, phy: PhyAddr) {
|
pub unsafe fn set_phy(&mut self, phy: PhyAddr) {
|
||||||
self.as_mut_raw().set_bits(12..52, phy.0 >> 12);
|
self.as_mut_raw().set_bits(12..52, phy.0 >> 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue