blob: 285c9505a08dc393562be037998e745aebc9660e [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"
36#include "exec-all.h"
37#include "qemu-common.h"
38#include "tcg.h"
39#include "hw/hw.h"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070040#include "osdep.h"
41#include "kvm.h"
David Turner6a9ef172010-09-09 22:54:36 +020042#include "qemu-timer.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080043#if defined(CONFIG_USER_ONLY)
44#include <qemu.h>
45#endif
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -080046#ifdef CONFIG_MEMCHECK
47#include "memcheck/memcheck_api.h"
48#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080049
50//#define DEBUG_TB_INVALIDATE
51//#define DEBUG_FLUSH
52//#define DEBUG_TLB
53//#define DEBUG_UNASSIGNED
54
55/* make various TB consistency checks */
56//#define DEBUG_TB_CHECK
57//#define DEBUG_TLB_CHECK
58
59//#define DEBUG_IOPORT
60//#define DEBUG_SUBPAGE
61
62#if !defined(CONFIG_USER_ONLY)
63/* TB consistency checks only implemented for usermode emulation. */
64#undef DEBUG_TB_CHECK
65#endif
66
67#define SMC_BITMAP_USE_THRESHOLD 10
68
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080069#if defined(TARGET_SPARC64)
70#define TARGET_PHYS_ADDR_SPACE_BITS 41
71#elif defined(TARGET_SPARC)
72#define TARGET_PHYS_ADDR_SPACE_BITS 36
73#elif defined(TARGET_ALPHA)
74#define TARGET_PHYS_ADDR_SPACE_BITS 42
75#define TARGET_VIRT_ADDR_SPACE_BITS 42
76#elif defined(TARGET_PPC64)
77#define TARGET_PHYS_ADDR_SPACE_BITS 42
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070078#elif defined(TARGET_X86_64)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080079#define TARGET_PHYS_ADDR_SPACE_BITS 42
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070080#elif defined(TARGET_I386)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080081#define TARGET_PHYS_ADDR_SPACE_BITS 36
82#else
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080083#define TARGET_PHYS_ADDR_SPACE_BITS 32
84#endif
85
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070086static TranslationBlock *tbs;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080087int code_gen_max_blocks;
88TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070089static int nb_tbs;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080090/* any access to the tbs or the page table must use this lock */
91spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
92
93#if defined(__arm__) || defined(__sparc_v9__)
94/* The prologue must be reachable with a direct jump. ARM and Sparc64
95 have limited branch ranges (possibly also PPC) so place it in a
96 section close to code segment. */
97#define code_gen_section \
98 __attribute__((__section__(".gen_code"))) \
99 __attribute__((aligned (32)))
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700100#elif defined(_WIN32)
101/* Maximum alignment for Win32 is 16. */
102#define code_gen_section \
103 __attribute__((aligned (16)))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800104#else
105#define code_gen_section \
106 __attribute__((aligned (32)))
107#endif
108
109uint8_t code_gen_prologue[1024] code_gen_section;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700110static uint8_t *code_gen_buffer;
111static unsigned long code_gen_buffer_size;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800112/* threshold to flush the translated code buffer */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700113static unsigned long code_gen_buffer_max_size;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800114uint8_t *code_gen_ptr;
115
116#if !defined(CONFIG_USER_ONLY)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800117int phys_ram_fd;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700118static int in_migration;
119
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200120RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list) };
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800121#endif
122
123CPUState *first_cpu;
124/* current CPU in the current thread. It is only valid inside
125 cpu_exec() */
126CPUState *cpu_single_env;
127/* 0 = Do not count executed instructions.
128 1 = Precise instruction counting.
129 2 = Adaptive rate instruction counting. */
130int use_icount = 0;
131/* Current instruction counter. While executing translated code this may
132 include some instructions that have not yet been executed. */
133int64_t qemu_icount;
134
135typedef struct PageDesc {
136 /* list of TBs intersecting this ram page */
137 TranslationBlock *first_tb;
138 /* in order to optimize self modifying code, we count the number
139 of lookups we do to a given page to use a bitmap */
140 unsigned int code_write_count;
141 uint8_t *code_bitmap;
142#if defined(CONFIG_USER_ONLY)
143 unsigned long flags;
144#endif
145} PageDesc;
146
147typedef struct PhysPageDesc {
148 /* offset in host memory of the page + io_index in the low bits */
149 ram_addr_t phys_offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700150 ram_addr_t region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800151} PhysPageDesc;
152
153#define L2_BITS 10
154#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
155/* XXX: this is a temporary hack for alpha target.
156 * In the future, this is to be replaced by a multi-level table
157 * to actually be able to handle the complete 64 bits address space.
158 */
159#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
160#else
161#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
162#endif
163
164#define L1_SIZE (1 << L1_BITS)
165#define L2_SIZE (1 << L2_BITS)
166
167unsigned long qemu_real_host_page_size;
168unsigned long qemu_host_page_bits;
169unsigned long qemu_host_page_size;
170unsigned long qemu_host_page_mask;
171
172/* XXX: for system emulation, it could just be an array */
173static PageDesc *l1_map[L1_SIZE];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700174static PhysPageDesc **l1_phys_map;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800175
176#if !defined(CONFIG_USER_ONLY)
177static void io_mem_init(void);
178
179/* io memory support */
180CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
181CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
182void *io_mem_opaque[IO_MEM_NB_ENTRIES];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700183static char io_mem_used[IO_MEM_NB_ENTRIES];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800184static int io_mem_watch;
185#endif
186
187/* log support */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700188#ifdef WIN32
189static const char *logfilename = "qemu.log";
190#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700191static const char *logfilename = "/tmp/qemu.log";
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700192#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800193FILE *logfile;
194int loglevel;
195static int log_append = 0;
196
197/* statistics */
198static int tlb_flush_count;
199static int tb_flush_count;
200static int tb_phys_invalidate_count;
201
202#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
203typedef struct subpage_t {
204 target_phys_addr_t base;
205 CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE][4];
206 CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE][4];
207 void *opaque[TARGET_PAGE_SIZE][2][4];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700208 ram_addr_t region_offset[TARGET_PAGE_SIZE][2][4];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800209} subpage_t;
210
211#ifdef _WIN32
212static void map_exec(void *addr, long size)
213{
214 DWORD old_protect;
215 VirtualProtect(addr, size,
216 PAGE_EXECUTE_READWRITE, &old_protect);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200217
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800218}
219#else
220static void map_exec(void *addr, long size)
221{
222 unsigned long start, end, page_size;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200223
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800224 page_size = getpagesize();
225 start = (unsigned long)addr;
226 start &= ~(page_size - 1);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200227
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800228 end = (unsigned long)addr + size;
229 end += page_size - 1;
230 end &= ~(page_size - 1);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200231
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800232 mprotect((void *)start, end - start,
233 PROT_READ | PROT_WRITE | PROT_EXEC);
234}
235#endif
236
237static void page_init(void)
238{
239 /* NOTE: we can always suppose that qemu_host_page_size >=
240 TARGET_PAGE_SIZE */
241#ifdef _WIN32
242 {
243 SYSTEM_INFO system_info;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800244
245 GetSystemInfo(&system_info);
246 qemu_real_host_page_size = system_info.dwPageSize;
247 }
248#else
249 qemu_real_host_page_size = getpagesize();
250#endif
251 if (qemu_host_page_size == 0)
252 qemu_host_page_size = qemu_real_host_page_size;
253 if (qemu_host_page_size < TARGET_PAGE_SIZE)
254 qemu_host_page_size = TARGET_PAGE_SIZE;
255 qemu_host_page_bits = 0;
256 while ((1 << qemu_host_page_bits) < qemu_host_page_size)
257 qemu_host_page_bits++;
258 qemu_host_page_mask = ~(qemu_host_page_size - 1);
259 l1_phys_map = qemu_vmalloc(L1_SIZE * sizeof(void *));
260 memset(l1_phys_map, 0, L1_SIZE * sizeof(void *));
261
262#if !defined(_WIN32) && defined(CONFIG_USER_ONLY)
263 {
264 long long startaddr, endaddr;
265 FILE *f;
266 int n;
267
268 mmap_lock();
269 last_brk = (unsigned long)sbrk(0);
270 f = fopen("/proc/self/maps", "r");
271 if (f) {
272 do {
273 n = fscanf (f, "%llx-%llx %*[^\n]\n", &startaddr, &endaddr);
274 if (n == 2) {
275 startaddr = MIN(startaddr,
276 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
277 endaddr = MIN(endaddr,
278 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
279 page_set_flags(startaddr & TARGET_PAGE_MASK,
280 TARGET_PAGE_ALIGN(endaddr),
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800281 PAGE_RESERVED);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800282 }
283 } while (!feof(f));
284 fclose(f);
285 }
286 mmap_unlock();
287 }
288#endif
289}
290
291static inline PageDesc **page_l1_map(target_ulong index)
292{
293#if TARGET_LONG_BITS > 32
294 /* Host memory outside guest VM. For 32-bit targets we have already
295 excluded high addresses. */
296 if (index > ((target_ulong)L2_SIZE * L1_SIZE))
297 return NULL;
298#endif
299 return &l1_map[index >> L2_BITS];
300}
301
302static inline PageDesc *page_find_alloc(target_ulong index)
303{
304 PageDesc **lp, *p;
305 lp = page_l1_map(index);
306 if (!lp)
307 return NULL;
308
309 p = *lp;
310 if (!p) {
311 /* allocate if not found */
312#if defined(CONFIG_USER_ONLY)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800313 size_t len = sizeof(PageDesc) * L2_SIZE;
314 /* Don't use qemu_malloc because it may recurse. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700315 p = mmap(NULL, len, PROT_READ | PROT_WRITE,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800316 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
317 *lp = p;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700318 if (h2g_valid(p)) {
319 unsigned long addr = h2g(p);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800320 page_set_flags(addr & TARGET_PAGE_MASK,
321 TARGET_PAGE_ALIGN(addr + len),
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800322 PAGE_RESERVED);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800323 }
324#else
325 p = qemu_mallocz(sizeof(PageDesc) * L2_SIZE);
326 *lp = p;
327#endif
328 }
329 return p + (index & (L2_SIZE - 1));
330}
331
332static inline PageDesc *page_find(target_ulong index)
333{
334 PageDesc **lp, *p;
335 lp = page_l1_map(index);
336 if (!lp)
337 return NULL;
338
339 p = *lp;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700340 if (!p) {
341 return NULL;
342 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800343 return p + (index & (L2_SIZE - 1));
344}
345
346static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
347{
348 void **lp, **p;
349 PhysPageDesc *pd;
350
351 p = (void **)l1_phys_map;
352#if TARGET_PHYS_ADDR_SPACE_BITS > 32
353
354#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
355#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
356#endif
357 lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1));
358 p = *lp;
359 if (!p) {
360 /* allocate if not found */
361 if (!alloc)
362 return NULL;
363 p = qemu_vmalloc(sizeof(void *) * L1_SIZE);
364 memset(p, 0, sizeof(void *) * L1_SIZE);
365 *lp = p;
366 }
367#endif
368 lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
369 pd = *lp;
370 if (!pd) {
371 int i;
372 /* allocate if not found */
373 if (!alloc)
374 return NULL;
375 pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
376 *lp = pd;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700377 for (i = 0; i < L2_SIZE; i++) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800378 pd[i].phys_offset = IO_MEM_UNASSIGNED;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700379 pd[i].region_offset = (index + i) << TARGET_PAGE_BITS;
380 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800381 }
382 return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
383}
384
385static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
386{
387 return phys_page_find_alloc(index, 0);
388}
389
390#if !defined(CONFIG_USER_ONLY)
391static void tlb_protect_code(ram_addr_t ram_addr);
392static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
393 target_ulong vaddr);
394#define mmap_lock() do { } while(0)
395#define mmap_unlock() do { } while(0)
396#endif
397
398#define DEFAULT_CODE_GEN_BUFFER_SIZE (32 * 1024 * 1024)
399
400#if defined(CONFIG_USER_ONLY)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700401/* Currently it is not recommended to allocate big chunks of data in
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800402 user mode. It will change when a dedicated libc will be used */
403#define USE_STATIC_CODE_GEN_BUFFER
404#endif
405
406#ifdef USE_STATIC_CODE_GEN_BUFFER
407static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE];
408#endif
409
410static void code_gen_alloc(unsigned long tb_size)
411{
412#ifdef USE_STATIC_CODE_GEN_BUFFER
413 code_gen_buffer = static_code_gen_buffer;
414 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
415 map_exec(code_gen_buffer, code_gen_buffer_size);
416#else
417 code_gen_buffer_size = tb_size;
418 if (code_gen_buffer_size == 0) {
419#if defined(CONFIG_USER_ONLY)
420 /* in user mode, phys_ram_size is not meaningful */
421 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
422#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700423 /* XXX: needs adjustments */
424 code_gen_buffer_size = (unsigned long)(ram_size / 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800425#endif
426 }
427 if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE)
428 code_gen_buffer_size = MIN_CODE_GEN_BUFFER_SIZE;
429 /* The code gen buffer location may have constraints depending on
430 the host cpu and OS */
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200431#if defined(__linux__)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800432 {
433 int flags;
434 void *start = NULL;
435
436 flags = MAP_PRIVATE | MAP_ANONYMOUS;
437#if defined(__x86_64__)
438 flags |= MAP_32BIT;
439 /* Cannot map more than that */
440 if (code_gen_buffer_size > (800 * 1024 * 1024))
441 code_gen_buffer_size = (800 * 1024 * 1024);
442#elif defined(__sparc_v9__)
443 // Map the buffer below 2G, so we can use direct calls and branches
444 flags |= MAP_FIXED;
445 start = (void *) 0x60000000UL;
446 if (code_gen_buffer_size > (512 * 1024 * 1024))
447 code_gen_buffer_size = (512 * 1024 * 1024);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700448#elif defined(__arm__)
449 /* Map the buffer below 32M, so we can use direct calls and branches */
450 flags |= MAP_FIXED;
451 start = (void *) 0x01000000UL;
452 if (code_gen_buffer_size > 16 * 1024 * 1024)
453 code_gen_buffer_size = 16 * 1024 * 1024;
David 'Digit' Turner36411062010-12-22 17:34:53 +0100454#elif defined(__s390x__)
455 /* Map the buffer so that we can use direct calls and branches. */
456 /* We have a +- 4GB range on the branches; leave some slop. */
457 if (code_gen_buffer_size > (3ul * 1024 * 1024 * 1024)) {
458 code_gen_buffer_size = 3ul * 1024 * 1024 * 1024;
459 }
460 start = (void *)0x90000000UL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800461#endif
462 code_gen_buffer = mmap(start, code_gen_buffer_size,
463 PROT_WRITE | PROT_READ | PROT_EXEC,
464 flags, -1, 0);
465 if (code_gen_buffer == MAP_FAILED) {
466 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
467 exit(1);
468 }
469 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200470#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \
471 || defined(__DragonFly__) || defined(__OpenBSD__)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700472 {
473 int flags;
474 void *addr = NULL;
475 flags = MAP_PRIVATE | MAP_ANONYMOUS;
476#if defined(__x86_64__)
477 /* FreeBSD doesn't have MAP_32BIT, use MAP_FIXED and assume
478 * 0x40000000 is free */
479 flags |= MAP_FIXED;
480 addr = (void *)0x40000000;
481 /* Cannot map more than that */
482 if (code_gen_buffer_size > (800 * 1024 * 1024))
483 code_gen_buffer_size = (800 * 1024 * 1024);
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200484#elif defined(__sparc_v9__)
485 // Map the buffer below 2G, so we can use direct calls and branches
486 flags |= MAP_FIXED;
487 addr = (void *) 0x60000000UL;
488 if (code_gen_buffer_size > (512 * 1024 * 1024)) {
489 code_gen_buffer_size = (512 * 1024 * 1024);
490 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700491#endif
492 code_gen_buffer = mmap(addr, code_gen_buffer_size,
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200493 PROT_WRITE | PROT_READ | PROT_EXEC,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700494 flags, -1, 0);
495 if (code_gen_buffer == MAP_FAILED) {
496 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
497 exit(1);
498 }
499 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800500#else
501 code_gen_buffer = qemu_malloc(code_gen_buffer_size);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800502 map_exec(code_gen_buffer, code_gen_buffer_size);
503#endif
504#endif /* !USE_STATIC_CODE_GEN_BUFFER */
505 map_exec(code_gen_prologue, sizeof(code_gen_prologue));
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800506 code_gen_buffer_max_size = code_gen_buffer_size -
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800507 code_gen_max_block_size();
508 code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
509 tbs = qemu_malloc(code_gen_max_blocks * sizeof(TranslationBlock));
510}
511
512/* Must be called before using the QEMU cpus. 'tb_size' is the size
513 (in bytes) allocated to the translation buffer. Zero means default
514 size. */
515void cpu_exec_init_all(unsigned long tb_size)
516{
517 cpu_gen_init();
518 code_gen_alloc(tb_size);
519 code_gen_ptr = code_gen_buffer;
520 page_init();
521#if !defined(CONFIG_USER_ONLY)
522 io_mem_init();
523#endif
524}
525
526#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
527
528#define CPU_COMMON_SAVE_VERSION 1
529
530static void cpu_common_save(QEMUFile *f, void *opaque)
531{
532 CPUState *env = opaque;
533
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700534 cpu_synchronize_state(env, 0);
535
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800536 qemu_put_be32s(f, &env->halted);
537 qemu_put_be32s(f, &env->interrupt_request);
538}
539
540static int cpu_common_load(QEMUFile *f, void *opaque, int version_id)
541{
542 CPUState *env = opaque;
543
544 if (version_id != CPU_COMMON_SAVE_VERSION)
545 return -EINVAL;
546
547 qemu_get_be32s(f, &env->halted);
548 qemu_get_be32s(f, &env->interrupt_request);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700549 /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
550 version_id is increased. */
551 env->interrupt_request &= ~0x01;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800552 tlb_flush(env, 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700553 cpu_synchronize_state(env, 1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800554
555 return 0;
556}
557#endif
558
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700559CPUState *qemu_get_cpu(int cpu)
560{
561 CPUState *env = first_cpu;
562
563 while (env) {
564 if (env->cpu_index == cpu)
565 break;
566 env = env->next_cpu;
567 }
568
569 return env;
570}
571
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800572void cpu_exec_init(CPUState *env)
573{
574 CPUState **penv;
575 int cpu_index;
576
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700577#if defined(CONFIG_USER_ONLY)
578 cpu_list_lock();
579#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800580 env->next_cpu = NULL;
581 penv = &first_cpu;
582 cpu_index = 0;
583 while (*penv != NULL) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700584 penv = &(*penv)->next_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800585 cpu_index++;
586 }
587 env->cpu_index = cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700588 env->numa_node = 0;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700589 QTAILQ_INIT(&env->breakpoints);
590 QTAILQ_INIT(&env->watchpoints);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800591 *penv = env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700592#if defined(CONFIG_USER_ONLY)
593 cpu_list_unlock();
594#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800595#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
596 register_savevm("cpu_common", cpu_index, CPU_COMMON_SAVE_VERSION,
597 cpu_common_save, cpu_common_load, env);
598 register_savevm("cpu", cpu_index, CPU_SAVE_VERSION,
599 cpu_save, cpu_load, env);
600#endif
601}
602
603static inline void invalidate_page_bitmap(PageDesc *p)
604{
605 if (p->code_bitmap) {
606 qemu_free(p->code_bitmap);
607 p->code_bitmap = NULL;
608 }
609 p->code_write_count = 0;
610}
611
612/* set to NULL all the 'first_tb' fields in all PageDescs */
613static void page_flush_tb(void)
614{
615 int i, j;
616 PageDesc *p;
617
618 for(i = 0; i < L1_SIZE; i++) {
619 p = l1_map[i];
620 if (p) {
621 for(j = 0; j < L2_SIZE; j++) {
622 p->first_tb = NULL;
623 invalidate_page_bitmap(p);
624 p++;
625 }
626 }
627 }
628}
629
630/* flush all the translation blocks */
631/* XXX: tb_flush is currently not thread safe */
632void tb_flush(CPUState *env1)
633{
634 CPUState *env;
635#if defined(DEBUG_FLUSH)
636 printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
637 (unsigned long)(code_gen_ptr - code_gen_buffer),
638 nb_tbs, nb_tbs > 0 ?
639 ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
640#endif
641 if ((unsigned long)(code_gen_ptr - code_gen_buffer) > code_gen_buffer_size)
642 cpu_abort(env1, "Internal error: code buffer overflow\n");
643
644 nb_tbs = 0;
645
646 for(env = first_cpu; env != NULL; env = env->next_cpu) {
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800647#ifdef CONFIG_MEMCHECK
648 int tb_to_clean;
649 for (tb_to_clean = 0; tb_to_clean < TB_JMP_CACHE_SIZE; tb_to_clean++) {
650 if (env->tb_jmp_cache[tb_to_clean] != NULL &&
651 env->tb_jmp_cache[tb_to_clean]->tpc2gpc != NULL) {
652 qemu_free(env->tb_jmp_cache[tb_to_clean]->tpc2gpc);
653 env->tb_jmp_cache[tb_to_clean]->tpc2gpc = NULL;
654 env->tb_jmp_cache[tb_to_clean]->tpc2gpc_pairs = 0;
655 }
656 }
657#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800658 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
659 }
660
661 memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
662 page_flush_tb();
663
664 code_gen_ptr = code_gen_buffer;
665 /* XXX: flush processor icache at this point if cache flush is
666 expensive */
667 tb_flush_count++;
668}
669
670#ifdef DEBUG_TB_CHECK
671
672static void tb_invalidate_check(target_ulong address)
673{
674 TranslationBlock *tb;
675 int i;
676 address &= TARGET_PAGE_MASK;
677 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
678 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
679 if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
680 address >= tb->pc + tb->size)) {
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700681 printf("ERROR invalidate: address=" TARGET_FMT_lx
682 " PC=%08lx size=%04x\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800683 address, (long)tb->pc, tb->size);
684 }
685 }
686 }
687}
688
689/* verify that all the pages have correct rights for code */
690static void tb_page_check(void)
691{
692 TranslationBlock *tb;
693 int i, flags1, flags2;
694
695 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
696 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
697 flags1 = page_get_flags(tb->pc);
698 flags2 = page_get_flags(tb->pc + tb->size - 1);
699 if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
700 printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
701 (long)tb->pc, tb->size, flags1, flags2);
702 }
703 }
704 }
705}
706
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800707#endif
708
709/* invalidate one TB */
710static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb,
711 int next_offset)
712{
713 TranslationBlock *tb1;
714 for(;;) {
715 tb1 = *ptb;
716 if (tb1 == tb) {
717 *ptb = *(TranslationBlock **)((char *)tb1 + next_offset);
718 break;
719 }
720 ptb = (TranslationBlock **)((char *)tb1 + next_offset);
721 }
722}
723
724static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
725{
726 TranslationBlock *tb1;
727 unsigned int n1;
728
729 for(;;) {
730 tb1 = *ptb;
731 n1 = (long)tb1 & 3;
732 tb1 = (TranslationBlock *)((long)tb1 & ~3);
733 if (tb1 == tb) {
734 *ptb = tb1->page_next[n1];
735 break;
736 }
737 ptb = &tb1->page_next[n1];
738 }
739}
740
741static inline void tb_jmp_remove(TranslationBlock *tb, int n)
742{
743 TranslationBlock *tb1, **ptb;
744 unsigned int n1;
745
746 ptb = &tb->jmp_next[n];
747 tb1 = *ptb;
748 if (tb1) {
749 /* find tb(n) in circular list */
750 for(;;) {
751 tb1 = *ptb;
752 n1 = (long)tb1 & 3;
753 tb1 = (TranslationBlock *)((long)tb1 & ~3);
754 if (n1 == n && tb1 == tb)
755 break;
756 if (n1 == 2) {
757 ptb = &tb1->jmp_first;
758 } else {
759 ptb = &tb1->jmp_next[n1];
760 }
761 }
762 /* now we can suppress tb(n) from the list */
763 *ptb = tb->jmp_next[n];
764
765 tb->jmp_next[n] = NULL;
766 }
767}
768
769/* reset the jump entry 'n' of a TB so that it is not chained to
770 another TB */
771static inline void tb_reset_jump(TranslationBlock *tb, int n)
772{
773 tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
774}
775
776void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr)
777{
778 CPUState *env;
779 PageDesc *p;
780 unsigned int h, n1;
781 target_phys_addr_t phys_pc;
782 TranslationBlock *tb1, *tb2;
783
784 /* remove the TB from the hash list */
785 phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
786 h = tb_phys_hash_func(phys_pc);
787 tb_remove(&tb_phys_hash[h], tb,
788 offsetof(TranslationBlock, phys_hash_next));
789
790 /* remove the TB from the page list */
791 if (tb->page_addr[0] != page_addr) {
792 p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
793 tb_page_remove(&p->first_tb, tb);
794 invalidate_page_bitmap(p);
795 }
796 if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
797 p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
798 tb_page_remove(&p->first_tb, tb);
799 invalidate_page_bitmap(p);
800 }
801
802 tb_invalidated_flag = 1;
803
804 /* remove the TB from the hash list */
805 h = tb_jmp_cache_hash_func(tb->pc);
806 for(env = first_cpu; env != NULL; env = env->next_cpu) {
807 if (env->tb_jmp_cache[h] == tb)
808 env->tb_jmp_cache[h] = NULL;
809 }
810
811 /* suppress this TB from the two jump lists */
812 tb_jmp_remove(tb, 0);
813 tb_jmp_remove(tb, 1);
814
815 /* suppress any remaining jumps to this TB */
816 tb1 = tb->jmp_first;
817 for(;;) {
818 n1 = (long)tb1 & 3;
819 if (n1 == 2)
820 break;
821 tb1 = (TranslationBlock *)((long)tb1 & ~3);
822 tb2 = tb1->jmp_next[n1];
823 tb_reset_jump(tb1, n1);
824 tb1->jmp_next[n1] = NULL;
825 tb1 = tb2;
826 }
827 tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
828
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800829#ifdef CONFIG_MEMCHECK
830 if (tb->tpc2gpc != NULL) {
831 qemu_free(tb->tpc2gpc);
832 tb->tpc2gpc = NULL;
833 tb->tpc2gpc_pairs = 0;
834 }
835#endif // CONFIG_MEMCHECK
836
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800837 tb_phys_invalidate_count++;
838}
839
840static inline void set_bits(uint8_t *tab, int start, int len)
841{
842 int end, mask, end1;
843
844 end = start + len;
845 tab += start >> 3;
846 mask = 0xff << (start & 7);
847 if ((start & ~7) == (end & ~7)) {
848 if (start < end) {
849 mask &= ~(0xff << (end & 7));
850 *tab |= mask;
851 }
852 } else {
853 *tab++ |= mask;
854 start = (start + 8) & ~7;
855 end1 = end & ~7;
856 while (start < end1) {
857 *tab++ = 0xff;
858 start += 8;
859 }
860 if (start < end) {
861 mask = ~(0xff << (end & 7));
862 *tab |= mask;
863 }
864 }
865}
866
867static void build_page_bitmap(PageDesc *p)
868{
869 int n, tb_start, tb_end;
870 TranslationBlock *tb;
871
872 p->code_bitmap = qemu_mallocz(TARGET_PAGE_SIZE / 8);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800873
874 tb = p->first_tb;
875 while (tb != NULL) {
876 n = (long)tb & 3;
877 tb = (TranslationBlock *)((long)tb & ~3);
878 /* NOTE: this is subtle as a TB may span two physical pages */
879 if (n == 0) {
880 /* NOTE: tb_end may be after the end of the page, but
881 it is not a problem */
882 tb_start = tb->pc & ~TARGET_PAGE_MASK;
883 tb_end = tb_start + tb->size;
884 if (tb_end > TARGET_PAGE_SIZE)
885 tb_end = TARGET_PAGE_SIZE;
886 } else {
887 tb_start = 0;
888 tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
889 }
890 set_bits(p->code_bitmap, tb_start, tb_end - tb_start);
891 tb = tb->page_next[n];
892 }
893}
894
895TranslationBlock *tb_gen_code(CPUState *env,
896 target_ulong pc, target_ulong cs_base,
897 int flags, int cflags)
898{
899 TranslationBlock *tb;
900 uint8_t *tc_ptr;
901 target_ulong phys_pc, phys_page2, virt_page2;
902 int code_gen_size;
903
904 phys_pc = get_phys_addr_code(env, pc);
905 tb = tb_alloc(pc);
906 if (!tb) {
907 /* flush must be done */
908 tb_flush(env);
909 /* cannot fail at this point */
910 tb = tb_alloc(pc);
911 /* Don't forget to invalidate previous TB info. */
912 tb_invalidated_flag = 1;
913 }
914 tc_ptr = code_gen_ptr;
915 tb->tc_ptr = tc_ptr;
916 tb->cs_base = cs_base;
917 tb->flags = flags;
918 tb->cflags = cflags;
919#ifdef CONFIG_TRACE
920 tb->bb_rec = NULL;
921 tb->prev_time = 0;
922#endif
923 cpu_gen_code(env, tb, &code_gen_size);
924 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
925
926 /* check next page if needed */
927 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
928 phys_page2 = -1;
929 if ((pc & TARGET_PAGE_MASK) != virt_page2) {
930 phys_page2 = get_phys_addr_code(env, virt_page2);
931 }
932 tb_link_phys(tb, phys_pc, phys_page2);
933 return tb;
934}
935
936/* invalidate all TBs which intersect with the target physical page
937 starting in range [start;end[. NOTE: start and end must refer to
938 the same physical page. 'is_cpu_write_access' should be true if called
939 from a real cpu write access: the virtual CPU will exit the current
940 TB if code is modified inside this TB. */
941void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t end,
942 int is_cpu_write_access)
943{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700944 TranslationBlock *tb, *tb_next, *saved_tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800945 CPUState *env = cpu_single_env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800946 target_ulong tb_start, tb_end;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700947 PageDesc *p;
948 int n;
949#ifdef TARGET_HAS_PRECISE_SMC
950 int current_tb_not_found = is_cpu_write_access;
951 TranslationBlock *current_tb = NULL;
952 int current_tb_modified = 0;
953 target_ulong current_pc = 0;
954 target_ulong current_cs_base = 0;
955 int current_flags = 0;
956#endif /* TARGET_HAS_PRECISE_SMC */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800957
958 p = page_find(start >> TARGET_PAGE_BITS);
959 if (!p)
960 return;
961 if (!p->code_bitmap &&
962 ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
963 is_cpu_write_access) {
964 /* build code bitmap */
965 build_page_bitmap(p);
966 }
967
968 /* we remove all the TBs in the range [start, end[ */
969 /* 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 -0800970 tb = p->first_tb;
971 while (tb != NULL) {
972 n = (long)tb & 3;
973 tb = (TranslationBlock *)((long)tb & ~3);
974 tb_next = tb->page_next[n];
975 /* NOTE: this is subtle as a TB may span two physical pages */
976 if (n == 0) {
977 /* NOTE: tb_end may be after the end of the page, but
978 it is not a problem */
979 tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
980 tb_end = tb_start + tb->size;
981 } else {
982 tb_start = tb->page_addr[1];
983 tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
984 }
985 if (!(tb_end <= start || tb_start >= end)) {
986#ifdef TARGET_HAS_PRECISE_SMC
987 if (current_tb_not_found) {
988 current_tb_not_found = 0;
989 current_tb = NULL;
990 if (env->mem_io_pc) {
991 /* now we have a real cpu fault */
992 current_tb = tb_find_pc(env->mem_io_pc);
993 }
994 }
995 if (current_tb == tb &&
996 (current_tb->cflags & CF_COUNT_MASK) != 1) {
997 /* If we are modifying the current TB, we must stop
998 its execution. We could be more precise by checking
999 that the modification is after the current PC, but it
1000 would require a specialized function to partially
1001 restore the CPU state */
1002
1003 current_tb_modified = 1;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02001004 cpu_restore_state(current_tb, env, env->mem_io_pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001005 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
1006 &current_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001007 }
1008#endif /* TARGET_HAS_PRECISE_SMC */
1009 /* we need to do that to handle the case where a signal
1010 occurs while doing tb_phys_invalidate() */
1011 saved_tb = NULL;
1012 if (env) {
1013 saved_tb = env->current_tb;
1014 env->current_tb = NULL;
1015 }
1016 tb_phys_invalidate(tb, -1);
1017 if (env) {
1018 env->current_tb = saved_tb;
1019 if (env->interrupt_request && env->current_tb)
1020 cpu_interrupt(env, env->interrupt_request);
1021 }
1022 }
1023 tb = tb_next;
1024 }
1025#if !defined(CONFIG_USER_ONLY)
1026 /* if no code remaining, no need to continue to use slow writes */
1027 if (!p->first_tb) {
1028 invalidate_page_bitmap(p);
1029 if (is_cpu_write_access) {
1030 tlb_unprotect_code_phys(env, start, env->mem_io_vaddr);
1031 }
1032 }
1033#endif
1034#ifdef TARGET_HAS_PRECISE_SMC
1035 if (current_tb_modified) {
1036 /* we generate a block containing just the instruction
1037 modifying the memory. It will ensure that it cannot modify
1038 itself */
1039 env->current_tb = NULL;
1040 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1041 cpu_resume_from_signal(env, NULL);
1042 }
1043#endif
1044}
1045
1046/* len must be <= 8 and start must be a multiple of len */
1047static inline void tb_invalidate_phys_page_fast(target_phys_addr_t start, int len)
1048{
1049 PageDesc *p;
1050 int offset, b;
1051#if 0
1052 if (1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001053 qemu_log("modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
1054 cpu_single_env->mem_io_vaddr, len,
1055 cpu_single_env->eip,
1056 cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001057 }
1058#endif
1059 p = page_find(start >> TARGET_PAGE_BITS);
1060 if (!p)
1061 return;
1062 if (p->code_bitmap) {
1063 offset = start & ~TARGET_PAGE_MASK;
1064 b = p->code_bitmap[offset >> 3] >> (offset & 7);
1065 if (b & ((1 << len) - 1))
1066 goto do_invalidate;
1067 } else {
1068 do_invalidate:
1069 tb_invalidate_phys_page_range(start, start + len, 1);
1070 }
1071}
1072
1073#if !defined(CONFIG_SOFTMMU)
1074static void tb_invalidate_phys_page(target_phys_addr_t addr,
1075 unsigned long pc, void *puc)
1076{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001077 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001078 PageDesc *p;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001079 int n;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001080#ifdef TARGET_HAS_PRECISE_SMC
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001081 TranslationBlock *current_tb = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001082 CPUState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001083 int current_tb_modified = 0;
1084 target_ulong current_pc = 0;
1085 target_ulong current_cs_base = 0;
1086 int current_flags = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001087#endif
1088
1089 addr &= TARGET_PAGE_MASK;
1090 p = page_find(addr >> TARGET_PAGE_BITS);
1091 if (!p)
1092 return;
1093 tb = p->first_tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001094#ifdef TARGET_HAS_PRECISE_SMC
1095 if (tb && pc != 0) {
1096 current_tb = tb_find_pc(pc);
1097 }
1098#endif
1099 while (tb != NULL) {
1100 n = (long)tb & 3;
1101 tb = (TranslationBlock *)((long)tb & ~3);
1102#ifdef TARGET_HAS_PRECISE_SMC
1103 if (current_tb == tb &&
1104 (current_tb->cflags & CF_COUNT_MASK) != 1) {
1105 /* If we are modifying the current TB, we must stop
1106 its execution. We could be more precise by checking
1107 that the modification is after the current PC, but it
1108 would require a specialized function to partially
1109 restore the CPU state */
1110
1111 current_tb_modified = 1;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02001112 cpu_restore_state(current_tb, env, pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001113 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
1114 &current_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001115 }
1116#endif /* TARGET_HAS_PRECISE_SMC */
1117 tb_phys_invalidate(tb, addr);
1118 tb = tb->page_next[n];
1119 }
1120 p->first_tb = NULL;
1121#ifdef TARGET_HAS_PRECISE_SMC
1122 if (current_tb_modified) {
1123 /* we generate a block containing just the instruction
1124 modifying the memory. It will ensure that it cannot modify
1125 itself */
1126 env->current_tb = NULL;
1127 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1128 cpu_resume_from_signal(env, puc);
1129 }
1130#endif
1131}
1132#endif
1133
1134/* add the tb in the target page and protect it if necessary */
1135static inline void tb_alloc_page(TranslationBlock *tb,
1136 unsigned int n, target_ulong page_addr)
1137{
1138 PageDesc *p;
1139 TranslationBlock *last_first_tb;
1140
1141 tb->page_addr[n] = page_addr;
1142 p = page_find_alloc(page_addr >> TARGET_PAGE_BITS);
1143 tb->page_next[n] = p->first_tb;
1144 last_first_tb = p->first_tb;
1145 p->first_tb = (TranslationBlock *)((long)tb | n);
1146 invalidate_page_bitmap(p);
1147
1148#if defined(TARGET_HAS_SMC) || 1
1149
1150#if defined(CONFIG_USER_ONLY)
1151 if (p->flags & PAGE_WRITE) {
1152 target_ulong addr;
1153 PageDesc *p2;
1154 int prot;
1155
1156 /* force the host page as non writable (writes will have a
1157 page fault + mprotect overhead) */
1158 page_addr &= qemu_host_page_mask;
1159 prot = 0;
1160 for(addr = page_addr; addr < page_addr + qemu_host_page_size;
1161 addr += TARGET_PAGE_SIZE) {
1162
1163 p2 = page_find (addr >> TARGET_PAGE_BITS);
1164 if (!p2)
1165 continue;
1166 prot |= p2->flags;
1167 p2->flags &= ~PAGE_WRITE;
1168 page_get_flags(addr);
1169 }
1170 mprotect(g2h(page_addr), qemu_host_page_size,
1171 (prot & PAGE_BITS) & ~PAGE_WRITE);
1172#ifdef DEBUG_TB_INVALIDATE
1173 printf("protecting code page: 0x" TARGET_FMT_lx "\n",
1174 page_addr);
1175#endif
1176 }
1177#else
1178 /* if some code is already present, then the pages are already
1179 protected. So we handle the case where only the first TB is
1180 allocated in a physical page */
1181 if (!last_first_tb) {
1182 tlb_protect_code(page_addr);
1183 }
1184#endif
1185
1186#endif /* TARGET_HAS_SMC */
1187}
1188
1189/* Allocate a new translation block. Flush the translation buffer if
1190 too many translation blocks or too much generated code. */
1191TranslationBlock *tb_alloc(target_ulong pc)
1192{
1193 TranslationBlock *tb;
1194
1195 if (nb_tbs >= code_gen_max_blocks ||
1196 (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
1197 return NULL;
1198 tb = &tbs[nb_tbs++];
1199 tb->pc = pc;
1200 tb->cflags = 0;
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -08001201#ifdef CONFIG_MEMCHECK
1202 tb->tpc2gpc = NULL;
1203 tb->tpc2gpc_pairs = 0;
1204#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001205 return tb;
1206}
1207
1208void tb_free(TranslationBlock *tb)
1209{
1210 /* In practice this is mostly used for single use temporary TB
1211 Ignore the hard cases and just back up if this TB happens to
1212 be the last one generated. */
1213 if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) {
1214 code_gen_ptr = tb->tc_ptr;
1215 nb_tbs--;
1216 }
1217}
1218
1219/* add a new TB and link it to the physical page tables. phys_page2 is
1220 (-1) to indicate that only one page contains the TB. */
1221void tb_link_phys(TranslationBlock *tb,
1222 target_ulong phys_pc, target_ulong phys_page2)
1223{
1224 unsigned int h;
1225 TranslationBlock **ptb;
1226
1227 /* Grab the mmap lock to stop another thread invalidating this TB
1228 before we are done. */
1229 mmap_lock();
1230 /* add in the physical hash table */
1231 h = tb_phys_hash_func(phys_pc);
1232 ptb = &tb_phys_hash[h];
1233 tb->phys_hash_next = *ptb;
1234 *ptb = tb;
1235
1236 /* add in the page list */
1237 tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK);
1238 if (phys_page2 != -1)
1239 tb_alloc_page(tb, 1, phys_page2);
1240 else
1241 tb->page_addr[1] = -1;
1242
1243 tb->jmp_first = (TranslationBlock *)((long)tb | 2);
1244 tb->jmp_next[0] = NULL;
1245 tb->jmp_next[1] = NULL;
1246
1247 /* init original jump addresses */
1248 if (tb->tb_next_offset[0] != 0xffff)
1249 tb_reset_jump(tb, 0);
1250 if (tb->tb_next_offset[1] != 0xffff)
1251 tb_reset_jump(tb, 1);
1252
1253#ifdef DEBUG_TB_CHECK
1254 tb_page_check();
1255#endif
1256 mmap_unlock();
1257}
1258
1259/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
1260 tb[1].tc_ptr. Return NULL if not found */
1261TranslationBlock *tb_find_pc(unsigned long tc_ptr)
1262{
1263 int m_min, m_max, m;
1264 unsigned long v;
1265 TranslationBlock *tb;
1266
1267 if (nb_tbs <= 0)
1268 return NULL;
1269 if (tc_ptr < (unsigned long)code_gen_buffer ||
1270 tc_ptr >= (unsigned long)code_gen_ptr)
1271 return NULL;
1272 /* binary search (cf Knuth) */
1273 m_min = 0;
1274 m_max = nb_tbs - 1;
1275 while (m_min <= m_max) {
1276 m = (m_min + m_max) >> 1;
1277 tb = &tbs[m];
1278 v = (unsigned long)tb->tc_ptr;
1279 if (v == tc_ptr)
1280 return tb;
1281 else if (tc_ptr < v) {
1282 m_max = m - 1;
1283 } else {
1284 m_min = m + 1;
1285 }
1286 }
1287 return &tbs[m_max];
1288}
1289
1290static void tb_reset_jump_recursive(TranslationBlock *tb);
1291
1292static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
1293{
1294 TranslationBlock *tb1, *tb_next, **ptb;
1295 unsigned int n1;
1296
1297 tb1 = tb->jmp_next[n];
1298 if (tb1 != NULL) {
1299 /* find head of list */
1300 for(;;) {
1301 n1 = (long)tb1 & 3;
1302 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1303 if (n1 == 2)
1304 break;
1305 tb1 = tb1->jmp_next[n1];
1306 }
1307 /* we are now sure now that tb jumps to tb1 */
1308 tb_next = tb1;
1309
1310 /* remove tb from the jmp_first list */
1311 ptb = &tb_next->jmp_first;
1312 for(;;) {
1313 tb1 = *ptb;
1314 n1 = (long)tb1 & 3;
1315 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1316 if (n1 == n && tb1 == tb)
1317 break;
1318 ptb = &tb1->jmp_next[n1];
1319 }
1320 *ptb = tb->jmp_next[n];
1321 tb->jmp_next[n] = NULL;
1322
1323 /* suppress the jump to next tb in generated code */
1324 tb_reset_jump(tb, n);
1325
1326 /* suppress jumps in the tb on which we could have jumped */
1327 tb_reset_jump_recursive(tb_next);
1328 }
1329}
1330
1331static void tb_reset_jump_recursive(TranslationBlock *tb)
1332{
1333 tb_reset_jump_recursive2(tb, 0);
1334 tb_reset_jump_recursive2(tb, 1);
1335}
1336
1337#if defined(TARGET_HAS_ICE)
1338static void breakpoint_invalidate(CPUState *env, target_ulong pc)
1339{
1340 target_phys_addr_t addr;
1341 target_ulong pd;
1342 ram_addr_t ram_addr;
1343 PhysPageDesc *p;
1344
1345 addr = cpu_get_phys_page_debug(env, pc);
1346 p = phys_page_find(addr >> TARGET_PAGE_BITS);
1347 if (!p) {
1348 pd = IO_MEM_UNASSIGNED;
1349 } else {
1350 pd = p->phys_offset;
1351 }
1352 ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
1353 tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
1354}
1355#endif
1356
1357/* Add a watchpoint. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001358int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
1359 int flags, CPUWatchpoint **watchpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001360{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001361 target_ulong len_mask = ~(len - 1);
1362 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001363
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001364 /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
1365 if ((len != 1 && len != 2 && len != 4 && len != 8) || (addr & ~len_mask)) {
1366 fprintf(stderr, "qemu: tried to set invalid watchpoint at "
1367 TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
1368 return -EINVAL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001369 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001370 wp = qemu_malloc(sizeof(*wp));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001371
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001372 wp->vaddr = addr;
1373 wp->len_mask = len_mask;
1374 wp->flags = flags;
1375
1376 /* keep all GDB-injected watchpoints in front */
1377 if (flags & BP_GDB)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001378 QTAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001379 else
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001380 QTAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001381
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001382 tlb_flush_page(env, addr);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001383
1384 if (watchpoint)
1385 *watchpoint = wp;
1386 return 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001387}
1388
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001389/* Remove a specific watchpoint. */
1390int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len,
1391 int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001392{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001393 target_ulong len_mask = ~(len - 1);
1394 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001395
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001396 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001397 if (addr == wp->vaddr && len_mask == wp->len_mask
1398 && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
1399 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001400 return 0;
1401 }
1402 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001403 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001404}
1405
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001406/* Remove a specific watchpoint by reference. */
1407void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint)
1408{
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001409 QTAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001410
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001411 tlb_flush_page(env, watchpoint->vaddr);
1412
1413 qemu_free(watchpoint);
1414}
1415
1416/* Remove all matching watchpoints. */
1417void cpu_watchpoint_remove_all(CPUState *env, int mask)
1418{
1419 CPUWatchpoint *wp, *next;
1420
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001421 QTAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001422 if (wp->flags & mask)
1423 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001424 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001425}
1426
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001427/* Add a breakpoint. */
1428int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
1429 CPUBreakpoint **breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001430{
1431#if defined(TARGET_HAS_ICE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001432 CPUBreakpoint *bp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001433
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001434 bp = qemu_malloc(sizeof(*bp));
1435
1436 bp->pc = pc;
1437 bp->flags = flags;
1438
1439 /* keep all GDB-injected breakpoints in front */
1440 if (flags & BP_GDB)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001441 QTAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001442 else
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001443 QTAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001444
1445 breakpoint_invalidate(env, pc);
1446
1447 if (breakpoint)
1448 *breakpoint = bp;
1449 return 0;
1450#else
1451 return -ENOSYS;
1452#endif
1453}
1454
1455/* Remove a specific breakpoint. */
1456int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags)
1457{
1458#if defined(TARGET_HAS_ICE)
1459 CPUBreakpoint *bp;
1460
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001461 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001462 if (bp->pc == pc && bp->flags == flags) {
1463 cpu_breakpoint_remove_by_ref(env, bp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001464 return 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001465 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001466 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001467 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001468#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001469 return -ENOSYS;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001470#endif
1471}
1472
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001473/* Remove a specific breakpoint by reference. */
1474void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001475{
1476#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001477 QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001478
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001479 breakpoint_invalidate(env, breakpoint->pc);
1480
1481 qemu_free(breakpoint);
1482#endif
1483}
1484
1485/* Remove all matching breakpoints. */
1486void cpu_breakpoint_remove_all(CPUState *env, int mask)
1487{
1488#if defined(TARGET_HAS_ICE)
1489 CPUBreakpoint *bp, *next;
1490
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001491 QTAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001492 if (bp->flags & mask)
1493 cpu_breakpoint_remove_by_ref(env, bp);
1494 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001495#endif
1496}
1497
1498/* enable or disable single step mode. EXCP_DEBUG is returned by the
1499 CPU loop after each instruction */
1500void cpu_single_step(CPUState *env, int enabled)
1501{
1502#if defined(TARGET_HAS_ICE)
1503 if (env->singlestep_enabled != enabled) {
1504 env->singlestep_enabled = enabled;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001505 if (kvm_enabled())
1506 kvm_update_guest_debug(env, 0);
1507 else {
1508 /* must flush all the translated code to avoid inconsistencies */
1509 /* XXX: only flush what is necessary */
1510 tb_flush(env);
1511 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001512 }
1513#endif
1514}
1515
1516/* enable or disable low levels log */
1517void cpu_set_log(int log_flags)
1518{
1519 loglevel = log_flags;
1520 if (loglevel && !logfile) {
1521 logfile = fopen(logfilename, log_append ? "a" : "w");
1522 if (!logfile) {
1523 perror(logfilename);
1524 _exit(1);
1525 }
1526#if !defined(CONFIG_SOFTMMU)
1527 /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1528 {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001529 static char logfile_buf[4096];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001530 setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1531 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001532#elif !defined(_WIN32)
1533 /* Win32 doesn't support line-buffering and requires size >= 2 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001534 setvbuf(logfile, NULL, _IOLBF, 0);
1535#endif
1536 log_append = 1;
1537 }
1538 if (!loglevel && logfile) {
1539 fclose(logfile);
1540 logfile = NULL;
1541 }
1542}
1543
1544void cpu_set_log_filename(const char *filename)
1545{
1546 logfilename = strdup(filename);
1547 if (logfile) {
1548 fclose(logfile);
1549 logfile = NULL;
1550 }
1551 cpu_set_log(loglevel);
1552}
1553
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001554static void cpu_unlink_tb(CPUState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001555{
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001556 /* FIXME: TB unchaining isn't SMP safe. For now just ignore the
1557 problem and hope the cpu will stop of its own accord. For userspace
1558 emulation this often isn't actually as bad as it sounds. Often
1559 signals are used primarily to interrupt blocking syscalls. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001560 TranslationBlock *tb;
1561 static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
1562
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001563 spin_lock(&interrupt_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001564 tb = env->current_tb;
1565 /* if the cpu is currently executing code, we must unlink it and
1566 all the potentially executing TB */
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001567 if (tb) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001568 env->current_tb = NULL;
1569 tb_reset_jump_recursive(tb);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001570 }
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001571 spin_unlock(&interrupt_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001572}
1573
1574/* mask must never be zero, except for A20 change call */
1575void cpu_interrupt(CPUState *env, int mask)
1576{
1577 int old_mask;
1578
1579 old_mask = env->interrupt_request;
1580 env->interrupt_request |= mask;
1581
1582#ifndef CONFIG_USER_ONLY
1583 /*
1584 * If called from iothread context, wake the target cpu in
1585 * case its halted.
1586 */
1587 if (!qemu_cpu_self(env)) {
1588 qemu_cpu_kick(env);
1589 return;
1590 }
1591#endif
1592
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001593 if (use_icount) {
1594 env->icount_decr.u16.high = 0xffff;
1595#ifndef CONFIG_USER_ONLY
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001596 if (!can_do_io(env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001597 && (mask & ~old_mask) != 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001598 cpu_abort(env, "Raised interrupt while not in I/O function");
1599 }
1600#endif
1601 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001602 cpu_unlink_tb(env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001603 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001604}
1605
1606void cpu_reset_interrupt(CPUState *env, int mask)
1607{
1608 env->interrupt_request &= ~mask;
1609}
1610
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001611void cpu_exit(CPUState *env)
1612{
1613 env->exit_request = 1;
1614 cpu_unlink_tb(env);
1615}
1616
1617const CPULogItem cpu_log_items[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001618 { CPU_LOG_TB_OUT_ASM, "out_asm",
1619 "show generated host assembly code for each compiled TB" },
1620 { CPU_LOG_TB_IN_ASM, "in_asm",
1621 "show target assembly code for each compiled TB" },
1622 { CPU_LOG_TB_OP, "op",
1623 "show micro ops for each compiled TB" },
1624 { CPU_LOG_TB_OP_OPT, "op_opt",
1625 "show micro ops "
1626#ifdef TARGET_I386
1627 "before eflags optimization and "
1628#endif
1629 "after liveness analysis" },
1630 { CPU_LOG_INT, "int",
1631 "show interrupts/exceptions in short format" },
1632 { CPU_LOG_EXEC, "exec",
1633 "show trace before each executed TB (lots of logs)" },
1634 { CPU_LOG_TB_CPU, "cpu",
1635 "show CPU state before block translation" },
1636#ifdef TARGET_I386
1637 { CPU_LOG_PCALL, "pcall",
1638 "show protected mode far calls/returns/exceptions" },
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001639 { CPU_LOG_RESET, "cpu_reset",
1640 "show CPU state before CPU resets" },
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001641#endif
1642#ifdef DEBUG_IOPORT
1643 { CPU_LOG_IOPORT, "ioport",
1644 "show all i/o ports accesses" },
1645#endif
1646 { 0, NULL, NULL },
1647};
1648
1649static int cmp1(const char *s1, int n, const char *s2)
1650{
1651 if (strlen(s2) != n)
1652 return 0;
1653 return memcmp(s1, s2, n) == 0;
1654}
1655
1656/* takes a comma separated list of log masks. Return 0 if error. */
1657int cpu_str_to_log_mask(const char *str)
1658{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001659 const CPULogItem *item;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001660 int mask;
1661 const char *p, *p1;
1662
1663 p = str;
1664 mask = 0;
1665 for(;;) {
1666 p1 = strchr(p, ',');
1667 if (!p1)
1668 p1 = p + strlen(p);
1669 if(cmp1(p,p1-p,"all")) {
1670 for(item = cpu_log_items; item->mask != 0; item++) {
1671 mask |= item->mask;
1672 }
1673 } else {
1674 for(item = cpu_log_items; item->mask != 0; item++) {
1675 if (cmp1(p, p1 - p, item->name))
1676 goto found;
1677 }
1678 return 0;
1679 }
1680 found:
1681 mask |= item->mask;
1682 if (*p1 != ',')
1683 break;
1684 p = p1 + 1;
1685 }
1686 return mask;
1687}
1688
1689void cpu_abort(CPUState *env, const char *fmt, ...)
1690{
1691 va_list ap;
1692 va_list ap2;
1693
1694 va_start(ap, fmt);
1695 va_copy(ap2, ap);
1696 fprintf(stderr, "qemu: fatal: ");
1697 vfprintf(stderr, fmt, ap);
1698 fprintf(stderr, "\n");
1699#ifdef TARGET_I386
1700 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1701#else
1702 cpu_dump_state(env, stderr, fprintf, 0);
1703#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001704 if (qemu_log_enabled()) {
1705 qemu_log("qemu: fatal: ");
1706 qemu_log_vprintf(fmt, ap2);
1707 qemu_log("\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001708#ifdef TARGET_I386
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001709 log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001710#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001711 log_cpu_state(env, 0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001712#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001713 qemu_log_flush();
1714 qemu_log_close();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001715 }
1716 va_end(ap2);
1717 va_end(ap);
David 'Digit' Turner36411062010-12-22 17:34:53 +01001718#if defined(CONFIG_USER_ONLY)
1719 {
1720 struct sigaction act;
1721 sigfillset(&act.sa_mask);
1722 act.sa_handler = SIG_DFL;
1723 sigaction(SIGABRT, &act, NULL);
1724 }
1725#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001726 abort();
1727}
1728
1729CPUState *cpu_copy(CPUState *env)
1730{
1731 CPUState *new_env = cpu_init(env->cpu_model_str);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001732 CPUState *next_cpu = new_env->next_cpu;
1733 int cpu_index = new_env->cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001734#if defined(TARGET_HAS_ICE)
1735 CPUBreakpoint *bp;
1736 CPUWatchpoint *wp;
1737#endif
1738
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001739 memcpy(new_env, env, sizeof(CPUState));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001740
1741 /* Preserve chaining and index. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001742 new_env->next_cpu = next_cpu;
1743 new_env->cpu_index = cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001744
1745 /* Clone all break/watchpoints.
1746 Note: Once we support ptrace with hw-debug register access, make sure
1747 BP_CPU break/watchpoints are handled correctly on clone. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001748 QTAILQ_INIT(&env->breakpoints);
1749 QTAILQ_INIT(&env->watchpoints);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001750#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001751 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001752 cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
1753 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001754 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001755 cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
1756 wp->flags, NULL);
1757 }
1758#endif
1759
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001760 return new_env;
1761}
1762
1763#if !defined(CONFIG_USER_ONLY)
1764
1765static inline void tlb_flush_jmp_cache(CPUState *env, target_ulong addr)
1766{
1767 unsigned int i;
1768
1769 /* Discard jump cache entries for any tb which might potentially
1770 overlap the flushed page. */
1771 i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02001772 memset (&env->tb_jmp_cache[i], 0,
David 'Digit' Turner36411062010-12-22 17:34:53 +01001773 TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001774
1775 i = tb_jmp_cache_hash_page(addr);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02001776 memset (&env->tb_jmp_cache[i], 0,
David 'Digit' Turner36411062010-12-22 17:34:53 +01001777 TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001778}
1779
1780/* NOTE: if flush_global is true, also flush global entries (not
1781 implemented yet) */
1782void tlb_flush(CPUState *env, int flush_global)
1783{
1784 int i;
1785
1786#if defined(DEBUG_TLB)
1787 printf("tlb_flush:\n");
1788#endif
1789 /* must reset current TB so that interrupts cannot modify the
1790 links while we are modifying them */
1791 env->current_tb = NULL;
1792
1793 for(i = 0; i < CPU_TLB_SIZE; i++) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001794 int mmu_idx;
1795 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1796 env->tlb_table[mmu_idx][i].addr_read = -1;
1797 env->tlb_table[mmu_idx][i].addr_write = -1;
1798 env->tlb_table[mmu_idx][i].addr_code = -1;
1799 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001800 }
1801
1802 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
1803
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001804#ifdef CONFIG_KQEMU
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001805 if (env->kqemu_enabled) {
1806 kqemu_flush(env, flush_global);
1807 }
1808#endif
1809 tlb_flush_count++;
1810}
1811
1812static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
1813{
1814 if (addr == (tlb_entry->addr_read &
1815 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1816 addr == (tlb_entry->addr_write &
1817 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1818 addr == (tlb_entry->addr_code &
1819 (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1820 tlb_entry->addr_read = -1;
1821 tlb_entry->addr_write = -1;
1822 tlb_entry->addr_code = -1;
1823 }
1824}
1825
1826void tlb_flush_page(CPUState *env, target_ulong addr)
1827{
1828 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001829 int mmu_idx;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001830
1831#if defined(DEBUG_TLB)
1832 printf("tlb_flush_page: " TARGET_FMT_lx "\n", addr);
1833#endif
1834 /* must reset current TB so that interrupts cannot modify the
1835 links while we are modifying them */
1836 env->current_tb = NULL;
1837
1838 addr &= TARGET_PAGE_MASK;
1839 i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001840 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++)
1841 tlb_flush_entry(&env->tlb_table[mmu_idx][i], addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001842
1843 tlb_flush_jmp_cache(env, addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001844}
1845
1846/* update the TLBs so that writes to code in the virtual page 'addr'
1847 can be detected */
1848static void tlb_protect_code(ram_addr_t ram_addr)
1849{
1850 cpu_physical_memory_reset_dirty(ram_addr,
1851 ram_addr + TARGET_PAGE_SIZE,
1852 CODE_DIRTY_FLAG);
1853}
1854
1855/* update the TLB so that writes in physical page 'phys_addr' are no longer
1856 tested for self modifying code */
1857static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
1858 target_ulong vaddr)
1859{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001860 cpu_physical_memory_set_dirty_flags(ram_addr, CODE_DIRTY_FLAG);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001861}
1862
1863static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
1864 unsigned long start, unsigned long length)
1865{
1866 unsigned long addr;
1867 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1868 addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
1869 if ((addr - start) < length) {
1870 tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
1871 }
1872 }
1873}
1874
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001875/* Note: start and end must be within the same ram block. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001876void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
1877 int dirty_flags)
1878{
1879 CPUState *env;
1880 unsigned long length, start1;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001881 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001882
1883 start &= TARGET_PAGE_MASK;
1884 end = TARGET_PAGE_ALIGN(end);
1885
1886 length = end - start;
1887 if (length == 0)
1888 return;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001889 cpu_physical_memory_mask_dirty_range(start, length, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001890
1891 /* we modify the TLB cache so that the dirty bit will be set again
1892 when accessing the range */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001893 start1 = (unsigned long)qemu_safe_ram_ptr(start);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001894 /* Chek that we don't span multiple blocks - this breaks the
1895 address comparisons below. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001896 if ((unsigned long)qemu_safe_ram_ptr(end - 1) - start1
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001897 != (end - 1) - start) {
1898 abort();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001899 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001900
1901 for(env = first_cpu; env != NULL; env = env->next_cpu) {
1902 int mmu_idx;
1903 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1904 for(i = 0; i < CPU_TLB_SIZE; i++)
1905 tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
1906 start1, length);
1907 }
1908 }
1909}
1910
1911int cpu_physical_memory_set_dirty_tracking(int enable)
1912{
1913 in_migration = enable;
1914 if (kvm_enabled()) {
1915 return kvm_set_migration_log(enable);
1916 }
1917 return 0;
1918}
1919
1920int cpu_physical_memory_get_dirty_tracking(void)
1921{
1922 return in_migration;
1923}
1924
1925int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
1926 target_phys_addr_t end_addr)
1927{
1928 int ret = 0;
1929
1930 if (kvm_enabled())
1931 ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
1932 return ret;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001933}
1934
1935static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1936{
1937 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001938 void *p;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001939
1940 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001941 p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
1942 + tlb_entry->addend);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001943 ram_addr = qemu_ram_addr_from_host_nofail(p);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001944 if (!cpu_physical_memory_is_dirty(ram_addr)) {
1945 tlb_entry->addr_write |= TLB_NOTDIRTY;
1946 }
1947 }
1948}
1949
1950/* update the TLB according to the current state of the dirty bits */
1951void cpu_tlb_update_dirty(CPUState *env)
1952{
1953 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001954 int mmu_idx;
1955 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1956 for(i = 0; i < CPU_TLB_SIZE; i++)
1957 tlb_update_dirty(&env->tlb_table[mmu_idx][i]);
1958 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001959}
1960
1961static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, target_ulong vaddr)
1962{
1963 if (tlb_entry->addr_write == (vaddr | TLB_NOTDIRTY))
1964 tlb_entry->addr_write = vaddr;
1965}
1966
1967/* update the TLB corresponding to virtual page vaddr
1968 so that it is no longer dirty */
1969static inline void tlb_set_dirty(CPUState *env, target_ulong vaddr)
1970{
1971 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001972 int mmu_idx;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001973
1974 vaddr &= TARGET_PAGE_MASK;
1975 i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001976 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++)
1977 tlb_set_dirty1(&env->tlb_table[mmu_idx][i], vaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001978}
1979
1980/* add a new TLB entry. At most one entry for a given virtual address
1981 is permitted. Return 0 if OK or 2 if the page could not be mapped
1982 (can only happen in non SOFTMMU mode for I/O pages or pages
1983 conflicting with the host address space). */
1984int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
1985 target_phys_addr_t paddr, int prot,
1986 int mmu_idx, int is_softmmu)
1987{
1988 PhysPageDesc *p;
1989 unsigned long pd;
1990 unsigned int index;
1991 target_ulong address;
1992 target_ulong code_address;
David 'Digit' Turnerd9b6cb92010-10-20 19:07:28 +02001993 ptrdiff_t addend;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001994 int ret;
1995 CPUTLBEntry *te;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001996 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001997 target_phys_addr_t iotlb;
1998
1999 p = phys_page_find(paddr >> TARGET_PAGE_BITS);
2000 if (!p) {
2001 pd = IO_MEM_UNASSIGNED;
2002 } else {
2003 pd = p->phys_offset;
2004 }
2005#if defined(DEBUG_TLB)
2006 printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x idx=%d smmu=%d pd=0x%08lx\n",
2007 vaddr, (int)paddr, prot, mmu_idx, is_softmmu, pd);
2008#endif
2009
2010 ret = 0;
2011 address = vaddr;
2012 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
2013 /* IO memory case (romd handled later) */
2014 address |= TLB_MMIO;
2015 }
David 'Digit' Turnerd9b6cb92010-10-20 19:07:28 +02002016 addend = (ptrdiff_t)qemu_get_ram_ptr(pd & TARGET_PAGE_MASK);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002017 if ((pd & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
2018 /* Normal RAM. */
2019 iotlb = pd & TARGET_PAGE_MASK;
2020 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM)
2021 iotlb |= IO_MEM_NOTDIRTY;
2022 else
2023 iotlb |= IO_MEM_ROM;
2024 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002025 /* IO handlers are currently passed a physical address.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002026 It would be nice to pass an offset from the base address
2027 of that region. This would avoid having to special case RAM,
2028 and avoid full address decoding in every device.
2029 We can't use the high bits of pd for this because
2030 IO_MEM_ROMD uses these as a ram address. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002031 iotlb = (pd & ~TARGET_PAGE_MASK);
2032 if (p) {
2033 iotlb += p->region_offset;
2034 } else {
2035 iotlb += paddr;
2036 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002037 }
2038
2039 code_address = address;
2040 /* Make accesses to pages with watchpoints go via the
2041 watchpoint trap routines. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002042 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002043 if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002044 iotlb = io_mem_watch + paddr;
2045 /* TODO: The memory case can be optimized by not trapping
2046 reads of pages with a write breakpoint. */
2047 address |= TLB_MMIO;
2048 }
2049 }
2050
2051 index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
2052 env->iotlb[mmu_idx][index] = iotlb - vaddr;
2053 te = &env->tlb_table[mmu_idx][index];
2054 te->addend = addend - vaddr;
2055 if (prot & PAGE_READ) {
2056 te->addr_read = address;
2057 } else {
2058 te->addr_read = -1;
2059 }
2060
2061 if (prot & PAGE_EXEC) {
2062 te->addr_code = code_address;
2063 } else {
2064 te->addr_code = -1;
2065 }
2066 if (prot & PAGE_WRITE) {
2067 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM ||
2068 (pd & IO_MEM_ROMD)) {
2069 /* Write access calls the I/O callback. */
2070 te->addr_write = address | TLB_MMIO;
2071 } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
2072 !cpu_physical_memory_is_dirty(pd)) {
2073 te->addr_write = address | TLB_NOTDIRTY;
2074 } else {
2075 te->addr_write = address;
2076 }
2077 } else {
2078 te->addr_write = -1;
2079 }
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -08002080
2081#ifdef CONFIG_MEMCHECK
2082 /*
2083 * If we have memchecker running, we need to make sure that page, cached
2084 * into TLB as the result of this operation will comply with our requirement
2085 * to cause __ld/__stx_mmu being called for memory access on the pages
2086 * containing memory blocks that require access violation checks.
2087 *
2088 * We need to check with memory checker if we should invalidate this page
2089 * iff:
2090 * - Memchecking is enabled.
2091 * - Page that's been cached belongs to the user space.
2092 * - Request to cache this page didn't come from softmmu. We're covered
2093 * there, because after page was cached here we will invalidate it in
2094 * the __ld/__stx_mmu wrapper.
2095 * - Cached page belongs to RAM, not I/O area.
2096 * - Page is cached for read, or write access.
2097 */
2098 if (memcheck_instrument_mmu && mmu_idx == 1 && !is_softmmu &&
2099 (pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
2100 (prot & (PAGE_READ | PAGE_WRITE)) &&
2101 memcheck_is_checked(vaddr & TARGET_PAGE_MASK, TARGET_PAGE_SIZE)) {
2102 if (prot & PAGE_READ) {
2103 te->addr_read ^= TARGET_PAGE_MASK;
2104 }
2105 if (prot & PAGE_WRITE) {
2106 te->addr_write ^= TARGET_PAGE_MASK;
2107 }
2108 }
2109#endif // CONFIG_MEMCHECK
2110
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002111 return ret;
2112}
2113
2114#else
2115
2116void tlb_flush(CPUState *env, int flush_global)
2117{
2118}
2119
2120void tlb_flush_page(CPUState *env, target_ulong addr)
2121{
2122}
2123
2124int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
2125 target_phys_addr_t paddr, int prot,
2126 int mmu_idx, int is_softmmu)
2127{
2128 return 0;
2129}
2130
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002131/*
2132 * Walks guest process memory "regions" one by one
2133 * and calls callback function 'fn' for each region.
2134 */
2135int walk_memory_regions(void *priv,
2136 int (*fn)(void *, unsigned long, unsigned long, unsigned long))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002137{
2138 unsigned long start, end;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002139 PageDesc *p = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002140 int i, j, prot, prot1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002141 int rc = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002142
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002143 start = end = -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002144 prot = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002145
2146 for (i = 0; i <= L1_SIZE; i++) {
2147 p = (i < L1_SIZE) ? l1_map[i] : NULL;
2148 for (j = 0; j < L2_SIZE; j++) {
2149 prot1 = (p == NULL) ? 0 : p[j].flags;
2150 /*
2151 * "region" is one continuous chunk of memory
2152 * that has same protection flags set.
2153 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002154 if (prot1 != prot) {
2155 end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
2156 if (start != -1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002157 rc = (*fn)(priv, start, end, prot);
2158 /* callback can stop iteration by returning != 0 */
2159 if (rc != 0)
2160 return (rc);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002161 }
2162 if (prot1 != 0)
2163 start = end;
2164 else
2165 start = -1;
2166 prot = prot1;
2167 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002168 if (p == NULL)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002169 break;
2170 }
2171 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002172 return (rc);
2173}
2174
2175static int dump_region(void *priv, unsigned long start,
2176 unsigned long end, unsigned long prot)
2177{
2178 FILE *f = (FILE *)priv;
2179
2180 (void) fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
2181 start, end, end - start,
2182 ((prot & PAGE_READ) ? 'r' : '-'),
2183 ((prot & PAGE_WRITE) ? 'w' : '-'),
2184 ((prot & PAGE_EXEC) ? 'x' : '-'));
2185
2186 return (0);
2187}
2188
2189/* dump memory mappings */
2190void page_dump(FILE *f)
2191{
2192 (void) fprintf(f, "%-8s %-8s %-8s %s\n",
2193 "start", "end", "size", "prot");
2194 walk_memory_regions(f, dump_region);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002195}
2196
2197int page_get_flags(target_ulong address)
2198{
2199 PageDesc *p;
2200
2201 p = page_find(address >> TARGET_PAGE_BITS);
2202 if (!p)
2203 return 0;
2204 return p->flags;
2205}
2206
David 'Digit' Turner36411062010-12-22 17:34:53 +01002207/* Modify the flags of a page and invalidate the code if necessary.
2208 The flag PAGE_WRITE_ORG is positioned automatically depending
2209 on PAGE_WRITE. The mmap_lock should already be held. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002210void page_set_flags(target_ulong start, target_ulong end, int flags)
2211{
2212 PageDesc *p;
2213 target_ulong addr;
2214
2215 /* mmap_lock should already be held. */
2216 start = start & TARGET_PAGE_MASK;
2217 end = TARGET_PAGE_ALIGN(end);
2218 if (flags & PAGE_WRITE)
2219 flags |= PAGE_WRITE_ORG;
2220 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2221 p = page_find_alloc(addr >> TARGET_PAGE_BITS);
2222 /* We may be called for host regions that are outside guest
2223 address space. */
2224 if (!p)
2225 return;
2226 /* if the write protection is set, then we invalidate the code
2227 inside */
2228 if (!(p->flags & PAGE_WRITE) &&
2229 (flags & PAGE_WRITE) &&
2230 p->first_tb) {
2231 tb_invalidate_phys_page(addr, 0, NULL);
2232 }
2233 p->flags = flags;
2234 }
2235}
2236
2237int page_check_range(target_ulong start, target_ulong len, int flags)
2238{
2239 PageDesc *p;
2240 target_ulong end;
2241 target_ulong addr;
2242
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002243 if (start + len < start)
2244 /* we've wrapped around */
2245 return -1;
2246
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002247 end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
2248 start = start & TARGET_PAGE_MASK;
2249
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002250 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2251 p = page_find(addr >> TARGET_PAGE_BITS);
2252 if( !p )
2253 return -1;
2254 if( !(p->flags & PAGE_VALID) )
2255 return -1;
2256
2257 if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
2258 return -1;
2259 if (flags & PAGE_WRITE) {
2260 if (!(p->flags & PAGE_WRITE_ORG))
2261 return -1;
2262 /* unprotect the page if it was put read-only because it
2263 contains translated code */
2264 if (!(p->flags & PAGE_WRITE)) {
2265 if (!page_unprotect(addr, 0, NULL))
2266 return -1;
2267 }
2268 return 0;
2269 }
2270 }
2271 return 0;
2272}
2273
2274/* called from signal handler: invalidate the code and unprotect the
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002275 page. Return TRUE if the fault was successfully handled. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002276int page_unprotect(target_ulong address, unsigned long pc, void *puc)
2277{
2278 unsigned int page_index, prot, pindex;
2279 PageDesc *p, *p1;
2280 target_ulong host_start, host_end, addr;
2281
2282 /* Technically this isn't safe inside a signal handler. However we
2283 know this only ever happens in a synchronous SEGV handler, so in
2284 practice it seems to be ok. */
2285 mmap_lock();
2286
2287 host_start = address & qemu_host_page_mask;
2288 page_index = host_start >> TARGET_PAGE_BITS;
2289 p1 = page_find(page_index);
2290 if (!p1) {
2291 mmap_unlock();
2292 return 0;
2293 }
2294 host_end = host_start + qemu_host_page_size;
2295 p = p1;
2296 prot = 0;
2297 for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
2298 prot |= p->flags;
2299 p++;
2300 }
2301 /* if the page was really writable, then we change its
2302 protection back to writable */
2303 if (prot & PAGE_WRITE_ORG) {
2304 pindex = (address - host_start) >> TARGET_PAGE_BITS;
2305 if (!(p1[pindex].flags & PAGE_WRITE)) {
2306 mprotect((void *)g2h(host_start), qemu_host_page_size,
2307 (prot & PAGE_BITS) | PAGE_WRITE);
2308 p1[pindex].flags |= PAGE_WRITE;
2309 /* and since the content will be modified, we must invalidate
2310 the corresponding translated code. */
2311 tb_invalidate_phys_page(address, pc, puc);
2312#ifdef DEBUG_TB_CHECK
2313 tb_invalidate_check(address);
2314#endif
2315 mmap_unlock();
2316 return 1;
2317 }
2318 }
2319 mmap_unlock();
2320 return 0;
2321}
2322
2323static inline void tlb_set_dirty(CPUState *env,
2324 unsigned long addr, target_ulong vaddr)
2325{
2326}
2327#endif /* defined(CONFIG_USER_ONLY) */
2328
2329#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002330
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002331static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002332 ram_addr_t memory, ram_addr_t region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002333static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002334 ram_addr_t orig_memory, ram_addr_t region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002335#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
2336 need_subpage) \
2337 do { \
2338 if (addr > start_addr) \
2339 start_addr2 = 0; \
2340 else { \
2341 start_addr2 = start_addr & ~TARGET_PAGE_MASK; \
2342 if (start_addr2 > 0) \
2343 need_subpage = 1; \
2344 } \
2345 \
2346 if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE) \
2347 end_addr2 = TARGET_PAGE_SIZE - 1; \
2348 else { \
2349 end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
2350 if (end_addr2 < TARGET_PAGE_SIZE - 1) \
2351 need_subpage = 1; \
2352 } \
2353 } while (0)
2354
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002355/* register physical memory.
2356 For RAM, 'size' must be a multiple of the target page size.
2357 If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002358 io memory page. The address used when calling the IO function is
2359 the offset from the start of the region, plus region_offset. Both
2360 start_addr and region_offset are rounded down to a page boundary
2361 before calculating this offset. This should not be a problem unless
2362 the low bits of start_addr and region_offset differ. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002363void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002364 ram_addr_t size,
2365 ram_addr_t phys_offset,
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002366 ram_addr_t region_offset,
2367 bool log_dirty)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002368{
2369 target_phys_addr_t addr, end_addr;
2370 PhysPageDesc *p;
2371 CPUState *env;
2372 ram_addr_t orig_size = size;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002373 subpage_t *subpage;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002374
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002375 if (kvm_enabled())
2376 kvm_set_phys_mem(start_addr, size, phys_offset);
2377
2378 if (phys_offset == IO_MEM_UNASSIGNED) {
2379 region_offset = start_addr;
2380 }
2381 region_offset &= TARGET_PAGE_MASK;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002382 size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
2383 end_addr = start_addr + (target_phys_addr_t)size;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002384
2385 addr = start_addr;
2386 do {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002387 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2388 if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
2389 ram_addr_t orig_memory = p->phys_offset;
2390 target_phys_addr_t start_addr2, end_addr2;
2391 int need_subpage = 0;
2392
2393 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2394 need_subpage);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002395 if (need_subpage) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002396 if (!(orig_memory & IO_MEM_SUBPAGE)) {
2397 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002398 &p->phys_offset, orig_memory,
2399 p->region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002400 } else {
2401 subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
2402 >> IO_MEM_SHIFT];
2403 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002404 subpage_register(subpage, start_addr2, end_addr2, phys_offset,
2405 region_offset);
2406 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002407 } else {
2408 p->phys_offset = phys_offset;
2409 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2410 (phys_offset & IO_MEM_ROMD))
2411 phys_offset += TARGET_PAGE_SIZE;
2412 }
2413 } else {
2414 p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2415 p->phys_offset = phys_offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002416 p->region_offset = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002417 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002418 (phys_offset & IO_MEM_ROMD)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002419 phys_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002420 } else {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002421 target_phys_addr_t start_addr2, end_addr2;
2422 int need_subpage = 0;
2423
2424 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2425 end_addr2, need_subpage);
2426
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002427 if (need_subpage) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002428 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002429 &p->phys_offset, IO_MEM_UNASSIGNED,
2430 addr & TARGET_PAGE_MASK);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002431 subpage_register(subpage, start_addr2, end_addr2,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002432 phys_offset, region_offset);
2433 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002434 }
2435 }
2436 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002437 region_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002438 addr += TARGET_PAGE_SIZE;
2439 } while (addr != end_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002440
2441 /* since each CPU stores ram addresses in its TLB cache, we must
2442 reset the modified entries */
2443 /* XXX: slow ! */
2444 for(env = first_cpu; env != NULL; env = env->next_cpu) {
2445 tlb_flush(env, 1);
2446 }
2447}
2448
2449/* XXX: temporary until new memory mapping API */
2450ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr)
2451{
2452 PhysPageDesc *p;
2453
2454 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2455 if (!p)
2456 return IO_MEM_UNASSIGNED;
2457 return p->phys_offset;
2458}
2459
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002460void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
2461{
2462 if (kvm_enabled())
2463 kvm_coalesce_mmio_region(addr, size);
2464}
2465
2466void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
2467{
2468 if (kvm_enabled())
2469 kvm_uncoalesce_mmio_region(addr, size);
2470}
2471
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002472static ram_addr_t find_ram_offset(ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002473{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002474 RAMBlock *block, *next_block;
2475 ram_addr_t offset = 0, mingap = ULONG_MAX;
2476
2477 if (QLIST_EMPTY(&ram_list.blocks))
2478 return 0;
2479
2480 QLIST_FOREACH(block, &ram_list.blocks, next) {
2481 ram_addr_t end, next = ULONG_MAX;
2482
2483 end = block->offset + block->length;
2484
2485 QLIST_FOREACH(next_block, &ram_list.blocks, next) {
2486 if (next_block->offset >= end) {
2487 next = MIN(next, next_block->offset);
2488 }
2489 }
2490 if (next - end >= size && next - end < mingap) {
2491 offset = end;
2492 mingap = next - end;
2493 }
2494 }
2495 return offset;
2496}
2497
2498static ram_addr_t last_ram_offset(void)
2499{
2500 RAMBlock *block;
2501 ram_addr_t last = 0;
2502
2503 QLIST_FOREACH(block, &ram_list.blocks, next)
2504 last = MAX(last, block->offset + block->length);
2505
2506 return last;
2507}
2508
2509ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
2510 ram_addr_t size, void *host)
2511{
2512 RAMBlock *new_block, *block;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002513
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002514 size = TARGET_PAGE_ALIGN(size);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002515 new_block = qemu_mallocz(sizeof(*new_block));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002516
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002517#if 0
2518 if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
2519 char *id = dev->parent_bus->info->get_dev_path(dev);
2520 if (id) {
2521 snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id);
2522 qemu_free(id);
2523 }
2524 }
2525#endif
2526 pstrcat(new_block->idstr, sizeof(new_block->idstr), name);
2527
2528 QLIST_FOREACH(block, &ram_list.blocks, next) {
2529 if (!strcmp(block->idstr, new_block->idstr)) {
2530 fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n",
2531 new_block->idstr);
2532 abort();
2533 }
2534 }
2535
2536 if (host) {
2537 new_block->host = host;
2538 new_block->flags |= RAM_PREALLOC_MASK;
2539 } else {
2540 if (mem_path) {
2541#if 0 && defined (__linux__) && !defined(TARGET_S390X)
2542 new_block->host = file_ram_alloc(new_block, size, mem_path);
2543 if (!new_block->host) {
2544 new_block->host = qemu_vmalloc(size);
2545 qemu_madvise(new_block->host, size, QEMU_MADV_MERGEABLE);
2546 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002547#else
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002548 fprintf(stderr, "-mem-path option unsupported\n");
2549 exit(1);
2550#endif
2551 } else {
2552#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2553 /* XXX S390 KVM requires the topmost vma of the RAM to be < 256GB */
2554 new_block->host = mmap((void*)0x1000000, size,
2555 PROT_EXEC|PROT_READ|PROT_WRITE,
2556 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
2557#else
2558 new_block->host = qemu_vmalloc(size);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002559#endif
2560#ifdef MADV_MERGEABLE
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002561 madvise(new_block->host, size, MADV_MERGEABLE);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002562#endif
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002563 }
2564 }
2565
2566 new_block->offset = find_ram_offset(size);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002567 new_block->length = size;
2568
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002569 QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002570
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002571 ram_list.phys_dirty = qemu_realloc(ram_list.phys_dirty,
2572 last_ram_offset() >> TARGET_PAGE_BITS);
2573 memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002574 0xff, size >> TARGET_PAGE_BITS);
2575
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002576 if (kvm_enabled())
2577 kvm_setup_guest_memory(new_block->host, size);
2578
2579 return new_block->offset;
2580}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002581
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002582ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
2583{
2584 return qemu_ram_alloc_from_ptr(dev, name, size, NULL);
2585}
2586
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002587void qemu_ram_free(ram_addr_t addr)
2588{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002589 RAMBlock *block;
2590
2591 QLIST_FOREACH(block, &ram_list.blocks, next) {
2592 if (addr == block->offset) {
2593 QLIST_REMOVE(block, next);
2594 if (block->flags & RAM_PREALLOC_MASK) {
2595 ;
2596 } else if (mem_path) {
2597#if defined (__linux__) && !defined(TARGET_S390X)
2598 if (block->fd) {
2599 munmap(block->host, block->length);
2600 close(block->fd);
2601 } else {
2602 qemu_vfree(block->host);
2603 }
2604#else
2605 abort();
2606#endif
2607 } else {
2608#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2609 munmap(block->host, block->length);
2610#else
2611 qemu_vfree(block->host);
2612#endif
2613 }
2614 qemu_free(block);
2615 return;
2616 }
2617 }
2618
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002619}
2620
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002621#ifndef _WIN32
2622void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
2623{
2624#ifndef CONFIG_ANDROID
2625 RAMBlock *block;
2626 ram_addr_t offset;
2627 int flags;
2628 void *area, *vaddr;
2629
2630 QLIST_FOREACH(block, &ram_list.blocks, next) {
2631 offset = addr - block->offset;
2632 if (offset < block->length) {
2633 vaddr = block->host + offset;
2634 if (block->flags & RAM_PREALLOC_MASK) {
2635 ;
2636 } else {
2637 flags = MAP_FIXED;
2638 munmap(vaddr, length);
2639 if (mem_path) {
2640#if defined(__linux__) && !defined(TARGET_S390X)
2641 if (block->fd) {
2642#ifdef MAP_POPULATE
2643 flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED :
2644 MAP_PRIVATE;
2645#else
2646 flags |= MAP_PRIVATE;
2647#endif
2648 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2649 flags, block->fd, offset);
2650 } else {
2651 flags |= MAP_PRIVATE | MAP_ANONYMOUS;
2652 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2653 flags, -1, 0);
2654 }
2655#else
2656 abort();
2657#endif
2658 } else {
2659#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2660 flags |= MAP_SHARED | MAP_ANONYMOUS;
2661 area = mmap(vaddr, length, PROT_EXEC|PROT_READ|PROT_WRITE,
2662 flags, -1, 0);
2663#else
2664 flags |= MAP_PRIVATE | MAP_ANONYMOUS;
2665 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2666 flags, -1, 0);
2667#endif
2668 }
2669 if (area != vaddr) {
2670 fprintf(stderr, "Could not remap addr: %lx@%lx\n",
2671 length, addr);
2672 exit(1);
2673 }
2674 qemu_madvise(vaddr, length, QEMU_MADV_MERGEABLE);
2675 }
2676 return;
2677 }
2678 }
2679#endif /* !CONFIG_ANDROID */
2680}
2681#endif /* !_WIN32 */
2682
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002683/* Return a host pointer to ram allocated with qemu_ram_alloc.
2684 With the exception of the softmmu code in this file, this should
2685 only be used for local memory (e.g. video ram) that the device owns,
2686 and knows it isn't going to access beyond the end of the block.
2687
2688 It should not be used for general purpose DMA.
2689 Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
2690 */
2691void *qemu_get_ram_ptr(ram_addr_t addr)
2692{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002693 RAMBlock *block;
2694
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002695 QLIST_FOREACH(block, &ram_list.blocks, next) {
2696 if (addr - block->offset < block->length) {
2697 /* Move this entry to to start of the list. */
2698 if (block != QLIST_FIRST(&ram_list.blocks)) {
2699 QLIST_REMOVE(block, next);
2700 QLIST_INSERT_HEAD(&ram_list.blocks, block, next);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002701 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002702 return block->host + (addr - block->offset);
2703 }
2704 }
2705
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002706 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2707 abort();
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002708
2709 return NULL;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002710 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002711
2712/* Return a host pointer to ram allocated with qemu_ram_alloc.
2713 * Same as qemu_get_ram_ptr but avoid reordering ramblocks.
2714 */
2715void *qemu_safe_ram_ptr(ram_addr_t addr)
2716{
2717 RAMBlock *block;
2718
2719 QLIST_FOREACH(block, &ram_list.blocks, next) {
2720 if (addr - block->offset < block->length) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002721 return block->host + (addr - block->offset);
2722}
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002723 }
2724
2725 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2726 abort();
2727
2728 return NULL;
2729}
2730
2731int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
2732{
2733 RAMBlock *block;
2734 uint8_t *host = ptr;
2735
2736 QLIST_FOREACH(block, &ram_list.blocks, next) {
2737 if (host - block->host < block->length) {
2738 *ram_addr = block->offset + (host - block->host);
2739 return 0;
2740 }
2741 }
2742 return -1;
2743}
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002744
2745/* Some of the softmmu routines need to translate from a host pointer
2746 (typically a TLB entry) back to a ram offset. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002747ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002748{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002749 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002750
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002751 if (qemu_ram_addr_from_host(ptr, &ram_addr)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002752 fprintf(stderr, "Bad ram pointer %p\n", ptr);
2753 abort();
2754 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002755 return ram_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002756}
2757
2758static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
2759{
2760#ifdef DEBUG_UNASSIGNED
2761 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2762#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002763#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002764 do_unassigned_access(addr, 0, 0, 0, 1);
2765#endif
2766 return 0;
2767}
2768
2769static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr)
2770{
2771#ifdef DEBUG_UNASSIGNED
2772 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2773#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002774#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002775 do_unassigned_access(addr, 0, 0, 0, 2);
2776#endif
2777 return 0;
2778}
2779
2780static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr)
2781{
2782#ifdef DEBUG_UNASSIGNED
2783 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2784#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002785#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002786 do_unassigned_access(addr, 0, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002787#endif
2788 return 0;
2789}
2790
2791static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
2792{
2793#ifdef DEBUG_UNASSIGNED
2794 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2795#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002796#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002797 do_unassigned_access(addr, 1, 0, 0, 1);
2798#endif
2799}
2800
2801static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
2802{
2803#ifdef DEBUG_UNASSIGNED
2804 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2805#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002806#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002807 do_unassigned_access(addr, 1, 0, 0, 2);
2808#endif
2809}
2810
2811static void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
2812{
2813#ifdef DEBUG_UNASSIGNED
2814 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2815#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002816#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002817 do_unassigned_access(addr, 1, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002818#endif
2819}
2820
David 'Digit' Turner36411062010-12-22 17:34:53 +01002821static CPUReadMemoryFunc * const unassigned_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002822 unassigned_mem_readb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002823 unassigned_mem_readw,
2824 unassigned_mem_readl,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002825};
2826
David 'Digit' Turner36411062010-12-22 17:34:53 +01002827static CPUWriteMemoryFunc * const unassigned_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002828 unassigned_mem_writeb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002829 unassigned_mem_writew,
2830 unassigned_mem_writel,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002831};
2832
2833static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr,
2834 uint32_t val)
2835{
2836 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002837 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002838 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2839#if !defined(CONFIG_USER_ONLY)
2840 tb_invalidate_phys_page_fast(ram_addr, 1);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002841 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002842#endif
2843 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002844 stb_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002845 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002846 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002847 /* we remove the notdirty callback only if the code has been
2848 flushed */
2849 if (dirty_flags == 0xff)
2850 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2851}
2852
2853static void notdirty_mem_writew(void *opaque, target_phys_addr_t ram_addr,
2854 uint32_t val)
2855{
2856 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002857 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002858 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2859#if !defined(CONFIG_USER_ONLY)
2860 tb_invalidate_phys_page_fast(ram_addr, 2);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002861 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002862#endif
2863 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002864 stw_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002865 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002866 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002867 /* we remove the notdirty callback only if the code has been
2868 flushed */
2869 if (dirty_flags == 0xff)
2870 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2871}
2872
2873static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr,
2874 uint32_t val)
2875{
2876 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002877 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002878 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2879#if !defined(CONFIG_USER_ONLY)
2880 tb_invalidate_phys_page_fast(ram_addr, 4);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002881 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002882#endif
2883 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002884 stl_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002885 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002886 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002887 /* we remove the notdirty callback only if the code has been
2888 flushed */
2889 if (dirty_flags == 0xff)
2890 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2891}
2892
David 'Digit' Turner36411062010-12-22 17:34:53 +01002893static CPUReadMemoryFunc * const error_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002894 NULL, /* never used */
2895 NULL, /* never used */
2896 NULL, /* never used */
2897};
2898
David 'Digit' Turner36411062010-12-22 17:34:53 +01002899static CPUWriteMemoryFunc * const notdirty_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002900 notdirty_mem_writeb,
2901 notdirty_mem_writew,
2902 notdirty_mem_writel,
2903};
2904
2905/* Generate a debug exception if a watchpoint has been hit. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002906static void check_watchpoint(int offset, int len_mask, int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002907{
2908 CPUState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002909 target_ulong pc, cs_base;
2910 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002911 target_ulong vaddr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002912 CPUWatchpoint *wp;
2913 int cpu_flags;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002914
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002915 if (env->watchpoint_hit) {
2916 /* We re-entered the check after replacing the TB. Now raise
2917 * the debug interrupt so that is will trigger after the
2918 * current instruction. */
2919 cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2920 return;
2921 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002922 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002923 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002924 if ((vaddr == (wp->vaddr & len_mask) ||
2925 (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
2926 wp->flags |= BP_WATCHPOINT_HIT;
2927 if (!env->watchpoint_hit) {
2928 env->watchpoint_hit = wp;
2929 tb = tb_find_pc(env->mem_io_pc);
2930 if (!tb) {
2931 cpu_abort(env, "check_watchpoint: could not find TB for "
2932 "pc=%p", (void *)env->mem_io_pc);
2933 }
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02002934 cpu_restore_state(tb, env, env->mem_io_pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002935 tb_phys_invalidate(tb, -1);
2936 if (wp->flags & BP_STOP_BEFORE_ACCESS) {
2937 env->exception_index = EXCP_DEBUG;
2938 } else {
2939 cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
2940 tb_gen_code(env, pc, cs_base, cpu_flags, 1);
2941 }
2942 cpu_resume_from_signal(env, NULL);
2943 }
2944 } else {
2945 wp->flags &= ~BP_WATCHPOINT_HIT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002946 }
2947 }
2948}
2949
2950/* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
2951 so these check for a hit then pass through to the normal out-of-line
2952 phys routines. */
2953static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
2954{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002955 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002956 return ldub_phys(addr);
2957}
2958
2959static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
2960{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002961 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002962 return lduw_phys(addr);
2963}
2964
2965static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
2966{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002967 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002968 return ldl_phys(addr);
2969}
2970
2971static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
2972 uint32_t val)
2973{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002974 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002975 stb_phys(addr, val);
2976}
2977
2978static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
2979 uint32_t val)
2980{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002981 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002982 stw_phys(addr, val);
2983}
2984
2985static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
2986 uint32_t val)
2987{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002988 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002989 stl_phys(addr, val);
2990}
2991
David 'Digit' Turner36411062010-12-22 17:34:53 +01002992static CPUReadMemoryFunc * const watch_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002993 watch_mem_readb,
2994 watch_mem_readw,
2995 watch_mem_readl,
2996};
2997
David 'Digit' Turner36411062010-12-22 17:34:53 +01002998static CPUWriteMemoryFunc * const watch_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002999 watch_mem_writeb,
3000 watch_mem_writew,
3001 watch_mem_writel,
3002};
3003
3004static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr,
3005 unsigned int len)
3006{
3007 uint32_t ret;
3008 unsigned int idx;
3009
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003010 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003011#if defined(DEBUG_SUBPAGE)
3012 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
3013 mmio, len, addr, idx);
3014#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003015 ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len],
3016 addr + mmio->region_offset[idx][0][len]);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003017
3018 return ret;
3019}
3020
3021static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
3022 uint32_t value, unsigned int len)
3023{
3024 unsigned int idx;
3025
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003026 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003027#if defined(DEBUG_SUBPAGE)
3028 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
3029 mmio, len, addr, idx, value);
3030#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003031 (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len],
3032 addr + mmio->region_offset[idx][1][len],
3033 value);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003034}
3035
3036static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
3037{
3038#if defined(DEBUG_SUBPAGE)
3039 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
3040#endif
3041
3042 return subpage_readlen(opaque, addr, 0);
3043}
3044
3045static void subpage_writeb (void *opaque, target_phys_addr_t addr,
3046 uint32_t value)
3047{
3048#if defined(DEBUG_SUBPAGE)
3049 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
3050#endif
3051 subpage_writelen(opaque, addr, value, 0);
3052}
3053
3054static uint32_t subpage_readw (void *opaque, target_phys_addr_t addr)
3055{
3056#if defined(DEBUG_SUBPAGE)
3057 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
3058#endif
3059
3060 return subpage_readlen(opaque, addr, 1);
3061}
3062
3063static void subpage_writew (void *opaque, target_phys_addr_t addr,
3064 uint32_t value)
3065{
3066#if defined(DEBUG_SUBPAGE)
3067 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
3068#endif
3069 subpage_writelen(opaque, addr, value, 1);
3070}
3071
3072static uint32_t subpage_readl (void *opaque, target_phys_addr_t addr)
3073{
3074#if defined(DEBUG_SUBPAGE)
3075 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
3076#endif
3077
3078 return subpage_readlen(opaque, addr, 2);
3079}
3080
3081static void subpage_writel (void *opaque,
3082 target_phys_addr_t addr, uint32_t value)
3083{
3084#if defined(DEBUG_SUBPAGE)
3085 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
3086#endif
3087 subpage_writelen(opaque, addr, value, 2);
3088}
3089
David 'Digit' Turner36411062010-12-22 17:34:53 +01003090static CPUReadMemoryFunc * const subpage_read[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003091 &subpage_readb,
3092 &subpage_readw,
3093 &subpage_readl,
3094};
3095
David 'Digit' Turner36411062010-12-22 17:34:53 +01003096static CPUWriteMemoryFunc * const subpage_write[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003097 &subpage_writeb,
3098 &subpage_writew,
3099 &subpage_writel,
3100};
3101
3102static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003103 ram_addr_t memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003104{
3105 int idx, eidx;
3106 unsigned int i;
3107
3108 if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
3109 return -1;
3110 idx = SUBPAGE_IDX(start);
3111 eidx = SUBPAGE_IDX(end);
3112#if defined(DEBUG_SUBPAGE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003113 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 -08003114 mmio, start, end, idx, eidx, memory);
3115#endif
3116 memory >>= IO_MEM_SHIFT;
3117 for (; idx <= eidx; idx++) {
3118 for (i = 0; i < 4; i++) {
3119 if (io_mem_read[memory][i]) {
3120 mmio->mem_read[idx][i] = &io_mem_read[memory][i];
3121 mmio->opaque[idx][0][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003122 mmio->region_offset[idx][0][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003123 }
3124 if (io_mem_write[memory][i]) {
3125 mmio->mem_write[idx][i] = &io_mem_write[memory][i];
3126 mmio->opaque[idx][1][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003127 mmio->region_offset[idx][1][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003128 }
3129 }
3130 }
3131
3132 return 0;
3133}
3134
3135static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003136 ram_addr_t orig_memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003137{
3138 subpage_t *mmio;
3139 int subpage_memory;
3140
3141 mmio = qemu_mallocz(sizeof(subpage_t));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003142
3143 mmio->base = base;
3144 subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003145#if defined(DEBUG_SUBPAGE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003146 printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
3147 mmio, base, TARGET_PAGE_SIZE, subpage_memory);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003148#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003149 *phys = subpage_memory | IO_MEM_SUBPAGE;
3150 subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
3151 region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003152
3153 return mmio;
3154}
3155
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003156static int get_free_io_mem_idx(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003157{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003158 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003159
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003160 for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
3161 if (!io_mem_used[i]) {
3162 io_mem_used[i] = 1;
3163 return i;
3164 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003165 fprintf(stderr, "RAN out out io_mem_idx, max %d !\n", IO_MEM_NB_ENTRIES);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003166 return -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003167}
3168
3169/* mem_read and mem_write are arrays of functions containing the
3170 function to access byte (index 0), word (index 1) and dword (index
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003171 2). Functions can be omitted with a NULL function pointer.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003172 If io_index is non zero, the corresponding io zone is
3173 modified. If it is zero, a new io zone is allocated. The return
3174 value can be used with cpu_register_physical_memory(). (-1) is
3175 returned if error. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003176static int cpu_register_io_memory_fixed(int io_index,
David 'Digit' Turner36411062010-12-22 17:34:53 +01003177 CPUReadMemoryFunc * const *mem_read,
3178 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003179 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003180{
3181 int i, subwidth = 0;
3182
3183 if (io_index <= 0) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003184 io_index = get_free_io_mem_idx();
3185 if (io_index == -1)
3186 return io_index;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003187 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003188 io_index >>= IO_MEM_SHIFT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003189 if (io_index >= IO_MEM_NB_ENTRIES)
3190 return -1;
3191 }
3192
3193 for(i = 0;i < 3; i++) {
3194 if (!mem_read[i] || !mem_write[i])
3195 subwidth = IO_MEM_SUBWIDTH;
3196 io_mem_read[io_index][i] = mem_read[i];
3197 io_mem_write[io_index][i] = mem_write[i];
3198 }
3199 io_mem_opaque[io_index] = opaque;
3200 return (io_index << IO_MEM_SHIFT) | subwidth;
3201}
3202
David 'Digit' Turner36411062010-12-22 17:34:53 +01003203int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
3204 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003205 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003206{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003207 return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003208}
3209
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003210void cpu_unregister_io_memory(int io_table_address)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003211{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003212 int i;
3213 int io_index = io_table_address >> IO_MEM_SHIFT;
3214
3215 for (i=0;i < 3; i++) {
3216 io_mem_read[io_index][i] = unassigned_mem_read[i];
3217 io_mem_write[io_index][i] = unassigned_mem_write[i];
3218 }
3219 io_mem_opaque[io_index] = NULL;
3220 io_mem_used[io_index] = 0;
3221}
3222
3223static void io_mem_init(void)
3224{
3225 int i;
3226
3227 cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read, unassigned_mem_write, NULL);
3228 cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read, unassigned_mem_write, NULL);
3229 cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read, notdirty_mem_write, NULL);
3230 for (i=0; i<5; i++)
3231 io_mem_used[i] = 1;
3232
3233 io_mem_watch = cpu_register_io_memory(watch_mem_read,
3234 watch_mem_write, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003235}
3236
3237#endif /* !defined(CONFIG_USER_ONLY) */
3238
3239/* physical memory access (slow version, mainly for debug) */
3240#if defined(CONFIG_USER_ONLY)
3241void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
3242 int len, int is_write)
3243{
3244 int l, flags;
3245 target_ulong page;
3246 void * p;
3247
3248 while (len > 0) {
3249 page = addr & TARGET_PAGE_MASK;
3250 l = (page + TARGET_PAGE_SIZE) - addr;
3251 if (l > len)
3252 l = len;
3253 flags = page_get_flags(page);
3254 if (!(flags & PAGE_VALID))
3255 return;
3256 if (is_write) {
3257 if (!(flags & PAGE_WRITE))
3258 return;
3259 /* XXX: this code should not depend on lock_user */
3260 if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
3261 /* FIXME - should this return an error rather than just fail? */
3262 return;
3263 memcpy(p, buf, l);
3264 unlock_user(p, addr, l);
3265 } else {
3266 if (!(flags & PAGE_READ))
3267 return;
3268 /* XXX: this code should not depend on lock_user */
3269 if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
3270 /* FIXME - should this return an error rather than just fail? */
3271 return;
3272 memcpy(buf, p, l);
3273 unlock_user(p, addr, 0);
3274 }
3275 len -= l;
3276 buf += l;
3277 addr += l;
3278 }
3279}
3280
3281#else
3282void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
3283 int len, int is_write)
3284{
3285 int l, io_index;
3286 uint8_t *ptr;
3287 uint32_t val;
3288 target_phys_addr_t page;
3289 unsigned long pd;
3290 PhysPageDesc *p;
3291
3292 while (len > 0) {
3293 page = addr & TARGET_PAGE_MASK;
3294 l = (page + TARGET_PAGE_SIZE) - addr;
3295 if (l > len)
3296 l = len;
3297 p = phys_page_find(page >> TARGET_PAGE_BITS);
3298 if (!p) {
3299 pd = IO_MEM_UNASSIGNED;
3300 } else {
3301 pd = p->phys_offset;
3302 }
3303
3304 if (is_write) {
3305 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003306 target_phys_addr_t addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003307 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003308 if (p)
3309 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003310 /* XXX: could force cpu_single_env to NULL to avoid
3311 potential bugs */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003312 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003313 /* 32 bit write access */
3314 val = ldl_p(buf);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003315 io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003316 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003317 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003318 /* 16 bit write access */
3319 val = lduw_p(buf);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003320 io_mem_write[io_index][1](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003321 l = 2;
3322 } else {
3323 /* 8 bit write access */
3324 val = ldub_p(buf);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003325 io_mem_write[io_index][0](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003326 l = 1;
3327 }
3328 } else {
3329 unsigned long addr1;
3330 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3331 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003332 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003333 memcpy(ptr, buf, l);
3334 if (!cpu_physical_memory_is_dirty(addr1)) {
3335 /* invalidate code */
3336 tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
3337 /* set dirty bit */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003338 cpu_physical_memory_set_dirty_flags(
3339 addr1, (0xff & ~CODE_DIRTY_FLAG));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003340 }
3341 }
3342 } else {
3343 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3344 !(pd & IO_MEM_ROMD)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003345 target_phys_addr_t addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003346 /* I/O case */
3347 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003348 if (p)
3349 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3350 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003351 /* 32 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003352 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003353 stl_p(buf, val);
3354 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003355 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003356 /* 16 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003357 val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003358 stw_p(buf, val);
3359 l = 2;
3360 } else {
3361 /* 8 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003362 val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003363 stb_p(buf, val);
3364 l = 1;
3365 }
3366 } else {
3367 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003368 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003369 (addr & ~TARGET_PAGE_MASK);
3370 memcpy(buf, ptr, l);
3371 }
3372 }
3373 len -= l;
3374 buf += l;
3375 addr += l;
3376 }
3377}
3378
3379/* used for ROM loading : can write in RAM and ROM */
3380void cpu_physical_memory_write_rom(target_phys_addr_t addr,
3381 const uint8_t *buf, int len)
3382{
3383 int l;
3384 uint8_t *ptr;
3385 target_phys_addr_t page;
3386 unsigned long pd;
3387 PhysPageDesc *p;
3388
3389 while (len > 0) {
3390 page = addr & TARGET_PAGE_MASK;
3391 l = (page + TARGET_PAGE_SIZE) - addr;
3392 if (l > len)
3393 l = len;
3394 p = phys_page_find(page >> TARGET_PAGE_BITS);
3395 if (!p) {
3396 pd = IO_MEM_UNASSIGNED;
3397 } else {
3398 pd = p->phys_offset;
3399 }
3400
3401 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
3402 (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
3403 !(pd & IO_MEM_ROMD)) {
3404 /* do nothing */
3405 } else {
3406 unsigned long addr1;
3407 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3408 /* ROM/RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003409 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003410 memcpy(ptr, buf, l);
3411 }
3412 len -= l;
3413 buf += l;
3414 addr += l;
3415 }
3416}
3417
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003418typedef struct {
3419 void *buffer;
3420 target_phys_addr_t addr;
3421 target_phys_addr_t len;
3422} BounceBuffer;
3423
3424static BounceBuffer bounce;
3425
3426typedef struct MapClient {
3427 void *opaque;
3428 void (*callback)(void *opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003429 QLIST_ENTRY(MapClient) link;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003430} MapClient;
3431
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003432static QLIST_HEAD(map_client_list, MapClient) map_client_list
3433 = QLIST_HEAD_INITIALIZER(map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003434
3435void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
3436{
3437 MapClient *client = qemu_malloc(sizeof(*client));
3438
3439 client->opaque = opaque;
3440 client->callback = callback;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003441 QLIST_INSERT_HEAD(&map_client_list, client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003442 return client;
3443}
3444
3445void cpu_unregister_map_client(void *_client)
3446{
3447 MapClient *client = (MapClient *)_client;
3448
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003449 QLIST_REMOVE(client, link);
3450 qemu_free(client);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003451}
3452
3453static void cpu_notify_map_clients(void)
3454{
3455 MapClient *client;
3456
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003457 while (!QLIST_EMPTY(&map_client_list)) {
3458 client = QLIST_FIRST(&map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003459 client->callback(client->opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003460 QLIST_REMOVE(client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003461 }
3462}
3463
3464/* Map a physical memory region into a host virtual address.
3465 * May map a subset of the requested range, given by and returned in *plen.
3466 * May return NULL if resources needed to perform the mapping are exhausted.
3467 * Use only for reads OR writes - not for read-modify-write operations.
3468 * Use cpu_register_map_client() to know when retrying the map operation is
3469 * likely to succeed.
3470 */
3471void *cpu_physical_memory_map(target_phys_addr_t addr,
3472 target_phys_addr_t *plen,
3473 int is_write)
3474{
3475 target_phys_addr_t len = *plen;
3476 target_phys_addr_t done = 0;
3477 int l;
3478 uint8_t *ret = NULL;
3479 uint8_t *ptr;
3480 target_phys_addr_t page;
3481 unsigned long pd;
3482 PhysPageDesc *p;
3483 unsigned long addr1;
3484
3485 while (len > 0) {
3486 page = addr & TARGET_PAGE_MASK;
3487 l = (page + TARGET_PAGE_SIZE) - addr;
3488 if (l > len)
3489 l = len;
3490 p = phys_page_find(page >> TARGET_PAGE_BITS);
3491 if (!p) {
3492 pd = IO_MEM_UNASSIGNED;
3493 } else {
3494 pd = p->phys_offset;
3495 }
3496
3497 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3498 if (done || bounce.buffer) {
3499 break;
3500 }
3501 bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
3502 bounce.addr = addr;
3503 bounce.len = l;
3504 if (!is_write) {
3505 cpu_physical_memory_rw(addr, bounce.buffer, l, 0);
3506 }
3507 ptr = bounce.buffer;
3508 } else {
3509 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3510 ptr = qemu_get_ram_ptr(addr1);
3511 }
3512 if (!done) {
3513 ret = ptr;
3514 } else if (ret + done != ptr) {
3515 break;
3516 }
3517
3518 len -= l;
3519 addr += l;
3520 done += l;
3521 }
3522 *plen = done;
3523 return ret;
3524}
3525
3526/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
3527 * Will also mark the memory as dirty if is_write == 1. access_len gives
3528 * the amount of memory that was actually read or written by the caller.
3529 */
3530void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
3531 int is_write, target_phys_addr_t access_len)
3532{
3533 if (buffer != bounce.buffer) {
3534 if (is_write) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003535 ram_addr_t addr1 = qemu_ram_addr_from_host_nofail(buffer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003536 while (access_len) {
3537 unsigned l;
3538 l = TARGET_PAGE_SIZE;
3539 if (l > access_len)
3540 l = access_len;
3541 if (!cpu_physical_memory_is_dirty(addr1)) {
3542 /* invalidate code */
3543 tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
3544 /* set dirty bit */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003545 cpu_physical_memory_set_dirty_flags(
3546 addr1, (0xff & ~CODE_DIRTY_FLAG));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003547 }
3548 addr1 += l;
3549 access_len -= l;
3550 }
3551 }
3552 return;
3553 }
3554 if (is_write) {
3555 cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
3556 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003557 qemu_vfree(bounce.buffer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003558 bounce.buffer = NULL;
3559 cpu_notify_map_clients();
3560}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003561
3562/* warning: addr must be aligned */
3563uint32_t ldl_phys(target_phys_addr_t addr)
3564{
3565 int io_index;
3566 uint8_t *ptr;
3567 uint32_t val;
3568 unsigned long pd;
3569 PhysPageDesc *p;
3570
3571 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3572 if (!p) {
3573 pd = IO_MEM_UNASSIGNED;
3574 } else {
3575 pd = p->phys_offset;
3576 }
3577
3578 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3579 !(pd & IO_MEM_ROMD)) {
3580 /* I/O case */
3581 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003582 if (p)
3583 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003584 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3585 } else {
3586 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003587 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003588 (addr & ~TARGET_PAGE_MASK);
3589 val = ldl_p(ptr);
3590 }
3591 return val;
3592}
3593
3594/* warning: addr must be aligned */
3595uint64_t ldq_phys(target_phys_addr_t addr)
3596{
3597 int io_index;
3598 uint8_t *ptr;
3599 uint64_t val;
3600 unsigned long pd;
3601 PhysPageDesc *p;
3602
3603 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3604 if (!p) {
3605 pd = IO_MEM_UNASSIGNED;
3606 } else {
3607 pd = p->phys_offset;
3608 }
3609
3610 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3611 !(pd & IO_MEM_ROMD)) {
3612 /* I/O case */
3613 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003614 if (p)
3615 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003616#ifdef TARGET_WORDS_BIGENDIAN
3617 val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
3618 val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
3619#else
3620 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3621 val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
3622#endif
3623 } else {
3624 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003625 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003626 (addr & ~TARGET_PAGE_MASK);
3627 val = ldq_p(ptr);
3628 }
3629 return val;
3630}
3631
3632/* XXX: optimize */
3633uint32_t ldub_phys(target_phys_addr_t addr)
3634{
3635 uint8_t val;
3636 cpu_physical_memory_read(addr, &val, 1);
3637 return val;
3638}
3639
3640/* XXX: optimize */
3641uint32_t lduw_phys(target_phys_addr_t addr)
3642{
3643 uint16_t val;
3644 cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
3645 return tswap16(val);
3646}
3647
3648/* warning: addr must be aligned. The ram page is not masked as dirty
3649 and the code inside is not invalidated. It is useful if the dirty
3650 bits are used to track modified PTEs */
3651void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
3652{
3653 int io_index;
3654 uint8_t *ptr;
3655 unsigned long pd;
3656 PhysPageDesc *p;
3657
3658 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3659 if (!p) {
3660 pd = IO_MEM_UNASSIGNED;
3661 } else {
3662 pd = p->phys_offset;
3663 }
3664
3665 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3666 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003667 if (p)
3668 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003669 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3670 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003671 unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3672 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003673 stl_p(ptr, val);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003674
3675 if (unlikely(in_migration)) {
3676 if (!cpu_physical_memory_is_dirty(addr1)) {
3677 /* invalidate code */
3678 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3679 /* set dirty bit */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003680 cpu_physical_memory_set_dirty_flags(
3681 addr1, (0xff & ~CODE_DIRTY_FLAG));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003682 }
3683 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003684 }
3685}
3686
3687void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
3688{
3689 int io_index;
3690 uint8_t *ptr;
3691 unsigned long pd;
3692 PhysPageDesc *p;
3693
3694 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3695 if (!p) {
3696 pd = IO_MEM_UNASSIGNED;
3697 } else {
3698 pd = p->phys_offset;
3699 }
3700
3701 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3702 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003703 if (p)
3704 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003705#ifdef TARGET_WORDS_BIGENDIAN
3706 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
3707 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
3708#else
3709 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3710 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
3711#endif
3712 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003713 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003714 (addr & ~TARGET_PAGE_MASK);
3715 stq_p(ptr, val);
3716 }
3717}
3718
3719/* warning: addr must be aligned */
3720void stl_phys(target_phys_addr_t addr, uint32_t val)
3721{
3722 int io_index;
3723 uint8_t *ptr;
3724 unsigned long pd;
3725 PhysPageDesc *p;
3726
3727 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3728 if (!p) {
3729 pd = IO_MEM_UNASSIGNED;
3730 } else {
3731 pd = p->phys_offset;
3732 }
3733
3734 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3735 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003736 if (p)
3737 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003738 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3739 } else {
3740 unsigned long addr1;
3741 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3742 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003743 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003744 stl_p(ptr, val);
3745 if (!cpu_physical_memory_is_dirty(addr1)) {
3746 /* invalidate code */
3747 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3748 /* set dirty bit */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003749 cpu_physical_memory_set_dirty_flags(addr1,
3750 (0xff & ~CODE_DIRTY_FLAG));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003751 }
3752 }
3753}
3754
3755/* XXX: optimize */
3756void stb_phys(target_phys_addr_t addr, uint32_t val)
3757{
3758 uint8_t v = val;
3759 cpu_physical_memory_write(addr, &v, 1);
3760}
3761
3762/* XXX: optimize */
3763void stw_phys(target_phys_addr_t addr, uint32_t val)
3764{
3765 uint16_t v = tswap16(val);
3766 cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
3767}
3768
3769/* XXX: optimize */
3770void stq_phys(target_phys_addr_t addr, uint64_t val)
3771{
3772 val = tswap64(val);
3773 cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
3774}
3775
3776#endif
3777
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003778/* virtual memory access for debug (includes writing to ROM) */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003779int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
3780 uint8_t *buf, int len, int is_write)
3781{
3782 int l;
3783 target_phys_addr_t phys_addr;
3784 target_ulong page;
3785
3786 while (len > 0) {
3787 page = addr & TARGET_PAGE_MASK;
3788 phys_addr = cpu_get_phys_page_debug(env, page);
3789 /* if no physical page mapped, return an error */
3790 if (phys_addr == -1)
3791 return -1;
3792 l = (page + TARGET_PAGE_SIZE) - addr;
3793 if (l > len)
3794 l = len;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003795 phys_addr += (addr & ~TARGET_PAGE_MASK);
3796#if !defined(CONFIG_USER_ONLY)
3797 if (is_write)
3798 cpu_physical_memory_write_rom(phys_addr, buf, l);
3799 else
3800#endif
3801 cpu_physical_memory_rw(phys_addr, buf, l, is_write);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003802 len -= l;
3803 buf += l;
3804 addr += l;
3805 }
3806 return 0;
3807}
3808
3809/* in deterministic execution mode, instructions doing device I/Os
3810 must be at the end of the TB */
3811void cpu_io_recompile(CPUState *env, void *retaddr)
3812{
3813 TranslationBlock *tb;
3814 uint32_t n, cflags;
3815 target_ulong pc, cs_base;
3816 uint64_t flags;
3817
3818 tb = tb_find_pc((unsigned long)retaddr);
3819 if (!tb) {
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02003820 cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003821 retaddr);
3822 }
3823 n = env->icount_decr.u16.low + tb->icount;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02003824 cpu_restore_state(tb, env, (unsigned long)retaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003825 /* Calculate how many instructions had been executed before the fault
3826 occurred. */
3827 n = n - env->icount_decr.u16.low;
3828 /* Generate a new TB ending on the I/O insn. */
3829 n++;
3830 /* On MIPS and SH, delay slot instructions can only be restarted if
3831 they were already the first instruction in the TB. If this is not
3832 the first instruction in a TB then re-execute the preceding
3833 branch. */
3834#if defined(TARGET_MIPS)
3835 if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) {
3836 env->active_tc.PC -= 4;
3837 env->icount_decr.u16.low++;
3838 env->hflags &= ~MIPS_HFLAG_BMASK;
3839 }
3840#elif defined(TARGET_SH4)
3841 if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
3842 && n > 1) {
3843 env->pc -= 2;
3844 env->icount_decr.u16.low++;
3845 env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
3846 }
3847#endif
3848 /* This should never happen. */
3849 if (n > CF_COUNT_MASK)
3850 cpu_abort(env, "TB too big during recompile");
3851
3852 cflags = n | CF_LAST_IO;
3853 pc = tb->pc;
3854 cs_base = tb->cs_base;
3855 flags = tb->flags;
3856 tb_phys_invalidate(tb, -1);
3857 /* FIXME: In theory this could raise an exception. In practice
3858 we have already translated the block once so it's probably ok. */
3859 tb_gen_code(env, pc, cs_base, flags, cflags);
3860 /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
3861 the first in the TB) then we end up generating a whole new TB and
3862 repeating the fault, which is horribly inefficient.
3863 Better would be to execute just this insn uncached, or generate a
3864 second new TB. */
3865 cpu_resume_from_signal(env, NULL);
3866}
3867
David 'Digit' Turner36411062010-12-22 17:34:53 +01003868#if !defined(CONFIG_USER_ONLY)
3869
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003870void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003871{
3872 int i, target_code_size, max_target_code_size;
3873 int direct_jmp_count, direct_jmp2_count, cross_page;
3874 TranslationBlock *tb;
3875
3876 target_code_size = 0;
3877 max_target_code_size = 0;
3878 cross_page = 0;
3879 direct_jmp_count = 0;
3880 direct_jmp2_count = 0;
3881 for(i = 0; i < nb_tbs; i++) {
3882 tb = &tbs[i];
3883 target_code_size += tb->size;
3884 if (tb->size > max_target_code_size)
3885 max_target_code_size = tb->size;
3886 if (tb->page_addr[1] != -1)
3887 cross_page++;
3888 if (tb->tb_next_offset[0] != 0xffff) {
3889 direct_jmp_count++;
3890 if (tb->tb_next_offset[1] != 0xffff) {
3891 direct_jmp2_count++;
3892 }
3893 }
3894 }
3895 /* XXX: avoid using doubles ? */
3896 cpu_fprintf(f, "Translation buffer state:\n");
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003897 cpu_fprintf(f, "gen code size %td/%ld\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003898 code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02003899 cpu_fprintf(f, "TB count %d/%d\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003900 nb_tbs, code_gen_max_blocks);
3901 cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
3902 nb_tbs ? target_code_size / nb_tbs : 0,
3903 max_target_code_size);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003904 cpu_fprintf(f, "TB avg host size %td bytes (expansion ratio: %0.1f)\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003905 nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
3906 target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
3907 cpu_fprintf(f, "cross page TB count %d (%d%%)\n",
3908 cross_page,
3909 nb_tbs ? (cross_page * 100) / nb_tbs : 0);
3910 cpu_fprintf(f, "direct jump count %d (%d%%) (2 jumps=%d %d%%)\n",
3911 direct_jmp_count,
3912 nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
3913 direct_jmp2_count,
3914 nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
3915 cpu_fprintf(f, "\nStatistics:\n");
3916 cpu_fprintf(f, "TB flush count %d\n", tb_flush_count);
3917 cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
3918 cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count);
3919 tcg_dump_info(f, cpu_fprintf);
3920}
3921
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003922#define MMUSUFFIX _cmmu
3923#define GETPC() NULL
3924#define env cpu_single_env
3925#define SOFTMMU_CODE_ACCESS
3926
3927#define SHIFT 0
3928#include "softmmu_template.h"
3929
3930#define SHIFT 1
3931#include "softmmu_template.h"
3932
3933#define SHIFT 2
3934#include "softmmu_template.h"
3935
3936#define SHIFT 3
3937#include "softmmu_template.h"
3938
3939#undef env
3940
3941#endif