Skip to content

Commit

Permalink
Kernel: Processes can now request memory from the kernel
Browse files Browse the repository at this point in the history
  • Loading branch information
corigan01 committed Jan 28, 2025
1 parent cf17db6 commit 94944aa
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 8 deletions.
33 changes: 31 additions & 2 deletions crates/mem/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ use core::{error::Error, fmt::Display};

use crate::{
MemoryError,
addr::{AlignedTo, VirtAddr},
addr::{AlignedTo, KERNEL_ADDR_START, VirtAddr},
page::{PhysPage, VirtPage},
paging::{PageCorrelationError, Virt2PhysMapping, VmOptions, VmPermissions},
pmm::SharedPhysPage,
};
use alloc::{boxed::Box, collections::BTreeMap, sync::Arc, vec::Vec};
use boolvec::BoolVec;

Check warning on line 37 in crates/mem/src/vm.rs

View workflow job for this annotation

GitHub Actions / Build OS

unused import: `boolvec::BoolVec`
use spin::RwLock;
use util::consts::PAGE_4K;

Expand Down Expand Up @@ -557,15 +558,43 @@ impl VmProcess {
})
}

/// Find a region of virtual memory that is not being used
pub fn find_vm_free(&self, min_page: VirtPage, n_pages: usize) -> Option<VmRegion> {
let mut previous_index = VmRegion::from_containing(VirtAddr::new(0), VirtAddr::new(0));
let mut ideal_page = None;

for region in self
.objects
.read()
.iter()
.map(|obj| obj.read().region)
.skip_while(|region| region.end < min_page)
.take_while(|region| region.end < VirtPage::containing_addr(KERNEL_ADDR_START))
{
if region.start.page() - previous_index.end.page() >= n_pages {
ideal_page = Some(previous_index.end.offset_by(1));
break;
}
previous_index = region;
}

let start = ideal_page?;
Some(VmRegion {
start,
end: start.offset_by(n_pages - 1),
})
}

/// Add a mapping to this process
pub fn insert_vm_object(
&self,
object: Arc<RwLock<VmObject>>,
) -> Result<(), InsertVmObjectError> {
let locked = object.read();
let region = locked.region;

// If there is already a region that exists on that virtual address
if let Some(existing) = self.check_overlapping(&locked.region) {
if let Some(existing) = self.check_overlapping(&region) {
return Err(InsertVmObjectError::Overlapping {
existing,
attempted: locked.region,
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ pub unsafe extern "C" fn kernel_entry() {
pop rdx
pop rcx
pop rbx
pop rax
add rsp, 8 # pop rax
add rsp, 8 # pop 0
add rsp, 8 # pop rip
Expand Down
67 changes: 65 additions & 2 deletions kernel/src/int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,18 @@ use arch::{
use lldebug::{log, logln, sync::Mutex, warnln};
use mem::{
addr::VirtAddr,
page::VirtPage,

Check warning on line 40 in kernel/src/int.rs

View workflow job for this annotation

GitHub Actions / Build OS

unused import: `page::VirtPage`
paging::VmPermissions,
vm::{PageFaultInfo, call_page_fault_handler},
};
use util::consts::PAGE_4K;

use crate::{
context::IN_USERSPACE,
process::{AccessViolationReason, ProcessError, SchedulerEvent, send_scheduler_event},
process::{
AccessViolationReason, ProcessError, SchedulerEvent, lock_ref_scheduler,
send_scheduler_event,
},
};

static INTERRUPT_TABLE: Mutex<InterruptDescTable> = Mutex::new(InterruptDescTable::new());
Expand Down Expand Up @@ -216,7 +222,7 @@ pub fn enable_pic() {
extern "C" fn syscall_handler(
rdi: u64,
rsi: u64,
_rdx: u64,
rdx: u64,
_rcx: u64,
_r8: u64,
syscall_number: u64,
Expand All @@ -226,6 +232,63 @@ extern "C" fn syscall_handler(
send_scheduler_event(SchedulerEvent::Exit);
unreachable!("Should not return from exit")
}
1 => {
let process = lock_ref_scheduler(|sc| sc.acquire_running_process())
.expect("Only a running process should be able to call syscalls!");

pub enum MemoryLocation {
Anywhere = 0,
}
pub enum MemoryProtections {

Check warning on line 242 in kernel/src/int.rs

View workflow job for this annotation

GitHub Actions / Build OS

enum `MemoryProtections` is never used
None = 0,
ReadExecute = 1,
ReadOnly = 2,
ReadWrite = 3,
}
pub enum SysMemoryError {
InvalidLength = 0,

Check warning on line 249 in kernel/src/int.rs

View workflow job for this annotation

GitHub Actions / Build OS

variants `InvalidLength` and `OutOfMemory` are never constructed
InvalidRequest = 1,
OutOfMemory = 2,
}

let _location = match rdi {
0 => MemoryLocation::Anywhere,
_ => return SysMemoryError::InvalidRequest as u64,
};
let protection = match rsi {
0 => VmPermissions::none()
.set_user_flag(true)
.set_read_flag(false)
.set_exec_flag(true /*FIXME: Exec flag always set*/),
1 => VmPermissions::none()
.set_user_flag(true)
.set_read_flag(true)
.set_exec_flag(true),
2 => VmPermissions::none()
.set_user_flag(true)
.set_read_flag(true)
.set_exec_flag(true),
3 => VmPermissions::none()
.set_user_flag(true)
.set_read_flag(true)
.set_exec_flag(true)
.set_write_flag(true),
_ => return SysMemoryError::InvalidRequest as u64,
};
let len = match rdx {
// TODO: This is just a random constraint, we should figure out
// how much memory the system has.
..16777216 => ((rdx as usize - 1) / PAGE_4K) + 1,
_ => return SysMemoryError::InvalidRequest as u64,
};

let region = process.read().add_anywhere(len, protection, false);
logln!("{:#?}", region);
return match region {
Ok(region) => region.start.addr().addr() as u64,
Err(_) => SysMemoryError::InvalidRequest as u64,
};
}
69 => ::lldebug::priv_print(
lldebug::LogKind::Log,
"userspace",
Expand Down
32 changes: 31 additions & 1 deletion kernel/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ use mem::{
};
use spin::RwLock;
use tar::{Tar, TarError};
use util::consts::PAGE_4K;
use util::consts::{PAGE_2M, PAGE_4K};
use vm_elf::VmElfInject;

pub mod vm_elf;
Expand Down Expand Up @@ -104,6 +104,8 @@ pub enum ProcessError {
NoSuchProcess(usize),
/// This process tried to access resources it does not have access to
AccessViolation(AccessViolationReason),
/// There was no remaining Virtual Memory to allocate to this process
OutOfVirtualMemory,
}

impl core::fmt::Display for ProcessError {
Expand Down Expand Up @@ -184,6 +186,29 @@ impl Process {
self.context.rflag = 0x200;
}

/// Map memory anywhere
pub fn add_anywhere(
&self,
n_pages: usize,
permissions: VmPermissions,
populate_now: bool,
) -> Result<VmRegion, ProcessError> {
logln!(
"'{}' is requesting memory! n_pages={}, perm={}",
self.name,
n_pages,
permissions
);

let region_free = self
.vm
.find_vm_free(VirtPage::containing_addr(VirtAddr::new(PAGE_2M)), n_pages)
.ok_or(ProcessError::OutOfVirtualMemory)?;

self.add_anon(region_free, permissions, populate_now)
.map(|_| region_free)
}

/// Map an anon zeroed scrubbed region to this local process
pub fn add_anon(
&self,
Expand Down Expand Up @@ -389,6 +414,11 @@ impl Scheduler {
}
}

/// Get a ref to the currently running process.
pub fn acquire_running_process(&self) -> Result<RefProcess, ProcessError> {
self.running.clone().ok_or(ProcessError::NotAnyProcess)
}

/// Insert a new process into the schedulers mapping, and get it ready to be scheduled
pub fn add_process<F>(&mut self, f: F) -> Result<(), ProcessError>
where
Expand Down
16 changes: 15 additions & 1 deletion user/hello-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
#![no_main]

use core::panic::PanicInfo;
use libq::{ExitCode, dbugln, exit};
use libq::{
ExitCode, dbugln, exit,
syscall::{MemoryLocation, MemoryProtections, map_memory},
};

#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
Expand All @@ -40,5 +43,16 @@ fn panic(info: &PanicInfo) -> ! {
extern "C" fn _start() {
dbugln!("Hello Server!");

let example_memory =
unsafe { map_memory(MemoryLocation::Anywhere, MemoryProtections::ReadWrite, 10) }.unwrap();

let slice = unsafe { core::slice::from_raw_parts_mut(example_memory, 10) };
slice
.iter_mut()
.enumerate()
.for_each(|(i, el)| *el = i as u8);

dbugln!("{:?}", slice);

exit(ExitCode::Success);
}
51 changes: 50 additions & 1 deletion user/libq/src/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ macro_rules! raw_syscall {

/// QuantumOS Exit SyscallID
pub const QOS_SYSCALL_NUMBER_EXIT: usize = 0;
/// QuantumOS Memory SyscallID
pub const QOS_SYSCALL_NUMBER_MEMORY: usize = 1;
/// QuantumOS Debug Output SyscallID
pub const QOS_SYSCALL_NUMBER_DEBUG: usize = 69;

Expand Down Expand Up @@ -152,7 +154,8 @@ pub unsafe fn debug_syscall(msg: &str) -> SysDebugResp {
0 => SysDebugResp::Okay,
1 => SysDebugResp::PtrInvalid,
2 => SysDebugResp::LenInvalid,
_ => SysDebugResp::Okay, // unreachable!("Kernel should only repond with SysDebugResp, kernel error?"),
// _ => unreachable!("Kernel should only repond with SysDebugResp, kernel error?"),
_ => SysDebugResp::Okay,
}
}

Expand All @@ -178,3 +181,49 @@ pub unsafe fn exit_syscall(exit_reason: SysExitCode) -> ! {
unsafe { raw_syscall!(QOS_SYSCALL_NUMBER_EXIT, sys_exit_code) };
unreachable!("Exit syscall should never return!")
}

#[repr(u64)]
#[derive(Debug, Clone, Copy)]
pub enum MemoryLocation {
Anywhere = 0,
}

#[repr(u64)]
#[derive(Debug, Clone, Copy)]
pub enum MemoryProtections {
None = 0,
ReadExecute = 1,
ReadOnly = 2,
ReadWrite = 3,
}

/// Possiable errors for `memory` system call.
#[repr(u64)]
#[derive(Debug, Clone, Copy)]
pub enum SysMemoryError {
InvalidLength = 0,
InvalidRequest = 1,
OutOfMemory = 2,
}

pub unsafe fn map_memory(
loc: MemoryLocation,
prot: MemoryProtections,
length: usize,
) -> Result<*mut u8, SysMemoryError> {
let arg0 = loc as u64;
let arg1 = prot as u64;
let arg2 = length as u64;

let resp = unsafe { raw_syscall!(QOS_SYSCALL_NUMBER_MEMORY, arg0, arg1, arg2) };

match resp {
// Since these are kernel PTRs, they should never be valid in userspace!
0 => Err(SysMemoryError::InvalidLength),
1 => Err(SysMemoryError::InvalidRequest),
2 => Err(SysMemoryError::OutOfMemory),
// Our stack ptr is the highest possible ptr in userspace
e if e < 0x7fffffffffff => Ok(e as *mut u8),
_ => unreachable!("Kernel should only repond with SysMemoryError, kernel error?"),
}
}

0 comments on commit 94944aa

Please sign in to comment.