1
This is fixing #404 ("windows xp boot takes much longer...")
1
This is fixing #404 ("windows xp boot takes much longer...")
2
and several other similar reports.
2
and several other similar reports.
3
3
4
For v2, all prerequisites and 7 of the patches from v1 with
4
Changes for v5:
5
reviews are now upstream.
5
* Include missing hunk in tb_gen_code, as noted in reply to v4.
6
* Remove helper_check_breakpoints from target/arm/.
7
* Reorg cflags_for_breakpoints into check_for_breakpoints;
8
reorg cpu_exec to use a break instead of a longjmp.
9
* Move singlestep_enabled check from cflags_for_breakpoints
10
to curr_cflags, which makes cpu_exec_step_atomic cleaner.
6
11
7
Mark Cave-Ayland reported success with WinXP with v1, with
12
Changes for v4:
8
this patch set being even faster than b55f54bc~1. Which was
13
* Issue breakpoints directly from cflags_for_breakpoints.
9
a bit of a surprise, but I'll take it. It means that it's
14
Do not generate code for a TB beginning with a BP at all.
10
probably not worth making the breakpoint detection scheme
15
* Drop the problematic TranslatorOps.breakpoint_check hook entirely.
11
any more complicated.
12
16
13
I'd still like some more feedback. Given this is fixing a
17
Changes for v3:
14
regression from qemu 5.2 I feel comfortable delaying this
18
* Map CF_COUNT_MASK == 0 -> TCG_MAX_INSNS.
15
past soft freeze, but not past hard freeze on the 20th.
19
* Split out *_breakpoint_check fixes for avr, mips, riscv.
20
21
Changes for v2:
22
* All prerequisites and 7 of the patches from v1 with are merged.
23
24
Patches lacking review are all new:
25
03-target-alpha-Drop-goto_tb-path-in-gen_call_pal.patch
26
08-hw-core-Introduce-TCGCPUOps.debug_check_breakpoin.patch
27
09-target-arm-Implement-debug_check_breakpoint.patch
28
10-target-i386-Implement-debug_check_breakpoint.patch
29
11-accel-tcg-Merge-tb_find-into-its-only-caller.patch
30
12-accel-tcg-Move-breakpoint-recognition-outside-tra.patch
31
13-accel-tcg-Remove-TranslatorOps.breakpoint_check.patch
32
15-accel-tcg-Record-singlestep_enabled-in-tb-cflags.patch
16
33
17
34
18
r~
35
r~
19
36
20
37
21
Richard Henderson (10):
38
Richard Henderson (15):
22
accel/tcg: Reduce CF_COUNT_MASK to match TCG_MAX_INSNS
39
accel/tcg: Reduce CF_COUNT_MASK to match TCG_MAX_INSNS
23
accel/tcg: Move curr_cflags into cpu-exec.c
40
accel/tcg: Move curr_cflags into cpu-exec.c
41
target/alpha: Drop goto_tb path in gen_call_pal
24
accel/tcg: Add CF_NO_GOTO_TB and CF_NO_GOTO_PTR
42
accel/tcg: Add CF_NO_GOTO_TB and CF_NO_GOTO_PTR
25
accel/tcg: Drop CF_NO_GOTO_PTR from -d nochain
43
accel/tcg: Drop CF_NO_GOTO_PTR from -d nochain
26
accel/tcg: Handle -singlestep in curr_cflags
44
accel/tcg: Handle -singlestep in curr_cflags
27
accel/tcg: Use CF_NO_GOTO_{TB,PTR} in cpu_exec_step_atomic
45
accel/tcg: Use CF_NO_GOTO_{TB, PTR} in cpu_exec_step_atomic
28
accel/tcg: Move cflags lookup into tb_find
46
hw/core: Introduce TCGCPUOps.debug_check_breakpoint
29
accel/tcg: Adjust interface of TranslatorOps.breakpoint_check
47
target/arm: Implement debug_check_breakpoint
48
target/i386: Implement debug_check_breakpoint
49
accel/tcg: Merge tb_find into its only caller
50
accel/tcg: Move breakpoint recognition outside translation
51
accel/tcg: Remove TranslatorOps.breakpoint_check
30
accel/tcg: Hoist tb_cflags to a local in translator_loop
52
accel/tcg: Hoist tb_cflags to a local in translator_loop
31
accel/tcg: Encode breakpoint info into tb->cflags
53
accel/tcg: Record singlestep_enabled in tb->cflags
32
54
33
include/exec/exec-all.h | 30 +++++---
55
include/exec/exec-all.h | 24 +++--
34
include/exec/translator.h | 17 +++--
56
include/exec/translator.h | 11 --
35
accel/tcg/cpu-exec.c | 130 ++++++++++++++++++++++++++++------
57
include/hw/core/tcg-cpu-ops.h | 6 ++
58
target/arm/helper.h | 2 -
59
target/arm/internals.h | 3 +
60
accel/tcg/cpu-exec.c | 192 +++++++++++++++++++++++++---------
36
accel/tcg/translate-all.c | 7 +-
61
accel/tcg/translate-all.c | 7 +-
37
accel/tcg/translator.c | 79 ++++++++++++++-------
62
accel/tcg/translator.c | 39 ++-----
38
cpu.c | 24 -------
63
cpu.c | 24 -----
39
target/alpha/translate.c | 12 +---
64
target/alpha/translate.c | 31 +-----
40
target/arm/translate-a64.c | 14 ++--
65
target/arm/cpu.c | 1 +
41
target/arm/translate.c | 20 +++---
66
target/arm/cpu_tcg.c | 1 +
42
target/avr/translate.c | 6 +-
67
target/arm/debug_helper.c | 12 +--
43
target/cris/translate.c | 14 ++--
68
target/arm/translate-a64.c | 25 -----
44
target/hexagon/translate.c | 13 +---
69
target/arm/translate.c | 29 -----
45
target/hppa/translate.c | 7 +-
70
target/avr/translate.c | 10 --
46
target/i386/tcg/translate.c | 15 ++--
71
target/cris/translate.c | 20 ----
47
target/m68k/translate.c | 14 +---
72
target/hexagon/translate.c | 17 ---
48
target/microblaze/translate.c | 14 +---
73
target/hppa/translate.c | 11 --
49
target/mips/tcg/translate.c | 14 ++--
74
target/i386/tcg/tcg-cpu.c | 12 +++
50
target/nios2/translate.c | 13 +---
75
target/i386/tcg/translate.c | 28 -----
51
target/openrisc/translate.c | 11 +--
76
target/m68k/translate.c | 18 ----
52
target/ppc/translate.c | 13 +---
77
target/microblaze/translate.c | 18 ----
53
target/riscv/translate.c | 11 +--
78
target/mips/tcg/translate.c | 19 ----
54
target/rx/translate.c | 8 +--
79
target/nios2/translate.c | 27 -----
55
target/s390x/translate.c | 12 ++--
80
target/openrisc/translate.c | 17 ---
56
target/sh4/translate.c | 12 ++--
81
target/ppc/translate.c | 18 ----
57
target/sparc/translate.c | 9 ++-
82
target/riscv/translate.c | 17 ---
58
target/tricore/translate.c | 13 +---
83
target/rx/translate.c | 14 ---
59
target/xtensa/translate.c | 12 ++--
84
target/s390x/tcg/translate.c | 24 -----
60
tcg/tcg-op.c | 28 ++++----
85
target/sh4/translate.c | 18 ----
61
28 files changed, 280 insertions(+), 292 deletions(-)
86
target/sparc/translate.c | 17 ---
87
target/tricore/translate.c | 16 ---
88
target/xtensa/translate.c | 17 ---
89
tcg/tcg-op.c | 28 +++--
90
35 files changed, 206 insertions(+), 567 deletions(-)
62
91
63
--
92
--
64
2.25.1
93
2.25.1
65
94
66
95
diff view generated by jsdifflib
1
The space reserved for CF_COUNT_MASK was overly large.
1
The space reserved for CF_COUNT_MASK was overly large.
2
Reduce to free up cflags bits and eliminate an extra test.
2
Reduce to free up cflags bits and eliminate an extra test.
3
3
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-Id: <20210717221851.2124573-2-richard.henderson@linaro.org>
5
---
8
---
6
include/exec/exec-all.h | 4 +++-
9
include/exec/exec-all.h | 4 +++-
7
accel/tcg/translate-all.c | 5 ++---
10
accel/tcg/translate-all.c | 5 ++---
8
2 files changed, 5 insertions(+), 4 deletions(-)
11
2 files changed, 5 insertions(+), 4 deletions(-)
9
12
...
...
25
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
28
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
26
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
27
--- a/accel/tcg/translate-all.c
30
--- a/accel/tcg/translate-all.c
28
+++ b/accel/tcg/translate-all.c
31
+++ b/accel/tcg/translate-all.c
29
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
32
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
33
34
max_insns = cflags & CF_COUNT_MASK;
30
if (max_insns == 0) {
35
if (max_insns == 0) {
31
max_insns = CF_COUNT_MASK;
36
- max_insns = CF_COUNT_MASK;
37
- }
38
- if (max_insns > TCG_MAX_INSNS) {
39
max_insns = TCG_MAX_INSNS;
32
}
40
}
33
- if (max_insns > TCG_MAX_INSNS) {
34
- max_insns = TCG_MAX_INSNS;
35
- }
36
+ QEMU_BUILD_BUG_ON(CF_COUNT_MASK + 1 != TCG_MAX_INSNS);
41
+ QEMU_BUILD_BUG_ON(CF_COUNT_MASK + 1 != TCG_MAX_INSNS);
37
+
42
+
38
if (cpu->singlestep_enabled || singlestep) {
43
if (cpu->singlestep_enabled || singlestep) {
39
max_insns = 1;
44
max_insns = 1;
40
}
45
}
41
--
46
--
42
2.25.1
47
2.25.1
43
48
44
49
diff view generated by jsdifflib
1
We will shortly have more than a simple member read here,
1
We will shortly have more than a simple member read here,
2
with stuff not necessarily exposed to exec/exec-all.h.
2
with stuff not necessarily exposed to exec/exec-all.h.
3
3
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-Id: <20210717221851.2124573-3-richard.henderson@linaro.org>
5
---
9
---
6
include/exec/exec-all.h | 5 +----
10
include/exec/exec-all.h | 5 +----
7
accel/tcg/cpu-exec.c | 5 +++++
11
accel/tcg/cpu-exec.c | 5 +++++
8
2 files changed, 6 insertions(+), 4 deletions(-)
12
2 files changed, 6 insertions(+), 4 deletions(-)
9
13
...
...
diff view generated by jsdifflib
New patch
1
We are certain of a page crossing here, entering the
2
PALcode image, so the call to use_goto_tb that should
3
have been here will never succeed.
1
4
5
We are shortly going to add an assert to tcg_gen_goto_tb
6
that would trigger for this case.
7
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
10
target/alpha/translate.c | 15 ++-------------
11
1 file changed, 2 insertions(+), 13 deletions(-)
12
13
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/alpha/translate.c
16
+++ b/target/alpha/translate.c
17
@@ -XXX,XX +XXX,XX @@ static DisasJumpType gen_call_pal(DisasContext *ctx, int palcode)
18
? 0x2000 + (palcode - 0x80) * 64
19
: 0x1000 + palcode * 64);
20
21
- /* Since the destination is running in PALmode, we don't really
22
- need the page permissions check. We'll see the existence of
23
- the page when we create the TB, and we'll flush all TBs if
24
- we change the PAL base register. */
25
- if (!ctx->base.singlestep_enabled) {
26
- tcg_gen_goto_tb(0);
27
- tcg_gen_movi_i64(cpu_pc, entry);
28
- tcg_gen_exit_tb(ctx->base.tb, 0);
29
- return DISAS_NORETURN;
30
- } else {
31
- tcg_gen_movi_i64(cpu_pc, entry);
32
- return DISAS_PC_UPDATED;
33
- }
34
+ tcg_gen_movi_i64(cpu_pc, entry);
35
+ return DISAS_PC_UPDATED;
36
}
37
#endif
38
}
39
--
40
2.25.1
41
42
diff view generated by jsdifflib
...
...
4
Set bits during curr_cflags, test them in translator_use_goto_tb,
4
Set bits during curr_cflags, test them in translator_use_goto_tb,
5
assert we're not doing anything odd in tcg_gen_goto_tb. The test
5
assert we're not doing anything odd in tcg_gen_goto_tb. The test
6
in tcg_gen_exit_tb is redundant with the assert for goto_tb_issue_mask.
6
in tcg_gen_exit_tb is redundant with the assert for goto_tb_issue_mask.
7
7
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-Id: <20210717221851.2124573-4-richard.henderson@linaro.org>
9
---
12
---
10
include/exec/exec-all.h | 16 +++++++++-------
13
include/exec/exec-all.h | 16 +++++++++-------
11
accel/tcg/cpu-exec.c | 8 +++++++-
14
accel/tcg/cpu-exec.c | 8 +++++++-
12
accel/tcg/translator.c | 5 +++++
15
accel/tcg/translator.c | 5 +++++
13
tcg/tcg-op.c | 28 ++++++++++++----------------
16
tcg/tcg-op.c | 28 ++++++++++++----------------
...
...
diff view generated by jsdifflib
1
The purpose of suppressing goto_ptr from -d nochain had been
1
The purpose of suppressing goto_ptr from -d nochain had been
2
to return to the main loop so that -d cpu would be recognized.
2
to return to the main loop so that -d cpu would be recognized.
3
But we now include -d cpu logging in helper_lookup_tb_ptr so
3
But we now include -d cpu logging in helper_lookup_tb_ptr so
4
there is no need to exclude goto_ptr.
4
there is no need to exclude goto_ptr.
5
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-Id: <20210717221851.2124573-5-richard.henderson@linaro.org>
7
---
9
---
8
accel/tcg/cpu-exec.c | 2 +-
10
accel/tcg/cpu-exec.c | 2 +-
9
1 file changed, 1 insertion(+), 1 deletion(-)
11
1 file changed, 1 insertion(+), 1 deletion(-)
10
12
11
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
13
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
...
...
diff view generated by jsdifflib
1
Exchange the test in translator_use_goto_tb for CF_NO_GOTO_TB,
1
Exchange the test in translator_use_goto_tb for CF_NO_GOTO_TB,
2
and the test in tb_gen_code for setting CF_COUNT_MASK to 1.
2
and the test in tb_gen_code for setting CF_COUNT_MASK to 1.
3
3
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Message-Id: <20210717221851.2124573-6-richard.henderson@linaro.org>
5
---
7
---
6
accel/tcg/cpu-exec.c | 8 +++++++-
8
accel/tcg/cpu-exec.c | 8 +++++++-
7
accel/tcg/translate-all.c | 2 +-
9
accel/tcg/translate-all.c | 2 +-
8
accel/tcg/translator.c | 2 +-
10
accel/tcg/translator.c | 2 +-
9
3 files changed, 9 insertions(+), 3 deletions(-)
11
3 files changed, 9 insertions(+), 3 deletions(-)
...
...
diff view generated by jsdifflib
1
Request that the one TB returns immediately, so that
1
Request that the one TB returns immediately, so that
2
we release the exclusive lock as soon as possible.
2
we release the exclusive lock as soon as possible.
3
3
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Message-Id: <20210717221851.2124573-7-richard.henderson@linaro.org>
5
---
8
---
6
accel/tcg/cpu-exec.c | 11 ++++++++---
9
accel/tcg/cpu-exec.c | 11 ++++++++---
7
1 file changed, 8 insertions(+), 3 deletions(-)
10
1 file changed, 8 insertions(+), 3 deletions(-)
8
11
9
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
12
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
...
...
diff view generated by jsdifflib
New patch
1
New hook to return true when an architectural breakpoint is
2
to be recognized and false when it should be suppressed.
1
3
4
First use must wait until other pieces are in place.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
include/hw/core/tcg-cpu-ops.h | 6 ++++++
9
1 file changed, 6 insertions(+)
10
11
diff --git a/include/hw/core/tcg-cpu-ops.h b/include/hw/core/tcg-cpu-ops.h
12
index XXXXXXX..XXXXXXX 100644
13
--- a/include/hw/core/tcg-cpu-ops.h
14
+++ b/include/hw/core/tcg-cpu-ops.h
15
@@ -XXX,XX +XXX,XX @@ struct TCGCPUOps {
16
*/
17
bool (*debug_check_watchpoint)(CPUState *cpu, CPUWatchpoint *wp);
18
19
+ /**
20
+ * @debug_check_breakpoint: return true if the architectural
21
+ * breakpoint whose PC has matched should really fire.
22
+ */
23
+ bool (*debug_check_breakpoint)(CPUState *cpu);
24
+
25
/**
26
* @io_recompile_replay_branch: Callback for cpu_io_recompile.
27
*
28
--
29
2.25.1
30
31
diff view generated by jsdifflib
New patch
1
Reuse the code at the bottom of helper_check_breakpoints,
2
which is what we currently call from *_tr_breakpoint_check.
1
3
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
---
6
target/arm/internals.h | 3 +++
7
target/arm/cpu.c | 1 +
8
target/arm/cpu_tcg.c | 1 +
9
target/arm/debug_helper.c | 7 +++----
10
4 files changed, 8 insertions(+), 4 deletions(-)
11
12
diff --git a/target/arm/internals.h b/target/arm/internals.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/internals.h
15
+++ b/target/arm/internals.h
16
@@ -XXX,XX +XXX,XX @@ void hw_breakpoint_update(ARMCPU *cpu, int n);
17
*/
18
void hw_breakpoint_update_all(ARMCPU *cpu);
19
20
+/* Callback function for checking if a breakpoint should trigger. */
21
+bool arm_debug_check_breakpoint(CPUState *cs);
22
+
23
/* Callback function for checking if a watchpoint should trigger. */
24
bool arm_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp);
25
26
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/cpu.c
29
+++ b/target/arm/cpu.c
30
@@ -XXX,XX +XXX,XX @@ static const struct TCGCPUOps arm_tcg_ops = {
31
.do_unaligned_access = arm_cpu_do_unaligned_access,
32
.adjust_watchpoint_address = arm_adjust_watchpoint_address,
33
.debug_check_watchpoint = arm_debug_check_watchpoint,
34
+ .debug_check_breakpoint = arm_debug_check_breakpoint,
35
#endif /* !CONFIG_USER_ONLY */
36
};
37
#endif /* CONFIG_TCG */
38
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/cpu_tcg.c
41
+++ b/target/arm/cpu_tcg.c
42
@@ -XXX,XX +XXX,XX @@ static const struct TCGCPUOps arm_v7m_tcg_ops = {
43
.do_unaligned_access = arm_cpu_do_unaligned_access,
44
.adjust_watchpoint_address = arm_adjust_watchpoint_address,
45
.debug_check_watchpoint = arm_debug_check_watchpoint,
46
+ .debug_check_breakpoint = arm_debug_check_breakpoint,
47
#endif /* !CONFIG_USER_ONLY */
48
};
49
#endif /* CONFIG_TCG */
50
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/debug_helper.c
53
+++ b/target/arm/debug_helper.c
54
@@ -XXX,XX +XXX,XX @@ static bool check_watchpoints(ARMCPU *cpu)
55
return false;
56
}
57
58
-static bool check_breakpoints(ARMCPU *cpu)
59
+bool arm_debug_check_breakpoint(CPUState *cs)
60
{
61
+ ARMCPU *cpu = ARM_CPU(cs);
62
CPUARMState *env = &cpu->env;
63
int n;
64
65
@@ -XXX,XX +XXX,XX @@ static bool check_breakpoints(ARMCPU *cpu)
66
67
void HELPER(check_breakpoints)(CPUARMState *env)
68
{
69
- ARMCPU *cpu = env_archcpu(env);
70
-
71
- if (check_breakpoints(cpu)) {
72
+ if (arm_debug_check_breakpoint(env_cpu(env))) {
73
HELPER(exception_internal(env, EXCP_DEBUG));
74
}
75
}
76
--
77
2.25.1
78
79
diff view generated by jsdifflib
New patch
1
Return false for RF set, as we do in i386_tr_breakpoint_check.
1
2
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
---
5
target/i386/tcg/tcg-cpu.c | 12 ++++++++++++
6
1 file changed, 12 insertions(+)
7
8
diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c
9
index XXXXXXX..XXXXXXX 100644
10
--- a/target/i386/tcg/tcg-cpu.c
11
+++ b/target/i386/tcg/tcg-cpu.c
12
@@ -XXX,XX +XXX,XX @@ static void x86_cpu_synchronize_from_tb(CPUState *cs,
13
cpu->env.eip = tb->pc - tb->cs_base;
14
}
15
16
+#ifndef CONFIG_USER_ONLY
17
+static bool x86_debug_check_breakpoint(CPUState *cs)
18
+{
19
+ X86CPU *cpu = X86_CPU(cs);
20
+ CPUX86State *env = &cpu->env;
21
+
22
+ /* RF disables all architectural breakpoints. */
23
+ return !(env->eflags & RF_MASK);
24
+}
25
+#endif
26
+
27
#include "hw/core/tcg-cpu-ops.h"
28
29
static const struct TCGCPUOps x86_tcg_ops = {
30
@@ -XXX,XX +XXX,XX @@ static const struct TCGCPUOps x86_tcg_ops = {
31
.tlb_fill = x86_cpu_tlb_fill,
32
#ifndef CONFIG_USER_ONLY
33
.debug_excp_handler = breakpoint_handler,
34
+ .debug_check_breakpoint = x86_debug_check_breakpoint,
35
#endif /* !CONFIG_USER_ONLY */
36
};
37
38
--
39
2.25.1
40
41
diff view generated by jsdifflib
1
We will shortly require the guest pc for computing cflags,
1
We are going to want two things:
2
so move the choice just after cpu_get_tb_cpu_state.
2
(1) check for breakpoints will want to break out of the loop here,
3
(2) cflags can only be calculated with pc in hand.
3
4
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
---
6
---
6
accel/tcg/cpu-exec.c | 34 +++++++++++++++++-----------------
7
accel/tcg/cpu-exec.c | 83 ++++++++++++++++++++++----------------------
7
1 file changed, 17 insertions(+), 17 deletions(-)
8
1 file changed, 41 insertions(+), 42 deletions(-)
8
9
9
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
10
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
10
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
11
--- a/accel/tcg/cpu-exec.c
12
--- a/accel/tcg/cpu-exec.c
12
+++ b/accel/tcg/cpu-exec.c
13
+++ b/accel/tcg/cpu-exec.c
13
@@ -XXX,XX +XXX,XX @@ static inline void tb_add_jump(TranslationBlock *tb, int n,
14
@@ -XXX,XX +XXX,XX @@ static inline void tb_add_jump(TranslationBlock *tb, int n,
14
15
return;
15
static inline TranslationBlock *tb_find(CPUState *cpu,
16
}
16
TranslationBlock *last_tb,
17
18
-static inline TranslationBlock *tb_find(CPUState *cpu,
19
- TranslationBlock *last_tb,
17
- int tb_exit, uint32_t cflags)
20
- int tb_exit, uint32_t cflags)
18
+ int tb_exit)
21
-{
22
- CPUArchState *env = (CPUArchState *)cpu->env_ptr;
23
- TranslationBlock *tb;
24
- target_ulong cs_base, pc;
25
- uint32_t flags;
26
-
27
- cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
28
-
29
- tb = tb_lookup(cpu, pc, cs_base, flags, cflags);
30
- if (tb == NULL) {
31
- mmap_lock();
32
- tb = tb_gen_code(cpu, pc, cs_base, flags, cflags);
33
- mmap_unlock();
34
- /* We add the TB in the virtual pc hash table for the fast lookup */
35
- qatomic_set(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)], tb);
36
- }
37
-#ifndef CONFIG_USER_ONLY
38
- /* We don't take care of direct jumps when address mapping changes in
39
- * system emulation. So it's not safe to make a direct jump to a TB
40
- * spanning two pages because the mapping for the second page can change.
41
- */
42
- if (tb->page_addr[1] != -1) {
43
- last_tb = NULL;
44
- }
45
-#endif
46
- /* See if we can patch the calling TB. */
47
- if (last_tb) {
48
- tb_add_jump(last_tb, tb_exit, tb);
49
- }
50
- return tb;
51
-}
52
-
53
static inline bool cpu_handle_halt(CPUState *cpu)
19
{
54
{
20
CPUArchState *env = (CPUArchState *)cpu->env_ptr;
55
if (cpu->halted) {
21
TranslationBlock *tb;
22
target_ulong cs_base, pc;
23
- uint32_t flags;
24
+ uint32_t flags, cflags;
25
26
cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
27
28
+ /*
29
+ * When requested, use an exact setting for cflags for the next
30
+ * execution. This is used for icount, precise smc, and stop-
31
+ * after-access watchpoints. Since this request should never
32
+ * have CF_INVALID set, -1 is a convenient invalid value that
33
+ * does not require tcg headers for cpu_common_reset.
34
+ */
35
+ cflags = cpu->cflags_next_tb;
36
+ if (cflags == -1) {
37
+ cflags = curr_cflags(cpu);
38
+ } else {
39
+ cpu->cflags_next_tb = -1;
40
+ }
41
+
42
tb = tb_lookup(cpu, pc, cs_base, flags, cflags);
43
if (tb == NULL) {
44
mmap_lock();
45
@@ -XXX,XX +XXX,XX @@ int cpu_exec(CPUState *cpu)
56
@@ -XXX,XX +XXX,XX @@ int cpu_exec(CPUState *cpu)
46
int tb_exit = 0;
57
int tb_exit = 0;
47
58
48
while (!cpu_handle_interrupt(cpu, &last_tb)) {
59
while (!cpu_handle_interrupt(cpu, &last_tb)) {
49
- uint32_t cflags = cpu->cflags_next_tb;
60
- uint32_t cflags = cpu->cflags_next_tb;
50
- TranslationBlock *tb;
61
TranslationBlock *tb;
51
-
62
+ target_ulong cs_base, pc;
63
+ uint32_t flags, cflags;
64
52
- /* When requested, use an exact setting for cflags for the next
65
- /* When requested, use an exact setting for cflags for the next
53
- execution. This is used for icount, precise smc, and stop-
66
- execution. This is used for icount, precise smc, and stop-
54
- after-access watchpoints. Since this request should never
67
- after-access watchpoints. Since this request should never
55
- have CF_INVALID set, -1 is a convenient invalid value that
68
- have CF_INVALID set, -1 is a convenient invalid value that
56
- does not require tcg headers for cpu_common_reset. */
69
- does not require tcg headers for cpu_common_reset. */
57
- if (cflags == -1) {
70
+ /*
58
- cflags = curr_cflags(cpu);
71
+ * When requested, use an exact setting for cflags for the next
59
- } else {
72
+ * execution. This is used for icount, precise smc, and stop-
60
- cpu->cflags_next_tb = -1;
73
+ * after-access watchpoints. Since this request should never
61
- }
74
+ * have CF_INVALID set, -1 is a convenient invalid value that
62
-
75
+ * does not require tcg headers for cpu_common_reset.
76
+ */
77
+ cflags = cpu->cflags_next_tb;
78
if (cflags == -1) {
79
cflags = curr_cflags(cpu);
80
} else {
81
cpu->cflags_next_tb = -1;
82
}
83
63
- tb = tb_find(cpu, last_tb, tb_exit, cflags);
84
- tb = tb_find(cpu, last_tb, tb_exit, cflags);
64
+ TranslationBlock *tb = tb_find(cpu, last_tb, tb_exit);
85
+ cpu_get_tb_cpu_state(cpu->env_ptr, &pc, &cs_base, &flags);
86
+
87
+ tb = tb_lookup(cpu, pc, cs_base, flags, cflags);
88
+ if (tb == NULL) {
89
+ mmap_lock();
90
+ tb = tb_gen_code(cpu, pc, cs_base, flags, cflags);
91
+ mmap_unlock();
92
+ /*
93
+ * We add the TB in the virtual pc hash table
94
+ * for the fast lookup
95
+ */
96
+ qatomic_set(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)], tb);
97
+ }
98
+
99
+#ifndef CONFIG_USER_ONLY
100
+ /*
101
+ * We don't take care of direct jumps when address mapping
102
+ * changes in system emulation. So it's not safe to make a
103
+ * direct jump to a TB spanning two pages because the mapping
104
+ * for the second page can change.
105
+ */
106
+ if (tb->page_addr[1] != -1) {
107
+ last_tb = NULL;
108
+ }
109
+#endif
110
+ /* See if we can patch the calling TB. */
111
+ if (last_tb) {
112
+ tb_add_jump(last_tb, tb_exit, tb);
113
+ }
114
+
65
cpu_loop_exec_tb(cpu, tb, &last_tb, &tb_exit);
115
cpu_loop_exec_tb(cpu, tb, &last_tb, &tb_exit);
116
+
66
/* Try to align the host and virtual clocks
117
/* Try to align the host and virtual clocks
67
if the guest is in advance */
118
if the guest is in advance */
119
align_clocks(&sc, cpu);
68
--
120
--
69
2.25.1
121
2.25.1
70
122
71
123
diff view generated by jsdifflib
1
Having this data in cflags means that hashing takes care
1
Trigger breakpoints before beginning translation of a TB
2
of selecting a TB with or without exceptions built in.
2
that would begin with a BP. Thus we never generate code
3
Which means that we no longer need to flush all TBs.
3
for the BP at all.
4
4
5
This does require that we single-step while we're within a page
5
Single-step instructions within a page containing a BP so
6
that contains a breakpoint, so it's not yet ideal, but should be
6
that we are sure to check each insn for the BP as above.
7
an improvement over some corner-case slowdowns.
7
8
8
We no longer need to flush any TBs when changing BPs.
9
10
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/286
9
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/404
11
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/404
12
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/489
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
---
14
---
12
include/exec/exec-all.h | 7 ++++
15
accel/tcg/cpu-exec.c | 78 ++++++++++++++++++++++++++++++++++++++++--
13
accel/tcg/cpu-exec.c | 68 ++++++++++++++++++++++++++++++-
16
accel/tcg/translator.c | 24 +------------
14
accel/tcg/translate-all.c | 4 --
17
cpu.c | 20 -----------
15
accel/tcg/translator.c | 85 +++++++++++++++++++++------------------
18
3 files changed, 76 insertions(+), 46 deletions(-)
16
cpu.c | 24 -----------
19
17
5 files changed, 119 insertions(+), 69 deletions(-)
18
19
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/exec/exec-all.h
22
+++ b/include/exec/exec-all.h
23
@@ -XXX,XX +XXX,XX @@ struct TranslationBlock {
24
#define CF_USE_ICOUNT 0x00020000
25
#define CF_INVALID 0x00040000 /* TB is stale. Set with @jmp_lock held */
26
#define CF_PARALLEL 0x00080000 /* Generate code for a parallel context */
27
+#define CF_BP_MASK 0x00300000 /* See below */
28
+#define CF_BP_SHIFT 20
29
#define CF_CLUSTER_MASK 0xff000000 /* Top 8 bits are cluster ID */
30
#define CF_CLUSTER_SHIFT 24
31
32
+#define CF_BP_NONE (0 << CF_BP_SHIFT) /* TB does not interact with BPs */
33
+#define CF_BP_SSTEP (1 << CF_BP_SHIFT) /* gdbstub single-step in effect */
34
+#define CF_BP_GDB (2 << CF_BP_SHIFT) /* gdbstub breakpoint at tb->pc */
35
+#define CF_BP_CPU (3 << CF_BP_SHIFT) /* arch breakpoint at tb->pc */
36
+
37
/* Per-vCPU dynamic tracing state used to generate this TB */
38
uint32_t trace_vcpu_dstate;
39
40
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
20
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
41
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
42
--- a/accel/tcg/cpu-exec.c
22
--- a/accel/tcg/cpu-exec.c
43
+++ b/accel/tcg/cpu-exec.c
23
+++ b/accel/tcg/cpu-exec.c
44
@@ -XXX,XX +XXX,XX @@ static inline void log_cpu_exec(target_ulong pc, CPUState *cpu,
24
@@ -XXX,XX +XXX,XX @@ static inline void log_cpu_exec(target_ulong pc, CPUState *cpu,
45
}
25
}
46
}
26
}
47
27
48
+static uint32_t cflags_for_breakpoints(CPUState *cpu, target_ulong pc,
28
+static bool check_for_breakpoints(CPUState *cpu, target_ulong pc,
49
+ uint32_t cflags)
29
+ uint32_t *cflags)
50
+{
30
+{
51
+ uint32_t bflags = 0;
31
+ CPUBreakpoint *bp;
52
+
32
+ bool match_page = false;
53
+ if (unlikely(cpu->singlestep_enabled)) {
33
+
54
+ bflags = CF_BP_SSTEP;
34
+ if (likely(QTAILQ_EMPTY(&cpu->breakpoints))) {
55
+ } else {
35
+ return false;
56
+ bool match_page = false;
36
+ }
57
+ CPUBreakpoint *bp;
37
+
58
+
38
+ QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
59
+ QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
39
+ /*
60
+ /* Note exact pc matches */
40
+ * If we have an exact pc match, trigger the breakpoint.
61
+ if (pc == bp->pc) {
41
+ * Otherwise, note matches within the page.
62
+ if (bp->flags & BP_GDB) {
42
+ */
63
+ bflags = CF_BP_GDB;
43
+ if (pc == bp->pc) {
64
+ break;
44
+ bool match_bp = false;
65
+ }
45
+
66
+ if (bp->flags & BP_CPU) {
46
+ if (bp->flags & BP_GDB) {
67
+ bflags = CF_BP_CPU;
47
+ match_bp = true;
68
+ break;
48
+ } else if (bp->flags & BP_CPU) {
69
+ }
49
+#ifdef CONFIG_USER_ONLY
50
+ g_assert_not_reached();
51
+#else
52
+ CPUClass *cc = CPU_GET_CLASS(cpu);
53
+ assert(cc->tcg_ops->debug_check_breakpoint);
54
+ match_bp = cc->tcg_ops->debug_check_breakpoint(cpu);
55
+#endif
70
+ }
56
+ }
71
+ /* Note page matches */
57
+
72
+ if (((pc ^ bp->pc) & TARGET_PAGE_MASK) == 0) {
58
+ if (match_bp) {
73
+ match_page = true;
59
+ cpu->exception_index = EXCP_DEBUG;
60
+ return true;
74
+ }
61
+ }
62
+ } else if (((pc ^ bp->pc) & TARGET_PAGE_MASK) == 0) {
63
+ match_page = true;
75
+ }
64
+ }
76
+
77
+ if (likely(!bflags)) {
78
+ if (likely(!match_page)) {
79
+ return cflags;
80
+ }
81
+
82
+ /*
83
+ * Within the same page as a breakpoint, single-step,
84
+ * returning to helper_lookup_tb_ptr after each looking
85
+ * for the actual breakpoint.
86
+ *
87
+ * TODO: Perhaps better to record all of the TBs associated
88
+ * with a given virtual page that contains a breakpoint, and
89
+ * then invalidate them when a new overlapping breakpoint is
90
+ * set on the page. Non-overlapping TBs would not be
91
+ * invalidated, nor would any TB need to be invalidated as
92
+ * breakpoints are removed.
93
+ */
94
+ bflags = CF_NO_GOTO_TB;
95
+ }
96
+ }
65
+ }
97
+
66
+
98
+ /*
67
+ /*
99
+ * Reduce the TB to one insn.
68
+ * Within the same page as a breakpoint, single-step,
100
+ * In the case of a BP hit, we will be raising an exception anyway.
69
+ * returning to helper_lookup_tb_ptr after each looking
101
+ * In the case of a page hit, return to helper_lookup_tb_ptr after
70
+ * for the actual breakpoint.
102
+ * every insn to look for the breakpoint.
71
+ *
72
+ * TODO: Perhaps better to record all of the TBs associated
73
+ * with a given virtual page that contains a breakpoint, and
74
+ * then invalidate them when a new overlapping breakpoint is
75
+ * set on the page. Non-overlapping TBs would not be
76
+ * invalidated, nor would any TB need to be invalidated as
77
+ * breakpoints are removed.
103
+ */
78
+ */
104
+ return (cflags & ~CF_COUNT_MASK) | 1 | bflags;
79
+ if (match_page) {
80
+ *cflags = (*cflags & ~CF_COUNT_MASK) | CF_NO_GOTO_TB | 1;
81
+ }
82
+ return false;
105
+}
83
+}
106
+
84
+
107
/**
85
/**
108
* helper_lookup_tb_ptr: quick check for next tb
86
* helper_lookup_tb_ptr: quick check for next tb
109
* @env: current cpu state
87
* @env: current cpu state
...
...
115
+ uint32_t flags, cflags;
93
+ uint32_t flags, cflags;
116
94
117
cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
95
cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
118
96
119
- tb = tb_lookup(cpu, pc, cs_base, flags, curr_cflags(cpu));
97
- tb = tb_lookup(cpu, pc, cs_base, flags, curr_cflags(cpu));
120
+ cflags = cflags_for_breakpoints(cpu, pc, curr_cflags(cpu));
98
+ cflags = curr_cflags(cpu);
99
+ if (check_for_breakpoints(cpu, pc, &cflags)) {
100
+ cpu_loop_exit(cpu);
101
+ }
121
+
102
+
122
+ tb = tb_lookup(cpu, pc, cs_base, flags, cflags);
103
+ tb = tb_lookup(cpu, pc, cs_base, flags, cflags);
123
if (tb == NULL) {
104
if (tb == NULL) {
124
return tcg_code_gen_epilogue;
105
return tcg_code_gen_epilogue;
125
}
106
}
126
@@ -XXX,XX +XXX,XX @@ void cpu_exec_step_atomic(CPUState *cpu)
107
@@ -XXX,XX +XXX,XX @@ void cpu_exec_step_atomic(CPUState *cpu)
127
cflags &= ~CF_PARALLEL;
108
cflags &= ~CF_PARALLEL;
128
/* After 1 insn, return and release the exclusive lock. */
109
/* After 1 insn, return and release the exclusive lock. */
129
cflags |= CF_NO_GOTO_TB | CF_NO_GOTO_PTR | 1;
110
cflags |= CF_NO_GOTO_TB | CF_NO_GOTO_PTR | 1;
130
+ /* Raise any post-instruction debug exceptions. */
111
+ /*
131
+ cflags = cflags_for_breakpoints(cpu, pc, cflags);
112
+ * No need to check_for_breakpoints here.
113
+ * We only arrive in cpu_exec_step_atomic after beginning execution
114
+ * of an insn that includes an atomic operation we can't handle.
115
+ * Any breakpoint for this insn will have been recognized earlier.
116
+ */
132
117
133
tb = tb_lookup(cpu, pc, cs_base, flags, cflags);
118
tb = tb_lookup(cpu, pc, cs_base, flags, cflags);
134
if (tb == NULL) {
119
if (tb == NULL) {
135
@@ -XXX,XX +XXX,XX @@ static inline TranslationBlock *tb_find(CPUState *cpu,
120
@@ -XXX,XX +XXX,XX @@ int cpu_exec(CPUState *cpu)
136
} else {
121
target_ulong cs_base, pc;
137
cpu->cflags_next_tb = -1;
122
uint32_t flags, cflags;
138
}
123
139
+ cflags = cflags_for_breakpoints(cpu, pc, cflags);
124
+ cpu_get_tb_cpu_state(cpu->env_ptr, &pc, &cs_base, &flags);
140
125
+
141
tb = tb_lookup(cpu, pc, cs_base, flags, cflags);
126
/*
142
if (tb == NULL) {
127
* When requested, use an exact setting for cflags for the next
143
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
128
* execution. This is used for icount, precise smc, and stop-
144
index XXXXXXX..XXXXXXX 100644
129
@@ -XXX,XX +XXX,XX @@ int cpu_exec(CPUState *cpu)
145
--- a/accel/tcg/translate-all.c
130
cpu->cflags_next_tb = -1;
146
+++ b/accel/tcg/translate-all.c
131
}
147
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
132
148
}
133
- cpu_get_tb_cpu_state(cpu->env_ptr, &pc, &cs_base, &flags);
149
QEMU_BUILD_BUG_ON(CF_COUNT_MASK + 1 != TCG_MAX_INSNS);
134
+ if (check_for_breakpoints(cpu, pc, &cflags)) {
150
135
+ break;
151
- if (cpu->singlestep_enabled) {
136
+ }
152
- max_insns = 1;
137
153
- }
138
tb = tb_lookup(cpu, pc, cs_base, flags, cflags);
154
-
139
if (tb == NULL) {
155
buffer_overflow:
156
tb = tcg_tb_alloc(tcg_ctx);
157
if (unlikely(!tb)) {
158
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
140
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
159
index XXXXXXX..XXXXXXX 100644
141
index XXXXXXX..XXXXXXX 100644
160
--- a/accel/tcg/translator.c
142
--- a/accel/tcg/translator.c
161
+++ b/accel/tcg/translator.c
143
+++ b/accel/tcg/translator.c
162
@@ -XXX,XX +XXX,XX @@ void translator_loop_temp_check(DisasContextBase *db)
144
@@ -XXX,XX +XXX,XX @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest)
163
145
void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
164
bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest)
165
{
166
- /* Suppress goto_tb if requested. */
167
- if (tb_cflags(db->tb) & CF_NO_GOTO_TB) {
168
- return false;
169
- }
170
-
171
- /* Suppress goto_tb in the case of single-steping. */
172
- if (db->singlestep_enabled) {
173
+ /* Suppress goto_tb if requested, or required by breakpoints. */
174
+ if (tb_cflags(db->tb) & (CF_NO_GOTO_TB | CF_BP_MASK)) {
175
return false;
176
}
177
178
@@ -XXX,XX +XXX,XX @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
179
CPUState *cpu, TranslationBlock *tb, int max_insns)
146
CPUState *cpu, TranslationBlock *tb, int max_insns)
180
{
147
{
181
uint32_t cflags = tb_cflags(tb);
148
- int bp_insn = 0;
182
+ int bp_flags = 0;
183
bool plugin_enabled;
149
bool plugin_enabled;
184
150
185
/* Initialize DisasContext */
151
/* Initialize DisasContext */
186
@@ -XXX,XX +XXX,XX @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
152
@@ -XXX,XX +XXX,XX @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
187
db->is_jmp = DISAS_NEXT;
153
plugin_gen_insn_start(cpu, db);
188
db->num_insns = 0;
189
db->max_insns = max_insns;
190
- db->singlestep_enabled = cpu->singlestep_enabled;
191
+ db->singlestep_enabled = false;
192
+
193
+ switch (cflags & CF_BP_MASK) {
194
+ case CF_BP_NONE:
195
+ break;
196
+ case CF_BP_SSTEP:
197
+ db->singlestep_enabled = true;
198
+ break;
199
+ case CF_BP_GDB:
200
+ bp_flags = BP_GDB;
201
+ break;
202
+ case CF_BP_CPU:
203
+ bp_flags = BP_CPU;
204
+ break;
205
+ default:
206
+ g_assert_not_reached();
207
+ }
208
209
ops->init_disas_context(db, cpu);
210
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
211
@@ -XXX,XX +XXX,XX @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
212
}
154
}
213
155
214
/* Pass breakpoint hits to target for further processing */
156
- /* Pass breakpoint hits to target for further processing */
215
- if (!db->singlestep_enabled
157
- if (!db->singlestep_enabled
216
- && unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
158
- && unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
217
- CPUBreakpoint *bp;
159
- CPUBreakpoint *bp;
218
- QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
160
- QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
219
- if (bp->pc == db->pc_next) {
161
- if (bp->pc == db->pc_next) {
220
- int len = ops->breakpoint_check(db, cpu, bp->flags);
162
- if (ops->breakpoint_check(db, cpu, bp)) {
221
+ if (unlikely(bp_flags)) {
163
- bp_insn = 1;
222
+ int len = ops->breakpoint_check(db, cpu, bp_flags);
164
- break;
223
224
- /*
225
- * The breakpoint_check hook may use DISAS_TOO_MANY
226
- * to indicate that only one more instruction is to
227
- * be executed. Otherwise it should use DISAS_NORETURN
228
- * when generating an exception, but may use a
229
- * DISAS_TARGET_* value for Something Else.
230
- */
231
- if (db->is_jmp > DISAS_TOO_MANY) {
232
- /*
233
- * The address covered by the breakpoint must be
234
- * included in [tb->pc, tb->pc + tb->size) in order
235
- * to for it to be properly cleared. Thus we
236
- * increment the PC here so that the logic setting
237
- * tb->size below does the right thing.
238
- */
239
- tcg_debug_assert(len > 0);
240
- db->pc_next += len;
241
+ /*
242
+ * When there is a bp hit, we're going to execute a maximum
243
+ * of one instruction. The breakpoint_check hook may use
244
+ * DISAS_NEXT or DISAS_TOO_MANY to indicate that the current
245
+ * instruction should be translated. Anything else is taken
246
+ * to mean that an exception has been raised and that zero
247
+ * instructions will be executed.
248
+ */
249
+ if (db->is_jmp > DISAS_TOO_MANY) {
250
+ /*
251
+ * The address covered by the breakpoint must be
252
+ * included in [tb->pc, tb->pc + tb->size) in order
253
+ * to for it to be properly cleared. Thus we
254
+ * increment the PC here so that the logic setting
255
+ * tb->size below does the right thing.
256
+ */
257
+ tcg_debug_assert(len > 0);
258
+ db->pc_next += len;
259
260
- /*
261
- * The breakpoint definitely hit, so decrement the
262
- * number of instructions completed for icount.
263
- */
264
- db->num_insns--;
265
- goto done;
266
- }
165
- }
267
- }
166
- }
268
+ /*
167
- }
269
+ * The breakpoint definitely hit, so decrement the
168
- /* The breakpoint_check hook may use DISAS_TOO_MANY to indicate
270
+ * number of instructions completed for icount.
169
- that only one more instruction is to be executed. Otherwise
271
+ */
170
- it should use DISAS_NORETURN when generating an exception,
272
+ db->num_insns--;
171
- but may use a DISAS_TARGET_* value for Something Else. */
273
+ goto done;
172
- if (db->is_jmp > DISAS_TOO_MANY) {
274
}
173
- break;
275
}
174
- }
276
175
- }
176
-
177
/* Disassemble one instruction. The translate_insn hook should
178
update db->pc_next and db->is_jmp to indicate what should be
179
done next -- either exiting this loop or locate the start of
180
@@ -XXX,XX +XXX,XX @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
181
182
/* Emit code to exit the TB, as indicated by db->is_jmp. */
183
ops->tb_stop(db, cpu);
184
- gen_tb_end(db->tb, db->num_insns - bp_insn);
185
+ gen_tb_end(db->tb, db->num_insns);
186
187
if (plugin_enabled) {
188
plugin_gen_tb_end(cpu);
277
diff --git a/cpu.c b/cpu.c
189
diff --git a/cpu.c b/cpu.c
278
index XXXXXXX..XXXXXXX 100644
190
index XXXXXXX..XXXXXXX 100644
279
--- a/cpu.c
191
--- a/cpu.c
280
+++ b/cpu.c
192
+++ b/cpu.c
281
@@ -XXX,XX +XXX,XX @@ void tb_invalidate_phys_addr(target_ulong addr)
193
@@ -XXX,XX +XXX,XX @@ void tb_invalidate_phys_addr(target_ulong addr)
...
...
324
- breakpoint_invalidate(cpu, bp->pc);
236
- breakpoint_invalidate(cpu, bp->pc);
325
-
237
-
326
trace_breakpoint_remove(cpu->cpu_index, bp->pc, bp->flags);
238
trace_breakpoint_remove(cpu->cpu_index, bp->pc, bp->flags);
327
g_free(bp);
239
g_free(bp);
328
}
240
}
329
@@ -XXX,XX +XXX,XX @@ void cpu_single_step(CPUState *cpu, int enabled)
330
cpu->singlestep_enabled = enabled;
331
if (kvm_enabled()) {
332
kvm_update_guest_debug(cpu, 0);
333
- } else {
334
- /* must flush all the translated code to avoid inconsistencies */
335
- /* XXX: only flush what is necessary */
336
- tb_flush(cpu);
337
}
338
trace_breakpoint_singlestep(cpu->cpu_index, enabled);
339
}
340
--
241
--
341
2.25.1
242
2.25.1
342
243
343
244
diff view generated by jsdifflib
1
We don't need the whole CPUBreakpoint structure in the check,
1
The hook is now unused, with breakpoints checked outside translation.
2
only the flags. Return the instruction length to consolidate
3
the adjustment of db->pc_next.
4
2
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
4
---
7
include/exec/translator.h | 17 +++++++++------
5
include/exec/translator.h | 11 -----------
8
accel/tcg/translator.c | 40 ++++++++++++++++++++++++-----------
6
target/arm/helper.h | 2 --
9
target/alpha/translate.c | 12 +++--------
7
target/alpha/translate.c | 16 ----------------
10
target/arm/translate-a64.c | 14 ++++--------
8
target/arm/debug_helper.c | 7 -------
11
target/arm/translate.c | 20 +++++++-----------
9
target/arm/translate-a64.c | 25 -------------------------
12
target/avr/translate.c | 6 +++---
10
target/arm/translate.c | 29 -----------------------------
13
target/cris/translate.c | 14 ++++--------
11
target/avr/translate.c | 10 ----------
14
target/hexagon/translate.c | 13 +++---------
12
target/cris/translate.c | 20 --------------------
15
target/hppa/translate.c | 7 +++---
13
target/hexagon/translate.c | 17 -----------------
16
target/i386/tcg/translate.c | 15 ++++---------
14
target/hppa/translate.c | 11 -----------
17
target/m68k/translate.c | 14 +++---------
15
target/i386/tcg/translate.c | 28 ----------------------------
18
target/microblaze/translate.c | 14 +++---------
16
target/m68k/translate.c | 18 ------------------
19
target/mips/tcg/translate.c | 14 ++++--------
17
target/microblaze/translate.c | 18 ------------------
20
target/nios2/translate.c | 13 +++---------
18
target/mips/tcg/translate.c | 19 -------------------
21
target/openrisc/translate.c | 11 +++-------
19
target/nios2/translate.c | 27 ---------------------------
22
target/ppc/translate.c | 13 +++---------
20
target/openrisc/translate.c | 17 -----------------
23
target/riscv/translate.c | 11 +++-------
21
target/ppc/translate.c | 18 ------------------
24
target/rx/translate.c | 8 +++----
22
target/riscv/translate.c | 17 -----------------
25
target/s390x/translate.c | 12 ++++-------
23
target/rx/translate.c | 14 --------------
26
target/sh4/translate.c | 12 ++++-------
24
target/s390x/tcg/translate.c | 24 ------------------------
27
target/sparc/translate.c | 9 ++++----
25
target/sh4/translate.c | 18 ------------------
28
target/tricore/translate.c | 13 +++---------
26
target/sparc/translate.c | 17 -----------------
29
target/xtensa/translate.c | 12 ++++-------
27
target/tricore/translate.c | 16 ----------------
30
23 files changed, 115 insertions(+), 199 deletions(-)
28
target/xtensa/translate.c | 17 -----------------
29
24 files changed, 416 deletions(-)
31
30
32
diff --git a/include/exec/translator.h b/include/exec/translator.h
31
diff --git a/include/exec/translator.h b/include/exec/translator.h
33
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
34
--- a/include/exec/translator.h
33
--- a/include/exec/translator.h
35
+++ b/include/exec/translator.h
34
+++ b/include/exec/translator.h
36
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContextBase {
35
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContextBase {
37
* @breakpoint_check:
36
* @insn_start:
38
* When called, the breakpoint has already been checked to match the PC,
37
* Emit the tcg_gen_insn_start opcode.
39
* but the target may decide the breakpoint missed the address
38
*
39
- * @breakpoint_check:
40
- * When called, the breakpoint has already been checked to match the PC,
41
- * but the target may decide the breakpoint missed the address
40
- * (e.g., due to conditions encoded in their flags). Return true to
42
- * (e.g., due to conditions encoded in their flags). Return true to
41
- * indicate that the breakpoint did hit, in which case no more breakpoints
43
- * indicate that the breakpoint did hit, in which case no more breakpoints
42
- * are checked. If the breakpoint did hit, emit any code required to
44
- * are checked. If the breakpoint did hit, emit any code required to
43
- * signal the exception, and set db->is_jmp as necessary to terminate
45
- * signal the exception, and set db->is_jmp as necessary to terminate
44
- * the main loop.
46
- * the main loop.
45
+ * (e.g., due to conditions encoded in their flags), in which case
47
- *
46
+ * db->is_jmp may be left as DISAS_NEXT or DISAS_TOO_MANY to indicate
47
+ * that the insn should be translated. Anything other than those two
48
+ * will be taken to indicate an exception has been raised, but in most
49
+ * cases db->is_jmp should be set to DISAS_NORETURN.
50
+ *
51
+ * Return the minimum instruction size that should be applied to the TB.
52
+ * The size of any TB cannot be zero, as that breaks the math used to
53
+ * invalidate TBs.
54
*
55
* @translate_insn:
48
* @translate_insn:
56
* Disassemble one instruction and set db->pc_next for the start
49
* Disassemble one instruction and set db->pc_next for the start
50
* of the following instruction. Set db->is_jmp as necessary to
57
@@ -XXX,XX +XXX,XX @@ typedef struct TranslatorOps {
51
@@ -XXX,XX +XXX,XX @@ typedef struct TranslatorOps {
58
void (*init_disas_context)(DisasContextBase *db, CPUState *cpu);
52
void (*init_disas_context)(DisasContextBase *db, CPUState *cpu);
59
void (*tb_start)(DisasContextBase *db, CPUState *cpu);
53
void (*tb_start)(DisasContextBase *db, CPUState *cpu);
60
void (*insn_start)(DisasContextBase *db, CPUState *cpu);
54
void (*insn_start)(DisasContextBase *db, CPUState *cpu);
61
- bool (*breakpoint_check)(DisasContextBase *db, CPUState *cpu,
55
- bool (*breakpoint_check)(DisasContextBase *db, CPUState *cpu,
62
- const CPUBreakpoint *bp);
56
- const CPUBreakpoint *bp);
63
+ int (*breakpoint_check)(DisasContextBase *db, CPUState *cpu, int flags);
64
void (*translate_insn)(DisasContextBase *db, CPUState *cpu);
57
void (*translate_insn)(DisasContextBase *db, CPUState *cpu);
65
void (*tb_stop)(DisasContextBase *db, CPUState *cpu);
58
void (*tb_stop)(DisasContextBase *db, CPUState *cpu);
66
void (*disas_log)(const DisasContextBase *db, CPUState *cpu);
59
void (*disas_log)(const DisasContextBase *db, CPUState *cpu);
67
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
60
diff --git a/target/arm/helper.h b/target/arm/helper.h
68
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
69
--- a/accel/tcg/translator.c
62
--- a/target/arm/helper.h
70
+++ b/accel/tcg/translator.c
63
+++ b/target/arm/helper.h
71
@@ -XXX,XX +XXX,XX @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest)
64
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_1(yield, void, env)
72
void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
65
DEF_HELPER_1(pre_hvc, void, env)
73
CPUState *cpu, TranslationBlock *tb, int max_insns)
66
DEF_HELPER_2(pre_smc, void, env, i32)
74
{
67
75
- int bp_insn = 0;
68
-DEF_HELPER_1(check_breakpoints, void, env)
76
bool plugin_enabled;
69
-
77
70
DEF_HELPER_3(cpsr_write, void, env, i32, i32)
78
/* Initialize DisasContext */
71
DEF_HELPER_2(cpsr_write_eret, void, env, i32)
79
@@ -XXX,XX +XXX,XX @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
72
DEF_HELPER_1(cpsr_read, i32, env)
80
CPUBreakpoint *bp;
81
QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
82
if (bp->pc == db->pc_next) {
83
- if (ops->breakpoint_check(db, cpu, bp)) {
84
- bp_insn = 1;
85
- break;
86
+ int len = ops->breakpoint_check(db, cpu, bp->flags);
87
+
88
+ /*
89
+ * The breakpoint_check hook may use DISAS_TOO_MANY
90
+ * to indicate that only one more instruction is to
91
+ * be executed. Otherwise it should use DISAS_NORETURN
92
+ * when generating an exception, but may use a
93
+ * DISAS_TARGET_* value for Something Else.
94
+ */
95
+ if (db->is_jmp > DISAS_TOO_MANY) {
96
+ /*
97
+ * The address covered by the breakpoint must be
98
+ * included in [tb->pc, tb->pc + tb->size) in order
99
+ * to for it to be properly cleared. Thus we
100
+ * increment the PC here so that the logic setting
101
+ * tb->size below does the right thing.
102
+ */
103
+ tcg_debug_assert(len > 0);
104
+ db->pc_next += len;
105
+
106
+ /*
107
+ * The breakpoint definitely hit, so decrement the
108
+ * number of instructions completed for icount.
109
+ */
110
+ db->num_insns--;
111
+ goto done;
112
}
113
}
114
}
115
- /* The breakpoint_check hook may use DISAS_TOO_MANY to indicate
116
- that only one more instruction is to be executed. Otherwise
117
- it should use DISAS_NORETURN when generating an exception,
118
- but may use a DISAS_TARGET_* value for Something Else. */
119
- if (db->is_jmp > DISAS_TOO_MANY) {
120
- break;
121
- }
122
}
123
124
/* Disassemble one instruction. The translate_insn hook should
125
@@ -XXX,XX +XXX,XX @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
126
}
127
}
128
129
+ done:
130
/* Emit code to exit the TB, as indicated by db->is_jmp. */
131
ops->tb_stop(db, cpu);
132
- gen_tb_end(db->tb, db->num_insns - bp_insn);
133
+ gen_tb_end(db->tb, db->num_insns);
134
135
if (plugin_enabled) {
136
plugin_gen_tb_end(cpu);
137
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
73
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
138
index XXXXXXX..XXXXXXX 100644
74
index XXXXXXX..XXXXXXX 100644
139
--- a/target/alpha/translate.c
75
--- a/target/alpha/translate.c
140
+++ b/target/alpha/translate.c
76
+++ b/target/alpha/translate.c
141
@@ -XXX,XX +XXX,XX @@ static void alpha_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
77
@@ -XXX,XX +XXX,XX @@ static void alpha_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
142
tcg_gen_insn_start(dcbase->pc_next);
78
tcg_gen_insn_start(dcbase->pc_next);
143
}
79
}
144
80
145
-static bool alpha_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
81
-static bool alpha_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
146
- const CPUBreakpoint *bp)
82
- const CPUBreakpoint *bp)
147
+static int alpha_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
83
-{
148
+ int bp_flags)
84
- DisasContext *ctx = container_of(dcbase, DisasContext, base);
149
{
85
-
150
DisasContext *ctx = container_of(dcbase, DisasContext, base);
86
- ctx->base.is_jmp = gen_excp(ctx, EXCP_DEBUG, 0);
151
152
ctx->base.is_jmp = gen_excp(ctx, EXCP_DEBUG, 0);
153
-
87
-
154
- /* The address covered by the breakpoint must be included in
88
- /* The address covered by the breakpoint must be included in
155
- [tb->pc, tb->pc + tb->size) in order to for it to be
89
- [tb->pc, tb->pc + tb->size) in order to for it to be
156
- properly cleared -- thus we increment the PC here so that
90
- properly cleared -- thus we increment the PC here so that
157
- the logic setting tb->size below does the right thing. */
91
- the logic setting tb->size below does the right thing. */
158
- ctx->base.pc_next += 4;
92
- ctx->base.pc_next += 4;
159
- return true;
93
- return true;
160
+ return 4; /* minimum instruction length */
94
-}
161
}
95
-
162
163
static void alpha_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
96
static void alpha_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
97
{
98
DisasContext *ctx = container_of(dcbase, DisasContext, base);
99
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps alpha_tr_ops = {
100
.init_disas_context = alpha_tr_init_disas_context,
101
.tb_start = alpha_tr_tb_start,
102
.insn_start = alpha_tr_insn_start,
103
- .breakpoint_check = alpha_tr_breakpoint_check,
104
.translate_insn = alpha_tr_translate_insn,
105
.tb_stop = alpha_tr_tb_stop,
106
.disas_log = alpha_tr_disas_log,
107
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
108
index XXXXXXX..XXXXXXX 100644
109
--- a/target/arm/debug_helper.c
110
+++ b/target/arm/debug_helper.c
111
@@ -XXX,XX +XXX,XX @@ bool arm_debug_check_breakpoint(CPUState *cs)
112
return false;
113
}
114
115
-void HELPER(check_breakpoints)(CPUARMState *env)
116
-{
117
- if (arm_debug_check_breakpoint(env_cpu(env))) {
118
- HELPER(exception_internal(env, EXCP_DEBUG));
119
- }
120
-}
121
-
122
bool arm_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp)
123
{
124
/*
164
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
125
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
165
index XXXXXXX..XXXXXXX 100644
126
index XXXXXXX..XXXXXXX 100644
166
--- a/target/arm/translate-a64.c
127
--- a/target/arm/translate-a64.c
167
+++ b/target/arm/translate-a64.c
128
+++ b/target/arm/translate-a64.c
168
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
129
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
169
dc->insn_start = tcg_last_op();
130
dc->insn_start = tcg_last_op();
170
}
131
}
171
132
172
-static bool aarch64_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
133
-static bool aarch64_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
173
- const CPUBreakpoint *bp)
134
- const CPUBreakpoint *bp)
174
+static int aarch64_tr_breakpoint_check(DisasContextBase *dcbase,
135
-{
175
+ CPUState *cpu, int bp_flags)
136
- DisasContext *dc = container_of(dcbase, DisasContext, base);
176
{
137
-
177
DisasContext *dc = container_of(dcbase, DisasContext, base);
178
179
- if (bp->flags & BP_CPU) {
138
- if (bp->flags & BP_CPU) {
180
+ if (bp_flags & BP_CPU) {
139
- gen_a64_set_pc_im(dc->base.pc_next);
181
gen_a64_set_pc_im(dc->base.pc_next);
140
- gen_helper_check_breakpoints(cpu_env);
182
gen_helper_check_breakpoints(cpu_env);
141
- /* End the TB early; it likely won't be executed */
183
/* End the TB early; it likely won't be executed */
142
- dc->base.is_jmp = DISAS_TOO_MANY;
184
dc->base.is_jmp = DISAS_TOO_MANY;
143
- } else {
185
} else {
144
- gen_exception_internal_insn(dc, dc->base.pc_next, EXCP_DEBUG);
186
gen_exception_internal_insn(dc, dc->base.pc_next, EXCP_DEBUG);
187
- /* The address covered by the breakpoint must be
145
- /* The address covered by the breakpoint must be
188
- included in [tb->pc, tb->pc + tb->size) in order
146
- included in [tb->pc, tb->pc + tb->size) in order
189
- to for it to be properly cleared -- thus we
147
- to for it to be properly cleared -- thus we
190
- increment the PC here so that the logic setting
148
- increment the PC here so that the logic setting
191
- tb->size below does the right thing. */
149
- tb->size below does the right thing. */
192
- dc->base.pc_next += 4;
150
- dc->base.pc_next += 4;
193
dc->base.is_jmp = DISAS_NORETURN;
151
- dc->base.is_jmp = DISAS_NORETURN;
194
}
152
- }
195
153
-
196
- return true;
154
- return true;
197
+ return 4; /* minimum instruction length */
155
-}
198
}
156
-
199
200
static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
157
static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
158
{
159
DisasContext *dc = container_of(dcbase, DisasContext, base);
160
@@ -XXX,XX +XXX,XX @@ const TranslatorOps aarch64_translator_ops = {
161
.init_disas_context = aarch64_tr_init_disas_context,
162
.tb_start = aarch64_tr_tb_start,
163
.insn_start = aarch64_tr_insn_start,
164
- .breakpoint_check = aarch64_tr_breakpoint_check,
165
.translate_insn = aarch64_tr_translate_insn,
166
.tb_stop = aarch64_tr_tb_stop,
167
.disas_log = aarch64_tr_disas_log,
201
diff --git a/target/arm/translate.c b/target/arm/translate.c
168
diff --git a/target/arm/translate.c b/target/arm/translate.c
202
index XXXXXXX..XXXXXXX 100644
169
index XXXXXXX..XXXXXXX 100644
203
--- a/target/arm/translate.c
170
--- a/target/arm/translate.c
204
+++ b/target/arm/translate.c
171
+++ b/target/arm/translate.c
205
@@ -XXX,XX +XXX,XX @@ static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
172
@@ -XXX,XX +XXX,XX @@ static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
206
dc->insn_start = tcg_last_op();
173
dc->insn_start = tcg_last_op();
207
}
174
}
208
175
209
-static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
176
-static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
210
- const CPUBreakpoint *bp)
177
- const CPUBreakpoint *bp)
211
+static int arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
178
-{
212
+ int bp_flags)
179
- DisasContext *dc = container_of(dcbase, DisasContext, base);
213
{
180
-
214
DisasContext *dc = container_of(dcbase, DisasContext, base);
215
216
- if (bp->flags & BP_CPU) {
181
- if (bp->flags & BP_CPU) {
217
+ if (bp_flags & BP_CPU) {
182
- gen_set_condexec(dc);
218
gen_set_condexec(dc);
183
- gen_set_pc_im(dc, dc->base.pc_next);
219
gen_set_pc_im(dc, dc->base.pc_next);
184
- gen_helper_check_breakpoints(cpu_env);
220
gen_helper_check_breakpoints(cpu_env);
185
- /* End the TB early; it's likely not going to be executed */
221
@@ -XXX,XX +XXX,XX @@ static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
186
- dc->base.is_jmp = DISAS_TOO_MANY;
222
dc->base.is_jmp = DISAS_TOO_MANY;
187
- } else {
223
} else {
188
- gen_exception_internal_insn(dc, dc->base.pc_next, EXCP_DEBUG);
224
gen_exception_internal_insn(dc, dc->base.pc_next, EXCP_DEBUG);
225
- /* The address covered by the breakpoint must be
189
- /* The address covered by the breakpoint must be
226
- included in [tb->pc, tb->pc + tb->size) in order
190
- included in [tb->pc, tb->pc + tb->size) in order
227
- to for it to be properly cleared -- thus we
191
- to for it to be properly cleared -- thus we
228
- increment the PC here so that the logic setting
192
- increment the PC here so that the logic setting
229
- tb->size below does the right thing. */
193
- tb->size below does the right thing. */
230
- /* TODO: Advance PC by correct instruction length to
194
- /* TODO: Advance PC by correct instruction length to
231
- * avoid disassembler error messages */
195
- * avoid disassembler error messages */
232
- dc->base.pc_next += 2;
196
- dc->base.pc_next += 2;
233
dc->base.is_jmp = DISAS_NORETURN;
197
- dc->base.is_jmp = DISAS_NORETURN;
234
}
198
- }
235
199
-
236
- return true;
200
- return true;
237
+ /*
201
-}
238
+ * TODO: Advance PC by correct instruction length to avoid disassembler
202
-
239
+ * error messages. In the meantime, minimum instruction length.
240
+ */
241
+ return 2;
242
}
243
244
static bool arm_pre_translate_insn(DisasContext *dc)
203
static bool arm_pre_translate_insn(DisasContext *dc)
204
{
205
#ifdef CONFIG_USER_ONLY
206
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps arm_translator_ops = {
207
.init_disas_context = arm_tr_init_disas_context,
208
.tb_start = arm_tr_tb_start,
209
.insn_start = arm_tr_insn_start,
210
- .breakpoint_check = arm_tr_breakpoint_check,
211
.translate_insn = arm_tr_translate_insn,
212
.tb_stop = arm_tr_tb_stop,
213
.disas_log = arm_tr_disas_log,
214
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps thumb_translator_ops = {
215
.init_disas_context = arm_tr_init_disas_context,
216
.tb_start = arm_tr_tb_start,
217
.insn_start = arm_tr_insn_start,
218
- .breakpoint_check = arm_tr_breakpoint_check,
219
.translate_insn = thumb_tr_translate_insn,
220
.tb_stop = arm_tr_tb_stop,
221
.disas_log = arm_tr_disas_log,
245
diff --git a/target/avr/translate.c b/target/avr/translate.c
222
diff --git a/target/avr/translate.c b/target/avr/translate.c
246
index XXXXXXX..XXXXXXX 100644
223
index XXXXXXX..XXXXXXX 100644
247
--- a/target/avr/translate.c
224
--- a/target/avr/translate.c
248
+++ b/target/avr/translate.c
225
+++ b/target/avr/translate.c
249
@@ -XXX,XX +XXX,XX @@ static void avr_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
226
@@ -XXX,XX +XXX,XX @@ static void avr_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
250
tcg_gen_insn_start(ctx->npc);
227
tcg_gen_insn_start(ctx->npc);
251
}
228
}
252
229
253
-static bool avr_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
230
-static bool avr_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
254
- const CPUBreakpoint *bp)
231
- const CPUBreakpoint *bp)
255
+static int avr_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
232
-{
256
+ int bp_flags)
233
- DisasContext *ctx = container_of(dcbase, DisasContext, base);
234
-
235
- gen_breakpoint(ctx);
236
- return true;
237
-}
238
-
239
static void avr_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
257
{
240
{
258
DisasContext *ctx = container_of(dcbase, DisasContext, base);
241
DisasContext *ctx = container_of(dcbase, DisasContext, base);
259
242
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps avr_tr_ops = {
260
gen_breakpoint(ctx);
243
.init_disas_context = avr_tr_init_disas_context,
261
- return true;
244
.tb_start = avr_tr_tb_start,
262
+ return 2; /* minimum instruction length */
245
.insn_start = avr_tr_insn_start,
263
}
246
- .breakpoint_check = avr_tr_breakpoint_check,
264
247
.translate_insn = avr_tr_translate_insn,
265
static void avr_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
248
.tb_stop = avr_tr_tb_stop,
249
.disas_log = avr_tr_disas_log,
266
diff --git a/target/cris/translate.c b/target/cris/translate.c
250
diff --git a/target/cris/translate.c b/target/cris/translate.c
267
index XXXXXXX..XXXXXXX 100644
251
index XXXXXXX..XXXXXXX 100644
268
--- a/target/cris/translate.c
252
--- a/target/cris/translate.c
269
+++ b/target/cris/translate.c
253
+++ b/target/cris/translate.c
270
@@ -XXX,XX +XXX,XX @@ static void cris_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
254
@@ -XXX,XX +XXX,XX @@ static void cris_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
271
tcg_gen_insn_start(dc->delayed_branch == 1 ? dc->ppc | 1 : dc->pc);
255
tcg_gen_insn_start(dc->delayed_branch == 1 ? dc->ppc | 1 : dc->pc);
272
}
256
}
273
257
274
-static bool cris_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
258
-static bool cris_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
275
- const CPUBreakpoint *bp)
259
- const CPUBreakpoint *bp)
276
+static int cris_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
260
-{
277
+ int bp_flags)
261
- DisasContext *dc = container_of(dcbase, DisasContext, base);
278
{
262
-
279
DisasContext *dc = container_of(dcbase, DisasContext, base);
263
- cris_evaluate_flags(dc);
280
264
- tcg_gen_movi_tl(env_pc, dc->pc);
281
@@ -XXX,XX +XXX,XX @@ static bool cris_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
265
- t_gen_raise_exception(EXCP_DEBUG);
282
tcg_gen_movi_tl(env_pc, dc->pc);
266
- dc->base.is_jmp = DISAS_NORETURN;
283
t_gen_raise_exception(EXCP_DEBUG);
284
dc->base.is_jmp = DISAS_NORETURN;
285
- /*
267
- /*
286
- * The address covered by the breakpoint must be included in
268
- * The address covered by the breakpoint must be included in
287
- * [tb->pc, tb->pc + tb->size) in order to for it to be
269
- * [tb->pc, tb->pc + tb->size) in order to for it to be
288
- * properly cleared -- thus we increment the PC here so that
270
- * properly cleared -- thus we increment the PC here so that
289
- * the logic setting tb->size below does the right thing.
271
- * the logic setting tb->size below does the right thing.
290
- */
272
- */
291
- dc->pc += 2;
273
- dc->pc += 2;
292
- return true;
274
- return true;
293
+
275
-}
294
+ return 2; /* minimum instruction length */
276
-
295
}
296
297
static void cris_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
277
static void cris_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
278
{
279
DisasContext *dc = container_of(dcbase, DisasContext, base);
280
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps cris_tr_ops = {
281
.init_disas_context = cris_tr_init_disas_context,
282
.tb_start = cris_tr_tb_start,
283
.insn_start = cris_tr_insn_start,
284
- .breakpoint_check = cris_tr_breakpoint_check,
285
.translate_insn = cris_tr_translate_insn,
286
.tb_stop = cris_tr_tb_stop,
287
.disas_log = cris_tr_disas_log,
298
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
288
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
299
index XXXXXXX..XXXXXXX 100644
289
index XXXXXXX..XXXXXXX 100644
300
--- a/target/hexagon/translate.c
290
--- a/target/hexagon/translate.c
301
+++ b/target/hexagon/translate.c
291
+++ b/target/hexagon/translate.c
302
@@ -XXX,XX +XXX,XX @@ static void hexagon_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
292
@@ -XXX,XX +XXX,XX @@ static void hexagon_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
303
tcg_gen_insn_start(ctx->base.pc_next);
293
tcg_gen_insn_start(ctx->base.pc_next);
304
}
294
}
305
295
306
-static bool hexagon_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
296
-static bool hexagon_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
307
- const CPUBreakpoint *bp)
297
- const CPUBreakpoint *bp)
308
+static int hexagon_tr_breakpoint_check(DisasContextBase *dcbase,
298
-{
309
+ CPUState *cpu, int bp_flags)
299
- DisasContext *ctx = container_of(dcbase, DisasContext, base);
310
{
300
-
311
DisasContext *ctx = container_of(dcbase, DisasContext, base);
301
- gen_exception_end_tb(ctx, EXCP_DEBUG);
312
313
gen_exception_end_tb(ctx, EXCP_DEBUG);
314
- /*
302
- /*
315
- * The address covered by the breakpoint must be included in
303
- * The address covered by the breakpoint must be included in
316
- * [tb->pc, tb->pc + tb->size) in order to for it to be
304
- * [tb->pc, tb->pc + tb->size) in order to for it to be
317
- * properly cleared -- thus we increment the PC here so that
305
- * properly cleared -- thus we increment the PC here so that
318
- * the logic setting tb->size below does the right thing.
306
- * the logic setting tb->size below does the right thing.
319
- */
307
- */
320
- ctx->base.pc_next += 4;
308
- ctx->base.pc_next += 4;
321
- return true;
309
- return true;
322
+ return 4; /* minimum packet length */
310
-}
323
}
311
-
324
325
static bool pkt_crosses_page(CPUHexagonState *env, DisasContext *ctx)
312
static bool pkt_crosses_page(CPUHexagonState *env, DisasContext *ctx)
313
{
314
target_ulong page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
315
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps hexagon_tr_ops = {
316
.init_disas_context = hexagon_tr_init_disas_context,
317
.tb_start = hexagon_tr_tb_start,
318
.insn_start = hexagon_tr_insn_start,
319
- .breakpoint_check = hexagon_tr_breakpoint_check,
320
.translate_insn = hexagon_tr_translate_packet,
321
.tb_stop = hexagon_tr_tb_stop,
322
.disas_log = hexagon_tr_disas_log,
326
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
323
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
327
index XXXXXXX..XXXXXXX 100644
324
index XXXXXXX..XXXXXXX 100644
328
--- a/target/hppa/translate.c
325
--- a/target/hppa/translate.c
329
+++ b/target/hppa/translate.c
326
+++ b/target/hppa/translate.c
330
@@ -XXX,XX +XXX,XX @@ static void hppa_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
327
@@ -XXX,XX +XXX,XX @@ static void hppa_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
331
tcg_gen_insn_start(ctx->iaoq_f, ctx->iaoq_b);
328
tcg_gen_insn_start(ctx->iaoq_f, ctx->iaoq_b);
332
}
329
}
333
330
334
-static bool hppa_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
331
-static bool hppa_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
335
- const CPUBreakpoint *bp)
332
- const CPUBreakpoint *bp)
336
+static int hppa_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
333
-{
337
+ int bp_flags)
334
- DisasContext *ctx = container_of(dcbase, DisasContext, base);
335
-
336
- gen_excp(ctx, EXCP_DEBUG);
337
- ctx->base.pc_next += 4;
338
- return true;
339
-}
340
-
341
static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
338
{
342
{
339
DisasContext *ctx = container_of(dcbase, DisasContext, base);
343
DisasContext *ctx = container_of(dcbase, DisasContext, base);
340
344
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps hppa_tr_ops = {
341
gen_excp(ctx, EXCP_DEBUG);
345
.init_disas_context = hppa_tr_init_disas_context,
342
- ctx->base.pc_next += 4;
346
.tb_start = hppa_tr_tb_start,
343
- return true;
347
.insn_start = hppa_tr_insn_start,
344
+ return 4; /* minimum instruction length */
348
- .breakpoint_check = hppa_tr_breakpoint_check,
345
}
349
.translate_insn = hppa_tr_translate_insn,
346
350
.tb_stop = hppa_tr_tb_stop,
347
static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
351
.disas_log = hppa_tr_disas_log,
348
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
352
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
349
index XXXXXXX..XXXXXXX 100644
353
index XXXXXXX..XXXXXXX 100644
350
--- a/target/i386/tcg/translate.c
354
--- a/target/i386/tcg/translate.c
351
+++ b/target/i386/tcg/translate.c
355
+++ b/target/i386/tcg/translate.c
356
@@ -XXX,XX +XXX,XX @@ static void gen_interrupt(DisasContext *s, int intno,
357
s->base.is_jmp = DISAS_NORETURN;
358
}
359
360
-static void gen_debug(DisasContext *s)
361
-{
362
- gen_update_cc_op(s);
363
- gen_jmp_im(s, s->base.pc_next - s->cs_base);
364
- gen_helper_debug(cpu_env);
365
- s->base.is_jmp = DISAS_NORETURN;
366
-}
367
-
368
static void gen_set_hflag(DisasContext *s, uint32_t mask)
369
{
370
if ((s->flags & mask) == 0) {
352
@@ -XXX,XX +XXX,XX @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
371
@@ -XXX,XX +XXX,XX @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
353
tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
372
tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
354
}
373
}
355
374
356
-static bool i386_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
375
-static bool i386_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
357
- const CPUBreakpoint *bp)
376
- const CPUBreakpoint *bp)
358
+static int i386_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
377
-{
359
+ int bp_flags)
378
- DisasContext *dc = container_of(dcbase, DisasContext, base);
360
{
379
- /* If RF is set, suppress an internally generated breakpoint. */
361
DisasContext *dc = container_of(dcbase, DisasContext, base);
380
- int flags = dc->base.tb->flags & HF_RF_MASK ? BP_GDB : BP_ANY;
362
/* If RF is set, suppress an internally generated breakpoint. */
363
int flags = dc->base.tb->flags & HF_RF_MASK ? BP_GDB : BP_ANY;
364
- if (bp->flags & flags) {
381
- if (bp->flags & flags) {
365
+ if (bp_flags & flags) {
382
- gen_debug(dc);
366
gen_debug(dc);
367
- /* The address covered by the breakpoint must be included in
383
- /* The address covered by the breakpoint must be included in
368
- [tb->pc, tb->pc + tb->size) in order to for it to be
384
- [tb->pc, tb->pc + tb->size) in order to for it to be
369
- properly cleared -- thus we increment the PC here so that
385
- properly cleared -- thus we increment the PC here so that
370
- the generic logic setting tb->size later does the right thing. */
386
- the generic logic setting tb->size later does the right thing. */
371
- dc->base.pc_next += 1;
387
- dc->base.pc_next += 1;
372
- return true;
388
- return true;
373
- } else {
389
- } else {
374
- return false;
390
- return false;
375
}
391
- }
376
+ return 1; /* minimum instruction length */
392
-}
377
}
393
-
378
379
static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
394
static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
395
{
396
DisasContext *dc = container_of(dcbase, DisasContext, base);
397
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps i386_tr_ops = {
398
.init_disas_context = i386_tr_init_disas_context,
399
.tb_start = i386_tr_tb_start,
400
.insn_start = i386_tr_insn_start,
401
- .breakpoint_check = i386_tr_breakpoint_check,
402
.translate_insn = i386_tr_translate_insn,
403
.tb_stop = i386_tr_tb_stop,
404
.disas_log = i386_tr_disas_log,
380
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
405
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
381
index XXXXXXX..XXXXXXX 100644
406
index XXXXXXX..XXXXXXX 100644
382
--- a/target/m68k/translate.c
407
--- a/target/m68k/translate.c
383
+++ b/target/m68k/translate.c
408
+++ b/target/m68k/translate.c
384
@@ -XXX,XX +XXX,XX @@ static void m68k_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
409
@@ -XXX,XX +XXX,XX @@ static void m68k_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
385
tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
410
tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
386
}
411
}
387
412
388
-static bool m68k_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
413
-static bool m68k_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
389
- const CPUBreakpoint *bp)
414
- const CPUBreakpoint *bp)
390
+static int m68k_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
415
-{
391
+ int bp_flags)
416
- DisasContext *dc = container_of(dcbase, DisasContext, base);
392
{
417
-
393
DisasContext *dc = container_of(dcbase, DisasContext, base);
418
- gen_exception(dc, dc->base.pc_next, EXCP_DEBUG);
394
395
gen_exception(dc, dc->base.pc_next, EXCP_DEBUG);
396
- /*
419
- /*
397
- * The address covered by the breakpoint must be included in
420
- * The address covered by the breakpoint must be included in
398
- * [tb->pc, tb->pc + tb->size) in order to for it to be
421
- * [tb->pc, tb->pc + tb->size) in order to for it to be
399
- * properly cleared -- thus we increment the PC here so that
422
- * properly cleared -- thus we increment the PC here so that
400
- * the logic setting tb->size below does the right thing.
423
- * the logic setting tb->size below does the right thing.
401
- */
424
- */
402
- dc->base.pc_next += 2;
425
- dc->base.pc_next += 2;
403
-
426
-
404
- return true;
427
- return true;
405
+ return 2; /* minimum instruction length */
428
-}
406
}
429
-
407
408
static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
430
static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
431
{
432
DisasContext *dc = container_of(dcbase, DisasContext, base);
433
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps m68k_tr_ops = {
434
.init_disas_context = m68k_tr_init_disas_context,
435
.tb_start = m68k_tr_tb_start,
436
.insn_start = m68k_tr_insn_start,
437
- .breakpoint_check = m68k_tr_breakpoint_check,
438
.translate_insn = m68k_tr_translate_insn,
439
.tb_stop = m68k_tr_tb_stop,
440
.disas_log = m68k_tr_disas_log,
409
diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
441
diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
410
index XXXXXXX..XXXXXXX 100644
442
index XXXXXXX..XXXXXXX 100644
411
--- a/target/microblaze/translate.c
443
--- a/target/microblaze/translate.c
412
+++ b/target/microblaze/translate.c
444
+++ b/target/microblaze/translate.c
413
@@ -XXX,XX +XXX,XX @@ static void mb_tr_insn_start(DisasContextBase *dcb, CPUState *cs)
445
@@ -XXX,XX +XXX,XX @@ static void mb_tr_insn_start(DisasContextBase *dcb, CPUState *cs)
414
dc->insn_start = tcg_last_op();
446
dc->insn_start = tcg_last_op();
415
}
447
}
416
448
417
-static bool mb_tr_breakpoint_check(DisasContextBase *dcb, CPUState *cs,
449
-static bool mb_tr_breakpoint_check(DisasContextBase *dcb, CPUState *cs,
418
- const CPUBreakpoint *bp)
450
- const CPUBreakpoint *bp)
419
+static int mb_tr_breakpoint_check(DisasContextBase *dcb, CPUState *cs,
451
-{
420
+ int bp_flags)
452
- DisasContext *dc = container_of(dcb, DisasContext, base);
421
{
453
-
422
DisasContext *dc = container_of(dcb, DisasContext, base);
454
- gen_raise_exception_sync(dc, EXCP_DEBUG);
423
424
gen_raise_exception_sync(dc, EXCP_DEBUG);
425
-
455
-
426
- /*
456
- /*
427
- * The address covered by the breakpoint must be included in
457
- * The address covered by the breakpoint must be included in
428
- * [tb->pc, tb->pc + tb->size) in order to for it to be
458
- * [tb->pc, tb->pc + tb->size) in order to for it to be
429
- * properly cleared -- thus we increment the PC here so that
459
- * properly cleared -- thus we increment the PC here so that
430
- * the logic setting tb->size below does the right thing.
460
- * the logic setting tb->size below does the right thing.
431
- */
461
- */
432
- dc->base.pc_next += 4;
462
- dc->base.pc_next += 4;
433
- return true;
463
- return true;
434
+ return 4; /* minimum instruction length */
464
-}
435
}
465
-
436
437
static void mb_tr_translate_insn(DisasContextBase *dcb, CPUState *cs)
466
static void mb_tr_translate_insn(DisasContextBase *dcb, CPUState *cs)
467
{
468
DisasContext *dc = container_of(dcb, DisasContext, base);
469
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps mb_tr_ops = {
470
.init_disas_context = mb_tr_init_disas_context,
471
.tb_start = mb_tr_tb_start,
472
.insn_start = mb_tr_insn_start,
473
- .breakpoint_check = mb_tr_breakpoint_check,
474
.translate_insn = mb_tr_translate_insn,
475
.tb_stop = mb_tr_tb_stop,
476
.disas_log = mb_tr_disas_log,
438
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
477
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
439
index XXXXXXX..XXXXXXX 100644
478
index XXXXXXX..XXXXXXX 100644
440
--- a/target/mips/tcg/translate.c
479
--- a/target/mips/tcg/translate.c
441
+++ b/target/mips/tcg/translate.c
480
+++ b/target/mips/tcg/translate.c
442
@@ -XXX,XX +XXX,XX @@ static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
481
@@ -XXX,XX +XXX,XX @@ static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
443
ctx->btarget);
482
ctx->btarget);
444
}
483
}
445
484
446
-static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
485
-static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
447
- const CPUBreakpoint *bp)
486
- const CPUBreakpoint *bp)
448
+static int mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
487
-{
449
+ int bp_flags)
488
- DisasContext *ctx = container_of(dcbase, DisasContext, base);
450
{
489
-
451
DisasContext *ctx = container_of(dcbase, DisasContext, base);
490
- save_cpu_state(ctx, 1);
452
491
- ctx->base.is_jmp = DISAS_NORETURN;
453
save_cpu_state(ctx, 1);
492
- gen_helper_raise_exception_debug(cpu_env);
454
ctx->base.is_jmp = DISAS_NORETURN;
455
gen_helper_raise_exception_debug(cpu_env);
456
- /*
493
- /*
457
- * The address covered by the breakpoint must be included in
494
- * The address covered by the breakpoint must be included in
458
- * [tb->pc, tb->pc + tb->size) in order to for it to be
495
- * [tb->pc, tb->pc + tb->size) in order to for it to be
459
- * properly cleared -- thus we increment the PC here so that
496
- * properly cleared -- thus we increment the PC here so that
460
- * the logic setting tb->size below does the right thing.
497
- * the logic setting tb->size below does the right thing.
461
- */
498
- */
462
- ctx->base.pc_next += 4;
499
- ctx->base.pc_next += 4;
463
- return true;
500
- return true;
464
+
501
-}
465
+ return 2; /* minimum instruction length */
502
-
466
}
467
468
static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
503
static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
504
{
505
CPUMIPSState *env = cs->env_ptr;
506
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps mips_tr_ops = {
507
.init_disas_context = mips_tr_init_disas_context,
508
.tb_start = mips_tr_tb_start,
509
.insn_start = mips_tr_insn_start,
510
- .breakpoint_check = mips_tr_breakpoint_check,
511
.translate_insn = mips_tr_translate_insn,
512
.tb_stop = mips_tr_tb_stop,
513
.disas_log = mips_tr_disas_log,
469
diff --git a/target/nios2/translate.c b/target/nios2/translate.c
514
diff --git a/target/nios2/translate.c b/target/nios2/translate.c
470
index XXXXXXX..XXXXXXX 100644
515
index XXXXXXX..XXXXXXX 100644
471
--- a/target/nios2/translate.c
516
--- a/target/nios2/translate.c
472
+++ b/target/nios2/translate.c
517
+++ b/target/nios2/translate.c
518
@@ -XXX,XX +XXX,XX @@ static const char * const regnames[] = {
519
520
#include "exec/gen-icount.h"
521
522
-static void gen_exception(DisasContext *dc, uint32_t excp)
523
-{
524
- TCGv_i32 tmp = tcg_const_i32(excp);
525
-
526
- tcg_gen_movi_tl(cpu_R[R_PC], dc->pc);
527
- gen_helper_raise_exception(cpu_env, tmp);
528
- tcg_temp_free_i32(tmp);
529
- dc->base.is_jmp = DISAS_NORETURN;
530
-}
531
-
532
/* generate intermediate code for basic block 'tb'. */
533
static void nios2_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
534
{
473
@@ -XXX,XX +XXX,XX @@ static void nios2_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
535
@@ -XXX,XX +XXX,XX @@ static void nios2_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
474
tcg_gen_insn_start(dcbase->pc_next);
536
tcg_gen_insn_start(dcbase->pc_next);
475
}
537
}
476
538
477
-static bool nios2_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
539
-static bool nios2_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
478
- const CPUBreakpoint *bp)
540
- const CPUBreakpoint *bp)
479
+static int nios2_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
541
-{
480
+ int bp_flags)
542
- DisasContext *dc = container_of(dcbase, DisasContext, base);
481
{
543
-
482
DisasContext *dc = container_of(dcbase, DisasContext, base);
544
- gen_exception(dc, EXCP_DEBUG);
483
484
gen_exception(dc, EXCP_DEBUG);
485
- /*
545
- /*
486
- * The address covered by the breakpoint must be included in
546
- * The address covered by the breakpoint must be included in
487
- * [tb->pc, tb->pc + tb->size) in order to for it to be
547
- * [tb->pc, tb->pc + tb->size) in order to for it to be
488
- * properly cleared -- thus we increment the PC here so that
548
- * properly cleared -- thus we increment the PC here so that
489
- * the logic setting tb->size below does the right thing.
549
- * the logic setting tb->size below does the right thing.
490
- */
550
- */
491
- dc->base.pc_next += 4;
551
- dc->base.pc_next += 4;
492
- return true;
552
- return true;
493
+ return 4; /* minimum instruction length */
553
-}
494
}
554
-
495
496
static void nios2_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
555
static void nios2_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
556
{
557
DisasContext *dc = container_of(dcbase, DisasContext, base);
558
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps nios2_tr_ops = {
559
.init_disas_context = nios2_tr_init_disas_context,
560
.tb_start = nios2_tr_tb_start,
561
.insn_start = nios2_tr_insn_start,
562
- .breakpoint_check = nios2_tr_breakpoint_check,
563
.translate_insn = nios2_tr_translate_insn,
564
.tb_stop = nios2_tr_tb_stop,
565
.disas_log = nios2_tr_disas_log,
497
diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
566
diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
498
index XXXXXXX..XXXXXXX 100644
567
index XXXXXXX..XXXXXXX 100644
499
--- a/target/openrisc/translate.c
568
--- a/target/openrisc/translate.c
500
+++ b/target/openrisc/translate.c
569
+++ b/target/openrisc/translate.c
501
@@ -XXX,XX +XXX,XX @@ static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
570
@@ -XXX,XX +XXX,XX @@ static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
502
| (dc->base.num_insns > 1 ? 2 : 0));
571
| (dc->base.num_insns > 1 ? 2 : 0));
503
}
572
}
504
573
505
-static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
574
-static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
506
- const CPUBreakpoint *bp)
575
- const CPUBreakpoint *bp)
507
+static int openrisc_tr_breakpoint_check(DisasContextBase *dcbase,
576
-{
508
+ CPUState *cs, int bp_flags)
577
- DisasContext *dc = container_of(dcbase, DisasContext, base);
509
{
578
-
510
DisasContext *dc = container_of(dcbase, DisasContext, base);
579
- tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
511
580
- gen_exception(dc, EXCP_DEBUG);
512
tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
581
- dc->base.is_jmp = DISAS_NORETURN;
513
gen_exception(dc, EXCP_DEBUG);
514
dc->base.is_jmp = DISAS_NORETURN;
515
- /* The address covered by the breakpoint must be included in
582
- /* The address covered by the breakpoint must be included in
516
- [tb->pc, tb->pc + tb->size) in order to for it to be
583
- [tb->pc, tb->pc + tb->size) in order to for it to be
517
- properly cleared -- thus we increment the PC here so that
584
- properly cleared -- thus we increment the PC here so that
518
- the logic setting tb->size below does the right thing. */
585
- the logic setting tb->size below does the right thing. */
519
- dc->base.pc_next += 4;
586
- dc->base.pc_next += 4;
520
- return true;
587
- return true;
521
+ return 4; /* minimum instruction length */
588
-}
522
}
589
-
523
524
static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
590
static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
591
{
592
DisasContext *dc = container_of(dcbase, DisasContext, base);
593
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps openrisc_tr_ops = {
594
.init_disas_context = openrisc_tr_init_disas_context,
595
.tb_start = openrisc_tr_tb_start,
596
.insn_start = openrisc_tr_insn_start,
597
- .breakpoint_check = openrisc_tr_breakpoint_check,
598
.translate_insn = openrisc_tr_translate_insn,
599
.tb_stop = openrisc_tr_tb_stop,
600
.disas_log = openrisc_tr_disas_log,
525
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
601
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
526
index XXXXXXX..XXXXXXX 100644
602
index XXXXXXX..XXXXXXX 100644
527
--- a/target/ppc/translate.c
603
--- a/target/ppc/translate.c
528
+++ b/target/ppc/translate.c
604
+++ b/target/ppc/translate.c
529
@@ -XXX,XX +XXX,XX @@ static void ppc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
605
@@ -XXX,XX +XXX,XX @@ static void ppc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
530
tcg_gen_insn_start(dcbase->pc_next);
606
tcg_gen_insn_start(dcbase->pc_next);
531
}
607
}
532
608
533
-static bool ppc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
609
-static bool ppc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
534
- const CPUBreakpoint *bp)
610
- const CPUBreakpoint *bp)
535
+static int ppc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
611
-{
536
+ int bp_flags)
612
- DisasContext *ctx = container_of(dcbase, DisasContext, base);
537
{
613
-
538
DisasContext *ctx = container_of(dcbase, DisasContext, base);
614
- gen_update_nip(ctx, ctx->base.pc_next);
539
615
- gen_debug_exception(ctx);
540
gen_update_nip(ctx, ctx->base.pc_next);
541
gen_debug_exception(ctx);
542
- /*
616
- /*
543
- * The address covered by the breakpoint must be included in
617
- * The address covered by the breakpoint must be included in
544
- * [tb->pc, tb->pc + tb->size) in order to for it to be properly
618
- * [tb->pc, tb->pc + tb->size) in order to for it to be properly
545
- * cleared -- thus we increment the PC here so that the logic
619
- * cleared -- thus we increment the PC here so that the logic
546
- * setting tb->size below does the right thing.
620
- * setting tb->size below does the right thing.
547
- */
621
- */
548
- ctx->base.pc_next += 4;
622
- ctx->base.pc_next += 4;
549
- return true;
623
- return true;
550
+ return 4; /* minimum instruction length */
624
-}
551
}
625
-
552
553
static bool is_prefix_insn(DisasContext *ctx, uint32_t insn)
626
static bool is_prefix_insn(DisasContext *ctx, uint32_t insn)
627
{
628
REQUIRE_INSNS_FLAGS2(ctx, ISA310);
629
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps ppc_tr_ops = {
630
.init_disas_context = ppc_tr_init_disas_context,
631
.tb_start = ppc_tr_tb_start,
632
.insn_start = ppc_tr_insn_start,
633
- .breakpoint_check = ppc_tr_breakpoint_check,
634
.translate_insn = ppc_tr_translate_insn,
635
.tb_stop = ppc_tr_tb_stop,
636
.disas_log = ppc_tr_disas_log,
554
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
637
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
555
index XXXXXXX..XXXXXXX 100644
638
index XXXXXXX..XXXXXXX 100644
556
--- a/target/riscv/translate.c
639
--- a/target/riscv/translate.c
557
+++ b/target/riscv/translate.c
640
+++ b/target/riscv/translate.c
558
@@ -XXX,XX +XXX,XX @@ static void riscv_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
641
@@ -XXX,XX +XXX,XX @@ static void riscv_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
559
tcg_gen_insn_start(ctx->base.pc_next);
642
tcg_gen_insn_start(ctx->base.pc_next);
560
}
643
}
561
644
562
-static bool riscv_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
645
-static bool riscv_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
563
- const CPUBreakpoint *bp)
646
- const CPUBreakpoint *bp)
564
+static int riscv_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
647
-{
565
+ int bp_flags)
648
- DisasContext *ctx = container_of(dcbase, DisasContext, base);
566
{
649
-
567
DisasContext *ctx = container_of(dcbase, DisasContext, base);
650
- tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
568
651
- ctx->base.is_jmp = DISAS_NORETURN;
569
tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
652
- gen_exception_debug();
570
ctx->base.is_jmp = DISAS_NORETURN;
571
gen_exception_debug();
572
- /* The address covered by the breakpoint must be included in
653
- /* The address covered by the breakpoint must be included in
573
- [tb->pc, tb->pc + tb->size) in order to for it to be
654
- [tb->pc, tb->pc + tb->size) in order to for it to be
574
- properly cleared -- thus we increment the PC here so that
655
- properly cleared -- thus we increment the PC here so that
575
- the logic setting tb->size below does the right thing. */
656
- the logic setting tb->size below does the right thing. */
576
- ctx->base.pc_next += 4;
657
- ctx->base.pc_next += 4;
577
- return true;
658
- return true;
578
+ return 2; /* minimum instruction length */
659
-}
579
}
660
-
580
581
static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
661
static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
662
{
663
DisasContext *ctx = container_of(dcbase, DisasContext, base);
664
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps riscv_tr_ops = {
665
.init_disas_context = riscv_tr_init_disas_context,
666
.tb_start = riscv_tr_tb_start,
667
.insn_start = riscv_tr_insn_start,
668
- .breakpoint_check = riscv_tr_breakpoint_check,
669
.translate_insn = riscv_tr_translate_insn,
670
.tb_stop = riscv_tr_tb_stop,
671
.disas_log = riscv_tr_disas_log,
582
diff --git a/target/rx/translate.c b/target/rx/translate.c
672
diff --git a/target/rx/translate.c b/target/rx/translate.c
583
index XXXXXXX..XXXXXXX 100644
673
index XXXXXXX..XXXXXXX 100644
584
--- a/target/rx/translate.c
674
--- a/target/rx/translate.c
585
+++ b/target/rx/translate.c
675
+++ b/target/rx/translate.c
586
@@ -XXX,XX +XXX,XX @@ static void rx_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
676
@@ -XXX,XX +XXX,XX @@ static void rx_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
587
tcg_gen_insn_start(ctx->base.pc_next);
677
tcg_gen_insn_start(ctx->base.pc_next);
588
}
678
}
589
679
590
-static bool rx_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
680
-static bool rx_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
591
- const CPUBreakpoint *bp)
681
- const CPUBreakpoint *bp)
592
+static int rx_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
682
-{
593
+ int bp_flags)
683
- DisasContext *ctx = container_of(dcbase, DisasContext, base);
684
-
685
- /* We have hit a breakpoint - make sure PC is up-to-date */
686
- tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next);
687
- gen_helper_debug(cpu_env);
688
- ctx->base.is_jmp = DISAS_NORETURN;
689
- ctx->base.pc_next += 1;
690
- return true;
691
-}
692
-
693
static void rx_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
594
{
694
{
595
DisasContext *ctx = container_of(dcbase, DisasContext, base);
695
DisasContext *ctx = container_of(dcbase, DisasContext, base);
596
696
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps rx_tr_ops = {
597
@@ -XXX,XX +XXX,XX @@ static bool rx_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
697
.init_disas_context = rx_tr_init_disas_context,
598
tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next);
698
.tb_start = rx_tr_tb_start,
599
gen_helper_debug(cpu_env);
699
.insn_start = rx_tr_insn_start,
600
ctx->base.is_jmp = DISAS_NORETURN;
700
- .breakpoint_check = rx_tr_breakpoint_check,
601
- ctx->base.pc_next += 1;
701
.translate_insn = rx_tr_translate_insn,
602
- return true;
702
.tb_stop = rx_tr_tb_stop,
603
+
703
.disas_log = rx_tr_disas_log,
604
+ return 1; /* minimum instruction length */
704
diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c
605
}
705
index XXXXXXX..XXXXXXX 100644
606
706
--- a/target/s390x/tcg/translate.c
607
static void rx_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
707
+++ b/target/s390x/tcg/translate.c
608
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
609
index XXXXXXX..XXXXXXX 100644
610
--- a/target/s390x/translate.c
611
+++ b/target/s390x/translate.c
612
@@ -XXX,XX +XXX,XX @@ static void s390x_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
708
@@ -XXX,XX +XXX,XX @@ static void s390x_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
613
{
709
{
614
}
710
}
615
711
616
-static bool s390x_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
712
-static bool s390x_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
617
- const CPUBreakpoint *bp)
713
- const CPUBreakpoint *bp)
618
+static int s390x_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
714
-{
619
+ int bp_flags)
715
- DisasContext *dc = container_of(dcbase, DisasContext, base);
620
{
716
-
621
DisasContext *dc = container_of(dcbase, DisasContext, base);
717
- /*
622
718
- * Emit an insn_start to accompany the breakpoint exception.
623
@@ -XXX,XX +XXX,XX @@ static bool s390x_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
719
- * The ILEN value is a dummy, since this does not result in
624
720
- * an s390x exception, but an internal qemu exception which
625
dc->base.is_jmp = DISAS_PC_STALE;
721
- * brings us back to interact with the gdbstub.
626
dc->do_debug = true;
722
- */
723
- tcg_gen_insn_start(dc->base.pc_next, dc->cc_op, 2);
724
-
725
- dc->base.is_jmp = DISAS_PC_STALE;
726
- dc->do_debug = true;
627
- /* The address covered by the breakpoint must be included in
727
- /* The address covered by the breakpoint must be included in
628
- [tb->pc, tb->pc + tb->size) in order to for it to be
728
- [tb->pc, tb->pc + tb->size) in order to for it to be
629
- properly cleared -- thus we increment the PC here so that
729
- properly cleared -- thus we increment the PC here so that
630
- the logic setting tb->size does the right thing. */
730
- the logic setting tb->size does the right thing. */
631
- dc->base.pc_next += 2;
731
- dc->base.pc_next += 2;
632
- return true;
732
- return true;
633
+
733
-}
634
+ return 2; /* minimum instruction length */
734
-
635
}
636
637
static void s390x_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
735
static void s390x_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
736
{
737
CPUS390XState *env = cs->env_ptr;
738
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps s390x_tr_ops = {
739
.init_disas_context = s390x_tr_init_disas_context,
740
.tb_start = s390x_tr_tb_start,
741
.insn_start = s390x_tr_insn_start,
742
- .breakpoint_check = s390x_tr_breakpoint_check,
743
.translate_insn = s390x_tr_translate_insn,
744
.tb_stop = s390x_tr_tb_stop,
745
.disas_log = s390x_tr_disas_log,
638
diff --git a/target/sh4/translate.c b/target/sh4/translate.c
746
diff --git a/target/sh4/translate.c b/target/sh4/translate.c
639
index XXXXXXX..XXXXXXX 100644
747
index XXXXXXX..XXXXXXX 100644
640
--- a/target/sh4/translate.c
748
--- a/target/sh4/translate.c
641
+++ b/target/sh4/translate.c
749
+++ b/target/sh4/translate.c
642
@@ -XXX,XX +XXX,XX @@ static void sh4_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
750
@@ -XXX,XX +XXX,XX @@ static void sh4_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
643
tcg_gen_insn_start(ctx->base.pc_next, ctx->envflags);
751
tcg_gen_insn_start(ctx->base.pc_next, ctx->envflags);
644
}
752
}
645
753
646
-static bool sh4_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
754
-static bool sh4_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
647
- const CPUBreakpoint *bp)
755
- const CPUBreakpoint *bp)
648
+static int sh4_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
756
-{
649
+ int bp_flags)
757
- DisasContext *ctx = container_of(dcbase, DisasContext, base);
650
{
758
-
651
DisasContext *ctx = container_of(dcbase, DisasContext, base);
759
- /* We have hit a breakpoint - make sure PC is up-to-date */
652
760
- gen_save_cpu_state(ctx, true);
653
@@ -XXX,XX +XXX,XX @@ static bool sh4_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
761
- gen_helper_debug(cpu_env);
654
gen_save_cpu_state(ctx, true);
762
- ctx->base.is_jmp = DISAS_NORETURN;
655
gen_helper_debug(cpu_env);
656
ctx->base.is_jmp = DISAS_NORETURN;
657
- /* The address covered by the breakpoint must be included in
763
- /* The address covered by the breakpoint must be included in
658
- [tb->pc, tb->pc + tb->size) in order to for it to be
764
- [tb->pc, tb->pc + tb->size) in order to for it to be
659
- properly cleared -- thus we increment the PC here so that
765
- properly cleared -- thus we increment the PC here so that
660
- the logic setting tb->size below does the right thing. */
766
- the logic setting tb->size below does the right thing. */
661
- ctx->base.pc_next += 2;
767
- ctx->base.pc_next += 2;
662
- return true;
768
- return true;
663
+
769
-}
664
+ return 2; /* minimum instruction length */
770
-
665
}
666
667
static void sh4_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
771
static void sh4_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
772
{
773
CPUSH4State *env = cs->env_ptr;
774
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps sh4_tr_ops = {
775
.init_disas_context = sh4_tr_init_disas_context,
776
.tb_start = sh4_tr_tb_start,
777
.insn_start = sh4_tr_insn_start,
778
- .breakpoint_check = sh4_tr_breakpoint_check,
779
.translate_insn = sh4_tr_translate_insn,
780
.tb_stop = sh4_tr_tb_stop,
781
.disas_log = sh4_tr_disas_log,
668
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
782
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
669
index XXXXXXX..XXXXXXX 100644
783
index XXXXXXX..XXXXXXX 100644
670
--- a/target/sparc/translate.c
784
--- a/target/sparc/translate.c
671
+++ b/target/sparc/translate.c
785
+++ b/target/sparc/translate.c
672
@@ -XXX,XX +XXX,XX @@ static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
786
@@ -XXX,XX +XXX,XX @@ static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
673
}
787
}
674
}
788
}
675
789
676
-static bool sparc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
790
-static bool sparc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
677
- const CPUBreakpoint *bp)
791
- const CPUBreakpoint *bp)
678
+static int sparc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
792
-{
679
+ int bp_flags)
793
- DisasContext *dc = container_of(dcbase, DisasContext, base);
680
{
794
-
681
DisasContext *dc = container_of(dcbase, DisasContext, base);
795
- if (dc->pc != dc->base.pc_first) {
682
796
- save_state(dc);
683
@@ -XXX,XX +XXX,XX @@ static bool sparc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
797
- }
684
gen_helper_debug(cpu_env);
798
- gen_helper_debug(cpu_env);
685
tcg_gen_exit_tb(NULL, 0);
799
- tcg_gen_exit_tb(NULL, 0);
686
dc->base.is_jmp = DISAS_NORETURN;
800
- dc->base.is_jmp = DISAS_NORETURN;
687
- /* update pc_next so that the current instruction is included in tb->size */
801
- /* update pc_next so that the current instruction is included in tb->size */
688
- dc->base.pc_next += 4;
802
- dc->base.pc_next += 4;
689
- return true;
803
- return true;
690
+
804
-}
691
+ return 4; /* minimum instruction length */
805
-
692
}
693
694
static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
806
static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
807
{
808
DisasContext *dc = container_of(dcbase, DisasContext, base);
809
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps sparc_tr_ops = {
810
.init_disas_context = sparc_tr_init_disas_context,
811
.tb_start = sparc_tr_tb_start,
812
.insn_start = sparc_tr_insn_start,
813
- .breakpoint_check = sparc_tr_breakpoint_check,
814
.translate_insn = sparc_tr_translate_insn,
815
.tb_stop = sparc_tr_tb_stop,
816
.disas_log = sparc_tr_disas_log,
695
diff --git a/target/tricore/translate.c b/target/tricore/translate.c
817
diff --git a/target/tricore/translate.c b/target/tricore/translate.c
696
index XXXXXXX..XXXXXXX 100644
818
index XXXXXXX..XXXXXXX 100644
697
--- a/target/tricore/translate.c
819
--- a/target/tricore/translate.c
698
+++ b/target/tricore/translate.c
820
+++ b/target/tricore/translate.c
699
@@ -XXX,XX +XXX,XX @@ static void tricore_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
821
@@ -XXX,XX +XXX,XX @@ static void tricore_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
700
tcg_gen_insn_start(ctx->base.pc_next);
822
tcg_gen_insn_start(ctx->base.pc_next);
701
}
823
}
702
824
703
-static bool tricore_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
825
-static bool tricore_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
704
- const CPUBreakpoint *bp)
826
- const CPUBreakpoint *bp)
705
+static int tricore_tr_breakpoint_check(DisasContextBase *dcbase,
827
-{
706
+ CPUState *cpu, int bp_flags)
828
- DisasContext *ctx = container_of(dcbase, DisasContext, base);
707
{
829
- generate_qemu_excp(ctx, EXCP_DEBUG);
708
DisasContext *ctx = container_of(dcbase, DisasContext, base);
709
generate_qemu_excp(ctx, EXCP_DEBUG);
710
- /*
830
- /*
711
- * The address covered by the breakpoint must be included in
831
- * The address covered by the breakpoint must be included in
712
- * [tb->pc, tb->pc + tb->size) in order to for it to be
832
- * [tb->pc, tb->pc + tb->size) in order to for it to be
713
- * properly cleared -- thus we increment the PC here so that
833
- * properly cleared -- thus we increment the PC here so that
714
- * the logic setting tb->size below does the right thing.
834
- * the logic setting tb->size below does the right thing.
715
- */
835
- */
716
- ctx->base.pc_next += 4;
836
- ctx->base.pc_next += 4;
717
- return true;
837
- return true;
718
+ return 4; /* minimum instruction length */
838
-}
719
}
839
-
720
721
static bool insn_crosses_page(CPUTriCoreState *env, DisasContext *ctx)
840
static bool insn_crosses_page(CPUTriCoreState *env, DisasContext *ctx)
841
{
842
/*
843
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps tricore_tr_ops = {
844
.init_disas_context = tricore_tr_init_disas_context,
845
.tb_start = tricore_tr_tb_start,
846
.insn_start = tricore_tr_insn_start,
847
- .breakpoint_check = tricore_tr_breakpoint_check,
848
.translate_insn = tricore_tr_translate_insn,
849
.tb_stop = tricore_tr_tb_stop,
850
.disas_log = tricore_tr_disas_log,
722
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
851
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
723
index XXXXXXX..XXXXXXX 100644
852
index XXXXXXX..XXXXXXX 100644
724
--- a/target/xtensa/translate.c
853
--- a/target/xtensa/translate.c
725
+++ b/target/xtensa/translate.c
854
+++ b/target/xtensa/translate.c
726
@@ -XXX,XX +XXX,XX @@ static void xtensa_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
855
@@ -XXX,XX +XXX,XX @@ static void xtensa_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
727
tcg_gen_insn_start(dcbase->pc_next);
856
tcg_gen_insn_start(dcbase->pc_next);
728
}
857
}
729
858
730
-static bool xtensa_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
859
-static bool xtensa_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
731
- const CPUBreakpoint *bp)
860
- const CPUBreakpoint *bp)
732
+static int xtensa_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
861
-{
733
+ int bp_flags)
862
- DisasContext *dc = container_of(dcbase, DisasContext, base);
734
{
863
-
735
DisasContext *dc = container_of(dcbase, DisasContext, base);
864
- tcg_gen_movi_i32(cpu_pc, dc->base.pc_next);
736
865
- gen_exception(dc, EXCP_DEBUG);
737
tcg_gen_movi_i32(cpu_pc, dc->base.pc_next);
866
- dc->base.is_jmp = DISAS_NORETURN;
738
gen_exception(dc, EXCP_DEBUG);
739
dc->base.is_jmp = DISAS_NORETURN;
740
- /* The address covered by the breakpoint must be included in
867
- /* The address covered by the breakpoint must be included in
741
- [tb->pc, tb->pc + tb->size) in order to for it to be
868
- [tb->pc, tb->pc + tb->size) in order to for it to be
742
- properly cleared -- thus we increment the PC here so that
869
- properly cleared -- thus we increment the PC here so that
743
- the logic setting tb->size below does the right thing. */
870
- the logic setting tb->size below does the right thing. */
744
- dc->base.pc_next += 2;
871
- dc->base.pc_next += 2;
745
- return true;
872
- return true;
746
+
873
-}
747
+ return 2; /* minimum instruction length */
874
-
748
}
749
750
static void xtensa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
875
static void xtensa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
876
{
877
DisasContext *dc = container_of(dcbase, DisasContext, base);
878
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps xtensa_translator_ops = {
879
.init_disas_context = xtensa_tr_init_disas_context,
880
.tb_start = xtensa_tr_tb_start,
881
.insn_start = xtensa_tr_insn_start,
882
- .breakpoint_check = xtensa_tr_breakpoint_check,
883
.translate_insn = xtensa_tr_translate_insn,
884
.tb_stop = xtensa_tr_tb_stop,
885
.disas_log = xtensa_tr_disas_log,
751
--
886
--
752
2.25.1
887
2.25.1
753
888
754
889
diff view generated by jsdifflib
1
The access internal to tb_cflags() is atomic.
1
The access internal to tb_cflags() is atomic.
2
Avoid re-reading it as such for the multiple uses.
2
Avoid re-reading it as such for the multiple uses.
3
3
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
---
6
---
6
accel/tcg/translator.c | 9 ++++-----
7
accel/tcg/translator.c | 9 ++++-----
7
1 file changed, 4 insertions(+), 5 deletions(-)
8
1 file changed, 4 insertions(+), 5 deletions(-)
8
9
...
...
diff view generated by jsdifflib
New patch
1
Set CF_SINGLE_STEP when single-stepping is enabled.
2
This avoids the need to flush all tb's when turning
3
single-stepping on or off.
1
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
include/exec/exec-all.h | 1 +
8
accel/tcg/cpu-exec.c | 7 ++++++-
9
accel/tcg/translate-all.c | 4 ----
10
accel/tcg/translator.c | 7 +------
11
cpu.c | 4 ----
12
5 files changed, 8 insertions(+), 15 deletions(-)
13
14
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/exec/exec-all.h
17
+++ b/include/exec/exec-all.h
18
@@ -XXX,XX +XXX,XX @@ struct TranslationBlock {
19
#define CF_COUNT_MASK 0x000001ff
20
#define CF_NO_GOTO_TB 0x00000200 /* Do not chain with goto_tb */
21
#define CF_NO_GOTO_PTR 0x00000400 /* Do not chain with goto_ptr */
22
+#define CF_SINGLE_STEP 0x00000800 /* gdbstub single-step in effect */
23
#define CF_LAST_IO 0x00008000 /* Last insn may be an IO access. */
24
#define CF_MEMI_ONLY 0x00010000 /* Only instrument memory ops */
25
#define CF_USE_ICOUNT 0x00020000
26
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/accel/tcg/cpu-exec.c
29
+++ b/accel/tcg/cpu-exec.c
30
@@ -XXX,XX +XXX,XX @@ uint32_t curr_cflags(CPUState *cpu)
31
uint32_t cflags = cpu->tcg_cflags;
32
33
/*
34
+ * Record gdb single-step. We should be exiting the TB by raising
35
+ * EXCP_DEBUG, but to simplify other tests, disable chaining too.
36
+ *
37
* For singlestep and -d nochain, suppress goto_tb so that
38
* we can log -d cpu,exec after every TB.
39
*/
40
- if (singlestep) {
41
+ if (unlikely(cpu->singlestep_enabled)) {
42
+ cflags |= CF_NO_GOTO_TB | CF_NO_GOTO_PTR | CF_SINGLE_STEP | 1;
43
+ } else if (singlestep) {
44
cflags |= CF_NO_GOTO_TB | 1;
45
} else if (qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
46
cflags |= CF_NO_GOTO_TB;
47
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/accel/tcg/translate-all.c
50
+++ b/accel/tcg/translate-all.c
51
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
52
}
53
QEMU_BUILD_BUG_ON(CF_COUNT_MASK + 1 != TCG_MAX_INSNS);
54
55
- if (cpu->singlestep_enabled) {
56
- max_insns = 1;
57
- }
58
-
59
buffer_overflow:
60
tb = tcg_tb_alloc(tcg_ctx);
61
if (unlikely(!tb)) {
62
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/accel/tcg/translator.c
65
+++ b/accel/tcg/translator.c
66
@@ -XXX,XX +XXX,XX @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest)
67
return false;
68
}
69
70
- /* Suppress goto_tb in the case of single-steping. */
71
- if (db->singlestep_enabled) {
72
- return false;
73
- }
74
-
75
/* Check for the dest on the same page as the start of the TB. */
76
return ((db->pc_first ^ dest) & TARGET_PAGE_MASK) == 0;
77
}
78
@@ -XXX,XX +XXX,XX @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
79
db->is_jmp = DISAS_NEXT;
80
db->num_insns = 0;
81
db->max_insns = max_insns;
82
- db->singlestep_enabled = cpu->singlestep_enabled;
83
+ db->singlestep_enabled = cflags & CF_SINGLE_STEP;
84
85
ops->init_disas_context(db, cpu);
86
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
87
diff --git a/cpu.c b/cpu.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/cpu.c
90
+++ b/cpu.c
91
@@ -XXX,XX +XXX,XX @@ void cpu_single_step(CPUState *cpu, int enabled)
92
cpu->singlestep_enabled = enabled;
93
if (kvm_enabled()) {
94
kvm_update_guest_debug(cpu, 0);
95
- } else {
96
- /* must flush all the translated code to avoid inconsistencies */
97
- /* XXX: only flush what is necessary */
98
- tb_flush(cpu);
99
}
100
trace_breakpoint_singlestep(cpu->cpu_index, enabled);
101
}
102
--
103
2.25.1
104
105
diff view generated by jsdifflib