1
This is v4 of my notdirty + rom patch set with two suggested name
1
The following changes since commit 3e08b2b9cb64bff2b73fa9128c0e49bfcde0dd40:
2
changes (qemu_build_not_reached, TLB_DISCARD_WRITE) from David and Alex.
3
2
4
3
Merge remote-tracking branch 'remotes/philmd-gitlab/tags/edk2-next-20200121' into staging (2020-01-21 15:29:25 +0000)
5
r~
6
7
8
The following changes since commit 240ab11fb72049d6373cbbec8d788f8e411a00bc:
9
10
Merge remote-tracking branch 'remotes/aperard/tags/pull-xen-20190924' into staging (2019-09-24 15:36:31 +0100)
11
4
12
are available in the Git repository at:
5
are available in the Git repository at:
13
6
14
https://github.com/rth7680/qemu.git tags/pull-tcg-20190925
7
https://github.com/rth7680/qemu.git tags/pull-tcg-20200121
15
8
16
for you to fetch changes up to ae57db63acf5a0399232f852acc5c1d83ef63400:
9
for you to fetch changes up to 75fa376cdab5e5db2c7fdd107358e16f95503ac6:
17
10
18
cputlb: Pass retaddr to tb_check_watchpoint (2019-09-25 10:56:28 -0700)
11
scripts/git.orderfile: Display decodetree before C source (2020-01-21 15:26:09 -1000)
19
12
20
----------------------------------------------------------------
13
----------------------------------------------------------------
21
Fixes for TLB_BSWAP
14
Remove another limit to NB_MMU_MODES.
22
Coversion of NOTDIRTY and ROM handling to cputlb
15
Fix compilation using uclibc.
23
Followup cleanups to cputlb
16
Fix defaulting of -accel parameters.
17
Tidy cputlb basic routines.
18
Adjust git.orderfile for decodetree.
24
19
25
----------------------------------------------------------------
20
----------------------------------------------------------------
26
Richard Henderson (16):
21
Carlos Santos (1):
27
exec: Use TARGET_PAGE_BITS_MIN for TLB flags
22
util/cacheinfo: fix crash when compiling with uClibc
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
23
44
accel/tcg/translate-all.h | 8 +-
24
Philippe Mathieu-Daudé (1):
45
include/exec/cpu-all.h | 23 ++-
25
scripts/git.orderfile: Display decodetree before C source
46
include/exec/cpu-common.h | 3 -
47
include/exec/exec-all.h | 6 +-
48
include/exec/memory-internal.h | 65 --------
49
include/hw/core/cpu.h | 2 -
50
include/qemu/compiler.h | 26 +++
51
accel/tcg/cputlb.c | 348 +++++++++++++++++++++++++----------------
52
accel/tcg/translate-all.c | 51 +++---
53
exec.c | 158 +------------------
54
hw/core/cpu.c | 1 -
55
memory.c | 20 ---
56
trace-events | 4 +-
57
13 files changed, 288 insertions(+), 427 deletions(-)
58
26
27
Richard Henderson (14):
28
cputlb: Handle NB_MMU_MODES > TARGET_PAGE_BITS_MIN
29
vl: Remove unused variable in configure_accelerators
30
vl: Reduce scope of variables in configure_accelerators
31
vl: Remove useless test in configure_accelerators
32
vl: Only choose enabled accelerators in configure_accelerators
33
cputlb: Merge tlb_table_flush_by_mmuidx into tlb_flush_one_mmuidx_locked
34
cputlb: Make tlb_n_entries private to cputlb.c
35
cputlb: Pass CPUTLBDescFast to tlb_n_entries and sizeof_tlb
36
cputlb: Hoist tlb portions in tlb_mmu_resize_locked
37
cputlb: Hoist tlb portions in tlb_flush_one_mmuidx_locked
38
cputlb: Split out tlb_mmu_flush_locked
39
cputlb: Partially merge tlb_dyn_init into tlb_init
40
cputlb: Initialize tlbs as flushed
41
cputlb: Hoist timestamp outside of loops over tlbs
42
43
include/exec/cpu_ldst.h | 5 -
44
accel/tcg/cputlb.c | 287 +++++++++++++++++++++++++++++++++---------------
45
util/cacheinfo.c | 10 +-
46
vl.c | 27 +++--
47
scripts/git.orderfile | 3 +
48
5 files changed, 223 insertions(+), 109 deletions(-)
49
diff view generated by jsdifflib
1
We can use notdirty_write for the write and return a valid host
1
In target/arm we will shortly have "too many" mmu_idx.
2
pointer for this case.
2
The current minimum barrier is caused by the way in which
3
3
tlb_flush_page_by_mmuidx is coded.
4
Reviewed-by: David Hildenbrand <david@redhat.com>
4
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
We can remove this limitation by allocating memory for
6
consumption by the worker. Let us assume that this is
7
the unlikely case, as will be the case for the majority
8
of targets which have so far satisfied the BUILD_BUG_ON,
9
and only allocate memory when necessary.
10
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
13
---
8
accel/tcg/cputlb.c | 26 +++++++++++++++++---------
14
accel/tcg/cputlb.c | 167 +++++++++++++++++++++++++++++++++++----------
9
1 file changed, 17 insertions(+), 9 deletions(-)
15
1 file changed, 132 insertions(+), 35 deletions(-)
10
16
11
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
17
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/accel/tcg/cputlb.c
19
--- a/accel/tcg/cputlb.c
14
+++ b/accel/tcg/cputlb.c
20
+++ b/accel/tcg/cputlb.c
15
@@ -XXX,XX +XXX,XX @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
21
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_page_locked(CPUArchState *env, int midx,
16
return NULL;
17
}
22
}
18
23
}
19
- /* Handle watchpoints. */
24
20
- if (tlb_addr & TLB_WATCHPOINT) {
25
-/* As we are going to hijack the bottom bits of the page address for a
21
- cpu_check_watchpoint(env_cpu(env), addr, size,
26
- * mmuidx bit mask we need to fail to build if we can't do that
22
- env_tlb(env)->d[mmu_idx].iotlb[index].attrs,
27
+/**
23
- wp_access, retaddr);
28
+ * tlb_flush_page_by_mmuidx_async_0:
24
- }
29
+ * @cpu: cpu on which to flush
25
+ if (unlikely(tlb_addr & TLB_FLAGS_MASK)) {
30
+ * @addr: page of virtual address to flush
26
+ CPUIOTLBEntry *iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
31
+ * @idxmap: set of mmu_idx to flush
27
32
+ *
28
- /* Reject I/O access, or other required slow-path. */
33
+ * Helper for tlb_flush_page_by_mmuidx and friends, flush one page
29
- if (tlb_addr & (TLB_NOTDIRTY | TLB_MMIO | TLB_BSWAP | TLB_DISCARD_WRITE)) {
34
+ * at @addr from the tlbs indicated by @idxmap from @cpu.
30
- return NULL;
35
*/
31
+ /* Reject I/O access, or other required slow-path. */
36
-QEMU_BUILD_BUG_ON(NB_MMU_MODES > TARGET_PAGE_BITS_MIN);
32
+ if (tlb_addr & (TLB_MMIO | TLB_BSWAP | TLB_DISCARD_WRITE)) {
37
-
33
+ return NULL;
38
-static void tlb_flush_page_by_mmuidx_async_work(CPUState *cpu,
39
- run_on_cpu_data data)
40
+static void tlb_flush_page_by_mmuidx_async_0(CPUState *cpu,
41
+ target_ulong addr,
42
+ uint16_t idxmap)
43
{
44
CPUArchState *env = cpu->env_ptr;
45
- target_ulong addr_and_mmuidx = (target_ulong) data.target_ptr;
46
- target_ulong addr = addr_and_mmuidx & TARGET_PAGE_MASK;
47
- unsigned long mmu_idx_bitmap = addr_and_mmuidx & ALL_MMUIDX_BITS;
48
int mmu_idx;
49
50
assert_cpu_is_self(cpu);
51
52
- tlb_debug("page addr:" TARGET_FMT_lx " mmu_map:0x%lx\n",
53
- addr, mmu_idx_bitmap);
54
+ tlb_debug("page addr:" TARGET_FMT_lx " mmu_map:0x%x\n", addr, idxmap);
55
56
qemu_spin_lock(&env_tlb(env)->c.lock);
57
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
58
- if (test_bit(mmu_idx, &mmu_idx_bitmap)) {
59
+ if ((idxmap >> mmu_idx) & 1) {
60
tlb_flush_page_locked(env, mmu_idx, addr);
61
}
62
}
63
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_page_by_mmuidx_async_work(CPUState *cpu,
64
tb_flush_jmp_cache(cpu, addr);
65
}
66
67
+/**
68
+ * tlb_flush_page_by_mmuidx_async_1:
69
+ * @cpu: cpu on which to flush
70
+ * @data: encoded addr + idxmap
71
+ *
72
+ * Helper for tlb_flush_page_by_mmuidx and friends, called through
73
+ * async_run_on_cpu. The idxmap parameter is encoded in the page
74
+ * offset of the target_ptr field. This limits the set of mmu_idx
75
+ * that can be passed via this method.
76
+ */
77
+static void tlb_flush_page_by_mmuidx_async_1(CPUState *cpu,
78
+ run_on_cpu_data data)
79
+{
80
+ target_ulong addr_and_idxmap = (target_ulong) data.target_ptr;
81
+ target_ulong addr = addr_and_idxmap & TARGET_PAGE_MASK;
82
+ uint16_t idxmap = addr_and_idxmap & ~TARGET_PAGE_MASK;
83
+
84
+ tlb_flush_page_by_mmuidx_async_0(cpu, addr, idxmap);
85
+}
86
+
87
+typedef struct {
88
+ target_ulong addr;
89
+ uint16_t idxmap;
90
+} TLBFlushPageByMMUIdxData;
91
+
92
+/**
93
+ * tlb_flush_page_by_mmuidx_async_2:
94
+ * @cpu: cpu on which to flush
95
+ * @data: allocated addr + idxmap
96
+ *
97
+ * Helper for tlb_flush_page_by_mmuidx and friends, called through
98
+ * async_run_on_cpu. The addr+idxmap parameters are stored in a
99
+ * TLBFlushPageByMMUIdxData structure that has been allocated
100
+ * specifically for this helper. Free the structure when done.
101
+ */
102
+static void tlb_flush_page_by_mmuidx_async_2(CPUState *cpu,
103
+ run_on_cpu_data data)
104
+{
105
+ TLBFlushPageByMMUIdxData *d = data.host_ptr;
106
+
107
+ tlb_flush_page_by_mmuidx_async_0(cpu, d->addr, d->idxmap);
108
+ g_free(d);
109
+}
110
+
111
void tlb_flush_page_by_mmuidx(CPUState *cpu, target_ulong addr, uint16_t idxmap)
112
{
113
- target_ulong addr_and_mmu_idx;
114
-
115
tlb_debug("addr: "TARGET_FMT_lx" mmu_idx:%" PRIx16 "\n", addr, idxmap);
116
117
/* This should already be page aligned */
118
- addr_and_mmu_idx = addr & TARGET_PAGE_MASK;
119
- addr_and_mmu_idx |= idxmap;
120
+ addr &= TARGET_PAGE_MASK;
121
122
- if (!qemu_cpu_is_self(cpu)) {
123
- async_run_on_cpu(cpu, tlb_flush_page_by_mmuidx_async_work,
124
- RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
125
+ if (qemu_cpu_is_self(cpu)) {
126
+ tlb_flush_page_by_mmuidx_async_0(cpu, addr, idxmap);
127
+ } else if (idxmap < TARGET_PAGE_SIZE) {
128
+ /*
129
+ * Most targets have only a few mmu_idx. In the case where
130
+ * we can stuff idxmap into the low TARGET_PAGE_BITS, avoid
131
+ * allocating memory for this operation.
132
+ */
133
+ async_run_on_cpu(cpu, tlb_flush_page_by_mmuidx_async_1,
134
+ RUN_ON_CPU_TARGET_PTR(addr | idxmap));
135
} else {
136
- tlb_flush_page_by_mmuidx_async_work(
137
- cpu, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
138
+ TLBFlushPageByMMUIdxData *d = g_new(TLBFlushPageByMMUIdxData, 1);
139
+
140
+ /* Otherwise allocate a structure, freed by the worker. */
141
+ d->addr = addr;
142
+ d->idxmap = idxmap;
143
+ async_run_on_cpu(cpu, tlb_flush_page_by_mmuidx_async_2,
144
+ RUN_ON_CPU_HOST_PTR(d));
145
}
146
}
147
148
@@ -XXX,XX +XXX,XX @@ void tlb_flush_page(CPUState *cpu, target_ulong addr)
149
void tlb_flush_page_by_mmuidx_all_cpus(CPUState *src_cpu, target_ulong addr,
150
uint16_t idxmap)
151
{
152
- const run_on_cpu_func fn = tlb_flush_page_by_mmuidx_async_work;
153
- target_ulong addr_and_mmu_idx;
154
-
155
tlb_debug("addr: "TARGET_FMT_lx" mmu_idx:%"PRIx16"\n", addr, idxmap);
156
157
/* This should already be page aligned */
158
- addr_and_mmu_idx = addr & TARGET_PAGE_MASK;
159
- addr_and_mmu_idx |= idxmap;
160
+ addr &= TARGET_PAGE_MASK;
161
162
- flush_all_helper(src_cpu, fn, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
163
- fn(src_cpu, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
164
+ /*
165
+ * Allocate memory to hold addr+idxmap only when needed.
166
+ * See tlb_flush_page_by_mmuidx for details.
167
+ */
168
+ if (idxmap < TARGET_PAGE_SIZE) {
169
+ flush_all_helper(src_cpu, tlb_flush_page_by_mmuidx_async_1,
170
+ RUN_ON_CPU_TARGET_PTR(addr | idxmap));
171
+ } else {
172
+ CPUState *dst_cpu;
173
+
174
+ /* Allocate a separate data block for each destination cpu. */
175
+ CPU_FOREACH(dst_cpu) {
176
+ if (dst_cpu != src_cpu) {
177
+ TLBFlushPageByMMUIdxData *d
178
+ = g_new(TLBFlushPageByMMUIdxData, 1);
179
+
180
+ d->addr = addr;
181
+ d->idxmap = idxmap;
182
+ async_run_on_cpu(dst_cpu, tlb_flush_page_by_mmuidx_async_2,
183
+ RUN_ON_CPU_HOST_PTR(d));
184
+ }
34
+ }
185
+ }
35
+
186
+ }
36
+ /* Handle watchpoints. */
187
+
37
+ if (tlb_addr & TLB_WATCHPOINT) {
188
+ tlb_flush_page_by_mmuidx_async_0(src_cpu, addr, idxmap);
38
+ cpu_check_watchpoint(env_cpu(env), addr, size,
189
}
39
+ iotlbentry->attrs, wp_access, retaddr);
190
191
void tlb_flush_page_all_cpus(CPUState *src, target_ulong addr)
192
@@ -XXX,XX +XXX,XX @@ void tlb_flush_page_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
193
target_ulong addr,
194
uint16_t idxmap)
195
{
196
- const run_on_cpu_func fn = tlb_flush_page_by_mmuidx_async_work;
197
- target_ulong addr_and_mmu_idx;
198
-
199
tlb_debug("addr: "TARGET_FMT_lx" mmu_idx:%"PRIx16"\n", addr, idxmap);
200
201
/* This should already be page aligned */
202
- addr_and_mmu_idx = addr & TARGET_PAGE_MASK;
203
- addr_and_mmu_idx |= idxmap;
204
+ addr &= TARGET_PAGE_MASK;
205
206
- flush_all_helper(src_cpu, fn, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
207
- async_safe_run_on_cpu(src_cpu, fn, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
208
+ /*
209
+ * Allocate memory to hold addr+idxmap only when needed.
210
+ * See tlb_flush_page_by_mmuidx for details.
211
+ */
212
+ if (idxmap < TARGET_PAGE_SIZE) {
213
+ flush_all_helper(src_cpu, tlb_flush_page_by_mmuidx_async_1,
214
+ RUN_ON_CPU_TARGET_PTR(addr | idxmap));
215
+ async_safe_run_on_cpu(src_cpu, tlb_flush_page_by_mmuidx_async_1,
216
+ RUN_ON_CPU_TARGET_PTR(addr | idxmap));
217
+ } else {
218
+ CPUState *dst_cpu;
219
+ TLBFlushPageByMMUIdxData *d;
220
+
221
+ /* Allocate a separate data block for each destination cpu. */
222
+ CPU_FOREACH(dst_cpu) {
223
+ if (dst_cpu != src_cpu) {
224
+ d = g_new(TLBFlushPageByMMUIdxData, 1);
225
+ d->addr = addr;
226
+ d->idxmap = idxmap;
227
+ async_run_on_cpu(dst_cpu, tlb_flush_page_by_mmuidx_async_2,
228
+ RUN_ON_CPU_HOST_PTR(d));
229
+ }
40
+ }
230
+ }
41
+
231
+
42
+ /* Handle clean RAM pages. */
232
+ d = g_new(TLBFlushPageByMMUIdxData, 1);
43
+ if (tlb_addr & TLB_NOTDIRTY) {
233
+ d->addr = addr;
44
+ notdirty_write(env_cpu(env), addr, size, iotlbentry, retaddr);
234
+ d->idxmap = idxmap;
45
+ }
235
+ async_safe_run_on_cpu(src_cpu, tlb_flush_page_by_mmuidx_async_2,
46
}
236
+ RUN_ON_CPU_HOST_PTR(d));
47
237
+ }
48
return (void *)((uintptr_t)addr + entry->addend);
238
}
239
240
void tlb_flush_page_all_cpus_synced(CPUState *src, target_ulong addr)
49
--
241
--
50
2.17.1
242
2.20.1
51
243
52
244
diff view generated by jsdifflib
1
Fixes the previous TLB_WATCHPOINT patches because we are currently
1
From: Carlos Santos <casantos@redhat.com>
2
failing to set cpu->mem_io_pc with the call to cpu_check_watchpoint.
3
Pass down the retaddr directly because it's readily available.
4
2
5
Fixes: 50b107c5d61
3
uClibc defines _SC_LEVEL1_ICACHE_LINESIZE and _SC_LEVEL1_DCACHE_LINESIZE
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
but the corresponding sysconf calls returns -1, which is a valid result,
7
Reviewed-by: David Hildenbrand <david@redhat.com>
5
meaning that the limit is indeterminate.
6
7
Handle this situation using the fallback values instead of crashing due
8
to an assertion failure.
9
10
Signed-off-by: Carlos Santos <casantos@redhat.com>
11
Message-Id: <20191017123713.30192-1-casantos@redhat.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
13
---
10
accel/tcg/translate-all.h | 2 +-
14
util/cacheinfo.c | 10 ++++++++--
11
accel/tcg/translate-all.c | 6 +++---
15
1 file changed, 8 insertions(+), 2 deletions(-)
12
exec.c | 2 +-
13
3 files changed, 5 insertions(+), 5 deletions(-)
14
16
15
diff --git a/accel/tcg/translate-all.h b/accel/tcg/translate-all.h
17
diff --git a/util/cacheinfo.c b/util/cacheinfo.c
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/accel/tcg/translate-all.h
19
--- a/util/cacheinfo.c
18
+++ b/accel/tcg/translate-all.h
20
+++ b/util/cacheinfo.c
19
@@ -XXX,XX +XXX,XX @@ void tb_invalidate_phys_page_fast(struct page_collection *pages,
21
@@ -XXX,XX +XXX,XX @@ static void sys_cache_info(int *isize, int *dsize)
20
tb_page_addr_t start, int len,
22
static void sys_cache_info(int *isize, int *dsize)
21
uintptr_t retaddr);
22
void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end);
23
-void tb_check_watchpoint(CPUState *cpu);
24
+void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr);
25
26
#ifdef CONFIG_USER_ONLY
27
int page_unprotect(target_ulong address, uintptr_t pc);
28
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/accel/tcg/translate-all.c
31
+++ b/accel/tcg/translate-all.c
32
@@ -XXX,XX +XXX,XX @@ static bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc)
33
#endif
34
35
/* user-mode: call with mmap_lock held */
36
-void tb_check_watchpoint(CPUState *cpu)
37
+void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr)
38
{
23
{
39
TranslationBlock *tb;
24
# ifdef _SC_LEVEL1_ICACHE_LINESIZE
40
25
- *isize = sysconf(_SC_LEVEL1_ICACHE_LINESIZE);
41
assert_memory_lock();
26
+ int tmp_isize = (int) sysconf(_SC_LEVEL1_ICACHE_LINESIZE);
42
27
+ if (tmp_isize > 0) {
43
- tb = tcg_tb_lookup(cpu->mem_io_pc);
28
+ *isize = tmp_isize;
44
+ tb = tcg_tb_lookup(retaddr);
29
+ }
45
if (tb) {
30
# endif
46
/* We can use retranslation to find the PC. */
31
# ifdef _SC_LEVEL1_DCACHE_LINESIZE
47
- cpu_restore_state_from_tb(cpu, tb, cpu->mem_io_pc, true);
32
- *dsize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
48
+ cpu_restore_state_from_tb(cpu, tb, retaddr, true);
33
+ int tmp_dsize = (int) sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
49
tb_phys_invalidate(tb, -1);
34
+ if (tmp_dsize > 0) {
50
} else {
35
+ *dsize = tmp_dsize;
51
/* The exception probably happened in a helper. The CPU state should
36
+ }
52
diff --git a/exec.c b/exec.c
37
# endif
53
index XXXXXXX..XXXXXXX 100644
38
}
54
--- a/exec.c
39
#endif /* sys_cache_info */
55
+++ b/exec.c
56
@@ -XXX,XX +XXX,XX @@ void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
57
cpu->watchpoint_hit = wp;
58
59
mmap_lock();
60
- tb_check_watchpoint(cpu);
61
+ tb_check_watchpoint(cpu, ra);
62
if (wp->flags & BP_STOP_BEFORE_ACCESS) {
63
cpu->exception_index = EXCP_DEBUG;
64
mmap_unlock();
65
--
40
--
66
2.17.1
41
2.20.1
67
42
68
43
diff view generated by jsdifflib
1
All callers pass false to this argument. Remove it and pass the
1
The accel_initialised variable no longer has any setters.
2
constant on to tb_invalidate_phys_page_range__locked.
3
2
3
Fixes: 6f6e1698a68c
4
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: David Hildenbrand <david@redhat.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed by: Aleksandar Markovic <amarkovic@wavecomp.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
9
---
8
accel/tcg/translate-all.h | 3 +--
10
vl.c | 3 +--
9
accel/tcg/translate-all.c | 6 ++----
11
1 file changed, 1 insertion(+), 2 deletions(-)
10
exec.c | 4 ++--
11
3 files changed, 5 insertions(+), 8 deletions(-)
12
12
13
diff --git a/accel/tcg/translate-all.h b/accel/tcg/translate-all.h
13
diff --git a/vl.c b/vl.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/accel/tcg/translate-all.h
15
--- a/vl.c
16
+++ b/accel/tcg/translate-all.h
16
+++ b/vl.c
17
@@ -XXX,XX +XXX,XX @@ struct page_collection *page_collection_lock(tb_page_addr_t start,
17
@@ -XXX,XX +XXX,XX @@ static void configure_accelerators(const char *progname)
18
void page_collection_unlock(struct page_collection *set);
19
void tb_invalidate_phys_page_fast(struct page_collection *pages,
20
tb_page_addr_t start, int len);
21
-void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
22
- int is_cpu_write_access);
23
+void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end);
24
void tb_check_watchpoint(CPUState *cpu);
25
26
#ifdef CONFIG_USER_ONLY
27
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/accel/tcg/translate-all.c
30
+++ b/accel/tcg/translate-all.c
31
@@ -XXX,XX +XXX,XX @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
32
*
33
* Called with mmap_lock held for user-mode emulation
34
*/
35
-void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
36
- int is_cpu_write_access)
37
+void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end)
38
{
18
{
39
struct page_collection *pages;
19
const char *accel;
40
PageDesc *p;
20
char **accel_list, **tmp;
41
@@ -XXX,XX +XXX,XX @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
21
- bool accel_initialised = false;
42
return;
22
bool init_failed = false;
43
}
23
44
pages = page_collection_lock(start, end);
24
qemu_opts_foreach(qemu_find_opts("icount"),
45
- tb_invalidate_phys_page_range__locked(pages, p, start, end,
25
@@ -XXX,XX +XXX,XX @@ static void configure_accelerators(const char *progname)
46
- is_cpu_write_access);
26
47
+ tb_invalidate_phys_page_range__locked(pages, p, start, end, 0);
27
accel_list = g_strsplit(accel, ":", 0);
48
page_collection_unlock(pages);
28
49
}
29
- for (tmp = accel_list; !accel_initialised && tmp && *tmp; tmp++) {
50
30
+ for (tmp = accel_list; tmp && *tmp; tmp++) {
51
diff --git a/exec.c b/exec.c
31
/*
52
index XXXXXXX..XXXXXXX 100644
32
* Filter invalid accelerators here, to prevent obscenities
53
--- a/exec.c
33
* such as "-machine accel=tcg,,thread=single".
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
--
34
--
74
2.17.1
35
2.20.1
75
36
76
37
diff view generated by jsdifflib
1
Handle bswap on ram directly in load/store_helper. This fixes a
1
The accel_list and tmp variables are only used when manufacturing
2
bug with the previous implementation in that one cannot use the
2
-machine accel, options based on -accel.
3
I/O path for RAM.
4
3
5
Fixes: a26fc6f5152b47f1
4
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: David Hildenbrand <david@redhat.com>
6
Reviewed by: Aleksandar Markovic <amarkovic@wavecomp.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
8
---
10
include/exec/cpu-all.h | 4 ++-
9
vl.c | 3 ++-
11
accel/tcg/cputlb.c | 72 +++++++++++++++++++++++++-----------------
10
1 file changed, 2 insertions(+), 1 deletion(-)
12
2 files changed, 46 insertions(+), 30 deletions(-)
13
11
14
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
12
diff --git a/vl.c b/vl.c
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
16
--- a/include/exec/cpu-all.h
14
--- a/vl.c
17
+++ b/include/exec/cpu-all.h
15
+++ b/vl.c
18
@@ -XXX,XX +XXX,XX @@ CPUArchState *cpu_copy(CPUArchState *env);
16
@@ -XXX,XX +XXX,XX @@ static int do_configure_accelerator(void *opaque, QemuOpts *opts, Error **errp)
19
#define TLB_MMIO (1 << (TARGET_PAGE_BITS_MIN - 3))
17
static void configure_accelerators(const char *progname)
20
/* Set if TLB entry contains a watchpoint. */
18
{
21
#define TLB_WATCHPOINT (1 << (TARGET_PAGE_BITS_MIN - 4))
19
const char *accel;
22
+/* Set if TLB entry requires byte swap. */
20
- char **accel_list, **tmp;
23
+#define TLB_BSWAP (1 << (TARGET_PAGE_BITS_MIN - 5))
21
bool init_failed = false;
24
22
25
/* Use this mask to check interception with an alignment mask
23
qemu_opts_foreach(qemu_find_opts("icount"),
26
* in a TCG backend.
24
@@ -XXX,XX +XXX,XX @@ static void configure_accelerators(const char *progname)
27
*/
25
28
#define TLB_FLAGS_MASK \
26
accel = qemu_opt_get(qemu_get_machine_opts(), "accel");
29
- (TLB_INVALID_MASK | TLB_NOTDIRTY | TLB_MMIO | TLB_WATCHPOINT)
27
if (QTAILQ_EMPTY(&qemu_accel_opts.head)) {
30
+ (TLB_INVALID_MASK | TLB_NOTDIRTY | TLB_MMIO | TLB_WATCHPOINT | TLB_BSWAP)
28
+ char **accel_list, **tmp;
31
32
/**
33
* tlb_hit_page: return true if page aligned @addr is a hit against the
34
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/accel/tcg/cputlb.c
37
+++ b/accel/tcg/cputlb.c
38
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
39
address |= TLB_INVALID_MASK;
40
}
41
if (attrs.byte_swap) {
42
- /* Force the access through the I/O slow path. */
43
- address |= TLB_MMIO;
44
+ address |= TLB_BSWAP;
45
}
46
if (!memory_region_is_ram(section->mr) &&
47
!memory_region_is_romd(section->mr)) {
48
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
49
bool locked = false;
50
MemTxResult r;
51
52
- if (iotlbentry->attrs.byte_swap) {
53
- op ^= MO_BSWAP;
54
- }
55
-
56
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
57
mr = section->mr;
58
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
59
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
60
bool locked = false;
61
MemTxResult r;
62
63
- if (iotlbentry->attrs.byte_swap) {
64
- op ^= MO_BSWAP;
65
- }
66
-
67
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
68
mr = section->mr;
69
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
70
@@ -XXX,XX +XXX,XX @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
71
wp_access, retaddr);
72
}
73
74
- if (tlb_addr & (TLB_NOTDIRTY | TLB_MMIO)) {
75
- /* I/O access */
76
+ /* Reject I/O access, or other required slow-path. */
77
+ if (tlb_addr & (TLB_NOTDIRTY | TLB_MMIO | TLB_BSWAP)) {
78
return NULL;
79
}
80
81
@@ -XXX,XX +XXX,XX @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
82
/* Handle anything that isn't just a straight memory access. */
83
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
84
CPUIOTLBEntry *iotlbentry;
85
+ bool need_swap;
86
87
/* For anything that is unaligned, recurse through full_load. */
88
if ((addr & (size - 1)) != 0) {
89
@@ -XXX,XX +XXX,XX @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
90
/* On watchpoint hit, this will longjmp out. */
91
cpu_check_watchpoint(env_cpu(env), addr, size,
92
iotlbentry->attrs, BP_MEM_READ, retaddr);
93
-
94
- /* The backing page may or may not require I/O. */
95
- tlb_addr &= ~TLB_WATCHPOINT;
96
- if ((tlb_addr & ~TARGET_PAGE_MASK) == 0) {
97
- goto do_aligned_access;
98
- }
99
}
100
101
+ need_swap = size > 1 && (tlb_addr & TLB_BSWAP);
102
+
29
+
103
/* Handle I/O access. */
30
if (accel == NULL) {
104
- return io_readx(env, iotlbentry, mmu_idx, addr,
31
/* Select the default accelerator */
105
- retaddr, access_type, op);
32
if (!accel_find("tcg") && !accel_find("kvm")) {
106
+ if (likely(tlb_addr & TLB_MMIO)) {
107
+ return io_readx(env, iotlbentry, mmu_idx, addr, retaddr,
108
+ access_type, op ^ (need_swap * MO_BSWAP));
109
+ }
110
+
111
+ haddr = (void *)((uintptr_t)addr + entry->addend);
112
+
113
+ /*
114
+ * Keep these two load_memop separate to ensure that the compiler
115
+ * is able to fold the entire function to a single instruction.
116
+ * There is a build-time assert inside to remind you of this. ;-)
117
+ */
118
+ if (unlikely(need_swap)) {
119
+ return load_memop(haddr, op ^ MO_BSWAP);
120
+ }
121
+ return load_memop(haddr, op);
122
}
123
124
/* Handle slow unaligned access (it spans two pages or IO). */
125
@@ -XXX,XX +XXX,XX @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
126
return res & MAKE_64BIT_MASK(0, size * 8);
127
}
128
129
- do_aligned_access:
130
haddr = (void *)((uintptr_t)addr + entry->addend);
131
return load_memop(haddr, op);
132
}
133
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
134
/* Handle anything that isn't just a straight memory access. */
135
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
136
CPUIOTLBEntry *iotlbentry;
137
+ bool need_swap;
138
139
/* For anything that is unaligned, recurse through byte stores. */
140
if ((addr & (size - 1)) != 0) {
141
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
142
/* On watchpoint hit, this will longjmp out. */
143
cpu_check_watchpoint(env_cpu(env), addr, size,
144
iotlbentry->attrs, BP_MEM_WRITE, retaddr);
145
-
146
- /* The backing page may or may not require I/O. */
147
- tlb_addr &= ~TLB_WATCHPOINT;
148
- if ((tlb_addr & ~TARGET_PAGE_MASK) == 0) {
149
- goto do_aligned_access;
150
- }
151
}
152
153
+ need_swap = size > 1 && (tlb_addr & TLB_BSWAP);
154
+
155
/* Handle I/O access. */
156
- io_writex(env, iotlbentry, mmu_idx, val, addr, retaddr, op);
157
+ if (likely(tlb_addr & (TLB_MMIO | TLB_NOTDIRTY))) {
158
+ io_writex(env, iotlbentry, mmu_idx, val, addr, retaddr,
159
+ op ^ (need_swap * MO_BSWAP));
160
+ return;
161
+ }
162
+
163
+ haddr = (void *)((uintptr_t)addr + entry->addend);
164
+
165
+ /*
166
+ * Keep these two store_memop separate to ensure that the compiler
167
+ * is able to fold the entire function to a single instruction.
168
+ * There is a build-time assert inside to remind you of this. ;-)
169
+ */
170
+ if (unlikely(need_swap)) {
171
+ store_memop(haddr, val, op ^ MO_BSWAP);
172
+ } else {
173
+ store_memop(haddr, val, op);
174
+ }
175
return;
176
}
177
178
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
179
return;
180
}
181
182
- do_aligned_access:
183
haddr = (void *)((uintptr_t)addr + entry->addend);
184
store_memop(haddr, val, op);
185
}
186
--
33
--
187
2.17.1
34
2.20.1
188
35
189
36
diff view generated by jsdifflib
1
The memory_region_tb_read tracepoint is unreachable, since notdirty
1
The result of g_strsplit is never NULL.
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
2
6
Replace memory_region_tb_write with memory_notdirty_write_access,
3
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
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>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Reviewed-by: David Hildenbrand <david@redhat.com>
6
Reviewed by: Aleksandar Markovic <amarkovic@wavecomp.com>
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
---
8
---
16
exec.c | 3 +++
9
vl.c | 2 +-
17
memory.c | 4 ----
10
1 file changed, 1 insertion(+), 1 deletion(-)
18
trace-events | 4 ++--
19
3 files changed, 5 insertions(+), 6 deletions(-)
20
11
21
diff --git a/exec.c b/exec.c
12
diff --git a/vl.c b/vl.c
22
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
23
--- a/exec.c
14
--- a/vl.c
24
+++ b/exec.c
15
+++ b/vl.c
25
@@ -XXX,XX +XXX,XX @@ void memory_notdirty_write_prepare(NotDirtyInfo *ndi,
16
@@ -XXX,XX +XXX,XX @@ static void configure_accelerators(const char *progname)
26
ndi->size = size;
17
27
ndi->pages = NULL;
18
accel_list = g_strsplit(accel, ":", 0);
28
19
29
+ trace_memory_notdirty_write_access(mem_vaddr, ram_addr, size);
20
- for (tmp = accel_list; tmp && *tmp; tmp++) {
30
+
21
+ for (tmp = accel_list; *tmp; tmp++) {
31
assert(tcg_enabled());
22
/*
32
if (!cpu_physical_memory_get_dirty_flag(ram_addr, DIRTY_MEMORY_CODE)) {
23
* Filter invalid accelerators here, to prevent obscenities
33
ndi->pages = page_collection_lock(ram_addr, ram_addr + size);
24
* such as "-machine accel=tcg,,thread=single".
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
--
25
--
100
2.17.1
26
2.20.1
101
27
102
28
diff view generated by jsdifflib
1
Use this as a compile-time assert that a particular
1
By choosing "tcg:kvm" when kvm is not enabled, we generate
2
code path is not reachable.
2
an incorrect warning: "invalid accelerator kvm".
3
3
4
At the same time, use g_str_has_suffix rather than open-coding
5
the same operation.
6
7
Presumably the inverse is also true with --disable-tcg.
8
9
Fixes: 28a0961757fc
10
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Reviewed by: Aleksandar Markovic <amarkovic@wavecomp.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
14
---
7
include/qemu/compiler.h | 15 +++++++++++++++
15
vl.c | 21 +++++++++++++--------
8
1 file changed, 15 insertions(+)
16
1 file changed, 13 insertions(+), 8 deletions(-)
9
17
10
diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
18
diff --git a/vl.c b/vl.c
11
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
12
--- a/include/qemu/compiler.h
20
--- a/vl.c
13
+++ b/include/qemu/compiler.h
21
+++ b/vl.c
14
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ static void configure_accelerators(const char *progname)
15
#define QEMU_GENERIC9(x, a0, ...) QEMU_GENERIC_IF(x, a0, QEMU_GENERIC8(x, __VA_ARGS__))
23
16
#define QEMU_GENERIC10(x, a0, ...) QEMU_GENERIC_IF(x, a0, QEMU_GENERIC9(x, __VA_ARGS__))
24
if (accel == NULL) {
17
25
/* Select the default accelerator */
18
+/**
26
- if (!accel_find("tcg") && !accel_find("kvm")) {
19
+ * qemu_build_not_reached()
27
- error_report("No accelerator selected and"
20
+ *
28
- " no default accelerator available");
21
+ * The compiler, during optimization, is expected to prove that a call
29
- exit(1);
22
+ * to this function cannot be reached and remove it. If the compiler
30
- } else {
23
+ * supports QEMU_ERROR, this will be reported at compile time; otherwise
31
- int pnlen = strlen(progname);
24
+ * this will be reported at link time due to the missing symbol.
32
- if (pnlen >= 3 && g_str_equal(&progname[pnlen - 3], "kvm")) {
25
+ */
33
+ bool have_tcg = accel_find("tcg");
26
+#ifdef __OPTIMIZE__
34
+ bool have_kvm = accel_find("kvm");
27
+extern void QEMU_NORETURN QEMU_ERROR("code path is reachable")
28
+ qemu_build_not_reached(void);
29
+#else
30
+#define qemu_build_not_reached() g_assert_not_reached()
31
+#endif
32
+
35
+
33
#endif /* COMPILER_H */
36
+ if (have_tcg && have_kvm) {
37
+ if (g_str_has_suffix(progname, "kvm")) {
38
/* If the program name ends with "kvm", we prefer KVM */
39
accel = "kvm:tcg";
40
} else {
41
accel = "tcg:kvm";
42
}
43
+ } else if (have_kvm) {
44
+ accel = "kvm";
45
+ } else if (have_tcg) {
46
+ accel = "tcg";
47
+ } else {
48
+ error_report("No accelerator selected and"
49
+ " no default accelerator available");
50
+ exit(1);
51
}
52
}
53
-
54
accel_list = g_strsplit(accel, ":", 0);
55
56
for (tmp = accel_list; *tmp; tmp++) {
34
--
57
--
35
2.17.1
58
2.20.1
36
59
37
60
diff view generated by jsdifflib
1
Since 9458a9a1df1a, all readers of the dirty bitmaps wait
1
There is only one caller for tlb_table_flush_by_mmuidx. Place
2
for the rcu lock, which means that they wait until the end
2
the result at the earlier line number, due to an expected user
3
of any executing TranslationBlock.
3
in the near future.
4
4
5
As a consequence, there is no need for the actual access
6
to happen in between the _prepare and _complete. Therefore,
7
we can improve things by merging the two functions into
8
notdirty_write and dropping the NotDirtyInfo structure.
9
10
In addition, the only users of notdirty_write are in cputlb.c,
11
so move the merged function there. Pass in the CPUIOTLBEntry
12
from which the ram_addr_t may be computed.
13
14
Reviewed-by: David Hildenbrand <david@redhat.com>
15
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
16
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
17
---
8
---
18
include/exec/memory-internal.h | 65 -----------------------------
9
accel/tcg/cputlb.c | 19 +++++++------------
19
accel/tcg/cputlb.c | 76 +++++++++++++++++++---------------
10
1 file changed, 7 insertions(+), 12 deletions(-)
20
exec.c | 44 --------------------
21
3 files changed, 42 insertions(+), 143 deletions(-)
22
11
23
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/exec/memory-internal.h
26
+++ b/include/exec/memory-internal.h
27
@@ -XXX,XX +XXX,XX @@ void address_space_dispatch_free(AddressSpaceDispatch *d);
28
29
void mtree_print_dispatch(struct AddressSpaceDispatch *d,
30
MemoryRegion *root);
31
-
32
-struct page_collection;
33
-
34
-/* Opaque struct for passing info from memory_notdirty_write_prepare()
35
- * to memory_notdirty_write_complete(). Callers should treat all fields
36
- * as private, with the exception of @active.
37
- *
38
- * @active is a field which is not touched by either the prepare or
39
- * complete functions, but which the caller can use if it wishes to
40
- * track whether it has called prepare for this struct and so needs
41
- * to later call the complete function.
42
- */
43
-typedef struct {
44
- CPUState *cpu;
45
- struct page_collection *pages;
46
- ram_addr_t ram_addr;
47
- vaddr mem_vaddr;
48
- unsigned size;
49
- bool active;
50
-} NotDirtyInfo;
51
-
52
-/**
53
- * memory_notdirty_write_prepare: call before writing to non-dirty memory
54
- * @ndi: pointer to opaque NotDirtyInfo struct
55
- * @cpu: CPU doing the write
56
- * @mem_vaddr: virtual address of write
57
- * @ram_addr: the ram address of the write
58
- * @size: size of write in bytes
59
- *
60
- * Any code which writes to the host memory corresponding to
61
- * guest RAM which has been marked as NOTDIRTY must wrap those
62
- * writes in calls to memory_notdirty_write_prepare() and
63
- * memory_notdirty_write_complete():
64
- *
65
- * NotDirtyInfo ndi;
66
- * memory_notdirty_write_prepare(&ndi, ....);
67
- * ... perform write here ...
68
- * memory_notdirty_write_complete(&ndi);
69
- *
70
- * These calls will ensure that we flush any TCG translated code for
71
- * the memory being written, update the dirty bits and (if possible)
72
- * remove the slowpath callback for writing to the memory.
73
- *
74
- * This must only be called if we are using TCG; it will assert otherwise.
75
- *
76
- * We may take locks in the prepare call, so callers must ensure that
77
- * they don't exit (via longjump or otherwise) without calling complete.
78
- *
79
- * This call must only be made inside an RCU critical section.
80
- * (Note that while we're executing a TCG TB we're always in an
81
- * RCU critical section, which is likely to be the case for callers
82
- * of these functions.)
83
- */
84
-void memory_notdirty_write_prepare(NotDirtyInfo *ndi,
85
- CPUState *cpu,
86
- vaddr mem_vaddr,
87
- ram_addr_t ram_addr,
88
- unsigned size);
89
-/**
90
- * memory_notdirty_write_complete: finish write to non-dirty memory
91
- * @ndi: pointer to the opaque NotDirtyInfo struct which was initialized
92
- * by memory_not_dirty_write_prepare().
93
- */
94
-void memory_notdirty_write_complete(NotDirtyInfo *ndi);
95
-
96
#endif
97
#endif
98
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
12
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
99
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
100
--- a/accel/tcg/cputlb.c
14
--- a/accel/tcg/cputlb.c
101
+++ b/accel/tcg/cputlb.c
15
+++ b/accel/tcg/cputlb.c
102
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_resize_locked(CPUArchState *env, int mmu_idx)
103
#include "exec/helper-proto.h"
17
}
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
}
18
}
113
19
114
+static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size,
20
-static inline void tlb_table_flush_by_mmuidx(CPUArchState *env, int mmu_idx)
115
+ CPUIOTLBEntry *iotlbentry, uintptr_t retaddr)
21
+static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
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
{
22
{
156
size_t mmu_idx = get_mmuidx(oi);
23
tlb_mmu_resize_locked(env, mmu_idx);
157
uintptr_t index = tlb_index(env, mmu_idx, addr);
24
- memset(env_tlb(env)->f[mmu_idx].table, -1, sizeof_tlb(env, mmu_idx));
158
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
25
env_tlb(env)->d[mmu_idx].n_used_entries = 0;
159
26
+ env_tlb(env)->d[mmu_idx].large_page_addr = -1;
160
hostaddr = (void *)((uintptr_t)addr + tlbe->addend);
27
+ env_tlb(env)->d[mmu_idx].large_page_mask = -1;
161
28
+ env_tlb(env)->d[mmu_idx].vindex = 0;
162
- ndi->active = false;
29
+ memset(env_tlb(env)->f[mmu_idx].table, -1, sizeof_tlb(env, mmu_idx));
163
if (unlikely(tlb_addr & TLB_NOTDIRTY)) {
30
+ memset(env_tlb(env)->d[mmu_idx].vtable, -1,
164
- ndi->active = true;
31
+ sizeof(env_tlb(env)->d[0].vtable));
165
- memory_notdirty_write_prepare(ndi, env_cpu(env), addr,
166
- qemu_ram_addr_from_host_nofail(hostaddr),
167
- 1 << s_bits);
168
+ notdirty_write(env_cpu(env), addr, 1 << s_bits,
169
+ &env_tlb(env)->d[mmu_idx].iotlb[index], retaddr);
170
}
171
172
return hostaddr;
173
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
174
return;
175
}
176
177
- haddr = (void *)((uintptr_t)addr + entry->addend);
178
-
179
/* Handle clean RAM pages. */
180
if (tlb_addr & TLB_NOTDIRTY) {
181
- NotDirtyInfo ndi;
182
-
183
- /* We require mem_io_pc in tb_invalidate_phys_page_range. */
184
- env_cpu(env)->mem_io_pc = retaddr;
185
-
186
- memory_notdirty_write_prepare(&ndi, env_cpu(env), addr,
187
- addr + iotlbentry->addr, size);
188
-
189
- if (unlikely(need_swap)) {
190
- store_memop(haddr, val, op ^ MO_BSWAP);
191
- } else {
192
- store_memop(haddr, val, op);
193
- }
194
-
195
- memory_notdirty_write_complete(&ndi);
196
- return;
197
+ notdirty_write(env_cpu(env), addr, size, iotlbentry, retaddr);
198
}
199
200
+ haddr = (void *)((uintptr_t)addr + entry->addend);
201
+
202
/*
203
* Keep these two store_memop separate to ensure that the compiler
204
* is able to fold the entire function to a single instruction.
205
@@ -XXX,XX +XXX,XX @@ void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
206
#define EXTRA_ARGS , TCGMemOpIdx oi, uintptr_t retaddr
207
#define ATOMIC_NAME(X) \
208
HELPER(glue(glue(glue(atomic_ ## X, SUFFIX), END), _mmu))
209
-#define ATOMIC_MMU_DECLS NotDirtyInfo ndi
210
-#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, oi, retaddr, &ndi)
211
-#define ATOMIC_MMU_CLEANUP \
212
- do { \
213
- if (unlikely(ndi.active)) { \
214
- memory_notdirty_write_complete(&ndi); \
215
- } \
216
- } while (0)
217
+#define ATOMIC_MMU_DECLS
218
+#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, oi, retaddr)
219
+#define ATOMIC_MMU_CLEANUP
220
221
#define DATA_SIZE 1
222
#include "atomic_template.h"
223
@@ -XXX,XX +XXX,XX @@ void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
224
#undef ATOMIC_MMU_LOOKUP
225
#define EXTRA_ARGS , TCGMemOpIdx oi
226
#define ATOMIC_NAME(X) HELPER(glue(glue(atomic_ ## X, SUFFIX), END))
227
-#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, oi, GETPC(), &ndi)
228
+#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, oi, GETPC())
229
230
#define DATA_SIZE 1
231
#include "atomic_template.h"
232
diff --git a/exec.c b/exec.c
233
index XXXXXXX..XXXXXXX 100644
234
--- a/exec.c
235
+++ b/exec.c
236
@@ -XXX,XX +XXX,XX @@ ram_addr_t qemu_ram_addr_from_host(void *ptr)
237
return block->offset + offset;
238
}
32
}
239
33
240
-/* Called within RCU critical section. */
34
static inline void tlb_n_used_entries_inc(CPUArchState *env, uintptr_t mmu_idx)
241
-void memory_notdirty_write_prepare(NotDirtyInfo *ndi,
35
@@ -XXX,XX +XXX,XX @@ void tlb_flush_counts(size_t *pfull, size_t *ppart, size_t *pelide)
242
- CPUState *cpu,
36
*pelide = elide;
243
- vaddr mem_vaddr,
37
}
244
- ram_addr_t ram_addr,
38
245
- unsigned size)
39
-static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
246
-{
40
-{
247
- ndi->cpu = cpu;
41
- tlb_table_flush_by_mmuidx(env, mmu_idx);
248
- ndi->ram_addr = ram_addr;
42
- env_tlb(env)->d[mmu_idx].large_page_addr = -1;
249
- ndi->mem_vaddr = mem_vaddr;
43
- env_tlb(env)->d[mmu_idx].large_page_mask = -1;
250
- ndi->size = size;
44
- env_tlb(env)->d[mmu_idx].vindex = 0;
251
- ndi->pages = NULL;
45
- memset(env_tlb(env)->d[mmu_idx].vtable, -1,
252
-
46
- sizeof(env_tlb(env)->d[0].vtable));
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
-}
47
-}
261
-
48
-
262
-/* Called within RCU critical section. */
49
static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data)
263
-void memory_notdirty_write_complete(NotDirtyInfo *ndi)
50
{
264
-{
51
CPUArchState *env = cpu->env_ptr;
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
--
52
--
288
2.17.1
53
2.20.1
289
54
290
55
diff view generated by jsdifflib
1
This forced inlining can result in missing symbols,
1
There are no users of this function outside cputlb.c,
2
which makes a debugging build harder to follow.
2
and its interface will change in the next patch.
3
3
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
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>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
8
---
10
include/qemu/compiler.h | 11 +++++++++++
9
include/exec/cpu_ldst.h | 5 -----
11
accel/tcg/cputlb.c | 4 ++--
10
accel/tcg/cputlb.c | 5 +++++
12
2 files changed, 13 insertions(+), 2 deletions(-)
11
2 files changed, 5 insertions(+), 5 deletions(-)
13
12
14
diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
13
diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/include/qemu/compiler.h
15
--- a/include/exec/cpu_ldst.h
17
+++ b/include/qemu/compiler.h
16
+++ b/include/exec/cpu_ldst.h
18
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ static inline uintptr_t tlb_index(CPUArchState *env, uintptr_t mmu_idx,
19
# define QEMU_NONSTRING
18
return (addr >> TARGET_PAGE_BITS) & size_mask;
20
#endif
19
}
21
20
22
+/*
21
-static inline size_t tlb_n_entries(CPUArchState *env, uintptr_t mmu_idx)
23
+ * Forced inlining may be desired to encourage constant propagation
22
-{
24
+ * of function parameters. However, it can also make debugging harder,
23
- return (env_tlb(env)->f[mmu_idx].mask >> CPU_TLB_ENTRY_BITS) + 1;
25
+ * so disable it for a non-optimizing build.
24
-}
26
+ */
25
-
27
+#if defined(__OPTIMIZE__)
26
/* Find the TLB entry corresponding to the mmu_idx + address pair. */
28
+#define QEMU_ALWAYS_INLINE __attribute__((always_inline))
27
static inline CPUTLBEntry *tlb_entry(CPUArchState *env, uintptr_t mmu_idx,
29
+#else
28
target_ulong addr)
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
29
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
37
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
38
--- a/accel/tcg/cputlb.c
31
--- a/accel/tcg/cputlb.c
39
+++ b/accel/tcg/cputlb.c
32
+++ b/accel/tcg/cputlb.c
40
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
33
@@ -XXX,XX +XXX,XX @@ QEMU_BUILD_BUG_ON(sizeof(target_ulong) > sizeof(run_on_cpu_data));
41
typedef uint64_t FullLoadHelper(CPUArchState *env, target_ulong addr,
34
QEMU_BUILD_BUG_ON(NB_MMU_MODES > 16);
42
TCGMemOpIdx oi, uintptr_t retaddr);
35
#define ALL_MMUIDX_BITS ((1 << NB_MMU_MODES) - 1)
43
36
44
-static inline uint64_t __attribute__((always_inline))
37
+static inline size_t tlb_n_entries(CPUArchState *env, uintptr_t mmu_idx)
45
+static inline uint64_t QEMU_ALWAYS_INLINE
38
+{
46
load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
39
+ return (env_tlb(env)->f[mmu_idx].mask >> CPU_TLB_ENTRY_BITS) + 1;
47
uintptr_t retaddr, MemOp op, bool code_read,
40
+}
48
FullLoadHelper *full_load)
41
+
49
@@ -XXX,XX +XXX,XX @@ tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr,
42
static inline size_t sizeof_tlb(CPUArchState *env, uintptr_t mmu_idx)
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
{
43
{
44
return env_tlb(env)->f[mmu_idx].mask + (1 << CPU_TLB_ENTRY_BITS);
58
--
45
--
59
2.17.1
46
2.20.1
60
47
61
48
diff view generated by jsdifflib
1
We will shortly be using these more than once.
1
We do not need the entire CPUArchState to compute these values.
2
2
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: David Hildenbrand <david@redhat.com>
4
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
---
7
accel/tcg/cputlb.c | 107 +++++++++++++++++++++++----------------------
8
accel/tcg/cputlb.c | 15 ++++++++-------
8
1 file changed, 55 insertions(+), 52 deletions(-)
9
1 file changed, 8 insertions(+), 7 deletions(-)
9
10
10
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
11
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
11
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
12
--- a/accel/tcg/cputlb.c
13
--- a/accel/tcg/cputlb.c
13
+++ b/accel/tcg/cputlb.c
14
+++ b/accel/tcg/cputlb.c
14
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
15
@@ -XXX,XX +XXX,XX @@ QEMU_BUILD_BUG_ON(sizeof(target_ulong) > sizeof(run_on_cpu_data));
15
typedef uint64_t FullLoadHelper(CPUArchState *env, target_ulong addr,
16
QEMU_BUILD_BUG_ON(NB_MMU_MODES > 16);
16
TCGMemOpIdx oi, uintptr_t retaddr);
17
#define ALL_MMUIDX_BITS ((1 << NB_MMU_MODES) - 1)
17
18
18
+static inline uint64_t QEMU_ALWAYS_INLINE
19
-static inline size_t tlb_n_entries(CPUArchState *env, uintptr_t mmu_idx)
19
+load_memop(const void *haddr, MemOp op)
20
+static inline size_t tlb_n_entries(CPUTLBDescFast *fast)
20
+{
21
{
21
+ switch (op) {
22
- return (env_tlb(env)->f[mmu_idx].mask >> CPU_TLB_ENTRY_BITS) + 1;
22
+ case MO_UB:
23
+ return (fast->mask >> CPU_TLB_ENTRY_BITS) + 1;
23
+ return ldub_p(haddr);
24
+ case MO_BEUW:
25
+ return lduw_be_p(haddr);
26
+ case MO_LEUW:
27
+ return lduw_le_p(haddr);
28
+ case MO_BEUL:
29
+ return (uint32_t)ldl_be_p(haddr);
30
+ case MO_LEUL:
31
+ return (uint32_t)ldl_le_p(haddr);
32
+ case MO_BEQ:
33
+ return ldq_be_p(haddr);
34
+ case MO_LEQ:
35
+ return ldq_le_p(haddr);
36
+ default:
37
+ qemu_build_not_reached();
38
+ }
39
+}
40
+
41
static inline uint64_t QEMU_ALWAYS_INLINE
42
load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
43
uintptr_t retaddr, MemOp op, bool code_read,
44
@@ -XXX,XX +XXX,XX @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
45
46
do_aligned_access:
47
haddr = (void *)((uintptr_t)addr + entry->addend);
48
- switch (op) {
49
- case MO_UB:
50
- res = ldub_p(haddr);
51
- break;
52
- case MO_BEUW:
53
- res = lduw_be_p(haddr);
54
- break;
55
- case MO_LEUW:
56
- res = lduw_le_p(haddr);
57
- break;
58
- case MO_BEUL:
59
- res = (uint32_t)ldl_be_p(haddr);
60
- break;
61
- case MO_LEUL:
62
- res = (uint32_t)ldl_le_p(haddr);
63
- break;
64
- case MO_BEQ:
65
- res = ldq_be_p(haddr);
66
- break;
67
- case MO_LEQ:
68
- res = ldq_le_p(haddr);
69
- break;
70
- default:
71
- qemu_build_not_reached();
72
- }
73
-
74
- return res;
75
+ return load_memop(haddr, op);
76
}
24
}
77
25
78
/*
26
-static inline size_t sizeof_tlb(CPUArchState *env, uintptr_t mmu_idx)
79
@@ -XXX,XX +XXX,XX @@ tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr,
27
+static inline size_t sizeof_tlb(CPUTLBDescFast *fast)
80
* Store Helpers
28
{
81
*/
29
- return env_tlb(env)->f[mmu_idx].mask + (1 << CPU_TLB_ENTRY_BITS);
82
30
+ return fast->mask + (1 << CPU_TLB_ENTRY_BITS);
83
+static inline void QEMU_ALWAYS_INLINE
84
+store_memop(void *haddr, uint64_t val, MemOp op)
85
+{
86
+ switch (op) {
87
+ case MO_UB:
88
+ stb_p(haddr, val);
89
+ break;
90
+ case MO_BEUW:
91
+ stw_be_p(haddr, val);
92
+ break;
93
+ case MO_LEUW:
94
+ stw_le_p(haddr, val);
95
+ break;
96
+ case MO_BEUL:
97
+ stl_be_p(haddr, val);
98
+ break;
99
+ case MO_LEUL:
100
+ stl_le_p(haddr, val);
101
+ break;
102
+ case MO_BEQ:
103
+ stq_be_p(haddr, val);
104
+ break;
105
+ case MO_LEQ:
106
+ stq_le_p(haddr, val);
107
+ break;
108
+ default:
109
+ qemu_build_not_reached();
110
+ }
111
+}
112
+
113
static inline void QEMU_ALWAYS_INLINE
114
store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
115
TCGMemOpIdx oi, uintptr_t retaddr, MemOp op)
116
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
117
118
do_aligned_access:
119
haddr = (void *)((uintptr_t)addr + entry->addend);
120
- switch (op) {
121
- case MO_UB:
122
- stb_p(haddr, val);
123
- break;
124
- case MO_BEUW:
125
- stw_be_p(haddr, val);
126
- break;
127
- case MO_LEUW:
128
- stw_le_p(haddr, val);
129
- break;
130
- case MO_BEUL:
131
- stl_be_p(haddr, val);
132
- break;
133
- case MO_LEUL:
134
- stl_le_p(haddr, val);
135
- break;
136
- case MO_BEQ:
137
- stq_be_p(haddr, val);
138
- break;
139
- case MO_LEQ:
140
- stq_le_p(haddr, val);
141
- break;
142
- default:
143
- qemu_build_not_reached();
144
- }
145
+ store_memop(haddr, val, op);
146
}
31
}
147
32
148
void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
33
static void tlb_window_reset(CPUTLBDesc *desc, int64_t ns,
34
@@ -XXX,XX +XXX,XX @@ static void tlb_dyn_init(CPUArchState *env)
35
static void tlb_mmu_resize_locked(CPUArchState *env, int mmu_idx)
36
{
37
CPUTLBDesc *desc = &env_tlb(env)->d[mmu_idx];
38
- size_t old_size = tlb_n_entries(env, mmu_idx);
39
+ size_t old_size = tlb_n_entries(&env_tlb(env)->f[mmu_idx]);
40
size_t rate;
41
size_t new_size = old_size;
42
int64_t now = get_clock_realtime();
43
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
44
env_tlb(env)->d[mmu_idx].large_page_addr = -1;
45
env_tlb(env)->d[mmu_idx].large_page_mask = -1;
46
env_tlb(env)->d[mmu_idx].vindex = 0;
47
- memset(env_tlb(env)->f[mmu_idx].table, -1, sizeof_tlb(env, mmu_idx));
48
+ memset(env_tlb(env)->f[mmu_idx].table, -1,
49
+ sizeof_tlb(&env_tlb(env)->f[mmu_idx]));
50
memset(env_tlb(env)->d[mmu_idx].vtable, -1,
51
sizeof(env_tlb(env)->d[0].vtable));
52
}
53
@@ -XXX,XX +XXX,XX @@ void tlb_reset_dirty(CPUState *cpu, ram_addr_t start1, ram_addr_t length)
54
qemu_spin_lock(&env_tlb(env)->c.lock);
55
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
56
unsigned int i;
57
- unsigned int n = tlb_n_entries(env, mmu_idx);
58
+ unsigned int n = tlb_n_entries(&env_tlb(env)->f[mmu_idx]);
59
60
for (i = 0; i < n; i++) {
61
tlb_reset_dirty_range_locked(&env_tlb(env)->f[mmu_idx].table[i],
149
--
62
--
150
2.17.1
63
2.20.1
151
64
152
65
diff view generated by jsdifflib
1
Rather than rely on cpu->mem_io_pc, pass retaddr down directly.
1
No functional change, but the smaller expressions make
2
2
the code easier to read.
3
Within tb_invalidate_phys_page_range__locked, the is_cpu_write_access
4
parameter is non-zero exactly when retaddr would be non-zero, so that
5
is a simple replacement.
6
7
Recognize that current_tb_not_found is true only when mem_io_pc
8
(and now retaddr) are also non-zero, so remove a redundant test.
9
3
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Reviewed-by: David Hildenbrand <david@redhat.com>
5
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
---
8
---
14
accel/tcg/translate-all.h | 3 ++-
9
accel/tcg/cputlb.c | 35 +++++++++++++++++------------------
15
accel/tcg/cputlb.c | 6 +-----
10
1 file changed, 17 insertions(+), 18 deletions(-)
16
accel/tcg/translate-all.c | 39 +++++++++++++++++++--------------------
17
3 files changed, 22 insertions(+), 26 deletions(-)
18
11
19
diff --git a/accel/tcg/translate-all.h b/accel/tcg/translate-all.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/accel/tcg/translate-all.h
22
+++ b/accel/tcg/translate-all.h
23
@@ -XXX,XX +XXX,XX @@ struct page_collection *page_collection_lock(tb_page_addr_t start,
24
tb_page_addr_t end);
25
void page_collection_unlock(struct page_collection *set);
26
void tb_invalidate_phys_page_fast(struct page_collection *pages,
27
- tb_page_addr_t start, int len);
28
+ tb_page_addr_t start, int len,
29
+ uintptr_t retaddr);
30
void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end);
31
void tb_check_watchpoint(CPUState *cpu);
32
33
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
12
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
34
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
35
--- a/accel/tcg/cputlb.c
14
--- a/accel/tcg/cputlb.c
36
+++ b/accel/tcg/cputlb.c
15
+++ b/accel/tcg/cputlb.c
37
@@ -XXX,XX +XXX,XX @@ static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size,
16
@@ -XXX,XX +XXX,XX @@ static void tlb_dyn_init(CPUArchState *env)
38
if (!cpu_physical_memory_get_dirty_flag(ram_addr, DIRTY_MEMORY_CODE)) {
17
39
struct page_collection *pages
18
/**
40
= page_collection_lock(ram_addr, ram_addr + size);
19
* tlb_mmu_resize_locked() - perform TLB resize bookkeeping; resize if necessary
41
-
20
- * @env: CPU that owns the TLB
42
- /* We require mem_io_pc in tb_invalidate_phys_page_range. */
21
- * @mmu_idx: MMU index of the TLB
43
- cpu->mem_io_pc = retaddr;
22
+ * @desc: The CPUTLBDesc portion of the TLB
44
-
23
+ * @fast: The CPUTLBDescFast portion of the same TLB
45
- tb_invalidate_phys_page_fast(pages, ram_addr, size);
24
*
46
+ tb_invalidate_phys_page_fast(pages, ram_addr, size, retaddr);
25
* Called with tlb_lock_held.
47
page_collection_unlock(pages);
26
*
27
@@ -XXX,XX +XXX,XX @@ static void tlb_dyn_init(CPUArchState *env)
28
* high), since otherwise we are likely to have a significant amount of
29
* conflict misses.
30
*/
31
-static void tlb_mmu_resize_locked(CPUArchState *env, int mmu_idx)
32
+static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast)
33
{
34
- CPUTLBDesc *desc = &env_tlb(env)->d[mmu_idx];
35
- size_t old_size = tlb_n_entries(&env_tlb(env)->f[mmu_idx]);
36
+ size_t old_size = tlb_n_entries(fast);
37
size_t rate;
38
size_t new_size = old_size;
39
int64_t now = get_clock_realtime();
40
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_resize_locked(CPUArchState *env, int mmu_idx)
41
return;
48
}
42
}
49
43
50
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
44
- g_free(env_tlb(env)->f[mmu_idx].table);
51
index XXXXXXX..XXXXXXX 100644
45
- g_free(env_tlb(env)->d[mmu_idx].iotlb);
52
--- a/accel/tcg/translate-all.c
46
+ g_free(fast->table);
53
+++ b/accel/tcg/translate-all.c
47
+ g_free(desc->iotlb);
54
@@ -XXX,XX +XXX,XX @@ static void
48
55
tb_invalidate_phys_page_range__locked(struct page_collection *pages,
49
tlb_window_reset(desc, now, 0);
56
PageDesc *p, tb_page_addr_t start,
50
/* desc->n_used_entries is cleared by the caller */
57
tb_page_addr_t end,
51
- env_tlb(env)->f[mmu_idx].mask = (new_size - 1) << CPU_TLB_ENTRY_BITS;
58
- int is_cpu_write_access)
52
- env_tlb(env)->f[mmu_idx].table = g_try_new(CPUTLBEntry, new_size);
59
+ uintptr_t retaddr)
53
- env_tlb(env)->d[mmu_idx].iotlb = g_try_new(CPUIOTLBEntry, new_size);
60
{
54
+ fast->mask = (new_size - 1) << CPU_TLB_ENTRY_BITS;
61
TranslationBlock *tb;
55
+ fast->table = g_try_new(CPUTLBEntry, new_size);
62
tb_page_addr_t tb_start, tb_end;
56
+ desc->iotlb = g_try_new(CPUIOTLBEntry, new_size);
63
@@ -XXX,XX +XXX,XX @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
57
+
64
#ifdef TARGET_HAS_PRECISE_SMC
58
/*
65
CPUState *cpu = current_cpu;
59
* If the allocations fail, try smaller sizes. We just freed some
66
CPUArchState *env = NULL;
60
* memory, so going back to half of new_size has a good chance of working.
67
- int current_tb_not_found = is_cpu_write_access;
61
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_resize_locked(CPUArchState *env, int mmu_idx)
68
+ bool current_tb_not_found = retaddr != 0;
62
* allocations to fail though, so we progressively reduce the allocation
69
+ bool current_tb_modified = false;
63
* size, aborting if we cannot even allocate the smallest TLB we support.
70
TranslationBlock *current_tb = NULL;
64
*/
71
- int current_tb_modified = 0;
65
- while (env_tlb(env)->f[mmu_idx].table == NULL ||
72
target_ulong current_pc = 0;
66
- env_tlb(env)->d[mmu_idx].iotlb == NULL) {
73
target_ulong current_cs_base = 0;
67
+ while (fast->table == NULL || desc->iotlb == NULL) {
74
uint32_t current_flags = 0;
68
if (new_size == (1 << CPU_TLB_DYN_MIN_BITS)) {
75
@@ -XXX,XX +XXX,XX @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
69
error_report("%s: %s", __func__, strerror(errno));
76
if (!(tb_end <= start || tb_start >= end)) {
70
abort();
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
}
71
}
124
} else {
72
new_size = MAX(new_size >> 1, 1 << CPU_TLB_DYN_MIN_BITS);
125
do_invalidate:
73
- env_tlb(env)->f[mmu_idx].mask = (new_size - 1) << CPU_TLB_ENTRY_BITS;
126
- tb_invalidate_phys_page_range__locked(pages, p, start, start + len, 1);
74
+ fast->mask = (new_size - 1) << CPU_TLB_ENTRY_BITS;
127
+ tb_invalidate_phys_page_range__locked(pages, p, start, start + len,
75
128
+ retaddr);
76
- g_free(env_tlb(env)->f[mmu_idx].table);
77
- g_free(env_tlb(env)->d[mmu_idx].iotlb);
78
- env_tlb(env)->f[mmu_idx].table = g_try_new(CPUTLBEntry, new_size);
79
- env_tlb(env)->d[mmu_idx].iotlb = g_try_new(CPUIOTLBEntry, new_size);
80
+ g_free(fast->table);
81
+ g_free(desc->iotlb);
82
+ fast->table = g_try_new(CPUTLBEntry, new_size);
83
+ desc->iotlb = g_try_new(CPUIOTLBEntry, new_size);
129
}
84
}
130
}
85
}
131
#else
86
87
static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
88
{
89
- tlb_mmu_resize_locked(env, mmu_idx);
90
+ tlb_mmu_resize_locked(&env_tlb(env)->d[mmu_idx], &env_tlb(env)->f[mmu_idx]);
91
env_tlb(env)->d[mmu_idx].n_used_entries = 0;
92
env_tlb(env)->d[mmu_idx].large_page_addr = -1;
93
env_tlb(env)->d[mmu_idx].large_page_mask = -1;
132
--
94
--
133
2.17.1
95
2.20.1
134
96
135
97
diff view generated by jsdifflib
1
With the merge of notdirty handling into store_helper,
1
No functional change, but the smaller expressions make
2
the last user of cpu->mem_io_vaddr was removed.
2
the code easier to read.
3
3
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: David Hildenbrand <david@redhat.com>
5
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
---
8
include/hw/core/cpu.h | 2 --
9
accel/tcg/cputlb.c | 19 ++++++++++---------
9
accel/tcg/cputlb.c | 2 --
10
1 file changed, 10 insertions(+), 9 deletions(-)
10
hw/core/cpu.c | 1 -
11
3 files changed, 5 deletions(-)
12
11
13
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/core/cpu.h
16
+++ b/include/hw/core/cpu.h
17
@@ -XXX,XX +XXX,XX @@ struct qemu_work_item;
18
* @next_cpu: Next CPU sharing TB cache.
19
* @opaque: User data.
20
* @mem_io_pc: Host Program Counter at which the memory was accessed.
21
- * @mem_io_vaddr: Target virtual address at which the memory was accessed.
22
* @kvm_fd: vCPU file descriptor for KVM.
23
* @work_mutex: Lock to prevent multiple access to queued_work_*.
24
* @queued_work_first: First asynchronous work pending.
25
@@ -XXX,XX +XXX,XX @@ struct CPUState {
26
* we store some rarely used information in the CPU context.
27
*/
28
uintptr_t mem_io_pc;
29
- vaddr mem_io_vaddr;
30
/*
31
* This is only needed for the legacy cpu_unassigned_access() hook;
32
* when all targets using it have been converted to use
33
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
12
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
34
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
35
--- a/accel/tcg/cputlb.c
14
--- a/accel/tcg/cputlb.c
36
+++ b/accel/tcg/cputlb.c
15
+++ b/accel/tcg/cputlb.c
37
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
16
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast)
38
cpu_io_recompile(cpu, retaddr);
17
39
}
18
static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
40
19
{
41
- cpu->mem_io_vaddr = addr;
20
- tlb_mmu_resize_locked(&env_tlb(env)->d[mmu_idx], &env_tlb(env)->f[mmu_idx]);
42
cpu->mem_io_access_type = access_type;
21
- env_tlb(env)->d[mmu_idx].n_used_entries = 0;
43
22
- env_tlb(env)->d[mmu_idx].large_page_addr = -1;
44
if (mr->global_locking && !qemu_mutex_iothread_locked()) {
23
- env_tlb(env)->d[mmu_idx].large_page_mask = -1;
45
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
24
- env_tlb(env)->d[mmu_idx].vindex = 0;
46
if (!cpu->can_do_io) {
25
- memset(env_tlb(env)->f[mmu_idx].table, -1,
47
cpu_io_recompile(cpu, retaddr);
26
- sizeof_tlb(&env_tlb(env)->f[mmu_idx]));
48
}
27
- memset(env_tlb(env)->d[mmu_idx].vtable, -1,
49
- cpu->mem_io_vaddr = addr;
28
- sizeof(env_tlb(env)->d[0].vtable));
50
cpu->mem_io_pc = retaddr;
29
+ CPUTLBDesc *desc = &env_tlb(env)->d[mmu_idx];
51
30
+ CPUTLBDescFast *fast = &env_tlb(env)->f[mmu_idx];
52
if (mr->global_locking && !qemu_mutex_iothread_locked()) {
31
+
53
diff --git a/hw/core/cpu.c b/hw/core/cpu.c
32
+ tlb_mmu_resize_locked(desc, fast);
54
index XXXXXXX..XXXXXXX 100644
33
+ desc->n_used_entries = 0;
55
--- a/hw/core/cpu.c
34
+ desc->large_page_addr = -1;
56
+++ b/hw/core/cpu.c
35
+ desc->large_page_mask = -1;
57
@@ -XXX,XX +XXX,XX @@ static void cpu_common_reset(CPUState *cpu)
36
+ desc->vindex = 0;
58
cpu->interrupt_request = 0;
37
+ memset(fast->table, -1, sizeof_tlb(fast));
59
cpu->halted = 0;
38
+ memset(desc->vtable, -1, sizeof(desc->vtable));
60
cpu->mem_io_pc = 0;
39
}
61
- cpu->mem_io_vaddr = 0;
40
62
cpu->icount_extra = 0;
41
static inline void tlb_n_used_entries_inc(CPUArchState *env, uintptr_t mmu_idx)
63
atomic_set(&cpu->icount_decr_ptr->u32, 0);
64
cpu->can_do_io = 1;
65
--
42
--
66
2.17.1
43
2.20.1
67
44
68
45
diff view generated by jsdifflib
1
Increase the current runtime assert to a compile-time assert.
1
We will want to be able to flush a tlb without resizing.
2
2
3
Reviewed-by: David Hildenbrand <david@redhat.com>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
---
7
accel/tcg/cputlb.c | 5 ++---
8
accel/tcg/cputlb.c | 15 ++++++++++-----
8
1 file changed, 2 insertions(+), 3 deletions(-)
9
1 file changed, 10 insertions(+), 5 deletions(-)
9
10
10
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
11
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
11
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
12
--- a/accel/tcg/cputlb.c
13
--- a/accel/tcg/cputlb.c
13
+++ b/accel/tcg/cputlb.c
14
+++ b/accel/tcg/cputlb.c
14
@@ -XXX,XX +XXX,XX @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
15
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast)
15
res = ldq_le_p(haddr);
16
break;
17
default:
18
- g_assert_not_reached();
19
+ qemu_build_not_reached();
20
}
21
22
return res;
23
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
24
stq_le_p(haddr, val);
25
break;
26
default:
27
- g_assert_not_reached();
28
- break;
29
+ qemu_build_not_reached();
30
}
16
}
31
}
17
}
32
18
19
-static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
20
+static void tlb_mmu_flush_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast)
21
{
22
- CPUTLBDesc *desc = &env_tlb(env)->d[mmu_idx];
23
- CPUTLBDescFast *fast = &env_tlb(env)->f[mmu_idx];
24
-
25
- tlb_mmu_resize_locked(desc, fast);
26
desc->n_used_entries = 0;
27
desc->large_page_addr = -1;
28
desc->large_page_mask = -1;
29
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
30
memset(desc->vtable, -1, sizeof(desc->vtable));
31
}
32
33
+static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
34
+{
35
+ CPUTLBDesc *desc = &env_tlb(env)->d[mmu_idx];
36
+ CPUTLBDescFast *fast = &env_tlb(env)->f[mmu_idx];
37
+
38
+ tlb_mmu_resize_locked(desc, fast);
39
+ tlb_mmu_flush_locked(desc, fast);
40
+}
41
+
42
static inline void tlb_n_used_entries_inc(CPUArchState *env, uintptr_t mmu_idx)
43
{
44
env_tlb(env)->d[mmu_idx].n_used_entries++;
33
--
45
--
34
2.17.1
46
2.20.1
35
47
36
48
diff view generated by jsdifflib
1
Pages that we want to track for NOTDIRTY are RAM. We do not
1
Merge into the only caller, but at the same time split
2
really need to go through the I/O path to handle them.
2
out tlb_mmu_init to initialize a single tlb entry.
3
3
4
Acked-by: David Hildenbrand <david@redhat.com>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
8
---
9
include/exec/cpu-common.h | 2 --
9
accel/tcg/cputlb.c | 33 ++++++++++++++++-----------------
10
accel/tcg/cputlb.c | 26 +++++++++++++++++---
10
1 file changed, 16 insertions(+), 17 deletions(-)
11
exec.c | 50 ---------------------------------------
12
memory.c | 16 -------------
13
4 files changed, 23 insertions(+), 71 deletions(-)
14
11
15
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/exec/cpu-common.h
18
+++ b/include/exec/cpu-common.h
19
@@ -XXX,XX +XXX,XX @@ void qemu_flush_coalesced_mmio_buffer(void);
20
21
void cpu_flush_icache_range(hwaddr start, hwaddr len);
22
23
-extern struct MemoryRegion io_mem_notdirty;
24
-
25
typedef int (RAMBlockIterFunc)(RAMBlock *rb, void *opaque);
26
27
int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque);
28
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
12
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
29
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
30
--- a/accel/tcg/cputlb.c
14
--- a/accel/tcg/cputlb.c
31
+++ b/accel/tcg/cputlb.c
15
+++ b/accel/tcg/cputlb.c
32
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
16
@@ -XXX,XX +XXX,XX @@ static void tlb_window_reset(CPUTLBDesc *desc, int64_t ns,
33
mr = section->mr;
17
desc->window_max_entries = max_entries;
34
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
35
cpu->mem_io_pc = retaddr;
36
- if (mr != &io_mem_notdirty && !cpu->can_do_io) {
37
+ if (!cpu->can_do_io) {
38
cpu_io_recompile(cpu, retaddr);
39
}
40
41
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
42
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
43
mr = section->mr;
44
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
45
- if (mr != &io_mem_notdirty && !cpu->can_do_io) {
46
+ if (!cpu->can_do_io) {
47
cpu_io_recompile(cpu, retaddr);
48
}
49
cpu->mem_io_vaddr = addr;
50
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
51
need_swap = size > 1 && (tlb_addr & TLB_BSWAP);
52
53
/* Handle I/O access. */
54
- if (likely(tlb_addr & (TLB_MMIO | TLB_NOTDIRTY))) {
55
+ if (tlb_addr & TLB_MMIO) {
56
io_writex(env, iotlbentry, mmu_idx, val, addr, retaddr,
57
op ^ (need_swap * MO_BSWAP));
58
return;
59
@@ -XXX,XX +XXX,XX @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
60
61
haddr = (void *)((uintptr_t)addr + entry->addend);
62
63
+ /* Handle clean RAM pages. */
64
+ if (tlb_addr & TLB_NOTDIRTY) {
65
+ NotDirtyInfo ndi;
66
+
67
+ /* We require mem_io_pc in tb_invalidate_phys_page_range. */
68
+ env_cpu(env)->mem_io_pc = retaddr;
69
+
70
+ memory_notdirty_write_prepare(&ndi, env_cpu(env), addr,
71
+ addr + iotlbentry->addr, size);
72
+
73
+ if (unlikely(need_swap)) {
74
+ store_memop(haddr, val, op ^ MO_BSWAP);
75
+ } else {
76
+ store_memop(haddr, val, op);
77
+ }
78
+
79
+ memory_notdirty_write_complete(&ndi);
80
+ return;
81
+ }
82
+
83
/*
84
* Keep these two store_memop separate to ensure that the compiler
85
* is able to fold the entire function to a single instruction.
86
diff --git a/exec.c b/exec.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/exec.c
89
+++ b/exec.c
90
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *system_io;
91
AddressSpace address_space_io;
92
AddressSpace address_space_memory;
93
94
-MemoryRegion io_mem_notdirty;
95
static MemoryRegion io_mem_unassigned;
96
#endif
97
98
@@ -XXX,XX +XXX,XX @@ typedef struct subpage_t {
99
} subpage_t;
100
101
#define PHYS_SECTION_UNASSIGNED 0
102
-#define PHYS_SECTION_NOTDIRTY 1
103
104
static void io_mem_init(void);
105
static void memory_map_init(void);
106
@@ -XXX,XX +XXX,XX @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu,
107
if (memory_region_is_ram(section->mr)) {
108
/* Normal RAM. */
109
iotlb = memory_region_get_ram_addr(section->mr) + xlat;
110
- if (!section->readonly) {
111
- iotlb |= PHYS_SECTION_NOTDIRTY;
112
- }
113
} else {
114
AddressSpaceDispatch *d;
115
116
@@ -XXX,XX +XXX,XX @@ void memory_notdirty_write_complete(NotDirtyInfo *ndi)
117
}
118
}
18
}
119
19
120
-/* Called within RCU critical section. */
20
-static void tlb_dyn_init(CPUArchState *env)
121
-static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
122
- uint64_t val, unsigned size)
123
-{
21
-{
124
- NotDirtyInfo ndi;
22
- int i;
125
-
23
-
126
- memory_notdirty_write_prepare(&ndi, current_cpu, current_cpu->mem_io_vaddr,
24
- for (i = 0; i < NB_MMU_MODES; i++) {
127
- ram_addr, size);
25
- CPUTLBDesc *desc = &env_tlb(env)->d[i];
26
- size_t n_entries = 1 << CPU_TLB_DYN_DEFAULT_BITS;
128
-
27
-
129
- stn_p(qemu_map_ram_ptr(NULL, ram_addr), size, val);
28
- tlb_window_reset(desc, get_clock_realtime(), 0);
130
- memory_notdirty_write_complete(&ndi);
29
- desc->n_used_entries = 0;
30
- env_tlb(env)->f[i].mask = (n_entries - 1) << CPU_TLB_ENTRY_BITS;
31
- env_tlb(env)->f[i].table = g_new(CPUTLBEntry, n_entries);
32
- env_tlb(env)->d[i].iotlb = g_new(CPUIOTLBEntry, n_entries);
33
- }
131
-}
34
-}
132
-
35
-
133
-static bool notdirty_mem_accepts(void *opaque, hwaddr addr,
36
/**
134
- unsigned size, bool is_write,
37
* tlb_mmu_resize_locked() - perform TLB resize bookkeeping; resize if necessary
135
- MemTxAttrs attrs)
38
* @desc: The CPUTLBDesc portion of the TLB
136
-{
39
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
137
- return is_write;
40
tlb_mmu_flush_locked(desc, fast);
138
-}
41
}
139
-
42
140
-static const MemoryRegionOps notdirty_mem_ops = {
43
+static void tlb_mmu_init(CPUTLBDesc *desc, CPUTLBDescFast *fast, int64_t now)
141
- .write = notdirty_mem_write,
44
+{
142
- .valid.accepts = notdirty_mem_accepts,
45
+ size_t n_entries = 1 << CPU_TLB_DYN_DEFAULT_BITS;
143
- .endianness = DEVICE_NATIVE_ENDIAN,
46
+
144
- .valid = {
47
+ tlb_window_reset(desc, now, 0);
145
- .min_access_size = 1,
48
+ desc->n_used_entries = 0;
146
- .max_access_size = 8,
49
+ fast->mask = (n_entries - 1) << CPU_TLB_ENTRY_BITS;
147
- .unaligned = false,
50
+ fast->table = g_new(CPUTLBEntry, n_entries);
148
- },
51
+ desc->iotlb = g_new(CPUIOTLBEntry, n_entries);
149
- .impl = {
52
+}
150
- .min_access_size = 1,
53
+
151
- .max_access_size = 8,
54
static inline void tlb_n_used_entries_inc(CPUArchState *env, uintptr_t mmu_idx)
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
{
55
{
161
memory_region_init_io(&io_mem_unassigned, NULL, &unassigned_mem_ops, NULL,
56
env_tlb(env)->d[mmu_idx].n_used_entries++;
162
NULL, UINT64_MAX);
57
@@ -XXX,XX +XXX,XX @@ static inline void tlb_n_used_entries_dec(CPUArchState *env, uintptr_t mmu_idx)
163
-
58
void tlb_init(CPUState *cpu)
164
- /* io_mem_notdirty calls tb_invalidate_phys_page_fast,
59
{
165
- * which can be called without the iothread mutex.
60
CPUArchState *env = cpu->env_ptr;
166
- */
61
+ int64_t now = get_clock_realtime();
167
- memory_region_init_io(&io_mem_notdirty, NULL, &notdirty_mem_ops, NULL,
62
+ int i;
168
- NULL, UINT64_MAX);
63
169
- memory_region_clear_global_locking(&io_mem_notdirty);
64
qemu_spin_init(&env_tlb(env)->c.lock);
65
66
/* Ensure that cpu_reset performs a full flush. */
67
env_tlb(env)->c.dirty = ALL_MMUIDX_BITS;
68
69
- tlb_dyn_init(env);
70
+ for (i = 0; i < NB_MMU_MODES; i++) {
71
+ tlb_mmu_init(&env_tlb(env)->d[i], &env_tlb(env)->f[i], now);
72
+ }
170
}
73
}
171
74
172
AddressSpaceDispatch *address_space_dispatch_new(FlatView *fv)
75
/* flush_all_helper: run fn across all cpus
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
--
76
--
231
2.17.1
77
2.20.1
232
78
233
79
diff view generated by jsdifflib
1
It does not require going through the whole I/O path
1
There's little point in leaving these data structures half initialized,
2
in order to discard a write.
2
and relying on a flush to be done during reset.
3
3
4
Reviewed-by: David Hildenbrand <david@redhat.com>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
---
7
include/exec/cpu-all.h | 5 ++++-
8
accel/tcg/cputlb.c | 5 +++--
8
include/exec/cpu-common.h | 1 -
9
1 file changed, 3 insertions(+), 2 deletions(-)
9
accel/tcg/cputlb.c | 36 ++++++++++++++++++++--------------
10
exec.c | 41 +--------------------------------------
11
4 files changed, 26 insertions(+), 57 deletions(-)
12
10
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
11
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
47
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
48
--- a/accel/tcg/cputlb.c
13
--- a/accel/tcg/cputlb.c
49
+++ b/accel/tcg/cputlb.c
14
+++ b/accel/tcg/cputlb.c
50
@@ -XXX,XX +XXX,XX @@ static void tlb_reset_dirty_range_locked(CPUTLBEntry *tlb_entry,
15
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_init(CPUTLBDesc *desc, CPUTLBDescFast *fast, int64_t now)
51
{
16
fast->mask = (n_entries - 1) << CPU_TLB_ENTRY_BITS;
52
uintptr_t addr = tlb_entry->addr_write;
17
fast->table = g_new(CPUTLBEntry, n_entries);
53
18
desc->iotlb = g_new(CPUIOTLBEntry, n_entries);
54
- if ((addr & (TLB_INVALID_MASK | TLB_MMIO | TLB_NOTDIRTY)) == 0) {
19
+ tlb_mmu_flush_locked(desc, fast);
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
}
20
}
168
21
169
-static void readonly_mem_write(void *opaque, hwaddr addr,
22
static inline void tlb_n_used_entries_inc(CPUArchState *env, uintptr_t mmu_idx)
170
- uint64_t val, unsigned size)
23
@@ -XXX,XX +XXX,XX @@ void tlb_init(CPUState *cpu)
171
-{
24
172
- /* Ignore any write to ROM. */
25
qemu_spin_init(&env_tlb(env)->c.lock);
173
-}
26
174
-
27
- /* Ensure that cpu_reset performs a full flush. */
175
-static bool readonly_mem_accepts(void *opaque, hwaddr addr,
28
- env_tlb(env)->c.dirty = ALL_MMUIDX_BITS;
176
- unsigned size, bool is_write,
29
+ /* All tlbs are initialized flushed. */
177
- MemTxAttrs attrs)
30
+ env_tlb(env)->c.dirty = 0;
178
-{
31
179
- return is_write;
32
for (i = 0; i < NB_MMU_MODES; i++) {
180
-}
33
tlb_mmu_init(&env_tlb(env)->d[i], &env_tlb(env)->f[i], now);
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
--
34
--
223
2.17.1
35
2.20.1
224
36
225
37
diff view generated by jsdifflib
1
There is only one caller, tlb_set_page_with_attrs. We cannot
1
Do not call get_clock_realtime() in tlb_mmu_resize_locked,
2
inline the entire function because the AddressSpaceDispatch
2
but hoist outside of any loop over a set of tlbs. This is
3
structure is private to exec.c, and cannot easily be moved to
3
only two (indirect) callers, tlb_flush_by_mmuidx_async_work
4
include/exec/memory-internal.h.
4
and tlb_flush_page_locked, so not onerous.
5
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
5
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
---
10
---
13
include/exec/exec-all.h | 6 +---
11
accel/tcg/cputlb.c | 14 ++++++++------
14
accel/tcg/cputlb.c | 68 ++++++++++++++++++++++++++---------------
12
1 file changed, 8 insertions(+), 6 deletions(-)
15
exec.c | 22 ++-----------
16
3 files changed, 47 insertions(+), 49 deletions(-)
17
13
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
14
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
36
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
37
--- a/accel/tcg/cputlb.c
16
--- a/accel/tcg/cputlb.c
38
+++ b/accel/tcg/cputlb.c
17
+++ b/accel/tcg/cputlb.c
39
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
18
@@ -XXX,XX +XXX,XX @@ static void tlb_window_reset(CPUTLBDesc *desc, int64_t ns,
40
MemoryRegionSection *section;
19
* high), since otherwise we are likely to have a significant amount of
41
unsigned int index;
20
* conflict misses.
42
target_ulong address;
21
*/
43
- target_ulong code_address;
22
-static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast)
44
+ target_ulong write_address;
23
+static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast,
45
uintptr_t addend;
24
+ int64_t now)
46
CPUTLBEntry *te, tn;
25
{
47
hwaddr iotlb, xlat, sz, paddr_page;
26
size_t old_size = tlb_n_entries(fast);
48
target_ulong vaddr_page;
27
size_t rate;
49
int asidx = cpu_asidx_from_attrs(cpu, attrs);
28
size_t new_size = old_size;
50
int wp_flags;
29
- int64_t now = get_clock_realtime();
51
+ bool is_ram, is_romd;
30
int64_t window_len_ms = 100;
31
int64_t window_len_ns = window_len_ms * 1000 * 1000;
32
bool window_expired = now > desc->window_begin_ns + window_len_ns;
33
@@ -XXX,XX +XXX,XX @@ static void tlb_mmu_flush_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast)
34
memset(desc->vtable, -1, sizeof(desc->vtable));
35
}
36
37
-static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
38
+static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx,
39
+ int64_t now)
40
{
41
CPUTLBDesc *desc = &env_tlb(env)->d[mmu_idx];
42
CPUTLBDescFast *fast = &env_tlb(env)->f[mmu_idx];
43
44
- tlb_mmu_resize_locked(desc, fast);
45
+ tlb_mmu_resize_locked(desc, fast, now);
46
tlb_mmu_flush_locked(desc, fast);
47
}
48
49
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data)
50
CPUArchState *env = cpu->env_ptr;
51
uint16_t asked = data.host_int;
52
uint16_t all_dirty, work, to_clean;
53
+ int64_t now = get_clock_realtime();
52
54
53
assert_cpu_is_self(cpu);
55
assert_cpu_is_self(cpu);
54
56
55
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
57
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data)
56
if (attrs.byte_swap) {
58
57
address |= TLB_BSWAP;
59
for (work = to_clean; work != 0; work &= work - 1) {
60
int mmu_idx = ctz32(work);
61
- tlb_flush_one_mmuidx_locked(env, mmu_idx);
62
+ tlb_flush_one_mmuidx_locked(env, mmu_idx, now);
58
}
63
}
59
- if (!memory_region_is_ram(section->mr) &&
64
60
- !memory_region_is_romd(section->mr)) {
65
qemu_spin_unlock(&env_tlb(env)->c.lock);
61
- /* IO memory case */
66
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_page_locked(CPUArchState *env, int midx,
62
- address |= TLB_MMIO;
67
tlb_debug("forcing full flush midx %d ("
63
- addend = 0;
68
TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
64
- } else {
69
midx, lp_addr, lp_mask);
65
+
70
- tlb_flush_one_mmuidx_locked(env, midx);
66
+ is_ram = memory_region_is_ram(section->mr);
71
+ tlb_flush_one_mmuidx_locked(env, midx, get_clock_realtime());
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 {
72
} else {
129
tn.addr_code = -1;
73
if (tlb_flush_entry_locked(tlb_entry(env, midx, page), page)) {
130
}
74
tlb_n_used_entries_dec(env, midx);
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
--
75
--
185
2.17.1
76
2.20.1
186
77
187
78
diff view generated by jsdifflib
1
These bits do not need to vary with the actual page size
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
used by the guest.
3
2
3
To avoid scrolling each instruction when reviewing tcg
4
helpers written for the decodetree script, display the
5
.decode files (similar to header declarations) before
6
the C source (implementation of previous declarations).
7
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: David Hildenbrand <david@redhat.com>
11
Message-Id: <20191230082856.30556-1-philmd@redhat.com>
6
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
13
---
9
include/exec/cpu-all.h | 16 ++++++++++------
14
scripts/git.orderfile | 3 +++
10
1 file changed, 10 insertions(+), 6 deletions(-)
15
1 file changed, 3 insertions(+)
11
16
12
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
17
diff --git a/scripts/git.orderfile b/scripts/git.orderfile
13
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
14
--- a/include/exec/cpu-all.h
19
--- a/scripts/git.orderfile
15
+++ b/include/exec/cpu-all.h
20
+++ b/scripts/git.orderfile
16
@@ -XXX,XX +XXX,XX @@ CPUArchState *cpu_copy(CPUArchState *env);
21
@@ -XXX,XX +XXX,XX @@ qga/*.json
17
22
# headers
18
#if !defined(CONFIG_USER_ONLY)
23
*.h
19
24
20
-/* Flags stored in the low bits of the TLB virtual address. These are
25
+# decoding tree specification
21
- * defined so that fast path ram access is all zeros.
26
+*.decode
22
+/*
27
+
23
+ * Flags stored in the low bits of the TLB virtual address.
28
# code
24
+ * These are defined so that fast path ram access is all zeros.
29
*.c
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
--
30
--
48
2.17.1
31
2.20.1
49
32
50
33
diff view generated by jsdifflib