Fix everything all the way to booting to desktop.
This commit is contained in:
+3
-1
@@ -44,7 +44,9 @@ raw-cpuid = "10.2.0"
|
||||
x86 = { version = "0.47.0", default-features = false }
|
||||
|
||||
[features]
|
||||
default = ["acpi", "multi_core", "graphical_debug", "serial_debug"]
|
||||
# TODO: Fix multicore
|
||||
#default = ["acpi", "multi_core", "graphical_debug", "serial_debug"]
|
||||
default = ["acpi", "graphical_debug", "serial_debug"]
|
||||
acpi = []
|
||||
doc = []
|
||||
graphical_debug = []
|
||||
|
||||
@@ -37,47 +37,8 @@
|
||||
|
||||
/// Offset to user image
|
||||
pub const USER_OFFSET: usize = 0;
|
||||
pub const USER_PML4: usize = (USER_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
|
||||
/// Offset to user arguments
|
||||
pub const USER_ARG_OFFSET: usize = USER_OFFSET + PML4_SIZE/2;
|
||||
|
||||
/// Offset to user grants
|
||||
pub const USER_GRANT_OFFSET: usize = USER_OFFSET + PML4_SIZE;
|
||||
pub const USER_GRANT_PML4: usize = (USER_GRANT_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
|
||||
/// Offset to user stack
|
||||
pub const USER_STACK_OFFSET: usize = USER_GRANT_OFFSET + PML4_SIZE;
|
||||
pub const USER_STACK_PML4: usize = (USER_STACK_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
/// Size of user stack
|
||||
pub const USER_STACK_SIZE: usize = 1024 * 1024; // 1 MB
|
||||
|
||||
/// Offset to user sigstack
|
||||
pub const USER_SIGSTACK_OFFSET: usize = USER_STACK_OFFSET + PML4_SIZE;
|
||||
pub const USER_SIGSTACK_PML4: usize = (USER_SIGSTACK_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
/// Size of user sigstack
|
||||
pub const USER_SIGSTACK_SIZE: usize = 256 * 1024; // 256 KB
|
||||
|
||||
/// Offset to user temporary image (used when cloning)
|
||||
pub const USER_TMP_OFFSET: usize = USER_SIGSTACK_OFFSET + PML4_SIZE;
|
||||
pub const USER_TMP_PML4: usize = (USER_TMP_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
|
||||
/// Offset to user temporary heap (used when cloning)
|
||||
pub const USER_TMP_HEAP_OFFSET: usize = USER_TMP_OFFSET + PML4_SIZE;
|
||||
pub const USER_TMP_HEAP_PML4: usize = (USER_TMP_HEAP_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
|
||||
/// Offset to user temporary page for grants
|
||||
pub const USER_TMP_GRANT_OFFSET: usize = USER_TMP_HEAP_OFFSET + PML4_SIZE;
|
||||
pub const USER_TMP_GRANT_PML4: usize = (USER_TMP_GRANT_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
|
||||
/// Offset to user temporary stack (used when cloning)
|
||||
pub const USER_TMP_STACK_OFFSET: usize = USER_TMP_GRANT_OFFSET + PML4_SIZE;
|
||||
pub const USER_TMP_STACK_PML4: usize = (USER_TMP_STACK_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
|
||||
/// Offset to user temporary sigstack (used when cloning)
|
||||
pub const USER_TMP_SIGSTACK_OFFSET: usize = USER_TMP_STACK_OFFSET + PML4_SIZE;
|
||||
pub const USER_TMP_SIGSTACK_PML4: usize = (USER_TMP_SIGSTACK_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
|
||||
/// Offset for usage in other temporary pages
|
||||
pub const USER_TMP_MISC_OFFSET: usize = USER_TMP_SIGSTACK_OFFSET + PML4_SIZE;
|
||||
// TODO: Currently used for ptrace but should be removed or replaced with a kernel address.
|
||||
pub const USER_TMP_MISC_OFFSET: usize = USER_OFFSET + PML4_SIZE;
|
||||
pub const USER_TMP_MISC_PML4: usize = (USER_TMP_MISC_OFFSET & PML4_MASK)/PML4_SIZE;
|
||||
|
||||
@@ -244,7 +244,11 @@ pub struct Context {
|
||||
/// A somewhat hacky way to initially stop a context when creating
|
||||
/// a new instance of the proc: scheme, entirely separate from
|
||||
/// signals or any other way to restart a process.
|
||||
pub ptrace_stop: bool
|
||||
pub ptrace_stop: bool,
|
||||
/// A pointer to the signal stack. If this is unset, none of the sigactions can be anything
|
||||
/// else than SIG_DFL, otherwise signals will not be delivered. Userspace is responsible for
|
||||
/// setting this.
|
||||
pub sigstack: Option<usize>,
|
||||
}
|
||||
|
||||
// Necessary because GlobalAlloc::dealloc requires the layout to be the same, and therefore Box
|
||||
@@ -345,7 +349,8 @@ impl Context {
|
||||
0
|
||||
); 128])),
|
||||
regs: None,
|
||||
ptrace_stop: false
|
||||
ptrace_stop: false,
|
||||
sigstack: None,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -13,12 +13,12 @@ pub fn is_user_handled(handler: Option<extern "C" fn(usize)>) -> bool {
|
||||
}
|
||||
|
||||
pub extern "C" fn signal_handler(sig: usize) {
|
||||
let (action, restorer) = {
|
||||
let ((action, restorer), sigstack) = {
|
||||
let contexts = contexts();
|
||||
let context_lock = contexts.current().expect("context::signal_handler not inside of context");
|
||||
let context = context_lock.read();
|
||||
let actions = context.actions.read();
|
||||
actions[sig]
|
||||
(actions[sig], context.sigstack)
|
||||
};
|
||||
|
||||
let handler = action.sa_handler.map(|ptr| ptr as usize).unwrap_or(0);
|
||||
@@ -115,7 +115,7 @@ pub extern "C" fn signal_handler(sig: usize) {
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let mut sp = crate::USER_SIGSTACK_OFFSET + crate::USER_SIGSTACK_SIZE - 256;
|
||||
let mut sp = sigstack.expect("sigaction was set while sigstack was not") - 256;
|
||||
|
||||
sp = (sp / 16) * 16;
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ use alloc::{
|
||||
};
|
||||
use core::{
|
||||
cmp,
|
||||
convert::TryFrom,
|
||||
mem,
|
||||
slice,
|
||||
str,
|
||||
@@ -102,6 +103,7 @@ enum Operation {
|
||||
Trace,
|
||||
Static(&'static str),
|
||||
Name,
|
||||
Sigstack,
|
||||
}
|
||||
impl Operation {
|
||||
fn needs_child_process(self) -> bool {
|
||||
@@ -111,6 +113,7 @@ impl Operation {
|
||||
Self::Trace => true,
|
||||
Self::Static(_) => false,
|
||||
Self::Name => false,
|
||||
Self::Sigstack => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -251,6 +254,7 @@ impl Scheme for ProcScheme {
|
||||
Some("trace") => Operation::Trace,
|
||||
Some("exe") => Operation::Static("exe"),
|
||||
Some("name") => Operation::Name,
|
||||
Some("sigstack") => Operation::Sigstack,
|
||||
_ => return Err(Error::new(EINVAL))
|
||||
};
|
||||
|
||||
@@ -529,6 +533,13 @@ impl Scheme for ProcScheme {
|
||||
Ok(to_copy)
|
||||
}
|
||||
}
|
||||
Operation::Sigstack => match context::contexts().current().ok_or(Error::new(ESRCH))?.read().sigstack.unwrap_or(!0).to_ne_bytes() {
|
||||
sigstack => {
|
||||
let to_copy = cmp::min(buf.len(), sigstack.len());
|
||||
buf[..to_copy].copy_from_slice(&sigstack[..to_copy]);
|
||||
Ok(to_copy)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -719,6 +730,12 @@ impl Scheme for ProcScheme {
|
||||
*context::contexts().current().ok_or(Error::new(ESRCH))?.read().name.write() = utf8;
|
||||
Ok(buf.len())
|
||||
}
|
||||
Operation::Sigstack => {
|
||||
let bytes = <[u8; mem::size_of::<usize>()]>::try_from(buf).map_err(|_| Error::new(EINVAL))?;
|
||||
let sigstack = usize::from_ne_bytes(bytes);
|
||||
context::contexts().current().ok_or(Error::new(ESRCH))?.write().sigstack = (sigstack != !0).then(|| sigstack);
|
||||
Ok(buf.len())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -757,6 +774,7 @@ impl Scheme for ProcScheme {
|
||||
Operation::Trace => "trace",
|
||||
Operation::Static(path) => path,
|
||||
Operation::Name => "name",
|
||||
Operation::Sigstack => "sigstack",
|
||||
});
|
||||
|
||||
let len = cmp::min(path.len(), buf.len());
|
||||
|
||||
+39
-48
@@ -1,9 +1,9 @@
|
||||
use crate::interrupt::InterruptStack;
|
||||
use crate::memory::{allocate_frames_complex, deallocate_frames, Frame};
|
||||
use crate::memory::{allocate_frames_complex, deallocate_frames, Frame, PAGE_SIZE};
|
||||
use crate::paging::{ActivePageTable, PageFlags, PhysicalAddress, VirtualAddress};
|
||||
use crate::paging::entry::EntryFlags;
|
||||
use crate::context;
|
||||
use crate::context::memory::{Grant, Region};
|
||||
use crate::context::memory::{DANGLING, Grant, Region};
|
||||
use crate::syscall::error::{Error, EFAULT, EINVAL, ENOMEM, EPERM, ESRCH, Result};
|
||||
use crate::syscall::flag::{PhysallocFlags, PartialAllocStrategy, PhysmapFlags, PHYSMAP_WRITE, PHYSMAP_WRITE_COMBINE, PHYSMAP_NO_CACHE};
|
||||
|
||||
@@ -71,56 +71,47 @@ pub fn physfree(physical_address: usize, size: usize) -> Result<usize> {
|
||||
}
|
||||
|
||||
//TODO: verify exlusive access to physical memory
|
||||
// TODO: Replace this completely with something such as `memory:physical`. Mmapping at offset
|
||||
// `physaddr` to `address` (optional) will map that physical address. We would have to find out
|
||||
// some way to pass flags such as WRITE_COMBINE/NO_CACHE however.
|
||||
pub fn inner_physmap(physical_address: usize, size: usize, flags: PhysmapFlags) -> Result<usize> {
|
||||
//TODO: Abstract with other grant creation
|
||||
if 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 from_address = (physical_address/4096) * 4096;
|
||||
let offset = physical_address - from_address;
|
||||
let full_size = ((offset + size + 4095)/4096) * 4096;
|
||||
let mut to_address = crate::USER_GRANT_OFFSET;
|
||||
|
||||
let mut page_flags = PageFlags::new().user(true);
|
||||
if flags.contains(PHYSMAP_WRITE) {
|
||||
page_flags = page_flags.write(true);
|
||||
}
|
||||
if flags.contains(PHYSMAP_WRITE_COMBINE) {
|
||||
page_flags = page_flags.custom_flag(EntryFlags::HUGE_PAGE.bits(), true);
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")] // TODO: AARCH64
|
||||
if flags.contains(PHYSMAP_NO_CACHE) {
|
||||
page_flags = page_flags.custom_flag(EntryFlags::NO_CACHE.bits(), true);
|
||||
}
|
||||
|
||||
// TODO: Make this faster than Sonic himself by using le superpowers of BTreeSet
|
||||
|
||||
for grant in grants.iter() {
|
||||
let start = grant.start_address().data();
|
||||
if to_address + full_size < start {
|
||||
break;
|
||||
}
|
||||
|
||||
let pages = (grant.size() + 4095) / 4096;
|
||||
let end = start + pages * 4096;
|
||||
to_address = end;
|
||||
}
|
||||
|
||||
grants.insert(Grant::physmap(
|
||||
PhysicalAddress::new(from_address),
|
||||
VirtualAddress::new(to_address),
|
||||
full_size,
|
||||
page_flags
|
||||
));
|
||||
|
||||
Ok(to_address + offset)
|
||||
return Ok(DANGLING);
|
||||
}
|
||||
if size % PAGE_SIZE != 0 || physical_address % PAGE_SIZE != 0 {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
// TODO: Enforce size being a multiple of the page size, fail otherwise.
|
||||
|
||||
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 dst_address = grants.find_free(size).ok_or(Error::new(ENOMEM))?;
|
||||
|
||||
let mut page_flags = PageFlags::new().user(true);
|
||||
if flags.contains(PHYSMAP_WRITE) {
|
||||
page_flags = page_flags.write(true);
|
||||
}
|
||||
if flags.contains(PHYSMAP_WRITE_COMBINE) {
|
||||
page_flags = page_flags.custom_flag(EntryFlags::HUGE_PAGE.bits(), true);
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")] // TODO: AARCH64
|
||||
if flags.contains(PHYSMAP_NO_CACHE) {
|
||||
page_flags = page_flags.custom_flag(EntryFlags::NO_CACHE.bits(), true);
|
||||
}
|
||||
|
||||
grants.insert(Grant::physmap(
|
||||
PhysicalAddress::new(physical_address),
|
||||
dst_address.start_address(),
|
||||
size,
|
||||
page_flags,
|
||||
));
|
||||
|
||||
Ok(dst_address.start_address().data())
|
||||
}
|
||||
pub fn physmap(physical_address: usize, size: usize, flags: PhysmapFlags) -> Result<usize> {
|
||||
enforce_root()?;
|
||||
|
||||
+12
-4
@@ -25,8 +25,8 @@ pub use self::process::*;
|
||||
pub use self::time::*;
|
||||
pub use self::validate::*;
|
||||
|
||||
use self::data::{ExecMemRange, Map, SigAction, Stat, TimeSpec};
|
||||
use self::error::{Error, Result, ENOSYS};
|
||||
use self::data::{CloneInfo, ExecMemRange, Map, SigAction, Stat, TimeSpec};
|
||||
use self::error::{Error, Result, ENOSYS, EINVAL};
|
||||
use self::flag::{CloneFlags, MapFlags, PhysmapFlags, WaitFlags};
|
||||
use self::number::*;
|
||||
|
||||
@@ -134,6 +134,13 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u
|
||||
SYS_CLONE => {
|
||||
let b = CloneFlags::from_bits_truncate(b);
|
||||
|
||||
let info = if b.contains(CloneFlags::CLONE_VM) {
|
||||
if d < core::mem::size_of::<CloneInfo>() {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
Some(&validate_slice(c as *const CloneInfo, 1)?[0])
|
||||
} else { None };
|
||||
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
{
|
||||
//TODO: CLONE_STACK
|
||||
@@ -144,10 +151,11 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
let old_rsp = stack.iret.rsp;
|
||||
// TODO: Unify CLONE_STACK and CLONE_VM.
|
||||
if b.contains(flag::CLONE_STACK) {
|
||||
stack.iret.rsp = c;
|
||||
stack.iret.rsp = info.as_ref().ok_or(Error::new(EINVAL))?.target_stack;
|
||||
}
|
||||
let ret = clone(b, bp).map(ContextId::into);
|
||||
let ret = clone(b, bp, info).map(ContextId::into);
|
||||
stack.iret.rsp = old_rsp;
|
||||
ret
|
||||
}
|
||||
|
||||
+26
-19
@@ -27,7 +27,7 @@ use crate::paging::{ActivePageTable, InactivePageTable, Page, PageFlags, RmmA, T
|
||||
use crate::{ptrace, syscall};
|
||||
use crate::scheme::FileHandle;
|
||||
use crate::start::usermode;
|
||||
use crate::syscall::data::{ExecMemRange, SigAction, Stat};
|
||||
use crate::syscall::data::{CloneInfo, ExecMemRange, SigAction, Stat};
|
||||
use crate::syscall::error::*;
|
||||
use crate::syscall::flag::{wifcontinued, wifstopped, AT_ENTRY, AT_NULL, AT_PHDR, AT_PHENT, AT_PHNUM, CloneFlags,
|
||||
CLONE_FILES, CLONE_FS, CLONE_SIGHAND, CLONE_STACK, CLONE_VFORK, CLONE_VM,
|
||||
@@ -37,7 +37,7 @@ use crate::syscall::flag::{wifcontinued, wifstopped, AT_ENTRY, AT_NULL, AT_PHDR,
|
||||
use crate::syscall::ptrace_event;
|
||||
use crate::syscall::validate::{validate_slice, validate_slice_mut};
|
||||
|
||||
pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
|
||||
pub fn clone(flags: CloneFlags, stack_base: usize, info: Option<&CloneInfo>) -> Result<ContextId> {
|
||||
let ppid;
|
||||
let pid;
|
||||
{
|
||||
@@ -61,6 +61,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
|
||||
let cwd;
|
||||
let files;
|
||||
let actions;
|
||||
let old_sigstack;
|
||||
|
||||
// Copy from old process
|
||||
{
|
||||
@@ -78,6 +79,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
|
||||
ens = context.ens;
|
||||
sigmask = context.sigmask;
|
||||
umask = context.umask;
|
||||
old_sigstack = context.sigstack;
|
||||
|
||||
// Uncomment to disable threads on different CPUs
|
||||
//TODO: fix memory allocation races when this is removed
|
||||
@@ -360,6 +362,12 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
|
||||
context.files = files;
|
||||
|
||||
context.actions = actions;
|
||||
|
||||
if flags.contains(CLONE_VM) {
|
||||
context.sigstack = info.and_then(|info| (info.target_sigstack != !0).then(|| info.target_sigstack));
|
||||
} else {
|
||||
context.sigstack = old_sigstack;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -747,24 +755,23 @@ pub fn setpgid(pid: ContextId, pgid: ContextId) -> Result<usize> {
|
||||
}
|
||||
|
||||
pub fn sigaction(sig: usize, act_opt: Option<&SigAction>, oldact_opt: Option<&mut SigAction>, restorer: usize) -> Result<usize> {
|
||||
if sig > 0 && sig <= 0x7F {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
let mut actions = context.actions.write();
|
||||
|
||||
if let Some(oldact) = oldact_opt {
|
||||
*oldact = actions[sig].0;
|
||||
}
|
||||
|
||||
if let Some(act) = act_opt {
|
||||
actions[sig] = (*act, restorer);
|
||||
}
|
||||
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(Error::new(EINVAL))
|
||||
if sig == 0 || sig > 0x7F {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
let mut actions = context.actions.write();
|
||||
|
||||
if let Some(oldact) = oldact_opt {
|
||||
*oldact = actions[sig].0;
|
||||
}
|
||||
|
||||
if let Some(act) = act_opt {
|
||||
actions[sig] = (*act, restorer);
|
||||
}
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
pub fn sigprocmask(how: usize, mask_opt: Option<&[u64; 2]>, oldmask_opt: Option<&mut [u64; 2]>) -> Result<usize> {
|
||||
|
||||
Reference in New Issue
Block a user