lib: ramdetect: Register exception handlers for ARMv8
Register exception handlers to avoid a Synchronous External Abort that is raised when you try to access a non-memory address on ARMv8. An exception handler can jump over the faulting instruction. This is the feature only for QEMU/AArch64. Signed-off-by: Asami Doi <d0iasm.pub@gmail.com> Change-Id: I09a306ca307ba4027d9758c3debc2e7c844c66b8 Reviewed-on: https://review.coreboot.org/c/coreboot/+/34774 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Raul Rangel <rrangel@chromium.org>
This commit is contained in:
parent
b0b99058cc
commit
06993ee729
|
@ -107,6 +107,7 @@ romstage-$(CONFIG_ARM64_USE_ARCH_TIMER) += arch_timer.c
|
||||||
romstage-y += memset.S
|
romstage-y += memset.S
|
||||||
romstage-y += memcpy.S
|
romstage-y += memcpy.S
|
||||||
romstage-y += memmove.S
|
romstage-y += memmove.S
|
||||||
|
romstage-y += ramdetect.c
|
||||||
romstage-y += romstage.c
|
romstage-y += romstage.c
|
||||||
romstage-y += transition.c transition_asm.S
|
romstage-y += transition.c transition_asm.S
|
||||||
|
|
||||||
|
@ -131,6 +132,7 @@ ramstage-y += div0.c
|
||||||
ramstage-y += eabi_compat.c
|
ramstage-y += eabi_compat.c
|
||||||
ramstage-y += boot.c
|
ramstage-y += boot.c
|
||||||
ramstage-y += tables.c
|
ramstage-y += tables.c
|
||||||
|
ramstage-y += ramdetect.c
|
||||||
ramstage-$(CONFIG_ARM64_USE_ARCH_TIMER) += arch_timer.c
|
ramstage-$(CONFIG_ARM64_USE_ARCH_TIMER) += arch_timer.c
|
||||||
ramstage-y += memset.S
|
ramstage-y += memset.S
|
||||||
ramstage-y += memcpy.S
|
ramstage-y += memcpy.S
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include <device/mmio.h>
|
||||||
|
#include <ramdetect.h>
|
||||||
|
#include <arch/exception.h>
|
||||||
|
#include <arch/transition.h>
|
||||||
|
|
||||||
|
static enum {
|
||||||
|
ABORT_CHECKER_NOT_TRIGGERED,
|
||||||
|
ABORT_CHECKER_TRIGGERED,
|
||||||
|
} abort_state = ABORT_CHECKER_NOT_TRIGGERED;
|
||||||
|
|
||||||
|
static int abort_checker(struct exc_state *state, uint64_t vector_id)
|
||||||
|
{
|
||||||
|
if (raw_read_esr_el3() >> 26 != 0x25)
|
||||||
|
return EXC_RET_IGNORED; /* Not a data abort. */
|
||||||
|
|
||||||
|
abort_state = ABORT_CHECKER_TRIGGERED;
|
||||||
|
state->elx.elr += sizeof(uint32_t); /* Jump over faulting instruction. */
|
||||||
|
raw_write_elr_el3(state->elx.elr);
|
||||||
|
return EXC_RET_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct exception_handler sync_el0 = {.handler = &abort_checker};
|
||||||
|
|
||||||
|
int probe_mb(const uintptr_t dram_start, const uintptr_t size)
|
||||||
|
{
|
||||||
|
uintptr_t addr = dram_start + (size * MiB) - sizeof(uint32_t);
|
||||||
|
void *ptr = (void *)addr;
|
||||||
|
|
||||||
|
abort_state = ABORT_CHECKER_NOT_TRIGGERED;
|
||||||
|
exception_handler_register(EXC_VID_CUR_SP_EL0_SYNC, &sync_el0);
|
||||||
|
read32(ptr);
|
||||||
|
exception_handler_unregister(EXC_VID_CUR_SP_EL0_SYNC, &sync_el0);
|
||||||
|
return abort_state == ABORT_CHECKER_NOT_TRIGGERED;
|
||||||
|
}
|
|
@ -11,6 +11,12 @@
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used in probe_ramsize(). This is a weak function and it's overridden for
|
||||||
|
* ARMv8. Return 1 when DRAM exists at the address, otherwise return 0.
|
||||||
|
*/
|
||||||
|
int probe_mb(const uintptr_t dram_start, const uintptr_t size);
|
||||||
/*
|
/*
|
||||||
* Probe an area if it's read/writable.
|
* Probe an area if it's read/writable.
|
||||||
* Primary use case is the detection of DRAM amount on emulators.
|
* Primary use case is the detection of DRAM amount on emulators.
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#define OVERLAP(a, b, s, e) ((b) > (s) && (a) < (e))
|
#define OVERLAP(a, b, s, e) ((b) > (s) && (a) < (e))
|
||||||
|
|
||||||
static int probe_mb(const uintptr_t dram_start, const uintptr_t size)
|
int __weak probe_mb(const uintptr_t dram_start, const uintptr_t size)
|
||||||
{
|
{
|
||||||
uintptr_t addr = dram_start + (size * MiB) - sizeof(uint32_t);
|
uintptr_t addr = dram_start + (size * MiB) - sizeof(uint32_t);
|
||||||
static const uint32_t patterns[] = {
|
static const uint32_t patterns[] = {
|
||||||
|
|
Loading…
Reference in New Issue