summaryrefslogtreecommitdiff
path: root/src/arch/arm64/ramdetect.c
diff options
context:
space:
mode:
authorAsami Doi <d0iasm.pub@gmail.com>2019-08-07 13:40:53 +0900
committerPatrick Georgi <pgeorgi@google.com>2019-08-26 07:14:03 +0000
commit06993ee7295c81f71462616277624fbf8ebc8ec9 (patch)
tree569e82efdd9292de5d318a4402d368359fbdd97f /src/arch/arm64/ramdetect.c
parentb0b99058ccf975f5612cdf4aa15607dee05822b1 (diff)
downloadcoreboot-06993ee7295c81f71462616277624fbf8ebc8ec9.tar.xz
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>
Diffstat (limited to 'src/arch/arm64/ramdetect.c')
-rw-r--r--src/arch/arm64/ramdetect.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/arch/arm64/ramdetect.c b/src/arch/arm64/ramdetect.c
new file mode 100644
index 0000000000..bc034c311b
--- /dev/null
+++ b/src/arch/arm64/ramdetect.c
@@ -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;
+}