WIP: Support clone in userspace
Everything seems to work for the most part, but now there are tons of daemons which rely on syscall::clone, which is now implemented in relibc :(
This commit is contained in:
@@ -35,7 +35,7 @@ pub struct Context {
|
||||
/// Base pointer
|
||||
rbp: usize,
|
||||
/// Stack pointer
|
||||
rsp: usize,
|
||||
pub(crate) rsp: usize,
|
||||
/// FSBASE.
|
||||
///
|
||||
/// NOTE: Same fsgsbase behavior as with gsbase.
|
||||
|
||||
+15
-3
@@ -12,7 +12,7 @@ use core::{
|
||||
};
|
||||
use spin::RwLock;
|
||||
|
||||
use crate::arch::{interrupt::InterruptStack, paging::PAGE_SIZE};
|
||||
use crate::arch::{interrupt::InterruptStack, paging::{PAGE_SIZE, RmmA, RmmArch}};
|
||||
use crate::common::unique::Unique;
|
||||
use crate::context::arch;
|
||||
use crate::context::file::{FileDescriptor, FileDescription};
|
||||
@@ -250,6 +250,11 @@ pub struct Context {
|
||||
/// else than SIG_DFL, otherwise signals will not be delivered. Userspace is responsible for
|
||||
/// setting this.
|
||||
pub sigstack: Option<usize>,
|
||||
/// An even hackier way to pass the return entry point and stack pointer to new contexts while
|
||||
/// implementing clone. Before a context has returned to userspace, its IntRegisters cannot be
|
||||
/// set since there is no interrupt stack (unless the kernel stack is copied, but that is in my
|
||||
/// opinion hackier and less efficient than this (and UB to do in Rust)).
|
||||
pub clone_entry: Option<[usize; 2]>,
|
||||
}
|
||||
|
||||
// Necessary because GlobalAlloc::dealloc requires the layout to be the same, and therefore Box
|
||||
@@ -352,6 +357,7 @@ impl Context {
|
||||
regs: None,
|
||||
ptrace_stop: false,
|
||||
sigstack: None,
|
||||
clone_entry: None,
|
||||
};
|
||||
this.set_addr_space(new_addrspace()?.1);
|
||||
Ok(this)
|
||||
@@ -528,8 +534,14 @@ impl Context {
|
||||
self.addr_space.as_ref().ok_or(Error::new(ESRCH))
|
||||
}
|
||||
pub fn set_addr_space(&mut self, addr_space: Arc<RwLock<AddrSpace>>) {
|
||||
assert!(!self.running);
|
||||
self.arch.set_page_utable(addr_space.read().frame.utable.start_address().data());
|
||||
let physaddr = addr_space.read().frame.utable.start_address();
|
||||
if self.running {
|
||||
unsafe {
|
||||
RmmA::set_table(physaddr);
|
||||
}
|
||||
}
|
||||
|
||||
self.arch.set_page_utable(physaddr.data());
|
||||
self.addr_space = Some(addr_space);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,8 +77,7 @@ impl AddrSpace {
|
||||
// TODO: Abstract away this.
|
||||
let (mut inactive, mut active);
|
||||
|
||||
// TODO: aarch64
|
||||
let mut this_mapper = if self.frame.utable.start_address().data() == unsafe { x86::controlregs::cr3() } as usize {
|
||||
let mut this_mapper = if self.is_current() {
|
||||
active = unsafe { ActivePageTable::new(rmm::TableKind::User) };
|
||||
active.mapper()
|
||||
} else {
|
||||
@@ -95,8 +94,8 @@ impl AddrSpace {
|
||||
|
||||
for page in new_grant.pages() {
|
||||
// FIXME: ENOMEM is wrong here, it cannot fail.
|
||||
let current_frame = this_mapper.translate_page(page).ok_or(Error::new(ENOMEM))?.start_address().data() as *const u8;
|
||||
let new_frame = new_mapper.mapper().translate_page(page).ok_or(Error::new(ENOMEM))?.start_address().data() as *mut u8;
|
||||
let current_frame = unsafe { RmmA::phys_to_virt(this_mapper.translate_page(page).ok_or(Error::new(ENOMEM))?.start_address()) }.data() as *const u8;
|
||||
let new_frame = unsafe { RmmA::phys_to_virt(new_mapper.mapper().translate_page(page).ok_or(Error::new(ENOMEM))?.start_address()) }.data() as *mut u8;
|
||||
|
||||
// TODO: Replace this with CoW
|
||||
unsafe {
|
||||
@@ -115,6 +114,9 @@ impl AddrSpace {
|
||||
id,
|
||||
})
|
||||
}
|
||||
pub fn is_current(&self) -> bool {
|
||||
self.frame.utable.start_address() == unsafe { RmmA::table() }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
Reference in New Issue
Block a user