Commit 608aa158 authored by Nifou's avatar Nifou

Divide the process' memory into several areas which can be mapped

parent fdca902a
......@@ -36,6 +36,7 @@ use crate::tasking::{
AuxVecItem,
},
scheduler::PROCESSES,
memory::MemoryArea,
};
#[derive(PartialEq, Debug, Clone, Copy)]
......@@ -165,8 +166,15 @@ impl<'a> ElfLoader<'a> {
flags.remove(Flags::NO_EXECUTE);
}
let mut area = MemoryArea::new(
mappings.first().unwrap().1.start_address().as_u64(),
mappings.last().unwrap().1.start_address().as_u64() + 4096, // TODO: Constant?
flags
);
area.mappings(mappings.clone());
// Add the mappings in the process' page table
process.memory.mappings(mappings.clone(), flags, Flags::PRESENT | Flags::USER_ACCESSIBLE);
process.memory.map(area);
// Unmap the binary in the kernel's address space
memory::unmap(mappings);
......
......@@ -18,7 +18,10 @@
use bitflags::bitflags;
use x86_64::structures::paging::page_table::PageTableFlags as Flags;
use crate::tasking::scheduler::{PROCESSES, SCHEDULER};
use crate::tasking::{
scheduler::{PROCESSES, SCHEDULER},
memory::MemoryArea,
};
use super::{Syscall, error::{Result, Error}};
bitflags! {
......@@ -80,10 +83,13 @@ impl Syscall {
// Get the current thread's process
let current_process = SCHEDULER.get().current().unwrap().process;
processes.get_mut(&current_process).unwrap().memory.map(0x300000, 0x300000 + len as u64, Flags::from(prot), Flags::PRESENT);
let free_area_start = processes.get_mut(&current_process).unwrap().memory.find_free_area(len);
let free_area = MemoryArea::new(free_area_start, free_area_start + len as u64, Flags::from(prot));
processes.get_mut(&current_process).unwrap().memory.map(free_area);
processes.get_mut(&current_process).unwrap().memory.switch_page_table();
Ok(0x300000)
Ok(free_area_start as usize)
}
else {
Ok(addr)
......@@ -108,7 +114,8 @@ impl Syscall {
// Get the current thread's process
let current_process = SCHEDULER.get().current().unwrap().process;
processes.get_mut(&current_process).unwrap().memory.map(0x10000000, 0x10004000, Flags::PRESENT | Flags::WRITABLE, Flags::PRESENT);
let area = MemoryArea::new(0x10000000, 0x10004000, Flags::PRESENT | Flags::WRITABLE);
processes.get_mut(&current_process).unwrap().memory.map(area);
processes.get_mut(&current_process).unwrap().memory.switch_page_table();
Ok(0x10000000)
......
......@@ -15,6 +15,11 @@
* along with this program. If not, see https://www.gnu.org/licenses.
*/
//! Memory used by a process management
use alloc::prelude::v1::Vec;
use core::{
fmt,
cmp::Ordering,
};
use x86_64::{
VirtAddr, PhysAddr,
structures::paging::{
......@@ -32,6 +37,9 @@ use crate::memory::table::ProcessPageTable;
pub struct ProcessMemory {
/// The frame which contains the PageTable
pub table: ProcessPageTable,
/// The areas used by this process
pub areas: Vec<MemoryArea>,
}
impl ProcessMemory {
......@@ -59,17 +67,51 @@ impl ProcessMemory {
Self {
table,
areas: vec![],
}
}
/// Map a range of pages to a range of frames in the process' page table
pub fn mappings(&mut self, mappings: memory::Mappings, flags: Flags, table_flags: Flags) {
unsafe { self.table.mappings(mappings, flags, table_flags); }
/// Map all pages between two addresses in the process' page table
pub fn map(&mut self, mut area: MemoryArea) {
// Use existing mappings if provided
if !area.mappings.is_empty() {
unsafe { self.table.mappings(area.clone().mappings, area.flags, Flags::PRESENT); }
}
else {
unsafe { self.table.map(area.start, area.end, area.flags, Flags::PRESENT); }
}
// Round the start and end addresses of the area by 4096 (the size of a page)
area.start = area.start - (area.start % 4096);
area.end = area.end + (area.end % 4096);
// Add the area in the list of existing areas
self.areas.push(area);
}
/// Map all pages between two addresses in the process' page table
pub fn map(&mut self, start: u64, end: u64, flags: Flags, table_flags: Flags) {
unsafe { self.table.map(start, end, flags, table_flags); }
/// Find a free memory area
pub fn find_free_area(&mut self, len: usize) -> u64 {
// Sort the areas
self.areas.sort();
// Test for space between existing areas
if let Some(area) = self.areas.iter().enumerate().find(|(i, area)| {
if self.areas[i + 1].start - area.end >= len as u64 {
true
} else {
false
}
}) {
area.1.end
} else {
if let Some(area) = self.areas.last() {
// Return the area after the others
area.end
} else {
// Return the first area
0
}
}
}
/// Switch to the process' page table
......@@ -77,3 +119,44 @@ impl ProcessMemory {
unsafe { self.table.switch(); }
}
}
#[derive(PartialEq, Eq, Clone)]
pub struct MemoryArea {
start: u64,
end: u64,
mappings: memory::Mappings,
flags: Flags,
}
impl fmt::Debug for MemoryArea {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Area\n - Start: {:#x}\n - End: {:#x}\n", self.start, self.end)
}
}
impl PartialOrd for MemoryArea {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.start.partial_cmp(&other.start)
}
}
impl Ord for MemoryArea {
fn cmp(&self, other: &Self) -> Ordering {
self.start.cmp(&other.start)
}
}
impl MemoryArea {
pub fn new(start: u64, end: u64, flags: Flags) -> Self {
Self {
start,
end,
mappings: vec![],
flags,
}
}
pub fn mappings(&mut self, mappings: memory::Mappings) {
self.mappings = mappings;
}
}
......@@ -21,7 +21,7 @@ use x86_64::structures::paging::page_table::PageTableFlags as Flags;
use crate::memory;
use super::{
memory::ProcessMemory,
memory::{ProcessMemory, MemoryArea},
info::ProcessInfo,
scheduler::{PROCESSES, SCHEDULER},
thread::{Thread, Tid},
......@@ -87,7 +87,13 @@ impl Process {
let cr3 = process.memory.table.frame().start_address().as_u64() as usize;
// Add the mappings in the process' page table
process.memory.mappings(mappings.clone(), Flags::PRESENT | Flags::WRITABLE, Flags::PRESENT | Flags::USER_ACCESSIBLE);
let mut area = MemoryArea::new(
mappings.first().unwrap().1.start_address().as_u64(),
mappings.last().unwrap().1.start_address().as_u64() + 4096, // TODO: Constant?
Flags::PRESENT | Flags::WRITABLE
);
area.mappings(mappings.clone());
process.memory.map(area);
// Unmap the stack in the kernel's address space
memory::unmap(mappings);
......@@ -103,7 +109,15 @@ impl Process {
// Add the new thread in the process' threads list
processes.get_mut(&process.pid).unwrap().threads.push(thread.tid);
processes.get_mut(&process.pid).unwrap().memory.mappings(mappings, Flags::PRESENT | Flags::WRITABLE | Flags::NO_EXECUTE, Flags::PRESENT | Flags::USER_ACCESSIBLE);
// Map the kernel stack
let mut area = MemoryArea::new(
mappings.first().unwrap().1.start_address().as_u64(),
mappings.last().unwrap().1.start_address().as_u64() + 4096, // TODO: Constant?
Flags::PRESENT | Flags::WRITABLE
);
area.mappings(mappings.clone());
processes.get_mut(&process.pid).unwrap().memory.map(area);
process.pid
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment