diff --git a/headers/private/kernel/arch/arm64/arch_cpu.h b/headers/private/kernel/arch/arm64/arch_cpu.h index 53a77cddcd..3d661901a8 100644 --- a/headers/private/kernel/arch/arm64/arch_cpu.h +++ b/headers/private/kernel/arch/arm64/arch_cpu.h @@ -138,6 +138,9 @@ struct iframe { // exception info uint64 esr; uint64 far; + + // fpu + struct aarch64_fpu_state fpu; }; diff --git a/src/system/kernel/arch/arm64/arch_int.cpp b/src/system/kernel/arch/arm64/arch_int.cpp index 2a13d59104..2cfcea780e 100644 --- a/src/system/kernel/arch/arm64/arch_int.cpp +++ b/src/system/kernel/arch/arm64/arch_int.cpp @@ -39,6 +39,11 @@ // threads yet. struct iframe_stack gBootFrameStack; +// In order to avoid store/restore of large FPU state, it is assumed that +// this code and page fault handling doesn't use FPU. +// Instead this is called manually when handling IRQ or syscall. +extern "C" void _fp_save(aarch64_fpu_state *fpu); +extern "C" void _fp_restore(aarch64_fpu_state *fpu); void arch_int_enable_io_interrupt(int32 irq) @@ -340,6 +345,8 @@ do_sync_handler(iframe * frame) } } + _fp_save(&frame->fpu); + thread_at_kernel_entry(system_time()); enable_interrupts(); @@ -362,6 +369,8 @@ do_sync_handler(iframe * frame) } } + _fp_restore(&frame->fpu); + return; } } @@ -393,11 +402,15 @@ do_irq_handler(iframe * frame) IFrameScope scope(frame); + _fp_save(&frame->fpu); + InterruptController *ic = InterruptController::Get(); if (ic != NULL) ic->HandleInterrupt(); after_exception(); + + _fp_restore(&frame->fpu); }