Add a memory: file for phys-contiguous mmaps.

This commit is contained in:
4lDO2
2023-09-01 18:08:31 +02:00
parent ebf96fa843
commit 77400f63ee
4 changed files with 58 additions and 13 deletions
Generated
+10 -4
View File
@@ -38,6 +38,12 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
[[package]]
name = "byteorder"
version = "1.4.3"
@@ -104,7 +110,7 @@ name = "kernel"
version = "0.4.1"
dependencies = [
"bitfield",
"bitflags",
"bitflags 1.3.2",
"byteorder",
"cc",
"fdt",
@@ -209,14 +215,14 @@ version = "10.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6aa2540135b6a94f74c7bc90ad4b794f822026a894f3d7bcd185c100d13d4ad6"
dependencies = [
"bitflags",
"bitflags 1.3.2",
]
[[package]]
name = "redox_syscall"
version = "0.4.1"
dependencies = [
"bitflags",
"bitflags 2.4.1",
]
[[package]]
@@ -387,7 +393,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55b5be8cc34d017d8aabec95bc45a43d0f20e8b2a31a453cabc804fe996f8dca"
dependencies = [
"bit_field",
"bitflags",
"bitflags 1.3.2",
"raw-cpuid",
]
+24
View File
@@ -777,6 +777,30 @@ impl Grant {
},
})
}
pub fn zeroed_phys_contiguous(span: PageSpan, flags: PageFlags<RmmA>, mapper: &mut PageMapper, mut flusher: impl Flusher<RmmA>) -> Result<Grant, Enomem> {
let base = crate::memory::allocate_frames(span.count).ok_or(Enomem)?;
for (i, page) in span.pages().enumerate() {
let frame = base.next_by(i);
get_page_info(base).expect("PageInfo must exist for allocated frame").refcount.store(RefCount::One.to_raw(), Ordering::Relaxed);
unsafe {
let result = mapper.map_phys(page.start_address(), frame.start_address(), flags).expect("TODO: page table OOM");
flusher.consume(result);
}
}
Ok(Grant {
base: span.base,
info: GrantInfo {
page_count: span.count,
flags,
mapped: true,
provider: Provider::Allocated { cow_file_ref: None },
},
})
}
pub fn zeroed(span: PageSpan, flags: PageFlags<RmmA>, mapper: &mut PageMapper, mut flusher: impl Flusher<RmmA>, shared: bool) -> Result<Grant, Enomem> {
const MAX_EAGER_PAGES: usize = 16;
+23 -8
View File
@@ -23,7 +23,8 @@ pub struct MemoryScheme;
// TODO: Use crate that autogenerates conversion functions.
#[repr(u8)]
enum Handle {
Anonymous = 0,
Zeroed = 0,
ZeroedPhysContiguous = 4,
PhysicalWb = 1,
PhysicalUc = 2,
@@ -42,7 +43,8 @@ pub enum MemoryType {
impl Handle {
fn from_raw(raw: usize) -> Option<Self> {
Some(match raw {
0 => Self::Anonymous,
0 => Self::Zeroed,
4 => Self::ZeroedPhysContiguous,
1 => Self::PhysicalWb,
2 => Self::PhysicalUc,
@@ -55,16 +57,26 @@ impl Handle {
}
impl MemoryScheme {
pub fn fmap_anonymous(addr_space: &Arc<RwLock<AddrSpace>>, map: &Map) -> Result<usize> {
pub fn fmap_anonymous(addr_space: &Arc<RwLock<AddrSpace>>, map: &Map, is_phys_contiguous: bool) -> Result<usize> {
let span = PageSpan::validate_nonempty(VirtualAddress::new(map.address), map.size).ok_or(Error::new(EINVAL))?;
let page_count = NonZeroUsize::new(span.count).ok_or(Error::new(EINVAL))?;
let mut notify_files = Vec::new();
if is_phys_contiguous && map.flags.contains(MapFlags::MAP_SHARED) {
// TODO: Should this be supported?
return Err(Error::new(EOPNOTSUPP));
}
let page = addr_space
.write()
.mmap((map.address != 0).then_some(span.base), page_count, map.flags, &mut notify_files, |dst_page, flags, mapper, flusher| {
Ok(Grant::zeroed(PageSpan::new(dst_page, page_count.get()), flags, mapper, flusher, map.flags.contains(MapFlags::MAP_SHARED))?)
let span = PageSpan::new(dst_page, page_count.get());
if is_phys_contiguous {
Ok(Grant::zeroed_phys_contiguous(span, flags, mapper, flusher)?)
} else {
Ok(Grant::zeroed(span, flags, mapper, flusher, map.flags.contains(MapFlags::MAP_SHARED))?)
}
})?;
handle_notify_files(notify_files);
@@ -121,7 +133,8 @@ impl MemoryScheme {
impl KernelScheme for MemoryScheme {
fn kopen(&self, path: &str, _flags: usize, ctx: CallerCtx) -> Result<OpenResult> {
let intended_handle = match path.trim_start_matches('/') {
"" => Handle::Anonymous,
"" | "zeroed" => Handle::Zeroed,
"zeroed_phys_contiguous" => Handle::ZeroedPhysContiguous,
"physical" | "physical@wb" => Handle::PhysicalWb,
"physical@uc" => Handle::PhysicalUc,
"physical@wc" => Handle::PhysicalWc,
@@ -130,7 +143,7 @@ impl KernelScheme for MemoryScheme {
_ => return Err(Error::new(ENOENT)),
};
if ctx.uid != 0 && !matches!(intended_handle, Handle::Anonymous) {
if ctx.uid != 0 && !matches!(intended_handle, Handle::Zeroed) {
return Err(Error::new(EACCES));
}
@@ -146,7 +159,8 @@ impl KernelScheme for MemoryScheme {
}
fn kfmap(&self, id: usize, addr_space: &Arc<RwLock<AddrSpace>>, map: &Map, _consume: bool) -> Result<usize> {
match Handle::from_raw(id).ok_or(Error::new(EBADF))? {
Handle::Anonymous => Self::fmap_anonymous(addr_space, map),
Handle::Zeroed => Self::fmap_anonymous(addr_space, map, false),
Handle::ZeroedPhysContiguous => Self::fmap_anonymous(addr_space, map, true),
Handle::PhysicalWb => Self::physmap(map.offset, map.size, map.flags, MemoryType::Writeback),
Handle::PhysicalUc => Self::physmap(map.offset, map.size, map.flags, MemoryType::Uncacheable),
Handle::PhysicalWc => Self::physmap(map.offset, map.size, map.flags, MemoryType::WriteCombining),
@@ -156,7 +170,8 @@ impl KernelScheme for MemoryScheme {
fn kfpath(&self, id: usize, dst: UserSliceWo) -> Result<usize> {
// TODO: Copy scheme name elsewhere in the kernel?
let src = match Handle::from_raw(id).ok_or(Error::new(EBADF))? {
Handle::Anonymous => "memory:",
Handle::Zeroed => "memory:zeroed",
Handle::ZeroedPhysContiguous => "memory:zeroed_phys_contiguous",
Handle::PhysicalWb => "memory:physical@wb",
Handle::PhysicalUc => "memory:physical@uc",
Handle::PhysicalWc => "memory:physical@wc",
+1 -1
View File
@@ -77,7 +77,7 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack
let addrspace = AddrSpace::current()?;
let map = unsafe { UserSlice::ro(c, d)?.read_exact::<Map>()? };
if b == !0 {
MemoryScheme::fmap_anonymous(&addrspace, &map)
MemoryScheme::fmap_anonymous(&addrspace, &map, false)
} else {
file_op_generic(fd, |scheme, _, number| scheme.kfmap(number, &addrspace, &map, false))
}