Skip to content

Commit

Permalink
aarch64: introduce explicit instructions to access MMIO
Browse files Browse the repository at this point in the history
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: Volodymyr Babchuk <[email protected]>
  • Loading branch information
lorc authored and nashif committed Jan 24, 2021
1 parent cd86ec2 commit 490408f
Showing 1 changed file with 22 additions and 6 deletions.
28 changes: 22 additions & 6 deletions include/arch/arm/aarch64/sys_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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
Expand Down

0 comments on commit 490408f

Please sign in to comment.