Commit 490408fa authored by Volodymyr Babchuk's avatar Volodymyr Babchuk Committed by Anas Nashif
Browse files

aarch64: introduce explicit instructions to access MMIO



With classic volatile pointer access gcc something generates
access instructions with immediate offset value, like

str     w4, [x1], #4

Such instructions produce invalid syndrome in HSR register when are
trapped by hypervisor. This leads to inability to emulate device access
in hypervisor.

So we need to make sure that any access to device memory is done
with plain str/ldr instructions without offset.

Signed-off-by: default avatarVolodymyr Babchuk <volodymyr_babchuk@epam.com>
parent cd86ec26
Loading
Loading
Loading
Loading
+22 −6
Original line number Diff line number Diff line
@@ -23,9 +23,21 @@ extern "C" {

/* Memory mapped registers I/O functions */

/*
 * We need to use explicit assembler instruction there, because with classic
 * "volatile pointer" approach compiler might generate instruction with
 * immediate value like
 *
 * str     w4, [x1], #4
 *
 * Such instructions produce invalid syndrome in HSR register, so hypervisor
 * can't emulate MMIO  when it traps memory access.
 */
static ALWAYS_INLINE uint8_t sys_read8(mem_addr_t addr)
{
	uint8_t val = *(volatile uint8_t *)addr;
	uint8_t val;

	__asm__ volatile("ldrb %w0, [%1]" : "=r" (val) : "r" (addr));

	__DMB();
	return val;
@@ -34,12 +46,14 @@ static ALWAYS_INLINE uint8_t sys_read8(mem_addr_t addr)
static ALWAYS_INLINE void sys_write8(uint8_t data, mem_addr_t addr)
{
	__DMB();
	*(volatile uint8_t *)addr = data;
	__asm__ volatile("strb %w0, [%1]" : : "r" (data), "r" (addr));
}

static ALWAYS_INLINE uint16_t sys_read16(mem_addr_t addr)
{
	uint16_t val = *(volatile uint16_t *)addr;
	uint16_t val;

	__asm__ volatile("ldrh %w0, [%1]" : "=r" (val) : "r" (addr));

	__DMB();
	return val;
@@ -48,12 +62,14 @@ static ALWAYS_INLINE uint16_t sys_read16(mem_addr_t addr)
static ALWAYS_INLINE void sys_write16(uint16_t data, mem_addr_t addr)
{
	__DMB();
	*(volatile uint16_t *)addr = data;
	__asm__ volatile("strh %w0, [%1]" : : "r" (data), "r" (addr));
}

static ALWAYS_INLINE uint32_t sys_read32(mem_addr_t addr)
{
	uint32_t val = *(volatile uint32_t *)addr;
	uint32_t val;

	__asm__ volatile("ldr %w0, [%1]" : "=r" (val) : "r" (addr));

	__DMB();
	return val;
@@ -62,7 +78,7 @@ static ALWAYS_INLINE uint32_t sys_read32(mem_addr_t addr)
static ALWAYS_INLINE void sys_write32(uint32_t data, mem_addr_t addr)
{
	__DMB();
	*(volatile uint32_t *)addr = data;
	__asm__ volatile("str %w0, [%1]" : : "r" (data), "r" (addr));
}

#ifdef __cplusplus