1
The following changes since commit e93ded1bf6c94ab95015b33e188bc8b0b0c32670:
1
Second try's the charm today, right?
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
4
r~
5
6
7
The following changes since commit 00b1faea41d283e931256aa78aa975a369ec3ae6:
8
9
Merge tag 'pull-target-arm-20230123' of https://git.linaro.org/people/pmaydell/qemu-arm into staging (2023-01-23 13:40:28 +0000)
4
10
5
are available in the Git repository at:
11
are available in the Git repository at:
6
12
7
https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20220901
13
https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20230123
8
14
9
for you to fetch changes up to 20011be2e30b8aa8ef1fc258485f00c688703deb:
15
for you to fetch changes up to 709bcd7da3f6b4655d910634a0d520fa1439df38:
10
16
11
target/riscv: Make translator stop before the end of a page (2022-09-01 07:43:08 +0100)
17
tcg/loongarch64: Reorg goto_tb implementation (2023-01-23 16:00:13 -1000)
12
18
13
----------------------------------------------------------------
19
----------------------------------------------------------------
14
Respect PROT_EXEC in user-only mode.
20
common-user: Re-enable ppc32 host
15
Fix s390x, i386 and riscv for translations crossing a page.
21
tcg: Avoid recursion in tcg_gen_mulu2_i32
22
tcg: Mark tcg helpers noinline to avoid an issue with LTO
23
tcg/arm: Use register pair allocation for qemu_{ld,st}_i64
24
disas: Enable loongarch disassembler, and fixes
25
tcg/loongarch64: Improve move immediate
26
tcg/loongarch64: Improve add immediate
27
tcg/loongarch64: Improve setcond
28
tcg/loongarch64: Implement movcond
29
tcg/loongarch64: Use tcg_pcrel_diff in tcg_out_ldst
30
tcg/loongarch64: Reorg goto_tb implementation
16
31
17
----------------------------------------------------------------
32
----------------------------------------------------------------
18
Ilya Leoshkevich (4):
33
Richard Henderson (14):
19
linux-user: Clear translations on mprotect()
34
tcg: Avoid recursion in tcg_gen_mulu2_i32
20
accel/tcg: Introduce is_same_page()
35
tcg/arm: Use register pair allocation for qemu_{ld,st}_i64
21
target/s390x: Make translator stop before the end of a page
36
common-user/host/ppc: Implement safe-syscall.inc.S
22
target/i386: Make translator stop before the end of a page
37
linux-user: Implment host/ppc/host-signal.h
38
tcg: Mark tcg helpers noinline to avoid an issue with LTO
39
target/loongarch: Enable the disassembler for host tcg
40
target/loongarch: Disassemble jirl properly
41
target/loongarch: Disassemble pcadd* addresses
42
tcg/loongarch64: Update tcg-insn-defs.c.inc
43
tcg/loongarch64: Introduce tcg_out_addi
44
tcg/loongarch64: Improve setcond expansion
45
tcg/loongarch64: Implement movcond
46
tcg/loongarch64: Use tcg_pcrel_diff in tcg_out_ldst
47
tcg/loongarch64: Reorg goto_tb implementation
23
48
24
Richard Henderson (16):
49
Rui Wang (1):
25
linux-user/arm: Mark the commpage executable
50
tcg/loongarch64: Optimize immediate loading
26
linux-user/hppa: Allocate page zero as a commpage
27
linux-user/x86_64: Allocate vsyscall page as a commpage
28
linux-user: Honor PT_GNU_STACK
29
tests/tcg/i386: Move smc_code2 to an executable section
30
accel/tcg: Properly implement get_page_addr_code for user-only
31
accel/tcg: Unlock mmap_lock after longjmp
32
accel/tcg: Make tb_htable_lookup static
33
accel/tcg: Move qemu_ram_addr_from_host_nofail to physmem.c
34
accel/tcg: Use probe_access_internal for softmmu get_page_addr_code_hostp
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
51
42
include/elf.h | 1 +
52
include/exec/helper-proto.h | 32 ++-
43
include/exec/cpu-common.h | 1 +
53
include/tcg/tcg.h | 7 -
44
include/exec/exec-all.h | 89 ++++++++----------------
54
linux-user/include/host/ppc/host-signal.h | 39 +++
45
include/exec/translator.h | 96 ++++++++++++++++---------
55
tcg/arm/tcg-target-con-set.h | 7 +-
46
linux-user/arm/target_cpu.h | 4 +-
56
tcg/arm/tcg-target-con-str.h | 2 +
47
linux-user/qemu.h | 1 +
57
tcg/loongarch64/tcg-target-con-set.h | 5 +-
48
accel/tcg/cpu-exec.c | 143 ++++++++++++++++++++------------------
58
tcg/loongarch64/tcg-target-con-str.h | 2 +-
49
accel/tcg/cputlb.c | 93 +++++++------------------
59
tcg/loongarch64/tcg-target.h | 11 +-
50
accel/tcg/translate-all.c | 29 ++++----
60
target/loongarch/insns.decode | 3 +-
51
accel/tcg/translator.c | 135 ++++++++++++++++++++++++++---------
61
disas.c | 2 +
52
accel/tcg/user-exec.c | 17 ++++-
62
target/loongarch/disas.c | 39 ++-
53
linux-user/elfload.c | 82 ++++++++++++++++++++--
63
tcg/tcg-op.c | 4 +-
54
linux-user/mmap.c | 6 +-
64
target/loongarch/insn_trans/trans_branch.c.inc | 2 +-
55
softmmu/physmem.c | 12 ++++
65
tcg/arm/tcg-target.c.inc | 28 +-
56
target/alpha/translate.c | 5 +-
66
tcg/loongarch64/tcg-insn-defs.c.inc | 10 +-
57
target/arm/translate.c | 5 +-
67
tcg/loongarch64/tcg-target.c.inc | 364 ++++++++++++++++---------
58
target/avr/translate.c | 5 +-
68
common-user/host/ppc/safe-syscall.inc.S | 107 ++++++++
59
target/cris/translate.c | 5 +-
69
target/loongarch/meson.build | 3 +-
60
target/hexagon/translate.c | 6 +-
70
18 files changed, 497 insertions(+), 170 deletions(-)
61
target/hppa/translate.c | 5 +-
71
create mode 100644 linux-user/include/host/ppc/host-signal.h
62
target/i386/tcg/translate.c | 71 +++++++++++--------
72
create mode 100644 common-user/host/ppc/safe-syscall.inc.S
63
target/loongarch/translate.c | 6 +-
64
target/m68k/translate.c | 5 +-
65
target/microblaze/translate.c | 5 +-
66
target/mips/tcg/translate.c | 5 +-
67
target/nios2/translate.c | 5 +-
68
target/openrisc/translate.c | 6 +-
69
target/ppc/translate.c | 5 +-
70
target/riscv/translate.c | 32 +++++++--
71
target/rx/translate.c | 5 +-
72
target/s390x/tcg/translate.c | 20 ++++--
73
target/sh4/translate.c | 5 +-
74
target/sparc/translate.c | 5 +-
75
target/tricore/translate.c | 6 +-
76
target/xtensa/translate.c | 6 +-
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
Pass these along to translator_loop -- pc may be used instead
1
We have a test for one of TCG_TARGET_HAS_mulu2_i32 or
2
of tb->pc, and host_pc is currently unused. Adjust all targets
2
TCG_TARGET_HAS_muluh_i32 being defined, but the test
3
at one time.
3
became non-functional when we changed to always define
4
all of these macros.
4
5
5
Acked-by: Alistair Francis <alistair.francis@wdc.com>
6
Replace this with a build-time test in tcg_gen_mulu2_i32.
6
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
7
7
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
8
Fixes: 25c4d9cc845 ("tcg: Always define all of the TCGOpcode enum members.")
9
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1435
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
11
---
10
include/exec/exec-all.h | 1 -
12
include/tcg/tcg.h | 7 -------
11
include/exec/translator.h | 24 ++++++++++++++++++++----
13
tcg/tcg-op.c | 4 +++-
12
accel/tcg/translate-all.c | 6 ++++--
14
2 files changed, 3 insertions(+), 8 deletions(-)
13
accel/tcg/translator.c | 9 +++++----
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
15
37
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
16
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
38
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
39
--- a/include/exec/exec-all.h
18
--- a/include/tcg/tcg.h
40
+++ b/include/exec/exec-all.h
19
+++ b/include/tcg/tcg.h
41
@@ -XXX,XX +XXX,XX @@ typedef ram_addr_t tb_page_addr_t;
20
@@ -XXX,XX +XXX,XX @@ typedef uint64_t TCGRegSet;
42
#define TB_PAGE_ADDR_FMT RAM_ADDR_FMT
21
#define TCG_TARGET_HAS_rem_i64 0
43
#endif
22
#endif
44
23
45
-void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns);
24
-/* For 32-bit targets, some sort of unsigned widening multiply is required. */
46
void restore_state_to_opc(CPUArchState *env, TranslationBlock *tb,
25
-#if TCG_TARGET_REG_BITS == 32 \
47
target_ulong *data);
26
- && !(defined(TCG_TARGET_HAS_mulu2_i32) \
48
27
- || defined(TCG_TARGET_HAS_muluh_i32))
49
diff --git a/include/exec/translator.h b/include/exec/translator.h
28
-# error "Missing unsigned widening multiply"
29
-#endif
30
-
31
#if !defined(TCG_TARGET_HAS_v64) \
32
&& !defined(TCG_TARGET_HAS_v128) \
33
&& !defined(TCG_TARGET_HAS_v256)
34
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
50
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
51
--- a/include/exec/translator.h
36
--- a/tcg/tcg-op.c
52
+++ b/include/exec/translator.h
37
+++ b/tcg/tcg-op.c
53
@@ -XXX,XX +XXX,XX @@
38
@@ -XXX,XX +XXX,XX @@ void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
54
#include "exec/translate-all.h"
39
tcg_gen_op3_i32(INDEX_op_muluh_i32, rh, arg1, arg2);
55
#include "tcg/tcg.h"
40
tcg_gen_mov_i32(rl, t);
56
41
tcg_temp_free_i32(t);
57
+/**
42
- } else {
58
+ * gen_intermediate_code
43
+ } else if (TCG_TARGET_REG_BITS == 64) {
59
+ * @cpu: cpu context
44
TCGv_i64 t0 = tcg_temp_new_i64();
60
+ * @tb: translation block
45
TCGv_i64 t1 = tcg_temp_new_i64();
61
+ * @max_insns: max number of instructions to translate
46
tcg_gen_extu_i32_i64(t0, arg1);
62
+ * @pc: guest virtual program counter address
47
@@ -XXX,XX +XXX,XX @@ void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
63
+ * @host_pc: host physical program counter address
48
tcg_gen_extr_i64_i32(rl, rh, t0);
64
+ *
49
tcg_temp_free_i64(t0);
65
+ * This function must be provided by the target, which should create
50
tcg_temp_free_i64(t1);
66
+ * the target-specific DisasContext, and then invoke translator_loop.
51
+ } else {
67
+ */
52
+ qemu_build_not_reached();
68
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
53
}
69
+ target_ulong pc, void *host_pc);
70
71
/**
72
* DisasJumpType:
73
@@ -XXX,XX +XXX,XX @@ typedef struct TranslatorOps {
74
75
/**
76
* translator_loop:
77
- * @ops: Target-specific operations.
78
- * @db: Disassembly context.
79
* @cpu: Target vCPU.
80
* @tb: Translation block.
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
*
87
* Generic translator loop.
88
*
89
@@ -XXX,XX +XXX,XX @@ typedef struct TranslatorOps {
90
* - When single-stepping is enabled (system-wide or on the current vCPU).
91
* - When too many instructions have been translated.
92
*/
93
-void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
94
- CPUState *cpu, TranslationBlock *tb, int max_insns);
95
+void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
96
+ target_ulong pc, void *host_pc,
97
+ const TranslatorOps *ops, DisasContextBase *db);
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
102
index XXXXXXX..XXXXXXX 100644
103
--- a/accel/tcg/translate-all.c
104
+++ b/accel/tcg/translate-all.c
105
@@ -XXX,XX +XXX,XX @@
106
107
#include "exec/cputlb.h"
108
#include "exec/translate-all.h"
109
+#include "exec/translator.h"
110
#include "qemu/bitmap.h"
111
#include "qemu/qemu-print.h"
112
#include "qemu/timer.h"
113
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
114
TCGProfile *prof = &tcg_ctx->prof;
115
int64_t ti;
116
#endif
117
+ void *host_pc;
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
}
54
}
143
55
144
-void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
145
- CPUState *cpu, TranslationBlock *tb, int max_insns)
146
+void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
147
+ target_ulong pc, void *host_pc,
148
+ const TranslatorOps *ops, DisasContextBase *db)
149
{
150
uint32_t cflags = tb_cflags(tb);
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
--
56
--
562
2.34.1
57
2.34.1
diff view generated by jsdifflib
1
Cache the translation from guest to host address, so we may
1
Although we still can't use ldrd and strd for all operations,
2
use direct loads when we hit on the primary translation page.
2
increase the chances by getting the register allocation correct.
3
3
4
Look up the second translation page only once, during translation.
5
This obviates another lookup of the second page within tb_gen_code
6
after translation.
7
8
Fixes a bug in that plugin_insn_append should be passed the bytes
9
in the original memory order, not bswapped by pieces.
10
11
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
12
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
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
tcg/arm/tcg-target-con-set.h | 7 ++++---
16
accel/tcg/translate-all.c | 23 +++----
7
tcg/arm/tcg-target-con-str.h | 2 ++
17
accel/tcg/translator.c | 126 +++++++++++++++++++++++++++++---------
8
tcg/arm/tcg-target.c.inc | 28 ++++++++++++++++++----------
18
3 files changed, 141 insertions(+), 71 deletions(-)
9
3 files changed, 24 insertions(+), 13 deletions(-)
19
10
20
diff --git a/include/exec/translator.h b/include/exec/translator.h
11
diff --git a/tcg/arm/tcg-target-con-set.h b/tcg/arm/tcg-target-con-set.h
21
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
22
--- a/include/exec/translator.h
13
--- a/tcg/arm/tcg-target-con-set.h
23
+++ b/include/exec/translator.h
14
+++ b/tcg/arm/tcg-target-con-set.h
24
@@ -XXX,XX +XXX,XX @@ typedef enum DisasJumpType {
15
@@ -XXX,XX +XXX,XX @@ C_O0_I2(r, rIN)
25
* Architecture-agnostic disassembly context.
16
C_O0_I2(s, s)
17
C_O0_I2(w, r)
18
C_O0_I3(s, s, s)
19
+C_O0_I3(S, p, s)
20
C_O0_I4(r, r, rI, rI)
21
-C_O0_I4(s, s, s, s)
22
+C_O0_I4(S, p, s, s)
23
C_O1_I1(r, l)
24
C_O1_I1(r, r)
25
C_O1_I1(w, r)
26
@@ -XXX,XX +XXX,XX @@ C_O1_I2(w, w, wZ)
27
C_O1_I3(w, w, w, w)
28
C_O1_I4(r, r, r, rI, rI)
29
C_O1_I4(r, r, rIN, rIK, 0)
30
-C_O2_I1(r, r, l)
31
-C_O2_I2(r, r, l, l)
32
+C_O2_I1(e, p, l)
33
+C_O2_I2(e, p, l, l)
34
C_O2_I2(r, r, r, r)
35
C_O2_I4(r, r, r, r, rIN, rIK)
36
C_O2_I4(r, r, rI, rI, rIN, rIK)
37
diff --git a/tcg/arm/tcg-target-con-str.h b/tcg/arm/tcg-target-con-str.h
38
index XXXXXXX..XXXXXXX 100644
39
--- a/tcg/arm/tcg-target-con-str.h
40
+++ b/tcg/arm/tcg-target-con-str.h
41
@@ -XXX,XX +XXX,XX @@
42
* Define constraint letters for register sets:
43
* REGS(letter, register_mask)
26
*/
44
*/
27
typedef struct DisasContextBase {
45
+REGS('e', ALL_GENERAL_REGS & 0x5555) /* even regs */
28
- const TranslationBlock *tb;
46
REGS('r', ALL_GENERAL_REGS)
29
+ TranslationBlock *tb;
47
REGS('l', ALL_QLOAD_REGS)
30
target_ulong pc_first;
48
REGS('s', ALL_QSTORE_REGS)
31
target_ulong pc_next;
49
+REGS('S', ALL_QSTORE_REGS & 0x5555) /* even qstore */
32
DisasJumpType is_jmp;
50
REGS('w', ALL_VECTOR_REGS)
33
int num_insns;
34
int max_insns;
35
bool singlestep_enabled;
36
-#ifdef CONFIG_USER_ONLY
37
- /*
38
- * Guest address of the last byte of the last protected page.
39
- *
40
- * Pages containing the translated instructions are made non-writable in
41
- * order to achieve consistency in case another thread is modifying the
42
- * code while translate_insn() fetches the instruction bytes piecemeal.
43
- * Such writer threads are blocked on mmap_lock() in page_unprotect().
44
- */
45
- target_ulong page_protect_end;
46
-#endif
47
+ void *host_addr[2];
48
} DisasContextBase;
49
50
/**
51
@@ -XXX,XX +XXX,XX @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest);
52
* the relevant information at translation time.
53
*/
54
55
-#define GEN_TRANSLATOR_LD(fullname, type, load_fn, swap_fn) \
56
- type fullname ## _swap(CPUArchState *env, DisasContextBase *dcbase, \
57
- abi_ptr pc, bool do_swap); \
58
- static inline type fullname(CPUArchState *env, \
59
- DisasContextBase *dcbase, abi_ptr pc) \
60
- { \
61
- return fullname ## _swap(env, dcbase, pc, false); \
62
+uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, abi_ptr pc);
63
+uint16_t translator_lduw(CPUArchState *env, DisasContextBase *db, abi_ptr pc);
64
+uint32_t translator_ldl(CPUArchState *env, DisasContextBase *db, abi_ptr pc);
65
+uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, abi_ptr pc);
66
+
67
+static inline uint16_t
68
+translator_lduw_swap(CPUArchState *env, DisasContextBase *db,
69
+ abi_ptr pc, bool do_swap)
70
+{
71
+ uint16_t ret = translator_lduw(env, db, pc);
72
+ if (do_swap) {
73
+ ret = bswap16(ret);
74
}
75
+ return ret;
76
+}
77
78
-#define FOR_EACH_TRANSLATOR_LD(F) \
79
- F(translator_ldub, uint8_t, cpu_ldub_code, /* no swap */) \
80
- F(translator_lduw, uint16_t, cpu_lduw_code, bswap16) \
81
- F(translator_ldl, uint32_t, cpu_ldl_code, bswap32) \
82
- F(translator_ldq, uint64_t, cpu_ldq_code, bswap64)
83
+static inline uint32_t
84
+translator_ldl_swap(CPUArchState *env, DisasContextBase *db,
85
+ abi_ptr pc, bool do_swap)
86
+{
87
+ uint32_t ret = translator_ldl(env, db, pc);
88
+ if (do_swap) {
89
+ ret = bswap32(ret);
90
+ }
91
+ return ret;
92
+}
93
94
-FOR_EACH_TRANSLATOR_LD(GEN_TRANSLATOR_LD)
95
-
96
-#undef GEN_TRANSLATOR_LD
97
+static inline uint64_t
98
+translator_ldq_swap(CPUArchState *env, DisasContextBase *db,
99
+ abi_ptr pc, bool do_swap)
100
+{
101
+ uint64_t ret = translator_ldq_swap(env, db, pc, false);
102
+ if (do_swap) {
103
+ ret = bswap64(ret);
104
+ }
105
+ return ret;
106
+}
107
51
108
/*
52
/*
109
* Return whether addr is on the same page as where disassembly started.
53
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
110
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
111
index XXXXXXX..XXXXXXX 100644
54
index XXXXXXX..XXXXXXX 100644
112
--- a/accel/tcg/translate-all.c
55
--- a/tcg/arm/tcg-target.c.inc
113
+++ b/accel/tcg/translate-all.c
56
+++ b/tcg/arm/tcg-target.c.inc
114
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
57
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_ld_index(TCGContext *s, MemOp opc,
115
{
58
tcg_out_ld32_r(s, COND_AL, datalo, addrlo, addend);
116
CPUArchState *env = cpu->env_ptr;
59
break;
117
TranslationBlock *tb, *existing_tb;
60
case MO_UQ:
118
- tb_page_addr_t phys_pc, phys_page2;
61
+ /* We used pair allocation for datalo, so already should be aligned. */
119
- target_ulong virt_page2;
62
+ tcg_debug_assert((datalo & 1) == 0);
120
+ tb_page_addr_t phys_pc;
63
+ tcg_debug_assert(datahi == datalo + 1);
121
tcg_insn_unit *gen_code_buf;
64
/* LDRD requires alignment; double-check that. */
122
int gen_code_size, search_size, max_insns;
65
- if (get_alignment_bits(opc) >= MO_64
123
#ifdef CONFIG_PROFILER
66
- && (datalo & 1) == 0 && datahi == datalo + 1) {
124
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
67
+ if (get_alignment_bits(opc) >= MO_64) {
125
tb->flags = flags;
68
/*
126
tb->cflags = cflags;
69
* Rm (the second address op) must not overlap Rt or Rt + 1.
127
tb->trace_vcpu_dstate = *cpu->trace_dstate;
70
* Since datalo is aligned, we can simplify the test via alignment.
128
+ tb->page_addr[0] = phys_pc;
71
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp opc, TCGReg datalo,
129
+ tb->page_addr[1] = -1;
72
tcg_out_ld32_12(s, COND_AL, datalo, addrlo, 0);
130
tcg_ctx->tb_cflags = cflags;
73
break;
131
tb_overflow:
74
case MO_UQ:
132
75
+ /* We used pair allocation for datalo, so already should be aligned. */
133
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
76
+ tcg_debug_assert((datalo & 1) == 0);
134
}
77
+ tcg_debug_assert(datahi == datalo + 1);
135
78
/* LDRD requires alignment; double-check that. */
136
/*
79
- if (get_alignment_bits(opc) >= MO_64
137
- * If the TB is not associated with a physical RAM page then
80
- && (datalo & 1) == 0 && datahi == datalo + 1) {
138
- * it must be a temporary one-insn TB, and we have nothing to do
81
+ if (get_alignment_bits(opc) >= MO_64) {
139
- * except fill in the page_addr[] fields. Return early before
82
tcg_out_ldrd_8(s, COND_AL, datalo, addrlo, 0);
140
- * attempting to link to other TBs or add to the lookup table.
83
} else if (datalo == addrlo) {
141
+ * If the TB is not associated with a physical RAM page then it must be
84
tcg_out_ld32_12(s, COND_AL, datahi, addrlo, 4);
142
+ * a temporary one-insn TB, and we have nothing left to do. Return early
85
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st_index(TCGContext *s, ARMCond cond, MemOp opc,
143
+ * before attempting to link to other TBs or add to the lookup table.
86
tcg_out_st32_r(s, cond, datalo, addrlo, addend);
144
*/
87
break;
145
- if (phys_pc == -1) {
88
case MO_64:
146
- tb->page_addr[0] = tb->page_addr[1] = -1;
89
+ /* We used pair allocation for datalo, so already should be aligned. */
147
+ if (tb->page_addr[0] == -1) {
90
+ tcg_debug_assert((datalo & 1) == 0);
148
return tb;
91
+ tcg_debug_assert(datahi == datalo + 1);
149
}
92
/* STRD requires alignment; double-check that. */
150
93
- if (get_alignment_bits(opc) >= MO_64
151
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
94
- && (datalo & 1) == 0 && datahi == datalo + 1) {
152
*/
95
+ if (get_alignment_bits(opc) >= MO_64) {
153
tcg_tb_insert(tb);
96
tcg_out_strd_r(s, cond, datalo, addrlo, addend);
154
97
} else if (scratch_addend) {
155
- /* check next page if needed */
98
tcg_out_st32_rwb(s, cond, datalo, addend, addrlo);
156
- virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
99
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st_direct(TCGContext *s, MemOp opc, TCGReg datalo,
157
- phys_page2 = -1;
100
tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0);
158
- if ((pc & TARGET_PAGE_MASK) != virt_page2) {
101
break;
159
- phys_page2 = get_page_addr_code(env, virt_page2);
102
case MO_64:
160
- }
103
+ /* We used pair allocation for datalo, so already should be aligned. */
161
/*
104
+ tcg_debug_assert((datalo & 1) == 0);
162
* No explicit memory barrier is required -- tb_link_page() makes the
105
+ tcg_debug_assert(datahi == datalo + 1);
163
* TB visible in a consistent state.
106
/* STRD requires alignment; double-check that. */
164
*/
107
- if (get_alignment_bits(opc) >= MO_64
165
- existing_tb = tb_link_page(tb, phys_pc, phys_page2);
108
- && (datalo & 1) == 0 && datahi == datalo + 1) {
166
+ existing_tb = tb_link_page(tb, tb->page_addr[0], tb->page_addr[1]);
109
+ if (get_alignment_bits(opc) >= MO_64) {
167
/* if the TB already exists, discard what we just translated */
110
tcg_out_strd_8(s, COND_AL, datalo, addrlo, 0);
168
if (unlikely(existing_tb != tb)) {
111
} else {
169
uintptr_t orig_aligned = (uintptr_t)gen_code_buf;
112
tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0);
170
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
113
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
171
index XXXXXXX..XXXXXXX 100644
114
case INDEX_op_qemu_ld_i32:
172
--- a/accel/tcg/translator.c
115
return TARGET_LONG_BITS == 32 ? C_O1_I1(r, l) : C_O1_I2(r, l, l);
173
+++ b/accel/tcg/translator.c
116
case INDEX_op_qemu_ld_i64:
174
@@ -XXX,XX +XXX,XX @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest)
117
- return TARGET_LONG_BITS == 32 ? C_O2_I1(r, r, l) : C_O2_I2(r, r, l, l);
175
return ((db->pc_first ^ dest) & TARGET_PAGE_MASK) == 0;
118
+ return TARGET_LONG_BITS == 32 ? C_O2_I1(e, p, l) : C_O2_I2(e, p, l, l);
176
}
119
case INDEX_op_qemu_st_i32:
177
120
return TARGET_LONG_BITS == 32 ? C_O0_I2(s, s) : C_O0_I3(s, s, s);
178
-static inline void translator_page_protect(DisasContextBase *dcbase,
121
case INDEX_op_qemu_st_i64:
179
- target_ulong pc)
122
- return TARGET_LONG_BITS == 32 ? C_O0_I3(s, s, s) : C_O0_I4(s, s, s, s);
180
-{
123
+ return TARGET_LONG_BITS == 32 ? C_O0_I3(S, p, s) : C_O0_I4(S, p, s, s);
181
-#ifdef CONFIG_USER_ONLY
124
182
- dcbase->page_protect_end = pc | ~TARGET_PAGE_MASK;
125
case INDEX_op_st_vec:
183
- page_protect(pc);
126
return C_O0_I2(w, r);
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
--
127
--
328
2.34.1
128
2.34.1
diff view generated by jsdifflib
1
Map the stack executable if required by default or on demand.
1
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
3
Message-Id: <20220729172141.1789105-2-richard.henderson@linaro.org>
4
---
5
common-user/host/ppc/safe-syscall.inc.S | 107 ++++++++++++++++++++++++
6
1 file changed, 107 insertions(+)
7
create mode 100644 common-user/host/ppc/safe-syscall.inc.S
2
8
3
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
9
diff --git a/common-user/host/ppc/safe-syscall.inc.S b/common-user/host/ppc/safe-syscall.inc.S
4
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
10
new file mode 100644
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
index XXXXXXX..XXXXXXX
6
---
12
--- /dev/null
7
include/elf.h | 1 +
13
+++ b/common-user/host/ppc/safe-syscall.inc.S
8
linux-user/qemu.h | 1 +
14
@@ -XXX,XX +XXX,XX @@
9
linux-user/elfload.c | 19 ++++++++++++++++++-
15
+/*
10
3 files changed, 20 insertions(+), 1 deletion(-)
16
+ * safe-syscall.inc.S : host-specific assembly fragment
11
17
+ * to handle signals occurring at the same time as system calls.
12
diff --git a/include/elf.h b/include/elf.h
18
+ * This is intended to be included by common-user/safe-syscall.S
13
index XXXXXXX..XXXXXXX 100644
19
+ *
14
--- a/include/elf.h
20
+ * Copyright (C) 2022 Linaro, Ltd.
15
+++ b/include/elf.h
21
+ *
16
@@ -XXX,XX +XXX,XX @@ typedef int64_t Elf64_Sxword;
22
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
17
#define PT_LOPROC 0x70000000
23
+ * See the COPYING file in the top-level directory.
18
#define PT_HIPROC 0x7fffffff
24
+ */
19
25
+
20
+#define PT_GNU_STACK (PT_LOOS + 0x474e551)
26
+/*
21
#define PT_GNU_PROPERTY (PT_LOOS + 0x474e553)
27
+ * Standardize on the _CALL_FOO symbols used by GCC:
22
28
+ * Apple XCode does not define _CALL_DARWIN.
23
#define PT_MIPS_REGINFO 0x70000000
29
+ * Clang defines _CALL_ELF (64-bit) but not _CALL_SYSV (32-bit).
24
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
30
+ */
25
index XXXXXXX..XXXXXXX 100644
31
+#if !defined(_CALL_SYSV) && \
26
--- a/linux-user/qemu.h
32
+ !defined(_CALL_DARWIN) && \
27
+++ b/linux-user/qemu.h
33
+ !defined(_CALL_AIX) && \
28
@@ -XXX,XX +XXX,XX @@ struct image_info {
34
+ !defined(_CALL_ELF)
29
uint32_t elf_flags;
35
+# if defined(__APPLE__)
30
int personality;
36
+# define _CALL_DARWIN
31
abi_ulong alignment;
37
+# elif defined(__ELF__) && TCG_TARGET_REG_BITS == 32
32
+ bool exec_stack;
38
+# define _CALL_SYSV
33
39
+# else
34
/* Generic semihosting knows about these pointers. */
40
+# error "Unknown ABI"
35
abi_ulong arg_strings; /* strings for argv */
41
+# endif
36
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
42
+#endif
37
index XXXXXXX..XXXXXXX 100644
43
+
38
--- a/linux-user/elfload.c
44
+#ifndef _CALL_SYSV
39
+++ b/linux-user/elfload.c
45
+# error "Unsupported ABI"
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
46
+#endif
87
+
47
+
88
#include "elf.h"
48
+
89
49
+ .global safe_syscall_base
90
/* We must delay the following stanzas until after "elf.h". */
50
+ .global safe_syscall_start
91
@@ -XXX,XX +XXX,XX @@ static abi_ulong setup_arg_pages(struct linux_binprm *bprm,
51
+ .global safe_syscall_end
92
struct image_info *info)
52
+ .type safe_syscall_base, @function
93
{
53
+
94
abi_ulong size, error, guard;
54
+ .text
95
+ int prot;
55
+
96
56
+ /*
97
size = guest_stack_size;
57
+ * This is the entry point for making a system call. The calling
98
if (size < STACK_LOWER_LIMIT) {
58
+ * convention here is that of a C varargs function with the
99
@@ -XXX,XX +XXX,XX @@ static abi_ulong setup_arg_pages(struct linux_binprm *bprm,
59
+ * first argument an 'int *' to the signal_pending flag, the
100
guard = qemu_real_host_page_size();
60
+ * second one the system call number (as a 'long'), and all further
101
}
61
+ * arguments being syscall arguments (also 'long').
102
62
+ */
103
- error = target_mmap(0, size + guard, PROT_READ | PROT_WRITE,
63
+safe_syscall_base:
104
+ prot = PROT_READ | PROT_WRITE;
64
+ .cfi_startproc
105
+ if (info->exec_stack) {
65
+ stwu 1, -8(1)
106
+ prot |= PROT_EXEC;
66
+ .cfi_def_cfa_offset 8
107
+ }
67
+ stw 30, 4(1)
108
+ error = target_mmap(0, size + guard, prot,
68
+ .cfi_offset 30, -4
109
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
69
+
110
if (error == -1) {
70
+ /*
111
perror("mmap stack");
71
+ * We enter with r3 == &signal_pending
112
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
72
+ * r4 == syscall number
113
*/
73
+ * r5 ... r10 == syscall arguments
114
loaddr = -1, hiaddr = 0;
74
+ * and return the result in r3
115
info->alignment = 0;
75
+ * and the syscall instruction needs
116
+ info->exec_stack = EXSTACK_DEFAULT;
76
+ * r0 == syscall number
117
for (i = 0; i < ehdr->e_phnum; ++i) {
77
+ * r3 ... r8 == syscall arguments
118
struct elf_phdr *eppnt = phdr + i;
78
+ * and returns the result in r3
119
if (eppnt->p_type == PT_LOAD) {
79
+ * Shuffle everything around appropriately.
120
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
80
+ */
121
if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) {
81
+ mr 30, 3 /* signal_pending */
122
goto exit_errmsg;
82
+ mr 0, 4 /* syscall number */
123
}
83
+ mr 3, 5 /* syscall arguments */
124
+ } else if (eppnt->p_type == PT_GNU_STACK) {
84
+ mr 4, 6
125
+ info->exec_stack = eppnt->p_flags & PF_X;
85
+ mr 5, 7
126
}
86
+ mr 6, 8
127
}
87
+ mr 7, 9
128
88
+ mr 8, 10
89
+
90
+ /*
91
+ * This next sequence of code works in conjunction with the
92
+ * rewind_if_safe_syscall_function(). If a signal is taken
93
+ * and the interrupted PC is anywhere between 'safe_syscall_start'
94
+ * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
95
+ * The code sequence must therefore be able to cope with this, and
96
+ * the syscall instruction must be the final one in the sequence.
97
+ */
98
+safe_syscall_start:
99
+ /* if signal_pending is non-zero, don't do the call */
100
+ lwz 12, 0(30)
101
+ cmpwi 0, 12, 0
102
+ bne- 2f
103
+ sc
104
+safe_syscall_end:
105
+ /* code path when we did execute the syscall */
106
+ lwz 30, 4(1) /* restore r30 */
107
+ addi 1, 1, 8 /* restore stack */
108
+ .cfi_restore 30
109
+ .cfi_def_cfa_offset 0
110
+ bnslr+ /* return on success */
111
+ b safe_syscall_set_errno_tail
112
+
113
+ /* code path when we didn't execute the syscall */
114
+2: lwz 30, 4(1)
115
+ addi 1, 1, 8
116
+ addi 3, 0, QEMU_ERESTARTSYS
117
+ b safe_syscall_set_errno_tail
118
+
119
+ .cfi_endproc
120
+
121
+ .size safe_syscall_base, .-safe_syscall_base
129
--
122
--
130
2.34.1
123
2.34.1
diff view generated by jsdifflib
1
Right now the translator stops right *after* the end of a page, which
1
This commit re-enables ppc32 as a linux-user host,
2
breaks reporting of fault locations when the last instruction of a
2
as existance of the directory is noted by configure.
3
multi-insn translation block crosses a page boundary.
4
3
5
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1155
4
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1097
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>
6
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
7
Message-Id: <20220729172141.1789105-3-richard.henderson@linaro.org>
10
---
8
---
11
target/riscv/translate.c | 17 +++++--
9
linux-user/include/host/ppc/host-signal.h | 39 +++++++++++++++++++++++
12
tests/tcg/riscv64/noexec.c | 79 +++++++++++++++++++++++++++++++
10
1 file changed, 39 insertions(+)
13
tests/tcg/riscv64/Makefile.target | 1 +
11
create mode 100644 linux-user/include/host/ppc/host-signal.h
14
3 files changed, 93 insertions(+), 4 deletions(-)
15
create mode 100644 tests/tcg/riscv64/noexec.c
16
12
17
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
13
diff --git a/linux-user/include/host/ppc/host-signal.h b/linux-user/include/host/ppc/host-signal.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/riscv/translate.c
20
+++ b/target/riscv/translate.c
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
14
new file mode 100644
49
index XXXXXXX..XXXXXXX
15
index XXXXXXX..XXXXXXX
50
--- /dev/null
16
--- /dev/null
51
+++ b/tests/tcg/riscv64/noexec.c
17
+++ b/linux-user/include/host/ppc/host-signal.h
52
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@
53
+#include "../multiarch/noexec.c.inc"
19
+/*
20
+ * host-signal.h: signal info dependent on the host architecture
21
+ *
22
+ * Copyright (c) 2022 Linaro Ltd.
23
+ *
24
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
25
+ * See the COPYING file in the top-level directory.
26
+ */
54
+
27
+
55
+static void *arch_mcontext_pc(const mcontext_t *ctx)
28
+#ifndef PPC_HOST_SIGNAL_H
29
+#define PPC_HOST_SIGNAL_H
30
+
31
+#include <asm/ptrace.h>
32
+
33
+/* The third argument to a SA_SIGINFO handler is ucontext_t. */
34
+typedef ucontext_t host_sigcontext;
35
+
36
+static inline uintptr_t host_signal_pc(host_sigcontext *uc)
56
+{
37
+{
57
+ return (void *)ctx->__gregs[REG_PC];
38
+ return uc->uc_mcontext.regs->nip;
58
+}
39
+}
59
+
40
+
60
+static int arch_mcontext_arg(const mcontext_t *ctx)
41
+static inline void host_signal_set_pc(host_sigcontext *uc, uintptr_t pc)
61
+{
42
+{
62
+ return ctx->__gregs[REG_A0];
43
+ uc->uc_mcontext.regs->nip = pc;
63
+}
44
+}
64
+
45
+
65
+static void arch_flush(void *p, int len)
46
+static inline void *host_signal_mask(host_sigcontext *uc)
66
+{
47
+{
67
+ __builtin___clear_cache(p, p + len);
48
+ return &uc->uc_sigmask;
68
+}
49
+}
69
+
50
+
70
+extern char noexec_1[];
51
+static inline bool host_signal_write(siginfo_t *info, host_sigcontext *uc)
71
+extern char noexec_2[];
52
+{
72
+extern char noexec_end[];
53
+ return uc->uc_mcontext.regs->trap != 0x400
54
+ && (uc->uc_mcontext.regs->dsisr & 0x02000000);
55
+}
73
+
56
+
74
+asm(".option push\n"
57
+#endif
75
+ ".option norvc\n"
76
+ "noexec_1:\n"
77
+ " li a0,1\n" /* a0 is 0 on entry, set 1. */
78
+ "noexec_2:\n"
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
134
--- a/tests/tcg/riscv64/Makefile.target
135
+++ b/tests/tcg/riscv64/Makefile.target
136
@@ -XXX,XX +XXX,XX @@
137
138
VPATH += $(SRC_PATH)/tests/tcg/riscv64
139
TESTS += test-div
140
+TESTS += noexec
141
--
58
--
142
2.34.1
59
2.34.1
diff view generated by jsdifflib
1
This bit is not saved across interrupts, so we must
1
Marking helpers __attribute__((noinline)) prevents an issue
2
delay delivering the interrupt until the skip has
2
with GCC's ipa-split pass under --enable-lto.
3
been processed.
4
3
5
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1118
4
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1454
6
Reviewed-by: Michael Rolnik <mrolnik@gmail.com>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Tested-by: Idan Horowitz <idan.horowitz@gmail.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
8
---
10
target/avr/helper.c | 9 +++++++++
9
include/exec/helper-proto.h | 32 ++++++++++++++++++++++++--------
11
target/avr/translate.c | 26 ++++++++++++++++++++++----
10
1 file changed, 24 insertions(+), 8 deletions(-)
12
2 files changed, 31 insertions(+), 4 deletions(-)
13
11
14
diff --git a/target/avr/helper.c b/target/avr/helper.c
12
diff --git a/include/exec/helper-proto.h b/include/exec/helper-proto.h
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
16
--- a/target/avr/helper.c
14
--- a/include/exec/helper-proto.h
17
+++ b/target/avr/helper.c
15
+++ b/include/exec/helper-proto.h
18
@@ -XXX,XX +XXX,XX @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
16
@@ -XXX,XX +XXX,XX @@
19
AVRCPU *cpu = AVR_CPU(cs);
17
20
CPUAVRState *env = &cpu->env;
18
#include "exec/helper-head.h"
21
19
22
+ /*
20
+/*
23
+ * We cannot separate a skip from the next instruction,
21
+ * Work around an issue with --enable-lto, in which GCC's ipa-split pass
24
+ * as the skip would not be preserved across the interrupt.
22
+ * decides to split out the noreturn code paths that raise an exception,
25
+ * Separating the two insn normally only happens at page boundaries.
23
+ * taking the __builtin_return_address() along into the new function,
26
+ */
24
+ * where it no longer computes a value that returns to TCG generated code.
27
+ if (env->skip) {
25
+ * Despite the name, the noinline attribute affects splitter, so this
28
+ return false;
26
+ * prevents the optimization in question. Given that helpers should not
29
+ }
27
+ * otherwise be called directly, this should have any other visible effect.
28
+ *
29
+ * See https://gitlab.com/qemu-project/qemu/-/issues/1454
30
+ */
31
+#define DEF_HELPER_ATTR __attribute__((noinline))
30
+
32
+
31
if (interrupt_request & CPU_INTERRUPT_RESET) {
33
#define DEF_HELPER_FLAGS_0(name, flags, ret) \
32
if (cpu_interrupts_enabled(env)) {
34
-dh_ctype(ret) HELPER(name) (void);
33
cs->exception_index = EXCP_RESET;
35
+dh_ctype(ret) HELPER(name) (void) DEF_HELPER_ATTR;
34
diff --git a/target/avr/translate.c b/target/avr/translate.c
36
35
index XXXXXXX..XXXXXXX 100644
37
#define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
36
--- a/target/avr/translate.c
38
-dh_ctype(ret) HELPER(name) (dh_ctype(t1));
37
+++ b/target/avr/translate.c
39
+dh_ctype(ret) HELPER(name) (dh_ctype(t1)) DEF_HELPER_ATTR;
38
@@ -XXX,XX +XXX,XX @@ static void avr_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
40
39
if (skip_label) {
41
#define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \
40
canonicalize_skip(ctx);
42
-dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2));
41
gen_set_label(skip_label);
43
+dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2)) DEF_HELPER_ATTR;
42
- if (ctx->base.is_jmp == DISAS_NORETURN) {
44
43
+
45
#define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \
44
+ switch (ctx->base.is_jmp) {
46
-dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3));
45
+ case DISAS_NORETURN:
47
+dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), \
46
ctx->base.is_jmp = DISAS_CHAIN;
48
+ dh_ctype(t3)) DEF_HELPER_ATTR;
47
+ break;
49
48
+ case DISAS_NEXT:
50
#define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
49
+ if (ctx->base.tb->flags & TB_FLAGS_SKIP) {
51
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
50
+ ctx->base.is_jmp = DISAS_TOO_MANY;
52
- dh_ctype(t4));
51
+ }
53
+ dh_ctype(t4)) DEF_HELPER_ATTR;
52
+ break;
54
53
+ default:
55
#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
54
+ break;
56
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
55
}
57
- dh_ctype(t4), dh_ctype(t5));
56
}
58
+ dh_ctype(t4), dh_ctype(t5)) DEF_HELPER_ATTR;
57
59
58
@@ -XXX,XX +XXX,XX @@ static void avr_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
60
#define DEF_HELPER_FLAGS_6(name, flags, ret, t1, t2, t3, t4, t5, t6) \
59
{
61
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
60
DisasContext *ctx = container_of(dcbase, DisasContext, base);
62
- dh_ctype(t4), dh_ctype(t5), dh_ctype(t6));
61
bool nonconst_skip = canonicalize_skip(ctx);
63
+ dh_ctype(t4), dh_ctype(t5), \
62
+ /*
64
+ dh_ctype(t6)) DEF_HELPER_ATTR;
63
+ * Because we disable interrupts while env->skip is set,
65
64
+ * we must return to the main loop to re-evaluate afterward.
66
#define DEF_HELPER_FLAGS_7(name, flags, ret, t1, t2, t3, t4, t5, t6, t7) \
65
+ */
67
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
66
+ bool force_exit = ctx->base.tb->flags & TB_FLAGS_SKIP;
68
dh_ctype(t4), dh_ctype(t5), dh_ctype(t6), \
67
69
- dh_ctype(t7));
68
switch (ctx->base.is_jmp) {
70
+ dh_ctype(t7)) DEF_HELPER_ATTR;
69
case DISAS_NORETURN:
71
70
@@ -XXX,XX +XXX,XX @@ static void avr_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
72
#define IN_HELPER_PROTO
71
case DISAS_NEXT:
73
72
case DISAS_TOO_MANY:
74
@@ -XXX,XX +XXX,XX @@ dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
73
case DISAS_CHAIN:
75
#undef DEF_HELPER_FLAGS_5
74
- if (!nonconst_skip) {
76
#undef DEF_HELPER_FLAGS_6
75
+ if (!nonconst_skip && !force_exit) {
77
#undef DEF_HELPER_FLAGS_7
76
/* Note gen_goto_tb checks singlestep. */
78
+#undef DEF_HELPER_ATTR
77
gen_goto_tb(ctx, 1, ctx->npc);
79
78
break;
80
#endif /* HELPER_PROTO_H */
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
--
81
--
94
2.34.1
82
2.34.1
95
83
96
84
diff view generated by jsdifflib
1
We cannot deliver two interrupts simultaneously;
1
Reuse the decodetree based disassembler from
2
the first interrupt handler must execute first.
2
target/loongarch/ for tcg/loongarch64/.
3
3
4
Reviewed-by: Michael Rolnik <mrolnik@gmail.com>
4
The generation of decode-insns.c.inc into ./libcommon.fa.p/ could
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
eventually result in conflict, if any other host requires the same
6
trick, but this is good enough for now.
7
8
Reviewed-by: WANG Xuerui <git@xen0n.name>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
11
---
8
target/avr/helper.c | 9 +++------
12
disas.c | 2 ++
9
1 file changed, 3 insertions(+), 6 deletions(-)
13
target/loongarch/meson.build | 3 ++-
14
2 files changed, 4 insertions(+), 1 deletion(-)
10
15
11
diff --git a/target/avr/helper.c b/target/avr/helper.c
16
diff --git a/disas.c b/disas.c
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/target/avr/helper.c
18
--- a/disas.c
14
+++ b/target/avr/helper.c
19
+++ b/disas.c
15
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static void initialize_debug_host(CPUDebug *s)
16
21
s->info.cap_insn_split = 6;
17
bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
22
#elif defined(__hppa__)
18
{
23
s->info.print_insn = print_insn_hppa;
19
- bool ret = false;
24
+#elif defined(__loongarch__)
20
AVRCPU *cpu = AVR_CPU(cs);
25
+ s->info.print_insn = print_insn_loongarch;
21
CPUAVRState *env = &cpu->env;
26
#endif
22
23
@@ -XXX,XX +XXX,XX @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
24
avr_cpu_do_interrupt(cs);
25
26
cs->interrupt_request &= ~CPU_INTERRUPT_RESET;
27
-
28
- ret = true;
29
+ return true;
30
}
31
}
32
if (interrupt_request & CPU_INTERRUPT_HARD) {
33
@@ -XXX,XX +XXX,XX @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
34
if (!env->intsrc) {
35
cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
36
}
37
-
38
- ret = true;
39
+ return true;
40
}
41
}
42
- return ret;
43
+ return false;
44
}
27
}
45
28
46
void avr_cpu_do_interrupt(CPUState *cs)
29
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/loongarch/meson.build
32
+++ b/target/loongarch/meson.build
33
@@ -XXX,XX +XXX,XX @@ gen = decodetree.process('insns.decode')
34
loongarch_ss = ss.source_set()
35
loongarch_ss.add(files(
36
'cpu.c',
37
- 'disas.c',
38
))
39
loongarch_tcg_ss = ss.source_set()
40
loongarch_tcg_ss.add(gen)
41
@@ -XXX,XX +XXX,XX @@ loongarch_softmmu_ss.add(files(
42
'iocsr_helper.c',
43
))
44
45
+common_ss.add(when: 'CONFIG_LOONGARCH_DIS', if_true: [files('disas.c'), gen])
46
+
47
loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss])
48
49
target_arch += {'loongarch': loongarch_ss}
47
--
50
--
48
2.34.1
51
2.34.1
49
52
50
53
diff view generated by jsdifflib
1
These will be useful in properly ending the TB.
1
While jirl shares the same instruction format as bne etc,
2
it is not assembled the same. In particular, rd is printed
3
first not second and the immediate is not pc-relative.
2
4
3
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
5
Decode into the arg_rr_i structure, which prints correctly.
4
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
6
This changes the "offs" member to "imm", to update translate.
5
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
7
8
Reviewed-by: WANG Xuerui <git@xen0n.name>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
10
---
8
target/riscv/translate.c | 10 +++++++++-
11
target/loongarch/insns.decode | 3 ++-
9
1 file changed, 9 insertions(+), 1 deletion(-)
12
target/loongarch/disas.c | 2 +-
13
target/loongarch/insn_trans/trans_branch.c.inc | 2 +-
14
3 files changed, 4 insertions(+), 3 deletions(-)
10
15
11
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
16
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/target/riscv/translate.c
18
--- a/target/loongarch/insns.decode
14
+++ b/target/riscv/translate.c
19
+++ b/target/loongarch/insns.decode
15
@@ -XXX,XX +XXX,XX @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
20
@@ -XXX,XX +XXX,XX @@
16
/* Include decoders for factored-out extensions */
21
@rr_ui12 .... ...... imm:12 rj:5 rd:5 &rr_i
17
#include "decode-XVentanaCondOps.c.inc"
22
@rr_i14s2 .... .... .............. rj:5 rd:5 &rr_i imm=%i14s2
18
23
@rr_i16 .... .. imm:s16 rj:5 rd:5 &rr_i
19
+/* The specification allows for longer insns, but not supported by qemu. */
24
+@rr_i16s2 .... .. ................ rj:5 rd:5 &rr_i imm=%offs16
20
+#define MAX_INSN_LEN 4
25
@hint_r_i12 .... ...... imm:s12 rj:5 hint:5 &hint_r_i
21
+
26
@rrr_sa2p1 .... ........ ... .. rk:5 rj:5 rd:5 &rrr_sa sa=%sa2p1
22
+static inline int insn_len(uint16_t first_word)
27
@rrr_sa2 .... ........ ... sa:2 rk:5 rj:5 rd:5 &rrr_sa
23
+{
28
@@ -XXX,XX +XXX,XX @@ beqz 0100 00 ................ ..... ..... @r_offs21
24
+ return (first_word & 3) == 3 ? 4 : 2;
29
bnez 0100 01 ................ ..... ..... @r_offs21
25
+}
30
bceqz 0100 10 ................ 00 ... ..... @c_offs21
26
+
31
bcnez 0100 10 ................ 01 ... ..... @c_offs21
27
static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
32
-jirl 0100 11 ................ ..... ..... @rr_offs16
28
{
33
+jirl 0100 11 ................ ..... ..... @rr_i16s2
29
/*
34
b 0101 00 .......................... @offs26
30
@@ -XXX,XX +XXX,XX @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
35
bl 0101 01 .......................... @offs26
31
};
36
beq 0101 10 ................ ..... ..... @rr_offs16
32
37
diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
33
/* Check for compressed insn */
38
index XXXXXXX..XXXXXXX 100644
34
- if (extract16(opcode, 0, 2) != 3) {
39
--- a/target/loongarch/disas.c
35
+ if (insn_len(opcode) == 2) {
40
+++ b/target/loongarch/disas.c
36
if (!has_ext(ctx, RVC)) {
41
@@ -XXX,XX +XXX,XX @@ INSN(beqz, r_offs)
37
gen_exception_illegal(ctx);
42
INSN(bnez, r_offs)
38
} else {
43
INSN(bceqz, c_offs)
44
INSN(bcnez, c_offs)
45
-INSN(jirl, rr_offs)
46
+INSN(jirl, rr_i)
47
INSN(b, offs)
48
INSN(bl, offs)
49
INSN(beq, rr_offs)
50
diff --git a/target/loongarch/insn_trans/trans_branch.c.inc b/target/loongarch/insn_trans/trans_branch.c.inc
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/loongarch/insn_trans/trans_branch.c.inc
53
+++ b/target/loongarch/insn_trans/trans_branch.c.inc
54
@@ -XXX,XX +XXX,XX @@ static bool trans_jirl(DisasContext *ctx, arg_jirl *a)
55
TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
56
TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
57
58
- tcg_gen_addi_tl(cpu_pc, src1, a->offs);
59
+ tcg_gen_addi_tl(cpu_pc, src1, a->imm);
60
tcg_gen_movi_tl(dest, ctx->base.pc_next + 4);
61
gen_set_gpr(a->rd, dest, EXT_NONE);
62
tcg_gen_lookup_and_goto_ptr();
39
--
63
--
40
2.34.1
64
2.34.1
diff view generated by jsdifflib
1
From: Ilya Leoshkevich <iii@linux.ibm.com>
1
Print both the raw field and the resolved pc-relative
2
address, as we do for branches.
2
3
3
Right now translator stops right *after* the end of a page, which
4
Reviewed-by: WANG Xuerui <git@xen0n.name>
4
breaks reporting of fault locations when the last instruction of a
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>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
---
6
---
12
target/s390x/tcg/translate.c | 15 +++-
7
target/loongarch/disas.c | 37 +++++++++++++++++++++++++++++++++----
13
tests/tcg/s390x/noexec.c | 106 +++++++++++++++++++++++
8
1 file changed, 33 insertions(+), 4 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
9
20
diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c
10
diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
21
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
22
--- a/target/s390x/tcg/translate.c
12
--- a/target/loongarch/disas.c
23
+++ b/target/s390x/tcg/translate.c
13
+++ b/target/loongarch/disas.c
24
@@ -XXX,XX +XXX,XX @@ static void s390x_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
14
@@ -XXX,XX +XXX,XX @@ INSN(fsel, fffc)
25
dc->insn_start = tcg_last_op();
15
INSN(addu16i_d, rr_i)
26
}
16
INSN(lu12i_w, r_i)
27
17
INSN(lu32i_d, r_i)
28
+static target_ulong get_next_pc(CPUS390XState *env, DisasContext *s,
18
-INSN(pcaddi, r_i)
29
+ uint64_t pc)
19
-INSN(pcalau12i, r_i)
30
+{
20
-INSN(pcaddu12i, r_i)
31
+ uint64_t insn = ld_code2(env, s, pc);
21
-INSN(pcaddu18i, r_i)
22
INSN(ll_w, rr_i)
23
INSN(sc_w, rr_i)
24
INSN(ll_d, rr_i)
25
@@ -XXX,XX +XXX,XX @@ static bool trans_fcmp_cond_##suffix(DisasContext *ctx, \
26
27
FCMP_INSN(s)
28
FCMP_INSN(d)
32
+
29
+
33
+ return pc + get_ilen((insn >> 8) & 0xff);
30
+#define PCADD_INSN(name) \
31
+static bool trans_##name(DisasContext *ctx, arg_##name *a) \
32
+{ \
33
+ output(ctx, #name, "r%d, %d # 0x%" PRIx64, \
34
+ a->rd, a->imm, gen_##name(ctx->pc, a->imm)); \
35
+ return true; \
34
+}
36
+}
35
+
37
+
36
static void s390x_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
38
+static uint64_t gen_pcaddi(uint64_t pc, int imm)
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
+{
39
+{
63
+ return (void *)ctx->psw.addr;
40
+ return pc + (imm << 2);
64
+}
41
+}
65
+
42
+
66
+static int arch_mcontext_arg(const mcontext_t *ctx)
43
+static uint64_t gen_pcalau12i(uint64_t pc, int imm)
67
+{
44
+{
68
+ return ctx->gregs[2];
45
+ return (pc + (imm << 12)) & ~0xfff;
69
+}
46
+}
70
+
47
+
71
+static void arch_flush(void *p, int len)
48
+static uint64_t gen_pcaddu12i(uint64_t pc, int imm)
72
+{
49
+{
50
+ return pc + (imm << 12);
73
+}
51
+}
74
+
52
+
75
+extern char noexec_1[];
53
+static uint64_t gen_pcaddu18i(uint64_t pc, int imm)
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
+{
54
+{
99
+ struct noexec_test noexec_tests[] = {
55
+ return pc + ((uint64_t)(imm) << 18);
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
+}
56
+}
215
+
57
+
216
+static void handle_segv(int sig, siginfo_t *info, void *ucontext)
58
+PCADD_INSN(pcaddi)
217
+{
59
+PCADD_INSN(pcalau12i)
218
+ const struct noexec_test *test = current_noexec_test;
60
+PCADD_INSN(pcaddu12i)
219
+ const mcontext_t *mc = &((ucontext_t *)ucontext)->uc_mcontext;
61
+PCADD_INSN(pcaddu18i)
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
+ }
237
+
238
+ pc = arch_mcontext_pc(mc);
239
+ expected_pc = page_base + test->expected_pc_ofs;
240
+ if (pc != expected_pc) {
241
+ printf("[ FAILED ] wrong pc (%p != %p)\n", pc, expected_pc);
242
+ exit(EXIT_FAILURE);
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
+ }
255
+}
256
+
257
+static void test_noexec_1(const struct noexec_test *test)
258
+{
259
+ void *start = page_base + test->page_ofs;
260
+ void (*fn)(int arg) = page_base + test->entry_ofs;
261
+
262
+ memcpy(start, test->test_code, test->test_len);
263
+ arch_flush(start, test->test_len);
264
+
265
+ /* Trigger TB creation in order to test invalidation. */
266
+ fn(0);
267
+
268
+ if (mprotect(page_base, page_size, PROT_NONE) < 0) {
269
+ handle_err("mprotect");
270
+ }
271
+
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
--
62
--
323
2.34.1
63
2.34.1
diff view generated by jsdifflib
1
The current implementation is a no-op, simply returning addr.
1
From: Rui Wang <wangrui@loongson.cn>
2
This is incorrect, because we ought to be checking the page
3
permissions for execution.
4
2
5
Make get_page_addr_code inline for both implementations.
3
diff:
4
Imm Before After
5
0000000000000000 addi.w rd, zero, 0 addi.w rd, zero, 0
6
lu52i.d rd, zero, 0
7
00000000fffff800 lu12i.w rd, -1 addi.w rd, zero, -2048
8
ori rd, rd, 2048 lu32i.d rd, 0
9
lu32i.d rd, 0
6
10
7
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
11
Reviewed-by: WANG Xuerui <git@xen0n.name>
8
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
12
Signed-off-by: Rui Wang <wangrui@loongson.cn>
9
Acked-by: Alistair Francis <alistair.francis@wdc.com>
13
Message-Id: <20221107144713.845550-1-wangrui@loongson.cn>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
---
15
---
12
include/exec/exec-all.h | 85 ++++++++++++++---------------------------
16
tcg/loongarch64/tcg-target.c.inc | 35 +++++++++++---------------------
13
accel/tcg/cputlb.c | 5 ---
17
1 file changed, 12 insertions(+), 23 deletions(-)
14
accel/tcg/user-exec.c | 14 +++++++
15
3 files changed, 42 insertions(+), 62 deletions(-)
16
18
17
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
19
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
18
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
19
--- a/include/exec/exec-all.h
21
--- a/tcg/loongarch64/tcg-target.c.inc
20
+++ b/include/exec/exec-all.h
22
+++ b/tcg/loongarch64/tcg-target.c.inc
21
@@ -XXX,XX +XXX,XX @@ struct MemoryRegionSection *iotlb_to_section(CPUState *cpu,
23
@@ -XXX,XX +XXX,XX @@ static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
22
hwaddr index, MemTxAttrs attrs);
24
return true;
23
#endif
24
25
-#if defined(CONFIG_USER_ONLY)
26
-void mmap_lock(void);
27
-void mmap_unlock(void);
28
-bool have_mmap_lock(void);
29
-
30
/**
31
- * get_page_addr_code() - user-mode version
32
+ * get_page_addr_code_hostp()
33
* @env: CPUArchState
34
* @addr: guest virtual address of guest code
35
*
36
- * Returns @addr.
37
+ * See get_page_addr_code() (full-system version) for documentation on the
38
+ * return value.
39
+ *
40
+ * Sets *@hostp (when @hostp is non-NULL) as follows.
41
+ * If the return value is -1, sets *@hostp to NULL. Otherwise, sets *@hostp
42
+ * to the host address where @addr's content is kept.
43
+ *
44
+ * Note: this function can trigger an exception.
45
+ */
46
+tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
47
+ void **hostp);
48
+
49
+/**
50
+ * get_page_addr_code()
51
+ * @env: CPUArchState
52
+ * @addr: guest virtual address of guest code
53
+ *
54
+ * If we cannot translate and execute from the entire RAM page, or if
55
+ * the region is not backed by RAM, returns -1. Otherwise, returns the
56
+ * ram_addr_t corresponding to the guest code at @addr.
57
+ *
58
+ * Note: this function can trigger an exception.
59
*/
60
static inline tb_page_addr_t get_page_addr_code(CPUArchState *env,
61
target_ulong addr)
62
{
63
- return addr;
64
+ return get_page_addr_code_hostp(env, addr, NULL);
65
}
25
}
66
26
67
-/**
27
-static bool imm_part_needs_loading(bool high_bits_are_ones,
68
- * get_page_addr_code_hostp() - user-mode version
28
- tcg_target_long part)
69
- * @env: CPUArchState
70
- * @addr: guest virtual address of guest code
71
- *
72
- * Returns @addr.
73
- *
74
- * If @hostp is non-NULL, sets *@hostp to the host address where @addr's content
75
- * is kept.
76
- */
77
-static inline tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env,
78
- target_ulong addr,
79
- void **hostp)
80
-{
29
-{
81
- if (hostp) {
30
- if (high_bits_are_ones) {
82
- *hostp = g2h_untagged(addr);
31
- return part != -1;
32
- } else {
33
- return part != 0;
83
- }
34
- }
84
- return addr;
85
-}
86
+#if defined(CONFIG_USER_ONLY)
87
+void mmap_lock(void);
88
+void mmap_unlock(void);
89
+bool have_mmap_lock(void);
90
91
/**
92
* adjust_signal_pc:
93
@@ -XXX,XX +XXX,XX @@ G_NORETURN void cpu_loop_exit_sigbus(CPUState *cpu, target_ulong addr,
94
static inline void mmap_lock(void) {}
95
static inline void mmap_unlock(void) {}
96
97
-/**
98
- * get_page_addr_code() - full-system version
99
- * @env: CPUArchState
100
- * @addr: guest virtual address of guest code
101
- *
102
- * If we cannot translate and execute from the entire RAM page, or if
103
- * the region is not backed by RAM, returns -1. Otherwise, returns the
104
- * ram_addr_t corresponding to the guest code at @addr.
105
- *
106
- * Note: this function can trigger an exception.
107
- */
108
-tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr);
109
-
110
-/**
111
- * get_page_addr_code_hostp() - full-system version
112
- * @env: CPUArchState
113
- * @addr: guest virtual address of guest code
114
- *
115
- * See get_page_addr_code() (full-system version) for documentation on the
116
- * return value.
117
- *
118
- * Sets *@hostp (when @hostp is non-NULL) as follows.
119
- * If the return value is -1, sets *@hostp to NULL. Otherwise, sets *@hostp
120
- * to the host address where @addr's content is kept.
121
- *
122
- * Note: this function can trigger an exception.
123
- */
124
-tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
125
- void **hostp);
126
-
127
void tlb_reset_dirty(CPUState *cpu, ram_addr_t start1, ram_addr_t length);
128
void tlb_set_dirty(CPUState *cpu, target_ulong vaddr);
129
130
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/accel/tcg/cputlb.c
133
+++ b/accel/tcg/cputlb.c
134
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
135
return qemu_ram_addr_from_host_nofail(p);
136
}
137
138
-tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
139
-{
140
- return get_page_addr_code_hostp(env, addr, NULL);
141
-}
35
-}
142
-
36
-
143
static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size,
37
/* Loads a 32-bit immediate into rd, sign-extended. */
144
CPUIOTLBEntry *iotlbentry, uintptr_t retaddr)
38
static void tcg_out_movi_i32(TCGContext *s, TCGReg rd, int32_t val)
145
{
39
{
146
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
40
@@ -XXX,XX +XXX,XX @@ static void tcg_out_movi_i32(TCGContext *s, TCGReg rd, int32_t val)
147
index XXXXXXX..XXXXXXX 100644
41
tcg_target_long hi12 = sextreg(val, 12, 20);
148
--- a/accel/tcg/user-exec.c
42
149
+++ b/accel/tcg/user-exec.c
43
/* Single-instruction cases. */
150
@@ -XXX,XX +XXX,XX @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
44
- if (lo == val) {
151
return size ? g2h(env_cpu(env), addr) : NULL;
45
- /* val fits in simm12: addi.w rd, zero, val */
46
- tcg_out_opc_addi_w(s, rd, TCG_REG_ZERO, val);
47
- return;
48
- }
49
- if (0x800 <= val && val <= 0xfff) {
50
+ if (hi12 == 0) {
51
/* val fits in uimm12: ori rd, zero, val */
52
tcg_out_opc_ori(s, rd, TCG_REG_ZERO, val);
53
return;
54
}
55
+ if (hi12 == sextreg(lo, 12, 20)) {
56
+ /* val fits in simm12: addi.w rd, zero, val */
57
+ tcg_out_opc_addi_w(s, rd, TCG_REG_ZERO, val);
58
+ return;
59
+ }
60
61
/* High bits must be set; load with lu12i.w + optional ori. */
62
tcg_out_opc_lu12i_w(s, rd, hi12);
63
@@ -XXX,XX +XXX,XX @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
64
65
intptr_t pc_offset;
66
tcg_target_long val_lo, val_hi, pc_hi, offset_hi;
67
- tcg_target_long hi32, hi52;
68
- bool rd_high_bits_are_ones;
69
+ tcg_target_long hi12, hi32, hi52;
70
71
/* Value fits in signed i32. */
72
if (type == TCG_TYPE_I32 || val == (int32_t)val) {
73
@@ -XXX,XX +XXX,XX @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
74
return;
75
}
76
77
+ hi12 = sextreg(val, 12, 20);
78
hi32 = sextreg(val, 32, 20);
79
hi52 = sextreg(val, 52, 12);
80
81
/* Single cu52i.d case. */
82
- if (ctz64(val) >= 52) {
83
+ if ((hi52 != 0) && (ctz64(val) >= 52)) {
84
tcg_out_opc_cu52i_d(s, rd, TCG_REG_ZERO, hi52);
85
return;
86
}
87
88
/* Slow path. Initialize the low 32 bits, then concat high bits. */
89
tcg_out_movi_i32(s, rd, val);
90
- rd_high_bits_are_ones = (int32_t)val < 0;
91
92
- if (imm_part_needs_loading(rd_high_bits_are_ones, hi32)) {
93
+ /* Load hi32 and hi52 explicitly when they are unexpected values. */
94
+ if (hi32 != sextreg(hi12, 20, 20)) {
95
tcg_out_opc_cu32i_d(s, rd, hi32);
96
- rd_high_bits_are_ones = hi32 < 0;
97
}
98
99
- if (imm_part_needs_loading(rd_high_bits_are_ones, hi52)) {
100
+ if (hi52 != sextreg(hi32, 20, 12)) {
101
tcg_out_opc_cu52i_d(s, rd, rd, hi52);
102
}
152
}
103
}
153
154
+tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
155
+ void **hostp)
156
+{
157
+ int flags;
158
+
159
+ flags = probe_access_internal(env, addr, 1, MMU_INST_FETCH, false, 0);
160
+ g_assert(flags == 0);
161
+
162
+ if (hostp) {
163
+ *hostp = g2h_untagged(addr);
164
+ }
165
+ return addr;
166
+}
167
+
168
/* The softmmu versions of these helpers are in cputlb.c. */
169
170
/*
171
--
104
--
172
2.34.1
105
2.34.1
diff view generated by jsdifflib
1
While there are no target-specific nonfaulting probes,
1
Regenerate with ADDU16I included:
2
generic code may grow some uses at some point.
3
2
4
Note that the attrs argument was incorrect -- it should have
3
$ cd loongarch-opcodes/scripts/go
5
been MEMTXATTRS_UNSPECIFIED. Just use the simpler interface.
4
$ go run ./genqemutcgdefs > $QEMU/tcg/loongarch64/tcg-insn-defs.c.inc
6
5
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: WANG Xuerui <git@xen0n.name>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
9
---
10
target/avr/helper.c | 46 ++++++++++++++++++++++++++++-----------------
10
tcg/loongarch64/tcg-insn-defs.c.inc | 10 +++++++++-
11
1 file changed, 29 insertions(+), 17 deletions(-)
11
1 file changed, 9 insertions(+), 1 deletion(-)
12
12
13
diff --git a/target/avr/helper.c b/target/avr/helper.c
13
diff --git a/tcg/loongarch64/tcg-insn-defs.c.inc b/tcg/loongarch64/tcg-insn-defs.c.inc
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/avr/helper.c
15
--- a/tcg/loongarch64/tcg-insn-defs.c.inc
16
+++ b/target/avr/helper.c
16
+++ b/tcg/loongarch64/tcg-insn-defs.c.inc
17
@@ -XXX,XX +XXX,XX @@ bool avr_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
17
@@ -XXX,XX +XXX,XX @@
18
MMUAccessType access_type, int mmu_idx,
18
*
19
bool probe, uintptr_t retaddr)
19
* This file is auto-generated by genqemutcgdefs from
20
{
20
* https://github.com/loongson-community/loongarch-opcodes,
21
- int prot = 0;
21
- * from commit 961f0c60f5b63e574d785995600c71ad5413fdc4.
22
- MemTxAttrs attrs = {};
22
+ * from commit 25ca7effe9d88101c1cf96c4005423643386d81f.
23
+ int prot, page_size = TARGET_PAGE_SIZE;
23
* DO NOT EDIT.
24
uint32_t paddr;
24
*/
25
25
26
address &= TARGET_PAGE_MASK;
26
@@ -XXX,XX +XXX,XX @@ typedef enum {
27
27
OPC_ANDI = 0x03400000,
28
if (mmu_idx == MMU_CODE_IDX) {
28
OPC_ORI = 0x03800000,
29
- /* access to code in flash */
29
OPC_XORI = 0x03c00000,
30
+ /* Access to code in flash. */
30
+ OPC_ADDU16I_D = 0x10000000,
31
paddr = OFFSET_CODE + address;
31
OPC_LU12I_W = 0x14000000,
32
prot = PAGE_READ | PAGE_EXEC;
32
OPC_CU32I_D = 0x16000000,
33
- if (paddr + TARGET_PAGE_SIZE > OFFSET_DATA) {
33
OPC_PCADDU2I = 0x18000000,
34
+ if (paddr >= OFFSET_DATA) {
34
@@ -XXX,XX +XXX,XX @@ tcg_out_opc_xori(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk12)
35
+ /*
35
tcg_out32(s, encode_djuk12_insn(OPC_XORI, d, j, uk12));
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
}
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
}
36
}
84
37
38
+/* Emits the `addu16i.d d, j, sk16` instruction. */
39
+static void __attribute__((unused))
40
+tcg_out_opc_addu16i_d(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16)
41
+{
42
+ tcg_out32(s, encode_djsk16_insn(OPC_ADDU16I_D, d, j, sk16));
43
+}
44
+
45
/* Emits the `lu12i.w d, sj20` instruction. */
46
static void __attribute__((unused))
47
tcg_out_opc_lu12i_w(TCGContext *s, TCGReg d, int32_t sj20)
85
--
48
--
86
2.34.1
49
2.34.1
87
50
88
51
diff view generated by jsdifflib
1
The function is not used outside of cpu-exec.c. Move it and
1
Adjust the constraints to allow any int32_t for immediate
2
its subroutines up in the file, before the first use.
2
addition. Split immediate adds into addu16i + addi, which
3
covers quite a lot of the immediate space. For the hole in
4
the middle, load the constant into TMP0 instead.
3
5
4
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: WANG Xuerui <git@xen0n.name>
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>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
8
---
9
include/exec/exec-all.h | 3 -
9
tcg/loongarch64/tcg-target-con-set.h | 4 +-
10
accel/tcg/cpu-exec.c | 122 ++++++++++++++++++++--------------------
10
tcg/loongarch64/tcg-target-con-str.h | 2 +-
11
2 files changed, 61 insertions(+), 64 deletions(-)
11
tcg/loongarch64/tcg-target.c.inc | 57 ++++++++++++++++++++++++----
12
3 files changed, 53 insertions(+), 10 deletions(-)
12
13
13
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
14
diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/include/exec/exec-all.h
16
--- a/tcg/loongarch64/tcg-target-con-set.h
16
+++ b/include/exec/exec-all.h
17
+++ b/tcg/loongarch64/tcg-target-con-set.h
17
@@ -XXX,XX +XXX,XX @@ void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs);
18
@@ -XXX,XX +XXX,XX @@ C_O1_I1(r, L)
18
#endif
19
C_O1_I2(r, r, rC)
19
void tb_flush(CPUState *cpu);
20
C_O1_I2(r, r, ri)
20
void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr);
21
C_O1_I2(r, r, rI)
21
-TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
22
+C_O1_I2(r, r, rJ)
22
- target_ulong cs_base, uint32_t flags,
23
C_O1_I2(r, r, rU)
23
- uint32_t cflags);
24
C_O1_I2(r, r, rW)
24
void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr);
25
C_O1_I2(r, r, rZ)
25
26
C_O1_I2(r, 0, rZ)
26
/* GETPC is the true target of the return instruction that we'll execute. */
27
-C_O1_I2(r, rZ, rN)
27
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
28
+C_O1_I2(r, rZ, ri)
29
+C_O1_I2(r, rZ, rJ)
30
C_O1_I2(r, rZ, rZ)
31
diff --git a/tcg/loongarch64/tcg-target-con-str.h b/tcg/loongarch64/tcg-target-con-str.h
28
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
29
--- a/accel/tcg/cpu-exec.c
33
--- a/tcg/loongarch64/tcg-target-con-str.h
30
+++ b/accel/tcg/cpu-exec.c
34
+++ b/tcg/loongarch64/tcg-target-con-str.h
31
@@ -XXX,XX +XXX,XX @@ uint32_t curr_cflags(CPUState *cpu)
35
@@ -XXX,XX +XXX,XX @@ REGS('L', ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS)
32
return cflags;
36
* CONST(letter, TCG_CT_CONST_* bit set)
37
*/
38
CONST('I', TCG_CT_CONST_S12)
39
-CONST('N', TCG_CT_CONST_N12)
40
+CONST('J', TCG_CT_CONST_S32)
41
CONST('U', TCG_CT_CONST_U12)
42
CONST('Z', TCG_CT_CONST_ZERO)
43
CONST('C', TCG_CT_CONST_C12)
44
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
45
index XXXXXXX..XXXXXXX 100644
46
--- a/tcg/loongarch64/tcg-target.c.inc
47
+++ b/tcg/loongarch64/tcg-target.c.inc
48
@@ -XXX,XX +XXX,XX @@ static const int tcg_target_call_oarg_regs[] = {
49
50
#define TCG_CT_CONST_ZERO 0x100
51
#define TCG_CT_CONST_S12 0x200
52
-#define TCG_CT_CONST_N12 0x400
53
+#define TCG_CT_CONST_S32 0x400
54
#define TCG_CT_CONST_U12 0x800
55
#define TCG_CT_CONST_C12 0x1000
56
#define TCG_CT_CONST_WSZ 0x2000
57
@@ -XXX,XX +XXX,XX @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
58
if ((ct & TCG_CT_CONST_S12) && val == sextreg(val, 0, 12)) {
59
return true;
60
}
61
- if ((ct & TCG_CT_CONST_N12) && -val == sextreg(-val, 0, 12)) {
62
+ if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
63
return true;
64
}
65
if ((ct & TCG_CT_CONST_U12) && val >= 0 && val <= 0xfff) {
66
@@ -XXX,XX +XXX,XX @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
67
}
33
}
68
}
34
69
35
+struct tb_desc {
70
+static void tcg_out_addi(TCGContext *s, TCGType type, TCGReg rd,
36
+ target_ulong pc;
71
+ TCGReg rs, tcg_target_long imm)
37
+ target_ulong cs_base;
72
+{
38
+ CPUArchState *env;
73
+ tcg_target_long lo12 = sextreg(imm, 0, 12);
39
+ tb_page_addr_t phys_page1;
74
+ tcg_target_long hi16 = sextreg(imm - lo12, 16, 16);
40
+ uint32_t flags;
41
+ uint32_t cflags;
42
+ uint32_t trace_vcpu_dstate;
43
+};
44
+
75
+
45
+static bool tb_lookup_cmp(const void *p, const void *d)
76
+ /*
46
+{
77
+ * Note that there's a hole in between hi16 and lo12:
47
+ const TranslationBlock *tb = p;
78
+ *
48
+ const struct tb_desc *desc = d;
79
+ * 3 2 1 0
49
+
80
+ * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
50
+ if (tb->pc == desc->pc &&
81
+ * ...+-------------------------------+-------+-----------------------+
51
+ tb->page_addr[0] == desc->phys_page1 &&
82
+ * | hi16 | | lo12 |
52
+ tb->cs_base == desc->cs_base &&
83
+ * ...+-------------------------------+-------+-----------------------+
53
+ tb->flags == desc->flags &&
84
+ *
54
+ tb->trace_vcpu_dstate == desc->trace_vcpu_dstate &&
85
+ * For bits within that hole, it's more efficient to use LU12I and ADD.
55
+ tb_cflags(tb) == desc->cflags) {
86
+ */
56
+ /* check next page if needed */
87
+ if (imm == (hi16 << 16) + lo12) {
57
+ if (tb->page_addr[1] == -1) {
88
+ if (hi16) {
58
+ return true;
89
+ tcg_out_opc_addu16i_d(s, rd, rs, hi16);
90
+ rs = rd;
91
+ }
92
+ if (type == TCG_TYPE_I32) {
93
+ tcg_out_opc_addi_w(s, rd, rs, lo12);
94
+ } else if (lo12) {
95
+ tcg_out_opc_addi_d(s, rd, rs, lo12);
59
+ } else {
96
+ } else {
60
+ tb_page_addr_t phys_page2;
97
+ tcg_out_mov(s, type, rd, rs);
61
+ target_ulong virt_page2;
98
+ }
62
+
99
+ } else {
63
+ virt_page2 = (desc->pc & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
100
+ tcg_out_movi(s, type, TCG_REG_TMP0, imm);
64
+ phys_page2 = get_page_addr_code(desc->env, virt_page2);
101
+ if (type == TCG_TYPE_I32) {
65
+ if (tb->page_addr[1] == phys_page2) {
102
+ tcg_out_opc_add_w(s, rd, rs, TCG_REG_TMP0);
66
+ return true;
103
+ } else {
67
+ }
104
+ tcg_out_opc_add_d(s, rd, rs, TCG_REG_TMP0);
68
+ }
105
+ }
69
+ }
106
+ }
70
+ return false;
71
+}
107
+}
72
+
108
+
73
+static TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
109
static void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg)
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
{
110
{
166
if (TCG_TARGET_HAS_direct_jump) {
111
tcg_out_opc_andi(s, ret, arg, 0xff);
112
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
113
114
case INDEX_op_add_i32:
115
if (c2) {
116
- tcg_out_opc_addi_w(s, a0, a1, a2);
117
+ tcg_out_addi(s, TCG_TYPE_I32, a0, a1, a2);
118
} else {
119
tcg_out_opc_add_w(s, a0, a1, a2);
120
}
121
break;
122
case INDEX_op_add_i64:
123
if (c2) {
124
- tcg_out_opc_addi_d(s, a0, a1, a2);
125
+ tcg_out_addi(s, TCG_TYPE_I64, a0, a1, a2);
126
} else {
127
tcg_out_opc_add_d(s, a0, a1, a2);
128
}
129
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
130
131
case INDEX_op_sub_i32:
132
if (c2) {
133
- tcg_out_opc_addi_w(s, a0, a1, -a2);
134
+ tcg_out_addi(s, TCG_TYPE_I32, a0, a1, -a2);
135
} else {
136
tcg_out_opc_sub_w(s, a0, a1, a2);
137
}
138
break;
139
case INDEX_op_sub_i64:
140
if (c2) {
141
- tcg_out_opc_addi_d(s, a0, a1, -a2);
142
+ tcg_out_addi(s, TCG_TYPE_I64, a0, a1, -a2);
143
} else {
144
tcg_out_opc_sub_d(s, a0, a1, a2);
145
}
146
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
147
return C_O1_I2(r, r, ri);
148
149
case INDEX_op_add_i32:
150
+ return C_O1_I2(r, r, ri);
151
case INDEX_op_add_i64:
152
- return C_O1_I2(r, r, rI);
153
+ return C_O1_I2(r, r, rJ);
154
155
case INDEX_op_and_i32:
156
case INDEX_op_and_i64:
157
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
158
return C_O1_I2(r, 0, rZ);
159
160
case INDEX_op_sub_i32:
161
+ return C_O1_I2(r, rZ, ri);
162
case INDEX_op_sub_i64:
163
- return C_O1_I2(r, rZ, rN);
164
+ return C_O1_I2(r, rZ, rJ);
165
166
case INDEX_op_mul_i32:
167
case INDEX_op_mul_i64:
167
--
168
--
168
2.34.1
169
2.34.1
diff view generated by jsdifflib
1
From: Ilya Leoshkevich <iii@linux.ibm.com>
1
Split out a helper function, tcg_out_setcond_int, which
2
does not always produce the complete boolean result, but
3
returns a set of flags to do so.
2
4
3
Right now translator stops right *after* the end of a page, which
5
Accept all int32_t as constant input, so that LE/GT can
4
breaks reporting of fault locations when the last instruction of a
6
adjust the constant to LT.
5
multi-insn translation block crosses a page boundary.
6
7
7
An implementation, like the one arm and s390x have, would require an
8
Reviewed-by: WANG Xuerui <git@xen0n.name>
8
i386 length disassembler, which is burdensome to maintain. Another
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>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
22
---
10
---
23
target/i386/tcg/translate.c | 64 ++++++++++++++++-----------
11
tcg/loongarch64/tcg-target.c.inc | 165 +++++++++++++++++++++----------
24
tests/tcg/x86_64/noexec.c | 75 ++++++++++++++++++++++++++++++++
12
1 file changed, 115 insertions(+), 50 deletions(-)
25
tests/tcg/x86_64/Makefile.target | 3 +-
26
3 files changed, 116 insertions(+), 26 deletions(-)
27
create mode 100644 tests/tcg/x86_64/noexec.c
28
13
29
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
14
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
30
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
31
--- a/target/i386/tcg/translate.c
16
--- a/tcg/loongarch64/tcg-target.c.inc
32
+++ b/target/i386/tcg/translate.c
17
+++ b/tcg/loongarch64/tcg-target.c.inc
33
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
18
@@ -XXX,XX +XXX,XX @@ static void tcg_out_clzctz(TCGContext *s, LoongArchInsn opc,
34
TCGv_i64 tmp1_i64;
19
tcg_out_opc_or(s, a0, TCG_REG_TMP0, a0);
35
20
}
36
sigjmp_buf jmpbuf;
21
37
+ TCGOp *prev_insn_end;
22
-static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
38
} DisasContext;
23
- TCGReg arg1, TCGReg arg2, bool c2)
39
24
-{
40
/* The environment in which user-only runs is constrained. */
25
- TCGReg tmp;
41
@@ -XXX,XX +XXX,XX @@ static uint64_t advance_pc(CPUX86State *env, DisasContext *s, int num_bytes)
26
+#define SETCOND_INV TCG_TARGET_NB_REGS
42
{
27
+#define SETCOND_NEZ (SETCOND_INV << 1)
43
uint64_t pc = s->pc;
28
+#define SETCOND_FLAGS (SETCOND_INV | SETCOND_NEZ)
44
29
45
+ /* This is a subsequent insn that crosses a page boundary. */
30
- if (c2) {
46
+ if (s->base.num_insns > 1 &&
31
- tcg_debug_assert(arg2 == 0);
47
+ !is_same_page(&s->base, s->pc + num_bytes - 1)) {
32
+static int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
48
+ siglongjmp(s->jmpbuf, 2);
33
+ TCGReg arg1, tcg_target_long arg2, bool c2)
34
+{
35
+ int flags = 0;
36
+
37
+ switch (cond) {
38
+ case TCG_COND_EQ: /* -> NE */
39
+ case TCG_COND_GE: /* -> LT */
40
+ case TCG_COND_GEU: /* -> LTU */
41
+ case TCG_COND_GT: /* -> LE */
42
+ case TCG_COND_GTU: /* -> LEU */
43
+ cond = tcg_invert_cond(cond);
44
+ flags ^= SETCOND_INV;
45
+ break;
46
+ default:
47
+ break;
48
}
49
50
switch (cond) {
51
- case TCG_COND_EQ:
52
- if (c2) {
53
- tmp = arg1;
54
- } else {
55
- tcg_out_opc_sub_d(s, ret, arg1, arg2);
56
- tmp = ret;
57
- }
58
- tcg_out_opc_sltui(s, ret, tmp, 1);
59
- break;
60
- case TCG_COND_NE:
61
- if (c2) {
62
- tmp = arg1;
63
- } else {
64
- tcg_out_opc_sub_d(s, ret, arg1, arg2);
65
- tmp = ret;
66
- }
67
- tcg_out_opc_sltu(s, ret, TCG_REG_ZERO, tmp);
68
- break;
69
- case TCG_COND_LT:
70
- tcg_out_opc_slt(s, ret, arg1, arg2);
71
- break;
72
- case TCG_COND_GE:
73
- tcg_out_opc_slt(s, ret, arg1, arg2);
74
- tcg_out_opc_xori(s, ret, ret, 1);
75
- break;
76
case TCG_COND_LE:
77
- tcg_out_setcond(s, TCG_COND_GE, ret, arg2, arg1, false);
78
- break;
79
- case TCG_COND_GT:
80
- tcg_out_setcond(s, TCG_COND_LT, ret, arg2, arg1, false);
81
- break;
82
- case TCG_COND_LTU:
83
- tcg_out_opc_sltu(s, ret, arg1, arg2);
84
- break;
85
- case TCG_COND_GEU:
86
- tcg_out_opc_sltu(s, ret, arg1, arg2);
87
- tcg_out_opc_xori(s, ret, ret, 1);
88
- break;
89
case TCG_COND_LEU:
90
- tcg_out_setcond(s, TCG_COND_GEU, ret, arg2, arg1, false);
91
+ /*
92
+ * If we have a constant input, the most efficient way to implement
93
+ * LE is by adding 1 and using LT. Watch out for wrap around for LEU.
94
+ * We don't need to care for this for LE because the constant input
95
+ * is still constrained to int32_t, and INT32_MAX+1 is representable
96
+ * in the 64-bit temporary register.
97
+ */
98
+ if (c2) {
99
+ if (cond == TCG_COND_LEU) {
100
+ /* unsigned <= -1 is true */
101
+ if (arg2 == -1) {
102
+ tcg_out_movi(s, TCG_TYPE_REG, ret, !(flags & SETCOND_INV));
103
+ return ret;
104
+ }
105
+ cond = TCG_COND_LTU;
106
+ } else {
107
+ cond = TCG_COND_LT;
108
+ }
109
+ arg2 += 1;
110
+ } else {
111
+ TCGReg tmp = arg2;
112
+ arg2 = arg1;
113
+ arg1 = tmp;
114
+ cond = tcg_swap_cond(cond); /* LE -> GE */
115
+ cond = tcg_invert_cond(cond); /* GE -> LT */
116
+ flags ^= SETCOND_INV;
117
+ }
118
break;
119
- case TCG_COND_GTU:
120
- tcg_out_setcond(s, TCG_COND_LTU, ret, arg2, arg1, false);
121
+ default:
122
break;
49
+ }
123
+ }
50
+
124
+
51
s->pc += num_bytes;
125
+ switch (cond) {
52
if (unlikely(s->pc - s->pc_start > X86_MAX_INSN_LENGTH)) {
126
+ case TCG_COND_NE:
53
/* If the instruction's 16th byte is on a different page than the 1st, a
127
+ flags |= SETCOND_NEZ;
54
@@ -XXX,XX +XXX,XX @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
128
+ if (!c2) {
55
int modrm, reg, rm, mod, op, opreg, val;
129
+ tcg_out_opc_xor(s, ret, arg1, arg2);
56
target_ulong next_eip, tval;
130
+ } else if (arg2 == 0) {
57
target_ulong pc_start = s->base.pc_next;
131
+ ret = arg1;
58
+ bool orig_cc_op_dirty = s->cc_op_dirty;
132
+ } else if (arg2 >= 0 && arg2 <= 0xfff) {
59
+ CCOp orig_cc_op = s->cc_op;
133
+ tcg_out_opc_xori(s, ret, arg1, arg2);
60
134
+ } else {
61
s->pc_start = s->pc = pc_start;
135
+ tcg_out_addi(s, TCG_TYPE_REG, ret, arg1, -arg2);
62
s->override = -1;
136
+ }
63
@@ -XXX,XX +XXX,XX @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
137
+ break;
64
s->rip_offset = 0; /* for relative ip address */
138
+
65
s->vex_l = 0;
139
+ case TCG_COND_LT:
66
s->vex_v = 0;
140
+ case TCG_COND_LTU:
67
- if (sigsetjmp(s->jmpbuf, 0) != 0) {
141
+ if (c2) {
68
+ switch (sigsetjmp(s->jmpbuf, 0)) {
142
+ if (arg2 >= -0x800 && arg2 <= 0x7ff) {
69
+ case 0:
143
+ if (cond == TCG_COND_LT) {
70
+ break;
144
+ tcg_out_opc_slti(s, ret, arg1, arg2);
71
+ case 1:
145
+ } else {
72
gen_exception_gpf(s);
146
+ tcg_out_opc_sltui(s, ret, arg1, arg2);
73
return s->pc;
147
+ }
74
+ case 2:
148
+ break;
75
+ /* Restore state that may affect the next instruction. */
149
+ }
76
+ s->cc_op_dirty = orig_cc_op_dirty;
150
+ tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP0, arg2);
77
+ s->cc_op = orig_cc_op;
151
+ arg2 = TCG_REG_TMP0;
78
+ s->base.num_insns--;
152
+ }
79
+ tcg_remove_ops_after(s->prev_insn_end);
153
+ if (cond == TCG_COND_LT) {
80
+ s->base.is_jmp = DISAS_TOO_MANY;
154
+ tcg_out_opc_slt(s, ret, arg1, arg2);
81
+ return pc_start;
155
+ } else {
82
+ default:
156
+ tcg_out_opc_sltu(s, ret, arg1, arg2);
83
+ g_assert_not_reached();
157
+ }
158
+ break;
159
+
160
default:
161
g_assert_not_reached();
162
break;
84
}
163
}
85
164
+
86
prefixes = 0;
165
+ return ret | flags;
87
@@ -XXX,XX +XXX,XX @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
166
+}
88
{
167
+
89
DisasContext *dc = container_of(dcbase, DisasContext, base);
168
+static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
90
169
+ TCGReg arg1, tcg_target_long arg2, bool c2)
91
+ dc->prev_insn_end = tcg_last_op();
170
+{
92
tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
171
+ int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2);
93
}
172
+
94
173
+ if (tmpflags != ret) {
95
@@ -XXX,XX +XXX,XX @@ static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
174
+ TCGReg tmp = tmpflags & ~SETCOND_FLAGS;
96
#endif
175
+
97
176
+ switch (tmpflags & SETCOND_FLAGS) {
98
pc_next = disas_insn(dc, cpu);
177
+ case SETCOND_INV:
99
-
178
+ /* Intermediate result is boolean: simply invert. */
100
- if (dc->flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)) {
179
+ tcg_out_opc_xori(s, ret, tmp, 1);
101
- /* if single step mode, we generate only one instruction and
180
+ break;
102
- generate an exception */
181
+ case SETCOND_NEZ:
103
- /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
182
+ /* Intermediate result is zero/non-zero: test != 0. */
104
- the flag and abort the translation to give the irqs a
183
+ tcg_out_opc_sltu(s, ret, TCG_REG_ZERO, tmp);
105
- chance to happen */
184
+ break;
106
- dc->base.is_jmp = DISAS_TOO_MANY;
185
+ case SETCOND_NEZ | SETCOND_INV:
107
- } else if ((tb_cflags(dc->base.tb) & CF_USE_ICOUNT)
186
+ /* Intermediate result is zero/non-zero: test == 0. */
108
- && ((pc_next & TARGET_PAGE_MASK)
187
+ tcg_out_opc_sltui(s, ret, tmp, 1);
109
- != ((pc_next + TARGET_MAX_INSN_SIZE - 1)
188
+ break;
110
- & TARGET_PAGE_MASK)
189
+ default:
111
- || (pc_next & ~TARGET_PAGE_MASK) == 0)) {
190
+ g_assert_not_reached();
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
+ }
191
+ }
138
+ }
192
+ }
139
}
193
}
140
194
141
static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
195
/*
142
diff --git a/tests/tcg/x86_64/noexec.c b/tests/tcg/x86_64/noexec.c
196
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
143
new file mode 100644
197
case INDEX_op_ctz_i64:
144
index XXXXXXX..XXXXXXX
198
return C_O1_I2(r, r, rW);
145
--- /dev/null
199
146
+++ b/tests/tcg/x86_64/noexec.c
200
- case INDEX_op_setcond_i32:
147
@@ -XXX,XX +XXX,XX @@
201
- case INDEX_op_setcond_i64:
148
+#include "../multiarch/noexec.c.inc"
202
- return C_O1_I2(r, r, rZ);
149
+
203
-
150
+static void *arch_mcontext_pc(const mcontext_t *ctx)
204
case INDEX_op_deposit_i32:
151
+{
205
case INDEX_op_deposit_i64:
152
+ return (void *)ctx->gregs[REG_RIP];
206
/* Must deposit into the same register as input */
153
+}
207
return C_O1_I2(r, 0, rZ);
154
+
208
155
+int arch_mcontext_arg(const mcontext_t *ctx)
209
case INDEX_op_sub_i32:
156
+{
210
+ case INDEX_op_setcond_i32:
157
+ return ctx->gregs[REG_RDI];
211
return C_O1_I2(r, rZ, ri);
158
+}
212
case INDEX_op_sub_i64:
159
+
213
+ case INDEX_op_setcond_i64:
160
+static void arch_flush(void *p, int len)
214
return C_O1_I2(r, rZ, rJ);
161
+{
215
162
+}
216
case INDEX_op_mul_i32:
163
+
164
+extern char noexec_1[];
165
+extern char noexec_2[];
166
+extern char noexec_end[];
167
+
168
+asm("noexec_1:\n"
169
+ " movq $1,%rdi\n" /* %rdi is 0 on entry, set 1. */
170
+ "noexec_2:\n"
171
+ " movq $2,%rdi\n" /* %rdi is 0/1; set 2. */
172
+ " ret\n"
173
+ "noexec_end:");
174
+
175
+int main(void)
176
+{
177
+ struct noexec_test noexec_tests[] = {
178
+ {
179
+ .name = "fallthrough",
180
+ .test_code = noexec_1,
181
+ .test_len = noexec_end - noexec_1,
182
+ .page_ofs = noexec_1 - noexec_2,
183
+ .entry_ofs = noexec_1 - noexec_2,
184
+ .expected_si_ofs = 0,
185
+ .expected_pc_ofs = 0,
186
+ .expected_arg = 1,
187
+ },
188
+ {
189
+ .name = "jump",
190
+ .test_code = noexec_1,
191
+ .test_len = noexec_end - noexec_1,
192
+ .page_ofs = noexec_1 - noexec_2,
193
+ .entry_ofs = 0,
194
+ .expected_si_ofs = 0,
195
+ .expected_pc_ofs = 0,
196
+ .expected_arg = 0,
197
+ },
198
+ {
199
+ .name = "fallthrough [cross]",
200
+ .test_code = noexec_1,
201
+ .test_len = noexec_end - noexec_1,
202
+ .page_ofs = noexec_1 - noexec_2 - 2,
203
+ .entry_ofs = noexec_1 - noexec_2 - 2,
204
+ .expected_si_ofs = 0,
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
--
217
--
243
2.34.1
218
2.34.1
diff view generated by jsdifflib
1
We're about to start validating PAGE_EXEC, which means that we've
1
Reviewed-by: WANG Xuerui <git@xen0n.name>
2
got to mark page zero executable. We had been special casing this
3
entirely within translate.
4
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>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
3
---
9
linux-user/elfload.c | 34 +++++++++++++++++++++++++++++++---
4
tcg/loongarch64/tcg-target-con-set.h | 1 +
10
1 file changed, 31 insertions(+), 3 deletions(-)
5
tcg/loongarch64/tcg-target.h | 4 ++--
6
tcg/loongarch64/tcg-target.c.inc | 33 ++++++++++++++++++++++++++++
7
3 files changed, 36 insertions(+), 2 deletions(-)
11
8
12
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
9
diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h
13
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
14
--- a/linux-user/elfload.c
11
--- a/tcg/loongarch64/tcg-target-con-set.h
15
+++ b/linux-user/elfload.c
12
+++ b/tcg/loongarch64/tcg-target-con-set.h
16
@@ -XXX,XX +XXX,XX @@ static inline void init_thread(struct target_pt_regs *regs,
13
@@ -XXX,XX +XXX,XX @@ C_O1_I2(r, 0, rZ)
17
regs->gr[31] = infop->entry;
14
C_O1_I2(r, rZ, ri)
15
C_O1_I2(r, rZ, rJ)
16
C_O1_I2(r, rZ, rZ)
17
+C_O1_I4(r, rZ, rJ, rZ, rZ)
18
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/tcg/loongarch64/tcg-target.h
21
+++ b/tcg/loongarch64/tcg-target.h
22
@@ -XXX,XX +XXX,XX @@ typedef enum {
23
#define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL
24
25
/* optional instructions */
26
-#define TCG_TARGET_HAS_movcond_i32 0
27
+#define TCG_TARGET_HAS_movcond_i32 1
28
#define TCG_TARGET_HAS_div_i32 1
29
#define TCG_TARGET_HAS_rem_i32 1
30
#define TCG_TARGET_HAS_div2_i32 0
31
@@ -XXX,XX +XXX,XX @@ typedef enum {
32
#define TCG_TARGET_HAS_qemu_st8_i32 0
33
34
/* 64-bit operations */
35
-#define TCG_TARGET_HAS_movcond_i64 0
36
+#define TCG_TARGET_HAS_movcond_i64 1
37
#define TCG_TARGET_HAS_div_i64 1
38
#define TCG_TARGET_HAS_rem_i64 1
39
#define TCG_TARGET_HAS_div2_i64 0
40
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
41
index XXXXXXX..XXXXXXX 100644
42
--- a/tcg/loongarch64/tcg-target.c.inc
43
+++ b/tcg/loongarch64/tcg-target.c.inc
44
@@ -XXX,XX +XXX,XX @@ static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
45
}
18
}
46
}
19
47
20
+#define LO_COMMPAGE 0
48
+static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
49
+ TCGReg c1, tcg_target_long c2, bool const2,
50
+ TCGReg v1, TCGReg v2)
51
+{
52
+ int tmpflags = tcg_out_setcond_int(s, cond, TCG_REG_TMP0, c1, c2, const2);
53
+ TCGReg t;
21
+
54
+
22
+static bool init_guest_commpage(void)
55
+ /* Standardize the test below to t != 0. */
23
+{
56
+ if (tmpflags & SETCOND_INV) {
24
+ void *want = g2h_untagged(LO_COMMPAGE);
57
+ t = v1, v1 = v2, v2 = t;
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
+ }
58
+ }
35
+
59
+
36
+ /*
60
+ t = tmpflags & ~SETCOND_FLAGS;
37
+ * On Linux, page zero is normally marked execute only + gateway.
61
+ if (v1 == TCG_REG_ZERO) {
38
+ * Normal read or write is supposed to fail (thus PROT_NONE above),
62
+ tcg_out_opc_masknez(s, ret, v2, t);
39
+ * but specific offsets have kernel code mapped to raise permissions
63
+ } else if (v2 == TCG_REG_ZERO) {
40
+ * and implement syscalls. Here, simply mark the page executable.
64
+ tcg_out_opc_maskeqz(s, ret, v1, t);
41
+ * Special case the entry points during translation (see do_page_zero).
65
+ } else {
42
+ */
66
+ tcg_out_opc_masknez(s, TCG_REG_TMP2, v2, t); /* t ? 0 : v2 */
43
+ page_set_flags(LO_COMMPAGE, LO_COMMPAGE + TARGET_PAGE_SIZE,
67
+ tcg_out_opc_maskeqz(s, TCG_REG_TMP1, v1, t); /* t ? v1 : 0 */
44
+ PAGE_EXEC | PAGE_VALID);
68
+ tcg_out_opc_or(s, ret, TCG_REG_TMP1, TCG_REG_TMP2);
45
+ return true;
69
+ }
46
+}
70
+}
47
+
71
+
48
#endif /* TARGET_HPPA */
72
/*
49
73
* Branch helpers
50
#ifdef TARGET_XTENSA
74
*/
51
@@ -XXX,XX +XXX,XX @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
75
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
52
}
76
tcg_out_setcond(s, args[3], a0, a1, a2, c2);
53
77
break;
54
#if defined(HI_COMMPAGE)
78
55
-#define LO_COMMPAGE 0
79
+ case INDEX_op_movcond_i32:
56
+#define LO_COMMPAGE -1
80
+ case INDEX_op_movcond_i64:
57
#elif defined(LO_COMMPAGE)
81
+ tcg_out_movcond(s, args[5], a0, a1, a2, c2, args[3], args[4]);
58
#define HI_COMMPAGE 0
82
+ break;
59
#else
83
+
60
#define HI_COMMPAGE 0
84
case INDEX_op_ld8s_i32:
61
-#define LO_COMMPAGE 0
85
case INDEX_op_ld8s_i64:
62
+#define LO_COMMPAGE -1
86
tcg_out_ldst(s, OPC_LD_B, a0, a1, a2);
63
#define init_guest_commpage() true
87
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
64
#endif
88
case INDEX_op_remu_i64:
65
89
return C_O1_I2(r, rZ, rZ);
66
@@ -XXX,XX +XXX,XX @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr,
90
67
} else {
91
+ case INDEX_op_movcond_i32:
68
offset = -(HI_COMMPAGE & -align);
92
+ case INDEX_op_movcond_i64:
69
}
93
+ return C_O1_I4(r, rZ, rJ, rZ, rZ);
70
- } else if (LO_COMMPAGE != 0) {
94
+
71
+ } else if (LO_COMMPAGE != -1) {
95
default:
72
loaddr = MIN(loaddr, LO_COMMPAGE & -align);
96
g_assert_not_reached();
73
}
97
}
74
75
--
98
--
76
2.34.1
99
2.34.1
diff view generated by jsdifflib
1
There is no need to go through cc->tcg_ops when
1
Take the w^x split into account when computing the
2
we know what value that must have.
2
pc-relative distance to an absolute pointer.
3
3
4
Reviewed-by: Michael Rolnik <mrolnik@gmail.com>
4
Reviewed-by: WANG Xuerui <git@xen0n.name>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
7
---
8
target/avr/helper.c | 5 ++---
8
tcg/loongarch64/tcg-target.c.inc | 2 +-
9
1 file changed, 2 insertions(+), 3 deletions(-)
9
1 file changed, 1 insertion(+), 1 deletion(-)
10
10
11
diff --git a/target/avr/helper.c b/target/avr/helper.c
11
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
12
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/avr/helper.c
13
--- a/tcg/loongarch64/tcg-target.c.inc
14
+++ b/target/avr/helper.c
14
+++ b/tcg/loongarch64/tcg-target.c.inc
15
@@ -XXX,XX +XXX,XX @@
15
@@ -XXX,XX +XXX,XX @@ static void tcg_out_ldst(TCGContext *s, LoongArchInsn opc, TCGReg data,
16
bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
16
intptr_t imm12 = sextreg(offset, 0, 12);
17
{
17
18
bool ret = false;
18
if (offset != imm12) {
19
- CPUClass *cc = CPU_GET_CLASS(cs);
19
- intptr_t diff = offset - (uintptr_t)s->code_ptr;
20
AVRCPU *cpu = AVR_CPU(cs);
20
+ intptr_t diff = tcg_pcrel_diff(s, (void *)offset);
21
CPUAVRState *env = &cpu->env;
21
22
22
if (addr == TCG_REG_ZERO && diff == (int32_t)diff) {
23
if (interrupt_request & CPU_INTERRUPT_RESET) {
23
imm12 = sextreg(diff, 0, 12);
24
if (cpu_interrupts_enabled(env)) {
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 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
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
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
1
The base qemu_ram_addr_from_host function is already in
1
The old implementation replaces two insns, swapping between
2
softmmu/physmem.c; move the nofail version to be adjacent.
3
2
4
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
3
b <dest>
5
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
4
nop
6
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
5
and
6
pcaddu18i tmp, <dest>
7
jirl zero, tmp, <dest> & 0xffff
8
9
There is a race condition in which a thread could be stopped at
10
the jirl, i.e. with the top of the address loaded, and when
11
restarted we have re-linked to a different TB, so that the top
12
half no longer matches the bottom half.
13
14
Note that while we never directly re-link to a different TB, we
15
can link, unlink, and link again all while the stopped thread
16
remains stopped.
17
18
The new implementation replaces only one insn, swapping between
19
20
b <dest>
21
and
22
pcadd tmp, <jmp_addr>
23
24
falling through to load the address from tmp, and branch.
25
26
Reviewed-by: WANG Xuerui <git@xen0n.name>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
27
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
28
---
9
include/exec/cpu-common.h | 1 +
29
tcg/loongarch64/tcg-target.h | 7 +---
10
accel/tcg/cputlb.c | 12 ------------
30
tcg/loongarch64/tcg-target.c.inc | 72 ++++++++++++++------------------
11
softmmu/physmem.c | 12 ++++++++++++
31
2 files changed, 33 insertions(+), 46 deletions(-)
12
3 files changed, 13 insertions(+), 12 deletions(-)
13
32
14
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
33
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
15
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
16
--- a/include/exec/cpu-common.h
35
--- a/tcg/loongarch64/tcg-target.h
17
+++ b/include/exec/cpu-common.h
36
+++ b/tcg/loongarch64/tcg-target.h
18
@@ -XXX,XX +XXX,XX @@ typedef uintptr_t ram_addr_t;
37
@@ -XXX,XX +XXX,XX @@
19
void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
38
20
/* This should not be used by devices. */
39
#define TCG_TARGET_INSN_UNIT_SIZE 4
21
ram_addr_t qemu_ram_addr_from_host(void *ptr);
40
#define TCG_TARGET_NB_REGS 32
22
+ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr);
41
-/*
23
RAMBlock *qemu_ram_block_by_name(const char *name);
42
- * PCADDU18I + JIRL sequence can give 20 + 16 + 2 = 38 bits
24
RAMBlock *qemu_ram_block_from_host(void *ptr, bool round_offset,
43
- * signed offset, which is +/- 128 GiB.
25
ram_addr_t *offset);
44
- */
26
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
45
-#define MAX_CODE_GEN_BUFFER_SIZE (128 * GiB)
46
+
47
+#define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1)
48
49
typedef enum {
50
TCG_REG_ZERO,
51
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
27
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
28
--- a/accel/tcg/cputlb.c
53
--- a/tcg/loongarch64/tcg-target.c.inc
29
+++ b/accel/tcg/cputlb.c
54
+++ b/tcg/loongarch64/tcg-target.c.inc
30
@@ -XXX,XX +XXX,XX @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
55
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args)
31
prot, mmu_idx, size);
56
#endif
32
}
57
}
33
58
34
-static inline ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
59
-/* LoongArch uses `andi zero, zero, 0` as NOP. */
60
-#define NOP OPC_ANDI
61
-static void tcg_out_nop(TCGContext *s)
35
-{
62
-{
36
- ram_addr_t ram_addr;
63
- tcg_out32(s, NOP);
64
-}
37
-
65
-
38
- ram_addr = qemu_ram_addr_from_host(ptr);
66
-void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
39
- if (ram_addr == RAM_ADDR_INVALID) {
67
- uintptr_t jmp_rx, uintptr_t jmp_rw)
40
- error_report("Bad ram pointer %p", ptr);
68
-{
41
- abort();
69
- tcg_insn_unit i1, i2;
70
- ptrdiff_t upper, lower;
71
- uintptr_t addr = tb->jmp_target_addr[n];
72
- ptrdiff_t offset = (ptrdiff_t)(addr - jmp_rx) >> 2;
73
-
74
- if (offset == sextreg(offset, 0, 26)) {
75
- i1 = encode_sd10k16_insn(OPC_B, offset);
76
- i2 = NOP;
77
- } else {
78
- tcg_debug_assert(offset == sextreg(offset, 0, 36));
79
- lower = (int16_t)offset;
80
- upper = (offset - lower) >> 16;
81
-
82
- i1 = encode_dsj20_insn(OPC_PCADDU18I, TCG_REG_TMP0, upper);
83
- i2 = encode_djsk16_insn(OPC_JIRL, TCG_REG_ZERO, TCG_REG_TMP0, lower);
42
- }
84
- }
43
- return ram_addr;
85
- uint64_t pair = ((uint64_t)i2 << 32) | i1;
86
- qatomic_set((uint64_t *)jmp_rw, pair);
87
- flush_idcache_range(jmp_rx, jmp_rw, 8);
44
-}
88
-}
45
-
89
-
46
/*
90
/*
47
* Note: tlb_fill() can trigger a resize of the TLB. This means that all of the
91
* Entry-points
48
* caller's prior references to the TLB table (e.g. CPUTLBEntry pointers) must
92
*/
49
diff --git a/softmmu/physmem.c b/softmmu/physmem.c
93
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
50
index XXXXXXX..XXXXXXX 100644
94
static void tcg_out_goto_tb(TCGContext *s, int which)
51
--- a/softmmu/physmem.c
95
{
52
+++ b/softmmu/physmem.c
96
/*
53
@@ -XXX,XX +XXX,XX @@ ram_addr_t qemu_ram_addr_from_host(void *ptr)
97
- * Ensure that patch area is 8-byte aligned so that an
54
return block->offset + offset;
98
- * atomic write can be used to patch the target address.
99
+ * Direct branch, or load indirect address, to be patched
100
+ * by tb_target_set_jmp_target. Check indirect load offset
101
+ * in range early, regardless of direct branch distance,
102
+ * via assert within tcg_out_opc_pcaddu2i.
103
*/
104
- if ((uintptr_t)s->code_ptr & 7) {
105
- tcg_out_nop(s);
106
- }
107
+ uintptr_t i_addr = get_jmp_target_addr(s, which);
108
+ intptr_t i_disp = tcg_pcrel_diff(s, (void *)i_addr);
109
+
110
set_jmp_insn_offset(s, which);
111
- /*
112
- * actual branch destination will be patched by
113
- * tb_target_set_jmp_target later
114
- */
115
- tcg_out_opc_pcaddu18i(s, TCG_REG_TMP0, 0);
116
+ tcg_out_opc_pcaddu2i(s, TCG_REG_TMP0, i_disp >> 2);
117
+
118
+ /* Finish the load and indirect branch. */
119
+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_TMP0, 0);
120
tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_TMP0, 0);
121
set_jmp_reset_offset(s, which);
55
}
122
}
56
123
57
+ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
124
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
125
+ uintptr_t jmp_rx, uintptr_t jmp_rw)
58
+{
126
+{
59
+ ram_addr_t ram_addr;
127
+ uintptr_t d_addr = tb->jmp_target_addr[n];
128
+ ptrdiff_t d_disp = (ptrdiff_t)(d_addr - jmp_rx) >> 2;
129
+ tcg_insn_unit insn;
60
+
130
+
61
+ ram_addr = qemu_ram_addr_from_host(ptr);
131
+ /* Either directly branch, or load slot address for indirect branch. */
62
+ if (ram_addr == RAM_ADDR_INVALID) {
132
+ if (d_disp == sextreg(d_disp, 0, 26)) {
63
+ error_report("Bad ram pointer %p", ptr);
133
+ insn = encode_sd10k16_insn(OPC_B, d_disp);
64
+ abort();
134
+ } else {
135
+ uintptr_t i_addr = (uintptr_t)&tb->jmp_target_addr[n];
136
+ intptr_t i_disp = i_addr - jmp_rx;
137
+ insn = encode_dsj20_insn(OPC_PCADDU2I, TCG_REG_TMP0, i_disp >> 2);
65
+ }
138
+ }
66
+ return ram_addr;
139
+
140
+ qatomic_set((tcg_insn_unit *)jmp_rw, insn);
141
+ flush_idcache_range(jmp_rx, jmp_rw, 4);
67
+}
142
+}
68
+
143
+
69
static MemTxResult flatview_read(FlatView *fv, hwaddr addr,
144
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
70
MemTxAttrs attrs, void *buf, hwaddr len);
145
const TCGArg args[TCG_MAX_OP_ARGS],
71
static MemTxResult flatview_write(FlatView *fv, hwaddr addr, MemTxAttrs attrs,
146
const int const_args[TCG_MAX_OP_ARGS])
72
--
147
--
73
2.34.1
148
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