2018-05-06 21:58:06 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0+
|
2014-06-09 18:12:59 +00:00
|
|
|
/*
|
2022-03-22 20:59:18 +00:00
|
|
|
* Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com>
|
2014-06-09 18:12:59 +00:00
|
|
|
* Copyright 2014 Broadcom Corporation
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <common.h>
|
|
|
|
|
2022-10-05 16:38:48 +00:00
|
|
|
/*
|
|
|
|
* Macro to force the compiler to *populate* memory (for an array or struct)
|
|
|
|
* before passing the pointer to an inline assembly call.
|
|
|
|
*/
|
|
|
|
#define USE_PTR(ptr) *(const char (*)[]) (ptr)
|
|
|
|
|
2022-10-05 16:38:47 +00:00
|
|
|
#if defined(CONFIG_ARM64)
|
|
|
|
#define SMH_TRAP "hlt #0xf000"
|
|
|
|
#elif defined(CONFIG_CPU_V7M)
|
|
|
|
#define SMH_TRAP "bkpt #0xAB"
|
|
|
|
#elif defined(CONFIG_SYS_THUMB_BUILD)
|
|
|
|
#define SMH_TRAP "svc #0xab"
|
|
|
|
#else
|
|
|
|
#define SMH_TRAP "svc #0x123456"
|
|
|
|
#endif
|
|
|
|
|
2014-06-09 18:12:59 +00:00
|
|
|
/*
|
|
|
|
* Call the handler
|
|
|
|
*/
|
2022-12-07 11:42:34 +00:00
|
|
|
long smh_trap(unsigned int sysnum, void *addr)
|
2014-06-09 18:12:59 +00:00
|
|
|
{
|
2014-12-15 10:05:56 +00:00
|
|
|
register long result asm("r0");
|
2022-10-05 16:38:49 +00:00
|
|
|
register void *_addr asm("r1") = addr;
|
2022-10-05 16:38:47 +00:00
|
|
|
|
2022-10-05 16:38:48 +00:00
|
|
|
/*
|
|
|
|
* We need a memory clobber (aka compiler barrier) for two reasons:
|
|
|
|
* - The compiler needs to populate any data structures pointed to
|
|
|
|
* by "addr" *before* the trap instruction is called.
|
|
|
|
* - At least the SYSREAD function puts the result into memory pointed
|
|
|
|
* to by "addr", so the compiler must not use a cached version of
|
|
|
|
* the previous content, after the call has finished.
|
|
|
|
*/
|
2022-10-05 16:38:47 +00:00
|
|
|
asm volatile (SMH_TRAP
|
|
|
|
: "=r" (result)
|
2022-10-05 16:38:49 +00:00
|
|
|
: "0"(sysnum), "r"(USE_PTR(_addr))
|
2022-10-05 16:38:47 +00:00
|
|
|
: "memory");
|
|
|
|
|
2014-06-09 18:12:59 +00:00
|
|
|
return result;
|
|
|
|
}
|