blob: 2f6a1cd50c05a2c25243a8855059539049e85bb2 [file] [log] [blame]
Patrick Georgi0a3d4e02020-03-04 14:39:09 +01001/* SPDX-License-Identifier: GPL-2.0-or-later */
Asami Doi06993ee2019-08-07 13:40:53 +09002
3#include <types.h>
4#include <device/mmio.h>
5#include <ramdetect.h>
6#include <arch/exception.h>
7#include <arch/transition.h>
8
9static enum {
10 ABORT_CHECKER_NOT_TRIGGERED,
11 ABORT_CHECKER_TRIGGERED,
12} abort_state = ABORT_CHECKER_NOT_TRIGGERED;
13
14static int abort_checker(struct exc_state *state, uint64_t vector_id)
15{
16 if (raw_read_esr_el3() >> 26 != 0x25)
17 return EXC_RET_IGNORED; /* Not a data abort. */
18
19 abort_state = ABORT_CHECKER_TRIGGERED;
20 state->elx.elr += sizeof(uint32_t); /* Jump over faulting instruction. */
21 raw_write_elr_el3(state->elx.elr);
22 return EXC_RET_HANDLED;
23}
24
25static struct exception_handler sync_el0 = {.handler = &abort_checker};
26
27int probe_mb(const uintptr_t dram_start, const uintptr_t size)
28{
29 uintptr_t addr = dram_start + (size * MiB) - sizeof(uint32_t);
30 void *ptr = (void *)addr;
31
32 abort_state = ABORT_CHECKER_NOT_TRIGGERED;
33 exception_handler_register(EXC_VID_CUR_SP_EL0_SYNC, &sync_el0);
34 read32(ptr);
35 exception_handler_unregister(EXC_VID_CUR_SP_EL0_SYNC, &sync_el0);
36 return abort_state == ABORT_CHECKER_NOT_TRIGGERED;
37}