Fix everything all the way to booting to desktop.

This commit is contained in:
4lDO2
2022-02-22 19:49:05 +01:00
parent e6e1348072
commit 15b029de36
8 changed files with 110 additions and 118 deletions
+3 -1
View File
@@ -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 = []
+2 -41
View File
@@ -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;
+7 -2
View File
@@ -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,
})
}
+3 -3
View File
@@ -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;
+18
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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> {