Skip to content

Commit 490408f

Browse files
lorcnashif
authored andcommitted
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: Volodymyr Babchuk <[email protected]>
1 parent cd86ec2 commit 490408f

File tree

1 file changed

+22
-6
lines changed

1 file changed

+22
-6
lines changed

include/arch/arm/aarch64/sys_io.h

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,21 @@ extern "C" {
2323

2424
/* Memory mapped registers I/O functions */
2525

26+
/*
27+
* We need to use explicit assembler instruction there, because with classic
28+
* "volatile pointer" approach compiler might generate instruction with
29+
* immediate value like
30+
*
31+
* str w4, [x1], #4
32+
*
33+
* Such instructions produce invalid syndrome in HSR register, so hypervisor
34+
* can't emulate MMIO when it traps memory access.
35+
*/
2636
static ALWAYS_INLINE uint8_t sys_read8(mem_addr_t addr)
2737
{
28-
uint8_t val = *(volatile uint8_t *)addr;
38+
uint8_t val;
39+
40+
__asm__ volatile("ldrb %w0, [%1]" : "=r" (val) : "r" (addr));
2941

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

4052
static ALWAYS_INLINE uint16_t sys_read16(mem_addr_t addr)
4153
{
42-
uint16_t val = *(volatile uint16_t *)addr;
54+
uint16_t val;
55+
56+
__asm__ volatile("ldrh %w0, [%1]" : "=r" (val) : "r" (addr));
4357

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

5468
static ALWAYS_INLINE uint32_t sys_read32(mem_addr_t addr)
5569
{
56-
uint32_t val = *(volatile uint32_t *)addr;
70+
uint32_t val;
71+
72+
__asm__ volatile("ldr %w0, [%1]" : "=r" (val) : "r" (addr));
5773

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

6884
#ifdef __cplusplus

0 commit comments

Comments
 (0)