Implement an efficient ranged page table

This commit is contained in:
Zhang Junyang
2024-03-25 13:25:32 +08:00
committed by Tate, Hongliang Tian
parent c9cfb98746
commit 24a868a670
25 changed files with 1540 additions and 964 deletions

View File

@ -6,13 +6,13 @@ use core::mem::size_of;
use log::warn;
use pod::Pod;
use super::second_stage::{PageTableEntry, PageTableFlags};
use super::second_stage::{DeviceMode, PageTableConsts, PageTableEntry};
use crate::{
bus::pci::PciDeviceLocation,
vm::{
dma::Daddr,
page_table::{DeviceMode, PageTableConfig, PageTableError},
Paddr, PageTable, VmAllocOptions, VmFrame, VmIo,
page_table::{CachePolicy, MapProperty, PageTableError},
Paddr, PageTable, VmAllocOptions, VmFrame, VmIo, VmPerm, PAGE_SIZE,
},
};
@ -123,7 +123,7 @@ impl RootTable {
pub fn specify_device_page_table(
&mut self,
device_id: PciDeviceLocation,
page_table: PageTable<PageTableEntry, DeviceMode>,
page_table: PageTable<DeviceMode, PageTableEntry, PageTableConsts>,
) {
let context_table = self.get_or_create_context_table(device_id);
@ -233,7 +233,7 @@ pub enum AddressWidth {
pub struct ContextTable {
/// Total 32 devices, each device has 8 functions.
entries_frame: VmFrame,
page_tables: BTreeMap<Paddr, PageTable<PageTableEntry, DeviceMode>>,
page_tables: BTreeMap<Paddr, PageTable<DeviceMode, PageTableEntry, PageTableConsts>>,
}
impl ContextTable {
@ -251,7 +251,7 @@ impl ContextTable {
fn get_or_create_page_table(
&mut self,
device: PciDeviceLocation,
) -> &mut PageTable<PageTableEntry, DeviceMode> {
) -> &mut PageTable<DeviceMode, PageTableEntry, PageTableConsts> {
let bus_entry = self
.entries_frame
.read_val::<ContextEntry>(
@ -260,10 +260,7 @@ impl ContextTable {
.unwrap();
if !bus_entry.is_present() {
let table: PageTable<PageTableEntry, DeviceMode> =
PageTable::<PageTableEntry, DeviceMode>::new(PageTableConfig {
address_width: crate::vm::page_table::AddressWidth::Level3,
});
let table = PageTable::<DeviceMode, PageTableEntry, PageTableConsts>::empty();
let address = table.root_paddr();
self.page_tables.insert(address, table);
let entry = ContextEntry(address as u128 | 3 | 0x1_0000_0000_0000_0000);
@ -282,10 +279,9 @@ impl ContextTable {
}
}
///
/// # Safety
///
/// User must ensure the given paddr is a valid one.
/// User must ensure that the given physical address is valid.
unsafe fn map(
&mut self,
device: PciDeviceLocation,
@ -295,22 +291,25 @@ impl ContextTable {
if device.device >= 32 || device.function >= 8 {
return Err(ContextTableError::InvalidDeviceId);
}
self.get_or_create_page_table(device)
.map_with_paddr(
daddr,
paddr,
PageTableFlags::WRITABLE | PageTableFlags::READABLE | PageTableFlags::LAST_PAGE,
)
.map_err(ContextTableError::ModificationError)
self.get_or_create_page_table(device).map_unchecked(
&(daddr..daddr + PAGE_SIZE),
&(paddr..paddr + PAGE_SIZE),
MapProperty {
perm: VmPerm::RW,
cache: CachePolicy::Uncacheable,
},
);
Ok(())
}
fn unmap(&mut self, device: PciDeviceLocation, daddr: Daddr) -> Result<(), ContextTableError> {
if device.device >= 32 || device.function >= 8 {
return Err(ContextTableError::InvalidDeviceId);
}
self.get_or_create_page_table(device)
.unmap(daddr)
.map_err(ContextTableError::ModificationError)
unsafe {
self.get_or_create_page_table(device)
.unmap_unchecked(&(daddr..daddr + PAGE_SIZE));
}
Ok(())
}
}