User-mode memory helper fixes
-----BEGIN PGP SIGNATURE----- iQEcBAABAgAGBQJaDDPhAAoJEGTfOOivfiFfyzEIAKr6TzG+r6R1d3hddvnS7o0c Iuut3skRc/OB4zpI0WQu3b2JQ2TWCZwT+fC7jZY+x0PVQPmwzzjvysWMprf3UR4c Nm6yU0qaFSrVy1QZVtATnA/0vrkssHb0A0Y2Ukr35j7XW8kTwe6DMB2lSkGu5/sc GLJrtITQm7uVbZljUNPEuzEUe4QSD0AGzNmtovAxWpc8qXhGDfVvRuH+RXxmlXyA WB8ldCNLyzY3W5h55WRpmN+x+76eVVPjt9UtV1dIbNaw68uQipCoHkNrSYd21Otx izrZblXUxwlQYrxPpp+s7l9yNaFymNinvCHJQfrOsbS7Bu0x4KLvaTtNOSbK9NE= =gHuZ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20171115' into staging User-mode memory helper fixes # gpg: Signature made Wed 15 Nov 2017 12:32:33 GMT # gpg: using RSA key 0x64DF38E8AF7E215F # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" # Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F * remotes/rth/tags/pull-tcg-20171115: target/arm: Fix GETPC usage in do_paired_cmpxchg64_l/be target/arm: Use helper_retaddr in stxp helpers tcg: Record code_gen_buffer address for user-only memory helpers Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
6a7cb8c3d6
|
@ -62,7 +62,9 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
|
||||||
ABI_TYPE cmpv, ABI_TYPE newv EXTRA_ARGS)
|
ABI_TYPE cmpv, ABI_TYPE newv EXTRA_ARGS)
|
||||||
{
|
{
|
||||||
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
|
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
|
||||||
return atomic_cmpxchg__nocheck(haddr, cmpv, newv);
|
DATA_TYPE ret = atomic_cmpxchg__nocheck(haddr, cmpv, newv);
|
||||||
|
ATOMIC_MMU_CLEANUP;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DATA_SIZE >= 16
|
#if DATA_SIZE >= 16
|
||||||
|
@ -70,6 +72,7 @@ ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr EXTRA_ARGS)
|
||||||
{
|
{
|
||||||
DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP;
|
DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP;
|
||||||
__atomic_load(haddr, &val, __ATOMIC_RELAXED);
|
__atomic_load(haddr, &val, __ATOMIC_RELAXED);
|
||||||
|
ATOMIC_MMU_CLEANUP;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,13 +81,16 @@ void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr,
|
||||||
{
|
{
|
||||||
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
|
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
|
||||||
__atomic_store(haddr, &val, __ATOMIC_RELAXED);
|
__atomic_store(haddr, &val, __ATOMIC_RELAXED);
|
||||||
|
ATOMIC_MMU_CLEANUP;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
|
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
|
||||||
ABI_TYPE val EXTRA_ARGS)
|
ABI_TYPE val EXTRA_ARGS)
|
||||||
{
|
{
|
||||||
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
|
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
|
||||||
return atomic_xchg__nocheck(haddr, val);
|
DATA_TYPE ret = atomic_xchg__nocheck(haddr, val);
|
||||||
|
ATOMIC_MMU_CLEANUP;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GEN_ATOMIC_HELPER(X) \
|
#define GEN_ATOMIC_HELPER(X) \
|
||||||
|
@ -92,8 +98,10 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
||||||
ABI_TYPE val EXTRA_ARGS) \
|
ABI_TYPE val EXTRA_ARGS) \
|
||||||
{ \
|
{ \
|
||||||
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \
|
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \
|
||||||
return atomic_##X(haddr, val); \
|
DATA_TYPE ret = atomic_##X(haddr, val); \
|
||||||
} \
|
ATOMIC_MMU_CLEANUP; \
|
||||||
|
return ret; \
|
||||||
|
}
|
||||||
|
|
||||||
GEN_ATOMIC_HELPER(fetch_add)
|
GEN_ATOMIC_HELPER(fetch_add)
|
||||||
GEN_ATOMIC_HELPER(fetch_and)
|
GEN_ATOMIC_HELPER(fetch_and)
|
||||||
|
@ -123,7 +131,9 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
|
||||||
ABI_TYPE cmpv, ABI_TYPE newv EXTRA_ARGS)
|
ABI_TYPE cmpv, ABI_TYPE newv EXTRA_ARGS)
|
||||||
{
|
{
|
||||||
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
|
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
|
||||||
return BSWAP(atomic_cmpxchg__nocheck(haddr, BSWAP(cmpv), BSWAP(newv)));
|
DATA_TYPE ret = atomic_cmpxchg__nocheck(haddr, BSWAP(cmpv), BSWAP(newv));
|
||||||
|
ATOMIC_MMU_CLEANUP;
|
||||||
|
return BSWAP(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DATA_SIZE >= 16
|
#if DATA_SIZE >= 16
|
||||||
|
@ -131,6 +141,7 @@ ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr EXTRA_ARGS)
|
||||||
{
|
{
|
||||||
DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP;
|
DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP;
|
||||||
__atomic_load(haddr, &val, __ATOMIC_RELAXED);
|
__atomic_load(haddr, &val, __ATOMIC_RELAXED);
|
||||||
|
ATOMIC_MMU_CLEANUP;
|
||||||
return BSWAP(val);
|
return BSWAP(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,13 +151,16 @@ void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr,
|
||||||
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
|
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
|
||||||
val = BSWAP(val);
|
val = BSWAP(val);
|
||||||
__atomic_store(haddr, &val, __ATOMIC_RELAXED);
|
__atomic_store(haddr, &val, __ATOMIC_RELAXED);
|
||||||
|
ATOMIC_MMU_CLEANUP;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
|
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
|
||||||
ABI_TYPE val EXTRA_ARGS)
|
ABI_TYPE val EXTRA_ARGS)
|
||||||
{
|
{
|
||||||
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
|
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
|
||||||
return BSWAP(atomic_xchg__nocheck(haddr, BSWAP(val)));
|
ABI_TYPE ret = atomic_xchg__nocheck(haddr, BSWAP(val));
|
||||||
|
ATOMIC_MMU_CLEANUP;
|
||||||
|
return BSWAP(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GEN_ATOMIC_HELPER(X) \
|
#define GEN_ATOMIC_HELPER(X) \
|
||||||
|
@ -154,7 +168,9 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
|
||||||
ABI_TYPE val EXTRA_ARGS) \
|
ABI_TYPE val EXTRA_ARGS) \
|
||||||
{ \
|
{ \
|
||||||
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \
|
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP; \
|
||||||
return BSWAP(atomic_##X(haddr, BSWAP(val))); \
|
DATA_TYPE ret = atomic_##X(haddr, BSWAP(val)); \
|
||||||
|
ATOMIC_MMU_CLEANUP; \
|
||||||
|
return BSWAP(ret); \
|
||||||
}
|
}
|
||||||
|
|
||||||
GEN_ATOMIC_HELPER(fetch_and)
|
GEN_ATOMIC_HELPER(fetch_and)
|
||||||
|
@ -180,6 +196,7 @@ ABI_TYPE ATOMIC_NAME(fetch_add)(CPUArchState *env, target_ulong addr,
|
||||||
sto = BSWAP(ret + val);
|
sto = BSWAP(ret + val);
|
||||||
ldn = atomic_cmpxchg__nocheck(haddr, ldo, sto);
|
ldn = atomic_cmpxchg__nocheck(haddr, ldo, sto);
|
||||||
if (ldn == ldo) {
|
if (ldn == ldo) {
|
||||||
|
ATOMIC_MMU_CLEANUP;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
ldo = ldn;
|
ldo = ldn;
|
||||||
|
@ -198,6 +215,7 @@ ABI_TYPE ATOMIC_NAME(add_fetch)(CPUArchState *env, target_ulong addr,
|
||||||
sto = BSWAP(ret);
|
sto = BSWAP(ret);
|
||||||
ldn = atomic_cmpxchg__nocheck(haddr, ldo, sto);
|
ldn = atomic_cmpxchg__nocheck(haddr, ldo, sto);
|
||||||
if (ldn == ldo) {
|
if (ldn == ldo) {
|
||||||
|
ATOMIC_MMU_CLEANUP;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
ldo = ldn;
|
ldo = ldn;
|
||||||
|
|
|
@ -1041,6 +1041,7 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
|
||||||
#define ATOMIC_NAME(X) \
|
#define ATOMIC_NAME(X) \
|
||||||
HELPER(glue(glue(glue(atomic_ ## X, SUFFIX), END), _mmu))
|
HELPER(glue(glue(glue(atomic_ ## X, SUFFIX), END), _mmu))
|
||||||
#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, oi, retaddr)
|
#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, oi, retaddr)
|
||||||
|
#define ATOMIC_MMU_CLEANUP do { } while (0)
|
||||||
|
|
||||||
#define DATA_SIZE 1
|
#define DATA_SIZE 1
|
||||||
#include "atomic_template.h"
|
#include "atomic_template.h"
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
#include <sys/ucontext.h>
|
#include <sys/ucontext.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
__thread uintptr_t helper_retaddr;
|
||||||
|
|
||||||
//#define DEBUG_SIGNAL
|
//#define DEBUG_SIGNAL
|
||||||
|
|
||||||
/* exit the current TB from a signal handler. The host registers are
|
/* exit the current TB from a signal handler. The host registers are
|
||||||
|
@ -62,6 +64,27 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
|
||||||
CPUClass *cc;
|
CPUClass *cc;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/* We must handle PC addresses from two different sources:
|
||||||
|
* a call return address and a signal frame address.
|
||||||
|
*
|
||||||
|
* Within cpu_restore_state_from_tb we assume the former and adjust
|
||||||
|
* the address by -GETPC_ADJ so that the address is within the call
|
||||||
|
* insn so that addr does not accidentally match the beginning of the
|
||||||
|
* next guest insn.
|
||||||
|
*
|
||||||
|
* However, when the PC comes from the signal frame, it points to
|
||||||
|
* the actual faulting host insn and not a call insn. Subtracting
|
||||||
|
* GETPC_ADJ in that case may accidentally match the previous guest insn.
|
||||||
|
*
|
||||||
|
* So for the later case, adjust forward to compensate for what
|
||||||
|
* will be done later by cpu_restore_state_from_tb.
|
||||||
|
*/
|
||||||
|
if (helper_retaddr) {
|
||||||
|
pc = helper_retaddr;
|
||||||
|
} else {
|
||||||
|
pc += GETPC_ADJ;
|
||||||
|
}
|
||||||
|
|
||||||
/* For synchronous signals we expect to be coming from the vCPU
|
/* For synchronous signals we expect to be coming from the vCPU
|
||||||
* thread (so current_cpu should be valid) and either from running
|
* thread (so current_cpu should be valid) and either from running
|
||||||
* code or during translation which can fault as we cross pages.
|
* code or during translation which can fault as we cross pages.
|
||||||
|
@ -84,21 +107,24 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
|
||||||
switch (page_unprotect(h2g(address), pc)) {
|
switch (page_unprotect(h2g(address), pc)) {
|
||||||
case 0:
|
case 0:
|
||||||
/* Fault not caused by a page marked unwritable to protect
|
/* Fault not caused by a page marked unwritable to protect
|
||||||
* cached translations, must be the guest binary's problem
|
* cached translations, must be the guest binary's problem.
|
||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
/* Fault caused by protection of cached translation; TBs
|
/* Fault caused by protection of cached translation; TBs
|
||||||
* invalidated, so resume execution
|
* invalidated, so resume execution. Retain helper_retaddr
|
||||||
|
* for a possible second fault.
|
||||||
*/
|
*/
|
||||||
return 1;
|
return 1;
|
||||||
case 2:
|
case 2:
|
||||||
/* Fault caused by protection of cached translation, and the
|
/* Fault caused by protection of cached translation, and the
|
||||||
* currently executing TB was modified and must be exited
|
* currently executing TB was modified and must be exited
|
||||||
* immediately.
|
* immediately. Clear helper_retaddr for next execution.
|
||||||
*/
|
*/
|
||||||
|
helper_retaddr = 0;
|
||||||
cpu_exit_tb_from_sighandler(cpu, old_set);
|
cpu_exit_tb_from_sighandler(cpu, old_set);
|
||||||
g_assert_not_reached();
|
/* NORETURN */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
@ -112,17 +138,25 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
|
||||||
/* see if it is an MMU fault */
|
/* see if it is an MMU fault */
|
||||||
g_assert(cc->handle_mmu_fault);
|
g_assert(cc->handle_mmu_fault);
|
||||||
ret = cc->handle_mmu_fault(cpu, address, is_write, MMU_USER_IDX);
|
ret = cc->handle_mmu_fault(cpu, address, is_write, MMU_USER_IDX);
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
/* The MMU fault was handled without causing real CPU fault.
|
||||||
|
* Retain helper_retaddr for a possible second fault.
|
||||||
|
*/
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All other paths lead to cpu_exit; clear helper_retaddr
|
||||||
|
* for next execution.
|
||||||
|
*/
|
||||||
|
helper_retaddr = 0;
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return 0; /* not an MMU fault */
|
return 0; /* not an MMU fault */
|
||||||
}
|
}
|
||||||
if (ret == 0) {
|
|
||||||
return 1; /* the MMU fault was handled without causing real CPU fault */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now we have a real cpu fault. Since this is the exact location of
|
/* Now we have a real cpu fault. */
|
||||||
* the exception, we must undo the adjustment done by cpu_restore_state
|
cpu_restore_state(cpu, pc);
|
||||||
* for handling call return addresses. */
|
|
||||||
cpu_restore_state(cpu, pc + GETPC_ADJ);
|
|
||||||
|
|
||||||
sigprocmask(SIG_SETMASK, old_set, NULL);
|
sigprocmask(SIG_SETMASK, old_set, NULL);
|
||||||
cpu_loop_exit(cpu);
|
cpu_loop_exit(cpu);
|
||||||
|
@ -585,11 +619,13 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
|
||||||
if (unlikely(addr & (size - 1))) {
|
if (unlikely(addr & (size - 1))) {
|
||||||
cpu_loop_exit_atomic(ENV_GET_CPU(env), retaddr);
|
cpu_loop_exit_atomic(ENV_GET_CPU(env), retaddr);
|
||||||
}
|
}
|
||||||
|
helper_retaddr = retaddr;
|
||||||
return g2h(addr);
|
return g2h(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Macro to call the above, with local variables from the use context. */
|
/* Macro to call the above, with local variables from the use context. */
|
||||||
#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, DATA_SIZE, GETPC())
|
#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, DATA_SIZE, GETPC())
|
||||||
|
#define ATOMIC_MMU_CLEANUP do { helper_retaddr = 0; } while (0)
|
||||||
|
|
||||||
#define ATOMIC_NAME(X) HELPER(glue(glue(atomic_ ## X, SUFFIX), END))
|
#define ATOMIC_NAME(X) HELPER(glue(glue(atomic_ ## X, SUFFIX), END))
|
||||||
#define EXTRA_ARGS
|
#define EXTRA_ARGS
|
||||||
|
|
|
@ -76,6 +76,8 @@
|
||||||
|
|
||||||
#if defined(CONFIG_USER_ONLY)
|
#if defined(CONFIG_USER_ONLY)
|
||||||
|
|
||||||
|
extern __thread uintptr_t helper_retaddr;
|
||||||
|
|
||||||
/* In user-only mode we provide only the _code and _data accessors. */
|
/* In user-only mode we provide only the _code and _data accessors. */
|
||||||
|
|
||||||
#define MEMSUFFIX _data
|
#define MEMSUFFIX _data
|
||||||
|
|
|
@ -73,7 +73,11 @@ glue(glue(glue(cpu_ld, USUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
|
||||||
target_ulong ptr,
|
target_ulong ptr,
|
||||||
uintptr_t retaddr)
|
uintptr_t retaddr)
|
||||||
{
|
{
|
||||||
return glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(env, ptr);
|
RES_TYPE ret;
|
||||||
|
helper_retaddr = retaddr;
|
||||||
|
ret = glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(env, ptr);
|
||||||
|
helper_retaddr = 0;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DATA_SIZE <= 2
|
#if DATA_SIZE <= 2
|
||||||
|
@ -93,7 +97,11 @@ glue(glue(glue(cpu_lds, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
|
||||||
target_ulong ptr,
|
target_ulong ptr,
|
||||||
uintptr_t retaddr)
|
uintptr_t retaddr)
|
||||||
{
|
{
|
||||||
return glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(env, ptr);
|
int ret;
|
||||||
|
helper_retaddr = retaddr;
|
||||||
|
ret = glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(env, ptr);
|
||||||
|
helper_retaddr = 0;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -116,7 +124,9 @@ glue(glue(glue(cpu_st, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
|
||||||
RES_TYPE v,
|
RES_TYPE v,
|
||||||
uintptr_t retaddr)
|
uintptr_t retaddr)
|
||||||
{
|
{
|
||||||
|
helper_retaddr = retaddr;
|
||||||
glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(env, ptr, v);
|
glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(env, ptr, v);
|
||||||
|
helper_retaddr = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -432,9 +432,8 @@ uint64_t HELPER(crc32c_64)(uint64_t acc, uint64_t val, uint32_t bytes)
|
||||||
/* Returns 0 on success; 1 otherwise. */
|
/* Returns 0 on success; 1 otherwise. */
|
||||||
static uint64_t do_paired_cmpxchg64_le(CPUARMState *env, uint64_t addr,
|
static uint64_t do_paired_cmpxchg64_le(CPUARMState *env, uint64_t addr,
|
||||||
uint64_t new_lo, uint64_t new_hi,
|
uint64_t new_lo, uint64_t new_hi,
|
||||||
bool parallel)
|
bool parallel, uintptr_t ra)
|
||||||
{
|
{
|
||||||
uintptr_t ra = GETPC();
|
|
||||||
Int128 oldv, cmpv, newv;
|
Int128 oldv, cmpv, newv;
|
||||||
bool success;
|
bool success;
|
||||||
|
|
||||||
|
@ -456,6 +455,8 @@ static uint64_t do_paired_cmpxchg64_le(CPUARMState *env, uint64_t addr,
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
/* ??? Enforce alignment. */
|
/* ??? Enforce alignment. */
|
||||||
uint64_t *haddr = g2h(addr);
|
uint64_t *haddr = g2h(addr);
|
||||||
|
|
||||||
|
helper_retaddr = ra;
|
||||||
o0 = ldq_le_p(haddr + 0);
|
o0 = ldq_le_p(haddr + 0);
|
||||||
o1 = ldq_le_p(haddr + 1);
|
o1 = ldq_le_p(haddr + 1);
|
||||||
oldv = int128_make128(o0, o1);
|
oldv = int128_make128(o0, o1);
|
||||||
|
@ -465,6 +466,7 @@ static uint64_t do_paired_cmpxchg64_le(CPUARMState *env, uint64_t addr,
|
||||||
stq_le_p(haddr + 0, int128_getlo(newv));
|
stq_le_p(haddr + 0, int128_getlo(newv));
|
||||||
stq_le_p(haddr + 1, int128_gethi(newv));
|
stq_le_p(haddr + 1, int128_gethi(newv));
|
||||||
}
|
}
|
||||||
|
helper_retaddr = 0;
|
||||||
#else
|
#else
|
||||||
int mem_idx = cpu_mmu_index(env, false);
|
int mem_idx = cpu_mmu_index(env, false);
|
||||||
TCGMemOpIdx oi0 = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
|
TCGMemOpIdx oi0 = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
|
||||||
|
@ -488,20 +490,19 @@ static uint64_t do_paired_cmpxchg64_le(CPUARMState *env, uint64_t addr,
|
||||||
uint64_t HELPER(paired_cmpxchg64_le)(CPUARMState *env, uint64_t addr,
|
uint64_t HELPER(paired_cmpxchg64_le)(CPUARMState *env, uint64_t addr,
|
||||||
uint64_t new_lo, uint64_t new_hi)
|
uint64_t new_lo, uint64_t new_hi)
|
||||||
{
|
{
|
||||||
return do_paired_cmpxchg64_le(env, addr, new_lo, new_hi, false);
|
return do_paired_cmpxchg64_le(env, addr, new_lo, new_hi, false, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t HELPER(paired_cmpxchg64_le_parallel)(CPUARMState *env, uint64_t addr,
|
uint64_t HELPER(paired_cmpxchg64_le_parallel)(CPUARMState *env, uint64_t addr,
|
||||||
uint64_t new_lo, uint64_t new_hi)
|
uint64_t new_lo, uint64_t new_hi)
|
||||||
{
|
{
|
||||||
return do_paired_cmpxchg64_le(env, addr, new_lo, new_hi, true);
|
return do_paired_cmpxchg64_le(env, addr, new_lo, new_hi, true, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t do_paired_cmpxchg64_be(CPUARMState *env, uint64_t addr,
|
static uint64_t do_paired_cmpxchg64_be(CPUARMState *env, uint64_t addr,
|
||||||
uint64_t new_lo, uint64_t new_hi,
|
uint64_t new_lo, uint64_t new_hi,
|
||||||
bool parallel)
|
bool parallel, uintptr_t ra)
|
||||||
{
|
{
|
||||||
uintptr_t ra = GETPC();
|
|
||||||
Int128 oldv, cmpv, newv;
|
Int128 oldv, cmpv, newv;
|
||||||
bool success;
|
bool success;
|
||||||
|
|
||||||
|
@ -523,6 +524,8 @@ static uint64_t do_paired_cmpxchg64_be(CPUARMState *env, uint64_t addr,
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
/* ??? Enforce alignment. */
|
/* ??? Enforce alignment. */
|
||||||
uint64_t *haddr = g2h(addr);
|
uint64_t *haddr = g2h(addr);
|
||||||
|
|
||||||
|
helper_retaddr = ra;
|
||||||
o1 = ldq_be_p(haddr + 0);
|
o1 = ldq_be_p(haddr + 0);
|
||||||
o0 = ldq_be_p(haddr + 1);
|
o0 = ldq_be_p(haddr + 1);
|
||||||
oldv = int128_make128(o0, o1);
|
oldv = int128_make128(o0, o1);
|
||||||
|
@ -532,6 +535,7 @@ static uint64_t do_paired_cmpxchg64_be(CPUARMState *env, uint64_t addr,
|
||||||
stq_be_p(haddr + 0, int128_gethi(newv));
|
stq_be_p(haddr + 0, int128_gethi(newv));
|
||||||
stq_be_p(haddr + 1, int128_getlo(newv));
|
stq_be_p(haddr + 1, int128_getlo(newv));
|
||||||
}
|
}
|
||||||
|
helper_retaddr = 0;
|
||||||
#else
|
#else
|
||||||
int mem_idx = cpu_mmu_index(env, false);
|
int mem_idx = cpu_mmu_index(env, false);
|
||||||
TCGMemOpIdx oi0 = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx);
|
TCGMemOpIdx oi0 = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx);
|
||||||
|
@ -555,11 +559,11 @@ static uint64_t do_paired_cmpxchg64_be(CPUARMState *env, uint64_t addr,
|
||||||
uint64_t HELPER(paired_cmpxchg64_be)(CPUARMState *env, uint64_t addr,
|
uint64_t HELPER(paired_cmpxchg64_be)(CPUARMState *env, uint64_t addr,
|
||||||
uint64_t new_lo, uint64_t new_hi)
|
uint64_t new_lo, uint64_t new_hi)
|
||||||
{
|
{
|
||||||
return do_paired_cmpxchg64_be(env, addr, new_lo, new_hi, false);
|
return do_paired_cmpxchg64_be(env, addr, new_lo, new_hi, false, GETPC());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t HELPER(paired_cmpxchg64_be_parallel)(CPUARMState *env, uint64_t addr,
|
uint64_t HELPER(paired_cmpxchg64_be_parallel)(CPUARMState *env, uint64_t addr,
|
||||||
uint64_t new_lo, uint64_t new_hi)
|
uint64_t new_lo, uint64_t new_hi)
|
||||||
{
|
{
|
||||||
return do_paired_cmpxchg64_be(env, addr, new_lo, new_hi, true);
|
return do_paired_cmpxchg64_be(env, addr, new_lo, new_hi, true, GETPC());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue