1
TCG patch queue, plus one target/sh4 patch that
1
The following changes since commit 9c6c079bc6723da8061ccfb44361d67b1dd785dd:
2
Yoshinori Sato asked me to process.
3
2
4
3
Merge tag 'pull-target-arm-20240430' of https://git.linaro.org/people/pmaydell/qemu-arm into staging (2024-04-30 09:58:54 -0700)
5
r~
6
7
8
The following changes since commit efbf38d73e5dcc4d5f8b98c6e7a12be1f3b91745:
9
10
Merge tag 'for-upstream' of git://repo.or.cz/qemu/kevin into staging (2022-10-03 15:06:07 -0400)
11
4
12
are available in the Git repository at:
5
are available in the Git repository at:
13
6
14
https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20221004
7
https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20240501
15
8
16
for you to fetch changes up to ab419fd8a035a65942de4e63effcd55ccbf1a9fe:
9
for you to fetch changes up to 917d7f8d948d706e275c9f33169b9dd0149ded1e:
17
10
18
target/sh4: Fix TB_FLAG_UNALIGN (2022-10-04 12:33:05 -0700)
11
plugins: Update the documentation block for plugin-gen.c (2024-04-30 16:12:05 -0700)
19
12
20
----------------------------------------------------------------
13
----------------------------------------------------------------
21
Cache CPUClass for use in hot code paths.
14
plugins: Rewrite plugin tcg expansion
22
Add CPUTLBEntryFull, probe_access_full, tlb_set_page_full.
23
Add generic support for TARGET_TB_PCREL.
24
tcg/ppc: Optimize 26-bit jumps using STQ for POWER 2.07
25
target/sh4: Fix TB_FLAG_UNALIGN
26
15
27
----------------------------------------------------------------
16
----------------------------------------------------------------
28
Alex Bennée (3):
17
Richard Henderson (20):
29
cpu: cache CPUClass in CPUState for hot code paths
18
tcg: Make tcg/helper-info.h self-contained
30
hw/core/cpu-sysemu: used cached class in cpu_asidx_from_attrs
19
tcg: Pass function pointer to tcg_gen_call*
31
cputlb: used cached CPUClass in our hot-paths
20
plugins: Zero new qemu_plugin_dyn_cb entries
21
plugins: Move function pointer in qemu_plugin_dyn_cb
22
plugins: Create TCGHelperInfo for all out-of-line callbacks
23
plugins: Use emit_before_op for PLUGIN_GEN_AFTER_INSN
24
plugins: Use emit_before_op for PLUGIN_GEN_FROM_TB
25
plugins: Add PLUGIN_GEN_AFTER_TB
26
plugins: Use emit_before_op for PLUGIN_GEN_FROM_INSN
27
plugins: Use emit_before_op for PLUGIN_GEN_FROM_MEM
28
plugins: Remove plugin helpers
29
tcg: Remove TCG_CALL_PLUGIN
30
tcg: Remove INDEX_op_plugin_cb_{start,end}
31
plugins: Simplify callback queues
32
plugins: Introduce PLUGIN_CB_MEM_REGULAR
33
plugins: Replace pr_ops with a proper debug dump flag
34
plugins: Split out common cb expanders
35
plugins: Merge qemu_plugin_tb_insn_get to plugin-gen.c
36
plugins: Inline plugin_gen_empty_callback
37
plugins: Update the documentation block for plugin-gen.c
32
38
33
Leandro Lupori (1):
39
accel/tcg/plugin-helpers.h | 5 -
34
tcg/ppc: Optimize 26-bit jumps
40
include/exec/helper-gen-common.h | 4 -
35
41
include/exec/helper-proto-common.h | 4 -
36
Richard Henderson (16):
42
include/exec/plugin-gen.h | 4 -
37
accel/tcg: Rename CPUIOTLBEntry to CPUTLBEntryFull
43
include/qemu/log.h | 1 +
38
accel/tcg: Drop addr member from SavedIOTLB
44
include/qemu/plugin.h | 67 +--
39
accel/tcg: Suppress auto-invalidate in probe_access_internal
45
include/tcg/helper-info.h | 3 +
40
accel/tcg: Introduce probe_access_full
46
include/tcg/tcg-op-common.h | 4 +-
41
accel/tcg: Introduce tlb_set_page_full
47
include/tcg/tcg-opc.h | 4 +-
42
include/exec: Introduce TARGET_PAGE_ENTRY_EXTRA
48
include/tcg/tcg.h | 26 +-
43
accel/tcg: Remove PageDesc code_bitmap
49
include/exec/helper-gen.h.inc | 24 +-
44
accel/tcg: Use bool for page_find_alloc
50
accel/tcg/plugin-gen.c | 1007 +++++++++---------------------------
45
accel/tcg: Use DisasContextBase in plugin_gen_tb_start
51
plugins/api.c | 26 +-
46
accel/tcg: Do not align tb->page_addr[0]
52
plugins/core.c | 61 ++-
47
accel/tcg: Inline tb_flush_jmp_cache
53
tcg/tcg-op-ldst.c | 6 +-
48
include/hw/core: Create struct CPUJumpCache
54
tcg/tcg-op.c | 8 +-
49
hw/core: Add CPUClass.get_pc
55
tcg/tcg.c | 78 ++-
50
accel/tcg: Introduce tb_pc and log_pc
56
tcg/tci.c | 1 +
51
accel/tcg: Introduce TARGET_TB_PCREL
57
util/log.c | 4 +
52
target/sh4: Fix TB_FLAG_UNALIGN
58
19 files changed, 399 insertions(+), 938 deletions(-)
53
59
delete mode 100644 accel/tcg/plugin-helpers.h
54
accel/tcg/internal.h | 10 ++
55
accel/tcg/tb-hash.h | 1 +
56
accel/tcg/tb-jmp-cache.h | 65 ++++++++
57
include/exec/cpu-common.h | 1 +
58
include/exec/cpu-defs.h | 48 ++++--
59
include/exec/exec-all.h | 75 ++++++++-
60
include/exec/plugin-gen.h | 7 +-
61
include/hw/core/cpu.h | 28 ++--
62
include/qemu/typedefs.h | 2 +
63
include/tcg/tcg.h | 2 +-
64
target/sh4/cpu.h | 56 ++++---
65
accel/stubs/tcg-stub.c | 4 +
66
accel/tcg/cpu-exec.c | 80 +++++-----
67
accel/tcg/cputlb.c | 259 ++++++++++++++++++--------------
68
accel/tcg/plugin-gen.c | 22 +--
69
accel/tcg/translate-all.c | 214 ++++++++++++--------------
70
accel/tcg/translator.c | 2 +-
71
cpu.c | 9 +-
72
hw/core/cpu-common.c | 3 +-
73
hw/core/cpu-sysemu.c | 5 +-
74
linux-user/sh4/signal.c | 6 +-
75
plugins/core.c | 2 +-
76
target/alpha/cpu.c | 9 ++
77
target/arm/cpu.c | 17 ++-
78
target/arm/mte_helper.c | 14 +-
79
target/arm/sve_helper.c | 4 +-
80
target/arm/translate-a64.c | 2 +-
81
target/avr/cpu.c | 10 +-
82
target/cris/cpu.c | 8 +
83
target/hexagon/cpu.c | 10 +-
84
target/hppa/cpu.c | 12 +-
85
target/i386/cpu.c | 9 ++
86
target/i386/tcg/tcg-cpu.c | 2 +-
87
target/loongarch/cpu.c | 11 +-
88
target/m68k/cpu.c | 8 +
89
target/microblaze/cpu.c | 10 +-
90
target/mips/cpu.c | 8 +
91
target/mips/tcg/exception.c | 2 +-
92
target/mips/tcg/sysemu/special_helper.c | 2 +-
93
target/nios2/cpu.c | 9 ++
94
target/openrisc/cpu.c | 10 +-
95
target/ppc/cpu_init.c | 8 +
96
target/riscv/cpu.c | 17 ++-
97
target/rx/cpu.c | 10 +-
98
target/s390x/cpu.c | 8 +
99
target/s390x/tcg/mem_helper.c | 4 -
100
target/sh4/cpu.c | 18 ++-
101
target/sh4/helper.c | 6 +-
102
target/sh4/translate.c | 90 +++++------
103
target/sparc/cpu.c | 10 +-
104
target/tricore/cpu.c | 11 +-
105
target/xtensa/cpu.c | 8 +
106
tcg/tcg.c | 8 +-
107
trace/control-target.c | 2 +-
108
tcg/ppc/tcg-target.c.inc | 119 +++++++++++----
109
55 files changed, 915 insertions(+), 462 deletions(-)
110
create mode 100644 accel/tcg/tb-jmp-cache.h
111
diff view generated by jsdifflib
1
When PAGE_WRITE_INV is set when calling tlb_set_page,
1
Move MAX_CALL_IARGS from tcg.h and include for
2
we immediately set TLB_INVALID_MASK in order to force
2
the define of TCG_TARGET_REG_BITS.
3
tlb_fill to be called on the next lookup. Here in
4
probe_access_internal, we have just called tlb_fill
5
and eliminated true misses, thus the lookup must be valid.
6
7
This allows us to remove a warning comment from s390x.
8
There doesn't seem to be a reason to change the code though.
9
3
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Reviewed-by: David Hildenbrand <david@redhat.com>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
---
7
---
15
accel/tcg/cputlb.c | 10 +++++++++-
8
include/tcg/helper-info.h | 3 +++
16
target/s390x/tcg/mem_helper.c | 4 ----
9
include/tcg/tcg.h | 2 --
17
2 files changed, 9 insertions(+), 5 deletions(-)
10
tcg/tci.c | 1 +
11
3 files changed, 4 insertions(+), 2 deletions(-)
18
12
19
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
13
diff --git a/include/tcg/helper-info.h b/include/tcg/helper-info.h
20
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
21
--- a/accel/tcg/cputlb.c
15
--- a/include/tcg/helper-info.h
22
+++ b/accel/tcg/cputlb.c
16
+++ b/include/tcg/helper-info.h
23
@@ -XXX,XX +XXX,XX @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
17
@@ -XXX,XX +XXX,XX @@
24
}
18
#ifdef CONFIG_TCG_INTERPRETER
25
tlb_addr = tlb_read_ofs(entry, elt_ofs);
19
#include <ffi.h>
26
20
#endif
27
+ flags = TLB_FLAGS_MASK;
21
+#include "tcg-target-reg-bits.h"
28
page_addr = addr & TARGET_PAGE_MASK;
29
if (!tlb_hit_page(tlb_addr, page_addr)) {
30
if (!victim_tlb_hit(env, mmu_idx, index, elt_ofs, page_addr)) {
31
@@ -XXX,XX +XXX,XX @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
32
33
/* TLB resize via tlb_fill may have moved the entry. */
34
entry = tlb_entry(env, mmu_idx, addr);
35
+
22
+
36
+ /*
23
+#define MAX_CALL_IARGS 7
37
+ * With PAGE_WRITE_INV, we set TLB_INVALID_MASK immediately,
24
38
+ * to force the next access through tlb_fill. We've just
25
/*
39
+ * called tlb_fill, so we know that this entry *is* valid.
26
* Describe the calling convention of a given argument type.
40
+ */
27
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
41
+ flags &= ~TLB_INVALID_MASK;
42
}
43
tlb_addr = tlb_read_ofs(entry, elt_ofs);
44
}
45
- flags = tlb_addr & TLB_FLAGS_MASK;
46
+ flags &= tlb_addr;
47
48
/* Fold all "mmio-like" bits into TLB_MMIO. This is not RAM. */
49
if (unlikely(flags & ~(TLB_WATCHPOINT | TLB_NOTDIRTY))) {
50
diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c
51
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
52
--- a/target/s390x/tcg/mem_helper.c
29
--- a/include/tcg/tcg.h
53
+++ b/target/s390x/tcg/mem_helper.c
30
+++ b/include/tcg/tcg.h
54
@@ -XXX,XX +XXX,XX @@ static int s390_probe_access(CPUArchState *env, target_ulong addr, int size,
31
@@ -XXX,XX +XXX,XX @@
55
#else
32
/* XXX: make safe guess about sizes */
56
int flags;
33
#define MAX_OP_PER_INSTR 266
57
34
58
- /*
35
-#define MAX_CALL_IARGS 7
59
- * For !CONFIG_USER_ONLY, we cannot rely on TLB_INVALID_MASK or haddr==NULL
36
-
60
- * to detect if there was an exception during tlb_fill().
37
#define CPU_TEMP_BUF_NLONGS 128
61
- */
38
#define TCG_STATIC_FRAME_SIZE (CPU_TEMP_BUF_NLONGS * sizeof(long))
62
env->tlb_fill_exc = 0;
39
63
flags = probe_access_flags(env, addr, access_type, mmu_idx, nonfault, phost,
40
diff --git a/tcg/tci.c b/tcg/tci.c
64
ra);
41
index XXXXXXX..XXXXXXX 100644
42
--- a/tcg/tci.c
43
+++ b/tcg/tci.c
44
@@ -XXX,XX +XXX,XX @@
45
46
#include "qemu/osdep.h"
47
#include "tcg/tcg.h"
48
+#include "tcg/helper-info.h"
49
#include "tcg/tcg-ldst.h"
50
#include <ffi.h>
51
65
--
52
--
66
2.34.1
53
2.34.1
67
54
68
55
diff view generated by jsdifflib
1
This bitmap is created and discarded immediately.
1
For normal helpers, read the function pointer from the
2
We gain nothing by its existence.
2
structure earlier. For plugins, this will allow the
3
function pointer to come from elsewhere.
3
4
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-Id: <20220822232338.1727934-2-richard.henderson@linaro.org>
7
---
8
---
8
accel/tcg/translate-all.c | 78 ++-------------------------------------
9
include/tcg/tcg.h | 21 +++++++++-------
9
1 file changed, 4 insertions(+), 74 deletions(-)
10
include/exec/helper-gen.h.inc | 24 ++++++++++++-------
10
11
tcg/tcg.c | 45 +++++++++++++++++++----------------
11
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
12
3 files changed, 52 insertions(+), 38 deletions(-)
13
14
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
12
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
13
--- a/accel/tcg/translate-all.c
16
--- a/include/tcg/tcg.h
14
+++ b/accel/tcg/translate-all.c
17
+++ b/include/tcg/tcg.h
18
@@ -XXX,XX +XXX,XX @@ typedef struct TCGTargetOpDef {
19
20
bool tcg_op_supported(TCGOpcode op);
21
22
-void tcg_gen_call0(TCGHelperInfo *, TCGTemp *ret);
23
-void tcg_gen_call1(TCGHelperInfo *, TCGTemp *ret, TCGTemp *);
24
-void tcg_gen_call2(TCGHelperInfo *, TCGTemp *ret, TCGTemp *, TCGTemp *);
25
-void tcg_gen_call3(TCGHelperInfo *, TCGTemp *ret, TCGTemp *,
26
+void tcg_gen_call0(void *func, TCGHelperInfo *, TCGTemp *ret);
27
+void tcg_gen_call1(void *func, TCGHelperInfo *, TCGTemp *ret, TCGTemp *);
28
+void tcg_gen_call2(void *func, TCGHelperInfo *, TCGTemp *ret,
29
TCGTemp *, TCGTemp *);
30
-void tcg_gen_call4(TCGHelperInfo *, TCGTemp *ret, TCGTemp *, TCGTemp *,
31
- TCGTemp *, TCGTemp *);
32
-void tcg_gen_call5(TCGHelperInfo *, TCGTemp *ret, TCGTemp *, TCGTemp *,
33
+void tcg_gen_call3(void *func, TCGHelperInfo *, TCGTemp *ret,
34
TCGTemp *, TCGTemp *, TCGTemp *);
35
-void tcg_gen_call6(TCGHelperInfo *, TCGTemp *ret, TCGTemp *, TCGTemp *,
36
+void tcg_gen_call4(void *func, TCGHelperInfo *, TCGTemp *ret,
37
TCGTemp *, TCGTemp *, TCGTemp *, TCGTemp *);
38
-void tcg_gen_call7(TCGHelperInfo *, TCGTemp *ret, TCGTemp *, TCGTemp *,
39
+void tcg_gen_call5(void *func, TCGHelperInfo *, TCGTemp *ret,
40
TCGTemp *, TCGTemp *, TCGTemp *, TCGTemp *, TCGTemp *);
41
+void tcg_gen_call6(void *func, TCGHelperInfo *, TCGTemp *ret,
42
+ TCGTemp *, TCGTemp *, TCGTemp *, TCGTemp *,
43
+ TCGTemp *, TCGTemp *);
44
+void tcg_gen_call7(void *func, TCGHelperInfo *, TCGTemp *ret,
45
+ TCGTemp *, TCGTemp *, TCGTemp *, TCGTemp *,
46
+ TCGTemp *, TCGTemp *, TCGTemp *);
47
48
TCGOp *tcg_emit_op(TCGOpcode opc, unsigned nargs);
49
void tcg_op_remove(TCGContext *s, TCGOp *op);
50
diff --git a/include/exec/helper-gen.h.inc b/include/exec/helper-gen.h.inc
51
index XXXXXXX..XXXXXXX 100644
52
--- a/include/exec/helper-gen.h.inc
53
+++ b/include/exec/helper-gen.h.inc
15
@@ -XXX,XX +XXX,XX @@
54
@@ -XXX,XX +XXX,XX @@
16
#define assert_memory_lock() tcg_debug_assert(have_mmap_lock())
55
extern TCGHelperInfo glue(helper_info_, name); \
17
#endif
56
static inline void glue(gen_helper_, name)(dh_retvar_decl0(ret)) \
18
57
{ \
19
-#define SMC_BITMAP_USE_THRESHOLD 10
58
- tcg_gen_call0(&glue(helper_info_, name), dh_retvar(ret)); \
20
-
59
+ tcg_gen_call0(glue(helper_info_,name).func, \
21
typedef struct PageDesc {
60
+ &glue(helper_info_,name), dh_retvar(ret)); \
22
/* list of TBs intersecting this ram page */
61
}
23
uintptr_t first_tb;
62
24
-#ifdef CONFIG_SOFTMMU
63
#define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
25
- /* in order to optimize self modifying code, we count the number
64
@@ -XXX,XX +XXX,XX @@ extern TCGHelperInfo glue(helper_info_, name); \
26
- of lookups we do to a given page to use a bitmap */
65
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
27
- unsigned long *code_bitmap;
66
dh_arg_decl(t1, 1)) \
28
- unsigned int code_write_count;
67
{ \
29
-#else
68
- tcg_gen_call1(&glue(helper_info_, name), dh_retvar(ret), \
30
+#ifdef CONFIG_USER_ONLY
69
+ tcg_gen_call1(glue(helper_info_,name).func, \
31
unsigned long flags;
70
+ &glue(helper_info_,name), dh_retvar(ret), \
32
void *target_data;
71
dh_arg(t1, 1)); \
33
#endif
72
}
34
-#ifndef CONFIG_USER_ONLY
73
35
+#ifdef CONFIG_SOFTMMU
74
@@ -XXX,XX +XXX,XX @@ extern TCGHelperInfo glue(helper_info_, name); \
36
QemuSpin lock;
75
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
37
#endif
76
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2)) \
38
} PageDesc;
77
{ \
39
@@ -XXX,XX +XXX,XX @@ void tb_htable_init(void)
78
- tcg_gen_call2(&glue(helper_info_, name), dh_retvar(ret), \
40
qht_init(&tb_ctx.htable, tb_cmp, CODE_GEN_HTABLE_SIZE, mode);
79
+ tcg_gen_call2(glue(helper_info_,name).func, \
41
}
80
+ &glue(helper_info_,name), dh_retvar(ret), \
42
81
dh_arg(t1, 1), dh_arg(t2, 2)); \
43
-/* call with @p->lock held */
82
}
44
-static inline void invalidate_page_bitmap(PageDesc *p)
83
45
-{
84
@@ -XXX,XX +XXX,XX @@ extern TCGHelperInfo glue(helper_info_, name); \
46
- assert_page_locked(p);
85
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
47
-#ifdef CONFIG_SOFTMMU
86
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3)) \
48
- g_free(p->code_bitmap);
87
{ \
49
- p->code_bitmap = NULL;
88
- tcg_gen_call3(&glue(helper_info_, name), dh_retvar(ret), \
50
- p->code_write_count = 0;
89
+ tcg_gen_call3(glue(helper_info_,name).func, \
51
-#endif
90
+ &glue(helper_info_,name), dh_retvar(ret), \
52
-}
91
dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3)); \
53
-
92
}
54
/* Set to NULL all the 'first_tb' fields in all PageDescs. */
93
55
static void page_flush_tb_1(int level, void **lp)
94
@@ -XXX,XX +XXX,XX @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
56
{
95
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), \
57
@@ -XXX,XX +XXX,XX @@ static void page_flush_tb_1(int level, void **lp)
96
dh_arg_decl(t3, 3), dh_arg_decl(t4, 4)) \
58
for (i = 0; i < V_L2_SIZE; ++i) {
97
{ \
59
page_lock(&pd[i]);
98
- tcg_gen_call4(&glue(helper_info_, name), dh_retvar(ret), \
60
pd[i].first_tb = (uintptr_t)NULL;
99
+ tcg_gen_call4(glue(helper_info_,name).func, \
61
- invalidate_page_bitmap(pd + i);
100
+ &glue(helper_info_,name), dh_retvar(ret), \
62
page_unlock(&pd[i]);
101
dh_arg(t1, 1), dh_arg(t2, 2), \
63
}
102
dh_arg(t3, 3), dh_arg(t4, 4)); \
64
} else {
103
}
65
@@ -XXX,XX +XXX,XX @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
104
@@ -XXX,XX +XXX,XX @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
66
if (rm_from_page_list) {
105
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
67
p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
106
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5)) \
68
tb_page_remove(p, tb);
107
{ \
69
- invalidate_page_bitmap(p);
108
- tcg_gen_call5(&glue(helper_info_, name), dh_retvar(ret), \
70
if (tb->page_addr[1] != -1) {
109
+ tcg_gen_call5(glue(helper_info_,name).func, \
71
p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
110
+ &glue(helper_info_,name), dh_retvar(ret), \
72
tb_page_remove(p, tb);
111
dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
73
- invalidate_page_bitmap(p);
112
dh_arg(t4, 4), dh_arg(t5, 5)); \
113
}
114
@@ -XXX,XX +XXX,XX @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
115
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
116
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5), dh_arg_decl(t6, 6)) \
117
{ \
118
- tcg_gen_call6(&glue(helper_info_, name), dh_retvar(ret), \
119
+ tcg_gen_call6(glue(helper_info_,name).func, \
120
+ &glue(helper_info_,name), dh_retvar(ret), \
121
dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
122
dh_arg(t4, 4), dh_arg(t5, 5), dh_arg(t6, 6)); \
123
}
124
@@ -XXX,XX +XXX,XX @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
125
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5), dh_arg_decl(t6, 6), \
126
dh_arg_decl(t7, 7)) \
127
{ \
128
- tcg_gen_call7(&glue(helper_info_, name), dh_retvar(ret), \
129
+ tcg_gen_call7(glue(helper_info_,name).func, \
130
+ &glue(helper_info_,name), dh_retvar(ret), \
131
dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
132
dh_arg(t4, 4), dh_arg(t5, 5), dh_arg(t6, 6), \
133
dh_arg(t7, 7)); \
134
diff --git a/tcg/tcg.c b/tcg/tcg.c
135
index XXXXXXX..XXXXXXX 100644
136
--- a/tcg/tcg.c
137
+++ b/tcg/tcg.c
138
@@ -XXX,XX +XXX,XX @@ bool tcg_op_supported(TCGOpcode op)
139
140
static TCGOp *tcg_op_alloc(TCGOpcode opc, unsigned nargs);
141
142
-static void tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, TCGTemp **args)
143
+static void tcg_gen_callN(void *func, TCGHelperInfo *info,
144
+ TCGTemp *ret, TCGTemp **args)
145
{
146
TCGv_i64 extend_free[MAX_CALL_IARGS];
147
int n_extend = 0;
148
@@ -XXX,XX +XXX,XX @@ static void tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, TCGTemp **args)
149
g_assert_not_reached();
74
}
150
}
75
}
151
}
76
152
- op->args[pi++] = (uintptr_t)info->func;
77
@@ -XXX,XX +XXX,XX @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
153
+ op->args[pi++] = (uintptr_t)func;
154
op->args[pi++] = (uintptr_t)info;
155
tcg_debug_assert(pi == total_args);
156
157
@@ -XXX,XX +XXX,XX @@ static void tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, TCGTemp **args)
78
}
158
}
79
}
159
}
80
160
81
-#ifdef CONFIG_SOFTMMU
161
-void tcg_gen_call0(TCGHelperInfo *info, TCGTemp *ret)
82
-/* call with @p->lock held */
162
+void tcg_gen_call0(void *func, TCGHelperInfo *info, TCGTemp *ret)
83
-static void build_page_bitmap(PageDesc *p)
163
{
84
-{
164
- tcg_gen_callN(info, ret, NULL);
85
- int n, tb_start, tb_end;
165
+ tcg_gen_callN(func, info, ret, NULL);
86
- TranslationBlock *tb;
166
}
87
-
167
88
- assert_page_locked(p);
168
-void tcg_gen_call1(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1)
89
- p->code_bitmap = bitmap_new(TARGET_PAGE_SIZE);
169
+void tcg_gen_call1(void *func, TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1)
90
-
170
{
91
- PAGE_FOR_EACH_TB(p, tb, n) {
171
- tcg_gen_callN(info, ret, &t1);
92
- /* NOTE: this is subtle as a TB may span two physical pages */
172
+ tcg_gen_callN(func, info, ret, &t1);
93
- if (n == 0) {
173
}
94
- /* NOTE: tb_end may be after the end of the page, but
174
95
- it is not a problem */
175
-void tcg_gen_call2(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1, TCGTemp *t2)
96
- tb_start = tb->pc & ~TARGET_PAGE_MASK;
176
+void tcg_gen_call2(void *func, TCGHelperInfo *info, TCGTemp *ret,
97
- tb_end = tb_start + tb->size;
177
+ TCGTemp *t1, TCGTemp *t2)
98
- if (tb_end > TARGET_PAGE_SIZE) {
178
{
99
- tb_end = TARGET_PAGE_SIZE;
179
TCGTemp *args[2] = { t1, t2 };
100
- }
180
- tcg_gen_callN(info, ret, args);
101
- } else {
181
+ tcg_gen_callN(func, info, ret, args);
102
- tb_start = 0;
182
}
103
- tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
183
104
- }
184
-void tcg_gen_call3(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1,
105
- bitmap_set(p->code_bitmap, tb_start, tb_end - tb_start);
185
- TCGTemp *t2, TCGTemp *t3)
106
- }
186
+void tcg_gen_call3(void *func, TCGHelperInfo *info, TCGTemp *ret,
107
-}
187
+ TCGTemp *t1, TCGTemp *t2, TCGTemp *t3)
108
-#endif
188
{
109
-
189
TCGTemp *args[3] = { t1, t2, t3 };
110
/* add the tb in the target page and protect it if necessary
190
- tcg_gen_callN(info, ret, args);
111
*
191
+ tcg_gen_callN(func, info, ret, args);
112
* Called with mmap_lock held for user-mode emulation.
192
}
113
@@ -XXX,XX +XXX,XX @@ static inline void tb_page_add(PageDesc *p, TranslationBlock *tb,
193
114
page_already_protected = p->first_tb != (uintptr_t)NULL;
194
-void tcg_gen_call4(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1,
115
#endif
195
- TCGTemp *t2, TCGTemp *t3, TCGTemp *t4)
116
p->first_tb = (uintptr_t)tb | n;
196
+void tcg_gen_call4(void *func, TCGHelperInfo *info, TCGTemp *ret,
117
- invalidate_page_bitmap(p);
197
+ TCGTemp *t1, TCGTemp *t2, TCGTemp *t3, TCGTemp *t4)
118
198
{
119
#if defined(CONFIG_USER_ONLY)
199
TCGTemp *args[4] = { t1, t2, t3, t4 };
120
/* translator_loop() must have made all TB pages non-writable */
200
- tcg_gen_callN(info, ret, args);
121
@@ -XXX,XX +XXX,XX @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
201
+ tcg_gen_callN(func, info, ret, args);
122
/* remove TB from the page(s) if we couldn't insert it */
202
}
123
if (unlikely(existing_tb)) {
203
124
tb_page_remove(p, tb);
204
-void tcg_gen_call5(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1,
125
- invalidate_page_bitmap(p);
205
+void tcg_gen_call5(void *func, TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1,
126
if (p2) {
206
TCGTemp *t2, TCGTemp *t3, TCGTemp *t4, TCGTemp *t5)
127
tb_page_remove(p2, tb);
207
{
128
- invalidate_page_bitmap(p2);
208
TCGTemp *args[5] = { t1, t2, t3, t4, t5 };
129
}
209
- tcg_gen_callN(info, ret, args);
130
tb = existing_tb;
210
+ tcg_gen_callN(func, info, ret, args);
131
}
211
}
132
@@ -XXX,XX +XXX,XX @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
212
133
#if !defined(CONFIG_USER_ONLY)
213
-void tcg_gen_call6(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1, TCGTemp *t2,
134
/* if no code remaining, no need to continue to use slow writes */
214
- TCGTemp *t3, TCGTemp *t4, TCGTemp *t5, TCGTemp *t6)
135
if (!p->first_tb) {
215
+void tcg_gen_call6(void *func, TCGHelperInfo *info, TCGTemp *ret,
136
- invalidate_page_bitmap(p);
216
+ TCGTemp *t1, TCGTemp *t2, TCGTemp *t3,
137
tlb_unprotect_code(start);
217
+ TCGTemp *t4, TCGTemp *t5, TCGTemp *t6)
138
}
218
{
139
#endif
219
TCGTemp *args[6] = { t1, t2, t3, t4, t5, t6 };
140
@@ -XXX,XX +XXX,XX @@ void tb_invalidate_phys_page_fast(struct page_collection *pages,
220
- tcg_gen_callN(info, ret, args);
141
}
221
+ tcg_gen_callN(func, info, ret, args);
142
222
}
143
assert_page_locked(p);
223
144
- if (!p->code_bitmap &&
224
-void tcg_gen_call7(TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1,
145
- ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD) {
225
+void tcg_gen_call7(void *func, TCGHelperInfo *info, TCGTemp *ret, TCGTemp *t1,
146
- build_page_bitmap(p);
226
TCGTemp *t2, TCGTemp *t3, TCGTemp *t4,
147
- }
227
TCGTemp *t5, TCGTemp *t6, TCGTemp *t7)
148
- if (p->code_bitmap) {
228
{
149
- unsigned int nr;
229
TCGTemp *args[7] = { t1, t2, t3, t4, t5, t6, t7 };
150
- unsigned long b;
230
- tcg_gen_callN(info, ret, args);
151
-
231
+ tcg_gen_callN(func, info, ret, args);
152
- nr = start & ~TARGET_PAGE_MASK;
232
}
153
- b = p->code_bitmap[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG - 1));
233
154
- if (b & ((1 << len) - 1)) {
234
static void tcg_reg_alloc_start(TCGContext *s)
155
- goto do_invalidate;
156
- }
157
- } else {
158
- do_invalidate:
159
- tb_invalidate_phys_page_range__locked(pages, p, start, start + len,
160
- retaddr);
161
- }
162
+ tb_invalidate_phys_page_range__locked(pages, p, start, start + len,
163
+ retaddr);
164
}
165
#else
166
/* Called with mmap_lock held. If pc is not 0 then it indicates the
167
--
235
--
168
2.34.1
236
2.34.1
169
237
170
238
diff view generated by jsdifflib
1
Let tb->page_addr[0] contain the address of the first byte of the
2
translated block, rather than the address of the page containing the
3
start of the translated block. We need to recover this value anyway
4
at various points, and it is easier to discard a page offset when it
5
is not needed, which happens naturally via the existing find_page shift.
6
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
1
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
3
---
10
accel/tcg/cpu-exec.c | 16 ++++++++--------
4
plugins/core.c | 2 +-
11
accel/tcg/cputlb.c | 3 ++-
5
1 file changed, 1 insertion(+), 1 deletion(-)
12
accel/tcg/translate-all.c | 9 +++++----
13
3 files changed, 15 insertions(+), 13 deletions(-)
14
6
15
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
7
diff --git a/plugins/core.c b/plugins/core.c
16
index XXXXXXX..XXXXXXX 100644
8
index XXXXXXX..XXXXXXX 100644
17
--- a/accel/tcg/cpu-exec.c
9
--- a/plugins/core.c
18
+++ b/accel/tcg/cpu-exec.c
10
+++ b/plugins/core.c
19
@@ -XXX,XX +XXX,XX @@ struct tb_desc {
11
@@ -XXX,XX +XXX,XX @@ static struct qemu_plugin_dyn_cb *plugin_get_dyn_cb(GArray **arr)
20
target_ulong pc;
12
GArray *cbs = *arr;
21
target_ulong cs_base;
13
22
CPUArchState *env;
14
if (!cbs) {
23
- tb_page_addr_t phys_page1;
15
- cbs = g_array_sized_new(false, false,
24
+ tb_page_addr_t page_addr0;
16
+ cbs = g_array_sized_new(false, true,
25
uint32_t flags;
17
sizeof(struct qemu_plugin_dyn_cb), 1);
26
uint32_t cflags;
18
*arr = cbs;
27
uint32_t trace_vcpu_dstate;
28
@@ -XXX,XX +XXX,XX @@ static bool tb_lookup_cmp(const void *p, const void *d)
29
const struct tb_desc *desc = d;
30
31
if (tb->pc == desc->pc &&
32
- tb->page_addr[0] == desc->phys_page1 &&
33
+ tb->page_addr[0] == desc->page_addr0 &&
34
tb->cs_base == desc->cs_base &&
35
tb->flags == desc->flags &&
36
tb->trace_vcpu_dstate == desc->trace_vcpu_dstate &&
37
@@ -XXX,XX +XXX,XX @@ static bool tb_lookup_cmp(const void *p, const void *d)
38
if (tb->page_addr[1] == -1) {
39
return true;
40
} else {
41
- tb_page_addr_t phys_page2;
42
- target_ulong virt_page2;
43
+ tb_page_addr_t phys_page1;
44
+ target_ulong virt_page1;
45
46
/*
47
* We know that the first page matched, and an otherwise valid TB
48
@@ -XXX,XX +XXX,XX @@ static bool tb_lookup_cmp(const void *p, const void *d)
49
* is different for the new TB. Therefore any exception raised
50
* here by the faulting lookup is not premature.
51
*/
52
- virt_page2 = TARGET_PAGE_ALIGN(desc->pc);
53
- phys_page2 = get_page_addr_code(desc->env, virt_page2);
54
- if (tb->page_addr[1] == phys_page2) {
55
+ virt_page1 = TARGET_PAGE_ALIGN(desc->pc);
56
+ phys_page1 = get_page_addr_code(desc->env, virt_page1);
57
+ if (tb->page_addr[1] == phys_page1) {
58
return true;
59
}
60
}
61
@@ -XXX,XX +XXX,XX @@ static TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
62
if (phys_pc == -1) {
63
return NULL;
64
}
19
}
65
- desc.phys_page1 = phys_pc & TARGET_PAGE_MASK;
66
+ desc.page_addr0 = phys_pc;
67
h = tb_hash_func(phys_pc, pc, flags, cflags, *cpu->trace_dstate);
68
return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp);
69
}
70
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/accel/tcg/cputlb.c
73
+++ b/accel/tcg/cputlb.c
74
@@ -XXX,XX +XXX,XX @@ void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
75
can be detected */
76
void tlb_protect_code(ram_addr_t ram_addr)
77
{
78
- cpu_physical_memory_test_and_clear_dirty(ram_addr, TARGET_PAGE_SIZE,
79
+ cpu_physical_memory_test_and_clear_dirty(ram_addr & TARGET_PAGE_MASK,
80
+ TARGET_PAGE_SIZE,
81
DIRTY_MEMORY_CODE);
82
}
83
84
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/accel/tcg/translate-all.c
87
+++ b/accel/tcg/translate-all.c
88
@@ -XXX,XX +XXX,XX @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
89
qemu_spin_unlock(&tb->jmp_lock);
90
91
/* remove the TB from the hash list */
92
- phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
93
+ phys_pc = tb->page_addr[0];
94
h = tb_hash_func(phys_pc, tb->pc, tb->flags, orig_cflags,
95
tb->trace_vcpu_dstate);
96
if (!qht_remove(&tb_ctx.htable, tb, h)) {
97
@@ -XXX,XX +XXX,XX @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
98
* we can only insert TBs that are fully initialized.
99
*/
100
page_lock_pair(&p, phys_pc, &p2, phys_page2, true);
101
- tb_page_add(p, tb, 0, phys_pc & TARGET_PAGE_MASK);
102
+ tb_page_add(p, tb, 0, phys_pc);
103
if (p2) {
104
tb_page_add(p2, tb, 1, phys_page2);
105
} else {
106
@@ -XXX,XX +XXX,XX @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
107
if (n == 0) {
108
/* NOTE: tb_end may be after the end of the page, but
109
it is not a problem */
110
- tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
111
+ tb_start = tb->page_addr[0];
112
tb_end = tb_start + tb->size;
113
} else {
114
tb_start = tb->page_addr[1];
115
- tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
116
+ tb_end = tb_start + ((tb->page_addr[0] + tb->size)
117
+ & ~TARGET_PAGE_MASK);
118
}
119
if (!(tb_end <= start || tb_start >= end)) {
120
#ifdef TARGET_HAS_PRECISE_SMC
121
--
20
--
122
2.34.1
21
2.34.1
123
22
124
23
diff view generated by jsdifflib
1
Wrap the bare TranslationBlock pointer into a structure.
1
The out-of-line function pointer is mutually exclusive
2
with inline expansion, so move it into the union.
3
Wrap the pointer in a structure named 'regular' to match
4
PLUGIN_CB_REGULAR.
2
5
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
9
---
7
accel/tcg/tb-hash.h | 1 +
10
include/qemu/plugin.h | 4 +++-
8
accel/tcg/tb-jmp-cache.h | 24 ++++++++++++++++++++++++
11
accel/tcg/plugin-gen.c | 4 ++--
9
include/exec/cpu-common.h | 1 +
12
plugins/core.c | 8 ++++----
10
include/hw/core/cpu.h | 15 +--------------
13
3 files changed, 9 insertions(+), 7 deletions(-)
11
include/qemu/typedefs.h | 1 +
12
accel/stubs/tcg-stub.c | 4 ++++
13
accel/tcg/cpu-exec.c | 10 +++++++---
14
accel/tcg/cputlb.c | 9 +++++----
15
accel/tcg/translate-all.c | 28 +++++++++++++++++++++++++---
16
hw/core/cpu-common.c | 3 +--
17
plugins/core.c | 2 +-
18
trace/control-target.c | 2 +-
19
12 files changed, 72 insertions(+), 28 deletions(-)
20
create mode 100644 accel/tcg/tb-jmp-cache.h
21
14
22
diff --git a/accel/tcg/tb-hash.h b/accel/tcg/tb-hash.h
15
diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h
23
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
24
--- a/accel/tcg/tb-hash.h
17
--- a/include/qemu/plugin.h
25
+++ b/accel/tcg/tb-hash.h
18
+++ b/include/qemu/plugin.h
26
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ enum plugin_dyn_cb_subtype {
27
#include "exec/cpu-defs.h"
20
* instance of a callback to be called upon the execution of a particular TB.
28
#include "exec/exec-all.h"
21
*/
29
#include "qemu/xxhash.h"
22
struct qemu_plugin_dyn_cb {
30
+#include "tb-jmp-cache.h"
23
- union qemu_plugin_cb_sig f;
31
24
void *userp;
32
#ifdef CONFIG_SOFTMMU
25
enum plugin_dyn_cb_subtype type;
33
26
/* @rw applies to mem callbacks only (both regular and inline) */
34
diff --git a/accel/tcg/tb-jmp-cache.h b/accel/tcg/tb-jmp-cache.h
27
enum qemu_plugin_mem_rw rw;
35
new file mode 100644
28
/* fields specific to each dyn_cb type go here */
36
index XXXXXXX..XXXXXXX
29
union {
37
--- /dev/null
30
+ struct {
38
+++ b/accel/tcg/tb-jmp-cache.h
31
+ union qemu_plugin_cb_sig f;
39
@@ -XXX,XX +XXX,XX @@
32
+ } regular;
40
+/*
33
struct {
41
+ * The per-CPU TranslationBlock jump cache.
34
qemu_plugin_u64 entry;
42
+ *
35
enum qemu_plugin_op op;
43
+ * Copyright (c) 2003 Fabrice Bellard
36
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
44
+ *
45
+ * SPDX-License-Identifier: GPL-2.0-or-later
46
+ */
47
+
48
+#ifndef ACCEL_TCG_TB_JMP_CACHE_H
49
+#define ACCEL_TCG_TB_JMP_CACHE_H
50
+
51
+#define TB_JMP_CACHE_BITS 12
52
+#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
53
+
54
+/*
55
+ * Accessed in parallel; all accesses to 'tb' must be atomic.
56
+ */
57
+struct CPUJumpCache {
58
+ struct {
59
+ TranslationBlock *tb;
60
+ } array[TB_JMP_CACHE_SIZE];
61
+};
62
+
63
+#endif /* ACCEL_TCG_TB_JMP_CACHE_H */
64
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
65
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
66
--- a/include/exec/cpu-common.h
38
--- a/accel/tcg/plugin-gen.c
67
+++ b/include/exec/cpu-common.h
39
+++ b/accel/tcg/plugin-gen.c
68
@@ -XXX,XX +XXX,XX @@ void cpu_list_unlock(void);
40
@@ -XXX,XX +XXX,XX @@ static TCGOp *append_udata_cb(const struct qemu_plugin_dyn_cb *cb,
69
unsigned int cpu_list_generation_id_get(void);
41
}
70
42
71
void tcg_flush_softmmu_tlb(CPUState *cs);
43
/* call */
72
+void tcg_flush_jmp_cache(CPUState *cs);
44
- op = copy_call(&begin_op, op, cb->f.vcpu_udata, cb_idx);
73
45
+ op = copy_call(&begin_op, op, cb->regular.f.vcpu_udata, cb_idx);
74
void tcg_iommu_init_notifier_list(CPUState *cpu);
46
75
void tcg_iommu_free_notifier_list(CPUState *cpu);
47
return op;
76
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
77
index XXXXXXX..XXXXXXX 100644
78
--- a/include/hw/core/cpu.h
79
+++ b/include/hw/core/cpu.h
80
@@ -XXX,XX +XXX,XX @@ struct kvm_run;
81
struct hax_vcpu_state;
82
struct hvf_vcpu_state;
83
84
-#define TB_JMP_CACHE_BITS 12
85
-#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
86
-
87
/* work queue */
88
89
/* The union type allows passing of 64 bit target pointers on 32 bit
90
@@ -XXX,XX +XXX,XX @@ struct CPUState {
91
CPUArchState *env_ptr;
92
IcountDecr *icount_decr_ptr;
93
94
- /* Accessed in parallel; all accesses must be atomic */
95
- TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE];
96
+ CPUJumpCache *tb_jmp_cache;
97
98
struct GDBRegisterState *gdb_regs;
99
int gdb_num_regs;
100
@@ -XXX,XX +XXX,XX @@ extern CPUTailQ cpus;
101
102
extern __thread CPUState *current_cpu;
103
104
-static inline void cpu_tb_jmp_cache_clear(CPUState *cpu)
105
-{
106
- unsigned int i;
107
-
108
- for (i = 0; i < TB_JMP_CACHE_SIZE; i++) {
109
- qatomic_set(&cpu->tb_jmp_cache[i], NULL);
110
- }
111
-}
112
-
113
/**
114
* qemu_tcg_mttcg_enabled:
115
* Check whether we are running MultiThread TCG or not.
116
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
117
index XXXXXXX..XXXXXXX 100644
118
--- a/include/qemu/typedefs.h
119
+++ b/include/qemu/typedefs.h
120
@@ -XXX,XX +XXX,XX @@ typedef struct CoMutex CoMutex;
121
typedef struct ConfidentialGuestSupport ConfidentialGuestSupport;
122
typedef struct CPUAddressSpace CPUAddressSpace;
123
typedef struct CPUArchState CPUArchState;
124
+typedef struct CPUJumpCache CPUJumpCache;
125
typedef struct CPUState CPUState;
126
typedef struct CPUTLBEntryFull CPUTLBEntryFull;
127
typedef struct DeviceListener DeviceListener;
128
diff --git a/accel/stubs/tcg-stub.c b/accel/stubs/tcg-stub.c
129
index XXXXXXX..XXXXXXX 100644
130
--- a/accel/stubs/tcg-stub.c
131
+++ b/accel/stubs/tcg-stub.c
132
@@ -XXX,XX +XXX,XX @@ void tlb_set_dirty(CPUState *cpu, target_ulong vaddr)
133
{
134
}
48
}
135
49
@@ -XXX,XX +XXX,XX @@ static TCGOp *append_mem_cb(const struct qemu_plugin_dyn_cb *cb,
136
+void tcg_flush_jmp_cache(CPUState *cpu)
50
137
+{
51
if (type == PLUGIN_GEN_CB_MEM) {
138
+}
52
/* call */
139
+
53
- op = copy_call(&begin_op, op, cb->f.vcpu_udata, cb_idx);
140
int probe_access_flags(CPUArchState *env, target_ulong addr,
54
+ op = copy_call(&begin_op, op, cb->regular.f.vcpu_udata, cb_idx);
141
MMUAccessType access_type, int mmu_idx,
142
bool nonfault, void **phost, uintptr_t retaddr)
143
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
144
index XXXXXXX..XXXXXXX 100644
145
--- a/accel/tcg/cpu-exec.c
146
+++ b/accel/tcg/cpu-exec.c
147
@@ -XXX,XX +XXX,XX @@
148
#include "sysemu/replay.h"
149
#include "sysemu/tcg.h"
150
#include "exec/helper-proto.h"
151
+#include "tb-jmp-cache.h"
152
#include "tb-hash.h"
153
#include "tb-context.h"
154
#include "internal.h"
155
@@ -XXX,XX +XXX,XX @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
156
tcg_debug_assert(!(cflags & CF_INVALID));
157
158
hash = tb_jmp_cache_hash_func(pc);
159
- tb = qatomic_rcu_read(&cpu->tb_jmp_cache[hash]);
160
+ tb = qatomic_rcu_read(&cpu->tb_jmp_cache->array[hash].tb);
161
162
if (likely(tb &&
163
tb->pc == pc &&
164
@@ -XXX,XX +XXX,XX @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
165
if (tb == NULL) {
166
return NULL;
167
}
55
}
168
- qatomic_set(&cpu->tb_jmp_cache[hash], tb);
56
169
+ qatomic_set(&cpu->tb_jmp_cache->array[hash].tb, tb);
57
return op;
170
return tb;
171
}
172
173
@@ -XXX,XX +XXX,XX @@ int cpu_exec(CPUState *cpu)
174
175
tb = tb_lookup(cpu, pc, cs_base, flags, cflags);
176
if (tb == NULL) {
177
+ uint32_t h;
178
+
179
mmap_lock();
180
tb = tb_gen_code(cpu, pc, cs_base, flags, cflags);
181
mmap_unlock();
182
@@ -XXX,XX +XXX,XX @@ int cpu_exec(CPUState *cpu)
183
* We add the TB in the virtual pc hash table
184
* for the fast lookup
185
*/
186
- qatomic_set(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)], tb);
187
+ h = tb_jmp_cache_hash_func(pc);
188
+ qatomic_set(&cpu->tb_jmp_cache->array[h].tb, tb);
189
}
190
191
#ifndef CONFIG_USER_ONLY
192
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/accel/tcg/cputlb.c
195
+++ b/accel/tcg/cputlb.c
196
@@ -XXX,XX +XXX,XX @@ static void tlb_window_reset(CPUTLBDesc *desc, int64_t ns,
197
198
static void tb_jmp_cache_clear_page(CPUState *cpu, target_ulong page_addr)
199
{
200
- unsigned int i, i0 = tb_jmp_cache_hash_page(page_addr);
201
+ int i, i0 = tb_jmp_cache_hash_page(page_addr);
202
+ CPUJumpCache *jc = cpu->tb_jmp_cache;
203
204
for (i = 0; i < TB_JMP_PAGE_SIZE; i++) {
205
- qatomic_set(&cpu->tb_jmp_cache[i0 + i], NULL);
206
+ qatomic_set(&jc->array[i0 + i].tb, NULL);
207
}
208
}
209
210
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data)
211
212
qemu_spin_unlock(&env_tlb(env)->c.lock);
213
214
- cpu_tb_jmp_cache_clear(cpu);
215
+ tcg_flush_jmp_cache(cpu);
216
217
if (to_clean == ALL_MMUIDX_BITS) {
218
qatomic_set(&env_tlb(env)->c.full_flush_count,
219
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_range_by_mmuidx_async_0(CPUState *cpu,
220
* longer to clear each entry individually than it will to clear it all.
221
*/
222
if (d.len >= (TARGET_PAGE_SIZE * TB_JMP_CACHE_SIZE)) {
223
- cpu_tb_jmp_cache_clear(cpu);
224
+ tcg_flush_jmp_cache(cpu);
225
return;
226
}
227
228
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
229
index XXXXXXX..XXXXXXX 100644
230
--- a/accel/tcg/translate-all.c
231
+++ b/accel/tcg/translate-all.c
232
@@ -XXX,XX +XXX,XX @@
233
#include "sysemu/tcg.h"
234
#include "qapi/error.h"
235
#include "hw/core/tcg-cpu-ops.h"
236
+#include "tb-jmp-cache.h"
237
#include "tb-hash.h"
238
#include "tb-context.h"
239
#include "internal.h"
240
@@ -XXX,XX +XXX,XX @@ static void do_tb_flush(CPUState *cpu, run_on_cpu_data tb_flush_count)
241
}
242
243
CPU_FOREACH(cpu) {
244
- cpu_tb_jmp_cache_clear(cpu);
245
+ tcg_flush_jmp_cache(cpu);
246
}
247
248
qht_reset_size(&tb_ctx.htable, CODE_GEN_HTABLE_SIZE);
249
@@ -XXX,XX +XXX,XX @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
250
/* remove the TB from the hash list */
251
h = tb_jmp_cache_hash_func(tb->pc);
252
CPU_FOREACH(cpu) {
253
- if (qatomic_read(&cpu->tb_jmp_cache[h]) == tb) {
254
- qatomic_set(&cpu->tb_jmp_cache[h], NULL);
255
+ CPUJumpCache *jc = cpu->tb_jmp_cache;
256
+ if (qatomic_read(&jc->array[h].tb) == tb) {
257
+ qatomic_set(&jc->array[h].tb, NULL);
258
}
259
}
260
261
@@ -XXX,XX +XXX,XX @@ int page_unprotect(target_ulong address, uintptr_t pc)
262
}
263
#endif /* CONFIG_USER_ONLY */
264
265
+/*
266
+ * Called by generic code at e.g. cpu reset after cpu creation,
267
+ * therefore we must be prepared to allocate the jump cache.
268
+ */
269
+void tcg_flush_jmp_cache(CPUState *cpu)
270
+{
271
+ CPUJumpCache *jc = cpu->tb_jmp_cache;
272
+
273
+ if (likely(jc)) {
274
+ for (int i = 0; i < TB_JMP_CACHE_SIZE; i++) {
275
+ qatomic_set(&jc->array[i].tb, NULL);
276
+ }
277
+ } else {
278
+ /* This should happen once during realize, and thus never race. */
279
+ jc = g_new0(CPUJumpCache, 1);
280
+ jc = qatomic_xchg(&cpu->tb_jmp_cache, jc);
281
+ assert(jc == NULL);
282
+ }
283
+}
284
+
285
/* This is a wrapper for common code that can not use CONFIG_SOFTMMU */
286
void tcg_flush_softmmu_tlb(CPUState *cs)
287
{
288
diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c
289
index XXXXXXX..XXXXXXX 100644
290
--- a/hw/core/cpu-common.c
291
+++ b/hw/core/cpu-common.c
292
@@ -XXX,XX +XXX,XX @@ static void cpu_common_reset(DeviceState *dev)
293
cpu->cflags_next_tb = -1;
294
295
if (tcg_enabled()) {
296
- cpu_tb_jmp_cache_clear(cpu);
297
-
298
+ tcg_flush_jmp_cache(cpu);
299
tcg_flush_softmmu_tlb(cpu);
300
}
301
}
302
diff --git a/plugins/core.c b/plugins/core.c
58
diff --git a/plugins/core.c b/plugins/core.c
303
index XXXXXXX..XXXXXXX 100644
59
index XXXXXXX..XXXXXXX 100644
304
--- a/plugins/core.c
60
--- a/plugins/core.c
305
+++ b/plugins/core.c
61
+++ b/plugins/core.c
306
@@ -XXX,XX +XXX,XX @@ struct qemu_plugin_ctx *plugin_id_to_ctx_locked(qemu_plugin_id_t id)
62
@@ -XXX,XX +XXX,XX @@ void plugin_register_dyn_cb__udata(GArray **arr,
307
static void plugin_cpu_update__async(CPUState *cpu, run_on_cpu_data data)
63
308
{
64
dyn_cb->userp = udata;
309
bitmap_copy(cpu->plugin_mask, &data.host_ulong, QEMU_PLUGIN_EV_MAX);
65
/* Note flags are discarded as unused. */
310
- cpu_tb_jmp_cache_clear(cpu);
66
- dyn_cb->f.vcpu_udata = cb;
311
+ tcg_flush_jmp_cache(cpu);
67
+ dyn_cb->regular.f.vcpu_udata = cb;
68
dyn_cb->type = PLUGIN_CB_REGULAR;
312
}
69
}
313
70
314
static void plugin_cpu_update__locked(gpointer k, gpointer v, gpointer udata)
71
@@ -XXX,XX +XXX,XX @@ void plugin_register_vcpu_mem_cb(GArray **arr,
315
diff --git a/trace/control-target.c b/trace/control-target.c
72
/* Note flags are discarded as unused. */
316
index XXXXXXX..XXXXXXX 100644
73
dyn_cb->type = PLUGIN_CB_REGULAR;
317
--- a/trace/control-target.c
74
dyn_cb->rw = rw;
318
+++ b/trace/control-target.c
75
- dyn_cb->f.generic = cb;
319
@@ -XXX,XX +XXX,XX @@ static void trace_event_synchronize_vcpu_state_dynamic(
76
+ dyn_cb->regular.f.vcpu_mem = cb;
320
{
321
bitmap_copy(vcpu->trace_dstate, vcpu->trace_dstate_delayed,
322
CPU_TRACE_DSTATE_MAX_EVENTS);
323
- cpu_tb_jmp_cache_clear(vcpu);
324
+ tcg_flush_jmp_cache(vcpu);
325
}
77
}
326
78
327
void trace_event_set_vcpu_state_dynamic(CPUState *vcpu,
79
/*
80
@@ -XXX,XX +XXX,XX @@ void qemu_plugin_vcpu_mem_cb(CPUState *cpu, uint64_t vaddr,
81
}
82
switch (cb->type) {
83
case PLUGIN_CB_REGULAR:
84
- cb->f.vcpu_mem(cpu->cpu_index, make_plugin_meminfo(oi, rw),
85
- vaddr, cb->userp);
86
+ cb->regular.f.vcpu_mem(cpu->cpu_index, make_plugin_meminfo(oi, rw),
87
+ vaddr, cb->userp);
88
break;
89
case PLUGIN_CB_INLINE:
90
exec_inline_op(cb, cpu->cpu_index);
328
--
91
--
329
2.34.1
92
2.34.1
330
93
331
94
diff view generated by jsdifflib
1
Allow the target to cache items from the guest page tables.
1
TCGHelperInfo includes the ABI for every function call.
2
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
5
---
8
include/exec/cpu-defs.h | 9 +++++++++
6
include/qemu/plugin.h | 1 +
9
1 file changed, 9 insertions(+)
7
plugins/core.c | 51 ++++++++++++++++++++++++++++++++++++++-----
8
2 files changed, 46 insertions(+), 6 deletions(-)
10
9
11
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
10
diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h
12
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
13
--- a/include/exec/cpu-defs.h
12
--- a/include/qemu/plugin.h
14
+++ b/include/exec/cpu-defs.h
13
+++ b/include/qemu/plugin.h
15
@@ -XXX,XX +XXX,XX @@ typedef struct CPUTLBEntryFull {
14
@@ -XXX,XX +XXX,XX @@ struct qemu_plugin_dyn_cb {
16
15
union {
17
/* @lg_page_size contains the log2 of the page size. */
16
struct {
18
uint8_t lg_page_size;
17
union qemu_plugin_cb_sig f;
18
+ TCGHelperInfo *info;
19
} regular;
20
struct {
21
qemu_plugin_u64 entry;
22
diff --git a/plugins/core.c b/plugins/core.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/plugins/core.c
25
+++ b/plugins/core.c
26
@@ -XXX,XX +XXX,XX @@ void plugin_register_dyn_cb__udata(GArray **arr,
27
enum qemu_plugin_cb_flags flags,
28
void *udata)
29
{
30
- struct qemu_plugin_dyn_cb *dyn_cb = plugin_get_dyn_cb(arr);
31
+ static TCGHelperInfo info[3] = {
32
+ [QEMU_PLUGIN_CB_NO_REGS].flags = TCG_CALL_NO_RWG | TCG_CALL_PLUGIN,
33
+ [QEMU_PLUGIN_CB_R_REGS].flags = TCG_CALL_NO_WG | TCG_CALL_PLUGIN,
34
+ [QEMU_PLUGIN_CB_RW_REGS].flags = TCG_CALL_PLUGIN,
35
+ /*
36
+ * Match qemu_plugin_vcpu_udata_cb_t:
37
+ * void (*)(uint32_t, void *)
38
+ */
39
+ [0 ... 2].typemask = (dh_typemask(void, 0) |
40
+ dh_typemask(i32, 1) |
41
+ dh_typemask(ptr, 2))
42
+ };
43
44
+ struct qemu_plugin_dyn_cb *dyn_cb = plugin_get_dyn_cb(arr);
45
dyn_cb->userp = udata;
46
- /* Note flags are discarded as unused. */
47
- dyn_cb->regular.f.vcpu_udata = cb;
48
dyn_cb->type = PLUGIN_CB_REGULAR;
49
+ dyn_cb->regular.f.vcpu_udata = cb;
19
+
50
+
51
+ assert((unsigned)flags < ARRAY_SIZE(info));
52
+ dyn_cb->regular.info = &info[flags];
53
}
54
55
void plugin_register_vcpu_mem_cb(GArray **arr,
56
@@ -XXX,XX +XXX,XX @@ void plugin_register_vcpu_mem_cb(GArray **arr,
57
enum qemu_plugin_mem_rw rw,
58
void *udata)
59
{
60
- struct qemu_plugin_dyn_cb *dyn_cb;
20
+ /*
61
+ /*
21
+ * Allow target-specific additions to this structure.
62
+ * Expect that the underlying type for enum qemu_plugin_meminfo_t
22
+ * This may be used to cache items from the guest cpu
63
+ * is either int32_t or uint32_t, aka int or unsigned int.
23
+ * page tables for later use by the implementation.
24
+ */
64
+ */
25
+#ifdef TARGET_PAGE_ENTRY_EXTRA
65
+ QEMU_BUILD_BUG_ON(
26
+ TARGET_PAGE_ENTRY_EXTRA
66
+ !__builtin_types_compatible_p(qemu_plugin_meminfo_t, uint32_t) &&
27
+#endif
67
+ !__builtin_types_compatible_p(qemu_plugin_meminfo_t, int32_t));
28
} CPUTLBEntryFull;
68
69
- dyn_cb = plugin_get_dyn_cb(arr);
70
+ static TCGHelperInfo info[3] = {
71
+ [QEMU_PLUGIN_CB_NO_REGS].flags = TCG_CALL_NO_RWG | TCG_CALL_PLUGIN,
72
+ [QEMU_PLUGIN_CB_R_REGS].flags = TCG_CALL_NO_WG | TCG_CALL_PLUGIN,
73
+ [QEMU_PLUGIN_CB_RW_REGS].flags = TCG_CALL_PLUGIN,
74
+ /*
75
+ * Match qemu_plugin_vcpu_mem_cb_t:
76
+ * void (*)(uint32_t, qemu_plugin_meminfo_t, uint64_t, void *)
77
+ */
78
+ [0 ... 2].typemask =
79
+ (dh_typemask(void, 0) |
80
+ dh_typemask(i32, 1) |
81
+ (__builtin_types_compatible_p(qemu_plugin_meminfo_t, uint32_t)
82
+ ? dh_typemask(i32, 2) : dh_typemask(s32, 2)) |
83
+ dh_typemask(i64, 3) |
84
+ dh_typemask(ptr, 4))
85
+ };
86
+
87
+ struct qemu_plugin_dyn_cb *dyn_cb = plugin_get_dyn_cb(arr);
88
dyn_cb->userp = udata;
89
- /* Note flags are discarded as unused. */
90
dyn_cb->type = PLUGIN_CB_REGULAR;
91
dyn_cb->rw = rw;
92
dyn_cb->regular.f.vcpu_mem = cb;
93
+
94
+ assert((unsigned)flags < ARRAY_SIZE(info));
95
+ dyn_cb->regular.info = &info[flags];
96
}
29
97
30
/*
98
/*
31
--
99
--
32
2.34.1
100
2.34.1
33
34
diff view generated by jsdifflib
1
Bool is more appropriate type for the alloc parameter.
1
Introduce a new plugin_cb op and migrate one operation.
2
By using emit_before_op, we do not need to emit opcodes
3
early and modify them later -- we can simply emit the
4
final set of opcodes once.
2
5
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
8
---
7
accel/tcg/translate-all.c | 14 +++++++-------
9
include/tcg/tcg-op-common.h | 1 +
8
1 file changed, 7 insertions(+), 7 deletions(-)
10
include/tcg/tcg-opc.h | 1 +
11
accel/tcg/plugin-gen.c | 74 +++++++++++++++++++++----------------
12
tcg/tcg-op.c | 5 +++
13
4 files changed, 50 insertions(+), 31 deletions(-)
9
14
10
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
15
diff --git a/include/tcg/tcg-op-common.h b/include/tcg/tcg-op-common.h
11
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
12
--- a/accel/tcg/translate-all.c
17
--- a/include/tcg/tcg-op-common.h
13
+++ b/accel/tcg/translate-all.c
18
+++ b/include/tcg/tcg-op-common.h
14
@@ -XXX,XX +XXX,XX @@ void page_init(void)
19
@@ -XXX,XX +XXX,XX @@ void tcg_gen_goto_tb(unsigned idx);
15
#endif
20
*/
21
void tcg_gen_lookup_and_goto_ptr(void);
22
23
+void tcg_gen_plugin_cb(unsigned from);
24
void tcg_gen_plugin_cb_start(unsigned from, unsigned type, unsigned wr);
25
void tcg_gen_plugin_cb_end(void);
26
27
diff --git a/include/tcg/tcg-opc.h b/include/tcg/tcg-opc.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/tcg/tcg-opc.h
30
+++ b/include/tcg/tcg-opc.h
31
@@ -XXX,XX +XXX,XX @@ DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_EXIT | TCG_OPF_BB_END)
32
DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_EXIT | TCG_OPF_BB_END)
33
DEF(goto_ptr, 0, 1, 0, TCG_OPF_BB_EXIT | TCG_OPF_BB_END)
34
35
+DEF(plugin_cb, 0, 0, 1, TCG_OPF_NOT_PRESENT)
36
DEF(plugin_cb_start, 0, 0, 3, TCG_OPF_NOT_PRESENT)
37
DEF(plugin_cb_end, 0, 0, 0, TCG_OPF_NOT_PRESENT)
38
39
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/accel/tcg/plugin-gen.c
42
+++ b/accel/tcg/plugin-gen.c
43
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_empty_callback(enum plugin_gen_from from)
44
{
45
switch (from) {
46
case PLUGIN_GEN_AFTER_INSN:
47
- gen_wrapped(from, PLUGIN_GEN_DISABLE_MEM_HELPER,
48
- gen_empty_mem_helper);
49
+ tcg_gen_plugin_cb(from);
50
break;
51
case PLUGIN_GEN_FROM_INSN:
52
/*
53
@@ -XXX,XX +XXX,XX @@ static void inject_mem_enable_helper(struct qemu_plugin_tb *ptb,
54
inject_mem_helper(begin_op, arr);
16
}
55
}
17
56
18
-static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc)
57
-static void inject_mem_disable_helper(struct qemu_plugin_insn *plugin_insn,
19
+static PageDesc *page_find_alloc(tb_page_addr_t index, bool alloc)
58
- TCGOp *begin_op)
59
-{
60
- if (likely(!plugin_insn->mem_helper)) {
61
- rm_ops(begin_op);
62
- return;
63
- }
64
- inject_mem_helper(begin_op, NULL);
65
-}
66
-
67
/* called before finishing a TB with exit_tb, goto_tb or goto_ptr */
68
void plugin_gen_disable_mem_helpers(void)
20
{
69
{
21
PageDesc *pd;
70
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_enable_mem_helper(struct qemu_plugin_tb *ptb,
22
void **lp;
71
inject_mem_enable_helper(ptb, insn, begin_op);
23
@@ -XXX,XX +XXX,XX @@ static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc)
72
}
24
73
25
static inline PageDesc *page_find(tb_page_addr_t index)
74
-static void plugin_gen_disable_mem_helper(struct qemu_plugin_tb *ptb,
75
- TCGOp *begin_op, int insn_idx)
76
+static void gen_disable_mem_helper(struct qemu_plugin_tb *ptb,
77
+ struct qemu_plugin_insn *insn)
26
{
78
{
27
- return page_find_alloc(index, 0);
79
- struct qemu_plugin_insn *insn = g_ptr_array_index(ptb->insns, insn_idx);
28
+ return page_find_alloc(index, false);
80
- inject_mem_disable_helper(insn, begin_op);
81
+ if (insn->mem_helper) {
82
+ tcg_gen_st_ptr(tcg_constant_ptr(0), tcg_env,
83
+ offsetof(CPUState, plugin_mem_cbs) -
84
+ offsetof(ArchCPU, env));
85
+ }
29
}
86
}
30
87
31
static void page_lock_pair(PageDesc **ret_p1, tb_page_addr_t phys1,
88
/* #define DEBUG_PLUGIN_GEN_OPS */
32
- PageDesc **ret_p2, tb_page_addr_t phys2, int alloc);
89
@@ -XXX,XX +XXX,XX @@ static void pr_ops(void)
33
+ PageDesc **ret_p2, tb_page_addr_t phys2, bool alloc);
90
34
91
static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
35
/* In user-mode page locks aren't used; mmap_lock is enough */
36
#ifdef CONFIG_USER_ONLY
37
@@ -XXX,XX +XXX,XX @@ static inline void page_unlock(PageDesc *pd)
38
/* lock the page(s) of a TB in the correct acquisition order */
39
static inline void page_lock_tb(const TranslationBlock *tb)
40
{
92
{
41
- page_lock_pair(NULL, tb->page_addr[0], NULL, tb->page_addr[1], 0);
93
- TCGOp *op;
42
+ page_lock_pair(NULL, tb->page_addr[0], NULL, tb->page_addr[1], false);
94
+ TCGOp *op, *next;
95
int insn_idx = -1;
96
97
pr_ops();
98
99
- QTAILQ_FOREACH(op, &tcg_ctx->ops, link) {
100
+ /*
101
+ * While injecting code, we cannot afford to reuse any ebb temps
102
+ * that might be live within the existing opcode stream.
103
+ * The simplest solution is to release them all and create new.
104
+ */
105
+ memset(tcg_ctx->free_temps, 0, sizeof(tcg_ctx->free_temps));
106
+
107
+ QTAILQ_FOREACH_SAFE(op, &tcg_ctx->ops, link, next) {
108
switch (op->opc) {
109
case INDEX_op_insn_start:
110
insn_idx++;
111
break;
112
+
113
+ case INDEX_op_plugin_cb:
114
+ {
115
+ enum plugin_gen_from from = op->args[0];
116
+ struct qemu_plugin_insn *insn = NULL;
117
+
118
+ if (insn_idx >= 0) {
119
+ insn = g_ptr_array_index(plugin_tb->insns, insn_idx);
120
+ }
121
+
122
+ tcg_ctx->emit_before_op = op;
123
+
124
+ switch (from) {
125
+ case PLUGIN_GEN_AFTER_INSN:
126
+ assert(insn != NULL);
127
+ gen_disable_mem_helper(plugin_tb, insn);
128
+ break;
129
+ default:
130
+ g_assert_not_reached();
131
+ }
132
+
133
+ tcg_ctx->emit_before_op = NULL;
134
+ tcg_op_remove(tcg_ctx, op);
135
+ break;
136
+ }
137
+
138
case INDEX_op_plugin_cb_start:
139
{
140
enum plugin_gen_from from = op->args[0];
141
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
142
143
break;
144
}
145
- case PLUGIN_GEN_AFTER_INSN:
146
- {
147
- g_assert(insn_idx >= 0);
148
-
149
- switch (type) {
150
- case PLUGIN_GEN_DISABLE_MEM_HELPER:
151
- plugin_gen_disable_mem_helper(plugin_tb, op, insn_idx);
152
- break;
153
- default:
154
- g_assert_not_reached();
155
- }
156
- break;
157
- }
158
default:
159
g_assert_not_reached();
160
}
161
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
162
index XXXXXXX..XXXXXXX 100644
163
--- a/tcg/tcg-op.c
164
+++ b/tcg/tcg-op.c
165
@@ -XXX,XX +XXX,XX @@ void tcg_gen_mb(TCGBar mb_type)
166
}
43
}
167
}
44
168
45
static inline void page_unlock_tb(const TranslationBlock *tb)
169
+void tcg_gen_plugin_cb(unsigned from)
46
@@ -XXX,XX +XXX,XX @@ void page_collection_unlock(struct page_collection *set)
170
+{
47
#endif /* !CONFIG_USER_ONLY */
171
+ tcg_gen_op1(INDEX_op_plugin_cb, from);
48
172
+}
49
static void page_lock_pair(PageDesc **ret_p1, tb_page_addr_t phys1,
173
+
50
- PageDesc **ret_p2, tb_page_addr_t phys2, int alloc)
174
void tcg_gen_plugin_cb_start(unsigned from, unsigned type, unsigned wr)
51
+ PageDesc **ret_p2, tb_page_addr_t phys2, bool alloc)
52
{
175
{
53
PageDesc *p1, *p2;
176
tcg_gen_op3(INDEX_op_plugin_cb_start, from, type, wr);
54
tb_page_addr_t page1;
55
@@ -XXX,XX +XXX,XX @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
56
* Note that inserting into the hash table first isn't an option, since
57
* we can only insert TBs that are fully initialized.
58
*/
59
- page_lock_pair(&p, phys_pc, &p2, phys_page2, 1);
60
+ page_lock_pair(&p, phys_pc, &p2, phys_page2, true);
61
tb_page_add(p, tb, 0, phys_pc & TARGET_PAGE_MASK);
62
if (p2) {
63
tb_page_add(p2, tb, 1, phys_page2);
64
@@ -XXX,XX +XXX,XX @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
65
for (addr = start, len = end - start;
66
len != 0;
67
len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
68
- PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
69
+ PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS, true);
70
71
/* If the write protection bit is set, then we invalidate
72
the code inside. */
73
--
177
--
74
2.34.1
178
2.34.1
75
76
diff view generated by jsdifflib
1
Populate this new method for all targets. Always match
1
By having the qemu_plugin_cb_flags be recorded in the TCGHelperInfo,
2
the result that would be given by cpu_get_tb_cpu_state,
2
we no longer need to distinguish PLUGIN_CB_REGULAR from
3
as we will want these values to correspond in the logs.
3
PLUGIN_CB_REGULAR_R, so place all TB callbacks in the same queue.
4
4
5
Reviewed-by: Taylor Simpson <tsimpson@quicinc.com>
5
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> (target/sparc)
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
7
---
10
Cc: Eduardo Habkost <eduardo@habkost.net> (supporter:Machine core)
8
accel/tcg/plugin-gen.c | 96 +++++++++++++++++++++++++-----------------
11
Cc: Marcel Apfelbaum <marcel.apfelbaum@gmail.com> (supporter:Machine core)
9
plugins/api.c | 6 +--
12
Cc: "Philippe Mathieu-Daudé" <f4bug@amsat.org> (reviewer:Machine core)
10
2 files changed, 58 insertions(+), 44 deletions(-)
13
Cc: Yanan Wang <wangyanan55@huawei.com> (reviewer:Machine core)
14
Cc: Michael Rolnik <mrolnik@gmail.com> (maintainer:AVR TCG CPUs)
15
Cc: "Edgar E. Iglesias" <edgar.iglesias@gmail.com> (maintainer:CRIS TCG CPUs)
16
Cc: Taylor Simpson <tsimpson@quicinc.com> (supporter:Hexagon TCG CPUs)
17
Cc: Song Gao <gaosong@loongson.cn> (maintainer:LoongArch TCG CPUs)
18
Cc: Xiaojuan Yang <yangxiaojuan@loongson.cn> (maintainer:LoongArch TCG CPUs)
19
Cc: Laurent Vivier <laurent@vivier.eu> (maintainer:M68K TCG CPUs)
20
Cc: Jiaxun Yang <jiaxun.yang@flygoat.com> (reviewer:MIPS TCG CPUs)
21
Cc: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> (reviewer:MIPS TCG CPUs)
22
Cc: Chris Wulff <crwulff@gmail.com> (maintainer:NiosII TCG CPUs)
23
Cc: Marek Vasut <marex@denx.de> (maintainer:NiosII TCG CPUs)
24
Cc: Stafford Horne <shorne@gmail.com> (odd fixer:OpenRISC TCG CPUs)
25
Cc: Yoshinori Sato <ysato@users.sourceforge.jp> (reviewer:RENESAS RX CPUs)
26
Cc: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> (maintainer:SPARC TCG CPUs)
27
Cc: Bastian Koppelmann <kbastian@mail.uni-paderborn.de> (maintainer:TriCore TCG CPUs)
28
Cc: Max Filippov <jcmvbkbc@gmail.com> (maintainer:Xtensa TCG CPUs)
29
Cc: qemu-arm@nongnu.org (open list:ARM TCG CPUs)
30
Cc: qemu-ppc@nongnu.org (open list:PowerPC TCG CPUs)
31
Cc: qemu-riscv@nongnu.org (open list:RISC-V TCG CPUs)
32
Cc: qemu-s390x@nongnu.org (open list:S390 TCG CPUs)
33
---
34
include/hw/core/cpu.h | 3 +++
35
target/alpha/cpu.c | 9 +++++++++
36
target/arm/cpu.c | 13 +++++++++++++
37
target/avr/cpu.c | 8 ++++++++
38
target/cris/cpu.c | 8 ++++++++
39
target/hexagon/cpu.c | 8 ++++++++
40
target/hppa/cpu.c | 8 ++++++++
41
target/i386/cpu.c | 9 +++++++++
42
target/loongarch/cpu.c | 9 +++++++++
43
target/m68k/cpu.c | 8 ++++++++
44
target/microblaze/cpu.c | 8 ++++++++
45
target/mips/cpu.c | 8 ++++++++
46
target/nios2/cpu.c | 9 +++++++++
47
target/openrisc/cpu.c | 8 ++++++++
48
target/ppc/cpu_init.c | 8 ++++++++
49
target/riscv/cpu.c | 13 +++++++++++++
50
target/rx/cpu.c | 8 ++++++++
51
target/s390x/cpu.c | 8 ++++++++
52
target/sh4/cpu.c | 8 ++++++++
53
target/sparc/cpu.c | 8 ++++++++
54
target/tricore/cpu.c | 9 +++++++++
55
target/xtensa/cpu.c | 8 ++++++++
56
22 files changed, 186 insertions(+)
57
11
58
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
12
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
59
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
60
--- a/include/hw/core/cpu.h
14
--- a/accel/tcg/plugin-gen.c
61
+++ b/include/hw/core/cpu.h
15
+++ b/accel/tcg/plugin-gen.c
62
@@ -XXX,XX +XXX,XX @@ struct SysemuCPUOps;
16
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_empty_callback(enum plugin_gen_from from)
63
* If the target behaviour here is anything other than "set
17
{
64
* the PC register to the value passed in" then the target must
18
switch (from) {
65
* also implement the synchronize_from_tb hook.
19
case PLUGIN_GEN_AFTER_INSN:
66
+ * @get_pc: Callback for getting the Program Counter register.
20
+ case PLUGIN_GEN_FROM_TB:
67
+ * As above, with the semantics of the target architecture.
21
tcg_gen_plugin_cb(from);
68
* @gdb_read_register: Callback for letting GDB read a register.
22
break;
69
* @gdb_write_register: Callback for letting GDB write a register.
23
case PLUGIN_GEN_FROM_INSN:
70
* @gdb_adjust_breakpoint: Callback for adjusting the address of a
24
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_empty_callback(enum plugin_gen_from from)
71
@@ -XXX,XX +XXX,XX @@ struct CPUClass {
25
*/
72
void (*dump_state)(CPUState *cpu, FILE *, int flags);
26
gen_wrapped(from, PLUGIN_GEN_ENABLE_MEM_HELPER,
73
int64_t (*get_arch_id)(CPUState *cpu);
27
gen_empty_mem_helper);
74
void (*set_pc)(CPUState *cpu, vaddr value);
28
- /* fall through */
75
+ vaddr (*get_pc)(CPUState *cpu);
29
- case PLUGIN_GEN_FROM_TB:
76
int (*gdb_read_register)(CPUState *cpu, GByteArray *buf, int reg);
30
gen_wrapped(from, PLUGIN_GEN_CB_UDATA, gen_empty_udata_cb_no_rwg);
77
int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg);
31
gen_wrapped(from, PLUGIN_GEN_CB_UDATA_R, gen_empty_udata_cb_no_wg);
78
vaddr (*gdb_adjust_breakpoint)(CPUState *cpu, vaddr addr);
32
gen_wrapped(from, PLUGIN_GEN_CB_INLINE, gen_empty_inline_cb);
79
diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
33
@@ -XXX,XX +XXX,XX @@ void plugin_gen_disable_mem_helpers(void)
80
index XXXXXXX..XXXXXXX 100644
34
offsetof(CPUState, plugin_mem_cbs) - offsetof(ArchCPU, env));
81
--- a/target/alpha/cpu.c
82
+++ b/target/alpha/cpu.c
83
@@ -XXX,XX +XXX,XX @@ static void alpha_cpu_set_pc(CPUState *cs, vaddr value)
84
cpu->env.pc = value;
85
}
35
}
86
36
87
+static vaddr alpha_cpu_get_pc(CPUState *cs)
37
-static void plugin_gen_tb_udata(const struct qemu_plugin_tb *ptb,
38
- TCGOp *begin_op)
39
-{
40
- inject_udata_cb(ptb->cbs[PLUGIN_CB_REGULAR], begin_op);
41
-}
42
-
43
-static void plugin_gen_tb_udata_r(const struct qemu_plugin_tb *ptb,
44
- TCGOp *begin_op)
45
-{
46
- inject_udata_cb(ptb->cbs[PLUGIN_CB_REGULAR_R], begin_op);
47
-}
48
-
49
-static void plugin_gen_tb_inline(const struct qemu_plugin_tb *ptb,
50
- TCGOp *begin_op)
51
-{
52
- inject_inline_cb(ptb->cbs[PLUGIN_CB_INLINE], begin_op, op_ok);
53
-}
54
-
55
static void plugin_gen_insn_udata(const struct qemu_plugin_tb *ptb,
56
TCGOp *begin_op, int insn_idx)
57
{
58
@@ -XXX,XX +XXX,XX @@ static void gen_disable_mem_helper(struct qemu_plugin_tb *ptb,
59
}
60
}
61
62
+static void gen_udata_cb(struct qemu_plugin_dyn_cb *cb)
88
+{
63
+{
89
+ AlphaCPU *cpu = ALPHA_CPU(cs);
64
+ TCGv_i32 cpu_index = tcg_temp_ebb_new_i32();
90
+
65
+
91
+ return cpu->env.pc;
66
+ tcg_gen_ld_i32(cpu_index, tcg_env,
67
+ -offsetof(ArchCPU, env) + offsetof(CPUState, cpu_index));
68
+ tcg_gen_call2(cb->regular.f.vcpu_udata, cb->regular.info, NULL,
69
+ tcgv_i32_temp(cpu_index),
70
+ tcgv_ptr_temp(tcg_constant_ptr(cb->userp)));
71
+ tcg_temp_free_i32(cpu_index);
92
+}
72
+}
93
+
73
+
74
+static void gen_inline_cb(struct qemu_plugin_dyn_cb *cb)
75
+{
76
+ GArray *arr = cb->inline_insn.entry.score->data;
77
+ size_t offset = cb->inline_insn.entry.offset;
78
+ TCGv_i32 cpu_index = tcg_temp_ebb_new_i32();
79
+ TCGv_i64 val = tcg_temp_ebb_new_i64();
80
+ TCGv_ptr ptr = tcg_temp_ebb_new_ptr();
94
+
81
+
95
static bool alpha_cpu_has_work(CPUState *cs)
82
+ tcg_gen_ld_i32(cpu_index, tcg_env,
83
+ -offsetof(ArchCPU, env) + offsetof(CPUState, cpu_index));
84
+ tcg_gen_muli_i32(cpu_index, cpu_index, g_array_get_element_size(arr));
85
+ tcg_gen_ext_i32_ptr(ptr, cpu_index);
86
+ tcg_temp_free_i32(cpu_index);
87
+
88
+ tcg_gen_addi_ptr(ptr, ptr, (intptr_t)arr->data);
89
+ tcg_gen_ld_i64(val, ptr, offset);
90
+ tcg_gen_addi_i64(val, val, cb->inline_insn.imm);
91
+ tcg_gen_st_i64(val, ptr, offset);
92
+
93
+ tcg_temp_free_i64(val);
94
+ tcg_temp_free_ptr(ptr);
95
+}
96
+
97
/* #define DEBUG_PLUGIN_GEN_OPS */
98
static void pr_ops(void)
96
{
99
{
97
/* Here we are checking to see if the CPU should wake up from HALT.
100
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
98
@@ -XXX,XX +XXX,XX @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data)
101
{
99
cc->has_work = alpha_cpu_has_work;
102
enum plugin_gen_from from = op->args[0];
100
cc->dump_state = alpha_cpu_dump_state;
103
struct qemu_plugin_insn *insn = NULL;
101
cc->set_pc = alpha_cpu_set_pc;
104
+ const GArray *cbs;
102
+ cc->get_pc = alpha_cpu_get_pc;
105
+ int i, n;
103
cc->gdb_read_register = alpha_cpu_gdb_read_register;
106
104
cc->gdb_write_register = alpha_cpu_gdb_write_register;
107
if (insn_idx >= 0) {
105
#ifndef CONFIG_USER_ONLY
108
insn = g_ptr_array_index(plugin_tb->insns, insn_idx);
106
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
109
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
110
assert(insn != NULL);
111
gen_disable_mem_helper(plugin_tb, insn);
112
break;
113
+
114
+ case PLUGIN_GEN_FROM_TB:
115
+ assert(insn == NULL);
116
+
117
+ cbs = plugin_tb->cbs[PLUGIN_CB_REGULAR];
118
+ for (i = 0, n = (cbs ? cbs->len : 0); i < n; i++) {
119
+ struct qemu_plugin_dyn_cb *cb =
120
+ &g_array_index(cbs, struct qemu_plugin_dyn_cb, i);
121
+ gen_udata_cb(cb);
122
+ }
123
+
124
+ cbs = plugin_tb->cbs[PLUGIN_CB_INLINE];
125
+ for (i = 0, n = (cbs ? cbs->len : 0); i < n; i++) {
126
+ struct qemu_plugin_dyn_cb *cb =
127
+ &g_array_index(cbs, struct qemu_plugin_dyn_cb, i);
128
+ gen_inline_cb(cb);
129
+ }
130
+ break;
131
+
132
default:
133
g_assert_not_reached();
134
}
135
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
136
enum plugin_gen_cb type = op->args[1];
137
138
switch (from) {
139
- case PLUGIN_GEN_FROM_TB:
140
- {
141
- g_assert(insn_idx == -1);
142
-
143
- switch (type) {
144
- case PLUGIN_GEN_CB_UDATA:
145
- plugin_gen_tb_udata(plugin_tb, op);
146
- break;
147
- case PLUGIN_GEN_CB_UDATA_R:
148
- plugin_gen_tb_udata_r(plugin_tb, op);
149
- break;
150
- case PLUGIN_GEN_CB_INLINE:
151
- plugin_gen_tb_inline(plugin_tb, op);
152
- break;
153
- default:
154
- g_assert_not_reached();
155
- }
156
- break;
157
- }
158
case PLUGIN_GEN_FROM_INSN:
159
{
160
g_assert(insn_idx >= 0);
161
diff --git a/plugins/api.c b/plugins/api.c
107
index XXXXXXX..XXXXXXX 100644
162
index XXXXXXX..XXXXXXX 100644
108
--- a/target/arm/cpu.c
163
--- a/plugins/api.c
109
+++ b/target/arm/cpu.c
164
+++ b/plugins/api.c
110
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_set_pc(CPUState *cs, vaddr value)
165
@@ -XXX,XX +XXX,XX @@ void qemu_plugin_register_vcpu_tb_exec_cb(struct qemu_plugin_tb *tb,
166
void *udata)
167
{
168
if (!tb->mem_only) {
169
- int index = flags == QEMU_PLUGIN_CB_R_REGS ||
170
- flags == QEMU_PLUGIN_CB_RW_REGS ?
171
- PLUGIN_CB_REGULAR_R : PLUGIN_CB_REGULAR;
172
-
173
- plugin_register_dyn_cb__udata(&tb->cbs[index],
174
+ plugin_register_dyn_cb__udata(&tb->cbs[PLUGIN_CB_REGULAR],
175
cb, flags, udata);
111
}
176
}
112
}
177
}
113
114
+static vaddr arm_cpu_get_pc(CPUState *cs)
115
+{
116
+ ARMCPU *cpu = ARM_CPU(cs);
117
+ CPUARMState *env = &cpu->env;
118
+
119
+ if (is_a64(env)) {
120
+ return env->pc;
121
+ } else {
122
+ return env->regs[15];
123
+ }
124
+}
125
+
126
#ifdef CONFIG_TCG
127
void arm_cpu_synchronize_from_tb(CPUState *cs,
128
const TranslationBlock *tb)
129
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
130
cc->has_work = arm_cpu_has_work;
131
cc->dump_state = arm_cpu_dump_state;
132
cc->set_pc = arm_cpu_set_pc;
133
+ cc->get_pc = arm_cpu_get_pc;
134
cc->gdb_read_register = arm_cpu_gdb_read_register;
135
cc->gdb_write_register = arm_cpu_gdb_write_register;
136
#ifndef CONFIG_USER_ONLY
137
diff --git a/target/avr/cpu.c b/target/avr/cpu.c
138
index XXXXXXX..XXXXXXX 100644
139
--- a/target/avr/cpu.c
140
+++ b/target/avr/cpu.c
141
@@ -XXX,XX +XXX,XX @@ static void avr_cpu_set_pc(CPUState *cs, vaddr value)
142
cpu->env.pc_w = value / 2; /* internally PC points to words */
143
}
144
145
+static vaddr avr_cpu_get_pc(CPUState *cs)
146
+{
147
+ AVRCPU *cpu = AVR_CPU(cs);
148
+
149
+ return cpu->env.pc_w * 2;
150
+}
151
+
152
static bool avr_cpu_has_work(CPUState *cs)
153
{
154
AVRCPU *cpu = AVR_CPU(cs);
155
@@ -XXX,XX +XXX,XX @@ static void avr_cpu_class_init(ObjectClass *oc, void *data)
156
cc->has_work = avr_cpu_has_work;
157
cc->dump_state = avr_cpu_dump_state;
158
cc->set_pc = avr_cpu_set_pc;
159
+ cc->get_pc = avr_cpu_get_pc;
160
dc->vmsd = &vms_avr_cpu;
161
cc->sysemu_ops = &avr_sysemu_ops;
162
cc->disas_set_info = avr_cpu_disas_set_info;
163
diff --git a/target/cris/cpu.c b/target/cris/cpu.c
164
index XXXXXXX..XXXXXXX 100644
165
--- a/target/cris/cpu.c
166
+++ b/target/cris/cpu.c
167
@@ -XXX,XX +XXX,XX @@ static void cris_cpu_set_pc(CPUState *cs, vaddr value)
168
cpu->env.pc = value;
169
}
170
171
+static vaddr cris_cpu_get_pc(CPUState *cs)
172
+{
173
+ CRISCPU *cpu = CRIS_CPU(cs);
174
+
175
+ return cpu->env.pc;
176
+}
177
+
178
static bool cris_cpu_has_work(CPUState *cs)
179
{
180
return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
181
@@ -XXX,XX +XXX,XX @@ static void cris_cpu_class_init(ObjectClass *oc, void *data)
182
cc->has_work = cris_cpu_has_work;
183
cc->dump_state = cris_cpu_dump_state;
184
cc->set_pc = cris_cpu_set_pc;
185
+ cc->get_pc = cris_cpu_get_pc;
186
cc->gdb_read_register = cris_cpu_gdb_read_register;
187
cc->gdb_write_register = cris_cpu_gdb_write_register;
188
#ifndef CONFIG_USER_ONLY
189
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
190
index XXXXXXX..XXXXXXX 100644
191
--- a/target/hexagon/cpu.c
192
+++ b/target/hexagon/cpu.c
193
@@ -XXX,XX +XXX,XX @@ static void hexagon_cpu_set_pc(CPUState *cs, vaddr value)
194
env->gpr[HEX_REG_PC] = value;
195
}
196
197
+static vaddr hexagon_cpu_get_pc(CPUState *cs)
198
+{
199
+ HexagonCPU *cpu = HEXAGON_CPU(cs);
200
+ CPUHexagonState *env = &cpu->env;
201
+ return env->gpr[HEX_REG_PC];
202
+}
203
+
204
static void hexagon_cpu_synchronize_from_tb(CPUState *cs,
205
const TranslationBlock *tb)
206
{
207
@@ -XXX,XX +XXX,XX @@ static void hexagon_cpu_class_init(ObjectClass *c, void *data)
208
cc->has_work = hexagon_cpu_has_work;
209
cc->dump_state = hexagon_dump_state;
210
cc->set_pc = hexagon_cpu_set_pc;
211
+ cc->get_pc = hexagon_cpu_get_pc;
212
cc->gdb_read_register = hexagon_gdb_read_register;
213
cc->gdb_write_register = hexagon_gdb_write_register;
214
cc->gdb_num_core_regs = TOTAL_PER_THREAD_REGS + NUM_VREGS + NUM_QREGS;
215
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
216
index XXXXXXX..XXXXXXX 100644
217
--- a/target/hppa/cpu.c
218
+++ b/target/hppa/cpu.c
219
@@ -XXX,XX +XXX,XX @@ static void hppa_cpu_set_pc(CPUState *cs, vaddr value)
220
cpu->env.iaoq_b = value + 4;
221
}
222
223
+static vaddr hppa_cpu_get_pc(CPUState *cs)
224
+{
225
+ HPPACPU *cpu = HPPA_CPU(cs);
226
+
227
+ return cpu->env.iaoq_f;
228
+}
229
+
230
static void hppa_cpu_synchronize_from_tb(CPUState *cs,
231
const TranslationBlock *tb)
232
{
233
@@ -XXX,XX +XXX,XX @@ static void hppa_cpu_class_init(ObjectClass *oc, void *data)
234
cc->has_work = hppa_cpu_has_work;
235
cc->dump_state = hppa_cpu_dump_state;
236
cc->set_pc = hppa_cpu_set_pc;
237
+ cc->get_pc = hppa_cpu_get_pc;
238
cc->gdb_read_register = hppa_cpu_gdb_read_register;
239
cc->gdb_write_register = hppa_cpu_gdb_write_register;
240
#ifndef CONFIG_USER_ONLY
241
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
242
index XXXXXXX..XXXXXXX 100644
243
--- a/target/i386/cpu.c
244
+++ b/target/i386/cpu.c
245
@@ -XXX,XX +XXX,XX @@ static void x86_cpu_set_pc(CPUState *cs, vaddr value)
246
cpu->env.eip = value;
247
}
248
249
+static vaddr x86_cpu_get_pc(CPUState *cs)
250
+{
251
+ X86CPU *cpu = X86_CPU(cs);
252
+
253
+ /* Match cpu_get_tb_cpu_state. */
254
+ return cpu->env.eip + cpu->env.segs[R_CS].base;
255
+}
256
+
257
int x86_cpu_pending_interrupt(CPUState *cs, int interrupt_request)
258
{
259
X86CPU *cpu = X86_CPU(cs);
260
@@ -XXX,XX +XXX,XX @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
261
cc->has_work = x86_cpu_has_work;
262
cc->dump_state = x86_cpu_dump_state;
263
cc->set_pc = x86_cpu_set_pc;
264
+ cc->get_pc = x86_cpu_get_pc;
265
cc->gdb_read_register = x86_cpu_gdb_read_register;
266
cc->gdb_write_register = x86_cpu_gdb_write_register;
267
cc->get_arch_id = x86_cpu_get_arch_id;
268
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
269
index XXXXXXX..XXXXXXX 100644
270
--- a/target/loongarch/cpu.c
271
+++ b/target/loongarch/cpu.c
272
@@ -XXX,XX +XXX,XX @@ static void loongarch_cpu_set_pc(CPUState *cs, vaddr value)
273
env->pc = value;
274
}
275
276
+static vaddr loongarch_cpu_get_pc(CPUState *cs)
277
+{
278
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
279
+ CPULoongArchState *env = &cpu->env;
280
+
281
+ return env->pc;
282
+}
283
+
284
#ifndef CONFIG_USER_ONLY
285
#include "hw/loongarch/virt.h"
286
287
@@ -XXX,XX +XXX,XX @@ static void loongarch_cpu_class_init(ObjectClass *c, void *data)
288
cc->has_work = loongarch_cpu_has_work;
289
cc->dump_state = loongarch_cpu_dump_state;
290
cc->set_pc = loongarch_cpu_set_pc;
291
+ cc->get_pc = loongarch_cpu_get_pc;
292
#ifndef CONFIG_USER_ONLY
293
dc->vmsd = &vmstate_loongarch_cpu;
294
cc->sysemu_ops = &loongarch_sysemu_ops;
295
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
296
index XXXXXXX..XXXXXXX 100644
297
--- a/target/m68k/cpu.c
298
+++ b/target/m68k/cpu.c
299
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_set_pc(CPUState *cs, vaddr value)
300
cpu->env.pc = value;
301
}
302
303
+static vaddr m68k_cpu_get_pc(CPUState *cs)
304
+{
305
+ M68kCPU *cpu = M68K_CPU(cs);
306
+
307
+ return cpu->env.pc;
308
+}
309
+
310
static bool m68k_cpu_has_work(CPUState *cs)
311
{
312
return cs->interrupt_request & CPU_INTERRUPT_HARD;
313
@@ -XXX,XX +XXX,XX @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
314
cc->has_work = m68k_cpu_has_work;
315
cc->dump_state = m68k_cpu_dump_state;
316
cc->set_pc = m68k_cpu_set_pc;
317
+ cc->get_pc = m68k_cpu_get_pc;
318
cc->gdb_read_register = m68k_cpu_gdb_read_register;
319
cc->gdb_write_register = m68k_cpu_gdb_write_register;
320
#if defined(CONFIG_SOFTMMU)
321
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
322
index XXXXXXX..XXXXXXX 100644
323
--- a/target/microblaze/cpu.c
324
+++ b/target/microblaze/cpu.c
325
@@ -XXX,XX +XXX,XX @@ static void mb_cpu_set_pc(CPUState *cs, vaddr value)
326
cpu->env.iflags = 0;
327
}
328
329
+static vaddr mb_cpu_get_pc(CPUState *cs)
330
+{
331
+ MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
332
+
333
+ return cpu->env.pc;
334
+}
335
+
336
static void mb_cpu_synchronize_from_tb(CPUState *cs,
337
const TranslationBlock *tb)
338
{
339
@@ -XXX,XX +XXX,XX @@ static void mb_cpu_class_init(ObjectClass *oc, void *data)
340
341
cc->dump_state = mb_cpu_dump_state;
342
cc->set_pc = mb_cpu_set_pc;
343
+ cc->get_pc = mb_cpu_get_pc;
344
cc->gdb_read_register = mb_cpu_gdb_read_register;
345
cc->gdb_write_register = mb_cpu_gdb_write_register;
346
347
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
348
index XXXXXXX..XXXXXXX 100644
349
--- a/target/mips/cpu.c
350
+++ b/target/mips/cpu.c
351
@@ -XXX,XX +XXX,XX @@ static void mips_cpu_set_pc(CPUState *cs, vaddr value)
352
mips_env_set_pc(&cpu->env, value);
353
}
354
355
+static vaddr mips_cpu_get_pc(CPUState *cs)
356
+{
357
+ MIPSCPU *cpu = MIPS_CPU(cs);
358
+
359
+ return cpu->env.active_tc.PC;
360
+}
361
+
362
static bool mips_cpu_has_work(CPUState *cs)
363
{
364
MIPSCPU *cpu = MIPS_CPU(cs);
365
@@ -XXX,XX +XXX,XX @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
366
cc->has_work = mips_cpu_has_work;
367
cc->dump_state = mips_cpu_dump_state;
368
cc->set_pc = mips_cpu_set_pc;
369
+ cc->get_pc = mips_cpu_get_pc;
370
cc->gdb_read_register = mips_cpu_gdb_read_register;
371
cc->gdb_write_register = mips_cpu_gdb_write_register;
372
#ifndef CONFIG_USER_ONLY
373
diff --git a/target/nios2/cpu.c b/target/nios2/cpu.c
374
index XXXXXXX..XXXXXXX 100644
375
--- a/target/nios2/cpu.c
376
+++ b/target/nios2/cpu.c
377
@@ -XXX,XX +XXX,XX @@ static void nios2_cpu_set_pc(CPUState *cs, vaddr value)
378
env->pc = value;
379
}
380
381
+static vaddr nios2_cpu_get_pc(CPUState *cs)
382
+{
383
+ Nios2CPU *cpu = NIOS2_CPU(cs);
384
+ CPUNios2State *env = &cpu->env;
385
+
386
+ return env->pc;
387
+}
388
+
389
static bool nios2_cpu_has_work(CPUState *cs)
390
{
391
return cs->interrupt_request & CPU_INTERRUPT_HARD;
392
@@ -XXX,XX +XXX,XX @@ static void nios2_cpu_class_init(ObjectClass *oc, void *data)
393
cc->has_work = nios2_cpu_has_work;
394
cc->dump_state = nios2_cpu_dump_state;
395
cc->set_pc = nios2_cpu_set_pc;
396
+ cc->get_pc = nios2_cpu_get_pc;
397
cc->disas_set_info = nios2_cpu_disas_set_info;
398
#ifndef CONFIG_USER_ONLY
399
cc->sysemu_ops = &nios2_sysemu_ops;
400
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
401
index XXXXXXX..XXXXXXX 100644
402
--- a/target/openrisc/cpu.c
403
+++ b/target/openrisc/cpu.c
404
@@ -XXX,XX +XXX,XX @@ static void openrisc_cpu_set_pc(CPUState *cs, vaddr value)
405
cpu->env.dflag = 0;
406
}
407
408
+static vaddr openrisc_cpu_get_pc(CPUState *cs)
409
+{
410
+ OpenRISCCPU *cpu = OPENRISC_CPU(cs);
411
+
412
+ return cpu->env.pc;
413
+}
414
+
415
static void openrisc_cpu_synchronize_from_tb(CPUState *cs,
416
const TranslationBlock *tb)
417
{
418
@@ -XXX,XX +XXX,XX @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
419
cc->has_work = openrisc_cpu_has_work;
420
cc->dump_state = openrisc_cpu_dump_state;
421
cc->set_pc = openrisc_cpu_set_pc;
422
+ cc->get_pc = openrisc_cpu_get_pc;
423
cc->gdb_read_register = openrisc_cpu_gdb_read_register;
424
cc->gdb_write_register = openrisc_cpu_gdb_write_register;
425
#ifndef CONFIG_USER_ONLY
426
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
427
index XXXXXXX..XXXXXXX 100644
428
--- a/target/ppc/cpu_init.c
429
+++ b/target/ppc/cpu_init.c
430
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_set_pc(CPUState *cs, vaddr value)
431
cpu->env.nip = value;
432
}
433
434
+static vaddr ppc_cpu_get_pc(CPUState *cs)
435
+{
436
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
437
+
438
+ return cpu->env.nip;
439
+}
440
+
441
static bool ppc_cpu_has_work(CPUState *cs)
442
{
443
PowerPCCPU *cpu = POWERPC_CPU(cs);
444
@@ -XXX,XX +XXX,XX @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
445
cc->has_work = ppc_cpu_has_work;
446
cc->dump_state = ppc_cpu_dump_state;
447
cc->set_pc = ppc_cpu_set_pc;
448
+ cc->get_pc = ppc_cpu_get_pc;
449
cc->gdb_read_register = ppc_cpu_gdb_read_register;
450
cc->gdb_write_register = ppc_cpu_gdb_write_register;
451
#ifndef CONFIG_USER_ONLY
452
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
453
index XXXXXXX..XXXXXXX 100644
454
--- a/target/riscv/cpu.c
455
+++ b/target/riscv/cpu.c
456
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_set_pc(CPUState *cs, vaddr value)
457
}
458
}
459
460
+static vaddr riscv_cpu_get_pc(CPUState *cs)
461
+{
462
+ RISCVCPU *cpu = RISCV_CPU(cs);
463
+ CPURISCVState *env = &cpu->env;
464
+
465
+ /* Match cpu_get_tb_cpu_state. */
466
+ if (env->xl == MXL_RV32) {
467
+ return env->pc & UINT32_MAX;
468
+ }
469
+ return env->pc;
470
+}
471
+
472
static void riscv_cpu_synchronize_from_tb(CPUState *cs,
473
const TranslationBlock *tb)
474
{
475
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
476
cc->has_work = riscv_cpu_has_work;
477
cc->dump_state = riscv_cpu_dump_state;
478
cc->set_pc = riscv_cpu_set_pc;
479
+ cc->get_pc = riscv_cpu_get_pc;
480
cc->gdb_read_register = riscv_cpu_gdb_read_register;
481
cc->gdb_write_register = riscv_cpu_gdb_write_register;
482
cc->gdb_num_core_regs = 33;
483
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
484
index XXXXXXX..XXXXXXX 100644
485
--- a/target/rx/cpu.c
486
+++ b/target/rx/cpu.c
487
@@ -XXX,XX +XXX,XX @@ static void rx_cpu_set_pc(CPUState *cs, vaddr value)
488
cpu->env.pc = value;
489
}
490
491
+static vaddr rx_cpu_get_pc(CPUState *cs)
492
+{
493
+ RXCPU *cpu = RX_CPU(cs);
494
+
495
+ return cpu->env.pc;
496
+}
497
+
498
static void rx_cpu_synchronize_from_tb(CPUState *cs,
499
const TranslationBlock *tb)
500
{
501
@@ -XXX,XX +XXX,XX @@ static void rx_cpu_class_init(ObjectClass *klass, void *data)
502
cc->has_work = rx_cpu_has_work;
503
cc->dump_state = rx_cpu_dump_state;
504
cc->set_pc = rx_cpu_set_pc;
505
+ cc->get_pc = rx_cpu_get_pc;
506
507
#ifndef CONFIG_USER_ONLY
508
cc->sysemu_ops = &rx_sysemu_ops;
509
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
510
index XXXXXXX..XXXXXXX 100644
511
--- a/target/s390x/cpu.c
512
+++ b/target/s390x/cpu.c
513
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_set_pc(CPUState *cs, vaddr value)
514
cpu->env.psw.addr = value;
515
}
516
517
+static vaddr s390_cpu_get_pc(CPUState *cs)
518
+{
519
+ S390CPU *cpu = S390_CPU(cs);
520
+
521
+ return cpu->env.psw.addr;
522
+}
523
+
524
static bool s390_cpu_has_work(CPUState *cs)
525
{
526
S390CPU *cpu = S390_CPU(cs);
527
@@ -XXX,XX +XXX,XX @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
528
cc->has_work = s390_cpu_has_work;
529
cc->dump_state = s390_cpu_dump_state;
530
cc->set_pc = s390_cpu_set_pc;
531
+ cc->get_pc = s390_cpu_get_pc;
532
cc->gdb_read_register = s390_cpu_gdb_read_register;
533
cc->gdb_write_register = s390_cpu_gdb_write_register;
534
#ifndef CONFIG_USER_ONLY
535
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
536
index XXXXXXX..XXXXXXX 100644
537
--- a/target/sh4/cpu.c
538
+++ b/target/sh4/cpu.c
539
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_set_pc(CPUState *cs, vaddr value)
540
cpu->env.pc = value;
541
}
542
543
+static vaddr superh_cpu_get_pc(CPUState *cs)
544
+{
545
+ SuperHCPU *cpu = SUPERH_CPU(cs);
546
+
547
+ return cpu->env.pc;
548
+}
549
+
550
static void superh_cpu_synchronize_from_tb(CPUState *cs,
551
const TranslationBlock *tb)
552
{
553
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_class_init(ObjectClass *oc, void *data)
554
cc->has_work = superh_cpu_has_work;
555
cc->dump_state = superh_cpu_dump_state;
556
cc->set_pc = superh_cpu_set_pc;
557
+ cc->get_pc = superh_cpu_get_pc;
558
cc->gdb_read_register = superh_cpu_gdb_read_register;
559
cc->gdb_write_register = superh_cpu_gdb_write_register;
560
#ifndef CONFIG_USER_ONLY
561
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
562
index XXXXXXX..XXXXXXX 100644
563
--- a/target/sparc/cpu.c
564
+++ b/target/sparc/cpu.c
565
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_set_pc(CPUState *cs, vaddr value)
566
cpu->env.npc = value + 4;
567
}
568
569
+static vaddr sparc_cpu_get_pc(CPUState *cs)
570
+{
571
+ SPARCCPU *cpu = SPARC_CPU(cs);
572
+
573
+ return cpu->env.pc;
574
+}
575
+
576
static void sparc_cpu_synchronize_from_tb(CPUState *cs,
577
const TranslationBlock *tb)
578
{
579
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data)
580
cc->memory_rw_debug = sparc_cpu_memory_rw_debug;
581
#endif
582
cc->set_pc = sparc_cpu_set_pc;
583
+ cc->get_pc = sparc_cpu_get_pc;
584
cc->gdb_read_register = sparc_cpu_gdb_read_register;
585
cc->gdb_write_register = sparc_cpu_gdb_write_register;
586
#ifndef CONFIG_USER_ONLY
587
diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c
588
index XXXXXXX..XXXXXXX 100644
589
--- a/target/tricore/cpu.c
590
+++ b/target/tricore/cpu.c
591
@@ -XXX,XX +XXX,XX @@ static void tricore_cpu_set_pc(CPUState *cs, vaddr value)
592
env->PC = value & ~(target_ulong)1;
593
}
594
595
+static vaddr tricore_cpu_get_pc(CPUState *cs)
596
+{
597
+ TriCoreCPU *cpu = TRICORE_CPU(cs);
598
+ CPUTriCoreState *env = &cpu->env;
599
+
600
+ return env->PC;
601
+}
602
+
603
static void tricore_cpu_synchronize_from_tb(CPUState *cs,
604
const TranslationBlock *tb)
605
{
606
@@ -XXX,XX +XXX,XX @@ static void tricore_cpu_class_init(ObjectClass *c, void *data)
607
608
cc->dump_state = tricore_cpu_dump_state;
609
cc->set_pc = tricore_cpu_set_pc;
610
+ cc->get_pc = tricore_cpu_get_pc;
611
cc->sysemu_ops = &tricore_sysemu_ops;
612
cc->tcg_ops = &tricore_tcg_ops;
613
}
614
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
615
index XXXXXXX..XXXXXXX 100644
616
--- a/target/xtensa/cpu.c
617
+++ b/target/xtensa/cpu.c
618
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_set_pc(CPUState *cs, vaddr value)
619
cpu->env.pc = value;
620
}
621
622
+static vaddr xtensa_cpu_get_pc(CPUState *cs)
623
+{
624
+ XtensaCPU *cpu = XTENSA_CPU(cs);
625
+
626
+ return cpu->env.pc;
627
+}
628
+
629
static bool xtensa_cpu_has_work(CPUState *cs)
630
{
631
#ifndef CONFIG_USER_ONLY
632
@@ -XXX,XX +XXX,XX @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
633
cc->has_work = xtensa_cpu_has_work;
634
cc->dump_state = xtensa_cpu_dump_state;
635
cc->set_pc = xtensa_cpu_set_pc;
636
+ cc->get_pc = xtensa_cpu_get_pc;
637
cc->gdb_read_register = xtensa_cpu_gdb_read_register;
638
cc->gdb_write_register = xtensa_cpu_gdb_write_register;
639
cc->gdb_stop_before_watchpoint = true;
640
--
178
--
641
2.34.1
179
2.34.1
642
643
diff view generated by jsdifflib
1
This structure will shortly contain more than just
1
Delay test of plugin_tb->mem_helper until the inject pass.
2
data for accessing MMIO. Rename the 'addr' member
3
to 'xlat_section' to more clearly indicate its purpose.
4
2
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
5
---
10
include/exec/cpu-defs.h | 22 ++++----
6
accel/tcg/plugin-gen.c | 37 ++++++++++++++++---------------------
11
accel/tcg/cputlb.c | 102 +++++++++++++++++++------------------
7
1 file changed, 16 insertions(+), 21 deletions(-)
12
target/arm/mte_helper.c | 14 ++---
13
target/arm/sve_helper.c | 4 +-
14
target/arm/translate-a64.c | 2 +-
15
5 files changed, 73 insertions(+), 71 deletions(-)
16
8
17
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
9
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
18
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
19
--- a/include/exec/cpu-defs.h
11
--- a/accel/tcg/plugin-gen.c
20
+++ b/include/exec/cpu-defs.h
12
+++ b/accel/tcg/plugin-gen.c
21
@@ -XXX,XX +XXX,XX @@ typedef uint64_t target_ulong;
13
@@ -XXX,XX +XXX,XX @@ enum plugin_gen_from {
22
# endif
14
PLUGIN_GEN_FROM_INSN,
23
# endif
15
PLUGIN_GEN_FROM_MEM,
24
16
PLUGIN_GEN_AFTER_INSN,
25
+/* Minimalized TLB entry for use by TCG fast path. */
17
+ PLUGIN_GEN_AFTER_TB,
26
typedef struct CPUTLBEntry {
18
PLUGIN_GEN_N_FROMS,
27
/* bit TARGET_LONG_BITS to TARGET_PAGE_BITS : virtual address
19
};
28
bit TARGET_PAGE_BITS-1..4 : Nonzero for accesses that should not
20
29
@@ -XXX,XX +XXX,XX @@ typedef struct CPUTLBEntry {
21
@@ -XXX,XX +XXX,XX @@ static void inject_mem_enable_helper(struct qemu_plugin_tb *ptb,
30
22
/* called before finishing a TB with exit_tb, goto_tb or goto_ptr */
31
QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
23
void plugin_gen_disable_mem_helpers(void)
32
24
{
33
-/* The IOTLB is not accessed directly inline by generated TCG code,
25
- /*
34
- * so the CPUIOTLBEntry layout is not as critical as that of the
26
- * We could emit the clearing unconditionally and be done. However, this can
35
- * CPUTLBEntry. (This is also why we don't want to combine the two
27
- * be wasteful if for instance plugins don't track memory accesses, or if
36
- * structs into one.)
28
- * most TBs don't use helpers. Instead, emit the clearing iff the TB calls
37
+/*
29
- * helpers that might access guest memory.
38
+ * The full TLB entry, which is not accessed by generated TCG code,
30
- *
39
+ * so the layout is not as critical as that of CPUTLBEntry. This is
31
- * Note: we do not reset plugin_tb->mem_helper here; a TB might have several
40
+ * also why we don't want to combine the two structs.
32
- * exit points, and we want to emit the clearing from all of them.
41
*/
33
- */
42
-typedef struct CPUIOTLBEntry {
34
- if (!tcg_ctx->plugin_tb->mem_helper) {
43
+typedef struct CPUTLBEntryFull {
35
- return;
44
/*
36
+ if (tcg_ctx->plugin_insn) {
45
- * @addr contains:
37
+ tcg_gen_plugin_cb(PLUGIN_GEN_AFTER_TB);
46
+ * @xlat_section contains:
47
* - in the lower TARGET_PAGE_BITS, a physical section number
48
* - with the lower TARGET_PAGE_BITS masked off, an offset which
49
* must be added to the virtual address to obtain:
50
@@ -XXX,XX +XXX,XX @@ typedef struct CPUIOTLBEntry {
51
* number is PHYS_SECTION_NOTDIRTY or PHYS_SECTION_ROM)
52
* + the offset within the target MemoryRegion (otherwise)
53
*/
54
- hwaddr addr;
55
+ hwaddr xlat_section;
56
MemTxAttrs attrs;
57
-} CPUIOTLBEntry;
58
+} CPUTLBEntryFull;
59
60
/*
61
* Data elements that are per MMU mode, minus the bits accessed by
62
@@ -XXX,XX +XXX,XX @@ typedef struct CPUTLBDesc {
63
size_t vindex;
64
/* The tlb victim table, in two parts. */
65
CPUTLBEntry vtable[CPU_VTLB_SIZE];
66
- CPUIOTLBEntry viotlb[CPU_VTLB_SIZE];
67
- /* The iotlb. */
68
- CPUIOTLBEntry *iotlb;
69
+ CPUTLBEntryFull vfulltlb[CPU_VTLB_SIZE];
70
+ CPUTLBEntryFull *fulltlb;
71
} CPUTLBDesc;
72
73
/*
74
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/accel/tcg/cputlb.c
77
+++ b/accel/tcg/cputlb.c
78
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast,
79
}
38
}
80
39
- tcg_gen_st_ptr(tcg_constant_ptr(NULL), tcg_env,
81
g_free(fast->table);
40
- offsetof(CPUState, plugin_mem_cbs) - offsetof(ArchCPU, env));
82
- g_free(desc->iotlb);
83
+ g_free(desc->fulltlb);
84
85
tlb_window_reset(desc, now, 0);
86
/* desc->n_used_entries is cleared by the caller */
87
fast->mask = (new_size - 1) << CPU_TLB_ENTRY_BITS;
88
fast->table = g_try_new(CPUTLBEntry, new_size);
89
- desc->iotlb = g_try_new(CPUIOTLBEntry, new_size);
90
+ desc->fulltlb = g_try_new(CPUTLBEntryFull, new_size);
91
92
/*
93
* If the allocations fail, try smaller sizes. We just freed some
94
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast,
95
* allocations to fail though, so we progressively reduce the allocation
96
* size, aborting if we cannot even allocate the smallest TLB we support.
97
*/
98
- while (fast->table == NULL || desc->iotlb == NULL) {
99
+ while (fast->table == NULL || desc->fulltlb == NULL) {
100
if (new_size == (1 << CPU_TLB_DYN_MIN_BITS)) {
101
error_report("%s: %s", __func__, strerror(errno));
102
abort();
103
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast,
104
fast->mask = (new_size - 1) << CPU_TLB_ENTRY_BITS;
105
106
g_free(fast->table);
107
- g_free(desc->iotlb);
108
+ g_free(desc->fulltlb);
109
fast->table = g_try_new(CPUTLBEntry, new_size);
110
- desc->iotlb = g_try_new(CPUIOTLBEntry, new_size);
111
+ desc->fulltlb = g_try_new(CPUTLBEntryFull, new_size);
112
}
113
}
41
}
114
42
115
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_init(CPUTLBDesc *desc, CPUTLBDescFast *fast, int64_t now)
43
static void plugin_gen_insn_udata(const struct qemu_plugin_tb *ptb,
116
desc->n_used_entries = 0;
44
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_enable_mem_helper(struct qemu_plugin_tb *ptb,
117
fast->mask = (n_entries - 1) << CPU_TLB_ENTRY_BITS;
45
inject_mem_enable_helper(ptb, insn, begin_op);
118
fast->table = g_new(CPUTLBEntry, n_entries);
119
- desc->iotlb = g_new(CPUIOTLBEntry, n_entries);
120
+ desc->fulltlb = g_new(CPUTLBEntryFull, n_entries);
121
tlb_mmu_flush_locked(desc, fast);
122
}
46
}
123
47
124
@@ -XXX,XX +XXX,XX @@ void tlb_destroy(CPUState *cpu)
48
-static void gen_disable_mem_helper(struct qemu_plugin_tb *ptb,
125
CPUTLBDescFast *fast = &env_tlb(env)->f[i];
49
- struct qemu_plugin_insn *insn)
126
50
+static void gen_disable_mem_helper(void)
127
g_free(fast->table);
51
{
128
- g_free(desc->iotlb);
52
- if (insn->mem_helper) {
129
+ g_free(desc->fulltlb);
53
- tcg_gen_st_ptr(tcg_constant_ptr(0), tcg_env,
130
}
54
- offsetof(CPUState, plugin_mem_cbs) -
55
- offsetof(ArchCPU, env));
56
- }
57
+ tcg_gen_st_ptr(tcg_constant_ptr(0), tcg_env,
58
+ offsetof(CPUState, plugin_mem_cbs) -
59
+ offsetof(ArchCPU, env));
131
}
60
}
132
61
133
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
62
static void gen_udata_cb(struct qemu_plugin_dyn_cb *cb)
134
63
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
135
/* Evict the old entry into the victim tlb. */
64
tcg_ctx->emit_before_op = op;
136
copy_tlb_helper_locked(tv, te);
65
137
- desc->viotlb[vidx] = desc->iotlb[index];
66
switch (from) {
138
+ desc->vfulltlb[vidx] = desc->fulltlb[index];
67
+ case PLUGIN_GEN_AFTER_TB:
139
tlb_n_used_entries_dec(env, mmu_idx);
68
+ if (plugin_tb->mem_helper) {
140
}
69
+ gen_disable_mem_helper();
141
70
+ }
142
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
71
+ break;
143
* subtract here is that of the page base, and not the same as the
72
+
144
* vaddr we add back in io_readx()/io_writex()/get_page_addr_code().
73
case PLUGIN_GEN_AFTER_INSN:
145
*/
74
assert(insn != NULL);
146
- desc->iotlb[index].addr = iotlb - vaddr_page;
75
- gen_disable_mem_helper(plugin_tb, insn);
147
- desc->iotlb[index].attrs = attrs;
76
+ if (insn->mem_helper) {
148
+ desc->fulltlb[index].xlat_section = iotlb - vaddr_page;
77
+ gen_disable_mem_helper();
149
+ desc->fulltlb[index].attrs = attrs;
78
+ }
150
79
break;
151
/* Now calculate the new entry */
80
152
tn.addend = addend - vaddr_page;
81
case PLUGIN_GEN_FROM_TB:
153
@@ -XXX,XX +XXX,XX @@ static inline void cpu_transaction_failed(CPUState *cpu, hwaddr physaddr,
154
}
155
}
156
157
-static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
158
+static uint64_t io_readx(CPUArchState *env, CPUTLBEntryFull *full,
159
int mmu_idx, target_ulong addr, uintptr_t retaddr,
160
MMUAccessType access_type, MemOp op)
161
{
162
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
163
bool locked = false;
164
MemTxResult r;
165
166
- section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
167
+ section = iotlb_to_section(cpu, full->xlat_section, full->attrs);
168
mr = section->mr;
169
- mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
170
+ mr_offset = (full->xlat_section & TARGET_PAGE_MASK) + addr;
171
cpu->mem_io_pc = retaddr;
172
if (!cpu->can_do_io) {
173
cpu_io_recompile(cpu, retaddr);
174
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
175
qemu_mutex_lock_iothread();
176
locked = true;
177
}
178
- r = memory_region_dispatch_read(mr, mr_offset, &val, op, iotlbentry->attrs);
179
+ r = memory_region_dispatch_read(mr, mr_offset, &val, op, full->attrs);
180
if (r != MEMTX_OK) {
181
hwaddr physaddr = mr_offset +
182
section->offset_within_address_space -
183
section->offset_within_region;
184
185
cpu_transaction_failed(cpu, physaddr, addr, memop_size(op), access_type,
186
- mmu_idx, iotlbentry->attrs, r, retaddr);
187
+ mmu_idx, full->attrs, r, retaddr);
188
}
189
if (locked) {
190
qemu_mutex_unlock_iothread();
191
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
192
}
193
194
/*
195
- * Save a potentially trashed IOTLB entry for later lookup by plugin.
196
- * This is read by tlb_plugin_lookup if the iotlb entry doesn't match
197
+ * Save a potentially trashed CPUTLBEntryFull for later lookup by plugin.
198
+ * This is read by tlb_plugin_lookup if the fulltlb entry doesn't match
199
* because of the side effect of io_writex changing memory layout.
200
*/
201
static void save_iotlb_data(CPUState *cs, hwaddr addr,
202
@@ -XXX,XX +XXX,XX @@ static void save_iotlb_data(CPUState *cs, hwaddr addr,
203
#endif
204
}
205
206
-static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
207
+static void io_writex(CPUArchState *env, CPUTLBEntryFull *full,
208
int mmu_idx, uint64_t val, target_ulong addr,
209
uintptr_t retaddr, MemOp op)
210
{
211
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
212
bool locked = false;
213
MemTxResult r;
214
215
- section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
216
+ section = iotlb_to_section(cpu, full->xlat_section, full->attrs);
217
mr = section->mr;
218
- mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
219
+ mr_offset = (full->xlat_section & TARGET_PAGE_MASK) + addr;
220
if (!cpu->can_do_io) {
221
cpu_io_recompile(cpu, retaddr);
222
}
223
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
224
* The memory_region_dispatch may trigger a flush/resize
225
* so for plugins we save the iotlb_data just in case.
226
*/
227
- save_iotlb_data(cpu, iotlbentry->addr, section, mr_offset);
228
+ save_iotlb_data(cpu, full->xlat_section, section, mr_offset);
229
230
if (!qemu_mutex_iothread_locked()) {
231
qemu_mutex_lock_iothread();
232
locked = true;
233
}
234
- r = memory_region_dispatch_write(mr, mr_offset, val, op, iotlbentry->attrs);
235
+ r = memory_region_dispatch_write(mr, mr_offset, val, op, full->attrs);
236
if (r != MEMTX_OK) {
237
hwaddr physaddr = mr_offset +
238
section->offset_within_address_space -
239
section->offset_within_region;
240
241
cpu_transaction_failed(cpu, physaddr, addr, memop_size(op),
242
- MMU_DATA_STORE, mmu_idx, iotlbentry->attrs, r,
243
+ MMU_DATA_STORE, mmu_idx, full->attrs, r,
244
retaddr);
245
}
246
if (locked) {
247
@@ -XXX,XX +XXX,XX @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
248
copy_tlb_helper_locked(vtlb, &tmptlb);
249
qemu_spin_unlock(&env_tlb(env)->c.lock);
250
251
- CPUIOTLBEntry tmpio, *io = &env_tlb(env)->d[mmu_idx].iotlb[index];
252
- CPUIOTLBEntry *vio = &env_tlb(env)->d[mmu_idx].viotlb[vidx];
253
- tmpio = *io; *io = *vio; *vio = tmpio;
254
+ CPUTLBEntryFull *f1 = &env_tlb(env)->d[mmu_idx].fulltlb[index];
255
+ CPUTLBEntryFull *f2 = &env_tlb(env)->d[mmu_idx].vfulltlb[vidx];
256
+ CPUTLBEntryFull tmpf;
257
+ tmpf = *f1; *f1 = *f2; *f2 = tmpf;
258
return true;
259
}
260
}
261
@@ -XXX,XX +XXX,XX @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
262
(ADDR) & TARGET_PAGE_MASK)
263
264
static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size,
265
- CPUIOTLBEntry *iotlbentry, uintptr_t retaddr)
266
+ CPUTLBEntryFull *full, uintptr_t retaddr)
267
{
268
- ram_addr_t ram_addr = mem_vaddr + iotlbentry->addr;
269
+ ram_addr_t ram_addr = mem_vaddr + full->xlat_section;
270
271
trace_memory_notdirty_write_access(mem_vaddr, ram_addr, size);
272
273
@@ -XXX,XX +XXX,XX @@ int probe_access_flags(CPUArchState *env, target_ulong addr,
274
/* Handle clean RAM pages. */
275
if (unlikely(flags & TLB_NOTDIRTY)) {
276
uintptr_t index = tlb_index(env, mmu_idx, addr);
277
- CPUIOTLBEntry *iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
278
+ CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
279
280
- notdirty_write(env_cpu(env), addr, 1, iotlbentry, retaddr);
281
+ notdirty_write(env_cpu(env), addr, 1, full, retaddr);
282
flags &= ~TLB_NOTDIRTY;
283
}
284
285
@@ -XXX,XX +XXX,XX @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
286
287
if (unlikely(flags & (TLB_NOTDIRTY | TLB_WATCHPOINT))) {
288
uintptr_t index = tlb_index(env, mmu_idx, addr);
289
- CPUIOTLBEntry *iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
290
+ CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
291
292
/* Handle watchpoints. */
293
if (flags & TLB_WATCHPOINT) {
294
int wp_access = (access_type == MMU_DATA_STORE
295
? BP_MEM_WRITE : BP_MEM_READ);
296
cpu_check_watchpoint(env_cpu(env), addr, size,
297
- iotlbentry->attrs, wp_access, retaddr);
298
+ full->attrs, wp_access, retaddr);
299
}
300
301
/* Handle clean RAM pages. */
302
if (flags & TLB_NOTDIRTY) {
303
- notdirty_write(env_cpu(env), addr, 1, iotlbentry, retaddr);
304
+ notdirty_write(env_cpu(env), addr, 1, full, retaddr);
305
}
306
}
307
308
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
309
* should have just filled the TLB. The one corner case is io_writex
310
* which can cause TLB flushes and potential resizing of the TLBs
311
* losing the information we need. In those cases we need to recover
312
- * data from a copy of the iotlbentry. As long as this always occurs
313
+ * data from a copy of the CPUTLBEntryFull. As long as this always occurs
314
* from the same thread (which a mem callback will be) this is safe.
315
*/
316
317
@@ -XXX,XX +XXX,XX @@ bool tlb_plugin_lookup(CPUState *cpu, target_ulong addr, int mmu_idx,
318
if (likely(tlb_hit(tlb_addr, addr))) {
319
/* We must have an iotlb entry for MMIO */
320
if (tlb_addr & TLB_MMIO) {
321
- CPUIOTLBEntry *iotlbentry;
322
- iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
323
+ CPUTLBEntryFull *full;
324
+ full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
325
data->is_io = true;
326
- data->v.io.section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
327
- data->v.io.offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
328
+ data->v.io.section =
329
+ iotlb_to_section(cpu, full->xlat_section, full->attrs);
330
+ data->v.io.offset = (full->xlat_section & TARGET_PAGE_MASK) + addr;
331
} else {
332
data->is_io = false;
333
data->v.ram.hostaddr = (void *)((uintptr_t)addr + tlbe->addend);
334
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
335
336
if (unlikely(tlb_addr & TLB_NOTDIRTY)) {
337
notdirty_write(env_cpu(env), addr, size,
338
- &env_tlb(env)->d[mmu_idx].iotlb[index], retaddr);
339
+ &env_tlb(env)->d[mmu_idx].fulltlb[index], retaddr);
340
}
341
342
return hostaddr;
343
@@ -XXX,XX +XXX,XX @@ load_helper(CPUArchState *env, target_ulong addr, MemOpIdx oi,
344
345
/* Handle anything that isn't just a straight memory access. */
346
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
347
- CPUIOTLBEntry *iotlbentry;
348
+ CPUTLBEntryFull *full;
349
bool need_swap;
350
351
/* For anything that is unaligned, recurse through full_load. */
352
@@ -XXX,XX +XXX,XX @@ load_helper(CPUArchState *env, target_ulong addr, MemOpIdx oi,
353
goto do_unaligned_access;
354
}
355
356
- iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
357
+ full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
358
359
/* Handle watchpoints. */
360
if (unlikely(tlb_addr & TLB_WATCHPOINT)) {
361
/* On watchpoint hit, this will longjmp out. */
362
cpu_check_watchpoint(env_cpu(env), addr, size,
363
- iotlbentry->attrs, BP_MEM_READ, retaddr);
364
+ full->attrs, BP_MEM_READ, retaddr);
365
}
366
367
need_swap = size > 1 && (tlb_addr & TLB_BSWAP);
368
369
/* Handle I/O access. */
370
if (likely(tlb_addr & TLB_MMIO)) {
371
- return io_readx(env, iotlbentry, mmu_idx, addr, retaddr,
372
+ return io_readx(env, full, mmu_idx, addr, retaddr,
373
access_type, op ^ (need_swap * MO_BSWAP));
374
}
375
376
@@ -XXX,XX +XXX,XX @@ store_helper_unaligned(CPUArchState *env, target_ulong addr, uint64_t val,
377
*/
378
if (unlikely(tlb_addr & TLB_WATCHPOINT)) {
379
cpu_check_watchpoint(env_cpu(env), addr, size - size2,
380
- env_tlb(env)->d[mmu_idx].iotlb[index].attrs,
381
+ env_tlb(env)->d[mmu_idx].fulltlb[index].attrs,
382
BP_MEM_WRITE, retaddr);
383
}
384
if (unlikely(tlb_addr2 & TLB_WATCHPOINT)) {
385
cpu_check_watchpoint(env_cpu(env), page2, size2,
386
- env_tlb(env)->d[mmu_idx].iotlb[index2].attrs,
387
+ env_tlb(env)->d[mmu_idx].fulltlb[index2].attrs,
388
BP_MEM_WRITE, retaddr);
389
}
390
391
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
392
393
/* Handle anything that isn't just a straight memory access. */
394
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
395
- CPUIOTLBEntry *iotlbentry;
396
+ CPUTLBEntryFull *full;
397
bool need_swap;
398
399
/* For anything that is unaligned, recurse through byte stores. */
400
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
401
goto do_unaligned_access;
402
}
403
404
- iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
405
+ full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
406
407
/* Handle watchpoints. */
408
if (unlikely(tlb_addr & TLB_WATCHPOINT)) {
409
/* On watchpoint hit, this will longjmp out. */
410
cpu_check_watchpoint(env_cpu(env), addr, size,
411
- iotlbentry->attrs, BP_MEM_WRITE, retaddr);
412
+ full->attrs, BP_MEM_WRITE, retaddr);
413
}
414
415
need_swap = size > 1 && (tlb_addr & TLB_BSWAP);
416
417
/* Handle I/O access. */
418
if (tlb_addr & TLB_MMIO) {
419
- io_writex(env, iotlbentry, mmu_idx, val, addr, retaddr,
420
+ io_writex(env, full, mmu_idx, val, addr, retaddr,
421
op ^ (need_swap * MO_BSWAP));
422
return;
423
}
424
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
425
426
/* Handle clean RAM pages. */
427
if (tlb_addr & TLB_NOTDIRTY) {
428
- notdirty_write(env_cpu(env), addr, size, iotlbentry, retaddr);
429
+ notdirty_write(env_cpu(env), addr, size, full, retaddr);
430
}
431
432
haddr = (void *)((uintptr_t)addr + entry->addend);
433
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
434
index XXXXXXX..XXXXXXX 100644
435
--- a/target/arm/mte_helper.c
436
+++ b/target/arm/mte_helper.c
437
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
438
return tags + index;
439
#else
440
uintptr_t index;
441
- CPUIOTLBEntry *iotlbentry;
442
+ CPUTLBEntryFull *full;
443
int in_page, flags;
444
ram_addr_t ptr_ra;
445
hwaddr ptr_paddr, tag_paddr, xlat;
446
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
447
assert(!(flags & TLB_INVALID_MASK));
448
449
/*
450
- * Find the iotlbentry for ptr. This *must* be present in the TLB
451
+ * Find the CPUTLBEntryFull for ptr. This *must* be present in the TLB
452
* because we just found the mapping.
453
* TODO: Perhaps there should be a cputlb helper that returns a
454
* matching tlb entry + iotlb entry.
455
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
456
g_assert(tlb_hit(comparator, ptr));
457
}
458
# endif
459
- iotlbentry = &env_tlb(env)->d[ptr_mmu_idx].iotlb[index];
460
+ full = &env_tlb(env)->d[ptr_mmu_idx].fulltlb[index];
461
462
/* If the virtual page MemAttr != Tagged, access unchecked. */
463
- if (!arm_tlb_mte_tagged(&iotlbentry->attrs)) {
464
+ if (!arm_tlb_mte_tagged(&full->attrs)) {
465
return NULL;
466
}
467
468
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
469
int wp = ptr_access == MMU_DATA_LOAD ? BP_MEM_READ : BP_MEM_WRITE;
470
assert(ra != 0);
471
cpu_check_watchpoint(env_cpu(env), ptr, ptr_size,
472
- iotlbentry->attrs, wp, ra);
473
+ full->attrs, wp, ra);
474
}
475
476
/*
477
@@ -XXX,XX +XXX,XX @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
478
tag_paddr = ptr_paddr >> (LOG2_TAG_GRANULE + 1);
479
480
/* Look up the address in tag space. */
481
- tag_asi = iotlbentry->attrs.secure ? ARMASIdx_TagS : ARMASIdx_TagNS;
482
+ tag_asi = full->attrs.secure ? ARMASIdx_TagS : ARMASIdx_TagNS;
483
tag_as = cpu_get_address_space(env_cpu(env), tag_asi);
484
mr = address_space_translate(tag_as, tag_paddr, &xlat, NULL,
485
tag_access == MMU_DATA_STORE,
486
- iotlbentry->attrs);
487
+ full->attrs);
488
489
/*
490
* Note that @mr will never be NULL. If there is nothing in the address
491
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
492
index XXXXXXX..XXXXXXX 100644
493
--- a/target/arm/sve_helper.c
494
+++ b/target/arm/sve_helper.c
495
@@ -XXX,XX +XXX,XX @@ bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
496
g_assert(tlb_hit(comparator, addr));
497
# endif
498
499
- CPUIOTLBEntry *iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
500
- info->attrs = iotlbentry->attrs;
501
+ CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
502
+ info->attrs = full->attrs;
503
}
504
#endif
505
506
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
507
index XXXXXXX..XXXXXXX 100644
508
--- a/target/arm/translate-a64.c
509
+++ b/target/arm/translate-a64.c
510
@@ -XXX,XX +XXX,XX @@ static bool is_guarded_page(CPUARMState *env, DisasContext *s)
511
* table entry even for that case.
512
*/
513
return (tlb_hit(entry->addr_code, addr) &&
514
- arm_tlb_bti_gp(&env_tlb(env)->d[mmu_idx].iotlb[index].attrs));
515
+ arm_tlb_bti_gp(&env_tlb(env)->d[mmu_idx].fulltlb[index].attrs));
516
#endif
517
}
518
519
--
82
--
520
2.34.1
83
2.34.1
521
522
diff view generated by jsdifflib
1
From: Leandro Lupori <leandro.lupori@eldorado.org.br>
1
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
2
3
PowerPC64 processors handle direct branches better than indirect
4
ones, resulting in less stalled cycles and branch misses.
5
6
However, PPC's tb_target_set_jmp_target() was only using direct
7
branches for 16-bit jumps, while PowerPC64's unconditional branch
8
instructions are able to handle displacements of up to 26 bits.
9
To take advantage of this, now jumps whose displacements fit in
10
between 17 and 26 bits are also converted to direct branches.
11
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Leandro Lupori <leandro.lupori@eldorado.org.br>
14
[rth: Expanded some commentary.]
15
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
16
---
3
---
17
tcg/ppc/tcg-target.c.inc | 119 +++++++++++++++++++++++++++++----------
4
include/qemu/plugin.h | 1 -
18
1 file changed, 88 insertions(+), 31 deletions(-)
5
accel/tcg/plugin-gen.c | 286 ++++++++++-------------------------------
6
plugins/api.c | 8 +-
7
3 files changed, 67 insertions(+), 228 deletions(-)
19
8
20
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
9
diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h
21
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
22
--- a/tcg/ppc/tcg-target.c.inc
11
--- a/include/qemu/plugin.h
23
+++ b/tcg/ppc/tcg-target.c.inc
12
+++ b/include/qemu/plugin.h
24
@@ -XXX,XX +XXX,XX @@ static void tcg_out_mb(TCGContext *s, TCGArg a0)
13
@@ -XXX,XX +XXX,XX @@ enum plugin_dyn_cb_type {
25
tcg_out32(s, insn);
14
26
}
15
enum plugin_dyn_cb_subtype {
27
16
PLUGIN_CB_REGULAR,
28
+static inline uint64_t make_pair(tcg_insn_unit i1, tcg_insn_unit i2)
17
- PLUGIN_CB_REGULAR_R,
29
+{
18
PLUGIN_CB_INLINE,
30
+ if (HOST_BIG_ENDIAN) {
19
PLUGIN_N_CB_SUBTYPES,
31
+ return (uint64_t)i1 << 32 | i2;
20
};
32
+ }
21
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
33
+ return (uint64_t)i2 << 32 | i1;
22
index XXXXXXX..XXXXXXX 100644
34
+}
23
--- a/accel/tcg/plugin-gen.c
35
+
24
+++ b/accel/tcg/plugin-gen.c
36
+static inline void ppc64_replace2(uintptr_t rx, uintptr_t rw,
25
@@ -XXX,XX +XXX,XX @@ void HELPER(plugin_vcpu_mem_cb)(unsigned int vcpu_index,
37
+ tcg_insn_unit i0, tcg_insn_unit i1)
26
void *userdata)
38
+{
27
{ }
39
+#if TCG_TARGET_REG_BITS == 64
28
40
+ qatomic_set((uint64_t *)rw, make_pair(i0, i1));
29
-static void gen_empty_udata_cb(void (*gen_helper)(TCGv_i32, TCGv_ptr))
41
+ flush_idcache_range(rx, rw, 8);
30
-{
42
+#else
31
- TCGv_i32 cpu_index = tcg_temp_ebb_new_i32();
43
+ qemu_build_not_reached();
32
- TCGv_ptr udata = tcg_temp_ebb_new_ptr();
44
+#endif
33
-
45
+}
34
- tcg_gen_movi_ptr(udata, 0);
46
+
35
- tcg_gen_ld_i32(cpu_index, tcg_env,
47
+static inline void ppc64_replace4(uintptr_t rx, uintptr_t rw,
36
- -offsetof(ArchCPU, env) + offsetof(CPUState, cpu_index));
48
+ tcg_insn_unit i0, tcg_insn_unit i1,
37
- gen_helper(cpu_index, udata);
49
+ tcg_insn_unit i2, tcg_insn_unit i3)
38
-
50
+{
39
- tcg_temp_free_ptr(udata);
51
+ uint64_t p[2];
40
- tcg_temp_free_i32(cpu_index);
52
+
41
-}
53
+ p[!HOST_BIG_ENDIAN] = make_pair(i0, i1);
42
-
54
+ p[HOST_BIG_ENDIAN] = make_pair(i2, i3);
43
-static void gen_empty_udata_cb_no_wg(void)
44
-{
45
- gen_empty_udata_cb(gen_helper_plugin_vcpu_udata_cb_no_wg);
46
-}
47
-
48
-static void gen_empty_udata_cb_no_rwg(void)
49
-{
50
- gen_empty_udata_cb(gen_helper_plugin_vcpu_udata_cb_no_rwg);
51
-}
52
-
53
/*
54
* For now we only support addi_i64.
55
* When we support more ops, we can generate one empty inline cb for each.
56
@@ -XXX,XX +XXX,XX @@ static void gen_empty_mem_cb(TCGv_i64 addr, uint32_t info)
57
tcg_temp_free_i32(cpu_index);
58
}
59
60
-/*
61
- * Share the same function for enable/disable. When enabling, the NULL
62
- * pointer will be overwritten later.
63
- */
64
-static void gen_empty_mem_helper(void)
65
-{
66
- TCGv_ptr ptr = tcg_temp_ebb_new_ptr();
67
-
68
- tcg_gen_movi_ptr(ptr, 0);
69
- tcg_gen_st_ptr(ptr, tcg_env, offsetof(CPUState, plugin_mem_cbs) -
70
- offsetof(ArchCPU, env));
71
- tcg_temp_free_ptr(ptr);
72
-}
73
-
74
static void gen_plugin_cb_start(enum plugin_gen_from from,
75
enum plugin_gen_cb type, unsigned wr)
76
{
77
tcg_gen_plugin_cb_start(from, type, wr);
78
}
79
80
-static void gen_wrapped(enum plugin_gen_from from,
81
- enum plugin_gen_cb type, void (*func)(void))
82
-{
83
- gen_plugin_cb_start(from, type, 0);
84
- func();
85
- tcg_gen_plugin_cb_end();
86
-}
87
-
88
static void plugin_gen_empty_callback(enum plugin_gen_from from)
89
{
90
switch (from) {
91
case PLUGIN_GEN_AFTER_INSN:
92
case PLUGIN_GEN_FROM_TB:
93
- tcg_gen_plugin_cb(from);
94
- break;
95
case PLUGIN_GEN_FROM_INSN:
96
- /*
97
- * Note: plugin_gen_inject() relies on ENABLE_MEM_HELPER being
98
- * the first callback of an instruction
99
- */
100
- gen_wrapped(from, PLUGIN_GEN_ENABLE_MEM_HELPER,
101
- gen_empty_mem_helper);
102
- gen_wrapped(from, PLUGIN_GEN_CB_UDATA, gen_empty_udata_cb_no_rwg);
103
- gen_wrapped(from, PLUGIN_GEN_CB_UDATA_R, gen_empty_udata_cb_no_wg);
104
- gen_wrapped(from, PLUGIN_GEN_CB_INLINE, gen_empty_inline_cb);
105
+ tcg_gen_plugin_cb(from);
106
break;
107
default:
108
g_assert_not_reached();
109
@@ -XXX,XX +XXX,XX @@ static TCGOp *copy_mul_i32(TCGOp **begin_op, TCGOp *op, uint32_t v)
110
return op;
111
}
112
113
-static TCGOp *copy_st_ptr(TCGOp **begin_op, TCGOp *op)
114
-{
115
- if (UINTPTR_MAX == UINT32_MAX) {
116
- /* st_i32 */
117
- op = copy_op(begin_op, op, INDEX_op_st_i32);
118
- } else {
119
- /* st_i64 */
120
- op = copy_st_i64(begin_op, op);
121
- }
122
- return op;
123
-}
124
-
125
static TCGOp *copy_call(TCGOp **begin_op, TCGOp *op, void *func, int *cb_idx)
126
{
127
TCGOp *old_op;
128
@@ -XXX,XX +XXX,XX @@ static TCGOp *copy_call(TCGOp **begin_op, TCGOp *op, void *func, int *cb_idx)
129
return op;
130
}
131
132
-/*
133
- * When we append/replace ops here we are sensitive to changing patterns of
134
- * TCGOps generated by the tcg_gen_FOO calls when we generated the
135
- * empty callbacks. This will assert very quickly in a debug build as
136
- * we assert the ops we are replacing are the correct ones.
137
- */
138
-static TCGOp *append_udata_cb(const struct qemu_plugin_dyn_cb *cb,
139
- TCGOp *begin_op, TCGOp *op, int *cb_idx)
140
-{
141
- /* const_ptr */
142
- op = copy_const_ptr(&begin_op, op, cb->userp);
143
-
144
- /* copy the ld_i32, but note that we only have to copy it once */
145
- if (*cb_idx == -1) {
146
- op = copy_op(&begin_op, op, INDEX_op_ld_i32);
147
- } else {
148
- begin_op = QTAILQ_NEXT(begin_op, link);
149
- tcg_debug_assert(begin_op && begin_op->opc == INDEX_op_ld_i32);
150
- }
151
-
152
- /* call */
153
- op = copy_call(&begin_op, op, cb->regular.f.vcpu_udata, cb_idx);
154
-
155
- return op;
156
-}
157
-
158
static TCGOp *append_inline_cb(const struct qemu_plugin_dyn_cb *cb,
159
TCGOp *begin_op, TCGOp *op,
160
int *unused)
161
@@ -XXX,XX +XXX,XX @@ typedef TCGOp *(*inject_fn)(const struct qemu_plugin_dyn_cb *cb,
162
TCGOp *begin_op, TCGOp *op, int *intp);
163
typedef bool (*op_ok_fn)(const TCGOp *op, const struct qemu_plugin_dyn_cb *cb);
164
165
-static bool op_ok(const TCGOp *op, const struct qemu_plugin_dyn_cb *cb)
166
-{
167
- return true;
168
-}
169
-
170
static bool op_rw(const TCGOp *op, const struct qemu_plugin_dyn_cb *cb)
171
{
172
int w;
173
@@ -XXX,XX +XXX,XX @@ static void inject_cb_type(const GArray *cbs, TCGOp *begin_op,
174
rm_ops_range(begin_op, end_op);
175
}
176
177
-static void
178
-inject_udata_cb(const GArray *cbs, TCGOp *begin_op)
179
-{
180
- inject_cb_type(cbs, begin_op, append_udata_cb, op_ok);
181
-}
182
-
183
static void
184
inject_inline_cb(const GArray *cbs, TCGOp *begin_op, op_ok_fn ok)
185
{
186
@@ -XXX,XX +XXX,XX @@ inject_mem_cb(const GArray *cbs, TCGOp *begin_op)
187
inject_cb_type(cbs, begin_op, append_mem_cb, op_rw);
188
}
189
190
-/* we could change the ops in place, but we can reuse more code by copying */
191
-static void inject_mem_helper(TCGOp *begin_op, GArray *arr)
192
-{
193
- TCGOp *orig_op = begin_op;
194
- TCGOp *end_op;
195
- TCGOp *op;
196
-
197
- end_op = find_op(begin_op, INDEX_op_plugin_cb_end);
198
- tcg_debug_assert(end_op);
199
-
200
- /* const ptr */
201
- op = copy_const_ptr(&begin_op, end_op, arr);
202
-
203
- /* st_ptr */
204
- op = copy_st_ptr(&begin_op, op);
205
-
206
- rm_ops_range(orig_op, end_op);
207
-}
208
-
209
-/*
210
- * Tracking memory accesses performed from helpers requires extra work.
211
- * If an instruction is emulated with helpers, we do two things:
212
- * (1) copy the CB descriptors, and keep track of it so that they can be
213
- * freed later on, and (2) point CPUState.plugin_mem_cbs to the descriptors, so
214
- * that we can read them at run-time (i.e. when the helper executes).
215
- * This run-time access is performed from qemu_plugin_vcpu_mem_cb.
216
- *
217
- * Note that plugin_gen_disable_mem_helpers undoes (2). Since it
218
- * is possible that the code we generate after the instruction is
219
- * dead, we also add checks before generating tb_exit etc.
220
- */
221
-static void inject_mem_enable_helper(struct qemu_plugin_tb *ptb,
222
- struct qemu_plugin_insn *plugin_insn,
223
- TCGOp *begin_op)
224
-{
225
- GArray *cbs[2];
226
- GArray *arr;
227
- size_t n_cbs, i;
228
-
229
- cbs[0] = plugin_insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_REGULAR];
230
- cbs[1] = plugin_insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_INLINE];
231
-
232
- n_cbs = 0;
233
- for (i = 0; i < ARRAY_SIZE(cbs); i++) {
234
- n_cbs += cbs[i]->len;
235
- }
236
-
237
- plugin_insn->mem_helper = plugin_insn->calls_helpers && n_cbs;
238
- if (likely(!plugin_insn->mem_helper)) {
239
- rm_ops(begin_op);
240
- return;
241
- }
242
- ptb->mem_helper = true;
243
-
244
- arr = g_array_sized_new(false, false,
245
- sizeof(struct qemu_plugin_dyn_cb), n_cbs);
246
-
247
- for (i = 0; i < ARRAY_SIZE(cbs); i++) {
248
- g_array_append_vals(arr, cbs[i]->data, cbs[i]->len);
249
- }
250
-
251
- qemu_plugin_add_dyn_cb_arr(arr);
252
- inject_mem_helper(begin_op, arr);
253
-}
254
-
255
/* called before finishing a TB with exit_tb, goto_tb or goto_ptr */
256
void plugin_gen_disable_mem_helpers(void)
257
{
258
@@ -XXX,XX +XXX,XX @@ void plugin_gen_disable_mem_helpers(void)
259
}
260
}
261
262
-static void plugin_gen_insn_udata(const struct qemu_plugin_tb *ptb,
263
- TCGOp *begin_op, int insn_idx)
264
-{
265
- struct qemu_plugin_insn *insn = g_ptr_array_index(ptb->insns, insn_idx);
266
-
267
- inject_udata_cb(insn->cbs[PLUGIN_CB_INSN][PLUGIN_CB_REGULAR], begin_op);
268
-}
269
-
270
-static void plugin_gen_insn_udata_r(const struct qemu_plugin_tb *ptb,
271
- TCGOp *begin_op, int insn_idx)
272
-{
273
- struct qemu_plugin_insn *insn = g_ptr_array_index(ptb->insns, insn_idx);
274
-
275
- inject_udata_cb(insn->cbs[PLUGIN_CB_INSN][PLUGIN_CB_REGULAR_R], begin_op);
276
-}
277
-
278
-static void plugin_gen_insn_inline(const struct qemu_plugin_tb *ptb,
279
- TCGOp *begin_op, int insn_idx)
280
-{
281
- struct qemu_plugin_insn *insn = g_ptr_array_index(ptb->insns, insn_idx);
282
- inject_inline_cb(insn->cbs[PLUGIN_CB_INSN][PLUGIN_CB_INLINE],
283
- begin_op, op_ok);
284
-}
285
-
286
static void plugin_gen_mem_regular(const struct qemu_plugin_tb *ptb,
287
TCGOp *begin_op, int insn_idx)
288
{
289
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_mem_inline(const struct qemu_plugin_tb *ptb,
290
inject_inline_cb(cbs, begin_op, op_rw);
291
}
292
293
-static void plugin_gen_enable_mem_helper(struct qemu_plugin_tb *ptb,
294
- TCGOp *begin_op, int insn_idx)
295
+static void gen_enable_mem_helper(struct qemu_plugin_tb *ptb,
296
+ struct qemu_plugin_insn *insn)
297
{
298
- struct qemu_plugin_insn *insn = g_ptr_array_index(ptb->insns, insn_idx);
299
- inject_mem_enable_helper(ptb, insn, begin_op);
300
+ GArray *cbs[2];
301
+ GArray *arr;
302
+ size_t n_cbs;
55
+
303
+
56
+ /*
304
+ /*
57
+ * There's no convenient way to get the compiler to allocate a pair
305
+ * Tracking memory accesses performed from helpers requires extra work.
58
+ * of registers at an even index, so copy into r6/r7 and clobber.
306
+ * If an instruction is emulated with helpers, we do two things:
307
+ * (1) copy the CB descriptors, and keep track of it so that they can be
308
+ * freed later on, and (2) point CPUState.plugin_mem_cbs to the
309
+ * descriptors, so that we can read them at run-time
310
+ * (i.e. when the helper executes).
311
+ * This run-time access is performed from qemu_plugin_vcpu_mem_cb.
312
+ *
313
+ * Note that plugin_gen_disable_mem_helpers undoes (2). Since it
314
+ * is possible that the code we generate after the instruction is
315
+ * dead, we also add checks before generating tb_exit etc.
59
+ */
316
+ */
60
+ asm("mr %%r6, %1\n\t"
317
+ if (!insn->calls_helpers) {
61
+ "mr %%r7, %2\n\t"
62
+ "stq %%r6, %0"
63
+ : "=Q"(*(__int128 *)rw) : "r"(p[0]), "r"(p[1]) : "r6", "r7");
64
+ flush_idcache_range(rx, rw, 16);
65
+}
66
+
67
void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
68
uintptr_t jmp_rw, uintptr_t addr)
69
{
70
- if (TCG_TARGET_REG_BITS == 64) {
71
- tcg_insn_unit i1, i2;
72
- intptr_t tb_diff = addr - tc_ptr;
73
- intptr_t br_diff = addr - (jmp_rx + 4);
74
- uint64_t pair;
75
+ tcg_insn_unit i0, i1, i2, i3;
76
+ intptr_t tb_diff = addr - tc_ptr;
77
+ intptr_t br_diff = addr - (jmp_rx + 4);
78
+ intptr_t lo, hi;
79
80
- /* This does not exercise the range of the branch, but we do
81
- still need to be able to load the new value of TCG_REG_TB.
82
- But this does still happen quite often. */
83
- if (tb_diff == (int16_t)tb_diff) {
84
- i1 = ADDI | TAI(TCG_REG_TB, TCG_REG_TB, tb_diff);
85
- i2 = B | (br_diff & 0x3fffffc);
86
- } else {
87
- intptr_t lo = (int16_t)tb_diff;
88
- intptr_t hi = (int32_t)(tb_diff - lo);
89
- assert(tb_diff == hi + lo);
90
- i1 = ADDIS | TAI(TCG_REG_TB, TCG_REG_TB, hi >> 16);
91
- i2 = ADDI | TAI(TCG_REG_TB, TCG_REG_TB, lo);
92
- }
93
-#if HOST_BIG_ENDIAN
94
- pair = (uint64_t)i1 << 32 | i2;
95
-#else
96
- pair = (uint64_t)i2 << 32 | i1;
97
-#endif
98
-
99
- /* As per the enclosing if, this is ppc64. Avoid the _Static_assert
100
- within qatomic_set that would fail to build a ppc32 host. */
101
- qatomic_set__nocheck((uint64_t *)jmp_rw, pair);
102
- flush_idcache_range(jmp_rx, jmp_rw, 8);
103
- } else {
104
+ if (TCG_TARGET_REG_BITS == 32) {
105
intptr_t diff = addr - jmp_rx;
106
tcg_debug_assert(in_range_b(diff));
107
qatomic_set((uint32_t *)jmp_rw, B | (diff & 0x3fffffc));
108
flush_idcache_range(jmp_rx, jmp_rw, 4);
109
+ return;
110
}
111
+
112
+ /*
113
+ * For 16-bit displacements, we can use a single add + branch.
114
+ * This happens quite often.
115
+ */
116
+ if (tb_diff == (int16_t)tb_diff) {
117
+ i0 = ADDI | TAI(TCG_REG_TB, TCG_REG_TB, tb_diff);
118
+ i1 = B | (br_diff & 0x3fffffc);
119
+ ppc64_replace2(jmp_rx, jmp_rw, i0, i1);
120
+ return;
318
+ return;
121
+ }
319
+ }
122
+
320
+
123
+ lo = (int16_t)tb_diff;
321
+ cbs[0] = insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_REGULAR];
124
+ hi = (int32_t)(tb_diff - lo);
322
+ cbs[1] = insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_INLINE];
125
+ assert(tb_diff == hi + lo);
323
+ n_cbs = cbs[0]->len + cbs[1]->len;
126
+ i0 = ADDIS | TAI(TCG_REG_TB, TCG_REG_TB, hi >> 16);
324
+
127
+ i1 = ADDI | TAI(TCG_REG_TB, TCG_REG_TB, lo);
325
+ if (n_cbs == 0) {
128
+
326
+ insn->mem_helper = false;
129
+ /*
130
+ * Without stq from 2.07, we can only update two insns,
131
+ * and those must be the ones that load the target address.
132
+ */
133
+ if (!have_isa_2_07) {
134
+ ppc64_replace2(jmp_rx, jmp_rw, i0, i1);
135
+ return;
327
+ return;
136
+ }
328
+ }
137
+
329
+ insn->mem_helper = true;
138
+ /*
330
+ ptb->mem_helper = true;
139
+ * For 26-bit displacements, we can use a direct branch.
331
+
140
+ * Otherwise we still need the indirect branch, which we
332
+ arr = g_array_sized_new(false, false,
141
+ * must restore after a potential direct branch write.
333
+ sizeof(struct qemu_plugin_dyn_cb), n_cbs);
142
+ */
334
+ g_array_append_vals(arr, cbs[0]->data, cbs[0]->len);
143
+ br_diff -= 4;
335
+ g_array_append_vals(arr, cbs[1]->data, cbs[1]->len);
144
+ if (in_range_b(br_diff)) {
336
+
145
+ i2 = B | (br_diff & 0x3fffffc);
337
+ qemu_plugin_add_dyn_cb_arr(arr);
146
+ i3 = NOP;
338
+
147
+ } else {
339
+ tcg_gen_st_ptr(tcg_constant_ptr((intptr_t)arr), tcg_env,
148
+ i2 = MTSPR | RS(TCG_REG_TB) | CTR;
340
+ offsetof(CPUState, plugin_mem_cbs) -
149
+ i3 = BCCTR | BO_ALWAYS;
341
+ offsetof(ArchCPU, env));
150
+ }
342
}
151
+ ppc64_replace4(jmp_rx, jmp_rw, i0, i1, i2, i3);
343
152
}
344
static void gen_disable_mem_helper(void)
153
345
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
154
static void tcg_out_call_int(TCGContext *s, int lk,
155
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
156
if (s->tb_jmp_insn_offset) {
157
/* Direct jump. */
158
if (TCG_TARGET_REG_BITS == 64) {
159
- /* Ensure the next insns are 8-byte aligned. */
160
- if ((uintptr_t)s->code_ptr & 7) {
161
+ /* Ensure the next insns are 8 or 16-byte aligned. */
162
+ while ((uintptr_t)s->code_ptr & (have_isa_2_07 ? 15 : 7)) {
163
tcg_out32(s, NOP);
164
}
346
}
165
s->tb_jmp_insn_offset[args[0]] = tcg_current_code_size(s);
347
break;
348
349
+ case PLUGIN_GEN_FROM_INSN:
350
+ assert(insn != NULL);
351
+
352
+ gen_enable_mem_helper(plugin_tb, insn);
353
+
354
+ cbs = insn->cbs[PLUGIN_CB_INSN][PLUGIN_CB_REGULAR];
355
+ for (i = 0, n = (cbs ? cbs->len : 0); i < n; i++) {
356
+ struct qemu_plugin_dyn_cb *cb =
357
+ &g_array_index(cbs, struct qemu_plugin_dyn_cb, i);
358
+ gen_udata_cb(cb);
359
+ }
360
+
361
+ cbs = insn->cbs[PLUGIN_CB_INSN][PLUGIN_CB_INLINE];
362
+ for (i = 0, n = (cbs ? cbs->len : 0); i < n; i++) {
363
+ struct qemu_plugin_dyn_cb *cb =
364
+ &g_array_index(cbs, struct qemu_plugin_dyn_cb, i);
365
+ gen_inline_cb(cb);
366
+ }
367
+ break;
368
+
369
default:
370
g_assert_not_reached();
371
}
372
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
373
enum plugin_gen_cb type = op->args[1];
374
375
switch (from) {
376
- case PLUGIN_GEN_FROM_INSN:
377
- {
378
- g_assert(insn_idx >= 0);
379
-
380
- switch (type) {
381
- case PLUGIN_GEN_CB_UDATA:
382
- plugin_gen_insn_udata(plugin_tb, op, insn_idx);
383
- break;
384
- case PLUGIN_GEN_CB_UDATA_R:
385
- plugin_gen_insn_udata_r(plugin_tb, op, insn_idx);
386
- break;
387
- case PLUGIN_GEN_CB_INLINE:
388
- plugin_gen_insn_inline(plugin_tb, op, insn_idx);
389
- break;
390
- case PLUGIN_GEN_ENABLE_MEM_HELPER:
391
- plugin_gen_enable_mem_helper(plugin_tb, op, insn_idx);
392
- break;
393
- default:
394
- g_assert_not_reached();
395
- }
396
- break;
397
- }
398
case PLUGIN_GEN_FROM_MEM:
399
{
400
g_assert(insn_idx >= 0);
401
diff --git a/plugins/api.c b/plugins/api.c
402
index XXXXXXX..XXXXXXX 100644
403
--- a/plugins/api.c
404
+++ b/plugins/api.c
405
@@ -XXX,XX +XXX,XX @@ void qemu_plugin_register_vcpu_insn_exec_cb(struct qemu_plugin_insn *insn,
406
void *udata)
407
{
408
if (!insn->mem_only) {
409
- int index = flags == QEMU_PLUGIN_CB_R_REGS ||
410
- flags == QEMU_PLUGIN_CB_RW_REGS ?
411
- PLUGIN_CB_REGULAR_R : PLUGIN_CB_REGULAR;
412
-
413
- plugin_register_dyn_cb__udata(&insn->cbs[PLUGIN_CB_INSN][index],
414
- cb, flags, udata);
415
+ plugin_register_dyn_cb__udata(
416
+ &insn->cbs[PLUGIN_CB_INSN][PLUGIN_CB_REGULAR], cb, flags, udata);
417
}
418
}
419
166
--
420
--
167
2.34.1
421
2.34.1
diff view generated by jsdifflib
1
Use the pc coming from db->pc_first rather than the TB.
1
Introduce a new plugin_mem_cb op to hold the address temp
2
and meminfo computed by tcg-op-ldst.c. Because this now
3
has its own opcode, we no longer need PLUGIN_GEN_FROM_MEM.
2
4
3
Use the cached host_addr rather than re-computing for the
5
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
4
first page. We still need a separate lookup for the second
5
page because it won't be computed for DisasContextBase until
6
the translator actually performs a read from the page.
7
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
---
7
---
11
include/exec/plugin-gen.h | 7 ++++---
8
include/exec/plugin-gen.h | 4 -
12
accel/tcg/plugin-gen.c | 22 +++++++++++-----------
9
include/tcg/tcg-op-common.h | 1 +
13
accel/tcg/translator.c | 2 +-
10
include/tcg/tcg-opc.h | 1 +
14
3 files changed, 16 insertions(+), 15 deletions(-)
11
accel/tcg/plugin-gen.c | 408 ++++--------------------------------
12
tcg/tcg-op-ldst.c | 6 +-
13
tcg/tcg-op.c | 5 +
14
6 files changed, 54 insertions(+), 371 deletions(-)
15
15
16
diff --git a/include/exec/plugin-gen.h b/include/exec/plugin-gen.h
16
diff --git a/include/exec/plugin-gen.h b/include/exec/plugin-gen.h
17
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/exec/plugin-gen.h
18
--- a/include/exec/plugin-gen.h
19
+++ b/include/exec/plugin-gen.h
19
+++ b/include/exec/plugin-gen.h
20
@@ -XXX,XX +XXX,XX @@ struct DisasContextBase;
20
@@ -XXX,XX +XXX,XX @@ void plugin_gen_insn_start(CPUState *cpu, const struct DisasContextBase *db);
21
22
#ifdef CONFIG_PLUGIN
23
24
-bool plugin_gen_tb_start(CPUState *cpu, const TranslationBlock *tb, bool supress);
25
+bool plugin_gen_tb_start(CPUState *cpu, const struct DisasContextBase *db,
26
+ bool supress);
27
void plugin_gen_tb_end(CPUState *cpu);
28
void plugin_gen_insn_start(CPUState *cpu, const struct DisasContextBase *db);
29
void plugin_gen_insn_end(void);
21
void plugin_gen_insn_end(void);
30
@@ -XXX,XX +XXX,XX @@ static inline void plugin_insn_append(abi_ptr pc, const void *from, size_t size)
22
23
void plugin_gen_disable_mem_helpers(void);
24
-void plugin_gen_empty_mem_callback(TCGv_i64 addr, uint32_t info);
31
25
32
#else /* !CONFIG_PLUGIN */
26
#else /* !CONFIG_PLUGIN */
33
27
34
-static inline
28
@@ -XXX,XX +XXX,XX @@ static inline void plugin_gen_tb_end(CPUState *cpu, size_t num_insns)
35
-bool plugin_gen_tb_start(CPUState *cpu, const TranslationBlock *tb, bool supress)
29
static inline void plugin_gen_disable_mem_helpers(void)
36
+static inline bool
30
{ }
37
+plugin_gen_tb_start(CPUState *cpu, const struct DisasContextBase *db, bool sup)
31
38
{
32
-static inline void plugin_gen_empty_mem_callback(TCGv_i64 addr, uint32_t info)
39
return false;
33
-{ }
40
}
34
-
35
#endif /* CONFIG_PLUGIN */
36
37
#endif /* QEMU_PLUGIN_GEN_H */
38
diff --git a/include/tcg/tcg-op-common.h b/include/tcg/tcg-op-common.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/tcg/tcg-op-common.h
41
+++ b/include/tcg/tcg-op-common.h
42
@@ -XXX,XX +XXX,XX @@ void tcg_gen_goto_tb(unsigned idx);
43
void tcg_gen_lookup_and_goto_ptr(void);
44
45
void tcg_gen_plugin_cb(unsigned from);
46
+void tcg_gen_plugin_mem_cb(TCGv_i64 addr, unsigned meminfo);
47
void tcg_gen_plugin_cb_start(unsigned from, unsigned type, unsigned wr);
48
void tcg_gen_plugin_cb_end(void);
49
50
diff --git a/include/tcg/tcg-opc.h b/include/tcg/tcg-opc.h
51
index XXXXXXX..XXXXXXX 100644
52
--- a/include/tcg/tcg-opc.h
53
+++ b/include/tcg/tcg-opc.h
54
@@ -XXX,XX +XXX,XX @@ DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_EXIT | TCG_OPF_BB_END)
55
DEF(goto_ptr, 0, 1, 0, TCG_OPF_BB_EXIT | TCG_OPF_BB_END)
56
57
DEF(plugin_cb, 0, 0, 1, TCG_OPF_NOT_PRESENT)
58
+DEF(plugin_mem_cb, 0, 1, 1, TCG_OPF_NOT_PRESENT)
59
DEF(plugin_cb_start, 0, 0, 3, TCG_OPF_NOT_PRESENT)
60
DEF(plugin_cb_end, 0, 0, 0, TCG_OPF_NOT_PRESENT)
61
41
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
62
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
42
index XXXXXXX..XXXXXXX 100644
63
index XXXXXXX..XXXXXXX 100644
43
--- a/accel/tcg/plugin-gen.c
64
--- a/accel/tcg/plugin-gen.c
44
+++ b/accel/tcg/plugin-gen.c
65
+++ b/accel/tcg/plugin-gen.c
45
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_inject(const struct qemu_plugin_tb *plugin_tb)
66
@@ -XXX,XX +XXX,XX @@
46
pr_ops();
67
enum plugin_gen_from {
47
}
68
PLUGIN_GEN_FROM_TB,
48
69
PLUGIN_GEN_FROM_INSN,
49
-bool plugin_gen_tb_start(CPUState *cpu, const TranslationBlock *tb, bool mem_only)
70
- PLUGIN_GEN_FROM_MEM,
50
+bool plugin_gen_tb_start(CPUState *cpu, const DisasContextBase *db,
71
PLUGIN_GEN_AFTER_INSN,
51
+ bool mem_only)
72
PLUGIN_GEN_AFTER_TB,
73
PLUGIN_GEN_N_FROMS,
74
@@ -XXX,XX +XXX,XX @@ void HELPER(plugin_vcpu_mem_cb)(unsigned int vcpu_index,
75
void *userdata)
76
{ }
77
78
-/*
79
- * For now we only support addi_i64.
80
- * When we support more ops, we can generate one empty inline cb for each.
81
- */
82
-static void gen_empty_inline_cb(void)
83
-{
84
- TCGv_i32 cpu_index = tcg_temp_ebb_new_i32();
85
- TCGv_ptr cpu_index_as_ptr = tcg_temp_ebb_new_ptr();
86
- TCGv_i64 val = tcg_temp_ebb_new_i64();
87
- TCGv_ptr ptr = tcg_temp_ebb_new_ptr();
88
-
89
- tcg_gen_ld_i32(cpu_index, tcg_env,
90
- -offsetof(ArchCPU, env) + offsetof(CPUState, cpu_index));
91
- /* second operand will be replaced by immediate value */
92
- tcg_gen_mul_i32(cpu_index, cpu_index, cpu_index);
93
- tcg_gen_ext_i32_ptr(cpu_index_as_ptr, cpu_index);
94
-
95
- tcg_gen_movi_ptr(ptr, 0);
96
- tcg_gen_add_ptr(ptr, ptr, cpu_index_as_ptr);
97
- tcg_gen_ld_i64(val, ptr, 0);
98
- /* second operand will be replaced by immediate value */
99
- tcg_gen_add_i64(val, val, val);
100
-
101
- tcg_gen_st_i64(val, ptr, 0);
102
- tcg_temp_free_ptr(ptr);
103
- tcg_temp_free_i64(val);
104
- tcg_temp_free_ptr(cpu_index_as_ptr);
105
- tcg_temp_free_i32(cpu_index);
106
-}
107
-
108
-static void gen_empty_mem_cb(TCGv_i64 addr, uint32_t info)
109
-{
110
- TCGv_i32 cpu_index = tcg_temp_ebb_new_i32();
111
- TCGv_i32 meminfo = tcg_temp_ebb_new_i32();
112
- TCGv_ptr udata = tcg_temp_ebb_new_ptr();
113
-
114
- tcg_gen_movi_i32(meminfo, info);
115
- tcg_gen_movi_ptr(udata, 0);
116
- tcg_gen_ld_i32(cpu_index, tcg_env,
117
- -offsetof(ArchCPU, env) + offsetof(CPUState, cpu_index));
118
-
119
- gen_helper_plugin_vcpu_mem_cb(cpu_index, meminfo, addr, udata);
120
-
121
- tcg_temp_free_ptr(udata);
122
- tcg_temp_free_i32(meminfo);
123
- tcg_temp_free_i32(cpu_index);
124
-}
125
-
126
-static void gen_plugin_cb_start(enum plugin_gen_from from,
127
- enum plugin_gen_cb type, unsigned wr)
128
-{
129
- tcg_gen_plugin_cb_start(from, type, wr);
130
-}
131
-
132
static void plugin_gen_empty_callback(enum plugin_gen_from from)
52
{
133
{
53
bool ret = false;
134
switch (from) {
54
135
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_empty_callback(enum plugin_gen_from from)
55
@@ -XXX,XX +XXX,XX @@ bool plugin_gen_tb_start(CPUState *cpu, const TranslationBlock *tb, bool mem_onl
56
57
ret = true;
58
59
- ptb->vaddr = tb->pc;
60
+ ptb->vaddr = db->pc_first;
61
ptb->vaddr2 = -1;
62
- get_page_addr_code_hostp(cpu->env_ptr, tb->pc, &ptb->haddr1);
63
+ ptb->haddr1 = db->host_addr[0];
64
ptb->haddr2 = NULL;
65
ptb->mem_only = mem_only;
66
67
@@ -XXX,XX +XXX,XX @@ void plugin_gen_insn_start(CPUState *cpu, const DisasContextBase *db)
68
* Note that we skip this when haddr1 == NULL, e.g. when we're
69
* fetching instructions from a region not backed by RAM.
70
*/
71
- if (likely(ptb->haddr1 != NULL && ptb->vaddr2 == -1) &&
72
- unlikely((db->pc_next & TARGET_PAGE_MASK) !=
73
- (db->pc_first & TARGET_PAGE_MASK))) {
74
- get_page_addr_code_hostp(cpu->env_ptr, db->pc_next,
75
- &ptb->haddr2);
76
- ptb->vaddr2 = db->pc_next;
77
- }
78
- if (likely(ptb->vaddr2 == -1)) {
79
+ if (ptb->haddr1 == NULL) {
80
+ pinsn->haddr = NULL;
81
+ } else if (is_same_page(db, db->pc_next)) {
82
pinsn->haddr = ptb->haddr1 + pinsn->vaddr - ptb->vaddr;
83
} else {
84
+ if (ptb->vaddr2 == -1) {
85
+ ptb->vaddr2 = TARGET_PAGE_ALIGN(db->pc_first);
86
+ get_page_addr_code_hostp(cpu->env_ptr, ptb->vaddr2, &ptb->haddr2);
87
+ }
88
pinsn->haddr = ptb->haddr2 + pinsn->vaddr - ptb->vaddr2;
89
}
136
}
90
}
137
}
91
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
138
139
-void plugin_gen_empty_mem_callback(TCGv_i64 addr, uint32_t info)
140
-{
141
- enum qemu_plugin_mem_rw rw = get_plugin_meminfo_rw(info);
142
-
143
- gen_plugin_cb_start(PLUGIN_GEN_FROM_MEM, PLUGIN_GEN_CB_MEM, rw);
144
- gen_empty_mem_cb(addr, info);
145
- tcg_gen_plugin_cb_end();
146
-
147
- gen_plugin_cb_start(PLUGIN_GEN_FROM_MEM, PLUGIN_GEN_CB_INLINE, rw);
148
- gen_empty_inline_cb();
149
- tcg_gen_plugin_cb_end();
150
-}
151
-
152
-static TCGOp *find_op(TCGOp *op, TCGOpcode opc)
153
-{
154
- while (op) {
155
- if (op->opc == opc) {
156
- return op;
157
- }
158
- op = QTAILQ_NEXT(op, link);
159
- }
160
- return NULL;
161
-}
162
-
163
-static TCGOp *rm_ops_range(TCGOp *begin, TCGOp *end)
164
-{
165
- TCGOp *ret = QTAILQ_NEXT(end, link);
166
-
167
- QTAILQ_REMOVE_SEVERAL(&tcg_ctx->ops, begin, end, link);
168
- return ret;
169
-}
170
-
171
-/* remove all ops until (and including) plugin_cb_end */
172
-static TCGOp *rm_ops(TCGOp *op)
173
-{
174
- TCGOp *end_op = find_op(op, INDEX_op_plugin_cb_end);
175
-
176
- tcg_debug_assert(end_op);
177
- return rm_ops_range(op, end_op);
178
-}
179
-
180
-static TCGOp *copy_op_nocheck(TCGOp **begin_op, TCGOp *op)
181
-{
182
- TCGOp *old_op = QTAILQ_NEXT(*begin_op, link);
183
- unsigned nargs = old_op->nargs;
184
-
185
- *begin_op = old_op;
186
- op = tcg_op_insert_after(tcg_ctx, op, old_op->opc, nargs);
187
- memcpy(op->args, old_op->args, sizeof(op->args[0]) * nargs);
188
-
189
- return op;
190
-}
191
-
192
-static TCGOp *copy_op(TCGOp **begin_op, TCGOp *op, TCGOpcode opc)
193
-{
194
- op = copy_op_nocheck(begin_op, op);
195
- tcg_debug_assert((*begin_op)->opc == opc);
196
- return op;
197
-}
198
-
199
-static TCGOp *copy_const_ptr(TCGOp **begin_op, TCGOp *op, void *ptr)
200
-{
201
- if (UINTPTR_MAX == UINT32_MAX) {
202
- /* mov_i32 */
203
- op = copy_op(begin_op, op, INDEX_op_mov_i32);
204
- op->args[1] = tcgv_i32_arg(tcg_constant_i32((uintptr_t)ptr));
205
- } else {
206
- /* mov_i64 */
207
- op = copy_op(begin_op, op, INDEX_op_mov_i64);
208
- op->args[1] = tcgv_i64_arg(tcg_constant_i64((uintptr_t)ptr));
209
- }
210
- return op;
211
-}
212
-
213
-static TCGOp *copy_ld_i32(TCGOp **begin_op, TCGOp *op)
214
-{
215
- return copy_op(begin_op, op, INDEX_op_ld_i32);
216
-}
217
-
218
-static TCGOp *copy_ext_i32_ptr(TCGOp **begin_op, TCGOp *op)
219
-{
220
- if (UINTPTR_MAX == UINT32_MAX) {
221
- op = copy_op(begin_op, op, INDEX_op_mov_i32);
222
- } else {
223
- op = copy_op(begin_op, op, INDEX_op_ext_i32_i64);
224
- }
225
- return op;
226
-}
227
-
228
-static TCGOp *copy_add_ptr(TCGOp **begin_op, TCGOp *op)
229
-{
230
- if (UINTPTR_MAX == UINT32_MAX) {
231
- op = copy_op(begin_op, op, INDEX_op_add_i32);
232
- } else {
233
- op = copy_op(begin_op, op, INDEX_op_add_i64);
234
- }
235
- return op;
236
-}
237
-
238
-static TCGOp *copy_ld_i64(TCGOp **begin_op, TCGOp *op)
239
-{
240
- if (TCG_TARGET_REG_BITS == 32) {
241
- /* 2x ld_i32 */
242
- op = copy_ld_i32(begin_op, op);
243
- op = copy_ld_i32(begin_op, op);
244
- } else {
245
- /* ld_i64 */
246
- op = copy_op(begin_op, op, INDEX_op_ld_i64);
247
- }
248
- return op;
249
-}
250
-
251
-static TCGOp *copy_st_i64(TCGOp **begin_op, TCGOp *op)
252
-{
253
- if (TCG_TARGET_REG_BITS == 32) {
254
- /* 2x st_i32 */
255
- op = copy_op(begin_op, op, INDEX_op_st_i32);
256
- op = copy_op(begin_op, op, INDEX_op_st_i32);
257
- } else {
258
- /* st_i64 */
259
- op = copy_op(begin_op, op, INDEX_op_st_i64);
260
- }
261
- return op;
262
-}
263
-
264
-static TCGOp *copy_add_i64(TCGOp **begin_op, TCGOp *op, uint64_t v)
265
-{
266
- if (TCG_TARGET_REG_BITS == 32) {
267
- /* all 32-bit backends must implement add2_i32 */
268
- g_assert(TCG_TARGET_HAS_add2_i32);
269
- op = copy_op(begin_op, op, INDEX_op_add2_i32);
270
- op->args[4] = tcgv_i32_arg(tcg_constant_i32(v));
271
- op->args[5] = tcgv_i32_arg(tcg_constant_i32(v >> 32));
272
- } else {
273
- op = copy_op(begin_op, op, INDEX_op_add_i64);
274
- op->args[2] = tcgv_i64_arg(tcg_constant_i64(v));
275
- }
276
- return op;
277
-}
278
-
279
-static TCGOp *copy_mul_i32(TCGOp **begin_op, TCGOp *op, uint32_t v)
280
-{
281
- op = copy_op(begin_op, op, INDEX_op_mul_i32);
282
- op->args[2] = tcgv_i32_arg(tcg_constant_i32(v));
283
- return op;
284
-}
285
-
286
-static TCGOp *copy_call(TCGOp **begin_op, TCGOp *op, void *func, int *cb_idx)
287
-{
288
- TCGOp *old_op;
289
- int func_idx;
290
-
291
- /* copy all ops until the call */
292
- do {
293
- op = copy_op_nocheck(begin_op, op);
294
- } while (op->opc != INDEX_op_call);
295
-
296
- /* fill in the op call */
297
- old_op = *begin_op;
298
- TCGOP_CALLI(op) = TCGOP_CALLI(old_op);
299
- TCGOP_CALLO(op) = TCGOP_CALLO(old_op);
300
- tcg_debug_assert(op->life == 0);
301
-
302
- func_idx = TCGOP_CALLO(op) + TCGOP_CALLI(op);
303
- *cb_idx = func_idx;
304
- op->args[func_idx] = (uintptr_t)func;
305
-
306
- return op;
307
-}
308
-
309
-static TCGOp *append_inline_cb(const struct qemu_plugin_dyn_cb *cb,
310
- TCGOp *begin_op, TCGOp *op,
311
- int *unused)
312
-{
313
- char *ptr = cb->inline_insn.entry.score->data->data;
314
- size_t elem_size = g_array_get_element_size(
315
- cb->inline_insn.entry.score->data);
316
- size_t offset = cb->inline_insn.entry.offset;
317
-
318
- op = copy_ld_i32(&begin_op, op);
319
- op = copy_mul_i32(&begin_op, op, elem_size);
320
- op = copy_ext_i32_ptr(&begin_op, op);
321
- op = copy_const_ptr(&begin_op, op, ptr + offset);
322
- op = copy_add_ptr(&begin_op, op);
323
- op = copy_ld_i64(&begin_op, op);
324
- op = copy_add_i64(&begin_op, op, cb->inline_insn.imm);
325
- op = copy_st_i64(&begin_op, op);
326
- return op;
327
-}
328
-
329
-static TCGOp *append_mem_cb(const struct qemu_plugin_dyn_cb *cb,
330
- TCGOp *begin_op, TCGOp *op, int *cb_idx)
331
-{
332
- enum plugin_gen_cb type = begin_op->args[1];
333
-
334
- tcg_debug_assert(type == PLUGIN_GEN_CB_MEM);
335
-
336
- /* const_i32 == mov_i32 ("info", so it remains as is) */
337
- op = copy_op(&begin_op, op, INDEX_op_mov_i32);
338
-
339
- /* const_ptr */
340
- op = copy_const_ptr(&begin_op, op, cb->userp);
341
-
342
- /* copy the ld_i32, but note that we only have to copy it once */
343
- if (*cb_idx == -1) {
344
- op = copy_op(&begin_op, op, INDEX_op_ld_i32);
345
- } else {
346
- begin_op = QTAILQ_NEXT(begin_op, link);
347
- tcg_debug_assert(begin_op && begin_op->opc == INDEX_op_ld_i32);
348
- }
349
-
350
- if (type == PLUGIN_GEN_CB_MEM) {
351
- /* call */
352
- op = copy_call(&begin_op, op, cb->regular.f.vcpu_udata, cb_idx);
353
- }
354
-
355
- return op;
356
-}
357
-
358
-typedef TCGOp *(*inject_fn)(const struct qemu_plugin_dyn_cb *cb,
359
- TCGOp *begin_op, TCGOp *op, int *intp);
360
-typedef bool (*op_ok_fn)(const TCGOp *op, const struct qemu_plugin_dyn_cb *cb);
361
-
362
-static bool op_rw(const TCGOp *op, const struct qemu_plugin_dyn_cb *cb)
363
-{
364
- int w;
365
-
366
- w = op->args[2];
367
- return !!(cb->rw & (w + 1));
368
-}
369
-
370
-static void inject_cb_type(const GArray *cbs, TCGOp *begin_op,
371
- inject_fn inject, op_ok_fn ok)
372
-{
373
- TCGOp *end_op;
374
- TCGOp *op;
375
- int cb_idx = -1;
376
- int i;
377
-
378
- if (!cbs || cbs->len == 0) {
379
- rm_ops(begin_op);
380
- return;
381
- }
382
-
383
- end_op = find_op(begin_op, INDEX_op_plugin_cb_end);
384
- tcg_debug_assert(end_op);
385
-
386
- op = end_op;
387
- for (i = 0; i < cbs->len; i++) {
388
- struct qemu_plugin_dyn_cb *cb =
389
- &g_array_index(cbs, struct qemu_plugin_dyn_cb, i);
390
-
391
- if (!ok(begin_op, cb)) {
392
- continue;
393
- }
394
- op = inject(cb, begin_op, op, &cb_idx);
395
- }
396
- rm_ops_range(begin_op, end_op);
397
-}
398
-
399
-static void
400
-inject_inline_cb(const GArray *cbs, TCGOp *begin_op, op_ok_fn ok)
401
-{
402
- inject_cb_type(cbs, begin_op, append_inline_cb, ok);
403
-}
404
-
405
-static void
406
-inject_mem_cb(const GArray *cbs, TCGOp *begin_op)
407
-{
408
- inject_cb_type(cbs, begin_op, append_mem_cb, op_rw);
409
-}
410
-
411
/* called before finishing a TB with exit_tb, goto_tb or goto_ptr */
412
void plugin_gen_disable_mem_helpers(void)
413
{
414
@@ -XXX,XX +XXX,XX @@ void plugin_gen_disable_mem_helpers(void)
415
}
416
}
417
418
-static void plugin_gen_mem_regular(const struct qemu_plugin_tb *ptb,
419
- TCGOp *begin_op, int insn_idx)
420
-{
421
- struct qemu_plugin_insn *insn = g_ptr_array_index(ptb->insns, insn_idx);
422
- inject_mem_cb(insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_REGULAR], begin_op);
423
-}
424
-
425
-static void plugin_gen_mem_inline(const struct qemu_plugin_tb *ptb,
426
- TCGOp *begin_op, int insn_idx)
427
-{
428
- const GArray *cbs;
429
- struct qemu_plugin_insn *insn = g_ptr_array_index(ptb->insns, insn_idx);
430
-
431
- cbs = insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_INLINE];
432
- inject_inline_cb(cbs, begin_op, op_rw);
433
-}
434
-
435
static void gen_enable_mem_helper(struct qemu_plugin_tb *ptb,
436
struct qemu_plugin_insn *insn)
437
{
438
@@ -XXX,XX +XXX,XX @@ static void gen_inline_cb(struct qemu_plugin_dyn_cb *cb)
439
tcg_temp_free_ptr(ptr);
440
}
441
442
+static void gen_mem_cb(struct qemu_plugin_dyn_cb *cb,
443
+ qemu_plugin_meminfo_t meminfo, TCGv_i64 addr)
444
+{
445
+ TCGv_i32 cpu_index = tcg_temp_ebb_new_i32();
446
+
447
+ tcg_gen_ld_i32(cpu_index, tcg_env,
448
+ -offsetof(ArchCPU, env) + offsetof(CPUState, cpu_index));
449
+ tcg_gen_call4(cb->regular.f.vcpu_mem, cb->regular.info, NULL,
450
+ tcgv_i32_temp(cpu_index),
451
+ tcgv_i32_temp(tcg_constant_i32(meminfo)),
452
+ tcgv_i64_temp(addr),
453
+ tcgv_ptr_temp(tcg_constant_ptr(cb->userp)));
454
+ tcg_temp_free_i32(cpu_index);
455
+}
456
+
457
/* #define DEBUG_PLUGIN_GEN_OPS */
458
static void pr_ops(void)
459
{
460
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
461
break;
462
}
463
464
- case INDEX_op_plugin_cb_start:
465
+ case INDEX_op_plugin_mem_cb:
466
{
467
- enum plugin_gen_from from = op->args[0];
468
- enum plugin_gen_cb type = op->args[1];
469
+ TCGv_i64 addr = temp_tcgv_i64(arg_temp(op->args[0]));
470
+ qemu_plugin_meminfo_t meminfo = op->args[1];
471
+ struct qemu_plugin_insn *insn;
472
+ const GArray *cbs;
473
+ int i, n, rw;
474
475
- switch (from) {
476
- case PLUGIN_GEN_FROM_MEM:
477
- {
478
- g_assert(insn_idx >= 0);
479
+ assert(insn_idx >= 0);
480
+ insn = g_ptr_array_index(plugin_tb->insns, insn_idx);
481
+ rw = qemu_plugin_mem_is_store(meminfo) ? 2 : 1;
482
483
- switch (type) {
484
- case PLUGIN_GEN_CB_MEM:
485
- plugin_gen_mem_regular(plugin_tb, op, insn_idx);
486
- break;
487
- case PLUGIN_GEN_CB_INLINE:
488
- plugin_gen_mem_inline(plugin_tb, op, insn_idx);
489
- break;
490
- default:
491
- g_assert_not_reached();
492
+ tcg_ctx->emit_before_op = op;
493
+
494
+ cbs = insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_REGULAR];
495
+ for (i = 0, n = (cbs ? cbs->len : 0); i < n; i++) {
496
+ struct qemu_plugin_dyn_cb *cb =
497
+ &g_array_index(cbs, struct qemu_plugin_dyn_cb, i);
498
+ if (cb->rw & rw) {
499
+ gen_mem_cb(cb, meminfo, addr);
500
}
501
+ }
502
503
- break;
504
- }
505
- default:
506
- g_assert_not_reached();
507
+ cbs = insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_INLINE];
508
+ for (i = 0, n = (cbs ? cbs->len : 0); i < n; i++) {
509
+ struct qemu_plugin_dyn_cb *cb =
510
+ &g_array_index(cbs, struct qemu_plugin_dyn_cb, i);
511
+ if (cb->rw & rw) {
512
+ gen_inline_cb(cb);
513
+ }
514
}
515
+
516
+ tcg_ctx->emit_before_op = NULL;
517
+ tcg_op_remove(tcg_ctx, op);
518
break;
519
}
520
+
521
default:
522
/* plugins don't care about any other ops */
523
break;
524
diff --git a/tcg/tcg-op-ldst.c b/tcg/tcg-op-ldst.c
92
index XXXXXXX..XXXXXXX 100644
525
index XXXXXXX..XXXXXXX 100644
93
--- a/accel/tcg/translator.c
526
--- a/tcg/tcg-op-ldst.c
94
+++ b/accel/tcg/translator.c
527
+++ b/tcg/tcg-op-ldst.c
95
@@ -XXX,XX +XXX,XX @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
528
@@ -XXX,XX +XXX,XX @@ plugin_gen_mem_callbacks(TCGv_i64 copy_addr, TCGTemp *orig_addr, MemOpIdx oi,
96
ops->tb_start(db, cpu);
529
copy_addr = tcg_temp_ebb_new_i64();
97
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
530
tcg_gen_extu_i32_i64(copy_addr, temp_tcgv_i32(orig_addr));
98
531
}
99
- plugin_enabled = plugin_gen_tb_start(cpu, tb, cflags & CF_MEMI_ONLY);
532
- plugin_gen_empty_mem_callback(copy_addr, info);
100
+ plugin_enabled = plugin_gen_tb_start(cpu, db, cflags & CF_MEMI_ONLY);
533
+ tcg_gen_plugin_mem_cb(copy_addr, info);
101
534
tcg_temp_free_i64(copy_addr);
102
while (true) {
535
} else {
103
db->num_insns++;
536
if (copy_addr) {
537
- plugin_gen_empty_mem_callback(copy_addr, info);
538
+ tcg_gen_plugin_mem_cb(copy_addr, info);
539
tcg_temp_free_i64(copy_addr);
540
} else {
541
- plugin_gen_empty_mem_callback(temp_tcgv_i64(orig_addr), info);
542
+ tcg_gen_plugin_mem_cb(temp_tcgv_i64(orig_addr), info);
543
}
544
}
545
}
546
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
547
index XXXXXXX..XXXXXXX 100644
548
--- a/tcg/tcg-op.c
549
+++ b/tcg/tcg-op.c
550
@@ -XXX,XX +XXX,XX @@ void tcg_gen_plugin_cb(unsigned from)
551
tcg_gen_op1(INDEX_op_plugin_cb, from);
552
}
553
554
+void tcg_gen_plugin_mem_cb(TCGv_i64 addr, unsigned meminfo)
555
+{
556
+ tcg_gen_op2(INDEX_op_plugin_mem_cb, tcgv_i64_arg(addr), meminfo);
557
+}
558
+
559
void tcg_gen_plugin_cb_start(unsigned from, unsigned type, unsigned wr)
560
{
561
tcg_gen_op3(INDEX_op_plugin_cb_start, from, type, wr);
104
--
562
--
105
2.34.1
563
2.34.1
106
107
diff view generated by jsdifflib
1
Now that we have collected all of the page data into
1
These placeholder helpers are no longer required.
2
CPUTLBEntryFull, provide an interface to record that
3
all in one go, instead of using 4 arguments. This interface
4
allows CPUTLBEntryFull to be extended without having to
5
change the number of arguments.
6
2
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
---
5
---
12
include/exec/cpu-defs.h | 14 +++++++++++
6
accel/tcg/plugin-helpers.h | 5 -----
13
include/exec/exec-all.h | 22 ++++++++++++++++++
7
include/exec/helper-gen-common.h | 4 ----
14
accel/tcg/cputlb.c | 51 ++++++++++++++++++++++++++---------------
8
include/exec/helper-proto-common.h | 4 ----
15
3 files changed, 69 insertions(+), 18 deletions(-)
9
accel/tcg/plugin-gen.c | 20 --------------------
10
4 files changed, 33 deletions(-)
11
delete mode 100644 accel/tcg/plugin-helpers.h
16
12
17
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
13
diff --git a/accel/tcg/plugin-helpers.h b/accel/tcg/plugin-helpers.h
14
deleted file mode 100644
15
index XXXXXXX..XXXXXXX
16
--- a/accel/tcg/plugin-helpers.h
17
+++ /dev/null
18
@@ -XXX,XX +XXX,XX @@
19
-#ifdef CONFIG_PLUGIN
20
-DEF_HELPER_FLAGS_2(plugin_vcpu_udata_cb_no_wg, TCG_CALL_NO_WG | TCG_CALL_PLUGIN, void, i32, ptr)
21
-DEF_HELPER_FLAGS_2(plugin_vcpu_udata_cb_no_rwg, TCG_CALL_NO_RWG | TCG_CALL_PLUGIN, void, i32, ptr)
22
-DEF_HELPER_FLAGS_4(plugin_vcpu_mem_cb, TCG_CALL_NO_RWG | TCG_CALL_PLUGIN, void, i32, i32, i64, ptr)
23
-#endif
24
diff --git a/include/exec/helper-gen-common.h b/include/exec/helper-gen-common.h
18
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
19
--- a/include/exec/cpu-defs.h
26
--- a/include/exec/helper-gen-common.h
20
+++ b/include/exec/cpu-defs.h
27
+++ b/include/exec/helper-gen-common.h
21
@@ -XXX,XX +XXX,XX @@ typedef struct CPUTLBEntryFull {
28
@@ -XXX,XX +XXX,XX @@
22
* + the offset within the target MemoryRegion (otherwise)
29
#include "exec/helper-gen.h.inc"
23
*/
30
#undef HELPER_H
24
hwaddr xlat_section;
31
25
+
32
-#define HELPER_H "accel/tcg/plugin-helpers.h"
26
+ /*
33
-#include "exec/helper-gen.h.inc"
27
+ * @phys_addr contains the physical address in the address space
34
-#undef HELPER_H
28
+ * given by cpu_asidx_from_attrs(cpu, @attrs).
35
-
29
+ */
36
#endif /* HELPER_GEN_COMMON_H */
30
+ hwaddr phys_addr;
37
diff --git a/include/exec/helper-proto-common.h b/include/exec/helper-proto-common.h
31
+
38
index XXXXXXX..XXXXXXX 100644
32
+ /* @attrs contains the memory transaction attributes for the page. */
39
--- a/include/exec/helper-proto-common.h
33
MemTxAttrs attrs;
40
+++ b/include/exec/helper-proto-common.h
34
+
41
@@ -XXX,XX +XXX,XX @@
35
+ /* @prot contains the complete protections for the page. */
42
#include "exec/helper-proto.h.inc"
36
+ uint8_t prot;
43
#undef HELPER_H
37
+
44
38
+ /* @lg_page_size contains the log2 of the page size. */
45
-#define HELPER_H "accel/tcg/plugin-helpers.h"
39
+ uint8_t lg_page_size;
46
-#include "exec/helper-proto.h.inc"
40
} CPUTLBEntryFull;
47
-#undef HELPER_H
48
-
49
#endif /* HELPER_PROTO_COMMON_H */
50
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/accel/tcg/plugin-gen.c
53
+++ b/accel/tcg/plugin-gen.c
54
@@ -XXX,XX +XXX,XX @@
55
#include "exec/exec-all.h"
56
#include "exec/plugin-gen.h"
57
#include "exec/translator.h"
58
-#include "exec/helper-proto-common.h"
59
-
60
-#define HELPER_H "accel/tcg/plugin-helpers.h"
61
-#include "exec/helper-info.c.inc"
62
-#undef HELPER_H
41
63
42
/*
64
/*
43
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
65
* plugin_cb_start TCG op args[]:
44
index XXXXXXX..XXXXXXX 100644
66
@@ -XXX,XX +XXX,XX @@ enum plugin_gen_cb {
45
--- a/include/exec/exec-all.h
67
PLUGIN_GEN_N_CBS,
46
+++ b/include/exec/exec-all.h
68
};
47
@@ -XXX,XX +XXX,XX @@ void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *cpu,
69
48
uint16_t idxmap,
70
-/*
49
unsigned bits);
71
- * These helpers are stubs that get dynamically switched out for calls
50
72
- * direct to the plugin if they are subscribed to.
51
+/**
73
- */
52
+ * tlb_set_page_full:
74
-void HELPER(plugin_vcpu_udata_cb_no_wg)(uint32_t cpu_index, void *udata)
53
+ * @cpu: CPU context
75
-{ }
54
+ * @mmu_idx: mmu index of the tlb to modify
76
-
55
+ * @vaddr: virtual address of the entry to add
77
-void HELPER(plugin_vcpu_udata_cb_no_rwg)(uint32_t cpu_index, void *udata)
56
+ * @full: the details of the tlb entry
78
-{ }
57
+ *
79
-
58
+ * Add an entry to @cpu tlb index @mmu_idx. All of the fields of
80
-void HELPER(plugin_vcpu_mem_cb)(unsigned int vcpu_index,
59
+ * @full must be filled, except for xlat_section, and constitute
81
- qemu_plugin_meminfo_t info, uint64_t vaddr,
60
+ * the complete description of the translated page.
82
- void *userdata)
61
+ *
83
-{ }
62
+ * This is generally called by the target tlb_fill function after
84
-
63
+ * having performed a successful page table walk to find the physical
85
static void plugin_gen_empty_callback(enum plugin_gen_from from)
64
+ * address and attributes for the translation.
65
+ *
66
+ * At most one entry for a given virtual address is permitted. Only a
67
+ * single TARGET_PAGE_SIZE region is mapped; @full->lg_page_size is only
68
+ * used by tlb_flush_page.
69
+ */
70
+void tlb_set_page_full(CPUState *cpu, int mmu_idx, target_ulong vaddr,
71
+ CPUTLBEntryFull *full);
72
+
73
/**
74
* tlb_set_page_with_attrs:
75
* @cpu: CPU to add this TLB entry for
76
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
77
index XXXXXXX..XXXXXXX 100644
78
--- a/accel/tcg/cputlb.c
79
+++ b/accel/tcg/cputlb.c
80
@@ -XXX,XX +XXX,XX @@ static void tlb_add_large_page(CPUArchState *env, int mmu_idx,
81
env_tlb(env)->d[mmu_idx].large_page_mask = lp_mask;
82
}
83
84
-/* Add a new TLB entry. At most one entry for a given virtual address
85
+/*
86
+ * Add a new TLB entry. At most one entry for a given virtual address
87
* is permitted. Only a single TARGET_PAGE_SIZE region is mapped, the
88
* supplied size is only used by tlb_flush_page.
89
*
90
* Called from TCG-generated code, which is under an RCU read-side
91
* critical section.
92
*/
93
-void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
94
- hwaddr paddr, MemTxAttrs attrs, int prot,
95
- int mmu_idx, target_ulong size)
96
+void tlb_set_page_full(CPUState *cpu, int mmu_idx,
97
+ target_ulong vaddr, CPUTLBEntryFull *full)
98
{
86
{
99
CPUArchState *env = cpu->env_ptr;
87
switch (from) {
100
CPUTLB *tlb = env_tlb(env);
101
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
102
CPUTLBEntry *te, tn;
103
hwaddr iotlb, xlat, sz, paddr_page;
104
target_ulong vaddr_page;
105
- int asidx = cpu_asidx_from_attrs(cpu, attrs);
106
- int wp_flags;
107
+ int asidx, wp_flags, prot;
108
bool is_ram, is_romd;
109
110
assert_cpu_is_self(cpu);
111
112
- if (size <= TARGET_PAGE_SIZE) {
113
+ if (full->lg_page_size <= TARGET_PAGE_BITS) {
114
sz = TARGET_PAGE_SIZE;
115
} else {
116
- tlb_add_large_page(env, mmu_idx, vaddr, size);
117
- sz = size;
118
+ sz = (hwaddr)1 << full->lg_page_size;
119
+ tlb_add_large_page(env, mmu_idx, vaddr, sz);
120
}
121
vaddr_page = vaddr & TARGET_PAGE_MASK;
122
- paddr_page = paddr & TARGET_PAGE_MASK;
123
+ paddr_page = full->phys_addr & TARGET_PAGE_MASK;
124
125
+ prot = full->prot;
126
+ asidx = cpu_asidx_from_attrs(cpu, full->attrs);
127
section = address_space_translate_for_iotlb(cpu, asidx, paddr_page,
128
- &xlat, &sz, attrs, &prot);
129
+ &xlat, &sz, full->attrs, &prot);
130
assert(sz >= TARGET_PAGE_SIZE);
131
132
tlb_debug("vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx
133
" prot=%x idx=%d\n",
134
- vaddr, paddr, prot, mmu_idx);
135
+ vaddr, full->phys_addr, prot, mmu_idx);
136
137
address = vaddr_page;
138
- if (size < TARGET_PAGE_SIZE) {
139
+ if (full->lg_page_size < TARGET_PAGE_BITS) {
140
/* Repeat the MMU check and TLB fill on every access. */
141
address |= TLB_INVALID_MASK;
142
}
143
- if (attrs.byte_swap) {
144
+ if (full->attrs.byte_swap) {
145
address |= TLB_BSWAP;
146
}
147
148
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
149
* subtract here is that of the page base, and not the same as the
150
* vaddr we add back in io_readx()/io_writex()/get_page_addr_code().
151
*/
152
+ desc->fulltlb[index] = *full;
153
desc->fulltlb[index].xlat_section = iotlb - vaddr_page;
154
- desc->fulltlb[index].attrs = attrs;
155
+ desc->fulltlb[index].phys_addr = paddr_page;
156
+ desc->fulltlb[index].prot = prot;
157
158
/* Now calculate the new entry */
159
tn.addend = addend - vaddr_page;
160
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
161
qemu_spin_unlock(&tlb->c.lock);
162
}
163
164
-/* Add a new TLB entry, but without specifying the memory
165
- * transaction attributes to be used.
166
- */
167
+void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
168
+ hwaddr paddr, MemTxAttrs attrs, int prot,
169
+ int mmu_idx, target_ulong size)
170
+{
171
+ CPUTLBEntryFull full = {
172
+ .phys_addr = paddr,
173
+ .attrs = attrs,
174
+ .prot = prot,
175
+ .lg_page_size = ctz64(size)
176
+ };
177
+
178
+ assert(is_power_of_2(size));
179
+ tlb_set_page_full(cpu, mmu_idx, vaddr, &full);
180
+}
181
+
182
void tlb_set_page(CPUState *cpu, target_ulong vaddr,
183
hwaddr paddr, int prot,
184
int mmu_idx, target_ulong size)
185
--
88
--
186
2.34.1
89
2.34.1
187
90
188
91
diff view generated by jsdifflib
1
This field is only written, not read; remove it.
1
Since we no longer emit plugin helpers during the initial code
2
translation phase, we don't need to specially mark plugin helpers.
2
3
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
6
---
8
include/hw/core/cpu.h | 1 -
7
include/tcg/tcg.h | 2 --
9
accel/tcg/cputlb.c | 7 +++----
8
plugins/core.c | 10 ++++------
10
2 files changed, 3 insertions(+), 5 deletions(-)
9
tcg/tcg.c | 4 +---
10
3 files changed, 5 insertions(+), 11 deletions(-)
11
11
12
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
12
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
13
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/core/cpu.h
14
--- a/include/tcg/tcg.h
15
+++ b/include/hw/core/cpu.h
15
+++ b/include/tcg/tcg.h
16
@@ -XXX,XX +XXX,XX @@ struct CPUWatchpoint {
16
@@ -XXX,XX +XXX,XX @@ typedef TCGv_ptr TCGv_env;
17
* the memory regions get moved around by io_writex.
17
#define TCG_CALL_NO_SIDE_EFFECTS 0x0004
18
*/
18
/* Helper is G_NORETURN. */
19
typedef struct SavedIOTLB {
19
#define TCG_CALL_NO_RETURN 0x0008
20
- hwaddr addr;
20
-/* Helper is part of Plugins. */
21
MemoryRegionSection *section;
21
-#define TCG_CALL_PLUGIN 0x0010
22
hwaddr mr_offset;
22
23
} SavedIOTLB;
23
/* convenience version of most used call flags */
24
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
24
#define TCG_CALL_NO_RWG TCG_CALL_NO_READ_GLOBALS
25
diff --git a/plugins/core.c b/plugins/core.c
25
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
26
--- a/accel/tcg/cputlb.c
27
--- a/plugins/core.c
27
+++ b/accel/tcg/cputlb.c
28
+++ b/plugins/core.c
28
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUTLBEntryFull *full,
29
@@ -XXX,XX +XXX,XX @@ void plugin_register_dyn_cb__udata(GArray **arr,
29
* This is read by tlb_plugin_lookup if the fulltlb entry doesn't match
30
void *udata)
30
* because of the side effect of io_writex changing memory layout.
31
*/
32
-static void save_iotlb_data(CPUState *cs, hwaddr addr,
33
- MemoryRegionSection *section, hwaddr mr_offset)
34
+static void save_iotlb_data(CPUState *cs, MemoryRegionSection *section,
35
+ hwaddr mr_offset)
36
{
31
{
32
static TCGHelperInfo info[3] = {
33
- [QEMU_PLUGIN_CB_NO_REGS].flags = TCG_CALL_NO_RWG | TCG_CALL_PLUGIN,
34
- [QEMU_PLUGIN_CB_R_REGS].flags = TCG_CALL_NO_WG | TCG_CALL_PLUGIN,
35
- [QEMU_PLUGIN_CB_RW_REGS].flags = TCG_CALL_PLUGIN,
36
+ [QEMU_PLUGIN_CB_NO_REGS].flags = TCG_CALL_NO_RWG,
37
+ [QEMU_PLUGIN_CB_R_REGS].flags = TCG_CALL_NO_WG,
38
/*
39
* Match qemu_plugin_vcpu_udata_cb_t:
40
* void (*)(uint32_t, void *)
41
@@ -XXX,XX +XXX,XX @@ void plugin_register_vcpu_mem_cb(GArray **arr,
42
!__builtin_types_compatible_p(qemu_plugin_meminfo_t, int32_t));
43
44
static TCGHelperInfo info[3] = {
45
- [QEMU_PLUGIN_CB_NO_REGS].flags = TCG_CALL_NO_RWG | TCG_CALL_PLUGIN,
46
- [QEMU_PLUGIN_CB_R_REGS].flags = TCG_CALL_NO_WG | TCG_CALL_PLUGIN,
47
- [QEMU_PLUGIN_CB_RW_REGS].flags = TCG_CALL_PLUGIN,
48
+ [QEMU_PLUGIN_CB_NO_REGS].flags = TCG_CALL_NO_RWG,
49
+ [QEMU_PLUGIN_CB_R_REGS].flags = TCG_CALL_NO_WG,
50
/*
51
* Match qemu_plugin_vcpu_mem_cb_t:
52
* void (*)(uint32_t, qemu_plugin_meminfo_t, uint64_t, void *)
53
diff --git a/tcg/tcg.c b/tcg/tcg.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/tcg/tcg.c
56
+++ b/tcg/tcg.c
57
@@ -XXX,XX +XXX,XX @@ static void tcg_gen_callN(void *func, TCGHelperInfo *info,
58
37
#ifdef CONFIG_PLUGIN
59
#ifdef CONFIG_PLUGIN
38
SavedIOTLB *saved = &cs->saved_iotlb;
60
/* Flag helpers that may affect guest state */
39
- saved->addr = addr;
61
- if (tcg_ctx->plugin_insn &&
40
saved->section = section;
62
- !(info->flags & TCG_CALL_PLUGIN) &&
41
saved->mr_offset = mr_offset;
63
- !(info->flags & TCG_CALL_NO_SIDE_EFFECTS)) {
64
+ if (tcg_ctx->plugin_insn && !(info->flags & TCG_CALL_NO_SIDE_EFFECTS)) {
65
tcg_ctx->plugin_insn->calls_helpers = true;
66
}
42
#endif
67
#endif
43
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUTLBEntryFull *full,
44
* The memory_region_dispatch may trigger a flush/resize
45
* so for plugins we save the iotlb_data just in case.
46
*/
47
- save_iotlb_data(cpu, full->xlat_section, section, mr_offset);
48
+ save_iotlb_data(cpu, section, mr_offset);
49
50
if (!qemu_mutex_iothread_locked()) {
51
qemu_mutex_lock_iothread();
52
--
68
--
53
2.34.1
69
2.34.1
54
55
diff view generated by jsdifflib
1
The value previously chosen overlaps GUSA_MASK.
1
These opcodes are no longer used.
2
2
3
Rename all DELAY_SLOT_* and GUSA_* defines to emphasize
3
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
4
that they are included in TB_FLAGs. Add aliases for the
5
FPSCR and SR bits that are included in TB_FLAGS, so that
6
we don't accidentally reassign those bits.
7
8
Fixes: 4da06fb3062 ("target/sh4: Implement prctl_unalign_sigbus")
9
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/856
10
Reviewed-by: Yoshinori Sato <ysato@users.sourceforge.jp>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
---
5
---
13
target/sh4/cpu.h | 56 +++++++++++++------------
6
include/tcg/tcg-op-common.h | 2 --
14
linux-user/sh4/signal.c | 6 +--
7
include/tcg/tcg-opc.h | 2 --
15
target/sh4/cpu.c | 6 +--
8
accel/tcg/plugin-gen.c | 18 ------------------
16
target/sh4/helper.c | 6 +--
9
tcg/tcg-op.c | 10 ----------
17
target/sh4/translate.c | 90 ++++++++++++++++++++++-------------------
10
4 files changed, 32 deletions(-)
18
5 files changed, 88 insertions(+), 76 deletions(-)
19
11
20
diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h
12
diff --git a/include/tcg/tcg-op-common.h b/include/tcg/tcg-op-common.h
21
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
22
--- a/target/sh4/cpu.h
14
--- a/include/tcg/tcg-op-common.h
23
+++ b/target/sh4/cpu.h
15
+++ b/include/tcg/tcg-op-common.h
16
@@ -XXX,XX +XXX,XX @@ void tcg_gen_lookup_and_goto_ptr(void);
17
18
void tcg_gen_plugin_cb(unsigned from);
19
void tcg_gen_plugin_mem_cb(TCGv_i64 addr, unsigned meminfo);
20
-void tcg_gen_plugin_cb_start(unsigned from, unsigned type, unsigned wr);
21
-void tcg_gen_plugin_cb_end(void);
22
23
/* 32 bit ops */
24
25
diff --git a/include/tcg/tcg-opc.h b/include/tcg/tcg-opc.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/include/tcg/tcg-opc.h
28
+++ b/include/tcg/tcg-opc.h
29
@@ -XXX,XX +XXX,XX @@ DEF(goto_ptr, 0, 1, 0, TCG_OPF_BB_EXIT | TCG_OPF_BB_END)
30
31
DEF(plugin_cb, 0, 0, 1, TCG_OPF_NOT_PRESENT)
32
DEF(plugin_mem_cb, 0, 1, 1, TCG_OPF_NOT_PRESENT)
33
-DEF(plugin_cb_start, 0, 0, 3, TCG_OPF_NOT_PRESENT)
34
-DEF(plugin_cb_end, 0, 0, 0, TCG_OPF_NOT_PRESENT)
35
36
/* Replicate ld/st ops for 32 and 64-bit guest addresses. */
37
DEF(qemu_ld_a32_i32, 1, 1, 1,
38
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/accel/tcg/plugin-gen.c
41
+++ b/accel/tcg/plugin-gen.c
24
@@ -XXX,XX +XXX,XX @@
42
@@ -XXX,XX +XXX,XX @@
25
#define FPSCR_RM_NEAREST (0 << 0)
43
#include "exec/plugin-gen.h"
26
#define FPSCR_RM_ZERO (1 << 0)
44
#include "exec/translator.h"
27
45
28
-#define DELAY_SLOT_MASK 0x7
46
-/*
29
-#define DELAY_SLOT (1 << 0)
47
- * plugin_cb_start TCG op args[]:
30
-#define DELAY_SLOT_CONDITIONAL (1 << 1)
48
- * 0: enum plugin_gen_from
31
-#define DELAY_SLOT_RTE (1 << 2)
49
- * 1: enum plugin_gen_cb
32
+#define TB_FLAG_DELAY_SLOT (1 << 0)
50
- * 2: set to 1 for mem callback that is a write, 0 otherwise.
33
+#define TB_FLAG_DELAY_SLOT_COND (1 << 1)
51
- */
34
+#define TB_FLAG_DELAY_SLOT_RTE (1 << 2)
35
+#define TB_FLAG_PENDING_MOVCA (1 << 3)
36
+#define TB_FLAG_GUSA_SHIFT 4 /* [11:4] */
37
+#define TB_FLAG_GUSA_EXCLUSIVE (1 << 12)
38
+#define TB_FLAG_UNALIGN (1 << 13)
39
+#define TB_FLAG_SR_FD (1 << SR_FD) /* 15 */
40
+#define TB_FLAG_FPSCR_PR FPSCR_PR /* 19 */
41
+#define TB_FLAG_FPSCR_SZ FPSCR_SZ /* 20 */
42
+#define TB_FLAG_FPSCR_FR FPSCR_FR /* 21 */
43
+#define TB_FLAG_SR_RB (1 << SR_RB) /* 29 */
44
+#define TB_FLAG_SR_MD (1 << SR_MD) /* 30 */
45
46
-#define TB_FLAG_PENDING_MOVCA (1 << 3)
47
-#define TB_FLAG_UNALIGN (1 << 4)
48
-
52
-
49
-#define GUSA_SHIFT 4
53
enum plugin_gen_from {
50
-#ifdef CONFIG_USER_ONLY
54
PLUGIN_GEN_FROM_TB,
51
-#define GUSA_EXCLUSIVE (1 << 12)
55
PLUGIN_GEN_FROM_INSN,
52
-#define GUSA_MASK ((0xff << GUSA_SHIFT) | GUSA_EXCLUSIVE)
56
PLUGIN_GEN_AFTER_INSN,
53
-#else
57
PLUGIN_GEN_AFTER_TB,
54
-/* Provide dummy versions of the above to allow tests against tbflags
58
- PLUGIN_GEN_N_FROMS,
55
- to be elided while avoiding ifdefs. */
59
-};
56
-#define GUSA_EXCLUSIVE 0
57
-#define GUSA_MASK 0
58
-#endif
59
-
60
-
60
-#define TB_FLAG_ENVFLAGS_MASK (DELAY_SLOT_MASK | GUSA_MASK)
61
-enum plugin_gen_cb {
61
+#define TB_FLAG_DELAY_SLOT_MASK (TB_FLAG_DELAY_SLOT | \
62
- PLUGIN_GEN_CB_UDATA,
62
+ TB_FLAG_DELAY_SLOT_COND | \
63
- PLUGIN_GEN_CB_UDATA_R,
63
+ TB_FLAG_DELAY_SLOT_RTE)
64
- PLUGIN_GEN_CB_INLINE,
64
+#define TB_FLAG_GUSA_MASK ((0xff << TB_FLAG_GUSA_SHIFT) | \
65
- PLUGIN_GEN_CB_MEM,
65
+ TB_FLAG_GUSA_EXCLUSIVE)
66
- PLUGIN_GEN_ENABLE_MEM_HELPER,
66
+#define TB_FLAG_FPSCR_MASK (TB_FLAG_FPSCR_PR | \
67
- PLUGIN_GEN_DISABLE_MEM_HELPER,
67
+ TB_FLAG_FPSCR_SZ | \
68
- PLUGIN_GEN_N_CBS,
68
+ TB_FLAG_FPSCR_FR)
69
};
69
+#define TB_FLAG_SR_MASK (TB_FLAG_SR_FD | \
70
70
+ TB_FLAG_SR_RB | \
71
static void plugin_gen_empty_callback(enum plugin_gen_from from)
71
+ TB_FLAG_SR_MD)
72
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
72
+#define TB_FLAG_ENVFLAGS_MASK (TB_FLAG_DELAY_SLOT_MASK | \
73
+ TB_FLAG_GUSA_MASK)
74
75
typedef struct tlb_t {
76
uint32_t vpn;        /* virtual page number */
77
@@ -XXX,XX +XXX,XX @@ static inline int cpu_mmu_index (CPUSH4State *env, bool ifetch)
78
{
79
/* The instruction in a RTE delay slot is fetched in privileged
80
mode, but executed in user mode. */
81
- if (ifetch && (env->flags & DELAY_SLOT_RTE)) {
82
+ if (ifetch && (env->flags & TB_FLAG_DELAY_SLOT_RTE)) {
83
return 0;
84
} else {
85
return (env->sr & (1u << SR_MD)) == 0 ? 1 : 0;
86
@@ -XXX,XX +XXX,XX @@ static inline void cpu_get_tb_cpu_state(CPUSH4State *env, target_ulong *pc,
87
{
88
*pc = env->pc;
89
/* For a gUSA region, notice the end of the region. */
90
- *cs_base = env->flags & GUSA_MASK ? env->gregs[0] : 0;
91
- *flags = env->flags /* TB_FLAG_ENVFLAGS_MASK: bits 0-2, 4-12 */
92
- | (env->fpscr & (FPSCR_FR | FPSCR_SZ | FPSCR_PR)) /* Bits 19-21 */
93
- | (env->sr & ((1u << SR_MD) | (1u << SR_RB))) /* Bits 29-30 */
94
- | (env->sr & (1u << SR_FD)) /* Bit 15 */
95
+ *cs_base = env->flags & TB_FLAG_GUSA_MASK ? env->gregs[0] : 0;
96
+ *flags = env->flags
97
+ | (env->fpscr & TB_FLAG_FPSCR_MASK)
98
+ | (env->sr & TB_FLAG_SR_MASK)
99
| (env->movcal_backup ? TB_FLAG_PENDING_MOVCA : 0); /* Bit 3 */
100
#ifdef CONFIG_USER_ONLY
101
*flags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus;
102
diff --git a/linux-user/sh4/signal.c b/linux-user/sh4/signal.c
103
index XXXXXXX..XXXXXXX 100644
73
index XXXXXXX..XXXXXXX 100644
104
--- a/linux-user/sh4/signal.c
74
--- a/tcg/tcg-op.c
105
+++ b/linux-user/sh4/signal.c
75
+++ b/tcg/tcg-op.c
106
@@ -XXX,XX +XXX,XX @@ static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
76
@@ -XXX,XX +XXX,XX @@ void tcg_gen_plugin_mem_cb(TCGv_i64 addr, unsigned meminfo)
107
__get_user(regs->fpul, &sc->sc_fpul);
77
tcg_gen_op2(INDEX_op_plugin_mem_cb, tcgv_i64_arg(addr), meminfo);
108
109
regs->tra = -1; /* disable syscall checks */
110
- regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
111
+ regs->flags = 0;
112
}
78
}
113
79
114
void setup_frame(int sig, struct target_sigaction *ka,
80
-void tcg_gen_plugin_cb_start(unsigned from, unsigned type, unsigned wr)
115
@@ -XXX,XX +XXX,XX @@ void setup_frame(int sig, struct target_sigaction *ka,
81
-{
116
regs->gregs[5] = 0;
82
- tcg_gen_op3(INDEX_op_plugin_cb_start, from, type, wr);
117
regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc);
83
-}
118
regs->pc = (unsigned long) ka->_sa_handler;
84
-
119
- regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
85
-void tcg_gen_plugin_cb_end(void)
120
+ regs->flags &= ~(TB_FLAG_DELAY_SLOT_MASK | TB_FLAG_GUSA_MASK);
86
-{
121
87
- tcg_emit_op(INDEX_op_plugin_cb_end, 0);
122
unlock_user_struct(frame, frame_addr, 1);
88
-}
123
return;
89
-
124
@@ -XXX,XX +XXX,XX @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
90
/* 32 bit ops */
125
regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info);
91
126
regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc);
92
void tcg_gen_discard_i32(TCGv_i32 arg)
127
regs->pc = (unsigned long) ka->_sa_handler;
128
- regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK);
129
+ regs->flags &= ~(TB_FLAG_DELAY_SLOT_MASK | TB_FLAG_GUSA_MASK);
130
131
unlock_user_struct(frame, frame_addr, 1);
132
return;
133
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
134
index XXXXXXX..XXXXXXX 100644
135
--- a/target/sh4/cpu.c
136
+++ b/target/sh4/cpu.c
137
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_synchronize_from_tb(CPUState *cs,
138
SuperHCPU *cpu = SUPERH_CPU(cs);
139
140
cpu->env.pc = tb_pc(tb);
141
- cpu->env.flags = tb->flags & TB_FLAG_ENVFLAGS_MASK;
142
+ cpu->env.flags = tb->flags;
143
}
144
145
#ifndef CONFIG_USER_ONLY
146
@@ -XXX,XX +XXX,XX @@ static bool superh_io_recompile_replay_branch(CPUState *cs,
147
SuperHCPU *cpu = SUPERH_CPU(cs);
148
CPUSH4State *env = &cpu->env;
149
150
- if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
151
+ if ((env->flags & (TB_FLAG_DELAY_SLOT | TB_FLAG_DELAY_SLOT_COND))
152
&& env->pc != tb_pc(tb)) {
153
env->pc -= 2;
154
- env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
155
+ env->flags &= ~(TB_FLAG_DELAY_SLOT | TB_FLAG_DELAY_SLOT_COND);
156
return true;
157
}
158
return false;
159
diff --git a/target/sh4/helper.c b/target/sh4/helper.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/target/sh4/helper.c
162
+++ b/target/sh4/helper.c
163
@@ -XXX,XX +XXX,XX @@ void superh_cpu_do_interrupt(CPUState *cs)
164
env->sr |= (1u << SR_BL) | (1u << SR_MD) | (1u << SR_RB);
165
env->lock_addr = -1;
166
167
- if (env->flags & DELAY_SLOT_MASK) {
168
+ if (env->flags & TB_FLAG_DELAY_SLOT_MASK) {
169
/* Branch instruction should be executed again before delay slot. */
170
    env->spc -= 2;
171
    /* Clear flags for exception/interrupt routine. */
172
- env->flags &= ~DELAY_SLOT_MASK;
173
+ env->flags &= ~TB_FLAG_DELAY_SLOT_MASK;
174
}
175
176
if (do_exp) {
177
@@ -XXX,XX +XXX,XX @@ bool superh_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
178
CPUSH4State *env = &cpu->env;
179
180
/* Delay slots are indivisible, ignore interrupts */
181
- if (env->flags & DELAY_SLOT_MASK) {
182
+ if (env->flags & TB_FLAG_DELAY_SLOT_MASK) {
183
return false;
184
} else {
185
superh_cpu_do_interrupt(cs);
186
diff --git a/target/sh4/translate.c b/target/sh4/translate.c
187
index XXXXXXX..XXXXXXX 100644
188
--- a/target/sh4/translate.c
189
+++ b/target/sh4/translate.c
190
@@ -XXX,XX +XXX,XX @@ void superh_cpu_dump_state(CPUState *cs, FILE *f, int flags)
191
         i, env->gregs[i], i + 1, env->gregs[i + 1],
192
         i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]);
193
}
194
- if (env->flags & DELAY_SLOT) {
195
+ if (env->flags & TB_FLAG_DELAY_SLOT) {
196
qemu_printf("in delay slot (delayed_pc=0x%08x)\n",
197
         env->delayed_pc);
198
- } else if (env->flags & DELAY_SLOT_CONDITIONAL) {
199
+ } else if (env->flags & TB_FLAG_DELAY_SLOT_COND) {
200
qemu_printf("in conditional delay slot (delayed_pc=0x%08x)\n",
201
         env->delayed_pc);
202
- } else if (env->flags & DELAY_SLOT_RTE) {
203
+ } else if (env->flags & TB_FLAG_DELAY_SLOT_RTE) {
204
qemu_fprintf(f, "in rte delay slot (delayed_pc=0x%08x)\n",
205
env->delayed_pc);
206
}
207
@@ -XXX,XX +XXX,XX @@ static inline void gen_save_cpu_state(DisasContext *ctx, bool save_pc)
208
209
static inline bool use_exit_tb(DisasContext *ctx)
210
{
211
- return (ctx->tbflags & GUSA_EXCLUSIVE) != 0;
212
+ return (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) != 0;
213
}
214
215
static bool use_goto_tb(DisasContext *ctx, target_ulong dest)
216
@@ -XXX,XX +XXX,XX @@ static void gen_conditional_jump(DisasContext *ctx, target_ulong dest,
217
TCGLabel *l1 = gen_new_label();
218
TCGCond cond_not_taken = jump_if_true ? TCG_COND_EQ : TCG_COND_NE;
219
220
- if (ctx->tbflags & GUSA_EXCLUSIVE) {
221
+ if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
222
/* When in an exclusive region, we must continue to the end.
223
Therefore, exit the region on a taken branch, but otherwise
224
fall through to the next instruction. */
225
tcg_gen_brcondi_i32(cond_not_taken, cpu_sr_t, 0, l1);
226
- tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~GUSA_MASK);
227
+ tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~TB_FLAG_GUSA_MASK);
228
/* Note that this won't actually use a goto_tb opcode because we
229
disallow it in use_goto_tb, but it handles exit + singlestep. */
230
gen_goto_tb(ctx, 0, dest);
231
@@ -XXX,XX +XXX,XX @@ static void gen_delayed_conditional_jump(DisasContext * ctx)
232
tcg_gen_mov_i32(ds, cpu_delayed_cond);
233
tcg_gen_discard_i32(cpu_delayed_cond);
234
235
- if (ctx->tbflags & GUSA_EXCLUSIVE) {
236
+ if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
237
/* When in an exclusive region, we must continue to the end.
238
Therefore, exit the region on a taken branch, but otherwise
239
fall through to the next instruction. */
240
tcg_gen_brcondi_i32(TCG_COND_EQ, ds, 0, l1);
241
242
/* Leave the gUSA region. */
243
- tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~GUSA_MASK);
244
+ tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~TB_FLAG_GUSA_MASK);
245
gen_jump(ctx);
246
247
gen_set_label(l1);
248
@@ -XXX,XX +XXX,XX @@ static inline void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
249
#define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe))
250
251
#define CHECK_NOT_DELAY_SLOT \
252
- if (ctx->envflags & DELAY_SLOT_MASK) { \
253
- goto do_illegal_slot; \
254
+ if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) { \
255
+ goto do_illegal_slot; \
256
}
257
258
#define CHECK_PRIVILEGED \
259
@@ -XXX,XX +XXX,XX @@ static void _decode_opc(DisasContext * ctx)
260
case 0x000b:        /* rts */
261
    CHECK_NOT_DELAY_SLOT
262
    tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr);
263
- ctx->envflags |= DELAY_SLOT;
264
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
265
    ctx->delayed_pc = (uint32_t) - 1;
266
    return;
267
case 0x0028:        /* clrmac */
268
@@ -XXX,XX +XXX,XX @@ static void _decode_opc(DisasContext * ctx)
269
    CHECK_NOT_DELAY_SLOT
270
gen_write_sr(cpu_ssr);
271
    tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc);
272
- ctx->envflags |= DELAY_SLOT_RTE;
273
+ ctx->envflags |= TB_FLAG_DELAY_SLOT_RTE;
274
    ctx->delayed_pc = (uint32_t) - 1;
275
ctx->base.is_jmp = DISAS_STOP;
276
    return;
277
@@ -XXX,XX +XXX,XX @@ static void _decode_opc(DisasContext * ctx)
278
    return;
279
case 0xe000:        /* mov #imm,Rn */
280
#ifdef CONFIG_USER_ONLY
281
- /* Detect the start of a gUSA region. If so, update envflags
282
- and end the TB. This will allow us to see the end of the
283
- region (stored in R0) in the next TB. */
284
+ /*
285
+ * Detect the start of a gUSA region (mov #-n, r15).
286
+ * If so, update envflags and end the TB. This will allow us
287
+ * to see the end of the region (stored in R0) in the next TB.
288
+ */
289
if (B11_8 == 15 && B7_0s < 0 &&
290
(tb_cflags(ctx->base.tb) & CF_PARALLEL)) {
291
- ctx->envflags = deposit32(ctx->envflags, GUSA_SHIFT, 8, B7_0s);
292
+ ctx->envflags =
293
+ deposit32(ctx->envflags, TB_FLAG_GUSA_SHIFT, 8, B7_0s);
294
ctx->base.is_jmp = DISAS_STOP;
295
}
296
#endif
297
@@ -XXX,XX +XXX,XX @@ static void _decode_opc(DisasContext * ctx)
298
case 0xa000:        /* bra disp */
299
    CHECK_NOT_DELAY_SLOT
300
ctx->delayed_pc = ctx->base.pc_next + 4 + B11_0s * 2;
301
- ctx->envflags |= DELAY_SLOT;
302
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
303
    return;
304
case 0xb000:        /* bsr disp */
305
    CHECK_NOT_DELAY_SLOT
306
tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4);
307
ctx->delayed_pc = ctx->base.pc_next + 4 + B11_0s * 2;
308
- ctx->envflags |= DELAY_SLOT;
309
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
310
    return;
311
}
312
313
@@ -XXX,XX +XXX,XX @@ static void _decode_opc(DisasContext * ctx)
314
    CHECK_NOT_DELAY_SLOT
315
tcg_gen_xori_i32(cpu_delayed_cond, cpu_sr_t, 1);
316
ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2;
317
- ctx->envflags |= DELAY_SLOT_CONDITIONAL;
318
+ ctx->envflags |= TB_FLAG_DELAY_SLOT_COND;
319
    return;
320
case 0x8900:        /* bt label */
321
    CHECK_NOT_DELAY_SLOT
322
@@ -XXX,XX +XXX,XX @@ static void _decode_opc(DisasContext * ctx)
323
    CHECK_NOT_DELAY_SLOT
324
tcg_gen_mov_i32(cpu_delayed_cond, cpu_sr_t);
325
ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2;
326
- ctx->envflags |= DELAY_SLOT_CONDITIONAL;
327
+ ctx->envflags |= TB_FLAG_DELAY_SLOT_COND;
328
    return;
329
case 0x8800:        /* cmp/eq #imm,R0 */
330
tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(0), B7_0s);
331
@@ -XXX,XX +XXX,XX @@ static void _decode_opc(DisasContext * ctx)
332
case 0x0023:        /* braf Rn */
333
    CHECK_NOT_DELAY_SLOT
334
tcg_gen_addi_i32(cpu_delayed_pc, REG(B11_8), ctx->base.pc_next + 4);
335
- ctx->envflags |= DELAY_SLOT;
336
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
337
    ctx->delayed_pc = (uint32_t) - 1;
338
    return;
339
case 0x0003:        /* bsrf Rn */
340
    CHECK_NOT_DELAY_SLOT
341
tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4);
342
    tcg_gen_add_i32(cpu_delayed_pc, REG(B11_8), cpu_pr);
343
- ctx->envflags |= DELAY_SLOT;
344
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
345
    ctx->delayed_pc = (uint32_t) - 1;
346
    return;
347
case 0x4015:        /* cmp/pl Rn */
348
@@ -XXX,XX +XXX,XX @@ static void _decode_opc(DisasContext * ctx)
349
case 0x402b:        /* jmp @Rn */
350
    CHECK_NOT_DELAY_SLOT
351
    tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
352
- ctx->envflags |= DELAY_SLOT;
353
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
354
    ctx->delayed_pc = (uint32_t) - 1;
355
    return;
356
case 0x400b:        /* jsr @Rn */
357
    CHECK_NOT_DELAY_SLOT
358
tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4);
359
    tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8));
360
- ctx->envflags |= DELAY_SLOT;
361
+ ctx->envflags |= TB_FLAG_DELAY_SLOT;
362
    ctx->delayed_pc = (uint32_t) - 1;
363
    return;
364
case 0x400e:        /* ldc Rm,SR */
365
@@ -XXX,XX +XXX,XX @@ static void _decode_opc(DisasContext * ctx)
366
fflush(stderr);
367
#endif
368
do_illegal:
369
- if (ctx->envflags & DELAY_SLOT_MASK) {
370
+ if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) {
371
do_illegal_slot:
372
gen_save_cpu_state(ctx, true);
373
gen_helper_raise_slot_illegal_instruction(cpu_env);
374
@@ -XXX,XX +XXX,XX @@ static void _decode_opc(DisasContext * ctx)
375
376
do_fpu_disabled:
377
gen_save_cpu_state(ctx, true);
378
- if (ctx->envflags & DELAY_SLOT_MASK) {
379
+ if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) {
380
gen_helper_raise_slot_fpu_disable(cpu_env);
381
} else {
382
gen_helper_raise_fpu_disable(cpu_env);
383
@@ -XXX,XX +XXX,XX @@ static void decode_opc(DisasContext * ctx)
384
385
_decode_opc(ctx);
386
387
- if (old_flags & DELAY_SLOT_MASK) {
388
+ if (old_flags & TB_FLAG_DELAY_SLOT_MASK) {
389
/* go out of the delay slot */
390
- ctx->envflags &= ~DELAY_SLOT_MASK;
391
+ ctx->envflags &= ~TB_FLAG_DELAY_SLOT_MASK;
392
393
/* When in an exclusive region, we must continue to the end
394
for conditional branches. */
395
- if (ctx->tbflags & GUSA_EXCLUSIVE
396
- && old_flags & DELAY_SLOT_CONDITIONAL) {
397
+ if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE
398
+ && old_flags & TB_FLAG_DELAY_SLOT_COND) {
399
gen_delayed_conditional_jump(ctx);
400
return;
401
}
402
/* Otherwise this is probably an invalid gUSA region.
403
Drop the GUSA bits so the next TB doesn't see them. */
404
- ctx->envflags &= ~GUSA_MASK;
405
+ ctx->envflags &= ~TB_FLAG_GUSA_MASK;
406
407
tcg_gen_movi_i32(cpu_flags, ctx->envflags);
408
- if (old_flags & DELAY_SLOT_CONDITIONAL) {
409
+ if (old_flags & TB_FLAG_DELAY_SLOT_COND) {
410
     gen_delayed_conditional_jump(ctx);
411
} else {
412
gen_jump(ctx);
413
@@ -XXX,XX +XXX,XX @@ static void decode_gusa(DisasContext *ctx, CPUSH4State *env)
414
}
415
416
/* The entire region has been translated. */
417
- ctx->envflags &= ~GUSA_MASK;
418
+ ctx->envflags &= ~TB_FLAG_GUSA_MASK;
419
ctx->base.pc_next = pc_end;
420
ctx->base.num_insns += max_insns - 1;
421
return;
422
@@ -XXX,XX +XXX,XX @@ static void decode_gusa(DisasContext *ctx, CPUSH4State *env)
423
424
/* Restart with the EXCLUSIVE bit set, within a TB run via
425
cpu_exec_step_atomic holding the exclusive lock. */
426
- ctx->envflags |= GUSA_EXCLUSIVE;
427
+ ctx->envflags |= TB_FLAG_GUSA_EXCLUSIVE;
428
gen_save_cpu_state(ctx, false);
429
gen_helper_exclusive(cpu_env);
430
ctx->base.is_jmp = DISAS_NORETURN;
431
@@ -XXX,XX +XXX,XX @@ static void sh4_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
432
(tbflags & (1 << SR_RB))) * 0x10;
433
ctx->fbank = tbflags & FPSCR_FR ? 0x10 : 0;
434
435
- if (tbflags & GUSA_MASK) {
436
+#ifdef CONFIG_USER_ONLY
437
+ if (tbflags & TB_FLAG_GUSA_MASK) {
438
+ /* In gUSA exclusive region. */
439
uint32_t pc = ctx->base.pc_next;
440
uint32_t pc_end = ctx->base.tb->cs_base;
441
- int backup = sextract32(ctx->tbflags, GUSA_SHIFT, 8);
442
+ int backup = sextract32(ctx->tbflags, TB_FLAG_GUSA_SHIFT, 8);
443
int max_insns = (pc_end - pc) / 2;
444
445
if (pc != pc_end + backup || max_insns < 2) {
446
/* This is a malformed gUSA region. Don't do anything special,
447
since the interpreter is likely to get confused. */
448
- ctx->envflags &= ~GUSA_MASK;
449
- } else if (tbflags & GUSA_EXCLUSIVE) {
450
+ ctx->envflags &= ~TB_FLAG_GUSA_MASK;
451
+ } else if (tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
452
/* Regardless of single-stepping or the end of the page,
453
we must complete execution of the gUSA region while
454
holding the exclusive lock. */
455
@@ -XXX,XX +XXX,XX @@ static void sh4_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
456
return;
457
}
458
}
459
+#endif
460
461
/* Since the ISA is fixed-width, we can bound by the number
462
of instructions remaining on the page. */
463
@@ -XXX,XX +XXX,XX @@ static void sh4_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
464
DisasContext *ctx = container_of(dcbase, DisasContext, base);
465
466
#ifdef CONFIG_USER_ONLY
467
- if (unlikely(ctx->envflags & GUSA_MASK)
468
- && !(ctx->envflags & GUSA_EXCLUSIVE)) {
469
+ if (unlikely(ctx->envflags & TB_FLAG_GUSA_MASK)
470
+ && !(ctx->envflags & TB_FLAG_GUSA_EXCLUSIVE)) {
471
/* We're in an gUSA region, and we have not already fallen
472
back on using an exclusive region. Attempt to parse the
473
region into a single supported atomic operation. Failure
474
@@ -XXX,XX +XXX,XX @@ static void sh4_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
475
{
476
DisasContext *ctx = container_of(dcbase, DisasContext, base);
477
478
- if (ctx->tbflags & GUSA_EXCLUSIVE) {
479
+ if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
480
/* Ending the region of exclusivity. Clear the bits. */
481
- ctx->envflags &= ~GUSA_MASK;
482
+ ctx->envflags &= ~TB_FLAG_GUSA_MASK;
483
}
484
485
switch (ctx->base.is_jmp) {
486
--
93
--
487
2.34.1
94
2.34.1
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
We have qemu_plugin_dyn_cb.type to differentiate the various
2
callback types, so we do not need to keep them in separate queues.
2
3
3
Before: 35.912 s ± 0.168 s
4
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
4
After: 35.565 s ± 0.087 s
5
6
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-Id: <20220811151413.3350684-5-alex.bennee@linaro.org>
9
Signed-off-by: Cédric Le Goater <clg@kaod.org>
10
Message-Id: <20220923084803.498337-5-clg@kaod.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
---
6
---
13
accel/tcg/cputlb.c | 15 ++++++---------
7
include/qemu/plugin.h | 35 ++++++----------
14
1 file changed, 6 insertions(+), 9 deletions(-)
8
accel/tcg/plugin-gen.c | 90 ++++++++++++++++++++++--------------------
9
plugins/api.c | 18 +++------
10
3 files changed, 65 insertions(+), 78 deletions(-)
15
11
16
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
12
diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/accel/tcg/cputlb.c
14
--- a/include/qemu/plugin.h
19
+++ b/accel/tcg/cputlb.c
15
+++ b/include/qemu/plugin.h
20
@@ -XXX,XX +XXX,XX @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
16
@@ -XXX,XX +XXX,XX @@ union qemu_plugin_cb_sig {
21
static void tlb_fill(CPUState *cpu, target_ulong addr, int size,
17
};
22
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
18
23
{
19
enum plugin_dyn_cb_type {
24
- CPUClass *cc = CPU_GET_CLASS(cpu);
20
- PLUGIN_CB_INSN,
25
bool ok;
21
- PLUGIN_CB_MEM,
22
- PLUGIN_N_CB_TYPES,
23
-};
24
-
25
-enum plugin_dyn_cb_subtype {
26
PLUGIN_CB_REGULAR,
27
PLUGIN_CB_INLINE,
28
- PLUGIN_N_CB_SUBTYPES,
29
};
30
31
/*
32
@@ -XXX,XX +XXX,XX @@ enum plugin_dyn_cb_subtype {
33
*/
34
struct qemu_plugin_dyn_cb {
35
void *userp;
36
- enum plugin_dyn_cb_subtype type;
37
+ enum plugin_dyn_cb_type type;
38
/* @rw applies to mem callbacks only (both regular and inline) */
39
enum qemu_plugin_mem_rw rw;
40
/* fields specific to each dyn_cb type go here */
41
@@ -XXX,XX +XXX,XX @@ struct qemu_plugin_insn {
42
GByteArray *data;
43
uint64_t vaddr;
44
void *haddr;
45
- GArray *cbs[PLUGIN_N_CB_TYPES][PLUGIN_N_CB_SUBTYPES];
46
+ GArray *insn_cbs;
47
+ GArray *mem_cbs;
48
bool calls_helpers;
49
50
/* if set, the instruction calls helpers that might access guest memory */
51
@@ -XXX,XX +XXX,XX @@ static inline void qemu_plugin_insn_cleanup_fn(gpointer data)
52
53
static inline struct qemu_plugin_insn *qemu_plugin_insn_alloc(void)
54
{
55
- int i, j;
56
struct qemu_plugin_insn *insn = g_new0(struct qemu_plugin_insn, 1);
57
- insn->data = g_byte_array_sized_new(4);
58
59
- for (i = 0; i < PLUGIN_N_CB_TYPES; i++) {
60
- for (j = 0; j < PLUGIN_N_CB_SUBTYPES; j++) {
61
- insn->cbs[i][j] = g_array_new(false, false,
62
- sizeof(struct qemu_plugin_dyn_cb));
63
- }
64
- }
65
+ insn->data = g_byte_array_sized_new(4);
66
return insn;
67
}
68
69
@@ -XXX,XX +XXX,XX @@ struct qemu_plugin_tb {
70
/* if set, the TB calls helpers that might access guest memory */
71
bool mem_helper;
72
73
- GArray *cbs[PLUGIN_N_CB_SUBTYPES];
74
+ GArray *cbs;
75
};
76
77
/**
78
@@ -XXX,XX +XXX,XX @@ struct qemu_plugin_insn *qemu_plugin_tb_insn_get(struct qemu_plugin_tb *tb,
79
uint64_t pc)
80
{
81
struct qemu_plugin_insn *insn;
82
- int i, j;
83
84
if (unlikely(tb->n == tb->insns->len)) {
85
struct qemu_plugin_insn *new_insn = qemu_plugin_insn_alloc();
86
g_ptr_array_add(tb->insns, new_insn);
87
}
88
+
89
insn = g_ptr_array_index(tb->insns, tb->n++);
90
g_byte_array_set_size(insn->data, 0);
91
insn->calls_helpers = false;
92
insn->mem_helper = false;
93
insn->vaddr = pc;
94
-
95
- for (i = 0; i < PLUGIN_N_CB_TYPES; i++) {
96
- for (j = 0; j < PLUGIN_N_CB_SUBTYPES; j++) {
97
- g_array_set_size(insn->cbs[i][j], 0);
98
- }
99
+ if (insn->insn_cbs) {
100
+ g_array_set_size(insn->insn_cbs, 0);
101
+ }
102
+ if (insn->mem_cbs) {
103
+ g_array_set_size(insn->mem_cbs, 0);
104
}
105
106
return insn;
107
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
108
index XXXXXXX..XXXXXXX 100644
109
--- a/accel/tcg/plugin-gen.c
110
+++ b/accel/tcg/plugin-gen.c
111
@@ -XXX,XX +XXX,XX @@ void plugin_gen_disable_mem_helpers(void)
112
static void gen_enable_mem_helper(struct qemu_plugin_tb *ptb,
113
struct qemu_plugin_insn *insn)
114
{
115
- GArray *cbs[2];
116
GArray *arr;
117
- size_t n_cbs;
118
+ size_t len;
26
119
27
/*
120
/*
28
* This is not a probe, so only valid return is success; failure
121
* Tracking memory accesses performed from helpers requires extra work.
29
* should result in exception + longjmp to the cpu loop.
122
@@ -XXX,XX +XXX,XX @@ static void gen_enable_mem_helper(struct qemu_plugin_tb *ptb,
30
*/
123
return;
31
- ok = cc->tcg_ops->tlb_fill(cpu, addr, size,
124
}
32
- access_type, mmu_idx, false, retaddr);
125
33
+ ok = cpu->cc->tcg_ops->tlb_fill(cpu, addr, size,
126
- cbs[0] = insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_REGULAR];
34
+ access_type, mmu_idx, false, retaddr);
127
- cbs[1] = insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_INLINE];
35
assert(ok);
128
- n_cbs = cbs[0]->len + cbs[1]->len;
36
}
37
38
@@ -XXX,XX +XXX,XX @@ static inline void cpu_unaligned_access(CPUState *cpu, vaddr addr,
39
MMUAccessType access_type,
40
int mmu_idx, uintptr_t retaddr)
41
{
42
- CPUClass *cc = CPU_GET_CLASS(cpu);
43
-
129
-
44
- cc->tcg_ops->do_unaligned_access(cpu, addr, access_type, mmu_idx, retaddr);
130
- if (n_cbs == 0) {
45
+ cpu->cc->tcg_ops->do_unaligned_access(cpu, addr, access_type,
131
+ if (!insn->mem_cbs || !insn->mem_cbs->len) {
46
+ mmu_idx, retaddr);
132
insn->mem_helper = false;
47
}
133
return;
48
134
}
49
static inline void cpu_transaction_failed(CPUState *cpu, hwaddr physaddr,
135
insn->mem_helper = true;
50
@@ -XXX,XX +XXX,XX @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
136
ptb->mem_helper = true;
51
if (!tlb_hit_page(tlb_addr, page_addr)) {
137
52
if (!victim_tlb_hit(env, mmu_idx, index, elt_ofs, page_addr)) {
138
+ /*
53
CPUState *cs = env_cpu(env);
139
+ * TODO: It seems like we should be able to use ref/unref
54
- CPUClass *cc = CPU_GET_CLASS(cs);
140
+ * to avoid needing to actually copy this array.
55
141
+ * Alternately, perhaps we could allocate new memory adjacent
56
- if (!cc->tcg_ops->tlb_fill(cs, addr, fault_size, access_type,
142
+ * to the TranslationBlock itself, so that we do not have to
57
- mmu_idx, nonfault, retaddr)) {
143
+ * actively manage the lifetime after this.
58
+ if (!cs->cc->tcg_ops->tlb_fill(cs, addr, fault_size, access_type,
144
+ */
59
+ mmu_idx, nonfault, retaddr)) {
145
+ len = insn->mem_cbs->len;
60
/* Non-faulting page table read failed. */
146
arr = g_array_sized_new(false, false,
61
*phost = NULL;
147
- sizeof(struct qemu_plugin_dyn_cb), n_cbs);
62
return TLB_INVALID_MASK;
148
- g_array_append_vals(arr, cbs[0]->data, cbs[0]->len);
149
- g_array_append_vals(arr, cbs[1]->data, cbs[1]->len);
150
-
151
+ sizeof(struct qemu_plugin_dyn_cb), len);
152
+ memcpy(arr->data, insn->mem_cbs->data,
153
+ len * sizeof(struct qemu_plugin_dyn_cb));
154
qemu_plugin_add_dyn_cb_arr(arr);
155
156
tcg_gen_st_ptr(tcg_constant_ptr((intptr_t)arr), tcg_env,
157
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
158
case PLUGIN_GEN_FROM_TB:
159
assert(insn == NULL);
160
161
- cbs = plugin_tb->cbs[PLUGIN_CB_REGULAR];
162
+ cbs = plugin_tb->cbs;
163
for (i = 0, n = (cbs ? cbs->len : 0); i < n; i++) {
164
struct qemu_plugin_dyn_cb *cb =
165
&g_array_index(cbs, struct qemu_plugin_dyn_cb, i);
166
- gen_udata_cb(cb);
167
- }
168
169
- cbs = plugin_tb->cbs[PLUGIN_CB_INLINE];
170
- for (i = 0, n = (cbs ? cbs->len : 0); i < n; i++) {
171
- struct qemu_plugin_dyn_cb *cb =
172
- &g_array_index(cbs, struct qemu_plugin_dyn_cb, i);
173
- gen_inline_cb(cb);
174
+ switch (cb->type) {
175
+ case PLUGIN_CB_REGULAR:
176
+ gen_udata_cb(cb);
177
+ break;
178
+ case PLUGIN_CB_INLINE:
179
+ gen_inline_cb(cb);
180
+ break;
181
+ default:
182
+ g_assert_not_reached();
183
+ }
184
}
185
break;
186
187
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
188
189
gen_enable_mem_helper(plugin_tb, insn);
190
191
- cbs = insn->cbs[PLUGIN_CB_INSN][PLUGIN_CB_REGULAR];
192
+ cbs = insn->insn_cbs;
193
for (i = 0, n = (cbs ? cbs->len : 0); i < n; i++) {
194
struct qemu_plugin_dyn_cb *cb =
195
&g_array_index(cbs, struct qemu_plugin_dyn_cb, i);
196
- gen_udata_cb(cb);
197
- }
198
199
- cbs = insn->cbs[PLUGIN_CB_INSN][PLUGIN_CB_INLINE];
200
- for (i = 0, n = (cbs ? cbs->len : 0); i < n; i++) {
201
- struct qemu_plugin_dyn_cb *cb =
202
- &g_array_index(cbs, struct qemu_plugin_dyn_cb, i);
203
- gen_inline_cb(cb);
204
+ switch (cb->type) {
205
+ case PLUGIN_CB_REGULAR:
206
+ gen_udata_cb(cb);
207
+ break;
208
+ case PLUGIN_CB_INLINE:
209
+ gen_inline_cb(cb);
210
+ break;
211
+ default:
212
+ g_assert_not_reached();
213
+ }
214
}
215
break;
216
217
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
218
219
tcg_ctx->emit_before_op = op;
220
221
- cbs = insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_REGULAR];
222
+ cbs = insn->mem_cbs;
223
for (i = 0, n = (cbs ? cbs->len : 0); i < n; i++) {
224
struct qemu_plugin_dyn_cb *cb =
225
&g_array_index(cbs, struct qemu_plugin_dyn_cb, i);
226
- if (cb->rw & rw) {
227
- gen_mem_cb(cb, meminfo, addr);
228
- }
229
- }
230
231
- cbs = insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_INLINE];
232
- for (i = 0, n = (cbs ? cbs->len : 0); i < n; i++) {
233
- struct qemu_plugin_dyn_cb *cb =
234
- &g_array_index(cbs, struct qemu_plugin_dyn_cb, i);
235
if (cb->rw & rw) {
236
- gen_inline_cb(cb);
237
+ switch (cb->type) {
238
+ case PLUGIN_CB_REGULAR:
239
+ gen_mem_cb(cb, meminfo, addr);
240
+ break;
241
+ case PLUGIN_CB_INLINE:
242
+ gen_inline_cb(cb);
243
+ break;
244
+ default:
245
+ g_assert_not_reached();
246
+ }
247
}
248
}
249
250
@@ -XXX,XX +XXX,XX @@ bool plugin_gen_tb_start(CPUState *cpu, const DisasContextBase *db,
251
252
if (test_bit(QEMU_PLUGIN_EV_VCPU_TB_TRANS, cpu->plugin_state->event_mask)) {
253
struct qemu_plugin_tb *ptb = tcg_ctx->plugin_tb;
254
- int i;
255
256
/* reset callbacks */
257
- for (i = 0; i < PLUGIN_N_CB_SUBTYPES; i++) {
258
- if (ptb->cbs[i]) {
259
- g_array_set_size(ptb->cbs[i], 0);
260
- }
261
+ if (ptb->cbs) {
262
+ g_array_set_size(ptb->cbs, 0);
263
}
264
ptb->n = 0;
265
266
diff --git a/plugins/api.c b/plugins/api.c
267
index XXXXXXX..XXXXXXX 100644
268
--- a/plugins/api.c
269
+++ b/plugins/api.c
270
@@ -XXX,XX +XXX,XX @@ void qemu_plugin_register_vcpu_tb_exec_cb(struct qemu_plugin_tb *tb,
271
void *udata)
272
{
273
if (!tb->mem_only) {
274
- plugin_register_dyn_cb__udata(&tb->cbs[PLUGIN_CB_REGULAR],
275
- cb, flags, udata);
276
+ plugin_register_dyn_cb__udata(&tb->cbs, cb, flags, udata);
277
}
278
}
279
280
@@ -XXX,XX +XXX,XX @@ void qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu(
281
uint64_t imm)
282
{
283
if (!tb->mem_only) {
284
- plugin_register_inline_op_on_entry(
285
- &tb->cbs[PLUGIN_CB_INLINE], 0, op, entry, imm);
286
+ plugin_register_inline_op_on_entry(&tb->cbs, 0, op, entry, imm);
287
}
288
}
289
290
@@ -XXX,XX +XXX,XX @@ void qemu_plugin_register_vcpu_insn_exec_cb(struct qemu_plugin_insn *insn,
291
void *udata)
292
{
293
if (!insn->mem_only) {
294
- plugin_register_dyn_cb__udata(
295
- &insn->cbs[PLUGIN_CB_INSN][PLUGIN_CB_REGULAR], cb, flags, udata);
296
+ plugin_register_dyn_cb__udata(&insn->insn_cbs, cb, flags, udata);
297
}
298
}
299
300
@@ -XXX,XX +XXX,XX @@ void qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu(
301
uint64_t imm)
302
{
303
if (!insn->mem_only) {
304
- plugin_register_inline_op_on_entry(
305
- &insn->cbs[PLUGIN_CB_INSN][PLUGIN_CB_INLINE], 0, op, entry, imm);
306
+ plugin_register_inline_op_on_entry(&insn->insn_cbs, 0, op, entry, imm);
307
}
308
}
309
310
@@ -XXX,XX +XXX,XX @@ void qemu_plugin_register_vcpu_mem_cb(struct qemu_plugin_insn *insn,
311
enum qemu_plugin_mem_rw rw,
312
void *udata)
313
{
314
- plugin_register_vcpu_mem_cb(&insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_REGULAR],
315
- cb, flags, rw, udata);
316
+ plugin_register_vcpu_mem_cb(&insn->mem_cbs, cb, flags, rw, udata);
317
}
318
319
void qemu_plugin_register_vcpu_mem_inline_per_vcpu(
320
@@ -XXX,XX +XXX,XX @@ void qemu_plugin_register_vcpu_mem_inline_per_vcpu(
321
qemu_plugin_u64 entry,
322
uint64_t imm)
323
{
324
- plugin_register_inline_op_on_entry(
325
- &insn->cbs[PLUGIN_CB_MEM][PLUGIN_CB_INLINE], rw, op, entry, imm);
326
+ plugin_register_inline_op_on_entry(&insn->mem_cbs, rw, op, entry, imm);
327
}
328
329
void qemu_plugin_register_vcpu_tb_trans_cb(qemu_plugin_id_t id,
63
--
330
--
64
2.34.1
331
2.34.1
65
66
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
Use different enumerators for vcpu_udata and vcpu_mem callbacks.
2
2
3
This is a heavily used function so lets avoid the cost of
3
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
4
CPU_GET_CLASS. On the romulus-bmc run it has a modest effect:
5
6
Before: 36.812 s ± 0.506 s
7
After: 35.912 s ± 0.168 s
8
9
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-Id: <20220811151413.3350684-4-alex.bennee@linaro.org>
12
Signed-off-by: Cédric Le Goater <clg@kaod.org>
13
Message-Id: <20220923084803.498337-4-clg@kaod.org>
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
---
5
---
16
hw/core/cpu-sysemu.c | 5 ++---
6
include/qemu/plugin.h | 1 +
17
1 file changed, 2 insertions(+), 3 deletions(-)
7
accel/tcg/plugin-gen.c | 2 +-
8
plugins/core.c | 4 ++--
9
3 files changed, 4 insertions(+), 3 deletions(-)
18
10
19
diff --git a/hw/core/cpu-sysemu.c b/hw/core/cpu-sysemu.c
11
diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h
20
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/core/cpu-sysemu.c
13
--- a/include/qemu/plugin.h
22
+++ b/hw/core/cpu-sysemu.c
14
+++ b/include/qemu/plugin.h
23
@@ -XXX,XX +XXX,XX @@ hwaddr cpu_get_phys_page_debug(CPUState *cpu, vaddr addr)
15
@@ -XXX,XX +XXX,XX @@ union qemu_plugin_cb_sig {
24
16
25
int cpu_asidx_from_attrs(CPUState *cpu, MemTxAttrs attrs)
17
enum plugin_dyn_cb_type {
26
{
18
PLUGIN_CB_REGULAR,
27
- CPUClass *cc = CPU_GET_CLASS(cpu);
19
+ PLUGIN_CB_MEM_REGULAR,
28
int ret = 0;
20
PLUGIN_CB_INLINE,
29
21
};
30
- if (cc->sysemu_ops->asidx_from_attrs) {
22
31
- ret = cc->sysemu_ops->asidx_from_attrs(cpu, attrs);
23
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
32
+ if (cpu->cc->sysemu_ops->asidx_from_attrs) {
24
index XXXXXXX..XXXXXXX 100644
33
+ ret = cpu->cc->sysemu_ops->asidx_from_attrs(cpu, attrs);
25
--- a/accel/tcg/plugin-gen.c
34
assert(ret < cpu->num_ases && ret >= 0);
26
+++ b/accel/tcg/plugin-gen.c
35
}
27
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
36
return ret;
28
29
if (cb->rw & rw) {
30
switch (cb->type) {
31
- case PLUGIN_CB_REGULAR:
32
+ case PLUGIN_CB_MEM_REGULAR:
33
gen_mem_cb(cb, meminfo, addr);
34
break;
35
case PLUGIN_CB_INLINE:
36
diff --git a/plugins/core.c b/plugins/core.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/plugins/core.c
39
+++ b/plugins/core.c
40
@@ -XXX,XX +XXX,XX @@ void plugin_register_vcpu_mem_cb(GArray **arr,
41
42
struct qemu_plugin_dyn_cb *dyn_cb = plugin_get_dyn_cb(arr);
43
dyn_cb->userp = udata;
44
- dyn_cb->type = PLUGIN_CB_REGULAR;
45
+ dyn_cb->type = PLUGIN_CB_MEM_REGULAR;
46
dyn_cb->rw = rw;
47
dyn_cb->regular.f.vcpu_mem = cb;
48
49
@@ -XXX,XX +XXX,XX @@ void qemu_plugin_vcpu_mem_cb(CPUState *cpu, uint64_t vaddr,
50
break;
51
}
52
switch (cb->type) {
53
- case PLUGIN_CB_REGULAR:
54
+ case PLUGIN_CB_MEM_REGULAR:
55
cb->regular.f.vcpu_mem(cpu->cpu_index, make_plugin_meminfo(oi, rw),
56
vaddr, cb->userp);
57
break;
37
--
58
--
38
2.34.1
59
2.34.1
39
40
diff view generated by jsdifflib
1
The availability of tb->pc will shortly be conditional.
1
The DEBUG_PLUGIN_GEN_OPS ifdef is replaced with "-d op_plugin".
2
Introduce accessor functions to minimize ifdefs.
2
The second pr_ops call can be obtained with "-d op".
3
3
4
Pass around a known pc to places like tcg_gen_code,
4
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
5
where the caller must already have the value.
6
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
6
---
10
accel/tcg/internal.h | 6 ++++
7
include/qemu/log.h | 1 +
11
include/exec/exec-all.h | 6 ++++
8
include/tcg/tcg.h | 1 +
12
include/tcg/tcg.h | 2 +-
9
accel/tcg/plugin-gen.c | 67 +++++++-----------------------------------
13
accel/tcg/cpu-exec.c | 46 ++++++++++++++-----------
10
tcg/tcg.c | 29 +++++++++++++++++-
14
accel/tcg/translate-all.c | 37 +++++++++++---------
11
util/log.c | 4 +++
15
target/arm/cpu.c | 4 +--
12
5 files changed, 45 insertions(+), 57 deletions(-)
16
target/avr/cpu.c | 2 +-
17
target/hexagon/cpu.c | 2 +-
18
target/hppa/cpu.c | 4 +--
19
target/i386/tcg/tcg-cpu.c | 2 +-
20
target/loongarch/cpu.c | 2 +-
21
target/microblaze/cpu.c | 2 +-
22
target/mips/tcg/exception.c | 2 +-
23
target/mips/tcg/sysemu/special_helper.c | 2 +-
24
target/openrisc/cpu.c | 2 +-
25
target/riscv/cpu.c | 4 +--
26
target/rx/cpu.c | 2 +-
27
target/sh4/cpu.c | 4 +--
28
target/sparc/cpu.c | 2 +-
29
target/tricore/cpu.c | 2 +-
30
tcg/tcg.c | 8 ++---
31
21 files changed, 82 insertions(+), 61 deletions(-)
32
13
33
diff --git a/accel/tcg/internal.h b/accel/tcg/internal.h
14
diff --git a/include/qemu/log.h b/include/qemu/log.h
34
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
35
--- a/accel/tcg/internal.h
16
--- a/include/qemu/log.h
36
+++ b/accel/tcg/internal.h
17
+++ b/include/qemu/log.h
37
@@ -XXX,XX +XXX,XX @@ G_NORETURN void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr);
18
@@ -XXX,XX +XXX,XX @@ bool qemu_log_separate(void);
38
void page_init(void);
19
#define LOG_STRACE (1 << 19)
39
void tb_htable_init(void);
20
#define LOG_PER_THREAD (1 << 20)
40
21
#define CPU_LOG_TB_VPU (1 << 21)
41
+/* Return the current PC from CPU, which may be cached in TB. */
22
+#define LOG_TB_OP_PLUGIN (1 << 22)
42
+static inline target_ulong log_pc(CPUState *cpu, const TranslationBlock *tb)
23
43
+{
24
/* Lock/unlock output. */
44
+ return tb_pc(tb);
25
45
+}
46
+
47
#endif /* ACCEL_TCG_INTERNAL_H */
48
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
49
index XXXXXXX..XXXXXXX 100644
50
--- a/include/exec/exec-all.h
51
+++ b/include/exec/exec-all.h
52
@@ -XXX,XX +XXX,XX @@ struct TranslationBlock {
53
uintptr_t jmp_dest[2];
54
};
55
56
+/* Hide the read to avoid ifdefs for TARGET_TB_PCREL. */
57
+static inline target_ulong tb_pc(const TranslationBlock *tb)
58
+{
59
+ return tb->pc;
60
+}
61
+
62
/* Hide the qatomic_read to make code a little easier on the eyes */
63
static inline uint32_t tb_cflags(const TranslationBlock *tb)
64
{
65
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
26
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
66
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
67
--- a/include/tcg/tcg.h
28
--- a/include/tcg/tcg.h
68
+++ b/include/tcg/tcg.h
29
+++ b/include/tcg/tcg.h
69
@@ -XXX,XX +XXX,XX @@ void tcg_register_thread(void);
30
@@ -XXX,XX +XXX,XX @@ static inline const TCGOpcode *tcg_swap_vecop_list(const TCGOpcode *n)
70
void tcg_prologue_init(TCGContext *s);
71
void tcg_func_start(TCGContext *s);
72
73
-int tcg_gen_code(TCGContext *s, TranslationBlock *tb);
74
+int tcg_gen_code(TCGContext *s, TranslationBlock *tb, target_ulong pc_start);
75
76
void tcg_set_frame(TCGContext *s, TCGReg reg, intptr_t start, intptr_t size);
77
78
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/accel/tcg/cpu-exec.c
81
+++ b/accel/tcg/cpu-exec.c
82
@@ -XXX,XX +XXX,XX @@ static bool tb_lookup_cmp(const void *p, const void *d)
83
const TranslationBlock *tb = p;
84
const struct tb_desc *desc = d;
85
86
- if (tb->pc == desc->pc &&
87
+ if (tb_pc(tb) == desc->pc &&
88
tb->page_addr[0] == desc->page_addr0 &&
89
tb->cs_base == desc->cs_base &&
90
tb->flags == desc->flags &&
91
@@ -XXX,XX +XXX,XX @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
92
return tb;
93
}
31
}
94
32
95
-static inline void log_cpu_exec(target_ulong pc, CPUState *cpu,
33
bool tcg_can_emit_vecop_list(const TCGOpcode *, TCGType, unsigned);
96
- const TranslationBlock *tb)
34
+void tcg_dump_ops(TCGContext *s, FILE *f, bool have_prefs);
97
+static void log_cpu_exec(target_ulong pc, CPUState *cpu,
35
98
+ const TranslationBlock *tb)
36
#endif /* TCG_H */
37
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/accel/tcg/plugin-gen.c
40
+++ b/accel/tcg/plugin-gen.c
41
@@ -XXX,XX +XXX,XX @@
42
*/
43
#include "qemu/osdep.h"
44
#include "qemu/plugin.h"
45
+#include "qemu/log.h"
46
#include "cpu.h"
47
#include "tcg/tcg.h"
48
#include "tcg/tcg-temp-internal.h"
49
@@ -XXX,XX +XXX,XX @@ static void gen_mem_cb(struct qemu_plugin_dyn_cb *cb,
50
tcg_temp_free_i32(cpu_index);
51
}
52
53
-/* #define DEBUG_PLUGIN_GEN_OPS */
54
-static void pr_ops(void)
55
-{
56
-#ifdef DEBUG_PLUGIN_GEN_OPS
57
- TCGOp *op;
58
- int i = 0;
59
-
60
- QTAILQ_FOREACH(op, &tcg_ctx->ops, link) {
61
- const char *name = "";
62
- const char *type = "";
63
-
64
- if (op->opc == INDEX_op_plugin_cb_start) {
65
- switch (op->args[0]) {
66
- case PLUGIN_GEN_FROM_TB:
67
- name = "tb";
68
- break;
69
- case PLUGIN_GEN_FROM_INSN:
70
- name = "insn";
71
- break;
72
- case PLUGIN_GEN_FROM_MEM:
73
- name = "mem";
74
- break;
75
- case PLUGIN_GEN_AFTER_INSN:
76
- name = "after insn";
77
- break;
78
- default:
79
- break;
80
- }
81
- switch (op->args[1]) {
82
- case PLUGIN_GEN_CB_UDATA:
83
- type = "udata";
84
- break;
85
- case PLUGIN_GEN_CB_INLINE:
86
- type = "inline";
87
- break;
88
- case PLUGIN_GEN_CB_MEM:
89
- type = "mem";
90
- break;
91
- case PLUGIN_GEN_ENABLE_MEM_HELPER:
92
- type = "enable mem helper";
93
- break;
94
- case PLUGIN_GEN_DISABLE_MEM_HELPER:
95
- type = "disable mem helper";
96
- break;
97
- default:
98
- break;
99
- }
100
- }
101
- printf("op[%2i]: %s %s %s\n", i, tcg_op_defs[op->opc].name, name, type);
102
- i++;
103
- }
104
-#endif
105
-}
106
-
107
static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
99
{
108
{
100
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_CPU | CPU_LOG_EXEC))
109
TCGOp *op, *next;
101
- && qemu_log_in_addr_range(pc)) {
110
int insn_idx = -1;
102
-
111
103
+ if (qemu_log_in_addr_range(pc)) {
112
- pr_ops();
104
qemu_log_mask(CPU_LOG_EXEC,
113
+ if (unlikely(qemu_loglevel_mask(LOG_TB_OP_PLUGIN)
105
"Trace %d: %p [" TARGET_FMT_lx
114
+ && qemu_log_in_addr_range(plugin_tb->vaddr))) {
106
"/" TARGET_FMT_lx "/%08x/%08x] %s\n",
115
+ FILE *logfile = qemu_log_trylock();
107
@@ -XXX,XX +XXX,XX @@ const void *HELPER(lookup_tb_ptr)(CPUArchState *env)
116
+ if (logfile) {
108
return tcg_code_gen_epilogue;
117
+ fprintf(logfile, "OP before plugin injection:\n");
109
}
118
+ tcg_dump_ops(tcg_ctx, logfile, false);
110
119
+ fprintf(logfile, "\n");
111
- log_cpu_exec(pc, cpu, tb);
120
+ qemu_log_unlock(logfile);
112
+ if (qemu_loglevel_mask(CPU_LOG_TB_CPU | CPU_LOG_EXEC)) {
121
+ }
113
+ log_cpu_exec(pc, cpu, tb);
114
+ }
122
+ }
115
123
116
return tb->tc.ptr;
124
/*
117
}
125
* While injecting code, we cannot afford to reuse any ebb temps
118
@@ -XXX,XX +XXX,XX @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit)
126
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
119
TranslationBlock *last_tb;
127
break;
120
const void *tb_ptr = itb->tc.ptr;
121
122
- log_cpu_exec(itb->pc, cpu, itb);
123
+ if (qemu_loglevel_mask(CPU_LOG_TB_CPU | CPU_LOG_EXEC)) {
124
+ log_cpu_exec(log_pc(cpu, itb), cpu, itb);
125
+ }
126
127
qemu_thread_jit_execute();
128
ret = tcg_qemu_tb_exec(env, tb_ptr);
129
@@ -XXX,XX +XXX,XX @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit)
130
* of the start of the TB.
131
*/
132
CPUClass *cc = CPU_GET_CLASS(cpu);
133
- qemu_log_mask_and_addr(CPU_LOG_EXEC, last_tb->pc,
134
- "Stopped execution of TB chain before %p ["
135
- TARGET_FMT_lx "] %s\n",
136
- last_tb->tc.ptr, last_tb->pc,
137
- lookup_symbol(last_tb->pc));
138
+
139
if (cc->tcg_ops->synchronize_from_tb) {
140
cc->tcg_ops->synchronize_from_tb(cpu, last_tb);
141
} else {
142
assert(cc->set_pc);
143
- cc->set_pc(cpu, last_tb->pc);
144
+ cc->set_pc(cpu, tb_pc(last_tb));
145
+ }
146
+ if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
147
+ target_ulong pc = log_pc(cpu, last_tb);
148
+ if (qemu_log_in_addr_range(pc)) {
149
+ qemu_log("Stopped execution of TB chain before %p ["
150
+ TARGET_FMT_lx "] %s\n",
151
+ last_tb->tc.ptr, pc, lookup_symbol(pc));
152
+ }
153
}
128
}
154
}
129
}
155
130
- pr_ops();
156
@@ -XXX,XX +XXX,XX @@ static inline void tb_add_jump(TranslationBlock *tb, int n,
157
158
qemu_spin_unlock(&tb_next->jmp_lock);
159
160
- qemu_log_mask_and_addr(CPU_LOG_EXEC, tb->pc,
161
- "Linking TBs %p [" TARGET_FMT_lx
162
- "] index %d -> %p [" TARGET_FMT_lx "]\n",
163
- tb->tc.ptr, tb->pc, n,
164
- tb_next->tc.ptr, tb_next->pc);
165
+ qemu_log_mask(CPU_LOG_EXEC, "Linking TBs %p index %d -> %p\n",
166
+ tb->tc.ptr, n, tb_next->tc.ptr);
167
return;
168
169
out_unlock_next:
170
@@ -XXX,XX +XXX,XX @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
171
}
131
}
172
132
173
static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
133
bool plugin_gen_tb_start(CPUState *cpu, const DisasContextBase *db,
174
+ target_ulong pc,
175
TranslationBlock **last_tb, int *tb_exit)
176
{
177
int32_t insns_left;
178
179
- trace_exec_tb(tb, tb->pc);
180
+ trace_exec_tb(tb, pc);
181
tb = cpu_tb_exec(cpu, tb, tb_exit);
182
if (*tb_exit != TB_EXIT_REQUESTED) {
183
*last_tb = tb;
184
@@ -XXX,XX +XXX,XX @@ int cpu_exec(CPUState *cpu)
185
tb_add_jump(last_tb, tb_exit, tb);
186
}
187
188
- cpu_loop_exec_tb(cpu, tb, &last_tb, &tb_exit);
189
+ cpu_loop_exec_tb(cpu, tb, pc, &last_tb, &tb_exit);
190
191
/* Try to align the host and virtual clocks
192
if the guest is in advance */
193
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
194
index XXXXXXX..XXXXXXX 100644
195
--- a/accel/tcg/translate-all.c
196
+++ b/accel/tcg/translate-all.c
197
@@ -XXX,XX +XXX,XX @@ static int encode_search(TranslationBlock *tb, uint8_t *block)
198
199
for (j = 0; j < TARGET_INSN_START_WORDS; ++j) {
200
if (i == 0) {
201
- prev = (j == 0 ? tb->pc : 0);
202
+ prev = (j == 0 ? tb_pc(tb) : 0);
203
} else {
204
prev = tcg_ctx->gen_insn_data[i - 1][j];
205
}
206
@@ -XXX,XX +XXX,XX @@ static int encode_search(TranslationBlock *tb, uint8_t *block)
207
static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
208
uintptr_t searched_pc, bool reset_icount)
209
{
210
- target_ulong data[TARGET_INSN_START_WORDS] = { tb->pc };
211
+ target_ulong data[TARGET_INSN_START_WORDS] = { tb_pc(tb) };
212
uintptr_t host_pc = (uintptr_t)tb->tc.ptr;
213
CPUArchState *env = cpu->env_ptr;
214
const uint8_t *p = tb->tc.ptr + tb->tc.size;
215
@@ -XXX,XX +XXX,XX @@ static bool tb_cmp(const void *ap, const void *bp)
216
const TranslationBlock *a = ap;
217
const TranslationBlock *b = bp;
218
219
- return a->pc == b->pc &&
220
+ return tb_pc(a) == tb_pc(b) &&
221
a->cs_base == b->cs_base &&
222
a->flags == b->flags &&
223
(tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) &&
224
@@ -XXX,XX +XXX,XX @@ static void do_tb_invalidate_check(void *p, uint32_t hash, void *userp)
225
TranslationBlock *tb = p;
226
target_ulong addr = *(target_ulong *)userp;
227
228
- if (!(addr + TARGET_PAGE_SIZE <= tb->pc || addr >= tb->pc + tb->size)) {
229
+ if (!(addr + TARGET_PAGE_SIZE <= tb_pc(tb) ||
230
+ addr >= tb_pc(tb) + tb->size)) {
231
printf("ERROR invalidate: address=" TARGET_FMT_lx
232
- " PC=%08lx size=%04x\n", addr, (long)tb->pc, tb->size);
233
+ " PC=%08lx size=%04x\n", addr, (long)tb_pc(tb), tb->size);
234
}
235
}
236
237
@@ -XXX,XX +XXX,XX @@ static void do_tb_page_check(void *p, uint32_t hash, void *userp)
238
TranslationBlock *tb = p;
239
int flags1, flags2;
240
241
- flags1 = page_get_flags(tb->pc);
242
- flags2 = page_get_flags(tb->pc + tb->size - 1);
243
+ flags1 = page_get_flags(tb_pc(tb));
244
+ flags2 = page_get_flags(tb_pc(tb) + tb->size - 1);
245
if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
246
printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
247
- (long)tb->pc, tb->size, flags1, flags2);
248
+ (long)tb_pc(tb), tb->size, flags1, flags2);
249
}
250
}
251
252
@@ -XXX,XX +XXX,XX @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
253
254
/* remove the TB from the hash list */
255
phys_pc = tb->page_addr[0];
256
- h = tb_hash_func(phys_pc, tb->pc, tb->flags, orig_cflags,
257
+ h = tb_hash_func(phys_pc, tb_pc(tb), tb->flags, orig_cflags,
258
tb->trace_vcpu_dstate);
259
if (!qht_remove(&tb_ctx.htable, tb, h)) {
260
return;
261
@@ -XXX,XX +XXX,XX @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
262
}
263
264
/* add in the hash table */
265
- h = tb_hash_func(phys_pc, tb->pc, tb->flags, tb->cflags,
266
+ h = tb_hash_func(phys_pc, tb_pc(tb), tb->flags, tb->cflags,
267
tb->trace_vcpu_dstate);
268
qht_insert(&tb_ctx.htable, tb, h, &existing_tb);
269
270
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
271
tcg_ctx->cpu = NULL;
272
max_insns = tb->icount;
273
274
- trace_translate_block(tb, tb->pc, tb->tc.ptr);
275
+ trace_translate_block(tb, pc, tb->tc.ptr);
276
277
/* generate machine code */
278
tb->jmp_reset_offset[0] = TB_JMP_RESET_OFFSET_INVALID;
279
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
280
ti = profile_getclock();
281
#endif
282
283
- gen_code_size = tcg_gen_code(tcg_ctx, tb);
284
+ gen_code_size = tcg_gen_code(tcg_ctx, tb, pc);
285
if (unlikely(gen_code_size < 0)) {
286
error_return:
287
switch (gen_code_size) {
288
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
289
290
#ifdef DEBUG_DISAS
291
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM) &&
292
- qemu_log_in_addr_range(tb->pc)) {
293
+ qemu_log_in_addr_range(pc)) {
294
FILE *logfile = qemu_log_trylock();
295
if (logfile) {
296
int code_size, data_size;
297
@@ -XXX,XX +XXX,XX @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
298
*/
299
cpu->cflags_next_tb = curr_cflags(cpu) | CF_MEMI_ONLY | CF_LAST_IO | n;
300
301
- qemu_log_mask_and_addr(CPU_LOG_EXEC, tb->pc,
302
- "cpu_io_recompile: rewound execution of TB to "
303
- TARGET_FMT_lx "\n", tb->pc);
304
+ if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
305
+ target_ulong pc = log_pc(cpu, tb);
306
+ if (qemu_log_in_addr_range(pc)) {
307
+ qemu_log("cpu_io_recompile: rewound execution of TB to "
308
+ TARGET_FMT_lx "\n", pc);
309
+ }
310
+ }
311
312
cpu_loop_exit_noexc(cpu);
313
}
314
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
315
index XXXXXXX..XXXXXXX 100644
316
--- a/target/arm/cpu.c
317
+++ b/target/arm/cpu.c
318
@@ -XXX,XX +XXX,XX @@ void arm_cpu_synchronize_from_tb(CPUState *cs,
319
* never possible for an AArch64 TB to chain to an AArch32 TB.
320
*/
321
if (is_a64(env)) {
322
- env->pc = tb->pc;
323
+ env->pc = tb_pc(tb);
324
} else {
325
- env->regs[15] = tb->pc;
326
+ env->regs[15] = tb_pc(tb);
327
}
328
}
329
#endif /* CONFIG_TCG */
330
diff --git a/target/avr/cpu.c b/target/avr/cpu.c
331
index XXXXXXX..XXXXXXX 100644
332
--- a/target/avr/cpu.c
333
+++ b/target/avr/cpu.c
334
@@ -XXX,XX +XXX,XX @@ static void avr_cpu_synchronize_from_tb(CPUState *cs,
335
AVRCPU *cpu = AVR_CPU(cs);
336
CPUAVRState *env = &cpu->env;
337
338
- env->pc_w = tb->pc / 2; /* internally PC points to words */
339
+ env->pc_w = tb_pc(tb) / 2; /* internally PC points to words */
340
}
341
342
static void avr_cpu_reset(DeviceState *ds)
343
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
344
index XXXXXXX..XXXXXXX 100644
345
--- a/target/hexagon/cpu.c
346
+++ b/target/hexagon/cpu.c
347
@@ -XXX,XX +XXX,XX @@ static void hexagon_cpu_synchronize_from_tb(CPUState *cs,
348
{
349
HexagonCPU *cpu = HEXAGON_CPU(cs);
350
CPUHexagonState *env = &cpu->env;
351
- env->gpr[HEX_REG_PC] = tb->pc;
352
+ env->gpr[HEX_REG_PC] = tb_pc(tb);
353
}
354
355
static bool hexagon_cpu_has_work(CPUState *cs)
356
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
357
index XXXXXXX..XXXXXXX 100644
358
--- a/target/hppa/cpu.c
359
+++ b/target/hppa/cpu.c
360
@@ -XXX,XX +XXX,XX @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs,
361
HPPACPU *cpu = HPPA_CPU(cs);
362
363
#ifdef CONFIG_USER_ONLY
364
- cpu->env.iaoq_f = tb->pc;
365
+ cpu->env.iaoq_f = tb_pc(tb);
366
cpu->env.iaoq_b = tb->cs_base;
367
#else
368
/* Recover the IAOQ values from the GVA + PRIV. */
369
@@ -XXX,XX +XXX,XX @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs,
370
int32_t diff = cs_base;
371
372
cpu->env.iasq_f = iasq_f;
373
- cpu->env.iaoq_f = (tb->pc & ~iasq_f) + priv;
374
+ cpu->env.iaoq_f = (tb_pc(tb) & ~iasq_f) + priv;
375
if (diff) {
376
cpu->env.iaoq_b = cpu->env.iaoq_f + diff;
377
}
378
diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c
379
index XXXXXXX..XXXXXXX 100644
380
--- a/target/i386/tcg/tcg-cpu.c
381
+++ b/target/i386/tcg/tcg-cpu.c
382
@@ -XXX,XX +XXX,XX @@ static void x86_cpu_synchronize_from_tb(CPUState *cs,
383
{
384
X86CPU *cpu = X86_CPU(cs);
385
386
- cpu->env.eip = tb->pc - tb->cs_base;
387
+ cpu->env.eip = tb_pc(tb) - tb->cs_base;
388
}
389
390
#ifndef CONFIG_USER_ONLY
391
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
392
index XXXXXXX..XXXXXXX 100644
393
--- a/target/loongarch/cpu.c
394
+++ b/target/loongarch/cpu.c
395
@@ -XXX,XX +XXX,XX @@ static void loongarch_cpu_synchronize_from_tb(CPUState *cs,
396
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
397
CPULoongArchState *env = &cpu->env;
398
399
- env->pc = tb->pc;
400
+ env->pc = tb_pc(tb);
401
}
402
#endif /* CONFIG_TCG */
403
404
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
405
index XXXXXXX..XXXXXXX 100644
406
--- a/target/microblaze/cpu.c
407
+++ b/target/microblaze/cpu.c
408
@@ -XXX,XX +XXX,XX @@ static void mb_cpu_synchronize_from_tb(CPUState *cs,
409
{
410
MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
411
412
- cpu->env.pc = tb->pc;
413
+ cpu->env.pc = tb_pc(tb);
414
cpu->env.iflags = tb->flags & IFLAGS_TB_MASK;
415
}
416
417
diff --git a/target/mips/tcg/exception.c b/target/mips/tcg/exception.c
418
index XXXXXXX..XXXXXXX 100644
419
--- a/target/mips/tcg/exception.c
420
+++ b/target/mips/tcg/exception.c
421
@@ -XXX,XX +XXX,XX @@ void mips_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb)
422
MIPSCPU *cpu = MIPS_CPU(cs);
423
CPUMIPSState *env = &cpu->env;
424
425
- env->active_tc.PC = tb->pc;
426
+ env->active_tc.PC = tb_pc(tb);
427
env->hflags &= ~MIPS_HFLAG_BMASK;
428
env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
429
}
430
diff --git a/target/mips/tcg/sysemu/special_helper.c b/target/mips/tcg/sysemu/special_helper.c
431
index XXXXXXX..XXXXXXX 100644
432
--- a/target/mips/tcg/sysemu/special_helper.c
433
+++ b/target/mips/tcg/sysemu/special_helper.c
434
@@ -XXX,XX +XXX,XX @@ bool mips_io_recompile_replay_branch(CPUState *cs, const TranslationBlock *tb)
435
CPUMIPSState *env = &cpu->env;
436
437
if ((env->hflags & MIPS_HFLAG_BMASK) != 0
438
- && env->active_tc.PC != tb->pc) {
439
+ && env->active_tc.PC != tb_pc(tb)) {
440
env->active_tc.PC -= (env->hflags & MIPS_HFLAG_B16 ? 2 : 4);
441
env->hflags &= ~MIPS_HFLAG_BMASK;
442
return true;
443
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
444
index XXXXXXX..XXXXXXX 100644
445
--- a/target/openrisc/cpu.c
446
+++ b/target/openrisc/cpu.c
447
@@ -XXX,XX +XXX,XX @@ static void openrisc_cpu_synchronize_from_tb(CPUState *cs,
448
{
449
OpenRISCCPU *cpu = OPENRISC_CPU(cs);
450
451
- cpu->env.pc = tb->pc;
452
+ cpu->env.pc = tb_pc(tb);
453
}
454
455
456
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
457
index XXXXXXX..XXXXXXX 100644
458
--- a/target/riscv/cpu.c
459
+++ b/target/riscv/cpu.c
460
@@ -XXX,XX +XXX,XX @@ static void riscv_cpu_synchronize_from_tb(CPUState *cs,
461
RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
462
463
if (xl == MXL_RV32) {
464
- env->pc = (int32_t)tb->pc;
465
+ env->pc = (int32_t)tb_pc(tb);
466
} else {
467
- env->pc = tb->pc;
468
+ env->pc = tb_pc(tb);
469
}
470
}
471
472
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
473
index XXXXXXX..XXXXXXX 100644
474
--- a/target/rx/cpu.c
475
+++ b/target/rx/cpu.c
476
@@ -XXX,XX +XXX,XX @@ static void rx_cpu_synchronize_from_tb(CPUState *cs,
477
{
478
RXCPU *cpu = RX_CPU(cs);
479
480
- cpu->env.pc = tb->pc;
481
+ cpu->env.pc = tb_pc(tb);
482
}
483
484
static bool rx_cpu_has_work(CPUState *cs)
485
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
486
index XXXXXXX..XXXXXXX 100644
487
--- a/target/sh4/cpu.c
488
+++ b/target/sh4/cpu.c
489
@@ -XXX,XX +XXX,XX @@ static void superh_cpu_synchronize_from_tb(CPUState *cs,
490
{
491
SuperHCPU *cpu = SUPERH_CPU(cs);
492
493
- cpu->env.pc = tb->pc;
494
+ cpu->env.pc = tb_pc(tb);
495
cpu->env.flags = tb->flags & TB_FLAG_ENVFLAGS_MASK;
496
}
497
498
@@ -XXX,XX +XXX,XX @@ static bool superh_io_recompile_replay_branch(CPUState *cs,
499
CPUSH4State *env = &cpu->env;
500
501
if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
502
- && env->pc != tb->pc) {
503
+ && env->pc != tb_pc(tb)) {
504
env->pc -= 2;
505
env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
506
return true;
507
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
508
index XXXXXXX..XXXXXXX 100644
509
--- a/target/sparc/cpu.c
510
+++ b/target/sparc/cpu.c
511
@@ -XXX,XX +XXX,XX @@ static void sparc_cpu_synchronize_from_tb(CPUState *cs,
512
{
513
SPARCCPU *cpu = SPARC_CPU(cs);
514
515
- cpu->env.pc = tb->pc;
516
+ cpu->env.pc = tb_pc(tb);
517
cpu->env.npc = tb->cs_base;
518
}
519
520
diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c
521
index XXXXXXX..XXXXXXX 100644
522
--- a/target/tricore/cpu.c
523
+++ b/target/tricore/cpu.c
524
@@ -XXX,XX +XXX,XX @@ static void tricore_cpu_synchronize_from_tb(CPUState *cs,
525
TriCoreCPU *cpu = TRICORE_CPU(cs);
526
CPUTriCoreState *env = &cpu->env;
527
528
- env->PC = tb->pc;
529
+ env->PC = tb_pc(tb);
530
}
531
532
static void tricore_cpu_reset(DeviceState *dev)
533
diff --git a/tcg/tcg.c b/tcg/tcg.c
134
diff --git a/tcg/tcg.c b/tcg/tcg.c
534
index XXXXXXX..XXXXXXX 100644
135
index XXXXXXX..XXXXXXX 100644
535
--- a/tcg/tcg.c
136
--- a/tcg/tcg.c
536
+++ b/tcg/tcg.c
137
+++ b/tcg/tcg.c
537
@@ -XXX,XX +XXX,XX @@ int64_t tcg_cpu_exec_time(void)
138
@@ -XXX,XX +XXX,XX @@ static const char bswap_flag_name[][6] = {
538
#endif
139
[TCG_BSWAP_IZ | TCG_BSWAP_OS] = "iz,os",
539
140
};
540
141
541
-int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
142
+#ifdef CONFIG_PLUGIN
542
+int tcg_gen_code(TCGContext *s, TranslationBlock *tb, target_ulong pc_start)
143
+static const char * const plugin_from_name[] = {
144
+ "from-tb",
145
+ "from-insn",
146
+ "after-insn",
147
+ "after-tb",
148
+};
149
+#endif
150
+
151
static inline bool tcg_regset_single(TCGRegSet d)
543
{
152
{
544
#ifdef CONFIG_PROFILER
153
return (d & (d - 1)) == 0;
545
TCGProfile *prof = &s->prof;
154
@@ -XXX,XX +XXX,XX @@ static inline TCGReg tcg_regset_first(TCGRegSet d)
546
@@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
155
#define ne_fprintf(...) \
547
156
({ int ret_ = fprintf(__VA_ARGS__); ret_ >= 0 ? ret_ : 0; })
548
#ifdef DEBUG_DISAS
157
549
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)
158
-static void tcg_dump_ops(TCGContext *s, FILE *f, bool have_prefs)
550
- && qemu_log_in_addr_range(tb->pc))) {
159
+void tcg_dump_ops(TCGContext *s, FILE *f, bool have_prefs)
551
+ && qemu_log_in_addr_range(pc_start))) {
160
{
552
FILE *logfile = qemu_log_trylock();
161
char buf[128];
553
if (logfile) {
162
TCGOp *op;
554
fprintf(logfile, "OP:\n");
163
@@ -XXX,XX +XXX,XX @@ static void tcg_dump_ops(TCGContext *s, FILE *f, bool have_prefs)
555
@@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
164
i = k = 1;
556
if (s->nb_indirects > 0) {
165
}
557
#ifdef DEBUG_DISAS
166
break;
558
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_IND)
167
+#ifdef CONFIG_PLUGIN
559
- && qemu_log_in_addr_range(tb->pc))) {
168
+ case INDEX_op_plugin_cb:
560
+ && qemu_log_in_addr_range(pc_start))) {
169
+ {
561
FILE *logfile = qemu_log_trylock();
170
+ TCGArg from = op->args[k++];
562
if (logfile) {
171
+ const char *name = NULL;
563
fprintf(logfile, "OP before indirect lowering:\n");
172
+
564
@@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
173
+ if (from < ARRAY_SIZE(plugin_from_name)) {
565
174
+ name = plugin_from_name[from];
566
#ifdef DEBUG_DISAS
175
+ }
567
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT)
176
+ if (name) {
568
- && qemu_log_in_addr_range(tb->pc))) {
177
+ col += ne_fprintf(f, "%s", name);
569
+ && qemu_log_in_addr_range(pc_start))) {
178
+ } else {
570
FILE *logfile = qemu_log_trylock();
179
+ col += ne_fprintf(f, "$0x%" TCG_PRIlx, from);
571
if (logfile) {
180
+ }
572
fprintf(logfile, "OP after optimization and liveness analysis:\n");
181
+ i = 1;
182
+ }
183
+ break;
184
+#endif
185
default:
186
i = 0;
187
break;
188
diff --git a/util/log.c b/util/log.c
189
index XXXXXXX..XXXXXXX 100644
190
--- a/util/log.c
191
+++ b/util/log.c
192
@@ -XXX,XX +XXX,XX @@ const QEMULogItem qemu_log_items[] = {
193
"show micro ops after optimization" },
194
{ CPU_LOG_TB_OP_IND, "op_ind",
195
"show micro ops before indirect lowering" },
196
+#ifdef CONFIG_PLUGIN
197
+ { LOG_TB_OP_PLUGIN, "op_plugin",
198
+ "show micro ops before plugin injection" },
199
+#endif
200
{ CPU_LOG_INT, "int",
201
"show interrupts/exceptions in short format" },
202
{ CPU_LOG_EXEC, "exec",
573
--
203
--
574
2.34.1
204
2.34.1
575
576
diff view generated by jsdifflib
1
Prepare for targets to be able to produce TBs that can
1
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
2
run in more than one virtual context.
3
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
3
---
7
accel/tcg/internal.h | 4 +++
4
accel/tcg/plugin-gen.c | 84 +++++++++++++++++++++---------------------
8
accel/tcg/tb-jmp-cache.h | 41 +++++++++++++++++++++++++
5
1 file changed, 41 insertions(+), 43 deletions(-)
9
include/exec/cpu-defs.h | 3 ++
10
include/exec/exec-all.h | 32 ++++++++++++++++++--
11
accel/tcg/cpu-exec.c | 16 ++++++----
12
accel/tcg/translate-all.c | 64 ++++++++++++++++++++++++++-------------
13
6 files changed, 131 insertions(+), 29 deletions(-)
14
6
15
diff --git a/accel/tcg/internal.h b/accel/tcg/internal.h
7
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
16
index XXXXXXX..XXXXXXX 100644
8
index XXXXXXX..XXXXXXX 100644
17
--- a/accel/tcg/internal.h
9
--- a/accel/tcg/plugin-gen.c
18
+++ b/accel/tcg/internal.h
10
+++ b/accel/tcg/plugin-gen.c
19
@@ -XXX,XX +XXX,XX @@ void tb_htable_init(void);
11
@@ -XXX,XX +XXX,XX @@ static void gen_mem_cb(struct qemu_plugin_dyn_cb *cb,
20
/* Return the current PC from CPU, which may be cached in TB. */
12
tcg_temp_free_i32(cpu_index);
21
static inline target_ulong log_pc(CPUState *cpu, const TranslationBlock *tb)
22
{
23
+#if TARGET_TB_PCREL
24
+ return cpu->cc->get_pc(cpu);
25
+#else
26
return tb_pc(tb);
27
+#endif
28
}
13
}
29
14
30
#endif /* ACCEL_TCG_INTERNAL_H */
15
+static void inject_cb(struct qemu_plugin_dyn_cb *cb)
31
diff --git a/accel/tcg/tb-jmp-cache.h b/accel/tcg/tb-jmp-cache.h
16
+
32
index XXXXXXX..XXXXXXX 100644
33
--- a/accel/tcg/tb-jmp-cache.h
34
+++ b/accel/tcg/tb-jmp-cache.h
35
@@ -XXX,XX +XXX,XX @@
36
37
/*
38
* Accessed in parallel; all accesses to 'tb' must be atomic.
39
+ * For TARGET_TB_PCREL, accesses to 'pc' must be protected by
40
+ * a load_acquire/store_release to 'tb'.
41
*/
42
struct CPUJumpCache {
43
struct {
44
TranslationBlock *tb;
45
+#if TARGET_TB_PCREL
46
+ target_ulong pc;
47
+#endif
48
} array[TB_JMP_CACHE_SIZE];
49
};
50
51
+static inline TranslationBlock *
52
+tb_jmp_cache_get_tb(CPUJumpCache *jc, uint32_t hash)
53
+{
17
+{
54
+#if TARGET_TB_PCREL
18
+ switch (cb->type) {
55
+ /* Use acquire to ensure current load of pc from jc. */
19
+ case PLUGIN_CB_REGULAR:
56
+ return qatomic_load_acquire(&jc->array[hash].tb);
20
+ gen_udata_cb(cb);
57
+#else
21
+ break;
58
+ /* Use rcu_read to ensure current load of pc from *tb. */
22
+ case PLUGIN_CB_INLINE:
59
+ return qatomic_rcu_read(&jc->array[hash].tb);
23
+ gen_inline_cb(cb);
60
+#endif
24
+ break;
25
+ default:
26
+ g_assert_not_reached();
27
+ }
61
+}
28
+}
62
+
29
+
63
+static inline target_ulong
30
+static void inject_mem_cb(struct qemu_plugin_dyn_cb *cb,
64
+tb_jmp_cache_get_pc(CPUJumpCache *jc, uint32_t hash, TranslationBlock *tb)
31
+ enum qemu_plugin_mem_rw rw,
32
+ qemu_plugin_meminfo_t meminfo, TCGv_i64 addr)
65
+{
33
+{
66
+#if TARGET_TB_PCREL
34
+ if (cb->rw & rw) {
67
+ return jc->array[hash].pc;
35
+ switch (cb->type) {
68
+#else
36
+ case PLUGIN_CB_MEM_REGULAR:
69
+ return tb_pc(tb);
37
+ gen_mem_cb(cb, meminfo, addr);
70
+#endif
38
+ break;
71
+}
39
+ default:
72
+
40
+ inject_cb(cb);
73
+static inline void
41
+ break;
74
+tb_jmp_cache_set(CPUJumpCache *jc, uint32_t hash,
75
+ TranslationBlock *tb, target_ulong pc)
76
+{
77
+#if TARGET_TB_PCREL
78
+ jc->array[hash].pc = pc;
79
+ /* Use store_release on tb to ensure pc is written first. */
80
+ qatomic_store_release(&jc->array[hash].tb, tb);
81
+#else
82
+ /* Use the pc value already stored in tb->pc. */
83
+ qatomic_set(&jc->array[hash].tb, tb);
84
+#endif
85
+}
86
+
87
#endif /* ACCEL_TCG_TB_JMP_CACHE_H */
88
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
89
index XXXXXXX..XXXXXXX 100644
90
--- a/include/exec/cpu-defs.h
91
+++ b/include/exec/cpu-defs.h
92
@@ -XXX,XX +XXX,XX @@
93
# error TARGET_PAGE_BITS must be defined in cpu-param.h
94
# endif
95
#endif
96
+#ifndef TARGET_TB_PCREL
97
+# define TARGET_TB_PCREL 0
98
+#endif
99
100
#define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8)
101
102
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
103
index XXXXXXX..XXXXXXX 100644
104
--- a/include/exec/exec-all.h
105
+++ b/include/exec/exec-all.h
106
@@ -XXX,XX +XXX,XX @@ struct tb_tc {
107
};
108
109
struct TranslationBlock {
110
- target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */
111
- target_ulong cs_base; /* CS base for this block */
112
+#if !TARGET_TB_PCREL
113
+ /*
114
+ * Guest PC corresponding to this block. This must be the true
115
+ * virtual address. Therefore e.g. x86 stores EIP + CS_BASE, and
116
+ * targets like Arm, MIPS, HP-PA, which reuse low bits for ISA or
117
+ * privilege, must store those bits elsewhere.
118
+ *
119
+ * If TARGET_TB_PCREL, the opcodes for the TranslationBlock are
120
+ * written such that the TB is associated only with the physical
121
+ * page and may be run in any virtual address context. In this case,
122
+ * PC must always be taken from ENV in a target-specific manner.
123
+ * Unwind information is taken as offsets from the page, to be
124
+ * deposited into the "current" PC.
125
+ */
126
+ target_ulong pc;
127
+#endif
128
+
129
+ /*
130
+ * Target-specific data associated with the TranslationBlock, e.g.:
131
+ * x86: the original user, the Code Segment virtual base,
132
+ * arm: an extension of tb->flags,
133
+ * s390x: instruction data for EXECUTE,
134
+ * sparc: the next pc of the instruction queue (for delay slots).
135
+ */
136
+ target_ulong cs_base;
137
+
138
uint32_t flags; /* flags defining in which context the code was generated */
139
uint32_t cflags; /* compile flags */
140
141
@@ -XXX,XX +XXX,XX @@ struct TranslationBlock {
142
/* Hide the read to avoid ifdefs for TARGET_TB_PCREL. */
143
static inline target_ulong tb_pc(const TranslationBlock *tb)
144
{
145
+#if TARGET_TB_PCREL
146
+ qemu_build_not_reached();
147
+#else
148
return tb->pc;
149
+#endif
150
}
151
152
/* Hide the qatomic_read to make code a little easier on the eyes */
153
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
154
index XXXXXXX..XXXXXXX 100644
155
--- a/accel/tcg/cpu-exec.c
156
+++ b/accel/tcg/cpu-exec.c
157
@@ -XXX,XX +XXX,XX @@ static bool tb_lookup_cmp(const void *p, const void *d)
158
const TranslationBlock *tb = p;
159
const struct tb_desc *desc = d;
160
161
- if (tb_pc(tb) == desc->pc &&
162
+ if ((TARGET_TB_PCREL || tb_pc(tb) == desc->pc) &&
163
tb->page_addr[0] == desc->page_addr0 &&
164
tb->cs_base == desc->cs_base &&
165
tb->flags == desc->flags &&
166
@@ -XXX,XX +XXX,XX @@ static TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
167
return NULL;
168
}
169
desc.page_addr0 = phys_pc;
170
- h = tb_hash_func(phys_pc, pc, flags, cflags, *cpu->trace_dstate);
171
+ h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : pc),
172
+ flags, cflags, *cpu->trace_dstate);
173
return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp);
174
}
175
176
@@ -XXX,XX +XXX,XX @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
177
uint32_t flags, uint32_t cflags)
178
{
179
TranslationBlock *tb;
180
+ CPUJumpCache *jc;
181
uint32_t hash;
182
183
/* we should never be trying to look up an INVALID tb */
184
tcg_debug_assert(!(cflags & CF_INVALID));
185
186
hash = tb_jmp_cache_hash_func(pc);
187
- tb = qatomic_rcu_read(&cpu->tb_jmp_cache->array[hash].tb);
188
+ jc = cpu->tb_jmp_cache;
189
+ tb = tb_jmp_cache_get_tb(jc, hash);
190
191
if (likely(tb &&
192
- tb->pc == pc &&
193
+ tb_jmp_cache_get_pc(jc, hash, tb) == pc &&
194
tb->cs_base == cs_base &&
195
tb->flags == flags &&
196
tb->trace_vcpu_dstate == *cpu->trace_dstate &&
197
@@ -XXX,XX +XXX,XX @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
198
if (tb == NULL) {
199
return NULL;
200
}
201
- qatomic_set(&cpu->tb_jmp_cache->array[hash].tb, tb);
202
+ tb_jmp_cache_set(jc, hash, tb, pc);
203
return tb;
204
}
205
206
@@ -XXX,XX +XXX,XX @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit)
207
if (cc->tcg_ops->synchronize_from_tb) {
208
cc->tcg_ops->synchronize_from_tb(cpu, last_tb);
209
} else {
210
+ assert(!TARGET_TB_PCREL);
211
assert(cc->set_pc);
212
cc->set_pc(cpu, tb_pc(last_tb));
213
}
214
@@ -XXX,XX +XXX,XX @@ int cpu_exec(CPUState *cpu)
215
* for the fast lookup
216
*/
217
h = tb_jmp_cache_hash_func(pc);
218
- qatomic_set(&cpu->tb_jmp_cache->array[h].tb, tb);
219
+ tb_jmp_cache_set(cpu->tb_jmp_cache, h, tb, pc);
220
}
221
222
#ifndef CONFIG_USER_ONLY
223
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
224
index XXXXXXX..XXXXXXX 100644
225
--- a/accel/tcg/translate-all.c
226
+++ b/accel/tcg/translate-all.c
227
@@ -XXX,XX +XXX,XX @@ static int encode_search(TranslationBlock *tb, uint8_t *block)
228
229
for (j = 0; j < TARGET_INSN_START_WORDS; ++j) {
230
if (i == 0) {
231
- prev = (j == 0 ? tb_pc(tb) : 0);
232
+ prev = (!TARGET_TB_PCREL && j == 0 ? tb_pc(tb) : 0);
233
} else {
234
prev = tcg_ctx->gen_insn_data[i - 1][j];
235
}
236
@@ -XXX,XX +XXX,XX @@ static int encode_search(TranslationBlock *tb, uint8_t *block)
237
static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
238
uintptr_t searched_pc, bool reset_icount)
239
{
240
- target_ulong data[TARGET_INSN_START_WORDS] = { tb_pc(tb) };
241
+ target_ulong data[TARGET_INSN_START_WORDS];
242
uintptr_t host_pc = (uintptr_t)tb->tc.ptr;
243
CPUArchState *env = cpu->env_ptr;
244
const uint8_t *p = tb->tc.ptr + tb->tc.size;
245
@@ -XXX,XX +XXX,XX @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
246
return -1;
247
}
248
249
+ memset(data, 0, sizeof(data));
250
+ if (!TARGET_TB_PCREL) {
251
+ data[0] = tb_pc(tb);
252
+ }
253
+
254
/* Reconstruct the stored insn data while looking for the point at
255
which the end of the insn exceeds the searched_pc. */
256
for (i = 0; i < num_insns; ++i) {
257
@@ -XXX,XX +XXX,XX @@ static bool tb_cmp(const void *ap, const void *bp)
258
const TranslationBlock *a = ap;
259
const TranslationBlock *b = bp;
260
261
- return tb_pc(a) == tb_pc(b) &&
262
- a->cs_base == b->cs_base &&
263
- a->flags == b->flags &&
264
- (tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) &&
265
- a->trace_vcpu_dstate == b->trace_vcpu_dstate &&
266
- a->page_addr[0] == b->page_addr[0] &&
267
- a->page_addr[1] == b->page_addr[1];
268
+ return ((TARGET_TB_PCREL || tb_pc(a) == tb_pc(b)) &&
269
+ a->cs_base == b->cs_base &&
270
+ a->flags == b->flags &&
271
+ (tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) &&
272
+ a->trace_vcpu_dstate == b->trace_vcpu_dstate &&
273
+ a->page_addr[0] == b->page_addr[0] &&
274
+ a->page_addr[1] == b->page_addr[1]);
275
}
276
277
void tb_htable_init(void)
278
@@ -XXX,XX +XXX,XX @@ static inline void tb_jmp_unlink(TranslationBlock *dest)
279
qemu_spin_unlock(&dest->jmp_lock);
280
}
281
282
+static void tb_jmp_cache_inval_tb(TranslationBlock *tb)
283
+{
284
+ CPUState *cpu;
285
+
286
+ if (TARGET_TB_PCREL) {
287
+ /* A TB may be at any virtual address */
288
+ CPU_FOREACH(cpu) {
289
+ tcg_flush_jmp_cache(cpu);
290
+ }
291
+ } else {
292
+ uint32_t h = tb_jmp_cache_hash_func(tb_pc(tb));
293
+
294
+ CPU_FOREACH(cpu) {
295
+ CPUJumpCache *jc = cpu->tb_jmp_cache;
296
+
297
+ if (qatomic_read(&jc->array[h].tb) == tb) {
298
+ qatomic_set(&jc->array[h].tb, NULL);
299
+ }
300
+ }
42
+ }
301
+ }
43
+ }
302
+}
44
+}
303
+
45
+
304
/*
46
static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
305
* In user-mode, call with mmap_lock held.
306
* In !user-mode, if @rm_from_page_list is set, call with the TB's pages'
307
@@ -XXX,XX +XXX,XX @@ static inline void tb_jmp_unlink(TranslationBlock *dest)
308
*/
309
static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
310
{
47
{
311
- CPUState *cpu;
48
TCGOp *op, *next;
312
PageDesc *p;
49
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
313
uint32_t h;
50
314
tb_page_addr_t phys_pc;
51
cbs = plugin_tb->cbs;
315
@@ -XXX,XX +XXX,XX @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
52
for (i = 0, n = (cbs ? cbs->len : 0); i < n; i++) {
316
53
- struct qemu_plugin_dyn_cb *cb =
317
/* remove the TB from the hash list */
54
- &g_array_index(cbs, struct qemu_plugin_dyn_cb, i);
318
phys_pc = tb->page_addr[0];
55
-
319
- h = tb_hash_func(phys_pc, tb_pc(tb), tb->flags, orig_cflags,
56
- switch (cb->type) {
320
- tb->trace_vcpu_dstate);
57
- case PLUGIN_CB_REGULAR:
321
+ h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : tb_pc(tb)),
58
- gen_udata_cb(cb);
322
+ tb->flags, orig_cflags, tb->trace_vcpu_dstate);
59
- break;
323
if (!qht_remove(&tb_ctx.htable, tb, h)) {
60
- case PLUGIN_CB_INLINE:
324
return;
61
- gen_inline_cb(cb);
325
}
62
- break;
326
@@ -XXX,XX +XXX,XX @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
63
- default:
327
}
64
- g_assert_not_reached();
328
65
- }
329
/* remove the TB from the hash list */
66
+ inject_cb(
330
- h = tb_jmp_cache_hash_func(tb->pc);
67
+ &g_array_index(cbs, struct qemu_plugin_dyn_cb, i));
331
- CPU_FOREACH(cpu) {
68
}
332
- CPUJumpCache *jc = cpu->tb_jmp_cache;
69
break;
333
- if (qatomic_read(&jc->array[h].tb) == tb) {
70
334
- qatomic_set(&jc->array[h].tb, NULL);
71
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
335
- }
72
336
- }
73
cbs = insn->insn_cbs;
337
+ tb_jmp_cache_inval_tb(tb);
74
for (i = 0, n = (cbs ? cbs->len : 0); i < n; i++) {
338
75
- struct qemu_plugin_dyn_cb *cb =
339
/* suppress this TB from the two jump lists */
76
- &g_array_index(cbs, struct qemu_plugin_dyn_cb, i);
340
tb_remove_from_jmp_list(tb, 0);
77
-
341
@@ -XXX,XX +XXX,XX @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
78
- switch (cb->type) {
342
}
79
- case PLUGIN_CB_REGULAR:
343
80
- gen_udata_cb(cb);
344
/* add in the hash table */
81
- break;
345
- h = tb_hash_func(phys_pc, tb_pc(tb), tb->flags, tb->cflags,
82
- case PLUGIN_CB_INLINE:
346
- tb->trace_vcpu_dstate);
83
- gen_inline_cb(cb);
347
+ h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : tb_pc(tb)),
84
- break;
348
+ tb->flags, tb->cflags, tb->trace_vcpu_dstate);
85
- default:
349
qht_insert(&tb_ctx.htable, tb, h, &existing_tb);
86
- g_assert_not_reached();
350
87
- }
351
/* remove TB from the page(s) if we couldn't insert it */
88
+ inject_cb(
352
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
89
+ &g_array_index(cbs, struct qemu_plugin_dyn_cb, i));
353
90
}
354
gen_code_buf = tcg_ctx->code_gen_ptr;
91
break;
355
tb->tc.ptr = tcg_splitwx_to_rx(gen_code_buf);
92
356
+#if !TARGET_TB_PCREL
93
@@ -XXX,XX +XXX,XX @@ static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
357
tb->pc = pc;
94
{
358
+#endif
95
TCGv_i64 addr = temp_tcgv_i64(arg_temp(op->args[0]));
359
tb->cs_base = cs_base;
96
qemu_plugin_meminfo_t meminfo = op->args[1];
360
tb->flags = flags;
97
+ enum qemu_plugin_mem_rw rw =
361
tb->cflags = cflags;
98
+ (qemu_plugin_mem_is_store(meminfo)
99
+ ? QEMU_PLUGIN_MEM_W : QEMU_PLUGIN_MEM_R);
100
struct qemu_plugin_insn *insn;
101
const GArray *cbs;
102
- int i, n, rw;
103
+ int i, n;
104
105
assert(insn_idx >= 0);
106
insn = g_ptr_array_index(plugin_tb->insns, insn_idx);
107
- rw = qemu_plugin_mem_is_store(meminfo) ? 2 : 1;
108
109
tcg_ctx->emit_before_op = op;
110
111
cbs = insn->mem_cbs;
112
for (i = 0, n = (cbs ? cbs->len : 0); i < n; i++) {
113
- struct qemu_plugin_dyn_cb *cb =
114
- &g_array_index(cbs, struct qemu_plugin_dyn_cb, i);
115
-
116
- if (cb->rw & rw) {
117
- switch (cb->type) {
118
- case PLUGIN_CB_MEM_REGULAR:
119
- gen_mem_cb(cb, meminfo, addr);
120
- break;
121
- case PLUGIN_CB_INLINE:
122
- gen_inline_cb(cb);
123
- break;
124
- default:
125
- g_assert_not_reached();
126
- }
127
- }
128
+ inject_mem_cb(&g_array_index(cbs, struct qemu_plugin_dyn_cb, i),
129
+ rw, meminfo, addr);
130
}
131
132
tcg_ctx->emit_before_op = NULL;
362
--
133
--
363
2.34.1
134
2.34.1
364
365
diff view generated by jsdifflib
1
This function has two users, who use it incompatibly.
1
Merge qemu_plugin_insn_alloc and qemu_plugin_tb_insn_get into
2
In tlb_flush_page_by_mmuidx_async_0, when flushing a
2
plugin_gen_insn_start, since it is used nowhere else.
3
single page, we need to flush exactly two pages.
4
In tlb_flush_range_by_mmuidx_async_0, when flushing a
5
range of pages, we need to flush N+1 pages.
6
3
7
This avoids double-flushing of jmp cache pages in a range.
4
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
8
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
---
6
---
12
accel/tcg/cputlb.c | 25 ++++++++++++++-----------
7
include/qemu/plugin.h | 39 ---------------------------------------
13
1 file changed, 14 insertions(+), 11 deletions(-)
8
accel/tcg/plugin-gen.c | 39 ++++++++++++++++++++++++++++++++-------
9
2 files changed, 32 insertions(+), 46 deletions(-)
14
10
15
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
11
diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h
16
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
17
--- a/accel/tcg/cputlb.c
13
--- a/include/qemu/plugin.h
18
+++ b/accel/tcg/cputlb.c
14
+++ b/include/qemu/plugin.h
19
@@ -XXX,XX +XXX,XX @@ static void tb_jmp_cache_clear_page(CPUState *cpu, target_ulong page_addr)
15
@@ -XXX,XX +XXX,XX @@ static inline void qemu_plugin_insn_cleanup_fn(gpointer data)
20
}
16
g_byte_array_free(insn->data, true);
21
}
17
}
22
18
23
-static void tb_flush_jmp_cache(CPUState *cpu, target_ulong addr)
19
-static inline struct qemu_plugin_insn *qemu_plugin_insn_alloc(void)
24
-{
20
-{
25
- /* Discard jump cache entries for any tb which might potentially
21
- struct qemu_plugin_insn *insn = g_new0(struct qemu_plugin_insn, 1);
26
- overlap the flushed page. */
22
-
27
- tb_jmp_cache_clear_page(cpu, addr - TARGET_PAGE_SIZE);
23
- insn->data = g_byte_array_sized_new(4);
28
- tb_jmp_cache_clear_page(cpu, addr);
24
- return insn;
25
-}
26
-
27
/* Internal context for this TranslationBlock */
28
struct qemu_plugin_tb {
29
GPtrArray *insns;
30
@@ -XXX,XX +XXX,XX @@ struct qemu_plugin_tb {
31
GArray *cbs;
32
};
33
34
-/**
35
- * qemu_plugin_tb_insn_get(): get next plugin record for translation.
36
- * @tb: the internal tb context
37
- * @pc: address of instruction
38
- */
39
-static inline
40
-struct qemu_plugin_insn *qemu_plugin_tb_insn_get(struct qemu_plugin_tb *tb,
41
- uint64_t pc)
42
-{
43
- struct qemu_plugin_insn *insn;
44
-
45
- if (unlikely(tb->n == tb->insns->len)) {
46
- struct qemu_plugin_insn *new_insn = qemu_plugin_insn_alloc();
47
- g_ptr_array_add(tb->insns, new_insn);
48
- }
49
-
50
- insn = g_ptr_array_index(tb->insns, tb->n++);
51
- g_byte_array_set_size(insn->data, 0);
52
- insn->calls_helpers = false;
53
- insn->mem_helper = false;
54
- insn->vaddr = pc;
55
- if (insn->insn_cbs) {
56
- g_array_set_size(insn->insn_cbs, 0);
57
- }
58
- if (insn->mem_cbs) {
59
- g_array_set_size(insn->mem_cbs, 0);
60
- }
61
-
62
- return insn;
29
-}
63
-}
30
-
64
-
31
/**
65
/**
32
* tlb_mmu_resize_locked() - perform TLB resize bookkeeping; resize if necessary
66
* struct CPUPluginState - per-CPU state for plugins
33
* @desc: The CPUTLBDesc portion of the TLB
67
* @event_mask: plugin event bitmap. Modified only via async work.
34
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_page_by_mmuidx_async_0(CPUState *cpu,
68
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/accel/tcg/plugin-gen.c
71
+++ b/accel/tcg/plugin-gen.c
72
@@ -XXX,XX +XXX,XX @@ bool plugin_gen_tb_start(CPUState *cpu, const DisasContextBase *db,
73
void plugin_gen_insn_start(CPUState *cpu, const DisasContextBase *db)
74
{
75
struct qemu_plugin_tb *ptb = tcg_ctx->plugin_tb;
76
- struct qemu_plugin_insn *pinsn;
77
+ struct qemu_plugin_insn *insn;
78
+ size_t n = db->num_insns;
79
+ vaddr pc;
80
81
- pinsn = qemu_plugin_tb_insn_get(ptb, db->pc_next);
82
- tcg_ctx->plugin_insn = pinsn;
83
- plugin_gen_empty_callback(PLUGIN_GEN_FROM_INSN);
84
+ assert(n >= 1);
85
+ ptb->n = n;
86
+ if (n <= ptb->insns->len) {
87
+ insn = g_ptr_array_index(ptb->insns, n - 1);
88
+ g_byte_array_set_size(insn->data, 0);
89
+ } else {
90
+ assert(n - 1 == ptb->insns->len);
91
+ insn = g_new0(struct qemu_plugin_insn, 1);
92
+ insn->data = g_byte_array_sized_new(4);
93
+ g_ptr_array_add(ptb->insns, insn);
94
+ }
95
+
96
+ tcg_ctx->plugin_insn = insn;
97
+ insn->calls_helpers = false;
98
+ insn->mem_helper = false;
99
+ if (insn->insn_cbs) {
100
+ g_array_set_size(insn->insn_cbs, 0);
101
+ }
102
+ if (insn->mem_cbs) {
103
+ g_array_set_size(insn->mem_cbs, 0);
104
+ }
105
+
106
+ pc = db->pc_next;
107
+ insn->vaddr = pc;
108
109
/*
110
* Detect page crossing to get the new host address.
111
@@ -XXX,XX +XXX,XX @@ void plugin_gen_insn_start(CPUState *cpu, const DisasContextBase *db)
112
* fetching instructions from a region not backed by RAM.
113
*/
114
if (ptb->haddr1 == NULL) {
115
- pinsn->haddr = NULL;
116
+ insn->haddr = NULL;
117
} else if (is_same_page(db, db->pc_next)) {
118
- pinsn->haddr = ptb->haddr1 + pinsn->vaddr - ptb->vaddr;
119
+ insn->haddr = ptb->haddr1 + pc - ptb->vaddr;
120
} else {
121
if (ptb->vaddr2 == -1) {
122
ptb->vaddr2 = TARGET_PAGE_ALIGN(db->pc_first);
123
get_page_addr_code_hostp(cpu_env(cpu), ptb->vaddr2, &ptb->haddr2);
124
}
125
- pinsn->haddr = ptb->haddr2 + pinsn->vaddr - ptb->vaddr2;
126
+ insn->haddr = ptb->haddr2 + pc - ptb->vaddr2;
35
}
127
}
36
qemu_spin_unlock(&env_tlb(env)->c.lock);
128
+
37
129
+ plugin_gen_empty_callback(PLUGIN_GEN_FROM_INSN);
38
- tb_flush_jmp_cache(cpu, addr);
39
+ /*
40
+ * Discard jump cache entries for any tb which might potentially
41
+ * overlap the flushed page, which includes the previous.
42
+ */
43
+ tb_jmp_cache_clear_page(cpu, addr - TARGET_PAGE_SIZE);
44
+ tb_jmp_cache_clear_page(cpu, addr);
45
}
130
}
46
131
47
/**
132
void plugin_gen_insn_end(void)
48
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_range_by_mmuidx_async_0(CPUState *cpu,
49
return;
50
}
51
52
- for (target_ulong i = 0; i < d.len; i += TARGET_PAGE_SIZE) {
53
- tb_flush_jmp_cache(cpu, d.addr + i);
54
+ /*
55
+ * Discard jump cache entries for any tb which might potentially
56
+ * overlap the flushed pages, which includes the previous.
57
+ */
58
+ d.addr -= TARGET_PAGE_SIZE;
59
+ for (target_ulong i = 0, n = d.len / TARGET_PAGE_SIZE + 1; i < n; i++) {
60
+ tb_jmp_cache_clear_page(cpu, d.addr);
61
+ d.addr += TARGET_PAGE_SIZE;
62
}
63
}
64
65
--
133
--
66
2.34.1
134
2.34.1
67
68
diff view generated by jsdifflib
1
Add an interface to return the CPUTLBEntryFull struct
1
Each caller can use tcg_gen_plugin_cb directly.
2
that goes with the lookup. The result is not intended
3
to be valid across multiple lookups, so the user must
4
use the results immediately.
5
2
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
---
5
---
11
include/exec/exec-all.h | 15 +++++++++++++
6
accel/tcg/plugin-gen.c | 19 +++----------------
12
include/qemu/typedefs.h | 1 +
7
1 file changed, 3 insertions(+), 16 deletions(-)
13
accel/tcg/cputlb.c | 47 +++++++++++++++++++++++++----------------
14
3 files changed, 45 insertions(+), 18 deletions(-)
15
8
16
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
9
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
17
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
18
--- a/include/exec/exec-all.h
11
--- a/accel/tcg/plugin-gen.c
19
+++ b/include/exec/exec-all.h
12
+++ b/accel/tcg/plugin-gen.c
20
@@ -XXX,XX +XXX,XX @@ int probe_access_flags(CPUArchState *env, target_ulong addr,
13
@@ -XXX,XX +XXX,XX @@ enum plugin_gen_from {
21
MMUAccessType access_type, int mmu_idx,
14
PLUGIN_GEN_AFTER_TB,
22
bool nonfault, void **phost, uintptr_t retaddr);
15
};
23
16
24
+#ifndef CONFIG_USER_ONLY
17
-static void plugin_gen_empty_callback(enum plugin_gen_from from)
25
+/**
18
-{
26
+ * probe_access_full:
19
- switch (from) {
27
+ * Like probe_access_flags, except also return into @pfull.
20
- case PLUGIN_GEN_AFTER_INSN:
28
+ *
21
- case PLUGIN_GEN_FROM_TB:
29
+ * The CPUTLBEntryFull structure returned via @pfull is transient
22
- case PLUGIN_GEN_FROM_INSN:
30
+ * and must be consumed or copied immediately, before any further
23
- tcg_gen_plugin_cb(from);
31
+ * access or changes to TLB @mmu_idx.
24
- break;
32
+ */
25
- default:
33
+int probe_access_full(CPUArchState *env, target_ulong addr,
26
- g_assert_not_reached();
34
+ MMUAccessType access_type, int mmu_idx,
27
- }
35
+ bool nonfault, void **phost,
28
-}
36
+ CPUTLBEntryFull **pfull, uintptr_t retaddr);
29
-
37
+#endif
30
/* called before finishing a TB with exit_tb, goto_tb or goto_ptr */
38
+
31
void plugin_gen_disable_mem_helpers(void)
39
#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
40
41
/* Estimated block size for TB allocation. */
42
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
43
index XXXXXXX..XXXXXXX 100644
44
--- a/include/qemu/typedefs.h
45
+++ b/include/qemu/typedefs.h
46
@@ -XXX,XX +XXX,XX @@ typedef struct ConfidentialGuestSupport ConfidentialGuestSupport;
47
typedef struct CPUAddressSpace CPUAddressSpace;
48
typedef struct CPUArchState CPUArchState;
49
typedef struct CPUState CPUState;
50
+typedef struct CPUTLBEntryFull CPUTLBEntryFull;
51
typedef struct DeviceListener DeviceListener;
52
typedef struct DeviceState DeviceState;
53
typedef struct DirtyBitmapSnapshot DirtyBitmapSnapshot;
54
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/accel/tcg/cputlb.c
57
+++ b/accel/tcg/cputlb.c
58
@@ -XXX,XX +XXX,XX @@ static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size,
59
static int probe_access_internal(CPUArchState *env, target_ulong addr,
60
int fault_size, MMUAccessType access_type,
61
int mmu_idx, bool nonfault,
62
- void **phost, uintptr_t retaddr)
63
+ void **phost, CPUTLBEntryFull **pfull,
64
+ uintptr_t retaddr)
65
{
32
{
66
uintptr_t index = tlb_index(env, mmu_idx, addr);
33
@@ -XXX,XX +XXX,XX @@ bool plugin_gen_tb_start(CPUState *cpu, const DisasContextBase *db,
67
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
34
ptb->mem_only = mem_only;
68
@@ -XXX,XX +XXX,XX @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
35
ptb->mem_helper = false;
69
mmu_idx, nonfault, retaddr)) {
36
70
/* Non-faulting page table read failed. */
37
- plugin_gen_empty_callback(PLUGIN_GEN_FROM_TB);
71
*phost = NULL;
38
+ tcg_gen_plugin_cb(PLUGIN_GEN_FROM_TB);
72
+ *pfull = NULL;
73
return TLB_INVALID_MASK;
74
}
75
76
/* TLB resize via tlb_fill may have moved the entry. */
77
+ index = tlb_index(env, mmu_idx, addr);
78
entry = tlb_entry(env, mmu_idx, addr);
79
80
/*
81
@@ -XXX,XX +XXX,XX @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
82
}
39
}
83
flags &= tlb_addr;
40
84
41
tcg_ctx->plugin_insn = NULL;
85
+ *pfull = &env_tlb(env)->d[mmu_idx].fulltlb[index];
42
@@ -XXX,XX +XXX,XX @@ void plugin_gen_insn_start(CPUState *cpu, const DisasContextBase *db)
86
+
43
insn->haddr = ptb->haddr2 + pc - ptb->vaddr2;
87
/* Fold all "mmio-like" bits into TLB_MMIO. This is not RAM. */
44
}
88
if (unlikely(flags & ~(TLB_WATCHPOINT | TLB_NOTDIRTY))) {
45
89
*phost = NULL;
46
- plugin_gen_empty_callback(PLUGIN_GEN_FROM_INSN);
90
@@ -XXX,XX +XXX,XX @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
47
+ tcg_gen_plugin_cb(PLUGIN_GEN_FROM_INSN);
91
return flags;
92
}
48
}
93
49
94
-int probe_access_flags(CPUArchState *env, target_ulong addr,
50
void plugin_gen_insn_end(void)
95
- MMUAccessType access_type, int mmu_idx,
96
- bool nonfault, void **phost, uintptr_t retaddr)
97
+int probe_access_full(CPUArchState *env, target_ulong addr,
98
+ MMUAccessType access_type, int mmu_idx,
99
+ bool nonfault, void **phost, CPUTLBEntryFull **pfull,
100
+ uintptr_t retaddr)
101
{
51
{
102
- int flags;
52
- plugin_gen_empty_callback(PLUGIN_GEN_AFTER_INSN);
103
-
53
+ tcg_gen_plugin_cb(PLUGIN_GEN_AFTER_INSN);
104
- flags = probe_access_internal(env, addr, 0, access_type, mmu_idx,
105
- nonfault, phost, retaddr);
106
+ int flags = probe_access_internal(env, addr, 0, access_type, mmu_idx,
107
+ nonfault, phost, pfull, retaddr);
108
109
/* Handle clean RAM pages. */
110
if (unlikely(flags & TLB_NOTDIRTY)) {
111
- uintptr_t index = tlb_index(env, mmu_idx, addr);
112
- CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
113
-
114
- notdirty_write(env_cpu(env), addr, 1, full, retaddr);
115
+ notdirty_write(env_cpu(env), addr, 1, *pfull, retaddr);
116
flags &= ~TLB_NOTDIRTY;
117
}
118
119
return flags;
120
}
54
}
121
55
122
+int probe_access_flags(CPUArchState *env, target_ulong addr,
56
/*
123
+ MMUAccessType access_type, int mmu_idx,
124
+ bool nonfault, void **phost, uintptr_t retaddr)
125
+{
126
+ CPUTLBEntryFull *full;
127
+
128
+ return probe_access_full(env, addr, access_type, mmu_idx,
129
+ nonfault, phost, &full, retaddr);
130
+}
131
+
132
void *probe_access(CPUArchState *env, target_ulong addr, int size,
133
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
134
{
135
+ CPUTLBEntryFull *full;
136
void *host;
137
int flags;
138
139
g_assert(-(addr | TARGET_PAGE_MASK) >= size);
140
141
flags = probe_access_internal(env, addr, size, access_type, mmu_idx,
142
- false, &host, retaddr);
143
+ false, &host, &full, retaddr);
144
145
/* Per the interface, size == 0 merely faults the access. */
146
if (size == 0) {
147
@@ -XXX,XX +XXX,XX @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
148
}
149
150
if (unlikely(flags & (TLB_NOTDIRTY | TLB_WATCHPOINT))) {
151
- uintptr_t index = tlb_index(env, mmu_idx, addr);
152
- CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
153
-
154
/* Handle watchpoints. */
155
if (flags & TLB_WATCHPOINT) {
156
int wp_access = (access_type == MMU_DATA_STORE
157
@@ -XXX,XX +XXX,XX @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
158
void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
159
MMUAccessType access_type, int mmu_idx)
160
{
161
+ CPUTLBEntryFull *full;
162
void *host;
163
int flags;
164
165
flags = probe_access_internal(env, addr, 0, access_type,
166
- mmu_idx, true, &host, 0);
167
+ mmu_idx, true, &host, &full, 0);
168
169
/* No combination of flags are expected by the caller. */
170
return flags ? NULL : host;
171
@@ -XXX,XX +XXX,XX @@ void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
172
tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
173
void **hostp)
174
{
175
+ CPUTLBEntryFull *full;
176
void *p;
177
178
(void)probe_access_internal(env, addr, 1, MMU_INST_FETCH,
179
- cpu_mmu_index(env, true), false, &p, 0);
180
+ cpu_mmu_index(env, true), false, &p, &full, 0);
181
if (p == NULL) {
182
return -1;
183
}
184
--
57
--
185
2.34.1
58
2.34.1
186
59
187
60
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
2
3
The class cast checkers are quite expensive and always on (unlike the
4
dynamic case who's checks are gated by CONFIG_QOM_CAST_DEBUG). To
5
avoid the overhead of repeatedly checking something which should never
6
change we cache the CPUClass reference for use in the hot code paths.
7
8
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-Id: <20220811151413.3350684-3-alex.bennee@linaro.org>
11
Signed-off-by: Cédric Le Goater <clg@kaod.org>
12
Message-Id: <20220923084803.498337-3-clg@kaod.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
---
3
---
15
include/hw/core/cpu.h | 9 +++++++++
4
accel/tcg/plugin-gen.c | 31 ++++---------------------------
16
cpu.c | 9 ++++-----
5
1 file changed, 4 insertions(+), 27 deletions(-)
17
2 files changed, 13 insertions(+), 5 deletions(-)
18
6
19
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
7
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
20
index XXXXXXX..XXXXXXX 100644
8
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/core/cpu.h
9
--- a/accel/tcg/plugin-gen.c
22
+++ b/include/hw/core/cpu.h
10
+++ b/accel/tcg/plugin-gen.c
23
@@ -XXX,XX +XXX,XX @@ typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size,
11
@@ -XXX,XX +XXX,XX @@
12
* Injecting the desired instrumentation could be done with a second
13
* translation pass that combined the instrumentation requests, but that
14
* would be ugly and inefficient since we would decode the guest code twice.
15
- * Instead, during TB translation we add "empty" instrumentation calls for all
16
- * possible instrumentation events, and then once we collect the instrumentation
17
- * requests from plugins, we either "fill in" those empty events or remove them
18
- * if they have no requests.
19
- *
20
- * When "filling in" an event we first copy the empty callback's TCG ops. This
21
- * might seem unnecessary, but it is done to support an arbitrary number
22
- * of callbacks per event. Take for example a regular instruction callback.
23
- * We first generate a callback to an empty helper function. Then, if two
24
- * plugins register one callback each for this instruction, we make two copies
25
- * of the TCG ops generated for the empty callback, substituting the function
26
- * pointer that points to the empty helper function with the plugins' desired
27
- * callback functions. After that we remove the empty callback's ops.
28
- *
29
- * Note that the location in TCGOp.args[] of the pointer to a helper function
30
- * varies across different guest and host architectures. Instead of duplicating
31
- * the logic that figures this out, we rely on the fact that the empty
32
- * callbacks point to empty functions that are unique pointers in the program.
33
- * Thus, to find the right location we just have to look for a match in
34
- * TCGOp.args[]. This is the main reason why we first copy an empty callback's
35
- * TCG ops and then fill them in; regardless of whether we have one or many
36
- * callbacks for that event, the logic to add all of them is the same.
37
- *
38
- * When generating more than one callback per event, we make a small
39
- * optimization to avoid generating redundant operations. For instance, for the
40
- * second and all subsequent callbacks of an event, we do not need to reload the
41
- * CPU's index into a TCG temp, since the first callback did it already.
42
+ * Instead, during TB translation we add "plugin_cb" marker opcodes
43
+ * for all possible instrumentation events, and then once we collect the
44
+ * instrumentation requests from plugins, we generate code for those markers
45
+ * or remove them if they have no requests.
24
*/
46
*/
25
#define CPU(obj) ((CPUState *)(obj))
47
#include "qemu/osdep.h"
26
48
#include "qemu/plugin.h"
27
+/*
28
+ * The class checkers bring in CPU_GET_CLASS() which is potentially
29
+ * expensive given the eventual call to
30
+ * object_class_dynamic_cast_assert(). Because of this the CPUState
31
+ * has a cached value for the class in cs->cc which is set up in
32
+ * cpu_exec_realizefn() for use in hot code paths.
33
+ */
34
typedef struct CPUClass CPUClass;
35
DECLARE_CLASS_CHECKERS(CPUClass, CPU,
36
TYPE_CPU)
37
@@ -XXX,XX +XXX,XX @@ struct qemu_work_item;
38
struct CPUState {
39
/*< private >*/
40
DeviceState parent_obj;
41
+ /* cache to avoid expensive CPU_GET_CLASS */
42
+ CPUClass *cc;
43
/*< public >*/
44
45
int nr_cores;
46
diff --git a/cpu.c b/cpu.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/cpu.c
49
+++ b/cpu.c
50
@@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_cpu_common = {
51
52
void cpu_exec_realizefn(CPUState *cpu, Error **errp)
53
{
54
-#ifndef CONFIG_USER_ONLY
55
- CPUClass *cc = CPU_GET_CLASS(cpu);
56
-#endif
57
+ /* cache the cpu class for the hotpath */
58
+ cpu->cc = CPU_GET_CLASS(cpu);
59
60
cpu_list_add(cpu);
61
if (!accel_cpu_realizefn(cpu, errp)) {
62
@@ -XXX,XX +XXX,XX @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
63
if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
64
vmstate_register(NULL, cpu->cpu_index, &vmstate_cpu_common, cpu);
65
}
66
- if (cc->sysemu_ops->legacy_vmsd != NULL) {
67
- vmstate_register(NULL, cpu->cpu_index, cc->sysemu_ops->legacy_vmsd, cpu);
68
+ if (cpu->cc->sysemu_ops->legacy_vmsd != NULL) {
69
+ vmstate_register(NULL, cpu->cpu_index, cpu->cc->sysemu_ops->legacy_vmsd, cpu);
70
}
71
#endif /* CONFIG_USER_ONLY */
72
}
73
--
49
--
74
2.34.1
50
2.34.1
75
76
diff view generated by jsdifflib