Add a memory: file for phys-contiguous mmaps.
This commit is contained in:
Generated
+10
-4
@@ -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",
|
||||
]
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user