Implement (mostly) fmap2 for memory:
This commit is contained in:
@@ -196,10 +196,16 @@ impl Grant {
|
||||
pub fn start_address(&self) -> VirtualAddress {
|
||||
self.start
|
||||
}
|
||||
pub unsafe fn set_start_address(&mut self, start: VirtualAddress) {
|
||||
self.start = start;
|
||||
}
|
||||
|
||||
pub fn size(&self) -> usize {
|
||||
self.size
|
||||
}
|
||||
pub unsafe fn set_size(&mut self, size: usize) {
|
||||
self.size = size;
|
||||
}
|
||||
|
||||
pub fn flags(&self) -> EntryFlags {
|
||||
self.flags
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use crate::context;
|
||||
use crate::context::memory::Grant;
|
||||
use crate::memory::{free_frames, used_frames};
|
||||
use crate::memory::{free_frames, used_frames, PAGE_SIZE};
|
||||
use crate::paging::VirtualAddress;
|
||||
use crate::paging::entry::EntryFlags;
|
||||
use crate::syscall::data::{Map, StatVfs};
|
||||
use crate::syscall::data::{Map, Map2, StatVfs};
|
||||
use crate::syscall::error::*;
|
||||
use crate::syscall::flag::{PROT_EXEC, PROT_READ, PROT_WRITE};
|
||||
use crate::syscall::flag::{MapFlags, PROT_EXEC, PROT_READ, PROT_WRITE};
|
||||
use crate::syscall::scheme::Scheme;
|
||||
|
||||
pub struct MemoryScheme;
|
||||
@@ -24,7 +24,7 @@ impl Scheme for MemoryScheme {
|
||||
let used = used_frames() as u64;
|
||||
let free = free_frames() as u64;
|
||||
|
||||
stat.f_bsize = 4096;
|
||||
stat.f_bsize = PAGE_SIZE as u32;
|
||||
stat.f_blocks = used + free;
|
||||
stat.f_bfree = free;
|
||||
stat.f_bavail = stat.f_bfree;
|
||||
@@ -32,7 +32,7 @@ impl Scheme for MemoryScheme {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn fmap(&self, _id: usize, map: &Map) -> Result<usize> {
|
||||
fn fmap2(&self, _id: usize, map: &Map2) -> Result<usize> {
|
||||
//TODO: Abstract with other grant creation
|
||||
if map.size == 0 {
|
||||
Ok(0)
|
||||
@@ -41,10 +41,19 @@ impl Scheme for MemoryScheme {
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
|
||||
let fixed = map.flags.contains(MapFlags::MAP_FIXED);
|
||||
let fixed_noreplace = map.flags.contains(MapFlags::MAP_FIXED_NOREPLACE);
|
||||
|
||||
let mut grants = context.grants.lock();
|
||||
|
||||
let full_size = ((map.size + 4095)/4096) * 4096;
|
||||
let mut to_address = crate::USER_GRANT_OFFSET;
|
||||
let full_size = ((map.size + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
|
||||
|
||||
let mut to_address = if map.address == 0 { crate::USER_GRANT_OFFSET } else {
|
||||
if map.address < crate::USER_GRANT_OFFSET || map.address + map.size > crate::USER_GRANT_OFFSET + crate::PML4_SIZE || map.address % PAGE_SIZE != 0 {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
map.address
|
||||
};
|
||||
|
||||
let mut entry_flags = EntryFlags::PRESENT | EntryFlags::USER_ACCESSIBLE;
|
||||
if !map.flags.contains(PROT_EXEC) {
|
||||
@@ -58,27 +67,85 @@ impl Scheme for MemoryScheme {
|
||||
}
|
||||
|
||||
let mut i = 0;
|
||||
while i < grants.len() {
|
||||
let start = grants[i].start_address().get();
|
||||
if to_address + full_size < start {
|
||||
break;
|
||||
|
||||
while i < grants.len() {
|
||||
let grant = &mut grants[i];
|
||||
|
||||
let mut grant_start = grant.start_address().get();
|
||||
let mut grant_len = ((grant.size() + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
|
||||
let mut grant_end = grant_start + grant_len;
|
||||
|
||||
if grant_end <= to_address {
|
||||
// grant has nothing to do with the memory to map, and thus we can safely just
|
||||
// go on to the next one.
|
||||
|
||||
if !fixed {
|
||||
to_address = grant_end;
|
||||
}
|
||||
i += 1;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// check whether this grant overlaps with the memory range to use, by checking that
|
||||
// the start and end of the grant is not within the memory range to map
|
||||
if grant_start <= to_address && grant_end > to_address || grant_start <= to_address + full_size && grant_end > to_address + full_size {
|
||||
// the range overlaps, thus we'll have to continue to the next grant, or to
|
||||
// insert a new grant at the end (if not MapFlags::MAP_FIXED).
|
||||
|
||||
if fixed_noreplace {
|
||||
return Err(Error::new(EEXIST));
|
||||
} else if fixed {
|
||||
/*
|
||||
// shrink the grant, removing it if necessary. since the to_address isn't
|
||||
// changed at all when mapping to a fixed address, we can just continue to
|
||||
// the next grant and shrink or remove that one if it was also overlapping.
|
||||
if to_address + full_size > grant_start {
|
||||
let new_start = core::cmp::min(grant_end, to_address + full_size);
|
||||
|
||||
let new_size = grant.size() - (new_start - grant_start);
|
||||
unsafe { grant.set_size(new_size) };
|
||||
grant_len = ((new_size + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
|
||||
|
||||
let new_start = VirtualAddress::new(new_start);
|
||||
unsafe { grant.set_start_address(new_start) };
|
||||
grant_start = new_start;
|
||||
|
||||
grant_end = grant_start + grant_len;
|
||||
}
|
||||
*/
|
||||
// TODO
|
||||
return Err(Error::new(EOPNOTSUPP));
|
||||
} else {
|
||||
to_address = grant_end;
|
||||
i += 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
let pages = (grants[i].size() + 4095) / 4096;
|
||||
let end = start + pages * 4096;
|
||||
to_address = end;
|
||||
i += 1;
|
||||
}
|
||||
|
||||
grants.insert(i, Grant::map(
|
||||
VirtualAddress::new(to_address),
|
||||
full_size,
|
||||
entry_flags
|
||||
entry_flags,
|
||||
));
|
||||
|
||||
Ok(to_address)
|
||||
}
|
||||
}
|
||||
fn fmap(&self, id: usize, map: &Map) -> Result<usize> {
|
||||
if map.flags.contains(MapFlags::MAP_FIXED) {
|
||||
// not supported for fmap, which lacks the address argument.
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
self.fmap2(id, &Map2 {
|
||||
offset: map.offset,
|
||||
size: map.size,
|
||||
flags: map.flags,
|
||||
address: 0,
|
||||
})
|
||||
}
|
||||
|
||||
fn fcntl(&self, _id: usize, _cmd: usize, _arg: usize) -> Result<usize> {
|
||||
Ok(0)
|
||||
|
||||
2
syscall
2
syscall
Submodule syscall updated: 122878874d...27fcecb30f
Reference in New Issue
Block a user