mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-26 02:43:24 +00:00
Implement an efficient ranged page table
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
c9cfb98746
commit
24a868a670
@ -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(())
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user