1
The following changes since commit ee26ce674a93c824713542cec3b6a9ca85459165:
1
Changes since v1:
2
* Added QEMU_ERROR to wrap __attribute__((error)) -- patch 12.
2
3
3
Merge remote-tracking branch 'remotes/jsnow/tags/python-pull-request' into staging (2021-10-12 16:08:33 -0700)
4
5
r~
6
7
8
The following changes since commit 77f7c747193662edfadeeb3118d63eed0eac51a6:
9
10
Merge remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2018-10-17' into staging (2018-10-18 13:40:19 +0100)
4
11
5
are available in the Git repository at:
12
are available in the Git repository at:
6
13
7
https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20211013
14
https://github.com/rth7680/qemu.git tags/pull-tcg-20181018
8
15
9
for you to fetch changes up to 76e366e728549b3324cc2dee6745d6a4f1af18e6:
16
for you to fetch changes up to 403f290c0603f35f2d09c982bf5549b6d0803ec1:
10
17
11
tcg: Canonicalize alignment flags in MemOp (2021-10-13 09:14:35 -0700)
18
cputlb: read CPUTLBEntry.addr_write atomically (2018-10-18 19:46:53 -0700)
12
19
13
----------------------------------------------------------------
20
----------------------------------------------------------------
14
Use MO_128 for 16-byte atomic memory operations.
21
Queued tcg patches.
15
Add cpu_ld/st_mmu memory primitives.
16
Move helper_ld/st memory helpers out of tcg.h.
17
Canonicalize alignment flags in MemOp.
18
22
19
----------------------------------------------------------------
23
----------------------------------------------------------------
20
BALATON Zoltan (1):
24
Emilio G. Cota (10):
21
memory: Log access direction for invalid accesses
25
tcg: access cpu->icount_decr.u16.high with atomics
26
tcg: fix use of uninitialized variable under CONFIG_PROFILER
27
tcg: plug holes in struct TCGProfile
28
tcg: distribute tcg_time into TCG contexts
29
target/alpha: remove tlb_flush from alpha_cpu_initfn
30
target/unicore32: remove tlb_flush from uc32_init_fn
31
exec: introduce tlb_init
32
cputlb: fix assert_cpu_is_self macro
33
cputlb: serialize tlb updates with env->tlb_lock
34
cputlb: read CPUTLBEntry.addr_write atomically
22
35
23
Richard Henderson (14):
36
Richard Henderson (11):
24
target/arm: Use MO_128 for 16 byte atomics
37
tcg: Implement CPU_LOG_TB_NOCHAIN during expansion
25
target/i386: Use MO_128 for 16 byte atomics
38
tcg: Add tlb_index and tlb_entry helpers
26
target/ppc: Use MO_128 for 16 byte atomics
39
tcg: Split CONFIG_ATOMIC128
27
target/s390x: Use MO_128 for 16 byte atomics
40
target/i386: Convert to HAVE_CMPXCHG128
28
target/hexagon: Implement cpu_mmu_index
41
target/arm: Convert to HAVE_CMPXCHG128
29
accel/tcg: Add cpu_{ld,st}*_mmu interfaces
42
target/arm: Check HAVE_CMPXCHG128 at translate time
30
accel/tcg: Move cpu_atomic decls to exec/cpu_ldst.h
43
target/ppc: Convert to HAVE_CMPXCHG128 and HAVE_ATOMIC128
31
target/mips: Use cpu_*_data_ra for msa load/store
44
target/s390x: Convert to HAVE_CMPXCHG128 and HAVE_ATOMIC128
32
target/mips: Use 8-byte memory ops for msa load/store
45
target/s390x: Split do_cdsg, do_lpq, do_stpq
33
target/s390x: Use cpu_*_mmu instead of helper_*_mmu
46
target/s390x: Skip wout, cout helpers if op helper does not return
34
target/sparc: Use cpu_*_mmu instead of helper_*_mmu
47
target/s390x: Check HAVE_ATOMIC128 and HAVE_CMPXCHG128 at translate
35
target/arm: Use cpu_*_mmu instead of helper_*_mmu
36
tcg: Move helper_*_mmu decls to tcg/tcg-ldst.h
37
tcg: Canonicalize alignment flags in MemOp
38
48
39
docs/devel/loads-stores.rst | 52 +++++-
49
accel/tcg/atomic_template.h | 20 +++-
40
include/exec/cpu_ldst.h | 332 ++++++++++++++++++-----------------
50
accel/tcg/softmmu_template.h | 64 +++++-----
41
include/tcg/tcg-ldst.h | 74 ++++++++
51
include/exec/cpu-defs.h | 3 +
42
include/tcg/tcg.h | 158 -----------------
52
include/exec/cpu_ldst.h | 30 ++++-
43
target/hexagon/cpu.h | 9 +
53
include/exec/cpu_ldst_template.h | 25 ++--
44
accel/tcg/cputlb.c | 393 ++++++++++++++----------------------------
54
include/exec/exec-all.h | 8 ++
45
accel/tcg/user-exec.c | 385 +++++++++++++++++------------------------
55
include/qemu/atomic128.h | 153 ++++++++++++++++++++++++
46
softmmu/memory.c | 20 +--
56
include/qemu/compiler.h | 11 ++
47
target/arm/helper-a64.c | 61 ++-----
57
include/qemu/timer.h | 1 -
48
target/arm/m_helper.c | 6 +-
58
target/ppc/helper.h | 2 +-
49
target/i386/tcg/mem_helper.c | 2 +-
59
tcg/tcg.h | 20 ++--
50
target/m68k/op_helper.c | 1 -
60
accel/tcg/cpu-exec.c | 2 +-
51
target/mips/tcg/msa_helper.c | 389 ++++++++++-------------------------------
61
accel/tcg/cputlb.c | 235 +++++++++++++++++++-----------------
52
target/ppc/mem_helper.c | 1 -
62
accel/tcg/tcg-all.c | 2 +-
53
target/ppc/translate.c | 12 +-
63
accel/tcg/translate-all.c | 2 +-
54
target/s390x/tcg/mem_helper.c | 13 +-
64
accel/tcg/user-exec.c | 5 +-
55
target/sparc/ldst_helper.c | 14 +-
65
cpus.c | 3 +-
56
tcg/tcg-op.c | 7 +-
66
exec.c | 1 +
57
tcg/tcg.c | 1 +
67
monitor.c | 13 +-
58
tcg/tci.c | 1 +
68
qom/cpu.c | 2 +-
59
accel/tcg/ldst_common.c.inc | 307 +++++++++++++++++++++++++++++++++
69
target/alpha/cpu.c | 1 -
60
21 files changed, 1032 insertions(+), 1206 deletions(-)
70
target/arm/helper-a64.c | 251 +++++++++++++++++++--------------------
61
create mode 100644 include/tcg/tcg-ldst.h
71
target/arm/translate-a64.c | 38 +++---
62
create mode 100644 accel/tcg/ldst_common.c.inc
72
target/i386/mem_helper.c | 9 +-
73
target/ppc/mem_helper.c | 33 ++++-
74
target/ppc/translate.c | 115 +++++++++---------
75
target/s390x/mem_helper.c | 202 +++++++++++++++----------------
76
target/s390x/translate.c | 45 +++++--
77
target/unicore32/cpu.c | 2 -
78
tcg/tcg-op.c | 9 +-
79
tcg/tcg.c | 25 +++-
80
configure | 19 +++
81
32 files changed, 839 insertions(+), 512 deletions(-)
82
create mode 100644 include/qemu/atomic128.h
63
83
diff view generated by jsdifflib
1
Having observed e.g. al8+leq in dumps, canonicalize to al+leq.
1
Rather than test NOCHAIN before linking, do not emit the
2
goto_tb opcode at all. We already do this for goto_ptr.
2
3
3
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
---
5
---
6
tcg/tcg-op.c | 7 ++++++-
6
accel/tcg/cpu-exec.c | 2 +-
7
1 file changed, 6 insertions(+), 1 deletion(-)
7
tcg/tcg-op.c | 9 ++++++++-
8
2 files changed, 9 insertions(+), 2 deletions(-)
8
9
10
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/accel/tcg/cpu-exec.c
13
+++ b/accel/tcg/cpu-exec.c
14
@@ -XXX,XX +XXX,XX @@ static inline TranslationBlock *tb_find(CPUState *cpu,
15
}
16
#endif
17
/* See if we can patch the calling TB. */
18
- if (last_tb && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
19
+ if (last_tb) {
20
tb_add_jump(last_tb, tb_exit, tb);
21
}
22
return tb;
9
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
23
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
10
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
11
--- a/tcg/tcg-op.c
25
--- a/tcg/tcg-op.c
12
+++ b/tcg/tcg-op.c
26
+++ b/tcg/tcg-op.c
13
@@ -XXX,XX +XXX,XX @@ void tcg_gen_lookup_and_goto_ptr(void)
27
@@ -XXX,XX +XXX,XX @@ void tcg_gen_exit_tb(TranslationBlock *tb, unsigned idx)
14
static inline MemOp tcg_canonicalize_memop(MemOp op, bool is64, bool st)
28
seen this numbered exit before, via tcg_gen_goto_tb. */
15
{
29
tcg_debug_assert(tcg_ctx->goto_tb_issue_mask & (1 << idx));
16
/* Trigger the asserts within as early as possible. */
30
#endif
17
- (void)get_alignment_bits(op);
31
+ /* When not chaining, exit without indicating a link. */
18
+ unsigned a_bits = get_alignment_bits(op);
32
+ if (qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
19
+
33
+ val = 0;
20
+ /* Prefer MO_ALIGN+MO_XX over MO_ALIGN_XX+MO_XX */
34
+ }
21
+ if (a_bits == (op & MO_SIZE)) {
35
} else {
22
+ op = (op & ~MO_AMASK) | MO_ALIGN;
36
/* This is an exit via the exitreq label. */
37
tcg_debug_assert(idx == TB_EXIT_REQUESTED);
38
@@ -XXX,XX +XXX,XX @@ void tcg_gen_goto_tb(unsigned idx)
39
tcg_debug_assert((tcg_ctx->goto_tb_issue_mask & (1 << idx)) == 0);
40
tcg_ctx->goto_tb_issue_mask |= 1 << idx;
41
#endif
42
- tcg_gen_op1i(INDEX_op_goto_tb, idx);
43
+ /* When not chaining, we simply fall through to the "fallback" exit. */
44
+ if (!qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
45
+ tcg_gen_op1i(INDEX_op_goto_tb, idx);
23
+ }
46
+ }
24
47
}
25
switch (op & MO_SIZE) {
48
26
case MO_8:
49
void tcg_gen_lookup_and_goto_ptr(void)
27
--
50
--
28
2.25.1
51
2.17.2
29
52
30
53
diff view generated by jsdifflib
New patch
1
From: "Emilio G. Cota" <cota@braap.org>
1
2
3
Consistently access u16.high with atomics to avoid
4
undefined behaviour in MTTCG.
5
6
Note that icount_decr.u16.low is only used in icount mode,
7
so regular accesses to it are OK.
8
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Emilio G. Cota <cota@braap.org>
11
Message-Id: <20181010144853.13005-2-cota@braap.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
---
14
accel/tcg/tcg-all.c | 2 +-
15
accel/tcg/translate-all.c | 2 +-
16
qom/cpu.c | 2 +-
17
3 files changed, 3 insertions(+), 3 deletions(-)
18
19
diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/accel/tcg/tcg-all.c
22
+++ b/accel/tcg/tcg-all.c
23
@@ -XXX,XX +XXX,XX @@ static void tcg_handle_interrupt(CPUState *cpu, int mask)
24
if (!qemu_cpu_is_self(cpu)) {
25
qemu_cpu_kick(cpu);
26
} else {
27
- cpu->icount_decr.u16.high = -1;
28
+ atomic_set(&cpu->icount_decr.u16.high, -1);
29
if (use_icount &&
30
!cpu->can_do_io
31
&& (mask & ~old_mask) != 0) {
32
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/accel/tcg/translate-all.c
35
+++ b/accel/tcg/translate-all.c
36
@@ -XXX,XX +XXX,XX @@ void cpu_interrupt(CPUState *cpu, int mask)
37
{
38
g_assert(qemu_mutex_iothread_locked());
39
cpu->interrupt_request |= mask;
40
- cpu->icount_decr.u16.high = -1;
41
+ atomic_set(&cpu->icount_decr.u16.high, -1);
42
}
43
44
/*
45
diff --git a/qom/cpu.c b/qom/cpu.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/qom/cpu.c
48
+++ b/qom/cpu.c
49
@@ -XXX,XX +XXX,XX @@ static void cpu_common_reset(CPUState *cpu)
50
cpu->mem_io_pc = 0;
51
cpu->mem_io_vaddr = 0;
52
cpu->icount_extra = 0;
53
- cpu->icount_decr.u32 = 0;
54
+ atomic_set(&cpu->icount_decr.u32, 0);
55
cpu->can_do_io = 1;
56
cpu->exception_index = -1;
57
cpu->crash_occurred = false;
58
--
59
2.17.2
60
61
diff view generated by jsdifflib
New patch
1
From: "Emilio G. Cota" <cota@braap.org>
1
2
3
We forgot to initialize n in commit 15fa08f845 ("tcg: Dynamically
4
allocate TCGOps", 2017-12-29).
5
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Signed-off-by: Emilio G. Cota <cota@braap.org>
8
Message-Id: <20181010144853.13005-3-cota@braap.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
---
11
tcg/tcg.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
14
diff --git a/tcg/tcg.c b/tcg/tcg.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tcg/tcg.c
17
+++ b/tcg/tcg.c
18
@@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
19
20
#ifdef CONFIG_PROFILER
21
{
22
- int n;
23
+ int n = 0;
24
25
QTAILQ_FOREACH(op, &s->ops, link) {
26
n++;
27
--
28
2.17.2
29
30
diff view generated by jsdifflib
1
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: "Emilio G. Cota" <cota@braap.org>
2
3
This plugs two 4-byte holes in 64-bit.
4
5
Signed-off-by: Emilio G. Cota <cota@braap.org>
6
Message-Id: <20181010144853.13005-4-cota@braap.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
8
---
4
target/i386/tcg/mem_helper.c | 2 +-
9
tcg/tcg.h | 2 +-
5
1 file changed, 1 insertion(+), 1 deletion(-)
10
1 file changed, 1 insertion(+), 1 deletion(-)
6
11
7
diff --git a/target/i386/tcg/mem_helper.c b/target/i386/tcg/mem_helper.c
12
diff --git a/tcg/tcg.h b/tcg/tcg.h
8
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
9
--- a/target/i386/tcg/mem_helper.c
14
--- a/tcg/tcg.h
10
+++ b/target/i386/tcg/mem_helper.c
15
+++ b/tcg/tcg.h
11
@@ -XXX,XX +XXX,XX @@ void helper_cmpxchg16b(CPUX86State *env, target_ulong a0)
16
@@ -XXX,XX +XXX,XX @@ typedef struct TCGProfile {
12
Int128 newv = int128_make128(env->regs[R_EBX], env->regs[R_ECX]);
17
int64_t tb_count;
13
18
int64_t op_count; /* total insn count */
14
int mem_idx = cpu_mmu_index(env, false);
19
int op_count_max; /* max insn per TB */
15
- MemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
20
- int64_t temp_count;
16
+ MemOpIdx oi = make_memop_idx(MO_TE | MO_128 | MO_ALIGN, mem_idx);
21
int temp_count_max;
17
Int128 oldv = cpu_atomic_cmpxchgo_le_mmu(env, a0, cmpv, newv, oi, ra);
22
+ int64_t temp_count;
18
23
int64_t del_op_count;
19
if (int128_eq(oldv, cmpv)) {
24
int64_t code_in_len;
25
int64_t code_out_len;
20
--
26
--
21
2.25.1
27
2.17.2
22
28
23
29
diff view generated by jsdifflib
New patch
1
From: "Emilio G. Cota" <cota@braap.org>
1
2
3
When we implemented per-vCPU TCG contexts, we forgot to also
4
distribute the tcg_time counter, which has remained as a global
5
accessed without any serialization, leading to potentially missed
6
counts.
7
8
Fix it by distributing the field over the TCG contexts, embedding
9
it into TCGProfile with a field called "cpu_exec_time", which is more
10
descriptive than "tcg_time". Add a function to query this value
11
directly, and for completeness, fill in the field in
12
tcg_profile_snapshot, even though its callers do not use it.
13
14
Signed-off-by: Emilio G. Cota <cota@braap.org>
15
Message-Id: <20181010144853.13005-5-cota@braap.org>
16
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
17
---
18
include/qemu/timer.h | 1 -
19
tcg/tcg.h | 2 ++
20
cpus.c | 3 ++-
21
monitor.c | 13 ++++++++++---
22
tcg/tcg.c | 23 +++++++++++++++++++++++
23
5 files changed, 37 insertions(+), 5 deletions(-)
24
25
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/include/qemu/timer.h
28
+++ b/include/qemu/timer.h
29
@@ -XXX,XX +XXX,XX @@ static inline int64_t profile_getclock(void)
30
return get_clock();
31
}
32
33
-extern int64_t tcg_time;
34
extern int64_t dev_time;
35
#endif
36
37
diff --git a/tcg/tcg.h b/tcg/tcg.h
38
index XXXXXXX..XXXXXXX 100644
39
--- a/tcg/tcg.h
40
+++ b/tcg/tcg.h
41
@@ -XXX,XX +XXX,XX @@ typedef struct TCGOp {
42
QEMU_BUILD_BUG_ON(NB_OPS > (1 << 8));
43
44
typedef struct TCGProfile {
45
+ int64_t cpu_exec_time;
46
int64_t tb_count1;
47
int64_t tb_count;
48
int64_t op_count; /* total insn count */
49
@@ -XXX,XX +XXX,XX @@ int tcg_check_temp_count(void);
50
#define tcg_check_temp_count() 0
51
#endif
52
53
+int64_t tcg_cpu_exec_time(void);
54
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf);
55
void tcg_dump_op_count(FILE *f, fprintf_function cpu_fprintf);
56
57
diff --git a/cpus.c b/cpus.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/cpus.c
60
+++ b/cpus.c
61
@@ -XXX,XX +XXX,XX @@ static int tcg_cpu_exec(CPUState *cpu)
62
ret = cpu_exec(cpu);
63
cpu_exec_end(cpu);
64
#ifdef CONFIG_PROFILER
65
- tcg_time += profile_getclock() - ti;
66
+ atomic_set(&tcg_ctx->prof.cpu_exec_time,
67
+ tcg_ctx->prof.cpu_exec_time + profile_getclock() - ti);
68
#endif
69
return ret;
70
}
71
diff --git a/monitor.c b/monitor.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/monitor.c
74
+++ b/monitor.c
75
@@ -XXX,XX +XXX,XX @@
76
#include "sysemu/cpus.h"
77
#include "sysemu/iothread.h"
78
#include "qemu/cutils.h"
79
+#include "tcg/tcg.h"
80
81
#if defined(TARGET_S390X)
82
#include "hw/s390x/storage-keys.h"
83
@@ -XXX,XX +XXX,XX @@ static void hmp_info_numa(Monitor *mon, const QDict *qdict)
84
85
#ifdef CONFIG_PROFILER
86
87
-int64_t tcg_time;
88
int64_t dev_time;
89
90
static void hmp_info_profile(Monitor *mon, const QDict *qdict)
91
{
92
+ static int64_t last_cpu_exec_time;
93
+ int64_t cpu_exec_time;
94
+ int64_t delta;
95
+
96
+ cpu_exec_time = tcg_cpu_exec_time();
97
+ delta = cpu_exec_time - last_cpu_exec_time;
98
+
99
monitor_printf(mon, "async time %" PRId64 " (%0.3f)\n",
100
dev_time, dev_time / (double)NANOSECONDS_PER_SECOND);
101
monitor_printf(mon, "qemu time %" PRId64 " (%0.3f)\n",
102
- tcg_time, tcg_time / (double)NANOSECONDS_PER_SECOND);
103
- tcg_time = 0;
104
+ delta, delta / (double)NANOSECONDS_PER_SECOND);
105
+ last_cpu_exec_time = cpu_exec_time;
106
dev_time = 0;
107
}
108
#else
109
diff --git a/tcg/tcg.c b/tcg/tcg.c
110
index XXXXXXX..XXXXXXX 100644
111
--- a/tcg/tcg.c
112
+++ b/tcg/tcg.c
113
@@ -XXX,XX +XXX,XX @@
114
/* Define to jump the ELF file used to communicate with GDB. */
115
#undef DEBUG_JIT
116
117
+#include "qemu/error-report.h"
118
#include "qemu/cutils.h"
119
#include "qemu/host-utils.h"
120
#include "qemu/timer.h"
121
@@ -XXX,XX +XXX,XX @@ void tcg_profile_snapshot(TCGProfile *prof, bool counters, bool table)
122
const TCGProfile *orig = &s->prof;
123
124
if (counters) {
125
+ PROF_ADD(prof, orig, cpu_exec_time);
126
PROF_ADD(prof, orig, tb_count1);
127
PROF_ADD(prof, orig, tb_count);
128
PROF_ADD(prof, orig, op_count);
129
@@ -XXX,XX +XXX,XX @@ void tcg_dump_op_count(FILE *f, fprintf_function cpu_fprintf)
130
prof.table_op_count[i]);
131
}
132
}
133
+
134
+int64_t tcg_cpu_exec_time(void)
135
+{
136
+ unsigned int n_ctxs = atomic_read(&n_tcg_ctxs);
137
+ unsigned int i;
138
+ int64_t ret = 0;
139
+
140
+ for (i = 0; i < n_ctxs; i++) {
141
+ const TCGContext *s = atomic_read(&tcg_ctxs[i]);
142
+ const TCGProfile *prof = &s->prof;
143
+
144
+ ret += atomic_read(&prof->cpu_exec_time);
145
+ }
146
+ return ret;
147
+}
148
#else
149
void tcg_dump_op_count(FILE *f, fprintf_function cpu_fprintf)
150
{
151
cpu_fprintf(f, "[TCG profiler not compiled]\n");
152
}
153
+
154
+int64_t tcg_cpu_exec_time(void)
155
+{
156
+ error_report("%s: TCG profiler not compiled", __func__);
157
+ exit(EXIT_FAILURE);
158
+}
159
#endif
160
161
162
--
163
2.17.2
164
165
diff view generated by jsdifflib
New patch
1
From: "Emilio G. Cota" <cota@braap.org>
1
2
3
As far as I can tell tlb_flush does not need to be called
4
this early. tlb_flush is eventually called after the CPU
5
has been realized.
6
7
This change paves the way to the introduction of tlb_init,
8
which will be called from cpu_exec_realizefn.
9
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Signed-off-by: Emilio G. Cota <cota@braap.org>
13
Message-Id: <20181009174557.16125-2-cota@braap.org>
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
---
16
target/alpha/cpu.c | 1 -
17
1 file changed, 1 deletion(-)
18
19
diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/alpha/cpu.c
22
+++ b/target/alpha/cpu.c
23
@@ -XXX,XX +XXX,XX @@ static void alpha_cpu_initfn(Object *obj)
24
CPUAlphaState *env = &cpu->env;
25
26
cs->env_ptr = env;
27
- tlb_flush(cs);
28
29
env->lock_addr = -1;
30
#if defined(CONFIG_USER_ONLY)
31
--
32
2.17.2
33
34
diff view generated by jsdifflib
1
The helper_*_mmu functions were the only thing available
1
From: "Emilio G. Cota" <cota@braap.org>
2
when this code was written. This could have been adjusted
3
when we added cpu_*_mmuidx_ra, but now we can most easily
4
use the newest set of interfaces.
5
2
6
Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
3
As far as I can tell tlb_flush does not need to be called
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
this early. tlb_flush is eventually called after the CPU
5
has been realized.
6
7
This change paves the way to the introduction of tlb_init,
8
which will be called from cpu_exec_realizefn.
9
10
Cc: Guan Xuetao <gxt@mprc.pku.edu.cn>
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Emilio G. Cota <cota@braap.org>
14
Message-Id: <20181009174557.16125-3-cota@braap.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
16
---
10
target/sparc/ldst_helper.c | 14 +++++++-------
17
target/unicore32/cpu.c | 2 --
11
1 file changed, 7 insertions(+), 7 deletions(-)
18
1 file changed, 2 deletions(-)
12
19
13
diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c
20
diff --git a/target/unicore32/cpu.c b/target/unicore32/cpu.c
14
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
15
--- a/target/sparc/ldst_helper.c
22
--- a/target/unicore32/cpu.c
16
+++ b/target/sparc/ldst_helper.c
23
+++ b/target/unicore32/cpu.c
17
@@ -XXX,XX +XXX,XX @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr,
24
@@ -XXX,XX +XXX,XX @@ static void uc32_cpu_initfn(Object *obj)
18
oi = make_memop_idx(memop, idx);
25
env->uncached_asr = ASR_MODE_PRIV;
19
switch (size) {
26
env->regs[31] = 0x03000000;
20
case 1:
27
#endif
21
- ret = helper_ret_ldub_mmu(env, addr, oi, GETPC());
28
-
22
+ ret = cpu_ldb_mmu(env, addr, oi, GETPC());
29
- tlb_flush(cs);
23
break;
30
}
24
case 2:
31
25
if (asi & 8) {
32
static const VMStateDescription vmstate_uc32_cpu = {
26
- ret = helper_le_lduw_mmu(env, addr, oi, GETPC());
27
+ ret = cpu_ldw_le_mmu(env, addr, oi, GETPC());
28
} else {
29
- ret = helper_be_lduw_mmu(env, addr, oi, GETPC());
30
+ ret = cpu_ldw_be_mmu(env, addr, oi, GETPC());
31
}
32
break;
33
case 4:
34
if (asi & 8) {
35
- ret = helper_le_ldul_mmu(env, addr, oi, GETPC());
36
+ ret = cpu_ldl_le_mmu(env, addr, oi, GETPC());
37
} else {
38
- ret = helper_be_ldul_mmu(env, addr, oi, GETPC());
39
+ ret = cpu_ldl_be_mmu(env, addr, oi, GETPC());
40
}
41
break;
42
case 8:
43
if (asi & 8) {
44
- ret = helper_le_ldq_mmu(env, addr, oi, GETPC());
45
+ ret = cpu_ldq_le_mmu(env, addr, oi, GETPC());
46
} else {
47
- ret = helper_be_ldq_mmu(env, addr, oi, GETPC());
48
+ ret = cpu_ldq_be_mmu(env, addr, oi, GETPC());
49
}
50
break;
51
default:
52
--
33
--
53
2.25.1
34
2.17.2
54
35
55
36
diff view generated by jsdifflib
1
The helper_*_mmu functions were the only thing available
1
From: "Emilio G. Cota" <cota@braap.org>
2
when this code was written. This could have been adjusted
3
when we added cpu_*_mmuidx_ra, but now we can most easily
4
use the newest set of interfaces.
5
2
6
Reviewed-by: David Hildenbrand <david@redhat.com>
3
Paves the way for the addition of a per-TLB lock.
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Emilio G. Cota <cota@braap.org>
8
Message-Id: <20181009174557.16125-4-cota@braap.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
10
---
10
target/s390x/tcg/mem_helper.c | 8 ++++----
11
include/exec/exec-all.h | 8 ++++++++
11
1 file changed, 4 insertions(+), 4 deletions(-)
12
accel/tcg/cputlb.c | 4 ++++
13
exec.c | 1 +
14
3 files changed, 13 insertions(+)
12
15
13
diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c
16
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/target/s390x/tcg/mem_helper.c
18
--- a/include/exec/exec-all.h
16
+++ b/target/s390x/tcg/mem_helper.c
19
+++ b/include/exec/exec-all.h
17
@@ -XXX,XX +XXX,XX @@ static void do_access_memset(CPUS390XState *env, vaddr vaddr, char *haddr,
20
@@ -XXX,XX +XXX,XX @@ void cpu_address_space_init(CPUState *cpu, int asidx,
18
* page. This is especially relevant to speed up TLB_NOTDIRTY.
21
19
*/
22
#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
20
g_assert(size > 0);
23
/* cputlb.c */
21
- helper_ret_stb_mmu(env, vaddr, byte, oi, ra);
24
+/**
22
+ cpu_stb_mmu(env, vaddr, byte, oi, ra);
25
+ * tlb_init - initialize a CPU's TLB
23
haddr = tlb_vaddr_to_host(env, vaddr, MMU_DATA_STORE, mmu_idx);
26
+ * @cpu: CPU whose TLB should be initialized
24
if (likely(haddr)) {
27
+ */
25
memset(haddr + 1, byte, size - 1);
28
+void tlb_init(CPUState *cpu);
26
} else {
29
/**
27
for (i = 1; i < size; i++) {
30
* tlb_flush_page:
28
- helper_ret_stb_mmu(env, vaddr + i, byte, oi, ra);
31
* @cpu: CPU whose TLB should be flushed
29
+ cpu_stb_mmu(env, vaddr + i, byte, oi, ra);
32
@@ -XXX,XX +XXX,XX @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
30
}
33
void probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx,
31
}
34
uintptr_t retaddr);
35
#else
36
+static inline void tlb_init(CPUState *cpu)
37
+{
38
+}
39
static inline void tlb_flush_page(CPUState *cpu, target_ulong addr)
40
{
41
}
42
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/accel/tcg/cputlb.c
45
+++ b/accel/tcg/cputlb.c
46
@@ -XXX,XX +XXX,XX @@ QEMU_BUILD_BUG_ON(sizeof(target_ulong) > sizeof(run_on_cpu_data));
47
QEMU_BUILD_BUG_ON(NB_MMU_MODES > 16);
48
#define ALL_MMUIDX_BITS ((1 << NB_MMU_MODES) - 1)
49
50
+void tlb_init(CPUState *cpu)
51
+{
52
+}
53
+
54
/* flush_all_helper: run fn across all cpus
55
*
56
* If the wait flag is set then the src cpu's helper will be queued as
57
diff --git a/exec.c b/exec.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/exec.c
60
+++ b/exec.c
61
@@ -XXX,XX +XXX,XX @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
62
tcg_target_initialized = true;
63
cc->tcg_initialize();
32
}
64
}
33
@@ -XXX,XX +XXX,XX @@ static uint8_t do_access_get_byte(CPUS390XState *env, vaddr vaddr, char **haddr,
65
+ tlb_init(cpu);
34
* Do a single access and test if we can then get access to the
66
35
* page. This is especially relevant to speed up TLB_NOTDIRTY.
67
#ifndef CONFIG_USER_ONLY
36
*/
68
if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
37
- byte = helper_ret_ldub_mmu(env, vaddr + offset, oi, ra);
38
+ byte = cpu_ldb_mmu(env, vaddr + offset, oi, ra);
39
*haddr = tlb_vaddr_to_host(env, vaddr, MMU_DATA_LOAD, mmu_idx);
40
return byte;
41
#endif
42
@@ -XXX,XX +XXX,XX @@ static void do_access_set_byte(CPUS390XState *env, vaddr vaddr, char **haddr,
43
* Do a single access and test if we can then get access to the
44
* page. This is especially relevant to speed up TLB_NOTDIRTY.
45
*/
46
- helper_ret_stb_mmu(env, vaddr + offset, byte, oi, ra);
47
+ cpu_stb_mmu(env, vaddr + offset, byte, oi, ra);
48
*haddr = tlb_vaddr_to_host(env, vaddr, MMU_DATA_STORE, mmu_idx);
49
#endif
50
}
51
--
69
--
52
2.25.1
70
2.17.2
53
71
54
72
diff view generated by jsdifflib
1
The function is trivial for user-only, but still must be present.
1
From: "Emilio G. Cota" <cota@braap.org>
2
2
3
Reviewed-by: Taylor Simpson <tsimpson@quicinc.com>
3
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Emilio G. Cota <cota@braap.org>
6
Message-Id: <20181009174557.16125-5-cota@braap.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
8
---
7
target/hexagon/cpu.h | 9 +++++++++
9
accel/tcg/cputlb.c | 4 ++--
8
1 file changed, 9 insertions(+)
10
1 file changed, 2 insertions(+), 2 deletions(-)
9
11
10
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
12
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
11
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
12
--- a/target/hexagon/cpu.h
14
--- a/accel/tcg/cputlb.c
13
+++ b/target/hexagon/cpu.h
15
+++ b/accel/tcg/cputlb.c
14
@@ -XXX,XX +XXX,XX @@ static inline void cpu_get_tb_cpu_state(CPUHexagonState *env, target_ulong *pc,
16
@@ -XXX,XX +XXX,XX @@
15
#endif
17
} \
16
}
18
} while (0)
17
19
18
+static inline int cpu_mmu_index(CPUHexagonState *env, bool ifetch)
20
-#define assert_cpu_is_self(this_cpu) do { \
19
+{
21
+#define assert_cpu_is_self(cpu) do { \
20
+#ifdef CONFIG_USER_ONLY
22
if (DEBUG_TLB_GATE) { \
21
+ return MMU_USER_IDX;
23
- g_assert(!cpu->created || qemu_cpu_is_self(cpu)); \
22
+#else
24
+ g_assert(!(cpu)->created || qemu_cpu_is_self(cpu)); \
23
+#error System mode not supported on Hexagon yet
25
} \
24
+#endif
26
} while (0)
25
+}
26
+
27
typedef struct CPUHexagonState CPUArchState;
28
typedef HexagonCPU ArchCPU;
29
27
30
--
28
--
31
2.25.1
29
2.17.2
32
30
33
31
diff view generated by jsdifflib
New patch
1
1
From: "Emilio G. Cota" <cota@braap.org>
2
3
Currently we rely on atomic operations for cross-CPU invalidations.
4
There are two cases that these atomics miss: cross-CPU invalidations
5
can race with either (1) vCPU threads flushing their TLB, which
6
happens via memset, or (2) vCPUs calling tlb_reset_dirty on their TLB,
7
which updates .addr_write with a regular store. This results in
8
undefined behaviour, since we're mixing regular and atomic ops
9
on concurrent accesses.
10
11
Fix it by using tlb_lock, a per-vCPU lock. All updaters of tlb_table
12
and the corresponding victim cache now hold the lock.
13
The readers that do not hold tlb_lock must use atomic reads when
14
reading .addr_write, since this field can be updated by other threads;
15
the conversion to atomic reads is done in the next patch.
16
17
Note that an alternative fix would be to expand the use of atomic ops.
18
However, in the case of TLB flushes this would have a huge performance
19
impact, since (1) TLB flushes can happen very frequently and (2) we
20
currently use a full memory barrier to flush each TLB entry, and a TLB
21
has many entries. Instead, acquiring the lock is barely slower than a
22
full memory barrier since it is uncontended, and with a single lock
23
acquisition we can flush the entire TLB.
24
25
Tested-by: Alex Bennée <alex.bennee@linaro.org>
26
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
27
Signed-off-by: Emilio G. Cota <cota@braap.org>
28
Message-Id: <20181009174557.16125-6-cota@braap.org>
29
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
30
---
31
include/exec/cpu-defs.h | 3 +
32
accel/tcg/cputlb.c | 155 ++++++++++++++++++++++------------------
33
2 files changed, 87 insertions(+), 71 deletions(-)
34
35
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/include/exec/cpu-defs.h
38
+++ b/include/exec/cpu-defs.h
39
@@ -XXX,XX +XXX,XX @@
40
#endif
41
42
#include "qemu/host-utils.h"
43
+#include "qemu/thread.h"
44
#include "qemu/queue.h"
45
#ifdef CONFIG_TCG
46
#include "tcg-target.h"
47
@@ -XXX,XX +XXX,XX @@ typedef struct CPUIOTLBEntry {
48
49
#define CPU_COMMON_TLB \
50
/* The meaning of the MMU modes is defined in the target code. */ \
51
+ /* tlb_lock serializes updates to tlb_table and tlb_v_table */ \
52
+ QemuSpin tlb_lock; \
53
CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \
54
CPUTLBEntry tlb_v_table[NB_MMU_MODES][CPU_VTLB_SIZE]; \
55
CPUIOTLBEntry iotlb[NB_MMU_MODES][CPU_TLB_SIZE]; \
56
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/accel/tcg/cputlb.c
59
+++ b/accel/tcg/cputlb.c
60
@@ -XXX,XX +XXX,XX @@ QEMU_BUILD_BUG_ON(NB_MMU_MODES > 16);
61
62
void tlb_init(CPUState *cpu)
63
{
64
+ CPUArchState *env = cpu->env_ptr;
65
+
66
+ qemu_spin_init(&env->tlb_lock);
67
}
68
69
/* flush_all_helper: run fn across all cpus
70
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_nocheck(CPUState *cpu)
71
atomic_set(&env->tlb_flush_count, env->tlb_flush_count + 1);
72
tlb_debug("(count: %zu)\n", tlb_flush_count());
73
74
+ /*
75
+ * tlb_table/tlb_v_table updates from any thread must hold tlb_lock.
76
+ * However, updates from the owner thread (as is the case here; see the
77
+ * above assert_cpu_is_self) do not need atomic_set because all reads
78
+ * that do not hold the lock are performed by the same owner thread.
79
+ */
80
+ qemu_spin_lock(&env->tlb_lock);
81
memset(env->tlb_table, -1, sizeof(env->tlb_table));
82
memset(env->tlb_v_table, -1, sizeof(env->tlb_v_table));
83
+ qemu_spin_unlock(&env->tlb_lock);
84
+
85
cpu_tb_jmp_cache_clear(cpu);
86
87
env->vtlb_index = 0;
88
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data)
89
90
tlb_debug("start: mmu_idx:0x%04lx\n", mmu_idx_bitmask);
91
92
+ qemu_spin_lock(&env->tlb_lock);
93
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
94
95
if (test_bit(mmu_idx, &mmu_idx_bitmask)) {
96
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data)
97
memset(env->tlb_v_table[mmu_idx], -1, sizeof(env->tlb_v_table[0]));
98
}
99
}
100
+ qemu_spin_unlock(&env->tlb_lock);
101
102
cpu_tb_jmp_cache_clear(cpu);
103
104
@@ -XXX,XX +XXX,XX @@ static inline bool tlb_hit_page_anyprot(CPUTLBEntry *tlb_entry,
105
tlb_hit_page(tlb_entry->addr_code, page);
106
}
107
108
-static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong page)
109
+/* Called with tlb_lock held */
110
+static inline void tlb_flush_entry_locked(CPUTLBEntry *tlb_entry,
111
+ target_ulong page)
112
{
113
if (tlb_hit_page_anyprot(tlb_entry, page)) {
114
memset(tlb_entry, -1, sizeof(*tlb_entry));
115
}
116
}
117
118
-static inline void tlb_flush_vtlb_page(CPUArchState *env, int mmu_idx,
119
- target_ulong page)
120
+/* Called with tlb_lock held */
121
+static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx,
122
+ target_ulong page)
123
{
124
int k;
125
+
126
+ assert_cpu_is_self(ENV_GET_CPU(env));
127
for (k = 0; k < CPU_VTLB_SIZE; k++) {
128
- tlb_flush_entry(&env->tlb_v_table[mmu_idx][k], page);
129
+ tlb_flush_entry_locked(&env->tlb_v_table[mmu_idx][k], page);
130
}
131
}
132
133
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_page_async_work(CPUState *cpu, run_on_cpu_data data)
134
135
addr &= TARGET_PAGE_MASK;
136
i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
137
+ qemu_spin_lock(&env->tlb_lock);
138
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
139
- tlb_flush_entry(&env->tlb_table[mmu_idx][i], addr);
140
- tlb_flush_vtlb_page(env, mmu_idx, addr);
141
+ tlb_flush_entry_locked(&env->tlb_table[mmu_idx][i], addr);
142
+ tlb_flush_vtlb_page_locked(env, mmu_idx, addr);
143
}
144
+ qemu_spin_unlock(&env->tlb_lock);
145
146
tb_flush_jmp_cache(cpu, addr);
147
}
148
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_page_by_mmuidx_async_work(CPUState *cpu,
149
tlb_debug("page:%d addr:"TARGET_FMT_lx" mmu_idx:0x%lx\n",
150
page, addr, mmu_idx_bitmap);
151
152
+ qemu_spin_lock(&env->tlb_lock);
153
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
154
if (test_bit(mmu_idx, &mmu_idx_bitmap)) {
155
- tlb_flush_entry(&env->tlb_table[mmu_idx][page], addr);
156
- tlb_flush_vtlb_page(env, mmu_idx, addr);
157
+ tlb_flush_entry_locked(&env->tlb_table[mmu_idx][page], addr);
158
+ tlb_flush_vtlb_page_locked(env, mmu_idx, addr);
159
}
160
}
161
+ qemu_spin_unlock(&env->tlb_lock);
162
163
tb_flush_jmp_cache(cpu, addr);
164
}
165
@@ -XXX,XX +XXX,XX @@ void tlb_unprotect_code(ram_addr_t ram_addr)
166
* most usual is detecting writes to code regions which may invalidate
167
* generated code.
168
*
169
- * Because we want other vCPUs to respond to changes straight away we
170
- * update the te->addr_write field atomically. If the TLB entry has
171
- * been changed by the vCPU in the mean time we skip the update.
172
+ * Other vCPUs might be reading their TLBs during guest execution, so we update
173
+ * te->addr_write with atomic_set. We don't need to worry about this for
174
+ * oversized guests as MTTCG is disabled for them.
175
*
176
- * As this function uses atomic accesses we also need to ensure
177
- * updates to tlb_entries follow the same access rules. We don't need
178
- * to worry about this for oversized guests as MTTCG is disabled for
179
- * them.
180
+ * Called with tlb_lock held.
181
*/
182
-
183
-static void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, uintptr_t start,
184
- uintptr_t length)
185
+static void tlb_reset_dirty_range_locked(CPUTLBEntry *tlb_entry,
186
+ uintptr_t start, uintptr_t length)
187
{
188
-#if TCG_OVERSIZED_GUEST
189
uintptr_t addr = tlb_entry->addr_write;
190
191
if ((addr & (TLB_INVALID_MASK | TLB_MMIO | TLB_NOTDIRTY)) == 0) {
192
addr &= TARGET_PAGE_MASK;
193
addr += tlb_entry->addend;
194
if ((addr - start) < length) {
195
+#if TCG_OVERSIZED_GUEST
196
tlb_entry->addr_write |= TLB_NOTDIRTY;
197
- }
198
- }
199
#else
200
- /* paired with atomic_mb_set in tlb_set_page_with_attrs */
201
- uintptr_t orig_addr = atomic_mb_read(&tlb_entry->addr_write);
202
- uintptr_t addr = orig_addr;
203
-
204
- if ((addr & (TLB_INVALID_MASK | TLB_MMIO | TLB_NOTDIRTY)) == 0) {
205
- addr &= TARGET_PAGE_MASK;
206
- addr += atomic_read(&tlb_entry->addend);
207
- if ((addr - start) < length) {
208
- uintptr_t notdirty_addr = orig_addr | TLB_NOTDIRTY;
209
- atomic_cmpxchg(&tlb_entry->addr_write, orig_addr, notdirty_addr);
210
+ atomic_set(&tlb_entry->addr_write,
211
+ tlb_entry->addr_write | TLB_NOTDIRTY);
212
+#endif
213
}
214
}
215
-#endif
216
}
217
218
-/* For atomic correctness when running MTTCG we need to use the right
219
- * primitives when copying entries */
220
-static inline void copy_tlb_helper(CPUTLBEntry *d, CPUTLBEntry *s,
221
- bool atomic_set)
222
+/*
223
+ * Called with tlb_lock held.
224
+ * Called only from the vCPU context, i.e. the TLB's owner thread.
225
+ */
226
+static inline void copy_tlb_helper_locked(CPUTLBEntry *d, const CPUTLBEntry *s)
227
{
228
-#if TCG_OVERSIZED_GUEST
229
*d = *s;
230
-#else
231
- if (atomic_set) {
232
- d->addr_read = s->addr_read;
233
- d->addr_code = s->addr_code;
234
- atomic_set(&d->addend, atomic_read(&s->addend));
235
- /* Pairs with flag setting in tlb_reset_dirty_range */
236
- atomic_mb_set(&d->addr_write, atomic_read(&s->addr_write));
237
- } else {
238
- d->addr_read = s->addr_read;
239
- d->addr_write = atomic_read(&s->addr_write);
240
- d->addr_code = s->addr_code;
241
- d->addend = atomic_read(&s->addend);
242
- }
243
-#endif
244
}
245
246
/* This is a cross vCPU call (i.e. another vCPU resetting the flags of
247
- * the target vCPU). As such care needs to be taken that we don't
248
- * dangerously race with another vCPU update. The only thing actually
249
- * updated is the target TLB entry ->addr_write flags.
250
+ * the target vCPU).
251
+ * We must take tlb_lock to avoid racing with another vCPU update. The only
252
+ * thing actually updated is the target TLB entry ->addr_write flags.
253
*/
254
void tlb_reset_dirty(CPUState *cpu, ram_addr_t start1, ram_addr_t length)
255
{
256
@@ -XXX,XX +XXX,XX @@ void tlb_reset_dirty(CPUState *cpu, ram_addr_t start1, ram_addr_t length)
257
int mmu_idx;
258
259
env = cpu->env_ptr;
260
+ qemu_spin_lock(&env->tlb_lock);
261
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
262
unsigned int i;
263
264
for (i = 0; i < CPU_TLB_SIZE; i++) {
265
- tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
266
- start1, length);
267
+ tlb_reset_dirty_range_locked(&env->tlb_table[mmu_idx][i], start1,
268
+ length);
269
}
270
271
for (i = 0; i < CPU_VTLB_SIZE; i++) {
272
- tlb_reset_dirty_range(&env->tlb_v_table[mmu_idx][i],
273
- start1, length);
274
+ tlb_reset_dirty_range_locked(&env->tlb_v_table[mmu_idx][i], start1,
275
+ length);
276
}
277
}
278
+ qemu_spin_unlock(&env->tlb_lock);
279
}
280
281
-static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, target_ulong vaddr)
282
+/* Called with tlb_lock held */
283
+static inline void tlb_set_dirty1_locked(CPUTLBEntry *tlb_entry,
284
+ target_ulong vaddr)
285
{
286
if (tlb_entry->addr_write == (vaddr | TLB_NOTDIRTY)) {
287
tlb_entry->addr_write = vaddr;
288
@@ -XXX,XX +XXX,XX @@ void tlb_set_dirty(CPUState *cpu, target_ulong vaddr)
289
290
vaddr &= TARGET_PAGE_MASK;
291
i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
292
+ qemu_spin_lock(&env->tlb_lock);
293
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
294
- tlb_set_dirty1(&env->tlb_table[mmu_idx][i], vaddr);
295
+ tlb_set_dirty1_locked(&env->tlb_table[mmu_idx][i], vaddr);
296
}
297
298
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
299
int k;
300
for (k = 0; k < CPU_VTLB_SIZE; k++) {
301
- tlb_set_dirty1(&env->tlb_v_table[mmu_idx][k], vaddr);
302
+ tlb_set_dirty1_locked(&env->tlb_v_table[mmu_idx][k], vaddr);
303
}
304
}
305
+ qemu_spin_unlock(&env->tlb_lock);
306
}
307
308
/* Our TLB does not support large pages, so remember the area covered by
309
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
310
addend = (uintptr_t)memory_region_get_ram_ptr(section->mr) + xlat;
311
}
312
313
- /* Make sure there's no cached translation for the new page. */
314
- tlb_flush_vtlb_page(env, mmu_idx, vaddr_page);
315
-
316
code_address = address;
317
iotlb = memory_region_section_get_iotlb(cpu, section, vaddr_page,
318
paddr_page, xlat, prot, &address);
319
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
320
index = (vaddr_page >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
321
te = &env->tlb_table[mmu_idx][index];
322
323
+ /*
324
+ * Hold the TLB lock for the rest of the function. We could acquire/release
325
+ * the lock several times in the function, but it is faster to amortize the
326
+ * acquisition cost by acquiring it just once. Note that this leads to
327
+ * a longer critical section, but this is not a concern since the TLB lock
328
+ * is unlikely to be contended.
329
+ */
330
+ qemu_spin_lock(&env->tlb_lock);
331
+
332
+ /* Make sure there's no cached translation for the new page. */
333
+ tlb_flush_vtlb_page_locked(env, mmu_idx, vaddr_page);
334
+
335
/*
336
* Only evict the old entry to the victim tlb if it's for a
337
* different page; otherwise just overwrite the stale data.
338
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
339
CPUTLBEntry *tv = &env->tlb_v_table[mmu_idx][vidx];
340
341
/* Evict the old entry into the victim tlb. */
342
- copy_tlb_helper(tv, te, true);
343
+ copy_tlb_helper_locked(tv, te);
344
env->iotlb_v[mmu_idx][vidx] = env->iotlb[mmu_idx][index];
345
}
346
347
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
348
}
349
}
350
351
- /* Pairs with flag setting in tlb_reset_dirty_range */
352
- copy_tlb_helper(te, &tn, true);
353
- /* atomic_mb_set(&te->addr_write, write_address); */
354
+ copy_tlb_helper_locked(te, &tn);
355
+ qemu_spin_unlock(&env->tlb_lock);
356
}
357
358
/* Add a new TLB entry, but without specifying the memory
359
@@ -XXX,XX +XXX,XX @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
360
size_t elt_ofs, target_ulong page)
361
{
362
size_t vidx;
363
+
364
+ assert_cpu_is_self(ENV_GET_CPU(env));
365
for (vidx = 0; vidx < CPU_VTLB_SIZE; ++vidx) {
366
CPUTLBEntry *vtlb = &env->tlb_v_table[mmu_idx][vidx];
367
target_ulong cmp = *(target_ulong *)((uintptr_t)vtlb + elt_ofs);
368
@@ -XXX,XX +XXX,XX @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
369
/* Found entry in victim tlb, swap tlb and iotlb. */
370
CPUTLBEntry tmptlb, *tlb = &env->tlb_table[mmu_idx][index];
371
372
- copy_tlb_helper(&tmptlb, tlb, false);
373
- copy_tlb_helper(tlb, vtlb, true);
374
- copy_tlb_helper(vtlb, &tmptlb, true);
375
+ qemu_spin_lock(&env->tlb_lock);
376
+ copy_tlb_helper_locked(&tmptlb, tlb);
377
+ copy_tlb_helper_locked(tlb, vtlb);
378
+ copy_tlb_helper_locked(vtlb, &tmptlb);
379
+ qemu_spin_unlock(&env->tlb_lock);
380
381
CPUIOTLBEntry tmpio, *io = &env->iotlb[mmu_idx][index];
382
CPUIOTLBEntry *vio = &env->iotlb_v[mmu_idx][vidx];
383
--
384
2.17.2
385
386
diff view generated by jsdifflib
1
These functions are much closer to the softmmu helper
1
Isolate the computation of an index from an address into a
2
functions, in that they take the complete MemOpIdx,
2
helper before we change that function.
3
and from that they may enforce required alignment.
4
3
5
The previous cpu_ldst.h functions did not have alignment info,
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
and so did not enforce it. Retain this by adding MO_UNALN to
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
the MemOp that we create in calling the new functions.
6
[ cota: convert tlb_vaddr_to_host; use atomic_read on addr_write ]
7
Signed-off-by: Emilio G. Cota <cota@braap.org>
8
Message-Id: <20181009175129.17888-2-cota@braap.org>
9
---
10
accel/tcg/softmmu_template.h | 64 +++++++++++++++++---------------
11
include/exec/cpu_ldst.h | 19 ++++++++--
12
include/exec/cpu_ldst_template.h | 25 +++++++------
13
accel/tcg/cputlb.c | 60 ++++++++++++++----------------
14
4 files changed, 90 insertions(+), 78 deletions(-)
8
15
9
Note that we are not yet enforcing alignment for user-only,
16
diff --git a/accel/tcg/softmmu_template.h b/accel/tcg/softmmu_template.h
10
but we now have the information with which to do so.
11
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
---
15
docs/devel/loads-stores.rst | 52 ++++-
16
include/exec/cpu_ldst.h | 245 ++++++++--------------
17
accel/tcg/cputlb.c | 392 ++++++++++++------------------------
18
accel/tcg/user-exec.c | 385 +++++++++++++++--------------------
19
accel/tcg/ldst_common.c.inc | 307 ++++++++++++++++++++++++++++
20
5 files changed, 717 insertions(+), 664 deletions(-)
21
create mode 100644 accel/tcg/ldst_common.c.inc
22
23
diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
24
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
25
--- a/docs/devel/loads-stores.rst
18
--- a/accel/tcg/softmmu_template.h
26
+++ b/docs/devel/loads-stores.rst
19
+++ b/accel/tcg/softmmu_template.h
27
@@ -XXX,XX +XXX,XX @@ Regexes for git grep
20
@@ -XXX,XX +XXX,XX @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
28
- ``\<ldn_\([hbl]e\)?_p\>``
21
WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr,
29
- ``\<stn_\([hbl]e\)?_p\>``
22
TCGMemOpIdx oi, uintptr_t retaddr)
30
23
{
31
-``cpu_{ld,st}*_mmuidx_ra``
24
- unsigned mmu_idx = get_mmuidx(oi);
32
-~~~~~~~~~~~~~~~~~~~~~~~~~~
25
- int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
33
+``cpu_{ld,st}*_mmu``
26
- target_ulong tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
34
+~~~~~~~~~~~~~~~~~~~~
27
+ uintptr_t mmu_idx = get_mmuidx(oi);
35
28
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
36
-These functions operate on a guest virtual address plus a context,
29
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
37
-known as a "mmu index" or ``mmuidx``, which controls how that virtual
30
+ target_ulong tlb_addr = entry->ADDR_READ;
38
-address is translated. The meaning of the indexes are target specific,
31
unsigned a_bits = get_alignment_bits(get_memop(oi));
39
-but specifying a particular index might be necessary if, for instance,
32
uintptr_t haddr;
40
-the helper requires an "always as non-privileged" access rather that
33
DATA_TYPE res;
41
-the default access for the current state of the guest CPU.
34
@@ -XXX,XX +XXX,XX @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr,
42
+These functions operate on a guest virtual address, plus a context
35
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, READ_ACCESS_TYPE,
43
+known as a "mmu index" which controls how that virtual address is
36
mmu_idx, retaddr);
44
+translated, plus a ``MemOp`` which contains alignment requirements
37
}
45
+among other things. The ``MemOp`` and mmu index are combined into
38
- tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
46
+a single argument of type ``MemOpIdx``.
39
+ tlb_addr = entry->ADDR_READ;
47
+
40
}
48
+The meaning of the indexes are target specific, but specifying a
41
49
+particular index might be necessary if, for instance, the helper
42
/* Handle an IO access. */
50
+requires a "always as non-privileged" access rather than the
43
@@ -XXX,XX +XXX,XX @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr,
51
+default access for the current state of the guest CPU.
44
return res;
52
45
}
53
These functions may cause a guest CPU exception to be taken
46
54
(e.g. for an alignment fault or MMU fault) which will result in
47
- haddr = addr + env->tlb_table[mmu_idx][index].addend;
55
@@ -XXX,XX +XXX,XX @@ function, which is a return address into the generated code [#gpc]_.
48
+ haddr = addr + entry->addend;
56
49
#if DATA_SIZE == 1
57
Function names follow the pattern:
50
res = glue(glue(ld, LSUFFIX), _p)((uint8_t *)haddr);
58
51
#else
59
+load: ``cpu_ld{size}{end}_mmu(env, ptr, oi, retaddr)``
52
@@ -XXX,XX +XXX,XX @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr,
60
+
53
WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr,
61
+store: ``cpu_st{size}{end}_mmu(env, ptr, val, oi, retaddr)``
54
TCGMemOpIdx oi, uintptr_t retaddr)
62
+
55
{
63
+``size``
56
- unsigned mmu_idx = get_mmuidx(oi);
64
+ - ``b`` : 8 bits
57
- int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
65
+ - ``w`` : 16 bits
58
- target_ulong tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
66
+ - ``l`` : 32 bits
59
+ uintptr_t mmu_idx = get_mmuidx(oi);
67
+ - ``q`` : 64 bits
60
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
68
+
61
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
69
+``end``
62
+ target_ulong tlb_addr = entry->ADDR_READ;
70
+ - (empty) : for target endian, or 8 bit sizes
63
unsigned a_bits = get_alignment_bits(get_memop(oi));
71
+ - ``_be`` : big endian
64
uintptr_t haddr;
72
+ - ``_le`` : little endian
65
DATA_TYPE res;
73
+
66
@@ -XXX,XX +XXX,XX @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr,
74
+Regexes for git grep:
67
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, READ_ACCESS_TYPE,
75
+ - ``\<cpu_ld[bwlq](_[bl]e)\?_mmu\>``
68
mmu_idx, retaddr);
76
+ - ``\<cpu_st[bwlq](_[bl]e)\?_mmu\>``
69
}
77
+
70
- tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
78
+
71
+ tlb_addr = entry->ADDR_READ;
79
+``cpu_{ld,st}*_mmuidx_ra``
72
}
80
+~~~~~~~~~~~~~~~~~~~~~~~~~~
73
81
+
74
/* Handle an IO access. */
82
+These functions work like the ``cpu_{ld,st}_mmu`` functions except
75
@@ -XXX,XX +XXX,XX @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr,
83
+that the ``mmuidx`` parameter is not combined with a ``MemOp``,
76
return res;
84
+and therefore there is no required alignment supplied or enforced.
77
}
85
+
78
86
+Function names follow the pattern:
79
- haddr = addr + env->tlb_table[mmu_idx][index].addend;
87
+
80
+ haddr = addr + entry->addend;
88
load: ``cpu_ld{sign}{size}{end}_mmuidx_ra(env, ptr, mmuidx, retaddr)``
81
res = glue(glue(ld, LSUFFIX), _be_p)((uint8_t *)haddr);
89
82
return res;
90
store: ``cpu_st{size}{end}_mmuidx_ra(env, ptr, val, mmuidx, retaddr)``
83
}
91
@@ -XXX,XX +XXX,XX @@ of the guest CPU, as determined by ``cpu_mmu_index(env, false)``.
84
@@ -XXX,XX +XXX,XX @@ static inline void glue(io_write, SUFFIX)(CPUArchState *env,
92
85
void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
93
These are generally the preferred way to do accesses by guest
86
TCGMemOpIdx oi, uintptr_t retaddr)
94
virtual address from helper functions, unless the access should
87
{
95
-be performed with a context other than the default.
88
- unsigned mmu_idx = get_mmuidx(oi);
96
+be performed with a context other than the default, or alignment
89
- int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
97
+should be enforced for the access.
90
- target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
98
91
+ uintptr_t mmu_idx = get_mmuidx(oi);
99
Function names follow the pattern:
92
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
100
93
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
94
+ target_ulong tlb_addr = entry->addr_write;
95
unsigned a_bits = get_alignment_bits(get_memop(oi));
96
uintptr_t haddr;
97
98
@@ -XXX,XX +XXX,XX @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
99
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE,
100
mmu_idx, retaddr);
101
}
102
- tlb_addr = env->tlb_table[mmu_idx][index].addr_write & ~TLB_INVALID_MASK;
103
+ tlb_addr = entry->addr_write & ~TLB_INVALID_MASK;
104
}
105
106
/* Handle an IO access. */
107
@@ -XXX,XX +XXX,XX @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
108
if (DATA_SIZE > 1
109
&& unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
110
>= TARGET_PAGE_SIZE)) {
111
- int i, index2;
112
- target_ulong page2, tlb_addr2;
113
+ int i;
114
+ target_ulong page2;
115
+ CPUTLBEntry *entry2;
116
do_unaligned_access:
117
/* Ensure the second page is in the TLB. Note that the first page
118
is already guaranteed to be filled, and that the second page
119
cannot evict the first. */
120
page2 = (addr + DATA_SIZE) & TARGET_PAGE_MASK;
121
- index2 = (page2 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
122
- tlb_addr2 = env->tlb_table[mmu_idx][index2].addr_write;
123
- if (!tlb_hit_page(tlb_addr2, page2)
124
+ entry2 = tlb_entry(env, mmu_idx, page2);
125
+ if (!tlb_hit_page(entry2->addr_write, page2)
126
&& !VICTIM_TLB_HIT(addr_write, page2)) {
127
tlb_fill(ENV_GET_CPU(env), page2, DATA_SIZE, MMU_DATA_STORE,
128
mmu_idx, retaddr);
129
@@ -XXX,XX +XXX,XX @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
130
return;
131
}
132
133
- haddr = addr + env->tlb_table[mmu_idx][index].addend;
134
+ haddr = addr + entry->addend;
135
#if DATA_SIZE == 1
136
glue(glue(st, SUFFIX), _p)((uint8_t *)haddr, val);
137
#else
138
@@ -XXX,XX +XXX,XX @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
139
void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
140
TCGMemOpIdx oi, uintptr_t retaddr)
141
{
142
- unsigned mmu_idx = get_mmuidx(oi);
143
- int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
144
- target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
145
+ uintptr_t mmu_idx = get_mmuidx(oi);
146
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
147
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
148
+ target_ulong tlb_addr = entry->addr_write;
149
unsigned a_bits = get_alignment_bits(get_memop(oi));
150
uintptr_t haddr;
151
152
@@ -XXX,XX +XXX,XX @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
153
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE,
154
mmu_idx, retaddr);
155
}
156
- tlb_addr = env->tlb_table[mmu_idx][index].addr_write & ~TLB_INVALID_MASK;
157
+ tlb_addr = entry->addr_write & ~TLB_INVALID_MASK;
158
}
159
160
/* Handle an IO access. */
161
@@ -XXX,XX +XXX,XX @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
162
if (DATA_SIZE > 1
163
&& unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
164
>= TARGET_PAGE_SIZE)) {
165
- int i, index2;
166
- target_ulong page2, tlb_addr2;
167
+ int i;
168
+ target_ulong page2;
169
+ CPUTLBEntry *entry2;
170
do_unaligned_access:
171
/* Ensure the second page is in the TLB. Note that the first page
172
is already guaranteed to be filled, and that the second page
173
cannot evict the first. */
174
page2 = (addr + DATA_SIZE) & TARGET_PAGE_MASK;
175
- index2 = (page2 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
176
- tlb_addr2 = env->tlb_table[mmu_idx][index2].addr_write;
177
- if (!tlb_hit_page(tlb_addr2, page2)
178
+ entry2 = tlb_entry(env, mmu_idx, page2);
179
+ if (!tlb_hit_page(entry2->addr_write, page2)
180
&& !VICTIM_TLB_HIT(addr_write, page2)) {
181
tlb_fill(ENV_GET_CPU(env), page2, DATA_SIZE, MMU_DATA_STORE,
182
mmu_idx, retaddr);
183
@@ -XXX,XX +XXX,XX @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
184
return;
185
}
186
187
- haddr = addr + env->tlb_table[mmu_idx][index].addend;
188
+ haddr = addr + entry->addend;
189
glue(glue(st, SUFFIX), _be_p)((uint8_t *)haddr, val);
190
}
191
#endif /* DATA_SIZE > 1 */
101
diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
192
diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
102
index XXXXXXX..XXXXXXX 100644
193
index XXXXXXX..XXXXXXX 100644
103
--- a/include/exec/cpu_ldst.h
194
--- a/include/exec/cpu_ldst.h
104
+++ b/include/exec/cpu_ldst.h
195
+++ b/include/exec/cpu_ldst.h
105
@@ -XXX,XX +XXX,XX @@
196
@@ -XXX,XX +XXX,XX @@ extern __thread uintptr_t helper_retaddr;
106
* load: cpu_ld{sign}{size}{end}_{mmusuffix}(env, ptr)
197
/* The memory helpers for tcg-generated code need tcg_target_long etc. */
107
* cpu_ld{sign}{size}{end}_{mmusuffix}_ra(env, ptr, retaddr)
198
#include "tcg.h"
108
* cpu_ld{sign}{size}{end}_mmuidx_ra(env, ptr, mmu_idx, retaddr)
199
109
+ * cpu_ld{sign}{size}{end}_mmu(env, ptr, oi, retaddr)
200
+/* Find the TLB index corresponding to the mmu_idx + address pair. */
110
*
201
+static inline uintptr_t tlb_index(CPUArchState *env, uintptr_t mmu_idx,
111
* store: cpu_st{size}{end}_{mmusuffix}(env, ptr, val)
202
+ target_ulong addr)
112
* cpu_st{size}{end}_{mmusuffix}_ra(env, ptr, val, retaddr)
203
+{
113
* cpu_st{size}{end}_mmuidx_ra(env, ptr, val, mmu_idx, retaddr)
204
+ return (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
114
+ * cpu_st{size}{end}_mmu(env, ptr, val, oi, retaddr)
205
+}
115
*
116
* sign is:
117
* (empty): for 32 and 64 bit sizes
118
@@ -XXX,XX +XXX,XX @@
119
* The "mmuidx" suffix carries an extra mmu_idx argument that specifies
120
* the index to use; the "data" and "code" suffixes take the index from
121
* cpu_mmu_index().
122
+ *
123
+ * The "mmu" suffix carries the full MemOpIdx, with both mmu_idx and the
124
+ * MemOp including alignment requirements. The alignment will be enforced.
125
*/
126
#ifndef CPU_LDST_H
127
#define CPU_LDST_H
128
129
+#include "exec/memopidx.h"
130
+
206
+
207
+/* Find the TLB entry corresponding to the mmu_idx + address pair. */
208
+static inline CPUTLBEntry *tlb_entry(CPUArchState *env, uintptr_t mmu_idx,
209
+ target_ulong addr)
210
+{
211
+ return &env->tlb_table[mmu_idx][tlb_index(env, mmu_idx, addr)];
212
+}
213
+
214
#ifdef MMU_MODE0_SUFFIX
215
#define CPU_MMU_INDEX 0
216
#define MEMSUFFIX MMU_MODE0_SUFFIX
217
@@ -XXX,XX +XXX,XX @@ static inline void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
131
#if defined(CONFIG_USER_ONLY)
218
#if defined(CONFIG_USER_ONLY)
132
/* sparc32plus has 64bit long but 32bit space address
219
return g2h(addr);
133
* this can make bad result with g2h() and h2g()
220
#else
134
@@ -XXX,XX +XXX,XX @@ typedef target_ulong abi_ptr;
221
- int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
135
222
- CPUTLBEntry *tlbentry = &env->tlb_table[mmu_idx][index];
136
uint32_t cpu_ldub_data(CPUArchState *env, abi_ptr ptr);
223
+ CPUTLBEntry *tlbentry = tlb_entry(env, mmu_idx, addr);
137
int cpu_ldsb_data(CPUArchState *env, abi_ptr ptr);
224
abi_ptr tlb_addr;
138
-
225
uintptr_t haddr;
139
uint32_t cpu_lduw_be_data(CPUArchState *env, abi_ptr ptr);
226
140
int cpu_ldsw_be_data(CPUArchState *env, abi_ptr ptr);
227
@@ -XXX,XX +XXX,XX @@ static inline void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
141
uint32_t cpu_ldl_be_data(CPUArchState *env, abi_ptr ptr);
228
return NULL;
142
uint64_t cpu_ldq_be_data(CPUArchState *env, abi_ptr ptr);
229
}
143
-
230
144
uint32_t cpu_lduw_le_data(CPUArchState *env, abi_ptr ptr);
231
- haddr = addr + env->tlb_table[mmu_idx][index].addend;
145
int cpu_ldsw_le_data(CPUArchState *env, abi_ptr ptr);
232
+ haddr = addr + tlbentry->addend;
146
uint32_t cpu_ldl_le_data(CPUArchState *env, abi_ptr ptr);
233
return (void *)haddr;
147
@@ -XXX,XX +XXX,XX @@ uint64_t cpu_ldq_le_data(CPUArchState *env, abi_ptr ptr);
234
#endif /* defined(CONFIG_USER_ONLY) */
148
149
uint32_t cpu_ldub_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra);
150
int cpu_ldsb_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra);
151
-
152
uint32_t cpu_lduw_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra);
153
int cpu_ldsw_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra);
154
uint32_t cpu_ldl_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra);
155
uint64_t cpu_ldq_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra);
156
-
157
uint32_t cpu_lduw_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra);
158
int cpu_ldsw_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra);
159
uint32_t cpu_ldl_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra);
160
uint64_t cpu_ldq_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra);
161
162
void cpu_stb_data(CPUArchState *env, abi_ptr ptr, uint32_t val);
163
-
164
void cpu_stw_be_data(CPUArchState *env, abi_ptr ptr, uint32_t val);
165
void cpu_stl_be_data(CPUArchState *env, abi_ptr ptr, uint32_t val);
166
void cpu_stq_be_data(CPUArchState *env, abi_ptr ptr, uint64_t val);
167
-
168
void cpu_stw_le_data(CPUArchState *env, abi_ptr ptr, uint32_t val);
169
void cpu_stl_le_data(CPUArchState *env, abi_ptr ptr, uint32_t val);
170
void cpu_stq_le_data(CPUArchState *env, abi_ptr ptr, uint64_t val);
171
172
void cpu_stb_data_ra(CPUArchState *env, abi_ptr ptr,
173
uint32_t val, uintptr_t ra);
174
-
175
void cpu_stw_be_data_ra(CPUArchState *env, abi_ptr ptr,
176
uint32_t val, uintptr_t ra);
177
void cpu_stl_be_data_ra(CPUArchState *env, abi_ptr ptr,
178
uint32_t val, uintptr_t ra);
179
void cpu_stq_be_data_ra(CPUArchState *env, abi_ptr ptr,
180
uint64_t val, uintptr_t ra);
181
-
182
void cpu_stw_le_data_ra(CPUArchState *env, abi_ptr ptr,
183
uint32_t val, uintptr_t ra);
184
void cpu_stl_le_data_ra(CPUArchState *env, abi_ptr ptr,
185
@@ -XXX,XX +XXX,XX @@ void cpu_stl_le_data_ra(CPUArchState *env, abi_ptr ptr,
186
void cpu_stq_le_data_ra(CPUArchState *env, abi_ptr ptr,
187
uint64_t val, uintptr_t ra);
188
189
+uint32_t cpu_ldub_mmuidx_ra(CPUArchState *env, abi_ptr ptr,
190
+ int mmu_idx, uintptr_t ra);
191
+int cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr ptr,
192
+ int mmu_idx, uintptr_t ra);
193
+uint32_t cpu_lduw_be_mmuidx_ra(CPUArchState *env, abi_ptr ptr,
194
+ int mmu_idx, uintptr_t ra);
195
+int cpu_ldsw_be_mmuidx_ra(CPUArchState *env, abi_ptr ptr,
196
+ int mmu_idx, uintptr_t ra);
197
+uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr ptr,
198
+ int mmu_idx, uintptr_t ra);
199
+uint64_t cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr ptr,
200
+ int mmu_idx, uintptr_t ra);
201
+uint32_t cpu_lduw_le_mmuidx_ra(CPUArchState *env, abi_ptr ptr,
202
+ int mmu_idx, uintptr_t ra);
203
+int cpu_ldsw_le_mmuidx_ra(CPUArchState *env, abi_ptr ptr,
204
+ int mmu_idx, uintptr_t ra);
205
+uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr ptr,
206
+ int mmu_idx, uintptr_t ra);
207
+uint64_t cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr ptr,
208
+ int mmu_idx, uintptr_t ra);
209
+
210
+void cpu_stb_mmuidx_ra(CPUArchState *env, abi_ptr ptr, uint32_t val,
211
+ int mmu_idx, uintptr_t ra);
212
+void cpu_stw_be_mmuidx_ra(CPUArchState *env, abi_ptr ptr, uint32_t val,
213
+ int mmu_idx, uintptr_t ra);
214
+void cpu_stl_be_mmuidx_ra(CPUArchState *env, abi_ptr ptr, uint32_t val,
215
+ int mmu_idx, uintptr_t ra);
216
+void cpu_stq_be_mmuidx_ra(CPUArchState *env, abi_ptr ptr, uint64_t val,
217
+ int mmu_idx, uintptr_t ra);
218
+void cpu_stw_le_mmuidx_ra(CPUArchState *env, abi_ptr ptr, uint32_t val,
219
+ int mmu_idx, uintptr_t ra);
220
+void cpu_stl_le_mmuidx_ra(CPUArchState *env, abi_ptr ptr, uint32_t val,
221
+ int mmu_idx, uintptr_t ra);
222
+void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr ptr, uint64_t val,
223
+ int mmu_idx, uintptr_t ra);
224
+
225
+uint8_t cpu_ldb_mmu(CPUArchState *env, abi_ptr ptr, MemOpIdx oi, uintptr_t ra);
226
+uint16_t cpu_ldw_be_mmu(CPUArchState *env, abi_ptr ptr,
227
+ MemOpIdx oi, uintptr_t ra);
228
+uint32_t cpu_ldl_be_mmu(CPUArchState *env, abi_ptr ptr,
229
+ MemOpIdx oi, uintptr_t ra);
230
+uint64_t cpu_ldq_be_mmu(CPUArchState *env, abi_ptr ptr,
231
+ MemOpIdx oi, uintptr_t ra);
232
+uint16_t cpu_ldw_le_mmu(CPUArchState *env, abi_ptr ptr,
233
+ MemOpIdx oi, uintptr_t ra);
234
+uint32_t cpu_ldl_le_mmu(CPUArchState *env, abi_ptr ptr,
235
+ MemOpIdx oi, uintptr_t ra);
236
+uint64_t cpu_ldq_le_mmu(CPUArchState *env, abi_ptr ptr,
237
+ MemOpIdx oi, uintptr_t ra);
238
+
239
+void cpu_stb_mmu(CPUArchState *env, abi_ptr ptr, uint8_t val,
240
+ MemOpIdx oi, uintptr_t ra);
241
+void cpu_stw_be_mmu(CPUArchState *env, abi_ptr ptr, uint16_t val,
242
+ MemOpIdx oi, uintptr_t ra);
243
+void cpu_stl_be_mmu(CPUArchState *env, abi_ptr ptr, uint32_t val,
244
+ MemOpIdx oi, uintptr_t ra);
245
+void cpu_stq_be_mmu(CPUArchState *env, abi_ptr ptr, uint64_t val,
246
+ MemOpIdx oi, uintptr_t ra);
247
+void cpu_stw_le_mmu(CPUArchState *env, abi_ptr ptr, uint16_t val,
248
+ MemOpIdx oi, uintptr_t ra);
249
+void cpu_stl_le_mmu(CPUArchState *env, abi_ptr ptr, uint32_t val,
250
+ MemOpIdx oi, uintptr_t ra);
251
+void cpu_stq_le_mmu(CPUArchState *env, abi_ptr ptr, uint64_t val,
252
+ MemOpIdx oi, uintptr_t ra);
253
+
254
#if defined(CONFIG_USER_ONLY)
255
256
extern __thread uintptr_t helper_retaddr;
257
@@ -XXX,XX +XXX,XX @@ static inline void clear_helper_retaddr(void)
258
helper_retaddr = 0;
259
}
235
}
260
236
diff --git a/include/exec/cpu_ldst_template.h b/include/exec/cpu_ldst_template.h
261
-/*
237
index XXXXXXX..XXXXXXX 100644
262
- * Provide the same *_mmuidx_ra interface as for softmmu.
238
--- a/include/exec/cpu_ldst_template.h
263
- * The mmu_idx argument is ignored.
239
+++ b/include/exec/cpu_ldst_template.h
264
- */
240
@@ -XXX,XX +XXX,XX @@ glue(glue(glue(cpu_ld, USUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
265
-
241
target_ulong ptr,
266
-static inline uint32_t cpu_ldub_mmuidx_ra(CPUArchState *env, abi_ptr addr,
242
uintptr_t retaddr)
267
- int mmu_idx, uintptr_t ra)
243
{
268
-{
244
- int page_index;
269
- return cpu_ldub_data_ra(env, addr, ra);
245
+ CPUTLBEntry *entry;
270
-}
246
RES_TYPE res;
271
-
247
target_ulong addr;
272
-static inline int cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr addr,
248
int mmu_idx;
273
- int mmu_idx, uintptr_t ra)
249
@@ -XXX,XX +XXX,XX @@ glue(glue(glue(cpu_ld, USUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
274
-{
250
#endif
275
- return cpu_ldsb_data_ra(env, addr, ra);
251
276
-}
252
addr = ptr;
277
-
253
- page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
278
-static inline uint32_t cpu_lduw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
254
mmu_idx = CPU_MMU_INDEX;
279
- int mmu_idx, uintptr_t ra)
255
- if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
280
-{
256
+ entry = tlb_entry(env, mmu_idx, addr);
281
- return cpu_lduw_be_data_ra(env, addr, ra);
257
+ if (unlikely(entry->ADDR_READ !=
282
-}
258
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
283
-
259
oi = make_memop_idx(SHIFT, mmu_idx);
284
-static inline int cpu_ldsw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
260
res = glue(glue(helper_ret_ld, URETSUFFIX), MMUSUFFIX)(env, addr,
285
- int mmu_idx, uintptr_t ra)
261
oi, retaddr);
286
-{
262
} else {
287
- return cpu_ldsw_be_data_ra(env, addr, ra);
263
- uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
288
-}
264
+ uintptr_t hostaddr = addr + entry->addend;
289
-
265
res = glue(glue(ld, USUFFIX), _p)((uint8_t *)hostaddr);
290
-static inline uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
266
}
291
- int mmu_idx, uintptr_t ra)
267
return res;
292
-{
268
@@ -XXX,XX +XXX,XX @@ glue(glue(glue(cpu_lds, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
293
- return cpu_ldl_be_data_ra(env, addr, ra);
269
target_ulong ptr,
294
-}
270
uintptr_t retaddr)
295
-
271
{
296
-static inline uint64_t cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
272
- int res, page_index;
297
- int mmu_idx, uintptr_t ra)
273
+ CPUTLBEntry *entry;
298
-{
274
+ int res;
299
- return cpu_ldq_be_data_ra(env, addr, ra);
275
target_ulong addr;
300
-}
276
int mmu_idx;
301
-
277
TCGMemOpIdx oi;
302
-static inline uint32_t cpu_lduw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
278
@@ -XXX,XX +XXX,XX @@ glue(glue(glue(cpu_lds, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
303
- int mmu_idx, uintptr_t ra)
279
#endif
304
-{
280
305
- return cpu_lduw_le_data_ra(env, addr, ra);
281
addr = ptr;
306
-}
282
- page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
307
-
283
mmu_idx = CPU_MMU_INDEX;
308
-static inline int cpu_ldsw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
284
- if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
309
- int mmu_idx, uintptr_t ra)
285
+ entry = tlb_entry(env, mmu_idx, addr);
310
-{
286
+ if (unlikely(entry->ADDR_READ !=
311
- return cpu_ldsw_le_data_ra(env, addr, ra);
287
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
312
-}
288
oi = make_memop_idx(SHIFT, mmu_idx);
313
-
289
res = (DATA_STYPE)glue(glue(helper_ret_ld, SRETSUFFIX),
314
-static inline uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
290
MMUSUFFIX)(env, addr, oi, retaddr);
315
- int mmu_idx, uintptr_t ra)
291
} else {
316
-{
292
- uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
317
- return cpu_ldl_le_data_ra(env, addr, ra);
293
+ uintptr_t hostaddr = addr + entry->addend;
318
-}
294
res = glue(glue(lds, SUFFIX), _p)((uint8_t *)hostaddr);
319
-
295
}
320
-static inline uint64_t cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
296
return res;
321
- int mmu_idx, uintptr_t ra)
297
@@ -XXX,XX +XXX,XX @@ glue(glue(glue(cpu_st, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
322
-{
298
target_ulong ptr,
323
- return cpu_ldq_le_data_ra(env, addr, ra);
299
RES_TYPE v, uintptr_t retaddr)
324
-}
300
{
325
-
301
- int page_index;
326
-static inline void cpu_stb_mmuidx_ra(CPUArchState *env, abi_ptr addr,
302
+ CPUTLBEntry *entry;
327
- uint32_t val, int mmu_idx, uintptr_t ra)
303
target_ulong addr;
328
-{
304
int mmu_idx;
329
- cpu_stb_data_ra(env, addr, val, ra);
305
TCGMemOpIdx oi;
330
-}
306
@@ -XXX,XX +XXX,XX @@ glue(glue(glue(cpu_st, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
331
-
307
#endif
332
-static inline void cpu_stw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
308
333
- uint32_t val, int mmu_idx,
309
addr = ptr;
334
- uintptr_t ra)
310
- page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
335
-{
311
mmu_idx = CPU_MMU_INDEX;
336
- cpu_stw_be_data_ra(env, addr, val, ra);
312
- if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write !=
337
-}
313
+ entry = tlb_entry(env, mmu_idx, addr);
338
-
314
+ if (unlikely(entry->addr_write !=
339
-static inline void cpu_stl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
315
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
340
- uint32_t val, int mmu_idx,
316
oi = make_memop_idx(SHIFT, mmu_idx);
341
- uintptr_t ra)
317
glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)(env, addr, v, oi,
342
-{
318
retaddr);
343
- cpu_stl_be_data_ra(env, addr, val, ra);
319
} else {
344
-}
320
- uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
345
-
321
+ uintptr_t hostaddr = addr + entry->addend;
346
-static inline void cpu_stq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
322
glue(glue(st, SUFFIX), _p)((uint8_t *)hostaddr, v);
347
- uint64_t val, int mmu_idx,
323
}
348
- uintptr_t ra)
349
-{
350
- cpu_stq_be_data_ra(env, addr, val, ra);
351
-}
352
-
353
-static inline void cpu_stw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
354
- uint32_t val, int mmu_idx,
355
- uintptr_t ra)
356
-{
357
- cpu_stw_le_data_ra(env, addr, val, ra);
358
-}
359
-
360
-static inline void cpu_stl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
361
- uint32_t val, int mmu_idx,
362
- uintptr_t ra)
363
-{
364
- cpu_stl_le_data_ra(env, addr, val, ra);
365
-}
366
-
367
-static inline void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
368
- uint64_t val, int mmu_idx,
369
- uintptr_t ra)
370
-{
371
- cpu_stq_le_data_ra(env, addr, val, ra);
372
-}
373
-
374
#else
375
376
/* Needed for TCG_OVERSIZED_GUEST */
377
@@ -XXX,XX +XXX,XX @@ static inline CPUTLBEntry *tlb_entry(CPUArchState *env, uintptr_t mmu_idx,
378
return &env_tlb(env)->f[mmu_idx].table[tlb_index(env, mmu_idx, addr)];
379
}
324
}
380
381
-uint32_t cpu_ldub_mmuidx_ra(CPUArchState *env, abi_ptr addr,
382
- int mmu_idx, uintptr_t ra);
383
-int cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr addr,
384
- int mmu_idx, uintptr_t ra);
385
-
386
-uint32_t cpu_lduw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
387
- int mmu_idx, uintptr_t ra);
388
-int cpu_ldsw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
389
- int mmu_idx, uintptr_t ra);
390
-uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
391
- int mmu_idx, uintptr_t ra);
392
-uint64_t cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
393
- int mmu_idx, uintptr_t ra);
394
-
395
-uint32_t cpu_lduw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
396
- int mmu_idx, uintptr_t ra);
397
-int cpu_ldsw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
398
- int mmu_idx, uintptr_t ra);
399
-uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
400
- int mmu_idx, uintptr_t ra);
401
-uint64_t cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
402
- int mmu_idx, uintptr_t ra);
403
-
404
-void cpu_stb_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
405
- int mmu_idx, uintptr_t retaddr);
406
-
407
-void cpu_stw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
408
- int mmu_idx, uintptr_t retaddr);
409
-void cpu_stl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
410
- int mmu_idx, uintptr_t retaddr);
411
-void cpu_stq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
412
- int mmu_idx, uintptr_t retaddr);
413
-
414
-void cpu_stw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
415
- int mmu_idx, uintptr_t retaddr);
416
-void cpu_stl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
417
- int mmu_idx, uintptr_t retaddr);
418
-void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
419
- int mmu_idx, uintptr_t retaddr);
420
-
421
#endif /* defined(CONFIG_USER_ONLY) */
422
423
#ifdef TARGET_WORDS_BIGENDIAN
424
@@ -XXX,XX +XXX,XX @@ void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
425
# define cpu_ldsw_mmuidx_ra cpu_ldsw_be_mmuidx_ra
426
# define cpu_ldl_mmuidx_ra cpu_ldl_be_mmuidx_ra
427
# define cpu_ldq_mmuidx_ra cpu_ldq_be_mmuidx_ra
428
+# define cpu_ldw_mmu cpu_ldw_be_mmu
429
+# define cpu_ldl_mmu cpu_ldl_be_mmu
430
+# define cpu_ldq_mmu cpu_ldq_be_mmu
431
# define cpu_stw_data cpu_stw_be_data
432
# define cpu_stl_data cpu_stl_be_data
433
# define cpu_stq_data cpu_stq_be_data
434
@@ -XXX,XX +XXX,XX @@ void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
435
# define cpu_stw_mmuidx_ra cpu_stw_be_mmuidx_ra
436
# define cpu_stl_mmuidx_ra cpu_stl_be_mmuidx_ra
437
# define cpu_stq_mmuidx_ra cpu_stq_be_mmuidx_ra
438
+# define cpu_stw_mmu cpu_stw_be_mmu
439
+# define cpu_stl_mmu cpu_stl_be_mmu
440
+# define cpu_stq_mmu cpu_stq_be_mmu
441
#else
442
# define cpu_lduw_data cpu_lduw_le_data
443
# define cpu_ldsw_data cpu_ldsw_le_data
444
@@ -XXX,XX +XXX,XX @@ void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
445
# define cpu_ldsw_mmuidx_ra cpu_ldsw_le_mmuidx_ra
446
# define cpu_ldl_mmuidx_ra cpu_ldl_le_mmuidx_ra
447
# define cpu_ldq_mmuidx_ra cpu_ldq_le_mmuidx_ra
448
+# define cpu_ldw_mmu cpu_ldw_le_mmu
449
+# define cpu_ldl_mmu cpu_ldl_le_mmu
450
+# define cpu_ldq_mmu cpu_ldq_le_mmu
451
# define cpu_stw_data cpu_stw_le_data
452
# define cpu_stl_data cpu_stl_le_data
453
# define cpu_stq_data cpu_stq_le_data
454
@@ -XXX,XX +XXX,XX @@ void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
455
# define cpu_stw_mmuidx_ra cpu_stw_le_mmuidx_ra
456
# define cpu_stl_mmuidx_ra cpu_stl_le_mmuidx_ra
457
# define cpu_stq_mmuidx_ra cpu_stq_le_mmuidx_ra
458
+# define cpu_stw_mmu cpu_stw_le_mmu
459
+# define cpu_stl_mmu cpu_stl_le_mmu
460
+# define cpu_stq_mmu cpu_stq_le_mmu
461
#endif
462
463
uint32_t cpu_ldub_code(CPUArchState *env, abi_ptr addr);
464
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
325
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
465
index XXXXXXX..XXXXXXX 100644
326
index XXXXXXX..XXXXXXX 100644
466
--- a/accel/tcg/cputlb.c
327
--- a/accel/tcg/cputlb.c
467
+++ b/accel/tcg/cputlb.c
328
+++ b/accel/tcg/cputlb.c
329
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_page_async_work(CPUState *cpu, run_on_cpu_data data)
330
{
331
CPUArchState *env = cpu->env_ptr;
332
target_ulong addr = (target_ulong) data.target_ptr;
333
- int i;
334
int mmu_idx;
335
336
assert_cpu_is_self(cpu);
337
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_page_async_work(CPUState *cpu, run_on_cpu_data data)
338
}
339
340
addr &= TARGET_PAGE_MASK;
341
- i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
342
qemu_spin_lock(&env->tlb_lock);
343
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
344
- tlb_flush_entry_locked(&env->tlb_table[mmu_idx][i], addr);
345
+ tlb_flush_entry_locked(tlb_entry(env, mmu_idx, addr), addr);
346
tlb_flush_vtlb_page_locked(env, mmu_idx, addr);
347
}
348
qemu_spin_unlock(&env->tlb_lock);
349
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_page_by_mmuidx_async_work(CPUState *cpu,
350
target_ulong addr_and_mmuidx = (target_ulong) data.target_ptr;
351
target_ulong addr = addr_and_mmuidx & TARGET_PAGE_MASK;
352
unsigned long mmu_idx_bitmap = addr_and_mmuidx & ALL_MMUIDX_BITS;
353
- int page = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
354
int mmu_idx;
355
356
assert_cpu_is_self(cpu);
357
358
- tlb_debug("page:%d addr:"TARGET_FMT_lx" mmu_idx:0x%lx\n",
359
- page, addr, mmu_idx_bitmap);
360
+ tlb_debug("flush page addr:"TARGET_FMT_lx" mmu_idx:0x%lx\n",
361
+ addr, mmu_idx_bitmap);
362
363
qemu_spin_lock(&env->tlb_lock);
364
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
365
if (test_bit(mmu_idx, &mmu_idx_bitmap)) {
366
- tlb_flush_entry_locked(&env->tlb_table[mmu_idx][page], addr);
367
+ tlb_flush_entry_locked(tlb_entry(env, mmu_idx, addr), addr);
368
tlb_flush_vtlb_page_locked(env, mmu_idx, addr);
369
}
370
}
371
@@ -XXX,XX +XXX,XX @@ static inline void tlb_set_dirty1_locked(CPUTLBEntry *tlb_entry,
372
void tlb_set_dirty(CPUState *cpu, target_ulong vaddr)
373
{
374
CPUArchState *env = cpu->env_ptr;
375
- int i;
376
int mmu_idx;
377
378
assert_cpu_is_self(cpu);
379
380
vaddr &= TARGET_PAGE_MASK;
381
- i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
382
qemu_spin_lock(&env->tlb_lock);
383
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
384
- tlb_set_dirty1_locked(&env->tlb_table[mmu_idx][i], vaddr);
385
+ tlb_set_dirty1_locked(tlb_entry(env, mmu_idx, vaddr), vaddr);
386
}
387
388
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
389
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
390
iotlb = memory_region_section_get_iotlb(cpu, section, vaddr_page,
391
paddr_page, xlat, prot, &address);
392
393
- index = (vaddr_page >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
394
- te = &env->tlb_table[mmu_idx][index];
395
+ index = tlb_index(env, mmu_idx, vaddr_page);
396
+ te = tlb_entry(env, mmu_idx, vaddr_page);
397
398
/*
399
* Hold the TLB lock for the rest of the function. We could acquire/release
400
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
401
* repeat the MMU check here. This tlb_fill() call might
402
* longjump out if this access should cause a guest exception.
403
*/
404
- int index;
405
+ CPUTLBEntry *entry;
406
target_ulong tlb_addr;
407
408
tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
409
410
- index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
411
- tlb_addr = env->tlb_table[mmu_idx][index].addr_read;
412
+ entry = tlb_entry(env, mmu_idx, addr);
413
+ tlb_addr = entry->addr_read;
414
if (!(tlb_addr & ~(TARGET_PAGE_MASK | TLB_RECHECK))) {
415
/* RAM access */
416
- uintptr_t haddr = addr + env->tlb_table[mmu_idx][index].addend;
417
+ uintptr_t haddr = addr + entry->addend;
418
419
return ldn_p((void *)haddr, size);
420
}
421
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
422
* repeat the MMU check here. This tlb_fill() call might
423
* longjump out if this access should cause a guest exception.
424
*/
425
- int index;
426
+ CPUTLBEntry *entry;
427
target_ulong tlb_addr;
428
429
tlb_fill(cpu, addr, size, MMU_DATA_STORE, mmu_idx, retaddr);
430
431
- index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
432
- tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
433
+ entry = tlb_entry(env, mmu_idx, addr);
434
+ tlb_addr = entry->addr_write;
435
if (!(tlb_addr & ~(TARGET_PAGE_MASK | TLB_RECHECK))) {
436
/* RAM access */
437
- uintptr_t haddr = addr + env->tlb_table[mmu_idx][index].addend;
438
+ uintptr_t haddr = addr + entry->addend;
439
440
stn_p((void *)haddr, size, val);
441
return;
442
@@ -XXX,XX +XXX,XX @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
443
*/
444
tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
445
{
446
- int mmu_idx, index;
447
+ uintptr_t mmu_idx = cpu_mmu_index(env, true);
448
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
449
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
450
void *p;
451
452
- index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
453
- mmu_idx = cpu_mmu_index(env, true);
454
- if (unlikely(!tlb_hit(env->tlb_table[mmu_idx][index].addr_code, addr))) {
455
+ if (unlikely(!tlb_hit(entry->addr_code, addr))) {
456
if (!VICTIM_TLB_HIT(addr_code, addr)) {
457
tlb_fill(ENV_GET_CPU(env), addr, 0, MMU_INST_FETCH, mmu_idx, 0);
458
}
459
- assert(tlb_hit(env->tlb_table[mmu_idx][index].addr_code, addr));
460
+ assert(tlb_hit(entry->addr_code, addr));
461
}
462
463
- if (unlikely(env->tlb_table[mmu_idx][index].addr_code &
464
- (TLB_RECHECK | TLB_MMIO))) {
465
+ if (unlikely(entry->addr_code & (TLB_RECHECK | TLB_MMIO))) {
466
/*
467
* Return -1 if we can't translate and execute from an entire
468
* page of RAM here, which will cause us to execute by loading
469
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
470
return -1;
471
}
472
473
- p = (void *)((uintptr_t)addr + env->tlb_table[mmu_idx][index].addend);
474
+ p = (void *)((uintptr_t)addr + entry->addend);
475
return qemu_ram_addr_from_host_nofail(p);
476
}
477
478
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
479
void probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx,
480
uintptr_t retaddr)
481
{
482
- int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
483
- target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
484
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
485
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
486
487
- if (!tlb_hit(tlb_addr, addr)) {
488
+ if (!tlb_hit(entry->addr_write, addr)) {
489
/* TLB entry is for a different page */
490
if (!VICTIM_TLB_HIT(addr_write, addr)) {
491
tlb_fill(ENV_GET_CPU(env), addr, size, MMU_DATA_STORE,
468
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
492
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
469
cpu_loop_exit_atomic(env_cpu(env), retaddr);
493
NotDirtyInfo *ndi)
470
}
494
{
471
495
size_t mmu_idx = get_mmuidx(oi);
472
+/*
496
- size_t index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
473
+ * Verify that we have passed the correct MemOp to the correct function.
497
- CPUTLBEntry *tlbe = &env->tlb_table[mmu_idx][index];
474
+ *
498
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
475
+ * In the case of the helper_*_mmu functions, we will have done this by
499
+ CPUTLBEntry *tlbe = tlb_entry(env, mmu_idx, addr);
476
+ * using the MemOp to look up the helper during code generation.
500
target_ulong tlb_addr = tlbe->addr_write;
477
+ *
501
TCGMemOp mop = get_memop(oi);
478
+ * In the case of the cpu_*_mmu functions, this is up to the caller.
502
int a_bits = get_alignment_bits(mop);
479
+ * We could present one function to target code, and dispatch based on
480
+ * the MemOp, but so far we have worked hard to avoid an indirect function
481
+ * call along the memory path.
482
+ */
483
+static void validate_memop(MemOpIdx oi, MemOp expected)
484
+{
485
+#ifdef CONFIG_DEBUG_TCG
486
+ MemOp have = get_memop(oi) & (MO_SIZE | MO_BSWAP);
487
+ assert(have == expected);
488
+#endif
489
+}
490
+
491
/*
492
* Load Helpers
493
*
494
@@ -XXX,XX +XXX,XX @@ load_helper(CPUArchState *env, target_ulong addr, MemOpIdx oi,
495
static uint64_t full_ldub_mmu(CPUArchState *env, target_ulong addr,
496
MemOpIdx oi, uintptr_t retaddr)
497
{
498
+ validate_memop(oi, MO_UB);
499
return load_helper(env, addr, oi, retaddr, MO_UB, false, full_ldub_mmu);
500
}
501
502
@@ -XXX,XX +XXX,XX @@ tcg_target_ulong helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr,
503
static uint64_t full_le_lduw_mmu(CPUArchState *env, target_ulong addr,
504
MemOpIdx oi, uintptr_t retaddr)
505
{
506
+ validate_memop(oi, MO_LEUW);
507
return load_helper(env, addr, oi, retaddr, MO_LEUW, false,
508
full_le_lduw_mmu);
509
}
510
@@ -XXX,XX +XXX,XX @@ tcg_target_ulong helper_le_lduw_mmu(CPUArchState *env, target_ulong addr,
511
static uint64_t full_be_lduw_mmu(CPUArchState *env, target_ulong addr,
512
MemOpIdx oi, uintptr_t retaddr)
513
{
514
+ validate_memop(oi, MO_BEUW);
515
return load_helper(env, addr, oi, retaddr, MO_BEUW, false,
516
full_be_lduw_mmu);
517
}
518
@@ -XXX,XX +XXX,XX @@ tcg_target_ulong helper_be_lduw_mmu(CPUArchState *env, target_ulong addr,
519
static uint64_t full_le_ldul_mmu(CPUArchState *env, target_ulong addr,
520
MemOpIdx oi, uintptr_t retaddr)
521
{
522
+ validate_memop(oi, MO_LEUL);
523
return load_helper(env, addr, oi, retaddr, MO_LEUL, false,
524
full_le_ldul_mmu);
525
}
526
@@ -XXX,XX +XXX,XX @@ tcg_target_ulong helper_le_ldul_mmu(CPUArchState *env, target_ulong addr,
527
static uint64_t full_be_ldul_mmu(CPUArchState *env, target_ulong addr,
528
MemOpIdx oi, uintptr_t retaddr)
529
{
530
+ validate_memop(oi, MO_BEUL);
531
return load_helper(env, addr, oi, retaddr, MO_BEUL, false,
532
full_be_ldul_mmu);
533
}
534
@@ -XXX,XX +XXX,XX @@ tcg_target_ulong helper_be_ldul_mmu(CPUArchState *env, target_ulong addr,
535
uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr,
536
MemOpIdx oi, uintptr_t retaddr)
537
{
538
+ validate_memop(oi, MO_LEQ);
539
return load_helper(env, addr, oi, retaddr, MO_LEQ, false,
540
helper_le_ldq_mmu);
541
}
542
@@ -XXX,XX +XXX,XX @@ uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr,
543
uint64_t helper_be_ldq_mmu(CPUArchState *env, target_ulong addr,
544
MemOpIdx oi, uintptr_t retaddr)
545
{
546
+ validate_memop(oi, MO_BEQ);
547
return load_helper(env, addr, oi, retaddr, MO_BEQ, false,
548
helper_be_ldq_mmu);
549
}
550
@@ -XXX,XX +XXX,XX @@ tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr,
551
*/
552
553
static inline uint64_t cpu_load_helper(CPUArchState *env, abi_ptr addr,
554
- int mmu_idx, uintptr_t retaddr,
555
- MemOp op, FullLoadHelper *full_load)
556
+ MemOpIdx oi, uintptr_t retaddr,
557
+ FullLoadHelper *full_load)
558
{
559
- MemOpIdx oi = make_memop_idx(op, mmu_idx);
560
uint64_t ret;
561
562
trace_guest_ld_before_exec(env_cpu(env), addr, oi);
563
-
564
ret = full_load(env, addr, oi, retaddr);
565
-
566
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
567
-
568
return ret;
569
}
570
571
-uint32_t cpu_ldub_mmuidx_ra(CPUArchState *env, abi_ptr addr,
572
- int mmu_idx, uintptr_t ra)
573
+uint8_t cpu_ldb_mmu(CPUArchState *env, abi_ptr addr, MemOpIdx oi, uintptr_t ra)
574
{
575
- return cpu_load_helper(env, addr, mmu_idx, ra, MO_UB, full_ldub_mmu);
576
+ return cpu_load_helper(env, addr, oi, ra, full_ldub_mmu);
577
}
578
579
-int cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr addr,
580
- int mmu_idx, uintptr_t ra)
581
+uint16_t cpu_ldw_be_mmu(CPUArchState *env, abi_ptr addr,
582
+ MemOpIdx oi, uintptr_t ra)
583
{
584
- return (int8_t)cpu_ldub_mmuidx_ra(env, addr, mmu_idx, ra);
585
+ return cpu_load_helper(env, addr, oi, ra, full_be_lduw_mmu);
586
}
587
588
-uint32_t cpu_lduw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
589
- int mmu_idx, uintptr_t ra)
590
+uint32_t cpu_ldl_be_mmu(CPUArchState *env, abi_ptr addr,
591
+ MemOpIdx oi, uintptr_t ra)
592
{
593
- return cpu_load_helper(env, addr, mmu_idx, ra, MO_BEUW, full_be_lduw_mmu);
594
+ return cpu_load_helper(env, addr, oi, ra, full_be_ldul_mmu);
595
}
596
597
-int cpu_ldsw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
598
- int mmu_idx, uintptr_t ra)
599
+uint64_t cpu_ldq_be_mmu(CPUArchState *env, abi_ptr addr,
600
+ MemOpIdx oi, uintptr_t ra)
601
{
602
- return (int16_t)cpu_lduw_be_mmuidx_ra(env, addr, mmu_idx, ra);
603
+ return cpu_load_helper(env, addr, oi, MO_BEQ, helper_be_ldq_mmu);
604
}
605
606
-uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
607
- int mmu_idx, uintptr_t ra)
608
+uint16_t cpu_ldw_le_mmu(CPUArchState *env, abi_ptr addr,
609
+ MemOpIdx oi, uintptr_t ra)
610
{
611
- return cpu_load_helper(env, addr, mmu_idx, ra, MO_BEUL, full_be_ldul_mmu);
612
+ return cpu_load_helper(env, addr, oi, ra, full_le_lduw_mmu);
613
}
614
615
-uint64_t cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
616
- int mmu_idx, uintptr_t ra)
617
+uint32_t cpu_ldl_le_mmu(CPUArchState *env, abi_ptr addr,
618
+ MemOpIdx oi, uintptr_t ra)
619
{
620
- return cpu_load_helper(env, addr, mmu_idx, ra, MO_BEQ, helper_be_ldq_mmu);
621
+ return cpu_load_helper(env, addr, oi, ra, full_le_ldul_mmu);
622
}
623
624
-uint32_t cpu_lduw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
625
- int mmu_idx, uintptr_t ra)
626
+uint64_t cpu_ldq_le_mmu(CPUArchState *env, abi_ptr addr,
627
+ MemOpIdx oi, uintptr_t ra)
628
{
629
- return cpu_load_helper(env, addr, mmu_idx, ra, MO_LEUW, full_le_lduw_mmu);
630
-}
631
-
632
-int cpu_ldsw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
633
- int mmu_idx, uintptr_t ra)
634
-{
635
- return (int16_t)cpu_lduw_le_mmuidx_ra(env, addr, mmu_idx, ra);
636
-}
637
-
638
-uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
639
- int mmu_idx, uintptr_t ra)
640
-{
641
- return cpu_load_helper(env, addr, mmu_idx, ra, MO_LEUL, full_le_ldul_mmu);
642
-}
643
-
644
-uint64_t cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
645
- int mmu_idx, uintptr_t ra)
646
-{
647
- return cpu_load_helper(env, addr, mmu_idx, ra, MO_LEQ, helper_le_ldq_mmu);
648
-}
649
-
650
-uint32_t cpu_ldub_data_ra(CPUArchState *env, target_ulong ptr,
651
- uintptr_t retaddr)
652
-{
653
- return cpu_ldub_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
654
-}
655
-
656
-int cpu_ldsb_data_ra(CPUArchState *env, target_ulong ptr, uintptr_t retaddr)
657
-{
658
- return cpu_ldsb_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
659
-}
660
-
661
-uint32_t cpu_lduw_be_data_ra(CPUArchState *env, target_ulong ptr,
662
- uintptr_t retaddr)
663
-{
664
- return cpu_lduw_be_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
665
-}
666
-
667
-int cpu_ldsw_be_data_ra(CPUArchState *env, target_ulong ptr, uintptr_t retaddr)
668
-{
669
- return cpu_ldsw_be_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
670
-}
671
-
672
-uint32_t cpu_ldl_be_data_ra(CPUArchState *env, target_ulong ptr,
673
- uintptr_t retaddr)
674
-{
675
- return cpu_ldl_be_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
676
-}
677
-
678
-uint64_t cpu_ldq_be_data_ra(CPUArchState *env, target_ulong ptr,
679
- uintptr_t retaddr)
680
-{
681
- return cpu_ldq_be_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
682
-}
683
-
684
-uint32_t cpu_lduw_le_data_ra(CPUArchState *env, target_ulong ptr,
685
- uintptr_t retaddr)
686
-{
687
- return cpu_lduw_le_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
688
-}
689
-
690
-int cpu_ldsw_le_data_ra(CPUArchState *env, target_ulong ptr, uintptr_t retaddr)
691
-{
692
- return cpu_ldsw_le_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
693
-}
694
-
695
-uint32_t cpu_ldl_le_data_ra(CPUArchState *env, target_ulong ptr,
696
- uintptr_t retaddr)
697
-{
698
- return cpu_ldl_le_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
699
-}
700
-
701
-uint64_t cpu_ldq_le_data_ra(CPUArchState *env, target_ulong ptr,
702
- uintptr_t retaddr)
703
-{
704
- return cpu_ldq_le_mmuidx_ra(env, ptr, cpu_mmu_index(env, false), retaddr);
705
-}
706
-
707
-uint32_t cpu_ldub_data(CPUArchState *env, target_ulong ptr)
708
-{
709
- return cpu_ldub_data_ra(env, ptr, 0);
710
-}
711
-
712
-int cpu_ldsb_data(CPUArchState *env, target_ulong ptr)
713
-{
714
- return cpu_ldsb_data_ra(env, ptr, 0);
715
-}
716
-
717
-uint32_t cpu_lduw_be_data(CPUArchState *env, target_ulong ptr)
718
-{
719
- return cpu_lduw_be_data_ra(env, ptr, 0);
720
-}
721
-
722
-int cpu_ldsw_be_data(CPUArchState *env, target_ulong ptr)
723
-{
724
- return cpu_ldsw_be_data_ra(env, ptr, 0);
725
-}
726
-
727
-uint32_t cpu_ldl_be_data(CPUArchState *env, target_ulong ptr)
728
-{
729
- return cpu_ldl_be_data_ra(env, ptr, 0);
730
-}
731
-
732
-uint64_t cpu_ldq_be_data(CPUArchState *env, target_ulong ptr)
733
-{
734
- return cpu_ldq_be_data_ra(env, ptr, 0);
735
-}
736
-
737
-uint32_t cpu_lduw_le_data(CPUArchState *env, target_ulong ptr)
738
-{
739
- return cpu_lduw_le_data_ra(env, ptr, 0);
740
-}
741
-
742
-int cpu_ldsw_le_data(CPUArchState *env, target_ulong ptr)
743
-{
744
- return cpu_ldsw_le_data_ra(env, ptr, 0);
745
-}
746
-
747
-uint32_t cpu_ldl_le_data(CPUArchState *env, target_ulong ptr)
748
-{
749
- return cpu_ldl_le_data_ra(env, ptr, 0);
750
-}
751
-
752
-uint64_t cpu_ldq_le_data(CPUArchState *env, target_ulong ptr)
753
-{
754
- return cpu_ldq_le_data_ra(env, ptr, 0);
755
+ return cpu_load_helper(env, addr, oi, ra, helper_le_ldq_mmu);
756
}
757
758
/*
759
@@ -XXX,XX +XXX,XX @@ store_memop(void *haddr, uint64_t val, MemOp op)
760
}
761
}
762
763
+static void full_stb_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
764
+ MemOpIdx oi, uintptr_t retaddr);
765
+
766
static void __attribute__((noinline))
767
store_helper_unaligned(CPUArchState *env, target_ulong addr, uint64_t val,
768
uintptr_t retaddr, size_t size, uintptr_t mmu_idx,
769
@@ -XXX,XX +XXX,XX @@ store_helper_unaligned(CPUArchState *env, target_ulong addr, uint64_t val,
770
for (i = 0; i < size; ++i) {
771
/* Big-endian extract. */
772
uint8_t val8 = val >> (((size - 1) * 8) - (i * 8));
773
- helper_ret_stb_mmu(env, addr + i, val8, oi, retaddr);
774
+ full_stb_mmu(env, addr + i, val8, oi, retaddr);
775
}
776
} else {
777
for (i = 0; i < size; ++i) {
778
/* Little-endian extract. */
779
uint8_t val8 = val >> (i * 8);
780
- helper_ret_stb_mmu(env, addr + i, val8, oi, retaddr);
781
+ full_stb_mmu(env, addr + i, val8, oi, retaddr);
782
}
783
}
784
}
785
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
786
store_memop(haddr, val, op);
787
}
788
789
-void __attribute__((noinline))
790
-helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
791
- MemOpIdx oi, uintptr_t retaddr)
792
+static void __attribute__((noinline))
793
+full_stb_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
794
+ MemOpIdx oi, uintptr_t retaddr)
795
{
796
+ validate_memop(oi, MO_UB);
797
store_helper(env, addr, val, oi, retaddr, MO_UB);
798
}
799
800
+void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
801
+ MemOpIdx oi, uintptr_t retaddr)
802
+{
803
+ full_stb_mmu(env, addr, val, oi, retaddr);
804
+}
805
+
806
+static void full_le_stw_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
807
+ MemOpIdx oi, uintptr_t retaddr)
808
+{
809
+ validate_memop(oi, MO_LEUW);
810
+ store_helper(env, addr, val, oi, retaddr, MO_LEUW);
811
+}
812
+
813
void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
814
MemOpIdx oi, uintptr_t retaddr)
815
{
816
- store_helper(env, addr, val, oi, retaddr, MO_LEUW);
817
+ full_le_stw_mmu(env, addr, val, oi, retaddr);
818
+}
819
+
820
+static void full_be_stw_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
821
+ MemOpIdx oi, uintptr_t retaddr)
822
+{
823
+ validate_memop(oi, MO_BEUW);
824
+ store_helper(env, addr, val, oi, retaddr, MO_BEUW);
825
}
826
827
void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
828
MemOpIdx oi, uintptr_t retaddr)
829
{
830
- store_helper(env, addr, val, oi, retaddr, MO_BEUW);
831
+ full_be_stw_mmu(env, addr, val, oi, retaddr);
832
+}
833
+
834
+static void full_le_stl_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
835
+ MemOpIdx oi, uintptr_t retaddr)
836
+{
837
+ validate_memop(oi, MO_LEUL);
838
+ store_helper(env, addr, val, oi, retaddr, MO_LEUL);
839
}
840
841
void helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
842
MemOpIdx oi, uintptr_t retaddr)
843
{
844
- store_helper(env, addr, val, oi, retaddr, MO_LEUL);
845
+ full_le_stl_mmu(env, addr, val, oi, retaddr);
846
+}
847
+
848
+static void full_be_stl_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
849
+ MemOpIdx oi, uintptr_t retaddr)
850
+{
851
+ validate_memop(oi, MO_BEUL);
852
+ store_helper(env, addr, val, oi, retaddr, MO_BEUL);
853
}
854
855
void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
856
MemOpIdx oi, uintptr_t retaddr)
857
{
858
- store_helper(env, addr, val, oi, retaddr, MO_BEUL);
859
+ full_be_stl_mmu(env, addr, val, oi, retaddr);
860
}
861
862
void helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
863
MemOpIdx oi, uintptr_t retaddr)
864
{
865
+ validate_memop(oi, MO_LEQ);
866
store_helper(env, addr, val, oi, retaddr, MO_LEQ);
867
}
868
869
void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
870
MemOpIdx oi, uintptr_t retaddr)
871
{
872
+ validate_memop(oi, MO_BEQ);
873
store_helper(env, addr, val, oi, retaddr, MO_BEQ);
874
}
875
876
@@ -XXX,XX +XXX,XX @@ void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
877
* Store Helpers for cpu_ldst.h
878
*/
879
880
-static inline void QEMU_ALWAYS_INLINE
881
-cpu_store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
882
- int mmu_idx, uintptr_t retaddr, MemOp op)
883
+typedef void FullStoreHelper(CPUArchState *env, target_ulong addr,
884
+ uint64_t val, MemOpIdx oi, uintptr_t retaddr);
885
+
886
+static inline void cpu_store_helper(CPUArchState *env, target_ulong addr,
887
+ uint64_t val, MemOpIdx oi, uintptr_t ra,
888
+ FullStoreHelper *full_store)
889
{
890
- MemOpIdx oi = make_memop_idx(op, mmu_idx);
891
-
892
trace_guest_st_before_exec(env_cpu(env), addr, oi);
893
-
894
- store_helper(env, addr, val, oi, retaddr, op);
895
-
896
+ full_store(env, addr, val, oi, ra);
897
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
898
}
899
900
-void cpu_stb_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val,
901
- int mmu_idx, uintptr_t retaddr)
902
+void cpu_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
903
+ MemOpIdx oi, uintptr_t retaddr)
904
{
905
- cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_UB);
906
+ cpu_store_helper(env, addr, val, oi, retaddr, full_stb_mmu);
907
}
908
909
-void cpu_stw_be_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val,
910
- int mmu_idx, uintptr_t retaddr)
911
+void cpu_stw_be_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
912
+ MemOpIdx oi, uintptr_t retaddr)
913
{
914
- cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_BEUW);
915
+ cpu_store_helper(env, addr, val, oi, retaddr, full_be_stw_mmu);
916
}
917
918
-void cpu_stl_be_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val,
919
- int mmu_idx, uintptr_t retaddr)
920
+void cpu_stl_be_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
921
+ MemOpIdx oi, uintptr_t retaddr)
922
{
923
- cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_BEUL);
924
+ cpu_store_helper(env, addr, val, oi, retaddr, full_be_stl_mmu);
925
}
926
927
-void cpu_stq_be_mmuidx_ra(CPUArchState *env, target_ulong addr, uint64_t val,
928
- int mmu_idx, uintptr_t retaddr)
929
+void cpu_stq_be_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
930
+ MemOpIdx oi, uintptr_t retaddr)
931
{
932
- cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_BEQ);
933
+ cpu_store_helper(env, addr, val, oi, retaddr, helper_be_stq_mmu);
934
}
935
936
-void cpu_stw_le_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val,
937
- int mmu_idx, uintptr_t retaddr)
938
+void cpu_stw_le_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
939
+ MemOpIdx oi, uintptr_t retaddr)
940
{
941
- cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_LEUW);
942
+ cpu_store_helper(env, addr, val, oi, retaddr, full_le_stw_mmu);
943
}
944
945
-void cpu_stl_le_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val,
946
- int mmu_idx, uintptr_t retaddr)
947
+void cpu_stl_le_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
948
+ MemOpIdx oi, uintptr_t retaddr)
949
{
950
- cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_LEUL);
951
+ cpu_store_helper(env, addr, val, oi, retaddr, full_le_stl_mmu);
952
}
953
954
-void cpu_stq_le_mmuidx_ra(CPUArchState *env, target_ulong addr, uint64_t val,
955
- int mmu_idx, uintptr_t retaddr)
956
+void cpu_stq_le_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
957
+ MemOpIdx oi, uintptr_t retaddr)
958
{
959
- cpu_store_helper(env, addr, val, mmu_idx, retaddr, MO_LEQ);
960
+ cpu_store_helper(env, addr, val, oi, retaddr, helper_le_stq_mmu);
961
}
962
963
-void cpu_stb_data_ra(CPUArchState *env, target_ulong ptr,
964
- uint32_t val, uintptr_t retaddr)
965
-{
966
- cpu_stb_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
967
-}
968
-
969
-void cpu_stw_be_data_ra(CPUArchState *env, target_ulong ptr,
970
- uint32_t val, uintptr_t retaddr)
971
-{
972
- cpu_stw_be_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
973
-}
974
-
975
-void cpu_stl_be_data_ra(CPUArchState *env, target_ulong ptr,
976
- uint32_t val, uintptr_t retaddr)
977
-{
978
- cpu_stl_be_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
979
-}
980
-
981
-void cpu_stq_be_data_ra(CPUArchState *env, target_ulong ptr,
982
- uint64_t val, uintptr_t retaddr)
983
-{
984
- cpu_stq_be_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
985
-}
986
-
987
-void cpu_stw_le_data_ra(CPUArchState *env, target_ulong ptr,
988
- uint32_t val, uintptr_t retaddr)
989
-{
990
- cpu_stw_le_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
991
-}
992
-
993
-void cpu_stl_le_data_ra(CPUArchState *env, target_ulong ptr,
994
- uint32_t val, uintptr_t retaddr)
995
-{
996
- cpu_stl_le_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
997
-}
998
-
999
-void cpu_stq_le_data_ra(CPUArchState *env, target_ulong ptr,
1000
- uint64_t val, uintptr_t retaddr)
1001
-{
1002
- cpu_stq_le_mmuidx_ra(env, ptr, val, cpu_mmu_index(env, false), retaddr);
1003
-}
1004
-
1005
-void cpu_stb_data(CPUArchState *env, target_ulong ptr, uint32_t val)
1006
-{
1007
- cpu_stb_data_ra(env, ptr, val, 0);
1008
-}
1009
-
1010
-void cpu_stw_be_data(CPUArchState *env, target_ulong ptr, uint32_t val)
1011
-{
1012
- cpu_stw_be_data_ra(env, ptr, val, 0);
1013
-}
1014
-
1015
-void cpu_stl_be_data(CPUArchState *env, target_ulong ptr, uint32_t val)
1016
-{
1017
- cpu_stl_be_data_ra(env, ptr, val, 0);
1018
-}
1019
-
1020
-void cpu_stq_be_data(CPUArchState *env, target_ulong ptr, uint64_t val)
1021
-{
1022
- cpu_stq_be_data_ra(env, ptr, val, 0);
1023
-}
1024
-
1025
-void cpu_stw_le_data(CPUArchState *env, target_ulong ptr, uint32_t val)
1026
-{
1027
- cpu_stw_le_data_ra(env, ptr, val, 0);
1028
-}
1029
-
1030
-void cpu_stl_le_data(CPUArchState *env, target_ulong ptr, uint32_t val)
1031
-{
1032
- cpu_stl_le_data_ra(env, ptr, val, 0);
1033
-}
1034
-
1035
-void cpu_stq_le_data(CPUArchState *env, target_ulong ptr, uint64_t val)
1036
-{
1037
- cpu_stq_le_data_ra(env, ptr, val, 0);
1038
-}
1039
+#include "ldst_common.c.inc"
1040
1041
/*
1042
* First set of functions passes in OI and RETADDR.
1043
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
1044
index XXXXXXX..XXXXXXX 100644
1045
--- a/accel/tcg/user-exec.c
1046
+++ b/accel/tcg/user-exec.c
1047
@@ -XXX,XX +XXX,XX @@ int cpu_signal_handler(int host_signum, void *pinfo,
1048
1049
/* The softmmu versions of these helpers are in cputlb.c. */
1050
1051
-uint32_t cpu_ldub_data(CPUArchState *env, abi_ptr ptr)
1052
+/*
1053
+ * Verify that we have passed the correct MemOp to the correct function.
1054
+ *
1055
+ * We could present one function to target code, and dispatch based on
1056
+ * the MemOp, but so far we have worked hard to avoid an indirect function
1057
+ * call along the memory path.
1058
+ */
1059
+static void validate_memop(MemOpIdx oi, MemOp expected)
1060
{
1061
- MemOpIdx oi = make_memop_idx(MO_UB, MMU_USER_IDX);
1062
- uint32_t ret;
1063
+#ifdef CONFIG_DEBUG_TCG
1064
+ MemOp have = get_memop(oi) & (MO_SIZE | MO_BSWAP);
1065
+ assert(have == expected);
1066
+#endif
1067
+}
1068
1069
- trace_guest_ld_before_exec(env_cpu(env), ptr, oi);
1070
- ret = ldub_p(g2h(env_cpu(env), ptr));
1071
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_R);
1072
+static void *cpu_mmu_lookup(CPUArchState *env, target_ulong addr,
1073
+ MemOpIdx oi, uintptr_t ra, MMUAccessType type)
1074
+{
1075
+ void *ret;
1076
+
1077
+ /* TODO: Enforce guest required alignment. */
1078
+
1079
+ ret = g2h(env_cpu(env), addr);
1080
+ set_helper_retaddr(ra);
1081
return ret;
1082
}
1083
1084
-int cpu_ldsb_data(CPUArchState *env, abi_ptr ptr)
1085
+uint8_t cpu_ldb_mmu(CPUArchState *env, abi_ptr addr,
1086
+ MemOpIdx oi, uintptr_t ra)
1087
{
1088
- return (int8_t)cpu_ldub_data(env, ptr);
1089
-}
1090
+ void *haddr;
1091
+ uint8_t ret;
1092
1093
-uint32_t cpu_lduw_be_data(CPUArchState *env, abi_ptr ptr)
1094
-{
1095
- MemOpIdx oi = make_memop_idx(MO_BEUW, MMU_USER_IDX);
1096
- uint32_t ret;
1097
-
1098
- trace_guest_ld_before_exec(env_cpu(env), ptr, oi);
1099
- ret = lduw_be_p(g2h(env_cpu(env), ptr));
1100
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_R);
1101
+ validate_memop(oi, MO_UB);
1102
+ trace_guest_ld_before_exec(env_cpu(env), addr, oi);
1103
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
1104
+ ret = ldub_p(haddr);
1105
+ clear_helper_retaddr();
1106
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
1107
return ret;
1108
}
1109
1110
-int cpu_ldsw_be_data(CPUArchState *env, abi_ptr ptr)
1111
+uint16_t cpu_ldw_be_mmu(CPUArchState *env, abi_ptr addr,
1112
+ MemOpIdx oi, uintptr_t ra)
1113
{
1114
- return (int16_t)cpu_lduw_be_data(env, ptr);
1115
-}
1116
+ void *haddr;
1117
+ uint16_t ret;
1118
1119
-uint32_t cpu_ldl_be_data(CPUArchState *env, abi_ptr ptr)
1120
-{
1121
- MemOpIdx oi = make_memop_idx(MO_BEUL, MMU_USER_IDX);
1122
- uint32_t ret;
1123
-
1124
- trace_guest_ld_before_exec(env_cpu(env), ptr, oi);
1125
- ret = ldl_be_p(g2h(env_cpu(env), ptr));
1126
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_R);
1127
+ validate_memop(oi, MO_BEUW);
1128
+ trace_guest_ld_before_exec(env_cpu(env), addr, oi);
1129
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
1130
+ ret = lduw_be_p(haddr);
1131
+ clear_helper_retaddr();
1132
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
1133
return ret;
1134
}
1135
1136
-uint64_t cpu_ldq_be_data(CPUArchState *env, abi_ptr ptr)
1137
+uint32_t cpu_ldl_be_mmu(CPUArchState *env, abi_ptr addr,
1138
+ MemOpIdx oi, uintptr_t ra)
1139
{
1140
- MemOpIdx oi = make_memop_idx(MO_BEQ, MMU_USER_IDX);
1141
+ void *haddr;
1142
+ uint32_t ret;
1143
+
1144
+ validate_memop(oi, MO_BEUL);
1145
+ trace_guest_ld_before_exec(env_cpu(env), addr, oi);
1146
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
1147
+ ret = ldl_be_p(haddr);
1148
+ clear_helper_retaddr();
1149
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
1150
+ return ret;
1151
+}
1152
+
1153
+uint64_t cpu_ldq_be_mmu(CPUArchState *env, abi_ptr addr,
1154
+ MemOpIdx oi, uintptr_t ra)
1155
+{
1156
+ void *haddr;
1157
uint64_t ret;
1158
1159
- trace_guest_ld_before_exec(env_cpu(env), ptr, oi);
1160
- ret = ldq_be_p(g2h(env_cpu(env), ptr));
1161
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_R);
1162
+ validate_memop(oi, MO_BEQ);
1163
+ trace_guest_ld_before_exec(env_cpu(env), addr, oi);
1164
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
1165
+ ret = ldq_be_p(haddr);
1166
+ clear_helper_retaddr();
1167
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
1168
return ret;
1169
}
1170
1171
-uint32_t cpu_lduw_le_data(CPUArchState *env, abi_ptr ptr)
1172
+uint16_t cpu_ldw_le_mmu(CPUArchState *env, abi_ptr addr,
1173
+ MemOpIdx oi, uintptr_t ra)
1174
{
1175
- MemOpIdx oi = make_memop_idx(MO_LEUW, MMU_USER_IDX);
1176
+ void *haddr;
1177
+ uint16_t ret;
1178
+
1179
+ validate_memop(oi, MO_LEUW);
1180
+ trace_guest_ld_before_exec(env_cpu(env), addr, oi);
1181
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
1182
+ ret = lduw_le_p(haddr);
1183
+ clear_helper_retaddr();
1184
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
1185
+ return ret;
1186
+}
1187
+
1188
+uint32_t cpu_ldl_le_mmu(CPUArchState *env, abi_ptr addr,
1189
+ MemOpIdx oi, uintptr_t ra)
1190
+{
1191
+ void *haddr;
1192
uint32_t ret;
1193
1194
- trace_guest_ld_before_exec(env_cpu(env), ptr, oi);
1195
- ret = lduw_le_p(g2h(env_cpu(env), ptr));
1196
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_R);
1197
+ validate_memop(oi, MO_LEUL);
1198
+ trace_guest_ld_before_exec(env_cpu(env), addr, oi);
1199
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
1200
+ ret = ldl_le_p(haddr);
1201
+ clear_helper_retaddr();
1202
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
1203
return ret;
1204
}
1205
1206
-int cpu_ldsw_le_data(CPUArchState *env, abi_ptr ptr)
1207
+uint64_t cpu_ldq_le_mmu(CPUArchState *env, abi_ptr addr,
1208
+ MemOpIdx oi, uintptr_t ra)
1209
{
1210
- return (int16_t)cpu_lduw_le_data(env, ptr);
1211
-}
1212
-
1213
-uint32_t cpu_ldl_le_data(CPUArchState *env, abi_ptr ptr)
1214
-{
1215
- MemOpIdx oi = make_memop_idx(MO_LEUL, MMU_USER_IDX);
1216
- uint32_t ret;
1217
-
1218
- trace_guest_ld_before_exec(env_cpu(env), ptr, oi);
1219
- ret = ldl_le_p(g2h(env_cpu(env), ptr));
1220
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_R);
1221
- return ret;
1222
-}
1223
-
1224
-uint64_t cpu_ldq_le_data(CPUArchState *env, abi_ptr ptr)
1225
-{
1226
- MemOpIdx oi = make_memop_idx(MO_LEQ, MMU_USER_IDX);
1227
+ void *haddr;
1228
uint64_t ret;
1229
1230
- trace_guest_ld_before_exec(env_cpu(env), ptr, oi);
1231
- ret = ldq_le_p(g2h(env_cpu(env), ptr));
1232
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_R);
1233
+ validate_memop(oi, MO_LEQ);
1234
+ trace_guest_ld_before_exec(env_cpu(env), addr, oi);
1235
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
1236
+ ret = ldq_le_p(haddr);
1237
+ clear_helper_retaddr();
1238
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
1239
return ret;
1240
}
1241
1242
-uint32_t cpu_ldub_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
1243
+void cpu_stb_mmu(CPUArchState *env, abi_ptr addr, uint8_t val,
1244
+ MemOpIdx oi, uintptr_t ra)
1245
{
1246
- uint32_t ret;
1247
+ void *haddr;
1248
1249
- set_helper_retaddr(retaddr);
1250
- ret = cpu_ldub_data(env, ptr);
1251
+ validate_memop(oi, MO_UB);
1252
+ trace_guest_st_before_exec(env_cpu(env), addr, oi);
1253
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
1254
+ stb_p(haddr, val);
1255
clear_helper_retaddr();
1256
- return ret;
1257
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
1258
}
1259
1260
-int cpu_ldsb_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
1261
+void cpu_stw_be_mmu(CPUArchState *env, abi_ptr addr, uint16_t val,
1262
+ MemOpIdx oi, uintptr_t ra)
1263
{
1264
- return (int8_t)cpu_ldub_data_ra(env, ptr, retaddr);
1265
-}
1266
+ void *haddr;
1267
1268
-uint32_t cpu_lduw_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
1269
-{
1270
- uint32_t ret;
1271
-
1272
- set_helper_retaddr(retaddr);
1273
- ret = cpu_lduw_be_data(env, ptr);
1274
+ validate_memop(oi, MO_BEUW);
1275
+ trace_guest_st_before_exec(env_cpu(env), addr, oi);
1276
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
1277
+ stw_be_p(haddr, val);
1278
clear_helper_retaddr();
1279
- return ret;
1280
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
1281
}
1282
1283
-int cpu_ldsw_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
1284
+void cpu_stl_be_mmu(CPUArchState *env, abi_ptr addr, uint32_t val,
1285
+ MemOpIdx oi, uintptr_t ra)
1286
{
1287
- return (int16_t)cpu_lduw_be_data_ra(env, ptr, retaddr);
1288
-}
1289
+ void *haddr;
1290
1291
-uint32_t cpu_ldl_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
1292
-{
1293
- uint32_t ret;
1294
-
1295
- set_helper_retaddr(retaddr);
1296
- ret = cpu_ldl_be_data(env, ptr);
1297
+ validate_memop(oi, MO_BEUL);
1298
+ trace_guest_st_before_exec(env_cpu(env), addr, oi);
1299
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
1300
+ stl_be_p(haddr, val);
1301
clear_helper_retaddr();
1302
- return ret;
1303
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
1304
}
1305
1306
-uint64_t cpu_ldq_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
1307
+void cpu_stq_be_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
1308
+ MemOpIdx oi, uintptr_t ra)
1309
{
1310
- uint64_t ret;
1311
+ void *haddr;
1312
1313
- set_helper_retaddr(retaddr);
1314
- ret = cpu_ldq_be_data(env, ptr);
1315
+ validate_memop(oi, MO_BEQ);
1316
+ trace_guest_st_before_exec(env_cpu(env), addr, oi);
1317
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
1318
+ stq_be_p(haddr, val);
1319
clear_helper_retaddr();
1320
- return ret;
1321
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
1322
}
1323
1324
-uint32_t cpu_lduw_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
1325
+void cpu_stw_le_mmu(CPUArchState *env, abi_ptr addr, uint16_t val,
1326
+ MemOpIdx oi, uintptr_t ra)
1327
{
1328
- uint32_t ret;
1329
+ void *haddr;
1330
1331
- set_helper_retaddr(retaddr);
1332
- ret = cpu_lduw_le_data(env, ptr);
1333
+ validate_memop(oi, MO_LEUW);
1334
+ trace_guest_st_before_exec(env_cpu(env), addr, oi);
1335
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
1336
+ stw_le_p(haddr, val);
1337
clear_helper_retaddr();
1338
- return ret;
1339
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
1340
}
1341
1342
-int cpu_ldsw_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
1343
+void cpu_stl_le_mmu(CPUArchState *env, abi_ptr addr, uint32_t val,
1344
+ MemOpIdx oi, uintptr_t ra)
1345
{
1346
- return (int16_t)cpu_lduw_le_data_ra(env, ptr, retaddr);
1347
-}
1348
+ void *haddr;
1349
1350
-uint32_t cpu_ldl_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
1351
-{
1352
- uint32_t ret;
1353
-
1354
- set_helper_retaddr(retaddr);
1355
- ret = cpu_ldl_le_data(env, ptr);
1356
+ validate_memop(oi, MO_LEUL);
1357
+ trace_guest_st_before_exec(env_cpu(env), addr, oi);
1358
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
1359
+ stl_le_p(haddr, val);
1360
clear_helper_retaddr();
1361
- return ret;
1362
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
1363
}
1364
1365
-uint64_t cpu_ldq_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
1366
+void cpu_stq_le_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
1367
+ MemOpIdx oi, uintptr_t ra)
1368
{
1369
- uint64_t ret;
1370
+ void *haddr;
1371
1372
- set_helper_retaddr(retaddr);
1373
- ret = cpu_ldq_le_data(env, ptr);
1374
- clear_helper_retaddr();
1375
- return ret;
1376
-}
1377
-
1378
-void cpu_stb_data(CPUArchState *env, abi_ptr ptr, uint32_t val)
1379
-{
1380
- MemOpIdx oi = make_memop_idx(MO_UB, MMU_USER_IDX);
1381
-
1382
- trace_guest_st_before_exec(env_cpu(env), ptr, oi);
1383
- stb_p(g2h(env_cpu(env), ptr), val);
1384
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_W);
1385
-}
1386
-
1387
-void cpu_stw_be_data(CPUArchState *env, abi_ptr ptr, uint32_t val)
1388
-{
1389
- MemOpIdx oi = make_memop_idx(MO_BEUW, MMU_USER_IDX);
1390
-
1391
- trace_guest_st_before_exec(env_cpu(env), ptr, oi);
1392
- stw_be_p(g2h(env_cpu(env), ptr), val);
1393
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_W);
1394
-}
1395
-
1396
-void cpu_stl_be_data(CPUArchState *env, abi_ptr ptr, uint32_t val)
1397
-{
1398
- MemOpIdx oi = make_memop_idx(MO_BEUL, MMU_USER_IDX);
1399
-
1400
- trace_guest_st_before_exec(env_cpu(env), ptr, oi);
1401
- stl_be_p(g2h(env_cpu(env), ptr), val);
1402
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_W);
1403
-}
1404
-
1405
-void cpu_stq_be_data(CPUArchState *env, abi_ptr ptr, uint64_t val)
1406
-{
1407
- MemOpIdx oi = make_memop_idx(MO_BEQ, MMU_USER_IDX);
1408
-
1409
- trace_guest_st_before_exec(env_cpu(env), ptr, oi);
1410
- stq_be_p(g2h(env_cpu(env), ptr), val);
1411
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_W);
1412
-}
1413
-
1414
-void cpu_stw_le_data(CPUArchState *env, abi_ptr ptr, uint32_t val)
1415
-{
1416
- MemOpIdx oi = make_memop_idx(MO_LEUW, MMU_USER_IDX);
1417
-
1418
- trace_guest_st_before_exec(env_cpu(env), ptr, oi);
1419
- stw_le_p(g2h(env_cpu(env), ptr), val);
1420
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_W);
1421
-}
1422
-
1423
-void cpu_stl_le_data(CPUArchState *env, abi_ptr ptr, uint32_t val)
1424
-{
1425
- MemOpIdx oi = make_memop_idx(MO_LEUL, MMU_USER_IDX);
1426
-
1427
- trace_guest_st_before_exec(env_cpu(env), ptr, oi);
1428
- stl_le_p(g2h(env_cpu(env), ptr), val);
1429
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_W);
1430
-}
1431
-
1432
-void cpu_stq_le_data(CPUArchState *env, abi_ptr ptr, uint64_t val)
1433
-{
1434
- MemOpIdx oi = make_memop_idx(MO_LEQ, MMU_USER_IDX);
1435
-
1436
- trace_guest_st_before_exec(env_cpu(env), ptr, oi);
1437
- stq_le_p(g2h(env_cpu(env), ptr), val);
1438
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_W);
1439
-}
1440
-
1441
-void cpu_stb_data_ra(CPUArchState *env, abi_ptr ptr,
1442
- uint32_t val, uintptr_t retaddr)
1443
-{
1444
- set_helper_retaddr(retaddr);
1445
- cpu_stb_data(env, ptr, val);
1446
- clear_helper_retaddr();
1447
-}
1448
-
1449
-void cpu_stw_be_data_ra(CPUArchState *env, abi_ptr ptr,
1450
- uint32_t val, uintptr_t retaddr)
1451
-{
1452
- set_helper_retaddr(retaddr);
1453
- cpu_stw_be_data(env, ptr, val);
1454
- clear_helper_retaddr();
1455
-}
1456
-
1457
-void cpu_stl_be_data_ra(CPUArchState *env, abi_ptr ptr,
1458
- uint32_t val, uintptr_t retaddr)
1459
-{
1460
- set_helper_retaddr(retaddr);
1461
- cpu_stl_be_data(env, ptr, val);
1462
- clear_helper_retaddr();
1463
-}
1464
-
1465
-void cpu_stq_be_data_ra(CPUArchState *env, abi_ptr ptr,
1466
- uint64_t val, uintptr_t retaddr)
1467
-{
1468
- set_helper_retaddr(retaddr);
1469
- cpu_stq_be_data(env, ptr, val);
1470
- clear_helper_retaddr();
1471
-}
1472
-
1473
-void cpu_stw_le_data_ra(CPUArchState *env, abi_ptr ptr,
1474
- uint32_t val, uintptr_t retaddr)
1475
-{
1476
- set_helper_retaddr(retaddr);
1477
- cpu_stw_le_data(env, ptr, val);
1478
- clear_helper_retaddr();
1479
-}
1480
-
1481
-void cpu_stl_le_data_ra(CPUArchState *env, abi_ptr ptr,
1482
- uint32_t val, uintptr_t retaddr)
1483
-{
1484
- set_helper_retaddr(retaddr);
1485
- cpu_stl_le_data(env, ptr, val);
1486
- clear_helper_retaddr();
1487
-}
1488
-
1489
-void cpu_stq_le_data_ra(CPUArchState *env, abi_ptr ptr,
1490
- uint64_t val, uintptr_t retaddr)
1491
-{
1492
- set_helper_retaddr(retaddr);
1493
- cpu_stq_le_data(env, ptr, val);
1494
+ validate_memop(oi, MO_LEQ);
1495
+ trace_guest_st_before_exec(env_cpu(env), addr, oi);
1496
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
1497
+ stq_le_p(haddr, val);
1498
clear_helper_retaddr();
1499
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
1500
}
1501
1502
uint32_t cpu_ldub_code(CPUArchState *env, abi_ptr ptr)
1503
@@ -XXX,XX +XXX,XX @@ uint64_t cpu_ldq_code(CPUArchState *env, abi_ptr ptr)
1504
return ret;
1505
}
1506
1507
+#include "ldst_common.c.inc"
1508
+
1509
/*
1510
* Do not allow unaligned operations to proceed. Return the host address.
1511
*
1512
diff --git a/accel/tcg/ldst_common.c.inc b/accel/tcg/ldst_common.c.inc
1513
new file mode 100644
1514
index XXXXXXX..XXXXXXX
1515
--- /dev/null
1516
+++ b/accel/tcg/ldst_common.c.inc
1517
@@ -XXX,XX +XXX,XX @@
1518
+/*
1519
+ * Routines common to user and system emulation of load/store.
1520
+ *
1521
+ * Copyright (c) 2003 Fabrice Bellard
1522
+ *
1523
+ * SPDX-License-Identifier: GPL-2.0-or-later
1524
+ *
1525
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
1526
+ * See the COPYING file in the top-level directory.
1527
+ */
1528
+
1529
+uint32_t cpu_ldub_mmuidx_ra(CPUArchState *env, abi_ptr addr,
1530
+ int mmu_idx, uintptr_t ra)
1531
+{
1532
+ MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
1533
+ return cpu_ldb_mmu(env, addr, oi, ra);
1534
+}
1535
+
1536
+int cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr addr,
1537
+ int mmu_idx, uintptr_t ra)
1538
+{
1539
+ return (int8_t)cpu_ldub_mmuidx_ra(env, addr, mmu_idx, ra);
1540
+}
1541
+
1542
+uint32_t cpu_lduw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
1543
+ int mmu_idx, uintptr_t ra)
1544
+{
1545
+ MemOpIdx oi = make_memop_idx(MO_BEUW | MO_UNALN, mmu_idx);
1546
+ return cpu_ldw_be_mmu(env, addr, oi, ra);
1547
+}
1548
+
1549
+int cpu_ldsw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
1550
+ int mmu_idx, uintptr_t ra)
1551
+{
1552
+ return (int16_t)cpu_lduw_be_mmuidx_ra(env, addr, mmu_idx, ra);
1553
+}
1554
+
1555
+uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
1556
+ int mmu_idx, uintptr_t ra)
1557
+{
1558
+ MemOpIdx oi = make_memop_idx(MO_BEUL | MO_UNALN, mmu_idx);
1559
+ return cpu_ldl_be_mmu(env, addr, oi, ra);
1560
+}
1561
+
1562
+uint64_t cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
1563
+ int mmu_idx, uintptr_t ra)
1564
+{
1565
+ MemOpIdx oi = make_memop_idx(MO_BEQ | MO_UNALN, mmu_idx);
1566
+ return cpu_ldq_be_mmu(env, addr, oi, ra);
1567
+}
1568
+
1569
+uint32_t cpu_lduw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
1570
+ int mmu_idx, uintptr_t ra)
1571
+{
1572
+ MemOpIdx oi = make_memop_idx(MO_LEUW | MO_UNALN, mmu_idx);
1573
+ return cpu_ldw_le_mmu(env, addr, oi, ra);
1574
+}
1575
+
1576
+int cpu_ldsw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
1577
+ int mmu_idx, uintptr_t ra)
1578
+{
1579
+ return (int16_t)cpu_lduw_le_mmuidx_ra(env, addr, mmu_idx, ra);
1580
+}
1581
+
1582
+uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
1583
+ int mmu_idx, uintptr_t ra)
1584
+{
1585
+ MemOpIdx oi = make_memop_idx(MO_LEUL | MO_UNALN, mmu_idx);
1586
+ return cpu_ldl_le_mmu(env, addr, oi, ra);
1587
+}
1588
+
1589
+uint64_t cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
1590
+ int mmu_idx, uintptr_t ra)
1591
+{
1592
+ MemOpIdx oi = make_memop_idx(MO_LEQ | MO_UNALN, mmu_idx);
1593
+ return cpu_ldq_le_mmu(env, addr, oi, ra);
1594
+}
1595
+
1596
+void cpu_stb_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
1597
+ int mmu_idx, uintptr_t ra)
1598
+{
1599
+ MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
1600
+ cpu_stb_mmu(env, addr, val, oi, ra);
1601
+}
1602
+
1603
+void cpu_stw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
1604
+ int mmu_idx, uintptr_t ra)
1605
+{
1606
+ MemOpIdx oi = make_memop_idx(MO_BEUW | MO_UNALN, mmu_idx);
1607
+ cpu_stw_be_mmu(env, addr, val, oi, ra);
1608
+}
1609
+
1610
+void cpu_stl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
1611
+ int mmu_idx, uintptr_t ra)
1612
+{
1613
+ MemOpIdx oi = make_memop_idx(MO_BEUL | MO_UNALN, mmu_idx);
1614
+ cpu_stl_be_mmu(env, addr, val, oi, ra);
1615
+}
1616
+
1617
+void cpu_stq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
1618
+ int mmu_idx, uintptr_t ra)
1619
+{
1620
+ MemOpIdx oi = make_memop_idx(MO_BEQ | MO_UNALN, mmu_idx);
1621
+ cpu_stq_be_mmu(env, addr, val, oi, ra);
1622
+}
1623
+
1624
+void cpu_stw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
1625
+ int mmu_idx, uintptr_t ra)
1626
+{
1627
+ MemOpIdx oi = make_memop_idx(MO_LEUW | MO_UNALN, mmu_idx);
1628
+ cpu_stw_le_mmu(env, addr, val, oi, ra);
1629
+}
1630
+
1631
+void cpu_stl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
1632
+ int mmu_idx, uintptr_t ra)
1633
+{
1634
+ MemOpIdx oi = make_memop_idx(MO_LEUL | MO_UNALN, mmu_idx);
1635
+ cpu_stl_le_mmu(env, addr, val, oi, ra);
1636
+}
1637
+
1638
+void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
1639
+ int mmu_idx, uintptr_t ra)
1640
+{
1641
+ MemOpIdx oi = make_memop_idx(MO_LEQ | MO_UNALN, mmu_idx);
1642
+ cpu_stq_le_mmu(env, addr, val, oi, ra);
1643
+}
1644
+
1645
+/*--------------------------*/
1646
+
1647
+uint32_t cpu_ldub_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
1648
+{
1649
+ return cpu_ldub_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
1650
+}
1651
+
1652
+int cpu_ldsb_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
1653
+{
1654
+ return (int8_t)cpu_ldub_data_ra(env, addr, ra);
1655
+}
1656
+
1657
+uint32_t cpu_lduw_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
1658
+{
1659
+ return cpu_lduw_be_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
1660
+}
1661
+
1662
+int cpu_ldsw_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
1663
+{
1664
+ return (int16_t)cpu_lduw_be_data_ra(env, addr, ra);
1665
+}
1666
+
1667
+uint32_t cpu_ldl_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
1668
+{
1669
+ return cpu_ldl_be_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
1670
+}
1671
+
1672
+uint64_t cpu_ldq_be_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
1673
+{
1674
+ return cpu_ldq_be_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
1675
+}
1676
+
1677
+uint32_t cpu_lduw_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
1678
+{
1679
+ return cpu_lduw_le_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
1680
+}
1681
+
1682
+int cpu_ldsw_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
1683
+{
1684
+ return (int16_t)cpu_lduw_le_data_ra(env, addr, ra);
1685
+}
1686
+
1687
+uint32_t cpu_ldl_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
1688
+{
1689
+ return cpu_ldl_le_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
1690
+}
1691
+
1692
+uint64_t cpu_ldq_le_data_ra(CPUArchState *env, abi_ptr addr, uintptr_t ra)
1693
+{
1694
+ return cpu_ldq_le_mmuidx_ra(env, addr, cpu_mmu_index(env, false), ra);
1695
+}
1696
+
1697
+void cpu_stb_data_ra(CPUArchState *env, abi_ptr addr,
1698
+ uint32_t val, uintptr_t ra)
1699
+{
1700
+ cpu_stb_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
1701
+}
1702
+
1703
+void cpu_stw_be_data_ra(CPUArchState *env, abi_ptr addr,
1704
+ uint32_t val, uintptr_t ra)
1705
+{
1706
+ cpu_stw_be_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
1707
+}
1708
+
1709
+void cpu_stl_be_data_ra(CPUArchState *env, abi_ptr addr,
1710
+ uint32_t val, uintptr_t ra)
1711
+{
1712
+ cpu_stl_be_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
1713
+}
1714
+
1715
+void cpu_stq_be_data_ra(CPUArchState *env, abi_ptr addr,
1716
+ uint64_t val, uintptr_t ra)
1717
+{
1718
+ cpu_stq_be_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
1719
+}
1720
+
1721
+void cpu_stw_le_data_ra(CPUArchState *env, abi_ptr addr,
1722
+ uint32_t val, uintptr_t ra)
1723
+{
1724
+ cpu_stw_le_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
1725
+}
1726
+
1727
+void cpu_stl_le_data_ra(CPUArchState *env, abi_ptr addr,
1728
+ uint32_t val, uintptr_t ra)
1729
+{
1730
+ cpu_stl_le_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
1731
+}
1732
+
1733
+void cpu_stq_le_data_ra(CPUArchState *env, abi_ptr addr,
1734
+ uint64_t val, uintptr_t ra)
1735
+{
1736
+ cpu_stq_le_mmuidx_ra(env, addr, val, cpu_mmu_index(env, false), ra);
1737
+}
1738
+
1739
+/*--------------------------*/
1740
+
1741
+uint32_t cpu_ldub_data(CPUArchState *env, abi_ptr addr)
1742
+{
1743
+ return cpu_ldub_data_ra(env, addr, 0);
1744
+}
1745
+
1746
+int cpu_ldsb_data(CPUArchState *env, abi_ptr addr)
1747
+{
1748
+ return (int8_t)cpu_ldub_data(env, addr);
1749
+}
1750
+
1751
+uint32_t cpu_lduw_be_data(CPUArchState *env, abi_ptr addr)
1752
+{
1753
+ return cpu_lduw_be_data_ra(env, addr, 0);
1754
+}
1755
+
1756
+int cpu_ldsw_be_data(CPUArchState *env, abi_ptr addr)
1757
+{
1758
+ return (int16_t)cpu_lduw_be_data(env, addr);
1759
+}
1760
+
1761
+uint32_t cpu_ldl_be_data(CPUArchState *env, abi_ptr addr)
1762
+{
1763
+ return cpu_ldl_be_data_ra(env, addr, 0);
1764
+}
1765
+
1766
+uint64_t cpu_ldq_be_data(CPUArchState *env, abi_ptr addr)
1767
+{
1768
+ return cpu_ldq_be_data_ra(env, addr, 0);
1769
+}
1770
+
1771
+uint32_t cpu_lduw_le_data(CPUArchState *env, abi_ptr addr)
1772
+{
1773
+ return cpu_lduw_le_data_ra(env, addr, 0);
1774
+}
1775
+
1776
+int cpu_ldsw_le_data(CPUArchState *env, abi_ptr addr)
1777
+{
1778
+ return (int16_t)cpu_lduw_le_data(env, addr);
1779
+}
1780
+
1781
+uint32_t cpu_ldl_le_data(CPUArchState *env, abi_ptr addr)
1782
+{
1783
+ return cpu_ldl_le_data_ra(env, addr, 0);
1784
+}
1785
+
1786
+uint64_t cpu_ldq_le_data(CPUArchState *env, abi_ptr addr)
1787
+{
1788
+ return cpu_ldq_le_data_ra(env, addr, 0);
1789
+}
1790
+
1791
+void cpu_stb_data(CPUArchState *env, abi_ptr addr, uint32_t val)
1792
+{
1793
+ cpu_stb_data_ra(env, addr, val, 0);
1794
+}
1795
+
1796
+void cpu_stw_be_data(CPUArchState *env, abi_ptr addr, uint32_t val)
1797
+{
1798
+ cpu_stw_be_data_ra(env, addr, val, 0);
1799
+}
1800
+
1801
+void cpu_stl_be_data(CPUArchState *env, abi_ptr addr, uint32_t val)
1802
+{
1803
+ cpu_stl_be_data_ra(env, addr, val, 0);
1804
+}
1805
+
1806
+void cpu_stq_be_data(CPUArchState *env, abi_ptr addr, uint64_t val)
1807
+{
1808
+ cpu_stq_be_data_ra(env, addr, val, 0);
1809
+}
1810
+
1811
+void cpu_stw_le_data(CPUArchState *env, abi_ptr addr, uint32_t val)
1812
+{
1813
+ cpu_stw_le_data_ra(env, addr, val, 0);
1814
+}
1815
+
1816
+void cpu_stl_le_data(CPUArchState *env, abi_ptr addr, uint32_t val)
1817
+{
1818
+ cpu_stl_le_data_ra(env, addr, val, 0);
1819
+}
1820
+
1821
+void cpu_stq_le_data(CPUArchState *env, abi_ptr addr, uint64_t val)
1822
+{
1823
+ cpu_stq_le_data_ra(env, addr, val, 0);
1824
+}
1825
--
503
--
1826
2.25.1
504
2.17.2
1827
505
1828
506
diff view generated by jsdifflib
1
These functions have been replaced by cpu_*_mmu as the
1
GCC7+ will no longer advertise support for 16-byte __atomic operations
2
most proper interface to use from target code.
2
if only cmpxchg is supported, as for x86_64. Fortunately, x86_64 still
3
has support for __sync_compare_and_swap_16 and we can make use of that.
4
AArch64 does not have, nor ever has had such support, so open-code it.
3
5
4
Hide these declarations from code that should not use them.
6
Reviewed-by: Emilio G. Cota <cota@braap.org>
5
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
8
---
9
include/tcg/tcg-ldst.h | 74 ++++++++++++++++++++++++++++++++++++++++++
9
accel/tcg/atomic_template.h | 20 ++++-
10
include/tcg/tcg.h | 71 ----------------------------------------
10
include/qemu/atomic128.h | 153 ++++++++++++++++++++++++++++++++++++
11
accel/tcg/cputlb.c | 1 +
11
include/qemu/compiler.h | 11 +++
12
tcg/tcg.c | 1 +
12
tcg/tcg.h | 16 ++--
13
tcg/tci.c | 1 +
13
accel/tcg/cputlb.c | 3 +-
14
5 files changed, 77 insertions(+), 71 deletions(-)
14
accel/tcg/user-exec.c | 5 +-
15
create mode 100644 include/tcg/tcg-ldst.h
15
configure | 19 +++++
16
7 files changed, 213 insertions(+), 14 deletions(-)
17
create mode 100644 include/qemu/atomic128.h
16
18
17
diff --git a/include/tcg/tcg-ldst.h b/include/tcg/tcg-ldst.h
19
diff --git a/accel/tcg/atomic_template.h b/accel/tcg/atomic_template.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/accel/tcg/atomic_template.h
22
+++ b/accel/tcg/atomic_template.h
23
@@ -XXX,XX +XXX,XX @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
24
DATA_TYPE ret;
25
26
ATOMIC_TRACE_RMW;
27
+#if DATA_SIZE == 16
28
+ ret = atomic16_cmpxchg(haddr, cmpv, newv);
29
+#else
30
ret = atomic_cmpxchg__nocheck(haddr, cmpv, newv);
31
+#endif
32
ATOMIC_MMU_CLEANUP;
33
return ret;
34
}
35
36
#if DATA_SIZE >= 16
37
+#if HAVE_ATOMIC128
38
ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr EXTRA_ARGS)
39
{
40
ATOMIC_MMU_DECLS;
41
DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP;
42
43
ATOMIC_TRACE_LD;
44
- __atomic_load(haddr, &val, __ATOMIC_RELAXED);
45
+ val = atomic16_read(haddr);
46
ATOMIC_MMU_CLEANUP;
47
return val;
48
}
49
@@ -XXX,XX +XXX,XX @@ void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr,
50
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
51
52
ATOMIC_TRACE_ST;
53
- __atomic_store(haddr, &val, __ATOMIC_RELAXED);
54
+ atomic16_set(haddr, val);
55
ATOMIC_MMU_CLEANUP;
56
}
57
+#endif
58
#else
59
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
60
ABI_TYPE val EXTRA_ARGS)
61
@@ -XXX,XX +XXX,XX @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
62
DATA_TYPE ret;
63
64
ATOMIC_TRACE_RMW;
65
+#if DATA_SIZE == 16
66
+ ret = atomic16_cmpxchg(haddr, BSWAP(cmpv), BSWAP(newv));
67
+#else
68
ret = atomic_cmpxchg__nocheck(haddr, BSWAP(cmpv), BSWAP(newv));
69
+#endif
70
ATOMIC_MMU_CLEANUP;
71
return BSWAP(ret);
72
}
73
74
#if DATA_SIZE >= 16
75
+#if HAVE_ATOMIC128
76
ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr EXTRA_ARGS)
77
{
78
ATOMIC_MMU_DECLS;
79
DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP;
80
81
ATOMIC_TRACE_LD;
82
- __atomic_load(haddr, &val, __ATOMIC_RELAXED);
83
+ val = atomic16_read(haddr);
84
ATOMIC_MMU_CLEANUP;
85
return BSWAP(val);
86
}
87
@@ -XXX,XX +XXX,XX @@ void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr,
88
89
ATOMIC_TRACE_ST;
90
val = BSWAP(val);
91
- __atomic_store(haddr, &val, __ATOMIC_RELAXED);
92
+ atomic16_set(haddr, val);
93
ATOMIC_MMU_CLEANUP;
94
}
95
+#endif
96
#else
97
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
98
ABI_TYPE val EXTRA_ARGS)
99
diff --git a/include/qemu/atomic128.h b/include/qemu/atomic128.h
18
new file mode 100644
100
new file mode 100644
19
index XXXXXXX..XXXXXXX
101
index XXXXXXX..XXXXXXX
20
--- /dev/null
102
--- /dev/null
21
+++ b/include/tcg/tcg-ldst.h
103
+++ b/include/qemu/atomic128.h
22
@@ -XXX,XX +XXX,XX @@
104
@@ -XXX,XX +XXX,XX @@
23
+/*
105
+/*
24
+ * Memory helpers that will be used by TCG generated code.
106
+ * Simple interface for 128-bit atomic operations.
25
+ *
107
+ *
26
+ * Copyright (c) 2008 Fabrice Bellard
108
+ * Copyright (C) 2018 Linaro, Ltd.
27
+ *
109
+ *
28
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
110
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
29
+ * of this software and associated documentation files (the "Software"), to deal
111
+ * See the COPYING file in the top-level directory.
30
+ * in the Software without restriction, including without limitation the rights
112
+ *
31
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
113
+ * See docs/devel/atomics.txt for discussion about the guarantees each
32
+ * copies of the Software, and to permit persons to whom the Software is
114
+ * atomic primitive is meant to provide.
33
+ * furnished to do so, subject to the following conditions:
34
+ *
35
+ * The above copyright notice and this permission notice shall be included in
36
+ * all copies or substantial portions of the Software.
37
+ *
38
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
44
+ * THE SOFTWARE.
45
+ */
115
+ */
46
+
116
+
47
+#ifndef TCG_LDST_H
117
+#ifndef QEMU_ATOMIC128_H
48
+#define TCG_LDST_H 1
118
+#define QEMU_ATOMIC128_H
49
+
119
+
50
+#ifdef CONFIG_SOFTMMU
120
+/*
51
+
121
+ * GCC is a house divided about supporting large atomic operations.
52
+/* Value zero-extended to tcg register size. */
122
+ *
53
+tcg_target_ulong helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr,
123
+ * For hosts that only have large compare-and-swap, a legalistic reading
54
+ MemOpIdx oi, uintptr_t retaddr);
124
+ * of the C++ standard means that one cannot implement __atomic_read on
55
+tcg_target_ulong helper_le_lduw_mmu(CPUArchState *env, target_ulong addr,
125
+ * read-only memory, and thus all atomic operations must synchronize
56
+ MemOpIdx oi, uintptr_t retaddr);
126
+ * through libatomic.
57
+tcg_target_ulong helper_le_ldul_mmu(CPUArchState *env, target_ulong addr,
127
+ *
58
+ MemOpIdx oi, uintptr_t retaddr);
128
+ * See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80878
59
+uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr,
129
+ *
60
+ MemOpIdx oi, uintptr_t retaddr);
130
+ * This interpretation is not especially helpful for QEMU.
61
+tcg_target_ulong helper_be_lduw_mmu(CPUArchState *env, target_ulong addr,
131
+ * For softmmu, all RAM is always read/write from the hypervisor.
62
+ MemOpIdx oi, uintptr_t retaddr);
132
+ * For user-only, if the guest doesn't implement such an __atomic_read
63
+tcg_target_ulong helper_be_ldul_mmu(CPUArchState *env, target_ulong addr,
133
+ * then the host need not worry about it either.
64
+ MemOpIdx oi, uintptr_t retaddr);
134
+ *
65
+uint64_t helper_be_ldq_mmu(CPUArchState *env, target_ulong addr,
135
+ * Moreover, using libatomic is not an option, because its interface is
66
+ MemOpIdx oi, uintptr_t retaddr);
136
+ * built for std::atomic<T>, and requires that *all* accesses to such an
67
+
137
+ * object go through the library. In our case we do not have an object
68
+/* Value sign-extended to tcg register size. */
138
+ * in the C/C++ sense, but a view of memory as seen by the guest.
69
+tcg_target_ulong helper_ret_ldsb_mmu(CPUArchState *env, target_ulong addr,
139
+ * The guest may issue a large atomic operation and then access those
70
+ MemOpIdx oi, uintptr_t retaddr);
140
+ * pieces using word-sized accesses. From the hypervisor, we have no
71
+tcg_target_ulong helper_le_ldsw_mmu(CPUArchState *env, target_ulong addr,
141
+ * way to connect those two actions.
72
+ MemOpIdx oi, uintptr_t retaddr);
142
+ *
73
+tcg_target_ulong helper_le_ldsl_mmu(CPUArchState *env, target_ulong addr,
143
+ * Therefore, special case each platform.
74
+ MemOpIdx oi, uintptr_t retaddr);
144
+ */
75
+tcg_target_ulong helper_be_ldsw_mmu(CPUArchState *env, target_ulong addr,
145
+
76
+ MemOpIdx oi, uintptr_t retaddr);
146
+#if defined(CONFIG_ATOMIC128)
77
+tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr,
147
+static inline Int128 atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
78
+ MemOpIdx oi, uintptr_t retaddr);
148
+{
79
+
149
+ return atomic_cmpxchg__nocheck(ptr, cmp, new);
80
+void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
150
+}
81
+ MemOpIdx oi, uintptr_t retaddr);
151
+# define HAVE_CMPXCHG128 1
82
+void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
152
+#elif defined(CONFIG_CMPXCHG128)
83
+ MemOpIdx oi, uintptr_t retaddr);
153
+static inline Int128 atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
84
+void helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
154
+{
85
+ MemOpIdx oi, uintptr_t retaddr);
155
+ return __sync_val_compare_and_swap_16(ptr, cmp, new);
86
+void helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
156
+}
87
+ MemOpIdx oi, uintptr_t retaddr);
157
+# define HAVE_CMPXCHG128 1
88
+void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
158
+#elif defined(__aarch64__)
89
+ MemOpIdx oi, uintptr_t retaddr);
159
+/* Through gcc 8, aarch64 has no support for 128-bit at all. */
90
+void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
160
+static inline Int128 atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
91
+ MemOpIdx oi, uintptr_t retaddr);
161
+{
92
+void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
162
+ uint64_t cmpl = int128_getlo(cmp), cmph = int128_gethi(cmp);
93
+ MemOpIdx oi, uintptr_t retaddr);
163
+ uint64_t newl = int128_getlo(new), newh = int128_gethi(new);
94
+
164
+ uint64_t oldl, oldh;
95
+#endif /* CONFIG_SOFTMMU */
165
+ uint32_t tmp;
96
+#endif /* TCG_LDST_H */
166
+
97
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
167
+ asm("0: ldaxp %[oldl], %[oldh], %[mem]\n\t"
168
+ "cmp %[oldl], %[cmpl]\n\t"
169
+ "ccmp %[oldh], %[cmph], #0, eq\n\t"
170
+ "b.ne 1f\n\t"
171
+ "stlxp %w[tmp], %[newl], %[newh], %[mem]\n\t"
172
+ "cbnz %w[tmp], 0b\n"
173
+ "1:"
174
+ : [mem] "+m"(*ptr), [tmp] "=&r"(tmp),
175
+ [oldl] "=&r"(oldl), [oldh] "=r"(oldh)
176
+ : [cmpl] "r"(cmpl), [cmph] "r"(cmph),
177
+ [newl] "r"(newl), [newh] "r"(newh)
178
+ : "memory", "cc");
179
+
180
+ return int128_make128(oldl, oldh);
181
+}
182
+# define HAVE_CMPXCHG128 1
183
+#else
184
+/* Fallback definition that must be optimized away, or error. */
185
+Int128 QEMU_ERROR("unsupported atomic")
186
+ atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new);
187
+# define HAVE_CMPXCHG128 0
188
+#endif /* Some definition for HAVE_CMPXCHG128 */
189
+
190
+
191
+#if defined(CONFIG_ATOMIC128)
192
+static inline Int128 atomic16_read(Int128 *ptr)
193
+{
194
+ return atomic_read__nocheck(ptr);
195
+}
196
+
197
+static inline void atomic16_set(Int128 *ptr, Int128 val)
198
+{
199
+ atomic_set__nocheck(ptr, val);
200
+}
201
+
202
+# define HAVE_ATOMIC128 1
203
+#elif !defined(CONFIG_USER_ONLY) && defined(__aarch64__)
204
+/* We can do better than cmpxchg for AArch64. */
205
+static inline Int128 atomic16_read(Int128 *ptr)
206
+{
207
+ uint64_t l, h;
208
+ uint32_t tmp;
209
+
210
+ /* The load must be paired with the store to guarantee not tearing. */
211
+ asm("0: ldxp %[l], %[h], %[mem]\n\t"
212
+ "stxp %w[tmp], %[l], %[h], %[mem]\n\t"
213
+ "cbnz %w[tmp], 0b"
214
+ : [mem] "+m"(*ptr), [tmp] "=r"(tmp), [l] "=r"(l), [h] "=r"(h));
215
+
216
+ return int128_make128(l, h);
217
+}
218
+
219
+static inline void atomic16_set(Int128 *ptr, Int128 val)
220
+{
221
+ uint64_t l = int128_getlo(val), h = int128_gethi(val);
222
+ uint64_t t1, t2;
223
+
224
+ /* Load into temporaries to acquire the exclusive access lock. */
225
+ asm("0: ldxp %[t1], %[t2], %[mem]\n\t"
226
+ "stxp %w[t1], %[l], %[h], %[mem]\n\t"
227
+ "cbnz %w[t1], 0b"
228
+ : [mem] "+m"(*ptr), [t1] "=&r"(t1), [t2] "=&r"(t2)
229
+ : [l] "r"(l), [h] "r"(h));
230
+}
231
+
232
+# define HAVE_ATOMIC128 1
233
+#elif !defined(CONFIG_USER_ONLY) && HAVE_CMPXCHG128
234
+static inline Int128 atomic16_read(Int128 *ptr)
235
+{
236
+ /* Maybe replace 0 with 0, returning the old value. */
237
+ return atomic16_cmpxchg(ptr, 0, 0);
238
+}
239
+
240
+static inline void atomic16_set(Int128 *ptr, Int128 val)
241
+{
242
+ Int128 old = *ptr, cmp;
243
+ do {
244
+ cmp = old;
245
+ old = atomic16_cmpxchg(ptr, cmp, val);
246
+ } while (old != cmp);
247
+}
248
+
249
+# define HAVE_ATOMIC128 1
250
+#else
251
+/* Fallback definitions that must be optimized away, or error. */
252
+Int128 QEMU_ERROR("unsupported atomic") atomic16_read(Int128 *ptr);
253
+void QEMU_ERROR("unsupported atomic") atomic16_set(Int128 *ptr, Int128 val);
254
+# define HAVE_ATOMIC128 0
255
+#endif /* Some definition for HAVE_ATOMIC128 */
256
+
257
+#endif /* QEMU_ATOMIC128_H */
258
diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
98
index XXXXXXX..XXXXXXX 100644
259
index XXXXXXX..XXXXXXX 100644
99
--- a/include/tcg/tcg.h
260
--- a/include/qemu/compiler.h
100
+++ b/include/tcg/tcg.h
261
+++ b/include/qemu/compiler.h
101
@@ -XXX,XX +XXX,XX @@ uint64_t dup_const(unsigned vece, uint64_t c);
262
@@ -XXX,XX +XXX,XX @@
102
: (target_long)dup_const(VECE, C))
263
# define QEMU_FLATTEN
103
#endif
264
#endif
104
265
105
-/*
266
+/*
106
- * Memory helpers that will be used by TCG generated code.
267
+ * If __attribute__((error)) is present, use it to produce an error at
107
- */
268
+ * compile time. Otherwise, one must wait for the linker to diagnose
108
-#ifdef CONFIG_SOFTMMU
269
+ * the missing symbol.
109
-/* Value zero-extended to tcg register size. */
270
+ */
110
-tcg_target_ulong helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr,
271
+#if __has_attribute(error)
111
- MemOpIdx oi, uintptr_t retaddr);
272
+# define QEMU_ERROR(X) __attribute__((error(X)))
112
-tcg_target_ulong helper_le_lduw_mmu(CPUArchState *env, target_ulong addr,
273
+#else
113
- MemOpIdx oi, uintptr_t retaddr);
274
+# define QEMU_ERROR(X)
114
-tcg_target_ulong helper_le_ldul_mmu(CPUArchState *env, target_ulong addr,
275
+#endif
115
- MemOpIdx oi, uintptr_t retaddr);
276
+
116
-uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr,
277
/* Implement C11 _Generic via GCC builtins. Example:
117
- MemOpIdx oi, uintptr_t retaddr);
278
*
118
-tcg_target_ulong helper_be_lduw_mmu(CPUArchState *env, target_ulong addr,
279
* QEMU_GENERIC(x, (float, sinf), (long double, sinl), sin) (x)
119
- MemOpIdx oi, uintptr_t retaddr);
280
diff --git a/tcg/tcg.h b/tcg/tcg.h
120
-tcg_target_ulong helper_be_ldul_mmu(CPUArchState *env, target_ulong addr,
281
index XXXXXXX..XXXXXXX 100644
121
- MemOpIdx oi, uintptr_t retaddr);
282
--- a/tcg/tcg.h
122
-uint64_t helper_be_ldq_mmu(CPUArchState *env, target_ulong addr,
283
+++ b/tcg/tcg.h
123
- MemOpIdx oi, uintptr_t retaddr);
284
@@ -XXX,XX +XXX,XX @@
285
#include "qemu/queue.h"
286
#include "tcg-mo.h"
287
#include "tcg-target.h"
288
+#include "qemu/int128.h"
289
290
/* XXX: make safe guess about sizes */
291
#define MAX_OP_PER_INSTR 266
292
@@ -XXX,XX +XXX,XX @@ GEN_ATOMIC_HELPER_ALL(xchg)
293
#undef GEN_ATOMIC_HELPER
294
#endif /* CONFIG_SOFTMMU */
295
296
-#ifdef CONFIG_ATOMIC128
297
-#include "qemu/int128.h"
124
-
298
-
125
-/* Value sign-extended to tcg register size. */
299
-/* These aren't really a "proper" helpers because TCG cannot manage Int128.
126
-tcg_target_ulong helper_ret_ldsb_mmu(CPUArchState *env, target_ulong addr,
300
- However, use the same format as the others, for use by the backends. */
127
- MemOpIdx oi, uintptr_t retaddr);
301
+/*
128
-tcg_target_ulong helper_le_ldsw_mmu(CPUArchState *env, target_ulong addr,
302
+ * These aren't really a "proper" helpers because TCG cannot manage Int128.
129
- MemOpIdx oi, uintptr_t retaddr);
303
+ * However, use the same format as the others, for use by the backends.
130
-tcg_target_ulong helper_le_ldsl_mmu(CPUArchState *env, target_ulong addr,
304
+ *
131
- MemOpIdx oi, uintptr_t retaddr);
305
+ * The cmpxchg functions are only defined if HAVE_CMPXCHG128;
132
-tcg_target_ulong helper_be_ldsw_mmu(CPUArchState *env, target_ulong addr,
306
+ * the ld/st functions are only defined if HAVE_ATOMIC128,
133
- MemOpIdx oi, uintptr_t retaddr);
307
+ * as defined by <qemu/atomic128.h>.
134
-tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr,
308
+ */
135
- MemOpIdx oi, uintptr_t retaddr);
309
Int128 helper_atomic_cmpxchgo_le_mmu(CPUArchState *env, target_ulong addr,
310
Int128 cmpv, Int128 newv,
311
TCGMemOpIdx oi, uintptr_t retaddr);
312
@@ -XXX,XX +XXX,XX @@ void helper_atomic_sto_le_mmu(CPUArchState *env, target_ulong addr, Int128 val,
313
void helper_atomic_sto_be_mmu(CPUArchState *env, target_ulong addr, Int128 val,
314
TCGMemOpIdx oi, uintptr_t retaddr);
315
316
-#endif /* CONFIG_ATOMIC128 */
136
-
317
-
137
-void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
318
#endif /* TCG_H */
138
- MemOpIdx oi, uintptr_t retaddr);
139
-void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
140
- MemOpIdx oi, uintptr_t retaddr);
141
-void helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
142
- MemOpIdx oi, uintptr_t retaddr);
143
-void helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
144
- MemOpIdx oi, uintptr_t retaddr);
145
-void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
146
- MemOpIdx oi, uintptr_t retaddr);
147
-void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
148
- MemOpIdx oi, uintptr_t retaddr);
149
-void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
150
- MemOpIdx oi, uintptr_t retaddr);
151
-
152
-/* Temporary aliases until backends are converted. */
153
-#ifdef TARGET_WORDS_BIGENDIAN
154
-# define helper_ret_ldsw_mmu helper_be_ldsw_mmu
155
-# define helper_ret_lduw_mmu helper_be_lduw_mmu
156
-# define helper_ret_ldsl_mmu helper_be_ldsl_mmu
157
-# define helper_ret_ldul_mmu helper_be_ldul_mmu
158
-# define helper_ret_ldl_mmu helper_be_ldul_mmu
159
-# define helper_ret_ldq_mmu helper_be_ldq_mmu
160
-# define helper_ret_stw_mmu helper_be_stw_mmu
161
-# define helper_ret_stl_mmu helper_be_stl_mmu
162
-# define helper_ret_stq_mmu helper_be_stq_mmu
163
-#else
164
-# define helper_ret_ldsw_mmu helper_le_ldsw_mmu
165
-# define helper_ret_lduw_mmu helper_le_lduw_mmu
166
-# define helper_ret_ldsl_mmu helper_le_ldsl_mmu
167
-# define helper_ret_ldul_mmu helper_le_ldul_mmu
168
-# define helper_ret_ldl_mmu helper_le_ldul_mmu
169
-# define helper_ret_ldq_mmu helper_le_ldq_mmu
170
-# define helper_ret_stw_mmu helper_le_stw_mmu
171
-# define helper_ret_stl_mmu helper_le_stl_mmu
172
-# define helper_ret_stq_mmu helper_le_stq_mmu
173
-#endif
174
-#endif /* CONFIG_SOFTMMU */
175
-
176
#ifdef CONFIG_DEBUG_TCG
177
void tcg_assert_listed_vecop(TCGOpcode);
178
#else
179
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
319
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
180
index XXXXXXX..XXXXXXX 100644
320
index XXXXXXX..XXXXXXX 100644
181
--- a/accel/tcg/cputlb.c
321
--- a/accel/tcg/cputlb.c
182
+++ b/accel/tcg/cputlb.c
322
+++ b/accel/tcg/cputlb.c
183
@@ -XXX,XX +XXX,XX @@
323
@@ -XXX,XX +XXX,XX @@
184
#ifdef CONFIG_PLUGIN
324
#include "exec/log.h"
185
#include "qemu/plugin-memory.h"
325
#include "exec/helper-proto.h"
186
#endif
326
#include "qemu/atomic.h"
187
+#include "tcg/tcg-ldst.h"
327
+#include "qemu/atomic128.h"
188
328
189
/* DEBUG defines, enable DEBUG_TLB_LOG to log to the CPU_LOG_MMU target */
329
/* DEBUG defines, enable DEBUG_TLB_LOG to log to the CPU_LOG_MMU target */
190
/* #define DEBUG_TLB */
330
/* #define DEBUG_TLB */
191
diff --git a/tcg/tcg.c b/tcg/tcg.c
331
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
332
#include "atomic_template.h"
333
#endif
334
335
-#ifdef CONFIG_ATOMIC128
336
+#if HAVE_CMPXCHG128 || HAVE_ATOMIC128
337
#define DATA_SIZE 16
338
#include "atomic_template.h"
339
#endif
340
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
192
index XXXXXXX..XXXXXXX 100644
341
index XXXXXXX..XXXXXXX 100644
193
--- a/tcg/tcg.c
342
--- a/accel/tcg/user-exec.c
194
+++ b/tcg/tcg.c
343
+++ b/accel/tcg/user-exec.c
195
@@ -XXX,XX +XXX,XX @@
344
@@ -XXX,XX +XXX,XX @@
196
197
#include "elf.h"
198
#include "exec/log.h"
199
+#include "tcg/tcg-ldst.h"
200
#include "tcg-internal.h"
201
202
#ifdef CONFIG_TCG_INTERPRETER
203
diff --git a/tcg/tci.c b/tcg/tci.c
204
index XXXXXXX..XXXXXXX 100644
205
--- a/tcg/tci.c
206
+++ b/tcg/tci.c
207
@@ -XXX,XX +XXX,XX @@
208
#include "tcg/tcg.h" /* MAX_OPC_PARAM_IARGS */
209
#include "exec/cpu_ldst.h"
345
#include "exec/cpu_ldst.h"
210
#include "tcg/tcg-op.h"
346
#include "translate-all.h"
211
+#include "tcg/tcg-ldst.h"
347
#include "exec/helper-proto.h"
212
#include "qemu/compiler.h"
348
+#include "qemu/atomic128.h"
213
#include <ffi.h>
349
214
350
#undef EAX
351
#undef ECX
352
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
353
/* The following is only callable from other helpers, and matches up
354
with the softmmu version. */
355
356
-#ifdef CONFIG_ATOMIC128
357
+#if HAVE_ATOMIC128 || HAVE_CMPXCHG128
358
359
#undef EXTRA_ARGS
360
#undef ATOMIC_NAME
361
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
362
363
#define DATA_SIZE 16
364
#include "atomic_template.h"
365
-#endif /* CONFIG_ATOMIC128 */
366
+#endif
367
diff --git a/configure b/configure
368
index XXXXXXX..XXXXXXX 100755
369
--- a/configure
370
+++ b/configure
371
@@ -XXX,XX +XXX,XX @@ EOF
372
fi
373
fi
374
375
+cmpxchg128=no
376
+if test "$int128" = yes -a "$atomic128" = no; then
377
+ cat > $TMPC << EOF
378
+int main(void)
379
+{
380
+ unsigned __int128 x = 0, y = 0;
381
+ __sync_val_compare_and_swap_16(&x, y, x);
382
+ return 0;
383
+}
384
+EOF
385
+ if compile_prog "" "" ; then
386
+ cmpxchg128=yes
387
+ fi
388
+fi
389
+
390
#########################################
391
# See if 64-bit atomic operations are supported.
392
# Note that without __atomic builtins, we can only
393
@@ -XXX,XX +XXX,XX @@ if test "$atomic128" = "yes" ; then
394
echo "CONFIG_ATOMIC128=y" >> $config_host_mak
395
fi
396
397
+if test "$cmpxchg128" = "yes" ; then
398
+ echo "CONFIG_CMPXCHG128=y" >> $config_host_mak
399
+fi
400
+
401
if test "$atomic64" = "yes" ; then
402
echo "CONFIG_ATOMIC64=y" >> $config_host_mak
403
fi
215
--
404
--
216
2.25.1
405
2.17.2
217
406
218
407
diff view generated by jsdifflib
1
The previous placement in tcg/tcg.h was not logical.
1
Reviewed-by: Emilio G. Cota <cota@braap.org>
2
2
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
3
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
---
4
---
6
include/exec/cpu_ldst.h | 87 +++++++++++++++++++++++++++++++++++
5
target/i386/mem_helper.c | 9 ++++-----
7
include/tcg/tcg.h | 87 -----------------------------------
6
1 file changed, 4 insertions(+), 5 deletions(-)
8
target/arm/helper-a64.c | 1 -
9
target/m68k/op_helper.c | 1 -
10
target/ppc/mem_helper.c | 1 -
11
target/s390x/tcg/mem_helper.c | 1 -
12
6 files changed, 87 insertions(+), 91 deletions(-)
13
7
14
diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
8
diff --git a/target/i386/mem_helper.c b/target/i386/mem_helper.c
15
index XXXXXXX..XXXXXXX 100644
9
index XXXXXXX..XXXXXXX 100644
16
--- a/include/exec/cpu_ldst.h
10
--- a/target/i386/mem_helper.c
17
+++ b/include/exec/cpu_ldst.h
11
+++ b/target/i386/mem_helper.c
18
@@ -XXX,XX +XXX,XX @@
19
#define CPU_LDST_H
20
21
#include "exec/memopidx.h"
22
+#include "qemu/int128.h"
23
24
#if defined(CONFIG_USER_ONLY)
25
/* sparc32plus has 64bit long but 32bit space address
26
@@ -XXX,XX +XXX,XX @@ void cpu_stl_le_mmu(CPUArchState *env, abi_ptr ptr, uint32_t val,
27
void cpu_stq_le_mmu(CPUArchState *env, abi_ptr ptr, uint64_t val,
28
MemOpIdx oi, uintptr_t ra);
29
30
+uint32_t cpu_atomic_cmpxchgb_mmu(CPUArchState *env, target_ulong addr,
31
+ uint32_t cmpv, uint32_t newv,
32
+ MemOpIdx oi, uintptr_t retaddr);
33
+uint32_t cpu_atomic_cmpxchgw_le_mmu(CPUArchState *env, target_ulong addr,
34
+ uint32_t cmpv, uint32_t newv,
35
+ MemOpIdx oi, uintptr_t retaddr);
36
+uint32_t cpu_atomic_cmpxchgl_le_mmu(CPUArchState *env, target_ulong addr,
37
+ uint32_t cmpv, uint32_t newv,
38
+ MemOpIdx oi, uintptr_t retaddr);
39
+uint64_t cpu_atomic_cmpxchgq_le_mmu(CPUArchState *env, target_ulong addr,
40
+ uint64_t cmpv, uint64_t newv,
41
+ MemOpIdx oi, uintptr_t retaddr);
42
+uint32_t cpu_atomic_cmpxchgw_be_mmu(CPUArchState *env, target_ulong addr,
43
+ uint32_t cmpv, uint32_t newv,
44
+ MemOpIdx oi, uintptr_t retaddr);
45
+uint32_t cpu_atomic_cmpxchgl_be_mmu(CPUArchState *env, target_ulong addr,
46
+ uint32_t cmpv, uint32_t newv,
47
+ MemOpIdx oi, uintptr_t retaddr);
48
+uint64_t cpu_atomic_cmpxchgq_be_mmu(CPUArchState *env, target_ulong addr,
49
+ uint64_t cmpv, uint64_t newv,
50
+ MemOpIdx oi, uintptr_t retaddr);
51
+
52
+#define GEN_ATOMIC_HELPER(NAME, TYPE, SUFFIX) \
53
+TYPE cpu_atomic_ ## NAME ## SUFFIX ## _mmu \
54
+ (CPUArchState *env, target_ulong addr, TYPE val, \
55
+ MemOpIdx oi, uintptr_t retaddr);
56
+
57
+#ifdef CONFIG_ATOMIC64
58
+#define GEN_ATOMIC_HELPER_ALL(NAME) \
59
+ GEN_ATOMIC_HELPER(NAME, uint32_t, b) \
60
+ GEN_ATOMIC_HELPER(NAME, uint32_t, w_le) \
61
+ GEN_ATOMIC_HELPER(NAME, uint32_t, w_be) \
62
+ GEN_ATOMIC_HELPER(NAME, uint32_t, l_le) \
63
+ GEN_ATOMIC_HELPER(NAME, uint32_t, l_be) \
64
+ GEN_ATOMIC_HELPER(NAME, uint64_t, q_le) \
65
+ GEN_ATOMIC_HELPER(NAME, uint64_t, q_be)
66
+#else
67
+#define GEN_ATOMIC_HELPER_ALL(NAME) \
68
+ GEN_ATOMIC_HELPER(NAME, uint32_t, b) \
69
+ GEN_ATOMIC_HELPER(NAME, uint32_t, w_le) \
70
+ GEN_ATOMIC_HELPER(NAME, uint32_t, w_be) \
71
+ GEN_ATOMIC_HELPER(NAME, uint32_t, l_le) \
72
+ GEN_ATOMIC_HELPER(NAME, uint32_t, l_be)
73
+#endif
74
+
75
+GEN_ATOMIC_HELPER_ALL(fetch_add)
76
+GEN_ATOMIC_HELPER_ALL(fetch_sub)
77
+GEN_ATOMIC_HELPER_ALL(fetch_and)
78
+GEN_ATOMIC_HELPER_ALL(fetch_or)
79
+GEN_ATOMIC_HELPER_ALL(fetch_xor)
80
+GEN_ATOMIC_HELPER_ALL(fetch_smin)
81
+GEN_ATOMIC_HELPER_ALL(fetch_umin)
82
+GEN_ATOMIC_HELPER_ALL(fetch_smax)
83
+GEN_ATOMIC_HELPER_ALL(fetch_umax)
84
+
85
+GEN_ATOMIC_HELPER_ALL(add_fetch)
86
+GEN_ATOMIC_HELPER_ALL(sub_fetch)
87
+GEN_ATOMIC_HELPER_ALL(and_fetch)
88
+GEN_ATOMIC_HELPER_ALL(or_fetch)
89
+GEN_ATOMIC_HELPER_ALL(xor_fetch)
90
+GEN_ATOMIC_HELPER_ALL(smin_fetch)
91
+GEN_ATOMIC_HELPER_ALL(umin_fetch)
92
+GEN_ATOMIC_HELPER_ALL(smax_fetch)
93
+GEN_ATOMIC_HELPER_ALL(umax_fetch)
94
+
95
+GEN_ATOMIC_HELPER_ALL(xchg)
96
+
97
+#undef GEN_ATOMIC_HELPER_ALL
98
+#undef GEN_ATOMIC_HELPER
99
+
100
+Int128 cpu_atomic_cmpxchgo_le_mmu(CPUArchState *env, target_ulong addr,
101
+ Int128 cmpv, Int128 newv,
102
+ MemOpIdx oi, uintptr_t retaddr);
103
+Int128 cpu_atomic_cmpxchgo_be_mmu(CPUArchState *env, target_ulong addr,
104
+ Int128 cmpv, Int128 newv,
105
+ MemOpIdx oi, uintptr_t retaddr);
106
+
107
+Int128 cpu_atomic_ldo_le_mmu(CPUArchState *env, target_ulong addr,
108
+ MemOpIdx oi, uintptr_t retaddr);
109
+Int128 cpu_atomic_ldo_be_mmu(CPUArchState *env, target_ulong addr,
110
+ MemOpIdx oi, uintptr_t retaddr);
111
+void cpu_atomic_sto_le_mmu(CPUArchState *env, target_ulong addr, Int128 val,
112
+ MemOpIdx oi, uintptr_t retaddr);
113
+void cpu_atomic_sto_be_mmu(CPUArchState *env, target_ulong addr, Int128 val,
114
+ MemOpIdx oi, uintptr_t retaddr);
115
+
116
#if defined(CONFIG_USER_ONLY)
117
118
extern __thread uintptr_t helper_retaddr;
119
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
120
index XXXXXXX..XXXXXXX 100644
121
--- a/include/tcg/tcg.h
122
+++ b/include/tcg/tcg.h
123
@@ -XXX,XX +XXX,XX @@
124
#include "qemu/queue.h"
125
#include "tcg/tcg-mo.h"
126
#include "tcg-target.h"
127
-#include "qemu/int128.h"
128
#include "tcg/tcg-cond.h"
129
130
/* XXX: make safe guess about sizes */
131
@@ -XXX,XX +XXX,XX @@ void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
132
#endif
133
#endif /* CONFIG_SOFTMMU */
134
135
-uint32_t cpu_atomic_cmpxchgb_mmu(CPUArchState *env, target_ulong addr,
136
- uint32_t cmpv, uint32_t newv,
137
- MemOpIdx oi, uintptr_t retaddr);
138
-uint32_t cpu_atomic_cmpxchgw_le_mmu(CPUArchState *env, target_ulong addr,
139
- uint32_t cmpv, uint32_t newv,
140
- MemOpIdx oi, uintptr_t retaddr);
141
-uint32_t cpu_atomic_cmpxchgl_le_mmu(CPUArchState *env, target_ulong addr,
142
- uint32_t cmpv, uint32_t newv,
143
- MemOpIdx oi, uintptr_t retaddr);
144
-uint64_t cpu_atomic_cmpxchgq_le_mmu(CPUArchState *env, target_ulong addr,
145
- uint64_t cmpv, uint64_t newv,
146
- MemOpIdx oi, uintptr_t retaddr);
147
-uint32_t cpu_atomic_cmpxchgw_be_mmu(CPUArchState *env, target_ulong addr,
148
- uint32_t cmpv, uint32_t newv,
149
- MemOpIdx oi, uintptr_t retaddr);
150
-uint32_t cpu_atomic_cmpxchgl_be_mmu(CPUArchState *env, target_ulong addr,
151
- uint32_t cmpv, uint32_t newv,
152
- MemOpIdx oi, uintptr_t retaddr);
153
-uint64_t cpu_atomic_cmpxchgq_be_mmu(CPUArchState *env, target_ulong addr,
154
- uint64_t cmpv, uint64_t newv,
155
- MemOpIdx oi, uintptr_t retaddr);
156
-
157
-#define GEN_ATOMIC_HELPER(NAME, TYPE, SUFFIX) \
158
-TYPE cpu_atomic_ ## NAME ## SUFFIX ## _mmu \
159
- (CPUArchState *env, target_ulong addr, TYPE val, \
160
- MemOpIdx oi, uintptr_t retaddr);
161
-
162
-#ifdef CONFIG_ATOMIC64
163
-#define GEN_ATOMIC_HELPER_ALL(NAME) \
164
- GEN_ATOMIC_HELPER(NAME, uint32_t, b) \
165
- GEN_ATOMIC_HELPER(NAME, uint32_t, w_le) \
166
- GEN_ATOMIC_HELPER(NAME, uint32_t, w_be) \
167
- GEN_ATOMIC_HELPER(NAME, uint32_t, l_le) \
168
- GEN_ATOMIC_HELPER(NAME, uint32_t, l_be) \
169
- GEN_ATOMIC_HELPER(NAME, uint64_t, q_le) \
170
- GEN_ATOMIC_HELPER(NAME, uint64_t, q_be)
171
-#else
172
-#define GEN_ATOMIC_HELPER_ALL(NAME) \
173
- GEN_ATOMIC_HELPER(NAME, uint32_t, b) \
174
- GEN_ATOMIC_HELPER(NAME, uint32_t, w_le) \
175
- GEN_ATOMIC_HELPER(NAME, uint32_t, w_be) \
176
- GEN_ATOMIC_HELPER(NAME, uint32_t, l_le) \
177
- GEN_ATOMIC_HELPER(NAME, uint32_t, l_be)
178
-#endif
179
-
180
-GEN_ATOMIC_HELPER_ALL(fetch_add)
181
-GEN_ATOMIC_HELPER_ALL(fetch_sub)
182
-GEN_ATOMIC_HELPER_ALL(fetch_and)
183
-GEN_ATOMIC_HELPER_ALL(fetch_or)
184
-GEN_ATOMIC_HELPER_ALL(fetch_xor)
185
-GEN_ATOMIC_HELPER_ALL(fetch_smin)
186
-GEN_ATOMIC_HELPER_ALL(fetch_umin)
187
-GEN_ATOMIC_HELPER_ALL(fetch_smax)
188
-GEN_ATOMIC_HELPER_ALL(fetch_umax)
189
-
190
-GEN_ATOMIC_HELPER_ALL(add_fetch)
191
-GEN_ATOMIC_HELPER_ALL(sub_fetch)
192
-GEN_ATOMIC_HELPER_ALL(and_fetch)
193
-GEN_ATOMIC_HELPER_ALL(or_fetch)
194
-GEN_ATOMIC_HELPER_ALL(xor_fetch)
195
-GEN_ATOMIC_HELPER_ALL(smin_fetch)
196
-GEN_ATOMIC_HELPER_ALL(umin_fetch)
197
-GEN_ATOMIC_HELPER_ALL(smax_fetch)
198
-GEN_ATOMIC_HELPER_ALL(umax_fetch)
199
-
200
-GEN_ATOMIC_HELPER_ALL(xchg)
201
-
202
-#undef GEN_ATOMIC_HELPER_ALL
203
-#undef GEN_ATOMIC_HELPER
204
-
205
-Int128 cpu_atomic_cmpxchgo_le_mmu(CPUArchState *env, target_ulong addr,
206
- Int128 cmpv, Int128 newv,
207
- MemOpIdx oi, uintptr_t retaddr);
208
-Int128 cpu_atomic_cmpxchgo_be_mmu(CPUArchState *env, target_ulong addr,
209
- Int128 cmpv, Int128 newv,
210
- MemOpIdx oi, uintptr_t retaddr);
211
-
212
-Int128 cpu_atomic_ldo_le_mmu(CPUArchState *env, target_ulong addr,
213
- MemOpIdx oi, uintptr_t retaddr);
214
-Int128 cpu_atomic_ldo_be_mmu(CPUArchState *env, target_ulong addr,
215
- MemOpIdx oi, uintptr_t retaddr);
216
-void cpu_atomic_sto_le_mmu(CPUArchState *env, target_ulong addr, Int128 val,
217
- MemOpIdx oi, uintptr_t retaddr);
218
-void cpu_atomic_sto_be_mmu(CPUArchState *env, target_ulong addr, Int128 val,
219
- MemOpIdx oi, uintptr_t retaddr);
220
-
221
#ifdef CONFIG_DEBUG_TCG
222
void tcg_assert_listed_vecop(TCGOpcode);
223
#else
224
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
225
index XXXXXXX..XXXXXXX 100644
226
--- a/target/arm/helper-a64.c
227
+++ b/target/arm/helper-a64.c
228
@@ -XXX,XX +XXX,XX @@
229
#include "exec/cpu_ldst.h"
230
#include "qemu/int128.h"
231
#include "qemu/atomic128.h"
232
-#include "tcg/tcg.h"
233
#include "fpu/softfloat.h"
234
#include <zlib.h> /* For crc32 */
235
236
diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c
237
index XXXXXXX..XXXXXXX 100644
238
--- a/target/m68k/op_helper.c
239
+++ b/target/m68k/op_helper.c
240
@@ -XXX,XX +XXX,XX @@
12
@@ -XXX,XX +XXX,XX @@
241
#include "exec/exec-all.h"
13
#include "exec/exec-all.h"
242
#include "exec/cpu_ldst.h"
14
#include "exec/cpu_ldst.h"
243
#include "semihosting/semihost.h"
244
-#include "tcg/tcg.h"
245
246
#if !defined(CONFIG_USER_ONLY)
247
248
diff --git a/target/ppc/mem_helper.c b/target/ppc/mem_helper.c
249
index XXXXXXX..XXXXXXX 100644
250
--- a/target/ppc/mem_helper.c
251
+++ b/target/ppc/mem_helper.c
252
@@ -XXX,XX +XXX,XX @@
253
#include "exec/helper-proto.h"
254
#include "helper_regs.h"
255
#include "exec/cpu_ldst.h"
256
-#include "tcg/tcg.h"
257
#include "internal.h"
258
#include "qemu/atomic128.h"
259
260
diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c
261
index XXXXXXX..XXXXXXX 100644
262
--- a/target/s390x/tcg/mem_helper.c
263
+++ b/target/s390x/tcg/mem_helper.c
264
@@ -XXX,XX +XXX,XX @@
265
#include "exec/cpu_ldst.h"
266
#include "qemu/int128.h"
15
#include "qemu/int128.h"
267
#include "qemu/atomic128.h"
16
+#include "qemu/atomic128.h"
268
-#include "tcg/tcg.h"
17
#include "tcg.h"
269
#include "trace.h"
18
270
19
void helper_cmpxchg8b_unlocked(CPUX86State *env, target_ulong a0)
271
#if !defined(CONFIG_USER_ONLY)
20
@@ -XXX,XX +XXX,XX @@ void helper_cmpxchg16b(CPUX86State *env, target_ulong a0)
21
22
if ((a0 & 0xf) != 0) {
23
raise_exception_ra(env, EXCP0D_GPF, ra);
24
- } else {
25
-#ifndef CONFIG_ATOMIC128
26
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
27
-#else
28
+ } else if (HAVE_CMPXCHG128) {
29
int eflags = cpu_cc_compute_all(env, CC_OP);
30
31
Int128 cmpv = int128_make128(env->regs[R_EAX], env->regs[R_EDX]);
32
@@ -XXX,XX +XXX,XX @@ void helper_cmpxchg16b(CPUX86State *env, target_ulong a0)
33
eflags &= ~CC_Z;
34
}
35
CC_SRC = eflags;
36
-#endif
37
+ } else {
38
+ cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
39
}
40
}
41
#endif
272
--
42
--
273
2.25.1
43
2.17.2
274
44
275
45
diff view generated by jsdifflib
1
The helper_*_mmu functions were the only thing available
1
Reviewed-by: Emilio G. Cota <cota@braap.org>
2
when this code was written. This could have been adjusted
3
when we added cpu_*_mmuidx_ra, but now we can most easily
4
use the newest set of interfaces.
5
6
Cc: qemu-arm@nongnu.org
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
3
---
10
target/arm/helper-a64.c | 52 +++++++----------------------------------
4
target/arm/helper-a64.c | 259 +++++++++++++++++++++-------------------
11
target/arm/m_helper.c | 6 ++---
5
1 file changed, 133 insertions(+), 126 deletions(-)
12
2 files changed, 11 insertions(+), 47 deletions(-)
13
6
14
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
7
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
15
index XXXXXXX..XXXXXXX 100644
8
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-a64.c
9
--- a/target/arm/helper-a64.c
17
+++ b/target/arm/helper-a64.c
10
+++ b/target/arm/helper-a64.c
18
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(paired_cmpxchg64_le)(CPUARMState *env, uint64_t addr,
11
@@ -XXX,XX +XXX,XX @@
19
uintptr_t ra = GETPC();
12
#include "exec/exec-all.h"
20
uint64_t o0, o1;
13
#include "exec/cpu_ldst.h"
14
#include "qemu/int128.h"
15
+#include "qemu/atomic128.h"
16
#include "tcg.h"
17
#include "fpu/softfloat.h"
18
#include <zlib.h> /* For crc32 */
19
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(crc32c_64)(uint64_t acc, uint64_t val, uint32_t bytes)
20
return crc32c(acc, buf, bytes) ^ 0xffffffff;
21
}
22
23
-/* Returns 0 on success; 1 otherwise. */
24
-static uint64_t do_paired_cmpxchg64_le(CPUARMState *env, uint64_t addr,
25
- uint64_t new_lo, uint64_t new_hi,
26
- bool parallel, uintptr_t ra)
27
+uint64_t HELPER(paired_cmpxchg64_le)(CPUARMState *env, uint64_t addr,
28
+ uint64_t new_lo, uint64_t new_hi)
29
{
30
- Int128 oldv, cmpv, newv;
31
+ Int128 cmpv = int128_make128(env->exclusive_val, env->exclusive_high);
32
+ Int128 newv = int128_make128(new_lo, new_hi);
33
+ Int128 oldv;
34
+ uintptr_t ra = GETPC();
35
+ uint64_t o0, o1;
21
bool success;
36
bool success;
37
38
- cmpv = int128_make128(env->exclusive_val, env->exclusive_high);
39
- newv = int128_make128(new_lo, new_hi);
40
-
41
- if (parallel) {
42
-#ifndef CONFIG_ATOMIC128
43
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
44
-#else
45
- int mem_idx = cpu_mmu_index(env, false);
46
- TCGMemOpIdx oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
47
- oldv = helper_atomic_cmpxchgo_le_mmu(env, addr, cmpv, newv, oi, ra);
48
- success = int128_eq(oldv, cmpv);
49
-#endif
50
- } else {
51
- uint64_t o0, o1;
52
-
53
#ifdef CONFIG_USER_ONLY
54
- /* ??? Enforce alignment. */
55
- uint64_t *haddr = g2h(addr);
56
+ /* ??? Enforce alignment. */
57
+ uint64_t *haddr = g2h(addr);
58
59
- helper_retaddr = ra;
60
- o0 = ldq_le_p(haddr + 0);
61
- o1 = ldq_le_p(haddr + 1);
62
- oldv = int128_make128(o0, o1);
63
+ helper_retaddr = ra;
64
+ o0 = ldq_le_p(haddr + 0);
65
+ o1 = ldq_le_p(haddr + 1);
66
+ oldv = int128_make128(o0, o1);
67
68
- success = int128_eq(oldv, cmpv);
69
- if (success) {
70
- stq_le_p(haddr + 0, int128_getlo(newv));
71
- stq_le_p(haddr + 1, int128_gethi(newv));
72
- }
73
- helper_retaddr = 0;
74
-#else
75
- int mem_idx = cpu_mmu_index(env, false);
76
- TCGMemOpIdx oi0 = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
77
- TCGMemOpIdx oi1 = make_memop_idx(MO_LEQ, mem_idx);
78
-
79
- o0 = helper_le_ldq_mmu(env, addr + 0, oi0, ra);
80
- o1 = helper_le_ldq_mmu(env, addr + 8, oi1, ra);
81
- oldv = int128_make128(o0, o1);
82
-
83
- success = int128_eq(oldv, cmpv);
84
- if (success) {
85
- helper_le_stq_mmu(env, addr + 0, int128_getlo(newv), oi1, ra);
86
- helper_le_stq_mmu(env, addr + 8, int128_gethi(newv), oi1, ra);
87
- }
88
-#endif
89
+ success = int128_eq(oldv, cmpv);
90
+ if (success) {
91
+ stq_le_p(haddr + 0, int128_getlo(newv));
92
+ stq_le_p(haddr + 1, int128_gethi(newv));
93
}
94
+ helper_retaddr = 0;
95
+#else
96
+ int mem_idx = cpu_mmu_index(env, false);
97
+ TCGMemOpIdx oi0 = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
98
+ TCGMemOpIdx oi1 = make_memop_idx(MO_LEQ, mem_idx);
99
+
100
+ o0 = helper_le_ldq_mmu(env, addr + 0, oi0, ra);
101
+ o1 = helper_le_ldq_mmu(env, addr + 8, oi1, ra);
102
+ oldv = int128_make128(o0, o1);
103
+
104
+ success = int128_eq(oldv, cmpv);
105
+ if (success) {
106
+ helper_le_stq_mmu(env, addr + 0, int128_getlo(newv), oi1, ra);
107
+ helper_le_stq_mmu(env, addr + 8, int128_gethi(newv), oi1, ra);
108
+ }
109
+#endif
110
111
return !success;
112
}
113
114
-uint64_t HELPER(paired_cmpxchg64_le)(CPUARMState *env, uint64_t addr,
115
- uint64_t new_lo, uint64_t new_hi)
116
-{
117
- return do_paired_cmpxchg64_le(env, addr, new_lo, new_hi, false, GETPC());
118
-}
119
-
120
uint64_t HELPER(paired_cmpxchg64_le_parallel)(CPUARMState *env, uint64_t addr,
121
uint64_t new_lo, uint64_t new_hi)
122
-{
123
- return do_paired_cmpxchg64_le(env, addr, new_lo, new_hi, true, GETPC());
124
-}
125
-
126
-static uint64_t do_paired_cmpxchg64_be(CPUARMState *env, uint64_t addr,
127
- uint64_t new_lo, uint64_t new_hi,
128
- bool parallel, uintptr_t ra)
129
{
130
Int128 oldv, cmpv, newv;
131
+ uintptr_t ra = GETPC();
132
bool success;
133
+ int mem_idx;
134
+ TCGMemOpIdx oi;
135
136
- /* high and low need to be switched here because this is not actually a
137
- * 128bit store but two doublewords stored consecutively
138
- */
139
- cmpv = int128_make128(env->exclusive_high, env->exclusive_val);
140
- newv = int128_make128(new_hi, new_lo);
141
-
142
- if (parallel) {
143
-#ifndef CONFIG_ATOMIC128
144
+ if (!HAVE_CMPXCHG128) {
145
cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
146
-#else
147
- int mem_idx = cpu_mmu_index(env, false);
148
- TCGMemOpIdx oi = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx);
149
- oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra);
150
- success = int128_eq(oldv, cmpv);
151
-#endif
152
- } else {
153
- uint64_t o0, o1;
22
-
154
-
23
-#ifdef CONFIG_USER_ONLY
155
-#ifdef CONFIG_USER_ONLY
24
- /* ??? Enforce alignment. */
156
- /* ??? Enforce alignment. */
25
- uint64_t *haddr = g2h(env_cpu(env), addr);
157
- uint64_t *haddr = g2h(addr);
26
-
158
-
27
- set_helper_retaddr(ra);
159
- helper_retaddr = ra;
28
- o0 = ldq_le_p(haddr + 0);
160
- o1 = ldq_be_p(haddr + 0);
29
- o1 = ldq_le_p(haddr + 1);
161
- o0 = ldq_be_p(haddr + 1);
30
- oldv = int128_make128(o0, o1);
162
- oldv = int128_make128(o0, o1);
31
-
163
-
32
- success = int128_eq(oldv, cmpv);
164
- success = int128_eq(oldv, cmpv);
33
- if (success) {
165
- if (success) {
34
- stq_le_p(haddr + 0, int128_getlo(newv));
166
- stq_be_p(haddr + 0, int128_gethi(newv));
35
- stq_le_p(haddr + 1, int128_gethi(newv));
167
- stq_be_p(haddr + 1, int128_getlo(newv));
36
- }
168
- }
37
- clear_helper_retaddr();
169
- helper_retaddr = 0;
38
-#else
170
-#else
39
int mem_idx = cpu_mmu_index(env, false);
171
- int mem_idx = cpu_mmu_index(env, false);
40
MemOpIdx oi0 = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
172
- TCGMemOpIdx oi0 = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx);
41
MemOpIdx oi1 = make_memop_idx(MO_LEQ, mem_idx);
173
- TCGMemOpIdx oi1 = make_memop_idx(MO_BEQ, mem_idx);
42
174
-
43
- o0 = helper_le_ldq_mmu(env, addr + 0, oi0, ra);
175
- o1 = helper_be_ldq_mmu(env, addr + 0, oi0, ra);
44
- o1 = helper_le_ldq_mmu(env, addr + 8, oi1, ra);
176
- o0 = helper_be_ldq_mmu(env, addr + 8, oi1, ra);
45
+ o0 = cpu_ldq_le_mmu(env, addr + 0, oi0, ra);
177
- oldv = int128_make128(o0, o1);
46
+ o1 = cpu_ldq_le_mmu(env, addr + 8, oi1, ra);
178
-
47
oldv = int128_make128(o0, o1);
179
- success = int128_eq(oldv, cmpv);
48
180
- if (success) {
49
success = int128_eq(oldv, cmpv);
181
- helper_be_stq_mmu(env, addr + 0, int128_gethi(newv), oi1, ra);
50
if (success) {
182
- helper_be_stq_mmu(env, addr + 8, int128_getlo(newv), oi1, ra);
51
- helper_le_stq_mmu(env, addr + 0, int128_getlo(newv), oi1, ra);
183
- }
52
- helper_le_stq_mmu(env, addr + 8, int128_gethi(newv), oi1, ra);
184
-#endif
53
+ cpu_stq_le_mmu(env, addr + 0, int128_getlo(newv), oi1, ra);
54
+ cpu_stq_le_mmu(env, addr + 8, int128_gethi(newv), oi1, ra);
55
}
185
}
56
-#endif
186
57
187
+ mem_idx = cpu_mmu_index(env, false);
188
+ oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
189
+
190
+ cmpv = int128_make128(env->exclusive_val, env->exclusive_high);
191
+ newv = int128_make128(new_lo, new_hi);
192
+ oldv = helper_atomic_cmpxchgo_le_mmu(env, addr, cmpv, newv, oi, ra);
193
+
194
+ success = int128_eq(oldv, cmpv);
58
return !success;
195
return !success;
59
}
196
}
60
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(paired_cmpxchg64_be)(CPUARMState *env, uint64_t addr,
197
61
uintptr_t ra = GETPC();
198
uint64_t HELPER(paired_cmpxchg64_be)(CPUARMState *env, uint64_t addr,
62
uint64_t o0, o1;
199
uint64_t new_lo, uint64_t new_hi)
63
bool success;
200
{
64
-
201
- return do_paired_cmpxchg64_be(env, addr, new_lo, new_hi, false, GETPC());
65
-#ifdef CONFIG_USER_ONLY
202
+ /*
66
- /* ??? Enforce alignment. */
203
+ * High and low need to be switched here because this is not actually a
67
- uint64_t *haddr = g2h(env_cpu(env), addr);
204
+ * 128bit store but two doublewords stored consecutively
68
-
205
+ */
69
- set_helper_retaddr(ra);
206
+ Int128 cmpv = int128_make128(env->exclusive_val, env->exclusive_high);
70
- o1 = ldq_be_p(haddr + 0);
207
+ Int128 newv = int128_make128(new_lo, new_hi);
71
- o0 = ldq_be_p(haddr + 1);
208
+ Int128 oldv;
72
- oldv = int128_make128(o0, o1);
209
+ uintptr_t ra = GETPC();
73
-
210
+ uint64_t o0, o1;
74
- success = int128_eq(oldv, cmpv);
211
+ bool success;
75
- if (success) {
212
+
76
- stq_be_p(haddr + 0, int128_gethi(newv));
213
+#ifdef CONFIG_USER_ONLY
77
- stq_be_p(haddr + 1, int128_getlo(newv));
214
+ /* ??? Enforce alignment. */
78
- }
215
+ uint64_t *haddr = g2h(addr);
79
- clear_helper_retaddr();
216
+
80
-#else
217
+ helper_retaddr = ra;
81
int mem_idx = cpu_mmu_index(env, false);
218
+ o1 = ldq_be_p(haddr + 0);
82
MemOpIdx oi0 = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx);
219
+ o0 = ldq_be_p(haddr + 1);
83
MemOpIdx oi1 = make_memop_idx(MO_BEQ, mem_idx);
220
+ oldv = int128_make128(o0, o1);
84
221
+
85
- o1 = helper_be_ldq_mmu(env, addr + 0, oi0, ra);
222
+ success = int128_eq(oldv, cmpv);
86
- o0 = helper_be_ldq_mmu(env, addr + 8, oi1, ra);
223
+ if (success) {
87
+ o1 = cpu_ldq_be_mmu(env, addr + 0, oi0, ra);
224
+ stq_be_p(haddr + 0, int128_gethi(newv));
88
+ o0 = cpu_ldq_be_mmu(env, addr + 8, oi1, ra);
225
+ stq_be_p(haddr + 1, int128_getlo(newv));
89
oldv = int128_make128(o0, o1);
226
+ }
90
227
+ helper_retaddr = 0;
91
success = int128_eq(oldv, cmpv);
228
+#else
92
if (success) {
229
+ int mem_idx = cpu_mmu_index(env, false);
93
- helper_be_stq_mmu(env, addr + 0, int128_gethi(newv), oi1, ra);
230
+ TCGMemOpIdx oi0 = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx);
94
- helper_be_stq_mmu(env, addr + 8, int128_getlo(newv), oi1, ra);
231
+ TCGMemOpIdx oi1 = make_memop_idx(MO_BEQ, mem_idx);
95
+ cpu_stq_be_mmu(env, addr + 0, int128_gethi(newv), oi1, ra);
232
+
96
+ cpu_stq_be_mmu(env, addr + 8, int128_getlo(newv), oi1, ra);
233
+ o1 = helper_be_ldq_mmu(env, addr + 0, oi0, ra);
97
}
234
+ o0 = helper_be_ldq_mmu(env, addr + 8, oi1, ra);
98
-#endif
235
+ oldv = int128_make128(o0, o1);
99
236
+
100
return !success;
237
+ success = int128_eq(oldv, cmpv);
101
}
238
+ if (success) {
102
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
239
+ helper_be_stq_mmu(env, addr + 0, int128_gethi(newv), oi1, ra);
103
index XXXXXXX..XXXXXXX 100644
240
+ helper_be_stq_mmu(env, addr + 8, int128_getlo(newv), oi1, ra);
104
--- a/target/arm/m_helper.c
241
+ }
105
+++ b/target/arm/m_helper.c
242
+#endif
106
@@ -XXX,XX +XXX,XX @@ static bool do_v7m_function_return(ARMCPU *cpu)
243
+
107
* do them as secure, so work out what MMU index that is.
244
+ return !success;
108
*/
245
}
109
mmu_idx = arm_v7m_mmu_idx_for_secstate(env, true);
246
110
- oi = make_memop_idx(MO_LE, arm_to_core_mmu_idx(mmu_idx));
247
uint64_t HELPER(paired_cmpxchg64_be_parallel)(CPUARMState *env, uint64_t addr,
111
- newpc = helper_le_ldul_mmu(env, frameptr, oi, 0);
248
- uint64_t new_lo, uint64_t new_hi)
112
- newpsr = helper_le_ldul_mmu(env, frameptr + 4, oi, 0);
249
+ uint64_t new_lo, uint64_t new_hi)
113
+ oi = make_memop_idx(MO_LEUL, arm_to_core_mmu_idx(mmu_idx));
250
{
114
+ newpc = cpu_ldl_le_mmu(env, frameptr, oi, 0);
251
- return do_paired_cmpxchg64_be(env, addr, new_lo, new_hi, true, GETPC());
115
+ newpsr = cpu_ldl_le_mmu(env, frameptr + 4, oi, 0);
252
+ Int128 oldv, cmpv, newv;
116
253
+ uintptr_t ra = GETPC();
117
/* Consistency checks on new IPSR */
254
+ bool success;
118
newpsr_exc = newpsr & XPSR_EXCP;
255
+ int mem_idx;
256
+ TCGMemOpIdx oi;
257
+
258
+ if (!HAVE_CMPXCHG128) {
259
+ cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
260
+ }
261
+
262
+ mem_idx = cpu_mmu_index(env, false);
263
+ oi = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx);
264
+
265
+ /*
266
+ * High and low need to be switched here because this is not actually a
267
+ * 128bit store but two doublewords stored consecutively
268
+ */
269
+ cmpv = int128_make128(env->exclusive_high, env->exclusive_val);
270
+ newv = int128_make128(new_hi, new_lo);
271
+ oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra);
272
+
273
+ success = int128_eq(oldv, cmpv);
274
+ return !success;
275
}
276
277
/* Writes back the old data into Rs. */
278
void HELPER(casp_le_parallel)(CPUARMState *env, uint32_t rs, uint64_t addr,
279
uint64_t new_lo, uint64_t new_hi)
280
{
281
- uintptr_t ra = GETPC();
282
-#ifndef CONFIG_ATOMIC128
283
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
284
-#else
285
Int128 oldv, cmpv, newv;
286
+ uintptr_t ra = GETPC();
287
+ int mem_idx;
288
+ TCGMemOpIdx oi;
289
+
290
+ if (!HAVE_CMPXCHG128) {
291
+ cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
292
+ }
293
+
294
+ mem_idx = cpu_mmu_index(env, false);
295
+ oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
296
297
cmpv = int128_make128(env->xregs[rs], env->xregs[rs + 1]);
298
newv = int128_make128(new_lo, new_hi);
299
-
300
- int mem_idx = cpu_mmu_index(env, false);
301
- TCGMemOpIdx oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
302
oldv = helper_atomic_cmpxchgo_le_mmu(env, addr, cmpv, newv, oi, ra);
303
304
env->xregs[rs] = int128_getlo(oldv);
305
env->xregs[rs + 1] = int128_gethi(oldv);
306
-#endif
307
}
308
309
void HELPER(casp_be_parallel)(CPUARMState *env, uint32_t rs, uint64_t addr,
310
uint64_t new_hi, uint64_t new_lo)
311
{
312
- uintptr_t ra = GETPC();
313
-#ifndef CONFIG_ATOMIC128
314
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
315
-#else
316
Int128 oldv, cmpv, newv;
317
+ uintptr_t ra = GETPC();
318
+ int mem_idx;
319
+ TCGMemOpIdx oi;
320
+
321
+ if (!HAVE_CMPXCHG128) {
322
+ cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
323
+ }
324
+
325
+ mem_idx = cpu_mmu_index(env, false);
326
+ oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
327
328
cmpv = int128_make128(env->xregs[rs + 1], env->xregs[rs]);
329
newv = int128_make128(new_lo, new_hi);
330
-
331
- int mem_idx = cpu_mmu_index(env, false);
332
- TCGMemOpIdx oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
333
oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra);
334
335
env->xregs[rs + 1] = int128_getlo(oldv);
336
env->xregs[rs] = int128_gethi(oldv);
337
-#endif
338
}
339
340
/*
119
--
341
--
120
2.25.1
342
2.17.2
121
343
122
344
diff view generated by jsdifflib
1
Cc: qemu-arm@nongnu.org
1
Reviewed-by: Emilio G. Cota <cota@braap.org>
2
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
---
4
---
5
target/arm/helper-a64.c | 8 ++++----
5
target/arm/helper-a64.c | 16 ++++------------
6
1 file changed, 4 insertions(+), 4 deletions(-)
6
target/arm/translate-a64.c | 38 ++++++++++++++++++++++----------------
7
2 files changed, 26 insertions(+), 28 deletions(-)
7
8
8
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
9
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
9
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
10
--- a/target/arm/helper-a64.c
11
--- a/target/arm/helper-a64.c
11
+++ b/target/arm/helper-a64.c
12
+++ b/target/arm/helper-a64.c
12
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(paired_cmpxchg64_le_parallel)(CPUARMState *env, uint64_t addr,
13
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(paired_cmpxchg64_le_parallel)(CPUARMState *env, uint64_t addr,
13
assert(HAVE_CMPXCHG128);
14
int mem_idx;
15
TCGMemOpIdx oi;
16
17
- if (!HAVE_CMPXCHG128) {
18
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
19
- }
20
+ assert(HAVE_CMPXCHG128);
14
21
15
mem_idx = cpu_mmu_index(env, false);
22
mem_idx = cpu_mmu_index(env, false);
16
- oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
23
oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
17
+ oi = make_memop_idx(MO_LE | MO_128 | MO_ALIGN, mem_idx);
18
19
cmpv = int128_make128(env->exclusive_val, env->exclusive_high);
20
newv = int128_make128(new_lo, new_hi);
21
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(paired_cmpxchg64_be_parallel)(CPUARMState *env, uint64_t addr,
24
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(paired_cmpxchg64_be_parallel)(CPUARMState *env, uint64_t addr,
22
assert(HAVE_CMPXCHG128);
25
int mem_idx;
26
TCGMemOpIdx oi;
27
28
- if (!HAVE_CMPXCHG128) {
29
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
30
- }
31
+ assert(HAVE_CMPXCHG128);
23
32
24
mem_idx = cpu_mmu_index(env, false);
33
mem_idx = cpu_mmu_index(env, false);
25
- oi = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx);
34
oi = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx);
26
+ oi = make_memop_idx(MO_BE | MO_128 | MO_ALIGN, mem_idx);
27
28
/*
29
* High and low need to be switched here because this is not actually a
30
@@ -XXX,XX +XXX,XX @@ void HELPER(casp_le_parallel)(CPUARMState *env, uint32_t rs, uint64_t addr,
35
@@ -XXX,XX +XXX,XX @@ void HELPER(casp_le_parallel)(CPUARMState *env, uint32_t rs, uint64_t addr,
31
assert(HAVE_CMPXCHG128);
36
int mem_idx;
37
TCGMemOpIdx oi;
38
39
- if (!HAVE_CMPXCHG128) {
40
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
41
- }
42
+ assert(HAVE_CMPXCHG128);
32
43
33
mem_idx = cpu_mmu_index(env, false);
44
mem_idx = cpu_mmu_index(env, false);
34
- oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
45
oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
35
+ oi = make_memop_idx(MO_LE | MO_128 | MO_ALIGN, mem_idx);
36
37
cmpv = int128_make128(env->xregs[rs], env->xregs[rs + 1]);
38
newv = int128_make128(new_lo, new_hi);
39
@@ -XXX,XX +XXX,XX @@ void HELPER(casp_be_parallel)(CPUARMState *env, uint32_t rs, uint64_t addr,
46
@@ -XXX,XX +XXX,XX @@ void HELPER(casp_be_parallel)(CPUARMState *env, uint32_t rs, uint64_t addr,
40
assert(HAVE_CMPXCHG128);
47
int mem_idx;
48
TCGMemOpIdx oi;
49
50
- if (!HAVE_CMPXCHG128) {
51
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
52
- }
53
+ assert(HAVE_CMPXCHG128);
41
54
42
mem_idx = cpu_mmu_index(env, false);
55
mem_idx = cpu_mmu_index(env, false);
43
- oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
56
oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
44
+ oi = make_memop_idx(MO_LE | MO_128 | MO_ALIGN, mem_idx);
57
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
45
58
index XXXXXXX..XXXXXXX 100644
46
cmpv = int128_make128(env->xregs[rs + 1], env->xregs[rs]);
59
--- a/target/arm/translate-a64.c
47
newv = int128_make128(new_lo, new_hi);
60
+++ b/target/arm/translate-a64.c
61
@@ -XXX,XX +XXX,XX @@
62
63
#include "trace-tcg.h"
64
#include "translate-a64.h"
65
+#include "qemu/atomic128.h"
66
67
static TCGv_i64 cpu_X[32];
68
static TCGv_i64 cpu_pc;
69
@@ -XXX,XX +XXX,XX @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
70
get_mem_index(s),
71
MO_64 | MO_ALIGN | s->be_data);
72
tcg_gen_setcond_i64(TCG_COND_NE, tmp, tmp, cpu_exclusive_val);
73
- } else if (s->be_data == MO_LE) {
74
- if (tb_cflags(s->base.tb) & CF_PARALLEL) {
75
+ } else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
76
+ if (!HAVE_CMPXCHG128) {
77
+ gen_helper_exit_atomic(cpu_env);
78
+ s->base.is_jmp = DISAS_NORETURN;
79
+ } else if (s->be_data == MO_LE) {
80
gen_helper_paired_cmpxchg64_le_parallel(tmp, cpu_env,
81
cpu_exclusive_addr,
82
cpu_reg(s, rt),
83
cpu_reg(s, rt2));
84
} else {
85
- gen_helper_paired_cmpxchg64_le(tmp, cpu_env, cpu_exclusive_addr,
86
- cpu_reg(s, rt), cpu_reg(s, rt2));
87
- }
88
- } else {
89
- if (tb_cflags(s->base.tb) & CF_PARALLEL) {
90
gen_helper_paired_cmpxchg64_be_parallel(tmp, cpu_env,
91
cpu_exclusive_addr,
92
cpu_reg(s, rt),
93
cpu_reg(s, rt2));
94
- } else {
95
- gen_helper_paired_cmpxchg64_be(tmp, cpu_env, cpu_exclusive_addr,
96
- cpu_reg(s, rt), cpu_reg(s, rt2));
97
}
98
+ } else if (s->be_data == MO_LE) {
99
+ gen_helper_paired_cmpxchg64_le(tmp, cpu_env, cpu_exclusive_addr,
100
+ cpu_reg(s, rt), cpu_reg(s, rt2));
101
+ } else {
102
+ gen_helper_paired_cmpxchg64_be(tmp, cpu_env, cpu_exclusive_addr,
103
+ cpu_reg(s, rt), cpu_reg(s, rt2));
104
}
105
} else {
106
tcg_gen_atomic_cmpxchg_i64(tmp, cpu_exclusive_addr, cpu_exclusive_val,
107
@@ -XXX,XX +XXX,XX @@ static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt,
108
}
109
tcg_temp_free_i64(cmp);
110
} else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
111
- TCGv_i32 tcg_rs = tcg_const_i32(rs);
112
-
113
- if (s->be_data == MO_LE) {
114
- gen_helper_casp_le_parallel(cpu_env, tcg_rs, addr, t1, t2);
115
+ if (HAVE_CMPXCHG128) {
116
+ TCGv_i32 tcg_rs = tcg_const_i32(rs);
117
+ if (s->be_data == MO_LE) {
118
+ gen_helper_casp_le_parallel(cpu_env, tcg_rs, addr, t1, t2);
119
+ } else {
120
+ gen_helper_casp_be_parallel(cpu_env, tcg_rs, addr, t1, t2);
121
+ }
122
+ tcg_temp_free_i32(tcg_rs);
123
} else {
124
- gen_helper_casp_be_parallel(cpu_env, tcg_rs, addr, t1, t2);
125
+ gen_helper_exit_atomic(cpu_env);
126
+ s->base.is_jmp = DISAS_NORETURN;
127
}
128
- tcg_temp_free_i32(tcg_rs);
129
} else {
130
TCGv_i64 d1 = tcg_temp_new_i64();
131
TCGv_i64 d2 = tcg_temp_new_i64();
48
--
132
--
49
2.25.1
133
2.17.2
50
134
51
135
diff view generated by jsdifflib
1
Cc: qemu-ppc@nongnu.org
1
Reviewed-by: Emilio G. Cota <cota@braap.org>
2
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
---
3
---
5
target/ppc/translate.c | 12 +++++++-----
4
target/ppc/helper.h | 2 +-
6
1 file changed, 7 insertions(+), 5 deletions(-)
5
target/ppc/mem_helper.c | 33 ++++++++++--
6
target/ppc/translate.c | 115 +++++++++++++++++++++-------------------
7
3 files changed, 88 insertions(+), 62 deletions(-)
7
8
9
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
10
index XXXXXXX..XXXXXXX 100644
11
--- a/target/ppc/helper.h
12
+++ b/target/ppc/helper.h
13
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_4(dscliq, void, env, fprp, fprp, i32)
14
DEF_HELPER_1(tbegin, void, env)
15
DEF_HELPER_FLAGS_1(fixup_thrm, TCG_CALL_NO_RWG, void, env)
16
17
-#if defined(TARGET_PPC64) && defined(CONFIG_ATOMIC128)
18
+#ifdef TARGET_PPC64
19
DEF_HELPER_FLAGS_3(lq_le_parallel, TCG_CALL_NO_WG, i64, env, tl, i32)
20
DEF_HELPER_FLAGS_3(lq_be_parallel, TCG_CALL_NO_WG, i64, env, tl, i32)
21
DEF_HELPER_FLAGS_5(stq_le_parallel, TCG_CALL_NO_WG,
22
diff --git a/target/ppc/mem_helper.c b/target/ppc/mem_helper.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/ppc/mem_helper.c
25
+++ b/target/ppc/mem_helper.c
26
@@ -XXX,XX +XXX,XX @@
27
#include "exec/cpu_ldst.h"
28
#include "tcg.h"
29
#include "internal.h"
30
+#include "qemu/atomic128.h"
31
32
//#define DEBUG_OP
33
34
@@ -XXX,XX +XXX,XX @@ target_ulong helper_lscbx(CPUPPCState *env, target_ulong addr, uint32_t reg,
35
return i;
36
}
37
38
-#if defined(TARGET_PPC64) && defined(CONFIG_ATOMIC128)
39
+#ifdef TARGET_PPC64
40
uint64_t helper_lq_le_parallel(CPUPPCState *env, target_ulong addr,
41
uint32_t opidx)
42
{
43
- Int128 ret = helper_atomic_ldo_le_mmu(env, addr, opidx, GETPC());
44
+ Int128 ret;
45
+
46
+ /* We will have raised EXCP_ATOMIC from the translator. */
47
+ assert(HAVE_ATOMIC128);
48
+ ret = helper_atomic_ldo_le_mmu(env, addr, opidx, GETPC());
49
env->retxh = int128_gethi(ret);
50
return int128_getlo(ret);
51
}
52
@@ -XXX,XX +XXX,XX @@ uint64_t helper_lq_le_parallel(CPUPPCState *env, target_ulong addr,
53
uint64_t helper_lq_be_parallel(CPUPPCState *env, target_ulong addr,
54
uint32_t opidx)
55
{
56
- Int128 ret = helper_atomic_ldo_be_mmu(env, addr, opidx, GETPC());
57
+ Int128 ret;
58
+
59
+ /* We will have raised EXCP_ATOMIC from the translator. */
60
+ assert(HAVE_ATOMIC128);
61
+ ret = helper_atomic_ldo_be_mmu(env, addr, opidx, GETPC());
62
env->retxh = int128_gethi(ret);
63
return int128_getlo(ret);
64
}
65
@@ -XXX,XX +XXX,XX @@ uint64_t helper_lq_be_parallel(CPUPPCState *env, target_ulong addr,
66
void helper_stq_le_parallel(CPUPPCState *env, target_ulong addr,
67
uint64_t lo, uint64_t hi, uint32_t opidx)
68
{
69
- Int128 val = int128_make128(lo, hi);
70
+ Int128 val;
71
+
72
+ /* We will have raised EXCP_ATOMIC from the translator. */
73
+ assert(HAVE_ATOMIC128);
74
+ val = int128_make128(lo, hi);
75
helper_atomic_sto_le_mmu(env, addr, val, opidx, GETPC());
76
}
77
78
void helper_stq_be_parallel(CPUPPCState *env, target_ulong addr,
79
uint64_t lo, uint64_t hi, uint32_t opidx)
80
{
81
- Int128 val = int128_make128(lo, hi);
82
+ Int128 val;
83
+
84
+ /* We will have raised EXCP_ATOMIC from the translator. */
85
+ assert(HAVE_ATOMIC128);
86
+ val = int128_make128(lo, hi);
87
helper_atomic_sto_be_mmu(env, addr, val, opidx, GETPC());
88
}
89
90
@@ -XXX,XX +XXX,XX @@ uint32_t helper_stqcx_le_parallel(CPUPPCState *env, target_ulong addr,
91
{
92
bool success = false;
93
94
+ /* We will have raised EXCP_ATOMIC from the translator. */
95
+ assert(HAVE_CMPXCHG128);
96
+
97
if (likely(addr == env->reserve_addr)) {
98
Int128 oldv, cmpv, newv;
99
100
@@ -XXX,XX +XXX,XX @@ uint32_t helper_stqcx_be_parallel(CPUPPCState *env, target_ulong addr,
101
{
102
bool success = false;
103
104
+ /* We will have raised EXCP_ATOMIC from the translator. */
105
+ assert(HAVE_CMPXCHG128);
106
+
107
if (likely(addr == env->reserve_addr)) {
108
Int128 oldv, cmpv, newv;
109
8
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
110
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
9
index XXXXXXX..XXXXXXX 100644
111
index XXXXXXX..XXXXXXX 100644
10
--- a/target/ppc/translate.c
112
--- a/target/ppc/translate.c
11
+++ b/target/ppc/translate.c
113
+++ b/target/ppc/translate.c
114
@@ -XXX,XX +XXX,XX @@
115
#include "trace-tcg.h"
116
#include "exec/translator.h"
117
#include "exec/log.h"
118
+#include "qemu/atomic128.h"
119
120
121
#define CPU_SINGLE_STEP 0x1
122
@@ -XXX,XX +XXX,XX @@ static void gen_lq(DisasContext *ctx)
123
hi = cpu_gpr[rd];
124
125
if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
126
-#ifdef CONFIG_ATOMIC128
127
- TCGv_i32 oi = tcg_temp_new_i32();
128
- if (ctx->le_mode) {
129
- tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ, ctx->mem_idx));
130
- gen_helper_lq_le_parallel(lo, cpu_env, EA, oi);
131
+ if (HAVE_ATOMIC128) {
132
+ TCGv_i32 oi = tcg_temp_new_i32();
133
+ if (ctx->le_mode) {
134
+ tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ, ctx->mem_idx));
135
+ gen_helper_lq_le_parallel(lo, cpu_env, EA, oi);
136
+ } else {
137
+ tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ, ctx->mem_idx));
138
+ gen_helper_lq_be_parallel(lo, cpu_env, EA, oi);
139
+ }
140
+ tcg_temp_free_i32(oi);
141
+ tcg_gen_ld_i64(hi, cpu_env, offsetof(CPUPPCState, retxh));
142
} else {
143
- tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ, ctx->mem_idx));
144
- gen_helper_lq_be_parallel(lo, cpu_env, EA, oi);
145
+ /* Restart with exclusive lock. */
146
+ gen_helper_exit_atomic(cpu_env);
147
+ ctx->base.is_jmp = DISAS_NORETURN;
148
}
149
- tcg_temp_free_i32(oi);
150
- tcg_gen_ld_i64(hi, cpu_env, offsetof(CPUPPCState, retxh));
151
-#else
152
- /* Restart with exclusive lock. */
153
- gen_helper_exit_atomic(cpu_env);
154
- ctx->base.is_jmp = DISAS_NORETURN;
155
-#endif
156
} else if (ctx->le_mode) {
157
tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_LEQ);
158
gen_addr_add(ctx, EA, EA, 8);
12
@@ -XXX,XX +XXX,XX @@ static void gen_std(DisasContext *ctx)
159
@@ -XXX,XX +XXX,XX @@ static void gen_std(DisasContext *ctx)
13
if (HAVE_ATOMIC128) {
160
hi = cpu_gpr[rs];
14
TCGv_i32 oi = tcg_temp_new_i32();
161
15
if (ctx->le_mode) {
162
if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
16
- tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ, ctx->mem_idx));
163
-#ifdef CONFIG_ATOMIC128
17
+ tcg_gen_movi_i32(oi, make_memop_idx(MO_LE | MO_128,
164
- TCGv_i32 oi = tcg_temp_new_i32();
18
+ ctx->mem_idx));
165
- if (ctx->le_mode) {
19
gen_helper_stq_le_parallel(cpu_env, EA, lo, hi, oi);
166
- tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ, ctx->mem_idx));
20
} else {
167
- gen_helper_stq_le_parallel(cpu_env, EA, lo, hi, oi);
21
- tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ, ctx->mem_idx));
168
+ if (HAVE_ATOMIC128) {
22
+ tcg_gen_movi_i32(oi, make_memop_idx(MO_BE | MO_128,
169
+ TCGv_i32 oi = tcg_temp_new_i32();
23
+ ctx->mem_idx));
170
+ if (ctx->le_mode) {
24
gen_helper_stq_be_parallel(cpu_env, EA, lo, hi, oi);
171
+ tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ, ctx->mem_idx));
25
}
172
+ gen_helper_stq_le_parallel(cpu_env, EA, lo, hi, oi);
26
tcg_temp_free_i32(oi);
173
+ } else {
174
+ tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ, ctx->mem_idx));
175
+ gen_helper_stq_be_parallel(cpu_env, EA, lo, hi, oi);
176
+ }
177
+ tcg_temp_free_i32(oi);
178
} else {
179
- tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ, ctx->mem_idx));
180
- gen_helper_stq_be_parallel(cpu_env, EA, lo, hi, oi);
181
+ /* Restart with exclusive lock. */
182
+ gen_helper_exit_atomic(cpu_env);
183
+ ctx->base.is_jmp = DISAS_NORETURN;
184
}
185
- tcg_temp_free_i32(oi);
186
-#else
187
- /* Restart with exclusive lock. */
188
- gen_helper_exit_atomic(cpu_env);
189
- ctx->base.is_jmp = DISAS_NORETURN;
190
-#endif
191
} else if (ctx->le_mode) {
192
tcg_gen_qemu_st_i64(lo, EA, ctx->mem_idx, MO_LEQ);
193
gen_addr_add(ctx, EA, EA, 8);
27
@@ -XXX,XX +XXX,XX @@ static void gen_lqarx(DisasContext *ctx)
194
@@ -XXX,XX +XXX,XX @@ static void gen_lqarx(DisasContext *ctx)
28
if (HAVE_ATOMIC128) {
195
hi = cpu_gpr[rd];
29
TCGv_i32 oi = tcg_temp_new_i32();
196
30
if (ctx->le_mode) {
197
if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
31
- tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ | MO_ALIGN_16,
198
-#ifdef CONFIG_ATOMIC128
32
+ tcg_gen_movi_i32(oi, make_memop_idx(MO_LE | MO_128 | MO_ALIGN,
199
- TCGv_i32 oi = tcg_temp_new_i32();
33
ctx->mem_idx));
200
- if (ctx->le_mode) {
34
gen_helper_lq_le_parallel(lo, cpu_env, EA, oi);
201
- tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ | MO_ALIGN_16,
35
} else {
202
- ctx->mem_idx));
36
- tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ | MO_ALIGN_16,
203
- gen_helper_lq_le_parallel(lo, cpu_env, EA, oi);
37
+ tcg_gen_movi_i32(oi, make_memop_idx(MO_BE | MO_128 | MO_ALIGN,
204
+ if (HAVE_ATOMIC128) {
38
ctx->mem_idx));
205
+ TCGv_i32 oi = tcg_temp_new_i32();
39
gen_helper_lq_be_parallel(lo, cpu_env, EA, oi);
206
+ if (ctx->le_mode) {
40
}
207
+ tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ | MO_ALIGN_16,
208
+ ctx->mem_idx));
209
+ gen_helper_lq_le_parallel(lo, cpu_env, EA, oi);
210
+ } else {
211
+ tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ | MO_ALIGN_16,
212
+ ctx->mem_idx));
213
+ gen_helper_lq_be_parallel(lo, cpu_env, EA, oi);
214
+ }
215
+ tcg_temp_free_i32(oi);
216
+ tcg_gen_ld_i64(hi, cpu_env, offsetof(CPUPPCState, retxh));
217
} else {
218
- tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ | MO_ALIGN_16,
219
- ctx->mem_idx));
220
- gen_helper_lq_be_parallel(lo, cpu_env, EA, oi);
221
+ /* Restart with exclusive lock. */
222
+ gen_helper_exit_atomic(cpu_env);
223
+ ctx->base.is_jmp = DISAS_NORETURN;
224
+ tcg_temp_free(EA);
225
+ return;
226
}
227
- tcg_temp_free_i32(oi);
228
- tcg_gen_ld_i64(hi, cpu_env, offsetof(CPUPPCState, retxh));
229
-#else
230
- /* Restart with exclusive lock. */
231
- gen_helper_exit_atomic(cpu_env);
232
- ctx->base.is_jmp = DISAS_NORETURN;
233
- tcg_temp_free(EA);
234
- return;
235
-#endif
236
} else if (ctx->le_mode) {
237
tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_LEQ | MO_ALIGN_16);
238
tcg_gen_mov_tl(cpu_reserve, EA);
41
@@ -XXX,XX +XXX,XX @@ static void gen_stqcx_(DisasContext *ctx)
239
@@ -XXX,XX +XXX,XX @@ static void gen_stqcx_(DisasContext *ctx)
240
hi = cpu_gpr[rs];
42
241
43
if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
242
if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
44
if (HAVE_CMPXCHG128) {
243
- TCGv_i32 oi = tcg_const_i32(DEF_MEMOP(MO_Q) | MO_ALIGN_16);
45
- TCGv_i32 oi = tcg_const_i32(DEF_MEMOP(MO_Q) | MO_ALIGN_16);
244
-#ifdef CONFIG_ATOMIC128
46
+ TCGv_i32 oi = tcg_const_i32(DEF_MEMOP(MO_128) | MO_ALIGN);
245
- if (ctx->le_mode) {
47
if (ctx->le_mode) {
246
- gen_helper_stqcx_le_parallel(cpu_crf[0], cpu_env, EA, lo, hi, oi);
48
gen_helper_stqcx_le_parallel(cpu_crf[0], cpu_env,
247
+ if (HAVE_CMPXCHG128) {
49
EA, lo, hi, oi);
248
+ TCGv_i32 oi = tcg_const_i32(DEF_MEMOP(MO_Q) | MO_ALIGN_16);
249
+ if (ctx->le_mode) {
250
+ gen_helper_stqcx_le_parallel(cpu_crf[0], cpu_env,
251
+ EA, lo, hi, oi);
252
+ } else {
253
+ gen_helper_stqcx_be_parallel(cpu_crf[0], cpu_env,
254
+ EA, lo, hi, oi);
255
+ }
256
+ tcg_temp_free_i32(oi);
257
} else {
258
- gen_helper_stqcx_le_parallel(cpu_crf[0], cpu_env, EA, lo, hi, oi);
259
+ /* Restart with exclusive lock. */
260
+ gen_helper_exit_atomic(cpu_env);
261
+ ctx->base.is_jmp = DISAS_NORETURN;
262
}
263
-#else
264
- /* Restart with exclusive lock. */
265
- gen_helper_exit_atomic(cpu_env);
266
- ctx->base.is_jmp = DISAS_NORETURN;
267
-#endif
268
tcg_temp_free(EA);
269
- tcg_temp_free_i32(oi);
270
} else {
271
TCGLabel *lab_fail = gen_new_label();
272
TCGLabel *lab_over = gen_new_label();
50
--
273
--
51
2.25.1
274
2.17.2
52
275
53
276
diff view generated by jsdifflib
1
Reviewed-by: David Hildenbrand <david@redhat.com>
1
Reviewed-by: David Hildenbrand <david@redhat.com>
2
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
---
3
---
5
target/s390x/tcg/mem_helper.c | 4 ++--
4
target/s390x/mem_helper.c | 92 +++++++++++++++++----------------------
6
1 file changed, 2 insertions(+), 2 deletions(-)
5
1 file changed, 41 insertions(+), 51 deletions(-)
7
6
8
diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c
7
diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
9
index XXXXXXX..XXXXXXX 100644
8
index XXXXXXX..XXXXXXX 100644
10
--- a/target/s390x/tcg/mem_helper.c
9
--- a/target/s390x/mem_helper.c
11
+++ b/target/s390x/tcg/mem_helper.c
10
+++ b/target/s390x/mem_helper.c
11
@@ -XXX,XX +XXX,XX @@
12
#include "exec/exec-all.h"
13
#include "exec/cpu_ldst.h"
14
#include "qemu/int128.h"
15
+#include "qemu/atomic128.h"
16
17
#if !defined(CONFIG_USER_ONLY)
18
#include "hw/s390x/storage-keys.h"
19
@@ -XXX,XX +XXX,XX @@ static void do_cdsg(CPUS390XState *env, uint64_t addr,
20
bool fail;
21
22
if (parallel) {
23
-#ifndef CONFIG_ATOMIC128
24
+#if !HAVE_CMPXCHG128
25
cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
26
#else
27
int mem_idx = cpu_mmu_index(env, false);
12
@@ -XXX,XX +XXX,XX @@ void HELPER(cdsg_parallel)(CPUS390XState *env, uint64_t addr,
28
@@ -XXX,XX +XXX,XX @@ void HELPER(cdsg_parallel)(CPUS390XState *env, uint64_t addr,
13
assert(HAVE_CMPXCHG128);
29
static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
14
30
uint64_t a2, bool parallel)
15
mem_idx = cpu_mmu_index(env, false);
31
{
16
- oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
32
-#if !defined(CONFIG_USER_ONLY) || defined(CONFIG_ATOMIC128)
17
+ oi = make_memop_idx(MO_TE | MO_128 | MO_ALIGN, mem_idx);
33
uint32_t mem_idx = cpu_mmu_index(env, false);
18
oldv = cpu_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra);
34
-#endif
19
fail = !int128_eq(oldv, cmpv);
35
uintptr_t ra = GETPC();
20
36
uint32_t fc = extract32(env->regs[0], 0, 8);
37
uint32_t sc = extract32(env->regs[0], 8, 8);
21
@@ -XXX,XX +XXX,XX @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
38
@@ -XXX,XX +XXX,XX @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
39
probe_write(env, a2, 0, mem_idx, ra);
40
#endif
41
42
- /* Note that the compare-and-swap is atomic, and the store is atomic, but
43
- the complete operation is not. Therefore we do not need to assert serial
44
- context in order to implement this. That said, restart early if we can't
45
- support either operation that is supposed to be atomic. */
46
+ /*
47
+ * Note that the compare-and-swap is atomic, and the store is atomic,
48
+ * but the complete operation is not. Therefore we do not need to
49
+ * assert serial context in order to implement this. That said,
50
+ * restart early if we can't support either operation that is supposed
51
+ * to be atomic.
52
+ */
53
if (parallel) {
54
- int mask = 0;
55
-#if !defined(CONFIG_ATOMIC64)
56
- mask = -8;
57
-#elif !defined(CONFIG_ATOMIC128)
58
- mask = -16;
59
+ uint32_t max = 2;
60
+#ifdef CONFIG_ATOMIC64
61
+ max = 3;
62
#endif
63
- if (((4 << fc) | (1 << sc)) & mask) {
64
+ if ((HAVE_CMPXCHG128 ? 0 : fc + 2 > max) ||
65
+ (HAVE_ATOMIC128 ? 0 : sc > max)) {
66
cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
67
}
68
}
69
@@ -XXX,XX +XXX,XX @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
70
Int128 cv = int128_make128(env->regs[r3 + 1], env->regs[r3]);
71
Int128 ov;
72
73
- if (parallel) {
74
-#ifdef CONFIG_ATOMIC128
75
- TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
76
- ov = helper_atomic_cmpxchgo_be_mmu(env, a1, cv, nv, oi, ra);
77
- cc = !int128_eq(ov, cv);
78
-#else
79
- /* Note that we asserted !parallel above. */
80
- g_assert_not_reached();
81
-#endif
82
- } else {
83
+ if (!parallel) {
84
uint64_t oh = cpu_ldq_data_ra(env, a1 + 0, ra);
85
uint64_t ol = cpu_ldq_data_ra(env, a1 + 8, ra);
86
87
@@ -XXX,XX +XXX,XX @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
88
22
cpu_stq_data_ra(env, a1 + 0, int128_gethi(nv), ra);
89
cpu_stq_data_ra(env, a1 + 0, int128_gethi(nv), ra);
23
cpu_stq_data_ra(env, a1 + 8, int128_getlo(nv), ra);
90
cpu_stq_data_ra(env, a1 + 8, int128_getlo(nv), ra);
24
} else if (HAVE_CMPXCHG128) {
91
+ } else if (HAVE_CMPXCHG128) {
25
- MemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
92
+ TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
26
+ MemOpIdx oi = make_memop_idx(MO_TE | MO_128 | MO_ALIGN, mem_idx);
93
+ ov = helper_atomic_cmpxchgo_be_mmu(env, a1, cv, nv, oi, ra);
27
ov = cpu_atomic_cmpxchgo_be_mmu(env, a1, cv, nv, oi, ra);
94
+ cc = !int128_eq(ov, cv);
28
cc = !int128_eq(ov, cv);
95
+ } else {
29
} else {
96
+ /* Note that we asserted !parallel above. */
97
+ g_assert_not_reached();
98
}
99
100
env->regs[r3 + 0] = int128_gethi(ov);
101
@@ -XXX,XX +XXX,XX @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
102
cpu_stq_data_ra(env, a2, svh, ra);
103
break;
104
case 4:
105
- if (parallel) {
106
-#ifdef CONFIG_ATOMIC128
107
+ if (!parallel) {
108
+ cpu_stq_data_ra(env, a2 + 0, svh, ra);
109
+ cpu_stq_data_ra(env, a2 + 8, svl, ra);
110
+ } else if (HAVE_ATOMIC128) {
111
TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
112
Int128 sv = int128_make128(svl, svh);
113
helper_atomic_sto_be_mmu(env, a2, sv, oi, ra);
114
-#else
115
+ } else {
116
/* Note that we asserted !parallel above. */
117
g_assert_not_reached();
118
-#endif
119
- } else {
120
- cpu_stq_data_ra(env, a2 + 0, svh, ra);
121
- cpu_stq_data_ra(env, a2 + 8, svl, ra);
122
}
123
break;
124
default:
125
@@ -XXX,XX +XXX,XX @@ static uint64_t do_lpq(CPUS390XState *env, uint64_t addr, bool parallel)
126
uintptr_t ra = GETPC();
127
uint64_t hi, lo;
128
129
- if (parallel) {
130
-#ifndef CONFIG_ATOMIC128
131
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
132
-#else
133
+ if (!parallel) {
134
+ check_alignment(env, addr, 16, ra);
135
+ hi = cpu_ldq_data_ra(env, addr + 0, ra);
136
+ lo = cpu_ldq_data_ra(env, addr + 8, ra);
137
+ } else if (HAVE_ATOMIC128) {
138
int mem_idx = cpu_mmu_index(env, false);
139
TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
140
Int128 v = helper_atomic_ldo_be_mmu(env, addr, oi, ra);
141
hi = int128_gethi(v);
142
lo = int128_getlo(v);
143
-#endif
144
} else {
145
- check_alignment(env, addr, 16, ra);
146
-
147
- hi = cpu_ldq_data_ra(env, addr + 0, ra);
148
- lo = cpu_ldq_data_ra(env, addr + 8, ra);
149
+ cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
150
}
151
152
env->retxl = lo;
153
@@ -XXX,XX +XXX,XX @@ static void do_stpq(CPUS390XState *env, uint64_t addr,
154
{
155
uintptr_t ra = GETPC();
156
157
- if (parallel) {
158
-#ifndef CONFIG_ATOMIC128
159
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
160
-#else
161
- int mem_idx = cpu_mmu_index(env, false);
162
- TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
163
-
164
- Int128 v = int128_make128(low, high);
165
- helper_atomic_sto_be_mmu(env, addr, v, oi, ra);
166
-#endif
167
- } else {
168
+ if (!parallel) {
169
check_alignment(env, addr, 16, ra);
170
-
171
cpu_stq_data_ra(env, addr + 0, high, ra);
172
cpu_stq_data_ra(env, addr + 8, low, ra);
173
+ } else if (HAVE_ATOMIC128) {
174
+ int mem_idx = cpu_mmu_index(env, false);
175
+ TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
176
+ Int128 v = int128_make128(low, high);
177
+ helper_atomic_sto_be_mmu(env, addr, v, oi, ra);
178
+ } else {
179
+ cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
180
}
181
}
182
30
--
183
--
31
2.25.1
184
2.17.2
32
185
33
186
diff view generated by jsdifflib
1
Rather than use 4-16 separate operations, use 2 operations
1
Reviewed-by: David Hildenbrand <david@redhat.com>
2
plus some byte reordering as necessary.
3
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
3
---
7
target/mips/tcg/msa_helper.c | 201 +++++++++++++----------------------
4
target/s390x/mem_helper.c | 128 ++++++++++++++++++--------------------
8
1 file changed, 71 insertions(+), 130 deletions(-)
5
1 file changed, 61 insertions(+), 67 deletions(-)
9
6
10
diff --git a/target/mips/tcg/msa_helper.c b/target/mips/tcg/msa_helper.c
7
diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
11
index XXXXXXX..XXXXXXX 100644
8
index XXXXXXX..XXXXXXX 100644
12
--- a/target/mips/tcg/msa_helper.c
9
--- a/target/s390x/mem_helper.c
13
+++ b/target/mips/tcg/msa_helper.c
10
+++ b/target/s390x/mem_helper.c
14
@@ -XXX,XX +XXX,XX @@ void helper_msa_ffint_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
11
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(trXX)(CPUS390XState *env, uint32_t r1, uint32_t r2,
15
#define MEMOP_IDX(DF)
12
return cc;
13
}
14
15
-static void do_cdsg(CPUS390XState *env, uint64_t addr,
16
- uint32_t r1, uint32_t r3, bool parallel)
17
+void HELPER(cdsg)(CPUS390XState *env, uint64_t addr,
18
+ uint32_t r1, uint32_t r3)
19
{
20
uintptr_t ra = GETPC();
21
Int128 cmpv = int128_make128(env->regs[r1 + 1], env->regs[r1]);
22
Int128 newv = int128_make128(env->regs[r3 + 1], env->regs[r3]);
23
Int128 oldv;
24
+ uint64_t oldh, oldl;
25
bool fail;
26
27
- if (parallel) {
28
-#if !HAVE_CMPXCHG128
29
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
30
-#else
31
- int mem_idx = cpu_mmu_index(env, false);
32
- TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
33
- oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra);
34
- fail = !int128_eq(oldv, cmpv);
35
-#endif
36
- } else {
37
- uint64_t oldh, oldl;
38
+ check_alignment(env, addr, 16, ra);
39
40
- check_alignment(env, addr, 16, ra);
41
+ oldh = cpu_ldq_data_ra(env, addr + 0, ra);
42
+ oldl = cpu_ldq_data_ra(env, addr + 8, ra);
43
44
- oldh = cpu_ldq_data_ra(env, addr + 0, ra);
45
- oldl = cpu_ldq_data_ra(env, addr + 8, ra);
46
-
47
- oldv = int128_make128(oldl, oldh);
48
- fail = !int128_eq(oldv, cmpv);
49
- if (fail) {
50
- newv = oldv;
51
- }
52
-
53
- cpu_stq_data_ra(env, addr + 0, int128_gethi(newv), ra);
54
- cpu_stq_data_ra(env, addr + 8, int128_getlo(newv), ra);
55
+ oldv = int128_make128(oldl, oldh);
56
+ fail = !int128_eq(oldv, cmpv);
57
+ if (fail) {
58
+ newv = oldv;
59
}
60
61
+ cpu_stq_data_ra(env, addr + 0, int128_gethi(newv), ra);
62
+ cpu_stq_data_ra(env, addr + 8, int128_getlo(newv), ra);
63
+
64
env->cc_op = fail;
65
env->regs[r1] = int128_gethi(oldv);
66
env->regs[r1 + 1] = int128_getlo(oldv);
67
}
68
69
-void HELPER(cdsg)(CPUS390XState *env, uint64_t addr,
70
- uint32_t r1, uint32_t r3)
71
-{
72
- do_cdsg(env, addr, r1, r3, false);
73
-}
74
-
75
void HELPER(cdsg_parallel)(CPUS390XState *env, uint64_t addr,
76
uint32_t r1, uint32_t r3)
77
{
78
- do_cdsg(env, addr, r1, r3, true);
79
+ uintptr_t ra = GETPC();
80
+ Int128 cmpv = int128_make128(env->regs[r1 + 1], env->regs[r1]);
81
+ Int128 newv = int128_make128(env->regs[r3 + 1], env->regs[r3]);
82
+ int mem_idx;
83
+ TCGMemOpIdx oi;
84
+ Int128 oldv;
85
+ bool fail;
86
+
87
+ if (!HAVE_CMPXCHG128) {
88
+ cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
89
+ }
90
+
91
+ mem_idx = cpu_mmu_index(env, false);
92
+ oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
93
+ oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra);
94
+ fail = !int128_eq(oldv, cmpv);
95
+
96
+ env->cc_op = fail;
97
+ env->regs[r1] = int128_gethi(oldv);
98
+ env->regs[r1 + 1] = int128_getlo(oldv);
99
}
100
101
static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
102
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr)
16
#endif
103
#endif
17
104
18
+#ifdef TARGET_WORDS_BIGENDIAN
105
/* load pair from quadword */
19
+static inline uint64_t bswap16x4(uint64_t x)
106
-static uint64_t do_lpq(CPUS390XState *env, uint64_t addr, bool parallel)
20
+{
107
+uint64_t HELPER(lpq)(CPUS390XState *env, uint64_t addr)
21
+ uint64_t m = 0x00ff00ff00ff00ffull;
108
{
22
+ return ((x & m) << 8) | ((x >> 8) & m);
109
uintptr_t ra = GETPC();
110
uint64_t hi, lo;
111
112
- if (!parallel) {
113
- check_alignment(env, addr, 16, ra);
114
- hi = cpu_ldq_data_ra(env, addr + 0, ra);
115
- lo = cpu_ldq_data_ra(env, addr + 8, ra);
116
- } else if (HAVE_ATOMIC128) {
117
+ check_alignment(env, addr, 16, ra);
118
+ hi = cpu_ldq_data_ra(env, addr + 0, ra);
119
+ lo = cpu_ldq_data_ra(env, addr + 8, ra);
120
+
121
+ env->retxl = lo;
122
+ return hi;
23
+}
123
+}
24
+
124
+
25
+static inline uint64_t bswap32x2(uint64_t x)
125
+uint64_t HELPER(lpq_parallel)(CPUS390XState *env, uint64_t addr)
26
+{
126
+{
27
+ return ror64(bswap64(x), 32);
127
+ uintptr_t ra = GETPC();
128
+ uint64_t hi, lo;
129
+
130
+ if (HAVE_ATOMIC128) {
131
int mem_idx = cpu_mmu_index(env, false);
132
TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
133
Int128 v = helper_atomic_ldo_be_mmu(env, addr, oi, ra);
134
@@ -XXX,XX +XXX,XX @@ static uint64_t do_lpq(CPUS390XState *env, uint64_t addr, bool parallel)
135
return hi;
136
}
137
138
-uint64_t HELPER(lpq)(CPUS390XState *env, uint64_t addr)
139
-{
140
- return do_lpq(env, addr, false);
141
-}
142
-
143
-uint64_t HELPER(lpq_parallel)(CPUS390XState *env, uint64_t addr)
144
-{
145
- return do_lpq(env, addr, true);
146
-}
147
-
148
/* store pair to quadword */
149
-static void do_stpq(CPUS390XState *env, uint64_t addr,
150
- uint64_t low, uint64_t high, bool parallel)
151
+void HELPER(stpq)(CPUS390XState *env, uint64_t addr,
152
+ uint64_t low, uint64_t high)
153
{
154
uintptr_t ra = GETPC();
155
156
- if (!parallel) {
157
- check_alignment(env, addr, 16, ra);
158
- cpu_stq_data_ra(env, addr + 0, high, ra);
159
- cpu_stq_data_ra(env, addr + 8, low, ra);
160
- } else if (HAVE_ATOMIC128) {
161
+ check_alignment(env, addr, 16, ra);
162
+ cpu_stq_data_ra(env, addr + 0, high, ra);
163
+ cpu_stq_data_ra(env, addr + 8, low, ra);
28
+}
164
+}
29
+#endif
30
+
165
+
31
void helper_msa_ld_b(CPUMIPSState *env, uint32_t wd,
166
+void HELPER(stpq_parallel)(CPUS390XState *env, uint64_t addr,
32
target_ulong addr)
167
+ uint64_t low, uint64_t high)
33
{
168
+{
34
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
169
+ uintptr_t ra = GETPC();
35
uintptr_t ra = GETPC();
170
+
36
+ uint64_t d0, d1;
171
+ if (HAVE_ATOMIC128) {
37
172
int mem_idx = cpu_mmu_index(env, false);
38
-#if !defined(HOST_WORDS_BIGENDIAN)
173
TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
39
- pwd->b[0] = cpu_ldub_data_ra(env, addr + (0 << DF_BYTE), ra);
174
Int128 v = int128_make128(low, high);
40
- pwd->b[1] = cpu_ldub_data_ra(env, addr + (1 << DF_BYTE), ra);
175
@@ -XXX,XX +XXX,XX @@ static void do_stpq(CPUS390XState *env, uint64_t addr,
41
- pwd->b[2] = cpu_ldub_data_ra(env, addr + (2 << DF_BYTE), ra);
176
}
42
- pwd->b[3] = cpu_ldub_data_ra(env, addr + (3 << DF_BYTE), ra);
43
- pwd->b[4] = cpu_ldub_data_ra(env, addr + (4 << DF_BYTE), ra);
44
- pwd->b[5] = cpu_ldub_data_ra(env, addr + (5 << DF_BYTE), ra);
45
- pwd->b[6] = cpu_ldub_data_ra(env, addr + (6 << DF_BYTE), ra);
46
- pwd->b[7] = cpu_ldub_data_ra(env, addr + (7 << DF_BYTE), ra);
47
- pwd->b[8] = cpu_ldub_data_ra(env, addr + (8 << DF_BYTE), ra);
48
- pwd->b[9] = cpu_ldub_data_ra(env, addr + (9 << DF_BYTE), ra);
49
- pwd->b[10] = cpu_ldub_data_ra(env, addr + (10 << DF_BYTE), ra);
50
- pwd->b[11] = cpu_ldub_data_ra(env, addr + (11 << DF_BYTE), ra);
51
- pwd->b[12] = cpu_ldub_data_ra(env, addr + (12 << DF_BYTE), ra);
52
- pwd->b[13] = cpu_ldub_data_ra(env, addr + (13 << DF_BYTE), ra);
53
- pwd->b[14] = cpu_ldub_data_ra(env, addr + (14 << DF_BYTE), ra);
54
- pwd->b[15] = cpu_ldub_data_ra(env, addr + (15 << DF_BYTE), ra);
55
-#else
56
- pwd->b[0] = cpu_ldub_data_ra(env, addr + (7 << DF_BYTE), ra);
57
- pwd->b[1] = cpu_ldub_data_ra(env, addr + (6 << DF_BYTE), ra);
58
- pwd->b[2] = cpu_ldub_data_ra(env, addr + (5 << DF_BYTE), ra);
59
- pwd->b[3] = cpu_ldub_data_ra(env, addr + (4 << DF_BYTE), ra);
60
- pwd->b[4] = cpu_ldub_data_ra(env, addr + (3 << DF_BYTE), ra);
61
- pwd->b[5] = cpu_ldub_data_ra(env, addr + (2 << DF_BYTE), ra);
62
- pwd->b[6] = cpu_ldub_data_ra(env, addr + (1 << DF_BYTE), ra);
63
- pwd->b[7] = cpu_ldub_data_ra(env, addr + (0 << DF_BYTE), ra);
64
- pwd->b[8] = cpu_ldub_data_ra(env, addr + (15 << DF_BYTE), ra);
65
- pwd->b[9] = cpu_ldub_data_ra(env, addr + (14 << DF_BYTE), ra);
66
- pwd->b[10] = cpu_ldub_data_ra(env, addr + (13 << DF_BYTE), ra);
67
- pwd->b[11] = cpu_ldub_data_ra(env, addr + (12 << DF_BYTE), ra);
68
- pwd->b[12] = cpu_ldub_data_ra(env, addr + (11 << DF_BYTE), ra);
69
- pwd->b[13] = cpu_ldub_data_ra(env, addr + (10 << DF_BYTE), ra);
70
- pwd->b[14] = cpu_ldub_data_ra(env, addr + (9 << DF_BYTE), ra);
71
- pwd->b[15] = cpu_ldub_data_ra(env, addr + (8 << DF_BYTE), ra);
72
-#endif
73
+ /* Load 8 bytes at a time. Vector element ordering makes this LE. */
74
+ d0 = cpu_ldq_le_data_ra(env, addr + 0, ra);
75
+ d1 = cpu_ldq_le_data_ra(env, addr + 8, ra);
76
+ pwd->d[0] = d0;
77
+ pwd->d[1] = d1;
78
}
177
}
79
178
80
void helper_msa_ld_h(CPUMIPSState *env, uint32_t wd,
179
-void HELPER(stpq)(CPUS390XState *env, uint64_t addr,
81
@@ -XXX,XX +XXX,XX @@ void helper_msa_ld_h(CPUMIPSState *env, uint32_t wd,
180
- uint64_t low, uint64_t high)
82
{
181
-{
83
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
182
- do_stpq(env, addr, low, high, false);
84
uintptr_t ra = GETPC();
183
-}
85
+ uint64_t d0, d1;
184
-
86
185
-void HELPER(stpq_parallel)(CPUS390XState *env, uint64_t addr,
87
-#if !defined(HOST_WORDS_BIGENDIAN)
186
- uint64_t low, uint64_t high)
88
- pwd->h[0] = cpu_lduw_data_ra(env, addr + (0 << DF_HALF), ra);
187
-{
89
- pwd->h[1] = cpu_lduw_data_ra(env, addr + (1 << DF_HALF), ra);
188
- do_stpq(env, addr, low, high, true);
90
- pwd->h[2] = cpu_lduw_data_ra(env, addr + (2 << DF_HALF), ra);
189
-}
91
- pwd->h[3] = cpu_lduw_data_ra(env, addr + (3 << DF_HALF), ra);
190
-
92
- pwd->h[4] = cpu_lduw_data_ra(env, addr + (4 << DF_HALF), ra);
191
/* Execute instruction. This instruction executes an insn modified with
93
- pwd->h[5] = cpu_lduw_data_ra(env, addr + (5 << DF_HALF), ra);
192
the contents of r1. It does not change the executed instruction in memory;
94
- pwd->h[6] = cpu_lduw_data_ra(env, addr + (6 << DF_HALF), ra);
193
it does not change the program counter.
95
- pwd->h[7] = cpu_lduw_data_ra(env, addr + (7 << DF_HALF), ra);
96
-#else
97
- pwd->h[0] = cpu_lduw_data_ra(env, addr + (3 << DF_HALF), ra);
98
- pwd->h[1] = cpu_lduw_data_ra(env, addr + (2 << DF_HALF), ra);
99
- pwd->h[2] = cpu_lduw_data_ra(env, addr + (1 << DF_HALF), ra);
100
- pwd->h[3] = cpu_lduw_data_ra(env, addr + (0 << DF_HALF), ra);
101
- pwd->h[4] = cpu_lduw_data_ra(env, addr + (7 << DF_HALF), ra);
102
- pwd->h[5] = cpu_lduw_data_ra(env, addr + (6 << DF_HALF), ra);
103
- pwd->h[6] = cpu_lduw_data_ra(env, addr + (5 << DF_HALF), ra);
104
- pwd->h[7] = cpu_lduw_data_ra(env, addr + (4 << DF_HALF), ra);
105
+ /*
106
+ * Load 8 bytes at a time. Use little-endian load, then for
107
+ * big-endian target, we must then swap the four halfwords.
108
+ */
109
+ d0 = cpu_ldq_le_data_ra(env, addr + 0, ra);
110
+ d1 = cpu_ldq_le_data_ra(env, addr + 8, ra);
111
+#ifdef TARGET_WORDS_BIGENDIAN
112
+ d0 = bswap16x4(d0);
113
+ d1 = bswap16x4(d1);
114
#endif
115
+ pwd->d[0] = d0;
116
+ pwd->d[1] = d1;
117
}
118
119
void helper_msa_ld_w(CPUMIPSState *env, uint32_t wd,
120
@@ -XXX,XX +XXX,XX @@ void helper_msa_ld_w(CPUMIPSState *env, uint32_t wd,
121
{
122
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
123
uintptr_t ra = GETPC();
124
+ uint64_t d0, d1;
125
126
-#if !defined(HOST_WORDS_BIGENDIAN)
127
- pwd->w[0] = cpu_ldl_data_ra(env, addr + (0 << DF_WORD), ra);
128
- pwd->w[1] = cpu_ldl_data_ra(env, addr + (1 << DF_WORD), ra);
129
- pwd->w[2] = cpu_ldl_data_ra(env, addr + (2 << DF_WORD), ra);
130
- pwd->w[3] = cpu_ldl_data_ra(env, addr + (3 << DF_WORD), ra);
131
-#else
132
- pwd->w[0] = cpu_ldl_data_ra(env, addr + (1 << DF_WORD), ra);
133
- pwd->w[1] = cpu_ldl_data_ra(env, addr + (0 << DF_WORD), ra);
134
- pwd->w[2] = cpu_ldl_data_ra(env, addr + (3 << DF_WORD), ra);
135
- pwd->w[3] = cpu_ldl_data_ra(env, addr + (2 << DF_WORD), ra);
136
+ /*
137
+ * Load 8 bytes at a time. Use little-endian load, then for
138
+ * big-endian target, we must then bswap the two words.
139
+ */
140
+ d0 = cpu_ldq_le_data_ra(env, addr + 0, ra);
141
+ d1 = cpu_ldq_le_data_ra(env, addr + 8, ra);
142
+#ifdef TARGET_WORDS_BIGENDIAN
143
+ d0 = bswap32x2(d0);
144
+ d1 = bswap32x2(d1);
145
#endif
146
+ pwd->d[0] = d0;
147
+ pwd->d[1] = d1;
148
}
149
150
void helper_msa_ld_d(CPUMIPSState *env, uint32_t wd,
151
@@ -XXX,XX +XXX,XX @@ void helper_msa_ld_d(CPUMIPSState *env, uint32_t wd,
152
{
153
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
154
uintptr_t ra = GETPC();
155
+ uint64_t d0, d1;
156
157
- pwd->d[0] = cpu_ldq_data_ra(env, addr + (0 << DF_DOUBLE), ra);
158
- pwd->d[1] = cpu_ldq_data_ra(env, addr + (1 << DF_DOUBLE), ra);
159
+ d0 = cpu_ldq_data_ra(env, addr + 0, ra);
160
+ d1 = cpu_ldq_data_ra(env, addr + 8, ra);
161
+ pwd->d[0] = d0;
162
+ pwd->d[1] = d1;
163
}
164
165
#define MSA_PAGESPAN(x) \
166
@@ -XXX,XX +XXX,XX @@ void helper_msa_st_b(CPUMIPSState *env, uint32_t wd,
167
168
ensure_writable_pages(env, addr, mmu_idx, ra);
169
170
-#if !defined(HOST_WORDS_BIGENDIAN)
171
- cpu_stb_data_ra(env, addr + (0 << DF_BYTE), pwd->b[0], ra);
172
- cpu_stb_data_ra(env, addr + (1 << DF_BYTE), pwd->b[1], ra);
173
- cpu_stb_data_ra(env, addr + (2 << DF_BYTE), pwd->b[2], ra);
174
- cpu_stb_data_ra(env, addr + (3 << DF_BYTE), pwd->b[3], ra);
175
- cpu_stb_data_ra(env, addr + (4 << DF_BYTE), pwd->b[4], ra);
176
- cpu_stb_data_ra(env, addr + (5 << DF_BYTE), pwd->b[5], ra);
177
- cpu_stb_data_ra(env, addr + (6 << DF_BYTE), pwd->b[6], ra);
178
- cpu_stb_data_ra(env, addr + (7 << DF_BYTE), pwd->b[7], ra);
179
- cpu_stb_data_ra(env, addr + (8 << DF_BYTE), pwd->b[8], ra);
180
- cpu_stb_data_ra(env, addr + (9 << DF_BYTE), pwd->b[9], ra);
181
- cpu_stb_data_ra(env, addr + (10 << DF_BYTE), pwd->b[10], ra);
182
- cpu_stb_data_ra(env, addr + (11 << DF_BYTE), pwd->b[11], ra);
183
- cpu_stb_data_ra(env, addr + (12 << DF_BYTE), pwd->b[12], ra);
184
- cpu_stb_data_ra(env, addr + (13 << DF_BYTE), pwd->b[13], ra);
185
- cpu_stb_data_ra(env, addr + (14 << DF_BYTE), pwd->b[14], ra);
186
- cpu_stb_data_ra(env, addr + (15 << DF_BYTE), pwd->b[15], ra);
187
-#else
188
- cpu_stb_data_ra(env, addr + (7 << DF_BYTE), pwd->b[0], ra);
189
- cpu_stb_data_ra(env, addr + (6 << DF_BYTE), pwd->b[1], ra);
190
- cpu_stb_data_ra(env, addr + (5 << DF_BYTE), pwd->b[2], ra);
191
- cpu_stb_data_ra(env, addr + (4 << DF_BYTE), pwd->b[3], ra);
192
- cpu_stb_data_ra(env, addr + (3 << DF_BYTE), pwd->b[4], ra);
193
- cpu_stb_data_ra(env, addr + (2 << DF_BYTE), pwd->b[5], ra);
194
- cpu_stb_data_ra(env, addr + (1 << DF_BYTE), pwd->b[6], ra);
195
- cpu_stb_data_ra(env, addr + (0 << DF_BYTE), pwd->b[7], ra);
196
- cpu_stb_data_ra(env, addr + (15 << DF_BYTE), pwd->b[8], ra);
197
- cpu_stb_data_ra(env, addr + (14 << DF_BYTE), pwd->b[9], ra);
198
- cpu_stb_data_ra(env, addr + (13 << DF_BYTE), pwd->b[10], ra);
199
- cpu_stb_data_ra(env, addr + (12 << DF_BYTE), pwd->b[11], ra);
200
- cpu_stb_data_ra(env, addr + (11 << DF_BYTE), pwd->b[12], ra);
201
- cpu_stb_data_ra(env, addr + (10 << DF_BYTE), pwd->b[13], ra);
202
- cpu_stb_data_ra(env, addr + (9 << DF_BYTE), pwd->b[14], ra);
203
- cpu_stb_data_ra(env, addr + (8 << DF_BYTE), pwd->b[15], ra);
204
-#endif
205
+ /* Store 8 bytes at a time. Vector element ordering makes this LE. */
206
+ cpu_stq_le_data_ra(env, addr + 0, pwd->d[0], ra);
207
+ cpu_stq_le_data_ra(env, addr + 0, pwd->d[1], ra);
208
}
209
210
void helper_msa_st_h(CPUMIPSState *env, uint32_t wd,
211
@@ -XXX,XX +XXX,XX @@ void helper_msa_st_h(CPUMIPSState *env, uint32_t wd,
212
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
213
int mmu_idx = cpu_mmu_index(env, false);
214
uintptr_t ra = GETPC();
215
+ uint64_t d0, d1;
216
217
ensure_writable_pages(env, addr, mmu_idx, ra);
218
219
-#if !defined(HOST_WORDS_BIGENDIAN)
220
- cpu_stw_data_ra(env, addr + (0 << DF_HALF), pwd->h[0], ra);
221
- cpu_stw_data_ra(env, addr + (1 << DF_HALF), pwd->h[1], ra);
222
- cpu_stw_data_ra(env, addr + (2 << DF_HALF), pwd->h[2], ra);
223
- cpu_stw_data_ra(env, addr + (3 << DF_HALF), pwd->h[3], ra);
224
- cpu_stw_data_ra(env, addr + (4 << DF_HALF), pwd->h[4], ra);
225
- cpu_stw_data_ra(env, addr + (5 << DF_HALF), pwd->h[5], ra);
226
- cpu_stw_data_ra(env, addr + (6 << DF_HALF), pwd->h[6], ra);
227
- cpu_stw_data_ra(env, addr + (7 << DF_HALF), pwd->h[7], ra);
228
-#else
229
- cpu_stw_data_ra(env, addr + (3 << DF_HALF), pwd->h[0], ra);
230
- cpu_stw_data_ra(env, addr + (2 << DF_HALF), pwd->h[1], ra);
231
- cpu_stw_data_ra(env, addr + (1 << DF_HALF), pwd->h[2], ra);
232
- cpu_stw_data_ra(env, addr + (0 << DF_HALF), pwd->h[3], ra);
233
- cpu_stw_data_ra(env, addr + (7 << DF_HALF), pwd->h[4], ra);
234
- cpu_stw_data_ra(env, addr + (6 << DF_HALF), pwd->h[5], ra);
235
- cpu_stw_data_ra(env, addr + (5 << DF_HALF), pwd->h[6], ra);
236
- cpu_stw_data_ra(env, addr + (4 << DF_HALF), pwd->h[7], ra);
237
+ /* Store 8 bytes at a time. See helper_msa_ld_h. */
238
+ d0 = pwd->d[0];
239
+ d1 = pwd->d[1];
240
+#ifdef TARGET_WORDS_BIGENDIAN
241
+ d0 = bswap16x4(d0);
242
+ d1 = bswap16x4(d1);
243
#endif
244
+ cpu_stq_le_data_ra(env, addr + 0, d0, ra);
245
+ cpu_stq_le_data_ra(env, addr + 8, d1, ra);
246
}
247
248
void helper_msa_st_w(CPUMIPSState *env, uint32_t wd,
249
@@ -XXX,XX +XXX,XX @@ void helper_msa_st_w(CPUMIPSState *env, uint32_t wd,
250
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
251
int mmu_idx = cpu_mmu_index(env, false);
252
uintptr_t ra = GETPC();
253
+ uint64_t d0, d1;
254
255
ensure_writable_pages(env, addr, mmu_idx, ra);
256
257
-#if !defined(HOST_WORDS_BIGENDIAN)
258
- cpu_stl_data_ra(env, addr + (0 << DF_WORD), pwd->w[0], ra);
259
- cpu_stl_data_ra(env, addr + (1 << DF_WORD), pwd->w[1], ra);
260
- cpu_stl_data_ra(env, addr + (2 << DF_WORD), pwd->w[2], ra);
261
- cpu_stl_data_ra(env, addr + (3 << DF_WORD), pwd->w[3], ra);
262
-#else
263
- cpu_stl_data_ra(env, addr + (1 << DF_WORD), pwd->w[0], ra);
264
- cpu_stl_data_ra(env, addr + (0 << DF_WORD), pwd->w[1], ra);
265
- cpu_stl_data_ra(env, addr + (3 << DF_WORD), pwd->w[2], ra);
266
- cpu_stl_data_ra(env, addr + (2 << DF_WORD), pwd->w[3], ra);
267
+ /* Store 8 bytes at a time. See helper_msa_ld_w. */
268
+ d0 = pwd->d[0];
269
+ d1 = pwd->d[1];
270
+#ifdef TARGET_WORDS_BIGENDIAN
271
+ d0 = bswap32x2(d0);
272
+ d1 = bswap32x2(d1);
273
#endif
274
+ cpu_stq_le_data_ra(env, addr + 0, d0, ra);
275
+ cpu_stq_le_data_ra(env, addr + 8, d1, ra);
276
}
277
278
void helper_msa_st_d(CPUMIPSState *env, uint32_t wd,
279
@@ -XXX,XX +XXX,XX @@ void helper_msa_st_d(CPUMIPSState *env, uint32_t wd,
280
281
ensure_writable_pages(env, addr, mmu_idx, GETPC());
282
283
- cpu_stq_data_ra(env, addr + (0 << DF_DOUBLE), pwd->d[0], ra);
284
- cpu_stq_data_ra(env, addr + (1 << DF_DOUBLE), pwd->d[1], ra);
285
+ cpu_stq_data_ra(env, addr + 0, pwd->d[0], ra);
286
+ cpu_stq_data_ra(env, addr + 8, pwd->d[1], ra);
287
}
288
--
194
--
289
2.25.1
195
2.17.2
290
196
291
197
diff view generated by jsdifflib
1
From: BALATON Zoltan <balaton@eik.bme.hu>
1
When op raises an exception, it may not have initialized the output
2
2
temps that would be written back by wout or cout.
3
In memory_region_access_valid() invalid accesses are logged to help
4
debugging but the log message does not say if it was a read or write.
5
Log that too to better identify the access causing the problem.
6
3
7
Reviewed-by: David Hildenbrand <david@redhat.com>
4
Reviewed-by: David Hildenbrand <david@redhat.com>
8
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
9
Message-Id: <20211011173616.F1DE0756022@zero.eik.bme.hu>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
---
6
---
12
softmmu/memory.c | 20 ++++++++++----------
7
target/s390x/translate.c | 20 +++++++++++++++-----
13
1 file changed, 10 insertions(+), 10 deletions(-)
8
1 file changed, 15 insertions(+), 5 deletions(-)
14
9
15
diff --git a/softmmu/memory.c b/softmmu/memory.c
10
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
16
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
17
--- a/softmmu/memory.c
12
--- a/target/s390x/translate.c
18
+++ b/softmmu/memory.c
13
+++ b/target/s390x/translate.c
19
@@ -XXX,XX +XXX,XX @@ bool memory_region_access_valid(MemoryRegion *mr,
14
@@ -XXX,XX +XXX,XX @@ struct DisasInsn {
20
{
15
21
if (mr->ops->valid.accepts
16
const char *name;
22
&& !mr->ops->valid.accepts(mr->opaque, addr, size, is_write, attrs)) {
17
23
- qemu_log_mask(LOG_GUEST_ERROR, "Invalid access at addr "
18
+ /* Pre-process arguments before HELP_OP. */
24
- "0x%" HWADDR_PRIX ", size %u, "
19
void (*help_in1)(DisasContext *, DisasFields *, DisasOps *);
25
- "region '%s', reason: rejected\n",
20
void (*help_in2)(DisasContext *, DisasFields *, DisasOps *);
26
+ qemu_log_mask(LOG_GUEST_ERROR, "Invalid %s at addr 0x%" HWADDR_PRIX
21
void (*help_prep)(DisasContext *, DisasFields *, DisasOps *);
27
+ ", size %u, region '%s', reason: rejected\n",
22
+
28
+ is_write ? "write" : "read",
23
+ /*
29
addr, size, memory_region_name(mr));
24
+ * Post-process output after HELP_OP.
30
return false;
25
+ * Note that these are not called if HELP_OP returns DISAS_NORETURN.
26
+ */
27
void (*help_wout)(DisasContext *, DisasFields *, DisasOps *);
28
void (*help_cout)(DisasContext *, DisasOps *);
29
+
30
+ /* Implement the operation itself. */
31
DisasJumpType (*help_op)(DisasContext *, DisasOps *);
32
33
uint64_t data;
34
@@ -XXX,XX +XXX,XX @@ static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s)
35
if (insn->help_op) {
36
ret = insn->help_op(s, &o);
31
}
37
}
32
38
- if (insn->help_wout) {
33
if (!mr->ops->valid.unaligned && (addr & (size - 1))) {
39
- insn->help_wout(s, &f, &o);
34
- qemu_log_mask(LOG_GUEST_ERROR, "Invalid access at addr "
40
- }
35
- "0x%" HWADDR_PRIX ", size %u, "
41
- if (insn->help_cout) {
36
- "region '%s', reason: unaligned\n",
42
- insn->help_cout(s, &o);
37
+ qemu_log_mask(LOG_GUEST_ERROR, "Invalid %s at addr 0x%" HWADDR_PRIX
43
+ if (ret != DISAS_NORETURN) {
38
+ ", size %u, region '%s', reason: unaligned\n",
44
+ if (insn->help_wout) {
39
+ is_write ? "write" : "read",
45
+ insn->help_wout(s, &f, &o);
40
addr, size, memory_region_name(mr));
46
+ }
41
return false;
47
+ if (insn->help_cout) {
48
+ insn->help_cout(s, &o);
49
+ }
42
}
50
}
43
@@ -XXX,XX +XXX,XX @@ bool memory_region_access_valid(MemoryRegion *mr,
51
44
52
/* Free any temporaries created by the helpers. */
45
if (size > mr->ops->valid.max_access_size
46
|| size < mr->ops->valid.min_access_size) {
47
- qemu_log_mask(LOG_GUEST_ERROR, "Invalid access at addr "
48
- "0x%" HWADDR_PRIX ", size %u, "
49
- "region '%s', reason: invalid size "
50
- "(min:%u max:%u)\n",
51
+ qemu_log_mask(LOG_GUEST_ERROR, "Invalid %s at addr 0x%" HWADDR_PRIX
52
+ ", size %u, region '%s', reason: invalid size "
53
+ "(min:%u max:%u)\n",
54
+ is_write ? "write" : "read",
55
addr, size, memory_region_name(mr),
56
mr->ops->valid.min_access_size,
57
mr->ops->valid.max_access_size);
58
--
53
--
59
2.25.1
54
2.17.2
60
55
61
56
diff view generated by jsdifflib
1
We should not have been using the helper_ret_* set of
1
Reviewed-by: David Hildenbrand <david@redhat.com>
2
functions, as they are supposed to be private to tcg.
3
Nor should we have been using the plain cpu_*_data set
4
of functions, as they do not handle unwinding properly.
5
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
3
---
9
target/mips/tcg/msa_helper.c | 420 +++++++++++------------------------
4
target/s390x/mem_helper.c | 40 +++++++++++++++++++--------------------
10
1 file changed, 135 insertions(+), 285 deletions(-)
5
target/s390x/translate.c | 25 +++++++++++++++++-------
6
2 files changed, 38 insertions(+), 27 deletions(-)
11
7
12
diff --git a/target/mips/tcg/msa_helper.c b/target/mips/tcg/msa_helper.c
8
diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
13
index XXXXXXX..XXXXXXX 100644
9
index XXXXXXX..XXXXXXX 100644
14
--- a/target/mips/tcg/msa_helper.c
10
--- a/target/s390x/mem_helper.c
15
+++ b/target/mips/tcg/msa_helper.c
11
+++ b/target/s390x/mem_helper.c
16
@@ -XXX,XX +XXX,XX @@ void helper_msa_ld_b(CPUMIPSState *env, uint32_t wd,
12
@@ -XXX,XX +XXX,XX @@ void HELPER(cdsg_parallel)(CPUS390XState *env, uint64_t addr,
17
target_ulong addr)
13
Int128 oldv;
14
bool fail;
15
16
- if (!HAVE_CMPXCHG128) {
17
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
18
- }
19
+ assert(HAVE_CMPXCHG128);
20
21
mem_idx = cpu_mmu_index(env, false);
22
oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
23
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(lpq_parallel)(CPUS390XState *env, uint64_t addr)
18
{
24
{
19
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
25
uintptr_t ra = GETPC();
20
- MEMOP_IDX(DF_BYTE)
26
uint64_t hi, lo;
21
-#if !defined(CONFIG_USER_ONLY)
27
+ int mem_idx;
22
+ uintptr_t ra = GETPC();
28
+ TCGMemOpIdx oi;
29
+ Int128 v;
30
31
- if (HAVE_ATOMIC128) {
32
- int mem_idx = cpu_mmu_index(env, false);
33
- TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
34
- Int128 v = helper_atomic_ldo_be_mmu(env, addr, oi, ra);
35
- hi = int128_gethi(v);
36
- lo = int128_getlo(v);
37
- } else {
38
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
39
- }
40
+ assert(HAVE_ATOMIC128);
23
+
41
+
24
#if !defined(HOST_WORDS_BIGENDIAN)
42
+ mem_idx = cpu_mmu_index(env, false);
25
- pwd->b[0] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC());
43
+ oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
26
- pwd->b[1] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC());
44
+ v = helper_atomic_ldo_be_mmu(env, addr, oi, ra);
27
- pwd->b[2] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC());
45
+ hi = int128_gethi(v);
28
- pwd->b[3] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC());
46
+ lo = int128_getlo(v);
29
- pwd->b[4] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC());
47
30
- pwd->b[5] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC());
48
env->retxl = lo;
31
- pwd->b[6] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC());
49
return hi;
32
- pwd->b[7] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC());
50
@@ -XXX,XX +XXX,XX @@ void HELPER(stpq_parallel)(CPUS390XState *env, uint64_t addr,
33
- pwd->b[8] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC());
51
uint64_t low, uint64_t high)
34
- pwd->b[9] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC());
52
{
35
- pwd->b[10] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC());
53
uintptr_t ra = GETPC();
36
- pwd->b[11] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC());
54
+ int mem_idx;
37
- pwd->b[12] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC());
55
+ TCGMemOpIdx oi;
38
- pwd->b[13] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC());
56
+ Int128 v;
39
- pwd->b[14] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC());
57
40
- pwd->b[15] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC());
58
- if (HAVE_ATOMIC128) {
41
+ pwd->b[0] = cpu_ldub_data_ra(env, addr + (0 << DF_BYTE), ra);
59
- int mem_idx = cpu_mmu_index(env, false);
42
+ pwd->b[1] = cpu_ldub_data_ra(env, addr + (1 << DF_BYTE), ra);
60
- TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
43
+ pwd->b[2] = cpu_ldub_data_ra(env, addr + (2 << DF_BYTE), ra);
61
- Int128 v = int128_make128(low, high);
44
+ pwd->b[3] = cpu_ldub_data_ra(env, addr + (3 << DF_BYTE), ra);
62
- helper_atomic_sto_be_mmu(env, addr, v, oi, ra);
45
+ pwd->b[4] = cpu_ldub_data_ra(env, addr + (4 << DF_BYTE), ra);
63
- } else {
46
+ pwd->b[5] = cpu_ldub_data_ra(env, addr + (5 << DF_BYTE), ra);
64
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
47
+ pwd->b[6] = cpu_ldub_data_ra(env, addr + (6 << DF_BYTE), ra);
65
- }
48
+ pwd->b[7] = cpu_ldub_data_ra(env, addr + (7 << DF_BYTE), ra);
66
+ assert(HAVE_ATOMIC128);
49
+ pwd->b[8] = cpu_ldub_data_ra(env, addr + (8 << DF_BYTE), ra);
67
+
50
+ pwd->b[9] = cpu_ldub_data_ra(env, addr + (9 << DF_BYTE), ra);
68
+ mem_idx = cpu_mmu_index(env, false);
51
+ pwd->b[10] = cpu_ldub_data_ra(env, addr + (10 << DF_BYTE), ra);
69
+ oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
52
+ pwd->b[11] = cpu_ldub_data_ra(env, addr + (11 << DF_BYTE), ra);
70
+ v = int128_make128(low, high);
53
+ pwd->b[12] = cpu_ldub_data_ra(env, addr + (12 << DF_BYTE), ra);
71
+ helper_atomic_sto_be_mmu(env, addr, v, oi, ra);
54
+ pwd->b[13] = cpu_ldub_data_ra(env, addr + (13 << DF_BYTE), ra);
55
+ pwd->b[14] = cpu_ldub_data_ra(env, addr + (14 << DF_BYTE), ra);
56
+ pwd->b[15] = cpu_ldub_data_ra(env, addr + (15 << DF_BYTE), ra);
57
#else
58
- pwd->b[0] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC());
59
- pwd->b[1] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC());
60
- pwd->b[2] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC());
61
- pwd->b[3] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC());
62
- pwd->b[4] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC());
63
- pwd->b[5] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC());
64
- pwd->b[6] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC());
65
- pwd->b[7] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC());
66
- pwd->b[8] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC());
67
- pwd->b[9] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC());
68
- pwd->b[10] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC());
69
- pwd->b[11] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC());
70
- pwd->b[12] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC());
71
- pwd->b[13] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC());
72
- pwd->b[14] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC());
73
- pwd->b[15] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC());
74
-#endif
75
-#else
76
-#if !defined(HOST_WORDS_BIGENDIAN)
77
- pwd->b[0] = cpu_ldub_data(env, addr + (0 << DF_BYTE));
78
- pwd->b[1] = cpu_ldub_data(env, addr + (1 << DF_BYTE));
79
- pwd->b[2] = cpu_ldub_data(env, addr + (2 << DF_BYTE));
80
- pwd->b[3] = cpu_ldub_data(env, addr + (3 << DF_BYTE));
81
- pwd->b[4] = cpu_ldub_data(env, addr + (4 << DF_BYTE));
82
- pwd->b[5] = cpu_ldub_data(env, addr + (5 << DF_BYTE));
83
- pwd->b[6] = cpu_ldub_data(env, addr + (6 << DF_BYTE));
84
- pwd->b[7] = cpu_ldub_data(env, addr + (7 << DF_BYTE));
85
- pwd->b[8] = cpu_ldub_data(env, addr + (8 << DF_BYTE));
86
- pwd->b[9] = cpu_ldub_data(env, addr + (9 << DF_BYTE));
87
- pwd->b[10] = cpu_ldub_data(env, addr + (10 << DF_BYTE));
88
- pwd->b[11] = cpu_ldub_data(env, addr + (11 << DF_BYTE));
89
- pwd->b[12] = cpu_ldub_data(env, addr + (12 << DF_BYTE));
90
- pwd->b[13] = cpu_ldub_data(env, addr + (13 << DF_BYTE));
91
- pwd->b[14] = cpu_ldub_data(env, addr + (14 << DF_BYTE));
92
- pwd->b[15] = cpu_ldub_data(env, addr + (15 << DF_BYTE));
93
-#else
94
- pwd->b[0] = cpu_ldub_data(env, addr + (7 << DF_BYTE));
95
- pwd->b[1] = cpu_ldub_data(env, addr + (6 << DF_BYTE));
96
- pwd->b[2] = cpu_ldub_data(env, addr + (5 << DF_BYTE));
97
- pwd->b[3] = cpu_ldub_data(env, addr + (4 << DF_BYTE));
98
- pwd->b[4] = cpu_ldub_data(env, addr + (3 << DF_BYTE));
99
- pwd->b[5] = cpu_ldub_data(env, addr + (2 << DF_BYTE));
100
- pwd->b[6] = cpu_ldub_data(env, addr + (1 << DF_BYTE));
101
- pwd->b[7] = cpu_ldub_data(env, addr + (0 << DF_BYTE));
102
- pwd->b[8] = cpu_ldub_data(env, addr + (15 << DF_BYTE));
103
- pwd->b[9] = cpu_ldub_data(env, addr + (14 << DF_BYTE));
104
- pwd->b[10] = cpu_ldub_data(env, addr + (13 << DF_BYTE));
105
- pwd->b[11] = cpu_ldub_data(env, addr + (12 << DF_BYTE));
106
- pwd->b[12] = cpu_ldub_data(env, addr + (11 << DF_BYTE));
107
- pwd->b[13] = cpu_ldub_data(env, addr + (10 << DF_BYTE));
108
- pwd->b[14] = cpu_ldub_data(env, addr + (9 << DF_BYTE));
109
- pwd->b[15] = cpu_ldub_data(env, addr + (8 << DF_BYTE));
110
-#endif
111
+ pwd->b[0] = cpu_ldub_data_ra(env, addr + (7 << DF_BYTE), ra);
112
+ pwd->b[1] = cpu_ldub_data_ra(env, addr + (6 << DF_BYTE), ra);
113
+ pwd->b[2] = cpu_ldub_data_ra(env, addr + (5 << DF_BYTE), ra);
114
+ pwd->b[3] = cpu_ldub_data_ra(env, addr + (4 << DF_BYTE), ra);
115
+ pwd->b[4] = cpu_ldub_data_ra(env, addr + (3 << DF_BYTE), ra);
116
+ pwd->b[5] = cpu_ldub_data_ra(env, addr + (2 << DF_BYTE), ra);
117
+ pwd->b[6] = cpu_ldub_data_ra(env, addr + (1 << DF_BYTE), ra);
118
+ pwd->b[7] = cpu_ldub_data_ra(env, addr + (0 << DF_BYTE), ra);
119
+ pwd->b[8] = cpu_ldub_data_ra(env, addr + (15 << DF_BYTE), ra);
120
+ pwd->b[9] = cpu_ldub_data_ra(env, addr + (14 << DF_BYTE), ra);
121
+ pwd->b[10] = cpu_ldub_data_ra(env, addr + (13 << DF_BYTE), ra);
122
+ pwd->b[11] = cpu_ldub_data_ra(env, addr + (12 << DF_BYTE), ra);
123
+ pwd->b[12] = cpu_ldub_data_ra(env, addr + (11 << DF_BYTE), ra);
124
+ pwd->b[13] = cpu_ldub_data_ra(env, addr + (10 << DF_BYTE), ra);
125
+ pwd->b[14] = cpu_ldub_data_ra(env, addr + (9 << DF_BYTE), ra);
126
+ pwd->b[15] = cpu_ldub_data_ra(env, addr + (8 << DF_BYTE), ra);
127
#endif
128
}
72
}
129
73
130
@@ -XXX,XX +XXX,XX @@ void helper_msa_ld_h(CPUMIPSState *env, uint32_t wd,
74
/* Execute instruction. This instruction executes an insn modified with
131
target_ulong addr)
75
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/s390x/translate.c
78
+++ b/target/s390x/translate.c
79
@@ -XXX,XX +XXX,XX @@
80
#include "trace-tcg.h"
81
#include "exec/translator.h"
82
#include "exec/log.h"
83
+#include "qemu/atomic128.h"
84
85
86
/* Information that (most) every instruction needs to manipulate. */
87
@@ -XXX,XX +XXX,XX @@ static DisasJumpType op_cdsg(DisasContext *s, DisasOps *o)
88
int r3 = get_field(s->fields, r3);
89
int d2 = get_field(s->fields, d2);
90
int b2 = get_field(s->fields, b2);
91
+ DisasJumpType ret = DISAS_NEXT;
92
TCGv_i64 addr;
93
TCGv_i32 t_r1, t_r3;
94
95
@@ -XXX,XX +XXX,XX @@ static DisasJumpType op_cdsg(DisasContext *s, DisasOps *o)
96
addr = get_address(s, 0, b2, d2);
97
t_r1 = tcg_const_i32(r1);
98
t_r3 = tcg_const_i32(r3);
99
- if (tb_cflags(s->base.tb) & CF_PARALLEL) {
100
+ if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
101
+ gen_helper_cdsg(cpu_env, addr, t_r1, t_r3);
102
+ } else if (HAVE_CMPXCHG128) {
103
gen_helper_cdsg_parallel(cpu_env, addr, t_r1, t_r3);
104
} else {
105
- gen_helper_cdsg(cpu_env, addr, t_r1, t_r3);
106
+ gen_helper_exit_atomic(cpu_env);
107
+ ret = DISAS_NORETURN;
108
}
109
tcg_temp_free_i64(addr);
110
tcg_temp_free_i32(t_r1);
111
tcg_temp_free_i32(t_r3);
112
113
set_cc_static(s);
114
- return DISAS_NEXT;
115
+ return ret;
116
}
117
118
static DisasJumpType op_csst(DisasContext *s, DisasOps *o)
119
@@ -XXX,XX +XXX,XX @@ static DisasJumpType op_lpd(DisasContext *s, DisasOps *o)
120
121
static DisasJumpType op_lpq(DisasContext *s, DisasOps *o)
132
{
122
{
133
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
123
- if (tb_cflags(s->base.tb) & CF_PARALLEL) {
134
- MEMOP_IDX(DF_HALF)
124
+ if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
135
-#if !defined(CONFIG_USER_ONLY)
125
+ gen_helper_lpq(o->out, cpu_env, o->in2);
136
+ uintptr_t ra = GETPC();
126
+ } else if (HAVE_ATOMIC128) {
137
+
127
gen_helper_lpq_parallel(o->out, cpu_env, o->in2);
138
#if !defined(HOST_WORDS_BIGENDIAN)
128
} else {
139
- pwd->h[0] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC());
129
- gen_helper_lpq(o->out, cpu_env, o->in2);
140
- pwd->h[1] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC());
130
+ gen_helper_exit_atomic(cpu_env);
141
- pwd->h[2] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC());
131
+ return DISAS_NORETURN;
142
- pwd->h[3] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC());
132
}
143
- pwd->h[4] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC());
133
return_low128(o->out2);
144
- pwd->h[5] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC());
134
return DISAS_NEXT;
145
- pwd->h[6] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC());
135
@@ -XXX,XX +XXX,XX @@ static DisasJumpType op_stmh(DisasContext *s, DisasOps *o)
146
- pwd->h[7] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC());
136
147
+ pwd->h[0] = cpu_lduw_data_ra(env, addr + (0 << DF_HALF), ra);
137
static DisasJumpType op_stpq(DisasContext *s, DisasOps *o)
148
+ pwd->h[1] = cpu_lduw_data_ra(env, addr + (1 << DF_HALF), ra);
149
+ pwd->h[2] = cpu_lduw_data_ra(env, addr + (2 << DF_HALF), ra);
150
+ pwd->h[3] = cpu_lduw_data_ra(env, addr + (3 << DF_HALF), ra);
151
+ pwd->h[4] = cpu_lduw_data_ra(env, addr + (4 << DF_HALF), ra);
152
+ pwd->h[5] = cpu_lduw_data_ra(env, addr + (5 << DF_HALF), ra);
153
+ pwd->h[6] = cpu_lduw_data_ra(env, addr + (6 << DF_HALF), ra);
154
+ pwd->h[7] = cpu_lduw_data_ra(env, addr + (7 << DF_HALF), ra);
155
#else
156
- pwd->h[0] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC());
157
- pwd->h[1] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC());
158
- pwd->h[2] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC());
159
- pwd->h[3] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC());
160
- pwd->h[4] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC());
161
- pwd->h[5] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC());
162
- pwd->h[6] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC());
163
- pwd->h[7] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC());
164
-#endif
165
-#else
166
-#if !defined(HOST_WORDS_BIGENDIAN)
167
- pwd->h[0] = cpu_lduw_data(env, addr + (0 << DF_HALF));
168
- pwd->h[1] = cpu_lduw_data(env, addr + (1 << DF_HALF));
169
- pwd->h[2] = cpu_lduw_data(env, addr + (2 << DF_HALF));
170
- pwd->h[3] = cpu_lduw_data(env, addr + (3 << DF_HALF));
171
- pwd->h[4] = cpu_lduw_data(env, addr + (4 << DF_HALF));
172
- pwd->h[5] = cpu_lduw_data(env, addr + (5 << DF_HALF));
173
- pwd->h[6] = cpu_lduw_data(env, addr + (6 << DF_HALF));
174
- pwd->h[7] = cpu_lduw_data(env, addr + (7 << DF_HALF));
175
-#else
176
- pwd->h[0] = cpu_lduw_data(env, addr + (3 << DF_HALF));
177
- pwd->h[1] = cpu_lduw_data(env, addr + (2 << DF_HALF));
178
- pwd->h[2] = cpu_lduw_data(env, addr + (1 << DF_HALF));
179
- pwd->h[3] = cpu_lduw_data(env, addr + (0 << DF_HALF));
180
- pwd->h[4] = cpu_lduw_data(env, addr + (7 << DF_HALF));
181
- pwd->h[5] = cpu_lduw_data(env, addr + (6 << DF_HALF));
182
- pwd->h[6] = cpu_lduw_data(env, addr + (5 << DF_HALF));
183
- pwd->h[7] = cpu_lduw_data(env, addr + (4 << DF_HALF));
184
-#endif
185
+ pwd->h[0] = cpu_lduw_data_ra(env, addr + (3 << DF_HALF), ra);
186
+ pwd->h[1] = cpu_lduw_data_ra(env, addr + (2 << DF_HALF), ra);
187
+ pwd->h[2] = cpu_lduw_data_ra(env, addr + (1 << DF_HALF), ra);
188
+ pwd->h[3] = cpu_lduw_data_ra(env, addr + (0 << DF_HALF), ra);
189
+ pwd->h[4] = cpu_lduw_data_ra(env, addr + (7 << DF_HALF), ra);
190
+ pwd->h[5] = cpu_lduw_data_ra(env, addr + (6 << DF_HALF), ra);
191
+ pwd->h[6] = cpu_lduw_data_ra(env, addr + (5 << DF_HALF), ra);
192
+ pwd->h[7] = cpu_lduw_data_ra(env, addr + (4 << DF_HALF), ra);
193
#endif
194
}
195
196
@@ -XXX,XX +XXX,XX @@ void helper_msa_ld_w(CPUMIPSState *env, uint32_t wd,
197
target_ulong addr)
198
{
138
{
199
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
139
- if (tb_cflags(s->base.tb) & CF_PARALLEL) {
200
- MEMOP_IDX(DF_WORD)
140
+ if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
201
-#if !defined(CONFIG_USER_ONLY)
141
+ gen_helper_stpq(cpu_env, o->in2, o->out2, o->out);
202
+ uintptr_t ra = GETPC();
142
+ } else if (HAVE_ATOMIC128) {
203
+
143
gen_helper_stpq_parallel(cpu_env, o->in2, o->out2, o->out);
204
#if !defined(HOST_WORDS_BIGENDIAN)
144
} else {
205
- pwd->w[0] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC());
145
- gen_helper_stpq(cpu_env, o->in2, o->out2, o->out);
206
- pwd->w[1] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC());
146
+ gen_helper_exit_atomic(cpu_env);
207
- pwd->w[2] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC());
147
+ return DISAS_NORETURN;
208
- pwd->w[3] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC());
148
}
209
+ pwd->w[0] = cpu_ldl_data_ra(env, addr + (0 << DF_WORD), ra);
149
return DISAS_NEXT;
210
+ pwd->w[1] = cpu_ldl_data_ra(env, addr + (1 << DF_WORD), ra);
211
+ pwd->w[2] = cpu_ldl_data_ra(env, addr + (2 << DF_WORD), ra);
212
+ pwd->w[3] = cpu_ldl_data_ra(env, addr + (3 << DF_WORD), ra);
213
#else
214
- pwd->w[0] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC());
215
- pwd->w[1] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC());
216
- pwd->w[2] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC());
217
- pwd->w[3] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC());
218
-#endif
219
-#else
220
-#if !defined(HOST_WORDS_BIGENDIAN)
221
- pwd->w[0] = cpu_ldl_data(env, addr + (0 << DF_WORD));
222
- pwd->w[1] = cpu_ldl_data(env, addr + (1 << DF_WORD));
223
- pwd->w[2] = cpu_ldl_data(env, addr + (2 << DF_WORD));
224
- pwd->w[3] = cpu_ldl_data(env, addr + (3 << DF_WORD));
225
-#else
226
- pwd->w[0] = cpu_ldl_data(env, addr + (1 << DF_WORD));
227
- pwd->w[1] = cpu_ldl_data(env, addr + (0 << DF_WORD));
228
- pwd->w[2] = cpu_ldl_data(env, addr + (3 << DF_WORD));
229
- pwd->w[3] = cpu_ldl_data(env, addr + (2 << DF_WORD));
230
-#endif
231
+ pwd->w[0] = cpu_ldl_data_ra(env, addr + (1 << DF_WORD), ra);
232
+ pwd->w[1] = cpu_ldl_data_ra(env, addr + (0 << DF_WORD), ra);
233
+ pwd->w[2] = cpu_ldl_data_ra(env, addr + (3 << DF_WORD), ra);
234
+ pwd->w[3] = cpu_ldl_data_ra(env, addr + (2 << DF_WORD), ra);
235
#endif
236
}
237
238
@@ -XXX,XX +XXX,XX @@ void helper_msa_ld_d(CPUMIPSState *env, uint32_t wd,
239
target_ulong addr)
240
{
241
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
242
- MEMOP_IDX(DF_DOUBLE)
243
-#if !defined(CONFIG_USER_ONLY)
244
- pwd->d[0] = helper_ret_ldq_mmu(env, addr + (0 << DF_DOUBLE), oi, GETPC());
245
- pwd->d[1] = helper_ret_ldq_mmu(env, addr + (1 << DF_DOUBLE), oi, GETPC());
246
-#else
247
- pwd->d[0] = cpu_ldq_data(env, addr + (0 << DF_DOUBLE));
248
- pwd->d[1] = cpu_ldq_data(env, addr + (1 << DF_DOUBLE));
249
-#endif
250
+ uintptr_t ra = GETPC();
251
+
252
+ pwd->d[0] = cpu_ldq_data_ra(env, addr + (0 << DF_DOUBLE), ra);
253
+ pwd->d[1] = cpu_ldq_data_ra(env, addr + (1 << DF_DOUBLE), ra);
254
}
255
256
#define MSA_PAGESPAN(x) \
257
@@ -XXX,XX +XXX,XX @@ void helper_msa_st_b(CPUMIPSState *env, uint32_t wd,
258
{
259
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
260
int mmu_idx = cpu_mmu_index(env, false);
261
+ uintptr_t ra = GETPC();
262
+
263
+ ensure_writable_pages(env, addr, mmu_idx, ra);
264
265
- MEMOP_IDX(DF_BYTE)
266
- ensure_writable_pages(env, addr, mmu_idx, GETPC());
267
-#if !defined(CONFIG_USER_ONLY)
268
#if !defined(HOST_WORDS_BIGENDIAN)
269
- helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[0], oi, GETPC());
270
- helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[1], oi, GETPC());
271
- helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[2], oi, GETPC());
272
- helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[3], oi, GETPC());
273
- helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[4], oi, GETPC());
274
- helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[5], oi, GETPC());
275
- helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[6], oi, GETPC());
276
- helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[7], oi, GETPC());
277
- helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[8], oi, GETPC());
278
- helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[9], oi, GETPC());
279
- helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[10], oi, GETPC());
280
- helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[11], oi, GETPC());
281
- helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[12], oi, GETPC());
282
- helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[13], oi, GETPC());
283
- helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[14], oi, GETPC());
284
- helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[15], oi, GETPC());
285
+ cpu_stb_data_ra(env, addr + (0 << DF_BYTE), pwd->b[0], ra);
286
+ cpu_stb_data_ra(env, addr + (1 << DF_BYTE), pwd->b[1], ra);
287
+ cpu_stb_data_ra(env, addr + (2 << DF_BYTE), pwd->b[2], ra);
288
+ cpu_stb_data_ra(env, addr + (3 << DF_BYTE), pwd->b[3], ra);
289
+ cpu_stb_data_ra(env, addr + (4 << DF_BYTE), pwd->b[4], ra);
290
+ cpu_stb_data_ra(env, addr + (5 << DF_BYTE), pwd->b[5], ra);
291
+ cpu_stb_data_ra(env, addr + (6 << DF_BYTE), pwd->b[6], ra);
292
+ cpu_stb_data_ra(env, addr + (7 << DF_BYTE), pwd->b[7], ra);
293
+ cpu_stb_data_ra(env, addr + (8 << DF_BYTE), pwd->b[8], ra);
294
+ cpu_stb_data_ra(env, addr + (9 << DF_BYTE), pwd->b[9], ra);
295
+ cpu_stb_data_ra(env, addr + (10 << DF_BYTE), pwd->b[10], ra);
296
+ cpu_stb_data_ra(env, addr + (11 << DF_BYTE), pwd->b[11], ra);
297
+ cpu_stb_data_ra(env, addr + (12 << DF_BYTE), pwd->b[12], ra);
298
+ cpu_stb_data_ra(env, addr + (13 << DF_BYTE), pwd->b[13], ra);
299
+ cpu_stb_data_ra(env, addr + (14 << DF_BYTE), pwd->b[14], ra);
300
+ cpu_stb_data_ra(env, addr + (15 << DF_BYTE), pwd->b[15], ra);
301
#else
302
- helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[0], oi, GETPC());
303
- helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[1], oi, GETPC());
304
- helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[2], oi, GETPC());
305
- helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[3], oi, GETPC());
306
- helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[4], oi, GETPC());
307
- helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[5], oi, GETPC());
308
- helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[6], oi, GETPC());
309
- helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[7], oi, GETPC());
310
- helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[8], oi, GETPC());
311
- helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[9], oi, GETPC());
312
- helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[10], oi, GETPC());
313
- helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[11], oi, GETPC());
314
- helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[12], oi, GETPC());
315
- helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[13], oi, GETPC());
316
- helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[14], oi, GETPC());
317
- helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[15], oi, GETPC());
318
-#endif
319
-#else
320
-#if !defined(HOST_WORDS_BIGENDIAN)
321
- cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[0]);
322
- cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[1]);
323
- cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[2]);
324
- cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[3]);
325
- cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[4]);
326
- cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[5]);
327
- cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[6]);
328
- cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[7]);
329
- cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[8]);
330
- cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[9]);
331
- cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[10]);
332
- cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[11]);
333
- cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[12]);
334
- cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[13]);
335
- cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[14]);
336
- cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[15]);
337
-#else
338
- cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[0]);
339
- cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[1]);
340
- cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[2]);
341
- cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[3]);
342
- cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[4]);
343
- cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[5]);
344
- cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[6]);
345
- cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[7]);
346
- cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[8]);
347
- cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[9]);
348
- cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[10]);
349
- cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[11]);
350
- cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[12]);
351
- cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[13]);
352
- cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[14]);
353
- cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[15]);
354
-#endif
355
+ cpu_stb_data_ra(env, addr + (7 << DF_BYTE), pwd->b[0], ra);
356
+ cpu_stb_data_ra(env, addr + (6 << DF_BYTE), pwd->b[1], ra);
357
+ cpu_stb_data_ra(env, addr + (5 << DF_BYTE), pwd->b[2], ra);
358
+ cpu_stb_data_ra(env, addr + (4 << DF_BYTE), pwd->b[3], ra);
359
+ cpu_stb_data_ra(env, addr + (3 << DF_BYTE), pwd->b[4], ra);
360
+ cpu_stb_data_ra(env, addr + (2 << DF_BYTE), pwd->b[5], ra);
361
+ cpu_stb_data_ra(env, addr + (1 << DF_BYTE), pwd->b[6], ra);
362
+ cpu_stb_data_ra(env, addr + (0 << DF_BYTE), pwd->b[7], ra);
363
+ cpu_stb_data_ra(env, addr + (15 << DF_BYTE), pwd->b[8], ra);
364
+ cpu_stb_data_ra(env, addr + (14 << DF_BYTE), pwd->b[9], ra);
365
+ cpu_stb_data_ra(env, addr + (13 << DF_BYTE), pwd->b[10], ra);
366
+ cpu_stb_data_ra(env, addr + (12 << DF_BYTE), pwd->b[11], ra);
367
+ cpu_stb_data_ra(env, addr + (11 << DF_BYTE), pwd->b[12], ra);
368
+ cpu_stb_data_ra(env, addr + (10 << DF_BYTE), pwd->b[13], ra);
369
+ cpu_stb_data_ra(env, addr + (9 << DF_BYTE), pwd->b[14], ra);
370
+ cpu_stb_data_ra(env, addr + (8 << DF_BYTE), pwd->b[15], ra);
371
#endif
372
}
373
374
@@ -XXX,XX +XXX,XX @@ void helper_msa_st_h(CPUMIPSState *env, uint32_t wd,
375
{
376
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
377
int mmu_idx = cpu_mmu_index(env, false);
378
+ uintptr_t ra = GETPC();
379
+
380
+ ensure_writable_pages(env, addr, mmu_idx, ra);
381
382
- MEMOP_IDX(DF_HALF)
383
- ensure_writable_pages(env, addr, mmu_idx, GETPC());
384
-#if !defined(CONFIG_USER_ONLY)
385
#if !defined(HOST_WORDS_BIGENDIAN)
386
- helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[0], oi, GETPC());
387
- helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[1], oi, GETPC());
388
- helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[2], oi, GETPC());
389
- helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[3], oi, GETPC());
390
- helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[4], oi, GETPC());
391
- helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[5], oi, GETPC());
392
- helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[6], oi, GETPC());
393
- helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[7], oi, GETPC());
394
+ cpu_stw_data_ra(env, addr + (0 << DF_HALF), pwd->h[0], ra);
395
+ cpu_stw_data_ra(env, addr + (1 << DF_HALF), pwd->h[1], ra);
396
+ cpu_stw_data_ra(env, addr + (2 << DF_HALF), pwd->h[2], ra);
397
+ cpu_stw_data_ra(env, addr + (3 << DF_HALF), pwd->h[3], ra);
398
+ cpu_stw_data_ra(env, addr + (4 << DF_HALF), pwd->h[4], ra);
399
+ cpu_stw_data_ra(env, addr + (5 << DF_HALF), pwd->h[5], ra);
400
+ cpu_stw_data_ra(env, addr + (6 << DF_HALF), pwd->h[6], ra);
401
+ cpu_stw_data_ra(env, addr + (7 << DF_HALF), pwd->h[7], ra);
402
#else
403
- helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[0], oi, GETPC());
404
- helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[1], oi, GETPC());
405
- helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[2], oi, GETPC());
406
- helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[3], oi, GETPC());
407
- helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[4], oi, GETPC());
408
- helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[5], oi, GETPC());
409
- helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[6], oi, GETPC());
410
- helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[7], oi, GETPC());
411
-#endif
412
-#else
413
-#if !defined(HOST_WORDS_BIGENDIAN)
414
- cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[0]);
415
- cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[1]);
416
- cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[2]);
417
- cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[3]);
418
- cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[4]);
419
- cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[5]);
420
- cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[6]);
421
- cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[7]);
422
-#else
423
- cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[0]);
424
- cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[1]);
425
- cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[2]);
426
- cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[3]);
427
- cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[4]);
428
- cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[5]);
429
- cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[6]);
430
- cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[7]);
431
-#endif
432
+ cpu_stw_data_ra(env, addr + (3 << DF_HALF), pwd->h[0], ra);
433
+ cpu_stw_data_ra(env, addr + (2 << DF_HALF), pwd->h[1], ra);
434
+ cpu_stw_data_ra(env, addr + (1 << DF_HALF), pwd->h[2], ra);
435
+ cpu_stw_data_ra(env, addr + (0 << DF_HALF), pwd->h[3], ra);
436
+ cpu_stw_data_ra(env, addr + (7 << DF_HALF), pwd->h[4], ra);
437
+ cpu_stw_data_ra(env, addr + (6 << DF_HALF), pwd->h[5], ra);
438
+ cpu_stw_data_ra(env, addr + (5 << DF_HALF), pwd->h[6], ra);
439
+ cpu_stw_data_ra(env, addr + (4 << DF_HALF), pwd->h[7], ra);
440
#endif
441
}
442
443
@@ -XXX,XX +XXX,XX @@ void helper_msa_st_w(CPUMIPSState *env, uint32_t wd,
444
{
445
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
446
int mmu_idx = cpu_mmu_index(env, false);
447
+ uintptr_t ra = GETPC();
448
+
449
+ ensure_writable_pages(env, addr, mmu_idx, ra);
450
451
- MEMOP_IDX(DF_WORD)
452
- ensure_writable_pages(env, addr, mmu_idx, GETPC());
453
-#if !defined(CONFIG_USER_ONLY)
454
#if !defined(HOST_WORDS_BIGENDIAN)
455
- helper_ret_stl_mmu(env, addr + (0 << DF_WORD), pwd->w[0], oi, GETPC());
456
- helper_ret_stl_mmu(env, addr + (1 << DF_WORD), pwd->w[1], oi, GETPC());
457
- helper_ret_stl_mmu(env, addr + (2 << DF_WORD), pwd->w[2], oi, GETPC());
458
- helper_ret_stl_mmu(env, addr + (3 << DF_WORD), pwd->w[3], oi, GETPC());
459
+ cpu_stl_data_ra(env, addr + (0 << DF_WORD), pwd->w[0], ra);
460
+ cpu_stl_data_ra(env, addr + (1 << DF_WORD), pwd->w[1], ra);
461
+ cpu_stl_data_ra(env, addr + (2 << DF_WORD), pwd->w[2], ra);
462
+ cpu_stl_data_ra(env, addr + (3 << DF_WORD), pwd->w[3], ra);
463
#else
464
- helper_ret_stl_mmu(env, addr + (1 << DF_WORD), pwd->w[0], oi, GETPC());
465
- helper_ret_stl_mmu(env, addr + (0 << DF_WORD), pwd->w[1], oi, GETPC());
466
- helper_ret_stl_mmu(env, addr + (3 << DF_WORD), pwd->w[2], oi, GETPC());
467
- helper_ret_stl_mmu(env, addr + (2 << DF_WORD), pwd->w[3], oi, GETPC());
468
-#endif
469
-#else
470
-#if !defined(HOST_WORDS_BIGENDIAN)
471
- cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[0]);
472
- cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[1]);
473
- cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[2]);
474
- cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[3]);
475
-#else
476
- cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[0]);
477
- cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[1]);
478
- cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[2]);
479
- cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[3]);
480
-#endif
481
+ cpu_stl_data_ra(env, addr + (1 << DF_WORD), pwd->w[0], ra);
482
+ cpu_stl_data_ra(env, addr + (0 << DF_WORD), pwd->w[1], ra);
483
+ cpu_stl_data_ra(env, addr + (3 << DF_WORD), pwd->w[2], ra);
484
+ cpu_stl_data_ra(env, addr + (2 << DF_WORD), pwd->w[3], ra);
485
#endif
486
}
487
488
@@ -XXX,XX +XXX,XX @@ void helper_msa_st_d(CPUMIPSState *env, uint32_t wd,
489
{
490
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
491
int mmu_idx = cpu_mmu_index(env, false);
492
+ uintptr_t ra = GETPC();
493
494
- MEMOP_IDX(DF_DOUBLE)
495
ensure_writable_pages(env, addr, mmu_idx, GETPC());
496
-#if !defined(CONFIG_USER_ONLY)
497
- helper_ret_stq_mmu(env, addr + (0 << DF_DOUBLE), pwd->d[0], oi, GETPC());
498
- helper_ret_stq_mmu(env, addr + (1 << DF_DOUBLE), pwd->d[1], oi, GETPC());
499
-#else
500
- cpu_stq_data(env, addr + (0 << DF_DOUBLE), pwd->d[0]);
501
- cpu_stq_data(env, addr + (1 << DF_DOUBLE), pwd->d[1]);
502
-#endif
503
+
504
+ cpu_stq_data_ra(env, addr + (0 << DF_DOUBLE), pwd->d[0], ra);
505
+ cpu_stq_data_ra(env, addr + (1 << DF_DOUBLE), pwd->d[1], ra);
506
}
150
}
507
--
151
--
508
2.25.1
152
2.17.2
509
153
510
154
diff view generated by jsdifflib
New patch
1
1
From: "Emilio G. Cota" <cota@braap.org>
2
3
Updates can come from other threads, so readers that do not
4
take tlb_lock must use atomic_read to avoid undefined
5
behaviour (UB).
6
7
This completes the conversion to tlb_lock. This conversion results
8
on average in no performance loss, as the following experiments
9
(run on an Intel i7-6700K CPU @ 4.00GHz) show.
10
11
1. aarch64 bootup+shutdown test:
12
13
- Before:
14
Performance counter stats for 'taskset -c 0 ../img/aarch64/die.sh' (10 runs):
15
16
7487.087786 task-clock (msec) # 0.998 CPUs utilized ( +- 0.12% )
17
31,574,905,303 cycles # 4.217 GHz ( +- 0.12% )
18
57,097,908,812 instructions # 1.81 insns per cycle ( +- 0.08% )
19
10,255,415,367 branches # 1369.747 M/sec ( +- 0.08% )
20
173,278,962 branch-misses # 1.69% of all branches ( +- 0.18% )
21
22
7.504481349 seconds time elapsed ( +- 0.14% )
23
24
- After:
25
Performance counter stats for 'taskset -c 0 ../img/aarch64/die.sh' (10 runs):
26
27
7462.441328 task-clock (msec) # 0.998 CPUs utilized ( +- 0.07% )
28
31,478,476,520 cycles # 4.218 GHz ( +- 0.07% )
29
57,017,330,084 instructions # 1.81 insns per cycle ( +- 0.05% )
30
10,251,929,667 branches # 1373.804 M/sec ( +- 0.05% )
31
173,023,787 branch-misses # 1.69% of all branches ( +- 0.11% )
32
33
7.474970463 seconds time elapsed ( +- 0.07% )
34
35
2. SPEC06int:
36
SPEC06int (test set)
37
[Y axis: Speedup over master]
38
1.15 +-+----+------+------+------+------+------+-------+------+------+------+------+------+------+----+-+
39
| |
40
1.1 +-+.................................+++.............................+ tlb-lock-v2 (m+++x) +-+
41
| +++ | +++ tlb-lock-v3 (spinl|ck) |
42
| +++ | | +++ +++ | | |
43
1.05 +-+....+++...........####.........|####.+++.|......|.....###....+++...........+++....###.........+-+
44
| ### ++#| # |# |# ***### +++### +++#+# | +++ | #|# ### |
45
1 +-+++***+#++++####+++#++#++++++++++#++#+*+*++#++++#+#+****+#++++###++++###++++###++++#+#++++#+#+++-+
46
| *+* # #++# *** # #### *** # * *++# ****+# *| * # ****|# |# # #|# #+# # # |
47
0.95 +-+..*.*.#....#..#.*|*..#...#..#.*|*..#.*.*..#.*|.*.#.*++*.#.*++*+#.****.#....#+#....#.#..++#.#..+-+
48
| * * # # # *|* # # # *|* # * * # *++* # * * # * * # * |* # ++# # # # *** # |
49
| * * # ++# # *+* # # # *|* # * * # * * # * * # * * # *++* # **** # ++# # * * # |
50
0.9 +-+..*.*.#...|#..#.*.*..#.++#..#.*|*..#.*.*..#.*..*.#.*..*.#.*..*.#.*..*.#.*.|*.#...|#.#..*.*.#..+-+
51
| * * # *** # * * # |# # *+* # * * # * * # * * # * * # * * # *++* # |# # * * # |
52
0.85 +-+..*.*.#..*|*..#.*.*..#.***..#.*.*..#.*.*..#.*..*.#.*..*.#.*..*.#.*..*.#.*..*.#.****.#..*.*.#..+-+
53
| * * # *+* # * * # *|* # * * # * * # * * # * * # * * # * * # * * # * |* # * * # |
54
| * * # * * # * * # *+* # * * # * * # * * # * * # * * # * * # * * # * |* # * * # |
55
0.8 +-+..*.*.#..*.*..#.*.*..#.*.*..#.*.*..#.*.*..#.*..*.#.*..*.#.*..*.#.*..*.#.*..*.#.*++*.#..*.*.#..+-+
56
| * * # * * # * * # * * # * * # * * # * * # * * # * * # * * # * * # * * # * * # |
57
0.75 +-+--***##--***###-***###-***###-***###-***###-****##-****##-****##-****##-****##-****##--***##--+-+
58
400.perlben401.bzip2403.gcc429.m445.gob456.hmme45462.libqua464.h26471.omnet473483.xalancbmkgeomean
59
60
png: https://imgur.com/a/BHzpPTW
61
62
Notes:
63
- tlb-lock-v2 corresponds to an implementation with a mutex.
64
- tlb-lock-v3 corresponds to the current implementation, i.e.
65
a spinlock and a single lock acquisition in tlb_set_page_with_attrs.
66
67
Signed-off-by: Emilio G. Cota <cota@braap.org>
68
Message-Id: <20181016153840.25877-1-cota@braap.org>
69
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
70
---
71
accel/tcg/softmmu_template.h | 12 ++++++------
72
include/exec/cpu_ldst.h | 11 ++++++++++-
73
include/exec/cpu_ldst_template.h | 2 +-
74
accel/tcg/cputlb.c | 19 +++++++++++++------
75
4 files changed, 30 insertions(+), 14 deletions(-)
76
77
diff --git a/accel/tcg/softmmu_template.h b/accel/tcg/softmmu_template.h
78
index XXXXXXX..XXXXXXX 100644
79
--- a/accel/tcg/softmmu_template.h
80
+++ b/accel/tcg/softmmu_template.h
81
@@ -XXX,XX +XXX,XX @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
82
uintptr_t mmu_idx = get_mmuidx(oi);
83
uintptr_t index = tlb_index(env, mmu_idx, addr);
84
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
85
- target_ulong tlb_addr = entry->addr_write;
86
+ target_ulong tlb_addr = tlb_addr_write(entry);
87
unsigned a_bits = get_alignment_bits(get_memop(oi));
88
uintptr_t haddr;
89
90
@@ -XXX,XX +XXX,XX @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
91
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE,
92
mmu_idx, retaddr);
93
}
94
- tlb_addr = entry->addr_write & ~TLB_INVALID_MASK;
95
+ tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK;
96
}
97
98
/* Handle an IO access. */
99
@@ -XXX,XX +XXX,XX @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
100
cannot evict the first. */
101
page2 = (addr + DATA_SIZE) & TARGET_PAGE_MASK;
102
entry2 = tlb_entry(env, mmu_idx, page2);
103
- if (!tlb_hit_page(entry2->addr_write, page2)
104
+ if (!tlb_hit_page(tlb_addr_write(entry2), page2)
105
&& !VICTIM_TLB_HIT(addr_write, page2)) {
106
tlb_fill(ENV_GET_CPU(env), page2, DATA_SIZE, MMU_DATA_STORE,
107
mmu_idx, retaddr);
108
@@ -XXX,XX +XXX,XX @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
109
uintptr_t mmu_idx = get_mmuidx(oi);
110
uintptr_t index = tlb_index(env, mmu_idx, addr);
111
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
112
- target_ulong tlb_addr = entry->addr_write;
113
+ target_ulong tlb_addr = tlb_addr_write(entry);
114
unsigned a_bits = get_alignment_bits(get_memop(oi));
115
uintptr_t haddr;
116
117
@@ -XXX,XX +XXX,XX @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
118
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE,
119
mmu_idx, retaddr);
120
}
121
- tlb_addr = entry->addr_write & ~TLB_INVALID_MASK;
122
+ tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK;
123
}
124
125
/* Handle an IO access. */
126
@@ -XXX,XX +XXX,XX @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
127
cannot evict the first. */
128
page2 = (addr + DATA_SIZE) & TARGET_PAGE_MASK;
129
entry2 = tlb_entry(env, mmu_idx, page2);
130
- if (!tlb_hit_page(entry2->addr_write, page2)
131
+ if (!tlb_hit_page(tlb_addr_write(entry2), page2)
132
&& !VICTIM_TLB_HIT(addr_write, page2)) {
133
tlb_fill(ENV_GET_CPU(env), page2, DATA_SIZE, MMU_DATA_STORE,
134
mmu_idx, retaddr);
135
diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
136
index XXXXXXX..XXXXXXX 100644
137
--- a/include/exec/cpu_ldst.h
138
+++ b/include/exec/cpu_ldst.h
139
@@ -XXX,XX +XXX,XX @@ extern __thread uintptr_t helper_retaddr;
140
/* The memory helpers for tcg-generated code need tcg_target_long etc. */
141
#include "tcg.h"
142
143
+static inline target_ulong tlb_addr_write(const CPUTLBEntry *entry)
144
+{
145
+#if TCG_OVERSIZED_GUEST
146
+ return entry->addr_write;
147
+#else
148
+ return atomic_read(&entry->addr_write);
149
+#endif
150
+}
151
+
152
/* Find the TLB index corresponding to the mmu_idx + address pair. */
153
static inline uintptr_t tlb_index(CPUArchState *env, uintptr_t mmu_idx,
154
target_ulong addr)
155
@@ -XXX,XX +XXX,XX @@ static inline void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
156
tlb_addr = tlbentry->addr_read;
157
break;
158
case 1:
159
- tlb_addr = tlbentry->addr_write;
160
+ tlb_addr = tlb_addr_write(tlbentry);
161
break;
162
case 2:
163
tlb_addr = tlbentry->addr_code;
164
diff --git a/include/exec/cpu_ldst_template.h b/include/exec/cpu_ldst_template.h
165
index XXXXXXX..XXXXXXX 100644
166
--- a/include/exec/cpu_ldst_template.h
167
+++ b/include/exec/cpu_ldst_template.h
168
@@ -XXX,XX +XXX,XX @@ glue(glue(glue(cpu_st, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
169
addr = ptr;
170
mmu_idx = CPU_MMU_INDEX;
171
entry = tlb_entry(env, mmu_idx, addr);
172
- if (unlikely(entry->addr_write !=
173
+ if (unlikely(tlb_addr_write(entry) !=
174
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
175
oi = make_memop_idx(SHIFT, mmu_idx);
176
glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)(env, addr, v, oi,
177
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
178
index XXXXXXX..XXXXXXX 100644
179
--- a/accel/tcg/cputlb.c
180
+++ b/accel/tcg/cputlb.c
181
@@ -XXX,XX +XXX,XX @@ static inline bool tlb_hit_page_anyprot(CPUTLBEntry *tlb_entry,
182
target_ulong page)
183
{
184
return tlb_hit_page(tlb_entry->addr_read, page) ||
185
- tlb_hit_page(tlb_entry->addr_write, page) ||
186
+ tlb_hit_page(tlb_addr_write(tlb_entry), page) ||
187
tlb_hit_page(tlb_entry->addr_code, page);
188
}
189
190
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
191
tlb_fill(cpu, addr, size, MMU_DATA_STORE, mmu_idx, retaddr);
192
193
entry = tlb_entry(env, mmu_idx, addr);
194
- tlb_addr = entry->addr_write;
195
+ tlb_addr = tlb_addr_write(entry);
196
if (!(tlb_addr & ~(TARGET_PAGE_MASK | TLB_RECHECK))) {
197
/* RAM access */
198
uintptr_t haddr = addr + entry->addend;
199
@@ -XXX,XX +XXX,XX @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
200
assert_cpu_is_self(ENV_GET_CPU(env));
201
for (vidx = 0; vidx < CPU_VTLB_SIZE; ++vidx) {
202
CPUTLBEntry *vtlb = &env->tlb_v_table[mmu_idx][vidx];
203
- target_ulong cmp = *(target_ulong *)((uintptr_t)vtlb + elt_ofs);
204
+ target_ulong cmp;
205
+
206
+ /* elt_ofs might correspond to .addr_write, so use atomic_read */
207
+#if TCG_OVERSIZED_GUEST
208
+ cmp = *(target_ulong *)((uintptr_t)vtlb + elt_ofs);
209
+#else
210
+ cmp = atomic_read((target_ulong *)((uintptr_t)vtlb + elt_ofs));
211
+#endif
212
213
if (cmp == page) {
214
/* Found entry in victim tlb, swap tlb and iotlb. */
215
@@ -XXX,XX +XXX,XX @@ void probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx,
216
uintptr_t index = tlb_index(env, mmu_idx, addr);
217
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
218
219
- if (!tlb_hit(entry->addr_write, addr)) {
220
+ if (!tlb_hit(tlb_addr_write(entry), addr)) {
221
/* TLB entry is for a different page */
222
if (!VICTIM_TLB_HIT(addr_write, addr)) {
223
tlb_fill(ENV_GET_CPU(env), addr, size, MMU_DATA_STORE,
224
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
225
size_t mmu_idx = get_mmuidx(oi);
226
uintptr_t index = tlb_index(env, mmu_idx, addr);
227
CPUTLBEntry *tlbe = tlb_entry(env, mmu_idx, addr);
228
- target_ulong tlb_addr = tlbe->addr_write;
229
+ target_ulong tlb_addr = tlb_addr_write(tlbe);
230
TCGMemOp mop = get_memop(oi);
231
int a_bits = get_alignment_bits(mop);
232
int s_bits = mop & MO_SIZE;
233
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
234
tlb_fill(ENV_GET_CPU(env), addr, 1 << s_bits, MMU_DATA_STORE,
235
mmu_idx, retaddr);
236
}
237
- tlb_addr = tlbe->addr_write & ~TLB_INVALID_MASK;
238
+ tlb_addr = tlb_addr_write(tlbe) & ~TLB_INVALID_MASK;
239
}
240
241
/* Notice an IO access or a needs-MMU-lookup access */
242
--
243
2.17.2
244
245
diff view generated by jsdifflib