blob: a81df7d147df34fd435aff8f9f4778016a84b67a [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
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001568 spin_lock(&interrupt_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001569 tb = env->current_tb;
1570 /* if the cpu is currently executing code, we must unlink it and
1571 all the potentially executing TB */
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001572 if (tb) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001573 env->current_tb = NULL;
1574 tb_reset_jump_recursive(tb);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001575 }
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001576 spin_unlock(&interrupt_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001577}
1578
1579/* mask must never be zero, except for A20 change call */
1580void cpu_interrupt(CPUState *env, int mask)
1581{
1582 int old_mask;
1583
1584 old_mask = env->interrupt_request;
1585 env->interrupt_request |= mask;
1586
1587#ifndef CONFIG_USER_ONLY
1588 /*
1589 * If called from iothread context, wake the target cpu in
1590 * case its halted.
1591 */
1592 if (!qemu_cpu_self(env)) {
1593 qemu_cpu_kick(env);
1594 return;
1595 }
1596#endif
1597
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001598 if (use_icount) {
1599 env->icount_decr.u16.high = 0xffff;
1600#ifndef CONFIG_USER_ONLY
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001601 if (!can_do_io(env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001602 && (mask & ~old_mask) != 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001603 cpu_abort(env, "Raised interrupt while not in I/O function");
1604 }
1605#endif
1606 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001607 cpu_unlink_tb(env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001608 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001609}
1610
1611void cpu_reset_interrupt(CPUState *env, int mask)
1612{
1613 env->interrupt_request &= ~mask;
1614}
1615
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001616void cpu_exit(CPUState *env)
1617{
1618 env->exit_request = 1;
1619 cpu_unlink_tb(env);
1620}
1621
1622const CPULogItem cpu_log_items[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001623 { CPU_LOG_TB_OUT_ASM, "out_asm",
1624 "show generated host assembly code for each compiled TB" },
1625 { CPU_LOG_TB_IN_ASM, "in_asm",
1626 "show target assembly code for each compiled TB" },
1627 { CPU_LOG_TB_OP, "op",
1628 "show micro ops for each compiled TB" },
1629 { CPU_LOG_TB_OP_OPT, "op_opt",
1630 "show micro ops "
1631#ifdef TARGET_I386
1632 "before eflags optimization and "
1633#endif
1634 "after liveness analysis" },
1635 { CPU_LOG_INT, "int",
1636 "show interrupts/exceptions in short format" },
1637 { CPU_LOG_EXEC, "exec",
1638 "show trace before each executed TB (lots of logs)" },
1639 { CPU_LOG_TB_CPU, "cpu",
1640 "show CPU state before block translation" },
1641#ifdef TARGET_I386
1642 { CPU_LOG_PCALL, "pcall",
1643 "show protected mode far calls/returns/exceptions" },
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001644 { CPU_LOG_RESET, "cpu_reset",
1645 "show CPU state before CPU resets" },
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001646#endif
1647#ifdef DEBUG_IOPORT
1648 { CPU_LOG_IOPORT, "ioport",
1649 "show all i/o ports accesses" },
1650#endif
1651 { 0, NULL, NULL },
1652};
1653
1654static int cmp1(const char *s1, int n, const char *s2)
1655{
1656 if (strlen(s2) != n)
1657 return 0;
1658 return memcmp(s1, s2, n) == 0;
1659}
1660
1661/* takes a comma separated list of log masks. Return 0 if error. */
1662int cpu_str_to_log_mask(const char *str)
1663{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001664 const CPULogItem *item;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001665 int mask;
1666 const char *p, *p1;
1667
1668 p = str;
1669 mask = 0;
1670 for(;;) {
1671 p1 = strchr(p, ',');
1672 if (!p1)
1673 p1 = p + strlen(p);
1674 if(cmp1(p,p1-p,"all")) {
1675 for(item = cpu_log_items; item->mask != 0; item++) {
1676 mask |= item->mask;
1677 }
1678 } else {
1679 for(item = cpu_log_items; item->mask != 0; item++) {
1680 if (cmp1(p, p1 - p, item->name))
1681 goto found;
1682 }
1683 return 0;
1684 }
1685 found:
1686 mask |= item->mask;
1687 if (*p1 != ',')
1688 break;
1689 p = p1 + 1;
1690 }
1691 return mask;
1692}
1693
1694void cpu_abort(CPUState *env, const char *fmt, ...)
1695{
1696 va_list ap;
1697 va_list ap2;
1698
1699 va_start(ap, fmt);
1700 va_copy(ap2, ap);
1701 fprintf(stderr, "qemu: fatal: ");
1702 vfprintf(stderr, fmt, ap);
1703 fprintf(stderr, "\n");
1704#ifdef TARGET_I386
1705 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1706#else
1707 cpu_dump_state(env, stderr, fprintf, 0);
1708#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001709 if (qemu_log_enabled()) {
1710 qemu_log("qemu: fatal: ");
1711 qemu_log_vprintf(fmt, ap2);
1712 qemu_log("\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001713#ifdef TARGET_I386
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001714 log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001715#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001716 log_cpu_state(env, 0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001717#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001718 qemu_log_flush();
1719 qemu_log_close();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001720 }
1721 va_end(ap2);
1722 va_end(ap);
David 'Digit' Turner36411062010-12-22 17:34:53 +01001723#if defined(CONFIG_USER_ONLY)
1724 {
1725 struct sigaction act;
1726 sigfillset(&act.sa_mask);
1727 act.sa_handler = SIG_DFL;
1728 sigaction(SIGABRT, &act, NULL);
1729 }
1730#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001731 abort();
1732}
1733
1734CPUState *cpu_copy(CPUState *env)
1735{
1736 CPUState *new_env = cpu_init(env->cpu_model_str);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001737 CPUState *next_cpu = new_env->next_cpu;
1738 int cpu_index = new_env->cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001739#if defined(TARGET_HAS_ICE)
1740 CPUBreakpoint *bp;
1741 CPUWatchpoint *wp;
1742#endif
1743
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001744 memcpy(new_env, env, sizeof(CPUState));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001745
1746 /* Preserve chaining and index. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001747 new_env->next_cpu = next_cpu;
1748 new_env->cpu_index = cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001749
1750 /* Clone all break/watchpoints.
1751 Note: Once we support ptrace with hw-debug register access, make sure
1752 BP_CPU break/watchpoints are handled correctly on clone. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001753 QTAILQ_INIT(&env->breakpoints);
1754 QTAILQ_INIT(&env->watchpoints);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001755#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001756 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001757 cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
1758 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001759 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001760 cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
1761 wp->flags, NULL);
1762 }
1763#endif
1764
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001765 return new_env;
1766}
1767
1768#if !defined(CONFIG_USER_ONLY)
1769
1770static inline void tlb_flush_jmp_cache(CPUState *env, target_ulong addr)
1771{
1772 unsigned int i;
1773
1774 /* Discard jump cache entries for any tb which might potentially
1775 overlap the flushed page. */
1776 i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
David 'Digit' Turner36411062010-12-22 17:34:53 +01001777 memset (&env->tb_jmp_cache[i], 0,
1778 TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001779
1780 i = tb_jmp_cache_hash_page(addr);
David 'Digit' Turner36411062010-12-22 17:34:53 +01001781 memset (&env->tb_jmp_cache[i], 0,
1782 TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001783}
1784
1785/* NOTE: if flush_global is true, also flush global entries (not
1786 implemented yet) */
1787void tlb_flush(CPUState *env, int flush_global)
1788{
1789 int i;
1790
1791#if defined(DEBUG_TLB)
1792 printf("tlb_flush:\n");
1793#endif
1794 /* must reset current TB so that interrupts cannot modify the
1795 links while we are modifying them */
1796 env->current_tb = NULL;
1797
1798 for(i = 0; i < CPU_TLB_SIZE; i++) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001799 int mmu_idx;
1800 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1801 env->tlb_table[mmu_idx][i].addr_read = -1;
1802 env->tlb_table[mmu_idx][i].addr_write = -1;
1803 env->tlb_table[mmu_idx][i].addr_code = -1;
1804 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001805 }
1806
1807 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
1808
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001809#ifdef CONFIG_KQEMU
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001810 if (env->kqemu_enabled) {
1811 kqemu_flush(env, flush_global);
1812 }
1813#endif
1814 tlb_flush_count++;
1815}
1816
1817static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
1818{
1819 if (addr == (tlb_entry->addr_read &
1820 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1821 addr == (tlb_entry->addr_write &
1822 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1823 addr == (tlb_entry->addr_code &
1824 (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1825 tlb_entry->addr_read = -1;
1826 tlb_entry->addr_write = -1;
1827 tlb_entry->addr_code = -1;
1828 }
1829}
1830
1831void tlb_flush_page(CPUState *env, target_ulong addr)
1832{
1833 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001834 int mmu_idx;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001835
1836#if defined(DEBUG_TLB)
1837 printf("tlb_flush_page: " TARGET_FMT_lx "\n", addr);
1838#endif
1839 /* must reset current TB so that interrupts cannot modify the
1840 links while we are modifying them */
1841 env->current_tb = NULL;
1842
1843 addr &= TARGET_PAGE_MASK;
1844 i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001845 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++)
1846 tlb_flush_entry(&env->tlb_table[mmu_idx][i], addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001847
1848 tlb_flush_jmp_cache(env, addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001849}
1850
1851/* update the TLBs so that writes to code in the virtual page 'addr'
1852 can be detected */
1853static void tlb_protect_code(ram_addr_t ram_addr)
1854{
1855 cpu_physical_memory_reset_dirty(ram_addr,
1856 ram_addr + TARGET_PAGE_SIZE,
1857 CODE_DIRTY_FLAG);
1858}
1859
1860/* update the TLB so that writes in physical page 'phys_addr' are no longer
1861 tested for self modifying code */
1862static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
1863 target_ulong vaddr)
1864{
1865 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] |= CODE_DIRTY_FLAG;
1866}
1867
1868static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
1869 unsigned long start, unsigned long length)
1870{
1871 unsigned long addr;
1872 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1873 addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
1874 if ((addr - start) < length) {
1875 tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
1876 }
1877 }
1878}
1879
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001880/* Note: start and end must be within the same ram block. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001881void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
1882 int dirty_flags)
1883{
1884 CPUState *env;
1885 unsigned long length, start1;
1886 int i, mask, len;
1887 uint8_t *p;
1888
1889 start &= TARGET_PAGE_MASK;
1890 end = TARGET_PAGE_ALIGN(end);
1891
1892 length = end - start;
1893 if (length == 0)
1894 return;
1895 len = length >> TARGET_PAGE_BITS;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001896 mask = ~dirty_flags;
1897 p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
1898 for(i = 0; i < len; i++)
1899 p[i] &= mask;
1900
1901 /* we modify the TLB cache so that the dirty bit will be set again
1902 when accessing the range */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001903 start1 = (unsigned long)qemu_get_ram_ptr(start);
1904 /* Chek that we don't span multiple blocks - this breaks the
1905 address comparisons below. */
1906 if ((unsigned long)qemu_get_ram_ptr(end - 1) - start1
1907 != (end - 1) - start) {
1908 abort();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001909 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001910
1911 for(env = first_cpu; env != NULL; env = env->next_cpu) {
1912 int mmu_idx;
1913 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1914 for(i = 0; i < CPU_TLB_SIZE; i++)
1915 tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
1916 start1, length);
1917 }
1918 }
1919}
1920
1921int cpu_physical_memory_set_dirty_tracking(int enable)
1922{
1923 in_migration = enable;
1924 if (kvm_enabled()) {
1925 return kvm_set_migration_log(enable);
1926 }
1927 return 0;
1928}
1929
1930int cpu_physical_memory_get_dirty_tracking(void)
1931{
1932 return in_migration;
1933}
1934
1935int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
1936 target_phys_addr_t end_addr)
1937{
1938 int ret = 0;
1939
1940 if (kvm_enabled())
1941 ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
1942 return ret;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001943}
1944
1945static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1946{
1947 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001948 void *p;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001949
1950 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001951 p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
1952 + tlb_entry->addend);
1953 ram_addr = qemu_ram_addr_from_host(p);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001954 if (!cpu_physical_memory_is_dirty(ram_addr)) {
1955 tlb_entry->addr_write |= TLB_NOTDIRTY;
1956 }
1957 }
1958}
1959
1960/* update the TLB according to the current state of the dirty bits */
1961void cpu_tlb_update_dirty(CPUState *env)
1962{
1963 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001964 int mmu_idx;
1965 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1966 for(i = 0; i < CPU_TLB_SIZE; i++)
1967 tlb_update_dirty(&env->tlb_table[mmu_idx][i]);
1968 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001969}
1970
1971static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, target_ulong vaddr)
1972{
1973 if (tlb_entry->addr_write == (vaddr | TLB_NOTDIRTY))
1974 tlb_entry->addr_write = vaddr;
1975}
1976
1977/* update the TLB corresponding to virtual page vaddr
1978 so that it is no longer dirty */
1979static inline void tlb_set_dirty(CPUState *env, target_ulong vaddr)
1980{
1981 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001982 int mmu_idx;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001983
1984 vaddr &= TARGET_PAGE_MASK;
1985 i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001986 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++)
1987 tlb_set_dirty1(&env->tlb_table[mmu_idx][i], vaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001988}
1989
1990/* add a new TLB entry. At most one entry for a given virtual address
1991 is permitted. Return 0 if OK or 2 if the page could not be mapped
1992 (can only happen in non SOFTMMU mode for I/O pages or pages
1993 conflicting with the host address space). */
1994int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
1995 target_phys_addr_t paddr, int prot,
1996 int mmu_idx, int is_softmmu)
1997{
1998 PhysPageDesc *p;
1999 unsigned long pd;
2000 unsigned int index;
2001 target_ulong address;
2002 target_ulong code_address;
David 'Digit' Turnerd9b6cb92010-10-20 19:07:28 +02002003 ptrdiff_t addend;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002004 int ret;
2005 CPUTLBEntry *te;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002006 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002007 target_phys_addr_t iotlb;
2008
2009 p = phys_page_find(paddr >> TARGET_PAGE_BITS);
2010 if (!p) {
2011 pd = IO_MEM_UNASSIGNED;
2012 } else {
2013 pd = p->phys_offset;
2014 }
2015#if defined(DEBUG_TLB)
2016 printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x idx=%d smmu=%d pd=0x%08lx\n",
2017 vaddr, (int)paddr, prot, mmu_idx, is_softmmu, pd);
2018#endif
2019
2020 ret = 0;
2021 address = vaddr;
2022 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
2023 /* IO memory case (romd handled later) */
2024 address |= TLB_MMIO;
2025 }
David 'Digit' Turnerd9b6cb92010-10-20 19:07:28 +02002026 addend = (ptrdiff_t)qemu_get_ram_ptr(pd & TARGET_PAGE_MASK);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002027 if ((pd & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
2028 /* Normal RAM. */
2029 iotlb = pd & TARGET_PAGE_MASK;
2030 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM)
2031 iotlb |= IO_MEM_NOTDIRTY;
2032 else
2033 iotlb |= IO_MEM_ROM;
2034 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002035 /* IO handlers are currently passed a physical address.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002036 It would be nice to pass an offset from the base address
2037 of that region. This would avoid having to special case RAM,
2038 and avoid full address decoding in every device.
2039 We can't use the high bits of pd for this because
2040 IO_MEM_ROMD uses these as a ram address. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002041 iotlb = (pd & ~TARGET_PAGE_MASK);
2042 if (p) {
2043 iotlb += p->region_offset;
2044 } else {
2045 iotlb += paddr;
2046 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002047 }
2048
2049 code_address = address;
2050 /* Make accesses to pages with watchpoints go via the
2051 watchpoint trap routines. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002052 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002053 if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002054 iotlb = io_mem_watch + paddr;
2055 /* TODO: The memory case can be optimized by not trapping
2056 reads of pages with a write breakpoint. */
2057 address |= TLB_MMIO;
2058 }
2059 }
2060
2061 index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
2062 env->iotlb[mmu_idx][index] = iotlb - vaddr;
2063 te = &env->tlb_table[mmu_idx][index];
2064 te->addend = addend - vaddr;
2065 if (prot & PAGE_READ) {
2066 te->addr_read = address;
2067 } else {
2068 te->addr_read = -1;
2069 }
2070
2071 if (prot & PAGE_EXEC) {
2072 te->addr_code = code_address;
2073 } else {
2074 te->addr_code = -1;
2075 }
2076 if (prot & PAGE_WRITE) {
2077 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM ||
2078 (pd & IO_MEM_ROMD)) {
2079 /* Write access calls the I/O callback. */
2080 te->addr_write = address | TLB_MMIO;
2081 } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
2082 !cpu_physical_memory_is_dirty(pd)) {
2083 te->addr_write = address | TLB_NOTDIRTY;
2084 } else {
2085 te->addr_write = address;
2086 }
2087 } else {
2088 te->addr_write = -1;
2089 }
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -08002090
2091#ifdef CONFIG_MEMCHECK
2092 /*
2093 * If we have memchecker running, we need to make sure that page, cached
2094 * into TLB as the result of this operation will comply with our requirement
2095 * to cause __ld/__stx_mmu being called for memory access on the pages
2096 * containing memory blocks that require access violation checks.
2097 *
2098 * We need to check with memory checker if we should invalidate this page
2099 * iff:
2100 * - Memchecking is enabled.
2101 * - Page that's been cached belongs to the user space.
2102 * - Request to cache this page didn't come from softmmu. We're covered
2103 * there, because after page was cached here we will invalidate it in
2104 * the __ld/__stx_mmu wrapper.
2105 * - Cached page belongs to RAM, not I/O area.
2106 * - Page is cached for read, or write access.
2107 */
2108 if (memcheck_instrument_mmu && mmu_idx == 1 && !is_softmmu &&
2109 (pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
2110 (prot & (PAGE_READ | PAGE_WRITE)) &&
2111 memcheck_is_checked(vaddr & TARGET_PAGE_MASK, TARGET_PAGE_SIZE)) {
2112 if (prot & PAGE_READ) {
2113 te->addr_read ^= TARGET_PAGE_MASK;
2114 }
2115 if (prot & PAGE_WRITE) {
2116 te->addr_write ^= TARGET_PAGE_MASK;
2117 }
2118 }
2119#endif // CONFIG_MEMCHECK
2120
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002121 return ret;
2122}
2123
2124#else
2125
2126void tlb_flush(CPUState *env, int flush_global)
2127{
2128}
2129
2130void tlb_flush_page(CPUState *env, target_ulong addr)
2131{
2132}
2133
2134int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
2135 target_phys_addr_t paddr, int prot,
2136 int mmu_idx, int is_softmmu)
2137{
2138 return 0;
2139}
2140
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002141/*
2142 * Walks guest process memory "regions" one by one
2143 * and calls callback function 'fn' for each region.
2144 */
2145int walk_memory_regions(void *priv,
2146 int (*fn)(void *, unsigned long, unsigned long, unsigned long))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002147{
2148 unsigned long start, end;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002149 PageDesc *p = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002150 int i, j, prot, prot1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002151 int rc = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002152
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002153 start = end = -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002154 prot = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002155
2156 for (i = 0; i <= L1_SIZE; i++) {
2157 p = (i < L1_SIZE) ? l1_map[i] : NULL;
2158 for (j = 0; j < L2_SIZE; j++) {
2159 prot1 = (p == NULL) ? 0 : p[j].flags;
2160 /*
2161 * "region" is one continuous chunk of memory
2162 * that has same protection flags set.
2163 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002164 if (prot1 != prot) {
2165 end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
2166 if (start != -1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002167 rc = (*fn)(priv, start, end, prot);
2168 /* callback can stop iteration by returning != 0 */
2169 if (rc != 0)
2170 return (rc);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002171 }
2172 if (prot1 != 0)
2173 start = end;
2174 else
2175 start = -1;
2176 prot = prot1;
2177 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002178 if (p == NULL)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002179 break;
2180 }
2181 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002182 return (rc);
2183}
2184
2185static int dump_region(void *priv, unsigned long start,
2186 unsigned long end, unsigned long prot)
2187{
2188 FILE *f = (FILE *)priv;
2189
2190 (void) fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
2191 start, end, end - start,
2192 ((prot & PAGE_READ) ? 'r' : '-'),
2193 ((prot & PAGE_WRITE) ? 'w' : '-'),
2194 ((prot & PAGE_EXEC) ? 'x' : '-'));
2195
2196 return (0);
2197}
2198
2199/* dump memory mappings */
2200void page_dump(FILE *f)
2201{
2202 (void) fprintf(f, "%-8s %-8s %-8s %s\n",
2203 "start", "end", "size", "prot");
2204 walk_memory_regions(f, dump_region);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002205}
2206
2207int page_get_flags(target_ulong address)
2208{
2209 PageDesc *p;
2210
2211 p = page_find(address >> TARGET_PAGE_BITS);
2212 if (!p)
2213 return 0;
2214 return p->flags;
2215}
2216
David 'Digit' Turner36411062010-12-22 17:34:53 +01002217/* Modify the flags of a page and invalidate the code if necessary.
2218 The flag PAGE_WRITE_ORG is positioned automatically depending
2219 on PAGE_WRITE. The mmap_lock should already be held. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002220void page_set_flags(target_ulong start, target_ulong end, int flags)
2221{
2222 PageDesc *p;
2223 target_ulong addr;
2224
2225 /* mmap_lock should already be held. */
2226 start = start & TARGET_PAGE_MASK;
2227 end = TARGET_PAGE_ALIGN(end);
2228 if (flags & PAGE_WRITE)
2229 flags |= PAGE_WRITE_ORG;
2230 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2231 p = page_find_alloc(addr >> TARGET_PAGE_BITS);
2232 /* We may be called for host regions that are outside guest
2233 address space. */
2234 if (!p)
2235 return;
2236 /* if the write protection is set, then we invalidate the code
2237 inside */
2238 if (!(p->flags & PAGE_WRITE) &&
2239 (flags & PAGE_WRITE) &&
2240 p->first_tb) {
2241 tb_invalidate_phys_page(addr, 0, NULL);
2242 }
2243 p->flags = flags;
2244 }
2245}
2246
2247int page_check_range(target_ulong start, target_ulong len, int flags)
2248{
2249 PageDesc *p;
2250 target_ulong end;
2251 target_ulong addr;
2252
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002253 if (start + len < start)
2254 /* we've wrapped around */
2255 return -1;
2256
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002257 end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
2258 start = start & TARGET_PAGE_MASK;
2259
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002260 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2261 p = page_find(addr >> TARGET_PAGE_BITS);
2262 if( !p )
2263 return -1;
2264 if( !(p->flags & PAGE_VALID) )
2265 return -1;
2266
2267 if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
2268 return -1;
2269 if (flags & PAGE_WRITE) {
2270 if (!(p->flags & PAGE_WRITE_ORG))
2271 return -1;
2272 /* unprotect the page if it was put read-only because it
2273 contains translated code */
2274 if (!(p->flags & PAGE_WRITE)) {
2275 if (!page_unprotect(addr, 0, NULL))
2276 return -1;
2277 }
2278 return 0;
2279 }
2280 }
2281 return 0;
2282}
2283
2284/* called from signal handler: invalidate the code and unprotect the
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002285 page. Return TRUE if the fault was successfully handled. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002286int page_unprotect(target_ulong address, unsigned long pc, void *puc)
2287{
2288 unsigned int page_index, prot, pindex;
2289 PageDesc *p, *p1;
2290 target_ulong host_start, host_end, addr;
2291
2292 /* Technically this isn't safe inside a signal handler. However we
2293 know this only ever happens in a synchronous SEGV handler, so in
2294 practice it seems to be ok. */
2295 mmap_lock();
2296
2297 host_start = address & qemu_host_page_mask;
2298 page_index = host_start >> TARGET_PAGE_BITS;
2299 p1 = page_find(page_index);
2300 if (!p1) {
2301 mmap_unlock();
2302 return 0;
2303 }
2304 host_end = host_start + qemu_host_page_size;
2305 p = p1;
2306 prot = 0;
2307 for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
2308 prot |= p->flags;
2309 p++;
2310 }
2311 /* if the page was really writable, then we change its
2312 protection back to writable */
2313 if (prot & PAGE_WRITE_ORG) {
2314 pindex = (address - host_start) >> TARGET_PAGE_BITS;
2315 if (!(p1[pindex].flags & PAGE_WRITE)) {
2316 mprotect((void *)g2h(host_start), qemu_host_page_size,
2317 (prot & PAGE_BITS) | PAGE_WRITE);
2318 p1[pindex].flags |= PAGE_WRITE;
2319 /* and since the content will be modified, we must invalidate
2320 the corresponding translated code. */
2321 tb_invalidate_phys_page(address, pc, puc);
2322#ifdef DEBUG_TB_CHECK
2323 tb_invalidate_check(address);
2324#endif
2325 mmap_unlock();
2326 return 1;
2327 }
2328 }
2329 mmap_unlock();
2330 return 0;
2331}
2332
2333static inline void tlb_set_dirty(CPUState *env,
2334 unsigned long addr, target_ulong vaddr)
2335{
2336}
2337#endif /* defined(CONFIG_USER_ONLY) */
2338
2339#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002340
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002341static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002342 ram_addr_t memory, ram_addr_t region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002343static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002344 ram_addr_t orig_memory, ram_addr_t region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002345#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
2346 need_subpage) \
2347 do { \
2348 if (addr > start_addr) \
2349 start_addr2 = 0; \
2350 else { \
2351 start_addr2 = start_addr & ~TARGET_PAGE_MASK; \
2352 if (start_addr2 > 0) \
2353 need_subpage = 1; \
2354 } \
2355 \
2356 if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE) \
2357 end_addr2 = TARGET_PAGE_SIZE - 1; \
2358 else { \
2359 end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
2360 if (end_addr2 < TARGET_PAGE_SIZE - 1) \
2361 need_subpage = 1; \
2362 } \
2363 } while (0)
2364
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002365/* register physical memory.
2366 For RAM, 'size' must be a multiple of the target page size.
2367 If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002368 io memory page. The address used when calling the IO function is
2369 the offset from the start of the region, plus region_offset. Both
2370 start_addr and region_offset are rounded down to a page boundary
2371 before calculating this offset. This should not be a problem unless
2372 the low bits of start_addr and region_offset differ. */
2373void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
2374 ram_addr_t size,
2375 ram_addr_t phys_offset,
2376 ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002377{
2378 target_phys_addr_t addr, end_addr;
2379 PhysPageDesc *p;
2380 CPUState *env;
2381 ram_addr_t orig_size = size;
2382 void *subpage;
2383
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002384 if (kvm_enabled())
2385 kvm_set_phys_mem(start_addr, size, phys_offset);
2386
2387 if (phys_offset == IO_MEM_UNASSIGNED) {
2388 region_offset = start_addr;
2389 }
2390 region_offset &= TARGET_PAGE_MASK;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002391 size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
2392 end_addr = start_addr + (target_phys_addr_t)size;
2393 for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
2394 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2395 if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
2396 ram_addr_t orig_memory = p->phys_offset;
2397 target_phys_addr_t start_addr2, end_addr2;
2398 int need_subpage = 0;
2399
2400 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2401 need_subpage);
2402 if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
2403 if (!(orig_memory & IO_MEM_SUBPAGE)) {
2404 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002405 &p->phys_offset, orig_memory,
2406 p->region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002407 } else {
2408 subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
2409 >> IO_MEM_SHIFT];
2410 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002411 subpage_register(subpage, start_addr2, end_addr2, phys_offset,
2412 region_offset);
2413 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002414 } else {
2415 p->phys_offset = phys_offset;
2416 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2417 (phys_offset & IO_MEM_ROMD))
2418 phys_offset += TARGET_PAGE_SIZE;
2419 }
2420 } else {
2421 p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2422 p->phys_offset = phys_offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002423 p->region_offset = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002424 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002425 (phys_offset & IO_MEM_ROMD)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002426 phys_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002427 } else {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002428 target_phys_addr_t start_addr2, end_addr2;
2429 int need_subpage = 0;
2430
2431 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2432 end_addr2, need_subpage);
2433
2434 if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
2435 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002436 &p->phys_offset, IO_MEM_UNASSIGNED,
2437 addr & TARGET_PAGE_MASK);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002438 subpage_register(subpage, start_addr2, end_addr2,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002439 phys_offset, region_offset);
2440 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002441 }
2442 }
2443 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002444 region_offset += TARGET_PAGE_SIZE;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002445 }
2446
2447 /* since each CPU stores ram addresses in its TLB cache, we must
2448 reset the modified entries */
2449 /* XXX: slow ! */
2450 for(env = first_cpu; env != NULL; env = env->next_cpu) {
2451 tlb_flush(env, 1);
2452 }
2453}
2454
2455/* XXX: temporary until new memory mapping API */
2456ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr)
2457{
2458 PhysPageDesc *p;
2459
2460 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2461 if (!p)
2462 return IO_MEM_UNASSIGNED;
2463 return p->phys_offset;
2464}
2465
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002466void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
2467{
2468 if (kvm_enabled())
2469 kvm_coalesce_mmio_region(addr, size);
2470}
2471
2472void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
2473{
2474 if (kvm_enabled())
2475 kvm_uncoalesce_mmio_region(addr, size);
2476}
2477
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002478ram_addr_t qemu_ram_alloc(ram_addr_t size)
2479{
2480 RAMBlock *new_block;
2481
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002482 size = TARGET_PAGE_ALIGN(size);
2483 new_block = qemu_malloc(sizeof(*new_block));
2484
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002485#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2486 /* XXX S390 KVM requires the topmost vma of the RAM to be < 256GB */
2487 new_block->host = mmap((void*)0x1000000, size, PROT_EXEC|PROT_READ|PROT_WRITE,
2488 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
2489#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002490 new_block->host = qemu_vmalloc(size);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002491#endif
2492#ifdef MADV_MERGEABLE
2493 madvise(new_block->host, size, MADV_MERGEABLE);
2494#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002495 new_block->offset = last_ram_offset;
2496 new_block->length = size;
2497
2498 new_block->next = ram_blocks;
2499 ram_blocks = new_block;
2500
2501 phys_ram_dirty = qemu_realloc(phys_ram_dirty,
2502 (last_ram_offset + size) >> TARGET_PAGE_BITS);
2503 memset(phys_ram_dirty + (last_ram_offset >> TARGET_PAGE_BITS),
2504 0xff, size >> TARGET_PAGE_BITS);
2505
2506 last_ram_offset += size;
2507
2508 if (kvm_enabled())
2509 kvm_setup_guest_memory(new_block->host, size);
2510
2511 return new_block->offset;
2512}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002513
2514void qemu_ram_free(ram_addr_t addr)
2515{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002516 /* TODO: implement this. */
2517}
2518
2519/* Return a host pointer to ram allocated with qemu_ram_alloc.
2520 With the exception of the softmmu code in this file, this should
2521 only be used for local memory (e.g. video ram) that the device owns,
2522 and knows it isn't going to access beyond the end of the block.
2523
2524 It should not be used for general purpose DMA.
2525 Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
2526 */
2527void *qemu_get_ram_ptr(ram_addr_t addr)
2528{
2529 RAMBlock *prev;
2530 RAMBlock **prevp;
2531 RAMBlock *block;
2532
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002533 prev = NULL;
2534 prevp = &ram_blocks;
2535 block = ram_blocks;
2536 while (block && (block->offset > addr
2537 || block->offset + block->length <= addr)) {
2538 if (prev)
2539 prevp = &prev->next;
2540 prev = block;
2541 block = block->next;
2542 }
2543 if (!block) {
2544 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2545 abort();
2546 }
2547 /* Move this entry to to start of the list. */
2548 if (prev) {
2549 prev->next = block->next;
2550 block->next = *prevp;
2551 *prevp = block;
2552 }
2553 return block->host + (addr - block->offset);
2554}
2555
2556/* Some of the softmmu routines need to translate from a host pointer
2557 (typically a TLB entry) back to a ram offset. */
2558ram_addr_t qemu_ram_addr_from_host(void *ptr)
2559{
2560 RAMBlock *prev;
2561 RAMBlock **prevp;
2562 RAMBlock *block;
2563 uint8_t *host = ptr;
2564
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002565 prev = NULL;
2566 prevp = &ram_blocks;
2567 block = ram_blocks;
2568 while (block && (block->host > host
2569 || block->host + block->length <= host)) {
2570 if (prev)
2571 prevp = &prev->next;
2572 prev = block;
2573 block = block->next;
2574 }
2575 if (!block) {
2576 fprintf(stderr, "Bad ram pointer %p\n", ptr);
2577 abort();
2578 }
2579 return block->offset + (host - block->host);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002580}
2581
2582static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
2583{
2584#ifdef DEBUG_UNASSIGNED
2585 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2586#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002587#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002588 do_unassigned_access(addr, 0, 0, 0, 1);
2589#endif
2590 return 0;
2591}
2592
2593static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr)
2594{
2595#ifdef DEBUG_UNASSIGNED
2596 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2597#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002598#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002599 do_unassigned_access(addr, 0, 0, 0, 2);
2600#endif
2601 return 0;
2602}
2603
2604static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr)
2605{
2606#ifdef DEBUG_UNASSIGNED
2607 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2608#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002609#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002610 do_unassigned_access(addr, 0, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002611#endif
2612 return 0;
2613}
2614
2615static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
2616{
2617#ifdef DEBUG_UNASSIGNED
2618 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2619#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002620#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002621 do_unassigned_access(addr, 1, 0, 0, 1);
2622#endif
2623}
2624
2625static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
2626{
2627#ifdef DEBUG_UNASSIGNED
2628 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2629#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002630#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002631 do_unassigned_access(addr, 1, 0, 0, 2);
2632#endif
2633}
2634
2635static void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
2636{
2637#ifdef DEBUG_UNASSIGNED
2638 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2639#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002640#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002641 do_unassigned_access(addr, 1, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002642#endif
2643}
2644
David 'Digit' Turner36411062010-12-22 17:34:53 +01002645static CPUReadMemoryFunc * const unassigned_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002646 unassigned_mem_readb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002647 unassigned_mem_readw,
2648 unassigned_mem_readl,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002649};
2650
David 'Digit' Turner36411062010-12-22 17:34:53 +01002651static CPUWriteMemoryFunc * const unassigned_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002652 unassigned_mem_writeb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002653 unassigned_mem_writew,
2654 unassigned_mem_writel,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002655};
2656
2657static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr,
2658 uint32_t val)
2659{
2660 int dirty_flags;
2661 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2662 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2663#if !defined(CONFIG_USER_ONLY)
2664 tb_invalidate_phys_page_fast(ram_addr, 1);
2665 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2666#endif
2667 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002668 stb_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002669 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2670 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2671 /* we remove the notdirty callback only if the code has been
2672 flushed */
2673 if (dirty_flags == 0xff)
2674 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2675}
2676
2677static void notdirty_mem_writew(void *opaque, target_phys_addr_t ram_addr,
2678 uint32_t val)
2679{
2680 int dirty_flags;
2681 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2682 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2683#if !defined(CONFIG_USER_ONLY)
2684 tb_invalidate_phys_page_fast(ram_addr, 2);
2685 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2686#endif
2687 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002688 stw_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002689 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2690 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2691 /* we remove the notdirty callback only if the code has been
2692 flushed */
2693 if (dirty_flags == 0xff)
2694 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2695}
2696
2697static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr,
2698 uint32_t val)
2699{
2700 int dirty_flags;
2701 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2702 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2703#if !defined(CONFIG_USER_ONLY)
2704 tb_invalidate_phys_page_fast(ram_addr, 4);
2705 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2706#endif
2707 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002708 stl_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002709 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2710 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2711 /* we remove the notdirty callback only if the code has been
2712 flushed */
2713 if (dirty_flags == 0xff)
2714 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2715}
2716
David 'Digit' Turner36411062010-12-22 17:34:53 +01002717static CPUReadMemoryFunc * const error_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002718 NULL, /* never used */
2719 NULL, /* never used */
2720 NULL, /* never used */
2721};
2722
David 'Digit' Turner36411062010-12-22 17:34:53 +01002723static CPUWriteMemoryFunc * const notdirty_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002724 notdirty_mem_writeb,
2725 notdirty_mem_writew,
2726 notdirty_mem_writel,
2727};
2728
2729/* Generate a debug exception if a watchpoint has been hit. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002730static void check_watchpoint(int offset, int len_mask, int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002731{
2732 CPUState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002733 target_ulong pc, cs_base;
2734 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002735 target_ulong vaddr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002736 CPUWatchpoint *wp;
2737 int cpu_flags;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002738
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002739 if (env->watchpoint_hit) {
2740 /* We re-entered the check after replacing the TB. Now raise
2741 * the debug interrupt so that is will trigger after the
2742 * current instruction. */
2743 cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2744 return;
2745 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002746 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002747 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002748 if ((vaddr == (wp->vaddr & len_mask) ||
2749 (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
2750 wp->flags |= BP_WATCHPOINT_HIT;
2751 if (!env->watchpoint_hit) {
2752 env->watchpoint_hit = wp;
2753 tb = tb_find_pc(env->mem_io_pc);
2754 if (!tb) {
2755 cpu_abort(env, "check_watchpoint: could not find TB for "
2756 "pc=%p", (void *)env->mem_io_pc);
2757 }
2758 cpu_restore_state(tb, env, env->mem_io_pc, NULL);
2759 tb_phys_invalidate(tb, -1);
2760 if (wp->flags & BP_STOP_BEFORE_ACCESS) {
2761 env->exception_index = EXCP_DEBUG;
2762 } else {
2763 cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
2764 tb_gen_code(env, pc, cs_base, cpu_flags, 1);
2765 }
2766 cpu_resume_from_signal(env, NULL);
2767 }
2768 } else {
2769 wp->flags &= ~BP_WATCHPOINT_HIT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002770 }
2771 }
2772}
2773
2774/* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
2775 so these check for a hit then pass through to the normal out-of-line
2776 phys routines. */
2777static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
2778{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002779 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002780 return ldub_phys(addr);
2781}
2782
2783static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
2784{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002785 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002786 return lduw_phys(addr);
2787}
2788
2789static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
2790{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002791 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002792 return ldl_phys(addr);
2793}
2794
2795static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
2796 uint32_t val)
2797{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002798 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002799 stb_phys(addr, val);
2800}
2801
2802static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
2803 uint32_t val)
2804{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002805 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002806 stw_phys(addr, val);
2807}
2808
2809static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
2810 uint32_t val)
2811{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002812 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002813 stl_phys(addr, val);
2814}
2815
David 'Digit' Turner36411062010-12-22 17:34:53 +01002816static CPUReadMemoryFunc * const watch_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002817 watch_mem_readb,
2818 watch_mem_readw,
2819 watch_mem_readl,
2820};
2821
David 'Digit' Turner36411062010-12-22 17:34:53 +01002822static CPUWriteMemoryFunc * const watch_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002823 watch_mem_writeb,
2824 watch_mem_writew,
2825 watch_mem_writel,
2826};
2827
2828static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr,
2829 unsigned int len)
2830{
2831 uint32_t ret;
2832 unsigned int idx;
2833
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002834 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002835#if defined(DEBUG_SUBPAGE)
2836 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
2837 mmio, len, addr, idx);
2838#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002839 ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len],
2840 addr + mmio->region_offset[idx][0][len]);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002841
2842 return ret;
2843}
2844
2845static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
2846 uint32_t value, unsigned int len)
2847{
2848 unsigned int idx;
2849
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002850 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002851#if defined(DEBUG_SUBPAGE)
2852 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
2853 mmio, len, addr, idx, value);
2854#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002855 (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len],
2856 addr + mmio->region_offset[idx][1][len],
2857 value);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002858}
2859
2860static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
2861{
2862#if defined(DEBUG_SUBPAGE)
2863 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2864#endif
2865
2866 return subpage_readlen(opaque, addr, 0);
2867}
2868
2869static void subpage_writeb (void *opaque, target_phys_addr_t addr,
2870 uint32_t value)
2871{
2872#if defined(DEBUG_SUBPAGE)
2873 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2874#endif
2875 subpage_writelen(opaque, addr, value, 0);
2876}
2877
2878static uint32_t subpage_readw (void *opaque, target_phys_addr_t addr)
2879{
2880#if defined(DEBUG_SUBPAGE)
2881 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2882#endif
2883
2884 return subpage_readlen(opaque, addr, 1);
2885}
2886
2887static void subpage_writew (void *opaque, target_phys_addr_t addr,
2888 uint32_t value)
2889{
2890#if defined(DEBUG_SUBPAGE)
2891 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2892#endif
2893 subpage_writelen(opaque, addr, value, 1);
2894}
2895
2896static uint32_t subpage_readl (void *opaque, target_phys_addr_t addr)
2897{
2898#if defined(DEBUG_SUBPAGE)
2899 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2900#endif
2901
2902 return subpage_readlen(opaque, addr, 2);
2903}
2904
2905static void subpage_writel (void *opaque,
2906 target_phys_addr_t addr, uint32_t value)
2907{
2908#if defined(DEBUG_SUBPAGE)
2909 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2910#endif
2911 subpage_writelen(opaque, addr, value, 2);
2912}
2913
David 'Digit' Turner36411062010-12-22 17:34:53 +01002914static CPUReadMemoryFunc * const subpage_read[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002915 &subpage_readb,
2916 &subpage_readw,
2917 &subpage_readl,
2918};
2919
David 'Digit' Turner36411062010-12-22 17:34:53 +01002920static CPUWriteMemoryFunc * const subpage_write[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002921 &subpage_writeb,
2922 &subpage_writew,
2923 &subpage_writel,
2924};
2925
2926static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002927 ram_addr_t memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002928{
2929 int idx, eidx;
2930 unsigned int i;
2931
2932 if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
2933 return -1;
2934 idx = SUBPAGE_IDX(start);
2935 eidx = SUBPAGE_IDX(end);
2936#if defined(DEBUG_SUBPAGE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002937 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 -08002938 mmio, start, end, idx, eidx, memory);
2939#endif
2940 memory >>= IO_MEM_SHIFT;
2941 for (; idx <= eidx; idx++) {
2942 for (i = 0; i < 4; i++) {
2943 if (io_mem_read[memory][i]) {
2944 mmio->mem_read[idx][i] = &io_mem_read[memory][i];
2945 mmio->opaque[idx][0][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002946 mmio->region_offset[idx][0][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002947 }
2948 if (io_mem_write[memory][i]) {
2949 mmio->mem_write[idx][i] = &io_mem_write[memory][i];
2950 mmio->opaque[idx][1][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002951 mmio->region_offset[idx][1][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002952 }
2953 }
2954 }
2955
2956 return 0;
2957}
2958
2959static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002960 ram_addr_t orig_memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002961{
2962 subpage_t *mmio;
2963 int subpage_memory;
2964
2965 mmio = qemu_mallocz(sizeof(subpage_t));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002966
2967 mmio->base = base;
2968 subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002969#if defined(DEBUG_SUBPAGE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002970 printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
2971 mmio, base, TARGET_PAGE_SIZE, subpage_memory);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002972#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002973 *phys = subpage_memory | IO_MEM_SUBPAGE;
2974 subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
2975 region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002976
2977 return mmio;
2978}
2979
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002980static int get_free_io_mem_idx(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002981{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002982 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002983
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002984 for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
2985 if (!io_mem_used[i]) {
2986 io_mem_used[i] = 1;
2987 return i;
2988 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002989 fprintf(stderr, "RAN out out io_mem_idx, max %d !\n", IO_MEM_NB_ENTRIES);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002990 return -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002991}
2992
2993/* mem_read and mem_write are arrays of functions containing the
2994 function to access byte (index 0), word (index 1) and dword (index
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002995 2). Functions can be omitted with a NULL function pointer.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002996 If io_index is non zero, the corresponding io zone is
2997 modified. If it is zero, a new io zone is allocated. The return
2998 value can be used with cpu_register_physical_memory(). (-1) is
2999 returned if error. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003000static int cpu_register_io_memory_fixed(int io_index,
David 'Digit' Turner36411062010-12-22 17:34:53 +01003001 CPUReadMemoryFunc * const *mem_read,
3002 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003003 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003004{
3005 int i, subwidth = 0;
3006
3007 if (io_index <= 0) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003008 io_index = get_free_io_mem_idx();
3009 if (io_index == -1)
3010 return io_index;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003011 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003012 io_index >>= IO_MEM_SHIFT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003013 if (io_index >= IO_MEM_NB_ENTRIES)
3014 return -1;
3015 }
3016
3017 for(i = 0;i < 3; i++) {
3018 if (!mem_read[i] || !mem_write[i])
3019 subwidth = IO_MEM_SUBWIDTH;
3020 io_mem_read[io_index][i] = mem_read[i];
3021 io_mem_write[io_index][i] = mem_write[i];
3022 }
3023 io_mem_opaque[io_index] = opaque;
3024 return (io_index << IO_MEM_SHIFT) | subwidth;
3025}
3026
David 'Digit' Turner36411062010-12-22 17:34:53 +01003027int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
3028 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003029 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003030{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003031 return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003032}
3033
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003034void cpu_unregister_io_memory(int io_table_address)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003035{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003036 int i;
3037 int io_index = io_table_address >> IO_MEM_SHIFT;
3038
3039 for (i=0;i < 3; i++) {
3040 io_mem_read[io_index][i] = unassigned_mem_read[i];
3041 io_mem_write[io_index][i] = unassigned_mem_write[i];
3042 }
3043 io_mem_opaque[io_index] = NULL;
3044 io_mem_used[io_index] = 0;
3045}
3046
3047static void io_mem_init(void)
3048{
3049 int i;
3050
3051 cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read, unassigned_mem_write, NULL);
3052 cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read, unassigned_mem_write, NULL);
3053 cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read, notdirty_mem_write, NULL);
3054 for (i=0; i<5; i++)
3055 io_mem_used[i] = 1;
3056
3057 io_mem_watch = cpu_register_io_memory(watch_mem_read,
3058 watch_mem_write, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003059}
3060
3061#endif /* !defined(CONFIG_USER_ONLY) */
3062
3063/* physical memory access (slow version, mainly for debug) */
3064#if defined(CONFIG_USER_ONLY)
3065void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
3066 int len, int is_write)
3067{
3068 int l, flags;
3069 target_ulong page;
3070 void * p;
3071
3072 while (len > 0) {
3073 page = addr & TARGET_PAGE_MASK;
3074 l = (page + TARGET_PAGE_SIZE) - addr;
3075 if (l > len)
3076 l = len;
3077 flags = page_get_flags(page);
3078 if (!(flags & PAGE_VALID))
3079 return;
3080 if (is_write) {
3081 if (!(flags & PAGE_WRITE))
3082 return;
3083 /* XXX: this code should not depend on lock_user */
3084 if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
3085 /* FIXME - should this return an error rather than just fail? */
3086 return;
3087 memcpy(p, buf, l);
3088 unlock_user(p, addr, l);
3089 } else {
3090 if (!(flags & PAGE_READ))
3091 return;
3092 /* XXX: this code should not depend on lock_user */
3093 if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
3094 /* FIXME - should this return an error rather than just fail? */
3095 return;
3096 memcpy(buf, p, l);
3097 unlock_user(p, addr, 0);
3098 }
3099 len -= l;
3100 buf += l;
3101 addr += l;
3102 }
3103}
3104
3105#else
3106void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
3107 int len, int is_write)
3108{
3109 int l, io_index;
3110 uint8_t *ptr;
3111 uint32_t val;
3112 target_phys_addr_t page;
3113 unsigned long pd;
3114 PhysPageDesc *p;
3115
3116 while (len > 0) {
3117 page = addr & TARGET_PAGE_MASK;
3118 l = (page + TARGET_PAGE_SIZE) - addr;
3119 if (l > len)
3120 l = len;
3121 p = phys_page_find(page >> TARGET_PAGE_BITS);
3122 if (!p) {
3123 pd = IO_MEM_UNASSIGNED;
3124 } else {
3125 pd = p->phys_offset;
3126 }
3127
3128 if (is_write) {
3129 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003130 target_phys_addr_t addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003131 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003132 if (p)
3133 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003134 /* XXX: could force cpu_single_env to NULL to avoid
3135 potential bugs */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003136 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003137 /* 32 bit write access */
3138 val = ldl_p(buf);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003139 io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003140 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003141 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003142 /* 16 bit write access */
3143 val = lduw_p(buf);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003144 io_mem_write[io_index][1](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003145 l = 2;
3146 } else {
3147 /* 8 bit write access */
3148 val = ldub_p(buf);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003149 io_mem_write[io_index][0](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003150 l = 1;
3151 }
3152 } else {
3153 unsigned long addr1;
3154 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3155 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003156 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003157 memcpy(ptr, buf, l);
3158 if (!cpu_physical_memory_is_dirty(addr1)) {
3159 /* invalidate code */
3160 tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
3161 /* set dirty bit */
3162 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3163 (0xff & ~CODE_DIRTY_FLAG);
3164 }
3165 }
3166 } else {
3167 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3168 !(pd & IO_MEM_ROMD)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003169 target_phys_addr_t addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003170 /* I/O case */
3171 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003172 if (p)
3173 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3174 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003175 /* 32 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003176 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003177 stl_p(buf, val);
3178 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003179 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003180 /* 16 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003181 val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003182 stw_p(buf, val);
3183 l = 2;
3184 } else {
3185 /* 8 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003186 val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003187 stb_p(buf, val);
3188 l = 1;
3189 }
3190 } else {
3191 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003192 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003193 (addr & ~TARGET_PAGE_MASK);
3194 memcpy(buf, ptr, l);
3195 }
3196 }
3197 len -= l;
3198 buf += l;
3199 addr += l;
3200 }
3201}
3202
3203/* used for ROM loading : can write in RAM and ROM */
3204void cpu_physical_memory_write_rom(target_phys_addr_t addr,
3205 const uint8_t *buf, int len)
3206{
3207 int l;
3208 uint8_t *ptr;
3209 target_phys_addr_t page;
3210 unsigned long pd;
3211 PhysPageDesc *p;
3212
3213 while (len > 0) {
3214 page = addr & TARGET_PAGE_MASK;
3215 l = (page + TARGET_PAGE_SIZE) - addr;
3216 if (l > len)
3217 l = len;
3218 p = phys_page_find(page >> TARGET_PAGE_BITS);
3219 if (!p) {
3220 pd = IO_MEM_UNASSIGNED;
3221 } else {
3222 pd = p->phys_offset;
3223 }
3224
3225 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
3226 (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
3227 !(pd & IO_MEM_ROMD)) {
3228 /* do nothing */
3229 } else {
3230 unsigned long addr1;
3231 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3232 /* ROM/RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003233 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003234 memcpy(ptr, buf, l);
3235 }
3236 len -= l;
3237 buf += l;
3238 addr += l;
3239 }
3240}
3241
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003242typedef struct {
3243 void *buffer;
3244 target_phys_addr_t addr;
3245 target_phys_addr_t len;
3246} BounceBuffer;
3247
3248static BounceBuffer bounce;
3249
3250typedef struct MapClient {
3251 void *opaque;
3252 void (*callback)(void *opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003253 QLIST_ENTRY(MapClient) link;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003254} MapClient;
3255
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003256static QLIST_HEAD(map_client_list, MapClient) map_client_list
3257 = QLIST_HEAD_INITIALIZER(map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003258
3259void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
3260{
3261 MapClient *client = qemu_malloc(sizeof(*client));
3262
3263 client->opaque = opaque;
3264 client->callback = callback;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003265 QLIST_INSERT_HEAD(&map_client_list, client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003266 return client;
3267}
3268
3269void cpu_unregister_map_client(void *_client)
3270{
3271 MapClient *client = (MapClient *)_client;
3272
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003273 QLIST_REMOVE(client, link);
3274 qemu_free(client);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003275}
3276
3277static void cpu_notify_map_clients(void)
3278{
3279 MapClient *client;
3280
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003281 while (!QLIST_EMPTY(&map_client_list)) {
3282 client = QLIST_FIRST(&map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003283 client->callback(client->opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003284 QLIST_REMOVE(client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003285 }
3286}
3287
3288/* Map a physical memory region into a host virtual address.
3289 * May map a subset of the requested range, given by and returned in *plen.
3290 * May return NULL if resources needed to perform the mapping are exhausted.
3291 * Use only for reads OR writes - not for read-modify-write operations.
3292 * Use cpu_register_map_client() to know when retrying the map operation is
3293 * likely to succeed.
3294 */
3295void *cpu_physical_memory_map(target_phys_addr_t addr,
3296 target_phys_addr_t *plen,
3297 int is_write)
3298{
3299 target_phys_addr_t len = *plen;
3300 target_phys_addr_t done = 0;
3301 int l;
3302 uint8_t *ret = NULL;
3303 uint8_t *ptr;
3304 target_phys_addr_t page;
3305 unsigned long pd;
3306 PhysPageDesc *p;
3307 unsigned long addr1;
3308
3309 while (len > 0) {
3310 page = addr & TARGET_PAGE_MASK;
3311 l = (page + TARGET_PAGE_SIZE) - addr;
3312 if (l > len)
3313 l = len;
3314 p = phys_page_find(page >> TARGET_PAGE_BITS);
3315 if (!p) {
3316 pd = IO_MEM_UNASSIGNED;
3317 } else {
3318 pd = p->phys_offset;
3319 }
3320
3321 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3322 if (done || bounce.buffer) {
3323 break;
3324 }
3325 bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
3326 bounce.addr = addr;
3327 bounce.len = l;
3328 if (!is_write) {
3329 cpu_physical_memory_rw(addr, bounce.buffer, l, 0);
3330 }
3331 ptr = bounce.buffer;
3332 } else {
3333 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3334 ptr = qemu_get_ram_ptr(addr1);
3335 }
3336 if (!done) {
3337 ret = ptr;
3338 } else if (ret + done != ptr) {
3339 break;
3340 }
3341
3342 len -= l;
3343 addr += l;
3344 done += l;
3345 }
3346 *plen = done;
3347 return ret;
3348}
3349
3350/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
3351 * Will also mark the memory as dirty if is_write == 1. access_len gives
3352 * the amount of memory that was actually read or written by the caller.
3353 */
3354void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
3355 int is_write, target_phys_addr_t access_len)
3356{
3357 if (buffer != bounce.buffer) {
3358 if (is_write) {
3359 ram_addr_t addr1 = qemu_ram_addr_from_host(buffer);
3360 while (access_len) {
3361 unsigned l;
3362 l = TARGET_PAGE_SIZE;
3363 if (l > access_len)
3364 l = access_len;
3365 if (!cpu_physical_memory_is_dirty(addr1)) {
3366 /* invalidate code */
3367 tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
3368 /* set dirty bit */
3369 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3370 (0xff & ~CODE_DIRTY_FLAG);
3371 }
3372 addr1 += l;
3373 access_len -= l;
3374 }
3375 }
3376 return;
3377 }
3378 if (is_write) {
3379 cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
3380 }
3381 qemu_free(bounce.buffer);
3382 bounce.buffer = NULL;
3383 cpu_notify_map_clients();
3384}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003385
3386/* warning: addr must be aligned */
3387uint32_t ldl_phys(target_phys_addr_t addr)
3388{
3389 int io_index;
3390 uint8_t *ptr;
3391 uint32_t val;
3392 unsigned long pd;
3393 PhysPageDesc *p;
3394
3395 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3396 if (!p) {
3397 pd = IO_MEM_UNASSIGNED;
3398 } else {
3399 pd = p->phys_offset;
3400 }
3401
3402 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3403 !(pd & IO_MEM_ROMD)) {
3404 /* I/O case */
3405 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003406 if (p)
3407 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003408 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3409 } else {
3410 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003411 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003412 (addr & ~TARGET_PAGE_MASK);
3413 val = ldl_p(ptr);
3414 }
3415 return val;
3416}
3417
3418/* warning: addr must be aligned */
3419uint64_t ldq_phys(target_phys_addr_t addr)
3420{
3421 int io_index;
3422 uint8_t *ptr;
3423 uint64_t val;
3424 unsigned long pd;
3425 PhysPageDesc *p;
3426
3427 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3428 if (!p) {
3429 pd = IO_MEM_UNASSIGNED;
3430 } else {
3431 pd = p->phys_offset;
3432 }
3433
3434 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3435 !(pd & IO_MEM_ROMD)) {
3436 /* I/O case */
3437 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003438 if (p)
3439 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003440#ifdef TARGET_WORDS_BIGENDIAN
3441 val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
3442 val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
3443#else
3444 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3445 val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
3446#endif
3447 } else {
3448 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003449 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003450 (addr & ~TARGET_PAGE_MASK);
3451 val = ldq_p(ptr);
3452 }
3453 return val;
3454}
3455
3456/* XXX: optimize */
3457uint32_t ldub_phys(target_phys_addr_t addr)
3458{
3459 uint8_t val;
3460 cpu_physical_memory_read(addr, &val, 1);
3461 return val;
3462}
3463
3464/* XXX: optimize */
3465uint32_t lduw_phys(target_phys_addr_t addr)
3466{
3467 uint16_t val;
3468 cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
3469 return tswap16(val);
3470}
3471
3472/* warning: addr must be aligned. The ram page is not masked as dirty
3473 and the code inside is not invalidated. It is useful if the dirty
3474 bits are used to track modified PTEs */
3475void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
3476{
3477 int io_index;
3478 uint8_t *ptr;
3479 unsigned long pd;
3480 PhysPageDesc *p;
3481
3482 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3483 if (!p) {
3484 pd = IO_MEM_UNASSIGNED;
3485 } else {
3486 pd = p->phys_offset;
3487 }
3488
3489 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3490 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003491 if (p)
3492 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003493 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3494 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003495 unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3496 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003497 stl_p(ptr, val);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003498
3499 if (unlikely(in_migration)) {
3500 if (!cpu_physical_memory_is_dirty(addr1)) {
3501 /* invalidate code */
3502 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3503 /* set dirty bit */
3504 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3505 (0xff & ~CODE_DIRTY_FLAG);
3506 }
3507 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003508 }
3509}
3510
3511void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
3512{
3513 int io_index;
3514 uint8_t *ptr;
3515 unsigned long pd;
3516 PhysPageDesc *p;
3517
3518 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3519 if (!p) {
3520 pd = IO_MEM_UNASSIGNED;
3521 } else {
3522 pd = p->phys_offset;
3523 }
3524
3525 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3526 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003527 if (p)
3528 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003529#ifdef TARGET_WORDS_BIGENDIAN
3530 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
3531 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
3532#else
3533 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3534 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
3535#endif
3536 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003537 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003538 (addr & ~TARGET_PAGE_MASK);
3539 stq_p(ptr, val);
3540 }
3541}
3542
3543/* warning: addr must be aligned */
3544void stl_phys(target_phys_addr_t addr, uint32_t val)
3545{
3546 int io_index;
3547 uint8_t *ptr;
3548 unsigned long pd;
3549 PhysPageDesc *p;
3550
3551 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3552 if (!p) {
3553 pd = IO_MEM_UNASSIGNED;
3554 } else {
3555 pd = p->phys_offset;
3556 }
3557
3558 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3559 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003560 if (p)
3561 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003562 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3563 } else {
3564 unsigned long addr1;
3565 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3566 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003567 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003568 stl_p(ptr, val);
3569 if (!cpu_physical_memory_is_dirty(addr1)) {
3570 /* invalidate code */
3571 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3572 /* set dirty bit */
3573 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3574 (0xff & ~CODE_DIRTY_FLAG);
3575 }
3576 }
3577}
3578
3579/* XXX: optimize */
3580void stb_phys(target_phys_addr_t addr, uint32_t val)
3581{
3582 uint8_t v = val;
3583 cpu_physical_memory_write(addr, &v, 1);
3584}
3585
3586/* XXX: optimize */
3587void stw_phys(target_phys_addr_t addr, uint32_t val)
3588{
3589 uint16_t v = tswap16(val);
3590 cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
3591}
3592
3593/* XXX: optimize */
3594void stq_phys(target_phys_addr_t addr, uint64_t val)
3595{
3596 val = tswap64(val);
3597 cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
3598}
3599
3600#endif
3601
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003602/* virtual memory access for debug (includes writing to ROM) */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003603int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
3604 uint8_t *buf, int len, int is_write)
3605{
3606 int l;
3607 target_phys_addr_t phys_addr;
3608 target_ulong page;
3609
3610 while (len > 0) {
3611 page = addr & TARGET_PAGE_MASK;
3612 phys_addr = cpu_get_phys_page_debug(env, page);
3613 /* if no physical page mapped, return an error */
3614 if (phys_addr == -1)
3615 return -1;
3616 l = (page + TARGET_PAGE_SIZE) - addr;
3617 if (l > len)
3618 l = len;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003619 phys_addr += (addr & ~TARGET_PAGE_MASK);
3620#if !defined(CONFIG_USER_ONLY)
3621 if (is_write)
3622 cpu_physical_memory_write_rom(phys_addr, buf, l);
3623 else
3624#endif
3625 cpu_physical_memory_rw(phys_addr, buf, l, is_write);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003626 len -= l;
3627 buf += l;
3628 addr += l;
3629 }
3630 return 0;
3631}
3632
3633/* in deterministic execution mode, instructions doing device I/Os
3634 must be at the end of the TB */
3635void cpu_io_recompile(CPUState *env, void *retaddr)
3636{
3637 TranslationBlock *tb;
3638 uint32_t n, cflags;
3639 target_ulong pc, cs_base;
3640 uint64_t flags;
3641
3642 tb = tb_find_pc((unsigned long)retaddr);
3643 if (!tb) {
David 'Digit' Turner36411062010-12-22 17:34:53 +01003644 cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003645 retaddr);
3646 }
3647 n = env->icount_decr.u16.low + tb->icount;
3648 cpu_restore_state(tb, env, (unsigned long)retaddr, NULL);
3649 /* Calculate how many instructions had been executed before the fault
3650 occurred. */
3651 n = n - env->icount_decr.u16.low;
3652 /* Generate a new TB ending on the I/O insn. */
3653 n++;
3654 /* On MIPS and SH, delay slot instructions can only be restarted if
3655 they were already the first instruction in the TB. If this is not
3656 the first instruction in a TB then re-execute the preceding
3657 branch. */
3658#if defined(TARGET_MIPS)
3659 if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) {
3660 env->active_tc.PC -= 4;
3661 env->icount_decr.u16.low++;
3662 env->hflags &= ~MIPS_HFLAG_BMASK;
3663 }
3664#elif defined(TARGET_SH4)
3665 if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
3666 && n > 1) {
3667 env->pc -= 2;
3668 env->icount_decr.u16.low++;
3669 env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
3670 }
3671#endif
3672 /* This should never happen. */
3673 if (n > CF_COUNT_MASK)
3674 cpu_abort(env, "TB too big during recompile");
3675
3676 cflags = n | CF_LAST_IO;
3677 pc = tb->pc;
3678 cs_base = tb->cs_base;
3679 flags = tb->flags;
3680 tb_phys_invalidate(tb, -1);
3681 /* FIXME: In theory this could raise an exception. In practice
3682 we have already translated the block once so it's probably ok. */
3683 tb_gen_code(env, pc, cs_base, flags, cflags);
3684 /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
3685 the first in the TB) then we end up generating a whole new TB and
3686 repeating the fault, which is horribly inefficient.
3687 Better would be to execute just this insn uncached, or generate a
3688 second new TB. */
3689 cpu_resume_from_signal(env, NULL);
3690}
3691
David 'Digit' Turner36411062010-12-22 17:34:53 +01003692#if !defined(CONFIG_USER_ONLY)
3693
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003694void dump_exec_info(FILE *f,
3695 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
3696{
3697 int i, target_code_size, max_target_code_size;
3698 int direct_jmp_count, direct_jmp2_count, cross_page;
3699 TranslationBlock *tb;
3700
3701 target_code_size = 0;
3702 max_target_code_size = 0;
3703 cross_page = 0;
3704 direct_jmp_count = 0;
3705 direct_jmp2_count = 0;
3706 for(i = 0; i < nb_tbs; i++) {
3707 tb = &tbs[i];
3708 target_code_size += tb->size;
3709 if (tb->size > max_target_code_size)
3710 max_target_code_size = tb->size;
3711 if (tb->page_addr[1] != -1)
3712 cross_page++;
3713 if (tb->tb_next_offset[0] != 0xffff) {
3714 direct_jmp_count++;
3715 if (tb->tb_next_offset[1] != 0xffff) {
3716 direct_jmp2_count++;
3717 }
3718 }
3719 }
3720 /* XXX: avoid using doubles ? */
3721 cpu_fprintf(f, "Translation buffer state:\n");
3722 cpu_fprintf(f, "gen code size %ld/%ld\n",
3723 code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size);
David 'Digit' Turner36411062010-12-22 17:34:53 +01003724 cpu_fprintf(f, "TB count %d/%d\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003725 nb_tbs, code_gen_max_blocks);
3726 cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
3727 nb_tbs ? target_code_size / nb_tbs : 0,
3728 max_target_code_size);
3729 cpu_fprintf(f, "TB avg host size %d bytes (expansion ratio: %0.1f)\n",
3730 nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
3731 target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
3732 cpu_fprintf(f, "cross page TB count %d (%d%%)\n",
3733 cross_page,
3734 nb_tbs ? (cross_page * 100) / nb_tbs : 0);
3735 cpu_fprintf(f, "direct jump count %d (%d%%) (2 jumps=%d %d%%)\n",
3736 direct_jmp_count,
3737 nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
3738 direct_jmp2_count,
3739 nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
3740 cpu_fprintf(f, "\nStatistics:\n");
3741 cpu_fprintf(f, "TB flush count %d\n", tb_flush_count);
3742 cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
3743 cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count);
3744 tcg_dump_info(f, cpu_fprintf);
3745}
3746
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003747#define MMUSUFFIX _cmmu
3748#define GETPC() NULL
3749#define env cpu_single_env
3750#define SOFTMMU_CODE_ACCESS
3751
3752#define SHIFT 0
3753#include "softmmu_template.h"
3754
3755#define SHIFT 1
3756#include "softmmu_template.h"
3757
3758#define SHIFT 2
3759#include "softmmu_template.h"
3760
3761#define SHIFT 3
3762#include "softmmu_template.h"
3763
3764#undef env
3765
3766#endif