blob: ef437fae10b127d23ed4f19f9b08936f7dc2b1d3 [file] [log] [blame]
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001/*
2 * virtual page mapping and translated block 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
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070017 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080018 */
19#include "config.h"
20#ifdef _WIN32
21#define WIN32_LEAN_AND_MEAN
22#include <windows.h>
23#else
24#include <sys/types.h>
25#include <sys/mman.h>
26#endif
27#include <stdlib.h>
28#include <stdio.h>
29#include <stdarg.h>
30#include <string.h>
31#include <errno.h>
32#include <unistd.h>
33#include <inttypes.h>
34
35#include "cpu.h"
David 'Digit' Turner852088c2013-12-14 23:04:12 +010036#include "exec/exec-all.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080037#include "qemu-common.h"
38#include "tcg.h"
39#include "hw/hw.h"
David 'Digit' Turner84569132013-12-13 17:34:07 +010040#include "qemu/osdep.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +010041#include "sysemu/kvm.h"
David 'Digit' Turner3dc53fc2014-01-17 01:23:40 +010042#include "exec/cputlb.h"
David 'Digit' Turnere1e03df2013-12-15 00:42:21 +010043#include "exec/hax.h"
David 'Digit' Turner7a78db72013-12-14 11:46:01 +010044#include "qemu/timer.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080045#if defined(CONFIG_USER_ONLY)
46#include <qemu.h>
47#endif
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -080048#ifdef CONFIG_MEMCHECK
49#include "memcheck/memcheck_api.h"
50#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080051
52//#define DEBUG_TB_INVALIDATE
53//#define DEBUG_FLUSH
54//#define DEBUG_TLB
55//#define DEBUG_UNASSIGNED
56
57/* make various TB consistency checks */
58//#define DEBUG_TB_CHECK
59//#define DEBUG_TLB_CHECK
60
61//#define DEBUG_IOPORT
62//#define DEBUG_SUBPAGE
63
64#if !defined(CONFIG_USER_ONLY)
65/* TB consistency checks only implemented for usermode emulation. */
66#undef DEBUG_TB_CHECK
67#endif
68
69#define SMC_BITMAP_USE_THRESHOLD 10
70
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070071static TranslationBlock *tbs;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080072int code_gen_max_blocks;
73TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070074static int nb_tbs;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080075/* any access to the tbs or the page table must use this lock */
76spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
77
78#if defined(__arm__) || defined(__sparc_v9__)
79/* The prologue must be reachable with a direct jump. ARM and Sparc64
80 have limited branch ranges (possibly also PPC) so place it in a
81 section close to code segment. */
82#define code_gen_section \
83 __attribute__((__section__(".gen_code"))) \
84 __attribute__((aligned (32)))
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070085#elif defined(_WIN32)
86/* Maximum alignment for Win32 is 16. */
87#define code_gen_section \
88 __attribute__((aligned (16)))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080089#else
90#define code_gen_section \
91 __attribute__((aligned (32)))
92#endif
93
94uint8_t code_gen_prologue[1024] code_gen_section;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070095static uint8_t *code_gen_buffer;
96static unsigned long code_gen_buffer_size;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080097/* threshold to flush the translated code buffer */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070098static unsigned long code_gen_buffer_max_size;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080099uint8_t *code_gen_ptr;
100
101#if !defined(CONFIG_USER_ONLY)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800102int phys_ram_fd;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700103static int in_migration;
104
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200105RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list) };
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800106#endif
107
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100108CPUArchState *first_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800109/* current CPU in the current thread. It is only valid inside
110 cpu_exec() */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100111CPUArchState *cpu_single_env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800112/* 0 = Do not count executed instructions.
113 1 = Precise instruction counting.
114 2 = Adaptive rate instruction counting. */
115int use_icount = 0;
116/* Current instruction counter. While executing translated code this may
117 include some instructions that have not yet been executed. */
118int64_t qemu_icount;
119
120typedef struct PageDesc {
121 /* list of TBs intersecting this ram page */
122 TranslationBlock *first_tb;
123 /* in order to optimize self modifying code, we count the number
124 of lookups we do to a given page to use a bitmap */
125 unsigned int code_write_count;
126 uint8_t *code_bitmap;
127#if defined(CONFIG_USER_ONLY)
128 unsigned long flags;
129#endif
130} PageDesc;
131
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800132#define L2_BITS 10
133#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
134/* XXX: this is a temporary hack for alpha target.
135 * In the future, this is to be replaced by a multi-level table
136 * to actually be able to handle the complete 64 bits address space.
137 */
138#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
139#else
140#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
141#endif
142
143#define L1_SIZE (1 << L1_BITS)
144#define L2_SIZE (1 << L2_BITS)
145
David 'Digit' Turnerf0729c72014-01-13 16:10:10 +0100146uintptr_t qemu_real_host_page_size;
David 'Digit' Turnerf0729c72014-01-13 16:10:10 +0100147uintptr_t qemu_host_page_size;
148uintptr_t qemu_host_page_mask;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800149
150/* XXX: for system emulation, it could just be an array */
151static PageDesc *l1_map[L1_SIZE];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700152static PhysPageDesc **l1_phys_map;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800153
154#if !defined(CONFIG_USER_ONLY)
155static void io_mem_init(void);
156
157/* io memory support */
158CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
159CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
160void *io_mem_opaque[IO_MEM_NB_ENTRIES];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700161static char io_mem_used[IO_MEM_NB_ENTRIES];
David 'Digit' Turner3dc53fc2014-01-17 01:23:40 +0100162int io_mem_watch;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800163#endif
164
165/* log support */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700166#ifdef WIN32
167static const char *logfilename = "qemu.log";
168#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700169static const char *logfilename = "/tmp/qemu.log";
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700170#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800171FILE *logfile;
172int loglevel;
173static int log_append = 0;
174
175/* statistics */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800176static int tb_flush_count;
177static int tb_phys_invalidate_count;
178
179#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
180typedef struct subpage_t {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100181 hwaddr base;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800182 CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE][4];
183 CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE][4];
184 void *opaque[TARGET_PAGE_SIZE][2][4];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700185 ram_addr_t region_offset[TARGET_PAGE_SIZE][2][4];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800186} subpage_t;
187
188#ifdef _WIN32
189static void map_exec(void *addr, long size)
190{
191 DWORD old_protect;
192 VirtualProtect(addr, size,
193 PAGE_EXECUTE_READWRITE, &old_protect);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200194
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800195}
196#else
197static void map_exec(void *addr, long size)
198{
199 unsigned long start, end, page_size;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200200
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800201 page_size = getpagesize();
202 start = (unsigned long)addr;
203 start &= ~(page_size - 1);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200204
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800205 end = (unsigned long)addr + size;
206 end += page_size - 1;
207 end &= ~(page_size - 1);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200208
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800209 mprotect((void *)start, end - start,
210 PROT_READ | PROT_WRITE | PROT_EXEC);
211}
212#endif
213
214static void page_init(void)
215{
216 /* NOTE: we can always suppose that qemu_host_page_size >=
217 TARGET_PAGE_SIZE */
218#ifdef _WIN32
219 {
220 SYSTEM_INFO system_info;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800221
222 GetSystemInfo(&system_info);
223 qemu_real_host_page_size = system_info.dwPageSize;
224 }
225#else
226 qemu_real_host_page_size = getpagesize();
227#endif
228 if (qemu_host_page_size == 0)
229 qemu_host_page_size = qemu_real_host_page_size;
230 if (qemu_host_page_size < TARGET_PAGE_SIZE)
231 qemu_host_page_size = TARGET_PAGE_SIZE;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800232 qemu_host_page_mask = ~(qemu_host_page_size - 1);
233 l1_phys_map = qemu_vmalloc(L1_SIZE * sizeof(void *));
234 memset(l1_phys_map, 0, L1_SIZE * sizeof(void *));
235
236#if !defined(_WIN32) && defined(CONFIG_USER_ONLY)
237 {
238 long long startaddr, endaddr;
239 FILE *f;
240 int n;
241
242 mmap_lock();
243 last_brk = (unsigned long)sbrk(0);
244 f = fopen("/proc/self/maps", "r");
245 if (f) {
246 do {
247 n = fscanf (f, "%llx-%llx %*[^\n]\n", &startaddr, &endaddr);
248 if (n == 2) {
249 startaddr = MIN(startaddr,
250 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
251 endaddr = MIN(endaddr,
252 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
253 page_set_flags(startaddr & TARGET_PAGE_MASK,
254 TARGET_PAGE_ALIGN(endaddr),
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800255 PAGE_RESERVED);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800256 }
257 } while (!feof(f));
258 fclose(f);
259 }
260 mmap_unlock();
261 }
262#endif
263}
264
265static inline PageDesc **page_l1_map(target_ulong index)
266{
267#if TARGET_LONG_BITS > 32
268 /* Host memory outside guest VM. For 32-bit targets we have already
269 excluded high addresses. */
270 if (index > ((target_ulong)L2_SIZE * L1_SIZE))
271 return NULL;
272#endif
273 return &l1_map[index >> L2_BITS];
274}
275
276static inline PageDesc *page_find_alloc(target_ulong index)
277{
278 PageDesc **lp, *p;
279 lp = page_l1_map(index);
280 if (!lp)
281 return NULL;
282
283 p = *lp;
284 if (!p) {
285 /* allocate if not found */
286#if defined(CONFIG_USER_ONLY)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800287 size_t len = sizeof(PageDesc) * L2_SIZE;
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100288 /* Don't use g_malloc because it may recurse. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700289 p = mmap(NULL, len, PROT_READ | PROT_WRITE,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800290 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
291 *lp = p;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700292 if (h2g_valid(p)) {
293 unsigned long addr = h2g(p);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800294 page_set_flags(addr & TARGET_PAGE_MASK,
295 TARGET_PAGE_ALIGN(addr + len),
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800296 PAGE_RESERVED);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800297 }
298#else
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100299 p = g_malloc0(sizeof(PageDesc) * L2_SIZE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800300 *lp = p;
301#endif
302 }
303 return p + (index & (L2_SIZE - 1));
304}
305
306static inline PageDesc *page_find(target_ulong index)
307{
308 PageDesc **lp, *p;
309 lp = page_l1_map(index);
310 if (!lp)
311 return NULL;
312
313 p = *lp;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700314 if (!p) {
315 return NULL;
316 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800317 return p + (index & (L2_SIZE - 1));
318}
319
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100320static PhysPageDesc *phys_page_find_alloc(hwaddr index, int alloc)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800321{
322 void **lp, **p;
323 PhysPageDesc *pd;
324
325 p = (void **)l1_phys_map;
326#if TARGET_PHYS_ADDR_SPACE_BITS > 32
327
328#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
329#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
330#endif
331 lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1));
332 p = *lp;
333 if (!p) {
334 /* allocate if not found */
335 if (!alloc)
336 return NULL;
337 p = qemu_vmalloc(sizeof(void *) * L1_SIZE);
338 memset(p, 0, sizeof(void *) * L1_SIZE);
339 *lp = p;
340 }
341#endif
342 lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
343 pd = *lp;
344 if (!pd) {
345 int i;
346 /* allocate if not found */
347 if (!alloc)
348 return NULL;
349 pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
350 *lp = pd;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700351 for (i = 0; i < L2_SIZE; i++) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800352 pd[i].phys_offset = IO_MEM_UNASSIGNED;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700353 pd[i].region_offset = (index + i) << TARGET_PAGE_BITS;
354 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800355 }
356 return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
357}
358
David 'Digit' Turner3dc53fc2014-01-17 01:23:40 +0100359PhysPageDesc *phys_page_find(hwaddr index)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800360{
361 return phys_page_find_alloc(index, 0);
362}
363
364#if !defined(CONFIG_USER_ONLY)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800365#define mmap_lock() do { } while(0)
366#define mmap_unlock() do { } while(0)
367#endif
368
369#define DEFAULT_CODE_GEN_BUFFER_SIZE (32 * 1024 * 1024)
370
371#if defined(CONFIG_USER_ONLY)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700372/* Currently it is not recommended to allocate big chunks of data in
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800373 user mode. It will change when a dedicated libc will be used */
374#define USE_STATIC_CODE_GEN_BUFFER
375#endif
376
377#ifdef USE_STATIC_CODE_GEN_BUFFER
378static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE];
379#endif
380
381static void code_gen_alloc(unsigned long tb_size)
382{
383#ifdef USE_STATIC_CODE_GEN_BUFFER
384 code_gen_buffer = static_code_gen_buffer;
385 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
386 map_exec(code_gen_buffer, code_gen_buffer_size);
387#else
388 code_gen_buffer_size = tb_size;
389 if (code_gen_buffer_size == 0) {
390#if defined(CONFIG_USER_ONLY)
391 /* in user mode, phys_ram_size is not meaningful */
392 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
393#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700394 /* XXX: needs adjustments */
395 code_gen_buffer_size = (unsigned long)(ram_size / 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800396#endif
397 }
398 if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE)
399 code_gen_buffer_size = MIN_CODE_GEN_BUFFER_SIZE;
400 /* The code gen buffer location may have constraints depending on
401 the host cpu and OS */
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200402#if defined(__linux__)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800403 {
404 int flags;
405 void *start = NULL;
406
407 flags = MAP_PRIVATE | MAP_ANONYMOUS;
408#if defined(__x86_64__)
409 flags |= MAP_32BIT;
410 /* Cannot map more than that */
411 if (code_gen_buffer_size > (800 * 1024 * 1024))
412 code_gen_buffer_size = (800 * 1024 * 1024);
413#elif defined(__sparc_v9__)
414 // Map the buffer below 2G, so we can use direct calls and branches
415 flags |= MAP_FIXED;
416 start = (void *) 0x60000000UL;
417 if (code_gen_buffer_size > (512 * 1024 * 1024))
418 code_gen_buffer_size = (512 * 1024 * 1024);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700419#elif defined(__arm__)
420 /* Map the buffer below 32M, so we can use direct calls and branches */
421 flags |= MAP_FIXED;
422 start = (void *) 0x01000000UL;
423 if (code_gen_buffer_size > 16 * 1024 * 1024)
424 code_gen_buffer_size = 16 * 1024 * 1024;
David 'Digit' Turner36411062010-12-22 17:34:53 +0100425#elif defined(__s390x__)
426 /* Map the buffer so that we can use direct calls and branches. */
427 /* We have a +- 4GB range on the branches; leave some slop. */
428 if (code_gen_buffer_size > (3ul * 1024 * 1024 * 1024)) {
429 code_gen_buffer_size = 3ul * 1024 * 1024 * 1024;
430 }
431 start = (void *)0x90000000UL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800432#endif
433 code_gen_buffer = mmap(start, code_gen_buffer_size,
434 PROT_WRITE | PROT_READ | PROT_EXEC,
435 flags, -1, 0);
436 if (code_gen_buffer == MAP_FAILED) {
437 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
438 exit(1);
439 }
440 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200441#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \
442 || defined(__DragonFly__) || defined(__OpenBSD__)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700443 {
444 int flags;
445 void *addr = NULL;
446 flags = MAP_PRIVATE | MAP_ANONYMOUS;
447#if defined(__x86_64__)
448 /* FreeBSD doesn't have MAP_32BIT, use MAP_FIXED and assume
449 * 0x40000000 is free */
450 flags |= MAP_FIXED;
451 addr = (void *)0x40000000;
452 /* Cannot map more than that */
453 if (code_gen_buffer_size > (800 * 1024 * 1024))
454 code_gen_buffer_size = (800 * 1024 * 1024);
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200455#elif defined(__sparc_v9__)
456 // Map the buffer below 2G, so we can use direct calls and branches
457 flags |= MAP_FIXED;
458 addr = (void *) 0x60000000UL;
459 if (code_gen_buffer_size > (512 * 1024 * 1024)) {
460 code_gen_buffer_size = (512 * 1024 * 1024);
461 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700462#endif
463 code_gen_buffer = mmap(addr, code_gen_buffer_size,
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200464 PROT_WRITE | PROT_READ | PROT_EXEC,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700465 flags, -1, 0);
466 if (code_gen_buffer == MAP_FAILED) {
467 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
468 exit(1);
469 }
470 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800471#else
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100472 code_gen_buffer = g_malloc(code_gen_buffer_size);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800473 map_exec(code_gen_buffer, code_gen_buffer_size);
474#endif
475#endif /* !USE_STATIC_CODE_GEN_BUFFER */
476 map_exec(code_gen_prologue, sizeof(code_gen_prologue));
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800477 code_gen_buffer_max_size = code_gen_buffer_size -
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800478 code_gen_max_block_size();
479 code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100480 tbs = g_malloc(code_gen_max_blocks * sizeof(TranslationBlock));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800481}
482
483/* Must be called before using the QEMU cpus. 'tb_size' is the size
484 (in bytes) allocated to the translation buffer. Zero means default
485 size. */
486void cpu_exec_init_all(unsigned long tb_size)
487{
488 cpu_gen_init();
489 code_gen_alloc(tb_size);
490 code_gen_ptr = code_gen_buffer;
491 page_init();
492#if !defined(CONFIG_USER_ONLY)
493 io_mem_init();
494#endif
David 'Digit' Turnerf1d9bf12011-05-11 18:19:41 +0200495#if !defined(CONFIG_USER_ONLY) || !defined(CONFIG_USE_GUEST_BASE)
496 /* There's no guest base to take into account, so go ahead and
497 initialize the prologue now. */
498 tcg_prologue_init(&tcg_ctx);
499#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800500}
501
502#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
503
504#define CPU_COMMON_SAVE_VERSION 1
505
506static void cpu_common_save(QEMUFile *f, void *opaque)
507{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100508 CPUOldState *env = opaque;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800509
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700510 cpu_synchronize_state(env, 0);
511
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800512 qemu_put_be32s(f, &env->halted);
513 qemu_put_be32s(f, &env->interrupt_request);
514}
515
516static int cpu_common_load(QEMUFile *f, void *opaque, int version_id)
517{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100518 CPUOldState *env = opaque;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800519
520 if (version_id != CPU_COMMON_SAVE_VERSION)
521 return -EINVAL;
522
523 qemu_get_be32s(f, &env->halted);
524 qemu_get_be32s(f, &env->interrupt_request);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700525 /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
526 version_id is increased. */
527 env->interrupt_request &= ~0x01;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800528 tlb_flush(env, 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700529 cpu_synchronize_state(env, 1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800530
531 return 0;
532}
533#endif
534
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100535CPUArchState *qemu_get_cpu(int cpu)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700536{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100537 CPUArchState *env = first_cpu;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700538
539 while (env) {
540 if (env->cpu_index == cpu)
541 break;
542 env = env->next_cpu;
543 }
544
545 return env;
546}
547
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100548void cpu_exec_init(CPUArchState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800549{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100550 CPUArchState **penv;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800551 int cpu_index;
552
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700553#if defined(CONFIG_USER_ONLY)
554 cpu_list_lock();
555#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800556 env->next_cpu = NULL;
557 penv = &first_cpu;
558 cpu_index = 0;
559 while (*penv != NULL) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700560 penv = &(*penv)->next_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800561 cpu_index++;
562 }
563 env->cpu_index = cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700564 env->numa_node = 0;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700565 QTAILQ_INIT(&env->breakpoints);
566 QTAILQ_INIT(&env->watchpoints);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800567 *penv = env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700568#if defined(CONFIG_USER_ONLY)
569 cpu_list_unlock();
570#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800571#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
572 register_savevm("cpu_common", cpu_index, CPU_COMMON_SAVE_VERSION,
573 cpu_common_save, cpu_common_load, env);
574 register_savevm("cpu", cpu_index, CPU_SAVE_VERSION,
575 cpu_save, cpu_load, env);
576#endif
577}
578
579static inline void invalidate_page_bitmap(PageDesc *p)
580{
581 if (p->code_bitmap) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100582 g_free(p->code_bitmap);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800583 p->code_bitmap = NULL;
584 }
585 p->code_write_count = 0;
586}
587
588/* set to NULL all the 'first_tb' fields in all PageDescs */
589static void page_flush_tb(void)
590{
591 int i, j;
592 PageDesc *p;
593
594 for(i = 0; i < L1_SIZE; i++) {
595 p = l1_map[i];
596 if (p) {
597 for(j = 0; j < L2_SIZE; j++) {
598 p->first_tb = NULL;
599 invalidate_page_bitmap(p);
600 p++;
601 }
602 }
603 }
604}
605
606/* flush all the translation blocks */
607/* XXX: tb_flush is currently not thread safe */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100608void tb_flush(CPUArchState *env1)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800609{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100610 CPUArchState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800611#if defined(DEBUG_FLUSH)
612 printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
613 (unsigned long)(code_gen_ptr - code_gen_buffer),
614 nb_tbs, nb_tbs > 0 ?
615 ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
616#endif
617 if ((unsigned long)(code_gen_ptr - code_gen_buffer) > code_gen_buffer_size)
618 cpu_abort(env1, "Internal error: code buffer overflow\n");
619
620 nb_tbs = 0;
621
622 for(env = first_cpu; env != NULL; env = env->next_cpu) {
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800623#ifdef CONFIG_MEMCHECK
624 int tb_to_clean;
625 for (tb_to_clean = 0; tb_to_clean < TB_JMP_CACHE_SIZE; tb_to_clean++) {
626 if (env->tb_jmp_cache[tb_to_clean] != NULL &&
627 env->tb_jmp_cache[tb_to_clean]->tpc2gpc != NULL) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100628 g_free(env->tb_jmp_cache[tb_to_clean]->tpc2gpc);
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800629 env->tb_jmp_cache[tb_to_clean]->tpc2gpc = NULL;
630 env->tb_jmp_cache[tb_to_clean]->tpc2gpc_pairs = 0;
631 }
632 }
633#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800634 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
635 }
636
637 memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
638 page_flush_tb();
639
640 code_gen_ptr = code_gen_buffer;
641 /* XXX: flush processor icache at this point if cache flush is
642 expensive */
643 tb_flush_count++;
644}
645
646#ifdef DEBUG_TB_CHECK
647
648static void tb_invalidate_check(target_ulong address)
649{
650 TranslationBlock *tb;
651 int i;
652 address &= TARGET_PAGE_MASK;
653 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
654 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
655 if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
656 address >= tb->pc + tb->size)) {
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700657 printf("ERROR invalidate: address=" TARGET_FMT_lx
658 " PC=%08lx size=%04x\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800659 address, (long)tb->pc, tb->size);
660 }
661 }
662 }
663}
664
665/* verify that all the pages have correct rights for code */
666static void tb_page_check(void)
667{
668 TranslationBlock *tb;
669 int i, flags1, flags2;
670
671 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
672 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
673 flags1 = page_get_flags(tb->pc);
674 flags2 = page_get_flags(tb->pc + tb->size - 1);
675 if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
676 printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
677 (long)tb->pc, tb->size, flags1, flags2);
678 }
679 }
680 }
681}
682
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800683#endif
684
685/* invalidate one TB */
686static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb,
687 int next_offset)
688{
689 TranslationBlock *tb1;
690 for(;;) {
691 tb1 = *ptb;
692 if (tb1 == tb) {
693 *ptb = *(TranslationBlock **)((char *)tb1 + next_offset);
694 break;
695 }
696 ptb = (TranslationBlock **)((char *)tb1 + next_offset);
697 }
698}
699
700static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
701{
702 TranslationBlock *tb1;
703 unsigned int n1;
704
705 for(;;) {
706 tb1 = *ptb;
707 n1 = (long)tb1 & 3;
708 tb1 = (TranslationBlock *)((long)tb1 & ~3);
709 if (tb1 == tb) {
710 *ptb = tb1->page_next[n1];
711 break;
712 }
713 ptb = &tb1->page_next[n1];
714 }
715}
716
717static inline void tb_jmp_remove(TranslationBlock *tb, int n)
718{
719 TranslationBlock *tb1, **ptb;
720 unsigned int n1;
721
722 ptb = &tb->jmp_next[n];
723 tb1 = *ptb;
724 if (tb1) {
725 /* find tb(n) in circular list */
726 for(;;) {
727 tb1 = *ptb;
728 n1 = (long)tb1 & 3;
729 tb1 = (TranslationBlock *)((long)tb1 & ~3);
730 if (n1 == n && tb1 == tb)
731 break;
732 if (n1 == 2) {
733 ptb = &tb1->jmp_first;
734 } else {
735 ptb = &tb1->jmp_next[n1];
736 }
737 }
738 /* now we can suppress tb(n) from the list */
739 *ptb = tb->jmp_next[n];
740
741 tb->jmp_next[n] = NULL;
742 }
743}
744
745/* reset the jump entry 'n' of a TB so that it is not chained to
746 another TB */
747static inline void tb_reset_jump(TranslationBlock *tb, int n)
748{
749 tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
750}
751
752void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr)
753{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100754 CPUArchState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800755 PageDesc *p;
756 unsigned int h, n1;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100757 hwaddr phys_pc;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800758 TranslationBlock *tb1, *tb2;
759
760 /* remove the TB from the hash list */
761 phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
762 h = tb_phys_hash_func(phys_pc);
763 tb_remove(&tb_phys_hash[h], tb,
764 offsetof(TranslationBlock, phys_hash_next));
765
766 /* remove the TB from the page list */
767 if (tb->page_addr[0] != page_addr) {
768 p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
769 tb_page_remove(&p->first_tb, tb);
770 invalidate_page_bitmap(p);
771 }
772 if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
773 p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
774 tb_page_remove(&p->first_tb, tb);
775 invalidate_page_bitmap(p);
776 }
777
778 tb_invalidated_flag = 1;
779
780 /* remove the TB from the hash list */
781 h = tb_jmp_cache_hash_func(tb->pc);
782 for(env = first_cpu; env != NULL; env = env->next_cpu) {
783 if (env->tb_jmp_cache[h] == tb)
784 env->tb_jmp_cache[h] = NULL;
785 }
786
787 /* suppress this TB from the two jump lists */
788 tb_jmp_remove(tb, 0);
789 tb_jmp_remove(tb, 1);
790
791 /* suppress any remaining jumps to this TB */
792 tb1 = tb->jmp_first;
793 for(;;) {
794 n1 = (long)tb1 & 3;
795 if (n1 == 2)
796 break;
797 tb1 = (TranslationBlock *)((long)tb1 & ~3);
798 tb2 = tb1->jmp_next[n1];
799 tb_reset_jump(tb1, n1);
800 tb1->jmp_next[n1] = NULL;
801 tb1 = tb2;
802 }
803 tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
804
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800805#ifdef CONFIG_MEMCHECK
806 if (tb->tpc2gpc != NULL) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100807 g_free(tb->tpc2gpc);
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800808 tb->tpc2gpc = NULL;
809 tb->tpc2gpc_pairs = 0;
810 }
811#endif // CONFIG_MEMCHECK
812
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800813 tb_phys_invalidate_count++;
814}
815
816static inline void set_bits(uint8_t *tab, int start, int len)
817{
818 int end, mask, end1;
819
820 end = start + len;
821 tab += start >> 3;
822 mask = 0xff << (start & 7);
823 if ((start & ~7) == (end & ~7)) {
824 if (start < end) {
825 mask &= ~(0xff << (end & 7));
826 *tab |= mask;
827 }
828 } else {
829 *tab++ |= mask;
830 start = (start + 8) & ~7;
831 end1 = end & ~7;
832 while (start < end1) {
833 *tab++ = 0xff;
834 start += 8;
835 }
836 if (start < end) {
837 mask = ~(0xff << (end & 7));
838 *tab |= mask;
839 }
840 }
841}
842
843static void build_page_bitmap(PageDesc *p)
844{
845 int n, tb_start, tb_end;
846 TranslationBlock *tb;
847
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100848 p->code_bitmap = g_malloc0(TARGET_PAGE_SIZE / 8);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800849
850 tb = p->first_tb;
851 while (tb != NULL) {
852 n = (long)tb & 3;
853 tb = (TranslationBlock *)((long)tb & ~3);
854 /* NOTE: this is subtle as a TB may span two physical pages */
855 if (n == 0) {
856 /* NOTE: tb_end may be after the end of the page, but
857 it is not a problem */
858 tb_start = tb->pc & ~TARGET_PAGE_MASK;
859 tb_end = tb_start + tb->size;
860 if (tb_end > TARGET_PAGE_SIZE)
861 tb_end = TARGET_PAGE_SIZE;
862 } else {
863 tb_start = 0;
864 tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
865 }
866 set_bits(p->code_bitmap, tb_start, tb_end - tb_start);
867 tb = tb->page_next[n];
868 }
869}
870
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100871TranslationBlock *tb_gen_code(CPUArchState *env,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800872 target_ulong pc, target_ulong cs_base,
873 int flags, int cflags)
874{
875 TranslationBlock *tb;
876 uint8_t *tc_ptr;
877 target_ulong phys_pc, phys_page2, virt_page2;
878 int code_gen_size;
879
880 phys_pc = get_phys_addr_code(env, pc);
881 tb = tb_alloc(pc);
882 if (!tb) {
883 /* flush must be done */
884 tb_flush(env);
885 /* cannot fail at this point */
886 tb = tb_alloc(pc);
887 /* Don't forget to invalidate previous TB info. */
888 tb_invalidated_flag = 1;
889 }
890 tc_ptr = code_gen_ptr;
891 tb->tc_ptr = tc_ptr;
892 tb->cs_base = cs_base;
893 tb->flags = flags;
894 tb->cflags = cflags;
895#ifdef CONFIG_TRACE
896 tb->bb_rec = NULL;
897 tb->prev_time = 0;
898#endif
899 cpu_gen_code(env, tb, &code_gen_size);
900 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
901
902 /* check next page if needed */
903 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
904 phys_page2 = -1;
905 if ((pc & TARGET_PAGE_MASK) != virt_page2) {
906 phys_page2 = get_phys_addr_code(env, virt_page2);
907 }
908 tb_link_phys(tb, phys_pc, phys_page2);
909 return tb;
910}
911
912/* invalidate all TBs which intersect with the target physical page
913 starting in range [start;end[. NOTE: start and end must refer to
914 the same physical page. 'is_cpu_write_access' should be true if called
915 from a real cpu write access: the virtual CPU will exit the current
916 TB if code is modified inside this TB. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100917void tb_invalidate_phys_page_range(hwaddr start, hwaddr end,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800918 int is_cpu_write_access)
919{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700920 TranslationBlock *tb, *tb_next, *saved_tb;
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100921 CPUArchState *env = cpu_single_env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800922 target_ulong tb_start, tb_end;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700923 PageDesc *p;
924 int n;
925#ifdef TARGET_HAS_PRECISE_SMC
926 int current_tb_not_found = is_cpu_write_access;
927 TranslationBlock *current_tb = NULL;
928 int current_tb_modified = 0;
929 target_ulong current_pc = 0;
930 target_ulong current_cs_base = 0;
931 int current_flags = 0;
932#endif /* TARGET_HAS_PRECISE_SMC */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800933
934 p = page_find(start >> TARGET_PAGE_BITS);
935 if (!p)
936 return;
937 if (!p->code_bitmap &&
938 ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
939 is_cpu_write_access) {
940 /* build code bitmap */
941 build_page_bitmap(p);
942 }
943
944 /* we remove all the TBs in the range [start, end[ */
945 /* XXX: see if in some cases it could be faster to invalidate all the code */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800946 tb = p->first_tb;
947 while (tb != NULL) {
948 n = (long)tb & 3;
949 tb = (TranslationBlock *)((long)tb & ~3);
950 tb_next = tb->page_next[n];
951 /* NOTE: this is subtle as a TB may span two physical pages */
952 if (n == 0) {
953 /* NOTE: tb_end may be after the end of the page, but
954 it is not a problem */
955 tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
956 tb_end = tb_start + tb->size;
957 } else {
958 tb_start = tb->page_addr[1];
959 tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
960 }
961 if (!(tb_end <= start || tb_start >= end)) {
962#ifdef TARGET_HAS_PRECISE_SMC
963 if (current_tb_not_found) {
964 current_tb_not_found = 0;
965 current_tb = NULL;
966 if (env->mem_io_pc) {
967 /* now we have a real cpu fault */
968 current_tb = tb_find_pc(env->mem_io_pc);
969 }
970 }
971 if (current_tb == tb &&
972 (current_tb->cflags & CF_COUNT_MASK) != 1) {
973 /* If we are modifying the current TB, we must stop
974 its execution. We could be more precise by checking
975 that the modification is after the current PC, but it
976 would require a specialized function to partially
977 restore the CPU state */
978
979 current_tb_modified = 1;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200980 cpu_restore_state(current_tb, env, env->mem_io_pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700981 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
982 &current_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800983 }
984#endif /* TARGET_HAS_PRECISE_SMC */
985 /* we need to do that to handle the case where a signal
986 occurs while doing tb_phys_invalidate() */
987 saved_tb = NULL;
988 if (env) {
989 saved_tb = env->current_tb;
990 env->current_tb = NULL;
991 }
992 tb_phys_invalidate(tb, -1);
993 if (env) {
994 env->current_tb = saved_tb;
995 if (env->interrupt_request && env->current_tb)
996 cpu_interrupt(env, env->interrupt_request);
997 }
998 }
999 tb = tb_next;
1000 }
1001#if !defined(CONFIG_USER_ONLY)
1002 /* if no code remaining, no need to continue to use slow writes */
1003 if (!p->first_tb) {
1004 invalidate_page_bitmap(p);
1005 if (is_cpu_write_access) {
1006 tlb_unprotect_code_phys(env, start, env->mem_io_vaddr);
1007 }
1008 }
1009#endif
1010#ifdef TARGET_HAS_PRECISE_SMC
1011 if (current_tb_modified) {
1012 /* we generate a block containing just the instruction
1013 modifying the memory. It will ensure that it cannot modify
1014 itself */
1015 env->current_tb = NULL;
1016 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1017 cpu_resume_from_signal(env, NULL);
1018 }
1019#endif
1020}
1021
1022/* len must be <= 8 and start must be a multiple of len */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001023static inline void tb_invalidate_phys_page_fast(hwaddr start, int len)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001024{
1025 PageDesc *p;
1026 int offset, b;
1027#if 0
1028 if (1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001029 qemu_log("modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
1030 cpu_single_env->mem_io_vaddr, len,
1031 cpu_single_env->eip,
1032 cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001033 }
1034#endif
1035 p = page_find(start >> TARGET_PAGE_BITS);
1036 if (!p)
1037 return;
1038 if (p->code_bitmap) {
1039 offset = start & ~TARGET_PAGE_MASK;
1040 b = p->code_bitmap[offset >> 3] >> (offset & 7);
1041 if (b & ((1 << len) - 1))
1042 goto do_invalidate;
1043 } else {
1044 do_invalidate:
1045 tb_invalidate_phys_page_range(start, start + len, 1);
1046 }
1047}
1048
1049#if !defined(CONFIG_SOFTMMU)
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001050static void tb_invalidate_phys_page(hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001051 unsigned long pc, void *puc)
1052{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001053 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001054 PageDesc *p;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001055 int n;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001056#ifdef TARGET_HAS_PRECISE_SMC
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001057 TranslationBlock *current_tb = NULL;
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001058 CPUArchState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001059 int current_tb_modified = 0;
1060 target_ulong current_pc = 0;
1061 target_ulong current_cs_base = 0;
1062 int current_flags = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001063#endif
1064
1065 addr &= TARGET_PAGE_MASK;
1066 p = page_find(addr >> TARGET_PAGE_BITS);
1067 if (!p)
1068 return;
1069 tb = p->first_tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001070#ifdef TARGET_HAS_PRECISE_SMC
1071 if (tb && pc != 0) {
1072 current_tb = tb_find_pc(pc);
1073 }
1074#endif
1075 while (tb != NULL) {
1076 n = (long)tb & 3;
1077 tb = (TranslationBlock *)((long)tb & ~3);
1078#ifdef TARGET_HAS_PRECISE_SMC
1079 if (current_tb == tb &&
1080 (current_tb->cflags & CF_COUNT_MASK) != 1) {
1081 /* If we are modifying the current TB, we must stop
1082 its execution. We could be more precise by checking
1083 that the modification is after the current PC, but it
1084 would require a specialized function to partially
1085 restore the CPU state */
1086
1087 current_tb_modified = 1;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02001088 cpu_restore_state(current_tb, env, pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001089 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
1090 &current_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001091 }
1092#endif /* TARGET_HAS_PRECISE_SMC */
1093 tb_phys_invalidate(tb, addr);
1094 tb = tb->page_next[n];
1095 }
1096 p->first_tb = NULL;
1097#ifdef TARGET_HAS_PRECISE_SMC
1098 if (current_tb_modified) {
1099 /* we generate a block containing just the instruction
1100 modifying the memory. It will ensure that it cannot modify
1101 itself */
1102 env->current_tb = NULL;
1103 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1104 cpu_resume_from_signal(env, puc);
1105 }
1106#endif
1107}
1108#endif
1109
1110/* add the tb in the target page and protect it if necessary */
1111static inline void tb_alloc_page(TranslationBlock *tb,
1112 unsigned int n, target_ulong page_addr)
1113{
1114 PageDesc *p;
1115 TranslationBlock *last_first_tb;
1116
1117 tb->page_addr[n] = page_addr;
1118 p = page_find_alloc(page_addr >> TARGET_PAGE_BITS);
1119 tb->page_next[n] = p->first_tb;
1120 last_first_tb = p->first_tb;
1121 p->first_tb = (TranslationBlock *)((long)tb | n);
1122 invalidate_page_bitmap(p);
1123
1124#if defined(TARGET_HAS_SMC) || 1
1125
1126#if defined(CONFIG_USER_ONLY)
1127 if (p->flags & PAGE_WRITE) {
1128 target_ulong addr;
1129 PageDesc *p2;
1130 int prot;
1131
1132 /* force the host page as non writable (writes will have a
1133 page fault + mprotect overhead) */
1134 page_addr &= qemu_host_page_mask;
1135 prot = 0;
1136 for(addr = page_addr; addr < page_addr + qemu_host_page_size;
1137 addr += TARGET_PAGE_SIZE) {
1138
1139 p2 = page_find (addr >> TARGET_PAGE_BITS);
1140 if (!p2)
1141 continue;
1142 prot |= p2->flags;
1143 p2->flags &= ~PAGE_WRITE;
1144 page_get_flags(addr);
1145 }
1146 mprotect(g2h(page_addr), qemu_host_page_size,
1147 (prot & PAGE_BITS) & ~PAGE_WRITE);
1148#ifdef DEBUG_TB_INVALIDATE
1149 printf("protecting code page: 0x" TARGET_FMT_lx "\n",
1150 page_addr);
1151#endif
1152 }
1153#else
1154 /* if some code is already present, then the pages are already
1155 protected. So we handle the case where only the first TB is
1156 allocated in a physical page */
1157 if (!last_first_tb) {
1158 tlb_protect_code(page_addr);
1159 }
1160#endif
1161
1162#endif /* TARGET_HAS_SMC */
1163}
1164
1165/* Allocate a new translation block. Flush the translation buffer if
1166 too many translation blocks or too much generated code. */
1167TranslationBlock *tb_alloc(target_ulong pc)
1168{
1169 TranslationBlock *tb;
1170
1171 if (nb_tbs >= code_gen_max_blocks ||
1172 (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
1173 return NULL;
1174 tb = &tbs[nb_tbs++];
1175 tb->pc = pc;
1176 tb->cflags = 0;
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -08001177#ifdef CONFIG_MEMCHECK
1178 tb->tpc2gpc = NULL;
1179 tb->tpc2gpc_pairs = 0;
1180#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001181 return tb;
1182}
1183
1184void tb_free(TranslationBlock *tb)
1185{
1186 /* In practice this is mostly used for single use temporary TB
1187 Ignore the hard cases and just back up if this TB happens to
1188 be the last one generated. */
1189 if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) {
1190 code_gen_ptr = tb->tc_ptr;
1191 nb_tbs--;
1192 }
1193}
1194
1195/* add a new TB and link it to the physical page tables. phys_page2 is
1196 (-1) to indicate that only one page contains the TB. */
1197void tb_link_phys(TranslationBlock *tb,
1198 target_ulong phys_pc, target_ulong phys_page2)
1199{
1200 unsigned int h;
1201 TranslationBlock **ptb;
1202
1203 /* Grab the mmap lock to stop another thread invalidating this TB
1204 before we are done. */
1205 mmap_lock();
1206 /* add in the physical hash table */
1207 h = tb_phys_hash_func(phys_pc);
1208 ptb = &tb_phys_hash[h];
1209 tb->phys_hash_next = *ptb;
1210 *ptb = tb;
1211
1212 /* add in the page list */
1213 tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK);
1214 if (phys_page2 != -1)
1215 tb_alloc_page(tb, 1, phys_page2);
1216 else
1217 tb->page_addr[1] = -1;
1218
1219 tb->jmp_first = (TranslationBlock *)((long)tb | 2);
1220 tb->jmp_next[0] = NULL;
1221 tb->jmp_next[1] = NULL;
1222
1223 /* init original jump addresses */
1224 if (tb->tb_next_offset[0] != 0xffff)
1225 tb_reset_jump(tb, 0);
1226 if (tb->tb_next_offset[1] != 0xffff)
1227 tb_reset_jump(tb, 1);
1228
1229#ifdef DEBUG_TB_CHECK
1230 tb_page_check();
1231#endif
1232 mmap_unlock();
1233}
1234
1235/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
1236 tb[1].tc_ptr. Return NULL if not found */
1237TranslationBlock *tb_find_pc(unsigned long tc_ptr)
1238{
1239 int m_min, m_max, m;
1240 unsigned long v;
1241 TranslationBlock *tb;
1242
1243 if (nb_tbs <= 0)
1244 return NULL;
1245 if (tc_ptr < (unsigned long)code_gen_buffer ||
1246 tc_ptr >= (unsigned long)code_gen_ptr)
1247 return NULL;
1248 /* binary search (cf Knuth) */
1249 m_min = 0;
1250 m_max = nb_tbs - 1;
1251 while (m_min <= m_max) {
1252 m = (m_min + m_max) >> 1;
1253 tb = &tbs[m];
1254 v = (unsigned long)tb->tc_ptr;
1255 if (v == tc_ptr)
1256 return tb;
1257 else if (tc_ptr < v) {
1258 m_max = m - 1;
1259 } else {
1260 m_min = m + 1;
1261 }
1262 }
1263 return &tbs[m_max];
1264}
1265
1266static void tb_reset_jump_recursive(TranslationBlock *tb);
1267
1268static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
1269{
1270 TranslationBlock *tb1, *tb_next, **ptb;
1271 unsigned int n1;
1272
1273 tb1 = tb->jmp_next[n];
1274 if (tb1 != NULL) {
1275 /* find head of list */
1276 for(;;) {
1277 n1 = (long)tb1 & 3;
1278 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1279 if (n1 == 2)
1280 break;
1281 tb1 = tb1->jmp_next[n1];
1282 }
1283 /* we are now sure now that tb jumps to tb1 */
1284 tb_next = tb1;
1285
1286 /* remove tb from the jmp_first list */
1287 ptb = &tb_next->jmp_first;
1288 for(;;) {
1289 tb1 = *ptb;
1290 n1 = (long)tb1 & 3;
1291 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1292 if (n1 == n && tb1 == tb)
1293 break;
1294 ptb = &tb1->jmp_next[n1];
1295 }
1296 *ptb = tb->jmp_next[n];
1297 tb->jmp_next[n] = NULL;
1298
1299 /* suppress the jump to next tb in generated code */
1300 tb_reset_jump(tb, n);
1301
1302 /* suppress jumps in the tb on which we could have jumped */
1303 tb_reset_jump_recursive(tb_next);
1304 }
1305}
1306
1307static void tb_reset_jump_recursive(TranslationBlock *tb)
1308{
1309 tb_reset_jump_recursive2(tb, 0);
1310 tb_reset_jump_recursive2(tb, 1);
1311}
1312
1313#if defined(TARGET_HAS_ICE)
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001314static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001315{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001316 hwaddr addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001317 target_ulong pd;
1318 ram_addr_t ram_addr;
1319 PhysPageDesc *p;
1320
1321 addr = cpu_get_phys_page_debug(env, pc);
1322 p = phys_page_find(addr >> TARGET_PAGE_BITS);
1323 if (!p) {
1324 pd = IO_MEM_UNASSIGNED;
1325 } else {
1326 pd = p->phys_offset;
1327 }
1328 ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
1329 tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
1330}
1331#endif
1332
1333/* Add a watchpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001334int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001335 int flags, CPUWatchpoint **watchpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001336{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001337 target_ulong len_mask = ~(len - 1);
1338 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001339
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001340 /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
1341 if ((len != 1 && len != 2 && len != 4 && len != 8) || (addr & ~len_mask)) {
1342 fprintf(stderr, "qemu: tried to set invalid watchpoint at "
1343 TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
1344 return -EINVAL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001345 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001346 wp = g_malloc(sizeof(*wp));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001347
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001348 wp->vaddr = addr;
1349 wp->len_mask = len_mask;
1350 wp->flags = flags;
1351
1352 /* keep all GDB-injected watchpoints in front */
1353 if (flags & BP_GDB)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001354 QTAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001355 else
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001356 QTAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001357
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001358 tlb_flush_page(env, addr);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001359
1360 if (watchpoint)
1361 *watchpoint = wp;
1362 return 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001363}
1364
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001365/* Remove a specific watchpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001366int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, target_ulong len,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001367 int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001368{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001369 target_ulong len_mask = ~(len - 1);
1370 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001371
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001372 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001373 if (addr == wp->vaddr && len_mask == wp->len_mask
1374 && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
1375 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001376 return 0;
1377 }
1378 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001379 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001380}
1381
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001382/* Remove a specific watchpoint by reference. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001383void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001384{
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001385 QTAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001386
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001387 tlb_flush_page(env, watchpoint->vaddr);
1388
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001389 g_free(watchpoint);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001390}
1391
1392/* Remove all matching watchpoints. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001393void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001394{
1395 CPUWatchpoint *wp, *next;
1396
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001397 QTAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001398 if (wp->flags & mask)
1399 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001400 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001401}
1402
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001403/* Add a breakpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001404int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001405 CPUBreakpoint **breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001406{
1407#if defined(TARGET_HAS_ICE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001408 CPUBreakpoint *bp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001409
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001410 bp = g_malloc(sizeof(*bp));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001411
1412 bp->pc = pc;
1413 bp->flags = flags;
1414
1415 /* keep all GDB-injected breakpoints in front */
1416 if (flags & BP_GDB)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001417 QTAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001418 else
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001419 QTAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001420
1421 breakpoint_invalidate(env, pc);
1422
1423 if (breakpoint)
1424 *breakpoint = bp;
1425 return 0;
1426#else
1427 return -ENOSYS;
1428#endif
1429}
1430
1431/* Remove a specific breakpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001432int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001433{
1434#if defined(TARGET_HAS_ICE)
1435 CPUBreakpoint *bp;
1436
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001437 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001438 if (bp->pc == pc && bp->flags == flags) {
1439 cpu_breakpoint_remove_by_ref(env, bp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001440 return 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001441 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001442 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001443 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001444#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001445 return -ENOSYS;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001446#endif
1447}
1448
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001449/* Remove a specific breakpoint by reference. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001450void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001451{
1452#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001453 QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001454
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001455 breakpoint_invalidate(env, breakpoint->pc);
1456
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001457 g_free(breakpoint);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001458#endif
1459}
1460
1461/* Remove all matching breakpoints. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001462void cpu_breakpoint_remove_all(CPUArchState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001463{
1464#if defined(TARGET_HAS_ICE)
1465 CPUBreakpoint *bp, *next;
1466
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001467 QTAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001468 if (bp->flags & mask)
1469 cpu_breakpoint_remove_by_ref(env, bp);
1470 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001471#endif
1472}
1473
1474/* enable or disable single step mode. EXCP_DEBUG is returned by the
1475 CPU loop after each instruction */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001476void cpu_single_step(CPUOldState *env, int enabled)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001477{
1478#if defined(TARGET_HAS_ICE)
1479 if (env->singlestep_enabled != enabled) {
1480 env->singlestep_enabled = enabled;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001481 if (kvm_enabled())
1482 kvm_update_guest_debug(env, 0);
1483 else {
1484 /* must flush all the translated code to avoid inconsistencies */
1485 /* XXX: only flush what is necessary */
1486 tb_flush(env);
1487 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001488 }
1489#endif
1490}
1491
1492/* enable or disable low levels log */
1493void cpu_set_log(int log_flags)
1494{
1495 loglevel = log_flags;
1496 if (loglevel && !logfile) {
1497 logfile = fopen(logfilename, log_append ? "a" : "w");
1498 if (!logfile) {
1499 perror(logfilename);
Iliyan Malchev4a2c9dd2012-04-02 08:20:56 -07001500 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001501 }
1502#if !defined(CONFIG_SOFTMMU)
1503 /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1504 {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001505 static char logfile_buf[4096];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001506 setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1507 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001508#elif !defined(_WIN32)
1509 /* Win32 doesn't support line-buffering and requires size >= 2 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001510 setvbuf(logfile, NULL, _IOLBF, 0);
1511#endif
1512 log_append = 1;
1513 }
1514 if (!loglevel && logfile) {
1515 fclose(logfile);
1516 logfile = NULL;
1517 }
1518}
1519
1520void cpu_set_log_filename(const char *filename)
1521{
1522 logfilename = strdup(filename);
1523 if (logfile) {
1524 fclose(logfile);
1525 logfile = NULL;
1526 }
1527 cpu_set_log(loglevel);
1528}
1529
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001530static void cpu_unlink_tb(CPUOldState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001531{
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001532 /* FIXME: TB unchaining isn't SMP safe. For now just ignore the
1533 problem and hope the cpu will stop of its own accord. For userspace
1534 emulation this often isn't actually as bad as it sounds. Often
1535 signals are used primarily to interrupt blocking syscalls. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001536 TranslationBlock *tb;
1537 static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
1538
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001539 spin_lock(&interrupt_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001540 tb = env->current_tb;
1541 /* if the cpu is currently executing code, we must unlink it and
1542 all the potentially executing TB */
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001543 if (tb) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001544 env->current_tb = NULL;
1545 tb_reset_jump_recursive(tb);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001546 }
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001547 spin_unlock(&interrupt_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001548}
1549
1550/* mask must never be zero, except for A20 change call */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001551void cpu_interrupt(CPUOldState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001552{
1553 int old_mask;
1554
1555 old_mask = env->interrupt_request;
1556 env->interrupt_request |= mask;
1557
1558#ifndef CONFIG_USER_ONLY
1559 /*
1560 * If called from iothread context, wake the target cpu in
1561 * case its halted.
1562 */
1563 if (!qemu_cpu_self(env)) {
1564 qemu_cpu_kick(env);
1565 return;
1566 }
1567#endif
1568
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001569 if (use_icount) {
1570 env->icount_decr.u16.high = 0xffff;
1571#ifndef CONFIG_USER_ONLY
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001572 if (!can_do_io(env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001573 && (mask & ~old_mask) != 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001574 cpu_abort(env, "Raised interrupt while not in I/O function");
1575 }
1576#endif
1577 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001578 cpu_unlink_tb(env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001579 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001580}
1581
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001582void cpu_reset_interrupt(CPUOldState *env, int mask)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001583{
1584 env->interrupt_request &= ~mask;
1585}
1586
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001587void cpu_exit(CPUOldState *env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001588{
1589 env->exit_request = 1;
1590 cpu_unlink_tb(env);
1591}
1592
1593const CPULogItem cpu_log_items[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001594 { CPU_LOG_TB_OUT_ASM, "out_asm",
1595 "show generated host assembly code for each compiled TB" },
1596 { CPU_LOG_TB_IN_ASM, "in_asm",
1597 "show target assembly code for each compiled TB" },
1598 { CPU_LOG_TB_OP, "op",
1599 "show micro ops for each compiled TB" },
1600 { CPU_LOG_TB_OP_OPT, "op_opt",
1601 "show micro ops "
1602#ifdef TARGET_I386
1603 "before eflags optimization and "
1604#endif
1605 "after liveness analysis" },
1606 { CPU_LOG_INT, "int",
1607 "show interrupts/exceptions in short format" },
1608 { CPU_LOG_EXEC, "exec",
1609 "show trace before each executed TB (lots of logs)" },
1610 { CPU_LOG_TB_CPU, "cpu",
1611 "show CPU state before block translation" },
1612#ifdef TARGET_I386
1613 { CPU_LOG_PCALL, "pcall",
1614 "show protected mode far calls/returns/exceptions" },
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001615 { CPU_LOG_RESET, "cpu_reset",
1616 "show CPU state before CPU resets" },
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001617#endif
1618#ifdef DEBUG_IOPORT
1619 { CPU_LOG_IOPORT, "ioport",
1620 "show all i/o ports accesses" },
1621#endif
1622 { 0, NULL, NULL },
1623};
1624
1625static int cmp1(const char *s1, int n, const char *s2)
1626{
1627 if (strlen(s2) != n)
1628 return 0;
1629 return memcmp(s1, s2, n) == 0;
1630}
1631
1632/* takes a comma separated list of log masks. Return 0 if error. */
1633int cpu_str_to_log_mask(const char *str)
1634{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001635 const CPULogItem *item;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001636 int mask;
1637 const char *p, *p1;
1638
1639 p = str;
1640 mask = 0;
1641 for(;;) {
1642 p1 = strchr(p, ',');
1643 if (!p1)
1644 p1 = p + strlen(p);
1645 if(cmp1(p,p1-p,"all")) {
1646 for(item = cpu_log_items; item->mask != 0; item++) {
1647 mask |= item->mask;
1648 }
1649 } else {
1650 for(item = cpu_log_items; item->mask != 0; item++) {
1651 if (cmp1(p, p1 - p, item->name))
1652 goto found;
1653 }
1654 return 0;
1655 }
1656 found:
1657 mask |= item->mask;
1658 if (*p1 != ',')
1659 break;
1660 p = p1 + 1;
1661 }
1662 return mask;
1663}
1664
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001665void cpu_abort(CPUOldState *env, const char *fmt, ...)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001666{
1667 va_list ap;
1668 va_list ap2;
1669
1670 va_start(ap, fmt);
1671 va_copy(ap2, ap);
1672 fprintf(stderr, "qemu: fatal: ");
1673 vfprintf(stderr, fmt, ap);
1674 fprintf(stderr, "\n");
1675#ifdef TARGET_I386
1676 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1677#else
1678 cpu_dump_state(env, stderr, fprintf, 0);
1679#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001680 if (qemu_log_enabled()) {
1681 qemu_log("qemu: fatal: ");
1682 qemu_log_vprintf(fmt, ap2);
1683 qemu_log("\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001684#ifdef TARGET_I386
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001685 log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001686#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001687 log_cpu_state(env, 0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001688#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001689 qemu_log_flush();
1690 qemu_log_close();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001691 }
1692 va_end(ap2);
1693 va_end(ap);
David 'Digit' Turner36411062010-12-22 17:34:53 +01001694#if defined(CONFIG_USER_ONLY)
1695 {
1696 struct sigaction act;
1697 sigfillset(&act.sa_mask);
1698 act.sa_handler = SIG_DFL;
1699 sigaction(SIGABRT, &act, NULL);
1700 }
1701#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001702 abort();
1703}
1704
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001705CPUArchState *cpu_copy(CPUOldState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001706{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001707 CPUArchState *new_env = cpu_init(env->cpu_model_str);
1708 CPUArchState *next_cpu = new_env->next_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001709 int cpu_index = new_env->cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001710#if defined(TARGET_HAS_ICE)
1711 CPUBreakpoint *bp;
1712 CPUWatchpoint *wp;
1713#endif
1714
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001715 memcpy(new_env, env, sizeof(CPUOldState));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001716
1717 /* Preserve chaining and index. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001718 new_env->next_cpu = next_cpu;
1719 new_env->cpu_index = cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001720
1721 /* Clone all break/watchpoints.
1722 Note: Once we support ptrace with hw-debug register access, make sure
1723 BP_CPU break/watchpoints are handled correctly on clone. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001724 QTAILQ_INIT(&env->breakpoints);
1725 QTAILQ_INIT(&env->watchpoints);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001726#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001727 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001728 cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
1729 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001730 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001731 cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
1732 wp->flags, NULL);
1733 }
1734#endif
1735
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001736 return new_env;
1737}
1738
1739#if !defined(CONFIG_USER_ONLY)
1740
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001741/* Note: start and end must be within the same ram block. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001742void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
1743 int dirty_flags)
1744{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001745 CPUOldState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001746 unsigned long length, start1;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001747 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001748
1749 start &= TARGET_PAGE_MASK;
1750 end = TARGET_PAGE_ALIGN(end);
1751
1752 length = end - start;
1753 if (length == 0)
1754 return;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001755 cpu_physical_memory_mask_dirty_range(start, length, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001756
1757 /* we modify the TLB cache so that the dirty bit will be set again
1758 when accessing the range */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001759 start1 = (unsigned long)qemu_safe_ram_ptr(start);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001760 /* Chek that we don't span multiple blocks - this breaks the
1761 address comparisons below. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001762 if ((unsigned long)qemu_safe_ram_ptr(end - 1) - start1
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001763 != (end - 1) - start) {
1764 abort();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001765 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001766
1767 for(env = first_cpu; env != NULL; env = env->next_cpu) {
1768 int mmu_idx;
1769 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1770 for(i = 0; i < CPU_TLB_SIZE; i++)
1771 tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
1772 start1, length);
1773 }
1774 }
1775}
1776
1777int cpu_physical_memory_set_dirty_tracking(int enable)
1778{
1779 in_migration = enable;
1780 if (kvm_enabled()) {
1781 return kvm_set_migration_log(enable);
1782 }
1783 return 0;
1784}
1785
1786int cpu_physical_memory_get_dirty_tracking(void)
1787{
1788 return in_migration;
1789}
1790
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001791int cpu_physical_sync_dirty_bitmap(hwaddr start_addr,
1792 hwaddr end_addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001793{
1794 int ret = 0;
1795
1796 if (kvm_enabled())
1797 ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
1798 return ret;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001799}
1800
1801static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1802{
1803 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001804 void *p;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001805
1806 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001807 p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
1808 + tlb_entry->addend);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001809 ram_addr = qemu_ram_addr_from_host_nofail(p);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001810 if (!cpu_physical_memory_is_dirty(ram_addr)) {
1811 tlb_entry->addr_write |= TLB_NOTDIRTY;
1812 }
1813 }
1814}
1815
1816/* update the TLB according to the current state of the dirty bits */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001817void cpu_tlb_update_dirty(CPUArchState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001818{
1819 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001820 int mmu_idx;
1821 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1822 for(i = 0; i < CPU_TLB_SIZE; i++)
1823 tlb_update_dirty(&env->tlb_table[mmu_idx][i]);
1824 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001825}
1826
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001827
1828#else
1829
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001830void tlb_flush(CPUArchState *env, int flush_global)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001831{
1832}
1833
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001834void tlb_flush_page(CPUArchState *env, target_ulong addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001835{
1836}
1837
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001838int tlb_set_page_exec(CPUArchState *env, target_ulong vaddr,
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001839 hwaddr paddr, int prot,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001840 int mmu_idx, int is_softmmu)
1841{
1842 return 0;
1843}
1844
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001845/*
1846 * Walks guest process memory "regions" one by one
1847 * and calls callback function 'fn' for each region.
1848 */
1849int walk_memory_regions(void *priv,
1850 int (*fn)(void *, unsigned long, unsigned long, unsigned long))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001851{
1852 unsigned long start, end;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001853 PageDesc *p = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001854 int i, j, prot, prot1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001855 int rc = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001856
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001857 start = end = -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001858 prot = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001859
1860 for (i = 0; i <= L1_SIZE; i++) {
1861 p = (i < L1_SIZE) ? l1_map[i] : NULL;
1862 for (j = 0; j < L2_SIZE; j++) {
1863 prot1 = (p == NULL) ? 0 : p[j].flags;
1864 /*
1865 * "region" is one continuous chunk of memory
1866 * that has same protection flags set.
1867 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001868 if (prot1 != prot) {
1869 end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
1870 if (start != -1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001871 rc = (*fn)(priv, start, end, prot);
1872 /* callback can stop iteration by returning != 0 */
1873 if (rc != 0)
1874 return (rc);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001875 }
1876 if (prot1 != 0)
1877 start = end;
1878 else
1879 start = -1;
1880 prot = prot1;
1881 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001882 if (p == NULL)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001883 break;
1884 }
1885 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001886 return (rc);
1887}
1888
1889static int dump_region(void *priv, unsigned long start,
1890 unsigned long end, unsigned long prot)
1891{
1892 FILE *f = (FILE *)priv;
1893
1894 (void) fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
1895 start, end, end - start,
1896 ((prot & PAGE_READ) ? 'r' : '-'),
1897 ((prot & PAGE_WRITE) ? 'w' : '-'),
1898 ((prot & PAGE_EXEC) ? 'x' : '-'));
1899
1900 return (0);
1901}
1902
1903/* dump memory mappings */
1904void page_dump(FILE *f)
1905{
1906 (void) fprintf(f, "%-8s %-8s %-8s %s\n",
1907 "start", "end", "size", "prot");
1908 walk_memory_regions(f, dump_region);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001909}
1910
1911int page_get_flags(target_ulong address)
1912{
1913 PageDesc *p;
1914
1915 p = page_find(address >> TARGET_PAGE_BITS);
1916 if (!p)
1917 return 0;
1918 return p->flags;
1919}
1920
David 'Digit' Turner36411062010-12-22 17:34:53 +01001921/* Modify the flags of a page and invalidate the code if necessary.
1922 The flag PAGE_WRITE_ORG is positioned automatically depending
1923 on PAGE_WRITE. The mmap_lock should already be held. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001924void page_set_flags(target_ulong start, target_ulong end, int flags)
1925{
1926 PageDesc *p;
1927 target_ulong addr;
1928
1929 /* mmap_lock should already be held. */
1930 start = start & TARGET_PAGE_MASK;
1931 end = TARGET_PAGE_ALIGN(end);
1932 if (flags & PAGE_WRITE)
1933 flags |= PAGE_WRITE_ORG;
1934 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1935 p = page_find_alloc(addr >> TARGET_PAGE_BITS);
1936 /* We may be called for host regions that are outside guest
1937 address space. */
1938 if (!p)
1939 return;
1940 /* if the write protection is set, then we invalidate the code
1941 inside */
1942 if (!(p->flags & PAGE_WRITE) &&
1943 (flags & PAGE_WRITE) &&
1944 p->first_tb) {
1945 tb_invalidate_phys_page(addr, 0, NULL);
1946 }
1947 p->flags = flags;
1948 }
1949}
1950
1951int page_check_range(target_ulong start, target_ulong len, int flags)
1952{
1953 PageDesc *p;
1954 target_ulong end;
1955 target_ulong addr;
1956
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001957 if (start + len < start)
1958 /* we've wrapped around */
1959 return -1;
1960
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001961 end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
1962 start = start & TARGET_PAGE_MASK;
1963
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001964 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1965 p = page_find(addr >> TARGET_PAGE_BITS);
1966 if( !p )
1967 return -1;
1968 if( !(p->flags & PAGE_VALID) )
1969 return -1;
1970
1971 if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
1972 return -1;
1973 if (flags & PAGE_WRITE) {
1974 if (!(p->flags & PAGE_WRITE_ORG))
1975 return -1;
1976 /* unprotect the page if it was put read-only because it
1977 contains translated code */
1978 if (!(p->flags & PAGE_WRITE)) {
1979 if (!page_unprotect(addr, 0, NULL))
1980 return -1;
1981 }
1982 return 0;
1983 }
1984 }
1985 return 0;
1986}
1987
1988/* called from signal handler: invalidate the code and unprotect the
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001989 page. Return TRUE if the fault was successfully handled. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001990int page_unprotect(target_ulong address, unsigned long pc, void *puc)
1991{
1992 unsigned int page_index, prot, pindex;
1993 PageDesc *p, *p1;
1994 target_ulong host_start, host_end, addr;
1995
1996 /* Technically this isn't safe inside a signal handler. However we
1997 know this only ever happens in a synchronous SEGV handler, so in
1998 practice it seems to be ok. */
1999 mmap_lock();
2000
2001 host_start = address & qemu_host_page_mask;
2002 page_index = host_start >> TARGET_PAGE_BITS;
2003 p1 = page_find(page_index);
2004 if (!p1) {
2005 mmap_unlock();
2006 return 0;
2007 }
2008 host_end = host_start + qemu_host_page_size;
2009 p = p1;
2010 prot = 0;
2011 for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
2012 prot |= p->flags;
2013 p++;
2014 }
2015 /* if the page was really writable, then we change its
2016 protection back to writable */
2017 if (prot & PAGE_WRITE_ORG) {
2018 pindex = (address - host_start) >> TARGET_PAGE_BITS;
2019 if (!(p1[pindex].flags & PAGE_WRITE)) {
2020 mprotect((void *)g2h(host_start), qemu_host_page_size,
2021 (prot & PAGE_BITS) | PAGE_WRITE);
2022 p1[pindex].flags |= PAGE_WRITE;
2023 /* and since the content will be modified, we must invalidate
2024 the corresponding translated code. */
2025 tb_invalidate_phys_page(address, pc, puc);
2026#ifdef DEBUG_TB_CHECK
2027 tb_invalidate_check(address);
2028#endif
2029 mmap_unlock();
2030 return 1;
2031 }
2032 }
2033 mmap_unlock();
2034 return 0;
2035}
2036
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002037static inline void tlb_set_dirty(CPUOldState *env,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002038 unsigned long addr, target_ulong vaddr)
2039{
2040}
2041#endif /* defined(CONFIG_USER_ONLY) */
2042
2043#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002044
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002045static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002046 ram_addr_t memory, ram_addr_t region_offset);
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002047static void *subpage_init (hwaddr base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002048 ram_addr_t orig_memory, ram_addr_t region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002049#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
2050 need_subpage) \
2051 do { \
2052 if (addr > start_addr) \
2053 start_addr2 = 0; \
2054 else { \
2055 start_addr2 = start_addr & ~TARGET_PAGE_MASK; \
2056 if (start_addr2 > 0) \
2057 need_subpage = 1; \
2058 } \
2059 \
2060 if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE) \
2061 end_addr2 = TARGET_PAGE_SIZE - 1; \
2062 else { \
2063 end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
2064 if (end_addr2 < TARGET_PAGE_SIZE - 1) \
2065 need_subpage = 1; \
2066 } \
2067 } while (0)
2068
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002069/* register physical memory.
2070 For RAM, 'size' must be a multiple of the target page size.
2071 If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002072 io memory page. The address used when calling the IO function is
2073 the offset from the start of the region, plus region_offset. Both
2074 start_addr and region_offset are rounded down to a page boundary
2075 before calculating this offset. This should not be a problem unless
2076 the low bits of start_addr and region_offset differ. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002077void cpu_register_physical_memory_log(hwaddr start_addr,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002078 ram_addr_t size,
2079 ram_addr_t phys_offset,
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002080 ram_addr_t region_offset,
2081 bool log_dirty)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002082{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002083 hwaddr addr, end_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002084 PhysPageDesc *p;
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002085 CPUOldState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002086 ram_addr_t orig_size = size;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002087 subpage_t *subpage;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002088
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002089 if (kvm_enabled())
2090 kvm_set_phys_mem(start_addr, size, phys_offset);
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002091#ifdef CONFIG_HAX
2092 if (hax_enabled())
2093 hax_set_phys_mem(start_addr, size, phys_offset);
2094#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002095
2096 if (phys_offset == IO_MEM_UNASSIGNED) {
2097 region_offset = start_addr;
2098 }
2099 region_offset &= TARGET_PAGE_MASK;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002100 size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002101 end_addr = start_addr + (hwaddr)size;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002102
2103 addr = start_addr;
2104 do {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002105 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2106 if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
2107 ram_addr_t orig_memory = p->phys_offset;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002108 hwaddr start_addr2, end_addr2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002109 int need_subpage = 0;
2110
2111 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2112 need_subpage);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002113 if (need_subpage) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002114 if (!(orig_memory & IO_MEM_SUBPAGE)) {
2115 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002116 &p->phys_offset, orig_memory,
2117 p->region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002118 } else {
2119 subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
2120 >> IO_MEM_SHIFT];
2121 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002122 subpage_register(subpage, start_addr2, end_addr2, phys_offset,
2123 region_offset);
2124 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002125 } else {
2126 p->phys_offset = phys_offset;
2127 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2128 (phys_offset & IO_MEM_ROMD))
2129 phys_offset += TARGET_PAGE_SIZE;
2130 }
2131 } else {
2132 p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2133 p->phys_offset = phys_offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002134 p->region_offset = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002135 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002136 (phys_offset & IO_MEM_ROMD)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002137 phys_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002138 } else {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002139 hwaddr start_addr2, end_addr2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002140 int need_subpage = 0;
2141
2142 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2143 end_addr2, need_subpage);
2144
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002145 if (need_subpage) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002146 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002147 &p->phys_offset, IO_MEM_UNASSIGNED,
2148 addr & TARGET_PAGE_MASK);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002149 subpage_register(subpage, start_addr2, end_addr2,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002150 phys_offset, region_offset);
2151 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002152 }
2153 }
2154 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002155 region_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002156 addr += TARGET_PAGE_SIZE;
2157 } while (addr != end_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002158
2159 /* since each CPU stores ram addresses in its TLB cache, we must
2160 reset the modified entries */
2161 /* XXX: slow ! */
2162 for(env = first_cpu; env != NULL; env = env->next_cpu) {
2163 tlb_flush(env, 1);
2164 }
2165}
2166
2167/* XXX: temporary until new memory mapping API */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002168ram_addr_t cpu_get_physical_page_desc(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002169{
2170 PhysPageDesc *p;
2171
2172 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2173 if (!p)
2174 return IO_MEM_UNASSIGNED;
2175 return p->phys_offset;
2176}
2177
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002178void qemu_register_coalesced_mmio(hwaddr addr, ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002179{
2180 if (kvm_enabled())
2181 kvm_coalesce_mmio_region(addr, size);
2182}
2183
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002184void qemu_unregister_coalesced_mmio(hwaddr addr, ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002185{
2186 if (kvm_enabled())
2187 kvm_uncoalesce_mmio_region(addr, size);
2188}
2189
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002190static ram_addr_t find_ram_offset(ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002191{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002192 RAMBlock *block, *next_block;
2193 ram_addr_t offset = 0, mingap = ULONG_MAX;
2194
2195 if (QLIST_EMPTY(&ram_list.blocks))
2196 return 0;
2197
2198 QLIST_FOREACH(block, &ram_list.blocks, next) {
2199 ram_addr_t end, next = ULONG_MAX;
2200
2201 end = block->offset + block->length;
2202
2203 QLIST_FOREACH(next_block, &ram_list.blocks, next) {
2204 if (next_block->offset >= end) {
2205 next = MIN(next, next_block->offset);
2206 }
2207 }
2208 if (next - end >= size && next - end < mingap) {
2209 offset = end;
2210 mingap = next - end;
2211 }
2212 }
2213 return offset;
2214}
2215
2216static ram_addr_t last_ram_offset(void)
2217{
2218 RAMBlock *block;
2219 ram_addr_t last = 0;
2220
2221 QLIST_FOREACH(block, &ram_list.blocks, next)
2222 last = MAX(last, block->offset + block->length);
2223
2224 return last;
2225}
2226
2227ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
2228 ram_addr_t size, void *host)
2229{
2230 RAMBlock *new_block, *block;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002231
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002232 size = TARGET_PAGE_ALIGN(size);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002233 new_block = g_malloc0(sizeof(*new_block));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002234
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002235#if 0
2236 if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
2237 char *id = dev->parent_bus->info->get_dev_path(dev);
2238 if (id) {
2239 snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002240 g_free(id);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002241 }
2242 }
2243#endif
2244 pstrcat(new_block->idstr, sizeof(new_block->idstr), name);
2245
2246 QLIST_FOREACH(block, &ram_list.blocks, next) {
2247 if (!strcmp(block->idstr, new_block->idstr)) {
2248 fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n",
2249 new_block->idstr);
2250 abort();
2251 }
2252 }
2253
2254 if (host) {
2255 new_block->host = host;
2256 new_block->flags |= RAM_PREALLOC_MASK;
2257 } else {
2258 if (mem_path) {
2259#if 0 && defined (__linux__) && !defined(TARGET_S390X)
2260 new_block->host = file_ram_alloc(new_block, size, mem_path);
2261 if (!new_block->host) {
2262 new_block->host = qemu_vmalloc(size);
2263 qemu_madvise(new_block->host, size, QEMU_MADV_MERGEABLE);
2264 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002265#else
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002266 fprintf(stderr, "-mem-path option unsupported\n");
2267 exit(1);
2268#endif
2269 } else {
2270#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2271 /* XXX S390 KVM requires the topmost vma of the RAM to be < 256GB */
2272 new_block->host = mmap((void*)0x1000000, size,
2273 PROT_EXEC|PROT_READ|PROT_WRITE,
2274 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
2275#else
2276 new_block->host = qemu_vmalloc(size);
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002277
2278#ifdef CONFIG_HAX
2279 /*
2280 * In HAX, qemu allocates the virtual address, and HAX kernel
2281 * module populates the region with physical memory. Currently
2282 * we don’t populate guest memory on demand, thus we should
2283 * make sure that sufficient amount of memory is available in
2284 * advance.
2285 */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002286 if (hax_enabled()) {
2287 int ret = hax_populate_ram(
2288 (uint64_t)(uintptr_t)new_block->host,
2289 size);
2290 if (ret < 0) {
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002291 fprintf(stderr, "Hax failed to populate ram\n");
2292 exit(-1);
2293 }
2294 }
2295#endif
2296
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002297#endif
2298#ifdef MADV_MERGEABLE
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002299 madvise(new_block->host, size, MADV_MERGEABLE);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002300#endif
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002301 }
2302 }
2303
2304 new_block->offset = find_ram_offset(size);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002305 new_block->length = size;
2306
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002307 QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002308
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002309 ram_list.phys_dirty = g_realloc(ram_list.phys_dirty,
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002310 last_ram_offset() >> TARGET_PAGE_BITS);
2311 memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002312 0xff, size >> TARGET_PAGE_BITS);
2313
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002314 if (kvm_enabled())
2315 kvm_setup_guest_memory(new_block->host, size);
2316
2317 return new_block->offset;
2318}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002319
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002320ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
2321{
2322 return qemu_ram_alloc_from_ptr(dev, name, size, NULL);
2323}
2324
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002325void qemu_ram_free(ram_addr_t addr)
2326{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002327 RAMBlock *block;
2328
2329 QLIST_FOREACH(block, &ram_list.blocks, next) {
2330 if (addr == block->offset) {
2331 QLIST_REMOVE(block, next);
2332 if (block->flags & RAM_PREALLOC_MASK) {
2333 ;
2334 } else if (mem_path) {
2335#if defined (__linux__) && !defined(TARGET_S390X)
2336 if (block->fd) {
2337 munmap(block->host, block->length);
2338 close(block->fd);
2339 } else {
2340 qemu_vfree(block->host);
2341 }
2342#else
2343 abort();
2344#endif
2345 } else {
2346#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2347 munmap(block->host, block->length);
2348#else
2349 qemu_vfree(block->host);
2350#endif
2351 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002352 g_free(block);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002353 return;
2354 }
2355 }
2356
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002357}
2358
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002359#ifndef _WIN32
2360void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
2361{
2362#ifndef CONFIG_ANDROID
2363 RAMBlock *block;
2364 ram_addr_t offset;
2365 int flags;
2366 void *area, *vaddr;
2367
2368 QLIST_FOREACH(block, &ram_list.blocks, next) {
2369 offset = addr - block->offset;
2370 if (offset < block->length) {
2371 vaddr = block->host + offset;
2372 if (block->flags & RAM_PREALLOC_MASK) {
2373 ;
2374 } else {
2375 flags = MAP_FIXED;
2376 munmap(vaddr, length);
2377 if (mem_path) {
2378#if defined(__linux__) && !defined(TARGET_S390X)
2379 if (block->fd) {
2380#ifdef MAP_POPULATE
2381 flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED :
2382 MAP_PRIVATE;
2383#else
2384 flags |= MAP_PRIVATE;
2385#endif
2386 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2387 flags, block->fd, offset);
2388 } else {
2389 flags |= MAP_PRIVATE | MAP_ANONYMOUS;
2390 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2391 flags, -1, 0);
2392 }
2393#else
2394 abort();
2395#endif
2396 } else {
2397#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2398 flags |= MAP_SHARED | MAP_ANONYMOUS;
2399 area = mmap(vaddr, length, PROT_EXEC|PROT_READ|PROT_WRITE,
2400 flags, -1, 0);
2401#else
2402 flags |= MAP_PRIVATE | MAP_ANONYMOUS;
2403 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2404 flags, -1, 0);
2405#endif
2406 }
2407 if (area != vaddr) {
2408 fprintf(stderr, "Could not remap addr: %lx@%lx\n",
2409 length, addr);
2410 exit(1);
2411 }
2412 qemu_madvise(vaddr, length, QEMU_MADV_MERGEABLE);
2413 }
2414 return;
2415 }
2416 }
2417#endif /* !CONFIG_ANDROID */
2418}
2419#endif /* !_WIN32 */
2420
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002421/* Return a host pointer to ram allocated with qemu_ram_alloc.
2422 With the exception of the softmmu code in this file, this should
2423 only be used for local memory (e.g. video ram) that the device owns,
2424 and knows it isn't going to access beyond the end of the block.
2425
2426 It should not be used for general purpose DMA.
2427 Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
2428 */
2429void *qemu_get_ram_ptr(ram_addr_t addr)
2430{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002431 RAMBlock *block;
2432
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002433 QLIST_FOREACH(block, &ram_list.blocks, next) {
2434 if (addr - block->offset < block->length) {
2435 /* Move this entry to to start of the list. */
2436 if (block != QLIST_FIRST(&ram_list.blocks)) {
2437 QLIST_REMOVE(block, next);
2438 QLIST_INSERT_HEAD(&ram_list.blocks, block, next);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002439 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002440 return block->host + (addr - block->offset);
2441 }
2442 }
2443
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002444 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2445 abort();
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002446
2447 return NULL;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002448 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002449
2450/* Return a host pointer to ram allocated with qemu_ram_alloc.
2451 * Same as qemu_get_ram_ptr but avoid reordering ramblocks.
2452 */
2453void *qemu_safe_ram_ptr(ram_addr_t addr)
2454{
2455 RAMBlock *block;
2456
2457 QLIST_FOREACH(block, &ram_list.blocks, next) {
2458 if (addr - block->offset < block->length) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002459 return block->host + (addr - block->offset);
2460}
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002461 }
2462
2463 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2464 abort();
2465
2466 return NULL;
2467}
2468
2469int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
2470{
2471 RAMBlock *block;
2472 uint8_t *host = ptr;
2473
2474 QLIST_FOREACH(block, &ram_list.blocks, next) {
2475 if (host - block->host < block->length) {
2476 *ram_addr = block->offset + (host - block->host);
2477 return 0;
2478 }
2479 }
2480 return -1;
2481}
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002482
2483/* Some of the softmmu routines need to translate from a host pointer
2484 (typically a TLB entry) back to a ram offset. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002485ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002486{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002487 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002488
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002489 if (qemu_ram_addr_from_host(ptr, &ram_addr)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002490 fprintf(stderr, "Bad ram pointer %p\n", ptr);
2491 abort();
2492 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002493 return ram_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002494}
2495
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002496static uint32_t unassigned_mem_readb(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002497{
2498#ifdef DEBUG_UNASSIGNED
2499 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2500#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002501#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002502 do_unassigned_access(addr, 0, 0, 0, 1);
2503#endif
2504 return 0;
2505}
2506
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002507static uint32_t unassigned_mem_readw(void *opaque, hwaddr addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002508{
2509#ifdef DEBUG_UNASSIGNED
2510 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2511#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002512#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002513 do_unassigned_access(addr, 0, 0, 0, 2);
2514#endif
2515 return 0;
2516}
2517
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002518static uint32_t unassigned_mem_readl(void *opaque, hwaddr addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002519{
2520#ifdef DEBUG_UNASSIGNED
2521 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2522#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002523#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002524 do_unassigned_access(addr, 0, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002525#endif
2526 return 0;
2527}
2528
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002529static void unassigned_mem_writeb(void *opaque, hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002530{
2531#ifdef DEBUG_UNASSIGNED
2532 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2533#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002534#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002535 do_unassigned_access(addr, 1, 0, 0, 1);
2536#endif
2537}
2538
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002539static void unassigned_mem_writew(void *opaque, hwaddr addr, uint32_t val)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002540{
2541#ifdef DEBUG_UNASSIGNED
2542 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2543#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002544#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002545 do_unassigned_access(addr, 1, 0, 0, 2);
2546#endif
2547}
2548
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002549static void unassigned_mem_writel(void *opaque, hwaddr addr, uint32_t val)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002550{
2551#ifdef DEBUG_UNASSIGNED
2552 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2553#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002554#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002555 do_unassigned_access(addr, 1, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002556#endif
2557}
2558
David 'Digit' Turner36411062010-12-22 17:34:53 +01002559static CPUReadMemoryFunc * const unassigned_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002560 unassigned_mem_readb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002561 unassigned_mem_readw,
2562 unassigned_mem_readl,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002563};
2564
David 'Digit' Turner36411062010-12-22 17:34:53 +01002565static CPUWriteMemoryFunc * const unassigned_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002566 unassigned_mem_writeb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002567 unassigned_mem_writew,
2568 unassigned_mem_writel,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002569};
2570
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002571static void notdirty_mem_writeb(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002572 uint32_t val)
2573{
2574 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002575 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002576 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2577#if !defined(CONFIG_USER_ONLY)
2578 tb_invalidate_phys_page_fast(ram_addr, 1);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002579 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002580#endif
2581 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002582 stb_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002583 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002584 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002585 /* we remove the notdirty callback only if the code has been
2586 flushed */
2587 if (dirty_flags == 0xff)
2588 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2589}
2590
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002591static void notdirty_mem_writew(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002592 uint32_t val)
2593{
2594 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002595 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002596 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2597#if !defined(CONFIG_USER_ONLY)
2598 tb_invalidate_phys_page_fast(ram_addr, 2);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002599 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002600#endif
2601 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002602 stw_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002603 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002604 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002605 /* we remove the notdirty callback only if the code has been
2606 flushed */
2607 if (dirty_flags == 0xff)
2608 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2609}
2610
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002611static void notdirty_mem_writel(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002612 uint32_t val)
2613{
2614 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002615 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002616 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2617#if !defined(CONFIG_USER_ONLY)
2618 tb_invalidate_phys_page_fast(ram_addr, 4);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002619 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002620#endif
2621 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002622 stl_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002623 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002624 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002625 /* we remove the notdirty callback only if the code has been
2626 flushed */
2627 if (dirty_flags == 0xff)
2628 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2629}
2630
David 'Digit' Turner36411062010-12-22 17:34:53 +01002631static CPUReadMemoryFunc * const error_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002632 NULL, /* never used */
2633 NULL, /* never used */
2634 NULL, /* never used */
2635};
2636
David 'Digit' Turner36411062010-12-22 17:34:53 +01002637static CPUWriteMemoryFunc * const notdirty_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002638 notdirty_mem_writeb,
2639 notdirty_mem_writew,
2640 notdirty_mem_writel,
2641};
2642
2643/* Generate a debug exception if a watchpoint has been hit. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002644static void check_watchpoint(int offset, int len_mask, int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002645{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002646 CPUOldState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002647 target_ulong pc, cs_base;
2648 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002649 target_ulong vaddr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002650 CPUWatchpoint *wp;
2651 int cpu_flags;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002652
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002653 if (env->watchpoint_hit) {
2654 /* We re-entered the check after replacing the TB. Now raise
2655 * the debug interrupt so that is will trigger after the
2656 * current instruction. */
2657 cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2658 return;
2659 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002660 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002661 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002662 if ((vaddr == (wp->vaddr & len_mask) ||
2663 (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
2664 wp->flags |= BP_WATCHPOINT_HIT;
2665 if (!env->watchpoint_hit) {
2666 env->watchpoint_hit = wp;
2667 tb = tb_find_pc(env->mem_io_pc);
2668 if (!tb) {
2669 cpu_abort(env, "check_watchpoint: could not find TB for "
2670 "pc=%p", (void *)env->mem_io_pc);
2671 }
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02002672 cpu_restore_state(tb, env, env->mem_io_pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002673 tb_phys_invalidate(tb, -1);
2674 if (wp->flags & BP_STOP_BEFORE_ACCESS) {
2675 env->exception_index = EXCP_DEBUG;
2676 } else {
2677 cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
2678 tb_gen_code(env, pc, cs_base, cpu_flags, 1);
2679 }
2680 cpu_resume_from_signal(env, NULL);
2681 }
2682 } else {
2683 wp->flags &= ~BP_WATCHPOINT_HIT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002684 }
2685 }
2686}
2687
2688/* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
2689 so these check for a hit then pass through to the normal out-of-line
2690 phys routines. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002691static uint32_t watch_mem_readb(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002692{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002693 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002694 return ldub_phys(addr);
2695}
2696
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002697static uint32_t watch_mem_readw(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002698{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002699 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002700 return lduw_phys(addr);
2701}
2702
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002703static uint32_t watch_mem_readl(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002704{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002705 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002706 return ldl_phys(addr);
2707}
2708
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002709static void watch_mem_writeb(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002710 uint32_t val)
2711{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002712 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002713 stb_phys(addr, val);
2714}
2715
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002716static void watch_mem_writew(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002717 uint32_t val)
2718{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002719 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002720 stw_phys(addr, val);
2721}
2722
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002723static void watch_mem_writel(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002724 uint32_t val)
2725{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002726 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002727 stl_phys(addr, val);
2728}
2729
David 'Digit' Turner36411062010-12-22 17:34:53 +01002730static CPUReadMemoryFunc * const watch_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002731 watch_mem_readb,
2732 watch_mem_readw,
2733 watch_mem_readl,
2734};
2735
David 'Digit' Turner36411062010-12-22 17:34:53 +01002736static CPUWriteMemoryFunc * const watch_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002737 watch_mem_writeb,
2738 watch_mem_writew,
2739 watch_mem_writel,
2740};
2741
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002742static inline uint32_t subpage_readlen (subpage_t *mmio, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002743 unsigned int len)
2744{
2745 uint32_t ret;
2746 unsigned int idx;
2747
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002748 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002749#if defined(DEBUG_SUBPAGE)
2750 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
2751 mmio, len, addr, idx);
2752#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002753 ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len],
2754 addr + mmio->region_offset[idx][0][len]);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002755
2756 return ret;
2757}
2758
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002759static inline void subpage_writelen (subpage_t *mmio, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002760 uint32_t value, unsigned int len)
2761{
2762 unsigned int idx;
2763
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002764 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002765#if defined(DEBUG_SUBPAGE)
2766 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
2767 mmio, len, addr, idx, value);
2768#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002769 (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len],
2770 addr + mmio->region_offset[idx][1][len],
2771 value);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002772}
2773
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002774static uint32_t subpage_readb (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002775{
2776#if defined(DEBUG_SUBPAGE)
2777 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2778#endif
2779
2780 return subpage_readlen(opaque, addr, 0);
2781}
2782
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002783static void subpage_writeb (void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002784 uint32_t value)
2785{
2786#if defined(DEBUG_SUBPAGE)
2787 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2788#endif
2789 subpage_writelen(opaque, addr, value, 0);
2790}
2791
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002792static uint32_t subpage_readw (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002793{
2794#if defined(DEBUG_SUBPAGE)
2795 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2796#endif
2797
2798 return subpage_readlen(opaque, addr, 1);
2799}
2800
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002801static void subpage_writew (void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002802 uint32_t value)
2803{
2804#if defined(DEBUG_SUBPAGE)
2805 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2806#endif
2807 subpage_writelen(opaque, addr, value, 1);
2808}
2809
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002810static uint32_t subpage_readl (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002811{
2812#if defined(DEBUG_SUBPAGE)
2813 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2814#endif
2815
2816 return subpage_readlen(opaque, addr, 2);
2817}
2818
2819static void subpage_writel (void *opaque,
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002820 hwaddr addr, uint32_t value)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002821{
2822#if defined(DEBUG_SUBPAGE)
2823 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2824#endif
2825 subpage_writelen(opaque, addr, value, 2);
2826}
2827
David 'Digit' Turner36411062010-12-22 17:34:53 +01002828static CPUReadMemoryFunc * const subpage_read[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002829 &subpage_readb,
2830 &subpage_readw,
2831 &subpage_readl,
2832};
2833
David 'Digit' Turner36411062010-12-22 17:34:53 +01002834static CPUWriteMemoryFunc * const subpage_write[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002835 &subpage_writeb,
2836 &subpage_writew,
2837 &subpage_writel,
2838};
2839
2840static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002841 ram_addr_t memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002842{
2843 int idx, eidx;
2844 unsigned int i;
2845
2846 if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
2847 return -1;
2848 idx = SUBPAGE_IDX(start);
2849 eidx = SUBPAGE_IDX(end);
2850#if defined(DEBUG_SUBPAGE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002851 printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002852 mmio, start, end, idx, eidx, memory);
2853#endif
2854 memory >>= IO_MEM_SHIFT;
2855 for (; idx <= eidx; idx++) {
2856 for (i = 0; i < 4; i++) {
2857 if (io_mem_read[memory][i]) {
2858 mmio->mem_read[idx][i] = &io_mem_read[memory][i];
2859 mmio->opaque[idx][0][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002860 mmio->region_offset[idx][0][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002861 }
2862 if (io_mem_write[memory][i]) {
2863 mmio->mem_write[idx][i] = &io_mem_write[memory][i];
2864 mmio->opaque[idx][1][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002865 mmio->region_offset[idx][1][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002866 }
2867 }
2868 }
2869
2870 return 0;
2871}
2872
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002873static void *subpage_init (hwaddr base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002874 ram_addr_t orig_memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002875{
2876 subpage_t *mmio;
2877 int subpage_memory;
2878
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002879 mmio = g_malloc0(sizeof(subpage_t));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002880
2881 mmio->base = base;
2882 subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002883#if defined(DEBUG_SUBPAGE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002884 printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
2885 mmio, base, TARGET_PAGE_SIZE, subpage_memory);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002886#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002887 *phys = subpage_memory | IO_MEM_SUBPAGE;
2888 subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
2889 region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002890
2891 return mmio;
2892}
2893
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002894static int get_free_io_mem_idx(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002895{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002896 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002897
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002898 for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
2899 if (!io_mem_used[i]) {
2900 io_mem_used[i] = 1;
2901 return i;
2902 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002903 fprintf(stderr, "RAN out out io_mem_idx, max %d !\n", IO_MEM_NB_ENTRIES);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002904 return -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002905}
2906
2907/* mem_read and mem_write are arrays of functions containing the
2908 function to access byte (index 0), word (index 1) and dword (index
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002909 2). Functions can be omitted with a NULL function pointer.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002910 If io_index is non zero, the corresponding io zone is
2911 modified. If it is zero, a new io zone is allocated. The return
2912 value can be used with cpu_register_physical_memory(). (-1) is
2913 returned if error. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002914static int cpu_register_io_memory_fixed(int io_index,
David 'Digit' Turner36411062010-12-22 17:34:53 +01002915 CPUReadMemoryFunc * const *mem_read,
2916 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002917 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002918{
2919 int i, subwidth = 0;
2920
2921 if (io_index <= 0) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002922 io_index = get_free_io_mem_idx();
2923 if (io_index == -1)
2924 return io_index;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002925 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002926 io_index >>= IO_MEM_SHIFT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002927 if (io_index >= IO_MEM_NB_ENTRIES)
2928 return -1;
2929 }
2930
2931 for(i = 0;i < 3; i++) {
2932 if (!mem_read[i] || !mem_write[i])
2933 subwidth = IO_MEM_SUBWIDTH;
2934 io_mem_read[io_index][i] = mem_read[i];
2935 io_mem_write[io_index][i] = mem_write[i];
2936 }
2937 io_mem_opaque[io_index] = opaque;
2938 return (io_index << IO_MEM_SHIFT) | subwidth;
2939}
2940
David 'Digit' Turner36411062010-12-22 17:34:53 +01002941int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
2942 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002943 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002944{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002945 return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002946}
2947
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002948void cpu_unregister_io_memory(int io_table_address)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002949{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002950 int i;
2951 int io_index = io_table_address >> IO_MEM_SHIFT;
2952
2953 for (i=0;i < 3; i++) {
2954 io_mem_read[io_index][i] = unassigned_mem_read[i];
2955 io_mem_write[io_index][i] = unassigned_mem_write[i];
2956 }
2957 io_mem_opaque[io_index] = NULL;
2958 io_mem_used[io_index] = 0;
2959}
2960
2961static void io_mem_init(void)
2962{
2963 int i;
2964
2965 cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read, unassigned_mem_write, NULL);
2966 cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read, unassigned_mem_write, NULL);
2967 cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read, notdirty_mem_write, NULL);
2968 for (i=0; i<5; i++)
2969 io_mem_used[i] = 1;
2970
2971 io_mem_watch = cpu_register_io_memory(watch_mem_read,
2972 watch_mem_write, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002973}
2974
2975#endif /* !defined(CONFIG_USER_ONLY) */
2976
2977/* physical memory access (slow version, mainly for debug) */
2978#if defined(CONFIG_USER_ONLY)
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002979void cpu_physical_memory_rw(hwaddr addr, void *buf,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002980 int len, int is_write)
2981{
2982 int l, flags;
2983 target_ulong page;
2984 void * p;
2985
2986 while (len > 0) {
2987 page = addr & TARGET_PAGE_MASK;
2988 l = (page + TARGET_PAGE_SIZE) - addr;
2989 if (l > len)
2990 l = len;
2991 flags = page_get_flags(page);
2992 if (!(flags & PAGE_VALID))
2993 return;
2994 if (is_write) {
2995 if (!(flags & PAGE_WRITE))
2996 return;
2997 /* XXX: this code should not depend on lock_user */
2998 if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
2999 /* FIXME - should this return an error rather than just fail? */
3000 return;
3001 memcpy(p, buf, l);
3002 unlock_user(p, addr, l);
3003 } else {
3004 if (!(flags & PAGE_READ))
3005 return;
3006 /* XXX: this code should not depend on lock_user */
3007 if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
3008 /* FIXME - should this return an error rather than just fail? */
3009 return;
3010 memcpy(buf, p, l);
3011 unlock_user(p, addr, 0);
3012 }
3013 len -= l;
3014 buf += l;
3015 addr += l;
3016 }
3017}
3018
3019#else
Pete Delaneyd09d7662013-03-28 19:53:13 -07003020
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003021static void invalidate_and_set_dirty(hwaddr addr,
3022 hwaddr length)
Pete Delaneyd09d7662013-03-28 19:53:13 -07003023{
3024 if (!cpu_physical_memory_is_dirty(addr)) {
3025 /* invalidate code */
3026 tb_invalidate_phys_page_range(addr, addr + length, 0);
3027 /* set dirty bit */
3028 cpu_physical_memory_set_dirty_flags(addr, (0xff & ~CODE_DIRTY_FLAG));
3029 }
3030}
3031
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003032void cpu_physical_memory_rw(hwaddr addr, void *buf,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003033 int len, int is_write)
3034{
3035 int l, io_index;
3036 uint8_t *ptr;
3037 uint32_t val;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003038 hwaddr page;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003039 unsigned long pd;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003040 uint8_t* buf8 = (uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003041 PhysPageDesc *p;
3042
3043 while (len > 0) {
3044 page = addr & TARGET_PAGE_MASK;
3045 l = (page + TARGET_PAGE_SIZE) - addr;
3046 if (l > len)
3047 l = len;
3048 p = phys_page_find(page >> TARGET_PAGE_BITS);
3049 if (!p) {
3050 pd = IO_MEM_UNASSIGNED;
3051 } else {
3052 pd = p->phys_offset;
3053 }
3054
3055 if (is_write) {
3056 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003057 hwaddr addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003058 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003059 if (p)
3060 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003061 /* XXX: could force cpu_single_env to NULL to avoid
3062 potential bugs */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003063 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003064 /* 32 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003065 val = ldl_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003066 io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003067 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003068 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003069 /* 16 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003070 val = lduw_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003071 io_mem_write[io_index][1](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003072 l = 2;
3073 } else {
3074 /* 8 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003075 val = ldub_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003076 io_mem_write[io_index][0](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003077 l = 1;
3078 }
3079 } else {
3080 unsigned long addr1;
3081 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3082 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003083 ptr = qemu_get_ram_ptr(addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003084 memcpy(ptr, buf8, l);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003085 invalidate_and_set_dirty(addr1, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003086 }
3087 } else {
3088 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3089 !(pd & IO_MEM_ROMD)) {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003090 hwaddr addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003091 /* I/O case */
3092 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003093 if (p)
3094 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3095 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003096 /* 32 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003097 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003098 stl_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003099 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003100 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003101 /* 16 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003102 val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003103 stw_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003104 l = 2;
3105 } else {
3106 /* 8 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003107 val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003108 stb_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003109 l = 1;
3110 }
3111 } else {
3112 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003113 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003114 (addr & ~TARGET_PAGE_MASK);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003115 memcpy(buf8, ptr, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003116 }
3117 }
3118 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003119 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003120 addr += l;
3121 }
3122}
3123
3124/* used for ROM loading : can write in RAM and ROM */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003125void cpu_physical_memory_write_rom(hwaddr addr,
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003126 const void *buf, int len)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003127{
3128 int l;
3129 uint8_t *ptr;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003130 hwaddr page;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003131 unsigned long pd;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003132 const uint8_t* buf8 = (const uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003133 PhysPageDesc *p;
3134
3135 while (len > 0) {
3136 page = addr & TARGET_PAGE_MASK;
3137 l = (page + TARGET_PAGE_SIZE) - addr;
3138 if (l > len)
3139 l = len;
3140 p = phys_page_find(page >> TARGET_PAGE_BITS);
3141 if (!p) {
3142 pd = IO_MEM_UNASSIGNED;
3143 } else {
3144 pd = p->phys_offset;
3145 }
3146
3147 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
3148 (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
3149 !(pd & IO_MEM_ROMD)) {
3150 /* do nothing */
3151 } else {
3152 unsigned long addr1;
3153 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3154 /* ROM/RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003155 ptr = qemu_get_ram_ptr(addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003156 memcpy(ptr, buf8, l);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003157 invalidate_and_set_dirty(addr1, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003158 }
3159 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003160 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003161 addr += l;
3162 }
3163}
3164
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003165typedef struct {
3166 void *buffer;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003167 hwaddr addr;
3168 hwaddr len;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003169} BounceBuffer;
3170
3171static BounceBuffer bounce;
3172
3173typedef struct MapClient {
3174 void *opaque;
3175 void (*callback)(void *opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003176 QLIST_ENTRY(MapClient) link;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003177} MapClient;
3178
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003179static QLIST_HEAD(map_client_list, MapClient) map_client_list
3180 = QLIST_HEAD_INITIALIZER(map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003181
3182void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
3183{
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01003184 MapClient *client = g_malloc(sizeof(*client));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003185
3186 client->opaque = opaque;
3187 client->callback = callback;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003188 QLIST_INSERT_HEAD(&map_client_list, client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003189 return client;
3190}
3191
3192void cpu_unregister_map_client(void *_client)
3193{
3194 MapClient *client = (MapClient *)_client;
3195
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003196 QLIST_REMOVE(client, link);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01003197 g_free(client);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003198}
3199
3200static void cpu_notify_map_clients(void)
3201{
3202 MapClient *client;
3203
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003204 while (!QLIST_EMPTY(&map_client_list)) {
3205 client = QLIST_FIRST(&map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003206 client->callback(client->opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003207 QLIST_REMOVE(client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003208 }
3209}
3210
3211/* Map a physical memory region into a host virtual address.
3212 * May map a subset of the requested range, given by and returned in *plen.
3213 * May return NULL if resources needed to perform the mapping are exhausted.
3214 * Use only for reads OR writes - not for read-modify-write operations.
3215 * Use cpu_register_map_client() to know when retrying the map operation is
3216 * likely to succeed.
3217 */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003218void *cpu_physical_memory_map(hwaddr addr,
3219 hwaddr *plen,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003220 int is_write)
3221{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003222 hwaddr len = *plen;
3223 hwaddr done = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003224 int l;
3225 uint8_t *ret = NULL;
3226 uint8_t *ptr;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003227 hwaddr page;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003228 unsigned long pd;
3229 PhysPageDesc *p;
3230 unsigned long addr1;
3231
3232 while (len > 0) {
3233 page = addr & TARGET_PAGE_MASK;
3234 l = (page + TARGET_PAGE_SIZE) - addr;
3235 if (l > len)
3236 l = len;
3237 p = phys_page_find(page >> TARGET_PAGE_BITS);
3238 if (!p) {
3239 pd = IO_MEM_UNASSIGNED;
3240 } else {
3241 pd = p->phys_offset;
3242 }
3243
3244 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3245 if (done || bounce.buffer) {
3246 break;
3247 }
3248 bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
3249 bounce.addr = addr;
3250 bounce.len = l;
3251 if (!is_write) {
3252 cpu_physical_memory_rw(addr, bounce.buffer, l, 0);
3253 }
3254 ptr = bounce.buffer;
3255 } else {
3256 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3257 ptr = qemu_get_ram_ptr(addr1);
3258 }
3259 if (!done) {
3260 ret = ptr;
3261 } else if (ret + done != ptr) {
3262 break;
3263 }
3264
3265 len -= l;
3266 addr += l;
3267 done += l;
3268 }
3269 *plen = done;
3270 return ret;
3271}
3272
3273/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
3274 * Will also mark the memory as dirty if is_write == 1. access_len gives
3275 * the amount of memory that was actually read or written by the caller.
3276 */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003277void cpu_physical_memory_unmap(void *buffer, hwaddr len,
3278 int is_write, hwaddr access_len)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003279{
3280 if (buffer != bounce.buffer) {
3281 if (is_write) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003282 ram_addr_t addr1 = qemu_ram_addr_from_host_nofail(buffer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003283 while (access_len) {
3284 unsigned l;
3285 l = TARGET_PAGE_SIZE;
3286 if (l > access_len)
3287 l = access_len;
Pete Delaneyd09d7662013-03-28 19:53:13 -07003288 invalidate_and_set_dirty(addr1, l);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003289 addr1 += l;
3290 access_len -= l;
3291 }
3292 }
3293 return;
3294 }
3295 if (is_write) {
3296 cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
3297 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003298 qemu_vfree(bounce.buffer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003299 bounce.buffer = NULL;
3300 cpu_notify_map_clients();
3301}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003302
3303/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003304uint32_t ldl_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003305{
3306 int io_index;
3307 uint8_t *ptr;
3308 uint32_t val;
3309 unsigned long pd;
3310 PhysPageDesc *p;
3311
3312 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3313 if (!p) {
3314 pd = IO_MEM_UNASSIGNED;
3315 } else {
3316 pd = p->phys_offset;
3317 }
3318
3319 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3320 !(pd & IO_MEM_ROMD)) {
3321 /* I/O case */
3322 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003323 if (p)
3324 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003325 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3326 } else {
3327 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003328 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003329 (addr & ~TARGET_PAGE_MASK);
3330 val = ldl_p(ptr);
3331 }
3332 return val;
3333}
3334
3335/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003336uint64_t ldq_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003337{
3338 int io_index;
3339 uint8_t *ptr;
3340 uint64_t val;
3341 unsigned long pd;
3342 PhysPageDesc *p;
3343
3344 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3345 if (!p) {
3346 pd = IO_MEM_UNASSIGNED;
3347 } else {
3348 pd = p->phys_offset;
3349 }
3350
3351 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3352 !(pd & IO_MEM_ROMD)) {
3353 /* I/O case */
3354 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003355 if (p)
3356 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003357#ifdef TARGET_WORDS_BIGENDIAN
3358 val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
3359 val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
3360#else
3361 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3362 val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
3363#endif
3364 } else {
3365 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003366 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003367 (addr & ~TARGET_PAGE_MASK);
3368 val = ldq_p(ptr);
3369 }
3370 return val;
3371}
3372
3373/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003374uint32_t ldub_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003375{
3376 uint8_t val;
3377 cpu_physical_memory_read(addr, &val, 1);
3378 return val;
3379}
3380
3381/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003382uint32_t lduw_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003383{
3384 uint16_t val;
3385 cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
3386 return tswap16(val);
3387}
3388
3389/* warning: addr must be aligned. The ram page is not masked as dirty
3390 and the code inside is not invalidated. It is useful if the dirty
3391 bits are used to track modified PTEs */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003392void stl_phys_notdirty(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003393{
3394 int io_index;
3395 uint8_t *ptr;
3396 unsigned long pd;
3397 PhysPageDesc *p;
3398
3399 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3400 if (!p) {
3401 pd = IO_MEM_UNASSIGNED;
3402 } else {
3403 pd = p->phys_offset;
3404 }
3405
3406 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3407 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003408 if (p)
3409 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003410 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3411 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003412 unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3413 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003414 stl_p(ptr, val);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003415
3416 if (unlikely(in_migration)) {
3417 if (!cpu_physical_memory_is_dirty(addr1)) {
3418 /* invalidate code */
3419 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3420 /* set dirty bit */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003421 cpu_physical_memory_set_dirty_flags(
3422 addr1, (0xff & ~CODE_DIRTY_FLAG));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003423 }
3424 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003425 }
3426}
3427
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003428void stq_phys_notdirty(hwaddr addr, uint64_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003429{
3430 int io_index;
3431 uint8_t *ptr;
3432 unsigned long pd;
3433 PhysPageDesc *p;
3434
3435 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3436 if (!p) {
3437 pd = IO_MEM_UNASSIGNED;
3438 } else {
3439 pd = p->phys_offset;
3440 }
3441
3442 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3443 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003444 if (p)
3445 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003446#ifdef TARGET_WORDS_BIGENDIAN
3447 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
3448 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
3449#else
3450 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3451 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
3452#endif
3453 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003454 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003455 (addr & ~TARGET_PAGE_MASK);
3456 stq_p(ptr, val);
3457 }
3458}
3459
3460/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003461void stl_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003462{
3463 int io_index;
3464 uint8_t *ptr;
3465 unsigned long pd;
3466 PhysPageDesc *p;
3467
3468 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3469 if (!p) {
3470 pd = IO_MEM_UNASSIGNED;
3471 } else {
3472 pd = p->phys_offset;
3473 }
3474
3475 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3476 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003477 if (p)
3478 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003479 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3480 } else {
3481 unsigned long addr1;
3482 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3483 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003484 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003485 stl_p(ptr, val);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003486 invalidate_and_set_dirty(addr1, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003487 }
3488}
3489
3490/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003491void stb_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003492{
3493 uint8_t v = val;
3494 cpu_physical_memory_write(addr, &v, 1);
3495}
3496
3497/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003498void stw_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003499{
3500 uint16_t v = tswap16(val);
3501 cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
3502}
3503
3504/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003505void stq_phys(hwaddr addr, uint64_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003506{
3507 val = tswap64(val);
3508 cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
3509}
3510
3511#endif
3512
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003513/* virtual memory access for debug (includes writing to ROM) */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003514int cpu_memory_rw_debug(CPUOldState *env, target_ulong addr,
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003515 void *buf, int len, int is_write)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003516{
3517 int l;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003518 hwaddr phys_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003519 target_ulong page;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003520 uint8_t* buf8 = (uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003521
3522 while (len > 0) {
3523 page = addr & TARGET_PAGE_MASK;
3524 phys_addr = cpu_get_phys_page_debug(env, page);
3525 /* if no physical page mapped, return an error */
3526 if (phys_addr == -1)
3527 return -1;
3528 l = (page + TARGET_PAGE_SIZE) - addr;
3529 if (l > len)
3530 l = len;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003531 phys_addr += (addr & ~TARGET_PAGE_MASK);
3532#if !defined(CONFIG_USER_ONLY)
3533 if (is_write)
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003534 cpu_physical_memory_write_rom(phys_addr, buf8, l);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003535 else
3536#endif
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003537 cpu_physical_memory_rw(phys_addr, buf8, l, is_write);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003538 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003539 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003540 addr += l;
3541 }
3542 return 0;
3543}
3544
3545/* in deterministic execution mode, instructions doing device I/Os
3546 must be at the end of the TB */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01003547void cpu_io_recompile(CPUArchState *env, void *retaddr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003548{
3549 TranslationBlock *tb;
3550 uint32_t n, cflags;
3551 target_ulong pc, cs_base;
3552 uint64_t flags;
3553
3554 tb = tb_find_pc((unsigned long)retaddr);
3555 if (!tb) {
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02003556 cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003557 retaddr);
3558 }
3559 n = env->icount_decr.u16.low + tb->icount;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02003560 cpu_restore_state(tb, env, (unsigned long)retaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003561 /* Calculate how many instructions had been executed before the fault
3562 occurred. */
3563 n = n - env->icount_decr.u16.low;
3564 /* Generate a new TB ending on the I/O insn. */
3565 n++;
3566 /* On MIPS and SH, delay slot instructions can only be restarted if
3567 they were already the first instruction in the TB. If this is not
3568 the first instruction in a TB then re-execute the preceding
3569 branch. */
3570#if defined(TARGET_MIPS)
3571 if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) {
3572 env->active_tc.PC -= 4;
3573 env->icount_decr.u16.low++;
3574 env->hflags &= ~MIPS_HFLAG_BMASK;
3575 }
3576#elif defined(TARGET_SH4)
3577 if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
3578 && n > 1) {
3579 env->pc -= 2;
3580 env->icount_decr.u16.low++;
3581 env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
3582 }
3583#endif
3584 /* This should never happen. */
3585 if (n > CF_COUNT_MASK)
3586 cpu_abort(env, "TB too big during recompile");
3587
3588 cflags = n | CF_LAST_IO;
3589 pc = tb->pc;
3590 cs_base = tb->cs_base;
3591 flags = tb->flags;
3592 tb_phys_invalidate(tb, -1);
3593 /* FIXME: In theory this could raise an exception. In practice
3594 we have already translated the block once so it's probably ok. */
3595 tb_gen_code(env, pc, cs_base, flags, cflags);
3596 /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
3597 the first in the TB) then we end up generating a whole new TB and
3598 repeating the fault, which is horribly inefficient.
3599 Better would be to execute just this insn uncached, or generate a
3600 second new TB. */
3601 cpu_resume_from_signal(env, NULL);
3602}
3603
David 'Digit' Turner36411062010-12-22 17:34:53 +01003604#if !defined(CONFIG_USER_ONLY)
3605
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003606void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003607{
3608 int i, target_code_size, max_target_code_size;
3609 int direct_jmp_count, direct_jmp2_count, cross_page;
3610 TranslationBlock *tb;
3611
3612 target_code_size = 0;
3613 max_target_code_size = 0;
3614 cross_page = 0;
3615 direct_jmp_count = 0;
3616 direct_jmp2_count = 0;
3617 for(i = 0; i < nb_tbs; i++) {
3618 tb = &tbs[i];
3619 target_code_size += tb->size;
3620 if (tb->size > max_target_code_size)
3621 max_target_code_size = tb->size;
3622 if (tb->page_addr[1] != -1)
3623 cross_page++;
3624 if (tb->tb_next_offset[0] != 0xffff) {
3625 direct_jmp_count++;
3626 if (tb->tb_next_offset[1] != 0xffff) {
3627 direct_jmp2_count++;
3628 }
3629 }
3630 }
3631 /* XXX: avoid using doubles ? */
3632 cpu_fprintf(f, "Translation buffer state:\n");
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003633 cpu_fprintf(f, "gen code size %td/%ld\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003634 code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02003635 cpu_fprintf(f, "TB count %d/%d\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003636 nb_tbs, code_gen_max_blocks);
3637 cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
3638 nb_tbs ? target_code_size / nb_tbs : 0,
3639 max_target_code_size);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003640 cpu_fprintf(f, "TB avg host size %td bytes (expansion ratio: %0.1f)\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003641 nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
3642 target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
3643 cpu_fprintf(f, "cross page TB count %d (%d%%)\n",
3644 cross_page,
3645 nb_tbs ? (cross_page * 100) / nb_tbs : 0);
3646 cpu_fprintf(f, "direct jump count %d (%d%%) (2 jumps=%d %d%%)\n",
3647 direct_jmp_count,
3648 nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
3649 direct_jmp2_count,
3650 nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
3651 cpu_fprintf(f, "\nStatistics:\n");
3652 cpu_fprintf(f, "TB flush count %d\n", tb_flush_count);
3653 cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
3654 cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count);
3655 tcg_dump_info(f, cpu_fprintf);
3656}
3657
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003658#endif