summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/arm64/Makefile.inc2
-rw-r--r--src/arch/arm64/ramdetect.c41
-rw-r--r--src/include/ramdetect.h6
-rw-r--r--src/lib/ramdetect.c2
4 files changed, 50 insertions, 1 deletions
diff --git a/src/arch/arm64/Makefile.inc b/src/arch/arm64/Makefile.inc
index 6bb7196805..89cc8780a6 100644
--- a/src/arch/arm64/Makefile.inc
+++ b/src/arch/arm64/Makefile.inc
@@ -107,6 +107,7 @@ romstage-$(CONFIG_ARM64_USE_ARCH_TIMER) += arch_timer.c
romstage-y += memset.S
romstage-y += memcpy.S
romstage-y += memmove.S
+romstage-y += ramdetect.c
romstage-y += romstage.c
romstage-y += transition.c transition_asm.S
@@ -131,6 +132,7 @@ ramstage-y += div0.c
ramstage-y += eabi_compat.c
ramstage-y += boot.c
ramstage-y += tables.c
+ramstage-y += ramdetect.c
ramstage-$(CONFIG_ARM64_USE_ARCH_TIMER) += arch_timer.c
ramstage-y += memset.S
ramstage-y += memcpy.S
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;
+}
diff --git a/src/include/ramdetect.h b/src/include/ramdetect.h
index b63cdf14cf..e2a7eced67 100644
--- a/src/include/ramdetect.h
+++ b/src/include/ramdetect.h
@@ -11,6 +11,12 @@
* 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.
* Primary use case is the detection of DRAM amount on emulators.
diff --git a/src/lib/ramdetect.c b/src/lib/ramdetect.c
index 5416a580dd..2c83092ebc 100644
--- a/src/lib/ramdetect.c
+++ b/src/lib/ramdetect.c
@@ -19,7 +19,7 @@
#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);
static const uint32_t patterns[] = {