blob: 003a4ccc074b20fc4e703e00013a7044b8bc3aa2 [file] [log] [blame]
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001/*
2 * virtual page mapping and translated block handling
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070017 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080018 */
19#include "config.h"
20#ifdef _WIN32
21#define WIN32_LEAN_AND_MEAN
22#include <windows.h>
23#else
24#include <sys/types.h>
25#include <sys/mman.h>
26#endif
27#include <stdlib.h>
28#include <stdio.h>
29#include <stdarg.h>
30#include <string.h>
31#include <errno.h>
32#include <unistd.h>
33#include <inttypes.h>
34
35#include "cpu.h"
36#include "exec-all.h"
37#include "qemu-common.h"
38#include "tcg.h"
39#include "hw/hw.h"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070040#include "osdep.h"
41#include "kvm.h"
David Turner6a9ef172010-09-09 22:54:36 +020042#include "qemu-timer.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080043#if defined(CONFIG_USER_ONLY)
44#include <qemu.h>
45#endif
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -080046#ifdef CONFIG_MEMCHECK
47#include "memcheck/memcheck_api.h"
48#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080049
50//#define DEBUG_TB_INVALIDATE
51//#define DEBUG_FLUSH
52//#define DEBUG_TLB
53//#define DEBUG_UNASSIGNED
54
55/* make various TB consistency checks */
56//#define DEBUG_TB_CHECK
57//#define DEBUG_TLB_CHECK
58
59//#define DEBUG_IOPORT
60//#define DEBUG_SUBPAGE
61
62#if !defined(CONFIG_USER_ONLY)
63/* TB consistency checks only implemented for usermode emulation. */
64#undef DEBUG_TB_CHECK
65#endif
66
67#define SMC_BITMAP_USE_THRESHOLD 10
68
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080069#if defined(TARGET_SPARC64)
70#define TARGET_PHYS_ADDR_SPACE_BITS 41
71#elif defined(TARGET_SPARC)
72#define TARGET_PHYS_ADDR_SPACE_BITS 36
73#elif defined(TARGET_ALPHA)
74#define TARGET_PHYS_ADDR_SPACE_BITS 42
75#define TARGET_VIRT_ADDR_SPACE_BITS 42
76#elif defined(TARGET_PPC64)
77#define TARGET_PHYS_ADDR_SPACE_BITS 42
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070078#elif defined(TARGET_X86_64)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080079#define TARGET_PHYS_ADDR_SPACE_BITS 42
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070080#elif defined(TARGET_I386)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080081#define TARGET_PHYS_ADDR_SPACE_BITS 36
82#else
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080083#define TARGET_PHYS_ADDR_SPACE_BITS 32
84#endif
85
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070086static TranslationBlock *tbs;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080087int code_gen_max_blocks;
88TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070089static int nb_tbs;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080090/* any access to the tbs or the page table must use this lock */
91spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
92
93#if defined(__arm__) || defined(__sparc_v9__)
94/* The prologue must be reachable with a direct jump. ARM and Sparc64
95 have limited branch ranges (possibly also PPC) so place it in a
96 section close to code segment. */
97#define code_gen_section \
98 __attribute__((__section__(".gen_code"))) \
99 __attribute__((aligned (32)))
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700100#elif defined(_WIN32)
101/* Maximum alignment for Win32 is 16. */
102#define code_gen_section \
103 __attribute__((aligned (16)))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800104#else
105#define code_gen_section \
106 __attribute__((aligned (32)))
107#endif
108
109uint8_t code_gen_prologue[1024] code_gen_section;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700110static uint8_t *code_gen_buffer;
111static unsigned long code_gen_buffer_size;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800112/* threshold to flush the translated code buffer */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700113static unsigned long code_gen_buffer_max_size;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800114uint8_t *code_gen_ptr;
115
116#if !defined(CONFIG_USER_ONLY)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800117int phys_ram_fd;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800118uint8_t *phys_ram_dirty;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700119static int in_migration;
120
121typedef struct RAMBlock {
122 uint8_t *host;
123 ram_addr_t offset;
124 ram_addr_t length;
125 struct RAMBlock *next;
126} RAMBlock;
127
128static RAMBlock *ram_blocks;
129/* TODO: When we implement (and use) ram deallocation (e.g. for hotplug)
130 then we can no longer assume contiguous ram offsets, and external uses
131 of this variable will break. */
132ram_addr_t last_ram_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800133#endif
134
135CPUState *first_cpu;
136/* current CPU in the current thread. It is only valid inside
137 cpu_exec() */
138CPUState *cpu_single_env;
139/* 0 = Do not count executed instructions.
140 1 = Precise instruction counting.
141 2 = Adaptive rate instruction counting. */
142int use_icount = 0;
143/* Current instruction counter. While executing translated code this may
144 include some instructions that have not yet been executed. */
145int64_t qemu_icount;
146
147typedef struct PageDesc {
148 /* list of TBs intersecting this ram page */
149 TranslationBlock *first_tb;
150 /* in order to optimize self modifying code, we count the number
151 of lookups we do to a given page to use a bitmap */
152 unsigned int code_write_count;
153 uint8_t *code_bitmap;
154#if defined(CONFIG_USER_ONLY)
155 unsigned long flags;
156#endif
157} PageDesc;
158
159typedef struct PhysPageDesc {
160 /* offset in host memory of the page + io_index in the low bits */
161 ram_addr_t phys_offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700162 ram_addr_t region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800163} PhysPageDesc;
164
165#define L2_BITS 10
166#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
167/* XXX: this is a temporary hack for alpha target.
168 * In the future, this is to be replaced by a multi-level table
169 * to actually be able to handle the complete 64 bits address space.
170 */
171#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
172#else
173#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
174#endif
175
176#define L1_SIZE (1 << L1_BITS)
177#define L2_SIZE (1 << L2_BITS)
178
179unsigned long qemu_real_host_page_size;
180unsigned long qemu_host_page_bits;
181unsigned long qemu_host_page_size;
182unsigned long qemu_host_page_mask;
183
184/* XXX: for system emulation, it could just be an array */
185static PageDesc *l1_map[L1_SIZE];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700186static PhysPageDesc **l1_phys_map;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800187
188#if !defined(CONFIG_USER_ONLY)
189static void io_mem_init(void);
190
191/* io memory support */
192CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
193CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
194void *io_mem_opaque[IO_MEM_NB_ENTRIES];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700195static char io_mem_used[IO_MEM_NB_ENTRIES];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800196static int io_mem_watch;
197#endif
198
199/* log support */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700200#ifdef WIN32
201static const char *logfilename = "qemu.log";
202#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700203static const char *logfilename = "/tmp/qemu.log";
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700204#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800205FILE *logfile;
206int loglevel;
207static int log_append = 0;
208
209/* statistics */
210static int tlb_flush_count;
211static int tb_flush_count;
212static int tb_phys_invalidate_count;
213
214#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
215typedef struct subpage_t {
216 target_phys_addr_t base;
217 CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE][4];
218 CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE][4];
219 void *opaque[TARGET_PAGE_SIZE][2][4];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700220 ram_addr_t region_offset[TARGET_PAGE_SIZE][2][4];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800221} subpage_t;
222
223#ifdef _WIN32
224static void map_exec(void *addr, long size)
225{
226 DWORD old_protect;
227 VirtualProtect(addr, size,
228 PAGE_EXECUTE_READWRITE, &old_protect);
David 'Digit' Turner36411062010-12-22 17:34:53 +0100229
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800230}
231#else
232static void map_exec(void *addr, long size)
233{
234 unsigned long start, end, page_size;
David 'Digit' Turner36411062010-12-22 17:34:53 +0100235
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800236 page_size = getpagesize();
237 start = (unsigned long)addr;
238 start &= ~(page_size - 1);
David 'Digit' Turner36411062010-12-22 17:34:53 +0100239
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800240 end = (unsigned long)addr + size;
241 end += page_size - 1;
242 end &= ~(page_size - 1);
David 'Digit' Turner36411062010-12-22 17:34:53 +0100243
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800244 mprotect((void *)start, end - start,
245 PROT_READ | PROT_WRITE | PROT_EXEC);
246}
247#endif
248
249static void page_init(void)
250{
251 /* NOTE: we can always suppose that qemu_host_page_size >=
252 TARGET_PAGE_SIZE */
253#ifdef _WIN32
254 {
255 SYSTEM_INFO system_info;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800256
257 GetSystemInfo(&system_info);
258 qemu_real_host_page_size = system_info.dwPageSize;
259 }
260#else
261 qemu_real_host_page_size = getpagesize();
262#endif
263 if (qemu_host_page_size == 0)
264 qemu_host_page_size = qemu_real_host_page_size;
265 if (qemu_host_page_size < TARGET_PAGE_SIZE)
266 qemu_host_page_size = TARGET_PAGE_SIZE;
267 qemu_host_page_bits = 0;
268 while ((1 << qemu_host_page_bits) < qemu_host_page_size)
269 qemu_host_page_bits++;
270 qemu_host_page_mask = ~(qemu_host_page_size - 1);
271 l1_phys_map = qemu_vmalloc(L1_SIZE * sizeof(void *));
272 memset(l1_phys_map, 0, L1_SIZE * sizeof(void *));
273
274#if !defined(_WIN32) && defined(CONFIG_USER_ONLY)
275 {
276 long long startaddr, endaddr;
277 FILE *f;
278 int n;
279
280 mmap_lock();
281 last_brk = (unsigned long)sbrk(0);
282 f = fopen("/proc/self/maps", "r");
283 if (f) {
284 do {
285 n = fscanf (f, "%llx-%llx %*[^\n]\n", &startaddr, &endaddr);
286 if (n == 2) {
287 startaddr = MIN(startaddr,
288 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
289 endaddr = MIN(endaddr,
290 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
291 page_set_flags(startaddr & TARGET_PAGE_MASK,
292 TARGET_PAGE_ALIGN(endaddr),
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800293 PAGE_RESERVED);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800294 }
295 } while (!feof(f));
296 fclose(f);
297 }
298 mmap_unlock();
299 }
300#endif
301}
302
303static inline PageDesc **page_l1_map(target_ulong index)
304{
305#if TARGET_LONG_BITS > 32
306 /* Host memory outside guest VM. For 32-bit targets we have already
307 excluded high addresses. */
308 if (index > ((target_ulong)L2_SIZE * L1_SIZE))
309 return NULL;
310#endif
311 return &l1_map[index >> L2_BITS];
312}
313
314static inline PageDesc *page_find_alloc(target_ulong index)
315{
316 PageDesc **lp, *p;
317 lp = page_l1_map(index);
318 if (!lp)
319 return NULL;
320
321 p = *lp;
322 if (!p) {
323 /* allocate if not found */
324#if defined(CONFIG_USER_ONLY)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800325 size_t len = sizeof(PageDesc) * L2_SIZE;
326 /* Don't use qemu_malloc because it may recurse. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700327 p = mmap(NULL, len, PROT_READ | PROT_WRITE,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800328 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
329 *lp = p;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700330 if (h2g_valid(p)) {
331 unsigned long addr = h2g(p);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800332 page_set_flags(addr & TARGET_PAGE_MASK,
333 TARGET_PAGE_ALIGN(addr + len),
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800334 PAGE_RESERVED);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800335 }
336#else
337 p = qemu_mallocz(sizeof(PageDesc) * L2_SIZE);
338 *lp = p;
339#endif
340 }
341 return p + (index & (L2_SIZE - 1));
342}
343
344static inline PageDesc *page_find(target_ulong index)
345{
346 PageDesc **lp, *p;
347 lp = page_l1_map(index);
348 if (!lp)
349 return NULL;
350
351 p = *lp;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700352 if (!p) {
353 return NULL;
354 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800355 return p + (index & (L2_SIZE - 1));
356}
357
358static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
359{
360 void **lp, **p;
361 PhysPageDesc *pd;
362
363 p = (void **)l1_phys_map;
364#if TARGET_PHYS_ADDR_SPACE_BITS > 32
365
366#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
367#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
368#endif
369 lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1));
370 p = *lp;
371 if (!p) {
372 /* allocate if not found */
373 if (!alloc)
374 return NULL;
375 p = qemu_vmalloc(sizeof(void *) * L1_SIZE);
376 memset(p, 0, sizeof(void *) * L1_SIZE);
377 *lp = p;
378 }
379#endif
380 lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
381 pd = *lp;
382 if (!pd) {
383 int i;
384 /* allocate if not found */
385 if (!alloc)
386 return NULL;
387 pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
388 *lp = pd;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700389 for (i = 0; i < L2_SIZE; i++) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800390 pd[i].phys_offset = IO_MEM_UNASSIGNED;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700391 pd[i].region_offset = (index + i) << TARGET_PAGE_BITS;
392 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800393 }
394 return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
395}
396
397static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
398{
399 return phys_page_find_alloc(index, 0);
400}
401
402#if !defined(CONFIG_USER_ONLY)
403static void tlb_protect_code(ram_addr_t ram_addr);
404static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
405 target_ulong vaddr);
406#define mmap_lock() do { } while(0)
407#define mmap_unlock() do { } while(0)
408#endif
409
410#define DEFAULT_CODE_GEN_BUFFER_SIZE (32 * 1024 * 1024)
411
412#if defined(CONFIG_USER_ONLY)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700413/* Currently it is not recommended to allocate big chunks of data in
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800414 user mode. It will change when a dedicated libc will be used */
415#define USE_STATIC_CODE_GEN_BUFFER
416#endif
417
418#ifdef USE_STATIC_CODE_GEN_BUFFER
419static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE];
420#endif
421
422static void code_gen_alloc(unsigned long tb_size)
423{
424#ifdef USE_STATIC_CODE_GEN_BUFFER
425 code_gen_buffer = static_code_gen_buffer;
426 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
427 map_exec(code_gen_buffer, code_gen_buffer_size);
428#else
429 code_gen_buffer_size = tb_size;
430 if (code_gen_buffer_size == 0) {
431#if defined(CONFIG_USER_ONLY)
432 /* in user mode, phys_ram_size is not meaningful */
433 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
434#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700435 /* XXX: needs adjustments */
436 code_gen_buffer_size = (unsigned long)(ram_size / 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800437#endif
438 }
439 if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE)
440 code_gen_buffer_size = MIN_CODE_GEN_BUFFER_SIZE;
441 /* The code gen buffer location may have constraints depending on
442 the host cpu and OS */
David 'Digit' Turner36411062010-12-22 17:34:53 +0100443#if defined(__linux__)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800444 {
445 int flags;
446 void *start = NULL;
447
448 flags = MAP_PRIVATE | MAP_ANONYMOUS;
449#if defined(__x86_64__)
450 flags |= MAP_32BIT;
451 /* Cannot map more than that */
452 if (code_gen_buffer_size > (800 * 1024 * 1024))
453 code_gen_buffer_size = (800 * 1024 * 1024);
454#elif defined(__sparc_v9__)
455 // Map the buffer below 2G, so we can use direct calls and branches
456 flags |= MAP_FIXED;
457 start = (void *) 0x60000000UL;
458 if (code_gen_buffer_size > (512 * 1024 * 1024))
459 code_gen_buffer_size = (512 * 1024 * 1024);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700460#elif defined(__arm__)
461 /* Map the buffer below 32M, so we can use direct calls and branches */
462 flags |= MAP_FIXED;
463 start = (void *) 0x01000000UL;
464 if (code_gen_buffer_size > 16 * 1024 * 1024)
465 code_gen_buffer_size = 16 * 1024 * 1024;
David 'Digit' Turner36411062010-12-22 17:34:53 +0100466#elif defined(__s390x__)
467 /* Map the buffer so that we can use direct calls and branches. */
468 /* We have a +- 4GB range on the branches; leave some slop. */
469 if (code_gen_buffer_size > (3ul * 1024 * 1024 * 1024)) {
470 code_gen_buffer_size = 3ul * 1024 * 1024 * 1024;
471 }
472 start = (void *)0x90000000UL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800473#endif
474 code_gen_buffer = mmap(start, code_gen_buffer_size,
475 PROT_WRITE | PROT_READ | PROT_EXEC,
476 flags, -1, 0);
477 if (code_gen_buffer == MAP_FAILED) {
478 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
479 exit(1);
480 }
481 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700482#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700483 {
484 int flags;
485 void *addr = NULL;
486 flags = MAP_PRIVATE | MAP_ANONYMOUS;
487#if defined(__x86_64__)
488 /* FreeBSD doesn't have MAP_32BIT, use MAP_FIXED and assume
489 * 0x40000000 is free */
490 flags |= MAP_FIXED;
491 addr = (void *)0x40000000;
492 /* Cannot map more than that */
493 if (code_gen_buffer_size > (800 * 1024 * 1024))
494 code_gen_buffer_size = (800 * 1024 * 1024);
495#endif
496 code_gen_buffer = mmap(addr, code_gen_buffer_size,
David 'Digit' Turner36411062010-12-22 17:34:53 +0100497 PROT_WRITE | PROT_READ | PROT_EXEC,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700498 flags, -1, 0);
499 if (code_gen_buffer == MAP_FAILED) {
500 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
501 exit(1);
502 }
503 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800504#else
505 code_gen_buffer = qemu_malloc(code_gen_buffer_size);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800506 map_exec(code_gen_buffer, code_gen_buffer_size);
507#endif
508#endif /* !USE_STATIC_CODE_GEN_BUFFER */
509 map_exec(code_gen_prologue, sizeof(code_gen_prologue));
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800510 code_gen_buffer_max_size = code_gen_buffer_size -
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800511 code_gen_max_block_size();
512 code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
513 tbs = qemu_malloc(code_gen_max_blocks * sizeof(TranslationBlock));
514}
515
516/* Must be called before using the QEMU cpus. 'tb_size' is the size
517 (in bytes) allocated to the translation buffer. Zero means default
518 size. */
519void cpu_exec_init_all(unsigned long tb_size)
520{
521 cpu_gen_init();
522 code_gen_alloc(tb_size);
523 code_gen_ptr = code_gen_buffer;
524 page_init();
525#if !defined(CONFIG_USER_ONLY)
526 io_mem_init();
527#endif
528}
529
530#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
531
532#define CPU_COMMON_SAVE_VERSION 1
533
534static void cpu_common_save(QEMUFile *f, void *opaque)
535{
536 CPUState *env = opaque;
537
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700538 cpu_synchronize_state(env, 0);
539
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800540 qemu_put_be32s(f, &env->halted);
541 qemu_put_be32s(f, &env->interrupt_request);
542}
543
544static int cpu_common_load(QEMUFile *f, void *opaque, int version_id)
545{
546 CPUState *env = opaque;
547
548 if (version_id != CPU_COMMON_SAVE_VERSION)
549 return -EINVAL;
550
551 qemu_get_be32s(f, &env->halted);
552 qemu_get_be32s(f, &env->interrupt_request);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700553 /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
554 version_id is increased. */
555 env->interrupt_request &= ~0x01;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800556 tlb_flush(env, 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700557 cpu_synchronize_state(env, 1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800558
559 return 0;
560}
561#endif
562
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700563CPUState *qemu_get_cpu(int cpu)
564{
565 CPUState *env = first_cpu;
566
567 while (env) {
568 if (env->cpu_index == cpu)
569 break;
570 env = env->next_cpu;
571 }
572
573 return env;
574}
575
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800576void cpu_exec_init(CPUState *env)
577{
578 CPUState **penv;
579 int cpu_index;
580
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700581#if defined(CONFIG_USER_ONLY)
582 cpu_list_lock();
583#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800584 env->next_cpu = NULL;
585 penv = &first_cpu;
586 cpu_index = 0;
587 while (*penv != NULL) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700588 penv = &(*penv)->next_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800589 cpu_index++;
590 }
591 env->cpu_index = cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700592 env->numa_node = 0;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700593 QTAILQ_INIT(&env->breakpoints);
594 QTAILQ_INIT(&env->watchpoints);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800595 *penv = env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700596#if defined(CONFIG_USER_ONLY)
597 cpu_list_unlock();
598#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800599#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
600 register_savevm("cpu_common", cpu_index, CPU_COMMON_SAVE_VERSION,
601 cpu_common_save, cpu_common_load, env);
602 register_savevm("cpu", cpu_index, CPU_SAVE_VERSION,
603 cpu_save, cpu_load, env);
604#endif
605}
606
607static inline void invalidate_page_bitmap(PageDesc *p)
608{
609 if (p->code_bitmap) {
610 qemu_free(p->code_bitmap);
611 p->code_bitmap = NULL;
612 }
613 p->code_write_count = 0;
614}
615
616/* set to NULL all the 'first_tb' fields in all PageDescs */
617static void page_flush_tb(void)
618{
619 int i, j;
620 PageDesc *p;
621
622 for(i = 0; i < L1_SIZE; i++) {
623 p = l1_map[i];
624 if (p) {
625 for(j = 0; j < L2_SIZE; j++) {
626 p->first_tb = NULL;
627 invalidate_page_bitmap(p);
628 p++;
629 }
630 }
631 }
632}
633
634/* flush all the translation blocks */
635/* XXX: tb_flush is currently not thread safe */
636void tb_flush(CPUState *env1)
637{
638 CPUState *env;
639#if defined(DEBUG_FLUSH)
640 printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
641 (unsigned long)(code_gen_ptr - code_gen_buffer),
642 nb_tbs, nb_tbs > 0 ?
643 ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
644#endif
645 if ((unsigned long)(code_gen_ptr - code_gen_buffer) > code_gen_buffer_size)
646 cpu_abort(env1, "Internal error: code buffer overflow\n");
647
648 nb_tbs = 0;
649
650 for(env = first_cpu; env != NULL; env = env->next_cpu) {
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800651#ifdef CONFIG_MEMCHECK
652 int tb_to_clean;
653 for (tb_to_clean = 0; tb_to_clean < TB_JMP_CACHE_SIZE; tb_to_clean++) {
654 if (env->tb_jmp_cache[tb_to_clean] != NULL &&
655 env->tb_jmp_cache[tb_to_clean]->tpc2gpc != NULL) {
656 qemu_free(env->tb_jmp_cache[tb_to_clean]->tpc2gpc);
657 env->tb_jmp_cache[tb_to_clean]->tpc2gpc = NULL;
658 env->tb_jmp_cache[tb_to_clean]->tpc2gpc_pairs = 0;
659 }
660 }
661#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800662 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
663 }
664
665 memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
666 page_flush_tb();
667
668 code_gen_ptr = code_gen_buffer;
669 /* XXX: flush processor icache at this point if cache flush is
670 expensive */
671 tb_flush_count++;
672}
673
674#ifdef DEBUG_TB_CHECK
675
676static void tb_invalidate_check(target_ulong address)
677{
678 TranslationBlock *tb;
679 int i;
680 address &= TARGET_PAGE_MASK;
681 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
682 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
683 if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
684 address >= tb->pc + tb->size)) {
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700685 printf("ERROR invalidate: address=" TARGET_FMT_lx
686 " PC=%08lx size=%04x\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800687 address, (long)tb->pc, tb->size);
688 }
689 }
690 }
691}
692
693/* verify that all the pages have correct rights for code */
694static void tb_page_check(void)
695{
696 TranslationBlock *tb;
697 int i, flags1, flags2;
698
699 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
700 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
701 flags1 = page_get_flags(tb->pc);
702 flags2 = page_get_flags(tb->pc + tb->size - 1);
703 if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
704 printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
705 (long)tb->pc, tb->size, flags1, flags2);
706 }
707 }
708 }
709}
710
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800711#endif
712
713/* invalidate one TB */
714static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb,
715 int next_offset)
716{
717 TranslationBlock *tb1;
718 for(;;) {
719 tb1 = *ptb;
720 if (tb1 == tb) {
721 *ptb = *(TranslationBlock **)((char *)tb1 + next_offset);
722 break;
723 }
724 ptb = (TranslationBlock **)((char *)tb1 + next_offset);
725 }
726}
727
728static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
729{
730 TranslationBlock *tb1;
731 unsigned int n1;
732
733 for(;;) {
734 tb1 = *ptb;
735 n1 = (long)tb1 & 3;
736 tb1 = (TranslationBlock *)((long)tb1 & ~3);
737 if (tb1 == tb) {
738 *ptb = tb1->page_next[n1];
739 break;
740 }
741 ptb = &tb1->page_next[n1];
742 }
743}
744
745static inline void tb_jmp_remove(TranslationBlock *tb, int n)
746{
747 TranslationBlock *tb1, **ptb;
748 unsigned int n1;
749
750 ptb = &tb->jmp_next[n];
751 tb1 = *ptb;
752 if (tb1) {
753 /* find tb(n) in circular list */
754 for(;;) {
755 tb1 = *ptb;
756 n1 = (long)tb1 & 3;
757 tb1 = (TranslationBlock *)((long)tb1 & ~3);
758 if (n1 == n && tb1 == tb)
759 break;
760 if (n1 == 2) {
761 ptb = &tb1->jmp_first;
762 } else {
763 ptb = &tb1->jmp_next[n1];
764 }
765 }
766 /* now we can suppress tb(n) from the list */
767 *ptb = tb->jmp_next[n];
768
769 tb->jmp_next[n] = NULL;
770 }
771}
772
773/* reset the jump entry 'n' of a TB so that it is not chained to
774 another TB */
775static inline void tb_reset_jump(TranslationBlock *tb, int n)
776{
777 tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
778}
779
780void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr)
781{
782 CPUState *env;
783 PageDesc *p;
784 unsigned int h, n1;
785 target_phys_addr_t phys_pc;
786 TranslationBlock *tb1, *tb2;
787
788 /* remove the TB from the hash list */
789 phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
790 h = tb_phys_hash_func(phys_pc);
791 tb_remove(&tb_phys_hash[h], tb,
792 offsetof(TranslationBlock, phys_hash_next));
793
794 /* remove the TB from the page list */
795 if (tb->page_addr[0] != page_addr) {
796 p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
797 tb_page_remove(&p->first_tb, tb);
798 invalidate_page_bitmap(p);
799 }
800 if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
801 p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
802 tb_page_remove(&p->first_tb, tb);
803 invalidate_page_bitmap(p);
804 }
805
806 tb_invalidated_flag = 1;
807
808 /* remove the TB from the hash list */
809 h = tb_jmp_cache_hash_func(tb->pc);
810 for(env = first_cpu; env != NULL; env = env->next_cpu) {
811 if (env->tb_jmp_cache[h] == tb)
812 env->tb_jmp_cache[h] = NULL;
813 }
814
815 /* suppress this TB from the two jump lists */
816 tb_jmp_remove(tb, 0);
817 tb_jmp_remove(tb, 1);
818
819 /* suppress any remaining jumps to this TB */
820 tb1 = tb->jmp_first;
821 for(;;) {
822 n1 = (long)tb1 & 3;
823 if (n1 == 2)
824 break;
825 tb1 = (TranslationBlock *)((long)tb1 & ~3);
826 tb2 = tb1->jmp_next[n1];
827 tb_reset_jump(tb1, n1);
828 tb1->jmp_next[n1] = NULL;
829 tb1 = tb2;
830 }
831 tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
832
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800833#ifdef CONFIG_MEMCHECK
834 if (tb->tpc2gpc != NULL) {
835 qemu_free(tb->tpc2gpc);
836 tb->tpc2gpc = NULL;
837 tb->tpc2gpc_pairs = 0;
838 }
839#endif // CONFIG_MEMCHECK
840
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800841 tb_phys_invalidate_count++;
842}
843
844static inline void set_bits(uint8_t *tab, int start, int len)
845{
846 int end, mask, end1;
847
848 end = start + len;
849 tab += start >> 3;
850 mask = 0xff << (start & 7);
851 if ((start & ~7) == (end & ~7)) {
852 if (start < end) {
853 mask &= ~(0xff << (end & 7));
854 *tab |= mask;
855 }
856 } else {
857 *tab++ |= mask;
858 start = (start + 8) & ~7;
859 end1 = end & ~7;
860 while (start < end1) {
861 *tab++ = 0xff;
862 start += 8;
863 }
864 if (start < end) {
865 mask = ~(0xff << (end & 7));
866 *tab |= mask;
867 }
868 }
869}
870
871static void build_page_bitmap(PageDesc *p)
872{
873 int n, tb_start, tb_end;
874 TranslationBlock *tb;
875
876 p->code_bitmap = qemu_mallocz(TARGET_PAGE_SIZE / 8);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800877
878 tb = p->first_tb;
879 while (tb != NULL) {
880 n = (long)tb & 3;
881 tb = (TranslationBlock *)((long)tb & ~3);
882 /* NOTE: this is subtle as a TB may span two physical pages */
883 if (n == 0) {
884 /* NOTE: tb_end may be after the end of the page, but
885 it is not a problem */
886 tb_start = tb->pc & ~TARGET_PAGE_MASK;
887 tb_end = tb_start + tb->size;
888 if (tb_end > TARGET_PAGE_SIZE)
889 tb_end = TARGET_PAGE_SIZE;
890 } else {
891 tb_start = 0;
892 tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
893 }
894 set_bits(p->code_bitmap, tb_start, tb_end - tb_start);
895 tb = tb->page_next[n];
896 }
897}
898
899TranslationBlock *tb_gen_code(CPUState *env,
900 target_ulong pc, target_ulong cs_base,
901 int flags, int cflags)
902{
903 TranslationBlock *tb;
904 uint8_t *tc_ptr;
905 target_ulong phys_pc, phys_page2, virt_page2;
906 int code_gen_size;
907
908 phys_pc = get_phys_addr_code(env, pc);
909 tb = tb_alloc(pc);
910 if (!tb) {
911 /* flush must be done */
912 tb_flush(env);
913 /* cannot fail at this point */
914 tb = tb_alloc(pc);
915 /* Don't forget to invalidate previous TB info. */
916 tb_invalidated_flag = 1;
917 }
918 tc_ptr = code_gen_ptr;
919 tb->tc_ptr = tc_ptr;
920 tb->cs_base = cs_base;
921 tb->flags = flags;
922 tb->cflags = cflags;
923#ifdef CONFIG_TRACE
924 tb->bb_rec = NULL;
925 tb->prev_time = 0;
926#endif
927 cpu_gen_code(env, tb, &code_gen_size);
928 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
929
930 /* check next page if needed */
931 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
932 phys_page2 = -1;
933 if ((pc & TARGET_PAGE_MASK) != virt_page2) {
934 phys_page2 = get_phys_addr_code(env, virt_page2);
935 }
936 tb_link_phys(tb, phys_pc, phys_page2);
937 return tb;
938}
939
940/* invalidate all TBs which intersect with the target physical page
941 starting in range [start;end[. NOTE: start and end must refer to
942 the same physical page. 'is_cpu_write_access' should be true if called
943 from a real cpu write access: the virtual CPU will exit the current
944 TB if code is modified inside this TB. */
945void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t end,
946 int is_cpu_write_access)
947{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700948 TranslationBlock *tb, *tb_next, *saved_tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800949 CPUState *env = cpu_single_env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800950 target_ulong tb_start, tb_end;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700951 PageDesc *p;
952 int n;
953#ifdef TARGET_HAS_PRECISE_SMC
954 int current_tb_not_found = is_cpu_write_access;
955 TranslationBlock *current_tb = NULL;
956 int current_tb_modified = 0;
957 target_ulong current_pc = 0;
958 target_ulong current_cs_base = 0;
959 int current_flags = 0;
960#endif /* TARGET_HAS_PRECISE_SMC */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800961
962 p = page_find(start >> TARGET_PAGE_BITS);
963 if (!p)
964 return;
965 if (!p->code_bitmap &&
966 ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
967 is_cpu_write_access) {
968 /* build code bitmap */
969 build_page_bitmap(p);
970 }
971
972 /* we remove all the TBs in the range [start, end[ */
973 /* 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 -0800974 tb = p->first_tb;
975 while (tb != NULL) {
976 n = (long)tb & 3;
977 tb = (TranslationBlock *)((long)tb & ~3);
978 tb_next = tb->page_next[n];
979 /* NOTE: this is subtle as a TB may span two physical pages */
980 if (n == 0) {
981 /* NOTE: tb_end may be after the end of the page, but
982 it is not a problem */
983 tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
984 tb_end = tb_start + tb->size;
985 } else {
986 tb_start = tb->page_addr[1];
987 tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
988 }
989 if (!(tb_end <= start || tb_start >= end)) {
990#ifdef TARGET_HAS_PRECISE_SMC
991 if (current_tb_not_found) {
992 current_tb_not_found = 0;
993 current_tb = NULL;
994 if (env->mem_io_pc) {
995 /* now we have a real cpu fault */
996 current_tb = tb_find_pc(env->mem_io_pc);
997 }
998 }
999 if (current_tb == tb &&
1000 (current_tb->cflags & CF_COUNT_MASK) != 1) {
1001 /* If we are modifying the current TB, we must stop
1002 its execution. We could be more precise by checking
1003 that the modification is after the current PC, but it
1004 would require a specialized function to partially
1005 restore the CPU state */
1006
1007 current_tb_modified = 1;
1008 cpu_restore_state(current_tb, env,
1009 env->mem_io_pc, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001010 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
1011 &current_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001012 }
1013#endif /* TARGET_HAS_PRECISE_SMC */
1014 /* we need to do that to handle the case where a signal
1015 occurs while doing tb_phys_invalidate() */
1016 saved_tb = NULL;
1017 if (env) {
1018 saved_tb = env->current_tb;
1019 env->current_tb = NULL;
1020 }
1021 tb_phys_invalidate(tb, -1);
1022 if (env) {
1023 env->current_tb = saved_tb;
1024 if (env->interrupt_request && env->current_tb)
1025 cpu_interrupt(env, env->interrupt_request);
1026 }
1027 }
1028 tb = tb_next;
1029 }
1030#if !defined(CONFIG_USER_ONLY)
1031 /* if no code remaining, no need to continue to use slow writes */
1032 if (!p->first_tb) {
1033 invalidate_page_bitmap(p);
1034 if (is_cpu_write_access) {
1035 tlb_unprotect_code_phys(env, start, env->mem_io_vaddr);
1036 }
1037 }
1038#endif
1039#ifdef TARGET_HAS_PRECISE_SMC
1040 if (current_tb_modified) {
1041 /* we generate a block containing just the instruction
1042 modifying the memory. It will ensure that it cannot modify
1043 itself */
1044 env->current_tb = NULL;
1045 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1046 cpu_resume_from_signal(env, NULL);
1047 }
1048#endif
1049}
1050
1051/* len must be <= 8 and start must be a multiple of len */
1052static inline void tb_invalidate_phys_page_fast(target_phys_addr_t start, int len)
1053{
1054 PageDesc *p;
1055 int offset, b;
1056#if 0
1057 if (1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001058 qemu_log("modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
1059 cpu_single_env->mem_io_vaddr, len,
1060 cpu_single_env->eip,
1061 cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001062 }
1063#endif
1064 p = page_find(start >> TARGET_PAGE_BITS);
1065 if (!p)
1066 return;
1067 if (p->code_bitmap) {
1068 offset = start & ~TARGET_PAGE_MASK;
1069 b = p->code_bitmap[offset >> 3] >> (offset & 7);
1070 if (b & ((1 << len) - 1))
1071 goto do_invalidate;
1072 } else {
1073 do_invalidate:
1074 tb_invalidate_phys_page_range(start, start + len, 1);
1075 }
1076}
1077
1078#if !defined(CONFIG_SOFTMMU)
1079static void tb_invalidate_phys_page(target_phys_addr_t addr,
1080 unsigned long pc, void *puc)
1081{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001082 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001083 PageDesc *p;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001084 int n;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001085#ifdef TARGET_HAS_PRECISE_SMC
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001086 TranslationBlock *current_tb = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001087 CPUState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001088 int current_tb_modified = 0;
1089 target_ulong current_pc = 0;
1090 target_ulong current_cs_base = 0;
1091 int current_flags = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001092#endif
1093
1094 addr &= TARGET_PAGE_MASK;
1095 p = page_find(addr >> TARGET_PAGE_BITS);
1096 if (!p)
1097 return;
1098 tb = p->first_tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001099#ifdef TARGET_HAS_PRECISE_SMC
1100 if (tb && pc != 0) {
1101 current_tb = tb_find_pc(pc);
1102 }
1103#endif
1104 while (tb != NULL) {
1105 n = (long)tb & 3;
1106 tb = (TranslationBlock *)((long)tb & ~3);
1107#ifdef TARGET_HAS_PRECISE_SMC
1108 if (current_tb == tb &&
1109 (current_tb->cflags & CF_COUNT_MASK) != 1) {
1110 /* If we are modifying the current TB, we must stop
1111 its execution. We could be more precise by checking
1112 that the modification is after the current PC, but it
1113 would require a specialized function to partially
1114 restore the CPU state */
1115
1116 current_tb_modified = 1;
1117 cpu_restore_state(current_tb, env, pc, puc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001118 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
1119 &current_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001120 }
1121#endif /* TARGET_HAS_PRECISE_SMC */
1122 tb_phys_invalidate(tb, addr);
1123 tb = tb->page_next[n];
1124 }
1125 p->first_tb = NULL;
1126#ifdef TARGET_HAS_PRECISE_SMC
1127 if (current_tb_modified) {
1128 /* we generate a block containing just the instruction
1129 modifying the memory. It will ensure that it cannot modify
1130 itself */
1131 env->current_tb = NULL;
1132 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1133 cpu_resume_from_signal(env, puc);
1134 }
1135#endif
1136}
1137#endif
1138
1139/* add the tb in the target page and protect it if necessary */
1140static inline void tb_alloc_page(TranslationBlock *tb,
1141 unsigned int n, target_ulong page_addr)
1142{
1143 PageDesc *p;
1144 TranslationBlock *last_first_tb;
1145
1146 tb->page_addr[n] = page_addr;
1147 p = page_find_alloc(page_addr >> TARGET_PAGE_BITS);
1148 tb->page_next[n] = p->first_tb;
1149 last_first_tb = p->first_tb;
1150 p->first_tb = (TranslationBlock *)((long)tb | n);
1151 invalidate_page_bitmap(p);
1152
1153#if defined(TARGET_HAS_SMC) || 1
1154
1155#if defined(CONFIG_USER_ONLY)
1156 if (p->flags & PAGE_WRITE) {
1157 target_ulong addr;
1158 PageDesc *p2;
1159 int prot;
1160
1161 /* force the host page as non writable (writes will have a
1162 page fault + mprotect overhead) */
1163 page_addr &= qemu_host_page_mask;
1164 prot = 0;
1165 for(addr = page_addr; addr < page_addr + qemu_host_page_size;
1166 addr += TARGET_PAGE_SIZE) {
1167
1168 p2 = page_find (addr >> TARGET_PAGE_BITS);
1169 if (!p2)
1170 continue;
1171 prot |= p2->flags;
1172 p2->flags &= ~PAGE_WRITE;
1173 page_get_flags(addr);
1174 }
1175 mprotect(g2h(page_addr), qemu_host_page_size,
1176 (prot & PAGE_BITS) & ~PAGE_WRITE);
1177#ifdef DEBUG_TB_INVALIDATE
1178 printf("protecting code page: 0x" TARGET_FMT_lx "\n",
1179 page_addr);
1180#endif
1181 }
1182#else
1183 /* if some code is already present, then the pages are already
1184 protected. So we handle the case where only the first TB is
1185 allocated in a physical page */
1186 if (!last_first_tb) {
1187 tlb_protect_code(page_addr);
1188 }
1189#endif
1190
1191#endif /* TARGET_HAS_SMC */
1192}
1193
1194/* Allocate a new translation block. Flush the translation buffer if
1195 too many translation blocks or too much generated code. */
1196TranslationBlock *tb_alloc(target_ulong pc)
1197{
1198 TranslationBlock *tb;
1199
1200 if (nb_tbs >= code_gen_max_blocks ||
1201 (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
1202 return NULL;
1203 tb = &tbs[nb_tbs++];
1204 tb->pc = pc;
1205 tb->cflags = 0;
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -08001206#ifdef CONFIG_MEMCHECK
1207 tb->tpc2gpc = NULL;
1208 tb->tpc2gpc_pairs = 0;
1209#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001210 return tb;
1211}
1212
1213void tb_free(TranslationBlock *tb)
1214{
1215 /* In practice this is mostly used for single use temporary TB
1216 Ignore the hard cases and just back up if this TB happens to
1217 be the last one generated. */
1218 if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) {
1219 code_gen_ptr = tb->tc_ptr;
1220 nb_tbs--;
1221 }
1222}
1223
1224/* add a new TB and link it to the physical page tables. phys_page2 is
1225 (-1) to indicate that only one page contains the TB. */
1226void tb_link_phys(TranslationBlock *tb,
1227 target_ulong phys_pc, target_ulong phys_page2)
1228{
1229 unsigned int h;
1230 TranslationBlock **ptb;
1231
1232 /* Grab the mmap lock to stop another thread invalidating this TB
1233 before we are done. */
1234 mmap_lock();
1235 /* add in the physical hash table */
1236 h = tb_phys_hash_func(phys_pc);
1237 ptb = &tb_phys_hash[h];
1238 tb->phys_hash_next = *ptb;
1239 *ptb = tb;
1240
1241 /* add in the page list */
1242 tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK);
1243 if (phys_page2 != -1)
1244 tb_alloc_page(tb, 1, phys_page2);
1245 else
1246 tb->page_addr[1] = -1;
1247
1248 tb->jmp_first = (TranslationBlock *)((long)tb | 2);
1249 tb->jmp_next[0] = NULL;
1250 tb->jmp_next[1] = NULL;
1251
1252 /* init original jump addresses */
1253 if (tb->tb_next_offset[0] != 0xffff)
1254 tb_reset_jump(tb, 0);
1255 if (tb->tb_next_offset[1] != 0xffff)
1256 tb_reset_jump(tb, 1);
1257
1258#ifdef DEBUG_TB_CHECK
1259 tb_page_check();
1260#endif
1261 mmap_unlock();
1262}
1263
1264/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
1265 tb[1].tc_ptr. Return NULL if not found */
1266TranslationBlock *tb_find_pc(unsigned long tc_ptr)
1267{
1268 int m_min, m_max, m;
1269 unsigned long v;
1270 TranslationBlock *tb;
1271
1272 if (nb_tbs <= 0)
1273 return NULL;
1274 if (tc_ptr < (unsigned long)code_gen_buffer ||
1275 tc_ptr >= (unsigned long)code_gen_ptr)
1276 return NULL;
1277 /* binary search (cf Knuth) */
1278 m_min = 0;
1279 m_max = nb_tbs - 1;
1280 while (m_min <= m_max) {
1281 m = (m_min + m_max) >> 1;
1282 tb = &tbs[m];
1283 v = (unsigned long)tb->tc_ptr;
1284 if (v == tc_ptr)
1285 return tb;
1286 else if (tc_ptr < v) {
1287 m_max = m - 1;
1288 } else {
1289 m_min = m + 1;
1290 }
1291 }
1292 return &tbs[m_max];
1293}
1294
1295static void tb_reset_jump_recursive(TranslationBlock *tb);
1296
1297static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
1298{
1299 TranslationBlock *tb1, *tb_next, **ptb;
1300 unsigned int n1;
1301
1302 tb1 = tb->jmp_next[n];
1303 if (tb1 != NULL) {
1304 /* find head of list */
1305 for(;;) {
1306 n1 = (long)tb1 & 3;
1307 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1308 if (n1 == 2)
1309 break;
1310 tb1 = tb1->jmp_next[n1];
1311 }
1312 /* we are now sure now that tb jumps to tb1 */
1313 tb_next = tb1;
1314
1315 /* remove tb from the jmp_first list */
1316 ptb = &tb_next->jmp_first;
1317 for(;;) {
1318 tb1 = *ptb;
1319 n1 = (long)tb1 & 3;
1320 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1321 if (n1 == n && tb1 == tb)
1322 break;
1323 ptb = &tb1->jmp_next[n1];
1324 }
1325 *ptb = tb->jmp_next[n];
1326 tb->jmp_next[n] = NULL;
1327
1328 /* suppress the jump to next tb in generated code */
1329 tb_reset_jump(tb, n);
1330
1331 /* suppress jumps in the tb on which we could have jumped */
1332 tb_reset_jump_recursive(tb_next);
1333 }
1334}
1335
1336static void tb_reset_jump_recursive(TranslationBlock *tb)
1337{
1338 tb_reset_jump_recursive2(tb, 0);
1339 tb_reset_jump_recursive2(tb, 1);
1340}
1341
1342#if defined(TARGET_HAS_ICE)
1343static void breakpoint_invalidate(CPUState *env, target_ulong pc)
1344{
1345 target_phys_addr_t addr;
1346 target_ulong pd;
1347 ram_addr_t ram_addr;
1348 PhysPageDesc *p;
1349
1350 addr = cpu_get_phys_page_debug(env, pc);
1351 p = phys_page_find(addr >> TARGET_PAGE_BITS);
1352 if (!p) {
1353 pd = IO_MEM_UNASSIGNED;
1354 } else {
1355 pd = p->phys_offset;
1356 }
1357 ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
1358 tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
1359}
1360#endif
1361
1362/* Add a watchpoint. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001363int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
1364 int flags, CPUWatchpoint **watchpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001365{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001366 target_ulong len_mask = ~(len - 1);
1367 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001368
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001369 /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
1370 if ((len != 1 && len != 2 && len != 4 && len != 8) || (addr & ~len_mask)) {
1371 fprintf(stderr, "qemu: tried to set invalid watchpoint at "
1372 TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
1373 return -EINVAL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001374 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001375 wp = qemu_malloc(sizeof(*wp));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001376
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001377 wp->vaddr = addr;
1378 wp->len_mask = len_mask;
1379 wp->flags = flags;
1380
1381 /* keep all GDB-injected watchpoints in front */
1382 if (flags & BP_GDB)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001383 QTAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001384 else
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001385 QTAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001386
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001387 tlb_flush_page(env, addr);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001388
1389 if (watchpoint)
1390 *watchpoint = wp;
1391 return 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001392}
1393
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001394/* Remove a specific watchpoint. */
1395int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len,
1396 int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001397{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001398 target_ulong len_mask = ~(len - 1);
1399 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001400
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001401 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001402 if (addr == wp->vaddr && len_mask == wp->len_mask
1403 && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
1404 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001405 return 0;
1406 }
1407 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001408 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001409}
1410
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001411/* Remove a specific watchpoint by reference. */
1412void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint)
1413{
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001414 QTAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001415
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001416 tlb_flush_page(env, watchpoint->vaddr);
1417
1418 qemu_free(watchpoint);
1419}
1420
1421/* Remove all matching watchpoints. */
1422void cpu_watchpoint_remove_all(CPUState *env, int mask)
1423{
1424 CPUWatchpoint *wp, *next;
1425
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001426 QTAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001427 if (wp->flags & mask)
1428 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001429 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001430}
1431
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001432/* Add a breakpoint. */
1433int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
1434 CPUBreakpoint **breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001435{
1436#if defined(TARGET_HAS_ICE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001437 CPUBreakpoint *bp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001438
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001439 bp = qemu_malloc(sizeof(*bp));
1440
1441 bp->pc = pc;
1442 bp->flags = flags;
1443
1444 /* keep all GDB-injected breakpoints in front */
1445 if (flags & BP_GDB)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001446 QTAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001447 else
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001448 QTAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001449
1450 breakpoint_invalidate(env, pc);
1451
1452 if (breakpoint)
1453 *breakpoint = bp;
1454 return 0;
1455#else
1456 return -ENOSYS;
1457#endif
1458}
1459
1460/* Remove a specific breakpoint. */
1461int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags)
1462{
1463#if defined(TARGET_HAS_ICE)
1464 CPUBreakpoint *bp;
1465
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001466 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001467 if (bp->pc == pc && bp->flags == flags) {
1468 cpu_breakpoint_remove_by_ref(env, bp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001469 return 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001470 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001471 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001472 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001473#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001474 return -ENOSYS;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001475#endif
1476}
1477
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001478/* Remove a specific breakpoint by reference. */
1479void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001480{
1481#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001482 QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001483
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001484 breakpoint_invalidate(env, breakpoint->pc);
1485
1486 qemu_free(breakpoint);
1487#endif
1488}
1489
1490/* Remove all matching breakpoints. */
1491void cpu_breakpoint_remove_all(CPUState *env, int mask)
1492{
1493#if defined(TARGET_HAS_ICE)
1494 CPUBreakpoint *bp, *next;
1495
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001496 QTAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001497 if (bp->flags & mask)
1498 cpu_breakpoint_remove_by_ref(env, bp);
1499 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001500#endif
1501}
1502
1503/* enable or disable single step mode. EXCP_DEBUG is returned by the
1504 CPU loop after each instruction */
1505void cpu_single_step(CPUState *env, int enabled)
1506{
1507#if defined(TARGET_HAS_ICE)
1508 if (env->singlestep_enabled != enabled) {
1509 env->singlestep_enabled = enabled;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001510 if (kvm_enabled())
1511 kvm_update_guest_debug(env, 0);
1512 else {
1513 /* must flush all the translated code to avoid inconsistencies */
1514 /* XXX: only flush what is necessary */
1515 tb_flush(env);
1516 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001517 }
1518#endif
1519}
1520
1521/* enable or disable low levels log */
1522void cpu_set_log(int log_flags)
1523{
1524 loglevel = log_flags;
1525 if (loglevel && !logfile) {
1526 logfile = fopen(logfilename, log_append ? "a" : "w");
1527 if (!logfile) {
1528 perror(logfilename);
1529 _exit(1);
1530 }
1531#if !defined(CONFIG_SOFTMMU)
1532 /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1533 {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001534 static char logfile_buf[4096];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001535 setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1536 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001537#elif !defined(_WIN32)
1538 /* Win32 doesn't support line-buffering and requires size >= 2 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001539 setvbuf(logfile, NULL, _IOLBF, 0);
1540#endif
1541 log_append = 1;
1542 }
1543 if (!loglevel && logfile) {
1544 fclose(logfile);
1545 logfile = NULL;
1546 }
1547}
1548
1549void cpu_set_log_filename(const char *filename)
1550{
1551 logfilename = strdup(filename);
1552 if (logfile) {
1553 fclose(logfile);
1554 logfile = NULL;
1555 }
1556 cpu_set_log(loglevel);
1557}
1558
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001559static void cpu_unlink_tb(CPUState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001560{
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001561 /* FIXME: TB unchaining isn't SMP safe. For now just ignore the
1562 problem and hope the cpu will stop of its own accord. For userspace
1563 emulation this often isn't actually as bad as it sounds. Often
1564 signals are used primarily to interrupt blocking syscalls. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001565 TranslationBlock *tb;
1566 static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
1567
1568 tb = env->current_tb;
1569 /* if the cpu is currently executing code, we must unlink it and
1570 all the potentially executing TB */
1571 if (tb && !testandset(&interrupt_lock)) {
1572 env->current_tb = NULL;
1573 tb_reset_jump_recursive(tb);
1574 resetlock(&interrupt_lock);
1575 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001576}
1577
1578/* mask must never be zero, except for A20 change call */
1579void cpu_interrupt(CPUState *env, int mask)
1580{
1581 int old_mask;
1582
1583 old_mask = env->interrupt_request;
1584 env->interrupt_request |= mask;
1585
1586#ifndef CONFIG_USER_ONLY
1587 /*
1588 * If called from iothread context, wake the target cpu in
1589 * case its halted.
1590 */
1591 if (!qemu_cpu_self(env)) {
1592 qemu_cpu_kick(env);
1593 return;
1594 }
1595#endif
1596
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001597 if (use_icount) {
1598 env->icount_decr.u16.high = 0xffff;
1599#ifndef CONFIG_USER_ONLY
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001600 if (!can_do_io(env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001601 && (mask & ~old_mask) != 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001602 cpu_abort(env, "Raised interrupt while not in I/O function");
1603 }
1604#endif
1605 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001606 cpu_unlink_tb(env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001607 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001608}
1609
1610void cpu_reset_interrupt(CPUState *env, int mask)
1611{
1612 env->interrupt_request &= ~mask;
1613}
1614
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001615void cpu_exit(CPUState *env)
1616{
1617 env->exit_request = 1;
1618 cpu_unlink_tb(env);
1619}
1620
1621const CPULogItem cpu_log_items[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001622 { CPU_LOG_TB_OUT_ASM, "out_asm",
1623 "show generated host assembly code for each compiled TB" },
1624 { CPU_LOG_TB_IN_ASM, "in_asm",
1625 "show target assembly code for each compiled TB" },
1626 { CPU_LOG_TB_OP, "op",
1627 "show micro ops for each compiled TB" },
1628 { CPU_LOG_TB_OP_OPT, "op_opt",
1629 "show micro ops "
1630#ifdef TARGET_I386
1631 "before eflags optimization and "
1632#endif
1633 "after liveness analysis" },
1634 { CPU_LOG_INT, "int",
1635 "show interrupts/exceptions in short format" },
1636 { CPU_LOG_EXEC, "exec",
1637 "show trace before each executed TB (lots of logs)" },
1638 { CPU_LOG_TB_CPU, "cpu",
1639 "show CPU state before block translation" },
1640#ifdef TARGET_I386
1641 { CPU_LOG_PCALL, "pcall",
1642 "show protected mode far calls/returns/exceptions" },
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001643 { CPU_LOG_RESET, "cpu_reset",
1644 "show CPU state before CPU resets" },
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001645#endif
1646#ifdef DEBUG_IOPORT
1647 { CPU_LOG_IOPORT, "ioport",
1648 "show all i/o ports accesses" },
1649#endif
1650 { 0, NULL, NULL },
1651};
1652
1653static int cmp1(const char *s1, int n, const char *s2)
1654{
1655 if (strlen(s2) != n)
1656 return 0;
1657 return memcmp(s1, s2, n) == 0;
1658}
1659
1660/* takes a comma separated list of log masks. Return 0 if error. */
1661int cpu_str_to_log_mask(const char *str)
1662{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001663 const CPULogItem *item;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001664 int mask;
1665 const char *p, *p1;
1666
1667 p = str;
1668 mask = 0;
1669 for(;;) {
1670 p1 = strchr(p, ',');
1671 if (!p1)
1672 p1 = p + strlen(p);
1673 if(cmp1(p,p1-p,"all")) {
1674 for(item = cpu_log_items; item->mask != 0; item++) {
1675 mask |= item->mask;
1676 }
1677 } else {
1678 for(item = cpu_log_items; item->mask != 0; item++) {
1679 if (cmp1(p, p1 - p, item->name))
1680 goto found;
1681 }
1682 return 0;
1683 }
1684 found:
1685 mask |= item->mask;
1686 if (*p1 != ',')
1687 break;
1688 p = p1 + 1;
1689 }
1690 return mask;
1691}
1692
1693void cpu_abort(CPUState *env, const char *fmt, ...)
1694{
1695 va_list ap;
1696 va_list ap2;
1697
1698 va_start(ap, fmt);
1699 va_copy(ap2, ap);
1700 fprintf(stderr, "qemu: fatal: ");
1701 vfprintf(stderr, fmt, ap);
1702 fprintf(stderr, "\n");
1703#ifdef TARGET_I386
1704 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1705#else
1706 cpu_dump_state(env, stderr, fprintf, 0);
1707#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001708 if (qemu_log_enabled()) {
1709 qemu_log("qemu: fatal: ");
1710 qemu_log_vprintf(fmt, ap2);
1711 qemu_log("\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001712#ifdef TARGET_I386
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001713 log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001714#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001715 log_cpu_state(env, 0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001716#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001717 qemu_log_flush();
1718 qemu_log_close();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001719 }
1720 va_end(ap2);
1721 va_end(ap);
David 'Digit' Turner36411062010-12-22 17:34:53 +01001722#if defined(CONFIG_USER_ONLY)
1723 {
1724 struct sigaction act;
1725 sigfillset(&act.sa_mask);
1726 act.sa_handler = SIG_DFL;
1727 sigaction(SIGABRT, &act, NULL);
1728 }
1729#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001730 abort();
1731}
1732
1733CPUState *cpu_copy(CPUState *env)
1734{
1735 CPUState *new_env = cpu_init(env->cpu_model_str);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001736 CPUState *next_cpu = new_env->next_cpu;
1737 int cpu_index = new_env->cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001738#if defined(TARGET_HAS_ICE)
1739 CPUBreakpoint *bp;
1740 CPUWatchpoint *wp;
1741#endif
1742
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001743 memcpy(new_env, env, sizeof(CPUState));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001744
1745 /* Preserve chaining and index. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001746 new_env->next_cpu = next_cpu;
1747 new_env->cpu_index = cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001748
1749 /* Clone all break/watchpoints.
1750 Note: Once we support ptrace with hw-debug register access, make sure
1751 BP_CPU break/watchpoints are handled correctly on clone. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001752 QTAILQ_INIT(&env->breakpoints);
1753 QTAILQ_INIT(&env->watchpoints);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001754#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001755 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001756 cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
1757 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001758 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001759 cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
1760 wp->flags, NULL);
1761 }
1762#endif
1763
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001764 return new_env;
1765}
1766
1767#if !defined(CONFIG_USER_ONLY)
1768
1769static inline void tlb_flush_jmp_cache(CPUState *env, target_ulong addr)
1770{
1771 unsigned int i;
1772
1773 /* Discard jump cache entries for any tb which might potentially
1774 overlap the flushed page. */
1775 i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
David 'Digit' Turner36411062010-12-22 17:34:53 +01001776 memset (&env->tb_jmp_cache[i], 0,
1777 TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001778
1779 i = tb_jmp_cache_hash_page(addr);
David 'Digit' Turner36411062010-12-22 17:34:53 +01001780 memset (&env->tb_jmp_cache[i], 0,
1781 TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001782}
1783
1784/* NOTE: if flush_global is true, also flush global entries (not
1785 implemented yet) */
1786void tlb_flush(CPUState *env, int flush_global)
1787{
1788 int i;
1789
1790#if defined(DEBUG_TLB)
1791 printf("tlb_flush:\n");
1792#endif
1793 /* must reset current TB so that interrupts cannot modify the
1794 links while we are modifying them */
1795 env->current_tb = NULL;
1796
1797 for(i = 0; i < CPU_TLB_SIZE; i++) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001798 int mmu_idx;
1799 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1800 env->tlb_table[mmu_idx][i].addr_read = -1;
1801 env->tlb_table[mmu_idx][i].addr_write = -1;
1802 env->tlb_table[mmu_idx][i].addr_code = -1;
1803 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001804 }
1805
1806 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
1807
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001808#ifdef CONFIG_KQEMU
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001809 if (env->kqemu_enabled) {
1810 kqemu_flush(env, flush_global);
1811 }
1812#endif
1813 tlb_flush_count++;
1814}
1815
1816static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
1817{
1818 if (addr == (tlb_entry->addr_read &
1819 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1820 addr == (tlb_entry->addr_write &
1821 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1822 addr == (tlb_entry->addr_code &
1823 (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1824 tlb_entry->addr_read = -1;
1825 tlb_entry->addr_write = -1;
1826 tlb_entry->addr_code = -1;
1827 }
1828}
1829
1830void tlb_flush_page(CPUState *env, target_ulong addr)
1831{
1832 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001833 int mmu_idx;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001834
1835#if defined(DEBUG_TLB)
1836 printf("tlb_flush_page: " TARGET_FMT_lx "\n", addr);
1837#endif
1838 /* must reset current TB so that interrupts cannot modify the
1839 links while we are modifying them */
1840 env->current_tb = NULL;
1841
1842 addr &= TARGET_PAGE_MASK;
1843 i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001844 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++)
1845 tlb_flush_entry(&env->tlb_table[mmu_idx][i], addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001846
1847 tlb_flush_jmp_cache(env, addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001848}
1849
1850/* update the TLBs so that writes to code in the virtual page 'addr'
1851 can be detected */
1852static void tlb_protect_code(ram_addr_t ram_addr)
1853{
1854 cpu_physical_memory_reset_dirty(ram_addr,
1855 ram_addr + TARGET_PAGE_SIZE,
1856 CODE_DIRTY_FLAG);
1857}
1858
1859/* update the TLB so that writes in physical page 'phys_addr' are no longer
1860 tested for self modifying code */
1861static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
1862 target_ulong vaddr)
1863{
1864 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] |= CODE_DIRTY_FLAG;
1865}
1866
1867static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
1868 unsigned long start, unsigned long length)
1869{
1870 unsigned long addr;
1871 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1872 addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
1873 if ((addr - start) < length) {
1874 tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
1875 }
1876 }
1877}
1878
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001879/* Note: start and end must be within the same ram block. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001880void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
1881 int dirty_flags)
1882{
1883 CPUState *env;
1884 unsigned long length, start1;
1885 int i, mask, len;
1886 uint8_t *p;
1887
1888 start &= TARGET_PAGE_MASK;
1889 end = TARGET_PAGE_ALIGN(end);
1890
1891 length = end - start;
1892 if (length == 0)
1893 return;
1894 len = length >> TARGET_PAGE_BITS;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001895 mask = ~dirty_flags;
1896 p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
1897 for(i = 0; i < len; i++)
1898 p[i] &= mask;
1899
1900 /* we modify the TLB cache so that the dirty bit will be set again
1901 when accessing the range */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001902 start1 = (unsigned long)qemu_get_ram_ptr(start);
1903 /* Chek that we don't span multiple blocks - this breaks the
1904 address comparisons below. */
1905 if ((unsigned long)qemu_get_ram_ptr(end - 1) - start1
1906 != (end - 1) - start) {
1907 abort();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001908 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001909
1910 for(env = first_cpu; env != NULL; env = env->next_cpu) {
1911 int mmu_idx;
1912 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1913 for(i = 0; i < CPU_TLB_SIZE; i++)
1914 tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
1915 start1, length);
1916 }
1917 }
1918}
1919
1920int cpu_physical_memory_set_dirty_tracking(int enable)
1921{
1922 in_migration = enable;
1923 if (kvm_enabled()) {
1924 return kvm_set_migration_log(enable);
1925 }
1926 return 0;
1927}
1928
1929int cpu_physical_memory_get_dirty_tracking(void)
1930{
1931 return in_migration;
1932}
1933
1934int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
1935 target_phys_addr_t end_addr)
1936{
1937 int ret = 0;
1938
1939 if (kvm_enabled())
1940 ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
1941 return ret;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001942}
1943
1944static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1945{
1946 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001947 void *p;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001948
1949 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001950 p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
1951 + tlb_entry->addend);
1952 ram_addr = qemu_ram_addr_from_host(p);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001953 if (!cpu_physical_memory_is_dirty(ram_addr)) {
1954 tlb_entry->addr_write |= TLB_NOTDIRTY;
1955 }
1956 }
1957}
1958
1959/* update the TLB according to the current state of the dirty bits */
1960void cpu_tlb_update_dirty(CPUState *env)
1961{
1962 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001963 int mmu_idx;
1964 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1965 for(i = 0; i < CPU_TLB_SIZE; i++)
1966 tlb_update_dirty(&env->tlb_table[mmu_idx][i]);
1967 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001968}
1969
1970static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, target_ulong vaddr)
1971{
1972 if (tlb_entry->addr_write == (vaddr | TLB_NOTDIRTY))
1973 tlb_entry->addr_write = vaddr;
1974}
1975
1976/* update the TLB corresponding to virtual page vaddr
1977 so that it is no longer dirty */
1978static inline void tlb_set_dirty(CPUState *env, target_ulong vaddr)
1979{
1980 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001981 int mmu_idx;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001982
1983 vaddr &= TARGET_PAGE_MASK;
1984 i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001985 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++)
1986 tlb_set_dirty1(&env->tlb_table[mmu_idx][i], vaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001987}
1988
1989/* add a new TLB entry. At most one entry for a given virtual address
1990 is permitted. Return 0 if OK or 2 if the page could not be mapped
1991 (can only happen in non SOFTMMU mode for I/O pages or pages
1992 conflicting with the host address space). */
1993int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
1994 target_phys_addr_t paddr, int prot,
1995 int mmu_idx, int is_softmmu)
1996{
1997 PhysPageDesc *p;
1998 unsigned long pd;
1999 unsigned int index;
2000 target_ulong address;
2001 target_ulong code_address;
David 'Digit' Turnerd9b6cb92010-10-20 19:07:28 +02002002 ptrdiff_t addend;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002003 int ret;
2004 CPUTLBEntry *te;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002005 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002006 target_phys_addr_t iotlb;
2007
2008 p = phys_page_find(paddr >> TARGET_PAGE_BITS);
2009 if (!p) {
2010 pd = IO_MEM_UNASSIGNED;
2011 } else {
2012 pd = p->phys_offset;
2013 }
2014#if defined(DEBUG_TLB)
2015 printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x idx=%d smmu=%d pd=0x%08lx\n",
2016 vaddr, (int)paddr, prot, mmu_idx, is_softmmu, pd);
2017#endif
2018
2019 ret = 0;
2020 address = vaddr;
2021 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
2022 /* IO memory case (romd handled later) */
2023 address |= TLB_MMIO;
2024 }
David 'Digit' Turnerd9b6cb92010-10-20 19:07:28 +02002025 addend = (ptrdiff_t)qemu_get_ram_ptr(pd & TARGET_PAGE_MASK);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002026 if ((pd & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
2027 /* Normal RAM. */
2028 iotlb = pd & TARGET_PAGE_MASK;
2029 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM)
2030 iotlb |= IO_MEM_NOTDIRTY;
2031 else
2032 iotlb |= IO_MEM_ROM;
2033 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002034 /* IO handlers are currently passed a physical address.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002035 It would be nice to pass an offset from the base address
2036 of that region. This would avoid having to special case RAM,
2037 and avoid full address decoding in every device.
2038 We can't use the high bits of pd for this because
2039 IO_MEM_ROMD uses these as a ram address. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002040 iotlb = (pd & ~TARGET_PAGE_MASK);
2041 if (p) {
2042 iotlb += p->region_offset;
2043 } else {
2044 iotlb += paddr;
2045 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002046 }
2047
2048 code_address = address;
2049 /* Make accesses to pages with watchpoints go via the
2050 watchpoint trap routines. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002051 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002052 if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002053 iotlb = io_mem_watch + paddr;
2054 /* TODO: The memory case can be optimized by not trapping
2055 reads of pages with a write breakpoint. */
2056 address |= TLB_MMIO;
2057 }
2058 }
2059
2060 index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
2061 env->iotlb[mmu_idx][index] = iotlb - vaddr;
2062 te = &env->tlb_table[mmu_idx][index];
2063 te->addend = addend - vaddr;
2064 if (prot & PAGE_READ) {
2065 te->addr_read = address;
2066 } else {
2067 te->addr_read = -1;
2068 }
2069
2070 if (prot & PAGE_EXEC) {
2071 te->addr_code = code_address;
2072 } else {
2073 te->addr_code = -1;
2074 }
2075 if (prot & PAGE_WRITE) {
2076 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM ||
2077 (pd & IO_MEM_ROMD)) {
2078 /* Write access calls the I/O callback. */
2079 te->addr_write = address | TLB_MMIO;
2080 } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
2081 !cpu_physical_memory_is_dirty(pd)) {
2082 te->addr_write = address | TLB_NOTDIRTY;
2083 } else {
2084 te->addr_write = address;
2085 }
2086 } else {
2087 te->addr_write = -1;
2088 }
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -08002089
2090#ifdef CONFIG_MEMCHECK
2091 /*
2092 * If we have memchecker running, we need to make sure that page, cached
2093 * into TLB as the result of this operation will comply with our requirement
2094 * to cause __ld/__stx_mmu being called for memory access on the pages
2095 * containing memory blocks that require access violation checks.
2096 *
2097 * We need to check with memory checker if we should invalidate this page
2098 * iff:
2099 * - Memchecking is enabled.
2100 * - Page that's been cached belongs to the user space.
2101 * - Request to cache this page didn't come from softmmu. We're covered
2102 * there, because after page was cached here we will invalidate it in
2103 * the __ld/__stx_mmu wrapper.
2104 * - Cached page belongs to RAM, not I/O area.
2105 * - Page is cached for read, or write access.
2106 */
2107 if (memcheck_instrument_mmu && mmu_idx == 1 && !is_softmmu &&
2108 (pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
2109 (prot & (PAGE_READ | PAGE_WRITE)) &&
2110 memcheck_is_checked(vaddr & TARGET_PAGE_MASK, TARGET_PAGE_SIZE)) {
2111 if (prot & PAGE_READ) {
2112 te->addr_read ^= TARGET_PAGE_MASK;
2113 }
2114 if (prot & PAGE_WRITE) {
2115 te->addr_write ^= TARGET_PAGE_MASK;
2116 }
2117 }
2118#endif // CONFIG_MEMCHECK
2119
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002120 return ret;
2121}
2122
2123#else
2124
2125void tlb_flush(CPUState *env, int flush_global)
2126{
2127}
2128
2129void tlb_flush_page(CPUState *env, target_ulong addr)
2130{
2131}
2132
2133int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
2134 target_phys_addr_t paddr, int prot,
2135 int mmu_idx, int is_softmmu)
2136{
2137 return 0;
2138}
2139
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002140/*
2141 * Walks guest process memory "regions" one by one
2142 * and calls callback function 'fn' for each region.
2143 */
2144int walk_memory_regions(void *priv,
2145 int (*fn)(void *, unsigned long, unsigned long, unsigned long))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002146{
2147 unsigned long start, end;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002148 PageDesc *p = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002149 int i, j, prot, prot1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002150 int rc = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002151
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002152 start = end = -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002153 prot = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002154
2155 for (i = 0; i <= L1_SIZE; i++) {
2156 p = (i < L1_SIZE) ? l1_map[i] : NULL;
2157 for (j = 0; j < L2_SIZE; j++) {
2158 prot1 = (p == NULL) ? 0 : p[j].flags;
2159 /*
2160 * "region" is one continuous chunk of memory
2161 * that has same protection flags set.
2162 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002163 if (prot1 != prot) {
2164 end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
2165 if (start != -1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002166 rc = (*fn)(priv, start, end, prot);
2167 /* callback can stop iteration by returning != 0 */
2168 if (rc != 0)
2169 return (rc);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002170 }
2171 if (prot1 != 0)
2172 start = end;
2173 else
2174 start = -1;
2175 prot = prot1;
2176 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002177 if (p == NULL)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002178 break;
2179 }
2180 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002181 return (rc);
2182}
2183
2184static int dump_region(void *priv, unsigned long start,
2185 unsigned long end, unsigned long prot)
2186{
2187 FILE *f = (FILE *)priv;
2188
2189 (void) fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
2190 start, end, end - start,
2191 ((prot & PAGE_READ) ? 'r' : '-'),
2192 ((prot & PAGE_WRITE) ? 'w' : '-'),
2193 ((prot & PAGE_EXEC) ? 'x' : '-'));
2194
2195 return (0);
2196}
2197
2198/* dump memory mappings */
2199void page_dump(FILE *f)
2200{
2201 (void) fprintf(f, "%-8s %-8s %-8s %s\n",
2202 "start", "end", "size", "prot");
2203 walk_memory_regions(f, dump_region);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002204}
2205
2206int page_get_flags(target_ulong address)
2207{
2208 PageDesc *p;
2209
2210 p = page_find(address >> TARGET_PAGE_BITS);
2211 if (!p)
2212 return 0;
2213 return p->flags;
2214}
2215
David 'Digit' Turner36411062010-12-22 17:34:53 +01002216/* Modify the flags of a page and invalidate the code if necessary.
2217 The flag PAGE_WRITE_ORG is positioned automatically depending
2218 on PAGE_WRITE. The mmap_lock should already be held. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002219void page_set_flags(target_ulong start, target_ulong end, int flags)
2220{
2221 PageDesc *p;
2222 target_ulong addr;
2223
2224 /* mmap_lock should already be held. */
2225 start = start & TARGET_PAGE_MASK;
2226 end = TARGET_PAGE_ALIGN(end);
2227 if (flags & PAGE_WRITE)
2228 flags |= PAGE_WRITE_ORG;
2229 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2230 p = page_find_alloc(addr >> TARGET_PAGE_BITS);
2231 /* We may be called for host regions that are outside guest
2232 address space. */
2233 if (!p)
2234 return;
2235 /* if the write protection is set, then we invalidate the code
2236 inside */
2237 if (!(p->flags & PAGE_WRITE) &&
2238 (flags & PAGE_WRITE) &&
2239 p->first_tb) {
2240 tb_invalidate_phys_page(addr, 0, NULL);
2241 }
2242 p->flags = flags;
2243 }
2244}
2245
2246int page_check_range(target_ulong start, target_ulong len, int flags)
2247{
2248 PageDesc *p;
2249 target_ulong end;
2250 target_ulong addr;
2251
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002252 if (start + len < start)
2253 /* we've wrapped around */
2254 return -1;
2255
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002256 end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
2257 start = start & TARGET_PAGE_MASK;
2258
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002259 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2260 p = page_find(addr >> TARGET_PAGE_BITS);
2261 if( !p )
2262 return -1;
2263 if( !(p->flags & PAGE_VALID) )
2264 return -1;
2265
2266 if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
2267 return -1;
2268 if (flags & PAGE_WRITE) {
2269 if (!(p->flags & PAGE_WRITE_ORG))
2270 return -1;
2271 /* unprotect the page if it was put read-only because it
2272 contains translated code */
2273 if (!(p->flags & PAGE_WRITE)) {
2274 if (!page_unprotect(addr, 0, NULL))
2275 return -1;
2276 }
2277 return 0;
2278 }
2279 }
2280 return 0;
2281}
2282
2283/* called from signal handler: invalidate the code and unprotect the
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002284 page. Return TRUE if the fault was successfully handled. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002285int page_unprotect(target_ulong address, unsigned long pc, void *puc)
2286{
2287 unsigned int page_index, prot, pindex;
2288 PageDesc *p, *p1;
2289 target_ulong host_start, host_end, addr;
2290
2291 /* Technically this isn't safe inside a signal handler. However we
2292 know this only ever happens in a synchronous SEGV handler, so in
2293 practice it seems to be ok. */
2294 mmap_lock();
2295
2296 host_start = address & qemu_host_page_mask;
2297 page_index = host_start >> TARGET_PAGE_BITS;
2298 p1 = page_find(page_index);
2299 if (!p1) {
2300 mmap_unlock();
2301 return 0;
2302 }
2303 host_end = host_start + qemu_host_page_size;
2304 p = p1;
2305 prot = 0;
2306 for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
2307 prot |= p->flags;
2308 p++;
2309 }
2310 /* if the page was really writable, then we change its
2311 protection back to writable */
2312 if (prot & PAGE_WRITE_ORG) {
2313 pindex = (address - host_start) >> TARGET_PAGE_BITS;
2314 if (!(p1[pindex].flags & PAGE_WRITE)) {
2315 mprotect((void *)g2h(host_start), qemu_host_page_size,
2316 (prot & PAGE_BITS) | PAGE_WRITE);
2317 p1[pindex].flags |= PAGE_WRITE;
2318 /* and since the content will be modified, we must invalidate
2319 the corresponding translated code. */
2320 tb_invalidate_phys_page(address, pc, puc);
2321#ifdef DEBUG_TB_CHECK
2322 tb_invalidate_check(address);
2323#endif
2324 mmap_unlock();
2325 return 1;
2326 }
2327 }
2328 mmap_unlock();
2329 return 0;
2330}
2331
2332static inline void tlb_set_dirty(CPUState *env,
2333 unsigned long addr, target_ulong vaddr)
2334{
2335}
2336#endif /* defined(CONFIG_USER_ONLY) */
2337
2338#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002339
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002340static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002341 ram_addr_t memory, ram_addr_t region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002342static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002343 ram_addr_t orig_memory, ram_addr_t region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002344#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
2345 need_subpage) \
2346 do { \
2347 if (addr > start_addr) \
2348 start_addr2 = 0; \
2349 else { \
2350 start_addr2 = start_addr & ~TARGET_PAGE_MASK; \
2351 if (start_addr2 > 0) \
2352 need_subpage = 1; \
2353 } \
2354 \
2355 if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE) \
2356 end_addr2 = TARGET_PAGE_SIZE - 1; \
2357 else { \
2358 end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
2359 if (end_addr2 < TARGET_PAGE_SIZE - 1) \
2360 need_subpage = 1; \
2361 } \
2362 } while (0)
2363
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002364/* register physical memory.
2365 For RAM, 'size' must be a multiple of the target page size.
2366 If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002367 io memory page. The address used when calling the IO function is
2368 the offset from the start of the region, plus region_offset. Both
2369 start_addr and region_offset are rounded down to a page boundary
2370 before calculating this offset. This should not be a problem unless
2371 the low bits of start_addr and region_offset differ. */
2372void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
2373 ram_addr_t size,
2374 ram_addr_t phys_offset,
2375 ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002376{
2377 target_phys_addr_t addr, end_addr;
2378 PhysPageDesc *p;
2379 CPUState *env;
2380 ram_addr_t orig_size = size;
2381 void *subpage;
2382
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002383 if (kvm_enabled())
2384 kvm_set_phys_mem(start_addr, size, phys_offset);
2385
2386 if (phys_offset == IO_MEM_UNASSIGNED) {
2387 region_offset = start_addr;
2388 }
2389 region_offset &= TARGET_PAGE_MASK;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002390 size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
2391 end_addr = start_addr + (target_phys_addr_t)size;
2392 for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
2393 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2394 if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
2395 ram_addr_t orig_memory = p->phys_offset;
2396 target_phys_addr_t start_addr2, end_addr2;
2397 int need_subpage = 0;
2398
2399 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2400 need_subpage);
2401 if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
2402 if (!(orig_memory & IO_MEM_SUBPAGE)) {
2403 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002404 &p->phys_offset, orig_memory,
2405 p->region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002406 } else {
2407 subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
2408 >> IO_MEM_SHIFT];
2409 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002410 subpage_register(subpage, start_addr2, end_addr2, phys_offset,
2411 region_offset);
2412 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002413 } else {
2414 p->phys_offset = phys_offset;
2415 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2416 (phys_offset & IO_MEM_ROMD))
2417 phys_offset += TARGET_PAGE_SIZE;
2418 }
2419 } else {
2420 p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2421 p->phys_offset = phys_offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002422 p->region_offset = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002423 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002424 (phys_offset & IO_MEM_ROMD)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002425 phys_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002426 } else {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002427 target_phys_addr_t start_addr2, end_addr2;
2428 int need_subpage = 0;
2429
2430 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2431 end_addr2, need_subpage);
2432
2433 if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
2434 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002435 &p->phys_offset, IO_MEM_UNASSIGNED,
2436 addr & TARGET_PAGE_MASK);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002437 subpage_register(subpage, start_addr2, end_addr2,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002438 phys_offset, region_offset);
2439 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002440 }
2441 }
2442 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002443 region_offset += TARGET_PAGE_SIZE;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002444 }
2445
2446 /* since each CPU stores ram addresses in its TLB cache, we must
2447 reset the modified entries */
2448 /* XXX: slow ! */
2449 for(env = first_cpu; env != NULL; env = env->next_cpu) {
2450 tlb_flush(env, 1);
2451 }
2452}
2453
2454/* XXX: temporary until new memory mapping API */
2455ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr)
2456{
2457 PhysPageDesc *p;
2458
2459 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2460 if (!p)
2461 return IO_MEM_UNASSIGNED;
2462 return p->phys_offset;
2463}
2464
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002465void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
2466{
2467 if (kvm_enabled())
2468 kvm_coalesce_mmio_region(addr, size);
2469}
2470
2471void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
2472{
2473 if (kvm_enabled())
2474 kvm_uncoalesce_mmio_region(addr, size);
2475}
2476
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002477ram_addr_t qemu_ram_alloc(ram_addr_t size)
2478{
2479 RAMBlock *new_block;
2480
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002481 size = TARGET_PAGE_ALIGN(size);
2482 new_block = qemu_malloc(sizeof(*new_block));
2483
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002484#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2485 /* XXX S390 KVM requires the topmost vma of the RAM to be < 256GB */
2486 new_block->host = mmap((void*)0x1000000, size, PROT_EXEC|PROT_READ|PROT_WRITE,
2487 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
2488#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002489 new_block->host = qemu_vmalloc(size);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002490#endif
2491#ifdef MADV_MERGEABLE
2492 madvise(new_block->host, size, MADV_MERGEABLE);
2493#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002494 new_block->offset = last_ram_offset;
2495 new_block->length = size;
2496
2497 new_block->next = ram_blocks;
2498 ram_blocks = new_block;
2499
2500 phys_ram_dirty = qemu_realloc(phys_ram_dirty,
2501 (last_ram_offset + size) >> TARGET_PAGE_BITS);
2502 memset(phys_ram_dirty + (last_ram_offset >> TARGET_PAGE_BITS),
2503 0xff, size >> TARGET_PAGE_BITS);
2504
2505 last_ram_offset += size;
2506
2507 if (kvm_enabled())
2508 kvm_setup_guest_memory(new_block->host, size);
2509
2510 return new_block->offset;
2511}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002512
2513void qemu_ram_free(ram_addr_t addr)
2514{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002515 /* TODO: implement this. */
2516}
2517
2518/* Return a host pointer to ram allocated with qemu_ram_alloc.
2519 With the exception of the softmmu code in this file, this should
2520 only be used for local memory (e.g. video ram) that the device owns,
2521 and knows it isn't going to access beyond the end of the block.
2522
2523 It should not be used for general purpose DMA.
2524 Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
2525 */
2526void *qemu_get_ram_ptr(ram_addr_t addr)
2527{
2528 RAMBlock *prev;
2529 RAMBlock **prevp;
2530 RAMBlock *block;
2531
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002532 prev = NULL;
2533 prevp = &ram_blocks;
2534 block = ram_blocks;
2535 while (block && (block->offset > addr
2536 || block->offset + block->length <= addr)) {
2537 if (prev)
2538 prevp = &prev->next;
2539 prev = block;
2540 block = block->next;
2541 }
2542 if (!block) {
2543 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2544 abort();
2545 }
2546 /* Move this entry to to start of the list. */
2547 if (prev) {
2548 prev->next = block->next;
2549 block->next = *prevp;
2550 *prevp = block;
2551 }
2552 return block->host + (addr - block->offset);
2553}
2554
2555/* Some of the softmmu routines need to translate from a host pointer
2556 (typically a TLB entry) back to a ram offset. */
2557ram_addr_t qemu_ram_addr_from_host(void *ptr)
2558{
2559 RAMBlock *prev;
2560 RAMBlock **prevp;
2561 RAMBlock *block;
2562 uint8_t *host = ptr;
2563
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002564 prev = NULL;
2565 prevp = &ram_blocks;
2566 block = ram_blocks;
2567 while (block && (block->host > host
2568 || block->host + block->length <= host)) {
2569 if (prev)
2570 prevp = &prev->next;
2571 prev = block;
2572 block = block->next;
2573 }
2574 if (!block) {
2575 fprintf(stderr, "Bad ram pointer %p\n", ptr);
2576 abort();
2577 }
2578 return block->offset + (host - block->host);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002579}
2580
2581static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
2582{
2583#ifdef DEBUG_UNASSIGNED
2584 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2585#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002586#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002587 do_unassigned_access(addr, 0, 0, 0, 1);
2588#endif
2589 return 0;
2590}
2591
2592static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr)
2593{
2594#ifdef DEBUG_UNASSIGNED
2595 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2596#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002597#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002598 do_unassigned_access(addr, 0, 0, 0, 2);
2599#endif
2600 return 0;
2601}
2602
2603static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr)
2604{
2605#ifdef DEBUG_UNASSIGNED
2606 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2607#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002608#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002609 do_unassigned_access(addr, 0, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002610#endif
2611 return 0;
2612}
2613
2614static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
2615{
2616#ifdef DEBUG_UNASSIGNED
2617 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2618#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002619#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002620 do_unassigned_access(addr, 1, 0, 0, 1);
2621#endif
2622}
2623
2624static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
2625{
2626#ifdef DEBUG_UNASSIGNED
2627 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2628#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002629#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002630 do_unassigned_access(addr, 1, 0, 0, 2);
2631#endif
2632}
2633
2634static void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
2635{
2636#ifdef DEBUG_UNASSIGNED
2637 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2638#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002639#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002640 do_unassigned_access(addr, 1, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002641#endif
2642}
2643
David 'Digit' Turner36411062010-12-22 17:34:53 +01002644static CPUReadMemoryFunc * const unassigned_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002645 unassigned_mem_readb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002646 unassigned_mem_readw,
2647 unassigned_mem_readl,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002648};
2649
David 'Digit' Turner36411062010-12-22 17:34:53 +01002650static CPUWriteMemoryFunc * const unassigned_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002651 unassigned_mem_writeb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002652 unassigned_mem_writew,
2653 unassigned_mem_writel,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002654};
2655
2656static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr,
2657 uint32_t val)
2658{
2659 int dirty_flags;
2660 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2661 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2662#if !defined(CONFIG_USER_ONLY)
2663 tb_invalidate_phys_page_fast(ram_addr, 1);
2664 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2665#endif
2666 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002667 stb_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002668 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2669 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2670 /* we remove the notdirty callback only if the code has been
2671 flushed */
2672 if (dirty_flags == 0xff)
2673 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2674}
2675
2676static void notdirty_mem_writew(void *opaque, target_phys_addr_t ram_addr,
2677 uint32_t val)
2678{
2679 int dirty_flags;
2680 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2681 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2682#if !defined(CONFIG_USER_ONLY)
2683 tb_invalidate_phys_page_fast(ram_addr, 2);
2684 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2685#endif
2686 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002687 stw_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002688 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2689 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2690 /* we remove the notdirty callback only if the code has been
2691 flushed */
2692 if (dirty_flags == 0xff)
2693 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2694}
2695
2696static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr,
2697 uint32_t val)
2698{
2699 int dirty_flags;
2700 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2701 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2702#if !defined(CONFIG_USER_ONLY)
2703 tb_invalidate_phys_page_fast(ram_addr, 4);
2704 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2705#endif
2706 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002707 stl_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002708 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2709 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2710 /* we remove the notdirty callback only if the code has been
2711 flushed */
2712 if (dirty_flags == 0xff)
2713 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2714}
2715
David 'Digit' Turner36411062010-12-22 17:34:53 +01002716static CPUReadMemoryFunc * const error_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002717 NULL, /* never used */
2718 NULL, /* never used */
2719 NULL, /* never used */
2720};
2721
David 'Digit' Turner36411062010-12-22 17:34:53 +01002722static CPUWriteMemoryFunc * const notdirty_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002723 notdirty_mem_writeb,
2724 notdirty_mem_writew,
2725 notdirty_mem_writel,
2726};
2727
2728/* Generate a debug exception if a watchpoint has been hit. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002729static void check_watchpoint(int offset, int len_mask, int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002730{
2731 CPUState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002732 target_ulong pc, cs_base;
2733 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002734 target_ulong vaddr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002735 CPUWatchpoint *wp;
2736 int cpu_flags;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002737
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002738 if (env->watchpoint_hit) {
2739 /* We re-entered the check after replacing the TB. Now raise
2740 * the debug interrupt so that is will trigger after the
2741 * current instruction. */
2742 cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2743 return;
2744 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002745 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002746 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002747 if ((vaddr == (wp->vaddr & len_mask) ||
2748 (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
2749 wp->flags |= BP_WATCHPOINT_HIT;
2750 if (!env->watchpoint_hit) {
2751 env->watchpoint_hit = wp;
2752 tb = tb_find_pc(env->mem_io_pc);
2753 if (!tb) {
2754 cpu_abort(env, "check_watchpoint: could not find TB for "
2755 "pc=%p", (void *)env->mem_io_pc);
2756 }
2757 cpu_restore_state(tb, env, env->mem_io_pc, NULL);
2758 tb_phys_invalidate(tb, -1);
2759 if (wp->flags & BP_STOP_BEFORE_ACCESS) {
2760 env->exception_index = EXCP_DEBUG;
2761 } else {
2762 cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
2763 tb_gen_code(env, pc, cs_base, cpu_flags, 1);
2764 }
2765 cpu_resume_from_signal(env, NULL);
2766 }
2767 } else {
2768 wp->flags &= ~BP_WATCHPOINT_HIT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002769 }
2770 }
2771}
2772
2773/* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
2774 so these check for a hit then pass through to the normal out-of-line
2775 phys routines. */
2776static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
2777{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002778 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002779 return ldub_phys(addr);
2780}
2781
2782static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
2783{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002784 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002785 return lduw_phys(addr);
2786}
2787
2788static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
2789{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002790 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002791 return ldl_phys(addr);
2792}
2793
2794static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
2795 uint32_t val)
2796{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002797 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002798 stb_phys(addr, val);
2799}
2800
2801static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
2802 uint32_t val)
2803{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002804 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002805 stw_phys(addr, val);
2806}
2807
2808static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
2809 uint32_t val)
2810{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002811 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002812 stl_phys(addr, val);
2813}
2814
David 'Digit' Turner36411062010-12-22 17:34:53 +01002815static CPUReadMemoryFunc * const watch_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002816 watch_mem_readb,
2817 watch_mem_readw,
2818 watch_mem_readl,
2819};
2820
David 'Digit' Turner36411062010-12-22 17:34:53 +01002821static CPUWriteMemoryFunc * const watch_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002822 watch_mem_writeb,
2823 watch_mem_writew,
2824 watch_mem_writel,
2825};
2826
2827static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr,
2828 unsigned int len)
2829{
2830 uint32_t ret;
2831 unsigned int idx;
2832
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002833 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002834#if defined(DEBUG_SUBPAGE)
2835 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
2836 mmio, len, addr, idx);
2837#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002838 ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len],
2839 addr + mmio->region_offset[idx][0][len]);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002840
2841 return ret;
2842}
2843
2844static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
2845 uint32_t value, unsigned int len)
2846{
2847 unsigned int idx;
2848
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002849 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002850#if defined(DEBUG_SUBPAGE)
2851 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
2852 mmio, len, addr, idx, value);
2853#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002854 (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len],
2855 addr + mmio->region_offset[idx][1][len],
2856 value);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002857}
2858
2859static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
2860{
2861#if defined(DEBUG_SUBPAGE)
2862 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2863#endif
2864
2865 return subpage_readlen(opaque, addr, 0);
2866}
2867
2868static void subpage_writeb (void *opaque, target_phys_addr_t addr,
2869 uint32_t value)
2870{
2871#if defined(DEBUG_SUBPAGE)
2872 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2873#endif
2874 subpage_writelen(opaque, addr, value, 0);
2875}
2876
2877static uint32_t subpage_readw (void *opaque, target_phys_addr_t addr)
2878{
2879#if defined(DEBUG_SUBPAGE)
2880 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2881#endif
2882
2883 return subpage_readlen(opaque, addr, 1);
2884}
2885
2886static void subpage_writew (void *opaque, target_phys_addr_t addr,
2887 uint32_t value)
2888{
2889#if defined(DEBUG_SUBPAGE)
2890 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2891#endif
2892 subpage_writelen(opaque, addr, value, 1);
2893}
2894
2895static uint32_t subpage_readl (void *opaque, target_phys_addr_t addr)
2896{
2897#if defined(DEBUG_SUBPAGE)
2898 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2899#endif
2900
2901 return subpage_readlen(opaque, addr, 2);
2902}
2903
2904static void subpage_writel (void *opaque,
2905 target_phys_addr_t addr, uint32_t value)
2906{
2907#if defined(DEBUG_SUBPAGE)
2908 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2909#endif
2910 subpage_writelen(opaque, addr, value, 2);
2911}
2912
David 'Digit' Turner36411062010-12-22 17:34:53 +01002913static CPUReadMemoryFunc * const subpage_read[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002914 &subpage_readb,
2915 &subpage_readw,
2916 &subpage_readl,
2917};
2918
David 'Digit' Turner36411062010-12-22 17:34:53 +01002919static CPUWriteMemoryFunc * const subpage_write[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002920 &subpage_writeb,
2921 &subpage_writew,
2922 &subpage_writel,
2923};
2924
2925static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002926 ram_addr_t memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002927{
2928 int idx, eidx;
2929 unsigned int i;
2930
2931 if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
2932 return -1;
2933 idx = SUBPAGE_IDX(start);
2934 eidx = SUBPAGE_IDX(end);
2935#if defined(DEBUG_SUBPAGE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002936 printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002937 mmio, start, end, idx, eidx, memory);
2938#endif
2939 memory >>= IO_MEM_SHIFT;
2940 for (; idx <= eidx; idx++) {
2941 for (i = 0; i < 4; i++) {
2942 if (io_mem_read[memory][i]) {
2943 mmio->mem_read[idx][i] = &io_mem_read[memory][i];
2944 mmio->opaque[idx][0][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002945 mmio->region_offset[idx][0][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002946 }
2947 if (io_mem_write[memory][i]) {
2948 mmio->mem_write[idx][i] = &io_mem_write[memory][i];
2949 mmio->opaque[idx][1][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002950 mmio->region_offset[idx][1][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002951 }
2952 }
2953 }
2954
2955 return 0;
2956}
2957
2958static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002959 ram_addr_t orig_memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002960{
2961 subpage_t *mmio;
2962 int subpage_memory;
2963
2964 mmio = qemu_mallocz(sizeof(subpage_t));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002965
2966 mmio->base = base;
2967 subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002968#if defined(DEBUG_SUBPAGE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002969 printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
2970 mmio, base, TARGET_PAGE_SIZE, subpage_memory);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002971#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002972 *phys = subpage_memory | IO_MEM_SUBPAGE;
2973 subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
2974 region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002975
2976 return mmio;
2977}
2978
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002979static int get_free_io_mem_idx(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002980{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002981 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002982
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002983 for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
2984 if (!io_mem_used[i]) {
2985 io_mem_used[i] = 1;
2986 return i;
2987 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002988 fprintf(stderr, "RAN out out io_mem_idx, max %d !\n", IO_MEM_NB_ENTRIES);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002989 return -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002990}
2991
2992/* mem_read and mem_write are arrays of functions containing the
2993 function to access byte (index 0), word (index 1) and dword (index
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002994 2). Functions can be omitted with a NULL function pointer.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002995 If io_index is non zero, the corresponding io zone is
2996 modified. If it is zero, a new io zone is allocated. The return
2997 value can be used with cpu_register_physical_memory(). (-1) is
2998 returned if error. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002999static int cpu_register_io_memory_fixed(int io_index,
David 'Digit' Turner36411062010-12-22 17:34:53 +01003000 CPUReadMemoryFunc * const *mem_read,
3001 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003002 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003003{
3004 int i, subwidth = 0;
3005
3006 if (io_index <= 0) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003007 io_index = get_free_io_mem_idx();
3008 if (io_index == -1)
3009 return io_index;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003010 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003011 io_index >>= IO_MEM_SHIFT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003012 if (io_index >= IO_MEM_NB_ENTRIES)
3013 return -1;
3014 }
3015
3016 for(i = 0;i < 3; i++) {
3017 if (!mem_read[i] || !mem_write[i])
3018 subwidth = IO_MEM_SUBWIDTH;
3019 io_mem_read[io_index][i] = mem_read[i];
3020 io_mem_write[io_index][i] = mem_write[i];
3021 }
3022 io_mem_opaque[io_index] = opaque;
3023 return (io_index << IO_MEM_SHIFT) | subwidth;
3024}
3025
David 'Digit' Turner36411062010-12-22 17:34:53 +01003026int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
3027 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003028 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003029{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003030 return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003031}
3032
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003033void cpu_unregister_io_memory(int io_table_address)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003034{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003035 int i;
3036 int io_index = io_table_address >> IO_MEM_SHIFT;
3037
3038 for (i=0;i < 3; i++) {
3039 io_mem_read[io_index][i] = unassigned_mem_read[i];
3040 io_mem_write[io_index][i] = unassigned_mem_write[i];
3041 }
3042 io_mem_opaque[io_index] = NULL;
3043 io_mem_used[io_index] = 0;
3044}
3045
3046static void io_mem_init(void)
3047{
3048 int i;
3049
3050 cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read, unassigned_mem_write, NULL);
3051 cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read, unassigned_mem_write, NULL);
3052 cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read, notdirty_mem_write, NULL);
3053 for (i=0; i<5; i++)
3054 io_mem_used[i] = 1;
3055
3056 io_mem_watch = cpu_register_io_memory(watch_mem_read,
3057 watch_mem_write, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003058}
3059
3060#endif /* !defined(CONFIG_USER_ONLY) */
3061
3062/* physical memory access (slow version, mainly for debug) */
3063#if defined(CONFIG_USER_ONLY)
3064void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
3065 int len, int is_write)
3066{
3067 int l, flags;
3068 target_ulong page;
3069 void * p;
3070
3071 while (len > 0) {
3072 page = addr & TARGET_PAGE_MASK;
3073 l = (page + TARGET_PAGE_SIZE) - addr;
3074 if (l > len)
3075 l = len;
3076 flags = page_get_flags(page);
3077 if (!(flags & PAGE_VALID))
3078 return;
3079 if (is_write) {
3080 if (!(flags & PAGE_WRITE))
3081 return;
3082 /* XXX: this code should not depend on lock_user */
3083 if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
3084 /* FIXME - should this return an error rather than just fail? */
3085 return;
3086 memcpy(p, buf, l);
3087 unlock_user(p, addr, l);
3088 } else {
3089 if (!(flags & PAGE_READ))
3090 return;
3091 /* XXX: this code should not depend on lock_user */
3092 if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
3093 /* FIXME - should this return an error rather than just fail? */
3094 return;
3095 memcpy(buf, p, l);
3096 unlock_user(p, addr, 0);
3097 }
3098 len -= l;
3099 buf += l;
3100 addr += l;
3101 }
3102}
3103
3104#else
3105void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
3106 int len, int is_write)
3107{
3108 int l, io_index;
3109 uint8_t *ptr;
3110 uint32_t val;
3111 target_phys_addr_t page;
3112 unsigned long pd;
3113 PhysPageDesc *p;
3114
3115 while (len > 0) {
3116 page = addr & TARGET_PAGE_MASK;
3117 l = (page + TARGET_PAGE_SIZE) - addr;
3118 if (l > len)
3119 l = len;
3120 p = phys_page_find(page >> TARGET_PAGE_BITS);
3121 if (!p) {
3122 pd = IO_MEM_UNASSIGNED;
3123 } else {
3124 pd = p->phys_offset;
3125 }
3126
3127 if (is_write) {
3128 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003129 target_phys_addr_t addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003130 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003131 if (p)
3132 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003133 /* XXX: could force cpu_single_env to NULL to avoid
3134 potential bugs */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003135 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003136 /* 32 bit write access */
3137 val = ldl_p(buf);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003138 io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003139 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003140 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003141 /* 16 bit write access */
3142 val = lduw_p(buf);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003143 io_mem_write[io_index][1](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003144 l = 2;
3145 } else {
3146 /* 8 bit write access */
3147 val = ldub_p(buf);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003148 io_mem_write[io_index][0](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003149 l = 1;
3150 }
3151 } else {
3152 unsigned long addr1;
3153 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3154 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003155 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003156 memcpy(ptr, buf, l);
3157 if (!cpu_physical_memory_is_dirty(addr1)) {
3158 /* invalidate code */
3159 tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
3160 /* set dirty bit */
3161 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3162 (0xff & ~CODE_DIRTY_FLAG);
3163 }
3164 }
3165 } else {
3166 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3167 !(pd & IO_MEM_ROMD)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003168 target_phys_addr_t addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003169 /* I/O case */
3170 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003171 if (p)
3172 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3173 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003174 /* 32 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003175 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003176 stl_p(buf, val);
3177 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003178 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003179 /* 16 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003180 val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003181 stw_p(buf, val);
3182 l = 2;
3183 } else {
3184 /* 8 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003185 val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003186 stb_p(buf, val);
3187 l = 1;
3188 }
3189 } else {
3190 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003191 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003192 (addr & ~TARGET_PAGE_MASK);
3193 memcpy(buf, ptr, l);
3194 }
3195 }
3196 len -= l;
3197 buf += l;
3198 addr += l;
3199 }
3200}
3201
3202/* used for ROM loading : can write in RAM and ROM */
3203void cpu_physical_memory_write_rom(target_phys_addr_t addr,
3204 const uint8_t *buf, int len)
3205{
3206 int l;
3207 uint8_t *ptr;
3208 target_phys_addr_t page;
3209 unsigned long pd;
3210 PhysPageDesc *p;
3211
3212 while (len > 0) {
3213 page = addr & TARGET_PAGE_MASK;
3214 l = (page + TARGET_PAGE_SIZE) - addr;
3215 if (l > len)
3216 l = len;
3217 p = phys_page_find(page >> TARGET_PAGE_BITS);
3218 if (!p) {
3219 pd = IO_MEM_UNASSIGNED;
3220 } else {
3221 pd = p->phys_offset;
3222 }
3223
3224 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
3225 (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
3226 !(pd & IO_MEM_ROMD)) {
3227 /* do nothing */
3228 } else {
3229 unsigned long addr1;
3230 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3231 /* ROM/RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003232 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003233 memcpy(ptr, buf, l);
3234 }
3235 len -= l;
3236 buf += l;
3237 addr += l;
3238 }
3239}
3240
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003241typedef struct {
3242 void *buffer;
3243 target_phys_addr_t addr;
3244 target_phys_addr_t len;
3245} BounceBuffer;
3246
3247static BounceBuffer bounce;
3248
3249typedef struct MapClient {
3250 void *opaque;
3251 void (*callback)(void *opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003252 QLIST_ENTRY(MapClient) link;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003253} MapClient;
3254
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003255static QLIST_HEAD(map_client_list, MapClient) map_client_list
3256 = QLIST_HEAD_INITIALIZER(map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003257
3258void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
3259{
3260 MapClient *client = qemu_malloc(sizeof(*client));
3261
3262 client->opaque = opaque;
3263 client->callback = callback;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003264 QLIST_INSERT_HEAD(&map_client_list, client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003265 return client;
3266}
3267
3268void cpu_unregister_map_client(void *_client)
3269{
3270 MapClient *client = (MapClient *)_client;
3271
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003272 QLIST_REMOVE(client, link);
3273 qemu_free(client);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003274}
3275
3276static void cpu_notify_map_clients(void)
3277{
3278 MapClient *client;
3279
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003280 while (!QLIST_EMPTY(&map_client_list)) {
3281 client = QLIST_FIRST(&map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003282 client->callback(client->opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003283 QLIST_REMOVE(client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003284 }
3285}
3286
3287/* Map a physical memory region into a host virtual address.
3288 * May map a subset of the requested range, given by and returned in *plen.
3289 * May return NULL if resources needed to perform the mapping are exhausted.
3290 * Use only for reads OR writes - not for read-modify-write operations.
3291 * Use cpu_register_map_client() to know when retrying the map operation is
3292 * likely to succeed.
3293 */
3294void *cpu_physical_memory_map(target_phys_addr_t addr,
3295 target_phys_addr_t *plen,
3296 int is_write)
3297{
3298 target_phys_addr_t len = *plen;
3299 target_phys_addr_t done = 0;
3300 int l;
3301 uint8_t *ret = NULL;
3302 uint8_t *ptr;
3303 target_phys_addr_t page;
3304 unsigned long pd;
3305 PhysPageDesc *p;
3306 unsigned long addr1;
3307
3308 while (len > 0) {
3309 page = addr & TARGET_PAGE_MASK;
3310 l = (page + TARGET_PAGE_SIZE) - addr;
3311 if (l > len)
3312 l = len;
3313 p = phys_page_find(page >> TARGET_PAGE_BITS);
3314 if (!p) {
3315 pd = IO_MEM_UNASSIGNED;
3316 } else {
3317 pd = p->phys_offset;
3318 }
3319
3320 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3321 if (done || bounce.buffer) {
3322 break;
3323 }
3324 bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
3325 bounce.addr = addr;
3326 bounce.len = l;
3327 if (!is_write) {
3328 cpu_physical_memory_rw(addr, bounce.buffer, l, 0);
3329 }
3330 ptr = bounce.buffer;
3331 } else {
3332 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3333 ptr = qemu_get_ram_ptr(addr1);
3334 }
3335 if (!done) {
3336 ret = ptr;
3337 } else if (ret + done != ptr) {
3338 break;
3339 }
3340
3341 len -= l;
3342 addr += l;
3343 done += l;
3344 }
3345 *plen = done;
3346 return ret;
3347}
3348
3349/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
3350 * Will also mark the memory as dirty if is_write == 1. access_len gives
3351 * the amount of memory that was actually read or written by the caller.
3352 */
3353void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
3354 int is_write, target_phys_addr_t access_len)
3355{
3356 if (buffer != bounce.buffer) {
3357 if (is_write) {
3358 ram_addr_t addr1 = qemu_ram_addr_from_host(buffer);
3359 while (access_len) {
3360 unsigned l;
3361 l = TARGET_PAGE_SIZE;
3362 if (l > access_len)
3363 l = access_len;
3364 if (!cpu_physical_memory_is_dirty(addr1)) {
3365 /* invalidate code */
3366 tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
3367 /* set dirty bit */
3368 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3369 (0xff & ~CODE_DIRTY_FLAG);
3370 }
3371 addr1 += l;
3372 access_len -= l;
3373 }
3374 }
3375 return;
3376 }
3377 if (is_write) {
3378 cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
3379 }
3380 qemu_free(bounce.buffer);
3381 bounce.buffer = NULL;
3382 cpu_notify_map_clients();
3383}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003384
3385/* warning: addr must be aligned */
3386uint32_t ldl_phys(target_phys_addr_t addr)
3387{
3388 int io_index;
3389 uint8_t *ptr;
3390 uint32_t val;
3391 unsigned long pd;
3392 PhysPageDesc *p;
3393
3394 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3395 if (!p) {
3396 pd = IO_MEM_UNASSIGNED;
3397 } else {
3398 pd = p->phys_offset;
3399 }
3400
3401 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3402 !(pd & IO_MEM_ROMD)) {
3403 /* I/O case */
3404 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003405 if (p)
3406 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003407 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3408 } else {
3409 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003410 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003411 (addr & ~TARGET_PAGE_MASK);
3412 val = ldl_p(ptr);
3413 }
3414 return val;
3415}
3416
3417/* warning: addr must be aligned */
3418uint64_t ldq_phys(target_phys_addr_t addr)
3419{
3420 int io_index;
3421 uint8_t *ptr;
3422 uint64_t val;
3423 unsigned long pd;
3424 PhysPageDesc *p;
3425
3426 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3427 if (!p) {
3428 pd = IO_MEM_UNASSIGNED;
3429 } else {
3430 pd = p->phys_offset;
3431 }
3432
3433 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3434 !(pd & IO_MEM_ROMD)) {
3435 /* I/O case */
3436 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003437 if (p)
3438 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003439#ifdef TARGET_WORDS_BIGENDIAN
3440 val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
3441 val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
3442#else
3443 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3444 val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
3445#endif
3446 } else {
3447 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003448 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003449 (addr & ~TARGET_PAGE_MASK);
3450 val = ldq_p(ptr);
3451 }
3452 return val;
3453}
3454
3455/* XXX: optimize */
3456uint32_t ldub_phys(target_phys_addr_t addr)
3457{
3458 uint8_t val;
3459 cpu_physical_memory_read(addr, &val, 1);
3460 return val;
3461}
3462
3463/* XXX: optimize */
3464uint32_t lduw_phys(target_phys_addr_t addr)
3465{
3466 uint16_t val;
3467 cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
3468 return tswap16(val);
3469}
3470
3471/* warning: addr must be aligned. The ram page is not masked as dirty
3472 and the code inside is not invalidated. It is useful if the dirty
3473 bits are used to track modified PTEs */
3474void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
3475{
3476 int io_index;
3477 uint8_t *ptr;
3478 unsigned long pd;
3479 PhysPageDesc *p;
3480
3481 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3482 if (!p) {
3483 pd = IO_MEM_UNASSIGNED;
3484 } else {
3485 pd = p->phys_offset;
3486 }
3487
3488 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3489 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003490 if (p)
3491 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003492 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3493 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003494 unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3495 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003496 stl_p(ptr, val);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003497
3498 if (unlikely(in_migration)) {
3499 if (!cpu_physical_memory_is_dirty(addr1)) {
3500 /* invalidate code */
3501 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3502 /* set dirty bit */
3503 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3504 (0xff & ~CODE_DIRTY_FLAG);
3505 }
3506 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003507 }
3508}
3509
3510void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
3511{
3512 int io_index;
3513 uint8_t *ptr;
3514 unsigned long pd;
3515 PhysPageDesc *p;
3516
3517 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3518 if (!p) {
3519 pd = IO_MEM_UNASSIGNED;
3520 } else {
3521 pd = p->phys_offset;
3522 }
3523
3524 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3525 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003526 if (p)
3527 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003528#ifdef TARGET_WORDS_BIGENDIAN
3529 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
3530 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
3531#else
3532 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3533 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
3534#endif
3535 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003536 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003537 (addr & ~TARGET_PAGE_MASK);
3538 stq_p(ptr, val);
3539 }
3540}
3541
3542/* warning: addr must be aligned */
3543void stl_phys(target_phys_addr_t addr, uint32_t val)
3544{
3545 int io_index;
3546 uint8_t *ptr;
3547 unsigned long pd;
3548 PhysPageDesc *p;
3549
3550 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3551 if (!p) {
3552 pd = IO_MEM_UNASSIGNED;
3553 } else {
3554 pd = p->phys_offset;
3555 }
3556
3557 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3558 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003559 if (p)
3560 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003561 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3562 } else {
3563 unsigned long addr1;
3564 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3565 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003566 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003567 stl_p(ptr, val);
3568 if (!cpu_physical_memory_is_dirty(addr1)) {
3569 /* invalidate code */
3570 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3571 /* set dirty bit */
3572 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3573 (0xff & ~CODE_DIRTY_FLAG);
3574 }
3575 }
3576}
3577
3578/* XXX: optimize */
3579void stb_phys(target_phys_addr_t addr, uint32_t val)
3580{
3581 uint8_t v = val;
3582 cpu_physical_memory_write(addr, &v, 1);
3583}
3584
3585/* XXX: optimize */
3586void stw_phys(target_phys_addr_t addr, uint32_t val)
3587{
3588 uint16_t v = tswap16(val);
3589 cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
3590}
3591
3592/* XXX: optimize */
3593void stq_phys(target_phys_addr_t addr, uint64_t val)
3594{
3595 val = tswap64(val);
3596 cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
3597}
3598
3599#endif
3600
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003601/* virtual memory access for debug (includes writing to ROM) */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003602int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
3603 uint8_t *buf, int len, int is_write)
3604{
3605 int l;
3606 target_phys_addr_t phys_addr;
3607 target_ulong page;
3608
3609 while (len > 0) {
3610 page = addr & TARGET_PAGE_MASK;
3611 phys_addr = cpu_get_phys_page_debug(env, page);
3612 /* if no physical page mapped, return an error */
3613 if (phys_addr == -1)
3614 return -1;
3615 l = (page + TARGET_PAGE_SIZE) - addr;
3616 if (l > len)
3617 l = len;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003618 phys_addr += (addr & ~TARGET_PAGE_MASK);
3619#if !defined(CONFIG_USER_ONLY)
3620 if (is_write)
3621 cpu_physical_memory_write_rom(phys_addr, buf, l);
3622 else
3623#endif
3624 cpu_physical_memory_rw(phys_addr, buf, l, is_write);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003625 len -= l;
3626 buf += l;
3627 addr += l;
3628 }
3629 return 0;
3630}
3631
3632/* in deterministic execution mode, instructions doing device I/Os
3633 must be at the end of the TB */
3634void cpu_io_recompile(CPUState *env, void *retaddr)
3635{
3636 TranslationBlock *tb;
3637 uint32_t n, cflags;
3638 target_ulong pc, cs_base;
3639 uint64_t flags;
3640
3641 tb = tb_find_pc((unsigned long)retaddr);
3642 if (!tb) {
David 'Digit' Turner36411062010-12-22 17:34:53 +01003643 cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003644 retaddr);
3645 }
3646 n = env->icount_decr.u16.low + tb->icount;
3647 cpu_restore_state(tb, env, (unsigned long)retaddr, NULL);
3648 /* Calculate how many instructions had been executed before the fault
3649 occurred. */
3650 n = n - env->icount_decr.u16.low;
3651 /* Generate a new TB ending on the I/O insn. */
3652 n++;
3653 /* On MIPS and SH, delay slot instructions can only be restarted if
3654 they were already the first instruction in the TB. If this is not
3655 the first instruction in a TB then re-execute the preceding
3656 branch. */
3657#if defined(TARGET_MIPS)
3658 if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) {
3659 env->active_tc.PC -= 4;
3660 env->icount_decr.u16.low++;
3661 env->hflags &= ~MIPS_HFLAG_BMASK;
3662 }
3663#elif defined(TARGET_SH4)
3664 if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
3665 && n > 1) {
3666 env->pc -= 2;
3667 env->icount_decr.u16.low++;
3668 env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
3669 }
3670#endif
3671 /* This should never happen. */
3672 if (n > CF_COUNT_MASK)
3673 cpu_abort(env, "TB too big during recompile");
3674
3675 cflags = n | CF_LAST_IO;
3676 pc = tb->pc;
3677 cs_base = tb->cs_base;
3678 flags = tb->flags;
3679 tb_phys_invalidate(tb, -1);
3680 /* FIXME: In theory this could raise an exception. In practice
3681 we have already translated the block once so it's probably ok. */
3682 tb_gen_code(env, pc, cs_base, flags, cflags);
3683 /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
3684 the first in the TB) then we end up generating a whole new TB and
3685 repeating the fault, which is horribly inefficient.
3686 Better would be to execute just this insn uncached, or generate a
3687 second new TB. */
3688 cpu_resume_from_signal(env, NULL);
3689}
3690
David 'Digit' Turner36411062010-12-22 17:34:53 +01003691#if !defined(CONFIG_USER_ONLY)
3692
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003693void dump_exec_info(FILE *f,
3694 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
3695{
3696 int i, target_code_size, max_target_code_size;
3697 int direct_jmp_count, direct_jmp2_count, cross_page;
3698 TranslationBlock *tb;
3699
3700 target_code_size = 0;
3701 max_target_code_size = 0;
3702 cross_page = 0;
3703 direct_jmp_count = 0;
3704 direct_jmp2_count = 0;
3705 for(i = 0; i < nb_tbs; i++) {
3706 tb = &tbs[i];
3707 target_code_size += tb->size;
3708 if (tb->size > max_target_code_size)
3709 max_target_code_size = tb->size;
3710 if (tb->page_addr[1] != -1)
3711 cross_page++;
3712 if (tb->tb_next_offset[0] != 0xffff) {
3713 direct_jmp_count++;
3714 if (tb->tb_next_offset[1] != 0xffff) {
3715 direct_jmp2_count++;
3716 }
3717 }
3718 }
3719 /* XXX: avoid using doubles ? */
3720 cpu_fprintf(f, "Translation buffer state:\n");
3721 cpu_fprintf(f, "gen code size %ld/%ld\n",
3722 code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size);
David 'Digit' Turner36411062010-12-22 17:34:53 +01003723 cpu_fprintf(f, "TB count %d/%d\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003724 nb_tbs, code_gen_max_blocks);
3725 cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
3726 nb_tbs ? target_code_size / nb_tbs : 0,
3727 max_target_code_size);
3728 cpu_fprintf(f, "TB avg host size %d bytes (expansion ratio: %0.1f)\n",
3729 nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
3730 target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
3731 cpu_fprintf(f, "cross page TB count %d (%d%%)\n",
3732 cross_page,
3733 nb_tbs ? (cross_page * 100) / nb_tbs : 0);
3734 cpu_fprintf(f, "direct jump count %d (%d%%) (2 jumps=%d %d%%)\n",
3735 direct_jmp_count,
3736 nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
3737 direct_jmp2_count,
3738 nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
3739 cpu_fprintf(f, "\nStatistics:\n");
3740 cpu_fprintf(f, "TB flush count %d\n", tb_flush_count);
3741 cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
3742 cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count);
3743 tcg_dump_info(f, cpu_fprintf);
3744}
3745
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003746#define MMUSUFFIX _cmmu
3747#define GETPC() NULL
3748#define env cpu_single_env
3749#define SOFTMMU_CODE_ACCESS
3750
3751#define SHIFT 0
3752#include "softmmu_template.h"
3753
3754#define SHIFT 1
3755#include "softmmu_template.h"
3756
3757#define SHIFT 2
3758#include "softmmu_template.h"
3759
3760#define SHIFT 3
3761#include "softmmu_template.h"
3762
3763#undef env
3764
3765#endif