1
Mini PR, aimed at fixing the mips and ovmf regressions.
1
v2: Fix incorretly resolved rebase conflict in patch 16.
2
2
3
3
4
r~
4
r~
5
5
6
The following changes since commit 36e9aab3c569d4c9ad780473596e18479838d1aa:
7
6
8
migration: Move return path cleanup to main migration thread (2023-09-27 13:58:02 -0400)
7
The following changes since commit 61fd710b8da8aedcea9b4f197283dc38638e4b60:
8
9
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging (2022-09-02 13:24:28 -0400)
9
10
10
are available in the Git repository at:
11
are available in the Git repository at:
11
12
12
https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20230928
13
https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20220904
13
14
14
for you to fetch changes up to 18a536f1f8d6222e562f59179e837fdfd8b92718:
15
for you to fetch changes up to cc64de1fdeb81bc1ab8bb6c7c24bfd4fc9b28ef2:
15
16
16
accel/tcg: Always require can_do_io (2023-09-28 10:08:13 -0700)
17
target/riscv: Make translator stop before the end of a page (2022-09-03 09:27:05 +0100)
17
18
18
----------------------------------------------------------------
19
----------------------------------------------------------------
19
accel/tcg: Always require can_do_io, for #1866
20
Respect PROT_EXEC in user-only mode.
21
Fix s390x, i386 and riscv for translations crossing a page.
20
22
21
----------------------------------------------------------------
23
----------------------------------------------------------------
22
Richard Henderson (6):
24
Ilya Leoshkevich (4):
23
accel/tcg: Avoid load of icount_decr if unused
25
linux-user: Clear translations on mprotect()
24
accel/tcg: Hoist CF_MEMI_ONLY check outside translation loop
26
accel/tcg: Introduce is_same_page()
25
accel/tcg: Track current value of can_do_io in the TB
27
target/s390x: Make translator stop before the end of a page
26
accel/tcg: Improve setting of can_do_io at start of TB
28
target/i386: Make translator stop before the end of a page
27
accel/tcg: Always set CF_LAST_IO with CF_NOIRQ
28
accel/tcg: Always require can_do_io
29
29
30
include/exec/translator.h | 2 ++
30
Richard Henderson (16):
31
accel/tcg/cpu-exec.c | 2 +-
31
linux-user/arm: Mark the commpage executable
32
accel/tcg/tb-maint.c | 6 ++--
32
linux-user/hppa: Allocate page zero as a commpage
33
accel/tcg/translator.c | 72 +++++++++++++++++++++------------------------
33
linux-user/x86_64: Allocate vsyscall page as a commpage
34
target/mips/tcg/translate.c | 1 -
34
linux-user: Honor PT_GNU_STACK
35
5 files changed, 41 insertions(+), 42 deletions(-)
35
tests/tcg/i386: Move smc_code2 to an executable section
36
accel/tcg: Properly implement get_page_addr_code for user-only
37
accel/tcg: Unlock mmap_lock after longjmp
38
accel/tcg: Make tb_htable_lookup static
39
accel/tcg: Move qemu_ram_addr_from_host_nofail to physmem.c
40
accel/tcg: Use probe_access_internal for softmmu get_page_addr_code_hostp
41
accel/tcg: Document the faulting lookup in tb_lookup_cmp
42
accel/tcg: Remove translator_ldsw
43
accel/tcg: Add pc and host_pc params to gen_intermediate_code
44
accel/tcg: Add fast path for translator_ld*
45
target/riscv: Add MAX_INSN_LEN and insn_len
46
target/riscv: Make translator stop before the end of a page
47
48
include/elf.h | 1 +
49
include/exec/cpu-common.h | 1 +
50
include/exec/exec-all.h | 89 ++++++++----------------
51
include/exec/translator.h | 96 ++++++++++++++++---------
52
linux-user/arm/target_cpu.h | 4 +-
53
linux-user/qemu.h | 1 +
54
accel/tcg/cpu-exec.c | 143 ++++++++++++++++++++------------------
55
accel/tcg/cputlb.c | 93 +++++++------------------
56
accel/tcg/translate-all.c | 29 ++++----
57
accel/tcg/translator.c | 135 ++++++++++++++++++++++++++---------
58
accel/tcg/user-exec.c | 17 ++++-
59
linux-user/elfload.c | 82 ++++++++++++++++++++--
60
linux-user/mmap.c | 6 +-
61
softmmu/physmem.c | 12 ++++
62
target/alpha/translate.c | 5 +-
63
target/arm/translate.c | 5 +-
64
target/avr/translate.c | 5 +-
65
target/cris/translate.c | 5 +-
66
target/hexagon/translate.c | 6 +-
67
target/hppa/translate.c | 5 +-
68
target/i386/tcg/translate.c | 71 +++++++++++--------
69
target/loongarch/translate.c | 6 +-
70
target/m68k/translate.c | 5 +-
71
target/microblaze/translate.c | 5 +-
72
target/mips/tcg/translate.c | 5 +-
73
target/nios2/translate.c | 5 +-
74
target/openrisc/translate.c | 6 +-
75
target/ppc/translate.c | 5 +-
76
target/riscv/translate.c | 32 +++++++--
77
target/rx/translate.c | 5 +-
78
target/s390x/tcg/translate.c | 20 ++++--
79
target/sh4/translate.c | 5 +-
80
target/sparc/translate.c | 5 +-
81
target/tricore/translate.c | 6 +-
82
target/xtensa/translate.c | 6 +-
83
tests/tcg/i386/test-i386.c | 2 +-
84
tests/tcg/riscv64/noexec.c | 79 +++++++++++++++++++++
85
tests/tcg/s390x/noexec.c | 106 ++++++++++++++++++++++++++++
86
tests/tcg/x86_64/noexec.c | 75 ++++++++++++++++++++
87
tests/tcg/multiarch/noexec.c.inc | 139 ++++++++++++++++++++++++++++++++++++
88
tests/tcg/riscv64/Makefile.target | 1 +
89
tests/tcg/s390x/Makefile.target | 1 +
90
tests/tcg/x86_64/Makefile.target | 3 +-
91
43 files changed, 966 insertions(+), 367 deletions(-)
92
create mode 100644 tests/tcg/riscv64/noexec.c
93
create mode 100644 tests/tcg/s390x/noexec.c
94
create mode 100644 tests/tcg/x86_64/noexec.c
95
create mode 100644 tests/tcg/multiarch/noexec.c.inc
diff view generated by jsdifflib
Deleted patch
1
With CF_NOIRQ and without !CF_USE_ICOUNT, the load isn't used.
2
Avoid emitting it.
3
1
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
accel/tcg/translator.c | 11 +++++++----
8
1 file changed, 7 insertions(+), 4 deletions(-)
9
10
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/accel/tcg/translator.c
13
+++ b/accel/tcg/translator.c
14
@@ -XXX,XX +XXX,XX @@ bool translator_io_start(DisasContextBase *db)
15
16
static TCGOp *gen_tb_start(uint32_t cflags)
17
{
18
- TCGv_i32 count = tcg_temp_new_i32();
19
+ TCGv_i32 count = NULL;
20
TCGOp *icount_start_insn = NULL;
21
22
- tcg_gen_ld_i32(count, cpu_env,
23
- offsetof(ArchCPU, neg.icount_decr.u32) -
24
- offsetof(ArchCPU, env));
25
+ if ((cflags & CF_USE_ICOUNT) || !(cflags & CF_NOIRQ)) {
26
+ count = tcg_temp_new_i32();
27
+ tcg_gen_ld_i32(count, cpu_env,
28
+ offsetof(ArchCPU, neg.icount_decr.u32) -
29
+ offsetof(ArchCPU, env));
30
+ }
31
32
if (cflags & CF_USE_ICOUNT) {
33
/*
34
--
35
2.34.1
36
37
diff view generated by jsdifflib
Deleted patch
1
The condition checked is loop invariant; check it only once.
2
1
3
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
---
6
accel/tcg/translator.c | 14 ++++++++------
7
1 file changed, 8 insertions(+), 6 deletions(-)
8
9
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
10
index XXXXXXX..XXXXXXX 100644
11
--- a/accel/tcg/translator.c
12
+++ b/accel/tcg/translator.c
13
@@ -XXX,XX +XXX,XX @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
14
ops->tb_start(db, cpu);
15
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
16
17
- plugin_enabled = plugin_gen_tb_start(cpu, db, cflags & CF_MEMI_ONLY);
18
+ if (cflags & CF_MEMI_ONLY) {
19
+ /* We should only see CF_MEMI_ONLY for io_recompile. */
20
+ assert(cflags & CF_LAST_IO);
21
+ plugin_enabled = plugin_gen_tb_start(cpu, db, true);
22
+ } else {
23
+ plugin_enabled = plugin_gen_tb_start(cpu, db, false);
24
+ }
25
26
while (true) {
27
*max_insns = ++db->num_insns;
28
@@ -XXX,XX +XXX,XX @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
29
if (db->num_insns == db->max_insns && (cflags & CF_LAST_IO)) {
30
/* Accept I/O on the last instruction. */
31
gen_io_start();
32
- ops->translate_insn(db, cpu);
33
- } else {
34
- /* we should only see CF_MEMI_ONLY for io_recompile */
35
- tcg_debug_assert(!(cflags & CF_MEMI_ONLY));
36
- ops->translate_insn(db, cpu);
37
}
38
+ ops->translate_insn(db, cpu);
39
40
/*
41
* We can't instrument after instructions that change control
42
--
43
2.34.1
44
45
diff view generated by jsdifflib
1
Simplify translator_io_start by recording the current
1
Cache the translation from guest to host address, so we may
2
known value of can_do_io within DisasContextBase.
2
use direct loads when we hit on the primary translation page.
3
3
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Look up the second translation page only once, during translation.
5
This obviates another lookup of the second page within tb_gen_code
6
after translation.
7
8
Fixes a bug in that plugin_insn_append should be passed the bytes
9
in the original memory order, not bswapped by pieces.
10
11
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
12
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
14
---
7
include/exec/translator.h | 2 ++
15
include/exec/translator.h | 63 +++++++++++--------
8
accel/tcg/translator.c | 31 ++++++++++++++-----------------
16
accel/tcg/translate-all.c | 23 +++----
9
2 files changed, 16 insertions(+), 17 deletions(-)
17
accel/tcg/translator.c | 126 +++++++++++++++++++++++++++++---------
18
3 files changed, 141 insertions(+), 71 deletions(-)
10
19
11
diff --git a/include/exec/translator.h b/include/exec/translator.h
20
diff --git a/include/exec/translator.h b/include/exec/translator.h
12
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
13
--- a/include/exec/translator.h
22
--- a/include/exec/translator.h
14
+++ b/include/exec/translator.h
23
+++ b/include/exec/translator.h
15
@@ -XXX,XX +XXX,XX @@ typedef enum DisasJumpType {
24
@@ -XXX,XX +XXX,XX @@ typedef enum DisasJumpType {
16
* @num_insns: Number of translated instructions (including current).
17
* @max_insns: Maximum number of instructions to be translated in this TB.
18
* @singlestep_enabled: "Hardware" single stepping enabled.
19
+ * @saved_can_do_io: Known value of cpu->neg.can_do_io, or -1 for unknown.
20
*
21
* Architecture-agnostic disassembly context.
25
* Architecture-agnostic disassembly context.
22
*/
26
*/
23
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContextBase {
27
typedef struct DisasContextBase {
28
- const TranslationBlock *tb;
29
+ TranslationBlock *tb;
30
target_ulong pc_first;
31
target_ulong pc_next;
32
DisasJumpType is_jmp;
24
int num_insns;
33
int num_insns;
25
int max_insns;
34
int max_insns;
26
bool singlestep_enabled;
35
bool singlestep_enabled;
27
+ int8_t saved_can_do_io;
36
-#ifdef CONFIG_USER_ONLY
28
void *host_addr[2];
37
- /*
38
- * Guest address of the last byte of the last protected page.
39
- *
40
- * Pages containing the translated instructions are made non-writable in
41
- * order to achieve consistency in case another thread is modifying the
42
- * code while translate_insn() fetches the instruction bytes piecemeal.
43
- * Such writer threads are blocked on mmap_lock() in page_unprotect().
44
- */
45
- target_ulong page_protect_end;
46
-#endif
47
+ void *host_addr[2];
29
} DisasContextBase;
48
} DisasContextBase;
30
49
50
/**
51
@@ -XXX,XX +XXX,XX @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest);
52
* the relevant information at translation time.
53
*/
54
55
-#define GEN_TRANSLATOR_LD(fullname, type, load_fn, swap_fn) \
56
- type fullname ## _swap(CPUArchState *env, DisasContextBase *dcbase, \
57
- abi_ptr pc, bool do_swap); \
58
- static inline type fullname(CPUArchState *env, \
59
- DisasContextBase *dcbase, abi_ptr pc) \
60
- { \
61
- return fullname ## _swap(env, dcbase, pc, false); \
62
+uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, abi_ptr pc);
63
+uint16_t translator_lduw(CPUArchState *env, DisasContextBase *db, abi_ptr pc);
64
+uint32_t translator_ldl(CPUArchState *env, DisasContextBase *db, abi_ptr pc);
65
+uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, abi_ptr pc);
66
+
67
+static inline uint16_t
68
+translator_lduw_swap(CPUArchState *env, DisasContextBase *db,
69
+ abi_ptr pc, bool do_swap)
70
+{
71
+ uint16_t ret = translator_lduw(env, db, pc);
72
+ if (do_swap) {
73
+ ret = bswap16(ret);
74
}
75
+ return ret;
76
+}
77
78
-#define FOR_EACH_TRANSLATOR_LD(F) \
79
- F(translator_ldub, uint8_t, cpu_ldub_code, /* no swap */) \
80
- F(translator_lduw, uint16_t, cpu_lduw_code, bswap16) \
81
- F(translator_ldl, uint32_t, cpu_ldl_code, bswap32) \
82
- F(translator_ldq, uint64_t, cpu_ldq_code, bswap64)
83
+static inline uint32_t
84
+translator_ldl_swap(CPUArchState *env, DisasContextBase *db,
85
+ abi_ptr pc, bool do_swap)
86
+{
87
+ uint32_t ret = translator_ldl(env, db, pc);
88
+ if (do_swap) {
89
+ ret = bswap32(ret);
90
+ }
91
+ return ret;
92
+}
93
94
-FOR_EACH_TRANSLATOR_LD(GEN_TRANSLATOR_LD)
95
-
96
-#undef GEN_TRANSLATOR_LD
97
+static inline uint64_t
98
+translator_ldq_swap(CPUArchState *env, DisasContextBase *db,
99
+ abi_ptr pc, bool do_swap)
100
+{
101
+ uint64_t ret = translator_ldq(env, db, pc);
102
+ if (do_swap) {
103
+ ret = bswap64(ret);
104
+ }
105
+ return ret;
106
+}
107
108
/*
109
* Return whether addr is on the same page as where disassembly started.
110
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
111
index XXXXXXX..XXXXXXX 100644
112
--- a/accel/tcg/translate-all.c
113
+++ b/accel/tcg/translate-all.c
114
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
115
{
116
CPUArchState *env = cpu->env_ptr;
117
TranslationBlock *tb, *existing_tb;
118
- tb_page_addr_t phys_pc, phys_page2;
119
- target_ulong virt_page2;
120
+ tb_page_addr_t phys_pc;
121
tcg_insn_unit *gen_code_buf;
122
int gen_code_size, search_size, max_insns;
123
#ifdef CONFIG_PROFILER
124
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
125
tb->flags = flags;
126
tb->cflags = cflags;
127
tb->trace_vcpu_dstate = *cpu->trace_dstate;
128
+ tb->page_addr[0] = phys_pc;
129
+ tb->page_addr[1] = -1;
130
tcg_ctx->tb_cflags = cflags;
131
tb_overflow:
132
133
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
134
}
135
136
/*
137
- * If the TB is not associated with a physical RAM page then
138
- * it must be a temporary one-insn TB, and we have nothing to do
139
- * except fill in the page_addr[] fields. Return early before
140
- * attempting to link to other TBs or add to the lookup table.
141
+ * If the TB is not associated with a physical RAM page then it must be
142
+ * a temporary one-insn TB, and we have nothing left to do. Return early
143
+ * before attempting to link to other TBs or add to the lookup table.
144
*/
145
- if (phys_pc == -1) {
146
- tb->page_addr[0] = tb->page_addr[1] = -1;
147
+ if (tb->page_addr[0] == -1) {
148
return tb;
149
}
150
151
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
152
*/
153
tcg_tb_insert(tb);
154
155
- /* check next page if needed */
156
- virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
157
- phys_page2 = -1;
158
- if ((pc & TARGET_PAGE_MASK) != virt_page2) {
159
- phys_page2 = get_page_addr_code(env, virt_page2);
160
- }
161
/*
162
* No explicit memory barrier is required -- tb_link_page() makes the
163
* TB visible in a consistent state.
164
*/
165
- existing_tb = tb_link_page(tb, phys_pc, phys_page2);
166
+ existing_tb = tb_link_page(tb, tb->page_addr[0], tb->page_addr[1]);
167
/* if the TB already exists, discard what we just translated */
168
if (unlikely(existing_tb != tb)) {
169
uintptr_t orig_aligned = (uintptr_t)gen_code_buf;
31
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
170
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
32
index XXXXXXX..XXXXXXX 100644
171
index XXXXXXX..XXXXXXX 100644
33
--- a/accel/tcg/translator.c
172
--- a/accel/tcg/translator.c
34
+++ b/accel/tcg/translator.c
173
+++ b/accel/tcg/translator.c
35
@@ -XXX,XX +XXX,XX @@
174
@@ -XXX,XX +XXX,XX @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest)
36
#include "tcg/tcg-op-common.h"
175
return ((db->pc_first ^ dest) & TARGET_PAGE_MASK) == 0;
37
#include "internal.h"
176
}
38
177
39
-static void gen_io_start(void)
178
-static inline void translator_page_protect(DisasContextBase *dcbase,
40
+static void set_can_do_io(DisasContextBase *db, bool val)
179
- target_ulong pc)
180
-{
181
-#ifdef CONFIG_USER_ONLY
182
- dcbase->page_protect_end = pc | ~TARGET_PAGE_MASK;
183
- page_protect(pc);
184
-#endif
185
-}
186
-
187
void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
188
target_ulong pc, void *host_pc,
189
const TranslatorOps *ops, DisasContextBase *db)
190
@@ -XXX,XX +XXX,XX @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
191
db->num_insns = 0;
192
db->max_insns = max_insns;
193
db->singlestep_enabled = cflags & CF_SINGLE_STEP;
194
- translator_page_protect(db, db->pc_next);
195
+ db->host_addr[0] = host_pc;
196
+ db->host_addr[1] = NULL;
197
+
198
+#ifdef CONFIG_USER_ONLY
199
+ page_protect(pc);
200
+#endif
201
202
ops->init_disas_context(db, cpu);
203
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
204
@@ -XXX,XX +XXX,XX @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
205
#endif
206
}
207
208
-static inline void translator_maybe_page_protect(DisasContextBase *dcbase,
209
- target_ulong pc, size_t len)
210
+static void *translator_access(CPUArchState *env, DisasContextBase *db,
211
+ target_ulong pc, size_t len)
41
{
212
{
42
- tcg_gen_st_i32(tcg_constant_i32(1), cpu_env,
213
-#ifdef CONFIG_USER_ONLY
43
- offsetof(ArchCPU, parent_obj.can_do_io) -
214
- target_ulong end = pc + len - 1;
44
- offsetof(ArchCPU, env));
215
+ void *host;
45
+ if (db->saved_can_do_io != val) {
216
+ target_ulong base, end;
46
+ db->saved_can_do_io = val;
217
+ TranslationBlock *tb;
47
+ tcg_gen_st_i32(tcg_constant_i32(val), cpu_env,
218
48
+ offsetof(ArchCPU, parent_obj.can_do_io) -
219
- if (end > dcbase->page_protect_end) {
49
+ offsetof(ArchCPU, env));
220
- translator_page_protect(dcbase, end);
50
+ }
221
+ tb = db->tb;
222
+
223
+ /* Use slow path if first page is MMIO. */
224
+ if (unlikely(tb->page_addr[0] == -1)) {
225
+ return NULL;
226
}
227
+
228
+ end = pc + len - 1;
229
+ if (likely(is_same_page(db, end))) {
230
+ host = db->host_addr[0];
231
+ base = db->pc_first;
232
+ } else {
233
+ host = db->host_addr[1];
234
+ base = TARGET_PAGE_ALIGN(db->pc_first);
235
+ if (host == NULL) {
236
+ tb->page_addr[1] =
237
+ get_page_addr_code_hostp(env, base, &db->host_addr[1]);
238
+#ifdef CONFIG_USER_ONLY
239
+ page_protect(end);
240
#endif
241
+ /* We cannot handle MMIO as second page. */
242
+ assert(tb->page_addr[1] != -1);
243
+ host = db->host_addr[1];
244
+ }
245
+
246
+ /* Use slow path when crossing pages. */
247
+ if (is_same_page(db, pc)) {
248
+ return NULL;
249
+ }
250
+ }
251
+
252
+ tcg_debug_assert(pc >= base);
253
+ return host + (pc - base);
51
}
254
}
52
255
53
bool translator_io_start(DisasContextBase *db)
256
-#define GEN_TRANSLATOR_LD(fullname, type, load_fn, swap_fn) \
54
@@ -XXX,XX +XXX,XX @@ bool translator_io_start(DisasContextBase *db)
257
- type fullname ## _swap(CPUArchState *env, DisasContextBase *dcbase, \
55
if (!(cflags & CF_USE_ICOUNT)) {
258
- abi_ptr pc, bool do_swap) \
56
return false;
259
- { \
57
}
260
- translator_maybe_page_protect(dcbase, pc, sizeof(type)); \
58
- if (db->num_insns == db->max_insns && (cflags & CF_LAST_IO)) {
261
- type ret = load_fn(env, pc); \
59
- /* Already started in translator_loop. */
262
- if (do_swap) { \
60
- return true;
263
- ret = swap_fn(ret); \
61
- }
264
- } \
62
265
- plugin_insn_append(pc, &ret, sizeof(ret)); \
63
- gen_io_start();
266
- return ret; \
64
+ set_can_do_io(db, true);
267
+uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
65
268
+{
66
/*
269
+ uint8_t ret;
67
* Ensure that this instruction will be the last in the TB.
270
+ void *p = translator_access(env, db, pc, sizeof(ret));
68
@@ -XXX,XX +XXX,XX @@ bool translator_io_start(DisasContextBase *db)
271
+
69
return true;
272
+ if (p) {
70
}
273
+ plugin_insn_append(pc, p, sizeof(ret));
71
274
+ return ldub_p(p);
72
-static TCGOp *gen_tb_start(uint32_t cflags)
275
}
73
+static TCGOp *gen_tb_start(DisasContextBase *db, uint32_t cflags)
276
+ ret = cpu_ldub_code(env, pc);
74
{
277
+ plugin_insn_append(pc, &ret, sizeof(ret));
75
TCGv_i32 count = NULL;
278
+ return ret;
76
TCGOp *icount_start_insn = NULL;
279
+}
77
@@ -XXX,XX +XXX,XX @@ static TCGOp *gen_tb_start(uint32_t cflags)
280
78
* cpu->can_do_io is cleared automatically here at the beginning of
281
-FOR_EACH_TRANSLATOR_LD(GEN_TRANSLATOR_LD)
79
* each translation block. The cost is minimal and only paid for
282
+uint16_t translator_lduw(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
80
* -icount, plus it would be very easy to forget doing it in the
283
+{
81
- * translator. Doing it here means we don't need a gen_io_end() to
284
+ uint16_t ret, plug;
82
- * go with gen_io_start().
285
+ void *p = translator_access(env, db, pc, sizeof(ret));
83
+ * translator.
286
84
*/
287
-#undef GEN_TRANSLATOR_LD
85
- tcg_gen_st_i32(tcg_constant_i32(0), cpu_env,
288
+ if (p) {
86
- offsetof(ArchCPU, parent_obj.can_do_io) -
289
+ plugin_insn_append(pc, p, sizeof(ret));
87
- offsetof(ArchCPU, env));
290
+ return lduw_p(p);
88
+ set_can_do_io(db, false);
291
+ }
89
}
292
+ ret = cpu_lduw_code(env, pc);
90
293
+ plug = tswap16(ret);
91
return icount_start_insn;
294
+ plugin_insn_append(pc, &plug, sizeof(ret));
92
@@ -XXX,XX +XXX,XX @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
295
+ return ret;
93
db->num_insns = 0;
296
+}
94
db->max_insns = *max_insns;
297
+
95
db->singlestep_enabled = cflags & CF_SINGLE_STEP;
298
+uint32_t translator_ldl(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
96
+ db->saved_can_do_io = -1;
299
+{
97
db->host_addr[0] = host_pc;
300
+ uint32_t ret, plug;
98
db->host_addr[1] = NULL;
301
+ void *p = translator_access(env, db, pc, sizeof(ret));
99
302
+
100
@@ -XXX,XX +XXX,XX @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
303
+ if (p) {
101
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
304
+ plugin_insn_append(pc, p, sizeof(ret));
102
305
+ return ldl_p(p);
103
/* Start translating. */
306
+ }
104
- icount_start_insn = gen_tb_start(cflags);
307
+ ret = cpu_ldl_code(env, pc);
105
+ icount_start_insn = gen_tb_start(db, cflags);
308
+ plug = tswap32(ret);
106
ops->tb_start(db, cpu);
309
+ plugin_insn_append(pc, &plug, sizeof(ret));
107
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
310
+ return ret;
108
311
+}
109
@@ -XXX,XX +XXX,XX @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
312
+
110
the next instruction. */
313
+uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
111
if (db->num_insns == db->max_insns && (cflags & CF_LAST_IO)) {
314
+{
112
/* Accept I/O on the last instruction. */
315
+ uint64_t ret, plug;
113
- gen_io_start();
316
+ void *p = translator_access(env, db, pc, sizeof(ret));
114
+ set_can_do_io(db, true);
317
+
115
}
318
+ if (p) {
116
ops->translate_insn(db, cpu);
319
+ plugin_insn_append(pc, p, sizeof(ret));
117
320
+ return ldq_p(p);
321
+ }
322
+ ret = cpu_ldq_code(env, pc);
323
+ plug = tswap64(ret);
324
+ plugin_insn_append(pc, &plug, sizeof(ret));
325
+ return ret;
326
+}
118
--
327
--
119
2.34.1
328
2.34.1
120
121
diff view generated by jsdifflib
Deleted patch
1
Initialize can_do_io to true if this the TB has CF_LAST_IO
2
and will consist of a single instruction. This avoids a
3
set to 0 followed immediately by a set to 1.
4
1
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
accel/tcg/translator.c | 4 ++--
9
1 file changed, 2 insertions(+), 2 deletions(-)
10
11
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/accel/tcg/translator.c
14
+++ b/accel/tcg/translator.c
15
@@ -XXX,XX +XXX,XX @@ static TCGOp *gen_tb_start(DisasContextBase *db, uint32_t cflags)
16
offsetof(ArchCPU, neg.icount_decr.u16.low) -
17
offsetof(ArchCPU, env));
18
/*
19
- * cpu->can_do_io is cleared automatically here at the beginning of
20
+ * cpu->can_do_io is set automatically here at the beginning of
21
* each translation block. The cost is minimal and only paid for
22
* -icount, plus it would be very easy to forget doing it in the
23
* translator.
24
*/
25
- set_can_do_io(db, false);
26
+ set_can_do_io(db, db->max_insns == 1 && (cflags & CF_LAST_IO));
27
}
28
29
return icount_start_insn;
30
--
31
2.34.1
32
33
diff view generated by jsdifflib
Deleted patch
1
Without this we can get see loops through cpu_io_recompile,
2
in which the cpu makes no progress.
3
1
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
accel/tcg/cpu-exec.c | 2 +-
8
accel/tcg/tb-maint.c | 6 ++++--
9
2 files changed, 5 insertions(+), 3 deletions(-)
10
11
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/accel/tcg/cpu-exec.c
14
+++ b/accel/tcg/cpu-exec.c
15
@@ -XXX,XX +XXX,XX @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
16
&& cpu_neg(cpu)->icount_decr.u16.low + cpu->icount_extra == 0) {
17
/* Execute just one insn to trigger exception pending in the log */
18
cpu->cflags_next_tb = (curr_cflags(cpu) & ~CF_USE_ICOUNT)
19
- | CF_NOIRQ | 1;
20
+ | CF_LAST_IO | CF_NOIRQ | 1;
21
}
22
#endif
23
return false;
24
diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/accel/tcg/tb-maint.c
27
+++ b/accel/tcg/tb-maint.c
28
@@ -XXX,XX +XXX,XX @@ bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc)
29
if (current_tb_modified) {
30
/* Force execution of one insn next time. */
31
CPUState *cpu = current_cpu;
32
- cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(current_cpu);
33
+ cpu->cflags_next_tb =
34
+ 1 | CF_LAST_IO | CF_NOIRQ | curr_cflags(current_cpu);
35
return true;
36
}
37
return false;
38
@@ -XXX,XX +XXX,XX @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
39
if (current_tb_modified) {
40
page_collection_unlock(pages);
41
/* Force execution of one insn next time. */
42
- current_cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(current_cpu);
43
+ current_cpu->cflags_next_tb =
44
+ 1 | CF_LAST_IO | CF_NOIRQ | curr_cflags(current_cpu);
45
mmap_unlock();
46
cpu_loop_exit_noexc(current_cpu);
47
}
48
--
49
2.34.1
50
51
diff view generated by jsdifflib
Deleted patch
1
Require i/o as the last insn of a TranslationBlock always,
2
not only with icount. This is required for i/o that alters
3
the address space, such as a pci config space write.
4
1
5
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1866
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
accel/tcg/translator.c | 20 +++++++-------------
10
target/mips/tcg/translate.c | 1 -
11
2 files changed, 7 insertions(+), 14 deletions(-)
12
13
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/accel/tcg/translator.c
16
+++ b/accel/tcg/translator.c
17
@@ -XXX,XX +XXX,XX @@ static void set_can_do_io(DisasContextBase *db, bool val)
18
19
bool translator_io_start(DisasContextBase *db)
20
{
21
- uint32_t cflags = tb_cflags(db->tb);
22
-
23
- if (!(cflags & CF_USE_ICOUNT)) {
24
- return false;
25
- }
26
-
27
set_can_do_io(db, true);
28
29
/*
30
@@ -XXX,XX +XXX,XX @@ static TCGOp *gen_tb_start(DisasContextBase *db, uint32_t cflags)
31
tcg_gen_st16_i32(count, cpu_env,
32
offsetof(ArchCPU, neg.icount_decr.u16.low) -
33
offsetof(ArchCPU, env));
34
- /*
35
- * cpu->can_do_io is set automatically here at the beginning of
36
- * each translation block. The cost is minimal and only paid for
37
- * -icount, plus it would be very easy to forget doing it in the
38
- * translator.
39
- */
40
- set_can_do_io(db, db->max_insns == 1 && (cflags & CF_LAST_IO));
41
}
42
43
+ /*
44
+ * cpu->can_do_io is set automatically here at the beginning of
45
+ * each translation block. The cost is minimal, plus it would be
46
+ * very easy to forget doing it in the translator.
47
+ */
48
+ set_can_do_io(db, db->max_insns == 1 && (cflags & CF_LAST_IO));
49
+
50
return icount_start_insn;
51
}
52
53
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/mips/tcg/translate.c
56
+++ b/target/mips/tcg/translate.c
57
@@ -XXX,XX +XXX,XX @@ static void gen_branch(DisasContext *ctx, int insn_bytes)
58
/* Branches completion */
59
clear_branch_hflags(ctx);
60
ctx->base.is_jmp = DISAS_NORETURN;
61
- /* FIXME: Need to clear can_do_io. */
62
switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
63
case MIPS_HFLAG_FBNSLOT:
64
gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
65
--
66
2.34.1
67
68
diff view generated by jsdifflib