blob: 2f44aa46059bb0a615f64a696ecfafd3bf42d5b6 [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
David 'Digit' Turner85c62202014-02-16 20:53:40 +0100752void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800753{
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
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001329#if defined(CONFIG_USER_ONLY)
1330void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
1331
1332{
1333}
1334
1335int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
1336 int flags, CPUWatchpoint **watchpoint)
1337{
1338 return -ENOSYS;
1339}
1340#else
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001341/* Add a watchpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001342int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001343 int flags, CPUWatchpoint **watchpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001344{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001345 target_ulong len_mask = ~(len - 1);
1346 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001347
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001348 /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001349 if ((len & (len - 1)) || (addr & ~len_mask) ||
1350 len == 0 || len > TARGET_PAGE_SIZE) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001351 fprintf(stderr, "qemu: tried to set invalid watchpoint at "
1352 TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
1353 return -EINVAL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001354 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001355 wp = g_malloc(sizeof(*wp));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001356
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001357 wp->vaddr = addr;
1358 wp->len_mask = len_mask;
1359 wp->flags = flags;
1360
1361 /* keep all GDB-injected watchpoints in front */
1362 if (flags & BP_GDB)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001363 QTAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001364 else
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001365 QTAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001366
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001367 tlb_flush_page(env, addr);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001368
1369 if (watchpoint)
1370 *watchpoint = wp;
1371 return 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001372}
1373
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001374/* Remove a specific watchpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001375int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, target_ulong len,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001376 int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001377{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001378 target_ulong len_mask = ~(len - 1);
1379 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001380
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001381 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001382 if (addr == wp->vaddr && len_mask == wp->len_mask
1383 && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
1384 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001385 return 0;
1386 }
1387 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001388 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001389}
1390
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001391/* Remove a specific watchpoint by reference. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001392void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001393{
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001394 QTAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001395
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001396 tlb_flush_page(env, watchpoint->vaddr);
1397
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001398 g_free(watchpoint);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001399}
1400
1401/* Remove all matching watchpoints. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001402void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001403{
1404 CPUWatchpoint *wp, *next;
1405
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001406 QTAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001407 if (wp->flags & mask)
1408 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001409 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001410}
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001411#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001412
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001413/* Add a breakpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001414int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001415 CPUBreakpoint **breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001416{
1417#if defined(TARGET_HAS_ICE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001418 CPUBreakpoint *bp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001419
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001420 bp = g_malloc(sizeof(*bp));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001421
1422 bp->pc = pc;
1423 bp->flags = flags;
1424
1425 /* keep all GDB-injected breakpoints in front */
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001426 if (flags & BP_GDB) {
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001427 QTAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001428 } else {
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001429 QTAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001430 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001431
1432 breakpoint_invalidate(env, pc);
1433
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001434 if (breakpoint) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001435 *breakpoint = bp;
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001436 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001437 return 0;
1438#else
1439 return -ENOSYS;
1440#endif
1441}
1442
1443/* Remove a specific breakpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001444int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001445{
1446#if defined(TARGET_HAS_ICE)
1447 CPUBreakpoint *bp;
1448
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001449 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001450 if (bp->pc == pc && bp->flags == flags) {
1451 cpu_breakpoint_remove_by_ref(env, bp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001452 return 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001453 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001454 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001455 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001456#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001457 return -ENOSYS;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001458#endif
1459}
1460
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001461/* Remove a specific breakpoint by reference. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001462void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001463{
1464#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001465 QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001466
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001467 breakpoint_invalidate(env, breakpoint->pc);
1468
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001469 g_free(breakpoint);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001470#endif
1471}
1472
1473/* Remove all matching breakpoints. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001474void cpu_breakpoint_remove_all(CPUArchState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001475{
1476#if defined(TARGET_HAS_ICE)
1477 CPUBreakpoint *bp, *next;
1478
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001479 QTAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001480 if (bp->flags & mask)
1481 cpu_breakpoint_remove_by_ref(env, bp);
1482 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001483#endif
1484}
1485
1486/* enable or disable single step mode. EXCP_DEBUG is returned by the
1487 CPU loop after each instruction */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001488void cpu_single_step(CPUOldState *env, int enabled)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001489{
1490#if defined(TARGET_HAS_ICE)
1491 if (env->singlestep_enabled != enabled) {
1492 env->singlestep_enabled = enabled;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001493 if (kvm_enabled())
1494 kvm_update_guest_debug(env, 0);
1495 else {
1496 /* must flush all the translated code to avoid inconsistencies */
1497 /* XXX: only flush what is necessary */
1498 tb_flush(env);
1499 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001500 }
1501#endif
1502}
1503
1504/* enable or disable low levels log */
1505void cpu_set_log(int log_flags)
1506{
1507 loglevel = log_flags;
1508 if (loglevel && !logfile) {
1509 logfile = fopen(logfilename, log_append ? "a" : "w");
1510 if (!logfile) {
1511 perror(logfilename);
Iliyan Malchev4a2c9dd2012-04-02 08:20:56 -07001512 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001513 }
1514#if !defined(CONFIG_SOFTMMU)
1515 /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1516 {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001517 static char logfile_buf[4096];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001518 setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1519 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001520#elif !defined(_WIN32)
1521 /* Win32 doesn't support line-buffering and requires size >= 2 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001522 setvbuf(logfile, NULL, _IOLBF, 0);
1523#endif
1524 log_append = 1;
1525 }
1526 if (!loglevel && logfile) {
1527 fclose(logfile);
1528 logfile = NULL;
1529 }
1530}
1531
1532void cpu_set_log_filename(const char *filename)
1533{
1534 logfilename = strdup(filename);
1535 if (logfile) {
1536 fclose(logfile);
1537 logfile = NULL;
1538 }
1539 cpu_set_log(loglevel);
1540}
1541
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001542static void cpu_unlink_tb(CPUOldState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001543{
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001544 /* FIXME: TB unchaining isn't SMP safe. For now just ignore the
1545 problem and hope the cpu will stop of its own accord. For userspace
1546 emulation this often isn't actually as bad as it sounds. Often
1547 signals are used primarily to interrupt blocking syscalls. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001548 TranslationBlock *tb;
1549 static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
1550
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001551 spin_lock(&interrupt_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001552 tb = env->current_tb;
1553 /* if the cpu is currently executing code, we must unlink it and
1554 all the potentially executing TB */
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001555 if (tb) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001556 env->current_tb = NULL;
1557 tb_reset_jump_recursive(tb);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001558 }
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001559 spin_unlock(&interrupt_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001560}
1561
1562/* mask must never be zero, except for A20 change call */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001563void cpu_interrupt(CPUOldState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001564{
1565 int old_mask;
1566
1567 old_mask = env->interrupt_request;
1568 env->interrupt_request |= mask;
1569
1570#ifndef CONFIG_USER_ONLY
1571 /*
1572 * If called from iothread context, wake the target cpu in
1573 * case its halted.
1574 */
1575 if (!qemu_cpu_self(env)) {
1576 qemu_cpu_kick(env);
1577 return;
1578 }
1579#endif
1580
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001581 if (use_icount) {
1582 env->icount_decr.u16.high = 0xffff;
1583#ifndef CONFIG_USER_ONLY
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001584 if (!can_do_io(env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001585 && (mask & ~old_mask) != 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001586 cpu_abort(env, "Raised interrupt while not in I/O function");
1587 }
1588#endif
1589 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001590 cpu_unlink_tb(env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001591 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001592}
1593
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001594void cpu_reset_interrupt(CPUOldState *env, int mask)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001595{
1596 env->interrupt_request &= ~mask;
1597}
1598
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001599void cpu_exit(CPUOldState *env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001600{
1601 env->exit_request = 1;
1602 cpu_unlink_tb(env);
1603}
1604
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001605void cpu_abort(CPUArchState *env, const char *fmt, ...)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001606{
1607 va_list ap;
1608 va_list ap2;
1609
1610 va_start(ap, fmt);
1611 va_copy(ap2, ap);
1612 fprintf(stderr, "qemu: fatal: ");
1613 vfprintf(stderr, fmt, ap);
1614 fprintf(stderr, "\n");
1615#ifdef TARGET_I386
1616 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1617#else
1618 cpu_dump_state(env, stderr, fprintf, 0);
1619#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001620 if (qemu_log_enabled()) {
1621 qemu_log("qemu: fatal: ");
1622 qemu_log_vprintf(fmt, ap2);
1623 qemu_log("\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001624#ifdef TARGET_I386
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001625 log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001626#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001627 log_cpu_state(env, 0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001628#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001629 qemu_log_flush();
1630 qemu_log_close();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001631 }
1632 va_end(ap2);
1633 va_end(ap);
David 'Digit' Turner36411062010-12-22 17:34:53 +01001634#if defined(CONFIG_USER_ONLY)
1635 {
1636 struct sigaction act;
1637 sigfillset(&act.sa_mask);
1638 act.sa_handler = SIG_DFL;
1639 sigaction(SIGABRT, &act, NULL);
1640 }
1641#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001642 abort();
1643}
1644
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001645CPUArchState *cpu_copy(CPUOldState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001646{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001647 CPUArchState *new_env = cpu_init(env->cpu_model_str);
1648 CPUArchState *next_cpu = new_env->next_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001649 int cpu_index = new_env->cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001650#if defined(TARGET_HAS_ICE)
1651 CPUBreakpoint *bp;
1652 CPUWatchpoint *wp;
1653#endif
1654
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001655 memcpy(new_env, env, sizeof(CPUOldState));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001656
1657 /* Preserve chaining and index. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001658 new_env->next_cpu = next_cpu;
1659 new_env->cpu_index = cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001660
1661 /* Clone all break/watchpoints.
1662 Note: Once we support ptrace with hw-debug register access, make sure
1663 BP_CPU break/watchpoints are handled correctly on clone. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001664 QTAILQ_INIT(&env->breakpoints);
1665 QTAILQ_INIT(&env->watchpoints);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001666#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001667 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001668 cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
1669 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001670 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001671 cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
1672 wp->flags, NULL);
1673 }
1674#endif
1675
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001676 return new_env;
1677}
1678
1679#if !defined(CONFIG_USER_ONLY)
1680
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001681/* Note: start and end must be within the same ram block. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001682void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
1683 int dirty_flags)
1684{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001685 CPUOldState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001686 unsigned long length, start1;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001687 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001688
1689 start &= TARGET_PAGE_MASK;
1690 end = TARGET_PAGE_ALIGN(end);
1691
1692 length = end - start;
1693 if (length == 0)
1694 return;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001695 cpu_physical_memory_mask_dirty_range(start, length, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001696
1697 /* we modify the TLB cache so that the dirty bit will be set again
1698 when accessing the range */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001699 start1 = (unsigned long)qemu_safe_ram_ptr(start);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001700 /* Chek that we don't span multiple blocks - this breaks the
1701 address comparisons below. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001702 if ((unsigned long)qemu_safe_ram_ptr(end - 1) - start1
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001703 != (end - 1) - start) {
1704 abort();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001705 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001706
1707 for(env = first_cpu; env != NULL; env = env->next_cpu) {
1708 int mmu_idx;
1709 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1710 for(i = 0; i < CPU_TLB_SIZE; i++)
1711 tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
1712 start1, length);
1713 }
1714 }
1715}
1716
1717int cpu_physical_memory_set_dirty_tracking(int enable)
1718{
1719 in_migration = enable;
1720 if (kvm_enabled()) {
1721 return kvm_set_migration_log(enable);
1722 }
1723 return 0;
1724}
1725
1726int cpu_physical_memory_get_dirty_tracking(void)
1727{
1728 return in_migration;
1729}
1730
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001731int cpu_physical_sync_dirty_bitmap(hwaddr start_addr,
1732 hwaddr end_addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001733{
1734 int ret = 0;
1735
1736 if (kvm_enabled())
1737 ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
1738 return ret;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001739}
1740
1741static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1742{
1743 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001744 void *p;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001745
1746 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001747 p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
1748 + tlb_entry->addend);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001749 ram_addr = qemu_ram_addr_from_host_nofail(p);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001750 if (!cpu_physical_memory_is_dirty(ram_addr)) {
1751 tlb_entry->addr_write |= TLB_NOTDIRTY;
1752 }
1753 }
1754}
1755
1756/* update the TLB according to the current state of the dirty bits */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001757void cpu_tlb_update_dirty(CPUArchState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001758{
1759 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001760 int mmu_idx;
1761 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1762 for(i = 0; i < CPU_TLB_SIZE; i++)
1763 tlb_update_dirty(&env->tlb_table[mmu_idx][i]);
1764 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001765}
1766
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001767
1768#else
1769
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001770void tlb_flush(CPUArchState *env, int flush_global)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001771{
1772}
1773
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001774void tlb_flush_page(CPUArchState *env, target_ulong addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001775{
1776}
1777
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001778int tlb_set_page_exec(CPUArchState *env, target_ulong vaddr,
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001779 hwaddr paddr, int prot,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001780 int mmu_idx, int is_softmmu)
1781{
1782 return 0;
1783}
1784
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001785/*
1786 * Walks guest process memory "regions" one by one
1787 * and calls callback function 'fn' for each region.
1788 */
1789int walk_memory_regions(void *priv,
1790 int (*fn)(void *, unsigned long, unsigned long, unsigned long))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001791{
1792 unsigned long start, end;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001793 PageDesc *p = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001794 int i, j, prot, prot1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001795 int rc = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001796
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001797 start = end = -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001798 prot = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001799
1800 for (i = 0; i <= L1_SIZE; i++) {
1801 p = (i < L1_SIZE) ? l1_map[i] : NULL;
1802 for (j = 0; j < L2_SIZE; j++) {
1803 prot1 = (p == NULL) ? 0 : p[j].flags;
1804 /*
1805 * "region" is one continuous chunk of memory
1806 * that has same protection flags set.
1807 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001808 if (prot1 != prot) {
1809 end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
1810 if (start != -1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001811 rc = (*fn)(priv, start, end, prot);
1812 /* callback can stop iteration by returning != 0 */
1813 if (rc != 0)
1814 return (rc);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001815 }
1816 if (prot1 != 0)
1817 start = end;
1818 else
1819 start = -1;
1820 prot = prot1;
1821 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001822 if (p == NULL)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001823 break;
1824 }
1825 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001826 return (rc);
1827}
1828
1829static int dump_region(void *priv, unsigned long start,
1830 unsigned long end, unsigned long prot)
1831{
1832 FILE *f = (FILE *)priv;
1833
1834 (void) fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
1835 start, end, end - start,
1836 ((prot & PAGE_READ) ? 'r' : '-'),
1837 ((prot & PAGE_WRITE) ? 'w' : '-'),
1838 ((prot & PAGE_EXEC) ? 'x' : '-'));
1839
1840 return (0);
1841}
1842
1843/* dump memory mappings */
1844void page_dump(FILE *f)
1845{
1846 (void) fprintf(f, "%-8s %-8s %-8s %s\n",
1847 "start", "end", "size", "prot");
1848 walk_memory_regions(f, dump_region);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001849}
1850
1851int page_get_flags(target_ulong address)
1852{
1853 PageDesc *p;
1854
1855 p = page_find(address >> TARGET_PAGE_BITS);
1856 if (!p)
1857 return 0;
1858 return p->flags;
1859}
1860
David 'Digit' Turner36411062010-12-22 17:34:53 +01001861/* Modify the flags of a page and invalidate the code if necessary.
1862 The flag PAGE_WRITE_ORG is positioned automatically depending
1863 on PAGE_WRITE. The mmap_lock should already be held. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001864void page_set_flags(target_ulong start, target_ulong end, int flags)
1865{
1866 PageDesc *p;
1867 target_ulong addr;
1868
1869 /* mmap_lock should already be held. */
1870 start = start & TARGET_PAGE_MASK;
1871 end = TARGET_PAGE_ALIGN(end);
1872 if (flags & PAGE_WRITE)
1873 flags |= PAGE_WRITE_ORG;
1874 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1875 p = page_find_alloc(addr >> TARGET_PAGE_BITS);
1876 /* We may be called for host regions that are outside guest
1877 address space. */
1878 if (!p)
1879 return;
1880 /* if the write protection is set, then we invalidate the code
1881 inside */
1882 if (!(p->flags & PAGE_WRITE) &&
1883 (flags & PAGE_WRITE) &&
1884 p->first_tb) {
1885 tb_invalidate_phys_page(addr, 0, NULL);
1886 }
1887 p->flags = flags;
1888 }
1889}
1890
1891int page_check_range(target_ulong start, target_ulong len, int flags)
1892{
1893 PageDesc *p;
1894 target_ulong end;
1895 target_ulong addr;
1896
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001897 if (start + len < start)
1898 /* we've wrapped around */
1899 return -1;
1900
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001901 end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
1902 start = start & TARGET_PAGE_MASK;
1903
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001904 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1905 p = page_find(addr >> TARGET_PAGE_BITS);
1906 if( !p )
1907 return -1;
1908 if( !(p->flags & PAGE_VALID) )
1909 return -1;
1910
1911 if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
1912 return -1;
1913 if (flags & PAGE_WRITE) {
1914 if (!(p->flags & PAGE_WRITE_ORG))
1915 return -1;
1916 /* unprotect the page if it was put read-only because it
1917 contains translated code */
1918 if (!(p->flags & PAGE_WRITE)) {
1919 if (!page_unprotect(addr, 0, NULL))
1920 return -1;
1921 }
1922 return 0;
1923 }
1924 }
1925 return 0;
1926}
1927
1928/* called from signal handler: invalidate the code and unprotect the
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001929 page. Return TRUE if the fault was successfully handled. */
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001930int page_unprotect(target_ulong address, uintptr_t pc, void *puc)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001931{
1932 unsigned int page_index, prot, pindex;
1933 PageDesc *p, *p1;
1934 target_ulong host_start, host_end, addr;
1935
1936 /* Technically this isn't safe inside a signal handler. However we
1937 know this only ever happens in a synchronous SEGV handler, so in
1938 practice it seems to be ok. */
1939 mmap_lock();
1940
1941 host_start = address & qemu_host_page_mask;
1942 page_index = host_start >> TARGET_PAGE_BITS;
1943 p1 = page_find(page_index);
1944 if (!p1) {
1945 mmap_unlock();
1946 return 0;
1947 }
1948 host_end = host_start + qemu_host_page_size;
1949 p = p1;
1950 prot = 0;
1951 for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
1952 prot |= p->flags;
1953 p++;
1954 }
1955 /* if the page was really writable, then we change its
1956 protection back to writable */
1957 if (prot & PAGE_WRITE_ORG) {
1958 pindex = (address - host_start) >> TARGET_PAGE_BITS;
1959 if (!(p1[pindex].flags & PAGE_WRITE)) {
1960 mprotect((void *)g2h(host_start), qemu_host_page_size,
1961 (prot & PAGE_BITS) | PAGE_WRITE);
1962 p1[pindex].flags |= PAGE_WRITE;
1963 /* and since the content will be modified, we must invalidate
1964 the corresponding translated code. */
1965 tb_invalidate_phys_page(address, pc, puc);
1966#ifdef DEBUG_TB_CHECK
1967 tb_invalidate_check(address);
1968#endif
1969 mmap_unlock();
1970 return 1;
1971 }
1972 }
1973 mmap_unlock();
1974 return 0;
1975}
1976
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001977static inline void tlb_set_dirty(CPUOldState *env,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001978 unsigned long addr, target_ulong vaddr)
1979{
1980}
1981#endif /* defined(CONFIG_USER_ONLY) */
1982
1983#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001984
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001985static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001986 ram_addr_t memory, ram_addr_t region_offset);
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001987static void *subpage_init (hwaddr base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001988 ram_addr_t orig_memory, ram_addr_t region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001989#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
1990 need_subpage) \
1991 do { \
1992 if (addr > start_addr) \
1993 start_addr2 = 0; \
1994 else { \
1995 start_addr2 = start_addr & ~TARGET_PAGE_MASK; \
1996 if (start_addr2 > 0) \
1997 need_subpage = 1; \
1998 } \
1999 \
2000 if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE) \
2001 end_addr2 = TARGET_PAGE_SIZE - 1; \
2002 else { \
2003 end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
2004 if (end_addr2 < TARGET_PAGE_SIZE - 1) \
2005 need_subpage = 1; \
2006 } \
2007 } while (0)
2008
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002009/* register physical memory.
2010 For RAM, 'size' must be a multiple of the target page size.
2011 If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002012 io memory page. The address used when calling the IO function is
2013 the offset from the start of the region, plus region_offset. Both
2014 start_addr and region_offset are rounded down to a page boundary
2015 before calculating this offset. This should not be a problem unless
2016 the low bits of start_addr and region_offset differ. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002017void cpu_register_physical_memory_log(hwaddr start_addr,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002018 ram_addr_t size,
2019 ram_addr_t phys_offset,
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002020 ram_addr_t region_offset,
2021 bool log_dirty)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002022{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002023 hwaddr addr, end_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002024 PhysPageDesc *p;
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002025 CPUOldState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002026 ram_addr_t orig_size = size;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002027 subpage_t *subpage;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002028
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002029 if (kvm_enabled())
2030 kvm_set_phys_mem(start_addr, size, phys_offset);
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002031#ifdef CONFIG_HAX
2032 if (hax_enabled())
2033 hax_set_phys_mem(start_addr, size, phys_offset);
2034#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002035
2036 if (phys_offset == IO_MEM_UNASSIGNED) {
2037 region_offset = start_addr;
2038 }
2039 region_offset &= TARGET_PAGE_MASK;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002040 size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002041 end_addr = start_addr + (hwaddr)size;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002042
2043 addr = start_addr;
2044 do {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002045 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2046 if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
2047 ram_addr_t orig_memory = p->phys_offset;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002048 hwaddr start_addr2, end_addr2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002049 int need_subpage = 0;
2050
2051 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2052 need_subpage);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002053 if (need_subpage) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002054 if (!(orig_memory & IO_MEM_SUBPAGE)) {
2055 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002056 &p->phys_offset, orig_memory,
2057 p->region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002058 } else {
2059 subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
2060 >> IO_MEM_SHIFT];
2061 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002062 subpage_register(subpage, start_addr2, end_addr2, phys_offset,
2063 region_offset);
2064 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002065 } else {
2066 p->phys_offset = phys_offset;
2067 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2068 (phys_offset & IO_MEM_ROMD))
2069 phys_offset += TARGET_PAGE_SIZE;
2070 }
2071 } else {
2072 p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2073 p->phys_offset = phys_offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002074 p->region_offset = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002075 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002076 (phys_offset & IO_MEM_ROMD)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002077 phys_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002078 } else {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002079 hwaddr start_addr2, end_addr2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002080 int need_subpage = 0;
2081
2082 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2083 end_addr2, need_subpage);
2084
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002085 if (need_subpage) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002086 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002087 &p->phys_offset, IO_MEM_UNASSIGNED,
2088 addr & TARGET_PAGE_MASK);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002089 subpage_register(subpage, start_addr2, end_addr2,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002090 phys_offset, region_offset);
2091 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002092 }
2093 }
2094 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002095 region_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002096 addr += TARGET_PAGE_SIZE;
2097 } while (addr != end_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002098
2099 /* since each CPU stores ram addresses in its TLB cache, we must
2100 reset the modified entries */
2101 /* XXX: slow ! */
2102 for(env = first_cpu; env != NULL; env = env->next_cpu) {
2103 tlb_flush(env, 1);
2104 }
2105}
2106
2107/* XXX: temporary until new memory mapping API */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002108ram_addr_t cpu_get_physical_page_desc(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002109{
2110 PhysPageDesc *p;
2111
2112 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2113 if (!p)
2114 return IO_MEM_UNASSIGNED;
2115 return p->phys_offset;
2116}
2117
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002118void qemu_register_coalesced_mmio(hwaddr addr, ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002119{
2120 if (kvm_enabled())
2121 kvm_coalesce_mmio_region(addr, size);
2122}
2123
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002124void qemu_unregister_coalesced_mmio(hwaddr addr, ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002125{
2126 if (kvm_enabled())
2127 kvm_uncoalesce_mmio_region(addr, size);
2128}
2129
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002130static ram_addr_t find_ram_offset(ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002131{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002132 RAMBlock *block, *next_block;
2133 ram_addr_t offset = 0, mingap = ULONG_MAX;
2134
2135 if (QLIST_EMPTY(&ram_list.blocks))
2136 return 0;
2137
2138 QLIST_FOREACH(block, &ram_list.blocks, next) {
2139 ram_addr_t end, next = ULONG_MAX;
2140
2141 end = block->offset + block->length;
2142
2143 QLIST_FOREACH(next_block, &ram_list.blocks, next) {
2144 if (next_block->offset >= end) {
2145 next = MIN(next, next_block->offset);
2146 }
2147 }
2148 if (next - end >= size && next - end < mingap) {
2149 offset = end;
2150 mingap = next - end;
2151 }
2152 }
2153 return offset;
2154}
2155
2156static ram_addr_t last_ram_offset(void)
2157{
2158 RAMBlock *block;
2159 ram_addr_t last = 0;
2160
2161 QLIST_FOREACH(block, &ram_list.blocks, next)
2162 last = MAX(last, block->offset + block->length);
2163
2164 return last;
2165}
2166
2167ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
2168 ram_addr_t size, void *host)
2169{
2170 RAMBlock *new_block, *block;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002171
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002172 size = TARGET_PAGE_ALIGN(size);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002173 new_block = g_malloc0(sizeof(*new_block));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002174
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002175#if 0
2176 if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
2177 char *id = dev->parent_bus->info->get_dev_path(dev);
2178 if (id) {
2179 snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002180 g_free(id);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002181 }
2182 }
2183#endif
2184 pstrcat(new_block->idstr, sizeof(new_block->idstr), name);
2185
2186 QLIST_FOREACH(block, &ram_list.blocks, next) {
2187 if (!strcmp(block->idstr, new_block->idstr)) {
2188 fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n",
2189 new_block->idstr);
2190 abort();
2191 }
2192 }
2193
2194 if (host) {
2195 new_block->host = host;
2196 new_block->flags |= RAM_PREALLOC_MASK;
2197 } else {
2198 if (mem_path) {
2199#if 0 && defined (__linux__) && !defined(TARGET_S390X)
2200 new_block->host = file_ram_alloc(new_block, size, mem_path);
2201 if (!new_block->host) {
2202 new_block->host = qemu_vmalloc(size);
2203 qemu_madvise(new_block->host, size, QEMU_MADV_MERGEABLE);
2204 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002205#else
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002206 fprintf(stderr, "-mem-path option unsupported\n");
2207 exit(1);
2208#endif
2209 } else {
2210#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2211 /* XXX S390 KVM requires the topmost vma of the RAM to be < 256GB */
2212 new_block->host = mmap((void*)0x1000000, size,
2213 PROT_EXEC|PROT_READ|PROT_WRITE,
2214 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
2215#else
2216 new_block->host = qemu_vmalloc(size);
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002217
2218#ifdef CONFIG_HAX
2219 /*
2220 * In HAX, qemu allocates the virtual address, and HAX kernel
2221 * module populates the region with physical memory. Currently
2222 * we don’t populate guest memory on demand, thus we should
2223 * make sure that sufficient amount of memory is available in
2224 * advance.
2225 */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002226 if (hax_enabled()) {
2227 int ret = hax_populate_ram(
2228 (uint64_t)(uintptr_t)new_block->host,
2229 size);
2230 if (ret < 0) {
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002231 fprintf(stderr, "Hax failed to populate ram\n");
2232 exit(-1);
2233 }
2234 }
2235#endif
2236
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002237#endif
2238#ifdef MADV_MERGEABLE
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002239 madvise(new_block->host, size, MADV_MERGEABLE);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002240#endif
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002241 }
2242 }
2243
2244 new_block->offset = find_ram_offset(size);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002245 new_block->length = size;
2246
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002247 QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002248
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002249 ram_list.phys_dirty = g_realloc(ram_list.phys_dirty,
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002250 last_ram_offset() >> TARGET_PAGE_BITS);
2251 memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002252 0xff, size >> TARGET_PAGE_BITS);
2253
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002254 if (kvm_enabled())
2255 kvm_setup_guest_memory(new_block->host, size);
2256
2257 return new_block->offset;
2258}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002259
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002260ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
2261{
2262 return qemu_ram_alloc_from_ptr(dev, name, size, NULL);
2263}
2264
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002265void qemu_ram_free(ram_addr_t addr)
2266{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002267 RAMBlock *block;
2268
2269 QLIST_FOREACH(block, &ram_list.blocks, next) {
2270 if (addr == block->offset) {
2271 QLIST_REMOVE(block, next);
2272 if (block->flags & RAM_PREALLOC_MASK) {
2273 ;
2274 } else if (mem_path) {
2275#if defined (__linux__) && !defined(TARGET_S390X)
2276 if (block->fd) {
2277 munmap(block->host, block->length);
2278 close(block->fd);
2279 } else {
2280 qemu_vfree(block->host);
2281 }
2282#else
2283 abort();
2284#endif
2285 } else {
2286#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2287 munmap(block->host, block->length);
2288#else
2289 qemu_vfree(block->host);
2290#endif
2291 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002292 g_free(block);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002293 return;
2294 }
2295 }
2296
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002297}
2298
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002299#ifndef _WIN32
2300void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
2301{
2302#ifndef CONFIG_ANDROID
2303 RAMBlock *block;
2304 ram_addr_t offset;
2305 int flags;
2306 void *area, *vaddr;
2307
2308 QLIST_FOREACH(block, &ram_list.blocks, next) {
2309 offset = addr - block->offset;
2310 if (offset < block->length) {
2311 vaddr = block->host + offset;
2312 if (block->flags & RAM_PREALLOC_MASK) {
2313 ;
2314 } else {
2315 flags = MAP_FIXED;
2316 munmap(vaddr, length);
2317 if (mem_path) {
2318#if defined(__linux__) && !defined(TARGET_S390X)
2319 if (block->fd) {
2320#ifdef MAP_POPULATE
2321 flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED :
2322 MAP_PRIVATE;
2323#else
2324 flags |= MAP_PRIVATE;
2325#endif
2326 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2327 flags, block->fd, offset);
2328 } else {
2329 flags |= MAP_PRIVATE | MAP_ANONYMOUS;
2330 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2331 flags, -1, 0);
2332 }
2333#else
2334 abort();
2335#endif
2336 } else {
2337#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2338 flags |= MAP_SHARED | MAP_ANONYMOUS;
2339 area = mmap(vaddr, length, PROT_EXEC|PROT_READ|PROT_WRITE,
2340 flags, -1, 0);
2341#else
2342 flags |= MAP_PRIVATE | MAP_ANONYMOUS;
2343 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2344 flags, -1, 0);
2345#endif
2346 }
2347 if (area != vaddr) {
2348 fprintf(stderr, "Could not remap addr: %lx@%lx\n",
2349 length, addr);
2350 exit(1);
2351 }
2352 qemu_madvise(vaddr, length, QEMU_MADV_MERGEABLE);
2353 }
2354 return;
2355 }
2356 }
2357#endif /* !CONFIG_ANDROID */
2358}
2359#endif /* !_WIN32 */
2360
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002361/* Return a host pointer to ram allocated with qemu_ram_alloc.
2362 With the exception of the softmmu code in this file, this should
2363 only be used for local memory (e.g. video ram) that the device owns,
2364 and knows it isn't going to access beyond the end of the block.
2365
2366 It should not be used for general purpose DMA.
2367 Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
2368 */
2369void *qemu_get_ram_ptr(ram_addr_t addr)
2370{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002371 RAMBlock *block;
2372
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002373 QLIST_FOREACH(block, &ram_list.blocks, next) {
2374 if (addr - block->offset < block->length) {
2375 /* Move this entry to to start of the list. */
2376 if (block != QLIST_FIRST(&ram_list.blocks)) {
2377 QLIST_REMOVE(block, next);
2378 QLIST_INSERT_HEAD(&ram_list.blocks, block, next);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002379 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002380 return block->host + (addr - block->offset);
2381 }
2382 }
2383
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002384 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2385 abort();
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002386
2387 return NULL;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002388 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002389
2390/* Return a host pointer to ram allocated with qemu_ram_alloc.
2391 * Same as qemu_get_ram_ptr but avoid reordering ramblocks.
2392 */
2393void *qemu_safe_ram_ptr(ram_addr_t addr)
2394{
2395 RAMBlock *block;
2396
2397 QLIST_FOREACH(block, &ram_list.blocks, next) {
2398 if (addr - block->offset < block->length) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002399 return block->host + (addr - block->offset);
2400}
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002401 }
2402
2403 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2404 abort();
2405
2406 return NULL;
2407}
2408
2409int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
2410{
2411 RAMBlock *block;
2412 uint8_t *host = ptr;
2413
2414 QLIST_FOREACH(block, &ram_list.blocks, next) {
2415 if (host - block->host < block->length) {
2416 *ram_addr = block->offset + (host - block->host);
2417 return 0;
2418 }
2419 }
2420 return -1;
2421}
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002422
2423/* Some of the softmmu routines need to translate from a host pointer
2424 (typically a TLB entry) back to a ram offset. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002425ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002426{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002427 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002428
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002429 if (qemu_ram_addr_from_host(ptr, &ram_addr)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002430 fprintf(stderr, "Bad ram pointer %p\n", ptr);
2431 abort();
2432 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002433 return ram_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002434}
2435
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002436static uint32_t unassigned_mem_readb(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002437{
2438#ifdef DEBUG_UNASSIGNED
2439 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2440#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002441#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002442 do_unassigned_access(addr, 0, 0, 0, 1);
2443#endif
2444 return 0;
2445}
2446
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002447static uint32_t unassigned_mem_readw(void *opaque, hwaddr addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002448{
2449#ifdef DEBUG_UNASSIGNED
2450 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2451#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002452#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002453 do_unassigned_access(addr, 0, 0, 0, 2);
2454#endif
2455 return 0;
2456}
2457
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002458static uint32_t unassigned_mem_readl(void *opaque, hwaddr addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002459{
2460#ifdef DEBUG_UNASSIGNED
2461 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2462#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002463#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002464 do_unassigned_access(addr, 0, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002465#endif
2466 return 0;
2467}
2468
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002469static void unassigned_mem_writeb(void *opaque, hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002470{
2471#ifdef DEBUG_UNASSIGNED
2472 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2473#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002474#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002475 do_unassigned_access(addr, 1, 0, 0, 1);
2476#endif
2477}
2478
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002479static void unassigned_mem_writew(void *opaque, hwaddr addr, uint32_t val)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002480{
2481#ifdef DEBUG_UNASSIGNED
2482 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2483#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002484#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002485 do_unassigned_access(addr, 1, 0, 0, 2);
2486#endif
2487}
2488
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002489static void unassigned_mem_writel(void *opaque, hwaddr addr, uint32_t val)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002490{
2491#ifdef DEBUG_UNASSIGNED
2492 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2493#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002494#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002495 do_unassigned_access(addr, 1, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002496#endif
2497}
2498
David 'Digit' Turner36411062010-12-22 17:34:53 +01002499static CPUReadMemoryFunc * const unassigned_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002500 unassigned_mem_readb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002501 unassigned_mem_readw,
2502 unassigned_mem_readl,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002503};
2504
David 'Digit' Turner36411062010-12-22 17:34:53 +01002505static CPUWriteMemoryFunc * const unassigned_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002506 unassigned_mem_writeb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002507 unassigned_mem_writew,
2508 unassigned_mem_writel,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002509};
2510
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002511static void notdirty_mem_writeb(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002512 uint32_t val)
2513{
2514 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002515 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002516 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2517#if !defined(CONFIG_USER_ONLY)
2518 tb_invalidate_phys_page_fast(ram_addr, 1);
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#endif
2521 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002522 stb_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002523 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002524 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002525 /* we remove the notdirty callback only if the code has been
2526 flushed */
2527 if (dirty_flags == 0xff)
2528 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2529}
2530
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002531static void notdirty_mem_writew(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002532 uint32_t val)
2533{
2534 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002535 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002536 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2537#if !defined(CONFIG_USER_ONLY)
2538 tb_invalidate_phys_page_fast(ram_addr, 2);
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#endif
2541 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002542 stw_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002543 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002544 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002545 /* we remove the notdirty callback only if the code has been
2546 flushed */
2547 if (dirty_flags == 0xff)
2548 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2549}
2550
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002551static void notdirty_mem_writel(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002552 uint32_t val)
2553{
2554 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002555 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002556 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2557#if !defined(CONFIG_USER_ONLY)
2558 tb_invalidate_phys_page_fast(ram_addr, 4);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002559 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002560#endif
2561 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002562 stl_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002563 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002564 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002565 /* we remove the notdirty callback only if the code has been
2566 flushed */
2567 if (dirty_flags == 0xff)
2568 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2569}
2570
David 'Digit' Turner36411062010-12-22 17:34:53 +01002571static CPUReadMemoryFunc * const error_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002572 NULL, /* never used */
2573 NULL, /* never used */
2574 NULL, /* never used */
2575};
2576
David 'Digit' Turner36411062010-12-22 17:34:53 +01002577static CPUWriteMemoryFunc * const notdirty_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002578 notdirty_mem_writeb,
2579 notdirty_mem_writew,
2580 notdirty_mem_writel,
2581};
2582
2583/* Generate a debug exception if a watchpoint has been hit. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002584static void check_watchpoint(int offset, int len_mask, int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002585{
David 'Digit' Turner85c62202014-02-16 20:53:40 +01002586 CPUArchState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002587 target_ulong pc, cs_base;
2588 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002589 target_ulong vaddr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002590 CPUWatchpoint *wp;
2591 int cpu_flags;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002592
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002593 if (env->watchpoint_hit) {
2594 /* We re-entered the check after replacing the TB. Now raise
2595 * the debug interrupt so that is will trigger after the
2596 * current instruction. */
2597 cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2598 return;
2599 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002600 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002601 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002602 if ((vaddr == (wp->vaddr & len_mask) ||
2603 (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
2604 wp->flags |= BP_WATCHPOINT_HIT;
2605 if (!env->watchpoint_hit) {
2606 env->watchpoint_hit = wp;
2607 tb = tb_find_pc(env->mem_io_pc);
2608 if (!tb) {
2609 cpu_abort(env, "check_watchpoint: could not find TB for "
2610 "pc=%p", (void *)env->mem_io_pc);
2611 }
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02002612 cpu_restore_state(tb, env, env->mem_io_pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002613 tb_phys_invalidate(tb, -1);
2614 if (wp->flags & BP_STOP_BEFORE_ACCESS) {
2615 env->exception_index = EXCP_DEBUG;
David 'Digit' Turner85c62202014-02-16 20:53:40 +01002616 cpu_loop_exit(env);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002617 } else {
2618 cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
2619 tb_gen_code(env, pc, cs_base, cpu_flags, 1);
David 'Digit' Turner85c62202014-02-16 20:53:40 +01002620 cpu_resume_from_signal(env, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002621 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002622 }
2623 } else {
2624 wp->flags &= ~BP_WATCHPOINT_HIT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002625 }
2626 }
2627}
2628
2629/* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
2630 so these check for a hit then pass through to the normal out-of-line
2631 phys routines. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002632static uint32_t watch_mem_readb(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002633{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002634 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002635 return ldub_phys(addr);
2636}
2637
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002638static uint32_t watch_mem_readw(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002639{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002640 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002641 return lduw_phys(addr);
2642}
2643
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002644static uint32_t watch_mem_readl(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002645{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002646 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002647 return ldl_phys(addr);
2648}
2649
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002650static void watch_mem_writeb(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002651 uint32_t val)
2652{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002653 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002654 stb_phys(addr, val);
2655}
2656
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002657static void watch_mem_writew(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002658 uint32_t val)
2659{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002660 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002661 stw_phys(addr, val);
2662}
2663
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002664static void watch_mem_writel(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002665 uint32_t val)
2666{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002667 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002668 stl_phys(addr, val);
2669}
2670
David 'Digit' Turner36411062010-12-22 17:34:53 +01002671static CPUReadMemoryFunc * const watch_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002672 watch_mem_readb,
2673 watch_mem_readw,
2674 watch_mem_readl,
2675};
2676
David 'Digit' Turner36411062010-12-22 17:34:53 +01002677static CPUWriteMemoryFunc * const watch_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002678 watch_mem_writeb,
2679 watch_mem_writew,
2680 watch_mem_writel,
2681};
2682
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002683static inline uint32_t subpage_readlen (subpage_t *mmio, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002684 unsigned int len)
2685{
2686 uint32_t ret;
2687 unsigned int idx;
2688
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002689 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002690#if defined(DEBUG_SUBPAGE)
2691 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
2692 mmio, len, addr, idx);
2693#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002694 ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len],
2695 addr + mmio->region_offset[idx][0][len]);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002696
2697 return ret;
2698}
2699
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002700static inline void subpage_writelen (subpage_t *mmio, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002701 uint32_t value, unsigned int len)
2702{
2703 unsigned int idx;
2704
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002705 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002706#if defined(DEBUG_SUBPAGE)
2707 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
2708 mmio, len, addr, idx, value);
2709#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002710 (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len],
2711 addr + mmio->region_offset[idx][1][len],
2712 value);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002713}
2714
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002715static uint32_t subpage_readb (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002716{
2717#if defined(DEBUG_SUBPAGE)
2718 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2719#endif
2720
2721 return subpage_readlen(opaque, addr, 0);
2722}
2723
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002724static void subpage_writeb (void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002725 uint32_t value)
2726{
2727#if defined(DEBUG_SUBPAGE)
2728 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2729#endif
2730 subpage_writelen(opaque, addr, value, 0);
2731}
2732
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002733static uint32_t subpage_readw (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002734{
2735#if defined(DEBUG_SUBPAGE)
2736 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2737#endif
2738
2739 return subpage_readlen(opaque, addr, 1);
2740}
2741
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002742static void subpage_writew (void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002743 uint32_t value)
2744{
2745#if defined(DEBUG_SUBPAGE)
2746 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2747#endif
2748 subpage_writelen(opaque, addr, value, 1);
2749}
2750
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002751static uint32_t subpage_readl (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002752{
2753#if defined(DEBUG_SUBPAGE)
2754 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2755#endif
2756
2757 return subpage_readlen(opaque, addr, 2);
2758}
2759
2760static void subpage_writel (void *opaque,
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002761 hwaddr addr, uint32_t value)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002762{
2763#if defined(DEBUG_SUBPAGE)
2764 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2765#endif
2766 subpage_writelen(opaque, addr, value, 2);
2767}
2768
David 'Digit' Turner36411062010-12-22 17:34:53 +01002769static CPUReadMemoryFunc * const subpage_read[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002770 &subpage_readb,
2771 &subpage_readw,
2772 &subpage_readl,
2773};
2774
David 'Digit' Turner36411062010-12-22 17:34:53 +01002775static CPUWriteMemoryFunc * const subpage_write[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002776 &subpage_writeb,
2777 &subpage_writew,
2778 &subpage_writel,
2779};
2780
2781static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002782 ram_addr_t memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002783{
2784 int idx, eidx;
2785 unsigned int i;
2786
2787 if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
2788 return -1;
2789 idx = SUBPAGE_IDX(start);
2790 eidx = SUBPAGE_IDX(end);
2791#if defined(DEBUG_SUBPAGE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002792 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 -08002793 mmio, start, end, idx, eidx, memory);
2794#endif
2795 memory >>= IO_MEM_SHIFT;
2796 for (; idx <= eidx; idx++) {
2797 for (i = 0; i < 4; i++) {
2798 if (io_mem_read[memory][i]) {
2799 mmio->mem_read[idx][i] = &io_mem_read[memory][i];
2800 mmio->opaque[idx][0][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002801 mmio->region_offset[idx][0][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002802 }
2803 if (io_mem_write[memory][i]) {
2804 mmio->mem_write[idx][i] = &io_mem_write[memory][i];
2805 mmio->opaque[idx][1][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002806 mmio->region_offset[idx][1][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002807 }
2808 }
2809 }
2810
2811 return 0;
2812}
2813
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002814static void *subpage_init (hwaddr base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002815 ram_addr_t orig_memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002816{
2817 subpage_t *mmio;
2818 int subpage_memory;
2819
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002820 mmio = g_malloc0(sizeof(subpage_t));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002821
2822 mmio->base = base;
2823 subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002824#if defined(DEBUG_SUBPAGE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002825 printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
2826 mmio, base, TARGET_PAGE_SIZE, subpage_memory);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002827#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002828 *phys = subpage_memory | IO_MEM_SUBPAGE;
2829 subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
2830 region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002831
2832 return mmio;
2833}
2834
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002835static int get_free_io_mem_idx(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002836{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002837 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002838
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002839 for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
2840 if (!io_mem_used[i]) {
2841 io_mem_used[i] = 1;
2842 return i;
2843 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002844 fprintf(stderr, "RAN out out io_mem_idx, max %d !\n", IO_MEM_NB_ENTRIES);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002845 return -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002846}
2847
2848/* mem_read and mem_write are arrays of functions containing the
2849 function to access byte (index 0), word (index 1) and dword (index
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002850 2). Functions can be omitted with a NULL function pointer.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002851 If io_index is non zero, the corresponding io zone is
2852 modified. If it is zero, a new io zone is allocated. The return
2853 value can be used with cpu_register_physical_memory(). (-1) is
2854 returned if error. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002855static int cpu_register_io_memory_fixed(int io_index,
David 'Digit' Turner36411062010-12-22 17:34:53 +01002856 CPUReadMemoryFunc * const *mem_read,
2857 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002858 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002859{
2860 int i, subwidth = 0;
2861
2862 if (io_index <= 0) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002863 io_index = get_free_io_mem_idx();
2864 if (io_index == -1)
2865 return io_index;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002866 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002867 io_index >>= IO_MEM_SHIFT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002868 if (io_index >= IO_MEM_NB_ENTRIES)
2869 return -1;
2870 }
2871
2872 for(i = 0;i < 3; i++) {
2873 if (!mem_read[i] || !mem_write[i])
2874 subwidth = IO_MEM_SUBWIDTH;
2875 io_mem_read[io_index][i] = mem_read[i];
2876 io_mem_write[io_index][i] = mem_write[i];
2877 }
2878 io_mem_opaque[io_index] = opaque;
2879 return (io_index << IO_MEM_SHIFT) | subwidth;
2880}
2881
David 'Digit' Turner36411062010-12-22 17:34:53 +01002882int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
2883 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002884 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002885{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002886 return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002887}
2888
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002889void cpu_unregister_io_memory(int io_table_address)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002890{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002891 int i;
2892 int io_index = io_table_address >> IO_MEM_SHIFT;
2893
2894 for (i=0;i < 3; i++) {
2895 io_mem_read[io_index][i] = unassigned_mem_read[i];
2896 io_mem_write[io_index][i] = unassigned_mem_write[i];
2897 }
2898 io_mem_opaque[io_index] = NULL;
2899 io_mem_used[io_index] = 0;
2900}
2901
2902static void io_mem_init(void)
2903{
2904 int i;
2905
2906 cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read, unassigned_mem_write, NULL);
2907 cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read, unassigned_mem_write, NULL);
2908 cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read, notdirty_mem_write, NULL);
2909 for (i=0; i<5; i++)
2910 io_mem_used[i] = 1;
2911
2912 io_mem_watch = cpu_register_io_memory(watch_mem_read,
2913 watch_mem_write, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002914}
2915
2916#endif /* !defined(CONFIG_USER_ONLY) */
2917
2918/* physical memory access (slow version, mainly for debug) */
2919#if defined(CONFIG_USER_ONLY)
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002920void cpu_physical_memory_rw(hwaddr addr, void *buf,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002921 int len, int is_write)
2922{
2923 int l, flags;
2924 target_ulong page;
2925 void * p;
2926
2927 while (len > 0) {
2928 page = addr & TARGET_PAGE_MASK;
2929 l = (page + TARGET_PAGE_SIZE) - addr;
2930 if (l > len)
2931 l = len;
2932 flags = page_get_flags(page);
2933 if (!(flags & PAGE_VALID))
2934 return;
2935 if (is_write) {
2936 if (!(flags & PAGE_WRITE))
2937 return;
2938 /* XXX: this code should not depend on lock_user */
2939 if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
2940 /* FIXME - should this return an error rather than just fail? */
2941 return;
2942 memcpy(p, buf, l);
2943 unlock_user(p, addr, l);
2944 } else {
2945 if (!(flags & PAGE_READ))
2946 return;
2947 /* XXX: this code should not depend on lock_user */
2948 if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
2949 /* FIXME - should this return an error rather than just fail? */
2950 return;
2951 memcpy(buf, p, l);
2952 unlock_user(p, addr, 0);
2953 }
2954 len -= l;
2955 buf += l;
2956 addr += l;
2957 }
2958}
2959
2960#else
Pete Delaneyd09d7662013-03-28 19:53:13 -07002961
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002962static void invalidate_and_set_dirty(hwaddr addr,
2963 hwaddr length)
Pete Delaneyd09d7662013-03-28 19:53:13 -07002964{
2965 if (!cpu_physical_memory_is_dirty(addr)) {
2966 /* invalidate code */
2967 tb_invalidate_phys_page_range(addr, addr + length, 0);
2968 /* set dirty bit */
2969 cpu_physical_memory_set_dirty_flags(addr, (0xff & ~CODE_DIRTY_FLAG));
2970 }
2971}
2972
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002973void cpu_physical_memory_rw(hwaddr addr, void *buf,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002974 int len, int is_write)
2975{
2976 int l, io_index;
2977 uint8_t *ptr;
2978 uint32_t val;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002979 hwaddr page;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002980 unsigned long pd;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002981 uint8_t* buf8 = (uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002982 PhysPageDesc *p;
2983
2984 while (len > 0) {
2985 page = addr & TARGET_PAGE_MASK;
2986 l = (page + TARGET_PAGE_SIZE) - addr;
2987 if (l > len)
2988 l = len;
2989 p = phys_page_find(page >> TARGET_PAGE_BITS);
2990 if (!p) {
2991 pd = IO_MEM_UNASSIGNED;
2992 } else {
2993 pd = p->phys_offset;
2994 }
2995
2996 if (is_write) {
2997 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002998 hwaddr addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002999 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003000 if (p)
3001 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003002 /* XXX: could force cpu_single_env to NULL to avoid
3003 potential bugs */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003004 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003005 /* 32 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003006 val = ldl_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003007 io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003008 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003009 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003010 /* 16 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003011 val = lduw_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003012 io_mem_write[io_index][1](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003013 l = 2;
3014 } else {
3015 /* 8 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003016 val = ldub_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003017 io_mem_write[io_index][0](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003018 l = 1;
3019 }
3020 } else {
3021 unsigned long addr1;
3022 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3023 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003024 ptr = qemu_get_ram_ptr(addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003025 memcpy(ptr, buf8, l);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003026 invalidate_and_set_dirty(addr1, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003027 }
3028 } else {
3029 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3030 !(pd & IO_MEM_ROMD)) {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003031 hwaddr addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003032 /* I/O case */
3033 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003034 if (p)
3035 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3036 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003037 /* 32 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003038 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003039 stl_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003040 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003041 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003042 /* 16 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003043 val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003044 stw_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003045 l = 2;
3046 } else {
3047 /* 8 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003048 val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003049 stb_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003050 l = 1;
3051 }
3052 } else {
3053 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003054 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003055 (addr & ~TARGET_PAGE_MASK);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003056 memcpy(buf8, ptr, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003057 }
3058 }
3059 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003060 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003061 addr += l;
3062 }
3063}
3064
3065/* used for ROM loading : can write in RAM and ROM */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003066void cpu_physical_memory_write_rom(hwaddr addr,
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003067 const void *buf, int len)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003068{
3069 int l;
3070 uint8_t *ptr;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003071 hwaddr page;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003072 unsigned long pd;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003073 const uint8_t* buf8 = (const uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003074 PhysPageDesc *p;
3075
3076 while (len > 0) {
3077 page = addr & TARGET_PAGE_MASK;
3078 l = (page + TARGET_PAGE_SIZE) - addr;
3079 if (l > len)
3080 l = len;
3081 p = phys_page_find(page >> TARGET_PAGE_BITS);
3082 if (!p) {
3083 pd = IO_MEM_UNASSIGNED;
3084 } else {
3085 pd = p->phys_offset;
3086 }
3087
3088 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
3089 (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
3090 !(pd & IO_MEM_ROMD)) {
3091 /* do nothing */
3092 } else {
3093 unsigned long addr1;
3094 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3095 /* ROM/RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003096 ptr = qemu_get_ram_ptr(addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003097 memcpy(ptr, buf8, l);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003098 invalidate_and_set_dirty(addr1, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003099 }
3100 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003101 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003102 addr += l;
3103 }
3104}
3105
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003106typedef struct {
3107 void *buffer;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003108 hwaddr addr;
3109 hwaddr len;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003110} BounceBuffer;
3111
3112static BounceBuffer bounce;
3113
3114typedef struct MapClient {
3115 void *opaque;
3116 void (*callback)(void *opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003117 QLIST_ENTRY(MapClient) link;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003118} MapClient;
3119
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003120static QLIST_HEAD(map_client_list, MapClient) map_client_list
3121 = QLIST_HEAD_INITIALIZER(map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003122
3123void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
3124{
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01003125 MapClient *client = g_malloc(sizeof(*client));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003126
3127 client->opaque = opaque;
3128 client->callback = callback;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003129 QLIST_INSERT_HEAD(&map_client_list, client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003130 return client;
3131}
3132
3133void cpu_unregister_map_client(void *_client)
3134{
3135 MapClient *client = (MapClient *)_client;
3136
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003137 QLIST_REMOVE(client, link);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01003138 g_free(client);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003139}
3140
3141static void cpu_notify_map_clients(void)
3142{
3143 MapClient *client;
3144
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003145 while (!QLIST_EMPTY(&map_client_list)) {
3146 client = QLIST_FIRST(&map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003147 client->callback(client->opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003148 QLIST_REMOVE(client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003149 }
3150}
3151
3152/* Map a physical memory region into a host virtual address.
3153 * May map a subset of the requested range, given by and returned in *plen.
3154 * May return NULL if resources needed to perform the mapping are exhausted.
3155 * Use only for reads OR writes - not for read-modify-write operations.
3156 * Use cpu_register_map_client() to know when retrying the map operation is
3157 * likely to succeed.
3158 */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003159void *cpu_physical_memory_map(hwaddr addr,
3160 hwaddr *plen,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003161 int is_write)
3162{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003163 hwaddr len = *plen;
3164 hwaddr done = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003165 int l;
3166 uint8_t *ret = NULL;
3167 uint8_t *ptr;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003168 hwaddr page;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003169 unsigned long pd;
3170 PhysPageDesc *p;
3171 unsigned long addr1;
3172
3173 while (len > 0) {
3174 page = addr & TARGET_PAGE_MASK;
3175 l = (page + TARGET_PAGE_SIZE) - addr;
3176 if (l > len)
3177 l = len;
3178 p = phys_page_find(page >> TARGET_PAGE_BITS);
3179 if (!p) {
3180 pd = IO_MEM_UNASSIGNED;
3181 } else {
3182 pd = p->phys_offset;
3183 }
3184
3185 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3186 if (done || bounce.buffer) {
3187 break;
3188 }
3189 bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
3190 bounce.addr = addr;
3191 bounce.len = l;
3192 if (!is_write) {
3193 cpu_physical_memory_rw(addr, bounce.buffer, l, 0);
3194 }
3195 ptr = bounce.buffer;
3196 } else {
3197 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3198 ptr = qemu_get_ram_ptr(addr1);
3199 }
3200 if (!done) {
3201 ret = ptr;
3202 } else if (ret + done != ptr) {
3203 break;
3204 }
3205
3206 len -= l;
3207 addr += l;
3208 done += l;
3209 }
3210 *plen = done;
3211 return ret;
3212}
3213
3214/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
3215 * Will also mark the memory as dirty if is_write == 1. access_len gives
3216 * the amount of memory that was actually read or written by the caller.
3217 */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003218void cpu_physical_memory_unmap(void *buffer, hwaddr len,
3219 int is_write, hwaddr access_len)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003220{
3221 if (buffer != bounce.buffer) {
3222 if (is_write) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003223 ram_addr_t addr1 = qemu_ram_addr_from_host_nofail(buffer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003224 while (access_len) {
3225 unsigned l;
3226 l = TARGET_PAGE_SIZE;
3227 if (l > access_len)
3228 l = access_len;
Pete Delaneyd09d7662013-03-28 19:53:13 -07003229 invalidate_and_set_dirty(addr1, l);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003230 addr1 += l;
3231 access_len -= l;
3232 }
3233 }
3234 return;
3235 }
3236 if (is_write) {
3237 cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
3238 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003239 qemu_vfree(bounce.buffer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003240 bounce.buffer = NULL;
3241 cpu_notify_map_clients();
3242}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003243
3244/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003245uint32_t ldl_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003246{
3247 int io_index;
3248 uint8_t *ptr;
3249 uint32_t val;
3250 unsigned long pd;
3251 PhysPageDesc *p;
3252
3253 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3254 if (!p) {
3255 pd = IO_MEM_UNASSIGNED;
3256 } else {
3257 pd = p->phys_offset;
3258 }
3259
3260 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3261 !(pd & IO_MEM_ROMD)) {
3262 /* I/O case */
3263 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003264 if (p)
3265 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003266 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3267 } else {
3268 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003269 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003270 (addr & ~TARGET_PAGE_MASK);
3271 val = ldl_p(ptr);
3272 }
3273 return val;
3274}
3275
3276/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003277uint64_t ldq_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003278{
3279 int io_index;
3280 uint8_t *ptr;
3281 uint64_t val;
3282 unsigned long pd;
3283 PhysPageDesc *p;
3284
3285 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3286 if (!p) {
3287 pd = IO_MEM_UNASSIGNED;
3288 } else {
3289 pd = p->phys_offset;
3290 }
3291
3292 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3293 !(pd & IO_MEM_ROMD)) {
3294 /* I/O case */
3295 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003296 if (p)
3297 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003298#ifdef TARGET_WORDS_BIGENDIAN
3299 val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
3300 val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
3301#else
3302 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3303 val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
3304#endif
3305 } else {
3306 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003307 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003308 (addr & ~TARGET_PAGE_MASK);
3309 val = ldq_p(ptr);
3310 }
3311 return val;
3312}
3313
3314/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003315uint32_t ldub_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003316{
3317 uint8_t val;
3318 cpu_physical_memory_read(addr, &val, 1);
3319 return val;
3320}
3321
3322/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003323uint32_t lduw_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003324{
3325 uint16_t val;
3326 cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
3327 return tswap16(val);
3328}
3329
3330/* warning: addr must be aligned. The ram page is not masked as dirty
3331 and the code inside is not invalidated. It is useful if the dirty
3332 bits are used to track modified PTEs */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003333void stl_phys_notdirty(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003334{
3335 int io_index;
3336 uint8_t *ptr;
3337 unsigned long pd;
3338 PhysPageDesc *p;
3339
3340 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3341 if (!p) {
3342 pd = IO_MEM_UNASSIGNED;
3343 } else {
3344 pd = p->phys_offset;
3345 }
3346
3347 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3348 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003349 if (p)
3350 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003351 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3352 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003353 unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3354 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003355 stl_p(ptr, val);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003356
3357 if (unlikely(in_migration)) {
3358 if (!cpu_physical_memory_is_dirty(addr1)) {
3359 /* invalidate code */
3360 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3361 /* set dirty bit */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003362 cpu_physical_memory_set_dirty_flags(
3363 addr1, (0xff & ~CODE_DIRTY_FLAG));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003364 }
3365 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003366 }
3367}
3368
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003369void stq_phys_notdirty(hwaddr addr, uint64_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003370{
3371 int io_index;
3372 uint8_t *ptr;
3373 unsigned long pd;
3374 PhysPageDesc *p;
3375
3376 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3377 if (!p) {
3378 pd = IO_MEM_UNASSIGNED;
3379 } else {
3380 pd = p->phys_offset;
3381 }
3382
3383 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3384 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003385 if (p)
3386 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003387#ifdef TARGET_WORDS_BIGENDIAN
3388 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
3389 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
3390#else
3391 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3392 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
3393#endif
3394 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003395 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003396 (addr & ~TARGET_PAGE_MASK);
3397 stq_p(ptr, val);
3398 }
3399}
3400
3401/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003402void stl_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003403{
3404 int io_index;
3405 uint8_t *ptr;
3406 unsigned long pd;
3407 PhysPageDesc *p;
3408
3409 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3410 if (!p) {
3411 pd = IO_MEM_UNASSIGNED;
3412 } else {
3413 pd = p->phys_offset;
3414 }
3415
3416 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3417 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003418 if (p)
3419 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003420 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3421 } else {
3422 unsigned long addr1;
3423 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3424 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003425 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003426 stl_p(ptr, val);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003427 invalidate_and_set_dirty(addr1, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003428 }
3429}
3430
3431/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003432void stb_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003433{
3434 uint8_t v = val;
3435 cpu_physical_memory_write(addr, &v, 1);
3436}
3437
3438/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003439void stw_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003440{
3441 uint16_t v = tswap16(val);
3442 cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
3443}
3444
3445/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003446void stq_phys(hwaddr addr, uint64_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003447{
3448 val = tswap64(val);
3449 cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
3450}
3451
3452#endif
3453
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003454/* virtual memory access for debug (includes writing to ROM) */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003455int cpu_memory_rw_debug(CPUOldState *env, target_ulong addr,
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003456 void *buf, int len, int is_write)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003457{
3458 int l;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003459 hwaddr phys_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003460 target_ulong page;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003461 uint8_t* buf8 = (uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003462
3463 while (len > 0) {
3464 page = addr & TARGET_PAGE_MASK;
3465 phys_addr = cpu_get_phys_page_debug(env, page);
3466 /* if no physical page mapped, return an error */
3467 if (phys_addr == -1)
3468 return -1;
3469 l = (page + TARGET_PAGE_SIZE) - addr;
3470 if (l > len)
3471 l = len;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003472 phys_addr += (addr & ~TARGET_PAGE_MASK);
3473#if !defined(CONFIG_USER_ONLY)
3474 if (is_write)
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003475 cpu_physical_memory_write_rom(phys_addr, buf8, l);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003476 else
3477#endif
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003478 cpu_physical_memory_rw(phys_addr, buf8, l, is_write);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003479 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003480 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003481 addr += l;
3482 }
3483 return 0;
3484}
3485
3486/* in deterministic execution mode, instructions doing device I/Os
3487 must be at the end of the TB */
David 'Digit' Turner85c62202014-02-16 20:53:40 +01003488void cpu_io_recompile(CPUArchState *env, uintptr_t retaddr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003489{
3490 TranslationBlock *tb;
3491 uint32_t n, cflags;
3492 target_ulong pc, cs_base;
3493 uint64_t flags;
3494
David 'Digit' Turner85c62202014-02-16 20:53:40 +01003495 tb = tb_find_pc(retaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003496 if (!tb) {
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02003497 cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p",
David 'Digit' Turner85c62202014-02-16 20:53:40 +01003498 (void*)retaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003499 }
3500 n = env->icount_decr.u16.low + tb->icount;
David 'Digit' Turner85c62202014-02-16 20:53:40 +01003501 cpu_restore_state(tb, env, retaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003502 /* Calculate how many instructions had been executed before the fault
3503 occurred. */
3504 n = n - env->icount_decr.u16.low;
3505 /* Generate a new TB ending on the I/O insn. */
3506 n++;
3507 /* On MIPS and SH, delay slot instructions can only be restarted if
3508 they were already the first instruction in the TB. If this is not
3509 the first instruction in a TB then re-execute the preceding
3510 branch. */
3511#if defined(TARGET_MIPS)
3512 if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) {
3513 env->active_tc.PC -= 4;
3514 env->icount_decr.u16.low++;
3515 env->hflags &= ~MIPS_HFLAG_BMASK;
3516 }
3517#elif defined(TARGET_SH4)
3518 if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
3519 && n > 1) {
3520 env->pc -= 2;
3521 env->icount_decr.u16.low++;
3522 env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
3523 }
3524#endif
3525 /* This should never happen. */
3526 if (n > CF_COUNT_MASK)
3527 cpu_abort(env, "TB too big during recompile");
3528
3529 cflags = n | CF_LAST_IO;
3530 pc = tb->pc;
3531 cs_base = tb->cs_base;
3532 flags = tb->flags;
3533 tb_phys_invalidate(tb, -1);
3534 /* FIXME: In theory this could raise an exception. In practice
3535 we have already translated the block once so it's probably ok. */
3536 tb_gen_code(env, pc, cs_base, flags, cflags);
3537 /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
3538 the first in the TB) then we end up generating a whole new TB and
3539 repeating the fault, which is horribly inefficient.
3540 Better would be to execute just this insn uncached, or generate a
3541 second new TB. */
3542 cpu_resume_from_signal(env, NULL);
3543}
3544
David 'Digit' Turner36411062010-12-22 17:34:53 +01003545#if !defined(CONFIG_USER_ONLY)
3546
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003547void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003548{
3549 int i, target_code_size, max_target_code_size;
3550 int direct_jmp_count, direct_jmp2_count, cross_page;
3551 TranslationBlock *tb;
3552
3553 target_code_size = 0;
3554 max_target_code_size = 0;
3555 cross_page = 0;
3556 direct_jmp_count = 0;
3557 direct_jmp2_count = 0;
3558 for(i = 0; i < nb_tbs; i++) {
3559 tb = &tbs[i];
3560 target_code_size += tb->size;
3561 if (tb->size > max_target_code_size)
3562 max_target_code_size = tb->size;
3563 if (tb->page_addr[1] != -1)
3564 cross_page++;
3565 if (tb->tb_next_offset[0] != 0xffff) {
3566 direct_jmp_count++;
3567 if (tb->tb_next_offset[1] != 0xffff) {
3568 direct_jmp2_count++;
3569 }
3570 }
3571 }
3572 /* XXX: avoid using doubles ? */
3573 cpu_fprintf(f, "Translation buffer state:\n");
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003574 cpu_fprintf(f, "gen code size %td/%ld\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003575 code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02003576 cpu_fprintf(f, "TB count %d/%d\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003577 nb_tbs, code_gen_max_blocks);
3578 cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
3579 nb_tbs ? target_code_size / nb_tbs : 0,
3580 max_target_code_size);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003581 cpu_fprintf(f, "TB avg host size %td bytes (expansion ratio: %0.1f)\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003582 nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
3583 target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
3584 cpu_fprintf(f, "cross page TB count %d (%d%%)\n",
3585 cross_page,
3586 nb_tbs ? (cross_page * 100) / nb_tbs : 0);
3587 cpu_fprintf(f, "direct jump count %d (%d%%) (2 jumps=%d %d%%)\n",
3588 direct_jmp_count,
3589 nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
3590 direct_jmp2_count,
3591 nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
3592 cpu_fprintf(f, "\nStatistics:\n");
3593 cpu_fprintf(f, "TB flush count %d\n", tb_flush_count);
3594 cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
3595 cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count);
3596 tcg_dump_info(f, cpu_fprintf);
3597}
3598
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003599#endif