Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nested interrupt support for aarch64 #178

Merged
merged 3 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions src/kernel/src/arch/aarch64/exception.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,6 @@ impl From<ExceptionContext> for UpcallFrame {
}
}

// TODO: reentrant/nested interrupt support
// x save spsr_el1 and elr_el1 before calling handler
// - enable interrupts while servicing exceptions

/// macro creates a high level exception handler
/// to be used in the exception vector table.
/// saves/restores regs on the current stack pointer
Expand Down Expand Up @@ -432,7 +428,7 @@ fn sync_handler(ctx: &mut ExceptionContext) {
todo!("Permission fault, level {} {:?} {:?}", level, cause, far_va);
}
crate::thread::enter_kernel();
// crate::interrupt::set(true);
crate::interrupt::set(true);
let elr = ctx.elr;
if let Ok(elr_va) = VirtAddr::new(elr) {
crate::memory::context::virtmem::page_fault(
Expand All @@ -444,7 +440,7 @@ fn sync_handler(ctx: &mut ExceptionContext) {
} else {
todo!("send upcall exception info");
}
// crate::interrupt::set(false);
crate::interrupt::set(false);
crate::thread::exit_kernel();
},
Some(ESR_EL1::EC::Value::InstrAbortLowerEL) => {
Expand All @@ -463,6 +459,7 @@ fn sync_handler(ctx: &mut ExceptionContext) {
debug_handler(ctx)
},
}
crate::interrupt::post_interrupt();
}

fn handle_inst_abort(ctx: &mut ExceptionContext, esr_reg: &InMemoryRegister<u64, ESR_EL1::Register>) {
Expand Down Expand Up @@ -503,7 +500,7 @@ fn handle_inst_abort(ctx: &mut ExceptionContext, esr_reg: &InMemoryRegister<u64,
}

crate::thread::enter_kernel();
// crate::interrupt::set(true);
crate::interrupt::set(true);
let elr = ctx.elr;
if let Ok(elr_va) = VirtAddr::new(elr) {
// logln!("fault {:?} from {:?}", far_va, elr_va);
Expand All @@ -516,7 +513,7 @@ fn handle_inst_abort(ctx: &mut ExceptionContext, esr_reg: &InMemoryRegister<u64,
} else {
todo!("send upcall exception info");
}
// crate::interrupt::set(false);
crate::interrupt::set(false);
crate::thread::exit_kernel();
}

Expand Down
1 change: 1 addition & 0 deletions src/kernel/src/arch/aarch64/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ pub fn init_interrupts() {
PhysicalTimer::INTERRUPT_ID,
cpu.id,
);
INTERRUPT_CONTROLLER.enable_interrupt(PhysicalTimer::INTERRUPT_ID);
}

pub fn set_interrupt(
Expand Down
12 changes: 5 additions & 7 deletions src/kernel/src/arch/aarch64/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,6 @@ pub unsafe fn return_to_user(context: &Armv8SyscallContext) -> ! {
// set the stack pointer
SP_EL0.set(context.sp);

// TODO: enable interrupts when we can support nested exception handling
// crate::interrupt::set(true);

// configure the execution state for EL0:
// - interrupts unmasked
// - el0 exception level
Expand All @@ -130,9 +127,6 @@ pub unsafe fn return_to_user(context: &Armv8SyscallContext) -> ! {

/// Service a system call according to the ABI defined in [`twizzler_abi`]
pub fn handle_syscall(ctx: &mut ExceptionContext) {
crate::thread::enter_kernel();
crate::interrupt::set(true);

let mut context: Armv8SyscallContext = Default::default();
context.x0 = ctx.x0;
context.x1 = ctx.x1;
Expand All @@ -145,8 +139,12 @@ pub fn handle_syscall(ctx: &mut ExceptionContext) {
context.sp = ctx.sp;
context.elr = ctx.elr;

crate::thread::enter_kernel();
crate::interrupt::set(true);

crate::syscall::syscall_entry(&mut context);
// crate::interrupt::set(false);

crate::interrupt::set(false);
crate::thread::exit_kernel();

// copy over result values to exception return context
Expand Down
34 changes: 22 additions & 12 deletions src/kernel/src/arch/aarch64/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use twizzler_abi::upcall::{UpcallFrame, UpcallInfo, UpcallTarget};
use crate::thread::Thread;
use crate::memory::VirtAddr;

use super::{exception::ExceptionContext, syscall::Armv8SyscallContext};
use super::{exception::ExceptionContext, syscall::Armv8SyscallContext, interrupt::DAIFMaskBits};

#[derive(Copy, Clone)]
pub enum Registers {
Expand Down Expand Up @@ -48,6 +48,8 @@ struct RegisterContext {
// thread local storage for user space
tpidr: u64,
tpidrro: u64,
// interrupt state
daif: u64,
}

// arch specific thread state
Expand All @@ -62,7 +64,7 @@ unsafe impl Send for ArchThread {}
impl ArchThread {
pub fn new() -> Self {
Self {
context: RegisterContext::default()
context: RegisterContext::default(),
}
}
}
Expand Down Expand Up @@ -149,12 +151,14 @@ impl Thread {
// save the fp (x29) and the lr (x30)
"stp x29, x30, [x11, #16 * 5]",
// save stack pointer
"mov x15, sp",
"mov x12, sp",
// save the thread pointer registers
"mrs x14, tpidr_el0",
"mrs x13, tpidrro_el0",
"stp x15, x14, [x11, #16 * 6]",
"str x13, [x11, #16 * 7]",
"mrs x13, tpidr_el0",
"mrs x14, tpidrro_el0",
// save the current interrupt state
"mrs x15, daif",
"stp x12, x13, [x11, #16 * 6]",
"stp x14, x15, [x11, #16 * 7]",
// (2) restore next thread's regs
"ldp x19, x20, [x10, #16 * 0]",
"ldp x21, x22, [x10, #16 * 1]",
Expand All @@ -163,12 +167,15 @@ impl Thread {
"ldp x27, x28, [x10, #16 * 4]",
// restore the fp (x29) and the lr (x30)
"ldp x29, x30, [x10, #16 * 5]",
// restore the thread pointer registers
"ldp x12, x13, [x10, #16 * 6]",
"ldp x14, x15, [x10, #16 * 7]",
"msr tpidr_el0, x13",
"msr tpidrro_el0, x14",
// (3) switch thread stacks
"ldp x15, x14, [x10, #16 * 6]",
"ldr x13, [x10, #16 * 7]",
"msr tpidr_el0, x14",
"msr tpidrro_el0, x13",
"mov sp, x15",
"mov sp, x12",
// set the current interrupt state
"msr daif, x15",
// (4) execution resumes in the address
// pointed to by the link register (x30)
"ret",
Expand All @@ -190,5 +197,8 @@ impl Thread {
self.arch.context.sp = stack as u64;
// set the link register as the second to last entry (x30)
self.arch.context.lr = entry as u64;
// by default interrupts are enabled (unmask the I bit)
// in other words set bits D,A, and F in DAIF[9:6]
self.arch.context.daif = (DAIFMaskBits::IRQ.complement().bits() as u64) << 6;
}
}
Loading