1
The following changes since commit e93ded1bf6c94ab95015b33e188bc8b0b0c32670:
1
The following changes since commit 75d30fde55485b965a1168a21d016dd07b50ed32:
2
2
3
Merge tag 'testing-pull-request-2022-08-30' of https://gitlab.com/thuth/qemu into staging (2022-08-31 18:19:03 -0400)
3
Merge tag 'block-pull-request' of https://gitlab.com/stefanha/qemu into staging (2022-10-30 15:07:25 -0400)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20220901
7
https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20221031
8
8
9
for you to fetch changes up to 20011be2e30b8aa8ef1fc258485f00c688703deb:
9
for you to fetch changes up to cb375590983fc3d23600d02ba05a05d34fe44150:
10
10
11
target/riscv: Make translator stop before the end of a page (2022-09-01 07:43:08 +0100)
11
target/i386: Expand eflags updates inline (2022-10-31 11:39:10 +1100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Respect PROT_EXEC in user-only mode.
14
Remove sparc32plus support from tcg/sparc.
15
Fix s390x, i386 and riscv for translations crossing a page.
15
target/i386: Use cpu_unwind_state_data for tpr access.
16
target/i386: Expand eflags updates inline
16
17
17
----------------------------------------------------------------
18
----------------------------------------------------------------
18
Ilya Leoshkevich (4):
19
Icenowy Zheng (1):
19
linux-user: Clear translations on mprotect()
20
tcg/tci: fix logic error when registering helpers via FFI
20
accel/tcg: Introduce is_same_page()
21
target/s390x: Make translator stop before the end of a page
22
target/i386: Make translator stop before the end of a page
23
21
24
Richard Henderson (16):
22
Richard Henderson (10):
25
linux-user/arm: Mark the commpage executable
23
tcg/sparc: Remove support for sparc32plus
26
linux-user/hppa: Allocate page zero as a commpage
24
tcg/sparc64: Rename from tcg/sparc
27
linux-user/x86_64: Allocate vsyscall page as a commpage
25
tcg/sparc64: Remove sparc32plus constraints
28
linux-user: Honor PT_GNU_STACK
26
accel/tcg: Introduce cpu_unwind_state_data
29
tests/tcg/i386: Move smc_code2 to an executable section
27
target/i386: Use cpu_unwind_state_data for tpr access
30
accel/tcg: Properly implement get_page_addr_code for user-only
28
target/openrisc: Always exit after mtspr npc
31
accel/tcg: Unlock mmap_lock after longjmp
29
target/openrisc: Use cpu_unwind_state_data for mfspr
32
accel/tcg: Make tb_htable_lookup static
30
accel/tcg: Remove will_exit argument from cpu_restore_state
33
accel/tcg: Move qemu_ram_addr_from_host_nofail to physmem.c
31
accel/tcg: Remove reset_icount argument from cpu_restore_state_from_tb
34
accel/tcg: Use probe_access_internal for softmmu get_page_addr_code_hostp
32
target/i386: Expand eflags updates inline
35
accel/tcg: Document the faulting lookup in tb_lookup_cmp
36
accel/tcg: Remove translator_ldsw
37
accel/tcg: Add pc and host_pc params to gen_intermediate_code
38
accel/tcg: Add fast path for translator_ld*
39
target/riscv: Add MAX_INSN_LEN and insn_len
40
target/riscv: Make translator stop before the end of a page
41
33
42
include/elf.h | 1 +
34
meson.build | 4 +-
43
include/exec/cpu-common.h | 1 +
35
accel/tcg/internal.h | 4 +-
44
include/exec/exec-all.h | 89 ++++++++----------------
36
include/exec/exec-all.h | 24 ++-
45
include/exec/translator.h | 96 ++++++++++++++++---------
37
target/i386/helper.h | 5 -
46
linux-user/arm/target_cpu.h | 4 +-
38
tcg/{sparc => sparc64}/tcg-target-con-set.h | 16 +-
47
linux-user/qemu.h | 1 +
39
tcg/{sparc => sparc64}/tcg-target-con-str.h | 3 -
48
accel/tcg/cpu-exec.c | 143 ++++++++++++++++++++------------------
40
tcg/{sparc => sparc64}/tcg-target.h | 11 --
49
accel/tcg/cputlb.c | 93 +++++++------------------
41
accel/tcg/cpu-exec-common.c | 2 +-
50
accel/tcg/translate-all.c | 29 ++++----
42
accel/tcg/tb-maint.c | 4 +-
51
accel/tcg/translator.c | 135 ++++++++++++++++++++++++++---------
43
accel/tcg/translate-all.c | 91 +++++----
52
accel/tcg/user-exec.c | 17 ++++-
44
target/alpha/helper.c | 2 +-
53
linux-user/elfload.c | 82 ++++++++++++++++++++--
45
target/alpha/mem_helper.c | 2 +-
54
linux-user/mmap.c | 6 +-
46
target/arm/op_helper.c | 2 +-
55
softmmu/physmem.c | 12 ++++
47
target/arm/tlb_helper.c | 8 +-
56
target/alpha/translate.c | 5 +-
48
target/cris/helper.c | 2 +-
57
target/arm/translate.c | 5 +-
49
target/i386/helper.c | 21 ++-
58
target/avr/translate.c | 5 +-
50
target/i386/tcg/cc_helper.c | 41 -----
59
target/cris/translate.c | 5 +-
51
target/i386/tcg/sysemu/svm_helper.c | 2 +-
60
target/hexagon/translate.c | 6 +-
52
target/i386/tcg/translate.c | 30 ++-
61
target/hppa/translate.c | 5 +-
53
target/m68k/op_helper.c | 4 +-
62
target/i386/tcg/translate.c | 71 +++++++++++--------
54
target/microblaze/helper.c | 2 +-
63
target/loongarch/translate.c | 6 +-
55
target/nios2/op_helper.c | 2 +-
64
target/m68k/translate.c | 5 +-
56
target/openrisc/sys_helper.c | 17 +-
65
target/microblaze/translate.c | 5 +-
57
target/ppc/excp_helper.c | 2 +-
66
target/mips/tcg/translate.c | 5 +-
58
target/s390x/tcg/excp_helper.c | 2 +-
67
target/nios2/translate.c | 5 +-
59
target/tricore/op_helper.c | 2 +-
68
target/openrisc/translate.c | 6 +-
60
target/xtensa/helper.c | 6 +-
69
target/ppc/translate.c | 5 +-
61
tcg/tcg.c | 81 +-------
70
target/riscv/translate.c | 32 +++++++--
62
tcg/{sparc => sparc64}/tcg-target.c.inc | 275 ++++++++--------------------
71
target/rx/translate.c | 5 +-
63
MAINTAINERS | 2 +-
72
target/s390x/tcg/translate.c | 20 ++++--
64
30 files changed, 232 insertions(+), 437 deletions(-)
73
target/sh4/translate.c | 5 +-
65
rename tcg/{sparc => sparc64}/tcg-target-con-set.h (69%)
74
target/sparc/translate.c | 5 +-
66
rename tcg/{sparc => sparc64}/tcg-target-con-str.h (77%)
75
target/tricore/translate.c | 6 +-
67
rename tcg/{sparc => sparc64}/tcg-target.h (95%)
76
target/xtensa/translate.c | 6 +-
68
rename tcg/{sparc => sparc64}/tcg-target.c.inc (91%)
77
tests/tcg/i386/test-i386.c | 2 +-
78
tests/tcg/riscv64/noexec.c | 79 +++++++++++++++++++++
79
tests/tcg/s390x/noexec.c | 106 ++++++++++++++++++++++++++++
80
tests/tcg/x86_64/noexec.c | 75 ++++++++++++++++++++
81
tests/tcg/multiarch/noexec.c.inc | 139 ++++++++++++++++++++++++++++++++++++
82
tests/tcg/riscv64/Makefile.target | 1 +
83
tests/tcg/s390x/Makefile.target | 1 +
84
tests/tcg/x86_64/Makefile.target | 3 +-
85
43 files changed, 966 insertions(+), 367 deletions(-)
86
create mode 100644 tests/tcg/riscv64/noexec.c
87
create mode 100644 tests/tcg/s390x/noexec.c
88
create mode 100644 tests/tcg/x86_64/noexec.c
89
create mode 100644 tests/tcg/multiarch/noexec.c.inc
diff view generated by jsdifflib
Deleted patch
1
We're about to start validating PAGE_EXEC, which means
2
that we've got to mark the commpage executable. We had
3
been placing the commpage outside of reserved_va, which
4
was incorrect and lead to an abort.
5
1
6
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
7
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
10
linux-user/arm/target_cpu.h | 4 ++--
11
linux-user/elfload.c | 6 +++++-
12
2 files changed, 7 insertions(+), 3 deletions(-)
13
14
diff --git a/linux-user/arm/target_cpu.h b/linux-user/arm/target_cpu.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/arm/target_cpu.h
17
+++ b/linux-user/arm/target_cpu.h
18
@@ -XXX,XX +XXX,XX @@ static inline unsigned long arm_max_reserved_va(CPUState *cs)
19
} else {
20
/*
21
* We need to be able to map the commpage.
22
- * See validate_guest_space in linux-user/elfload.c.
23
+ * See init_guest_commpage in linux-user/elfload.c.
24
*/
25
- return 0xffff0000ul;
26
+ return 0xfffffffful;
27
}
28
}
29
#define MAX_RESERVED_VA arm_max_reserved_va
30
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/linux-user/elfload.c
33
+++ b/linux-user/elfload.c
34
@@ -XXX,XX +XXX,XX @@ enum {
35
36
static bool init_guest_commpage(void)
37
{
38
- void *want = g2h_untagged(HI_COMMPAGE & -qemu_host_page_size);
39
+ abi_ptr commpage = HI_COMMPAGE & -qemu_host_page_size;
40
+ void *want = g2h_untagged(commpage);
41
void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE,
42
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
43
44
@@ -XXX,XX +XXX,XX @@ static bool init_guest_commpage(void)
45
perror("Protecting guest commpage");
46
exit(EXIT_FAILURE);
47
}
48
+
49
+ page_set_flags(commpage, commpage + qemu_host_page_size,
50
+ PAGE_READ | PAGE_EXEC | PAGE_VALID);
51
return true;
52
}
53
54
--
55
2.34.1
diff view generated by jsdifflib
1
We cannot deliver two interrupts simultaneously;
1
Since 9b9c37c36439, we have only supported sparc64 cpus.
2
the first interrupt handler must execute first.
2
Debian and Gentoo now only support 64-bit sparc64 userland,
3
so it is time to drop the 32-bit sparc64 userland: sparc32plus.
3
4
4
Reviewed-by: Michael Rolnik <mrolnik@gmail.com>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
---
8
target/avr/helper.c | 9 +++------
9
tcg/sparc/tcg-target.h | 11 ---
9
1 file changed, 3 insertions(+), 6 deletions(-)
10
tcg/tcg.c | 75 +----------------
11
tcg/sparc/tcg-target.c.inc | 166 +++++++------------------------------
12
3 files changed, 33 insertions(+), 219 deletions(-)
10
13
11
diff --git a/target/avr/helper.c b/target/avr/helper.c
14
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
12
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
13
--- a/target/avr/helper.c
16
--- a/tcg/sparc/tcg-target.h
14
+++ b/target/avr/helper.c
17
+++ b/tcg/sparc/tcg-target.h
15
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@
16
19
#ifndef SPARC_TCG_TARGET_H
17
bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
20
#define SPARC_TCG_TARGET_H
21
22
-#define TCG_TARGET_REG_BITS 64
23
-
24
#define TCG_TARGET_INSN_UNIT_SIZE 4
25
#define TCG_TARGET_TLB_DISPLACEMENT_BITS 32
26
#define TCG_TARGET_NB_REGS 32
27
@@ -XXX,XX +XXX,XX @@ typedef enum {
28
/* used for function call generation */
29
#define TCG_REG_CALL_STACK TCG_REG_O6
30
31
-#ifdef __arch64__
32
#define TCG_TARGET_STACK_BIAS 2047
33
#define TCG_TARGET_STACK_ALIGN 16
34
#define TCG_TARGET_CALL_STACK_OFFSET (128 + 6*8 + TCG_TARGET_STACK_BIAS)
35
-#else
36
-#define TCG_TARGET_STACK_BIAS 0
37
-#define TCG_TARGET_STACK_ALIGN 8
38
-#define TCG_TARGET_CALL_STACK_OFFSET (64 + 4 + 6*4)
39
-#endif
40
-
41
-#ifdef __arch64__
42
#define TCG_TARGET_EXTEND_ARGS 1
43
-#endif
44
45
#if defined(__VIS__) && __VIS__ >= 0x300
46
#define use_vis3_instructions 1
47
diff --git a/tcg/tcg.c b/tcg/tcg.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/tcg/tcg.c
50
+++ b/tcg/tcg.c
51
@@ -XXX,XX +XXX,XX @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
52
}
53
#endif
54
55
-#if defined(__sparc__) && !defined(__arch64__) \
56
- && !defined(CONFIG_TCG_INTERPRETER)
57
- /* We have 64-bit values in one register, but need to pass as two
58
- separate parameters. Split them. */
59
- int orig_typemask = typemask;
60
- int orig_nargs = nargs;
61
- TCGv_i64 retl, reth;
62
- TCGTemp *split_args[MAX_OPC_PARAM];
63
-
64
- retl = NULL;
65
- reth = NULL;
66
- typemask = 0;
67
- for (i = real_args = 0; i < nargs; ++i) {
68
- int argtype = extract32(orig_typemask, (i + 1) * 3, 3);
69
- bool is_64bit = (argtype & ~1) == dh_typecode_i64;
70
-
71
- if (is_64bit) {
72
- TCGv_i64 orig = temp_tcgv_i64(args[i]);
73
- TCGv_i32 h = tcg_temp_new_i32();
74
- TCGv_i32 l = tcg_temp_new_i32();
75
- tcg_gen_extr_i64_i32(l, h, orig);
76
- split_args[real_args++] = tcgv_i32_temp(h);
77
- typemask |= dh_typecode_i32 << (real_args * 3);
78
- split_args[real_args++] = tcgv_i32_temp(l);
79
- typemask |= dh_typecode_i32 << (real_args * 3);
80
- } else {
81
- split_args[real_args++] = args[i];
82
- typemask |= argtype << (real_args * 3);
83
- }
84
- }
85
- nargs = real_args;
86
- args = split_args;
87
-#elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
88
+#if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
89
for (i = 0; i < nargs; ++i) {
90
int argtype = extract32(typemask, (i + 1) * 3, 3);
91
bool is_32bit = (argtype & ~1) == dh_typecode_i32;
92
@@ -XXX,XX +XXX,XX @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
93
94
pi = 0;
95
if (ret != NULL) {
96
-#if defined(__sparc__) && !defined(__arch64__) \
97
- && !defined(CONFIG_TCG_INTERPRETER)
98
- if ((typemask & 6) == dh_typecode_i64) {
99
- /* The 32-bit ABI is going to return the 64-bit value in
100
- the %o0/%o1 register pair. Prepare for this by using
101
- two return temporaries, and reassemble below. */
102
- retl = tcg_temp_new_i64();
103
- reth = tcg_temp_new_i64();
104
- op->args[pi++] = tcgv_i64_arg(reth);
105
- op->args[pi++] = tcgv_i64_arg(retl);
106
- nb_rets = 2;
107
- } else {
108
- op->args[pi++] = temp_arg(ret);
109
- nb_rets = 1;
110
- }
111
-#else
112
if (TCG_TARGET_REG_BITS < 64 && (typemask & 6) == dh_typecode_i64) {
113
#if HOST_BIG_ENDIAN
114
op->args[pi++] = temp_arg(ret + 1);
115
@@ -XXX,XX +XXX,XX @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
116
op->args[pi++] = temp_arg(ret);
117
nb_rets = 1;
118
}
119
-#endif
120
} else {
121
nb_rets = 0;
122
}
123
@@ -XXX,XX +XXX,XX @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
124
tcg_debug_assert(TCGOP_CALLI(op) == real_args);
125
tcg_debug_assert(pi <= ARRAY_SIZE(op->args));
126
127
-#if defined(__sparc__) && !defined(__arch64__) \
128
- && !defined(CONFIG_TCG_INTERPRETER)
129
- /* Free all of the parts we allocated above. */
130
- for (i = real_args = 0; i < orig_nargs; ++i) {
131
- int argtype = extract32(orig_typemask, (i + 1) * 3, 3);
132
- bool is_64bit = (argtype & ~1) == dh_typecode_i64;
133
-
134
- if (is_64bit) {
135
- tcg_temp_free_internal(args[real_args++]);
136
- tcg_temp_free_internal(args[real_args++]);
137
- } else {
138
- real_args++;
139
- }
140
- }
141
- if ((orig_typemask & 6) == dh_typecode_i64) {
142
- /* The 32-bit ABI returned two 32-bit pieces. Re-assemble them.
143
- Note that describing these as TCGv_i64 eliminates an unnecessary
144
- zero-extension that tcg_gen_concat_i32_i64 would create. */
145
- tcg_gen_concat32_i64(temp_tcgv_i64(ret), retl, reth);
146
- tcg_temp_free_i64(retl);
147
- tcg_temp_free_i64(reth);
148
- }
149
-#elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
150
+#if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
151
for (i = 0; i < nargs; ++i) {
152
int argtype = extract32(typemask, (i + 1) * 3, 3);
153
bool is_32bit = (argtype & ~1) == dh_typecode_i32;
154
diff --git a/tcg/sparc/tcg-target.c.inc b/tcg/sparc/tcg-target.c.inc
155
index XXXXXXX..XXXXXXX 100644
156
--- a/tcg/sparc/tcg-target.c.inc
157
+++ b/tcg/sparc/tcg-target.c.inc
158
@@ -XXX,XX +XXX,XX @@
159
* THE SOFTWARE.
160
*/
161
162
+/* We only support generating code for 64-bit mode. */
163
+#ifndef __arch64__
164
+#error "unsupported code generation mode"
165
+#endif
166
+
167
#include "../tcg-pool.c.inc"
168
169
#ifdef CONFIG_DEBUG_TCG
170
@@ -XXX,XX +XXX,XX @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
171
};
172
#endif
173
174
-#ifdef __arch64__
175
-# define SPARC64 1
176
-#else
177
-# define SPARC64 0
178
-#endif
179
-
180
#define TCG_CT_CONST_S11 0x100
181
#define TCG_CT_CONST_S13 0x200
182
#define TCG_CT_CONST_ZERO 0x400
183
@@ -XXX,XX +XXX,XX @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
184
* high bits of the %i and %l registers garbage at all times.
185
*/
186
#define ALL_GENERAL_REGS MAKE_64BIT_MASK(0, 32)
187
-#if SPARC64
188
# define ALL_GENERAL_REGS64 ALL_GENERAL_REGS
189
-#else
190
-# define ALL_GENERAL_REGS64 MAKE_64BIT_MASK(0, 16)
191
-#endif
192
#define ALL_QLDST_REGS (ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS)
193
#define ALL_QLDST_REGS64 (ALL_GENERAL_REGS64 & ~SOFTMMU_RESERVE_REGS)
194
195
@@ -XXX,XX +XXX,XX @@ static bool check_fit_i32(int32_t val, unsigned int bits)
196
}
197
198
#define check_fit_tl check_fit_i64
199
-#if SPARC64
200
-# define check_fit_ptr check_fit_i64
201
-#else
202
-# define check_fit_ptr check_fit_i32
203
-#endif
204
+#define check_fit_ptr check_fit_i64
205
206
static bool patch_reloc(tcg_insn_unit *src_rw, int type,
207
intptr_t value, intptr_t addend)
208
@@ -XXX,XX +XXX,XX @@ static void tcg_out_sety(TCGContext *s, TCGReg rs)
209
tcg_out32(s, WRY | INSN_RS1(TCG_REG_G0) | INSN_RS2(rs));
210
}
211
212
-static void tcg_out_rdy(TCGContext *s, TCGReg rd)
213
-{
214
- tcg_out32(s, RDY | INSN_RD(rd));
215
-}
216
-
217
static void tcg_out_div32(TCGContext *s, TCGReg rd, TCGReg rs1,
218
int32_t val2, int val2const, int uns)
18
{
219
{
19
- bool ret = false;
220
@@ -XXX,XX +XXX,XX @@ static void emit_extend(TCGContext *s, TCGReg r, int op)
20
AVRCPU *cpu = AVR_CPU(cs);
221
tcg_out_arithi(s, r, r, 16, SHIFT_SRL);
21
CPUAVRState *env = &cpu->env;
222
break;
22
223
case MO_32:
23
@@ -XXX,XX +XXX,XX @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
224
- if (SPARC64) {
24
avr_cpu_do_interrupt(cs);
225
- tcg_out_arith(s, r, r, 0, SHIFT_SRL);
25
226
- }
26
cs->interrupt_request &= ~CPU_INTERRUPT_RESET;
227
+ tcg_out_arith(s, r, r, 0, SHIFT_SRL);
27
-
228
break;
28
- ret = true;
229
case MO_64:
29
+ return true;
230
break;
231
@@ -XXX,XX +XXX,XX @@ static void build_trampolines(TCGContext *s)
232
};
233
234
int i;
235
- TCGReg ra;
236
237
for (i = 0; i < ARRAY_SIZE(qemu_ld_helpers); ++i) {
238
if (qemu_ld_helpers[i] == NULL) {
239
@@ -XXX,XX +XXX,XX @@ static void build_trampolines(TCGContext *s)
30
}
240
}
241
qemu_ld_trampoline[i] = tcg_splitwx_to_rx(s->code_ptr);
242
243
- if (SPARC64 || TARGET_LONG_BITS == 32) {
244
- ra = TCG_REG_O3;
245
- } else {
246
- /* Install the high part of the address. */
247
- tcg_out_arithi(s, TCG_REG_O1, TCG_REG_O2, 32, SHIFT_SRLX);
248
- ra = TCG_REG_O4;
249
- }
250
-
251
/* Set the retaddr operand. */
252
- tcg_out_mov(s, TCG_TYPE_PTR, ra, TCG_REG_O7);
253
+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_O3, TCG_REG_O7);
254
/* Tail call. */
255
tcg_out_jmpl_const(s, qemu_ld_helpers[i], true, true);
256
/* delay slot -- set the env argument */
257
@@ -XXX,XX +XXX,XX @@ static void build_trampolines(TCGContext *s)
258
}
259
qemu_st_trampoline[i] = tcg_splitwx_to_rx(s->code_ptr);
260
261
- if (SPARC64) {
262
- emit_extend(s, TCG_REG_O2, i);
263
- ra = TCG_REG_O4;
264
- } else {
265
- ra = TCG_REG_O1;
266
- if (TARGET_LONG_BITS == 64) {
267
- /* Install the high part of the address. */
268
- tcg_out_arithi(s, ra, ra + 1, 32, SHIFT_SRLX);
269
- ra += 2;
270
- } else {
271
- ra += 1;
272
- }
273
- if ((i & MO_SIZE) == MO_64) {
274
- /* Install the high part of the data. */
275
- tcg_out_arithi(s, ra, ra + 1, 32, SHIFT_SRLX);
276
- ra += 2;
277
- } else {
278
- emit_extend(s, ra, i);
279
- ra += 1;
280
- }
281
- /* Skip the oi argument. */
282
- ra += 1;
283
- }
284
-
285
+ emit_extend(s, TCG_REG_O2, i);
286
+
287
/* Set the retaddr operand. */
288
- if (ra >= TCG_REG_O6) {
289
- tcg_out_st(s, TCG_TYPE_PTR, TCG_REG_O7, TCG_REG_CALL_STACK,
290
- TCG_TARGET_CALL_STACK_OFFSET);
291
- } else {
292
- tcg_out_mov(s, TCG_TYPE_PTR, ra, TCG_REG_O7);
293
- }
294
+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_O4, TCG_REG_O7);
295
296
/* Tail call. */
297
tcg_out_jmpl_const(s, qemu_st_helpers[i], true, true);
298
@@ -XXX,XX +XXX,XX @@ static void build_trampolines(TCGContext *s)
299
qemu_unalign_st_trampoline = tcg_splitwx_to_rx(s->code_ptr);
300
}
301
302
- if (!SPARC64 && TARGET_LONG_BITS == 64) {
303
- /* Install the high part of the address. */
304
- tcg_out_arithi(s, TCG_REG_O1, TCG_REG_O2, 32, SHIFT_SRLX);
305
- }
306
-
307
/* Tail call. */
308
tcg_out_jmpl_const(s, helper, true, true);
309
/* delay slot -- set the env argument */
310
@@ -XXX,XX +XXX,XX @@ static TCGReg tcg_out_tlb_load(TCGContext *s, TCGReg addr, int mem_index,
311
tcg_out_cmp(s, r0, r2, 0);
312
313
/* If the guest address must be zero-extended, do so now. */
314
- if (SPARC64 && TARGET_LONG_BITS == 32) {
315
+ if (TARGET_LONG_BITS == 32) {
316
tcg_out_arithi(s, r0, addr, 0, SHIFT_SRL);
317
return r0;
31
}
318
}
32
if (interrupt_request & CPU_INTERRUPT_HARD) {
319
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data, TCGReg addr,
33
@@ -XXX,XX +XXX,XX @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
320
34
if (!env->intsrc) {
321
#ifdef CONFIG_SOFTMMU
35
cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
322
unsigned memi = get_mmuidx(oi);
36
}
323
- TCGReg addrz, param;
37
-
324
+ TCGReg addrz;
38
- ret = true;
325
const tcg_insn_unit *func;
39
+ return true;
326
40
}
327
addrz = tcg_out_tlb_load(s, addr, memi, memop,
328
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data, TCGReg addr,
329
330
/* TLB Miss. */
331
332
- param = TCG_REG_O1;
333
- if (!SPARC64 && TARGET_LONG_BITS == 64) {
334
- /* Skip the high-part; we'll perform the extract in the trampoline. */
335
- param++;
336
- }
337
- tcg_out_mov(s, TCG_TYPE_REG, param++, addrz);
338
+ tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_O1, addrz);
339
340
/* We use the helpers to extend SB and SW data, leaving the case
341
of SL needing explicit extending below. */
342
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data, TCGReg addr,
343
tcg_debug_assert(func != NULL);
344
tcg_out_call_nodelay(s, func, false);
345
/* delay slot */
346
- tcg_out_movi(s, TCG_TYPE_I32, param, oi);
347
+ tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_O2, oi);
348
349
- /* Recall that all of the helpers return 64-bit results.
350
- Which complicates things for sparcv8plus. */
351
- if (SPARC64) {
352
- /* We let the helper sign-extend SB and SW, but leave SL for here. */
353
- if (is_64 && (memop & MO_SSIZE) == MO_SL) {
354
- tcg_out_arithi(s, data, TCG_REG_O0, 0, SHIFT_SRA);
355
- } else {
356
- tcg_out_mov(s, TCG_TYPE_REG, data, TCG_REG_O0);
357
- }
358
+ /* We let the helper sign-extend SB and SW, but leave SL for here. */
359
+ if (is_64 && (memop & MO_SSIZE) == MO_SL) {
360
+ tcg_out_arithi(s, data, TCG_REG_O0, 0, SHIFT_SRA);
361
} else {
362
- if ((memop & MO_SIZE) == MO_64) {
363
- tcg_out_arithi(s, TCG_REG_O0, TCG_REG_O0, 32, SHIFT_SLLX);
364
- tcg_out_arithi(s, TCG_REG_O1, TCG_REG_O1, 0, SHIFT_SRL);
365
- tcg_out_arith(s, data, TCG_REG_O0, TCG_REG_O1, ARITH_OR);
366
- } else if (is_64) {
367
- /* Re-extend from 32-bit rather than reassembling when we
368
- know the high register must be an extension. */
369
- tcg_out_arithi(s, data, TCG_REG_O1, 0,
370
- memop & MO_SIGN ? SHIFT_SRA : SHIFT_SRL);
371
- } else {
372
- tcg_out_mov(s, TCG_TYPE_I32, data, TCG_REG_O1);
373
- }
374
+ tcg_out_mov(s, TCG_TYPE_REG, data, TCG_REG_O0);
41
}
375
}
42
- return ret;
376
43
+ return false;
377
*label_ptr |= INSN_OFF19(tcg_ptr_byte_diff(s->code_ptr, label_ptr));
378
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data, TCGReg addr,
379
unsigned s_bits = memop & MO_SIZE;
380
unsigned t_bits;
381
382
- if (SPARC64 && TARGET_LONG_BITS == 32) {
383
+ if (TARGET_LONG_BITS == 32) {
384
tcg_out_arithi(s, TCG_REG_T1, addr, 0, SHIFT_SRL);
385
addr = TCG_REG_T1;
386
}
387
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data, TCGReg addr,
388
* operation in the delay slot, and failure need only invoke the
389
* handler for SIGBUS.
390
*/
391
- TCGReg arg_low = TCG_REG_O1 + (!SPARC64 && TARGET_LONG_BITS == 64);
392
tcg_out_call_nodelay(s, qemu_unalign_ld_trampoline, false);
393
/* delay slot -- move to low part of argument reg */
394
- tcg_out_mov_delay(s, arg_low, addr);
395
+ tcg_out_mov_delay(s, TCG_REG_O1, addr);
396
} else {
397
/* Underalignment: load by pieces of minimum alignment. */
398
int ld_opc, a_size, s_size, i;
399
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data, TCGReg addr,
400
401
#ifdef CONFIG_SOFTMMU
402
unsigned memi = get_mmuidx(oi);
403
- TCGReg addrz, param;
404
+ TCGReg addrz;
405
const tcg_insn_unit *func;
406
407
addrz = tcg_out_tlb_load(s, addr, memi, memop,
408
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data, TCGReg addr,
409
410
/* TLB Miss. */
411
412
- param = TCG_REG_O1;
413
- if (!SPARC64 && TARGET_LONG_BITS == 64) {
414
- /* Skip the high-part; we'll perform the extract in the trampoline. */
415
- param++;
416
- }
417
- tcg_out_mov(s, TCG_TYPE_REG, param++, addrz);
418
- if (!SPARC64 && (memop & MO_SIZE) == MO_64) {
419
- /* Skip the high-part; we'll perform the extract in the trampoline. */
420
- param++;
421
- }
422
- tcg_out_mov(s, TCG_TYPE_REG, param++, data);
423
+ tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_O1, addrz);
424
+ tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_O2, data);
425
426
func = qemu_st_trampoline[memop & (MO_BSWAP | MO_SIZE)];
427
tcg_debug_assert(func != NULL);
428
tcg_out_call_nodelay(s, func, false);
429
/* delay slot */
430
- tcg_out_movi(s, TCG_TYPE_I32, param, oi);
431
+ tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_O3, oi);
432
433
*label_ptr |= INSN_OFF19(tcg_ptr_byte_diff(s->code_ptr, label_ptr));
434
#else
435
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data, TCGReg addr,
436
unsigned s_bits = memop & MO_SIZE;
437
unsigned t_bits;
438
439
- if (SPARC64 && TARGET_LONG_BITS == 32) {
440
+ if (TARGET_LONG_BITS == 32) {
441
tcg_out_arithi(s, TCG_REG_T1, addr, 0, SHIFT_SRL);
442
addr = TCG_REG_T1;
443
}
444
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data, TCGReg addr,
445
* operation in the delay slot, and failure need only invoke the
446
* handler for SIGBUS.
447
*/
448
- TCGReg arg_low = TCG_REG_O1 + (!SPARC64 && TARGET_LONG_BITS == 64);
449
tcg_out_call_nodelay(s, qemu_unalign_st_trampoline, false);
450
/* delay slot -- move to low part of argument reg */
451
- tcg_out_mov_delay(s, arg_low, addr);
452
+ tcg_out_mov_delay(s, TCG_REG_O1, addr);
453
} else {
454
/* Underalignment: store by pieces of minimum alignment. */
455
int st_opc, a_size, s_size, i;
456
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
457
case INDEX_op_muls2_i32:
458
c = ARITH_SMUL;
459
do_mul2:
460
- /* The 32-bit multiply insns produce a full 64-bit result. If the
461
- destination register can hold it, we can avoid the slower RDY. */
462
+ /* The 32-bit multiply insns produce a full 64-bit result. */
463
tcg_out_arithc(s, a0, a2, args[3], const_args[3], c);
464
- if (SPARC64 || a0 <= TCG_REG_O7) {
465
- tcg_out_arithi(s, a1, a0, 32, SHIFT_SRLX);
466
- } else {
467
- tcg_out_rdy(s, a1);
468
- }
469
+ tcg_out_arithi(s, a1, a0, 32, SHIFT_SRLX);
470
break;
471
472
case INDEX_op_qemu_ld_i32:
473
@@ -XXX,XX +XXX,XX @@ static void tcg_target_init(TCGContext *s)
474
tcg_regset_set_reg(s->reserved_regs, TCG_REG_T2); /* for internal use */
44
}
475
}
45
476
46
void avr_cpu_do_interrupt(CPUState *cs)
477
-#if SPARC64
478
-# define ELF_HOST_MACHINE EM_SPARCV9
479
-#else
480
-# define ELF_HOST_MACHINE EM_SPARC32PLUS
481
-# define ELF_HOST_FLAGS EF_SPARC_32PLUS
482
-#endif
483
+#define ELF_HOST_MACHINE EM_SPARCV9
484
485
typedef struct {
486
DebugFrameHeader h;
487
- uint8_t fde_def_cfa[SPARC64 ? 4 : 2];
488
+ uint8_t fde_def_cfa[4];
489
uint8_t fde_win_save;
490
uint8_t fde_ret_save[3];
491
} DebugFrame;
492
@@ -XXX,XX +XXX,XX @@ static const DebugFrame debug_frame = {
493
.h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
494
495
.fde_def_cfa = {
496
-#if SPARC64
497
12, 30, /* DW_CFA_def_cfa i6, 2047 */
498
(2047 & 0x7f) | 0x80, (2047 >> 7)
499
-#else
500
- 13, 30 /* DW_CFA_def_cfa_register i6 */
501
-#endif
502
},
503
.fde_win_save = 0x2d, /* DW_CFA_GNU_window_save */
504
.fde_ret_save = { 9, 15, 31 }, /* DW_CFA_register o7, i7 */
47
--
505
--
48
2.34.1
506
2.34.1
49
507
50
508
diff view generated by jsdifflib
1
This bit is not saved across interrupts, so we must
1
Emphasize that we only support full 64-bit code generation.
2
delay delivering the interrupt until the skip has
3
been processed.
4
2
5
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1118
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Michael Rolnik <mrolnik@gmail.com>
4
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>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
6
---
10
target/avr/helper.c | 9 +++++++++
7
meson.build | 4 +---
11
target/avr/translate.c | 26 ++++++++++++++++++++++----
8
tcg/{sparc => sparc64}/tcg-target-con-set.h | 0
12
2 files changed, 31 insertions(+), 4 deletions(-)
9
tcg/{sparc => sparc64}/tcg-target-con-str.h | 0
10
tcg/{sparc => sparc64}/tcg-target.h | 0
11
tcg/{sparc => sparc64}/tcg-target.c.inc | 0
12
MAINTAINERS | 2 +-
13
6 files changed, 2 insertions(+), 4 deletions(-)
14
rename tcg/{sparc => sparc64}/tcg-target-con-set.h (100%)
15
rename tcg/{sparc => sparc64}/tcg-target-con-str.h (100%)
16
rename tcg/{sparc => sparc64}/tcg-target.h (100%)
17
rename tcg/{sparc => sparc64}/tcg-target.c.inc (100%)
13
18
14
diff --git a/target/avr/helper.c b/target/avr/helper.c
19
diff --git a/meson.build b/meson.build
15
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
16
--- a/target/avr/helper.c
21
--- a/meson.build
17
+++ b/target/avr/helper.c
22
+++ b/meson.build
18
@@ -XXX,XX +XXX,XX @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
23
@@ -XXX,XX +XXX,XX @@ qapi_trace_events = []
19
AVRCPU *cpu = AVR_CPU(cs);
24
bsd_oses = ['gnu/kfreebsd', 'freebsd', 'netbsd', 'openbsd', 'dragonfly', 'darwin']
20
CPUAVRState *env = &cpu->env;
25
supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux']
21
26
supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv', 'x86', 'x86_64',
22
+ /*
27
- 'arm', 'aarch64', 'loongarch64', 'mips', 'mips64', 'sparc', 'sparc64']
23
+ * We cannot separate a skip from the next instruction,
28
+ 'arm', 'aarch64', 'loongarch64', 'mips', 'mips64', 'sparc64']
24
+ * as the skip would not be preserved across the interrupt.
29
25
+ * Separating the two insn normally only happens at page boundaries.
30
cpu = host_machine.cpu_family()
26
+ */
31
27
+ if (env->skip) {
32
@@ -XXX,XX +XXX,XX @@ if get_option('tcg').allowed()
28
+ return false;
33
endif
29
+ }
34
if get_option('tcg_interpreter')
30
+
35
tcg_arch = 'tci'
31
if (interrupt_request & CPU_INTERRUPT_RESET) {
36
- elif host_arch == 'sparc64'
32
if (cpu_interrupts_enabled(env)) {
37
- tcg_arch = 'sparc'
33
cs->exception_index = EXCP_RESET;
38
elif host_arch == 'x86_64'
34
diff --git a/target/avr/translate.c b/target/avr/translate.c
39
tcg_arch = 'i386'
40
elif host_arch == 'ppc64'
41
diff --git a/tcg/sparc/tcg-target-con-set.h b/tcg/sparc64/tcg-target-con-set.h
42
similarity index 100%
43
rename from tcg/sparc/tcg-target-con-set.h
44
rename to tcg/sparc64/tcg-target-con-set.h
45
diff --git a/tcg/sparc/tcg-target-con-str.h b/tcg/sparc64/tcg-target-con-str.h
46
similarity index 100%
47
rename from tcg/sparc/tcg-target-con-str.h
48
rename to tcg/sparc64/tcg-target-con-str.h
49
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc64/tcg-target.h
50
similarity index 100%
51
rename from tcg/sparc/tcg-target.h
52
rename to tcg/sparc64/tcg-target.h
53
diff --git a/tcg/sparc/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc
54
similarity index 100%
55
rename from tcg/sparc/tcg-target.c.inc
56
rename to tcg/sparc64/tcg-target.c.inc
57
diff --git a/MAINTAINERS b/MAINTAINERS
35
index XXXXXXX..XXXXXXX 100644
58
index XXXXXXX..XXXXXXX 100644
36
--- a/target/avr/translate.c
59
--- a/MAINTAINERS
37
+++ b/target/avr/translate.c
60
+++ b/MAINTAINERS
38
@@ -XXX,XX +XXX,XX @@ static void avr_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
61
@@ -XXX,XX +XXX,XX @@ L: qemu-s390x@nongnu.org
39
if (skip_label) {
62
40
canonicalize_skip(ctx);
63
SPARC TCG target
41
gen_set_label(skip_label);
64
S: Odd Fixes
42
- if (ctx->base.is_jmp == DISAS_NORETURN) {
65
-F: tcg/sparc/
43
+
66
+F: tcg/sparc64/
44
+ switch (ctx->base.is_jmp) {
67
F: disas/sparc.c
45
+ case DISAS_NORETURN:
68
46
ctx->base.is_jmp = DISAS_CHAIN;
69
TCI TCG target
47
+ break;
48
+ case DISAS_NEXT:
49
+ if (ctx->base.tb->flags & TB_FLAGS_SKIP) {
50
+ ctx->base.is_jmp = DISAS_TOO_MANY;
51
+ }
52
+ break;
53
+ default:
54
+ break;
55
}
56
}
57
58
@@ -XXX,XX +XXX,XX @@ static void avr_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
59
{
60
DisasContext *ctx = container_of(dcbase, DisasContext, base);
61
bool nonconst_skip = canonicalize_skip(ctx);
62
+ /*
63
+ * Because we disable interrupts while env->skip is set,
64
+ * we must return to the main loop to re-evaluate afterward.
65
+ */
66
+ bool force_exit = ctx->base.tb->flags & TB_FLAGS_SKIP;
67
68
switch (ctx->base.is_jmp) {
69
case DISAS_NORETURN:
70
@@ -XXX,XX +XXX,XX @@ static void avr_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
71
case DISAS_NEXT:
72
case DISAS_TOO_MANY:
73
case DISAS_CHAIN:
74
- if (!nonconst_skip) {
75
+ if (!nonconst_skip && !force_exit) {
76
/* Note gen_goto_tb checks singlestep. */
77
gen_goto_tb(ctx, 1, ctx->npc);
78
break;
79
@@ -XXX,XX +XXX,XX @@ static void avr_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
80
tcg_gen_movi_tl(cpu_pc, ctx->npc);
81
/* fall through */
82
case DISAS_LOOKUP:
83
- tcg_gen_lookup_and_goto_ptr();
84
- break;
85
+ if (!force_exit) {
86
+ tcg_gen_lookup_and_goto_ptr();
87
+ break;
88
+ }
89
+ /* fall through */
90
case DISAS_EXIT:
91
tcg_gen_exit_tb(NULL, 0);
92
break;
93
--
70
--
94
2.34.1
71
2.34.1
95
72
96
73
diff view generated by jsdifflib
1
Right now the translator stops right *after* the end of a page, which
1
With sparc64 we need not distinguish between registers that
2
breaks reporting of fault locations when the last instruction of a
2
can hold 32-bit values and those that can hold 64-bit values.
3
multi-insn translation block crosses a page boundary.
4
3
5
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1155
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
8
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
---
6
---
11
target/riscv/translate.c | 17 +++++--
7
tcg/sparc64/tcg-target-con-set.h | 16 +----
12
tests/tcg/riscv64/noexec.c | 79 +++++++++++++++++++++++++++++++
8
tcg/sparc64/tcg-target-con-str.h | 3 -
13
tests/tcg/riscv64/Makefile.target | 1 +
9
tcg/sparc64/tcg-target.c.inc | 109 ++++++++++++-------------------
14
3 files changed, 93 insertions(+), 4 deletions(-)
10
3 files changed, 44 insertions(+), 84 deletions(-)
15
create mode 100644 tests/tcg/riscv64/noexec.c
16
11
17
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
12
diff --git a/tcg/sparc64/tcg-target-con-set.h b/tcg/sparc64/tcg-target-con-set.h
18
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
19
--- a/target/riscv/translate.c
14
--- a/tcg/sparc64/tcg-target-con-set.h
20
+++ b/target/riscv/translate.c
15
+++ b/tcg/sparc64/tcg-target-con-set.h
21
@@ -XXX,XX +XXX,XX @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
22
}
23
ctx->nftemp = 0;
24
25
+ /* Only the first insn within a TB is allowed to cross a page boundary. */
26
if (ctx->base.is_jmp == DISAS_NEXT) {
27
- target_ulong page_start;
28
-
29
- page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
30
- if (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE) {
31
+ if (!is_same_page(&ctx->base, ctx->base.pc_next)) {
32
ctx->base.is_jmp = DISAS_TOO_MANY;
33
+ } else {
34
+ unsigned page_ofs = ctx->base.pc_next & ~TARGET_PAGE_MASK;
35
+
36
+ if (page_ofs > TARGET_PAGE_SIZE - MAX_INSN_LEN) {
37
+ uint16_t next_insn = cpu_lduw_code(env, ctx->base.pc_next);
38
+ int len = insn_len(next_insn);
39
+
40
+ if (!is_same_page(&ctx->base, ctx->base.pc_next + len)) {
41
+ ctx->base.is_jmp = DISAS_TOO_MANY;
42
+ }
43
+ }
44
}
45
}
46
}
47
diff --git a/tests/tcg/riscv64/noexec.c b/tests/tcg/riscv64/noexec.c
48
new file mode 100644
49
index XXXXXXX..XXXXXXX
50
--- /dev/null
51
+++ b/tests/tcg/riscv64/noexec.c
52
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@
53
+#include "../multiarch/noexec.c.inc"
17
*/
54
+
18
C_O0_I1(r)
55
+static void *arch_mcontext_pc(const mcontext_t *ctx)
19
C_O0_I2(rZ, r)
56
+{
20
-C_O0_I2(RZ, r)
57
+ return (void *)ctx->__gregs[REG_PC];
21
C_O0_I2(rZ, rJ)
58
+}
22
-C_O0_I2(RZ, RJ)
59
+
23
-C_O0_I2(sZ, A)
60
+static int arch_mcontext_arg(const mcontext_t *ctx)
24
-C_O0_I2(SZ, A)
61
+{
25
-C_O1_I1(r, A)
62
+ return ctx->__gregs[REG_A0];
26
-C_O1_I1(R, A)
63
+}
27
+C_O0_I2(sZ, s)
64
+
28
+C_O1_I1(r, s)
65
+static void arch_flush(void *p, int len)
29
C_O1_I1(r, r)
66
+{
30
-C_O1_I1(r, R)
67
+ __builtin___clear_cache(p, p + len);
31
-C_O1_I1(R, r)
68
+}
32
-C_O1_I1(R, R)
69
+
33
-C_O1_I2(R, R, R)
70
+extern char noexec_1[];
34
+C_O1_I2(r, r, r)
71
+extern char noexec_2[];
35
C_O1_I2(r, rZ, rJ)
72
+extern char noexec_end[];
36
-C_O1_I2(R, RZ, RJ)
73
+
37
C_O1_I4(r, rZ, rJ, rI, 0)
74
+asm(".option push\n"
38
-C_O1_I4(R, RZ, RJ, RI, 0)
75
+ ".option norvc\n"
39
C_O2_I2(r, r, rZ, rJ)
76
+ "noexec_1:\n"
40
-C_O2_I4(R, R, RZ, RZ, RJ, RI)
77
+ " li a0,1\n" /* a0 is 0 on entry, set 1. */
41
C_O2_I4(r, r, rZ, rZ, rJ, rJ)
78
+ "noexec_2:\n"
42
diff --git a/tcg/sparc64/tcg-target-con-str.h b/tcg/sparc64/tcg-target-con-str.h
79
+ " li a0,2\n" /* a0 is 0/1; set 2. */
80
+ " ret\n"
81
+ "noexec_end:\n"
82
+ ".option pop");
83
+
84
+int main(void)
85
+{
86
+ struct noexec_test noexec_tests[] = {
87
+ {
88
+ .name = "fallthrough",
89
+ .test_code = noexec_1,
90
+ .test_len = noexec_end - noexec_1,
91
+ .page_ofs = noexec_1 - noexec_2,
92
+ .entry_ofs = noexec_1 - noexec_2,
93
+ .expected_si_ofs = 0,
94
+ .expected_pc_ofs = 0,
95
+ .expected_arg = 1,
96
+ },
97
+ {
98
+ .name = "jump",
99
+ .test_code = noexec_1,
100
+ .test_len = noexec_end - noexec_1,
101
+ .page_ofs = noexec_1 - noexec_2,
102
+ .entry_ofs = 0,
103
+ .expected_si_ofs = 0,
104
+ .expected_pc_ofs = 0,
105
+ .expected_arg = 0,
106
+ },
107
+ {
108
+ .name = "fallthrough [cross]",
109
+ .test_code = noexec_1,
110
+ .test_len = noexec_end - noexec_1,
111
+ .page_ofs = noexec_1 - noexec_2 - 2,
112
+ .entry_ofs = noexec_1 - noexec_2 - 2,
113
+ .expected_si_ofs = 0,
114
+ .expected_pc_ofs = -2,
115
+ .expected_arg = 1,
116
+ },
117
+ {
118
+ .name = "jump [cross]",
119
+ .test_code = noexec_1,
120
+ .test_len = noexec_end - noexec_1,
121
+ .page_ofs = noexec_1 - noexec_2 - 2,
122
+ .entry_ofs = -2,
123
+ .expected_si_ofs = 0,
124
+ .expected_pc_ofs = -2,
125
+ .expected_arg = 0,
126
+ },
127
+ };
128
+
129
+ return test_noexec(noexec_tests,
130
+ sizeof(noexec_tests) / sizeof(noexec_tests[0]));
131
+}
132
diff --git a/tests/tcg/riscv64/Makefile.target b/tests/tcg/riscv64/Makefile.target
133
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
134
--- a/tests/tcg/riscv64/Makefile.target
44
--- a/tcg/sparc64/tcg-target-con-str.h
135
+++ b/tests/tcg/riscv64/Makefile.target
45
+++ b/tcg/sparc64/tcg-target-con-str.h
136
@@ -XXX,XX +XXX,XX @@
46
@@ -XXX,XX +XXX,XX @@
137
47
* REGS(letter, register_mask)
138
VPATH += $(SRC_PATH)/tests/tcg/riscv64
48
*/
139
TESTS += test-div
49
REGS('r', ALL_GENERAL_REGS)
140
+TESTS += noexec
50
-REGS('R', ALL_GENERAL_REGS64)
51
REGS('s', ALL_QLDST_REGS)
52
-REGS('S', ALL_QLDST_REGS64)
53
-REGS('A', TARGET_LONG_BITS == 64 ? ALL_QLDST_REGS64 : ALL_QLDST_REGS)
54
55
/*
56
* Define constraint letters for constants:
57
diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc
58
index XXXXXXX..XXXXXXX 100644
59
--- a/tcg/sparc64/tcg-target.c.inc
60
+++ b/tcg/sparc64/tcg-target.c.inc
61
@@ -XXX,XX +XXX,XX @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
62
#else
63
#define SOFTMMU_RESERVE_REGS 0
64
#endif
65
-
66
-/*
67
- * Note that sparcv8plus can only hold 64 bit quantities in %g and %o
68
- * registers. These are saved manually by the kernel in full 64-bit
69
- * slots. The %i and %l registers are saved by the register window
70
- * mechanism, which only allocates space for 32 bits. Given that this
71
- * window spill/fill can happen on any signal, we must consider the
72
- * high bits of the %i and %l registers garbage at all times.
73
- */
74
#define ALL_GENERAL_REGS MAKE_64BIT_MASK(0, 32)
75
-# define ALL_GENERAL_REGS64 ALL_GENERAL_REGS
76
#define ALL_QLDST_REGS (ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS)
77
-#define ALL_QLDST_REGS64 (ALL_GENERAL_REGS64 & ~SOFTMMU_RESERVE_REGS)
78
79
/* Define some temporary registers. T2 is used for constant generation. */
80
#define TCG_REG_T1 TCG_REG_G1
81
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
82
return C_O0_I1(r);
83
84
case INDEX_op_ld8u_i32:
85
+ case INDEX_op_ld8u_i64:
86
case INDEX_op_ld8s_i32:
87
+ case INDEX_op_ld8s_i64:
88
case INDEX_op_ld16u_i32:
89
+ case INDEX_op_ld16u_i64:
90
case INDEX_op_ld16s_i32:
91
+ case INDEX_op_ld16s_i64:
92
case INDEX_op_ld_i32:
93
+ case INDEX_op_ld32u_i64:
94
+ case INDEX_op_ld32s_i64:
95
+ case INDEX_op_ld_i64:
96
case INDEX_op_neg_i32:
97
+ case INDEX_op_neg_i64:
98
case INDEX_op_not_i32:
99
+ case INDEX_op_not_i64:
100
+ case INDEX_op_ext32s_i64:
101
+ case INDEX_op_ext32u_i64:
102
+ case INDEX_op_ext_i32_i64:
103
+ case INDEX_op_extu_i32_i64:
104
+ case INDEX_op_extrl_i64_i32:
105
+ case INDEX_op_extrh_i64_i32:
106
return C_O1_I1(r, r);
107
108
case INDEX_op_st8_i32:
109
+ case INDEX_op_st8_i64:
110
case INDEX_op_st16_i32:
111
+ case INDEX_op_st16_i64:
112
case INDEX_op_st_i32:
113
+ case INDEX_op_st32_i64:
114
+ case INDEX_op_st_i64:
115
return C_O0_I2(rZ, r);
116
117
case INDEX_op_add_i32:
118
+ case INDEX_op_add_i64:
119
case INDEX_op_mul_i32:
120
+ case INDEX_op_mul_i64:
121
case INDEX_op_div_i32:
122
+ case INDEX_op_div_i64:
123
case INDEX_op_divu_i32:
124
+ case INDEX_op_divu_i64:
125
case INDEX_op_sub_i32:
126
+ case INDEX_op_sub_i64:
127
case INDEX_op_and_i32:
128
+ case INDEX_op_and_i64:
129
case INDEX_op_andc_i32:
130
+ case INDEX_op_andc_i64:
131
case INDEX_op_or_i32:
132
+ case INDEX_op_or_i64:
133
case INDEX_op_orc_i32:
134
+ case INDEX_op_orc_i64:
135
case INDEX_op_xor_i32:
136
+ case INDEX_op_xor_i64:
137
case INDEX_op_shl_i32:
138
+ case INDEX_op_shl_i64:
139
case INDEX_op_shr_i32:
140
+ case INDEX_op_shr_i64:
141
case INDEX_op_sar_i32:
142
+ case INDEX_op_sar_i64:
143
case INDEX_op_setcond_i32:
144
+ case INDEX_op_setcond_i64:
145
return C_O1_I2(r, rZ, rJ);
146
147
case INDEX_op_brcond_i32:
148
+ case INDEX_op_brcond_i64:
149
return C_O0_I2(rZ, rJ);
150
case INDEX_op_movcond_i32:
151
+ case INDEX_op_movcond_i64:
152
return C_O1_I4(r, rZ, rJ, rI, 0);
153
case INDEX_op_add2_i32:
154
+ case INDEX_op_add2_i64:
155
case INDEX_op_sub2_i32:
156
+ case INDEX_op_sub2_i64:
157
return C_O2_I4(r, r, rZ, rZ, rJ, rJ);
158
case INDEX_op_mulu2_i32:
159
case INDEX_op_muls2_i32:
160
return C_O2_I2(r, r, rZ, rJ);
161
-
162
- case INDEX_op_ld8u_i64:
163
- case INDEX_op_ld8s_i64:
164
- case INDEX_op_ld16u_i64:
165
- case INDEX_op_ld16s_i64:
166
- case INDEX_op_ld32u_i64:
167
- case INDEX_op_ld32s_i64:
168
- case INDEX_op_ld_i64:
169
- case INDEX_op_ext_i32_i64:
170
- case INDEX_op_extu_i32_i64:
171
- return C_O1_I1(R, r);
172
-
173
- case INDEX_op_st8_i64:
174
- case INDEX_op_st16_i64:
175
- case INDEX_op_st32_i64:
176
- case INDEX_op_st_i64:
177
- return C_O0_I2(RZ, r);
178
-
179
- case INDEX_op_add_i64:
180
- case INDEX_op_mul_i64:
181
- case INDEX_op_div_i64:
182
- case INDEX_op_divu_i64:
183
- case INDEX_op_sub_i64:
184
- case INDEX_op_and_i64:
185
- case INDEX_op_andc_i64:
186
- case INDEX_op_or_i64:
187
- case INDEX_op_orc_i64:
188
- case INDEX_op_xor_i64:
189
- case INDEX_op_shl_i64:
190
- case INDEX_op_shr_i64:
191
- case INDEX_op_sar_i64:
192
- case INDEX_op_setcond_i64:
193
- return C_O1_I2(R, RZ, RJ);
194
-
195
- case INDEX_op_neg_i64:
196
- case INDEX_op_not_i64:
197
- case INDEX_op_ext32s_i64:
198
- case INDEX_op_ext32u_i64:
199
- return C_O1_I1(R, R);
200
-
201
- case INDEX_op_extrl_i64_i32:
202
- case INDEX_op_extrh_i64_i32:
203
- return C_O1_I1(r, R);
204
-
205
- case INDEX_op_brcond_i64:
206
- return C_O0_I2(RZ, RJ);
207
- case INDEX_op_movcond_i64:
208
- return C_O1_I4(R, RZ, RJ, RI, 0);
209
- case INDEX_op_add2_i64:
210
- case INDEX_op_sub2_i64:
211
- return C_O2_I4(R, R, RZ, RZ, RJ, RI);
212
case INDEX_op_muluh_i64:
213
- return C_O1_I2(R, R, R);
214
+ return C_O1_I2(r, r, r);
215
216
case INDEX_op_qemu_ld_i32:
217
- return C_O1_I1(r, A);
218
case INDEX_op_qemu_ld_i64:
219
- return C_O1_I1(R, A);
220
+ return C_O1_I1(r, s);
221
case INDEX_op_qemu_st_i32:
222
- return C_O0_I2(sZ, A);
223
case INDEX_op_qemu_st_i64:
224
- return C_O0_I2(SZ, A);
225
+ return C_O0_I2(sZ, s);
226
227
default:
228
g_assert_not_reached();
229
@@ -XXX,XX +XXX,XX @@ static void tcg_target_init(TCGContext *s)
230
#endif
231
232
tcg_target_available_regs[TCG_TYPE_I32] = ALL_GENERAL_REGS;
233
- tcg_target_available_regs[TCG_TYPE_I64] = ALL_GENERAL_REGS64;
234
+ tcg_target_available_regs[TCG_TYPE_I64] = ALL_GENERAL_REGS;
235
236
tcg_target_call_clobber_regs = 0;
237
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_G1);
141
--
238
--
142
2.34.1
239
2.34.1
diff view generated by jsdifflib
1
While there are no target-specific nonfaulting probes,
1
From: Icenowy Zheng <uwu@icenowy.me>
2
generic code may grow some uses at some point.
3
2
4
Note that the attrs argument was incorrect -- it should have
3
When registering helpers via FFI for TCI, the inner loop that iterates
5
been MEMTXATTRS_UNSPECIFIED. Just use the simpler interface.
4
parameters of the helper reuses (and thus pollutes) the same variable
5
used by the outer loop that iterates all helpers, thus made some helpers
6
unregistered.
6
7
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Fix this logic error by using a dedicated temporary variable for the
9
inner loop.
10
11
Fixes: 22f15579fa ("tcg: Build ffi data structures for helpers")
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
14
Signed-off-by: Icenowy Zheng <uwu@icenowy.me>
15
Message-Id: <20221028072145.1593205-1-uwu@icenowy.me>
16
[rth: Move declaration of j to the for loop itself]
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
17
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
18
---
10
target/avr/helper.c | 46 ++++++++++++++++++++++++++++-----------------
19
tcg/tcg.c | 6 +++---
11
1 file changed, 29 insertions(+), 17 deletions(-)
20
1 file changed, 3 insertions(+), 3 deletions(-)
12
21
13
diff --git a/target/avr/helper.c b/target/avr/helper.c
22
diff --git a/tcg/tcg.c b/tcg/tcg.c
14
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
15
--- a/target/avr/helper.c
24
--- a/tcg/tcg.c
16
+++ b/target/avr/helper.c
25
+++ b/tcg/tcg.c
17
@@ -XXX,XX +XXX,XX @@ bool avr_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
26
@@ -XXX,XX +XXX,XX @@ static void tcg_context_init(unsigned max_cpus)
18
MMUAccessType access_type, int mmu_idx,
27
19
bool probe, uintptr_t retaddr)
28
if (nargs != 0) {
20
{
29
ca->cif.arg_types = ca->args;
21
- int prot = 0;
30
- for (i = 0; i < nargs; ++i) {
22
- MemTxAttrs attrs = {};
31
- int typecode = extract32(typemask, (i + 1) * 3, 3);
23
+ int prot, page_size = TARGET_PAGE_SIZE;
32
- ca->args[i] = typecode_to_ffi[typecode];
24
uint32_t paddr;
33
+ for (int j = 0; j < nargs; ++j) {
25
34
+ int typecode = extract32(typemask, (j + 1) * 3, 3);
26
address &= TARGET_PAGE_MASK;
35
+ ca->args[j] = typecode_to_ffi[typecode];
27
36
}
28
if (mmu_idx == MMU_CODE_IDX) {
29
- /* access to code in flash */
30
+ /* Access to code in flash. */
31
paddr = OFFSET_CODE + address;
32
prot = PAGE_READ | PAGE_EXEC;
33
- if (paddr + TARGET_PAGE_SIZE > OFFSET_DATA) {
34
+ if (paddr >= OFFSET_DATA) {
35
+ /*
36
+ * This should not be possible via any architectural operations.
37
+ * There is certainly not an exception that we can deliver.
38
+ * Accept probing that might come from generic code.
39
+ */
40
+ if (probe) {
41
+ return false;
42
+ }
43
error_report("execution left flash memory");
44
abort();
45
}
37
}
46
- } else if (address < NUMBER_OF_CPU_REGISTERS + NUMBER_OF_IO_REGISTERS) {
47
- /*
48
- * access to CPU registers, exit and rebuilt this TB to use full access
49
- * incase it touches specially handled registers like SREG or SP
50
- */
51
- AVRCPU *cpu = AVR_CPU(cs);
52
- CPUAVRState *env = &cpu->env;
53
- env->fullacc = 1;
54
- cpu_loop_exit_restore(cs, retaddr);
55
} else {
56
- /* access to memory. nothing special */
57
+ /* Access to memory. */
58
paddr = OFFSET_DATA + address;
59
prot = PAGE_READ | PAGE_WRITE;
60
+ if (address < NUMBER_OF_CPU_REGISTERS + NUMBER_OF_IO_REGISTERS) {
61
+ /*
62
+ * Access to CPU registers, exit and rebuilt this TB to use
63
+ * full access in case it touches specially handled registers
64
+ * like SREG or SP. For probing, set page_size = 1, in order
65
+ * to force tlb_fill to be called for the next access.
66
+ */
67
+ if (probe) {
68
+ page_size = 1;
69
+ } else {
70
+ AVRCPU *cpu = AVR_CPU(cs);
71
+ CPUAVRState *env = &cpu->env;
72
+ env->fullacc = 1;
73
+ cpu_loop_exit_restore(cs, retaddr);
74
+ }
75
+ }
76
}
77
78
- tlb_set_page_with_attrs(cs, address, paddr, attrs, prot,
79
- mmu_idx, TARGET_PAGE_SIZE);
80
-
81
+ tlb_set_page(cs, address, paddr, prot, mmu_idx, page_size);
82
return true;
83
}
84
38
85
--
39
--
86
2.34.1
40
2.34.1
87
41
88
42
diff view generated by jsdifflib
1
Pass these along to translator_loop -- pc may be used instead
1
Add a way to examine the unwind data without actually
2
of tb->pc, and host_pc is currently unused. Adjust all targets
2
restoring the data back into env.
3
at one time.
4
3
5
Acked-by: Alistair Francis <alistair.francis@wdc.com>
4
Reviewed-by: Claudio Fontana <cfontana@suse.de>
6
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
7
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
6
---
10
include/exec/exec-all.h | 1 -
7
accel/tcg/internal.h | 4 +--
11
include/exec/translator.h | 24 ++++++++++++++++++++----
8
include/exec/exec-all.h | 21 ++++++++---
12
accel/tcg/translate-all.c | 6 ++++--
9
accel/tcg/translate-all.c | 74 ++++++++++++++++++++++++++-------------
13
accel/tcg/translator.c | 9 +++++----
10
3 files changed, 68 insertions(+), 31 deletions(-)
14
target/alpha/translate.c | 5 +++--
15
target/arm/translate.c | 5 +++--
16
target/avr/translate.c | 5 +++--
17
target/cris/translate.c | 5 +++--
18
target/hexagon/translate.c | 6 ++++--
19
target/hppa/translate.c | 5 +++--
20
target/i386/tcg/translate.c | 5 +++--
21
target/loongarch/translate.c | 6 ++++--
22
target/m68k/translate.c | 5 +++--
23
target/microblaze/translate.c | 5 +++--
24
target/mips/tcg/translate.c | 5 +++--
25
target/nios2/translate.c | 5 +++--
26
target/openrisc/translate.c | 6 ++++--
27
target/ppc/translate.c | 5 +++--
28
target/riscv/translate.c | 5 +++--
29
target/rx/translate.c | 5 +++--
30
target/s390x/tcg/translate.c | 5 +++--
31
target/sh4/translate.c | 5 +++--
32
target/sparc/translate.c | 5 +++--
33
target/tricore/translate.c | 6 ++++--
34
target/xtensa/translate.c | 6 ++++--
35
25 files changed, 97 insertions(+), 53 deletions(-)
36
11
12
diff --git a/accel/tcg/internal.h b/accel/tcg/internal.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/accel/tcg/internal.h
15
+++ b/accel/tcg/internal.h
16
@@ -XXX,XX +XXX,XX @@ void tb_reset_jump(TranslationBlock *tb, int n);
17
TranslationBlock *tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
18
tb_page_addr_t phys_page2);
19
bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc);
20
-int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
21
- uintptr_t searched_pc, bool reset_icount);
22
+void cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
23
+ uintptr_t host_pc, bool reset_icount);
24
25
/* Return the current PC from CPU, which may be cached in TB. */
26
static inline target_ulong log_pc(CPUState *cpu, const TranslationBlock *tb)
37
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
27
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
38
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
39
--- a/include/exec/exec-all.h
29
--- a/include/exec/exec-all.h
40
+++ b/include/exec/exec-all.h
30
+++ b/include/exec/exec-all.h
41
@@ -XXX,XX +XXX,XX @@ typedef ram_addr_t tb_page_addr_t;
31
@@ -XXX,XX +XXX,XX @@ typedef ram_addr_t tb_page_addr_t;
42
#define TB_PAGE_ADDR_FMT RAM_ADDR_FMT
32
#define TB_PAGE_ADDR_FMT RAM_ADDR_FMT
43
#endif
33
#endif
44
34
45
-void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns);
46
void restore_state_to_opc(CPUArchState *env, TranslationBlock *tb,
47
target_ulong *data);
48
49
diff --git a/include/exec/translator.h b/include/exec/translator.h
50
index XXXXXXX..XXXXXXX 100644
51
--- a/include/exec/translator.h
52
+++ b/include/exec/translator.h
53
@@ -XXX,XX +XXX,XX @@
54
#include "exec/translate-all.h"
55
#include "tcg/tcg.h"
56
57
+/**
35
+/**
58
+ * gen_intermediate_code
36
+ * cpu_unwind_state_data:
59
+ * @cpu: cpu context
37
+ * @cpu: the cpu context
60
+ * @tb: translation block
38
+ * @host_pc: the host pc within the translation
61
+ * @max_insns: max number of instructions to translate
39
+ * @data: output data
62
+ * @pc: guest virtual program counter address
63
+ * @host_pc: host physical program counter address
64
+ *
40
+ *
65
+ * This function must be provided by the target, which should create
41
+ * Attempt to load the the unwind state for a host pc occurring in
66
+ * the target-specific DisasContext, and then invoke translator_loop.
42
+ * translated code. If @host_pc is not in translated code, the
43
+ * function returns false; otherwise @data is loaded.
44
+ * This is the same unwind info as given to restore_state_to_opc.
67
+ */
45
+ */
68
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
46
+bool cpu_unwind_state_data(CPUState *cpu, uintptr_t host_pc, uint64_t *data);
69
+ target_ulong pc, void *host_pc);
47
+
70
71
/**
48
/**
72
* DisasJumpType:
49
* cpu_restore_state:
73
@@ -XXX,XX +XXX,XX @@ typedef struct TranslatorOps {
50
- * @cpu: the vCPU state is to be restore to
74
51
- * @searched_pc: the host PC the fault occurred at
75
/**
52
+ * @cpu: the cpu context
76
* translator_loop:
53
+ * @host_pc: the host pc within the translation
77
- * @ops: Target-specific operations.
54
* @will_exit: true if the TB executed will be interrupted after some
78
- * @db: Disassembly context.
55
cpu adjustments. Required for maintaining the correct
79
* @cpu: Target vCPU.
56
icount valus
80
* @tb: Translation block.
57
* @return: true if state was restored, false otherwise
81
* @max_insns: Maximum number of insns to translate.
82
+ * @pc: guest virtual program counter address
83
+ * @host_pc: host physical program counter address
84
+ * @ops: Target-specific operations.
85
+ * @db: Disassembly context.
86
*
58
*
87
* Generic translator loop.
59
* Attempt to restore the state for a fault occurring in translated
88
*
60
- * code. If the searched_pc is not in translated code no state is
89
@@ -XXX,XX +XXX,XX @@ typedef struct TranslatorOps {
61
+ * code. If @host_pc is not in translated code no state is
90
* - When single-stepping is enabled (system-wide or on the current vCPU).
62
* restored and the function returns false.
91
* - When too many instructions have been translated.
92
*/
63
*/
93
-void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
64
-bool cpu_restore_state(CPUState *cpu, uintptr_t searched_pc, bool will_exit);
94
- CPUState *cpu, TranslationBlock *tb, int max_insns);
65
+bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit);
95
+void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
66
96
+ target_ulong pc, void *host_pc,
67
G_NORETURN void cpu_loop_exit_noexc(CPUState *cpu);
97
+ const TranslatorOps *ops, DisasContextBase *db);
68
G_NORETURN void cpu_loop_exit(CPUState *cpu);
98
99
void translator_loop_temp_check(DisasContextBase *db);
100
101
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
69
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
102
index XXXXXXX..XXXXXXX 100644
70
index XXXXXXX..XXXXXXX 100644
103
--- a/accel/tcg/translate-all.c
71
--- a/accel/tcg/translate-all.c
104
+++ b/accel/tcg/translate-all.c
72
+++ b/accel/tcg/translate-all.c
105
@@ -XXX,XX +XXX,XX @@
73
@@ -XXX,XX +XXX,XX @@ static int encode_search(TranslationBlock *tb, uint8_t *block)
106
74
return p - block;
107
#include "exec/cputlb.h"
75
}
108
#include "exec/translate-all.h"
76
109
+#include "exec/translator.h"
77
-/* The cpu state corresponding to 'searched_pc' is restored.
110
#include "qemu/bitmap.h"
78
- * When reset_icount is true, current TB will be interrupted and
111
#include "qemu/qemu-print.h"
79
- * icount should be recalculated.
112
#include "qemu/timer.h"
80
- */
113
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
81
-int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
114
TCGProfile *prof = &tcg_ctx->prof;
82
- uintptr_t searched_pc, bool reset_icount)
115
int64_t ti;
83
+static int cpu_unwind_data_from_tb(TranslationBlock *tb, uintptr_t host_pc,
84
+ uint64_t *data)
85
{
86
- uint64_t data[TARGET_INSN_START_WORDS];
87
- uintptr_t host_pc = (uintptr_t)tb->tc.ptr;
88
+ uintptr_t iter_pc = (uintptr_t)tb->tc.ptr;
89
const uint8_t *p = tb->tc.ptr + tb->tc.size;
90
int i, j, num_insns = tb->icount;
91
-#ifdef CONFIG_PROFILER
92
- TCGProfile *prof = &tcg_ctx->prof;
93
- int64_t ti = profile_getclock();
94
-#endif
95
96
- searched_pc -= GETPC_ADJ;
97
+ host_pc -= GETPC_ADJ;
98
99
- if (searched_pc < host_pc) {
100
+ if (host_pc < iter_pc) {
101
return -1;
102
}
103
104
- memset(data, 0, sizeof(data));
105
+ memset(data, 0, sizeof(uint64_t) * TARGET_INSN_START_WORDS);
106
if (!TARGET_TB_PCREL) {
107
data[0] = tb_pc(tb);
108
}
109
110
- /* Reconstruct the stored insn data while looking for the point at
111
- which the end of the insn exceeds the searched_pc. */
112
+ /*
113
+ * Reconstruct the stored insn data while looking for the point
114
+ * at which the end of the insn exceeds host_pc.
115
+ */
116
for (i = 0; i < num_insns; ++i) {
117
for (j = 0; j < TARGET_INSN_START_WORDS; ++j) {
118
data[j] += decode_sleb128(&p);
119
}
120
- host_pc += decode_sleb128(&p);
121
- if (host_pc > searched_pc) {
122
- goto found;
123
+ iter_pc += decode_sleb128(&p);
124
+ if (iter_pc > host_pc) {
125
+ return num_insns - i;
126
}
127
}
128
return -1;
129
+}
130
+
131
+/*
132
+ * The cpu state corresponding to 'host_pc' is restored.
133
+ * When reset_icount is true, current TB will be interrupted and
134
+ * icount should be recalculated.
135
+ */
136
+void cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
137
+ uintptr_t host_pc, bool reset_icount)
138
+{
139
+ uint64_t data[TARGET_INSN_START_WORDS];
140
+#ifdef CONFIG_PROFILER
141
+ TCGProfile *prof = &tcg_ctx->prof;
142
+ int64_t ti = profile_getclock();
143
+#endif
144
+ int insns_left = cpu_unwind_data_from_tb(tb, host_pc, data);
145
+
146
+ if (insns_left < 0) {
147
+ return;
148
+ }
149
150
- found:
151
if (reset_icount && (tb_cflags(tb) & CF_USE_ICOUNT)) {
152
assert(icount_enabled());
153
- /* Reset the cycle counter to the start of the block
154
- and shift if to the number of actually executed instructions */
155
- cpu_neg(cpu)->icount_decr.u16.low += num_insns - i;
156
+ /*
157
+ * Reset the cycle counter to the start of the block and
158
+ * shift if to the number of actually executed instructions.
159
+ */
160
+ cpu_neg(cpu)->icount_decr.u16.low += insns_left;
161
}
162
163
cpu->cc->tcg_ops->restore_state_to_opc(cpu, tb, data);
164
@@ -XXX,XX +XXX,XX @@ int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
165
prof->restore_time + profile_getclock() - ti);
166
qatomic_set(&prof->restore_count, prof->restore_count + 1);
116
#endif
167
#endif
117
+ void *host_pc;
168
- return 0;
118
119
assert_memory_lock();
120
qemu_thread_jit_write();
121
122
- phys_pc = get_page_addr_code(env, pc);
123
+ phys_pc = get_page_addr_code_hostp(env, pc, &host_pc);
124
125
if (phys_pc == -1) {
126
/* Generate a one-shot TB with 1 insn in it */
127
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
128
tcg_func_start(tcg_ctx);
129
130
tcg_ctx->cpu = env_cpu(env);
131
- gen_intermediate_code(cpu, tb, max_insns);
132
+ gen_intermediate_code(cpu, tb, max_insns, pc, host_pc);
133
assert(tb->size != 0);
134
tcg_ctx->cpu = NULL;
135
max_insns = tb->icount;
136
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
137
index XXXXXXX..XXXXXXX 100644
138
--- a/accel/tcg/translator.c
139
+++ b/accel/tcg/translator.c
140
@@ -XXX,XX +XXX,XX @@ static inline void translator_page_protect(DisasContextBase *dcbase,
141
#endif
142
}
169
}
143
170
144
-void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
171
bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit)
145
- CPUState *cpu, TranslationBlock *tb, int max_insns)
172
@@ -XXX,XX +XXX,XX @@ bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit)
146
+void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
173
return false;
147
+ target_ulong pc, void *host_pc,
174
}
148
+ const TranslatorOps *ops, DisasContextBase *db)
175
176
+bool cpu_unwind_state_data(CPUState *cpu, uintptr_t host_pc, uint64_t *data)
177
+{
178
+ if (in_code_gen_buffer((const void *)(host_pc - tcg_splitwx_diff))) {
179
+ TranslationBlock *tb = tcg_tb_lookup(host_pc);
180
+ if (tb) {
181
+ return cpu_unwind_data_from_tb(tb, host_pc, data) >= 0;
182
+ }
183
+ }
184
+ return false;
185
+}
186
+
187
void page_init(void)
149
{
188
{
150
uint32_t cflags = tb_cflags(tb);
189
page_size_init();
151
bool plugin_enabled;
152
153
/* Initialize DisasContext */
154
db->tb = tb;
155
- db->pc_first = tb->pc;
156
- db->pc_next = db->pc_first;
157
+ db->pc_first = pc;
158
+ db->pc_next = pc;
159
db->is_jmp = DISAS_NEXT;
160
db->num_insns = 0;
161
db->max_insns = max_insns;
162
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
163
index XXXXXXX..XXXXXXX 100644
164
--- a/target/alpha/translate.c
165
+++ b/target/alpha/translate.c
166
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps alpha_tr_ops = {
167
.disas_log = alpha_tr_disas_log,
168
};
169
170
-void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
171
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
172
+ target_ulong pc, void *host_pc)
173
{
174
DisasContext dc;
175
- translator_loop(&alpha_tr_ops, &dc.base, cpu, tb, max_insns);
176
+ translator_loop(cpu, tb, max_insns, pc, host_pc, &alpha_tr_ops, &dc.base);
177
}
178
179
void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb,
180
diff --git a/target/arm/translate.c b/target/arm/translate.c
181
index XXXXXXX..XXXXXXX 100644
182
--- a/target/arm/translate.c
183
+++ b/target/arm/translate.c
184
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps thumb_translator_ops = {
185
};
186
187
/* generate intermediate code for basic block 'tb'. */
188
-void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
189
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
190
+ target_ulong pc, void *host_pc)
191
{
192
DisasContext dc = { };
193
const TranslatorOps *ops = &arm_translator_ops;
194
@@ -XXX,XX +XXX,XX @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
195
}
196
#endif
197
198
- translator_loop(ops, &dc.base, cpu, tb, max_insns);
199
+ translator_loop(cpu, tb, max_insns, pc, host_pc, ops, &dc.base);
200
}
201
202
void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
203
diff --git a/target/avr/translate.c b/target/avr/translate.c
204
index XXXXXXX..XXXXXXX 100644
205
--- a/target/avr/translate.c
206
+++ b/target/avr/translate.c
207
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps avr_tr_ops = {
208
.disas_log = avr_tr_disas_log,
209
};
210
211
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
212
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
213
+ target_ulong pc, void *host_pc)
214
{
215
DisasContext dc = { };
216
- translator_loop(&avr_tr_ops, &dc.base, cs, tb, max_insns);
217
+ translator_loop(cs, tb, max_insns, pc, host_pc, &avr_tr_ops, &dc.base);
218
}
219
220
void restore_state_to_opc(CPUAVRState *env, TranslationBlock *tb,
221
diff --git a/target/cris/translate.c b/target/cris/translate.c
222
index XXXXXXX..XXXXXXX 100644
223
--- a/target/cris/translate.c
224
+++ b/target/cris/translate.c
225
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps cris_tr_ops = {
226
.disas_log = cris_tr_disas_log,
227
};
228
229
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
230
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
231
+ target_ulong pc, void *host_pc)
232
{
233
DisasContext dc;
234
- translator_loop(&cris_tr_ops, &dc.base, cs, tb, max_insns);
235
+ translator_loop(cs, tb, max_insns, pc, host_pc, &cris_tr_ops, &dc.base);
236
}
237
238
void cris_cpu_dump_state(CPUState *cs, FILE *f, int flags)
239
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
240
index XXXXXXX..XXXXXXX 100644
241
--- a/target/hexagon/translate.c
242
+++ b/target/hexagon/translate.c
243
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps hexagon_tr_ops = {
244
.disas_log = hexagon_tr_disas_log,
245
};
246
247
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
248
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
249
+ target_ulong pc, void *host_pc)
250
{
251
DisasContext ctx;
252
253
- translator_loop(&hexagon_tr_ops, &ctx.base, cs, tb, max_insns);
254
+ translator_loop(cs, tb, max_insns, pc, host_pc,
255
+ &hexagon_tr_ops, &ctx.base);
256
}
257
258
#define NAME_LEN 64
259
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
260
index XXXXXXX..XXXXXXX 100644
261
--- a/target/hppa/translate.c
262
+++ b/target/hppa/translate.c
263
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps hppa_tr_ops = {
264
.disas_log = hppa_tr_disas_log,
265
};
266
267
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
268
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
269
+ target_ulong pc, void *host_pc)
270
{
271
DisasContext ctx;
272
- translator_loop(&hppa_tr_ops, &ctx.base, cs, tb, max_insns);
273
+ translator_loop(cs, tb, max_insns, pc, host_pc, &hppa_tr_ops, &ctx.base);
274
}
275
276
void restore_state_to_opc(CPUHPPAState *env, TranslationBlock *tb,
277
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
278
index XXXXXXX..XXXXXXX 100644
279
--- a/target/i386/tcg/translate.c
280
+++ b/target/i386/tcg/translate.c
281
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps i386_tr_ops = {
282
};
283
284
/* generate intermediate code for basic block 'tb'. */
285
-void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
286
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
287
+ target_ulong pc, void *host_pc)
288
{
289
DisasContext dc;
290
291
- translator_loop(&i386_tr_ops, &dc.base, cpu, tb, max_insns);
292
+ translator_loop(cpu, tb, max_insns, pc, host_pc, &i386_tr_ops, &dc.base);
293
}
294
295
void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
296
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
297
index XXXXXXX..XXXXXXX 100644
298
--- a/target/loongarch/translate.c
299
+++ b/target/loongarch/translate.c
300
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps loongarch_tr_ops = {
301
.disas_log = loongarch_tr_disas_log,
302
};
303
304
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
305
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
306
+ target_ulong pc, void *host_pc)
307
{
308
DisasContext ctx;
309
310
- translator_loop(&loongarch_tr_ops, &ctx.base, cs, tb, max_insns);
311
+ translator_loop(cs, tb, max_insns, pc, host_pc,
312
+ &loongarch_tr_ops, &ctx.base);
313
}
314
315
void loongarch_translate_init(void)
316
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
317
index XXXXXXX..XXXXXXX 100644
318
--- a/target/m68k/translate.c
319
+++ b/target/m68k/translate.c
320
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps m68k_tr_ops = {
321
.disas_log = m68k_tr_disas_log,
322
};
323
324
-void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
325
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
326
+ target_ulong pc, void *host_pc)
327
{
328
DisasContext dc;
329
- translator_loop(&m68k_tr_ops, &dc.base, cpu, tb, max_insns);
330
+ translator_loop(cpu, tb, max_insns, pc, host_pc, &m68k_tr_ops, &dc.base);
331
}
332
333
static double floatx80_to_double(CPUM68KState *env, uint16_t high, uint64_t low)
334
diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
335
index XXXXXXX..XXXXXXX 100644
336
--- a/target/microblaze/translate.c
337
+++ b/target/microblaze/translate.c
338
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps mb_tr_ops = {
339
.disas_log = mb_tr_disas_log,
340
};
341
342
-void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
343
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
344
+ target_ulong pc, void *host_pc)
345
{
346
DisasContext dc;
347
- translator_loop(&mb_tr_ops, &dc.base, cpu, tb, max_insns);
348
+ translator_loop(cpu, tb, max_insns, pc, host_pc, &mb_tr_ops, &dc.base);
349
}
350
351
void mb_cpu_dump_state(CPUState *cs, FILE *f, int flags)
352
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
353
index XXXXXXX..XXXXXXX 100644
354
--- a/target/mips/tcg/translate.c
355
+++ b/target/mips/tcg/translate.c
356
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps mips_tr_ops = {
357
.disas_log = mips_tr_disas_log,
358
};
359
360
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
361
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
362
+ target_ulong pc, void *host_pc)
363
{
364
DisasContext ctx;
365
366
- translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
367
+ translator_loop(cs, tb, max_insns, pc, host_pc, &mips_tr_ops, &ctx.base);
368
}
369
370
void mips_tcg_init(void)
371
diff --git a/target/nios2/translate.c b/target/nios2/translate.c
372
index XXXXXXX..XXXXXXX 100644
373
--- a/target/nios2/translate.c
374
+++ b/target/nios2/translate.c
375
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps nios2_tr_ops = {
376
.disas_log = nios2_tr_disas_log,
377
};
378
379
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
380
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
381
+ target_ulong pc, void *host_pc)
382
{
383
DisasContext dc;
384
- translator_loop(&nios2_tr_ops, &dc.base, cs, tb, max_insns);
385
+ translator_loop(cs, tb, max_insns, pc, host_pc, &nios2_tr_ops, &dc.base);
386
}
387
388
void nios2_cpu_dump_state(CPUState *cs, FILE *f, int flags)
389
diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
390
index XXXXXXX..XXXXXXX 100644
391
--- a/target/openrisc/translate.c
392
+++ b/target/openrisc/translate.c
393
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps openrisc_tr_ops = {
394
.disas_log = openrisc_tr_disas_log,
395
};
396
397
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
398
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
399
+ target_ulong pc, void *host_pc)
400
{
401
DisasContext ctx;
402
403
- translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb, max_insns);
404
+ translator_loop(cs, tb, max_insns, pc, host_pc,
405
+ &openrisc_tr_ops, &ctx.base);
406
}
407
408
void openrisc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
409
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
410
index XXXXXXX..XXXXXXX 100644
411
--- a/target/ppc/translate.c
412
+++ b/target/ppc/translate.c
413
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps ppc_tr_ops = {
414
.disas_log = ppc_tr_disas_log,
415
};
416
417
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
418
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
419
+ target_ulong pc, void *host_pc)
420
{
421
DisasContext ctx;
422
423
- translator_loop(&ppc_tr_ops, &ctx.base, cs, tb, max_insns);
424
+ translator_loop(cs, tb, max_insns, pc, host_pc, &ppc_tr_ops, &ctx.base);
425
}
426
427
void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb,
428
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
429
index XXXXXXX..XXXXXXX 100644
430
--- a/target/riscv/translate.c
431
+++ b/target/riscv/translate.c
432
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps riscv_tr_ops = {
433
.disas_log = riscv_tr_disas_log,
434
};
435
436
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
437
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
438
+ target_ulong pc, void *host_pc)
439
{
440
DisasContext ctx;
441
442
- translator_loop(&riscv_tr_ops, &ctx.base, cs, tb, max_insns);
443
+ translator_loop(cs, tb, max_insns, pc, host_pc, &riscv_tr_ops, &ctx.base);
444
}
445
446
void riscv_translate_init(void)
447
diff --git a/target/rx/translate.c b/target/rx/translate.c
448
index XXXXXXX..XXXXXXX 100644
449
--- a/target/rx/translate.c
450
+++ b/target/rx/translate.c
451
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps rx_tr_ops = {
452
.disas_log = rx_tr_disas_log,
453
};
454
455
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
456
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
457
+ target_ulong pc, void *host_pc)
458
{
459
DisasContext dc;
460
461
- translator_loop(&rx_tr_ops, &dc.base, cs, tb, max_insns);
462
+ translator_loop(cs, tb, max_insns, pc, host_pc, &rx_tr_ops, &dc.base);
463
}
464
465
void restore_state_to_opc(CPURXState *env, TranslationBlock *tb,
466
diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c
467
index XXXXXXX..XXXXXXX 100644
468
--- a/target/s390x/tcg/translate.c
469
+++ b/target/s390x/tcg/translate.c
470
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps s390x_tr_ops = {
471
.disas_log = s390x_tr_disas_log,
472
};
473
474
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
475
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
476
+ target_ulong pc, void *host_pc)
477
{
478
DisasContext dc;
479
480
- translator_loop(&s390x_tr_ops, &dc.base, cs, tb, max_insns);
481
+ translator_loop(cs, tb, max_insns, pc, host_pc, &s390x_tr_ops, &dc.base);
482
}
483
484
void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb,
485
diff --git a/target/sh4/translate.c b/target/sh4/translate.c
486
index XXXXXXX..XXXXXXX 100644
487
--- a/target/sh4/translate.c
488
+++ b/target/sh4/translate.c
489
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps sh4_tr_ops = {
490
.disas_log = sh4_tr_disas_log,
491
};
492
493
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
494
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
495
+ target_ulong pc, void *host_pc)
496
{
497
DisasContext ctx;
498
499
- translator_loop(&sh4_tr_ops, &ctx.base, cs, tb, max_insns);
500
+ translator_loop(cs, tb, max_insns, pc, host_pc, &sh4_tr_ops, &ctx.base);
501
}
502
503
void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb,
504
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
505
index XXXXXXX..XXXXXXX 100644
506
--- a/target/sparc/translate.c
507
+++ b/target/sparc/translate.c
508
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps sparc_tr_ops = {
509
.disas_log = sparc_tr_disas_log,
510
};
511
512
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
513
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
514
+ target_ulong pc, void *host_pc)
515
{
516
DisasContext dc = {};
517
518
- translator_loop(&sparc_tr_ops, &dc.base, cs, tb, max_insns);
519
+ translator_loop(cs, tb, max_insns, pc, host_pc, &sparc_tr_ops, &dc.base);
520
}
521
522
void sparc_tcg_init(void)
523
diff --git a/target/tricore/translate.c b/target/tricore/translate.c
524
index XXXXXXX..XXXXXXX 100644
525
--- a/target/tricore/translate.c
526
+++ b/target/tricore/translate.c
527
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps tricore_tr_ops = {
528
};
529
530
531
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
532
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
533
+ target_ulong pc, void *host_pc)
534
{
535
DisasContext ctx;
536
- translator_loop(&tricore_tr_ops, &ctx.base, cs, tb, max_insns);
537
+ translator_loop(cs, tb, max_insns, pc, host_pc,
538
+ &tricore_tr_ops, &ctx.base);
539
}
540
541
void
542
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
543
index XXXXXXX..XXXXXXX 100644
544
--- a/target/xtensa/translate.c
545
+++ b/target/xtensa/translate.c
546
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps xtensa_translator_ops = {
547
.disas_log = xtensa_tr_disas_log,
548
};
549
550
-void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
551
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
552
+ target_ulong pc, void *host_pc)
553
{
554
DisasContext dc = {};
555
- translator_loop(&xtensa_translator_ops, &dc.base, cpu, tb, max_insns);
556
+ translator_loop(cpu, tb, max_insns, pc, host_pc,
557
+ &xtensa_translator_ops, &dc.base);
558
}
559
560
void xtensa_cpu_dump_state(CPUState *cs, FILE *f, int flags)
561
--
190
--
562
2.34.1
191
2.34.1
diff view generated by jsdifflib
1
From: Ilya Leoshkevich <iii@linux.ibm.com>
1
Avoid cpu_restore_state, and modifying env->eip out from
2
underneath the translator with TARGET_TB_PCREL. There is
3
some slight duplication from x86_restore_state_to_opc,
4
but it's just a few lines.
2
5
3
Right now translator stops right *after* the end of a page, which
6
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1269
4
breaks reporting of fault locations when the last instruction of a
7
Reviewed-by: Claudio Fontana <cfontana@suse.de>
5
multi-insn translation block crosses a page boundary.
6
7
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-Id: <20220817150506.592862-3-iii@linux.ibm.com>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
---
9
---
12
target/s390x/tcg/translate.c | 15 +++-
10
target/i386/helper.c | 21 +++++++++++++++++++--
13
tests/tcg/s390x/noexec.c | 106 +++++++++++++++++++++++
11
1 file changed, 19 insertions(+), 2 deletions(-)
14
tests/tcg/multiarch/noexec.c.inc | 139 +++++++++++++++++++++++++++++++
15
tests/tcg/s390x/Makefile.target | 1 +
16
4 files changed, 257 insertions(+), 4 deletions(-)
17
create mode 100644 tests/tcg/s390x/noexec.c
18
create mode 100644 tests/tcg/multiarch/noexec.c.inc
19
12
20
diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c
13
diff --git a/target/i386/helper.c b/target/i386/helper.c
21
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
22
--- a/target/s390x/tcg/translate.c
15
--- a/target/i386/helper.c
23
+++ b/target/s390x/tcg/translate.c
16
+++ b/target/i386/helper.c
24
@@ -XXX,XX +XXX,XX @@ static void s390x_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
17
@@ -XXX,XX +XXX,XX @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
25
dc->insn_start = tcg_last_op();
18
}
26
}
19
}
27
20
28
+static target_ulong get_next_pc(CPUS390XState *env, DisasContext *s,
21
+static target_ulong get_memio_eip(CPUX86State *env)
29
+ uint64_t pc)
30
+{
22
+{
31
+ uint64_t insn = ld_code2(env, s, pc);
23
+ uint64_t data[TARGET_INSN_START_WORDS];
24
+ CPUState *cs = env_cpu(env);
32
+
25
+
33
+ return pc + get_ilen((insn >> 8) & 0xff);
26
+ if (!cpu_unwind_state_data(cs, cs->mem_io_pc, data)) {
34
+}
27
+ return env->eip;
35
+
36
static void s390x_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
37
{
38
CPUS390XState *env = cs->env_ptr;
39
@@ -XXX,XX +XXX,XX @@ static void s390x_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
40
41
dc->base.is_jmp = translate_one(env, dc);
42
if (dc->base.is_jmp == DISAS_NEXT) {
43
- uint64_t page_start;
44
-
45
- page_start = dc->base.pc_first & TARGET_PAGE_MASK;
46
- if (dc->base.pc_next - page_start >= TARGET_PAGE_SIZE || dc->ex_value) {
47
+ if (!is_same_page(dcbase, dc->base.pc_next) ||
48
+ !is_same_page(dcbase, get_next_pc(env, dc, dc->base.pc_next)) ||
49
+ dc->ex_value) {
50
dc->base.is_jmp = DISAS_TOO_MANY;
51
}
52
}
53
diff --git a/tests/tcg/s390x/noexec.c b/tests/tcg/s390x/noexec.c
54
new file mode 100644
55
index XXXXXXX..XXXXXXX
56
--- /dev/null
57
+++ b/tests/tcg/s390x/noexec.c
58
@@ -XXX,XX +XXX,XX @@
59
+#include "../multiarch/noexec.c.inc"
60
+
61
+static void *arch_mcontext_pc(const mcontext_t *ctx)
62
+{
63
+ return (void *)ctx->psw.addr;
64
+}
65
+
66
+static int arch_mcontext_arg(const mcontext_t *ctx)
67
+{
68
+ return ctx->gregs[2];
69
+}
70
+
71
+static void arch_flush(void *p, int len)
72
+{
73
+}
74
+
75
+extern char noexec_1[];
76
+extern char noexec_2[];
77
+extern char noexec_end[];
78
+
79
+asm("noexec_1:\n"
80
+ " lgfi %r2,1\n" /* %r2 is 0 on entry, set 1. */
81
+ "noexec_2:\n"
82
+ " lgfi %r2,2\n" /* %r2 is 0/1; set 2. */
83
+ " br %r14\n" /* return */
84
+ "noexec_end:");
85
+
86
+extern char exrl_1[];
87
+extern char exrl_2[];
88
+extern char exrl_end[];
89
+
90
+asm("exrl_1:\n"
91
+ " exrl %r0, exrl_2\n"
92
+ " br %r14\n"
93
+ "exrl_2:\n"
94
+ " lgfi %r2,2\n"
95
+ "exrl_end:");
96
+
97
+int main(void)
98
+{
99
+ struct noexec_test noexec_tests[] = {
100
+ {
101
+ .name = "fallthrough",
102
+ .test_code = noexec_1,
103
+ .test_len = noexec_end - noexec_1,
104
+ .page_ofs = noexec_1 - noexec_2,
105
+ .entry_ofs = noexec_1 - noexec_2,
106
+ .expected_si_ofs = 0,
107
+ .expected_pc_ofs = 0,
108
+ .expected_arg = 1,
109
+ },
110
+ {
111
+ .name = "jump",
112
+ .test_code = noexec_1,
113
+ .test_len = noexec_end - noexec_1,
114
+ .page_ofs = noexec_1 - noexec_2,
115
+ .entry_ofs = 0,
116
+ .expected_si_ofs = 0,
117
+ .expected_pc_ofs = 0,
118
+ .expected_arg = 0,
119
+ },
120
+ {
121
+ .name = "exrl",
122
+ .test_code = exrl_1,
123
+ .test_len = exrl_end - exrl_1,
124
+ .page_ofs = exrl_1 - exrl_2,
125
+ .entry_ofs = exrl_1 - exrl_2,
126
+ .expected_si_ofs = 0,
127
+ .expected_pc_ofs = exrl_1 - exrl_2,
128
+ .expected_arg = 0,
129
+ },
130
+ {
131
+ .name = "fallthrough [cross]",
132
+ .test_code = noexec_1,
133
+ .test_len = noexec_end - noexec_1,
134
+ .page_ofs = noexec_1 - noexec_2 - 2,
135
+ .entry_ofs = noexec_1 - noexec_2 - 2,
136
+ .expected_si_ofs = 0,
137
+ .expected_pc_ofs = -2,
138
+ .expected_arg = 1,
139
+ },
140
+ {
141
+ .name = "jump [cross]",
142
+ .test_code = noexec_1,
143
+ .test_len = noexec_end - noexec_1,
144
+ .page_ofs = noexec_1 - noexec_2 - 2,
145
+ .entry_ofs = -2,
146
+ .expected_si_ofs = 0,
147
+ .expected_pc_ofs = -2,
148
+ .expected_arg = 0,
149
+ },
150
+ {
151
+ .name = "exrl [cross]",
152
+ .test_code = exrl_1,
153
+ .test_len = exrl_end - exrl_1,
154
+ .page_ofs = exrl_1 - exrl_2 - 2,
155
+ .entry_ofs = exrl_1 - exrl_2 - 2,
156
+ .expected_si_ofs = 0,
157
+ .expected_pc_ofs = exrl_1 - exrl_2 - 2,
158
+ .expected_arg = 0,
159
+ },
160
+ };
161
+
162
+ return test_noexec(noexec_tests,
163
+ sizeof(noexec_tests) / sizeof(noexec_tests[0]));
164
+}
165
diff --git a/tests/tcg/multiarch/noexec.c.inc b/tests/tcg/multiarch/noexec.c.inc
166
new file mode 100644
167
index XXXXXXX..XXXXXXX
168
--- /dev/null
169
+++ b/tests/tcg/multiarch/noexec.c.inc
170
@@ -XXX,XX +XXX,XX @@
171
+/*
172
+ * Common code for arch-specific MMU_INST_FETCH fault testing.
173
+ */
174
+
175
+#define _GNU_SOURCE
176
+
177
+#include <assert.h>
178
+#include <signal.h>
179
+#include <stdio.h>
180
+#include <stdlib.h>
181
+#include <string.h>
182
+#include <errno.h>
183
+#include <unistd.h>
184
+#include <sys/mman.h>
185
+#include <sys/ucontext.h>
186
+
187
+/* Forward declarations. */
188
+
189
+static void *arch_mcontext_pc(const mcontext_t *ctx);
190
+static int arch_mcontext_arg(const mcontext_t *ctx);
191
+static void arch_flush(void *p, int len);
192
+
193
+/* Testing infrastructure. */
194
+
195
+struct noexec_test {
196
+ const char *name;
197
+ const char *test_code;
198
+ int test_len;
199
+ int page_ofs;
200
+ int entry_ofs;
201
+ int expected_si_ofs;
202
+ int expected_pc_ofs;
203
+ int expected_arg;
204
+};
205
+
206
+static void *page_base;
207
+static int page_size;
208
+static const struct noexec_test *current_noexec_test;
209
+
210
+static void handle_err(const char *syscall)
211
+{
212
+ printf("[ FAILED ] %s: %s\n", syscall, strerror(errno));
213
+ exit(EXIT_FAILURE);
214
+}
215
+
216
+static void handle_segv(int sig, siginfo_t *info, void *ucontext)
217
+{
218
+ const struct noexec_test *test = current_noexec_test;
219
+ const mcontext_t *mc = &((ucontext_t *)ucontext)->uc_mcontext;
220
+ void *expected_si;
221
+ void *expected_pc;
222
+ void *pc;
223
+ int arg;
224
+
225
+ if (test == NULL) {
226
+ printf("[ FAILED ] unexpected SEGV\n");
227
+ exit(EXIT_FAILURE);
228
+ }
229
+ current_noexec_test = NULL;
230
+
231
+ expected_si = page_base + test->expected_si_ofs;
232
+ if (info->si_addr != expected_si) {
233
+ printf("[ FAILED ] wrong si_addr (%p != %p)\n",
234
+ info->si_addr, expected_si);
235
+ exit(EXIT_FAILURE);
236
+ }
28
+ }
237
+
29
+
238
+ pc = arch_mcontext_pc(mc);
30
+ /* Per x86_restore_state_to_opc. */
239
+ expected_pc = page_base + test->expected_pc_ofs;
31
+ if (TARGET_TB_PCREL) {
240
+ if (pc != expected_pc) {
32
+ return (env->eip & TARGET_PAGE_MASK) | data[0];
241
+ printf("[ FAILED ] wrong pc (%p != %p)\n", pc, expected_pc);
33
+ } else {
242
+ exit(EXIT_FAILURE);
34
+ return data[0] - env->segs[R_CS].base;
243
+ }
244
+
245
+ arg = arch_mcontext_arg(mc);
246
+ if (arg != test->expected_arg) {
247
+ printf("[ FAILED ] wrong arg (%d != %d)\n", arg, test->expected_arg);
248
+ exit(EXIT_FAILURE);
249
+ }
250
+
251
+ if (mprotect(page_base, page_size,
252
+ PROT_READ | PROT_WRITE | PROT_EXEC) < 0) {
253
+ handle_err("mprotect");
254
+ }
35
+ }
255
+}
36
+}
256
+
37
+
257
+static void test_noexec_1(const struct noexec_test *test)
38
void cpu_report_tpr_access(CPUX86State *env, TPRAccess access)
258
+{
39
{
259
+ void *start = page_base + test->page_ofs;
40
X86CPU *cpu = env_archcpu(env);
260
+ void (*fn)(int arg) = page_base + test->entry_ofs;
41
@@ -XXX,XX +XXX,XX @@ void cpu_report_tpr_access(CPUX86State *env, TPRAccess access)
261
+
42
262
+ memcpy(start, test->test_code, test->test_len);
43
cpu_interrupt(cs, CPU_INTERRUPT_TPR);
263
+ arch_flush(start, test->test_len);
44
} else if (tcg_enabled()) {
264
+
45
- cpu_restore_state(cs, cs->mem_io_pc, false);
265
+ /* Trigger TB creation in order to test invalidation. */
46
+ target_ulong eip = get_memio_eip(env);
266
+ fn(0);
47
267
+
48
- apic_handle_tpr_access_report(cpu->apic_state, env->eip, access);
268
+ if (mprotect(page_base, page_size, PROT_NONE) < 0) {
49
+ apic_handle_tpr_access_report(cpu->apic_state, eip, access);
269
+ handle_err("mprotect");
50
}
270
+ }
51
}
271
+
52
#endif /* !CONFIG_USER_ONLY */
272
+ /* Trigger SEGV and check that handle_segv() ran. */
273
+ current_noexec_test = test;
274
+ fn(0);
275
+ assert(current_noexec_test == NULL);
276
+}
277
+
278
+static int test_noexec(struct noexec_test *tests, size_t n_tests)
279
+{
280
+ struct sigaction act;
281
+ size_t i;
282
+
283
+ memset(&act, 0, sizeof(act));
284
+ act.sa_sigaction = handle_segv;
285
+ act.sa_flags = SA_SIGINFO;
286
+ if (sigaction(SIGSEGV, &act, NULL) < 0) {
287
+ handle_err("sigaction");
288
+ }
289
+
290
+ page_size = getpagesize();
291
+ page_base = mmap(NULL, 2 * page_size,
292
+ PROT_READ | PROT_WRITE | PROT_EXEC,
293
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
294
+ if (page_base == MAP_FAILED) {
295
+ handle_err("mmap");
296
+ }
297
+ page_base += page_size;
298
+
299
+ for (i = 0; i < n_tests; i++) {
300
+ struct noexec_test *test = &tests[i];
301
+
302
+ printf("[ RUN ] %s\n", test->name);
303
+ test_noexec_1(test);
304
+ printf("[ OK ]\n");
305
+ }
306
+
307
+ printf("[ PASSED ]\n");
308
+ return EXIT_SUCCESS;
309
+}
310
diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target
311
index XXXXXXX..XXXXXXX 100644
312
--- a/tests/tcg/s390x/Makefile.target
313
+++ b/tests/tcg/s390x/Makefile.target
314
@@ -XXX,XX +XXX,XX @@ TESTS+=shift
315
TESTS+=trap
316
TESTS+=signals-s390x
317
TESTS+=branch-relative-long
318
+TESTS+=noexec
319
320
Z14_TESTS=vfminmax
321
vfminmax: LDFLAGS+=-lm
322
--
53
--
323
2.34.1
54
2.34.1
diff view generated by jsdifflib
1
There is no need to go through cc->tcg_ops when
1
We have called cpu_restore_state asserting will_exit.
2
we know what value that must have.
2
Do not go back on that promise. This affects icount.
3
3
4
Reviewed-by: Michael Rolnik <mrolnik@gmail.com>
4
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>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
6
---
8
target/avr/helper.c | 5 ++---
7
target/openrisc/sys_helper.c | 2 +-
9
1 file changed, 2 insertions(+), 3 deletions(-)
8
1 file changed, 1 insertion(+), 1 deletion(-)
10
9
11
diff --git a/target/avr/helper.c b/target/avr/helper.c
10
diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
12
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
13
--- a/target/avr/helper.c
12
--- a/target/openrisc/sys_helper.c
14
+++ b/target/avr/helper.c
13
+++ b/target/openrisc/sys_helper.c
15
@@ -XXX,XX +XXX,XX @@
14
@@ -XXX,XX +XXX,XX @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb)
16
bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
15
if (env->pc != rb) {
17
{
16
env->pc = rb;
18
bool ret = false;
17
env->dflag = 0;
19
- CPUClass *cc = CPU_GET_CLASS(cs);
18
- cpu_loop_exit(cs);
20
AVRCPU *cpu = AVR_CPU(cs);
19
}
21
CPUAVRState *env = &cpu->env;
20
+ cpu_loop_exit(cs);
22
21
break;
23
if (interrupt_request & CPU_INTERRUPT_RESET) {
22
24
if (cpu_interrupts_enabled(env)) {
23
case TO_SPR(0, 17): /* SR */
25
cs->exception_index = EXCP_RESET;
26
- cc->tcg_ops->do_interrupt(cs);
27
+ avr_cpu_do_interrupt(cs);
28
29
cs->interrupt_request &= ~CPU_INTERRUPT_RESET;
30
31
@@ -XXX,XX +XXX,XX @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
32
if (cpu_interrupts_enabled(env) && env->intsrc != 0) {
33
int index = ctz32(env->intsrc);
34
cs->exception_index = EXCP_INT(index);
35
- cc->tcg_ops->do_interrupt(cs);
36
+ avr_cpu_do_interrupt(cs);
37
38
env->intsrc &= env->intsrc - 1; /* clear the interrupt */
39
if (!env->intsrc) {
40
--
24
--
41
2.34.1
25
2.34.1
42
26
43
27
diff view generated by jsdifflib
Deleted patch
1
We're about to start validating PAGE_EXEC, which means that we've
2
got to mark page zero executable. We had been special casing this
3
entirely within translate.
4
1
5
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
6
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
linux-user/elfload.c | 34 +++++++++++++++++++++++++++++++---
10
1 file changed, 31 insertions(+), 3 deletions(-)
11
12
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/linux-user/elfload.c
15
+++ b/linux-user/elfload.c
16
@@ -XXX,XX +XXX,XX @@ static inline void init_thread(struct target_pt_regs *regs,
17
regs->gr[31] = infop->entry;
18
}
19
20
+#define LO_COMMPAGE 0
21
+
22
+static bool init_guest_commpage(void)
23
+{
24
+ void *want = g2h_untagged(LO_COMMPAGE);
25
+ void *addr = mmap(want, qemu_host_page_size, PROT_NONE,
26
+ MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
27
+
28
+ if (addr == MAP_FAILED) {
29
+ perror("Allocating guest commpage");
30
+ exit(EXIT_FAILURE);
31
+ }
32
+ if (addr != want) {
33
+ return false;
34
+ }
35
+
36
+ /*
37
+ * On Linux, page zero is normally marked execute only + gateway.
38
+ * Normal read or write is supposed to fail (thus PROT_NONE above),
39
+ * but specific offsets have kernel code mapped to raise permissions
40
+ * and implement syscalls. Here, simply mark the page executable.
41
+ * Special case the entry points during translation (see do_page_zero).
42
+ */
43
+ page_set_flags(LO_COMMPAGE, LO_COMMPAGE + TARGET_PAGE_SIZE,
44
+ PAGE_EXEC | PAGE_VALID);
45
+ return true;
46
+}
47
+
48
#endif /* TARGET_HPPA */
49
50
#ifdef TARGET_XTENSA
51
@@ -XXX,XX +XXX,XX @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
52
}
53
54
#if defined(HI_COMMPAGE)
55
-#define LO_COMMPAGE 0
56
+#define LO_COMMPAGE -1
57
#elif defined(LO_COMMPAGE)
58
#define HI_COMMPAGE 0
59
#else
60
#define HI_COMMPAGE 0
61
-#define LO_COMMPAGE 0
62
+#define LO_COMMPAGE -1
63
#define init_guest_commpage() true
64
#endif
65
66
@@ -XXX,XX +XXX,XX @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr,
67
} else {
68
offset = -(HI_COMMPAGE & -align);
69
}
70
- } else if (LO_COMMPAGE != 0) {
71
+ } else if (LO_COMMPAGE != -1) {
72
loaddr = MIN(loaddr, LO_COMMPAGE & -align);
73
}
74
75
--
76
2.34.1
diff view generated by jsdifflib
Deleted patch
1
We're about to start validating PAGE_EXEC, which means that we've
2
got to mark the vsyscall page executable. We had been special
3
casing this entirely within translate.
4
1
5
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
6
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
linux-user/elfload.c | 23 +++++++++++++++++++++++
10
1 file changed, 23 insertions(+)
11
12
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/linux-user/elfload.c
15
+++ b/linux-user/elfload.c
16
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *en
17
(*regs)[26] = tswapreg(env->segs[R_GS].selector & 0xffff);
18
}
19
20
+#if ULONG_MAX >= TARGET_VSYSCALL_PAGE
21
+#define INIT_GUEST_COMMPAGE
22
+static bool init_guest_commpage(void)
23
+{
24
+ /*
25
+ * The vsyscall page is at a high negative address aka kernel space,
26
+ * which means that we cannot actually allocate it with target_mmap.
27
+ * We still should be able to use page_set_flags, unless the user
28
+ * has specified -R reserved_va, which would trigger an assert().
29
+ */
30
+ if (reserved_va != 0 &&
31
+ TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE >= reserved_va) {
32
+ error_report("Cannot allocate vsyscall page");
33
+ exit(EXIT_FAILURE);
34
+ }
35
+ page_set_flags(TARGET_VSYSCALL_PAGE,
36
+ TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE,
37
+ PAGE_EXEC | PAGE_VALID);
38
+ return true;
39
+}
40
+#endif
41
#else
42
43
#define ELF_START_MMAP 0x80000000
44
@@ -XXX,XX +XXX,XX @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
45
#else
46
#define HI_COMMPAGE 0
47
#define LO_COMMPAGE -1
48
+#ifndef INIT_GUEST_COMMPAGE
49
#define init_guest_commpage() true
50
#endif
51
+#endif
52
53
static void pgb_fail_in_use(const char *image_name)
54
{
55
--
56
2.34.1
diff view generated by jsdifflib
Deleted patch
1
Map the stack executable if required by default or on demand.
2
1
3
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
4
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
include/elf.h | 1 +
8
linux-user/qemu.h | 1 +
9
linux-user/elfload.c | 19 ++++++++++++++++++-
10
3 files changed, 20 insertions(+), 1 deletion(-)
11
12
diff --git a/include/elf.h b/include/elf.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/include/elf.h
15
+++ b/include/elf.h
16
@@ -XXX,XX +XXX,XX @@ typedef int64_t Elf64_Sxword;
17
#define PT_LOPROC 0x70000000
18
#define PT_HIPROC 0x7fffffff
19
20
+#define PT_GNU_STACK (PT_LOOS + 0x474e551)
21
#define PT_GNU_PROPERTY (PT_LOOS + 0x474e553)
22
23
#define PT_MIPS_REGINFO 0x70000000
24
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/linux-user/qemu.h
27
+++ b/linux-user/qemu.h
28
@@ -XXX,XX +XXX,XX @@ struct image_info {
29
uint32_t elf_flags;
30
int personality;
31
abi_ulong alignment;
32
+ bool exec_stack;
33
34
/* Generic semihosting knows about these pointers. */
35
abi_ulong arg_strings; /* strings for argv */
36
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/linux-user/elfload.c
39
+++ b/linux-user/elfload.c
40
@@ -XXX,XX +XXX,XX @@ static bool init_guest_commpage(void)
41
#define ELF_ARCH EM_386
42
43
#define ELF_PLATFORM get_elf_platform()
44
+#define EXSTACK_DEFAULT true
45
46
static const char *get_elf_platform(void)
47
{
48
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *en
49
50
#define ELF_ARCH EM_ARM
51
#define ELF_CLASS ELFCLASS32
52
+#define EXSTACK_DEFAULT true
53
54
static inline void init_thread(struct target_pt_regs *regs,
55
struct image_info *infop)
56
@@ -XXX,XX +XXX,XX @@ static inline void init_thread(struct target_pt_regs *regs,
57
#else
58
59
#define ELF_CLASS ELFCLASS32
60
+#define EXSTACK_DEFAULT true
61
62
#endif
63
64
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *en
65
66
#define ELF_CLASS ELFCLASS64
67
#define ELF_ARCH EM_LOONGARCH
68
+#define EXSTACK_DEFAULT true
69
70
#define elf_check_arch(x) ((x) == EM_LOONGARCH)
71
72
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
73
#define ELF_CLASS ELFCLASS32
74
#endif
75
#define ELF_ARCH EM_MIPS
76
+#define EXSTACK_DEFAULT true
77
78
#ifdef TARGET_ABI_MIPSN32
79
#define elf_check_abi(x) ((x) & EF_MIPS_ABI2)
80
@@ -XXX,XX +XXX,XX @@ static inline void init_thread(struct target_pt_regs *regs,
81
#define bswaptls(ptr) bswap32s(ptr)
82
#endif
83
84
+#ifndef EXSTACK_DEFAULT
85
+#define EXSTACK_DEFAULT false
86
+#endif
87
+
88
#include "elf.h"
89
90
/* We must delay the following stanzas until after "elf.h". */
91
@@ -XXX,XX +XXX,XX @@ static abi_ulong setup_arg_pages(struct linux_binprm *bprm,
92
struct image_info *info)
93
{
94
abi_ulong size, error, guard;
95
+ int prot;
96
97
size = guest_stack_size;
98
if (size < STACK_LOWER_LIMIT) {
99
@@ -XXX,XX +XXX,XX @@ static abi_ulong setup_arg_pages(struct linux_binprm *bprm,
100
guard = qemu_real_host_page_size();
101
}
102
103
- error = target_mmap(0, size + guard, PROT_READ | PROT_WRITE,
104
+ prot = PROT_READ | PROT_WRITE;
105
+ if (info->exec_stack) {
106
+ prot |= PROT_EXEC;
107
+ }
108
+ error = target_mmap(0, size + guard, prot,
109
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
110
if (error == -1) {
111
perror("mmap stack");
112
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
113
*/
114
loaddr = -1, hiaddr = 0;
115
info->alignment = 0;
116
+ info->exec_stack = EXSTACK_DEFAULT;
117
for (i = 0; i < ehdr->e_phnum; ++i) {
118
struct elf_phdr *eppnt = phdr + i;
119
if (eppnt->p_type == PT_LOAD) {
120
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
121
if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) {
122
goto exit_errmsg;
123
}
124
+ } else if (eppnt->p_type == PT_GNU_STACK) {
125
+ info->exec_stack = eppnt->p_flags & PF_X;
126
}
127
}
128
129
--
130
2.34.1
diff view generated by jsdifflib
Deleted patch
1
From: Ilya Leoshkevich <iii@linux.ibm.com>
2
1
3
Currently it's possible to execute pages that do not have PAGE_EXEC
4
if there is an existing translation block. Fix by invalidating TBs
5
that touch the affected pages.
6
7
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
8
Message-Id: <20220817150506.592862-2-iii@linux.ibm.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
---
11
linux-user/mmap.c | 6 ++++--
12
1 file changed, 4 insertions(+), 2 deletions(-)
13
14
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/mmap.c
17
+++ b/linux-user/mmap.c
18
@@ -XXX,XX +XXX,XX @@ int target_mprotect(abi_ulong start, abi_ulong len, int target_prot)
19
goto error;
20
}
21
}
22
+
23
page_set_flags(start, start + len, page_flags);
24
- mmap_unlock();
25
- return 0;
26
+ tb_invalidate_phys_range(start, start + len);
27
+ ret = 0;
28
+
29
error:
30
mmap_unlock();
31
return ret;
32
--
33
2.34.1
diff view generated by jsdifflib
Deleted patch
1
We're about to start validating PAGE_EXEC, which means
2
that we've got to put this code into a section that is
3
both writable and executable.
4
1
5
Note that this test did not run on hardware beforehand either.
6
7
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
8
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
---
11
tests/tcg/i386/test-i386.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
14
diff --git a/tests/tcg/i386/test-i386.c b/tests/tcg/i386/test-i386.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/tcg/i386/test-i386.c
17
+++ b/tests/tcg/i386/test-i386.c
18
@@ -XXX,XX +XXX,XX @@ uint8_t code[] = {
19
0xc3, /* ret */
20
};
21
22
-asm(".section \".data\"\n"
23
+asm(".section \".data_x\",\"awx\"\n"
24
"smc_code2:\n"
25
"movl 4(%esp), %eax\n"
26
"movl %eax, smc_patch_addr2 + 1\n"
27
--
28
2.34.1
diff view generated by jsdifflib
Deleted patch
1
From: Ilya Leoshkevich <iii@linux.ibm.com>
2
1
3
Introduce a function that checks whether a given address is on the same
4
page as where disassembly started. Having it improves readability of
5
the following patches.
6
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
9
Message-Id: <20220811095534.241224-3-iii@linux.ibm.com>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
[rth: Make the DisasContextBase parameter const.]
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
---
14
include/exec/translator.h | 10 ++++++++++
15
1 file changed, 10 insertions(+)
16
17
diff --git a/include/exec/translator.h b/include/exec/translator.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/exec/translator.h
20
+++ b/include/exec/translator.h
21
@@ -XXX,XX +XXX,XX @@ FOR_EACH_TRANSLATOR_LD(GEN_TRANSLATOR_LD)
22
23
#undef GEN_TRANSLATOR_LD
24
25
+/*
26
+ * Return whether addr is on the same page as where disassembly started.
27
+ * Translators can use this to enforce the rule that only single-insn
28
+ * translation blocks are allowed to cross page boundaries.
29
+ */
30
+static inline bool is_same_page(const DisasContextBase *db, target_ulong addr)
31
+{
32
+ return ((addr ^ db->pc_first) & TARGET_PAGE_MASK) == 0;
33
+}
34
+
35
#endif /* EXEC__TRANSLATOR_H */
36
--
37
2.34.1
diff view generated by jsdifflib
1
The function is not used outside of cpu-exec.c. Move it and
1
Since we do not plan to exit, use cpu_unwind_state_data
2
its subroutines up in the file, before the first use.
2
and extract exactly the data requested.
3
3
4
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
4
This is a bug fix, in that we no longer clobber dflag.
5
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
5
6
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
6
Consider:
7
8
l.j L2 // branch
9
l.mfspr r1, ppc // delay
10
11
L1: boom
12
L2: l.lwa r3, (r4)
13
14
Here, dflag would be set by cpu_restore_state (because that is the current
15
state of the cpu), but but not cleared by tb_stop on exiting the TB
16
(because DisasContext has recorded the current value as zero).
17
18
The next TB begins at L2 with dflag incorrectly set. If the load has a
19
tlb miss, then the exception will be delivered as per a delay slot:
20
with DSX set in the status register and PC decremented (delay slots
21
restart by re-executing the branch). This will cause the return from
22
interrupt to go to L1, and boom!
23
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
24
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
25
---
9
include/exec/exec-all.h | 3 -
26
target/openrisc/sys_helper.c | 11 +++++++++--
10
accel/tcg/cpu-exec.c | 122 ++++++++++++++++++++--------------------
27
1 file changed, 9 insertions(+), 2 deletions(-)
11
2 files changed, 61 insertions(+), 64 deletions(-)
12
28
13
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
29
diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
14
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
15
--- a/include/exec/exec-all.h
31
--- a/target/openrisc/sys_helper.c
16
+++ b/include/exec/exec-all.h
32
+++ b/target/openrisc/sys_helper.c
17
@@ -XXX,XX +XXX,XX @@ void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs);
33
@@ -XXX,XX +XXX,XX @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd,
18
#endif
34
target_ulong spr)
19
void tb_flush(CPUState *cpu);
35
{
20
void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr);
36
#ifndef CONFIG_USER_ONLY
21
-TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
37
+ uint64_t data[TARGET_INSN_START_WORDS];
22
- target_ulong cs_base, uint32_t flags,
38
MachineState *ms = MACHINE(qdev_get_machine());
23
- uint32_t cflags);
39
OpenRISCCPU *cpu = env_archcpu(env);
24
void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr);
40
CPUState *cs = env_cpu(env);
25
41
@@ -XXX,XX +XXX,XX @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd,
26
/* GETPC is the true target of the return instruction that we'll execute. */
42
return env->evbar;
27
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
43
28
index XXXXXXX..XXXXXXX 100644
44
case TO_SPR(0, 16): /* NPC (equals PC) */
29
--- a/accel/tcg/cpu-exec.c
45
- cpu_restore_state(cs, GETPC(), false);
30
+++ b/accel/tcg/cpu-exec.c
46
+ if (cpu_unwind_state_data(cs, GETPC(), data)) {
31
@@ -XXX,XX +XXX,XX @@ uint32_t curr_cflags(CPUState *cpu)
47
+ return data[0];
32
return cflags;
48
+ }
33
}
49
return env->pc;
34
50
35
+struct tb_desc {
51
case TO_SPR(0, 17): /* SR */
36
+ target_ulong pc;
52
return cpu_get_sr(env);
37
+ target_ulong cs_base;
53
38
+ CPUArchState *env;
54
case TO_SPR(0, 18): /* PPC */
39
+ tb_page_addr_t phys_page1;
55
- cpu_restore_state(cs, GETPC(), false);
40
+ uint32_t flags;
56
+ if (cpu_unwind_state_data(cs, GETPC(), data)) {
41
+ uint32_t cflags;
57
+ if (data[1] & 2) {
42
+ uint32_t trace_vcpu_dstate;
58
+ return data[0] - 4;
43
+};
44
+
45
+static bool tb_lookup_cmp(const void *p, const void *d)
46
+{
47
+ const TranslationBlock *tb = p;
48
+ const struct tb_desc *desc = d;
49
+
50
+ if (tb->pc == desc->pc &&
51
+ tb->page_addr[0] == desc->phys_page1 &&
52
+ tb->cs_base == desc->cs_base &&
53
+ tb->flags == desc->flags &&
54
+ tb->trace_vcpu_dstate == desc->trace_vcpu_dstate &&
55
+ tb_cflags(tb) == desc->cflags) {
56
+ /* check next page if needed */
57
+ if (tb->page_addr[1] == -1) {
58
+ return true;
59
+ } else {
60
+ tb_page_addr_t phys_page2;
61
+ target_ulong virt_page2;
62
+
63
+ virt_page2 = (desc->pc & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
64
+ phys_page2 = get_page_addr_code(desc->env, virt_page2);
65
+ if (tb->page_addr[1] == phys_page2) {
66
+ return true;
67
+ }
59
+ }
68
+ }
60
+ }
69
+ }
61
return env->ppc;
70
+ return false;
62
71
+}
63
case TO_SPR(0, 32): /* EPCR */
72
+
73
+static TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
74
+ target_ulong cs_base, uint32_t flags,
75
+ uint32_t cflags)
76
+{
77
+ tb_page_addr_t phys_pc;
78
+ struct tb_desc desc;
79
+ uint32_t h;
80
+
81
+ desc.env = cpu->env_ptr;
82
+ desc.cs_base = cs_base;
83
+ desc.flags = flags;
84
+ desc.cflags = cflags;
85
+ desc.trace_vcpu_dstate = *cpu->trace_dstate;
86
+ desc.pc = pc;
87
+ phys_pc = get_page_addr_code(desc.env, pc);
88
+ if (phys_pc == -1) {
89
+ return NULL;
90
+ }
91
+ desc.phys_page1 = phys_pc & TARGET_PAGE_MASK;
92
+ h = tb_hash_func(phys_pc, pc, flags, cflags, *cpu->trace_dstate);
93
+ return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp);
94
+}
95
+
96
/* Might cause an exception, so have a longjmp destination ready */
97
static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
98
target_ulong cs_base,
99
@@ -XXX,XX +XXX,XX @@ void cpu_exec_step_atomic(CPUState *cpu)
100
end_exclusive();
101
}
102
103
-struct tb_desc {
104
- target_ulong pc;
105
- target_ulong cs_base;
106
- CPUArchState *env;
107
- tb_page_addr_t phys_page1;
108
- uint32_t flags;
109
- uint32_t cflags;
110
- uint32_t trace_vcpu_dstate;
111
-};
112
-
113
-static bool tb_lookup_cmp(const void *p, const void *d)
114
-{
115
- const TranslationBlock *tb = p;
116
- const struct tb_desc *desc = d;
117
-
118
- if (tb->pc == desc->pc &&
119
- tb->page_addr[0] == desc->phys_page1 &&
120
- tb->cs_base == desc->cs_base &&
121
- tb->flags == desc->flags &&
122
- tb->trace_vcpu_dstate == desc->trace_vcpu_dstate &&
123
- tb_cflags(tb) == desc->cflags) {
124
- /* check next page if needed */
125
- if (tb->page_addr[1] == -1) {
126
- return true;
127
- } else {
128
- tb_page_addr_t phys_page2;
129
- target_ulong virt_page2;
130
-
131
- virt_page2 = (desc->pc & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
132
- phys_page2 = get_page_addr_code(desc->env, virt_page2);
133
- if (tb->page_addr[1] == phys_page2) {
134
- return true;
135
- }
136
- }
137
- }
138
- return false;
139
-}
140
-
141
-TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
142
- target_ulong cs_base, uint32_t flags,
143
- uint32_t cflags)
144
-{
145
- tb_page_addr_t phys_pc;
146
- struct tb_desc desc;
147
- uint32_t h;
148
-
149
- desc.env = cpu->env_ptr;
150
- desc.cs_base = cs_base;
151
- desc.flags = flags;
152
- desc.cflags = cflags;
153
- desc.trace_vcpu_dstate = *cpu->trace_dstate;
154
- desc.pc = pc;
155
- phys_pc = get_page_addr_code(desc.env, pc);
156
- if (phys_pc == -1) {
157
- return NULL;
158
- }
159
- desc.phys_page1 = phys_pc & TARGET_PAGE_MASK;
160
- h = tb_hash_func(phys_pc, pc, flags, cflags, *cpu->trace_dstate);
161
- return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp);
162
-}
163
-
164
void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr)
165
{
166
if (TCG_TARGET_HAS_direct_jump) {
167
--
64
--
168
2.34.1
65
2.34.1
diff view generated by jsdifflib
1
The current implementation is a no-op, simply returning addr.
1
The value passed is always true, and if the target's
2
This is incorrect, because we ought to be checking the page
2
synchronize_from_tb hook is non-trivial, not exiting
3
permissions for execution.
3
may be erroneous.
4
4
5
Make get_page_addr_code inline for both implementations.
5
Reviewed-by: Claudio Fontana <cfontana@suse.de>
6
7
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
8
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
9
Acked-by: Alistair Francis <alistair.francis@wdc.com>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
---
7
---
12
include/exec/exec-all.h | 85 ++++++++++++++---------------------------
8
include/exec/exec-all.h | 5 +----
13
accel/tcg/cputlb.c | 5 ---
9
accel/tcg/cpu-exec-common.c | 2 +-
14
accel/tcg/user-exec.c | 14 +++++++
10
accel/tcg/translate-all.c | 12 ++----------
15
3 files changed, 42 insertions(+), 62 deletions(-)
11
target/alpha/helper.c | 2 +-
12
target/alpha/mem_helper.c | 2 +-
13
target/arm/op_helper.c | 2 +-
14
target/arm/tlb_helper.c | 8 ++++----
15
target/cris/helper.c | 2 +-
16
target/i386/tcg/sysemu/svm_helper.c | 2 +-
17
target/m68k/op_helper.c | 4 ++--
18
target/microblaze/helper.c | 2 +-
19
target/nios2/op_helper.c | 2 +-
20
target/openrisc/sys_helper.c | 4 ++--
21
target/ppc/excp_helper.c | 2 +-
22
target/s390x/tcg/excp_helper.c | 2 +-
23
target/tricore/op_helper.c | 2 +-
24
target/xtensa/helper.c | 6 +++---
25
17 files changed, 25 insertions(+), 36 deletions(-)
16
26
17
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
27
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
18
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
19
--- a/include/exec/exec-all.h
29
--- a/include/exec/exec-all.h
20
+++ b/include/exec/exec-all.h
30
+++ b/include/exec/exec-all.h
21
@@ -XXX,XX +XXX,XX @@ struct MemoryRegionSection *iotlb_to_section(CPUState *cpu,
31
@@ -XXX,XX +XXX,XX @@ bool cpu_unwind_state_data(CPUState *cpu, uintptr_t host_pc, uint64_t *data);
22
hwaddr index, MemTxAttrs attrs);
32
* cpu_restore_state:
33
* @cpu: the cpu context
34
* @host_pc: the host pc within the translation
35
- * @will_exit: true if the TB executed will be interrupted after some
36
- cpu adjustments. Required for maintaining the correct
37
- icount valus
38
* @return: true if state was restored, false otherwise
39
*
40
* Attempt to restore the state for a fault occurring in translated
41
* code. If @host_pc is not in translated code no state is
42
* restored and the function returns false.
43
*/
44
-bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit);
45
+bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc);
46
47
G_NORETURN void cpu_loop_exit_noexc(CPUState *cpu);
48
G_NORETURN void cpu_loop_exit(CPUState *cpu);
49
diff --git a/accel/tcg/cpu-exec-common.c b/accel/tcg/cpu-exec-common.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/accel/tcg/cpu-exec-common.c
52
+++ b/accel/tcg/cpu-exec-common.c
53
@@ -XXX,XX +XXX,XX @@ void cpu_loop_exit(CPUState *cpu)
54
void cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc)
55
{
56
if (pc) {
57
- cpu_restore_state(cpu, pc, true);
58
+ cpu_restore_state(cpu, pc);
59
}
60
cpu_loop_exit(cpu);
61
}
62
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/accel/tcg/translate-all.c
65
+++ b/accel/tcg/translate-all.c
66
@@ -XXX,XX +XXX,XX @@ void cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
23
#endif
67
#endif
24
68
}
25
-#if defined(CONFIG_USER_ONLY)
69
26
-void mmap_lock(void);
70
-bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit)
27
-void mmap_unlock(void);
71
+bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc)
28
-bool have_mmap_lock(void);
72
{
73
- /*
74
- * The pc update associated with restore without exit will
75
- * break the relative pc adjustments performed by TARGET_TB_PCREL.
76
- */
77
- if (TARGET_TB_PCREL) {
78
- assert(will_exit);
79
- }
29
-
80
-
30
/**
81
/*
31
- * get_page_addr_code() - user-mode version
82
* The host_pc has to be in the rx region of the code buffer.
32
+ * get_page_addr_code_hostp()
83
* If it is not we will not be able to resolve it here.
33
* @env: CPUArchState
84
@@ -XXX,XX +XXX,XX @@ bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit)
34
* @addr: guest virtual address of guest code
85
if (in_code_gen_buffer((const void *)(host_pc - tcg_splitwx_diff))) {
35
*
86
TranslationBlock *tb = tcg_tb_lookup(host_pc);
36
- * Returns @addr.
87
if (tb) {
37
+ * See get_page_addr_code() (full-system version) for documentation on the
88
- cpu_restore_state_from_tb(cpu, tb, host_pc, will_exit);
38
+ * return value.
89
+ cpu_restore_state_from_tb(cpu, tb, host_pc, true);
39
+ *
90
return true;
40
+ * Sets *@hostp (when @hostp is non-NULL) as follows.
91
}
41
+ * If the return value is -1, sets *@hostp to NULL. Otherwise, sets *@hostp
92
}
42
+ * to the host address where @addr's content is kept.
93
diff --git a/target/alpha/helper.c b/target/alpha/helper.c
43
+ *
94
index XXXXXXX..XXXXXXX 100644
44
+ * Note: this function can trigger an exception.
95
--- a/target/alpha/helper.c
45
+ */
96
+++ b/target/alpha/helper.c
46
+tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
97
@@ -XXX,XX +XXX,XX @@ G_NORETURN void dynamic_excp(CPUAlphaState *env, uintptr_t retaddr,
47
+ void **hostp);
98
cs->exception_index = excp;
48
+
99
env->error_code = error;
49
+/**
100
if (retaddr) {
50
+ * get_page_addr_code()
101
- cpu_restore_state(cs, retaddr, true);
51
+ * @env: CPUArchState
102
+ cpu_restore_state(cs, retaddr);
52
+ * @addr: guest virtual address of guest code
103
/* Floating-point exceptions (our only users) point to the next PC. */
53
+ *
104
env->pc += 4;
54
+ * If we cannot translate and execute from the entire RAM page, or if
105
}
55
+ * the region is not backed by RAM, returns -1. Otherwise, returns the
106
diff --git a/target/alpha/mem_helper.c b/target/alpha/mem_helper.c
56
+ * ram_addr_t corresponding to the guest code at @addr.
107
index XXXXXXX..XXXXXXX 100644
57
+ *
108
--- a/target/alpha/mem_helper.c
58
+ * Note: this function can trigger an exception.
109
+++ b/target/alpha/mem_helper.c
59
*/
110
@@ -XXX,XX +XXX,XX @@ static void do_unaligned_access(CPUAlphaState *env, vaddr addr, uintptr_t retadd
60
static inline tb_page_addr_t get_page_addr_code(CPUArchState *env,
111
uint64_t pc;
61
target_ulong addr)
112
uint32_t insn;
62
{
113
63
- return addr;
114
- cpu_restore_state(env_cpu(env), retaddr, true);
64
+ return get_page_addr_code_hostp(env, addr, NULL);
115
+ cpu_restore_state(env_cpu(env), retaddr);
65
}
116
66
117
pc = env->pc;
67
-/**
118
insn = cpu_ldl_code(env, pc);
68
- * get_page_addr_code_hostp() - user-mode version
119
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
69
- * @env: CPUArchState
120
index XXXXXXX..XXXXXXX 100644
70
- * @addr: guest virtual address of guest code
121
--- a/target/arm/op_helper.c
71
- *
122
+++ b/target/arm/op_helper.c
72
- * Returns @addr.
123
@@ -XXX,XX +XXX,XX @@ void raise_exception_ra(CPUARMState *env, uint32_t excp, uint32_t syndrome,
73
- *
124
* we must restore CPU state here before setting the syndrome
74
- * If @hostp is non-NULL, sets *@hostp to the host address where @addr's content
125
* the caller passed us, and cannot use cpu_loop_exit_restore().
75
- * is kept.
126
*/
76
- */
127
- cpu_restore_state(cs, ra, true);
77
-static inline tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env,
128
+ cpu_restore_state(cs, ra);
78
- target_ulong addr,
129
raise_exception(env, excp, syndrome, target_el);
79
- void **hostp)
130
}
80
-{
131
81
- if (hostp) {
132
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
82
- *hostp = g2h_untagged(addr);
133
index XXXXXXX..XXXXXXX 100644
83
- }
134
--- a/target/arm/tlb_helper.c
84
- return addr;
135
+++ b/target/arm/tlb_helper.c
85
-}
136
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
86
+#if defined(CONFIG_USER_ONLY)
137
ARMMMUFaultInfo fi = {};
87
+void mmap_lock(void);
138
88
+void mmap_unlock(void);
139
/* now we have a real cpu fault */
89
+bool have_mmap_lock(void);
140
- cpu_restore_state(cs, retaddr, true);
90
141
+ cpu_restore_state(cs, retaddr);
91
/**
142
92
* adjust_signal_pc:
143
fi.type = ARMFault_Alignment;
93
@@ -XXX,XX +XXX,XX @@ G_NORETURN void cpu_loop_exit_sigbus(CPUState *cpu, target_ulong addr,
144
arm_deliver_fault(cpu, vaddr, access_type, mmu_idx, &fi);
94
static inline void mmap_lock(void) {}
145
@@ -XXX,XX +XXX,XX @@ void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
95
static inline void mmap_unlock(void) {}
146
ARMMMUFaultInfo fi = {};
96
147
97
-/**
148
/* now we have a real cpu fault */
98
- * get_page_addr_code() - full-system version
149
- cpu_restore_state(cs, retaddr, true);
99
- * @env: CPUArchState
150
+ cpu_restore_state(cs, retaddr);
100
- * @addr: guest virtual address of guest code
151
101
- *
152
fi.ea = arm_extabort_type(response);
102
- * If we cannot translate and execute from the entire RAM page, or if
153
fi.type = ARMFault_SyncExternal;
103
- * the region is not backed by RAM, returns -1. Otherwise, returns the
154
@@ -XXX,XX +XXX,XX @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
104
- * ram_addr_t corresponding to the guest code at @addr.
155
return false;
105
- *
156
} else {
106
- * Note: this function can trigger an exception.
157
/* now we have a real cpu fault */
107
- */
158
- cpu_restore_state(cs, retaddr, true);
108
-tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr);
159
+ cpu_restore_state(cs, retaddr);
109
-
160
arm_deliver_fault(cpu, address, access_type, mmu_idx, fi);
110
-/**
161
}
111
- * get_page_addr_code_hostp() - full-system version
162
}
112
- * @env: CPUArchState
163
@@ -XXX,XX +XXX,XX @@ void arm_cpu_record_sigsegv(CPUState *cs, vaddr addr,
113
- * @addr: guest virtual address of guest code
164
* We report both ESR and FAR to signal handlers.
114
- *
165
* For now, it's easiest to deliver the fault normally.
115
- * See get_page_addr_code() (full-system version) for documentation on the
166
*/
116
- * return value.
167
- cpu_restore_state(cs, ra, true);
117
- *
168
+ cpu_restore_state(cs, ra);
118
- * Sets *@hostp (when @hostp is non-NULL) as follows.
169
arm_deliver_fault(cpu, addr, access_type, MMU_USER_IDX, &fi);
119
- * If the return value is -1, sets *@hostp to NULL. Otherwise, sets *@hostp
170
}
120
- * to the host address where @addr's content is kept.
171
121
- *
172
diff --git a/target/cris/helper.c b/target/cris/helper.c
122
- * Note: this function can trigger an exception.
173
index XXXXXXX..XXXXXXX 100644
123
- */
174
--- a/target/cris/helper.c
124
-tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
175
+++ b/target/cris/helper.c
125
- void **hostp);
176
@@ -XXX,XX +XXX,XX @@ bool cris_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
126
-
177
cs->exception_index = EXCP_BUSFAULT;
127
void tlb_reset_dirty(CPUState *cpu, ram_addr_t start1, ram_addr_t length);
178
env->fault_vector = res.bf_vec;
128
void tlb_set_dirty(CPUState *cpu, target_ulong vaddr);
179
if (retaddr) {
129
180
- if (cpu_restore_state(cs, retaddr, true)) {
130
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
181
+ if (cpu_restore_state(cs, retaddr)) {
131
index XXXXXXX..XXXXXXX 100644
182
/* Evaluate flags after retranslation. */
132
--- a/accel/tcg/cputlb.c
183
helper_top_evaluate_flags(env);
133
+++ b/accel/tcg/cputlb.c
184
}
134
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
185
diff --git a/target/i386/tcg/sysemu/svm_helper.c b/target/i386/tcg/sysemu/svm_helper.c
135
return qemu_ram_addr_from_host_nofail(p);
186
index XXXXXXX..XXXXXXX 100644
136
}
187
--- a/target/i386/tcg/sysemu/svm_helper.c
137
188
+++ b/target/i386/tcg/sysemu/svm_helper.c
138
-tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
189
@@ -XXX,XX +XXX,XX @@ void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1,
139
-{
190
{
140
- return get_page_addr_code_hostp(env, addr, NULL);
191
CPUState *cs = env_cpu(env);
141
-}
192
142
-
193
- cpu_restore_state(cs, retaddr, true);
143
static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size,
194
+ cpu_restore_state(cs, retaddr);
144
CPUIOTLBEntry *iotlbentry, uintptr_t retaddr)
195
145
{
196
qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016"
146
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
197
PRIx64 ", " TARGET_FMT_lx ")!\n",
147
index XXXXXXX..XXXXXXX 100644
198
diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c
148
--- a/accel/tcg/user-exec.c
199
index XXXXXXX..XXXXXXX 100644
149
+++ b/accel/tcg/user-exec.c
200
--- a/target/m68k/op_helper.c
150
@@ -XXX,XX +XXX,XX @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
201
+++ b/target/m68k/op_helper.c
151
return size ? g2h(env_cpu(env), addr) : NULL;
202
@@ -XXX,XX +XXX,XX @@ void m68k_cpu_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr,
152
}
203
M68kCPU *cpu = M68K_CPU(cs);
153
204
CPUM68KState *env = &cpu->env;
154
+tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
205
155
+ void **hostp)
206
- cpu_restore_state(cs, retaddr, true);
156
+{
207
+ cpu_restore_state(cs, retaddr);
157
+ int flags;
208
158
+
209
if (m68k_feature(env, M68K_FEATURE_M68040)) {
159
+ flags = probe_access_internal(env, addr, 1, MMU_INST_FETCH, false, 0);
210
env->mmu.mmusr = 0;
160
+ g_assert(flags == 0);
211
@@ -XXX,XX +XXX,XX @@ raise_exception_format2(CPUM68KState *env, int tt, int ilen, uintptr_t raddr)
161
+
212
cs->exception_index = tt;
162
+ if (hostp) {
213
163
+ *hostp = g2h_untagged(addr);
214
/* Recover PC and CC_OP for the beginning of the insn. */
164
+ }
215
- cpu_restore_state(cs, raddr, true);
165
+ return addr;
216
+ cpu_restore_state(cs, raddr);
166
+}
217
167
+
218
/* Flags are current in env->cc_*, or are undefined. */
168
/* The softmmu versions of these helpers are in cputlb.c. */
219
env->cc_op = CC_OP_FLAGS;
169
220
diff --git a/target/microblaze/helper.c b/target/microblaze/helper.c
170
/*
221
index XXXXXXX..XXXXXXX 100644
222
--- a/target/microblaze/helper.c
223
+++ b/target/microblaze/helper.c
224
@@ -XXX,XX +XXX,XX @@ void mb_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
225
uint32_t esr, iflags;
226
227
/* Recover the pc and iflags from the corresponding insn_start. */
228
- cpu_restore_state(cs, retaddr, true);
229
+ cpu_restore_state(cs, retaddr);
230
iflags = cpu->env.iflags;
231
232
qemu_log_mask(CPU_LOG_INT,
233
diff --git a/target/nios2/op_helper.c b/target/nios2/op_helper.c
234
index XXXXXXX..XXXXXXX 100644
235
--- a/target/nios2/op_helper.c
236
+++ b/target/nios2/op_helper.c
237
@@ -XXX,XX +XXX,XX @@ void nios2_cpu_loop_exit_advance(CPUNios2State *env, uintptr_t retaddr)
238
* Do this here, rather than in restore_state_to_opc(),
239
* lest we affect QEMU internal exceptions, like EXCP_DEBUG.
240
*/
241
- cpu_restore_state(cs, retaddr, true);
242
+ cpu_restore_state(cs, retaddr);
243
env->pc += 4;
244
cpu_loop_exit(cs);
245
}
246
diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
247
index XXXXXXX..XXXXXXX 100644
248
--- a/target/openrisc/sys_helper.c
249
+++ b/target/openrisc/sys_helper.c
250
@@ -XXX,XX +XXX,XX @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb)
251
break;
252
253
case TO_SPR(0, 16): /* NPC */
254
- cpu_restore_state(cs, GETPC(), true);
255
+ cpu_restore_state(cs, GETPC());
256
/* ??? Mirror or1ksim in not trashing delayed branch state
257
when "jumping" to the current instruction. */
258
if (env->pc != rb) {
259
@@ -XXX,XX +XXX,XX @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb)
260
case TO_SPR(8, 0): /* PMR */
261
env->pmr = rb;
262
if (env->pmr & PMR_DME || env->pmr & PMR_SME) {
263
- cpu_restore_state(cs, GETPC(), true);
264
+ cpu_restore_state(cs, GETPC());
265
env->pc += 4;
266
cs->halted = 1;
267
raise_exception(cpu, EXCP_HALTED);
268
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
269
index XXXXXXX..XXXXXXX 100644
270
--- a/target/ppc/excp_helper.c
271
+++ b/target/ppc/excp_helper.c
272
@@ -XXX,XX +XXX,XX @@ void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
273
uint32_t insn;
274
275
/* Restore state and reload the insn we executed, for filling in DSISR. */
276
- cpu_restore_state(cs, retaddr, true);
277
+ cpu_restore_state(cs, retaddr);
278
insn = cpu_ldl_code(env, env->nip);
279
280
switch (env->mmu_model) {
281
diff --git a/target/s390x/tcg/excp_helper.c b/target/s390x/tcg/excp_helper.c
282
index XXXXXXX..XXXXXXX 100644
283
--- a/target/s390x/tcg/excp_helper.c
284
+++ b/target/s390x/tcg/excp_helper.c
285
@@ -XXX,XX +XXX,XX @@ G_NORETURN void tcg_s390_program_interrupt(CPUS390XState *env,
286
{
287
CPUState *cs = env_cpu(env);
288
289
- cpu_restore_state(cs, ra, true);
290
+ cpu_restore_state(cs, ra);
291
qemu_log_mask(CPU_LOG_INT, "program interrupt at %#" PRIx64 "\n",
292
env->psw.addr);
293
trigger_pgm_exception(env, code);
294
diff --git a/target/tricore/op_helper.c b/target/tricore/op_helper.c
295
index XXXXXXX..XXXXXXX 100644
296
--- a/target/tricore/op_helper.c
297
+++ b/target/tricore/op_helper.c
298
@@ -XXX,XX +XXX,XX @@ void raise_exception_sync_internal(CPUTriCoreState *env, uint32_t class, int tin
299
{
300
CPUState *cs = env_cpu(env);
301
/* in case we come from a helper-call we need to restore the PC */
302
- cpu_restore_state(cs, pc, true);
303
+ cpu_restore_state(cs, pc);
304
305
/* Tin is loaded into d[15] */
306
env->gpr_d[15] = tin;
307
diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c
308
index XXXXXXX..XXXXXXX 100644
309
--- a/target/xtensa/helper.c
310
+++ b/target/xtensa/helper.c
311
@@ -XXX,XX +XXX,XX @@ void xtensa_cpu_do_unaligned_access(CPUState *cs,
312
313
assert(xtensa_option_enabled(env->config,
314
XTENSA_OPTION_UNALIGNED_EXCEPTION));
315
- cpu_restore_state(CPU(cpu), retaddr, true);
316
+ cpu_restore_state(CPU(cpu), retaddr);
317
HELPER(exception_cause_vaddr)(env,
318
env->pc, LOAD_STORE_ALIGNMENT_CAUSE,
319
addr);
320
@@ -XXX,XX +XXX,XX @@ bool xtensa_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
321
} else if (probe) {
322
return false;
323
} else {
324
- cpu_restore_state(cs, retaddr, true);
325
+ cpu_restore_state(cs, retaddr);
326
HELPER(exception_cause_vaddr)(env, env->pc, ret, address);
327
}
328
}
329
@@ -XXX,XX +XXX,XX @@ void xtensa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr,
330
XtensaCPU *cpu = XTENSA_CPU(cs);
331
CPUXtensaState *env = &cpu->env;
332
333
- cpu_restore_state(cs, retaddr, true);
334
+ cpu_restore_state(cs, retaddr);
335
HELPER(exception_cause_vaddr)(env, env->pc,
336
access_type == MMU_INST_FETCH ?
337
INSTR_PIF_ADDR_ERROR_CAUSE :
171
--
338
--
172
2.34.1
339
2.34.1
diff view generated by jsdifflib
Deleted patch
1
The mmap_lock is held around tb_gen_code. While the comment
2
is correct that the lock is dropped when tb_gen_code runs out
3
of memory, the lock is *not* dropped when an exception is
4
raised reading code for translation.
5
1
6
Acked-by: Alistair Francis <alistair.francis@wdc.com>
7
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
8
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
---
11
accel/tcg/cpu-exec.c | 12 ++++++------
12
accel/tcg/user-exec.c | 3 ---
13
2 files changed, 6 insertions(+), 9 deletions(-)
14
15
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/accel/tcg/cpu-exec.c
18
+++ b/accel/tcg/cpu-exec.c
19
@@ -XXX,XX +XXX,XX @@ void cpu_exec_step_atomic(CPUState *cpu)
20
cpu_tb_exec(cpu, tb, &tb_exit);
21
cpu_exec_exit(cpu);
22
} else {
23
- /*
24
- * The mmap_lock is dropped by tb_gen_code if it runs out of
25
- * memory.
26
- */
27
#ifndef CONFIG_SOFTMMU
28
clear_helper_retaddr();
29
- tcg_debug_assert(!have_mmap_lock());
30
+ if (have_mmap_lock()) {
31
+ mmap_unlock();
32
+ }
33
#endif
34
if (qemu_mutex_iothread_locked()) {
35
qemu_mutex_unlock_iothread();
36
@@ -XXX,XX +XXX,XX @@ int cpu_exec(CPUState *cpu)
37
38
#ifndef CONFIG_SOFTMMU
39
clear_helper_retaddr();
40
- tcg_debug_assert(!have_mmap_lock());
41
+ if (have_mmap_lock()) {
42
+ mmap_unlock();
43
+ }
44
#endif
45
if (qemu_mutex_iothread_locked()) {
46
qemu_mutex_unlock_iothread();
47
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/accel/tcg/user-exec.c
50
+++ b/accel/tcg/user-exec.c
51
@@ -XXX,XX +XXX,XX @@ MMUAccessType adjust_signal_pc(uintptr_t *pc, bool is_write)
52
* (and if the translator doesn't handle page boundaries correctly
53
* there's little we can do about that here). Therefore, do not
54
* trigger the unwinder.
55
- *
56
- * Like tb_gen_code, release the memory lock before cpu_loop_exit.
57
*/
58
- mmap_unlock();
59
*pc = 0;
60
return MMU_INST_FETCH;
61
}
62
--
63
2.34.1
diff view generated by jsdifflib
Deleted patch
1
The base qemu_ram_addr_from_host function is already in
2
softmmu/physmem.c; move the nofail version to be adjacent.
3
1
4
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
5
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
6
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
include/exec/cpu-common.h | 1 +
10
accel/tcg/cputlb.c | 12 ------------
11
softmmu/physmem.c | 12 ++++++++++++
12
3 files changed, 13 insertions(+), 12 deletions(-)
13
14
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/exec/cpu-common.h
17
+++ b/include/exec/cpu-common.h
18
@@ -XXX,XX +XXX,XX @@ typedef uintptr_t ram_addr_t;
19
void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
20
/* This should not be used by devices. */
21
ram_addr_t qemu_ram_addr_from_host(void *ptr);
22
+ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr);
23
RAMBlock *qemu_ram_block_by_name(const char *name);
24
RAMBlock *qemu_ram_block_from_host(void *ptr, bool round_offset,
25
ram_addr_t *offset);
26
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/accel/tcg/cputlb.c
29
+++ b/accel/tcg/cputlb.c
30
@@ -XXX,XX +XXX,XX @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
31
prot, mmu_idx, size);
32
}
33
34
-static inline ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
35
-{
36
- ram_addr_t ram_addr;
37
-
38
- ram_addr = qemu_ram_addr_from_host(ptr);
39
- if (ram_addr == RAM_ADDR_INVALID) {
40
- error_report("Bad ram pointer %p", ptr);
41
- abort();
42
- }
43
- return ram_addr;
44
-}
45
-
46
/*
47
* Note: tlb_fill() can trigger a resize of the TLB. This means that all of the
48
* caller's prior references to the TLB table (e.g. CPUTLBEntry pointers) must
49
diff --git a/softmmu/physmem.c b/softmmu/physmem.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/softmmu/physmem.c
52
+++ b/softmmu/physmem.c
53
@@ -XXX,XX +XXX,XX @@ ram_addr_t qemu_ram_addr_from_host(void *ptr)
54
return block->offset + offset;
55
}
56
57
+ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
58
+{
59
+ ram_addr_t ram_addr;
60
+
61
+ ram_addr = qemu_ram_addr_from_host(ptr);
62
+ if (ram_addr == RAM_ADDR_INVALID) {
63
+ error_report("Bad ram pointer %p", ptr);
64
+ abort();
65
+ }
66
+ return ram_addr;
67
+}
68
+
69
static MemTxResult flatview_read(FlatView *fv, hwaddr addr,
70
MemTxAttrs attrs, void *buf, hwaddr len);
71
static MemTxResult flatview_write(FlatView *fv, hwaddr addr, MemTxAttrs attrs,
72
--
73
2.34.1
diff view generated by jsdifflib
Deleted patch
1
Simplify the implementation of get_page_addr_code_hostp
2
by reusing the existing probe_access infrastructure.
3
1
4
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
5
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
accel/tcg/cputlb.c | 76 ++++++++++++++++------------------------------
9
1 file changed, 26 insertions(+), 50 deletions(-)
10
11
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/accel/tcg/cputlb.c
14
+++ b/accel/tcg/cputlb.c
15
@@ -XXX,XX +XXX,XX @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
16
victim_tlb_hit(env, mmu_idx, index, offsetof(CPUTLBEntry, TY), \
17
(ADDR) & TARGET_PAGE_MASK)
18
19
-/*
20
- * Return a ram_addr_t for the virtual address for execution.
21
- *
22
- * Return -1 if we can't translate and execute from an entire page
23
- * of RAM. This will force us to execute by loading and translating
24
- * one insn at a time, without caching.
25
- *
26
- * NOTE: This function will trigger an exception if the page is
27
- * not executable.
28
- */
29
-tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
30
- void **hostp)
31
-{
32
- uintptr_t mmu_idx = cpu_mmu_index(env, true);
33
- uintptr_t index = tlb_index(env, mmu_idx, addr);
34
- CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
35
- void *p;
36
-
37
- if (unlikely(!tlb_hit(entry->addr_code, addr))) {
38
- if (!VICTIM_TLB_HIT(addr_code, addr)) {
39
- tlb_fill(env_cpu(env), addr, 0, MMU_INST_FETCH, mmu_idx, 0);
40
- index = tlb_index(env, mmu_idx, addr);
41
- entry = tlb_entry(env, mmu_idx, addr);
42
-
43
- if (unlikely(entry->addr_code & TLB_INVALID_MASK)) {
44
- /*
45
- * The MMU protection covers a smaller range than a target
46
- * page, so we must redo the MMU check for every insn.
47
- */
48
- return -1;
49
- }
50
- }
51
- assert(tlb_hit(entry->addr_code, addr));
52
- }
53
-
54
- if (unlikely(entry->addr_code & TLB_MMIO)) {
55
- /* The region is not backed by RAM. */
56
- if (hostp) {
57
- *hostp = NULL;
58
- }
59
- return -1;
60
- }
61
-
62
- p = (void *)((uintptr_t)addr + entry->addend);
63
- if (hostp) {
64
- *hostp = p;
65
- }
66
- return qemu_ram_addr_from_host_nofail(p);
67
-}
68
-
69
static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size,
70
CPUIOTLBEntry *iotlbentry, uintptr_t retaddr)
71
{
72
@@ -XXX,XX +XXX,XX @@ void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
73
return flags ? NULL : host;
74
}
75
76
+/*
77
+ * Return a ram_addr_t for the virtual address for execution.
78
+ *
79
+ * Return -1 if we can't translate and execute from an entire page
80
+ * of RAM. This will force us to execute by loading and translating
81
+ * one insn at a time, without caching.
82
+ *
83
+ * NOTE: This function will trigger an exception if the page is
84
+ * not executable.
85
+ */
86
+tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
87
+ void **hostp)
88
+{
89
+ void *p;
90
+
91
+ (void)probe_access_internal(env, addr, 1, MMU_INST_FETCH,
92
+ cpu_mmu_index(env, true), false, &p, 0);
93
+ if (p == NULL) {
94
+ return -1;
95
+ }
96
+ if (hostp) {
97
+ *hostp = p;
98
+ }
99
+ return qemu_ram_addr_from_host_nofail(p);
100
+}
101
+
102
#ifdef CONFIG_PLUGIN
103
/*
104
* Perform a TLB lookup and populate the qemu_plugin_hwaddr structure.
105
--
106
2.34.1
diff view generated by jsdifflib
Deleted patch
1
It was non-obvious to me why we can raise an exception in
2
the middle of a comparison function, but it works.
3
While nearby, use TARGET_PAGE_ALIGN instead of open-coding.
4
1
5
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
accel/tcg/cpu-exec.c | 11 ++++++++++-
9
1 file changed, 10 insertions(+), 1 deletion(-)
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 bool tb_lookup_cmp(const void *p, const void *d)
16
tb_page_addr_t phys_page2;
17
target_ulong virt_page2;
18
19
- virt_page2 = (desc->pc & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
20
+ /*
21
+ * We know that the first page matched, and an otherwise valid TB
22
+ * encountered an incomplete instruction at the end of that page,
23
+ * therefore we know that generating a new TB from the current PC
24
+ * must also require reading from the next page -- even if the
25
+ * second pages do not match, and therefore the resulting insn
26
+ * is different for the new TB. Therefore any exception raised
27
+ * here by the faulting lookup is not premature.
28
+ */
29
+ virt_page2 = TARGET_PAGE_ALIGN(desc->pc);
30
phys_page2 = get_page_addr_code(desc->env, virt_page2);
31
if (tb->page_addr[1] == phys_page2) {
32
return true;
33
--
34
2.34.1
diff view generated by jsdifflib
Deleted patch
1
The only user can easily use translator_lduw and
2
adjust the type to signed during the return.
3
1
4
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
5
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
6
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
include/exec/translator.h | 1 -
10
target/i386/tcg/translate.c | 2 +-
11
2 files changed, 1 insertion(+), 2 deletions(-)
12
13
diff --git a/include/exec/translator.h b/include/exec/translator.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/exec/translator.h
16
+++ b/include/exec/translator.h
17
@@ -XXX,XX +XXX,XX @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest);
18
19
#define FOR_EACH_TRANSLATOR_LD(F) \
20
F(translator_ldub, uint8_t, cpu_ldub_code, /* no swap */) \
21
- F(translator_ldsw, int16_t, cpu_ldsw_code, bswap16) \
22
F(translator_lduw, uint16_t, cpu_lduw_code, bswap16) \
23
F(translator_ldl, uint32_t, cpu_ldl_code, bswap32) \
24
F(translator_ldq, uint64_t, cpu_ldq_code, bswap64)
25
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/target/i386/tcg/translate.c
28
+++ b/target/i386/tcg/translate.c
29
@@ -XXX,XX +XXX,XX @@ static inline uint8_t x86_ldub_code(CPUX86State *env, DisasContext *s)
30
31
static inline int16_t x86_ldsw_code(CPUX86State *env, DisasContext *s)
32
{
33
- return translator_ldsw(env, &s->base, advance_pc(env, s, 2));
34
+ return translator_lduw(env, &s->base, advance_pc(env, s, 2));
35
}
36
37
static inline uint16_t x86_lduw_code(CPUX86State *env, DisasContext *s)
38
--
39
2.34.1
diff view generated by jsdifflib
1
Cache the translation from guest to host address, so we may
1
The value passed is always true.
2
use direct loads when we hit on the primary translation page.
3
2
4
Look up the second translation page only once, during translation.
3
Reviewed-by: Claudio Fontana <cfontana@suse.de>
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>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
---
5
---
15
include/exec/translator.h | 63 +++++++++++--------
6
accel/tcg/internal.h | 2 +-
16
accel/tcg/translate-all.c | 23 +++----
7
accel/tcg/tb-maint.c | 4 ++--
17
accel/tcg/translator.c | 126 +++++++++++++++++++++++++++++---------
8
accel/tcg/translate-all.c | 15 +++++++--------
18
3 files changed, 141 insertions(+), 71 deletions(-)
9
3 files changed, 10 insertions(+), 11 deletions(-)
19
10
20
diff --git a/include/exec/translator.h b/include/exec/translator.h
11
diff --git a/accel/tcg/internal.h b/accel/tcg/internal.h
21
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
22
--- a/include/exec/translator.h
13
--- a/accel/tcg/internal.h
23
+++ b/include/exec/translator.h
14
+++ b/accel/tcg/internal.h
24
@@ -XXX,XX +XXX,XX @@ typedef enum DisasJumpType {
15
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
25
* Architecture-agnostic disassembly context.
16
tb_page_addr_t phys_page2);
26
*/
17
bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc);
27
typedef struct DisasContextBase {
18
void cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
28
- const TranslationBlock *tb;
19
- uintptr_t host_pc, bool reset_icount);
29
+ TranslationBlock *tb;
20
+ uintptr_t host_pc);
30
target_ulong pc_first;
21
31
target_ulong pc_next;
22
/* Return the current PC from CPU, which may be cached in TB. */
32
DisasJumpType is_jmp;
23
static inline target_ulong log_pc(CPUState *cpu, const TranslationBlock *tb)
33
int num_insns;
24
diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c
34
int max_insns;
25
index XXXXXXX..XXXXXXX 100644
35
bool singlestep_enabled;
26
--- a/accel/tcg/tb-maint.c
36
-#ifdef CONFIG_USER_ONLY
27
+++ b/accel/tcg/tb-maint.c
37
- /*
28
@@ -XXX,XX +XXX,XX @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
38
- * Guest address of the last byte of the last protected page.
29
* restore the CPU state.
39
- *
30
*/
40
- * Pages containing the translated instructions are made non-writable in
31
current_tb_modified = true;
41
- * order to achieve consistency in case another thread is modifying the
32
- cpu_restore_state_from_tb(cpu, current_tb, retaddr, true);
42
- * code while translate_insn() fetches the instruction bytes piecemeal.
33
+ cpu_restore_state_from_tb(cpu, current_tb, retaddr);
43
- * Such writer threads are blocked on mmap_lock() in page_unprotect().
34
}
44
- */
35
#endif /* TARGET_HAS_PRECISE_SMC */
45
- target_ulong page_protect_end;
36
tb_phys_invalidate__locked(tb);
46
-#endif
37
@@ -XXX,XX +XXX,XX @@ bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc)
47
+ void *host_addr[2];
38
* function to partially restore the CPU state.
48
} DisasContextBase;
39
*/
49
40
current_tb_modified = true;
50
/**
41
- cpu_restore_state_from_tb(cpu, current_tb, pc, true);
51
@@ -XXX,XX +XXX,XX @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest);
42
+ cpu_restore_state_from_tb(cpu, current_tb, pc);
52
* the relevant information at translation time.
43
}
53
*/
44
#endif /* TARGET_HAS_PRECISE_SMC */
54
45
tb_phys_invalidate(tb, addr);
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_swap(env, db, pc, false);
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
46
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
111
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
112
--- a/accel/tcg/translate-all.c
48
--- a/accel/tcg/translate-all.c
113
+++ b/accel/tcg/translate-all.c
49
+++ b/accel/tcg/translate-all.c
114
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
50
@@ -XXX,XX +XXX,XX @@ static int cpu_unwind_data_from_tb(TranslationBlock *tb, uintptr_t host_pc,
51
}
52
53
/*
54
- * The cpu state corresponding to 'host_pc' is restored.
55
- * When reset_icount is true, current TB will be interrupted and
56
- * icount should be recalculated.
57
+ * The cpu state corresponding to 'host_pc' is restored in
58
+ * preparation for exiting the TB.
59
*/
60
void cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
61
- uintptr_t host_pc, bool reset_icount)
62
+ uintptr_t host_pc)
115
{
63
{
116
CPUArchState *env = cpu->env_ptr;
64
uint64_t data[TARGET_INSN_START_WORDS];
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
65
#ifdef CONFIG_PROFILER
124
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
66
@@ -XXX,XX +XXX,XX @@ void cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
125
tb->flags = flags;
67
return;
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
}
68
}
135
69
70
- if (reset_icount && (tb_cflags(tb) & CF_USE_ICOUNT)) {
71
+ if (tb_cflags(tb) & CF_USE_ICOUNT) {
72
assert(icount_enabled());
73
/*
74
* Reset the cycle counter to the start of the block and
75
@@ -XXX,XX +XXX,XX @@ bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc)
76
if (in_code_gen_buffer((const void *)(host_pc - tcg_splitwx_diff))) {
77
TranslationBlock *tb = tcg_tb_lookup(host_pc);
78
if (tb) {
79
- cpu_restore_state_from_tb(cpu, tb, host_pc, true);
80
+ cpu_restore_state_from_tb(cpu, tb, host_pc);
81
return true;
82
}
83
}
84
@@ -XXX,XX +XXX,XX @@ void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr)
85
tb = tcg_tb_lookup(retaddr);
86
if (tb) {
87
/* We can use retranslation to find the PC. */
88
- cpu_restore_state_from_tb(cpu, tb, retaddr, true);
89
+ cpu_restore_state_from_tb(cpu, tb, retaddr);
90
tb_phys_invalidate(tb, -1);
91
} else {
92
/* The exception probably happened in a helper. The CPU state should
93
@@ -XXX,XX +XXX,XX @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
94
cpu_abort(cpu, "cpu_io_recompile: could not find TB for pc=%p",
95
(void *)retaddr);
96
}
97
- cpu_restore_state_from_tb(cpu, tb, retaddr, true);
98
+ cpu_restore_state_from_tb(cpu, tb, retaddr);
99
136
/*
100
/*
137
- * If the TB is not associated with a physical RAM page then
101
* Some guests must re-execute the branch when re-executing a delay
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;
170
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
171
index XXXXXXX..XXXXXXX 100644
172
--- a/accel/tcg/translator.c
173
+++ b/accel/tcg/translator.c
174
@@ -XXX,XX +XXX,XX @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest)
175
return ((db->pc_first ^ dest) & TARGET_PAGE_MASK) == 0;
176
}
177
178
-static inline void translator_page_protect(DisasContextBase *dcbase,
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)
212
{
213
-#ifdef CONFIG_USER_ONLY
214
- target_ulong end = pc + len - 1;
215
+ void *host;
216
+ target_ulong base, end;
217
+ TranslationBlock *tb;
218
219
- if (end > dcbase->page_protect_end) {
220
- translator_page_protect(dcbase, end);
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);
254
}
255
256
-#define GEN_TRANSLATOR_LD(fullname, type, load_fn, swap_fn) \
257
- type fullname ## _swap(CPUArchState *env, DisasContextBase *dcbase, \
258
- abi_ptr pc, bool do_swap) \
259
- { \
260
- translator_maybe_page_protect(dcbase, pc, sizeof(type)); \
261
- type ret = load_fn(env, pc); \
262
- if (do_swap) { \
263
- ret = swap_fn(ret); \
264
- } \
265
- plugin_insn_append(pc, &ret, sizeof(ret)); \
266
- return ret; \
267
+uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
268
+{
269
+ uint8_t ret;
270
+ void *p = translator_access(env, db, pc, sizeof(ret));
271
+
272
+ if (p) {
273
+ plugin_insn_append(pc, p, sizeof(ret));
274
+ return ldub_p(p);
275
}
276
+ ret = cpu_ldub_code(env, pc);
277
+ plugin_insn_append(pc, &ret, sizeof(ret));
278
+ return ret;
279
+}
280
281
-FOR_EACH_TRANSLATOR_LD(GEN_TRANSLATOR_LD)
282
+uint16_t translator_lduw(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
283
+{
284
+ uint16_t ret, plug;
285
+ void *p = translator_access(env, db, pc, sizeof(ret));
286
287
-#undef GEN_TRANSLATOR_LD
288
+ if (p) {
289
+ plugin_insn_append(pc, p, sizeof(ret));
290
+ return lduw_p(p);
291
+ }
292
+ ret = cpu_lduw_code(env, pc);
293
+ plug = tswap16(ret);
294
+ plugin_insn_append(pc, &plug, sizeof(ret));
295
+ return ret;
296
+}
297
+
298
+uint32_t translator_ldl(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
299
+{
300
+ uint32_t ret, plug;
301
+ void *p = translator_access(env, db, pc, sizeof(ret));
302
+
303
+ if (p) {
304
+ plugin_insn_append(pc, p, sizeof(ret));
305
+ return ldl_p(p);
306
+ }
307
+ ret = cpu_ldl_code(env, pc);
308
+ plug = tswap32(ret);
309
+ plugin_insn_append(pc, &plug, sizeof(ret));
310
+ return ret;
311
+}
312
+
313
+uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
314
+{
315
+ uint64_t ret, plug;
316
+ void *p = translator_access(env, db, pc, sizeof(ret));
317
+
318
+ if (p) {
319
+ plugin_insn_append(pc, p, sizeof(ret));
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
+}
327
--
102
--
328
2.34.1
103
2.34.1
diff view generated by jsdifflib
1
From: Ilya Leoshkevich <iii@linux.ibm.com>
1
The helpers for reset_rf, cli, sti, clac, stac are
2
completely trivial; implement them inline.
2
3
3
Right now translator stops right *after* the end of a page, which
4
Drop some nearby #if 0 code.
4
breaks reporting of fault locations when the last instruction of a
5
multi-insn translation block crosses a page boundary.
6
5
7
An implementation, like the one arm and s390x have, would require an
6
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
8
i386 length disassembler, which is burdensome to maintain. Another
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
alternative would be to single-step at the end of a guest page, but
10
this may come with a performance impact.
11
12
Fix by snapshotting disassembly state and restoring it after we figure
13
out we crossed a page boundary. This includes rolling back cc_op
14
updates and emitted ops.
15
16
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1143
19
Message-Id: <20220817150506.592862-4-iii@linux.ibm.com>
20
[rth: Simplify end-of-insn cross-page checks.]
21
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
22
---
9
---
23
target/i386/tcg/translate.c | 64 ++++++++++++++++-----------
10
target/i386/helper.h | 5 -----
24
tests/tcg/x86_64/noexec.c | 75 ++++++++++++++++++++++++++++++++
11
target/i386/tcg/cc_helper.c | 41 -------------------------------------
25
tests/tcg/x86_64/Makefile.target | 3 +-
12
target/i386/tcg/translate.c | 30 ++++++++++++++++++++++-----
26
3 files changed, 116 insertions(+), 26 deletions(-)
13
3 files changed, 25 insertions(+), 51 deletions(-)
27
create mode 100644 tests/tcg/x86_64/noexec.c
28
14
15
diff --git a/target/i386/helper.h b/target/i386/helper.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/i386/helper.h
18
+++ b/target/i386/helper.h
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(syscall, void, env, int)
20
DEF_HELPER_2(sysret, void, env, int)
21
#endif
22
DEF_HELPER_FLAGS_2(pause, TCG_CALL_NO_WG, noreturn, env, int)
23
-DEF_HELPER_1(reset_rf, void, env)
24
DEF_HELPER_FLAGS_3(raise_interrupt, TCG_CALL_NO_WG, noreturn, env, int, int)
25
DEF_HELPER_FLAGS_2(raise_exception, TCG_CALL_NO_WG, noreturn, env, int)
26
-DEF_HELPER_1(cli, void, env)
27
-DEF_HELPER_1(sti, void, env)
28
-DEF_HELPER_1(clac, void, env)
29
-DEF_HELPER_1(stac, void, env)
30
DEF_HELPER_3(boundw, void, env, tl, int)
31
DEF_HELPER_3(boundl, void, env, tl, int)
32
33
diff --git a/target/i386/tcg/cc_helper.c b/target/i386/tcg/cc_helper.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/i386/tcg/cc_helper.c
36
+++ b/target/i386/tcg/cc_helper.c
37
@@ -XXX,XX +XXX,XX @@ void helper_clts(CPUX86State *env)
38
env->cr[0] &= ~CR0_TS_MASK;
39
env->hflags &= ~HF_TS_MASK;
40
}
41
-
42
-void helper_reset_rf(CPUX86State *env)
43
-{
44
- env->eflags &= ~RF_MASK;
45
-}
46
-
47
-void helper_cli(CPUX86State *env)
48
-{
49
- env->eflags &= ~IF_MASK;
50
-}
51
-
52
-void helper_sti(CPUX86State *env)
53
-{
54
- env->eflags |= IF_MASK;
55
-}
56
-
57
-void helper_clac(CPUX86State *env)
58
-{
59
- env->eflags &= ~AC_MASK;
60
-}
61
-
62
-void helper_stac(CPUX86State *env)
63
-{
64
- env->eflags |= AC_MASK;
65
-}
66
-
67
-#if 0
68
-/* vm86plus instructions */
69
-void helper_cli_vm(CPUX86State *env)
70
-{
71
- env->eflags &= ~VIF_MASK;
72
-}
73
-
74
-void helper_sti_vm(CPUX86State *env)
75
-{
76
- env->eflags |= VIF_MASK;
77
- if (env->eflags & VIP_MASK) {
78
- raise_exception_ra(env, EXCP0D_GPF, GETPC());
79
- }
80
-}
81
-#endif
29
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
82
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
30
index XXXXXXX..XXXXXXX 100644
83
index XXXXXXX..XXXXXXX 100644
31
--- a/target/i386/tcg/translate.c
84
--- a/target/i386/tcg/translate.c
32
+++ b/target/i386/tcg/translate.c
85
+++ b/target/i386/tcg/translate.c
33
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
86
@@ -XXX,XX +XXX,XX @@ static void gen_reset_hflag(DisasContext *s, uint32_t mask)
34
TCGv_i64 tmp1_i64;
87
}
35
88
}
36
sigjmp_buf jmpbuf;
89
37
+ TCGOp *prev_insn_end;
90
+static void gen_set_eflags(DisasContext *s, target_ulong mask)
38
} DisasContext;
91
+{
39
92
+ TCGv t = tcg_temp_new();
40
/* The environment in which user-only runs is constrained. */
41
@@ -XXX,XX +XXX,XX @@ static uint64_t advance_pc(CPUX86State *env, DisasContext *s, int num_bytes)
42
{
43
uint64_t pc = s->pc;
44
45
+ /* This is a subsequent insn that crosses a page boundary. */
46
+ if (s->base.num_insns > 1 &&
47
+ !is_same_page(&s->base, s->pc + num_bytes - 1)) {
48
+ siglongjmp(s->jmpbuf, 2);
49
+ }
50
+
93
+
51
s->pc += num_bytes;
94
+ tcg_gen_ld_tl(t, cpu_env, offsetof(CPUX86State, eflags));
52
if (unlikely(s->pc - s->pc_start > X86_MAX_INSN_LENGTH)) {
95
+ tcg_gen_ori_tl(t, t, mask);
53
/* If the instruction's 16th byte is on a different page than the 1st, a
96
+ tcg_gen_st_tl(t, cpu_env, offsetof(CPUX86State, eflags));
54
@@ -XXX,XX +XXX,XX @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
97
+ tcg_temp_free(t);
55
int modrm, reg, rm, mod, op, opreg, val;
56
target_ulong next_eip, tval;
57
target_ulong pc_start = s->base.pc_next;
58
+ bool orig_cc_op_dirty = s->cc_op_dirty;
59
+ CCOp orig_cc_op = s->cc_op;
60
61
s->pc_start = s->pc = pc_start;
62
s->override = -1;
63
@@ -XXX,XX +XXX,XX @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
64
s->rip_offset = 0; /* for relative ip address */
65
s->vex_l = 0;
66
s->vex_v = 0;
67
- if (sigsetjmp(s->jmpbuf, 0) != 0) {
68
+ switch (sigsetjmp(s->jmpbuf, 0)) {
69
+ case 0:
70
+ break;
71
+ case 1:
72
gen_exception_gpf(s);
73
return s->pc;
74
+ case 2:
75
+ /* Restore state that may affect the next instruction. */
76
+ s->cc_op_dirty = orig_cc_op_dirty;
77
+ s->cc_op = orig_cc_op;
78
+ s->base.num_insns--;
79
+ tcg_remove_ops_after(s->prev_insn_end);
80
+ s->base.is_jmp = DISAS_TOO_MANY;
81
+ return pc_start;
82
+ default:
83
+ g_assert_not_reached();
84
}
85
86
prefixes = 0;
87
@@ -XXX,XX +XXX,XX @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
88
{
89
DisasContext *dc = container_of(dcbase, DisasContext, base);
90
91
+ dc->prev_insn_end = tcg_last_op();
92
tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
93
}
94
95
@@ -XXX,XX +XXX,XX @@ static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
96
#endif
97
98
pc_next = disas_insn(dc, cpu);
99
-
100
- if (dc->flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)) {
101
- /* if single step mode, we generate only one instruction and
102
- generate an exception */
103
- /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
104
- the flag and abort the translation to give the irqs a
105
- chance to happen */
106
- dc->base.is_jmp = DISAS_TOO_MANY;
107
- } else if ((tb_cflags(dc->base.tb) & CF_USE_ICOUNT)
108
- && ((pc_next & TARGET_PAGE_MASK)
109
- != ((pc_next + TARGET_MAX_INSN_SIZE - 1)
110
- & TARGET_PAGE_MASK)
111
- || (pc_next & ~TARGET_PAGE_MASK) == 0)) {
112
- /* Do not cross the boundary of the pages in icount mode,
113
- it can cause an exception. Do it only when boundary is
114
- crossed by the first instruction in the block.
115
- If current instruction already crossed the bound - it's ok,
116
- because an exception hasn't stopped this code.
117
- */
118
- dc->base.is_jmp = DISAS_TOO_MANY;
119
- } else if ((pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32)) {
120
- dc->base.is_jmp = DISAS_TOO_MANY;
121
- }
122
-
123
dc->base.pc_next = pc_next;
124
+
125
+ if (dc->base.is_jmp == DISAS_NEXT) {
126
+ if (dc->flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)) {
127
+ /*
128
+ * If single step mode, we generate only one instruction and
129
+ * generate an exception.
130
+ * If irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
131
+ * the flag and abort the translation to give the irqs a
132
+ * chance to happen.
133
+ */
134
+ dc->base.is_jmp = DISAS_TOO_MANY;
135
+ } else if (!is_same_page(&dc->base, pc_next)) {
136
+ dc->base.is_jmp = DISAS_TOO_MANY;
137
+ }
138
+ }
139
}
140
141
static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
142
diff --git a/tests/tcg/x86_64/noexec.c b/tests/tcg/x86_64/noexec.c
143
new file mode 100644
144
index XXXXXXX..XXXXXXX
145
--- /dev/null
146
+++ b/tests/tcg/x86_64/noexec.c
147
@@ -XXX,XX +XXX,XX @@
148
+#include "../multiarch/noexec.c.inc"
149
+
150
+static void *arch_mcontext_pc(const mcontext_t *ctx)
151
+{
152
+ return (void *)ctx->gregs[REG_RIP];
153
+}
98
+}
154
+
99
+
155
+int arch_mcontext_arg(const mcontext_t *ctx)
100
+static void gen_reset_eflags(DisasContext *s, target_ulong mask)
156
+{
101
+{
157
+ return ctx->gregs[REG_RDI];
102
+ TCGv t = tcg_temp_new();
103
+
104
+ tcg_gen_ld_tl(t, cpu_env, offsetof(CPUX86State, eflags));
105
+ tcg_gen_andi_tl(t, t, ~mask);
106
+ tcg_gen_st_tl(t, cpu_env, offsetof(CPUX86State, eflags));
107
+ tcg_temp_free(t);
158
+}
108
+}
159
+
109
+
160
+static void arch_flush(void *p, int len)
110
/* Clear BND registers during legacy branches. */
161
+{
111
static void gen_bnd_jmp(DisasContext *s)
162
+}
112
{
163
+
113
@@ -XXX,XX +XXX,XX @@ do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, bool jr)
164
+extern char noexec_1[];
114
}
165
+extern char noexec_2[];
115
166
+extern char noexec_end[];
116
if (s->base.tb->flags & HF_RF_MASK) {
167
+
117
- gen_helper_reset_rf(cpu_env);
168
+asm("noexec_1:\n"
118
+ gen_reset_eflags(s, RF_MASK);
169
+ " movq $1,%rdi\n" /* %rdi is 0 on entry, set 1. */
119
}
170
+ "noexec_2:\n"
120
if (recheck_tf) {
171
+ " movq $2,%rdi\n" /* %rdi is 0/1; set 2. */
121
gen_helper_rechecking_single_step(cpu_env);
172
+ " ret\n"
122
@@ -XXX,XX +XXX,XX @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
173
+ "noexec_end:");
123
#endif
174
+
124
case 0xfa: /* cli */
175
+int main(void)
125
if (check_iopl(s)) {
176
+{
126
- gen_helper_cli(cpu_env);
177
+ struct noexec_test noexec_tests[] = {
127
+ gen_reset_eflags(s, IF_MASK);
178
+ {
128
}
179
+ .name = "fallthrough",
129
break;
180
+ .test_code = noexec_1,
130
case 0xfb: /* sti */
181
+ .test_len = noexec_end - noexec_1,
131
if (check_iopl(s)) {
182
+ .page_ofs = noexec_1 - noexec_2,
132
- gen_helper_sti(cpu_env);
183
+ .entry_ofs = noexec_1 - noexec_2,
133
+ gen_set_eflags(s, IF_MASK);
184
+ .expected_si_ofs = 0,
134
/* interruptions are enabled only the first insn after sti */
185
+ .expected_pc_ofs = 0,
135
gen_update_eip_next(s);
186
+ .expected_arg = 1,
136
gen_eob_inhibit_irq(s, true);
187
+ },
137
@@ -XXX,XX +XXX,XX @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
188
+ {
138
|| CPL(s) != 0) {
189
+ .name = "jump",
139
goto illegal_op;
190
+ .test_code = noexec_1,
140
}
191
+ .test_len = noexec_end - noexec_1,
141
- gen_helper_clac(cpu_env);
192
+ .page_ofs = noexec_1 - noexec_2,
142
+ gen_reset_eflags(s, AC_MASK);
193
+ .entry_ofs = 0,
143
s->base.is_jmp = DISAS_EOB_NEXT;
194
+ .expected_si_ofs = 0,
144
break;
195
+ .expected_pc_ofs = 0,
145
196
+ .expected_arg = 0,
146
@@ -XXX,XX +XXX,XX @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
197
+ },
147
|| CPL(s) != 0) {
198
+ {
148
goto illegal_op;
199
+ .name = "fallthrough [cross]",
149
}
200
+ .test_code = noexec_1,
150
- gen_helper_stac(cpu_env);
201
+ .test_len = noexec_end - noexec_1,
151
+ gen_set_eflags(s, AC_MASK);
202
+ .page_ofs = noexec_1 - noexec_2 - 2,
152
s->base.is_jmp = DISAS_EOB_NEXT;
203
+ .entry_ofs = noexec_1 - noexec_2 - 2,
153
break;
204
+ .expected_si_ofs = 0,
154
205
+ .expected_pc_ofs = -2,
206
+ .expected_arg = 1,
207
+ },
208
+ {
209
+ .name = "jump [cross]",
210
+ .test_code = noexec_1,
211
+ .test_len = noexec_end - noexec_1,
212
+ .page_ofs = noexec_1 - noexec_2 - 2,
213
+ .entry_ofs = -2,
214
+ .expected_si_ofs = 0,
215
+ .expected_pc_ofs = -2,
216
+ .expected_arg = 0,
217
+ },
218
+ };
219
+
220
+ return test_noexec(noexec_tests,
221
+ sizeof(noexec_tests) / sizeof(noexec_tests[0]));
222
+}
223
diff --git a/tests/tcg/x86_64/Makefile.target b/tests/tcg/x86_64/Makefile.target
224
index XXXXXXX..XXXXXXX 100644
225
--- a/tests/tcg/x86_64/Makefile.target
226
+++ b/tests/tcg/x86_64/Makefile.target
227
@@ -XXX,XX +XXX,XX @@ include $(SRC_PATH)/tests/tcg/i386/Makefile.target
228
229
ifeq ($(filter %-linux-user, $(TARGET)),$(TARGET))
230
X86_64_TESTS += vsyscall
231
+X86_64_TESTS += noexec
232
TESTS=$(MULTIARCH_TESTS) $(X86_64_TESTS) test-x86_64
233
else
234
TESTS=$(MULTIARCH_TESTS)
235
@@ -XXX,XX +XXX,XX @@ test-x86_64: LDFLAGS+=-lm -lc
236
test-x86_64: test-i386.c test-i386.h test-i386-shift.h test-i386-muldiv.h
237
    $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
238
239
-vsyscall: $(SRC_PATH)/tests/tcg/x86_64/vsyscall.c
240
+%: $(SRC_PATH)/tests/tcg/x86_64/%.c
241
    $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
242
--
155
--
243
2.34.1
156
2.34.1
157
158
diff view generated by jsdifflib
Deleted patch
1
These will be useful in properly ending the TB.
2
1
3
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
4
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
5
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
target/riscv/translate.c | 10 +++++++++-
9
1 file changed, 9 insertions(+), 1 deletion(-)
10
11
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/riscv/translate.c
14
+++ b/target/riscv/translate.c
15
@@ -XXX,XX +XXX,XX @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
16
/* Include decoders for factored-out extensions */
17
#include "decode-XVentanaCondOps.c.inc"
18
19
+/* The specification allows for longer insns, but not supported by qemu. */
20
+#define MAX_INSN_LEN 4
21
+
22
+static inline int insn_len(uint16_t first_word)
23
+{
24
+ return (first_word & 3) == 3 ? 4 : 2;
25
+}
26
+
27
static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
28
{
29
/*
30
@@ -XXX,XX +XXX,XX @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
31
};
32
33
/* Check for compressed insn */
34
- if (extract16(opcode, 0, 2) != 3) {
35
+ if (insn_len(opcode) == 2) {
36
if (!has_ext(ctx, RVC)) {
37
gen_exception_illegal(ctx);
38
} else {
39
--
40
2.34.1
diff view generated by jsdifflib