Remove FmapCtxt.
This commit is contained in:
@@ -30,7 +30,7 @@ use crate::syscall::flag::{SIG_DFL, SigActionFlags};
|
||||
/// Unique identifier for a context (i.e. `pid`).
|
||||
use ::core::sync::atomic::AtomicUsize;
|
||||
|
||||
use super::memory::FmapCtxt;
|
||||
use super::memory::GrantFileRef;
|
||||
int_like!(ContextId, AtomicContextId, usize, AtomicUsize);
|
||||
|
||||
/// The status of a context - used for scheduling
|
||||
@@ -64,7 +64,7 @@ impl Status {
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum HardBlockedReason {
|
||||
AwaitingMmap { ctxt: Arc<FmapCtxt> },
|
||||
AwaitingMmap { file_ref: GrantFileRef },
|
||||
// TODO: PageFaultOom?
|
||||
// TODO: NotYetStarted/ManuallyBlocked (when new contexts are created)
|
||||
// TODO: ptrace_stop?
|
||||
|
||||
+42
-42
@@ -9,7 +9,7 @@ use syscall::{
|
||||
flag::MapFlags,
|
||||
error::*,
|
||||
};
|
||||
use rmm::Arch as _;
|
||||
use rmm::{Arch as _, PhysicalAddress};
|
||||
|
||||
use crate::arch::paging::PAGE_SIZE;
|
||||
use crate::memory::{Enomem, Frame, get_page_info, PageInfo};
|
||||
@@ -90,7 +90,7 @@ impl AddrSpace {
|
||||
new_mapper,
|
||||
(),
|
||||
)?,
|
||||
Provider::Allocated { ref fmap } => Grant::cow(
|
||||
Provider::Allocated { ref cow_file_ref } => Grant::cow(
|
||||
Arc::clone(&self_arc),
|
||||
grant_base,
|
||||
grant_base,
|
||||
@@ -100,12 +100,12 @@ impl AddrSpace {
|
||||
new_mapper,
|
||||
&mut this_flusher,
|
||||
(),
|
||||
fmap.as_ref().map(Arc::clone),
|
||||
cow_file_ref.clone(),
|
||||
)?,
|
||||
|
||||
// MAP_SHARED grants are retained by reference, across address space clones (across
|
||||
// forks on monolithic kernels).
|
||||
Provider::External { ref address_space, src_base, ref fmap } => Grant::borrow_grant(
|
||||
Provider::External { ref address_space, src_base } => Grant::borrow_grant(
|
||||
Arc::clone(&address_space),
|
||||
grant_base,
|
||||
grant_base,
|
||||
@@ -113,7 +113,6 @@ impl AddrSpace {
|
||||
new_mapper,
|
||||
(),
|
||||
false,
|
||||
fmap.as_ref().map(Arc::clone),
|
||||
)?,
|
||||
// TODO: "clone grant using fmap"
|
||||
Provider::FmapBorrowed { .. } => continue,
|
||||
@@ -562,16 +561,11 @@ pub struct GrantInfo {
|
||||
pub(crate) provider: Provider,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FmapCtxt {
|
||||
pub file_ref: GrantFileRef,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Provider {
|
||||
/// The grant was initialized with (lazy) zeroed memory, and any changes will make it owned by
|
||||
/// the frame allocator.
|
||||
Allocated { fmap: Option<Arc<FmapCtxt>> },
|
||||
Allocated { cow_file_ref: Option<GrantFileRef> },
|
||||
|
||||
/// The grant is not owned, but borrowed from physical memory frames that do not belong to the
|
||||
/// frame allocator.
|
||||
@@ -579,10 +573,11 @@ pub enum Provider {
|
||||
|
||||
/// The memory is borrowed directly from another address space.
|
||||
///
|
||||
/// All grants in the specified range must be of type Allocated.
|
||||
External { address_space: Arc<RwLock<AddrSpace>>, src_base: Page, fmap: Option<Arc<FmapCtxt>> },
|
||||
/// Those grants will be pinned, and thus cannot be removed until they are unpinned, when this
|
||||
/// grant is unmapped.
|
||||
External { address_space: Arc<RwLock<AddrSpace>>, src_base: Page },
|
||||
|
||||
FmapBorrowed { fmap: Arc<FmapCtxt> },
|
||||
FmapBorrowed { file_ref: GrantFileRef },
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -638,14 +633,14 @@ impl Grant {
|
||||
page_count: span.count,
|
||||
flags,
|
||||
mapped: true,
|
||||
provider: Provider::Allocated { fmap: None },
|
||||
provider: Provider::Allocated { cow_file_ref: None },
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// XXX: borrow_grant is needed because of the borrow checker (iterator invalidation), maybe
|
||||
// borrow_grant/borrow can be abstracted somehow?
|
||||
pub fn borrow_grant(src_address_space_lock: Arc<RwLock<AddrSpace>>, src_base: Page, dst_base: Page, src_info: &GrantInfo, mapper: &mut PageMapper, dst_flusher: impl Flusher<RmmA>, eager: bool, fmap: Option<Arc<FmapCtxt>>) -> Result<Grant, Enomem> {
|
||||
pub fn borrow_grant(src_address_space_lock: Arc<RwLock<AddrSpace>>, src_base: Page, dst_base: Page, src_info: &GrantInfo, mapper: &mut PageMapper, dst_flusher: impl Flusher<RmmA>, eager: bool) -> Result<Grant, Enomem> {
|
||||
Ok(Grant {
|
||||
base: dst_base,
|
||||
info: GrantInfo {
|
||||
@@ -655,13 +650,12 @@ impl Grant {
|
||||
provider: Provider::External {
|
||||
src_base,
|
||||
address_space: src_address_space_lock,
|
||||
fmap,
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
pub fn borrow_fmap(span: PageSpan, flags: PageFlags<RmmA>, fmap: Arc<FmapCtxt>, src: Option<BorrowedFmapSource<'_>>, mapper: &mut PageMapper, mut flusher: impl Flusher<RmmA>) -> Self {
|
||||
pub fn borrow_fmap(span: PageSpan, flags: PageFlags<RmmA>, file_ref: GrantFileRef, src: Option<BorrowedFmapSource<'_>>, mapper: &mut PageMapper, mut flusher: impl Flusher<RmmA>) -> Self {
|
||||
if let Some(mut src) = src {
|
||||
for dst_page in span.pages() {
|
||||
let src_page = src.src_page.next_by(dst_page.offset_from(span.base));
|
||||
@@ -679,7 +673,7 @@ impl Grant {
|
||||
page_count: span.count,
|
||||
mapped: true,
|
||||
flags,
|
||||
provider: Provider::FmapBorrowed { fmap },
|
||||
provider: Provider::FmapBorrowed { file_ref },
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -690,6 +684,7 @@ impl Grant {
|
||||
/// mapping them into `[dst_base, dst_base+page_count)`. The destination pages will lazily read
|
||||
/// the page tables of the source pages, but once present in the destination address space,
|
||||
/// pages that are unmaped or moved will not be made visible to the destination address space.
|
||||
// TODO: Return only one grant
|
||||
pub fn borrow(
|
||||
src_address_space_lock: Arc<RwLock<AddrSpace>>,
|
||||
src_address_space: &AddrSpace,
|
||||
@@ -738,16 +733,15 @@ impl Grant {
|
||||
flags,
|
||||
mapped: true,
|
||||
provider: match src_grant.provider {
|
||||
Provider::Allocated { ref fmap } => Provider::External {
|
||||
Provider::Allocated { .. } => Provider::External {
|
||||
src_base,
|
||||
address_space: Arc::clone(&src_address_space_lock),
|
||||
fmap: fmap.as_ref().map(Arc::clone),
|
||||
},
|
||||
Provider::PhysBorrowed { base: src_phys_base } => Provider::PhysBorrowed {
|
||||
base: src_phys_base.next_by(offset_from_src_base),
|
||||
},
|
||||
Provider::External { ref address_space, src_base, ref fmap } => Provider::External { address_space: Arc::clone(address_space), src_base, fmap: fmap.as_ref().map(Arc::clone) },
|
||||
Provider::FmapBorrowed { ref fmap } => Provider::FmapBorrowed { fmap: Arc::clone(fmap) }
|
||||
Provider::External { ref address_space, src_base } => Provider::External { address_space: Arc::clone(address_space), src_base },
|
||||
Provider::FmapBorrowed { ref file_ref } => Provider::FmapBorrowed { file_ref: file_ref.clone() }
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -776,7 +770,7 @@ impl Grant {
|
||||
dst_mapper: &mut PageMapper,
|
||||
mut src_flusher: impl Flusher<RmmA>,
|
||||
mut dst_flusher: impl Flusher<RmmA>,
|
||||
fmap: Option<Arc<FmapCtxt>>,
|
||||
cow_file_ref: Option<GrantFileRef>,
|
||||
) -> Result<Grant, Enomem> {
|
||||
// TODO: Page table iterator
|
||||
for page_idx in 0..page_count {
|
||||
@@ -809,7 +803,7 @@ impl Grant {
|
||||
page_count,
|
||||
flags,
|
||||
mapped: true,
|
||||
provider: Provider::Allocated { fmap },
|
||||
provider: Provider::Allocated { cow_file_ref },
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -868,11 +862,15 @@ impl Grant {
|
||||
|
||||
self.info.mapped = false;
|
||||
|
||||
// Dummy value, won't be read.
|
||||
let dangling_frame = Frame::containing_address(PhysicalAddress::new(PAGE_SIZE));
|
||||
let provider = core::mem::replace(&mut self.info.provider, Provider::PhysBorrowed { base: dangling_frame });
|
||||
|
||||
UnmapResult {
|
||||
file_desc: if let Provider::Allocated { ref mut fmap } | Provider::External { ref mut fmap, .. } = self.info.provider && let Some(fmap) = fmap.take() && let Ok(ctxt) = Arc::try_unwrap(fmap) {
|
||||
Some(ctxt.file_ref)
|
||||
} else {
|
||||
None
|
||||
file_desc: match provider {
|
||||
Provider::Allocated { cow_file_ref } => cow_file_ref,
|
||||
Provider::FmapBorrowed { file_ref } => Some(file_ref),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -903,20 +901,20 @@ impl Grant {
|
||||
mapped: self.info.mapped,
|
||||
page_count: span.count,
|
||||
provider: match self.info.provider {
|
||||
Provider::External { ref address_space, src_base, ref fmap } => Provider::External {
|
||||
Provider::External { ref address_space, src_base } => Provider::External {
|
||||
address_space: Arc::clone(address_space),
|
||||
src_base,
|
||||
fmap: fmap.as_ref().map(Arc::clone),
|
||||
},
|
||||
Provider::Allocated { ref fmap } => Provider::Allocated { fmap: fmap.as_ref().map(Arc::clone) },
|
||||
Provider::Allocated { ref cow_file_ref } => Provider::Allocated { cow_file_ref: cow_file_ref.clone() },
|
||||
Provider::PhysBorrowed { ref base } => Provider::PhysBorrowed { base: base.clone() },
|
||||
Provider::FmapBorrowed { ref fmap } => Provider::FmapBorrowed { fmap: Arc::clone(fmap) }
|
||||
Provider::FmapBorrowed { ref file_ref } => Provider::FmapBorrowed { file_ref: file_ref.clone() }
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
match self.info.provider {
|
||||
Provider::PhysBorrowed { ref mut base } => *base = base.next_by(before_grant.as_ref().map_or(0, |g| g.info.page_count)),
|
||||
// TODO: Adjust cow_file_ref offset
|
||||
Provider::Allocated { .. } | Provider::External { .. } | Provider::FmapBorrowed { .. } => (),
|
||||
}
|
||||
|
||||
@@ -928,15 +926,15 @@ impl Grant {
|
||||
mapped: self.info.mapped,
|
||||
page_count: span.count,
|
||||
provider: match self.info.provider {
|
||||
Provider::Allocated { ref fmap } => Provider::Allocated { fmap: fmap.as_ref().map(Arc::clone) },
|
||||
Provider::External { ref address_space, src_base, ref fmap } => Provider::External {
|
||||
// TODO: Adjust offset
|
||||
Provider::Allocated { ref cow_file_ref } => Provider::Allocated { cow_file_ref: cow_file_ref.clone() },
|
||||
Provider::External { ref address_space, src_base } => Provider::External {
|
||||
address_space: Arc::clone(address_space),
|
||||
src_base,
|
||||
fmap: fmap.as_ref().map(Arc::clone),
|
||||
},
|
||||
|
||||
Provider::PhysBorrowed { base } => Provider::PhysBorrowed { base: base.next_by(this_span.count) },
|
||||
Provider::FmapBorrowed { ref fmap } => Provider::FmapBorrowed { fmap: Arc::clone(fmap) }
|
||||
Provider::FmapBorrowed { ref file_ref } => Provider::FmapBorrowed { file_ref: file_ref.clone() },
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -1246,23 +1244,25 @@ pub fn try_correcting_page_tables(faulting_page: Page, access: AccessMode) -> Re
|
||||
map_zeroed(&mut guard.table.utable, src_page, grant_flags, access == AccessMode::Write)?
|
||||
}
|
||||
}
|
||||
Provider::FmapBorrowed { ref fmap } => {
|
||||
let ctxt = Arc::clone(fmap);
|
||||
// TODO: NonfatalInternalError if !MAP_LAZY and this page fault occurs.
|
||||
|
||||
Provider::FmapBorrowed { ref file_ref } => {
|
||||
let file_ref = file_ref.clone();
|
||||
let flags = map_flags(grant_info.flags());
|
||||
drop(addr_space_guard);
|
||||
|
||||
let (scheme_id, scheme_number) = match ctxt.file_ref.description.read() {
|
||||
let (scheme_id, scheme_number) = match file_ref.description.read() {
|
||||
ref desc => (desc.scheme, desc.number),
|
||||
};
|
||||
let user_inner = scheme::schemes()
|
||||
.get(scheme_id).and_then(|s| s.as_user_inner().transpose().ok().flatten())
|
||||
.ok_or(PfError::Segv)?;
|
||||
|
||||
let offset = ctxt.file_ref.base_offset as u64 + (pages_from_grant_start * PAGE_SIZE) as u64;
|
||||
let offset = file_ref.base_offset as u64 + (pages_from_grant_start * PAGE_SIZE) as u64;
|
||||
user_inner.request_fmap(scheme_number, offset, 1, flags).unwrap();
|
||||
|
||||
let context_lock = super::current().map_err(|_| PfError::NonfatalInternalError)?;
|
||||
context_lock.write().hard_block(HardBlockedReason::AwaitingMmap { ctxt });
|
||||
context_lock.write().hard_block(HardBlockedReason::AwaitingMmap { file_ref });
|
||||
|
||||
unsafe { super::switch(); }
|
||||
|
||||
|
||||
+6
-9
@@ -1,7 +1,6 @@
|
||||
use alloc::sync::{Arc, Weak};
|
||||
use alloc::boxed::Box;
|
||||
use alloc::collections::BTreeMap;
|
||||
use rmm::PageFlushAll;
|
||||
use syscall::{SKMSG_FRETURNFD, CallerCtx, SKMSG_PROVIDE_MMAP};
|
||||
use core::num::NonZeroUsize;
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
@@ -12,7 +11,7 @@ use spin::{Mutex, RwLock};
|
||||
use crate::context::context::HardBlockedReason;
|
||||
use crate::context::{self, Context, BorrowedHtBuf, Status};
|
||||
use crate::context::file::FileDescription;
|
||||
use crate::context::memory::{AddrSpace, DANGLING, Grant, GrantFileRef, PageSpan, MmapMode, page_flags, FmapCtxt, BorrowedFmapSource};
|
||||
use crate::context::memory::{AddrSpace, DANGLING, Grant, GrantFileRef, PageSpan, MmapMode, page_flags, BorrowedFmapSource};
|
||||
use crate::event;
|
||||
use crate::memory::Frame;
|
||||
use crate::paging::{PAGE_SIZE, Page, VirtualAddress};
|
||||
@@ -503,12 +502,10 @@ impl UserInner {
|
||||
let dst_base = match mode {
|
||||
MmapMode::Cow => todo!("mmap CoW"),
|
||||
MmapMode::Shared => {
|
||||
let ctxt = Arc::new(FmapCtxt {
|
||||
file_ref: GrantFileRef {
|
||||
description: desc,
|
||||
base_offset: map.offset,
|
||||
},
|
||||
});
|
||||
let file_ref = GrantFileRef {
|
||||
description: desc,
|
||||
base_offset: map.offset,
|
||||
};
|
||||
let src_guard = src_address_space.read();
|
||||
let src = match base_page_opt {
|
||||
Some(base_addr) => Some(BorrowedFmapSource {
|
||||
@@ -519,7 +516,7 @@ impl UserInner {
|
||||
};
|
||||
let page_count_nz = NonZeroUsize::new(page_count).expect("already validated map.size != 0");
|
||||
dst_addr_space.write().mmap(dst_base, page_count_nz, map.flags, |dst_base, flags, mapper, flusher| {
|
||||
Ok(Grant::borrow_fmap(PageSpan::new(dst_base, page_count), page_flags(map.flags), ctxt, src, mapper, flusher))
|
||||
Ok(Grant::borrow_fmap(PageSpan::new(dst_base, page_count), page_flags(map.flags), file_ref, src, mapper, flusher))
|
||||
})?
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user