Atomic operation in aarch64
作者:schspa 发布于:2021-11-15 19:42 分类:ARMv8A Arch
Atomic operation in aarch64
Table of Contents
在Linux内核中看到下面这句话:
At least on ARM, pgprot_noncached causes the
memory to be mapped strongly ordered, and atomic operations on strongly ordered
memory are implementation defined, and won't work on many ARMs such as omaps.
所以, 为什么对用户non-cached的内存,部分平台不支持原子操作?
先看看ARM64平台原子操作实现原理
先看看Linux内核中的实现。
linux
-
atomic_read & atomic_set
#define atomic_read(v) READ_ONCE((v)->counter) #define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i))
对于读和写,在ARM平台上使用正常使用的读写操作即可。
-
atomic_add & atomic_dec
对于加减的原子操作,由于需要执行读,改,写三步,需要使用特殊的指令才可以实现。static inline void atomic_add(int i, atomic_t *v) { kasan_check_write(v, sizeof(*v)); arch_atomic_add(i, v); } #define atomic_add atomic_add ATOMIC_OP(atomic_add) #define ATOMIC_OP(op) \ static inline void arch_##op(int i, atomic_t *v) \ { \ __lse_ll_sc_body(op, i, v); \ } #define __lse_ll_sc_body(op, ...) \ ({ \ system_uses_lse_atomics() ? \ __lse_##op(__VA_ARGS__) : \ __ll_sc_##op(__VA_ARGS__); \ })
-
Linux atomic指令的两种实现
-
LSE
使用ARMv8.1中新增加的原子操作指令
#define ATOMIC_OP(op, asm_op) \ static inline void __lse_atomic_##op(int i, atomic_t *v) \ { \ asm volatile( \ " " #asm_op " %w[i], %[v]\n" \ : [i] "+r" (i), [v] "+Q" (v->counter) \ : "r" (v)); \ } ATOMIC_OP(andnot, stclr) ATOMIC_OP(or, stset) ATOMIC_OP(xor, steor) ATOMIC_OP(add, stadd) static inline void __lse_atomic64_sub(s64 i, atomic64_t *v) { asm volatile( " neg %[i], %[i]\n" " stadd %[i], %[v]" : [i] "+&r" (i), [v] "+Q" (v->counter) : "r" (v)); }
从上可以看到,系统使用了单条指令stadd就完成了原子加操作,这些指令是ARMv8.1 添加的指令,并不是所有的AARCH64都支持这种指令。
-
LL_SC]] Load-link/store-condiitional
#define ATOMIC_OP(op, asm_op, constraint) \ static inline void \ __ll_sc_atomic_##op(int i, atomic_t *v) \ { \ unsigned long tmp; \ int result; \ \ asm volatile("// atomic_" #op "\n" \ __LL_SC_FALLBACK( \ " prfm pstl1strm, %2\n" \ "1: ldxr %w0, %2\n" \ " " #asm_op " %w0, %w0, %w3\n" \ " stxr %w1, %w0, %2\n" \ " cbnz %w1, 1b\n") \ : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \ : __stringify(constraint) "r" (i)); \ } #define ATOMIC_OPS(...) \ ATOMIC_OP(__VA_ARGS__) \ ATOMIC_OP_RETURN( , dmb ish, , l, "memory", __VA_ARGS__)\ ATOMIC_OP_RETURN(_relaxed, , , , , __VA_ARGS__)\ ATOMIC_OP_RETURN(_acquire, , a, , "memory", __VA_ARGS__)\ ATOMIC_OP_RETURN(_release, , , l, "memory", __VA_ARGS__)\ ATOMIC_FETCH_OP ( , dmb ish, , l, "memory", __VA_ARGS__)\ ATOMIC_FETCH_OP (_relaxed, , , , , __VA_ARGS__)\ ATOMIC_FETCH_OP (_acquire, , a, , "memory", __VA_ARGS__)\ ATOMIC_FETCH_OP (_release, , , l, "memory", __VA_ARGS__) ATOMIC_OPS(add, add, I) ATOMIC_OPS(sub, sub, J)
从这里的实现可一看到,系统同过ldxr和stxr指令对配和算数运算指令一同完成原子操作。
-
LSE
ARM64平台原子操作指令
A64: ldx, ldax,stx,stlx
A32/T32: ldrex, strex, ldaex, stlex
-
从上面Linux的实现中就可以得知,在ARMv8中有对于原子操作有两种不同得实现,一种是LLSC形式的原子操作,另一种是LSE
ARMV8a中的设置
ARMv8a手册
ARMV8a中对于原子操作的描述
以上地方仅仅描述了原子操作指令使用时需要注意的地方,并无法找到我们的答案,下面去看看CPU手册吧。
Crotex A55手册
-
从上面可以看到,在ARMv8中, 对于cacheable memory, 原子操作都是没有问题的, 因为系统可以通过cache来完成原子操作.
-
对于devices或者non-cacheable内存, 原子操作依赖于互联网络的支持. 在arm上就是各种AMBA总线,如果互联网络不支持的话,就会引发同步或者异步的异常.
从以上信息可知,对于部分non-cacheable内存,在ARM平台上,不支持原子操作的原因是因为硬件的互连网络不支持原子操作。
CPUECTLR.ATOM
通过CPU的这个寄存器可以控制atomic访问的时候具体是使用near/far,默认的配置中,根据不同的情况,硬件一般会自动根据cache hit的情况自动切换,这之中并不需要软件的参与。
总线的设置
关于AMBA总线:
参考 `代码改变世界ctw` 的文章,可以对AMBA总线有个大概的了解
https://blog.csdn.net/weixin_42135087/article/details/111557929
在总线上,为了exclude access,硬件上有一套具体的协议来支持,并且有相应信号。
AMBA AXI: Atomic transaction support
从上面arm官方的示意图中,AMBA中 exclusive access monitor 会存储传输的id和地址,由此来监控原子传输。
对于内核注释中提到的omap平台,硬件上使用了哪种互连网络,最终导致了系统无法在non-cached内存中使用原子操作?
由于没有具体的OMAP平台资料,由上述的信息可以得知,这个是由于SOC内部的总线,或者最后端内存的硬件实现而造成的。不光是OMAP,很多ARM平台的SOC都有相同的问题. 但是一般cache都是打开的状态,所以软件一般不需要关心这个问题。
DONE 对于上述平台,如果软件上去使用原子操作指令访问non-cached内存,会有什么后果?
出现问题之后cpu会进入同步异常
Data abort with DFSC:
0b110101 implementation defined fault (Unsupported Exclusive or Atomic access).
esr_el3 = 0x0000000096000035

评论:
功能
最新评论
文章分类
随机文章
文章存档
- 2024年2月(1)
- 2023年5月(1)
- 2022年10月(1)
- 2022年8月(1)
- 2022年6月(1)
- 2022年5月(1)
- 2022年4月(2)
- 2022年2月(2)
- 2021年12月(1)
- 2021年11月(5)
- 2021年7月(1)
- 2021年6月(1)
- 2021年5月(3)
- 2020年3月(3)
- 2020年2月(2)
- 2020年1月(3)
- 2019年12月(3)
- 2019年5月(4)
- 2019年3月(1)
- 2019年1月(3)
- 2018年12月(2)
- 2018年11月(1)
- 2018年10月(2)
- 2018年8月(1)
- 2018年6月(1)
- 2018年5月(1)
- 2018年4月(7)
- 2018年2月(4)
- 2018年1月(5)
- 2017年12月(2)
- 2017年11月(2)
- 2017年10月(1)
- 2017年9月(5)
- 2017年8月(4)
- 2017年7月(4)
- 2017年6月(3)
- 2017年5月(3)
- 2017年4月(1)
- 2017年3月(8)
- 2017年2月(6)
- 2017年1月(5)
- 2016年12月(6)
- 2016年11月(11)
- 2016年10月(9)
- 2016年9月(6)
- 2016年8月(9)
- 2016年7月(5)
- 2016年6月(8)
- 2016年5月(8)
- 2016年4月(7)
- 2016年3月(5)
- 2016年2月(5)
- 2016年1月(6)
- 2015年12月(6)
- 2015年11月(9)
- 2015年10月(9)
- 2015年9月(4)
- 2015年8月(3)
- 2015年7月(7)
- 2015年6月(3)
- 2015年5月(6)
- 2015年4月(9)
- 2015年3月(9)
- 2015年2月(6)
- 2015年1月(6)
- 2014年12月(17)
- 2014年11月(8)
- 2014年10月(9)
- 2014年9月(7)
- 2014年8月(12)
- 2014年7月(6)
- 2014年6月(6)
- 2014年5月(9)
- 2014年4月(9)
- 2014年3月(7)
- 2014年2月(3)
- 2014年1月(4)
2021-11-18 19:56