Files
redox-kernel/src/scheme/memory.rs
2021-04-28 20:06:07 -06:00

100 lines
3.2 KiB
Rust

use crate::context;
use crate::context::memory::{entry_flags, Grant};
use crate::memory::{free_frames, used_frames, PAGE_SIZE};
use crate::paging::{ActivePageTable, PageTableType, VirtualAddress, VirtualAddressType};
use crate::syscall::data::{Map, OldMap, StatVfs};
use crate::syscall::error::*;
use crate::syscall::flag::MapFlags;
use crate::syscall::scheme::Scheme;
pub struct MemoryScheme;
impl MemoryScheme {
pub fn new() -> Self {
MemoryScheme
}
}
impl Scheme for MemoryScheme {
fn open(&self, _path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
Ok(0)
}
fn fstatvfs(&self, _file: usize, stat: &mut StatVfs) -> Result<usize> {
let used = used_frames() as u64;
let free = free_frames() as u64;
stat.f_bsize = PAGE_SIZE as u32;
stat.f_blocks = used + free;
stat.f_bfree = free;
stat.f_bavail = stat.f_bfree;
Ok(0)
}
fn fmap(&self, _id: usize, map: &Map) -> Result<usize> {
//TODO: Abstract with other grant creation
if map.size == 0 {
Ok(0)
} else {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
let mut grants = context.grants.write();
let region = grants.find_free_at(VirtualAddress::new(map.address), map.size, map.flags)?.round();
{
// Make sure it's *absolutely* not mapped already
// TODO: Keep track of all allocated memory so this isn't necessary
let active_table = match VirtualAddress::new(map.address).get_type() {
VirtualAddressType::User => unsafe { ActivePageTable::new(PageTableType::User) },
VirtualAddressType::Kernel => unsafe { ActivePageTable::new(PageTableType::Kernel) }
};
for page in region.pages() {
if active_table.translate_page(page).is_some() {
println!("page at {:#x} was already mapped", page.start_address().data());
return Err(Error::new(EEXIST))
}
}
}
grants.insert(Grant::map(region.start_address(), region.size(), entry_flags(map.flags)));
Ok(region.start_address().data())
}
}
fn fmap_old(&self, id: usize, map: &OldMap) -> Result<usize> {
if map.flags.contains(MapFlags::MAP_FIXED) {
// not supported for fmap, which lacks the address argument.
return Err(Error::new(EINVAL));
}
self.fmap(id, &Map {
offset: map.offset,
size: map.size,
flags: map.flags,
address: 0,
})
}
fn fcntl(&self, _id: usize, _cmd: usize, _arg: usize) -> Result<usize> {
Ok(0)
}
fn fpath(&self, _id: usize, buf: &mut [u8]) -> Result<usize> {
let mut i = 0;
let scheme_path = b"memory:";
while i < buf.len() && i < scheme_path.len() {
buf[i] = scheme_path[i];
i += 1;
}
Ok(i)
}
fn close(&self, _id: usize) -> Result<usize> {
Ok(0)
}
}