blob: 048d396ffeedb1727034bf93d0c4484b3b93887f [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <arch/exception.h>
#include <types.h>
#include <console/console.h>
#include <device/mmio.h>
#include <ramdetect.h>
#include <arch/smp/spinlock.h>
#include <vm.h>
static enum {
ABORT_CHECKER_NOT_TRIGGERED,
ABORT_CHECKER_TRIGGERED,
} abort_state = ABORT_CHECKER_NOT_TRIGGERED;
extern void (*trap_handler)(struct trapframe *tf);
static int get_instruction_len(uintptr_t addr)
{
uint16_t ins = read16p(addr);
/*
* 16-bit or 32-bit instructions supported
*/
if ((ins & 0x3) != 3) {
return 2;
} else if ((ins & 0x1f) != 0x1f) {
return 4;
}
die("Not a 16bit or 32bit instruction 0x%x\n", ins);
}
static void ramcheck_trap_handler(struct trapframe *tf)
{
abort_state = ABORT_CHECKER_TRIGGERED;
/*
* skip read instruction.
*/
int insn_size = get_instruction_len(tf->epc);
write_csr(mepc, read_csr(mepc) + insn_size);
}
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;
trap_handler = ramcheck_trap_handler;
barrier();
read32(ptr);
trap_handler = default_trap_handler;
barrier();
printk(BIOS_DEBUG, "%lx is %s DRAM\n", dram_start + size * MiB,
abort_state == ABORT_CHECKER_NOT_TRIGGERED ? "" : "not");
return abort_state == ABORT_CHECKER_NOT_TRIGGERED;
}