WIP: Remove SYS_CLONE (to be done in userspace).
This commit is contained in:
+19
-7
@@ -16,13 +16,13 @@ use crate::arch::{interrupt::InterruptStack, paging::PAGE_SIZE};
|
||||
use crate::common::unique::Unique;
|
||||
use crate::context::arch;
|
||||
use crate::context::file::{FileDescriptor, FileDescription};
|
||||
use crate::context::memory::UserGrants;
|
||||
use crate::context::memory::{AddrSpace, new_addrspace, UserGrants};
|
||||
use crate::ipi::{ipi, IpiKind, IpiTarget};
|
||||
use crate::scheme::{SchemeNamespace, FileHandle};
|
||||
use crate::sync::WaitMap;
|
||||
|
||||
use crate::syscall::data::SigAction;
|
||||
use crate::syscall::error::{Result, Error, ENOMEM};
|
||||
use crate::syscall::error::{Result, Error, ENOMEM, ESRCH};
|
||||
use crate::syscall::flag::{SIG_DFL, SigActionFlags};
|
||||
|
||||
/// Unique identifier for a context (i.e. `pid`).
|
||||
@@ -226,8 +226,9 @@ pub struct Context {
|
||||
pub ksig: Option<(arch::Context, Option<Box<[u8]>>, Option<Box<[u8]>>, u8)>,
|
||||
/// Restore ksig context on next switch
|
||||
pub ksig_restore: bool,
|
||||
/// User grants
|
||||
pub grants: Arc<RwLock<UserGrants>>,
|
||||
/// Address space containing a page table lock, and grants. Normally this will have a value,
|
||||
/// but can be None while the context is being reaped.
|
||||
pub addr_space: Option<Arc<RwLock<AddrSpace>>>,
|
||||
/// The name of the context
|
||||
pub name: Arc<RwLock<Box<str>>>,
|
||||
/// The current working directory
|
||||
@@ -307,7 +308,7 @@ impl Context {
|
||||
let syscall_head = AlignedBox::try_zeroed()?;
|
||||
let syscall_tail = AlignedBox::try_zeroed()?;
|
||||
|
||||
Ok(Context {
|
||||
let mut this = Context {
|
||||
id,
|
||||
pgid: id,
|
||||
ppid: ContextId::from(0),
|
||||
@@ -336,7 +337,7 @@ impl Context {
|
||||
kstack: None,
|
||||
ksig: None,
|
||||
ksig_restore: false,
|
||||
grants: Arc::new(RwLock::new(UserGrants::default())),
|
||||
addr_space: None,
|
||||
name: Arc::new(RwLock::new(String::new().into_boxed_str())),
|
||||
cwd: Arc::new(RwLock::new(String::new())),
|
||||
files: Arc::new(RwLock::new(Vec::new())),
|
||||
@@ -351,7 +352,9 @@ impl Context {
|
||||
regs: None,
|
||||
ptrace_stop: false,
|
||||
sigstack: None,
|
||||
})
|
||||
};
|
||||
this.set_addr_space(new_addrspace()?.1);
|
||||
Ok(this)
|
||||
}
|
||||
|
||||
/// Make a relative path absolute
|
||||
@@ -520,4 +523,13 @@ impl Context {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addr_space(&self) -> Result<&Arc<RwLock<AddrSpace>>> {
|
||||
self.addr_space.as_ref().ok_or(Error::new(ESRCH))
|
||||
}
|
||||
pub fn set_addr_space(&mut self, addr_space: Arc<RwLock<AddrSpace>>) {
|
||||
assert!(!self.running);
|
||||
self.arch.set_page_utable(addr_space.read().frame.utable.start_address().data());
|
||||
self.addr_space = Some(addr_space);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-9
@@ -7,7 +7,7 @@ use core::sync::atomic::Ordering;
|
||||
use crate::paging::{ActivePageTable, TableKind};
|
||||
use spin::RwLock;
|
||||
|
||||
use crate::syscall::error::{Result, Error, EAGAIN};
|
||||
use crate::syscall::error::{Result, Error, EAGAIN, ENOMEM};
|
||||
use super::context::{Context, ContextId};
|
||||
|
||||
/// Context list type
|
||||
@@ -79,7 +79,11 @@ impl ContextList {
|
||||
let context_lock = self.new_context()?;
|
||||
{
|
||||
let mut context = context_lock.write();
|
||||
let mut fx = unsafe { Box::from_raw(crate::ALLOCATOR.alloc(Layout::from_size_align_unchecked(1024, 16)) as *mut [u8; 1024]) };
|
||||
let mut fx = unsafe {
|
||||
let ptr = crate::ALLOCATOR.alloc(Layout::from_size_align_unchecked(1024, 16)) as *mut [u8; 1024];
|
||||
if ptr.is_null() { return Err(Error::new(ENOMEM)); }
|
||||
Box::from_raw(ptr)
|
||||
};
|
||||
for b in fx.iter_mut() {
|
||||
*b = 0;
|
||||
}
|
||||
@@ -100,13 +104,6 @@ impl ContextList {
|
||||
context.arch.set_context_handle();
|
||||
}
|
||||
|
||||
let mut new_tables = super::memory::setup_new_utable()?;
|
||||
new_tables.take();
|
||||
|
||||
context.arch.set_page_utable(unsafe { new_tables.new_utable.address() });
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
context.arch.set_page_ktable(unsafe { new_tables.new_ktable.address() });
|
||||
|
||||
context.arch.set_fx(fx.as_ptr() as usize);
|
||||
context.arch.set_stack(stack.as_ptr() as usize + offset);
|
||||
context.kfx = Some(fx);
|
||||
|
||||
+121
-197
@@ -5,7 +5,8 @@ use core::cmp::{self, Eq, Ordering, PartialEq, PartialOrd};
|
||||
use core::fmt::{self, Debug};
|
||||
use core::intrinsics;
|
||||
use core::ops::Deref;
|
||||
use spin::Mutex;
|
||||
use core::sync::atomic;
|
||||
use spin::{Mutex, RwLock};
|
||||
use syscall::{
|
||||
flag::MapFlags,
|
||||
error::*,
|
||||
@@ -14,9 +15,8 @@ use rmm::Arch as _;
|
||||
|
||||
use crate::arch::paging::PAGE_SIZE;
|
||||
use crate::context::file::FileDescriptor;
|
||||
use crate::ipi::{ipi, IpiKind, IpiTarget};
|
||||
use crate::memory::Frame;
|
||||
use crate::paging::mapper::PageFlushAll;
|
||||
use crate::paging::mapper::{Flusher, InactiveFlusher, Mapper, PageFlushAll};
|
||||
use crate::paging::{ActivePageTable, InactivePageTable, Page, PageFlags, PageIter, PhysicalAddress, RmmA, TableKind, VirtualAddress};
|
||||
|
||||
/// Round down to the nearest multiple of page size
|
||||
@@ -47,6 +47,76 @@ impl Drop for UnmapResult {
|
||||
}
|
||||
}
|
||||
|
||||
int_like!(PtId, usize);
|
||||
|
||||
static ADDRSPACES: RwLock<BTreeMap<PtId, Arc<RwLock<AddrSpace>>>> = RwLock::new(BTreeMap::new());
|
||||
static NEXT_PTID: atomic::AtomicUsize = atomic::AtomicUsize::new(1);
|
||||
|
||||
pub fn new_addrspace() -> Result<(PtId, Arc<RwLock<AddrSpace>>)> {
|
||||
let id = PtId::from(NEXT_PTID.fetch_add(1, atomic::Ordering::Relaxed));
|
||||
let arc = Arc::try_new(RwLock::new(AddrSpace::new(id)?)).map_err(|_| Error::new(ENOMEM))?;
|
||||
ADDRSPACES.write().insert(id, Arc::clone(&arc));
|
||||
Ok((id, arc))
|
||||
}
|
||||
pub fn addrspace(id: PtId) -> Option<Arc<RwLock<AddrSpace>>> {
|
||||
ADDRSPACES.read().get(&id).map(Arc::clone)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AddrSpace {
|
||||
pub frame: Tables,
|
||||
pub grants: UserGrants,
|
||||
pub id: PtId,
|
||||
}
|
||||
impl AddrSpace {
|
||||
/// Attempt to clone an existing address space so that all mappings are copied (CoW).
|
||||
// TODO: Actually use CoW!
|
||||
pub fn try_clone(&self) -> Result<(PtId, Arc<RwLock<Self>>)> {
|
||||
let (id, mut new) = new_addrspace()?;
|
||||
|
||||
// TODO: Abstract away this.
|
||||
let (mut inactive, mut active);
|
||||
|
||||
// TODO: aarch64
|
||||
let mut this_mapper = if self.frame.utable.start_address().data() == unsafe { x86::controlregs::cr3() } as usize {
|
||||
active = unsafe { ActivePageTable::new(rmm::TableKind::User) };
|
||||
active.mapper()
|
||||
} else {
|
||||
inactive = unsafe { InactivePageTable::from_address(self.frame.utable.start_address().data()) };
|
||||
inactive.mapper()
|
||||
};
|
||||
let mut new_mapper = unsafe { InactivePageTable::from_address(new.read().frame.utable.start_address().data()) };
|
||||
|
||||
for grant in self.grants.iter() {
|
||||
// TODO: Fail if there are borrowed grants, rather than simply ignoring them?
|
||||
if !grant.is_owned() { continue; }
|
||||
|
||||
let new_grant = Grant::zeroed(Page::containing_address(grant.start_address()), grant.size() / PAGE_SIZE, grant.flags(), &mut new_mapper.mapper(), ())?;
|
||||
|
||||
for page in new_grant.pages() {
|
||||
// FIXME: ENOMEM is wrong here, it cannot fail.
|
||||
let current_frame = this_mapper.translate_page(page).ok_or(Error::new(ENOMEM))?.start_address().data() as *const u8;
|
||||
let new_frame = new_mapper.mapper().translate_page(page).ok_or(Error::new(ENOMEM))?.start_address().data() as *mut u8;
|
||||
|
||||
// TODO: Replace this with CoW
|
||||
unsafe {
|
||||
new_frame.copy_from_nonoverlapping(current_frame, PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
new.write().grants.insert(new_grant);
|
||||
}
|
||||
Ok((id, new))
|
||||
}
|
||||
pub fn new(id: PtId) -> Result<Self> {
|
||||
Ok(Self {
|
||||
grants: UserGrants::new(),
|
||||
frame: setup_new_utable()?,
|
||||
id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UserGrants {
|
||||
inner: BTreeSet<Grant>,
|
||||
@@ -406,7 +476,7 @@ impl Grant {
|
||||
pub fn physmap(from: PhysicalAddress, to: VirtualAddress, size: usize, flags: PageFlags<RmmA>) -> Grant {
|
||||
let mut active_table = unsafe { ActivePageTable::new(to.kind()) };
|
||||
|
||||
let flush_all = PageFlushAll::new();
|
||||
let mut flush_all = PageFlushAll::new();
|
||||
|
||||
let start_page = Page::containing_address(to);
|
||||
let end_page = Page::containing_address(VirtualAddress::new(to.data() + size - 1));
|
||||
@@ -429,40 +499,10 @@ impl Grant {
|
||||
desc_opt: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map(to: VirtualAddress, size: usize, flags: PageFlags<RmmA>) -> Grant {
|
||||
let mut active_table = unsafe { ActivePageTable::new(to.kind()) };
|
||||
|
||||
let flush_all = PageFlushAll::new();
|
||||
|
||||
let start_page = Page::containing_address(to);
|
||||
let end_page = Page::containing_address(VirtualAddress::new(to.data() + size - 1));
|
||||
for page in Page::range_inclusive(start_page, end_page) {
|
||||
let result = active_table
|
||||
.map(page, flags)
|
||||
.expect("TODO: handle ENOMEM in Grant::map");
|
||||
flush_all.consume(result);
|
||||
}
|
||||
|
||||
flush_all.flush();
|
||||
|
||||
Grant {
|
||||
region: Region {
|
||||
start: to,
|
||||
size,
|
||||
},
|
||||
flags,
|
||||
mapped: true,
|
||||
owned: true,
|
||||
desc_opt: None,
|
||||
}
|
||||
}
|
||||
pub fn zeroed_inactive(dst: Page, page_count: usize, flags: PageFlags<RmmA>, table: &mut InactivePageTable) -> Result<Grant> {
|
||||
let mut inactive_mapper = table.mapper();
|
||||
|
||||
pub fn zeroed(dst: Page, page_count: usize, flags: PageFlags<RmmA>, mapper: &mut Mapper, mut flusher: impl Flusher<RmmA>) -> Result<Grant> {
|
||||
for page in Page::range_exclusive(dst, dst.next_by(page_count)) {
|
||||
let flush = inactive_mapper.map(page, flags).map_err(|_| Error::new(ENOMEM))?;
|
||||
unsafe { flush.ignore(); }
|
||||
let flush = mapper.map(page, flags).map_err(|_| Error::new(ENOMEM))?;
|
||||
flusher.consume(flush);
|
||||
}
|
||||
Ok(Grant { region: Region { start: dst.start_address(), size: page_count * PAGE_SIZE }, flags, mapped: true, owned: true, desc_opt: None })
|
||||
}
|
||||
@@ -487,8 +527,6 @@ impl Grant {
|
||||
unsafe { inactive_flush.ignore(); }
|
||||
}
|
||||
|
||||
ipi(IpiKind::Tlb, IpiTarget::Other);
|
||||
|
||||
Grant {
|
||||
region: Region {
|
||||
start: dst,
|
||||
@@ -501,97 +539,22 @@ impl Grant {
|
||||
}
|
||||
}
|
||||
|
||||
/// This function should only be used in clone!
|
||||
pub(crate) fn secret_clone(&self, inactive_table: &mut InactivePageTable) -> Grant {
|
||||
assert!(self.mapped);
|
||||
|
||||
let active_table = unsafe { ActivePageTable::new(TableKind::User) };
|
||||
let mut inactive_mapper = inactive_table.mapper();
|
||||
|
||||
for page in self.pages() {
|
||||
//TODO: One function to do both?
|
||||
let flags = active_table.translate_page_flags(page).expect("grant references unmapped memory");
|
||||
let old_frame = active_table.translate_page(page).expect("grant references unmapped memory");
|
||||
|
||||
let frame = if self.owned {
|
||||
// TODO: CoW paging
|
||||
let new_frame = crate::memory::allocate_frames(1)
|
||||
.expect("TODO: handle ENOMEM in Grant::secret_clone");
|
||||
|
||||
unsafe {
|
||||
// We might as well use self.start_address() directly, but if we were to
|
||||
// introduce SMAP it would help to only move to/from kernel memory, and we are
|
||||
// copying physical frames anyway.
|
||||
let src_pointer = RmmA::phys_to_virt(old_frame.start_address()).data() as *const u8;
|
||||
let dst_pointer = RmmA::phys_to_virt(new_frame.start_address()).data() as *mut u8;
|
||||
dst_pointer.copy_from_nonoverlapping(src_pointer, PAGE_SIZE);
|
||||
}
|
||||
|
||||
new_frame
|
||||
} else {
|
||||
old_frame
|
||||
};
|
||||
|
||||
let flush = inactive_mapper.map_to(page, frame, flags);
|
||||
// SAFETY: This happens within an inactive table.
|
||||
unsafe { flush.ignore() }
|
||||
}
|
||||
|
||||
Grant {
|
||||
region: Region {
|
||||
start: self.region.start,
|
||||
size: self.region.size,
|
||||
},
|
||||
flags: self.flags,
|
||||
mapped: true,
|
||||
owned: self.owned,
|
||||
desc_opt: self.desc_opt.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn flags(&self) -> PageFlags<RmmA> {
|
||||
self.flags
|
||||
}
|
||||
|
||||
pub fn unmap(mut self) -> UnmapResult {
|
||||
pub fn unmap(mut self, mapper: &mut Mapper, mut flusher: impl Flusher<RmmA>) -> UnmapResult {
|
||||
assert!(self.mapped);
|
||||
|
||||
let mut active_table = unsafe { ActivePageTable::new(self.start_address().kind()) };
|
||||
|
||||
let flush_all = PageFlushAll::new();
|
||||
|
||||
for page in self.pages() {
|
||||
let (result, frame) = active_table.unmap_return(page, false);
|
||||
let (result, frame) = mapper.unmap_return(page, false);
|
||||
if self.owned {
|
||||
//TODO: make sure this frame can be safely freed, physical use counter
|
||||
crate::memory::deallocate_frames(frame, 1);
|
||||
}
|
||||
flush_all.consume(result);
|
||||
flusher.consume(result);
|
||||
}
|
||||
|
||||
flush_all.flush();
|
||||
|
||||
self.mapped = false;
|
||||
|
||||
// TODO: This imposes a large cost on unmapping, but that cost cannot be avoided without modifying fmap and funmap
|
||||
UnmapResult { file_desc: self.desc_opt.take() }
|
||||
}
|
||||
|
||||
pub fn unmap_inactive(mut self, other_table: &mut InactivePageTable) -> UnmapResult {
|
||||
assert!(self.mapped);
|
||||
|
||||
for page in self.pages() {
|
||||
let (result, frame) = other_table.mapper().unmap_return(page, false);
|
||||
if self.owned {
|
||||
//TODO: make sure this frame can be safely freed, physical use counter
|
||||
crate::memory::deallocate_frames(frame, 1);
|
||||
}
|
||||
// This is not the active table, so the flush can be ignored
|
||||
unsafe { result.ignore(); }
|
||||
}
|
||||
|
||||
ipi(IpiKind::Tlb, IpiTarget::Other);
|
||||
|
||||
self.mapped = false;
|
||||
|
||||
// TODO: This imposes a large cost on unmapping, but that cost cannot be avoided without modifying fmap and funmap
|
||||
@@ -636,34 +599,6 @@ impl Grant {
|
||||
|
||||
Some((before_grant, self, after_grant))
|
||||
}
|
||||
pub fn move_to_address_space(&mut self, new_start: Page, new_page_table: &mut InactivePageTable, flags: PageFlags<RmmA>, flush_all: &mut PageFlushAll<RmmA>) -> Grant {
|
||||
assert!(self.mapped);
|
||||
|
||||
let mut active_table = unsafe { ActivePageTable::new(TableKind::User) };
|
||||
let mut new_mapper = new_page_table.mapper();
|
||||
let keep_parents = false;
|
||||
|
||||
for (i, page) in self.pages().enumerate() {
|
||||
unsafe {
|
||||
let (flush, frame) = active_table.unmap_return(page, keep_parents);
|
||||
flush_all.consume(flush);
|
||||
|
||||
let flush = new_mapper.map_to(new_start.next_by(i), frame, flags);
|
||||
flush.ignore();
|
||||
}
|
||||
}
|
||||
|
||||
let was_owned = core::mem::replace(&mut self.owned, false);
|
||||
self.mapped = false;
|
||||
|
||||
Self {
|
||||
region: Region::new(new_start.start_address(), self.region.size),
|
||||
flags,
|
||||
mapped: true,
|
||||
owned: was_owned,
|
||||
desc_opt: self.desc_opt.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Grant {
|
||||
@@ -704,79 +639,68 @@ impl Drop for Grant {
|
||||
|
||||
pub const DANGLING: usize = 1 << (usize::BITS - 2);
|
||||
|
||||
pub struct NewTables {
|
||||
#[derive(Debug)]
|
||||
pub struct Tables {
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub new_ktable: InactivePageTable,
|
||||
pub new_utable: InactivePageTable,
|
||||
pub ktable: Frame,
|
||||
|
||||
taken: bool,
|
||||
}
|
||||
impl NewTables {
|
||||
pub fn take(&mut self) {
|
||||
self.taken = true;
|
||||
}
|
||||
pub utable: Frame,
|
||||
}
|
||||
|
||||
impl Drop for NewTables {
|
||||
impl Drop for Tables {
|
||||
fn drop(&mut self) {
|
||||
if self.taken { return }
|
||||
use crate::memory::deallocate_frames;
|
||||
deallocate_frames(Frame::containing_address(PhysicalAddress::new(self.utable.start_address().data())), 1);
|
||||
|
||||
unsafe {
|
||||
use crate::memory::deallocate_frames;
|
||||
deallocate_frames(Frame::containing_address(PhysicalAddress::new(self.new_utable.address())), 1);
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
deallocate_frames(Frame::containing_address(PhysicalAddress::new(self.new_ktable.address())), 1);
|
||||
}
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
deallocate_frames(Frame::containing_address(PhysicalAddress::new(self.ktable.start_address().data())), 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// Allocates a new identically mapped ktable and empty utable (same memory on x86_64).
|
||||
pub fn setup_new_utable() -> Result<NewTables> {
|
||||
let mut new_utable = unsafe { InactivePageTable::new(crate::memory::allocate_frames(1).ok_or(Error::new(ENOMEM))?) };
|
||||
pub fn setup_new_utable() -> Result<Tables> {
|
||||
let mut new_utable = crate::memory::allocate_frames(1).ok_or(Error::new(ENOMEM))?;
|
||||
|
||||
let mut new_ktable = if cfg!(target_arch = "aarch64") {
|
||||
unsafe { InactivePageTable::new(crate::memory::allocate_frames(1).ok_or(Error::new(ENOMEM))?) }
|
||||
} else {
|
||||
unsafe { InactivePageTable::from_address(new_utable.address()) }
|
||||
};
|
||||
// TODO: There is only supposed to be one ktable, right? Use a global variable to store the
|
||||
// ktable (or access it from a control register) on architectures which have ktables, or obtain
|
||||
// it from *any* utable on architectures which do not.
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
let new_ktable = crate::memory::allocate_frames(1).ok_or(Error::new(ENOMEM))?;
|
||||
|
||||
let active_ktable = unsafe { ActivePageTable::new(TableKind::Kernel) };
|
||||
|
||||
// Copy kernel image mapping
|
||||
{
|
||||
let frame = active_ktable.p4()[crate::KERNEL_PML4].pointed_frame().expect("kernel image not mapped");
|
||||
let flags = active_ktable.p4()[crate::KERNEL_PML4].flags();
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
let ktable = &new_ktable;
|
||||
|
||||
new_ktable.mapper().p4_mut()[crate::KERNEL_PML4].set(frame, flags);
|
||||
}
|
||||
#[cfg(not(target_arch = "aarch64"))]
|
||||
let ktable = &new_utable;
|
||||
|
||||
let mut new_mapper = unsafe { InactivePageTable::from_address(ktable.start_address().data()) };
|
||||
|
||||
let mut copy_mapping = |p4_no| {
|
||||
let frame = active_ktable.p4()[p4_no].pointed_frame().expect("kernel image not mapped");
|
||||
let flags = active_ktable.p4()[p4_no].flags();
|
||||
|
||||
new_mapper.mapper().p4_mut()[p4_no].set(frame, flags);
|
||||
};
|
||||
// TODO: Just copy all 256 mappings?
|
||||
|
||||
// Copy kernel image mapping
|
||||
copy_mapping(crate::KERNEL_PML4);
|
||||
|
||||
// Copy kernel heap mapping
|
||||
{
|
||||
let frame = active_ktable.p4()[crate::KERNEL_HEAP_PML4].pointed_frame().expect("kernel heap not mapped");
|
||||
let flags = active_ktable.p4()[crate::KERNEL_HEAP_PML4].flags();
|
||||
|
||||
new_ktable.mapper().p4_mut()[crate::KERNEL_HEAP_PML4].set(frame, flags);
|
||||
}
|
||||
copy_mapping(crate::KERNEL_HEAP_PML4);
|
||||
|
||||
// Copy physmap mapping
|
||||
{
|
||||
let frame = active_ktable.p4()[crate::PHYS_PML4].pointed_frame().expect("physmap not mapped");
|
||||
let flags = active_ktable.p4()[crate::PHYS_PML4].flags();
|
||||
new_ktable.mapper().p4_mut()[crate::PHYS_PML4].set(frame, flags);
|
||||
}
|
||||
// Copy kernel percpu (similar to TLS) mapping.
|
||||
{
|
||||
let frame = active_ktable.p4()[crate::KERNEL_PERCPU_PML4].pointed_frame().expect("kernel TLS not mapped");
|
||||
let flags = active_ktable.p4()[crate::KERNEL_PERCPU_PML4].flags();
|
||||
new_ktable.mapper().p4_mut()[crate::KERNEL_PERCPU_PML4].set(frame, flags);
|
||||
}
|
||||
copy_mapping(crate::PHYS_PML4);
|
||||
|
||||
Ok(NewTables {
|
||||
taken: false,
|
||||
new_utable,
|
||||
// Copy kernel percpu (similar to TLS) mapping.
|
||||
copy_mapping(crate::KERNEL_PERCPU_PML4);
|
||||
|
||||
Ok(Tables {
|
||||
utable: new_utable,
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
new_ktable,
|
||||
ktable: new_ktable,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user