1
TCG patch queue, plus one target/sh4 patch that
1
Second pull for this week, since this set is large enough by itself.
2
Yoshinori Sato asked me to process.
3
2
4
3
5
r~
4
r~
6
5
7
6
8
The following changes since commit efbf38d73e5dcc4d5f8b98c6e7a12be1f3b91745:
7
The following changes since commit 7c9236d6d61f30583d5d860097d88dbf0fe487bf:
9
8
10
Merge tag 'for-upstream' of git://repo.or.cz/qemu/kevin into staging (2022-10-03 15:06:07 -0400)
9
Merge tag 'pull-tcg-20230116' of https://gitlab.com/rth7680/qemu into staging (2023-01-17 10:24:16 +0000)
11
10
12
are available in the Git repository at:
11
are available in the Git repository at:
13
12
14
https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20221004
13
https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20230117
15
14
16
for you to fetch changes up to ab419fd8a035a65942de4e63effcd55ccbf1a9fe:
15
for you to fetch changes up to 493c9b19a7fb7f387c4fcf57d3836504d5242bf5:
17
16
18
target/sh4: Fix TB_FLAG_UNALIGN (2022-10-04 12:33:05 -0700)
17
tcg/riscv: Implement direct branch for goto_tb (2023-01-17 22:36:17 +0000)
19
18
20
----------------------------------------------------------------
19
----------------------------------------------------------------
21
Cache CPUClass for use in hot code paths.
20
tcg: Fix race conditions in (most) goto_tb implementations
22
Add CPUTLBEntryFull, probe_access_full, tlb_set_page_full.
23
Add generic support for TARGET_TB_PCREL.
24
tcg/ppc: Optimize 26-bit jumps using STQ for POWER 2.07
25
target/sh4: Fix TB_FLAG_UNALIGN
26
21
27
----------------------------------------------------------------
22
----------------------------------------------------------------
28
Alex Bennée (3):
23
Richard Henderson (22):
29
cpu: cache CPUClass in CPUState for hot code paths
24
tcg: Split out tcg_out_exit_tb
30
hw/core/cpu-sysemu: used cached class in cpu_asidx_from_attrs
25
tcg/i386: Remove unused goto_tb code for indirect jump
31
cputlb: used cached CPUClass in our hot-paths
26
tcg/ppc: Remove unused goto_tb code for indirect jump
27
tcg/sparc64: Remove unused goto_tb code for indirect jump
28
tcg: Replace asserts on tcg_jmp_insn_offset
29
tcg: Introduce set_jmp_insn_offset
30
tcg: Introduce get_jmp_target_addr
31
tcg: Split out tcg_out_goto_tb
32
tcg: Rename TB_JMP_RESET_OFFSET_INVALID to TB_JMP_OFFSET_INVALID
33
tcg: Add gen_tb to TCGContext
34
tcg: Add TranslationBlock.jmp_insn_offset
35
tcg: Change tb_target_set_jmp_target arguments
36
tcg: Move tb_target_set_jmp_target declaration to tcg.h
37
tcg: Always define tb_target_set_jmp_target
38
tcg: Remove TCG_TARGET_HAS_direct_jump
39
tcg/aarch64: Reorg goto_tb implementation
40
tcg/ppc: Reorg goto_tb implementation
41
tcg/sparc64: Remove USE_REG_TB
42
tcg/sparc64: Reorg goto_tb implementation
43
tcg/arm: Implement direct branch for goto_tb
44
tcg/riscv: Introduce OPC_NOP
45
tcg/riscv: Implement direct branch for goto_tb
32
46
33
Leandro Lupori (1):
47
include/exec/exec-all.h | 5 +-
34
tcg/ppc: Optimize 26-bit jumps
48
include/tcg/tcg.h | 14 ++-
35
49
tcg/aarch64/tcg-target.h | 6 +-
36
Richard Henderson (16):
50
tcg/arm/tcg-target.h | 5 -
37
accel/tcg: Rename CPUIOTLBEntry to CPUTLBEntryFull
51
tcg/i386/tcg-target.h | 9 --
38
accel/tcg: Drop addr member from SavedIOTLB
52
tcg/loongarch64/tcg-target.h | 3 -
39
accel/tcg: Suppress auto-invalidate in probe_access_internal
53
tcg/mips/tcg-target.h | 5 -
40
accel/tcg: Introduce probe_access_full
54
tcg/ppc/tcg-target.h | 7 +-
41
accel/tcg: Introduce tlb_set_page_full
55
tcg/riscv/tcg-target.h | 4 -
42
include/exec: Introduce TARGET_PAGE_ENTRY_EXTRA
56
tcg/s390x/tcg-target.h | 11 ---
43
accel/tcg: Remove PageDesc code_bitmap
57
tcg/sparc64/tcg-target.h | 4 -
44
accel/tcg: Use bool for page_find_alloc
58
tcg/tci/tcg-target.h | 4 -
45
accel/tcg: Use DisasContextBase in plugin_gen_tb_start
59
accel/tcg/cpu-exec.c | 21 ++--
46
accel/tcg: Do not align tb->page_addr[0]
60
accel/tcg/translate-all.c | 10 +-
47
accel/tcg: Inline tb_flush_jmp_cache
61
tcg/tcg-op.c | 14 +--
48
include/hw/core: Create struct CPUJumpCache
62
tcg/tcg.c | 42 +++++---
49
hw/core: Add CPUClass.get_pc
63
tcg/aarch64/tcg-target.c.inc | 106 ++++++++++-----------
50
accel/tcg: Introduce tb_pc and log_pc
64
tcg/arm/tcg-target.c.inc | 89 +++++++++++------
51
accel/tcg: Introduce TARGET_TB_PCREL
65
tcg/i386/tcg-target.c.inc | 68 +++++++------
52
target/sh4: Fix TB_FLAG_UNALIGN
66
tcg/loongarch64/tcg-target.c.inc | 66 +++++++------
53
67
tcg/mips/tcg-target.c.inc | 59 +++++++-----
54
accel/tcg/internal.h | 10 ++
68
tcg/ppc/tcg-target.c.inc | 193 ++++++++++++-------------------------
55
accel/tcg/tb-hash.h | 1 +
69
tcg/riscv/tcg-target.c.inc | 65 +++++++++----
56
accel/tcg/tb-jmp-cache.h | 65 ++++++++
70
tcg/s390x/tcg-target.c.inc | 67 ++++++++-----
57
include/exec/cpu-common.h | 1 +
71
tcg/sparc64/tcg-target.c.inc | 201 +++++++++++++++------------------------
58
include/exec/cpu-defs.h | 48 ++++--
72
tcg/tci/tcg-target.c.inc | 31 +++---
59
include/exec/exec-all.h | 75 ++++++++-
73
26 files changed, 528 insertions(+), 581 deletions(-)
60
include/exec/plugin-gen.h | 7 +-
61
include/hw/core/cpu.h | 28 ++--
62
include/qemu/typedefs.h | 2 +
63
include/tcg/tcg.h | 2 +-
64
target/sh4/cpu.h | 56 ++++---
65
accel/stubs/tcg-stub.c | 4 +
66
accel/tcg/cpu-exec.c | 80 +++++-----
67
accel/tcg/cputlb.c | 259 ++++++++++++++++++--------------
68
accel/tcg/plugin-gen.c | 22 +--
69
accel/tcg/translate-all.c | 214 ++++++++++++--------------
70
accel/tcg/translator.c | 2 +-
71
cpu.c | 9 +-
72
hw/core/cpu-common.c | 3 +-
73
hw/core/cpu-sysemu.c | 5 +-
74
linux-user/sh4/signal.c | 6 +-
75
plugins/core.c | 2 +-
76
target/alpha/cpu.c | 9 ++
77
target/arm/cpu.c | 17 ++-
78
target/arm/mte_helper.c | 14 +-
79
target/arm/sve_helper.c | 4 +-
80
target/arm/translate-a64.c | 2 +-
81
target/avr/cpu.c | 10 +-
82
target/cris/cpu.c | 8 +
83
target/hexagon/cpu.c | 10 +-
84
target/hppa/cpu.c | 12 +-
85
target/i386/cpu.c | 9 ++
86
target/i386/tcg/tcg-cpu.c | 2 +-
87
target/loongarch/cpu.c | 11 +-
88
target/m68k/cpu.c | 8 +
89
target/microblaze/cpu.c | 10 +-
90
target/mips/cpu.c | 8 +
91
target/mips/tcg/exception.c | 2 +-
92
target/mips/tcg/sysemu/special_helper.c | 2 +-
93
target/nios2/cpu.c | 9 ++
94
target/openrisc/cpu.c | 10 +-
95
target/ppc/cpu_init.c | 8 +
96
target/riscv/cpu.c | 17 ++-
97
target/rx/cpu.c | 10 +-
98
target/s390x/cpu.c | 8 +
99
target/s390x/tcg/mem_helper.c | 4 -
100
target/sh4/cpu.c | 18 ++-
101
target/sh4/helper.c | 6 +-
102
target/sh4/translate.c | 90 +++++------
103
target/sparc/cpu.c | 10 +-
104
target/tricore/cpu.c | 11 +-
105
target/xtensa/cpu.c | 8 +
106
tcg/tcg.c | 8 +-
107
trace/control-target.c | 2 +-
108
tcg/ppc/tcg-target.c.inc | 119 +++++++++++----
109
55 files changed, 915 insertions(+), 462 deletions(-)
110
create mode 100644 accel/tcg/tb-jmp-cache.h
111
diff view generated by jsdifflib
1
This structure will shortly contain more than just
1
The INDEX_op_exit_tb opcode needs no register allocation.
2
data for accessing MMIO. Rename the 'addr' member
2
Split out a dedicated helper function for it.
3
to 'xlat_section' to more clearly indicate its purpose.
4
3
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
7
---
10
include/exec/cpu-defs.h | 22 ++++----
8
tcg/tcg.c | 4 ++++
11
accel/tcg/cputlb.c | 102 +++++++++++++++++++------------------
9
tcg/aarch64/tcg-target.c.inc | 22 ++++++++++--------
12
target/arm/mte_helper.c | 14 ++---
10
tcg/arm/tcg-target.c.inc | 11 +++++----
13
target/arm/sve_helper.c | 4 +-
11
tcg/i386/tcg-target.c.inc | 21 +++++++++--------
14
target/arm/translate-a64.c | 2 +-
12
tcg/loongarch64/tcg-target.c.inc | 22 ++++++++++--------
15
5 files changed, 73 insertions(+), 71 deletions(-)
13
tcg/mips/tcg-target.c.inc | 33 +++++++++++++--------------
14
tcg/ppc/tcg-target.c.inc | 11 +++++----
15
tcg/riscv/tcg-target.c.inc | 22 ++++++++++--------
16
tcg/s390x/tcg-target.c.inc | 23 ++++++++++---------
17
tcg/sparc64/tcg-target.c.inc | 39 +++++++++++++++++---------------
18
tcg/tci/tcg-target.c.inc | 10 ++++----
19
11 files changed, 121 insertions(+), 97 deletions(-)
16
20
17
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
21
diff --git a/tcg/tcg.c b/tcg/tcg.c
18
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
19
--- a/include/exec/cpu-defs.h
23
--- a/tcg/tcg.c
20
+++ b/include/exec/cpu-defs.h
24
+++ b/tcg/tcg.c
21
@@ -XXX,XX +XXX,XX @@ typedef uint64_t target_ulong;
25
@@ -XXX,XX +XXX,XX @@ static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
22
# endif
26
static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
23
# endif
27
static void tcg_out_movi(TCGContext *s, TCGType type,
24
28
TCGReg ret, tcg_target_long arg);
25
+/* Minimalized TLB entry for use by TCG fast path. */
29
+static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg);
26
typedef struct CPUTLBEntry {
30
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
27
/* bit TARGET_LONG_BITS to TARGET_PAGE_BITS : virtual address
31
const TCGArg args[TCG_MAX_OP_ARGS],
28
bit TARGET_PAGE_BITS-1..4 : Nonzero for accesses that should not
32
const int const_args[TCG_MAX_OP_ARGS]);
29
@@ -XXX,XX +XXX,XX @@ typedef struct CPUTLBEntry {
33
@@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, target_ulong pc_start)
30
34
case INDEX_op_call:
31
QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
35
tcg_reg_alloc_call(s, op);
32
36
break;
33
-/* The IOTLB is not accessed directly inline by generated TCG code,
37
+ case INDEX_op_exit_tb:
34
- * so the CPUIOTLBEntry layout is not as critical as that of the
38
+ tcg_out_exit_tb(s, op->args[0]);
35
- * CPUTLBEntry. (This is also why we don't want to combine the two
39
+ break;
36
- * structs into one.)
40
case INDEX_op_dup2_vec:
37
+/*
41
if (tcg_reg_alloc_dup2(s, op)) {
38
+ * The full TLB entry, which is not accessed by generated TCG code,
42
break;
39
+ * so the layout is not as critical as that of CPUTLBEntry. This is
43
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
40
+ * also why we don't want to combine the two structs.
44
index XXXXXXX..XXXXXXX 100644
41
*/
45
--- a/tcg/aarch64/tcg-target.c.inc
42
-typedef struct CPUIOTLBEntry {
46
+++ b/tcg/aarch64/tcg-target.c.inc
43
+typedef struct CPUTLBEntryFull {
47
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
44
/*
48
45
- * @addr contains:
49
static const tcg_insn_unit *tb_ret_addr;
46
+ * @xlat_section contains:
50
47
* - in the lower TARGET_PAGE_BITS, a physical section number
51
+static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
48
* - with the lower TARGET_PAGE_BITS masked off, an offset which
52
+{
49
* must be added to the virtual address to obtain:
53
+ /* Reuse the zeroing that exists for goto_ptr. */
50
@@ -XXX,XX +XXX,XX @@ typedef struct CPUIOTLBEntry {
54
+ if (a0 == 0) {
51
* number is PHYS_SECTION_NOTDIRTY or PHYS_SECTION_ROM)
55
+ tcg_out_goto_long(s, tcg_code_gen_epilogue);
52
* + the offset within the target MemoryRegion (otherwise)
56
+ } else {
53
*/
57
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, a0);
54
- hwaddr addr;
58
+ tcg_out_goto_long(s, tb_ret_addr);
55
+ hwaddr xlat_section;
59
+ }
56
MemTxAttrs attrs;
60
+}
57
-} CPUIOTLBEntry;
61
+
58
+} CPUTLBEntryFull;
62
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
59
63
const TCGArg args[TCG_MAX_OP_ARGS],
60
/*
64
const int const_args[TCG_MAX_OP_ARGS])
61
* Data elements that are per MMU mode, minus the bits accessed by
65
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
62
@@ -XXX,XX +XXX,XX @@ typedef struct CPUTLBDesc {
66
#define REG0(I) (const_args[I] ? TCG_REG_XZR : (TCGReg)args[I])
63
size_t vindex;
67
64
/* The tlb victim table, in two parts. */
68
switch (opc) {
65
CPUTLBEntry vtable[CPU_VTLB_SIZE];
69
- case INDEX_op_exit_tb:
66
- CPUIOTLBEntry viotlb[CPU_VTLB_SIZE];
70
- /* Reuse the zeroing that exists for goto_ptr. */
67
- /* The iotlb. */
71
- if (a0 == 0) {
68
- CPUIOTLBEntry *iotlb;
72
- tcg_out_goto_long(s, tcg_code_gen_epilogue);
69
+ CPUTLBEntryFull vfulltlb[CPU_VTLB_SIZE];
73
- } else {
70
+ CPUTLBEntryFull *fulltlb;
74
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, a0);
71
} CPUTLBDesc;
75
- tcg_out_goto_long(s, tb_ret_addr);
72
76
- }
73
/*
77
- break;
74
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
78
-
75
index XXXXXXX..XXXXXXX 100644
79
case INDEX_op_goto_tb:
76
--- a/accel/tcg/cputlb.c
80
tcg_debug_assert(s->tb_jmp_insn_offset != NULL);
77
+++ b/accel/tcg/cputlb.c
81
/*
78
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast,
82
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
79
}
83
case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
80
84
case INDEX_op_mov_i64:
81
g_free(fast->table);
85
case INDEX_op_call: /* Always emitted via tcg_out_call. */
82
- g_free(desc->iotlb);
86
+ case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
83
+ g_free(desc->fulltlb);
87
default:
84
88
g_assert_not_reached();
85
tlb_window_reset(desc, now, 0);
89
}
86
/* desc->n_used_entries is cleared by the caller */
90
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
87
fast->mask = (new_size - 1) << CPU_TLB_ENTRY_BITS;
91
index XXXXXXX..XXXXXXX 100644
88
fast->table = g_try_new(CPUTLBEntry, new_size);
92
--- a/tcg/arm/tcg-target.c.inc
89
- desc->iotlb = g_try_new(CPUIOTLBEntry, new_size);
93
+++ b/tcg/arm/tcg-target.c.inc
90
+ desc->fulltlb = g_try_new(CPUTLBEntryFull, new_size);
94
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
91
95
92
/*
96
static void tcg_out_epilogue(TCGContext *s);
93
* If the allocations fail, try smaller sizes. We just freed some
97
94
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast,
98
+static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg)
95
* allocations to fail though, so we progressively reduce the allocation
99
+{
96
* size, aborting if we cannot even allocate the smallest TLB we support.
100
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R0, arg);
97
*/
101
+ tcg_out_epilogue(s);
98
- while (fast->table == NULL || desc->iotlb == NULL) {
102
+}
99
+ while (fast->table == NULL || desc->fulltlb == NULL) {
103
+
100
if (new_size == (1 << CPU_TLB_DYN_MIN_BITS)) {
104
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
101
error_report("%s: %s", __func__, strerror(errno));
105
const TCGArg args[TCG_MAX_OP_ARGS],
102
abort();
106
const int const_args[TCG_MAX_OP_ARGS])
103
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast,
107
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
104
fast->mask = (new_size - 1) << CPU_TLB_ENTRY_BITS;
108
int c;
105
109
106
g_free(fast->table);
110
switch (opc) {
107
- g_free(desc->iotlb);
111
- case INDEX_op_exit_tb:
108
+ g_free(desc->fulltlb);
112
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R0, args[0]);
109
fast->table = g_try_new(CPUTLBEntry, new_size);
113
- tcg_out_epilogue(s);
110
- desc->iotlb = g_try_new(CPUIOTLBEntry, new_size);
114
- break;
111
+ desc->fulltlb = g_try_new(CPUTLBEntryFull, new_size);
115
case INDEX_op_goto_tb:
112
}
116
{
113
}
117
/* Indirect jump method */
114
118
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
115
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_init(CPUTLBDesc *desc, CPUTLBDescFast *fast, int64_t now)
119
116
desc->n_used_entries = 0;
120
case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
117
fast->mask = (n_entries - 1) << CPU_TLB_ENTRY_BITS;
121
case INDEX_op_call: /* Always emitted via tcg_out_call. */
118
fast->table = g_new(CPUTLBEntry, n_entries);
122
+ case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
119
- desc->iotlb = g_new(CPUIOTLBEntry, n_entries);
123
default:
120
+ desc->fulltlb = g_new(CPUTLBEntryFull, n_entries);
124
tcg_abort();
121
tlb_mmu_flush_locked(desc, fast);
125
}
122
}
126
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
123
127
index XXXXXXX..XXXXXXX 100644
124
@@ -XXX,XX +XXX,XX @@ void tlb_destroy(CPUState *cpu)
128
--- a/tcg/i386/tcg-target.c.inc
125
CPUTLBDescFast *fast = &env_tlb(env)->f[i];
129
+++ b/tcg/i386/tcg-target.c.inc
126
130
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
127
g_free(fast->table);
128
- g_free(desc->iotlb);
129
+ g_free(desc->fulltlb);
130
}
131
}
132
133
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
134
135
/* Evict the old entry into the victim tlb. */
136
copy_tlb_helper_locked(tv, te);
137
- desc->viotlb[vidx] = desc->iotlb[index];
138
+ desc->vfulltlb[vidx] = desc->fulltlb[index];
139
tlb_n_used_entries_dec(env, mmu_idx);
140
}
141
142
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
143
* subtract here is that of the page base, and not the same as the
144
* vaddr we add back in io_readx()/io_writex()/get_page_addr_code().
145
*/
146
- desc->iotlb[index].addr = iotlb - vaddr_page;
147
- desc->iotlb[index].attrs = attrs;
148
+ desc->fulltlb[index].xlat_section = iotlb - vaddr_page;
149
+ desc->fulltlb[index].attrs = attrs;
150
151
/* Now calculate the new entry */
152
tn.addend = addend - vaddr_page;
153
@@ -XXX,XX +XXX,XX @@ static inline void cpu_transaction_failed(CPUState *cpu, hwaddr physaddr,
154
}
155
}
156
157
-static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
158
+static uint64_t io_readx(CPUArchState *env, CPUTLBEntryFull *full,
159
int mmu_idx, target_ulong addr, uintptr_t retaddr,
160
MMUAccessType access_type, MemOp op)
161
{
162
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
163
bool locked = false;
164
MemTxResult r;
165
166
- section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
167
+ section = iotlb_to_section(cpu, full->xlat_section, full->attrs);
168
mr = section->mr;
169
- mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
170
+ mr_offset = (full->xlat_section & TARGET_PAGE_MASK) + addr;
171
cpu->mem_io_pc = retaddr;
172
if (!cpu->can_do_io) {
173
cpu_io_recompile(cpu, retaddr);
174
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
175
qemu_mutex_lock_iothread();
176
locked = true;
177
}
178
- r = memory_region_dispatch_read(mr, mr_offset, &val, op, iotlbentry->attrs);
179
+ r = memory_region_dispatch_read(mr, mr_offset, &val, op, full->attrs);
180
if (r != MEMTX_OK) {
181
hwaddr physaddr = mr_offset +
182
section->offset_within_address_space -
183
section->offset_within_region;
184
185
cpu_transaction_failed(cpu, physaddr, addr, memop_size(op), access_type,
186
- mmu_idx, iotlbentry->attrs, r, retaddr);
187
+ mmu_idx, full->attrs, r, retaddr);
188
}
189
if (locked) {
190
qemu_mutex_unlock_iothread();
191
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
192
}
193
194
/*
195
- * Save a potentially trashed IOTLB entry for later lookup by plugin.
196
- * This is read by tlb_plugin_lookup if the iotlb entry doesn't match
197
+ * Save a potentially trashed CPUTLBEntryFull for later lookup by plugin.
198
+ * This is read by tlb_plugin_lookup if the fulltlb entry doesn't match
199
* because of the side effect of io_writex changing memory layout.
200
*/
201
static void save_iotlb_data(CPUState *cs, hwaddr addr,
202
@@ -XXX,XX +XXX,XX @@ static void save_iotlb_data(CPUState *cs, hwaddr addr,
203
#endif
131
#endif
204
}
132
}
205
133
206
-static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
134
+static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
207
+static void io_writex(CPUArchState *env, CPUTLBEntryFull *full,
135
+{
208
int mmu_idx, uint64_t val, target_ulong addr,
136
+ /* Reuse the zeroing that exists for goto_ptr. */
209
uintptr_t retaddr, MemOp op)
137
+ if (a0 == 0) {
210
{
138
+ tcg_out_jmp(s, tcg_code_gen_epilogue);
211
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
139
+ } else {
212
bool locked = false;
140
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_EAX, a0);
213
MemTxResult r;
141
+ tcg_out_jmp(s, tb_ret_addr);
214
142
+ }
215
- section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
143
+}
216
+ section = iotlb_to_section(cpu, full->xlat_section, full->attrs);
144
+
217
mr = section->mr;
145
static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
218
- mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
146
const TCGArg args[TCG_MAX_OP_ARGS],
219
+ mr_offset = (full->xlat_section & TARGET_PAGE_MASK) + addr;
147
const int const_args[TCG_MAX_OP_ARGS])
220
if (!cpu->can_do_io) {
148
@@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
221
cpu_io_recompile(cpu, retaddr);
149
const_a2 = const_args[2];
222
}
150
223
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
151
switch (opc) {
224
* The memory_region_dispatch may trigger a flush/resize
152
- case INDEX_op_exit_tb:
225
* so for plugins we save the iotlb_data just in case.
153
- /* Reuse the zeroing that exists for goto_ptr. */
226
*/
154
- if (a0 == 0) {
227
- save_iotlb_data(cpu, iotlbentry->addr, section, mr_offset);
155
- tcg_out_jmp(s, tcg_code_gen_epilogue);
228
+ save_iotlb_data(cpu, full->xlat_section, section, mr_offset);
156
- } else {
229
157
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_EAX, a0);
230
if (!qemu_mutex_iothread_locked()) {
158
- tcg_out_jmp(s, tb_ret_addr);
231
qemu_mutex_lock_iothread();
159
- }
232
locked = true;
160
- break;
233
}
161
case INDEX_op_goto_tb:
234
- r = memory_region_dispatch_write(mr, mr_offset, val, op, iotlbentry->attrs);
162
if (s->tb_jmp_insn_offset) {
235
+ r = memory_region_dispatch_write(mr, mr_offset, val, op, full->attrs);
163
/* direct jump method */
236
if (r != MEMTX_OK) {
164
@@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
237
hwaddr physaddr = mr_offset +
165
case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
238
section->offset_within_address_space -
166
case INDEX_op_mov_i64:
239
section->offset_within_region;
167
case INDEX_op_call: /* Always emitted via tcg_out_call. */
240
168
+ case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
241
cpu_transaction_failed(cpu, physaddr, addr, memop_size(op),
169
default:
242
- MMU_DATA_STORE, mmu_idx, iotlbentry->attrs, r,
170
tcg_abort();
243
+ MMU_DATA_STORE, mmu_idx, full->attrs, r,
171
}
244
retaddr);
172
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
245
}
173
index XXXXXXX..XXXXXXX 100644
246
if (locked) {
174
--- a/tcg/loongarch64/tcg-target.c.inc
247
@@ -XXX,XX +XXX,XX @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
175
+++ b/tcg/loongarch64/tcg-target.c.inc
248
copy_tlb_helper_locked(vtlb, &tmptlb);
176
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
249
qemu_spin_unlock(&env_tlb(env)->c.lock);
177
250
178
static const tcg_insn_unit *tb_ret_addr;
251
- CPUIOTLBEntry tmpio, *io = &env_tlb(env)->d[mmu_idx].iotlb[index];
179
252
- CPUIOTLBEntry *vio = &env_tlb(env)->d[mmu_idx].viotlb[vidx];
180
+static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
253
- tmpio = *io; *io = *vio; *vio = tmpio;
181
+{
254
+ CPUTLBEntryFull *f1 = &env_tlb(env)->d[mmu_idx].fulltlb[index];
182
+ /* Reuse the zeroing that exists for goto_ptr. */
255
+ CPUTLBEntryFull *f2 = &env_tlb(env)->d[mmu_idx].vfulltlb[vidx];
183
+ if (a0 == 0) {
256
+ CPUTLBEntryFull tmpf;
184
+ tcg_out_call_int(s, tcg_code_gen_epilogue, true);
257
+ tmpf = *f1; *f1 = *f2; *f2 = tmpf;
185
+ } else {
258
return true;
186
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0);
259
}
187
+ tcg_out_call_int(s, tb_ret_addr, true);
260
}
188
+ }
261
@@ -XXX,XX +XXX,XX @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
189
+}
262
(ADDR) & TARGET_PAGE_MASK)
190
+
263
191
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
264
static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size,
192
const TCGArg args[TCG_MAX_OP_ARGS],
265
- CPUIOTLBEntry *iotlbentry, uintptr_t retaddr)
193
const int const_args[TCG_MAX_OP_ARGS])
266
+ CPUTLBEntryFull *full, uintptr_t retaddr)
194
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
267
{
195
int c2 = const_args[2];
268
- ram_addr_t ram_addr = mem_vaddr + iotlbentry->addr;
196
269
+ ram_addr_t ram_addr = mem_vaddr + full->xlat_section;
197
switch (opc) {
270
198
- case INDEX_op_exit_tb:
271
trace_memory_notdirty_write_access(mem_vaddr, ram_addr, size);
199
- /* Reuse the zeroing that exists for goto_ptr. */
272
200
- if (a0 == 0) {
273
@@ -XXX,XX +XXX,XX @@ int probe_access_flags(CPUArchState *env, target_ulong addr,
201
- tcg_out_call_int(s, tcg_code_gen_epilogue, true);
274
/* Handle clean RAM pages. */
202
- } else {
275
if (unlikely(flags & TLB_NOTDIRTY)) {
203
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0);
276
uintptr_t index = tlb_index(env, mmu_idx, addr);
204
- tcg_out_call_int(s, tb_ret_addr, true);
277
- CPUIOTLBEntry *iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
205
- }
278
+ CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
206
- break;
279
207
-
280
- notdirty_write(env_cpu(env), addr, 1, iotlbentry, retaddr);
208
case INDEX_op_goto_tb:
281
+ notdirty_write(env_cpu(env), addr, 1, full, retaddr);
209
tcg_debug_assert(s->tb_jmp_insn_offset != NULL);
282
flags &= ~TLB_NOTDIRTY;
210
/*
283
}
211
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
284
212
case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
285
@@ -XXX,XX +XXX,XX @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
213
case INDEX_op_mov_i64:
286
214
case INDEX_op_call: /* Always emitted via tcg_out_call. */
287
if (unlikely(flags & (TLB_NOTDIRTY | TLB_WATCHPOINT))) {
215
+ case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
288
uintptr_t index = tlb_index(env, mmu_idx, addr);
216
default:
289
- CPUIOTLBEntry *iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
217
g_assert_not_reached();
290
+ CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
218
}
291
219
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
292
/* Handle watchpoints. */
220
index XXXXXXX..XXXXXXX 100644
293
if (flags & TLB_WATCHPOINT) {
221
--- a/tcg/mips/tcg-target.c.inc
294
int wp_access = (access_type == MMU_DATA_STORE
222
+++ b/tcg/mips/tcg-target.c.inc
295
? BP_MEM_WRITE : BP_MEM_READ);
223
@@ -XXX,XX +XXX,XX @@ static void tcg_out_clz(TCGContext *s, MIPSInsn opcv2, MIPSInsn opcv6,
296
cpu_check_watchpoint(env_cpu(env), addr, size,
224
}
297
- iotlbentry->attrs, wp_access, retaddr);
225
}
298
+ full->attrs, wp_access, retaddr);
226
299
}
227
+static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
300
228
+{
301
/* Handle clean RAM pages. */
229
+ TCGReg b0 = TCG_REG_ZERO;
302
if (flags & TLB_NOTDIRTY) {
230
+
303
- notdirty_write(env_cpu(env), addr, 1, iotlbentry, retaddr);
231
+ if (a0 & ~0xffff) {
304
+ notdirty_write(env_cpu(env), addr, 1, full, retaddr);
232
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, a0 & ~0xffff);
305
}
233
+ b0 = TCG_REG_V0;
306
}
234
+ }
307
235
+ if (!tcg_out_opc_jmp(s, OPC_J, tb_ret_addr)) {
308
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
236
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, (uintptr_t)tb_ret_addr);
309
* should have just filled the TLB. The one corner case is io_writex
237
+ tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
310
* which can cause TLB flushes and potential resizing of the TLBs
238
+ }
311
* losing the information we need. In those cases we need to recover
239
+ tcg_out_opc_imm(s, OPC_ORI, TCG_REG_V0, b0, a0 & 0xffff);
312
- * data from a copy of the iotlbentry. As long as this always occurs
240
+}
313
+ * data from a copy of the CPUTLBEntryFull. As long as this always occurs
241
+
314
* from the same thread (which a mem callback will be) this is safe.
242
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
315
*/
243
const TCGArg args[TCG_MAX_OP_ARGS],
316
244
const int const_args[TCG_MAX_OP_ARGS])
317
@@ -XXX,XX +XXX,XX @@ bool tlb_plugin_lookup(CPUState *cpu, target_ulong addr, int mmu_idx,
245
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
318
if (likely(tlb_hit(tlb_addr, addr))) {
246
c2 = const_args[2];
319
/* We must have an iotlb entry for MMIO */
247
320
if (tlb_addr & TLB_MMIO) {
248
switch (opc) {
321
- CPUIOTLBEntry *iotlbentry;
249
- case INDEX_op_exit_tb:
322
- iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
250
- {
323
+ CPUTLBEntryFull *full;
251
- TCGReg b0 = TCG_REG_ZERO;
324
+ full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
252
-
325
data->is_io = true;
253
- a0 = (intptr_t)a0;
326
- data->v.io.section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
254
- if (a0 & ~0xffff) {
327
- data->v.io.offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
255
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, a0 & ~0xffff);
328
+ data->v.io.section =
256
- b0 = TCG_REG_V0;
329
+ iotlb_to_section(cpu, full->xlat_section, full->attrs);
257
- }
330
+ data->v.io.offset = (full->xlat_section & TARGET_PAGE_MASK) + addr;
258
- if (!tcg_out_opc_jmp(s, OPC_J, tb_ret_addr)) {
331
} else {
259
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0,
332
data->is_io = false;
260
- (uintptr_t)tb_ret_addr);
333
data->v.ram.hostaddr = (void *)((uintptr_t)addr + tlbe->addend);
261
- tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
334
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
262
- }
335
263
- tcg_out_opc_imm(s, OPC_ORI, TCG_REG_V0, b0, a0 & 0xffff);
336
if (unlikely(tlb_addr & TLB_NOTDIRTY)) {
264
- }
337
notdirty_write(env_cpu(env), addr, size,
265
- break;
338
- &env_tlb(env)->d[mmu_idx].iotlb[index], retaddr);
266
case INDEX_op_goto_tb:
339
+ &env_tlb(env)->d[mmu_idx].fulltlb[index], retaddr);
267
/* indirect jump method */
340
}
268
tcg_debug_assert(s->tb_jmp_insn_offset == 0);
341
269
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
342
return hostaddr;
270
case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
343
@@ -XXX,XX +XXX,XX @@ load_helper(CPUArchState *env, target_ulong addr, MemOpIdx oi,
271
case INDEX_op_mov_i64:
344
272
case INDEX_op_call: /* Always emitted via tcg_out_call. */
345
/* Handle anything that isn't just a straight memory access. */
273
+ case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
346
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
274
default:
347
- CPUIOTLBEntry *iotlbentry;
275
tcg_abort();
348
+ CPUTLBEntryFull *full;
276
}
349
bool need_swap;
277
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
350
278
index XXXXXXX..XXXXXXX 100644
351
/* For anything that is unaligned, recurse through full_load. */
279
--- a/tcg/ppc/tcg-target.c.inc
352
@@ -XXX,XX +XXX,XX @@ load_helper(CPUArchState *env, target_ulong addr, MemOpIdx oi,
280
+++ b/tcg/ppc/tcg-target.c.inc
353
goto do_unaligned_access;
281
@@ -XXX,XX +XXX,XX @@ static void tcg_target_qemu_prologue(TCGContext *s)
354
}
282
tcg_out32(s, BCLR | BO_ALWAYS);
355
283
}
356
- iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
284
357
+ full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
285
+static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg)
358
286
+{
359
/* Handle watchpoints. */
287
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R3, arg);
360
if (unlikely(tlb_addr & TLB_WATCHPOINT)) {
288
+ tcg_out_b(s, 0, tcg_code_gen_epilogue);
361
/* On watchpoint hit, this will longjmp out. */
289
+}
362
cpu_check_watchpoint(env_cpu(env), addr, size,
290
+
363
- iotlbentry->attrs, BP_MEM_READ, retaddr);
291
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
364
+ full->attrs, BP_MEM_READ, retaddr);
292
const TCGArg args[TCG_MAX_OP_ARGS],
365
}
293
const int const_args[TCG_MAX_OP_ARGS])
366
294
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
367
need_swap = size > 1 && (tlb_addr & TLB_BSWAP);
295
TCGArg a0, a1, a2;
368
296
369
/* Handle I/O access. */
297
switch (opc) {
370
if (likely(tlb_addr & TLB_MMIO)) {
298
- case INDEX_op_exit_tb:
371
- return io_readx(env, iotlbentry, mmu_idx, addr, retaddr,
299
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R3, args[0]);
372
+ return io_readx(env, full, mmu_idx, addr, retaddr,
300
- tcg_out_b(s, 0, tcg_code_gen_epilogue);
373
access_type, op ^ (need_swap * MO_BSWAP));
301
- break;
374
}
302
case INDEX_op_goto_tb:
375
303
if (s->tb_jmp_insn_offset) {
376
@@ -XXX,XX +XXX,XX @@ store_helper_unaligned(CPUArchState *env, target_ulong addr, uint64_t val,
304
/* Direct jump. */
377
*/
305
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
378
if (unlikely(tlb_addr & TLB_WATCHPOINT)) {
306
case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
379
cpu_check_watchpoint(env_cpu(env), addr, size - size2,
307
case INDEX_op_mov_i64:
380
- env_tlb(env)->d[mmu_idx].iotlb[index].attrs,
308
case INDEX_op_call: /* Always emitted via tcg_out_call. */
381
+ env_tlb(env)->d[mmu_idx].fulltlb[index].attrs,
309
+ case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
382
BP_MEM_WRITE, retaddr);
310
default:
383
}
311
tcg_abort();
384
if (unlikely(tlb_addr2 & TLB_WATCHPOINT)) {
312
}
385
cpu_check_watchpoint(env_cpu(env), page2, size2,
313
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
386
- env_tlb(env)->d[mmu_idx].iotlb[index2].attrs,
314
index XXXXXXX..XXXXXXX 100644
387
+ env_tlb(env)->d[mmu_idx].fulltlb[index2].attrs,
315
--- a/tcg/riscv/tcg-target.c.inc
388
BP_MEM_WRITE, retaddr);
316
+++ b/tcg/riscv/tcg-target.c.inc
389
}
317
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
390
318
391
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
319
static const tcg_insn_unit *tb_ret_addr;
392
320
393
/* Handle anything that isn't just a straight memory access. */
321
+static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
394
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
322
+{
395
- CPUIOTLBEntry *iotlbentry;
323
+ /* Reuse the zeroing that exists for goto_ptr. */
396
+ CPUTLBEntryFull *full;
324
+ if (a0 == 0) {
397
bool need_swap;
325
+ tcg_out_call_int(s, tcg_code_gen_epilogue, true);
398
326
+ } else {
399
/* For anything that is unaligned, recurse through byte stores. */
327
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0);
400
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
328
+ tcg_out_call_int(s, tb_ret_addr, true);
401
goto do_unaligned_access;
329
+ }
402
}
330
+}
403
331
+
404
- iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
332
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
405
+ full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
333
const TCGArg args[TCG_MAX_OP_ARGS],
406
334
const int const_args[TCG_MAX_OP_ARGS])
407
/* Handle watchpoints. */
335
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
408
if (unlikely(tlb_addr & TLB_WATCHPOINT)) {
336
int c2 = const_args[2];
409
/* On watchpoint hit, this will longjmp out. */
337
410
cpu_check_watchpoint(env_cpu(env), addr, size,
338
switch (opc) {
411
- iotlbentry->attrs, BP_MEM_WRITE, retaddr);
339
- case INDEX_op_exit_tb:
412
+ full->attrs, BP_MEM_WRITE, retaddr);
340
- /* Reuse the zeroing that exists for goto_ptr. */
413
}
341
- if (a0 == 0) {
414
342
- tcg_out_call_int(s, tcg_code_gen_epilogue, true);
415
need_swap = size > 1 && (tlb_addr & TLB_BSWAP);
343
- } else {
416
344
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0);
417
/* Handle I/O access. */
345
- tcg_out_call_int(s, tb_ret_addr, true);
418
if (tlb_addr & TLB_MMIO) {
346
- }
419
- io_writex(env, iotlbentry, mmu_idx, val, addr, retaddr,
347
- break;
420
+ io_writex(env, full, mmu_idx, val, addr, retaddr,
348
-
421
op ^ (need_swap * MO_BSWAP));
349
case INDEX_op_goto_tb:
422
return;
350
assert(s->tb_jmp_insn_offset == 0);
423
}
351
/* indirect jump method */
424
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
352
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
425
353
case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
426
/* Handle clean RAM pages. */
354
case INDEX_op_mov_i64:
427
if (tlb_addr & TLB_NOTDIRTY) {
355
case INDEX_op_call: /* Always emitted via tcg_out_call. */
428
- notdirty_write(env_cpu(env), addr, size, iotlbentry, retaddr);
356
+ case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
429
+ notdirty_write(env_cpu(env), addr, size, full, retaddr);
357
default:
430
}
358
g_assert_not_reached();
431
359
}
432
haddr = (void *)((uintptr_t)addr + entry->addend);
360
diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc
433
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
361
index XXXXXXX..XXXXXXX 100644
434
index XXXXXXX..XXXXXXX 100644
362
--- a/tcg/s390x/tcg-target.c.inc
435
--- a/target/arm/mte_helper.c
363
+++ b/tcg/s390x/tcg-target.c.inc
436
+++ b/target/arm/mte_helper.c
364
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st(TCGContext* s, TCGReg data_reg, TCGReg addr_reg,
437
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
438
return tags + index;
439
#else
440
uintptr_t index;
441
- CPUIOTLBEntry *iotlbentry;
442
+ CPUTLBEntryFull *full;
443
int in_page, flags;
444
ram_addr_t ptr_ra;
445
hwaddr ptr_paddr, tag_paddr, xlat;
446
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
447
assert(!(flags & TLB_INVALID_MASK));
448
449
/*
450
- * Find the iotlbentry for ptr. This *must* be present in the TLB
451
+ * Find the CPUTLBEntryFull for ptr. This *must* be present in the TLB
452
* because we just found the mapping.
453
* TODO: Perhaps there should be a cputlb helper that returns a
454
* matching tlb entry + iotlb entry.
455
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
456
g_assert(tlb_hit(comparator, ptr));
457
}
458
# endif
459
- iotlbentry = &env_tlb(env)->d[ptr_mmu_idx].iotlb[index];
460
+ full = &env_tlb(env)->d[ptr_mmu_idx].fulltlb[index];
461
462
/* If the virtual page MemAttr != Tagged, access unchecked. */
463
- if (!arm_tlb_mte_tagged(&iotlbentry->attrs)) {
464
+ if (!arm_tlb_mte_tagged(&full->attrs)) {
465
return NULL;
466
}
467
468
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
469
int wp = ptr_access == MMU_DATA_LOAD ? BP_MEM_READ : BP_MEM_WRITE;
470
assert(ra != 0);
471
cpu_check_watchpoint(env_cpu(env), ptr, ptr_size,
472
- iotlbentry->attrs, wp, ra);
473
+ full->attrs, wp, ra);
474
}
475
476
/*
477
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
478
tag_paddr = ptr_paddr >> (LOG2_TAG_GRANULE + 1);
479
480
/* Look up the address in tag space. */
481
- tag_asi = iotlbentry->attrs.secure ? ARMASIdx_TagS : ARMASIdx_TagNS;
482
+ tag_asi = full->attrs.secure ? ARMASIdx_TagS : ARMASIdx_TagNS;
483
tag_as = cpu_get_address_space(env_cpu(env), tag_asi);
484
mr = address_space_translate(tag_as, tag_paddr, &xlat, NULL,
485
tag_access == MMU_DATA_STORE,
486
- iotlbentry->attrs);
487
+ full->attrs);
488
489
/*
490
* Note that @mr will never be NULL. If there is nothing in the address
491
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
492
index XXXXXXX..XXXXXXX 100644
493
--- a/target/arm/sve_helper.c
494
+++ b/target/arm/sve_helper.c
495
@@ -XXX,XX +XXX,XX @@ bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
496
g_assert(tlb_hit(comparator, addr));
497
# endif
498
499
- CPUIOTLBEntry *iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
500
- info->attrs = iotlbentry->attrs;
501
+ CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
502
+ info->attrs = full->attrs;
503
}
504
#endif
505
506
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
507
index XXXXXXX..XXXXXXX 100644
508
--- a/target/arm/translate-a64.c
509
+++ b/target/arm/translate-a64.c
510
@@ -XXX,XX +XXX,XX @@ static bool is_guarded_page(CPUARMState *env, DisasContext *s)
511
* table entry even for that case.
512
*/
513
return (tlb_hit(entry->addr_code, addr) &&
514
- arm_tlb_bti_gp(&env_tlb(env)->d[mmu_idx].iotlb[index].attrs));
515
+ arm_tlb_bti_gp(&env_tlb(env)->d[mmu_idx].fulltlb[index].attrs));
516
#endif
365
#endif
517
}
366
}
518
367
368
+static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
369
+{
370
+ /* Reuse the zeroing that exists for goto_ptr. */
371
+ if (a0 == 0) {
372
+ tgen_gotoi(s, S390_CC_ALWAYS, tcg_code_gen_epilogue);
373
+ } else {
374
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, a0);
375
+ tgen_gotoi(s, S390_CC_ALWAYS, tb_ret_addr);
376
+ }
377
+}
378
+
379
# define OP_32_64(x) \
380
case glue(glue(INDEX_op_,x),_i32): \
381
case glue(glue(INDEX_op_,x),_i64)
382
@@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
383
TCGArg a0, a1, a2;
384
385
switch (opc) {
386
- case INDEX_op_exit_tb:
387
- /* Reuse the zeroing that exists for goto_ptr. */
388
- a0 = args[0];
389
- if (a0 == 0) {
390
- tgen_gotoi(s, S390_CC_ALWAYS, tcg_code_gen_epilogue);
391
- } else {
392
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, a0);
393
- tgen_gotoi(s, S390_CC_ALWAYS, tb_ret_addr);
394
- }
395
- break;
396
-
397
case INDEX_op_goto_tb:
398
a0 = args[0];
399
/*
400
@@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
401
case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
402
case INDEX_op_mov_i64:
403
case INDEX_op_call: /* Always emitted via tcg_out_call. */
404
+ case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
405
default:
406
tcg_abort();
407
}
408
diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc
409
index XXXXXXX..XXXXXXX 100644
410
--- a/tcg/sparc64/tcg-target.c.inc
411
+++ b/tcg/sparc64/tcg-target.c.inc
412
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data, TCGReg addr,
413
#endif /* CONFIG_SOFTMMU */
414
}
415
416
+static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
417
+{
418
+ if (check_fit_ptr(a0, 13)) {
419
+ tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN);
420
+ tcg_out_movi_imm13(s, TCG_REG_O0, a0);
421
+ return;
422
+ } else if (USE_REG_TB) {
423
+ intptr_t tb_diff = tcg_tbrel_diff(s, (void *)a0);
424
+ if (check_fit_ptr(tb_diff, 13)) {
425
+ tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN);
426
+ /* Note that TCG_REG_TB has been unwound to O1. */
427
+ tcg_out_arithi(s, TCG_REG_O0, TCG_REG_O1, tb_diff, ARITH_ADD);
428
+ return;
429
+ }
430
+ }
431
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I0, a0 & ~0x3ff);
432
+ tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN);
433
+ tcg_out_arithi(s, TCG_REG_O0, TCG_REG_O0, a0 & 0x3ff, ARITH_OR);
434
+}
435
+
436
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
437
const TCGArg args[TCG_MAX_OP_ARGS],
438
const int const_args[TCG_MAX_OP_ARGS])
439
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
440
c2 = const_args[2];
441
442
switch (opc) {
443
- case INDEX_op_exit_tb:
444
- if (check_fit_ptr(a0, 13)) {
445
- tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN);
446
- tcg_out_movi_imm13(s, TCG_REG_O0, a0);
447
- break;
448
- } else if (USE_REG_TB) {
449
- intptr_t tb_diff = tcg_tbrel_diff(s, (void *)a0);
450
- if (check_fit_ptr(tb_diff, 13)) {
451
- tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN);
452
- /* Note that TCG_REG_TB has been unwound to O1. */
453
- tcg_out_arithi(s, TCG_REG_O0, TCG_REG_O1, tb_diff, ARITH_ADD);
454
- break;
455
- }
456
- }
457
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I0, a0 & ~0x3ff);
458
- tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN);
459
- tcg_out_arithi(s, TCG_REG_O0, TCG_REG_O0, a0 & 0x3ff, ARITH_OR);
460
- break;
461
case INDEX_op_goto_tb:
462
if (s->tb_jmp_insn_offset) {
463
/* direct jump method */
464
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
465
case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
466
case INDEX_op_mov_i64:
467
case INDEX_op_call: /* Always emitted via tcg_out_call. */
468
+ case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
469
default:
470
tcg_abort();
471
}
472
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
473
index XXXXXXX..XXXXXXX 100644
474
--- a/tcg/tci/tcg-target.c.inc
475
+++ b/tcg/tci/tcg-target.c.inc
476
@@ -XXX,XX +XXX,XX @@ static void tcg_out_call(TCGContext *s, const tcg_insn_unit *func,
477
# define CASE_64(x)
478
#endif
479
480
+static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg)
481
+{
482
+ tcg_out_op_p(s, INDEX_op_exit_tb, (void *)arg);
483
+}
484
+
485
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
486
const TCGArg args[TCG_MAX_OP_ARGS],
487
const int const_args[TCG_MAX_OP_ARGS])
488
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
489
TCGOpcode exts;
490
491
switch (opc) {
492
- case INDEX_op_exit_tb:
493
- tcg_out_op_p(s, opc, (void *)args[0]);
494
- break;
495
-
496
case INDEX_op_goto_tb:
497
tcg_debug_assert(s->tb_jmp_insn_offset == 0);
498
/* indirect jump method. */
499
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
500
case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
501
case INDEX_op_mov_i64:
502
case INDEX_op_call: /* Always emitted via tcg_out_call. */
503
+ case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
504
default:
505
tcg_abort();
506
}
519
--
507
--
520
2.34.1
508
2.34.1
521
509
522
510
diff view generated by jsdifflib
New patch
1
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
4
tcg/i386/tcg-target.c.inc | 14 +++++---------
5
1 file changed, 5 insertions(+), 9 deletions(-)
1
6
7
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
8
index XXXXXXX..XXXXXXX 100644
9
--- a/tcg/i386/tcg-target.c.inc
10
+++ b/tcg/i386/tcg-target.c.inc
11
@@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
12
13
switch (opc) {
14
case INDEX_op_goto_tb:
15
- if (s->tb_jmp_insn_offset) {
16
- /* direct jump method */
17
- int gap;
18
- /* jump displacement must be aligned for atomic patching;
19
+ qemu_build_assert(TCG_TARGET_HAS_direct_jump);
20
+ {
21
+ /*
22
+ * Jump displacement must be aligned for atomic patching;
23
* see if we need to add extra nops before jump
24
*/
25
- gap = QEMU_ALIGN_PTR_UP(s->code_ptr + 1, 4) - s->code_ptr;
26
+ int gap = QEMU_ALIGN_PTR_UP(s->code_ptr + 1, 4) - s->code_ptr;
27
if (gap != 1) {
28
tcg_out_nopn(s, gap - 1);
29
}
30
tcg_out8(s, OPC_JMP_long); /* jmp im */
31
s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
32
tcg_out32(s, 0);
33
- } else {
34
- /* indirect jump method */
35
- tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, -1,
36
- (intptr_t)(s->tb_jmp_target_addr + a0));
37
}
38
set_jmp_reset_offset(s, a0);
39
break;
40
--
41
2.34.1
42
43
diff view generated by jsdifflib
New patch
1
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
4
tcg/ppc/tcg-target.c.inc | 32 +++++++++++++-------------------
5
1 file changed, 13 insertions(+), 19 deletions(-)
1
6
7
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
8
index XXXXXXX..XXXXXXX 100644
9
--- a/tcg/ppc/tcg-target.c.inc
10
+++ b/tcg/ppc/tcg-target.c.inc
11
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
12
13
switch (opc) {
14
case INDEX_op_goto_tb:
15
- if (s->tb_jmp_insn_offset) {
16
- /* Direct jump. */
17
- if (TCG_TARGET_REG_BITS == 64) {
18
- /* Ensure the next insns are 8 or 16-byte aligned. */
19
- while ((uintptr_t)s->code_ptr & (have_isa_2_07 ? 15 : 7)) {
20
- tcg_out32(s, NOP);
21
- }
22
- s->tb_jmp_insn_offset[args[0]] = tcg_current_code_size(s);
23
- tcg_out32(s, ADDIS | TAI(TCG_REG_TB, TCG_REG_TB, 0));
24
- tcg_out32(s, ADDI | TAI(TCG_REG_TB, TCG_REG_TB, 0));
25
- } else {
26
- s->tb_jmp_insn_offset[args[0]] = tcg_current_code_size(s);
27
- tcg_out32(s, B);
28
- s->tb_jmp_reset_offset[args[0]] = tcg_current_code_size(s);
29
- break;
30
+ qemu_build_assert(TCG_TARGET_HAS_direct_jump);
31
+ /* Direct jump. */
32
+ if (TCG_TARGET_REG_BITS == 64) {
33
+ /* Ensure the next insns are 8 or 16-byte aligned. */
34
+ while ((uintptr_t)s->code_ptr & (have_isa_2_07 ? 15 : 7)) {
35
+ tcg_out32(s, NOP);
36
}
37
+ s->tb_jmp_insn_offset[args[0]] = tcg_current_code_size(s);
38
+ tcg_out32(s, ADDIS | TAI(TCG_REG_TB, TCG_REG_TB, 0));
39
+ tcg_out32(s, ADDI | TAI(TCG_REG_TB, TCG_REG_TB, 0));
40
} else {
41
- /* Indirect jump. */
42
- tcg_debug_assert(s->tb_jmp_insn_offset == NULL);
43
- tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TB, 0,
44
- (intptr_t)(s->tb_jmp_insn_offset + args[0]));
45
+ s->tb_jmp_insn_offset[args[0]] = tcg_current_code_size(s);
46
+ tcg_out32(s, B);
47
+ s->tb_jmp_reset_offset[args[0]] = tcg_current_code_size(s);
48
+ break;
49
}
50
tcg_out32(s, MTSPR | RS(TCG_REG_TB) | CTR);
51
tcg_out32(s, BCCTR | BO_ALWAYS);
52
--
53
2.34.1
54
55
diff view generated by jsdifflib
1
Use the pc coming from db->pc_first rather than the TB.
2
3
Use the cached host_addr rather than re-computing for the
4
first page. We still need a separate lookup for the second
5
page because it won't be computed for DisasContextBase until
6
the translator actually performs a read from the page.
7
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
1
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
---
3
---
11
include/exec/plugin-gen.h | 7 ++++---
4
tcg/sparc64/tcg-target.c.inc | 41 +++++++++++-------------------------
12
accel/tcg/plugin-gen.c | 22 +++++++++++-----------
5
1 file changed, 12 insertions(+), 29 deletions(-)
13
accel/tcg/translator.c | 2 +-
14
3 files changed, 16 insertions(+), 15 deletions(-)
15
6
16
diff --git a/include/exec/plugin-gen.h b/include/exec/plugin-gen.h
7
diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc
17
index XXXXXXX..XXXXXXX 100644
8
index XXXXXXX..XXXXXXX 100644
18
--- a/include/exec/plugin-gen.h
9
--- a/tcg/sparc64/tcg-target.c.inc
19
+++ b/include/exec/plugin-gen.h
10
+++ b/tcg/sparc64/tcg-target.c.inc
20
@@ -XXX,XX +XXX,XX @@ struct DisasContextBase;
11
@@ -XXX,XX +XXX,XX @@ static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
21
22
#ifdef CONFIG_PLUGIN
23
24
-bool plugin_gen_tb_start(CPUState *cpu, const TranslationBlock *tb, bool supress);
25
+bool plugin_gen_tb_start(CPUState *cpu, const struct DisasContextBase *db,
26
+ bool supress);
27
void plugin_gen_tb_end(CPUState *cpu);
28
void plugin_gen_insn_start(CPUState *cpu, const struct DisasContextBase *db);
29
void plugin_gen_insn_end(void);
30
@@ -XXX,XX +XXX,XX @@ static inline void plugin_insn_append(abi_ptr pc, const void *from, size_t size)
31
32
#else /* !CONFIG_PLUGIN */
33
34
-static inline
35
-bool plugin_gen_tb_start(CPUState *cpu, const TranslationBlock *tb, bool supress)
36
+static inline bool
37
+plugin_gen_tb_start(CPUState *cpu, const struct DisasContextBase *db, bool sup)
38
{
39
return false;
12
return false;
40
}
13
}
41
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
14
42
index XXXXXXX..XXXXXXX 100644
15
-static void tcg_out_ld_ptr(TCGContext *s, TCGReg ret, const void *arg)
43
--- a/accel/tcg/plugin-gen.c
16
-{
44
+++ b/accel/tcg/plugin-gen.c
17
- intptr_t diff = tcg_tbrel_diff(s, arg);
45
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_inject(const struct qemu_plugin_tb *plugin_tb)
18
- if (USE_REG_TB && check_fit_ptr(diff, 13)) {
46
pr_ops();
19
- tcg_out_ld(s, TCG_TYPE_PTR, ret, TCG_REG_TB, diff);
47
}
20
- return;
48
21
- }
49
-bool plugin_gen_tb_start(CPUState *cpu, const TranslationBlock *tb, bool mem_only)
22
- tcg_out_movi(s, TCG_TYPE_PTR, ret, (uintptr_t)arg & ~0x3ff);
50
+bool plugin_gen_tb_start(CPUState *cpu, const DisasContextBase *db,
23
- tcg_out_ld(s, TCG_TYPE_PTR, ret, ret, (uintptr_t)arg & 0x3ff);
51
+ bool mem_only)
24
-}
25
-
26
static void tcg_out_sety(TCGContext *s, TCGReg rs)
52
{
27
{
53
bool ret = false;
28
tcg_out32(s, WRY | INSN_RS1(TCG_REG_G0) | INSN_RS2(rs));
54
29
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
55
@@ -XXX,XX +XXX,XX @@ bool plugin_gen_tb_start(CPUState *cpu, const TranslationBlock *tb, bool mem_onl
30
56
31
switch (opc) {
57
ret = true;
32
case INDEX_op_goto_tb:
58
33
- if (s->tb_jmp_insn_offset) {
59
- ptb->vaddr = tb->pc;
34
- /* direct jump method */
60
+ ptb->vaddr = db->pc_first;
35
- if (USE_REG_TB) {
61
ptb->vaddr2 = -1;
36
- /* make sure the patch is 8-byte aligned. */
62
- get_page_addr_code_hostp(cpu->env_ptr, tb->pc, &ptb->haddr1);
37
- if ((intptr_t)s->code_ptr & 4) {
63
+ ptb->haddr1 = db->host_addr[0];
38
- tcg_out_nop(s);
64
ptb->haddr2 = NULL;
39
- }
65
ptb->mem_only = mem_only;
40
- s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
66
41
- tcg_out_sethi(s, TCG_REG_T1, 0);
67
@@ -XXX,XX +XXX,XX @@ void plugin_gen_insn_start(CPUState *cpu, const DisasContextBase *db)
42
- tcg_out_arithi(s, TCG_REG_T1, TCG_REG_T1, 0, ARITH_OR);
68
* Note that we skip this when haddr1 == NULL, e.g. when we're
43
- tcg_out_arith(s, TCG_REG_G0, TCG_REG_TB, TCG_REG_T1, JMPL);
69
* fetching instructions from a region not backed by RAM.
44
- tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD);
70
*/
45
- } else {
71
- if (likely(ptb->haddr1 != NULL && ptb->vaddr2 == -1) &&
46
- s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
72
- unlikely((db->pc_next & TARGET_PAGE_MASK) !=
47
- tcg_out32(s, CALL);
73
- (db->pc_first & TARGET_PAGE_MASK))) {
48
+ qemu_build_assert(TCG_TARGET_HAS_direct_jump);
74
- get_page_addr_code_hostp(cpu->env_ptr, db->pc_next,
49
+ /* Direct jump. */
75
- &ptb->haddr2);
50
+ if (USE_REG_TB) {
76
- ptb->vaddr2 = db->pc_next;
51
+ /* make sure the patch is 8-byte aligned. */
77
- }
52
+ if ((intptr_t)s->code_ptr & 4) {
78
- if (likely(ptb->vaddr2 == -1)) {
53
tcg_out_nop(s);
79
+ if (ptb->haddr1 == NULL) {
54
}
80
+ pinsn->haddr = NULL;
55
+ s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
81
+ } else if (is_same_page(db, db->pc_next)) {
56
+ tcg_out_sethi(s, TCG_REG_T1, 0);
82
pinsn->haddr = ptb->haddr1 + pinsn->vaddr - ptb->vaddr;
57
+ tcg_out_arithi(s, TCG_REG_T1, TCG_REG_T1, 0, ARITH_OR);
83
} else {
58
+ tcg_out_arith(s, TCG_REG_G0, TCG_REG_TB, TCG_REG_T1, JMPL);
84
+ if (ptb->vaddr2 == -1) {
59
+ tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD);
85
+ ptb->vaddr2 = TARGET_PAGE_ALIGN(db->pc_first);
60
} else {
86
+ get_page_addr_code_hostp(cpu->env_ptr, ptb->vaddr2, &ptb->haddr2);
61
- /* indirect jump method */
87
+ }
62
- tcg_out_ld_ptr(s, TCG_REG_TB, s->tb_jmp_target_addr + a0);
88
pinsn->haddr = ptb->haddr2 + pinsn->vaddr - ptb->vaddr2;
63
- tcg_out_arithi(s, TCG_REG_G0, TCG_REG_TB, 0, JMPL);
89
}
64
+ s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
90
}
65
+ tcg_out32(s, CALL);
91
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
66
tcg_out_nop(s);
92
index XXXXXXX..XXXXXXX 100644
67
}
93
--- a/accel/tcg/translator.c
68
set_jmp_reset_offset(s, a0);
94
+++ b/accel/tcg/translator.c
95
@@ -XXX,XX +XXX,XX @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
96
ops->tb_start(db, cpu);
97
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
98
99
- plugin_enabled = plugin_gen_tb_start(cpu, tb, cflags & CF_MEMI_ONLY);
100
+ plugin_enabled = plugin_gen_tb_start(cpu, db, cflags & CF_MEMI_ONLY);
101
102
while (true) {
103
db->num_insns++;
104
--
69
--
105
2.34.1
70
2.34.1
106
71
107
72
diff view generated by jsdifflib
1
Allow the target to cache items from the guest page tables.
1
Test TCG_TARGET_HAS_direct_jump instead of testing an
2
implementation pointer.
2
3
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.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/cpu-defs.h | 9 +++++++++
8
tcg/aarch64/tcg-target.c.inc | 2 +-
9
1 file changed, 9 insertions(+)
9
tcg/arm/tcg-target.c.inc | 2 +-
10
tcg/loongarch64/tcg-target.c.inc | 2 +-
11
tcg/mips/tcg-target.c.inc | 2 +-
12
tcg/riscv/tcg-target.c.inc | 2 +-
13
tcg/tci/tcg-target.c.inc | 2 +-
14
6 files changed, 6 insertions(+), 6 deletions(-)
10
15
11
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
16
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/include/exec/cpu-defs.h
18
--- a/tcg/aarch64/tcg-target.c.inc
14
+++ b/include/exec/cpu-defs.h
19
+++ b/tcg/aarch64/tcg-target.c.inc
15
@@ -XXX,XX +XXX,XX @@ typedef struct CPUTLBEntryFull {
20
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
16
21
17
/* @lg_page_size contains the log2 of the page size. */
22
switch (opc) {
18
uint8_t lg_page_size;
23
case INDEX_op_goto_tb:
19
+
24
- tcg_debug_assert(s->tb_jmp_insn_offset != NULL);
20
+ /*
25
+ qemu_build_assert(TCG_TARGET_HAS_direct_jump);
21
+ * Allow target-specific additions to this structure.
26
/*
22
+ * This may be used to cache items from the guest cpu
27
* Ensure that ADRP+ADD are 8-byte aligned so that an atomic
23
+ * page tables for later use by the implementation.
28
* write can be used to patch the target address.
24
+ */
29
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
25
+#ifdef TARGET_PAGE_ENTRY_EXTRA
30
index XXXXXXX..XXXXXXX 100644
26
+ TARGET_PAGE_ENTRY_EXTRA
31
--- a/tcg/arm/tcg-target.c.inc
27
+#endif
32
+++ b/tcg/arm/tcg-target.c.inc
28
} CPUTLBEntryFull;
33
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
29
34
intptr_t ptr, dif, dil;
30
/*
35
TCGReg base = TCG_REG_PC;
36
37
- tcg_debug_assert(s->tb_jmp_insn_offset == 0);
38
+ qemu_build_assert(!TCG_TARGET_HAS_direct_jump);
39
ptr = (intptr_t)tcg_splitwx_to_rx(s->tb_jmp_target_addr + args[0]);
40
dif = tcg_pcrel_diff(s, (void *)ptr) - 8;
41
dil = sextract32(dif, 0, 12);
42
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
43
index XXXXXXX..XXXXXXX 100644
44
--- a/tcg/loongarch64/tcg-target.c.inc
45
+++ b/tcg/loongarch64/tcg-target.c.inc
46
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
47
48
switch (opc) {
49
case INDEX_op_goto_tb:
50
- tcg_debug_assert(s->tb_jmp_insn_offset != NULL);
51
+ qemu_build_assert(TCG_TARGET_HAS_direct_jump);
52
/*
53
* Ensure that patch area is 8-byte aligned so that an
54
* atomic write can be used to patch the target address.
55
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
56
index XXXXXXX..XXXXXXX 100644
57
--- a/tcg/mips/tcg-target.c.inc
58
+++ b/tcg/mips/tcg-target.c.inc
59
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
60
switch (opc) {
61
case INDEX_op_goto_tb:
62
/* indirect jump method */
63
- tcg_debug_assert(s->tb_jmp_insn_offset == 0);
64
+ qemu_build_assert(!TCG_TARGET_HAS_direct_jump);
65
tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_REG_ZERO,
66
(uintptr_t)(s->tb_jmp_target_addr + a0));
67
tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
68
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
69
index XXXXXXX..XXXXXXX 100644
70
--- a/tcg/riscv/tcg-target.c.inc
71
+++ b/tcg/riscv/tcg-target.c.inc
72
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
73
74
switch (opc) {
75
case INDEX_op_goto_tb:
76
- assert(s->tb_jmp_insn_offset == 0);
77
+ qemu_build_assert(!TCG_TARGET_HAS_direct_jump);
78
/* indirect jump method */
79
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO,
80
(uintptr_t)(s->tb_jmp_target_addr + a0));
81
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
82
index XXXXXXX..XXXXXXX 100644
83
--- a/tcg/tci/tcg-target.c.inc
84
+++ b/tcg/tci/tcg-target.c.inc
85
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
86
87
switch (opc) {
88
case INDEX_op_goto_tb:
89
- tcg_debug_assert(s->tb_jmp_insn_offset == 0);
90
+ qemu_build_assert(!TCG_TARGET_HAS_direct_jump);
91
/* indirect jump method. */
92
tcg_out_op_p(s, opc, s->tb_jmp_target_addr + args[0]);
93
set_jmp_reset_offset(s, args[0]);
31
--
94
--
32
2.34.1
95
2.34.1
33
96
34
97
diff view generated by jsdifflib
1
When PAGE_WRITE_INV is set when calling tlb_set_page,
1
Similar to the existing set_jmp_reset_offset. Move any assert for
2
we immediately set TLB_INVALID_MASK in order to force
2
TCG_TARGET_HAS_direct_jump into the new function (which now cannot
3
tlb_fill to be called on the next lookup. Here in
3
be build-time). Will be unused if TCG_TARGET_HAS_direct_jump is
4
probe_access_internal, we have just called tlb_fill
4
constant 0, but we can't test for constant in the preprocessor,
5
and eliminated true misses, thus the lookup must be valid.
5
so just mark it G_GNUC_UNUSED.
6
7
This allows us to remove a warning comment from s390x.
8
There doesn't seem to be a reason to change the code though.
9
6
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Reviewed-by: David Hildenbrand <david@redhat.com>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
---
9
---
15
accel/tcg/cputlb.c | 10 +++++++++-
10
tcg/tcg.c | 10 ++++++++++
16
target/s390x/tcg/mem_helper.c | 4 ----
11
tcg/aarch64/tcg-target.c.inc | 3 +--
17
2 files changed, 9 insertions(+), 5 deletions(-)
12
tcg/i386/tcg-target.c.inc | 3 +--
13
tcg/loongarch64/tcg-target.c.inc | 3 +--
14
tcg/ppc/tcg-target.c.inc | 7 +++----
15
tcg/s390x/tcg-target.c.inc | 2 +-
16
tcg/sparc64/tcg-target.c.inc | 5 ++---
17
7 files changed, 19 insertions(+), 14 deletions(-)
18
18
19
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
19
diff --git a/tcg/tcg.c b/tcg/tcg.c
20
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
21
--- a/accel/tcg/cputlb.c
21
--- a/tcg/tcg.c
22
+++ b/accel/tcg/cputlb.c
22
+++ b/tcg/tcg.c
23
@@ -XXX,XX +XXX,XX @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
23
@@ -XXX,XX +XXX,XX @@ static void set_jmp_reset_offset(TCGContext *s, int which)
24
}
24
s->tb_jmp_reset_offset[which] = tcg_current_code_size(s);
25
tlb_addr = tlb_read_ofs(entry, elt_ofs);
25
}
26
26
27
+ flags = TLB_FLAGS_MASK;
27
+static void G_GNUC_UNUSED set_jmp_insn_offset(TCGContext *s, int which)
28
page_addr = addr & TARGET_PAGE_MASK;
28
+{
29
if (!tlb_hit_page(tlb_addr, page_addr)) {
29
+ /*
30
if (!victim_tlb_hit(env, mmu_idx, index, elt_ofs, page_addr)) {
30
+ * We will check for overflow at the end of the opcode loop in
31
@@ -XXX,XX +XXX,XX @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
31
+ * tcg_gen_code, where we bound tcg_current_code_size to UINT16_MAX.
32
32
+ */
33
/* TLB resize via tlb_fill may have moved the entry. */
33
+ tcg_debug_assert(TCG_TARGET_HAS_direct_jump);
34
entry = tlb_entry(env, mmu_idx, addr);
34
+ s->tb_jmp_insn_offset[which] = tcg_current_code_size(s);
35
+}
35
+
36
+
36
+ /*
37
/* Signal overflow, starting over with fewer guest insns. */
37
+ * With PAGE_WRITE_INV, we set TLB_INVALID_MASK immediately,
38
static G_NORETURN
38
+ * to force the next access through tlb_fill. We've just
39
void tcg_raise_tb_overflow(TCGContext *s)
39
+ * called tlb_fill, so we know that this entry *is* valid.
40
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
40
+ */
41
index XXXXXXX..XXXXXXX 100644
41
+ flags &= ~TLB_INVALID_MASK;
42
--- a/tcg/aarch64/tcg-target.c.inc
43
+++ b/tcg/aarch64/tcg-target.c.inc
44
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
45
46
switch (opc) {
47
case INDEX_op_goto_tb:
48
- qemu_build_assert(TCG_TARGET_HAS_direct_jump);
49
/*
50
* Ensure that ADRP+ADD are 8-byte aligned so that an atomic
51
* write can be used to patch the target address.
52
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
53
if ((uintptr_t)s->code_ptr & 7) {
54
tcg_out32(s, NOP);
42
}
55
}
43
tlb_addr = tlb_read_ofs(entry, elt_ofs);
56
- s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
44
}
57
+ set_jmp_insn_offset(s, a0);
45
- flags = tlb_addr & TLB_FLAGS_MASK;
58
/*
46
+ flags &= tlb_addr;
59
* actual branch destination will be patched by
47
60
* tb_target_set_jmp_target later
48
/* Fold all "mmio-like" bits into TLB_MMIO. This is not RAM. */
61
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
49
if (unlikely(flags & ~(TLB_WATCHPOINT | TLB_NOTDIRTY))) {
50
diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c
51
index XXXXXXX..XXXXXXX 100644
62
index XXXXXXX..XXXXXXX 100644
52
--- a/target/s390x/tcg/mem_helper.c
63
--- a/tcg/i386/tcg-target.c.inc
53
+++ b/target/s390x/tcg/mem_helper.c
64
+++ b/tcg/i386/tcg-target.c.inc
54
@@ -XXX,XX +XXX,XX @@ static int s390_probe_access(CPUArchState *env, target_ulong addr, int size,
65
@@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
55
#else
66
56
int flags;
67
switch (opc) {
57
68
case INDEX_op_goto_tb:
58
- /*
69
- qemu_build_assert(TCG_TARGET_HAS_direct_jump);
59
- * For !CONFIG_USER_ONLY, we cannot rely on TLB_INVALID_MASK or haddr==NULL
70
{
60
- * to detect if there was an exception during tlb_fill().
71
/*
61
- */
72
* Jump displacement must be aligned for atomic patching;
62
env->tlb_fill_exc = 0;
73
@@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
63
flags = probe_access_flags(env, addr, access_type, mmu_idx, nonfault, phost,
74
tcg_out_nopn(s, gap - 1);
64
ra);
75
}
76
tcg_out8(s, OPC_JMP_long); /* jmp im */
77
- s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
78
+ set_jmp_insn_offset(s, a0);
79
tcg_out32(s, 0);
80
}
81
set_jmp_reset_offset(s, a0);
82
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
83
index XXXXXXX..XXXXXXX 100644
84
--- a/tcg/loongarch64/tcg-target.c.inc
85
+++ b/tcg/loongarch64/tcg-target.c.inc
86
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
87
88
switch (opc) {
89
case INDEX_op_goto_tb:
90
- qemu_build_assert(TCG_TARGET_HAS_direct_jump);
91
/*
92
* Ensure that patch area is 8-byte aligned so that an
93
* atomic write can be used to patch the target address.
94
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
95
if ((uintptr_t)s->code_ptr & 7) {
96
tcg_out_nop(s);
97
}
98
- s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
99
+ set_jmp_insn_offset(s, a0);
100
/*
101
* actual branch destination will be patched by
102
* tb_target_set_jmp_target later
103
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
104
index XXXXXXX..XXXXXXX 100644
105
--- a/tcg/ppc/tcg-target.c.inc
106
+++ b/tcg/ppc/tcg-target.c.inc
107
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
108
109
switch (opc) {
110
case INDEX_op_goto_tb:
111
- qemu_build_assert(TCG_TARGET_HAS_direct_jump);
112
/* Direct jump. */
113
if (TCG_TARGET_REG_BITS == 64) {
114
/* Ensure the next insns are 8 or 16-byte aligned. */
115
while ((uintptr_t)s->code_ptr & (have_isa_2_07 ? 15 : 7)) {
116
tcg_out32(s, NOP);
117
}
118
- s->tb_jmp_insn_offset[args[0]] = tcg_current_code_size(s);
119
+ set_jmp_insn_offset(s, args[0]);
120
tcg_out32(s, ADDIS | TAI(TCG_REG_TB, TCG_REG_TB, 0));
121
tcg_out32(s, ADDI | TAI(TCG_REG_TB, TCG_REG_TB, 0));
122
} else {
123
- s->tb_jmp_insn_offset[args[0]] = tcg_current_code_size(s);
124
+ set_jmp_insn_offset(s, args[0]);
125
tcg_out32(s, B);
126
- s->tb_jmp_reset_offset[args[0]] = tcg_current_code_size(s);
127
+ set_jmp_reset_offset(s, args[0]);
128
break;
129
}
130
tcg_out32(s, MTSPR | RS(TCG_REG_TB) | CTR);
131
diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc
132
index XXXXXXX..XXXXXXX 100644
133
--- a/tcg/s390x/tcg-target.c.inc
134
+++ b/tcg/s390x/tcg-target.c.inc
135
@@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
136
tcg_out16(s, NOP);
137
}
138
tcg_out16(s, RIL_BRCL | (S390_CC_ALWAYS << 4));
139
- s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
140
+ set_jmp_insn_offset(s, a0);
141
s->code_ptr += 2;
142
set_jmp_reset_offset(s, a0);
143
break;
144
diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc
145
index XXXXXXX..XXXXXXX 100644
146
--- a/tcg/sparc64/tcg-target.c.inc
147
+++ b/tcg/sparc64/tcg-target.c.inc
148
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
149
150
switch (opc) {
151
case INDEX_op_goto_tb:
152
- qemu_build_assert(TCG_TARGET_HAS_direct_jump);
153
/* Direct jump. */
154
if (USE_REG_TB) {
155
/* make sure the patch is 8-byte aligned. */
156
if ((intptr_t)s->code_ptr & 4) {
157
tcg_out_nop(s);
158
}
159
- s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
160
+ set_jmp_insn_offset(s, a0);
161
tcg_out_sethi(s, TCG_REG_T1, 0);
162
tcg_out_arithi(s, TCG_REG_T1, TCG_REG_T1, 0, ARITH_OR);
163
tcg_out_arith(s, TCG_REG_G0, TCG_REG_TB, TCG_REG_T1, JMPL);
164
tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD);
165
} else {
166
- s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
167
+ set_jmp_insn_offset(s, a0);
168
tcg_out32(s, CALL);
169
tcg_out_nop(s);
170
}
65
--
171
--
66
2.34.1
172
2.34.1
67
173
68
174
diff view generated by jsdifflib
1
Add an interface to return the CPUTLBEntryFull struct
1
Similar to the existing set_jmp_reset_offset. Include the
2
that goes with the lookup. The result is not intended
2
rw->rx address space conversion done by arm and s390x, and
3
to be valid across multiple lookups, so the user must
3
forgotten by mips and riscv.
4
use the results immediately.
5
4
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
---
8
---
11
include/exec/exec-all.h | 15 +++++++++++++
9
tcg/tcg.c | 9 +++++++++
12
include/qemu/typedefs.h | 1 +
10
tcg/arm/tcg-target.c.inc | 2 +-
13
accel/tcg/cputlb.c | 47 +++++++++++++++++++++++++----------------
11
tcg/mips/tcg-target.c.inc | 2 +-
14
3 files changed, 45 insertions(+), 18 deletions(-)
12
tcg/riscv/tcg-target.c.inc | 2 +-
13
tcg/tci/tcg-target.c.inc | 2 +-
14
5 files changed, 13 insertions(+), 4 deletions(-)
15
15
16
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
16
diff --git a/tcg/tcg.c b/tcg/tcg.c
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/exec/exec-all.h
18
--- a/tcg/tcg.c
19
+++ b/include/exec/exec-all.h
19
+++ b/tcg/tcg.c
20
@@ -XXX,XX +XXX,XX @@ int probe_access_flags(CPUArchState *env, target_ulong addr,
20
@@ -XXX,XX +XXX,XX @@ static void G_GNUC_UNUSED set_jmp_insn_offset(TCGContext *s, int which)
21
MMUAccessType access_type, int mmu_idx,
21
s->tb_jmp_insn_offset[which] = tcg_current_code_size(s);
22
bool nonfault, void **phost, uintptr_t retaddr);
23
24
+#ifndef CONFIG_USER_ONLY
25
+/**
26
+ * probe_access_full:
27
+ * Like probe_access_flags, except also return into @pfull.
28
+ *
29
+ * The CPUTLBEntryFull structure returned via @pfull is transient
30
+ * and must be consumed or copied immediately, before any further
31
+ * access or changes to TLB @mmu_idx.
32
+ */
33
+int probe_access_full(CPUArchState *env, target_ulong addr,
34
+ MMUAccessType access_type, int mmu_idx,
35
+ bool nonfault, void **phost,
36
+ CPUTLBEntryFull **pfull, uintptr_t retaddr);
37
+#endif
38
+
39
#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
40
41
/* Estimated block size for TB allocation. */
42
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
43
index XXXXXXX..XXXXXXX 100644
44
--- a/include/qemu/typedefs.h
45
+++ b/include/qemu/typedefs.h
46
@@ -XXX,XX +XXX,XX @@ typedef struct ConfidentialGuestSupport ConfidentialGuestSupport;
47
typedef struct CPUAddressSpace CPUAddressSpace;
48
typedef struct CPUArchState CPUArchState;
49
typedef struct CPUState CPUState;
50
+typedef struct CPUTLBEntryFull CPUTLBEntryFull;
51
typedef struct DeviceListener DeviceListener;
52
typedef struct DeviceState DeviceState;
53
typedef struct DirtyBitmapSnapshot DirtyBitmapSnapshot;
54
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/accel/tcg/cputlb.c
57
+++ b/accel/tcg/cputlb.c
58
@@ -XXX,XX +XXX,XX @@ static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size,
59
static int probe_access_internal(CPUArchState *env, target_ulong addr,
60
int fault_size, MMUAccessType access_type,
61
int mmu_idx, bool nonfault,
62
- void **phost, uintptr_t retaddr)
63
+ void **phost, CPUTLBEntryFull **pfull,
64
+ uintptr_t retaddr)
65
{
66
uintptr_t index = tlb_index(env, mmu_idx, addr);
67
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
68
@@ -XXX,XX +XXX,XX @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
69
mmu_idx, nonfault, retaddr)) {
70
/* Non-faulting page table read failed. */
71
*phost = NULL;
72
+ *pfull = NULL;
73
return TLB_INVALID_MASK;
74
}
75
76
/* TLB resize via tlb_fill may have moved the entry. */
77
+ index = tlb_index(env, mmu_idx, addr);
78
entry = tlb_entry(env, mmu_idx, addr);
79
80
/*
81
@@ -XXX,XX +XXX,XX @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
82
}
83
flags &= tlb_addr;
84
85
+ *pfull = &env_tlb(env)->d[mmu_idx].fulltlb[index];
86
+
87
/* Fold all "mmio-like" bits into TLB_MMIO. This is not RAM. */
88
if (unlikely(flags & ~(TLB_WATCHPOINT | TLB_NOTDIRTY))) {
89
*phost = NULL;
90
@@ -XXX,XX +XXX,XX @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
91
return flags;
92
}
22
}
93
23
94
-int probe_access_flags(CPUArchState *env, target_ulong addr,
24
+static uintptr_t G_GNUC_UNUSED get_jmp_target_addr(TCGContext *s, int which)
95
- MMUAccessType access_type, int mmu_idx,
96
- bool nonfault, void **phost, uintptr_t retaddr)
97
+int probe_access_full(CPUArchState *env, target_ulong addr,
98
+ MMUAccessType access_type, int mmu_idx,
99
+ bool nonfault, void **phost, CPUTLBEntryFull **pfull,
100
+ uintptr_t retaddr)
101
{
102
- int flags;
103
-
104
- flags = probe_access_internal(env, addr, 0, access_type, mmu_idx,
105
- nonfault, phost, retaddr);
106
+ int flags = probe_access_internal(env, addr, 0, access_type, mmu_idx,
107
+ nonfault, phost, pfull, retaddr);
108
109
/* Handle clean RAM pages. */
110
if (unlikely(flags & TLB_NOTDIRTY)) {
111
- uintptr_t index = tlb_index(env, mmu_idx, addr);
112
- CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
113
-
114
- notdirty_write(env_cpu(env), addr, 1, full, retaddr);
115
+ notdirty_write(env_cpu(env), addr, 1, *pfull, retaddr);
116
flags &= ~TLB_NOTDIRTY;
117
}
118
119
return flags;
120
}
121
122
+int probe_access_flags(CPUArchState *env, target_ulong addr,
123
+ MMUAccessType access_type, int mmu_idx,
124
+ bool nonfault, void **phost, uintptr_t retaddr)
125
+{
25
+{
126
+ CPUTLBEntryFull *full;
26
+ /*
127
+
27
+ * Return the read-execute version of the pointer, for the benefit
128
+ return probe_access_full(env, addr, access_type, mmu_idx,
28
+ * of any pc-relative addressing mode.
129
+ nonfault, phost, &full, retaddr);
29
+ */
30
+ return (uintptr_t)tcg_splitwx_to_rx(&s->tb_jmp_target_addr[which]);
130
+}
31
+}
131
+
32
+
132
void *probe_access(CPUArchState *env, target_ulong addr, int size,
33
/* Signal overflow, starting over with fewer guest insns. */
133
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
34
static G_NORETURN
134
{
35
void tcg_raise_tb_overflow(TCGContext *s)
135
+ CPUTLBEntryFull *full;
36
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
136
void *host;
37
index XXXXXXX..XXXXXXX 100644
137
int flags;
38
--- a/tcg/arm/tcg-target.c.inc
138
39
+++ b/tcg/arm/tcg-target.c.inc
139
g_assert(-(addr | TARGET_PAGE_MASK) >= size);
40
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
140
41
TCGReg base = TCG_REG_PC;
141
flags = probe_access_internal(env, addr, size, access_type, mmu_idx,
42
142
- false, &host, retaddr);
43
qemu_build_assert(!TCG_TARGET_HAS_direct_jump);
143
+ false, &host, &full, retaddr);
44
- ptr = (intptr_t)tcg_splitwx_to_rx(s->tb_jmp_target_addr + args[0]);
144
45
+ ptr = get_jmp_target_addr(s, args[0]);
145
/* Per the interface, size == 0 merely faults the access. */
46
dif = tcg_pcrel_diff(s, (void *)ptr) - 8;
146
if (size == 0) {
47
dil = sextract32(dif, 0, 12);
147
@@ -XXX,XX +XXX,XX @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
48
if (dif != dil) {
148
}
49
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
149
50
index XXXXXXX..XXXXXXX 100644
150
if (unlikely(flags & (TLB_NOTDIRTY | TLB_WATCHPOINT))) {
51
--- a/tcg/mips/tcg-target.c.inc
151
- uintptr_t index = tlb_index(env, mmu_idx, addr);
52
+++ b/tcg/mips/tcg-target.c.inc
152
- CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
53
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
153
-
54
/* indirect jump method */
154
/* Handle watchpoints. */
55
qemu_build_assert(!TCG_TARGET_HAS_direct_jump);
155
if (flags & TLB_WATCHPOINT) {
56
tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_REG_ZERO,
156
int wp_access = (access_type == MMU_DATA_STORE
57
- (uintptr_t)(s->tb_jmp_target_addr + a0));
157
@@ -XXX,XX +XXX,XX @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
58
+ get_jmp_target_addr(s, a0));
158
void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
59
tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
159
MMUAccessType access_type, int mmu_idx)
60
tcg_out_nop(s);
160
{
61
set_jmp_reset_offset(s, a0);
161
+ CPUTLBEntryFull *full;
62
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
162
void *host;
63
index XXXXXXX..XXXXXXX 100644
163
int flags;
64
--- a/tcg/riscv/tcg-target.c.inc
164
65
+++ b/tcg/riscv/tcg-target.c.inc
165
flags = probe_access_internal(env, addr, 0, access_type,
66
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
166
- mmu_idx, true, &host, 0);
67
qemu_build_assert(!TCG_TARGET_HAS_direct_jump);
167
+ mmu_idx, true, &host, &full, 0);
68
/* indirect jump method */
168
69
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO,
169
/* No combination of flags are expected by the caller. */
70
- (uintptr_t)(s->tb_jmp_target_addr + a0));
170
return flags ? NULL : host;
71
+ get_jmp_target_addr(s, a0));
171
@@ -XXX,XX +XXX,XX @@ void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
72
tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_TMP0, 0);
172
tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
73
set_jmp_reset_offset(s, a0);
173
void **hostp)
74
break;
174
{
75
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
175
+ CPUTLBEntryFull *full;
76
index XXXXXXX..XXXXXXX 100644
176
void *p;
77
--- a/tcg/tci/tcg-target.c.inc
177
78
+++ b/tcg/tci/tcg-target.c.inc
178
(void)probe_access_internal(env, addr, 1, MMU_INST_FETCH,
79
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
179
- cpu_mmu_index(env, true), false, &p, 0);
80
case INDEX_op_goto_tb:
180
+ cpu_mmu_index(env, true), false, &p, &full, 0);
81
qemu_build_assert(!TCG_TARGET_HAS_direct_jump);
181
if (p == NULL) {
82
/* indirect jump method. */
182
return -1;
83
- tcg_out_op_p(s, opc, s->tb_jmp_target_addr + args[0]);
183
}
84
+ tcg_out_op_p(s, opc, (void *)get_jmp_target_addr(s, args[0]));
85
set_jmp_reset_offset(s, args[0]);
86
break;
87
184
--
88
--
185
2.34.1
89
2.34.1
186
90
187
91
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
The INDEX_op_goto_tb opcode needs no register allocation.
2
Split out a dedicated helper function for it.
2
3
3
This is a heavily used function so lets avoid the cost of
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
CPU_GET_CLASS. On the romulus-bmc run it has a modest effect:
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
6
Before: 36.812 s ± 0.506 s
7
After: 35.912 s ± 0.168 s
8
9
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-Id: <20220811151413.3350684-4-alex.bennee@linaro.org>
12
Signed-off-by: Cédric Le Goater <clg@kaod.org>
13
Message-Id: <20220923084803.498337-4-clg@kaod.org>
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
---
7
---
16
hw/core/cpu-sysemu.c | 5 ++---
8
tcg/tcg.c | 4 ++
17
1 file changed, 2 insertions(+), 3 deletions(-)
9
tcg/aarch64/tcg-target.c.inc | 40 ++++++++++---------
10
tcg/arm/tcg-target.c.inc | 49 ++++++++++++-----------
11
tcg/i386/tcg-target.c.inc | 33 ++++++++--------
12
tcg/loongarch64/tcg-target.c.inc | 38 +++++++++---------
13
tcg/mips/tcg-target.c.inc | 21 +++++-----
14
tcg/ppc/tcg-target.c.inc | 52 ++++++++++++------------
15
tcg/riscv/tcg-target.c.inc | 20 +++++-----
16
tcg/s390x/tcg-target.c.inc | 31 ++++++++-------
17
tcg/sparc64/tcg-target.c.inc | 68 +++++++++++++++++---------------
18
tcg/tci/tcg-target.c.inc | 16 ++++----
19
11 files changed, 199 insertions(+), 173 deletions(-)
18
20
19
diff --git a/hw/core/cpu-sysemu.c b/hw/core/cpu-sysemu.c
21
diff --git a/tcg/tcg.c b/tcg/tcg.c
20
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/core/cpu-sysemu.c
23
--- a/tcg/tcg.c
22
+++ b/hw/core/cpu-sysemu.c
24
+++ b/tcg/tcg.c
23
@@ -XXX,XX +XXX,XX @@ hwaddr cpu_get_phys_page_debug(CPUState *cpu, vaddr addr)
25
@@ -XXX,XX +XXX,XX @@ static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
24
26
static void tcg_out_movi(TCGContext *s, TCGType type,
25
int cpu_asidx_from_attrs(CPUState *cpu, MemTxAttrs attrs)
27
TCGReg ret, tcg_target_long arg);
26
{
28
static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg);
27
- CPUClass *cc = CPU_GET_CLASS(cpu);
29
+static void tcg_out_goto_tb(TCGContext *s, int which);
28
int ret = 0;
30
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
29
31
const TCGArg args[TCG_MAX_OP_ARGS],
30
- if (cc->sysemu_ops->asidx_from_attrs) {
32
const int const_args[TCG_MAX_OP_ARGS]);
31
- ret = cc->sysemu_ops->asidx_from_attrs(cpu, attrs);
33
@@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, target_ulong pc_start)
32
+ if (cpu->cc->sysemu_ops->asidx_from_attrs) {
34
case INDEX_op_exit_tb:
33
+ ret = cpu->cc->sysemu_ops->asidx_from_attrs(cpu, attrs);
35
tcg_out_exit_tb(s, op->args[0]);
34
assert(ret < cpu->num_ases && ret >= 0);
36
break;
35
}
37
+ case INDEX_op_goto_tb:
36
return ret;
38
+ tcg_out_goto_tb(s, op->args[0]);
39
+ break;
40
case INDEX_op_dup2_vec:
41
if (tcg_reg_alloc_dup2(s, op)) {
42
break;
43
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
44
index XXXXXXX..XXXXXXX 100644
45
--- a/tcg/aarch64/tcg-target.c.inc
46
+++ b/tcg/aarch64/tcg-target.c.inc
47
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
48
}
49
}
50
51
+static void tcg_out_goto_tb(TCGContext *s, int which)
52
+{
53
+ /*
54
+ * Ensure that ADRP+ADD are 8-byte aligned so that an atomic
55
+ * write can be used to patch the target address.
56
+ */
57
+ if ((uintptr_t)s->code_ptr & 7) {
58
+ tcg_out32(s, NOP);
59
+ }
60
+ set_jmp_insn_offset(s, which);
61
+ /*
62
+ * actual branch destination will be patched by
63
+ * tb_target_set_jmp_target later
64
+ */
65
+ tcg_out_insn(s, 3406, ADRP, TCG_REG_TMP, 0);
66
+ tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_TMP, TCG_REG_TMP, 0);
67
+ tcg_out_insn(s, 3207, BR, TCG_REG_TMP);
68
+ set_jmp_reset_offset(s, which);
69
+}
70
+
71
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
72
const TCGArg args[TCG_MAX_OP_ARGS],
73
const int const_args[TCG_MAX_OP_ARGS])
74
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
75
#define REG0(I) (const_args[I] ? TCG_REG_XZR : (TCGReg)args[I])
76
77
switch (opc) {
78
- case INDEX_op_goto_tb:
79
- /*
80
- * Ensure that ADRP+ADD are 8-byte aligned so that an atomic
81
- * write can be used to patch the target address.
82
- */
83
- if ((uintptr_t)s->code_ptr & 7) {
84
- tcg_out32(s, NOP);
85
- }
86
- set_jmp_insn_offset(s, a0);
87
- /*
88
- * actual branch destination will be patched by
89
- * tb_target_set_jmp_target later
90
- */
91
- tcg_out_insn(s, 3406, ADRP, TCG_REG_TMP, 0);
92
- tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_TMP, TCG_REG_TMP, 0);
93
- tcg_out_insn(s, 3207, BR, TCG_REG_TMP);
94
- set_jmp_reset_offset(s, a0);
95
- break;
96
-
97
case INDEX_op_goto_ptr:
98
tcg_out_insn(s, 3207, BR, a0);
99
break;
100
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
101
case INDEX_op_mov_i64:
102
case INDEX_op_call: /* Always emitted via tcg_out_call. */
103
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
104
+ case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
105
default:
106
g_assert_not_reached();
107
}
108
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
109
index XXXXXXX..XXXXXXX 100644
110
--- a/tcg/arm/tcg-target.c.inc
111
+++ b/tcg/arm/tcg-target.c.inc
112
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg)
113
tcg_out_epilogue(s);
114
}
115
116
+static void tcg_out_goto_tb(TCGContext *s, int which)
117
+{
118
+ /* Indirect jump method */
119
+ intptr_t ptr, dif, dil;
120
+ TCGReg base = TCG_REG_PC;
121
+
122
+ qemu_build_assert(!TCG_TARGET_HAS_direct_jump);
123
+ ptr = get_jmp_target_addr(s, which);
124
+ dif = tcg_pcrel_diff(s, (void *)ptr) - 8;
125
+ dil = sextract32(dif, 0, 12);
126
+ if (dif != dil) {
127
+ /*
128
+ * The TB is close, but outside the 12 bits addressable by
129
+ * the load. We can extend this to 20 bits with a sub of a
130
+ * shifted immediate from pc. In the vastly unlikely event
131
+ * the code requires more than 1MB, we'll use 2 insns and
132
+ * be no worse off.
133
+ */
134
+ base = TCG_REG_R0;
135
+ tcg_out_movi32(s, COND_AL, base, ptr - dil);
136
+ }
137
+ tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, base, dil);
138
+ set_jmp_reset_offset(s, which);
139
+}
140
+
141
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
142
const TCGArg args[TCG_MAX_OP_ARGS],
143
const int const_args[TCG_MAX_OP_ARGS])
144
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
145
int c;
146
147
switch (opc) {
148
- case INDEX_op_goto_tb:
149
- {
150
- /* Indirect jump method */
151
- intptr_t ptr, dif, dil;
152
- TCGReg base = TCG_REG_PC;
153
-
154
- qemu_build_assert(!TCG_TARGET_HAS_direct_jump);
155
- ptr = get_jmp_target_addr(s, args[0]);
156
- dif = tcg_pcrel_diff(s, (void *)ptr) - 8;
157
- dil = sextract32(dif, 0, 12);
158
- if (dif != dil) {
159
- /* The TB is close, but outside the 12 bits addressable by
160
- the load. We can extend this to 20 bits with a sub of a
161
- shifted immediate from pc. In the vastly unlikely event
162
- the code requires more than 1MB, we'll use 2 insns and
163
- be no worse off. */
164
- base = TCG_REG_R0;
165
- tcg_out_movi32(s, COND_AL, base, ptr - dil);
166
- }
167
- tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, base, dil);
168
- set_jmp_reset_offset(s, args[0]);
169
- }
170
- break;
171
case INDEX_op_goto_ptr:
172
tcg_out_b_reg(s, COND_AL, args[0]);
173
break;
174
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
175
case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
176
case INDEX_op_call: /* Always emitted via tcg_out_call. */
177
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
178
+ case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
179
default:
180
tcg_abort();
181
}
182
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
183
index XXXXXXX..XXXXXXX 100644
184
--- a/tcg/i386/tcg-target.c.inc
185
+++ b/tcg/i386/tcg-target.c.inc
186
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
187
}
188
}
189
190
+static void tcg_out_goto_tb(TCGContext *s, int which)
191
+{
192
+ /*
193
+ * Jump displacement must be aligned for atomic patching;
194
+ * see if we need to add extra nops before jump
195
+ */
196
+ int gap = QEMU_ALIGN_PTR_UP(s->code_ptr + 1, 4) - s->code_ptr;
197
+ if (gap != 1) {
198
+ tcg_out_nopn(s, gap - 1);
199
+ }
200
+ tcg_out8(s, OPC_JMP_long); /* jmp im */
201
+ set_jmp_insn_offset(s, which);
202
+ tcg_out32(s, 0);
203
+ set_jmp_reset_offset(s, which);
204
+}
205
+
206
static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
207
const TCGArg args[TCG_MAX_OP_ARGS],
208
const int const_args[TCG_MAX_OP_ARGS])
209
@@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
210
const_a2 = const_args[2];
211
212
switch (opc) {
213
- case INDEX_op_goto_tb:
214
- {
215
- /*
216
- * Jump displacement must be aligned for atomic patching;
217
- * see if we need to add extra nops before jump
218
- */
219
- int gap = QEMU_ALIGN_PTR_UP(s->code_ptr + 1, 4) - s->code_ptr;
220
- if (gap != 1) {
221
- tcg_out_nopn(s, gap - 1);
222
- }
223
- tcg_out8(s, OPC_JMP_long); /* jmp im */
224
- set_jmp_insn_offset(s, a0);
225
- tcg_out32(s, 0);
226
- }
227
- set_jmp_reset_offset(s, a0);
228
- break;
229
case INDEX_op_goto_ptr:
230
/* jmp to the given host address (could be epilogue) */
231
tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, a0);
232
@@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
233
case INDEX_op_mov_i64:
234
case INDEX_op_call: /* Always emitted via tcg_out_call. */
235
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
236
+ case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
237
default:
238
tcg_abort();
239
}
240
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
241
index XXXXXXX..XXXXXXX 100644
242
--- a/tcg/loongarch64/tcg-target.c.inc
243
+++ b/tcg/loongarch64/tcg-target.c.inc
244
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
245
}
246
}
247
248
+static void tcg_out_goto_tb(TCGContext *s, int which)
249
+{
250
+ /*
251
+ * Ensure that patch area is 8-byte aligned so that an
252
+ * atomic write can be used to patch the target address.
253
+ */
254
+ if ((uintptr_t)s->code_ptr & 7) {
255
+ tcg_out_nop(s);
256
+ }
257
+ set_jmp_insn_offset(s, which);
258
+ /*
259
+ * actual branch destination will be patched by
260
+ * tb_target_set_jmp_target later
261
+ */
262
+ tcg_out_opc_pcaddu18i(s, TCG_REG_TMP0, 0);
263
+ tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_TMP0, 0);
264
+ set_jmp_reset_offset(s, which);
265
+}
266
+
267
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
268
const TCGArg args[TCG_MAX_OP_ARGS],
269
const int const_args[TCG_MAX_OP_ARGS])
270
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
271
int c2 = const_args[2];
272
273
switch (opc) {
274
- case INDEX_op_goto_tb:
275
- /*
276
- * Ensure that patch area is 8-byte aligned so that an
277
- * atomic write can be used to patch the target address.
278
- */
279
- if ((uintptr_t)s->code_ptr & 7) {
280
- tcg_out_nop(s);
281
- }
282
- set_jmp_insn_offset(s, a0);
283
- /*
284
- * actual branch destination will be patched by
285
- * tb_target_set_jmp_target later
286
- */
287
- tcg_out_opc_pcaddu18i(s, TCG_REG_TMP0, 0);
288
- tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_TMP0, 0);
289
- set_jmp_reset_offset(s, a0);
290
- break;
291
-
292
case INDEX_op_mb:
293
tcg_out_mb(s, a0);
294
break;
295
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
296
case INDEX_op_mov_i64:
297
case INDEX_op_call: /* Always emitted via tcg_out_call. */
298
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
299
+ case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
300
default:
301
g_assert_not_reached();
302
}
303
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
304
index XXXXXXX..XXXXXXX 100644
305
--- a/tcg/mips/tcg-target.c.inc
306
+++ b/tcg/mips/tcg-target.c.inc
307
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
308
tcg_out_opc_imm(s, OPC_ORI, TCG_REG_V0, b0, a0 & 0xffff);
309
}
310
311
+static void tcg_out_goto_tb(TCGContext *s, int which)
312
+{
313
+ /* indirect jump method */
314
+ qemu_build_assert(!TCG_TARGET_HAS_direct_jump);
315
+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_REG_ZERO,
316
+ get_jmp_target_addr(s, which));
317
+ tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
318
+ tcg_out_nop(s);
319
+ set_jmp_reset_offset(s, which);
320
+}
321
+
322
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
323
const TCGArg args[TCG_MAX_OP_ARGS],
324
const int const_args[TCG_MAX_OP_ARGS])
325
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
326
c2 = const_args[2];
327
328
switch (opc) {
329
- case INDEX_op_goto_tb:
330
- /* indirect jump method */
331
- qemu_build_assert(!TCG_TARGET_HAS_direct_jump);
332
- tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_REG_ZERO,
333
- get_jmp_target_addr(s, a0));
334
- tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
335
- tcg_out_nop(s);
336
- set_jmp_reset_offset(s, a0);
337
- break;
338
case INDEX_op_goto_ptr:
339
/* jmp to the given host address (could be epilogue) */
340
tcg_out_opc_reg(s, OPC_JR, 0, a0, 0);
341
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
342
case INDEX_op_mov_i64:
343
case INDEX_op_call: /* Always emitted via tcg_out_call. */
344
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
345
+ case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
346
default:
347
tcg_abort();
348
}
349
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
350
index XXXXXXX..XXXXXXX 100644
351
--- a/tcg/ppc/tcg-target.c.inc
352
+++ b/tcg/ppc/tcg-target.c.inc
353
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg)
354
tcg_out_b(s, 0, tcg_code_gen_epilogue);
355
}
356
357
+static void tcg_out_goto_tb(TCGContext *s, int which)
358
+{
359
+ /* Direct jump. */
360
+ if (TCG_TARGET_REG_BITS == 64) {
361
+ /* Ensure the next insns are 8 or 16-byte aligned. */
362
+ while ((uintptr_t)s->code_ptr & (have_isa_2_07 ? 15 : 7)) {
363
+ tcg_out32(s, NOP);
364
+ }
365
+ set_jmp_insn_offset(s, which);
366
+ tcg_out32(s, ADDIS | TAI(TCG_REG_TB, TCG_REG_TB, 0));
367
+ tcg_out32(s, ADDI | TAI(TCG_REG_TB, TCG_REG_TB, 0));
368
+ tcg_out32(s, MTSPR | RS(TCG_REG_TB) | CTR);
369
+ tcg_out32(s, BCCTR | BO_ALWAYS);
370
+ set_jmp_reset_offset(s, which);
371
+ if (USE_REG_TB) {
372
+ /* For the unlinked case, need to reset TCG_REG_TB. */
373
+ tcg_out_mem_long(s, ADDI, ADD, TCG_REG_TB, TCG_REG_TB,
374
+ -tcg_current_code_size(s));
375
+ }
376
+ } else {
377
+ set_jmp_insn_offset(s, which);
378
+ tcg_out32(s, B);
379
+ set_jmp_reset_offset(s, which);
380
+ }
381
+}
382
+
383
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
384
const TCGArg args[TCG_MAX_OP_ARGS],
385
const int const_args[TCG_MAX_OP_ARGS])
386
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
387
TCGArg a0, a1, a2;
388
389
switch (opc) {
390
- case INDEX_op_goto_tb:
391
- /* Direct jump. */
392
- if (TCG_TARGET_REG_BITS == 64) {
393
- /* Ensure the next insns are 8 or 16-byte aligned. */
394
- while ((uintptr_t)s->code_ptr & (have_isa_2_07 ? 15 : 7)) {
395
- tcg_out32(s, NOP);
396
- }
397
- set_jmp_insn_offset(s, args[0]);
398
- tcg_out32(s, ADDIS | TAI(TCG_REG_TB, TCG_REG_TB, 0));
399
- tcg_out32(s, ADDI | TAI(TCG_REG_TB, TCG_REG_TB, 0));
400
- } else {
401
- set_jmp_insn_offset(s, args[0]);
402
- tcg_out32(s, B);
403
- set_jmp_reset_offset(s, args[0]);
404
- break;
405
- }
406
- tcg_out32(s, MTSPR | RS(TCG_REG_TB) | CTR);
407
- tcg_out32(s, BCCTR | BO_ALWAYS);
408
- set_jmp_reset_offset(s, args[0]);
409
- if (USE_REG_TB) {
410
- /* For the unlinked case, need to reset TCG_REG_TB. */
411
- tcg_out_mem_long(s, ADDI, ADD, TCG_REG_TB, TCG_REG_TB,
412
- -tcg_current_code_size(s));
413
- }
414
- break;
415
case INDEX_op_goto_ptr:
416
tcg_out32(s, MTSPR | RS(args[0]) | CTR);
417
if (USE_REG_TB) {
418
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
419
case INDEX_op_mov_i64:
420
case INDEX_op_call: /* Always emitted via tcg_out_call. */
421
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
422
+ case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
423
default:
424
tcg_abort();
425
}
426
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
427
index XXXXXXX..XXXXXXX 100644
428
--- a/tcg/riscv/tcg-target.c.inc
429
+++ b/tcg/riscv/tcg-target.c.inc
430
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
431
}
432
}
433
434
+static void tcg_out_goto_tb(TCGContext *s, int which)
435
+{
436
+ qemu_build_assert(!TCG_TARGET_HAS_direct_jump);
437
+ /* indirect jump method */
438
+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO,
439
+ get_jmp_target_addr(s, which));
440
+ tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_TMP0, 0);
441
+ set_jmp_reset_offset(s, which);
442
+}
443
+
444
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
445
const TCGArg args[TCG_MAX_OP_ARGS],
446
const int const_args[TCG_MAX_OP_ARGS])
447
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
448
int c2 = const_args[2];
449
450
switch (opc) {
451
- case INDEX_op_goto_tb:
452
- qemu_build_assert(!TCG_TARGET_HAS_direct_jump);
453
- /* indirect jump method */
454
- tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO,
455
- get_jmp_target_addr(s, a0));
456
- tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_TMP0, 0);
457
- set_jmp_reset_offset(s, a0);
458
- break;
459
-
460
case INDEX_op_goto_ptr:
461
tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, a0, 0);
462
break;
463
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
464
case INDEX_op_mov_i64:
465
case INDEX_op_call: /* Always emitted via tcg_out_call. */
466
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
467
+ case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
468
default:
469
g_assert_not_reached();
470
}
471
diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc
472
index XXXXXXX..XXXXXXX 100644
473
--- a/tcg/s390x/tcg-target.c.inc
474
+++ b/tcg/s390x/tcg-target.c.inc
475
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
476
}
477
}
478
479
+static void tcg_out_goto_tb(TCGContext *s, int which)
480
+{
481
+ /*
482
+ * Branch displacement must be aligned for atomic patching;
483
+ * see if we need to add extra nop before branch
484
+ */
485
+ if (!QEMU_PTR_IS_ALIGNED(s->code_ptr + 1, 4)) {
486
+ tcg_out16(s, NOP);
487
+ }
488
+ tcg_out16(s, RIL_BRCL | (S390_CC_ALWAYS << 4));
489
+ set_jmp_insn_offset(s, which);
490
+ s->code_ptr += 2;
491
+ set_jmp_reset_offset(s, which);
492
+}
493
+
494
# define OP_32_64(x) \
495
case glue(glue(INDEX_op_,x),_i32): \
496
case glue(glue(INDEX_op_,x),_i64)
497
@@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
498
TCGArg a0, a1, a2;
499
500
switch (opc) {
501
- case INDEX_op_goto_tb:
502
- a0 = args[0];
503
- /*
504
- * branch displacement must be aligned for atomic patching;
505
- * see if we need to add extra nop before branch
506
- */
507
- if (!QEMU_PTR_IS_ALIGNED(s->code_ptr + 1, 4)) {
508
- tcg_out16(s, NOP);
509
- }
510
- tcg_out16(s, RIL_BRCL | (S390_CC_ALWAYS << 4));
511
- set_jmp_insn_offset(s, a0);
512
- s->code_ptr += 2;
513
- set_jmp_reset_offset(s, a0);
514
- break;
515
-
516
case INDEX_op_goto_ptr:
517
a0 = args[0];
518
tcg_out_insn(s, RR, BCR, S390_CC_ALWAYS, a0);
519
@@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
520
case INDEX_op_mov_i64:
521
case INDEX_op_call: /* Always emitted via tcg_out_call. */
522
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
523
+ case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
524
default:
525
tcg_abort();
526
}
527
diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc
528
index XXXXXXX..XXXXXXX 100644
529
--- a/tcg/sparc64/tcg-target.c.inc
530
+++ b/tcg/sparc64/tcg-target.c.inc
531
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
532
tcg_out_arithi(s, TCG_REG_O0, TCG_REG_O0, a0 & 0x3ff, ARITH_OR);
533
}
534
535
+static void tcg_out_goto_tb(TCGContext *s, int which)
536
+{
537
+ /* Direct jump. */
538
+ if (USE_REG_TB) {
539
+ /* make sure the patch is 8-byte aligned. */
540
+ if ((intptr_t)s->code_ptr & 4) {
541
+ tcg_out_nop(s);
542
+ }
543
+ set_jmp_insn_offset(s, which);
544
+ tcg_out_sethi(s, TCG_REG_T1, 0);
545
+ tcg_out_arithi(s, TCG_REG_T1, TCG_REG_T1, 0, ARITH_OR);
546
+ tcg_out_arith(s, TCG_REG_G0, TCG_REG_TB, TCG_REG_T1, JMPL);
547
+ tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD);
548
+ } else {
549
+ set_jmp_insn_offset(s, which);
550
+ tcg_out32(s, CALL);
551
+ tcg_out_nop(s);
552
+ }
553
+ set_jmp_reset_offset(s, which);
554
+
555
+ /*
556
+ * For the unlinked path of goto_tb, we need to reset TCG_REG_TB
557
+ * to the beginning of this TB.
558
+ */
559
+ if (USE_REG_TB) {
560
+ int c = -tcg_current_code_size(s);
561
+ if (check_fit_i32(c, 13)) {
562
+ tcg_out_arithi(s, TCG_REG_TB, TCG_REG_TB, c, ARITH_ADD);
563
+ } else {
564
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, c);
565
+ tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD);
566
+ }
567
+ }
568
+}
569
+
570
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
571
const TCGArg args[TCG_MAX_OP_ARGS],
572
const int const_args[TCG_MAX_OP_ARGS])
573
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
574
c2 = const_args[2];
575
576
switch (opc) {
577
- case INDEX_op_goto_tb:
578
- /* Direct jump. */
579
- if (USE_REG_TB) {
580
- /* make sure the patch is 8-byte aligned. */
581
- if ((intptr_t)s->code_ptr & 4) {
582
- tcg_out_nop(s);
583
- }
584
- set_jmp_insn_offset(s, a0);
585
- tcg_out_sethi(s, TCG_REG_T1, 0);
586
- tcg_out_arithi(s, TCG_REG_T1, TCG_REG_T1, 0, ARITH_OR);
587
- tcg_out_arith(s, TCG_REG_G0, TCG_REG_TB, TCG_REG_T1, JMPL);
588
- tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD);
589
- } else {
590
- set_jmp_insn_offset(s, a0);
591
- tcg_out32(s, CALL);
592
- tcg_out_nop(s);
593
- }
594
- set_jmp_reset_offset(s, a0);
595
-
596
- /* For the unlinked path of goto_tb, we need to reset
597
- TCG_REG_TB to the beginning of this TB. */
598
- if (USE_REG_TB) {
599
- c = -tcg_current_code_size(s);
600
- if (check_fit_i32(c, 13)) {
601
- tcg_out_arithi(s, TCG_REG_TB, TCG_REG_TB, c, ARITH_ADD);
602
- } else {
603
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, c);
604
- tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB,
605
- TCG_REG_T1, ARITH_ADD);
606
- }
607
- }
608
- break;
609
case INDEX_op_goto_ptr:
610
tcg_out_arithi(s, TCG_REG_G0, a0, 0, JMPL);
611
if (USE_REG_TB) {
612
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
613
case INDEX_op_mov_i64:
614
case INDEX_op_call: /* Always emitted via tcg_out_call. */
615
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
616
+ case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
617
default:
618
tcg_abort();
619
}
620
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
621
index XXXXXXX..XXXXXXX 100644
622
--- a/tcg/tci/tcg-target.c.inc
623
+++ b/tcg/tci/tcg-target.c.inc
624
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg)
625
tcg_out_op_p(s, INDEX_op_exit_tb, (void *)arg);
626
}
627
628
+static void tcg_out_goto_tb(TCGContext *s, int which)
629
+{
630
+ qemu_build_assert(!TCG_TARGET_HAS_direct_jump);
631
+ /* indirect jump method. */
632
+ tcg_out_op_p(s, INDEX_op_goto_tb, (void *)get_jmp_target_addr(s, which));
633
+ set_jmp_reset_offset(s, which);
634
+}
635
+
636
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
637
const TCGArg args[TCG_MAX_OP_ARGS],
638
const int const_args[TCG_MAX_OP_ARGS])
639
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
640
TCGOpcode exts;
641
642
switch (opc) {
643
- case INDEX_op_goto_tb:
644
- qemu_build_assert(!TCG_TARGET_HAS_direct_jump);
645
- /* indirect jump method. */
646
- tcg_out_op_p(s, opc, (void *)get_jmp_target_addr(s, args[0]));
647
- set_jmp_reset_offset(s, args[0]);
648
- break;
649
-
650
case INDEX_op_goto_ptr:
651
tcg_out_op_r(s, opc, args[0]);
652
break;
653
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
654
case INDEX_op_mov_i64:
655
case INDEX_op_call: /* Always emitted via tcg_out_call. */
656
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
657
+ case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
658
default:
659
tcg_abort();
660
}
37
--
661
--
38
2.34.1
662
2.34.1
39
663
40
664
diff view generated by jsdifflib
1
The availability of tb->pc will shortly be conditional.
1
This will shortly be used for more than reset.
2
Introduce accessor functions to minimize ifdefs.
3
4
Pass around a known pc to places like tcg_gen_code,
5
where the caller must already have the value.
6
2
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Reviewed-by: Alex Bennée <alex.bennee@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
accel/tcg/internal.h | 6 ++++
7
include/exec/exec-all.h | 2 +-
11
include/exec/exec-all.h | 6 ++++
8
accel/tcg/translate-all.c | 8 ++++----
12
include/tcg/tcg.h | 2 +-
9
tcg/tcg.c | 4 ++--
13
accel/tcg/cpu-exec.c | 46 ++++++++++++++-----------
10
3 files changed, 7 insertions(+), 7 deletions(-)
14
accel/tcg/translate-all.c | 37 +++++++++++---------
15
target/arm/cpu.c | 4 +--
16
target/avr/cpu.c | 2 +-
17
target/hexagon/cpu.c | 2 +-
18
target/hppa/cpu.c | 4 +--
19
target/i386/tcg/tcg-cpu.c | 2 +-
20
target/loongarch/cpu.c | 2 +-
21
target/microblaze/cpu.c | 2 +-
22
target/mips/tcg/exception.c | 2 +-
23
target/mips/tcg/sysemu/special_helper.c | 2 +-
24
target/openrisc/cpu.c | 2 +-
25
target/riscv/cpu.c | 4 +--
26
target/rx/cpu.c | 2 +-
27
target/sh4/cpu.c | 4 +--
28
target/sparc/cpu.c | 2 +-
29
target/tricore/cpu.c | 2 +-
30
tcg/tcg.c | 8 ++---
31
21 files changed, 82 insertions(+), 61 deletions(-)
32
11
33
diff --git a/accel/tcg/internal.h b/accel/tcg/internal.h
34
index XXXXXXX..XXXXXXX 100644
35
--- a/accel/tcg/internal.h
36
+++ b/accel/tcg/internal.h
37
@@ -XXX,XX +XXX,XX @@ G_NORETURN void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr);
38
void page_init(void);
39
void tb_htable_init(void);
40
41
+/* Return the current PC from CPU, which may be cached in TB. */
42
+static inline target_ulong log_pc(CPUState *cpu, const TranslationBlock *tb)
43
+{
44
+ return tb_pc(tb);
45
+}
46
+
47
#endif /* ACCEL_TCG_INTERNAL_H */
48
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
12
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
49
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
50
--- a/include/exec/exec-all.h
14
--- a/include/exec/exec-all.h
51
+++ b/include/exec/exec-all.h
15
+++ b/include/exec/exec-all.h
52
@@ -XXX,XX +XXX,XX @@ struct TranslationBlock {
16
@@ -XXX,XX +XXX,XX @@ struct TranslationBlock {
53
uintptr_t jmp_dest[2];
17
* setting one of the jump targets (or patching the jump instruction). Only
54
};
18
* two of such jumps are supported.
55
19
*/
56
+/* Hide the read to avoid ifdefs for TARGET_TB_PCREL. */
20
+#define TB_JMP_OFFSET_INVALID 0xffff /* indicates no jump generated */
57
+static inline target_ulong tb_pc(const TranslationBlock *tb)
21
uint16_t jmp_reset_offset[2]; /* offset of original jump target */
58
+{
22
-#define TB_JMP_RESET_OFFSET_INVALID 0xffff /* indicates no jump generated */
59
+ return tb->pc;
23
uintptr_t jmp_target_arg[2]; /* target address or offset */
60
+}
24
61
+
25
/*
62
/* Hide the qatomic_read to make code a little easier on the eyes */
63
static inline uint32_t tb_cflags(const TranslationBlock *tb)
64
{
65
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
66
index XXXXXXX..XXXXXXX 100644
67
--- a/include/tcg/tcg.h
68
+++ b/include/tcg/tcg.h
69
@@ -XXX,XX +XXX,XX @@ void tcg_register_thread(void);
70
void tcg_prologue_init(TCGContext *s);
71
void tcg_func_start(TCGContext *s);
72
73
-int tcg_gen_code(TCGContext *s, TranslationBlock *tb);
74
+int tcg_gen_code(TCGContext *s, TranslationBlock *tb, target_ulong pc_start);
75
76
void tcg_set_frame(TCGContext *s, TCGReg reg, intptr_t start, intptr_t size);
77
78
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/accel/tcg/cpu-exec.c
81
+++ b/accel/tcg/cpu-exec.c
82
@@ -XXX,XX +XXX,XX @@ static bool tb_lookup_cmp(const void *p, const void *d)
83
const TranslationBlock *tb = p;
84
const struct tb_desc *desc = d;
85
86
- if (tb->pc == desc->pc &&
87
+ if (tb_pc(tb) == desc->pc &&
88
tb->page_addr[0] == desc->page_addr0 &&
89
tb->cs_base == desc->cs_base &&
90
tb->flags == desc->flags &&
91
@@ -XXX,XX +XXX,XX @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
92
return tb;
93
}
94
95
-static inline void log_cpu_exec(target_ulong pc, CPUState *cpu,
96
- const TranslationBlock *tb)
97
+static void log_cpu_exec(target_ulong pc, CPUState *cpu,
98
+ const TranslationBlock *tb)
99
{
100
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_CPU | CPU_LOG_EXEC))
101
- && qemu_log_in_addr_range(pc)) {
102
-
103
+ if (qemu_log_in_addr_range(pc)) {
104
qemu_log_mask(CPU_LOG_EXEC,
105
"Trace %d: %p [" TARGET_FMT_lx
106
"/" TARGET_FMT_lx "/%08x/%08x] %s\n",
107
@@ -XXX,XX +XXX,XX @@ const void *HELPER(lookup_tb_ptr)(CPUArchState *env)
108
return tcg_code_gen_epilogue;
109
}
110
111
- log_cpu_exec(pc, cpu, tb);
112
+ if (qemu_loglevel_mask(CPU_LOG_TB_CPU | CPU_LOG_EXEC)) {
113
+ log_cpu_exec(pc, cpu, tb);
114
+ }
115
116
return tb->tc.ptr;
117
}
118
@@ -XXX,XX +XXX,XX @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit)
119
TranslationBlock *last_tb;
120
const void *tb_ptr = itb->tc.ptr;
121
122
- log_cpu_exec(itb->pc, cpu, itb);
123
+ if (qemu_loglevel_mask(CPU_LOG_TB_CPU | CPU_LOG_EXEC)) {
124
+ log_cpu_exec(log_pc(cpu, itb), cpu, itb);
125
+ }
126
127
qemu_thread_jit_execute();
128
ret = tcg_qemu_tb_exec(env, tb_ptr);
129
@@ -XXX,XX +XXX,XX @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit)
130
* of the start of the TB.
131
*/
132
CPUClass *cc = CPU_GET_CLASS(cpu);
133
- qemu_log_mask_and_addr(CPU_LOG_EXEC, last_tb->pc,
134
- "Stopped execution of TB chain before %p ["
135
- TARGET_FMT_lx "] %s\n",
136
- last_tb->tc.ptr, last_tb->pc,
137
- lookup_symbol(last_tb->pc));
138
+
139
if (cc->tcg_ops->synchronize_from_tb) {
140
cc->tcg_ops->synchronize_from_tb(cpu, last_tb);
141
} else {
142
assert(cc->set_pc);
143
- cc->set_pc(cpu, last_tb->pc);
144
+ cc->set_pc(cpu, tb_pc(last_tb));
145
+ }
146
+ if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
147
+ target_ulong pc = log_pc(cpu, last_tb);
148
+ if (qemu_log_in_addr_range(pc)) {
149
+ qemu_log("Stopped execution of TB chain before %p ["
150
+ TARGET_FMT_lx "] %s\n",
151
+ last_tb->tc.ptr, pc, lookup_symbol(pc));
152
+ }
153
}
154
}
155
156
@@ -XXX,XX +XXX,XX @@ static inline void tb_add_jump(TranslationBlock *tb, int n,
157
158
qemu_spin_unlock(&tb_next->jmp_lock);
159
160
- qemu_log_mask_and_addr(CPU_LOG_EXEC, tb->pc,
161
- "Linking TBs %p [" TARGET_FMT_lx
162
- "] index %d -> %p [" TARGET_FMT_lx "]\n",
163
- tb->tc.ptr, tb->pc, n,
164
- tb_next->tc.ptr, tb_next->pc);
165
+ qemu_log_mask(CPU_LOG_EXEC, "Linking TBs %p index %d -> %p\n",
166
+ tb->tc.ptr, n, tb_next->tc.ptr);
167
return;
168
169
out_unlock_next:
170
@@ -XXX,XX +XXX,XX @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
171
}
172
173
static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
174
+ target_ulong pc,
175
TranslationBlock **last_tb, int *tb_exit)
176
{
177
int32_t insns_left;
178
179
- trace_exec_tb(tb, tb->pc);
180
+ trace_exec_tb(tb, pc);
181
tb = cpu_tb_exec(cpu, tb, tb_exit);
182
if (*tb_exit != TB_EXIT_REQUESTED) {
183
*last_tb = tb;
184
@@ -XXX,XX +XXX,XX @@ int cpu_exec(CPUState *cpu)
185
tb_add_jump(last_tb, tb_exit, tb);
186
}
187
188
- cpu_loop_exec_tb(cpu, tb, &last_tb, &tb_exit);
189
+ cpu_loop_exec_tb(cpu, tb, pc, &last_tb, &tb_exit);
190
191
/* Try to align the host and virtual clocks
192
if the guest is in advance */
193
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
26
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
194
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
195
--- a/accel/tcg/translate-all.c
28
--- a/accel/tcg/translate-all.c
196
+++ b/accel/tcg/translate-all.c
29
+++ b/accel/tcg/translate-all.c
197
@@ -XXX,XX +XXX,XX @@ static int encode_search(TranslationBlock *tb, uint8_t *block)
30
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
198
31
tb->jmp_dest[1] = (uintptr_t)NULL;
199
for (j = 0; j < TARGET_INSN_START_WORDS; ++j) {
32
200
if (i == 0) {
33
/* init original jump addresses which have been set during tcg_gen_code() */
201
- prev = (j == 0 ? tb->pc : 0);
34
- if (tb->jmp_reset_offset[0] != TB_JMP_RESET_OFFSET_INVALID) {
202
+ prev = (j == 0 ? tb_pc(tb) : 0);
35
+ if (tb->jmp_reset_offset[0] != TB_JMP_OFFSET_INVALID) {
203
} else {
36
tb_reset_jump(tb, 0);
204
prev = tcg_ctx->gen_insn_data[i - 1][j];
205
}
206
@@ -XXX,XX +XXX,XX @@ static int encode_search(TranslationBlock *tb, uint8_t *block)
207
static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
208
uintptr_t searched_pc, bool reset_icount)
209
{
210
- target_ulong data[TARGET_INSN_START_WORDS] = { tb->pc };
211
+ target_ulong data[TARGET_INSN_START_WORDS] = { tb_pc(tb) };
212
uintptr_t host_pc = (uintptr_t)tb->tc.ptr;
213
CPUArchState *env = cpu->env_ptr;
214
const uint8_t *p = tb->tc.ptr + tb->tc.size;
215
@@ -XXX,XX +XXX,XX @@ static bool tb_cmp(const void *ap, const void *bp)
216
const TranslationBlock *a = ap;
217
const TranslationBlock *b = bp;
218
219
- return a->pc == b->pc &&
220
+ return tb_pc(a) == tb_pc(b) &&
221
a->cs_base == b->cs_base &&
222
a->flags == b->flags &&
223
(tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) &&
224
@@ -XXX,XX +XXX,XX @@ static void do_tb_invalidate_check(void *p, uint32_t hash, void *userp)
225
TranslationBlock *tb = p;
226
target_ulong addr = *(target_ulong *)userp;
227
228
- if (!(addr + TARGET_PAGE_SIZE <= tb->pc || addr >= tb->pc + tb->size)) {
229
+ if (!(addr + TARGET_PAGE_SIZE <= tb_pc(tb) ||
230
+ addr >= tb_pc(tb) + tb->size)) {
231
printf("ERROR invalidate: address=" TARGET_FMT_lx
232
- " PC=%08lx size=%04x\n", addr, (long)tb->pc, tb->size);
233
+ " PC=%08lx size=%04x\n", addr, (long)tb_pc(tb), tb->size);
234
}
37
}
235
}
38
- if (tb->jmp_reset_offset[1] != TB_JMP_RESET_OFFSET_INVALID) {
236
39
+ if (tb->jmp_reset_offset[1] != TB_JMP_OFFSET_INVALID) {
237
@@ -XXX,XX +XXX,XX @@ static void do_tb_page_check(void *p, uint32_t hash, void *userp)
40
tb_reset_jump(tb, 1);
238
TranslationBlock *tb = p;
239
int flags1, flags2;
240
241
- flags1 = page_get_flags(tb->pc);
242
- flags2 = page_get_flags(tb->pc + tb->size - 1);
243
+ flags1 = page_get_flags(tb_pc(tb));
244
+ flags2 = page_get_flags(tb_pc(tb) + tb->size - 1);
245
if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
246
printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
247
- (long)tb->pc, tb->size, flags1, flags2);
248
+ (long)tb_pc(tb), tb->size, flags1, flags2);
249
}
41
}
250
}
42
251
43
@@ -XXX,XX +XXX,XX @@ static gboolean tb_tree_stats_iter(gpointer key, gpointer value, gpointer data)
252
@@ -XXX,XX +XXX,XX @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
44
if (tb_page_addr1(tb) != -1) {
253
45
tst->cross_page++;
254
/* remove the TB from the hash list */
255
phys_pc = tb->page_addr[0];
256
- h = tb_hash_func(phys_pc, tb->pc, tb->flags, orig_cflags,
257
+ h = tb_hash_func(phys_pc, tb_pc(tb), tb->flags, orig_cflags,
258
tb->trace_vcpu_dstate);
259
if (!qht_remove(&tb_ctx.htable, tb, h)) {
260
return;
261
@@ -XXX,XX +XXX,XX @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
262
}
46
}
263
47
- if (tb->jmp_reset_offset[0] != TB_JMP_RESET_OFFSET_INVALID) {
264
/* add in the hash table */
48
+ if (tb->jmp_reset_offset[0] != TB_JMP_OFFSET_INVALID) {
265
- h = tb_hash_func(phys_pc, tb->pc, tb->flags, tb->cflags,
49
tst->direct_jmp_count++;
266
+ h = tb_hash_func(phys_pc, tb_pc(tb), tb->flags, tb->cflags,
50
- if (tb->jmp_reset_offset[1] != TB_JMP_RESET_OFFSET_INVALID) {
267
tb->trace_vcpu_dstate);
51
+ if (tb->jmp_reset_offset[1] != TB_JMP_OFFSET_INVALID) {
268
qht_insert(&tb_ctx.htable, tb, h, &existing_tb);
52
tst->direct_jmp2_count++;
269
53
}
270
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
271
tcg_ctx->cpu = NULL;
272
max_insns = tb->icount;
273
274
- trace_translate_block(tb, tb->pc, tb->tc.ptr);
275
+ trace_translate_block(tb, pc, tb->tc.ptr);
276
277
/* generate machine code */
278
tb->jmp_reset_offset[0] = TB_JMP_RESET_OFFSET_INVALID;
279
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
280
ti = profile_getclock();
281
#endif
282
283
- gen_code_size = tcg_gen_code(tcg_ctx, tb);
284
+ gen_code_size = tcg_gen_code(tcg_ctx, tb, pc);
285
if (unlikely(gen_code_size < 0)) {
286
error_return:
287
switch (gen_code_size) {
288
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
289
290
#ifdef DEBUG_DISAS
291
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM) &&
292
- qemu_log_in_addr_range(tb->pc)) {
293
+ qemu_log_in_addr_range(pc)) {
294
FILE *logfile = qemu_log_trylock();
295
if (logfile) {
296
int code_size, data_size;
297
@@ -XXX,XX +XXX,XX @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
298
*/
299
cpu->cflags_next_tb = curr_cflags(cpu) | CF_MEMI_ONLY | CF_LAST_IO | n;
300
301
- qemu_log_mask_and_addr(CPU_LOG_EXEC, tb->pc,
302
- "cpu_io_recompile: rewound execution of TB to "
303
- TARGET_FMT_lx "\n", tb->pc);
304
+ if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
305
+ target_ulong pc = log_pc(cpu, tb);
306
+ if (qemu_log_in_addr_range(pc)) {
307
+ qemu_log("cpu_io_recompile: rewound execution of TB to "
308
+ TARGET_FMT_lx "\n", pc);
309
+ }
310
+ }
311
312
cpu_loop_exit_noexc(cpu);
313
}
314
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
315
index XXXXXXX..XXXXXXX 100644
316
--- a/target/arm/cpu.c
317
+++ b/target/arm/cpu.c
318
@@ -XXX,XX +XXX,XX @@ void arm_cpu_synchronize_from_tb(CPUState *cs,
319
* never possible for an AArch64 TB to chain to an AArch32 TB.
320
*/
321
if (is_a64(env)) {
322
- env->pc = tb->pc;
323
+ env->pc = tb_pc(tb);
324
} else {
325
- env->regs[15] = tb->pc;
326
+ env->regs[15] = tb_pc(tb);
327
}
54
}
328
}
329
#endif /* CONFIG_TCG */
330
diff --git a/target/avr/cpu.c b/target/avr/cpu.c
331
index XXXXXXX..XXXXXXX 100644
332
--- a/target/avr/cpu.c
333
+++ b/target/avr/cpu.c
334
@@ -XXX,XX +XXX,XX @@ static void avr_cpu_synchronize_from_tb(CPUState *cs,
335
AVRCPU *cpu = AVR_CPU(cs);
336
CPUAVRState *env = &cpu->env;
337
338
- env->pc_w = tb->pc / 2; /* internally PC points to words */
339
+ env->pc_w = tb_pc(tb) / 2; /* internally PC points to words */
340
}
341
342
static void avr_cpu_reset(DeviceState *ds)
343
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
344
index XXXXXXX..XXXXXXX 100644
345
--- a/target/hexagon/cpu.c
346
+++ b/target/hexagon/cpu.c
347
@@ -XXX,XX +XXX,XX @@ static void hexagon_cpu_synchronize_from_tb(CPUState *cs,
348
{
349
HexagonCPU *cpu = HEXAGON_CPU(cs);
350
CPUHexagonState *env = &cpu->env;
351
- env->gpr[HEX_REG_PC] = tb->pc;
352
+ env->gpr[HEX_REG_PC] = tb_pc(tb);
353
}
354
355
static bool hexagon_cpu_has_work(CPUState *cs)
356
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
357
index XXXXXXX..XXXXXXX 100644
358
--- a/target/hppa/cpu.c
359
+++ b/target/hppa/cpu.c
360
@@ -XXX,XX +XXX,XX @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs,
361
HPPACPU *cpu = HPPA_CPU(cs);
362
363
#ifdef CONFIG_USER_ONLY
364
- cpu->env.iaoq_f = tb->pc;
365
+ cpu->env.iaoq_f = tb_pc(tb);
366
cpu->env.iaoq_b = tb->cs_base;
367
#else
368
/* Recover the IAOQ values from the GVA + PRIV. */
369
@@ -XXX,XX +XXX,XX @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs,
370
int32_t diff = cs_base;
371
372
cpu->env.iasq_f = iasq_f;
373
- cpu->env.iaoq_f = (tb->pc & ~iasq_f) + priv;
374
+ cpu->env.iaoq_f = (tb_pc(tb) & ~iasq_f) + priv;
375
if (diff) {
376
cpu->env.iaoq_b = cpu->env.iaoq_f + diff;
377
}
378
diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c
379
index XXXXXXX..XXXXXXX 100644
380
--- a/target/i386/tcg/tcg-cpu.c
381
+++ b/target/i386/tcg/tcg-cpu.c
382
@@ -XXX,XX +XXX,XX @@ static void x86_cpu_synchronize_from_tb(CPUState *cs,
383
{
384
X86CPU *cpu = X86_CPU(cs);
385
386
- cpu->env.eip = tb->pc - tb->cs_base;
387
+ cpu->env.eip = tb_pc(tb) - tb->cs_base;
388
}
389
390
#ifndef CONFIG_USER_ONLY
391
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
392
index XXXXXXX..XXXXXXX 100644
393
--- a/target/loongarch/cpu.c
394
+++ b/target/loongarch/cpu.c
395
@@ -XXX,XX +XXX,XX @@ static void loongarch_cpu_synchronize_from_tb(CPUState *cs,
396
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
397
CPULoongArchState *env = &cpu->env;
398
399
- env->pc = tb->pc;
400
+ env->pc = tb_pc(tb);
401
}
402
#endif /* CONFIG_TCG */
403
404
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
405
index XXXXXXX..XXXXXXX 100644
406
--- a/target/microblaze/cpu.c
407
+++ b/target/microblaze/cpu.c
408
@@ -XXX,XX +XXX,XX @@ static void mb_cpu_synchronize_from_tb(CPUState *cs,
409
{
410
MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
411
412
- cpu->env.pc = tb->pc;
413
+ cpu->env.pc = tb_pc(tb);
414
cpu->env.iflags = tb->flags & IFLAGS_TB_MASK;
415
}
416
417
diff --git a/target/mips/tcg/exception.c b/target/mips/tcg/exception.c
418
index XXXXXXX..XXXXXXX 100644
419
--- a/target/mips/tcg/exception.c
420
+++ b/target/mips/tcg/exception.c
421
@@ -XXX,XX +XXX,XX @@ void mips_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb)
422
MIPSCPU *cpu = MIPS_CPU(cs);
423
CPUMIPSState *env = &cpu->env;
424
425
- env->active_tc.PC = tb->pc;
426
+ env->active_tc.PC = tb_pc(tb);
427
env->hflags &= ~MIPS_HFLAG_BMASK;
428
env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
429
}
430
diff --git a/target/mips/tcg/sysemu/special_helper.c b/target/mips/tcg/sysemu/special_helper.c
431
index XXXXXXX..XXXXXXX 100644
432
--- a/target/mips/tcg/sysemu/special_helper.c
433
+++ b/target/mips/tcg/sysemu/special_helper.c
434
@@ -XXX,XX +XXX,XX @@ bool mips_io_recompile_replay_branch(CPUState *cs, const TranslationBlock *tb)
435
CPUMIPSState *env = &cpu->env;
436
437
if ((env->hflags & MIPS_HFLAG_BMASK) != 0
438
- && env->active_tc.PC != tb->pc) {
439
+ && env->active_tc.PC != tb_pc(tb)) {
440
env->active_tc.PC -= (env->hflags & MIPS_HFLAG_B16 ? 2 : 4);
441
env->hflags &= ~MIPS_HFLAG_BMASK;
442
return true;
443
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
444
index XXXXXXX..XXXXXXX 100644
445
--- a/target/openrisc/cpu.c
446
+++ b/target/openrisc/cpu.c
447
@@ -XXX,XX +XXX,XX @@ static void openrisc_cpu_synchronize_from_tb(CPUState *cs,
448
{
449
OpenRISCCPU *cpu = OPENRISC_CPU(cs);
450
451
- cpu->env.pc = tb->pc;
452
+ cpu->env.pc = tb_pc(tb);
453
}
454
455
456
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
457
index XXXXXXX..XXXXXXX 100644
458
--- a/target/riscv/cpu.c
459
+++ b/target/riscv/cpu.c
460
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_synchronize_from_tb(CPUState *cs,
461
RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
462
463
if (xl == MXL_RV32) {
464
- env->pc = (int32_t)tb->pc;
465
+ env->pc = (int32_t)tb_pc(tb);
466
} else {
467
- env->pc = tb->pc;
468
+ env->pc = tb_pc(tb);
469
}
470
}
471
472
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
473
index XXXXXXX..XXXXXXX 100644
474
--- a/target/rx/cpu.c
475
+++ b/target/rx/cpu.c
476
@@ -XXX,XX +XXX,XX @@ static void rx_cpu_synchronize_from_tb(CPUState *cs,
477
{
478
RXCPU *cpu = RX_CPU(cs);
479
480
- cpu->env.pc = tb->pc;
481
+ cpu->env.pc = tb_pc(tb);
482
}
483
484
static bool rx_cpu_has_work(CPUState *cs)
485
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
486
index XXXXXXX..XXXXXXX 100644
487
--- a/target/sh4/cpu.c
488
+++ b/target/sh4/cpu.c
489
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_synchronize_from_tb(CPUState *cs,
490
{
491
SuperHCPU *cpu = SUPERH_CPU(cs);
492
493
- cpu->env.pc = tb->pc;
494
+ cpu->env.pc = tb_pc(tb);
495
cpu->env.flags = tb->flags & TB_FLAG_ENVFLAGS_MASK;
496
}
497
498
@@ -XXX,XX +XXX,XX @@ static bool superh_io_recompile_replay_branch(CPUState *cs,
499
CPUSH4State *env = &cpu->env;
500
501
if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
502
- && env->pc != tb->pc) {
503
+ && env->pc != tb_pc(tb)) {
504
env->pc -= 2;
505
env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
506
return true;
507
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
508
index XXXXXXX..XXXXXXX 100644
509
--- a/target/sparc/cpu.c
510
+++ b/target/sparc/cpu.c
511
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_synchronize_from_tb(CPUState *cs,
512
{
513
SPARCCPU *cpu = SPARC_CPU(cs);
514
515
- cpu->env.pc = tb->pc;
516
+ cpu->env.pc = tb_pc(tb);
517
cpu->env.npc = tb->cs_base;
518
}
519
520
diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c
521
index XXXXXXX..XXXXXXX 100644
522
--- a/target/tricore/cpu.c
523
+++ b/target/tricore/cpu.c
524
@@ -XXX,XX +XXX,XX @@ static void tricore_cpu_synchronize_from_tb(CPUState *cs,
525
TriCoreCPU *cpu = TRICORE_CPU(cs);
526
CPUTriCoreState *env = &cpu->env;
527
528
- env->PC = tb->pc;
529
+ env->PC = tb_pc(tb);
530
}
531
532
static void tricore_cpu_reset(DeviceState *dev)
533
diff --git a/tcg/tcg.c b/tcg/tcg.c
55
diff --git a/tcg/tcg.c b/tcg/tcg.c
534
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
535
--- a/tcg/tcg.c
57
--- a/tcg/tcg.c
536
+++ b/tcg/tcg.c
58
+++ b/tcg/tcg.c
537
@@ -XXX,XX +XXX,XX @@ int64_t tcg_cpu_exec_time(void)
59
@@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, target_ulong pc_start)
538
#endif
60
#endif
539
61
540
62
/* Initialize goto_tb jump offsets. */
541
-int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
63
- tb->jmp_reset_offset[0] = TB_JMP_RESET_OFFSET_INVALID;
542
+int tcg_gen_code(TCGContext *s, TranslationBlock *tb, target_ulong pc_start)
64
- tb->jmp_reset_offset[1] = TB_JMP_RESET_OFFSET_INVALID;
543
{
65
+ tb->jmp_reset_offset[0] = TB_JMP_OFFSET_INVALID;
544
#ifdef CONFIG_PROFILER
66
+ tb->jmp_reset_offset[1] = TB_JMP_OFFSET_INVALID;
545
TCGProfile *prof = &s->prof;
67
tcg_ctx->tb_jmp_reset_offset = tb->jmp_reset_offset;
546
@@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
68
if (TCG_TARGET_HAS_direct_jump) {
547
69
tcg_ctx->tb_jmp_insn_offset = tb->jmp_target_arg;
548
#ifdef DEBUG_DISAS
549
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)
550
- && qemu_log_in_addr_range(tb->pc))) {
551
+ && qemu_log_in_addr_range(pc_start))) {
552
FILE *logfile = qemu_log_trylock();
553
if (logfile) {
554
fprintf(logfile, "OP:\n");
555
@@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
556
if (s->nb_indirects > 0) {
557
#ifdef DEBUG_DISAS
558
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_IND)
559
- && qemu_log_in_addr_range(tb->pc))) {
560
+ && qemu_log_in_addr_range(pc_start))) {
561
FILE *logfile = qemu_log_trylock();
562
if (logfile) {
563
fprintf(logfile, "OP before indirect lowering:\n");
564
@@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
565
566
#ifdef DEBUG_DISAS
567
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT)
568
- && qemu_log_in_addr_range(tb->pc))) {
569
+ && qemu_log_in_addr_range(pc_start))) {
570
FILE *logfile = qemu_log_trylock();
571
if (logfile) {
572
fprintf(logfile, "OP after optimization and liveness analysis:\n");
573
--
70
--
574
2.34.1
71
2.34.1
575
72
576
73
diff view generated by jsdifflib
1
Bool is more appropriate type for the alloc parameter.
1
This can replace four other variables that are references
2
into the TranslationBlock structure.
2
3
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.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 | 14 +++++++-------
7
include/tcg/tcg.h | 11 +++--------
8
1 file changed, 7 insertions(+), 7 deletions(-)
8
accel/tcg/translate-all.c | 2 +-
9
tcg/tcg-op.c | 14 +++++++-------
10
tcg/tcg.c | 14 +++-----------
11
4 files changed, 14 insertions(+), 27 deletions(-)
9
12
13
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/tcg/tcg.h
16
+++ b/include/tcg/tcg.h
17
@@ -XXX,XX +XXX,XX @@ struct TCGContext {
18
int nb_indirects;
19
int nb_ops;
20
21
- /* goto_tb support */
22
- tcg_insn_unit *code_buf;
23
- uint16_t *tb_jmp_reset_offset; /* tb->jmp_reset_offset */
24
- uintptr_t *tb_jmp_insn_offset; /* tb->jmp_target_arg if direct_jump */
25
- uintptr_t *tb_jmp_target_addr; /* tb->jmp_target_arg if !direct_jump */
26
-
27
TCGRegSet reserved_regs;
28
- uint32_t tb_cflags; /* cflags of the current TB */
29
intptr_t current_frame_offset;
30
intptr_t frame_start;
31
intptr_t frame_end;
32
TCGTemp *frame_temp;
33
34
- tcg_insn_unit *code_ptr;
35
+ TranslationBlock *gen_tb; /* tb for which code is being generated */
36
+ tcg_insn_unit *code_buf; /* pointer for start of tb */
37
+ tcg_insn_unit *code_ptr; /* pointer for running end of tb */
38
39
#ifdef CONFIG_PROFILER
40
TCGProfile prof;
10
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
41
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
11
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
12
--- a/accel/tcg/translate-all.c
43
--- a/accel/tcg/translate-all.c
13
+++ b/accel/tcg/translate-all.c
44
+++ b/accel/tcg/translate-all.c
14
@@ -XXX,XX +XXX,XX @@ void page_init(void)
45
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
15
#endif
46
tb->trace_vcpu_dstate = *cpu->trace_dstate;
47
tb_set_page_addr0(tb, phys_pc);
48
tb_set_page_addr1(tb, -1);
49
- tcg_ctx->tb_cflags = cflags;
50
+ tcg_ctx->gen_tb = tb;
51
tb_overflow:
52
53
#ifdef CONFIG_PROFILER
54
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/tcg/tcg-op.c
57
+++ b/tcg/tcg-op.c
58
@@ -XXX,XX +XXX,XX @@ void tcg_gen_op6(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3,
59
60
void tcg_gen_mb(TCGBar mb_type)
61
{
62
- if (tcg_ctx->tb_cflags & CF_PARALLEL) {
63
+ if (tcg_ctx->gen_tb->cflags & CF_PARALLEL) {
64
tcg_gen_op1(INDEX_op_mb, mb_type);
65
}
16
}
66
}
17
67
@@ -XXX,XX +XXX,XX @@ void tcg_gen_exit_tb(const TranslationBlock *tb, unsigned idx)
18
-static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc)
68
void tcg_gen_goto_tb(unsigned idx)
19
+static PageDesc *page_find_alloc(tb_page_addr_t index, bool alloc)
20
{
69
{
21
PageDesc *pd;
70
/* We tested CF_NO_GOTO_TB in translator_use_goto_tb. */
22
void **lp;
71
- tcg_debug_assert(!(tcg_ctx->tb_cflags & CF_NO_GOTO_TB));
23
@@ -XXX,XX +XXX,XX @@ static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc)
72
+ tcg_debug_assert(!(tcg_ctx->gen_tb->cflags & CF_NO_GOTO_TB));
24
73
/* We only support two chained exits. */
25
static inline PageDesc *page_find(tb_page_addr_t index)
74
tcg_debug_assert(idx <= TB_EXIT_IDXMAX);
75
#ifdef CONFIG_DEBUG_TCG
76
@@ -XXX,XX +XXX,XX @@ void tcg_gen_lookup_and_goto_ptr(void)
26
{
77
{
27
- return page_find_alloc(index, 0);
78
TCGv_ptr ptr;
28
+ return page_find_alloc(index, false);
79
80
- if (tcg_ctx->tb_cflags & CF_NO_GOTO_PTR) {
81
+ if (tcg_ctx->gen_tb->cflags & CF_NO_GOTO_PTR) {
82
tcg_gen_exit_tb(NULL, 0);
83
return;
84
}
85
@@ -XXX,XX +XXX,XX @@ void tcg_gen_atomic_cmpxchg_i32(TCGv_i32 retv, TCGv addr, TCGv_i32 cmpv,
86
{
87
memop = tcg_canonicalize_memop(memop, 0, 0);
88
89
- if (!(tcg_ctx->tb_cflags & CF_PARALLEL)) {
90
+ if (!(tcg_ctx->gen_tb->cflags & CF_PARALLEL)) {
91
TCGv_i32 t1 = tcg_temp_new_i32();
92
TCGv_i32 t2 = tcg_temp_new_i32();
93
94
@@ -XXX,XX +XXX,XX @@ void tcg_gen_atomic_cmpxchg_i64(TCGv_i64 retv, TCGv addr, TCGv_i64 cmpv,
95
{
96
memop = tcg_canonicalize_memop(memop, 1, 0);
97
98
- if (!(tcg_ctx->tb_cflags & CF_PARALLEL)) {
99
+ if (!(tcg_ctx->gen_tb->cflags & CF_PARALLEL)) {
100
TCGv_i64 t1 = tcg_temp_new_i64();
101
TCGv_i64 t2 = tcg_temp_new_i64();
102
103
@@ -XXX,XX +XXX,XX @@ static void * const table_##NAME[(MO_SIZE | MO_BSWAP) + 1] = { \
104
void tcg_gen_atomic_##NAME##_i32 \
105
(TCGv_i32 ret, TCGv addr, TCGv_i32 val, TCGArg idx, MemOp memop) \
106
{ \
107
- if (tcg_ctx->tb_cflags & CF_PARALLEL) { \
108
+ if (tcg_ctx->gen_tb->cflags & CF_PARALLEL) { \
109
do_atomic_op_i32(ret, addr, val, idx, memop, table_##NAME); \
110
} else { \
111
do_nonatomic_op_i32(ret, addr, val, idx, memop, NEW, \
112
@@ -XXX,XX +XXX,XX @@ void tcg_gen_atomic_##NAME##_i32 \
113
void tcg_gen_atomic_##NAME##_i64 \
114
(TCGv_i64 ret, TCGv addr, TCGv_i64 val, TCGArg idx, MemOp memop) \
115
{ \
116
- if (tcg_ctx->tb_cflags & CF_PARALLEL) { \
117
+ if (tcg_ctx->gen_tb->cflags & CF_PARALLEL) { \
118
do_atomic_op_i64(ret, addr, val, idx, memop, table_##NAME); \
119
} else { \
120
do_nonatomic_op_i64(ret, addr, val, idx, memop, NEW, \
121
diff --git a/tcg/tcg.c b/tcg/tcg.c
122
index XXXXXXX..XXXXXXX 100644
123
--- a/tcg/tcg.c
124
+++ b/tcg/tcg.c
125
@@ -XXX,XX +XXX,XX @@ static void set_jmp_reset_offset(TCGContext *s, int which)
126
* We will check for overflow at the end of the opcode loop in
127
* tcg_gen_code, where we bound tcg_current_code_size to UINT16_MAX.
128
*/
129
- s->tb_jmp_reset_offset[which] = tcg_current_code_size(s);
130
+ s->gen_tb->jmp_reset_offset[which] = tcg_current_code_size(s);
29
}
131
}
30
132
31
static void page_lock_pair(PageDesc **ret_p1, tb_page_addr_t phys1,
133
static void G_GNUC_UNUSED set_jmp_insn_offset(TCGContext *s, int which)
32
- PageDesc **ret_p2, tb_page_addr_t phys2, int alloc);
134
@@ -XXX,XX +XXX,XX @@ static void G_GNUC_UNUSED set_jmp_insn_offset(TCGContext *s, int which)
33
+ PageDesc **ret_p2, tb_page_addr_t phys2, bool alloc);
135
* tcg_gen_code, where we bound tcg_current_code_size to UINT16_MAX.
34
136
*/
35
/* In user-mode page locks aren't used; mmap_lock is enough */
137
tcg_debug_assert(TCG_TARGET_HAS_direct_jump);
36
#ifdef CONFIG_USER_ONLY
138
- s->tb_jmp_insn_offset[which] = tcg_current_code_size(s);
37
@@ -XXX,XX +XXX,XX @@ static inline void page_unlock(PageDesc *pd)
139
+ s->gen_tb->jmp_target_arg[which] = tcg_current_code_size(s);
38
/* lock the page(s) of a TB in the correct acquisition order */
39
static inline void page_lock_tb(const TranslationBlock *tb)
40
{
41
- page_lock_pair(NULL, tb->page_addr[0], NULL, tb->page_addr[1], 0);
42
+ page_lock_pair(NULL, tb->page_addr[0], NULL, tb->page_addr[1], false);
43
}
140
}
44
141
45
static inline void page_unlock_tb(const TranslationBlock *tb)
142
static uintptr_t G_GNUC_UNUSED get_jmp_target_addr(TCGContext *s, int which)
46
@@ -XXX,XX +XXX,XX @@ void page_collection_unlock(struct page_collection *set)
143
@@ -XXX,XX +XXX,XX @@ static uintptr_t G_GNUC_UNUSED get_jmp_target_addr(TCGContext *s, int which)
47
#endif /* !CONFIG_USER_ONLY */
144
* Return the read-execute version of the pointer, for the benefit
48
145
* of any pc-relative addressing mode.
49
static void page_lock_pair(PageDesc **ret_p1, tb_page_addr_t phys1,
50
- PageDesc **ret_p2, tb_page_addr_t phys2, int alloc)
51
+ PageDesc **ret_p2, tb_page_addr_t phys2, bool alloc)
52
{
53
PageDesc *p1, *p2;
54
tb_page_addr_t page1;
55
@@ -XXX,XX +XXX,XX @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
56
* Note that inserting into the hash table first isn't an option, since
57
* we can only insert TBs that are fully initialized.
58
*/
146
*/
59
- page_lock_pair(&p, phys_pc, &p2, phys_page2, 1);
147
- return (uintptr_t)tcg_splitwx_to_rx(&s->tb_jmp_target_addr[which]);
60
+ page_lock_pair(&p, phys_pc, &p2, phys_page2, true);
148
+ return (uintptr_t)tcg_splitwx_to_rx(s->gen_tb->jmp_target_arg + which);
61
tb_page_add(p, tb, 0, phys_pc & TARGET_PAGE_MASK);
149
}
62
if (p2) {
150
63
tb_page_add(p2, tb, 1, phys_page2);
151
/* Signal overflow, starting over with fewer guest insns. */
64
@@ -XXX,XX +XXX,XX @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
152
@@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, target_ulong pc_start)
65
for (addr = start, len = end - start;
153
/* Initialize goto_tb jump offsets. */
66
len != 0;
154
tb->jmp_reset_offset[0] = TB_JMP_OFFSET_INVALID;
67
len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
155
tb->jmp_reset_offset[1] = TB_JMP_OFFSET_INVALID;
68
- PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
156
- tcg_ctx->tb_jmp_reset_offset = tb->jmp_reset_offset;
69
+ PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS, true);
157
- if (TCG_TARGET_HAS_direct_jump) {
70
158
- tcg_ctx->tb_jmp_insn_offset = tb->jmp_target_arg;
71
/* If the write protection bit is set, then we invalidate
159
- tcg_ctx->tb_jmp_target_addr = NULL;
72
the code inside. */
160
- } else {
161
- tcg_ctx->tb_jmp_insn_offset = NULL;
162
- tcg_ctx->tb_jmp_target_addr = tb->jmp_target_arg;
163
- }
164
165
tcg_reg_alloc_start(s);
166
73
--
167
--
74
2.34.1
168
2.34.1
75
169
76
170
diff view generated by jsdifflib
1
Prepare for targets to be able to produce TBs that can
1
Stop overloading jmp_target_arg for both offset and address,
2
run in more than one virtual context.
2
depending on TCG_TARGET_HAS_direct_jump. Instead, add a new
3
field to hold the jump insn offset and always set the target
4
address in jmp_target_addr[]. This will allow a tcg backend
5
to use either direct or indirect depending on displacement.
3
6
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
9
---
7
accel/tcg/internal.h | 4 +++
10
include/exec/exec-all.h | 3 ++-
8
accel/tcg/tb-jmp-cache.h | 41 +++++++++++++++++++++++++
11
accel/tcg/cpu-exec.c | 5 ++---
9
include/exec/cpu-defs.h | 3 ++
12
tcg/tcg.c | 6 ++++--
10
include/exec/exec-all.h | 32 ++++++++++++++++++--
13
3 files changed, 8 insertions(+), 6 deletions(-)
11
accel/tcg/cpu-exec.c | 16 ++++++----
12
accel/tcg/translate-all.c | 64 ++++++++++++++++++++++++++-------------
13
6 files changed, 131 insertions(+), 29 deletions(-)
14
14
15
diff --git a/accel/tcg/internal.h b/accel/tcg/internal.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/accel/tcg/internal.h
18
+++ b/accel/tcg/internal.h
19
@@ -XXX,XX +XXX,XX @@ void tb_htable_init(void);
20
/* Return the current PC from CPU, which may be cached in TB. */
21
static inline target_ulong log_pc(CPUState *cpu, const TranslationBlock *tb)
22
{
23
+#if TARGET_TB_PCREL
24
+ return cpu->cc->get_pc(cpu);
25
+#else
26
return tb_pc(tb);
27
+#endif
28
}
29
30
#endif /* ACCEL_TCG_INTERNAL_H */
31
diff --git a/accel/tcg/tb-jmp-cache.h b/accel/tcg/tb-jmp-cache.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/accel/tcg/tb-jmp-cache.h
34
+++ b/accel/tcg/tb-jmp-cache.h
35
@@ -XXX,XX +XXX,XX @@
36
37
/*
38
* Accessed in parallel; all accesses to 'tb' must be atomic.
39
+ * For TARGET_TB_PCREL, accesses to 'pc' must be protected by
40
+ * a load_acquire/store_release to 'tb'.
41
*/
42
struct CPUJumpCache {
43
struct {
44
TranslationBlock *tb;
45
+#if TARGET_TB_PCREL
46
+ target_ulong pc;
47
+#endif
48
} array[TB_JMP_CACHE_SIZE];
49
};
50
51
+static inline TranslationBlock *
52
+tb_jmp_cache_get_tb(CPUJumpCache *jc, uint32_t hash)
53
+{
54
+#if TARGET_TB_PCREL
55
+ /* Use acquire to ensure current load of pc from jc. */
56
+ return qatomic_load_acquire(&jc->array[hash].tb);
57
+#else
58
+ /* Use rcu_read to ensure current load of pc from *tb. */
59
+ return qatomic_rcu_read(&jc->array[hash].tb);
60
+#endif
61
+}
62
+
63
+static inline target_ulong
64
+tb_jmp_cache_get_pc(CPUJumpCache *jc, uint32_t hash, TranslationBlock *tb)
65
+{
66
+#if TARGET_TB_PCREL
67
+ return jc->array[hash].pc;
68
+#else
69
+ return tb_pc(tb);
70
+#endif
71
+}
72
+
73
+static inline void
74
+tb_jmp_cache_set(CPUJumpCache *jc, uint32_t hash,
75
+ TranslationBlock *tb, target_ulong pc)
76
+{
77
+#if TARGET_TB_PCREL
78
+ jc->array[hash].pc = pc;
79
+ /* Use store_release on tb to ensure pc is written first. */
80
+ qatomic_store_release(&jc->array[hash].tb, tb);
81
+#else
82
+ /* Use the pc value already stored in tb->pc. */
83
+ qatomic_set(&jc->array[hash].tb, tb);
84
+#endif
85
+}
86
+
87
#endif /* ACCEL_TCG_TB_JMP_CACHE_H */
88
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
89
index XXXXXXX..XXXXXXX 100644
90
--- a/include/exec/cpu-defs.h
91
+++ b/include/exec/cpu-defs.h
92
@@ -XXX,XX +XXX,XX @@
93
# error TARGET_PAGE_BITS must be defined in cpu-param.h
94
# endif
95
#endif
96
+#ifndef TARGET_TB_PCREL
97
+# define TARGET_TB_PCREL 0
98
+#endif
99
100
#define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8)
101
102
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
15
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
103
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
104
--- a/include/exec/exec-all.h
17
--- a/include/exec/exec-all.h
105
+++ b/include/exec/exec-all.h
18
+++ b/include/exec/exec-all.h
106
@@ -XXX,XX +XXX,XX @@ struct tb_tc {
107
};
108
109
struct TranslationBlock {
110
- target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */
111
- target_ulong cs_base; /* CS base for this block */
112
+#if !TARGET_TB_PCREL
113
+ /*
114
+ * Guest PC corresponding to this block. This must be the true
115
+ * virtual address. Therefore e.g. x86 stores EIP + CS_BASE, and
116
+ * targets like Arm, MIPS, HP-PA, which reuse low bits for ISA or
117
+ * privilege, must store those bits elsewhere.
118
+ *
119
+ * If TARGET_TB_PCREL, the opcodes for the TranslationBlock are
120
+ * written such that the TB is associated only with the physical
121
+ * page and may be run in any virtual address context. In this case,
122
+ * PC must always be taken from ENV in a target-specific manner.
123
+ * Unwind information is taken as offsets from the page, to be
124
+ * deposited into the "current" PC.
125
+ */
126
+ target_ulong pc;
127
+#endif
128
+
129
+ /*
130
+ * Target-specific data associated with the TranslationBlock, e.g.:
131
+ * x86: the original user, the Code Segment virtual base,
132
+ * arm: an extension of tb->flags,
133
+ * s390x: instruction data for EXECUTE,
134
+ * sparc: the next pc of the instruction queue (for delay slots).
135
+ */
136
+ target_ulong cs_base;
137
+
138
uint32_t flags; /* flags defining in which context the code was generated */
139
uint32_t cflags; /* compile flags */
140
141
@@ -XXX,XX +XXX,XX @@ struct TranslationBlock {
19
@@ -XXX,XX +XXX,XX @@ struct TranslationBlock {
142
/* Hide the read to avoid ifdefs for TARGET_TB_PCREL. */
20
*/
143
static inline target_ulong tb_pc(const TranslationBlock *tb)
21
#define TB_JMP_OFFSET_INVALID 0xffff /* indicates no jump generated */
144
{
22
uint16_t jmp_reset_offset[2]; /* offset of original jump target */
145
+#if TARGET_TB_PCREL
23
- uintptr_t jmp_target_arg[2]; /* target address or offset */
146
+ qemu_build_not_reached();
24
+ uint16_t jmp_insn_offset[2]; /* offset of direct jump insn */
147
+#else
25
+ uintptr_t jmp_target_addr[2]; /* target address */
148
return tb->pc;
26
149
+#endif
27
/*
150
}
28
* Each TB has a NULL-terminated list (jmp_list_head) of incoming jumps.
151
152
/* Hide the qatomic_read to make code a little easier on the eyes */
153
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
29
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
154
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
155
--- a/accel/tcg/cpu-exec.c
31
--- a/accel/tcg/cpu-exec.c
156
+++ b/accel/tcg/cpu-exec.c
32
+++ b/accel/tcg/cpu-exec.c
157
@@ -XXX,XX +XXX,XX @@ static bool tb_lookup_cmp(const void *p, const void *d)
33
@@ -XXX,XX +XXX,XX @@ void cpu_exec_step_atomic(CPUState *cpu)
158
const TranslationBlock *tb = p;
34
159
const struct tb_desc *desc = d;
35
void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr)
160
36
{
161
- if (tb_pc(tb) == desc->pc &&
37
+ tb->jmp_target_addr[n] = addr;
162
+ if ((TARGET_TB_PCREL || tb_pc(tb) == desc->pc) &&
38
if (TCG_TARGET_HAS_direct_jump) {
163
tb->page_addr[0] == desc->page_addr0 &&
39
- uintptr_t offset = tb->jmp_target_arg[n];
164
tb->cs_base == desc->cs_base &&
40
+ uintptr_t offset = tb->jmp_insn_offset[n];
165
tb->flags == desc->flags &&
41
uintptr_t tc_ptr = (uintptr_t)tb->tc.ptr;
166
@@ -XXX,XX +XXX,XX @@ static TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
42
uintptr_t jmp_rx = tc_ptr + offset;
167
return NULL;
43
uintptr_t jmp_rw = jmp_rx - tcg_splitwx_diff;
44
tb_target_set_jmp_target(tc_ptr, jmp_rx, jmp_rw, addr);
45
- } else {
46
- tb->jmp_target_arg[n] = addr;
168
}
47
}
169
desc.page_addr0 = phys_pc;
170
- h = tb_hash_func(phys_pc, pc, flags, cflags, *cpu->trace_dstate);
171
+ h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : pc),
172
+ flags, cflags, *cpu->trace_dstate);
173
return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp);
174
}
48
}
175
49
176
@@ -XXX,XX +XXX,XX @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
50
diff --git a/tcg/tcg.c b/tcg/tcg.c
177
uint32_t flags, uint32_t cflags)
51
index XXXXXXX..XXXXXXX 100644
178
{
52
--- a/tcg/tcg.c
179
TranslationBlock *tb;
53
+++ b/tcg/tcg.c
180
+ CPUJumpCache *jc;
54
@@ -XXX,XX +XXX,XX @@ static void G_GNUC_UNUSED set_jmp_insn_offset(TCGContext *s, int which)
181
uint32_t hash;
55
* tcg_gen_code, where we bound tcg_current_code_size to UINT16_MAX.
182
56
*/
183
/* we should never be trying to look up an INVALID tb */
57
tcg_debug_assert(TCG_TARGET_HAS_direct_jump);
184
tcg_debug_assert(!(cflags & CF_INVALID));
58
- s->gen_tb->jmp_target_arg[which] = tcg_current_code_size(s);
185
59
+ s->gen_tb->jmp_insn_offset[which] = tcg_current_code_size(s);
186
hash = tb_jmp_cache_hash_func(pc);
187
- tb = qatomic_rcu_read(&cpu->tb_jmp_cache->array[hash].tb);
188
+ jc = cpu->tb_jmp_cache;
189
+ tb = tb_jmp_cache_get_tb(jc, hash);
190
191
if (likely(tb &&
192
- tb->pc == pc &&
193
+ tb_jmp_cache_get_pc(jc, hash, tb) == pc &&
194
tb->cs_base == cs_base &&
195
tb->flags == flags &&
196
tb->trace_vcpu_dstate == *cpu->trace_dstate &&
197
@@ -XXX,XX +XXX,XX @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
198
if (tb == NULL) {
199
return NULL;
200
}
201
- qatomic_set(&cpu->tb_jmp_cache->array[hash].tb, tb);
202
+ tb_jmp_cache_set(jc, hash, tb, pc);
203
return tb;
204
}
60
}
205
61
206
@@ -XXX,XX +XXX,XX @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit)
62
static uintptr_t G_GNUC_UNUSED get_jmp_target_addr(TCGContext *s, int which)
207
if (cc->tcg_ops->synchronize_from_tb) {
63
@@ -XXX,XX +XXX,XX @@ static uintptr_t G_GNUC_UNUSED get_jmp_target_addr(TCGContext *s, int which)
208
cc->tcg_ops->synchronize_from_tb(cpu, last_tb);
64
* Return the read-execute version of the pointer, for the benefit
209
} else {
65
* of any pc-relative addressing mode.
210
+ assert(!TARGET_TB_PCREL);
66
*/
211
assert(cc->set_pc);
67
- return (uintptr_t)tcg_splitwx_to_rx(s->gen_tb->jmp_target_arg + which);
212
cc->set_pc(cpu, tb_pc(last_tb));
68
+ return (uintptr_t)tcg_splitwx_to_rx(&s->gen_tb->jmp_target_addr[which]);
213
}
214
@@ -XXX,XX +XXX,XX @@ int cpu_exec(CPUState *cpu)
215
* for the fast lookup
216
*/
217
h = tb_jmp_cache_hash_func(pc);
218
- qatomic_set(&cpu->tb_jmp_cache->array[h].tb, tb);
219
+ tb_jmp_cache_set(cpu->tb_jmp_cache, h, tb, pc);
220
}
221
222
#ifndef CONFIG_USER_ONLY
223
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
224
index XXXXXXX..XXXXXXX 100644
225
--- a/accel/tcg/translate-all.c
226
+++ b/accel/tcg/translate-all.c
227
@@ -XXX,XX +XXX,XX @@ static int encode_search(TranslationBlock *tb, uint8_t *block)
228
229
for (j = 0; j < TARGET_INSN_START_WORDS; ++j) {
230
if (i == 0) {
231
- prev = (j == 0 ? tb_pc(tb) : 0);
232
+ prev = (!TARGET_TB_PCREL && j == 0 ? tb_pc(tb) : 0);
233
} else {
234
prev = tcg_ctx->gen_insn_data[i - 1][j];
235
}
236
@@ -XXX,XX +XXX,XX @@ static int encode_search(TranslationBlock *tb, uint8_t *block)
237
static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
238
uintptr_t searched_pc, bool reset_icount)
239
{
240
- target_ulong data[TARGET_INSN_START_WORDS] = { tb_pc(tb) };
241
+ target_ulong data[TARGET_INSN_START_WORDS];
242
uintptr_t host_pc = (uintptr_t)tb->tc.ptr;
243
CPUArchState *env = cpu->env_ptr;
244
const uint8_t *p = tb->tc.ptr + tb->tc.size;
245
@@ -XXX,XX +XXX,XX @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
246
return -1;
247
}
248
249
+ memset(data, 0, sizeof(data));
250
+ if (!TARGET_TB_PCREL) {
251
+ data[0] = tb_pc(tb);
252
+ }
253
+
254
/* Reconstruct the stored insn data while looking for the point at
255
which the end of the insn exceeds the searched_pc. */
256
for (i = 0; i < num_insns; ++i) {
257
@@ -XXX,XX +XXX,XX @@ static bool tb_cmp(const void *ap, const void *bp)
258
const TranslationBlock *a = ap;
259
const TranslationBlock *b = bp;
260
261
- return tb_pc(a) == tb_pc(b) &&
262
- a->cs_base == b->cs_base &&
263
- a->flags == b->flags &&
264
- (tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) &&
265
- a->trace_vcpu_dstate == b->trace_vcpu_dstate &&
266
- a->page_addr[0] == b->page_addr[0] &&
267
- a->page_addr[1] == b->page_addr[1];
268
+ return ((TARGET_TB_PCREL || tb_pc(a) == tb_pc(b)) &&
269
+ a->cs_base == b->cs_base &&
270
+ a->flags == b->flags &&
271
+ (tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) &&
272
+ a->trace_vcpu_dstate == b->trace_vcpu_dstate &&
273
+ a->page_addr[0] == b->page_addr[0] &&
274
+ a->page_addr[1] == b->page_addr[1]);
275
}
69
}
276
70
277
void tb_htable_init(void)
71
/* Signal overflow, starting over with fewer guest insns. */
278
@@ -XXX,XX +XXX,XX @@ static inline void tb_jmp_unlink(TranslationBlock *dest)
72
@@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, target_ulong pc_start)
279
qemu_spin_unlock(&dest->jmp_lock);
73
/* Initialize goto_tb jump offsets. */
280
}
74
tb->jmp_reset_offset[0] = TB_JMP_OFFSET_INVALID;
281
75
tb->jmp_reset_offset[1] = TB_JMP_OFFSET_INVALID;
282
+static void tb_jmp_cache_inval_tb(TranslationBlock *tb)
76
+ tb->jmp_insn_offset[0] = TB_JMP_OFFSET_INVALID;
283
+{
77
+ tb->jmp_insn_offset[1] = TB_JMP_OFFSET_INVALID;
284
+ CPUState *cpu;
78
285
+
79
tcg_reg_alloc_start(s);
286
+ if (TARGET_TB_PCREL) {
80
287
+ /* A TB may be at any virtual address */
288
+ CPU_FOREACH(cpu) {
289
+ tcg_flush_jmp_cache(cpu);
290
+ }
291
+ } else {
292
+ uint32_t h = tb_jmp_cache_hash_func(tb_pc(tb));
293
+
294
+ CPU_FOREACH(cpu) {
295
+ CPUJumpCache *jc = cpu->tb_jmp_cache;
296
+
297
+ if (qatomic_read(&jc->array[h].tb) == tb) {
298
+ qatomic_set(&jc->array[h].tb, NULL);
299
+ }
300
+ }
301
+ }
302
+}
303
+
304
/*
305
* In user-mode, call with mmap_lock held.
306
* In !user-mode, if @rm_from_page_list is set, call with the TB's pages'
307
@@ -XXX,XX +XXX,XX @@ static inline void tb_jmp_unlink(TranslationBlock *dest)
308
*/
309
static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
310
{
311
- CPUState *cpu;
312
PageDesc *p;
313
uint32_t h;
314
tb_page_addr_t phys_pc;
315
@@ -XXX,XX +XXX,XX @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
316
317
/* remove the TB from the hash list */
318
phys_pc = tb->page_addr[0];
319
- h = tb_hash_func(phys_pc, tb_pc(tb), tb->flags, orig_cflags,
320
- tb->trace_vcpu_dstate);
321
+ h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : tb_pc(tb)),
322
+ tb->flags, orig_cflags, tb->trace_vcpu_dstate);
323
if (!qht_remove(&tb_ctx.htable, tb, h)) {
324
return;
325
}
326
@@ -XXX,XX +XXX,XX @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
327
}
328
329
/* remove the TB from the hash list */
330
- h = tb_jmp_cache_hash_func(tb->pc);
331
- CPU_FOREACH(cpu) {
332
- CPUJumpCache *jc = cpu->tb_jmp_cache;
333
- if (qatomic_read(&jc->array[h].tb) == tb) {
334
- qatomic_set(&jc->array[h].tb, NULL);
335
- }
336
- }
337
+ tb_jmp_cache_inval_tb(tb);
338
339
/* suppress this TB from the two jump lists */
340
tb_remove_from_jmp_list(tb, 0);
341
@@ -XXX,XX +XXX,XX @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
342
}
343
344
/* add in the hash table */
345
- h = tb_hash_func(phys_pc, tb_pc(tb), tb->flags, tb->cflags,
346
- tb->trace_vcpu_dstate);
347
+ h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : tb_pc(tb)),
348
+ tb->flags, tb->cflags, tb->trace_vcpu_dstate);
349
qht_insert(&tb_ctx.htable, tb, h, &existing_tb);
350
351
/* remove TB from the page(s) if we couldn't insert it */
352
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
353
354
gen_code_buf = tcg_ctx->code_gen_ptr;
355
tb->tc.ptr = tcg_splitwx_to_rx(gen_code_buf);
356
+#if !TARGET_TB_PCREL
357
tb->pc = pc;
358
+#endif
359
tb->cs_base = cs_base;
360
tb->flags = flags;
361
tb->cflags = cflags;
362
--
81
--
363
2.34.1
82
2.34.1
364
83
365
84
diff view generated by jsdifflib
1
Let tb->page_addr[0] contain the address of the first byte of the
1
Replace 'tc_ptr' and 'addr' with 'tb' and 'n'.
2
translated block, rather than the address of the page containing the
3
start of the translated block. We need to recover this value anyway
4
at various points, and it is easier to discard a page offset when it
5
is not needed, which happens naturally via the existing find_page shift.
6
2
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
5
---
10
accel/tcg/cpu-exec.c | 16 ++++++++--------
6
tcg/aarch64/tcg-target.h | 3 ++-
11
accel/tcg/cputlb.c | 3 ++-
7
tcg/arm/tcg-target.h | 3 ++-
12
accel/tcg/translate-all.c | 9 +++++----
8
tcg/i386/tcg-target.h | 9 ++-------
13
3 files changed, 15 insertions(+), 13 deletions(-)
9
tcg/loongarch64/tcg-target.h | 3 ++-
10
tcg/mips/tcg-target.h | 3 ++-
11
tcg/ppc/tcg-target.h | 3 ++-
12
tcg/riscv/tcg-target.h | 3 ++-
13
tcg/s390x/tcg-target.h | 10 ++--------
14
tcg/sparc64/tcg-target.h | 3 ++-
15
tcg/tci/tcg-target.h | 3 ++-
16
accel/tcg/cpu-exec.c | 11 ++++++++---
17
tcg/aarch64/tcg-target.c.inc | 5 +++--
18
tcg/i386/tcg-target.c.inc | 9 +++++++++
19
tcg/loongarch64/tcg-target.c.inc | 5 +++--
20
tcg/ppc/tcg-target.c.inc | 7 ++++---
21
tcg/s390x/tcg-target.c.inc | 10 ++++++++++
22
tcg/sparc64/tcg-target.c.inc | 7 ++++---
23
17 files changed, 61 insertions(+), 36 deletions(-)
14
24
25
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/tcg/aarch64/tcg-target.h
28
+++ b/tcg/aarch64/tcg-target.h
29
@@ -XXX,XX +XXX,XX @@ typedef enum {
30
#define TCG_TARGET_DEFAULT_MO (0)
31
#define TCG_TARGET_HAS_MEMORY_BSWAP 0
32
33
-void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
34
+void tb_target_set_jmp_target(const TranslationBlock *, int,
35
+ uintptr_t, uintptr_t);
36
37
#define TCG_TARGET_NEED_LDST_LABELS
38
#define TCG_TARGET_NEED_POOL_LABELS
39
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
40
index XXXXXXX..XXXXXXX 100644
41
--- a/tcg/arm/tcg-target.h
42
+++ b/tcg/arm/tcg-target.h
43
@@ -XXX,XX +XXX,XX @@ extern bool use_neon_instructions;
44
#define TCG_TARGET_HAS_MEMORY_BSWAP 0
45
46
/* not defined -- call should be eliminated at compile time */
47
-void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
48
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
49
+ uintptr_t, uintptr_t);
50
51
#define TCG_TARGET_NEED_LDST_LABELS
52
#define TCG_TARGET_NEED_POOL_LABELS
53
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
54
index XXXXXXX..XXXXXXX 100644
55
--- a/tcg/i386/tcg-target.h
56
+++ b/tcg/i386/tcg-target.h
57
@@ -XXX,XX +XXX,XX @@ extern bool have_movbe;
58
#define TCG_TARGET_extract_i64_valid(ofs, len) \
59
(((ofs) == 8 && (len) == 8) || ((ofs) + (len)) == 32)
60
61
-static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
62
- uintptr_t jmp_rw, uintptr_t addr)
63
-{
64
- /* patch the branch destination */
65
- qatomic_set((int32_t *)jmp_rw, addr - (jmp_rx + 4));
66
- /* no need to flush icache explicitly */
67
-}
68
+void tb_target_set_jmp_target(const TranslationBlock *, int,
69
+ uintptr_t, uintptr_t);
70
71
/* This defines the natural memory order supported by this
72
* architecture before guarantees made by various barrier
73
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
74
index XXXXXXX..XXXXXXX 100644
75
--- a/tcg/loongarch64/tcg-target.h
76
+++ b/tcg/loongarch64/tcg-target.h
77
@@ -XXX,XX +XXX,XX @@ typedef enum {
78
#define TCG_TARGET_HAS_muluh_i64 1
79
#define TCG_TARGET_HAS_mulsh_i64 1
80
81
-void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
82
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
83
+ uintptr_t, uintptr_t);
84
85
#define TCG_TARGET_DEFAULT_MO (0)
86
87
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
88
index XXXXXXX..XXXXXXX 100644
89
--- a/tcg/mips/tcg-target.h
90
+++ b/tcg/mips/tcg-target.h
91
@@ -XXX,XX +XXX,XX @@ extern bool use_mips32r2_instructions;
92
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
93
94
/* not defined -- call should be eliminated at compile time */
95
-void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t)
96
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
97
+ uintptr_t, uintptr_t)
98
QEMU_ERROR("code path is reachable");
99
100
#define TCG_TARGET_NEED_LDST_LABELS
101
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
102
index XXXXXXX..XXXXXXX 100644
103
--- a/tcg/ppc/tcg-target.h
104
+++ b/tcg/ppc/tcg-target.h
105
@@ -XXX,XX +XXX,XX @@ extern bool have_vsx;
106
#define TCG_TARGET_HAS_bitsel_vec have_vsx
107
#define TCG_TARGET_HAS_cmpsel_vec 0
108
109
-void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
110
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
111
+ uintptr_t, uintptr_t);
112
113
#define TCG_TARGET_DEFAULT_MO (0)
114
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
115
diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
116
index XXXXXXX..XXXXXXX 100644
117
--- a/tcg/riscv/tcg-target.h
118
+++ b/tcg/riscv/tcg-target.h
119
@@ -XXX,XX +XXX,XX @@ typedef enum {
120
#endif
121
122
/* not defined -- call should be eliminated at compile time */
123
-void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
124
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
125
+ uintptr_t, uintptr_t);
126
127
#define TCG_TARGET_DEFAULT_MO (0)
128
129
diff --git a/tcg/s390x/tcg-target.h b/tcg/s390x/tcg-target.h
130
index XXXXXXX..XXXXXXX 100644
131
--- a/tcg/s390x/tcg-target.h
132
+++ b/tcg/s390x/tcg-target.h
133
@@ -XXX,XX +XXX,XX @@ extern uint64_t s390_facilities[3];
134
135
#define TCG_TARGET_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD)
136
137
-static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
138
- uintptr_t jmp_rw, uintptr_t addr)
139
-{
140
- /* patch the branch destination */
141
- intptr_t disp = addr - (jmp_rx - 2);
142
- qatomic_set((int32_t *)jmp_rw, disp / 2);
143
- /* no need to flush icache explicitly */
144
-}
145
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
146
+ uintptr_t jmp_rx, uintptr_t jmp_rw);
147
148
#define TCG_TARGET_NEED_LDST_LABELS
149
#define TCG_TARGET_NEED_POOL_LABELS
150
diff --git a/tcg/sparc64/tcg-target.h b/tcg/sparc64/tcg-target.h
151
index XXXXXXX..XXXXXXX 100644
152
--- a/tcg/sparc64/tcg-target.h
153
+++ b/tcg/sparc64/tcg-target.h
154
@@ -XXX,XX +XXX,XX @@ extern bool use_vis3_instructions;
155
#define TCG_TARGET_DEFAULT_MO (0)
156
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
157
158
-void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
159
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
160
+ uintptr_t, uintptr_t);
161
162
#define TCG_TARGET_NEED_POOL_LABELS
163
164
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
165
index XXXXXXX..XXXXXXX 100644
166
--- a/tcg/tci/tcg-target.h
167
+++ b/tcg/tci/tcg-target.h
168
@@ -XXX,XX +XXX,XX @@ typedef enum {
169
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
170
171
/* not defined -- call should be eliminated at compile time */
172
-void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
173
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
174
+ uintptr_t, uintptr_t);
175
176
#endif /* TCG_TARGET_H */
15
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
177
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
16
index XXXXXXX..XXXXXXX 100644
178
index XXXXXXX..XXXXXXX 100644
17
--- a/accel/tcg/cpu-exec.c
179
--- a/accel/tcg/cpu-exec.c
18
+++ b/accel/tcg/cpu-exec.c
180
+++ b/accel/tcg/cpu-exec.c
19
@@ -XXX,XX +XXX,XX @@ struct tb_desc {
181
@@ -XXX,XX +XXX,XX @@ void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr)
20
target_ulong pc;
182
{
21
target_ulong cs_base;
183
tb->jmp_target_addr[n] = addr;
22
CPUArchState *env;
184
if (TCG_TARGET_HAS_direct_jump) {
23
- tb_page_addr_t phys_page1;
185
+ /*
24
+ tb_page_addr_t page_addr0;
186
+ * Get the rx view of the structure, from which we find the
25
uint32_t flags;
187
+ * executable code address, and tb_target_set_jmp_target can
26
uint32_t cflags;
188
+ * produce a pc-relative displacement to jmp_target_addr[n].
27
uint32_t trace_vcpu_dstate;
189
+ */
28
@@ -XXX,XX +XXX,XX @@ static bool tb_lookup_cmp(const void *p, const void *d)
190
+ const TranslationBlock *c_tb = tcg_splitwx_to_rx(tb);
29
const struct tb_desc *desc = d;
191
uintptr_t offset = tb->jmp_insn_offset[n];
30
192
- uintptr_t tc_ptr = (uintptr_t)tb->tc.ptr;
31
if (tb->pc == desc->pc &&
193
- uintptr_t jmp_rx = tc_ptr + offset;
32
- tb->page_addr[0] == desc->phys_page1 &&
194
+ uintptr_t jmp_rx = (uintptr_t)tb->tc.ptr + offset;
33
+ tb->page_addr[0] == desc->page_addr0 &&
195
uintptr_t jmp_rw = jmp_rx - tcg_splitwx_diff;
34
tb->cs_base == desc->cs_base &&
196
- tb_target_set_jmp_target(tc_ptr, jmp_rx, jmp_rw, addr);
35
tb->flags == desc->flags &&
197
+ tb_target_set_jmp_target(c_tb, n, jmp_rx, jmp_rw);
36
tb->trace_vcpu_dstate == desc->trace_vcpu_dstate &&
37
@@ -XXX,XX +XXX,XX @@ static bool tb_lookup_cmp(const void *p, const void *d)
38
if (tb->page_addr[1] == -1) {
39
return true;
40
} else {
41
- tb_page_addr_t phys_page2;
42
- target_ulong virt_page2;
43
+ tb_page_addr_t phys_page1;
44
+ target_ulong virt_page1;
45
46
/*
47
* We know that the first page matched, and an otherwise valid TB
48
@@ -XXX,XX +XXX,XX @@ static bool tb_lookup_cmp(const void *p, const void *d)
49
* is different for the new TB. Therefore any exception raised
50
* here by the faulting lookup is not premature.
51
*/
52
- virt_page2 = TARGET_PAGE_ALIGN(desc->pc);
53
- phys_page2 = get_page_addr_code(desc->env, virt_page2);
54
- if (tb->page_addr[1] == phys_page2) {
55
+ virt_page1 = TARGET_PAGE_ALIGN(desc->pc);
56
+ phys_page1 = get_page_addr_code(desc->env, virt_page1);
57
+ if (tb->page_addr[1] == phys_page1) {
58
return true;
59
}
60
}
61
@@ -XXX,XX +XXX,XX @@ static TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
62
if (phys_pc == -1) {
63
return NULL;
64
}
198
}
65
- desc.phys_page1 = phys_pc & TARGET_PAGE_MASK;
199
}
66
+ desc.page_addr0 = phys_pc;
200
67
h = tb_hash_func(phys_pc, pc, flags, cflags, *cpu->trace_dstate);
201
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
68
return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp);
202
index XXXXXXX..XXXXXXX 100644
69
}
203
--- a/tcg/aarch64/tcg-target.c.inc
70
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
204
+++ b/tcg/aarch64/tcg-target.c.inc
71
index XXXXXXX..XXXXXXX 100644
205
@@ -XXX,XX +XXX,XX @@ static void tcg_out_call(TCGContext *s, const tcg_insn_unit *target,
72
--- a/accel/tcg/cputlb.c
206
tcg_out_call_int(s, target);
73
+++ b/accel/tcg/cputlb.c
207
}
74
@@ -XXX,XX +XXX,XX @@ void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
208
75
can be detected */
209
-void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
76
void tlb_protect_code(ram_addr_t ram_addr)
210
- uintptr_t jmp_rw, uintptr_t addr)
77
{
211
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
78
- cpu_physical_memory_test_and_clear_dirty(ram_addr, TARGET_PAGE_SIZE,
212
+ uintptr_t jmp_rx, uintptr_t jmp_rw)
79
+ cpu_physical_memory_test_and_clear_dirty(ram_addr & TARGET_PAGE_MASK,
213
{
80
+ TARGET_PAGE_SIZE,
214
+ uintptr_t addr = tb->jmp_target_addr[n];
81
DIRTY_MEMORY_CODE);
215
tcg_insn_unit i1, i2;
82
}
216
TCGType rt = TCG_TYPE_I64;
83
217
TCGReg rd = TCG_REG_TMP;
84
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
218
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
85
index XXXXXXX..XXXXXXX 100644
219
index XXXXXXX..XXXXXXX 100644
86
--- a/accel/tcg/translate-all.c
220
--- a/tcg/i386/tcg-target.c.inc
87
+++ b/accel/tcg/translate-all.c
221
+++ b/tcg/i386/tcg-target.c.inc
88
@@ -XXX,XX +XXX,XX @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
222
@@ -XXX,XX +XXX,XX @@ static void tcg_out_goto_tb(TCGContext *s, int which)
89
qemu_spin_unlock(&tb->jmp_lock);
223
set_jmp_reset_offset(s, which);
90
224
}
91
/* remove the TB from the hash list */
225
92
- phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
226
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
93
+ phys_pc = tb->page_addr[0];
227
+ uintptr_t jmp_rx, uintptr_t jmp_rw)
94
h = tb_hash_func(phys_pc, tb->pc, tb->flags, orig_cflags,
228
+{
95
tb->trace_vcpu_dstate);
229
+ /* patch the branch destination */
96
if (!qht_remove(&tb_ctx.htable, tb, h)) {
230
+ uintptr_t addr = tb->jmp_target_addr[n];
97
@@ -XXX,XX +XXX,XX @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
231
+ qatomic_set((int32_t *)jmp_rw, addr - (jmp_rx + 4));
98
* we can only insert TBs that are fully initialized.
232
+ /* no need to flush icache explicitly */
99
*/
233
+}
100
page_lock_pair(&p, phys_pc, &p2, phys_page2, true);
234
+
101
- tb_page_add(p, tb, 0, phys_pc & TARGET_PAGE_MASK);
235
static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
102
+ tb_page_add(p, tb, 0, phys_pc);
236
const TCGArg args[TCG_MAX_OP_ARGS],
103
if (p2) {
237
const int const_args[TCG_MAX_OP_ARGS])
104
tb_page_add(p2, tb, 1, phys_page2);
238
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
105
} else {
239
index XXXXXXX..XXXXXXX 100644
106
@@ -XXX,XX +XXX,XX @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
240
--- a/tcg/loongarch64/tcg-target.c.inc
107
if (n == 0) {
241
+++ b/tcg/loongarch64/tcg-target.c.inc
108
/* NOTE: tb_end may be after the end of the page, but
242
@@ -XXX,XX +XXX,XX @@ static void tcg_out_nop(TCGContext *s)
109
it is not a problem */
243
tcg_out32(s, NOP);
110
- tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
244
}
111
+ tb_start = tb->page_addr[0];
245
112
tb_end = tb_start + tb->size;
246
-void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
113
} else {
247
- uintptr_t jmp_rw, uintptr_t addr)
114
tb_start = tb->page_addr[1];
248
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
115
- tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
249
+ uintptr_t jmp_rx, uintptr_t jmp_rw)
116
+ tb_end = tb_start + ((tb->page_addr[0] + tb->size)
250
{
117
+ & ~TARGET_PAGE_MASK);
251
tcg_insn_unit i1, i2;
118
}
252
ptrdiff_t upper, lower;
119
if (!(tb_end <= start || tb_start >= end)) {
253
+ uintptr_t addr = tb->jmp_target_addr[n];
120
#ifdef TARGET_HAS_PRECISE_SMC
254
ptrdiff_t offset = (ptrdiff_t)(addr - jmp_rx) >> 2;
255
256
if (offset == sextreg(offset, 0, 26)) {
257
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
258
index XXXXXXX..XXXXXXX 100644
259
--- a/tcg/ppc/tcg-target.c.inc
260
+++ b/tcg/ppc/tcg-target.c.inc
261
@@ -XXX,XX +XXX,XX @@ static inline void ppc64_replace4(uintptr_t rx, uintptr_t rw,
262
flush_idcache_range(rx, rw, 16);
263
}
264
265
-void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
266
- uintptr_t jmp_rw, uintptr_t addr)
267
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
268
+ uintptr_t jmp_rx, uintptr_t jmp_rw)
269
{
270
tcg_insn_unit i0, i1, i2, i3;
271
- intptr_t tb_diff = addr - tc_ptr;
272
+ uintptr_t addr = tb->jmp_target_addr[n];
273
+ intptr_t tb_diff = addr - (uintptr_t)tb->tc.ptr;
274
intptr_t br_diff = addr - (jmp_rx + 4);
275
intptr_t lo, hi;
276
277
diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc
278
index XXXXXXX..XXXXXXX 100644
279
--- a/tcg/s390x/tcg-target.c.inc
280
+++ b/tcg/s390x/tcg-target.c.inc
281
@@ -XXX,XX +XXX,XX @@ static void tcg_out_goto_tb(TCGContext *s, int which)
282
set_jmp_reset_offset(s, which);
283
}
284
285
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
286
+ uintptr_t jmp_rx, uintptr_t jmp_rw)
287
+{
288
+ /* patch the branch destination */
289
+ uintptr_t addr = tb->jmp_target_addr[n];
290
+ intptr_t disp = addr - (jmp_rx - 2);
291
+ qatomic_set((int32_t *)jmp_rw, disp / 2);
292
+ /* no need to flush icache explicitly */
293
+}
294
+
295
# define OP_32_64(x) \
296
case glue(glue(INDEX_op_,x),_i32): \
297
case glue(glue(INDEX_op_,x),_i64)
298
diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc
299
index XXXXXXX..XXXXXXX 100644
300
--- a/tcg/sparc64/tcg-target.c.inc
301
+++ b/tcg/sparc64/tcg-target.c.inc
302
@@ -XXX,XX +XXX,XX @@ void tcg_register_jit(const void *buf, size_t buf_size)
303
tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
304
}
305
306
-void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
307
- uintptr_t jmp_rw, uintptr_t addr)
308
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
309
+ uintptr_t jmp_rx, uintptr_t jmp_rw)
310
{
311
- intptr_t tb_disp = addr - tc_ptr;
312
+ uintptr_t addr = tb->jmp_target_addr[n];
313
+ intptr_t tb_disp = addr - (uintptr_t)tb->tc.ptr;
314
intptr_t br_disp = addr - jmp_rx;
315
tcg_insn_unit i1, i2;
316
121
--
317
--
122
2.34.1
318
2.34.1
123
319
124
320
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
2
2
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
3
The class cast checkers are quite expensive and always on (unlike the
4
dynamic case who's checks are gated by CONFIG_QOM_CAST_DEBUG). To
5
avoid the overhead of repeatedly checking something which should never
6
change we cache the CPUClass reference for use in the hot code paths.
7
8
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-Id: <20220811151413.3350684-3-alex.bennee@linaro.org>
11
Signed-off-by: Cédric Le Goater <clg@kaod.org>
12
Message-Id: <20220923084803.498337-3-clg@kaod.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
---
4
---
15
include/hw/core/cpu.h | 9 +++++++++
5
include/tcg/tcg.h | 3 +++
16
cpu.c | 9 ++++-----
6
tcg/aarch64/tcg-target.h | 4 ----
17
2 files changed, 13 insertions(+), 5 deletions(-)
7
tcg/arm/tcg-target.h | 5 -----
8
tcg/i386/tcg-target.h | 3 ---
9
tcg/loongarch64/tcg-target.h | 3 ---
10
tcg/mips/tcg-target.h | 5 -----
11
tcg/ppc/tcg-target.h | 4 ----
12
tcg/riscv/tcg-target.h | 4 ----
13
tcg/s390x/tcg-target.h | 4 ----
14
tcg/sparc64/tcg-target.h | 4 ----
15
tcg/tci/tcg-target.h | 4 ----
16
11 files changed, 3 insertions(+), 40 deletions(-)
18
17
19
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
18
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
20
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/core/cpu.h
20
--- a/include/tcg/tcg.h
22
+++ b/include/hw/core/cpu.h
21
+++ b/include/tcg/tcg.h
23
@@ -XXX,XX +XXX,XX @@ typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size,
22
@@ -XXX,XX +XXX,XX @@ void tcg_func_start(TCGContext *s);
24
*/
23
25
#define CPU(obj) ((CPUState *)(obj))
24
int tcg_gen_code(TCGContext *s, TranslationBlock *tb, target_ulong pc_start);
26
25
27
+/*
26
+void tb_target_set_jmp_target(const TranslationBlock *, int,
28
+ * The class checkers bring in CPU_GET_CLASS() which is potentially
27
+ uintptr_t, uintptr_t);
29
+ * expensive given the eventual call to
28
+
30
+ * object_class_dynamic_cast_assert(). Because of this the CPUState
29
void tcg_set_frame(TCGContext *s, TCGReg reg, intptr_t start, intptr_t size);
31
+ * has a cached value for the class in cs->cc which is set up in
30
32
+ * cpu_exec_realizefn() for use in hot code paths.
31
TCGTemp *tcg_global_mem_new_internal(TCGType, TCGv_ptr,
33
+ */
32
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
34
typedef struct CPUClass CPUClass;
35
DECLARE_CLASS_CHECKERS(CPUClass, CPU,
36
TYPE_CPU)
37
@@ -XXX,XX +XXX,XX @@ struct qemu_work_item;
38
struct CPUState {
39
/*< private >*/
40
DeviceState parent_obj;
41
+ /* cache to avoid expensive CPU_GET_CLASS */
42
+ CPUClass *cc;
43
/*< public >*/
44
45
int nr_cores;
46
diff --git a/cpu.c b/cpu.c
47
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
48
--- a/cpu.c
34
--- a/tcg/aarch64/tcg-target.h
49
+++ b/cpu.c
35
+++ b/tcg/aarch64/tcg-target.h
50
@@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_cpu_common = {
36
@@ -XXX,XX +XXX,XX @@ typedef enum {
51
37
52
void cpu_exec_realizefn(CPUState *cpu, Error **errp)
38
#define TCG_TARGET_DEFAULT_MO (0)
53
{
39
#define TCG_TARGET_HAS_MEMORY_BSWAP 0
54
-#ifndef CONFIG_USER_ONLY
40
-
55
- CPUClass *cc = CPU_GET_CLASS(cpu);
41
-void tb_target_set_jmp_target(const TranslationBlock *, int,
56
-#endif
42
- uintptr_t, uintptr_t);
57
+ /* cache the cpu class for the hotpath */
43
-
58
+ cpu->cc = CPU_GET_CLASS(cpu);
44
#define TCG_TARGET_NEED_LDST_LABELS
59
45
#define TCG_TARGET_NEED_POOL_LABELS
60
cpu_list_add(cpu);
46
61
if (!accel_cpu_realizefn(cpu, errp)) {
47
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
62
@@ -XXX,XX +XXX,XX @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
48
index XXXXXXX..XXXXXXX 100644
63
if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
49
--- a/tcg/arm/tcg-target.h
64
vmstate_register(NULL, cpu->cpu_index, &vmstate_cpu_common, cpu);
50
+++ b/tcg/arm/tcg-target.h
65
}
51
@@ -XXX,XX +XXX,XX @@ extern bool use_neon_instructions;
66
- if (cc->sysemu_ops->legacy_vmsd != NULL) {
52
67
- vmstate_register(NULL, cpu->cpu_index, cc->sysemu_ops->legacy_vmsd, cpu);
53
#define TCG_TARGET_DEFAULT_MO (0)
68
+ if (cpu->cc->sysemu_ops->legacy_vmsd != NULL) {
54
#define TCG_TARGET_HAS_MEMORY_BSWAP 0
69
+ vmstate_register(NULL, cpu->cpu_index, cpu->cc->sysemu_ops->legacy_vmsd, cpu);
55
-
70
}
56
-/* not defined -- call should be eliminated at compile time */
71
#endif /* CONFIG_USER_ONLY */
57
-void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
72
}
58
- uintptr_t, uintptr_t);
59
-
60
#define TCG_TARGET_NEED_LDST_LABELS
61
#define TCG_TARGET_NEED_POOL_LABELS
62
63
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
64
index XXXXXXX..XXXXXXX 100644
65
--- a/tcg/i386/tcg-target.h
66
+++ b/tcg/i386/tcg-target.h
67
@@ -XXX,XX +XXX,XX @@ extern bool have_movbe;
68
#define TCG_TARGET_extract_i64_valid(ofs, len) \
69
(((ofs) == 8 && (len) == 8) || ((ofs) + (len)) == 32)
70
71
-void tb_target_set_jmp_target(const TranslationBlock *, int,
72
- uintptr_t, uintptr_t);
73
-
74
/* This defines the natural memory order supported by this
75
* architecture before guarantees made by various barrier
76
* instructions.
77
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
78
index XXXXXXX..XXXXXXX 100644
79
--- a/tcg/loongarch64/tcg-target.h
80
+++ b/tcg/loongarch64/tcg-target.h
81
@@ -XXX,XX +XXX,XX @@ typedef enum {
82
#define TCG_TARGET_HAS_muluh_i64 1
83
#define TCG_TARGET_HAS_mulsh_i64 1
84
85
-void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
86
- uintptr_t, uintptr_t);
87
-
88
#define TCG_TARGET_DEFAULT_MO (0)
89
90
#define TCG_TARGET_NEED_LDST_LABELS
91
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
92
index XXXXXXX..XXXXXXX 100644
93
--- a/tcg/mips/tcg-target.h
94
+++ b/tcg/mips/tcg-target.h
95
@@ -XXX,XX +XXX,XX @@ extern bool use_mips32r2_instructions;
96
#define TCG_TARGET_DEFAULT_MO (0)
97
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
98
99
-/* not defined -- call should be eliminated at compile time */
100
-void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
101
- uintptr_t, uintptr_t)
102
- QEMU_ERROR("code path is reachable");
103
-
104
#define TCG_TARGET_NEED_LDST_LABELS
105
106
#endif
107
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
108
index XXXXXXX..XXXXXXX 100644
109
--- a/tcg/ppc/tcg-target.h
110
+++ b/tcg/ppc/tcg-target.h
111
@@ -XXX,XX +XXX,XX @@ extern bool have_vsx;
112
#define TCG_TARGET_HAS_bitsel_vec have_vsx
113
#define TCG_TARGET_HAS_cmpsel_vec 0
114
115
-void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
116
- uintptr_t, uintptr_t);
117
-
118
#define TCG_TARGET_DEFAULT_MO (0)
119
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
120
-
121
#define TCG_TARGET_NEED_LDST_LABELS
122
#define TCG_TARGET_NEED_POOL_LABELS
123
124
diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
125
index XXXXXXX..XXXXXXX 100644
126
--- a/tcg/riscv/tcg-target.h
127
+++ b/tcg/riscv/tcg-target.h
128
@@ -XXX,XX +XXX,XX @@ typedef enum {
129
#define TCG_TARGET_HAS_mulsh_i64 1
130
#endif
131
132
-/* not defined -- call should be eliminated at compile time */
133
-void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
134
- uintptr_t, uintptr_t);
135
-
136
#define TCG_TARGET_DEFAULT_MO (0)
137
138
#define TCG_TARGET_NEED_LDST_LABELS
139
diff --git a/tcg/s390x/tcg-target.h b/tcg/s390x/tcg-target.h
140
index XXXXXXX..XXXXXXX 100644
141
--- a/tcg/s390x/tcg-target.h
142
+++ b/tcg/s390x/tcg-target.h
143
@@ -XXX,XX +XXX,XX @@ extern uint64_t s390_facilities[3];
144
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
145
146
#define TCG_TARGET_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD)
147
-
148
-void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
149
- uintptr_t jmp_rx, uintptr_t jmp_rw);
150
-
151
#define TCG_TARGET_NEED_LDST_LABELS
152
#define TCG_TARGET_NEED_POOL_LABELS
153
154
diff --git a/tcg/sparc64/tcg-target.h b/tcg/sparc64/tcg-target.h
155
index XXXXXXX..XXXXXXX 100644
156
--- a/tcg/sparc64/tcg-target.h
157
+++ b/tcg/sparc64/tcg-target.h
158
@@ -XXX,XX +XXX,XX @@ extern bool use_vis3_instructions;
159
160
#define TCG_TARGET_DEFAULT_MO (0)
161
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
162
-
163
-void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
164
- uintptr_t, uintptr_t);
165
-
166
#define TCG_TARGET_NEED_POOL_LABELS
167
168
#endif
169
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
170
index XXXXXXX..XXXXXXX 100644
171
--- a/tcg/tci/tcg-target.h
172
+++ b/tcg/tci/tcg-target.h
173
@@ -XXX,XX +XXX,XX @@ typedef enum {
174
175
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
176
177
-/* not defined -- call should be eliminated at compile time */
178
-void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
179
- uintptr_t, uintptr_t);
180
-
181
#endif /* TCG_TARGET_H */
73
--
182
--
74
2.34.1
183
2.34.1
75
184
76
185
diff view generated by jsdifflib
1
Populate this new method for all targets. Always match
1
Install empty versions for !TCG_TARGET_HAS_direct_jump hosts.
2
the result that would be given by cpu_get_tb_cpu_state,
3
as we will want these values to correspond in the logs.
4
2
5
Reviewed-by: Taylor Simpson <tsimpson@quicinc.com>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> (target/sparc)
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
Cc: Eduardo Habkost <eduardo@habkost.net> (supporter:Machine core)
7
tcg/arm/tcg-target.c.inc | 6 ++++++
11
Cc: Marcel Apfelbaum <marcel.apfelbaum@gmail.com> (supporter:Machine core)
8
tcg/mips/tcg-target.c.inc | 6 ++++++
12
Cc: "Philippe Mathieu-Daudé" <f4bug@amsat.org> (reviewer:Machine core)
9
tcg/riscv/tcg-target.c.inc | 6 ++++++
13
Cc: Yanan Wang <wangyanan55@huawei.com> (reviewer:Machine core)
10
tcg/tci/tcg-target.c.inc | 6 ++++++
14
Cc: Michael Rolnik <mrolnik@gmail.com> (maintainer:AVR TCG CPUs)
11
4 files changed, 24 insertions(+)
15
Cc: "Edgar E. Iglesias" <edgar.iglesias@gmail.com> (maintainer:CRIS TCG CPUs)
16
Cc: Taylor Simpson <tsimpson@quicinc.com> (supporter:Hexagon TCG CPUs)
17
Cc: Song Gao <gaosong@loongson.cn> (maintainer:LoongArch TCG CPUs)
18
Cc: Xiaojuan Yang <yangxiaojuan@loongson.cn> (maintainer:LoongArch TCG CPUs)
19
Cc: Laurent Vivier <laurent@vivier.eu> (maintainer:M68K TCG CPUs)
20
Cc: Jiaxun Yang <jiaxun.yang@flygoat.com> (reviewer:MIPS TCG CPUs)
21
Cc: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> (reviewer:MIPS TCG CPUs)
22
Cc: Chris Wulff <crwulff@gmail.com> (maintainer:NiosII TCG CPUs)
23
Cc: Marek Vasut <marex@denx.de> (maintainer:NiosII TCG CPUs)
24
Cc: Stafford Horne <shorne@gmail.com> (odd fixer:OpenRISC TCG CPUs)
25
Cc: Yoshinori Sato <ysato@users.sourceforge.jp> (reviewer:RENESAS RX CPUs)
26
Cc: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> (maintainer:SPARC TCG CPUs)
27
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de> (maintainer:TriCore TCG CPUs)
28
Cc: Max Filippov <jcmvbkbc@gmail.com> (maintainer:Xtensa TCG CPUs)
29
Cc: qemu-arm@nongnu.org (open list:ARM TCG CPUs)
30
Cc: qemu-ppc@nongnu.org (open list:PowerPC TCG CPUs)
31
Cc: qemu-riscv@nongnu.org (open list:RISC-V TCG CPUs)
32
Cc: qemu-s390x@nongnu.org (open list:S390 TCG CPUs)
33
---
34
include/hw/core/cpu.h | 3 +++
35
target/alpha/cpu.c | 9 +++++++++
36
target/arm/cpu.c | 13 +++++++++++++
37
target/avr/cpu.c | 8 ++++++++
38
target/cris/cpu.c | 8 ++++++++
39
target/hexagon/cpu.c | 8 ++++++++
40
target/hppa/cpu.c | 8 ++++++++
41
target/i386/cpu.c | 9 +++++++++
42
target/loongarch/cpu.c | 9 +++++++++
43
target/m68k/cpu.c | 8 ++++++++
44
target/microblaze/cpu.c | 8 ++++++++
45
target/mips/cpu.c | 8 ++++++++
46
target/nios2/cpu.c | 9 +++++++++
47
target/openrisc/cpu.c | 8 ++++++++
48
target/ppc/cpu_init.c | 8 ++++++++
49
target/riscv/cpu.c | 13 +++++++++++++
50
target/rx/cpu.c | 8 ++++++++
51
target/s390x/cpu.c | 8 ++++++++
52
target/sh4/cpu.c | 8 ++++++++
53
target/sparc/cpu.c | 8 ++++++++
54
target/tricore/cpu.c | 9 +++++++++
55
target/xtensa/cpu.c | 8 ++++++++
56
22 files changed, 186 insertions(+)
57
12
58
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
13
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
59
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
60
--- a/include/hw/core/cpu.h
15
--- a/tcg/arm/tcg-target.c.inc
61
+++ b/include/hw/core/cpu.h
16
+++ b/tcg/arm/tcg-target.c.inc
62
@@ -XXX,XX +XXX,XX @@ struct SysemuCPUOps;
17
@@ -XXX,XX +XXX,XX @@ static void tcg_out_goto_tb(TCGContext *s, int which)
63
* If the target behaviour here is anything other than "set
18
set_jmp_reset_offset(s, which);
64
* the PC register to the value passed in" then the target must
65
* also implement the synchronize_from_tb hook.
66
+ * @get_pc: Callback for getting the Program Counter register.
67
+ * As above, with the semantics of the target architecture.
68
* @gdb_read_register: Callback for letting GDB read a register.
69
* @gdb_write_register: Callback for letting GDB write a register.
70
* @gdb_adjust_breakpoint: Callback for adjusting the address of a
71
@@ -XXX,XX +XXX,XX @@ struct CPUClass {
72
void (*dump_state)(CPUState *cpu, FILE *, int flags);
73
int64_t (*get_arch_id)(CPUState *cpu);
74
void (*set_pc)(CPUState *cpu, vaddr value);
75
+ vaddr (*get_pc)(CPUState *cpu);
76
int (*gdb_read_register)(CPUState *cpu, GByteArray *buf, int reg);
77
int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg);
78
vaddr (*gdb_adjust_breakpoint)(CPUState *cpu, vaddr addr);
79
diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/target/alpha/cpu.c
82
+++ b/target/alpha/cpu.c
83
@@ -XXX,XX +XXX,XX @@ static void alpha_cpu_set_pc(CPUState *cs, vaddr value)
84
cpu->env.pc = value;
85
}
19
}
86
20
87
+static vaddr alpha_cpu_get_pc(CPUState *cs)
21
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
22
+ uintptr_t jmp_rx, uintptr_t jmp_rw)
88
+{
23
+{
89
+ AlphaCPU *cpu = ALPHA_CPU(cs);
24
+ /* Always indirect, nothing to do */
90
+
91
+ return cpu->env.pc;
92
+}
25
+}
93
+
26
+
94
+
27
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
95
static bool alpha_cpu_has_work(CPUState *cs)
28
const TCGArg args[TCG_MAX_OP_ARGS],
96
{
29
const int const_args[TCG_MAX_OP_ARGS])
97
/* Here we are checking to see if the CPU should wake up from HALT.
30
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
98
@@ -XXX,XX +XXX,XX @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data)
99
cc->has_work = alpha_cpu_has_work;
100
cc->dump_state = alpha_cpu_dump_state;
101
cc->set_pc = alpha_cpu_set_pc;
102
+ cc->get_pc = alpha_cpu_get_pc;
103
cc->gdb_read_register = alpha_cpu_gdb_read_register;
104
cc->gdb_write_register = alpha_cpu_gdb_write_register;
105
#ifndef CONFIG_USER_ONLY
106
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
107
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
108
--- a/target/arm/cpu.c
32
--- a/tcg/mips/tcg-target.c.inc
109
+++ b/target/arm/cpu.c
33
+++ b/tcg/mips/tcg-target.c.inc
110
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_set_pc(CPUState *cs, vaddr value)
34
@@ -XXX,XX +XXX,XX @@ static void tcg_out_goto_tb(TCGContext *s, int which)
111
}
35
set_jmp_reset_offset(s, which);
112
}
36
}
113
37
114
+static vaddr arm_cpu_get_pc(CPUState *cs)
38
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
39
+ uintptr_t jmp_rx, uintptr_t jmp_rw)
115
+{
40
+{
116
+ ARMCPU *cpu = ARM_CPU(cs);
41
+ /* Always indirect, nothing to do */
117
+ CPUARMState *env = &cpu->env;
118
+
119
+ if (is_a64(env)) {
120
+ return env->pc;
121
+ } else {
122
+ return env->regs[15];
123
+ }
124
+}
42
+}
125
+
43
+
126
#ifdef CONFIG_TCG
44
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
127
void arm_cpu_synchronize_from_tb(CPUState *cs,
45
const TCGArg args[TCG_MAX_OP_ARGS],
128
const TranslationBlock *tb)
46
const int const_args[TCG_MAX_OP_ARGS])
129
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
47
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
130
cc->has_work = arm_cpu_has_work;
131
cc->dump_state = arm_cpu_dump_state;
132
cc->set_pc = arm_cpu_set_pc;
133
+ cc->get_pc = arm_cpu_get_pc;
134
cc->gdb_read_register = arm_cpu_gdb_read_register;
135
cc->gdb_write_register = arm_cpu_gdb_write_register;
136
#ifndef CONFIG_USER_ONLY
137
diff --git a/target/avr/cpu.c b/target/avr/cpu.c
138
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
139
--- a/target/avr/cpu.c
49
--- a/tcg/riscv/tcg-target.c.inc
140
+++ b/target/avr/cpu.c
50
+++ b/tcg/riscv/tcg-target.c.inc
141
@@ -XXX,XX +XXX,XX @@ static void avr_cpu_set_pc(CPUState *cs, vaddr value)
51
@@ -XXX,XX +XXX,XX @@ static void tcg_out_goto_tb(TCGContext *s, int which)
142
cpu->env.pc_w = value / 2; /* internally PC points to words */
52
set_jmp_reset_offset(s, which);
143
}
53
}
144
54
145
+static vaddr avr_cpu_get_pc(CPUState *cs)
55
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
56
+ uintptr_t jmp_rx, uintptr_t jmp_rw)
146
+{
57
+{
147
+ AVRCPU *cpu = AVR_CPU(cs);
58
+ /* Always indirect, nothing to do */
148
+
149
+ return cpu->env.pc_w * 2;
150
+}
59
+}
151
+
60
+
152
static bool avr_cpu_has_work(CPUState *cs)
61
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
153
{
62
const TCGArg args[TCG_MAX_OP_ARGS],
154
AVRCPU *cpu = AVR_CPU(cs);
63
const int const_args[TCG_MAX_OP_ARGS])
155
@@ -XXX,XX +XXX,XX @@ static void avr_cpu_class_init(ObjectClass *oc, void *data)
64
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
156
cc->has_work = avr_cpu_has_work;
157
cc->dump_state = avr_cpu_dump_state;
158
cc->set_pc = avr_cpu_set_pc;
159
+ cc->get_pc = avr_cpu_get_pc;
160
dc->vmsd = &vms_avr_cpu;
161
cc->sysemu_ops = &avr_sysemu_ops;
162
cc->disas_set_info = avr_cpu_disas_set_info;
163
diff --git a/target/cris/cpu.c b/target/cris/cpu.c
164
index XXXXXXX..XXXXXXX 100644
65
index XXXXXXX..XXXXXXX 100644
165
--- a/target/cris/cpu.c
66
--- a/tcg/tci/tcg-target.c.inc
166
+++ b/target/cris/cpu.c
67
+++ b/tcg/tci/tcg-target.c.inc
167
@@ -XXX,XX +XXX,XX @@ static void cris_cpu_set_pc(CPUState *cs, vaddr value)
68
@@ -XXX,XX +XXX,XX @@ static void tcg_out_goto_tb(TCGContext *s, int which)
168
cpu->env.pc = value;
69
set_jmp_reset_offset(s, which);
169
}
70
}
170
71
171
+static vaddr cris_cpu_get_pc(CPUState *cs)
72
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
73
+ uintptr_t jmp_rx, uintptr_t jmp_rw)
172
+{
74
+{
173
+ CRISCPU *cpu = CRIS_CPU(cs);
75
+ /* Always indirect, nothing to do */
174
+
175
+ return cpu->env.pc;
176
+}
76
+}
177
+
77
+
178
static bool cris_cpu_has_work(CPUState *cs)
78
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
179
{
79
const TCGArg args[TCG_MAX_OP_ARGS],
180
return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
80
const int const_args[TCG_MAX_OP_ARGS])
181
@@ -XXX,XX +XXX,XX @@ static void cris_cpu_class_init(ObjectClass *oc, void *data)
182
cc->has_work = cris_cpu_has_work;
183
cc->dump_state = cris_cpu_dump_state;
184
cc->set_pc = cris_cpu_set_pc;
185
+ cc->get_pc = cris_cpu_get_pc;
186
cc->gdb_read_register = cris_cpu_gdb_read_register;
187
cc->gdb_write_register = cris_cpu_gdb_write_register;
188
#ifndef CONFIG_USER_ONLY
189
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
190
index XXXXXXX..XXXXXXX 100644
191
--- a/target/hexagon/cpu.c
192
+++ b/target/hexagon/cpu.c
193
@@ -XXX,XX +XXX,XX @@ static void hexagon_cpu_set_pc(CPUState *cs, vaddr value)
194
env->gpr[HEX_REG_PC] = value;
195
}
196
197
+static vaddr hexagon_cpu_get_pc(CPUState *cs)
198
+{
199
+ HexagonCPU *cpu = HEXAGON_CPU(cs);
200
+ CPUHexagonState *env = &cpu->env;
201
+ return env->gpr[HEX_REG_PC];
202
+}
203
+
204
static void hexagon_cpu_synchronize_from_tb(CPUState *cs,
205
const TranslationBlock *tb)
206
{
207
@@ -XXX,XX +XXX,XX @@ static void hexagon_cpu_class_init(ObjectClass *c, void *data)
208
cc->has_work = hexagon_cpu_has_work;
209
cc->dump_state = hexagon_dump_state;
210
cc->set_pc = hexagon_cpu_set_pc;
211
+ cc->get_pc = hexagon_cpu_get_pc;
212
cc->gdb_read_register = hexagon_gdb_read_register;
213
cc->gdb_write_register = hexagon_gdb_write_register;
214
cc->gdb_num_core_regs = TOTAL_PER_THREAD_REGS + NUM_VREGS + NUM_QREGS;
215
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
216
index XXXXXXX..XXXXXXX 100644
217
--- a/target/hppa/cpu.c
218
+++ b/target/hppa/cpu.c
219
@@ -XXX,XX +XXX,XX @@ static void hppa_cpu_set_pc(CPUState *cs, vaddr value)
220
cpu->env.iaoq_b = value + 4;
221
}
222
223
+static vaddr hppa_cpu_get_pc(CPUState *cs)
224
+{
225
+ HPPACPU *cpu = HPPA_CPU(cs);
226
+
227
+ return cpu->env.iaoq_f;
228
+}
229
+
230
static void hppa_cpu_synchronize_from_tb(CPUState *cs,
231
const TranslationBlock *tb)
232
{
233
@@ -XXX,XX +XXX,XX @@ static void hppa_cpu_class_init(ObjectClass *oc, void *data)
234
cc->has_work = hppa_cpu_has_work;
235
cc->dump_state = hppa_cpu_dump_state;
236
cc->set_pc = hppa_cpu_set_pc;
237
+ cc->get_pc = hppa_cpu_get_pc;
238
cc->gdb_read_register = hppa_cpu_gdb_read_register;
239
cc->gdb_write_register = hppa_cpu_gdb_write_register;
240
#ifndef CONFIG_USER_ONLY
241
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
242
index XXXXXXX..XXXXXXX 100644
243
--- a/target/i386/cpu.c
244
+++ b/target/i386/cpu.c
245
@@ -XXX,XX +XXX,XX @@ static void x86_cpu_set_pc(CPUState *cs, vaddr value)
246
cpu->env.eip = value;
247
}
248
249
+static vaddr x86_cpu_get_pc(CPUState *cs)
250
+{
251
+ X86CPU *cpu = X86_CPU(cs);
252
+
253
+ /* Match cpu_get_tb_cpu_state. */
254
+ return cpu->env.eip + cpu->env.segs[R_CS].base;
255
+}
256
+
257
int x86_cpu_pending_interrupt(CPUState *cs, int interrupt_request)
258
{
259
X86CPU *cpu = X86_CPU(cs);
260
@@ -XXX,XX +XXX,XX @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
261
cc->has_work = x86_cpu_has_work;
262
cc->dump_state = x86_cpu_dump_state;
263
cc->set_pc = x86_cpu_set_pc;
264
+ cc->get_pc = x86_cpu_get_pc;
265
cc->gdb_read_register = x86_cpu_gdb_read_register;
266
cc->gdb_write_register = x86_cpu_gdb_write_register;
267
cc->get_arch_id = x86_cpu_get_arch_id;
268
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
269
index XXXXXXX..XXXXXXX 100644
270
--- a/target/loongarch/cpu.c
271
+++ b/target/loongarch/cpu.c
272
@@ -XXX,XX +XXX,XX @@ static void loongarch_cpu_set_pc(CPUState *cs, vaddr value)
273
env->pc = value;
274
}
275
276
+static vaddr loongarch_cpu_get_pc(CPUState *cs)
277
+{
278
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
279
+ CPULoongArchState *env = &cpu->env;
280
+
281
+ return env->pc;
282
+}
283
+
284
#ifndef CONFIG_USER_ONLY
285
#include "hw/loongarch/virt.h"
286
287
@@ -XXX,XX +XXX,XX @@ static void loongarch_cpu_class_init(ObjectClass *c, void *data)
288
cc->has_work = loongarch_cpu_has_work;
289
cc->dump_state = loongarch_cpu_dump_state;
290
cc->set_pc = loongarch_cpu_set_pc;
291
+ cc->get_pc = loongarch_cpu_get_pc;
292
#ifndef CONFIG_USER_ONLY
293
dc->vmsd = &vmstate_loongarch_cpu;
294
cc->sysemu_ops = &loongarch_sysemu_ops;
295
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
296
index XXXXXXX..XXXXXXX 100644
297
--- a/target/m68k/cpu.c
298
+++ b/target/m68k/cpu.c
299
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_set_pc(CPUState *cs, vaddr value)
300
cpu->env.pc = value;
301
}
302
303
+static vaddr m68k_cpu_get_pc(CPUState *cs)
304
+{
305
+ M68kCPU *cpu = M68K_CPU(cs);
306
+
307
+ return cpu->env.pc;
308
+}
309
+
310
static bool m68k_cpu_has_work(CPUState *cs)
311
{
312
return cs->interrupt_request & CPU_INTERRUPT_HARD;
313
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
314
cc->has_work = m68k_cpu_has_work;
315
cc->dump_state = m68k_cpu_dump_state;
316
cc->set_pc = m68k_cpu_set_pc;
317
+ cc->get_pc = m68k_cpu_get_pc;
318
cc->gdb_read_register = m68k_cpu_gdb_read_register;
319
cc->gdb_write_register = m68k_cpu_gdb_write_register;
320
#if defined(CONFIG_SOFTMMU)
321
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
322
index XXXXXXX..XXXXXXX 100644
323
--- a/target/microblaze/cpu.c
324
+++ b/target/microblaze/cpu.c
325
@@ -XXX,XX +XXX,XX @@ static void mb_cpu_set_pc(CPUState *cs, vaddr value)
326
cpu->env.iflags = 0;
327
}
328
329
+static vaddr mb_cpu_get_pc(CPUState *cs)
330
+{
331
+ MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
332
+
333
+ return cpu->env.pc;
334
+}
335
+
336
static void mb_cpu_synchronize_from_tb(CPUState *cs,
337
const TranslationBlock *tb)
338
{
339
@@ -XXX,XX +XXX,XX @@ static void mb_cpu_class_init(ObjectClass *oc, void *data)
340
341
cc->dump_state = mb_cpu_dump_state;
342
cc->set_pc = mb_cpu_set_pc;
343
+ cc->get_pc = mb_cpu_get_pc;
344
cc->gdb_read_register = mb_cpu_gdb_read_register;
345
cc->gdb_write_register = mb_cpu_gdb_write_register;
346
347
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
348
index XXXXXXX..XXXXXXX 100644
349
--- a/target/mips/cpu.c
350
+++ b/target/mips/cpu.c
351
@@ -XXX,XX +XXX,XX @@ static void mips_cpu_set_pc(CPUState *cs, vaddr value)
352
mips_env_set_pc(&cpu->env, value);
353
}
354
355
+static vaddr mips_cpu_get_pc(CPUState *cs)
356
+{
357
+ MIPSCPU *cpu = MIPS_CPU(cs);
358
+
359
+ return cpu->env.active_tc.PC;
360
+}
361
+
362
static bool mips_cpu_has_work(CPUState *cs)
363
{
364
MIPSCPU *cpu = MIPS_CPU(cs);
365
@@ -XXX,XX +XXX,XX @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
366
cc->has_work = mips_cpu_has_work;
367
cc->dump_state = mips_cpu_dump_state;
368
cc->set_pc = mips_cpu_set_pc;
369
+ cc->get_pc = mips_cpu_get_pc;
370
cc->gdb_read_register = mips_cpu_gdb_read_register;
371
cc->gdb_write_register = mips_cpu_gdb_write_register;
372
#ifndef CONFIG_USER_ONLY
373
diff --git a/target/nios2/cpu.c b/target/nios2/cpu.c
374
index XXXXXXX..XXXXXXX 100644
375
--- a/target/nios2/cpu.c
376
+++ b/target/nios2/cpu.c
377
@@ -XXX,XX +XXX,XX @@ static void nios2_cpu_set_pc(CPUState *cs, vaddr value)
378
env->pc = value;
379
}
380
381
+static vaddr nios2_cpu_get_pc(CPUState *cs)
382
+{
383
+ Nios2CPU *cpu = NIOS2_CPU(cs);
384
+ CPUNios2State *env = &cpu->env;
385
+
386
+ return env->pc;
387
+}
388
+
389
static bool nios2_cpu_has_work(CPUState *cs)
390
{
391
return cs->interrupt_request & CPU_INTERRUPT_HARD;
392
@@ -XXX,XX +XXX,XX @@ static void nios2_cpu_class_init(ObjectClass *oc, void *data)
393
cc->has_work = nios2_cpu_has_work;
394
cc->dump_state = nios2_cpu_dump_state;
395
cc->set_pc = nios2_cpu_set_pc;
396
+ cc->get_pc = nios2_cpu_get_pc;
397
cc->disas_set_info = nios2_cpu_disas_set_info;
398
#ifndef CONFIG_USER_ONLY
399
cc->sysemu_ops = &nios2_sysemu_ops;
400
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
401
index XXXXXXX..XXXXXXX 100644
402
--- a/target/openrisc/cpu.c
403
+++ b/target/openrisc/cpu.c
404
@@ -XXX,XX +XXX,XX @@ static void openrisc_cpu_set_pc(CPUState *cs, vaddr value)
405
cpu->env.dflag = 0;
406
}
407
408
+static vaddr openrisc_cpu_get_pc(CPUState *cs)
409
+{
410
+ OpenRISCCPU *cpu = OPENRISC_CPU(cs);
411
+
412
+ return cpu->env.pc;
413
+}
414
+
415
static void openrisc_cpu_synchronize_from_tb(CPUState *cs,
416
const TranslationBlock *tb)
417
{
418
@@ -XXX,XX +XXX,XX @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
419
cc->has_work = openrisc_cpu_has_work;
420
cc->dump_state = openrisc_cpu_dump_state;
421
cc->set_pc = openrisc_cpu_set_pc;
422
+ cc->get_pc = openrisc_cpu_get_pc;
423
cc->gdb_read_register = openrisc_cpu_gdb_read_register;
424
cc->gdb_write_register = openrisc_cpu_gdb_write_register;
425
#ifndef CONFIG_USER_ONLY
426
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
427
index XXXXXXX..XXXXXXX 100644
428
--- a/target/ppc/cpu_init.c
429
+++ b/target/ppc/cpu_init.c
430
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_set_pc(CPUState *cs, vaddr value)
431
cpu->env.nip = value;
432
}
433
434
+static vaddr ppc_cpu_get_pc(CPUState *cs)
435
+{
436
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
437
+
438
+ return cpu->env.nip;
439
+}
440
+
441
static bool ppc_cpu_has_work(CPUState *cs)
442
{
443
PowerPCCPU *cpu = POWERPC_CPU(cs);
444
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
445
cc->has_work = ppc_cpu_has_work;
446
cc->dump_state = ppc_cpu_dump_state;
447
cc->set_pc = ppc_cpu_set_pc;
448
+ cc->get_pc = ppc_cpu_get_pc;
449
cc->gdb_read_register = ppc_cpu_gdb_read_register;
450
cc->gdb_write_register = ppc_cpu_gdb_write_register;
451
#ifndef CONFIG_USER_ONLY
452
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
453
index XXXXXXX..XXXXXXX 100644
454
--- a/target/riscv/cpu.c
455
+++ b/target/riscv/cpu.c
456
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_set_pc(CPUState *cs, vaddr value)
457
}
458
}
459
460
+static vaddr riscv_cpu_get_pc(CPUState *cs)
461
+{
462
+ RISCVCPU *cpu = RISCV_CPU(cs);
463
+ CPURISCVState *env = &cpu->env;
464
+
465
+ /* Match cpu_get_tb_cpu_state. */
466
+ if (env->xl == MXL_RV32) {
467
+ return env->pc & UINT32_MAX;
468
+ }
469
+ return env->pc;
470
+}
471
+
472
static void riscv_cpu_synchronize_from_tb(CPUState *cs,
473
const TranslationBlock *tb)
474
{
475
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
476
cc->has_work = riscv_cpu_has_work;
477
cc->dump_state = riscv_cpu_dump_state;
478
cc->set_pc = riscv_cpu_set_pc;
479
+ cc->get_pc = riscv_cpu_get_pc;
480
cc->gdb_read_register = riscv_cpu_gdb_read_register;
481
cc->gdb_write_register = riscv_cpu_gdb_write_register;
482
cc->gdb_num_core_regs = 33;
483
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
484
index XXXXXXX..XXXXXXX 100644
485
--- a/target/rx/cpu.c
486
+++ b/target/rx/cpu.c
487
@@ -XXX,XX +XXX,XX @@ static void rx_cpu_set_pc(CPUState *cs, vaddr value)
488
cpu->env.pc = value;
489
}
490
491
+static vaddr rx_cpu_get_pc(CPUState *cs)
492
+{
493
+ RXCPU *cpu = RX_CPU(cs);
494
+
495
+ return cpu->env.pc;
496
+}
497
+
498
static void rx_cpu_synchronize_from_tb(CPUState *cs,
499
const TranslationBlock *tb)
500
{
501
@@ -XXX,XX +XXX,XX @@ static void rx_cpu_class_init(ObjectClass *klass, void *data)
502
cc->has_work = rx_cpu_has_work;
503
cc->dump_state = rx_cpu_dump_state;
504
cc->set_pc = rx_cpu_set_pc;
505
+ cc->get_pc = rx_cpu_get_pc;
506
507
#ifndef CONFIG_USER_ONLY
508
cc->sysemu_ops = &rx_sysemu_ops;
509
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
510
index XXXXXXX..XXXXXXX 100644
511
--- a/target/s390x/cpu.c
512
+++ b/target/s390x/cpu.c
513
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_set_pc(CPUState *cs, vaddr value)
514
cpu->env.psw.addr = value;
515
}
516
517
+static vaddr s390_cpu_get_pc(CPUState *cs)
518
+{
519
+ S390CPU *cpu = S390_CPU(cs);
520
+
521
+ return cpu->env.psw.addr;
522
+}
523
+
524
static bool s390_cpu_has_work(CPUState *cs)
525
{
526
S390CPU *cpu = S390_CPU(cs);
527
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
528
cc->has_work = s390_cpu_has_work;
529
cc->dump_state = s390_cpu_dump_state;
530
cc->set_pc = s390_cpu_set_pc;
531
+ cc->get_pc = s390_cpu_get_pc;
532
cc->gdb_read_register = s390_cpu_gdb_read_register;
533
cc->gdb_write_register = s390_cpu_gdb_write_register;
534
#ifndef CONFIG_USER_ONLY
535
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
536
index XXXXXXX..XXXXXXX 100644
537
--- a/target/sh4/cpu.c
538
+++ b/target/sh4/cpu.c
539
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_set_pc(CPUState *cs, vaddr value)
540
cpu->env.pc = value;
541
}
542
543
+static vaddr superh_cpu_get_pc(CPUState *cs)
544
+{
545
+ SuperHCPU *cpu = SUPERH_CPU(cs);
546
+
547
+ return cpu->env.pc;
548
+}
549
+
550
static void superh_cpu_synchronize_from_tb(CPUState *cs,
551
const TranslationBlock *tb)
552
{
553
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_class_init(ObjectClass *oc, void *data)
554
cc->has_work = superh_cpu_has_work;
555
cc->dump_state = superh_cpu_dump_state;
556
cc->set_pc = superh_cpu_set_pc;
557
+ cc->get_pc = superh_cpu_get_pc;
558
cc->gdb_read_register = superh_cpu_gdb_read_register;
559
cc->gdb_write_register = superh_cpu_gdb_write_register;
560
#ifndef CONFIG_USER_ONLY
561
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
562
index XXXXXXX..XXXXXXX 100644
563
--- a/target/sparc/cpu.c
564
+++ b/target/sparc/cpu.c
565
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
566
cpu->env.npc = value + 4;
567
}
568
569
+static vaddr sparc_cpu_get_pc(CPUState *cs)
570
+{
571
+ SPARCCPU *cpu = SPARC_CPU(cs);
572
+
573
+ return cpu->env.pc;
574
+}
575
+
576
static void sparc_cpu_synchronize_from_tb(CPUState *cs,
577
const TranslationBlock *tb)
578
{
579
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data)
580
cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
581
#endif
582
cc->set_pc = sparc_cpu_set_pc;
583
+ cc->get_pc = sparc_cpu_get_pc;
584
cc->gdb_read_register = sparc_cpu_gdb_read_register;
585
cc->gdb_write_register = sparc_cpu_gdb_write_register;
586
#ifndef CONFIG_USER_ONLY
587
diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c
588
index XXXXXXX..XXXXXXX 100644
589
--- a/target/tricore/cpu.c
590
+++ b/target/tricore/cpu.c
591
@@ -XXX,XX +XXX,XX @@ static void tricore_cpu_set_pc(CPUState *cs, vaddr value)
592
env->PC = value & ~(target_ulong)1;
593
}
594
595
+static vaddr tricore_cpu_get_pc(CPUState *cs)
596
+{
597
+ TriCoreCPU *cpu = TRICORE_CPU(cs);
598
+ CPUTriCoreState *env = &cpu->env;
599
+
600
+ return env->PC;
601
+}
602
+
603
static void tricore_cpu_synchronize_from_tb(CPUState *cs,
604
const TranslationBlock *tb)
605
{
606
@@ -XXX,XX +XXX,XX @@ static void tricore_cpu_class_init(ObjectClass *c, void *data)
607
608
cc->dump_state = tricore_cpu_dump_state;
609
cc->set_pc = tricore_cpu_set_pc;
610
+ cc->get_pc = tricore_cpu_get_pc;
611
cc->sysemu_ops = &tricore_sysemu_ops;
612
cc->tcg_ops = &tricore_tcg_ops;
613
}
614
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
615
index XXXXXXX..XXXXXXX 100644
616
--- a/target/xtensa/cpu.c
617
+++ b/target/xtensa/cpu.c
618
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_set_pc(CPUState *cs, vaddr value)
619
cpu->env.pc = value;
620
}
621
622
+static vaddr xtensa_cpu_get_pc(CPUState *cs)
623
+{
624
+ XtensaCPU *cpu = XTENSA_CPU(cs);
625
+
626
+ return cpu->env.pc;
627
+}
628
+
629
static bool xtensa_cpu_has_work(CPUState *cs)
630
{
631
#ifndef CONFIG_USER_ONLY
632
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
633
cc->has_work = xtensa_cpu_has_work;
634
cc->dump_state = xtensa_cpu_dump_state;
635
cc->set_pc = xtensa_cpu_set_pc;
636
+ cc->get_pc = xtensa_cpu_get_pc;
637
cc->gdb_read_register = xtensa_cpu_gdb_read_register;
638
cc->gdb_write_register = xtensa_cpu_gdb_write_register;
639
cc->gdb_stop_before_watchpoint = true;
640
--
81
--
641
2.34.1
82
2.34.1
642
83
643
84
diff view generated by jsdifflib
1
Wrap the bare TranslationBlock pointer into a structure.
1
We now have the option to generate direct or indirect
2
goto_tb depending on the dynamic displacement, thus
3
the define is no longer necessary or completely accurate.
2
4
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.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/tb-hash.h | 1 +
8
tcg/aarch64/tcg-target.h | 1 -
8
accel/tcg/tb-jmp-cache.h | 24 ++++++++++++++++++++++++
9
tcg/arm/tcg-target.h | 1 -
9
include/exec/cpu-common.h | 1 +
10
tcg/i386/tcg-target.h | 1 -
10
include/hw/core/cpu.h | 15 +--------------
11
tcg/loongarch64/tcg-target.h | 1 -
11
include/qemu/typedefs.h | 1 +
12
tcg/mips/tcg-target.h | 1 -
12
accel/stubs/tcg-stub.c | 4 ++++
13
tcg/ppc/tcg-target.h | 1 -
13
accel/tcg/cpu-exec.c | 10 +++++++---
14
tcg/riscv/tcg-target.h | 1 -
14
accel/tcg/cputlb.c | 9 +++++----
15
tcg/s390x/tcg-target.h | 1 -
15
accel/tcg/translate-all.c | 28 +++++++++++++++++++++++++---
16
tcg/sparc64/tcg-target.h | 1 -
16
hw/core/cpu-common.c | 3 +--
17
tcg/tci/tcg-target.h | 1 -
17
plugins/core.c | 2 +-
18
accel/tcg/cpu-exec.c | 23 +++++++++++------------
18
trace/control-target.c | 2 +-
19
tcg/tcg.c | 1 -
19
12 files changed, 72 insertions(+), 28 deletions(-)
20
tcg/arm/tcg-target.c.inc | 1 -
20
create mode 100644 accel/tcg/tb-jmp-cache.h
21
tcg/mips/tcg-target.c.inc | 1 -
21
22
tcg/riscv/tcg-target.c.inc | 1 -
22
diff --git a/accel/tcg/tb-hash.h b/accel/tcg/tb-hash.h
23
tcg/s390x/tcg-target.c.inc | 3 +++
23
index XXXXXXX..XXXXXXX 100644
24
tcg/tci/tcg-target.c.inc | 1 -
24
--- a/accel/tcg/tb-hash.h
25
17 files changed, 14 insertions(+), 27 deletions(-)
25
+++ b/accel/tcg/tb-hash.h
26
27
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/tcg/aarch64/tcg-target.h
30
+++ b/tcg/aarch64/tcg-target.h
31
@@ -XXX,XX +XXX,XX @@ typedef enum {
32
#define TCG_TARGET_HAS_muls2_i64 0
33
#define TCG_TARGET_HAS_muluh_i64 1
34
#define TCG_TARGET_HAS_mulsh_i64 1
35
-#define TCG_TARGET_HAS_direct_jump 1
36
37
#define TCG_TARGET_HAS_v64 1
38
#define TCG_TARGET_HAS_v128 1
39
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
40
index XXXXXXX..XXXXXXX 100644
41
--- a/tcg/arm/tcg-target.h
42
+++ b/tcg/arm/tcg-target.h
43
@@ -XXX,XX +XXX,XX @@ extern bool use_neon_instructions;
44
#define TCG_TARGET_HAS_mulsh_i32 0
45
#define TCG_TARGET_HAS_div_i32 use_idiv_instructions
46
#define TCG_TARGET_HAS_rem_i32 0
47
-#define TCG_TARGET_HAS_direct_jump 0
48
#define TCG_TARGET_HAS_qemu_st8_i32 0
49
50
#define TCG_TARGET_HAS_v64 use_neon_instructions
51
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
52
index XXXXXXX..XXXXXXX 100644
53
--- a/tcg/i386/tcg-target.h
54
+++ b/tcg/i386/tcg-target.h
55
@@ -XXX,XX +XXX,XX @@ extern bool have_movbe;
56
#define TCG_TARGET_HAS_muls2_i32 1
57
#define TCG_TARGET_HAS_muluh_i32 0
58
#define TCG_TARGET_HAS_mulsh_i32 0
59
-#define TCG_TARGET_HAS_direct_jump 1
60
61
#if TCG_TARGET_REG_BITS == 64
62
/* Keep target addresses zero-extended in a register. */
63
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
64
index XXXXXXX..XXXXXXX 100644
65
--- a/tcg/loongarch64/tcg-target.h
66
+++ b/tcg/loongarch64/tcg-target.h
67
@@ -XXX,XX +XXX,XX @@ typedef enum {
68
#define TCG_TARGET_HAS_clz_i32 1
69
#define TCG_TARGET_HAS_ctz_i32 1
70
#define TCG_TARGET_HAS_ctpop_i32 0
71
-#define TCG_TARGET_HAS_direct_jump 1
72
#define TCG_TARGET_HAS_brcond2 0
73
#define TCG_TARGET_HAS_setcond2 0
74
#define TCG_TARGET_HAS_qemu_st8_i32 0
75
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
76
index XXXXXXX..XXXXXXX 100644
77
--- a/tcg/mips/tcg-target.h
78
+++ b/tcg/mips/tcg-target.h
79
@@ -XXX,XX +XXX,XX @@ extern bool use_mips32r2_instructions;
80
#define TCG_TARGET_HAS_muluh_i32 1
81
#define TCG_TARGET_HAS_mulsh_i32 1
82
#define TCG_TARGET_HAS_bswap32_i32 1
83
-#define TCG_TARGET_HAS_direct_jump 0
84
85
#if TCG_TARGET_REG_BITS == 64
86
#define TCG_TARGET_HAS_add2_i32 0
87
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
88
index XXXXXXX..XXXXXXX 100644
89
--- a/tcg/ppc/tcg-target.h
90
+++ b/tcg/ppc/tcg-target.h
91
@@ -XXX,XX +XXX,XX @@ extern bool have_vsx;
92
#define TCG_TARGET_HAS_muls2_i32 0
93
#define TCG_TARGET_HAS_muluh_i32 1
94
#define TCG_TARGET_HAS_mulsh_i32 1
95
-#define TCG_TARGET_HAS_direct_jump 1
96
#define TCG_TARGET_HAS_qemu_st8_i32 0
97
98
#if TCG_TARGET_REG_BITS == 64
99
diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
100
index XXXXXXX..XXXXXXX 100644
101
--- a/tcg/riscv/tcg-target.h
102
+++ b/tcg/riscv/tcg-target.h
103
@@ -XXX,XX +XXX,XX @@ typedef enum {
104
#define TCG_TARGET_HAS_clz_i32 0
105
#define TCG_TARGET_HAS_ctz_i32 0
106
#define TCG_TARGET_HAS_ctpop_i32 0
107
-#define TCG_TARGET_HAS_direct_jump 0
108
#define TCG_TARGET_HAS_brcond2 1
109
#define TCG_TARGET_HAS_setcond2 1
110
#define TCG_TARGET_HAS_qemu_st8_i32 0
111
diff --git a/tcg/s390x/tcg-target.h b/tcg/s390x/tcg-target.h
112
index XXXXXXX..XXXXXXX 100644
113
--- a/tcg/s390x/tcg-target.h
114
+++ b/tcg/s390x/tcg-target.h
115
@@ -XXX,XX +XXX,XX @@ extern uint64_t s390_facilities[3];
116
#define TCG_TARGET_HAS_mulsh_i32 0
117
#define TCG_TARGET_HAS_extrl_i64_i32 0
118
#define TCG_TARGET_HAS_extrh_i64_i32 0
119
-#define TCG_TARGET_HAS_direct_jump 1
120
#define TCG_TARGET_HAS_qemu_st8_i32 0
121
122
#define TCG_TARGET_HAS_div2_i64 1
123
diff --git a/tcg/sparc64/tcg-target.h b/tcg/sparc64/tcg-target.h
124
index XXXXXXX..XXXXXXX 100644
125
--- a/tcg/sparc64/tcg-target.h
126
+++ b/tcg/sparc64/tcg-target.h
127
@@ -XXX,XX +XXX,XX @@ extern bool use_vis3_instructions;
128
#define TCG_TARGET_HAS_muls2_i32 1
129
#define TCG_TARGET_HAS_muluh_i32 0
130
#define TCG_TARGET_HAS_mulsh_i32 0
131
-#define TCG_TARGET_HAS_direct_jump 1
132
#define TCG_TARGET_HAS_qemu_st8_i32 0
133
134
#define TCG_TARGET_HAS_extrl_i64_i32 1
135
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
136
index XXXXXXX..XXXXXXX 100644
137
--- a/tcg/tci/tcg-target.h
138
+++ b/tcg/tci/tcg-target.h
26
@@ -XXX,XX +XXX,XX @@
139
@@ -XXX,XX +XXX,XX @@
27
#include "exec/cpu-defs.h"
140
#define TCG_TARGET_HAS_muls2_i32 1
28
#include "exec/exec-all.h"
141
#define TCG_TARGET_HAS_muluh_i32 0
29
#include "qemu/xxhash.h"
142
#define TCG_TARGET_HAS_mulsh_i32 0
30
+#include "tb-jmp-cache.h"
143
-#define TCG_TARGET_HAS_direct_jump 0
31
144
#define TCG_TARGET_HAS_qemu_st8_i32 0
32
#ifdef CONFIG_SOFTMMU
145
33
146
#if TCG_TARGET_REG_BITS == 64
34
diff --git a/accel/tcg/tb-jmp-cache.h b/accel/tcg/tb-jmp-cache.h
35
new file mode 100644
36
index XXXXXXX..XXXXXXX
37
--- /dev/null
38
+++ b/accel/tcg/tb-jmp-cache.h
39
@@ -XXX,XX +XXX,XX @@
40
+/*
41
+ * The per-CPU TranslationBlock jump cache.
42
+ *
43
+ * Copyright (c) 2003 Fabrice Bellard
44
+ *
45
+ * SPDX-License-Identifier: GPL-2.0-or-later
46
+ */
47
+
48
+#ifndef ACCEL_TCG_TB_JMP_CACHE_H
49
+#define ACCEL_TCG_TB_JMP_CACHE_H
50
+
51
+#define TB_JMP_CACHE_BITS 12
52
+#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
53
+
54
+/*
55
+ * Accessed in parallel; all accesses to 'tb' must be atomic.
56
+ */
57
+struct CPUJumpCache {
58
+ struct {
59
+ TranslationBlock *tb;
60
+ } array[TB_JMP_CACHE_SIZE];
61
+};
62
+
63
+#endif /* ACCEL_TCG_TB_JMP_CACHE_H */
64
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
65
index XXXXXXX..XXXXXXX 100644
66
--- a/include/exec/cpu-common.h
67
+++ b/include/exec/cpu-common.h
68
@@ -XXX,XX +XXX,XX @@ void cpu_list_unlock(void);
69
unsigned int cpu_list_generation_id_get(void);
70
71
void tcg_flush_softmmu_tlb(CPUState *cs);
72
+void tcg_flush_jmp_cache(CPUState *cs);
73
74
void tcg_iommu_init_notifier_list(CPUState *cpu);
75
void tcg_iommu_free_notifier_list(CPUState *cpu);
76
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
77
index XXXXXXX..XXXXXXX 100644
78
--- a/include/hw/core/cpu.h
79
+++ b/include/hw/core/cpu.h
80
@@ -XXX,XX +XXX,XX @@ struct kvm_run;
81
struct hax_vcpu_state;
82
struct hvf_vcpu_state;
83
84
-#define TB_JMP_CACHE_BITS 12
85
-#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
86
-
87
/* work queue */
88
89
/* The union type allows passing of 64 bit target pointers on 32 bit
90
@@ -XXX,XX +XXX,XX @@ struct CPUState {
91
CPUArchState *env_ptr;
92
IcountDecr *icount_decr_ptr;
93
94
- /* Accessed in parallel; all accesses must be atomic */
95
- TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE];
96
+ CPUJumpCache *tb_jmp_cache;
97
98
struct GDBRegisterState *gdb_regs;
99
int gdb_num_regs;
100
@@ -XXX,XX +XXX,XX @@ extern CPUTailQ cpus;
101
102
extern __thread CPUState *current_cpu;
103
104
-static inline void cpu_tb_jmp_cache_clear(CPUState *cpu)
105
-{
106
- unsigned int i;
107
-
108
- for (i = 0; i < TB_JMP_CACHE_SIZE; i++) {
109
- qatomic_set(&cpu->tb_jmp_cache[i], NULL);
110
- }
111
-}
112
-
113
/**
114
* qemu_tcg_mttcg_enabled:
115
* Check whether we are running MultiThread TCG or not.
116
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
117
index XXXXXXX..XXXXXXX 100644
118
--- a/include/qemu/typedefs.h
119
+++ b/include/qemu/typedefs.h
120
@@ -XXX,XX +XXX,XX @@ typedef struct CoMutex CoMutex;
121
typedef struct ConfidentialGuestSupport ConfidentialGuestSupport;
122
typedef struct CPUAddressSpace CPUAddressSpace;
123
typedef struct CPUArchState CPUArchState;
124
+typedef struct CPUJumpCache CPUJumpCache;
125
typedef struct CPUState CPUState;
126
typedef struct CPUTLBEntryFull CPUTLBEntryFull;
127
typedef struct DeviceListener DeviceListener;
128
diff --git a/accel/stubs/tcg-stub.c b/accel/stubs/tcg-stub.c
129
index XXXXXXX..XXXXXXX 100644
130
--- a/accel/stubs/tcg-stub.c
131
+++ b/accel/stubs/tcg-stub.c
132
@@ -XXX,XX +XXX,XX @@ void tlb_set_dirty(CPUState *cpu, target_ulong vaddr)
133
{
134
}
135
136
+void tcg_flush_jmp_cache(CPUState *cpu)
137
+{
138
+}
139
+
140
int probe_access_flags(CPUArchState *env, target_ulong addr,
141
MMUAccessType access_type, int mmu_idx,
142
bool nonfault, void **phost, uintptr_t retaddr)
143
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
147
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
144
index XXXXXXX..XXXXXXX 100644
148
index XXXXXXX..XXXXXXX 100644
145
--- a/accel/tcg/cpu-exec.c
149
--- a/accel/tcg/cpu-exec.c
146
+++ b/accel/tcg/cpu-exec.c
150
+++ b/accel/tcg/cpu-exec.c
147
@@ -XXX,XX +XXX,XX @@
151
@@ -XXX,XX +XXX,XX @@ void cpu_exec_step_atomic(CPUState *cpu)
148
#include "sysemu/replay.h"
152
149
#include "sysemu/tcg.h"
153
void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr)
150
#include "exec/helper-proto.h"
154
{
151
+#include "tb-jmp-cache.h"
155
+ /*
152
#include "tb-hash.h"
156
+ * Get the rx view of the structure, from which we find the
153
#include "tb-context.h"
157
+ * executable code address, and tb_target_set_jmp_target can
154
#include "internal.h"
158
+ * produce a pc-relative displacement to jmp_target_addr[n].
155
@@ -XXX,XX +XXX,XX @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
159
+ */
156
tcg_debug_assert(!(cflags & CF_INVALID));
160
+ const TranslationBlock *c_tb = tcg_splitwx_to_rx(tb);
157
161
+ uintptr_t offset = tb->jmp_insn_offset[n];
158
hash = tb_jmp_cache_hash_func(pc);
162
+ uintptr_t jmp_rx = (uintptr_t)tb->tc.ptr + offset;
159
- tb = qatomic_rcu_read(&cpu->tb_jmp_cache[hash]);
163
+ uintptr_t jmp_rw = jmp_rx - tcg_splitwx_diff;
160
+ tb = qatomic_rcu_read(&cpu->tb_jmp_cache->array[hash].tb);
164
+
161
165
tb->jmp_target_addr[n] = addr;
162
if (likely(tb &&
166
- if (TCG_TARGET_HAS_direct_jump) {
163
tb->pc == pc &&
167
- /*
164
@@ -XXX,XX +XXX,XX @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
168
- * Get the rx view of the structure, from which we find the
165
if (tb == NULL) {
169
- * executable code address, and tb_target_set_jmp_target can
166
return NULL;
170
- * produce a pc-relative displacement to jmp_target_addr[n].
167
}
171
- */
168
- qatomic_set(&cpu->tb_jmp_cache[hash], tb);
172
- const TranslationBlock *c_tb = tcg_splitwx_to_rx(tb);
169
+ qatomic_set(&cpu->tb_jmp_cache->array[hash].tb, tb);
173
- uintptr_t offset = tb->jmp_insn_offset[n];
170
return tb;
174
- uintptr_t jmp_rx = (uintptr_t)tb->tc.ptr + offset;
175
- uintptr_t jmp_rw = jmp_rx - tcg_splitwx_diff;
176
- tb_target_set_jmp_target(c_tb, n, jmp_rx, jmp_rw);
177
- }
178
+ tb_target_set_jmp_target(c_tb, n, jmp_rx, jmp_rw);
171
}
179
}
172
180
173
@@ -XXX,XX +XXX,XX @@ int cpu_exec(CPUState *cpu)
181
static inline void tb_add_jump(TranslationBlock *tb, int n,
174
182
diff --git a/tcg/tcg.c b/tcg/tcg.c
175
tb = tb_lookup(cpu, pc, cs_base, flags, cflags);
183
index XXXXXXX..XXXXXXX 100644
176
if (tb == NULL) {
184
--- a/tcg/tcg.c
177
+ uint32_t h;
185
+++ b/tcg/tcg.c
178
+
186
@@ -XXX,XX +XXX,XX @@ static void G_GNUC_UNUSED set_jmp_insn_offset(TCGContext *s, int which)
179
mmap_lock();
187
* We will check for overflow at the end of the opcode loop in
180
tb = tb_gen_code(cpu, pc, cs_base, flags, cflags);
188
* tcg_gen_code, where we bound tcg_current_code_size to UINT16_MAX.
181
mmap_unlock();
189
*/
182
@@ -XXX,XX +XXX,XX @@ int cpu_exec(CPUState *cpu)
190
- tcg_debug_assert(TCG_TARGET_HAS_direct_jump);
183
* We add the TB in the virtual pc hash table
191
s->gen_tb->jmp_insn_offset[which] = tcg_current_code_size(s);
184
* for the fast lookup
185
*/
186
- qatomic_set(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)], tb);
187
+ h = tb_jmp_cache_hash_func(pc);
188
+ qatomic_set(&cpu->tb_jmp_cache->array[h].tb, tb);
189
}
190
191
#ifndef CONFIG_USER_ONLY
192
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/accel/tcg/cputlb.c
195
+++ b/accel/tcg/cputlb.c
196
@@ -XXX,XX +XXX,XX @@ static void tlb_window_reset(CPUTLBDesc *desc, int64_t ns,
197
198
static void tb_jmp_cache_clear_page(CPUState *cpu, target_ulong page_addr)
199
{
200
- unsigned int i, i0 = tb_jmp_cache_hash_page(page_addr);
201
+ int i, i0 = tb_jmp_cache_hash_page(page_addr);
202
+ CPUJumpCache *jc = cpu->tb_jmp_cache;
203
204
for (i = 0; i < TB_JMP_PAGE_SIZE; i++) {
205
- qatomic_set(&cpu->tb_jmp_cache[i0 + i], NULL);
206
+ qatomic_set(&jc->array[i0 + i].tb, NULL);
207
}
208
}
192
}
209
193
210
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data)
194
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
211
195
index XXXXXXX..XXXXXXX 100644
212
qemu_spin_unlock(&env_tlb(env)->c.lock);
196
--- a/tcg/arm/tcg-target.c.inc
213
197
+++ b/tcg/arm/tcg-target.c.inc
214
- cpu_tb_jmp_cache_clear(cpu);
198
@@ -XXX,XX +XXX,XX @@ static void tcg_out_goto_tb(TCGContext *s, int which)
215
+ tcg_flush_jmp_cache(cpu);
199
intptr_t ptr, dif, dil;
216
200
TCGReg base = TCG_REG_PC;
217
if (to_clean == ALL_MMUIDX_BITS) {
201
218
qatomic_set(&env_tlb(env)->c.full_flush_count,
202
- qemu_build_assert(!TCG_TARGET_HAS_direct_jump);
219
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_range_by_mmuidx_async_0(CPUState *cpu,
203
ptr = get_jmp_target_addr(s, which);
220
* longer to clear each entry individually than it will to clear it all.
204
dif = tcg_pcrel_diff(s, (void *)ptr) - 8;
221
*/
205
dil = sextract32(dif, 0, 12);
222
if (d.len >= (TARGET_PAGE_SIZE * TB_JMP_CACHE_SIZE)) {
206
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
223
- cpu_tb_jmp_cache_clear(cpu);
207
index XXXXXXX..XXXXXXX 100644
224
+ tcg_flush_jmp_cache(cpu);
208
--- a/tcg/mips/tcg-target.c.inc
225
return;
209
+++ b/tcg/mips/tcg-target.c.inc
226
}
210
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
227
211
static void tcg_out_goto_tb(TCGContext *s, int which)
228
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
212
{
229
index XXXXXXX..XXXXXXX 100644
213
/* indirect jump method */
230
--- a/accel/tcg/translate-all.c
214
- qemu_build_assert(!TCG_TARGET_HAS_direct_jump);
231
+++ b/accel/tcg/translate-all.c
215
tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_REG_ZERO,
232
@@ -XXX,XX +XXX,XX @@
216
get_jmp_target_addr(s, which));
233
#include "sysemu/tcg.h"
217
tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
234
#include "qapi/error.h"
218
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
235
#include "hw/core/tcg-cpu-ops.h"
219
index XXXXXXX..XXXXXXX 100644
236
+#include "tb-jmp-cache.h"
220
--- a/tcg/riscv/tcg-target.c.inc
237
#include "tb-hash.h"
221
+++ b/tcg/riscv/tcg-target.c.inc
238
#include "tb-context.h"
222
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
239
#include "internal.h"
223
240
@@ -XXX,XX +XXX,XX @@ static void do_tb_flush(CPUState *cpu, run_on_cpu_data tb_flush_count)
224
static void tcg_out_goto_tb(TCGContext *s, int which)
241
}
225
{
242
226
- qemu_build_assert(!TCG_TARGET_HAS_direct_jump);
243
CPU_FOREACH(cpu) {
227
/* indirect jump method */
244
- cpu_tb_jmp_cache_clear(cpu);
228
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO,
245
+ tcg_flush_jmp_cache(cpu);
229
get_jmp_target_addr(s, which));
246
}
230
diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc
247
231
index XXXXXXX..XXXXXXX 100644
248
qht_reset_size(&tb_ctx.htable, CODE_GEN_HTABLE_SIZE);
232
--- a/tcg/s390x/tcg-target.c.inc
249
@@ -XXX,XX +XXX,XX @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
233
+++ b/tcg/s390x/tcg-target.c.inc
250
/* remove the TB from the hash list */
234
@@ -XXX,XX +XXX,XX @@ static void tcg_out_goto_tb(TCGContext *s, int which)
251
h = tb_jmp_cache_hash_func(tb->pc);
235
void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
252
CPU_FOREACH(cpu) {
236
uintptr_t jmp_rx, uintptr_t jmp_rw)
253
- if (qatomic_read(&cpu->tb_jmp_cache[h]) == tb) {
237
{
254
- qatomic_set(&cpu->tb_jmp_cache[h], NULL);
238
+ if (!HAVE_FACILITY(GEN_INST_EXT)) {
255
+ CPUJumpCache *jc = cpu->tb_jmp_cache;
239
+ return;
256
+ if (qatomic_read(&jc->array[h].tb) == tb) {
257
+ qatomic_set(&jc->array[h].tb, NULL);
258
}
259
}
260
261
@@ -XXX,XX +XXX,XX @@ int page_unprotect(target_ulong address, uintptr_t pc)
262
}
263
#endif /* CONFIG_USER_ONLY */
264
265
+/*
266
+ * Called by generic code at e.g. cpu reset after cpu creation,
267
+ * therefore we must be prepared to allocate the jump cache.
268
+ */
269
+void tcg_flush_jmp_cache(CPUState *cpu)
270
+{
271
+ CPUJumpCache *jc = cpu->tb_jmp_cache;
272
+
273
+ if (likely(jc)) {
274
+ for (int i = 0; i < TB_JMP_CACHE_SIZE; i++) {
275
+ qatomic_set(&jc->array[i].tb, NULL);
276
+ }
277
+ } else {
278
+ /* This should happen once during realize, and thus never race. */
279
+ jc = g_new0(CPUJumpCache, 1);
280
+ jc = qatomic_xchg(&cpu->tb_jmp_cache, jc);
281
+ assert(jc == NULL);
282
+ }
240
+ }
283
+}
241
/* patch the branch destination */
284
+
242
uintptr_t addr = tb->jmp_target_addr[n];
285
/* This is a wrapper for common code that can not use CONFIG_SOFTMMU */
243
intptr_t disp = addr - (jmp_rx - 2);
286
void tcg_flush_softmmu_tlb(CPUState *cs)
244
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
287
{
245
index XXXXXXX..XXXXXXX 100644
288
diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c
246
--- a/tcg/tci/tcg-target.c.inc
289
index XXXXXXX..XXXXXXX 100644
247
+++ b/tcg/tci/tcg-target.c.inc
290
--- a/hw/core/cpu-common.c
248
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg)
291
+++ b/hw/core/cpu-common.c
249
292
@@ -XXX,XX +XXX,XX @@ static void cpu_common_reset(DeviceState *dev)
250
static void tcg_out_goto_tb(TCGContext *s, int which)
293
cpu->cflags_next_tb = -1;
251
{
294
252
- qemu_build_assert(!TCG_TARGET_HAS_direct_jump);
295
if (tcg_enabled()) {
253
/* indirect jump method. */
296
- cpu_tb_jmp_cache_clear(cpu);
254
tcg_out_op_p(s, INDEX_op_goto_tb, (void *)get_jmp_target_addr(s, which));
297
-
255
set_jmp_reset_offset(s, which);
298
+ tcg_flush_jmp_cache(cpu);
299
tcg_flush_softmmu_tlb(cpu);
300
}
301
}
302
diff --git a/plugins/core.c b/plugins/core.c
303
index XXXXXXX..XXXXXXX 100644
304
--- a/plugins/core.c
305
+++ b/plugins/core.c
306
@@ -XXX,XX +XXX,XX @@ struct qemu_plugin_ctx *plugin_id_to_ctx_locked(qemu_plugin_id_t id)
307
static void plugin_cpu_update__async(CPUState *cpu, run_on_cpu_data data)
308
{
309
bitmap_copy(cpu->plugin_mask, &data.host_ulong, QEMU_PLUGIN_EV_MAX);
310
- cpu_tb_jmp_cache_clear(cpu);
311
+ tcg_flush_jmp_cache(cpu);
312
}
313
314
static void plugin_cpu_update__locked(gpointer k, gpointer v, gpointer udata)
315
diff --git a/trace/control-target.c b/trace/control-target.c
316
index XXXXXXX..XXXXXXX 100644
317
--- a/trace/control-target.c
318
+++ b/trace/control-target.c
319
@@ -XXX,XX +XXX,XX @@ static void trace_event_synchronize_vcpu_state_dynamic(
320
{
321
bitmap_copy(vcpu->trace_dstate, vcpu->trace_dstate_delayed,
322
CPU_TRACE_DSTATE_MAX_EVENTS);
323
- cpu_tb_jmp_cache_clear(vcpu);
324
+ tcg_flush_jmp_cache(vcpu);
325
}
326
327
void trace_event_set_vcpu_state_dynamic(CPUState *vcpu,
328
--
256
--
329
2.34.1
257
2.34.1
330
258
331
259
diff view generated by jsdifflib
1
This function has two users, who use it incompatibly.
1
The old implementation replaces two insns, swapping between
2
In tlb_flush_page_by_mmuidx_async_0, when flushing a
3
single page, we need to flush exactly two pages.
4
In tlb_flush_range_by_mmuidx_async_0, when flushing a
5
range of pages, we need to flush N+1 pages.
6
2
7
This avoids double-flushing of jmp cache pages in a range.
3
    b    <dest>
4
    nop
5
    br    x30
6
and
7
    adrp    x30, <dest>
8
    addi    x30, x30, lo12:<dest>
9
    br    x30
8
10
11
There is a race condition in which a thread could be stopped at
12
the PC of the second insn, and when restarted does not see the
13
complete address computation and branches to nowhere.
14
15
The new implemetation replaces only one insn, swapping between
16
17
    b    <dest>
18
    br    tmp
19
and
20
    ldr    tmp, <jmp_addr>
21
    br    tmp
22
23
Reported-by: hev <r@hev.cc>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
24
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
25
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
---
26
---
12
accel/tcg/cputlb.c | 25 ++++++++++++++-----------
27
tcg/aarch64/tcg-target.h | 2 +-
13
1 file changed, 14 insertions(+), 11 deletions(-)
28
tcg/aarch64/tcg-target.c.inc | 66 +++++++++++++++---------------------
29
2 files changed, 29 insertions(+), 39 deletions(-)
14
30
15
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
31
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
16
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
17
--- a/accel/tcg/cputlb.c
33
--- a/tcg/aarch64/tcg-target.h
18
+++ b/accel/tcg/cputlb.c
34
+++ b/tcg/aarch64/tcg-target.h
19
@@ -XXX,XX +XXX,XX @@ static void tb_jmp_cache_clear_page(CPUState *cpu, target_ulong page_addr)
35
@@ -XXX,XX +XXX,XX @@
20
}
36
37
#define TCG_TARGET_INSN_UNIT_SIZE 4
38
#define TCG_TARGET_TLB_DISPLACEMENT_BITS 24
39
-#define MAX_CODE_GEN_BUFFER_SIZE (2 * GiB)
40
+#define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1)
41
42
typedef enum {
43
TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3,
44
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
45
index XXXXXXX..XXXXXXX 100644
46
--- a/tcg/aarch64/tcg-target.c.inc
47
+++ b/tcg/aarch64/tcg-target.c.inc
48
@@ -XXX,XX +XXX,XX @@ static void tcg_out_call(TCGContext *s, const tcg_insn_unit *target,
49
tcg_out_call_int(s, target);
21
}
50
}
22
51
23
-static void tb_flush_jmp_cache(CPUState *cpu, target_ulong addr)
52
-void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
53
- uintptr_t jmp_rx, uintptr_t jmp_rw)
24
-{
54
-{
25
- /* Discard jump cache entries for any tb which might potentially
55
- uintptr_t addr = tb->jmp_target_addr[n];
26
- overlap the flushed page. */
56
- tcg_insn_unit i1, i2;
27
- tb_jmp_cache_clear_page(cpu, addr - TARGET_PAGE_SIZE);
57
- TCGType rt = TCG_TYPE_I64;
28
- tb_jmp_cache_clear_page(cpu, addr);
58
- TCGReg rd = TCG_REG_TMP;
59
- uint64_t pair;
60
-
61
- ptrdiff_t offset = addr - jmp_rx;
62
-
63
- if (offset == sextract64(offset, 0, 26)) {
64
- i1 = I3206_B | ((offset >> 2) & 0x3ffffff);
65
- i2 = NOP;
66
- } else {
67
- offset = (addr >> 12) - (jmp_rx >> 12);
68
-
69
- /* patch ADRP */
70
- i1 = I3406_ADRP | (offset & 3) << 29 | (offset & 0x1ffffc) << (5 - 2) | rd;
71
- /* patch ADDI */
72
- i2 = I3401_ADDI | rt << 31 | (addr & 0xfff) << 10 | rd << 5 | rd;
73
- }
74
- pair = (uint64_t)i2 << 32 | i1;
75
- qatomic_set((uint64_t *)jmp_rw, pair);
76
- flush_idcache_range(jmp_rx, jmp_rw, 8);
29
-}
77
-}
30
-
78
-
31
/**
79
static inline void tcg_out_goto_label(TCGContext *s, TCGLabel *l)
32
* tlb_mmu_resize_locked() - perform TLB resize bookkeeping; resize if necessary
80
{
33
* @desc: The CPUTLBDesc portion of the TLB
81
if (!l->has_value) {
34
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_page_by_mmuidx_async_0(CPUState *cpu,
82
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
35
}
83
static void tcg_out_goto_tb(TCGContext *s, int which)
36
qemu_spin_unlock(&env_tlb(env)->c.lock);
84
{
37
85
/*
38
- tb_flush_jmp_cache(cpu, addr);
86
- * Ensure that ADRP+ADD are 8-byte aligned so that an atomic
39
+ /*
87
- * write can be used to patch the target address.
40
+ * Discard jump cache entries for any tb which might potentially
88
+ * Direct branch, or indirect address load, will be patched
41
+ * overlap the flushed page, which includes the previous.
89
+ * by tb_target_set_jmp_target. Assert indirect load offset
42
+ */
90
+ * in range early, regardless of direct branch distance.
43
+ tb_jmp_cache_clear_page(cpu, addr - TARGET_PAGE_SIZE);
91
*/
44
+ tb_jmp_cache_clear_page(cpu, addr);
92
- if ((uintptr_t)s->code_ptr & 7) {
93
- tcg_out32(s, NOP);
94
- }
95
+ intptr_t i_off = tcg_pcrel_diff(s, (void *)get_jmp_target_addr(s, which));
96
+ tcg_debug_assert(i_off == sextract64(i_off, 0, 21));
97
+
98
set_jmp_insn_offset(s, which);
99
- /*
100
- * actual branch destination will be patched by
101
- * tb_target_set_jmp_target later
102
- */
103
- tcg_out_insn(s, 3406, ADRP, TCG_REG_TMP, 0);
104
- tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_TMP, TCG_REG_TMP, 0);
105
+ tcg_out32(s, I3206_B);
106
tcg_out_insn(s, 3207, BR, TCG_REG_TMP);
107
set_jmp_reset_offset(s, which);
45
}
108
}
46
109
47
/**
110
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
48
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_range_by_mmuidx_async_0(CPUState *cpu,
111
+ uintptr_t jmp_rx, uintptr_t jmp_rw)
49
return;
112
+{
50
}
113
+ uintptr_t d_addr = tb->jmp_target_addr[n];
51
114
+ ptrdiff_t d_offset = d_addr - jmp_rx;
52
- for (target_ulong i = 0; i < d.len; i += TARGET_PAGE_SIZE) {
115
+ tcg_insn_unit insn;
53
- tb_flush_jmp_cache(cpu, d.addr + i);
116
+
54
+ /*
117
+ /* Either directly branch, or indirect branch load. */
55
+ * Discard jump cache entries for any tb which might potentially
118
+ if (d_offset == sextract64(d_offset, 0, 28)) {
56
+ * overlap the flushed pages, which includes the previous.
119
+ insn = deposit32(I3206_B, 0, 26, d_offset >> 2);
57
+ */
120
+ } else {
58
+ d.addr -= TARGET_PAGE_SIZE;
121
+ uintptr_t i_addr = (uintptr_t)&tb->jmp_target_addr[n];
59
+ for (target_ulong i = 0, n = d.len / TARGET_PAGE_SIZE + 1; i < n; i++) {
122
+ ptrdiff_t i_offset = i_addr - jmp_rx;
60
+ tb_jmp_cache_clear_page(cpu, d.addr);
123
+
61
+ d.addr += TARGET_PAGE_SIZE;
124
+ /* Note that we asserted this in range in tcg_out_goto_tb. */
62
}
125
+ insn = deposit32(I3305_LDR | TCG_REG_TMP, 0, 5, i_offset >> 2);
63
}
126
+ }
64
127
+ qatomic_set((uint32_t *)jmp_rw, insn);
128
+ flush_idcache_range(jmp_rx, jmp_rw, 4);
129
+}
130
+
131
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
132
const TCGArg args[TCG_MAX_OP_ARGS],
133
const int const_args[TCG_MAX_OP_ARGS])
65
--
134
--
66
2.34.1
135
2.34.1
67
136
68
137
diff view generated by jsdifflib
1
From: Leandro Lupori <leandro.lupori@eldorado.org.br>
1
The old ppc64 implementation replaces 2 or 4 insns, which leaves a race
2
2
condition in which a thread could be stopped at a PC in the middle of
3
PowerPC64 processors handle direct branches better than indirect
3
the sequence, and when restarted does not see the complete address
4
ones, resulting in less stalled cycles and branch misses.
4
computation and branches to nowhere.
5
5
6
However, PPC's tb_target_set_jmp_target() was only using direct
6
The new implemetation replaces only one insn, swapping between
7
branches for 16-bit jumps, while PowerPC64's unconditional branch
7
8
instructions are able to handle displacements of up to 26 bits.
8
    b <dest>
9
To take advantage of this, now jumps whose displacements fit in
9
and
10
between 17 and 26 bits are also converted to direct branches.
10
    mtctr    r31
11
11
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
falling through to a general-case indirect branch.
13
Signed-off-by: Leandro Lupori <leandro.lupori@eldorado.org.br>
13
14
[rth: Expanded some commentary.]
14
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
15
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
16
---
16
---
17
tcg/ppc/tcg-target.c.inc | 119 +++++++++++++++++++++++++++++----------
17
tcg/ppc/tcg-target.h | 3 +-
18
1 file changed, 88 insertions(+), 31 deletions(-)
18
tcg/ppc/tcg-target.c.inc | 158 +++++++++++----------------------------
19
19
2 files changed, 44 insertions(+), 117 deletions(-)
20
21
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/tcg/ppc/tcg-target.h
24
+++ b/tcg/ppc/tcg-target.h
25
@@ -XXX,XX +XXX,XX @@
26
27
#ifdef _ARCH_PPC64
28
# define TCG_TARGET_REG_BITS 64
29
-# define MAX_CODE_GEN_BUFFER_SIZE (2 * GiB)
30
#else
31
# define TCG_TARGET_REG_BITS 32
32
-# define MAX_CODE_GEN_BUFFER_SIZE (32 * MiB)
33
#endif
34
+#define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1)
35
36
#define TCG_TARGET_NB_REGS 64
37
#define TCG_TARGET_INSN_UNIT_SIZE 4
20
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
38
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
21
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
22
--- a/tcg/ppc/tcg-target.c.inc
40
--- a/tcg/ppc/tcg-target.c.inc
23
+++ b/tcg/ppc/tcg-target.c.inc
41
+++ b/tcg/ppc/tcg-target.c.inc
24
@@ -XXX,XX +XXX,XX @@ static void tcg_out_mb(TCGContext *s, TCGArg a0)
42
@@ -XXX,XX +XXX,XX @@ static void tcg_out_mb(TCGContext *s, TCGArg a0)
25
tcg_out32(s, insn);
43
tcg_out32(s, insn);
26
}
44
}
27
45
28
+static inline uint64_t make_pair(tcg_insn_unit i1, tcg_insn_unit i2)
46
-static inline uint64_t make_pair(tcg_insn_unit i1, tcg_insn_unit i2)
47
-{
48
- if (HOST_BIG_ENDIAN) {
49
- return (uint64_t)i1 << 32 | i2;
50
- }
51
- return (uint64_t)i2 << 32 | i1;
52
-}
53
-
54
-static inline void ppc64_replace2(uintptr_t rx, uintptr_t rw,
55
- tcg_insn_unit i0, tcg_insn_unit i1)
56
-{
57
-#if TCG_TARGET_REG_BITS == 64
58
- qatomic_set((uint64_t *)rw, make_pair(i0, i1));
59
- flush_idcache_range(rx, rw, 8);
60
-#else
61
- qemu_build_not_reached();
62
-#endif
63
-}
64
-
65
-static inline void ppc64_replace4(uintptr_t rx, uintptr_t rw,
66
- tcg_insn_unit i0, tcg_insn_unit i1,
67
- tcg_insn_unit i2, tcg_insn_unit i3)
68
-{
69
- uint64_t p[2];
70
-
71
- p[!HOST_BIG_ENDIAN] = make_pair(i0, i1);
72
- p[HOST_BIG_ENDIAN] = make_pair(i2, i3);
73
-
74
- /*
75
- * There's no convenient way to get the compiler to allocate a pair
76
- * of registers at an even index, so copy into r6/r7 and clobber.
77
- */
78
- asm("mr %%r6, %1\n\t"
79
- "mr %%r7, %2\n\t"
80
- "stq %%r6, %0"
81
- : "=Q"(*(__int128 *)rw) : "r"(p[0]), "r"(p[1]) : "r6", "r7");
82
- flush_idcache_range(rx, rw, 16);
83
-}
84
-
85
-void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
86
- uintptr_t jmp_rx, uintptr_t jmp_rw)
87
-{
88
- tcg_insn_unit i0, i1, i2, i3;
89
- uintptr_t addr = tb->jmp_target_addr[n];
90
- intptr_t tb_diff = addr - (uintptr_t)tb->tc.ptr;
91
- intptr_t br_diff = addr - (jmp_rx + 4);
92
- intptr_t lo, hi;
93
-
94
- if (TCG_TARGET_REG_BITS == 32) {
95
- intptr_t diff = addr - jmp_rx;
96
- tcg_debug_assert(in_range_b(diff));
97
- qatomic_set((uint32_t *)jmp_rw, B | (diff & 0x3fffffc));
98
- flush_idcache_range(jmp_rx, jmp_rw, 4);
99
- return;
100
- }
101
-
102
- /*
103
- * For 16-bit displacements, we can use a single add + branch.
104
- * This happens quite often.
105
- */
106
- if (tb_diff == (int16_t)tb_diff) {
107
- i0 = ADDI | TAI(TCG_REG_TB, TCG_REG_TB, tb_diff);
108
- i1 = B | (br_diff & 0x3fffffc);
109
- ppc64_replace2(jmp_rx, jmp_rw, i0, i1);
110
- return;
111
- }
112
-
113
- lo = (int16_t)tb_diff;
114
- hi = (int32_t)(tb_diff - lo);
115
- assert(tb_diff == hi + lo);
116
- i0 = ADDIS | TAI(TCG_REG_TB, TCG_REG_TB, hi >> 16);
117
- i1 = ADDI | TAI(TCG_REG_TB, TCG_REG_TB, lo);
118
-
119
- /*
120
- * Without stq from 2.07, we can only update two insns,
121
- * and those must be the ones that load the target address.
122
- */
123
- if (!have_isa_2_07) {
124
- ppc64_replace2(jmp_rx, jmp_rw, i0, i1);
125
- return;
126
- }
127
-
128
- /*
129
- * For 26-bit displacements, we can use a direct branch.
130
- * Otherwise we still need the indirect branch, which we
131
- * must restore after a potential direct branch write.
132
- */
133
- br_diff -= 4;
134
- if (in_range_b(br_diff)) {
135
- i2 = B | (br_diff & 0x3fffffc);
136
- i3 = NOP;
137
- } else {
138
- i2 = MTSPR | RS(TCG_REG_TB) | CTR;
139
- i3 = BCCTR | BO_ALWAYS;
140
- }
141
- ppc64_replace4(jmp_rx, jmp_rw, i0, i1, i2, i3);
142
-}
143
-
144
static void tcg_out_call_int(TCGContext *s, int lk,
145
const tcg_insn_unit *target)
146
{
147
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg)
148
149
static void tcg_out_goto_tb(TCGContext *s, int which)
150
{
151
- /* Direct jump. */
152
- if (TCG_TARGET_REG_BITS == 64) {
153
- /* Ensure the next insns are 8 or 16-byte aligned. */
154
- while ((uintptr_t)s->code_ptr & (have_isa_2_07 ? 15 : 7)) {
155
- tcg_out32(s, NOP);
156
- }
157
+ uintptr_t ptr = get_jmp_target_addr(s, which);
158
+
159
+ if (USE_REG_TB) {
160
+ ptrdiff_t offset = tcg_tbrel_diff(s, (void *)ptr);
161
+ tcg_out_mem_long(s, LD, LDX, TCG_REG_TB, TCG_REG_TB, offset);
162
+
163
+ /* Direct branch will be patched by tb_target_set_jmp_target. */
164
set_jmp_insn_offset(s, which);
165
- tcg_out32(s, ADDIS | TAI(TCG_REG_TB, TCG_REG_TB, 0));
166
- tcg_out32(s, ADDI | TAI(TCG_REG_TB, TCG_REG_TB, 0));
167
tcg_out32(s, MTSPR | RS(TCG_REG_TB) | CTR);
168
+
169
+ /* When branch is out of range, fall through to indirect. */
170
+ tcg_out32(s, BCCTR | BO_ALWAYS);
171
+
172
+ /* For the unlinked case, need to reset TCG_REG_TB. */
173
+ set_jmp_reset_offset(s, which);
174
+ tcg_out_mem_long(s, ADDI, ADD, TCG_REG_TB, TCG_REG_TB,
175
+ -tcg_current_code_size(s));
176
+ } else {
177
+ /* Direct branch will be patched by tb_target_set_jmp_target. */
178
+ set_jmp_insn_offset(s, which);
179
+ tcg_out32(s, NOP);
180
+
181
+ /* When branch is out of range, fall through to indirect. */
182
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP1, ptr - (int16_t)ptr);
183
+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_REG_TMP1, (int16_t)ptr);
184
+ tcg_out32(s, MTSPR | RS(TCG_REG_TMP1) | CTR);
185
tcg_out32(s, BCCTR | BO_ALWAYS);
186
set_jmp_reset_offset(s, which);
187
- if (USE_REG_TB) {
188
- /* For the unlinked case, need to reset TCG_REG_TB. */
189
- tcg_out_mem_long(s, ADDI, ADD, TCG_REG_TB, TCG_REG_TB,
190
- -tcg_current_code_size(s));
191
- }
192
- } else {
193
- set_jmp_insn_offset(s, which);
194
- tcg_out32(s, B);
195
- set_jmp_reset_offset(s, which);
196
}
197
}
198
199
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
200
+ uintptr_t jmp_rx, uintptr_t jmp_rw)
29
+{
201
+{
30
+ if (HOST_BIG_ENDIAN) {
202
+ uintptr_t addr = tb->jmp_target_addr[n];
31
+ return (uint64_t)i1 << 32 | i2;
203
+ intptr_t diff = addr - jmp_rx;
204
+ tcg_insn_unit insn;
205
+
206
+ if (in_range_b(diff)) {
207
+ insn = B | (diff & 0x3fffffc);
208
+ } else if (USE_REG_TB) {
209
+ insn = MTSPR | RS(TCG_REG_TB) | CTR;
210
+ } else {
211
+ insn = NOP;
32
+ }
212
+ }
33
+ return (uint64_t)i2 << 32 | i1;
213
+
214
+ qatomic_set((uint32_t *)jmp_rw, insn);
215
+ flush_idcache_range(jmp_rx, jmp_rw, 4);
34
+}
216
+}
35
+
217
+
36
+static inline void ppc64_replace2(uintptr_t rx, uintptr_t rw,
218
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
37
+ tcg_insn_unit i0, tcg_insn_unit i1)
219
const TCGArg args[TCG_MAX_OP_ARGS],
38
+{
220
const int const_args[TCG_MAX_OP_ARGS])
39
+#if TCG_TARGET_REG_BITS == 64
40
+ qatomic_set((uint64_t *)rw, make_pair(i0, i1));
41
+ flush_idcache_range(rx, rw, 8);
42
+#else
43
+ qemu_build_not_reached();
44
+#endif
45
+}
46
+
47
+static inline void ppc64_replace4(uintptr_t rx, uintptr_t rw,
48
+ tcg_insn_unit i0, tcg_insn_unit i1,
49
+ tcg_insn_unit i2, tcg_insn_unit i3)
50
+{
51
+ uint64_t p[2];
52
+
53
+ p[!HOST_BIG_ENDIAN] = make_pair(i0, i1);
54
+ p[HOST_BIG_ENDIAN] = make_pair(i2, i3);
55
+
56
+ /*
57
+ * There's no convenient way to get the compiler to allocate a pair
58
+ * of registers at an even index, so copy into r6/r7 and clobber.
59
+ */
60
+ asm("mr %%r6, %1\n\t"
61
+ "mr %%r7, %2\n\t"
62
+ "stq %%r6, %0"
63
+ : "=Q"(*(__int128 *)rw) : "r"(p[0]), "r"(p[1]) : "r6", "r7");
64
+ flush_idcache_range(rx, rw, 16);
65
+}
66
+
67
void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
68
uintptr_t jmp_rw, uintptr_t addr)
69
{
70
- if (TCG_TARGET_REG_BITS == 64) {
71
- tcg_insn_unit i1, i2;
72
- intptr_t tb_diff = addr - tc_ptr;
73
- intptr_t br_diff = addr - (jmp_rx + 4);
74
- uint64_t pair;
75
+ tcg_insn_unit i0, i1, i2, i3;
76
+ intptr_t tb_diff = addr - tc_ptr;
77
+ intptr_t br_diff = addr - (jmp_rx + 4);
78
+ intptr_t lo, hi;
79
80
- /* This does not exercise the range of the branch, but we do
81
- still need to be able to load the new value of TCG_REG_TB.
82
- But this does still happen quite often. */
83
- if (tb_diff == (int16_t)tb_diff) {
84
- i1 = ADDI | TAI(TCG_REG_TB, TCG_REG_TB, tb_diff);
85
- i2 = B | (br_diff & 0x3fffffc);
86
- } else {
87
- intptr_t lo = (int16_t)tb_diff;
88
- intptr_t hi = (int32_t)(tb_diff - lo);
89
- assert(tb_diff == hi + lo);
90
- i1 = ADDIS | TAI(TCG_REG_TB, TCG_REG_TB, hi >> 16);
91
- i2 = ADDI | TAI(TCG_REG_TB, TCG_REG_TB, lo);
92
- }
93
-#if HOST_BIG_ENDIAN
94
- pair = (uint64_t)i1 << 32 | i2;
95
-#else
96
- pair = (uint64_t)i2 << 32 | i1;
97
-#endif
98
-
99
- /* As per the enclosing if, this is ppc64. Avoid the _Static_assert
100
- within qatomic_set that would fail to build a ppc32 host. */
101
- qatomic_set__nocheck((uint64_t *)jmp_rw, pair);
102
- flush_idcache_range(jmp_rx, jmp_rw, 8);
103
- } else {
104
+ if (TCG_TARGET_REG_BITS == 32) {
105
intptr_t diff = addr - jmp_rx;
106
tcg_debug_assert(in_range_b(diff));
107
qatomic_set((uint32_t *)jmp_rw, B | (diff & 0x3fffffc));
108
flush_idcache_range(jmp_rx, jmp_rw, 4);
109
+ return;
110
}
111
+
112
+ /*
113
+ * For 16-bit displacements, we can use a single add + branch.
114
+ * This happens quite often.
115
+ */
116
+ if (tb_diff == (int16_t)tb_diff) {
117
+ i0 = ADDI | TAI(TCG_REG_TB, TCG_REG_TB, tb_diff);
118
+ i1 = B | (br_diff & 0x3fffffc);
119
+ ppc64_replace2(jmp_rx, jmp_rw, i0, i1);
120
+ return;
121
+ }
122
+
123
+ lo = (int16_t)tb_diff;
124
+ hi = (int32_t)(tb_diff - lo);
125
+ assert(tb_diff == hi + lo);
126
+ i0 = ADDIS | TAI(TCG_REG_TB, TCG_REG_TB, hi >> 16);
127
+ i1 = ADDI | TAI(TCG_REG_TB, TCG_REG_TB, lo);
128
+
129
+ /*
130
+ * Without stq from 2.07, we can only update two insns,
131
+ * and those must be the ones that load the target address.
132
+ */
133
+ if (!have_isa_2_07) {
134
+ ppc64_replace2(jmp_rx, jmp_rw, i0, i1);
135
+ return;
136
+ }
137
+
138
+ /*
139
+ * For 26-bit displacements, we can use a direct branch.
140
+ * Otherwise we still need the indirect branch, which we
141
+ * must restore after a potential direct branch write.
142
+ */
143
+ br_diff -= 4;
144
+ if (in_range_b(br_diff)) {
145
+ i2 = B | (br_diff & 0x3fffffc);
146
+ i3 = NOP;
147
+ } else {
148
+ i2 = MTSPR | RS(TCG_REG_TB) | CTR;
149
+ i3 = BCCTR | BO_ALWAYS;
150
+ }
151
+ ppc64_replace4(jmp_rx, jmp_rw, i0, i1, i2, i3);
152
}
153
154
static void tcg_out_call_int(TCGContext *s, int lk,
155
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
156
if (s->tb_jmp_insn_offset) {
157
/* Direct jump. */
158
if (TCG_TARGET_REG_BITS == 64) {
159
- /* Ensure the next insns are 8-byte aligned. */
160
- if ((uintptr_t)s->code_ptr & 7) {
161
+ /* Ensure the next insns are 8 or 16-byte aligned. */
162
+ while ((uintptr_t)s->code_ptr & (have_isa_2_07 ? 15 : 7)) {
163
tcg_out32(s, NOP);
164
}
165
s->tb_jmp_insn_offset[args[0]] = tcg_current_code_size(s);
166
--
221
--
167
2.34.1
222
2.34.1
223
224
diff view generated by jsdifflib
1
This bitmap is created and discarded immediately.
1
This is always true for sparc64, so this is dead since 3a5f6805c7ca.
2
We gain nothing by its existence.
3
2
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-Id: <20220822232338.1727934-2-richard.henderson@linaro.org>
7
---
6
---
8
accel/tcg/translate-all.c | 78 ++-------------------------------------
7
tcg/sparc64/tcg-target.c.inc | 62 ++++++++++++------------------------
9
1 file changed, 4 insertions(+), 74 deletions(-)
8
1 file changed, 21 insertions(+), 41 deletions(-)
10
9
11
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
10
diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc
12
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
13
--- a/accel/tcg/translate-all.c
12
--- a/tcg/sparc64/tcg-target.c.inc
14
+++ b/accel/tcg/translate-all.c
13
+++ b/tcg/sparc64/tcg-target.c.inc
15
@@ -XXX,XX +XXX,XX @@
14
@@ -XXX,XX +XXX,XX @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
16
#define assert_memory_lock() tcg_debug_assert(have_mmap_lock())
17
#endif
15
#endif
18
16
19
-#define SMC_BITMAP_USE_THRESHOLD 10
17
#define TCG_REG_TB TCG_REG_I1
20
-
18
-#define USE_REG_TB (sizeof(void *) > 4)
21
typedef struct PageDesc {
19
22
/* list of TBs intersecting this ram page */
20
static const int tcg_target_reg_alloc_order[] = {
23
uintptr_t first_tb;
21
TCG_REG_L0,
24
-#ifdef CONFIG_SOFTMMU
22
@@ -XXX,XX +XXX,XX @@ static void tcg_out_movi_int(TCGContext *s, TCGType type, TCGReg ret,
25
- /* in order to optimize self modifying code, we count the number
23
}
26
- of lookups we do to a given page to use a bitmap */
24
27
- unsigned long *code_bitmap;
25
/* A 13-bit constant relative to the TB. */
28
- unsigned int code_write_count;
26
- if (!in_prologue && USE_REG_TB) {
29
-#else
27
+ if (!in_prologue) {
30
+#ifdef CONFIG_USER_ONLY
28
test = tcg_tbrel_diff(s, (void *)arg);
31
unsigned long flags;
29
if (check_fit_ptr(test, 13)) {
32
void *target_data;
30
tcg_out_arithi(s, ret, TCG_REG_TB, test, ARITH_ADD);
31
@@ -XXX,XX +XXX,XX @@ static void tcg_out_movi_int(TCGContext *s, TCGType type, TCGReg ret,
32
}
33
34
/* Use the constant pool, if possible. */
35
- if (!in_prologue && USE_REG_TB) {
36
+ if (!in_prologue) {
37
new_pool_label(s, arg, R_SPARC_13, s->code_ptr,
38
tcg_tbrel_diff(s, NULL));
39
tcg_out32(s, LDX | INSN_RD(ret) | INSN_RS1(TCG_REG_TB));
40
@@ -XXX,XX +XXX,XX @@ static void tcg_target_qemu_prologue(TCGContext *s)
33
#endif
41
#endif
34
-#ifndef CONFIG_USER_ONLY
42
35
+#ifdef CONFIG_SOFTMMU
43
/* We choose TCG_REG_TB such that no move is required. */
36
QemuSpin lock;
44
- if (USE_REG_TB) {
37
#endif
45
- QEMU_BUILD_BUG_ON(TCG_REG_TB != TCG_REG_I1);
38
} PageDesc;
46
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_TB);
39
@@ -XXX,XX +XXX,XX @@ void tb_htable_init(void)
47
- }
40
qht_init(&tb_ctx.htable, tb_cmp, CODE_GEN_HTABLE_SIZE, mode);
48
+ QEMU_BUILD_BUG_ON(TCG_REG_TB != TCG_REG_I1);
41
}
49
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_TB);
42
50
43
-/* call with @p->lock held */
51
tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I1, 0, JMPL);
44
-static inline void invalidate_page_bitmap(PageDesc *p)
52
/* delay slot */
45
-{
53
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
46
- assert_page_locked(p);
54
tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN);
47
-#ifdef CONFIG_SOFTMMU
55
tcg_out_movi_imm13(s, TCG_REG_O0, a0);
48
- g_free(p->code_bitmap);
56
return;
49
- p->code_bitmap = NULL;
57
- } else if (USE_REG_TB) {
50
- p->code_write_count = 0;
58
+ } else {
51
-#endif
59
intptr_t tb_diff = tcg_tbrel_diff(s, (void *)a0);
52
-}
60
if (check_fit_ptr(tb_diff, 13)) {
53
-
61
tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN);
54
/* Set to NULL all the 'first_tb' fields in all PageDescs. */
62
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
55
static void page_flush_tb_1(int level, void **lp)
63
64
static void tcg_out_goto_tb(TCGContext *s, int which)
56
{
65
{
57
@@ -XXX,XX +XXX,XX @@ static void page_flush_tb_1(int level, void **lp)
66
+ int c;
58
for (i = 0; i < V_L2_SIZE; ++i) {
67
+
59
page_lock(&pd[i]);
68
/* Direct jump. */
60
pd[i].first_tb = (uintptr_t)NULL;
69
- if (USE_REG_TB) {
61
- invalidate_page_bitmap(pd + i);
70
- /* make sure the patch is 8-byte aligned. */
62
page_unlock(&pd[i]);
71
- if ((intptr_t)s->code_ptr & 4) {
63
}
72
- tcg_out_nop(s);
64
} else {
73
- }
65
@@ -XXX,XX +XXX,XX @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
74
- set_jmp_insn_offset(s, which);
66
if (rm_from_page_list) {
75
- tcg_out_sethi(s, TCG_REG_T1, 0);
67
p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
76
- tcg_out_arithi(s, TCG_REG_T1, TCG_REG_T1, 0, ARITH_OR);
68
tb_page_remove(p, tb);
77
- tcg_out_arith(s, TCG_REG_G0, TCG_REG_TB, TCG_REG_T1, JMPL);
69
- invalidate_page_bitmap(p);
78
- tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD);
70
if (tb->page_addr[1] != -1) {
79
- } else {
71
p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
80
- set_jmp_insn_offset(s, which);
72
tb_page_remove(p, tb);
81
- tcg_out32(s, CALL);
73
- invalidate_page_bitmap(p);
82
+ /* make sure the patch is 8-byte aligned. */
74
}
83
+ if ((intptr_t)s->code_ptr & 4) {
84
tcg_out_nop(s);
75
}
85
}
76
86
+ set_jmp_insn_offset(s, which);
77
@@ -XXX,XX +XXX,XX @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
87
+ tcg_out_sethi(s, TCG_REG_T1, 0);
88
+ tcg_out_arithi(s, TCG_REG_T1, TCG_REG_T1, 0, ARITH_OR);
89
+ tcg_out_arith(s, TCG_REG_G0, TCG_REG_TB, TCG_REG_T1, JMPL);
90
+ tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD);
91
set_jmp_reset_offset(s, which);
92
93
/*
94
* For the unlinked path of goto_tb, we need to reset TCG_REG_TB
95
* to the beginning of this TB.
96
*/
97
- if (USE_REG_TB) {
98
- int c = -tcg_current_code_size(s);
99
- if (check_fit_i32(c, 13)) {
100
- tcg_out_arithi(s, TCG_REG_TB, TCG_REG_TB, c, ARITH_ADD);
101
- } else {
102
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, c);
103
- tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD);
104
- }
105
+ c = -tcg_current_code_size(s);
106
+ if (check_fit_i32(c, 13)) {
107
+ tcg_out_arithi(s, TCG_REG_TB, TCG_REG_TB, c, ARITH_ADD);
108
+ } else {
109
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, c);
110
+ tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD);
78
}
111
}
79
}
112
}
80
113
81
-#ifdef CONFIG_SOFTMMU
114
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
82
-/* call with @p->lock held */
115
switch (opc) {
83
-static void build_page_bitmap(PageDesc *p)
116
case INDEX_op_goto_ptr:
84
-{
117
tcg_out_arithi(s, TCG_REG_G0, a0, 0, JMPL);
85
- int n, tb_start, tb_end;
118
- if (USE_REG_TB) {
86
- TranslationBlock *tb;
119
- tcg_out_mov_delay(s, TCG_REG_TB, a0);
120
- } else {
121
- tcg_out_nop(s);
122
- }
123
+ tcg_out_mov_delay(s, TCG_REG_TB, a0);
124
break;
125
case INDEX_op_br:
126
tcg_out_bpcc(s, COND_A, BPCC_PT, arg_label(a0));
127
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
128
tcg_debug_assert(tb_disp == (int32_t)tb_disp);
129
tcg_debug_assert(br_disp == (int32_t)br_disp);
130
131
- if (!USE_REG_TB) {
132
- qatomic_set((uint32_t *)jmp_rw,
133
-         deposit32(CALL, 0, 30, br_disp >> 2));
134
- flush_idcache_range(jmp_rx, jmp_rw, 4);
135
- return;
136
- }
87
-
137
-
88
- assert_page_locked(p);
138
/* This does not exercise the range of the branch, but we do
89
- p->code_bitmap = bitmap_new(TARGET_PAGE_SIZE);
139
still need to be able to load the new value of TCG_REG_TB.
90
-
140
But this does still happen quite often. */
91
- PAGE_FOR_EACH_TB(p, tb, n) {
92
- /* NOTE: this is subtle as a TB may span two physical pages */
93
- if (n == 0) {
94
- /* NOTE: tb_end may be after the end of the page, but
95
- it is not a problem */
96
- tb_start = tb->pc & ~TARGET_PAGE_MASK;
97
- tb_end = tb_start + tb->size;
98
- if (tb_end > TARGET_PAGE_SIZE) {
99
- tb_end = TARGET_PAGE_SIZE;
100
- }
101
- } else {
102
- tb_start = 0;
103
- tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
104
- }
105
- bitmap_set(p->code_bitmap, tb_start, tb_end - tb_start);
106
- }
107
-}
108
-#endif
109
-
110
/* add the tb in the target page and protect it if necessary
111
*
112
* Called with mmap_lock held for user-mode emulation.
113
@@ -XXX,XX +XXX,XX @@ static inline void tb_page_add(PageDesc *p, TranslationBlock *tb,
114
page_already_protected = p->first_tb != (uintptr_t)NULL;
115
#endif
116
p->first_tb = (uintptr_t)tb | n;
117
- invalidate_page_bitmap(p);
118
119
#if defined(CONFIG_USER_ONLY)
120
/* translator_loop() must have made all TB pages non-writable */
121
@@ -XXX,XX +XXX,XX @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
122
/* remove TB from the page(s) if we couldn't insert it */
123
if (unlikely(existing_tb)) {
124
tb_page_remove(p, tb);
125
- invalidate_page_bitmap(p);
126
if (p2) {
127
tb_page_remove(p2, tb);
128
- invalidate_page_bitmap(p2);
129
}
130
tb = existing_tb;
131
}
132
@@ -XXX,XX +XXX,XX @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
133
#if !defined(CONFIG_USER_ONLY)
134
/* if no code remaining, no need to continue to use slow writes */
135
if (!p->first_tb) {
136
- invalidate_page_bitmap(p);
137
tlb_unprotect_code(start);
138
}
139
#endif
140
@@ -XXX,XX +XXX,XX @@ void tb_invalidate_phys_page_fast(struct page_collection *pages,
141
}
142
143
assert_page_locked(p);
144
- if (!p->code_bitmap &&
145
- ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD) {
146
- build_page_bitmap(p);
147
- }
148
- if (p->code_bitmap) {
149
- unsigned int nr;
150
- unsigned long b;
151
-
152
- nr = start & ~TARGET_PAGE_MASK;
153
- b = p->code_bitmap[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG - 1));
154
- if (b & ((1 << len) - 1)) {
155
- goto do_invalidate;
156
- }
157
- } else {
158
- do_invalidate:
159
- tb_invalidate_phys_page_range__locked(pages, p, start, start + len,
160
- retaddr);
161
- }
162
+ tb_invalidate_phys_page_range__locked(pages, p, start, start + len,
163
+ retaddr);
164
}
165
#else
166
/* Called with mmap_lock held. If pc is not 0 then it indicates the
167
--
141
--
168
2.34.1
142
2.34.1
169
143
170
144
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
The old sparc64 implementation may replace two insns, which leaves
2
a race condition in which a thread could be stopped at a PC in the
3
middle of the sequence, and when restarted does not see the complete
4
address computation and branches to nowhere.
2
5
3
Before: 35.912 s ± 0.168 s
6
The new implemetation replaces only one insn, swapping between a
4
After: 35.565 s ± 0.087 s
7
direct branch and a direct call. The TCG_REG_TB register is loaded
8
from tb->jmp_target_addr[] in the delay slot.
5
9
6
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-Id: <20220811151413.3350684-5-alex.bennee@linaro.org>
9
Signed-off-by: Cédric Le Goater <clg@kaod.org>
10
Message-Id: <20220923084803.498337-5-clg@kaod.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
---
12
---
13
accel/tcg/cputlb.c | 15 ++++++---------
13
tcg/sparc64/tcg-target.c.inc | 87 +++++++++++++++---------------------
14
1 file changed, 6 insertions(+), 9 deletions(-)
14
1 file changed, 37 insertions(+), 50 deletions(-)
15
15
16
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
16
diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/accel/tcg/cputlb.c
18
--- a/tcg/sparc64/tcg-target.c.inc
19
+++ b/accel/tcg/cputlb.c
19
+++ b/tcg/sparc64/tcg-target.c.inc
20
@@ -XXX,XX +XXX,XX @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
20
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
21
static void tlb_fill(CPUState *cpu, target_ulong addr, int size,
21
22
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
22
static void tcg_out_goto_tb(TCGContext *s, int which)
23
{
23
{
24
- CPUClass *cc = CPU_GET_CLASS(cpu);
24
- int c;
25
bool ok;
25
+ ptrdiff_t off = tcg_tbrel_diff(s, (void *)get_jmp_target_addr(s, which));
26
27
- /* Direct jump. */
28
- /* make sure the patch is 8-byte aligned. */
29
- if ((intptr_t)s->code_ptr & 4) {
30
- tcg_out_nop(s);
31
- }
32
+ /* Direct branch will be patched by tb_target_set_jmp_target. */
33
set_jmp_insn_offset(s, which);
34
- tcg_out_sethi(s, TCG_REG_T1, 0);
35
- tcg_out_arithi(s, TCG_REG_T1, TCG_REG_T1, 0, ARITH_OR);
36
- tcg_out_arith(s, TCG_REG_G0, TCG_REG_TB, TCG_REG_T1, JMPL);
37
- tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD);
38
+ tcg_out32(s, CALL);
39
+ /* delay slot */
40
+ tcg_debug_assert(check_fit_ptr(off, 13));
41
+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TB, TCG_REG_TB, off);
42
set_jmp_reset_offset(s, which);
26
43
27
/*
44
/*
28
* This is not a probe, so only valid return is success; failure
45
* For the unlinked path of goto_tb, we need to reset TCG_REG_TB
29
* should result in exception + longjmp to the cpu loop.
46
* to the beginning of this TB.
30
*/
47
*/
31
- ok = cc->tcg_ops->tlb_fill(cpu, addr, size,
48
- c = -tcg_current_code_size(s);
32
- access_type, mmu_idx, false, retaddr);
49
- if (check_fit_i32(c, 13)) {
33
+ ok = cpu->cc->tcg_ops->tlb_fill(cpu, addr, size,
50
- tcg_out_arithi(s, TCG_REG_TB, TCG_REG_TB, c, ARITH_ADD);
34
+ access_type, mmu_idx, false, retaddr);
51
+ off = -tcg_current_code_size(s);
35
assert(ok);
52
+ if (check_fit_i32(off, 13)) {
53
+ tcg_out_arithi(s, TCG_REG_TB, TCG_REG_TB, off, ARITH_ADD);
54
} else {
55
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, c);
56
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, off);
57
tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD);
58
}
36
}
59
}
37
60
38
@@ -XXX,XX +XXX,XX @@ static inline void cpu_unaligned_access(CPUState *cpu, vaddr addr,
61
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
39
MMUAccessType access_type,
62
+ uintptr_t jmp_rx, uintptr_t jmp_rw)
40
int mmu_idx, uintptr_t retaddr)
63
+{
64
+ uintptr_t addr = tb->jmp_target_addr[n];
65
+ intptr_t br_disp = (intptr_t)(addr - jmp_rx) >> 2;
66
+ tcg_insn_unit insn;
67
+
68
+ br_disp >>= 2;
69
+ if (check_fit_ptr(br_disp, 19)) {
70
+ /* ba,pt %icc, addr */
71
+ insn = deposit32(INSN_OP(0) | INSN_OP2(1) | INSN_COND(COND_A)
72
+ | BPCC_ICC | BPCC_PT, 0, 19, br_disp);
73
+ } else if (check_fit_ptr(br_disp, 22)) {
74
+ /* ba addr */
75
+ insn = deposit32(INSN_OP(0) | INSN_OP2(2) | INSN_COND(COND_A),
76
+ 0, 22, br_disp);
77
+ } else {
78
+ /* The code_gen_buffer can't be larger than 2GB. */
79
+ tcg_debug_assert(check_fit_ptr(br_disp, 30));
80
+ /* call addr */
81
+ insn = deposit32(CALL, 0, 30, br_disp);
82
+ }
83
+
84
+ qatomic_set((uint32_t *)jmp_rw, insn);
85
+ flush_idcache_range(jmp_rx, jmp_rw, 4);
86
+}
87
+
88
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
89
const TCGArg args[TCG_MAX_OP_ARGS],
90
const int const_args[TCG_MAX_OP_ARGS])
91
@@ -XXX,XX +XXX,XX @@ void tcg_register_jit(const void *buf, size_t buf_size)
41
{
92
{
42
- CPUClass *cc = CPU_GET_CLASS(cpu);
93
tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
94
}
43
-
95
-
44
- cc->tcg_ops->do_unaligned_access(cpu, addr, access_type, mmu_idx, retaddr);
96
-void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
45
+ cpu->cc->tcg_ops->do_unaligned_access(cpu, addr, access_type,
97
- uintptr_t jmp_rx, uintptr_t jmp_rw)
46
+ mmu_idx, retaddr);
98
-{
47
}
99
- uintptr_t addr = tb->jmp_target_addr[n];
48
100
- intptr_t tb_disp = addr - (uintptr_t)tb->tc.ptr;
49
static inline void cpu_transaction_failed(CPUState *cpu, hwaddr physaddr,
101
- intptr_t br_disp = addr - jmp_rx;
50
@@ -XXX,XX +XXX,XX @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
102
- tcg_insn_unit i1, i2;
51
if (!tlb_hit_page(tlb_addr, page_addr)) {
103
-
52
if (!victim_tlb_hit(env, mmu_idx, index, elt_ofs, page_addr)) {
104
- /* We can reach the entire address space for ILP32.
53
CPUState *cs = env_cpu(env);
105
- For LP64, the code_gen_buffer can't be larger than 2GB. */
54
- CPUClass *cc = CPU_GET_CLASS(cs);
106
- tcg_debug_assert(tb_disp == (int32_t)tb_disp);
55
107
- tcg_debug_assert(br_disp == (int32_t)br_disp);
56
- if (!cc->tcg_ops->tlb_fill(cs, addr, fault_size, access_type,
108
-
57
- mmu_idx, nonfault, retaddr)) {
109
- /* This does not exercise the range of the branch, but we do
58
+ if (!cs->cc->tcg_ops->tlb_fill(cs, addr, fault_size, access_type,
110
- still need to be able to load the new value of TCG_REG_TB.
59
+ mmu_idx, nonfault, retaddr)) {
111
- But this does still happen quite often. */
60
/* Non-faulting page table read failed. */
112
- if (check_fit_ptr(tb_disp, 13)) {
61
*phost = NULL;
113
- /* ba,pt %icc, addr */
62
return TLB_INVALID_MASK;
114
- i1 = (INSN_OP(0) | INSN_OP2(1) | INSN_COND(COND_A)
115
- | BPCC_ICC | BPCC_PT | INSN_OFF19(br_disp));
116
- i2 = (ARITH_ADD | INSN_RD(TCG_REG_TB) | INSN_RS1(TCG_REG_TB)
117
- | INSN_IMM13(tb_disp));
118
- } else if (tb_disp >= 0) {
119
- i1 = SETHI | INSN_RD(TCG_REG_T1) | ((tb_disp & 0xfffffc00) >> 10);
120
- i2 = (ARITH_OR | INSN_RD(TCG_REG_T1) | INSN_RS1(TCG_REG_T1)
121
- | INSN_IMM13(tb_disp & 0x3ff));
122
- } else {
123
- i1 = SETHI | INSN_RD(TCG_REG_T1) | ((~tb_disp & 0xfffffc00) >> 10);
124
- i2 = (ARITH_XOR | INSN_RD(TCG_REG_T1) | INSN_RS1(TCG_REG_T1)
125
- | INSN_IMM13((tb_disp & 0x3ff) | -0x400));
126
- }
127
-
128
- qatomic_set((uint64_t *)jmp_rw, deposit64(i2, 32, 32, i1));
129
- flush_idcache_range(jmp_rx, jmp_rw, 8);
130
-}
63
--
131
--
64
2.34.1
132
2.34.1
65
133
66
134
diff view generated by jsdifflib
1
The value previously chosen overlaps GUSA_MASK.
1
Now that tcg can handle direct and indirect goto_tb
2
simultaneously, we can optimistically leave space for
3
a direct branch and fall back to loading the pointer
4
from the TB for an indirect branch.
2
5
3
Rename all DELAY_SLOT_* and GUSA_* defines to emphasize
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
that they are included in TB_FLAGs. Add aliases for the
5
FPSCR and SR bits that are included in TB_FLAGS, so that
6
we don't accidentally reassign those bits.
7
8
Fixes: 4da06fb3062 ("target/sh4: Implement prctl_unalign_sigbus")
9
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/856
10
Reviewed-by: Yoshinori Sato <ysato@users.sourceforge.jp>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
---
8
---
13
target/sh4/cpu.h | 56 +++++++++++++------------
9
tcg/arm/tcg-target.c.inc | 52 ++++++++++++++++++++++++++++------------
14
linux-user/sh4/signal.c | 6 +--
10
1 file changed, 37 insertions(+), 15 deletions(-)
15
target/sh4/cpu.c | 6 +--
16
target/sh4/helper.c | 6 +--
17
target/sh4/translate.c | 90 ++++++++++++++++++++++-------------------
18
5 files changed, 88 insertions(+), 76 deletions(-)
19
11
20
diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h
12
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
21
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
22
--- a/target/sh4/cpu.h
14
--- a/tcg/arm/tcg-target.c.inc
23
+++ b/target/sh4/cpu.h
15
+++ b/tcg/arm/tcg-target.c.inc
24
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ typedef enum {
25
#define FPSCR_RM_NEAREST (0 << 0)
17
ARITH_BIC = 0xe << 21,
26
#define FPSCR_RM_ZERO (1 << 0)
18
ARITH_MVN = 0xf << 21,
27
19
28
-#define DELAY_SLOT_MASK 0x7
20
+ INSN_B = 0x0a000000,
29
-#define DELAY_SLOT (1 << 0)
21
+
30
-#define DELAY_SLOT_CONDITIONAL (1 << 1)
22
INSN_CLZ = 0x016f0f10,
31
-#define DELAY_SLOT_RTE (1 << 2)
23
INSN_RBIT = 0x06ff0f30,
32
+#define TB_FLAG_DELAY_SLOT (1 << 0)
24
33
+#define TB_FLAG_DELAY_SLOT_COND (1 << 1)
25
@@ -XXX,XX +XXX,XX @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
34
+#define TB_FLAG_DELAY_SLOT_RTE (1 << 2)
26
35
+#define TB_FLAG_PENDING_MOVCA (1 << 3)
27
static void tcg_out_b_imm(TCGContext *s, ARMCond cond, int32_t offset)
36
+#define TB_FLAG_GUSA_SHIFT 4 /* [11:4] */
37
+#define TB_FLAG_GUSA_EXCLUSIVE (1 << 12)
38
+#define TB_FLAG_UNALIGN (1 << 13)
39
+#define TB_FLAG_SR_FD (1 << SR_FD) /* 15 */
40
+#define TB_FLAG_FPSCR_PR FPSCR_PR /* 19 */
41
+#define TB_FLAG_FPSCR_SZ FPSCR_SZ /* 20 */
42
+#define TB_FLAG_FPSCR_FR FPSCR_FR /* 21 */
43
+#define TB_FLAG_SR_RB (1 << SR_RB) /* 29 */
44
+#define TB_FLAG_SR_MD (1 << SR_MD) /* 30 */
45
46
-#define TB_FLAG_PENDING_MOVCA (1 << 3)
47
-#define TB_FLAG_UNALIGN (1 << 4)
48
-
49
-#define GUSA_SHIFT 4
50
-#ifdef CONFIG_USER_ONLY
51
-#define GUSA_EXCLUSIVE (1 << 12)
52
-#define GUSA_MASK ((0xff << GUSA_SHIFT) | GUSA_EXCLUSIVE)
53
-#else
54
-/* Provide dummy versions of the above to allow tests against tbflags
55
- to be elided while avoiding ifdefs. */
56
-#define GUSA_EXCLUSIVE 0
57
-#define GUSA_MASK 0
58
-#endif
59
-
60
-#define TB_FLAG_ENVFLAGS_MASK (DELAY_SLOT_MASK | GUSA_MASK)
61
+#define TB_FLAG_DELAY_SLOT_MASK (TB_FLAG_DELAY_SLOT | \
62
+ TB_FLAG_DELAY_SLOT_COND | \
63
+ TB_FLAG_DELAY_SLOT_RTE)
64
+#define TB_FLAG_GUSA_MASK ((0xff << TB_FLAG_GUSA_SHIFT) | \
65
+ TB_FLAG_GUSA_EXCLUSIVE)
66
+#define TB_FLAG_FPSCR_MASK (TB_FLAG_FPSCR_PR | \
67
+ TB_FLAG_FPSCR_SZ | \
68
+ TB_FLAG_FPSCR_FR)
69
+#define TB_FLAG_SR_MASK (TB_FLAG_SR_FD | \
70
+ TB_FLAG_SR_RB | \
71
+ TB_FLAG_SR_MD)
72
+#define TB_FLAG_ENVFLAGS_MASK (TB_FLAG_DELAY_SLOT_MASK | \
73
+ TB_FLAG_GUSA_MASK)
74
75
typedef struct tlb_t {
76
uint32_t vpn;        /* virtual page number */
77
@@ -XXX,XX +XXX,XX @@ static inline int cpu_mmu_index (CPUSH4State *env, bool ifetch)
78
{
28
{
79
/* The instruction in a RTE delay slot is fetched in privileged
29
- tcg_out32(s, (cond << 28) | 0x0a000000 |
80
mode, but executed in user mode. */
30
+ tcg_out32(s, (cond << 28) | INSN_B |
81
- if (ifetch && (env->flags & DELAY_SLOT_RTE)) {
31
(((offset - 8) >> 2) & 0x00ffffff));
82
+ if (ifetch && (env->flags & TB_FLAG_DELAY_SLOT_RTE)) {
32
}
83
return 0;
33
84
} else {
34
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg)
85
return (env->sr & (1u << SR_MD)) == 0 ? 1 : 0;
35
86
@@ -XXX,XX +XXX,XX @@ static inline void cpu_get_tb_cpu_state(CPUSH4State *env, target_ulong *pc,
36
static void tcg_out_goto_tb(TCGContext *s, int which)
87
{
37
{
88
*pc = env->pc;
38
- /* Indirect jump method */
89
/* For a gUSA region, notice the end of the region. */
39
- intptr_t ptr, dif, dil;
90
- *cs_base = env->flags & GUSA_MASK ? env->gregs[0] : 0;
40
- TCGReg base = TCG_REG_PC;
91
- *flags = env->flags /* TB_FLAG_ENVFLAGS_MASK: bits 0-2, 4-12 */
41
+ uintptr_t i_addr;
92
- | (env->fpscr & (FPSCR_FR | FPSCR_SZ | FPSCR_PR)) /* Bits 19-21 */
42
+ intptr_t i_disp;
93
- | (env->sr & ((1u << SR_MD) | (1u << SR_RB))) /* Bits 29-30 */
43
94
- | (env->sr & (1u << SR_FD)) /* Bit 15 */
44
- ptr = get_jmp_target_addr(s, which);
95
+ *cs_base = env->flags & TB_FLAG_GUSA_MASK ? env->gregs[0] : 0;
45
- dif = tcg_pcrel_diff(s, (void *)ptr) - 8;
96
+ *flags = env->flags
46
- dil = sextract32(dif, 0, 12);
97
+ | (env->fpscr & TB_FLAG_FPSCR_MASK)
47
- if (dif != dil) {
98
+ | (env->sr & TB_FLAG_SR_MASK)
48
+ /* Direct branch will be patched by tb_target_set_jmp_target. */
99
| (env->movcal_backup ? TB_FLAG_PENDING_MOVCA : 0); /* Bit 3 */
49
+ set_jmp_insn_offset(s, which);
100
#ifdef CONFIG_USER_ONLY
50
+ tcg_out32(s, INSN_NOP);
101
*flags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus;
51
+
102
diff --git a/linux-user/sh4/signal.c b/linux-user/sh4/signal.c
52
+ /* When branch is out of range, fall through to indirect. */
103
index XXXXXXX..XXXXXXX 100644
53
+ i_addr = get_jmp_target_addr(s, which);
104
--- a/linux-user/sh4/signal.c
54
+ i_disp = tcg_pcrel_diff(s, (void *)i_addr) - 8;
105
+++ b/linux-user/sh4/signal.c
55
+ tcg_debug_assert(i_disp < 0);
106
@@ -XXX,XX +XXX,XX @@ static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
56
+ if (i_disp >= -0xfff) {
107
__get_user(regs->fpul, &sc->sc_fpul);
57
+ tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, i_disp);
108
58
+ } else {
109
regs->tra = -1; /* disable syscall checks */
59
/*
110
- regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
60
* The TB is close, but outside the 12 bits addressable by
111
+ regs->flags = 0;
61
* the load. We can extend this to 20 bits with a sub of a
62
- * shifted immediate from pc. In the vastly unlikely event
63
- * the code requires more than 1MB, we'll use 2 insns and
64
- * be no worse off.
65
+ * shifted immediate from pc.
66
*/
67
- base = TCG_REG_R0;
68
- tcg_out_movi32(s, COND_AL, base, ptr - dil);
69
+ int h = -i_disp;
70
+ int l = h & 0xfff;
71
+
72
+ h = encode_imm_nofail(h - l);
73
+ tcg_out_dat_imm(s, COND_AL, ARITH_SUB, TCG_REG_R0, TCG_REG_PC, h);
74
+ tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, l);
75
}
76
- tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, base, dil);
77
set_jmp_reset_offset(s, which);
112
}
78
}
113
79
114
void setup_frame(int sig, struct target_sigaction *ka,
80
void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
115
@@ -XXX,XX +XXX,XX @@ void setup_frame(int sig, struct target_sigaction *ka,
81
uintptr_t jmp_rx, uintptr_t jmp_rw)
116
regs->gregs[5] = 0;
82
{
117
regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
83
- /* Always indirect, nothing to do */
118
regs->pc = (unsigned long) ka->_sa_handler;
84
+ uintptr_t addr = tb->jmp_target_addr[n];
119
- regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
85
+ ptrdiff_t offset = addr - (jmp_rx + 8);
120
+ regs->flags &= ~(TB_FLAG_DELAY_SLOT_MASK | TB_FLAG_GUSA_MASK);
86
+ tcg_insn_unit insn;
121
87
+
122
unlock_user_struct(frame, frame_addr, 1);
88
+ /* Either directly branch, or fall through to indirect branch. */
123
return;
89
+ if (offset == sextract64(offset, 0, 26)) {
124
@@ -XXX,XX +XXX,XX @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
90
+ /* B <addr> */
125
regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
91
+ insn = deposit32((COND_AL << 28) | INSN_B, 0, 24, offset >> 2);
126
regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
92
+ } else {
127
regs->pc = (unsigned long) ka->_sa_handler;
93
+ insn = INSN_NOP;
128
- regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
94
+ }
129
+ regs->flags &= ~(TB_FLAG_DELAY_SLOT_MASK | TB_FLAG_GUSA_MASK);
95
+
130
96
+ qatomic_set((uint32_t *)jmp_rw, insn);
131
unlock_user_struct(frame, frame_addr, 1);
97
+ flush_idcache_range(jmp_rx, jmp_rw, 4);
132
return;
133
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
134
index XXXXXXX..XXXXXXX 100644
135
--- a/target/sh4/cpu.c
136
+++ b/target/sh4/cpu.c
137
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_synchronize_from_tb(CPUState *cs,
138
SuperHCPU *cpu = SUPERH_CPU(cs);
139
140
cpu->env.pc = tb_pc(tb);
141
- cpu->env.flags = tb->flags & TB_FLAG_ENVFLAGS_MASK;
142
+ cpu->env.flags = tb->flags;
143
}
98
}
144
99
145
#ifndef CONFIG_USER_ONLY
100
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
146
@@ -XXX,XX +XXX,XX @@ static bool superh_io_recompile_replay_branch(CPUState *cs,
147
SuperHCPU *cpu = SUPERH_CPU(cs);
148
CPUSH4State *env = &cpu->env;
149
150
- if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
151
+ if ((env->flags & (TB_FLAG_DELAY_SLOT | TB_FLAG_DELAY_SLOT_COND))
152
&& env->pc != tb_pc(tb)) {
153
env->pc -= 2;
154
- env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
155
+ env->flags &= ~(TB_FLAG_DELAY_SLOT | TB_FLAG_DELAY_SLOT_COND);
156
return true;
157
}
158
return false;
159
diff --git a/target/sh4/helper.c b/target/sh4/helper.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/target/sh4/helper.c
162
+++ b/target/sh4/helper.c
163
@@ -XXX,XX +XXX,XX @@ void superh_cpu_do_interrupt(CPUState *cs)
164
env->sr |= (1u << SR_BL) | (1u << SR_MD) | (1u << SR_RB);
165
env->lock_addr = -1;
166
167
- if (env->flags & DELAY_SLOT_MASK) {
168
+ if (env->flags & TB_FLAG_DELAY_SLOT_MASK) {
169
/* Branch instruction should be executed again before delay slot. */
170
    env->spc -= 2;
171
    /* Clear flags for exception/interrupt routine. */
172
- env->flags &= ~DELAY_SLOT_MASK;
173
+ env->flags &= ~TB_FLAG_DELAY_SLOT_MASK;
174
}
175
176
if (do_exp) {
177
@@ -XXX,XX +XXX,XX @@ bool superh_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
178
CPUSH4State *env = &cpu->env;
179
180
/* Delay slots are indivisible, ignore interrupts */
181
- if (env->flags & DELAY_SLOT_MASK) {
182
+ if (env->flags & TB_FLAG_DELAY_SLOT_MASK) {
183
return false;
184
} else {
185
superh_cpu_do_interrupt(cs);
186
diff --git a/target/sh4/translate.c b/target/sh4/translate.c
187
index XXXXXXX..XXXXXXX 100644
188
--- a/target/sh4/translate.c
189
+++ b/target/sh4/translate.c
190
@@ -XXX,XX +XXX,XX @@ void superh_cpu_dump_state(CPUState *cs, FILE *f, int flags)
191
         i, env->gregs[i], i + 1, env->gregs[i + 1],
192
         i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]);
193
}
194
- if (env->flags & DELAY_SLOT) {
195
+ if (env->flags & TB_FLAG_DELAY_SLOT) {
196
qemu_printf("in delay slot (delayed_pc=0x%08x)\n",
197
         env->delayed_pc);
198
- } else if (env->flags & DELAY_SLOT_CONDITIONAL) {
199
+ } else if (env->flags & TB_FLAG_DELAY_SLOT_COND) {
200
qemu_printf("in conditional delay slot (delayed_pc=0x%08x)\n",
201
         env->delayed_pc);
202
- } else if (env->flags & DELAY_SLOT_RTE) {
203
+ } else if (env->flags & TB_FLAG_DELAY_SLOT_RTE) {
204
qemu_fprintf(f, "in rte delay slot (delayed_pc=0x%08x)\n",
205
env->delayed_pc);
206
}
207
@@ -XXX,XX +XXX,XX @@ static inline void gen_save_cpu_state(DisasContext *ctx, bool save_pc)
208
209
static inline bool use_exit_tb(DisasContext *ctx)
210
{
211
- return (ctx->tbflags & GUSA_EXCLUSIVE) != 0;
212
+ return (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) != 0;
213
}
214
215
static bool use_goto_tb(DisasContext *ctx, target_ulong dest)
216
@@ -XXX,XX +XXX,XX @@ static void gen_conditional_jump(DisasContext *ctx, target_ulong dest,
217
TCGLabel *l1 = gen_new_label();
218
TCGCond cond_not_taken = jump_if_true ? TCG_COND_EQ : TCG_COND_NE;
219
220
- if (ctx->tbflags & GUSA_EXCLUSIVE) {
221
+ if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
222
/* When in an exclusive region, we must continue to the end.
223
Therefore, exit the region on a taken branch, but otherwise
224
fall through to the next instruction. */
225
tcg_gen_brcondi_i32(cond_not_taken, cpu_sr_t, 0, l1);
226
- tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~GUSA_MASK);
227
+ tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~TB_FLAG_GUSA_MASK);
228
/* Note that this won't actually use a goto_tb opcode because we
229
disallow it in use_goto_tb, but it handles exit + singlestep. */
230
gen_goto_tb(ctx, 0, dest);
231
@@ -XXX,XX +XXX,XX @@ static void gen_delayed_conditional_jump(DisasContext * ctx)
232
tcg_gen_mov_i32(ds, cpu_delayed_cond);
233
tcg_gen_discard_i32(cpu_delayed_cond);
234
235
- if (ctx->tbflags & GUSA_EXCLUSIVE) {
236
+ if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
237
/* When in an exclusive region, we must continue to the end.
238
Therefore, exit the region on a taken branch, but otherwise
239
fall through to the next instruction. */
240
tcg_gen_brcondi_i32(TCG_COND_EQ, ds, 0, l1);
241
242
/* Leave the gUSA region. */
243
- tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~GUSA_MASK);
244
+ tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~TB_FLAG_GUSA_MASK);
245
gen_jump(ctx);
246
247
gen_set_label(l1);
248
@@ -XXX,XX +XXX,XX @@ static inline void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
249
#define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
250
251
#define CHECK_NOT_DELAY_SLOT \
252
- if (ctx->envflags & DELAY_SLOT_MASK) { \
253
- goto do_illegal_slot; \
254
+ if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) { \
255
+ goto do_illegal_slot; \
256
}
257
258
#define CHECK_PRIVILEGED \
259
@@ -XXX,XX +XXX,XX @@ static void _decode_opc(DisasContext * ctx)
260
case 0x000b:        /* rts */
261
    CHECK_NOT_DELAY_SLOT
262
    tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr);
263
- ctx->envflags |= DELAY_SLOT;
264
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
265
    ctx->delayed_pc = (uint32_t) - 1;
266
    return;
267
case 0x0028:        /* clrmac */
268
@@ -XXX,XX +XXX,XX @@ static void _decode_opc(DisasContext * ctx)
269
    CHECK_NOT_DELAY_SLOT
270
gen_write_sr(cpu_ssr);
271
    tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc);
272
- ctx->envflags |= DELAY_SLOT_RTE;
273
+ ctx->envflags |= TB_FLAG_DELAY_SLOT_RTE;
274
    ctx->delayed_pc = (uint32_t) - 1;
275
ctx->base.is_jmp = DISAS_STOP;
276
    return;
277
@@ -XXX,XX +XXX,XX @@ static void _decode_opc(DisasContext * ctx)
278
    return;
279
case 0xe000:        /* mov #imm,Rn */
280
#ifdef CONFIG_USER_ONLY
281
- /* Detect the start of a gUSA region. If so, update envflags
282
- and end the TB. This will allow us to see the end of the
283
- region (stored in R0) in the next TB. */
284
+ /*
285
+ * Detect the start of a gUSA region (mov #-n, r15).
286
+ * If so, update envflags and end the TB. This will allow us
287
+ * to see the end of the region (stored in R0) in the next TB.
288
+ */
289
if (B11_8 == 15 && B7_0s < 0 &&
290
(tb_cflags(ctx->base.tb) & CF_PARALLEL)) {
291
- ctx->envflags = deposit32(ctx->envflags, GUSA_SHIFT, 8, B7_0s);
292
+ ctx->envflags =
293
+ deposit32(ctx->envflags, TB_FLAG_GUSA_SHIFT, 8, B7_0s);
294
ctx->base.is_jmp = DISAS_STOP;
295
}
296
#endif
297
@@ -XXX,XX +XXX,XX @@ static void _decode_opc(DisasContext * ctx)
298
case 0xa000:        /* bra disp */
299
    CHECK_NOT_DELAY_SLOT
300
ctx->delayed_pc = ctx->base.pc_next + 4 + B11_0s * 2;
301
- ctx->envflags |= DELAY_SLOT;
302
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
303
    return;
304
case 0xb000:        /* bsr disp */
305
    CHECK_NOT_DELAY_SLOT
306
tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4);
307
ctx->delayed_pc = ctx->base.pc_next + 4 + B11_0s * 2;
308
- ctx->envflags |= DELAY_SLOT;
309
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
310
    return;
311
}
312
313
@@ -XXX,XX +XXX,XX @@ static void _decode_opc(DisasContext * ctx)
314
    CHECK_NOT_DELAY_SLOT
315
tcg_gen_xori_i32(cpu_delayed_cond, cpu_sr_t, 1);
316
ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2;
317
- ctx->envflags |= DELAY_SLOT_CONDITIONAL;
318
+ ctx->envflags |= TB_FLAG_DELAY_SLOT_COND;
319
    return;
320
case 0x8900:        /* bt label */
321
    CHECK_NOT_DELAY_SLOT
322
@@ -XXX,XX +XXX,XX @@ static void _decode_opc(DisasContext * ctx)
323
    CHECK_NOT_DELAY_SLOT
324
tcg_gen_mov_i32(cpu_delayed_cond, cpu_sr_t);
325
ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2;
326
- ctx->envflags |= DELAY_SLOT_CONDITIONAL;
327
+ ctx->envflags |= TB_FLAG_DELAY_SLOT_COND;
328
    return;
329
case 0x8800:        /* cmp/eq #imm,R0 */
330
tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(0), B7_0s);
331
@@ -XXX,XX +XXX,XX @@ static void _decode_opc(DisasContext * ctx)
332
case 0x0023:        /* braf Rn */
333
    CHECK_NOT_DELAY_SLOT
334
tcg_gen_addi_i32(cpu_delayed_pc, REG(B11_8), ctx->base.pc_next + 4);
335
- ctx->envflags |= DELAY_SLOT;
336
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
337
    ctx->delayed_pc = (uint32_t) - 1;
338
    return;
339
case 0x0003:        /* bsrf Rn */
340
    CHECK_NOT_DELAY_SLOT
341
tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4);
342
    tcg_gen_add_i32(cpu_delayed_pc, REG(B11_8), cpu_pr);
343
- ctx->envflags |= DELAY_SLOT;
344
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
345
    ctx->delayed_pc = (uint32_t) - 1;
346
    return;
347
case 0x4015:        /* cmp/pl Rn */
348
@@ -XXX,XX +XXX,XX @@ static void _decode_opc(DisasContext * ctx)
349
case 0x402b:        /* jmp @Rn */
350
    CHECK_NOT_DELAY_SLOT
351
    tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
352
- ctx->envflags |= DELAY_SLOT;
353
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
354
    ctx->delayed_pc = (uint32_t) - 1;
355
    return;
356
case 0x400b:        /* jsr @Rn */
357
    CHECK_NOT_DELAY_SLOT
358
tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4);
359
    tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
360
- ctx->envflags |= DELAY_SLOT;
361
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
362
    ctx->delayed_pc = (uint32_t) - 1;
363
    return;
364
case 0x400e:        /* ldc Rm,SR */
365
@@ -XXX,XX +XXX,XX @@ static void _decode_opc(DisasContext * ctx)
366
fflush(stderr);
367
#endif
368
do_illegal:
369
- if (ctx->envflags & DELAY_SLOT_MASK) {
370
+ if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) {
371
do_illegal_slot:
372
gen_save_cpu_state(ctx, true);
373
gen_helper_raise_slot_illegal_instruction(cpu_env);
374
@@ -XXX,XX +XXX,XX @@ static void _decode_opc(DisasContext * ctx)
375
376
do_fpu_disabled:
377
gen_save_cpu_state(ctx, true);
378
- if (ctx->envflags & DELAY_SLOT_MASK) {
379
+ if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) {
380
gen_helper_raise_slot_fpu_disable(cpu_env);
381
} else {
382
gen_helper_raise_fpu_disable(cpu_env);
383
@@ -XXX,XX +XXX,XX @@ static void decode_opc(DisasContext * ctx)
384
385
_decode_opc(ctx);
386
387
- if (old_flags & DELAY_SLOT_MASK) {
388
+ if (old_flags & TB_FLAG_DELAY_SLOT_MASK) {
389
/* go out of the delay slot */
390
- ctx->envflags &= ~DELAY_SLOT_MASK;
391
+ ctx->envflags &= ~TB_FLAG_DELAY_SLOT_MASK;
392
393
/* When in an exclusive region, we must continue to the end
394
for conditional branches. */
395
- if (ctx->tbflags & GUSA_EXCLUSIVE
396
- && old_flags & DELAY_SLOT_CONDITIONAL) {
397
+ if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE
398
+ && old_flags & TB_FLAG_DELAY_SLOT_COND) {
399
gen_delayed_conditional_jump(ctx);
400
return;
401
}
402
/* Otherwise this is probably an invalid gUSA region.
403
Drop the GUSA bits so the next TB doesn't see them. */
404
- ctx->envflags &= ~GUSA_MASK;
405
+ ctx->envflags &= ~TB_FLAG_GUSA_MASK;
406
407
tcg_gen_movi_i32(cpu_flags, ctx->envflags);
408
- if (old_flags & DELAY_SLOT_CONDITIONAL) {
409
+ if (old_flags & TB_FLAG_DELAY_SLOT_COND) {
410
     gen_delayed_conditional_jump(ctx);
411
} else {
412
gen_jump(ctx);
413
@@ -XXX,XX +XXX,XX @@ static void decode_gusa(DisasContext *ctx, CPUSH4State *env)
414
}
415
416
/* The entire region has been translated. */
417
- ctx->envflags &= ~GUSA_MASK;
418
+ ctx->envflags &= ~TB_FLAG_GUSA_MASK;
419
ctx->base.pc_next = pc_end;
420
ctx->base.num_insns += max_insns - 1;
421
return;
422
@@ -XXX,XX +XXX,XX @@ static void decode_gusa(DisasContext *ctx, CPUSH4State *env)
423
424
/* Restart with the EXCLUSIVE bit set, within a TB run via
425
cpu_exec_step_atomic holding the exclusive lock. */
426
- ctx->envflags |= GUSA_EXCLUSIVE;
427
+ ctx->envflags |= TB_FLAG_GUSA_EXCLUSIVE;
428
gen_save_cpu_state(ctx, false);
429
gen_helper_exclusive(cpu_env);
430
ctx->base.is_jmp = DISAS_NORETURN;
431
@@ -XXX,XX +XXX,XX @@ static void sh4_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
432
(tbflags & (1 << SR_RB))) * 0x10;
433
ctx->fbank = tbflags & FPSCR_FR ? 0x10 : 0;
434
435
- if (tbflags & GUSA_MASK) {
436
+#ifdef CONFIG_USER_ONLY
437
+ if (tbflags & TB_FLAG_GUSA_MASK) {
438
+ /* In gUSA exclusive region. */
439
uint32_t pc = ctx->base.pc_next;
440
uint32_t pc_end = ctx->base.tb->cs_base;
441
- int backup = sextract32(ctx->tbflags, GUSA_SHIFT, 8);
442
+ int backup = sextract32(ctx->tbflags, TB_FLAG_GUSA_SHIFT, 8);
443
int max_insns = (pc_end - pc) / 2;
444
445
if (pc != pc_end + backup || max_insns < 2) {
446
/* This is a malformed gUSA region. Don't do anything special,
447
since the interpreter is likely to get confused. */
448
- ctx->envflags &= ~GUSA_MASK;
449
- } else if (tbflags & GUSA_EXCLUSIVE) {
450
+ ctx->envflags &= ~TB_FLAG_GUSA_MASK;
451
+ } else if (tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
452
/* Regardless of single-stepping or the end of the page,
453
we must complete execution of the gUSA region while
454
holding the exclusive lock. */
455
@@ -XXX,XX +XXX,XX @@ static void sh4_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
456
return;
457
}
458
}
459
+#endif
460
461
/* Since the ISA is fixed-width, we can bound by the number
462
of instructions remaining on the page. */
463
@@ -XXX,XX +XXX,XX @@ static void sh4_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
464
DisasContext *ctx = container_of(dcbase, DisasContext, base);
465
466
#ifdef CONFIG_USER_ONLY
467
- if (unlikely(ctx->envflags & GUSA_MASK)
468
- && !(ctx->envflags & GUSA_EXCLUSIVE)) {
469
+ if (unlikely(ctx->envflags & TB_FLAG_GUSA_MASK)
470
+ && !(ctx->envflags & TB_FLAG_GUSA_EXCLUSIVE)) {
471
/* We're in an gUSA region, and we have not already fallen
472
back on using an exclusive region. Attempt to parse the
473
region into a single supported atomic operation. Failure
474
@@ -XXX,XX +XXX,XX @@ static void sh4_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
475
{
476
DisasContext *ctx = container_of(dcbase, DisasContext, base);
477
478
- if (ctx->tbflags & GUSA_EXCLUSIVE) {
479
+ if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
480
/* Ending the region of exclusivity. Clear the bits. */
481
- ctx->envflags &= ~GUSA_MASK;
482
+ ctx->envflags &= ~TB_FLAG_GUSA_MASK;
483
}
484
485
switch (ctx->base.is_jmp) {
486
--
101
--
487
2.34.1
102
2.34.1
103
104
diff view generated by jsdifflib
1
Now that we have collected all of the page data into
2
CPUTLBEntryFull, provide an interface to record that
3
all in one go, instead of using 4 arguments. This interface
4
allows CPUTLBEntryFull to be extended without having to
5
change the number of arguments.
6
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
1
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
2
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
---
4
---
12
include/exec/cpu-defs.h | 14 +++++++++++
5
tcg/riscv/tcg-target.c.inc | 3 ++-
13
include/exec/exec-all.h | 22 ++++++++++++++++++
6
1 file changed, 2 insertions(+), 1 deletion(-)
14
accel/tcg/cputlb.c | 51 ++++++++++++++++++++++++++---------------
15
3 files changed, 69 insertions(+), 18 deletions(-)
16
7
17
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
8
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
18
index XXXXXXX..XXXXXXX 100644
9
index XXXXXXX..XXXXXXX 100644
19
--- a/include/exec/cpu-defs.h
10
--- a/tcg/riscv/tcg-target.c.inc
20
+++ b/include/exec/cpu-defs.h
11
+++ b/tcg/riscv/tcg-target.c.inc
21
@@ -XXX,XX +XXX,XX @@ typedef struct CPUTLBEntryFull {
12
@@ -XXX,XX +XXX,XX @@ typedef enum {
22
* + the offset within the target MemoryRegion (otherwise)
13
#endif
23
*/
14
24
hwaddr xlat_section;
15
OPC_FENCE = 0x0000000f,
25
+
16
+ OPC_NOP = OPC_ADDI, /* nop = addi r0,r0,0 */
26
+ /*
17
} RISCVInsn;
27
+ * @phys_addr contains the physical address in the address space
28
+ * given by cpu_asidx_from_attrs(cpu, @attrs).
29
+ */
30
+ hwaddr phys_addr;
31
+
32
+ /* @attrs contains the memory transaction attributes for the page. */
33
MemTxAttrs attrs;
34
+
35
+ /* @prot contains the complete protections for the page. */
36
+ uint8_t prot;
37
+
38
+ /* @lg_page_size contains the log2 of the page size. */
39
+ uint8_t lg_page_size;
40
} CPUTLBEntryFull;
41
18
42
/*
19
/*
43
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
20
@@ -XXX,XX +XXX,XX @@ static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
44
index XXXXXXX..XXXXXXX 100644
21
{
45
--- a/include/exec/exec-all.h
22
int i;
46
+++ b/include/exec/exec-all.h
23
for (i = 0; i < count; ++i) {
47
@@ -XXX,XX +XXX,XX @@ void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *cpu,
24
- p[i] = encode_i(OPC_ADDI, TCG_REG_ZERO, TCG_REG_ZERO, 0);
48
uint16_t idxmap,
25
+ p[i] = OPC_NOP;
49
unsigned bits);
26
}
50
51
+/**
52
+ * tlb_set_page_full:
53
+ * @cpu: CPU context
54
+ * @mmu_idx: mmu index of the tlb to modify
55
+ * @vaddr: virtual address of the entry to add
56
+ * @full: the details of the tlb entry
57
+ *
58
+ * Add an entry to @cpu tlb index @mmu_idx. All of the fields of
59
+ * @full must be filled, except for xlat_section, and constitute
60
+ * the complete description of the translated page.
61
+ *
62
+ * This is generally called by the target tlb_fill function after
63
+ * having performed a successful page table walk to find the physical
64
+ * address and attributes for the translation.
65
+ *
66
+ * At most one entry for a given virtual address is permitted. Only a
67
+ * single TARGET_PAGE_SIZE region is mapped; @full->lg_page_size is only
68
+ * used by tlb_flush_page.
69
+ */
70
+void tlb_set_page_full(CPUState *cpu, int mmu_idx, target_ulong vaddr,
71
+ CPUTLBEntryFull *full);
72
+
73
/**
74
* tlb_set_page_with_attrs:
75
* @cpu: CPU to add this TLB entry for
76
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
77
index XXXXXXX..XXXXXXX 100644
78
--- a/accel/tcg/cputlb.c
79
+++ b/accel/tcg/cputlb.c
80
@@ -XXX,XX +XXX,XX @@ static void tlb_add_large_page(CPUArchState *env, int mmu_idx,
81
env_tlb(env)->d[mmu_idx].large_page_mask = lp_mask;
82
}
27
}
83
28
84
-/* Add a new TLB entry. At most one entry for a given virtual address
85
+/*
86
+ * Add a new TLB entry. At most one entry for a given virtual address
87
* is permitted. Only a single TARGET_PAGE_SIZE region is mapped, the
88
* supplied size is only used by tlb_flush_page.
89
*
90
* Called from TCG-generated code, which is under an RCU read-side
91
* critical section.
92
*/
93
-void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
94
- hwaddr paddr, MemTxAttrs attrs, int prot,
95
- int mmu_idx, target_ulong size)
96
+void tlb_set_page_full(CPUState *cpu, int mmu_idx,
97
+ target_ulong vaddr, CPUTLBEntryFull *full)
98
{
99
CPUArchState *env = cpu->env_ptr;
100
CPUTLB *tlb = env_tlb(env);
101
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
102
CPUTLBEntry *te, tn;
103
hwaddr iotlb, xlat, sz, paddr_page;
104
target_ulong vaddr_page;
105
- int asidx = cpu_asidx_from_attrs(cpu, attrs);
106
- int wp_flags;
107
+ int asidx, wp_flags, prot;
108
bool is_ram, is_romd;
109
110
assert_cpu_is_self(cpu);
111
112
- if (size <= TARGET_PAGE_SIZE) {
113
+ if (full->lg_page_size <= TARGET_PAGE_BITS) {
114
sz = TARGET_PAGE_SIZE;
115
} else {
116
- tlb_add_large_page(env, mmu_idx, vaddr, size);
117
- sz = size;
118
+ sz = (hwaddr)1 << full->lg_page_size;
119
+ tlb_add_large_page(env, mmu_idx, vaddr, sz);
120
}
121
vaddr_page = vaddr & TARGET_PAGE_MASK;
122
- paddr_page = paddr & TARGET_PAGE_MASK;
123
+ paddr_page = full->phys_addr & TARGET_PAGE_MASK;
124
125
+ prot = full->prot;
126
+ asidx = cpu_asidx_from_attrs(cpu, full->attrs);
127
section = address_space_translate_for_iotlb(cpu, asidx, paddr_page,
128
- &xlat, &sz, attrs, &prot);
129
+ &xlat, &sz, full->attrs, &prot);
130
assert(sz >= TARGET_PAGE_SIZE);
131
132
tlb_debug("vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx
133
" prot=%x idx=%d\n",
134
- vaddr, paddr, prot, mmu_idx);
135
+ vaddr, full->phys_addr, prot, mmu_idx);
136
137
address = vaddr_page;
138
- if (size < TARGET_PAGE_SIZE) {
139
+ if (full->lg_page_size < TARGET_PAGE_BITS) {
140
/* Repeat the MMU check and TLB fill on every access. */
141
address |= TLB_INVALID_MASK;
142
}
143
- if (attrs.byte_swap) {
144
+ if (full->attrs.byte_swap) {
145
address |= TLB_BSWAP;
146
}
147
148
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
149
* subtract here is that of the page base, and not the same as the
150
* vaddr we add back in io_readx()/io_writex()/get_page_addr_code().
151
*/
152
+ desc->fulltlb[index] = *full;
153
desc->fulltlb[index].xlat_section = iotlb - vaddr_page;
154
- desc->fulltlb[index].attrs = attrs;
155
+ desc->fulltlb[index].phys_addr = paddr_page;
156
+ desc->fulltlb[index].prot = prot;
157
158
/* Now calculate the new entry */
159
tn.addend = addend - vaddr_page;
160
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
161
qemu_spin_unlock(&tlb->c.lock);
162
}
163
164
-/* Add a new TLB entry, but without specifying the memory
165
- * transaction attributes to be used.
166
- */
167
+void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
168
+ hwaddr paddr, MemTxAttrs attrs, int prot,
169
+ int mmu_idx, target_ulong size)
170
+{
171
+ CPUTLBEntryFull full = {
172
+ .phys_addr = paddr,
173
+ .attrs = attrs,
174
+ .prot = prot,
175
+ .lg_page_size = ctz64(size)
176
+ };
177
+
178
+ assert(is_power_of_2(size));
179
+ tlb_set_page_full(cpu, mmu_idx, vaddr, &full);
180
+}
181
+
182
void tlb_set_page(CPUState *cpu, target_ulong vaddr,
183
hwaddr paddr, int prot,
184
int mmu_idx, target_ulong size)
185
--
29
--
186
2.34.1
30
2.34.1
187
31
188
32
diff view generated by jsdifflib
1
This field is only written, not read; remove it.
1
Now that tcg can handle direct and indirect goto_tb simultaneously,
2
we can optimistically leave space for a direct branch and fall back
3
to loading the pointer from the TB for an indirect branch.
2
4
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.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/hw/core/cpu.h | 1 -
8
tcg/riscv/tcg-target.c.inc | 19 +++++++++++++++++--
9
accel/tcg/cputlb.c | 7 +++----
9
1 file changed, 17 insertions(+), 2 deletions(-)
10
2 files changed, 3 insertions(+), 5 deletions(-)
11
10
12
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
11
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
13
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/core/cpu.h
13
--- a/tcg/riscv/tcg-target.c.inc
15
+++ b/include/hw/core/cpu.h
14
+++ b/tcg/riscv/tcg-target.c.inc
16
@@ -XXX,XX +XXX,XX @@ struct CPUWatchpoint {
15
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
17
* the memory regions get moved around by io_writex.
16
18
*/
17
static void tcg_out_goto_tb(TCGContext *s, int which)
19
typedef struct SavedIOTLB {
20
- hwaddr addr;
21
MemoryRegionSection *section;
22
hwaddr mr_offset;
23
} SavedIOTLB;
24
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/accel/tcg/cputlb.c
27
+++ b/accel/tcg/cputlb.c
28
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUTLBEntryFull *full,
29
* This is read by tlb_plugin_lookup if the fulltlb entry doesn't match
30
* because of the side effect of io_writex changing memory layout.
31
*/
32
-static void save_iotlb_data(CPUState *cs, hwaddr addr,
33
- MemoryRegionSection *section, hwaddr mr_offset)
34
+static void save_iotlb_data(CPUState *cs, MemoryRegionSection *section,
35
+ hwaddr mr_offset)
36
{
18
{
37
#ifdef CONFIG_PLUGIN
19
- /* indirect jump method */
38
SavedIOTLB *saved = &cs->saved_iotlb;
20
+ /* Direct branch will be patched by tb_target_set_jmp_target. */
39
- saved->addr = addr;
21
+ set_jmp_insn_offset(s, which);
40
saved->section = section;
22
+ tcg_out32(s, OPC_JAL);
41
saved->mr_offset = mr_offset;
23
+
42
#endif
24
+ /* When branch is out of range, fall through to indirect. */
43
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUTLBEntryFull *full,
25
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO,
44
* The memory_region_dispatch may trigger a flush/resize
26
get_jmp_target_addr(s, which));
45
* so for plugins we save the iotlb_data just in case.
27
tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_TMP0, 0);
46
*/
28
@@ -XXX,XX +XXX,XX @@ static void tcg_out_goto_tb(TCGContext *s, int which)
47
- save_iotlb_data(cpu, full->xlat_section, section, mr_offset);
29
void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
48
+ save_iotlb_data(cpu, section, mr_offset);
30
uintptr_t jmp_rx, uintptr_t jmp_rw)
49
31
{
50
if (!qemu_mutex_iothread_locked()) {
32
- /* Always indirect, nothing to do */
51
qemu_mutex_lock_iothread();
33
+ uintptr_t addr = tb->jmp_target_addr[n];
34
+ ptrdiff_t offset = addr - jmp_rx;
35
+ tcg_insn_unit insn;
36
+
37
+ /* Either directly branch, or fall through to indirect branch. */
38
+ if (offset == sextreg(offset, 0, 20)) {
39
+ insn = encode_uj(OPC_JAL, TCG_REG_ZERO, offset);
40
+ } else {
41
+ insn = OPC_NOP;
42
+ }
43
+ qatomic_set((uint32_t *)jmp_rw, insn);
44
+ flush_idcache_range(jmp_rx, jmp_rw, 4);
45
}
46
47
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
52
--
48
--
53
2.34.1
49
2.34.1
54
50
55
51
diff view generated by jsdifflib