blob: 44f89c07a1da1a78fe802e0207ff392329aa5c83 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <stdio.h>
#include <zircon/assert.h>
#include <phys/exception.h>
#include <phys/symbolize.h>
#ifdef __aarch64__
#include <lib/arch/arm64/system.h>
#endif
#include "test-main.h"
namespace {
// These are actually defined with internal linkage in the __asm__ in TestMain.
extern "C" void ExceptionSite(), ExceptionResume();
const uint64_t kExceptionSite = reinterpret_cast<uintptr_t>(ExceptionSite);
const uint64_t kExceptionResume = reinterpret_cast<uintptr_t>(ExceptionResume);
#if defined(__aarch64__)
uint64_t& TestRegister(PhysExceptionState& state) { return state.regs.r[0]; }
#elif defined(__x86_64__)
uint64_t& TestRegister(PhysExceptionState& state) { return state.regs.rax; }
#endif
PHYS_SINGLETHREAD uint64_t HandleExpectedException(uint64_t vector, const char* vector_name,
PhysExceptionState& state) {
PrintPhysException(vector, vector_name, state);
ZX_ASSERT(state.pc() == kExceptionSite);
uint64_t& test_value = TestRegister(state);
ZX_ASSERT(test_value == 17);
test_value = 23;
printf("%s: Resume from exception at %#" PRIx64 " to PC %#" PRIx64 "...\n", ProgramName(),
state.pc(), kExceptionResume);
return PhysExceptionResume(state, kExceptionResume, state.sp(), state.psr());
}
} // namespace
int TestMain(void* zbi, arch::EarlyTicks ticks) {
MainSymbolize symbolize("phys-exception-test");
symbolize.ContextAlways();
printf("Hello, world.\n");
gPhysHandledException = {.pc = reinterpret_cast<uintptr_t>(ExceptionSite),
.handler = HandleExpectedException};
uint64_t interrupted_register = 17;
printf("I'm going to crash now! The magic number is %" PRIu64 ".\n", interrupted_register);
#if defined(__aarch64__)
__asm__(
R"""(
mov x0, %[before]
ExceptionSite:
brk #0
ExceptionResume:
mov %[after], x0
)"""
: [after] "=r"(interrupted_register)
: [before] "r"(interrupted_register)
: "x0");
#elif defined(__x86_64__)
__asm__(
R"""(
ExceptionSite:
ud2
ExceptionResume:
)"""
: "=a"(interrupted_register)
: "a"(interrupted_register));
#else
__builtin_trap();
#endif
printf("I'm back now! The magic number is %" PRIu64 ".\n", interrupted_register);
ZX_ASSERT(interrupted_register == 23);
return 0;
}