Fix running on multi_core.
Turns out the problem all along was that the ActivePageTable was never dropped in usermode_bootstrap. So as soon as any other hardware thread tried to do page table business, it deadlocked!
This commit is contained in:
@@ -38,7 +38,5 @@
|
||||
/// Offset to user image
|
||||
pub const USER_OFFSET: usize = 0;
|
||||
|
||||
/// Offset for usage in other temporary pages
|
||||
// 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;
|
||||
/// End offset of the user image, i.e. kernel start
|
||||
pub const USER_END_OFFSET: usize = 256 * PML4_SIZE;
|
||||
|
||||
@@ -68,7 +68,7 @@ impl UserGrants {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
inner: BTreeSet::new(),
|
||||
holes: core::iter::once((VirtualAddress::new(0), crate::PML4_SIZE * 256)).collect::<BTreeMap<_, _>>(),
|
||||
holes: core::iter::once((VirtualAddress::new(0), crate::USER_END_OFFSET)).collect::<BTreeMap<_, _>>(),
|
||||
funmap: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
@@ -114,7 +114,7 @@ impl UserGrants {
|
||||
let mut requested = Region::new(address, size);
|
||||
|
||||
if
|
||||
requested.end_address().data() > crate::PML4_SIZE * 256 // There are 256 PML4 entries reserved for userspace
|
||||
requested.end_address().data() > crate::USER_END_OFFSET
|
||||
|| address.data() % PAGE_SIZE != 0
|
||||
{
|
||||
// ... but it was invalid
|
||||
|
||||
@@ -451,13 +451,9 @@ pub unsafe fn regs_for_mut(context: &mut Context) -> Option<&mut InterruptStack>
|
||||
// Returns an iterator which splits [start, start + len) into an iterator of possibly trimmed
|
||||
// pages.
|
||||
fn page_aligned_chunks(mut start: usize, mut len: usize) -> impl Iterator<Item = (usize, usize)> {
|
||||
// TODO: Define this elsewhere!
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
const KERNEL_SPLIT_START: usize = crate::PML4_SIZE * 256;
|
||||
|
||||
// Ensure no pages can overlap with kernel memory.
|
||||
if start.saturating_add(len) > KERNEL_SPLIT_START {
|
||||
len = KERNEL_SPLIT_START.saturating_sub(start);
|
||||
if start.saturating_add(len) > crate::USER_END_OFFSET {
|
||||
len = crate::USER_END_OFFSET.saturating_sub(start);
|
||||
}
|
||||
|
||||
let first_len = core::cmp::min(len, PAGE_SIZE - start % PAGE_SIZE);
|
||||
|
||||
@@ -645,7 +645,7 @@ impl Scheme for ProcScheme {
|
||||
let flags = chunks.next().and_then(|f| MapFlags::from_bits(f)).ok_or(Error::new(EINVAL))?;
|
||||
let region = Region::new(VirtualAddress::new(base), size);
|
||||
|
||||
if base % PAGE_SIZE != 0 || size % PAGE_SIZE != 0 || base.saturating_add(size) > crate::PML4_SIZE * 256 {
|
||||
if base % PAGE_SIZE != 0 || size % PAGE_SIZE != 0 || base.saturating_add(size) > crate::USER_END_OFFSET {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize, info: Option<&CloneInfo>) ->
|
||||
cpu_id_opt = context.cpu_id;
|
||||
}
|
||||
|
||||
// TODO: Fill with newest registers.
|
||||
arch = context.arch.clone();
|
||||
|
||||
if let Some(ref fx) = context.kfx {
|
||||
@@ -115,6 +116,9 @@ pub fn clone(flags: CloneFlags, stack_base: usize, info: Option<&CloneInfo>) ->
|
||||
//
|
||||
// (base pointer - start of stack) - one
|
||||
offset = stack_base - stack.as_ptr() as usize - mem::size_of::<usize>(); // Add clone ret
|
||||
// FIXME: This is incredibly UB, making Rust think the current stack being
|
||||
// copied is simply a regular immutable slice. This part should either be
|
||||
// written in assembly or have clone moved to userspace.
|
||||
let mut new_stack = stack.clone();
|
||||
|
||||
unsafe {
|
||||
@@ -352,7 +356,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize, info: Option<&CloneInfo>) ->
|
||||
};
|
||||
let _ = scheme.kfmap(number, &map, &new_context_lock);
|
||||
}
|
||||
new_context_lock.write().unblock();
|
||||
new_context_lock.write().status = context::Status::Runnable;
|
||||
}
|
||||
|
||||
if ptrace::send_event(ptrace_event!(PTRACE_EVENT_CLONE, pid.into())).is_some() {
|
||||
@@ -997,12 +1001,14 @@ pub fn usermode_bootstrap(mut data: Box<[u8]>) -> ! {
|
||||
const LOAD_BASE: usize = 0;
|
||||
let grant = context::memory::Grant::map(VirtualAddress::new(LOAD_BASE), ((data.len()+PAGE_SIZE-1)/PAGE_SIZE)*PAGE_SIZE, PageFlags::new().user(true).write(true).execute(true));
|
||||
|
||||
let mut active_table = unsafe { ActivePageTable::new(TableKind::User) };
|
||||
{
|
||||
let mut active_table = unsafe { ActivePageTable::new(TableKind::User) };
|
||||
|
||||
for (index, page) in grant.pages().enumerate() {
|
||||
let len = if data.len() - index * PAGE_SIZE < PAGE_SIZE { data.len() % PAGE_SIZE } else { PAGE_SIZE };
|
||||
let frame = active_table.translate_page(page).expect("expected mapped init memory to have a corresponding frame");
|
||||
unsafe { ((frame.start_address().data() + crate::PHYS_OFFSET) as *mut u8).copy_from_nonoverlapping(data.as_ptr().add(index * PAGE_SIZE), len); }
|
||||
for (index, page) in grant.pages().enumerate() {
|
||||
let len = if data.len() - index * PAGE_SIZE < PAGE_SIZE { data.len() % PAGE_SIZE } else { PAGE_SIZE };
|
||||
let frame = active_table.translate_page(page).expect("expected mapped init memory to have a corresponding frame");
|
||||
unsafe { ((frame.start_address().data() + crate::PHYS_OFFSET) as *mut u8).copy_from_nonoverlapping(data.as_ptr().add(index * PAGE_SIZE), len); }
|
||||
}
|
||||
}
|
||||
|
||||
context::contexts().current().expect("expected a context to exist when executing init").read().grants.write().insert(grant);
|
||||
@@ -1012,8 +1018,7 @@ pub fn usermode_bootstrap(mut data: Box<[u8]>) -> ! {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
unsafe {
|
||||
let start = ((LOAD_BASE + 0x18) as *mut usize).read();
|
||||
// Start with the (probably) ELF executable loaded, without any stack the ability to load
|
||||
// sections to arbitrary addresses.
|
||||
// Start with the (probably) ELF executable loaded, without any stack.
|
||||
usermode(start, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user