1
The following changes since commit e750a7ace492f0b450653d4ad368a77d6f660fb8:
1
The following changes since commit aa33508196f4e2da04625bee36e1f7be5b9267e7:
2
2
3
Merge tag 'pull-9p-20221024' of https://github.com/cschoenebeck/qemu into staging (2022-10-24 14:27:12 -0400)
3
Merge tag 'mem-2023-05-23' of https://github.com/davidhildenbrand/qemu into staging (2023-05-23 10:57:25 -0700)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20221026
7
https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20230523
8
8
9
for you to fetch changes up to 04f105758b0089f73ee47260671580cde35f96cc:
9
for you to fetch changes up to 30d56836f98c7ed2d309bff1dde8854f3d0b5634:
10
10
11
accel/tcg: Remove restore_state_to_opc function (2022-10-26 11:11:28 +1000)
11
tcg: Remove USE_TCG_OPTIMIZATIONS (2023-05-23 16:52:39 -0700)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Revert incorrect cflags initialization.
14
util: Host cpu detection for x86 and aa64
15
Add direct jumps for tcg/loongarch64.
15
util: Use cpu detection for bufferiszero
16
Speed up breakpoint check.
16
migration: Use cpu detection for xbzrle
17
Improve assertions for atomic.h.
17
tcg: Replace and remove cpu_atomic_{ld,st}o*
18
Move restore_state_to_opc to TCGCPUOps.
18
host/include: Split qemu/atomic128.h
19
Cleanups to TranslationBlock maintenance.
19
tcg: Remove DEBUG_DISAS
20
tcg: Remove USE_TCG_OPTIMIZATIONS
20
21
21
----------------------------------------------------------------
22
----------------------------------------------------------------
22
Leandro Lupori (1):
23
Richard Henderson (28):
23
accel/tcg: Add a quicker check for breakpoints
24
util: Introduce host-specific cpuinfo.h
25
util: Add cpuinfo-i386.c
26
util: Add i386 CPUINFO_ATOMIC_VMOVDQU
27
tcg/i386: Use host/cpuinfo.h
28
util/bufferiszero: Use i386 host/cpuinfo.h
29
migration/xbzrle: Shuffle function order
30
migration/xbzrle: Use i386 host/cpuinfo.h
31
migration: Build migration_files once
32
util: Add cpuinfo-aarch64.c
33
include/host: Split out atomic128-cas.h
34
include/host: Split out atomic128-ldst.h
35
meson: Fix detect atomic128 support with optimization
36
include/qemu: Move CONFIG_ATOMIC128_OPT handling to atomic128.h
37
target/ppc: Use tcg_gen_qemu_{ld,st}_i128 for LQARX, LQ, STQ
38
target/s390x: Use tcg_gen_qemu_{ld,st}_i128 for LPQ, STPQ
39
accel/tcg: Unify cpu_{ld,st}*_{be,le}_mmu
40
target/s390x: Use cpu_{ld,st}*_mmu in do_csst
41
target/s390x: Always use cpu_atomic_cmpxchgl_be_mmu in do_csst
42
accel/tcg: Remove cpu_atomic_{ld,st}o_*_mmu
43
accel/tcg: Remove prot argument to atomic_mmu_lookup
44
accel/tcg: Eliminate #if on HAVE_ATOMIC128 and HAVE_CMPXCHG128
45
qemu/atomic128: Split atomic16_read
46
accel/tcg: Correctly use atomic128.h in ldst_atomicity.c.inc
47
tcg: Split out tcg/debug-assert.h
48
qemu/atomic128: Improve cmpxchg fallback for atomic16_set
49
qemu/atomic128: Add runtime test for FEAT_LSE2
50
tcg: Remove DEBUG_DISAS
51
tcg: Remove USE_TCG_OPTIMIZATIONS
24
52
25
Peter Maydell (1):
53
accel/tcg/atomic_template.h | 93 +-----
26
Revert "accel/tcg: Init TCG cflags in vCPU thread handler"
54
host/include/aarch64/host/atomic128-cas.h | 45 +++
27
55
host/include/aarch64/host/atomic128-ldst.h | 79 +++++
28
Qi Hu (2):
56
host/include/aarch64/host/cpuinfo.h | 22 ++
29
tcg/loongarch64: Add direct jump support
57
host/include/generic/host/atomic128-cas.h | 47 +++
30
tcg/aarch64: Remove unused code in tcg_out_op
58
host/include/generic/host/atomic128-ldst.h | 81 +++++
31
59
host/include/generic/host/cpuinfo.h | 4 +
32
Richard Henderson (43):
60
host/include/i386/host/cpuinfo.h | 39 +++
33
include/qemu/osdep: Add qemu_build_assert
61
host/include/x86_64/host/cpuinfo.h | 1 +
34
include/qemu/atomic: Use qemu_build_assert
62
include/exec/cpu_ldst.h | 67 +----
35
include/qemu/thread: Use qatomic_* functions
63
include/exec/exec-all.h | 3 -
36
accel/tcg: Make page_alloc_target_data allocation constant
64
include/qemu/atomic128.h | 146 ++-------
37
accel/tcg: Remove disabled debug in translate-all.c
65
include/tcg/debug-assert.h | 17 ++
38
accel/tcg: Split out PageDesc to internal.h
66
include/tcg/tcg.h | 9 +-
39
accel/tcg: Split out tb-maint.c
67
migration/xbzrle.h | 5 +-
40
accel/tcg: Move assert_no_pages_locked to internal.h
68
target/ppc/cpu.h | 1 -
41
accel/tcg: Drop cpu_get_tb_cpu_state from TARGET_HAS_PRECISE_SMC
69
target/ppc/helper.h | 9 -
42
accel/tcg: Remove duplicate store to tb->page_addr[]
70
target/s390x/cpu.h | 3 -
43
accel/tcg: Introduce tb_{set_}page_addr{0,1}
71
target/s390x/helper.h | 4 -
44
accel/tcg: Rename tb_invalidate_phys_page
72
tcg/aarch64/tcg-target.h | 6 +-
45
accel/tcg: Rename tb_invalidate_phys_page_range and drop end parameter
73
tcg/i386/tcg-target.h | 28 +-
46
accel/tcg: Unify declarations of tb_invalidate_phys_range
74
accel/tcg/cpu-exec.c | 2 -
47
accel/tcg: Use tb_invalidate_phys_page in page_set_flags
75
accel/tcg/cputlb.c | 211 ++++---------
48
accel/tcg: Call tb_invalidate_phys_page for PAGE_RESET
76
accel/tcg/translate-all.c | 2 -
49
accel/tcg: Use page_reset_target_data in page_set_flags
77
accel/tcg/translator.c | 2 -
50
accel/tcg: Use tb_invalidate_phys_range in page_set_flags
78
accel/tcg/user-exec.c | 332 ++++++--------------
51
accel/tcg: Move TARGET_PAGE_DATA_SIZE impl to user-exec.c
79
migration/ram.c | 34 +--
52
accel/tcg: Simplify page_get/alloc_target_data
80
migration/xbzrle.c | 268 +++++++++--------
53
accel/tcg: Add restore_state_to_opc to TCGCPUOps
81
target/arm/tcg/m_helper.c | 4 +-
54
target/alpha: Convert to tcg_ops restore_state_to_opc
82
target/ppc/mem_helper.c | 48 ---
55
target/arm: Convert to tcg_ops restore_state_to_opc
83
target/ppc/translate.c | 34 +--
56
target/avr: Convert to tcg_ops restore_state_to_opc
84
target/s390x/tcg/mem_helper.c | 137 ++-------
57
target/cris: Convert to tcg_ops restore_state_to_opc
85
target/s390x/tcg/translate.c | 30 +-
58
target/hexagon: Convert to tcg_ops restore_state_to_opc
86
target/sh4/translate.c | 2 -
59
target/hppa: Convert to tcg_ops restore_state_to_opc
87
target/sparc/ldst_helper.c | 18 +-
60
target/i386: Convert to tcg_ops restore_state_to_opc
88
target/sparc/translate.c | 2 -
61
target/loongarch: Convert to tcg_ops restore_state_to_opc
89
tcg/tcg.c | 14 +-
62
target/m68k: Convert to tcg_ops restore_state_to_opc
90
tests/bench/xbzrle-bench.c | 469 -----------------------------
63
target/microblaze: Convert to tcg_ops restore_state_to_opc
91
tests/unit/test-xbzrle.c | 49 +--
64
target/mips: Convert to tcg_ops restore_state_to_opc
92
util/bufferiszero.c | 127 +++-----
65
target/nios2: Convert to tcg_ops restore_state_to_opc
93
util/cpuinfo-aarch64.c | 67 +++++
66
target/openrisc: Convert to tcg_ops restore_state_to_opc
94
util/cpuinfo-i386.c | 99 ++++++
67
target/ppc: Convert to tcg_ops restore_state_to_opc
95
MAINTAINERS | 3 +
68
target/riscv: Convert to tcg_ops restore_state_to_opc
96
accel/tcg/atomic_common.c.inc | 14 -
69
target/rx: Convert to tcg_ops restore_state_to_opc
97
accel/tcg/ldst_atomicity.c.inc | 135 ++-------
70
target/s390x: Convert to tcg_ops restore_state_to_opc
98
accel/tcg/ldst_common.c.inc | 24 +-
71
target/sh4: Convert to tcg_ops restore_state_to_opc
99
meson.build | 12 +-
72
target/sparc: Convert to tcg_ops restore_state_to_opc
100
migration/meson.build | 1 -
73
target/tricore: Convert to tcg_ops restore_state_to_opc
101
target/ppc/translate/fixedpoint-impl.c.inc | 51 +---
74
target/xtensa: Convert to tcg_ops restore_state_to_opc
102
target/s390x/tcg/insn-data.h.inc | 2 +-
75
accel/tcg: Remove restore_state_to_opc function
103
tcg/aarch64/tcg-target.c.inc | 40 ---
76
104
tcg/i386/tcg-target.c.inc | 123 +-------
77
accel/tcg/internal.h | 91 ++++
105
tests/bench/meson.build | 6 -
78
include/exec/cpu-all.h | 22 +-
106
util/meson.build | 6 +
79
include/exec/exec-all.h | 35 +-
107
54 files changed, 1035 insertions(+), 2042 deletions(-)
80
include/exec/ram_addr.h | 2 -
108
create mode 100644 host/include/aarch64/host/atomic128-cas.h
81
include/exec/translate-all.h | 2 +-
109
create mode 100644 host/include/aarch64/host/atomic128-ldst.h
82
include/hw/core/tcg-cpu-ops.h | 11 +
110
create mode 100644 host/include/aarch64/host/cpuinfo.h
83
include/qemu/atomic.h | 16 +-
111
create mode 100644 host/include/generic/host/atomic128-cas.h
84
include/qemu/osdep.h | 8 +
112
create mode 100644 host/include/generic/host/atomic128-ldst.h
85
include/qemu/thread.h | 8 +-
113
create mode 100644 host/include/generic/host/cpuinfo.h
86
target/arm/cpu.h | 8 +
114
create mode 100644 host/include/i386/host/cpuinfo.h
87
target/arm/internals.h | 4 -
115
create mode 100644 host/include/x86_64/host/cpuinfo.h
88
target/mips/tcg/tcg-internal.h | 3 +
116
create mode 100644 include/tcg/debug-assert.h
89
target/s390x/s390x-internal.h | 4 +-
117
delete mode 100644 tests/bench/xbzrle-bench.c
90
target/sparc/cpu.h | 3 +
118
create mode 100644 util/cpuinfo-aarch64.c
91
tcg/loongarch64/tcg-target.h | 9 +-
119
create mode 100644 util/cpuinfo-i386.c
92
accel/tcg/cpu-exec.c | 24 +-
93
accel/tcg/tb-maint.c | 704 ++++++++++++++++++++++++++
94
accel/tcg/tcg-accel-ops-mttcg.c | 5 +-
95
accel/tcg/tcg-accel-ops-rr.c | 7 +-
96
accel/tcg/translate-all.c | 1017 ++------------------------------------
97
accel/tcg/translator.c | 9 +-
98
accel/tcg/user-exec.c | 42 ++
99
bsd-user/mmap.c | 2 -
100
cpu.c | 4 +-
101
linux-user/mmap.c | 4 -
102
target/alpha/cpu.c | 9 +
103
target/alpha/translate.c | 6 -
104
target/arm/cpu.c | 26 +
105
target/arm/mte_helper.c | 5 -
106
target/arm/translate.c | 22 -
107
target/avr/cpu.c | 11 +
108
target/avr/translate.c | 6 -
109
target/cris/cpu.c | 11 +
110
target/cris/translate.c | 6 -
111
target/hexagon/cpu.c | 9 +-
112
target/hppa/cpu.c | 19 +
113
target/hppa/translate.c | 13 -
114
target/i386/tcg/tcg-cpu.c | 19 +
115
target/i386/tcg/translate.c | 15 -
116
target/loongarch/cpu.c | 11 +
117
target/loongarch/translate.c | 6 -
118
target/m68k/cpu.c | 14 +
119
target/m68k/translate.c | 10 -
120
target/microblaze/cpu.c | 11 +
121
target/microblaze/translate.c | 7 -
122
target/mips/cpu.c | 1 +
123
target/mips/tcg/translate.c | 8 +-
124
target/nios2/cpu.c | 11 +
125
target/nios2/translate.c | 6 -
126
target/openrisc/cpu.c | 13 +
127
target/openrisc/translate.c | 10 -
128
target/ppc/cpu_init.c | 10 +
129
target/ppc/translate.c | 6 -
130
target/riscv/cpu.c | 9 +-
131
target/rx/cpu.c | 10 +
132
target/rx/translate.c | 6 -
133
target/s390x/cpu.c | 1 +
134
target/s390x/tcg/translate.c | 7 +-
135
target/sh4/cpu.c | 16 +
136
target/sh4/translate.c | 10 -
137
target/sparc/cpu.c | 1 +
138
target/sparc/translate.c | 7 +-
139
target/tricore/cpu.c | 11 +
140
target/tricore/translate.c | 6 -
141
target/xtensa/cpu.c | 10 +
142
target/xtensa/translate.c | 6 -
143
tcg/aarch64/tcg-target.c.inc | 31 +-
144
tcg/loongarch64/tcg-target.c.inc | 48 +-
145
accel/tcg/meson.build | 1 +
146
69 files changed, 1304 insertions(+), 1221 deletions(-)
147
create mode 100644 accel/tcg/tb-maint.c
diff view generated by jsdifflib
Deleted patch
1
From: Peter Maydell <peter.maydell@linaro.org>
2
1
3
Commit a82fd5a4ec24d was intended to be a code cleanup, but
4
unfortunately it has a bug. It moves the initialization of the
5
TCG cflags from the "start a new vcpu" function to the
6
thread handler; this is fine when each vcpu has its own thread,
7
but when we are doing round-robin of vcpus on a single thread
8
we end up only initializing the cflags for CPU 0, not for any
9
of the others.
10
11
The most obvious effect of this bug is that running in icount
12
mode with more than one CPU is broken; typically the guest
13
hangs shortly after it brings up the secondary CPUs.
14
15
This reverts commit a82fd5a4ec24d923ff1e6da128c0fd4a74079d99.
16
17
Cc: qemu-stable@nongnu.org
18
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Message-Id: <20221021163409.3674911-1-peter.maydell@linaro.org>
22
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
23
---
24
accel/tcg/tcg-accel-ops-mttcg.c | 5 +++--
25
accel/tcg/tcg-accel-ops-rr.c | 7 ++++---
26
2 files changed, 7 insertions(+), 5 deletions(-)
27
28
diff --git a/accel/tcg/tcg-accel-ops-mttcg.c b/accel/tcg/tcg-accel-ops-mttcg.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/accel/tcg/tcg-accel-ops-mttcg.c
31
+++ b/accel/tcg/tcg-accel-ops-mttcg.c
32
@@ -XXX,XX +XXX,XX @@ static void *mttcg_cpu_thread_fn(void *arg)
33
assert(tcg_enabled());
34
g_assert(!icount_enabled());
35
36
- tcg_cpu_init_cflags(cpu, current_machine->smp.max_cpus > 1);
37
-
38
rcu_register_thread();
39
force_rcu.notifier.notify = mttcg_force_rcu;
40
force_rcu.cpu = cpu;
41
@@ -XXX,XX +XXX,XX @@ void mttcg_start_vcpu_thread(CPUState *cpu)
42
{
43
char thread_name[VCPU_THREAD_NAME_SIZE];
44
45
+ g_assert(tcg_enabled());
46
+ tcg_cpu_init_cflags(cpu, current_machine->smp.max_cpus > 1);
47
+
48
cpu->thread = g_new0(QemuThread, 1);
49
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
50
qemu_cond_init(cpu->halt_cond);
51
diff --git a/accel/tcg/tcg-accel-ops-rr.c b/accel/tcg/tcg-accel-ops-rr.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/accel/tcg/tcg-accel-ops-rr.c
54
+++ b/accel/tcg/tcg-accel-ops-rr.c
55
@@ -XXX,XX +XXX,XX @@ static void *rr_cpu_thread_fn(void *arg)
56
Notifier force_rcu;
57
CPUState *cpu = arg;
58
59
- g_assert(tcg_enabled());
60
- tcg_cpu_init_cflags(cpu, false);
61
-
62
+ assert(tcg_enabled());
63
rcu_register_thread();
64
force_rcu.notify = rr_force_rcu;
65
rcu_add_force_rcu_notifier(&force_rcu);
66
@@ -XXX,XX +XXX,XX @@ void rr_start_vcpu_thread(CPUState *cpu)
67
static QemuCond *single_tcg_halt_cond;
68
static QemuThread *single_tcg_cpu_thread;
69
70
+ g_assert(tcg_enabled());
71
+ tcg_cpu_init_cflags(cpu, false);
72
+
73
if (!single_tcg_cpu_thread) {
74
cpu->thread = g_new0(QemuThread, 1);
75
cpu->halt_cond = g_new0(QemuCond, 1);
76
--
77
2.34.1
78
79
diff view generated by jsdifflib
Deleted patch
1
From: Qi Hu <huqi@loongson.cn>
2
1
3
Similar to the ARM64, LoongArch has PC-relative instructions such as
4
PCADDU18I. These instructions can be used to support direct jump for
5
LoongArch. Additionally, if instruction "B offset" can cover the target
6
address(target is within ±128MB range), a single "B offset" plus a nop
7
will be used by "tb_target_set_jump_target".
8
9
Signed-off-by: Qi Hu <huqi@loongson.cn>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: WANG Xuerui <git@xen0n.name>
12
Message-Id: <20221015092754.91971-1-huqi@loongson.cn>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
---
15
tcg/loongarch64/tcg-target.h | 9 ++++--
16
tcg/loongarch64/tcg-target.c.inc | 48 +++++++++++++++++++++++++++++---
17
2 files changed, 50 insertions(+), 7 deletions(-)
18
19
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/tcg/loongarch64/tcg-target.h
22
+++ b/tcg/loongarch64/tcg-target.h
23
@@ -XXX,XX +XXX,XX @@
24
25
#define TCG_TARGET_INSN_UNIT_SIZE 4
26
#define TCG_TARGET_NB_REGS 32
27
-#define MAX_CODE_GEN_BUFFER_SIZE SIZE_MAX
28
+/*
29
+ * PCADDU18I + JIRL sequence can give 20 + 16 + 2 = 38 bits
30
+ * signed offset, which is +/- 128 GiB.
31
+ */
32
+#define MAX_CODE_GEN_BUFFER_SIZE (128 * GiB)
33
34
typedef enum {
35
TCG_REG_ZERO,
36
@@ -XXX,XX +XXX,XX @@ typedef enum {
37
#define TCG_TARGET_HAS_clz_i32 1
38
#define TCG_TARGET_HAS_ctz_i32 1
39
#define TCG_TARGET_HAS_ctpop_i32 0
40
-#define TCG_TARGET_HAS_direct_jump 0
41
+#define TCG_TARGET_HAS_direct_jump 1
42
#define TCG_TARGET_HAS_brcond2 0
43
#define TCG_TARGET_HAS_setcond2 0
44
#define TCG_TARGET_HAS_qemu_st8_i32 0
45
@@ -XXX,XX +XXX,XX @@ typedef enum {
46
#define TCG_TARGET_HAS_muluh_i64 1
47
#define TCG_TARGET_HAS_mulsh_i64 1
48
49
-/* not defined -- call should be eliminated at compile time */
50
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
51
52
#define TCG_TARGET_DEFAULT_MO (0)
53
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
54
index XXXXXXX..XXXXXXX 100644
55
--- a/tcg/loongarch64/tcg-target.c.inc
56
+++ b/tcg/loongarch64/tcg-target.c.inc
57
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args)
58
#endif
59
}
60
61
+/* LoongArch uses `andi zero, zero, 0` as NOP. */
62
+#define NOP OPC_ANDI
63
+static void tcg_out_nop(TCGContext *s)
64
+{
65
+ tcg_out32(s, NOP);
66
+}
67
+
68
+void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
69
+ uintptr_t jmp_rw, uintptr_t addr)
70
+{
71
+ tcg_insn_unit i1, i2;
72
+ ptrdiff_t upper, lower;
73
+ ptrdiff_t offset = (ptrdiff_t)(addr - jmp_rx) >> 2;
74
+
75
+ if (offset == sextreg(offset, 0, 26)) {
76
+ i1 = encode_sd10k16_insn(OPC_B, offset);
77
+ i2 = NOP;
78
+ } else {
79
+ tcg_debug_assert(offset == sextreg(offset, 0, 36));
80
+ lower = (int16_t)offset;
81
+ upper = (offset - lower) >> 16;
82
+
83
+ i1 = encode_dsj20_insn(OPC_PCADDU18I, TCG_REG_TMP0, upper);
84
+ i2 = encode_djsk16_insn(OPC_JIRL, TCG_REG_ZERO, TCG_REG_TMP0, lower);
85
+ }
86
+ uint64_t pair = ((uint64_t)i2 << 32) | i1;
87
+ qatomic_set((uint64_t *)jmp_rw, pair);
88
+ flush_idcache_range(jmp_rx, jmp_rw, 8);
89
+}
90
+
91
/*
92
* Entry-points
93
*/
94
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
95
break;
96
97
case INDEX_op_goto_tb:
98
- assert(s->tb_jmp_insn_offset == 0);
99
- /* indirect jump method */
100
- tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO,
101
- (uintptr_t)(s->tb_jmp_target_addr + a0));
102
+ tcg_debug_assert(s->tb_jmp_insn_offset != NULL);
103
+ /*
104
+ * Ensure that patch area is 8-byte aligned so that an
105
+ * atomic write can be used to patch the target address.
106
+ */
107
+ if ((uintptr_t)s->code_ptr & 7) {
108
+ tcg_out_nop(s);
109
+ }
110
+ s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
111
+ /*
112
+ * actual branch destination will be patched by
113
+ * tb_target_set_jmp_target later
114
+ */
115
+ tcg_out_opc_pcaddu18i(s, TCG_REG_TMP0, 0);
116
tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_TMP0, 0);
117
set_jmp_reset_offset(s, a0);
118
break;
119
--
120
2.34.1
121
122
diff view generated by jsdifflib
Deleted patch
1
From: Qi Hu <huqi@loongson.cn>
2
1
3
AArch64 defines the TCG_TARGET_HAS_direct_jump. So the "else" block is
4
useless in the case of "INDEX_op_goto_tb" in function "tcg_out_op". Add
5
an assertion and delete these codes for clarity.
6
7
Suggested-by: WANG Xuerui <git@xen0n.name>
8
Signed-off-by: Qi Hu <huqi@loongson.cn>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-Id: <20221017020826.990729-1-huqi@loongson.cn>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
---
14
tcg/aarch64/tcg-target.c.inc | 31 ++++++++++++++-----------------
15
1 file changed, 14 insertions(+), 17 deletions(-)
16
17
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
18
index XXXXXXX..XXXXXXX 100644
19
--- a/tcg/aarch64/tcg-target.c.inc
20
+++ b/tcg/aarch64/tcg-target.c.inc
21
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
22
break;
23
24
case INDEX_op_goto_tb:
25
- if (s->tb_jmp_insn_offset != NULL) {
26
- /* TCG_TARGET_HAS_direct_jump */
27
- /* Ensure that ADRP+ADD are 8-byte aligned so that an atomic
28
- write can be used to patch the target address. */
29
- if ((uintptr_t)s->code_ptr & 7) {
30
- tcg_out32(s, NOP);
31
- }
32
- s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
33
- /* actual branch destination will be patched by
34
- tb_target_set_jmp_target later. */
35
- tcg_out_insn(s, 3406, ADRP, TCG_REG_TMP, 0);
36
- tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_TMP, TCG_REG_TMP, 0);
37
- } else {
38
- /* !TCG_TARGET_HAS_direct_jump */
39
- tcg_debug_assert(s->tb_jmp_target_addr != NULL);
40
- intptr_t offset = tcg_pcrel_diff(s, (s->tb_jmp_target_addr + a0)) >> 2;
41
- tcg_out_insn(s, 3305, LDR, offset, TCG_REG_TMP);
42
+ tcg_debug_assert(s->tb_jmp_insn_offset != NULL);
43
+ /*
44
+ * Ensure that ADRP+ADD are 8-byte aligned so that an atomic
45
+ * write can be used to patch the target address.
46
+ */
47
+ if ((uintptr_t)s->code_ptr & 7) {
48
+ tcg_out32(s, NOP);
49
}
50
+ s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
51
+ /*
52
+ * actual branch destination will be patched by
53
+ * tb_target_set_jmp_target later
54
+ */
55
+ tcg_out_insn(s, 3406, ADRP, TCG_REG_TMP, 0);
56
+ tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_TMP, TCG_REG_TMP, 0);
57
tcg_out_insn(s, 3207, BR, TCG_REG_TMP);
58
set_jmp_reset_offset(s, a0);
59
break;
60
--
61
2.34.1
62
63
diff view generated by jsdifflib
Deleted patch
1
From: Leandro Lupori <leandro.lupori@eldorado.org.br>
2
1
3
Profiling QEMU during Fedora 35 for PPC64 boot revealed that a
4
considerable amount of time was being spent in
5
check_for_breakpoints() (0.61% of total time on PPC64 and 2.19% on
6
amd64), even though it was just checking that its queue was empty
7
and returning, when no breakpoints were set. It turns out this
8
function is not inlined by the compiler and it's always called by
9
helper_lookup_tb_ptr(), one of the most called functions.
10
11
By leaving only the check for empty queue in
12
check_for_breakpoints() and moving the remaining code to
13
check_for_breakpoints_slow(), called only when the queue is not
14
empty, it's possible to avoid the call overhead. An improvement of
15
about 3% in total time was measured on POWER9.
16
17
Signed-off-by: Leandro Lupori <leandro.lupori@eldorado.org.br>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-Id: <20221025202424.195984-2-leandro.lupori@eldorado.org.br>
20
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
21
---
22
accel/tcg/cpu-exec.c | 15 +++++++++------
23
1 file changed, 9 insertions(+), 6 deletions(-)
24
25
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/accel/tcg/cpu-exec.c
28
+++ b/accel/tcg/cpu-exec.c
29
@@ -XXX,XX +XXX,XX @@ static void log_cpu_exec(target_ulong pc, CPUState *cpu,
30
}
31
}
32
33
-static bool check_for_breakpoints(CPUState *cpu, target_ulong pc,
34
- uint32_t *cflags)
35
+static bool check_for_breakpoints_slow(CPUState *cpu, target_ulong pc,
36
+ uint32_t *cflags)
37
{
38
CPUBreakpoint *bp;
39
bool match_page = false;
40
41
- if (likely(QTAILQ_EMPTY(&cpu->breakpoints))) {
42
- return false;
43
- }
44
-
45
/*
46
* Singlestep overrides breakpoints.
47
* This requirement is visible in the record-replay tests, where
48
@@ -XXX,XX +XXX,XX @@ static bool check_for_breakpoints(CPUState *cpu, target_ulong pc,
49
return false;
50
}
51
52
+static inline bool check_for_breakpoints(CPUState *cpu, target_ulong pc,
53
+ uint32_t *cflags)
54
+{
55
+ return unlikely(!QTAILQ_EMPTY(&cpu->breakpoints)) &&
56
+ check_for_breakpoints_slow(cpu, pc, cflags);
57
+}
58
+
59
/**
60
* helper_lookup_tb_ptr: quick check for next tb
61
* @env: current cpu state
62
--
63
2.34.1
diff view generated by jsdifflib
1
The entire contents of the header is host-specific, but the
2
existence of such a header is not, which could prevent some
3
host specific ifdefs at the top of the file for the include.
4
5
Add host/include/{arch,generic} to the project arguments.
6
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Reviewed-by: Juan Quintela <quintela@redhat.com>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
11
---
4
target/xtensa/cpu.c | 10 ++++++++++
12
host/include/generic/host/cpuinfo.h | 4 ++++
5
target/xtensa/translate.c | 6 ------
13
meson.build | 10 ++++++++++
6
2 files changed, 10 insertions(+), 6 deletions(-)
14
2 files changed, 14 insertions(+)
15
create mode 100644 host/include/generic/host/cpuinfo.h
7
16
8
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
17
diff --git a/host/include/generic/host/cpuinfo.h b/host/include/generic/host/cpuinfo.h
18
new file mode 100644
19
index XXXXXXX..XXXXXXX
20
--- /dev/null
21
+++ b/host/include/generic/host/cpuinfo.h
22
@@ -XXX,XX +XXX,XX @@
23
+/*
24
+ * No host specific cpu indentification.
25
+ * SPDX-License-Identifier: GPL-2.0-or-later
26
+ */
27
diff --git a/meson.build b/meson.build
9
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
10
--- a/target/xtensa/cpu.c
29
--- a/meson.build
11
+++ b/target/xtensa/cpu.c
30
+++ b/meson.build
12
@@ -XXX,XX +XXX,XX @@ static vaddr xtensa_cpu_get_pc(CPUState *cs)
31
@@ -XXX,XX +XXX,XX @@ add_project_arguments('-iquote', '.',
13
return cpu->env.pc;
32
'-iquote', meson.current_source_dir() / 'include',
14
}
33
language: all_languages)
15
34
16
+static void xtensa_restore_state_to_opc(CPUState *cs,
35
+# If a host-specific include directory exists, list that first...
17
+ const TranslationBlock *tb,
36
+host_include = meson.current_source_dir() / 'host/include/'
18
+ const uint64_t *data)
37
+if fs.is_dir(host_include / host_arch)
19
+{
38
+ add_project_arguments('-iquote', host_include / host_arch,
20
+ XtensaCPU *cpu = XTENSA_CPU(cs);
39
+ language: all_languages)
40
+endif
41
+# ... followed by the generic fallback.
42
+add_project_arguments('-iquote', host_include / 'generic',
43
+ language: all_languages)
21
+
44
+
22
+ cpu->env.pc = data[0];
45
sparse = find_program('cgcc', required: get_option('sparse'))
23
+}
46
if sparse.found()
24
+
47
run_target('sparse',
25
static bool xtensa_cpu_has_work(CPUState *cs)
26
{
27
#ifndef CONFIG_USER_ONLY
28
@@ -XXX,XX +XXX,XX @@ static const struct SysemuCPUOps xtensa_sysemu_ops = {
29
static const struct TCGCPUOps xtensa_tcg_ops = {
30
.initialize = xtensa_translate_init,
31
.debug_excp_handler = xtensa_breakpoint_handler,
32
+ .restore_state_to_opc = xtensa_restore_state_to_opc,
33
34
#ifndef CONFIG_USER_ONLY
35
.tlb_fill = xtensa_cpu_tlb_fill,
36
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/xtensa/translate.c
39
+++ b/target/xtensa/translate.c
40
@@ -XXX,XX +XXX,XX @@ void xtensa_cpu_dump_state(CPUState *cs, FILE *f, int flags)
41
}
42
}
43
44
-void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb,
45
- target_ulong *data)
46
-{
47
- env->pc = data[0];
48
-}
49
-
50
static void translate_abs(DisasContext *dc, const OpcodeArg arg[],
51
const uint32_t par[])
52
{
53
--
48
--
54
2.34.1
49
2.34.1
55
50
56
51
diff view generated by jsdifflib
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
1
Add cpuinfo.h for i386 and x86_64, and the initialization
2
for that in util/. Populate that with a slightly altered
3
copy of the tcg host probing code. Other uses of cpuid.h
4
will be adjusted one patch at a time.
5
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Juan Quintela <quintela@redhat.com>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
9
---
4
target/tricore/cpu.c | 11 +++++++++++
10
host/include/i386/host/cpuinfo.h | 38 ++++++++++++
5
target/tricore/translate.c | 6 ------
11
host/include/x86_64/host/cpuinfo.h | 1 +
6
2 files changed, 11 insertions(+), 6 deletions(-)
12
util/cpuinfo-i386.c | 97 ++++++++++++++++++++++++++++++
7
13
MAINTAINERS | 2 +
8
diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c
14
util/meson.build | 4 ++
15
5 files changed, 142 insertions(+)
16
create mode 100644 host/include/i386/host/cpuinfo.h
17
create mode 100644 host/include/x86_64/host/cpuinfo.h
18
create mode 100644 util/cpuinfo-i386.c
19
20
diff --git a/host/include/i386/host/cpuinfo.h b/host/include/i386/host/cpuinfo.h
21
new file mode 100644
22
index XXXXXXX..XXXXXXX
23
--- /dev/null
24
+++ b/host/include/i386/host/cpuinfo.h
25
@@ -XXX,XX +XXX,XX @@
26
+/*
27
+ * SPDX-License-Identifier: GPL-2.0-or-later
28
+ * Host specific cpu indentification for x86.
29
+ */
30
+
31
+#ifndef HOST_CPUINFO_H
32
+#define HOST_CPUINFO_H
33
+
34
+/* Digested version of <cpuid.h> */
35
+
36
+#define CPUINFO_ALWAYS (1u << 0) /* so cpuinfo is nonzero */
37
+#define CPUINFO_CMOV (1u << 1)
38
+#define CPUINFO_MOVBE (1u << 2)
39
+#define CPUINFO_LZCNT (1u << 3)
40
+#define CPUINFO_POPCNT (1u << 4)
41
+#define CPUINFO_BMI1 (1u << 5)
42
+#define CPUINFO_BMI2 (1u << 6)
43
+#define CPUINFO_SSE2 (1u << 7)
44
+#define CPUINFO_SSE4 (1u << 8)
45
+#define CPUINFO_AVX1 (1u << 9)
46
+#define CPUINFO_AVX2 (1u << 10)
47
+#define CPUINFO_AVX512F (1u << 11)
48
+#define CPUINFO_AVX512VL (1u << 12)
49
+#define CPUINFO_AVX512BW (1u << 13)
50
+#define CPUINFO_AVX512DQ (1u << 14)
51
+#define CPUINFO_AVX512VBMI2 (1u << 15)
52
+#define CPUINFO_ATOMIC_VMOVDQA (1u << 16)
53
+
54
+/* Initialized with a constructor. */
55
+extern unsigned cpuinfo;
56
+
57
+/*
58
+ * We cannot rely on constructor ordering, so other constructors must
59
+ * use the function interface rather than the variable above.
60
+ */
61
+unsigned cpuinfo_init(void);
62
+
63
+#endif /* HOST_CPUINFO_H */
64
diff --git a/host/include/x86_64/host/cpuinfo.h b/host/include/x86_64/host/cpuinfo.h
65
new file mode 100644
66
index XXXXXXX..XXXXXXX
67
--- /dev/null
68
+++ b/host/include/x86_64/host/cpuinfo.h
69
@@ -0,0 +1 @@
70
+#include "host/include/i386/host/cpuinfo.h"
71
diff --git a/util/cpuinfo-i386.c b/util/cpuinfo-i386.c
72
new file mode 100644
73
index XXXXXXX..XXXXXXX
74
--- /dev/null
75
+++ b/util/cpuinfo-i386.c
76
@@ -XXX,XX +XXX,XX @@
77
+/*
78
+ * SPDX-License-Identifier: GPL-2.0-or-later
79
+ * Host specific cpu indentification for x86.
80
+ */
81
+
82
+#include "qemu/osdep.h"
83
+#include "host/cpuinfo.h"
84
+#ifdef CONFIG_CPUID_H
85
+# include "qemu/cpuid.h"
86
+#endif
87
+
88
+unsigned cpuinfo;
89
+
90
+/* Called both as constructor and (possibly) via other constructors. */
91
+unsigned __attribute__((constructor)) cpuinfo_init(void)
92
+{
93
+ unsigned info = cpuinfo;
94
+
95
+ if (info) {
96
+ return info;
97
+ }
98
+
99
+#ifdef CONFIG_CPUID_H
100
+ unsigned max, a, b, c, d, b7 = 0, c7 = 0;
101
+
102
+ max = __get_cpuid_max(0, 0);
103
+
104
+ if (max >= 7) {
105
+ __cpuid_count(7, 0, a, b7, c7, d);
106
+ info |= (b7 & bit_BMI ? CPUINFO_BMI1 : 0);
107
+ info |= (b7 & bit_BMI2 ? CPUINFO_BMI2 : 0);
108
+ }
109
+
110
+ if (max >= 1) {
111
+ __cpuid(1, a, b, c, d);
112
+
113
+ info |= (d & bit_CMOV ? CPUINFO_CMOV : 0);
114
+ info |= (d & bit_SSE2 ? CPUINFO_SSE2 : 0);
115
+ info |= (c & bit_SSE4_1 ? CPUINFO_SSE4 : 0);
116
+ info |= (c & bit_MOVBE ? CPUINFO_MOVBE : 0);
117
+ info |= (c & bit_POPCNT ? CPUINFO_POPCNT : 0);
118
+
119
+ /* For AVX features, we must check available and usable. */
120
+ if ((c & bit_AVX) && (c & bit_OSXSAVE)) {
121
+ unsigned bv = xgetbv_low(0);
122
+
123
+ if ((bv & 6) == 6) {
124
+ info |= CPUINFO_AVX1;
125
+ info |= (b7 & bit_AVX2 ? CPUINFO_AVX2 : 0);
126
+
127
+ if ((bv & 0xe0) == 0xe0) {
128
+ info |= (b7 & bit_AVX512F ? CPUINFO_AVX512F : 0);
129
+ info |= (b7 & bit_AVX512VL ? CPUINFO_AVX512VL : 0);
130
+ info |= (b7 & bit_AVX512BW ? CPUINFO_AVX512BW : 0);
131
+ info |= (b7 & bit_AVX512DQ ? CPUINFO_AVX512DQ : 0);
132
+ info |= (c7 & bit_AVX512VBMI2 ? CPUINFO_AVX512VBMI2 : 0);
133
+ }
134
+
135
+ /*
136
+ * The Intel SDM has added:
137
+ * Processors that enumerate support for Intel® AVX
138
+ * (by setting the feature flag CPUID.01H:ECX.AVX[bit 28])
139
+ * guarantee that the 16-byte memory operations performed
140
+ * by the following instructions will always be carried
141
+ * out atomically:
142
+ * - MOVAPD, MOVAPS, and MOVDQA.
143
+ * - VMOVAPD, VMOVAPS, and VMOVDQA when encoded with VEX.128.
144
+ * - VMOVAPD, VMOVAPS, VMOVDQA32, and VMOVDQA64 when encoded
145
+ * with EVEX.128 and k0 (masking disabled).
146
+ * Note that these instructions require the linear addresses
147
+ * of their memory operands to be 16-byte aligned.
148
+ *
149
+ * AMD has provided an even stronger guarantee that processors
150
+ * with AVX provide 16-byte atomicity for all cachable,
151
+ * naturally aligned single loads and stores, e.g. MOVDQU.
152
+ *
153
+ * See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104688
154
+ */
155
+ __cpuid(0, a, b, c, d);
156
+ if (c == signature_INTEL_ecx || c == signature_AMD_ecx) {
157
+ info |= CPUINFO_ATOMIC_VMOVDQA;
158
+ }
159
+ }
160
+ }
161
+ }
162
+
163
+ max = __get_cpuid_max(0x8000000, 0);
164
+ if (max >= 1) {
165
+ __cpuid(0x80000001, a, b, c, d);
166
+ info |= (c & bit_LZCNT ? CPUINFO_LZCNT : 0);
167
+ }
168
+#endif
169
+
170
+ info |= CPUINFO_ALWAYS;
171
+ cpuinfo = info;
172
+ return info;
173
+}
174
diff --git a/MAINTAINERS b/MAINTAINERS
9
index XXXXXXX..XXXXXXX 100644
175
index XXXXXXX..XXXXXXX 100644
10
--- a/target/tricore/cpu.c
176
--- a/MAINTAINERS
11
+++ b/target/tricore/cpu.c
177
+++ b/MAINTAINERS
12
@@ -XXX,XX +XXX,XX @@ static void tricore_cpu_synchronize_from_tb(CPUState *cs,
178
@@ -XXX,XX +XXX,XX @@ F: include/exec/helper*.h
13
env->PC = tb_pc(tb);
179
F: include/sysemu/cpus.h
14
}
180
F: include/sysemu/tcg.h
15
181
F: include/hw/core/tcg-cpu-ops.h
16
+static void tricore_restore_state_to_opc(CPUState *cs,
182
+F: host/include/*/host/cpuinfo.h
17
+ const TranslationBlock *tb,
183
+F: util/cpuinfo-*.c
18
+ const uint64_t *data)
184
19
+{
185
FPU emulation
20
+ TriCoreCPU *cpu = TRICORE_CPU(cs);
186
M: Aurelien Jarno <aurelien@aurel32.net>
21
+ CPUTriCoreState *env = &cpu->env;
187
diff --git a/util/meson.build b/util/meson.build
22
+
23
+ env->PC = data[0];
24
+}
25
+
26
static void tricore_cpu_reset(DeviceState *dev)
27
{
28
CPUState *s = CPU(dev);
29
@@ -XXX,XX +XXX,XX @@ static const struct SysemuCPUOps tricore_sysemu_ops = {
30
static const struct TCGCPUOps tricore_tcg_ops = {
31
.initialize = tricore_tcg_init,
32
.synchronize_from_tb = tricore_cpu_synchronize_from_tb,
33
+ .restore_state_to_opc = tricore_restore_state_to_opc,
34
.tlb_fill = tricore_cpu_tlb_fill,
35
};
36
37
diff --git a/target/tricore/translate.c b/target/tricore/translate.c
38
index XXXXXXX..XXXXXXX 100644
188
index XXXXXXX..XXXXXXX 100644
39
--- a/target/tricore/translate.c
189
--- a/util/meson.build
40
+++ b/target/tricore/translate.c
190
+++ b/util/meson.build
41
@@ -XXX,XX +XXX,XX @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
191
@@ -XXX,XX +XXX,XX @@ if have_block
42
&tricore_tr_ops, &ctx.base);
192
endif
43
}
193
util_ss.add(when: 'CONFIG_LINUX', if_true: files('vfio-helpers.c'))
44
194
endif
45
-void
195
+
46
-restore_state_to_opc(CPUTriCoreState *env, TranslationBlock *tb,
196
+if cpu in ['x86', 'x86_64']
47
- target_ulong *data)
197
+ util_ss.add(files('cpuinfo-i386.c'))
48
-{
198
+endif
49
- env->PC = data[0];
50
-}
51
/*
52
*
53
* Initialization
54
--
199
--
55
2.34.1
200
2.34.1
56
201
57
202
diff view generated by jsdifflib
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
1
Add a bit to indicate when VMOVDQU is also atomic if aligned.
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
6
---
4
target/sparc/cpu.h | 3 +++
7
host/include/i386/host/cpuinfo.h | 1 +
5
target/sparc/cpu.c | 1 +
8
util/cpuinfo-i386.c | 4 +++-
6
target/sparc/translate.c | 7 +++++--
9
2 files changed, 4 insertions(+), 1 deletion(-)
7
3 files changed, 9 insertions(+), 2 deletions(-)
8
10
9
diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
11
diff --git a/host/include/i386/host/cpuinfo.h b/host/include/i386/host/cpuinfo.h
10
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
11
--- a/target/sparc/cpu.h
13
--- a/host/include/i386/host/cpuinfo.h
12
+++ b/target/sparc/cpu.h
14
+++ b/host/include/i386/host/cpuinfo.h
13
@@ -XXX,XX +XXX,XX @@ int sparc_cpu_memory_rw_debug(CPUState *cpu, vaddr addr,
15
@@ -XXX,XX +XXX,XX @@
14
16
#define CPUINFO_AVX512DQ (1u << 14)
15
/* translate.c */
17
#define CPUINFO_AVX512VBMI2 (1u << 15)
16
void sparc_tcg_init(void);
18
#define CPUINFO_ATOMIC_VMOVDQA (1u << 16)
17
+void sparc_restore_state_to_opc(CPUState *cs,
19
+#define CPUINFO_ATOMIC_VMOVDQU (1u << 17)
18
+ const TranslationBlock *tb,
20
19
+ const uint64_t *data);
21
/* Initialized with a constructor. */
20
22
extern unsigned cpuinfo;
21
/* cpu-exec.c */
23
diff --git a/util/cpuinfo-i386.c b/util/cpuinfo-i386.c
22
23
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
24
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
25
--- a/target/sparc/cpu.c
25
--- a/util/cpuinfo-i386.c
26
+++ b/target/sparc/cpu.c
26
+++ b/util/cpuinfo-i386.c
27
@@ -XXX,XX +XXX,XX @@ static const struct SysemuCPUOps sparc_sysemu_ops = {
27
@@ -XXX,XX +XXX,XX @@ unsigned __attribute__((constructor)) cpuinfo_init(void)
28
static const struct TCGCPUOps sparc_tcg_ops = {
28
* See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104688
29
.initialize = sparc_tcg_init,
29
*/
30
.synchronize_from_tb = sparc_cpu_synchronize_from_tb,
30
__cpuid(0, a, b, c, d);
31
+ .restore_state_to_opc = sparc_restore_state_to_opc,
31
- if (c == signature_INTEL_ecx || c == signature_AMD_ecx) {
32
32
+ if (c == signature_INTEL_ecx) {
33
#ifndef CONFIG_USER_ONLY
33
info |= CPUINFO_ATOMIC_VMOVDQA;
34
.tlb_fill = sparc_cpu_tlb_fill,
34
+ } else if (c == signature_AMD_ecx) {
35
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
35
+ info |= CPUINFO_ATOMIC_VMOVDQA | CPUINFO_ATOMIC_VMOVDQU;
36
index XXXXXXX..XXXXXXX 100644
36
}
37
--- a/target/sparc/translate.c
37
}
38
+++ b/target/sparc/translate.c
38
}
39
@@ -XXX,XX +XXX,XX @@ void sparc_tcg_init(void)
40
}
41
}
42
43
-void restore_state_to_opc(CPUSPARCState *env, TranslationBlock *tb,
44
- target_ulong *data)
45
+void sparc_restore_state_to_opc(CPUState *cs,
46
+ const TranslationBlock *tb,
47
+ const uint64_t *data)
48
{
49
+ SPARCCPU *cpu = SPARC_CPU(cs);
50
+ CPUSPARCState *env = &cpu->env;
51
target_ulong pc = data[0];
52
target_ulong npc = data[1];
53
54
--
39
--
55
2.34.1
40
2.34.1
56
41
57
42
diff view generated by jsdifflib
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
1
Use the CPUINFO_* bits instead of the individual boolean
2
variables that we had been using. Remove all of the init
3
code that was moved over to cpuinfo-i386.c.
4
5
Note that have_avx512* check both AVX512{F,VL}, as we had
6
previously done during tcg_target_init.
7
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
11
---
4
target/sh4/cpu.c | 16 ++++++++++++++++
12
tcg/i386/tcg-target.h | 28 +++++----
5
target/sh4/translate.c | 10 ----------
13
tcg/i386/tcg-target.c.inc | 123 ++------------------------------------
6
2 files changed, 16 insertions(+), 10 deletions(-)
14
2 files changed, 22 insertions(+), 129 deletions(-)
7
15
8
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
16
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
9
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
10
--- a/target/sh4/cpu.c
18
--- a/tcg/i386/tcg-target.h
11
+++ b/target/sh4/cpu.c
19
+++ b/tcg/i386/tcg-target.h
12
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_synchronize_from_tb(CPUState *cs,
20
@@ -XXX,XX +XXX,XX @@
13
cpu->env.flags = tb->flags;
21
#ifndef I386_TCG_TARGET_H
14
}
22
#define I386_TCG_TARGET_H
15
23
16
+static void superh_restore_state_to_opc(CPUState *cs,
24
+#include "host/cpuinfo.h"
17
+ const TranslationBlock *tb,
18
+ const uint64_t *data)
19
+{
20
+ SuperHCPU *cpu = SUPERH_CPU(cs);
21
+
25
+
22
+ cpu->env.pc = data[0];
26
#define TCG_TARGET_INSN_UNIT_SIZE 1
23
+ cpu->env.flags = data[1];
27
#define TCG_TARGET_TLB_DISPLACEMENT_BITS 31
24
+ /*
28
25
+ * Theoretically delayed_pc should also be restored. In practice the
29
@@ -XXX,XX +XXX,XX @@ typedef enum {
26
+ * branch instruction is re-executed after exception, so the delayed
30
# define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_BY_REF
27
+ * branch target will be recomputed.
31
#endif
28
+ */
32
29
+}
33
-extern bool have_bmi1;
34
-extern bool have_popcnt;
35
-extern bool have_avx1;
36
-extern bool have_avx2;
37
-extern bool have_avx512bw;
38
-extern bool have_avx512dq;
39
-extern bool have_avx512vbmi2;
40
-extern bool have_avx512vl;
41
-extern bool have_movbe;
42
-extern bool have_atomic16;
43
+#define have_bmi1 (cpuinfo & CPUINFO_BMI1)
44
+#define have_popcnt (cpuinfo & CPUINFO_POPCNT)
45
+#define have_avx1 (cpuinfo & CPUINFO_AVX1)
46
+#define have_avx2 (cpuinfo & CPUINFO_AVX2)
47
+#define have_movbe (cpuinfo & CPUINFO_MOVBE)
48
+#define have_atomic16 (cpuinfo & CPUINFO_ATOMIC_VMOVDQA)
30
+
49
+
31
#ifndef CONFIG_USER_ONLY
50
+/*
32
static bool superh_io_recompile_replay_branch(CPUState *cs,
51
+ * There are interesting instructions in AVX512, so long as we have AVX512VL,
33
const TranslationBlock *tb)
52
+ * which indicates support for EVEX on sizes smaller than 512 bits.
34
@@ -XXX,XX +XXX,XX @@ static const struct SysemuCPUOps sh4_sysemu_ops = {
53
+ */
35
static const struct TCGCPUOps superh_tcg_ops = {
54
+#define have_avx512vl ((cpuinfo & CPUINFO_AVX512VL) && \
36
.initialize = sh4_translate_init,
55
+ (cpuinfo & CPUINFO_AVX512F))
37
.synchronize_from_tb = superh_cpu_synchronize_from_tb,
56
+#define have_avx512bw ((cpuinfo & CPUINFO_AVX512BW) && have_avx512vl)
38
+ .restore_state_to_opc = superh_restore_state_to_opc,
57
+#define have_avx512dq ((cpuinfo & CPUINFO_AVX512DQ) && have_avx512vl)
39
58
+#define have_avx512vbmi2 ((cpuinfo & CPUINFO_AVX512VBMI2) && have_avx512vl)
40
#ifndef CONFIG_USER_ONLY
59
41
.tlb_fill = superh_cpu_tlb_fill,
60
/* optional instructions */
42
diff --git a/target/sh4/translate.c b/target/sh4/translate.c
61
#define TCG_TARGET_HAS_div2_i32 1
62
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
43
index XXXXXXX..XXXXXXX 100644
63
index XXXXXXX..XXXXXXX 100644
44
--- a/target/sh4/translate.c
64
--- a/tcg/i386/tcg-target.c.inc
45
+++ b/target/sh4/translate.c
65
+++ b/tcg/i386/tcg-target.c.inc
46
@@ -XXX,XX +XXX,XX @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
66
@@ -XXX,XX +XXX,XX @@ static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
47
67
# define SOFTMMU_RESERVE_REGS 0
48
translator_loop(cs, tb, max_insns, pc, host_pc, &sh4_tr_ops, &ctx.base);
68
#endif
49
}
69
50
-
70
-/* The host compiler should supply <cpuid.h> to enable runtime features
51
-void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb,
71
- detection, as we're not going to go so far as our own inline assembly.
52
- target_ulong *data)
72
- If not available, default values will be assumed. */
53
-{
73
-#if defined(CONFIG_CPUID_H)
54
- env->pc = data[0];
74
-#include "qemu/cpuid.h"
55
- env->flags = data[1];
75
-#endif
56
- /* Theoretically delayed_pc should also be restored. In practice the
76
-
57
- branch instruction is re-executed after exception, so the delayed
77
/* For 64-bit, we always know that CMOV is available. */
58
- branch target will be recomputed. */
78
#if TCG_TARGET_REG_BITS == 64
59
-}
79
-# define have_cmov 1
80
-#elif defined(CONFIG_CPUID_H)
81
-static bool have_cmov;
82
+# define have_cmov true
83
#else
84
-# define have_cmov 0
85
-#endif
86
-
87
-/* We need these symbols in tcg-target.h, and we can't properly conditionalize
88
- it there. Therefore we always define the variable. */
89
-bool have_bmi1;
90
-bool have_popcnt;
91
-bool have_avx1;
92
-bool have_avx2;
93
-bool have_avx512bw;
94
-bool have_avx512dq;
95
-bool have_avx512vbmi2;
96
-bool have_avx512vl;
97
-bool have_movbe;
98
-bool have_atomic16;
99
-
100
-#ifdef CONFIG_CPUID_H
101
-static bool have_bmi2;
102
-static bool have_lzcnt;
103
-#else
104
-# define have_bmi2 0
105
-# define have_lzcnt 0
106
+# define have_cmov (cpuinfo & CPUINFO_CMOV)
107
#endif
108
+#define have_bmi2 (cpuinfo & CPUINFO_BMI2)
109
+#define have_lzcnt (cpuinfo & CPUINFO_LZCNT)
110
111
static const tcg_insn_unit *tb_ret_addr;
112
113
@@ -XXX,XX +XXX,XX @@ static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
114
115
static void tcg_target_init(TCGContext *s)
116
{
117
-#ifdef CONFIG_CPUID_H
118
- unsigned a, b, c, d, b7 = 0, c7 = 0;
119
- unsigned max = __get_cpuid_max(0, 0);
120
-
121
- if (max >= 7) {
122
- /* BMI1 is available on AMD Piledriver and Intel Haswell CPUs. */
123
- __cpuid_count(7, 0, a, b7, c7, d);
124
- have_bmi1 = (b7 & bit_BMI) != 0;
125
- have_bmi2 = (b7 & bit_BMI2) != 0;
126
- }
127
-
128
- if (max >= 1) {
129
- __cpuid(1, a, b, c, d);
130
-#ifndef have_cmov
131
- /* For 32-bit, 99% certainty that we're running on hardware that
132
- supports cmov, but we still need to check. In case cmov is not
133
- available, we'll use a small forward branch. */
134
- have_cmov = (d & bit_CMOV) != 0;
135
-#endif
136
-
137
- /* MOVBE is only available on Intel Atom and Haswell CPUs, so we
138
- need to probe for it. */
139
- have_movbe = (c & bit_MOVBE) != 0;
140
- have_popcnt = (c & bit_POPCNT) != 0;
141
-
142
- /* There are a number of things we must check before we can be
143
- sure of not hitting invalid opcode. */
144
- if (c & bit_OSXSAVE) {
145
- unsigned bv = xgetbv_low(0);
146
-
147
- if ((bv & 6) == 6) {
148
- have_avx1 = (c & bit_AVX) != 0;
149
- have_avx2 = (b7 & bit_AVX2) != 0;
150
-
151
- /*
152
- * There are interesting instructions in AVX512, so long
153
- * as we have AVX512VL, which indicates support for EVEX
154
- * on sizes smaller than 512 bits. We are required to
155
- * check that OPMASK and all extended ZMM state are enabled
156
- * even if we're not using them -- the insns will fault.
157
- */
158
- if ((bv & 0xe0) == 0xe0
159
- && (b7 & bit_AVX512F)
160
- && (b7 & bit_AVX512VL)) {
161
- have_avx512vl = true;
162
- have_avx512bw = (b7 & bit_AVX512BW) != 0;
163
- have_avx512dq = (b7 & bit_AVX512DQ) != 0;
164
- have_avx512vbmi2 = (c7 & bit_AVX512VBMI2) != 0;
165
- }
166
-
167
- /*
168
- * The Intel SDM has added:
169
- * Processors that enumerate support for Intel® AVX
170
- * (by setting the feature flag CPUID.01H:ECX.AVX[bit 28])
171
- * guarantee that the 16-byte memory operations performed
172
- * by the following instructions will always be carried
173
- * out atomically:
174
- * - MOVAPD, MOVAPS, and MOVDQA.
175
- * - VMOVAPD, VMOVAPS, and VMOVDQA when encoded with VEX.128.
176
- * - VMOVAPD, VMOVAPS, VMOVDQA32, and VMOVDQA64 when encoded
177
- * with EVEX.128 and k0 (masking disabled).
178
- * Note that these instructions require the linear addresses
179
- * of their memory operands to be 16-byte aligned.
180
- *
181
- * AMD has provided an even stronger guarantee that processors
182
- * with AVX provide 16-byte atomicity for all cachable,
183
- * naturally aligned single loads and stores, e.g. MOVDQU.
184
- *
185
- * See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104688
186
- */
187
- if (have_avx1) {
188
- __cpuid(0, a, b, c, d);
189
- have_atomic16 = (c == signature_INTEL_ecx ||
190
- c == signature_AMD_ecx);
191
- }
192
- }
193
- }
194
- }
195
-
196
- max = __get_cpuid_max(0x8000000, 0);
197
- if (max >= 1) {
198
- __cpuid(0x80000001, a, b, c, d);
199
- /* LZCNT was introduced with AMD Barcelona and Intel Haswell CPUs. */
200
- have_lzcnt = (c & bit_LZCNT) != 0;
201
- }
202
-#endif /* CONFIG_CPUID_H */
203
-
204
tcg_target_available_regs[TCG_TYPE_I32] = ALL_GENERAL_REGS;
205
if (TCG_TARGET_REG_BITS == 64) {
206
tcg_target_available_regs[TCG_TYPE_I64] = ALL_GENERAL_REGS;
60
--
207
--
61
2.34.1
208
2.34.1
62
209
63
210
diff view generated by jsdifflib
1
We missed this function when we introduced tb_page_addr_t.
1
Use cpuinfo_init() during init_accel(), and the variable cpuinfo
2
during test_buffer_is_zero_next_accel(). Adjust the logic that
3
cycles through the set of accelerators for testing.
2
4
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
---
7
---
6
include/exec/exec-all.h | 2 +-
8
util/bufferiszero.c | 127 ++++++++++++++++----------------------------
7
include/exec/ram_addr.h | 2 --
9
1 file changed, 46 insertions(+), 81 deletions(-)
8
accel/tcg/tb-maint.c | 13 ++-----------
9
3 files changed, 3 insertions(+), 14 deletions(-)
10
10
11
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
11
diff --git a/util/bufferiszero.c b/util/bufferiszero.c
12
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
13
--- a/include/exec/exec-all.h
13
--- a/util/bufferiszero.c
14
+++ b/include/exec/exec-all.h
14
+++ b/util/bufferiszero.c
15
@@ -XXX,XX +XXX,XX @@ uint32_t curr_cflags(CPUState *cpu);
16
/* TranslationBlock invalidate API */
17
#if defined(CONFIG_USER_ONLY)
18
void tb_invalidate_phys_addr(target_ulong addr);
19
-void tb_invalidate_phys_range(target_ulong start, target_ulong end);
20
#else
21
void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs);
22
#endif
23
void tb_flush(CPUState *cpu);
24
void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr);
25
+void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end);
26
void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr);
27
28
/* GETPC is the true target of the return instruction that we'll execute. */
29
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/include/exec/ram_addr.h
32
+++ b/include/exec/ram_addr.h
33
@@ -XXX,XX +XXX,XX @@ static inline void qemu_ram_block_writeback(RAMBlock *block)
34
#define DIRTY_CLIENTS_ALL ((1 << DIRTY_MEMORY_NUM) - 1)
35
#define DIRTY_CLIENTS_NOCODE (DIRTY_CLIENTS_ALL & ~(1 << DIRTY_MEMORY_CODE))
36
37
-void tb_invalidate_phys_range(ram_addr_t start, ram_addr_t end);
38
-
39
static inline bool cpu_physical_memory_get_dirty(ram_addr_t start,
40
ram_addr_t length,
41
unsigned client)
42
diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/accel/tcg/tb-maint.c
45
+++ b/accel/tcg/tb-maint.c
46
@@ -XXX,XX +XXX,XX @@
15
@@ -XXX,XX +XXX,XX @@
47
#include "qemu/osdep.h"
16
#include "qemu/osdep.h"
48
#include "exec/cputlb.h"
17
#include "qemu/cutils.h"
49
#include "exec/log.h"
18
#include "qemu/bswap.h"
50
+#include "exec/exec-all.h"
19
+#include "host/cpuinfo.h"
51
#include "exec/translate-all.h"
20
52
#include "sysemu/tcg.h"
21
static bool
53
#include "tcg/tcg.h"
22
buffer_zero_int(const void *buf, size_t len)
54
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ buffer_zero_avx512(const void *buf, size_t len)
55
#include "tb-context.h"
24
}
56
#include "internal.h"
25
#endif /* CONFIG_AVX512F_OPT */
57
26
58
-/* FIXME: tb_invalidate_phys_range is declared in different places. */
27
-
59
-#ifdef CONFIG_USER_ONLY
28
-/* Note that for test_buffer_is_zero_next_accel, the most preferred
60
-#include "exec/exec-all.h"
29
- * ISA must have the least significant bit.
61
-#else
30
- */
62
-#include "exec/ram_addr.h"
31
-#define CACHE_AVX512F 1
32
-#define CACHE_AVX2 2
33
-#define CACHE_SSE4 4
34
-#define CACHE_SSE2 8
35
-
36
-/* Make sure that these variables are appropriately initialized when
37
+/*
38
+ * Make sure that these variables are appropriately initialized when
39
* SSE2 is enabled on the compiler command-line, but the compiler is
40
* too old to support CONFIG_AVX2_OPT.
41
*/
42
#if defined(CONFIG_AVX512F_OPT) || defined(CONFIG_AVX2_OPT)
43
-# define INIT_CACHE 0
44
-# define INIT_ACCEL buffer_zero_int
45
+# define INIT_USED 0
46
+# define INIT_LENGTH 0
47
+# define INIT_ACCEL buffer_zero_int
48
#else
49
# ifndef __SSE2__
50
# error "ISA selection confusion"
51
# endif
52
-# define INIT_CACHE CACHE_SSE2
53
-# define INIT_ACCEL buffer_zero_sse2
54
+# define INIT_USED CPUINFO_SSE2
55
+# define INIT_LENGTH 64
56
+# define INIT_ACCEL buffer_zero_sse2
57
#endif
58
59
-static unsigned cpuid_cache = INIT_CACHE;
60
+static unsigned used_accel = INIT_USED;
61
+static unsigned length_to_accel = INIT_LENGTH;
62
static bool (*buffer_accel)(const void *, size_t) = INIT_ACCEL;
63
-static int length_to_accel = 64;
64
65
-static void init_accel(unsigned cache)
66
+static unsigned __attribute__((noinline))
67
+select_accel_cpuinfo(unsigned info)
68
{
69
- bool (*fn)(const void *, size_t) = buffer_zero_int;
70
- if (cache & CACHE_SSE2) {
71
- fn = buffer_zero_sse2;
72
- length_to_accel = 64;
73
- }
74
-#ifdef CONFIG_AVX2_OPT
75
- if (cache & CACHE_SSE4) {
76
- fn = buffer_zero_sse4;
77
- length_to_accel = 64;
78
- }
79
- if (cache & CACHE_AVX2) {
80
- fn = buffer_zero_avx2;
81
- length_to_accel = 128;
82
- }
63
-#endif
83
-#endif
64
84
+ /* Array is sorted in order of algorithm preference. */
65
static bool tb_cmp(const void *ap, const void *bp)
85
+ static const struct {
86
+ unsigned bit;
87
+ unsigned len;
88
+ bool (*fn)(const void *, size_t);
89
+ } all[] = {
90
#ifdef CONFIG_AVX512F_OPT
91
- if (cache & CACHE_AVX512F) {
92
- fn = buffer_zero_avx512;
93
- length_to_accel = 256;
94
- }
95
+ { CPUINFO_AVX512F, 256, buffer_zero_avx512 },
96
#endif
97
- buffer_accel = fn;
98
+#ifdef CONFIG_AVX2_OPT
99
+ { CPUINFO_AVX2, 128, buffer_zero_avx2 },
100
+ { CPUINFO_SSE4, 64, buffer_zero_sse4 },
101
+#endif
102
+ { CPUINFO_SSE2, 64, buffer_zero_sse2 },
103
+ { CPUINFO_ALWAYS, 0, buffer_zero_int },
104
+ };
105
+
106
+ for (unsigned i = 0; i < ARRAY_SIZE(all); ++i) {
107
+ if (info & all[i].bit) {
108
+ length_to_accel = all[i].len;
109
+ buffer_accel = all[i].fn;
110
+ return all[i].bit;
111
+ }
112
+ }
113
+ return 0;
114
}
115
116
#if defined(CONFIG_AVX512F_OPT) || defined(CONFIG_AVX2_OPT)
117
-#include "qemu/cpuid.h"
118
-
119
-static void __attribute__((constructor)) init_cpuid_cache(void)
120
+static void __attribute__((constructor)) init_accel(void)
66
{
121
{
67
@@ -XXX,XX +XXX,XX @@ void tb_invalidate_phys_page(tb_page_addr_t addr)
122
- unsigned max = __get_cpuid_max(0, NULL);
68
*
123
- int a, b, c, d;
69
* Called with mmap_lock held for user-mode emulation.
124
- unsigned cache = 0;
70
*/
125
-
71
-#ifdef CONFIG_SOFTMMU
126
- if (max >= 1) {
72
-void tb_invalidate_phys_range(ram_addr_t start, ram_addr_t end)
127
- __cpuid(1, a, b, c, d);
73
-#else
128
- if (d & bit_SSE2) {
74
-void tb_invalidate_phys_range(target_ulong start, target_ulong end)
129
- cache |= CACHE_SSE2;
75
-#endif
130
- }
76
+void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end)
131
- if (c & bit_SSE4_1) {
132
- cache |= CACHE_SSE4;
133
- }
134
-
135
- /* We must check that AVX is not just available, but usable. */
136
- if ((c & bit_OSXSAVE) && (c & bit_AVX) && max >= 7) {
137
- unsigned bv = xgetbv_low(0);
138
- __cpuid_count(7, 0, a, b, c, d);
139
- if ((bv & 0x6) == 0x6 && (b & bit_AVX2)) {
140
- cache |= CACHE_AVX2;
141
- }
142
- /* 0xe6:
143
- * XCR0[7:5] = 111b (OPMASK state, upper 256-bit of ZMM0-ZMM15
144
- * and ZMM16-ZMM31 state are enabled by OS)
145
- * XCR0[2:1] = 11b (XMM state and YMM state are enabled by OS)
146
- */
147
- if ((bv & 0xe6) == 0xe6 && (b & bit_AVX512F)) {
148
- cache |= CACHE_AVX512F;
149
- }
150
- }
151
- }
152
- cpuid_cache = cache;
153
- init_accel(cache);
154
+ used_accel = select_accel_cpuinfo(cpuinfo_init());
155
}
156
#endif /* CONFIG_AVX2_OPT */
157
158
bool test_buffer_is_zero_next_accel(void)
77
{
159
{
78
struct page_collection *pages;
160
- /* If no bits set, we just tested buffer_zero_int, and there
79
tb_page_addr_t next;
161
- are no more acceleration options to test. */
162
- if (cpuid_cache == 0) {
163
- return false;
164
- }
165
- /* Disable the accelerator we used before and select a new one. */
166
- cpuid_cache &= cpuid_cache - 1;
167
- init_accel(cpuid_cache);
168
- return true;
169
+ /*
170
+ * Accumulate the accelerators that we've already tested, and
171
+ * remove them from the set to test this round. We'll get back
172
+ * a zero from select_accel_cpuinfo when there are no more.
173
+ */
174
+ unsigned used = select_accel_cpuinfo(cpuinfo & ~used_accel);
175
+ used_accel |= used;
176
+ return used;
177
}
178
179
static bool select_accel_fn(const void *buf, size_t len)
80
--
180
--
81
2.34.1
181
2.34.1
82
182
83
183
diff view generated by jsdifflib
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
1
Place the CONFIG_AVX512BW_OPT block at the top,
2
which will aid function selection in the next patch.
3
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Juan Quintela <quintela@redhat.com>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
7
---
4
target/s390x/s390x-internal.h | 4 +++-
8
migration/xbzrle.c | 244 ++++++++++++++++++++++-----------------------
5
target/s390x/cpu.c | 1 +
9
1 file changed, 122 insertions(+), 122 deletions(-)
6
target/s390x/tcg/translate.c | 7 +++++--
10
7
3 files changed, 9 insertions(+), 3 deletions(-)
11
diff --git a/migration/xbzrle.c b/migration/xbzrle.c
8
9
diff --git a/target/s390x/s390x-internal.h b/target/s390x/s390x-internal.h
10
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
11
--- a/target/s390x/s390x-internal.h
13
--- a/migration/xbzrle.c
12
+++ b/target/s390x/s390x-internal.h
14
+++ b/migration/xbzrle.c
13
@@ -XXX,XX +XXX,XX @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3,
15
@@ -XXX,XX +XXX,XX @@
14
16
#include "qemu/host-utils.h"
15
/* translate.c */
17
#include "xbzrle.h"
16
void s390x_translate_init(void);
18
17
-
19
+#if defined(CONFIG_AVX512BW_OPT)
18
+void s390x_restore_state_to_opc(CPUState *cs,
20
+#include <immintrin.h>
19
+ const TranslationBlock *tb,
21
+
20
+ const uint64_t *data);
22
+int __attribute__((target("avx512bw")))
21
23
+xbzrle_encode_buffer_avx512(uint8_t *old_buf, uint8_t *new_buf, int slen,
22
/* sigp.c */
24
+ uint8_t *dst, int dlen)
23
int handle_sigp(CPUS390XState *env, uint8_t order, uint64_t r1, uint64_t r3);
25
+{
24
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
26
+ uint32_t zrun_len = 0, nzrun_len = 0;
25
index XXXXXXX..XXXXXXX 100644
27
+ int d = 0, i = 0, num = 0;
26
--- a/target/s390x/cpu.c
28
+ uint8_t *nzrun_start = NULL;
27
+++ b/target/s390x/cpu.c
29
+ /* add 1 to include residual part in main loop */
28
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_reset_full(DeviceState *dev)
30
+ uint32_t count512s = (slen >> 6) + 1;
29
31
+ /* countResidual is tail of data, i.e., countResidual = slen % 64 */
30
static const struct TCGCPUOps s390_tcg_ops = {
32
+ uint32_t count_residual = slen & 0b111111;
31
.initialize = s390x_translate_init,
33
+ bool never_same = true;
32
+ .restore_state_to_opc = s390x_restore_state_to_opc,
34
+ uint64_t mask_residual = 1;
33
35
+ mask_residual <<= count_residual;
34
#ifdef CONFIG_USER_ONLY
36
+ mask_residual -= 1;
35
.record_sigsegv = s390_cpu_record_sigsegv,
37
+ __m512i r = _mm512_set1_epi32(0);
36
diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c
38
+
37
index XXXXXXX..XXXXXXX 100644
39
+ while (count512s) {
38
--- a/target/s390x/tcg/translate.c
40
+ int bytes_to_check = 64;
39
+++ b/target/s390x/tcg/translate.c
41
+ uint64_t mask = 0xffffffffffffffff;
40
@@ -XXX,XX +XXX,XX @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
42
+ if (count512s == 1) {
41
translator_loop(cs, tb, max_insns, pc, host_pc, &s390x_tr_ops, &dc.base);
43
+ bytes_to_check = count_residual;
44
+ mask = mask_residual;
45
+ }
46
+ __m512i old_data = _mm512_mask_loadu_epi8(r,
47
+ mask, old_buf + i);
48
+ __m512i new_data = _mm512_mask_loadu_epi8(r,
49
+ mask, new_buf + i);
50
+ uint64_t comp = _mm512_cmpeq_epi8_mask(old_data, new_data);
51
+ count512s--;
52
+
53
+ bool is_same = (comp & 0x1);
54
+ while (bytes_to_check) {
55
+ if (d + 2 > dlen) {
56
+ return -1;
57
+ }
58
+ if (is_same) {
59
+ if (nzrun_len) {
60
+ d += uleb128_encode_small(dst + d, nzrun_len);
61
+ if (d + nzrun_len > dlen) {
62
+ return -1;
63
+ }
64
+ nzrun_start = new_buf + i - nzrun_len;
65
+ memcpy(dst + d, nzrun_start, nzrun_len);
66
+ d += nzrun_len;
67
+ nzrun_len = 0;
68
+ }
69
+ /* 64 data at a time for speed */
70
+ if (count512s && (comp == 0xffffffffffffffff)) {
71
+ i += 64;
72
+ zrun_len += 64;
73
+ break;
74
+ }
75
+ never_same = false;
76
+ num = ctz64(~comp);
77
+ num = (num < bytes_to_check) ? num : bytes_to_check;
78
+ zrun_len += num;
79
+ bytes_to_check -= num;
80
+ comp >>= num;
81
+ i += num;
82
+ if (bytes_to_check) {
83
+ /* still has different data after same data */
84
+ d += uleb128_encode_small(dst + d, zrun_len);
85
+ zrun_len = 0;
86
+ } else {
87
+ break;
88
+ }
89
+ }
90
+ if (never_same || zrun_len) {
91
+ /*
92
+ * never_same only acts if
93
+ * data begins with diff in first count512s
94
+ */
95
+ d += uleb128_encode_small(dst + d, zrun_len);
96
+ zrun_len = 0;
97
+ never_same = false;
98
+ }
99
+ /* has diff, 64 data at a time for speed */
100
+ if ((bytes_to_check == 64) && (comp == 0x0)) {
101
+ i += 64;
102
+ nzrun_len += 64;
103
+ break;
104
+ }
105
+ num = ctz64(comp);
106
+ num = (num < bytes_to_check) ? num : bytes_to_check;
107
+ nzrun_len += num;
108
+ bytes_to_check -= num;
109
+ comp >>= num;
110
+ i += num;
111
+ if (bytes_to_check) {
112
+ /* mask like 111000 */
113
+ d += uleb128_encode_small(dst + d, nzrun_len);
114
+ /* overflow */
115
+ if (d + nzrun_len > dlen) {
116
+ return -1;
117
+ }
118
+ nzrun_start = new_buf + i - nzrun_len;
119
+ memcpy(dst + d, nzrun_start, nzrun_len);
120
+ d += nzrun_len;
121
+ nzrun_len = 0;
122
+ is_same = true;
123
+ }
124
+ }
125
+ }
126
+
127
+ if (nzrun_len != 0) {
128
+ d += uleb128_encode_small(dst + d, nzrun_len);
129
+ /* overflow */
130
+ if (d + nzrun_len > dlen) {
131
+ return -1;
132
+ }
133
+ nzrun_start = new_buf + i - nzrun_len;
134
+ memcpy(dst + d, nzrun_start, nzrun_len);
135
+ d += nzrun_len;
136
+ }
137
+ return d;
138
+}
139
+#endif
140
+
141
/*
142
page = zrun nzrun
143
| zrun nzrun page
144
@@ -XXX,XX +XXX,XX @@ int xbzrle_decode_buffer(uint8_t *src, int slen, uint8_t *dst, int dlen)
145
146
return d;
42
}
147
}
43
148
-
44
-void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb,
149
-#if defined(CONFIG_AVX512BW_OPT)
45
- target_ulong *data)
150
-#include <immintrin.h>
46
+void s390x_restore_state_to_opc(CPUState *cs,
151
-
47
+ const TranslationBlock *tb,
152
-int __attribute__((target("avx512bw")))
48
+ const uint64_t *data)
153
-xbzrle_encode_buffer_avx512(uint8_t *old_buf, uint8_t *new_buf, int slen,
49
{
154
- uint8_t *dst, int dlen)
50
+ S390CPU *cpu = S390_CPU(cs);
155
-{
51
+ CPUS390XState *env = &cpu->env;
156
- uint32_t zrun_len = 0, nzrun_len = 0;
52
int cc_op = data[1];
157
- int d = 0, i = 0, num = 0;
53
158
- uint8_t *nzrun_start = NULL;
54
env->psw.addr = data[0];
159
- /* add 1 to include residual part in main loop */
160
- uint32_t count512s = (slen >> 6) + 1;
161
- /* countResidual is tail of data, i.e., countResidual = slen % 64 */
162
- uint32_t count_residual = slen & 0b111111;
163
- bool never_same = true;
164
- uint64_t mask_residual = 1;
165
- mask_residual <<= count_residual;
166
- mask_residual -= 1;
167
- __m512i r = _mm512_set1_epi32(0);
168
-
169
- while (count512s) {
170
- int bytes_to_check = 64;
171
- uint64_t mask = 0xffffffffffffffff;
172
- if (count512s == 1) {
173
- bytes_to_check = count_residual;
174
- mask = mask_residual;
175
- }
176
- __m512i old_data = _mm512_mask_loadu_epi8(r,
177
- mask, old_buf + i);
178
- __m512i new_data = _mm512_mask_loadu_epi8(r,
179
- mask, new_buf + i);
180
- uint64_t comp = _mm512_cmpeq_epi8_mask(old_data, new_data);
181
- count512s--;
182
-
183
- bool is_same = (comp & 0x1);
184
- while (bytes_to_check) {
185
- if (d + 2 > dlen) {
186
- return -1;
187
- }
188
- if (is_same) {
189
- if (nzrun_len) {
190
- d += uleb128_encode_small(dst + d, nzrun_len);
191
- if (d + nzrun_len > dlen) {
192
- return -1;
193
- }
194
- nzrun_start = new_buf + i - nzrun_len;
195
- memcpy(dst + d, nzrun_start, nzrun_len);
196
- d += nzrun_len;
197
- nzrun_len = 0;
198
- }
199
- /* 64 data at a time for speed */
200
- if (count512s && (comp == 0xffffffffffffffff)) {
201
- i += 64;
202
- zrun_len += 64;
203
- break;
204
- }
205
- never_same = false;
206
- num = ctz64(~comp);
207
- num = (num < bytes_to_check) ? num : bytes_to_check;
208
- zrun_len += num;
209
- bytes_to_check -= num;
210
- comp >>= num;
211
- i += num;
212
- if (bytes_to_check) {
213
- /* still has different data after same data */
214
- d += uleb128_encode_small(dst + d, zrun_len);
215
- zrun_len = 0;
216
- } else {
217
- break;
218
- }
219
- }
220
- if (never_same || zrun_len) {
221
- /*
222
- * never_same only acts if
223
- * data begins with diff in first count512s
224
- */
225
- d += uleb128_encode_small(dst + d, zrun_len);
226
- zrun_len = 0;
227
- never_same = false;
228
- }
229
- /* has diff, 64 data at a time for speed */
230
- if ((bytes_to_check == 64) && (comp == 0x0)) {
231
- i += 64;
232
- nzrun_len += 64;
233
- break;
234
- }
235
- num = ctz64(comp);
236
- num = (num < bytes_to_check) ? num : bytes_to_check;
237
- nzrun_len += num;
238
- bytes_to_check -= num;
239
- comp >>= num;
240
- i += num;
241
- if (bytes_to_check) {
242
- /* mask like 111000 */
243
- d += uleb128_encode_small(dst + d, nzrun_len);
244
- /* overflow */
245
- if (d + nzrun_len > dlen) {
246
- return -1;
247
- }
248
- nzrun_start = new_buf + i - nzrun_len;
249
- memcpy(dst + d, nzrun_start, nzrun_len);
250
- d += nzrun_len;
251
- nzrun_len = 0;
252
- is_same = true;
253
- }
254
- }
255
- }
256
-
257
- if (nzrun_len != 0) {
258
- d += uleb128_encode_small(dst + d, nzrun_len);
259
- /* overflow */
260
- if (d + nzrun_len > dlen) {
261
- return -1;
262
- }
263
- nzrun_start = new_buf + i - nzrun_len;
264
- memcpy(dst + d, nzrun_start, nzrun_len);
265
- d += nzrun_len;
266
- }
267
- return d;
268
-}
269
-#endif
55
--
270
--
56
2.34.1
271
2.34.1
57
272
58
273
diff view generated by jsdifflib
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
1
Perform the function selection once, and only if CONFIG_AVX512_OPT
2
is enabled. Centralize the selection to xbzrle.c, instead of
3
spreading the init across 3 files.
4
5
Remove xbzrle-bench.c. The benefit of being able to benchmark
6
the different implementations is less important than not peeking
7
into the internals of the implementation.
8
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Reviewed-by: Juan Quintela <quintela@redhat.com>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
12
---
4
target/m68k/cpu.c | 14 ++++++++++++++
13
migration/xbzrle.h | 5 +-
5
target/m68k/translate.c | 10 ----------
14
migration/ram.c | 34 +--
6
2 files changed, 14 insertions(+), 10 deletions(-)
15
migration/xbzrle.c | 26 +-
16
tests/bench/xbzrle-bench.c | 469 -------------------------------------
17
tests/unit/test-xbzrle.c | 49 +---
18
tests/bench/meson.build | 6 -
19
6 files changed, 39 insertions(+), 550 deletions(-)
20
delete mode 100644 tests/bench/xbzrle-bench.c
7
21
8
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
22
diff --git a/migration/xbzrle.h b/migration/xbzrle.h
9
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
10
--- a/target/m68k/cpu.c
24
--- a/migration/xbzrle.h
11
+++ b/target/m68k/cpu.c
25
+++ b/migration/xbzrle.h
12
@@ -XXX,XX +XXX,XX @@ static vaddr m68k_cpu_get_pc(CPUState *cs)
26
@@ -XXX,XX +XXX,XX @@ int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen,
13
return cpu->env.pc;
27
uint8_t *dst, int dlen);
28
29
int xbzrle_decode_buffer(uint8_t *src, int slen, uint8_t *dst, int dlen);
30
-#if defined(CONFIG_AVX512BW_OPT)
31
-int xbzrle_encode_buffer_avx512(uint8_t *old_buf, uint8_t *new_buf, int slen,
32
- uint8_t *dst, int dlen);
33
-#endif
34
+
35
#endif
36
diff --git a/migration/ram.c b/migration/ram.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/migration/ram.c
39
+++ b/migration/ram.c
40
@@ -XXX,XX +XXX,XX @@
41
#define RAM_SAVE_FLAG_MULTIFD_FLUSH 0x200
42
/* We can't use any flag that is bigger than 0x200 */
43
44
-int (*xbzrle_encode_buffer_func)(uint8_t *, uint8_t *, int,
45
- uint8_t *, int) = xbzrle_encode_buffer;
46
-#if defined(CONFIG_AVX512BW_OPT)
47
-#include "qemu/cpuid.h"
48
-static void __attribute__((constructor)) init_cpu_flag(void)
49
-{
50
- unsigned max = __get_cpuid_max(0, NULL);
51
- int a, b, c, d;
52
- if (max >= 1) {
53
- __cpuid(1, a, b, c, d);
54
- /* We must check that AVX is not just available, but usable. */
55
- if ((c & bit_OSXSAVE) && (c & bit_AVX) && max >= 7) {
56
- int bv;
57
- __asm("xgetbv" : "=a"(bv), "=d"(d) : "c"(0));
58
- __cpuid_count(7, 0, a, b, c, d);
59
- /* 0xe6:
60
- * XCR0[7:5] = 111b (OPMASK state, upper 256-bit of ZMM0-ZMM15
61
- * and ZMM16-ZMM31 state are enabled by OS)
62
- * XCR0[2:1] = 11b (XMM state and YMM state are enabled by OS)
63
- */
64
- if ((bv & 0xe6) == 0xe6 && (b & bit_AVX512BW)) {
65
- xbzrle_encode_buffer_func = xbzrle_encode_buffer_avx512;
66
- }
67
- }
68
- }
69
-}
70
-#endif
71
-
72
XBZRLECacheStats xbzrle_counters;
73
74
/* used by the search for pages to send */
75
@@ -XXX,XX +XXX,XX @@ static int save_xbzrle_page(RAMState *rs, PageSearchStatus *pss,
76
memcpy(XBZRLE.current_buf, *current_data, TARGET_PAGE_SIZE);
77
78
/* XBZRLE encoding (if there is no overflow) */
79
- encoded_len = xbzrle_encode_buffer_func(prev_cached_page, XBZRLE.current_buf,
80
- TARGET_PAGE_SIZE, XBZRLE.encoded_buf,
81
- TARGET_PAGE_SIZE);
82
+ encoded_len = xbzrle_encode_buffer(prev_cached_page, XBZRLE.current_buf,
83
+ TARGET_PAGE_SIZE, XBZRLE.encoded_buf,
84
+ TARGET_PAGE_SIZE);
85
86
/*
87
* Update the cache contents, so that it corresponds to the data
88
diff --git a/migration/xbzrle.c b/migration/xbzrle.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/migration/xbzrle.c
91
+++ b/migration/xbzrle.c
92
@@ -XXX,XX +XXX,XX @@
93
94
#if defined(CONFIG_AVX512BW_OPT)
95
#include <immintrin.h>
96
+#include "host/cpuinfo.h"
97
98
-int __attribute__((target("avx512bw")))
99
+static int __attribute__((target("avx512bw")))
100
xbzrle_encode_buffer_avx512(uint8_t *old_buf, uint8_t *new_buf, int slen,
101
uint8_t *dst, int dlen)
102
{
103
@@ -XXX,XX +XXX,XX @@ xbzrle_encode_buffer_avx512(uint8_t *old_buf, uint8_t *new_buf, int slen,
104
}
105
return d;
14
}
106
}
15
107
+
16
+static void m68k_restore_state_to_opc(CPUState *cs,
108
+static int xbzrle_encode_buffer_int(uint8_t *old_buf, uint8_t *new_buf,
17
+ const TranslationBlock *tb,
109
+ int slen, uint8_t *dst, int dlen);
18
+ const uint64_t *data)
110
+
111
+static int (*accel_func)(uint8_t *, uint8_t *, int, uint8_t *, int);
112
+
113
+static void __attribute__((constructor)) init_accel(void)
19
+{
114
+{
20
+ M68kCPU *cpu = M68K_CPU(cs);
115
+ unsigned info = cpuinfo_init();
21
+ int cc_op = data[1];
116
+ if (info & CPUINFO_AVX512BW) {
22
+
117
+ accel_func = xbzrle_encode_buffer_avx512;
23
+ cpu->env.pc = data[0];
118
+ } else {
24
+ if (cc_op != CC_OP_DYNAMIC) {
119
+ accel_func = xbzrle_encode_buffer_int;
25
+ cpu->env.cc_op = cc_op;
26
+ }
120
+ }
27
+}
121
+}
28
+
122
+
29
static bool m68k_cpu_has_work(CPUState *cs)
123
+int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen,
124
+ uint8_t *dst, int dlen)
125
+{
126
+ return accel_func(old_buf, new_buf, slen, dst, dlen);
127
+}
128
+
129
+#define xbzrle_encode_buffer xbzrle_encode_buffer_int
130
#endif
131
132
/*
133
diff --git a/tests/bench/xbzrle-bench.c b/tests/bench/xbzrle-bench.c
134
deleted file mode 100644
135
index XXXXXXX..XXXXXXX
136
--- a/tests/bench/xbzrle-bench.c
137
+++ /dev/null
138
@@ -XXX,XX +XXX,XX @@
139
-/*
140
- * Xor Based Zero Run Length Encoding unit tests.
141
- *
142
- * Copyright 2013 Red Hat, Inc. and/or its affiliates
143
- *
144
- * Authors:
145
- * Orit Wasserman <owasserm@redhat.com>
146
- *
147
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
148
- * See the COPYING file in the top-level directory.
149
- *
150
- */
151
-#include "qemu/osdep.h"
152
-#include "qemu/cutils.h"
153
-#include "../migration/xbzrle.h"
154
-
155
-#if defined(CONFIG_AVX512BW_OPT)
156
-#define XBZRLE_PAGE_SIZE 4096
157
-static bool is_cpu_support_avx512bw;
158
-#include "qemu/cpuid.h"
159
-static void __attribute__((constructor)) init_cpu_flag(void)
160
-{
161
- unsigned max = __get_cpuid_max(0, NULL);
162
- int a, b, c, d;
163
- is_cpu_support_avx512bw = false;
164
- if (max >= 1) {
165
- __cpuid(1, a, b, c, d);
166
- /* We must check that AVX is not just available, but usable. */
167
- if ((c & bit_OSXSAVE) && (c & bit_AVX) && max >= 7) {
168
- int bv;
169
- __asm("xgetbv" : "=a"(bv), "=d"(d) : "c"(0));
170
- __cpuid_count(7, 0, a, b, c, d);
171
- /* 0xe6:
172
- * XCR0[7:5] = 111b (OPMASK state, upper 256-bit of ZMM0-ZMM15
173
- * and ZMM16-ZMM31 state are enabled by OS)
174
- * XCR0[2:1] = 11b (XMM state and YMM state are enabled by OS)
175
- */
176
- if ((bv & 0xe6) == 0xe6 && (b & bit_AVX512BW)) {
177
- is_cpu_support_avx512bw = true;
178
- }
179
- }
180
- }
181
- return ;
182
-}
183
-
184
-struct ResTime {
185
- float t_raw;
186
- float t_512;
187
-};
188
-
189
-
190
-/* Function prototypes
191
-int xbzrle_encode_buffer_avx512(uint8_t *old_buf, uint8_t *new_buf, int slen,
192
- uint8_t *dst, int dlen);
193
-*/
194
-static void encode_decode_zero(struct ResTime *res)
195
-{
196
- uint8_t *buffer = g_malloc0(XBZRLE_PAGE_SIZE);
197
- uint8_t *compressed = g_malloc0(XBZRLE_PAGE_SIZE);
198
- uint8_t *buffer512 = g_malloc0(XBZRLE_PAGE_SIZE);
199
- uint8_t *compressed512 = g_malloc0(XBZRLE_PAGE_SIZE);
200
- int i = 0;
201
- int dlen = 0, dlen512 = 0;
202
- int diff_len = g_test_rand_int_range(0, XBZRLE_PAGE_SIZE - 1006);
203
-
204
- for (i = diff_len; i > 0; i--) {
205
- buffer[1000 + i] = i;
206
- buffer512[1000 + i] = i;
207
- }
208
-
209
- buffer[1000 + diff_len + 3] = 103;
210
- buffer[1000 + diff_len + 5] = 105;
211
-
212
- buffer512[1000 + diff_len + 3] = 103;
213
- buffer512[1000 + diff_len + 5] = 105;
214
-
215
- /* encode zero page */
216
- time_t t_start, t_end, t_start512, t_end512;
217
- t_start = clock();
218
- dlen = xbzrle_encode_buffer(buffer, buffer, XBZRLE_PAGE_SIZE, compressed,
219
- XBZRLE_PAGE_SIZE);
220
- t_end = clock();
221
- float time_val = difftime(t_end, t_start);
222
- g_assert(dlen == 0);
223
-
224
- t_start512 = clock();
225
- dlen512 = xbzrle_encode_buffer_avx512(buffer512, buffer512, XBZRLE_PAGE_SIZE,
226
- compressed512, XBZRLE_PAGE_SIZE);
227
- t_end512 = clock();
228
- float time_val512 = difftime(t_end512, t_start512);
229
- g_assert(dlen512 == 0);
230
-
231
- res->t_raw = time_val;
232
- res->t_512 = time_val512;
233
-
234
- g_free(buffer);
235
- g_free(compressed);
236
- g_free(buffer512);
237
- g_free(compressed512);
238
-
239
-}
240
-
241
-static void test_encode_decode_zero_avx512(void)
242
-{
243
- int i;
244
- float time_raw = 0.0, time_512 = 0.0;
245
- struct ResTime res;
246
- for (i = 0; i < 10000; i++) {
247
- encode_decode_zero(&res);
248
- time_raw += res.t_raw;
249
- time_512 += res.t_512;
250
- }
251
- printf("Zero test:\n");
252
- printf("Raw xbzrle_encode time is %f ms\n", time_raw);
253
- printf("512 xbzrle_encode time is %f ms\n", time_512);
254
-}
255
-
256
-static void encode_decode_unchanged(struct ResTime *res)
257
-{
258
- uint8_t *compressed = g_malloc0(XBZRLE_PAGE_SIZE);
259
- uint8_t *test = g_malloc0(XBZRLE_PAGE_SIZE);
260
- uint8_t *compressed512 = g_malloc0(XBZRLE_PAGE_SIZE);
261
- uint8_t *test512 = g_malloc0(XBZRLE_PAGE_SIZE);
262
- int i = 0;
263
- int dlen = 0, dlen512 = 0;
264
- int diff_len = g_test_rand_int_range(0, XBZRLE_PAGE_SIZE - 1006);
265
-
266
- for (i = diff_len; i > 0; i--) {
267
- test[1000 + i] = i + 4;
268
- test512[1000 + i] = i + 4;
269
- }
270
-
271
- test[1000 + diff_len + 3] = 107;
272
- test[1000 + diff_len + 5] = 109;
273
-
274
- test512[1000 + diff_len + 3] = 107;
275
- test512[1000 + diff_len + 5] = 109;
276
-
277
- /* test unchanged buffer */
278
- time_t t_start, t_end, t_start512, t_end512;
279
- t_start = clock();
280
- dlen = xbzrle_encode_buffer(test, test, XBZRLE_PAGE_SIZE, compressed,
281
- XBZRLE_PAGE_SIZE);
282
- t_end = clock();
283
- float time_val = difftime(t_end, t_start);
284
- g_assert(dlen == 0);
285
-
286
- t_start512 = clock();
287
- dlen512 = xbzrle_encode_buffer_avx512(test512, test512, XBZRLE_PAGE_SIZE,
288
- compressed512, XBZRLE_PAGE_SIZE);
289
- t_end512 = clock();
290
- float time_val512 = difftime(t_end512, t_start512);
291
- g_assert(dlen512 == 0);
292
-
293
- res->t_raw = time_val;
294
- res->t_512 = time_val512;
295
-
296
- g_free(test);
297
- g_free(compressed);
298
- g_free(test512);
299
- g_free(compressed512);
300
-
301
-}
302
-
303
-static void test_encode_decode_unchanged_avx512(void)
304
-{
305
- int i;
306
- float time_raw = 0.0, time_512 = 0.0;
307
- struct ResTime res;
308
- for (i = 0; i < 10000; i++) {
309
- encode_decode_unchanged(&res);
310
- time_raw += res.t_raw;
311
- time_512 += res.t_512;
312
- }
313
- printf("Unchanged test:\n");
314
- printf("Raw xbzrle_encode time is %f ms\n", time_raw);
315
- printf("512 xbzrle_encode time is %f ms\n", time_512);
316
-}
317
-
318
-static void encode_decode_1_byte(struct ResTime *res)
319
-{
320
- uint8_t *buffer = g_malloc0(XBZRLE_PAGE_SIZE);
321
- uint8_t *test = g_malloc0(XBZRLE_PAGE_SIZE);
322
- uint8_t *compressed = g_malloc(XBZRLE_PAGE_SIZE);
323
- uint8_t *buffer512 = g_malloc0(XBZRLE_PAGE_SIZE);
324
- uint8_t *test512 = g_malloc0(XBZRLE_PAGE_SIZE);
325
- uint8_t *compressed512 = g_malloc(XBZRLE_PAGE_SIZE);
326
- int dlen = 0, rc = 0, dlen512 = 0, rc512 = 0;
327
- uint8_t buf[2];
328
- uint8_t buf512[2];
329
-
330
- test[XBZRLE_PAGE_SIZE - 1] = 1;
331
- test512[XBZRLE_PAGE_SIZE - 1] = 1;
332
-
333
- time_t t_start, t_end, t_start512, t_end512;
334
- t_start = clock();
335
- dlen = xbzrle_encode_buffer(buffer, test, XBZRLE_PAGE_SIZE, compressed,
336
- XBZRLE_PAGE_SIZE);
337
- t_end = clock();
338
- float time_val = difftime(t_end, t_start);
339
- g_assert(dlen == (uleb128_encode_small(&buf[0], 4095) + 2));
340
-
341
- rc = xbzrle_decode_buffer(compressed, dlen, buffer, XBZRLE_PAGE_SIZE);
342
- g_assert(rc == XBZRLE_PAGE_SIZE);
343
- g_assert(memcmp(test, buffer, XBZRLE_PAGE_SIZE) == 0);
344
-
345
- t_start512 = clock();
346
- dlen512 = xbzrle_encode_buffer_avx512(buffer512, test512, XBZRLE_PAGE_SIZE,
347
- compressed512, XBZRLE_PAGE_SIZE);
348
- t_end512 = clock();
349
- float time_val512 = difftime(t_end512, t_start512);
350
- g_assert(dlen512 == (uleb128_encode_small(&buf512[0], 4095) + 2));
351
-
352
- rc512 = xbzrle_decode_buffer(compressed512, dlen512, buffer512,
353
- XBZRLE_PAGE_SIZE);
354
- g_assert(rc512 == XBZRLE_PAGE_SIZE);
355
- g_assert(memcmp(test512, buffer512, XBZRLE_PAGE_SIZE) == 0);
356
-
357
- res->t_raw = time_val;
358
- res->t_512 = time_val512;
359
-
360
- g_free(buffer);
361
- g_free(compressed);
362
- g_free(test);
363
- g_free(buffer512);
364
- g_free(compressed512);
365
- g_free(test512);
366
-
367
-}
368
-
369
-static void test_encode_decode_1_byte_avx512(void)
370
-{
371
- int i;
372
- float time_raw = 0.0, time_512 = 0.0;
373
- struct ResTime res;
374
- for (i = 0; i < 10000; i++) {
375
- encode_decode_1_byte(&res);
376
- time_raw += res.t_raw;
377
- time_512 += res.t_512;
378
- }
379
- printf("1 byte test:\n");
380
- printf("Raw xbzrle_encode time is %f ms\n", time_raw);
381
- printf("512 xbzrle_encode time is %f ms\n", time_512);
382
-}
383
-
384
-static void encode_decode_overflow(struct ResTime *res)
385
-{
386
- uint8_t *compressed = g_malloc0(XBZRLE_PAGE_SIZE);
387
- uint8_t *test = g_malloc0(XBZRLE_PAGE_SIZE);
388
- uint8_t *buffer = g_malloc0(XBZRLE_PAGE_SIZE);
389
- uint8_t *compressed512 = g_malloc0(XBZRLE_PAGE_SIZE);
390
- uint8_t *test512 = g_malloc0(XBZRLE_PAGE_SIZE);
391
- uint8_t *buffer512 = g_malloc0(XBZRLE_PAGE_SIZE);
392
- int i = 0, rc = 0, rc512 = 0;
393
-
394
- for (i = 0; i < XBZRLE_PAGE_SIZE / 2 - 1; i++) {
395
- test[i * 2] = 1;
396
- test512[i * 2] = 1;
397
- }
398
-
399
- /* encode overflow */
400
- time_t t_start, t_end, t_start512, t_end512;
401
- t_start = clock();
402
- rc = xbzrle_encode_buffer(buffer, test, XBZRLE_PAGE_SIZE, compressed,
403
- XBZRLE_PAGE_SIZE);
404
- t_end = clock();
405
- float time_val = difftime(t_end, t_start);
406
- g_assert(rc == -1);
407
-
408
- t_start512 = clock();
409
- rc512 = xbzrle_encode_buffer_avx512(buffer512, test512, XBZRLE_PAGE_SIZE,
410
- compressed512, XBZRLE_PAGE_SIZE);
411
- t_end512 = clock();
412
- float time_val512 = difftime(t_end512, t_start512);
413
- g_assert(rc512 == -1);
414
-
415
- res->t_raw = time_val;
416
- res->t_512 = time_val512;
417
-
418
- g_free(buffer);
419
- g_free(compressed);
420
- g_free(test);
421
- g_free(buffer512);
422
- g_free(compressed512);
423
- g_free(test512);
424
-
425
-}
426
-
427
-static void test_encode_decode_overflow_avx512(void)
428
-{
429
- int i;
430
- float time_raw = 0.0, time_512 = 0.0;
431
- struct ResTime res;
432
- for (i = 0; i < 10000; i++) {
433
- encode_decode_overflow(&res);
434
- time_raw += res.t_raw;
435
- time_512 += res.t_512;
436
- }
437
- printf("Overflow test:\n");
438
- printf("Raw xbzrle_encode time is %f ms\n", time_raw);
439
- printf("512 xbzrle_encode time is %f ms\n", time_512);
440
-}
441
-
442
-static void encode_decode_range_avx512(struct ResTime *res)
443
-{
444
- uint8_t *buffer = g_malloc0(XBZRLE_PAGE_SIZE);
445
- uint8_t *compressed = g_malloc(XBZRLE_PAGE_SIZE);
446
- uint8_t *test = g_malloc0(XBZRLE_PAGE_SIZE);
447
- uint8_t *buffer512 = g_malloc0(XBZRLE_PAGE_SIZE);
448
- uint8_t *compressed512 = g_malloc(XBZRLE_PAGE_SIZE);
449
- uint8_t *test512 = g_malloc0(XBZRLE_PAGE_SIZE);
450
- int i = 0, rc = 0, rc512 = 0;
451
- int dlen = 0, dlen512 = 0;
452
-
453
- int diff_len = g_test_rand_int_range(0, XBZRLE_PAGE_SIZE - 1006);
454
-
455
- for (i = diff_len; i > 0; i--) {
456
- buffer[1000 + i] = i;
457
- test[1000 + i] = i + 4;
458
- buffer512[1000 + i] = i;
459
- test512[1000 + i] = i + 4;
460
- }
461
-
462
- buffer[1000 + diff_len + 3] = 103;
463
- test[1000 + diff_len + 3] = 107;
464
-
465
- buffer[1000 + diff_len + 5] = 105;
466
- test[1000 + diff_len + 5] = 109;
467
-
468
- buffer512[1000 + diff_len + 3] = 103;
469
- test512[1000 + diff_len + 3] = 107;
470
-
471
- buffer512[1000 + diff_len + 5] = 105;
472
- test512[1000 + diff_len + 5] = 109;
473
-
474
- /* test encode/decode */
475
- time_t t_start, t_end, t_start512, t_end512;
476
- t_start = clock();
477
- dlen = xbzrle_encode_buffer(test, buffer, XBZRLE_PAGE_SIZE, compressed,
478
- XBZRLE_PAGE_SIZE);
479
- t_end = clock();
480
- float time_val = difftime(t_end, t_start);
481
- rc = xbzrle_decode_buffer(compressed, dlen, test, XBZRLE_PAGE_SIZE);
482
- g_assert(rc < XBZRLE_PAGE_SIZE);
483
- g_assert(memcmp(test, buffer, XBZRLE_PAGE_SIZE) == 0);
484
-
485
- t_start512 = clock();
486
- dlen512 = xbzrle_encode_buffer_avx512(test512, buffer512, XBZRLE_PAGE_SIZE,
487
- compressed512, XBZRLE_PAGE_SIZE);
488
- t_end512 = clock();
489
- float time_val512 = difftime(t_end512, t_start512);
490
- rc512 = xbzrle_decode_buffer(compressed512, dlen512, test512, XBZRLE_PAGE_SIZE);
491
- g_assert(rc512 < XBZRLE_PAGE_SIZE);
492
- g_assert(memcmp(test512, buffer512, XBZRLE_PAGE_SIZE) == 0);
493
-
494
- res->t_raw = time_val;
495
- res->t_512 = time_val512;
496
-
497
- g_free(buffer);
498
- g_free(compressed);
499
- g_free(test);
500
- g_free(buffer512);
501
- g_free(compressed512);
502
- g_free(test512);
503
-
504
-}
505
-
506
-static void test_encode_decode_avx512(void)
507
-{
508
- int i;
509
- float time_raw = 0.0, time_512 = 0.0;
510
- struct ResTime res;
511
- for (i = 0; i < 10000; i++) {
512
- encode_decode_range_avx512(&res);
513
- time_raw += res.t_raw;
514
- time_512 += res.t_512;
515
- }
516
- printf("Encode decode test:\n");
517
- printf("Raw xbzrle_encode time is %f ms\n", time_raw);
518
- printf("512 xbzrle_encode time is %f ms\n", time_512);
519
-}
520
-
521
-static void encode_decode_random(struct ResTime *res)
522
-{
523
- uint8_t *buffer = g_malloc0(XBZRLE_PAGE_SIZE);
524
- uint8_t *compressed = g_malloc(XBZRLE_PAGE_SIZE);
525
- uint8_t *test = g_malloc0(XBZRLE_PAGE_SIZE);
526
- uint8_t *buffer512 = g_malloc0(XBZRLE_PAGE_SIZE);
527
- uint8_t *compressed512 = g_malloc(XBZRLE_PAGE_SIZE);
528
- uint8_t *test512 = g_malloc0(XBZRLE_PAGE_SIZE);
529
- int i = 0, rc = 0, rc512 = 0;
530
- int dlen = 0, dlen512 = 0;
531
-
532
- int diff_len = g_test_rand_int_range(0, XBZRLE_PAGE_SIZE - 1);
533
- /* store the index of diff */
534
- int dirty_index[diff_len];
535
- for (int j = 0; j < diff_len; j++) {
536
- dirty_index[j] = g_test_rand_int_range(0, XBZRLE_PAGE_SIZE - 1);
537
- }
538
- for (i = diff_len - 1; i >= 0; i--) {
539
- buffer[dirty_index[i]] = i;
540
- test[dirty_index[i]] = i + 4;
541
- buffer512[dirty_index[i]] = i;
542
- test512[dirty_index[i]] = i + 4;
543
- }
544
-
545
- time_t t_start, t_end, t_start512, t_end512;
546
- t_start = clock();
547
- dlen = xbzrle_encode_buffer(test, buffer, XBZRLE_PAGE_SIZE, compressed,
548
- XBZRLE_PAGE_SIZE);
549
- t_end = clock();
550
- float time_val = difftime(t_end, t_start);
551
- rc = xbzrle_decode_buffer(compressed, dlen, test, XBZRLE_PAGE_SIZE);
552
- g_assert(rc < XBZRLE_PAGE_SIZE);
553
-
554
- t_start512 = clock();
555
- dlen512 = xbzrle_encode_buffer_avx512(test512, buffer512, XBZRLE_PAGE_SIZE,
556
- compressed512, XBZRLE_PAGE_SIZE);
557
- t_end512 = clock();
558
- float time_val512 = difftime(t_end512, t_start512);
559
- rc512 = xbzrle_decode_buffer(compressed512, dlen512, test512, XBZRLE_PAGE_SIZE);
560
- g_assert(rc512 < XBZRLE_PAGE_SIZE);
561
-
562
- res->t_raw = time_val;
563
- res->t_512 = time_val512;
564
-
565
- g_free(buffer);
566
- g_free(compressed);
567
- g_free(test);
568
- g_free(buffer512);
569
- g_free(compressed512);
570
- g_free(test512);
571
-
572
-}
573
-
574
-static void test_encode_decode_random_avx512(void)
575
-{
576
- int i;
577
- float time_raw = 0.0, time_512 = 0.0;
578
- struct ResTime res;
579
- for (i = 0; i < 10000; i++) {
580
- encode_decode_random(&res);
581
- time_raw += res.t_raw;
582
- time_512 += res.t_512;
583
- }
584
- printf("Random test:\n");
585
- printf("Raw xbzrle_encode time is %f ms\n", time_raw);
586
- printf("512 xbzrle_encode time is %f ms\n", time_512);
587
-}
588
-#endif
589
-
590
-int main(int argc, char **argv)
591
-{
592
- g_test_init(&argc, &argv, NULL);
593
- g_test_rand_int();
594
- #if defined(CONFIG_AVX512BW_OPT)
595
- if (likely(is_cpu_support_avx512bw)) {
596
- g_test_add_func("/xbzrle/encode_decode_zero", test_encode_decode_zero_avx512);
597
- g_test_add_func("/xbzrle/encode_decode_unchanged",
598
- test_encode_decode_unchanged_avx512);
599
- g_test_add_func("/xbzrle/encode_decode_1_byte", test_encode_decode_1_byte_avx512);
600
- g_test_add_func("/xbzrle/encode_decode_overflow",
601
- test_encode_decode_overflow_avx512);
602
- g_test_add_func("/xbzrle/encode_decode", test_encode_decode_avx512);
603
- g_test_add_func("/xbzrle/encode_decode_random", test_encode_decode_random_avx512);
604
- }
605
- #endif
606
- return g_test_run();
607
-}
608
diff --git a/tests/unit/test-xbzrle.c b/tests/unit/test-xbzrle.c
609
index XXXXXXX..XXXXXXX 100644
610
--- a/tests/unit/test-xbzrle.c
611
+++ b/tests/unit/test-xbzrle.c
612
@@ -XXX,XX +XXX,XX @@
613
614
#define XBZRLE_PAGE_SIZE 4096
615
616
-int (*xbzrle_encode_buffer_func)(uint8_t *, uint8_t *, int,
617
- uint8_t *, int) = xbzrle_encode_buffer;
618
-#if defined(CONFIG_AVX512BW_OPT)
619
-#include "qemu/cpuid.h"
620
-static void __attribute__((constructor)) init_cpu_flag(void)
621
-{
622
- unsigned max = __get_cpuid_max(0, NULL);
623
- int a, b, c, d;
624
- if (max >= 1) {
625
- __cpuid(1, a, b, c, d);
626
- /* We must check that AVX is not just available, but usable. */
627
- if ((c & bit_OSXSAVE) && (c & bit_AVX) && max >= 7) {
628
- int bv;
629
- __asm("xgetbv" : "=a"(bv), "=d"(d) : "c"(0));
630
- __cpuid_count(7, 0, a, b, c, d);
631
- /* 0xe6:
632
- * XCR0[7:5] = 111b (OPMASK state, upper 256-bit of ZMM0-ZMM15
633
- * and ZMM16-ZMM31 state are enabled by OS)
634
- * XCR0[2:1] = 11b (XMM state and YMM state are enabled by OS)
635
- */
636
- if ((bv & 0xe6) == 0xe6 && (b & bit_AVX512BW)) {
637
- xbzrle_encode_buffer_func = xbzrle_encode_buffer_avx512;
638
- }
639
- }
640
- }
641
- return ;
642
-}
643
-#endif
644
-
645
static void test_uleb(void)
30
{
646
{
31
return cs->interrupt_request & CPU_INTERRUPT_HARD;
647
uint32_t i, val;
32
@@ -XXX,XX +XXX,XX @@ static const struct SysemuCPUOps m68k_sysemu_ops = {
648
@@ -XXX,XX +XXX,XX @@ static void test_encode_decode_zero(void)
33
649
buffer[1000 + diff_len + 5] = 105;
34
static const struct TCGCPUOps m68k_tcg_ops = {
650
35
.initialize = m68k_tcg_init,
651
/* encode zero page */
36
+ .restore_state_to_opc = m68k_restore_state_to_opc,
652
- dlen = xbzrle_encode_buffer_func(buffer, buffer, XBZRLE_PAGE_SIZE, compressed,
37
653
- XBZRLE_PAGE_SIZE);
38
#ifndef CONFIG_USER_ONLY
654
+ dlen = xbzrle_encode_buffer(buffer, buffer, XBZRLE_PAGE_SIZE,
39
.tlb_fill = m68k_cpu_tlb_fill,
655
+ compressed, XBZRLE_PAGE_SIZE);
40
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
656
g_assert(dlen == 0);
657
658
g_free(buffer);
659
@@ -XXX,XX +XXX,XX @@ static void test_encode_decode_unchanged(void)
660
test[1000 + diff_len + 5] = 109;
661
662
/* test unchanged buffer */
663
- dlen = xbzrle_encode_buffer_func(test, test, XBZRLE_PAGE_SIZE, compressed,
664
- XBZRLE_PAGE_SIZE);
665
+ dlen = xbzrle_encode_buffer(test, test, XBZRLE_PAGE_SIZE,
666
+ compressed, XBZRLE_PAGE_SIZE);
667
g_assert(dlen == 0);
668
669
g_free(test);
670
@@ -XXX,XX +XXX,XX @@ static void test_encode_decode_1_byte(void)
671
672
test[XBZRLE_PAGE_SIZE - 1] = 1;
673
674
- dlen = xbzrle_encode_buffer_func(buffer, test, XBZRLE_PAGE_SIZE, compressed,
675
- XBZRLE_PAGE_SIZE);
676
+ dlen = xbzrle_encode_buffer(buffer, test, XBZRLE_PAGE_SIZE,
677
+ compressed, XBZRLE_PAGE_SIZE);
678
g_assert(dlen == (uleb128_encode_small(&buf[0], 4095) + 2));
679
680
rc = xbzrle_decode_buffer(compressed, dlen, buffer, XBZRLE_PAGE_SIZE);
681
@@ -XXX,XX +XXX,XX @@ static void test_encode_decode_overflow(void)
682
}
683
684
/* encode overflow */
685
- rc = xbzrle_encode_buffer_func(buffer, test, XBZRLE_PAGE_SIZE, compressed,
686
- XBZRLE_PAGE_SIZE);
687
+ rc = xbzrle_encode_buffer(buffer, test, XBZRLE_PAGE_SIZE,
688
+ compressed, XBZRLE_PAGE_SIZE);
689
g_assert(rc == -1);
690
691
g_free(buffer);
692
@@ -XXX,XX +XXX,XX @@ static void encode_decode_range(void)
693
test[1000 + diff_len + 5] = 109;
694
695
/* test encode/decode */
696
- dlen = xbzrle_encode_buffer_func(test, buffer, XBZRLE_PAGE_SIZE, compressed,
697
- XBZRLE_PAGE_SIZE);
698
+ dlen = xbzrle_encode_buffer(test, buffer, XBZRLE_PAGE_SIZE,
699
+ compressed, XBZRLE_PAGE_SIZE);
700
701
rc = xbzrle_decode_buffer(compressed, dlen, test, XBZRLE_PAGE_SIZE);
702
g_assert(rc < XBZRLE_PAGE_SIZE);
703
diff --git a/tests/bench/meson.build b/tests/bench/meson.build
41
index XXXXXXX..XXXXXXX 100644
704
index XXXXXXX..XXXXXXX 100644
42
--- a/target/m68k/translate.c
705
--- a/tests/bench/meson.build
43
+++ b/target/m68k/translate.c
706
+++ b/tests/bench/meson.build
44
@@ -XXX,XX +XXX,XX @@ void m68k_cpu_dump_state(CPUState *cs, FILE *f, int flags)
707
@@ -XXX,XX +XXX,XX @@ qht_bench = executable('qht-bench',
45
env->mmu.mmusr, env->mmu.ar);
708
sources: 'qht-bench.c',
46
#endif
709
dependencies: [qemuutil])
47
}
710
48
-
711
-if have_system
49
-void restore_state_to_opc(CPUM68KState *env, TranslationBlock *tb,
712
-xbzrle_bench = executable('xbzrle-bench',
50
- target_ulong *data)
713
- sources: 'xbzrle-bench.c',
51
-{
714
- dependencies: [qemuutil,migration])
52
- int cc_op = data[1];
715
-endif
53
- env->pc = data[0];
716
-
54
- if (cc_op != CC_OP_DYNAMIC) {
717
qtree_bench = executable('qtree-bench',
55
- env->cc_op = cc_op;
718
sources: 'qtree-bench.c',
56
- }
719
dependencies: [qemuutil])
57
-}
58
--
720
--
59
2.34.1
721
2.34.1
60
722
61
723
diff view generated by jsdifflib
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
1
The items in migration_files are built for libmigration and included
2
info softmmu_ss from there; no need to also include them directly.
3
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Juan Quintela <quintela@redhat.com>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
7
---
4
target/rx/cpu.c | 10 ++++++++++
8
migration/meson.build | 1 -
5
target/rx/translate.c | 6 ------
9
1 file changed, 1 deletion(-)
6
2 files changed, 10 insertions(+), 6 deletions(-)
7
10
8
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
11
diff --git a/migration/meson.build b/migration/meson.build
9
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
10
--- a/target/rx/cpu.c
13
--- a/migration/meson.build
11
+++ b/target/rx/cpu.c
14
+++ b/migration/meson.build
12
@@ -XXX,XX +XXX,XX @@ static void rx_cpu_synchronize_from_tb(CPUState *cs,
15
@@ -XXX,XX +XXX,XX @@ migration_files = files(
13
cpu->env.pc = tb_pc(tb);
16
'qemu-file.c',
14
}
17
'yank_functions.c',
15
18
)
16
+static void rx_restore_state_to_opc(CPUState *cs,
19
-softmmu_ss.add(migration_files)
17
+ const TranslationBlock *tb,
20
18
+ const uint64_t *data)
21
softmmu_ss.add(files(
19
+{
22
'block-dirty-bitmap.c',
20
+ RXCPU *cpu = RX_CPU(cs);
21
+
22
+ cpu->env.pc = data[0];
23
+}
24
+
25
static bool rx_cpu_has_work(CPUState *cs)
26
{
27
return cs->interrupt_request &
28
@@ -XXX,XX +XXX,XX @@ static const struct SysemuCPUOps rx_sysemu_ops = {
29
static const struct TCGCPUOps rx_tcg_ops = {
30
.initialize = rx_translate_init,
31
.synchronize_from_tb = rx_cpu_synchronize_from_tb,
32
+ .restore_state_to_opc = rx_restore_state_to_opc,
33
.tlb_fill = rx_cpu_tlb_fill,
34
35
#ifndef CONFIG_USER_ONLY
36
diff --git a/target/rx/translate.c b/target/rx/translate.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/rx/translate.c
39
+++ b/target/rx/translate.c
40
@@ -XXX,XX +XXX,XX @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
41
translator_loop(cs, tb, max_insns, pc, host_pc, &rx_tr_ops, &dc.base);
42
}
43
44
-void restore_state_to_opc(CPURXState *env, TranslationBlock *tb,
45
- target_ulong *data)
46
-{
47
- env->pc = data[0];
48
-}
49
-
50
#define ALLOC_REGISTER(sym, name) \
51
cpu_##sym = tcg_global_mem_new_i32(cpu_env, \
52
offsetof(CPURXState, sym), name)
53
--
23
--
54
2.34.1
24
2.34.1
55
25
56
26
diff view generated by jsdifflib
1
Move all of the TranslationBlock flushing and page linking
1
Move the code from tcg/. The only use of these bits so far
2
code from translate-all.c to tb-maint.c.
2
is with respect to the atomicity of tcg operations.
3
3
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
---
7
accel/tcg/internal.h | 55 +++
8
host/include/aarch64/host/cpuinfo.h | 22 ++++++++++
8
accel/tcg/tb-maint.c | 735 ++++++++++++++++++++++++++++++++++++
9
tcg/aarch64/tcg-target.h | 6 ++-
9
accel/tcg/translate-all.c | 766 +-------------------------------------
10
util/cpuinfo-aarch64.c | 67 +++++++++++++++++++++++++++++
10
accel/tcg/meson.build | 1 +
11
tcg/aarch64/tcg-target.c.inc | 40 -----------------
11
4 files changed, 802 insertions(+), 755 deletions(-)
12
util/meson.build | 4 +-
12
create mode 100644 accel/tcg/tb-maint.c
13
5 files changed, 96 insertions(+), 43 deletions(-)
13
14
create mode 100644 host/include/aarch64/host/cpuinfo.h
14
diff --git a/accel/tcg/internal.h b/accel/tcg/internal.h
15
create mode 100644 util/cpuinfo-aarch64.c
15
index XXXXXXX..XXXXXXX 100644
16
16
--- a/accel/tcg/internal.h
17
diff --git a/host/include/aarch64/host/cpuinfo.h b/host/include/aarch64/host/cpuinfo.h
17
+++ b/accel/tcg/internal.h
18
@@ -XXX,XX +XXX,XX @@ typedef struct PageDesc {
19
#endif
20
} PageDesc;
21
22
+/* Size of the L2 (and L3, etc) page tables. */
23
+#define V_L2_BITS 10
24
+#define V_L2_SIZE (1 << V_L2_BITS)
25
+
26
+/*
27
+ * L1 Mapping properties
28
+ */
29
+extern int v_l1_size;
30
+extern int v_l1_shift;
31
+extern int v_l2_levels;
32
+
33
+/*
34
+ * The bottom level has pointers to PageDesc, and is indexed by
35
+ * anything from 4 to (V_L2_BITS + 3) bits, depending on target page size.
36
+ */
37
+#define V_L1_MIN_BITS 4
38
+#define V_L1_MAX_BITS (V_L2_BITS + 3)
39
+#define V_L1_MAX_SIZE (1 << V_L1_MAX_BITS)
40
+
41
+extern void *l1_map[V_L1_MAX_SIZE];
42
+
43
PageDesc *page_find_alloc(tb_page_addr_t index, bool alloc);
44
45
static inline PageDesc *page_find(tb_page_addr_t index)
46
@@ -XXX,XX +XXX,XX @@ static inline PageDesc *page_find(tb_page_addr_t index)
47
return page_find_alloc(index, false);
48
}
49
50
+/* list iterators for lists of tagged pointers in TranslationBlock */
51
+#define TB_FOR_EACH_TAGGED(head, tb, n, field) \
52
+ for (n = (head) & 1, tb = (TranslationBlock *)((head) & ~1); \
53
+ tb; tb = (TranslationBlock *)tb->field[n], n = (uintptr_t)tb & 1, \
54
+ tb = (TranslationBlock *)((uintptr_t)tb & ~1))
55
+
56
+#define PAGE_FOR_EACH_TB(pagedesc, tb, n) \
57
+ TB_FOR_EACH_TAGGED((pagedesc)->first_tb, tb, n, page_next)
58
+
59
+#define TB_FOR_EACH_JMP(head_tb, tb, n) \
60
+ TB_FOR_EACH_TAGGED((head_tb)->jmp_list_head, tb, n, jmp_list_next)
61
+
62
+/* In user-mode page locks aren't used; mmap_lock is enough */
63
+#ifdef CONFIG_USER_ONLY
64
+#define assert_page_locked(pd) tcg_debug_assert(have_mmap_lock())
65
+static inline void page_lock(PageDesc *pd) { }
66
+static inline void page_unlock(PageDesc *pd) { }
67
+#else
68
+#ifdef CONFIG_DEBUG_TCG
69
+void do_assert_page_locked(const PageDesc *pd, const char *file, int line);
70
+#define assert_page_locked(pd) do_assert_page_locked(pd, __FILE__, __LINE__)
71
+#else
72
+#define assert_page_locked(pd)
73
+#endif
74
+void page_lock(PageDesc *pd);
75
+void page_unlock(PageDesc *pd);
76
+#endif
77
+
78
TranslationBlock *tb_gen_code(CPUState *cpu, target_ulong pc,
79
target_ulong cs_base, uint32_t flags,
80
int cflags);
81
G_NORETURN void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr);
82
void page_init(void);
83
void tb_htable_init(void);
84
+void tb_reset_jump(TranslationBlock *tb, int n);
85
+TranslationBlock *tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
86
+ tb_page_addr_t phys_page2);
87
+bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc);
88
+int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
89
+ uintptr_t searched_pc, bool reset_icount);
90
91
/* Return the current PC from CPU, which may be cached in TB. */
92
static inline target_ulong log_pc(CPUState *cpu, const TranslationBlock *tb)
93
diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c
94
new file mode 100644
18
new file mode 100644
95
index XXXXXXX..XXXXXXX
19
index XXXXXXX..XXXXXXX
96
--- /dev/null
20
--- /dev/null
97
+++ b/accel/tcg/tb-maint.c
21
+++ b/host/include/aarch64/host/cpuinfo.h
98
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@
99
+/*
23
+/*
100
+ * Translation Block Maintaince
24
+ * SPDX-License-Identifier: GPL-2.0-or-later
101
+ *
25
+ * Host specific cpu indentification for AArch64.
102
+ * Copyright (c) 2003 Fabrice Bellard
103
+ *
104
+ * This library is free software; you can redistribute it and/or
105
+ * modify it under the terms of the GNU Lesser General Public
106
+ * License as published by the Free Software Foundation; either
107
+ * version 2.1 of the License, or (at your option) any later version.
108
+ *
109
+ * This library is distributed in the hope that it will be useful,
110
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
111
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
112
+ * Lesser General Public License for more details.
113
+ *
114
+ * You should have received a copy of the GNU Lesser General Public
115
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
116
+ */
26
+ */
117
+
27
+
28
+#ifndef HOST_CPUINFO_H
29
+#define HOST_CPUINFO_H
30
+
31
+#define CPUINFO_ALWAYS (1u << 0) /* so cpuinfo is nonzero */
32
+#define CPUINFO_LSE (1u << 1)
33
+#define CPUINFO_LSE2 (1u << 2)
34
+
35
+/* Initialized with a constructor. */
36
+extern unsigned cpuinfo;
37
+
38
+/*
39
+ * We cannot rely on constructor ordering, so other constructors must
40
+ * use the function interface rather than the variable above.
41
+ */
42
+unsigned cpuinfo_init(void);
43
+
44
+#endif /* HOST_CPUINFO_H */
45
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/tcg/aarch64/tcg-target.h
48
+++ b/tcg/aarch64/tcg-target.h
49
@@ -XXX,XX +XXX,XX @@
50
#ifndef AARCH64_TCG_TARGET_H
51
#define AARCH64_TCG_TARGET_H
52
53
+#include "host/cpuinfo.h"
54
+
55
#define TCG_TARGET_INSN_UNIT_SIZE 4
56
#define TCG_TARGET_TLB_DISPLACEMENT_BITS 24
57
#define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1)
58
@@ -XXX,XX +XXX,XX @@ typedef enum {
59
#define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_EVEN
60
#define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL
61
62
-extern bool have_lse;
63
-extern bool have_lse2;
64
+#define have_lse (cpuinfo & CPUINFO_LSE)
65
+#define have_lse2 (cpuinfo & CPUINFO_LSE2)
66
67
/* optional instructions */
68
#define TCG_TARGET_HAS_div_i32 1
69
diff --git a/util/cpuinfo-aarch64.c b/util/cpuinfo-aarch64.c
70
new file mode 100644
71
index XXXXXXX..XXXXXXX
72
--- /dev/null
73
+++ b/util/cpuinfo-aarch64.c
74
@@ -XXX,XX +XXX,XX @@
75
+/*
76
+ * SPDX-License-Identifier: GPL-2.0-or-later
77
+ * Host specific cpu indentification for AArch64.
78
+ */
79
+
118
+#include "qemu/osdep.h"
80
+#include "qemu/osdep.h"
119
+#include "exec/cputlb.h"
81
+#include "host/cpuinfo.h"
120
+#include "exec/log.h"
82
+
121
+#include "exec/translate-all.h"
83
+#ifdef CONFIG_LINUX
122
+#include "sysemu/tcg.h"
84
+# ifdef CONFIG_GETAUXVAL
123
+#include "tcg/tcg.h"
85
+# include <sys/auxv.h>
124
+#include "tb-hash.h"
86
+# else
125
+#include "tb-context.h"
87
+# include <asm/hwcap.h>
126
+#include "internal.h"
88
+# include "elf.h"
127
+
89
+# endif
128
+/* FIXME: tb_invalidate_phys_range is declared in different places. */
90
+#endif
129
+#ifdef CONFIG_USER_ONLY
91
+#ifdef CONFIG_DARWIN
130
+#include "exec/exec-all.h"
92
+# include <sys/sysctl.h>
131
+#else
93
+#endif
132
+#include "exec/ram_addr.h"
94
+
133
+#endif
95
+unsigned cpuinfo;
134
+
96
+
135
+static bool tb_cmp(const void *ap, const void *bp)
97
+#ifdef CONFIG_DARWIN
98
+static bool sysctl_for_bool(const char *name)
136
+{
99
+{
137
+ const TranslationBlock *a = ap;
100
+ int val = 0;
138
+ const TranslationBlock *b = bp;
101
+ size_t len = sizeof(val);
139
+
102
+
140
+ return ((TARGET_TB_PCREL || tb_pc(a) == tb_pc(b)) &&
103
+ if (sysctlbyname(name, &val, &len, NULL, 0) == 0) {
141
+ a->cs_base == b->cs_base &&
104
+ return val != 0;
142
+ a->flags == b->flags &&
143
+ (tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) &&
144
+ a->trace_vcpu_dstate == b->trace_vcpu_dstate &&
145
+ a->page_addr[0] == b->page_addr[0] &&
146
+ a->page_addr[1] == b->page_addr[1]);
147
+}
148
+
149
+void tb_htable_init(void)
150
+{
151
+ unsigned int mode = QHT_MODE_AUTO_RESIZE;
152
+
153
+ qht_init(&tb_ctx.htable, tb_cmp, CODE_GEN_HTABLE_SIZE, mode);
154
+}
155
+
156
+/* Set to NULL all the 'first_tb' fields in all PageDescs. */
157
+static void page_flush_tb_1(int level, void **lp)
158
+{
159
+ int i;
160
+
161
+ if (*lp == NULL) {
162
+ return;
163
+ }
105
+ }
164
+ if (level == 0) {
106
+
165
+ PageDesc *pd = *lp;
166
+
167
+ for (i = 0; i < V_L2_SIZE; ++i) {
168
+ page_lock(&pd[i]);
169
+ pd[i].first_tb = (uintptr_t)NULL;
170
+ page_unlock(&pd[i]);
171
+ }
172
+ } else {
173
+ void **pp = *lp;
174
+
175
+ for (i = 0; i < V_L2_SIZE; ++i) {
176
+ page_flush_tb_1(level - 1, pp + i);
177
+ }
178
+ }
179
+}
180
+
181
+static void page_flush_tb(void)
182
+{
183
+ int i, l1_sz = v_l1_size;
184
+
185
+ for (i = 0; i < l1_sz; i++) {
186
+ page_flush_tb_1(v_l2_levels, l1_map + i);
187
+ }
188
+}
189
+
190
+/* flush all the translation blocks */
191
+static void do_tb_flush(CPUState *cpu, run_on_cpu_data tb_flush_count)
192
+{
193
+ bool did_flush = false;
194
+
195
+ mmap_lock();
196
+ /* If it is already been done on request of another CPU, just retry. */
197
+ if (tb_ctx.tb_flush_count != tb_flush_count.host_int) {
198
+ goto done;
199
+ }
200
+ did_flush = true;
201
+
202
+ CPU_FOREACH(cpu) {
203
+ tcg_flush_jmp_cache(cpu);
204
+ }
205
+
206
+ qht_reset_size(&tb_ctx.htable, CODE_GEN_HTABLE_SIZE);
207
+ page_flush_tb();
208
+
209
+ tcg_region_reset_all();
210
+ /* XXX: flush processor icache at this point if cache flush is expensive */
211
+ qatomic_mb_set(&tb_ctx.tb_flush_count, tb_ctx.tb_flush_count + 1);
212
+
213
+done:
214
+ mmap_unlock();
215
+ if (did_flush) {
216
+ qemu_plugin_flush_cb();
217
+ }
218
+}
219
+
220
+void tb_flush(CPUState *cpu)
221
+{
222
+ if (tcg_enabled()) {
223
+ unsigned tb_flush_count = qatomic_mb_read(&tb_ctx.tb_flush_count);
224
+
225
+ if (cpu_in_exclusive_context(cpu)) {
226
+ do_tb_flush(cpu, RUN_ON_CPU_HOST_INT(tb_flush_count));
227
+ } else {
228
+ async_safe_run_on_cpu(cpu, do_tb_flush,
229
+ RUN_ON_CPU_HOST_INT(tb_flush_count));
230
+ }
231
+ }
232
+}
233
+
234
+/*
235
+ * user-mode: call with mmap_lock held
236
+ * !user-mode: call with @pd->lock held
237
+ */
238
+static inline void tb_page_remove(PageDesc *pd, TranslationBlock *tb)
239
+{
240
+ TranslationBlock *tb1;
241
+ uintptr_t *pprev;
242
+ unsigned int n1;
243
+
244
+ assert_page_locked(pd);
245
+ pprev = &pd->first_tb;
246
+ PAGE_FOR_EACH_TB(pd, tb1, n1) {
247
+ if (tb1 == tb) {
248
+ *pprev = tb1->page_next[n1];
249
+ return;
250
+ }
251
+ pprev = &tb1->page_next[n1];
252
+ }
253
+ g_assert_not_reached();
254
+}
255
+
256
+/* remove @orig from its @n_orig-th jump list */
257
+static inline void tb_remove_from_jmp_list(TranslationBlock *orig, int n_orig)
258
+{
259
+ uintptr_t ptr, ptr_locked;
260
+ TranslationBlock *dest;
261
+ TranslationBlock *tb;
262
+ uintptr_t *pprev;
263
+ int n;
264
+
265
+ /* mark the LSB of jmp_dest[] so that no further jumps can be inserted */
266
+ ptr = qatomic_or_fetch(&orig->jmp_dest[n_orig], 1);
267
+ dest = (TranslationBlock *)(ptr & ~1);
268
+ if (dest == NULL) {
269
+ return;
270
+ }
271
+
272
+ qemu_spin_lock(&dest->jmp_lock);
273
+ /*
107
+ /*
274
+ * While acquiring the lock, the jump might have been removed if the
108
+ * We might in the future ask for properties not present in older kernels,
275
+ * destination TB was invalidated; check again.
109
+ * but we're only asking about static properties, all of which should be
110
+ * 'int'. So we shouln't see ENOMEM (val too small), or any of the other
111
+ * more exotic errors.
276
+ */
112
+ */
277
+ ptr_locked = qatomic_read(&orig->jmp_dest[n_orig]);
113
+ assert(errno == ENOENT);
278
+ if (ptr_locked != ptr) {
279
+ qemu_spin_unlock(&dest->jmp_lock);
280
+ /*
281
+ * The only possibility is that the jump was unlinked via
282
+ * tb_jump_unlink(dest). Seeing here another destination would be a bug,
283
+ * because we set the LSB above.
284
+ */
285
+ g_assert(ptr_locked == 1 && dest->cflags & CF_INVALID);
286
+ return;
287
+ }
288
+ /*
289
+ * We first acquired the lock, and since the destination pointer matches,
290
+ * we know for sure that @orig is in the jmp list.
291
+ */
292
+ pprev = &dest->jmp_list_head;
293
+ TB_FOR_EACH_JMP(dest, tb, n) {
294
+ if (tb == orig && n == n_orig) {
295
+ *pprev = tb->jmp_list_next[n];
296
+ /* no need to set orig->jmp_dest[n]; setting the LSB was enough */
297
+ qemu_spin_unlock(&dest->jmp_lock);
298
+ return;
299
+ }
300
+ pprev = &tb->jmp_list_next[n];
301
+ }
302
+ g_assert_not_reached();
303
+}
304
+
305
+/*
306
+ * Reset the jump entry 'n' of a TB so that it is not chained to another TB.
307
+ */
308
+void tb_reset_jump(TranslationBlock *tb, int n)
309
+{
310
+ uintptr_t addr = (uintptr_t)(tb->tc.ptr + tb->jmp_reset_offset[n]);
311
+ tb_set_jmp_target(tb, n, addr);
312
+}
313
+
314
+/* remove any jumps to the TB */
315
+static inline void tb_jmp_unlink(TranslationBlock *dest)
316
+{
317
+ TranslationBlock *tb;
318
+ int n;
319
+
320
+ qemu_spin_lock(&dest->jmp_lock);
321
+
322
+ TB_FOR_EACH_JMP(dest, tb, n) {
323
+ tb_reset_jump(tb, n);
324
+ qatomic_and(&tb->jmp_dest[n], (uintptr_t)NULL | 1);
325
+ /* No need to clear the list entry; setting the dest ptr is enough */
326
+ }
327
+ dest->jmp_list_head = (uintptr_t)NULL;
328
+
329
+ qemu_spin_unlock(&dest->jmp_lock);
330
+}
331
+
332
+static void tb_jmp_cache_inval_tb(TranslationBlock *tb)
333
+{
334
+ CPUState *cpu;
335
+
336
+ if (TARGET_TB_PCREL) {
337
+ /* A TB may be at any virtual address */
338
+ CPU_FOREACH(cpu) {
339
+ tcg_flush_jmp_cache(cpu);
340
+ }
341
+ } else {
342
+ uint32_t h = tb_jmp_cache_hash_func(tb_pc(tb));
343
+
344
+ CPU_FOREACH(cpu) {
345
+ CPUJumpCache *jc = cpu->tb_jmp_cache;
346
+
347
+ if (qatomic_read(&jc->array[h].tb) == tb) {
348
+ qatomic_set(&jc->array[h].tb, NULL);
349
+ }
350
+ }
351
+ }
352
+}
353
+
354
+/*
355
+ * In user-mode, call with mmap_lock held.
356
+ * In !user-mode, if @rm_from_page_list is set, call with the TB's pages'
357
+ * locks held.
358
+ */
359
+static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
360
+{
361
+ PageDesc *p;
362
+ uint32_t h;
363
+ tb_page_addr_t phys_pc;
364
+ uint32_t orig_cflags = tb_cflags(tb);
365
+
366
+ assert_memory_lock();
367
+
368
+ /* make sure no further incoming jumps will be chained to this TB */
369
+ qemu_spin_lock(&tb->jmp_lock);
370
+ qatomic_set(&tb->cflags, tb->cflags | CF_INVALID);
371
+ qemu_spin_unlock(&tb->jmp_lock);
372
+
373
+ /* remove the TB from the hash list */
374
+ phys_pc = tb->page_addr[0];
375
+ h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : tb_pc(tb)),
376
+ tb->flags, orig_cflags, tb->trace_vcpu_dstate);
377
+ if (!qht_remove(&tb_ctx.htable, tb, h)) {
378
+ return;
379
+ }
380
+
381
+ /* remove the TB from the page list */
382
+ if (rm_from_page_list) {
383
+ p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
384
+ tb_page_remove(p, tb);
385
+ if (tb->page_addr[1] != -1) {
386
+ p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
387
+ tb_page_remove(p, tb);
388
+ }
389
+ }
390
+
391
+ /* remove the TB from the hash list */
392
+ tb_jmp_cache_inval_tb(tb);
393
+
394
+ /* suppress this TB from the two jump lists */
395
+ tb_remove_from_jmp_list(tb, 0);
396
+ tb_remove_from_jmp_list(tb, 1);
397
+
398
+ /* suppress any remaining jumps to this TB */
399
+ tb_jmp_unlink(tb);
400
+
401
+ qatomic_set(&tb_ctx.tb_phys_invalidate_count,
402
+ tb_ctx.tb_phys_invalidate_count + 1);
403
+}
404
+
405
+static void tb_phys_invalidate__locked(TranslationBlock *tb)
406
+{
407
+ qemu_thread_jit_write();
408
+ do_tb_phys_invalidate(tb, true);
409
+ qemu_thread_jit_execute();
410
+}
411
+
412
+static void page_lock_pair(PageDesc **ret_p1, tb_page_addr_t phys1,
413
+ PageDesc **ret_p2, tb_page_addr_t phys2, bool alloc)
414
+{
415
+ PageDesc *p1, *p2;
416
+ tb_page_addr_t page1;
417
+ tb_page_addr_t page2;
418
+
419
+ assert_memory_lock();
420
+ g_assert(phys1 != -1);
421
+
422
+ page1 = phys1 >> TARGET_PAGE_BITS;
423
+ page2 = phys2 >> TARGET_PAGE_BITS;
424
+
425
+ p1 = page_find_alloc(page1, alloc);
426
+ if (ret_p1) {
427
+ *ret_p1 = p1;
428
+ }
429
+ if (likely(phys2 == -1)) {
430
+ page_lock(p1);
431
+ return;
432
+ } else if (page1 == page2) {
433
+ page_lock(p1);
434
+ if (ret_p2) {
435
+ *ret_p2 = p1;
436
+ }
437
+ return;
438
+ }
439
+ p2 = page_find_alloc(page2, alloc);
440
+ if (ret_p2) {
441
+ *ret_p2 = p2;
442
+ }
443
+ if (page1 < page2) {
444
+ page_lock(p1);
445
+ page_lock(p2);
446
+ } else {
447
+ page_lock(p2);
448
+ page_lock(p1);
449
+ }
450
+}
451
+
452
+#ifdef CONFIG_USER_ONLY
453
+static inline void page_lock_tb(const TranslationBlock *tb) { }
454
+static inline void page_unlock_tb(const TranslationBlock *tb) { }
455
+#else
456
+/* lock the page(s) of a TB in the correct acquisition order */
457
+static void page_lock_tb(const TranslationBlock *tb)
458
+{
459
+ page_lock_pair(NULL, tb->page_addr[0], NULL, tb->page_addr[1], false);
460
+}
461
+
462
+static void page_unlock_tb(const TranslationBlock *tb)
463
+{
464
+ PageDesc *p1 = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
465
+
466
+ page_unlock(p1);
467
+ if (unlikely(tb->page_addr[1] != -1)) {
468
+ PageDesc *p2 = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
469
+
470
+ if (p2 != p1) {
471
+ page_unlock(p2);
472
+ }
473
+ }
474
+}
475
+#endif
476
+
477
+/*
478
+ * Invalidate one TB.
479
+ * Called with mmap_lock held in user-mode.
480
+ */
481
+void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
482
+{
483
+ if (page_addr == -1 && tb->page_addr[0] != -1) {
484
+ page_lock_tb(tb);
485
+ do_tb_phys_invalidate(tb, true);
486
+ page_unlock_tb(tb);
487
+ } else {
488
+ do_tb_phys_invalidate(tb, false);
489
+ }
490
+}
491
+
492
+/*
493
+ * Add the tb in the target page and protect it if necessary.
494
+ * Called with mmap_lock held for user-mode emulation.
495
+ * Called with @p->lock held in !user-mode.
496
+ */
497
+static inline void tb_page_add(PageDesc *p, TranslationBlock *tb,
498
+ unsigned int n, tb_page_addr_t page_addr)
499
+{
500
+#ifndef CONFIG_USER_ONLY
501
+ bool page_already_protected;
502
+#endif
503
+
504
+ assert_page_locked(p);
505
+
506
+ tb->page_addr[n] = page_addr;
507
+ tb->page_next[n] = p->first_tb;
508
+#ifndef CONFIG_USER_ONLY
509
+ page_already_protected = p->first_tb != (uintptr_t)NULL;
510
+#endif
511
+ p->first_tb = (uintptr_t)tb | n;
512
+
513
+#if defined(CONFIG_USER_ONLY)
514
+ /* translator_loop() must have made all TB pages non-writable */
515
+ assert(!(p->flags & PAGE_WRITE));
516
+#else
517
+ /*
518
+ * If some code is already present, then the pages are already
519
+ * protected. So we handle the case where only the first TB is
520
+ * allocated in a physical page.
521
+ */
522
+ if (!page_already_protected) {
523
+ tlb_protect_code(page_addr);
524
+ }
525
+#endif
526
+}
527
+
528
+/*
529
+ * Add a new TB and link it to the physical page tables. phys_page2 is
530
+ * (-1) to indicate that only one page contains the TB.
531
+ *
532
+ * Called with mmap_lock held for user-mode emulation.
533
+ *
534
+ * Returns a pointer @tb, or a pointer to an existing TB that matches @tb.
535
+ * Note that in !user-mode, another thread might have already added a TB
536
+ * for the same block of guest code that @tb corresponds to. In that case,
537
+ * the caller should discard the original @tb, and use instead the returned TB.
538
+ */
539
+TranslationBlock *tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
540
+ tb_page_addr_t phys_page2)
541
+{
542
+ PageDesc *p;
543
+ PageDesc *p2 = NULL;
544
+ void *existing_tb = NULL;
545
+ uint32_t h;
546
+
547
+ assert_memory_lock();
548
+ tcg_debug_assert(!(tb->cflags & CF_INVALID));
549
+
550
+ /*
551
+ * Add the TB to the page list, acquiring first the pages's locks.
552
+ * We keep the locks held until after inserting the TB in the hash table,
553
+ * so that if the insertion fails we know for sure that the TBs are still
554
+ * in the page descriptors.
555
+ * Note that inserting into the hash table first isn't an option, since
556
+ * we can only insert TBs that are fully initialized.
557
+ */
558
+ page_lock_pair(&p, phys_pc, &p2, phys_page2, true);
559
+ tb_page_add(p, tb, 0, phys_pc);
560
+ if (p2) {
561
+ tb_page_add(p2, tb, 1, phys_page2);
562
+ } else {
563
+ tb->page_addr[1] = -1;
564
+ }
565
+
566
+ /* add in the hash table */
567
+ h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : tb_pc(tb)),
568
+ tb->flags, tb->cflags, tb->trace_vcpu_dstate);
569
+ qht_insert(&tb_ctx.htable, tb, h, &existing_tb);
570
+
571
+ /* remove TB from the page(s) if we couldn't insert it */
572
+ if (unlikely(existing_tb)) {
573
+ tb_page_remove(p, tb);
574
+ if (p2) {
575
+ tb_page_remove(p2, tb);
576
+ }
577
+ tb = existing_tb;
578
+ }
579
+
580
+ if (p2 && p2 != p) {
581
+ page_unlock(p2);
582
+ }
583
+ page_unlock(p);
584
+ return tb;
585
+}
586
+
587
+/*
588
+ * @p must be non-NULL.
589
+ * user-mode: call with mmap_lock held.
590
+ * !user-mode: call with all @pages locked.
591
+ */
592
+static void
593
+tb_invalidate_phys_page_range__locked(struct page_collection *pages,
594
+ PageDesc *p, tb_page_addr_t start,
595
+ tb_page_addr_t end,
596
+ uintptr_t retaddr)
597
+{
598
+ TranslationBlock *tb;
599
+ tb_page_addr_t tb_start, tb_end;
600
+ int n;
601
+#ifdef TARGET_HAS_PRECISE_SMC
602
+ CPUState *cpu = current_cpu;
603
+ CPUArchState *env = NULL;
604
+ bool current_tb_not_found = retaddr != 0;
605
+ bool current_tb_modified = false;
606
+ TranslationBlock *current_tb = NULL;
607
+ target_ulong current_pc = 0;
608
+ target_ulong current_cs_base = 0;
609
+ uint32_t current_flags = 0;
610
+#endif /* TARGET_HAS_PRECISE_SMC */
611
+
612
+ assert_page_locked(p);
613
+
614
+#if defined(TARGET_HAS_PRECISE_SMC)
615
+ if (cpu != NULL) {
616
+ env = cpu->env_ptr;
617
+ }
618
+#endif
619
+
620
+ /*
621
+ * We remove all the TBs in the range [start, end[.
622
+ * XXX: see if in some cases it could be faster to invalidate all the code
623
+ */
624
+ PAGE_FOR_EACH_TB(p, tb, n) {
625
+ assert_page_locked(p);
626
+ /* NOTE: this is subtle as a TB may span two physical pages */
627
+ if (n == 0) {
628
+ /* NOTE: tb_end may be after the end of the page, but
629
+ it is not a problem */
630
+ tb_start = tb->page_addr[0];
631
+ tb_end = tb_start + tb->size;
632
+ } else {
633
+ tb_start = tb->page_addr[1];
634
+ tb_end = tb_start + ((tb->page_addr[0] + tb->size)
635
+ & ~TARGET_PAGE_MASK);
636
+ }
637
+ if (!(tb_end <= start || tb_start >= end)) {
638
+#ifdef TARGET_HAS_PRECISE_SMC
639
+ if (current_tb_not_found) {
640
+ current_tb_not_found = false;
641
+ /* now we have a real cpu fault */
642
+ current_tb = tcg_tb_lookup(retaddr);
643
+ }
644
+ if (current_tb == tb &&
645
+ (tb_cflags(current_tb) & CF_COUNT_MASK) != 1) {
646
+ /*
647
+ * If we are modifying the current TB, we must stop
648
+ * its execution. We could be more precise by checking
649
+ * that the modification is after the current PC, but it
650
+ * would require a specialized function to partially
651
+ * restore the CPU state.
652
+ */
653
+ current_tb_modified = true;
654
+ cpu_restore_state_from_tb(cpu, current_tb, retaddr, true);
655
+ cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
656
+ &current_flags);
657
+ }
658
+#endif /* TARGET_HAS_PRECISE_SMC */
659
+ tb_phys_invalidate__locked(tb);
660
+ }
661
+ }
662
+#if !defined(CONFIG_USER_ONLY)
663
+ /* if no code remaining, no need to continue to use slow writes */
664
+ if (!p->first_tb) {
665
+ tlb_unprotect_code(start);
666
+ }
667
+#endif
668
+#ifdef TARGET_HAS_PRECISE_SMC
669
+ if (current_tb_modified) {
670
+ page_collection_unlock(pages);
671
+ /* Force execution of one insn next time. */
672
+ cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(cpu);
673
+ mmap_unlock();
674
+ cpu_loop_exit_noexc(cpu);
675
+ }
676
+#endif
677
+}
678
+
679
+/*
680
+ * Invalidate all TBs which intersect with the target physical address range
681
+ * [start;end[. NOTE: start and end must refer to the *same* physical page.
682
+ * 'is_cpu_write_access' should be true if called from a real cpu write
683
+ * access: the virtual CPU will exit the current TB if code is modified inside
684
+ * this TB.
685
+ *
686
+ * Called with mmap_lock held for user-mode emulation
687
+ */
688
+void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end)
689
+{
690
+ struct page_collection *pages;
691
+ PageDesc *p;
692
+
693
+ assert_memory_lock();
694
+
695
+ p = page_find(start >> TARGET_PAGE_BITS);
696
+ if (p == NULL) {
697
+ return;
698
+ }
699
+ pages = page_collection_lock(start, end);
700
+ tb_invalidate_phys_page_range__locked(pages, p, start, end, 0);
701
+ page_collection_unlock(pages);
702
+}
703
+
704
+/*
705
+ * Invalidate all TBs which intersect with the target physical address range
706
+ * [start;end[. NOTE: start and end may refer to *different* physical pages.
707
+ * 'is_cpu_write_access' should be true if called from a real cpu write
708
+ * access: the virtual CPU will exit the current TB if code is modified inside
709
+ * this TB.
710
+ *
711
+ * Called with mmap_lock held for user-mode emulation.
712
+ */
713
+#ifdef CONFIG_SOFTMMU
714
+void tb_invalidate_phys_range(ram_addr_t start, ram_addr_t end)
715
+#else
716
+void tb_invalidate_phys_range(target_ulong start, target_ulong end)
717
+#endif
718
+{
719
+ struct page_collection *pages;
720
+ tb_page_addr_t next;
721
+
722
+ assert_memory_lock();
723
+
724
+ pages = page_collection_lock(start, end);
725
+ for (next = (start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
726
+ start < end;
727
+ start = next, next += TARGET_PAGE_SIZE) {
728
+ PageDesc *pd = page_find(start >> TARGET_PAGE_BITS);
729
+ tb_page_addr_t bound = MIN(next, end);
730
+
731
+ if (pd == NULL) {
732
+ continue;
733
+ }
734
+ tb_invalidate_phys_page_range__locked(pages, pd, start, bound, 0);
735
+ }
736
+ page_collection_unlock(pages);
737
+}
738
+
739
+#ifdef CONFIG_SOFTMMU
740
+/*
741
+ * len must be <= 8 and start must be a multiple of len.
742
+ * Called via softmmu_template.h when code areas are written to with
743
+ * iothread mutex not held.
744
+ *
745
+ * Call with all @pages in the range [@start, @start + len[ locked.
746
+ */
747
+void tb_invalidate_phys_page_fast(struct page_collection *pages,
748
+ tb_page_addr_t start, int len,
749
+ uintptr_t retaddr)
750
+{
751
+ PageDesc *p;
752
+
753
+ assert_memory_lock();
754
+
755
+ p = page_find(start >> TARGET_PAGE_BITS);
756
+ if (!p) {
757
+ return;
758
+ }
759
+
760
+ assert_page_locked(p);
761
+ tb_invalidate_phys_page_range__locked(pages, p, start, start + len,
762
+ retaddr);
763
+}
764
+#else
765
+/*
766
+ * Called with mmap_lock held. If pc is not 0 then it indicates the
767
+ * host PC of the faulting store instruction that caused this invalidate.
768
+ * Returns true if the caller needs to abort execution of the current
769
+ * TB (because it was modified by this store and the guest CPU has
770
+ * precise-SMC semantics).
771
+ */
772
+bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc)
773
+{
774
+ TranslationBlock *tb;
775
+ PageDesc *p;
776
+ int n;
777
+#ifdef TARGET_HAS_PRECISE_SMC
778
+ TranslationBlock *current_tb = NULL;
779
+ CPUState *cpu = current_cpu;
780
+ CPUArchState *env = NULL;
781
+ int current_tb_modified = 0;
782
+ target_ulong current_pc = 0;
783
+ target_ulong current_cs_base = 0;
784
+ uint32_t current_flags = 0;
785
+#endif
786
+
787
+ assert_memory_lock();
788
+
789
+ addr &= TARGET_PAGE_MASK;
790
+ p = page_find(addr >> TARGET_PAGE_BITS);
791
+ if (!p) {
792
+ return false;
793
+ }
794
+
795
+#ifdef TARGET_HAS_PRECISE_SMC
796
+ if (p->first_tb && pc != 0) {
797
+ current_tb = tcg_tb_lookup(pc);
798
+ }
799
+ if (cpu != NULL) {
800
+ env = cpu->env_ptr;
801
+ }
802
+#endif
803
+ assert_page_locked(p);
804
+ PAGE_FOR_EACH_TB(p, tb, n) {
805
+#ifdef TARGET_HAS_PRECISE_SMC
806
+ if (current_tb == tb &&
807
+ (tb_cflags(current_tb) & CF_COUNT_MASK) != 1) {
808
+ /*
809
+ * If we are modifying the current TB, we must stop its execution.
810
+ * We could be more precise by checking that the modification is
811
+ * after the current PC, but it would require a specialized
812
+ * function to partially restore the CPU state.
813
+ */
814
+ current_tb_modified = 1;
815
+ cpu_restore_state_from_tb(cpu, current_tb, pc, true);
816
+ cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
817
+ &current_flags);
818
+ }
819
+#endif /* TARGET_HAS_PRECISE_SMC */
820
+ tb_phys_invalidate(tb, addr);
821
+ }
822
+ p->first_tb = (uintptr_t)NULL;
823
+#ifdef TARGET_HAS_PRECISE_SMC
824
+ if (current_tb_modified) {
825
+ /* Force execution of one insn next time. */
826
+ cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(cpu);
827
+ return true;
828
+ }
829
+#endif
830
+
831
+ return false;
114
+ return false;
832
+}
115
+}
833
+#endif
116
+#endif
834
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
117
+
118
+/* Called both as constructor and (possibly) via other constructors. */
119
+unsigned __attribute__((constructor)) cpuinfo_init(void)
120
+{
121
+ unsigned info = cpuinfo;
122
+
123
+ if (info) {
124
+ return info;
125
+ }
126
+
127
+ info = CPUINFO_ALWAYS;
128
+
129
+#ifdef CONFIG_LINUX
130
+ unsigned long hwcap = qemu_getauxval(AT_HWCAP);
131
+ info |= (hwcap & HWCAP_ATOMICS ? CPUINFO_LSE : 0);
132
+ info |= (hwcap & HWCAP_USCAT ? CPUINFO_LSE2 : 0);
133
+#endif
134
+#ifdef CONFIG_DARWIN
135
+ info |= sysctl_for_bool("hw.optional.arm.FEAT_LSE") * CPUINFO_LSE;
136
+ info |= sysctl_for_bool("hw.optional.arm.FEAT_LSE2") * CPUINFO_LSE2;
137
+#endif
138
+
139
+ cpuinfo = info;
140
+ return info;
141
+}
142
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
835
index XXXXXXX..XXXXXXX 100644
143
index XXXXXXX..XXXXXXX 100644
836
--- a/accel/tcg/translate-all.c
144
--- a/tcg/aarch64/tcg-target.c.inc
837
+++ b/accel/tcg/translate-all.c
145
+++ b/tcg/aarch64/tcg-target.c.inc
838
@@ -XXX,XX +XXX,XX @@ struct page_collection {
146
@@ -XXX,XX +XXX,XX @@
839
struct page_entry *max;
147
#include "../tcg-ldst.c.inc"
840
};
148
#include "../tcg-pool.c.inc"
841
149
#include "qemu/bitops.h"
842
-/* list iterators for lists of tagged pointers in TranslationBlock */
150
-#ifdef __linux__
843
-#define TB_FOR_EACH_TAGGED(head, tb, n, field) \
151
-#include <asm/hwcap.h>
844
- for (n = (head) & 1, tb = (TranslationBlock *)((head) & ~1); \
152
-#endif
845
- tb; tb = (TranslationBlock *)tb->field[n], n = (uintptr_t)tb & 1, \
153
-#ifdef CONFIG_DARWIN
846
- tb = (TranslationBlock *)((uintptr_t)tb & ~1))
154
-#include <sys/sysctl.h>
847
-
155
-#endif
848
-#define PAGE_FOR_EACH_TB(pagedesc, tb, n) \
156
849
- TB_FOR_EACH_TAGGED((pagedesc)->first_tb, tb, n, page_next)
157
/* We're going to re-use TCGType in setting of the SF bit, which controls
850
-
158
the size of the operation performed. If we know the values match, it
851
-#define TB_FOR_EACH_JMP(head_tb, tb, n) \
159
@@ -XXX,XX +XXX,XX @@ static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
852
- TB_FOR_EACH_TAGGED((head_tb)->jmp_list_head, tb, n, jmp_list_next)
160
return TCG_REG_X0 + slot;
853
-
854
/*
855
* In system mode we want L1_MAP to be based on ram offsets,
856
* while in user mode we want it to be based on virtual addresses.
857
@@ -XXX,XX +XXX,XX @@ struct page_collection {
858
# define L1_MAP_ADDR_SPACE_BITS MIN(HOST_LONG_BITS, TARGET_ABI_BITS)
859
#endif
860
861
-/* Size of the L2 (and L3, etc) page tables. */
862
-#define V_L2_BITS 10
863
-#define V_L2_SIZE (1 << V_L2_BITS)
864
-
865
/* Make sure all possible CPU event bits fit in tb->trace_vcpu_dstate */
866
QEMU_BUILD_BUG_ON(CPU_TRACE_DSTATE_MAX_EVENTS >
867
sizeof_field(TranslationBlock, trace_vcpu_dstate)
868
@@ -XXX,XX +XXX,XX @@ QEMU_BUILD_BUG_ON(CPU_TRACE_DSTATE_MAX_EVENTS >
869
/*
870
* L1 Mapping properties
871
*/
872
-static int v_l1_size;
873
-static int v_l1_shift;
874
-static int v_l2_levels;
875
+int v_l1_size;
876
+int v_l1_shift;
877
+int v_l2_levels;
878
879
-/* The bottom level has pointers to PageDesc, and is indexed by
880
- * anything from 4 to (V_L2_BITS + 3) bits, depending on target page size.
881
- */
882
-#define V_L1_MIN_BITS 4
883
-#define V_L1_MAX_BITS (V_L2_BITS + 3)
884
-#define V_L1_MAX_SIZE (1 << V_L1_MAX_BITS)
885
-
886
-static void *l1_map[V_L1_MAX_SIZE];
887
+void *l1_map[V_L1_MAX_SIZE];
888
889
TBContext tb_ctx;
890
891
@@ -XXX,XX +XXX,XX @@ static int encode_search(TranslationBlock *tb, uint8_t *block)
892
* When reset_icount is true, current TB will be interrupted and
893
* icount should be recalculated.
894
*/
895
-static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
896
- uintptr_t searched_pc, bool reset_icount)
897
+int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
898
+ uintptr_t searched_pc, bool reset_icount)
899
{
900
target_ulong data[TARGET_INSN_START_WORDS];
901
uintptr_t host_pc = (uintptr_t)tb->tc.ptr;
902
@@ -XXX,XX +XXX,XX @@ PageDesc *page_find_alloc(tb_page_addr_t index, bool alloc)
903
return pd + (index & (V_L2_SIZE - 1));
904
}
161
}
905
162
906
-static void page_lock_pair(PageDesc **ret_p1, tb_page_addr_t phys1,
163
-bool have_lse;
907
- PageDesc **ret_p2, tb_page_addr_t phys2, bool alloc);
164
-bool have_lse2;
908
-
165
-
909
/* In user-mode page locks aren't used; mmap_lock is enough */
166
#define TCG_REG_TMP TCG_REG_X30
910
#ifdef CONFIG_USER_ONLY
167
#define TCG_VEC_TMP TCG_REG_V31
911
-
168
912
-#define assert_page_locked(pd) tcg_debug_assert(have_mmap_lock())
169
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
913
-
914
-static inline void page_lock(PageDesc *pd)
915
-{ }
916
-
917
-static inline void page_unlock(PageDesc *pd)
918
-{ }
919
-
920
-static inline void page_lock_tb(const TranslationBlock *tb)
921
-{ }
922
-
923
-static inline void page_unlock_tb(const TranslationBlock *tb)
924
-{ }
925
-
926
struct page_collection *
927
page_collection_lock(tb_page_addr_t start, tb_page_addr_t end)
928
{
929
@@ -XXX,XX +XXX,XX @@ static void page_unlock__debug(const PageDesc *pd)
930
g_assert(removed);
931
}
932
933
-static void
934
-do_assert_page_locked(const PageDesc *pd, const char *file, int line)
935
+void do_assert_page_locked(const PageDesc *pd, const char *file, int line)
936
{
937
if (unlikely(!page_is_locked(pd))) {
938
error_report("assert_page_lock: PageDesc %p not locked @ %s:%d",
939
@@ -XXX,XX +XXX,XX @@ do_assert_page_locked(const PageDesc *pd, const char *file, int line)
940
}
170
}
941
}
171
}
942
172
943
-#define assert_page_locked(pd) do_assert_page_locked(pd, __FILE__, __LINE__)
173
-#ifdef CONFIG_DARWIN
944
-
174
-static bool sysctl_for_bool(const char *name)
945
void assert_no_pages_locked(void)
946
{
947
ht_pages_locked_debug_init();
948
@@ -XXX,XX +XXX,XX @@ void assert_no_pages_locked(void)
949
950
#else /* !CONFIG_DEBUG_TCG */
951
952
-#define assert_page_locked(pd)
953
-
954
-static inline void page_lock__debug(const PageDesc *pd)
955
-{
175
-{
956
-}
176
- int val = 0;
957
-
177
- size_t len = sizeof(val);
958
-static inline void page_unlock__debug(const PageDesc *pd)
178
-
959
-{
179
- if (sysctlbyname(name, &val, &len, NULL, 0) == 0) {
960
-}
180
- return val != 0;
961
+static inline void page_lock__debug(const PageDesc *pd) { }
962
+static inline void page_unlock__debug(const PageDesc *pd) { }
963
964
#endif /* CONFIG_DEBUG_TCG */
965
966
-static inline void page_lock(PageDesc *pd)
967
+void page_lock(PageDesc *pd)
968
{
969
page_lock__debug(pd);
970
qemu_spin_lock(&pd->lock);
971
}
972
973
-static inline void page_unlock(PageDesc *pd)
974
+void page_unlock(PageDesc *pd)
975
{
976
qemu_spin_unlock(&pd->lock);
977
page_unlock__debug(pd);
978
}
979
980
-/* lock the page(s) of a TB in the correct acquisition order */
981
-static inline void page_lock_tb(const TranslationBlock *tb)
982
-{
983
- page_lock_pair(NULL, tb->page_addr[0], NULL, tb->page_addr[1], false);
984
-}
985
-
986
-static inline void page_unlock_tb(const TranslationBlock *tb)
987
-{
988
- PageDesc *p1 = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
989
-
990
- page_unlock(p1);
991
- if (unlikely(tb->page_addr[1] != -1)) {
992
- PageDesc *p2 = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
993
-
994
- if (p2 != p1) {
995
- page_unlock(p2);
996
- }
997
- }
181
- }
998
-}
182
-
999
-
183
- /*
1000
static inline struct page_entry *
184
- * We might in the future ask for properties not present in older kernels,
1001
page_entry_new(PageDesc *pd, tb_page_addr_t index)
185
- * but we're only asking about static properties, all of which should be
1002
{
186
- * 'int'. So we shouln't see ENOMEM (val too small), or any of the other
1003
@@ -XXX,XX +XXX,XX @@ void page_collection_unlock(struct page_collection *set)
187
- * more exotic errors.
1004
1005
#endif /* !CONFIG_USER_ONLY */
1006
1007
-static void page_lock_pair(PageDesc **ret_p1, tb_page_addr_t phys1,
1008
- PageDesc **ret_p2, tb_page_addr_t phys2, bool alloc)
1009
-{
1010
- PageDesc *p1, *p2;
1011
- tb_page_addr_t page1;
1012
- tb_page_addr_t page2;
1013
-
1014
- assert_memory_lock();
1015
- g_assert(phys1 != -1);
1016
-
1017
- page1 = phys1 >> TARGET_PAGE_BITS;
1018
- page2 = phys2 >> TARGET_PAGE_BITS;
1019
-
1020
- p1 = page_find_alloc(page1, alloc);
1021
- if (ret_p1) {
1022
- *ret_p1 = p1;
1023
- }
1024
- if (likely(phys2 == -1)) {
1025
- page_lock(p1);
1026
- return;
1027
- } else if (page1 == page2) {
1028
- page_lock(p1);
1029
- if (ret_p2) {
1030
- *ret_p2 = p1;
1031
- }
1032
- return;
1033
- }
1034
- p2 = page_find_alloc(page2, alloc);
1035
- if (ret_p2) {
1036
- *ret_p2 = p2;
1037
- }
1038
- if (page1 < page2) {
1039
- page_lock(p1);
1040
- page_lock(p2);
1041
- } else {
1042
- page_lock(p2);
1043
- page_lock(p1);
1044
- }
1045
-}
1046
-
1047
-static bool tb_cmp(const void *ap, const void *bp)
1048
-{
1049
- const TranslationBlock *a = ap;
1050
- const TranslationBlock *b = bp;
1051
-
1052
- return ((TARGET_TB_PCREL || tb_pc(a) == tb_pc(b)) &&
1053
- a->cs_base == b->cs_base &&
1054
- a->flags == b->flags &&
1055
- (tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) &&
1056
- a->trace_vcpu_dstate == b->trace_vcpu_dstate &&
1057
- a->page_addr[0] == b->page_addr[0] &&
1058
- a->page_addr[1] == b->page_addr[1]);
1059
-}
1060
-
1061
-void tb_htable_init(void)
1062
-{
1063
- unsigned int mode = QHT_MODE_AUTO_RESIZE;
1064
-
1065
- qht_init(&tb_ctx.htable, tb_cmp, CODE_GEN_HTABLE_SIZE, mode);
1066
-}
1067
-
1068
-/* Set to NULL all the 'first_tb' fields in all PageDescs. */
1069
-static void page_flush_tb_1(int level, void **lp)
1070
-{
1071
- int i;
1072
-
1073
- if (*lp == NULL) {
1074
- return;
1075
- }
1076
- if (level == 0) {
1077
- PageDesc *pd = *lp;
1078
-
1079
- for (i = 0; i < V_L2_SIZE; ++i) {
1080
- page_lock(&pd[i]);
1081
- pd[i].first_tb = (uintptr_t)NULL;
1082
- page_unlock(&pd[i]);
1083
- }
1084
- } else {
1085
- void **pp = *lp;
1086
-
1087
- for (i = 0; i < V_L2_SIZE; ++i) {
1088
- page_flush_tb_1(level - 1, pp + i);
1089
- }
1090
- }
1091
-}
1092
-
1093
-static void page_flush_tb(void)
1094
-{
1095
- int i, l1_sz = v_l1_size;
1096
-
1097
- for (i = 0; i < l1_sz; i++) {
1098
- page_flush_tb_1(v_l2_levels, l1_map + i);
1099
- }
1100
-}
1101
-
1102
-/* flush all the translation blocks */
1103
-static void do_tb_flush(CPUState *cpu, run_on_cpu_data tb_flush_count)
1104
-{
1105
- bool did_flush = false;
1106
-
1107
- mmap_lock();
1108
- /* If it is already been done on request of another CPU,
1109
- * just retry.
1110
- */
188
- */
1111
- if (tb_ctx.tb_flush_count != tb_flush_count.host_int) {
189
- assert(errno == ENOENT);
1112
- goto done;
1113
- }
1114
- did_flush = true;
1115
-
1116
- CPU_FOREACH(cpu) {
1117
- tcg_flush_jmp_cache(cpu);
1118
- }
1119
-
1120
- qht_reset_size(&tb_ctx.htable, CODE_GEN_HTABLE_SIZE);
1121
- page_flush_tb();
1122
-
1123
- tcg_region_reset_all();
1124
- /* XXX: flush processor icache at this point if cache flush is
1125
- expensive */
1126
- qatomic_mb_set(&tb_ctx.tb_flush_count, tb_ctx.tb_flush_count + 1);
1127
-
1128
-done:
1129
- mmap_unlock();
1130
- if (did_flush) {
1131
- qemu_plugin_flush_cb();
1132
- }
1133
-}
1134
-
1135
-void tb_flush(CPUState *cpu)
1136
-{
1137
- if (tcg_enabled()) {
1138
- unsigned tb_flush_count = qatomic_mb_read(&tb_ctx.tb_flush_count);
1139
-
1140
- if (cpu_in_exclusive_context(cpu)) {
1141
- do_tb_flush(cpu, RUN_ON_CPU_HOST_INT(tb_flush_count));
1142
- } else {
1143
- async_safe_run_on_cpu(cpu, do_tb_flush,
1144
- RUN_ON_CPU_HOST_INT(tb_flush_count));
1145
- }
1146
- }
1147
-}
1148
-
1149
-/*
1150
- * user-mode: call with mmap_lock held
1151
- * !user-mode: call with @pd->lock held
1152
- */
1153
-static inline void tb_page_remove(PageDesc *pd, TranslationBlock *tb)
1154
-{
1155
- TranslationBlock *tb1;
1156
- uintptr_t *pprev;
1157
- unsigned int n1;
1158
-
1159
- assert_page_locked(pd);
1160
- pprev = &pd->first_tb;
1161
- PAGE_FOR_EACH_TB(pd, tb1, n1) {
1162
- if (tb1 == tb) {
1163
- *pprev = tb1->page_next[n1];
1164
- return;
1165
- }
1166
- pprev = &tb1->page_next[n1];
1167
- }
1168
- g_assert_not_reached();
1169
-}
1170
-
1171
-/* remove @orig from its @n_orig-th jump list */
1172
-static inline void tb_remove_from_jmp_list(TranslationBlock *orig, int n_orig)
1173
-{
1174
- uintptr_t ptr, ptr_locked;
1175
- TranslationBlock *dest;
1176
- TranslationBlock *tb;
1177
- uintptr_t *pprev;
1178
- int n;
1179
-
1180
- /* mark the LSB of jmp_dest[] so that no further jumps can be inserted */
1181
- ptr = qatomic_or_fetch(&orig->jmp_dest[n_orig], 1);
1182
- dest = (TranslationBlock *)(ptr & ~1);
1183
- if (dest == NULL) {
1184
- return;
1185
- }
1186
-
1187
- qemu_spin_lock(&dest->jmp_lock);
1188
- /*
1189
- * While acquiring the lock, the jump might have been removed if the
1190
- * destination TB was invalidated; check again.
1191
- */
1192
- ptr_locked = qatomic_read(&orig->jmp_dest[n_orig]);
1193
- if (ptr_locked != ptr) {
1194
- qemu_spin_unlock(&dest->jmp_lock);
1195
- /*
1196
- * The only possibility is that the jump was unlinked via
1197
- * tb_jump_unlink(dest). Seeing here another destination would be a bug,
1198
- * because we set the LSB above.
1199
- */
1200
- g_assert(ptr_locked == 1 && dest->cflags & CF_INVALID);
1201
- return;
1202
- }
1203
- /*
1204
- * We first acquired the lock, and since the destination pointer matches,
1205
- * we know for sure that @orig is in the jmp list.
1206
- */
1207
- pprev = &dest->jmp_list_head;
1208
- TB_FOR_EACH_JMP(dest, tb, n) {
1209
- if (tb == orig && n == n_orig) {
1210
- *pprev = tb->jmp_list_next[n];
1211
- /* no need to set orig->jmp_dest[n]; setting the LSB was enough */
1212
- qemu_spin_unlock(&dest->jmp_lock);
1213
- return;
1214
- }
1215
- pprev = &tb->jmp_list_next[n];
1216
- }
1217
- g_assert_not_reached();
1218
-}
1219
-
1220
-/* reset the jump entry 'n' of a TB so that it is not chained to
1221
- another TB */
1222
-static inline void tb_reset_jump(TranslationBlock *tb, int n)
1223
-{
1224
- uintptr_t addr = (uintptr_t)(tb->tc.ptr + tb->jmp_reset_offset[n]);
1225
- tb_set_jmp_target(tb, n, addr);
1226
-}
1227
-
1228
-/* remove any jumps to the TB */
1229
-static inline void tb_jmp_unlink(TranslationBlock *dest)
1230
-{
1231
- TranslationBlock *tb;
1232
- int n;
1233
-
1234
- qemu_spin_lock(&dest->jmp_lock);
1235
-
1236
- TB_FOR_EACH_JMP(dest, tb, n) {
1237
- tb_reset_jump(tb, n);
1238
- qatomic_and(&tb->jmp_dest[n], (uintptr_t)NULL | 1);
1239
- /* No need to clear the list entry; setting the dest ptr is enough */
1240
- }
1241
- dest->jmp_list_head = (uintptr_t)NULL;
1242
-
1243
- qemu_spin_unlock(&dest->jmp_lock);
1244
-}
1245
-
1246
-static void tb_jmp_cache_inval_tb(TranslationBlock *tb)
1247
-{
1248
- CPUState *cpu;
1249
-
1250
- if (TARGET_TB_PCREL) {
1251
- /* A TB may be at any virtual address */
1252
- CPU_FOREACH(cpu) {
1253
- tcg_flush_jmp_cache(cpu);
1254
- }
1255
- } else {
1256
- uint32_t h = tb_jmp_cache_hash_func(tb_pc(tb));
1257
-
1258
- CPU_FOREACH(cpu) {
1259
- CPUJumpCache *jc = cpu->tb_jmp_cache;
1260
-
1261
- if (qatomic_read(&jc->array[h].tb) == tb) {
1262
- qatomic_set(&jc->array[h].tb, NULL);
1263
- }
1264
- }
1265
- }
1266
-}
1267
-
1268
-/*
1269
- * In user-mode, call with mmap_lock held.
1270
- * In !user-mode, if @rm_from_page_list is set, call with the TB's pages'
1271
- * locks held.
1272
- */
1273
-static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
1274
-{
1275
- PageDesc *p;
1276
- uint32_t h;
1277
- tb_page_addr_t phys_pc;
1278
- uint32_t orig_cflags = tb_cflags(tb);
1279
-
1280
- assert_memory_lock();
1281
-
1282
- /* make sure no further incoming jumps will be chained to this TB */
1283
- qemu_spin_lock(&tb->jmp_lock);
1284
- qatomic_set(&tb->cflags, tb->cflags | CF_INVALID);
1285
- qemu_spin_unlock(&tb->jmp_lock);
1286
-
1287
- /* remove the TB from the hash list */
1288
- phys_pc = tb->page_addr[0];
1289
- h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : tb_pc(tb)),
1290
- tb->flags, orig_cflags, tb->trace_vcpu_dstate);
1291
- if (!qht_remove(&tb_ctx.htable, tb, h)) {
1292
- return;
1293
- }
1294
-
1295
- /* remove the TB from the page list */
1296
- if (rm_from_page_list) {
1297
- p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
1298
- tb_page_remove(p, tb);
1299
- if (tb->page_addr[1] != -1) {
1300
- p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
1301
- tb_page_remove(p, tb);
1302
- }
1303
- }
1304
-
1305
- /* remove the TB from the hash list */
1306
- tb_jmp_cache_inval_tb(tb);
1307
-
1308
- /* suppress this TB from the two jump lists */
1309
- tb_remove_from_jmp_list(tb, 0);
1310
- tb_remove_from_jmp_list(tb, 1);
1311
-
1312
- /* suppress any remaining jumps to this TB */
1313
- tb_jmp_unlink(tb);
1314
-
1315
- qatomic_set(&tb_ctx.tb_phys_invalidate_count,
1316
- tb_ctx.tb_phys_invalidate_count + 1);
1317
-}
1318
-
1319
-static void tb_phys_invalidate__locked(TranslationBlock *tb)
1320
-{
1321
- qemu_thread_jit_write();
1322
- do_tb_phys_invalidate(tb, true);
1323
- qemu_thread_jit_execute();
1324
-}
1325
-
1326
-/* invalidate one TB
1327
- *
1328
- * Called with mmap_lock held in user-mode.
1329
- */
1330
-void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
1331
-{
1332
- if (page_addr == -1 && tb->page_addr[0] != -1) {
1333
- page_lock_tb(tb);
1334
- do_tb_phys_invalidate(tb, true);
1335
- page_unlock_tb(tb);
1336
- } else {
1337
- do_tb_phys_invalidate(tb, false);
1338
- }
1339
-}
1340
-
1341
-/* add the tb in the target page and protect it if necessary
1342
- *
1343
- * Called with mmap_lock held for user-mode emulation.
1344
- * Called with @p->lock held in !user-mode.
1345
- */
1346
-static inline void tb_page_add(PageDesc *p, TranslationBlock *tb,
1347
- unsigned int n, tb_page_addr_t page_addr)
1348
-{
1349
-#ifndef CONFIG_USER_ONLY
1350
- bool page_already_protected;
1351
-#endif
1352
-
1353
- assert_page_locked(p);
1354
-
1355
- tb->page_addr[n] = page_addr;
1356
- tb->page_next[n] = p->first_tb;
1357
-#ifndef CONFIG_USER_ONLY
1358
- page_already_protected = p->first_tb != (uintptr_t)NULL;
1359
-#endif
1360
- p->first_tb = (uintptr_t)tb | n;
1361
-
1362
-#if defined(CONFIG_USER_ONLY)
1363
- /* translator_loop() must have made all TB pages non-writable */
1364
- assert(!(p->flags & PAGE_WRITE));
1365
-#else
1366
- /* if some code is already present, then the pages are already
1367
- protected. So we handle the case where only the first TB is
1368
- allocated in a physical page */
1369
- if (!page_already_protected) {
1370
- tlb_protect_code(page_addr);
1371
- }
1372
-#endif
1373
-}
1374
-
1375
-/*
1376
- * Add a new TB and link it to the physical page tables. phys_page2 is
1377
- * (-1) to indicate that only one page contains the TB.
1378
- *
1379
- * Called with mmap_lock held for user-mode emulation.
1380
- *
1381
- * Returns a pointer @tb, or a pointer to an existing TB that matches @tb.
1382
- * Note that in !user-mode, another thread might have already added a TB
1383
- * for the same block of guest code that @tb corresponds to. In that case,
1384
- * the caller should discard the original @tb, and use instead the returned TB.
1385
- */
1386
-static TranslationBlock *
1387
-tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
1388
- tb_page_addr_t phys_page2)
1389
-{
1390
- PageDesc *p;
1391
- PageDesc *p2 = NULL;
1392
- void *existing_tb = NULL;
1393
- uint32_t h;
1394
-
1395
- assert_memory_lock();
1396
- tcg_debug_assert(!(tb->cflags & CF_INVALID));
1397
-
1398
- /*
1399
- * Add the TB to the page list, acquiring first the pages's locks.
1400
- * We keep the locks held until after inserting the TB in the hash table,
1401
- * so that if the insertion fails we know for sure that the TBs are still
1402
- * in the page descriptors.
1403
- * Note that inserting into the hash table first isn't an option, since
1404
- * we can only insert TBs that are fully initialized.
1405
- */
1406
- page_lock_pair(&p, phys_pc, &p2, phys_page2, true);
1407
- tb_page_add(p, tb, 0, phys_pc);
1408
- if (p2) {
1409
- tb_page_add(p2, tb, 1, phys_page2);
1410
- } else {
1411
- tb->page_addr[1] = -1;
1412
- }
1413
-
1414
- /* add in the hash table */
1415
- h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : tb_pc(tb)),
1416
- tb->flags, tb->cflags, tb->trace_vcpu_dstate);
1417
- qht_insert(&tb_ctx.htable, tb, h, &existing_tb);
1418
-
1419
- /* remove TB from the page(s) if we couldn't insert it */
1420
- if (unlikely(existing_tb)) {
1421
- tb_page_remove(p, tb);
1422
- if (p2) {
1423
- tb_page_remove(p2, tb);
1424
- }
1425
- tb = existing_tb;
1426
- }
1427
-
1428
- if (p2 && p2 != p) {
1429
- page_unlock(p2);
1430
- }
1431
- page_unlock(p);
1432
- return tb;
1433
-}
1434
-
1435
/* Called with mmap_lock held for user mode emulation. */
1436
TranslationBlock *tb_gen_code(CPUState *cpu,
1437
target_ulong pc, target_ulong cs_base,
1438
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
1439
return tb;
1440
}
1441
1442
-/*
1443
- * @p must be non-NULL.
1444
- * user-mode: call with mmap_lock held.
1445
- * !user-mode: call with all @pages locked.
1446
- */
1447
-static void
1448
-tb_invalidate_phys_page_range__locked(struct page_collection *pages,
1449
- PageDesc *p, tb_page_addr_t start,
1450
- tb_page_addr_t end,
1451
- uintptr_t retaddr)
1452
-{
1453
- TranslationBlock *tb;
1454
- tb_page_addr_t tb_start, tb_end;
1455
- int n;
1456
-#ifdef TARGET_HAS_PRECISE_SMC
1457
- CPUState *cpu = current_cpu;
1458
- CPUArchState *env = NULL;
1459
- bool current_tb_not_found = retaddr != 0;
1460
- bool current_tb_modified = false;
1461
- TranslationBlock *current_tb = NULL;
1462
- target_ulong current_pc = 0;
1463
- target_ulong current_cs_base = 0;
1464
- uint32_t current_flags = 0;
1465
-#endif /* TARGET_HAS_PRECISE_SMC */
1466
-
1467
- assert_page_locked(p);
1468
-
1469
-#if defined(TARGET_HAS_PRECISE_SMC)
1470
- if (cpu != NULL) {
1471
- env = cpu->env_ptr;
1472
- }
1473
-#endif
1474
-
1475
- /* we remove all the TBs in the range [start, end[ */
1476
- /* XXX: see if in some cases it could be faster to invalidate all
1477
- the code */
1478
- PAGE_FOR_EACH_TB(p, tb, n) {
1479
- assert_page_locked(p);
1480
- /* NOTE: this is subtle as a TB may span two physical pages */
1481
- if (n == 0) {
1482
- /* NOTE: tb_end may be after the end of the page, but
1483
- it is not a problem */
1484
- tb_start = tb->page_addr[0];
1485
- tb_end = tb_start + tb->size;
1486
- } else {
1487
- tb_start = tb->page_addr[1];
1488
- tb_end = tb_start + ((tb->page_addr[0] + tb->size)
1489
- & ~TARGET_PAGE_MASK);
1490
- }
1491
- if (!(tb_end <= start || tb_start >= end)) {
1492
-#ifdef TARGET_HAS_PRECISE_SMC
1493
- if (current_tb_not_found) {
1494
- current_tb_not_found = false;
1495
- /* now we have a real cpu fault */
1496
- current_tb = tcg_tb_lookup(retaddr);
1497
- }
1498
- if (current_tb == tb &&
1499
- (tb_cflags(current_tb) & CF_COUNT_MASK) != 1) {
1500
- /*
1501
- * If we are modifying the current TB, we must stop
1502
- * its execution. We could be more precise by checking
1503
- * that the modification is after the current PC, but it
1504
- * would require a specialized function to partially
1505
- * restore the CPU state.
1506
- */
1507
- current_tb_modified = true;
1508
- cpu_restore_state_from_tb(cpu, current_tb, retaddr, true);
1509
- cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
1510
- &current_flags);
1511
- }
1512
-#endif /* TARGET_HAS_PRECISE_SMC */
1513
- tb_phys_invalidate__locked(tb);
1514
- }
1515
- }
1516
-#if !defined(CONFIG_USER_ONLY)
1517
- /* if no code remaining, no need to continue to use slow writes */
1518
- if (!p->first_tb) {
1519
- tlb_unprotect_code(start);
1520
- }
1521
-#endif
1522
-#ifdef TARGET_HAS_PRECISE_SMC
1523
- if (current_tb_modified) {
1524
- page_collection_unlock(pages);
1525
- /* Force execution of one insn next time. */
1526
- cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(cpu);
1527
- mmap_unlock();
1528
- cpu_loop_exit_noexc(cpu);
1529
- }
1530
-#endif
1531
-}
1532
-
1533
-/*
1534
- * Invalidate all TBs which intersect with the target physical address range
1535
- * [start;end[. NOTE: start and end must refer to the *same* physical page.
1536
- * 'is_cpu_write_access' should be true if called from a real cpu write
1537
- * access: the virtual CPU will exit the current TB if code is modified inside
1538
- * this TB.
1539
- *
1540
- * Called with mmap_lock held for user-mode emulation
1541
- */
1542
-void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end)
1543
-{
1544
- struct page_collection *pages;
1545
- PageDesc *p;
1546
-
1547
- assert_memory_lock();
1548
-
1549
- p = page_find(start >> TARGET_PAGE_BITS);
1550
- if (p == NULL) {
1551
- return;
1552
- }
1553
- pages = page_collection_lock(start, end);
1554
- tb_invalidate_phys_page_range__locked(pages, p, start, end, 0);
1555
- page_collection_unlock(pages);
1556
-}
1557
-
1558
-/*
1559
- * Invalidate all TBs which intersect with the target physical address range
1560
- * [start;end[. NOTE: start and end may refer to *different* physical pages.
1561
- * 'is_cpu_write_access' should be true if called from a real cpu write
1562
- * access: the virtual CPU will exit the current TB if code is modified inside
1563
- * this TB.
1564
- *
1565
- * Called with mmap_lock held for user-mode emulation.
1566
- */
1567
-#ifdef CONFIG_SOFTMMU
1568
-void tb_invalidate_phys_range(ram_addr_t start, ram_addr_t end)
1569
-#else
1570
-void tb_invalidate_phys_range(target_ulong start, target_ulong end)
1571
-#endif
1572
-{
1573
- struct page_collection *pages;
1574
- tb_page_addr_t next;
1575
-
1576
- assert_memory_lock();
1577
-
1578
- pages = page_collection_lock(start, end);
1579
- for (next = (start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
1580
- start < end;
1581
- start = next, next += TARGET_PAGE_SIZE) {
1582
- PageDesc *pd = page_find(start >> TARGET_PAGE_BITS);
1583
- tb_page_addr_t bound = MIN(next, end);
1584
-
1585
- if (pd == NULL) {
1586
- continue;
1587
- }
1588
- tb_invalidate_phys_page_range__locked(pages, pd, start, bound, 0);
1589
- }
1590
- page_collection_unlock(pages);
1591
-}
1592
-
1593
-#ifdef CONFIG_SOFTMMU
1594
-/* len must be <= 8 and start must be a multiple of len.
1595
- * Called via softmmu_template.h when code areas are written to with
1596
- * iothread mutex not held.
1597
- *
1598
- * Call with all @pages in the range [@start, @start + len[ locked.
1599
- */
1600
-void tb_invalidate_phys_page_fast(struct page_collection *pages,
1601
- tb_page_addr_t start, int len,
1602
- uintptr_t retaddr)
1603
-{
1604
- PageDesc *p;
1605
-
1606
- assert_memory_lock();
1607
-
1608
- p = page_find(start >> TARGET_PAGE_BITS);
1609
- if (!p) {
1610
- return;
1611
- }
1612
-
1613
- assert_page_locked(p);
1614
- tb_invalidate_phys_page_range__locked(pages, p, start, start + len,
1615
- retaddr);
1616
-}
1617
-#else
1618
-/* Called with mmap_lock held. If pc is not 0 then it indicates the
1619
- * host PC of the faulting store instruction that caused this invalidate.
1620
- * Returns true if the caller needs to abort execution of the current
1621
- * TB (because it was modified by this store and the guest CPU has
1622
- * precise-SMC semantics).
1623
- */
1624
-static bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc)
1625
-{
1626
- TranslationBlock *tb;
1627
- PageDesc *p;
1628
- int n;
1629
-#ifdef TARGET_HAS_PRECISE_SMC
1630
- TranslationBlock *current_tb = NULL;
1631
- CPUState *cpu = current_cpu;
1632
- CPUArchState *env = NULL;
1633
- int current_tb_modified = 0;
1634
- target_ulong current_pc = 0;
1635
- target_ulong current_cs_base = 0;
1636
- uint32_t current_flags = 0;
1637
-#endif
1638
-
1639
- assert_memory_lock();
1640
-
1641
- addr &= TARGET_PAGE_MASK;
1642
- p = page_find(addr >> TARGET_PAGE_BITS);
1643
- if (!p) {
1644
- return false;
1645
- }
1646
-
1647
-#ifdef TARGET_HAS_PRECISE_SMC
1648
- if (p->first_tb && pc != 0) {
1649
- current_tb = tcg_tb_lookup(pc);
1650
- }
1651
- if (cpu != NULL) {
1652
- env = cpu->env_ptr;
1653
- }
1654
-#endif
1655
- assert_page_locked(p);
1656
- PAGE_FOR_EACH_TB(p, tb, n) {
1657
-#ifdef TARGET_HAS_PRECISE_SMC
1658
- if (current_tb == tb &&
1659
- (tb_cflags(current_tb) & CF_COUNT_MASK) != 1) {
1660
- /* If we are modifying the current TB, we must stop
1661
- its execution. We could be more precise by checking
1662
- that the modification is after the current PC, but it
1663
- would require a specialized function to partially
1664
- restore the CPU state */
1665
-
1666
- current_tb_modified = 1;
1667
- cpu_restore_state_from_tb(cpu, current_tb, pc, true);
1668
- cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
1669
- &current_flags);
1670
- }
1671
-#endif /* TARGET_HAS_PRECISE_SMC */
1672
- tb_phys_invalidate(tb, addr);
1673
- }
1674
- p->first_tb = (uintptr_t)NULL;
1675
-#ifdef TARGET_HAS_PRECISE_SMC
1676
- if (current_tb_modified) {
1677
- /* Force execution of one insn next time. */
1678
- cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(cpu);
1679
- return true;
1680
- }
1681
-#endif
1682
-
1683
- return false;
190
- return false;
1684
-}
191
-}
1685
-#endif
192
-#endif
1686
-
193
-
1687
/* user-mode: call with mmap_lock held */
194
static void tcg_target_init(TCGContext *s)
1688
void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr)
1689
{
195
{
1690
diff --git a/accel/tcg/meson.build b/accel/tcg/meson.build
196
-#ifdef __linux__
197
- unsigned long hwcap = qemu_getauxval(AT_HWCAP);
198
- have_lse = hwcap & HWCAP_ATOMICS;
199
- have_lse2 = hwcap & HWCAP_USCAT;
200
-#endif
201
-#ifdef CONFIG_DARWIN
202
- have_lse = sysctl_for_bool("hw.optional.arm.FEAT_LSE");
203
- have_lse2 = sysctl_for_bool("hw.optional.arm.FEAT_LSE2");
204
-#endif
205
-
206
tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffffu;
207
tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffffu;
208
tcg_target_available_regs[TCG_TYPE_V64] = 0xffffffff00000000ull;
209
diff --git a/util/meson.build b/util/meson.build
1691
index XXXXXXX..XXXXXXX 100644
210
index XXXXXXX..XXXXXXX 100644
1692
--- a/accel/tcg/meson.build
211
--- a/util/meson.build
1693
+++ b/accel/tcg/meson.build
212
+++ b/util/meson.build
1694
@@ -XXX,XX +XXX,XX @@ tcg_ss.add(files(
213
@@ -XXX,XX +XXX,XX @@ if have_block
1695
'tcg-all.c',
214
util_ss.add(when: 'CONFIG_LINUX', if_true: files('vfio-helpers.c'))
1696
'cpu-exec-common.c',
215
endif
1697
'cpu-exec.c',
216
1698
+ 'tb-maint.c',
217
-if cpu in ['x86', 'x86_64']
1699
'tcg-runtime-gvec.c',
218
+if cpu == 'aarch64'
1700
'tcg-runtime.c',
219
+ util_ss.add(files('cpuinfo-aarch64.c'))
1701
'translate-all.c',
220
+elif cpu in ['x86', 'x86_64']
221
util_ss.add(files('cpuinfo-i386.c'))
222
endif
1702
--
223
--
1703
2.34.1
224
2.34.1
1704
225
1705
226
diff view generated by jsdifflib
1
Use a constant target data allocation size for all pages.
1
Separates the aarch64-specific portion into its own file.
2
This will be necessary to reduce overhead of page tracking.
3
Since TARGET_PAGE_DATA_SIZE is now required, we can use this
4
to omit data tracking for targets that don't require it.
5
2
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
5
---
9
include/exec/cpu-all.h | 9 ++++-----
6
host/include/aarch64/host/atomic128-cas.h | 43 ++++++++++++++++++
10
target/arm/cpu.h | 8 ++++++++
7
host/include/generic/host/atomic128-cas.h | 43 ++++++++++++++++++
11
target/arm/internals.h | 4 ----
8
include/qemu/atomic128.h | 55 +----------------------
12
accel/tcg/translate-all.c | 8 ++++++--
9
3 files changed, 87 insertions(+), 54 deletions(-)
13
target/arm/mte_helper.c | 3 +--
10
create mode 100644 host/include/aarch64/host/atomic128-cas.h
14
5 files changed, 19 insertions(+), 13 deletions(-)
11
create mode 100644 host/include/generic/host/atomic128-cas.h
15
12
16
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
13
diff --git a/host/include/aarch64/host/atomic128-cas.h b/host/include/aarch64/host/atomic128-cas.h
17
index XXXXXXX..XXXXXXX 100644
14
new file mode 100644
18
--- a/include/exec/cpu-all.h
15
index XXXXXXX..XXXXXXX
19
+++ b/include/exec/cpu-all.h
16
--- /dev/null
20
@@ -XXX,XX +XXX,XX @@ void page_reset_target_data(target_ulong start, target_ulong end);
17
+++ b/host/include/aarch64/host/atomic128-cas.h
21
int page_check_range(target_ulong start, target_ulong len, int flags);
18
@@ -XXX,XX +XXX,XX @@
22
19
+/*
23
/**
20
+ * SPDX-License-Identifier: GPL-2.0-or-later
24
- * page_alloc_target_data(address, size)
21
+ * Compare-and-swap for 128-bit atomic operations, AArch64 version.
25
+ * page_alloc_target_data(address)
22
+ *
26
* @address: guest virtual address
23
+ * Copyright (C) 2018, 2023 Linaro, Ltd.
27
- * @size: size of data to allocate
24
+ *
28
*
25
+ * See docs/devel/atomics.rst for discussion about the guarantees each
29
- * Allocate @size bytes of out-of-band data to associate with the
26
+ * atomic primitive is meant to provide.
30
- * guest page at @address. If the page is not mapped, NULL will
27
+ */
31
+ * Allocate TARGET_PAGE_DATA_SIZE bytes of out-of-band data to associate
32
+ * with the guest page at @address. If the page is not mapped, NULL will
33
* be returned. If there is existing data associated with @address,
34
* no new memory will be allocated.
35
*
36
* The memory will be freed when the guest page is deallocated,
37
* e.g. with the munmap system call.
38
*/
39
-void *page_alloc_target_data(target_ulong address, size_t size);
40
+void *page_alloc_target_data(target_ulong address);
41
42
/**
43
* page_get_target_data(address)
44
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/cpu.h
47
+++ b/target/arm/cpu.h
48
@@ -XXX,XX +XXX,XX @@ extern const uint64_t pred_esz_masks[5];
49
#define PAGE_MTE PAGE_TARGET_2
50
#define PAGE_TARGET_STICKY PAGE_MTE
51
52
+/* We associate one allocation tag per 16 bytes, the minimum. */
53
+#define LOG2_TAG_GRANULE 4
54
+#define TAG_GRANULE (1 << LOG2_TAG_GRANULE)
55
+
28
+
56
+#ifdef CONFIG_USER_ONLY
29
+#ifndef AARCH64_ATOMIC128_CAS_H
57
+#define TARGET_PAGE_DATA_SIZE (TARGET_PAGE_SIZE >> (LOG2_TAG_GRANULE + 1))
30
+#define AARCH64_ATOMIC128_CAS_H
31
+
32
+/* Through gcc 10, aarch64 has no support for 128-bit atomics. */
33
+#if defined(CONFIG_ATOMIC128) || defined(CONFIG_CMPXCHG128)
34
+#include "host/include/generic/host/atomic128-cas.h"
35
+#else
36
+static inline Int128 atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
37
+{
38
+ uint64_t cmpl = int128_getlo(cmp), cmph = int128_gethi(cmp);
39
+ uint64_t newl = int128_getlo(new), newh = int128_gethi(new);
40
+ uint64_t oldl, oldh;
41
+ uint32_t tmp;
42
+
43
+ asm("0: ldaxp %[oldl], %[oldh], %[mem]\n\t"
44
+ "cmp %[oldl], %[cmpl]\n\t"
45
+ "ccmp %[oldh], %[cmph], #0, eq\n\t"
46
+ "b.ne 1f\n\t"
47
+ "stlxp %w[tmp], %[newl], %[newh], %[mem]\n\t"
48
+ "cbnz %w[tmp], 0b\n"
49
+ "1:"
50
+ : [mem] "+m"(*ptr), [tmp] "=&r"(tmp),
51
+ [oldl] "=&r"(oldl), [oldh] "=&r"(oldh)
52
+ : [cmpl] "r"(cmpl), [cmph] "r"(cmph),
53
+ [newl] "r"(newl), [newh] "r"(newh)
54
+ : "memory", "cc");
55
+
56
+ return int128_make128(oldl, oldh);
57
+}
58
+# define HAVE_CMPXCHG128 1
58
+#endif
59
+#endif
59
+
60
+
60
#ifdef TARGET_TAGGED_ADDRESSES
61
+#endif /* AARCH64_ATOMIC128_CAS_H */
61
/**
62
diff --git a/host/include/generic/host/atomic128-cas.h b/host/include/generic/host/atomic128-cas.h
62
* cpu_untagged_addr:
63
new file mode 100644
63
diff --git a/target/arm/internals.h b/target/arm/internals.h
64
index XXXXXXX..XXXXXXX
65
--- /dev/null
66
+++ b/host/include/generic/host/atomic128-cas.h
67
@@ -XXX,XX +XXX,XX @@
68
+/*
69
+ * SPDX-License-Identifier: GPL-2.0-or-later
70
+ * Compare-and-swap for 128-bit atomic operations, generic version.
71
+ *
72
+ * Copyright (C) 2018, 2023 Linaro, Ltd.
73
+ *
74
+ * See docs/devel/atomics.rst for discussion about the guarantees each
75
+ * atomic primitive is meant to provide.
76
+ */
77
+
78
+#ifndef HOST_ATOMIC128_CAS_H
79
+#define HOST_ATOMIC128_CAS_H
80
+
81
+#if defined(CONFIG_ATOMIC128)
82
+static inline Int128 atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
83
+{
84
+ Int128Alias r, c, n;
85
+
86
+ c.s = cmp;
87
+ n.s = new;
88
+ r.i = qatomic_cmpxchg__nocheck((__int128_t *)ptr, c.i, n.i);
89
+ return r.s;
90
+}
91
+# define HAVE_CMPXCHG128 1
92
+#elif defined(CONFIG_CMPXCHG128)
93
+static inline Int128 atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
94
+{
95
+ Int128Alias r, c, n;
96
+
97
+ c.s = cmp;
98
+ n.s = new;
99
+ r.i = __sync_val_compare_and_swap_16((__int128_t *)ptr, c.i, n.i);
100
+ return r.s;
101
+}
102
+# define HAVE_CMPXCHG128 1
103
+#else
104
+/* Fallback definition that must be optimized away, or error. */
105
+Int128 QEMU_ERROR("unsupported atomic")
106
+ atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new);
107
+# define HAVE_CMPXCHG128 0
108
+#endif
109
+
110
+#endif /* HOST_ATOMIC128_CAS_H */
111
diff --git a/include/qemu/atomic128.h b/include/qemu/atomic128.h
64
index XXXXXXX..XXXXXXX 100644
112
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/internals.h
113
--- a/include/qemu/atomic128.h
66
+++ b/target/arm/internals.h
114
+++ b/include/qemu/atomic128.h
67
@@ -XXX,XX +XXX,XX @@ void arm_log_exception(CPUState *cs);
115
@@ -XXX,XX +XXX,XX @@
116
* Therefore, special case each platform.
68
*/
117
*/
69
#define GMID_EL1_BS 6
118
70
119
-#if defined(CONFIG_ATOMIC128)
71
-/* We associate one allocation tag per 16 bytes, the minimum. */
120
-static inline Int128 atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
72
-#define LOG2_TAG_GRANULE 4
121
-{
73
-#define TAG_GRANULE (1 << LOG2_TAG_GRANULE)
122
- Int128Alias r, c, n;
74
-
123
-
75
/*
124
- c.s = cmp;
76
* SVE predicates are 1/8 the size of SVE vectors, and cannot use
125
- n.s = new;
77
* the same simd_desc() encoding due to restrictions on size.
126
- r.i = qatomic_cmpxchg__nocheck((__int128_t *)ptr, c.i, n.i);
78
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
127
- return r.s;
79
index XXXXXXX..XXXXXXX 100644
128
-}
80
--- a/accel/tcg/translate-all.c
129
-# define HAVE_CMPXCHG128 1
81
+++ b/accel/tcg/translate-all.c
130
-#elif defined(CONFIG_CMPXCHG128)
82
@@ -XXX,XX +XXX,XX @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
131
-static inline Int128 atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
83
132
-{
84
void page_reset_target_data(target_ulong start, target_ulong end)
133
- Int128Alias r, c, n;
85
{
134
-
86
+#ifdef TARGET_PAGE_DATA_SIZE
135
- c.s = cmp;
87
target_ulong addr, len;
136
- n.s = new;
88
137
- r.i = __sync_val_compare_and_swap_16((__int128_t *)ptr, c.i, n.i);
89
/*
138
- return r.s;
90
@@ -XXX,XX +XXX,XX @@ void page_reset_target_data(target_ulong start, target_ulong end)
139
-}
91
g_free(p->target_data);
140
-# define HAVE_CMPXCHG128 1
92
p->target_data = NULL;
141
-#elif defined(__aarch64__)
93
}
142
-/* Through gcc 8, aarch64 has no support for 128-bit at all. */
94
+#endif
143
-static inline Int128 atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
95
}
144
-{
96
145
- uint64_t cmpl = int128_getlo(cmp), cmph = int128_gethi(cmp);
97
+#ifdef TARGET_PAGE_DATA_SIZE
146
- uint64_t newl = int128_getlo(new), newh = int128_gethi(new);
98
void *page_get_target_data(target_ulong address)
147
- uint64_t oldl, oldh;
99
{
148
- uint32_t tmp;
100
PageDesc *p = page_find(address >> TARGET_PAGE_BITS);
149
-
101
return p ? p->target_data : NULL;
150
- asm("0: ldaxp %[oldl], %[oldh], %[mem]\n\t"
102
}
151
- "cmp %[oldl], %[cmpl]\n\t"
103
152
- "ccmp %[oldh], %[cmph], #0, eq\n\t"
104
-void *page_alloc_target_data(target_ulong address, size_t size)
153
- "b.ne 1f\n\t"
105
+void *page_alloc_target_data(target_ulong address)
154
- "stlxp %w[tmp], %[newl], %[newh], %[mem]\n\t"
106
{
155
- "cbnz %w[tmp], 0b\n"
107
PageDesc *p = page_find(address >> TARGET_PAGE_BITS);
156
- "1:"
108
void *ret = NULL;
157
- : [mem] "+m"(*ptr), [tmp] "=&r"(tmp),
109
@@ -XXX,XX +XXX,XX @@ void *page_alloc_target_data(target_ulong address, size_t size)
158
- [oldl] "=&r"(oldl), [oldh] "=&r"(oldh)
110
if (p->flags & PAGE_VALID) {
159
- : [cmpl] "r"(cmpl), [cmph] "r"(cmph),
111
ret = p->target_data;
160
- [newl] "r"(newl), [newh] "r"(newh)
112
if (!ret) {
161
- : "memory", "cc");
113
- p->target_data = ret = g_malloc0(size);
162
-
114
+ p->target_data = ret = g_malloc0(TARGET_PAGE_DATA_SIZE);
163
- return int128_make128(oldl, oldh);
115
}
164
-}
116
}
165
-# define HAVE_CMPXCHG128 1
117
return ret;
166
-#else
118
}
167
-/* Fallback definition that must be optimized away, or error. */
119
+#endif /* TARGET_PAGE_DATA_SIZE */
168
-Int128 QEMU_ERROR("unsupported atomic")
120
169
- atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new);
121
int page_check_range(target_ulong start, target_ulong len, int flags)
170
-# define HAVE_CMPXCHG128 0
122
{
171
-#endif /* Some definition for HAVE_CMPXCHG128 */
123
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
172
-
124
index XXXXXXX..XXXXXXX 100644
173
+#include "host/atomic128-cas.h"
125
--- a/target/arm/mte_helper.c
174
126
+++ b/target/arm/mte_helper.c
175
#if defined(CONFIG_ATOMIC128)
127
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
176
static inline Int128 atomic16_read(Int128 *ptr)
128
129
tags = page_get_target_data(clean_ptr);
130
if (tags == NULL) {
131
- size_t alloc_size = TARGET_PAGE_SIZE >> (LOG2_TAG_GRANULE + 1);
132
- tags = page_alloc_target_data(clean_ptr, alloc_size);
133
+ tags = page_alloc_target_data(clean_ptr);
134
assert(tags != NULL);
135
}
136
137
--
177
--
138
2.34.1
178
2.34.1
139
179
140
180
diff view generated by jsdifflib
1
Rename to tb_invalidate_phys_page_unwind to emphasize that
1
Separates the aarch64-specific portion into its own file.
2
we also detect invalidating the current TB, and also to free
3
up that name for other usage.
4
2
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
5
---
8
accel/tcg/internal.h | 2 +-
6
host/include/aarch64/host/atomic128-ldst.h | 49 ++++++++++++++
9
accel/tcg/tb-maint.c | 2 +-
7
host/include/generic/host/atomic128-ldst.h | 57 +++++++++++++++++
10
accel/tcg/translate-all.c | 5 +++--
8
include/qemu/atomic128.h | 74 +---------------------
11
3 files changed, 5 insertions(+), 4 deletions(-)
9
3 files changed, 107 insertions(+), 73 deletions(-)
12
10
create mode 100644 host/include/aarch64/host/atomic128-ldst.h
13
diff --git a/accel/tcg/internal.h b/accel/tcg/internal.h
11
create mode 100644 host/include/generic/host/atomic128-ldst.h
12
13
diff --git a/host/include/aarch64/host/atomic128-ldst.h b/host/include/aarch64/host/atomic128-ldst.h
14
new file mode 100644
15
index XXXXXXX..XXXXXXX
16
--- /dev/null
17
+++ b/host/include/aarch64/host/atomic128-ldst.h
18
@@ -XXX,XX +XXX,XX @@
19
+/*
20
+ * SPDX-License-Identifier: GPL-2.0-or-later
21
+ * Load/store for 128-bit atomic operations, AArch64 version.
22
+ *
23
+ * Copyright (C) 2018, 2023 Linaro, Ltd.
24
+ *
25
+ * See docs/devel/atomics.rst for discussion about the guarantees each
26
+ * atomic primitive is meant to provide.
27
+ */
28
+
29
+#ifndef AARCH64_ATOMIC128_LDST_H
30
+#define AARCH64_ATOMIC128_LDST_H
31
+
32
+/* Through gcc 10, aarch64 has no support for 128-bit atomics. */
33
+#if !defined(CONFIG_ATOMIC128) && !defined(CONFIG_USER_ONLY)
34
+/* We can do better than cmpxchg for AArch64. */
35
+static inline Int128 atomic16_read(Int128 *ptr)
36
+{
37
+ uint64_t l, h;
38
+ uint32_t tmp;
39
+
40
+ /* The load must be paired with the store to guarantee not tearing. */
41
+ asm("0: ldxp %[l], %[h], %[mem]\n\t"
42
+ "stxp %w[tmp], %[l], %[h], %[mem]\n\t"
43
+ "cbnz %w[tmp], 0b"
44
+ : [mem] "+m"(*ptr), [tmp] "=r"(tmp), [l] "=r"(l), [h] "=r"(h));
45
+
46
+ return int128_make128(l, h);
47
+}
48
+
49
+static inline void atomic16_set(Int128 *ptr, Int128 val)
50
+{
51
+ uint64_t l = int128_getlo(val), h = int128_gethi(val);
52
+ uint64_t t1, t2;
53
+
54
+ /* Load into temporaries to acquire the exclusive access lock. */
55
+ asm("0: ldxp %[t1], %[t2], %[mem]\n\t"
56
+ "stxp %w[t1], %[l], %[h], %[mem]\n\t"
57
+ "cbnz %w[t1], 0b"
58
+ : [mem] "+m"(*ptr), [t1] "=&r"(t1), [t2] "=&r"(t2)
59
+ : [l] "r"(l), [h] "r"(h));
60
+}
61
+
62
+# define HAVE_ATOMIC128 1
63
+#else
64
+#include "host/include/generic/host/atomic128-ldst.h"
65
+#endif
66
+
67
+#endif /* AARCH64_ATOMIC128_LDST_H */
68
diff --git a/host/include/generic/host/atomic128-ldst.h b/host/include/generic/host/atomic128-ldst.h
69
new file mode 100644
70
index XXXXXXX..XXXXXXX
71
--- /dev/null
72
+++ b/host/include/generic/host/atomic128-ldst.h
73
@@ -XXX,XX +XXX,XX @@
74
+/*
75
+ * SPDX-License-Identifier: GPL-2.0-or-later
76
+ * Load/store for 128-bit atomic operations, generic version.
77
+ *
78
+ * Copyright (C) 2018, 2023 Linaro, Ltd.
79
+ *
80
+ * See docs/devel/atomics.rst for discussion about the guarantees each
81
+ * atomic primitive is meant to provide.
82
+ */
83
+
84
+#ifndef HOST_ATOMIC128_LDST_H
85
+#define HOST_ATOMIC128_LDST_H
86
+
87
+#if defined(CONFIG_ATOMIC128)
88
+static inline Int128 atomic16_read(Int128 *ptr)
89
+{
90
+ Int128Alias r;
91
+
92
+ r.i = qatomic_read__nocheck((__int128_t *)ptr);
93
+ return r.s;
94
+}
95
+
96
+static inline void atomic16_set(Int128 *ptr, Int128 val)
97
+{
98
+ Int128Alias v;
99
+
100
+ v.s = val;
101
+ qatomic_set__nocheck((__int128_t *)ptr, v.i);
102
+}
103
+
104
+# define HAVE_ATOMIC128 1
105
+#elif !defined(CONFIG_USER_ONLY) && HAVE_CMPXCHG128
106
+static inline Int128 atomic16_read(Int128 *ptr)
107
+{
108
+ /* Maybe replace 0 with 0, returning the old value. */
109
+ Int128 z = int128_make64(0);
110
+ return atomic16_cmpxchg(ptr, z, z);
111
+}
112
+
113
+static inline void atomic16_set(Int128 *ptr, Int128 val)
114
+{
115
+ Int128 old = *ptr, cmp;
116
+ do {
117
+ cmp = old;
118
+ old = atomic16_cmpxchg(ptr, cmp, val);
119
+ } while (int128_ne(old, cmp));
120
+}
121
+
122
+# define HAVE_ATOMIC128 1
123
+#else
124
+/* Fallback definitions that must be optimized away, or error. */
125
+Int128 QEMU_ERROR("unsupported atomic") atomic16_read(Int128 *ptr);
126
+void QEMU_ERROR("unsupported atomic") atomic16_set(Int128 *ptr, Int128 val);
127
+# define HAVE_ATOMIC128 0
128
+#endif
129
+
130
+#endif /* HOST_ATOMIC128_LDST_H */
131
diff --git a/include/qemu/atomic128.h b/include/qemu/atomic128.h
14
index XXXXXXX..XXXXXXX 100644
132
index XXXXXXX..XXXXXXX 100644
15
--- a/accel/tcg/internal.h
133
--- a/include/qemu/atomic128.h
16
+++ b/accel/tcg/internal.h
134
+++ b/include/qemu/atomic128.h
17
@@ -XXX,XX +XXX,XX @@ void tb_htable_init(void);
135
@@ -XXX,XX +XXX,XX @@
18
void tb_reset_jump(TranslationBlock *tb, int n);
19
TranslationBlock *tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
20
tb_page_addr_t phys_page2);
21
-bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc);
22
+bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc);
23
int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
24
uintptr_t searched_pc, bool reset_icount);
25
26
diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/accel/tcg/tb-maint.c
29
+++ b/accel/tcg/tb-maint.c
30
@@ -XXX,XX +XXX,XX @@ void tb_invalidate_phys_page_fast(struct page_collection *pages,
31
* TB (because it was modified by this store and the guest CPU has
32
* precise-SMC semantics).
33
*/
136
*/
34
-bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc)
137
35
+bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc)
138
#include "host/atomic128-cas.h"
36
{
139
-
37
TranslationBlock *tb;
140
-#if defined(CONFIG_ATOMIC128)
38
PageDesc *p;
141
-static inline Int128 atomic16_read(Int128 *ptr)
39
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
142
-{
40
index XXXXXXX..XXXXXXX 100644
143
- Int128Alias r;
41
--- a/accel/tcg/translate-all.c
144
-
42
+++ b/accel/tcg/translate-all.c
145
- r.i = qatomic_read__nocheck((__int128_t *)ptr);
43
@@ -XXX,XX +XXX,XX @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
146
- return r.s;
44
if (!(p->flags & PAGE_WRITE) &&
147
-}
45
(flags & PAGE_WRITE) &&
148
-
46
p->first_tb) {
149
-static inline void atomic16_set(Int128 *ptr, Int128 val)
47
- tb_invalidate_phys_page(addr, 0);
150
-{
48
+ tb_invalidate_phys_page_unwind(addr, 0);
151
- Int128Alias v;
49
}
152
-
50
if (reset_target_data) {
153
- v.s = val;
51
g_free(p->target_data);
154
- qatomic_set__nocheck((__int128_t *)ptr, v.i);
52
@@ -XXX,XX +XXX,XX @@ int page_unprotect(target_ulong address, uintptr_t pc)
155
-}
53
156
-
54
/* and since the content will be modified, we must invalidate
157
-# define HAVE_ATOMIC128 1
55
the corresponding translated code. */
158
-#elif !defined(CONFIG_USER_ONLY) && defined(__aarch64__)
56
- current_tb_invalidated |= tb_invalidate_phys_page(addr, pc);
159
-/* We can do better than cmpxchg for AArch64. */
57
+ current_tb_invalidated |=
160
-static inline Int128 atomic16_read(Int128 *ptr)
58
+ tb_invalidate_phys_page_unwind(addr, pc);
161
-{
59
}
162
- uint64_t l, h;
60
mprotect((void *)g2h_untagged(host_start), qemu_host_page_size,
163
- uint32_t tmp;
61
prot & PAGE_BITS);
164
-
165
- /* The load must be paired with the store to guarantee not tearing. */
166
- asm("0: ldxp %[l], %[h], %[mem]\n\t"
167
- "stxp %w[tmp], %[l], %[h], %[mem]\n\t"
168
- "cbnz %w[tmp], 0b"
169
- : [mem] "+m"(*ptr), [tmp] "=r"(tmp), [l] "=r"(l), [h] "=r"(h));
170
-
171
- return int128_make128(l, h);
172
-}
173
-
174
-static inline void atomic16_set(Int128 *ptr, Int128 val)
175
-{
176
- uint64_t l = int128_getlo(val), h = int128_gethi(val);
177
- uint64_t t1, t2;
178
-
179
- /* Load into temporaries to acquire the exclusive access lock. */
180
- asm("0: ldxp %[t1], %[t2], %[mem]\n\t"
181
- "stxp %w[t1], %[l], %[h], %[mem]\n\t"
182
- "cbnz %w[t1], 0b"
183
- : [mem] "+m"(*ptr), [t1] "=&r"(t1), [t2] "=&r"(t2)
184
- : [l] "r"(l), [h] "r"(h));
185
-}
186
-
187
-# define HAVE_ATOMIC128 1
188
-#elif !defined(CONFIG_USER_ONLY) && HAVE_CMPXCHG128
189
-static inline Int128 atomic16_read(Int128 *ptr)
190
-{
191
- /* Maybe replace 0 with 0, returning the old value. */
192
- Int128 z = int128_make64(0);
193
- return atomic16_cmpxchg(ptr, z, z);
194
-}
195
-
196
-static inline void atomic16_set(Int128 *ptr, Int128 val)
197
-{
198
- Int128 old = *ptr, cmp;
199
- do {
200
- cmp = old;
201
- old = atomic16_cmpxchg(ptr, cmp, val);
202
- } while (int128_ne(old, cmp));
203
-}
204
-
205
-# define HAVE_ATOMIC128 1
206
-#else
207
-/* Fallback definitions that must be optimized away, or error. */
208
-Int128 QEMU_ERROR("unsupported atomic") atomic16_read(Int128 *ptr);
209
-void QEMU_ERROR("unsupported atomic") atomic16_set(Int128 *ptr, Int128 val);
210
-# define HAVE_ATOMIC128 0
211
-#endif /* Some definition for HAVE_ATOMIC128 */
212
+#include "host/atomic128-ldst.h"
213
214
#endif /* QEMU_ATOMIC128_H */
62
--
215
--
63
2.34.1
216
2.34.1
64
217
65
218
diff view generated by jsdifflib
1
We do not require detection of overlapping TBs here,
1
Silly typo: sizeof(16) != 16.
2
so use the more appropriate function.
3
2
3
Fixes: e61f1efeb730 ("meson: Detect atomic128 support with optimization")
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
---
7
accel/tcg/translate-all.c | 2 +-
8
meson.build | 2 +-
8
1 file changed, 1 insertion(+), 1 deletion(-)
9
1 file changed, 1 insertion(+), 1 deletion(-)
9
10
10
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
11
diff --git a/meson.build b/meson.build
11
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
12
--- a/accel/tcg/translate-all.c
13
--- a/meson.build
13
+++ b/accel/tcg/translate-all.c
14
+++ b/meson.build
14
@@ -XXX,XX +XXX,XX @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
15
@@ -XXX,XX +XXX,XX @@ if has_int128
15
if (!(p->flags & PAGE_WRITE) &&
16
# __alignof(unsigned __int128) for the host.
16
(flags & PAGE_WRITE) &&
17
atomic_test_128 = '''
17
p->first_tb) {
18
int main(int ac, char **av) {
18
- tb_invalidate_phys_page_unwind(addr, 0);
19
- unsigned __int128 *p = __builtin_assume_aligned(av[ac - 1], sizeof(16));
19
+ tb_invalidate_phys_page(addr);
20
+ unsigned __int128 *p = __builtin_assume_aligned(av[ac - 1], 16);
20
}
21
p[1] = __atomic_load_n(&p[0], __ATOMIC_RELAXED);
21
if (reset_target_data) {
22
__atomic_store_n(&p[2], p[3], __ATOMIC_RELAXED);
22
g_free(p->target_data);
23
__atomic_compare_exchange_n(&p[4], &p[5], p[6], 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
23
--
24
--
24
2.34.1
25
2.34.1
25
26
26
27
diff view generated by jsdifflib
1
Not only the routines in ldst_atomicity.c.inc need markup,
2
but also the ones in the headers.
3
1
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
6
---
4
accel/tcg/internal.h | 31 +++++++++++++++++++++++++++++++
7
host/include/generic/host/atomic128-cas.h | 12 ++++++++----
5
accel/tcg/translate-all.c | 31 +------------------------------
8
host/include/generic/host/atomic128-ldst.h | 18 ++++++++++++------
6
2 files changed, 32 insertions(+), 30 deletions(-)
9
include/qemu/atomic128.h | 17 +++++++++++++++++
10
accel/tcg/ldst_atomicity.c.inc | 17 -----------------
11
4 files changed, 37 insertions(+), 27 deletions(-)
7
12
8
diff --git a/accel/tcg/internal.h b/accel/tcg/internal.h
13
diff --git a/host/include/generic/host/atomic128-cas.h b/host/include/generic/host/atomic128-cas.h
9
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
10
--- a/accel/tcg/internal.h
15
--- a/host/include/generic/host/atomic128-cas.h
11
+++ b/accel/tcg/internal.h
16
+++ b/host/include/generic/host/atomic128-cas.h
12
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@
13
18
#define HOST_ATOMIC128_CAS_H
14
#include "exec/exec-all.h"
19
20
#if defined(CONFIG_ATOMIC128)
21
-static inline Int128 atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
22
+static inline Int128 ATTRIBUTE_ATOMIC128_OPT
23
+atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
24
{
25
+ __int128_t *ptr_align = __builtin_assume_aligned(ptr, 16);
26
Int128Alias r, c, n;
27
28
c.s = cmp;
29
n.s = new;
30
- r.i = qatomic_cmpxchg__nocheck((__int128_t *)ptr, c.i, n.i);
31
+ r.i = qatomic_cmpxchg__nocheck(ptr_align, c.i, n.i);
32
return r.s;
33
}
34
# define HAVE_CMPXCHG128 1
35
#elif defined(CONFIG_CMPXCHG128)
36
-static inline Int128 atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
37
+static inline Int128 ATTRIBUTE_ATOMIC128_OPT
38
+atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
39
{
40
+ __int128_t *ptr_align = __builtin_assume_aligned(ptr, 16);
41
Int128Alias r, c, n;
42
43
c.s = cmp;
44
n.s = new;
45
- r.i = __sync_val_compare_and_swap_16((__int128_t *)ptr, c.i, n.i);
46
+ r.i = __sync_val_compare_and_swap_16(ptr_align, c.i, n.i);
47
return r.s;
48
}
49
# define HAVE_CMPXCHG128 1
50
diff --git a/host/include/generic/host/atomic128-ldst.h b/host/include/generic/host/atomic128-ldst.h
51
index XXXXXXX..XXXXXXX 100644
52
--- a/host/include/generic/host/atomic128-ldst.h
53
+++ b/host/include/generic/host/atomic128-ldst.h
54
@@ -XXX,XX +XXX,XX @@
55
#define HOST_ATOMIC128_LDST_H
56
57
#if defined(CONFIG_ATOMIC128)
58
-static inline Int128 atomic16_read(Int128 *ptr)
59
+static inline Int128 ATTRIBUTE_ATOMIC128_OPT
60
+atomic16_read(Int128 *ptr)
61
{
62
+ __int128_t *ptr_align = __builtin_assume_aligned(ptr, 16);
63
Int128Alias r;
64
65
- r.i = qatomic_read__nocheck((__int128_t *)ptr);
66
+ r.i = qatomic_read__nocheck(ptr_align);
67
return r.s;
68
}
69
70
-static inline void atomic16_set(Int128 *ptr, Int128 val)
71
+static inline void ATTRIBUTE_ATOMIC128_OPT
72
+atomic16_set(Int128 *ptr, Int128 val)
73
{
74
+ __int128_t *ptr_align = __builtin_assume_aligned(ptr, 16);
75
Int128Alias v;
76
77
v.s = val;
78
- qatomic_set__nocheck((__int128_t *)ptr, v.i);
79
+ qatomic_set__nocheck(ptr_align, v.i);
80
}
81
82
# define HAVE_ATOMIC128 1
83
#elif !defined(CONFIG_USER_ONLY) && HAVE_CMPXCHG128
84
-static inline Int128 atomic16_read(Int128 *ptr)
85
+static inline Int128 ATTRIBUTE_ATOMIC128_OPT
86
+atomic16_read(Int128 *ptr)
87
{
88
/* Maybe replace 0 with 0, returning the old value. */
89
Int128 z = int128_make64(0);
90
return atomic16_cmpxchg(ptr, z, z);
91
}
92
93
-static inline void atomic16_set(Int128 *ptr, Int128 val)
94
+static inline void ATTRIBUTE_ATOMIC128_OPT
95
+atomic16_set(Int128 *ptr, Int128 val)
96
{
97
Int128 old = *ptr, cmp;
98
do {
99
diff --git a/include/qemu/atomic128.h b/include/qemu/atomic128.h
100
index XXXXXXX..XXXXXXX 100644
101
--- a/include/qemu/atomic128.h
102
+++ b/include/qemu/atomic128.h
103
@@ -XXX,XX +XXX,XX @@
104
105
#include "qemu/int128.h"
15
106
16
+/*
107
+/*
17
+ * Access to the various translations structures need to be serialised
108
+ * If __alignof(unsigned __int128) < 16, GCC may refuse to inline atomics
18
+ * via locks for consistency. In user-mode emulation access to the
109
+ * that are supported by the host, e.g. s390x. We can force the pointer to
19
+ * memory related structures are protected with mmap_lock.
110
+ * have our known alignment with __builtin_assume_aligned, however prior to
20
+ * In !user-mode we use per-page locks.
111
+ * GCC 13 that was only reliable with optimization enabled. See
112
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107389
21
+ */
113
+ */
22
+#ifdef CONFIG_SOFTMMU
114
+#if defined(CONFIG_ATOMIC128_OPT)
23
+#define assert_memory_lock()
115
+# if !defined(__OPTIMIZE__)
24
+#else
116
+# define ATTRIBUTE_ATOMIC128_OPT __attribute__((optimize("O1")))
25
+#define assert_memory_lock() tcg_debug_assert(have_mmap_lock())
117
+# endif
118
+# define CONFIG_ATOMIC128
119
+#endif
120
+#ifndef ATTRIBUTE_ATOMIC128_OPT
121
+# define ATTRIBUTE_ATOMIC128_OPT
26
+#endif
122
+#endif
27
+
123
+
28
+typedef struct PageDesc {
124
/*
29
+ /* list of TBs intersecting this ram page */
125
* GCC is a house divided about supporting large atomic operations.
30
+ uintptr_t first_tb;
126
*
31
+#ifdef CONFIG_USER_ONLY
127
diff --git a/accel/tcg/ldst_atomicity.c.inc b/accel/tcg/ldst_atomicity.c.inc
32
+ unsigned long flags;
33
+ void *target_data;
34
+#endif
35
+#ifdef CONFIG_SOFTMMU
36
+ QemuSpin lock;
37
+#endif
38
+} PageDesc;
39
+
40
+PageDesc *page_find_alloc(tb_page_addr_t index, bool alloc);
41
+
42
+static inline PageDesc *page_find(tb_page_addr_t index)
43
+{
44
+ return page_find_alloc(index, false);
45
+}
46
+
47
TranslationBlock *tb_gen_code(CPUState *cpu, target_ulong pc,
48
target_ulong cs_base, uint32_t flags,
49
int cflags);
50
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
51
index XXXXXXX..XXXXXXX 100644
128
index XXXXXXX..XXXXXXX 100644
52
--- a/accel/tcg/translate-all.c
129
--- a/accel/tcg/ldst_atomicity.c.inc
53
+++ b/accel/tcg/translate-all.c
130
+++ b/accel/tcg/ldst_atomicity.c.inc
54
@@ -XXX,XX +XXX,XX @@
131
@@ -XXX,XX +XXX,XX @@
55
132
#endif
56
/* make various TB consistency checks */
133
#define HAVE_al8_fast (ATOMIC_REG_SIZE >= 8)
57
134
58
-/* Access to the various translations structures need to be serialised via locks
135
-/*
59
- * for consistency.
136
- * If __alignof(unsigned __int128) < 16, GCC may refuse to inline atomics
60
- * In user-mode emulation access to the memory related structures are protected
137
- * that are supported by the host, e.g. s390x. We can force the pointer to
61
- * with mmap_lock.
138
- * have our known alignment with __builtin_assume_aligned, however prior to
62
- * In !user-mode we use per-page locks.
139
- * GCC 13 that was only reliable with optimization enabled. See
140
- * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107389
63
- */
141
- */
64
-#ifdef CONFIG_SOFTMMU
142
-#if defined(CONFIG_ATOMIC128_OPT)
65
-#define assert_memory_lock()
143
-# if !defined(__OPTIMIZE__)
66
-#else
144
-# define ATTRIBUTE_ATOMIC128_OPT __attribute__((optimize("O1")))
67
-#define assert_memory_lock() tcg_debug_assert(have_mmap_lock())
145
-# endif
146
-# define CONFIG_ATOMIC128
147
-#endif
148
-#ifndef ATTRIBUTE_ATOMIC128_OPT
149
-# define ATTRIBUTE_ATOMIC128_OPT
68
-#endif
150
-#endif
69
-
151
-
70
-typedef struct PageDesc {
152
#if defined(CONFIG_ATOMIC128)
71
- /* list of TBs intersecting this ram page */
153
# define HAVE_al16_fast true
72
- uintptr_t first_tb;
154
#else
73
-#ifdef CONFIG_USER_ONLY
74
- unsigned long flags;
75
- void *target_data;
76
-#endif
77
-#ifdef CONFIG_SOFTMMU
78
- QemuSpin lock;
79
-#endif
80
-} PageDesc;
81
-
82
/**
83
* struct page_entry - page descriptor entry
84
* @pd: pointer to the &struct PageDesc of the page this entry represents
85
@@ -XXX,XX +XXX,XX @@ void page_init(void)
86
#endif
87
}
88
89
-static PageDesc *page_find_alloc(tb_page_addr_t index, bool alloc)
90
+PageDesc *page_find_alloc(tb_page_addr_t index, bool alloc)
91
{
92
PageDesc *pd;
93
void **lp;
94
@@ -XXX,XX +XXX,XX @@ static PageDesc *page_find_alloc(tb_page_addr_t index, bool alloc)
95
return pd + (index & (V_L2_SIZE - 1));
96
}
97
98
-static inline PageDesc *page_find(tb_page_addr_t index)
99
-{
100
- return page_find_alloc(index, false);
101
-}
102
-
103
static void page_lock_pair(PageDesc **ret_p1, tb_page_addr_t phys1,
104
PageDesc **ret_p2, tb_page_addr_t phys2, bool alloc);
105
106
--
155
--
107
2.34.1
156
2.34.1
108
157
109
158
diff view generated by jsdifflib
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
1
No need to roll our own, as this is now provided by tcg.
2
This was the last use of retxl, so remove that too.
3
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
6
---
4
target/ppc/cpu_init.c | 10 ++++++++++
7
target/ppc/cpu.h | 1 -
5
target/ppc/translate.c | 6 ------
8
target/ppc/helper.h | 9 ----
6
2 files changed, 10 insertions(+), 6 deletions(-)
9
target/ppc/mem_helper.c | 48 --------------------
7
10
target/ppc/translate.c | 34 ++-------------
8
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
11
target/ppc/translate/fixedpoint-impl.c.inc | 51 +++-------------------
9
index XXXXXXX..XXXXXXX 100644
12
5 files changed, 11 insertions(+), 132 deletions(-)
10
--- a/target/ppc/cpu_init.c
13
11
+++ b/target/ppc/cpu_init.c
14
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
12
@@ -XXX,XX +XXX,XX @@ static vaddr ppc_cpu_get_pc(CPUState *cs)
15
index XXXXXXX..XXXXXXX 100644
13
return cpu->env.nip;
16
--- a/target/ppc/cpu.h
17
+++ b/target/ppc/cpu.h
18
@@ -XXX,XX +XXX,XX @@ struct CPUArchState {
19
/* used to speed-up TLB assist handlers */
20
21
target_ulong nip; /* next instruction pointer */
22
- uint64_t retxh; /* high part of 128-bit helper return */
23
24
/* when a memory exception occurs, the access type is stored here */
25
int access_type;
26
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/ppc/helper.h
29
+++ b/target/ppc/helper.h
30
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_4(DSCLIQ, void, env, fprp, fprp, i32)
31
32
DEF_HELPER_1(tbegin, void, env)
33
DEF_HELPER_FLAGS_1(fixup_thrm, TCG_CALL_NO_RWG, void, env)
34
-
35
-#ifdef TARGET_PPC64
36
-DEF_HELPER_FLAGS_3(lq_le_parallel, TCG_CALL_NO_WG, i64, env, tl, i32)
37
-DEF_HELPER_FLAGS_3(lq_be_parallel, TCG_CALL_NO_WG, i64, env, tl, i32)
38
-DEF_HELPER_FLAGS_5(stq_le_parallel, TCG_CALL_NO_WG,
39
- void, env, tl, i64, i64, i32)
40
-DEF_HELPER_FLAGS_5(stq_be_parallel, TCG_CALL_NO_WG,
41
- void, env, tl, i64, i64, i32)
42
-#endif
43
diff --git a/target/ppc/mem_helper.c b/target/ppc/mem_helper.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/ppc/mem_helper.c
46
+++ b/target/ppc/mem_helper.c
47
@@ -XXX,XX +XXX,XX @@ target_ulong helper_lscbx(CPUPPCState *env, target_ulong addr, uint32_t reg,
48
return i;
14
}
49
}
15
50
16
+static void ppc_restore_state_to_opc(CPUState *cs,
51
-#ifdef TARGET_PPC64
17
+ const TranslationBlock *tb,
52
-uint64_t helper_lq_le_parallel(CPUPPCState *env, target_ulong addr,
18
+ const uint64_t *data)
53
- uint32_t opidx)
19
+{
54
-{
20
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
55
- Int128 ret;
21
+
56
-
22
+ cpu->env.nip = data[0];
57
- /* We will have raised EXCP_ATOMIC from the translator. */
23
+}
58
- assert(HAVE_ATOMIC128);
24
+
59
- ret = cpu_atomic_ldo_le_mmu(env, addr, opidx, GETPC());
25
static bool ppc_cpu_has_work(CPUState *cs)
60
- env->retxh = int128_gethi(ret);
26
{
61
- return int128_getlo(ret);
27
PowerPCCPU *cpu = POWERPC_CPU(cs);
62
-}
28
@@ -XXX,XX +XXX,XX @@ static const struct SysemuCPUOps ppc_sysemu_ops = {
63
-
29
64
-uint64_t helper_lq_be_parallel(CPUPPCState *env, target_ulong addr,
30
static const struct TCGCPUOps ppc_tcg_ops = {
65
- uint32_t opidx)
31
.initialize = ppc_translate_init,
66
-{
32
+ .restore_state_to_opc = ppc_restore_state_to_opc,
67
- Int128 ret;
33
68
-
34
#ifdef CONFIG_USER_ONLY
69
- /* We will have raised EXCP_ATOMIC from the translator. */
35
.record_sigsegv = ppc_cpu_record_sigsegv,
70
- assert(HAVE_ATOMIC128);
71
- ret = cpu_atomic_ldo_be_mmu(env, addr, opidx, GETPC());
72
- env->retxh = int128_gethi(ret);
73
- return int128_getlo(ret);
74
-}
75
-
76
-void helper_stq_le_parallel(CPUPPCState *env, target_ulong addr,
77
- uint64_t lo, uint64_t hi, uint32_t opidx)
78
-{
79
- Int128 val;
80
-
81
- /* We will have raised EXCP_ATOMIC from the translator. */
82
- assert(HAVE_ATOMIC128);
83
- val = int128_make128(lo, hi);
84
- cpu_atomic_sto_le_mmu(env, addr, val, opidx, GETPC());
85
-}
86
-
87
-void helper_stq_be_parallel(CPUPPCState *env, target_ulong addr,
88
- uint64_t lo, uint64_t hi, uint32_t opidx)
89
-{
90
- Int128 val;
91
-
92
- /* We will have raised EXCP_ATOMIC from the translator. */
93
- assert(HAVE_ATOMIC128);
94
- val = int128_make128(lo, hi);
95
- cpu_atomic_sto_be_mmu(env, addr, val, opidx, GETPC());
96
-}
97
-#endif
98
-
99
/*****************************************************************************/
100
/* Altivec extension helpers */
101
#if HOST_BIG_ENDIAN
36
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
102
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
37
index XXXXXXX..XXXXXXX 100644
103
index XXXXXXX..XXXXXXX 100644
38
--- a/target/ppc/translate.c
104
--- a/target/ppc/translate.c
39
+++ b/target/ppc/translate.c
105
+++ b/target/ppc/translate.c
40
@@ -XXX,XX +XXX,XX @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
106
@@ -XXX,XX +XXX,XX @@ static void gen_lqarx(DisasContext *ctx)
41
107
{
42
translator_loop(cs, tb, max_insns, pc, host_pc, &ppc_tr_ops, &ctx.base);
108
int rd = rD(ctx->opcode);
43
}
109
TCGv EA, hi, lo;
44
-
110
+ TCGv_i128 t16;
45
-void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb,
111
46
- target_ulong *data)
112
if (unlikely((rd & 1) || (rd == rA(ctx->opcode)) ||
47
-{
113
(rd == rB(ctx->opcode)))) {
48
- env->nip = data[0];
114
@@ -XXX,XX +XXX,XX @@ static void gen_lqarx(DisasContext *ctx)
49
-}
115
lo = cpu_gpr[rd + 1];
116
hi = cpu_gpr[rd];
117
118
- if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
119
- if (HAVE_ATOMIC128) {
120
- TCGv_i32 oi = tcg_temp_new_i32();
121
- if (ctx->le_mode) {
122
- tcg_gen_movi_i32(oi, make_memop_idx(MO_LE | MO_128 | MO_ALIGN,
123
- ctx->mem_idx));
124
- gen_helper_lq_le_parallel(lo, cpu_env, EA, oi);
125
- } else {
126
- tcg_gen_movi_i32(oi, make_memop_idx(MO_BE | MO_128 | MO_ALIGN,
127
- ctx->mem_idx));
128
- gen_helper_lq_be_parallel(lo, cpu_env, EA, oi);
129
- }
130
- tcg_gen_ld_i64(hi, cpu_env, offsetof(CPUPPCState, retxh));
131
- } else {
132
- /* Restart with exclusive lock. */
133
- gen_helper_exit_atomic(cpu_env);
134
- ctx->base.is_jmp = DISAS_NORETURN;
135
- return;
136
- }
137
- } else if (ctx->le_mode) {
138
- tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_LEUQ | MO_ALIGN_16);
139
- tcg_gen_mov_tl(cpu_reserve, EA);
140
- gen_addr_add(ctx, EA, EA, 8);
141
- tcg_gen_qemu_ld_i64(hi, EA, ctx->mem_idx, MO_LEUQ);
142
- } else {
143
- tcg_gen_qemu_ld_i64(hi, EA, ctx->mem_idx, MO_BEUQ | MO_ALIGN_16);
144
- tcg_gen_mov_tl(cpu_reserve, EA);
145
- gen_addr_add(ctx, EA, EA, 8);
146
- tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_BEUQ);
147
- }
148
+ t16 = tcg_temp_new_i128();
149
+ tcg_gen_qemu_ld_i128(t16, EA, ctx->mem_idx, DEF_MEMOP(MO_128 | MO_ALIGN));
150
+ tcg_gen_extr_i128_i64(lo, hi, t16);
151
152
tcg_gen_st_tl(hi, cpu_env, offsetof(CPUPPCState, reserve_val));
153
tcg_gen_st_tl(lo, cpu_env, offsetof(CPUPPCState, reserve_val2));
154
diff --git a/target/ppc/translate/fixedpoint-impl.c.inc b/target/ppc/translate/fixedpoint-impl.c.inc
155
index XXXXXXX..XXXXXXX 100644
156
--- a/target/ppc/translate/fixedpoint-impl.c.inc
157
+++ b/target/ppc/translate/fixedpoint-impl.c.inc
158
@@ -XXX,XX +XXX,XX @@ static bool do_ldst_quad(DisasContext *ctx, arg_D *a, bool store, bool prefixed)
159
#if defined(TARGET_PPC64)
160
TCGv ea;
161
TCGv_i64 low_addr_gpr, high_addr_gpr;
162
- MemOp mop;
163
+ TCGv_i128 t16;
164
165
REQUIRE_INSNS_FLAGS(ctx, 64BX);
166
167
@@ -XXX,XX +XXX,XX @@ static bool do_ldst_quad(DisasContext *ctx, arg_D *a, bool store, bool prefixed)
168
low_addr_gpr = cpu_gpr[a->rt + 1];
169
high_addr_gpr = cpu_gpr[a->rt];
170
}
171
+ t16 = tcg_temp_new_i128();
172
173
- if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
174
- if (HAVE_ATOMIC128) {
175
- mop = DEF_MEMOP(MO_128);
176
- TCGv_i32 oi = tcg_constant_i32(make_memop_idx(mop, ctx->mem_idx));
177
- if (store) {
178
- if (ctx->le_mode) {
179
- gen_helper_stq_le_parallel(cpu_env, ea, low_addr_gpr,
180
- high_addr_gpr, oi);
181
- } else {
182
- gen_helper_stq_be_parallel(cpu_env, ea, high_addr_gpr,
183
- low_addr_gpr, oi);
184
-
185
- }
186
- } else {
187
- if (ctx->le_mode) {
188
- gen_helper_lq_le_parallel(low_addr_gpr, cpu_env, ea, oi);
189
- tcg_gen_ld_i64(high_addr_gpr, cpu_env,
190
- offsetof(CPUPPCState, retxh));
191
- } else {
192
- gen_helper_lq_be_parallel(high_addr_gpr, cpu_env, ea, oi);
193
- tcg_gen_ld_i64(low_addr_gpr, cpu_env,
194
- offsetof(CPUPPCState, retxh));
195
- }
196
- }
197
- } else {
198
- /* Restart with exclusive lock. */
199
- gen_helper_exit_atomic(cpu_env);
200
- ctx->base.is_jmp = DISAS_NORETURN;
201
- }
202
+ if (store) {
203
+ tcg_gen_concat_i64_i128(t16, low_addr_gpr, high_addr_gpr);
204
+ tcg_gen_qemu_st_i128(t16, ea, ctx->mem_idx, DEF_MEMOP(MO_128));
205
} else {
206
- mop = DEF_MEMOP(MO_UQ);
207
- if (store) {
208
- tcg_gen_qemu_st_i64(low_addr_gpr, ea, ctx->mem_idx, mop);
209
- } else {
210
- tcg_gen_qemu_ld_i64(low_addr_gpr, ea, ctx->mem_idx, mop);
211
- }
212
-
213
- gen_addr_add(ctx, ea, ea, 8);
214
-
215
- if (store) {
216
- tcg_gen_qemu_st_i64(high_addr_gpr, ea, ctx->mem_idx, mop);
217
- } else {
218
- tcg_gen_qemu_ld_i64(high_addr_gpr, ea, ctx->mem_idx, mop);
219
- }
220
+ tcg_gen_qemu_ld_i128(t16, ea, ctx->mem_idx, DEF_MEMOP(MO_128));
221
+ tcg_gen_extr_i128_i64(low_addr_gpr, high_addr_gpr, t16);
222
}
223
#else
224
qemu_build_not_reached();
50
--
225
--
51
2.34.1
226
2.34.1
52
227
53
228
diff view generated by jsdifflib
1
These items printf, and could be replaced with proper
1
No need to roll our own, as this is now provided by tcg.
2
tracepoints if we really cared.
2
This was the last use of retxl, so remove that too.
3
3
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: David Hildenbrand <david@redhat.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
---
7
accel/tcg/translate-all.c | 109 --------------------------------------
8
target/s390x/cpu.h | 3 --
8
1 file changed, 109 deletions(-)
9
target/s390x/helper.h | 4 ---
10
target/s390x/tcg/mem_helper.c | 61 --------------------------------
11
target/s390x/tcg/translate.c | 30 +++++-----------
12
target/s390x/tcg/insn-data.h.inc | 2 +-
13
5 files changed, 9 insertions(+), 91 deletions(-)
9
14
10
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
15
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
11
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
12
--- a/accel/tcg/translate-all.c
17
--- a/target/s390x/cpu.h
13
+++ b/accel/tcg/translate-all.c
18
+++ b/target/s390x/cpu.h
14
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ struct CPUArchState {
15
#include "tb-context.h"
20
16
#include "internal.h"
21
float_status fpu_status; /* passed to softfloat lib */
17
22
18
-/* #define DEBUG_TB_INVALIDATE */
23
- /* The low part of a 128-bit return, or remainder of a divide. */
19
-/* #define DEBUG_TB_FLUSH */
24
- uint64_t retxl;
20
/* make various TB consistency checks */
21
-/* #define DEBUG_TB_CHECK */
22
-
25
-
23
-#ifdef DEBUG_TB_INVALIDATE
26
PSW psw;
24
-#define DEBUG_TB_INVALIDATE_GATE 1
27
25
-#else
28
S390CrashReason crash_reason;
26
-#define DEBUG_TB_INVALIDATE_GATE 0
29
diff --git a/target/s390x/helper.h b/target/s390x/helper.h
27
-#endif
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/s390x/helper.h
32
+++ b/target/s390x/helper.h
33
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(sfas, TCG_CALL_NO_WG, void, env, i64)
34
DEF_HELPER_FLAGS_2(srnm, TCG_CALL_NO_WG, void, env, i64)
35
DEF_HELPER_FLAGS_1(popcnt, TCG_CALL_NO_RWG_SE, i64, i64)
36
DEF_HELPER_2(stfle, i32, env, i64)
37
-DEF_HELPER_FLAGS_2(lpq, TCG_CALL_NO_WG, i64, env, i64)
38
-DEF_HELPER_FLAGS_2(lpq_parallel, TCG_CALL_NO_WG, i64, env, i64)
39
-DEF_HELPER_FLAGS_4(stpq, TCG_CALL_NO_WG, void, env, i64, i64, i64)
40
-DEF_HELPER_FLAGS_4(stpq_parallel, TCG_CALL_NO_WG, void, env, i64, i64, i64)
41
DEF_HELPER_4(mvcos, i32, env, i64, i64, i64)
42
DEF_HELPER_4(cu12, i32, env, i32, i32, i32)
43
DEF_HELPER_4(cu14, i32, env, i32, i32, i32)
44
diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/s390x/tcg/mem_helper.c
47
+++ b/target/s390x/tcg/mem_helper.c
48
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr)
49
}
50
#endif
51
52
-/* load pair from quadword */
53
-uint64_t HELPER(lpq)(CPUS390XState *env, uint64_t addr)
54
-{
55
- uintptr_t ra = GETPC();
56
- uint64_t hi, lo;
28
-
57
-
29
-#ifdef DEBUG_TB_FLUSH
58
- check_alignment(env, addr, 16, ra);
30
-#define DEBUG_TB_FLUSH_GATE 1
59
- hi = cpu_ldq_data_ra(env, addr + 0, ra);
31
-#else
60
- lo = cpu_ldq_data_ra(env, addr + 8, ra);
32
-#define DEBUG_TB_FLUSH_GATE 0
33
-#endif
34
-
61
-
35
-#if !defined(CONFIG_USER_ONLY)
62
- env->retxl = lo;
36
-/* TB consistency checks only implemented for usermode emulation. */
63
- return hi;
37
-#undef DEBUG_TB_CHECK
38
-#endif
39
-
40
-#ifdef DEBUG_TB_CHECK
41
-#define DEBUG_TB_CHECK_GATE 1
42
-#else
43
-#define DEBUG_TB_CHECK_GATE 0
44
-#endif
45
46
/* Access to the various translations structures need to be serialised via locks
47
* for consistency.
48
@@ -XXX,XX +XXX,XX @@ static void page_flush_tb(void)
49
}
50
}
51
52
-static gboolean tb_host_size_iter(gpointer key, gpointer value, gpointer data)
53
-{
54
- const TranslationBlock *tb = value;
55
- size_t *size = data;
56
-
57
- *size += tb->tc.size;
58
- return false;
59
-}
64
-}
60
-
65
-
61
/* flush all the translation blocks */
66
-uint64_t HELPER(lpq_parallel)(CPUS390XState *env, uint64_t addr)
62
static void do_tb_flush(CPUState *cpu, run_on_cpu_data tb_flush_count)
67
-{
63
{
68
- uintptr_t ra = GETPC();
64
@@ -XXX,XX +XXX,XX @@ static void do_tb_flush(CPUState *cpu, run_on_cpu_data tb_flush_count)
69
- uint64_t hi, lo;
65
}
70
- int mem_idx;
66
did_flush = true;
71
- MemOpIdx oi;
67
72
- Int128 v;
68
- if (DEBUG_TB_FLUSH_GATE) {
69
- size_t nb_tbs = tcg_nb_tbs();
70
- size_t host_size = 0;
71
-
73
-
72
- tcg_tb_foreach(tb_host_size_iter, &host_size);
74
- assert(HAVE_ATOMIC128);
73
- printf("qemu: flush code_size=%zu nb_tbs=%zu avg_tb_size=%zu\n",
74
- tcg_code_size(), nb_tbs, nb_tbs > 0 ? host_size / nb_tbs : 0);
75
- }
76
-
75
-
77
CPU_FOREACH(cpu) {
76
- mem_idx = cpu_mmu_index(env, false);
78
tcg_flush_jmp_cache(cpu);
77
- oi = make_memop_idx(MO_TEUQ | MO_ALIGN_16, mem_idx);
79
}
78
- v = cpu_atomic_ldo_be_mmu(env, addr, oi, ra);
80
@@ -XXX,XX +XXX,XX @@ void tb_flush(CPUState *cpu)
79
- hi = int128_gethi(v);
81
}
80
- lo = int128_getlo(v);
82
}
83
84
-/*
85
- * Formerly ifdef DEBUG_TB_CHECK. These debug functions are user-mode-only,
86
- * so in order to prevent bit rot we compile them unconditionally in user-mode,
87
- * and let the optimizer get rid of them by wrapping their user-only callers
88
- * with if (DEBUG_TB_CHECK_GATE).
89
- */
90
-#ifdef CONFIG_USER_ONLY
91
-
81
-
92
-static void do_tb_invalidate_check(void *p, uint32_t hash, void *userp)
82
- env->retxl = lo;
93
-{
83
- return hi;
94
- TranslationBlock *tb = p;
95
- target_ulong addr = *(target_ulong *)userp;
96
-
97
- if (!(addr + TARGET_PAGE_SIZE <= tb_pc(tb) ||
98
- addr >= tb_pc(tb) + tb->size)) {
99
- printf("ERROR invalidate: address=" TARGET_FMT_lx
100
- " PC=%08lx size=%04x\n", addr, (long)tb_pc(tb), tb->size);
101
- }
102
-}
84
-}
103
-
85
-
104
-/* verify that all the pages have correct rights for code
86
-/* store pair to quadword */
105
- *
87
-void HELPER(stpq)(CPUS390XState *env, uint64_t addr,
106
- * Called with mmap_lock held.
88
- uint64_t low, uint64_t high)
107
- */
108
-static void tb_invalidate_check(target_ulong address)
109
-{
89
-{
110
- address &= TARGET_PAGE_MASK;
90
- uintptr_t ra = GETPC();
111
- qht_iter(&tb_ctx.htable, do_tb_invalidate_check, &address);
91
-
92
- check_alignment(env, addr, 16, ra);
93
- cpu_stq_data_ra(env, addr + 0, high, ra);
94
- cpu_stq_data_ra(env, addr + 8, low, ra);
112
-}
95
-}
113
-
96
-
114
-static void do_tb_page_check(void *p, uint32_t hash, void *userp)
97
-void HELPER(stpq_parallel)(CPUS390XState *env, uint64_t addr,
98
- uint64_t low, uint64_t high)
115
-{
99
-{
116
- TranslationBlock *tb = p;
100
- uintptr_t ra = GETPC();
117
- int flags1, flags2;
101
- int mem_idx;
102
- MemOpIdx oi;
103
- Int128 v;
118
-
104
-
119
- flags1 = page_get_flags(tb_pc(tb));
105
- assert(HAVE_ATOMIC128);
120
- flags2 = page_get_flags(tb_pc(tb) + tb->size - 1);
106
-
121
- if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
107
- mem_idx = cpu_mmu_index(env, false);
122
- printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
108
- oi = make_memop_idx(MO_TEUQ | MO_ALIGN_16, mem_idx);
123
- (long)tb_pc(tb), tb->size, flags1, flags2);
109
- v = int128_make128(low, high);
124
- }
110
- cpu_atomic_sto_be_mmu(env, addr, v, oi, ra);
125
-}
111
-}
126
-
112
-
127
-/* verify that all the pages have correct rights for code */
113
/* Execute instruction. This instruction executes an insn modified with
128
-static void tb_page_check(void)
114
the contents of r1. It does not change the executed instruction in memory;
115
it does not change the program counter.
116
diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/target/s390x/tcg/translate.c
119
+++ b/target/s390x/tcg/translate.c
120
@@ -XXX,XX +XXX,XX @@ static void store_freg32_i64(int reg, TCGv_i64 v)
121
tcg_gen_st32_i64(v, cpu_env, freg32_offset(reg));
122
}
123
124
-static void return_low128(TCGv_i64 dest)
129
-{
125
-{
130
- qht_iter(&tb_ctx.htable, do_tb_page_check, NULL);
126
- tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUS390XState, retxl));
131
-}
127
-}
132
-
128
-
133
-#endif /* CONFIG_USER_ONLY */
129
static void update_psw_addr(DisasContext *s)
134
-
130
{
135
/*
131
/* psw.addr */
136
* user-mode: call with mmap_lock held
132
@@ -XXX,XX +XXX,XX @@ static DisasJumpType op_lpd(DisasContext *s, DisasOps *o)
137
* !user-mode: call with @pd->lock held
133
138
@@ -XXX,XX +XXX,XX @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
134
static DisasJumpType op_lpq(DisasContext *s, DisasOps *o)
139
page_unlock(p2);
135
{
140
}
136
- if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
141
page_unlock(p);
137
- gen_helper_lpq(o->out, cpu_env, o->in2);
142
-
138
- } else if (HAVE_ATOMIC128) {
143
-#ifdef CONFIG_USER_ONLY
139
- gen_helper_lpq_parallel(o->out, cpu_env, o->in2);
144
- if (DEBUG_TB_CHECK_GATE) {
140
- } else {
145
- tb_page_check();
141
- gen_helper_exit_atomic(cpu_env);
142
- return DISAS_NORETURN;
146
- }
143
- }
147
-#endif
144
- return_low128(o->out2);
148
return tb;
145
+ o->out_128 = tcg_temp_new_i128();
146
+ tcg_gen_qemu_ld_i128(o->out_128, o->in2, get_mem_index(s),
147
+ MO_TE | MO_128 | MO_ALIGN);
148
return DISAS_NEXT;
149
}
149
}
150
150
151
@@ -XXX,XX +XXX,XX @@ void page_protect(tb_page_addr_t page_addr)
151
@@ -XXX,XX +XXX,XX @@ static DisasJumpType op_stmh(DisasContext *s, DisasOps *o)
152
}
152
153
mprotect(g2h_untagged(page_addr), qemu_host_page_size,
153
static DisasJumpType op_stpq(DisasContext *s, DisasOps *o)
154
(prot & PAGE_BITS) & ~PAGE_WRITE);
154
{
155
- if (DEBUG_TB_INVALIDATE_GATE) {
155
- if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
156
- printf("protecting code page: 0x" TB_PAGE_ADDR_FMT "\n", page_addr);
156
- gen_helper_stpq(cpu_env, o->in2, o->out2, o->out);
157
- }
157
- } else if (HAVE_ATOMIC128) {
158
}
158
- gen_helper_stpq_parallel(cpu_env, o->in2, o->out2, o->out);
159
- } else {
160
- gen_helper_exit_atomic(cpu_env);
161
- return DISAS_NORETURN;
162
- }
163
+ TCGv_i128 t16 = tcg_temp_new_i128();
164
+
165
+ tcg_gen_concat_i64_i128(t16, o->out2, o->out);
166
+ tcg_gen_qemu_st_i128(t16, o->in2, get_mem_index(s),
167
+ MO_TE | MO_128 | MO_ALIGN);
168
return DISAS_NEXT;
159
}
169
}
160
170
161
@@ -XXX,XX +XXX,XX @@ int page_unprotect(target_ulong address, uintptr_t pc)
171
diff --git a/target/s390x/tcg/insn-data.h.inc b/target/s390x/tcg/insn-data.h.inc
162
/* and since the content will be modified, we must invalidate
172
index XXXXXXX..XXXXXXX 100644
163
the corresponding translated code. */
173
--- a/target/s390x/tcg/insn-data.h.inc
164
current_tb_invalidated |= tb_invalidate_phys_page(addr, pc);
174
+++ b/target/s390x/tcg/insn-data.h.inc
165
-#ifdef CONFIG_USER_ONLY
175
@@ -XXX,XX +XXX,XX @@
166
- if (DEBUG_TB_CHECK_GATE) {
176
D(0xc804, LPD, SSF, ILA, 0, 0, new_P, r3_P32, lpd, 0, MO_TEUL)
167
- tb_invalidate_check(addr);
177
D(0xc805, LPDG, SSF, ILA, 0, 0, new_P, r3_P64, lpd, 0, MO_TEUQ)
168
- }
178
/* LOAD PAIR FROM QUADWORD */
169
-#endif
179
- C(0xe38f, LPQ, RXY_a, Z, 0, a2, r1_P, 0, lpq, 0)
170
}
180
+ C(0xe38f, LPQ, RXY_a, Z, 0, a2, 0, r1_D64, lpq, 0)
171
mprotect((void *)g2h_untagged(host_start), qemu_host_page_size,
181
/* LOAD POSITIVE */
172
prot & PAGE_BITS);
182
C(0x1000, LPR, RR_a, Z, 0, r2_32s, new, r1_32, abs, abs32)
183
C(0xb900, LPGR, RRE, Z, 0, r2, r1, 0, abs, abs64)
173
--
184
--
174
2.34.1
185
2.34.1
175
186
176
187
diff view generated by jsdifflib
1
With the current structure of cputlb.c, there is no difference
2
between the little-endian and big-endian entry points, aside
3
from the assert. Unify the pairs of functions.
4
5
The only use of the functions with explicit endianness was in
6
target/sparc64, and that was only to satisfy the assert: the
7
correct endianness is already built into memop.
8
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
12
---
4
target/nios2/cpu.c | 11 +++++++++++
13
include/exec/cpu_ldst.h | 58 ++-----
5
target/nios2/translate.c | 6 ------
14
accel/tcg/cputlb.c | 122 +++-----------
6
2 files changed, 11 insertions(+), 6 deletions(-)
15
accel/tcg/user-exec.c | 322 ++++++++++--------------------------
16
target/arm/tcg/m_helper.c | 4 +-
17
target/sparc/ldst_helper.c | 18 +-
18
accel/tcg/ldst_common.c.inc | 24 +--
19
6 files changed, 137 insertions(+), 411 deletions(-)
7
20
8
diff --git a/target/nios2/cpu.c b/target/nios2/cpu.c
21
diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
9
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
10
--- a/target/nios2/cpu.c
23
--- a/include/exec/cpu_ldst.h
11
+++ b/target/nios2/cpu.c
24
+++ b/include/exec/cpu_ldst.h
12
@@ -XXX,XX +XXX,XX @@ static vaddr nios2_cpu_get_pc(CPUState *cs)
25
@@ -XXX,XX +XXX,XX @@ void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr ptr, uint64_t val,
13
return env->pc;
26
int mmu_idx, uintptr_t ra);
14
}
27
15
28
uint8_t cpu_ldb_mmu(CPUArchState *env, abi_ptr ptr, MemOpIdx oi, uintptr_t ra);
16
+static void nios2_restore_state_to_opc(CPUState *cs,
29
-uint16_t cpu_ldw_be_mmu(CPUArchState *env, abi_ptr ptr,
17
+ const TranslationBlock *tb,
30
- MemOpIdx oi, uintptr_t ra);
18
+ const uint64_t *data)
31
-uint32_t cpu_ldl_be_mmu(CPUArchState *env, abi_ptr ptr,
32
- MemOpIdx oi, uintptr_t ra);
33
-uint64_t cpu_ldq_be_mmu(CPUArchState *env, abi_ptr ptr,
34
- MemOpIdx oi, uintptr_t ra);
35
-uint16_t cpu_ldw_le_mmu(CPUArchState *env, abi_ptr ptr,
36
- MemOpIdx oi, uintptr_t ra);
37
-uint32_t cpu_ldl_le_mmu(CPUArchState *env, abi_ptr ptr,
38
- MemOpIdx oi, uintptr_t ra);
39
-uint64_t cpu_ldq_le_mmu(CPUArchState *env, abi_ptr ptr,
40
- MemOpIdx oi, uintptr_t ra);
41
-
42
-Int128 cpu_ld16_be_mmu(CPUArchState *env, abi_ptr addr,
43
- MemOpIdx oi, uintptr_t ra);
44
-Int128 cpu_ld16_le_mmu(CPUArchState *env, abi_ptr addr,
45
- MemOpIdx oi, uintptr_t ra);
46
+uint16_t cpu_ldw_mmu(CPUArchState *env, abi_ptr ptr, MemOpIdx oi, uintptr_t ra);
47
+uint32_t cpu_ldl_mmu(CPUArchState *env, abi_ptr ptr, MemOpIdx oi, uintptr_t ra);
48
+uint64_t cpu_ldq_mmu(CPUArchState *env, abi_ptr ptr, MemOpIdx oi, uintptr_t ra);
49
+Int128 cpu_ld16_mmu(CPUArchState *env, abi_ptr addr, MemOpIdx oi, uintptr_t ra);
50
51
void cpu_stb_mmu(CPUArchState *env, abi_ptr ptr, uint8_t val,
52
MemOpIdx oi, uintptr_t ra);
53
-void cpu_stw_be_mmu(CPUArchState *env, abi_ptr ptr, uint16_t val,
54
- MemOpIdx oi, uintptr_t ra);
55
-void cpu_stl_be_mmu(CPUArchState *env, abi_ptr ptr, uint32_t val,
56
- MemOpIdx oi, uintptr_t ra);
57
-void cpu_stq_be_mmu(CPUArchState *env, abi_ptr ptr, uint64_t val,
58
- MemOpIdx oi, uintptr_t ra);
59
-void cpu_stw_le_mmu(CPUArchState *env, abi_ptr ptr, uint16_t val,
60
- MemOpIdx oi, uintptr_t ra);
61
-void cpu_stl_le_mmu(CPUArchState *env, abi_ptr ptr, uint32_t val,
62
- MemOpIdx oi, uintptr_t ra);
63
-void cpu_stq_le_mmu(CPUArchState *env, abi_ptr ptr, uint64_t val,
64
- MemOpIdx oi, uintptr_t ra);
65
-
66
-void cpu_st16_be_mmu(CPUArchState *env, abi_ptr addr, Int128 val,
67
- MemOpIdx oi, uintptr_t ra);
68
-void cpu_st16_le_mmu(CPUArchState *env, abi_ptr addr, Int128 val,
69
- MemOpIdx oi, uintptr_t ra);
70
+void cpu_stw_mmu(CPUArchState *env, abi_ptr ptr, uint16_t val,
71
+ MemOpIdx oi, uintptr_t ra);
72
+void cpu_stl_mmu(CPUArchState *env, abi_ptr ptr, uint32_t val,
73
+ MemOpIdx oi, uintptr_t ra);
74
+void cpu_stq_mmu(CPUArchState *env, abi_ptr ptr, uint64_t val,
75
+ MemOpIdx oi, uintptr_t ra);
76
+void cpu_st16_mmu(CPUArchState *env, abi_ptr addr, Int128 val,
77
+ MemOpIdx oi, uintptr_t ra);
78
79
uint32_t cpu_atomic_cmpxchgb_mmu(CPUArchState *env, target_ulong addr,
80
uint32_t cmpv, uint32_t newv,
81
@@ -XXX,XX +XXX,XX @@ static inline CPUTLBEntry *tlb_entry(CPUArchState *env, uintptr_t mmu_idx,
82
# define cpu_ldsw_mmuidx_ra cpu_ldsw_be_mmuidx_ra
83
# define cpu_ldl_mmuidx_ra cpu_ldl_be_mmuidx_ra
84
# define cpu_ldq_mmuidx_ra cpu_ldq_be_mmuidx_ra
85
-# define cpu_ldw_mmu cpu_ldw_be_mmu
86
-# define cpu_ldl_mmu cpu_ldl_be_mmu
87
-# define cpu_ldq_mmu cpu_ldq_be_mmu
88
# define cpu_stw_data cpu_stw_be_data
89
# define cpu_stl_data cpu_stl_be_data
90
# define cpu_stq_data cpu_stq_be_data
91
@@ -XXX,XX +XXX,XX @@ static inline CPUTLBEntry *tlb_entry(CPUArchState *env, uintptr_t mmu_idx,
92
# define cpu_stw_mmuidx_ra cpu_stw_be_mmuidx_ra
93
# define cpu_stl_mmuidx_ra cpu_stl_be_mmuidx_ra
94
# define cpu_stq_mmuidx_ra cpu_stq_be_mmuidx_ra
95
-# define cpu_stw_mmu cpu_stw_be_mmu
96
-# define cpu_stl_mmu cpu_stl_be_mmu
97
-# define cpu_stq_mmu cpu_stq_be_mmu
98
#else
99
# define cpu_lduw_data cpu_lduw_le_data
100
# define cpu_ldsw_data cpu_ldsw_le_data
101
@@ -XXX,XX +XXX,XX @@ static inline CPUTLBEntry *tlb_entry(CPUArchState *env, uintptr_t mmu_idx,
102
# define cpu_ldsw_mmuidx_ra cpu_ldsw_le_mmuidx_ra
103
# define cpu_ldl_mmuidx_ra cpu_ldl_le_mmuidx_ra
104
# define cpu_ldq_mmuidx_ra cpu_ldq_le_mmuidx_ra
105
-# define cpu_ldw_mmu cpu_ldw_le_mmu
106
-# define cpu_ldl_mmu cpu_ldl_le_mmu
107
-# define cpu_ldq_mmu cpu_ldq_le_mmu
108
# define cpu_stw_data cpu_stw_le_data
109
# define cpu_stl_data cpu_stl_le_data
110
# define cpu_stq_data cpu_stq_le_data
111
@@ -XXX,XX +XXX,XX @@ static inline CPUTLBEntry *tlb_entry(CPUArchState *env, uintptr_t mmu_idx,
112
# define cpu_stw_mmuidx_ra cpu_stw_le_mmuidx_ra
113
# define cpu_stl_mmuidx_ra cpu_stl_le_mmuidx_ra
114
# define cpu_stq_mmuidx_ra cpu_stq_le_mmuidx_ra
115
-# define cpu_stw_mmu cpu_stw_le_mmu
116
-# define cpu_stl_mmu cpu_stl_le_mmu
117
-# define cpu_stq_mmu cpu_stq_le_mmu
118
#endif
119
120
uint8_t cpu_ldb_code_mmu(CPUArchState *env, abi_ptr addr,
121
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
122
index XXXXXXX..XXXXXXX 100644
123
--- a/accel/tcg/cputlb.c
124
+++ b/accel/tcg/cputlb.c
125
@@ -XXX,XX +XXX,XX @@ uint8_t cpu_ldb_mmu(CPUArchState *env, abi_ptr addr, MemOpIdx oi, uintptr_t ra)
126
return ret;
127
}
128
129
-uint16_t cpu_ldw_be_mmu(CPUArchState *env, abi_ptr addr,
130
- MemOpIdx oi, uintptr_t ra)
131
+uint16_t cpu_ldw_mmu(CPUArchState *env, abi_ptr addr,
132
+ MemOpIdx oi, uintptr_t ra)
133
{
134
uint16_t ret;
135
136
- tcg_debug_assert((get_memop(oi) & (MO_BSWAP | MO_SIZE)) == MO_BEUW);
137
+ tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_16);
138
ret = do_ld2_mmu(env, addr, oi, ra, MMU_DATA_LOAD);
139
plugin_load_cb(env, addr, oi);
140
return ret;
141
}
142
143
-uint32_t cpu_ldl_be_mmu(CPUArchState *env, abi_ptr addr,
144
- MemOpIdx oi, uintptr_t ra)
145
+uint32_t cpu_ldl_mmu(CPUArchState *env, abi_ptr addr,
146
+ MemOpIdx oi, uintptr_t ra)
147
{
148
uint32_t ret;
149
150
- tcg_debug_assert((get_memop(oi) & (MO_BSWAP | MO_SIZE)) == MO_BEUL);
151
+ tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_32);
152
ret = do_ld4_mmu(env, addr, oi, ra, MMU_DATA_LOAD);
153
plugin_load_cb(env, addr, oi);
154
return ret;
155
}
156
157
-uint64_t cpu_ldq_be_mmu(CPUArchState *env, abi_ptr addr,
158
- MemOpIdx oi, uintptr_t ra)
159
+uint64_t cpu_ldq_mmu(CPUArchState *env, abi_ptr addr,
160
+ MemOpIdx oi, uintptr_t ra)
161
{
162
uint64_t ret;
163
164
- tcg_debug_assert((get_memop(oi) & (MO_BSWAP | MO_SIZE)) == MO_BEUQ);
165
+ tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_64);
166
ret = do_ld8_mmu(env, addr, oi, ra, MMU_DATA_LOAD);
167
plugin_load_cb(env, addr, oi);
168
return ret;
169
}
170
171
-uint16_t cpu_ldw_le_mmu(CPUArchState *env, abi_ptr addr,
172
- MemOpIdx oi, uintptr_t ra)
173
-{
174
- uint16_t ret;
175
-
176
- tcg_debug_assert((get_memop(oi) & (MO_BSWAP | MO_SIZE)) == MO_LEUW);
177
- ret = do_ld2_mmu(env, addr, oi, ra, MMU_DATA_LOAD);
178
- plugin_load_cb(env, addr, oi);
179
- return ret;
180
-}
181
-
182
-uint32_t cpu_ldl_le_mmu(CPUArchState *env, abi_ptr addr,
183
- MemOpIdx oi, uintptr_t ra)
184
-{
185
- uint32_t ret;
186
-
187
- tcg_debug_assert((get_memop(oi) & (MO_BSWAP | MO_SIZE)) == MO_LEUL);
188
- ret = do_ld4_mmu(env, addr, oi, ra, MMU_DATA_LOAD);
189
- plugin_load_cb(env, addr, oi);
190
- return ret;
191
-}
192
-
193
-uint64_t cpu_ldq_le_mmu(CPUArchState *env, abi_ptr addr,
194
- MemOpIdx oi, uintptr_t ra)
195
-{
196
- uint64_t ret;
197
-
198
- tcg_debug_assert((get_memop(oi) & (MO_BSWAP | MO_SIZE)) == MO_LEUQ);
199
- ret = do_ld8_mmu(env, addr, oi, ra, MMU_DATA_LOAD);
200
- plugin_load_cb(env, addr, oi);
201
- return ret;
202
-}
203
-
204
-Int128 cpu_ld16_be_mmu(CPUArchState *env, abi_ptr addr,
205
- MemOpIdx oi, uintptr_t ra)
206
+Int128 cpu_ld16_mmu(CPUArchState *env, abi_ptr addr,
207
+ MemOpIdx oi, uintptr_t ra)
208
{
209
Int128 ret;
210
211
- tcg_debug_assert((get_memop(oi) & (MO_BSWAP|MO_SIZE)) == (MO_BE|MO_128));
212
- ret = do_ld16_mmu(env, addr, oi, ra);
213
- plugin_load_cb(env, addr, oi);
214
- return ret;
215
-}
216
-
217
-Int128 cpu_ld16_le_mmu(CPUArchState *env, abi_ptr addr,
218
- MemOpIdx oi, uintptr_t ra)
219
-{
220
- Int128 ret;
221
-
222
- tcg_debug_assert((get_memop(oi) & (MO_BSWAP|MO_SIZE)) == (MO_LE|MO_128));
223
+ tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_128);
224
ret = do_ld16_mmu(env, addr, oi, ra);
225
plugin_load_cb(env, addr, oi);
226
return ret;
227
@@ -XXX,XX +XXX,XX @@ void cpu_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
228
plugin_store_cb(env, addr, oi);
229
}
230
231
-void cpu_stw_be_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
232
- MemOpIdx oi, uintptr_t retaddr)
233
+void cpu_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
234
+ MemOpIdx oi, uintptr_t retaddr)
235
{
236
- tcg_debug_assert((get_memop(oi) & (MO_BSWAP | MO_SIZE)) == MO_BEUW);
237
+ tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_16);
238
do_st2_mmu(env, addr, val, oi, retaddr);
239
plugin_store_cb(env, addr, oi);
240
}
241
242
-void cpu_stl_be_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
243
+void cpu_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
244
MemOpIdx oi, uintptr_t retaddr)
245
{
246
- tcg_debug_assert((get_memop(oi) & (MO_BSWAP | MO_SIZE)) == MO_BEUL);
247
+ tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_32);
248
do_st4_mmu(env, addr, val, oi, retaddr);
249
plugin_store_cb(env, addr, oi);
250
}
251
252
-void cpu_stq_be_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
253
- MemOpIdx oi, uintptr_t retaddr)
254
+void cpu_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
255
+ MemOpIdx oi, uintptr_t retaddr)
256
{
257
- tcg_debug_assert((get_memop(oi) & (MO_BSWAP | MO_SIZE)) == MO_BEUQ);
258
+ tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_64);
259
do_st8_mmu(env, addr, val, oi, retaddr);
260
plugin_store_cb(env, addr, oi);
261
}
262
263
-void cpu_stw_le_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
264
- MemOpIdx oi, uintptr_t retaddr)
265
+void cpu_st16_mmu(CPUArchState *env, target_ulong addr, Int128 val,
266
+ MemOpIdx oi, uintptr_t retaddr)
267
{
268
- tcg_debug_assert((get_memop(oi) & (MO_BSWAP | MO_SIZE)) == MO_LEUW);
269
- do_st2_mmu(env, addr, val, oi, retaddr);
270
- plugin_store_cb(env, addr, oi);
271
-}
272
-
273
-void cpu_stl_le_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
274
- MemOpIdx oi, uintptr_t retaddr)
275
-{
276
- tcg_debug_assert((get_memop(oi) & (MO_BSWAP | MO_SIZE)) == MO_LEUL);
277
- do_st4_mmu(env, addr, val, oi, retaddr);
278
- plugin_store_cb(env, addr, oi);
279
-}
280
-
281
-void cpu_stq_le_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
282
- MemOpIdx oi, uintptr_t retaddr)
283
-{
284
- tcg_debug_assert((get_memop(oi) & (MO_BSWAP | MO_SIZE)) == MO_LEUQ);
285
- do_st8_mmu(env, addr, val, oi, retaddr);
286
- plugin_store_cb(env, addr, oi);
287
-}
288
-
289
-void cpu_st16_be_mmu(CPUArchState *env, target_ulong addr, Int128 val,
290
- MemOpIdx oi, uintptr_t retaddr)
291
-{
292
- tcg_debug_assert((get_memop(oi) & (MO_BSWAP|MO_SIZE)) == (MO_BE|MO_128));
293
- do_st16_mmu(env, addr, val, oi, retaddr);
294
- plugin_store_cb(env, addr, oi);
295
-}
296
-
297
-void cpu_st16_le_mmu(CPUArchState *env, target_ulong addr, Int128 val,
298
- MemOpIdx oi, uintptr_t retaddr)
299
-{
300
- tcg_debug_assert((get_memop(oi) & (MO_BSWAP|MO_SIZE)) == (MO_LE|MO_128));
301
+ tcg_debug_assert((get_memop(oi) & MO_SIZE) == MO_128);
302
do_st16_mmu(env, addr, val, oi, retaddr);
303
plugin_store_cb(env, addr, oi);
304
}
305
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
306
index XXXXXXX..XXXXXXX 100644
307
--- a/accel/tcg/user-exec.c
308
+++ b/accel/tcg/user-exec.c
309
@@ -XXX,XX +XXX,XX @@ uint8_t cpu_ldb_mmu(CPUArchState *env, abi_ptr addr,
310
return ret;
311
}
312
313
-static uint16_t do_ld2_he_mmu(CPUArchState *env, abi_ptr addr,
314
- MemOp mop, uintptr_t ra)
315
+static uint16_t do_ld2_mmu(CPUArchState *env, abi_ptr addr,
316
+ MemOp mop, uintptr_t ra)
317
{
318
void *haddr;
319
uint16_t ret;
320
@@ -XXX,XX +XXX,XX @@ static uint16_t do_ld2_he_mmu(CPUArchState *env, abi_ptr addr,
321
haddr = cpu_mmu_lookup(env, addr, mop, ra, MMU_DATA_LOAD);
322
ret = load_atom_2(env, ra, haddr, mop);
323
clear_helper_retaddr();
324
+
325
+ if (mop & MO_BSWAP) {
326
+ ret = bswap16(ret);
327
+ }
328
return ret;
329
}
330
331
tcg_target_ulong helper_lduw_mmu(CPUArchState *env, uint64_t addr,
332
MemOpIdx oi, uintptr_t ra)
333
{
334
- MemOp mop = get_memop(oi);
335
- uint16_t ret = do_ld2_he_mmu(env, addr, mop, ra);
336
-
337
- if (mop & MO_BSWAP) {
338
- ret = bswap16(ret);
339
- }
340
- return ret;
341
+ return do_ld2_mmu(env, addr, get_memop(oi), ra);
342
}
343
344
tcg_target_ulong helper_ldsw_mmu(CPUArchState *env, uint64_t addr,
345
MemOpIdx oi, uintptr_t ra)
346
{
347
- MemOp mop = get_memop(oi);
348
- int16_t ret = do_ld2_he_mmu(env, addr, mop, ra);
349
+ return (int16_t)do_ld2_mmu(env, addr, get_memop(oi), ra);
350
+}
351
352
- if (mop & MO_BSWAP) {
353
- ret = bswap16(ret);
354
- }
355
+uint16_t cpu_ldw_mmu(CPUArchState *env, abi_ptr addr,
356
+ MemOpIdx oi, uintptr_t ra)
19
+{
357
+{
20
+ Nios2CPU *cpu = NIOS2_CPU(cs);
358
+ uint16_t ret = do_ld2_mmu(env, addr, get_memop(oi), ra);
21
+ CPUNios2State *env = &cpu->env;
359
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
360
return ret;
361
}
362
363
-uint16_t cpu_ldw_be_mmu(CPUArchState *env, abi_ptr addr,
364
- MemOpIdx oi, uintptr_t ra)
365
-{
366
- MemOp mop = get_memop(oi);
367
- uint16_t ret;
368
-
369
- tcg_debug_assert((mop & MO_BSWAP) == MO_BE);
370
- ret = do_ld2_he_mmu(env, addr, mop, ra);
371
- qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
372
- return cpu_to_be16(ret);
373
-}
374
-
375
-uint16_t cpu_ldw_le_mmu(CPUArchState *env, abi_ptr addr,
376
- MemOpIdx oi, uintptr_t ra)
377
-{
378
- MemOp mop = get_memop(oi);
379
- uint16_t ret;
380
-
381
- tcg_debug_assert((mop & MO_BSWAP) == MO_LE);
382
- ret = do_ld2_he_mmu(env, addr, mop, ra);
383
- qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
384
- return cpu_to_le16(ret);
385
-}
386
-
387
-static uint32_t do_ld4_he_mmu(CPUArchState *env, abi_ptr addr,
388
- MemOp mop, uintptr_t ra)
389
+static uint32_t do_ld4_mmu(CPUArchState *env, abi_ptr addr,
390
+ MemOp mop, uintptr_t ra)
391
{
392
void *haddr;
393
uint32_t ret;
394
@@ -XXX,XX +XXX,XX @@ static uint32_t do_ld4_he_mmu(CPUArchState *env, abi_ptr addr,
395
haddr = cpu_mmu_lookup(env, addr, mop, ra, MMU_DATA_LOAD);
396
ret = load_atom_4(env, ra, haddr, mop);
397
clear_helper_retaddr();
22
+
398
+
23
+ env->pc = data[0];
399
+ if (mop & MO_BSWAP) {
400
+ ret = bswap32(ret);
401
+ }
402
return ret;
403
}
404
405
tcg_target_ulong helper_ldul_mmu(CPUArchState *env, uint64_t addr,
406
MemOpIdx oi, uintptr_t ra)
407
{
408
- MemOp mop = get_memop(oi);
409
- uint32_t ret = do_ld4_he_mmu(env, addr, mop, ra);
410
-
411
- if (mop & MO_BSWAP) {
412
- ret = bswap32(ret);
413
- }
414
- return ret;
415
+ return do_ld4_mmu(env, addr, get_memop(oi), ra);
416
}
417
418
tcg_target_ulong helper_ldsl_mmu(CPUArchState *env, uint64_t addr,
419
MemOpIdx oi, uintptr_t ra)
420
{
421
- MemOp mop = get_memop(oi);
422
- int32_t ret = do_ld4_he_mmu(env, addr, mop, ra);
423
+ return (int32_t)do_ld4_mmu(env, addr, get_memop(oi), ra);
424
+}
425
426
- if (mop & MO_BSWAP) {
427
- ret = bswap32(ret);
428
- }
429
+uint32_t cpu_ldl_mmu(CPUArchState *env, abi_ptr addr,
430
+ MemOpIdx oi, uintptr_t ra)
431
+{
432
+ uint32_t ret = do_ld4_mmu(env, addr, get_memop(oi), ra);
433
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
434
return ret;
435
}
436
437
-uint32_t cpu_ldl_be_mmu(CPUArchState *env, abi_ptr addr,
438
- MemOpIdx oi, uintptr_t ra)
439
-{
440
- MemOp mop = get_memop(oi);
441
- uint32_t ret;
442
-
443
- tcg_debug_assert((mop & MO_BSWAP) == MO_BE);
444
- ret = do_ld4_he_mmu(env, addr, mop, ra);
445
- qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
446
- return cpu_to_be32(ret);
447
-}
448
-
449
-uint32_t cpu_ldl_le_mmu(CPUArchState *env, abi_ptr addr,
450
- MemOpIdx oi, uintptr_t ra)
451
-{
452
- MemOp mop = get_memop(oi);
453
- uint32_t ret;
454
-
455
- tcg_debug_assert((mop & MO_BSWAP) == MO_LE);
456
- ret = do_ld4_he_mmu(env, addr, mop, ra);
457
- qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
458
- return cpu_to_le32(ret);
459
-}
460
-
461
-static uint64_t do_ld8_he_mmu(CPUArchState *env, abi_ptr addr,
462
- MemOp mop, uintptr_t ra)
463
+static uint64_t do_ld8_mmu(CPUArchState *env, abi_ptr addr,
464
+ MemOp mop, uintptr_t ra)
465
{
466
void *haddr;
467
uint64_t ret;
468
@@ -XXX,XX +XXX,XX @@ static uint64_t do_ld8_he_mmu(CPUArchState *env, abi_ptr addr,
469
haddr = cpu_mmu_lookup(env, addr, mop, ra, MMU_DATA_LOAD);
470
ret = load_atom_8(env, ra, haddr, mop);
471
clear_helper_retaddr();
472
- return ret;
473
-}
474
-
475
-uint64_t helper_ldq_mmu(CPUArchState *env, uint64_t addr,
476
- MemOpIdx oi, uintptr_t ra)
477
-{
478
- MemOp mop = get_memop(oi);
479
- uint64_t ret = do_ld8_he_mmu(env, addr, mop, ra);
480
481
if (mop & MO_BSWAP) {
482
ret = bswap64(ret);
483
@@ -XXX,XX +XXX,XX @@ uint64_t helper_ldq_mmu(CPUArchState *env, uint64_t addr,
484
return ret;
485
}
486
487
-uint64_t cpu_ldq_be_mmu(CPUArchState *env, abi_ptr addr,
488
+uint64_t helper_ldq_mmu(CPUArchState *env, uint64_t addr,
489
MemOpIdx oi, uintptr_t ra)
490
{
491
- MemOp mop = get_memop(oi);
492
- uint64_t ret;
493
-
494
- tcg_debug_assert((mop & MO_BSWAP) == MO_BE);
495
- ret = do_ld8_he_mmu(env, addr, mop, ra);
496
- qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
497
- return cpu_to_be64(ret);
498
+ return do_ld8_mmu(env, addr, get_memop(oi), ra);
499
}
500
501
-uint64_t cpu_ldq_le_mmu(CPUArchState *env, abi_ptr addr,
502
- MemOpIdx oi, uintptr_t ra)
503
+uint64_t cpu_ldq_mmu(CPUArchState *env, abi_ptr addr,
504
+ MemOpIdx oi, uintptr_t ra)
505
{
506
- MemOp mop = get_memop(oi);
507
- uint64_t ret;
508
-
509
- tcg_debug_assert((mop & MO_BSWAP) == MO_LE);
510
- ret = do_ld8_he_mmu(env, addr, mop, ra);
511
+ uint64_t ret = do_ld8_mmu(env, addr, get_memop(oi), ra);
512
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
513
- return cpu_to_le64(ret);
514
+ return ret;
515
}
516
517
-static Int128 do_ld16_he_mmu(CPUArchState *env, abi_ptr addr,
518
- MemOp mop, uintptr_t ra)
519
+static Int128 do_ld16_mmu(CPUArchState *env, abi_ptr addr,
520
+ MemOp mop, uintptr_t ra)
521
{
522
void *haddr;
523
Int128 ret;
524
@@ -XXX,XX +XXX,XX @@ static Int128 do_ld16_he_mmu(CPUArchState *env, abi_ptr addr,
525
haddr = cpu_mmu_lookup(env, addr, mop, ra, MMU_DATA_LOAD);
526
ret = load_atom_16(env, ra, haddr, mop);
527
clear_helper_retaddr();
528
- return ret;
529
-}
530
-
531
-Int128 helper_ld16_mmu(CPUArchState *env, uint64_t addr,
532
- MemOpIdx oi, uintptr_t ra)
533
-{
534
- MemOp mop = get_memop(oi);
535
- Int128 ret = do_ld16_he_mmu(env, addr, mop, ra);
536
537
if (mop & MO_BSWAP) {
538
ret = bswap128(ret);
539
@@ -XXX,XX +XXX,XX @@ Int128 helper_ld16_mmu(CPUArchState *env, uint64_t addr,
540
return ret;
541
}
542
543
+Int128 helper_ld16_mmu(CPUArchState *env, uint64_t addr,
544
+ MemOpIdx oi, uintptr_t ra)
545
+{
546
+ return do_ld16_mmu(env, addr, get_memop(oi), ra);
24
+}
547
+}
25
+
548
+
26
static bool nios2_cpu_has_work(CPUState *cs)
549
Int128 helper_ld_i128(CPUArchState *env, uint64_t addr, MemOpIdx oi)
27
{
550
{
28
return cs->interrupt_request & CPU_INTERRUPT_HARD;
551
return helper_ld16_mmu(env, addr, oi, GETPC());
29
@@ -XXX,XX +XXX,XX @@ static const struct SysemuCPUOps nios2_sysemu_ops = {
552
}
30
553
31
static const struct TCGCPUOps nios2_tcg_ops = {
554
-Int128 cpu_ld16_be_mmu(CPUArchState *env, abi_ptr addr,
32
.initialize = nios2_tcg_init,
555
- MemOpIdx oi, uintptr_t ra)
33
+ .restore_state_to_opc = nios2_restore_state_to_opc,
556
+Int128 cpu_ld16_mmu(CPUArchState *env, abi_ptr addr,
34
557
+ MemOpIdx oi, uintptr_t ra)
35
#ifndef CONFIG_USER_ONLY
558
{
36
.tlb_fill = nios2_cpu_tlb_fill,
559
- MemOp mop = get_memop(oi);
37
diff --git a/target/nios2/translate.c b/target/nios2/translate.c
560
- Int128 ret;
561
-
562
- tcg_debug_assert((mop & MO_BSWAP) == MO_BE);
563
- ret = do_ld16_he_mmu(env, addr, mop, ra);
564
+ Int128 ret = do_ld16_mmu(env, addr, get_memop(oi), ra);
565
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
566
- if (!HOST_BIG_ENDIAN) {
567
- ret = bswap128(ret);
568
- }
569
- return ret;
570
-}
571
-
572
-Int128 cpu_ld16_le_mmu(CPUArchState *env, abi_ptr addr,
573
- MemOpIdx oi, uintptr_t ra)
574
-{
575
- MemOp mop = get_memop(oi);
576
- Int128 ret;
577
-
578
- tcg_debug_assert((mop & MO_BSWAP) == MO_LE);
579
- ret = do_ld16_he_mmu(env, addr, mop, ra);
580
- qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
581
- if (HOST_BIG_ENDIAN) {
582
- ret = bswap128(ret);
583
- }
584
return ret;
585
}
586
587
@@ -XXX,XX +XXX,XX @@ void cpu_stb_mmu(CPUArchState *env, abi_ptr addr, uint8_t val,
588
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
589
}
590
591
-static void do_st2_he_mmu(CPUArchState *env, abi_ptr addr, uint16_t val,
592
- MemOp mop, uintptr_t ra)
593
+static void do_st2_mmu(CPUArchState *env, abi_ptr addr, uint16_t val,
594
+ MemOp mop, uintptr_t ra)
595
{
596
void *haddr;
597
598
tcg_debug_assert((mop & MO_SIZE) == MO_16);
599
haddr = cpu_mmu_lookup(env, addr, mop, ra, MMU_DATA_STORE);
600
+
601
+ if (mop & MO_BSWAP) {
602
+ val = bswap16(val);
603
+ }
604
store_atom_2(env, ra, haddr, mop, val);
605
clear_helper_retaddr();
606
}
607
@@ -XXX,XX +XXX,XX @@ static void do_st2_he_mmu(CPUArchState *env, abi_ptr addr, uint16_t val,
608
void helper_stw_mmu(CPUArchState *env, uint64_t addr, uint32_t val,
609
MemOpIdx oi, uintptr_t ra)
610
{
611
- MemOp mop = get_memop(oi);
612
-
613
- if (mop & MO_BSWAP) {
614
- val = bswap16(val);
615
- }
616
- do_st2_he_mmu(env, addr, val, mop, ra);
617
+ do_st2_mmu(env, addr, val, get_memop(oi), ra);
618
}
619
620
-void cpu_stw_be_mmu(CPUArchState *env, abi_ptr addr, uint16_t val,
621
+void cpu_stw_mmu(CPUArchState *env, abi_ptr addr, uint16_t val,
622
MemOpIdx oi, uintptr_t ra)
623
{
624
- MemOp mop = get_memop(oi);
625
-
626
- tcg_debug_assert((mop & MO_BSWAP) == MO_BE);
627
- do_st2_he_mmu(env, addr, be16_to_cpu(val), mop, ra);
628
+ do_st2_mmu(env, addr, val, get_memop(oi), ra);
629
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
630
}
631
632
-void cpu_stw_le_mmu(CPUArchState *env, abi_ptr addr, uint16_t val,
633
- MemOpIdx oi, uintptr_t ra)
634
-{
635
- MemOp mop = get_memop(oi);
636
-
637
- tcg_debug_assert((mop & MO_BSWAP) == MO_LE);
638
- do_st2_he_mmu(env, addr, le16_to_cpu(val), mop, ra);
639
- qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
640
-}
641
-
642
-static void do_st4_he_mmu(CPUArchState *env, abi_ptr addr, uint32_t val,
643
- MemOp mop, uintptr_t ra)
644
+static void do_st4_mmu(CPUArchState *env, abi_ptr addr, uint32_t val,
645
+ MemOp mop, uintptr_t ra)
646
{
647
void *haddr;
648
649
tcg_debug_assert((mop & MO_SIZE) == MO_32);
650
haddr = cpu_mmu_lookup(env, addr, mop, ra, MMU_DATA_STORE);
651
+
652
+ if (mop & MO_BSWAP) {
653
+ val = bswap32(val);
654
+ }
655
store_atom_4(env, ra, haddr, mop, val);
656
clear_helper_retaddr();
657
}
658
@@ -XXX,XX +XXX,XX @@ static void do_st4_he_mmu(CPUArchState *env, abi_ptr addr, uint32_t val,
659
void helper_stl_mmu(CPUArchState *env, uint64_t addr, uint32_t val,
660
MemOpIdx oi, uintptr_t ra)
661
{
662
- MemOp mop = get_memop(oi);
663
-
664
- if (mop & MO_BSWAP) {
665
- val = bswap32(val);
666
- }
667
- do_st4_he_mmu(env, addr, val, mop, ra);
668
+ do_st4_mmu(env, addr, val, get_memop(oi), ra);
669
}
670
671
-void cpu_stl_be_mmu(CPUArchState *env, abi_ptr addr, uint32_t val,
672
- MemOpIdx oi, uintptr_t ra)
673
+void cpu_stl_mmu(CPUArchState *env, abi_ptr addr, uint32_t val,
674
+ MemOpIdx oi, uintptr_t ra)
675
{
676
- MemOp mop = get_memop(oi);
677
-
678
- tcg_debug_assert((mop & MO_BSWAP) == MO_BE);
679
- do_st4_he_mmu(env, addr, be32_to_cpu(val), mop, ra);
680
+ do_st4_mmu(env, addr, val, get_memop(oi), ra);
681
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
682
}
683
684
-void cpu_stl_le_mmu(CPUArchState *env, abi_ptr addr, uint32_t val,
685
- MemOpIdx oi, uintptr_t ra)
686
-{
687
- MemOp mop = get_memop(oi);
688
-
689
- tcg_debug_assert((mop & MO_BSWAP) == MO_LE);
690
- do_st4_he_mmu(env, addr, le32_to_cpu(val), mop, ra);
691
- qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
692
-}
693
-
694
-static void do_st8_he_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
695
- MemOp mop, uintptr_t ra)
696
+static void do_st8_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
697
+ MemOp mop, uintptr_t ra)
698
{
699
void *haddr;
700
701
tcg_debug_assert((mop & MO_SIZE) == MO_64);
702
haddr = cpu_mmu_lookup(env, addr, mop, ra, MMU_DATA_STORE);
703
+
704
+ if (mop & MO_BSWAP) {
705
+ val = bswap64(val);
706
+ }
707
store_atom_8(env, ra, haddr, mop, val);
708
clear_helper_retaddr();
709
}
710
@@ -XXX,XX +XXX,XX @@ static void do_st8_he_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
711
void helper_stq_mmu(CPUArchState *env, uint64_t addr, uint64_t val,
712
MemOpIdx oi, uintptr_t ra)
713
{
714
- MemOp mop = get_memop(oi);
715
-
716
- if (mop & MO_BSWAP) {
717
- val = bswap64(val);
718
- }
719
- do_st8_he_mmu(env, addr, val, mop, ra);
720
+ do_st8_mmu(env, addr, val, get_memop(oi), ra);
721
}
722
723
-void cpu_stq_be_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
724
+void cpu_stq_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
725
MemOpIdx oi, uintptr_t ra)
726
{
727
- MemOp mop = get_memop(oi);
728
-
729
- tcg_debug_assert((mop & MO_BSWAP) == MO_BE);
730
- do_st8_he_mmu(env, addr, cpu_to_be64(val), mop, ra);
731
+ do_st8_mmu(env, addr, val, get_memop(oi), ra);
732
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
733
}
734
735
-void cpu_stq_le_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
736
- MemOpIdx oi, uintptr_t ra)
737
-{
738
- MemOp mop = get_memop(oi);
739
-
740
- tcg_debug_assert((mop & MO_BSWAP) == MO_LE);
741
- do_st8_he_mmu(env, addr, cpu_to_le64(val), mop, ra);
742
- qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
743
-}
744
-
745
-static void do_st16_he_mmu(CPUArchState *env, abi_ptr addr, Int128 val,
746
- MemOp mop, uintptr_t ra)
747
+static void do_st16_mmu(CPUArchState *env, abi_ptr addr, Int128 val,
748
+ MemOp mop, uintptr_t ra)
749
{
750
void *haddr;
751
752
tcg_debug_assert((mop & MO_SIZE) == MO_128);
753
haddr = cpu_mmu_lookup(env, addr, mop, ra, MMU_DATA_STORE);
754
+
755
+ if (mop & MO_BSWAP) {
756
+ val = bswap128(val);
757
+ }
758
store_atom_16(env, ra, haddr, mop, val);
759
clear_helper_retaddr();
760
}
761
@@ -XXX,XX +XXX,XX @@ static void do_st16_he_mmu(CPUArchState *env, abi_ptr addr, Int128 val,
762
void helper_st16_mmu(CPUArchState *env, uint64_t addr, Int128 val,
763
MemOpIdx oi, uintptr_t ra)
764
{
765
- MemOp mop = get_memop(oi);
766
-
767
- if (mop & MO_BSWAP) {
768
- val = bswap128(val);
769
- }
770
- do_st16_he_mmu(env, addr, val, mop, ra);
771
+ do_st16_mmu(env, addr, val, get_memop(oi), ra);
772
}
773
774
void helper_st_i128(CPUArchState *env, uint64_t addr, Int128 val, MemOpIdx oi)
775
@@ -XXX,XX +XXX,XX @@ void helper_st_i128(CPUArchState *env, uint64_t addr, Int128 val, MemOpIdx oi)
776
helper_st16_mmu(env, addr, val, oi, GETPC());
777
}
778
779
-void cpu_st16_be_mmu(CPUArchState *env, abi_ptr addr,
780
- Int128 val, MemOpIdx oi, uintptr_t ra)
781
+void cpu_st16_mmu(CPUArchState *env, abi_ptr addr,
782
+ Int128 val, MemOpIdx oi, uintptr_t ra)
783
{
784
- MemOp mop = get_memop(oi);
785
-
786
- tcg_debug_assert((mop & MO_BSWAP) == MO_BE);
787
- if (!HOST_BIG_ENDIAN) {
788
- val = bswap128(val);
789
- }
790
- do_st16_he_mmu(env, addr, val, mop, ra);
791
- qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
792
-}
793
-
794
-void cpu_st16_le_mmu(CPUArchState *env, abi_ptr addr,
795
- Int128 val, MemOpIdx oi, uintptr_t ra)
796
-{
797
- MemOp mop = get_memop(oi);
798
-
799
- tcg_debug_assert((mop & MO_BSWAP) == MO_LE);
800
- if (HOST_BIG_ENDIAN) {
801
- val = bswap128(val);
802
- }
803
- do_st16_he_mmu(env, addr, val, mop, ra);
804
+ do_st16_mmu(env, addr, val, get_memop(oi), ra);
805
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
806
}
807
808
diff --git a/target/arm/tcg/m_helper.c b/target/arm/tcg/m_helper.c
38
index XXXXXXX..XXXXXXX 100644
809
index XXXXXXX..XXXXXXX 100644
39
--- a/target/nios2/translate.c
810
--- a/target/arm/tcg/m_helper.c
40
+++ b/target/nios2/translate.c
811
+++ b/target/arm/tcg/m_helper.c
41
@@ -XXX,XX +XXX,XX @@ void nios2_tcg_init(void)
812
@@ -XXX,XX +XXX,XX @@ static bool do_v7m_function_return(ARMCPU *cpu)
42
cpu_pc = tcg_global_mem_new(cpu_env,
813
*/
43
offsetof(CPUNios2State, pc), "pc");
814
mmu_idx = arm_v7m_mmu_idx_for_secstate(env, true);
44
}
815
oi = make_memop_idx(MO_LEUL, arm_to_core_mmu_idx(mmu_idx));
45
-
816
- newpc = cpu_ldl_le_mmu(env, frameptr, oi, 0);
46
-void restore_state_to_opc(CPUNios2State *env, TranslationBlock *tb,
817
- newpsr = cpu_ldl_le_mmu(env, frameptr + 4, oi, 0);
47
- target_ulong *data)
818
+ newpc = cpu_ldl_mmu(env, frameptr, oi, 0);
48
-{
819
+ newpsr = cpu_ldl_mmu(env, frameptr + 4, oi, 0);
49
- env->pc = data[0];
820
50
-}
821
/* Consistency checks on new IPSR */
822
newpsr_exc = newpsr & XPSR_EXCP;
823
diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c
824
index XXXXXXX..XXXXXXX 100644
825
--- a/target/sparc/ldst_helper.c
826
+++ b/target/sparc/ldst_helper.c
827
@@ -XXX,XX +XXX,XX @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr,
828
ret = cpu_ldb_mmu(env, addr, oi, GETPC());
829
break;
830
case 2:
831
- if (asi & 8) {
832
- ret = cpu_ldw_le_mmu(env, addr, oi, GETPC());
833
- } else {
834
- ret = cpu_ldw_be_mmu(env, addr, oi, GETPC());
835
- }
836
+ ret = cpu_ldw_mmu(env, addr, oi, GETPC());
837
break;
838
case 4:
839
- if (asi & 8) {
840
- ret = cpu_ldl_le_mmu(env, addr, oi, GETPC());
841
- } else {
842
- ret = cpu_ldl_be_mmu(env, addr, oi, GETPC());
843
- }
844
+ ret = cpu_ldl_mmu(env, addr, oi, GETPC());
845
break;
846
case 8:
847
- if (asi & 8) {
848
- ret = cpu_ldq_le_mmu(env, addr, oi, GETPC());
849
- } else {
850
- ret = cpu_ldq_be_mmu(env, addr, oi, GETPC());
851
- }
852
+ ret = cpu_ldq_mmu(env, addr, oi, GETPC());
853
break;
854
default:
855
g_assert_not_reached();
856
diff --git a/accel/tcg/ldst_common.c.inc b/accel/tcg/ldst_common.c.inc
857
index XXXXXXX..XXXXXXX 100644
858
--- a/accel/tcg/ldst_common.c.inc
859
+++ b/accel/tcg/ldst_common.c.inc
860
@@ -XXX,XX +XXX,XX @@ uint32_t cpu_lduw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
861
int mmu_idx, uintptr_t ra)
862
{
863
MemOpIdx oi = make_memop_idx(MO_BEUW | MO_UNALN, mmu_idx);
864
- return cpu_ldw_be_mmu(env, addr, oi, ra);
865
+ return cpu_ldw_mmu(env, addr, oi, ra);
866
}
867
868
int cpu_ldsw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
869
@@ -XXX,XX +XXX,XX @@ uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
870
int mmu_idx, uintptr_t ra)
871
{
872
MemOpIdx oi = make_memop_idx(MO_BEUL | MO_UNALN, mmu_idx);
873
- return cpu_ldl_be_mmu(env, addr, oi, ra);
874
+ return cpu_ldl_mmu(env, addr, oi, ra);
875
}
876
877
uint64_t cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
878
int mmu_idx, uintptr_t ra)
879
{
880
MemOpIdx oi = make_memop_idx(MO_BEUQ | MO_UNALN, mmu_idx);
881
- return cpu_ldq_be_mmu(env, addr, oi, ra);
882
+ return cpu_ldq_mmu(env, addr, oi, ra);
883
}
884
885
uint32_t cpu_lduw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
886
int mmu_idx, uintptr_t ra)
887
{
888
MemOpIdx oi = make_memop_idx(MO_LEUW | MO_UNALN, mmu_idx);
889
- return cpu_ldw_le_mmu(env, addr, oi, ra);
890
+ return cpu_ldw_mmu(env, addr, oi, ra);
891
}
892
893
int cpu_ldsw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
894
@@ -XXX,XX +XXX,XX @@ uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
895
int mmu_idx, uintptr_t ra)
896
{
897
MemOpIdx oi = make_memop_idx(MO_LEUL | MO_UNALN, mmu_idx);
898
- return cpu_ldl_le_mmu(env, addr, oi, ra);
899
+ return cpu_ldl_mmu(env, addr, oi, ra);
900
}
901
902
uint64_t cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
903
int mmu_idx, uintptr_t ra)
904
{
905
MemOpIdx oi = make_memop_idx(MO_LEUQ | MO_UNALN, mmu_idx);
906
- return cpu_ldq_le_mmu(env, addr, oi, ra);
907
+ return cpu_ldq_mmu(env, addr, oi, ra);
908
}
909
910
void cpu_stb_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
911
@@ -XXX,XX +XXX,XX @@ void cpu_stw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
912
int mmu_idx, uintptr_t ra)
913
{
914
MemOpIdx oi = make_memop_idx(MO_BEUW | MO_UNALN, mmu_idx);
915
- cpu_stw_be_mmu(env, addr, val, oi, ra);
916
+ cpu_stw_mmu(env, addr, val, oi, ra);
917
}
918
919
void cpu_stl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
920
int mmu_idx, uintptr_t ra)
921
{
922
MemOpIdx oi = make_memop_idx(MO_BEUL | MO_UNALN, mmu_idx);
923
- cpu_stl_be_mmu(env, addr, val, oi, ra);
924
+ cpu_stl_mmu(env, addr, val, oi, ra);
925
}
926
927
void cpu_stq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
928
int mmu_idx, uintptr_t ra)
929
{
930
MemOpIdx oi = make_memop_idx(MO_BEUQ | MO_UNALN, mmu_idx);
931
- cpu_stq_be_mmu(env, addr, val, oi, ra);
932
+ cpu_stq_mmu(env, addr, val, oi, ra);
933
}
934
935
void cpu_stw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
936
int mmu_idx, uintptr_t ra)
937
{
938
MemOpIdx oi = make_memop_idx(MO_LEUW | MO_UNALN, mmu_idx);
939
- cpu_stw_le_mmu(env, addr, val, oi, ra);
940
+ cpu_stw_mmu(env, addr, val, oi, ra);
941
}
942
943
void cpu_stl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
944
int mmu_idx, uintptr_t ra)
945
{
946
MemOpIdx oi = make_memop_idx(MO_LEUL | MO_UNALN, mmu_idx);
947
- cpu_stl_le_mmu(env, addr, val, oi, ra);
948
+ cpu_stl_mmu(env, addr, val, oi, ra);
949
}
950
951
void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
952
int mmu_idx, uintptr_t ra)
953
{
954
MemOpIdx oi = make_memop_idx(MO_LEUQ | MO_UNALN, mmu_idx);
955
- cpu_stq_le_mmu(env, addr, val, oi, ra);
956
+ cpu_stq_mmu(env, addr, val, oi, ra);
957
}
958
959
/*--------------------------*/
51
--
960
--
52
2.34.1
961
2.34.1
53
962
54
963
diff view generated by jsdifflib
1
When PAGE_RESET is set, we are replacing pages with new
1
Use cpu_ld16_mmu and cpu_st16_mmu to eliminate the special case,
2
content, which means that we need to invalidate existing
2
and change all of the *_data_ra functions to match.
3
cached data, such as TranslationBlocks. Perform the
4
reset invalidate while we're doing other invalidates,
5
which allows us to remove the separate invalidates from
6
the user-only mmap/munmap/mprotect routines.
7
3
8
In addition, restrict invalidation to PAGE_EXEC pages.
4
Note that we check the alignment of both compare and store
9
Since cdf713085131, we have validated PAGE_EXEC is present
5
pointers at the top of the function, so MO_ALIGN* may be
10
before translation, which means we can assume that if the
6
safely removed from the individual memory operations.
11
bit is not present, there are no translations to invalidate.
12
7
13
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Reviewed-by: David Hildenbrand <david@redhat.com>
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
---
11
---
16
accel/tcg/translate-all.c | 19 +++++++++++--------
12
target/s390x/tcg/mem_helper.c | 66 ++++++++++++++---------------------
17
bsd-user/mmap.c | 2 --
13
1 file changed, 27 insertions(+), 39 deletions(-)
18
linux-user/mmap.c | 4 ----
19
3 files changed, 11 insertions(+), 14 deletions(-)
20
14
21
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
15
diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c
22
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
23
--- a/accel/tcg/translate-all.c
17
--- a/target/s390x/tcg/mem_helper.c
24
+++ b/accel/tcg/translate-all.c
18
+++ b/target/s390x/tcg/mem_helper.c
25
@@ -XXX,XX +XXX,XX @@ int page_get_flags(target_ulong address)
19
@@ -XXX,XX +XXX,XX @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
26
void page_set_flags(target_ulong start, target_ulong end, int flags)
20
uint64_t a2, bool parallel)
27
{
21
{
28
target_ulong addr, len;
22
uint32_t mem_idx = cpu_mmu_index(env, false);
29
- bool reset_target_data;
23
+ MemOpIdx oi16 = make_memop_idx(MO_TE | MO_128, mem_idx);
30
+ bool reset;
24
+ MemOpIdx oi8 = make_memop_idx(MO_TE | MO_64, mem_idx);
31
25
+ MemOpIdx oi4 = make_memop_idx(MO_TE | MO_32, mem_idx);
32
/* This function should never be called with addresses outside the
26
+ MemOpIdx oi2 = make_memop_idx(MO_TE | MO_16, mem_idx);
33
guest address space. If this assert fires, it probably indicates
27
+ MemOpIdx oi1 = make_memop_idx(MO_8, mem_idx);
34
@@ -XXX,XX +XXX,XX @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
28
uintptr_t ra = GETPC();
35
if (flags & PAGE_WRITE) {
29
uint32_t fc = extract32(env->regs[0], 0, 8);
36
flags |= PAGE_WRITE_ORG;
30
uint32_t sc = extract32(env->regs[0], 8, 8);
37
}
31
@@ -XXX,XX +XXX,XX @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
38
- reset_target_data = !(flags & PAGE_VALID) || (flags & PAGE_RESET);
39
+ reset = !(flags & PAGE_VALID) || (flags & PAGE_RESET);
40
flags &= ~PAGE_RESET;
41
42
for (addr = start, len = end - start;
43
@@ -XXX,XX +XXX,XX @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
44
len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
45
PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS, true);
46
47
- /* If the write protection bit is set, then we invalidate
48
- the code inside. */
49
- if (!(p->flags & PAGE_WRITE) &&
50
- (flags & PAGE_WRITE) &&
51
- p->first_tb) {
52
+ /*
53
+ * If the page was executable, but is reset, or is no longer
54
+ * executable, or has become writable, then invalidate any code.
55
+ */
56
+ if ((p->flags & PAGE_EXEC)
57
+ && (reset ||
58
+ !(flags & PAGE_EXEC) ||
59
+ (flags & ~p->flags & PAGE_WRITE))) {
60
tb_invalidate_phys_page(addr);
61
}
62
- if (reset_target_data) {
63
+ if (reset) {
64
g_free(p->target_data);
65
p->target_data = NULL;
66
p->flags = flags;
67
diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/bsd-user/mmap.c
70
+++ b/bsd-user/mmap.c
71
@@ -XXX,XX +XXX,XX @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
72
page_dump(stdout);
73
printf("\n");
74
#endif
75
- tb_invalidate_phys_range(start, start + len);
76
mmap_unlock();
77
return start;
78
fail:
79
@@ -XXX,XX +XXX,XX @@ int target_munmap(abi_ulong start, abi_ulong len)
80
81
if (ret == 0) {
82
page_set_flags(start, start + len, 0);
83
- tb_invalidate_phys_range(start, start + len);
84
}
85
mmap_unlock();
86
return ret;
87
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/linux-user/mmap.c
90
+++ b/linux-user/mmap.c
91
@@ -XXX,XX +XXX,XX @@ int target_mprotect(abi_ulong start, abi_ulong len, int target_prot)
92
}
93
94
page_set_flags(start, start + len, page_flags);
95
- tb_invalidate_phys_range(start, start + len);
96
ret = 0;
97
98
error:
99
@@ -XXX,XX +XXX,XX @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
100
qemu_log_unlock(f);
101
}
32
}
102
}
33
}
103
- tb_invalidate_phys_range(start, start + len);
34
104
mmap_unlock();
35
- /* All loads happen before all stores. For simplicity, load the entire
105
return start;
36
- store value area from the parameter list. */
106
fail:
37
- svh = cpu_ldq_data_ra(env, pl + 16, ra);
107
@@ -XXX,XX +XXX,XX @@ int target_munmap(abi_ulong start, abi_ulong len)
38
- svl = cpu_ldq_data_ra(env, pl + 24, ra);
108
39
+ /*
109
if (ret == 0) {
40
+ * All loads happen before all stores. For simplicity, load the entire
110
page_set_flags(start, start + len, 0);
41
+ * store value area from the parameter list.
111
- tb_invalidate_phys_range(start, start + len);
42
+ */
112
}
43
+ svh = cpu_ldq_mmu(env, pl + 16, oi8, ra);
113
mmap_unlock();
44
+ svl = cpu_ldq_mmu(env, pl + 24, oi8, ra);
114
return ret;
45
115
@@ -XXX,XX +XXX,XX @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
46
switch (fc) {
116
page_set_flags(new_addr, new_addr + new_size,
47
case 0:
117
prot | PAGE_VALID | PAGE_RESET);
48
{
118
}
49
- uint32_t nv = cpu_ldl_data_ra(env, pl, ra);
119
- tb_invalidate_phys_range(new_addr, new_addr + new_size);
50
+ uint32_t nv = cpu_ldl_mmu(env, pl, oi4, ra);
120
mmap_unlock();
51
uint32_t cv = env->regs[r3];
121
return new_addr;
52
uint32_t ov;
122
}
53
54
@@ -XXX,XX +XXX,XX @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
55
ov = cpu_atomic_cmpxchgl_be_mmu(env, a1, cv, nv, oi, ra);
56
#endif
57
} else {
58
- ov = cpu_ldl_data_ra(env, a1, ra);
59
- cpu_stl_data_ra(env, a1, (ov == cv ? nv : ov), ra);
60
+ ov = cpu_ldl_mmu(env, a1, oi4, ra);
61
+ cpu_stl_mmu(env, a1, (ov == cv ? nv : ov), oi4, ra);
62
}
63
cc = (ov != cv);
64
env->regs[r3] = deposit64(env->regs[r3], 32, 32, ov);
65
@@ -XXX,XX +XXX,XX @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
66
67
case 1:
68
{
69
- uint64_t nv = cpu_ldq_data_ra(env, pl, ra);
70
+ uint64_t nv = cpu_ldq_mmu(env, pl, oi8, ra);
71
uint64_t cv = env->regs[r3];
72
uint64_t ov;
73
74
if (parallel) {
75
#ifdef CONFIG_ATOMIC64
76
- MemOpIdx oi = make_memop_idx(MO_TEUQ | MO_ALIGN, mem_idx);
77
- ov = cpu_atomic_cmpxchgq_be_mmu(env, a1, cv, nv, oi, ra);
78
+ ov = cpu_atomic_cmpxchgq_be_mmu(env, a1, cv, nv, oi8, ra);
79
#else
80
/* Note that we asserted !parallel above. */
81
g_assert_not_reached();
82
#endif
83
} else {
84
- ov = cpu_ldq_data_ra(env, a1, ra);
85
- cpu_stq_data_ra(env, a1, (ov == cv ? nv : ov), ra);
86
+ ov = cpu_ldq_mmu(env, a1, oi8, ra);
87
+ cpu_stq_mmu(env, a1, (ov == cv ? nv : ov), oi8, ra);
88
}
89
cc = (ov != cv);
90
env->regs[r3] = ov;
91
@@ -XXX,XX +XXX,XX @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
92
93
case 2:
94
{
95
- uint64_t nvh = cpu_ldq_data_ra(env, pl, ra);
96
- uint64_t nvl = cpu_ldq_data_ra(env, pl + 8, ra);
97
- Int128 nv = int128_make128(nvl, nvh);
98
+ Int128 nv = cpu_ld16_mmu(env, pl, oi16, ra);
99
Int128 cv = int128_make128(env->regs[r3 + 1], env->regs[r3]);
100
Int128 ov;
101
102
if (!parallel) {
103
- uint64_t oh = cpu_ldq_data_ra(env, a1 + 0, ra);
104
- uint64_t ol = cpu_ldq_data_ra(env, a1 + 8, ra);
105
-
106
- ov = int128_make128(ol, oh);
107
+ ov = cpu_ld16_mmu(env, a1, oi16, ra);
108
cc = !int128_eq(ov, cv);
109
if (cc) {
110
nv = ov;
111
}
112
-
113
- cpu_stq_data_ra(env, a1 + 0, int128_gethi(nv), ra);
114
- cpu_stq_data_ra(env, a1 + 8, int128_getlo(nv), ra);
115
+ cpu_st16_mmu(env, a1, nv, oi16, ra);
116
} else if (HAVE_CMPXCHG128) {
117
- MemOpIdx oi = make_memop_idx(MO_TE | MO_128 | MO_ALIGN, mem_idx);
118
- ov = cpu_atomic_cmpxchgo_be_mmu(env, a1, cv, nv, oi, ra);
119
+ ov = cpu_atomic_cmpxchgo_be_mmu(env, a1, cv, nv, oi16, ra);
120
cc = !int128_eq(ov, cv);
121
} else {
122
/* Note that we asserted !parallel above. */
123
@@ -XXX,XX +XXX,XX @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
124
if (cc == 0) {
125
switch (sc) {
126
case 0:
127
- cpu_stb_data_ra(env, a2, svh >> 56, ra);
128
+ cpu_stb_mmu(env, a2, svh >> 56, oi1, ra);
129
break;
130
case 1:
131
- cpu_stw_data_ra(env, a2, svh >> 48, ra);
132
+ cpu_stw_mmu(env, a2, svh >> 48, oi2, ra);
133
break;
134
case 2:
135
- cpu_stl_data_ra(env, a2, svh >> 32, ra);
136
+ cpu_stl_mmu(env, a2, svh >> 32, oi4, ra);
137
break;
138
case 3:
139
- cpu_stq_data_ra(env, a2, svh, ra);
140
+ cpu_stq_mmu(env, a2, svh, oi8, ra);
141
break;
142
case 4:
143
- if (!parallel) {
144
- cpu_stq_data_ra(env, a2 + 0, svh, ra);
145
- cpu_stq_data_ra(env, a2 + 8, svl, ra);
146
- } else if (HAVE_ATOMIC128) {
147
- MemOpIdx oi = make_memop_idx(MO_TEUQ | MO_ALIGN_16, mem_idx);
148
- Int128 sv = int128_make128(svl, svh);
149
- cpu_atomic_sto_be_mmu(env, a2, sv, oi, ra);
150
- } else {
151
- /* Note that we asserted !parallel above. */
152
- g_assert_not_reached();
153
- }
154
+ cpu_st16_mmu(env, a2, int128_make128(svl, svh), oi16, ra);
155
break;
156
default:
157
g_assert_not_reached();
123
--
158
--
124
2.34.1
159
2.34.1
125
160
126
161
diff view generated by jsdifflib
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
1
Eliminate the CONFIG_USER_ONLY specialization.
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: David Hildenbrand <david@redhat.com>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
6
---
4
target/riscv/cpu.c | 9 +++++++--
7
target/s390x/tcg/mem_helper.c | 8 +-------
5
1 file changed, 7 insertions(+), 2 deletions(-)
8
1 file changed, 1 insertion(+), 7 deletions(-)
6
9
7
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
10
diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c
8
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
9
--- a/target/riscv/cpu.c
12
--- a/target/s390x/tcg/mem_helper.c
10
+++ b/target/riscv/cpu.c
13
+++ b/target/s390x/tcg/mem_helper.c
11
@@ -XXX,XX +XXX,XX @@ static bool riscv_cpu_has_work(CPUState *cs)
14
@@ -XXX,XX +XXX,XX @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
12
#endif
15
uint32_t ov;
13
}
16
14
17
if (parallel) {
15
-void restore_state_to_opc(CPURISCVState *env, TranslationBlock *tb,
18
-#ifdef CONFIG_USER_ONLY
16
- target_ulong *data)
19
- uint32_t *haddr = g2h(env_cpu(env), a1);
17
+static void riscv_restore_state_to_opc(CPUState *cs,
20
- ov = qatomic_cmpxchg__nocheck(haddr, cv, nv);
18
+ const TranslationBlock *tb,
21
-#else
19
+ const uint64_t *data)
22
- MemOpIdx oi = make_memop_idx(MO_TEUL | MO_ALIGN, mem_idx);
20
{
23
- ov = cpu_atomic_cmpxchgl_be_mmu(env, a1, cv, nv, oi, ra);
21
+ RISCVCPU *cpu = RISCV_CPU(cs);
24
-#endif
22
+ CPURISCVState *env = &cpu->env;
25
+ ov = cpu_atomic_cmpxchgl_be_mmu(env, a1, cv, nv, oi4, ra);
23
RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
26
} else {
24
+
27
ov = cpu_ldl_mmu(env, a1, oi4, ra);
25
if (xl == MXL_RV32) {
28
cpu_stl_mmu(env, a1, (ov == cv ? nv : ov), oi4, ra);
26
env->pc = (int32_t)data[0];
27
} else {
28
@@ -XXX,XX +XXX,XX @@ static const struct SysemuCPUOps riscv_sysemu_ops = {
29
static const struct TCGCPUOps riscv_tcg_ops = {
30
.initialize = riscv_translate_init,
31
.synchronize_from_tb = riscv_cpu_synchronize_from_tb,
32
+ .restore_state_to_opc = riscv_restore_state_to_opc,
33
34
#ifndef CONFIG_USER_ONLY
35
.tlb_fill = riscv_cpu_tlb_fill,
36
--
29
--
37
2.34.1
30
2.34.1
38
31
39
32
diff view generated by jsdifflib
1
There are no users outside of accel/tcg; this function
1
Atomic load/store of 128-byte quantities is now handled
2
does not need to be defined in exec-all.h.
2
by cpu_{ld,st}16_mmu.
3
3
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
6
---
7
accel/tcg/internal.h | 5 +++++
7
accel/tcg/atomic_template.h | 61 +++--------------------------------
8
include/exec/exec-all.h | 8 --------
8
include/exec/cpu_ldst.h | 9 ------
9
2 files changed, 5 insertions(+), 8 deletions(-)
9
accel/tcg/atomic_common.c.inc | 14 --------
10
3 files changed, 4 insertions(+), 80 deletions(-)
10
11
11
diff --git a/accel/tcg/internal.h b/accel/tcg/internal.h
12
diff --git a/accel/tcg/atomic_template.h b/accel/tcg/atomic_template.h
12
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
13
--- a/accel/tcg/internal.h
14
--- a/accel/tcg/atomic_template.h
14
+++ b/accel/tcg/internal.h
15
+++ b/accel/tcg/atomic_template.h
15
@@ -XXX,XX +XXX,XX @@ void do_assert_page_locked(const PageDesc *pd, const char *file, int line);
16
@@ -XXX,XX +XXX,XX @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
16
void page_lock(PageDesc *pd);
17
return ret;
17
void page_unlock(PageDesc *pd);
18
}
18
#endif
19
19
+#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_DEBUG_TCG)
20
-#if DATA_SIZE >= 16
20
+void assert_no_pages_locked(void);
21
-#if HAVE_ATOMIC128
21
+#else
22
-ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr,
22
+static inline void assert_no_pages_locked(void) { }
23
- MemOpIdx oi, uintptr_t retaddr)
23
+#endif
24
-{
24
25
- DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
25
TranslationBlock *tb_gen_code(CPUState *cpu, target_ulong pc,
26
- PAGE_READ, retaddr);
26
target_ulong cs_base, uint32_t flags,
27
- DATA_TYPE val;
27
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
28
-
29
- val = atomic16_read(haddr);
30
- ATOMIC_MMU_CLEANUP;
31
- atomic_trace_ld_post(env, addr, oi);
32
- return val;
33
-}
34
-
35
-void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
36
- MemOpIdx oi, uintptr_t retaddr)
37
-{
38
- DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
39
- PAGE_WRITE, retaddr);
40
-
41
- atomic16_set(haddr, val);
42
- ATOMIC_MMU_CLEANUP;
43
- atomic_trace_st_post(env, addr, oi);
44
-}
45
-#endif
46
-#else
47
+#if DATA_SIZE < 16
48
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
49
MemOpIdx oi, uintptr_t retaddr)
50
{
51
@@ -XXX,XX +XXX,XX @@ GEN_ATOMIC_HELPER_FN(smax_fetch, MAX, SDATA_TYPE, new)
52
GEN_ATOMIC_HELPER_FN(umax_fetch, MAX, DATA_TYPE, new)
53
54
#undef GEN_ATOMIC_HELPER_FN
55
-#endif /* DATA SIZE >= 16 */
56
+#endif /* DATA SIZE < 16 */
57
58
#undef END
59
60
@@ -XXX,XX +XXX,XX @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
61
return BSWAP(ret);
62
}
63
64
-#if DATA_SIZE >= 16
65
-#if HAVE_ATOMIC128
66
-ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr,
67
- MemOpIdx oi, uintptr_t retaddr)
68
-{
69
- DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
70
- PAGE_READ, retaddr);
71
- DATA_TYPE val;
72
-
73
- val = atomic16_read(haddr);
74
- ATOMIC_MMU_CLEANUP;
75
- atomic_trace_ld_post(env, addr, oi);
76
- return BSWAP(val);
77
-}
78
-
79
-void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
80
- MemOpIdx oi, uintptr_t retaddr)
81
-{
82
- DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
83
- PAGE_WRITE, retaddr);
84
-
85
- val = BSWAP(val);
86
- atomic16_set(haddr, val);
87
- ATOMIC_MMU_CLEANUP;
88
- atomic_trace_st_post(env, addr, oi);
89
-}
90
-#endif
91
-#else
92
+#if DATA_SIZE < 16
93
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
94
MemOpIdx oi, uintptr_t retaddr)
95
{
96
@@ -XXX,XX +XXX,XX @@ GEN_ATOMIC_HELPER_FN(add_fetch, ADD, DATA_TYPE, new)
97
#undef ADD
98
99
#undef GEN_ATOMIC_HELPER_FN
100
-#endif /* DATA_SIZE >= 16 */
101
+#endif /* DATA_SIZE < 16 */
102
103
#undef END
104
#endif /* DATA_SIZE > 1 */
105
diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
28
index XXXXXXX..XXXXXXX 100644
106
index XXXXXXX..XXXXXXX 100644
29
--- a/include/exec/exec-all.h
107
--- a/include/exec/cpu_ldst.h
30
+++ b/include/exec/exec-all.h
108
+++ b/include/exec/cpu_ldst.h
31
@@ -XXX,XX +XXX,XX @@ extern __thread uintptr_t tci_tb_ptr;
109
@@ -XXX,XX +XXX,XX @@ Int128 cpu_atomic_cmpxchgo_be_mmu(CPUArchState *env, target_ulong addr,
32
smaller than 4 bytes, so we don't worry about special-casing this. */
110
Int128 cmpv, Int128 newv,
33
#define GETPC_ADJ 2
111
MemOpIdx oi, uintptr_t retaddr);
34
112
35
-#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_DEBUG_TCG)
113
-Int128 cpu_atomic_ldo_le_mmu(CPUArchState *env, target_ulong addr,
36
-void assert_no_pages_locked(void);
114
- MemOpIdx oi, uintptr_t retaddr);
37
-#else
115
-Int128 cpu_atomic_ldo_be_mmu(CPUArchState *env, target_ulong addr,
38
-static inline void assert_no_pages_locked(void)
116
- MemOpIdx oi, uintptr_t retaddr);
117
-void cpu_atomic_sto_le_mmu(CPUArchState *env, target_ulong addr, Int128 val,
118
- MemOpIdx oi, uintptr_t retaddr);
119
-void cpu_atomic_sto_be_mmu(CPUArchState *env, target_ulong addr, Int128 val,
120
- MemOpIdx oi, uintptr_t retaddr);
121
-
122
#if defined(CONFIG_USER_ONLY)
123
124
extern __thread uintptr_t helper_retaddr;
125
diff --git a/accel/tcg/atomic_common.c.inc b/accel/tcg/atomic_common.c.inc
126
index XXXXXXX..XXXXXXX 100644
127
--- a/accel/tcg/atomic_common.c.inc
128
+++ b/accel/tcg/atomic_common.c.inc
129
@@ -XXX,XX +XXX,XX @@ static void atomic_trace_rmw_post(CPUArchState *env, uint64_t addr,
130
qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_RW);
131
}
132
133
-#if HAVE_ATOMIC128
134
-static void atomic_trace_ld_post(CPUArchState *env, uint64_t addr,
135
- MemOpIdx oi)
39
-{
136
-{
137
- qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
138
-}
139
-
140
-static void atomic_trace_st_post(CPUArchState *env, uint64_t addr,
141
- MemOpIdx oi)
142
-{
143
- qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
40
-}
144
-}
41
-#endif
145
-#endif
42
-
146
-
43
#if !defined(CONFIG_USER_ONLY)
147
/*
44
148
* Atomic helpers callable from TCG.
45
/**
149
* These have a common interface and all defer to cpu_atomic_*
46
--
150
--
47
2.34.1
151
2.34.1
48
152
49
153
diff view generated by jsdifflib
1
Since "target data" is always user-only, move it out of
1
Now that load/store are gone, we're always passing
2
translate-all.c to user-exec.c.
2
PAGE_READ | PAGE_WRITE for RMW atomic operations.
3
3
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
6
---
7
accel/tcg/translate-all.c | 50 ---------------------------------------
7
accel/tcg/atomic_template.h | 32 ++++++--------
8
accel/tcg/user-exec.c | 50 +++++++++++++++++++++++++++++++++++++++
8
accel/tcg/cputlb.c | 85 ++++++++++++++-----------------------
9
2 files changed, 50 insertions(+), 50 deletions(-)
9
accel/tcg/user-exec.c | 8 +---
10
10
3 files changed, 45 insertions(+), 80 deletions(-)
11
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
11
12
diff --git a/accel/tcg/atomic_template.h b/accel/tcg/atomic_template.h
12
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
13
--- a/accel/tcg/translate-all.c
14
--- a/accel/tcg/atomic_template.h
14
+++ b/accel/tcg/translate-all.c
15
+++ b/accel/tcg/atomic_template.h
15
@@ -XXX,XX +XXX,XX @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
16
@@ -XXX,XX +XXX,XX @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
16
}
17
ABI_TYPE cmpv, ABI_TYPE newv,
17
}
18
MemOpIdx oi, uintptr_t retaddr)
18
19
{
19
-void page_reset_target_data(target_ulong start, target_ulong end)
20
- DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
20
-{
21
- PAGE_READ | PAGE_WRITE, retaddr);
21
-#ifdef TARGET_PAGE_DATA_SIZE
22
+ DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, retaddr);
22
- target_ulong addr, len;
23
DATA_TYPE ret;
24
25
#if DATA_SIZE == 16
26
@@ -XXX,XX +XXX,XX @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
27
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
28
MemOpIdx oi, uintptr_t retaddr)
29
{
30
- DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
31
- PAGE_READ | PAGE_WRITE, retaddr);
32
+ DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, retaddr);
33
DATA_TYPE ret;
34
35
ret = qatomic_xchg__nocheck(haddr, val);
36
@@ -XXX,XX +XXX,XX @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
37
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
38
ABI_TYPE val, MemOpIdx oi, uintptr_t retaddr) \
39
{ \
40
- DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
41
- PAGE_READ | PAGE_WRITE, retaddr); \
42
- DATA_TYPE ret; \
43
+ DATA_TYPE *haddr, ret; \
44
+ haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, retaddr); \
45
ret = qatomic_##X(haddr, val); \
46
ATOMIC_MMU_CLEANUP; \
47
atomic_trace_rmw_post(env, addr, oi); \
48
@@ -XXX,XX +XXX,XX @@ GEN_ATOMIC_HELPER(xor_fetch)
49
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
50
ABI_TYPE xval, MemOpIdx oi, uintptr_t retaddr) \
51
{ \
52
- XDATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
53
- PAGE_READ | PAGE_WRITE, retaddr); \
54
- XDATA_TYPE cmp, old, new, val = xval; \
55
+ XDATA_TYPE *haddr, cmp, old, new, val = xval; \
56
+ haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, retaddr); \
57
smp_mb(); \
58
cmp = qatomic_read__nocheck(haddr); \
59
do { \
60
@@ -XXX,XX +XXX,XX @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
61
ABI_TYPE cmpv, ABI_TYPE newv,
62
MemOpIdx oi, uintptr_t retaddr)
63
{
64
- DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
65
- PAGE_READ | PAGE_WRITE, retaddr);
66
+ DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, retaddr);
67
DATA_TYPE ret;
68
69
#if DATA_SIZE == 16
70
@@ -XXX,XX +XXX,XX @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
71
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
72
MemOpIdx oi, uintptr_t retaddr)
73
{
74
- DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
75
- PAGE_READ | PAGE_WRITE, retaddr);
76
+ DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, retaddr);
77
ABI_TYPE ret;
78
79
ret = qatomic_xchg__nocheck(haddr, BSWAP(val));
80
@@ -XXX,XX +XXX,XX @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
81
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
82
ABI_TYPE val, MemOpIdx oi, uintptr_t retaddr) \
83
{ \
84
- DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
85
- PAGE_READ | PAGE_WRITE, retaddr); \
86
- DATA_TYPE ret; \
87
+ DATA_TYPE *haddr, ret; \
88
+ haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, retaddr); \
89
ret = qatomic_##X(haddr, BSWAP(val)); \
90
ATOMIC_MMU_CLEANUP; \
91
atomic_trace_rmw_post(env, addr, oi); \
92
@@ -XXX,XX +XXX,XX @@ GEN_ATOMIC_HELPER(xor_fetch)
93
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr, \
94
ABI_TYPE xval, MemOpIdx oi, uintptr_t retaddr) \
95
{ \
96
- XDATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
97
- PAGE_READ | PAGE_WRITE, retaddr); \
98
- XDATA_TYPE ldo, ldn, old, new, val = xval; \
99
+ XDATA_TYPE *haddr, ldo, ldn, old, new, val = xval; \
100
+ haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, retaddr); \
101
smp_mb(); \
102
ldn = qatomic_read__nocheck(haddr); \
103
do { \
104
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
105
index XXXXXXX..XXXXXXX 100644
106
--- a/accel/tcg/cputlb.c
107
+++ b/accel/tcg/cputlb.c
108
@@ -XXX,XX +XXX,XX @@ static bool mmu_lookup(CPUArchState *env, target_ulong addr, MemOpIdx oi,
109
/*
110
* Probe for an atomic operation. Do not allow unaligned operations,
111
* or io operations to proceed. Return the host address.
112
- *
113
- * @prot may be PAGE_READ, PAGE_WRITE, or PAGE_READ|PAGE_WRITE.
114
*/
115
static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
116
- MemOpIdx oi, int size, int prot,
117
- uintptr_t retaddr)
118
+ MemOpIdx oi, int size, uintptr_t retaddr)
119
{
120
uintptr_t mmu_idx = get_mmuidx(oi);
121
MemOp mop = get_memop(oi);
122
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
123
tlbe = tlb_entry(env, mmu_idx, addr);
124
125
/* Check TLB entry and enforce page permissions. */
126
- if (prot & PAGE_WRITE) {
127
- tlb_addr = tlb_addr_write(tlbe);
128
- if (!tlb_hit(tlb_addr, addr)) {
129
- if (!victim_tlb_hit(env, mmu_idx, index, MMU_DATA_STORE,
130
- addr & TARGET_PAGE_MASK)) {
131
- tlb_fill(env_cpu(env), addr, size,
132
- MMU_DATA_STORE, mmu_idx, retaddr);
133
- index = tlb_index(env, mmu_idx, addr);
134
- tlbe = tlb_entry(env, mmu_idx, addr);
135
- }
136
- tlb_addr = tlb_addr_write(tlbe) & ~TLB_INVALID_MASK;
137
- }
23
-
138
-
24
- /*
139
- if (prot & PAGE_READ) {
25
- * This function should never be called with addresses outside the
140
- /*
26
- * guest address space. If this assert fires, it probably indicates
141
- * Let the guest notice RMW on a write-only page.
27
- * a missing call to h2g_valid.
142
- * We have just verified that the page is writable.
28
- */
143
- * Subpage lookups may have left TLB_INVALID_MASK set,
29
- assert(end - 1 <= GUEST_ADDR_MAX);
144
- * but addr_read will only be -1 if PAGE_READ was unset.
30
- assert(start < end);
145
- */
31
- assert_memory_lock();
146
- if (unlikely(tlbe->addr_read == -1)) {
32
-
147
- tlb_fill(env_cpu(env), addr, size,
33
- start = start & TARGET_PAGE_MASK;
148
- MMU_DATA_LOAD, mmu_idx, retaddr);
34
- end = TARGET_PAGE_ALIGN(end);
149
- /*
35
-
150
- * Since we don't support reads and writes to different
36
- for (addr = start, len = end - start;
151
- * addresses, and we do have the proper page loaded for
37
- len != 0;
152
- * write, this shouldn't ever return. But just in case,
38
- len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
153
- * handle via stop-the-world.
39
- PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
154
- */
40
-
155
- goto stop_the_world;
41
- g_free(p->target_data);
156
- }
42
- p->target_data = NULL;
157
- /* Collect TLB_WATCHPOINT for read. */
43
- }
158
- tlb_addr |= tlbe->addr_read;
44
-#endif
45
-}
46
-
47
-#ifdef TARGET_PAGE_DATA_SIZE
48
-void *page_get_target_data(target_ulong address)
49
-{
50
- PageDesc *p = page_find(address >> TARGET_PAGE_BITS);
51
- return p ? p->target_data : NULL;
52
-}
53
-
54
-void *page_alloc_target_data(target_ulong address)
55
-{
56
- PageDesc *p = page_find(address >> TARGET_PAGE_BITS);
57
- void *ret = NULL;
58
-
59
- if (p->flags & PAGE_VALID) {
60
- ret = p->target_data;
61
- if (!ret) {
62
- p->target_data = ret = g_malloc0(TARGET_PAGE_DATA_SIZE);
63
- }
159
- }
64
- }
160
- } else /* if (prot & PAGE_READ) */ {
65
- return ret;
161
- tlb_addr = tlbe->addr_read;
66
-}
162
- if (!tlb_hit(tlb_addr, addr)) {
67
-#endif /* TARGET_PAGE_DATA_SIZE */
163
- if (!victim_tlb_hit(env, mmu_idx, index, MMU_DATA_LOAD,
68
-
164
- addr & TARGET_PAGE_MASK)) {
69
int page_check_range(target_ulong start, target_ulong len, int flags)
165
- tlb_fill(env_cpu(env), addr, size,
70
{
166
- MMU_DATA_LOAD, mmu_idx, retaddr);
71
PageDesc *p;
167
- index = tlb_index(env, mmu_idx, addr);
168
- tlbe = tlb_entry(env, mmu_idx, addr);
169
- }
170
- tlb_addr = tlbe->addr_read & ~TLB_INVALID_MASK;
171
+ tlb_addr = tlb_addr_write(tlbe);
172
+ if (!tlb_hit(tlb_addr, addr)) {
173
+ if (!victim_tlb_hit(env, mmu_idx, index, MMU_DATA_STORE,
174
+ addr & TARGET_PAGE_MASK)) {
175
+ tlb_fill(env_cpu(env), addr, size,
176
+ MMU_DATA_STORE, mmu_idx, retaddr);
177
+ index = tlb_index(env, mmu_idx, addr);
178
+ tlbe = tlb_entry(env, mmu_idx, addr);
179
}
180
+ tlb_addr = tlb_addr_write(tlbe) & ~TLB_INVALID_MASK;
181
}
182
183
+ /*
184
+ * Let the guest notice RMW on a write-only page.
185
+ * We have just verified that the page is writable.
186
+ * Subpage lookups may have left TLB_INVALID_MASK set,
187
+ * but addr_read will only be -1 if PAGE_READ was unset.
188
+ */
189
+ if (unlikely(tlbe->addr_read == -1)) {
190
+ tlb_fill(env_cpu(env), addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
191
+ /*
192
+ * Since we don't support reads and writes to different
193
+ * addresses, and we do have the proper page loaded for
194
+ * write, this shouldn't ever return. But just in case,
195
+ * handle via stop-the-world.
196
+ */
197
+ goto stop_the_world;
198
+ }
199
+ /* Collect TLB_WATCHPOINT for read. */
200
+ tlb_addr |= tlbe->addr_read;
201
+
202
/* Notice an IO access or a needs-MMU-lookup access */
203
if (unlikely(tlb_addr & (TLB_MMIO | TLB_DISCARD_WRITE))) {
204
/* There's really nothing that can be done to
205
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
206
}
207
208
if (unlikely(tlb_addr & TLB_WATCHPOINT)) {
209
- QEMU_BUILD_BUG_ON(PAGE_READ != BP_MEM_READ);
210
- QEMU_BUILD_BUG_ON(PAGE_WRITE != BP_MEM_WRITE);
211
- /* therefore prot == watchpoint bits */
212
- cpu_check_watchpoint(env_cpu(env), addr, size,
213
- full->attrs, prot, retaddr);
214
+ cpu_check_watchpoint(env_cpu(env), addr, size, full->attrs,
215
+ BP_MEM_READ | BP_MEM_WRITE, retaddr);
216
}
217
218
return hostaddr;
72
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
219
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
73
index XXXXXXX..XXXXXXX 100644
220
index XXXXXXX..XXXXXXX 100644
74
--- a/accel/tcg/user-exec.c
221
--- a/accel/tcg/user-exec.c
75
+++ b/accel/tcg/user-exec.c
222
+++ b/accel/tcg/user-exec.c
76
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
223
@@ -XXX,XX +XXX,XX @@ uint64_t cpu_ldq_code_mmu(CPUArchState *env, abi_ptr addr,
77
return addr;
78
}
79
80
+void page_reset_target_data(target_ulong start, target_ulong end)
81
+{
82
+#ifdef TARGET_PAGE_DATA_SIZE
83
+ target_ulong addr, len;
84
+
85
+ /*
86
+ * This function should never be called with addresses outside the
87
+ * guest address space. If this assert fires, it probably indicates
88
+ * a missing call to h2g_valid.
89
+ */
90
+ assert(end - 1 <= GUEST_ADDR_MAX);
91
+ assert(start < end);
92
+ assert_memory_lock();
93
+
94
+ start = start & TARGET_PAGE_MASK;
95
+ end = TARGET_PAGE_ALIGN(end);
96
+
97
+ for (addr = start, len = end - start;
98
+ len != 0;
99
+ len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
100
+ PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
101
+
102
+ g_free(p->target_data);
103
+ p->target_data = NULL;
104
+ }
105
+#endif
106
+}
107
+
108
+#ifdef TARGET_PAGE_DATA_SIZE
109
+void *page_get_target_data(target_ulong address)
110
+{
111
+ PageDesc *p = page_find(address >> TARGET_PAGE_BITS);
112
+ return p ? p->target_data : NULL;
113
+}
114
+
115
+void *page_alloc_target_data(target_ulong address)
116
+{
117
+ PageDesc *p = page_find(address >> TARGET_PAGE_BITS);
118
+ void *ret = NULL;
119
+
120
+ if (p->flags & PAGE_VALID) {
121
+ ret = p->target_data;
122
+ if (!ret) {
123
+ p->target_data = ret = g_malloc0(TARGET_PAGE_DATA_SIZE);
124
+ }
125
+ }
126
+ return ret;
127
+}
128
+#endif
129
+
130
/* The softmmu versions of these helpers are in cputlb.c. */
131
224
132
/*
225
/*
226
* Do not allow unaligned operations to proceed. Return the host address.
227
- *
228
- * @prot may be PAGE_READ, PAGE_WRITE, or PAGE_READ|PAGE_WRITE.
229
*/
230
static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
231
- MemOpIdx oi, int size, int prot,
232
- uintptr_t retaddr)
233
+ MemOpIdx oi, int size, uintptr_t retaddr)
234
{
235
MemOp mop = get_memop(oi);
236
int a_bits = get_alignment_bits(mop);
237
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
238
239
/* Enforce guest required alignment. */
240
if (unlikely(addr & ((1 << a_bits) - 1))) {
241
- MMUAccessType t = prot == PAGE_READ ? MMU_DATA_LOAD : MMU_DATA_STORE;
242
- cpu_loop_exit_sigbus(env_cpu(env), addr, t, retaddr);
243
+ cpu_loop_exit_sigbus(env_cpu(env), addr, MMU_DATA_STORE, retaddr);
244
}
245
246
/* Enforce qemu required alignment. */
133
--
247
--
134
2.34.1
248
2.34.1
135
249
136
250
diff view generated by jsdifflib
1
Since the only user, Arm MTE, always requires allocation,
1
These symbols will shortly become dynamic runtime tests and
2
merge the get and alloc functions to always produce a
2
therefore not appropriate for the preprocessor. Use the
3
non-null result. Also assume that the user has already
3
matching CONFIG_* symbols for that purpose.
4
checked page validity.
5
4
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
7
---
9
include/exec/cpu-all.h | 21 ++++++---------------
8
host/include/aarch64/host/atomic128-cas.h | 2 ++
10
accel/tcg/user-exec.c | 16 ++++------------
9
host/include/generic/host/atomic128-ldst.h | 2 +-
11
target/arm/mte_helper.c | 4 ----
10
accel/tcg/cputlb.c | 2 +-
12
3 files changed, 10 insertions(+), 31 deletions(-)
11
accel/tcg/user-exec.c | 2 +-
12
4 files changed, 5 insertions(+), 3 deletions(-)
13
13
14
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
14
diff --git a/host/include/aarch64/host/atomic128-cas.h b/host/include/aarch64/host/atomic128-cas.h
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/exec/cpu-all.h
16
--- a/host/include/aarch64/host/atomic128-cas.h
17
+++ b/include/exec/cpu-all.h
17
+++ b/host/include/aarch64/host/atomic128-cas.h
18
@@ -XXX,XX +XXX,XX @@ void page_reset_target_data(target_ulong start, target_ulong end);
18
@@ -XXX,XX +XXX,XX @@ static inline Int128 atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
19
int page_check_range(target_ulong start, target_ulong len, int flags);
19
20
20
return int128_make128(oldl, oldh);
21
/**
21
}
22
- * page_alloc_target_data(address)
22
+
23
+ * page_get_target_data(address)
23
+# define CONFIG_CMPXCHG128 1
24
* @address: guest virtual address
24
# define HAVE_CMPXCHG128 1
25
*
26
- * Allocate TARGET_PAGE_DATA_SIZE bytes of out-of-band data to associate
27
- * with the guest page at @address. If the page is not mapped, NULL will
28
- * be returned. If there is existing data associated with @address,
29
- * no new memory will be allocated.
30
+ * Return TARGET_PAGE_DATA_SIZE bytes of out-of-band data to associate
31
+ * with the guest page at @address, allocating it if necessary. The
32
+ * caller should already have verified that the address is valid.
33
*
34
* The memory will be freed when the guest page is deallocated,
35
* e.g. with the munmap system call.
36
*/
37
-void *page_alloc_target_data(target_ulong address);
38
-
39
-/**
40
- * page_get_target_data(address)
41
- * @address: guest virtual address
42
- *
43
- * Return any out-of-bound memory assocated with the guest page
44
- * at @address, as per page_alloc_target_data.
45
- */
46
-void *page_get_target_data(target_ulong address);
47
+void *page_get_target_data(target_ulong address)
48
+ __attribute__((returns_nonnull));
49
#endif
25
#endif
50
26
51
CPUArchState *cpu_copy(CPUArchState *env);
27
diff --git a/host/include/generic/host/atomic128-ldst.h b/host/include/generic/host/atomic128-ldst.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/host/include/generic/host/atomic128-ldst.h
30
+++ b/host/include/generic/host/atomic128-ldst.h
31
@@ -XXX,XX +XXX,XX @@ atomic16_set(Int128 *ptr, Int128 val)
32
}
33
34
# define HAVE_ATOMIC128 1
35
-#elif !defined(CONFIG_USER_ONLY) && HAVE_CMPXCHG128
36
+#elif defined(CONFIG_CMPXCHG128) && !defined(CONFIG_USER_ONLY)
37
static inline Int128 ATTRIBUTE_ATOMIC128_OPT
38
atomic16_read(Int128 *ptr)
39
{
40
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/accel/tcg/cputlb.c
43
+++ b/accel/tcg/cputlb.c
44
@@ -XXX,XX +XXX,XX @@ void cpu_st16_mmu(CPUArchState *env, target_ulong addr, Int128 val,
45
#include "atomic_template.h"
46
#endif
47
48
-#if HAVE_CMPXCHG128 || HAVE_ATOMIC128
49
+#if defined(CONFIG_ATOMIC128) || defined(CONFIG_CMPXCHG128)
50
#define DATA_SIZE 16
51
#include "atomic_template.h"
52
#endif
52
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
53
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
53
index XXXXXXX..XXXXXXX 100644
54
index XXXXXXX..XXXXXXX 100644
54
--- a/accel/tcg/user-exec.c
55
--- a/accel/tcg/user-exec.c
55
+++ b/accel/tcg/user-exec.c
56
+++ b/accel/tcg/user-exec.c
56
@@ -XXX,XX +XXX,XX @@ void page_reset_target_data(target_ulong start, target_ulong end)
57
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
57
void *page_get_target_data(target_ulong address)
58
#include "atomic_template.h"
58
{
59
#endif
59
PageDesc *p = page_find(address >> TARGET_PAGE_BITS);
60
60
- return p ? p->target_data : NULL;
61
-#if HAVE_ATOMIC128 || HAVE_CMPXCHG128
61
-}
62
+#if defined(CONFIG_ATOMIC128) || defined(CONFIG_CMPXCHG128)
62
+ void *ret = p->target_data;
63
#define DATA_SIZE 16
63
64
#include "atomic_template.h"
64
-void *page_alloc_target_data(target_ulong address)
65
#endif
65
-{
66
- PageDesc *p = page_find(address >> TARGET_PAGE_BITS);
67
- void *ret = NULL;
68
-
69
- if (p->flags & PAGE_VALID) {
70
- ret = p->target_data;
71
- if (!ret) {
72
- p->target_data = ret = g_malloc0(TARGET_PAGE_DATA_SIZE);
73
- }
74
+ if (!ret) {
75
+ ret = g_malloc0(TARGET_PAGE_DATA_SIZE);
76
+ p->target_data = ret;
77
}
78
return ret;
79
}
80
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/target/arm/mte_helper.c
83
+++ b/target/arm/mte_helper.c
84
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
85
}
86
87
tags = page_get_target_data(clean_ptr);
88
- if (tags == NULL) {
89
- tags = page_alloc_target_data(clean_ptr);
90
- assert(tags != NULL);
91
- }
92
93
index = extract32(ptr, LOG2_TAG_GRANULE + 1,
94
TARGET_PAGE_BITS - LOG2_TAG_GRANULE - 1);
95
--
66
--
96
2.34.1
67
2.34.1
97
68
98
69
diff view generated by jsdifflib
1
The results of the calls to cpu_get_tb_cpu_state,
1
Create both atomic16_read_ro and atomic16_read_rw.
2
current_{pc,cs_base,flags}, are not used.
2
Previously we pretended that we had atomic16_read in system mode,
3
In tb_invalidate_phys_page, use bool for current_tb_modified.
3
because we "know" that all ram is always writable to the host.
4
Now, expose read-only and read-write versions all of the time.
5
6
For aarch64, do not fall back to __atomic_read_16 even if
7
supported by the compiler, to work around a clang bug.
4
8
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
11
---
8
accel/tcg/tb-maint.c | 25 ++-----------------------
12
host/include/aarch64/host/atomic128-ldst.h | 21 ++++++++-------
9
1 file changed, 2 insertions(+), 23 deletions(-)
13
host/include/generic/host/atomic128-ldst.h | 31 ++++++++++++++++------
14
target/s390x/tcg/mem_helper.c | 2 +-
15
3 files changed, 36 insertions(+), 18 deletions(-)
10
16
11
diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c
17
diff --git a/host/include/aarch64/host/atomic128-ldst.h b/host/include/aarch64/host/atomic128-ldst.h
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/accel/tcg/tb-maint.c
19
--- a/host/include/aarch64/host/atomic128-ldst.h
14
+++ b/accel/tcg/tb-maint.c
20
+++ b/host/include/aarch64/host/atomic128-ldst.h
15
@@ -XXX,XX +XXX,XX @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
21
@@ -XXX,XX +XXX,XX @@
16
int n;
22
#ifndef AARCH64_ATOMIC128_LDST_H
17
#ifdef TARGET_HAS_PRECISE_SMC
23
#define AARCH64_ATOMIC128_LDST_H
18
CPUState *cpu = current_cpu;
24
19
- CPUArchState *env = NULL;
25
-/* Through gcc 10, aarch64 has no support for 128-bit atomics. */
20
bool current_tb_not_found = retaddr != 0;
26
-#if !defined(CONFIG_ATOMIC128) && !defined(CONFIG_USER_ONLY)
21
bool current_tb_modified = false;
27
-/* We can do better than cmpxchg for AArch64. */
22
TranslationBlock *current_tb = NULL;
28
-static inline Int128 atomic16_read(Int128 *ptr)
23
- target_ulong current_pc = 0;
29
+/*
24
- target_ulong current_cs_base = 0;
30
+ * Through gcc 10, aarch64 has no support for 128-bit atomics.
25
- uint32_t current_flags = 0;
31
+ * Through clang 16, without -march=armv8.4-a, __atomic_load_16
26
#endif /* TARGET_HAS_PRECISE_SMC */
32
+ * is incorrectly expanded to a read-write operation.
27
33
+ */
28
assert_page_locked(p);
34
+
29
35
+#define HAVE_ATOMIC128_RO 0
30
-#if defined(TARGET_HAS_PRECISE_SMC)
36
+#define HAVE_ATOMIC128_RW 1
31
- if (cpu != NULL) {
37
+
32
- env = cpu->env_ptr;
38
+Int128 QEMU_ERROR("unsupported atomic") atomic16_read_ro(const Int128 *ptr);
33
- }
39
+
40
+static inline Int128 atomic16_read_rw(Int128 *ptr)
41
{
42
uint64_t l, h;
43
uint32_t tmp;
44
@@ -XXX,XX +XXX,XX @@ static inline void atomic16_set(Int128 *ptr, Int128 val)
45
: [l] "r"(l), [h] "r"(h));
46
}
47
48
-# define HAVE_ATOMIC128 1
49
-#else
50
-#include "host/include/generic/host/atomic128-ldst.h"
34
-#endif
51
-#endif
35
-
52
-
36
/*
53
#endif /* AARCH64_ATOMIC128_LDST_H */
37
* We remove all the TBs in the range [start, end[.
54
diff --git a/host/include/generic/host/atomic128-ldst.h b/host/include/generic/host/atomic128-ldst.h
38
* XXX: see if in some cases it could be faster to invalidate all the code
55
index XXXXXXX..XXXXXXX 100644
39
@@ -XXX,XX +XXX,XX @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
56
--- a/host/include/generic/host/atomic128-ldst.h
40
*/
57
+++ b/host/include/generic/host/atomic128-ldst.h
41
current_tb_modified = true;
58
@@ -XXX,XX +XXX,XX @@
42
cpu_restore_state_from_tb(cpu, current_tb, retaddr, true);
59
#define HOST_ATOMIC128_LDST_H
43
- cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
60
44
- &current_flags);
61
#if defined(CONFIG_ATOMIC128)
45
}
62
+# define HAVE_ATOMIC128_RO 1
46
#endif /* TARGET_HAS_PRECISE_SMC */
63
+# define HAVE_ATOMIC128_RW 1
47
tb_phys_invalidate__locked(tb);
64
+
48
@@ -XXX,XX +XXX,XX @@ bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc)
65
static inline Int128 ATTRIBUTE_ATOMIC128_OPT
49
#ifdef TARGET_HAS_PRECISE_SMC
66
-atomic16_read(Int128 *ptr)
50
TranslationBlock *current_tb = NULL;
67
+atomic16_read_ro(const Int128 *ptr)
51
CPUState *cpu = current_cpu;
68
{
52
- CPUArchState *env = NULL;
69
- __int128_t *ptr_align = __builtin_assume_aligned(ptr, 16);
53
- int current_tb_modified = 0;
70
+ const __int128_t *ptr_align = __builtin_assume_aligned(ptr, 16);
54
- target_ulong current_pc = 0;
71
Int128Alias r;
55
- target_ulong current_cs_base = 0;
72
56
- uint32_t current_flags = 0;
73
r.i = qatomic_read__nocheck(ptr_align);
57
+ bool current_tb_modified = false;
74
return r.s;
75
}
76
77
+static inline Int128 ATTRIBUTE_ATOMIC128_OPT
78
+atomic16_read_rw(Int128 *ptr)
79
+{
80
+ return atomic16_read_ro(ptr);
81
+}
82
+
83
static inline void ATTRIBUTE_ATOMIC128_OPT
84
atomic16_set(Int128 *ptr, Int128 val)
85
{
86
@@ -XXX,XX +XXX,XX @@ atomic16_set(Int128 *ptr, Int128 val)
87
qatomic_set__nocheck(ptr_align, v.i);
88
}
89
90
-# define HAVE_ATOMIC128 1
91
-#elif defined(CONFIG_CMPXCHG128) && !defined(CONFIG_USER_ONLY)
92
+#elif defined(CONFIG_CMPXCHG128)
93
+# define HAVE_ATOMIC128_RO 0
94
+# define HAVE_ATOMIC128_RW 1
95
+
96
+Int128 QEMU_ERROR("unsupported atomic") atomic16_read_ro(const Int128 *ptr);
97
+
98
static inline Int128 ATTRIBUTE_ATOMIC128_OPT
99
-atomic16_read(Int128 *ptr)
100
+atomic16_read_rw(Int128 *ptr)
101
{
102
/* Maybe replace 0 with 0, returning the old value. */
103
Int128 z = int128_make64(0);
104
@@ -XXX,XX +XXX,XX @@ atomic16_set(Int128 *ptr, Int128 val)
105
} while (int128_ne(old, cmp));
106
}
107
108
-# define HAVE_ATOMIC128 1
109
#else
110
+# define HAVE_ATOMIC128_RO 0
111
+# define HAVE_ATOMIC128_RW 0
112
+
113
/* Fallback definitions that must be optimized away, or error. */
114
-Int128 QEMU_ERROR("unsupported atomic") atomic16_read(Int128 *ptr);
115
+Int128 QEMU_ERROR("unsupported atomic") atomic16_read_ro(const Int128 *ptr);
116
+Int128 QEMU_ERROR("unsupported atomic") atomic16_read_rw(Int128 *ptr);
117
void QEMU_ERROR("unsupported atomic") atomic16_set(Int128 *ptr, Int128 val);
118
-# define HAVE_ATOMIC128 0
58
#endif
119
#endif
59
120
60
assert_memory_lock();
121
#endif /* HOST_ATOMIC128_LDST_H */
61
@@ -XXX,XX +XXX,XX @@ bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc)
122
diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c
62
if (p->first_tb && pc != 0) {
123
index XXXXXXX..XXXXXXX 100644
63
current_tb = tcg_tb_lookup(pc);
124
--- a/target/s390x/tcg/mem_helper.c
125
+++ b/target/s390x/tcg/mem_helper.c
126
@@ -XXX,XX +XXX,XX @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
127
max = 3;
128
#endif
129
if ((HAVE_CMPXCHG128 ? 0 : fc + 2 > max) ||
130
- (HAVE_ATOMIC128 ? 0 : sc > max)) {
131
+ (HAVE_ATOMIC128_RW ? 0 : sc > max)) {
132
cpu_loop_exit_atomic(env_cpu(env), ra);
133
}
64
}
134
}
65
- if (cpu != NULL) {
66
- env = cpu->env_ptr;
67
- }
68
#endif
69
assert_page_locked(p);
70
PAGE_FOR_EACH_TB(p, tb, n) {
71
@@ -XXX,XX +XXX,XX @@ bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc)
72
* after the current PC, but it would require a specialized
73
* function to partially restore the CPU state.
74
*/
75
- current_tb_modified = 1;
76
+ current_tb_modified = true;
77
cpu_restore_state_from_tb(cpu, current_tb, pc, true);
78
- cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
79
- &current_flags);
80
}
81
#endif /* TARGET_HAS_PRECISE_SMC */
82
tb_phys_invalidate(tb, addr);
83
--
135
--
84
2.34.1
136
2.34.1
85
137
86
138
diff view generated by jsdifflib
1
This function is is never called with a real range,
1
Remove the locally defined load_atomic16 and store_atomic16,
2
only for a single page. Drop the second parameter
2
along with HAVE_al16 and HAVE_al16_fast in favor of the
3
and rename to tb_invalidate_phys_page.
3
routines defined in atomic128.h.
4
4
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
7
---
8
include/exec/translate-all.h | 2 +-
8
accel/tcg/cputlb.c | 2 +-
9
accel/tcg/tb-maint.c | 15 ++++++++-------
9
accel/tcg/ldst_atomicity.c.inc | 118 +++++++--------------------------
10
cpu.c | 4 ++--
10
2 files changed, 24 insertions(+), 96 deletions(-)
11
3 files changed, 11 insertions(+), 10 deletions(-)
11
12
12
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
13
diff --git a/include/exec/translate-all.h b/include/exec/translate-all.h
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/include/exec/translate-all.h
14
--- a/accel/tcg/cputlb.c
16
+++ b/include/exec/translate-all.h
15
+++ b/accel/tcg/cputlb.c
17
@@ -XXX,XX +XXX,XX @@ void page_collection_unlock(struct page_collection *set);
16
@@ -XXX,XX +XXX,XX @@ static uint64_t do_st16_leN(CPUArchState *env, MMULookupPageData *p,
18
void tb_invalidate_phys_page_fast(struct page_collection *pages,
17
19
tb_page_addr_t start, int len,
18
case MO_ATOM_WITHIN16_PAIR:
20
uintptr_t retaddr);
19
/* Since size > 8, this is the half that must be atomic. */
21
-void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end);
20
- if (!HAVE_al16) {
22
+void tb_invalidate_phys_page(tb_page_addr_t addr);
21
+ if (!HAVE_ATOMIC128_RW) {
23
void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr);
22
cpu_loop_exit_atomic(env_cpu(env), ra);
23
}
24
return store_whole_le16(p->haddr, p->size, val_le);
25
diff --git a/accel/tcg/ldst_atomicity.c.inc b/accel/tcg/ldst_atomicity.c.inc
26
index XXXXXXX..XXXXXXX 100644
27
--- a/accel/tcg/ldst_atomicity.c.inc
28
+++ b/accel/tcg/ldst_atomicity.c.inc
29
@@ -XXX,XX +XXX,XX @@
30
#endif
31
#define HAVE_al8_fast (ATOMIC_REG_SIZE >= 8)
32
33
-#if defined(CONFIG_ATOMIC128)
34
-# define HAVE_al16_fast true
35
-#else
36
-# define HAVE_al16_fast false
37
-#endif
38
-#if defined(CONFIG_ATOMIC128) || defined(CONFIG_CMPXCHG128)
39
-# define HAVE_al16 true
40
-#else
41
-# define HAVE_al16 false
42
-#endif
43
-
44
-
45
/**
46
* required_atomicity:
47
*
48
@@ -XXX,XX +XXX,XX @@ static inline uint64_t load_atomic8(void *pv)
49
return qatomic_read__nocheck(p);
50
}
51
52
-/**
53
- * load_atomic16:
54
- * @pv: host address
55
- *
56
- * Atomically load 16 aligned bytes from @pv.
57
- */
58
-static inline Int128 ATTRIBUTE_ATOMIC128_OPT
59
-load_atomic16(void *pv)
60
-{
61
-#ifdef CONFIG_ATOMIC128
62
- __uint128_t *p = __builtin_assume_aligned(pv, 16);
63
- Int128Alias r;
64
-
65
- r.u = qatomic_read__nocheck(p);
66
- return r.s;
67
-#else
68
- qemu_build_not_reached();
69
-#endif
70
-}
71
-
72
/**
73
* load_atomic8_or_exit:
74
* @env: cpu context
75
@@ -XXX,XX +XXX,XX @@ static Int128 load_atomic16_or_exit(CPUArchState *env, uintptr_t ra, void *pv)
76
{
77
Int128 *p = __builtin_assume_aligned(pv, 16);
78
79
- if (HAVE_al16_fast) {
80
- return load_atomic16(p);
81
+ if (HAVE_ATOMIC128_RO) {
82
+ return atomic16_read_ro(p);
83
}
24
84
25
#ifdef CONFIG_USER_ONLY
85
#ifdef CONFIG_USER_ONLY
26
diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c
86
@@ -XXX,XX +XXX,XX @@ static Int128 load_atomic16_or_exit(CPUArchState *env, uintptr_t ra, void *pv)
27
index XXXXXXX..XXXXXXX 100644
87
* In system mode all guest pages are writable, and for user-only
28
--- a/accel/tcg/tb-maint.c
88
* we have just checked writability. Try cmpxchg.
29
+++ b/accel/tcg/tb-maint.c
89
*/
30
@@ -XXX,XX +XXX,XX @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
90
-#if defined(CONFIG_CMPXCHG128)
91
- /* Swap 0 with 0, with the side-effect of returning the old value. */
92
- {
93
- Int128Alias r;
94
- r.u = __sync_val_compare_and_swap_16((__uint128_t *)p, 0, 0);
95
- return r.s;
96
+ if (HAVE_ATOMIC128_RW) {
97
+ return atomic16_read_rw(p);
98
}
99
-#endif
100
101
/* Ultimate fallback: re-execute in serial context. */
102
cpu_loop_exit_atomic(env_cpu(env), ra);
103
@@ -XXX,XX +XXX,XX @@ static uint64_t load_atom_extract_al16_or_exit(CPUArchState *env, uintptr_t ra,
104
static inline uint64_t ATTRIBUTE_ATOMIC128_OPT
105
load_atom_extract_al16_or_al8(void *pv, int s)
106
{
107
-#if defined(CONFIG_ATOMIC128)
108
uintptr_t pi = (uintptr_t)pv;
109
int o = pi & 7;
110
int shr = (HOST_BIG_ENDIAN ? 16 - s - o : o) * 8;
111
- __uint128_t r;
112
+ Int128 r;
113
114
pv = (void *)(pi & ~7);
115
if (pi & 8) {
116
@@ -XXX,XX +XXX,XX @@ load_atom_extract_al16_or_al8(void *pv, int s)
117
uint64_t b = qatomic_read__nocheck(p8 + 1);
118
119
if (HOST_BIG_ENDIAN) {
120
- r = ((__uint128_t)a << 64) | b;
121
+ r = int128_make128(b, a);
122
} else {
123
- r = ((__uint128_t)b << 64) | a;
124
+ r = int128_make128(a, b);
125
}
126
} else {
127
- __uint128_t *p16 = __builtin_assume_aligned(pv, 16, 0);
128
- r = qatomic_read__nocheck(p16);
129
+ r = atomic16_read_ro(pv);
130
}
131
- return r >> shr;
132
-#else
133
- qemu_build_not_reached();
134
-#endif
135
+ return int128_getlo(int128_urshift(r, shr));
31
}
136
}
32
137
33
/*
138
/**
34
- * Invalidate all TBs which intersect with the target physical address range
139
@@ -XXX,XX +XXX,XX @@ static uint16_t load_atom_2(CPUArchState *env, uintptr_t ra,
35
- * [start;end[. NOTE: start and end must refer to the *same* physical page.
140
if (likely((pi & 1) == 0)) {
36
- * 'is_cpu_write_access' should be true if called from a real cpu write
141
return load_atomic2(pv);
37
- * access: the virtual CPU will exit the current TB if code is modified inside
142
}
38
- * this TB.
143
- if (HAVE_al16_fast) {
39
+ * Invalidate all TBs which intersect with the target physical
144
+ if (HAVE_ATOMIC128_RO) {
40
+ * address page @addr.
145
return load_atom_extract_al16_or_al8(pv, 2);
41
*
146
}
42
* Called with mmap_lock held for user-mode emulation
147
148
@@ -XXX,XX +XXX,XX @@ static uint32_t load_atom_4(CPUArchState *env, uintptr_t ra,
149
if (likely((pi & 3) == 0)) {
150
return load_atomic4(pv);
151
}
152
- if (HAVE_al16_fast) {
153
+ if (HAVE_ATOMIC128_RO) {
154
return load_atom_extract_al16_or_al8(pv, 4);
155
}
156
157
@@ -XXX,XX +XXX,XX @@ static uint64_t load_atom_8(CPUArchState *env, uintptr_t ra,
158
if (HAVE_al8 && likely((pi & 7) == 0)) {
159
return load_atomic8(pv);
160
}
161
- if (HAVE_al16_fast) {
162
+ if (HAVE_ATOMIC128_RO) {
163
return load_atom_extract_al16_or_al8(pv, 8);
164
}
165
166
@@ -XXX,XX +XXX,XX @@ static Int128 load_atom_16(CPUArchState *env, uintptr_t ra,
167
* If the host does not support 16-byte atomics, wait until we have
168
* examined the atomicity parameters below.
169
*/
170
- if (HAVE_al16_fast && likely((pi & 15) == 0)) {
171
- return load_atomic16(pv);
172
+ if (HAVE_ATOMIC128_RO && likely((pi & 15) == 0)) {
173
+ return atomic16_read_ro(pv);
174
}
175
176
atmax = required_atomicity(env, pi, memop);
177
@@ -XXX,XX +XXX,XX @@ static inline void store_atomic8(void *pv, uint64_t val)
178
qatomic_set__nocheck(p, val);
179
}
180
181
-/**
182
- * store_atomic16:
183
- * @pv: host address
184
- * @val: value to store
185
- *
186
- * Atomically store 16 aligned bytes to @pv.
187
- */
188
-static inline void ATTRIBUTE_ATOMIC128_OPT
189
-store_atomic16(void *pv, Int128Alias val)
190
-{
191
-#if defined(CONFIG_ATOMIC128)
192
- __uint128_t *pu = __builtin_assume_aligned(pv, 16);
193
- qatomic_set__nocheck(pu, val.u);
194
-#elif defined(CONFIG_CMPXCHG128)
195
- __uint128_t *pu = __builtin_assume_aligned(pv, 16);
196
- __uint128_t o;
197
-
198
- /*
199
- * Without CONFIG_ATOMIC128, __atomic_compare_exchange_n will always
200
- * defer to libatomic, so we must use __sync_*_compare_and_swap_16
201
- * and accept the sequential consistency that comes with it.
202
- */
203
- do {
204
- o = *pu;
205
- } while (!__sync_bool_compare_and_swap_16(pu, o, val.u));
206
-#else
207
- qemu_build_not_reached();
208
-#endif
209
-}
210
-
211
/**
212
* store_atom_4x2
43
*/
213
*/
44
-void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end)
214
@@ -XXX,XX +XXX,XX @@ static uint64_t store_whole_le16(void *pv, int size, Int128 val_le)
45
+void tb_invalidate_phys_page(tb_page_addr_t addr)
215
int sh = o * 8;
46
{
216
Int128 m, v;
47
struct page_collection *pages;
217
48
+ tb_page_addr_t start, end;
218
- qemu_build_assert(HAVE_al16);
49
PageDesc *p;
219
+ qemu_build_assert(HAVE_ATOMIC128_RW);
50
220
51
assert_memory_lock();
221
/* Like MAKE_64BIT_MASK(0, sz), but larger. */
52
222
if (sz <= 64) {
53
- p = page_find(start >> TARGET_PAGE_BITS);
223
@@ -XXX,XX +XXX,XX @@ static void store_atom_2(CPUArchState *env, uintptr_t ra,
54
+ p = page_find(addr >> TARGET_PAGE_BITS);
224
return;
55
if (p == NULL) {
225
}
226
} else if ((pi & 15) == 7) {
227
- if (HAVE_al16) {
228
+ if (HAVE_ATOMIC128_RW) {
229
Int128 v = int128_lshift(int128_make64(val), 56);
230
Int128 m = int128_lshift(int128_make64(0xffff), 56);
231
store_atom_insert_al16(pv - 7, v, m);
232
@@ -XXX,XX +XXX,XX @@ static void store_atom_4(CPUArchState *env, uintptr_t ra,
233
return;
234
}
235
} else {
236
- if (HAVE_al16) {
237
+ if (HAVE_ATOMIC128_RW) {
238
store_whole_le16(pv, 4, int128_make64(cpu_to_le32(val)));
239
return;
240
}
241
@@ -XXX,XX +XXX,XX @@ static void store_atom_8(CPUArchState *env, uintptr_t ra,
242
}
243
break;
244
case MO_64:
245
- if (HAVE_al16) {
246
+ if (HAVE_ATOMIC128_RW) {
247
store_whole_le16(pv, 8, int128_make64(cpu_to_le64(val)));
248
return;
249
}
250
@@ -XXX,XX +XXX,XX @@ static void store_atom_16(CPUArchState *env, uintptr_t ra,
251
uint64_t a, b;
252
int atmax;
253
254
- if (HAVE_al16_fast && likely((pi & 15) == 0)) {
255
- store_atomic16(pv, val);
256
+ if (HAVE_ATOMIC128_RW && likely((pi & 15) == 0)) {
257
+ atomic16_set(pv, val);
56
return;
258
return;
57
}
259
}
58
+
260
59
+ start = addr & TARGET_PAGE_MASK;
261
@@ -XXX,XX +XXX,XX @@ static void store_atom_16(CPUArchState *env, uintptr_t ra,
60
+ end = start + TARGET_PAGE_SIZE;
262
}
61
pages = page_collection_lock(start, end);
263
break;
62
tb_invalidate_phys_page_range__locked(pages, p, start, end, 0);
264
case -MO_64:
63
page_collection_unlock(pages);
265
- if (HAVE_al16) {
64
diff --git a/cpu.c b/cpu.c
266
+ if (HAVE_ATOMIC128_RW) {
65
index XXXXXXX..XXXXXXX 100644
267
uint64_t val_le;
66
--- a/cpu.c
268
int s2 = pi & 15;
67
+++ b/cpu.c
269
int s1 = 16 - s2;
68
@@ -XXX,XX +XXX,XX @@ void list_cpus(const char *optarg)
270
@@ -XXX,XX +XXX,XX @@ static void store_atom_16(CPUArchState *env, uintptr_t ra,
69
void tb_invalidate_phys_addr(target_ulong addr)
271
}
70
{
272
break;
71
mmap_lock();
273
case MO_128:
72
- tb_invalidate_phys_page_range(addr, addr + 1);
274
- if (HAVE_al16) {
73
+ tb_invalidate_phys_page(addr);
275
- store_atomic16(pv, val);
74
mmap_unlock();
276
+ if (HAVE_ATOMIC128_RW) {
75
}
277
+ atomic16_set(pv, val);
76
#else
278
return;
77
@@ -XXX,XX +XXX,XX @@ void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs)
279
}
78
return;
280
break;
79
}
80
ram_addr = memory_region_get_ram_addr(mr) + addr;
81
- tb_invalidate_phys_page_range(ram_addr, ram_addr + 1);
82
+ tb_invalidate_phys_page(ram_addr);
83
}
84
#endif
85
86
--
281
--
87
2.34.1
282
2.34.1
88
283
89
284
diff view generated by jsdifflib
1
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
2
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
4
---
4
target/openrisc/cpu.c | 13 +++++++++++++
5
include/tcg/debug-assert.h | 17 +++++++++++++++++
5
target/openrisc/translate.c | 10 ----------
6
include/tcg/tcg.h | 9 +--------
6
2 files changed, 13 insertions(+), 10 deletions(-)
7
MAINTAINERS | 1 +
8
3 files changed, 19 insertions(+), 8 deletions(-)
9
create mode 100644 include/tcg/debug-assert.h
7
10
8
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
11
diff --git a/include/tcg/debug-assert.h b/include/tcg/debug-assert.h
12
new file mode 100644
13
index XXXXXXX..XXXXXXX
14
--- /dev/null
15
+++ b/include/tcg/debug-assert.h
16
@@ -XXX,XX +XXX,XX @@
17
+/* SPDX-License-Identifier: MIT */
18
+/*
19
+ * Define tcg_debug_assert
20
+ * Copyright (c) 2008 Fabrice Bellard
21
+ */
22
+
23
+#ifndef TCG_DEBUG_ASSERT_H
24
+#define TCG_DEBUG_ASSERT_H
25
+
26
+#if defined CONFIG_DEBUG_TCG || defined QEMU_STATIC_ANALYSIS
27
+# define tcg_debug_assert(X) do { assert(X); } while (0)
28
+#else
29
+# define tcg_debug_assert(X) \
30
+ do { if (!(X)) { __builtin_unreachable(); } } while (0)
31
+#endif
32
+
33
+#endif
34
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
9
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
10
--- a/target/openrisc/cpu.c
36
--- a/include/tcg/tcg.h
11
+++ b/target/openrisc/cpu.c
37
+++ b/include/tcg/tcg.h
12
@@ -XXX,XX +XXX,XX @@ static void openrisc_cpu_synchronize_from_tb(CPUState *cs,
38
@@ -XXX,XX +XXX,XX @@
13
cpu->env.pc = tb_pc(tb);
39
#include "tcg/tcg-mo.h"
14
}
40
#include "tcg-target.h"
15
41
#include "tcg/tcg-cond.h"
16
+static void openrisc_restore_state_to_opc(CPUState *cs,
42
+#include "tcg/debug-assert.h"
17
+ const TranslationBlock *tb,
43
18
+ const uint64_t *data)
44
/* XXX: make safe guess about sizes */
19
+{
45
#define MAX_OP_PER_INSTR 266
20
+ OpenRISCCPU *cpu = OPENRISC_CPU(cs);
46
@@ -XXX,XX +XXX,XX @@ typedef uint64_t tcg_insn_unit;
21
+
47
/* The port better have done this. */
22
+ cpu->env.pc = data[0];
48
#endif
23
+ cpu->env.dflag = data[1] & 1;
49
24
+ if (data[1] & 2) {
50
-
25
+ cpu->env.ppc = cpu->env.pc - 4;
51
-#if defined CONFIG_DEBUG_TCG || defined QEMU_STATIC_ANALYSIS
26
+ }
52
-# define tcg_debug_assert(X) do { assert(X); } while (0)
27
+}
53
-#else
28
54
-# define tcg_debug_assert(X) \
29
static bool openrisc_cpu_has_work(CPUState *cs)
55
- do { if (!(X)) { __builtin_unreachable(); } } while (0)
30
{
56
-#endif
31
@@ -XXX,XX +XXX,XX @@ static const struct SysemuCPUOps openrisc_sysemu_ops = {
57
-
32
static const struct TCGCPUOps openrisc_tcg_ops = {
58
typedef struct TCGRelocation TCGRelocation;
33
.initialize = openrisc_translate_init,
59
struct TCGRelocation {
34
.synchronize_from_tb = openrisc_cpu_synchronize_from_tb,
60
QSIMPLEQ_ENTRY(TCGRelocation) next;
35
+ .restore_state_to_opc = openrisc_restore_state_to_opc,
61
diff --git a/MAINTAINERS b/MAINTAINERS
36
37
#ifndef CONFIG_USER_ONLY
38
.tlb_fill = openrisc_cpu_tlb_fill,
39
diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
40
index XXXXXXX..XXXXXXX 100644
62
index XXXXXXX..XXXXXXX 100644
41
--- a/target/openrisc/translate.c
63
--- a/MAINTAINERS
42
+++ b/target/openrisc/translate.c
64
+++ b/MAINTAINERS
43
@@ -XXX,XX +XXX,XX @@ void openrisc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
65
@@ -XXX,XX +XXX,XX @@ F: include/sysemu/tcg.h
44
(i % 4) == 3 ? '\n' : ' ');
66
F: include/hw/core/tcg-cpu-ops.h
45
}
67
F: host/include/*/host/cpuinfo.h
46
}
68
F: util/cpuinfo-*.c
47
-
69
+F: include/tcg/
48
-void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb,
70
49
- target_ulong *data)
71
FPU emulation
50
-{
72
M: Aurelien Jarno <aurelien@aurel32.net>
51
- env->pc = data[0];
52
- env->dflag = data[1] & 1;
53
- if (data[1] & 2) {
54
- env->ppc = env->pc - 4;
55
- }
56
-}
57
--
73
--
58
2.34.1
74
2.34.1
59
75
60
76
diff view generated by jsdifflib
1
Use the existing function for clearing target data.
1
Use __sync_bool_compare_and_swap_16 to control the loop,
2
rather than a separate comparison.
2
3
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
---
6
---
6
accel/tcg/translate-all.c | 13 +++++--------
7
host/include/generic/host/atomic128-ldst.h | 11 +++++++----
7
1 file changed, 5 insertions(+), 8 deletions(-)
8
1 file changed, 7 insertions(+), 4 deletions(-)
8
9
9
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
10
diff --git a/host/include/generic/host/atomic128-ldst.h b/host/include/generic/host/atomic128-ldst.h
10
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
11
--- a/accel/tcg/translate-all.c
12
--- a/host/include/generic/host/atomic128-ldst.h
12
+++ b/accel/tcg/translate-all.c
13
+++ b/host/include/generic/host/atomic128-ldst.h
13
@@ -XXX,XX +XXX,XX @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
14
@@ -XXX,XX +XXX,XX @@ atomic16_read_rw(Int128 *ptr)
14
flags |= PAGE_WRITE_ORG;
15
static inline void ATTRIBUTE_ATOMIC128_OPT
15
}
16
atomic16_set(Int128 *ptr, Int128 val)
16
reset = !(flags & PAGE_VALID) || (flags & PAGE_RESET);
17
{
17
+ if (reset) {
18
- Int128 old = *ptr, cmp;
18
+ page_reset_target_data(start, end);
19
+ __int128_t *ptr_align = __builtin_assume_aligned(ptr, 16);
19
+ }
20
+ __int128_t old;
20
flags &= ~PAGE_RESET;
21
+ Int128Alias new;
21
22
+
22
for (addr = start, len = end - start;
23
+ new.s = val;
23
@@ -XXX,XX +XXX,XX @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
24
do {
24
(flags & ~p->flags & PAGE_WRITE))) {
25
- cmp = old;
25
tb_invalidate_phys_page(addr);
26
- old = atomic16_cmpxchg(ptr, cmp, val);
26
}
27
- } while (int128_ne(old, cmp));
27
- if (reset) {
28
+ old = *ptr_align;
28
- g_free(p->target_data);
29
+ } while (!__sync_bool_compare_and_swap_16(ptr_align, old, new.i));
29
- p->target_data = NULL;
30
- p->flags = flags;
31
- } else {
32
- /* Using mprotect on a page does not change sticky bits. */
33
- p->flags = (p->flags & PAGE_STICKY) | flags;
34
- }
35
+ /* Using mprotect on a page does not change sticky bits. */
36
+ p->flags = (reset ? 0 : p->flags & PAGE_STICKY) | flags;
37
}
38
}
30
}
39
31
32
#else
40
--
33
--
41
2.34.1
34
2.34.1
42
35
43
36
diff view generated by jsdifflib
1
Flush translation blocks in bulk, rather than page-by-page.
1
With FEAT_LSE2, load and store of int128 is directly supported.
2
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
---
5
---
6
accel/tcg/translate-all.c | 8 ++++++--
6
host/include/aarch64/host/atomic128-ldst.h | 53 ++++++++++++++++------
7
1 file changed, 6 insertions(+), 2 deletions(-)
7
1 file changed, 40 insertions(+), 13 deletions(-)
8
8
9
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
9
diff --git a/host/include/aarch64/host/atomic128-ldst.h b/host/include/aarch64/host/atomic128-ldst.h
10
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
11
--- a/accel/tcg/translate-all.c
11
--- a/host/include/aarch64/host/atomic128-ldst.h
12
+++ b/accel/tcg/translate-all.c
12
+++ b/host/include/aarch64/host/atomic128-ldst.h
13
@@ -XXX,XX +XXX,XX @@ int page_get_flags(target_ulong address)
13
@@ -XXX,XX +XXX,XX @@
14
void page_set_flags(target_ulong start, target_ulong end, int flags)
14
#ifndef AARCH64_ATOMIC128_LDST_H
15
#define AARCH64_ATOMIC128_LDST_H
16
17
+#include "host/cpuinfo.h"
18
+#include "tcg/debug-assert.h"
19
+
20
/*
21
* Through gcc 10, aarch64 has no support for 128-bit atomics.
22
* Through clang 16, without -march=armv8.4-a, __atomic_load_16
23
* is incorrectly expanded to a read-write operation.
24
+ *
25
+ * Anyway, this method allows runtime detection of FEAT_LSE2.
26
*/
27
28
-#define HAVE_ATOMIC128_RO 0
29
+#define HAVE_ATOMIC128_RO (cpuinfo & CPUINFO_LSE2)
30
#define HAVE_ATOMIC128_RW 1
31
32
-Int128 QEMU_ERROR("unsupported atomic") atomic16_read_ro(const Int128 *ptr);
33
+static inline Int128 atomic16_read_ro(const Int128 *ptr)
34
+{
35
+ uint64_t l, h;
36
+
37
+ tcg_debug_assert(HAVE_ATOMIC128_RO);
38
+ /* With FEAT_LSE2, 16-byte aligned LDP is atomic. */
39
+ asm("ldp %[l], %[h], %[mem]"
40
+ : [l] "=r"(l), [h] "=r"(h) : [mem] "m"(*ptr));
41
+
42
+ return int128_make128(l, h);
43
+}
44
45
static inline Int128 atomic16_read_rw(Int128 *ptr)
15
{
46
{
16
target_ulong addr, len;
47
uint64_t l, h;
17
- bool reset;
48
uint32_t tmp;
18
+ bool reset, inval_tb = false;
49
19
50
- /* The load must be paired with the store to guarantee not tearing. */
20
/* This function should never be called with addresses outside the
51
- asm("0: ldxp %[l], %[h], %[mem]\n\t"
21
guest address space. If this assert fires, it probably indicates
52
- "stxp %w[tmp], %[l], %[h], %[mem]\n\t"
22
@@ -XXX,XX +XXX,XX @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
53
- "cbnz %w[tmp], 0b"
23
&& (reset ||
54
- : [mem] "+m"(*ptr), [tmp] "=r"(tmp), [l] "=r"(l), [h] "=r"(h));
24
!(flags & PAGE_EXEC) ||
55
+ if (cpuinfo & CPUINFO_LSE2) {
25
(flags & ~p->flags & PAGE_WRITE))) {
56
+ /* With FEAT_LSE2, 16-byte aligned LDP is atomic. */
26
- tb_invalidate_phys_page(addr);
57
+ asm("ldp %[l], %[h], %[mem]"
27
+ inval_tb = true;
58
+ : [l] "=r"(l), [h] "=r"(h) : [mem] "m"(*ptr));
28
}
59
+ } else {
29
/* Using mprotect on a page does not change sticky bits. */
60
+ /* The load must be paired with the store to guarantee not tearing. */
30
p->flags = (reset ? 0 : p->flags & PAGE_STICKY) | flags;
61
+ asm("0: ldxp %[l], %[h], %[mem]\n\t"
31
}
62
+ "stxp %w[tmp], %[l], %[h], %[mem]\n\t"
32
+
63
+ "cbnz %w[tmp], 0b"
33
+ if (inval_tb) {
64
+ : [mem] "+m"(*ptr), [tmp] "=r"(tmp), [l] "=r"(l), [h] "=r"(h));
34
+ tb_invalidate_phys_range(start, end);
65
+ }
66
67
return int128_make128(l, h);
68
}
69
@@ -XXX,XX +XXX,XX @@ static inline void atomic16_set(Int128 *ptr, Int128 val)
70
uint64_t l = int128_getlo(val), h = int128_gethi(val);
71
uint64_t t1, t2;
72
73
- /* Load into temporaries to acquire the exclusive access lock. */
74
- asm("0: ldxp %[t1], %[t2], %[mem]\n\t"
75
- "stxp %w[t1], %[l], %[h], %[mem]\n\t"
76
- "cbnz %w[t1], 0b"
77
- : [mem] "+m"(*ptr), [t1] "=&r"(t1), [t2] "=&r"(t2)
78
- : [l] "r"(l), [h] "r"(h));
79
+ if (cpuinfo & CPUINFO_LSE2) {
80
+ /* With FEAT_LSE2, 16-byte aligned STP is atomic. */
81
+ asm("stp %[l], %[h], %[mem]"
82
+ : [mem] "=m"(*ptr) : [l] "r"(l), [h] "r"(h));
83
+ } else {
84
+ /* Load into temporaries to acquire the exclusive access lock. */
85
+ asm("0: ldxp %[t1], %[t2], %[mem]\n\t"
86
+ "stxp %w[t1], %[l], %[h], %[mem]\n\t"
87
+ "cbnz %w[t1], 0b"
88
+ : [mem] "+m"(*ptr), [t1] "=&r"(t1), [t2] "=&r"(t2)
89
+ : [l] "r"(l), [h] "r"(h));
35
+ }
90
+ }
36
}
91
}
37
92
38
void page_reset_target_data(target_ulong start, target_ulong end)
93
#endif /* AARCH64_ATOMIC128_LDST_H */
39
--
94
--
40
2.34.1
95
2.34.1
41
96
42
97
diff view generated by jsdifflib
1
This data structure will be replaced for user-only: add accessors.
1
This had been set since the beginning, is never undefined,
2
and it would seem to be harmful to debugging to do so.
2
3
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
---
6
---
6
include/exec/exec-all.h | 22 ++++++++++++++++++++++
7
include/exec/exec-all.h | 3 ---
7
accel/tcg/cpu-exec.c | 9 +++++----
8
accel/tcg/cpu-exec.c | 2 --
8
accel/tcg/tb-maint.c | 29 +++++++++++++++--------------
9
accel/tcg/translate-all.c | 2 --
9
accel/tcg/translate-all.c | 16 ++++++++--------
10
accel/tcg/translator.c | 2 --
10
accel/tcg/translator.c | 9 +++++----
11
target/sh4/translate.c | 2 --
11
5 files changed, 55 insertions(+), 30 deletions(-)
12
target/sparc/translate.c | 2 --
13
tcg/tcg.c | 9 +--------
14
7 files changed, 1 insertion(+), 21 deletions(-)
12
15
13
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
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/include/exec/exec-all.h
18
--- a/include/exec/exec-all.h
16
+++ b/include/exec/exec-all.h
19
+++ b/include/exec/exec-all.h
17
@@ -XXX,XX +XXX,XX @@ static inline uint32_t tb_cflags(const TranslationBlock *tb)
20
@@ -XXX,XX +XXX,XX @@
18
return qatomic_read(&tb->cflags);
21
#include "qemu/interval-tree.h"
19
}
22
#include "qemu/clang-tsa.h"
20
23
21
+static inline tb_page_addr_t tb_page_addr0(const TranslationBlock *tb)
24
-/* allow to see translation results - the slowdown should be negligible, so we leave it */
22
+{
25
-#define DEBUG_DISAS
23
+ return tb->page_addr[0];
26
-
24
+}
27
/* Page tracking code uses ram addresses in system mode, and virtual
25
+
28
addresses in userspace mode. Define tb_page_addr_t to be an appropriate
26
+static inline tb_page_addr_t tb_page_addr1(const TranslationBlock *tb)
29
type. */
27
+{
28
+ return tb->page_addr[1];
29
+}
30
+
31
+static inline void tb_set_page_addr0(TranslationBlock *tb,
32
+ tb_page_addr_t addr)
33
+{
34
+ tb->page_addr[0] = addr;
35
+}
36
+
37
+static inline void tb_set_page_addr1(TranslationBlock *tb,
38
+ tb_page_addr_t addr)
39
+{
40
+ tb->page_addr[1] = addr;
41
+}
42
+
43
/* current cflags for hashing/comparison */
44
uint32_t curr_cflags(CPUState *cpu);
45
46
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
30
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
47
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
48
--- a/accel/tcg/cpu-exec.c
32
--- a/accel/tcg/cpu-exec.c
49
+++ b/accel/tcg/cpu-exec.c
33
+++ b/accel/tcg/cpu-exec.c
50
@@ -XXX,XX +XXX,XX @@ static bool tb_lookup_cmp(const void *p, const void *d)
34
@@ -XXX,XX +XXX,XX @@ static void log_cpu_exec(target_ulong pc, CPUState *cpu,
51
const struct tb_desc *desc = d;
35
cpu->cpu_index, tb->tc.ptr, tb->cs_base, pc,
52
36
tb->flags, tb->cflags, lookup_symbol(pc));
53
if ((TARGET_TB_PCREL || tb_pc(tb) == desc->pc) &&
37
54
- tb->page_addr[0] == desc->page_addr0 &&
38
-#if defined(DEBUG_DISAS)
55
+ tb_page_addr0(tb) == desc->page_addr0 &&
39
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
56
tb->cs_base == desc->cs_base &&
40
FILE *logfile = qemu_log_trylock();
57
tb->flags == desc->flags &&
41
if (logfile) {
58
tb->trace_vcpu_dstate == desc->trace_vcpu_dstate &&
42
@@ -XXX,XX +XXX,XX @@ static void log_cpu_exec(target_ulong pc, CPUState *cpu,
59
tb_cflags(tb) == desc->cflags) {
43
qemu_log_unlock(logfile);
60
/* check next page if needed */
61
- if (tb->page_addr[1] == -1) {
62
+ tb_page_addr_t tb_phys_page1 = tb_page_addr1(tb);
63
+ if (tb_phys_page1 == -1) {
64
return true;
65
} else {
66
tb_page_addr_t phys_page1;
67
@@ -XXX,XX +XXX,XX @@ static bool tb_lookup_cmp(const void *p, const void *d)
68
*/
69
virt_page1 = TARGET_PAGE_ALIGN(desc->pc);
70
phys_page1 = get_page_addr_code(desc->env, virt_page1);
71
- if (tb->page_addr[1] == phys_page1) {
72
+ if (tb_phys_page1 == phys_page1) {
73
return true;
74
}
44
}
75
}
45
}
76
@@ -XXX,XX +XXX,XX @@ int cpu_exec(CPUState *cpu)
46
-#endif /* DEBUG_DISAS */
77
* direct jump to a TB spanning two pages because the mapping
47
}
78
* for the second page can change.
79
*/
80
- if (tb->page_addr[1] != -1) {
81
+ if (tb_page_addr1(tb) != -1) {
82
last_tb = NULL;
83
}
84
#endif
85
diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/accel/tcg/tb-maint.c
88
+++ b/accel/tcg/tb-maint.c
89
@@ -XXX,XX +XXX,XX @@ static bool tb_cmp(const void *ap, const void *bp)
90
a->flags == b->flags &&
91
(tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) &&
92
a->trace_vcpu_dstate == b->trace_vcpu_dstate &&
93
- a->page_addr[0] == b->page_addr[0] &&
94
- a->page_addr[1] == b->page_addr[1]);
95
+ tb_page_addr0(a) == tb_page_addr0(b) &&
96
+ tb_page_addr1(a) == tb_page_addr1(b));
97
}
48
}
98
49
99
void tb_htable_init(void)
100
@@ -XXX,XX +XXX,XX @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
101
qemu_spin_unlock(&tb->jmp_lock);
102
103
/* remove the TB from the hash list */
104
- phys_pc = tb->page_addr[0];
105
+ phys_pc = tb_page_addr0(tb);
106
h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : tb_pc(tb)),
107
tb->flags, orig_cflags, tb->trace_vcpu_dstate);
108
if (!qht_remove(&tb_ctx.htable, tb, h)) {
109
@@ -XXX,XX +XXX,XX @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
110
111
/* remove the TB from the page list */
112
if (rm_from_page_list) {
113
- p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
114
+ p = page_find(phys_pc >> TARGET_PAGE_BITS);
115
tb_page_remove(p, tb);
116
- if (tb->page_addr[1] != -1) {
117
- p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
118
+ phys_pc = tb_page_addr1(tb);
119
+ if (phys_pc != -1) {
120
+ p = page_find(phys_pc >> TARGET_PAGE_BITS);
121
tb_page_remove(p, tb);
122
}
123
}
124
@@ -XXX,XX +XXX,XX @@ static inline void page_unlock_tb(const TranslationBlock *tb) { }
125
/* lock the page(s) of a TB in the correct acquisition order */
126
static void page_lock_tb(const TranslationBlock *tb)
127
{
128
- page_lock_pair(NULL, tb->page_addr[0], NULL, tb->page_addr[1], false);
129
+ page_lock_pair(NULL, tb_page_addr0(tb), NULL, tb_page_addr1(tb), false);
130
}
131
132
static void page_unlock_tb(const TranslationBlock *tb)
133
{
134
- PageDesc *p1 = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
135
+ PageDesc *p1 = page_find(tb_page_addr0(tb) >> TARGET_PAGE_BITS);
136
137
page_unlock(p1);
138
- if (unlikely(tb->page_addr[1] != -1)) {
139
- PageDesc *p2 = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
140
+ if (unlikely(tb_page_addr1(tb) != -1)) {
141
+ PageDesc *p2 = page_find(tb_page_addr1(tb) >> TARGET_PAGE_BITS);
142
143
if (p2 != p1) {
144
page_unlock(p2);
145
@@ -XXX,XX +XXX,XX @@ static void page_unlock_tb(const TranslationBlock *tb)
146
*/
147
void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
148
{
149
- if (page_addr == -1 && tb->page_addr[0] != -1) {
150
+ if (page_addr == -1 && tb_page_addr0(tb) != -1) {
151
page_lock_tb(tb);
152
do_tb_phys_invalidate(tb, true);
153
page_unlock_tb(tb);
154
@@ -XXX,XX +XXX,XX @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
155
if (n == 0) {
156
/* NOTE: tb_end may be after the end of the page, but
157
it is not a problem */
158
- tb_start = tb->page_addr[0];
159
+ tb_start = tb_page_addr0(tb);
160
tb_end = tb_start + tb->size;
161
} else {
162
- tb_start = tb->page_addr[1];
163
- tb_end = tb_start + ((tb->page_addr[0] + tb->size)
164
+ tb_start = tb_page_addr1(tb);
165
+ tb_end = tb_start + ((tb_page_addr0(tb) + tb->size)
166
& ~TARGET_PAGE_MASK);
167
}
168
if (!(tb_end <= start || tb_start >= end)) {
169
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
50
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
170
index XXXXXXX..XXXXXXX 100644
51
index XXXXXXX..XXXXXXX 100644
171
--- a/accel/tcg/translate-all.c
52
--- a/accel/tcg/translate-all.c
172
+++ b/accel/tcg/translate-all.c
53
+++ b/accel/tcg/translate-all.c
173
@@ -XXX,XX +XXX,XX @@ page_collection_lock(tb_page_addr_t start, tb_page_addr_t end)
54
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
55
qatomic_set(&prof->search_out_len, prof->search_out_len + search_size);
56
#endif
57
58
-#ifdef DEBUG_DISAS
59
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM) &&
60
qemu_log_in_addr_range(pc)) {
61
FILE *logfile = qemu_log_trylock();
62
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
63
qemu_log_unlock(logfile);
174
}
64
}
175
assert_page_locked(pd);
176
PAGE_FOR_EACH_TB(pd, tb, n) {
177
- if (page_trylock_add(set, tb->page_addr[0]) ||
178
- (tb->page_addr[1] != -1 &&
179
- page_trylock_add(set, tb->page_addr[1]))) {
180
+ if (page_trylock_add(set, tb_page_addr0(tb)) ||
181
+ (tb_page_addr1(tb) != -1 &&
182
+ page_trylock_add(set, tb_page_addr1(tb)))) {
183
/* drop all locks, and reacquire in order */
184
g_tree_foreach(set->tree, page_entry_unlock, NULL);
185
goto retry;
186
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
187
tb->flags = flags;
188
tb->cflags = cflags;
189
tb->trace_vcpu_dstate = *cpu->trace_dstate;
190
- tb->page_addr[0] = phys_pc;
191
- tb->page_addr[1] = -1;
192
+ tb_set_page_addr0(tb, phys_pc);
193
+ tb_set_page_addr1(tb, -1);
194
tcg_ctx->tb_cflags = cflags;
195
tb_overflow:
196
197
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
198
* a temporary one-insn TB, and we have nothing left to do. Return early
199
* before attempting to link to other TBs or add to the lookup table.
200
*/
201
- if (tb->page_addr[0] == -1) {
202
+ if (tb_page_addr0(tb) == -1) {
203
return tb;
204
}
65
}
205
66
-#endif
206
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
67
207
* No explicit memory barrier is required -- tb_link_page() makes the
68
qatomic_set(&tcg_ctx->code_gen_ptr, (void *)
208
* TB visible in a consistent state.
69
ROUND_UP((uintptr_t)gen_code_buf + gen_code_size + search_size,
209
*/
210
- existing_tb = tb_link_page(tb, tb->page_addr[0], tb->page_addr[1]);
211
+ existing_tb = tb_link_page(tb, tb_page_addr0(tb), tb_page_addr1(tb));
212
/* if the TB already exists, discard what we just translated */
213
if (unlikely(existing_tb != tb)) {
214
uintptr_t orig_aligned = (uintptr_t)gen_code_buf;
215
@@ -XXX,XX +XXX,XX @@ static gboolean tb_tree_stats_iter(gpointer key, gpointer value, gpointer data)
216
if (tb->size > tst->max_target_size) {
217
tst->max_target_size = tb->size;
218
}
219
- if (tb->page_addr[1] != -1) {
220
+ if (tb_page_addr1(tb) != -1) {
221
tst->cross_page++;
222
}
223
if (tb->jmp_reset_offset[0] != TB_JMP_RESET_OFFSET_INVALID) {
224
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
70
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
225
index XXXXXXX..XXXXXXX 100644
71
index XXXXXXX..XXXXXXX 100644
226
--- a/accel/tcg/translator.c
72
--- a/accel/tcg/translator.c
227
+++ b/accel/tcg/translator.c
73
+++ b/accel/tcg/translator.c
228
@@ -XXX,XX +XXX,XX @@ static void *translator_access(CPUArchState *env, DisasContextBase *db,
74
@@ -XXX,XX +XXX,XX @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
229
tb = db->tb;
75
tb->size = db->pc_next - db->pc_first;
230
76
tb->icount = db->num_insns;
231
/* Use slow path if first page is MMIO. */
77
232
- if (unlikely(tb->page_addr[0] == -1)) {
78
-#ifdef DEBUG_DISAS
233
+ if (unlikely(tb_page_addr0(tb) == -1)) {
79
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
234
return NULL;
80
&& qemu_log_in_addr_range(db->pc_first)) {
81
FILE *logfile = qemu_log_trylock();
82
@@ -XXX,XX +XXX,XX @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
83
qemu_log_unlock(logfile);
84
}
235
}
85
}
236
86
-#endif
237
@@ -XXX,XX +XXX,XX @@ static void *translator_access(CPUArchState *env, DisasContextBase *db,
87
}
238
host = db->host_addr[1];
88
239
base = TARGET_PAGE_ALIGN(db->pc_first);
89
static void *translator_access(CPUArchState *env, DisasContextBase *db,
240
if (host == NULL) {
90
diff --git a/target/sh4/translate.c b/target/sh4/translate.c
241
- tb->page_addr[1] =
91
index XXXXXXX..XXXXXXX 100644
242
+ tb_page_addr_t phys_page =
92
--- a/target/sh4/translate.c
243
get_page_addr_code_hostp(env, base, &db->host_addr[1]);
93
+++ b/target/sh4/translate.c
244
+ /* We cannot handle MMIO as second page. */
94
@@ -XXX,XX +XXX,XX @@
245
+ assert(phys_page != -1);
95
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
246
+ tb_set_page_addr1(tb, phys_page);
96
*/
247
#ifdef CONFIG_USER_ONLY
97
248
page_protect(end);
98
-#define DEBUG_DISAS
99
-
100
#include "qemu/osdep.h"
101
#include "cpu.h"
102
#include "disas/disas.h"
103
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/target/sparc/translate.c
106
+++ b/target/sparc/translate.c
107
@@ -XXX,XX +XXX,XX @@
108
#include "asi.h"
109
110
111
-#define DEBUG_DISAS
112
-
113
#define DYNAMIC_PC 1 /* dynamic pc value */
114
#define JUMP_PC 2 /* dynamic pc value which takes only two values
115
according to jump_pc[T2] */
116
diff --git a/tcg/tcg.c b/tcg/tcg.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/tcg/tcg.c
119
+++ b/tcg/tcg.c
120
@@ -XXX,XX +XXX,XX @@ void tcg_prologue_init(TCGContext *s)
121
(uintptr_t)s->code_buf, prologue_size);
249
#endif
122
#endif
250
- /* We cannot handle MMIO as second page. */
123
251
- assert(tb->page_addr[1] != -1);
124
-#ifdef DEBUG_DISAS
252
host = db->host_addr[1];
125
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
126
FILE *logfile = qemu_log_trylock();
127
if (logfile) {
128
@@ -XXX,XX +XXX,XX @@ void tcg_prologue_init(TCGContext *s)
129
qemu_log_unlock(logfile);
253
}
130
}
254
131
}
132
-#endif
133
134
#ifndef CONFIG_TCG_INTERPRETER
135
/*
136
@@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
137
}
138
#endif
139
140
-#ifdef DEBUG_DISAS
141
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)
142
&& qemu_log_in_addr_range(pc_start))) {
143
FILE *logfile = qemu_log_trylock();
144
@@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
145
qemu_log_unlock(logfile);
146
}
147
}
148
-#endif
149
150
#ifdef CONFIG_DEBUG_TCG
151
/* Ensure all labels referenced have been emitted. */
152
@@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
153
liveness_pass_1(s);
154
155
if (s->nb_indirects > 0) {
156
-#ifdef DEBUG_DISAS
157
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_IND)
158
&& qemu_log_in_addr_range(pc_start))) {
159
FILE *logfile = qemu_log_trylock();
160
@@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
161
qemu_log_unlock(logfile);
162
}
163
}
164
-#endif
165
+
166
/* Replace indirect temps with direct temps. */
167
if (liveness_pass_2(s)) {
168
/* If changes were made, re-run liveness. */
169
@@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
170
qatomic_set(&prof->la_time, prof->la_time + profile_getclock());
171
#endif
172
173
-#ifdef DEBUG_DISAS
174
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT)
175
&& qemu_log_in_addr_range(pc_start))) {
176
FILE *logfile = qemu_log_trylock();
177
@@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
178
qemu_log_unlock(logfile);
179
}
180
}
181
-#endif
182
183
/* Initialize goto_tb jump offsets. */
184
tb->jmp_reset_offset[0] = TB_JMP_OFFSET_INVALID;
255
--
185
--
256
2.34.1
186
2.34.1
257
187
258
188
diff view generated by jsdifflib
1
This differs from assert, in that with optimization enabled it
1
This is always defined, and the optimization pass is
2
triggers at build-time. It differs from QEMU_BUILD_BUG_ON,
2
essential to producing reasonable code.
3
aka _Static_assert, in that it is sensitive to control flow
4
and is subject to dead-code elimination.
5
3
6
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
6
---
10
include/qemu/osdep.h | 8 ++++++++
7
tcg/tcg.c | 5 -----
11
1 file changed, 8 insertions(+)
8
1 file changed, 5 deletions(-)
12
9
13
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
10
diff --git a/tcg/tcg.c b/tcg/tcg.c
14
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
15
--- a/include/qemu/osdep.h
12
--- a/tcg/tcg.c
16
+++ b/include/qemu/osdep.h
13
+++ b/tcg/tcg.c
17
@@ -XXX,XX +XXX,XX @@ void QEMU_ERROR("code path is reachable")
14
@@ -XXX,XX +XXX,XX @@
18
#define qemu_build_not_reached() g_assert_not_reached()
15
* THE SOFTWARE.
16
*/
17
18
-/* define it to use liveness analysis (better code) */
19
-#define USE_TCG_OPTIMIZATIONS
20
-
21
#include "qemu/osdep.h"
22
23
/* Define to jump the ELF file used to communicate with GDB. */
24
@@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
25
qatomic_set(&prof->opt_time, prof->opt_time - profile_getclock());
19
#endif
26
#endif
20
27
21
+/**
28
-#ifdef USE_TCG_OPTIMIZATIONS
22
+ * qemu_build_assert()
29
tcg_optimize(s);
23
+ *
30
-#endif
24
+ * The compiler, during optimization, is expected to prove that the
31
25
+ * assertion is true.
32
#ifdef CONFIG_PROFILER
26
+ */
33
qatomic_set(&prof->opt_time, prof->opt_time + profile_getclock());
27
+#define qemu_build_assert(test) while (!(test)) qemu_build_not_reached()
28
+
29
/*
30
* According to waitpid man page:
31
* WCOREDUMP
32
--
34
--
33
2.34.1
35
2.34.1
34
36
35
37
diff view generated by jsdifflib
Deleted patch
1
Change from QEMU_BUILD_BUG_ON, which requires ifdefs to avoid
2
problematic code, to qemu_build_assert, which can use C ifs.
3
1
4
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
include/qemu/atomic.h | 16 ++++++++--------
9
1 file changed, 8 insertions(+), 8 deletions(-)
10
11
diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h
12
index XXXXXXX..XXXXXXX 100644
13
--- a/include/qemu/atomic.h
14
+++ b/include/qemu/atomic.h
15
@@ -XXX,XX +XXX,XX @@
16
17
#define qatomic_read(ptr) \
18
({ \
19
- QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \
20
+ qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
21
qatomic_read__nocheck(ptr); \
22
})
23
24
@@ -XXX,XX +XXX,XX @@
25
__atomic_store_n(ptr, i, __ATOMIC_RELAXED)
26
27
#define qatomic_set(ptr, i) do { \
28
- QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \
29
+ qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
30
qatomic_set__nocheck(ptr, i); \
31
} while(0)
32
33
@@ -XXX,XX +XXX,XX @@
34
35
#define qatomic_rcu_read(ptr) \
36
({ \
37
- QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \
38
+ qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
39
typeof_strip_qual(*ptr) _val; \
40
qatomic_rcu_read__nocheck(ptr, &_val); \
41
_val; \
42
})
43
44
#define qatomic_rcu_set(ptr, i) do { \
45
- QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \
46
+ qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
47
__atomic_store_n(ptr, i, __ATOMIC_RELEASE); \
48
} while(0)
49
50
#define qatomic_load_acquire(ptr) \
51
({ \
52
- QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \
53
+ qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
54
typeof_strip_qual(*ptr) _val; \
55
__atomic_load(ptr, &_val, __ATOMIC_ACQUIRE); \
56
_val; \
57
})
58
59
#define qatomic_store_release(ptr, i) do { \
60
- QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \
61
+ qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
62
__atomic_store_n(ptr, i, __ATOMIC_RELEASE); \
63
} while(0)
64
65
@@ -XXX,XX +XXX,XX @@
66
})
67
68
#define qatomic_xchg(ptr, i) ({ \
69
- QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \
70
+ qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
71
qatomic_xchg__nocheck(ptr, i); \
72
})
73
74
@@ -XXX,XX +XXX,XX @@
75
})
76
77
#define qatomic_cmpxchg(ptr, old, new) ({ \
78
- QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \
79
+ qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
80
qatomic_cmpxchg__nocheck(ptr, old, new); \
81
})
82
83
--
84
2.34.1
85
86
diff view generated by jsdifflib
Deleted patch
1
Use qatomic_*, which expands to __atomic_* in preference
2
to the "legacy" __sync_* functions.
3
1
4
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
include/qemu/thread.h | 8 ++++----
8
1 file changed, 4 insertions(+), 4 deletions(-)
9
10
diff --git a/include/qemu/thread.h b/include/qemu/thread.h
11
index XXXXXXX..XXXXXXX 100644
12
--- a/include/qemu/thread.h
13
+++ b/include/qemu/thread.h
14
@@ -XXX,XX +XXX,XX @@ struct QemuSpin {
15
16
static inline void qemu_spin_init(QemuSpin *spin)
17
{
18
- __sync_lock_release(&spin->value);
19
+ qatomic_set(&spin->value, 0);
20
#ifdef CONFIG_TSAN
21
__tsan_mutex_create(spin, __tsan_mutex_not_static);
22
#endif
23
@@ -XXX,XX +XXX,XX @@ static inline void qemu_spin_lock(QemuSpin *spin)
24
#ifdef CONFIG_TSAN
25
__tsan_mutex_pre_lock(spin, 0);
26
#endif
27
- while (unlikely(__sync_lock_test_and_set(&spin->value, true))) {
28
+ while (unlikely(qatomic_xchg(&spin->value, 1))) {
29
while (qatomic_read(&spin->value)) {
30
cpu_relax();
31
}
32
@@ -XXX,XX +XXX,XX @@ static inline bool qemu_spin_trylock(QemuSpin *spin)
33
#ifdef CONFIG_TSAN
34
__tsan_mutex_pre_lock(spin, __tsan_mutex_try_lock);
35
#endif
36
- bool busy = __sync_lock_test_and_set(&spin->value, true);
37
+ bool busy = qatomic_xchg(&spin->value, true);
38
#ifdef CONFIG_TSAN
39
unsigned flags = __tsan_mutex_try_lock;
40
flags |= busy ? __tsan_mutex_try_lock_failed : 0;
41
@@ -XXX,XX +XXX,XX @@ static inline void qemu_spin_unlock(QemuSpin *spin)
42
#ifdef CONFIG_TSAN
43
__tsan_mutex_pre_unlock(spin, 0);
44
#endif
45
- __sync_lock_release(&spin->value);
46
+ qatomic_store_release(&spin->value, 0);
47
#ifdef CONFIG_TSAN
48
__tsan_mutex_post_unlock(spin, 0);
49
#endif
50
--
51
2.34.1
diff view generated by jsdifflib
Deleted patch
1
When we added the fast path, we initialized page_addr[] early.
2
These stores in and around tb_page_add() are redundant; remove them.
3
1
4
Fixes: 50627f1b7b1 ("accel/tcg: Add fast path for translator_ld*")
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
accel/tcg/tb-maint.c | 3 ---
9
1 file changed, 3 deletions(-)
10
11
diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/accel/tcg/tb-maint.c
14
+++ b/accel/tcg/tb-maint.c
15
@@ -XXX,XX +XXX,XX @@ static inline void tb_page_add(PageDesc *p, TranslationBlock *tb,
16
17
assert_page_locked(p);
18
19
- tb->page_addr[n] = page_addr;
20
tb->page_next[n] = p->first_tb;
21
#ifndef CONFIG_USER_ONLY
22
page_already_protected = p->first_tb != (uintptr_t)NULL;
23
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
24
tb_page_add(p, tb, 0, phys_pc);
25
if (p2) {
26
tb_page_add(p2, tb, 1, phys_page2);
27
- } else {
28
- tb->page_addr[1] = -1;
29
}
30
31
/* add in the hash table */
32
--
33
2.34.1
34
35
diff view generated by jsdifflib
Deleted patch
1
Add a tcg_ops hook to replace the restore_state_to_opc
2
function call. Because these generic hooks cannot depend
3
on target-specific types, temporarily, copy the current
4
target_ulong data[] into uint64_t d64[].
5
1
6
Reviewed-by: Claudio Fontana <cfontana@suse.de>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
include/exec/exec-all.h | 2 +-
10
include/hw/core/tcg-cpu-ops.h | 11 +++++++++++
11
accel/tcg/translate-all.c | 24 ++++++++++++++++++++++--
12
3 files changed, 34 insertions(+), 3 deletions(-)
13
14
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/exec/exec-all.h
17
+++ b/include/exec/exec-all.h
18
@@ -XXX,XX +XXX,XX @@ typedef ram_addr_t tb_page_addr_t;
19
#endif
20
21
void restore_state_to_opc(CPUArchState *env, TranslationBlock *tb,
22
- target_ulong *data);
23
+ target_ulong *data) __attribute__((weak));
24
25
/**
26
* cpu_restore_state:
27
diff --git a/include/hw/core/tcg-cpu-ops.h b/include/hw/core/tcg-cpu-ops.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/hw/core/tcg-cpu-ops.h
30
+++ b/include/hw/core/tcg-cpu-ops.h
31
@@ -XXX,XX +XXX,XX @@ struct TCGCPUOps {
32
* function to restore all the state, and register it here.
33
*/
34
void (*synchronize_from_tb)(CPUState *cpu, const TranslationBlock *tb);
35
+ /**
36
+ * @restore_state_to_opc: Synchronize state from INDEX_op_start_insn
37
+ *
38
+ * This is called when we unwind state in the middle of a TB,
39
+ * usually before raising an exception. Set all part of the CPU
40
+ * state which are tracked insn-by-insn in the target-specific
41
+ * arguments to start_insn, passed as @data.
42
+ */
43
+ void (*restore_state_to_opc)(CPUState *cpu, const TranslationBlock *tb,
44
+ const uint64_t *data);
45
+
46
/** @cpu_exec_enter: Callback for cpu_exec preparation */
47
void (*cpu_exec_enter)(CPUState *cpu);
48
/** @cpu_exec_exit: Callback for cpu_exec cleanup */
49
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/accel/tcg/translate-all.c
52
+++ b/accel/tcg/translate-all.c
53
@@ -XXX,XX +XXX,XX @@ int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
54
{
55
target_ulong data[TARGET_INSN_START_WORDS];
56
uintptr_t host_pc = (uintptr_t)tb->tc.ptr;
57
- CPUArchState *env = cpu->env_ptr;
58
const uint8_t *p = tb->tc.ptr + tb->tc.size;
59
int i, j, num_insns = tb->icount;
60
#ifdef CONFIG_PROFILER
61
@@ -XXX,XX +XXX,XX @@ int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
62
and shift if to the number of actually executed instructions */
63
cpu_neg(cpu)->icount_decr.u16.low += num_insns - i;
64
}
65
- restore_state_to_opc(env, tb, data);
66
+
67
+ {
68
+ const struct TCGCPUOps *ops = cpu->cc->tcg_ops;
69
+ __typeof(ops->restore_state_to_opc) restore = ops->restore_state_to_opc;
70
+ if (restore) {
71
+ uint64_t d64[TARGET_INSN_START_WORDS];
72
+ for (i = 0; i < TARGET_INSN_START_WORDS; ++i) {
73
+ d64[i] = data[i];
74
+ }
75
+ restore(cpu, tb, d64);
76
+ } else {
77
+ restore_state_to_opc(cpu->env_ptr, tb, data);
78
+ }
79
+ }
80
81
#ifdef CONFIG_PROFILER
82
qatomic_set(&prof->restore_time,
83
@@ -XXX,XX +XXX,XX @@ int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
84
85
bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit)
86
{
87
+ /*
88
+ * The pc update associated with restore without exit will
89
+ * break the relative pc adjustments performed by TARGET_TB_PCREL.
90
+ */
91
+ if (TARGET_TB_PCREL) {
92
+ assert(will_exit);
93
+ }
94
+
95
/*
96
* The host_pc has to be in the rx region of the code buffer.
97
* If it is not we will not be able to resolve it here.
98
--
99
2.34.1
diff view generated by jsdifflib
Deleted patch
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
4
target/alpha/cpu.c | 9 +++++++++
5
target/alpha/translate.c | 6 ------
6
2 files changed, 9 insertions(+), 6 deletions(-)
7
1
8
diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
9
index XXXXXXX..XXXXXXX 100644
10
--- a/target/alpha/cpu.c
11
+++ b/target/alpha/cpu.c
12
@@ -XXX,XX +XXX,XX @@ static vaddr alpha_cpu_get_pc(CPUState *cs)
13
return cpu->env.pc;
14
}
15
16
+static void alpha_restore_state_to_opc(CPUState *cs,
17
+ const TranslationBlock *tb,
18
+ const uint64_t *data)
19
+{
20
+ AlphaCPU *cpu = ALPHA_CPU(cs);
21
+
22
+ cpu->env.pc = data[0];
23
+}
24
25
static bool alpha_cpu_has_work(CPUState *cs)
26
{
27
@@ -XXX,XX +XXX,XX @@ static const struct SysemuCPUOps alpha_sysemu_ops = {
28
29
static const struct TCGCPUOps alpha_tcg_ops = {
30
.initialize = alpha_translate_init,
31
+ .restore_state_to_opc = alpha_restore_state_to_opc,
32
33
#ifdef CONFIG_USER_ONLY
34
.record_sigsegv = alpha_cpu_record_sigsegv,
35
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/alpha/translate.c
38
+++ b/target/alpha/translate.c
39
@@ -XXX,XX +XXX,XX @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
40
DisasContext dc;
41
translator_loop(cpu, tb, max_insns, pc, host_pc, &alpha_tr_ops, &dc.base);
42
}
43
-
44
-void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb,
45
- target_ulong *data)
46
-{
47
- env->pc = data[0];
48
-}
49
--
50
2.34.1
51
52
diff view generated by jsdifflib
Deleted patch
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
4
target/arm/cpu.c | 26 ++++++++++++++++++++++++++
5
target/arm/translate.c | 22 ----------------------
6
2 files changed, 26 insertions(+), 22 deletions(-)
7
1
8
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
9
index XXXXXXX..XXXXXXX 100644
10
--- a/target/arm/cpu.c
11
+++ b/target/arm/cpu.c
12
@@ -XXX,XX +XXX,XX @@ void arm_cpu_synchronize_from_tb(CPUState *cs,
13
}
14
}
15
}
16
+
17
+static void arm_restore_state_to_opc(CPUState *cs,
18
+ const TranslationBlock *tb,
19
+ const uint64_t *data)
20
+{
21
+ CPUARMState *env = cs->env_ptr;
22
+
23
+ if (is_a64(env)) {
24
+ if (TARGET_TB_PCREL) {
25
+ env->pc = (env->pc & TARGET_PAGE_MASK) | data[0];
26
+ } else {
27
+ env->pc = data[0];
28
+ }
29
+ env->condexec_bits = 0;
30
+ env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
31
+ } else {
32
+ if (TARGET_TB_PCREL) {
33
+ env->regs[15] = (env->regs[15] & TARGET_PAGE_MASK) | data[0];
34
+ } else {
35
+ env->regs[15] = data[0];
36
+ }
37
+ env->condexec_bits = data[1];
38
+ env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
39
+ }
40
+}
41
#endif /* CONFIG_TCG */
42
43
static bool arm_cpu_has_work(CPUState *cs)
44
@@ -XXX,XX +XXX,XX @@ static const struct TCGCPUOps arm_tcg_ops = {
45
.initialize = arm_translate_init,
46
.synchronize_from_tb = arm_cpu_synchronize_from_tb,
47
.debug_excp_handler = arm_debug_excp_handler,
48
+ .restore_state_to_opc = arm_restore_state_to_opc,
49
50
#ifdef CONFIG_USER_ONLY
51
.record_sigsegv = arm_cpu_record_sigsegv,
52
diff --git a/target/arm/translate.c b/target/arm/translate.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/translate.c
55
+++ b/target/arm/translate.c
56
@@ -XXX,XX +XXX,XX @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
57
58
translator_loop(cpu, tb, max_insns, pc, host_pc, ops, &dc.base);
59
}
60
-
61
-void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
62
- target_ulong *data)
63
-{
64
- if (is_a64(env)) {
65
- if (TARGET_TB_PCREL) {
66
- env->pc = (env->pc & TARGET_PAGE_MASK) | data[0];
67
- } else {
68
- env->pc = data[0];
69
- }
70
- env->condexec_bits = 0;
71
- env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
72
- } else {
73
- if (TARGET_TB_PCREL) {
74
- env->regs[15] = (env->regs[15] & TARGET_PAGE_MASK) | data[0];
75
- } else {
76
- env->regs[15] = data[0];
77
- }
78
- env->condexec_bits = data[1];
79
- env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
80
- }
81
-}
82
--
83
2.34.1
84
85
diff view generated by jsdifflib
Deleted patch
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
4
target/avr/cpu.c | 11 +++++++++++
5
target/avr/translate.c | 6 ------
6
2 files changed, 11 insertions(+), 6 deletions(-)
7
1
8
diff --git a/target/avr/cpu.c b/target/avr/cpu.c
9
index XXXXXXX..XXXXXXX 100644
10
--- a/target/avr/cpu.c
11
+++ b/target/avr/cpu.c
12
@@ -XXX,XX +XXX,XX @@ static void avr_cpu_synchronize_from_tb(CPUState *cs,
13
env->pc_w = tb_pc(tb) / 2; /* internally PC points to words */
14
}
15
16
+static void avr_restore_state_to_opc(CPUState *cs,
17
+ const TranslationBlock *tb,
18
+ const uint64_t *data)
19
+{
20
+ AVRCPU *cpu = AVR_CPU(cs);
21
+ CPUAVRState *env = &cpu->env;
22
+
23
+ env->pc_w = data[0];
24
+}
25
+
26
static void avr_cpu_reset(DeviceState *ds)
27
{
28
CPUState *cs = CPU(ds);
29
@@ -XXX,XX +XXX,XX @@ static const struct SysemuCPUOps avr_sysemu_ops = {
30
static const struct TCGCPUOps avr_tcg_ops = {
31
.initialize = avr_cpu_tcg_init,
32
.synchronize_from_tb = avr_cpu_synchronize_from_tb,
33
+ .restore_state_to_opc = avr_restore_state_to_opc,
34
.cpu_exec_interrupt = avr_cpu_exec_interrupt,
35
.tlb_fill = avr_cpu_tlb_fill,
36
.do_interrupt = avr_cpu_do_interrupt,
37
diff --git a/target/avr/translate.c b/target/avr/translate.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/avr/translate.c
40
+++ b/target/avr/translate.c
41
@@ -XXX,XX +XXX,XX @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
42
DisasContext dc = { };
43
translator_loop(cs, tb, max_insns, pc, host_pc, &avr_tr_ops, &dc.base);
44
}
45
-
46
-void restore_state_to_opc(CPUAVRState *env, TranslationBlock *tb,
47
- target_ulong *data)
48
-{
49
- env->pc_w = data[0];
50
-}
51
--
52
2.34.1
53
54
diff view generated by jsdifflib
Deleted patch
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
4
target/cris/cpu.c | 11 +++++++++++
5
target/cris/translate.c | 6 ------
6
2 files changed, 11 insertions(+), 6 deletions(-)
7
1
8
diff --git a/target/cris/cpu.c b/target/cris/cpu.c
9
index XXXXXXX..XXXXXXX 100644
10
--- a/target/cris/cpu.c
11
+++ b/target/cris/cpu.c
12
@@ -XXX,XX +XXX,XX @@ static vaddr cris_cpu_get_pc(CPUState *cs)
13
return cpu->env.pc;
14
}
15
16
+static void cris_restore_state_to_opc(CPUState *cs,
17
+ const TranslationBlock *tb,
18
+ const uint64_t *data)
19
+{
20
+ CRISCPU *cpu = CRIS_CPU(cs);
21
+
22
+ cpu->env.pc = data[0];
23
+}
24
+
25
static bool cris_cpu_has_work(CPUState *cs)
26
{
27
return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
28
@@ -XXX,XX +XXX,XX @@ static const struct SysemuCPUOps cris_sysemu_ops = {
29
30
static const struct TCGCPUOps crisv10_tcg_ops = {
31
.initialize = cris_initialize_crisv10_tcg,
32
+ .restore_state_to_opc = cris_restore_state_to_opc,
33
34
#ifndef CONFIG_USER_ONLY
35
.tlb_fill = cris_cpu_tlb_fill,
36
@@ -XXX,XX +XXX,XX @@ static const struct TCGCPUOps crisv10_tcg_ops = {
37
38
static const struct TCGCPUOps crisv32_tcg_ops = {
39
.initialize = cris_initialize_tcg,
40
+ .restore_state_to_opc = cris_restore_state_to_opc,
41
42
#ifndef CONFIG_USER_ONLY
43
.tlb_fill = cris_cpu_tlb_fill,
44
diff --git a/target/cris/translate.c b/target/cris/translate.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/cris/translate.c
47
+++ b/target/cris/translate.c
48
@@ -XXX,XX +XXX,XX @@ void cris_initialize_tcg(void)
49
pregnames_v32[i]);
50
}
51
}
52
-
53
-void restore_state_to_opc(CPUCRISState *env, TranslationBlock *tb,
54
- target_ulong *data)
55
-{
56
- env->pc = data[0];
57
-}
58
--
59
2.34.1
60
61
diff view generated by jsdifflib
Deleted patch
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
4
target/hexagon/cpu.c | 9 +++++++--
5
1 file changed, 7 insertions(+), 2 deletions(-)
6
1
7
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
8
index XXXXXXX..XXXXXXX 100644
9
--- a/target/hexagon/cpu.c
10
+++ b/target/hexagon/cpu.c
11
@@ -XXX,XX +XXX,XX @@ static bool hexagon_cpu_has_work(CPUState *cs)
12
return true;
13
}
14
15
-void restore_state_to_opc(CPUHexagonState *env, TranslationBlock *tb,
16
- target_ulong *data)
17
+static void hexagon_restore_state_to_opc(CPUState *cs,
18
+ const TranslationBlock *tb,
19
+ const uint64_t *data)
20
{
21
+ HexagonCPU *cpu = HEXAGON_CPU(cs);
22
+ CPUHexagonState *env = &cpu->env;
23
+
24
env->gpr[HEX_REG_PC] = data[0];
25
}
26
27
@@ -XXX,XX +XXX,XX @@ static void hexagon_cpu_init(Object *obj)
28
static const struct TCGCPUOps hexagon_tcg_ops = {
29
.initialize = hexagon_translate_init,
30
.synchronize_from_tb = hexagon_cpu_synchronize_from_tb,
31
+ .restore_state_to_opc = hexagon_restore_state_to_opc,
32
};
33
34
static void hexagon_cpu_class_init(ObjectClass *c, void *data)
35
--
36
2.34.1
37
38
diff view generated by jsdifflib
Deleted patch
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
4
target/hppa/cpu.c | 19 +++++++++++++++++++
5
target/hppa/translate.c | 13 -------------
6
2 files changed, 19 insertions(+), 13 deletions(-)
7
1
8
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
9
index XXXXXXX..XXXXXXX 100644
10
--- a/target/hppa/cpu.c
11
+++ b/target/hppa/cpu.c
12
@@ -XXX,XX +XXX,XX @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs,
13
cpu->env.psw_n = (tb->flags & PSW_N) != 0;
14
}
15
16
+static void hppa_restore_state_to_opc(CPUState *cs,
17
+ const TranslationBlock *tb,
18
+ const uint64_t *data)
19
+{
20
+ HPPACPU *cpu = HPPA_CPU(cs);
21
+
22
+ cpu->env.iaoq_f = data[0];
23
+ if (data[1] != (target_ureg)-1) {
24
+ cpu->env.iaoq_b = data[1];
25
+ }
26
+ /*
27
+ * Since we were executing the instruction at IAOQ_F, and took some
28
+ * sort of action that provoked the cpu_restore_state, we can infer
29
+ * that the instruction was not nullified.
30
+ */
31
+ cpu->env.psw_n = 0;
32
+}
33
+
34
static bool hppa_cpu_has_work(CPUState *cs)
35
{
36
return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
37
@@ -XXX,XX +XXX,XX @@ static const struct SysemuCPUOps hppa_sysemu_ops = {
38
static const struct TCGCPUOps hppa_tcg_ops = {
39
.initialize = hppa_translate_init,
40
.synchronize_from_tb = hppa_cpu_synchronize_from_tb,
41
+ .restore_state_to_opc = hppa_restore_state_to_opc,
42
43
#ifndef CONFIG_USER_ONLY
44
.tlb_fill = hppa_cpu_tlb_fill,
45
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/hppa/translate.c
48
+++ b/target/hppa/translate.c
49
@@ -XXX,XX +XXX,XX @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
50
DisasContext ctx;
51
translator_loop(cs, tb, max_insns, pc, host_pc, &hppa_tr_ops, &ctx.base);
52
}
53
-
54
-void restore_state_to_opc(CPUHPPAState *env, TranslationBlock *tb,
55
- target_ulong *data)
56
-{
57
- env->iaoq_f = data[0];
58
- if (data[1] != (target_ureg)-1) {
59
- env->iaoq_b = data[1];
60
- }
61
- /* Since we were executing the instruction at IAOQ_F, and took some
62
- sort of action that provoked the cpu_restore_state, we can infer
63
- that the instruction was not nullified. */
64
- env->psw_n = 0;
65
-}
66
--
67
2.34.1
68
69
diff view generated by jsdifflib
Deleted patch
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
4
target/i386/tcg/tcg-cpu.c | 19 +++++++++++++++++++
5
target/i386/tcg/translate.c | 15 ---------------
6
2 files changed, 19 insertions(+), 15 deletions(-)
7
1
8
diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c
9
index XXXXXXX..XXXXXXX 100644
10
--- a/target/i386/tcg/tcg-cpu.c
11
+++ b/target/i386/tcg/tcg-cpu.c
12
@@ -XXX,XX +XXX,XX @@ static void x86_cpu_synchronize_from_tb(CPUState *cs,
13
}
14
}
15
16
+static void x86_restore_state_to_opc(CPUState *cs,
17
+ const TranslationBlock *tb,
18
+ const uint64_t *data)
19
+{
20
+ X86CPU *cpu = X86_CPU(cs);
21
+ CPUX86State *env = &cpu->env;
22
+ int cc_op = data[1];
23
+
24
+ if (TARGET_TB_PCREL) {
25
+ env->eip = (env->eip & TARGET_PAGE_MASK) | data[0];
26
+ } else {
27
+ env->eip = data[0] - tb->cs_base;
28
+ }
29
+ if (cc_op != CC_OP_DYNAMIC) {
30
+ env->cc_op = cc_op;
31
+ }
32
+}
33
+
34
#ifndef CONFIG_USER_ONLY
35
static bool x86_debug_check_breakpoint(CPUState *cs)
36
{
37
@@ -XXX,XX +XXX,XX @@ static bool x86_debug_check_breakpoint(CPUState *cs)
38
static const struct TCGCPUOps x86_tcg_ops = {
39
.initialize = tcg_x86_init,
40
.synchronize_from_tb = x86_cpu_synchronize_from_tb,
41
+ .restore_state_to_opc = x86_restore_state_to_opc,
42
.cpu_exec_enter = x86_cpu_exec_enter,
43
.cpu_exec_exit = x86_cpu_exec_exit,
44
#ifdef CONFIG_USER_ONLY
45
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/i386/tcg/translate.c
48
+++ b/target/i386/tcg/translate.c
49
@@ -XXX,XX +XXX,XX @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
50
51
translator_loop(cpu, tb, max_insns, pc, host_pc, &i386_tr_ops, &dc.base);
52
}
53
-
54
-void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
55
- target_ulong *data)
56
-{
57
- int cc_op = data[1];
58
-
59
- if (TARGET_TB_PCREL) {
60
- env->eip = (env->eip & TARGET_PAGE_MASK) | data[0];
61
- } else {
62
- env->eip = data[0] - tb->cs_base;
63
- }
64
- if (cc_op != CC_OP_DYNAMIC) {
65
- env->cc_op = cc_op;
66
- }
67
-}
68
--
69
2.34.1
70
71
diff view generated by jsdifflib
Deleted patch
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
4
target/loongarch/cpu.c | 11 +++++++++++
5
target/loongarch/translate.c | 6 ------
6
2 files changed, 11 insertions(+), 6 deletions(-)
7
1
8
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
9
index XXXXXXX..XXXXXXX 100644
10
--- a/target/loongarch/cpu.c
11
+++ b/target/loongarch/cpu.c
12
@@ -XXX,XX +XXX,XX @@ static void loongarch_cpu_synchronize_from_tb(CPUState *cs,
13
14
env->pc = tb_pc(tb);
15
}
16
+
17
+static void loongarch_restore_state_to_opc(CPUState *cs,
18
+ const TranslationBlock *tb,
19
+ const uint64_t *data)
20
+{
21
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
22
+ CPULoongArchState *env = &cpu->env;
23
+
24
+ env->pc = data[0];
25
+}
26
#endif /* CONFIG_TCG */
27
28
static bool loongarch_cpu_has_work(CPUState *cs)
29
@@ -XXX,XX +XXX,XX @@ void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
30
static struct TCGCPUOps loongarch_tcg_ops = {
31
.initialize = loongarch_translate_init,
32
.synchronize_from_tb = loongarch_cpu_synchronize_from_tb,
33
+ .restore_state_to_opc = loongarch_restore_state_to_opc,
34
35
#ifndef CONFIG_USER_ONLY
36
.tlb_fill = loongarch_cpu_tlb_fill,
37
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/loongarch/translate.c
40
+++ b/target/loongarch/translate.c
41
@@ -XXX,XX +XXX,XX @@ void loongarch_translate_init(void)
42
cpu_llval = tcg_global_mem_new(cpu_env,
43
offsetof(CPULoongArchState, llval), "llval");
44
}
45
-
46
-void restore_state_to_opc(CPULoongArchState *env, TranslationBlock *tb,
47
- target_ulong *data)
48
-{
49
- env->pc = data[0];
50
-}
51
--
52
2.34.1
53
54
diff view generated by jsdifflib
Deleted patch
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
4
target/microblaze/cpu.c | 11 +++++++++++
5
target/microblaze/translate.c | 7 -------
6
2 files changed, 11 insertions(+), 7 deletions(-)
7
1
8
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
9
index XXXXXXX..XXXXXXX 100644
10
--- a/target/microblaze/cpu.c
11
+++ b/target/microblaze/cpu.c
12
@@ -XXX,XX +XXX,XX @@ static void mb_cpu_synchronize_from_tb(CPUState *cs,
13
cpu->env.iflags = tb->flags & IFLAGS_TB_MASK;
14
}
15
16
+static void mb_restore_state_to_opc(CPUState *cs,
17
+ const TranslationBlock *tb,
18
+ const uint64_t *data)
19
+{
20
+ MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
21
+
22
+ cpu->env.pc = data[0];
23
+ cpu->env.iflags = data[1];
24
+}
25
+
26
static bool mb_cpu_has_work(CPUState *cs)
27
{
28
return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
29
@@ -XXX,XX +XXX,XX @@ static const struct SysemuCPUOps mb_sysemu_ops = {
30
static const struct TCGCPUOps mb_tcg_ops = {
31
.initialize = mb_tcg_init,
32
.synchronize_from_tb = mb_cpu_synchronize_from_tb,
33
+ .restore_state_to_opc = mb_restore_state_to_opc,
34
35
#ifndef CONFIG_USER_ONLY
36
.tlb_fill = mb_cpu_tlb_fill,
37
diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/microblaze/translate.c
40
+++ b/target/microblaze/translate.c
41
@@ -XXX,XX +XXX,XX @@ void mb_tcg_init(void)
42
cpu_res_addr =
43
tcg_global_mem_new(cpu_env, offsetof(CPUMBState, res_addr), "res_addr");
44
}
45
-
46
-void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb,
47
- target_ulong *data)
48
-{
49
- env->pc = data[0];
50
- env->iflags = data[1];
51
-}
52
--
53
2.34.1
54
55
diff view generated by jsdifflib
Deleted patch
1
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
4
target/mips/tcg/tcg-internal.h | 3 +++
5
target/mips/cpu.c | 1 +
6
target/mips/tcg/translate.c | 8 ++++++--
7
3 files changed, 10 insertions(+), 2 deletions(-)
8
1
9
diff --git a/target/mips/tcg/tcg-internal.h b/target/mips/tcg/tcg-internal.h
10
index XXXXXXX..XXXXXXX 100644
11
--- a/target/mips/tcg/tcg-internal.h
12
+++ b/target/mips/tcg/tcg-internal.h
13
@@ -XXX,XX +XXX,XX @@ void mips_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb);
14
G_NORETURN void mips_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
15
MMUAccessType access_type, int mmu_idx,
16
uintptr_t retaddr);
17
+void mips_restore_state_to_opc(CPUState *cs,
18
+ const TranslationBlock *tb,
19
+ const uint64_t *data);
20
21
const char *mips_exception_name(int32_t exception);
22
23
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/target/mips/cpu.c
26
+++ b/target/mips/cpu.c
27
@@ -XXX,XX +XXX,XX @@ static const struct SysemuCPUOps mips_sysemu_ops = {
28
static const struct TCGCPUOps mips_tcg_ops = {
29
.initialize = mips_tcg_init,
30
.synchronize_from_tb = mips_cpu_synchronize_from_tb,
31
+ .restore_state_to_opc = mips_restore_state_to_opc,
32
33
#if !defined(CONFIG_USER_ONLY)
34
.tlb_fill = mips_cpu_tlb_fill,
35
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/mips/tcg/translate.c
38
+++ b/target/mips/tcg/translate.c
39
@@ -XXX,XX +XXX,XX @@ void mips_tcg_init(void)
40
}
41
}
42
43
-void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
44
- target_ulong *data)
45
+void mips_restore_state_to_opc(CPUState *cs,
46
+ const TranslationBlock *tb,
47
+ const uint64_t *data)
48
{
49
+ MIPSCPU *cpu = MIPS_CPU(cs);
50
+ CPUMIPSState *env = &cpu->env;
51
+
52
env->active_tc.PC = data[0];
53
env->hflags &= ~MIPS_HFLAG_BMASK;
54
env->hflags |= data[1];
55
--
56
2.34.1
57
58
diff view generated by jsdifflib
Deleted patch
1
All targets have been updated. Use the tcg_ops target hook
2
exclusively, which allows the compat code to be removed.
3
1
4
Reviewed-by: Claudio Fontana <cfontana@suse.de>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
include/exec/exec-all.h | 3 ---
8
accel/tcg/translate-all.c | 16 ++--------------
9
2 files changed, 2 insertions(+), 17 deletions(-)
10
11
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
12
index XXXXXXX..XXXXXXX 100644
13
--- a/include/exec/exec-all.h
14
+++ b/include/exec/exec-all.h
15
@@ -XXX,XX +XXX,XX @@ typedef ram_addr_t tb_page_addr_t;
16
#define TB_PAGE_ADDR_FMT RAM_ADDR_FMT
17
#endif
18
19
-void restore_state_to_opc(CPUArchState *env, TranslationBlock *tb,
20
- target_ulong *data) __attribute__((weak));
21
-
22
/**
23
* cpu_restore_state:
24
* @cpu: the vCPU state is to be restore to
25
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/accel/tcg/translate-all.c
28
+++ b/accel/tcg/translate-all.c
29
@@ -XXX,XX +XXX,XX @@ static int encode_search(TranslationBlock *tb, uint8_t *block)
30
int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
31
uintptr_t searched_pc, bool reset_icount)
32
{
33
- target_ulong data[TARGET_INSN_START_WORDS];
34
+ uint64_t data[TARGET_INSN_START_WORDS];
35
uintptr_t host_pc = (uintptr_t)tb->tc.ptr;
36
const uint8_t *p = tb->tc.ptr + tb->tc.size;
37
int i, j, num_insns = tb->icount;
38
@@ -XXX,XX +XXX,XX @@ int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
39
cpu_neg(cpu)->icount_decr.u16.low += num_insns - i;
40
}
41
42
- {
43
- const struct TCGCPUOps *ops = cpu->cc->tcg_ops;
44
- __typeof(ops->restore_state_to_opc) restore = ops->restore_state_to_opc;
45
- if (restore) {
46
- uint64_t d64[TARGET_INSN_START_WORDS];
47
- for (i = 0; i < TARGET_INSN_START_WORDS; ++i) {
48
- d64[i] = data[i];
49
- }
50
- restore(cpu, tb, d64);
51
- } else {
52
- restore_state_to_opc(cpu->env_ptr, tb, data);
53
- }
54
- }
55
+ cpu->cc->tcg_ops->restore_state_to_opc(cpu, tb, data);
56
57
#ifdef CONFIG_PROFILER
58
qatomic_set(&prof->restore_time,
59
--
60
2.34.1
diff view generated by jsdifflib