1
This is v4 of my notdirty + rom patch set with two suggested name
1
The following changes since commit 3c8c36c9087da957f580a9bb5ebf7814a753d1c6:
2
changes (qemu_build_not_reached, TLB_DISCARD_WRITE) from David and Alex.
3
2
4
3
Merge remote-tracking branch 'remotes/kraxel/tags/ui-20201104-pull-request' into staging (2020-11-04 16:52:17 +0000)
5
r~
6
7
8
The following changes since commit 240ab11fb72049d6373cbbec8d788f8e411a00bc:
9
10
Merge remote-tracking branch 'remotes/aperard/tags/pull-xen-20190924' into staging (2019-09-24 15:36:31 +0100)
11
4
12
are available in the Git repository at:
5
are available in the Git repository at:
13
6
14
https://github.com/rth7680/qemu.git tags/pull-tcg-20190925
7
https://github.com/rth7680/qemu.git tags/pull-tcg-20201104
15
8
16
for you to fetch changes up to ae57db63acf5a0399232f852acc5c1d83ef63400:
9
for you to fetch changes up to c56caea3b2a4ef5d760266f554df0d92c5a45f87:
17
10
18
cputlb: Pass retaddr to tb_check_watchpoint (2019-09-25 10:56:28 -0700)
11
tcg: Revert "tcg/optimize: Flush data at labels not TCG_OPF_BB_END" (2020-11-04 10:35:40 -0800)
19
12
20
----------------------------------------------------------------
13
----------------------------------------------------------------
21
Fixes for TLB_BSWAP
14
Fix assert in set_jmp_reset_offset
22
Coversion of NOTDIRTY and ROM handling to cputlb
15
Revert cross-branch optimization in tcg/optimize.c.
23
Followup cleanups to cputlb
24
16
25
----------------------------------------------------------------
17
----------------------------------------------------------------
26
Richard Henderson (16):
18
Richard Henderson (2):
27
exec: Use TARGET_PAGE_BITS_MIN for TLB flags
19
tcg: Remove assert from set_jmp_reset_offset
28
cputlb: Disable __always_inline__ without optimization
20
tcg: Revert "tcg/optimize: Flush data at labels not TCG_OPF_BB_END"
29
qemu/compiler.h: Add qemu_build_not_reached
30
cputlb: Use qemu_build_not_reached in load/store_helpers
31
cputlb: Split out load/store_memop
32
cputlb: Introduce TLB_BSWAP
33
exec: Adjust notdirty tracing
34
cputlb: Move ROM handling from I/O path to TLB path
35
cputlb: Move NOTDIRTY handling from I/O path to TLB path
36
cputlb: Partially inline memory_region_section_get_iotlb
37
cputlb: Merge and move memory_notdirty_write_{prepare,complete}
38
cputlb: Handle TLB_NOTDIRTY in probe_access
39
cputlb: Remove cpu->mem_io_vaddr
40
cputlb: Remove tb_invalidate_phys_page_range is_cpu_write_access
41
cputlb: Pass retaddr to tb_invalidate_phys_page_fast
42
cputlb: Pass retaddr to tb_check_watchpoint
43
21
44
accel/tcg/translate-all.h | 8 +-
22
tcg/optimize.c | 35 +++++++++++++++++------------------
45
include/exec/cpu-all.h | 23 ++-
23
tcg/tcg.c | 9 +++++----
46
include/exec/cpu-common.h | 3 -
24
2 files changed, 22 insertions(+), 22 deletions(-)
47
include/exec/exec-all.h | 6 +-
48
include/exec/memory-internal.h | 65 --------
49
include/hw/core/cpu.h | 2 -
50
include/qemu/compiler.h | 26 +++
51
accel/tcg/cputlb.c | 348 +++++++++++++++++++++++++----------------
52
accel/tcg/translate-all.c | 51 +++---
53
exec.c | 158 +------------------
54
hw/core/cpu.c | 1 -
55
memory.c | 20 ---
56
trace-events | 4 +-
57
13 files changed, 288 insertions(+), 427 deletions(-)
58
25
diff view generated by jsdifflib
Deleted patch
1
These bits do not need to vary with the actual page size
2
used by the guest.
3
1
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: David Hildenbrand <david@redhat.com>
6
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
include/exec/cpu-all.h | 16 ++++++++++------
10
1 file changed, 10 insertions(+), 6 deletions(-)
11
12
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/include/exec/cpu-all.h
15
+++ b/include/exec/cpu-all.h
16
@@ -XXX,XX +XXX,XX @@ CPUArchState *cpu_copy(CPUArchState *env);
17
18
#if !defined(CONFIG_USER_ONLY)
19
20
-/* Flags stored in the low bits of the TLB virtual address. These are
21
- * defined so that fast path ram access is all zeros.
22
+/*
23
+ * Flags stored in the low bits of the TLB virtual address.
24
+ * These are defined so that fast path ram access is all zeros.
25
* The flags all must be between TARGET_PAGE_BITS and
26
* maximum address alignment bit.
27
+ *
28
+ * Use TARGET_PAGE_BITS_MIN so that these bits are constant
29
+ * when TARGET_PAGE_BITS_VARY is in effect.
30
*/
31
/* Zero if TLB entry is valid. */
32
-#define TLB_INVALID_MASK (1 << (TARGET_PAGE_BITS - 1))
33
+#define TLB_INVALID_MASK (1 << (TARGET_PAGE_BITS_MIN - 1))
34
/* Set if TLB entry references a clean RAM page. The iotlb entry will
35
contain the page physical address. */
36
-#define TLB_NOTDIRTY (1 << (TARGET_PAGE_BITS - 2))
37
+#define TLB_NOTDIRTY (1 << (TARGET_PAGE_BITS_MIN - 2))
38
/* Set if TLB entry is an IO callback. */
39
-#define TLB_MMIO (1 << (TARGET_PAGE_BITS - 3))
40
+#define TLB_MMIO (1 << (TARGET_PAGE_BITS_MIN - 3))
41
/* Set if TLB entry contains a watchpoint. */
42
-#define TLB_WATCHPOINT (1 << (TARGET_PAGE_BITS - 4))
43
+#define TLB_WATCHPOINT (1 << (TARGET_PAGE_BITS_MIN - 4))
44
45
/* Use this mask to check interception with an alignment mask
46
* in a TCG backend.
47
--
48
2.17.1
49
50
diff view generated by jsdifflib
Deleted patch
1
This forced inlining can result in missing symbols,
2
which makes a debugging build harder to follow.
3
1
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Reviewed-by: David Hildenbrand <david@redhat.com>
7
Reported-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
10
include/qemu/compiler.h | 11 +++++++++++
11
accel/tcg/cputlb.c | 4 ++--
12
2 files changed, 13 insertions(+), 2 deletions(-)
13
14
diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/qemu/compiler.h
17
+++ b/include/qemu/compiler.h
18
@@ -XXX,XX +XXX,XX @@
19
# define QEMU_NONSTRING
20
#endif
21
22
+/*
23
+ * Forced inlining may be desired to encourage constant propagation
24
+ * of function parameters. However, it can also make debugging harder,
25
+ * so disable it for a non-optimizing build.
26
+ */
27
+#if defined(__OPTIMIZE__)
28
+#define QEMU_ALWAYS_INLINE __attribute__((always_inline))
29
+#else
30
+#define QEMU_ALWAYS_INLINE
31
+#endif
32
+
33
/* Implement C11 _Generic via GCC builtins. Example:
34
*
35
* QEMU_GENERIC(x, (float, sinf), (long double, sinl), sin) (x)
36
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/accel/tcg/cputlb.c
39
+++ b/accel/tcg/cputlb.c
40
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
41
typedef uint64_t FullLoadHelper(CPUArchState *env, target_ulong addr,
42
TCGMemOpIdx oi, uintptr_t retaddr);
43
44
-static inline uint64_t __attribute__((always_inline))
45
+static inline uint64_t QEMU_ALWAYS_INLINE
46
load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
47
uintptr_t retaddr, MemOp op, bool code_read,
48
FullLoadHelper *full_load)
49
@@ -XXX,XX +XXX,XX @@ tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr,
50
* Store Helpers
51
*/
52
53
-static inline void __attribute__((always_inline))
54
+static inline void QEMU_ALWAYS_INLINE
55
store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
56
TCGMemOpIdx oi, uintptr_t retaddr, MemOp op)
57
{
58
--
59
2.17.1
60
61
diff view generated by jsdifflib
Deleted patch
1
Use this as a compile-time assert that a particular
2
code path is not reachable.
3
1
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
include/qemu/compiler.h | 15 +++++++++++++++
8
1 file changed, 15 insertions(+)
9
10
diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
11
index XXXXXXX..XXXXXXX 100644
12
--- a/include/qemu/compiler.h
13
+++ b/include/qemu/compiler.h
14
@@ -XXX,XX +XXX,XX @@
15
#define QEMU_GENERIC9(x, a0, ...) QEMU_GENERIC_IF(x, a0, QEMU_GENERIC8(x, __VA_ARGS__))
16
#define QEMU_GENERIC10(x, a0, ...) QEMU_GENERIC_IF(x, a0, QEMU_GENERIC9(x, __VA_ARGS__))
17
18
+/**
19
+ * qemu_build_not_reached()
20
+ *
21
+ * The compiler, during optimization, is expected to prove that a call
22
+ * to this function cannot be reached and remove it. If the compiler
23
+ * supports QEMU_ERROR, this will be reported at compile time; otherwise
24
+ * this will be reported at link time due to the missing symbol.
25
+ */
26
+#ifdef __OPTIMIZE__
27
+extern void QEMU_NORETURN QEMU_ERROR("code path is reachable")
28
+ qemu_build_not_reached(void);
29
+#else
30
+#define qemu_build_not_reached() g_assert_not_reached()
31
+#endif
32
+
33
#endif /* COMPILER_H */
34
--
35
2.17.1
36
37
diff view generated by jsdifflib
1
Increase the current runtime assert to a compile-time assert.
1
Since 6e6c4efed99, there has been a more appropriate range check
2
done later at the end of tcg_gen_code. There, a failing range
3
check results in a returned error code, which causes the TB to
4
be restarted at half the size.
2
5
3
Reviewed-by: David Hildenbrand <david@redhat.com>
6
Reported-by: Sai Pavan Boddu <saipava@xilinx.com>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Tested-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
10
---
7
accel/tcg/cputlb.c | 5 ++---
11
tcg/tcg.c | 9 +++++----
8
1 file changed, 2 insertions(+), 3 deletions(-)
12
1 file changed, 5 insertions(+), 4 deletions(-)
9
13
10
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
14
diff --git a/tcg/tcg.c b/tcg/tcg.c
11
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
12
--- a/accel/tcg/cputlb.c
16
--- a/tcg/tcg.c
13
+++ b/accel/tcg/cputlb.c
17
+++ b/tcg/tcg.c
14
@@ -XXX,XX +XXX,XX @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
18
@@ -XXX,XX +XXX,XX @@ static bool tcg_resolve_relocs(TCGContext *s)
15
res = ldq_le_p(haddr);
19
16
break;
20
static void set_jmp_reset_offset(TCGContext *s, int which)
17
default:
21
{
18
- g_assert_not_reached();
22
- size_t off = tcg_current_code_size(s);
19
+ qemu_build_not_reached();
23
- s->tb_jmp_reset_offset[which] = off;
20
}
24
- /* Make sure that we didn't overflow the stored offset. */
21
25
- assert(s->tb_jmp_reset_offset[which] == off);
22
return res;
26
+ /*
23
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
27
+ * We will check for overflow at the end of the opcode loop in
24
stq_le_p(haddr, val);
28
+ * tcg_gen_code, where we bound tcg_current_code_size to UINT16_MAX.
25
break;
29
+ */
26
default:
30
+ s->tb_jmp_reset_offset[which] = tcg_current_code_size(s);
27
- g_assert_not_reached();
28
- break;
29
+ qemu_build_not_reached();
30
}
31
}
31
}
32
32
33
#include "tcg-target.c.inc"
33
--
34
--
34
2.17.1
35
2.25.1
35
36
36
37
diff view generated by jsdifflib
Deleted patch
1
We will shortly be using these more than once.
2
1
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: David Hildenbrand <david@redhat.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
accel/tcg/cputlb.c | 107 +++++++++++++++++++++++----------------------
8
1 file changed, 55 insertions(+), 52 deletions(-)
9
10
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/accel/tcg/cputlb.c
13
+++ b/accel/tcg/cputlb.c
14
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
15
typedef uint64_t FullLoadHelper(CPUArchState *env, target_ulong addr,
16
TCGMemOpIdx oi, uintptr_t retaddr);
17
18
+static inline uint64_t QEMU_ALWAYS_INLINE
19
+load_memop(const void *haddr, MemOp op)
20
+{
21
+ switch (op) {
22
+ case MO_UB:
23
+ return ldub_p(haddr);
24
+ case MO_BEUW:
25
+ return lduw_be_p(haddr);
26
+ case MO_LEUW:
27
+ return lduw_le_p(haddr);
28
+ case MO_BEUL:
29
+ return (uint32_t)ldl_be_p(haddr);
30
+ case MO_LEUL:
31
+ return (uint32_t)ldl_le_p(haddr);
32
+ case MO_BEQ:
33
+ return ldq_be_p(haddr);
34
+ case MO_LEQ:
35
+ return ldq_le_p(haddr);
36
+ default:
37
+ qemu_build_not_reached();
38
+ }
39
+}
40
+
41
static inline uint64_t QEMU_ALWAYS_INLINE
42
load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
43
uintptr_t retaddr, MemOp op, bool code_read,
44
@@ -XXX,XX +XXX,XX @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
45
46
do_aligned_access:
47
haddr = (void *)((uintptr_t)addr + entry->addend);
48
- switch (op) {
49
- case MO_UB:
50
- res = ldub_p(haddr);
51
- break;
52
- case MO_BEUW:
53
- res = lduw_be_p(haddr);
54
- break;
55
- case MO_LEUW:
56
- res = lduw_le_p(haddr);
57
- break;
58
- case MO_BEUL:
59
- res = (uint32_t)ldl_be_p(haddr);
60
- break;
61
- case MO_LEUL:
62
- res = (uint32_t)ldl_le_p(haddr);
63
- break;
64
- case MO_BEQ:
65
- res = ldq_be_p(haddr);
66
- break;
67
- case MO_LEQ:
68
- res = ldq_le_p(haddr);
69
- break;
70
- default:
71
- qemu_build_not_reached();
72
- }
73
-
74
- return res;
75
+ return load_memop(haddr, op);
76
}
77
78
/*
79
@@ -XXX,XX +XXX,XX @@ tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr,
80
* Store Helpers
81
*/
82
83
+static inline void QEMU_ALWAYS_INLINE
84
+store_memop(void *haddr, uint64_t val, MemOp op)
85
+{
86
+ switch (op) {
87
+ case MO_UB:
88
+ stb_p(haddr, val);
89
+ break;
90
+ case MO_BEUW:
91
+ stw_be_p(haddr, val);
92
+ break;
93
+ case MO_LEUW:
94
+ stw_le_p(haddr, val);
95
+ break;
96
+ case MO_BEUL:
97
+ stl_be_p(haddr, val);
98
+ break;
99
+ case MO_LEUL:
100
+ stl_le_p(haddr, val);
101
+ break;
102
+ case MO_BEQ:
103
+ stq_be_p(haddr, val);
104
+ break;
105
+ case MO_LEQ:
106
+ stq_le_p(haddr, val);
107
+ break;
108
+ default:
109
+ qemu_build_not_reached();
110
+ }
111
+}
112
+
113
static inline void QEMU_ALWAYS_INLINE
114
store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
115
TCGMemOpIdx oi, uintptr_t retaddr, MemOp op)
116
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
117
118
do_aligned_access:
119
haddr = (void *)((uintptr_t)addr + entry->addend);
120
- switch (op) {
121
- case MO_UB:
122
- stb_p(haddr, val);
123
- break;
124
- case MO_BEUW:
125
- stw_be_p(haddr, val);
126
- break;
127
- case MO_LEUW:
128
- stw_le_p(haddr, val);
129
- break;
130
- case MO_BEUL:
131
- stl_be_p(haddr, val);
132
- break;
133
- case MO_LEUL:
134
- stl_le_p(haddr, val);
135
- break;
136
- case MO_BEQ:
137
- stq_be_p(haddr, val);
138
- break;
139
- case MO_LEQ:
140
- stq_le_p(haddr, val);
141
- break;
142
- default:
143
- qemu_build_not_reached();
144
- }
145
+ store_memop(haddr, val, op);
146
}
147
148
void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
149
--
150
2.17.1
151
152
diff view generated by jsdifflib
1
Handle bswap on ram directly in load/store_helper. This fixes a
1
This reverts commit cd0372c515c4732d8bd3777cdd995c139c7ed7ea.
2
bug with the previous implementation in that one cannot use the
3
I/O path for RAM.
4
2
5
Fixes: a26fc6f5152b47f1
3
The patch is incorrect in that it retains copies between globals and
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
non-local temps, and non-local temps still die at the end of the BB.
7
Reviewed-by: David Hildenbrand <david@redhat.com>
5
6
Failing test case for hppa:
7
8
    .globl    _start
9
_start:
10
    cmpiclr,=    0x24,%r19,%r0
11
    cmpiclr,<>    0x2f,%r19,%r19
12
13
---- 00010057 0001005b
14
movi_i32 tmp0,$0x24
15
sub_i32 tmp1,tmp0,r19
16
mov_i32 tmp2,tmp0
17
mov_i32 tmp3,r19
18
movi_i32 tmp1,$0x0
19
20
---- 0001005b 0001005f
21
brcond_i32 tmp2,tmp3,eq,$L1
22
movi_i32 tmp0,$0x2f
23
sub_i32 tmp1,tmp0,r19
24
mov_i32 tmp2,tmp0
25
mov_i32 tmp3,r19
26
movi_i32 tmp1,$0x0
27
mov_i32 r19,tmp1
28
setcond_i32 psw_n,tmp2,tmp3,ne
29
set_label $L1
30
31
In this case, both copies of "mov_i32 tmp3,r19" are removed. The
32
second because opt thought it was redundant. The first is removed
33
later by liveness because tmp3 is known to be dead. This leaves
34
the setcond_i32 with an uninitialized input.
35
36
Revert the entire patch for 5.2, and a proper optimization across
37
the branch may be considered for the next development cycle.
38
39
Reported-by: qemu@igor2.repo.hu
40
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
41
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
42
---
10
include/exec/cpu-all.h | 4 ++-
43
tcg/optimize.c | 35 +++++++++++++++++------------------
11
accel/tcg/cputlb.c | 72 +++++++++++++++++++++++++-----------------
44
1 file changed, 17 insertions(+), 18 deletions(-)
12
2 files changed, 46 insertions(+), 30 deletions(-)
13
45
14
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
46
diff --git a/tcg/optimize.c b/tcg/optimize.c
15
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
16
--- a/include/exec/cpu-all.h
48
--- a/tcg/optimize.c
17
+++ b/include/exec/cpu-all.h
49
+++ b/tcg/optimize.c
18
@@ -XXX,XX +XXX,XX @@ CPUArchState *cpu_copy(CPUArchState *env);
50
@@ -XXX,XX +XXX,XX @@ void tcg_optimize(TCGContext *s)
19
#define TLB_MMIO (1 << (TARGET_PAGE_BITS_MIN - 3))
51
}
20
/* Set if TLB entry contains a watchpoint. */
52
}
21
#define TLB_WATCHPOINT (1 << (TARGET_PAGE_BITS_MIN - 4))
53
}
22
+/* Set if TLB entry requires byte swap. */
54
- /* fall through */
23
+#define TLB_BSWAP (1 << (TARGET_PAGE_BITS_MIN - 5))
55
+ goto do_reset_output;
24
56
25
/* Use this mask to check interception with an alignment mask
57
default:
26
* in a TCG backend.
58
do_default:
27
*/
59
- /*
28
#define TLB_FLAGS_MASK \
60
- * Default case: we know nothing about operation (or were unable
29
- (TLB_INVALID_MASK | TLB_NOTDIRTY | TLB_MMIO | TLB_WATCHPOINT)
61
- * to compute the operation result) so no propagation is done.
30
+ (TLB_INVALID_MASK | TLB_NOTDIRTY | TLB_MMIO | TLB_WATCHPOINT | TLB_BSWAP)
62
- */
31
63
- for (i = 0; i < nb_oargs; i++) {
32
/**
64
- reset_temp(op->args[i]);
33
* tlb_hit_page: return true if page aligned @addr is a hit against the
65
- /*
34
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
66
- * Save the corresponding known-zero bits mask for the
35
index XXXXXXX..XXXXXXX 100644
67
- * first output argument (only one supported so far).
36
--- a/accel/tcg/cputlb.c
68
- */
37
+++ b/accel/tcg/cputlb.c
69
- if (i == 0) {
38
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
70
- arg_info(op->args[i])->mask = mask;
39
address |= TLB_INVALID_MASK;
71
+ /* Default case: we know nothing about operation (or were unable
40
}
72
+ to compute the operation result) so no propagation is done.
41
if (attrs.byte_swap) {
73
+ We trash everything if the operation is the end of a basic
42
- /* Force the access through the I/O slow path. */
74
+ block, otherwise we only trash the output args. "mask" is
43
- address |= TLB_MMIO;
75
+ the non-zero bits mask for the first output arg. */
44
+ address |= TLB_BSWAP;
76
+ if (def->flags & TCG_OPF_BB_END) {
45
}
77
+ bitmap_zero(temps_used.l, nb_temps);
46
if (!memory_region_is_ram(section->mr) &&
78
+ } else {
47
!memory_region_is_romd(section->mr)) {
79
+ do_reset_output:
48
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
80
+ for (i = 0; i < nb_oargs; i++) {
49
bool locked = false;
81
+ reset_temp(op->args[i]);
50
MemTxResult r;
82
+ /* Save the corresponding known-zero bits mask for the
51
83
+ first output argument (only one supported so far). */
52
- if (iotlbentry->attrs.byte_swap) {
84
+ if (i == 0) {
53
- op ^= MO_BSWAP;
85
+ arg_info(op->args[i])->mask = mask;
54
- }
86
+ }
87
}
88
}
89
break;
55
-
90
-
56
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
91
- case INDEX_op_set_label:
57
mr = section->mr;
92
- /* Trash everything at the start of a new extended bb. */
58
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
93
- bitmap_zero(temps_used.l, nb_temps);
59
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
94
- break;
60
bool locked = false;
61
MemTxResult r;
62
63
- if (iotlbentry->attrs.byte_swap) {
64
- op ^= MO_BSWAP;
65
- }
66
-
67
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
68
mr = section->mr;
69
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
70
@@ -XXX,XX +XXX,XX @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
71
wp_access, retaddr);
72
}
73
74
- if (tlb_addr & (TLB_NOTDIRTY | TLB_MMIO)) {
75
- /* I/O access */
76
+ /* Reject I/O access, or other required slow-path. */
77
+ if (tlb_addr & (TLB_NOTDIRTY | TLB_MMIO | TLB_BSWAP)) {
78
return NULL;
79
}
80
81
@@ -XXX,XX +XXX,XX @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
82
/* Handle anything that isn't just a straight memory access. */
83
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
84
CPUIOTLBEntry *iotlbentry;
85
+ bool need_swap;
86
87
/* For anything that is unaligned, recurse through full_load. */
88
if ((addr & (size - 1)) != 0) {
89
@@ -XXX,XX +XXX,XX @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
90
/* On watchpoint hit, this will longjmp out. */
91
cpu_check_watchpoint(env_cpu(env), addr, size,
92
iotlbentry->attrs, BP_MEM_READ, retaddr);
93
-
94
- /* The backing page may or may not require I/O. */
95
- tlb_addr &= ~TLB_WATCHPOINT;
96
- if ((tlb_addr & ~TARGET_PAGE_MASK) == 0) {
97
- goto do_aligned_access;
98
- }
99
}
95
}
100
96
101
+ need_swap = size > 1 && (tlb_addr & TLB_BSWAP);
97
/* Eliminate duplicate and redundant fence instructions. */
102
+
103
/* Handle I/O access. */
104
- return io_readx(env, iotlbentry, mmu_idx, addr,
105
- retaddr, access_type, op);
106
+ if (likely(tlb_addr & TLB_MMIO)) {
107
+ return io_readx(env, iotlbentry, mmu_idx, addr, retaddr,
108
+ access_type, op ^ (need_swap * MO_BSWAP));
109
+ }
110
+
111
+ haddr = (void *)((uintptr_t)addr + entry->addend);
112
+
113
+ /*
114
+ * Keep these two load_memop separate to ensure that the compiler
115
+ * is able to fold the entire function to a single instruction.
116
+ * There is a build-time assert inside to remind you of this. ;-)
117
+ */
118
+ if (unlikely(need_swap)) {
119
+ return load_memop(haddr, op ^ MO_BSWAP);
120
+ }
121
+ return load_memop(haddr, op);
122
}
123
124
/* Handle slow unaligned access (it spans two pages or IO). */
125
@@ -XXX,XX +XXX,XX @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
126
return res & MAKE_64BIT_MASK(0, size * 8);
127
}
128
129
- do_aligned_access:
130
haddr = (void *)((uintptr_t)addr + entry->addend);
131
return load_memop(haddr, op);
132
}
133
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
134
/* Handle anything that isn't just a straight memory access. */
135
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
136
CPUIOTLBEntry *iotlbentry;
137
+ bool need_swap;
138
139
/* For anything that is unaligned, recurse through byte stores. */
140
if ((addr & (size - 1)) != 0) {
141
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
142
/* On watchpoint hit, this will longjmp out. */
143
cpu_check_watchpoint(env_cpu(env), addr, size,
144
iotlbentry->attrs, BP_MEM_WRITE, retaddr);
145
-
146
- /* The backing page may or may not require I/O. */
147
- tlb_addr &= ~TLB_WATCHPOINT;
148
- if ((tlb_addr & ~TARGET_PAGE_MASK) == 0) {
149
- goto do_aligned_access;
150
- }
151
}
152
153
+ need_swap = size > 1 && (tlb_addr & TLB_BSWAP);
154
+
155
/* Handle I/O access. */
156
- io_writex(env, iotlbentry, mmu_idx, val, addr, retaddr, op);
157
+ if (likely(tlb_addr & (TLB_MMIO | TLB_NOTDIRTY))) {
158
+ io_writex(env, iotlbentry, mmu_idx, val, addr, retaddr,
159
+ op ^ (need_swap * MO_BSWAP));
160
+ return;
161
+ }
162
+
163
+ haddr = (void *)((uintptr_t)addr + entry->addend);
164
+
165
+ /*
166
+ * Keep these two store_memop separate to ensure that the compiler
167
+ * is able to fold the entire function to a single instruction.
168
+ * There is a build-time assert inside to remind you of this. ;-)
169
+ */
170
+ if (unlikely(need_swap)) {
171
+ store_memop(haddr, val, op ^ MO_BSWAP);
172
+ } else {
173
+ store_memop(haddr, val, op);
174
+ }
175
return;
176
}
177
178
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
179
return;
180
}
181
182
- do_aligned_access:
183
haddr = (void *)((uintptr_t)addr + entry->addend);
184
store_memop(haddr, val, op);
185
}
186
--
98
--
187
2.17.1
99
2.25.1
188
100
189
101
diff view generated by jsdifflib
Deleted patch
1
The memory_region_tb_read tracepoint is unreachable, since notdirty
2
is supposed to apply only to writes. The memory_region_tb_write
3
tracepoint is mis-named, because notdirty is not only used for TB
4
invalidation. It is also used for e.g. VGA RAM updates and migration.
5
1
6
Replace memory_region_tb_write with memory_notdirty_write_access,
7
and place it in memory_notdirty_write_prepare where it can catch
8
all of the instances. Add memory_notdirty_set_dirty to log when
9
we no longer intercept writes to a page.
10
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Reviewed-by: David Hildenbrand <david@redhat.com>
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
---
16
exec.c | 3 +++
17
memory.c | 4 ----
18
trace-events | 4 ++--
19
3 files changed, 5 insertions(+), 6 deletions(-)
20
21
diff --git a/exec.c b/exec.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/exec.c
24
+++ b/exec.c
25
@@ -XXX,XX +XXX,XX @@ void memory_notdirty_write_prepare(NotDirtyInfo *ndi,
26
ndi->size = size;
27
ndi->pages = NULL;
28
29
+ trace_memory_notdirty_write_access(mem_vaddr, ram_addr, size);
30
+
31
assert(tcg_enabled());
32
if (!cpu_physical_memory_get_dirty_flag(ram_addr, DIRTY_MEMORY_CODE)) {
33
ndi->pages = page_collection_lock(ram_addr, ram_addr + size);
34
@@ -XXX,XX +XXX,XX @@ void memory_notdirty_write_complete(NotDirtyInfo *ndi)
35
/* we remove the notdirty callback only if the code has been
36
flushed */
37
if (!cpu_physical_memory_is_clean(ndi->ram_addr)) {
38
+ trace_memory_notdirty_set_dirty(ndi->mem_vaddr);
39
tlb_set_dirty(ndi->cpu, ndi->mem_vaddr);
40
}
41
}
42
diff --git a/memory.c b/memory.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/memory.c
45
+++ b/memory.c
46
@@ -XXX,XX +XXX,XX @@ static MemTxResult memory_region_read_accessor(MemoryRegion *mr,
47
/* Accesses to code which has previously been translated into a TB show
48
* up in the MMIO path, as accesses to the io_mem_notdirty
49
* MemoryRegion. */
50
- trace_memory_region_tb_read(get_cpu_index(), addr, tmp, size);
51
} else if (TRACE_MEMORY_REGION_OPS_READ_ENABLED) {
52
hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr);
53
trace_memory_region_ops_read(get_cpu_index(), mr, abs_addr, tmp, size);
54
@@ -XXX,XX +XXX,XX @@ static MemTxResult memory_region_read_with_attrs_accessor(MemoryRegion *mr,
55
/* Accesses to code which has previously been translated into a TB show
56
* up in the MMIO path, as accesses to the io_mem_notdirty
57
* MemoryRegion. */
58
- trace_memory_region_tb_read(get_cpu_index(), addr, tmp, size);
59
} else if (TRACE_MEMORY_REGION_OPS_READ_ENABLED) {
60
hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr);
61
trace_memory_region_ops_read(get_cpu_index(), mr, abs_addr, tmp, size);
62
@@ -XXX,XX +XXX,XX @@ static MemTxResult memory_region_write_accessor(MemoryRegion *mr,
63
/* Accesses to code which has previously been translated into a TB show
64
* up in the MMIO path, as accesses to the io_mem_notdirty
65
* MemoryRegion. */
66
- trace_memory_region_tb_write(get_cpu_index(), addr, tmp, size);
67
} else if (TRACE_MEMORY_REGION_OPS_WRITE_ENABLED) {
68
hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr);
69
trace_memory_region_ops_write(get_cpu_index(), mr, abs_addr, tmp, size);
70
@@ -XXX,XX +XXX,XX @@ static MemTxResult memory_region_write_with_attrs_accessor(MemoryRegion *mr,
71
/* Accesses to code which has previously been translated into a TB show
72
* up in the MMIO path, as accesses to the io_mem_notdirty
73
* MemoryRegion. */
74
- trace_memory_region_tb_write(get_cpu_index(), addr, tmp, size);
75
} else if (TRACE_MEMORY_REGION_OPS_WRITE_ENABLED) {
76
hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr);
77
trace_memory_region_ops_write(get_cpu_index(), mr, abs_addr, tmp, size);
78
diff --git a/trace-events b/trace-events
79
index XXXXXXX..XXXXXXX 100644
80
--- a/trace-events
81
+++ b/trace-events
82
@@ -XXX,XX +XXX,XX @@ dma_map_wait(void *dbs) "dbs=%p"
83
find_ram_offset(uint64_t size, uint64_t offset) "size: 0x%" PRIx64 " @ 0x%" PRIx64
84
find_ram_offset_loop(uint64_t size, uint64_t candidate, uint64_t offset, uint64_t next, uint64_t mingap) "trying size: 0x%" PRIx64 " @ 0x%" PRIx64 ", offset: 0x%" PRIx64" next: 0x%" PRIx64 " mingap: 0x%" PRIx64
85
ram_block_discard_range(const char *rbname, void *hva, size_t length, bool need_madvise, bool need_fallocate, int ret) "%s@%p + 0x%zx: madvise: %d fallocate: %d ret: %d"
86
+memory_notdirty_write_access(uint64_t vaddr, uint64_t ram_addr, unsigned size) "0x%" PRIx64 " ram_addr 0x%" PRIx64 " size %u"
87
+memory_notdirty_set_dirty(uint64_t vaddr) "0x%" PRIx64
88
89
# memory.c
90
memory_region_ops_read(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
91
memory_region_ops_write(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
92
memory_region_subpage_read(int cpu_index, void *mr, uint64_t offset, uint64_t value, unsigned size) "cpu %d mr %p offset 0x%"PRIx64" value 0x%"PRIx64" size %u"
93
memory_region_subpage_write(int cpu_index, void *mr, uint64_t offset, uint64_t value, unsigned size) "cpu %d mr %p offset 0x%"PRIx64" value 0x%"PRIx64" size %u"
94
-memory_region_tb_read(int cpu_index, uint64_t addr, uint64_t value, unsigned size) "cpu %d addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
95
-memory_region_tb_write(int cpu_index, uint64_t addr, uint64_t value, unsigned size) "cpu %d addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
96
memory_region_ram_device_read(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
97
memory_region_ram_device_write(int cpu_index, void *mr, uint64_t addr, uint64_t value, unsigned size) "cpu %d mr %p addr 0x%"PRIx64" value 0x%"PRIx64" size %u"
98
flatview_new(void *view, void *root) "%p (root %p)"
99
--
100
2.17.1
101
102
diff view generated by jsdifflib
Deleted patch
1
It does not require going through the whole I/O path
2
in order to discard a write.
3
1
4
Reviewed-by: David Hildenbrand <david@redhat.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
include/exec/cpu-all.h | 5 ++++-
8
include/exec/cpu-common.h | 1 -
9
accel/tcg/cputlb.c | 36 ++++++++++++++++++++--------------
10
exec.c | 41 +--------------------------------------
11
4 files changed, 26 insertions(+), 57 deletions(-)
12
13
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/exec/cpu-all.h
16
+++ b/include/exec/cpu-all.h
17
@@ -XXX,XX +XXX,XX @@ CPUArchState *cpu_copy(CPUArchState *env);
18
#define TLB_WATCHPOINT (1 << (TARGET_PAGE_BITS_MIN - 4))
19
/* Set if TLB entry requires byte swap. */
20
#define TLB_BSWAP (1 << (TARGET_PAGE_BITS_MIN - 5))
21
+/* Set if TLB entry writes ignored. */
22
+#define TLB_DISCARD_WRITE (1 << (TARGET_PAGE_BITS_MIN - 6))
23
24
/* Use this mask to check interception with an alignment mask
25
* in a TCG backend.
26
*/
27
#define TLB_FLAGS_MASK \
28
- (TLB_INVALID_MASK | TLB_NOTDIRTY | TLB_MMIO | TLB_WATCHPOINT | TLB_BSWAP)
29
+ (TLB_INVALID_MASK | TLB_NOTDIRTY | TLB_MMIO \
30
+ | TLB_WATCHPOINT | TLB_BSWAP | TLB_DISCARD_WRITE)
31
32
/**
33
* tlb_hit_page: return true if page aligned @addr is a hit against the
34
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/include/exec/cpu-common.h
37
+++ b/include/exec/cpu-common.h
38
@@ -XXX,XX +XXX,XX @@ void qemu_flush_coalesced_mmio_buffer(void);
39
40
void cpu_flush_icache_range(hwaddr start, hwaddr len);
41
42
-extern struct MemoryRegion io_mem_rom;
43
extern struct MemoryRegion io_mem_notdirty;
44
45
typedef int (RAMBlockIterFunc)(RAMBlock *rb, void *opaque);
46
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/accel/tcg/cputlb.c
49
+++ b/accel/tcg/cputlb.c
50
@@ -XXX,XX +XXX,XX @@ static void tlb_reset_dirty_range_locked(CPUTLBEntry *tlb_entry,
51
{
52
uintptr_t addr = tlb_entry->addr_write;
53
54
- if ((addr & (TLB_INVALID_MASK | TLB_MMIO | TLB_NOTDIRTY)) == 0) {
55
+ if ((addr & (TLB_INVALID_MASK | TLB_MMIO |
56
+ TLB_DISCARD_WRITE | TLB_NOTDIRTY)) == 0) {
57
addr &= TARGET_PAGE_MASK;
58
addr += tlb_entry->addend;
59
if ((addr - start) < length) {
60
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
61
address |= TLB_MMIO;
62
addend = 0;
63
} else {
64
- /* TLB_MMIO for rom/romd handled below */
65
addend = (uintptr_t)memory_region_get_ram_ptr(section->mr) + xlat;
66
}
67
68
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
69
70
tn.addr_write = -1;
71
if (prot & PAGE_WRITE) {
72
- if ((memory_region_is_ram(section->mr) && section->readonly)
73
- || memory_region_is_romd(section->mr)) {
74
- /* Write access calls the I/O callback. */
75
- tn.addr_write = address | TLB_MMIO;
76
- } else if (memory_region_is_ram(section->mr)
77
- && cpu_physical_memory_is_clean(
78
- memory_region_get_ram_addr(section->mr) + xlat)) {
79
- tn.addr_write = address | TLB_NOTDIRTY;
80
- } else {
81
- tn.addr_write = address;
82
+ tn.addr_write = address;
83
+ if (memory_region_is_romd(section->mr)) {
84
+ /* Use the MMIO path so that the device can switch states. */
85
+ tn.addr_write |= TLB_MMIO;
86
+ } else if (memory_region_is_ram(section->mr)) {
87
+ if (section->readonly) {
88
+ tn.addr_write |= TLB_DISCARD_WRITE;
89
+ } else if (cpu_physical_memory_is_clean(
90
+ memory_region_get_ram_addr(section->mr) + xlat)) {
91
+ tn.addr_write |= TLB_NOTDIRTY;
92
+ }
93
}
94
if (prot & PAGE_WRITE_INV) {
95
tn.addr_write |= TLB_INVALID_MASK;
96
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
97
mr = section->mr;
98
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
99
cpu->mem_io_pc = retaddr;
100
- if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu->can_do_io) {
101
+ if (mr != &io_mem_notdirty && !cpu->can_do_io) {
102
cpu_io_recompile(cpu, retaddr);
103
}
104
105
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
106
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
107
mr = section->mr;
108
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
109
- if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu->can_do_io) {
110
+ if (mr != &io_mem_notdirty && !cpu->can_do_io) {
111
cpu_io_recompile(cpu, retaddr);
112
}
113
cpu->mem_io_vaddr = addr;
114
@@ -XXX,XX +XXX,XX @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
115
}
116
117
/* Reject I/O access, or other required slow-path. */
118
- if (tlb_addr & (TLB_NOTDIRTY | TLB_MMIO | TLB_BSWAP)) {
119
+ if (tlb_addr & (TLB_NOTDIRTY | TLB_MMIO | TLB_BSWAP | TLB_DISCARD_WRITE)) {
120
return NULL;
121
}
122
123
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
124
return;
125
}
126
127
+ /* Ignore writes to ROM. */
128
+ if (unlikely(tlb_addr & TLB_DISCARD_WRITE)) {
129
+ return;
130
+ }
131
+
132
haddr = (void *)((uintptr_t)addr + entry->addend);
133
134
/*
135
diff --git a/exec.c b/exec.c
136
index XXXXXXX..XXXXXXX 100644
137
--- a/exec.c
138
+++ b/exec.c
139
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *system_io;
140
AddressSpace address_space_io;
141
AddressSpace address_space_memory;
142
143
-MemoryRegion io_mem_rom, io_mem_notdirty;
144
+MemoryRegion io_mem_notdirty;
145
static MemoryRegion io_mem_unassigned;
146
#endif
147
148
@@ -XXX,XX +XXX,XX @@ typedef struct subpage_t {
149
150
#define PHYS_SECTION_UNASSIGNED 0
151
#define PHYS_SECTION_NOTDIRTY 1
152
-#define PHYS_SECTION_ROM 2
153
154
static void io_mem_init(void);
155
static void memory_map_init(void);
156
@@ -XXX,XX +XXX,XX @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu,
157
iotlb = memory_region_get_ram_addr(section->mr) + xlat;
158
if (!section->readonly) {
159
iotlb |= PHYS_SECTION_NOTDIRTY;
160
- } else {
161
- iotlb |= PHYS_SECTION_ROM;
162
}
163
} else {
164
AddressSpaceDispatch *d;
165
@@ -XXX,XX +XXX,XX @@ static uint16_t dummy_section(PhysPageMap *map, FlatView *fv, MemoryRegion *mr)
166
return phys_section_add(map, &section);
167
}
168
169
-static void readonly_mem_write(void *opaque, hwaddr addr,
170
- uint64_t val, unsigned size)
171
-{
172
- /* Ignore any write to ROM. */
173
-}
174
-
175
-static bool readonly_mem_accepts(void *opaque, hwaddr addr,
176
- unsigned size, bool is_write,
177
- MemTxAttrs attrs)
178
-{
179
- return is_write;
180
-}
181
-
182
-/* This will only be used for writes, because reads are special cased
183
- * to directly access the underlying host ram.
184
- */
185
-static const MemoryRegionOps readonly_mem_ops = {
186
- .write = readonly_mem_write,
187
- .valid.accepts = readonly_mem_accepts,
188
- .endianness = DEVICE_NATIVE_ENDIAN,
189
- .valid = {
190
- .min_access_size = 1,
191
- .max_access_size = 8,
192
- .unaligned = false,
193
- },
194
- .impl = {
195
- .min_access_size = 1,
196
- .max_access_size = 8,
197
- .unaligned = false,
198
- },
199
-};
200
-
201
MemoryRegionSection *iotlb_to_section(CPUState *cpu,
202
hwaddr index, MemTxAttrs attrs)
203
{
204
@@ -XXX,XX +XXX,XX @@ MemoryRegionSection *iotlb_to_section(CPUState *cpu,
205
206
static void io_mem_init(void)
207
{
208
- memory_region_init_io(&io_mem_rom, NULL, &readonly_mem_ops,
209
- NULL, NULL, UINT64_MAX);
210
memory_region_init_io(&io_mem_unassigned, NULL, &unassigned_mem_ops, NULL,
211
NULL, UINT64_MAX);
212
213
@@ -XXX,XX +XXX,XX @@ AddressSpaceDispatch *address_space_dispatch_new(FlatView *fv)
214
assert(n == PHYS_SECTION_UNASSIGNED);
215
n = dummy_section(&d->map, fv, &io_mem_notdirty);
216
assert(n == PHYS_SECTION_NOTDIRTY);
217
- n = dummy_section(&d->map, fv, &io_mem_rom);
218
- assert(n == PHYS_SECTION_ROM);
219
220
d->phys_map = (PhysPageEntry) { .ptr = PHYS_MAP_NODE_NIL, .skip = 1 };
221
222
--
223
2.17.1
224
225
diff view generated by jsdifflib
Deleted patch
1
Pages that we want to track for NOTDIRTY are RAM. We do not
2
really need to go through the I/O path to handle them.
3
1
4
Acked-by: David Hildenbrand <david@redhat.com>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
include/exec/cpu-common.h | 2 --
10
accel/tcg/cputlb.c | 26 +++++++++++++++++---
11
exec.c | 50 ---------------------------------------
12
memory.c | 16 -------------
13
4 files changed, 23 insertions(+), 71 deletions(-)
14
15
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/exec/cpu-common.h
18
+++ b/include/exec/cpu-common.h
19
@@ -XXX,XX +XXX,XX @@ void qemu_flush_coalesced_mmio_buffer(void);
20
21
void cpu_flush_icache_range(hwaddr start, hwaddr len);
22
23
-extern struct MemoryRegion io_mem_notdirty;
24
-
25
typedef int (RAMBlockIterFunc)(RAMBlock *rb, void *opaque);
26
27
int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque);
28
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/accel/tcg/cputlb.c
31
+++ b/accel/tcg/cputlb.c
32
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
33
mr = section->mr;
34
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
35
cpu->mem_io_pc = retaddr;
36
- if (mr != &io_mem_notdirty && !cpu->can_do_io) {
37
+ if (!cpu->can_do_io) {
38
cpu_io_recompile(cpu, retaddr);
39
}
40
41
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
42
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
43
mr = section->mr;
44
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
45
- if (mr != &io_mem_notdirty && !cpu->can_do_io) {
46
+ if (!cpu->can_do_io) {
47
cpu_io_recompile(cpu, retaddr);
48
}
49
cpu->mem_io_vaddr = addr;
50
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
51
need_swap = size > 1 && (tlb_addr & TLB_BSWAP);
52
53
/* Handle I/O access. */
54
- if (likely(tlb_addr & (TLB_MMIO | TLB_NOTDIRTY))) {
55
+ if (tlb_addr & TLB_MMIO) {
56
io_writex(env, iotlbentry, mmu_idx, val, addr, retaddr,
57
op ^ (need_swap * MO_BSWAP));
58
return;
59
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
60
61
haddr = (void *)((uintptr_t)addr + entry->addend);
62
63
+ /* Handle clean RAM pages. */
64
+ if (tlb_addr & TLB_NOTDIRTY) {
65
+ NotDirtyInfo ndi;
66
+
67
+ /* We require mem_io_pc in tb_invalidate_phys_page_range. */
68
+ env_cpu(env)->mem_io_pc = retaddr;
69
+
70
+ memory_notdirty_write_prepare(&ndi, env_cpu(env), addr,
71
+ addr + iotlbentry->addr, size);
72
+
73
+ if (unlikely(need_swap)) {
74
+ store_memop(haddr, val, op ^ MO_BSWAP);
75
+ } else {
76
+ store_memop(haddr, val, op);
77
+ }
78
+
79
+ memory_notdirty_write_complete(&ndi);
80
+ return;
81
+ }
82
+
83
/*
84
* Keep these two store_memop separate to ensure that the compiler
85
* is able to fold the entire function to a single instruction.
86
diff --git a/exec.c b/exec.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/exec.c
89
+++ b/exec.c
90
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *system_io;
91
AddressSpace address_space_io;
92
AddressSpace address_space_memory;
93
94
-MemoryRegion io_mem_notdirty;
95
static MemoryRegion io_mem_unassigned;
96
#endif
97
98
@@ -XXX,XX +XXX,XX @@ typedef struct subpage_t {
99
} subpage_t;
100
101
#define PHYS_SECTION_UNASSIGNED 0
102
-#define PHYS_SECTION_NOTDIRTY 1
103
104
static void io_mem_init(void);
105
static void memory_map_init(void);
106
@@ -XXX,XX +XXX,XX @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu,
107
if (memory_region_is_ram(section->mr)) {
108
/* Normal RAM. */
109
iotlb = memory_region_get_ram_addr(section->mr) + xlat;
110
- if (!section->readonly) {
111
- iotlb |= PHYS_SECTION_NOTDIRTY;
112
- }
113
} else {
114
AddressSpaceDispatch *d;
115
116
@@ -XXX,XX +XXX,XX @@ void memory_notdirty_write_complete(NotDirtyInfo *ndi)
117
}
118
}
119
120
-/* Called within RCU critical section. */
121
-static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
122
- uint64_t val, unsigned size)
123
-{
124
- NotDirtyInfo ndi;
125
-
126
- memory_notdirty_write_prepare(&ndi, current_cpu, current_cpu->mem_io_vaddr,
127
- ram_addr, size);
128
-
129
- stn_p(qemu_map_ram_ptr(NULL, ram_addr), size, val);
130
- memory_notdirty_write_complete(&ndi);
131
-}
132
-
133
-static bool notdirty_mem_accepts(void *opaque, hwaddr addr,
134
- unsigned size, bool is_write,
135
- MemTxAttrs attrs)
136
-{
137
- return is_write;
138
-}
139
-
140
-static const MemoryRegionOps notdirty_mem_ops = {
141
- .write = notdirty_mem_write,
142
- .valid.accepts = notdirty_mem_accepts,
143
- .endianness = DEVICE_NATIVE_ENDIAN,
144
- .valid = {
145
- .min_access_size = 1,
146
- .max_access_size = 8,
147
- .unaligned = false,
148
- },
149
- .impl = {
150
- .min_access_size = 1,
151
- .max_access_size = 8,
152
- .unaligned = false,
153
- },
154
-};
155
-
156
/* Generate a debug exception if a watchpoint has been hit. */
157
void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
158
MemTxAttrs attrs, int flags, uintptr_t ra)
159
@@ -XXX,XX +XXX,XX @@ static void io_mem_init(void)
160
{
161
memory_region_init_io(&io_mem_unassigned, NULL, &unassigned_mem_ops, NULL,
162
NULL, UINT64_MAX);
163
-
164
- /* io_mem_notdirty calls tb_invalidate_phys_page_fast,
165
- * which can be called without the iothread mutex.
166
- */
167
- memory_region_init_io(&io_mem_notdirty, NULL, &notdirty_mem_ops, NULL,
168
- NULL, UINT64_MAX);
169
- memory_region_clear_global_locking(&io_mem_notdirty);
170
}
171
172
AddressSpaceDispatch *address_space_dispatch_new(FlatView *fv)
173
@@ -XXX,XX +XXX,XX @@ AddressSpaceDispatch *address_space_dispatch_new(FlatView *fv)
174
175
n = dummy_section(&d->map, fv, &io_mem_unassigned);
176
assert(n == PHYS_SECTION_UNASSIGNED);
177
- n = dummy_section(&d->map, fv, &io_mem_notdirty);
178
- assert(n == PHYS_SECTION_NOTDIRTY);
179
180
d->phys_map = (PhysPageEntry) { .ptr = PHYS_MAP_NODE_NIL, .skip = 1 };
181
182
diff --git a/memory.c b/memory.c
183
index XXXXXXX..XXXXXXX 100644
184
--- a/memory.c
185
+++ b/memory.c
186
@@ -XXX,XX +XXX,XX @@ static MemTxResult memory_region_read_accessor(MemoryRegion *mr,
187
tmp = mr->ops->read(mr->opaque, addr, size);
188
if (mr->subpage) {
189
trace_memory_region_subpage_read(get_cpu_index(), mr, addr, tmp, size);
190
- } else if (mr == &io_mem_notdirty) {
191
- /* Accesses to code which has previously been translated into a TB show
192
- * up in the MMIO path, as accesses to the io_mem_notdirty
193
- * MemoryRegion. */
194
} else if (TRACE_MEMORY_REGION_OPS_READ_ENABLED) {
195
hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr);
196
trace_memory_region_ops_read(get_cpu_index(), mr, abs_addr, tmp, size);
197
@@ -XXX,XX +XXX,XX @@ static MemTxResult memory_region_read_with_attrs_accessor(MemoryRegion *mr,
198
r = mr->ops->read_with_attrs(mr->opaque, addr, &tmp, size, attrs);
199
if (mr->subpage) {
200
trace_memory_region_subpage_read(get_cpu_index(), mr, addr, tmp, size);
201
- } else if (mr == &io_mem_notdirty) {
202
- /* Accesses to code which has previously been translated into a TB show
203
- * up in the MMIO path, as accesses to the io_mem_notdirty
204
- * MemoryRegion. */
205
} else if (TRACE_MEMORY_REGION_OPS_READ_ENABLED) {
206
hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr);
207
trace_memory_region_ops_read(get_cpu_index(), mr, abs_addr, tmp, size);
208
@@ -XXX,XX +XXX,XX @@ static MemTxResult memory_region_write_accessor(MemoryRegion *mr,
209
210
if (mr->subpage) {
211
trace_memory_region_subpage_write(get_cpu_index(), mr, addr, tmp, size);
212
- } else if (mr == &io_mem_notdirty) {
213
- /* Accesses to code which has previously been translated into a TB show
214
- * up in the MMIO path, as accesses to the io_mem_notdirty
215
- * MemoryRegion. */
216
} else if (TRACE_MEMORY_REGION_OPS_WRITE_ENABLED) {
217
hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr);
218
trace_memory_region_ops_write(get_cpu_index(), mr, abs_addr, tmp, size);
219
@@ -XXX,XX +XXX,XX @@ static MemTxResult memory_region_write_with_attrs_accessor(MemoryRegion *mr,
220
221
if (mr->subpage) {
222
trace_memory_region_subpage_write(get_cpu_index(), mr, addr, tmp, size);
223
- } else if (mr == &io_mem_notdirty) {
224
- /* Accesses to code which has previously been translated into a TB show
225
- * up in the MMIO path, as accesses to the io_mem_notdirty
226
- * MemoryRegion. */
227
} else if (TRACE_MEMORY_REGION_OPS_WRITE_ENABLED) {
228
hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr);
229
trace_memory_region_ops_write(get_cpu_index(), mr, abs_addr, tmp, size);
230
--
231
2.17.1
232
233
diff view generated by jsdifflib
Deleted patch
1
There is only one caller, tlb_set_page_with_attrs. We cannot
2
inline the entire function because the AddressSpaceDispatch
3
structure is private to exec.c, and cannot easily be moved to
4
include/exec/memory-internal.h.
5
1
6
Compute is_ram and is_romd once within tlb_set_page_with_attrs.
7
Fold the number of tests against these predicates. Compute
8
cpu_physical_memory_is_clean outside of the tlb lock region.
9
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
---
13
include/exec/exec-all.h | 6 +---
14
accel/tcg/cputlb.c | 68 ++++++++++++++++++++++++++---------------
15
exec.c | 22 ++-----------
16
3 files changed, 47 insertions(+), 49 deletions(-)
17
18
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/exec/exec-all.h
21
+++ b/include/exec/exec-all.h
22
@@ -XXX,XX +XXX,XX @@ address_space_translate_for_iotlb(CPUState *cpu, int asidx, hwaddr addr,
23
hwaddr *xlat, hwaddr *plen,
24
MemTxAttrs attrs, int *prot);
25
hwaddr memory_region_section_get_iotlb(CPUState *cpu,
26
- MemoryRegionSection *section,
27
- target_ulong vaddr,
28
- hwaddr paddr, hwaddr xlat,
29
- int prot,
30
- target_ulong *address);
31
+ MemoryRegionSection *section);
32
#endif
33
34
/* vl.c */
35
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/accel/tcg/cputlb.c
38
+++ b/accel/tcg/cputlb.c
39
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
40
MemoryRegionSection *section;
41
unsigned int index;
42
target_ulong address;
43
- target_ulong code_address;
44
+ target_ulong write_address;
45
uintptr_t addend;
46
CPUTLBEntry *te, tn;
47
hwaddr iotlb, xlat, sz, paddr_page;
48
target_ulong vaddr_page;
49
int asidx = cpu_asidx_from_attrs(cpu, attrs);
50
int wp_flags;
51
+ bool is_ram, is_romd;
52
53
assert_cpu_is_self(cpu);
54
55
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
56
if (attrs.byte_swap) {
57
address |= TLB_BSWAP;
58
}
59
- if (!memory_region_is_ram(section->mr) &&
60
- !memory_region_is_romd(section->mr)) {
61
- /* IO memory case */
62
- address |= TLB_MMIO;
63
- addend = 0;
64
- } else {
65
+
66
+ is_ram = memory_region_is_ram(section->mr);
67
+ is_romd = memory_region_is_romd(section->mr);
68
+
69
+ if (is_ram || is_romd) {
70
+ /* RAM and ROMD both have associated host memory. */
71
addend = (uintptr_t)memory_region_get_ram_ptr(section->mr) + xlat;
72
+ } else {
73
+ /* I/O does not; force the host address to NULL. */
74
+ addend = 0;
75
+ }
76
+
77
+ write_address = address;
78
+ if (is_ram) {
79
+ iotlb = memory_region_get_ram_addr(section->mr) + xlat;
80
+ /*
81
+ * Computing is_clean is expensive; avoid all that unless
82
+ * the page is actually writable.
83
+ */
84
+ if (prot & PAGE_WRITE) {
85
+ if (section->readonly) {
86
+ write_address |= TLB_DISCARD_WRITE;
87
+ } else if (cpu_physical_memory_is_clean(iotlb)) {
88
+ write_address |= TLB_NOTDIRTY;
89
+ }
90
+ }
91
+ } else {
92
+ /* I/O or ROMD */
93
+ iotlb = memory_region_section_get_iotlb(cpu, section) + xlat;
94
+ /*
95
+ * Writes to romd devices must go through MMIO to enable write.
96
+ * Reads to romd devices go through the ram_ptr found above,
97
+ * but of course reads to I/O must go through MMIO.
98
+ */
99
+ write_address |= TLB_MMIO;
100
+ if (!is_romd) {
101
+ address = write_address;
102
+ }
103
}
104
105
- code_address = address;
106
- iotlb = memory_region_section_get_iotlb(cpu, section, vaddr_page,
107
- paddr_page, xlat, prot, &address);
108
wp_flags = cpu_watchpoint_address_matches(cpu, vaddr_page,
109
TARGET_PAGE_SIZE);
110
111
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
112
/*
113
* At this point iotlb contains a physical section number in the lower
114
* TARGET_PAGE_BITS, and either
115
- * + the ram_addr_t of the page base of the target RAM (if NOTDIRTY or ROM)
116
- * + the offset within section->mr of the page base (otherwise)
117
+ * + the ram_addr_t of the page base of the target RAM (RAM)
118
+ * + the offset within section->mr of the page base (I/O, ROMD)
119
* We subtract the vaddr_page (which is page aligned and thus won't
120
* disturb the low bits) to give an offset which can be added to the
121
* (non-page-aligned) vaddr of the eventual memory access to get
122
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
123
}
124
125
if (prot & PAGE_EXEC) {
126
- tn.addr_code = code_address;
127
+ tn.addr_code = address;
128
} else {
129
tn.addr_code = -1;
130
}
131
132
tn.addr_write = -1;
133
if (prot & PAGE_WRITE) {
134
- tn.addr_write = address;
135
- if (memory_region_is_romd(section->mr)) {
136
- /* Use the MMIO path so that the device can switch states. */
137
- tn.addr_write |= TLB_MMIO;
138
- } else if (memory_region_is_ram(section->mr)) {
139
- if (section->readonly) {
140
- tn.addr_write |= TLB_DISCARD_WRITE;
141
- } else if (cpu_physical_memory_is_clean(
142
- memory_region_get_ram_addr(section->mr) + xlat)) {
143
- tn.addr_write |= TLB_NOTDIRTY;
144
- }
145
- }
146
+ tn.addr_write = write_address;
147
if (prot & PAGE_WRITE_INV) {
148
tn.addr_write |= TLB_INVALID_MASK;
149
}
150
diff --git a/exec.c b/exec.c
151
index XXXXXXX..XXXXXXX 100644
152
--- a/exec.c
153
+++ b/exec.c
154
@@ -XXX,XX +XXX,XX @@ bool cpu_physical_memory_snapshot_get_dirty(DirtyBitmapSnapshot *snap,
155
156
/* Called from RCU critical section */
157
hwaddr memory_region_section_get_iotlb(CPUState *cpu,
158
- MemoryRegionSection *section,
159
- target_ulong vaddr,
160
- hwaddr paddr, hwaddr xlat,
161
- int prot,
162
- target_ulong *address)
163
+ MemoryRegionSection *section)
164
{
165
- hwaddr iotlb;
166
-
167
- if (memory_region_is_ram(section->mr)) {
168
- /* Normal RAM. */
169
- iotlb = memory_region_get_ram_addr(section->mr) + xlat;
170
- } else {
171
- AddressSpaceDispatch *d;
172
-
173
- d = flatview_to_dispatch(section->fv);
174
- iotlb = section - d->map.sections;
175
- iotlb += xlat;
176
- }
177
-
178
- return iotlb;
179
+ AddressSpaceDispatch *d = flatview_to_dispatch(section->fv);
180
+ return section - d->map.sections;
181
}
182
#endif /* defined(CONFIG_USER_ONLY) */
183
184
--
185
2.17.1
186
187
diff view generated by jsdifflib
Deleted patch
1
Since 9458a9a1df1a, all readers of the dirty bitmaps wait
2
for the rcu lock, which means that they wait until the end
3
of any executing TranslationBlock.
4
1
5
As a consequence, there is no need for the actual access
6
to happen in between the _prepare and _complete. Therefore,
7
we can improve things by merging the two functions into
8
notdirty_write and dropping the NotDirtyInfo structure.
9
10
In addition, the only users of notdirty_write are in cputlb.c,
11
so move the merged function there. Pass in the CPUIOTLBEntry
12
from which the ram_addr_t may be computed.
13
14
Reviewed-by: David Hildenbrand <david@redhat.com>
15
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
16
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
17
---
18
include/exec/memory-internal.h | 65 -----------------------------
19
accel/tcg/cputlb.c | 76 +++++++++++++++++++---------------
20
exec.c | 44 --------------------
21
3 files changed, 42 insertions(+), 143 deletions(-)
22
23
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/exec/memory-internal.h
26
+++ b/include/exec/memory-internal.h
27
@@ -XXX,XX +XXX,XX @@ void address_space_dispatch_free(AddressSpaceDispatch *d);
28
29
void mtree_print_dispatch(struct AddressSpaceDispatch *d,
30
MemoryRegion *root);
31
-
32
-struct page_collection;
33
-
34
-/* Opaque struct for passing info from memory_notdirty_write_prepare()
35
- * to memory_notdirty_write_complete(). Callers should treat all fields
36
- * as private, with the exception of @active.
37
- *
38
- * @active is a field which is not touched by either the prepare or
39
- * complete functions, but which the caller can use if it wishes to
40
- * track whether it has called prepare for this struct and so needs
41
- * to later call the complete function.
42
- */
43
-typedef struct {
44
- CPUState *cpu;
45
- struct page_collection *pages;
46
- ram_addr_t ram_addr;
47
- vaddr mem_vaddr;
48
- unsigned size;
49
- bool active;
50
-} NotDirtyInfo;
51
-
52
-/**
53
- * memory_notdirty_write_prepare: call before writing to non-dirty memory
54
- * @ndi: pointer to opaque NotDirtyInfo struct
55
- * @cpu: CPU doing the write
56
- * @mem_vaddr: virtual address of write
57
- * @ram_addr: the ram address of the write
58
- * @size: size of write in bytes
59
- *
60
- * Any code which writes to the host memory corresponding to
61
- * guest RAM which has been marked as NOTDIRTY must wrap those
62
- * writes in calls to memory_notdirty_write_prepare() and
63
- * memory_notdirty_write_complete():
64
- *
65
- * NotDirtyInfo ndi;
66
- * memory_notdirty_write_prepare(&ndi, ....);
67
- * ... perform write here ...
68
- * memory_notdirty_write_complete(&ndi);
69
- *
70
- * These calls will ensure that we flush any TCG translated code for
71
- * the memory being written, update the dirty bits and (if possible)
72
- * remove the slowpath callback for writing to the memory.
73
- *
74
- * This must only be called if we are using TCG; it will assert otherwise.
75
- *
76
- * We may take locks in the prepare call, so callers must ensure that
77
- * they don't exit (via longjump or otherwise) without calling complete.
78
- *
79
- * This call must only be made inside an RCU critical section.
80
- * (Note that while we're executing a TCG TB we're always in an
81
- * RCU critical section, which is likely to be the case for callers
82
- * of these functions.)
83
- */
84
-void memory_notdirty_write_prepare(NotDirtyInfo *ndi,
85
- CPUState *cpu,
86
- vaddr mem_vaddr,
87
- ram_addr_t ram_addr,
88
- unsigned size);
89
-/**
90
- * memory_notdirty_write_complete: finish write to non-dirty memory
91
- * @ndi: pointer to the opaque NotDirtyInfo struct which was initialized
92
- * by memory_not_dirty_write_prepare().
93
- */
94
-void memory_notdirty_write_complete(NotDirtyInfo *ndi);
95
-
96
#endif
97
#endif
98
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/accel/tcg/cputlb.c
101
+++ b/accel/tcg/cputlb.c
102
@@ -XXX,XX +XXX,XX @@
103
#include "exec/helper-proto.h"
104
#include "qemu/atomic.h"
105
#include "qemu/atomic128.h"
106
+#include "translate-all.h"
107
108
/* DEBUG defines, enable DEBUG_TLB_LOG to log to the CPU_LOG_MMU target */
109
/* #define DEBUG_TLB */
110
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
111
return qemu_ram_addr_from_host_nofail(p);
112
}
113
114
+static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size,
115
+ CPUIOTLBEntry *iotlbentry, uintptr_t retaddr)
116
+{
117
+ ram_addr_t ram_addr = mem_vaddr + iotlbentry->addr;
118
+
119
+ trace_memory_notdirty_write_access(mem_vaddr, ram_addr, size);
120
+
121
+ if (!cpu_physical_memory_get_dirty_flag(ram_addr, DIRTY_MEMORY_CODE)) {
122
+ struct page_collection *pages
123
+ = page_collection_lock(ram_addr, ram_addr + size);
124
+
125
+ /* We require mem_io_pc in tb_invalidate_phys_page_range. */
126
+ cpu->mem_io_pc = retaddr;
127
+
128
+ tb_invalidate_phys_page_fast(pages, ram_addr, size);
129
+ page_collection_unlock(pages);
130
+ }
131
+
132
+ /*
133
+ * Set both VGA and migration bits for simplicity and to remove
134
+ * the notdirty callback faster.
135
+ */
136
+ cpu_physical_memory_set_dirty_range(ram_addr, size, DIRTY_CLIENTS_NOCODE);
137
+
138
+ /* We remove the notdirty callback only if the code has been flushed. */
139
+ if (!cpu_physical_memory_is_clean(ram_addr)) {
140
+ trace_memory_notdirty_set_dirty(mem_vaddr);
141
+ tlb_set_dirty(cpu, mem_vaddr);
142
+ }
143
+}
144
+
145
/*
146
* Probe for whether the specified guest access is permitted. If it is not
147
* permitted then an exception will be taken in the same way as if this
148
@@ -XXX,XX +XXX,XX @@ void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
149
/* Probe for a read-modify-write atomic operation. Do not allow unaligned
150
* operations, or io operations to proceed. Return the host address. */
151
static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
152
- TCGMemOpIdx oi, uintptr_t retaddr,
153
- NotDirtyInfo *ndi)
154
+ TCGMemOpIdx oi, uintptr_t retaddr)
155
{
156
size_t mmu_idx = get_mmuidx(oi);
157
uintptr_t index = tlb_index(env, mmu_idx, addr);
158
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
159
160
hostaddr = (void *)((uintptr_t)addr + tlbe->addend);
161
162
- ndi->active = false;
163
if (unlikely(tlb_addr & TLB_NOTDIRTY)) {
164
- ndi->active = true;
165
- memory_notdirty_write_prepare(ndi, env_cpu(env), addr,
166
- qemu_ram_addr_from_host_nofail(hostaddr),
167
- 1 << s_bits);
168
+ notdirty_write(env_cpu(env), addr, 1 << s_bits,
169
+ &env_tlb(env)->d[mmu_idx].iotlb[index], retaddr);
170
}
171
172
return hostaddr;
173
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
174
return;
175
}
176
177
- haddr = (void *)((uintptr_t)addr + entry->addend);
178
-
179
/* Handle clean RAM pages. */
180
if (tlb_addr & TLB_NOTDIRTY) {
181
- NotDirtyInfo ndi;
182
-
183
- /* We require mem_io_pc in tb_invalidate_phys_page_range. */
184
- env_cpu(env)->mem_io_pc = retaddr;
185
-
186
- memory_notdirty_write_prepare(&ndi, env_cpu(env), addr,
187
- addr + iotlbentry->addr, size);
188
-
189
- if (unlikely(need_swap)) {
190
- store_memop(haddr, val, op ^ MO_BSWAP);
191
- } else {
192
- store_memop(haddr, val, op);
193
- }
194
-
195
- memory_notdirty_write_complete(&ndi);
196
- return;
197
+ notdirty_write(env_cpu(env), addr, size, iotlbentry, retaddr);
198
}
199
200
+ haddr = (void *)((uintptr_t)addr + entry->addend);
201
+
202
/*
203
* Keep these two store_memop separate to ensure that the compiler
204
* is able to fold the entire function to a single instruction.
205
@@ -XXX,XX +XXX,XX @@ void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
206
#define EXTRA_ARGS , TCGMemOpIdx oi, uintptr_t retaddr
207
#define ATOMIC_NAME(X) \
208
HELPER(glue(glue(glue(atomic_ ## X, SUFFIX), END), _mmu))
209
-#define ATOMIC_MMU_DECLS NotDirtyInfo ndi
210
-#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, oi, retaddr, &ndi)
211
-#define ATOMIC_MMU_CLEANUP \
212
- do { \
213
- if (unlikely(ndi.active)) { \
214
- memory_notdirty_write_complete(&ndi); \
215
- } \
216
- } while (0)
217
+#define ATOMIC_MMU_DECLS
218
+#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, oi, retaddr)
219
+#define ATOMIC_MMU_CLEANUP
220
221
#define DATA_SIZE 1
222
#include "atomic_template.h"
223
@@ -XXX,XX +XXX,XX @@ void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
224
#undef ATOMIC_MMU_LOOKUP
225
#define EXTRA_ARGS , TCGMemOpIdx oi
226
#define ATOMIC_NAME(X) HELPER(glue(glue(atomic_ ## X, SUFFIX), END))
227
-#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, oi, GETPC(), &ndi)
228
+#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, oi, GETPC())
229
230
#define DATA_SIZE 1
231
#include "atomic_template.h"
232
diff --git a/exec.c b/exec.c
233
index XXXXXXX..XXXXXXX 100644
234
--- a/exec.c
235
+++ b/exec.c
236
@@ -XXX,XX +XXX,XX @@ ram_addr_t qemu_ram_addr_from_host(void *ptr)
237
return block->offset + offset;
238
}
239
240
-/* Called within RCU critical section. */
241
-void memory_notdirty_write_prepare(NotDirtyInfo *ndi,
242
- CPUState *cpu,
243
- vaddr mem_vaddr,
244
- ram_addr_t ram_addr,
245
- unsigned size)
246
-{
247
- ndi->cpu = cpu;
248
- ndi->ram_addr = ram_addr;
249
- ndi->mem_vaddr = mem_vaddr;
250
- ndi->size = size;
251
- ndi->pages = NULL;
252
-
253
- trace_memory_notdirty_write_access(mem_vaddr, ram_addr, size);
254
-
255
- assert(tcg_enabled());
256
- if (!cpu_physical_memory_get_dirty_flag(ram_addr, DIRTY_MEMORY_CODE)) {
257
- ndi->pages = page_collection_lock(ram_addr, ram_addr + size);
258
- tb_invalidate_phys_page_fast(ndi->pages, ram_addr, size);
259
- }
260
-}
261
-
262
-/* Called within RCU critical section. */
263
-void memory_notdirty_write_complete(NotDirtyInfo *ndi)
264
-{
265
- if (ndi->pages) {
266
- assert(tcg_enabled());
267
- page_collection_unlock(ndi->pages);
268
- ndi->pages = NULL;
269
- }
270
-
271
- /* Set both VGA and migration bits for simplicity and to remove
272
- * the notdirty callback faster.
273
- */
274
- cpu_physical_memory_set_dirty_range(ndi->ram_addr, ndi->size,
275
- DIRTY_CLIENTS_NOCODE);
276
- /* we remove the notdirty callback only if the code has been
277
- flushed */
278
- if (!cpu_physical_memory_is_clean(ndi->ram_addr)) {
279
- trace_memory_notdirty_set_dirty(ndi->mem_vaddr);
280
- tlb_set_dirty(ndi->cpu, ndi->mem_vaddr);
281
- }
282
-}
283
-
284
/* Generate a debug exception if a watchpoint has been hit. */
285
void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
286
MemTxAttrs attrs, int flags, uintptr_t ra)
287
--
288
2.17.1
289
290
diff view generated by jsdifflib
Deleted patch
1
We can use notdirty_write for the write and return a valid host
2
pointer for this case.
3
1
4
Reviewed-by: David Hildenbrand <david@redhat.com>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
accel/tcg/cputlb.c | 26 +++++++++++++++++---------
9
1 file changed, 17 insertions(+), 9 deletions(-)
10
11
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/accel/tcg/cputlb.c
14
+++ b/accel/tcg/cputlb.c
15
@@ -XXX,XX +XXX,XX @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
16
return NULL;
17
}
18
19
- /* Handle watchpoints. */
20
- if (tlb_addr & TLB_WATCHPOINT) {
21
- cpu_check_watchpoint(env_cpu(env), addr, size,
22
- env_tlb(env)->d[mmu_idx].iotlb[index].attrs,
23
- wp_access, retaddr);
24
- }
25
+ if (unlikely(tlb_addr & TLB_FLAGS_MASK)) {
26
+ CPUIOTLBEntry *iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
27
28
- /* Reject I/O access, or other required slow-path. */
29
- if (tlb_addr & (TLB_NOTDIRTY | TLB_MMIO | TLB_BSWAP | TLB_DISCARD_WRITE)) {
30
- return NULL;
31
+ /* Reject I/O access, or other required slow-path. */
32
+ if (tlb_addr & (TLB_MMIO | TLB_BSWAP | TLB_DISCARD_WRITE)) {
33
+ return NULL;
34
+ }
35
+
36
+ /* Handle watchpoints. */
37
+ if (tlb_addr & TLB_WATCHPOINT) {
38
+ cpu_check_watchpoint(env_cpu(env), addr, size,
39
+ iotlbentry->attrs, wp_access, retaddr);
40
+ }
41
+
42
+ /* Handle clean RAM pages. */
43
+ if (tlb_addr & TLB_NOTDIRTY) {
44
+ notdirty_write(env_cpu(env), addr, size, iotlbentry, retaddr);
45
+ }
46
}
47
48
return (void *)((uintptr_t)addr + entry->addend);
49
--
50
2.17.1
51
52
diff view generated by jsdifflib
Deleted patch
1
With the merge of notdirty handling into store_helper,
2
the last user of cpu->mem_io_vaddr was removed.
3
1
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: David Hildenbrand <david@redhat.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
include/hw/core/cpu.h | 2 --
9
accel/tcg/cputlb.c | 2 --
10
hw/core/cpu.c | 1 -
11
3 files changed, 5 deletions(-)
12
13
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/core/cpu.h
16
+++ b/include/hw/core/cpu.h
17
@@ -XXX,XX +XXX,XX @@ struct qemu_work_item;
18
* @next_cpu: Next CPU sharing TB cache.
19
* @opaque: User data.
20
* @mem_io_pc: Host Program Counter at which the memory was accessed.
21
- * @mem_io_vaddr: Target virtual address at which the memory was accessed.
22
* @kvm_fd: vCPU file descriptor for KVM.
23
* @work_mutex: Lock to prevent multiple access to queued_work_*.
24
* @queued_work_first: First asynchronous work pending.
25
@@ -XXX,XX +XXX,XX @@ struct CPUState {
26
* we store some rarely used information in the CPU context.
27
*/
28
uintptr_t mem_io_pc;
29
- vaddr mem_io_vaddr;
30
/*
31
* This is only needed for the legacy cpu_unassigned_access() hook;
32
* when all targets using it have been converted to use
33
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/accel/tcg/cputlb.c
36
+++ b/accel/tcg/cputlb.c
37
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
38
cpu_io_recompile(cpu, retaddr);
39
}
40
41
- cpu->mem_io_vaddr = addr;
42
cpu->mem_io_access_type = access_type;
43
44
if (mr->global_locking && !qemu_mutex_iothread_locked()) {
45
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
46
if (!cpu->can_do_io) {
47
cpu_io_recompile(cpu, retaddr);
48
}
49
- cpu->mem_io_vaddr = addr;
50
cpu->mem_io_pc = retaddr;
51
52
if (mr->global_locking && !qemu_mutex_iothread_locked()) {
53
diff --git a/hw/core/cpu.c b/hw/core/cpu.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/hw/core/cpu.c
56
+++ b/hw/core/cpu.c
57
@@ -XXX,XX +XXX,XX @@ static void cpu_common_reset(CPUState *cpu)
58
cpu->interrupt_request = 0;
59
cpu->halted = 0;
60
cpu->mem_io_pc = 0;
61
- cpu->mem_io_vaddr = 0;
62
cpu->icount_extra = 0;
63
atomic_set(&cpu->icount_decr_ptr->u32, 0);
64
cpu->can_do_io = 1;
65
--
66
2.17.1
67
68
diff view generated by jsdifflib
Deleted patch
1
All callers pass false to this argument. Remove it and pass the
2
constant on to tb_invalidate_phys_page_range__locked.
3
1
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: David Hildenbrand <david@redhat.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
accel/tcg/translate-all.h | 3 +--
9
accel/tcg/translate-all.c | 6 ++----
10
exec.c | 4 ++--
11
3 files changed, 5 insertions(+), 8 deletions(-)
12
13
diff --git a/accel/tcg/translate-all.h b/accel/tcg/translate-all.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/accel/tcg/translate-all.h
16
+++ b/accel/tcg/translate-all.h
17
@@ -XXX,XX +XXX,XX @@ struct page_collection *page_collection_lock(tb_page_addr_t start,
18
void page_collection_unlock(struct page_collection *set);
19
void tb_invalidate_phys_page_fast(struct page_collection *pages,
20
tb_page_addr_t start, int len);
21
-void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
22
- int is_cpu_write_access);
23
+void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end);
24
void tb_check_watchpoint(CPUState *cpu);
25
26
#ifdef CONFIG_USER_ONLY
27
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/accel/tcg/translate-all.c
30
+++ b/accel/tcg/translate-all.c
31
@@ -XXX,XX +XXX,XX @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
32
*
33
* Called with mmap_lock held for user-mode emulation
34
*/
35
-void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
36
- int is_cpu_write_access)
37
+void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end)
38
{
39
struct page_collection *pages;
40
PageDesc *p;
41
@@ -XXX,XX +XXX,XX @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
42
return;
43
}
44
pages = page_collection_lock(start, end);
45
- tb_invalidate_phys_page_range__locked(pages, p, start, end,
46
- is_cpu_write_access);
47
+ tb_invalidate_phys_page_range__locked(pages, p, start, end, 0);
48
page_collection_unlock(pages);
49
}
50
51
diff --git a/exec.c b/exec.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/exec.c
54
+++ b/exec.c
55
@@ -XXX,XX +XXX,XX @@ const char *parse_cpu_option(const char *cpu_option)
56
void tb_invalidate_phys_addr(target_ulong addr)
57
{
58
mmap_lock();
59
- tb_invalidate_phys_page_range(addr, addr + 1, 0);
60
+ tb_invalidate_phys_page_range(addr, addr + 1);
61
mmap_unlock();
62
}
63
64
@@ -XXX,XX +XXX,XX @@ void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs)
65
return;
66
}
67
ram_addr = memory_region_get_ram_addr(mr) + addr;
68
- tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
69
+ tb_invalidate_phys_page_range(ram_addr, ram_addr + 1);
70
rcu_read_unlock();
71
}
72
73
--
74
2.17.1
75
76
diff view generated by jsdifflib
Deleted patch
1
Rather than rely on cpu->mem_io_pc, pass retaddr down directly.
2
1
3
Within tb_invalidate_phys_page_range__locked, the is_cpu_write_access
4
parameter is non-zero exactly when retaddr would be non-zero, so that
5
is a simple replacement.
6
7
Recognize that current_tb_not_found is true only when mem_io_pc
8
(and now retaddr) are also non-zero, so remove a redundant test.
9
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Reviewed-by: David Hildenbrand <david@redhat.com>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
---
14
accel/tcg/translate-all.h | 3 ++-
15
accel/tcg/cputlb.c | 6 +-----
16
accel/tcg/translate-all.c | 39 +++++++++++++++++++--------------------
17
3 files changed, 22 insertions(+), 26 deletions(-)
18
19
diff --git a/accel/tcg/translate-all.h b/accel/tcg/translate-all.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/accel/tcg/translate-all.h
22
+++ b/accel/tcg/translate-all.h
23
@@ -XXX,XX +XXX,XX @@ struct page_collection *page_collection_lock(tb_page_addr_t start,
24
tb_page_addr_t end);
25
void page_collection_unlock(struct page_collection *set);
26
void tb_invalidate_phys_page_fast(struct page_collection *pages,
27
- tb_page_addr_t start, int len);
28
+ tb_page_addr_t start, int len,
29
+ uintptr_t retaddr);
30
void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end);
31
void tb_check_watchpoint(CPUState *cpu);
32
33
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/accel/tcg/cputlb.c
36
+++ b/accel/tcg/cputlb.c
37
@@ -XXX,XX +XXX,XX @@ static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size,
38
if (!cpu_physical_memory_get_dirty_flag(ram_addr, DIRTY_MEMORY_CODE)) {
39
struct page_collection *pages
40
= page_collection_lock(ram_addr, ram_addr + size);
41
-
42
- /* We require mem_io_pc in tb_invalidate_phys_page_range. */
43
- cpu->mem_io_pc = retaddr;
44
-
45
- tb_invalidate_phys_page_fast(pages, ram_addr, size);
46
+ tb_invalidate_phys_page_fast(pages, ram_addr, size, retaddr);
47
page_collection_unlock(pages);
48
}
49
50
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/accel/tcg/translate-all.c
53
+++ b/accel/tcg/translate-all.c
54
@@ -XXX,XX +XXX,XX @@ static void
55
tb_invalidate_phys_page_range__locked(struct page_collection *pages,
56
PageDesc *p, tb_page_addr_t start,
57
tb_page_addr_t end,
58
- int is_cpu_write_access)
59
+ uintptr_t retaddr)
60
{
61
TranslationBlock *tb;
62
tb_page_addr_t tb_start, tb_end;
63
@@ -XXX,XX +XXX,XX @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
64
#ifdef TARGET_HAS_PRECISE_SMC
65
CPUState *cpu = current_cpu;
66
CPUArchState *env = NULL;
67
- int current_tb_not_found = is_cpu_write_access;
68
+ bool current_tb_not_found = retaddr != 0;
69
+ bool current_tb_modified = false;
70
TranslationBlock *current_tb = NULL;
71
- int current_tb_modified = 0;
72
target_ulong current_pc = 0;
73
target_ulong current_cs_base = 0;
74
uint32_t current_flags = 0;
75
@@ -XXX,XX +XXX,XX @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
76
if (!(tb_end <= start || tb_start >= end)) {
77
#ifdef TARGET_HAS_PRECISE_SMC
78
if (current_tb_not_found) {
79
- current_tb_not_found = 0;
80
- current_tb = NULL;
81
- if (cpu->mem_io_pc) {
82
- /* now we have a real cpu fault */
83
- current_tb = tcg_tb_lookup(cpu->mem_io_pc);
84
- }
85
+ current_tb_not_found = false;
86
+ /* now we have a real cpu fault */
87
+ current_tb = tcg_tb_lookup(retaddr);
88
}
89
if (current_tb == tb &&
90
(tb_cflags(current_tb) & CF_COUNT_MASK) != 1) {
91
- /* If we are modifying the current TB, we must stop
92
- its execution. We could be more precise by checking
93
- that the modification is after the current PC, but it
94
- would require a specialized function to partially
95
- restore the CPU state */
96
-
97
- current_tb_modified = 1;
98
- cpu_restore_state_from_tb(cpu, current_tb,
99
- cpu->mem_io_pc, true);
100
+ /*
101
+ * If we are modifying the current TB, we must stop
102
+ * its execution. We could be more precise by checking
103
+ * that the modification is after the current PC, but it
104
+ * would require a specialized function to partially
105
+ * restore the CPU state.
106
+ */
107
+ current_tb_modified = true;
108
+ cpu_restore_state_from_tb(cpu, current_tb, retaddr, true);
109
cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
110
&current_flags);
111
}
112
@@ -XXX,XX +XXX,XX @@ void tb_invalidate_phys_range(target_ulong start, target_ulong end)
113
* Call with all @pages in the range [@start, @start + len[ locked.
114
*/
115
void tb_invalidate_phys_page_fast(struct page_collection *pages,
116
- tb_page_addr_t start, int len)
117
+ tb_page_addr_t start, int len,
118
+ uintptr_t retaddr)
119
{
120
PageDesc *p;
121
122
@@ -XXX,XX +XXX,XX @@ void tb_invalidate_phys_page_fast(struct page_collection *pages,
123
}
124
} else {
125
do_invalidate:
126
- tb_invalidate_phys_page_range__locked(pages, p, start, start + len, 1);
127
+ tb_invalidate_phys_page_range__locked(pages, p, start, start + len,
128
+ retaddr);
129
}
130
}
131
#else
132
--
133
2.17.1
134
135
diff view generated by jsdifflib
Deleted patch
1
Fixes the previous TLB_WATCHPOINT patches because we are currently
2
failing to set cpu->mem_io_pc with the call to cpu_check_watchpoint.
3
Pass down the retaddr directly because it's readily available.
4
1
5
Fixes: 50b107c5d61
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: David Hildenbrand <david@redhat.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
10
accel/tcg/translate-all.h | 2 +-
11
accel/tcg/translate-all.c | 6 +++---
12
exec.c | 2 +-
13
3 files changed, 5 insertions(+), 5 deletions(-)
14
15
diff --git a/accel/tcg/translate-all.h b/accel/tcg/translate-all.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/accel/tcg/translate-all.h
18
+++ b/accel/tcg/translate-all.h
19
@@ -XXX,XX +XXX,XX @@ void tb_invalidate_phys_page_fast(struct page_collection *pages,
20
tb_page_addr_t start, int len,
21
uintptr_t retaddr);
22
void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end);
23
-void tb_check_watchpoint(CPUState *cpu);
24
+void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr);
25
26
#ifdef CONFIG_USER_ONLY
27
int page_unprotect(target_ulong address, uintptr_t pc);
28
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/accel/tcg/translate-all.c
31
+++ b/accel/tcg/translate-all.c
32
@@ -XXX,XX +XXX,XX @@ static bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc)
33
#endif
34
35
/* user-mode: call with mmap_lock held */
36
-void tb_check_watchpoint(CPUState *cpu)
37
+void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr)
38
{
39
TranslationBlock *tb;
40
41
assert_memory_lock();
42
43
- tb = tcg_tb_lookup(cpu->mem_io_pc);
44
+ tb = tcg_tb_lookup(retaddr);
45
if (tb) {
46
/* We can use retranslation to find the PC. */
47
- cpu_restore_state_from_tb(cpu, tb, cpu->mem_io_pc, true);
48
+ cpu_restore_state_from_tb(cpu, tb, retaddr, true);
49
tb_phys_invalidate(tb, -1);
50
} else {
51
/* The exception probably happened in a helper. The CPU state should
52
diff --git a/exec.c b/exec.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/exec.c
55
+++ b/exec.c
56
@@ -XXX,XX +XXX,XX @@ void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
57
cpu->watchpoint_hit = wp;
58
59
mmap_lock();
60
- tb_check_watchpoint(cpu);
61
+ tb_check_watchpoint(cpu, ra);
62
if (wp->flags & BP_STOP_BEFORE_ACCESS) {
63
cpu->exception_index = EXCP_DEBUG;
64
mmap_unlock();
65
--
66
2.17.1
67
68
diff view generated by jsdifflib