blob: f5d056cc083ff24777d72653c80222a0c27d1b65 [file] [log] [blame]
Blue Swirl0cac1b62012-04-09 16:50:52 +00001/*
2 * Common CPU TLB handling
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19
Peter Maydell7b31bbc2016-01-26 18:16:56 +000020#include "qemu/osdep.h"
Jan Kiszka8d04fb52017-02-23 18:29:11 +000021#include "qemu/main-loop.h"
Blue Swirl0cac1b62012-04-09 16:50:52 +000022#include "cpu.h"
Paolo Bonzini022c62c2012-12-17 18:19:49 +010023#include "exec/exec-all.h"
24#include "exec/memory.h"
25#include "exec/address-spaces.h"
Paolo Bonzinif08b6172014-03-28 19:42:10 +010026#include "exec/cpu_ldst.h"
Paolo Bonzini022c62c2012-12-17 18:19:49 +010027#include "exec/cputlb.h"
Paolo Bonzini022c62c2012-12-17 18:19:49 +010028#include "exec/memory-internal.h"
Juan Quintela220c3eb2013-10-14 17:13:59 +020029#include "exec/ram_addr.h"
Paolo Bonzini0f590e72014-03-28 17:55:24 +010030#include "tcg/tcg.h"
Peter Maydelld7f30402016-06-20 18:07:05 +010031#include "qemu/error-report.h"
32#include "exec/log.h"
Richard Hendersonc482cb12016-06-28 11:37:27 -070033#include "exec/helper-proto.h"
34#include "qemu/atomic.h"
Blue Swirl0cac1b62012-04-09 16:50:52 +000035
Alex Bennée8526e1f2016-03-15 14:30:24 +000036/* DEBUG defines, enable DEBUG_TLB_LOG to log to the CPU_LOG_MMU target */
37/* #define DEBUG_TLB */
38/* #define DEBUG_TLB_LOG */
39
40#ifdef DEBUG_TLB
41# define DEBUG_TLB_GATE 1
42# ifdef DEBUG_TLB_LOG
43# define DEBUG_TLB_LOG_GATE 1
44# else
45# define DEBUG_TLB_LOG_GATE 0
46# endif
47#else
48# define DEBUG_TLB_GATE 0
49# define DEBUG_TLB_LOG_GATE 0
50#endif
51
52#define tlb_debug(fmt, ...) do { \
53 if (DEBUG_TLB_LOG_GATE) { \
54 qemu_log_mask(CPU_LOG_MMU, "%s: " fmt, __func__, \
55 ## __VA_ARGS__); \
56 } else if (DEBUG_TLB_GATE) { \
57 fprintf(stderr, "%s: " fmt, __func__, ## __VA_ARGS__); \
58 } \
59} while (0)
Blue Swirl0cac1b62012-04-09 16:50:52 +000060
Alex Bennéef0aff0f2017-02-23 18:29:16 +000061#define assert_cpu_is_self(this_cpu) do { \
62 if (DEBUG_TLB_GATE) { \
63 g_assert(!cpu->created || qemu_cpu_is_self(cpu)); \
64 } \
65 } while (0)
66
KONRAD Frederice3b9ca82017-02-23 18:29:18 +000067/* run_on_cpu_data.target_ptr should always be big enough for a
68 * target_ulong even on 32 bit builds */
69QEMU_BUILD_BUG_ON(sizeof(target_ulong) > sizeof(run_on_cpu_data));
70
Alex Bennéee7218442017-02-23 18:29:20 +000071/* We currently can't handle more than 16 bits in the MMUIDX bitmask.
72 */
73QEMU_BUILD_BUG_ON(NB_MMU_MODES > 16);
74#define ALL_MMUIDX_BITS ((1 << NB_MMU_MODES) - 1)
75
Alex Bennéec3b9a072017-02-23 18:29:22 +000076/* flush_all_helper: run fn across all cpus
77 *
78 * If the wait flag is set then the src cpu's helper will be queued as
79 * "safe" work and the loop exited creating a synchronisation point
80 * where all queued work will be finished before execution starts
81 * again.
82 */
83static void flush_all_helper(CPUState *src, run_on_cpu_func fn,
84 run_on_cpu_data d)
85{
86 CPUState *cpu;
87
88 CPU_FOREACH(cpu) {
89 if (cpu != src) {
90 async_run_on_cpu(cpu, fn, d);
91 }
92 }
93}
94
Blue Swirl0cac1b62012-04-09 16:50:52 +000095/* statistics */
96int tlb_flush_count;
97
Alex Bennéed10eb082016-11-14 14:17:28 +000098/* This is OK because CPU architectures generally permit an
99 * implementation to drop entries from the TLB at any time, so
100 * flushing more entries than required is only an efficiency issue,
101 * not a correctness issue.
Blue Swirl0cac1b62012-04-09 16:50:52 +0000102 */
KONRAD Frederice3b9ca82017-02-23 18:29:18 +0000103static void tlb_flush_nocheck(CPUState *cpu)
Blue Swirl0cac1b62012-04-09 16:50:52 +0000104{
Andreas Färber00c8cb02013-09-04 02:19:44 +0200105 CPUArchState *env = cpu->env_ptr;
Blue Swirl0cac1b62012-04-09 16:50:52 +0000106
KONRAD Frederice3b9ca82017-02-23 18:29:18 +0000107 /* The QOM tests will trigger tlb_flushes without setting up TCG
108 * so we bug out here in that case.
109 */
110 if (!tcg_enabled()) {
111 return;
112 }
113
Alex Bennéef0aff0f2017-02-23 18:29:16 +0000114 assert_cpu_is_self(cpu);
115 tlb_debug("(count: %d)\n", tlb_flush_count++);
116
KONRAD Frederice3b9ca82017-02-23 18:29:18 +0000117 tb_lock();
118
Richard Henderson4fadb3b2013-12-07 10:44:51 +1300119 memset(env->tlb_table, -1, sizeof(env->tlb_table));
Xin Tong88e89a52014-08-04 20:35:23 -0500120 memset(env->tlb_v_table, -1, sizeof(env->tlb_v_table));
Andreas Färber8cd70432013-08-26 06:03:38 +0200121 memset(cpu->tb_jmp_cache, 0, sizeof(cpu->tb_jmp_cache));
Blue Swirl0cac1b62012-04-09 16:50:52 +0000122
Xin Tong88e89a52014-08-04 20:35:23 -0500123 env->vtlb_index = 0;
Blue Swirl0cac1b62012-04-09 16:50:52 +0000124 env->tlb_flush_addr = -1;
125 env->tlb_flush_mask = 0;
KONRAD Frederice3b9ca82017-02-23 18:29:18 +0000126
127 tb_unlock();
128
Alex Bennéee7218442017-02-23 18:29:20 +0000129 atomic_mb_set(&cpu->pending_tlb_flush, 0);
KONRAD Frederice3b9ca82017-02-23 18:29:18 +0000130}
131
132static void tlb_flush_global_async_work(CPUState *cpu, run_on_cpu_data data)
133{
134 tlb_flush_nocheck(cpu);
135}
136
137void tlb_flush(CPUState *cpu)
138{
139 if (cpu->created && !qemu_cpu_is_self(cpu)) {
Alex Bennéee7218442017-02-23 18:29:20 +0000140 if (atomic_mb_read(&cpu->pending_tlb_flush) != ALL_MMUIDX_BITS) {
141 atomic_mb_set(&cpu->pending_tlb_flush, ALL_MMUIDX_BITS);
KONRAD Frederice3b9ca82017-02-23 18:29:18 +0000142 async_run_on_cpu(cpu, tlb_flush_global_async_work,
143 RUN_ON_CPU_NULL);
144 }
145 } else {
146 tlb_flush_nocheck(cpu);
147 }
Blue Swirl0cac1b62012-04-09 16:50:52 +0000148}
149
Alex Bennéec3b9a072017-02-23 18:29:22 +0000150void tlb_flush_all_cpus(CPUState *src_cpu)
151{
152 const run_on_cpu_func fn = tlb_flush_global_async_work;
153 flush_all_helper(src_cpu, fn, RUN_ON_CPU_NULL);
154 fn(src_cpu, RUN_ON_CPU_NULL);
155}
156
157void tlb_flush_all_cpus_synced(CPUState *src_cpu)
158{
159 const run_on_cpu_func fn = tlb_flush_global_async_work;
160 flush_all_helper(src_cpu, fn, RUN_ON_CPU_NULL);
161 async_safe_run_on_cpu(src_cpu, fn, RUN_ON_CPU_NULL);
162}
163
Alex Bennéee7218442017-02-23 18:29:20 +0000164static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data)
Peter Maydelld7a74a92015-08-25 15:45:09 +0100165{
166 CPUArchState *env = cpu->env_ptr;
Alex Bennéee7218442017-02-23 18:29:20 +0000167 unsigned long mmu_idx_bitmask = data.host_int;
Alex Bennée0336cbf2017-02-23 18:29:19 +0000168 int mmu_idx;
Peter Maydelld7a74a92015-08-25 15:45:09 +0100169
Alex Bennéef0aff0f2017-02-23 18:29:16 +0000170 assert_cpu_is_self(cpu);
Peter Maydelld7a74a92015-08-25 15:45:09 +0100171
KONRAD Frederice3b9ca82017-02-23 18:29:18 +0000172 tb_lock();
173
Alex Bennéee7218442017-02-23 18:29:20 +0000174 tlb_debug("start: mmu_idx:0x%04lx\n", mmu_idx_bitmask);
175
Alex Bennée0336cbf2017-02-23 18:29:19 +0000176 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
Peter Maydelld7a74a92015-08-25 15:45:09 +0100177
Alex Bennée0336cbf2017-02-23 18:29:19 +0000178 if (test_bit(mmu_idx, &mmu_idx_bitmask)) {
179 tlb_debug("%d\n", mmu_idx);
180
181 memset(env->tlb_table[mmu_idx], -1, sizeof(env->tlb_table[0]));
182 memset(env->tlb_v_table[mmu_idx], -1, sizeof(env->tlb_v_table[0]));
Peter Maydelld7a74a92015-08-25 15:45:09 +0100183 }
Peter Maydelld7a74a92015-08-25 15:45:09 +0100184 }
185
Peter Maydelld7a74a92015-08-25 15:45:09 +0100186 memset(cpu->tb_jmp_cache, 0, sizeof(cpu->tb_jmp_cache));
KONRAD Frederice3b9ca82017-02-23 18:29:18 +0000187
Alex Bennéee7218442017-02-23 18:29:20 +0000188 tlb_debug("done\n");
189
KONRAD Frederice3b9ca82017-02-23 18:29:18 +0000190 tb_unlock();
Peter Maydelld7a74a92015-08-25 15:45:09 +0100191}
192
Alex Bennée0336cbf2017-02-23 18:29:19 +0000193void tlb_flush_by_mmuidx(CPUState *cpu, uint16_t idxmap)
Peter Maydelld7a74a92015-08-25 15:45:09 +0100194{
Alex Bennéee7218442017-02-23 18:29:20 +0000195 tlb_debug("mmu_idx: 0x%" PRIx16 "\n", idxmap);
196
197 if (!qemu_cpu_is_self(cpu)) {
198 uint16_t pending_flushes = idxmap;
199 pending_flushes &= ~atomic_mb_read(&cpu->pending_tlb_flush);
200
201 if (pending_flushes) {
202 tlb_debug("reduced mmu_idx: 0x%" PRIx16 "\n", pending_flushes);
203
204 atomic_or(&cpu->pending_tlb_flush, pending_flushes);
205 async_run_on_cpu(cpu, tlb_flush_by_mmuidx_async_work,
206 RUN_ON_CPU_HOST_INT(pending_flushes));
207 }
208 } else {
209 tlb_flush_by_mmuidx_async_work(cpu,
210 RUN_ON_CPU_HOST_INT(idxmap));
211 }
Peter Maydelld7a74a92015-08-25 15:45:09 +0100212}
213
Alex Bennéec3b9a072017-02-23 18:29:22 +0000214void tlb_flush_by_mmuidx_all_cpus(CPUState *src_cpu, uint16_t idxmap)
215{
216 const run_on_cpu_func fn = tlb_flush_by_mmuidx_async_work;
217
218 tlb_debug("mmu_idx: 0x%"PRIx16"\n", idxmap);
219
220 flush_all_helper(src_cpu, fn, RUN_ON_CPU_HOST_INT(idxmap));
221 fn(src_cpu, RUN_ON_CPU_HOST_INT(idxmap));
222}
223
224void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
225 uint16_t idxmap)
226{
227 const run_on_cpu_func fn = tlb_flush_by_mmuidx_async_work;
228
229 tlb_debug("mmu_idx: 0x%"PRIx16"\n", idxmap);
230
231 flush_all_helper(src_cpu, fn, RUN_ON_CPU_HOST_INT(idxmap));
232 async_safe_run_on_cpu(src_cpu, fn, RUN_ON_CPU_HOST_INT(idxmap));
233}
234
235
236
Blue Swirl0cac1b62012-04-09 16:50:52 +0000237static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
238{
239 if (addr == (tlb_entry->addr_read &
240 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
241 addr == (tlb_entry->addr_write &
242 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
243 addr == (tlb_entry->addr_code &
244 (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
Richard Henderson4fadb3b2013-12-07 10:44:51 +1300245 memset(tlb_entry, -1, sizeof(*tlb_entry));
Blue Swirl0cac1b62012-04-09 16:50:52 +0000246 }
247}
248
KONRAD Frederice3b9ca82017-02-23 18:29:18 +0000249static void tlb_flush_page_async_work(CPUState *cpu, run_on_cpu_data data)
Blue Swirl0cac1b62012-04-09 16:50:52 +0000250{
Andreas Färber31b030d2013-09-04 01:29:02 +0200251 CPUArchState *env = cpu->env_ptr;
KONRAD Frederice3b9ca82017-02-23 18:29:18 +0000252 target_ulong addr = (target_ulong) data.target_ptr;
Blue Swirl0cac1b62012-04-09 16:50:52 +0000253 int i;
254 int mmu_idx;
255
Alex Bennéef0aff0f2017-02-23 18:29:16 +0000256 assert_cpu_is_self(cpu);
KONRAD Frederice3b9ca82017-02-23 18:29:18 +0000257
Alex Bennée8526e1f2016-03-15 14:30:24 +0000258 tlb_debug("page :" TARGET_FMT_lx "\n", addr);
259
Blue Swirl0cac1b62012-04-09 16:50:52 +0000260 /* Check if we need to flush due to large pages. */
261 if ((addr & env->tlb_flush_mask) == env->tlb_flush_addr) {
Alex Bennée8526e1f2016-03-15 14:30:24 +0000262 tlb_debug("forcing full flush ("
263 TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
264 env->tlb_flush_addr, env->tlb_flush_mask);
265
Alex Bennéed10eb082016-11-14 14:17:28 +0000266 tlb_flush(cpu);
Blue Swirl0cac1b62012-04-09 16:50:52 +0000267 return;
268 }
Blue Swirl0cac1b62012-04-09 16:50:52 +0000269
270 addr &= TARGET_PAGE_MASK;
271 i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
272 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
273 tlb_flush_entry(&env->tlb_table[mmu_idx][i], addr);
274 }
275
Xin Tong88e89a52014-08-04 20:35:23 -0500276 /* check whether there are entries that need to be flushed in the vtlb */
277 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
278 int k;
279 for (k = 0; k < CPU_VTLB_SIZE; k++) {
280 tlb_flush_entry(&env->tlb_v_table[mmu_idx][k], addr);
281 }
282 }
283
Andreas Färber611d4f92013-09-01 17:52:07 +0200284 tb_flush_jmp_cache(cpu, addr);
Blue Swirl0cac1b62012-04-09 16:50:52 +0000285}
286
KONRAD Frederice3b9ca82017-02-23 18:29:18 +0000287void tlb_flush_page(CPUState *cpu, target_ulong addr)
288{
289 tlb_debug("page :" TARGET_FMT_lx "\n", addr);
290
291 if (!qemu_cpu_is_self(cpu)) {
292 async_run_on_cpu(cpu, tlb_flush_page_async_work,
293 RUN_ON_CPU_TARGET_PTR(addr));
294 } else {
295 tlb_flush_page_async_work(cpu, RUN_ON_CPU_TARGET_PTR(addr));
296 }
297}
298
Alex Bennéee7218442017-02-23 18:29:20 +0000299/* As we are going to hijack the bottom bits of the page address for a
300 * mmuidx bit mask we need to fail to build if we can't do that
301 */
302QEMU_BUILD_BUG_ON(NB_MMU_MODES > TARGET_PAGE_BITS_MIN);
303
304static void tlb_flush_page_by_mmuidx_async_work(CPUState *cpu,
305 run_on_cpu_data data)
Peter Maydelld7a74a92015-08-25 15:45:09 +0100306{
307 CPUArchState *env = cpu->env_ptr;
Alex Bennéee7218442017-02-23 18:29:20 +0000308 target_ulong addr_and_mmuidx = (target_ulong) data.target_ptr;
309 target_ulong addr = addr_and_mmuidx & TARGET_PAGE_MASK;
310 unsigned long mmu_idx_bitmap = addr_and_mmuidx & ALL_MMUIDX_BITS;
311 int page = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
312 int mmu_idx;
313 int i;
Peter Maydelld7a74a92015-08-25 15:45:09 +0100314
Alex Bennéef0aff0f2017-02-23 18:29:16 +0000315 assert_cpu_is_self(cpu);
Alex Bennée8526e1f2016-03-15 14:30:24 +0000316
Alex Bennéee7218442017-02-23 18:29:20 +0000317 tlb_debug("page:%d addr:"TARGET_FMT_lx" mmu_idx:0x%lx\n",
318 page, addr, mmu_idx_bitmap);
Peter Maydelld7a74a92015-08-25 15:45:09 +0100319
Alex Bennée0336cbf2017-02-23 18:29:19 +0000320 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
321 if (test_bit(mmu_idx, &mmu_idx_bitmap)) {
322 tlb_flush_entry(&env->tlb_table[mmu_idx][page], addr);
Peter Maydelld7a74a92015-08-25 15:45:09 +0100323
Alex Bennée0336cbf2017-02-23 18:29:19 +0000324 /* check whether there are vltb entries that need to be flushed */
325 for (i = 0; i < CPU_VTLB_SIZE; i++) {
326 tlb_flush_entry(&env->tlb_v_table[mmu_idx][i], addr);
327 }
Peter Maydelld7a74a92015-08-25 15:45:09 +0100328 }
329 }
Peter Maydelld7a74a92015-08-25 15:45:09 +0100330
Peter Maydelld7a74a92015-08-25 15:45:09 +0100331 tb_flush_jmp_cache(cpu, addr);
332}
333
Alex Bennéee7218442017-02-23 18:29:20 +0000334static void tlb_check_page_and_flush_by_mmuidx_async_work(CPUState *cpu,
335 run_on_cpu_data data)
336{
337 CPUArchState *env = cpu->env_ptr;
338 target_ulong addr_and_mmuidx = (target_ulong) data.target_ptr;
339 target_ulong addr = addr_and_mmuidx & TARGET_PAGE_MASK;
340 unsigned long mmu_idx_bitmap = addr_and_mmuidx & ALL_MMUIDX_BITS;
341
342 tlb_debug("addr:"TARGET_FMT_lx" mmu_idx: %04lx\n", addr, mmu_idx_bitmap);
343
344 /* Check if we need to flush due to large pages. */
345 if ((addr & env->tlb_flush_mask) == env->tlb_flush_addr) {
346 tlb_debug("forced full flush ("
347 TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
348 env->tlb_flush_addr, env->tlb_flush_mask);
349
350 tlb_flush_by_mmuidx_async_work(cpu,
351 RUN_ON_CPU_HOST_INT(mmu_idx_bitmap));
352 } else {
353 tlb_flush_page_by_mmuidx_async_work(cpu, data);
354 }
355}
356
357void tlb_flush_page_by_mmuidx(CPUState *cpu, target_ulong addr, uint16_t idxmap)
358{
359 target_ulong addr_and_mmu_idx;
360
361 tlb_debug("addr: "TARGET_FMT_lx" mmu_idx:%" PRIx16 "\n", addr, idxmap);
362
363 /* This should already be page aligned */
364 addr_and_mmu_idx = addr & TARGET_PAGE_MASK;
365 addr_and_mmu_idx |= idxmap;
366
367 if (!qemu_cpu_is_self(cpu)) {
368 async_run_on_cpu(cpu, tlb_check_page_and_flush_by_mmuidx_async_work,
369 RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
370 } else {
371 tlb_check_page_and_flush_by_mmuidx_async_work(
372 cpu, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
373 }
374}
375
Alex Bennéec3b9a072017-02-23 18:29:22 +0000376void tlb_flush_page_by_mmuidx_all_cpus(CPUState *src_cpu, target_ulong addr,
377 uint16_t idxmap)
KONRAD Frederice3b9ca82017-02-23 18:29:18 +0000378{
Alex Bennéec3b9a072017-02-23 18:29:22 +0000379 const run_on_cpu_func fn = tlb_check_page_and_flush_by_mmuidx_async_work;
380 target_ulong addr_and_mmu_idx;
KONRAD Frederice3b9ca82017-02-23 18:29:18 +0000381
Alex Bennéec3b9a072017-02-23 18:29:22 +0000382 tlb_debug("addr: "TARGET_FMT_lx" mmu_idx:%"PRIx16"\n", addr, idxmap);
383
384 /* This should already be page aligned */
385 addr_and_mmu_idx = addr & TARGET_PAGE_MASK;
386 addr_and_mmu_idx |= idxmap;
387
388 flush_all_helper(src_cpu, fn, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
389 fn(src_cpu, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
390}
391
392void tlb_flush_page_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
393 target_ulong addr,
394 uint16_t idxmap)
395{
396 const run_on_cpu_func fn = tlb_check_page_and_flush_by_mmuidx_async_work;
397 target_ulong addr_and_mmu_idx;
398
399 tlb_debug("addr: "TARGET_FMT_lx" mmu_idx:%"PRIx16"\n", addr, idxmap);
400
401 /* This should already be page aligned */
402 addr_and_mmu_idx = addr & TARGET_PAGE_MASK;
403 addr_and_mmu_idx |= idxmap;
404
405 flush_all_helper(src_cpu, fn, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
406 async_safe_run_on_cpu(src_cpu, fn, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
407}
408
409void tlb_flush_page_all_cpus(CPUState *src, target_ulong addr)
410{
411 const run_on_cpu_func fn = tlb_flush_page_async_work;
412
413 flush_all_helper(src, fn, RUN_ON_CPU_TARGET_PTR(addr));
414 fn(src, RUN_ON_CPU_TARGET_PTR(addr));
415}
416
417void tlb_flush_page_all_cpus_synced(CPUState *src,
418 target_ulong addr)
419{
420 const run_on_cpu_func fn = tlb_flush_page_async_work;
421
422 flush_all_helper(src, fn, RUN_ON_CPU_TARGET_PTR(addr));
423 async_safe_run_on_cpu(src, fn, RUN_ON_CPU_TARGET_PTR(addr));
KONRAD Frederice3b9ca82017-02-23 18:29:18 +0000424}
425
Blue Swirl0cac1b62012-04-09 16:50:52 +0000426/* update the TLBs so that writes to code in the virtual page 'addr'
427 can be detected */
428void tlb_protect_code(ram_addr_t ram_addr)
429{
Stefan Hajnoczi03eebc92014-12-02 11:23:18 +0000430 cpu_physical_memory_test_and_clear_dirty(ram_addr, TARGET_PAGE_SIZE,
431 DIRTY_MEMORY_CODE);
Blue Swirl0cac1b62012-04-09 16:50:52 +0000432}
433
434/* update the TLB so that writes in physical page 'phys_addr' are no longer
435 tested for self modifying code */
Paolo Bonzini9564f522015-04-22 14:24:54 +0200436void tlb_unprotect_code(ram_addr_t ram_addr)
Blue Swirl0cac1b62012-04-09 16:50:52 +0000437{
Juan Quintela52159192013-10-08 12:44:04 +0200438 cpu_physical_memory_set_dirty_flag(ram_addr, DIRTY_MEMORY_CODE);
Blue Swirl0cac1b62012-04-09 16:50:52 +0000439}
440
Blue Swirl0cac1b62012-04-09 16:50:52 +0000441
Alex Bennéeb0706b72017-02-23 18:29:21 +0000442/*
443 * Dirty write flag handling
444 *
445 * When the TCG code writes to a location it looks up the address in
446 * the TLB and uses that data to compute the final address. If any of
447 * the lower bits of the address are set then the slow path is forced.
448 * There are a number of reasons to do this but for normal RAM the
449 * most usual is detecting writes to code regions which may invalidate
450 * generated code.
451 *
452 * Because we want other vCPUs to respond to changes straight away we
453 * update the te->addr_write field atomically. If the TLB entry has
454 * been changed by the vCPU in the mean time we skip the update.
455 *
456 * As this function uses atomic accesses we also need to ensure
457 * updates to tlb_entries follow the same access rules. We don't need
458 * to worry about this for oversized guests as MTTCG is disabled for
459 * them.
460 */
461
462static void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, uintptr_t start,
Blue Swirl0cac1b62012-04-09 16:50:52 +0000463 uintptr_t length)
464{
Alex Bennéeb0706b72017-02-23 18:29:21 +0000465#if TCG_OVERSIZED_GUEST
466 uintptr_t addr = tlb_entry->addr_write;
Blue Swirl0cac1b62012-04-09 16:50:52 +0000467
Alex Bennéeb0706b72017-02-23 18:29:21 +0000468 if ((addr & (TLB_INVALID_MASK | TLB_MMIO | TLB_NOTDIRTY)) == 0) {
469 addr &= TARGET_PAGE_MASK;
470 addr += tlb_entry->addend;
Blue Swirl0cac1b62012-04-09 16:50:52 +0000471 if ((addr - start) < length) {
472 tlb_entry->addr_write |= TLB_NOTDIRTY;
473 }
474 }
Alex Bennéeb0706b72017-02-23 18:29:21 +0000475#else
476 /* paired with atomic_mb_set in tlb_set_page_with_attrs */
477 uintptr_t orig_addr = atomic_mb_read(&tlb_entry->addr_write);
478 uintptr_t addr = orig_addr;
479
480 if ((addr & (TLB_INVALID_MASK | TLB_MMIO | TLB_NOTDIRTY)) == 0) {
481 addr &= TARGET_PAGE_MASK;
482 addr += atomic_read(&tlb_entry->addend);
483 if ((addr - start) < length) {
484 uintptr_t notdirty_addr = orig_addr | TLB_NOTDIRTY;
485 atomic_cmpxchg(&tlb_entry->addr_write, orig_addr, notdirty_addr);
486 }
487 }
488#endif
Blue Swirl0cac1b62012-04-09 16:50:52 +0000489}
490
Alex Bennéeb0706b72017-02-23 18:29:21 +0000491/* For atomic correctness when running MTTCG we need to use the right
492 * primitives when copying entries */
493static inline void copy_tlb_helper(CPUTLBEntry *d, CPUTLBEntry *s,
494 bool atomic_set)
495{
496#if TCG_OVERSIZED_GUEST
497 *d = *s;
498#else
499 if (atomic_set) {
500 d->addr_read = s->addr_read;
501 d->addr_code = s->addr_code;
502 atomic_set(&d->addend, atomic_read(&s->addend));
503 /* Pairs with flag setting in tlb_reset_dirty_range */
504 atomic_mb_set(&d->addr_write, atomic_read(&s->addr_write));
505 } else {
506 d->addr_read = s->addr_read;
507 d->addr_write = atomic_read(&s->addr_write);
508 d->addr_code = s->addr_code;
509 d->addend = atomic_read(&s->addend);
510 }
511#endif
512}
513
514/* This is a cross vCPU call (i.e. another vCPU resetting the flags of
515 * the target vCPU). As such care needs to be taken that we don't
516 * dangerously race with another vCPU update. The only thing actually
517 * updated is the target TLB entry ->addr_write flags.
518 */
Peter Crosthwaite9a135652015-09-10 22:39:41 -0700519void tlb_reset_dirty(CPUState *cpu, ram_addr_t start1, ram_addr_t length)
Blue Swirl0cac1b62012-04-09 16:50:52 +0000520{
521 CPUArchState *env;
522
Peter Crosthwaite9a135652015-09-10 22:39:41 -0700523 int mmu_idx;
Blue Swirl0cac1b62012-04-09 16:50:52 +0000524
Peter Crosthwaite9a135652015-09-10 22:39:41 -0700525 env = cpu->env_ptr;
526 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
527 unsigned int i;
Blue Swirl0cac1b62012-04-09 16:50:52 +0000528
Peter Crosthwaite9a135652015-09-10 22:39:41 -0700529 for (i = 0; i < CPU_TLB_SIZE; i++) {
530 tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
531 start1, length);
532 }
Xin Tong88e89a52014-08-04 20:35:23 -0500533
Peter Crosthwaite9a135652015-09-10 22:39:41 -0700534 for (i = 0; i < CPU_VTLB_SIZE; i++) {
535 tlb_reset_dirty_range(&env->tlb_v_table[mmu_idx][i],
536 start1, length);
Blue Swirl0cac1b62012-04-09 16:50:52 +0000537 }
538 }
539}
540
541static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, target_ulong vaddr)
542{
543 if (tlb_entry->addr_write == (vaddr | TLB_NOTDIRTY)) {
544 tlb_entry->addr_write = vaddr;
545 }
546}
547
548/* update the TLB corresponding to virtual page vaddr
549 so that it is no longer dirty */
Peter Crosthwaitebcae01e2015-09-10 22:39:42 -0700550void tlb_set_dirty(CPUState *cpu, target_ulong vaddr)
Blue Swirl0cac1b62012-04-09 16:50:52 +0000551{
Peter Crosthwaitebcae01e2015-09-10 22:39:42 -0700552 CPUArchState *env = cpu->env_ptr;
Blue Swirl0cac1b62012-04-09 16:50:52 +0000553 int i;
554 int mmu_idx;
555
Alex Bennéef0aff0f2017-02-23 18:29:16 +0000556 assert_cpu_is_self(cpu);
557
Blue Swirl0cac1b62012-04-09 16:50:52 +0000558 vaddr &= TARGET_PAGE_MASK;
559 i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
560 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
561 tlb_set_dirty1(&env->tlb_table[mmu_idx][i], vaddr);
562 }
Xin Tong88e89a52014-08-04 20:35:23 -0500563
564 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
565 int k;
566 for (k = 0; k < CPU_VTLB_SIZE; k++) {
567 tlb_set_dirty1(&env->tlb_v_table[mmu_idx][k], vaddr);
568 }
569 }
Blue Swirl0cac1b62012-04-09 16:50:52 +0000570}
571
572/* Our TLB does not support large pages, so remember the area covered by
573 large pages and trigger a full TLB flush if these are invalidated. */
574static void tlb_add_large_page(CPUArchState *env, target_ulong vaddr,
575 target_ulong size)
576{
577 target_ulong mask = ~(size - 1);
578
579 if (env->tlb_flush_addr == (target_ulong)-1) {
580 env->tlb_flush_addr = vaddr & mask;
581 env->tlb_flush_mask = mask;
582 return;
583 }
584 /* Extend the existing region to include the new page.
585 This is a compromise between unnecessary flushes and the cost
586 of maintaining a full variable size TLB. */
587 mask &= env->tlb_flush_mask;
588 while (((env->tlb_flush_addr ^ vaddr) & mask) != 0) {
589 mask <<= 1;
590 }
591 env->tlb_flush_addr &= mask;
592 env->tlb_flush_mask = mask;
593}
594
595/* Add a new TLB entry. At most one entry for a given virtual address
Paolo Bonzini79e2b9a2015-01-21 12:09:14 +0100596 * is permitted. Only a single TARGET_PAGE_SIZE region is mapped, the
597 * supplied size is only used by tlb_flush_page.
598 *
599 * Called from TCG-generated code, which is under an RCU read-side
600 * critical section.
601 */
Peter Maydellfadc1cb2015-04-26 16:49:24 +0100602void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
603 hwaddr paddr, MemTxAttrs attrs, int prot,
604 int mmu_idx, target_ulong size)
Blue Swirl0cac1b62012-04-09 16:50:52 +0000605{
Andreas Färber0c591eb2013-09-03 13:59:37 +0200606 CPUArchState *env = cpu->env_ptr;
Blue Swirl0cac1b62012-04-09 16:50:52 +0000607 MemoryRegionSection *section;
608 unsigned int index;
609 target_ulong address;
610 target_ulong code_address;
611 uintptr_t addend;
Alex Bennéeb0706b72017-02-23 18:29:21 +0000612 CPUTLBEntry *te, *tv, tn;
Paolo Bonzini149f54b2013-05-24 12:59:37 +0200613 hwaddr iotlb, xlat, sz;
Xin Tong88e89a52014-08-04 20:35:23 -0500614 unsigned vidx = env->vtlb_index++ % CPU_VTLB_SIZE;
Peter Maydelld7898cd2016-01-21 14:15:05 +0000615 int asidx = cpu_asidx_from_attrs(cpu, attrs);
Blue Swirl0cac1b62012-04-09 16:50:52 +0000616
Alex Bennéef0aff0f2017-02-23 18:29:16 +0000617 assert_cpu_is_self(cpu);
Blue Swirl0cac1b62012-04-09 16:50:52 +0000618 assert(size >= TARGET_PAGE_SIZE);
619 if (size != TARGET_PAGE_SIZE) {
620 tlb_add_large_page(env, vaddr, size);
621 }
Paolo Bonzini149f54b2013-05-24 12:59:37 +0200622
623 sz = size;
Peter Maydelld7898cd2016-01-21 14:15:05 +0000624 section = address_space_translate_for_iotlb(cpu, asidx, paddr, &xlat, &sz);
Paolo Bonzini149f54b2013-05-24 12:59:37 +0200625 assert(sz >= TARGET_PAGE_SIZE);
626
Alex Bennée8526e1f2016-03-15 14:30:24 +0000627 tlb_debug("vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx
628 " prot=%x idx=%d\n",
629 vaddr, paddr, prot, mmu_idx);
Blue Swirl0cac1b62012-04-09 16:50:52 +0000630
631 address = vaddr;
Paolo Bonzini8f3e03c2013-05-24 16:45:30 +0200632 if (!memory_region_is_ram(section->mr) && !memory_region_is_romd(section->mr)) {
633 /* IO memory case */
Blue Swirl0cac1b62012-04-09 16:50:52 +0000634 address |= TLB_MMIO;
Paolo Bonzini8f3e03c2013-05-24 16:45:30 +0200635 addend = 0;
636 } else {
637 /* TLB_MMIO for rom/romd handled below */
Paolo Bonzini149f54b2013-05-24 12:59:37 +0200638 addend = (uintptr_t)memory_region_get_ram_ptr(section->mr) + xlat;
Blue Swirl0cac1b62012-04-09 16:50:52 +0000639 }
Blue Swirl0cac1b62012-04-09 16:50:52 +0000640
641 code_address = address;
Andreas Färberbb0e6272013-09-03 13:32:01 +0200642 iotlb = memory_region_section_get_iotlb(cpu, section, vaddr, paddr, xlat,
Paolo Bonzini149f54b2013-05-24 12:59:37 +0200643 prot, &address);
Blue Swirl0cac1b62012-04-09 16:50:52 +0000644
645 index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
Blue Swirl0cac1b62012-04-09 16:50:52 +0000646 te = &env->tlb_table[mmu_idx][index];
Xin Tong88e89a52014-08-04 20:35:23 -0500647 /* do not discard the translation in te, evict it into a victim tlb */
Alex Bennéeb0706b72017-02-23 18:29:21 +0000648 tv = &env->tlb_v_table[mmu_idx][vidx];
649
650 /* addr_write can race with tlb_reset_dirty_range */
651 copy_tlb_helper(tv, te, true);
652
Xin Tong88e89a52014-08-04 20:35:23 -0500653 env->iotlb_v[mmu_idx][vidx] = env->iotlb[mmu_idx][index];
654
655 /* refill the tlb */
Peter Maydelle469b222015-04-26 16:49:23 +0100656 env->iotlb[mmu_idx][index].addr = iotlb - vaddr;
Peter Maydellfadc1cb2015-04-26 16:49:24 +0100657 env->iotlb[mmu_idx][index].attrs = attrs;
Alex Bennéeb0706b72017-02-23 18:29:21 +0000658
659 /* Now calculate the new entry */
660 tn.addend = addend - vaddr;
Blue Swirl0cac1b62012-04-09 16:50:52 +0000661 if (prot & PAGE_READ) {
Alex Bennéeb0706b72017-02-23 18:29:21 +0000662 tn.addr_read = address;
Blue Swirl0cac1b62012-04-09 16:50:52 +0000663 } else {
Alex Bennéeb0706b72017-02-23 18:29:21 +0000664 tn.addr_read = -1;
Blue Swirl0cac1b62012-04-09 16:50:52 +0000665 }
666
667 if (prot & PAGE_EXEC) {
Alex Bennéeb0706b72017-02-23 18:29:21 +0000668 tn.addr_code = code_address;
Blue Swirl0cac1b62012-04-09 16:50:52 +0000669 } else {
Alex Bennéeb0706b72017-02-23 18:29:21 +0000670 tn.addr_code = -1;
Blue Swirl0cac1b62012-04-09 16:50:52 +0000671 }
Alex Bennéeb0706b72017-02-23 18:29:21 +0000672
673 tn.addr_write = -1;
Blue Swirl0cac1b62012-04-09 16:50:52 +0000674 if (prot & PAGE_WRITE) {
675 if ((memory_region_is_ram(section->mr) && section->readonly)
Blue Swirlcc5bea62012-04-14 14:56:48 +0000676 || memory_region_is_romd(section->mr)) {
Blue Swirl0cac1b62012-04-09 16:50:52 +0000677 /* Write access calls the I/O callback. */
Alex Bennéeb0706b72017-02-23 18:29:21 +0000678 tn.addr_write = address | TLB_MMIO;
Blue Swirl0cac1b62012-04-09 16:50:52 +0000679 } else if (memory_region_is_ram(section->mr)
Fam Zheng8e41fb62016-03-01 14:18:21 +0800680 && cpu_physical_memory_is_clean(
681 memory_region_get_ram_addr(section->mr) + xlat)) {
Alex Bennéeb0706b72017-02-23 18:29:21 +0000682 tn.addr_write = address | TLB_NOTDIRTY;
Blue Swirl0cac1b62012-04-09 16:50:52 +0000683 } else {
Alex Bennéeb0706b72017-02-23 18:29:21 +0000684 tn.addr_write = address;
Blue Swirl0cac1b62012-04-09 16:50:52 +0000685 }
Blue Swirl0cac1b62012-04-09 16:50:52 +0000686 }
Alex Bennéeb0706b72017-02-23 18:29:21 +0000687
688 /* Pairs with flag setting in tlb_reset_dirty_range */
689 copy_tlb_helper(te, &tn, true);
690 /* atomic_mb_set(&te->addr_write, write_address); */
Blue Swirl0cac1b62012-04-09 16:50:52 +0000691}
692
Peter Maydellfadc1cb2015-04-26 16:49:24 +0100693/* Add a new TLB entry, but without specifying the memory
694 * transaction attributes to be used.
695 */
696void tlb_set_page(CPUState *cpu, target_ulong vaddr,
697 hwaddr paddr, int prot,
698 int mmu_idx, target_ulong size)
699{
700 tlb_set_page_with_attrs(cpu, vaddr, paddr, MEMTXATTRS_UNSPECIFIED,
701 prot, mmu_idx, size);
702}
703
Peter Maydelld7f30402016-06-20 18:07:05 +0100704static void report_bad_exec(CPUState *cpu, target_ulong addr)
705{
706 /* Accidentally executing outside RAM or ROM is quite common for
707 * several user-error situations, so report it in a way that
708 * makes it clear that this isn't a QEMU bug and provide suggestions
709 * about what a user could do to fix things.
710 */
711 error_report("Trying to execute code outside RAM or ROM at 0x"
712 TARGET_FMT_lx, addr);
713 error_printf("This usually means one of the following happened:\n\n"
714 "(1) You told QEMU to execute a kernel for the wrong machine "
715 "type, and it crashed on startup (eg trying to run a "
716 "raspberry pi kernel on a versatilepb QEMU machine)\n"
717 "(2) You didn't give QEMU a kernel or BIOS filename at all, "
718 "and QEMU executed a ROM full of no-op instructions until "
719 "it fell off the end\n"
720 "(3) Your guest kernel has a bug and crashed by jumping "
721 "off into nowhere\n\n"
722 "This is almost always one of the first two, so check your "
723 "command line and that you are using the right type of kernel "
724 "for this machine.\n"
725 "If you think option (3) is likely then you can try debugging "
726 "your guest with the -d debug options; in particular "
727 "-d guest_errors will cause the log to include a dump of the "
728 "guest register state at this point.\n\n"
729 "Execution cannot continue; stopping here.\n\n");
730
731 /* Report also to the logs, with more detail including register dump */
732 qemu_log_mask(LOG_GUEST_ERROR, "qemu: fatal: Trying to execute code "
733 "outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);
734 log_cpu_state_mask(LOG_GUEST_ERROR, cpu, CPU_DUMP_FPU | CPU_DUMP_CCOP);
735}
736
Alex Bennée857baec2017-02-23 18:29:17 +0000737static inline ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
738{
739 ram_addr_t ram_addr;
740
741 ram_addr = qemu_ram_addr_from_host(ptr);
742 if (ram_addr == RAM_ADDR_INVALID) {
743 error_report("Bad ram pointer %p", ptr);
744 abort();
745 }
746 return ram_addr;
747}
748
Blue Swirl0cac1b62012-04-09 16:50:52 +0000749/* NOTE: this function can trigger an exception */
750/* NOTE2: the returned address is not exactly the physical address: it
Peter Maydell116aae32012-08-10 17:14:05 +0100751 * is actually a ram_addr_t (in system mode; the user mode emulation
752 * version of this function returns a guest virtual address).
753 */
Blue Swirl0cac1b62012-04-09 16:50:52 +0000754tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
755{
756 int mmu_idx, page_index, pd;
757 void *p;
758 MemoryRegion *mr;
Edgar E. Iglesias09daed82013-12-17 13:06:51 +1000759 CPUState *cpu = ENV_GET_CPU(env1);
Peter Maydella54c87b2016-01-21 14:15:05 +0000760 CPUIOTLBEntry *iotlbentry;
Blue Swirl0cac1b62012-04-09 16:50:52 +0000761
762 page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
Benjamin Herrenschmidt97ed5cc2015-08-17 17:34:10 +1000763 mmu_idx = cpu_mmu_index(env1, true);
Blue Swirl0cac1b62012-04-09 16:50:52 +0000764 if (unlikely(env1->tlb_table[mmu_idx][page_index].addr_code !=
765 (addr & TARGET_PAGE_MASK))) {
Blue Swirl0cac1b62012-04-09 16:50:52 +0000766 cpu_ldub_code(env1, addr);
Blue Swirl0cac1b62012-04-09 16:50:52 +0000767 }
Peter Maydella54c87b2016-01-21 14:15:05 +0000768 iotlbentry = &env1->iotlb[mmu_idx][page_index];
769 pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
770 mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
Blue Swirl0cac1b62012-04-09 16:50:52 +0000771 if (memory_region_is_unassigned(mr)) {
Peter Maydell44d7ce02017-02-28 12:08:15 +0000772 cpu_unassigned_access(cpu, addr, false, true, 0, 4);
773 /* The CPU's unassigned access hook might have longjumped out
774 * with an exception. If it didn't (or there was no hook) then
775 * we can't proceed further.
776 */
777 report_bad_exec(cpu, addr);
778 exit(1);
Blue Swirl0cac1b62012-04-09 16:50:52 +0000779 }
780 p = (void *)((uintptr_t)addr + env1->tlb_table[mmu_idx][page_index].addend);
781 return qemu_ram_addr_from_host_nofail(p);
782}
783
Richard Henderson82a45b92016-07-08 18:51:28 -0700784static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
785 target_ulong addr, uintptr_t retaddr, int size)
786{
787 CPUState *cpu = ENV_GET_CPU(env);
788 hwaddr physaddr = iotlbentry->addr;
789 MemoryRegion *mr = iotlb_to_region(cpu, physaddr, iotlbentry->attrs);
790 uint64_t val;
Jan Kiszka8d04fb52017-02-23 18:29:11 +0000791 bool locked = false;
Richard Henderson82a45b92016-07-08 18:51:28 -0700792
793 physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
794 cpu->mem_io_pc = retaddr;
795 if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu->can_do_io) {
796 cpu_io_recompile(cpu, retaddr);
797 }
798
799 cpu->mem_io_vaddr = addr;
Jan Kiszka8d04fb52017-02-23 18:29:11 +0000800
801 if (mr->global_locking) {
802 qemu_mutex_lock_iothread();
803 locked = true;
804 }
Richard Henderson82a45b92016-07-08 18:51:28 -0700805 memory_region_dispatch_read(mr, physaddr, &val, size, iotlbentry->attrs);
Jan Kiszka8d04fb52017-02-23 18:29:11 +0000806 if (locked) {
807 qemu_mutex_unlock_iothread();
808 }
809
Richard Henderson82a45b92016-07-08 18:51:28 -0700810 return val;
811}
812
813static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
814 uint64_t val, target_ulong addr,
815 uintptr_t retaddr, int size)
816{
817 CPUState *cpu = ENV_GET_CPU(env);
818 hwaddr physaddr = iotlbentry->addr;
819 MemoryRegion *mr = iotlb_to_region(cpu, physaddr, iotlbentry->attrs);
Jan Kiszka8d04fb52017-02-23 18:29:11 +0000820 bool locked = false;
Richard Henderson82a45b92016-07-08 18:51:28 -0700821
822 physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
823 if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu->can_do_io) {
824 cpu_io_recompile(cpu, retaddr);
825 }
Richard Henderson82a45b92016-07-08 18:51:28 -0700826 cpu->mem_io_vaddr = addr;
827 cpu->mem_io_pc = retaddr;
Jan Kiszka8d04fb52017-02-23 18:29:11 +0000828
829 if (mr->global_locking) {
830 qemu_mutex_lock_iothread();
831 locked = true;
832 }
Richard Henderson82a45b92016-07-08 18:51:28 -0700833 memory_region_dispatch_write(mr, physaddr, val, size, iotlbentry->attrs);
Jan Kiszka8d04fb52017-02-23 18:29:11 +0000834 if (locked) {
835 qemu_mutex_unlock_iothread();
836 }
Richard Henderson82a45b92016-07-08 18:51:28 -0700837}
838
Richard Henderson7e9a7c52016-07-08 12:19:32 -0700839/* Return true if ADDR is present in the victim tlb, and has been copied
840 back to the main tlb. */
841static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
842 size_t elt_ofs, target_ulong page)
843{
844 size_t vidx;
845 for (vidx = 0; vidx < CPU_VTLB_SIZE; ++vidx) {
846 CPUTLBEntry *vtlb = &env->tlb_v_table[mmu_idx][vidx];
847 target_ulong cmp = *(target_ulong *)((uintptr_t)vtlb + elt_ofs);
848
849 if (cmp == page) {
850 /* Found entry in victim tlb, swap tlb and iotlb. */
851 CPUTLBEntry tmptlb, *tlb = &env->tlb_table[mmu_idx][index];
Alex Bennéeb0706b72017-02-23 18:29:21 +0000852
853 copy_tlb_helper(&tmptlb, tlb, false);
854 copy_tlb_helper(tlb, vtlb, true);
855 copy_tlb_helper(vtlb, &tmptlb, true);
856
Richard Henderson7e9a7c52016-07-08 12:19:32 -0700857 CPUIOTLBEntry tmpio, *io = &env->iotlb[mmu_idx][index];
858 CPUIOTLBEntry *vio = &env->iotlb_v[mmu_idx][vidx];
Richard Henderson7e9a7c52016-07-08 12:19:32 -0700859 tmpio = *io; *io = *vio; *vio = tmpio;
860 return true;
861 }
862 }
863 return false;
864}
865
866/* Macro to call the above, with local variables from the use context. */
Samuel Damasheka3902842016-07-06 14:26:52 -0400867#define VICTIM_TLB_HIT(TY, ADDR) \
Richard Henderson7e9a7c52016-07-08 12:19:32 -0700868 victim_tlb_hit(env, mmu_idx, index, offsetof(CPUTLBEntry, TY), \
Samuel Damasheka3902842016-07-06 14:26:52 -0400869 (ADDR) & TARGET_PAGE_MASK)
Richard Henderson7e9a7c52016-07-08 12:19:32 -0700870
Richard Henderson3b08f0a2016-07-08 18:22:26 -0700871/* Probe for whether the specified guest write access is permitted.
872 * If it is not permitted then an exception will be taken in the same
873 * way as if this were a real write access (and we will not return).
874 * Otherwise the function will return, and there will be a valid
875 * entry in the TLB for this access.
876 */
877void probe_write(CPUArchState *env, target_ulong addr, int mmu_idx,
878 uintptr_t retaddr)
879{
880 int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
881 target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
882
883 if ((addr & TARGET_PAGE_MASK)
884 != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
885 /* TLB entry is for a different page */
886 if (!VICTIM_TLB_HIT(addr_write, addr)) {
887 tlb_fill(ENV_GET_CPU(env), addr, MMU_DATA_STORE, mmu_idx, retaddr);
888 }
889 }
890}
891
Richard Hendersonc482cb12016-06-28 11:37:27 -0700892/* Probe for a read-modify-write atomic operation. Do not allow unaligned
893 * operations, or io operations to proceed. Return the host address. */
894static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
895 TCGMemOpIdx oi, uintptr_t retaddr)
896{
897 size_t mmu_idx = get_mmuidx(oi);
898 size_t index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
899 CPUTLBEntry *tlbe = &env->tlb_table[mmu_idx][index];
900 target_ulong tlb_addr = tlbe->addr_write;
901 TCGMemOp mop = get_memop(oi);
902 int a_bits = get_alignment_bits(mop);
903 int s_bits = mop & MO_SIZE;
904
905 /* Adjust the given return address. */
906 retaddr -= GETPC_ADJ;
907
908 /* Enforce guest required alignment. */
909 if (unlikely(a_bits > 0 && (addr & ((1 << a_bits) - 1)))) {
910 /* ??? Maybe indicate atomic op to cpu_unaligned_access */
911 cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
912 mmu_idx, retaddr);
913 }
914
915 /* Enforce qemu required alignment. */
916 if (unlikely(addr & ((1 << s_bits) - 1))) {
917 /* We get here if guest alignment was not requested,
918 or was not enforced by cpu_unaligned_access above.
919 We might widen the access and emulate, but for now
920 mark an exception and exit the cpu loop. */
921 goto stop_the_world;
922 }
923
924 /* Check TLB entry and enforce page permissions. */
925 if ((addr & TARGET_PAGE_MASK)
926 != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
927 if (!VICTIM_TLB_HIT(addr_write, addr)) {
928 tlb_fill(ENV_GET_CPU(env), addr, MMU_DATA_STORE, mmu_idx, retaddr);
929 }
930 tlb_addr = tlbe->addr_write;
931 }
932
933 /* Notice an IO access, or a notdirty page. */
934 if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
935 /* There's really nothing that can be done to
936 support this apart from stop-the-world. */
937 goto stop_the_world;
938 }
939
940 /* Let the guest notice RMW on a write-only page. */
941 if (unlikely(tlbe->addr_read != tlb_addr)) {
942 tlb_fill(ENV_GET_CPU(env), addr, MMU_DATA_LOAD, mmu_idx, retaddr);
943 /* Since we don't support reads and writes to different addresses,
944 and we do have the proper page loaded for write, this shouldn't
945 ever return. But just in case, handle via stop-the-world. */
946 goto stop_the_world;
947 }
948
949 return (void *)((uintptr_t)addr + tlbe->addend);
950
951 stop_the_world:
952 cpu_loop_exit_atomic(ENV_GET_CPU(env), retaddr);
953}
954
Richard Hendersonc86c6e42016-07-08 19:02:33 -0700955#ifdef TARGET_WORDS_BIGENDIAN
956# define TGT_BE(X) (X)
957# define TGT_LE(X) BSWAP(X)
958#else
959# define TGT_BE(X) BSWAP(X)
960# define TGT_LE(X) (X)
961#endif
962
Paolo Bonzini0f590e72014-03-28 17:55:24 +0100963#define MMUSUFFIX _mmu
964
Richard Hendersondea21982016-07-08 18:14:28 -0700965#define DATA_SIZE 1
Paolo Bonzini58ed2702014-03-28 18:00:25 +0100966#include "softmmu_template.h"
Paolo Bonzini0f590e72014-03-28 17:55:24 +0100967
Richard Hendersondea21982016-07-08 18:14:28 -0700968#define DATA_SIZE 2
Paolo Bonzini58ed2702014-03-28 18:00:25 +0100969#include "softmmu_template.h"
Paolo Bonzini0f590e72014-03-28 17:55:24 +0100970
Richard Hendersondea21982016-07-08 18:14:28 -0700971#define DATA_SIZE 4
Paolo Bonzini58ed2702014-03-28 18:00:25 +0100972#include "softmmu_template.h"
Paolo Bonzini0f590e72014-03-28 17:55:24 +0100973
Richard Hendersondea21982016-07-08 18:14:28 -0700974#define DATA_SIZE 8
Paolo Bonzini58ed2702014-03-28 18:00:25 +0100975#include "softmmu_template.h"
Paolo Bonzini0f590e72014-03-28 17:55:24 +0100976
Richard Hendersonc482cb12016-06-28 11:37:27 -0700977/* First set of helpers allows passing in of OI and RETADDR. This makes
978 them callable from other helpers. */
979
980#define EXTRA_ARGS , TCGMemOpIdx oi, uintptr_t retaddr
981#define ATOMIC_NAME(X) \
982 HELPER(glue(glue(glue(atomic_ ## X, SUFFIX), END), _mmu))
983#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, oi, retaddr)
984
985#define DATA_SIZE 1
986#include "atomic_template.h"
987
988#define DATA_SIZE 2
989#include "atomic_template.h"
990
991#define DATA_SIZE 4
992#include "atomic_template.h"
993
Richard Hendersondf79b992016-09-02 12:23:57 -0700994#ifdef CONFIG_ATOMIC64
Richard Hendersonc482cb12016-06-28 11:37:27 -0700995#define DATA_SIZE 8
996#include "atomic_template.h"
Richard Hendersondf79b992016-09-02 12:23:57 -0700997#endif
Richard Hendersonc482cb12016-06-28 11:37:27 -0700998
Richard Henderson7ebee432016-06-29 21:10:59 -0700999#ifdef CONFIG_ATOMIC128
1000#define DATA_SIZE 16
1001#include "atomic_template.h"
1002#endif
1003
Richard Hendersonc482cb12016-06-28 11:37:27 -07001004/* Second set of helpers are directly callable from TCG as helpers. */
1005
1006#undef EXTRA_ARGS
1007#undef ATOMIC_NAME
1008#undef ATOMIC_MMU_LOOKUP
1009#define EXTRA_ARGS , TCGMemOpIdx oi
1010#define ATOMIC_NAME(X) HELPER(glue(glue(atomic_ ## X, SUFFIX), END))
1011#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, oi, GETPC())
1012
1013#define DATA_SIZE 1
1014#include "atomic_template.h"
1015
1016#define DATA_SIZE 2
1017#include "atomic_template.h"
1018
1019#define DATA_SIZE 4
1020#include "atomic_template.h"
1021
Richard Hendersondf79b992016-09-02 12:23:57 -07001022#ifdef CONFIG_ATOMIC64
Richard Hendersonc482cb12016-06-28 11:37:27 -07001023#define DATA_SIZE 8
1024#include "atomic_template.h"
Richard Hendersondf79b992016-09-02 12:23:57 -07001025#endif
Richard Hendersonc482cb12016-06-28 11:37:27 -07001026
1027/* Code access functions. */
1028
1029#undef MMUSUFFIX
Blue Swirl0cac1b62012-04-09 16:50:52 +00001030#define MMUSUFFIX _cmmu
Richard Henderson01ecaf42016-07-26 06:09:16 +05301031#undef GETPC
1032#define GETPC() ((uintptr_t)0)
Blue Swirl0cac1b62012-04-09 16:50:52 +00001033#define SOFTMMU_CODE_ACCESS
1034
Richard Hendersondea21982016-07-08 18:14:28 -07001035#define DATA_SIZE 1
Paolo Bonzini58ed2702014-03-28 18:00:25 +01001036#include "softmmu_template.h"
Blue Swirl0cac1b62012-04-09 16:50:52 +00001037
Richard Hendersondea21982016-07-08 18:14:28 -07001038#define DATA_SIZE 2
Paolo Bonzini58ed2702014-03-28 18:00:25 +01001039#include "softmmu_template.h"
Blue Swirl0cac1b62012-04-09 16:50:52 +00001040
Richard Hendersondea21982016-07-08 18:14:28 -07001041#define DATA_SIZE 4
Paolo Bonzini58ed2702014-03-28 18:00:25 +01001042#include "softmmu_template.h"
Blue Swirl0cac1b62012-04-09 16:50:52 +00001043
Richard Hendersondea21982016-07-08 18:14:28 -07001044#define DATA_SIZE 8
Paolo Bonzini58ed2702014-03-28 18:00:25 +01001045#include "softmmu_template.h"