blob: 609c4c7fec1c73a65189e478dd7c73ffdd372ce5 [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;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800895 cpu_gen_code(env, tb, &code_gen_size);
896 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
897
898 /* check next page if needed */
899 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
900 phys_page2 = -1;
901 if ((pc & TARGET_PAGE_MASK) != virt_page2) {
902 phys_page2 = get_phys_addr_code(env, virt_page2);
903 }
904 tb_link_phys(tb, phys_pc, phys_page2);
905 return tb;
906}
907
908/* invalidate all TBs which intersect with the target physical page
909 starting in range [start;end[. NOTE: start and end must refer to
910 the same physical page. 'is_cpu_write_access' should be true if called
911 from a real cpu write access: the virtual CPU will exit the current
912 TB if code is modified inside this TB. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100913void tb_invalidate_phys_page_range(hwaddr start, hwaddr end,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800914 int is_cpu_write_access)
915{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700916 TranslationBlock *tb, *tb_next, *saved_tb;
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100917 CPUArchState *env = cpu_single_env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800918 target_ulong tb_start, tb_end;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700919 PageDesc *p;
920 int n;
921#ifdef TARGET_HAS_PRECISE_SMC
922 int current_tb_not_found = is_cpu_write_access;
923 TranslationBlock *current_tb = NULL;
924 int current_tb_modified = 0;
925 target_ulong current_pc = 0;
926 target_ulong current_cs_base = 0;
927 int current_flags = 0;
928#endif /* TARGET_HAS_PRECISE_SMC */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800929
930 p = page_find(start >> TARGET_PAGE_BITS);
931 if (!p)
932 return;
933 if (!p->code_bitmap &&
934 ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
935 is_cpu_write_access) {
936 /* build code bitmap */
937 build_page_bitmap(p);
938 }
939
940 /* we remove all the TBs in the range [start, end[ */
941 /* 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 -0800942 tb = p->first_tb;
943 while (tb != NULL) {
944 n = (long)tb & 3;
945 tb = (TranslationBlock *)((long)tb & ~3);
946 tb_next = tb->page_next[n];
947 /* NOTE: this is subtle as a TB may span two physical pages */
948 if (n == 0) {
949 /* NOTE: tb_end may be after the end of the page, but
950 it is not a problem */
951 tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
952 tb_end = tb_start + tb->size;
953 } else {
954 tb_start = tb->page_addr[1];
955 tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
956 }
957 if (!(tb_end <= start || tb_start >= end)) {
958#ifdef TARGET_HAS_PRECISE_SMC
959 if (current_tb_not_found) {
960 current_tb_not_found = 0;
961 current_tb = NULL;
962 if (env->mem_io_pc) {
963 /* now we have a real cpu fault */
964 current_tb = tb_find_pc(env->mem_io_pc);
965 }
966 }
967 if (current_tb == tb &&
968 (current_tb->cflags & CF_COUNT_MASK) != 1) {
969 /* If we are modifying the current TB, we must stop
970 its execution. We could be more precise by checking
971 that the modification is after the current PC, but it
972 would require a specialized function to partially
973 restore the CPU state */
974
975 current_tb_modified = 1;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200976 cpu_restore_state(current_tb, env, env->mem_io_pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700977 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
978 &current_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800979 }
980#endif /* TARGET_HAS_PRECISE_SMC */
981 /* we need to do that to handle the case where a signal
982 occurs while doing tb_phys_invalidate() */
983 saved_tb = NULL;
984 if (env) {
985 saved_tb = env->current_tb;
986 env->current_tb = NULL;
987 }
988 tb_phys_invalidate(tb, -1);
989 if (env) {
990 env->current_tb = saved_tb;
991 if (env->interrupt_request && env->current_tb)
992 cpu_interrupt(env, env->interrupt_request);
993 }
994 }
995 tb = tb_next;
996 }
997#if !defined(CONFIG_USER_ONLY)
998 /* if no code remaining, no need to continue to use slow writes */
999 if (!p->first_tb) {
1000 invalidate_page_bitmap(p);
1001 if (is_cpu_write_access) {
1002 tlb_unprotect_code_phys(env, start, env->mem_io_vaddr);
1003 }
1004 }
1005#endif
1006#ifdef TARGET_HAS_PRECISE_SMC
1007 if (current_tb_modified) {
1008 /* we generate a block containing just the instruction
1009 modifying the memory. It will ensure that it cannot modify
1010 itself */
1011 env->current_tb = NULL;
1012 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1013 cpu_resume_from_signal(env, NULL);
1014 }
1015#endif
1016}
1017
1018/* len must be <= 8 and start must be a multiple of len */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001019static inline void tb_invalidate_phys_page_fast(hwaddr start, int len)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001020{
1021 PageDesc *p;
1022 int offset, b;
1023#if 0
1024 if (1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001025 qemu_log("modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
1026 cpu_single_env->mem_io_vaddr, len,
1027 cpu_single_env->eip,
1028 cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001029 }
1030#endif
1031 p = page_find(start >> TARGET_PAGE_BITS);
1032 if (!p)
1033 return;
1034 if (p->code_bitmap) {
1035 offset = start & ~TARGET_PAGE_MASK;
1036 b = p->code_bitmap[offset >> 3] >> (offset & 7);
1037 if (b & ((1 << len) - 1))
1038 goto do_invalidate;
1039 } else {
1040 do_invalidate:
1041 tb_invalidate_phys_page_range(start, start + len, 1);
1042 }
1043}
1044
1045#if !defined(CONFIG_SOFTMMU)
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001046static void tb_invalidate_phys_page(hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001047 unsigned long pc, void *puc)
1048{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001049 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001050 PageDesc *p;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001051 int n;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001052#ifdef TARGET_HAS_PRECISE_SMC
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001053 TranslationBlock *current_tb = NULL;
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001054 CPUArchState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001055 int current_tb_modified = 0;
1056 target_ulong current_pc = 0;
1057 target_ulong current_cs_base = 0;
1058 int current_flags = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001059#endif
1060
1061 addr &= TARGET_PAGE_MASK;
1062 p = page_find(addr >> TARGET_PAGE_BITS);
1063 if (!p)
1064 return;
1065 tb = p->first_tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001066#ifdef TARGET_HAS_PRECISE_SMC
1067 if (tb && pc != 0) {
1068 current_tb = tb_find_pc(pc);
1069 }
1070#endif
1071 while (tb != NULL) {
1072 n = (long)tb & 3;
1073 tb = (TranslationBlock *)((long)tb & ~3);
1074#ifdef TARGET_HAS_PRECISE_SMC
1075 if (current_tb == tb &&
1076 (current_tb->cflags & CF_COUNT_MASK) != 1) {
1077 /* If we are modifying the current TB, we must stop
1078 its execution. We could be more precise by checking
1079 that the modification is after the current PC, but it
1080 would require a specialized function to partially
1081 restore the CPU state */
1082
1083 current_tb_modified = 1;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02001084 cpu_restore_state(current_tb, env, pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001085 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
1086 &current_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001087 }
1088#endif /* TARGET_HAS_PRECISE_SMC */
1089 tb_phys_invalidate(tb, addr);
1090 tb = tb->page_next[n];
1091 }
1092 p->first_tb = NULL;
1093#ifdef TARGET_HAS_PRECISE_SMC
1094 if (current_tb_modified) {
1095 /* we generate a block containing just the instruction
1096 modifying the memory. It will ensure that it cannot modify
1097 itself */
1098 env->current_tb = NULL;
1099 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1100 cpu_resume_from_signal(env, puc);
1101 }
1102#endif
1103}
1104#endif
1105
1106/* add the tb in the target page and protect it if necessary */
1107static inline void tb_alloc_page(TranslationBlock *tb,
1108 unsigned int n, target_ulong page_addr)
1109{
1110 PageDesc *p;
1111 TranslationBlock *last_first_tb;
1112
1113 tb->page_addr[n] = page_addr;
1114 p = page_find_alloc(page_addr >> TARGET_PAGE_BITS);
1115 tb->page_next[n] = p->first_tb;
1116 last_first_tb = p->first_tb;
1117 p->first_tb = (TranslationBlock *)((long)tb | n);
1118 invalidate_page_bitmap(p);
1119
1120#if defined(TARGET_HAS_SMC) || 1
1121
1122#if defined(CONFIG_USER_ONLY)
1123 if (p->flags & PAGE_WRITE) {
1124 target_ulong addr;
1125 PageDesc *p2;
1126 int prot;
1127
1128 /* force the host page as non writable (writes will have a
1129 page fault + mprotect overhead) */
1130 page_addr &= qemu_host_page_mask;
1131 prot = 0;
1132 for(addr = page_addr; addr < page_addr + qemu_host_page_size;
1133 addr += TARGET_PAGE_SIZE) {
1134
1135 p2 = page_find (addr >> TARGET_PAGE_BITS);
1136 if (!p2)
1137 continue;
1138 prot |= p2->flags;
1139 p2->flags &= ~PAGE_WRITE;
1140 page_get_flags(addr);
1141 }
1142 mprotect(g2h(page_addr), qemu_host_page_size,
1143 (prot & PAGE_BITS) & ~PAGE_WRITE);
1144#ifdef DEBUG_TB_INVALIDATE
1145 printf("protecting code page: 0x" TARGET_FMT_lx "\n",
1146 page_addr);
1147#endif
1148 }
1149#else
1150 /* if some code is already present, then the pages are already
1151 protected. So we handle the case where only the first TB is
1152 allocated in a physical page */
1153 if (!last_first_tb) {
1154 tlb_protect_code(page_addr);
1155 }
1156#endif
1157
1158#endif /* TARGET_HAS_SMC */
1159}
1160
1161/* Allocate a new translation block. Flush the translation buffer if
1162 too many translation blocks or too much generated code. */
1163TranslationBlock *tb_alloc(target_ulong pc)
1164{
1165 TranslationBlock *tb;
1166
1167 if (nb_tbs >= code_gen_max_blocks ||
1168 (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
1169 return NULL;
1170 tb = &tbs[nb_tbs++];
1171 tb->pc = pc;
1172 tb->cflags = 0;
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -08001173#ifdef CONFIG_MEMCHECK
1174 tb->tpc2gpc = NULL;
1175 tb->tpc2gpc_pairs = 0;
1176#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001177 return tb;
1178}
1179
1180void tb_free(TranslationBlock *tb)
1181{
1182 /* In practice this is mostly used for single use temporary TB
1183 Ignore the hard cases and just back up if this TB happens to
1184 be the last one generated. */
1185 if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) {
1186 code_gen_ptr = tb->tc_ptr;
1187 nb_tbs--;
1188 }
1189}
1190
1191/* add a new TB and link it to the physical page tables. phys_page2 is
1192 (-1) to indicate that only one page contains the TB. */
1193void tb_link_phys(TranslationBlock *tb,
1194 target_ulong phys_pc, target_ulong phys_page2)
1195{
1196 unsigned int h;
1197 TranslationBlock **ptb;
1198
1199 /* Grab the mmap lock to stop another thread invalidating this TB
1200 before we are done. */
1201 mmap_lock();
1202 /* add in the physical hash table */
1203 h = tb_phys_hash_func(phys_pc);
1204 ptb = &tb_phys_hash[h];
1205 tb->phys_hash_next = *ptb;
1206 *ptb = tb;
1207
1208 /* add in the page list */
1209 tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK);
1210 if (phys_page2 != -1)
1211 tb_alloc_page(tb, 1, phys_page2);
1212 else
1213 tb->page_addr[1] = -1;
1214
1215 tb->jmp_first = (TranslationBlock *)((long)tb | 2);
1216 tb->jmp_next[0] = NULL;
1217 tb->jmp_next[1] = NULL;
1218
1219 /* init original jump addresses */
1220 if (tb->tb_next_offset[0] != 0xffff)
1221 tb_reset_jump(tb, 0);
1222 if (tb->tb_next_offset[1] != 0xffff)
1223 tb_reset_jump(tb, 1);
1224
1225#ifdef DEBUG_TB_CHECK
1226 tb_page_check();
1227#endif
1228 mmap_unlock();
1229}
1230
1231/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
1232 tb[1].tc_ptr. Return NULL if not found */
1233TranslationBlock *tb_find_pc(unsigned long tc_ptr)
1234{
1235 int m_min, m_max, m;
1236 unsigned long v;
1237 TranslationBlock *tb;
1238
1239 if (nb_tbs <= 0)
1240 return NULL;
1241 if (tc_ptr < (unsigned long)code_gen_buffer ||
1242 tc_ptr >= (unsigned long)code_gen_ptr)
1243 return NULL;
1244 /* binary search (cf Knuth) */
1245 m_min = 0;
1246 m_max = nb_tbs - 1;
1247 while (m_min <= m_max) {
1248 m = (m_min + m_max) >> 1;
1249 tb = &tbs[m];
1250 v = (unsigned long)tb->tc_ptr;
1251 if (v == tc_ptr)
1252 return tb;
1253 else if (tc_ptr < v) {
1254 m_max = m - 1;
1255 } else {
1256 m_min = m + 1;
1257 }
1258 }
1259 return &tbs[m_max];
1260}
1261
1262static void tb_reset_jump_recursive(TranslationBlock *tb);
1263
1264static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
1265{
1266 TranslationBlock *tb1, *tb_next, **ptb;
1267 unsigned int n1;
1268
1269 tb1 = tb->jmp_next[n];
1270 if (tb1 != NULL) {
1271 /* find head of list */
1272 for(;;) {
1273 n1 = (long)tb1 & 3;
1274 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1275 if (n1 == 2)
1276 break;
1277 tb1 = tb1->jmp_next[n1];
1278 }
1279 /* we are now sure now that tb jumps to tb1 */
1280 tb_next = tb1;
1281
1282 /* remove tb from the jmp_first list */
1283 ptb = &tb_next->jmp_first;
1284 for(;;) {
1285 tb1 = *ptb;
1286 n1 = (long)tb1 & 3;
1287 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1288 if (n1 == n && tb1 == tb)
1289 break;
1290 ptb = &tb1->jmp_next[n1];
1291 }
1292 *ptb = tb->jmp_next[n];
1293 tb->jmp_next[n] = NULL;
1294
1295 /* suppress the jump to next tb in generated code */
1296 tb_reset_jump(tb, n);
1297
1298 /* suppress jumps in the tb on which we could have jumped */
1299 tb_reset_jump_recursive(tb_next);
1300 }
1301}
1302
1303static void tb_reset_jump_recursive(TranslationBlock *tb)
1304{
1305 tb_reset_jump_recursive2(tb, 0);
1306 tb_reset_jump_recursive2(tb, 1);
1307}
1308
1309#if defined(TARGET_HAS_ICE)
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001310static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001311{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001312 hwaddr addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001313 target_ulong pd;
1314 ram_addr_t ram_addr;
1315 PhysPageDesc *p;
1316
1317 addr = cpu_get_phys_page_debug(env, pc);
1318 p = phys_page_find(addr >> TARGET_PAGE_BITS);
1319 if (!p) {
1320 pd = IO_MEM_UNASSIGNED;
1321 } else {
1322 pd = p->phys_offset;
1323 }
1324 ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
1325 tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
1326}
1327#endif
1328
1329/* Add a watchpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001330int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001331 int flags, CPUWatchpoint **watchpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001332{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001333 target_ulong len_mask = ~(len - 1);
1334 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001335
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001336 /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
1337 if ((len != 1 && len != 2 && len != 4 && len != 8) || (addr & ~len_mask)) {
1338 fprintf(stderr, "qemu: tried to set invalid watchpoint at "
1339 TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
1340 return -EINVAL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001341 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001342 wp = g_malloc(sizeof(*wp));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001343
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001344 wp->vaddr = addr;
1345 wp->len_mask = len_mask;
1346 wp->flags = flags;
1347
1348 /* keep all GDB-injected watchpoints in front */
1349 if (flags & BP_GDB)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001350 QTAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001351 else
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001352 QTAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001353
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001354 tlb_flush_page(env, addr);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001355
1356 if (watchpoint)
1357 *watchpoint = wp;
1358 return 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001359}
1360
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001361/* Remove a specific watchpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001362int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, target_ulong len,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001363 int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001364{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001365 target_ulong len_mask = ~(len - 1);
1366 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001367
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001368 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001369 if (addr == wp->vaddr && len_mask == wp->len_mask
1370 && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
1371 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001372 return 0;
1373 }
1374 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001375 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001376}
1377
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001378/* Remove a specific watchpoint by reference. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001379void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001380{
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001381 QTAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001382
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001383 tlb_flush_page(env, watchpoint->vaddr);
1384
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001385 g_free(watchpoint);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001386}
1387
1388/* Remove all matching watchpoints. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001389void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001390{
1391 CPUWatchpoint *wp, *next;
1392
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001393 QTAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001394 if (wp->flags & mask)
1395 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001396 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001397}
1398
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001399/* Add a breakpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001400int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001401 CPUBreakpoint **breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001402{
1403#if defined(TARGET_HAS_ICE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001404 CPUBreakpoint *bp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001405
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001406 bp = g_malloc(sizeof(*bp));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001407
1408 bp->pc = pc;
1409 bp->flags = flags;
1410
1411 /* keep all GDB-injected breakpoints in front */
1412 if (flags & BP_GDB)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001413 QTAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001414 else
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001415 QTAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001416
1417 breakpoint_invalidate(env, pc);
1418
1419 if (breakpoint)
1420 *breakpoint = bp;
1421 return 0;
1422#else
1423 return -ENOSYS;
1424#endif
1425}
1426
1427/* Remove a specific breakpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001428int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001429{
1430#if defined(TARGET_HAS_ICE)
1431 CPUBreakpoint *bp;
1432
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001433 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001434 if (bp->pc == pc && bp->flags == flags) {
1435 cpu_breakpoint_remove_by_ref(env, bp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001436 return 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001437 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001438 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001439 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001440#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001441 return -ENOSYS;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001442#endif
1443}
1444
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001445/* Remove a specific breakpoint by reference. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001446void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001447{
1448#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001449 QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001450
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001451 breakpoint_invalidate(env, breakpoint->pc);
1452
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001453 g_free(breakpoint);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001454#endif
1455}
1456
1457/* Remove all matching breakpoints. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001458void cpu_breakpoint_remove_all(CPUArchState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001459{
1460#if defined(TARGET_HAS_ICE)
1461 CPUBreakpoint *bp, *next;
1462
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001463 QTAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001464 if (bp->flags & mask)
1465 cpu_breakpoint_remove_by_ref(env, bp);
1466 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001467#endif
1468}
1469
1470/* enable or disable single step mode. EXCP_DEBUG is returned by the
1471 CPU loop after each instruction */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001472void cpu_single_step(CPUOldState *env, int enabled)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001473{
1474#if defined(TARGET_HAS_ICE)
1475 if (env->singlestep_enabled != enabled) {
1476 env->singlestep_enabled = enabled;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001477 if (kvm_enabled())
1478 kvm_update_guest_debug(env, 0);
1479 else {
1480 /* must flush all the translated code to avoid inconsistencies */
1481 /* XXX: only flush what is necessary */
1482 tb_flush(env);
1483 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001484 }
1485#endif
1486}
1487
1488/* enable or disable low levels log */
1489void cpu_set_log(int log_flags)
1490{
1491 loglevel = log_flags;
1492 if (loglevel && !logfile) {
1493 logfile = fopen(logfilename, log_append ? "a" : "w");
1494 if (!logfile) {
1495 perror(logfilename);
Iliyan Malchev4a2c9dd2012-04-02 08:20:56 -07001496 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001497 }
1498#if !defined(CONFIG_SOFTMMU)
1499 /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1500 {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001501 static char logfile_buf[4096];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001502 setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1503 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001504#elif !defined(_WIN32)
1505 /* Win32 doesn't support line-buffering and requires size >= 2 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001506 setvbuf(logfile, NULL, _IOLBF, 0);
1507#endif
1508 log_append = 1;
1509 }
1510 if (!loglevel && logfile) {
1511 fclose(logfile);
1512 logfile = NULL;
1513 }
1514}
1515
1516void cpu_set_log_filename(const char *filename)
1517{
1518 logfilename = strdup(filename);
1519 if (logfile) {
1520 fclose(logfile);
1521 logfile = NULL;
1522 }
1523 cpu_set_log(loglevel);
1524}
1525
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001526static void cpu_unlink_tb(CPUOldState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001527{
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001528 /* FIXME: TB unchaining isn't SMP safe. For now just ignore the
1529 problem and hope the cpu will stop of its own accord. For userspace
1530 emulation this often isn't actually as bad as it sounds. Often
1531 signals are used primarily to interrupt blocking syscalls. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001532 TranslationBlock *tb;
1533 static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
1534
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001535 spin_lock(&interrupt_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001536 tb = env->current_tb;
1537 /* if the cpu is currently executing code, we must unlink it and
1538 all the potentially executing TB */
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001539 if (tb) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001540 env->current_tb = NULL;
1541 tb_reset_jump_recursive(tb);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001542 }
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001543 spin_unlock(&interrupt_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001544}
1545
1546/* mask must never be zero, except for A20 change call */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001547void cpu_interrupt(CPUOldState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001548{
1549 int old_mask;
1550
1551 old_mask = env->interrupt_request;
1552 env->interrupt_request |= mask;
1553
1554#ifndef CONFIG_USER_ONLY
1555 /*
1556 * If called from iothread context, wake the target cpu in
1557 * case its halted.
1558 */
1559 if (!qemu_cpu_self(env)) {
1560 qemu_cpu_kick(env);
1561 return;
1562 }
1563#endif
1564
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001565 if (use_icount) {
1566 env->icount_decr.u16.high = 0xffff;
1567#ifndef CONFIG_USER_ONLY
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001568 if (!can_do_io(env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001569 && (mask & ~old_mask) != 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001570 cpu_abort(env, "Raised interrupt while not in I/O function");
1571 }
1572#endif
1573 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001574 cpu_unlink_tb(env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001575 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001576}
1577
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001578void cpu_reset_interrupt(CPUOldState *env, int mask)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001579{
1580 env->interrupt_request &= ~mask;
1581}
1582
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001583void cpu_exit(CPUOldState *env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001584{
1585 env->exit_request = 1;
1586 cpu_unlink_tb(env);
1587}
1588
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001589void cpu_abort(CPUOldState *env, const char *fmt, ...)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001590{
1591 va_list ap;
1592 va_list ap2;
1593
1594 va_start(ap, fmt);
1595 va_copy(ap2, ap);
1596 fprintf(stderr, "qemu: fatal: ");
1597 vfprintf(stderr, fmt, ap);
1598 fprintf(stderr, "\n");
1599#ifdef TARGET_I386
1600 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1601#else
1602 cpu_dump_state(env, stderr, fprintf, 0);
1603#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001604 if (qemu_log_enabled()) {
1605 qemu_log("qemu: fatal: ");
1606 qemu_log_vprintf(fmt, ap2);
1607 qemu_log("\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001608#ifdef TARGET_I386
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001609 log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001610#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001611 log_cpu_state(env, 0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001612#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001613 qemu_log_flush();
1614 qemu_log_close();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001615 }
1616 va_end(ap2);
1617 va_end(ap);
David 'Digit' Turner36411062010-12-22 17:34:53 +01001618#if defined(CONFIG_USER_ONLY)
1619 {
1620 struct sigaction act;
1621 sigfillset(&act.sa_mask);
1622 act.sa_handler = SIG_DFL;
1623 sigaction(SIGABRT, &act, NULL);
1624 }
1625#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001626 abort();
1627}
1628
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001629CPUArchState *cpu_copy(CPUOldState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001630{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001631 CPUArchState *new_env = cpu_init(env->cpu_model_str);
1632 CPUArchState *next_cpu = new_env->next_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001633 int cpu_index = new_env->cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001634#if defined(TARGET_HAS_ICE)
1635 CPUBreakpoint *bp;
1636 CPUWatchpoint *wp;
1637#endif
1638
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001639 memcpy(new_env, env, sizeof(CPUOldState));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001640
1641 /* Preserve chaining and index. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001642 new_env->next_cpu = next_cpu;
1643 new_env->cpu_index = cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001644
1645 /* Clone all break/watchpoints.
1646 Note: Once we support ptrace with hw-debug register access, make sure
1647 BP_CPU break/watchpoints are handled correctly on clone. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001648 QTAILQ_INIT(&env->breakpoints);
1649 QTAILQ_INIT(&env->watchpoints);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001650#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001651 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001652 cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
1653 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001654 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001655 cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
1656 wp->flags, NULL);
1657 }
1658#endif
1659
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001660 return new_env;
1661}
1662
1663#if !defined(CONFIG_USER_ONLY)
1664
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001665/* Note: start and end must be within the same ram block. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001666void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
1667 int dirty_flags)
1668{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001669 CPUOldState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001670 unsigned long length, start1;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001671 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001672
1673 start &= TARGET_PAGE_MASK;
1674 end = TARGET_PAGE_ALIGN(end);
1675
1676 length = end - start;
1677 if (length == 0)
1678 return;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001679 cpu_physical_memory_mask_dirty_range(start, length, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001680
1681 /* we modify the TLB cache so that the dirty bit will be set again
1682 when accessing the range */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001683 start1 = (unsigned long)qemu_safe_ram_ptr(start);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001684 /* Chek that we don't span multiple blocks - this breaks the
1685 address comparisons below. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001686 if ((unsigned long)qemu_safe_ram_ptr(end - 1) - start1
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001687 != (end - 1) - start) {
1688 abort();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001689 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001690
1691 for(env = first_cpu; env != NULL; env = env->next_cpu) {
1692 int mmu_idx;
1693 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1694 for(i = 0; i < CPU_TLB_SIZE; i++)
1695 tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
1696 start1, length);
1697 }
1698 }
1699}
1700
1701int cpu_physical_memory_set_dirty_tracking(int enable)
1702{
1703 in_migration = enable;
1704 if (kvm_enabled()) {
1705 return kvm_set_migration_log(enable);
1706 }
1707 return 0;
1708}
1709
1710int cpu_physical_memory_get_dirty_tracking(void)
1711{
1712 return in_migration;
1713}
1714
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001715int cpu_physical_sync_dirty_bitmap(hwaddr start_addr,
1716 hwaddr end_addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001717{
1718 int ret = 0;
1719
1720 if (kvm_enabled())
1721 ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
1722 return ret;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001723}
1724
1725static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1726{
1727 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001728 void *p;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001729
1730 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001731 p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
1732 + tlb_entry->addend);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001733 ram_addr = qemu_ram_addr_from_host_nofail(p);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001734 if (!cpu_physical_memory_is_dirty(ram_addr)) {
1735 tlb_entry->addr_write |= TLB_NOTDIRTY;
1736 }
1737 }
1738}
1739
1740/* update the TLB according to the current state of the dirty bits */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001741void cpu_tlb_update_dirty(CPUArchState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001742{
1743 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001744 int mmu_idx;
1745 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1746 for(i = 0; i < CPU_TLB_SIZE; i++)
1747 tlb_update_dirty(&env->tlb_table[mmu_idx][i]);
1748 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001749}
1750
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001751
1752#else
1753
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001754void tlb_flush(CPUArchState *env, int flush_global)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001755{
1756}
1757
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001758void tlb_flush_page(CPUArchState *env, target_ulong addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001759{
1760}
1761
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001762int tlb_set_page_exec(CPUArchState *env, target_ulong vaddr,
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001763 hwaddr paddr, int prot,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001764 int mmu_idx, int is_softmmu)
1765{
1766 return 0;
1767}
1768
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001769/*
1770 * Walks guest process memory "regions" one by one
1771 * and calls callback function 'fn' for each region.
1772 */
1773int walk_memory_regions(void *priv,
1774 int (*fn)(void *, unsigned long, unsigned long, unsigned long))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001775{
1776 unsigned long start, end;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001777 PageDesc *p = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001778 int i, j, prot, prot1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001779 int rc = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001780
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001781 start = end = -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001782 prot = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001783
1784 for (i = 0; i <= L1_SIZE; i++) {
1785 p = (i < L1_SIZE) ? l1_map[i] : NULL;
1786 for (j = 0; j < L2_SIZE; j++) {
1787 prot1 = (p == NULL) ? 0 : p[j].flags;
1788 /*
1789 * "region" is one continuous chunk of memory
1790 * that has same protection flags set.
1791 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001792 if (prot1 != prot) {
1793 end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
1794 if (start != -1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001795 rc = (*fn)(priv, start, end, prot);
1796 /* callback can stop iteration by returning != 0 */
1797 if (rc != 0)
1798 return (rc);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001799 }
1800 if (prot1 != 0)
1801 start = end;
1802 else
1803 start = -1;
1804 prot = prot1;
1805 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001806 if (p == NULL)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001807 break;
1808 }
1809 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001810 return (rc);
1811}
1812
1813static int dump_region(void *priv, unsigned long start,
1814 unsigned long end, unsigned long prot)
1815{
1816 FILE *f = (FILE *)priv;
1817
1818 (void) fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
1819 start, end, end - start,
1820 ((prot & PAGE_READ) ? 'r' : '-'),
1821 ((prot & PAGE_WRITE) ? 'w' : '-'),
1822 ((prot & PAGE_EXEC) ? 'x' : '-'));
1823
1824 return (0);
1825}
1826
1827/* dump memory mappings */
1828void page_dump(FILE *f)
1829{
1830 (void) fprintf(f, "%-8s %-8s %-8s %s\n",
1831 "start", "end", "size", "prot");
1832 walk_memory_regions(f, dump_region);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001833}
1834
1835int page_get_flags(target_ulong address)
1836{
1837 PageDesc *p;
1838
1839 p = page_find(address >> TARGET_PAGE_BITS);
1840 if (!p)
1841 return 0;
1842 return p->flags;
1843}
1844
David 'Digit' Turner36411062010-12-22 17:34:53 +01001845/* Modify the flags of a page and invalidate the code if necessary.
1846 The flag PAGE_WRITE_ORG is positioned automatically depending
1847 on PAGE_WRITE. The mmap_lock should already be held. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001848void page_set_flags(target_ulong start, target_ulong end, int flags)
1849{
1850 PageDesc *p;
1851 target_ulong addr;
1852
1853 /* mmap_lock should already be held. */
1854 start = start & TARGET_PAGE_MASK;
1855 end = TARGET_PAGE_ALIGN(end);
1856 if (flags & PAGE_WRITE)
1857 flags |= PAGE_WRITE_ORG;
1858 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1859 p = page_find_alloc(addr >> TARGET_PAGE_BITS);
1860 /* We may be called for host regions that are outside guest
1861 address space. */
1862 if (!p)
1863 return;
1864 /* if the write protection is set, then we invalidate the code
1865 inside */
1866 if (!(p->flags & PAGE_WRITE) &&
1867 (flags & PAGE_WRITE) &&
1868 p->first_tb) {
1869 tb_invalidate_phys_page(addr, 0, NULL);
1870 }
1871 p->flags = flags;
1872 }
1873}
1874
1875int page_check_range(target_ulong start, target_ulong len, int flags)
1876{
1877 PageDesc *p;
1878 target_ulong end;
1879 target_ulong addr;
1880
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001881 if (start + len < start)
1882 /* we've wrapped around */
1883 return -1;
1884
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001885 end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
1886 start = start & TARGET_PAGE_MASK;
1887
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001888 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1889 p = page_find(addr >> TARGET_PAGE_BITS);
1890 if( !p )
1891 return -1;
1892 if( !(p->flags & PAGE_VALID) )
1893 return -1;
1894
1895 if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
1896 return -1;
1897 if (flags & PAGE_WRITE) {
1898 if (!(p->flags & PAGE_WRITE_ORG))
1899 return -1;
1900 /* unprotect the page if it was put read-only because it
1901 contains translated code */
1902 if (!(p->flags & PAGE_WRITE)) {
1903 if (!page_unprotect(addr, 0, NULL))
1904 return -1;
1905 }
1906 return 0;
1907 }
1908 }
1909 return 0;
1910}
1911
1912/* called from signal handler: invalidate the code and unprotect the
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001913 page. Return TRUE if the fault was successfully handled. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001914int page_unprotect(target_ulong address, unsigned long pc, void *puc)
1915{
1916 unsigned int page_index, prot, pindex;
1917 PageDesc *p, *p1;
1918 target_ulong host_start, host_end, addr;
1919
1920 /* Technically this isn't safe inside a signal handler. However we
1921 know this only ever happens in a synchronous SEGV handler, so in
1922 practice it seems to be ok. */
1923 mmap_lock();
1924
1925 host_start = address & qemu_host_page_mask;
1926 page_index = host_start >> TARGET_PAGE_BITS;
1927 p1 = page_find(page_index);
1928 if (!p1) {
1929 mmap_unlock();
1930 return 0;
1931 }
1932 host_end = host_start + qemu_host_page_size;
1933 p = p1;
1934 prot = 0;
1935 for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
1936 prot |= p->flags;
1937 p++;
1938 }
1939 /* if the page was really writable, then we change its
1940 protection back to writable */
1941 if (prot & PAGE_WRITE_ORG) {
1942 pindex = (address - host_start) >> TARGET_PAGE_BITS;
1943 if (!(p1[pindex].flags & PAGE_WRITE)) {
1944 mprotect((void *)g2h(host_start), qemu_host_page_size,
1945 (prot & PAGE_BITS) | PAGE_WRITE);
1946 p1[pindex].flags |= PAGE_WRITE;
1947 /* and since the content will be modified, we must invalidate
1948 the corresponding translated code. */
1949 tb_invalidate_phys_page(address, pc, puc);
1950#ifdef DEBUG_TB_CHECK
1951 tb_invalidate_check(address);
1952#endif
1953 mmap_unlock();
1954 return 1;
1955 }
1956 }
1957 mmap_unlock();
1958 return 0;
1959}
1960
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001961static inline void tlb_set_dirty(CPUOldState *env,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001962 unsigned long addr, target_ulong vaddr)
1963{
1964}
1965#endif /* defined(CONFIG_USER_ONLY) */
1966
1967#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001968
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001969static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001970 ram_addr_t memory, ram_addr_t region_offset);
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001971static void *subpage_init (hwaddr base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001972 ram_addr_t orig_memory, ram_addr_t region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001973#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
1974 need_subpage) \
1975 do { \
1976 if (addr > start_addr) \
1977 start_addr2 = 0; \
1978 else { \
1979 start_addr2 = start_addr & ~TARGET_PAGE_MASK; \
1980 if (start_addr2 > 0) \
1981 need_subpage = 1; \
1982 } \
1983 \
1984 if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE) \
1985 end_addr2 = TARGET_PAGE_SIZE - 1; \
1986 else { \
1987 end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
1988 if (end_addr2 < TARGET_PAGE_SIZE - 1) \
1989 need_subpage = 1; \
1990 } \
1991 } while (0)
1992
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001993/* register physical memory.
1994 For RAM, 'size' must be a multiple of the target page size.
1995 If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001996 io memory page. The address used when calling the IO function is
1997 the offset from the start of the region, plus region_offset. Both
1998 start_addr and region_offset are rounded down to a page boundary
1999 before calculating this offset. This should not be a problem unless
2000 the low bits of start_addr and region_offset differ. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002001void cpu_register_physical_memory_log(hwaddr start_addr,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002002 ram_addr_t size,
2003 ram_addr_t phys_offset,
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002004 ram_addr_t region_offset,
2005 bool log_dirty)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002006{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002007 hwaddr addr, end_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002008 PhysPageDesc *p;
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002009 CPUOldState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002010 ram_addr_t orig_size = size;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002011 subpage_t *subpage;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002012
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002013 if (kvm_enabled())
2014 kvm_set_phys_mem(start_addr, size, phys_offset);
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002015#ifdef CONFIG_HAX
2016 if (hax_enabled())
2017 hax_set_phys_mem(start_addr, size, phys_offset);
2018#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002019
2020 if (phys_offset == IO_MEM_UNASSIGNED) {
2021 region_offset = start_addr;
2022 }
2023 region_offset &= TARGET_PAGE_MASK;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002024 size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002025 end_addr = start_addr + (hwaddr)size;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002026
2027 addr = start_addr;
2028 do {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002029 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2030 if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
2031 ram_addr_t orig_memory = p->phys_offset;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002032 hwaddr start_addr2, end_addr2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002033 int need_subpage = 0;
2034
2035 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2036 need_subpage);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002037 if (need_subpage) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002038 if (!(orig_memory & IO_MEM_SUBPAGE)) {
2039 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002040 &p->phys_offset, orig_memory,
2041 p->region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002042 } else {
2043 subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
2044 >> IO_MEM_SHIFT];
2045 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002046 subpage_register(subpage, start_addr2, end_addr2, phys_offset,
2047 region_offset);
2048 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002049 } else {
2050 p->phys_offset = phys_offset;
2051 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2052 (phys_offset & IO_MEM_ROMD))
2053 phys_offset += TARGET_PAGE_SIZE;
2054 }
2055 } else {
2056 p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2057 p->phys_offset = phys_offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002058 p->region_offset = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002059 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002060 (phys_offset & IO_MEM_ROMD)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002061 phys_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002062 } else {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002063 hwaddr start_addr2, end_addr2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002064 int need_subpage = 0;
2065
2066 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2067 end_addr2, need_subpage);
2068
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002069 if (need_subpage) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002070 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002071 &p->phys_offset, IO_MEM_UNASSIGNED,
2072 addr & TARGET_PAGE_MASK);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002073 subpage_register(subpage, start_addr2, end_addr2,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002074 phys_offset, region_offset);
2075 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002076 }
2077 }
2078 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002079 region_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002080 addr += TARGET_PAGE_SIZE;
2081 } while (addr != end_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002082
2083 /* since each CPU stores ram addresses in its TLB cache, we must
2084 reset the modified entries */
2085 /* XXX: slow ! */
2086 for(env = first_cpu; env != NULL; env = env->next_cpu) {
2087 tlb_flush(env, 1);
2088 }
2089}
2090
2091/* XXX: temporary until new memory mapping API */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002092ram_addr_t cpu_get_physical_page_desc(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002093{
2094 PhysPageDesc *p;
2095
2096 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2097 if (!p)
2098 return IO_MEM_UNASSIGNED;
2099 return p->phys_offset;
2100}
2101
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002102void qemu_register_coalesced_mmio(hwaddr addr, ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002103{
2104 if (kvm_enabled())
2105 kvm_coalesce_mmio_region(addr, size);
2106}
2107
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002108void qemu_unregister_coalesced_mmio(hwaddr addr, ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002109{
2110 if (kvm_enabled())
2111 kvm_uncoalesce_mmio_region(addr, size);
2112}
2113
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002114static ram_addr_t find_ram_offset(ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002115{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002116 RAMBlock *block, *next_block;
2117 ram_addr_t offset = 0, mingap = ULONG_MAX;
2118
2119 if (QLIST_EMPTY(&ram_list.blocks))
2120 return 0;
2121
2122 QLIST_FOREACH(block, &ram_list.blocks, next) {
2123 ram_addr_t end, next = ULONG_MAX;
2124
2125 end = block->offset + block->length;
2126
2127 QLIST_FOREACH(next_block, &ram_list.blocks, next) {
2128 if (next_block->offset >= end) {
2129 next = MIN(next, next_block->offset);
2130 }
2131 }
2132 if (next - end >= size && next - end < mingap) {
2133 offset = end;
2134 mingap = next - end;
2135 }
2136 }
2137 return offset;
2138}
2139
2140static ram_addr_t last_ram_offset(void)
2141{
2142 RAMBlock *block;
2143 ram_addr_t last = 0;
2144
2145 QLIST_FOREACH(block, &ram_list.blocks, next)
2146 last = MAX(last, block->offset + block->length);
2147
2148 return last;
2149}
2150
2151ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
2152 ram_addr_t size, void *host)
2153{
2154 RAMBlock *new_block, *block;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002155
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002156 size = TARGET_PAGE_ALIGN(size);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002157 new_block = g_malloc0(sizeof(*new_block));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002158
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002159#if 0
2160 if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
2161 char *id = dev->parent_bus->info->get_dev_path(dev);
2162 if (id) {
2163 snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002164 g_free(id);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002165 }
2166 }
2167#endif
2168 pstrcat(new_block->idstr, sizeof(new_block->idstr), name);
2169
2170 QLIST_FOREACH(block, &ram_list.blocks, next) {
2171 if (!strcmp(block->idstr, new_block->idstr)) {
2172 fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n",
2173 new_block->idstr);
2174 abort();
2175 }
2176 }
2177
2178 if (host) {
2179 new_block->host = host;
2180 new_block->flags |= RAM_PREALLOC_MASK;
2181 } else {
2182 if (mem_path) {
2183#if 0 && defined (__linux__) && !defined(TARGET_S390X)
2184 new_block->host = file_ram_alloc(new_block, size, mem_path);
2185 if (!new_block->host) {
2186 new_block->host = qemu_vmalloc(size);
2187 qemu_madvise(new_block->host, size, QEMU_MADV_MERGEABLE);
2188 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002189#else
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002190 fprintf(stderr, "-mem-path option unsupported\n");
2191 exit(1);
2192#endif
2193 } else {
2194#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2195 /* XXX S390 KVM requires the topmost vma of the RAM to be < 256GB */
2196 new_block->host = mmap((void*)0x1000000, size,
2197 PROT_EXEC|PROT_READ|PROT_WRITE,
2198 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
2199#else
2200 new_block->host = qemu_vmalloc(size);
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002201
2202#ifdef CONFIG_HAX
2203 /*
2204 * In HAX, qemu allocates the virtual address, and HAX kernel
2205 * module populates the region with physical memory. Currently
2206 * we don’t populate guest memory on demand, thus we should
2207 * make sure that sufficient amount of memory is available in
2208 * advance.
2209 */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002210 if (hax_enabled()) {
2211 int ret = hax_populate_ram(
2212 (uint64_t)(uintptr_t)new_block->host,
2213 size);
2214 if (ret < 0) {
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002215 fprintf(stderr, "Hax failed to populate ram\n");
2216 exit(-1);
2217 }
2218 }
2219#endif
2220
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002221#endif
2222#ifdef MADV_MERGEABLE
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002223 madvise(new_block->host, size, MADV_MERGEABLE);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002224#endif
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002225 }
2226 }
2227
2228 new_block->offset = find_ram_offset(size);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002229 new_block->length = size;
2230
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002231 QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002232
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002233 ram_list.phys_dirty = g_realloc(ram_list.phys_dirty,
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002234 last_ram_offset() >> TARGET_PAGE_BITS);
2235 memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002236 0xff, size >> TARGET_PAGE_BITS);
2237
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002238 if (kvm_enabled())
2239 kvm_setup_guest_memory(new_block->host, size);
2240
2241 return new_block->offset;
2242}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002243
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002244ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
2245{
2246 return qemu_ram_alloc_from_ptr(dev, name, size, NULL);
2247}
2248
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002249void qemu_ram_free(ram_addr_t addr)
2250{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002251 RAMBlock *block;
2252
2253 QLIST_FOREACH(block, &ram_list.blocks, next) {
2254 if (addr == block->offset) {
2255 QLIST_REMOVE(block, next);
2256 if (block->flags & RAM_PREALLOC_MASK) {
2257 ;
2258 } else if (mem_path) {
2259#if defined (__linux__) && !defined(TARGET_S390X)
2260 if (block->fd) {
2261 munmap(block->host, block->length);
2262 close(block->fd);
2263 } else {
2264 qemu_vfree(block->host);
2265 }
2266#else
2267 abort();
2268#endif
2269 } else {
2270#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2271 munmap(block->host, block->length);
2272#else
2273 qemu_vfree(block->host);
2274#endif
2275 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002276 g_free(block);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002277 return;
2278 }
2279 }
2280
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002281}
2282
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002283#ifndef _WIN32
2284void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
2285{
2286#ifndef CONFIG_ANDROID
2287 RAMBlock *block;
2288 ram_addr_t offset;
2289 int flags;
2290 void *area, *vaddr;
2291
2292 QLIST_FOREACH(block, &ram_list.blocks, next) {
2293 offset = addr - block->offset;
2294 if (offset < block->length) {
2295 vaddr = block->host + offset;
2296 if (block->flags & RAM_PREALLOC_MASK) {
2297 ;
2298 } else {
2299 flags = MAP_FIXED;
2300 munmap(vaddr, length);
2301 if (mem_path) {
2302#if defined(__linux__) && !defined(TARGET_S390X)
2303 if (block->fd) {
2304#ifdef MAP_POPULATE
2305 flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED :
2306 MAP_PRIVATE;
2307#else
2308 flags |= MAP_PRIVATE;
2309#endif
2310 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2311 flags, block->fd, offset);
2312 } else {
2313 flags |= MAP_PRIVATE | MAP_ANONYMOUS;
2314 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2315 flags, -1, 0);
2316 }
2317#else
2318 abort();
2319#endif
2320 } else {
2321#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2322 flags |= MAP_SHARED | MAP_ANONYMOUS;
2323 area = mmap(vaddr, length, PROT_EXEC|PROT_READ|PROT_WRITE,
2324 flags, -1, 0);
2325#else
2326 flags |= MAP_PRIVATE | MAP_ANONYMOUS;
2327 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2328 flags, -1, 0);
2329#endif
2330 }
2331 if (area != vaddr) {
2332 fprintf(stderr, "Could not remap addr: %lx@%lx\n",
2333 length, addr);
2334 exit(1);
2335 }
2336 qemu_madvise(vaddr, length, QEMU_MADV_MERGEABLE);
2337 }
2338 return;
2339 }
2340 }
2341#endif /* !CONFIG_ANDROID */
2342}
2343#endif /* !_WIN32 */
2344
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002345/* Return a host pointer to ram allocated with qemu_ram_alloc.
2346 With the exception of the softmmu code in this file, this should
2347 only be used for local memory (e.g. video ram) that the device owns,
2348 and knows it isn't going to access beyond the end of the block.
2349
2350 It should not be used for general purpose DMA.
2351 Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
2352 */
2353void *qemu_get_ram_ptr(ram_addr_t addr)
2354{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002355 RAMBlock *block;
2356
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002357 QLIST_FOREACH(block, &ram_list.blocks, next) {
2358 if (addr - block->offset < block->length) {
2359 /* Move this entry to to start of the list. */
2360 if (block != QLIST_FIRST(&ram_list.blocks)) {
2361 QLIST_REMOVE(block, next);
2362 QLIST_INSERT_HEAD(&ram_list.blocks, block, next);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002363 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002364 return block->host + (addr - block->offset);
2365 }
2366 }
2367
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002368 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2369 abort();
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002370
2371 return NULL;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002372 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002373
2374/* Return a host pointer to ram allocated with qemu_ram_alloc.
2375 * Same as qemu_get_ram_ptr but avoid reordering ramblocks.
2376 */
2377void *qemu_safe_ram_ptr(ram_addr_t addr)
2378{
2379 RAMBlock *block;
2380
2381 QLIST_FOREACH(block, &ram_list.blocks, next) {
2382 if (addr - block->offset < block->length) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002383 return block->host + (addr - block->offset);
2384}
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002385 }
2386
2387 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2388 abort();
2389
2390 return NULL;
2391}
2392
2393int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
2394{
2395 RAMBlock *block;
2396 uint8_t *host = ptr;
2397
2398 QLIST_FOREACH(block, &ram_list.blocks, next) {
2399 if (host - block->host < block->length) {
2400 *ram_addr = block->offset + (host - block->host);
2401 return 0;
2402 }
2403 }
2404 return -1;
2405}
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002406
2407/* Some of the softmmu routines need to translate from a host pointer
2408 (typically a TLB entry) back to a ram offset. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002409ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002410{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002411 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002412
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002413 if (qemu_ram_addr_from_host(ptr, &ram_addr)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002414 fprintf(stderr, "Bad ram pointer %p\n", ptr);
2415 abort();
2416 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002417 return ram_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002418}
2419
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002420static uint32_t unassigned_mem_readb(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002421{
2422#ifdef DEBUG_UNASSIGNED
2423 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2424#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002425#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002426 do_unassigned_access(addr, 0, 0, 0, 1);
2427#endif
2428 return 0;
2429}
2430
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002431static uint32_t unassigned_mem_readw(void *opaque, hwaddr addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002432{
2433#ifdef DEBUG_UNASSIGNED
2434 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2435#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002436#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002437 do_unassigned_access(addr, 0, 0, 0, 2);
2438#endif
2439 return 0;
2440}
2441
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002442static uint32_t unassigned_mem_readl(void *opaque, hwaddr addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002443{
2444#ifdef DEBUG_UNASSIGNED
2445 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2446#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002447#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002448 do_unassigned_access(addr, 0, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002449#endif
2450 return 0;
2451}
2452
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002453static void unassigned_mem_writeb(void *opaque, hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002454{
2455#ifdef DEBUG_UNASSIGNED
2456 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2457#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002458#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002459 do_unassigned_access(addr, 1, 0, 0, 1);
2460#endif
2461}
2462
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002463static void unassigned_mem_writew(void *opaque, hwaddr addr, uint32_t val)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002464{
2465#ifdef DEBUG_UNASSIGNED
2466 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2467#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002468#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002469 do_unassigned_access(addr, 1, 0, 0, 2);
2470#endif
2471}
2472
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002473static void unassigned_mem_writel(void *opaque, hwaddr addr, uint32_t val)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002474{
2475#ifdef DEBUG_UNASSIGNED
2476 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2477#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002478#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002479 do_unassigned_access(addr, 1, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002480#endif
2481}
2482
David 'Digit' Turner36411062010-12-22 17:34:53 +01002483static CPUReadMemoryFunc * const unassigned_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002484 unassigned_mem_readb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002485 unassigned_mem_readw,
2486 unassigned_mem_readl,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002487};
2488
David 'Digit' Turner36411062010-12-22 17:34:53 +01002489static CPUWriteMemoryFunc * const unassigned_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002490 unassigned_mem_writeb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002491 unassigned_mem_writew,
2492 unassigned_mem_writel,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002493};
2494
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002495static void notdirty_mem_writeb(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002496 uint32_t val)
2497{
2498 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002499 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002500 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2501#if !defined(CONFIG_USER_ONLY)
2502 tb_invalidate_phys_page_fast(ram_addr, 1);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002503 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002504#endif
2505 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002506 stb_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002507 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002508 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002509 /* we remove the notdirty callback only if the code has been
2510 flushed */
2511 if (dirty_flags == 0xff)
2512 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2513}
2514
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002515static void notdirty_mem_writew(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002516 uint32_t val)
2517{
2518 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002519 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002520 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2521#if !defined(CONFIG_USER_ONLY)
2522 tb_invalidate_phys_page_fast(ram_addr, 2);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002523 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002524#endif
2525 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002526 stw_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002527 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002528 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002529 /* we remove the notdirty callback only if the code has been
2530 flushed */
2531 if (dirty_flags == 0xff)
2532 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2533}
2534
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002535static void notdirty_mem_writel(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002536 uint32_t val)
2537{
2538 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002539 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002540 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2541#if !defined(CONFIG_USER_ONLY)
2542 tb_invalidate_phys_page_fast(ram_addr, 4);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002543 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002544#endif
2545 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002546 stl_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002547 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002548 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002549 /* we remove the notdirty callback only if the code has been
2550 flushed */
2551 if (dirty_flags == 0xff)
2552 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2553}
2554
David 'Digit' Turner36411062010-12-22 17:34:53 +01002555static CPUReadMemoryFunc * const error_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002556 NULL, /* never used */
2557 NULL, /* never used */
2558 NULL, /* never used */
2559};
2560
David 'Digit' Turner36411062010-12-22 17:34:53 +01002561static CPUWriteMemoryFunc * const notdirty_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002562 notdirty_mem_writeb,
2563 notdirty_mem_writew,
2564 notdirty_mem_writel,
2565};
2566
2567/* Generate a debug exception if a watchpoint has been hit. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002568static void check_watchpoint(int offset, int len_mask, int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002569{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002570 CPUOldState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002571 target_ulong pc, cs_base;
2572 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002573 target_ulong vaddr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002574 CPUWatchpoint *wp;
2575 int cpu_flags;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002576
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002577 if (env->watchpoint_hit) {
2578 /* We re-entered the check after replacing the TB. Now raise
2579 * the debug interrupt so that is will trigger after the
2580 * current instruction. */
2581 cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2582 return;
2583 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002584 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002585 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002586 if ((vaddr == (wp->vaddr & len_mask) ||
2587 (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
2588 wp->flags |= BP_WATCHPOINT_HIT;
2589 if (!env->watchpoint_hit) {
2590 env->watchpoint_hit = wp;
2591 tb = tb_find_pc(env->mem_io_pc);
2592 if (!tb) {
2593 cpu_abort(env, "check_watchpoint: could not find TB for "
2594 "pc=%p", (void *)env->mem_io_pc);
2595 }
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02002596 cpu_restore_state(tb, env, env->mem_io_pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002597 tb_phys_invalidate(tb, -1);
2598 if (wp->flags & BP_STOP_BEFORE_ACCESS) {
2599 env->exception_index = EXCP_DEBUG;
2600 } else {
2601 cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
2602 tb_gen_code(env, pc, cs_base, cpu_flags, 1);
2603 }
2604 cpu_resume_from_signal(env, NULL);
2605 }
2606 } else {
2607 wp->flags &= ~BP_WATCHPOINT_HIT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002608 }
2609 }
2610}
2611
2612/* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
2613 so these check for a hit then pass through to the normal out-of-line
2614 phys routines. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002615static uint32_t watch_mem_readb(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002616{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002617 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002618 return ldub_phys(addr);
2619}
2620
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002621static uint32_t watch_mem_readw(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002622{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002623 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002624 return lduw_phys(addr);
2625}
2626
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002627static uint32_t watch_mem_readl(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002628{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002629 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002630 return ldl_phys(addr);
2631}
2632
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002633static void watch_mem_writeb(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002634 uint32_t val)
2635{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002636 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002637 stb_phys(addr, val);
2638}
2639
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002640static void watch_mem_writew(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002641 uint32_t val)
2642{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002643 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002644 stw_phys(addr, val);
2645}
2646
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002647static void watch_mem_writel(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002648 uint32_t val)
2649{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002650 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002651 stl_phys(addr, val);
2652}
2653
David 'Digit' Turner36411062010-12-22 17:34:53 +01002654static CPUReadMemoryFunc * const watch_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002655 watch_mem_readb,
2656 watch_mem_readw,
2657 watch_mem_readl,
2658};
2659
David 'Digit' Turner36411062010-12-22 17:34:53 +01002660static CPUWriteMemoryFunc * const watch_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002661 watch_mem_writeb,
2662 watch_mem_writew,
2663 watch_mem_writel,
2664};
2665
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002666static inline uint32_t subpage_readlen (subpage_t *mmio, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002667 unsigned int len)
2668{
2669 uint32_t ret;
2670 unsigned int idx;
2671
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002672 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002673#if defined(DEBUG_SUBPAGE)
2674 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
2675 mmio, len, addr, idx);
2676#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002677 ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len],
2678 addr + mmio->region_offset[idx][0][len]);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002679
2680 return ret;
2681}
2682
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002683static inline void subpage_writelen (subpage_t *mmio, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002684 uint32_t value, unsigned int len)
2685{
2686 unsigned int idx;
2687
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002688 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002689#if defined(DEBUG_SUBPAGE)
2690 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
2691 mmio, len, addr, idx, value);
2692#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002693 (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len],
2694 addr + mmio->region_offset[idx][1][len],
2695 value);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002696}
2697
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002698static uint32_t subpage_readb (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002699{
2700#if defined(DEBUG_SUBPAGE)
2701 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2702#endif
2703
2704 return subpage_readlen(opaque, addr, 0);
2705}
2706
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002707static void subpage_writeb (void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002708 uint32_t value)
2709{
2710#if defined(DEBUG_SUBPAGE)
2711 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2712#endif
2713 subpage_writelen(opaque, addr, value, 0);
2714}
2715
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002716static uint32_t subpage_readw (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002717{
2718#if defined(DEBUG_SUBPAGE)
2719 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2720#endif
2721
2722 return subpage_readlen(opaque, addr, 1);
2723}
2724
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002725static void subpage_writew (void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002726 uint32_t value)
2727{
2728#if defined(DEBUG_SUBPAGE)
2729 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2730#endif
2731 subpage_writelen(opaque, addr, value, 1);
2732}
2733
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002734static uint32_t subpage_readl (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002735{
2736#if defined(DEBUG_SUBPAGE)
2737 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2738#endif
2739
2740 return subpage_readlen(opaque, addr, 2);
2741}
2742
2743static void subpage_writel (void *opaque,
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002744 hwaddr addr, uint32_t value)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002745{
2746#if defined(DEBUG_SUBPAGE)
2747 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2748#endif
2749 subpage_writelen(opaque, addr, value, 2);
2750}
2751
David 'Digit' Turner36411062010-12-22 17:34:53 +01002752static CPUReadMemoryFunc * const subpage_read[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002753 &subpage_readb,
2754 &subpage_readw,
2755 &subpage_readl,
2756};
2757
David 'Digit' Turner36411062010-12-22 17:34:53 +01002758static CPUWriteMemoryFunc * const subpage_write[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002759 &subpage_writeb,
2760 &subpage_writew,
2761 &subpage_writel,
2762};
2763
2764static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002765 ram_addr_t memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002766{
2767 int idx, eidx;
2768 unsigned int i;
2769
2770 if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
2771 return -1;
2772 idx = SUBPAGE_IDX(start);
2773 eidx = SUBPAGE_IDX(end);
2774#if defined(DEBUG_SUBPAGE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002775 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 -08002776 mmio, start, end, idx, eidx, memory);
2777#endif
2778 memory >>= IO_MEM_SHIFT;
2779 for (; idx <= eidx; idx++) {
2780 for (i = 0; i < 4; i++) {
2781 if (io_mem_read[memory][i]) {
2782 mmio->mem_read[idx][i] = &io_mem_read[memory][i];
2783 mmio->opaque[idx][0][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002784 mmio->region_offset[idx][0][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002785 }
2786 if (io_mem_write[memory][i]) {
2787 mmio->mem_write[idx][i] = &io_mem_write[memory][i];
2788 mmio->opaque[idx][1][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002789 mmio->region_offset[idx][1][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002790 }
2791 }
2792 }
2793
2794 return 0;
2795}
2796
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002797static void *subpage_init (hwaddr base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002798 ram_addr_t orig_memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002799{
2800 subpage_t *mmio;
2801 int subpage_memory;
2802
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002803 mmio = g_malloc0(sizeof(subpage_t));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002804
2805 mmio->base = base;
2806 subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002807#if defined(DEBUG_SUBPAGE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002808 printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
2809 mmio, base, TARGET_PAGE_SIZE, subpage_memory);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002810#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002811 *phys = subpage_memory | IO_MEM_SUBPAGE;
2812 subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
2813 region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002814
2815 return mmio;
2816}
2817
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002818static int get_free_io_mem_idx(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002819{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002820 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002821
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002822 for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
2823 if (!io_mem_used[i]) {
2824 io_mem_used[i] = 1;
2825 return i;
2826 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002827 fprintf(stderr, "RAN out out io_mem_idx, max %d !\n", IO_MEM_NB_ENTRIES);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002828 return -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002829}
2830
2831/* mem_read and mem_write are arrays of functions containing the
2832 function to access byte (index 0), word (index 1) and dword (index
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002833 2). Functions can be omitted with a NULL function pointer.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002834 If io_index is non zero, the corresponding io zone is
2835 modified. If it is zero, a new io zone is allocated. The return
2836 value can be used with cpu_register_physical_memory(). (-1) is
2837 returned if error. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002838static int cpu_register_io_memory_fixed(int io_index,
David 'Digit' Turner36411062010-12-22 17:34:53 +01002839 CPUReadMemoryFunc * const *mem_read,
2840 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002841 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002842{
2843 int i, subwidth = 0;
2844
2845 if (io_index <= 0) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002846 io_index = get_free_io_mem_idx();
2847 if (io_index == -1)
2848 return io_index;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002849 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002850 io_index >>= IO_MEM_SHIFT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002851 if (io_index >= IO_MEM_NB_ENTRIES)
2852 return -1;
2853 }
2854
2855 for(i = 0;i < 3; i++) {
2856 if (!mem_read[i] || !mem_write[i])
2857 subwidth = IO_MEM_SUBWIDTH;
2858 io_mem_read[io_index][i] = mem_read[i];
2859 io_mem_write[io_index][i] = mem_write[i];
2860 }
2861 io_mem_opaque[io_index] = opaque;
2862 return (io_index << IO_MEM_SHIFT) | subwidth;
2863}
2864
David 'Digit' Turner36411062010-12-22 17:34:53 +01002865int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
2866 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002867 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002868{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002869 return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002870}
2871
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002872void cpu_unregister_io_memory(int io_table_address)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002873{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002874 int i;
2875 int io_index = io_table_address >> IO_MEM_SHIFT;
2876
2877 for (i=0;i < 3; i++) {
2878 io_mem_read[io_index][i] = unassigned_mem_read[i];
2879 io_mem_write[io_index][i] = unassigned_mem_write[i];
2880 }
2881 io_mem_opaque[io_index] = NULL;
2882 io_mem_used[io_index] = 0;
2883}
2884
2885static void io_mem_init(void)
2886{
2887 int i;
2888
2889 cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read, unassigned_mem_write, NULL);
2890 cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read, unassigned_mem_write, NULL);
2891 cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read, notdirty_mem_write, NULL);
2892 for (i=0; i<5; i++)
2893 io_mem_used[i] = 1;
2894
2895 io_mem_watch = cpu_register_io_memory(watch_mem_read,
2896 watch_mem_write, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002897}
2898
2899#endif /* !defined(CONFIG_USER_ONLY) */
2900
2901/* physical memory access (slow version, mainly for debug) */
2902#if defined(CONFIG_USER_ONLY)
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002903void cpu_physical_memory_rw(hwaddr addr, void *buf,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002904 int len, int is_write)
2905{
2906 int l, flags;
2907 target_ulong page;
2908 void * p;
2909
2910 while (len > 0) {
2911 page = addr & TARGET_PAGE_MASK;
2912 l = (page + TARGET_PAGE_SIZE) - addr;
2913 if (l > len)
2914 l = len;
2915 flags = page_get_flags(page);
2916 if (!(flags & PAGE_VALID))
2917 return;
2918 if (is_write) {
2919 if (!(flags & PAGE_WRITE))
2920 return;
2921 /* XXX: this code should not depend on lock_user */
2922 if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
2923 /* FIXME - should this return an error rather than just fail? */
2924 return;
2925 memcpy(p, buf, l);
2926 unlock_user(p, addr, l);
2927 } else {
2928 if (!(flags & PAGE_READ))
2929 return;
2930 /* XXX: this code should not depend on lock_user */
2931 if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
2932 /* FIXME - should this return an error rather than just fail? */
2933 return;
2934 memcpy(buf, p, l);
2935 unlock_user(p, addr, 0);
2936 }
2937 len -= l;
2938 buf += l;
2939 addr += l;
2940 }
2941}
2942
2943#else
Pete Delaneyd09d7662013-03-28 19:53:13 -07002944
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002945static void invalidate_and_set_dirty(hwaddr addr,
2946 hwaddr length)
Pete Delaneyd09d7662013-03-28 19:53:13 -07002947{
2948 if (!cpu_physical_memory_is_dirty(addr)) {
2949 /* invalidate code */
2950 tb_invalidate_phys_page_range(addr, addr + length, 0);
2951 /* set dirty bit */
2952 cpu_physical_memory_set_dirty_flags(addr, (0xff & ~CODE_DIRTY_FLAG));
2953 }
2954}
2955
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002956void cpu_physical_memory_rw(hwaddr addr, void *buf,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002957 int len, int is_write)
2958{
2959 int l, io_index;
2960 uint8_t *ptr;
2961 uint32_t val;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002962 hwaddr page;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002963 unsigned long pd;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002964 uint8_t* buf8 = (uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002965 PhysPageDesc *p;
2966
2967 while (len > 0) {
2968 page = addr & TARGET_PAGE_MASK;
2969 l = (page + TARGET_PAGE_SIZE) - addr;
2970 if (l > len)
2971 l = len;
2972 p = phys_page_find(page >> TARGET_PAGE_BITS);
2973 if (!p) {
2974 pd = IO_MEM_UNASSIGNED;
2975 } else {
2976 pd = p->phys_offset;
2977 }
2978
2979 if (is_write) {
2980 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002981 hwaddr addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002982 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002983 if (p)
2984 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002985 /* XXX: could force cpu_single_env to NULL to avoid
2986 potential bugs */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002987 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002988 /* 32 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002989 val = ldl_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002990 io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002991 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002992 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002993 /* 16 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002994 val = lduw_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002995 io_mem_write[io_index][1](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002996 l = 2;
2997 } else {
2998 /* 8 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002999 val = ldub_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003000 io_mem_write[io_index][0](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003001 l = 1;
3002 }
3003 } else {
3004 unsigned long addr1;
3005 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3006 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003007 ptr = qemu_get_ram_ptr(addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003008 memcpy(ptr, buf8, l);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003009 invalidate_and_set_dirty(addr1, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003010 }
3011 } else {
3012 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3013 !(pd & IO_MEM_ROMD)) {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003014 hwaddr addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003015 /* I/O case */
3016 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003017 if (p)
3018 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3019 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003020 /* 32 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003021 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003022 stl_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003023 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003024 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003025 /* 16 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003026 val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003027 stw_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003028 l = 2;
3029 } else {
3030 /* 8 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003031 val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003032 stb_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003033 l = 1;
3034 }
3035 } else {
3036 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003037 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003038 (addr & ~TARGET_PAGE_MASK);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003039 memcpy(buf8, ptr, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003040 }
3041 }
3042 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003043 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003044 addr += l;
3045 }
3046}
3047
3048/* used for ROM loading : can write in RAM and ROM */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003049void cpu_physical_memory_write_rom(hwaddr addr,
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003050 const void *buf, int len)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003051{
3052 int l;
3053 uint8_t *ptr;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003054 hwaddr page;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003055 unsigned long pd;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003056 const uint8_t* buf8 = (const uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003057 PhysPageDesc *p;
3058
3059 while (len > 0) {
3060 page = addr & TARGET_PAGE_MASK;
3061 l = (page + TARGET_PAGE_SIZE) - addr;
3062 if (l > len)
3063 l = len;
3064 p = phys_page_find(page >> TARGET_PAGE_BITS);
3065 if (!p) {
3066 pd = IO_MEM_UNASSIGNED;
3067 } else {
3068 pd = p->phys_offset;
3069 }
3070
3071 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
3072 (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
3073 !(pd & IO_MEM_ROMD)) {
3074 /* do nothing */
3075 } else {
3076 unsigned long addr1;
3077 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3078 /* ROM/RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003079 ptr = qemu_get_ram_ptr(addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003080 memcpy(ptr, buf8, l);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003081 invalidate_and_set_dirty(addr1, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003082 }
3083 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003084 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003085 addr += l;
3086 }
3087}
3088
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003089typedef struct {
3090 void *buffer;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003091 hwaddr addr;
3092 hwaddr len;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003093} BounceBuffer;
3094
3095static BounceBuffer bounce;
3096
3097typedef struct MapClient {
3098 void *opaque;
3099 void (*callback)(void *opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003100 QLIST_ENTRY(MapClient) link;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003101} MapClient;
3102
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003103static QLIST_HEAD(map_client_list, MapClient) map_client_list
3104 = QLIST_HEAD_INITIALIZER(map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003105
3106void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
3107{
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01003108 MapClient *client = g_malloc(sizeof(*client));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003109
3110 client->opaque = opaque;
3111 client->callback = callback;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003112 QLIST_INSERT_HEAD(&map_client_list, client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003113 return client;
3114}
3115
3116void cpu_unregister_map_client(void *_client)
3117{
3118 MapClient *client = (MapClient *)_client;
3119
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003120 QLIST_REMOVE(client, link);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01003121 g_free(client);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003122}
3123
3124static void cpu_notify_map_clients(void)
3125{
3126 MapClient *client;
3127
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003128 while (!QLIST_EMPTY(&map_client_list)) {
3129 client = QLIST_FIRST(&map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003130 client->callback(client->opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003131 QLIST_REMOVE(client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003132 }
3133}
3134
3135/* Map a physical memory region into a host virtual address.
3136 * May map a subset of the requested range, given by and returned in *plen.
3137 * May return NULL if resources needed to perform the mapping are exhausted.
3138 * Use only for reads OR writes - not for read-modify-write operations.
3139 * Use cpu_register_map_client() to know when retrying the map operation is
3140 * likely to succeed.
3141 */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003142void *cpu_physical_memory_map(hwaddr addr,
3143 hwaddr *plen,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003144 int is_write)
3145{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003146 hwaddr len = *plen;
3147 hwaddr done = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003148 int l;
3149 uint8_t *ret = NULL;
3150 uint8_t *ptr;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003151 hwaddr page;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003152 unsigned long pd;
3153 PhysPageDesc *p;
3154 unsigned long addr1;
3155
3156 while (len > 0) {
3157 page = addr & TARGET_PAGE_MASK;
3158 l = (page + TARGET_PAGE_SIZE) - addr;
3159 if (l > len)
3160 l = len;
3161 p = phys_page_find(page >> TARGET_PAGE_BITS);
3162 if (!p) {
3163 pd = IO_MEM_UNASSIGNED;
3164 } else {
3165 pd = p->phys_offset;
3166 }
3167
3168 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3169 if (done || bounce.buffer) {
3170 break;
3171 }
3172 bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
3173 bounce.addr = addr;
3174 bounce.len = l;
3175 if (!is_write) {
3176 cpu_physical_memory_rw(addr, bounce.buffer, l, 0);
3177 }
3178 ptr = bounce.buffer;
3179 } else {
3180 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3181 ptr = qemu_get_ram_ptr(addr1);
3182 }
3183 if (!done) {
3184 ret = ptr;
3185 } else if (ret + done != ptr) {
3186 break;
3187 }
3188
3189 len -= l;
3190 addr += l;
3191 done += l;
3192 }
3193 *plen = done;
3194 return ret;
3195}
3196
3197/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
3198 * Will also mark the memory as dirty if is_write == 1. access_len gives
3199 * the amount of memory that was actually read or written by the caller.
3200 */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003201void cpu_physical_memory_unmap(void *buffer, hwaddr len,
3202 int is_write, hwaddr access_len)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003203{
3204 if (buffer != bounce.buffer) {
3205 if (is_write) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003206 ram_addr_t addr1 = qemu_ram_addr_from_host_nofail(buffer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003207 while (access_len) {
3208 unsigned l;
3209 l = TARGET_PAGE_SIZE;
3210 if (l > access_len)
3211 l = access_len;
Pete Delaneyd09d7662013-03-28 19:53:13 -07003212 invalidate_and_set_dirty(addr1, l);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003213 addr1 += l;
3214 access_len -= l;
3215 }
3216 }
3217 return;
3218 }
3219 if (is_write) {
3220 cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
3221 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003222 qemu_vfree(bounce.buffer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003223 bounce.buffer = NULL;
3224 cpu_notify_map_clients();
3225}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003226
3227/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003228uint32_t ldl_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003229{
3230 int io_index;
3231 uint8_t *ptr;
3232 uint32_t val;
3233 unsigned long pd;
3234 PhysPageDesc *p;
3235
3236 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3237 if (!p) {
3238 pd = IO_MEM_UNASSIGNED;
3239 } else {
3240 pd = p->phys_offset;
3241 }
3242
3243 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3244 !(pd & IO_MEM_ROMD)) {
3245 /* I/O case */
3246 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003247 if (p)
3248 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003249 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3250 } else {
3251 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003252 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003253 (addr & ~TARGET_PAGE_MASK);
3254 val = ldl_p(ptr);
3255 }
3256 return val;
3257}
3258
3259/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003260uint64_t ldq_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003261{
3262 int io_index;
3263 uint8_t *ptr;
3264 uint64_t val;
3265 unsigned long pd;
3266 PhysPageDesc *p;
3267
3268 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3269 if (!p) {
3270 pd = IO_MEM_UNASSIGNED;
3271 } else {
3272 pd = p->phys_offset;
3273 }
3274
3275 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3276 !(pd & IO_MEM_ROMD)) {
3277 /* I/O case */
3278 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003279 if (p)
3280 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003281#ifdef TARGET_WORDS_BIGENDIAN
3282 val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
3283 val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
3284#else
3285 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3286 val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
3287#endif
3288 } else {
3289 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003290 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003291 (addr & ~TARGET_PAGE_MASK);
3292 val = ldq_p(ptr);
3293 }
3294 return val;
3295}
3296
3297/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003298uint32_t ldub_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003299{
3300 uint8_t val;
3301 cpu_physical_memory_read(addr, &val, 1);
3302 return val;
3303}
3304
3305/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003306uint32_t lduw_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003307{
3308 uint16_t val;
3309 cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
3310 return tswap16(val);
3311}
3312
3313/* warning: addr must be aligned. The ram page is not masked as dirty
3314 and the code inside is not invalidated. It is useful if the dirty
3315 bits are used to track modified PTEs */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003316void stl_phys_notdirty(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003317{
3318 int io_index;
3319 uint8_t *ptr;
3320 unsigned long pd;
3321 PhysPageDesc *p;
3322
3323 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3324 if (!p) {
3325 pd = IO_MEM_UNASSIGNED;
3326 } else {
3327 pd = p->phys_offset;
3328 }
3329
3330 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3331 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003332 if (p)
3333 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003334 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3335 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003336 unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3337 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003338 stl_p(ptr, val);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003339
3340 if (unlikely(in_migration)) {
3341 if (!cpu_physical_memory_is_dirty(addr1)) {
3342 /* invalidate code */
3343 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3344 /* set dirty bit */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003345 cpu_physical_memory_set_dirty_flags(
3346 addr1, (0xff & ~CODE_DIRTY_FLAG));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003347 }
3348 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003349 }
3350}
3351
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003352void stq_phys_notdirty(hwaddr addr, uint64_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003353{
3354 int io_index;
3355 uint8_t *ptr;
3356 unsigned long pd;
3357 PhysPageDesc *p;
3358
3359 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3360 if (!p) {
3361 pd = IO_MEM_UNASSIGNED;
3362 } else {
3363 pd = p->phys_offset;
3364 }
3365
3366 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3367 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003368 if (p)
3369 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003370#ifdef TARGET_WORDS_BIGENDIAN
3371 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
3372 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
3373#else
3374 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3375 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
3376#endif
3377 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003378 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003379 (addr & ~TARGET_PAGE_MASK);
3380 stq_p(ptr, val);
3381 }
3382}
3383
3384/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003385void stl_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003386{
3387 int io_index;
3388 uint8_t *ptr;
3389 unsigned long pd;
3390 PhysPageDesc *p;
3391
3392 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3393 if (!p) {
3394 pd = IO_MEM_UNASSIGNED;
3395 } else {
3396 pd = p->phys_offset;
3397 }
3398
3399 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3400 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003401 if (p)
3402 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003403 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3404 } else {
3405 unsigned long addr1;
3406 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3407 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003408 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003409 stl_p(ptr, val);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003410 invalidate_and_set_dirty(addr1, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003411 }
3412}
3413
3414/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003415void stb_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003416{
3417 uint8_t v = val;
3418 cpu_physical_memory_write(addr, &v, 1);
3419}
3420
3421/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003422void stw_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003423{
3424 uint16_t v = tswap16(val);
3425 cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
3426}
3427
3428/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003429void stq_phys(hwaddr addr, uint64_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003430{
3431 val = tswap64(val);
3432 cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
3433}
3434
3435#endif
3436
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003437/* virtual memory access for debug (includes writing to ROM) */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003438int cpu_memory_rw_debug(CPUOldState *env, target_ulong addr,
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003439 void *buf, int len, int is_write)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003440{
3441 int l;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003442 hwaddr phys_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003443 target_ulong page;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003444 uint8_t* buf8 = (uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003445
3446 while (len > 0) {
3447 page = addr & TARGET_PAGE_MASK;
3448 phys_addr = cpu_get_phys_page_debug(env, page);
3449 /* if no physical page mapped, return an error */
3450 if (phys_addr == -1)
3451 return -1;
3452 l = (page + TARGET_PAGE_SIZE) - addr;
3453 if (l > len)
3454 l = len;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003455 phys_addr += (addr & ~TARGET_PAGE_MASK);
3456#if !defined(CONFIG_USER_ONLY)
3457 if (is_write)
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003458 cpu_physical_memory_write_rom(phys_addr, buf8, l);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003459 else
3460#endif
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003461 cpu_physical_memory_rw(phys_addr, buf8, l, is_write);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003462 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003463 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003464 addr += l;
3465 }
3466 return 0;
3467}
3468
3469/* in deterministic execution mode, instructions doing device I/Os
3470 must be at the end of the TB */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01003471void cpu_io_recompile(CPUArchState *env, void *retaddr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003472{
3473 TranslationBlock *tb;
3474 uint32_t n, cflags;
3475 target_ulong pc, cs_base;
3476 uint64_t flags;
3477
3478 tb = tb_find_pc((unsigned long)retaddr);
3479 if (!tb) {
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02003480 cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003481 retaddr);
3482 }
3483 n = env->icount_decr.u16.low + tb->icount;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02003484 cpu_restore_state(tb, env, (unsigned long)retaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003485 /* Calculate how many instructions had been executed before the fault
3486 occurred. */
3487 n = n - env->icount_decr.u16.low;
3488 /* Generate a new TB ending on the I/O insn. */
3489 n++;
3490 /* On MIPS and SH, delay slot instructions can only be restarted if
3491 they were already the first instruction in the TB. If this is not
3492 the first instruction in a TB then re-execute the preceding
3493 branch. */
3494#if defined(TARGET_MIPS)
3495 if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) {
3496 env->active_tc.PC -= 4;
3497 env->icount_decr.u16.low++;
3498 env->hflags &= ~MIPS_HFLAG_BMASK;
3499 }
3500#elif defined(TARGET_SH4)
3501 if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
3502 && n > 1) {
3503 env->pc -= 2;
3504 env->icount_decr.u16.low++;
3505 env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
3506 }
3507#endif
3508 /* This should never happen. */
3509 if (n > CF_COUNT_MASK)
3510 cpu_abort(env, "TB too big during recompile");
3511
3512 cflags = n | CF_LAST_IO;
3513 pc = tb->pc;
3514 cs_base = tb->cs_base;
3515 flags = tb->flags;
3516 tb_phys_invalidate(tb, -1);
3517 /* FIXME: In theory this could raise an exception. In practice
3518 we have already translated the block once so it's probably ok. */
3519 tb_gen_code(env, pc, cs_base, flags, cflags);
3520 /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
3521 the first in the TB) then we end up generating a whole new TB and
3522 repeating the fault, which is horribly inefficient.
3523 Better would be to execute just this insn uncached, or generate a
3524 second new TB. */
3525 cpu_resume_from_signal(env, NULL);
3526}
3527
David 'Digit' Turner36411062010-12-22 17:34:53 +01003528#if !defined(CONFIG_USER_ONLY)
3529
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003530void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003531{
3532 int i, target_code_size, max_target_code_size;
3533 int direct_jmp_count, direct_jmp2_count, cross_page;
3534 TranslationBlock *tb;
3535
3536 target_code_size = 0;
3537 max_target_code_size = 0;
3538 cross_page = 0;
3539 direct_jmp_count = 0;
3540 direct_jmp2_count = 0;
3541 for(i = 0; i < nb_tbs; i++) {
3542 tb = &tbs[i];
3543 target_code_size += tb->size;
3544 if (tb->size > max_target_code_size)
3545 max_target_code_size = tb->size;
3546 if (tb->page_addr[1] != -1)
3547 cross_page++;
3548 if (tb->tb_next_offset[0] != 0xffff) {
3549 direct_jmp_count++;
3550 if (tb->tb_next_offset[1] != 0xffff) {
3551 direct_jmp2_count++;
3552 }
3553 }
3554 }
3555 /* XXX: avoid using doubles ? */
3556 cpu_fprintf(f, "Translation buffer state:\n");
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003557 cpu_fprintf(f, "gen code size %td/%ld\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003558 code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02003559 cpu_fprintf(f, "TB count %d/%d\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003560 nb_tbs, code_gen_max_blocks);
3561 cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
3562 nb_tbs ? target_code_size / nb_tbs : 0,
3563 max_target_code_size);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003564 cpu_fprintf(f, "TB avg host size %td bytes (expansion ratio: %0.1f)\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003565 nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
3566 target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
3567 cpu_fprintf(f, "cross page TB count %d (%d%%)\n",
3568 cross_page,
3569 nb_tbs ? (cross_page * 100) / nb_tbs : 0);
3570 cpu_fprintf(f, "direct jump count %d (%d%%) (2 jumps=%d %d%%)\n",
3571 direct_jmp_count,
3572 nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
3573 direct_jmp2_count,
3574 nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
3575 cpu_fprintf(f, "\nStatistics:\n");
3576 cpu_fprintf(f, "TB flush count %d\n", tb_flush_count);
3577 cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
3578 cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count);
3579 tcg_dump_info(f, cpu_fprintf);
3580}
3581
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003582#endif