diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2019-04-18 16:37:00 -0700 |
---|---|---|
committer | Max Filippov <jcmvbkbc@gmail.com> | 2019-05-15 10:31:52 -0700 |
commit | b345e140534ea17814b02bdf8798f18db6295304 (patch) | |
tree | f9320a22da357d31ad10e17a340300b02a389b98 /target/xtensa/op_helper.c | |
parent | 98736654f3dfbf984d9e26c9be0480b0560c1067 (diff) |
target/xtensa: implement exclusive access option
The Exclusive Instructions provide a general-purpose mechanism for
atomic updates of memory-based synchronization variables that can be
used for exclusion algorithms.
Use cmpxchg-based implementation that is sufficient for the typical use
of exclusive access in atomic operations.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Diffstat (limited to 'target/xtensa/op_helper.c')
-rw-r--r-- | target/xtensa/op_helper.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/target/xtensa/op_helper.c b/target/xtensa/op_helper.c index 04971b044f..09f4962d00 100644 --- a/target/xtensa/op_helper.c +++ b/target/xtensa/op_helper.c @@ -130,6 +130,48 @@ void HELPER(check_atomctl)(CPUXtensaState *env, uint32_t pc, uint32_t vaddr) } } +void HELPER(check_exclusive)(CPUXtensaState *env, uint32_t pc, uint32_t vaddr, + uint32_t is_write) +{ + uint32_t paddr, page_size, access; + uint32_t atomctl = env->sregs[ATOMCTL]; + int rc = xtensa_get_physical_addr(env, true, vaddr, is_write, + xtensa_get_cring(env), &paddr, + &page_size, &access); + + if (rc) { + HELPER(exception_cause_vaddr)(env, pc, rc, vaddr); + } + + /* When data cache is not configured use ATOMCTL bypass field. */ + if (!xtensa_option_enabled(env->config, XTENSA_OPTION_DCACHE)) { + access = PAGE_CACHE_BYPASS; + } + + switch (access & PAGE_CACHE_MASK) { + case PAGE_CACHE_WB: + atomctl >>= 2; + /* fall through */ + case PAGE_CACHE_WT: + atomctl >>= 2; + /* fall through */ + case PAGE_CACHE_BYPASS: + if ((atomctl & 0x3) == 0) { + HELPER(exception_cause_vaddr)(env, pc, + EXCLUSIVE_ERROR_CAUSE, vaddr); + } + break; + + case PAGE_CACHE_ISOLATE: + HELPER(exception_cause_vaddr)(env, pc, + LOAD_STORE_ERROR_CAUSE, vaddr); + break; + + default: + break; + } +} + void HELPER(wsr_memctl)(CPUXtensaState *env, uint32_t v) { if (xtensa_option_enabled(env->config, XTENSA_OPTION_ICACHE)) { |