blob: 4f27734aac594ed999dfe2e342bf3cfdf0f4c660 [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)
David 'Digit' Turner5cb5c0b2014-02-17 16:04:03 +0100572 register_savevm(NULL,
573 "cpu_common",
574 cpu_index,
575 CPU_COMMON_SAVE_VERSION,
576 cpu_common_save,
577 cpu_common_load,
578 env);
579 register_savevm(NULL,
580 "cpu",
581 cpu_index,
582 CPU_SAVE_VERSION,
583 cpu_save,
584 cpu_load,
585 env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800586#endif
587}
588
589static inline void invalidate_page_bitmap(PageDesc *p)
590{
591 if (p->code_bitmap) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100592 g_free(p->code_bitmap);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800593 p->code_bitmap = NULL;
594 }
595 p->code_write_count = 0;
596}
597
598/* set to NULL all the 'first_tb' fields in all PageDescs */
599static void page_flush_tb(void)
600{
601 int i, j;
602 PageDesc *p;
603
604 for(i = 0; i < L1_SIZE; i++) {
605 p = l1_map[i];
606 if (p) {
607 for(j = 0; j < L2_SIZE; j++) {
608 p->first_tb = NULL;
609 invalidate_page_bitmap(p);
610 p++;
611 }
612 }
613 }
614}
615
616/* flush all the translation blocks */
617/* XXX: tb_flush is currently not thread safe */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100618void tb_flush(CPUArchState *env1)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800619{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100620 CPUArchState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800621#if defined(DEBUG_FLUSH)
622 printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
623 (unsigned long)(code_gen_ptr - code_gen_buffer),
624 nb_tbs, nb_tbs > 0 ?
625 ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
626#endif
627 if ((unsigned long)(code_gen_ptr - code_gen_buffer) > code_gen_buffer_size)
628 cpu_abort(env1, "Internal error: code buffer overflow\n");
629
630 nb_tbs = 0;
631
632 for(env = first_cpu; env != NULL; env = env->next_cpu) {
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800633#ifdef CONFIG_MEMCHECK
634 int tb_to_clean;
635 for (tb_to_clean = 0; tb_to_clean < TB_JMP_CACHE_SIZE; tb_to_clean++) {
636 if (env->tb_jmp_cache[tb_to_clean] != NULL &&
637 env->tb_jmp_cache[tb_to_clean]->tpc2gpc != NULL) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100638 g_free(env->tb_jmp_cache[tb_to_clean]->tpc2gpc);
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800639 env->tb_jmp_cache[tb_to_clean]->tpc2gpc = NULL;
640 env->tb_jmp_cache[tb_to_clean]->tpc2gpc_pairs = 0;
641 }
642 }
643#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800644 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
645 }
646
647 memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
648 page_flush_tb();
649
650 code_gen_ptr = code_gen_buffer;
651 /* XXX: flush processor icache at this point if cache flush is
652 expensive */
653 tb_flush_count++;
654}
655
656#ifdef DEBUG_TB_CHECK
657
658static void tb_invalidate_check(target_ulong address)
659{
660 TranslationBlock *tb;
661 int i;
662 address &= TARGET_PAGE_MASK;
663 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
664 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
665 if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
666 address >= tb->pc + tb->size)) {
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700667 printf("ERROR invalidate: address=" TARGET_FMT_lx
668 " PC=%08lx size=%04x\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800669 address, (long)tb->pc, tb->size);
670 }
671 }
672 }
673}
674
675/* verify that all the pages have correct rights for code */
676static void tb_page_check(void)
677{
678 TranslationBlock *tb;
679 int i, flags1, flags2;
680
681 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
682 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
683 flags1 = page_get_flags(tb->pc);
684 flags2 = page_get_flags(tb->pc + tb->size - 1);
685 if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
686 printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
687 (long)tb->pc, tb->size, flags1, flags2);
688 }
689 }
690 }
691}
692
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800693#endif
694
695/* invalidate one TB */
696static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb,
697 int next_offset)
698{
699 TranslationBlock *tb1;
700 for(;;) {
701 tb1 = *ptb;
702 if (tb1 == tb) {
703 *ptb = *(TranslationBlock **)((char *)tb1 + next_offset);
704 break;
705 }
706 ptb = (TranslationBlock **)((char *)tb1 + next_offset);
707 }
708}
709
710static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
711{
712 TranslationBlock *tb1;
713 unsigned int n1;
714
715 for(;;) {
716 tb1 = *ptb;
717 n1 = (long)tb1 & 3;
718 tb1 = (TranslationBlock *)((long)tb1 & ~3);
719 if (tb1 == tb) {
720 *ptb = tb1->page_next[n1];
721 break;
722 }
723 ptb = &tb1->page_next[n1];
724 }
725}
726
727static inline void tb_jmp_remove(TranslationBlock *tb, int n)
728{
729 TranslationBlock *tb1, **ptb;
730 unsigned int n1;
731
732 ptb = &tb->jmp_next[n];
733 tb1 = *ptb;
734 if (tb1) {
735 /* find tb(n) in circular list */
736 for(;;) {
737 tb1 = *ptb;
738 n1 = (long)tb1 & 3;
739 tb1 = (TranslationBlock *)((long)tb1 & ~3);
740 if (n1 == n && tb1 == tb)
741 break;
742 if (n1 == 2) {
743 ptb = &tb1->jmp_first;
744 } else {
745 ptb = &tb1->jmp_next[n1];
746 }
747 }
748 /* now we can suppress tb(n) from the list */
749 *ptb = tb->jmp_next[n];
750
751 tb->jmp_next[n] = NULL;
752 }
753}
754
755/* reset the jump entry 'n' of a TB so that it is not chained to
756 another TB */
757static inline void tb_reset_jump(TranslationBlock *tb, int n)
758{
759 tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
760}
761
David 'Digit' Turner85c62202014-02-16 20:53:40 +0100762void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800763{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100764 CPUArchState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800765 PageDesc *p;
766 unsigned int h, n1;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100767 hwaddr phys_pc;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800768 TranslationBlock *tb1, *tb2;
769
770 /* remove the TB from the hash list */
771 phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
772 h = tb_phys_hash_func(phys_pc);
773 tb_remove(&tb_phys_hash[h], tb,
774 offsetof(TranslationBlock, phys_hash_next));
775
776 /* remove the TB from the page list */
777 if (tb->page_addr[0] != page_addr) {
778 p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
779 tb_page_remove(&p->first_tb, tb);
780 invalidate_page_bitmap(p);
781 }
782 if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
783 p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
784 tb_page_remove(&p->first_tb, tb);
785 invalidate_page_bitmap(p);
786 }
787
788 tb_invalidated_flag = 1;
789
790 /* remove the TB from the hash list */
791 h = tb_jmp_cache_hash_func(tb->pc);
792 for(env = first_cpu; env != NULL; env = env->next_cpu) {
793 if (env->tb_jmp_cache[h] == tb)
794 env->tb_jmp_cache[h] = NULL;
795 }
796
797 /* suppress this TB from the two jump lists */
798 tb_jmp_remove(tb, 0);
799 tb_jmp_remove(tb, 1);
800
801 /* suppress any remaining jumps to this TB */
802 tb1 = tb->jmp_first;
803 for(;;) {
804 n1 = (long)tb1 & 3;
805 if (n1 == 2)
806 break;
807 tb1 = (TranslationBlock *)((long)tb1 & ~3);
808 tb2 = tb1->jmp_next[n1];
809 tb_reset_jump(tb1, n1);
810 tb1->jmp_next[n1] = NULL;
811 tb1 = tb2;
812 }
813 tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
814
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800815#ifdef CONFIG_MEMCHECK
816 if (tb->tpc2gpc != NULL) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100817 g_free(tb->tpc2gpc);
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800818 tb->tpc2gpc = NULL;
819 tb->tpc2gpc_pairs = 0;
820 }
821#endif // CONFIG_MEMCHECK
822
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800823 tb_phys_invalidate_count++;
824}
825
826static inline void set_bits(uint8_t *tab, int start, int len)
827{
828 int end, mask, end1;
829
830 end = start + len;
831 tab += start >> 3;
832 mask = 0xff << (start & 7);
833 if ((start & ~7) == (end & ~7)) {
834 if (start < end) {
835 mask &= ~(0xff << (end & 7));
836 *tab |= mask;
837 }
838 } else {
839 *tab++ |= mask;
840 start = (start + 8) & ~7;
841 end1 = end & ~7;
842 while (start < end1) {
843 *tab++ = 0xff;
844 start += 8;
845 }
846 if (start < end) {
847 mask = ~(0xff << (end & 7));
848 *tab |= mask;
849 }
850 }
851}
852
853static void build_page_bitmap(PageDesc *p)
854{
855 int n, tb_start, tb_end;
856 TranslationBlock *tb;
857
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100858 p->code_bitmap = g_malloc0(TARGET_PAGE_SIZE / 8);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800859
860 tb = p->first_tb;
861 while (tb != NULL) {
862 n = (long)tb & 3;
863 tb = (TranslationBlock *)((long)tb & ~3);
864 /* NOTE: this is subtle as a TB may span two physical pages */
865 if (n == 0) {
866 /* NOTE: tb_end may be after the end of the page, but
867 it is not a problem */
868 tb_start = tb->pc & ~TARGET_PAGE_MASK;
869 tb_end = tb_start + tb->size;
870 if (tb_end > TARGET_PAGE_SIZE)
871 tb_end = TARGET_PAGE_SIZE;
872 } else {
873 tb_start = 0;
874 tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
875 }
876 set_bits(p->code_bitmap, tb_start, tb_end - tb_start);
877 tb = tb->page_next[n];
878 }
879}
880
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100881TranslationBlock *tb_gen_code(CPUArchState *env,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800882 target_ulong pc, target_ulong cs_base,
883 int flags, int cflags)
884{
885 TranslationBlock *tb;
886 uint8_t *tc_ptr;
887 target_ulong phys_pc, phys_page2, virt_page2;
888 int code_gen_size;
889
890 phys_pc = get_phys_addr_code(env, pc);
891 tb = tb_alloc(pc);
892 if (!tb) {
893 /* flush must be done */
894 tb_flush(env);
895 /* cannot fail at this point */
896 tb = tb_alloc(pc);
897 /* Don't forget to invalidate previous TB info. */
898 tb_invalidated_flag = 1;
899 }
900 tc_ptr = code_gen_ptr;
901 tb->tc_ptr = tc_ptr;
902 tb->cs_base = cs_base;
903 tb->flags = flags;
904 tb->cflags = cflags;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800905 cpu_gen_code(env, tb, &code_gen_size);
906 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
907
908 /* check next page if needed */
909 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
910 phys_page2 = -1;
911 if ((pc & TARGET_PAGE_MASK) != virt_page2) {
912 phys_page2 = get_phys_addr_code(env, virt_page2);
913 }
914 tb_link_phys(tb, phys_pc, phys_page2);
915 return tb;
916}
917
918/* invalidate all TBs which intersect with the target physical page
919 starting in range [start;end[. NOTE: start and end must refer to
920 the same physical page. 'is_cpu_write_access' should be true if called
921 from a real cpu write access: the virtual CPU will exit the current
922 TB if code is modified inside this TB. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100923void tb_invalidate_phys_page_range(hwaddr start, hwaddr end,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800924 int is_cpu_write_access)
925{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700926 TranslationBlock *tb, *tb_next, *saved_tb;
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100927 CPUArchState *env = cpu_single_env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800928 target_ulong tb_start, tb_end;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700929 PageDesc *p;
930 int n;
931#ifdef TARGET_HAS_PRECISE_SMC
932 int current_tb_not_found = is_cpu_write_access;
933 TranslationBlock *current_tb = NULL;
934 int current_tb_modified = 0;
935 target_ulong current_pc = 0;
936 target_ulong current_cs_base = 0;
937 int current_flags = 0;
938#endif /* TARGET_HAS_PRECISE_SMC */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800939
940 p = page_find(start >> TARGET_PAGE_BITS);
941 if (!p)
942 return;
943 if (!p->code_bitmap &&
944 ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
945 is_cpu_write_access) {
946 /* build code bitmap */
947 build_page_bitmap(p);
948 }
949
950 /* we remove all the TBs in the range [start, end[ */
951 /* 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 -0800952 tb = p->first_tb;
953 while (tb != NULL) {
954 n = (long)tb & 3;
955 tb = (TranslationBlock *)((long)tb & ~3);
956 tb_next = tb->page_next[n];
957 /* NOTE: this is subtle as a TB may span two physical pages */
958 if (n == 0) {
959 /* NOTE: tb_end may be after the end of the page, but
960 it is not a problem */
961 tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
962 tb_end = tb_start + tb->size;
963 } else {
964 tb_start = tb->page_addr[1];
965 tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
966 }
967 if (!(tb_end <= start || tb_start >= end)) {
968#ifdef TARGET_HAS_PRECISE_SMC
969 if (current_tb_not_found) {
970 current_tb_not_found = 0;
971 current_tb = NULL;
972 if (env->mem_io_pc) {
973 /* now we have a real cpu fault */
974 current_tb = tb_find_pc(env->mem_io_pc);
975 }
976 }
977 if (current_tb == tb &&
978 (current_tb->cflags & CF_COUNT_MASK) != 1) {
979 /* If we are modifying the current TB, we must stop
980 its execution. We could be more precise by checking
981 that the modification is after the current PC, but it
982 would require a specialized function to partially
983 restore the CPU state */
984
985 current_tb_modified = 1;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200986 cpu_restore_state(current_tb, env, env->mem_io_pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700987 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
988 &current_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800989 }
990#endif /* TARGET_HAS_PRECISE_SMC */
991 /* we need to do that to handle the case where a signal
992 occurs while doing tb_phys_invalidate() */
993 saved_tb = NULL;
994 if (env) {
995 saved_tb = env->current_tb;
996 env->current_tb = NULL;
997 }
998 tb_phys_invalidate(tb, -1);
999 if (env) {
1000 env->current_tb = saved_tb;
1001 if (env->interrupt_request && env->current_tb)
1002 cpu_interrupt(env, env->interrupt_request);
1003 }
1004 }
1005 tb = tb_next;
1006 }
1007#if !defined(CONFIG_USER_ONLY)
1008 /* if no code remaining, no need to continue to use slow writes */
1009 if (!p->first_tb) {
1010 invalidate_page_bitmap(p);
1011 if (is_cpu_write_access) {
1012 tlb_unprotect_code_phys(env, start, env->mem_io_vaddr);
1013 }
1014 }
1015#endif
1016#ifdef TARGET_HAS_PRECISE_SMC
1017 if (current_tb_modified) {
1018 /* we generate a block containing just the instruction
1019 modifying the memory. It will ensure that it cannot modify
1020 itself */
1021 env->current_tb = NULL;
1022 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1023 cpu_resume_from_signal(env, NULL);
1024 }
1025#endif
1026}
1027
1028/* len must be <= 8 and start must be a multiple of len */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001029static inline void tb_invalidate_phys_page_fast(hwaddr start, int len)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001030{
1031 PageDesc *p;
1032 int offset, b;
1033#if 0
1034 if (1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001035 qemu_log("modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
1036 cpu_single_env->mem_io_vaddr, len,
1037 cpu_single_env->eip,
1038 cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001039 }
1040#endif
1041 p = page_find(start >> TARGET_PAGE_BITS);
1042 if (!p)
1043 return;
1044 if (p->code_bitmap) {
1045 offset = start & ~TARGET_PAGE_MASK;
1046 b = p->code_bitmap[offset >> 3] >> (offset & 7);
1047 if (b & ((1 << len) - 1))
1048 goto do_invalidate;
1049 } else {
1050 do_invalidate:
1051 tb_invalidate_phys_page_range(start, start + len, 1);
1052 }
1053}
1054
1055#if !defined(CONFIG_SOFTMMU)
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001056static void tb_invalidate_phys_page(hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001057 unsigned long pc, void *puc)
1058{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001059 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001060 PageDesc *p;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001061 int n;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001062#ifdef TARGET_HAS_PRECISE_SMC
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001063 TranslationBlock *current_tb = NULL;
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001064 CPUArchState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001065 int current_tb_modified = 0;
1066 target_ulong current_pc = 0;
1067 target_ulong current_cs_base = 0;
1068 int current_flags = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001069#endif
1070
1071 addr &= TARGET_PAGE_MASK;
1072 p = page_find(addr >> TARGET_PAGE_BITS);
1073 if (!p)
1074 return;
1075 tb = p->first_tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001076#ifdef TARGET_HAS_PRECISE_SMC
1077 if (tb && pc != 0) {
1078 current_tb = tb_find_pc(pc);
1079 }
1080#endif
1081 while (tb != NULL) {
1082 n = (long)tb & 3;
1083 tb = (TranslationBlock *)((long)tb & ~3);
1084#ifdef TARGET_HAS_PRECISE_SMC
1085 if (current_tb == tb &&
1086 (current_tb->cflags & CF_COUNT_MASK) != 1) {
1087 /* If we are modifying the current TB, we must stop
1088 its execution. We could be more precise by checking
1089 that the modification is after the current PC, but it
1090 would require a specialized function to partially
1091 restore the CPU state */
1092
1093 current_tb_modified = 1;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02001094 cpu_restore_state(current_tb, env, pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001095 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
1096 &current_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001097 }
1098#endif /* TARGET_HAS_PRECISE_SMC */
1099 tb_phys_invalidate(tb, addr);
1100 tb = tb->page_next[n];
1101 }
1102 p->first_tb = NULL;
1103#ifdef TARGET_HAS_PRECISE_SMC
1104 if (current_tb_modified) {
1105 /* we generate a block containing just the instruction
1106 modifying the memory. It will ensure that it cannot modify
1107 itself */
1108 env->current_tb = NULL;
1109 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1110 cpu_resume_from_signal(env, puc);
1111 }
1112#endif
1113}
1114#endif
1115
1116/* add the tb in the target page and protect it if necessary */
1117static inline void tb_alloc_page(TranslationBlock *tb,
1118 unsigned int n, target_ulong page_addr)
1119{
1120 PageDesc *p;
1121 TranslationBlock *last_first_tb;
1122
1123 tb->page_addr[n] = page_addr;
1124 p = page_find_alloc(page_addr >> TARGET_PAGE_BITS);
1125 tb->page_next[n] = p->first_tb;
1126 last_first_tb = p->first_tb;
1127 p->first_tb = (TranslationBlock *)((long)tb | n);
1128 invalidate_page_bitmap(p);
1129
1130#if defined(TARGET_HAS_SMC) || 1
1131
1132#if defined(CONFIG_USER_ONLY)
1133 if (p->flags & PAGE_WRITE) {
1134 target_ulong addr;
1135 PageDesc *p2;
1136 int prot;
1137
1138 /* force the host page as non writable (writes will have a
1139 page fault + mprotect overhead) */
1140 page_addr &= qemu_host_page_mask;
1141 prot = 0;
1142 for(addr = page_addr; addr < page_addr + qemu_host_page_size;
1143 addr += TARGET_PAGE_SIZE) {
1144
1145 p2 = page_find (addr >> TARGET_PAGE_BITS);
1146 if (!p2)
1147 continue;
1148 prot |= p2->flags;
1149 p2->flags &= ~PAGE_WRITE;
1150 page_get_flags(addr);
1151 }
1152 mprotect(g2h(page_addr), qemu_host_page_size,
1153 (prot & PAGE_BITS) & ~PAGE_WRITE);
1154#ifdef DEBUG_TB_INVALIDATE
1155 printf("protecting code page: 0x" TARGET_FMT_lx "\n",
1156 page_addr);
1157#endif
1158 }
1159#else
1160 /* if some code is already present, then the pages are already
1161 protected. So we handle the case where only the first TB is
1162 allocated in a physical page */
1163 if (!last_first_tb) {
1164 tlb_protect_code(page_addr);
1165 }
1166#endif
1167
1168#endif /* TARGET_HAS_SMC */
1169}
1170
1171/* Allocate a new translation block. Flush the translation buffer if
1172 too many translation blocks or too much generated code. */
1173TranslationBlock *tb_alloc(target_ulong pc)
1174{
1175 TranslationBlock *tb;
1176
1177 if (nb_tbs >= code_gen_max_blocks ||
1178 (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
1179 return NULL;
1180 tb = &tbs[nb_tbs++];
1181 tb->pc = pc;
1182 tb->cflags = 0;
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -08001183#ifdef CONFIG_MEMCHECK
1184 tb->tpc2gpc = NULL;
1185 tb->tpc2gpc_pairs = 0;
1186#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001187 return tb;
1188}
1189
1190void tb_free(TranslationBlock *tb)
1191{
1192 /* In practice this is mostly used for single use temporary TB
1193 Ignore the hard cases and just back up if this TB happens to
1194 be the last one generated. */
1195 if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) {
1196 code_gen_ptr = tb->tc_ptr;
1197 nb_tbs--;
1198 }
1199}
1200
1201/* add a new TB and link it to the physical page tables. phys_page2 is
1202 (-1) to indicate that only one page contains the TB. */
1203void tb_link_phys(TranslationBlock *tb,
1204 target_ulong phys_pc, target_ulong phys_page2)
1205{
1206 unsigned int h;
1207 TranslationBlock **ptb;
1208
1209 /* Grab the mmap lock to stop another thread invalidating this TB
1210 before we are done. */
1211 mmap_lock();
1212 /* add in the physical hash table */
1213 h = tb_phys_hash_func(phys_pc);
1214 ptb = &tb_phys_hash[h];
1215 tb->phys_hash_next = *ptb;
1216 *ptb = tb;
1217
1218 /* add in the page list */
1219 tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK);
1220 if (phys_page2 != -1)
1221 tb_alloc_page(tb, 1, phys_page2);
1222 else
1223 tb->page_addr[1] = -1;
1224
1225 tb->jmp_first = (TranslationBlock *)((long)tb | 2);
1226 tb->jmp_next[0] = NULL;
1227 tb->jmp_next[1] = NULL;
1228
1229 /* init original jump addresses */
1230 if (tb->tb_next_offset[0] != 0xffff)
1231 tb_reset_jump(tb, 0);
1232 if (tb->tb_next_offset[1] != 0xffff)
1233 tb_reset_jump(tb, 1);
1234
1235#ifdef DEBUG_TB_CHECK
1236 tb_page_check();
1237#endif
1238 mmap_unlock();
1239}
1240
1241/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
1242 tb[1].tc_ptr. Return NULL if not found */
1243TranslationBlock *tb_find_pc(unsigned long tc_ptr)
1244{
1245 int m_min, m_max, m;
1246 unsigned long v;
1247 TranslationBlock *tb;
1248
1249 if (nb_tbs <= 0)
1250 return NULL;
1251 if (tc_ptr < (unsigned long)code_gen_buffer ||
1252 tc_ptr >= (unsigned long)code_gen_ptr)
1253 return NULL;
1254 /* binary search (cf Knuth) */
1255 m_min = 0;
1256 m_max = nb_tbs - 1;
1257 while (m_min <= m_max) {
1258 m = (m_min + m_max) >> 1;
1259 tb = &tbs[m];
1260 v = (unsigned long)tb->tc_ptr;
1261 if (v == tc_ptr)
1262 return tb;
1263 else if (tc_ptr < v) {
1264 m_max = m - 1;
1265 } else {
1266 m_min = m + 1;
1267 }
1268 }
1269 return &tbs[m_max];
1270}
1271
1272static void tb_reset_jump_recursive(TranslationBlock *tb);
1273
1274static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
1275{
1276 TranslationBlock *tb1, *tb_next, **ptb;
1277 unsigned int n1;
1278
1279 tb1 = tb->jmp_next[n];
1280 if (tb1 != NULL) {
1281 /* find head of list */
1282 for(;;) {
1283 n1 = (long)tb1 & 3;
1284 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1285 if (n1 == 2)
1286 break;
1287 tb1 = tb1->jmp_next[n1];
1288 }
1289 /* we are now sure now that tb jumps to tb1 */
1290 tb_next = tb1;
1291
1292 /* remove tb from the jmp_first list */
1293 ptb = &tb_next->jmp_first;
1294 for(;;) {
1295 tb1 = *ptb;
1296 n1 = (long)tb1 & 3;
1297 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1298 if (n1 == n && tb1 == tb)
1299 break;
1300 ptb = &tb1->jmp_next[n1];
1301 }
1302 *ptb = tb->jmp_next[n];
1303 tb->jmp_next[n] = NULL;
1304
1305 /* suppress the jump to next tb in generated code */
1306 tb_reset_jump(tb, n);
1307
1308 /* suppress jumps in the tb on which we could have jumped */
1309 tb_reset_jump_recursive(tb_next);
1310 }
1311}
1312
1313static void tb_reset_jump_recursive(TranslationBlock *tb)
1314{
1315 tb_reset_jump_recursive2(tb, 0);
1316 tb_reset_jump_recursive2(tb, 1);
1317}
1318
1319#if defined(TARGET_HAS_ICE)
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001320static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001321{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001322 hwaddr addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001323 target_ulong pd;
1324 ram_addr_t ram_addr;
1325 PhysPageDesc *p;
1326
1327 addr = cpu_get_phys_page_debug(env, pc);
1328 p = phys_page_find(addr >> TARGET_PAGE_BITS);
1329 if (!p) {
1330 pd = IO_MEM_UNASSIGNED;
1331 } else {
1332 pd = p->phys_offset;
1333 }
1334 ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
1335 tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
1336}
1337#endif
1338
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001339#if defined(CONFIG_USER_ONLY)
1340void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
1341
1342{
1343}
1344
1345int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
1346 int flags, CPUWatchpoint **watchpoint)
1347{
1348 return -ENOSYS;
1349}
1350#else
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001351/* Add a watchpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001352int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001353 int flags, CPUWatchpoint **watchpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001354{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001355 target_ulong len_mask = ~(len - 1);
1356 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001357
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001358 /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001359 if ((len & (len - 1)) || (addr & ~len_mask) ||
1360 len == 0 || len > TARGET_PAGE_SIZE) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001361 fprintf(stderr, "qemu: tried to set invalid watchpoint at "
1362 TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
1363 return -EINVAL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001364 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001365 wp = g_malloc(sizeof(*wp));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001366
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001367 wp->vaddr = addr;
1368 wp->len_mask = len_mask;
1369 wp->flags = flags;
1370
1371 /* keep all GDB-injected watchpoints in front */
1372 if (flags & BP_GDB)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001373 QTAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001374 else
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001375 QTAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001376
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001377 tlb_flush_page(env, addr);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001378
1379 if (watchpoint)
1380 *watchpoint = wp;
1381 return 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001382}
1383
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001384/* Remove a specific watchpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001385int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, target_ulong len,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001386 int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001387{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001388 target_ulong len_mask = ~(len - 1);
1389 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001390
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001391 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001392 if (addr == wp->vaddr && len_mask == wp->len_mask
1393 && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
1394 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001395 return 0;
1396 }
1397 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001398 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001399}
1400
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001401/* Remove a specific watchpoint by reference. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001402void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001403{
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001404 QTAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001405
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001406 tlb_flush_page(env, watchpoint->vaddr);
1407
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001408 g_free(watchpoint);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001409}
1410
1411/* Remove all matching watchpoints. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001412void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001413{
1414 CPUWatchpoint *wp, *next;
1415
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001416 QTAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001417 if (wp->flags & mask)
1418 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001419 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001420}
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001421#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001422
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001423/* Add a breakpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001424int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001425 CPUBreakpoint **breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001426{
1427#if defined(TARGET_HAS_ICE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001428 CPUBreakpoint *bp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001429
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001430 bp = g_malloc(sizeof(*bp));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001431
1432 bp->pc = pc;
1433 bp->flags = flags;
1434
1435 /* keep all GDB-injected breakpoints in front */
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001436 if (flags & BP_GDB) {
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001437 QTAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001438 } else {
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001439 QTAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001440 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001441
1442 breakpoint_invalidate(env, pc);
1443
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001444 if (breakpoint) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001445 *breakpoint = bp;
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001446 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001447 return 0;
1448#else
1449 return -ENOSYS;
1450#endif
1451}
1452
1453/* Remove a specific breakpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001454int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001455{
1456#if defined(TARGET_HAS_ICE)
1457 CPUBreakpoint *bp;
1458
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001459 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001460 if (bp->pc == pc && bp->flags == flags) {
1461 cpu_breakpoint_remove_by_ref(env, bp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001462 return 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001463 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001464 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001465 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001466#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001467 return -ENOSYS;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001468#endif
1469}
1470
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001471/* Remove a specific breakpoint by reference. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001472void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001473{
1474#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001475 QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001476
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001477 breakpoint_invalidate(env, breakpoint->pc);
1478
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001479 g_free(breakpoint);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001480#endif
1481}
1482
1483/* Remove all matching breakpoints. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001484void cpu_breakpoint_remove_all(CPUArchState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001485{
1486#if defined(TARGET_HAS_ICE)
1487 CPUBreakpoint *bp, *next;
1488
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001489 QTAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001490 if (bp->flags & mask)
1491 cpu_breakpoint_remove_by_ref(env, bp);
1492 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001493#endif
1494}
1495
1496/* enable or disable single step mode. EXCP_DEBUG is returned by the
1497 CPU loop after each instruction */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001498void cpu_single_step(CPUOldState *env, int enabled)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001499{
1500#if defined(TARGET_HAS_ICE)
1501 if (env->singlestep_enabled != enabled) {
1502 env->singlestep_enabled = enabled;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001503 if (kvm_enabled())
1504 kvm_update_guest_debug(env, 0);
1505 else {
1506 /* must flush all the translated code to avoid inconsistencies */
1507 /* XXX: only flush what is necessary */
1508 tb_flush(env);
1509 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001510 }
1511#endif
1512}
1513
1514/* enable or disable low levels log */
1515void cpu_set_log(int log_flags)
1516{
1517 loglevel = log_flags;
1518 if (loglevel && !logfile) {
1519 logfile = fopen(logfilename, log_append ? "a" : "w");
1520 if (!logfile) {
1521 perror(logfilename);
Iliyan Malchev4a2c9dd2012-04-02 08:20:56 -07001522 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001523 }
1524#if !defined(CONFIG_SOFTMMU)
1525 /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1526 {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001527 static char logfile_buf[4096];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001528 setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1529 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001530#elif !defined(_WIN32)
1531 /* Win32 doesn't support line-buffering and requires size >= 2 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001532 setvbuf(logfile, NULL, _IOLBF, 0);
1533#endif
1534 log_append = 1;
1535 }
1536 if (!loglevel && logfile) {
1537 fclose(logfile);
1538 logfile = NULL;
1539 }
1540}
1541
1542void cpu_set_log_filename(const char *filename)
1543{
1544 logfilename = strdup(filename);
1545 if (logfile) {
1546 fclose(logfile);
1547 logfile = NULL;
1548 }
1549 cpu_set_log(loglevel);
1550}
1551
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001552static void cpu_unlink_tb(CPUOldState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001553{
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001554 /* FIXME: TB unchaining isn't SMP safe. For now just ignore the
1555 problem and hope the cpu will stop of its own accord. For userspace
1556 emulation this often isn't actually as bad as it sounds. Often
1557 signals are used primarily to interrupt blocking syscalls. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001558 TranslationBlock *tb;
1559 static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
1560
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001561 spin_lock(&interrupt_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001562 tb = env->current_tb;
1563 /* if the cpu is currently executing code, we must unlink it and
1564 all the potentially executing TB */
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001565 if (tb) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001566 env->current_tb = NULL;
1567 tb_reset_jump_recursive(tb);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001568 }
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001569 spin_unlock(&interrupt_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001570}
1571
1572/* mask must never be zero, except for A20 change call */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001573void cpu_interrupt(CPUOldState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001574{
1575 int old_mask;
1576
1577 old_mask = env->interrupt_request;
1578 env->interrupt_request |= mask;
1579
1580#ifndef CONFIG_USER_ONLY
1581 /*
1582 * If called from iothread context, wake the target cpu in
1583 * case its halted.
1584 */
1585 if (!qemu_cpu_self(env)) {
1586 qemu_cpu_kick(env);
1587 return;
1588 }
1589#endif
1590
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001591 if (use_icount) {
1592 env->icount_decr.u16.high = 0xffff;
1593#ifndef CONFIG_USER_ONLY
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001594 if (!can_do_io(env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001595 && (mask & ~old_mask) != 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001596 cpu_abort(env, "Raised interrupt while not in I/O function");
1597 }
1598#endif
1599 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001600 cpu_unlink_tb(env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001601 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001602}
1603
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001604void cpu_reset_interrupt(CPUOldState *env, int mask)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001605{
1606 env->interrupt_request &= ~mask;
1607}
1608
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001609void cpu_exit(CPUOldState *env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001610{
1611 env->exit_request = 1;
1612 cpu_unlink_tb(env);
1613}
1614
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001615void cpu_abort(CPUArchState *env, const char *fmt, ...)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001616{
1617 va_list ap;
1618 va_list ap2;
1619
1620 va_start(ap, fmt);
1621 va_copy(ap2, ap);
1622 fprintf(stderr, "qemu: fatal: ");
1623 vfprintf(stderr, fmt, ap);
1624 fprintf(stderr, "\n");
1625#ifdef TARGET_I386
1626 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1627#else
1628 cpu_dump_state(env, stderr, fprintf, 0);
1629#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001630 if (qemu_log_enabled()) {
1631 qemu_log("qemu: fatal: ");
1632 qemu_log_vprintf(fmt, ap2);
1633 qemu_log("\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001634#ifdef TARGET_I386
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001635 log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001636#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001637 log_cpu_state(env, 0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001638#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001639 qemu_log_flush();
1640 qemu_log_close();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001641 }
1642 va_end(ap2);
1643 va_end(ap);
David 'Digit' Turner36411062010-12-22 17:34:53 +01001644#if defined(CONFIG_USER_ONLY)
1645 {
1646 struct sigaction act;
1647 sigfillset(&act.sa_mask);
1648 act.sa_handler = SIG_DFL;
1649 sigaction(SIGABRT, &act, NULL);
1650 }
1651#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001652 abort();
1653}
1654
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001655CPUArchState *cpu_copy(CPUOldState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001656{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001657 CPUArchState *new_env = cpu_init(env->cpu_model_str);
1658 CPUArchState *next_cpu = new_env->next_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001659 int cpu_index = new_env->cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001660#if defined(TARGET_HAS_ICE)
1661 CPUBreakpoint *bp;
1662 CPUWatchpoint *wp;
1663#endif
1664
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001665 memcpy(new_env, env, sizeof(CPUOldState));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001666
1667 /* Preserve chaining and index. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001668 new_env->next_cpu = next_cpu;
1669 new_env->cpu_index = cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001670
1671 /* Clone all break/watchpoints.
1672 Note: Once we support ptrace with hw-debug register access, make sure
1673 BP_CPU break/watchpoints are handled correctly on clone. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001674 QTAILQ_INIT(&env->breakpoints);
1675 QTAILQ_INIT(&env->watchpoints);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001676#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001677 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001678 cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
1679 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001680 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001681 cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
1682 wp->flags, NULL);
1683 }
1684#endif
1685
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001686 return new_env;
1687}
1688
1689#if !defined(CONFIG_USER_ONLY)
1690
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001691/* Note: start and end must be within the same ram block. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001692void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
1693 int dirty_flags)
1694{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001695 CPUOldState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001696 unsigned long length, start1;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001697 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001698
1699 start &= TARGET_PAGE_MASK;
1700 end = TARGET_PAGE_ALIGN(end);
1701
1702 length = end - start;
1703 if (length == 0)
1704 return;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001705 cpu_physical_memory_mask_dirty_range(start, length, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001706
1707 /* we modify the TLB cache so that the dirty bit will be set again
1708 when accessing the range */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001709 start1 = (unsigned long)qemu_safe_ram_ptr(start);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001710 /* Chek that we don't span multiple blocks - this breaks the
1711 address comparisons below. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001712 if ((unsigned long)qemu_safe_ram_ptr(end - 1) - start1
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001713 != (end - 1) - start) {
1714 abort();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001715 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001716
1717 for(env = first_cpu; env != NULL; env = env->next_cpu) {
1718 int mmu_idx;
1719 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1720 for(i = 0; i < CPU_TLB_SIZE; i++)
1721 tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
1722 start1, length);
1723 }
1724 }
1725}
1726
1727int cpu_physical_memory_set_dirty_tracking(int enable)
1728{
1729 in_migration = enable;
1730 if (kvm_enabled()) {
1731 return kvm_set_migration_log(enable);
1732 }
1733 return 0;
1734}
1735
1736int cpu_physical_memory_get_dirty_tracking(void)
1737{
1738 return in_migration;
1739}
1740
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001741int cpu_physical_sync_dirty_bitmap(hwaddr start_addr,
1742 hwaddr end_addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001743{
1744 int ret = 0;
1745
1746 if (kvm_enabled())
1747 ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
1748 return ret;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001749}
1750
1751static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1752{
1753 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001754 void *p;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001755
1756 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001757 p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
1758 + tlb_entry->addend);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001759 ram_addr = qemu_ram_addr_from_host_nofail(p);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001760 if (!cpu_physical_memory_is_dirty(ram_addr)) {
1761 tlb_entry->addr_write |= TLB_NOTDIRTY;
1762 }
1763 }
1764}
1765
1766/* update the TLB according to the current state of the dirty bits */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001767void cpu_tlb_update_dirty(CPUArchState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001768{
1769 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001770 int mmu_idx;
1771 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1772 for(i = 0; i < CPU_TLB_SIZE; i++)
1773 tlb_update_dirty(&env->tlb_table[mmu_idx][i]);
1774 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001775}
1776
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001777
1778#else
1779
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001780void tlb_flush(CPUArchState *env, int flush_global)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001781{
1782}
1783
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001784void tlb_flush_page(CPUArchState *env, target_ulong addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001785{
1786}
1787
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001788int tlb_set_page_exec(CPUArchState *env, target_ulong vaddr,
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001789 hwaddr paddr, int prot,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001790 int mmu_idx, int is_softmmu)
1791{
1792 return 0;
1793}
1794
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001795/*
1796 * Walks guest process memory "regions" one by one
1797 * and calls callback function 'fn' for each region.
1798 */
1799int walk_memory_regions(void *priv,
1800 int (*fn)(void *, unsigned long, unsigned long, unsigned long))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001801{
1802 unsigned long start, end;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001803 PageDesc *p = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001804 int i, j, prot, prot1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001805 int rc = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001806
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001807 start = end = -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001808 prot = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001809
1810 for (i = 0; i <= L1_SIZE; i++) {
1811 p = (i < L1_SIZE) ? l1_map[i] : NULL;
1812 for (j = 0; j < L2_SIZE; j++) {
1813 prot1 = (p == NULL) ? 0 : p[j].flags;
1814 /*
1815 * "region" is one continuous chunk of memory
1816 * that has same protection flags set.
1817 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001818 if (prot1 != prot) {
1819 end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
1820 if (start != -1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001821 rc = (*fn)(priv, start, end, prot);
1822 /* callback can stop iteration by returning != 0 */
1823 if (rc != 0)
1824 return (rc);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001825 }
1826 if (prot1 != 0)
1827 start = end;
1828 else
1829 start = -1;
1830 prot = prot1;
1831 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001832 if (p == NULL)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001833 break;
1834 }
1835 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001836 return (rc);
1837}
1838
1839static int dump_region(void *priv, unsigned long start,
1840 unsigned long end, unsigned long prot)
1841{
1842 FILE *f = (FILE *)priv;
1843
1844 (void) fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
1845 start, end, end - start,
1846 ((prot & PAGE_READ) ? 'r' : '-'),
1847 ((prot & PAGE_WRITE) ? 'w' : '-'),
1848 ((prot & PAGE_EXEC) ? 'x' : '-'));
1849
1850 return (0);
1851}
1852
1853/* dump memory mappings */
1854void page_dump(FILE *f)
1855{
1856 (void) fprintf(f, "%-8s %-8s %-8s %s\n",
1857 "start", "end", "size", "prot");
1858 walk_memory_regions(f, dump_region);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001859}
1860
1861int page_get_flags(target_ulong address)
1862{
1863 PageDesc *p;
1864
1865 p = page_find(address >> TARGET_PAGE_BITS);
1866 if (!p)
1867 return 0;
1868 return p->flags;
1869}
1870
David 'Digit' Turner36411062010-12-22 17:34:53 +01001871/* Modify the flags of a page and invalidate the code if necessary.
1872 The flag PAGE_WRITE_ORG is positioned automatically depending
1873 on PAGE_WRITE. The mmap_lock should already be held. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001874void page_set_flags(target_ulong start, target_ulong end, int flags)
1875{
1876 PageDesc *p;
1877 target_ulong addr;
1878
1879 /* mmap_lock should already be held. */
1880 start = start & TARGET_PAGE_MASK;
1881 end = TARGET_PAGE_ALIGN(end);
1882 if (flags & PAGE_WRITE)
1883 flags |= PAGE_WRITE_ORG;
1884 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1885 p = page_find_alloc(addr >> TARGET_PAGE_BITS);
1886 /* We may be called for host regions that are outside guest
1887 address space. */
1888 if (!p)
1889 return;
1890 /* if the write protection is set, then we invalidate the code
1891 inside */
1892 if (!(p->flags & PAGE_WRITE) &&
1893 (flags & PAGE_WRITE) &&
1894 p->first_tb) {
1895 tb_invalidate_phys_page(addr, 0, NULL);
1896 }
1897 p->flags = flags;
1898 }
1899}
1900
1901int page_check_range(target_ulong start, target_ulong len, int flags)
1902{
1903 PageDesc *p;
1904 target_ulong end;
1905 target_ulong addr;
1906
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001907 if (start + len < start)
1908 /* we've wrapped around */
1909 return -1;
1910
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001911 end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
1912 start = start & TARGET_PAGE_MASK;
1913
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001914 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1915 p = page_find(addr >> TARGET_PAGE_BITS);
1916 if( !p )
1917 return -1;
1918 if( !(p->flags & PAGE_VALID) )
1919 return -1;
1920
1921 if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
1922 return -1;
1923 if (flags & PAGE_WRITE) {
1924 if (!(p->flags & PAGE_WRITE_ORG))
1925 return -1;
1926 /* unprotect the page if it was put read-only because it
1927 contains translated code */
1928 if (!(p->flags & PAGE_WRITE)) {
1929 if (!page_unprotect(addr, 0, NULL))
1930 return -1;
1931 }
1932 return 0;
1933 }
1934 }
1935 return 0;
1936}
1937
1938/* called from signal handler: invalidate the code and unprotect the
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001939 page. Return TRUE if the fault was successfully handled. */
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001940int page_unprotect(target_ulong address, uintptr_t pc, void *puc)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001941{
1942 unsigned int page_index, prot, pindex;
1943 PageDesc *p, *p1;
1944 target_ulong host_start, host_end, addr;
1945
1946 /* Technically this isn't safe inside a signal handler. However we
1947 know this only ever happens in a synchronous SEGV handler, so in
1948 practice it seems to be ok. */
1949 mmap_lock();
1950
1951 host_start = address & qemu_host_page_mask;
1952 page_index = host_start >> TARGET_PAGE_BITS;
1953 p1 = page_find(page_index);
1954 if (!p1) {
1955 mmap_unlock();
1956 return 0;
1957 }
1958 host_end = host_start + qemu_host_page_size;
1959 p = p1;
1960 prot = 0;
1961 for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
1962 prot |= p->flags;
1963 p++;
1964 }
1965 /* if the page was really writable, then we change its
1966 protection back to writable */
1967 if (prot & PAGE_WRITE_ORG) {
1968 pindex = (address - host_start) >> TARGET_PAGE_BITS;
1969 if (!(p1[pindex].flags & PAGE_WRITE)) {
1970 mprotect((void *)g2h(host_start), qemu_host_page_size,
1971 (prot & PAGE_BITS) | PAGE_WRITE);
1972 p1[pindex].flags |= PAGE_WRITE;
1973 /* and since the content will be modified, we must invalidate
1974 the corresponding translated code. */
1975 tb_invalidate_phys_page(address, pc, puc);
1976#ifdef DEBUG_TB_CHECK
1977 tb_invalidate_check(address);
1978#endif
1979 mmap_unlock();
1980 return 1;
1981 }
1982 }
1983 mmap_unlock();
1984 return 0;
1985}
1986
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001987static inline void tlb_set_dirty(CPUOldState *env,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001988 unsigned long addr, target_ulong vaddr)
1989{
1990}
1991#endif /* defined(CONFIG_USER_ONLY) */
1992
1993#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001994
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001995static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001996 ram_addr_t memory, ram_addr_t region_offset);
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001997static void *subpage_init (hwaddr base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001998 ram_addr_t orig_memory, ram_addr_t region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001999#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
2000 need_subpage) \
2001 do { \
2002 if (addr > start_addr) \
2003 start_addr2 = 0; \
2004 else { \
2005 start_addr2 = start_addr & ~TARGET_PAGE_MASK; \
2006 if (start_addr2 > 0) \
2007 need_subpage = 1; \
2008 } \
2009 \
2010 if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE) \
2011 end_addr2 = TARGET_PAGE_SIZE - 1; \
2012 else { \
2013 end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
2014 if (end_addr2 < TARGET_PAGE_SIZE - 1) \
2015 need_subpage = 1; \
2016 } \
2017 } while (0)
2018
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002019/* register physical memory.
2020 For RAM, 'size' must be a multiple of the target page size.
2021 If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002022 io memory page. The address used when calling the IO function is
2023 the offset from the start of the region, plus region_offset. Both
2024 start_addr and region_offset are rounded down to a page boundary
2025 before calculating this offset. This should not be a problem unless
2026 the low bits of start_addr and region_offset differ. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002027void cpu_register_physical_memory_log(hwaddr start_addr,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002028 ram_addr_t size,
2029 ram_addr_t phys_offset,
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002030 ram_addr_t region_offset,
2031 bool log_dirty)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002032{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002033 hwaddr addr, end_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002034 PhysPageDesc *p;
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002035 CPUOldState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002036 ram_addr_t orig_size = size;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002037 subpage_t *subpage;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002038
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002039 if (kvm_enabled())
2040 kvm_set_phys_mem(start_addr, size, phys_offset);
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002041#ifdef CONFIG_HAX
2042 if (hax_enabled())
2043 hax_set_phys_mem(start_addr, size, phys_offset);
2044#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002045
2046 if (phys_offset == IO_MEM_UNASSIGNED) {
2047 region_offset = start_addr;
2048 }
2049 region_offset &= TARGET_PAGE_MASK;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002050 size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002051 end_addr = start_addr + (hwaddr)size;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002052
2053 addr = start_addr;
2054 do {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002055 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2056 if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
2057 ram_addr_t orig_memory = p->phys_offset;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002058 hwaddr start_addr2, end_addr2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002059 int need_subpage = 0;
2060
2061 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2062 need_subpage);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002063 if (need_subpage) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002064 if (!(orig_memory & IO_MEM_SUBPAGE)) {
2065 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002066 &p->phys_offset, orig_memory,
2067 p->region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002068 } else {
2069 subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
2070 >> IO_MEM_SHIFT];
2071 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002072 subpage_register(subpage, start_addr2, end_addr2, phys_offset,
2073 region_offset);
2074 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002075 } else {
2076 p->phys_offset = phys_offset;
2077 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2078 (phys_offset & IO_MEM_ROMD))
2079 phys_offset += TARGET_PAGE_SIZE;
2080 }
2081 } else {
2082 p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2083 p->phys_offset = phys_offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002084 p->region_offset = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002085 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002086 (phys_offset & IO_MEM_ROMD)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002087 phys_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002088 } else {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002089 hwaddr start_addr2, end_addr2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002090 int need_subpage = 0;
2091
2092 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2093 end_addr2, need_subpage);
2094
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002095 if (need_subpage) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002096 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002097 &p->phys_offset, IO_MEM_UNASSIGNED,
2098 addr & TARGET_PAGE_MASK);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002099 subpage_register(subpage, start_addr2, end_addr2,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002100 phys_offset, region_offset);
2101 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002102 }
2103 }
2104 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002105 region_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002106 addr += TARGET_PAGE_SIZE;
2107 } while (addr != end_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002108
2109 /* since each CPU stores ram addresses in its TLB cache, we must
2110 reset the modified entries */
2111 /* XXX: slow ! */
2112 for(env = first_cpu; env != NULL; env = env->next_cpu) {
2113 tlb_flush(env, 1);
2114 }
2115}
2116
2117/* XXX: temporary until new memory mapping API */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002118ram_addr_t cpu_get_physical_page_desc(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002119{
2120 PhysPageDesc *p;
2121
2122 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2123 if (!p)
2124 return IO_MEM_UNASSIGNED;
2125 return p->phys_offset;
2126}
2127
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002128void qemu_register_coalesced_mmio(hwaddr addr, ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002129{
2130 if (kvm_enabled())
2131 kvm_coalesce_mmio_region(addr, size);
2132}
2133
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002134void qemu_unregister_coalesced_mmio(hwaddr addr, ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002135{
2136 if (kvm_enabled())
2137 kvm_uncoalesce_mmio_region(addr, size);
2138}
2139
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002140static ram_addr_t find_ram_offset(ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002141{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002142 RAMBlock *block, *next_block;
2143 ram_addr_t offset = 0, mingap = ULONG_MAX;
2144
2145 if (QLIST_EMPTY(&ram_list.blocks))
2146 return 0;
2147
2148 QLIST_FOREACH(block, &ram_list.blocks, next) {
2149 ram_addr_t end, next = ULONG_MAX;
2150
2151 end = block->offset + block->length;
2152
2153 QLIST_FOREACH(next_block, &ram_list.blocks, next) {
2154 if (next_block->offset >= end) {
2155 next = MIN(next, next_block->offset);
2156 }
2157 }
2158 if (next - end >= size && next - end < mingap) {
2159 offset = end;
2160 mingap = next - end;
2161 }
2162 }
2163 return offset;
2164}
2165
2166static ram_addr_t last_ram_offset(void)
2167{
2168 RAMBlock *block;
2169 ram_addr_t last = 0;
2170
2171 QLIST_FOREACH(block, &ram_list.blocks, next)
2172 last = MAX(last, block->offset + block->length);
2173
2174 return last;
2175}
2176
2177ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
2178 ram_addr_t size, void *host)
2179{
2180 RAMBlock *new_block, *block;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002181
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002182 size = TARGET_PAGE_ALIGN(size);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002183 new_block = g_malloc0(sizeof(*new_block));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002184
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002185#if 0
2186 if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
2187 char *id = dev->parent_bus->info->get_dev_path(dev);
2188 if (id) {
2189 snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002190 g_free(id);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002191 }
2192 }
2193#endif
2194 pstrcat(new_block->idstr, sizeof(new_block->idstr), name);
2195
2196 QLIST_FOREACH(block, &ram_list.blocks, next) {
2197 if (!strcmp(block->idstr, new_block->idstr)) {
2198 fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n",
2199 new_block->idstr);
2200 abort();
2201 }
2202 }
2203
2204 if (host) {
2205 new_block->host = host;
2206 new_block->flags |= RAM_PREALLOC_MASK;
2207 } else {
2208 if (mem_path) {
2209#if 0 && defined (__linux__) && !defined(TARGET_S390X)
2210 new_block->host = file_ram_alloc(new_block, size, mem_path);
2211 if (!new_block->host) {
2212 new_block->host = qemu_vmalloc(size);
2213 qemu_madvise(new_block->host, size, QEMU_MADV_MERGEABLE);
2214 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002215#else
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002216 fprintf(stderr, "-mem-path option unsupported\n");
2217 exit(1);
2218#endif
2219 } else {
2220#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2221 /* XXX S390 KVM requires the topmost vma of the RAM to be < 256GB */
2222 new_block->host = mmap((void*)0x1000000, size,
2223 PROT_EXEC|PROT_READ|PROT_WRITE,
2224 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
2225#else
2226 new_block->host = qemu_vmalloc(size);
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002227
2228#ifdef CONFIG_HAX
2229 /*
2230 * In HAX, qemu allocates the virtual address, and HAX kernel
2231 * module populates the region with physical memory. Currently
2232 * we don’t populate guest memory on demand, thus we should
2233 * make sure that sufficient amount of memory is available in
2234 * advance.
2235 */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002236 if (hax_enabled()) {
2237 int ret = hax_populate_ram(
2238 (uint64_t)(uintptr_t)new_block->host,
2239 size);
2240 if (ret < 0) {
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002241 fprintf(stderr, "Hax failed to populate ram\n");
2242 exit(-1);
2243 }
2244 }
2245#endif
2246
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002247#endif
2248#ifdef MADV_MERGEABLE
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002249 madvise(new_block->host, size, MADV_MERGEABLE);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002250#endif
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002251 }
2252 }
2253
2254 new_block->offset = find_ram_offset(size);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002255 new_block->length = size;
2256
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002257 QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002258
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002259 ram_list.phys_dirty = g_realloc(ram_list.phys_dirty,
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002260 last_ram_offset() >> TARGET_PAGE_BITS);
2261 memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002262 0xff, size >> TARGET_PAGE_BITS);
2263
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002264 if (kvm_enabled())
2265 kvm_setup_guest_memory(new_block->host, size);
2266
2267 return new_block->offset;
2268}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002269
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002270ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
2271{
2272 return qemu_ram_alloc_from_ptr(dev, name, size, NULL);
2273}
2274
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002275void qemu_ram_free(ram_addr_t addr)
2276{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002277 RAMBlock *block;
2278
2279 QLIST_FOREACH(block, &ram_list.blocks, next) {
2280 if (addr == block->offset) {
2281 QLIST_REMOVE(block, next);
2282 if (block->flags & RAM_PREALLOC_MASK) {
2283 ;
2284 } else if (mem_path) {
2285#if defined (__linux__) && !defined(TARGET_S390X)
2286 if (block->fd) {
2287 munmap(block->host, block->length);
2288 close(block->fd);
2289 } else {
2290 qemu_vfree(block->host);
2291 }
2292#else
2293 abort();
2294#endif
2295 } else {
2296#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2297 munmap(block->host, block->length);
2298#else
2299 qemu_vfree(block->host);
2300#endif
2301 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002302 g_free(block);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002303 return;
2304 }
2305 }
2306
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002307}
2308
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002309#ifndef _WIN32
2310void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
2311{
2312#ifndef CONFIG_ANDROID
2313 RAMBlock *block;
2314 ram_addr_t offset;
2315 int flags;
2316 void *area, *vaddr;
2317
2318 QLIST_FOREACH(block, &ram_list.blocks, next) {
2319 offset = addr - block->offset;
2320 if (offset < block->length) {
2321 vaddr = block->host + offset;
2322 if (block->flags & RAM_PREALLOC_MASK) {
2323 ;
2324 } else {
2325 flags = MAP_FIXED;
2326 munmap(vaddr, length);
2327 if (mem_path) {
2328#if defined(__linux__) && !defined(TARGET_S390X)
2329 if (block->fd) {
2330#ifdef MAP_POPULATE
2331 flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED :
2332 MAP_PRIVATE;
2333#else
2334 flags |= MAP_PRIVATE;
2335#endif
2336 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2337 flags, block->fd, offset);
2338 } else {
2339 flags |= MAP_PRIVATE | MAP_ANONYMOUS;
2340 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2341 flags, -1, 0);
2342 }
2343#else
2344 abort();
2345#endif
2346 } else {
2347#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2348 flags |= MAP_SHARED | MAP_ANONYMOUS;
2349 area = mmap(vaddr, length, PROT_EXEC|PROT_READ|PROT_WRITE,
2350 flags, -1, 0);
2351#else
2352 flags |= MAP_PRIVATE | MAP_ANONYMOUS;
2353 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2354 flags, -1, 0);
2355#endif
2356 }
2357 if (area != vaddr) {
2358 fprintf(stderr, "Could not remap addr: %lx@%lx\n",
2359 length, addr);
2360 exit(1);
2361 }
2362 qemu_madvise(vaddr, length, QEMU_MADV_MERGEABLE);
2363 }
2364 return;
2365 }
2366 }
2367#endif /* !CONFIG_ANDROID */
2368}
2369#endif /* !_WIN32 */
2370
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002371/* Return a host pointer to ram allocated with qemu_ram_alloc.
2372 With the exception of the softmmu code in this file, this should
2373 only be used for local memory (e.g. video ram) that the device owns,
2374 and knows it isn't going to access beyond the end of the block.
2375
2376 It should not be used for general purpose DMA.
2377 Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
2378 */
2379void *qemu_get_ram_ptr(ram_addr_t addr)
2380{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002381 RAMBlock *block;
2382
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002383 QLIST_FOREACH(block, &ram_list.blocks, next) {
2384 if (addr - block->offset < block->length) {
2385 /* Move this entry to to start of the list. */
2386 if (block != QLIST_FIRST(&ram_list.blocks)) {
2387 QLIST_REMOVE(block, next);
2388 QLIST_INSERT_HEAD(&ram_list.blocks, block, next);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002389 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002390 return block->host + (addr - block->offset);
2391 }
2392 }
2393
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002394 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2395 abort();
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002396
2397 return NULL;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002398 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002399
2400/* Return a host pointer to ram allocated with qemu_ram_alloc.
2401 * Same as qemu_get_ram_ptr but avoid reordering ramblocks.
2402 */
2403void *qemu_safe_ram_ptr(ram_addr_t addr)
2404{
2405 RAMBlock *block;
2406
2407 QLIST_FOREACH(block, &ram_list.blocks, next) {
2408 if (addr - block->offset < block->length) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002409 return block->host + (addr - block->offset);
2410}
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002411 }
2412
2413 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2414 abort();
2415
2416 return NULL;
2417}
2418
2419int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
2420{
2421 RAMBlock *block;
2422 uint8_t *host = ptr;
2423
2424 QLIST_FOREACH(block, &ram_list.blocks, next) {
2425 if (host - block->host < block->length) {
2426 *ram_addr = block->offset + (host - block->host);
2427 return 0;
2428 }
2429 }
2430 return -1;
2431}
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002432
2433/* Some of the softmmu routines need to translate from a host pointer
2434 (typically a TLB entry) back to a ram offset. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002435ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002436{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002437 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002438
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002439 if (qemu_ram_addr_from_host(ptr, &ram_addr)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002440 fprintf(stderr, "Bad ram pointer %p\n", ptr);
2441 abort();
2442 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002443 return ram_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002444}
2445
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002446static uint32_t unassigned_mem_readb(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002447{
2448#ifdef DEBUG_UNASSIGNED
2449 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2450#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002451#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002452 do_unassigned_access(addr, 0, 0, 0, 1);
2453#endif
2454 return 0;
2455}
2456
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002457static uint32_t unassigned_mem_readw(void *opaque, hwaddr addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002458{
2459#ifdef DEBUG_UNASSIGNED
2460 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2461#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002462#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002463 do_unassigned_access(addr, 0, 0, 0, 2);
2464#endif
2465 return 0;
2466}
2467
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002468static uint32_t unassigned_mem_readl(void *opaque, hwaddr addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002469{
2470#ifdef DEBUG_UNASSIGNED
2471 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2472#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002473#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002474 do_unassigned_access(addr, 0, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002475#endif
2476 return 0;
2477}
2478
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002479static void unassigned_mem_writeb(void *opaque, hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002480{
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, 1);
2486#endif
2487}
2488
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002489static void unassigned_mem_writew(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, 2);
2496#endif
2497}
2498
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002499static void unassigned_mem_writel(void *opaque, hwaddr addr, uint32_t val)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002500{
2501#ifdef DEBUG_UNASSIGNED
2502 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2503#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002504#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002505 do_unassigned_access(addr, 1, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002506#endif
2507}
2508
David 'Digit' Turner36411062010-12-22 17:34:53 +01002509static CPUReadMemoryFunc * const unassigned_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002510 unassigned_mem_readb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002511 unassigned_mem_readw,
2512 unassigned_mem_readl,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002513};
2514
David 'Digit' Turner36411062010-12-22 17:34:53 +01002515static CPUWriteMemoryFunc * const unassigned_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002516 unassigned_mem_writeb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002517 unassigned_mem_writew,
2518 unassigned_mem_writel,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002519};
2520
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002521static void notdirty_mem_writeb(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002522 uint32_t val)
2523{
2524 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002525 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002526 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2527#if !defined(CONFIG_USER_ONLY)
2528 tb_invalidate_phys_page_fast(ram_addr, 1);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002529 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002530#endif
2531 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002532 stb_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002533 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002534 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002535 /* we remove the notdirty callback only if the code has been
2536 flushed */
2537 if (dirty_flags == 0xff)
2538 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2539}
2540
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002541static void notdirty_mem_writew(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002542 uint32_t val)
2543{
2544 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002545 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002546 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2547#if !defined(CONFIG_USER_ONLY)
2548 tb_invalidate_phys_page_fast(ram_addr, 2);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002549 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002550#endif
2551 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002552 stw_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002553 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002554 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002555 /* we remove the notdirty callback only if the code has been
2556 flushed */
2557 if (dirty_flags == 0xff)
2558 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2559}
2560
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002561static void notdirty_mem_writel(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002562 uint32_t val)
2563{
2564 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002565 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002566 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2567#if !defined(CONFIG_USER_ONLY)
2568 tb_invalidate_phys_page_fast(ram_addr, 4);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002569 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002570#endif
2571 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002572 stl_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002573 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002574 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002575 /* we remove the notdirty callback only if the code has been
2576 flushed */
2577 if (dirty_flags == 0xff)
2578 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2579}
2580
David 'Digit' Turner36411062010-12-22 17:34:53 +01002581static CPUReadMemoryFunc * const error_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002582 NULL, /* never used */
2583 NULL, /* never used */
2584 NULL, /* never used */
2585};
2586
David 'Digit' Turner36411062010-12-22 17:34:53 +01002587static CPUWriteMemoryFunc * const notdirty_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002588 notdirty_mem_writeb,
2589 notdirty_mem_writew,
2590 notdirty_mem_writel,
2591};
2592
2593/* Generate a debug exception if a watchpoint has been hit. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002594static void check_watchpoint(int offset, int len_mask, int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002595{
David 'Digit' Turner85c62202014-02-16 20:53:40 +01002596 CPUArchState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002597 target_ulong pc, cs_base;
2598 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002599 target_ulong vaddr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002600 CPUWatchpoint *wp;
2601 int cpu_flags;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002602
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002603 if (env->watchpoint_hit) {
2604 /* We re-entered the check after replacing the TB. Now raise
2605 * the debug interrupt so that is will trigger after the
2606 * current instruction. */
2607 cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2608 return;
2609 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002610 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002611 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002612 if ((vaddr == (wp->vaddr & len_mask) ||
2613 (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
2614 wp->flags |= BP_WATCHPOINT_HIT;
2615 if (!env->watchpoint_hit) {
2616 env->watchpoint_hit = wp;
2617 tb = tb_find_pc(env->mem_io_pc);
2618 if (!tb) {
2619 cpu_abort(env, "check_watchpoint: could not find TB for "
2620 "pc=%p", (void *)env->mem_io_pc);
2621 }
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02002622 cpu_restore_state(tb, env, env->mem_io_pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002623 tb_phys_invalidate(tb, -1);
2624 if (wp->flags & BP_STOP_BEFORE_ACCESS) {
2625 env->exception_index = EXCP_DEBUG;
David 'Digit' Turner85c62202014-02-16 20:53:40 +01002626 cpu_loop_exit(env);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002627 } else {
2628 cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
2629 tb_gen_code(env, pc, cs_base, cpu_flags, 1);
David 'Digit' Turner85c62202014-02-16 20:53:40 +01002630 cpu_resume_from_signal(env, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002631 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002632 }
2633 } else {
2634 wp->flags &= ~BP_WATCHPOINT_HIT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002635 }
2636 }
2637}
2638
2639/* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
2640 so these check for a hit then pass through to the normal out-of-line
2641 phys routines. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002642static uint32_t watch_mem_readb(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002643{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002644 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002645 return ldub_phys(addr);
2646}
2647
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002648static uint32_t watch_mem_readw(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002649{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002650 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002651 return lduw_phys(addr);
2652}
2653
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002654static uint32_t watch_mem_readl(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002655{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002656 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002657 return ldl_phys(addr);
2658}
2659
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002660static void watch_mem_writeb(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002661 uint32_t val)
2662{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002663 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002664 stb_phys(addr, val);
2665}
2666
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002667static void watch_mem_writew(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002668 uint32_t val)
2669{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002670 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002671 stw_phys(addr, val);
2672}
2673
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002674static void watch_mem_writel(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002675 uint32_t val)
2676{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002677 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002678 stl_phys(addr, val);
2679}
2680
David 'Digit' Turner36411062010-12-22 17:34:53 +01002681static CPUReadMemoryFunc * const watch_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002682 watch_mem_readb,
2683 watch_mem_readw,
2684 watch_mem_readl,
2685};
2686
David 'Digit' Turner36411062010-12-22 17:34:53 +01002687static CPUWriteMemoryFunc * const watch_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002688 watch_mem_writeb,
2689 watch_mem_writew,
2690 watch_mem_writel,
2691};
2692
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002693static inline uint32_t subpage_readlen (subpage_t *mmio, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002694 unsigned int len)
2695{
2696 uint32_t ret;
2697 unsigned int idx;
2698
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002699 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002700#if defined(DEBUG_SUBPAGE)
2701 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
2702 mmio, len, addr, idx);
2703#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002704 ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len],
2705 addr + mmio->region_offset[idx][0][len]);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002706
2707 return ret;
2708}
2709
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002710static inline void subpage_writelen (subpage_t *mmio, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002711 uint32_t value, unsigned int len)
2712{
2713 unsigned int idx;
2714
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002715 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002716#if defined(DEBUG_SUBPAGE)
2717 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
2718 mmio, len, addr, idx, value);
2719#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002720 (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len],
2721 addr + mmio->region_offset[idx][1][len],
2722 value);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002723}
2724
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002725static uint32_t subpage_readb (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002726{
2727#if defined(DEBUG_SUBPAGE)
2728 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2729#endif
2730
2731 return subpage_readlen(opaque, addr, 0);
2732}
2733
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002734static void subpage_writeb (void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002735 uint32_t value)
2736{
2737#if defined(DEBUG_SUBPAGE)
2738 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2739#endif
2740 subpage_writelen(opaque, addr, value, 0);
2741}
2742
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002743static uint32_t subpage_readw (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002744{
2745#if defined(DEBUG_SUBPAGE)
2746 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2747#endif
2748
2749 return subpage_readlen(opaque, addr, 1);
2750}
2751
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002752static void subpage_writew (void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002753 uint32_t value)
2754{
2755#if defined(DEBUG_SUBPAGE)
2756 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2757#endif
2758 subpage_writelen(opaque, addr, value, 1);
2759}
2760
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002761static uint32_t subpage_readl (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002762{
2763#if defined(DEBUG_SUBPAGE)
2764 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2765#endif
2766
2767 return subpage_readlen(opaque, addr, 2);
2768}
2769
2770static void subpage_writel (void *opaque,
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002771 hwaddr addr, uint32_t value)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002772{
2773#if defined(DEBUG_SUBPAGE)
2774 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2775#endif
2776 subpage_writelen(opaque, addr, value, 2);
2777}
2778
David 'Digit' Turner36411062010-12-22 17:34:53 +01002779static CPUReadMemoryFunc * const subpage_read[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002780 &subpage_readb,
2781 &subpage_readw,
2782 &subpage_readl,
2783};
2784
David 'Digit' Turner36411062010-12-22 17:34:53 +01002785static CPUWriteMemoryFunc * const subpage_write[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002786 &subpage_writeb,
2787 &subpage_writew,
2788 &subpage_writel,
2789};
2790
2791static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002792 ram_addr_t memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002793{
2794 int idx, eidx;
2795 unsigned int i;
2796
2797 if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
2798 return -1;
2799 idx = SUBPAGE_IDX(start);
2800 eidx = SUBPAGE_IDX(end);
2801#if defined(DEBUG_SUBPAGE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002802 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 -08002803 mmio, start, end, idx, eidx, memory);
2804#endif
2805 memory >>= IO_MEM_SHIFT;
2806 for (; idx <= eidx; idx++) {
2807 for (i = 0; i < 4; i++) {
2808 if (io_mem_read[memory][i]) {
2809 mmio->mem_read[idx][i] = &io_mem_read[memory][i];
2810 mmio->opaque[idx][0][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002811 mmio->region_offset[idx][0][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002812 }
2813 if (io_mem_write[memory][i]) {
2814 mmio->mem_write[idx][i] = &io_mem_write[memory][i];
2815 mmio->opaque[idx][1][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002816 mmio->region_offset[idx][1][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002817 }
2818 }
2819 }
2820
2821 return 0;
2822}
2823
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002824static void *subpage_init (hwaddr base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002825 ram_addr_t orig_memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002826{
2827 subpage_t *mmio;
2828 int subpage_memory;
2829
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002830 mmio = g_malloc0(sizeof(subpage_t));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002831
2832 mmio->base = base;
2833 subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002834#if defined(DEBUG_SUBPAGE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002835 printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
2836 mmio, base, TARGET_PAGE_SIZE, subpage_memory);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002837#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002838 *phys = subpage_memory | IO_MEM_SUBPAGE;
2839 subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
2840 region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002841
2842 return mmio;
2843}
2844
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002845static int get_free_io_mem_idx(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002846{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002847 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002848
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002849 for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
2850 if (!io_mem_used[i]) {
2851 io_mem_used[i] = 1;
2852 return i;
2853 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002854 fprintf(stderr, "RAN out out io_mem_idx, max %d !\n", IO_MEM_NB_ENTRIES);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002855 return -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002856}
2857
2858/* mem_read and mem_write are arrays of functions containing the
2859 function to access byte (index 0), word (index 1) and dword (index
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002860 2). Functions can be omitted with a NULL function pointer.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002861 If io_index is non zero, the corresponding io zone is
2862 modified. If it is zero, a new io zone is allocated. The return
2863 value can be used with cpu_register_physical_memory(). (-1) is
2864 returned if error. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002865static int cpu_register_io_memory_fixed(int io_index,
David 'Digit' Turner36411062010-12-22 17:34:53 +01002866 CPUReadMemoryFunc * const *mem_read,
2867 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002868 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002869{
2870 int i, subwidth = 0;
2871
2872 if (io_index <= 0) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002873 io_index = get_free_io_mem_idx();
2874 if (io_index == -1)
2875 return io_index;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002876 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002877 io_index >>= IO_MEM_SHIFT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002878 if (io_index >= IO_MEM_NB_ENTRIES)
2879 return -1;
2880 }
2881
2882 for(i = 0;i < 3; i++) {
2883 if (!mem_read[i] || !mem_write[i])
2884 subwidth = IO_MEM_SUBWIDTH;
2885 io_mem_read[io_index][i] = mem_read[i];
2886 io_mem_write[io_index][i] = mem_write[i];
2887 }
2888 io_mem_opaque[io_index] = opaque;
2889 return (io_index << IO_MEM_SHIFT) | subwidth;
2890}
2891
David 'Digit' Turner36411062010-12-22 17:34:53 +01002892int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
2893 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002894 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002895{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002896 return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002897}
2898
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002899void cpu_unregister_io_memory(int io_table_address)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002900{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002901 int i;
2902 int io_index = io_table_address >> IO_MEM_SHIFT;
2903
2904 for (i=0;i < 3; i++) {
2905 io_mem_read[io_index][i] = unassigned_mem_read[i];
2906 io_mem_write[io_index][i] = unassigned_mem_write[i];
2907 }
2908 io_mem_opaque[io_index] = NULL;
2909 io_mem_used[io_index] = 0;
2910}
2911
2912static void io_mem_init(void)
2913{
2914 int i;
2915
2916 cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read, unassigned_mem_write, NULL);
2917 cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read, unassigned_mem_write, NULL);
2918 cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read, notdirty_mem_write, NULL);
2919 for (i=0; i<5; i++)
2920 io_mem_used[i] = 1;
2921
2922 io_mem_watch = cpu_register_io_memory(watch_mem_read,
2923 watch_mem_write, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002924}
2925
2926#endif /* !defined(CONFIG_USER_ONLY) */
2927
2928/* physical memory access (slow version, mainly for debug) */
2929#if defined(CONFIG_USER_ONLY)
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002930void cpu_physical_memory_rw(hwaddr addr, void *buf,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002931 int len, int is_write)
2932{
2933 int l, flags;
2934 target_ulong page;
2935 void * p;
2936
2937 while (len > 0) {
2938 page = addr & TARGET_PAGE_MASK;
2939 l = (page + TARGET_PAGE_SIZE) - addr;
2940 if (l > len)
2941 l = len;
2942 flags = page_get_flags(page);
2943 if (!(flags & PAGE_VALID))
2944 return;
2945 if (is_write) {
2946 if (!(flags & PAGE_WRITE))
2947 return;
2948 /* XXX: this code should not depend on lock_user */
2949 if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
2950 /* FIXME - should this return an error rather than just fail? */
2951 return;
2952 memcpy(p, buf, l);
2953 unlock_user(p, addr, l);
2954 } else {
2955 if (!(flags & PAGE_READ))
2956 return;
2957 /* XXX: this code should not depend on lock_user */
2958 if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
2959 /* FIXME - should this return an error rather than just fail? */
2960 return;
2961 memcpy(buf, p, l);
2962 unlock_user(p, addr, 0);
2963 }
2964 len -= l;
2965 buf += l;
2966 addr += l;
2967 }
2968}
2969
2970#else
Pete Delaneyd09d7662013-03-28 19:53:13 -07002971
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002972static void invalidate_and_set_dirty(hwaddr addr,
2973 hwaddr length)
Pete Delaneyd09d7662013-03-28 19:53:13 -07002974{
2975 if (!cpu_physical_memory_is_dirty(addr)) {
2976 /* invalidate code */
2977 tb_invalidate_phys_page_range(addr, addr + length, 0);
2978 /* set dirty bit */
2979 cpu_physical_memory_set_dirty_flags(addr, (0xff & ~CODE_DIRTY_FLAG));
2980 }
2981}
2982
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002983void cpu_physical_memory_rw(hwaddr addr, void *buf,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002984 int len, int is_write)
2985{
2986 int l, io_index;
2987 uint8_t *ptr;
2988 uint32_t val;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002989 hwaddr page;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002990 unsigned long pd;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002991 uint8_t* buf8 = (uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002992 PhysPageDesc *p;
2993
2994 while (len > 0) {
2995 page = addr & TARGET_PAGE_MASK;
2996 l = (page + TARGET_PAGE_SIZE) - addr;
2997 if (l > len)
2998 l = len;
2999 p = phys_page_find(page >> TARGET_PAGE_BITS);
3000 if (!p) {
3001 pd = IO_MEM_UNASSIGNED;
3002 } else {
3003 pd = p->phys_offset;
3004 }
3005
3006 if (is_write) {
3007 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003008 hwaddr addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003009 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003010 if (p)
3011 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003012 /* XXX: could force cpu_single_env to NULL to avoid
3013 potential bugs */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003014 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003015 /* 32 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003016 val = ldl_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003017 io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003018 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003019 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003020 /* 16 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003021 val = lduw_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003022 io_mem_write[io_index][1](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003023 l = 2;
3024 } else {
3025 /* 8 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003026 val = ldub_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003027 io_mem_write[io_index][0](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003028 l = 1;
3029 }
3030 } else {
3031 unsigned long addr1;
3032 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3033 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003034 ptr = qemu_get_ram_ptr(addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003035 memcpy(ptr, buf8, l);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003036 invalidate_and_set_dirty(addr1, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003037 }
3038 } else {
3039 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3040 !(pd & IO_MEM_ROMD)) {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003041 hwaddr addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003042 /* I/O case */
3043 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003044 if (p)
3045 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3046 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003047 /* 32 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003048 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003049 stl_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003050 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003051 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003052 /* 16 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003053 val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003054 stw_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003055 l = 2;
3056 } else {
3057 /* 8 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003058 val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003059 stb_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003060 l = 1;
3061 }
3062 } else {
3063 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003064 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003065 (addr & ~TARGET_PAGE_MASK);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003066 memcpy(buf8, ptr, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003067 }
3068 }
3069 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003070 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003071 addr += l;
3072 }
3073}
3074
3075/* used for ROM loading : can write in RAM and ROM */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003076void cpu_physical_memory_write_rom(hwaddr addr,
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003077 const void *buf, int len)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003078{
3079 int l;
3080 uint8_t *ptr;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003081 hwaddr page;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003082 unsigned long pd;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003083 const uint8_t* buf8 = (const uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003084 PhysPageDesc *p;
3085
3086 while (len > 0) {
3087 page = addr & TARGET_PAGE_MASK;
3088 l = (page + TARGET_PAGE_SIZE) - addr;
3089 if (l > len)
3090 l = len;
3091 p = phys_page_find(page >> TARGET_PAGE_BITS);
3092 if (!p) {
3093 pd = IO_MEM_UNASSIGNED;
3094 } else {
3095 pd = p->phys_offset;
3096 }
3097
3098 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
3099 (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
3100 !(pd & IO_MEM_ROMD)) {
3101 /* do nothing */
3102 } else {
3103 unsigned long addr1;
3104 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3105 /* ROM/RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003106 ptr = qemu_get_ram_ptr(addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003107 memcpy(ptr, buf8, l);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003108 invalidate_and_set_dirty(addr1, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003109 }
3110 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003111 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003112 addr += l;
3113 }
3114}
3115
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003116typedef struct {
3117 void *buffer;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003118 hwaddr addr;
3119 hwaddr len;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003120} BounceBuffer;
3121
3122static BounceBuffer bounce;
3123
3124typedef struct MapClient {
3125 void *opaque;
3126 void (*callback)(void *opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003127 QLIST_ENTRY(MapClient) link;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003128} MapClient;
3129
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003130static QLIST_HEAD(map_client_list, MapClient) map_client_list
3131 = QLIST_HEAD_INITIALIZER(map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003132
3133void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
3134{
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01003135 MapClient *client = g_malloc(sizeof(*client));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003136
3137 client->opaque = opaque;
3138 client->callback = callback;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003139 QLIST_INSERT_HEAD(&map_client_list, client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003140 return client;
3141}
3142
3143void cpu_unregister_map_client(void *_client)
3144{
3145 MapClient *client = (MapClient *)_client;
3146
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003147 QLIST_REMOVE(client, link);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01003148 g_free(client);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003149}
3150
3151static void cpu_notify_map_clients(void)
3152{
3153 MapClient *client;
3154
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003155 while (!QLIST_EMPTY(&map_client_list)) {
3156 client = QLIST_FIRST(&map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003157 client->callback(client->opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003158 QLIST_REMOVE(client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003159 }
3160}
3161
3162/* Map a physical memory region into a host virtual address.
3163 * May map a subset of the requested range, given by and returned in *plen.
3164 * May return NULL if resources needed to perform the mapping are exhausted.
3165 * Use only for reads OR writes - not for read-modify-write operations.
3166 * Use cpu_register_map_client() to know when retrying the map operation is
3167 * likely to succeed.
3168 */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003169void *cpu_physical_memory_map(hwaddr addr,
3170 hwaddr *plen,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003171 int is_write)
3172{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003173 hwaddr len = *plen;
3174 hwaddr done = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003175 int l;
3176 uint8_t *ret = NULL;
3177 uint8_t *ptr;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003178 hwaddr page;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003179 unsigned long pd;
3180 PhysPageDesc *p;
3181 unsigned long addr1;
3182
3183 while (len > 0) {
3184 page = addr & TARGET_PAGE_MASK;
3185 l = (page + TARGET_PAGE_SIZE) - addr;
3186 if (l > len)
3187 l = len;
3188 p = phys_page_find(page >> TARGET_PAGE_BITS);
3189 if (!p) {
3190 pd = IO_MEM_UNASSIGNED;
3191 } else {
3192 pd = p->phys_offset;
3193 }
3194
3195 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3196 if (done || bounce.buffer) {
3197 break;
3198 }
3199 bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
3200 bounce.addr = addr;
3201 bounce.len = l;
3202 if (!is_write) {
3203 cpu_physical_memory_rw(addr, bounce.buffer, l, 0);
3204 }
3205 ptr = bounce.buffer;
3206 } else {
3207 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3208 ptr = qemu_get_ram_ptr(addr1);
3209 }
3210 if (!done) {
3211 ret = ptr;
3212 } else if (ret + done != ptr) {
3213 break;
3214 }
3215
3216 len -= l;
3217 addr += l;
3218 done += l;
3219 }
3220 *plen = done;
3221 return ret;
3222}
3223
3224/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
3225 * Will also mark the memory as dirty if is_write == 1. access_len gives
3226 * the amount of memory that was actually read or written by the caller.
3227 */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003228void cpu_physical_memory_unmap(void *buffer, hwaddr len,
3229 int is_write, hwaddr access_len)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003230{
3231 if (buffer != bounce.buffer) {
3232 if (is_write) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003233 ram_addr_t addr1 = qemu_ram_addr_from_host_nofail(buffer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003234 while (access_len) {
3235 unsigned l;
3236 l = TARGET_PAGE_SIZE;
3237 if (l > access_len)
3238 l = access_len;
Pete Delaneyd09d7662013-03-28 19:53:13 -07003239 invalidate_and_set_dirty(addr1, l);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003240 addr1 += l;
3241 access_len -= l;
3242 }
3243 }
3244 return;
3245 }
3246 if (is_write) {
3247 cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
3248 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003249 qemu_vfree(bounce.buffer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003250 bounce.buffer = NULL;
3251 cpu_notify_map_clients();
3252}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003253
3254/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003255uint32_t ldl_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003256{
3257 int io_index;
3258 uint8_t *ptr;
3259 uint32_t val;
3260 unsigned long pd;
3261 PhysPageDesc *p;
3262
3263 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3264 if (!p) {
3265 pd = IO_MEM_UNASSIGNED;
3266 } else {
3267 pd = p->phys_offset;
3268 }
3269
3270 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3271 !(pd & IO_MEM_ROMD)) {
3272 /* I/O case */
3273 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003274 if (p)
3275 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003276 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3277 } else {
3278 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003279 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003280 (addr & ~TARGET_PAGE_MASK);
3281 val = ldl_p(ptr);
3282 }
3283 return val;
3284}
3285
3286/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003287uint64_t ldq_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003288{
3289 int io_index;
3290 uint8_t *ptr;
3291 uint64_t val;
3292 unsigned long pd;
3293 PhysPageDesc *p;
3294
3295 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3296 if (!p) {
3297 pd = IO_MEM_UNASSIGNED;
3298 } else {
3299 pd = p->phys_offset;
3300 }
3301
3302 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3303 !(pd & IO_MEM_ROMD)) {
3304 /* I/O case */
3305 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003306 if (p)
3307 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003308#ifdef TARGET_WORDS_BIGENDIAN
3309 val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
3310 val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
3311#else
3312 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3313 val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
3314#endif
3315 } else {
3316 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003317 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003318 (addr & ~TARGET_PAGE_MASK);
3319 val = ldq_p(ptr);
3320 }
3321 return val;
3322}
3323
3324/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003325uint32_t ldub_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003326{
3327 uint8_t val;
3328 cpu_physical_memory_read(addr, &val, 1);
3329 return val;
3330}
3331
3332/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003333uint32_t lduw_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003334{
3335 uint16_t val;
3336 cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
3337 return tswap16(val);
3338}
3339
3340/* warning: addr must be aligned. The ram page is not masked as dirty
3341 and the code inside is not invalidated. It is useful if the dirty
3342 bits are used to track modified PTEs */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003343void stl_phys_notdirty(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003344{
3345 int io_index;
3346 uint8_t *ptr;
3347 unsigned long pd;
3348 PhysPageDesc *p;
3349
3350 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3351 if (!p) {
3352 pd = IO_MEM_UNASSIGNED;
3353 } else {
3354 pd = p->phys_offset;
3355 }
3356
3357 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3358 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003359 if (p)
3360 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003361 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3362 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003363 unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3364 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003365 stl_p(ptr, val);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003366
3367 if (unlikely(in_migration)) {
3368 if (!cpu_physical_memory_is_dirty(addr1)) {
3369 /* invalidate code */
3370 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3371 /* set dirty bit */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003372 cpu_physical_memory_set_dirty_flags(
3373 addr1, (0xff & ~CODE_DIRTY_FLAG));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003374 }
3375 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003376 }
3377}
3378
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003379void stq_phys_notdirty(hwaddr addr, uint64_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003380{
3381 int io_index;
3382 uint8_t *ptr;
3383 unsigned long pd;
3384 PhysPageDesc *p;
3385
3386 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3387 if (!p) {
3388 pd = IO_MEM_UNASSIGNED;
3389 } else {
3390 pd = p->phys_offset;
3391 }
3392
3393 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3394 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003395 if (p)
3396 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003397#ifdef TARGET_WORDS_BIGENDIAN
3398 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
3399 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
3400#else
3401 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3402 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
3403#endif
3404 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003405 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003406 (addr & ~TARGET_PAGE_MASK);
3407 stq_p(ptr, val);
3408 }
3409}
3410
3411/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003412void stl_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003413{
3414 int io_index;
3415 uint8_t *ptr;
3416 unsigned long pd;
3417 PhysPageDesc *p;
3418
3419 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3420 if (!p) {
3421 pd = IO_MEM_UNASSIGNED;
3422 } else {
3423 pd = p->phys_offset;
3424 }
3425
3426 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3427 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003428 if (p)
3429 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003430 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3431 } else {
3432 unsigned long addr1;
3433 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3434 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003435 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003436 stl_p(ptr, val);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003437 invalidate_and_set_dirty(addr1, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003438 }
3439}
3440
3441/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003442void stb_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003443{
3444 uint8_t v = val;
3445 cpu_physical_memory_write(addr, &v, 1);
3446}
3447
3448/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003449void stw_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003450{
3451 uint16_t v = tswap16(val);
3452 cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
3453}
3454
3455/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003456void stq_phys(hwaddr addr, uint64_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003457{
3458 val = tswap64(val);
3459 cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
3460}
3461
3462#endif
3463
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003464/* virtual memory access for debug (includes writing to ROM) */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003465int cpu_memory_rw_debug(CPUOldState *env, target_ulong addr,
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003466 void *buf, int len, int is_write)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003467{
3468 int l;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003469 hwaddr phys_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003470 target_ulong page;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003471 uint8_t* buf8 = (uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003472
3473 while (len > 0) {
3474 page = addr & TARGET_PAGE_MASK;
3475 phys_addr = cpu_get_phys_page_debug(env, page);
3476 /* if no physical page mapped, return an error */
3477 if (phys_addr == -1)
3478 return -1;
3479 l = (page + TARGET_PAGE_SIZE) - addr;
3480 if (l > len)
3481 l = len;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003482 phys_addr += (addr & ~TARGET_PAGE_MASK);
3483#if !defined(CONFIG_USER_ONLY)
3484 if (is_write)
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003485 cpu_physical_memory_write_rom(phys_addr, buf8, l);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003486 else
3487#endif
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003488 cpu_physical_memory_rw(phys_addr, buf8, l, is_write);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003489 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003490 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003491 addr += l;
3492 }
3493 return 0;
3494}
3495
3496/* in deterministic execution mode, instructions doing device I/Os
3497 must be at the end of the TB */
David 'Digit' Turner85c62202014-02-16 20:53:40 +01003498void cpu_io_recompile(CPUArchState *env, uintptr_t retaddr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003499{
3500 TranslationBlock *tb;
3501 uint32_t n, cflags;
3502 target_ulong pc, cs_base;
3503 uint64_t flags;
3504
David 'Digit' Turner85c62202014-02-16 20:53:40 +01003505 tb = tb_find_pc(retaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003506 if (!tb) {
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02003507 cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p",
David 'Digit' Turner85c62202014-02-16 20:53:40 +01003508 (void*)retaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003509 }
3510 n = env->icount_decr.u16.low + tb->icount;
David 'Digit' Turner85c62202014-02-16 20:53:40 +01003511 cpu_restore_state(tb, env, retaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003512 /* Calculate how many instructions had been executed before the fault
3513 occurred. */
3514 n = n - env->icount_decr.u16.low;
3515 /* Generate a new TB ending on the I/O insn. */
3516 n++;
3517 /* On MIPS and SH, delay slot instructions can only be restarted if
3518 they were already the first instruction in the TB. If this is not
3519 the first instruction in a TB then re-execute the preceding
3520 branch. */
3521#if defined(TARGET_MIPS)
3522 if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) {
3523 env->active_tc.PC -= 4;
3524 env->icount_decr.u16.low++;
3525 env->hflags &= ~MIPS_HFLAG_BMASK;
3526 }
3527#elif defined(TARGET_SH4)
3528 if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
3529 && n > 1) {
3530 env->pc -= 2;
3531 env->icount_decr.u16.low++;
3532 env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
3533 }
3534#endif
3535 /* This should never happen. */
3536 if (n > CF_COUNT_MASK)
3537 cpu_abort(env, "TB too big during recompile");
3538
3539 cflags = n | CF_LAST_IO;
3540 pc = tb->pc;
3541 cs_base = tb->cs_base;
3542 flags = tb->flags;
3543 tb_phys_invalidate(tb, -1);
3544 /* FIXME: In theory this could raise an exception. In practice
3545 we have already translated the block once so it's probably ok. */
3546 tb_gen_code(env, pc, cs_base, flags, cflags);
3547 /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
3548 the first in the TB) then we end up generating a whole new TB and
3549 repeating the fault, which is horribly inefficient.
3550 Better would be to execute just this insn uncached, or generate a
3551 second new TB. */
3552 cpu_resume_from_signal(env, NULL);
3553}
3554
David 'Digit' Turner36411062010-12-22 17:34:53 +01003555#if !defined(CONFIG_USER_ONLY)
3556
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003557void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003558{
3559 int i, target_code_size, max_target_code_size;
3560 int direct_jmp_count, direct_jmp2_count, cross_page;
3561 TranslationBlock *tb;
3562
3563 target_code_size = 0;
3564 max_target_code_size = 0;
3565 cross_page = 0;
3566 direct_jmp_count = 0;
3567 direct_jmp2_count = 0;
3568 for(i = 0; i < nb_tbs; i++) {
3569 tb = &tbs[i];
3570 target_code_size += tb->size;
3571 if (tb->size > max_target_code_size)
3572 max_target_code_size = tb->size;
3573 if (tb->page_addr[1] != -1)
3574 cross_page++;
3575 if (tb->tb_next_offset[0] != 0xffff) {
3576 direct_jmp_count++;
3577 if (tb->tb_next_offset[1] != 0xffff) {
3578 direct_jmp2_count++;
3579 }
3580 }
3581 }
3582 /* XXX: avoid using doubles ? */
3583 cpu_fprintf(f, "Translation buffer state:\n");
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003584 cpu_fprintf(f, "gen code size %td/%ld\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003585 code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02003586 cpu_fprintf(f, "TB count %d/%d\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003587 nb_tbs, code_gen_max_blocks);
3588 cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
3589 nb_tbs ? target_code_size / nb_tbs : 0,
3590 max_target_code_size);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003591 cpu_fprintf(f, "TB avg host size %td bytes (expansion ratio: %0.1f)\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003592 nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
3593 target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
3594 cpu_fprintf(f, "cross page TB count %d (%d%%)\n",
3595 cross_page,
3596 nb_tbs ? (cross_page * 100) / nb_tbs : 0);
3597 cpu_fprintf(f, "direct jump count %d (%d%%) (2 jumps=%d %d%%)\n",
3598 direct_jmp_count,
3599 nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
3600 direct_jmp2_count,
3601 nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
3602 cpu_fprintf(f, "\nStatistics:\n");
3603 cpu_fprintf(f, "TB flush count %d\n", tb_flush_count);
3604 cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
3605 cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count);
3606 tcg_dump_info(f, cpu_fprintf);
3607}
3608
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003609#endif