Move handling of kernel page table entry copying to RMM
This way it can ensure those page table entries never get unmapped, ensuring they are kept in sync between all processes.
This commit is contained in:
@@ -144,7 +144,7 @@ pub(super) fn init(madt: Madt) {
|
||||
// Unmap trampoline
|
||||
let (_frame, _, flush) = unsafe {
|
||||
KernelMapper::lock_rw()
|
||||
.unmap_phys(trampoline_page.start_address(), true)
|
||||
.unmap_phys(trampoline_page.start_address())
|
||||
.expect("failed to unmap trampoline page")
|
||||
};
|
||||
flush.flush();
|
||||
|
||||
@@ -9,9 +9,6 @@ pub use crate::rmm::KernelMapper;
|
||||
pub mod entry;
|
||||
pub mod mapper;
|
||||
|
||||
/// Number of entries per page table
|
||||
pub const ENTRY_COUNT: usize = RmmA::PAGE_ENTRIES;
|
||||
|
||||
/// Size of pages
|
||||
pub const PAGE_SIZE: usize = RmmA::PAGE_SIZE;
|
||||
pub const PAGE_MASK: usize = RmmA::PAGE_OFFSET_MASK;
|
||||
|
||||
@@ -70,7 +70,7 @@ impl LocalApic {
|
||||
|
||||
if !self.x2 {
|
||||
debug!("Detected xAPIC at {:#x}", physaddr.data());
|
||||
if let Some((_entry, _, flush)) = mapper.unmap_phys(virtaddr, true) {
|
||||
if let Some((_entry, _, flush)) = mapper.unmap_phys(virtaddr) {
|
||||
// Unmap xAPIC page if already mapped
|
||||
flush.flush();
|
||||
}
|
||||
|
||||
@@ -23,8 +23,6 @@ pub mod entry {
|
||||
|
||||
pub mod mapper;
|
||||
|
||||
pub const ENTRY_COUNT: usize = RmmA::PAGE_ENTRIES;
|
||||
|
||||
/// Size of pages
|
||||
pub const PAGE_SIZE: usize = RmmA::PAGE_SIZE;
|
||||
pub const PAGE_MASK: usize = RmmA::PAGE_OFFSET_MASK;
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
use crate::{
|
||||
arch::{device::cpu::registers::control_regs, interrupt::InterruptStack, paging::PageMapper},
|
||||
context::{context::Kstack, memory::Table},
|
||||
arch::{device::cpu::registers::control_regs, interrupt::InterruptStack},
|
||||
context::context::Kstack,
|
||||
percpu::PercpuBlock,
|
||||
syscall::FloatRegisters,
|
||||
};
|
||||
use core::{mem, mem::offset_of, ptr, sync::atomic::AtomicBool};
|
||||
use rmm::TableKind;
|
||||
use spin::Once;
|
||||
use syscall::{EnvRegisters, Error, Result, ENOMEM};
|
||||
|
||||
@@ -390,13 +389,3 @@ unsafe extern "C" fn switch_to_inner(_prev: &mut Context, _next: &mut Context) {
|
||||
switch_hook = sym crate::context::switch_finish_hook,
|
||||
);
|
||||
}
|
||||
|
||||
/// Allocates a new empty utable
|
||||
pub fn setup_new_utable() -> Result<Table> {
|
||||
let utable = unsafe {
|
||||
PageMapper::create(TableKind::User, crate::memory::TheFrameAllocator)
|
||||
.ok_or(Error::new(ENOMEM))?
|
||||
};
|
||||
|
||||
Ok(Table { utable })
|
||||
}
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
use crate::{
|
||||
arch::{
|
||||
interrupt::InterruptStack,
|
||||
paging::{PageMapper, ENTRY_COUNT},
|
||||
},
|
||||
context::{context::Kstack, memory::Table},
|
||||
arch::interrupt::InterruptStack,
|
||||
context::context::Kstack,
|
||||
memory::{KernelMapper, RmmA},
|
||||
percpu::PercpuBlock,
|
||||
syscall::FloatRegisters,
|
||||
};
|
||||
use core::{mem::offset_of, sync::atomic::AtomicBool};
|
||||
use rmm::{Arch, TableKind, VirtualAddress};
|
||||
use rmm::{Arch, VirtualAddress};
|
||||
use spin::Once;
|
||||
use syscall::{error::*, EnvRegisters};
|
||||
|
||||
@@ -228,23 +225,3 @@ unsafe extern "C" fn switch_to_inner(prev: &mut Context, next: &mut Context) {
|
||||
switch_hook = sym crate::context::switch_finish_hook,
|
||||
);
|
||||
}
|
||||
|
||||
/// Allocates a new empty utable
|
||||
pub fn setup_new_utable() -> Result<Table> {
|
||||
let utable = unsafe {
|
||||
PageMapper::create(TableKind::User, crate::memory::TheFrameAllocator)
|
||||
.ok_or(Error::new(ENOMEM))?
|
||||
};
|
||||
|
||||
// Copy higher half (kernel) mappings
|
||||
unsafe {
|
||||
let active_ktable = KernelMapper::lock_ro();
|
||||
for pde_no in ENTRY_COUNT / 2..ENTRY_COUNT {
|
||||
if let Some(entry) = active_ktable.table().entry(pde_no) {
|
||||
utable.table().set_entry(pde_no, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Table { utable })
|
||||
}
|
||||
|
||||
+2
-36
@@ -6,13 +6,9 @@ use crate::{
|
||||
syscall::FloatRegisters,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
arch::{interrupt::InterruptStack, paging::PageMapper},
|
||||
context::{context::Kstack, memory::Table},
|
||||
memory::RmmA,
|
||||
};
|
||||
use crate::{arch::interrupt::InterruptStack, context::context::Kstack, memory::RmmA};
|
||||
use core::mem::offset_of;
|
||||
use rmm::{Arch, TableKind, VirtualAddress};
|
||||
use rmm::{Arch, VirtualAddress};
|
||||
use spin::Once;
|
||||
use syscall::{error::*, EnvRegisters};
|
||||
|
||||
@@ -315,33 +311,3 @@ unsafe extern "cdecl" fn switch_to_inner() {
|
||||
switch_hook = sym crate::context::switch_finish_hook,
|
||||
);
|
||||
}
|
||||
|
||||
/// Allocates a new identically mapped ktable and empty utable (same memory on x86)
|
||||
pub fn setup_new_utable() -> Result<Table> {
|
||||
use crate::memory::KernelMapper;
|
||||
|
||||
let utable = unsafe {
|
||||
PageMapper::create(TableKind::User, crate::memory::TheFrameAllocator)
|
||||
.ok_or(Error::new(ENOMEM))?
|
||||
};
|
||||
|
||||
{
|
||||
let active_ktable = KernelMapper::lock_ro();
|
||||
|
||||
let copy_mapping = |p4_no| unsafe {
|
||||
let entry = active_ktable
|
||||
.table()
|
||||
.entry(p4_no)
|
||||
.unwrap_or_else(|| panic!("expected kernel PML {} to be mapped", p4_no));
|
||||
|
||||
utable.table().set_entry(p4_no, entry)
|
||||
};
|
||||
|
||||
// Copy higher half (kernel) mappings
|
||||
for i in 512..1024 {
|
||||
copy_mapping(i);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Table { utable })
|
||||
}
|
||||
|
||||
@@ -5,16 +5,9 @@ use core::{
|
||||
|
||||
use crate::syscall::FloatRegisters;
|
||||
|
||||
use crate::{
|
||||
arch::{
|
||||
interrupt::InterruptStack,
|
||||
paging::{PageMapper, ENTRY_COUNT},
|
||||
},
|
||||
context::{context::Kstack, memory::Table},
|
||||
memory::RmmA,
|
||||
};
|
||||
use crate::{arch::interrupt::InterruptStack, context::context::Kstack, memory::RmmA};
|
||||
use core::mem::offset_of;
|
||||
use rmm::{Arch, TableKind, VirtualAddress};
|
||||
use rmm::{Arch, VirtualAddress};
|
||||
use spin::Once;
|
||||
use syscall::{error::*, EnvRegisters};
|
||||
use x86::msr;
|
||||
@@ -394,24 +387,3 @@ unsafe extern "sysv64" fn switch_to_inner(_prev: &mut Context, _next: &mut Conte
|
||||
switch_hook = sym crate::context::switch_finish_hook,
|
||||
);
|
||||
}
|
||||
|
||||
/// Allocates a new identically mapped ktable and empty utable (same memory on x86_64).
|
||||
pub fn setup_new_utable() -> Result<Table> {
|
||||
use crate::memory::{KernelMapper, TheFrameAllocator};
|
||||
|
||||
let utable = unsafe {
|
||||
PageMapper::create(TableKind::User, TheFrameAllocator).ok_or(Error::new(ENOMEM))?
|
||||
};
|
||||
|
||||
// Copy higher half (kernel) mappings
|
||||
unsafe {
|
||||
let active_ktable = KernelMapper::lock_ro();
|
||||
for pde_no in ENTRY_COUNT / 2..ENTRY_COUNT {
|
||||
if let Some(entry) = active_ktable.table().entry(pde_no) {
|
||||
utable.table().set_entry(pde_no, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Table { utable })
|
||||
}
|
||||
|
||||
+10
-8
@@ -14,7 +14,7 @@ use syscall::{error::*, flag::MapFlags, GrantFlags, MunmapFlags};
|
||||
|
||||
use crate::{
|
||||
arch::paging::PAGE_SIZE,
|
||||
context::{arch::setup_new_utable, file::LockedFileDescription},
|
||||
context::file::LockedFileDescription,
|
||||
cpu_set::LogicalCpuSet,
|
||||
memory::{
|
||||
deallocate_frame, get_page_info, init_frame, the_zeroed_frame, AddRefError, Enomem, Frame,
|
||||
@@ -566,9 +566,14 @@ impl AddrSpace {
|
||||
}
|
||||
|
||||
pub fn new() -> Result<Self> {
|
||||
let utable = unsafe {
|
||||
PageMapper::create(TableKind::User, crate::memory::TheFrameAllocator)
|
||||
.ok_or(Error::new(ENOMEM))?
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
grants: UserGrants::new(),
|
||||
table: setup_new_utable()?,
|
||||
table: Table { utable },
|
||||
mmap_min: MMAP_MIN_DEFAULT,
|
||||
used_by: LogicalCpuSet::empty(),
|
||||
})
|
||||
@@ -1822,11 +1827,9 @@ impl Grant {
|
||||
for src_page in self.span().pages() {
|
||||
let dst_page = dst_base.next_by(src_page.offset_from(self.base));
|
||||
|
||||
let unmap_parents = true;
|
||||
|
||||
// TODO: Validate flags?
|
||||
let Some((phys, _flags, flush)) =
|
||||
(unsafe { src_mapper.unmap_phys(src_page.start_address(), unmap_parents) })
|
||||
(unsafe { src_mapper.unmap_phys(src_page.start_address()) })
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
@@ -1953,7 +1956,7 @@ impl Grant {
|
||||
for i in 0..self.info.page_count {
|
||||
unsafe {
|
||||
let (phys, _, flush) = mapper
|
||||
.unmap_phys(self.base.next_by(i).start_address(), true)
|
||||
.unmap_phys(self.base.next_by(i).start_address())
|
||||
.expect("all physborrowed grants must be fully Present in the page tables");
|
||||
flush.ignore();
|
||||
|
||||
@@ -1969,8 +1972,7 @@ impl Grant {
|
||||
} else {
|
||||
for page in self.span().pages() {
|
||||
// Lazy mappings do not need to be unmapped.
|
||||
let Some((phys, _, flush)) =
|
||||
(unsafe { mapper.unmap_phys(page.start_address(), true) })
|
||||
let Some((phys, _, flush)) = (unsafe { mapper.unmap_phys(page.start_address()) })
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
@@ -295,23 +295,6 @@ unsafe fn map_memory<A: Arch>(areas: &[MemoryArea], mut bump_allocator: &mut Bum
|
||||
let mut mapper = PageMapper::<A, _>::create(TableKind::Kernel, &mut bump_allocator)
|
||||
.expect("failed to create Mapper");
|
||||
|
||||
if cfg!(target_arch = "x86") {
|
||||
// Pre-allocate all kernel PD entries so that when the page table is copied,
|
||||
// these entries are synced between processes
|
||||
for i in 512..1024 {
|
||||
use rmm::{FrameAllocator, PageEntry};
|
||||
|
||||
let phys = mapper
|
||||
.allocator_mut()
|
||||
.allocate_one()
|
||||
.expect("failed to map page table");
|
||||
let flags = A::ENTRY_FLAG_READWRITE | A::ENTRY_FLAG_DEFAULT_TABLE;
|
||||
mapper
|
||||
.table()
|
||||
.set_entry(i, PageEntry::new(phys.data(), flags));
|
||||
}
|
||||
}
|
||||
|
||||
// Map all physical areas at PHYS_OFFSET
|
||||
for area in areas.iter() {
|
||||
for i in 0..area.size / PAGE_SIZE {
|
||||
|
||||
Reference in New Issue
Block a user