1
This is v4 of my notdirty + rom patch set with two suggested name
1
The following changes since commit 6eeea6725a70e6fcb5abba0764496bdab07ddfb3:
2
changes (qemu_build_not_reached, TLB_DISCARD_WRITE) from David and Alex.
3
2
4
3
Merge remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2020-10-06' into staging (2020-10-06 21:13:34 +0100)
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-20201008
15
8
16
for you to fetch changes up to ae57db63acf5a0399232f852acc5c1d83ef63400:
9
for you to fetch changes up to 62475e9d007d83db4d0a6ccebcda8914f392e9c9:
17
10
18
cputlb: Pass retaddr to tb_check_watchpoint (2019-09-25 10:56:28 -0700)
11
accel/tcg: Fix computing of is_write for MIPS (2020-10-08 05:57:32 -0500)
19
12
20
----------------------------------------------------------------
13
----------------------------------------------------------------
21
Fixes for TLB_BSWAP
14
Extend maximum gvec vector size
22
Coversion of NOTDIRTY and ROM handling to cputlb
15
Fix i386 avx2 dupi
23
Followup cleanups to cputlb
16
Fix mips host user-only write detection
17
Misc cleanups.
24
18
25
----------------------------------------------------------------
19
----------------------------------------------------------------
26
Richard Henderson (16):
20
Kele Huang (1):
27
exec: Use TARGET_PAGE_BITS_MIN for TLB flags
21
accel/tcg: Fix computing of is_write for MIPS
28
cputlb: Disable __always_inline__ without optimization
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
22
44
accel/tcg/translate-all.h | 8 +-
23
Richard Henderson (10):
45
include/exec/cpu-all.h | 23 ++-
24
tcg: Adjust simd_desc size encoding
46
include/exec/cpu-common.h | 3 -
25
tcg: Drop union from TCGArgConstraint
47
include/exec/exec-all.h | 6 +-
26
tcg: Move sorted_args into TCGArgConstraint.sort_index
48
include/exec/memory-internal.h | 65 --------
27
tcg: Remove TCG_CT_REG
49
include/hw/core/cpu.h | 2 -
28
tcg: Move some TCG_CT_* bits to TCGArgConstraint bitfields
50
include/qemu/compiler.h | 26 +++
29
tcg: Remove TCGOpDef.used
51
accel/tcg/cputlb.c | 348 +++++++++++++++++++++++++----------------
30
tcg/i386: Fix dupi for avx2 32-bit hosts
52
accel/tcg/translate-all.c | 51 +++---
31
tcg: Fix generation of dupi_vec for 32-bit host
53
exec.c | 158 +------------------
32
tcg/optimize: Fold dup2_vec
54
hw/core/cpu.c | 1 -
33
tcg: Remove TCG_TARGET_HAS_cmp_vec
55
memory.c | 20 ---
56
trace-events | 4 +-
57
13 files changed, 288 insertions(+), 427 deletions(-)
58
34
35
include/tcg/tcg-gvec-desc.h | 38 ++++++++++++------
36
include/tcg/tcg.h | 22 ++++------
37
tcg/aarch64/tcg-target.h | 1 -
38
tcg/i386/tcg-target.h | 1 -
39
tcg/ppc/tcg-target.h | 1 -
40
accel/tcg/user-exec.c | 43 ++++++++++++++++++--
41
tcg/optimize.c | 15 +++++++
42
tcg/tcg-op-gvec.c | 35 ++++++++++++----
43
tcg/tcg-op-vec.c | 12 ++++--
44
tcg/tcg.c | 96 +++++++++++++++++++-------------------------
45
tcg/aarch64/tcg-target.c.inc | 17 ++++----
46
tcg/arm/tcg-target.c.inc | 29 ++++++-------
47
tcg/i386/tcg-target.c.inc | 39 +++++++-----------
48
tcg/mips/tcg-target.c.inc | 21 +++++-----
49
tcg/ppc/tcg-target.c.inc | 29 ++++++-------
50
tcg/riscv/tcg-target.c.inc | 16 ++++----
51
tcg/s390/tcg-target.c.inc | 22 +++++-----
52
tcg/sparc/tcg-target.c.inc | 21 ++++------
53
tcg/tci/tcg-target.c.inc | 3 +-
54
19 files changed, 244 insertions(+), 217 deletions(-)
55
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
1
We will shortly be using these more than once.
1
With larger vector sizes, it turns out oprsz == maxsz, and we only
2
need to represent mismatch for oprsz <= 32. We do, however, need
3
to represent larger oprsz and do so without reducing SIMD_DATA_BITS.
2
4
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reduce the size of the oprsz field and increase the maxsz field.
4
Reviewed-by: David Hildenbrand <david@redhat.com>
6
Steal the oprsz value of 24 to indicate equality with maxsz.
7
8
Tested-by: Frank Chang <frank.chang@sifive.com>
9
Reviewed-by: Frank Chang <frank.chang@sifive.com>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
12
---
7
accel/tcg/cputlb.c | 107 +++++++++++++++++++++++----------------------
13
include/tcg/tcg-gvec-desc.h | 38 ++++++++++++++++++++++++-------------
8
1 file changed, 55 insertions(+), 52 deletions(-)
14
tcg/tcg-op-gvec.c | 35 ++++++++++++++++++++++++++--------
15
2 files changed, 52 insertions(+), 21 deletions(-)
9
16
10
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
17
diff --git a/include/tcg/tcg-gvec-desc.h b/include/tcg/tcg-gvec-desc.h
11
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
12
--- a/accel/tcg/cputlb.c
19
--- a/include/tcg/tcg-gvec-desc.h
13
+++ b/accel/tcg/cputlb.c
20
+++ b/include/tcg/tcg-gvec-desc.h
14
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
21
@@ -XXX,XX +XXX,XX @@
15
typedef uint64_t FullLoadHelper(CPUArchState *env, target_ulong addr,
22
#ifndef TCG_TCG_GVEC_DESC_H
16
TCGMemOpIdx oi, uintptr_t retaddr);
23
#define TCG_TCG_GVEC_DESC_H
17
24
18
+static inline uint64_t QEMU_ALWAYS_INLINE
25
-/* ??? These bit widths are set for ARM SVE, maxing out at 256 byte vectors. */
19
+load_memop(const void *haddr, MemOp op)
26
-#define SIMD_OPRSZ_SHIFT 0
20
+{
27
-#define SIMD_OPRSZ_BITS 5
21
+ switch (op) {
28
+/*
22
+ case MO_UB:
29
+ * This configuration allows MAXSZ to represent 2048 bytes, and
23
+ return ldub_p(haddr);
30
+ * OPRSZ to match MAXSZ, or represent the smaller values 8, 16, or 32.
24
+ case MO_BEUW:
31
+ *
25
+ return lduw_be_p(haddr);
32
+ * Encode this with:
26
+ case MO_LEUW:
33
+ * 0, 1, 3 -> 8, 16, 32
27
+ return lduw_le_p(haddr);
34
+ * 2 -> maxsz
28
+ case MO_BEUL:
35
+ *
29
+ return (uint32_t)ldl_be_p(haddr);
36
+ * This steals the input that would otherwise map to 24 to match maxsz.
30
+ case MO_LEUL:
37
+ */
31
+ return (uint32_t)ldl_le_p(haddr);
38
+#define SIMD_MAXSZ_SHIFT 0
32
+ case MO_BEQ:
39
+#define SIMD_MAXSZ_BITS 8
33
+ return ldq_be_p(haddr);
40
34
+ case MO_LEQ:
41
-#define SIMD_MAXSZ_SHIFT (SIMD_OPRSZ_SHIFT + SIMD_OPRSZ_BITS)
35
+ return ldq_le_p(haddr);
42
-#define SIMD_MAXSZ_BITS 5
36
+ default:
43
+#define SIMD_OPRSZ_SHIFT (SIMD_MAXSZ_SHIFT + SIMD_MAXSZ_BITS)
37
+ qemu_build_not_reached();
44
+#define SIMD_OPRSZ_BITS 2
38
+ }
45
46
-#define SIMD_DATA_SHIFT (SIMD_MAXSZ_SHIFT + SIMD_MAXSZ_BITS)
47
+#define SIMD_DATA_SHIFT (SIMD_OPRSZ_SHIFT + SIMD_OPRSZ_BITS)
48
#define SIMD_DATA_BITS (32 - SIMD_DATA_SHIFT)
49
50
/* Create a descriptor from components. */
51
uint32_t simd_desc(uint32_t oprsz, uint32_t maxsz, int32_t data);
52
53
-/* Extract the operation size from a descriptor. */
54
-static inline intptr_t simd_oprsz(uint32_t desc)
55
-{
56
- return (extract32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS) + 1) * 8;
57
-}
58
-
59
/* Extract the max vector size from a descriptor. */
60
static inline intptr_t simd_maxsz(uint32_t desc)
61
{
62
- return (extract32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS) + 1) * 8;
63
+ return extract32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS) * 8 + 8;
39
+}
64
+}
40
+
65
+
41
static inline uint64_t QEMU_ALWAYS_INLINE
66
+/* Extract the operation size from a descriptor. */
42
load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
67
+static inline intptr_t simd_oprsz(uint32_t desc)
43
uintptr_t retaddr, MemOp op, bool code_read,
68
+{
44
@@ -XXX,XX +XXX,XX @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
69
+ uint32_t f = extract32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS);
45
70
+ intptr_t o = f * 8 + 8;
46
do_aligned_access:
71
+ intptr_t m = simd_maxsz(desc);
47
haddr = (void *)((uintptr_t)addr + entry->addend);
72
+ return f == 2 ? m : o;
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
}
73
}
77
74
78
/*
75
/* Extract the operation-specific data from a descriptor. */
79
@@ -XXX,XX +XXX,XX @@ tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr,
76
diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c
80
* Store Helpers
77
index XXXXXXX..XXXXXXX 100644
81
*/
78
--- a/tcg/tcg-op-gvec.c
82
79
+++ b/tcg/tcg-op-gvec.c
83
+static inline void QEMU_ALWAYS_INLINE
80
@@ -XXX,XX +XXX,XX @@ static const TCGOpcode vecop_list_empty[1] = { 0 };
84
+store_memop(void *haddr, uint64_t val, MemOp op)
81
of the operand offsets so that we can check them all at once. */
85
+{
82
static void check_size_align(uint32_t oprsz, uint32_t maxsz, uint32_t ofs)
86
+ switch (op) {
83
{
87
+ case MO_UB:
84
- uint32_t opr_align = oprsz >= 16 ? 15 : 7;
88
+ stb_p(haddr, val);
85
- uint32_t max_align = maxsz >= 16 || oprsz >= 16 ? 15 : 7;
89
+ break;
86
- tcg_debug_assert(oprsz > 0);
90
+ case MO_BEUW:
87
- tcg_debug_assert(oprsz <= maxsz);
91
+ stw_be_p(haddr, val);
88
- tcg_debug_assert((oprsz & opr_align) == 0);
92
+ break;
89
+ uint32_t max_align;
93
+ case MO_LEUW:
90
+
94
+ stw_le_p(haddr, val);
91
+ switch (oprsz) {
95
+ break;
92
+ case 8:
96
+ case MO_BEUL:
93
+ case 16:
97
+ stl_be_p(haddr, val);
94
+ case 32:
98
+ break;
95
+ tcg_debug_assert(oprsz <= maxsz);
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;
96
+ break;
108
+ default:
97
+ default:
109
+ qemu_build_not_reached();
98
+ tcg_debug_assert(oprsz == maxsz);
99
+ break;
110
+ }
100
+ }
111
+}
101
+ tcg_debug_assert(maxsz <= (8 << SIMD_MAXSZ_BITS));
112
+
102
+
113
static inline void QEMU_ALWAYS_INLINE
103
+ max_align = maxsz >= 16 ? 15 : 7;
114
store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
104
tcg_debug_assert((maxsz & max_align) == 0);
115
TCGMemOpIdx oi, uintptr_t retaddr, MemOp op)
105
tcg_debug_assert((ofs & max_align) == 0);
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
}
106
}
147
107
@@ -XXX,XX +XXX,XX @@ uint32_t simd_desc(uint32_t oprsz, uint32_t maxsz, int32_t data)
148
void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
108
{
109
uint32_t desc = 0;
110
111
- assert(oprsz % 8 == 0 && oprsz <= (8 << SIMD_OPRSZ_BITS));
112
- assert(maxsz % 8 == 0 && maxsz <= (8 << SIMD_MAXSZ_BITS));
113
- assert(data == sextract32(data, 0, SIMD_DATA_BITS));
114
+ check_size_align(oprsz, maxsz, 0);
115
+ tcg_debug_assert(data == sextract32(data, 0, SIMD_DATA_BITS));
116
117
oprsz = (oprsz / 8) - 1;
118
maxsz = (maxsz / 8) - 1;
119
+
120
+ /*
121
+ * We have just asserted in check_size_align that either
122
+ * oprsz is {8,16,32} or matches maxsz. Encode the final
123
+ * case with '2', as that would otherwise map to 24.
124
+ */
125
+ if (oprsz == maxsz) {
126
+ oprsz = 2;
127
+ }
128
+
129
desc = deposit32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS, oprsz);
130
desc = deposit32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS, maxsz);
131
desc = deposit32(desc, SIMD_DATA_SHIFT, SIMD_DATA_BITS, data);
149
--
132
--
150
2.17.1
133
2.25.1
151
134
152
135
diff view generated by jsdifflib
1
Handle bswap on ram directly in load/store_helper. This fixes a
1
The union is unused; let "regs" appear in the main structure
2
bug with the previous implementation in that one cannot use the
2
without the "u.regs" wrapping.
3
I/O path for RAM.
4
3
5
Fixes: a26fc6f5152b47f1
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
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>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
6
---
10
include/exec/cpu-all.h | 4 ++-
7
include/tcg/tcg.h | 4 +---
11
accel/tcg/cputlb.c | 72 +++++++++++++++++++++++++-----------------
8
tcg/tcg.c | 22 +++++++++++-----------
12
2 files changed, 46 insertions(+), 30 deletions(-)
9
tcg/aarch64/tcg-target.c.inc | 14 +++++++-------
10
tcg/arm/tcg-target.c.inc | 26 +++++++++++++-------------
11
tcg/i386/tcg-target.c.inc | 26 +++++++++++++-------------
12
tcg/mips/tcg-target.c.inc | 18 +++++++++---------
13
tcg/ppc/tcg-target.c.inc | 24 ++++++++++++------------
14
tcg/riscv/tcg-target.c.inc | 14 +++++++-------
15
tcg/s390/tcg-target.c.inc | 18 +++++++++---------
16
tcg/sparc/tcg-target.c.inc | 16 ++++++++--------
17
tcg/tci/tcg-target.c.inc | 2 +-
18
11 files changed, 91 insertions(+), 93 deletions(-)
13
19
14
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
20
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
15
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
16
--- a/include/exec/cpu-all.h
22
--- a/include/tcg/tcg.h
17
+++ b/include/exec/cpu-all.h
23
+++ b/include/tcg/tcg.h
18
@@ -XXX,XX +XXX,XX @@ CPUArchState *cpu_copy(CPUArchState *env);
24
@@ -XXX,XX +XXX,XX @@ void tcg_dump_op_count(void);
19
#define TLB_MMIO (1 << (TARGET_PAGE_BITS_MIN - 3))
25
typedef struct TCGArgConstraint {
20
/* Set if TLB entry contains a watchpoint. */
26
uint16_t ct;
21
#define TLB_WATCHPOINT (1 << (TARGET_PAGE_BITS_MIN - 4))
27
uint8_t alias_index;
22
+/* Set if TLB entry requires byte swap. */
28
- union {
23
+#define TLB_BSWAP (1 << (TARGET_PAGE_BITS_MIN - 5))
29
- TCGRegSet regs;
24
30
- } u;
25
/* Use this mask to check interception with an alignment mask
31
+ TCGRegSet regs;
26
* in a TCG backend.
32
} TCGArgConstraint;
27
*/
33
28
#define TLB_FLAGS_MASK \
34
#define TCG_MAX_OP_ARGS 16
29
- (TLB_INVALID_MASK | TLB_NOTDIRTY | TLB_MMIO | TLB_WATCHPOINT)
35
diff --git a/tcg/tcg.c b/tcg/tcg.c
30
+ (TLB_INVALID_MASK | TLB_NOTDIRTY | TLB_MMIO | TLB_WATCHPOINT | TLB_BSWAP)
36
index XXXXXXX..XXXXXXX 100644
31
37
--- a/tcg/tcg.c
32
/**
38
+++ b/tcg/tcg.c
33
* tlb_hit_page: return true if page aligned @addr is a hit against the
39
@@ -XXX,XX +XXX,XX @@ static int get_constraint_priority(const TCGOpDef *def, int k)
34
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
40
return 0;
35
index XXXXXXX..XXXXXXX 100644
41
n = 0;
36
--- a/accel/tcg/cputlb.c
42
for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
37
+++ b/accel/tcg/cputlb.c
43
- if (tcg_regset_test_reg(arg_ct->u.regs, i))
38
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
44
+ if (tcg_regset_test_reg(arg_ct->regs, i))
39
address |= TLB_INVALID_MASK;
45
n++;
46
}
40
}
47
}
41
if (attrs.byte_swap) {
48
@@ -XXX,XX +XXX,XX @@ static void process_op_defs(TCGContext *s)
42
- /* Force the access through the I/O slow path. */
49
/* Incomplete TCGTargetOpDef entry. */
43
- address |= TLB_MMIO;
50
tcg_debug_assert(ct_str != NULL);
44
+ address |= TLB_BSWAP;
51
45
}
52
- def->args_ct[i].u.regs = 0;
46
if (!memory_region_is_ram(section->mr) &&
53
+ def->args_ct[i].regs = 0;
47
!memory_region_is_romd(section->mr)) {
54
def->args_ct[i].ct = 0;
48
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
55
while (*ct_str != '\0') {
49
bool locked = false;
56
switch(*ct_str) {
50
MemTxResult r;
57
@@ -XXX,XX +XXX,XX @@ static void liveness_pass_1(TCGContext *s)
51
58
pset = la_temp_pref(ts);
52
- if (iotlbentry->attrs.byte_swap) {
59
set = *pset;
53
- op ^= MO_BSWAP;
60
54
- }
61
- set &= ct->u.regs;
55
-
62
+ set &= ct->regs;
56
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
63
if (ct->ct & TCG_CT_IALIAS) {
57
mr = section->mr;
64
set &= op->output_pref[ct->alias_index];
58
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
65
}
59
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
66
/* If the combination is not possible, restart. */
60
bool locked = false;
67
if (set == 0) {
61
MemTxResult r;
68
- set = ct->u.regs;
62
69
+ set = ct->regs;
63
- if (iotlbentry->attrs.byte_swap) {
70
}
64
- op ^= MO_BSWAP;
71
*pset = set;
65
- }
72
}
66
-
73
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_dup(TCGContext *s, const TCGOp *op)
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
}
100
101
+ need_swap = size > 1 && (tlb_addr & TLB_BSWAP);
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;
74
return;
176
}
75
}
177
76
178
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
77
- dup_out_regs = tcg_op_defs[INDEX_op_dup_vec].args_ct[0].u.regs;
179
return;
78
- dup_in_regs = tcg_op_defs[INDEX_op_dup_vec].args_ct[1].u.regs;
180
}
79
+ dup_out_regs = tcg_op_defs[INDEX_op_dup_vec].args_ct[0].regs;
181
80
+ dup_in_regs = tcg_op_defs[INDEX_op_dup_vec].args_ct[1].regs;
182
- do_aligned_access:
81
183
haddr = (void *)((uintptr_t)addr + entry->addend);
82
/* Allocate the output register now. */
184
store_memop(haddr, val, op);
83
if (ots->val_type != TEMP_VAL_REG) {
185
}
84
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
85
}
86
}
87
88
- temp_load(s, ts, arg_ct->u.regs, i_allocated_regs, i_preferred_regs);
89
+ temp_load(s, ts, arg_ct->regs, i_allocated_regs, i_preferred_regs);
90
reg = ts->reg;
91
92
- if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
93
+ if (tcg_regset_test_reg(arg_ct->regs, reg)) {
94
/* nothing to do : the constraint is satisfied */
95
} else {
96
allocate_in_reg:
97
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
98
and move the temporary register into it */
99
temp_load(s, ts, tcg_target_available_regs[ts->type],
100
i_allocated_regs, 0);
101
- reg = tcg_reg_alloc(s, arg_ct->u.regs, i_allocated_regs,
102
+ reg = tcg_reg_alloc(s, arg_ct->regs, i_allocated_regs,
103
o_preferred_regs, ts->indirect_base);
104
if (!tcg_out_mov(s, ts->type, reg, ts->reg)) {
105
/*
106
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
107
&& !const_args[arg_ct->alias_index]) {
108
reg = new_args[arg_ct->alias_index];
109
} else if (arg_ct->ct & TCG_CT_NEWREG) {
110
- reg = tcg_reg_alloc(s, arg_ct->u.regs,
111
+ reg = tcg_reg_alloc(s, arg_ct->regs,
112
i_allocated_regs | o_allocated_regs,
113
op->output_pref[k], ts->indirect_base);
114
} else {
115
- reg = tcg_reg_alloc(s, arg_ct->u.regs, o_allocated_regs,
116
+ reg = tcg_reg_alloc(s, arg_ct->regs, o_allocated_regs,
117
op->output_pref[k], ts->indirect_base);
118
}
119
tcg_regset_set_reg(o_allocated_regs, reg);
120
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
121
index XXXXXXX..XXXXXXX 100644
122
--- a/tcg/aarch64/tcg-target.c.inc
123
+++ b/tcg/aarch64/tcg-target.c.inc
124
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
125
switch (*ct_str++) {
126
case 'r': /* general registers */
127
ct->ct |= TCG_CT_REG;
128
- ct->u.regs |= 0xffffffffu;
129
+ ct->regs |= 0xffffffffu;
130
break;
131
case 'w': /* advsimd registers */
132
ct->ct |= TCG_CT_REG;
133
- ct->u.regs |= 0xffffffff00000000ull;
134
+ ct->regs |= 0xffffffff00000000ull;
135
break;
136
case 'l': /* qemu_ld / qemu_st address, data_reg */
137
ct->ct |= TCG_CT_REG;
138
- ct->u.regs = 0xffffffffu;
139
+ ct->regs = 0xffffffffu;
140
#ifdef CONFIG_SOFTMMU
141
/* x0 and x1 will be overwritten when reading the tlb entry,
142
and x2, and x3 for helper args, better to avoid using them. */
143
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_X0);
144
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_X1);
145
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_X2);
146
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_X3);
147
+ tcg_regset_reset_reg(ct->regs, TCG_REG_X0);
148
+ tcg_regset_reset_reg(ct->regs, TCG_REG_X1);
149
+ tcg_regset_reset_reg(ct->regs, TCG_REG_X2);
150
+ tcg_regset_reset_reg(ct->regs, TCG_REG_X3);
151
#endif
152
break;
153
case 'A': /* Valid for arithmetic immediate (positive or negative). */
154
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
155
index XXXXXXX..XXXXXXX 100644
156
--- a/tcg/arm/tcg-target.c.inc
157
+++ b/tcg/arm/tcg-target.c.inc
158
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
159
160
case 'r':
161
ct->ct |= TCG_CT_REG;
162
- ct->u.regs = 0xffff;
163
+ ct->regs = 0xffff;
164
break;
165
166
/* qemu_ld address */
167
case 'l':
168
ct->ct |= TCG_CT_REG;
169
- ct->u.regs = 0xffff;
170
+ ct->regs = 0xffff;
171
#ifdef CONFIG_SOFTMMU
172
/* r0-r2,lr will be overwritten when reading the tlb entry,
173
so don't use these. */
174
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
175
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
176
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
177
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
178
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14);
179
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R0);
180
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R1);
181
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R2);
182
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
183
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R14);
184
#endif
185
break;
186
187
/* qemu_st address & data */
188
case 's':
189
ct->ct |= TCG_CT_REG;
190
- ct->u.regs = 0xffff;
191
+ ct->regs = 0xffff;
192
/* r0-r2 will be overwritten when reading the tlb entry (softmmu only)
193
and r0-r1 doing the byte swapping, so don't use these. */
194
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
195
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
196
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R0);
197
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R1);
198
#if defined(CONFIG_SOFTMMU)
199
/* Avoid clashes with registers being used for helper args */
200
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
201
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R2);
202
#if TARGET_LONG_BITS == 64
203
/* Avoid clashes with registers being used for helper args */
204
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
205
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
206
#endif
207
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14);
208
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R14);
209
#endif
210
break;
211
212
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
213
index XXXXXXX..XXXXXXX 100644
214
--- a/tcg/i386/tcg-target.c.inc
215
+++ b/tcg/i386/tcg-target.c.inc
216
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
217
switch(*ct_str++) {
218
case 'a':
219
ct->ct |= TCG_CT_REG;
220
- tcg_regset_set_reg(ct->u.regs, TCG_REG_EAX);
221
+ tcg_regset_set_reg(ct->regs, TCG_REG_EAX);
222
break;
223
case 'b':
224
ct->ct |= TCG_CT_REG;
225
- tcg_regset_set_reg(ct->u.regs, TCG_REG_EBX);
226
+ tcg_regset_set_reg(ct->regs, TCG_REG_EBX);
227
break;
228
case 'c':
229
ct->ct |= TCG_CT_REG;
230
- tcg_regset_set_reg(ct->u.regs, TCG_REG_ECX);
231
+ tcg_regset_set_reg(ct->regs, TCG_REG_ECX);
232
break;
233
case 'd':
234
ct->ct |= TCG_CT_REG;
235
- tcg_regset_set_reg(ct->u.regs, TCG_REG_EDX);
236
+ tcg_regset_set_reg(ct->regs, TCG_REG_EDX);
237
break;
238
case 'S':
239
ct->ct |= TCG_CT_REG;
240
- tcg_regset_set_reg(ct->u.regs, TCG_REG_ESI);
241
+ tcg_regset_set_reg(ct->regs, TCG_REG_ESI);
242
break;
243
case 'D':
244
ct->ct |= TCG_CT_REG;
245
- tcg_regset_set_reg(ct->u.regs, TCG_REG_EDI);
246
+ tcg_regset_set_reg(ct->regs, TCG_REG_EDI);
247
break;
248
case 'q':
249
/* A register that can be used as a byte operand. */
250
ct->ct |= TCG_CT_REG;
251
- ct->u.regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xf;
252
+ ct->regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xf;
253
break;
254
case 'Q':
255
/* A register with an addressable second byte (e.g. %ah). */
256
ct->ct |= TCG_CT_REG;
257
- ct->u.regs = 0xf;
258
+ ct->regs = 0xf;
259
break;
260
case 'r':
261
/* A general register. */
262
ct->ct |= TCG_CT_REG;
263
- ct->u.regs |= ALL_GENERAL_REGS;
264
+ ct->regs |= ALL_GENERAL_REGS;
265
break;
266
case 'W':
267
/* With TZCNT/LZCNT, we can have operand-size as an input. */
268
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
269
case 'x':
270
/* A vector register. */
271
ct->ct |= TCG_CT_REG;
272
- ct->u.regs |= ALL_VECTOR_REGS;
273
+ ct->regs |= ALL_VECTOR_REGS;
274
break;
275
276
/* qemu_ld/st address constraint */
277
case 'L':
278
ct->ct |= TCG_CT_REG;
279
- ct->u.regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xff;
280
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_L0);
281
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_L1);
282
+ ct->regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xff;
283
+ tcg_regset_reset_reg(ct->regs, TCG_REG_L0);
284
+ tcg_regset_reset_reg(ct->regs, TCG_REG_L1);
285
break;
286
287
case 'e':
288
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
289
index XXXXXXX..XXXXXXX 100644
290
--- a/tcg/mips/tcg-target.c.inc
291
+++ b/tcg/mips/tcg-target.c.inc
292
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
293
switch(*ct_str++) {
294
case 'r':
295
ct->ct |= TCG_CT_REG;
296
- ct->u.regs = 0xffffffff;
297
+ ct->regs = 0xffffffff;
298
break;
299
case 'L': /* qemu_ld input arg constraint */
300
ct->ct |= TCG_CT_REG;
301
- ct->u.regs = 0xffffffff;
302
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
303
+ ct->regs = 0xffffffff;
304
+ tcg_regset_reset_reg(ct->regs, TCG_REG_A0);
305
#if defined(CONFIG_SOFTMMU)
306
if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
307
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
308
+ tcg_regset_reset_reg(ct->regs, TCG_REG_A2);
309
}
310
#endif
311
break;
312
case 'S': /* qemu_st constraint */
313
ct->ct |= TCG_CT_REG;
314
- ct->u.regs = 0xffffffff;
315
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
316
+ ct->regs = 0xffffffff;
317
+ tcg_regset_reset_reg(ct->regs, TCG_REG_A0);
318
#if defined(CONFIG_SOFTMMU)
319
if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
320
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
321
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_A3);
322
+ tcg_regset_reset_reg(ct->regs, TCG_REG_A2);
323
+ tcg_regset_reset_reg(ct->regs, TCG_REG_A3);
324
} else {
325
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
326
+ tcg_regset_reset_reg(ct->regs, TCG_REG_A1);
327
}
328
#endif
329
break;
330
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
331
index XXXXXXX..XXXXXXX 100644
332
--- a/tcg/ppc/tcg-target.c.inc
333
+++ b/tcg/ppc/tcg-target.c.inc
334
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
335
switch (*ct_str++) {
336
case 'A': case 'B': case 'C': case 'D':
337
ct->ct |= TCG_CT_REG;
338
- tcg_regset_set_reg(ct->u.regs, 3 + ct_str[0] - 'A');
339
+ tcg_regset_set_reg(ct->regs, 3 + ct_str[0] - 'A');
340
break;
341
case 'r':
342
ct->ct |= TCG_CT_REG;
343
- ct->u.regs = 0xffffffff;
344
+ ct->regs = 0xffffffff;
345
break;
346
case 'v':
347
ct->ct |= TCG_CT_REG;
348
- ct->u.regs = 0xffffffff00000000ull;
349
+ ct->regs = 0xffffffff00000000ull;
350
break;
351
case 'L': /* qemu_ld constraint */
352
ct->ct |= TCG_CT_REG;
353
- ct->u.regs = 0xffffffff;
354
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
355
+ ct->regs = 0xffffffff;
356
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
357
#ifdef CONFIG_SOFTMMU
358
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
359
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
360
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R4);
361
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R5);
362
#endif
363
break;
364
case 'S': /* qemu_st constraint */
365
ct->ct |= TCG_CT_REG;
366
- ct->u.regs = 0xffffffff;
367
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
368
+ ct->regs = 0xffffffff;
369
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
370
#ifdef CONFIG_SOFTMMU
371
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
372
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
373
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
374
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R4);
375
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R5);
376
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R6);
377
#endif
378
break;
379
case 'I':
380
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
381
index XXXXXXX..XXXXXXX 100644
382
--- a/tcg/riscv/tcg-target.c.inc
383
+++ b/tcg/riscv/tcg-target.c.inc
384
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
385
switch (*ct_str++) {
386
case 'r':
387
ct->ct |= TCG_CT_REG;
388
- ct->u.regs = 0xffffffff;
389
+ ct->regs = 0xffffffff;
390
break;
391
case 'L':
392
/* qemu_ld/qemu_st constraint */
393
ct->ct |= TCG_CT_REG;
394
- ct->u.regs = 0xffffffff;
395
+ ct->regs = 0xffffffff;
396
/* qemu_ld/qemu_st uses TCG_REG_TMP0 */
397
#if defined(CONFIG_SOFTMMU)
398
- tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[0]);
399
- tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[1]);
400
- tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[2]);
401
- tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[3]);
402
- tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[4]);
403
+ tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[0]);
404
+ tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[1]);
405
+ tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[2]);
406
+ tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[3]);
407
+ tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[4]);
408
#endif
409
break;
410
case 'I':
411
diff --git a/tcg/s390/tcg-target.c.inc b/tcg/s390/tcg-target.c.inc
412
index XXXXXXX..XXXXXXX 100644
413
--- a/tcg/s390/tcg-target.c.inc
414
+++ b/tcg/s390/tcg-target.c.inc
415
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
416
switch (*ct_str++) {
417
case 'r': /* all registers */
418
ct->ct |= TCG_CT_REG;
419
- ct->u.regs = 0xffff;
420
+ ct->regs = 0xffff;
421
break;
422
case 'L': /* qemu_ld/st constraint */
423
ct->ct |= TCG_CT_REG;
424
- ct->u.regs = 0xffff;
425
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
426
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
427
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
428
+ ct->regs = 0xffff;
429
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R2);
430
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
431
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R4);
432
break;
433
case 'a': /* force R2 for division */
434
ct->ct |= TCG_CT_REG;
435
- ct->u.regs = 0;
436
- tcg_regset_set_reg(ct->u.regs, TCG_REG_R2);
437
+ ct->regs = 0;
438
+ tcg_regset_set_reg(ct->regs, TCG_REG_R2);
439
break;
440
case 'b': /* force R3 for division */
441
ct->ct |= TCG_CT_REG;
442
- ct->u.regs = 0;
443
- tcg_regset_set_reg(ct->u.regs, TCG_REG_R3);
444
+ ct->regs = 0;
445
+ tcg_regset_set_reg(ct->regs, TCG_REG_R3);
446
break;
447
case 'A':
448
ct->ct |= TCG_CT_CONST_S33;
449
diff --git a/tcg/sparc/tcg-target.c.inc b/tcg/sparc/tcg-target.c.inc
450
index XXXXXXX..XXXXXXX 100644
451
--- a/tcg/sparc/tcg-target.c.inc
452
+++ b/tcg/sparc/tcg-target.c.inc
453
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
454
switch (*ct_str++) {
455
case 'r':
456
ct->ct |= TCG_CT_REG;
457
- ct->u.regs = 0xffffffff;
458
+ ct->regs = 0xffffffff;
459
break;
460
case 'R':
461
ct->ct |= TCG_CT_REG;
462
- ct->u.regs = ALL_64;
463
+ ct->regs = ALL_64;
464
break;
465
case 'A': /* qemu_ld/st address constraint */
466
ct->ct |= TCG_CT_REG;
467
- ct->u.regs = TARGET_LONG_BITS == 64 ? ALL_64 : 0xffffffff;
468
+ ct->regs = TARGET_LONG_BITS == 64 ? ALL_64 : 0xffffffff;
469
reserve_helpers:
470
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0);
471
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1);
472
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_O2);
473
+ tcg_regset_reset_reg(ct->regs, TCG_REG_O0);
474
+ tcg_regset_reset_reg(ct->regs, TCG_REG_O1);
475
+ tcg_regset_reset_reg(ct->regs, TCG_REG_O2);
476
break;
477
case 's': /* qemu_st data 32-bit constraint */
478
ct->ct |= TCG_CT_REG;
479
- ct->u.regs = 0xffffffff;
480
+ ct->regs = 0xffffffff;
481
goto reserve_helpers;
482
case 'S': /* qemu_st data 64-bit constraint */
483
ct->ct |= TCG_CT_REG;
484
- ct->u.regs = ALL_64;
485
+ ct->regs = ALL_64;
486
goto reserve_helpers;
487
case 'I':
488
ct->ct |= TCG_CT_CONST_S11;
489
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
490
index XXXXXXX..XXXXXXX 100644
491
--- a/tcg/tci/tcg-target.c.inc
492
+++ b/tcg/tci/tcg-target.c.inc
493
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
494
case 'L': /* qemu_ld constraint */
495
case 'S': /* qemu_st constraint */
496
ct->ct |= TCG_CT_REG;
497
- ct->u.regs = BIT(TCG_TARGET_NB_REGS) - 1;
498
+ ct->regs = BIT(TCG_TARGET_NB_REGS) - 1;
499
break;
500
default:
501
return NULL;
186
--
502
--
187
2.17.1
503
2.25.1
188
504
189
505
diff view generated by jsdifflib
1
We can use notdirty_write for the write and return a valid host
1
This uses an existing hole in the TCGArgConstraint structure
2
pointer for this case.
2
and will be convenient for keeping the data in one place.
3
3
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>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
5
---
8
accel/tcg/cputlb.c | 26 +++++++++++++++++---------
6
include/tcg/tcg.h | 2 +-
9
1 file changed, 17 insertions(+), 9 deletions(-)
7
tcg/tcg.c | 35 +++++++++++++++++------------------
8
2 files changed, 18 insertions(+), 19 deletions(-)
10
9
11
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
10
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
12
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
13
--- a/accel/tcg/cputlb.c
12
--- a/include/tcg/tcg.h
14
+++ b/accel/tcg/cputlb.c
13
+++ b/include/tcg/tcg.h
15
@@ -XXX,XX +XXX,XX @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
14
@@ -XXX,XX +XXX,XX @@ void tcg_dump_op_count(void);
16
return NULL;
15
typedef struct TCGArgConstraint {
16
uint16_t ct;
17
uint8_t alias_index;
18
+ uint8_t sort_index;
19
TCGRegSet regs;
20
} TCGArgConstraint;
21
22
@@ -XXX,XX +XXX,XX @@ typedef struct TCGOpDef {
23
uint8_t nb_oargs, nb_iargs, nb_cargs, nb_args;
24
uint8_t flags;
25
TCGArgConstraint *args_ct;
26
- int *sorted_args;
27
#if defined(CONFIG_DEBUG_TCG)
28
int used;
29
#endif
30
diff --git a/tcg/tcg.c b/tcg/tcg.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/tcg/tcg.c
33
+++ b/tcg/tcg.c
34
@@ -XXX,XX +XXX,XX @@ void tcg_context_init(TCGContext *s)
35
int op, total_args, n, i;
36
TCGOpDef *def;
37
TCGArgConstraint *args_ct;
38
- int *sorted_args;
39
TCGTemp *ts;
40
41
memset(s, 0, sizeof(*s));
42
@@ -XXX,XX +XXX,XX @@ void tcg_context_init(TCGContext *s)
17
}
43
}
18
44
19
- /* Handle watchpoints. */
45
args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
20
- if (tlb_addr & TLB_WATCHPOINT) {
46
- sorted_args = g_malloc(sizeof(int) * total_args);
21
- cpu_check_watchpoint(env_cpu(env), addr, size,
47
22
- env_tlb(env)->d[mmu_idx].iotlb[index].attrs,
48
for(op = 0; op < NB_OPS; op++) {
23
- wp_access, retaddr);
49
def = &tcg_op_defs[op];
24
- }
50
def->args_ct = args_ct;
25
+ if (unlikely(tlb_addr & TLB_FLAGS_MASK)) {
51
- def->sorted_args = sorted_args;
26
+ CPUIOTLBEntry *iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
52
n = def->nb_iargs + def->nb_oargs;
27
53
- sorted_args += n;
28
- /* Reject I/O access, or other required slow-path. */
54
args_ct += n;
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
}
55
}
47
56
48
return (void *)((uintptr_t)addr + entry->addend);
57
@@ -XXX,XX +XXX,XX @@ static int get_constraint_priority(const TCGOpDef *def, int k)
58
/* sort from highest priority to lowest */
59
static void sort_constraints(TCGOpDef *def, int start, int n)
60
{
61
- int i, j, p1, p2, tmp;
62
+ int i, j;
63
+ TCGArgConstraint *a = def->args_ct;
64
65
- for(i = 0; i < n; i++)
66
- def->sorted_args[start + i] = start + i;
67
- if (n <= 1)
68
+ for (i = 0; i < n; i++) {
69
+ a[start + i].sort_index = start + i;
70
+ }
71
+ if (n <= 1) {
72
return;
73
- for(i = 0; i < n - 1; i++) {
74
- for(j = i + 1; j < n; j++) {
75
- p1 = get_constraint_priority(def, def->sorted_args[start + i]);
76
- p2 = get_constraint_priority(def, def->sorted_args[start + j]);
77
+ }
78
+ for (i = 0; i < n - 1; i++) {
79
+ for (j = i + 1; j < n; j++) {
80
+ int p1 = get_constraint_priority(def, a[start + i].sort_index);
81
+ int p2 = get_constraint_priority(def, a[start + j].sort_index);
82
if (p1 < p2) {
83
- tmp = def->sorted_args[start + i];
84
- def->sorted_args[start + i] = def->sorted_args[start + j];
85
- def->sorted_args[start + j] = tmp;
86
+ int tmp = a[start + i].sort_index;
87
+ a[start + i].sort_index = a[start + j].sort_index;
88
+ a[start + j].sort_index = tmp;
89
}
90
}
91
}
92
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
93
for (k = 0; k < nb_iargs; k++) {
94
TCGRegSet i_preferred_regs, o_preferred_regs;
95
96
- i = def->sorted_args[nb_oargs + k];
97
+ i = def->args_ct[nb_oargs + k].sort_index;
98
arg = op->args[i];
99
arg_ct = &def->args_ct[i];
100
ts = arg_temp(arg);
101
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
102
int k2, i2;
103
reg = ts->reg;
104
for (k2 = 0 ; k2 < k ; k2++) {
105
- i2 = def->sorted_args[nb_oargs + k2];
106
+ i2 = def->args_ct[nb_oargs + k2].sort_index;
107
if ((def->args_ct[i2].ct & TCG_CT_IALIAS) &&
108
reg == new_args[i2]) {
109
goto allocate_in_reg;
110
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
111
112
/* satisfy the output constraints */
113
for(k = 0; k < nb_oargs; k++) {
114
- i = def->sorted_args[k];
115
+ i = def->args_ct[k].sort_index;
116
arg = op->args[i];
117
arg_ct = &def->args_ct[i];
118
ts = arg_temp(arg);
49
--
119
--
50
2.17.1
120
2.25.1
51
121
52
122
diff view generated by jsdifflib
1
Fixes the previous TLB_WATCHPOINT patches because we are currently
1
This wasn't actually used for anything, really. All variable
2
failing to set cpu->mem_io_pc with the call to cpu_check_watchpoint.
2
operands must accept registers, and which are indicated by the
3
Pass down the retaddr directly because it's readily available.
3
set in TCGArgConstraint.regs.
4
4
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>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
6
---
10
accel/tcg/translate-all.h | 2 +-
7
include/tcg/tcg.h | 1 -
11
accel/tcg/translate-all.c | 6 +++---
8
tcg/tcg.c | 15 ++++-----------
12
exec.c | 2 +-
9
tcg/aarch64/tcg-target.c.inc | 3 ---
13
3 files changed, 5 insertions(+), 5 deletions(-)
10
tcg/arm/tcg-target.c.inc | 3 ---
11
tcg/i386/tcg-target.c.inc | 11 -----------
12
tcg/mips/tcg-target.c.inc | 3 ---
13
tcg/ppc/tcg-target.c.inc | 5 -----
14
tcg/riscv/tcg-target.c.inc | 2 --
15
tcg/s390/tcg-target.c.inc | 4 ----
16
tcg/sparc/tcg-target.c.inc | 5 -----
17
tcg/tci/tcg-target.c.inc | 1 -
18
11 files changed, 4 insertions(+), 49 deletions(-)
14
19
15
diff --git a/accel/tcg/translate-all.h b/accel/tcg/translate-all.h
20
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
16
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
17
--- a/accel/tcg/translate-all.h
22
--- a/include/tcg/tcg.h
18
+++ b/accel/tcg/translate-all.h
23
+++ b/include/tcg/tcg.h
19
@@ -XXX,XX +XXX,XX @@ void tb_invalidate_phys_page_fast(struct page_collection *pages,
24
@@ -XXX,XX +XXX,XX @@ void tcg_dump_op_count(void);
20
tb_page_addr_t start, int len,
25
#define TCG_CT_ALIAS 0x80
21
uintptr_t retaddr);
26
#define TCG_CT_IALIAS 0x40
22
void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end);
27
#define TCG_CT_NEWREG 0x20 /* output requires a new register */
23
-void tb_check_watchpoint(CPUState *cpu);
28
-#define TCG_CT_REG 0x01
24
+void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr);
29
#define TCG_CT_CONST 0x02 /* any constant of register size */
25
30
26
#ifdef CONFIG_USER_ONLY
31
typedef struct TCGArgConstraint {
27
int page_unprotect(target_ulong address, uintptr_t pc);
32
diff --git a/tcg/tcg.c b/tcg/tcg.c
28
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
33
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
34
--- a/tcg/tcg.c
30
--- a/accel/tcg/translate-all.c
35
+++ b/tcg/tcg.c
31
+++ b/accel/tcg/translate-all.c
36
@@ -XXX,XX +XXX,XX @@ static void tcg_dump_ops(TCGContext *s, bool have_prefs)
32
@@ -XXX,XX +XXX,XX @@ static bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc)
37
/* we give more priority to constraints with less registers */
38
static int get_constraint_priority(const TCGOpDef *def, int k)
39
{
40
- const TCGArgConstraint *arg_ct;
41
+ const TCGArgConstraint *arg_ct = &def->args_ct[k];
42
+ int n;
43
44
- int i, n;
45
- arg_ct = &def->args_ct[k];
46
if (arg_ct->ct & TCG_CT_ALIAS) {
47
/* an alias is equivalent to a single register */
48
n = 1;
49
} else {
50
- if (!(arg_ct->ct & TCG_CT_REG))
51
- return 0;
52
- n = 0;
53
- for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
54
- if (tcg_regset_test_reg(arg_ct->regs, i))
55
- n++;
56
- }
57
+ n = ctpop64(arg_ct->regs);
58
}
59
return TCG_TARGET_NB_REGS - n + 1;
60
}
61
@@ -XXX,XX +XXX,XX @@ static void process_op_defs(TCGContext *s)
62
int oarg = *ct_str - '0';
63
tcg_debug_assert(ct_str == tdefs->args_ct_str[i]);
64
tcg_debug_assert(oarg < def->nb_oargs);
65
- tcg_debug_assert(def->args_ct[oarg].ct & TCG_CT_REG);
66
+ tcg_debug_assert(def->args_ct[oarg].regs != 0);
67
/* TCG_CT_ALIAS is for the output arguments.
68
The input is tagged with TCG_CT_IALIAS. */
69
def->args_ct[i] = def->args_ct[oarg];
70
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
71
index XXXXXXX..XXXXXXX 100644
72
--- a/tcg/aarch64/tcg-target.c.inc
73
+++ b/tcg/aarch64/tcg-target.c.inc
74
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
75
{
76
switch (*ct_str++) {
77
case 'r': /* general registers */
78
- ct->ct |= TCG_CT_REG;
79
ct->regs |= 0xffffffffu;
80
break;
81
case 'w': /* advsimd registers */
82
- ct->ct |= TCG_CT_REG;
83
ct->regs |= 0xffffffff00000000ull;
84
break;
85
case 'l': /* qemu_ld / qemu_st address, data_reg */
86
- ct->ct |= TCG_CT_REG;
87
ct->regs = 0xffffffffu;
88
#ifdef CONFIG_SOFTMMU
89
/* x0 and x1 will be overwritten when reading the tlb entry,
90
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
91
index XXXXXXX..XXXXXXX 100644
92
--- a/tcg/arm/tcg-target.c.inc
93
+++ b/tcg/arm/tcg-target.c.inc
94
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
95
break;
96
97
case 'r':
98
- ct->ct |= TCG_CT_REG;
99
ct->regs = 0xffff;
100
break;
101
102
/* qemu_ld address */
103
case 'l':
104
- ct->ct |= TCG_CT_REG;
105
ct->regs = 0xffff;
106
#ifdef CONFIG_SOFTMMU
107
/* r0-r2,lr will be overwritten when reading the tlb entry,
108
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
109
110
/* qemu_st address & data */
111
case 's':
112
- ct->ct |= TCG_CT_REG;
113
ct->regs = 0xffff;
114
/* r0-r2 will be overwritten when reading the tlb entry (softmmu only)
115
and r0-r1 doing the byte swapping, so don't use these. */
116
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
117
index XXXXXXX..XXXXXXX 100644
118
--- a/tcg/i386/tcg-target.c.inc
119
+++ b/tcg/i386/tcg-target.c.inc
120
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
121
{
122
switch(*ct_str++) {
123
case 'a':
124
- ct->ct |= TCG_CT_REG;
125
tcg_regset_set_reg(ct->regs, TCG_REG_EAX);
126
break;
127
case 'b':
128
- ct->ct |= TCG_CT_REG;
129
tcg_regset_set_reg(ct->regs, TCG_REG_EBX);
130
break;
131
case 'c':
132
- ct->ct |= TCG_CT_REG;
133
tcg_regset_set_reg(ct->regs, TCG_REG_ECX);
134
break;
135
case 'd':
136
- ct->ct |= TCG_CT_REG;
137
tcg_regset_set_reg(ct->regs, TCG_REG_EDX);
138
break;
139
case 'S':
140
- ct->ct |= TCG_CT_REG;
141
tcg_regset_set_reg(ct->regs, TCG_REG_ESI);
142
break;
143
case 'D':
144
- ct->ct |= TCG_CT_REG;
145
tcg_regset_set_reg(ct->regs, TCG_REG_EDI);
146
break;
147
case 'q':
148
/* A register that can be used as a byte operand. */
149
- ct->ct |= TCG_CT_REG;
150
ct->regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xf;
151
break;
152
case 'Q':
153
/* A register with an addressable second byte (e.g. %ah). */
154
- ct->ct |= TCG_CT_REG;
155
ct->regs = 0xf;
156
break;
157
case 'r':
158
/* A general register. */
159
- ct->ct |= TCG_CT_REG;
160
ct->regs |= ALL_GENERAL_REGS;
161
break;
162
case 'W':
163
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
164
break;
165
case 'x':
166
/* A vector register. */
167
- ct->ct |= TCG_CT_REG;
168
ct->regs |= ALL_VECTOR_REGS;
169
break;
170
171
/* qemu_ld/st address constraint */
172
case 'L':
173
- ct->ct |= TCG_CT_REG;
174
ct->regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xff;
175
tcg_regset_reset_reg(ct->regs, TCG_REG_L0);
176
tcg_regset_reset_reg(ct->regs, TCG_REG_L1);
177
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
178
index XXXXXXX..XXXXXXX 100644
179
--- a/tcg/mips/tcg-target.c.inc
180
+++ b/tcg/mips/tcg-target.c.inc
181
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
182
{
183
switch(*ct_str++) {
184
case 'r':
185
- ct->ct |= TCG_CT_REG;
186
ct->regs = 0xffffffff;
187
break;
188
case 'L': /* qemu_ld input arg constraint */
189
- ct->ct |= TCG_CT_REG;
190
ct->regs = 0xffffffff;
191
tcg_regset_reset_reg(ct->regs, TCG_REG_A0);
192
#if defined(CONFIG_SOFTMMU)
193
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
33
#endif
194
#endif
34
195
break;
35
/* user-mode: call with mmap_lock held */
196
case 'S': /* qemu_st constraint */
36
-void tb_check_watchpoint(CPUState *cpu)
197
- ct->ct |= TCG_CT_REG;
37
+void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr)
198
ct->regs = 0xffffffff;
38
{
199
tcg_regset_reset_reg(ct->regs, TCG_REG_A0);
39
TranslationBlock *tb;
200
#if defined(CONFIG_SOFTMMU)
40
201
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
41
assert_memory_lock();
202
index XXXXXXX..XXXXXXX 100644
42
203
--- a/tcg/ppc/tcg-target.c.inc
43
- tb = tcg_tb_lookup(cpu->mem_io_pc);
204
+++ b/tcg/ppc/tcg-target.c.inc
44
+ tb = tcg_tb_lookup(retaddr);
205
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
45
if (tb) {
206
{
46
/* We can use retranslation to find the PC. */
207
switch (*ct_str++) {
47
- cpu_restore_state_from_tb(cpu, tb, cpu->mem_io_pc, true);
208
case 'A': case 'B': case 'C': case 'D':
48
+ cpu_restore_state_from_tb(cpu, tb, retaddr, true);
209
- ct->ct |= TCG_CT_REG;
49
tb_phys_invalidate(tb, -1);
210
tcg_regset_set_reg(ct->regs, 3 + ct_str[0] - 'A');
50
} else {
211
break;
51
/* The exception probably happened in a helper. The CPU state should
212
case 'r':
52
diff --git a/exec.c b/exec.c
213
- ct->ct |= TCG_CT_REG;
53
index XXXXXXX..XXXXXXX 100644
214
ct->regs = 0xffffffff;
54
--- a/exec.c
215
break;
55
+++ b/exec.c
216
case 'v':
56
@@ -XXX,XX +XXX,XX @@ void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
217
- ct->ct |= TCG_CT_REG;
57
cpu->watchpoint_hit = wp;
218
ct->regs = 0xffffffff00000000ull;
58
219
break;
59
mmap_lock();
220
case 'L': /* qemu_ld constraint */
60
- tb_check_watchpoint(cpu);
221
- ct->ct |= TCG_CT_REG;
61
+ tb_check_watchpoint(cpu, ra);
222
ct->regs = 0xffffffff;
62
if (wp->flags & BP_STOP_BEFORE_ACCESS) {
223
tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
63
cpu->exception_index = EXCP_DEBUG;
224
#ifdef CONFIG_SOFTMMU
64
mmap_unlock();
225
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
226
#endif
227
break;
228
case 'S': /* qemu_st constraint */
229
- ct->ct |= TCG_CT_REG;
230
ct->regs = 0xffffffff;
231
tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
232
#ifdef CONFIG_SOFTMMU
233
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
234
index XXXXXXX..XXXXXXX 100644
235
--- a/tcg/riscv/tcg-target.c.inc
236
+++ b/tcg/riscv/tcg-target.c.inc
237
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
238
{
239
switch (*ct_str++) {
240
case 'r':
241
- ct->ct |= TCG_CT_REG;
242
ct->regs = 0xffffffff;
243
break;
244
case 'L':
245
/* qemu_ld/qemu_st constraint */
246
- ct->ct |= TCG_CT_REG;
247
ct->regs = 0xffffffff;
248
/* qemu_ld/qemu_st uses TCG_REG_TMP0 */
249
#if defined(CONFIG_SOFTMMU)
250
diff --git a/tcg/s390/tcg-target.c.inc b/tcg/s390/tcg-target.c.inc
251
index XXXXXXX..XXXXXXX 100644
252
--- a/tcg/s390/tcg-target.c.inc
253
+++ b/tcg/s390/tcg-target.c.inc
254
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
255
{
256
switch (*ct_str++) {
257
case 'r': /* all registers */
258
- ct->ct |= TCG_CT_REG;
259
ct->regs = 0xffff;
260
break;
261
case 'L': /* qemu_ld/st constraint */
262
- ct->ct |= TCG_CT_REG;
263
ct->regs = 0xffff;
264
tcg_regset_reset_reg(ct->regs, TCG_REG_R2);
265
tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
266
tcg_regset_reset_reg(ct->regs, TCG_REG_R4);
267
break;
268
case 'a': /* force R2 for division */
269
- ct->ct |= TCG_CT_REG;
270
ct->regs = 0;
271
tcg_regset_set_reg(ct->regs, TCG_REG_R2);
272
break;
273
case 'b': /* force R3 for division */
274
- ct->ct |= TCG_CT_REG;
275
ct->regs = 0;
276
tcg_regset_set_reg(ct->regs, TCG_REG_R3);
277
break;
278
diff --git a/tcg/sparc/tcg-target.c.inc b/tcg/sparc/tcg-target.c.inc
279
index XXXXXXX..XXXXXXX 100644
280
--- a/tcg/sparc/tcg-target.c.inc
281
+++ b/tcg/sparc/tcg-target.c.inc
282
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
283
{
284
switch (*ct_str++) {
285
case 'r':
286
- ct->ct |= TCG_CT_REG;
287
ct->regs = 0xffffffff;
288
break;
289
case 'R':
290
- ct->ct |= TCG_CT_REG;
291
ct->regs = ALL_64;
292
break;
293
case 'A': /* qemu_ld/st address constraint */
294
- ct->ct |= TCG_CT_REG;
295
ct->regs = TARGET_LONG_BITS == 64 ? ALL_64 : 0xffffffff;
296
reserve_helpers:
297
tcg_regset_reset_reg(ct->regs, TCG_REG_O0);
298
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
299
tcg_regset_reset_reg(ct->regs, TCG_REG_O2);
300
break;
301
case 's': /* qemu_st data 32-bit constraint */
302
- ct->ct |= TCG_CT_REG;
303
ct->regs = 0xffffffff;
304
goto reserve_helpers;
305
case 'S': /* qemu_st data 64-bit constraint */
306
- ct->ct |= TCG_CT_REG;
307
ct->regs = ALL_64;
308
goto reserve_helpers;
309
case 'I':
310
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
311
index XXXXXXX..XXXXXXX 100644
312
--- a/tcg/tci/tcg-target.c.inc
313
+++ b/tcg/tci/tcg-target.c.inc
314
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
315
case 'r':
316
case 'L': /* qemu_ld constraint */
317
case 'S': /* qemu_st constraint */
318
- ct->ct |= TCG_CT_REG;
319
ct->regs = BIT(TCG_TARGET_NB_REGS) - 1;
320
break;
321
default:
65
--
322
--
66
2.17.1
323
2.25.1
67
324
68
325
diff view generated by jsdifflib
1
Since 9458a9a1df1a, all readers of the dirty bitmaps wait
1
These are easier to set and test when they have their own fields.
2
for the rcu lock, which means that they wait until the end
2
Reduce the size of alias_index and sort_index to 4 bits, which is
3
of any executing TranslationBlock.
3
sufficient for TCG_MAX_OP_ARGS. This leaves only the bits indicating
4
constants within the ct field.
4
5
5
As a consequence, there is no need for the actual access
6
Move all initialization to allocation time, rather than init
6
to happen in between the _prepare and _complete. Therefore,
7
individual fields in process_op_defs.
7
we can improve things by merging the two functions into
8
notdirty_write and dropping the NotDirtyInfo structure.
9
8
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>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
17
---
10
---
18
include/exec/memory-internal.h | 65 -----------------------------
11
include/tcg/tcg.h | 14 +++++++-------
19
accel/tcg/cputlb.c | 76 +++++++++++++++++++---------------
12
tcg/tcg.c | 28 ++++++++++++----------------
20
exec.c | 44 --------------------
13
2 files changed, 19 insertions(+), 23 deletions(-)
21
3 files changed, 42 insertions(+), 143 deletions(-)
22
14
23
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
15
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
24
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
25
--- a/include/exec/memory-internal.h
17
--- a/include/tcg/tcg.h
26
+++ b/include/exec/memory-internal.h
18
+++ b/include/tcg/tcg.h
27
@@ -XXX,XX +XXX,XX @@ void address_space_dispatch_free(AddressSpaceDispatch *d);
19
@@ -XXX,XX +XXX,XX @@ int64_t tcg_cpu_exec_time(void);
28
20
void tcg_dump_info(void);
29
void mtree_print_dispatch(struct AddressSpaceDispatch *d,
21
void tcg_dump_op_count(void);
30
MemoryRegion *root);
22
31
-
23
-#define TCG_CT_ALIAS 0x80
32
-struct page_collection;
24
-#define TCG_CT_IALIAS 0x40
33
-
25
-#define TCG_CT_NEWREG 0x20 /* output requires a new register */
34
-/* Opaque struct for passing info from memory_notdirty_write_prepare()
26
-#define TCG_CT_CONST 0x02 /* any constant of register size */
35
- * to memory_notdirty_write_complete(). Callers should treat all fields
27
+#define TCG_CT_CONST 1 /* any constant of register size */
36
- * as private, with the exception of @active.
28
37
- *
29
typedef struct TCGArgConstraint {
38
- * @active is a field which is not touched by either the prepare or
30
- uint16_t ct;
39
- * complete functions, but which the caller can use if it wishes to
31
- uint8_t alias_index;
40
- * track whether it has called prepare for this struct and so needs
32
- uint8_t sort_index;
41
- * to later call the complete function.
33
+ unsigned ct : 16;
42
- */
34
+ unsigned alias_index : 4;
43
-typedef struct {
35
+ unsigned sort_index : 4;
44
- CPUState *cpu;
36
+ bool oalias : 1;
45
- struct page_collection *pages;
37
+ bool ialias : 1;
46
- ram_addr_t ram_addr;
38
+ bool newreg : 1;
47
- vaddr mem_vaddr;
39
TCGRegSet regs;
48
- unsigned size;
40
} TCGArgConstraint;
49
- bool active;
41
50
-} NotDirtyInfo;
42
diff --git a/tcg/tcg.c b/tcg/tcg.c
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
43
index XXXXXXX..XXXXXXX 100644
100
--- a/accel/tcg/cputlb.c
44
--- a/tcg/tcg.c
101
+++ b/accel/tcg/cputlb.c
45
+++ b/tcg/tcg.c
102
@@ -XXX,XX +XXX,XX @@
46
@@ -XXX,XX +XXX,XX @@ void tcg_context_init(TCGContext *s)
103
#include "exec/helper-proto.h"
47
total_args += n;
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
}
48
}
171
49
172
return hostaddr;
50
- args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
173
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
51
+ args_ct = g_new0(TCGArgConstraint, total_args);
174
return;
52
53
for(op = 0; op < NB_OPS; op++) {
54
def = &tcg_op_defs[op];
55
@@ -XXX,XX +XXX,XX @@ static int get_constraint_priority(const TCGOpDef *def, int k)
56
const TCGArgConstraint *arg_ct = &def->args_ct[k];
57
int n;
58
59
- if (arg_ct->ct & TCG_CT_ALIAS) {
60
+ if (arg_ct->oalias) {
61
/* an alias is equivalent to a single register */
62
n = 1;
63
} else {
64
@@ -XXX,XX +XXX,XX @@ static void process_op_defs(TCGContext *s)
65
/* Incomplete TCGTargetOpDef entry. */
66
tcg_debug_assert(ct_str != NULL);
67
68
- def->args_ct[i].regs = 0;
69
- def->args_ct[i].ct = 0;
70
while (*ct_str != '\0') {
71
switch(*ct_str) {
72
case '0' ... '9':
73
@@ -XXX,XX +XXX,XX @@ static void process_op_defs(TCGContext *s)
74
tcg_debug_assert(ct_str == tdefs->args_ct_str[i]);
75
tcg_debug_assert(oarg < def->nb_oargs);
76
tcg_debug_assert(def->args_ct[oarg].regs != 0);
77
- /* TCG_CT_ALIAS is for the output arguments.
78
- The input is tagged with TCG_CT_IALIAS. */
79
def->args_ct[i] = def->args_ct[oarg];
80
- def->args_ct[oarg].ct |= TCG_CT_ALIAS;
81
+ /* The output sets oalias. */
82
+ def->args_ct[oarg].oalias = true;
83
def->args_ct[oarg].alias_index = i;
84
- def->args_ct[i].ct |= TCG_CT_IALIAS;
85
+ /* The input sets ialias. */
86
+ def->args_ct[i].ialias = true;
87
def->args_ct[i].alias_index = oarg;
88
}
89
ct_str++;
90
break;
91
case '&':
92
- def->args_ct[i].ct |= TCG_CT_NEWREG;
93
+ def->args_ct[i].newreg = true;
94
ct_str++;
95
break;
96
case 'i':
97
@@ -XXX,XX +XXX,XX @@ static void liveness_pass_1(TCGContext *s)
98
set = *pset;
99
100
set &= ct->regs;
101
- if (ct->ct & TCG_CT_IALIAS) {
102
+ if (ct->ialias) {
103
set &= op->output_pref[ct->alias_index];
104
}
105
/* If the combination is not possible, restart. */
106
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
175
}
107
}
176
108
177
- haddr = (void *)((uintptr_t)addr + entry->addend);
109
i_preferred_regs = o_preferred_regs = 0;
178
-
110
- if (arg_ct->ct & TCG_CT_IALIAS) {
179
/* Handle clean RAM pages. */
111
+ if (arg_ct->ialias) {
180
if (tlb_addr & TLB_NOTDIRTY) {
112
o_preferred_regs = op->output_pref[arg_ct->alias_index];
181
- NotDirtyInfo ndi;
113
if (ts->fixed_reg) {
182
-
114
/* if fixed register, we must allocate a new register
183
- /* We require mem_io_pc in tb_invalidate_phys_page_range. */
115
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
184
- env_cpu(env)->mem_io_pc = retaddr;
116
reg = ts->reg;
185
-
117
for (k2 = 0 ; k2 < k ; k2++) {
186
- memory_notdirty_write_prepare(&ndi, env_cpu(env), addr,
118
i2 = def->args_ct[nb_oargs + k2].sort_index;
187
- addr + iotlbentry->addr, size);
119
- if ((def->args_ct[i2].ct & TCG_CT_IALIAS) &&
188
-
120
- reg == new_args[i2]) {
189
- if (unlikely(need_swap)) {
121
+ if (def->args_ct[i2].ialias && reg == new_args[i2]) {
190
- store_memop(haddr, val, op ^ MO_BSWAP);
122
goto allocate_in_reg;
191
- } else {
123
}
192
- store_memop(haddr, val, op);
124
}
193
- }
125
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
194
-
126
/* ENV should not be modified. */
195
- memory_notdirty_write_complete(&ndi);
127
tcg_debug_assert(!ts->fixed_reg);
196
- return;
128
197
+ notdirty_write(env_cpu(env), addr, size, iotlbentry, retaddr);
129
- if ((arg_ct->ct & TCG_CT_ALIAS)
198
}
130
- && !const_args[arg_ct->alias_index]) {
199
131
+ if (arg_ct->oalias && !const_args[arg_ct->alias_index]) {
200
+ haddr = (void *)((uintptr_t)addr + entry->addend);
132
reg = new_args[arg_ct->alias_index];
201
+
133
- } else if (arg_ct->ct & TCG_CT_NEWREG) {
202
/*
134
+ } else if (arg_ct->newreg) {
203
* Keep these two store_memop separate to ensure that the compiler
135
reg = tcg_reg_alloc(s, arg_ct->regs,
204
* is able to fold the entire function to a single instruction.
136
i_allocated_regs | o_allocated_regs,
205
@@ -XXX,XX +XXX,XX @@ void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
137
op->output_pref[k], ts->indirect_base);
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
--
138
--
288
2.17.1
139
2.25.1
289
140
290
141
diff view generated by jsdifflib
1
Rather than rely on cpu->mem_io_pc, pass retaddr down directly.
1
The last user of this field disappeared in f69d277ece4.
2
2
3
Within tb_invalidate_phys_page_range__locked, the is_cpu_write_access
3
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
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>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
---
5
---
14
accel/tcg/translate-all.h | 3 ++-
6
include/tcg/tcg.h | 3 ---
15
accel/tcg/cputlb.c | 6 +-----
7
1 file changed, 3 deletions(-)
16
accel/tcg/translate-all.c | 39 +++++++++++++++++++--------------------
17
3 files changed, 22 insertions(+), 26 deletions(-)
18
8
19
diff --git a/accel/tcg/translate-all.h b/accel/tcg/translate-all.h
9
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
20
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
21
--- a/accel/tcg/translate-all.h
11
--- a/include/tcg/tcg.h
22
+++ b/accel/tcg/translate-all.h
12
+++ b/include/tcg/tcg.h
23
@@ -XXX,XX +XXX,XX @@ struct page_collection *page_collection_lock(tb_page_addr_t start,
13
@@ -XXX,XX +XXX,XX @@ typedef struct TCGOpDef {
24
tb_page_addr_t end);
14
uint8_t nb_oargs, nb_iargs, nb_cargs, nb_args;
25
void page_collection_unlock(struct page_collection *set);
15
uint8_t flags;
26
void tb_invalidate_phys_page_fast(struct page_collection *pages,
16
TCGArgConstraint *args_ct;
27
- tb_page_addr_t start, int len);
17
-#if defined(CONFIG_DEBUG_TCG)
28
+ tb_page_addr_t start, int len,
18
- int used;
29
+ uintptr_t retaddr);
19
-#endif
30
void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end);
20
} TCGOpDef;
31
void tb_check_watchpoint(CPUState *cpu);
21
32
22
extern TCGOpDef tcg_op_defs[];
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
--
23
--
133
2.17.1
24
2.25.1
134
25
135
26
diff view generated by jsdifflib
1
All callers pass false to this argument. Remove it and pass the
1
The previous change wrongly stated that 32-bit avx2 should have
2
constant on to tb_invalidate_phys_page_range__locked.
2
used VPBROADCASTW. But that's a 16-bit broadcast and we want a
3
32-bit broadcast.
3
4
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Fixes: 7b60ef3264e
5
Reviewed-by: David Hildenbrand <david@redhat.com>
6
Cc: qemu-stable@nongnu.org
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
---
8
accel/tcg/translate-all.h | 3 +--
9
tcg/i386/tcg-target.c.inc | 2 +-
9
accel/tcg/translate-all.c | 6 ++----
10
1 file changed, 1 insertion(+), 1 deletion(-)
10
exec.c | 4 ++--
11
3 files changed, 5 insertions(+), 8 deletions(-)
12
11
13
diff --git a/accel/tcg/translate-all.h b/accel/tcg/translate-all.h
12
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/accel/tcg/translate-all.h
14
--- a/tcg/i386/tcg-target.c.inc
16
+++ b/accel/tcg/translate-all.h
15
+++ b/tcg/i386/tcg-target.c.inc
17
@@ -XXX,XX +XXX,XX @@ struct page_collection *page_collection_lock(tb_page_addr_t start,
16
@@ -XXX,XX +XXX,XX @@ static void tcg_out_dupi_vec(TCGContext *s, TCGType type,
18
void page_collection_unlock(struct page_collection *set);
17
new_pool_label(s, arg, R_386_PC32, s->code_ptr - 4, -4);
19
void tb_invalidate_phys_page_fast(struct page_collection *pages,
18
} else {
20
tb_page_addr_t start, int len);
19
if (have_avx2) {
21
-void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
20
- tcg_out_vex_modrm_pool(s, OPC_VPBROADCASTW + vex_l, ret);
22
- int is_cpu_write_access);
21
+ tcg_out_vex_modrm_pool(s, OPC_VPBROADCASTD + vex_l, ret);
23
+void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end);
22
} else {
24
void tb_check_watchpoint(CPUState *cpu);
23
tcg_out_vex_modrm_pool(s, OPC_VBROADCASTSS, ret);
25
24
}
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
--
25
--
74
2.17.1
26
2.25.1
75
27
76
28
diff view generated by jsdifflib
1
Pages that we want to track for NOTDIRTY are RAM. We do not
1
The definition of INDEX_op_dupi_vec is that it operates on
2
really need to go through the I/O path to handle them.
2
units of tcg_target_ulong -- in this case 32 bits. It does
3
not work to use this for a uint64_t value that happens to be
4
small enough to fit in tcg_target_ulong.
3
5
4
Acked-by: David Hildenbrand <david@redhat.com>
6
Fixes: d2fd745fe8b
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Fixes: db432672dc5
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Cc: qemu-stable@nongnu.org
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
10
---
9
include/exec/cpu-common.h | 2 --
11
tcg/tcg-op-vec.c | 12 ++++++++----
10
accel/tcg/cputlb.c | 26 +++++++++++++++++---
12
1 file changed, 8 insertions(+), 4 deletions(-)
11
exec.c | 50 ---------------------------------------
12
memory.c | 16 -------------
13
4 files changed, 23 insertions(+), 71 deletions(-)
14
13
15
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
14
diff --git a/tcg/tcg-op-vec.c b/tcg/tcg-op-vec.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/include/exec/cpu-common.h
16
--- a/tcg/tcg-op-vec.c
18
+++ b/include/exec/cpu-common.h
17
+++ b/tcg/tcg-op-vec.c
19
@@ -XXX,XX +XXX,XX @@ void qemu_flush_coalesced_mmio_buffer(void);
18
@@ -XXX,XX +XXX,XX @@ TCGv_vec tcg_const_ones_vec_matching(TCGv_vec m)
20
19
21
void cpu_flush_icache_range(hwaddr start, hwaddr len);
20
void tcg_gen_dup64i_vec(TCGv_vec r, uint64_t a)
22
21
{
23
-extern struct MemoryRegion io_mem_notdirty;
22
- if (TCG_TARGET_REG_BITS == 32 && a == deposit64(a, 32, 32, a)) {
24
-
23
- do_dupi_vec(r, MO_32, a);
25
typedef int (RAMBlockIterFunc)(RAMBlock *rb, void *opaque);
24
- } else if (TCG_TARGET_REG_BITS == 64 || a == (uint64_t)(int32_t)a) {
26
25
+ if (TCG_TARGET_REG_BITS == 64) {
27
int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque);
26
do_dupi_vec(r, MO_64, a);
28
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
27
+ } else if (a == dup_const(MO_32, a)) {
29
index XXXXXXX..XXXXXXX 100644
28
+ do_dupi_vec(r, MO_32, a);
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 {
29
} else {
114
AddressSpaceDispatch *d;
30
TCGv_i64 c = tcg_const_i64(a);
115
31
tcg_gen_dup_i64_vec(MO_64, r, c);
116
@@ -XXX,XX +XXX,XX @@ void memory_notdirty_write_complete(NotDirtyInfo *ndi)
32
@@ -XXX,XX +XXX,XX @@ void tcg_gen_dup8i_vec(TCGv_vec r, uint32_t a)
117
}
33
34
void tcg_gen_dupi_vec(unsigned vece, TCGv_vec r, uint64_t a)
35
{
36
- do_dupi_vec(r, MO_REG, dup_const(vece, a));
37
+ if (vece == MO_64) {
38
+ tcg_gen_dup64i_vec(r, a);
39
+ } else {
40
+ do_dupi_vec(r, MO_REG, dup_const(vece, a));
41
+ }
118
}
42
}
119
43
120
-/* Called within RCU critical section. */
44
void tcg_gen_dup_i64_vec(unsigned vece, TCGv_vec r, TCGv_i64 a)
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
--
45
--
231
2.17.1
46
2.25.1
232
47
233
48
diff view generated by jsdifflib
1
Use this as a compile-time assert that a particular
1
When the two arguments are identical, this can be reduced to
2
code path is not reachable.
2
dup_vec or to mov_vec from a tcg_constant_vec.
3
3
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
5
---
7
include/qemu/compiler.h | 15 +++++++++++++++
6
tcg/optimize.c | 15 +++++++++++++++
8
1 file changed, 15 insertions(+)
7
1 file changed, 15 insertions(+)
9
8
10
diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
9
diff --git a/tcg/optimize.c b/tcg/optimize.c
11
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
12
--- a/include/qemu/compiler.h
11
--- a/tcg/optimize.c
13
+++ b/include/qemu/compiler.h
12
+++ b/tcg/optimize.c
14
@@ -XXX,XX +XXX,XX @@
13
@@ -XXX,XX +XXX,XX @@ void tcg_optimize(TCGContext *s)
15
#define QEMU_GENERIC9(x, a0, ...) QEMU_GENERIC_IF(x, a0, QEMU_GENERIC8(x, __VA_ARGS__))
14
}
16
#define QEMU_GENERIC10(x, a0, ...) QEMU_GENERIC_IF(x, a0, QEMU_GENERIC9(x, __VA_ARGS__))
15
goto do_default;
17
16
18
+/**
17
+ case INDEX_op_dup2_vec:
19
+ * qemu_build_not_reached()
18
+ assert(TCG_TARGET_REG_BITS == 32);
20
+ *
19
+ if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
21
+ * The compiler, during optimization, is expected to prove that a call
20
+ tmp = arg_info(op->args[1])->val;
22
+ * to this function cannot be reached and remove it. If the compiler
21
+ if (tmp == arg_info(op->args[2])->val) {
23
+ * supports QEMU_ERROR, this will be reported at compile time; otherwise
22
+ tcg_opt_gen_movi(s, op, op->args[0], tmp);
24
+ * this will be reported at link time due to the missing symbol.
23
+ break;
25
+ */
24
+ }
26
+#ifdef __OPTIMIZE__
25
+ } else if (args_are_copies(op->args[1], op->args[2])) {
27
+extern void QEMU_NORETURN QEMU_ERROR("code path is reachable")
26
+ op->opc = INDEX_op_dup_vec;
28
+ qemu_build_not_reached(void);
27
+ TCGOP_VECE(op) = MO_32;
29
+#else
28
+ nb_iargs = 1;
30
+#define qemu_build_not_reached() g_assert_not_reached()
29
+ }
31
+#endif
30
+ goto do_default;
32
+
31
+
33
#endif /* COMPILER_H */
32
CASE_OP_32_64(not):
33
CASE_OP_32_64(neg):
34
CASE_OP_32_64(ext8s):
34
--
35
--
35
2.17.1
36
2.25.1
36
37
37
38
diff view generated by jsdifflib
1
With the merge of notdirty handling into store_helper,
1
The cmp_vec opcode is mandatory; this symbol is unused.
2
the last user of cpu->mem_io_vaddr was removed.
3
2
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: David Hildenbrand <david@redhat.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
5
---
8
include/hw/core/cpu.h | 2 --
6
tcg/aarch64/tcg-target.h | 1 -
9
accel/tcg/cputlb.c | 2 --
7
tcg/i386/tcg-target.h | 1 -
10
hw/core/cpu.c | 1 -
8
tcg/ppc/tcg-target.h | 1 -
11
3 files changed, 5 deletions(-)
9
3 files changed, 3 deletions(-)
12
10
13
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
11
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
14
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/core/cpu.h
13
--- a/tcg/aarch64/tcg-target.h
16
+++ b/include/hw/core/cpu.h
14
+++ b/tcg/aarch64/tcg-target.h
17
@@ -XXX,XX +XXX,XX @@ struct qemu_work_item;
15
@@ -XXX,XX +XXX,XX @@ typedef enum {
18
* @next_cpu: Next CPU sharing TB cache.
16
#define TCG_TARGET_HAS_shi_vec 1
19
* @opaque: User data.
17
#define TCG_TARGET_HAS_shs_vec 0
20
* @mem_io_pc: Host Program Counter at which the memory was accessed.
18
#define TCG_TARGET_HAS_shv_vec 1
21
- * @mem_io_vaddr: Target virtual address at which the memory was accessed.
19
-#define TCG_TARGET_HAS_cmp_vec 1
22
* @kvm_fd: vCPU file descriptor for KVM.
20
#define TCG_TARGET_HAS_mul_vec 1
23
* @work_mutex: Lock to prevent multiple access to queued_work_*.
21
#define TCG_TARGET_HAS_sat_vec 1
24
* @queued_work_first: First asynchronous work pending.
22
#define TCG_TARGET_HAS_minmax_vec 1
25
@@ -XXX,XX +XXX,XX @@ struct CPUState {
23
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
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
24
index XXXXXXX..XXXXXXX 100644
35
--- a/accel/tcg/cputlb.c
25
--- a/tcg/i386/tcg-target.h
36
+++ b/accel/tcg/cputlb.c
26
+++ b/tcg/i386/tcg-target.h
37
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
27
@@ -XXX,XX +XXX,XX @@ extern bool have_avx2;
38
cpu_io_recompile(cpu, retaddr);
28
#define TCG_TARGET_HAS_shi_vec 1
39
}
29
#define TCG_TARGET_HAS_shs_vec 1
40
30
#define TCG_TARGET_HAS_shv_vec have_avx2
41
- cpu->mem_io_vaddr = addr;
31
-#define TCG_TARGET_HAS_cmp_vec 1
42
cpu->mem_io_access_type = access_type;
32
#define TCG_TARGET_HAS_mul_vec 1
43
33
#define TCG_TARGET_HAS_sat_vec 1
44
if (mr->global_locking && !qemu_mutex_iothread_locked()) {
34
#define TCG_TARGET_HAS_minmax_vec 1
45
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
35
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
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
36
index XXXXXXX..XXXXXXX 100644
55
--- a/hw/core/cpu.c
37
--- a/tcg/ppc/tcg-target.h
56
+++ b/hw/core/cpu.c
38
+++ b/tcg/ppc/tcg-target.h
57
@@ -XXX,XX +XXX,XX @@ static void cpu_common_reset(CPUState *cpu)
39
@@ -XXX,XX +XXX,XX @@ extern bool have_vsx;
58
cpu->interrupt_request = 0;
40
#define TCG_TARGET_HAS_shi_vec 0
59
cpu->halted = 0;
41
#define TCG_TARGET_HAS_shs_vec 0
60
cpu->mem_io_pc = 0;
42
#define TCG_TARGET_HAS_shv_vec 1
61
- cpu->mem_io_vaddr = 0;
43
-#define TCG_TARGET_HAS_cmp_vec 1
62
cpu->icount_extra = 0;
44
#define TCG_TARGET_HAS_mul_vec 1
63
atomic_set(&cpu->icount_decr_ptr->u32, 0);
45
#define TCG_TARGET_HAS_sat_vec 1
64
cpu->can_do_io = 1;
46
#define TCG_TARGET_HAS_minmax_vec 1
65
--
47
--
66
2.17.1
48
2.25.1
67
49
68
50
diff view generated by jsdifflib
1
Increase the current runtime assert to a compile-time assert.
1
From: Kele Huang <kele.hwang@gmail.com>
2
2
3
Reviewed-by: David Hildenbrand <david@redhat.com>
3
Detect all MIPS store instructions in cpu_signal_handler for all available
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
MIPS versions, and set is_write if encountering such store instructions.
5
6
This fixed the error while dealing with self-modified code for MIPS.
7
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Kele Huang <kele.hwang@gmail.com>
10
Signed-off-by: Xu Zou <iwatchnima@gmail.com>
11
Message-Id: <20201002081420.10814-1-kele.hwang@gmail.com>
12
[rth: Use uintptr_t for pc to fix n32 build error.]
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
14
---
7
accel/tcg/cputlb.c | 5 ++---
15
accel/tcg/user-exec.c | 43 +++++++++++++++++++++++++++++++++++++++----
8
1 file changed, 2 insertions(+), 3 deletions(-)
16
1 file changed, 39 insertions(+), 4 deletions(-)
9
17
10
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
18
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
11
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
12
--- a/accel/tcg/cputlb.c
20
--- a/accel/tcg/user-exec.c
13
+++ b/accel/tcg/cputlb.c
21
+++ b/accel/tcg/user-exec.c
14
@@ -XXX,XX +XXX,XX @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
22
@@ -XXX,XX +XXX,XX @@ int cpu_signal_handler(int host_signum, void *pinfo,
15
res = ldq_le_p(haddr);
23
16
break;
24
#elif defined(__mips__)
17
default:
25
18
- g_assert_not_reached();
26
+#if defined(__misp16) || defined(__mips_micromips)
19
+ qemu_build_not_reached();
27
+#error "Unsupported encoding"
20
}
28
+#endif
21
29
+
22
return res;
30
int cpu_signal_handler(int host_signum, void *pinfo,
23
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
31
void *puc)
24
stq_le_p(haddr, val);
32
{
25
break;
33
siginfo_t *info = pinfo;
26
default:
34
ucontext_t *uc = puc;
27
- g_assert_not_reached();
35
- greg_t pc = uc->uc_mcontext.pc;
28
- break;
36
- int is_write;
29
+ qemu_build_not_reached();
37
+ uintptr_t pc = uc->uc_mcontext.pc;
30
}
38
+ uint32_t insn = *(uint32_t *)pc;
39
+ int is_write = 0;
40
+
41
+ /* Detect all store instructions at program counter. */
42
+ switch((insn >> 26) & 077) {
43
+ case 050: /* SB */
44
+ case 051: /* SH */
45
+ case 052: /* SWL */
46
+ case 053: /* SW */
47
+ case 054: /* SDL */
48
+ case 055: /* SDR */
49
+ case 056: /* SWR */
50
+ case 070: /* SC */
51
+ case 071: /* SWC1 */
52
+ case 074: /* SCD */
53
+ case 075: /* SDC1 */
54
+ case 077: /* SD */
55
+#if !defined(__mips_isa_rev) || __mips_isa_rev < 6
56
+ case 072: /* SWC2 */
57
+ case 076: /* SDC2 */
58
+#endif
59
+ is_write = 1;
60
+ break;
61
+ case 023: /* COP1X */
62
+ /* Required in all versions of MIPS64 since
63
+ MIPS64r1 and subsequent versions of MIPS32r2. */
64
+ switch (insn & 077) {
65
+ case 010: /* SWXC1 */
66
+ case 011: /* SDXC1 */
67
+ case 015: /* SUXC1 */
68
+ is_write = 1;
69
+ }
70
+ break;
71
+ }
72
73
- /* XXX: compute is_write */
74
- is_write = 0;
75
return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
31
}
76
}
32
77
33
--
78
--
34
2.17.1
79
2.25.1
35
80
36
81
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
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