Skip to content

Commit

Permalink
aarch64: properly handle unexpected synchronous exceptions
Browse files Browse the repository at this point in the history
Per the code in arch/aarch64/entry.S that sets up exception
vector table, OSv handles only exceptions in current EL with SPx.
In other words it implemements proper handlers only for exceptions
raised in the exception level EL1. All other exceptions
should never really happen and if the do they would be
caught by the entry_invalid routine that in essence makes
OSv guest hang.

The synchronous exception handler for EL1 - entry_sync -
is intended to handle page faults caused by at attempt to
read, write or execute against page of memory that has not been
been filled in yet. To accomplish it the assembly code
determines the class of the exception (EC) based on the value of
ESR register (Exception Syndrome Register). If the EC
is different from Data Abort or Instruction Abort it branches
to the same entry_invalid handler. This is unfortunate
as it makes debugging crashes/problems like #1100 way more
laborious and requires connecting with gdb jus to see what the issue is.

So this patch changes the the entry_sync to make it branch to the new
unexpected_sync_exception instead of entry_invalid in order to print
state of all registers and backtrace to the console and finally abort the guest.

Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com>
Message-Id: <20201215051218.98340-1-jwkozaczuk@gmail.com>
  • Loading branch information
wkozaczuk authored and nyh committed Dec 15, 2020
1 parent 04a3d7e commit 5e86572
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 3 deletions.
11 changes: 8 additions & 3 deletions arch/aarch64/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -142,16 +142,21 @@ entry_sync:
cmp x2, #ESR_EC_DATA_ABORT
b.eq handle_mem_abort
cmp x2, #ESR_EC_INSN_ABORT
b.ne entry_invalid
b.ne unexpected_sync_exception
handle_mem_abort:
cbz x3, entry_invalid
cbz x3, unexpected_sync_exception
cmp x3, #3
b.hi entry_invalid
b.hi unexpected_sync_exception

mov x0, sp // save exception_frame to x0
bl page_fault
pop_state_from_exception_frame
eret
unexpected_sync_exception:
mov x0, sp // save exception_frame to x0
bl handle_unexpected_sync_exception
pop_state_from_exception_frame
bl abort

.global entry_irq
.type entry_irq, @function
Expand Down
14 changes: 14 additions & 0 deletions arch/aarch64/exceptions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "exceptions.hh"
#include "fault-fixup.hh"
#include "dump.hh"

__thread exception_frame* current_interrupt_frame;
class interrupt_table idt __attribute__((init_priority((int)init_prio::idt)));
Expand Down Expand Up @@ -164,6 +165,19 @@ void interrupt(exception_frame* frame)
sched::preempt();
}

extern "C" { void handle_unexpected_sync_exception(exception_frame* frame); }

#define ESR_EC_BEG 26 // Exception Class field begins in ESR at the bit 26th
#define ESR_EC_END 31 // and ends at 31st
#define ESR_EC_MASK 0b111111UL

void handle_unexpected_sync_exception(exception_frame* frame)
{
u64 exception_class = (frame->esr >> ESR_EC_BEG) & ESR_EC_MASK;
debug_ll("unexpected synchronous exception, EC: 0x%04x\n", exception_class);
dump_registers(frame);
}

bool fixup_fault(exception_frame* ef)
{
fault_fixup v{ef->elr, 0};
Expand Down

0 comments on commit 5e86572

Please sign in to comment.