Merge branch 'wip-clone-and-misc-fixes' into 'aarch64-rebase'

Wip clone and misc fixes

See merge request redox-os/kernel!161
This commit is contained in:
Jeremy Soller
2021-01-18 23:00:00 +00:00
9 changed files with 226 additions and 107 deletions

View File

@@ -10,92 +10,92 @@ exception_vector_base:
.align 7
__vec_00:
mov x18, #0xb0b0
wfi
b __vec_00
b do_exception_synchronous
b __vec_00
.align 7
__vec_01:
mov x18, #0xb0b1
wfi
b __vec_01
b do_exception_irq
b __vec_01
.align 7
__vec_02:
mov x18, #0xb0b2
wfi
b __vec_02
b do_exception_unhandled
b __vec_02
.align 7
__vec_03:
mov x18, #0xb0b3
wfi
b __vec_03
b do_exception_unhandled
b __vec_03
.align 7
__vec_04:
b do_report_exception
wfi
b __vec_04
mov x18, #0xb0b4
b do_exception_synchronous
b __vec_04
.align 7
__vec_05:
b do_irq // First level interrupt handler
wfi
b __vec_05
mov x18, #0xb0b5
b do_exception_irq
b __vec_05
.align 7
__vec_06:
mov x18, #0xb0b6
wfi
b __vec_06
b do_exception_unhandled
b __vec_06
.align 7
__vec_07:
mov x18, #0xb0b7
wfi
b __vec_07
b do_exception_unhandled
b __vec_07
.align 7
__vec_08:
b do_syscall // Syscall handler
wfi
b __vec_08
mov x18, #0xb0b8
b do_exception_synchronous
b __vec_08
.align 7
__vec_09:
b do_irq // First level interrupt handler
wfi
b __vec_09
mov x18, #0xb0b9
b do_exception_irq
b __vec_09
.align 7
__vec_10:
mov x18, #0xb0bb
wfi
b __vec_10
mov x18, #0xb0ba
b do_exception_unhandled
b __vec_10
.align 7
__vec_11:
mov x18, #0xb0bc
wfi
b __vec_11
mov x18, #0xb0bb
b do_exception_unhandled
b __vec_11
.align 7
__vec_12:
mov x18, #0xb0bd
wfi
b __vec_12
mov x18, #0xb0bc
b do_exception_unhandled
b __vec_12
.align 7
__vec_13:
mov x18, #0xb0be
wfi
b __vec_13
mov x18, #0xb0bd
b do_exception_unhandled
b __vec_13
.align 7
__vec_14:
mov x18, #0xb0bf
wfi
b __vec_14
mov x18, #0xb0be
b do_exception_unhandled
b __vec_14
.align 7
exception_vector_end:

View File

@@ -12,7 +12,7 @@ pub static PIT_TICKS: AtomicUsize = ATOMIC_USIZE_INIT;
#[naked]
#[no_mangle]
pub unsafe extern fn do_irq() {
pub unsafe extern fn do_exception_irq() {
#[inline(never)]
unsafe fn inner() {
irq_demux();

View File

@@ -3,9 +3,91 @@ use crate::syscall;
#[naked]
#[no_mangle]
pub unsafe extern fn do_syscall() {
pub unsafe extern fn do_exception_unhandled() {
#[inline(never)]
unsafe fn inner(stack: &mut InterruptStack) -> usize {
println!("do_exception_unhandled: ELR: 0x{:016x}", stack.elr_el1);
loop {}
}
llvm_asm!("str x0, [sp, #-8]!
str x1, [sp, #-8]!
str x2, [sp, #-8]!
str x3, [sp, #-8]!
str x4, [sp, #-8]!
str x5, [sp, #-8]!
str x6, [sp, #-8]!
str x7, [sp, #-8]!
str x8, [sp, #-8]!
str x9, [sp, #-8]!
str x10, [sp, #-8]!
str x11, [sp, #-8]!
str x12, [sp, #-8]!
str x13, [sp, #-8]!
str x14, [sp, #-8]!
str x15, [sp, #-8]!
str x16, [sp, #-8]!
str x17, [sp, #-8]!
str x18, [sp, #-8]!
str x19, [sp, #-8]!
str x20, [sp, #-8]!
str x21, [sp, #-8]!
str x22, [sp, #-8]!
str x23, [sp, #-8]!
str x24, [sp, #-8]!
str x25, [sp, #-8]!
str x26, [sp, #-8]!
str x27, [sp, #-8]!
str x28, [sp, #-8]!
str x29, [sp, #-8]!
str x30, [sp, #-8]!
mrs x18, sp_el0
str x18, [sp, #-8]!
mrs x18, esr_el1
str x18, [sp, #-8]!
mrs x18, spsr_el1
str x18, [sp, #-8]!
mrs x18, tpidrro_el0
str x18, [sp, #-8]!
mrs x18, tpidr_el0
str x18, [sp, #-8]!
str x18, [sp, #-8]!
mrs x18, elr_el1
str x18, [sp, #-8]!"
: : : : "volatile");
let sp: usize;
llvm_asm!("" : "={sp}"(sp) : : : "volatile");
llvm_asm!("mov x29, sp" : : : : "volatile");
let a = inner(&mut *(sp as *mut InterruptStack));
}
#[naked]
#[no_mangle]
pub unsafe extern fn do_exception_synchronous() {
#[inline(never)]
unsafe fn inner(stack: &mut InterruptStack) -> usize {
let exception_code = (stack.esr_el1 & (0x3f << 26)) >> 26;
if exception_code != 0b010101 {
println!("do_exception_synchronous: Non-SVC!!!");
loop {}
} else {
println!("do_exception_synchronous: SVC: x8: 0x{:016x}", stack.scratch.x8);
}
llvm_asm!("nop": : : : "volatile");
llvm_asm!("nop": : : : "volatile");
llvm_asm!("nop": : : : "volatile");
llvm_asm!("nop": : : : "volatile");
let fp;
llvm_asm!("" : "={fp}"(fp) : : : "volatile");
@@ -183,15 +265,6 @@ pub struct SyscallStack {
#[naked]
pub unsafe extern fn clone_ret() {
llvm_asm!("ldp x29, x30, [sp], #16");
llvm_asm!("ldp x29, x30, [sp], #0x60");
llvm_asm!("mov x0, 0");
}
/*
#[naked]
pub unsafe extern fn clone_ret() {
llvm_asm!("add sp, sp, #16");
llvm_asm!("ldp x29, x30, [sp], #16");
llvm_asm!("mov x0, 0");
}
*/

View File

@@ -176,10 +176,8 @@ pub unsafe extern fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
#[naked]
pub unsafe fn usermode(ip: usize, sp: usize, arg: usize, singlestep: bool) -> ! {
let cpu_id: usize = 0;
let uspace_tls_start = (crate::USER_TLS_OFFSET + crate::USER_TLS_SIZE * cpu_id);
let spsr: u32 = 0;
llvm_asm!("msr tpidr_el0, $0" : : "r"(uspace_tls_start) : : "volatile");
llvm_asm!("msr spsr_el1, $0" : : "r"(spsr) : : "volatile");
llvm_asm!("msr elr_el1, $0" : : "r"(ip) : : "volatile");
llvm_asm!("msr sp_el0, $0" : : "r"(sp) : : "volatile");

View File

@@ -14,6 +14,7 @@ pub struct Context {
elr_el1: usize,
sp_el0: usize,
ttbr0_el1: usize, /* Pointer to U4 translation table for this Context */
ttbr1_el1: usize, /* Pointer to P4 translation table for this Context */
tpidr_el0: usize, /* Pointer to TLS region for this Context */
tpidrro_el0: usize, /* Pointer to TLS (read-only) region for this Context */
rflags: usize,
@@ -53,6 +54,7 @@ impl Context {
elr_el1: 0,
sp_el0: 0,
ttbr0_el1: 0,
ttbr1_el1: 0,
tpidr_el0: 0,
tpidrro_el0: 0,
rflags: 0, /* spsr_el1 */
@@ -92,10 +94,14 @@ impl Context {
pub fn set_fx(&mut self, _address: usize) {
}
pub fn set_page_table(&mut self, address: usize) {
pub fn set_page_utable(&mut self, address: usize) {
self.ttbr0_el1 = address;
}
pub fn set_page_ktable(&mut self, address: usize) {
self.ttbr1_el1 = address;
}
pub fn set_stack(&mut self, address: usize) {
self.sp = address;
}

View File

@@ -92,12 +92,12 @@ impl ContextList {
#[cfg(target_arch = "aarch64")]
{
let context_id = context.id.into();
context.arch.set_tcb(context_id);
context.arch.set_lr(func as usize);
context.arch.set_context_handle();
}
context.arch.set_page_table(unsafe { ActivePageTable::new(PageTableType::User).address() });
context.arch.set_page_utable(unsafe { ActivePageTable::new(PageTableType::User).address() });
context.arch.set_page_ktable(unsafe { ActivePageTable::new(PageTableType::Kernel).address() });
context.arch.set_fx(fx.as_ptr() as usize);
context.arch.set_stack(stack.as_ptr() as usize + offset);
context.kfx = Some(fx);

View File

@@ -151,6 +151,11 @@ pub unsafe fn switch() -> bool {
}
gdt::set_tcb((*to_ptr).id.into());
}
#[cfg(target_arch = "aarch64")]
{
let pid = (*to_ptr).id.into();
(*to_ptr).arch.set_tcb(pid);
}
CONTEXT_ID.store((*to_ptr).id, Ordering::SeqCst);
}

View File

@@ -129,7 +129,8 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u
#[cfg(target_arch = "aarch64")]
{
//TODO: CLONE_STACK
clone(b, bp).map(ContextId::into)
let ret = clone(b, bp).map(ContextId::into);
ret
}
#[cfg(target_arch = "x86_64")]

View File

@@ -94,30 +94,42 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
kfx_opt = Some(new_fx);
}
if let Some(ref stack) = context.kstack {
// Get the relative offset to the return address of the function
// obtaining `stack_base`.
//
// (base pointer - start of stack) - one
offset = stack_base - stack.as_ptr() as usize - mem::size_of::<usize>(); // Add clone ret
let mut new_stack = stack.clone();
#[cfg(target_arch = "x86_64")]
{
if let Some(ref stack) = context.kstack {
// Get the relative offset to the return address of the function
// obtaining `stack_base`.
//
// (base pointer - start of stack) - one
offset = stack_base - stack.as_ptr() as usize - mem::size_of::<usize>(); // Add clone ret
let mut new_stack = stack.clone();
unsafe {
// Set clone's return value to zero. This is done because
// the clone won't return like normal, which means the value
// would otherwise never get set.
#[cfg(target_arch = "x86_64")] // TODO
if let Some(regs) = ptrace::rebase_regs_ptr_mut(context.regs, Some(&mut new_stack)) {
(*regs).scratch.rax = 0;
unsafe {
// Set clone's return value to zero. This is done because
// the clone won't return like normal, which means the value
// would otherwise never get set.
if let Some(regs) = ptrace::rebase_regs_ptr_mut(context.regs, Some(&mut new_stack)) {
(*regs).scratch.rax = 0;
}
// Change the return address of the child (previously
// syscall) to the arch-specific clone_ret callback
let func_ptr = new_stack.as_mut_ptr().add(offset);
*(func_ptr as *mut usize) = interrupt::syscall::clone_ret as usize;
}
// Change the return address of the child (previously
// syscall) to the arch-specific clone_ret callback
let func_ptr = new_stack.as_mut_ptr().add(offset);
*(func_ptr as *mut usize) = interrupt::syscall::clone_ret as usize;
kstack_opt = Some(new_stack);
}
}
kstack_opt = Some(new_stack);
#[cfg(target_arch = "aarch64")]
{
if let Some(ref stack) = context.kstack {
offset = stack_base - stack.as_ptr() as usize;
let mut new_stack = stack.clone();
kstack_opt = Some(new_stack);
}
}
if flags.contains(CLONE_VM) {
@@ -338,31 +350,39 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
context.arch = arch;
let mut active_table = unsafe { ActivePageTable::new(PageTableType::User) };
let mut active_utable = unsafe { ActivePageTable::new(PageTableType::User) };
let mut active_ktable = unsafe { ActivePageTable::new(PageTableType::Kernel) };
let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(crate::USER_TMP_MISC_OFFSET)));
let mut temporary_upage = TemporaryPage::new(Page::containing_address(VirtualAddress::new(crate::USER_TMP_MISC_OFFSET)));
let mut temporary_kpage = TemporaryPage::new(Page::containing_address(VirtualAddress::new(crate::KERNEL_TMP_MISC_OFFSET)));
let mut new_table = {
let mut new_utable = {
let frame = allocate_frames(1).expect("no more frames in syscall::clone new_table");
InactivePageTable::new(frame, &mut active_table, &mut temporary_page)
InactivePageTable::new(frame, &mut active_utable, &mut temporary_upage)
};
context.arch.set_page_table(unsafe { new_table.address() });
let mut new_ktable = {
let frame = allocate_frames(1).expect("no more frames in syscall::clone new_table");
InactivePageTable::new(frame, &mut active_ktable, &mut temporary_kpage)
};
context.arch.set_page_utable(unsafe { new_utable.address() });
context.arch.set_page_ktable(unsafe { new_ktable.address() });
// Copy kernel image mapping
{
let frame = active_table.p4()[crate::KERNEL_PML4].pointed_frame().expect("kernel image not mapped");
let flags = active_table.p4()[crate::KERNEL_PML4].flags();
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
let frame = active_ktable.p4()[crate::KERNEL_PML4].pointed_frame().expect("kernel image not mapped");
let flags = active_ktable.p4()[crate::KERNEL_PML4].flags();
active_ktable.with(&mut new_ktable, &mut temporary_kpage, |mapper| {
mapper.p4_mut()[crate::KERNEL_PML4].set(frame, flags);
});
}
// Copy kernel heap mapping
{
let frame = active_table.p4()[crate::KERNEL_HEAP_PML4].pointed_frame().expect("kernel heap not mapped");
let flags = active_table.p4()[crate::KERNEL_HEAP_PML4].flags();
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
let frame = active_ktable.p4()[crate::KERNEL_HEAP_PML4].pointed_frame().expect("kernel heap not mapped");
let flags = active_ktable.p4()[crate::KERNEL_HEAP_PML4].flags();
active_ktable.with(&mut new_ktable, &mut temporary_kpage, |mapper| {
mapper.p4_mut()[crate::KERNEL_HEAP_PML4].set(frame, flags);
});
}
@@ -376,6 +396,10 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
if let Some(stack) = kstack_opt.take() {
context.arch.set_stack(stack.as_ptr() as usize + offset);
context.kstack = Some(stack);
#[cfg(target_arch = "aarch64")]
{
context.arch.set_lr(interrupt::syscall::clone_ret as usize);
}
}
// TODO: Clone ksig?
@@ -384,9 +408,9 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
if flags.contains(CLONE_VM) {
// Copy user image mapping, if found
if ! image.is_empty() {
let frame = active_table.p4()[crate::USER_PML4].pointed_frame().expect("user image not mapped");
let flags = active_table.p4()[crate::USER_PML4].flags();
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
let frame = active_utable.p4()[crate::USER_PML4].pointed_frame().expect("user image not mapped");
let flags = active_utable.p4()[crate::USER_PML4].flags();
active_utable.with(&mut new_utable, &mut temporary_upage, |mapper| {
mapper.p4_mut()[crate::USER_PML4].set(frame, flags);
});
}
@@ -394,9 +418,9 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
// Copy grant mapping
if ! grants.lock().is_empty() {
let frame = active_table.p4()[crate::USER_GRANT_PML4].pointed_frame().expect("user grants not mapped");
let flags = active_table.p4()[crate::USER_GRANT_PML4].flags();
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
let frame = active_utable.p4()[crate::USER_GRANT_PML4].pointed_frame().expect("user grants not mapped");
let flags = active_utable.p4()[crate::USER_GRANT_PML4].flags();
active_utable.with(&mut new_utable, &mut temporary_upage, |mapper| {
mapper.p4_mut()[crate::USER_GRANT_PML4].set(frame, flags);
});
}
@@ -419,8 +443,8 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
let start_page = Page::containing_address(VirtualAddress::new(start));
let end_page = Page::containing_address(VirtualAddress::new(end - 1));
for page in Page::range_inclusive(start_page, end_page) {
let frame = active_table.translate_page(page).expect("kernel percpu not mapped");
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
let frame = active_ktable.translate_page(page).expect("kernel percpu not mapped");
active_ktable.with(&mut new_ktable, &mut temporary_kpage, |mapper| {
let result = mapper.map_to(page, frame, EntryFlags::PRESENT | EntryFlags::NO_EXECUTE | EntryFlags::WRITABLE);
// Ignore result due to operating on inactive table
unsafe { result.ignore(); }
@@ -432,7 +456,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
for memory_shared in image.iter_mut() {
memory_shared.with(|memory| {
let start = VirtualAddress::new(memory.start_address().data() - crate::USER_TMP_OFFSET + crate::USER_OFFSET);
memory.move_to(start, &mut new_table, &mut temporary_page);
memory.move_to(start, &mut new_utable, &mut temporary_upage);
});
}
context.image = image;
@@ -444,7 +468,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
for mut grant in old_grants.inner.into_iter() {
let start = VirtualAddress::new(grant.start_address().data() + crate::USER_GRANT_OFFSET - crate::USER_TMP_GRANT_OFFSET);
grant.move_to(start, &mut new_table, &mut temporary_page);
grant.move_to(start, &mut new_utable, &mut temporary_upage);
grants.insert(grant);
}
}
@@ -454,14 +478,14 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
// Setup user stack
if let Some(stack_shared) = stack_opt {
if flags.contains(CLONE_STACK) {
let frame = active_table.p4()[crate::USER_STACK_PML4].pointed_frame().expect("user stack not mapped");
let flags = active_table.p4()[crate::USER_STACK_PML4].flags();
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
let frame = active_utable.p4()[crate::USER_STACK_PML4].pointed_frame().expect("user stack not mapped");
let flags = active_utable.p4()[crate::USER_STACK_PML4].flags();
active_utable.with(&mut new_utable, &mut temporary_upage, |mapper| {
mapper.p4_mut()[crate::USER_STACK_PML4].set(frame, flags);
});
} else {
stack_shared.with(|stack| {
stack.move_to(VirtualAddress::new(crate::USER_STACK_OFFSET), &mut new_table, &mut temporary_page);
stack.move_to(VirtualAddress::new(crate::USER_STACK_OFFSET), &mut new_utable, &mut temporary_upage);
});
}
context.stack = Some(stack_shared);
@@ -469,7 +493,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
// Setup user sigstack
if let Some(mut sigstack) = sigstack_opt {
sigstack.move_to(VirtualAddress::new(crate::USER_SIGSTACK_OFFSET), &mut new_table, &mut temporary_page);
sigstack.move_to(VirtualAddress::new(crate::USER_SIGSTACK_OFFSET), &mut new_utable, &mut temporary_upage);
context.sigstack = Some(sigstack);
}
@@ -482,13 +506,25 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
true
);
#[cfg(target_arch = "aarch64")]
{
if let Some(stack) = &mut context.kstack {
unsafe {
let interrupt_stack_offset_from_stack_base = *(stack_base as *const u64) - stack_base as u64;
let mut interrupt_stack = &mut *(stack.as_mut_ptr().add(offset + interrupt_stack_offset_from_stack_base as usize) as *mut crate::arch::interrupt::InterruptStack);
interrupt_stack.tpidr_el0 = tcb_addr;
}
}
}
// Setup user TLS
if let Some(mut tls) = tls_opt {
// Copy TLS mapping
{
let frame = active_table.p4()[crate::USER_TLS_PML4].pointed_frame().expect("user tls not mapped");
let flags = active_table.p4()[crate::USER_TLS_PML4].flags();
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
let frame = active_utable.p4()[crate::USER_TLS_PML4].pointed_frame().expect("user tls not mapped");
let flags = active_utable.p4()[crate::USER_TLS_PML4].flags();
active_utable.with(&mut new_utable, &mut temporary_upage, |mapper| {
mapper.p4_mut()[crate::USER_TLS_PML4].set(frame, flags);
});
}
@@ -496,7 +532,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
// TODO: Make sure size is not greater than USER_TLS_SIZE
let tls_addr = crate::USER_TLS_OFFSET + context.id.into() * crate::USER_TLS_SIZE;
//println!("{}: Copy TLS: address 0x{:x}, size 0x{:x}", context.id.into(), tls_addr, tls.mem.size());
tls.mem.move_to(VirtualAddress::new(tls_addr), &mut new_table, &mut temporary_page);
tls.mem.move_to(VirtualAddress::new(tls_addr), &mut new_utable, &mut temporary_upage);
unsafe {
*(tcb_addr as *mut usize) = tls.mem.start_address().data() + tls.mem.size();
}
@@ -511,7 +547,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
}
}
tcb.move_to(VirtualAddress::new(tcb_addr), &mut new_table, &mut temporary_page);
tcb.move_to(VirtualAddress::new(tcb_addr), &mut new_utable, &mut temporary_upage);
context.image.push(tcb.to_shared());
context.name = name;