blob: ce6aedad049741ab9ff472c161c0c26deb6990f6 [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
17 * License along with this library; if not, write to the Free Software
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080019 */
20#include "config.h"
21#ifdef _WIN32
22#define WIN32_LEAN_AND_MEAN
23#include <windows.h>
24#else
25#include <sys/types.h>
26#include <sys/mman.h>
27#endif
28#include <stdlib.h>
29#include <stdio.h>
30#include <stdarg.h>
31#include <string.h>
32#include <errno.h>
33#include <unistd.h>
34#include <inttypes.h>
35
36#include "cpu.h"
37#include "exec-all.h"
38#include "qemu-common.h"
39#include "tcg.h"
40#include "hw/hw.h"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070041#include "osdep.h"
42#include "kvm.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' Turner5d8f37a2009-09-14 14:32:27 -070078#elif defined(TARGET_X86_64) && !defined(CONFIG_KQEMU)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080079#define TARGET_PHYS_ADDR_SPACE_BITS 42
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070080#elif defined(TARGET_I386) && !defined(CONFIG_KQEMU)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080081#define TARGET_PHYS_ADDR_SPACE_BITS 36
82#else
83/* Note: for compatibility with kqemu, we use 32 bits for x86_64 */
84#define TARGET_PHYS_ADDR_SPACE_BITS 32
85#endif
86
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070087static TranslationBlock *tbs;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080088int code_gen_max_blocks;
89TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070090static int nb_tbs;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080091/* any access to the tbs or the page table must use this lock */
92spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
93
94#if defined(__arm__) || defined(__sparc_v9__)
95/* The prologue must be reachable with a direct jump. ARM and Sparc64
96 have limited branch ranges (possibly also PPC) so place it in a
97 section close to code segment. */
98#define code_gen_section \
99 __attribute__((__section__(".gen_code"))) \
100 __attribute__((aligned (32)))
101#else
102#define code_gen_section \
103 __attribute__((aligned (32)))
104#endif
105
106uint8_t code_gen_prologue[1024] code_gen_section;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700107static uint8_t *code_gen_buffer;
108static unsigned long code_gen_buffer_size;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800109/* threshold to flush the translated code buffer */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700110static unsigned long code_gen_buffer_max_size;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800111uint8_t *code_gen_ptr;
112
113#if !defined(CONFIG_USER_ONLY)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800114int phys_ram_fd;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800115uint8_t *phys_ram_dirty;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700116static int in_migration;
117
118typedef struct RAMBlock {
119 uint8_t *host;
120 ram_addr_t offset;
121 ram_addr_t length;
122 struct RAMBlock *next;
123} RAMBlock;
124
125static RAMBlock *ram_blocks;
126/* TODO: When we implement (and use) ram deallocation (e.g. for hotplug)
127 then we can no longer assume contiguous ram offsets, and external uses
128 of this variable will break. */
129ram_addr_t last_ram_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800130#endif
131
132CPUState *first_cpu;
133/* current CPU in the current thread. It is only valid inside
134 cpu_exec() */
135CPUState *cpu_single_env;
136/* 0 = Do not count executed instructions.
137 1 = Precise instruction counting.
138 2 = Adaptive rate instruction counting. */
139int use_icount = 0;
140/* Current instruction counter. While executing translated code this may
141 include some instructions that have not yet been executed. */
142int64_t qemu_icount;
143
144typedef struct PageDesc {
145 /* list of TBs intersecting this ram page */
146 TranslationBlock *first_tb;
147 /* in order to optimize self modifying code, we count the number
148 of lookups we do to a given page to use a bitmap */
149 unsigned int code_write_count;
150 uint8_t *code_bitmap;
151#if defined(CONFIG_USER_ONLY)
152 unsigned long flags;
153#endif
154} PageDesc;
155
156typedef struct PhysPageDesc {
157 /* offset in host memory of the page + io_index in the low bits */
158 ram_addr_t phys_offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700159 ram_addr_t region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800160} PhysPageDesc;
161
162#define L2_BITS 10
163#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
164/* XXX: this is a temporary hack for alpha target.
165 * In the future, this is to be replaced by a multi-level table
166 * to actually be able to handle the complete 64 bits address space.
167 */
168#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
169#else
170#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
171#endif
172
173#define L1_SIZE (1 << L1_BITS)
174#define L2_SIZE (1 << L2_BITS)
175
176unsigned long qemu_real_host_page_size;
177unsigned long qemu_host_page_bits;
178unsigned long qemu_host_page_size;
179unsigned long qemu_host_page_mask;
180
181/* XXX: for system emulation, it could just be an array */
182static PageDesc *l1_map[L1_SIZE];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700183static PhysPageDesc **l1_phys_map;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800184
185#if !defined(CONFIG_USER_ONLY)
186static void io_mem_init(void);
187
188/* io memory support */
189CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
190CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
191void *io_mem_opaque[IO_MEM_NB_ENTRIES];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700192static char io_mem_used[IO_MEM_NB_ENTRIES];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800193static int io_mem_watch;
194#endif
195
196/* log support */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700197static const char *logfilename = "/tmp/qemu.log";
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800198FILE *logfile;
199int loglevel;
200static int log_append = 0;
201
202/* statistics */
203static int tlb_flush_count;
204static int tb_flush_count;
205static int tb_phys_invalidate_count;
206
207#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
208typedef struct subpage_t {
209 target_phys_addr_t base;
210 CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE][4];
211 CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE][4];
212 void *opaque[TARGET_PAGE_SIZE][2][4];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700213 ram_addr_t region_offset[TARGET_PAGE_SIZE][2][4];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800214} subpage_t;
215
216#ifdef _WIN32
217static void map_exec(void *addr, long size)
218{
219 DWORD old_protect;
220 VirtualProtect(addr, size,
221 PAGE_EXECUTE_READWRITE, &old_protect);
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800222
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800223}
224#else
225static void map_exec(void *addr, long size)
226{
227 unsigned long start, end, page_size;
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800228
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800229 page_size = getpagesize();
230 start = (unsigned long)addr;
231 start &= ~(page_size - 1);
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800232
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800233 end = (unsigned long)addr + size;
234 end += page_size - 1;
235 end &= ~(page_size - 1);
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800236
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800237 mprotect((void *)start, end - start,
238 PROT_READ | PROT_WRITE | PROT_EXEC);
239}
240#endif
241
242static void page_init(void)
243{
244 /* NOTE: we can always suppose that qemu_host_page_size >=
245 TARGET_PAGE_SIZE */
246#ifdef _WIN32
247 {
248 SYSTEM_INFO system_info;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800249
250 GetSystemInfo(&system_info);
251 qemu_real_host_page_size = system_info.dwPageSize;
252 }
253#else
254 qemu_real_host_page_size = getpagesize();
255#endif
256 if (qemu_host_page_size == 0)
257 qemu_host_page_size = qemu_real_host_page_size;
258 if (qemu_host_page_size < TARGET_PAGE_SIZE)
259 qemu_host_page_size = TARGET_PAGE_SIZE;
260 qemu_host_page_bits = 0;
261 while ((1 << qemu_host_page_bits) < qemu_host_page_size)
262 qemu_host_page_bits++;
263 qemu_host_page_mask = ~(qemu_host_page_size - 1);
264 l1_phys_map = qemu_vmalloc(L1_SIZE * sizeof(void *));
265 memset(l1_phys_map, 0, L1_SIZE * sizeof(void *));
266
267#if !defined(_WIN32) && defined(CONFIG_USER_ONLY)
268 {
269 long long startaddr, endaddr;
270 FILE *f;
271 int n;
272
273 mmap_lock();
274 last_brk = (unsigned long)sbrk(0);
275 f = fopen("/proc/self/maps", "r");
276 if (f) {
277 do {
278 n = fscanf (f, "%llx-%llx %*[^\n]\n", &startaddr, &endaddr);
279 if (n == 2) {
280 startaddr = MIN(startaddr,
281 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
282 endaddr = MIN(endaddr,
283 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
284 page_set_flags(startaddr & TARGET_PAGE_MASK,
285 TARGET_PAGE_ALIGN(endaddr),
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800286 PAGE_RESERVED);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800287 }
288 } while (!feof(f));
289 fclose(f);
290 }
291 mmap_unlock();
292 }
293#endif
294}
295
296static inline PageDesc **page_l1_map(target_ulong index)
297{
298#if TARGET_LONG_BITS > 32
299 /* Host memory outside guest VM. For 32-bit targets we have already
300 excluded high addresses. */
301 if (index > ((target_ulong)L2_SIZE * L1_SIZE))
302 return NULL;
303#endif
304 return &l1_map[index >> L2_BITS];
305}
306
307static inline PageDesc *page_find_alloc(target_ulong index)
308{
309 PageDesc **lp, *p;
310 lp = page_l1_map(index);
311 if (!lp)
312 return NULL;
313
314 p = *lp;
315 if (!p) {
316 /* allocate if not found */
317#if defined(CONFIG_USER_ONLY)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800318 size_t len = sizeof(PageDesc) * L2_SIZE;
319 /* Don't use qemu_malloc because it may recurse. */
320 p = mmap(0, len, PROT_READ | PROT_WRITE,
321 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
322 *lp = p;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700323 if (h2g_valid(p)) {
324 unsigned long addr = h2g(p);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800325 page_set_flags(addr & TARGET_PAGE_MASK,
326 TARGET_PAGE_ALIGN(addr + len),
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800327 PAGE_RESERVED);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800328 }
329#else
330 p = qemu_mallocz(sizeof(PageDesc) * L2_SIZE);
331 *lp = p;
332#endif
333 }
334 return p + (index & (L2_SIZE - 1));
335}
336
337static inline PageDesc *page_find(target_ulong index)
338{
339 PageDesc **lp, *p;
340 lp = page_l1_map(index);
341 if (!lp)
342 return NULL;
343
344 p = *lp;
345 if (!p)
346 return 0;
347 return p + (index & (L2_SIZE - 1));
348}
349
350static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
351{
352 void **lp, **p;
353 PhysPageDesc *pd;
354
355 p = (void **)l1_phys_map;
356#if TARGET_PHYS_ADDR_SPACE_BITS > 32
357
358#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
359#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
360#endif
361 lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1));
362 p = *lp;
363 if (!p) {
364 /* allocate if not found */
365 if (!alloc)
366 return NULL;
367 p = qemu_vmalloc(sizeof(void *) * L1_SIZE);
368 memset(p, 0, sizeof(void *) * L1_SIZE);
369 *lp = p;
370 }
371#endif
372 lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
373 pd = *lp;
374 if (!pd) {
375 int i;
376 /* allocate if not found */
377 if (!alloc)
378 return NULL;
379 pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
380 *lp = pd;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700381 for (i = 0; i < L2_SIZE; i++) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800382 pd[i].phys_offset = IO_MEM_UNASSIGNED;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700383 pd[i].region_offset = (index + i) << TARGET_PAGE_BITS;
384 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800385 }
386 return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
387}
388
389static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
390{
391 return phys_page_find_alloc(index, 0);
392}
393
394#if !defined(CONFIG_USER_ONLY)
395static void tlb_protect_code(ram_addr_t ram_addr);
396static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
397 target_ulong vaddr);
398#define mmap_lock() do { } while(0)
399#define mmap_unlock() do { } while(0)
400#endif
401
402#define DEFAULT_CODE_GEN_BUFFER_SIZE (32 * 1024 * 1024)
403
404#if defined(CONFIG_USER_ONLY)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700405/* Currently it is not recommended to allocate big chunks of data in
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800406 user mode. It will change when a dedicated libc will be used */
407#define USE_STATIC_CODE_GEN_BUFFER
408#endif
409
410#ifdef USE_STATIC_CODE_GEN_BUFFER
411static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE];
412#endif
413
414static void code_gen_alloc(unsigned long tb_size)
415{
416#ifdef USE_STATIC_CODE_GEN_BUFFER
417 code_gen_buffer = static_code_gen_buffer;
418 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
419 map_exec(code_gen_buffer, code_gen_buffer_size);
420#else
421 code_gen_buffer_size = tb_size;
422 if (code_gen_buffer_size == 0) {
423#if defined(CONFIG_USER_ONLY)
424 /* in user mode, phys_ram_size is not meaningful */
425 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
426#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700427 /* XXX: needs adjustments */
428 code_gen_buffer_size = (unsigned long)(ram_size / 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800429#endif
430 }
431 if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE)
432 code_gen_buffer_size = MIN_CODE_GEN_BUFFER_SIZE;
433 /* The code gen buffer location may have constraints depending on
434 the host cpu and OS */
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800435#if defined(__linux__)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800436 {
437 int flags;
438 void *start = NULL;
439
440 flags = MAP_PRIVATE | MAP_ANONYMOUS;
441#if defined(__x86_64__)
442 flags |= MAP_32BIT;
443 /* Cannot map more than that */
444 if (code_gen_buffer_size > (800 * 1024 * 1024))
445 code_gen_buffer_size = (800 * 1024 * 1024);
446#elif defined(__sparc_v9__)
447 // Map the buffer below 2G, so we can use direct calls and branches
448 flags |= MAP_FIXED;
449 start = (void *) 0x60000000UL;
450 if (code_gen_buffer_size > (512 * 1024 * 1024))
451 code_gen_buffer_size = (512 * 1024 * 1024);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700452#elif defined(__arm__)
453 /* Map the buffer below 32M, so we can use direct calls and branches */
454 flags |= MAP_FIXED;
455 start = (void *) 0x01000000UL;
456 if (code_gen_buffer_size > 16 * 1024 * 1024)
457 code_gen_buffer_size = 16 * 1024 * 1024;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800458#endif
459 code_gen_buffer = mmap(start, code_gen_buffer_size,
460 PROT_WRITE | PROT_READ | PROT_EXEC,
461 flags, -1, 0);
462 if (code_gen_buffer == MAP_FAILED) {
463 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
464 exit(1);
465 }
466 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700467#elif defined(__FreeBSD__) || defined(__DragonFly__)
468 {
469 int flags;
470 void *addr = NULL;
471 flags = MAP_PRIVATE | MAP_ANONYMOUS;
472#if defined(__x86_64__)
473 /* FreeBSD doesn't have MAP_32BIT, use MAP_FIXED and assume
474 * 0x40000000 is free */
475 flags |= MAP_FIXED;
476 addr = (void *)0x40000000;
477 /* Cannot map more than that */
478 if (code_gen_buffer_size > (800 * 1024 * 1024))
479 code_gen_buffer_size = (800 * 1024 * 1024);
480#endif
481 code_gen_buffer = mmap(addr, code_gen_buffer_size,
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800482 PROT_WRITE | PROT_READ | PROT_EXEC,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700483 flags, -1, 0);
484 if (code_gen_buffer == MAP_FAILED) {
485 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
486 exit(1);
487 }
488 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800489#else
490 code_gen_buffer = qemu_malloc(code_gen_buffer_size);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800491 map_exec(code_gen_buffer, code_gen_buffer_size);
492#endif
493#endif /* !USE_STATIC_CODE_GEN_BUFFER */
494 map_exec(code_gen_prologue, sizeof(code_gen_prologue));
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800495 code_gen_buffer_max_size = code_gen_buffer_size -
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800496 code_gen_max_block_size();
497 code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
498 tbs = qemu_malloc(code_gen_max_blocks * sizeof(TranslationBlock));
499}
500
501/* Must be called before using the QEMU cpus. 'tb_size' is the size
502 (in bytes) allocated to the translation buffer. Zero means default
503 size. */
504void cpu_exec_init_all(unsigned long tb_size)
505{
506 cpu_gen_init();
507 code_gen_alloc(tb_size);
508 code_gen_ptr = code_gen_buffer;
509 page_init();
510#if !defined(CONFIG_USER_ONLY)
511 io_mem_init();
512#endif
513}
514
515#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
516
517#define CPU_COMMON_SAVE_VERSION 1
518
519static void cpu_common_save(QEMUFile *f, void *opaque)
520{
521 CPUState *env = opaque;
522
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700523 cpu_synchronize_state(env, 0);
524
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800525 qemu_put_be32s(f, &env->halted);
526 qemu_put_be32s(f, &env->interrupt_request);
527}
528
529static int cpu_common_load(QEMUFile *f, void *opaque, int version_id)
530{
531 CPUState *env = opaque;
532
533 if (version_id != CPU_COMMON_SAVE_VERSION)
534 return -EINVAL;
535
536 qemu_get_be32s(f, &env->halted);
537 qemu_get_be32s(f, &env->interrupt_request);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700538 /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
539 version_id is increased. */
540 env->interrupt_request &= ~0x01;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800541 tlb_flush(env, 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700542 cpu_synchronize_state(env, 1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800543
544 return 0;
545}
546#endif
547
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700548CPUState *qemu_get_cpu(int cpu)
549{
550 CPUState *env = first_cpu;
551
552 while (env) {
553 if (env->cpu_index == cpu)
554 break;
555 env = env->next_cpu;
556 }
557
558 return env;
559}
560
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800561void cpu_exec_init(CPUState *env)
562{
563 CPUState **penv;
564 int cpu_index;
565
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700566#if defined(CONFIG_USER_ONLY)
567 cpu_list_lock();
568#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800569 env->next_cpu = NULL;
570 penv = &first_cpu;
571 cpu_index = 0;
572 while (*penv != NULL) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700573 penv = &(*penv)->next_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800574 cpu_index++;
575 }
576 env->cpu_index = cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700577 env->numa_node = 0;
578 TAILQ_INIT(&env->breakpoints);
579 TAILQ_INIT(&env->watchpoints);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800580 *penv = env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700581#if defined(CONFIG_USER_ONLY)
582 cpu_list_unlock();
583#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800584#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
585 register_savevm("cpu_common", cpu_index, CPU_COMMON_SAVE_VERSION,
586 cpu_common_save, cpu_common_load, env);
587 register_savevm("cpu", cpu_index, CPU_SAVE_VERSION,
588 cpu_save, cpu_load, env);
589#endif
590}
591
592static inline void invalidate_page_bitmap(PageDesc *p)
593{
594 if (p->code_bitmap) {
595 qemu_free(p->code_bitmap);
596 p->code_bitmap = NULL;
597 }
598 p->code_write_count = 0;
599}
600
601/* set to NULL all the 'first_tb' fields in all PageDescs */
602static void page_flush_tb(void)
603{
604 int i, j;
605 PageDesc *p;
606
607 for(i = 0; i < L1_SIZE; i++) {
608 p = l1_map[i];
609 if (p) {
610 for(j = 0; j < L2_SIZE; j++) {
611 p->first_tb = NULL;
612 invalidate_page_bitmap(p);
613 p++;
614 }
615 }
616 }
617}
618
619/* flush all the translation blocks */
620/* XXX: tb_flush is currently not thread safe */
621void tb_flush(CPUState *env1)
622{
623 CPUState *env;
624#if defined(DEBUG_FLUSH)
625 printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
626 (unsigned long)(code_gen_ptr - code_gen_buffer),
627 nb_tbs, nb_tbs > 0 ?
628 ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
629#endif
630 if ((unsigned long)(code_gen_ptr - code_gen_buffer) > code_gen_buffer_size)
631 cpu_abort(env1, "Internal error: code buffer overflow\n");
632
633 nb_tbs = 0;
634
635 for(env = first_cpu; env != NULL; env = env->next_cpu) {
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800636#ifdef CONFIG_MEMCHECK
637 int tb_to_clean;
638 for (tb_to_clean = 0; tb_to_clean < TB_JMP_CACHE_SIZE; tb_to_clean++) {
639 if (env->tb_jmp_cache[tb_to_clean] != NULL &&
640 env->tb_jmp_cache[tb_to_clean]->tpc2gpc != NULL) {
641 qemu_free(env->tb_jmp_cache[tb_to_clean]->tpc2gpc);
642 env->tb_jmp_cache[tb_to_clean]->tpc2gpc = NULL;
643 env->tb_jmp_cache[tb_to_clean]->tpc2gpc_pairs = 0;
644 }
645 }
646#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800647 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
648 }
649
650 memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
651 page_flush_tb();
652
653 code_gen_ptr = code_gen_buffer;
654 /* XXX: flush processor icache at this point if cache flush is
655 expensive */
656 tb_flush_count++;
657}
658
659#ifdef DEBUG_TB_CHECK
660
661static void tb_invalidate_check(target_ulong address)
662{
663 TranslationBlock *tb;
664 int i;
665 address &= TARGET_PAGE_MASK;
666 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
667 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
668 if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
669 address >= tb->pc + tb->size)) {
670 printf("ERROR invalidate: address=%08lx PC=%08lx size=%04x\n",
671 address, (long)tb->pc, tb->size);
672 }
673 }
674 }
675}
676
677/* verify that all the pages have correct rights for code */
678static void tb_page_check(void)
679{
680 TranslationBlock *tb;
681 int i, flags1, flags2;
682
683 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
684 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
685 flags1 = page_get_flags(tb->pc);
686 flags2 = page_get_flags(tb->pc + tb->size - 1);
687 if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
688 printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
689 (long)tb->pc, tb->size, flags1, flags2);
690 }
691 }
692 }
693}
694
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700695static void tb_jmp_check(TranslationBlock *tb)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800696{
697 TranslationBlock *tb1;
698 unsigned int n1;
699
700 /* suppress any remaining jumps to this TB */
701 tb1 = tb->jmp_first;
702 for(;;) {
703 n1 = (long)tb1 & 3;
704 tb1 = (TranslationBlock *)((long)tb1 & ~3);
705 if (n1 == 2)
706 break;
707 tb1 = tb1->jmp_next[n1];
708 }
709 /* check end of list */
710 if (tb1 != tb) {
711 printf("ERROR: jmp_list from 0x%08lx\n", (long)tb);
712 }
713}
714
715#endif
716
717/* invalidate one TB */
718static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb,
719 int next_offset)
720{
721 TranslationBlock *tb1;
722 for(;;) {
723 tb1 = *ptb;
724 if (tb1 == tb) {
725 *ptb = *(TranslationBlock **)((char *)tb1 + next_offset);
726 break;
727 }
728 ptb = (TranslationBlock **)((char *)tb1 + next_offset);
729 }
730}
731
732static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
733{
734 TranslationBlock *tb1;
735 unsigned int n1;
736
737 for(;;) {
738 tb1 = *ptb;
739 n1 = (long)tb1 & 3;
740 tb1 = (TranslationBlock *)((long)tb1 & ~3);
741 if (tb1 == tb) {
742 *ptb = tb1->page_next[n1];
743 break;
744 }
745 ptb = &tb1->page_next[n1];
746 }
747}
748
749static inline void tb_jmp_remove(TranslationBlock *tb, int n)
750{
751 TranslationBlock *tb1, **ptb;
752 unsigned int n1;
753
754 ptb = &tb->jmp_next[n];
755 tb1 = *ptb;
756 if (tb1) {
757 /* find tb(n) in circular list */
758 for(;;) {
759 tb1 = *ptb;
760 n1 = (long)tb1 & 3;
761 tb1 = (TranslationBlock *)((long)tb1 & ~3);
762 if (n1 == n && tb1 == tb)
763 break;
764 if (n1 == 2) {
765 ptb = &tb1->jmp_first;
766 } else {
767 ptb = &tb1->jmp_next[n1];
768 }
769 }
770 /* now we can suppress tb(n) from the list */
771 *ptb = tb->jmp_next[n];
772
773 tb->jmp_next[n] = NULL;
774 }
775}
776
777/* reset the jump entry 'n' of a TB so that it is not chained to
778 another TB */
779static inline void tb_reset_jump(TranslationBlock *tb, int n)
780{
781 tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
782}
783
784void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr)
785{
786 CPUState *env;
787 PageDesc *p;
788 unsigned int h, n1;
789 target_phys_addr_t phys_pc;
790 TranslationBlock *tb1, *tb2;
791
792 /* remove the TB from the hash list */
793 phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
794 h = tb_phys_hash_func(phys_pc);
795 tb_remove(&tb_phys_hash[h], tb,
796 offsetof(TranslationBlock, phys_hash_next));
797
798 /* remove the TB from the page list */
799 if (tb->page_addr[0] != page_addr) {
800 p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
801 tb_page_remove(&p->first_tb, tb);
802 invalidate_page_bitmap(p);
803 }
804 if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
805 p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
806 tb_page_remove(&p->first_tb, tb);
807 invalidate_page_bitmap(p);
808 }
809
810 tb_invalidated_flag = 1;
811
812 /* remove the TB from the hash list */
813 h = tb_jmp_cache_hash_func(tb->pc);
814 for(env = first_cpu; env != NULL; env = env->next_cpu) {
815 if (env->tb_jmp_cache[h] == tb)
816 env->tb_jmp_cache[h] = NULL;
817 }
818
819 /* suppress this TB from the two jump lists */
820 tb_jmp_remove(tb, 0);
821 tb_jmp_remove(tb, 1);
822
823 /* suppress any remaining jumps to this TB */
824 tb1 = tb->jmp_first;
825 for(;;) {
826 n1 = (long)tb1 & 3;
827 if (n1 == 2)
828 break;
829 tb1 = (TranslationBlock *)((long)tb1 & ~3);
830 tb2 = tb1->jmp_next[n1];
831 tb_reset_jump(tb1, n1);
832 tb1->jmp_next[n1] = NULL;
833 tb1 = tb2;
834 }
835 tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
836
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800837#ifdef CONFIG_MEMCHECK
838 if (tb->tpc2gpc != NULL) {
839 qemu_free(tb->tpc2gpc);
840 tb->tpc2gpc = NULL;
841 tb->tpc2gpc_pairs = 0;
842 }
843#endif // CONFIG_MEMCHECK
844
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800845 tb_phys_invalidate_count++;
846}
847
848static inline void set_bits(uint8_t *tab, int start, int len)
849{
850 int end, mask, end1;
851
852 end = start + len;
853 tab += start >> 3;
854 mask = 0xff << (start & 7);
855 if ((start & ~7) == (end & ~7)) {
856 if (start < end) {
857 mask &= ~(0xff << (end & 7));
858 *tab |= mask;
859 }
860 } else {
861 *tab++ |= mask;
862 start = (start + 8) & ~7;
863 end1 = end & ~7;
864 while (start < end1) {
865 *tab++ = 0xff;
866 start += 8;
867 }
868 if (start < end) {
869 mask = ~(0xff << (end & 7));
870 *tab |= mask;
871 }
872 }
873}
874
875static void build_page_bitmap(PageDesc *p)
876{
877 int n, tb_start, tb_end;
878 TranslationBlock *tb;
879
880 p->code_bitmap = qemu_mallocz(TARGET_PAGE_SIZE / 8);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800881
882 tb = p->first_tb;
883 while (tb != NULL) {
884 n = (long)tb & 3;
885 tb = (TranslationBlock *)((long)tb & ~3);
886 /* NOTE: this is subtle as a TB may span two physical pages */
887 if (n == 0) {
888 /* NOTE: tb_end may be after the end of the page, but
889 it is not a problem */
890 tb_start = tb->pc & ~TARGET_PAGE_MASK;
891 tb_end = tb_start + tb->size;
892 if (tb_end > TARGET_PAGE_SIZE)
893 tb_end = TARGET_PAGE_SIZE;
894 } else {
895 tb_start = 0;
896 tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
897 }
898 set_bits(p->code_bitmap, tb_start, tb_end - tb_start);
899 tb = tb->page_next[n];
900 }
901}
902
903TranslationBlock *tb_gen_code(CPUState *env,
904 target_ulong pc, target_ulong cs_base,
905 int flags, int cflags)
906{
907 TranslationBlock *tb;
908 uint8_t *tc_ptr;
909 target_ulong phys_pc, phys_page2, virt_page2;
910 int code_gen_size;
911
912 phys_pc = get_phys_addr_code(env, pc);
913 tb = tb_alloc(pc);
914 if (!tb) {
915 /* flush must be done */
916 tb_flush(env);
917 /* cannot fail at this point */
918 tb = tb_alloc(pc);
919 /* Don't forget to invalidate previous TB info. */
920 tb_invalidated_flag = 1;
921 }
922 tc_ptr = code_gen_ptr;
923 tb->tc_ptr = tc_ptr;
924 tb->cs_base = cs_base;
925 tb->flags = flags;
926 tb->cflags = cflags;
927#ifdef CONFIG_TRACE
928 tb->bb_rec = NULL;
929 tb->prev_time = 0;
930#endif
931 cpu_gen_code(env, tb, &code_gen_size);
932 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
933
934 /* check next page if needed */
935 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
936 phys_page2 = -1;
937 if ((pc & TARGET_PAGE_MASK) != virt_page2) {
938 phys_page2 = get_phys_addr_code(env, virt_page2);
939 }
940 tb_link_phys(tb, phys_pc, phys_page2);
941 return tb;
942}
943
944/* invalidate all TBs which intersect with the target physical page
945 starting in range [start;end[. NOTE: start and end must refer to
946 the same physical page. 'is_cpu_write_access' should be true if called
947 from a real cpu write access: the virtual CPU will exit the current
948 TB if code is modified inside this TB. */
949void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t end,
950 int is_cpu_write_access)
951{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700952 TranslationBlock *tb, *tb_next, *saved_tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800953 CPUState *env = cpu_single_env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800954 target_ulong tb_start, tb_end;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700955 PageDesc *p;
956 int n;
957#ifdef TARGET_HAS_PRECISE_SMC
958 int current_tb_not_found = is_cpu_write_access;
959 TranslationBlock *current_tb = NULL;
960 int current_tb_modified = 0;
961 target_ulong current_pc = 0;
962 target_ulong current_cs_base = 0;
963 int current_flags = 0;
964#endif /* TARGET_HAS_PRECISE_SMC */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800965
966 p = page_find(start >> TARGET_PAGE_BITS);
967 if (!p)
968 return;
969 if (!p->code_bitmap &&
970 ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
971 is_cpu_write_access) {
972 /* build code bitmap */
973 build_page_bitmap(p);
974 }
975
976 /* we remove all the TBs in the range [start, end[ */
977 /* 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 -0800978 tb = p->first_tb;
979 while (tb != NULL) {
980 n = (long)tb & 3;
981 tb = (TranslationBlock *)((long)tb & ~3);
982 tb_next = tb->page_next[n];
983 /* NOTE: this is subtle as a TB may span two physical pages */
984 if (n == 0) {
985 /* NOTE: tb_end may be after the end of the page, but
986 it is not a problem */
987 tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
988 tb_end = tb_start + tb->size;
989 } else {
990 tb_start = tb->page_addr[1];
991 tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
992 }
993 if (!(tb_end <= start || tb_start >= end)) {
994#ifdef TARGET_HAS_PRECISE_SMC
995 if (current_tb_not_found) {
996 current_tb_not_found = 0;
997 current_tb = NULL;
998 if (env->mem_io_pc) {
999 /* now we have a real cpu fault */
1000 current_tb = tb_find_pc(env->mem_io_pc);
1001 }
1002 }
1003 if (current_tb == tb &&
1004 (current_tb->cflags & CF_COUNT_MASK) != 1) {
1005 /* If we are modifying the current TB, we must stop
1006 its execution. We could be more precise by checking
1007 that the modification is after the current PC, but it
1008 would require a specialized function to partially
1009 restore the CPU state */
1010
1011 current_tb_modified = 1;
1012 cpu_restore_state(current_tb, env,
1013 env->mem_io_pc, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001014 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
1015 &current_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001016 }
1017#endif /* TARGET_HAS_PRECISE_SMC */
1018 /* we need to do that to handle the case where a signal
1019 occurs while doing tb_phys_invalidate() */
1020 saved_tb = NULL;
1021 if (env) {
1022 saved_tb = env->current_tb;
1023 env->current_tb = NULL;
1024 }
1025 tb_phys_invalidate(tb, -1);
1026 if (env) {
1027 env->current_tb = saved_tb;
1028 if (env->interrupt_request && env->current_tb)
1029 cpu_interrupt(env, env->interrupt_request);
1030 }
1031 }
1032 tb = tb_next;
1033 }
1034#if !defined(CONFIG_USER_ONLY)
1035 /* if no code remaining, no need to continue to use slow writes */
1036 if (!p->first_tb) {
1037 invalidate_page_bitmap(p);
1038 if (is_cpu_write_access) {
1039 tlb_unprotect_code_phys(env, start, env->mem_io_vaddr);
1040 }
1041 }
1042#endif
1043#ifdef TARGET_HAS_PRECISE_SMC
1044 if (current_tb_modified) {
1045 /* we generate a block containing just the instruction
1046 modifying the memory. It will ensure that it cannot modify
1047 itself */
1048 env->current_tb = NULL;
1049 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1050 cpu_resume_from_signal(env, NULL);
1051 }
1052#endif
1053}
1054
1055/* len must be <= 8 and start must be a multiple of len */
1056static inline void tb_invalidate_phys_page_fast(target_phys_addr_t start, int len)
1057{
1058 PageDesc *p;
1059 int offset, b;
1060#if 0
1061 if (1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001062 qemu_log("modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
1063 cpu_single_env->mem_io_vaddr, len,
1064 cpu_single_env->eip,
1065 cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001066 }
1067#endif
1068 p = page_find(start >> TARGET_PAGE_BITS);
1069 if (!p)
1070 return;
1071 if (p->code_bitmap) {
1072 offset = start & ~TARGET_PAGE_MASK;
1073 b = p->code_bitmap[offset >> 3] >> (offset & 7);
1074 if (b & ((1 << len) - 1))
1075 goto do_invalidate;
1076 } else {
1077 do_invalidate:
1078 tb_invalidate_phys_page_range(start, start + len, 1);
1079 }
1080}
1081
1082#if !defined(CONFIG_SOFTMMU)
1083static void tb_invalidate_phys_page(target_phys_addr_t addr,
1084 unsigned long pc, void *puc)
1085{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001086 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001087 PageDesc *p;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001088 int n;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001089#ifdef TARGET_HAS_PRECISE_SMC
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001090 TranslationBlock *current_tb = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001091 CPUState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001092 int current_tb_modified = 0;
1093 target_ulong current_pc = 0;
1094 target_ulong current_cs_base = 0;
1095 int current_flags = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001096#endif
1097
1098 addr &= TARGET_PAGE_MASK;
1099 p = page_find(addr >> TARGET_PAGE_BITS);
1100 if (!p)
1101 return;
1102 tb = p->first_tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001103#ifdef TARGET_HAS_PRECISE_SMC
1104 if (tb && pc != 0) {
1105 current_tb = tb_find_pc(pc);
1106 }
1107#endif
1108 while (tb != NULL) {
1109 n = (long)tb & 3;
1110 tb = (TranslationBlock *)((long)tb & ~3);
1111#ifdef TARGET_HAS_PRECISE_SMC
1112 if (current_tb == tb &&
1113 (current_tb->cflags & CF_COUNT_MASK) != 1) {
1114 /* If we are modifying the current TB, we must stop
1115 its execution. We could be more precise by checking
1116 that the modification is after the current PC, but it
1117 would require a specialized function to partially
1118 restore the CPU state */
1119
1120 current_tb_modified = 1;
1121 cpu_restore_state(current_tb, env, pc, puc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001122 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
1123 &current_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001124 }
1125#endif /* TARGET_HAS_PRECISE_SMC */
1126 tb_phys_invalidate(tb, addr);
1127 tb = tb->page_next[n];
1128 }
1129 p->first_tb = NULL;
1130#ifdef TARGET_HAS_PRECISE_SMC
1131 if (current_tb_modified) {
1132 /* we generate a block containing just the instruction
1133 modifying the memory. It will ensure that it cannot modify
1134 itself */
1135 env->current_tb = NULL;
1136 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1137 cpu_resume_from_signal(env, puc);
1138 }
1139#endif
1140}
1141#endif
1142
1143/* add the tb in the target page and protect it if necessary */
1144static inline void tb_alloc_page(TranslationBlock *tb,
1145 unsigned int n, target_ulong page_addr)
1146{
1147 PageDesc *p;
1148 TranslationBlock *last_first_tb;
1149
1150 tb->page_addr[n] = page_addr;
1151 p = page_find_alloc(page_addr >> TARGET_PAGE_BITS);
1152 tb->page_next[n] = p->first_tb;
1153 last_first_tb = p->first_tb;
1154 p->first_tb = (TranslationBlock *)((long)tb | n);
1155 invalidate_page_bitmap(p);
1156
1157#if defined(TARGET_HAS_SMC) || 1
1158
1159#if defined(CONFIG_USER_ONLY)
1160 if (p->flags & PAGE_WRITE) {
1161 target_ulong addr;
1162 PageDesc *p2;
1163 int prot;
1164
1165 /* force the host page as non writable (writes will have a
1166 page fault + mprotect overhead) */
1167 page_addr &= qemu_host_page_mask;
1168 prot = 0;
1169 for(addr = page_addr; addr < page_addr + qemu_host_page_size;
1170 addr += TARGET_PAGE_SIZE) {
1171
1172 p2 = page_find (addr >> TARGET_PAGE_BITS);
1173 if (!p2)
1174 continue;
1175 prot |= p2->flags;
1176 p2->flags &= ~PAGE_WRITE;
1177 page_get_flags(addr);
1178 }
1179 mprotect(g2h(page_addr), qemu_host_page_size,
1180 (prot & PAGE_BITS) & ~PAGE_WRITE);
1181#ifdef DEBUG_TB_INVALIDATE
1182 printf("protecting code page: 0x" TARGET_FMT_lx "\n",
1183 page_addr);
1184#endif
1185 }
1186#else
1187 /* if some code is already present, then the pages are already
1188 protected. So we handle the case where only the first TB is
1189 allocated in a physical page */
1190 if (!last_first_tb) {
1191 tlb_protect_code(page_addr);
1192 }
1193#endif
1194
1195#endif /* TARGET_HAS_SMC */
1196}
1197
1198/* Allocate a new translation block. Flush the translation buffer if
1199 too many translation blocks or too much generated code. */
1200TranslationBlock *tb_alloc(target_ulong pc)
1201{
1202 TranslationBlock *tb;
1203
1204 if (nb_tbs >= code_gen_max_blocks ||
1205 (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
1206 return NULL;
1207 tb = &tbs[nb_tbs++];
1208 tb->pc = pc;
1209 tb->cflags = 0;
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -08001210#ifdef CONFIG_MEMCHECK
1211 tb->tpc2gpc = NULL;
1212 tb->tpc2gpc_pairs = 0;
1213#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001214 return tb;
1215}
1216
1217void tb_free(TranslationBlock *tb)
1218{
1219 /* In practice this is mostly used for single use temporary TB
1220 Ignore the hard cases and just back up if this TB happens to
1221 be the last one generated. */
1222 if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) {
1223 code_gen_ptr = tb->tc_ptr;
1224 nb_tbs--;
1225 }
1226}
1227
1228/* add a new TB and link it to the physical page tables. phys_page2 is
1229 (-1) to indicate that only one page contains the TB. */
1230void tb_link_phys(TranslationBlock *tb,
1231 target_ulong phys_pc, target_ulong phys_page2)
1232{
1233 unsigned int h;
1234 TranslationBlock **ptb;
1235
1236 /* Grab the mmap lock to stop another thread invalidating this TB
1237 before we are done. */
1238 mmap_lock();
1239 /* add in the physical hash table */
1240 h = tb_phys_hash_func(phys_pc);
1241 ptb = &tb_phys_hash[h];
1242 tb->phys_hash_next = *ptb;
1243 *ptb = tb;
1244
1245 /* add in the page list */
1246 tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK);
1247 if (phys_page2 != -1)
1248 tb_alloc_page(tb, 1, phys_page2);
1249 else
1250 tb->page_addr[1] = -1;
1251
1252 tb->jmp_first = (TranslationBlock *)((long)tb | 2);
1253 tb->jmp_next[0] = NULL;
1254 tb->jmp_next[1] = NULL;
1255
1256 /* init original jump addresses */
1257 if (tb->tb_next_offset[0] != 0xffff)
1258 tb_reset_jump(tb, 0);
1259 if (tb->tb_next_offset[1] != 0xffff)
1260 tb_reset_jump(tb, 1);
1261
1262#ifdef DEBUG_TB_CHECK
1263 tb_page_check();
1264#endif
1265 mmap_unlock();
1266}
1267
1268/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
1269 tb[1].tc_ptr. Return NULL if not found */
1270TranslationBlock *tb_find_pc(unsigned long tc_ptr)
1271{
1272 int m_min, m_max, m;
1273 unsigned long v;
1274 TranslationBlock *tb;
1275
1276 if (nb_tbs <= 0)
1277 return NULL;
1278 if (tc_ptr < (unsigned long)code_gen_buffer ||
1279 tc_ptr >= (unsigned long)code_gen_ptr)
1280 return NULL;
1281 /* binary search (cf Knuth) */
1282 m_min = 0;
1283 m_max = nb_tbs - 1;
1284 while (m_min <= m_max) {
1285 m = (m_min + m_max) >> 1;
1286 tb = &tbs[m];
1287 v = (unsigned long)tb->tc_ptr;
1288 if (v == tc_ptr)
1289 return tb;
1290 else if (tc_ptr < v) {
1291 m_max = m - 1;
1292 } else {
1293 m_min = m + 1;
1294 }
1295 }
1296 return &tbs[m_max];
1297}
1298
1299static void tb_reset_jump_recursive(TranslationBlock *tb);
1300
1301static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
1302{
1303 TranslationBlock *tb1, *tb_next, **ptb;
1304 unsigned int n1;
1305
1306 tb1 = tb->jmp_next[n];
1307 if (tb1 != NULL) {
1308 /* find head of list */
1309 for(;;) {
1310 n1 = (long)tb1 & 3;
1311 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1312 if (n1 == 2)
1313 break;
1314 tb1 = tb1->jmp_next[n1];
1315 }
1316 /* we are now sure now that tb jumps to tb1 */
1317 tb_next = tb1;
1318
1319 /* remove tb from the jmp_first list */
1320 ptb = &tb_next->jmp_first;
1321 for(;;) {
1322 tb1 = *ptb;
1323 n1 = (long)tb1 & 3;
1324 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1325 if (n1 == n && tb1 == tb)
1326 break;
1327 ptb = &tb1->jmp_next[n1];
1328 }
1329 *ptb = tb->jmp_next[n];
1330 tb->jmp_next[n] = NULL;
1331
1332 /* suppress the jump to next tb in generated code */
1333 tb_reset_jump(tb, n);
1334
1335 /* suppress jumps in the tb on which we could have jumped */
1336 tb_reset_jump_recursive(tb_next);
1337 }
1338}
1339
1340static void tb_reset_jump_recursive(TranslationBlock *tb)
1341{
1342 tb_reset_jump_recursive2(tb, 0);
1343 tb_reset_jump_recursive2(tb, 1);
1344}
1345
1346#if defined(TARGET_HAS_ICE)
1347static void breakpoint_invalidate(CPUState *env, target_ulong pc)
1348{
1349 target_phys_addr_t addr;
1350 target_ulong pd;
1351 ram_addr_t ram_addr;
1352 PhysPageDesc *p;
1353
1354 addr = cpu_get_phys_page_debug(env, pc);
1355 p = phys_page_find(addr >> TARGET_PAGE_BITS);
1356 if (!p) {
1357 pd = IO_MEM_UNASSIGNED;
1358 } else {
1359 pd = p->phys_offset;
1360 }
1361 ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
1362 tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
1363}
1364#endif
1365
1366/* Add a watchpoint. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001367int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
1368 int flags, CPUWatchpoint **watchpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001369{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001370 target_ulong len_mask = ~(len - 1);
1371 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001372
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001373 /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
1374 if ((len != 1 && len != 2 && len != 4 && len != 8) || (addr & ~len_mask)) {
1375 fprintf(stderr, "qemu: tried to set invalid watchpoint at "
1376 TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
1377 return -EINVAL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001378 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001379 wp = qemu_malloc(sizeof(*wp));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001380
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001381 wp->vaddr = addr;
1382 wp->len_mask = len_mask;
1383 wp->flags = flags;
1384
1385 /* keep all GDB-injected watchpoints in front */
1386 if (flags & BP_GDB)
1387 TAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
1388 else
1389 TAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
1390
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001391 tlb_flush_page(env, addr);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001392
1393 if (watchpoint)
1394 *watchpoint = wp;
1395 return 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001396}
1397
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001398/* Remove a specific watchpoint. */
1399int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len,
1400 int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001401{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001402 target_ulong len_mask = ~(len - 1);
1403 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001404
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001405 TAILQ_FOREACH(wp, &env->watchpoints, entry) {
1406 if (addr == wp->vaddr && len_mask == wp->len_mask
1407 && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
1408 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001409 return 0;
1410 }
1411 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001412 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001413}
1414
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001415/* Remove a specific watchpoint by reference. */
1416void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint)
1417{
1418 TAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001419
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001420 tlb_flush_page(env, watchpoint->vaddr);
1421
1422 qemu_free(watchpoint);
1423}
1424
1425/* Remove all matching watchpoints. */
1426void cpu_watchpoint_remove_all(CPUState *env, int mask)
1427{
1428 CPUWatchpoint *wp, *next;
1429
1430 TAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
1431 if (wp->flags & mask)
1432 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001433 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001434}
1435
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001436/* Add a breakpoint. */
1437int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
1438 CPUBreakpoint **breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001439{
1440#if defined(TARGET_HAS_ICE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001441 CPUBreakpoint *bp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001442
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001443 bp = qemu_malloc(sizeof(*bp));
1444
1445 bp->pc = pc;
1446 bp->flags = flags;
1447
1448 /* keep all GDB-injected breakpoints in front */
1449 if (flags & BP_GDB)
1450 TAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
1451 else
1452 TAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
1453
1454 breakpoint_invalidate(env, pc);
1455
1456 if (breakpoint)
1457 *breakpoint = bp;
1458 return 0;
1459#else
1460 return -ENOSYS;
1461#endif
1462}
1463
1464/* Remove a specific breakpoint. */
1465int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags)
1466{
1467#if defined(TARGET_HAS_ICE)
1468 CPUBreakpoint *bp;
1469
1470 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
1471 if (bp->pc == pc && bp->flags == flags) {
1472 cpu_breakpoint_remove_by_ref(env, bp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001473 return 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001474 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001475 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001476 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001477#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001478 return -ENOSYS;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001479#endif
1480}
1481
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001482/* Remove a specific breakpoint by reference. */
1483void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001484{
1485#if defined(TARGET_HAS_ICE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001486 TAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001487
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001488 breakpoint_invalidate(env, breakpoint->pc);
1489
1490 qemu_free(breakpoint);
1491#endif
1492}
1493
1494/* Remove all matching breakpoints. */
1495void cpu_breakpoint_remove_all(CPUState *env, int mask)
1496{
1497#if defined(TARGET_HAS_ICE)
1498 CPUBreakpoint *bp, *next;
1499
1500 TAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
1501 if (bp->flags & mask)
1502 cpu_breakpoint_remove_by_ref(env, bp);
1503 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001504#endif
1505}
1506
1507/* enable or disable single step mode. EXCP_DEBUG is returned by the
1508 CPU loop after each instruction */
1509void cpu_single_step(CPUState *env, int enabled)
1510{
1511#if defined(TARGET_HAS_ICE)
1512 if (env->singlestep_enabled != enabled) {
1513 env->singlestep_enabled = enabled;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001514 if (kvm_enabled())
1515 kvm_update_guest_debug(env, 0);
1516 else {
1517 /* must flush all the translated code to avoid inconsistencies */
1518 /* XXX: only flush what is necessary */
1519 tb_flush(env);
1520 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001521 }
1522#endif
1523}
1524
1525/* enable or disable low levels log */
1526void cpu_set_log(int log_flags)
1527{
1528 loglevel = log_flags;
1529 if (loglevel && !logfile) {
1530 logfile = fopen(logfilename, log_append ? "a" : "w");
1531 if (!logfile) {
1532 perror(logfilename);
1533 _exit(1);
1534 }
1535#if !defined(CONFIG_SOFTMMU)
1536 /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1537 {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001538 static char logfile_buf[4096];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001539 setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1540 }
1541#else
1542 setvbuf(logfile, NULL, _IOLBF, 0);
1543#endif
1544 log_append = 1;
1545 }
1546 if (!loglevel && logfile) {
1547 fclose(logfile);
1548 logfile = NULL;
1549 }
1550}
1551
1552void cpu_set_log_filename(const char *filename)
1553{
1554 logfilename = strdup(filename);
1555 if (logfile) {
1556 fclose(logfile);
1557 logfile = NULL;
1558 }
1559 cpu_set_log(loglevel);
1560}
1561
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001562static void cpu_unlink_tb(CPUState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001563{
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001564#if defined(USE_NPTL)
1565 /* FIXME: TB unchaining isn't SMP safe. For now just ignore the
1566 problem and hope the cpu will stop of its own accord. For userspace
1567 emulation this often isn't actually as bad as it sounds. Often
1568 signals are used primarily to interrupt blocking syscalls. */
1569#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001570 TranslationBlock *tb;
1571 static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
1572
1573 tb = env->current_tb;
1574 /* if the cpu is currently executing code, we must unlink it and
1575 all the potentially executing TB */
1576 if (tb && !testandset(&interrupt_lock)) {
1577 env->current_tb = NULL;
1578 tb_reset_jump_recursive(tb);
1579 resetlock(&interrupt_lock);
1580 }
1581#endif
1582}
1583
1584/* mask must never be zero, except for A20 change call */
1585void cpu_interrupt(CPUState *env, int mask)
1586{
1587 int old_mask;
1588
1589 old_mask = env->interrupt_request;
1590 env->interrupt_request |= mask;
1591
1592#ifndef CONFIG_USER_ONLY
1593 /*
1594 * If called from iothread context, wake the target cpu in
1595 * case its halted.
1596 */
1597 if (!qemu_cpu_self(env)) {
1598 qemu_cpu_kick(env);
1599 return;
1600 }
1601#endif
1602
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001603 if (use_icount) {
1604 env->icount_decr.u16.high = 0xffff;
1605#ifndef CONFIG_USER_ONLY
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001606 if (!can_do_io(env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001607 && (mask & ~old_mask) != 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001608 cpu_abort(env, "Raised interrupt while not in I/O function");
1609 }
1610#endif
1611 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001612 cpu_unlink_tb(env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001613 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001614}
1615
1616void cpu_reset_interrupt(CPUState *env, int mask)
1617{
1618 env->interrupt_request &= ~mask;
1619}
1620
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001621void cpu_exit(CPUState *env)
1622{
1623 env->exit_request = 1;
1624 cpu_unlink_tb(env);
1625}
1626
1627const CPULogItem cpu_log_items[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001628 { CPU_LOG_TB_OUT_ASM, "out_asm",
1629 "show generated host assembly code for each compiled TB" },
1630 { CPU_LOG_TB_IN_ASM, "in_asm",
1631 "show target assembly code for each compiled TB" },
1632 { CPU_LOG_TB_OP, "op",
1633 "show micro ops for each compiled TB" },
1634 { CPU_LOG_TB_OP_OPT, "op_opt",
1635 "show micro ops "
1636#ifdef TARGET_I386
1637 "before eflags optimization and "
1638#endif
1639 "after liveness analysis" },
1640 { CPU_LOG_INT, "int",
1641 "show interrupts/exceptions in short format" },
1642 { CPU_LOG_EXEC, "exec",
1643 "show trace before each executed TB (lots of logs)" },
1644 { CPU_LOG_TB_CPU, "cpu",
1645 "show CPU state before block translation" },
1646#ifdef TARGET_I386
1647 { CPU_LOG_PCALL, "pcall",
1648 "show protected mode far calls/returns/exceptions" },
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001649 { CPU_LOG_RESET, "cpu_reset",
1650 "show CPU state before CPU resets" },
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001651#endif
1652#ifdef DEBUG_IOPORT
1653 { CPU_LOG_IOPORT, "ioport",
1654 "show all i/o ports accesses" },
1655#endif
1656 { 0, NULL, NULL },
1657};
1658
1659static int cmp1(const char *s1, int n, const char *s2)
1660{
1661 if (strlen(s2) != n)
1662 return 0;
1663 return memcmp(s1, s2, n) == 0;
1664}
1665
1666/* takes a comma separated list of log masks. Return 0 if error. */
1667int cpu_str_to_log_mask(const char *str)
1668{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001669 const CPULogItem *item;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001670 int mask;
1671 const char *p, *p1;
1672
1673 p = str;
1674 mask = 0;
1675 for(;;) {
1676 p1 = strchr(p, ',');
1677 if (!p1)
1678 p1 = p + strlen(p);
1679 if(cmp1(p,p1-p,"all")) {
1680 for(item = cpu_log_items; item->mask != 0; item++) {
1681 mask |= item->mask;
1682 }
1683 } else {
1684 for(item = cpu_log_items; item->mask != 0; item++) {
1685 if (cmp1(p, p1 - p, item->name))
1686 goto found;
1687 }
1688 return 0;
1689 }
1690 found:
1691 mask |= item->mask;
1692 if (*p1 != ',')
1693 break;
1694 p = p1 + 1;
1695 }
1696 return mask;
1697}
1698
1699void cpu_abort(CPUState *env, const char *fmt, ...)
1700{
1701 va_list ap;
1702 va_list ap2;
1703
1704 va_start(ap, fmt);
1705 va_copy(ap2, ap);
1706 fprintf(stderr, "qemu: fatal: ");
1707 vfprintf(stderr, fmt, ap);
1708 fprintf(stderr, "\n");
1709#ifdef TARGET_I386
1710 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1711#else
1712 cpu_dump_state(env, stderr, fprintf, 0);
1713#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001714 if (qemu_log_enabled()) {
1715 qemu_log("qemu: fatal: ");
1716 qemu_log_vprintf(fmt, ap2);
1717 qemu_log("\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001718#ifdef TARGET_I386
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001719 log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001720#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001721 log_cpu_state(env, 0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001722#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001723 qemu_log_flush();
1724 qemu_log_close();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001725 }
1726 va_end(ap2);
1727 va_end(ap);
1728 abort();
1729}
1730
1731CPUState *cpu_copy(CPUState *env)
1732{
1733 CPUState *new_env = cpu_init(env->cpu_model_str);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001734 CPUState *next_cpu = new_env->next_cpu;
1735 int cpu_index = new_env->cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001736#if defined(TARGET_HAS_ICE)
1737 CPUBreakpoint *bp;
1738 CPUWatchpoint *wp;
1739#endif
1740
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001741 memcpy(new_env, env, sizeof(CPUState));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001742
1743 /* Preserve chaining and index. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001744 new_env->next_cpu = next_cpu;
1745 new_env->cpu_index = cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001746
1747 /* Clone all break/watchpoints.
1748 Note: Once we support ptrace with hw-debug register access, make sure
1749 BP_CPU break/watchpoints are handled correctly on clone. */
1750 TAILQ_INIT(&env->breakpoints);
1751 TAILQ_INIT(&env->watchpoints);
1752#if defined(TARGET_HAS_ICE)
1753 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
1754 cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
1755 }
1756 TAILQ_FOREACH(wp, &env->watchpoints, entry) {
1757 cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
1758 wp->flags, NULL);
1759 }
1760#endif
1761
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001762 return new_env;
1763}
1764
1765#if !defined(CONFIG_USER_ONLY)
1766
1767static inline void tlb_flush_jmp_cache(CPUState *env, target_ulong addr)
1768{
1769 unsigned int i;
1770
1771 /* Discard jump cache entries for any tb which might potentially
1772 overlap the flushed page. */
1773 i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -08001774 memset (&env->tb_jmp_cache[i], 0,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001775 TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
1776
1777 i = tb_jmp_cache_hash_page(addr);
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -08001778 memset (&env->tb_jmp_cache[i], 0,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001779 TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
1780}
1781
1782/* NOTE: if flush_global is true, also flush global entries (not
1783 implemented yet) */
1784void tlb_flush(CPUState *env, int flush_global)
1785{
1786 int i;
1787
1788#if defined(DEBUG_TLB)
1789 printf("tlb_flush:\n");
1790#endif
1791 /* must reset current TB so that interrupts cannot modify the
1792 links while we are modifying them */
1793 env->current_tb = NULL;
1794
1795 for(i = 0; i < CPU_TLB_SIZE; i++) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001796 int mmu_idx;
1797 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1798 env->tlb_table[mmu_idx][i].addr_read = -1;
1799 env->tlb_table[mmu_idx][i].addr_write = -1;
1800 env->tlb_table[mmu_idx][i].addr_code = -1;
1801 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001802 }
1803
1804 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
1805
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001806#ifdef CONFIG_KQEMU
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001807 if (env->kqemu_enabled) {
1808 kqemu_flush(env, flush_global);
1809 }
1810#endif
1811 tlb_flush_count++;
1812}
1813
1814static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
1815{
1816 if (addr == (tlb_entry->addr_read &
1817 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1818 addr == (tlb_entry->addr_write &
1819 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1820 addr == (tlb_entry->addr_code &
1821 (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1822 tlb_entry->addr_read = -1;
1823 tlb_entry->addr_write = -1;
1824 tlb_entry->addr_code = -1;
1825 }
1826}
1827
1828void tlb_flush_page(CPUState *env, target_ulong addr)
1829{
1830 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001831 int mmu_idx;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001832
1833#if defined(DEBUG_TLB)
1834 printf("tlb_flush_page: " TARGET_FMT_lx "\n", addr);
1835#endif
1836 /* must reset current TB so that interrupts cannot modify the
1837 links while we are modifying them */
1838 env->current_tb = NULL;
1839
1840 addr &= TARGET_PAGE_MASK;
1841 i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001842 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++)
1843 tlb_flush_entry(&env->tlb_table[mmu_idx][i], addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001844
1845 tlb_flush_jmp_cache(env, addr);
1846
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001847#ifdef CONFIG_KQEMU
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001848 if (env->kqemu_enabled) {
1849 kqemu_flush_page(env, addr);
1850 }
1851#endif
1852}
1853
1854/* update the TLBs so that writes to code in the virtual page 'addr'
1855 can be detected */
1856static void tlb_protect_code(ram_addr_t ram_addr)
1857{
1858 cpu_physical_memory_reset_dirty(ram_addr,
1859 ram_addr + TARGET_PAGE_SIZE,
1860 CODE_DIRTY_FLAG);
1861}
1862
1863/* update the TLB so that writes in physical page 'phys_addr' are no longer
1864 tested for self modifying code */
1865static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
1866 target_ulong vaddr)
1867{
1868 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] |= CODE_DIRTY_FLAG;
1869}
1870
1871static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
1872 unsigned long start, unsigned long length)
1873{
1874 unsigned long addr;
1875 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1876 addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
1877 if ((addr - start) < length) {
1878 tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
1879 }
1880 }
1881}
1882
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001883/* Note: start and end must be within the same ram block. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001884void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
1885 int dirty_flags)
1886{
1887 CPUState *env;
1888 unsigned long length, start1;
1889 int i, mask, len;
1890 uint8_t *p;
1891
1892 start &= TARGET_PAGE_MASK;
1893 end = TARGET_PAGE_ALIGN(end);
1894
1895 length = end - start;
1896 if (length == 0)
1897 return;
1898 len = length >> TARGET_PAGE_BITS;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001899#ifdef CONFIG_KQEMU
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001900 /* XXX: should not depend on cpu context */
1901 env = first_cpu;
1902 if (env->kqemu_enabled) {
1903 ram_addr_t addr;
1904 addr = start;
1905 for(i = 0; i < len; i++) {
1906 kqemu_set_notdirty(env, addr);
1907 addr += TARGET_PAGE_SIZE;
1908 }
1909 }
1910#endif
1911 mask = ~dirty_flags;
1912 p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
1913 for(i = 0; i < len; i++)
1914 p[i] &= mask;
1915
1916 /* we modify the TLB cache so that the dirty bit will be set again
1917 when accessing the range */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001918 start1 = (unsigned long)qemu_get_ram_ptr(start);
1919 /* Chek that we don't span multiple blocks - this breaks the
1920 address comparisons below. */
1921 if ((unsigned long)qemu_get_ram_ptr(end - 1) - start1
1922 != (end - 1) - start) {
1923 abort();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001924 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001925
1926 for(env = first_cpu; env != NULL; env = env->next_cpu) {
1927 int mmu_idx;
1928 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1929 for(i = 0; i < CPU_TLB_SIZE; i++)
1930 tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
1931 start1, length);
1932 }
1933 }
1934}
1935
1936int cpu_physical_memory_set_dirty_tracking(int enable)
1937{
1938 in_migration = enable;
1939 if (kvm_enabled()) {
1940 return kvm_set_migration_log(enable);
1941 }
1942 return 0;
1943}
1944
1945int cpu_physical_memory_get_dirty_tracking(void)
1946{
1947 return in_migration;
1948}
1949
1950int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
1951 target_phys_addr_t end_addr)
1952{
1953 int ret = 0;
1954
1955 if (kvm_enabled())
1956 ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
1957 return ret;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001958}
1959
1960static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1961{
1962 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001963 void *p;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001964
1965 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001966 p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
1967 + tlb_entry->addend);
1968 ram_addr = qemu_ram_addr_from_host(p);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001969 if (!cpu_physical_memory_is_dirty(ram_addr)) {
1970 tlb_entry->addr_write |= TLB_NOTDIRTY;
1971 }
1972 }
1973}
1974
1975/* update the TLB according to the current state of the dirty bits */
1976void cpu_tlb_update_dirty(CPUState *env)
1977{
1978 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001979 int mmu_idx;
1980 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1981 for(i = 0; i < CPU_TLB_SIZE; i++)
1982 tlb_update_dirty(&env->tlb_table[mmu_idx][i]);
1983 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001984}
1985
1986static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, target_ulong vaddr)
1987{
1988 if (tlb_entry->addr_write == (vaddr | TLB_NOTDIRTY))
1989 tlb_entry->addr_write = vaddr;
1990}
1991
1992/* update the TLB corresponding to virtual page vaddr
1993 so that it is no longer dirty */
1994static inline void tlb_set_dirty(CPUState *env, target_ulong vaddr)
1995{
1996 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001997 int mmu_idx;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001998
1999 vaddr &= TARGET_PAGE_MASK;
2000 i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002001 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++)
2002 tlb_set_dirty1(&env->tlb_table[mmu_idx][i], vaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002003}
2004
2005/* add a new TLB entry. At most one entry for a given virtual address
2006 is permitted. Return 0 if OK or 2 if the page could not be mapped
2007 (can only happen in non SOFTMMU mode for I/O pages or pages
2008 conflicting with the host address space). */
2009int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
2010 target_phys_addr_t paddr, int prot,
2011 int mmu_idx, int is_softmmu)
2012{
2013 PhysPageDesc *p;
2014 unsigned long pd;
2015 unsigned int index;
2016 target_ulong address;
2017 target_ulong code_address;
2018 target_phys_addr_t addend;
2019 int ret;
2020 CPUTLBEntry *te;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002021 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002022 target_phys_addr_t iotlb;
2023
2024 p = phys_page_find(paddr >> TARGET_PAGE_BITS);
2025 if (!p) {
2026 pd = IO_MEM_UNASSIGNED;
2027 } else {
2028 pd = p->phys_offset;
2029 }
2030#if defined(DEBUG_TLB)
2031 printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x idx=%d smmu=%d pd=0x%08lx\n",
2032 vaddr, (int)paddr, prot, mmu_idx, is_softmmu, pd);
2033#endif
2034
2035 ret = 0;
2036 address = vaddr;
2037 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
2038 /* IO memory case (romd handled later) */
2039 address |= TLB_MMIO;
2040 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002041 addend = (unsigned long)qemu_get_ram_ptr(pd & TARGET_PAGE_MASK);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002042 if ((pd & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
2043 /* Normal RAM. */
2044 iotlb = pd & TARGET_PAGE_MASK;
2045 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM)
2046 iotlb |= IO_MEM_NOTDIRTY;
2047 else
2048 iotlb |= IO_MEM_ROM;
2049 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002050 /* IO handlers are currently passed a physical address.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002051 It would be nice to pass an offset from the base address
2052 of that region. This would avoid having to special case RAM,
2053 and avoid full address decoding in every device.
2054 We can't use the high bits of pd for this because
2055 IO_MEM_ROMD uses these as a ram address. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002056 iotlb = (pd & ~TARGET_PAGE_MASK);
2057 if (p) {
2058 iotlb += p->region_offset;
2059 } else {
2060 iotlb += paddr;
2061 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002062 }
2063
2064 code_address = address;
2065 /* Make accesses to pages with watchpoints go via the
2066 watchpoint trap routines. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002067 TAILQ_FOREACH(wp, &env->watchpoints, entry) {
2068 if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002069 iotlb = io_mem_watch + paddr;
2070 /* TODO: The memory case can be optimized by not trapping
2071 reads of pages with a write breakpoint. */
2072 address |= TLB_MMIO;
2073 }
2074 }
2075
2076 index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
2077 env->iotlb[mmu_idx][index] = iotlb - vaddr;
2078 te = &env->tlb_table[mmu_idx][index];
2079 te->addend = addend - vaddr;
2080 if (prot & PAGE_READ) {
2081 te->addr_read = address;
2082 } else {
2083 te->addr_read = -1;
2084 }
2085
2086 if (prot & PAGE_EXEC) {
2087 te->addr_code = code_address;
2088 } else {
2089 te->addr_code = -1;
2090 }
2091 if (prot & PAGE_WRITE) {
2092 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM ||
2093 (pd & IO_MEM_ROMD)) {
2094 /* Write access calls the I/O callback. */
2095 te->addr_write = address | TLB_MMIO;
2096 } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
2097 !cpu_physical_memory_is_dirty(pd)) {
2098 te->addr_write = address | TLB_NOTDIRTY;
2099 } else {
2100 te->addr_write = address;
2101 }
2102 } else {
2103 te->addr_write = -1;
2104 }
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -08002105
2106#ifdef CONFIG_MEMCHECK
2107 /*
2108 * If we have memchecker running, we need to make sure that page, cached
2109 * into TLB as the result of this operation will comply with our requirement
2110 * to cause __ld/__stx_mmu being called for memory access on the pages
2111 * containing memory blocks that require access violation checks.
2112 *
2113 * We need to check with memory checker if we should invalidate this page
2114 * iff:
2115 * - Memchecking is enabled.
2116 * - Page that's been cached belongs to the user space.
2117 * - Request to cache this page didn't come from softmmu. We're covered
2118 * there, because after page was cached here we will invalidate it in
2119 * the __ld/__stx_mmu wrapper.
2120 * - Cached page belongs to RAM, not I/O area.
2121 * - Page is cached for read, or write access.
2122 */
2123 if (memcheck_instrument_mmu && mmu_idx == 1 && !is_softmmu &&
2124 (pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
2125 (prot & (PAGE_READ | PAGE_WRITE)) &&
2126 memcheck_is_checked(vaddr & TARGET_PAGE_MASK, TARGET_PAGE_SIZE)) {
2127 if (prot & PAGE_READ) {
2128 te->addr_read ^= TARGET_PAGE_MASK;
2129 }
2130 if (prot & PAGE_WRITE) {
2131 te->addr_write ^= TARGET_PAGE_MASK;
2132 }
2133 }
2134#endif // CONFIG_MEMCHECK
2135
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002136 return ret;
2137}
2138
2139#else
2140
2141void tlb_flush(CPUState *env, int flush_global)
2142{
2143}
2144
2145void tlb_flush_page(CPUState *env, target_ulong addr)
2146{
2147}
2148
2149int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
2150 target_phys_addr_t paddr, int prot,
2151 int mmu_idx, int is_softmmu)
2152{
2153 return 0;
2154}
2155
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002156/*
2157 * Walks guest process memory "regions" one by one
2158 * and calls callback function 'fn' for each region.
2159 */
2160int walk_memory_regions(void *priv,
2161 int (*fn)(void *, unsigned long, unsigned long, unsigned long))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002162{
2163 unsigned long start, end;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002164 PageDesc *p = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002165 int i, j, prot, prot1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002166 int rc = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002167
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002168 start = end = -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002169 prot = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002170
2171 for (i = 0; i <= L1_SIZE; i++) {
2172 p = (i < L1_SIZE) ? l1_map[i] : NULL;
2173 for (j = 0; j < L2_SIZE; j++) {
2174 prot1 = (p == NULL) ? 0 : p[j].flags;
2175 /*
2176 * "region" is one continuous chunk of memory
2177 * that has same protection flags set.
2178 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002179 if (prot1 != prot) {
2180 end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
2181 if (start != -1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002182 rc = (*fn)(priv, start, end, prot);
2183 /* callback can stop iteration by returning != 0 */
2184 if (rc != 0)
2185 return (rc);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002186 }
2187 if (prot1 != 0)
2188 start = end;
2189 else
2190 start = -1;
2191 prot = prot1;
2192 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002193 if (p == NULL)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002194 break;
2195 }
2196 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002197 return (rc);
2198}
2199
2200static int dump_region(void *priv, unsigned long start,
2201 unsigned long end, unsigned long prot)
2202{
2203 FILE *f = (FILE *)priv;
2204
2205 (void) fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
2206 start, end, end - start,
2207 ((prot & PAGE_READ) ? 'r' : '-'),
2208 ((prot & PAGE_WRITE) ? 'w' : '-'),
2209 ((prot & PAGE_EXEC) ? 'x' : '-'));
2210
2211 return (0);
2212}
2213
2214/* dump memory mappings */
2215void page_dump(FILE *f)
2216{
2217 (void) fprintf(f, "%-8s %-8s %-8s %s\n",
2218 "start", "end", "size", "prot");
2219 walk_memory_regions(f, dump_region);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002220}
2221
2222int page_get_flags(target_ulong address)
2223{
2224 PageDesc *p;
2225
2226 p = page_find(address >> TARGET_PAGE_BITS);
2227 if (!p)
2228 return 0;
2229 return p->flags;
2230}
2231
2232/* modify the flags of a page and invalidate the code if
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002233 necessary. The flag PAGE_WRITE_ORG is positioned automatically
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002234 depending on PAGE_WRITE */
2235void page_set_flags(target_ulong start, target_ulong end, int flags)
2236{
2237 PageDesc *p;
2238 target_ulong addr;
2239
2240 /* mmap_lock should already be held. */
2241 start = start & TARGET_PAGE_MASK;
2242 end = TARGET_PAGE_ALIGN(end);
2243 if (flags & PAGE_WRITE)
2244 flags |= PAGE_WRITE_ORG;
2245 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2246 p = page_find_alloc(addr >> TARGET_PAGE_BITS);
2247 /* We may be called for host regions that are outside guest
2248 address space. */
2249 if (!p)
2250 return;
2251 /* if the write protection is set, then we invalidate the code
2252 inside */
2253 if (!(p->flags & PAGE_WRITE) &&
2254 (flags & PAGE_WRITE) &&
2255 p->first_tb) {
2256 tb_invalidate_phys_page(addr, 0, NULL);
2257 }
2258 p->flags = flags;
2259 }
2260}
2261
2262int page_check_range(target_ulong start, target_ulong len, int flags)
2263{
2264 PageDesc *p;
2265 target_ulong end;
2266 target_ulong addr;
2267
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002268 if (start + len < start)
2269 /* we've wrapped around */
2270 return -1;
2271
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002272 end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
2273 start = start & TARGET_PAGE_MASK;
2274
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002275 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2276 p = page_find(addr >> TARGET_PAGE_BITS);
2277 if( !p )
2278 return -1;
2279 if( !(p->flags & PAGE_VALID) )
2280 return -1;
2281
2282 if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
2283 return -1;
2284 if (flags & PAGE_WRITE) {
2285 if (!(p->flags & PAGE_WRITE_ORG))
2286 return -1;
2287 /* unprotect the page if it was put read-only because it
2288 contains translated code */
2289 if (!(p->flags & PAGE_WRITE)) {
2290 if (!page_unprotect(addr, 0, NULL))
2291 return -1;
2292 }
2293 return 0;
2294 }
2295 }
2296 return 0;
2297}
2298
2299/* called from signal handler: invalidate the code and unprotect the
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002300 page. Return TRUE if the fault was successfully handled. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002301int page_unprotect(target_ulong address, unsigned long pc, void *puc)
2302{
2303 unsigned int page_index, prot, pindex;
2304 PageDesc *p, *p1;
2305 target_ulong host_start, host_end, addr;
2306
2307 /* Technically this isn't safe inside a signal handler. However we
2308 know this only ever happens in a synchronous SEGV handler, so in
2309 practice it seems to be ok. */
2310 mmap_lock();
2311
2312 host_start = address & qemu_host_page_mask;
2313 page_index = host_start >> TARGET_PAGE_BITS;
2314 p1 = page_find(page_index);
2315 if (!p1) {
2316 mmap_unlock();
2317 return 0;
2318 }
2319 host_end = host_start + qemu_host_page_size;
2320 p = p1;
2321 prot = 0;
2322 for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
2323 prot |= p->flags;
2324 p++;
2325 }
2326 /* if the page was really writable, then we change its
2327 protection back to writable */
2328 if (prot & PAGE_WRITE_ORG) {
2329 pindex = (address - host_start) >> TARGET_PAGE_BITS;
2330 if (!(p1[pindex].flags & PAGE_WRITE)) {
2331 mprotect((void *)g2h(host_start), qemu_host_page_size,
2332 (prot & PAGE_BITS) | PAGE_WRITE);
2333 p1[pindex].flags |= PAGE_WRITE;
2334 /* and since the content will be modified, we must invalidate
2335 the corresponding translated code. */
2336 tb_invalidate_phys_page(address, pc, puc);
2337#ifdef DEBUG_TB_CHECK
2338 tb_invalidate_check(address);
2339#endif
2340 mmap_unlock();
2341 return 1;
2342 }
2343 }
2344 mmap_unlock();
2345 return 0;
2346}
2347
2348static inline void tlb_set_dirty(CPUState *env,
2349 unsigned long addr, target_ulong vaddr)
2350{
2351}
2352#endif /* defined(CONFIG_USER_ONLY) */
2353
2354#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002355
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002356static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002357 ram_addr_t memory, ram_addr_t region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002358static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002359 ram_addr_t orig_memory, ram_addr_t region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002360#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
2361 need_subpage) \
2362 do { \
2363 if (addr > start_addr) \
2364 start_addr2 = 0; \
2365 else { \
2366 start_addr2 = start_addr & ~TARGET_PAGE_MASK; \
2367 if (start_addr2 > 0) \
2368 need_subpage = 1; \
2369 } \
2370 \
2371 if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE) \
2372 end_addr2 = TARGET_PAGE_SIZE - 1; \
2373 else { \
2374 end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
2375 if (end_addr2 < TARGET_PAGE_SIZE - 1) \
2376 need_subpage = 1; \
2377 } \
2378 } while (0)
2379
2380/* register physical memory. 'size' must be a multiple of the target
2381 page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002382 io memory page. The address used when calling the IO function is
2383 the offset from the start of the region, plus region_offset. Both
2384 start_addr and region_offset are rounded down to a page boundary
2385 before calculating this offset. This should not be a problem unless
2386 the low bits of start_addr and region_offset differ. */
2387void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
2388 ram_addr_t size,
2389 ram_addr_t phys_offset,
2390 ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002391{
2392 target_phys_addr_t addr, end_addr;
2393 PhysPageDesc *p;
2394 CPUState *env;
2395 ram_addr_t orig_size = size;
2396 void *subpage;
2397
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002398#ifdef CONFIG_KQEMU
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002399 /* XXX: should not depend on cpu context */
2400 env = first_cpu;
2401 if (env->kqemu_enabled) {
2402 kqemu_set_phys_mem(start_addr, size, phys_offset);
2403 }
2404#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002405 if (kvm_enabled())
2406 kvm_set_phys_mem(start_addr, size, phys_offset);
2407
2408 if (phys_offset == IO_MEM_UNASSIGNED) {
2409 region_offset = start_addr;
2410 }
2411 region_offset &= TARGET_PAGE_MASK;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002412 size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
2413 end_addr = start_addr + (target_phys_addr_t)size;
2414 for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
2415 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2416 if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
2417 ram_addr_t orig_memory = p->phys_offset;
2418 target_phys_addr_t start_addr2, end_addr2;
2419 int need_subpage = 0;
2420
2421 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2422 need_subpage);
2423 if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
2424 if (!(orig_memory & IO_MEM_SUBPAGE)) {
2425 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002426 &p->phys_offset, orig_memory,
2427 p->region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002428 } else {
2429 subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
2430 >> IO_MEM_SHIFT];
2431 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002432 subpage_register(subpage, start_addr2, end_addr2, phys_offset,
2433 region_offset);
2434 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002435 } else {
2436 p->phys_offset = phys_offset;
2437 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2438 (phys_offset & IO_MEM_ROMD))
2439 phys_offset += TARGET_PAGE_SIZE;
2440 }
2441 } else {
2442 p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2443 p->phys_offset = phys_offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002444 p->region_offset = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002445 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002446 (phys_offset & IO_MEM_ROMD)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002447 phys_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002448 } else {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002449 target_phys_addr_t start_addr2, end_addr2;
2450 int need_subpage = 0;
2451
2452 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2453 end_addr2, need_subpage);
2454
2455 if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
2456 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002457 &p->phys_offset, IO_MEM_UNASSIGNED,
2458 addr & TARGET_PAGE_MASK);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002459 subpage_register(subpage, start_addr2, end_addr2,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002460 phys_offset, region_offset);
2461 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002462 }
2463 }
2464 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002465 region_offset += TARGET_PAGE_SIZE;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002466 }
2467
2468 /* since each CPU stores ram addresses in its TLB cache, we must
2469 reset the modified entries */
2470 /* XXX: slow ! */
2471 for(env = first_cpu; env != NULL; env = env->next_cpu) {
2472 tlb_flush(env, 1);
2473 }
2474}
2475
2476/* XXX: temporary until new memory mapping API */
2477ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr)
2478{
2479 PhysPageDesc *p;
2480
2481 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2482 if (!p)
2483 return IO_MEM_UNASSIGNED;
2484 return p->phys_offset;
2485}
2486
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002487void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
2488{
2489 if (kvm_enabled())
2490 kvm_coalesce_mmio_region(addr, size);
2491}
2492
2493void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
2494{
2495 if (kvm_enabled())
2496 kvm_uncoalesce_mmio_region(addr, size);
2497}
2498
2499#ifdef CONFIG_KQEMU
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002500/* XXX: better than nothing */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002501static ram_addr_t kqemu_ram_alloc(ram_addr_t size)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002502{
2503 ram_addr_t addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002504 if ((last_ram_offset + size) > kqemu_phys_ram_size) {
2505 fprintf(stderr, "Not enough memory (requested_size = %" PRIu64 ", max memory = %" PRIu64 ")\n",
2506 (uint64_t)size, (uint64_t)kqemu_phys_ram_size);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002507 abort();
2508 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002509 addr = last_ram_offset;
2510 last_ram_offset = TARGET_PAGE_ALIGN(last_ram_offset + size);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002511 return addr;
2512}
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002513#endif
2514
2515ram_addr_t qemu_ram_alloc(ram_addr_t size)
2516{
2517 RAMBlock *new_block;
2518
2519#ifdef CONFIG_KQEMU
2520 if (kqemu_phys_ram_base) {
2521 return kqemu_ram_alloc(size);
2522 }
2523#endif
2524
2525 size = TARGET_PAGE_ALIGN(size);
2526 new_block = qemu_malloc(sizeof(*new_block));
2527
2528 new_block->host = qemu_vmalloc(size);
2529 new_block->offset = last_ram_offset;
2530 new_block->length = size;
2531
2532 new_block->next = ram_blocks;
2533 ram_blocks = new_block;
2534
2535 phys_ram_dirty = qemu_realloc(phys_ram_dirty,
2536 (last_ram_offset + size) >> TARGET_PAGE_BITS);
2537 memset(phys_ram_dirty + (last_ram_offset >> TARGET_PAGE_BITS),
2538 0xff, size >> TARGET_PAGE_BITS);
2539
2540 last_ram_offset += size;
2541
2542 if (kvm_enabled())
2543 kvm_setup_guest_memory(new_block->host, size);
2544
2545 return new_block->offset;
2546}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002547
2548void qemu_ram_free(ram_addr_t addr)
2549{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002550 /* TODO: implement this. */
2551}
2552
2553/* Return a host pointer to ram allocated with qemu_ram_alloc.
2554 With the exception of the softmmu code in this file, this should
2555 only be used for local memory (e.g. video ram) that the device owns,
2556 and knows it isn't going to access beyond the end of the block.
2557
2558 It should not be used for general purpose DMA.
2559 Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
2560 */
2561void *qemu_get_ram_ptr(ram_addr_t addr)
2562{
2563 RAMBlock *prev;
2564 RAMBlock **prevp;
2565 RAMBlock *block;
2566
2567#ifdef CONFIG_KQEMU
2568 if (kqemu_phys_ram_base) {
2569 return kqemu_phys_ram_base + addr;
2570 }
2571#endif
2572
2573 prev = NULL;
2574 prevp = &ram_blocks;
2575 block = ram_blocks;
2576 while (block && (block->offset > addr
2577 || block->offset + block->length <= addr)) {
2578 if (prev)
2579 prevp = &prev->next;
2580 prev = block;
2581 block = block->next;
2582 }
2583 if (!block) {
2584 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2585 abort();
2586 }
2587 /* Move this entry to to start of the list. */
2588 if (prev) {
2589 prev->next = block->next;
2590 block->next = *prevp;
2591 *prevp = block;
2592 }
2593 return block->host + (addr - block->offset);
2594}
2595
2596/* Some of the softmmu routines need to translate from a host pointer
2597 (typically a TLB entry) back to a ram offset. */
2598ram_addr_t qemu_ram_addr_from_host(void *ptr)
2599{
2600 RAMBlock *prev;
2601 RAMBlock **prevp;
2602 RAMBlock *block;
2603 uint8_t *host = ptr;
2604
2605#ifdef CONFIG_KQEMU
2606 if (kqemu_phys_ram_base) {
2607 return host - kqemu_phys_ram_base;
2608 }
2609#endif
2610
2611 prev = NULL;
2612 prevp = &ram_blocks;
2613 block = ram_blocks;
2614 while (block && (block->host > host
2615 || block->host + block->length <= host)) {
2616 if (prev)
2617 prevp = &prev->next;
2618 prev = block;
2619 block = block->next;
2620 }
2621 if (!block) {
2622 fprintf(stderr, "Bad ram pointer %p\n", ptr);
2623 abort();
2624 }
2625 return block->offset + (host - block->host);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002626}
2627
2628static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
2629{
2630#ifdef DEBUG_UNASSIGNED
2631 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2632#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002633#if defined(TARGET_SPARC)
2634 do_unassigned_access(addr, 0, 0, 0, 1);
2635#endif
2636 return 0;
2637}
2638
2639static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr)
2640{
2641#ifdef DEBUG_UNASSIGNED
2642 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2643#endif
2644#if defined(TARGET_SPARC)
2645 do_unassigned_access(addr, 0, 0, 0, 2);
2646#endif
2647 return 0;
2648}
2649
2650static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr)
2651{
2652#ifdef DEBUG_UNASSIGNED
2653 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2654#endif
2655#if defined(TARGET_SPARC)
2656 do_unassigned_access(addr, 0, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002657#endif
2658 return 0;
2659}
2660
2661static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
2662{
2663#ifdef DEBUG_UNASSIGNED
2664 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2665#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002666#if defined(TARGET_SPARC)
2667 do_unassigned_access(addr, 1, 0, 0, 1);
2668#endif
2669}
2670
2671static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
2672{
2673#ifdef DEBUG_UNASSIGNED
2674 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2675#endif
2676#if defined(TARGET_SPARC)
2677 do_unassigned_access(addr, 1, 0, 0, 2);
2678#endif
2679}
2680
2681static void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
2682{
2683#ifdef DEBUG_UNASSIGNED
2684 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2685#endif
2686#if defined(TARGET_SPARC)
2687 do_unassigned_access(addr, 1, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002688#endif
2689}
2690
2691static CPUReadMemoryFunc *unassigned_mem_read[3] = {
2692 unassigned_mem_readb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002693 unassigned_mem_readw,
2694 unassigned_mem_readl,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002695};
2696
2697static CPUWriteMemoryFunc *unassigned_mem_write[3] = {
2698 unassigned_mem_writeb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002699 unassigned_mem_writew,
2700 unassigned_mem_writel,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002701};
2702
2703static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr,
2704 uint32_t val)
2705{
2706 int dirty_flags;
2707 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2708 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2709#if !defined(CONFIG_USER_ONLY)
2710 tb_invalidate_phys_page_fast(ram_addr, 1);
2711 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2712#endif
2713 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002714 stb_p(qemu_get_ram_ptr(ram_addr), val);
2715#ifdef CONFIG_KQEMU
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002716 if (cpu_single_env->kqemu_enabled &&
2717 (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2718 kqemu_modify_page(cpu_single_env, ram_addr);
2719#endif
2720 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2721 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2722 /* we remove the notdirty callback only if the code has been
2723 flushed */
2724 if (dirty_flags == 0xff)
2725 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2726}
2727
2728static void notdirty_mem_writew(void *opaque, target_phys_addr_t ram_addr,
2729 uint32_t val)
2730{
2731 int dirty_flags;
2732 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2733 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2734#if !defined(CONFIG_USER_ONLY)
2735 tb_invalidate_phys_page_fast(ram_addr, 2);
2736 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2737#endif
2738 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002739 stw_p(qemu_get_ram_ptr(ram_addr), val);
2740#ifdef CONFIG_KQEMU
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002741 if (cpu_single_env->kqemu_enabled &&
2742 (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2743 kqemu_modify_page(cpu_single_env, ram_addr);
2744#endif
2745 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2746 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2747 /* we remove the notdirty callback only if the code has been
2748 flushed */
2749 if (dirty_flags == 0xff)
2750 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2751}
2752
2753static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr,
2754 uint32_t val)
2755{
2756 int dirty_flags;
2757 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2758 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2759#if !defined(CONFIG_USER_ONLY)
2760 tb_invalidate_phys_page_fast(ram_addr, 4);
2761 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2762#endif
2763 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002764 stl_p(qemu_get_ram_ptr(ram_addr), val);
2765#ifdef CONFIG_KQEMU
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002766 if (cpu_single_env->kqemu_enabled &&
2767 (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2768 kqemu_modify_page(cpu_single_env, ram_addr);
2769#endif
2770 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2771 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2772 /* we remove the notdirty callback only if the code has been
2773 flushed */
2774 if (dirty_flags == 0xff)
2775 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2776}
2777
2778static CPUReadMemoryFunc *error_mem_read[3] = {
2779 NULL, /* never used */
2780 NULL, /* never used */
2781 NULL, /* never used */
2782};
2783
2784static CPUWriteMemoryFunc *notdirty_mem_write[3] = {
2785 notdirty_mem_writeb,
2786 notdirty_mem_writew,
2787 notdirty_mem_writel,
2788};
2789
2790/* Generate a debug exception if a watchpoint has been hit. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002791static void check_watchpoint(int offset, int len_mask, int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002792{
2793 CPUState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002794 target_ulong pc, cs_base;
2795 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002796 target_ulong vaddr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002797 CPUWatchpoint *wp;
2798 int cpu_flags;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002799
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002800 if (env->watchpoint_hit) {
2801 /* We re-entered the check after replacing the TB. Now raise
2802 * the debug interrupt so that is will trigger after the
2803 * current instruction. */
2804 cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2805 return;
2806 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002807 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002808 TAILQ_FOREACH(wp, &env->watchpoints, entry) {
2809 if ((vaddr == (wp->vaddr & len_mask) ||
2810 (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
2811 wp->flags |= BP_WATCHPOINT_HIT;
2812 if (!env->watchpoint_hit) {
2813 env->watchpoint_hit = wp;
2814 tb = tb_find_pc(env->mem_io_pc);
2815 if (!tb) {
2816 cpu_abort(env, "check_watchpoint: could not find TB for "
2817 "pc=%p", (void *)env->mem_io_pc);
2818 }
2819 cpu_restore_state(tb, env, env->mem_io_pc, NULL);
2820 tb_phys_invalidate(tb, -1);
2821 if (wp->flags & BP_STOP_BEFORE_ACCESS) {
2822 env->exception_index = EXCP_DEBUG;
2823 } else {
2824 cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
2825 tb_gen_code(env, pc, cs_base, cpu_flags, 1);
2826 }
2827 cpu_resume_from_signal(env, NULL);
2828 }
2829 } else {
2830 wp->flags &= ~BP_WATCHPOINT_HIT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002831 }
2832 }
2833}
2834
2835/* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
2836 so these check for a hit then pass through to the normal out-of-line
2837 phys routines. */
2838static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
2839{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002840 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002841 return ldub_phys(addr);
2842}
2843
2844static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
2845{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002846 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002847 return lduw_phys(addr);
2848}
2849
2850static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
2851{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002852 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002853 return ldl_phys(addr);
2854}
2855
2856static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
2857 uint32_t val)
2858{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002859 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002860 stb_phys(addr, val);
2861}
2862
2863static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
2864 uint32_t val)
2865{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002866 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002867 stw_phys(addr, val);
2868}
2869
2870static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
2871 uint32_t val)
2872{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002873 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002874 stl_phys(addr, val);
2875}
2876
2877static CPUReadMemoryFunc *watch_mem_read[3] = {
2878 watch_mem_readb,
2879 watch_mem_readw,
2880 watch_mem_readl,
2881};
2882
2883static CPUWriteMemoryFunc *watch_mem_write[3] = {
2884 watch_mem_writeb,
2885 watch_mem_writew,
2886 watch_mem_writel,
2887};
2888
2889static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr,
2890 unsigned int len)
2891{
2892 uint32_t ret;
2893 unsigned int idx;
2894
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002895 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002896#if defined(DEBUG_SUBPAGE)
2897 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
2898 mmio, len, addr, idx);
2899#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002900 ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len],
2901 addr + mmio->region_offset[idx][0][len]);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002902
2903 return ret;
2904}
2905
2906static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
2907 uint32_t value, unsigned int len)
2908{
2909 unsigned int idx;
2910
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002911 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002912#if defined(DEBUG_SUBPAGE)
2913 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
2914 mmio, len, addr, idx, value);
2915#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002916 (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len],
2917 addr + mmio->region_offset[idx][1][len],
2918 value);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002919}
2920
2921static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
2922{
2923#if defined(DEBUG_SUBPAGE)
2924 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2925#endif
2926
2927 return subpage_readlen(opaque, addr, 0);
2928}
2929
2930static void subpage_writeb (void *opaque, target_phys_addr_t addr,
2931 uint32_t value)
2932{
2933#if defined(DEBUG_SUBPAGE)
2934 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2935#endif
2936 subpage_writelen(opaque, addr, value, 0);
2937}
2938
2939static uint32_t subpage_readw (void *opaque, target_phys_addr_t addr)
2940{
2941#if defined(DEBUG_SUBPAGE)
2942 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2943#endif
2944
2945 return subpage_readlen(opaque, addr, 1);
2946}
2947
2948static void subpage_writew (void *opaque, target_phys_addr_t addr,
2949 uint32_t value)
2950{
2951#if defined(DEBUG_SUBPAGE)
2952 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2953#endif
2954 subpage_writelen(opaque, addr, value, 1);
2955}
2956
2957static uint32_t subpage_readl (void *opaque, target_phys_addr_t addr)
2958{
2959#if defined(DEBUG_SUBPAGE)
2960 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2961#endif
2962
2963 return subpage_readlen(opaque, addr, 2);
2964}
2965
2966static void subpage_writel (void *opaque,
2967 target_phys_addr_t addr, uint32_t value)
2968{
2969#if defined(DEBUG_SUBPAGE)
2970 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2971#endif
2972 subpage_writelen(opaque, addr, value, 2);
2973}
2974
2975static CPUReadMemoryFunc *subpage_read[] = {
2976 &subpage_readb,
2977 &subpage_readw,
2978 &subpage_readl,
2979};
2980
2981static CPUWriteMemoryFunc *subpage_write[] = {
2982 &subpage_writeb,
2983 &subpage_writew,
2984 &subpage_writel,
2985};
2986
2987static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002988 ram_addr_t memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002989{
2990 int idx, eidx;
2991 unsigned int i;
2992
2993 if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
2994 return -1;
2995 idx = SUBPAGE_IDX(start);
2996 eidx = SUBPAGE_IDX(end);
2997#if defined(DEBUG_SUBPAGE)
2998 printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %d\n", __func__,
2999 mmio, start, end, idx, eidx, memory);
3000#endif
3001 memory >>= IO_MEM_SHIFT;
3002 for (; idx <= eidx; idx++) {
3003 for (i = 0; i < 4; i++) {
3004 if (io_mem_read[memory][i]) {
3005 mmio->mem_read[idx][i] = &io_mem_read[memory][i];
3006 mmio->opaque[idx][0][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003007 mmio->region_offset[idx][0][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003008 }
3009 if (io_mem_write[memory][i]) {
3010 mmio->mem_write[idx][i] = &io_mem_write[memory][i];
3011 mmio->opaque[idx][1][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003012 mmio->region_offset[idx][1][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003013 }
3014 }
3015 }
3016
3017 return 0;
3018}
3019
3020static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003021 ram_addr_t orig_memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003022{
3023 subpage_t *mmio;
3024 int subpage_memory;
3025
3026 mmio = qemu_mallocz(sizeof(subpage_t));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003027
3028 mmio->base = base;
3029 subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003030#if defined(DEBUG_SUBPAGE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003031 printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
3032 mmio, base, TARGET_PAGE_SIZE, subpage_memory);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003033#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003034 *phys = subpage_memory | IO_MEM_SUBPAGE;
3035 subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
3036 region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003037
3038 return mmio;
3039}
3040
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003041static int get_free_io_mem_idx(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003042{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003043 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003044
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003045 for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
3046 if (!io_mem_used[i]) {
3047 io_mem_used[i] = 1;
3048 return i;
3049 }
3050
3051 return -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003052}
3053
3054/* mem_read and mem_write are arrays of functions containing the
3055 function to access byte (index 0), word (index 1) and dword (index
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003056 2). Functions can be omitted with a NULL function pointer.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003057 If io_index is non zero, the corresponding io zone is
3058 modified. If it is zero, a new io zone is allocated. The return
3059 value can be used with cpu_register_physical_memory(). (-1) is
3060 returned if error. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003061static int cpu_register_io_memory_fixed(int io_index,
3062 CPUReadMemoryFunc **mem_read,
3063 CPUWriteMemoryFunc **mem_write,
3064 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003065{
3066 int i, subwidth = 0;
3067
3068 if (io_index <= 0) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003069 io_index = get_free_io_mem_idx();
3070 if (io_index == -1)
3071 return io_index;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003072 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003073 io_index >>= IO_MEM_SHIFT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003074 if (io_index >= IO_MEM_NB_ENTRIES)
3075 return -1;
3076 }
3077
3078 for(i = 0;i < 3; i++) {
3079 if (!mem_read[i] || !mem_write[i])
3080 subwidth = IO_MEM_SUBWIDTH;
3081 io_mem_read[io_index][i] = mem_read[i];
3082 io_mem_write[io_index][i] = mem_write[i];
3083 }
3084 io_mem_opaque[io_index] = opaque;
3085 return (io_index << IO_MEM_SHIFT) | subwidth;
3086}
3087
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003088int cpu_register_io_memory(CPUReadMemoryFunc **mem_read,
3089 CPUWriteMemoryFunc **mem_write,
3090 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003091{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003092 return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003093}
3094
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003095void cpu_unregister_io_memory(int io_table_address)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003096{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003097 int i;
3098 int io_index = io_table_address >> IO_MEM_SHIFT;
3099
3100 for (i=0;i < 3; i++) {
3101 io_mem_read[io_index][i] = unassigned_mem_read[i];
3102 io_mem_write[io_index][i] = unassigned_mem_write[i];
3103 }
3104 io_mem_opaque[io_index] = NULL;
3105 io_mem_used[io_index] = 0;
3106}
3107
3108static void io_mem_init(void)
3109{
3110 int i;
3111
3112 cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read, unassigned_mem_write, NULL);
3113 cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read, unassigned_mem_write, NULL);
3114 cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read, notdirty_mem_write, NULL);
3115 for (i=0; i<5; i++)
3116 io_mem_used[i] = 1;
3117
3118 io_mem_watch = cpu_register_io_memory(watch_mem_read,
3119 watch_mem_write, NULL);
3120#ifdef CONFIG_KQEMU
3121 if (kqemu_phys_ram_base) {
3122 /* alloc dirty bits array */
3123 phys_ram_dirty = qemu_vmalloc(kqemu_phys_ram_size >> TARGET_PAGE_BITS);
3124 memset(phys_ram_dirty, 0xff, kqemu_phys_ram_size >> TARGET_PAGE_BITS);
3125 }
3126#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003127}
3128
3129#endif /* !defined(CONFIG_USER_ONLY) */
3130
3131/* physical memory access (slow version, mainly for debug) */
3132#if defined(CONFIG_USER_ONLY)
3133void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
3134 int len, int is_write)
3135{
3136 int l, flags;
3137 target_ulong page;
3138 void * p;
3139
3140 while (len > 0) {
3141 page = addr & TARGET_PAGE_MASK;
3142 l = (page + TARGET_PAGE_SIZE) - addr;
3143 if (l > len)
3144 l = len;
3145 flags = page_get_flags(page);
3146 if (!(flags & PAGE_VALID))
3147 return;
3148 if (is_write) {
3149 if (!(flags & PAGE_WRITE))
3150 return;
3151 /* XXX: this code should not depend on lock_user */
3152 if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
3153 /* FIXME - should this return an error rather than just fail? */
3154 return;
3155 memcpy(p, buf, l);
3156 unlock_user(p, addr, l);
3157 } else {
3158 if (!(flags & PAGE_READ))
3159 return;
3160 /* XXX: this code should not depend on lock_user */
3161 if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
3162 /* FIXME - should this return an error rather than just fail? */
3163 return;
3164 memcpy(buf, p, l);
3165 unlock_user(p, addr, 0);
3166 }
3167 len -= l;
3168 buf += l;
3169 addr += l;
3170 }
3171}
3172
3173#else
3174void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
3175 int len, int is_write)
3176{
3177 int l, io_index;
3178 uint8_t *ptr;
3179 uint32_t val;
3180 target_phys_addr_t page;
3181 unsigned long pd;
3182 PhysPageDesc *p;
3183
3184 while (len > 0) {
3185 page = addr & TARGET_PAGE_MASK;
3186 l = (page + TARGET_PAGE_SIZE) - addr;
3187 if (l > len)
3188 l = len;
3189 p = phys_page_find(page >> TARGET_PAGE_BITS);
3190 if (!p) {
3191 pd = IO_MEM_UNASSIGNED;
3192 } else {
3193 pd = p->phys_offset;
3194 }
3195
3196 if (is_write) {
3197 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003198 target_phys_addr_t addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003199 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003200 if (p)
3201 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003202 /* XXX: could force cpu_single_env to NULL to avoid
3203 potential bugs */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003204 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003205 /* 32 bit write access */
3206 val = ldl_p(buf);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003207 io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003208 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003209 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003210 /* 16 bit write access */
3211 val = lduw_p(buf);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003212 io_mem_write[io_index][1](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003213 l = 2;
3214 } else {
3215 /* 8 bit write access */
3216 val = ldub_p(buf);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003217 io_mem_write[io_index][0](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003218 l = 1;
3219 }
3220 } else {
3221 unsigned long addr1;
3222 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3223 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003224 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003225 memcpy(ptr, buf, l);
3226 if (!cpu_physical_memory_is_dirty(addr1)) {
3227 /* invalidate code */
3228 tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
3229 /* set dirty bit */
3230 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3231 (0xff & ~CODE_DIRTY_FLAG);
3232 }
3233 }
3234 } else {
3235 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3236 !(pd & IO_MEM_ROMD)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003237 target_phys_addr_t addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003238 /* I/O case */
3239 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003240 if (p)
3241 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3242 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003243 /* 32 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003244 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003245 stl_p(buf, val);
3246 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003247 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003248 /* 16 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003249 val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003250 stw_p(buf, val);
3251 l = 2;
3252 } else {
3253 /* 8 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003254 val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003255 stb_p(buf, val);
3256 l = 1;
3257 }
3258 } else {
3259 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003260 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003261 (addr & ~TARGET_PAGE_MASK);
3262 memcpy(buf, ptr, l);
3263 }
3264 }
3265 len -= l;
3266 buf += l;
3267 addr += l;
3268 }
3269}
3270
3271/* used for ROM loading : can write in RAM and ROM */
3272void cpu_physical_memory_write_rom(target_phys_addr_t addr,
3273 const uint8_t *buf, int len)
3274{
3275 int l;
3276 uint8_t *ptr;
3277 target_phys_addr_t page;
3278 unsigned long pd;
3279 PhysPageDesc *p;
3280
3281 while (len > 0) {
3282 page = addr & TARGET_PAGE_MASK;
3283 l = (page + TARGET_PAGE_SIZE) - addr;
3284 if (l > len)
3285 l = len;
3286 p = phys_page_find(page >> TARGET_PAGE_BITS);
3287 if (!p) {
3288 pd = IO_MEM_UNASSIGNED;
3289 } else {
3290 pd = p->phys_offset;
3291 }
3292
3293 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
3294 (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
3295 !(pd & IO_MEM_ROMD)) {
3296 /* do nothing */
3297 } else {
3298 unsigned long addr1;
3299 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3300 /* ROM/RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003301 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003302 memcpy(ptr, buf, l);
3303 }
3304 len -= l;
3305 buf += l;
3306 addr += l;
3307 }
3308}
3309
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003310typedef struct {
3311 void *buffer;
3312 target_phys_addr_t addr;
3313 target_phys_addr_t len;
3314} BounceBuffer;
3315
3316static BounceBuffer bounce;
3317
3318typedef struct MapClient {
3319 void *opaque;
3320 void (*callback)(void *opaque);
3321 LIST_ENTRY(MapClient) link;
3322} MapClient;
3323
3324static LIST_HEAD(map_client_list, MapClient) map_client_list
3325 = LIST_HEAD_INITIALIZER(map_client_list);
3326
3327void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
3328{
3329 MapClient *client = qemu_malloc(sizeof(*client));
3330
3331 client->opaque = opaque;
3332 client->callback = callback;
3333 LIST_INSERT_HEAD(&map_client_list, client, link);
3334 return client;
3335}
3336
3337void cpu_unregister_map_client(void *_client)
3338{
3339 MapClient *client = (MapClient *)_client;
3340
3341 LIST_REMOVE(client, link);
3342}
3343
3344static void cpu_notify_map_clients(void)
3345{
3346 MapClient *client;
3347
3348 while (!LIST_EMPTY(&map_client_list)) {
3349 client = LIST_FIRST(&map_client_list);
3350 client->callback(client->opaque);
3351 LIST_REMOVE(client, link);
3352 }
3353}
3354
3355/* Map a physical memory region into a host virtual address.
3356 * May map a subset of the requested range, given by and returned in *plen.
3357 * May return NULL if resources needed to perform the mapping are exhausted.
3358 * Use only for reads OR writes - not for read-modify-write operations.
3359 * Use cpu_register_map_client() to know when retrying the map operation is
3360 * likely to succeed.
3361 */
3362void *cpu_physical_memory_map(target_phys_addr_t addr,
3363 target_phys_addr_t *plen,
3364 int is_write)
3365{
3366 target_phys_addr_t len = *plen;
3367 target_phys_addr_t done = 0;
3368 int l;
3369 uint8_t *ret = NULL;
3370 uint8_t *ptr;
3371 target_phys_addr_t page;
3372 unsigned long pd;
3373 PhysPageDesc *p;
3374 unsigned long addr1;
3375
3376 while (len > 0) {
3377 page = addr & TARGET_PAGE_MASK;
3378 l = (page + TARGET_PAGE_SIZE) - addr;
3379 if (l > len)
3380 l = len;
3381 p = phys_page_find(page >> TARGET_PAGE_BITS);
3382 if (!p) {
3383 pd = IO_MEM_UNASSIGNED;
3384 } else {
3385 pd = p->phys_offset;
3386 }
3387
3388 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3389 if (done || bounce.buffer) {
3390 break;
3391 }
3392 bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
3393 bounce.addr = addr;
3394 bounce.len = l;
3395 if (!is_write) {
3396 cpu_physical_memory_rw(addr, bounce.buffer, l, 0);
3397 }
3398 ptr = bounce.buffer;
3399 } else {
3400 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3401 ptr = qemu_get_ram_ptr(addr1);
3402 }
3403 if (!done) {
3404 ret = ptr;
3405 } else if (ret + done != ptr) {
3406 break;
3407 }
3408
3409 len -= l;
3410 addr += l;
3411 done += l;
3412 }
3413 *plen = done;
3414 return ret;
3415}
3416
3417/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
3418 * Will also mark the memory as dirty if is_write == 1. access_len gives
3419 * the amount of memory that was actually read or written by the caller.
3420 */
3421void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
3422 int is_write, target_phys_addr_t access_len)
3423{
3424 if (buffer != bounce.buffer) {
3425 if (is_write) {
3426 ram_addr_t addr1 = qemu_ram_addr_from_host(buffer);
3427 while (access_len) {
3428 unsigned l;
3429 l = TARGET_PAGE_SIZE;
3430 if (l > access_len)
3431 l = access_len;
3432 if (!cpu_physical_memory_is_dirty(addr1)) {
3433 /* invalidate code */
3434 tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
3435 /* set dirty bit */
3436 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3437 (0xff & ~CODE_DIRTY_FLAG);
3438 }
3439 addr1 += l;
3440 access_len -= l;
3441 }
3442 }
3443 return;
3444 }
3445 if (is_write) {
3446 cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
3447 }
3448 qemu_free(bounce.buffer);
3449 bounce.buffer = NULL;
3450 cpu_notify_map_clients();
3451}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003452
3453/* warning: addr must be aligned */
3454uint32_t ldl_phys(target_phys_addr_t addr)
3455{
3456 int io_index;
3457 uint8_t *ptr;
3458 uint32_t val;
3459 unsigned long pd;
3460 PhysPageDesc *p;
3461
3462 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3463 if (!p) {
3464 pd = IO_MEM_UNASSIGNED;
3465 } else {
3466 pd = p->phys_offset;
3467 }
3468
3469 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3470 !(pd & IO_MEM_ROMD)) {
3471 /* I/O case */
3472 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003473 if (p)
3474 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003475 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3476 } else {
3477 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003478 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003479 (addr & ~TARGET_PAGE_MASK);
3480 val = ldl_p(ptr);
3481 }
3482 return val;
3483}
3484
3485/* warning: addr must be aligned */
3486uint64_t ldq_phys(target_phys_addr_t addr)
3487{
3488 int io_index;
3489 uint8_t *ptr;
3490 uint64_t val;
3491 unsigned long pd;
3492 PhysPageDesc *p;
3493
3494 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3495 if (!p) {
3496 pd = IO_MEM_UNASSIGNED;
3497 } else {
3498 pd = p->phys_offset;
3499 }
3500
3501 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3502 !(pd & IO_MEM_ROMD)) {
3503 /* I/O case */
3504 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003505 if (p)
3506 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003507#ifdef TARGET_WORDS_BIGENDIAN
3508 val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
3509 val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
3510#else
3511 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3512 val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
3513#endif
3514 } else {
3515 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003516 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003517 (addr & ~TARGET_PAGE_MASK);
3518 val = ldq_p(ptr);
3519 }
3520 return val;
3521}
3522
3523/* XXX: optimize */
3524uint32_t ldub_phys(target_phys_addr_t addr)
3525{
3526 uint8_t val;
3527 cpu_physical_memory_read(addr, &val, 1);
3528 return val;
3529}
3530
3531/* XXX: optimize */
3532uint32_t lduw_phys(target_phys_addr_t addr)
3533{
3534 uint16_t val;
3535 cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
3536 return tswap16(val);
3537}
3538
3539/* warning: addr must be aligned. The ram page is not masked as dirty
3540 and the code inside is not invalidated. It is useful if the dirty
3541 bits are used to track modified PTEs */
3542void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
3543{
3544 int io_index;
3545 uint8_t *ptr;
3546 unsigned long pd;
3547 PhysPageDesc *p;
3548
3549 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3550 if (!p) {
3551 pd = IO_MEM_UNASSIGNED;
3552 } else {
3553 pd = p->phys_offset;
3554 }
3555
3556 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3557 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003558 if (p)
3559 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003560 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3561 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003562 unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3563 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003564 stl_p(ptr, val);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003565
3566 if (unlikely(in_migration)) {
3567 if (!cpu_physical_memory_is_dirty(addr1)) {
3568 /* invalidate code */
3569 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3570 /* set dirty bit */
3571 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3572 (0xff & ~CODE_DIRTY_FLAG);
3573 }
3574 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003575 }
3576}
3577
3578void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
3579{
3580 int io_index;
3581 uint8_t *ptr;
3582 unsigned long pd;
3583 PhysPageDesc *p;
3584
3585 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3586 if (!p) {
3587 pd = IO_MEM_UNASSIGNED;
3588 } else {
3589 pd = p->phys_offset;
3590 }
3591
3592 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3593 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003594 if (p)
3595 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003596#ifdef TARGET_WORDS_BIGENDIAN
3597 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
3598 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
3599#else
3600 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3601 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
3602#endif
3603 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003604 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003605 (addr & ~TARGET_PAGE_MASK);
3606 stq_p(ptr, val);
3607 }
3608}
3609
3610/* warning: addr must be aligned */
3611void stl_phys(target_phys_addr_t addr, uint32_t val)
3612{
3613 int io_index;
3614 uint8_t *ptr;
3615 unsigned long pd;
3616 PhysPageDesc *p;
3617
3618 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3619 if (!p) {
3620 pd = IO_MEM_UNASSIGNED;
3621 } else {
3622 pd = p->phys_offset;
3623 }
3624
3625 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3626 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003627 if (p)
3628 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003629 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3630 } else {
3631 unsigned long addr1;
3632 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3633 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003634 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003635 stl_p(ptr, val);
3636 if (!cpu_physical_memory_is_dirty(addr1)) {
3637 /* invalidate code */
3638 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3639 /* set dirty bit */
3640 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3641 (0xff & ~CODE_DIRTY_FLAG);
3642 }
3643 }
3644}
3645
3646/* XXX: optimize */
3647void stb_phys(target_phys_addr_t addr, uint32_t val)
3648{
3649 uint8_t v = val;
3650 cpu_physical_memory_write(addr, &v, 1);
3651}
3652
3653/* XXX: optimize */
3654void stw_phys(target_phys_addr_t addr, uint32_t val)
3655{
3656 uint16_t v = tswap16(val);
3657 cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
3658}
3659
3660/* XXX: optimize */
3661void stq_phys(target_phys_addr_t addr, uint64_t val)
3662{
3663 val = tswap64(val);
3664 cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
3665}
3666
3667#endif
3668
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003669/* virtual memory access for debug (includes writing to ROM) */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003670int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
3671 uint8_t *buf, int len, int is_write)
3672{
3673 int l;
3674 target_phys_addr_t phys_addr;
3675 target_ulong page;
3676
3677 while (len > 0) {
3678 page = addr & TARGET_PAGE_MASK;
3679 phys_addr = cpu_get_phys_page_debug(env, page);
3680 /* if no physical page mapped, return an error */
3681 if (phys_addr == -1)
3682 return -1;
3683 l = (page + TARGET_PAGE_SIZE) - addr;
3684 if (l > len)
3685 l = len;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003686 phys_addr += (addr & ~TARGET_PAGE_MASK);
3687#if !defined(CONFIG_USER_ONLY)
3688 if (is_write)
3689 cpu_physical_memory_write_rom(phys_addr, buf, l);
3690 else
3691#endif
3692 cpu_physical_memory_rw(phys_addr, buf, l, is_write);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003693 len -= l;
3694 buf += l;
3695 addr += l;
3696 }
3697 return 0;
3698}
3699
3700/* in deterministic execution mode, instructions doing device I/Os
3701 must be at the end of the TB */
3702void cpu_io_recompile(CPUState *env, void *retaddr)
3703{
3704 TranslationBlock *tb;
3705 uint32_t n, cflags;
3706 target_ulong pc, cs_base;
3707 uint64_t flags;
3708
3709 tb = tb_find_pc((unsigned long)retaddr);
3710 if (!tb) {
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -08003711 cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003712 retaddr);
3713 }
3714 n = env->icount_decr.u16.low + tb->icount;
3715 cpu_restore_state(tb, env, (unsigned long)retaddr, NULL);
3716 /* Calculate how many instructions had been executed before the fault
3717 occurred. */
3718 n = n - env->icount_decr.u16.low;
3719 /* Generate a new TB ending on the I/O insn. */
3720 n++;
3721 /* On MIPS and SH, delay slot instructions can only be restarted if
3722 they were already the first instruction in the TB. If this is not
3723 the first instruction in a TB then re-execute the preceding
3724 branch. */
3725#if defined(TARGET_MIPS)
3726 if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) {
3727 env->active_tc.PC -= 4;
3728 env->icount_decr.u16.low++;
3729 env->hflags &= ~MIPS_HFLAG_BMASK;
3730 }
3731#elif defined(TARGET_SH4)
3732 if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
3733 && n > 1) {
3734 env->pc -= 2;
3735 env->icount_decr.u16.low++;
3736 env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
3737 }
3738#endif
3739 /* This should never happen. */
3740 if (n > CF_COUNT_MASK)
3741 cpu_abort(env, "TB too big during recompile");
3742
3743 cflags = n | CF_LAST_IO;
3744 pc = tb->pc;
3745 cs_base = tb->cs_base;
3746 flags = tb->flags;
3747 tb_phys_invalidate(tb, -1);
3748 /* FIXME: In theory this could raise an exception. In practice
3749 we have already translated the block once so it's probably ok. */
3750 tb_gen_code(env, pc, cs_base, flags, cflags);
3751 /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
3752 the first in the TB) then we end up generating a whole new TB and
3753 repeating the fault, which is horribly inefficient.
3754 Better would be to execute just this insn uncached, or generate a
3755 second new TB. */
3756 cpu_resume_from_signal(env, NULL);
3757}
3758
3759void dump_exec_info(FILE *f,
3760 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
3761{
3762 int i, target_code_size, max_target_code_size;
3763 int direct_jmp_count, direct_jmp2_count, cross_page;
3764 TranslationBlock *tb;
3765
3766 target_code_size = 0;
3767 max_target_code_size = 0;
3768 cross_page = 0;
3769 direct_jmp_count = 0;
3770 direct_jmp2_count = 0;
3771 for(i = 0; i < nb_tbs; i++) {
3772 tb = &tbs[i];
3773 target_code_size += tb->size;
3774 if (tb->size > max_target_code_size)
3775 max_target_code_size = tb->size;
3776 if (tb->page_addr[1] != -1)
3777 cross_page++;
3778 if (tb->tb_next_offset[0] != 0xffff) {
3779 direct_jmp_count++;
3780 if (tb->tb_next_offset[1] != 0xffff) {
3781 direct_jmp2_count++;
3782 }
3783 }
3784 }
3785 /* XXX: avoid using doubles ? */
3786 cpu_fprintf(f, "Translation buffer state:\n");
3787 cpu_fprintf(f, "gen code size %ld/%ld\n",
3788 code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size);
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -08003789 cpu_fprintf(f, "TB count %d/%d\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003790 nb_tbs, code_gen_max_blocks);
3791 cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
3792 nb_tbs ? target_code_size / nb_tbs : 0,
3793 max_target_code_size);
3794 cpu_fprintf(f, "TB avg host size %d bytes (expansion ratio: %0.1f)\n",
3795 nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
3796 target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
3797 cpu_fprintf(f, "cross page TB count %d (%d%%)\n",
3798 cross_page,
3799 nb_tbs ? (cross_page * 100) / nb_tbs : 0);
3800 cpu_fprintf(f, "direct jump count %d (%d%%) (2 jumps=%d %d%%)\n",
3801 direct_jmp_count,
3802 nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
3803 direct_jmp2_count,
3804 nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
3805 cpu_fprintf(f, "\nStatistics:\n");
3806 cpu_fprintf(f, "TB flush count %d\n", tb_flush_count);
3807 cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
3808 cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count);
3809 tcg_dump_info(f, cpu_fprintf);
3810}
3811
3812#if !defined(CONFIG_USER_ONLY)
3813
3814#define MMUSUFFIX _cmmu
3815#define GETPC() NULL
3816#define env cpu_single_env
3817#define SOFTMMU_CODE_ACCESS
3818
3819#define SHIFT 0
3820#include "softmmu_template.h"
3821
3822#define SHIFT 1
3823#include "softmmu_template.h"
3824
3825#define SHIFT 2
3826#include "softmmu_template.h"
3827
3828#define SHIFT 3
3829#include "softmmu_template.h"
3830
3831#undef env
3832
3833#endif