blob: 2a2a74fa93abfccebf2efa5bfb6b0edbd3d52ca3 [file] [log] [blame]
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001/*
2 * virtual page mapping and translated block handling
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070017 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080018 */
19#include "config.h"
20#ifdef _WIN32
21#define WIN32_LEAN_AND_MEAN
22#include <windows.h>
23#else
24#include <sys/types.h>
25#include <sys/mman.h>
26#endif
27#include <stdlib.h>
28#include <stdio.h>
29#include <stdarg.h>
30#include <string.h>
31#include <errno.h>
32#include <unistd.h>
33#include <inttypes.h>
34
35#include "cpu.h"
David 'Digit' Turner852088c2013-12-14 23:04:12 +010036#include "exec/exec-all.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080037#include "qemu-common.h"
38#include "tcg.h"
39#include "hw/hw.h"
David 'Digit' Turner84569132013-12-13 17:34:07 +010040#include "qemu/osdep.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +010041#include "sysemu/kvm.h"
David 'Digit' Turnere1e03df2013-12-15 00:42:21 +010042#include "exec/hax.h"
David 'Digit' Turner7a78db72013-12-14 11:46:01 +010043#include "qemu/timer.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080044#if defined(CONFIG_USER_ONLY)
45#include <qemu.h>
46#endif
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -080047#ifdef CONFIG_MEMCHECK
48#include "memcheck/memcheck_api.h"
49#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080050
51//#define DEBUG_TB_INVALIDATE
52//#define DEBUG_FLUSH
53//#define DEBUG_TLB
54//#define DEBUG_UNASSIGNED
55
56/* make various TB consistency checks */
57//#define DEBUG_TB_CHECK
58//#define DEBUG_TLB_CHECK
59
60//#define DEBUG_IOPORT
61//#define DEBUG_SUBPAGE
62
63#if !defined(CONFIG_USER_ONLY)
64/* TB consistency checks only implemented for usermode emulation. */
65#undef DEBUG_TB_CHECK
66#endif
67
68#define SMC_BITMAP_USE_THRESHOLD 10
69
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080070#if defined(TARGET_SPARC64)
71#define TARGET_PHYS_ADDR_SPACE_BITS 41
72#elif defined(TARGET_SPARC)
73#define TARGET_PHYS_ADDR_SPACE_BITS 36
74#elif defined(TARGET_ALPHA)
75#define TARGET_PHYS_ADDR_SPACE_BITS 42
76#define TARGET_VIRT_ADDR_SPACE_BITS 42
77#elif defined(TARGET_PPC64)
78#define TARGET_PHYS_ADDR_SPACE_BITS 42
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070079#elif defined(TARGET_X86_64)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080080#define TARGET_PHYS_ADDR_SPACE_BITS 42
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070081#elif defined(TARGET_I386)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080082#define TARGET_PHYS_ADDR_SPACE_BITS 36
83#else
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080084#define TARGET_PHYS_ADDR_SPACE_BITS 32
85#endif
86
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070087static TranslationBlock *tbs;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080088int code_gen_max_blocks;
89TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070090static int nb_tbs;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080091/* any access to the tbs or the page table must use this lock */
92spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
93
94#if defined(__arm__) || defined(__sparc_v9__)
95/* The prologue must be reachable with a direct jump. ARM and Sparc64
96 have limited branch ranges (possibly also PPC) so place it in a
97 section close to code segment. */
98#define code_gen_section \
99 __attribute__((__section__(".gen_code"))) \
100 __attribute__((aligned (32)))
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700101#elif defined(_WIN32)
102/* Maximum alignment for Win32 is 16. */
103#define code_gen_section \
104 __attribute__((aligned (16)))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800105#else
106#define code_gen_section \
107 __attribute__((aligned (32)))
108#endif
109
110uint8_t code_gen_prologue[1024] code_gen_section;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700111static uint8_t *code_gen_buffer;
112static unsigned long code_gen_buffer_size;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800113/* threshold to flush the translated code buffer */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700114static unsigned long code_gen_buffer_max_size;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800115uint8_t *code_gen_ptr;
116
117#if !defined(CONFIG_USER_ONLY)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800118int phys_ram_fd;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700119static int in_migration;
120
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200121RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list) };
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800122#endif
123
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100124CPUOldState *first_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800125/* current CPU in the current thread. It is only valid inside
126 cpu_exec() */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100127CPUOldState *cpu_single_env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800128/* 0 = Do not count executed instructions.
129 1 = Precise instruction counting.
130 2 = Adaptive rate instruction counting. */
131int use_icount = 0;
132/* Current instruction counter. While executing translated code this may
133 include some instructions that have not yet been executed. */
134int64_t qemu_icount;
135
136typedef struct PageDesc {
137 /* list of TBs intersecting this ram page */
138 TranslationBlock *first_tb;
139 /* in order to optimize self modifying code, we count the number
140 of lookups we do to a given page to use a bitmap */
141 unsigned int code_write_count;
142 uint8_t *code_bitmap;
143#if defined(CONFIG_USER_ONLY)
144 unsigned long flags;
145#endif
146} PageDesc;
147
148typedef struct PhysPageDesc {
149 /* offset in host memory of the page + io_index in the low bits */
150 ram_addr_t phys_offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700151 ram_addr_t region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800152} PhysPageDesc;
153
154#define L2_BITS 10
155#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
156/* XXX: this is a temporary hack for alpha target.
157 * In the future, this is to be replaced by a multi-level table
158 * to actually be able to handle the complete 64 bits address space.
159 */
160#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
161#else
162#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
163#endif
164
165#define L1_SIZE (1 << L1_BITS)
166#define L2_SIZE (1 << L2_BITS)
167
David 'Digit' Turnerf0729c72014-01-13 16:10:10 +0100168uintptr_t qemu_real_host_page_size;
169uintptr_t qemu_host_page_bits;
170uintptr_t qemu_host_page_size;
171uintptr_t qemu_host_page_mask;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800172
173/* XXX: for system emulation, it could just be an array */
174static PageDesc *l1_map[L1_SIZE];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700175static PhysPageDesc **l1_phys_map;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800176
177#if !defined(CONFIG_USER_ONLY)
178static void io_mem_init(void);
179
180/* io memory support */
181CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
182CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
183void *io_mem_opaque[IO_MEM_NB_ENTRIES];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700184static char io_mem_used[IO_MEM_NB_ENTRIES];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800185static int io_mem_watch;
186#endif
187
188/* log support */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700189#ifdef WIN32
190static const char *logfilename = "qemu.log";
191#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700192static const char *logfilename = "/tmp/qemu.log";
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700193#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800194FILE *logfile;
195int loglevel;
196static int log_append = 0;
197
198/* statistics */
199static int tlb_flush_count;
200static int tb_flush_count;
201static int tb_phys_invalidate_count;
202
203#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
204typedef struct subpage_t {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100205 hwaddr base;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800206 CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE][4];
207 CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE][4];
208 void *opaque[TARGET_PAGE_SIZE][2][4];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700209 ram_addr_t region_offset[TARGET_PAGE_SIZE][2][4];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800210} subpage_t;
211
212#ifdef _WIN32
213static void map_exec(void *addr, long size)
214{
215 DWORD old_protect;
216 VirtualProtect(addr, size,
217 PAGE_EXECUTE_READWRITE, &old_protect);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200218
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800219}
220#else
221static void map_exec(void *addr, long size)
222{
223 unsigned long start, end, page_size;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200224
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800225 page_size = getpagesize();
226 start = (unsigned long)addr;
227 start &= ~(page_size - 1);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200228
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800229 end = (unsigned long)addr + size;
230 end += page_size - 1;
231 end &= ~(page_size - 1);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200232
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800233 mprotect((void *)start, end - start,
234 PROT_READ | PROT_WRITE | PROT_EXEC);
235}
236#endif
237
238static void page_init(void)
239{
240 /* NOTE: we can always suppose that qemu_host_page_size >=
241 TARGET_PAGE_SIZE */
242#ifdef _WIN32
243 {
244 SYSTEM_INFO system_info;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800245
246 GetSystemInfo(&system_info);
247 qemu_real_host_page_size = system_info.dwPageSize;
248 }
249#else
250 qemu_real_host_page_size = getpagesize();
251#endif
252 if (qemu_host_page_size == 0)
253 qemu_host_page_size = qemu_real_host_page_size;
254 if (qemu_host_page_size < TARGET_PAGE_SIZE)
255 qemu_host_page_size = TARGET_PAGE_SIZE;
256 qemu_host_page_bits = 0;
257 while ((1 << qemu_host_page_bits) < qemu_host_page_size)
258 qemu_host_page_bits++;
259 qemu_host_page_mask = ~(qemu_host_page_size - 1);
260 l1_phys_map = qemu_vmalloc(L1_SIZE * sizeof(void *));
261 memset(l1_phys_map, 0, L1_SIZE * sizeof(void *));
262
263#if !defined(_WIN32) && defined(CONFIG_USER_ONLY)
264 {
265 long long startaddr, endaddr;
266 FILE *f;
267 int n;
268
269 mmap_lock();
270 last_brk = (unsigned long)sbrk(0);
271 f = fopen("/proc/self/maps", "r");
272 if (f) {
273 do {
274 n = fscanf (f, "%llx-%llx %*[^\n]\n", &startaddr, &endaddr);
275 if (n == 2) {
276 startaddr = MIN(startaddr,
277 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
278 endaddr = MIN(endaddr,
279 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
280 page_set_flags(startaddr & TARGET_PAGE_MASK,
281 TARGET_PAGE_ALIGN(endaddr),
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800282 PAGE_RESERVED);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800283 }
284 } while (!feof(f));
285 fclose(f);
286 }
287 mmap_unlock();
288 }
289#endif
290}
291
292static inline PageDesc **page_l1_map(target_ulong index)
293{
294#if TARGET_LONG_BITS > 32
295 /* Host memory outside guest VM. For 32-bit targets we have already
296 excluded high addresses. */
297 if (index > ((target_ulong)L2_SIZE * L1_SIZE))
298 return NULL;
299#endif
300 return &l1_map[index >> L2_BITS];
301}
302
303static inline PageDesc *page_find_alloc(target_ulong index)
304{
305 PageDesc **lp, *p;
306 lp = page_l1_map(index);
307 if (!lp)
308 return NULL;
309
310 p = *lp;
311 if (!p) {
312 /* allocate if not found */
313#if defined(CONFIG_USER_ONLY)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800314 size_t len = sizeof(PageDesc) * L2_SIZE;
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100315 /* Don't use g_malloc because it may recurse. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700316 p = mmap(NULL, len, PROT_READ | PROT_WRITE,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800317 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
318 *lp = p;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700319 if (h2g_valid(p)) {
320 unsigned long addr = h2g(p);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800321 page_set_flags(addr & TARGET_PAGE_MASK,
322 TARGET_PAGE_ALIGN(addr + len),
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800323 PAGE_RESERVED);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800324 }
325#else
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100326 p = g_malloc0(sizeof(PageDesc) * L2_SIZE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800327 *lp = p;
328#endif
329 }
330 return p + (index & (L2_SIZE - 1));
331}
332
333static inline PageDesc *page_find(target_ulong index)
334{
335 PageDesc **lp, *p;
336 lp = page_l1_map(index);
337 if (!lp)
338 return NULL;
339
340 p = *lp;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700341 if (!p) {
342 return NULL;
343 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800344 return p + (index & (L2_SIZE - 1));
345}
346
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100347static PhysPageDesc *phys_page_find_alloc(hwaddr index, int alloc)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800348{
349 void **lp, **p;
350 PhysPageDesc *pd;
351
352 p = (void **)l1_phys_map;
353#if TARGET_PHYS_ADDR_SPACE_BITS > 32
354
355#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
356#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
357#endif
358 lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1));
359 p = *lp;
360 if (!p) {
361 /* allocate if not found */
362 if (!alloc)
363 return NULL;
364 p = qemu_vmalloc(sizeof(void *) * L1_SIZE);
365 memset(p, 0, sizeof(void *) * L1_SIZE);
366 *lp = p;
367 }
368#endif
369 lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
370 pd = *lp;
371 if (!pd) {
372 int i;
373 /* allocate if not found */
374 if (!alloc)
375 return NULL;
376 pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
377 *lp = pd;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700378 for (i = 0; i < L2_SIZE; i++) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800379 pd[i].phys_offset = IO_MEM_UNASSIGNED;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700380 pd[i].region_offset = (index + i) << TARGET_PAGE_BITS;
381 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800382 }
383 return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
384}
385
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100386static inline PhysPageDesc *phys_page_find(hwaddr index)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800387{
388 return phys_page_find_alloc(index, 0);
389}
390
391#if !defined(CONFIG_USER_ONLY)
392static void tlb_protect_code(ram_addr_t ram_addr);
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100393static void tlb_unprotect_code_phys(CPUOldState *env, ram_addr_t ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800394 target_ulong vaddr);
395#define mmap_lock() do { } while(0)
396#define mmap_unlock() do { } while(0)
397#endif
398
399#define DEFAULT_CODE_GEN_BUFFER_SIZE (32 * 1024 * 1024)
400
401#if defined(CONFIG_USER_ONLY)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700402/* Currently it is not recommended to allocate big chunks of data in
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800403 user mode. It will change when a dedicated libc will be used */
404#define USE_STATIC_CODE_GEN_BUFFER
405#endif
406
407#ifdef USE_STATIC_CODE_GEN_BUFFER
408static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE];
409#endif
410
411static void code_gen_alloc(unsigned long tb_size)
412{
413#ifdef USE_STATIC_CODE_GEN_BUFFER
414 code_gen_buffer = static_code_gen_buffer;
415 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
416 map_exec(code_gen_buffer, code_gen_buffer_size);
417#else
418 code_gen_buffer_size = tb_size;
419 if (code_gen_buffer_size == 0) {
420#if defined(CONFIG_USER_ONLY)
421 /* in user mode, phys_ram_size is not meaningful */
422 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
423#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700424 /* XXX: needs adjustments */
425 code_gen_buffer_size = (unsigned long)(ram_size / 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800426#endif
427 }
428 if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE)
429 code_gen_buffer_size = MIN_CODE_GEN_BUFFER_SIZE;
430 /* The code gen buffer location may have constraints depending on
431 the host cpu and OS */
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200432#if defined(__linux__)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800433 {
434 int flags;
435 void *start = NULL;
436
437 flags = MAP_PRIVATE | MAP_ANONYMOUS;
438#if defined(__x86_64__)
439 flags |= MAP_32BIT;
440 /* Cannot map more than that */
441 if (code_gen_buffer_size > (800 * 1024 * 1024))
442 code_gen_buffer_size = (800 * 1024 * 1024);
443#elif defined(__sparc_v9__)
444 // Map the buffer below 2G, so we can use direct calls and branches
445 flags |= MAP_FIXED;
446 start = (void *) 0x60000000UL;
447 if (code_gen_buffer_size > (512 * 1024 * 1024))
448 code_gen_buffer_size = (512 * 1024 * 1024);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700449#elif defined(__arm__)
450 /* Map the buffer below 32M, so we can use direct calls and branches */
451 flags |= MAP_FIXED;
452 start = (void *) 0x01000000UL;
453 if (code_gen_buffer_size > 16 * 1024 * 1024)
454 code_gen_buffer_size = 16 * 1024 * 1024;
David 'Digit' Turner36411062010-12-22 17:34:53 +0100455#elif defined(__s390x__)
456 /* Map the buffer so that we can use direct calls and branches. */
457 /* We have a +- 4GB range on the branches; leave some slop. */
458 if (code_gen_buffer_size > (3ul * 1024 * 1024 * 1024)) {
459 code_gen_buffer_size = 3ul * 1024 * 1024 * 1024;
460 }
461 start = (void *)0x90000000UL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800462#endif
463 code_gen_buffer = mmap(start, code_gen_buffer_size,
464 PROT_WRITE | PROT_READ | PROT_EXEC,
465 flags, -1, 0);
466 if (code_gen_buffer == MAP_FAILED) {
467 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
468 exit(1);
469 }
470 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200471#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \
472 || defined(__DragonFly__) || defined(__OpenBSD__)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700473 {
474 int flags;
475 void *addr = NULL;
476 flags = MAP_PRIVATE | MAP_ANONYMOUS;
477#if defined(__x86_64__)
478 /* FreeBSD doesn't have MAP_32BIT, use MAP_FIXED and assume
479 * 0x40000000 is free */
480 flags |= MAP_FIXED;
481 addr = (void *)0x40000000;
482 /* Cannot map more than that */
483 if (code_gen_buffer_size > (800 * 1024 * 1024))
484 code_gen_buffer_size = (800 * 1024 * 1024);
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200485#elif defined(__sparc_v9__)
486 // Map the buffer below 2G, so we can use direct calls and branches
487 flags |= MAP_FIXED;
488 addr = (void *) 0x60000000UL;
489 if (code_gen_buffer_size > (512 * 1024 * 1024)) {
490 code_gen_buffer_size = (512 * 1024 * 1024);
491 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700492#endif
493 code_gen_buffer = mmap(addr, code_gen_buffer_size,
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200494 PROT_WRITE | PROT_READ | PROT_EXEC,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700495 flags, -1, 0);
496 if (code_gen_buffer == MAP_FAILED) {
497 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
498 exit(1);
499 }
500 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800501#else
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100502 code_gen_buffer = g_malloc(code_gen_buffer_size);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800503 map_exec(code_gen_buffer, code_gen_buffer_size);
504#endif
505#endif /* !USE_STATIC_CODE_GEN_BUFFER */
506 map_exec(code_gen_prologue, sizeof(code_gen_prologue));
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800507 code_gen_buffer_max_size = code_gen_buffer_size -
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800508 code_gen_max_block_size();
509 code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100510 tbs = g_malloc(code_gen_max_blocks * sizeof(TranslationBlock));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800511}
512
513/* Must be called before using the QEMU cpus. 'tb_size' is the size
514 (in bytes) allocated to the translation buffer. Zero means default
515 size. */
516void cpu_exec_init_all(unsigned long tb_size)
517{
518 cpu_gen_init();
519 code_gen_alloc(tb_size);
520 code_gen_ptr = code_gen_buffer;
521 page_init();
522#if !defined(CONFIG_USER_ONLY)
523 io_mem_init();
524#endif
David 'Digit' Turnerf1d9bf12011-05-11 18:19:41 +0200525#if !defined(CONFIG_USER_ONLY) || !defined(CONFIG_USE_GUEST_BASE)
526 /* There's no guest base to take into account, so go ahead and
527 initialize the prologue now. */
528 tcg_prologue_init(&tcg_ctx);
529#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800530}
531
532#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
533
534#define CPU_COMMON_SAVE_VERSION 1
535
536static void cpu_common_save(QEMUFile *f, void *opaque)
537{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100538 CPUOldState *env = opaque;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800539
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700540 cpu_synchronize_state(env, 0);
541
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800542 qemu_put_be32s(f, &env->halted);
543 qemu_put_be32s(f, &env->interrupt_request);
544}
545
546static int cpu_common_load(QEMUFile *f, void *opaque, int version_id)
547{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100548 CPUOldState *env = opaque;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800549
550 if (version_id != CPU_COMMON_SAVE_VERSION)
551 return -EINVAL;
552
553 qemu_get_be32s(f, &env->halted);
554 qemu_get_be32s(f, &env->interrupt_request);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700555 /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
556 version_id is increased. */
557 env->interrupt_request &= ~0x01;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800558 tlb_flush(env, 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700559 cpu_synchronize_state(env, 1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800560
561 return 0;
562}
563#endif
564
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100565CPUOldState *qemu_get_cpu(int cpu)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700566{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100567 CPUOldState *env = first_cpu;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700568
569 while (env) {
570 if (env->cpu_index == cpu)
571 break;
572 env = env->next_cpu;
573 }
574
575 return env;
576}
577
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100578void cpu_exec_init(CPUOldState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800579{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100580 CPUOldState **penv;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800581 int cpu_index;
582
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700583#if defined(CONFIG_USER_ONLY)
584 cpu_list_lock();
585#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800586 env->next_cpu = NULL;
587 penv = &first_cpu;
588 cpu_index = 0;
589 while (*penv != NULL) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700590 penv = &(*penv)->next_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800591 cpu_index++;
592 }
593 env->cpu_index = cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700594 env->numa_node = 0;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700595 QTAILQ_INIT(&env->breakpoints);
596 QTAILQ_INIT(&env->watchpoints);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800597 *penv = env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700598#if defined(CONFIG_USER_ONLY)
599 cpu_list_unlock();
600#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800601#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
602 register_savevm("cpu_common", cpu_index, CPU_COMMON_SAVE_VERSION,
603 cpu_common_save, cpu_common_load, env);
604 register_savevm("cpu", cpu_index, CPU_SAVE_VERSION,
605 cpu_save, cpu_load, env);
606#endif
607}
608
609static inline void invalidate_page_bitmap(PageDesc *p)
610{
611 if (p->code_bitmap) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100612 g_free(p->code_bitmap);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800613 p->code_bitmap = NULL;
614 }
615 p->code_write_count = 0;
616}
617
618/* set to NULL all the 'first_tb' fields in all PageDescs */
619static void page_flush_tb(void)
620{
621 int i, j;
622 PageDesc *p;
623
624 for(i = 0; i < L1_SIZE; i++) {
625 p = l1_map[i];
626 if (p) {
627 for(j = 0; j < L2_SIZE; j++) {
628 p->first_tb = NULL;
629 invalidate_page_bitmap(p);
630 p++;
631 }
632 }
633 }
634}
635
636/* flush all the translation blocks */
637/* XXX: tb_flush is currently not thread safe */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100638void tb_flush(CPUOldState *env1)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800639{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100640 CPUOldState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800641#if defined(DEBUG_FLUSH)
642 printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
643 (unsigned long)(code_gen_ptr - code_gen_buffer),
644 nb_tbs, nb_tbs > 0 ?
645 ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
646#endif
647 if ((unsigned long)(code_gen_ptr - code_gen_buffer) > code_gen_buffer_size)
648 cpu_abort(env1, "Internal error: code buffer overflow\n");
649
650 nb_tbs = 0;
651
652 for(env = first_cpu; env != NULL; env = env->next_cpu) {
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800653#ifdef CONFIG_MEMCHECK
654 int tb_to_clean;
655 for (tb_to_clean = 0; tb_to_clean < TB_JMP_CACHE_SIZE; tb_to_clean++) {
656 if (env->tb_jmp_cache[tb_to_clean] != NULL &&
657 env->tb_jmp_cache[tb_to_clean]->tpc2gpc != NULL) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100658 g_free(env->tb_jmp_cache[tb_to_clean]->tpc2gpc);
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800659 env->tb_jmp_cache[tb_to_clean]->tpc2gpc = NULL;
660 env->tb_jmp_cache[tb_to_clean]->tpc2gpc_pairs = 0;
661 }
662 }
663#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800664 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
665 }
666
667 memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
668 page_flush_tb();
669
670 code_gen_ptr = code_gen_buffer;
671 /* XXX: flush processor icache at this point if cache flush is
672 expensive */
673 tb_flush_count++;
674}
675
676#ifdef DEBUG_TB_CHECK
677
678static void tb_invalidate_check(target_ulong address)
679{
680 TranslationBlock *tb;
681 int i;
682 address &= TARGET_PAGE_MASK;
683 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
684 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
685 if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
686 address >= tb->pc + tb->size)) {
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700687 printf("ERROR invalidate: address=" TARGET_FMT_lx
688 " PC=%08lx size=%04x\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800689 address, (long)tb->pc, tb->size);
690 }
691 }
692 }
693}
694
695/* verify that all the pages have correct rights for code */
696static void tb_page_check(void)
697{
698 TranslationBlock *tb;
699 int i, flags1, flags2;
700
701 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
702 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
703 flags1 = page_get_flags(tb->pc);
704 flags2 = page_get_flags(tb->pc + tb->size - 1);
705 if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
706 printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
707 (long)tb->pc, tb->size, flags1, flags2);
708 }
709 }
710 }
711}
712
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800713#endif
714
715/* invalidate one TB */
716static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb,
717 int next_offset)
718{
719 TranslationBlock *tb1;
720 for(;;) {
721 tb1 = *ptb;
722 if (tb1 == tb) {
723 *ptb = *(TranslationBlock **)((char *)tb1 + next_offset);
724 break;
725 }
726 ptb = (TranslationBlock **)((char *)tb1 + next_offset);
727 }
728}
729
730static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
731{
732 TranslationBlock *tb1;
733 unsigned int n1;
734
735 for(;;) {
736 tb1 = *ptb;
737 n1 = (long)tb1 & 3;
738 tb1 = (TranslationBlock *)((long)tb1 & ~3);
739 if (tb1 == tb) {
740 *ptb = tb1->page_next[n1];
741 break;
742 }
743 ptb = &tb1->page_next[n1];
744 }
745}
746
747static inline void tb_jmp_remove(TranslationBlock *tb, int n)
748{
749 TranslationBlock *tb1, **ptb;
750 unsigned int n1;
751
752 ptb = &tb->jmp_next[n];
753 tb1 = *ptb;
754 if (tb1) {
755 /* find tb(n) in circular list */
756 for(;;) {
757 tb1 = *ptb;
758 n1 = (long)tb1 & 3;
759 tb1 = (TranslationBlock *)((long)tb1 & ~3);
760 if (n1 == n && tb1 == tb)
761 break;
762 if (n1 == 2) {
763 ptb = &tb1->jmp_first;
764 } else {
765 ptb = &tb1->jmp_next[n1];
766 }
767 }
768 /* now we can suppress tb(n) from the list */
769 *ptb = tb->jmp_next[n];
770
771 tb->jmp_next[n] = NULL;
772 }
773}
774
775/* reset the jump entry 'n' of a TB so that it is not chained to
776 another TB */
777static inline void tb_reset_jump(TranslationBlock *tb, int n)
778{
779 tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
780}
781
782void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr)
783{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100784 CPUOldState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800785 PageDesc *p;
786 unsigned int h, n1;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100787 hwaddr phys_pc;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800788 TranslationBlock *tb1, *tb2;
789
790 /* remove the TB from the hash list */
791 phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
792 h = tb_phys_hash_func(phys_pc);
793 tb_remove(&tb_phys_hash[h], tb,
794 offsetof(TranslationBlock, phys_hash_next));
795
796 /* remove the TB from the page list */
797 if (tb->page_addr[0] != page_addr) {
798 p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
799 tb_page_remove(&p->first_tb, tb);
800 invalidate_page_bitmap(p);
801 }
802 if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
803 p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
804 tb_page_remove(&p->first_tb, tb);
805 invalidate_page_bitmap(p);
806 }
807
808 tb_invalidated_flag = 1;
809
810 /* remove the TB from the hash list */
811 h = tb_jmp_cache_hash_func(tb->pc);
812 for(env = first_cpu; env != NULL; env = env->next_cpu) {
813 if (env->tb_jmp_cache[h] == tb)
814 env->tb_jmp_cache[h] = NULL;
815 }
816
817 /* suppress this TB from the two jump lists */
818 tb_jmp_remove(tb, 0);
819 tb_jmp_remove(tb, 1);
820
821 /* suppress any remaining jumps to this TB */
822 tb1 = tb->jmp_first;
823 for(;;) {
824 n1 = (long)tb1 & 3;
825 if (n1 == 2)
826 break;
827 tb1 = (TranslationBlock *)((long)tb1 & ~3);
828 tb2 = tb1->jmp_next[n1];
829 tb_reset_jump(tb1, n1);
830 tb1->jmp_next[n1] = NULL;
831 tb1 = tb2;
832 }
833 tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
834
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800835#ifdef CONFIG_MEMCHECK
836 if (tb->tpc2gpc != NULL) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100837 g_free(tb->tpc2gpc);
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800838 tb->tpc2gpc = NULL;
839 tb->tpc2gpc_pairs = 0;
840 }
841#endif // CONFIG_MEMCHECK
842
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800843 tb_phys_invalidate_count++;
844}
845
846static inline void set_bits(uint8_t *tab, int start, int len)
847{
848 int end, mask, end1;
849
850 end = start + len;
851 tab += start >> 3;
852 mask = 0xff << (start & 7);
853 if ((start & ~7) == (end & ~7)) {
854 if (start < end) {
855 mask &= ~(0xff << (end & 7));
856 *tab |= mask;
857 }
858 } else {
859 *tab++ |= mask;
860 start = (start + 8) & ~7;
861 end1 = end & ~7;
862 while (start < end1) {
863 *tab++ = 0xff;
864 start += 8;
865 }
866 if (start < end) {
867 mask = ~(0xff << (end & 7));
868 *tab |= mask;
869 }
870 }
871}
872
873static void build_page_bitmap(PageDesc *p)
874{
875 int n, tb_start, tb_end;
876 TranslationBlock *tb;
877
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100878 p->code_bitmap = g_malloc0(TARGET_PAGE_SIZE / 8);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800879
880 tb = p->first_tb;
881 while (tb != NULL) {
882 n = (long)tb & 3;
883 tb = (TranslationBlock *)((long)tb & ~3);
884 /* NOTE: this is subtle as a TB may span two physical pages */
885 if (n == 0) {
886 /* NOTE: tb_end may be after the end of the page, but
887 it is not a problem */
888 tb_start = tb->pc & ~TARGET_PAGE_MASK;
889 tb_end = tb_start + tb->size;
890 if (tb_end > TARGET_PAGE_SIZE)
891 tb_end = TARGET_PAGE_SIZE;
892 } else {
893 tb_start = 0;
894 tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
895 }
896 set_bits(p->code_bitmap, tb_start, tb_end - tb_start);
897 tb = tb->page_next[n];
898 }
899}
900
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100901TranslationBlock *tb_gen_code(CPUOldState *env,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800902 target_ulong pc, target_ulong cs_base,
903 int flags, int cflags)
904{
905 TranslationBlock *tb;
906 uint8_t *tc_ptr;
907 target_ulong phys_pc, phys_page2, virt_page2;
908 int code_gen_size;
909
910 phys_pc = get_phys_addr_code(env, pc);
911 tb = tb_alloc(pc);
912 if (!tb) {
913 /* flush must be done */
914 tb_flush(env);
915 /* cannot fail at this point */
916 tb = tb_alloc(pc);
917 /* Don't forget to invalidate previous TB info. */
918 tb_invalidated_flag = 1;
919 }
920 tc_ptr = code_gen_ptr;
921 tb->tc_ptr = tc_ptr;
922 tb->cs_base = cs_base;
923 tb->flags = flags;
924 tb->cflags = cflags;
925#ifdef CONFIG_TRACE
926 tb->bb_rec = NULL;
927 tb->prev_time = 0;
928#endif
929 cpu_gen_code(env, tb, &code_gen_size);
930 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
931
932 /* check next page if needed */
933 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
934 phys_page2 = -1;
935 if ((pc & TARGET_PAGE_MASK) != virt_page2) {
936 phys_page2 = get_phys_addr_code(env, virt_page2);
937 }
938 tb_link_phys(tb, phys_pc, phys_page2);
939 return tb;
940}
941
942/* invalidate all TBs which intersect with the target physical page
943 starting in range [start;end[. NOTE: start and end must refer to
944 the same physical page. 'is_cpu_write_access' should be true if called
945 from a real cpu write access: the virtual CPU will exit the current
946 TB if code is modified inside this TB. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100947void tb_invalidate_phys_page_range(hwaddr start, hwaddr end,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800948 int is_cpu_write_access)
949{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700950 TranslationBlock *tb, *tb_next, *saved_tb;
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100951 CPUOldState *env = cpu_single_env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800952 target_ulong tb_start, tb_end;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700953 PageDesc *p;
954 int n;
955#ifdef TARGET_HAS_PRECISE_SMC
956 int current_tb_not_found = is_cpu_write_access;
957 TranslationBlock *current_tb = NULL;
958 int current_tb_modified = 0;
959 target_ulong current_pc = 0;
960 target_ulong current_cs_base = 0;
961 int current_flags = 0;
962#endif /* TARGET_HAS_PRECISE_SMC */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800963
964 p = page_find(start >> TARGET_PAGE_BITS);
965 if (!p)
966 return;
967 if (!p->code_bitmap &&
968 ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
969 is_cpu_write_access) {
970 /* build code bitmap */
971 build_page_bitmap(p);
972 }
973
974 /* we remove all the TBs in the range [start, end[ */
975 /* 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 -0800976 tb = p->first_tb;
977 while (tb != NULL) {
978 n = (long)tb & 3;
979 tb = (TranslationBlock *)((long)tb & ~3);
980 tb_next = tb->page_next[n];
981 /* NOTE: this is subtle as a TB may span two physical pages */
982 if (n == 0) {
983 /* NOTE: tb_end may be after the end of the page, but
984 it is not a problem */
985 tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
986 tb_end = tb_start + tb->size;
987 } else {
988 tb_start = tb->page_addr[1];
989 tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
990 }
991 if (!(tb_end <= start || tb_start >= end)) {
992#ifdef TARGET_HAS_PRECISE_SMC
993 if (current_tb_not_found) {
994 current_tb_not_found = 0;
995 current_tb = NULL;
996 if (env->mem_io_pc) {
997 /* now we have a real cpu fault */
998 current_tb = tb_find_pc(env->mem_io_pc);
999 }
1000 }
1001 if (current_tb == tb &&
1002 (current_tb->cflags & CF_COUNT_MASK) != 1) {
1003 /* If we are modifying the current TB, we must stop
1004 its execution. We could be more precise by checking
1005 that the modification is after the current PC, but it
1006 would require a specialized function to partially
1007 restore the CPU state */
1008
1009 current_tb_modified = 1;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02001010 cpu_restore_state(current_tb, env, env->mem_io_pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001011 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
1012 &current_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001013 }
1014#endif /* TARGET_HAS_PRECISE_SMC */
1015 /* we need to do that to handle the case where a signal
1016 occurs while doing tb_phys_invalidate() */
1017 saved_tb = NULL;
1018 if (env) {
1019 saved_tb = env->current_tb;
1020 env->current_tb = NULL;
1021 }
1022 tb_phys_invalidate(tb, -1);
1023 if (env) {
1024 env->current_tb = saved_tb;
1025 if (env->interrupt_request && env->current_tb)
1026 cpu_interrupt(env, env->interrupt_request);
1027 }
1028 }
1029 tb = tb_next;
1030 }
1031#if !defined(CONFIG_USER_ONLY)
1032 /* if no code remaining, no need to continue to use slow writes */
1033 if (!p->first_tb) {
1034 invalidate_page_bitmap(p);
1035 if (is_cpu_write_access) {
1036 tlb_unprotect_code_phys(env, start, env->mem_io_vaddr);
1037 }
1038 }
1039#endif
1040#ifdef TARGET_HAS_PRECISE_SMC
1041 if (current_tb_modified) {
1042 /* we generate a block containing just the instruction
1043 modifying the memory. It will ensure that it cannot modify
1044 itself */
1045 env->current_tb = NULL;
1046 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1047 cpu_resume_from_signal(env, NULL);
1048 }
1049#endif
1050}
1051
1052/* len must be <= 8 and start must be a multiple of len */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001053static inline void tb_invalidate_phys_page_fast(hwaddr start, int len)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001054{
1055 PageDesc *p;
1056 int offset, b;
1057#if 0
1058 if (1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001059 qemu_log("modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
1060 cpu_single_env->mem_io_vaddr, len,
1061 cpu_single_env->eip,
1062 cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001063 }
1064#endif
1065 p = page_find(start >> TARGET_PAGE_BITS);
1066 if (!p)
1067 return;
1068 if (p->code_bitmap) {
1069 offset = start & ~TARGET_PAGE_MASK;
1070 b = p->code_bitmap[offset >> 3] >> (offset & 7);
1071 if (b & ((1 << len) - 1))
1072 goto do_invalidate;
1073 } else {
1074 do_invalidate:
1075 tb_invalidate_phys_page_range(start, start + len, 1);
1076 }
1077}
1078
1079#if !defined(CONFIG_SOFTMMU)
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001080static void tb_invalidate_phys_page(hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001081 unsigned long pc, void *puc)
1082{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001083 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001084 PageDesc *p;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001085 int n;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001086#ifdef TARGET_HAS_PRECISE_SMC
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001087 TranslationBlock *current_tb = NULL;
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001088 CPUOldState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001089 int current_tb_modified = 0;
1090 target_ulong current_pc = 0;
1091 target_ulong current_cs_base = 0;
1092 int current_flags = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001093#endif
1094
1095 addr &= TARGET_PAGE_MASK;
1096 p = page_find(addr >> TARGET_PAGE_BITS);
1097 if (!p)
1098 return;
1099 tb = p->first_tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001100#ifdef TARGET_HAS_PRECISE_SMC
1101 if (tb && pc != 0) {
1102 current_tb = tb_find_pc(pc);
1103 }
1104#endif
1105 while (tb != NULL) {
1106 n = (long)tb & 3;
1107 tb = (TranslationBlock *)((long)tb & ~3);
1108#ifdef TARGET_HAS_PRECISE_SMC
1109 if (current_tb == tb &&
1110 (current_tb->cflags & CF_COUNT_MASK) != 1) {
1111 /* If we are modifying the current TB, we must stop
1112 its execution. We could be more precise by checking
1113 that the modification is after the current PC, but it
1114 would require a specialized function to partially
1115 restore the CPU state */
1116
1117 current_tb_modified = 1;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02001118 cpu_restore_state(current_tb, env, pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001119 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
1120 &current_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001121 }
1122#endif /* TARGET_HAS_PRECISE_SMC */
1123 tb_phys_invalidate(tb, addr);
1124 tb = tb->page_next[n];
1125 }
1126 p->first_tb = NULL;
1127#ifdef TARGET_HAS_PRECISE_SMC
1128 if (current_tb_modified) {
1129 /* we generate a block containing just the instruction
1130 modifying the memory. It will ensure that it cannot modify
1131 itself */
1132 env->current_tb = NULL;
1133 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1134 cpu_resume_from_signal(env, puc);
1135 }
1136#endif
1137}
1138#endif
1139
1140/* add the tb in the target page and protect it if necessary */
1141static inline void tb_alloc_page(TranslationBlock *tb,
1142 unsigned int n, target_ulong page_addr)
1143{
1144 PageDesc *p;
1145 TranslationBlock *last_first_tb;
1146
1147 tb->page_addr[n] = page_addr;
1148 p = page_find_alloc(page_addr >> TARGET_PAGE_BITS);
1149 tb->page_next[n] = p->first_tb;
1150 last_first_tb = p->first_tb;
1151 p->first_tb = (TranslationBlock *)((long)tb | n);
1152 invalidate_page_bitmap(p);
1153
1154#if defined(TARGET_HAS_SMC) || 1
1155
1156#if defined(CONFIG_USER_ONLY)
1157 if (p->flags & PAGE_WRITE) {
1158 target_ulong addr;
1159 PageDesc *p2;
1160 int prot;
1161
1162 /* force the host page as non writable (writes will have a
1163 page fault + mprotect overhead) */
1164 page_addr &= qemu_host_page_mask;
1165 prot = 0;
1166 for(addr = page_addr; addr < page_addr + qemu_host_page_size;
1167 addr += TARGET_PAGE_SIZE) {
1168
1169 p2 = page_find (addr >> TARGET_PAGE_BITS);
1170 if (!p2)
1171 continue;
1172 prot |= p2->flags;
1173 p2->flags &= ~PAGE_WRITE;
1174 page_get_flags(addr);
1175 }
1176 mprotect(g2h(page_addr), qemu_host_page_size,
1177 (prot & PAGE_BITS) & ~PAGE_WRITE);
1178#ifdef DEBUG_TB_INVALIDATE
1179 printf("protecting code page: 0x" TARGET_FMT_lx "\n",
1180 page_addr);
1181#endif
1182 }
1183#else
1184 /* if some code is already present, then the pages are already
1185 protected. So we handle the case where only the first TB is
1186 allocated in a physical page */
1187 if (!last_first_tb) {
1188 tlb_protect_code(page_addr);
1189 }
1190#endif
1191
1192#endif /* TARGET_HAS_SMC */
1193}
1194
1195/* Allocate a new translation block. Flush the translation buffer if
1196 too many translation blocks or too much generated code. */
1197TranslationBlock *tb_alloc(target_ulong pc)
1198{
1199 TranslationBlock *tb;
1200
1201 if (nb_tbs >= code_gen_max_blocks ||
1202 (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
1203 return NULL;
1204 tb = &tbs[nb_tbs++];
1205 tb->pc = pc;
1206 tb->cflags = 0;
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -08001207#ifdef CONFIG_MEMCHECK
1208 tb->tpc2gpc = NULL;
1209 tb->tpc2gpc_pairs = 0;
1210#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001211 return tb;
1212}
1213
1214void tb_free(TranslationBlock *tb)
1215{
1216 /* In practice this is mostly used for single use temporary TB
1217 Ignore the hard cases and just back up if this TB happens to
1218 be the last one generated. */
1219 if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) {
1220 code_gen_ptr = tb->tc_ptr;
1221 nb_tbs--;
1222 }
1223}
1224
1225/* add a new TB and link it to the physical page tables. phys_page2 is
1226 (-1) to indicate that only one page contains the TB. */
1227void tb_link_phys(TranslationBlock *tb,
1228 target_ulong phys_pc, target_ulong phys_page2)
1229{
1230 unsigned int h;
1231 TranslationBlock **ptb;
1232
1233 /* Grab the mmap lock to stop another thread invalidating this TB
1234 before we are done. */
1235 mmap_lock();
1236 /* add in the physical hash table */
1237 h = tb_phys_hash_func(phys_pc);
1238 ptb = &tb_phys_hash[h];
1239 tb->phys_hash_next = *ptb;
1240 *ptb = tb;
1241
1242 /* add in the page list */
1243 tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK);
1244 if (phys_page2 != -1)
1245 tb_alloc_page(tb, 1, phys_page2);
1246 else
1247 tb->page_addr[1] = -1;
1248
1249 tb->jmp_first = (TranslationBlock *)((long)tb | 2);
1250 tb->jmp_next[0] = NULL;
1251 tb->jmp_next[1] = NULL;
1252
1253 /* init original jump addresses */
1254 if (tb->tb_next_offset[0] != 0xffff)
1255 tb_reset_jump(tb, 0);
1256 if (tb->tb_next_offset[1] != 0xffff)
1257 tb_reset_jump(tb, 1);
1258
1259#ifdef DEBUG_TB_CHECK
1260 tb_page_check();
1261#endif
1262 mmap_unlock();
1263}
1264
1265/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
1266 tb[1].tc_ptr. Return NULL if not found */
1267TranslationBlock *tb_find_pc(unsigned long tc_ptr)
1268{
1269 int m_min, m_max, m;
1270 unsigned long v;
1271 TranslationBlock *tb;
1272
1273 if (nb_tbs <= 0)
1274 return NULL;
1275 if (tc_ptr < (unsigned long)code_gen_buffer ||
1276 tc_ptr >= (unsigned long)code_gen_ptr)
1277 return NULL;
1278 /* binary search (cf Knuth) */
1279 m_min = 0;
1280 m_max = nb_tbs - 1;
1281 while (m_min <= m_max) {
1282 m = (m_min + m_max) >> 1;
1283 tb = &tbs[m];
1284 v = (unsigned long)tb->tc_ptr;
1285 if (v == tc_ptr)
1286 return tb;
1287 else if (tc_ptr < v) {
1288 m_max = m - 1;
1289 } else {
1290 m_min = m + 1;
1291 }
1292 }
1293 return &tbs[m_max];
1294}
1295
1296static void tb_reset_jump_recursive(TranslationBlock *tb);
1297
1298static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
1299{
1300 TranslationBlock *tb1, *tb_next, **ptb;
1301 unsigned int n1;
1302
1303 tb1 = tb->jmp_next[n];
1304 if (tb1 != NULL) {
1305 /* find head of list */
1306 for(;;) {
1307 n1 = (long)tb1 & 3;
1308 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1309 if (n1 == 2)
1310 break;
1311 tb1 = tb1->jmp_next[n1];
1312 }
1313 /* we are now sure now that tb jumps to tb1 */
1314 tb_next = tb1;
1315
1316 /* remove tb from the jmp_first list */
1317 ptb = &tb_next->jmp_first;
1318 for(;;) {
1319 tb1 = *ptb;
1320 n1 = (long)tb1 & 3;
1321 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1322 if (n1 == n && tb1 == tb)
1323 break;
1324 ptb = &tb1->jmp_next[n1];
1325 }
1326 *ptb = tb->jmp_next[n];
1327 tb->jmp_next[n] = NULL;
1328
1329 /* suppress the jump to next tb in generated code */
1330 tb_reset_jump(tb, n);
1331
1332 /* suppress jumps in the tb on which we could have jumped */
1333 tb_reset_jump_recursive(tb_next);
1334 }
1335}
1336
1337static void tb_reset_jump_recursive(TranslationBlock *tb)
1338{
1339 tb_reset_jump_recursive2(tb, 0);
1340 tb_reset_jump_recursive2(tb, 1);
1341}
1342
1343#if defined(TARGET_HAS_ICE)
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001344static void breakpoint_invalidate(CPUOldState *env, target_ulong pc)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001345{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001346 hwaddr addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001347 target_ulong pd;
1348 ram_addr_t ram_addr;
1349 PhysPageDesc *p;
1350
1351 addr = cpu_get_phys_page_debug(env, pc);
1352 p = phys_page_find(addr >> TARGET_PAGE_BITS);
1353 if (!p) {
1354 pd = IO_MEM_UNASSIGNED;
1355 } else {
1356 pd = p->phys_offset;
1357 }
1358 ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
1359 tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
1360}
1361#endif
1362
1363/* Add a watchpoint. */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001364int cpu_watchpoint_insert(CPUOldState *env, target_ulong addr, target_ulong len,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001365 int flags, CPUWatchpoint **watchpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001366{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001367 target_ulong len_mask = ~(len - 1);
1368 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001369
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001370 /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
1371 if ((len != 1 && len != 2 && len != 4 && len != 8) || (addr & ~len_mask)) {
1372 fprintf(stderr, "qemu: tried to set invalid watchpoint at "
1373 TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
1374 return -EINVAL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001375 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001376 wp = g_malloc(sizeof(*wp));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001377
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001378 wp->vaddr = addr;
1379 wp->len_mask = len_mask;
1380 wp->flags = flags;
1381
1382 /* keep all GDB-injected watchpoints in front */
1383 if (flags & BP_GDB)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001384 QTAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001385 else
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001386 QTAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001387
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001388 tlb_flush_page(env, addr);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001389
1390 if (watchpoint)
1391 *watchpoint = wp;
1392 return 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001393}
1394
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001395/* Remove a specific watchpoint. */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001396int cpu_watchpoint_remove(CPUOldState *env, target_ulong addr, target_ulong len,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001397 int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001398{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001399 target_ulong len_mask = ~(len - 1);
1400 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001401
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001402 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001403 if (addr == wp->vaddr && len_mask == wp->len_mask
1404 && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
1405 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001406 return 0;
1407 }
1408 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001409 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001410}
1411
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001412/* Remove a specific watchpoint by reference. */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001413void cpu_watchpoint_remove_by_ref(CPUOldState *env, CPUWatchpoint *watchpoint)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001414{
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001415 QTAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001416
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001417 tlb_flush_page(env, watchpoint->vaddr);
1418
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001419 g_free(watchpoint);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001420}
1421
1422/* Remove all matching watchpoints. */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001423void cpu_watchpoint_remove_all(CPUOldState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001424{
1425 CPUWatchpoint *wp, *next;
1426
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001427 QTAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001428 if (wp->flags & mask)
1429 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001430 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001431}
1432
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001433/* Add a breakpoint. */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001434int cpu_breakpoint_insert(CPUOldState *env, target_ulong pc, int flags,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001435 CPUBreakpoint **breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001436{
1437#if defined(TARGET_HAS_ICE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001438 CPUBreakpoint *bp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001439
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001440 bp = g_malloc(sizeof(*bp));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001441
1442 bp->pc = pc;
1443 bp->flags = flags;
1444
1445 /* keep all GDB-injected breakpoints in front */
1446 if (flags & BP_GDB)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001447 QTAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001448 else
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001449 QTAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001450
1451 breakpoint_invalidate(env, pc);
1452
1453 if (breakpoint)
1454 *breakpoint = bp;
1455 return 0;
1456#else
1457 return -ENOSYS;
1458#endif
1459}
1460
1461/* Remove a specific breakpoint. */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001462int cpu_breakpoint_remove(CPUOldState *env, target_ulong pc, int flags)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001463{
1464#if defined(TARGET_HAS_ICE)
1465 CPUBreakpoint *bp;
1466
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001467 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001468 if (bp->pc == pc && bp->flags == flags) {
1469 cpu_breakpoint_remove_by_ref(env, bp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001470 return 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001471 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001472 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001473 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001474#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001475 return -ENOSYS;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001476#endif
1477}
1478
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001479/* Remove a specific breakpoint by reference. */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001480void cpu_breakpoint_remove_by_ref(CPUOldState *env, CPUBreakpoint *breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001481{
1482#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001483 QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001484
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001485 breakpoint_invalidate(env, breakpoint->pc);
1486
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001487 g_free(breakpoint);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001488#endif
1489}
1490
1491/* Remove all matching breakpoints. */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001492void cpu_breakpoint_remove_all(CPUOldState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001493{
1494#if defined(TARGET_HAS_ICE)
1495 CPUBreakpoint *bp, *next;
1496
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001497 QTAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001498 if (bp->flags & mask)
1499 cpu_breakpoint_remove_by_ref(env, bp);
1500 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001501#endif
1502}
1503
1504/* enable or disable single step mode. EXCP_DEBUG is returned by the
1505 CPU loop after each instruction */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001506void cpu_single_step(CPUOldState *env, int enabled)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001507{
1508#if defined(TARGET_HAS_ICE)
1509 if (env->singlestep_enabled != enabled) {
1510 env->singlestep_enabled = enabled;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001511 if (kvm_enabled())
1512 kvm_update_guest_debug(env, 0);
1513 else {
1514 /* must flush all the translated code to avoid inconsistencies */
1515 /* XXX: only flush what is necessary */
1516 tb_flush(env);
1517 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001518 }
1519#endif
1520}
1521
1522/* enable or disable low levels log */
1523void cpu_set_log(int log_flags)
1524{
1525 loglevel = log_flags;
1526 if (loglevel && !logfile) {
1527 logfile = fopen(logfilename, log_append ? "a" : "w");
1528 if (!logfile) {
1529 perror(logfilename);
Iliyan Malchev4a2c9dd2012-04-02 08:20:56 -07001530 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001531 }
1532#if !defined(CONFIG_SOFTMMU)
1533 /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1534 {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001535 static char logfile_buf[4096];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001536 setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1537 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001538#elif !defined(_WIN32)
1539 /* Win32 doesn't support line-buffering and requires size >= 2 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001540 setvbuf(logfile, NULL, _IOLBF, 0);
1541#endif
1542 log_append = 1;
1543 }
1544 if (!loglevel && logfile) {
1545 fclose(logfile);
1546 logfile = NULL;
1547 }
1548}
1549
1550void cpu_set_log_filename(const char *filename)
1551{
1552 logfilename = strdup(filename);
1553 if (logfile) {
1554 fclose(logfile);
1555 logfile = NULL;
1556 }
1557 cpu_set_log(loglevel);
1558}
1559
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001560static void cpu_unlink_tb(CPUOldState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001561{
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001562 /* FIXME: TB unchaining isn't SMP safe. For now just ignore the
1563 problem and hope the cpu will stop of its own accord. For userspace
1564 emulation this often isn't actually as bad as it sounds. Often
1565 signals are used primarily to interrupt blocking syscalls. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001566 TranslationBlock *tb;
1567 static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
1568
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001569 spin_lock(&interrupt_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001570 tb = env->current_tb;
1571 /* if the cpu is currently executing code, we must unlink it and
1572 all the potentially executing TB */
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001573 if (tb) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001574 env->current_tb = NULL;
1575 tb_reset_jump_recursive(tb);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001576 }
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001577 spin_unlock(&interrupt_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001578}
1579
1580/* mask must never be zero, except for A20 change call */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001581void cpu_interrupt(CPUOldState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001582{
1583 int old_mask;
1584
1585 old_mask = env->interrupt_request;
1586 env->interrupt_request |= mask;
1587
1588#ifndef CONFIG_USER_ONLY
1589 /*
1590 * If called from iothread context, wake the target cpu in
1591 * case its halted.
1592 */
1593 if (!qemu_cpu_self(env)) {
1594 qemu_cpu_kick(env);
1595 return;
1596 }
1597#endif
1598
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001599 if (use_icount) {
1600 env->icount_decr.u16.high = 0xffff;
1601#ifndef CONFIG_USER_ONLY
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001602 if (!can_do_io(env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001603 && (mask & ~old_mask) != 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001604 cpu_abort(env, "Raised interrupt while not in I/O function");
1605 }
1606#endif
1607 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001608 cpu_unlink_tb(env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001609 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001610}
1611
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001612void cpu_reset_interrupt(CPUOldState *env, int mask)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001613{
1614 env->interrupt_request &= ~mask;
1615}
1616
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001617void cpu_exit(CPUOldState *env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001618{
1619 env->exit_request = 1;
1620 cpu_unlink_tb(env);
1621}
1622
1623const CPULogItem cpu_log_items[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001624 { CPU_LOG_TB_OUT_ASM, "out_asm",
1625 "show generated host assembly code for each compiled TB" },
1626 { CPU_LOG_TB_IN_ASM, "in_asm",
1627 "show target assembly code for each compiled TB" },
1628 { CPU_LOG_TB_OP, "op",
1629 "show micro ops for each compiled TB" },
1630 { CPU_LOG_TB_OP_OPT, "op_opt",
1631 "show micro ops "
1632#ifdef TARGET_I386
1633 "before eflags optimization and "
1634#endif
1635 "after liveness analysis" },
1636 { CPU_LOG_INT, "int",
1637 "show interrupts/exceptions in short format" },
1638 { CPU_LOG_EXEC, "exec",
1639 "show trace before each executed TB (lots of logs)" },
1640 { CPU_LOG_TB_CPU, "cpu",
1641 "show CPU state before block translation" },
1642#ifdef TARGET_I386
1643 { CPU_LOG_PCALL, "pcall",
1644 "show protected mode far calls/returns/exceptions" },
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001645 { CPU_LOG_RESET, "cpu_reset",
1646 "show CPU state before CPU resets" },
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001647#endif
1648#ifdef DEBUG_IOPORT
1649 { CPU_LOG_IOPORT, "ioport",
1650 "show all i/o ports accesses" },
1651#endif
1652 { 0, NULL, NULL },
1653};
1654
1655static int cmp1(const char *s1, int n, const char *s2)
1656{
1657 if (strlen(s2) != n)
1658 return 0;
1659 return memcmp(s1, s2, n) == 0;
1660}
1661
1662/* takes a comma separated list of log masks. Return 0 if error. */
1663int cpu_str_to_log_mask(const char *str)
1664{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001665 const CPULogItem *item;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001666 int mask;
1667 const char *p, *p1;
1668
1669 p = str;
1670 mask = 0;
1671 for(;;) {
1672 p1 = strchr(p, ',');
1673 if (!p1)
1674 p1 = p + strlen(p);
1675 if(cmp1(p,p1-p,"all")) {
1676 for(item = cpu_log_items; item->mask != 0; item++) {
1677 mask |= item->mask;
1678 }
1679 } else {
1680 for(item = cpu_log_items; item->mask != 0; item++) {
1681 if (cmp1(p, p1 - p, item->name))
1682 goto found;
1683 }
1684 return 0;
1685 }
1686 found:
1687 mask |= item->mask;
1688 if (*p1 != ',')
1689 break;
1690 p = p1 + 1;
1691 }
1692 return mask;
1693}
1694
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001695void cpu_abort(CPUOldState *env, const char *fmt, ...)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001696{
1697 va_list ap;
1698 va_list ap2;
1699
1700 va_start(ap, fmt);
1701 va_copy(ap2, ap);
1702 fprintf(stderr, "qemu: fatal: ");
1703 vfprintf(stderr, fmt, ap);
1704 fprintf(stderr, "\n");
1705#ifdef TARGET_I386
1706 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1707#else
1708 cpu_dump_state(env, stderr, fprintf, 0);
1709#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001710 if (qemu_log_enabled()) {
1711 qemu_log("qemu: fatal: ");
1712 qemu_log_vprintf(fmt, ap2);
1713 qemu_log("\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001714#ifdef TARGET_I386
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001715 log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001716#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001717 log_cpu_state(env, 0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001718#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001719 qemu_log_flush();
1720 qemu_log_close();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001721 }
1722 va_end(ap2);
1723 va_end(ap);
David 'Digit' Turner36411062010-12-22 17:34:53 +01001724#if defined(CONFIG_USER_ONLY)
1725 {
1726 struct sigaction act;
1727 sigfillset(&act.sa_mask);
1728 act.sa_handler = SIG_DFL;
1729 sigaction(SIGABRT, &act, NULL);
1730 }
1731#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001732 abort();
1733}
1734
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001735CPUOldState *cpu_copy(CPUOldState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001736{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001737 CPUOldState *new_env = cpu_init(env->cpu_model_str);
1738 CPUOldState *next_cpu = new_env->next_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001739 int cpu_index = new_env->cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001740#if defined(TARGET_HAS_ICE)
1741 CPUBreakpoint *bp;
1742 CPUWatchpoint *wp;
1743#endif
1744
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001745 memcpy(new_env, env, sizeof(CPUOldState));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001746
1747 /* Preserve chaining and index. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001748 new_env->next_cpu = next_cpu;
1749 new_env->cpu_index = cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001750
1751 /* Clone all break/watchpoints.
1752 Note: Once we support ptrace with hw-debug register access, make sure
1753 BP_CPU break/watchpoints are handled correctly on clone. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001754 QTAILQ_INIT(&env->breakpoints);
1755 QTAILQ_INIT(&env->watchpoints);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001756#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001757 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001758 cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
1759 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001760 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001761 cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
1762 wp->flags, NULL);
1763 }
1764#endif
1765
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001766 return new_env;
1767}
1768
1769#if !defined(CONFIG_USER_ONLY)
1770
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001771static inline void tlb_flush_jmp_cache(CPUOldState *env, target_ulong addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001772{
1773 unsigned int i;
1774
1775 /* Discard jump cache entries for any tb which might potentially
1776 overlap the flushed page. */
1777 i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02001778 memset (&env->tb_jmp_cache[i], 0,
David 'Digit' Turner36411062010-12-22 17:34:53 +01001779 TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001780
1781 i = tb_jmp_cache_hash_page(addr);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02001782 memset (&env->tb_jmp_cache[i], 0,
David 'Digit' Turner36411062010-12-22 17:34:53 +01001783 TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001784}
1785
1786/* NOTE: if flush_global is true, also flush global entries (not
1787 implemented yet) */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001788void tlb_flush(CPUOldState *env, int flush_global)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001789{
1790 int i;
1791
1792#if defined(DEBUG_TLB)
1793 printf("tlb_flush:\n");
1794#endif
1795 /* must reset current TB so that interrupts cannot modify the
1796 links while we are modifying them */
1797 env->current_tb = NULL;
1798
1799 for(i = 0; i < CPU_TLB_SIZE; i++) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001800 int mmu_idx;
1801 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1802 env->tlb_table[mmu_idx][i].addr_read = -1;
1803 env->tlb_table[mmu_idx][i].addr_write = -1;
1804 env->tlb_table[mmu_idx][i].addr_code = -1;
1805 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001806 }
1807
1808 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
1809
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001810#ifdef CONFIG_KQEMU
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001811 if (env->kqemu_enabled) {
1812 kqemu_flush(env, flush_global);
1813 }
1814#endif
1815 tlb_flush_count++;
1816}
1817
1818static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
1819{
1820 if (addr == (tlb_entry->addr_read &
1821 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1822 addr == (tlb_entry->addr_write &
1823 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1824 addr == (tlb_entry->addr_code &
1825 (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1826 tlb_entry->addr_read = -1;
1827 tlb_entry->addr_write = -1;
1828 tlb_entry->addr_code = -1;
1829 }
1830}
1831
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001832void tlb_flush_page(CPUOldState *env, target_ulong addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001833{
1834 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001835 int mmu_idx;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001836
1837#if defined(DEBUG_TLB)
1838 printf("tlb_flush_page: " TARGET_FMT_lx "\n", addr);
1839#endif
1840 /* must reset current TB so that interrupts cannot modify the
1841 links while we are modifying them */
1842 env->current_tb = NULL;
1843
1844 addr &= TARGET_PAGE_MASK;
1845 i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001846 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++)
1847 tlb_flush_entry(&env->tlb_table[mmu_idx][i], addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001848
1849 tlb_flush_jmp_cache(env, addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001850}
1851
1852/* update the TLBs so that writes to code in the virtual page 'addr'
1853 can be detected */
1854static void tlb_protect_code(ram_addr_t ram_addr)
1855{
1856 cpu_physical_memory_reset_dirty(ram_addr,
1857 ram_addr + TARGET_PAGE_SIZE,
1858 CODE_DIRTY_FLAG);
1859}
1860
1861/* update the TLB so that writes in physical page 'phys_addr' are no longer
1862 tested for self modifying code */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001863static void tlb_unprotect_code_phys(CPUOldState *env, ram_addr_t ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001864 target_ulong vaddr)
1865{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001866 cpu_physical_memory_set_dirty_flags(ram_addr, CODE_DIRTY_FLAG);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001867}
1868
1869static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
1870 unsigned long start, unsigned long length)
1871{
1872 unsigned long addr;
1873 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1874 addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
1875 if ((addr - start) < length) {
1876 tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
1877 }
1878 }
1879}
1880
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001881/* Note: start and end must be within the same ram block. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001882void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
1883 int dirty_flags)
1884{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001885 CPUOldState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001886 unsigned long length, start1;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001887 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001888
1889 start &= TARGET_PAGE_MASK;
1890 end = TARGET_PAGE_ALIGN(end);
1891
1892 length = end - start;
1893 if (length == 0)
1894 return;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001895 cpu_physical_memory_mask_dirty_range(start, length, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001896
1897 /* we modify the TLB cache so that the dirty bit will be set again
1898 when accessing the range */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001899 start1 = (unsigned long)qemu_safe_ram_ptr(start);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001900 /* Chek that we don't span multiple blocks - this breaks the
1901 address comparisons below. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001902 if ((unsigned long)qemu_safe_ram_ptr(end - 1) - start1
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001903 != (end - 1) - start) {
1904 abort();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001905 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001906
1907 for(env = first_cpu; env != NULL; env = env->next_cpu) {
1908 int mmu_idx;
1909 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1910 for(i = 0; i < CPU_TLB_SIZE; i++)
1911 tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
1912 start1, length);
1913 }
1914 }
1915}
1916
1917int cpu_physical_memory_set_dirty_tracking(int enable)
1918{
1919 in_migration = enable;
1920 if (kvm_enabled()) {
1921 return kvm_set_migration_log(enable);
1922 }
1923 return 0;
1924}
1925
1926int cpu_physical_memory_get_dirty_tracking(void)
1927{
1928 return in_migration;
1929}
1930
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001931int cpu_physical_sync_dirty_bitmap(hwaddr start_addr,
1932 hwaddr end_addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001933{
1934 int ret = 0;
1935
1936 if (kvm_enabled())
1937 ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
1938 return ret;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001939}
1940
1941static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1942{
1943 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001944 void *p;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001945
1946 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001947 p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
1948 + tlb_entry->addend);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001949 ram_addr = qemu_ram_addr_from_host_nofail(p);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001950 if (!cpu_physical_memory_is_dirty(ram_addr)) {
1951 tlb_entry->addr_write |= TLB_NOTDIRTY;
1952 }
1953 }
1954}
1955
1956/* update the TLB according to the current state of the dirty bits */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001957void cpu_tlb_update_dirty(CPUOldState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001958{
1959 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001960 int mmu_idx;
1961 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1962 for(i = 0; i < CPU_TLB_SIZE; i++)
1963 tlb_update_dirty(&env->tlb_table[mmu_idx][i]);
1964 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001965}
1966
1967static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, target_ulong vaddr)
1968{
1969 if (tlb_entry->addr_write == (vaddr | TLB_NOTDIRTY))
1970 tlb_entry->addr_write = vaddr;
1971}
1972
1973/* update the TLB corresponding to virtual page vaddr
1974 so that it is no longer dirty */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001975static inline void tlb_set_dirty(CPUOldState *env, target_ulong vaddr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001976{
1977 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001978 int mmu_idx;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001979
1980 vaddr &= TARGET_PAGE_MASK;
1981 i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001982 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++)
1983 tlb_set_dirty1(&env->tlb_table[mmu_idx][i], vaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001984}
1985
1986/* add a new TLB entry. At most one entry for a given virtual address
1987 is permitted. Return 0 if OK or 2 if the page could not be mapped
1988 (can only happen in non SOFTMMU mode for I/O pages or pages
1989 conflicting with the host address space). */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001990int tlb_set_page_exec(CPUOldState *env, target_ulong vaddr,
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001991 hwaddr paddr, int prot,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001992 int mmu_idx, int is_softmmu)
1993{
1994 PhysPageDesc *p;
1995 unsigned long pd;
1996 unsigned int index;
1997 target_ulong address;
1998 target_ulong code_address;
David 'Digit' Turnerd9b6cb92010-10-20 19:07:28 +02001999 ptrdiff_t addend;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002000 int ret;
2001 CPUTLBEntry *te;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002002 CPUWatchpoint *wp;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002003 hwaddr iotlb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002004
2005 p = phys_page_find(paddr >> TARGET_PAGE_BITS);
2006 if (!p) {
2007 pd = IO_MEM_UNASSIGNED;
2008 } else {
2009 pd = p->phys_offset;
2010 }
2011#if defined(DEBUG_TLB)
2012 printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x idx=%d smmu=%d pd=0x%08lx\n",
2013 vaddr, (int)paddr, prot, mmu_idx, is_softmmu, pd);
2014#endif
2015
2016 ret = 0;
2017 address = vaddr;
2018 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
2019 /* IO memory case (romd handled later) */
2020 address |= TLB_MMIO;
2021 }
David 'Digit' Turnerd9b6cb92010-10-20 19:07:28 +02002022 addend = (ptrdiff_t)qemu_get_ram_ptr(pd & TARGET_PAGE_MASK);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002023 if ((pd & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
2024 /* Normal RAM. */
2025 iotlb = pd & TARGET_PAGE_MASK;
2026 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM)
2027 iotlb |= IO_MEM_NOTDIRTY;
2028 else
2029 iotlb |= IO_MEM_ROM;
2030 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002031 /* IO handlers are currently passed a physical address.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002032 It would be nice to pass an offset from the base address
2033 of that region. This would avoid having to special case RAM,
2034 and avoid full address decoding in every device.
2035 We can't use the high bits of pd for this because
2036 IO_MEM_ROMD uses these as a ram address. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002037 iotlb = (pd & ~TARGET_PAGE_MASK);
2038 if (p) {
2039 iotlb += p->region_offset;
2040 } else {
2041 iotlb += paddr;
2042 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002043 }
2044
2045 code_address = address;
2046 /* Make accesses to pages with watchpoints go via the
2047 watchpoint trap routines. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002048 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002049 if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002050 iotlb = io_mem_watch + paddr;
2051 /* TODO: The memory case can be optimized by not trapping
2052 reads of pages with a write breakpoint. */
2053 address |= TLB_MMIO;
2054 }
2055 }
2056
2057 index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
2058 env->iotlb[mmu_idx][index] = iotlb - vaddr;
2059 te = &env->tlb_table[mmu_idx][index];
2060 te->addend = addend - vaddr;
2061 if (prot & PAGE_READ) {
2062 te->addr_read = address;
2063 } else {
2064 te->addr_read = -1;
2065 }
2066
2067 if (prot & PAGE_EXEC) {
2068 te->addr_code = code_address;
2069 } else {
2070 te->addr_code = -1;
2071 }
2072 if (prot & PAGE_WRITE) {
2073 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM ||
2074 (pd & IO_MEM_ROMD)) {
2075 /* Write access calls the I/O callback. */
2076 te->addr_write = address | TLB_MMIO;
2077 } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
2078 !cpu_physical_memory_is_dirty(pd)) {
2079 te->addr_write = address | TLB_NOTDIRTY;
2080 } else {
2081 te->addr_write = address;
2082 }
2083 } else {
2084 te->addr_write = -1;
2085 }
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -08002086
2087#ifdef CONFIG_MEMCHECK
2088 /*
2089 * If we have memchecker running, we need to make sure that page, cached
2090 * into TLB as the result of this operation will comply with our requirement
2091 * to cause __ld/__stx_mmu being called for memory access on the pages
2092 * containing memory blocks that require access violation checks.
2093 *
2094 * We need to check with memory checker if we should invalidate this page
2095 * iff:
2096 * - Memchecking is enabled.
2097 * - Page that's been cached belongs to the user space.
2098 * - Request to cache this page didn't come from softmmu. We're covered
2099 * there, because after page was cached here we will invalidate it in
2100 * the __ld/__stx_mmu wrapper.
2101 * - Cached page belongs to RAM, not I/O area.
2102 * - Page is cached for read, or write access.
2103 */
2104 if (memcheck_instrument_mmu && mmu_idx == 1 && !is_softmmu &&
2105 (pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
2106 (prot & (PAGE_READ | PAGE_WRITE)) &&
2107 memcheck_is_checked(vaddr & TARGET_PAGE_MASK, TARGET_PAGE_SIZE)) {
2108 if (prot & PAGE_READ) {
2109 te->addr_read ^= TARGET_PAGE_MASK;
2110 }
2111 if (prot & PAGE_WRITE) {
2112 te->addr_write ^= TARGET_PAGE_MASK;
2113 }
2114 }
2115#endif // CONFIG_MEMCHECK
2116
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002117 return ret;
2118}
2119
2120#else
2121
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002122void tlb_flush(CPUOldState *env, int flush_global)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002123{
2124}
2125
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002126void tlb_flush_page(CPUOldState *env, target_ulong addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002127{
2128}
2129
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002130int tlb_set_page_exec(CPUOldState *env, target_ulong vaddr,
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002131 hwaddr paddr, int prot,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002132 int mmu_idx, int is_softmmu)
2133{
2134 return 0;
2135}
2136
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002137/*
2138 * Walks guest process memory "regions" one by one
2139 * and calls callback function 'fn' for each region.
2140 */
2141int walk_memory_regions(void *priv,
2142 int (*fn)(void *, unsigned long, unsigned long, unsigned long))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002143{
2144 unsigned long start, end;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002145 PageDesc *p = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002146 int i, j, prot, prot1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002147 int rc = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002148
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002149 start = end = -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002150 prot = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002151
2152 for (i = 0; i <= L1_SIZE; i++) {
2153 p = (i < L1_SIZE) ? l1_map[i] : NULL;
2154 for (j = 0; j < L2_SIZE; j++) {
2155 prot1 = (p == NULL) ? 0 : p[j].flags;
2156 /*
2157 * "region" is one continuous chunk of memory
2158 * that has same protection flags set.
2159 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002160 if (prot1 != prot) {
2161 end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
2162 if (start != -1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002163 rc = (*fn)(priv, start, end, prot);
2164 /* callback can stop iteration by returning != 0 */
2165 if (rc != 0)
2166 return (rc);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002167 }
2168 if (prot1 != 0)
2169 start = end;
2170 else
2171 start = -1;
2172 prot = prot1;
2173 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002174 if (p == NULL)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002175 break;
2176 }
2177 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002178 return (rc);
2179}
2180
2181static int dump_region(void *priv, unsigned long start,
2182 unsigned long end, unsigned long prot)
2183{
2184 FILE *f = (FILE *)priv;
2185
2186 (void) fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
2187 start, end, end - start,
2188 ((prot & PAGE_READ) ? 'r' : '-'),
2189 ((prot & PAGE_WRITE) ? 'w' : '-'),
2190 ((prot & PAGE_EXEC) ? 'x' : '-'));
2191
2192 return (0);
2193}
2194
2195/* dump memory mappings */
2196void page_dump(FILE *f)
2197{
2198 (void) fprintf(f, "%-8s %-8s %-8s %s\n",
2199 "start", "end", "size", "prot");
2200 walk_memory_regions(f, dump_region);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002201}
2202
2203int page_get_flags(target_ulong address)
2204{
2205 PageDesc *p;
2206
2207 p = page_find(address >> TARGET_PAGE_BITS);
2208 if (!p)
2209 return 0;
2210 return p->flags;
2211}
2212
David 'Digit' Turner36411062010-12-22 17:34:53 +01002213/* Modify the flags of a page and invalidate the code if necessary.
2214 The flag PAGE_WRITE_ORG is positioned automatically depending
2215 on PAGE_WRITE. The mmap_lock should already be held. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002216void page_set_flags(target_ulong start, target_ulong end, int flags)
2217{
2218 PageDesc *p;
2219 target_ulong addr;
2220
2221 /* mmap_lock should already be held. */
2222 start = start & TARGET_PAGE_MASK;
2223 end = TARGET_PAGE_ALIGN(end);
2224 if (flags & PAGE_WRITE)
2225 flags |= PAGE_WRITE_ORG;
2226 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2227 p = page_find_alloc(addr >> TARGET_PAGE_BITS);
2228 /* We may be called for host regions that are outside guest
2229 address space. */
2230 if (!p)
2231 return;
2232 /* if the write protection is set, then we invalidate the code
2233 inside */
2234 if (!(p->flags & PAGE_WRITE) &&
2235 (flags & PAGE_WRITE) &&
2236 p->first_tb) {
2237 tb_invalidate_phys_page(addr, 0, NULL);
2238 }
2239 p->flags = flags;
2240 }
2241}
2242
2243int page_check_range(target_ulong start, target_ulong len, int flags)
2244{
2245 PageDesc *p;
2246 target_ulong end;
2247 target_ulong addr;
2248
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002249 if (start + len < start)
2250 /* we've wrapped around */
2251 return -1;
2252
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002253 end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
2254 start = start & TARGET_PAGE_MASK;
2255
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002256 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2257 p = page_find(addr >> TARGET_PAGE_BITS);
2258 if( !p )
2259 return -1;
2260 if( !(p->flags & PAGE_VALID) )
2261 return -1;
2262
2263 if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
2264 return -1;
2265 if (flags & PAGE_WRITE) {
2266 if (!(p->flags & PAGE_WRITE_ORG))
2267 return -1;
2268 /* unprotect the page if it was put read-only because it
2269 contains translated code */
2270 if (!(p->flags & PAGE_WRITE)) {
2271 if (!page_unprotect(addr, 0, NULL))
2272 return -1;
2273 }
2274 return 0;
2275 }
2276 }
2277 return 0;
2278}
2279
2280/* called from signal handler: invalidate the code and unprotect the
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002281 page. Return TRUE if the fault was successfully handled. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002282int page_unprotect(target_ulong address, unsigned long pc, void *puc)
2283{
2284 unsigned int page_index, prot, pindex;
2285 PageDesc *p, *p1;
2286 target_ulong host_start, host_end, addr;
2287
2288 /* Technically this isn't safe inside a signal handler. However we
2289 know this only ever happens in a synchronous SEGV handler, so in
2290 practice it seems to be ok. */
2291 mmap_lock();
2292
2293 host_start = address & qemu_host_page_mask;
2294 page_index = host_start >> TARGET_PAGE_BITS;
2295 p1 = page_find(page_index);
2296 if (!p1) {
2297 mmap_unlock();
2298 return 0;
2299 }
2300 host_end = host_start + qemu_host_page_size;
2301 p = p1;
2302 prot = 0;
2303 for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
2304 prot |= p->flags;
2305 p++;
2306 }
2307 /* if the page was really writable, then we change its
2308 protection back to writable */
2309 if (prot & PAGE_WRITE_ORG) {
2310 pindex = (address - host_start) >> TARGET_PAGE_BITS;
2311 if (!(p1[pindex].flags & PAGE_WRITE)) {
2312 mprotect((void *)g2h(host_start), qemu_host_page_size,
2313 (prot & PAGE_BITS) | PAGE_WRITE);
2314 p1[pindex].flags |= PAGE_WRITE;
2315 /* and since the content will be modified, we must invalidate
2316 the corresponding translated code. */
2317 tb_invalidate_phys_page(address, pc, puc);
2318#ifdef DEBUG_TB_CHECK
2319 tb_invalidate_check(address);
2320#endif
2321 mmap_unlock();
2322 return 1;
2323 }
2324 }
2325 mmap_unlock();
2326 return 0;
2327}
2328
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002329static inline void tlb_set_dirty(CPUOldState *env,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002330 unsigned long addr, target_ulong vaddr)
2331{
2332}
2333#endif /* defined(CONFIG_USER_ONLY) */
2334
2335#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002336
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002337static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002338 ram_addr_t memory, ram_addr_t region_offset);
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002339static void *subpage_init (hwaddr base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002340 ram_addr_t orig_memory, ram_addr_t region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002341#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
2342 need_subpage) \
2343 do { \
2344 if (addr > start_addr) \
2345 start_addr2 = 0; \
2346 else { \
2347 start_addr2 = start_addr & ~TARGET_PAGE_MASK; \
2348 if (start_addr2 > 0) \
2349 need_subpage = 1; \
2350 } \
2351 \
2352 if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE) \
2353 end_addr2 = TARGET_PAGE_SIZE - 1; \
2354 else { \
2355 end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
2356 if (end_addr2 < TARGET_PAGE_SIZE - 1) \
2357 need_subpage = 1; \
2358 } \
2359 } while (0)
2360
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002361/* register physical memory.
2362 For RAM, 'size' must be a multiple of the target page size.
2363 If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002364 io memory page. The address used when calling the IO function is
2365 the offset from the start of the region, plus region_offset. Both
2366 start_addr and region_offset are rounded down to a page boundary
2367 before calculating this offset. This should not be a problem unless
2368 the low bits of start_addr and region_offset differ. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002369void cpu_register_physical_memory_log(hwaddr start_addr,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002370 ram_addr_t size,
2371 ram_addr_t phys_offset,
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002372 ram_addr_t region_offset,
2373 bool log_dirty)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002374{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002375 hwaddr addr, end_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002376 PhysPageDesc *p;
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002377 CPUOldState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002378 ram_addr_t orig_size = size;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002379 subpage_t *subpage;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002380
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002381 if (kvm_enabled())
2382 kvm_set_phys_mem(start_addr, size, phys_offset);
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002383#ifdef CONFIG_HAX
2384 if (hax_enabled())
2385 hax_set_phys_mem(start_addr, size, phys_offset);
2386#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002387
2388 if (phys_offset == IO_MEM_UNASSIGNED) {
2389 region_offset = start_addr;
2390 }
2391 region_offset &= TARGET_PAGE_MASK;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002392 size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002393 end_addr = start_addr + (hwaddr)size;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002394
2395 addr = start_addr;
2396 do {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002397 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2398 if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
2399 ram_addr_t orig_memory = p->phys_offset;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002400 hwaddr start_addr2, end_addr2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002401 int need_subpage = 0;
2402
2403 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2404 need_subpage);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002405 if (need_subpage) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002406 if (!(orig_memory & IO_MEM_SUBPAGE)) {
2407 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002408 &p->phys_offset, orig_memory,
2409 p->region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002410 } else {
2411 subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
2412 >> IO_MEM_SHIFT];
2413 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002414 subpage_register(subpage, start_addr2, end_addr2, phys_offset,
2415 region_offset);
2416 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002417 } else {
2418 p->phys_offset = phys_offset;
2419 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2420 (phys_offset & IO_MEM_ROMD))
2421 phys_offset += TARGET_PAGE_SIZE;
2422 }
2423 } else {
2424 p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2425 p->phys_offset = phys_offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002426 p->region_offset = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002427 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002428 (phys_offset & IO_MEM_ROMD)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002429 phys_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002430 } else {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002431 hwaddr start_addr2, end_addr2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002432 int need_subpage = 0;
2433
2434 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2435 end_addr2, need_subpage);
2436
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002437 if (need_subpage) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002438 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002439 &p->phys_offset, IO_MEM_UNASSIGNED,
2440 addr & TARGET_PAGE_MASK);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002441 subpage_register(subpage, start_addr2, end_addr2,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002442 phys_offset, region_offset);
2443 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002444 }
2445 }
2446 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002447 region_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002448 addr += TARGET_PAGE_SIZE;
2449 } while (addr != end_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002450
2451 /* since each CPU stores ram addresses in its TLB cache, we must
2452 reset the modified entries */
2453 /* XXX: slow ! */
2454 for(env = first_cpu; env != NULL; env = env->next_cpu) {
2455 tlb_flush(env, 1);
2456 }
2457}
2458
2459/* XXX: temporary until new memory mapping API */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002460ram_addr_t cpu_get_physical_page_desc(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002461{
2462 PhysPageDesc *p;
2463
2464 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2465 if (!p)
2466 return IO_MEM_UNASSIGNED;
2467 return p->phys_offset;
2468}
2469
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002470void qemu_register_coalesced_mmio(hwaddr addr, ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002471{
2472 if (kvm_enabled())
2473 kvm_coalesce_mmio_region(addr, size);
2474}
2475
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002476void qemu_unregister_coalesced_mmio(hwaddr addr, ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002477{
2478 if (kvm_enabled())
2479 kvm_uncoalesce_mmio_region(addr, size);
2480}
2481
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002482static ram_addr_t find_ram_offset(ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002483{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002484 RAMBlock *block, *next_block;
2485 ram_addr_t offset = 0, mingap = ULONG_MAX;
2486
2487 if (QLIST_EMPTY(&ram_list.blocks))
2488 return 0;
2489
2490 QLIST_FOREACH(block, &ram_list.blocks, next) {
2491 ram_addr_t end, next = ULONG_MAX;
2492
2493 end = block->offset + block->length;
2494
2495 QLIST_FOREACH(next_block, &ram_list.blocks, next) {
2496 if (next_block->offset >= end) {
2497 next = MIN(next, next_block->offset);
2498 }
2499 }
2500 if (next - end >= size && next - end < mingap) {
2501 offset = end;
2502 mingap = next - end;
2503 }
2504 }
2505 return offset;
2506}
2507
2508static ram_addr_t last_ram_offset(void)
2509{
2510 RAMBlock *block;
2511 ram_addr_t last = 0;
2512
2513 QLIST_FOREACH(block, &ram_list.blocks, next)
2514 last = MAX(last, block->offset + block->length);
2515
2516 return last;
2517}
2518
2519ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
2520 ram_addr_t size, void *host)
2521{
2522 RAMBlock *new_block, *block;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002523
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002524 size = TARGET_PAGE_ALIGN(size);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002525 new_block = g_malloc0(sizeof(*new_block));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002526
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002527#if 0
2528 if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
2529 char *id = dev->parent_bus->info->get_dev_path(dev);
2530 if (id) {
2531 snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002532 g_free(id);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002533 }
2534 }
2535#endif
2536 pstrcat(new_block->idstr, sizeof(new_block->idstr), name);
2537
2538 QLIST_FOREACH(block, &ram_list.blocks, next) {
2539 if (!strcmp(block->idstr, new_block->idstr)) {
2540 fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n",
2541 new_block->idstr);
2542 abort();
2543 }
2544 }
2545
2546 if (host) {
2547 new_block->host = host;
2548 new_block->flags |= RAM_PREALLOC_MASK;
2549 } else {
2550 if (mem_path) {
2551#if 0 && defined (__linux__) && !defined(TARGET_S390X)
2552 new_block->host = file_ram_alloc(new_block, size, mem_path);
2553 if (!new_block->host) {
2554 new_block->host = qemu_vmalloc(size);
2555 qemu_madvise(new_block->host, size, QEMU_MADV_MERGEABLE);
2556 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002557#else
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002558 fprintf(stderr, "-mem-path option unsupported\n");
2559 exit(1);
2560#endif
2561 } else {
2562#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2563 /* XXX S390 KVM requires the topmost vma of the RAM to be < 256GB */
2564 new_block->host = mmap((void*)0x1000000, size,
2565 PROT_EXEC|PROT_READ|PROT_WRITE,
2566 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
2567#else
2568 new_block->host = qemu_vmalloc(size);
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002569
2570#ifdef CONFIG_HAX
2571 /*
2572 * In HAX, qemu allocates the virtual address, and HAX kernel
2573 * module populates the region with physical memory. Currently
2574 * we don’t populate guest memory on demand, thus we should
2575 * make sure that sufficient amount of memory is available in
2576 * advance.
2577 */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01002578 if (hax_enabled()) {
2579 int ret = hax_populate_ram(
2580 (uint64_t)(uintptr_t)new_block->host,
2581 size);
2582 if (ret < 0) {
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002583 fprintf(stderr, "Hax failed to populate ram\n");
2584 exit(-1);
2585 }
2586 }
2587#endif
2588
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002589#endif
2590#ifdef MADV_MERGEABLE
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002591 madvise(new_block->host, size, MADV_MERGEABLE);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002592#endif
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002593 }
2594 }
2595
2596 new_block->offset = find_ram_offset(size);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002597 new_block->length = size;
2598
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002599 QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002600
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002601 ram_list.phys_dirty = g_realloc(ram_list.phys_dirty,
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002602 last_ram_offset() >> TARGET_PAGE_BITS);
2603 memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002604 0xff, size >> TARGET_PAGE_BITS);
2605
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002606 if (kvm_enabled())
2607 kvm_setup_guest_memory(new_block->host, size);
2608
2609 return new_block->offset;
2610}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002611
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002612ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
2613{
2614 return qemu_ram_alloc_from_ptr(dev, name, size, NULL);
2615}
2616
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002617void qemu_ram_free(ram_addr_t addr)
2618{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002619 RAMBlock *block;
2620
2621 QLIST_FOREACH(block, &ram_list.blocks, next) {
2622 if (addr == block->offset) {
2623 QLIST_REMOVE(block, next);
2624 if (block->flags & RAM_PREALLOC_MASK) {
2625 ;
2626 } else if (mem_path) {
2627#if defined (__linux__) && !defined(TARGET_S390X)
2628 if (block->fd) {
2629 munmap(block->host, block->length);
2630 close(block->fd);
2631 } else {
2632 qemu_vfree(block->host);
2633 }
2634#else
2635 abort();
2636#endif
2637 } else {
2638#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2639 munmap(block->host, block->length);
2640#else
2641 qemu_vfree(block->host);
2642#endif
2643 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002644 g_free(block);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002645 return;
2646 }
2647 }
2648
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002649}
2650
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002651#ifndef _WIN32
2652void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
2653{
2654#ifndef CONFIG_ANDROID
2655 RAMBlock *block;
2656 ram_addr_t offset;
2657 int flags;
2658 void *area, *vaddr;
2659
2660 QLIST_FOREACH(block, &ram_list.blocks, next) {
2661 offset = addr - block->offset;
2662 if (offset < block->length) {
2663 vaddr = block->host + offset;
2664 if (block->flags & RAM_PREALLOC_MASK) {
2665 ;
2666 } else {
2667 flags = MAP_FIXED;
2668 munmap(vaddr, length);
2669 if (mem_path) {
2670#if defined(__linux__) && !defined(TARGET_S390X)
2671 if (block->fd) {
2672#ifdef MAP_POPULATE
2673 flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED :
2674 MAP_PRIVATE;
2675#else
2676 flags |= MAP_PRIVATE;
2677#endif
2678 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2679 flags, block->fd, offset);
2680 } else {
2681 flags |= MAP_PRIVATE | MAP_ANONYMOUS;
2682 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2683 flags, -1, 0);
2684 }
2685#else
2686 abort();
2687#endif
2688 } else {
2689#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2690 flags |= MAP_SHARED | MAP_ANONYMOUS;
2691 area = mmap(vaddr, length, PROT_EXEC|PROT_READ|PROT_WRITE,
2692 flags, -1, 0);
2693#else
2694 flags |= MAP_PRIVATE | MAP_ANONYMOUS;
2695 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2696 flags, -1, 0);
2697#endif
2698 }
2699 if (area != vaddr) {
2700 fprintf(stderr, "Could not remap addr: %lx@%lx\n",
2701 length, addr);
2702 exit(1);
2703 }
2704 qemu_madvise(vaddr, length, QEMU_MADV_MERGEABLE);
2705 }
2706 return;
2707 }
2708 }
2709#endif /* !CONFIG_ANDROID */
2710}
2711#endif /* !_WIN32 */
2712
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002713/* Return a host pointer to ram allocated with qemu_ram_alloc.
2714 With the exception of the softmmu code in this file, this should
2715 only be used for local memory (e.g. video ram) that the device owns,
2716 and knows it isn't going to access beyond the end of the block.
2717
2718 It should not be used for general purpose DMA.
2719 Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
2720 */
2721void *qemu_get_ram_ptr(ram_addr_t addr)
2722{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002723 RAMBlock *block;
2724
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002725 QLIST_FOREACH(block, &ram_list.blocks, next) {
2726 if (addr - block->offset < block->length) {
2727 /* Move this entry to to start of the list. */
2728 if (block != QLIST_FIRST(&ram_list.blocks)) {
2729 QLIST_REMOVE(block, next);
2730 QLIST_INSERT_HEAD(&ram_list.blocks, block, next);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002731 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002732 return block->host + (addr - block->offset);
2733 }
2734 }
2735
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002736 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2737 abort();
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002738
2739 return NULL;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002740 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002741
2742/* Return a host pointer to ram allocated with qemu_ram_alloc.
2743 * Same as qemu_get_ram_ptr but avoid reordering ramblocks.
2744 */
2745void *qemu_safe_ram_ptr(ram_addr_t addr)
2746{
2747 RAMBlock *block;
2748
2749 QLIST_FOREACH(block, &ram_list.blocks, next) {
2750 if (addr - block->offset < block->length) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002751 return block->host + (addr - block->offset);
2752}
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002753 }
2754
2755 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2756 abort();
2757
2758 return NULL;
2759}
2760
2761int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
2762{
2763 RAMBlock *block;
2764 uint8_t *host = ptr;
2765
2766 QLIST_FOREACH(block, &ram_list.blocks, next) {
2767 if (host - block->host < block->length) {
2768 *ram_addr = block->offset + (host - block->host);
2769 return 0;
2770 }
2771 }
2772 return -1;
2773}
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002774
2775/* Some of the softmmu routines need to translate from a host pointer
2776 (typically a TLB entry) back to a ram offset. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002777ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002778{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002779 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002780
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002781 if (qemu_ram_addr_from_host(ptr, &ram_addr)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002782 fprintf(stderr, "Bad ram pointer %p\n", ptr);
2783 abort();
2784 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002785 return ram_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002786}
2787
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002788static uint32_t unassigned_mem_readb(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002789{
2790#ifdef DEBUG_UNASSIGNED
2791 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2792#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002793#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002794 do_unassigned_access(addr, 0, 0, 0, 1);
2795#endif
2796 return 0;
2797}
2798
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002799static uint32_t unassigned_mem_readw(void *opaque, hwaddr addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002800{
2801#ifdef DEBUG_UNASSIGNED
2802 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2803#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002804#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002805 do_unassigned_access(addr, 0, 0, 0, 2);
2806#endif
2807 return 0;
2808}
2809
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002810static uint32_t unassigned_mem_readl(void *opaque, hwaddr addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002811{
2812#ifdef DEBUG_UNASSIGNED
2813 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2814#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002815#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002816 do_unassigned_access(addr, 0, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002817#endif
2818 return 0;
2819}
2820
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002821static void unassigned_mem_writeb(void *opaque, hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002822{
2823#ifdef DEBUG_UNASSIGNED
2824 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2825#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002826#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002827 do_unassigned_access(addr, 1, 0, 0, 1);
2828#endif
2829}
2830
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002831static void unassigned_mem_writew(void *opaque, hwaddr addr, uint32_t val)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002832{
2833#ifdef DEBUG_UNASSIGNED
2834 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2835#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002836#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002837 do_unassigned_access(addr, 1, 0, 0, 2);
2838#endif
2839}
2840
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002841static void unassigned_mem_writel(void *opaque, hwaddr addr, uint32_t val)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002842{
2843#ifdef DEBUG_UNASSIGNED
2844 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2845#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002846#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002847 do_unassigned_access(addr, 1, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002848#endif
2849}
2850
David 'Digit' Turner36411062010-12-22 17:34:53 +01002851static CPUReadMemoryFunc * const unassigned_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002852 unassigned_mem_readb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002853 unassigned_mem_readw,
2854 unassigned_mem_readl,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002855};
2856
David 'Digit' Turner36411062010-12-22 17:34:53 +01002857static CPUWriteMemoryFunc * const unassigned_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002858 unassigned_mem_writeb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002859 unassigned_mem_writew,
2860 unassigned_mem_writel,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002861};
2862
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002863static void notdirty_mem_writeb(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002864 uint32_t val)
2865{
2866 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002867 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002868 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2869#if !defined(CONFIG_USER_ONLY)
2870 tb_invalidate_phys_page_fast(ram_addr, 1);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002871 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002872#endif
2873 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002874 stb_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002875 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002876 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002877 /* we remove the notdirty callback only if the code has been
2878 flushed */
2879 if (dirty_flags == 0xff)
2880 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2881}
2882
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002883static void notdirty_mem_writew(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002884 uint32_t val)
2885{
2886 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002887 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002888 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2889#if !defined(CONFIG_USER_ONLY)
2890 tb_invalidate_phys_page_fast(ram_addr, 2);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002891 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002892#endif
2893 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002894 stw_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002895 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002896 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002897 /* we remove the notdirty callback only if the code has been
2898 flushed */
2899 if (dirty_flags == 0xff)
2900 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2901}
2902
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002903static void notdirty_mem_writel(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002904 uint32_t val)
2905{
2906 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002907 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002908 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2909#if !defined(CONFIG_USER_ONLY)
2910 tb_invalidate_phys_page_fast(ram_addr, 4);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002911 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002912#endif
2913 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002914 stl_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002915 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002916 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002917 /* we remove the notdirty callback only if the code has been
2918 flushed */
2919 if (dirty_flags == 0xff)
2920 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2921}
2922
David 'Digit' Turner36411062010-12-22 17:34:53 +01002923static CPUReadMemoryFunc * const error_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002924 NULL, /* never used */
2925 NULL, /* never used */
2926 NULL, /* never used */
2927};
2928
David 'Digit' Turner36411062010-12-22 17:34:53 +01002929static CPUWriteMemoryFunc * const notdirty_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002930 notdirty_mem_writeb,
2931 notdirty_mem_writew,
2932 notdirty_mem_writel,
2933};
2934
2935/* Generate a debug exception if a watchpoint has been hit. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002936static void check_watchpoint(int offset, int len_mask, int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002937{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002938 CPUOldState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002939 target_ulong pc, cs_base;
2940 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002941 target_ulong vaddr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002942 CPUWatchpoint *wp;
2943 int cpu_flags;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002944
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002945 if (env->watchpoint_hit) {
2946 /* We re-entered the check after replacing the TB. Now raise
2947 * the debug interrupt so that is will trigger after the
2948 * current instruction. */
2949 cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2950 return;
2951 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002952 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002953 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002954 if ((vaddr == (wp->vaddr & len_mask) ||
2955 (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
2956 wp->flags |= BP_WATCHPOINT_HIT;
2957 if (!env->watchpoint_hit) {
2958 env->watchpoint_hit = wp;
2959 tb = tb_find_pc(env->mem_io_pc);
2960 if (!tb) {
2961 cpu_abort(env, "check_watchpoint: could not find TB for "
2962 "pc=%p", (void *)env->mem_io_pc);
2963 }
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02002964 cpu_restore_state(tb, env, env->mem_io_pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002965 tb_phys_invalidate(tb, -1);
2966 if (wp->flags & BP_STOP_BEFORE_ACCESS) {
2967 env->exception_index = EXCP_DEBUG;
2968 } else {
2969 cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
2970 tb_gen_code(env, pc, cs_base, cpu_flags, 1);
2971 }
2972 cpu_resume_from_signal(env, NULL);
2973 }
2974 } else {
2975 wp->flags &= ~BP_WATCHPOINT_HIT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002976 }
2977 }
2978}
2979
2980/* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
2981 so these check for a hit then pass through to the normal out-of-line
2982 phys routines. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002983static uint32_t watch_mem_readb(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002984{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002985 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002986 return ldub_phys(addr);
2987}
2988
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002989static uint32_t watch_mem_readw(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002990{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002991 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002992 return lduw_phys(addr);
2993}
2994
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002995static uint32_t watch_mem_readl(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002996{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002997 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002998 return ldl_phys(addr);
2999}
3000
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003001static void watch_mem_writeb(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003002 uint32_t val)
3003{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003004 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003005 stb_phys(addr, val);
3006}
3007
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003008static void watch_mem_writew(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003009 uint32_t val)
3010{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003011 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003012 stw_phys(addr, val);
3013}
3014
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003015static void watch_mem_writel(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003016 uint32_t val)
3017{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003018 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003019 stl_phys(addr, val);
3020}
3021
David 'Digit' Turner36411062010-12-22 17:34:53 +01003022static CPUReadMemoryFunc * const watch_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003023 watch_mem_readb,
3024 watch_mem_readw,
3025 watch_mem_readl,
3026};
3027
David 'Digit' Turner36411062010-12-22 17:34:53 +01003028static CPUWriteMemoryFunc * const watch_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003029 watch_mem_writeb,
3030 watch_mem_writew,
3031 watch_mem_writel,
3032};
3033
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003034static inline uint32_t subpage_readlen (subpage_t *mmio, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003035 unsigned int len)
3036{
3037 uint32_t ret;
3038 unsigned int idx;
3039
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003040 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003041#if defined(DEBUG_SUBPAGE)
3042 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
3043 mmio, len, addr, idx);
3044#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003045 ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len],
3046 addr + mmio->region_offset[idx][0][len]);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003047
3048 return ret;
3049}
3050
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003051static inline void subpage_writelen (subpage_t *mmio, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003052 uint32_t value, unsigned int len)
3053{
3054 unsigned int idx;
3055
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003056 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003057#if defined(DEBUG_SUBPAGE)
3058 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
3059 mmio, len, addr, idx, value);
3060#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003061 (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len],
3062 addr + mmio->region_offset[idx][1][len],
3063 value);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003064}
3065
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003066static uint32_t subpage_readb (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003067{
3068#if defined(DEBUG_SUBPAGE)
3069 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
3070#endif
3071
3072 return subpage_readlen(opaque, addr, 0);
3073}
3074
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003075static void subpage_writeb (void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003076 uint32_t value)
3077{
3078#if defined(DEBUG_SUBPAGE)
3079 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
3080#endif
3081 subpage_writelen(opaque, addr, value, 0);
3082}
3083
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003084static uint32_t subpage_readw (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003085{
3086#if defined(DEBUG_SUBPAGE)
3087 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
3088#endif
3089
3090 return subpage_readlen(opaque, addr, 1);
3091}
3092
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003093static void subpage_writew (void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003094 uint32_t value)
3095{
3096#if defined(DEBUG_SUBPAGE)
3097 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
3098#endif
3099 subpage_writelen(opaque, addr, value, 1);
3100}
3101
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003102static uint32_t subpage_readl (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003103{
3104#if defined(DEBUG_SUBPAGE)
3105 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
3106#endif
3107
3108 return subpage_readlen(opaque, addr, 2);
3109}
3110
3111static void subpage_writel (void *opaque,
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003112 hwaddr addr, uint32_t value)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003113{
3114#if defined(DEBUG_SUBPAGE)
3115 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
3116#endif
3117 subpage_writelen(opaque, addr, value, 2);
3118}
3119
David 'Digit' Turner36411062010-12-22 17:34:53 +01003120static CPUReadMemoryFunc * const subpage_read[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003121 &subpage_readb,
3122 &subpage_readw,
3123 &subpage_readl,
3124};
3125
David 'Digit' Turner36411062010-12-22 17:34:53 +01003126static CPUWriteMemoryFunc * const subpage_write[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003127 &subpage_writeb,
3128 &subpage_writew,
3129 &subpage_writel,
3130};
3131
3132static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003133 ram_addr_t memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003134{
3135 int idx, eidx;
3136 unsigned int i;
3137
3138 if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
3139 return -1;
3140 idx = SUBPAGE_IDX(start);
3141 eidx = SUBPAGE_IDX(end);
3142#if defined(DEBUG_SUBPAGE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003143 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 -08003144 mmio, start, end, idx, eidx, memory);
3145#endif
3146 memory >>= IO_MEM_SHIFT;
3147 for (; idx <= eidx; idx++) {
3148 for (i = 0; i < 4; i++) {
3149 if (io_mem_read[memory][i]) {
3150 mmio->mem_read[idx][i] = &io_mem_read[memory][i];
3151 mmio->opaque[idx][0][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003152 mmio->region_offset[idx][0][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003153 }
3154 if (io_mem_write[memory][i]) {
3155 mmio->mem_write[idx][i] = &io_mem_write[memory][i];
3156 mmio->opaque[idx][1][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003157 mmio->region_offset[idx][1][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003158 }
3159 }
3160 }
3161
3162 return 0;
3163}
3164
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003165static void *subpage_init (hwaddr base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003166 ram_addr_t orig_memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003167{
3168 subpage_t *mmio;
3169 int subpage_memory;
3170
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01003171 mmio = g_malloc0(sizeof(subpage_t));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003172
3173 mmio->base = base;
3174 subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003175#if defined(DEBUG_SUBPAGE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003176 printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
3177 mmio, base, TARGET_PAGE_SIZE, subpage_memory);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003178#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003179 *phys = subpage_memory | IO_MEM_SUBPAGE;
3180 subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
3181 region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003182
3183 return mmio;
3184}
3185
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003186static int get_free_io_mem_idx(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003187{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003188 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003189
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003190 for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
3191 if (!io_mem_used[i]) {
3192 io_mem_used[i] = 1;
3193 return i;
3194 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003195 fprintf(stderr, "RAN out out io_mem_idx, max %d !\n", IO_MEM_NB_ENTRIES);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003196 return -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003197}
3198
3199/* mem_read and mem_write are arrays of functions containing the
3200 function to access byte (index 0), word (index 1) and dword (index
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003201 2). Functions can be omitted with a NULL function pointer.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003202 If io_index is non zero, the corresponding io zone is
3203 modified. If it is zero, a new io zone is allocated. The return
3204 value can be used with cpu_register_physical_memory(). (-1) is
3205 returned if error. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003206static int cpu_register_io_memory_fixed(int io_index,
David 'Digit' Turner36411062010-12-22 17:34:53 +01003207 CPUReadMemoryFunc * const *mem_read,
3208 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003209 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003210{
3211 int i, subwidth = 0;
3212
3213 if (io_index <= 0) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003214 io_index = get_free_io_mem_idx();
3215 if (io_index == -1)
3216 return io_index;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003217 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003218 io_index >>= IO_MEM_SHIFT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003219 if (io_index >= IO_MEM_NB_ENTRIES)
3220 return -1;
3221 }
3222
3223 for(i = 0;i < 3; i++) {
3224 if (!mem_read[i] || !mem_write[i])
3225 subwidth = IO_MEM_SUBWIDTH;
3226 io_mem_read[io_index][i] = mem_read[i];
3227 io_mem_write[io_index][i] = mem_write[i];
3228 }
3229 io_mem_opaque[io_index] = opaque;
3230 return (io_index << IO_MEM_SHIFT) | subwidth;
3231}
3232
David 'Digit' Turner36411062010-12-22 17:34:53 +01003233int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
3234 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003235 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003236{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003237 return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003238}
3239
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003240void cpu_unregister_io_memory(int io_table_address)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003241{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003242 int i;
3243 int io_index = io_table_address >> IO_MEM_SHIFT;
3244
3245 for (i=0;i < 3; i++) {
3246 io_mem_read[io_index][i] = unassigned_mem_read[i];
3247 io_mem_write[io_index][i] = unassigned_mem_write[i];
3248 }
3249 io_mem_opaque[io_index] = NULL;
3250 io_mem_used[io_index] = 0;
3251}
3252
3253static void io_mem_init(void)
3254{
3255 int i;
3256
3257 cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read, unassigned_mem_write, NULL);
3258 cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read, unassigned_mem_write, NULL);
3259 cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read, notdirty_mem_write, NULL);
3260 for (i=0; i<5; i++)
3261 io_mem_used[i] = 1;
3262
3263 io_mem_watch = cpu_register_io_memory(watch_mem_read,
3264 watch_mem_write, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003265}
3266
3267#endif /* !defined(CONFIG_USER_ONLY) */
3268
3269/* physical memory access (slow version, mainly for debug) */
3270#if defined(CONFIG_USER_ONLY)
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003271void cpu_physical_memory_rw(hwaddr addr, void *buf,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003272 int len, int is_write)
3273{
3274 int l, flags;
3275 target_ulong page;
3276 void * p;
3277
3278 while (len > 0) {
3279 page = addr & TARGET_PAGE_MASK;
3280 l = (page + TARGET_PAGE_SIZE) - addr;
3281 if (l > len)
3282 l = len;
3283 flags = page_get_flags(page);
3284 if (!(flags & PAGE_VALID))
3285 return;
3286 if (is_write) {
3287 if (!(flags & PAGE_WRITE))
3288 return;
3289 /* XXX: this code should not depend on lock_user */
3290 if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
3291 /* FIXME - should this return an error rather than just fail? */
3292 return;
3293 memcpy(p, buf, l);
3294 unlock_user(p, addr, l);
3295 } else {
3296 if (!(flags & PAGE_READ))
3297 return;
3298 /* XXX: this code should not depend on lock_user */
3299 if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
3300 /* FIXME - should this return an error rather than just fail? */
3301 return;
3302 memcpy(buf, p, l);
3303 unlock_user(p, addr, 0);
3304 }
3305 len -= l;
3306 buf += l;
3307 addr += l;
3308 }
3309}
3310
3311#else
Pete Delaneyd09d7662013-03-28 19:53:13 -07003312
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003313static void invalidate_and_set_dirty(hwaddr addr,
3314 hwaddr length)
Pete Delaneyd09d7662013-03-28 19:53:13 -07003315{
3316 if (!cpu_physical_memory_is_dirty(addr)) {
3317 /* invalidate code */
3318 tb_invalidate_phys_page_range(addr, addr + length, 0);
3319 /* set dirty bit */
3320 cpu_physical_memory_set_dirty_flags(addr, (0xff & ~CODE_DIRTY_FLAG));
3321 }
3322}
3323
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003324void cpu_physical_memory_rw(hwaddr addr, void *buf,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003325 int len, int is_write)
3326{
3327 int l, io_index;
3328 uint8_t *ptr;
3329 uint32_t val;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003330 hwaddr page;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003331 unsigned long pd;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003332 uint8_t* buf8 = (uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003333 PhysPageDesc *p;
3334
3335 while (len > 0) {
3336 page = addr & TARGET_PAGE_MASK;
3337 l = (page + TARGET_PAGE_SIZE) - addr;
3338 if (l > len)
3339 l = len;
3340 p = phys_page_find(page >> TARGET_PAGE_BITS);
3341 if (!p) {
3342 pd = IO_MEM_UNASSIGNED;
3343 } else {
3344 pd = p->phys_offset;
3345 }
3346
3347 if (is_write) {
3348 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003349 hwaddr addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003350 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003351 if (p)
3352 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003353 /* XXX: could force cpu_single_env to NULL to avoid
3354 potential bugs */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003355 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003356 /* 32 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003357 val = ldl_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003358 io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003359 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003360 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003361 /* 16 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003362 val = lduw_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003363 io_mem_write[io_index][1](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003364 l = 2;
3365 } else {
3366 /* 8 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003367 val = ldub_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003368 io_mem_write[io_index][0](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003369 l = 1;
3370 }
3371 } else {
3372 unsigned long addr1;
3373 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3374 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003375 ptr = qemu_get_ram_ptr(addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003376 memcpy(ptr, buf8, l);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003377 invalidate_and_set_dirty(addr1, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003378 }
3379 } else {
3380 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3381 !(pd & IO_MEM_ROMD)) {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003382 hwaddr addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003383 /* I/O case */
3384 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003385 if (p)
3386 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3387 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003388 /* 32 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003389 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003390 stl_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003391 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003392 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003393 /* 16 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003394 val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003395 stw_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003396 l = 2;
3397 } else {
3398 /* 8 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003399 val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003400 stb_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003401 l = 1;
3402 }
3403 } else {
3404 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003405 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003406 (addr & ~TARGET_PAGE_MASK);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003407 memcpy(buf8, ptr, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003408 }
3409 }
3410 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003411 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003412 addr += l;
3413 }
3414}
3415
3416/* used for ROM loading : can write in RAM and ROM */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003417void cpu_physical_memory_write_rom(hwaddr addr,
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003418 const void *buf, int len)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003419{
3420 int l;
3421 uint8_t *ptr;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003422 hwaddr page;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003423 unsigned long pd;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003424 const uint8_t* buf8 = (const uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003425 PhysPageDesc *p;
3426
3427 while (len > 0) {
3428 page = addr & TARGET_PAGE_MASK;
3429 l = (page + TARGET_PAGE_SIZE) - addr;
3430 if (l > len)
3431 l = len;
3432 p = phys_page_find(page >> TARGET_PAGE_BITS);
3433 if (!p) {
3434 pd = IO_MEM_UNASSIGNED;
3435 } else {
3436 pd = p->phys_offset;
3437 }
3438
3439 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
3440 (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
3441 !(pd & IO_MEM_ROMD)) {
3442 /* do nothing */
3443 } else {
3444 unsigned long addr1;
3445 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3446 /* ROM/RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003447 ptr = qemu_get_ram_ptr(addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003448 memcpy(ptr, buf8, l);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003449 invalidate_and_set_dirty(addr1, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003450 }
3451 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003452 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003453 addr += l;
3454 }
3455}
3456
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003457typedef struct {
3458 void *buffer;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003459 hwaddr addr;
3460 hwaddr len;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003461} BounceBuffer;
3462
3463static BounceBuffer bounce;
3464
3465typedef struct MapClient {
3466 void *opaque;
3467 void (*callback)(void *opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003468 QLIST_ENTRY(MapClient) link;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003469} MapClient;
3470
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003471static QLIST_HEAD(map_client_list, MapClient) map_client_list
3472 = QLIST_HEAD_INITIALIZER(map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003473
3474void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
3475{
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01003476 MapClient *client = g_malloc(sizeof(*client));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003477
3478 client->opaque = opaque;
3479 client->callback = callback;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003480 QLIST_INSERT_HEAD(&map_client_list, client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003481 return client;
3482}
3483
3484void cpu_unregister_map_client(void *_client)
3485{
3486 MapClient *client = (MapClient *)_client;
3487
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003488 QLIST_REMOVE(client, link);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01003489 g_free(client);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003490}
3491
3492static void cpu_notify_map_clients(void)
3493{
3494 MapClient *client;
3495
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003496 while (!QLIST_EMPTY(&map_client_list)) {
3497 client = QLIST_FIRST(&map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003498 client->callback(client->opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003499 QLIST_REMOVE(client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003500 }
3501}
3502
3503/* Map a physical memory region into a host virtual address.
3504 * May map a subset of the requested range, given by and returned in *plen.
3505 * May return NULL if resources needed to perform the mapping are exhausted.
3506 * Use only for reads OR writes - not for read-modify-write operations.
3507 * Use cpu_register_map_client() to know when retrying the map operation is
3508 * likely to succeed.
3509 */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003510void *cpu_physical_memory_map(hwaddr addr,
3511 hwaddr *plen,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003512 int is_write)
3513{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003514 hwaddr len = *plen;
3515 hwaddr done = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003516 int l;
3517 uint8_t *ret = NULL;
3518 uint8_t *ptr;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003519 hwaddr page;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003520 unsigned long pd;
3521 PhysPageDesc *p;
3522 unsigned long addr1;
3523
3524 while (len > 0) {
3525 page = addr & TARGET_PAGE_MASK;
3526 l = (page + TARGET_PAGE_SIZE) - addr;
3527 if (l > len)
3528 l = len;
3529 p = phys_page_find(page >> TARGET_PAGE_BITS);
3530 if (!p) {
3531 pd = IO_MEM_UNASSIGNED;
3532 } else {
3533 pd = p->phys_offset;
3534 }
3535
3536 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3537 if (done || bounce.buffer) {
3538 break;
3539 }
3540 bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
3541 bounce.addr = addr;
3542 bounce.len = l;
3543 if (!is_write) {
3544 cpu_physical_memory_rw(addr, bounce.buffer, l, 0);
3545 }
3546 ptr = bounce.buffer;
3547 } else {
3548 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3549 ptr = qemu_get_ram_ptr(addr1);
3550 }
3551 if (!done) {
3552 ret = ptr;
3553 } else if (ret + done != ptr) {
3554 break;
3555 }
3556
3557 len -= l;
3558 addr += l;
3559 done += l;
3560 }
3561 *plen = done;
3562 return ret;
3563}
3564
3565/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
3566 * Will also mark the memory as dirty if is_write == 1. access_len gives
3567 * the amount of memory that was actually read or written by the caller.
3568 */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003569void cpu_physical_memory_unmap(void *buffer, hwaddr len,
3570 int is_write, hwaddr access_len)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003571{
3572 if (buffer != bounce.buffer) {
3573 if (is_write) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003574 ram_addr_t addr1 = qemu_ram_addr_from_host_nofail(buffer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003575 while (access_len) {
3576 unsigned l;
3577 l = TARGET_PAGE_SIZE;
3578 if (l > access_len)
3579 l = access_len;
Pete Delaneyd09d7662013-03-28 19:53:13 -07003580 invalidate_and_set_dirty(addr1, l);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003581 addr1 += l;
3582 access_len -= l;
3583 }
3584 }
3585 return;
3586 }
3587 if (is_write) {
3588 cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
3589 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003590 qemu_vfree(bounce.buffer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003591 bounce.buffer = NULL;
3592 cpu_notify_map_clients();
3593}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003594
3595/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003596uint32_t ldl_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003597{
3598 int io_index;
3599 uint8_t *ptr;
3600 uint32_t val;
3601 unsigned long pd;
3602 PhysPageDesc *p;
3603
3604 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3605 if (!p) {
3606 pd = IO_MEM_UNASSIGNED;
3607 } else {
3608 pd = p->phys_offset;
3609 }
3610
3611 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3612 !(pd & IO_MEM_ROMD)) {
3613 /* I/O case */
3614 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003615 if (p)
3616 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003617 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3618 } else {
3619 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003620 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003621 (addr & ~TARGET_PAGE_MASK);
3622 val = ldl_p(ptr);
3623 }
3624 return val;
3625}
3626
3627/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003628uint64_t ldq_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003629{
3630 int io_index;
3631 uint8_t *ptr;
3632 uint64_t val;
3633 unsigned long pd;
3634 PhysPageDesc *p;
3635
3636 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3637 if (!p) {
3638 pd = IO_MEM_UNASSIGNED;
3639 } else {
3640 pd = p->phys_offset;
3641 }
3642
3643 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3644 !(pd & IO_MEM_ROMD)) {
3645 /* I/O case */
3646 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003647 if (p)
3648 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003649#ifdef TARGET_WORDS_BIGENDIAN
3650 val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
3651 val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
3652#else
3653 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3654 val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
3655#endif
3656 } else {
3657 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003658 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003659 (addr & ~TARGET_PAGE_MASK);
3660 val = ldq_p(ptr);
3661 }
3662 return val;
3663}
3664
3665/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003666uint32_t ldub_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003667{
3668 uint8_t val;
3669 cpu_physical_memory_read(addr, &val, 1);
3670 return val;
3671}
3672
3673/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003674uint32_t lduw_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003675{
3676 uint16_t val;
3677 cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
3678 return tswap16(val);
3679}
3680
3681/* warning: addr must be aligned. The ram page is not masked as dirty
3682 and the code inside is not invalidated. It is useful if the dirty
3683 bits are used to track modified PTEs */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003684void stl_phys_notdirty(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003685{
3686 int io_index;
3687 uint8_t *ptr;
3688 unsigned long pd;
3689 PhysPageDesc *p;
3690
3691 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3692 if (!p) {
3693 pd = IO_MEM_UNASSIGNED;
3694 } else {
3695 pd = p->phys_offset;
3696 }
3697
3698 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3699 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003700 if (p)
3701 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003702 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3703 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003704 unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3705 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003706 stl_p(ptr, val);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003707
3708 if (unlikely(in_migration)) {
3709 if (!cpu_physical_memory_is_dirty(addr1)) {
3710 /* invalidate code */
3711 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3712 /* set dirty bit */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003713 cpu_physical_memory_set_dirty_flags(
3714 addr1, (0xff & ~CODE_DIRTY_FLAG));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003715 }
3716 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003717 }
3718}
3719
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003720void stq_phys_notdirty(hwaddr addr, uint64_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003721{
3722 int io_index;
3723 uint8_t *ptr;
3724 unsigned long pd;
3725 PhysPageDesc *p;
3726
3727 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3728 if (!p) {
3729 pd = IO_MEM_UNASSIGNED;
3730 } else {
3731 pd = p->phys_offset;
3732 }
3733
3734 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3735 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003736 if (p)
3737 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003738#ifdef TARGET_WORDS_BIGENDIAN
3739 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
3740 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
3741#else
3742 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3743 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
3744#endif
3745 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003746 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003747 (addr & ~TARGET_PAGE_MASK);
3748 stq_p(ptr, val);
3749 }
3750}
3751
3752/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003753void stl_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003754{
3755 int io_index;
3756 uint8_t *ptr;
3757 unsigned long pd;
3758 PhysPageDesc *p;
3759
3760 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3761 if (!p) {
3762 pd = IO_MEM_UNASSIGNED;
3763 } else {
3764 pd = p->phys_offset;
3765 }
3766
3767 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3768 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003769 if (p)
3770 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003771 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3772 } else {
3773 unsigned long addr1;
3774 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3775 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003776 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003777 stl_p(ptr, val);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003778 invalidate_and_set_dirty(addr1, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003779 }
3780}
3781
3782/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003783void stb_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003784{
3785 uint8_t v = val;
3786 cpu_physical_memory_write(addr, &v, 1);
3787}
3788
3789/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003790void stw_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003791{
3792 uint16_t v = tswap16(val);
3793 cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
3794}
3795
3796/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003797void stq_phys(hwaddr addr, uint64_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003798{
3799 val = tswap64(val);
3800 cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
3801}
3802
3803#endif
3804
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003805/* virtual memory access for debug (includes writing to ROM) */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003806int cpu_memory_rw_debug(CPUOldState *env, target_ulong addr,
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003807 void *buf, int len, int is_write)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003808{
3809 int l;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003810 hwaddr phys_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003811 target_ulong page;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003812 uint8_t* buf8 = (uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003813
3814 while (len > 0) {
3815 page = addr & TARGET_PAGE_MASK;
3816 phys_addr = cpu_get_phys_page_debug(env, page);
3817 /* if no physical page mapped, return an error */
3818 if (phys_addr == -1)
3819 return -1;
3820 l = (page + TARGET_PAGE_SIZE) - addr;
3821 if (l > len)
3822 l = len;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003823 phys_addr += (addr & ~TARGET_PAGE_MASK);
3824#if !defined(CONFIG_USER_ONLY)
3825 if (is_write)
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003826 cpu_physical_memory_write_rom(phys_addr, buf8, l);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003827 else
3828#endif
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003829 cpu_physical_memory_rw(phys_addr, buf8, l, is_write);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003830 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003831 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003832 addr += l;
3833 }
3834 return 0;
3835}
3836
3837/* in deterministic execution mode, instructions doing device I/Os
3838 must be at the end of the TB */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003839void cpu_io_recompile(CPUOldState *env, void *retaddr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003840{
3841 TranslationBlock *tb;
3842 uint32_t n, cflags;
3843 target_ulong pc, cs_base;
3844 uint64_t flags;
3845
3846 tb = tb_find_pc((unsigned long)retaddr);
3847 if (!tb) {
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02003848 cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003849 retaddr);
3850 }
3851 n = env->icount_decr.u16.low + tb->icount;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02003852 cpu_restore_state(tb, env, (unsigned long)retaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003853 /* Calculate how many instructions had been executed before the fault
3854 occurred. */
3855 n = n - env->icount_decr.u16.low;
3856 /* Generate a new TB ending on the I/O insn. */
3857 n++;
3858 /* On MIPS and SH, delay slot instructions can only be restarted if
3859 they were already the first instruction in the TB. If this is not
3860 the first instruction in a TB then re-execute the preceding
3861 branch. */
3862#if defined(TARGET_MIPS)
3863 if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) {
3864 env->active_tc.PC -= 4;
3865 env->icount_decr.u16.low++;
3866 env->hflags &= ~MIPS_HFLAG_BMASK;
3867 }
3868#elif defined(TARGET_SH4)
3869 if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
3870 && n > 1) {
3871 env->pc -= 2;
3872 env->icount_decr.u16.low++;
3873 env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
3874 }
3875#endif
3876 /* This should never happen. */
3877 if (n > CF_COUNT_MASK)
3878 cpu_abort(env, "TB too big during recompile");
3879
3880 cflags = n | CF_LAST_IO;
3881 pc = tb->pc;
3882 cs_base = tb->cs_base;
3883 flags = tb->flags;
3884 tb_phys_invalidate(tb, -1);
3885 /* FIXME: In theory this could raise an exception. In practice
3886 we have already translated the block once so it's probably ok. */
3887 tb_gen_code(env, pc, cs_base, flags, cflags);
3888 /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
3889 the first in the TB) then we end up generating a whole new TB and
3890 repeating the fault, which is horribly inefficient.
3891 Better would be to execute just this insn uncached, or generate a
3892 second new TB. */
3893 cpu_resume_from_signal(env, NULL);
3894}
3895
David 'Digit' Turner36411062010-12-22 17:34:53 +01003896#if !defined(CONFIG_USER_ONLY)
3897
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003898void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003899{
3900 int i, target_code_size, max_target_code_size;
3901 int direct_jmp_count, direct_jmp2_count, cross_page;
3902 TranslationBlock *tb;
3903
3904 target_code_size = 0;
3905 max_target_code_size = 0;
3906 cross_page = 0;
3907 direct_jmp_count = 0;
3908 direct_jmp2_count = 0;
3909 for(i = 0; i < nb_tbs; i++) {
3910 tb = &tbs[i];
3911 target_code_size += tb->size;
3912 if (tb->size > max_target_code_size)
3913 max_target_code_size = tb->size;
3914 if (tb->page_addr[1] != -1)
3915 cross_page++;
3916 if (tb->tb_next_offset[0] != 0xffff) {
3917 direct_jmp_count++;
3918 if (tb->tb_next_offset[1] != 0xffff) {
3919 direct_jmp2_count++;
3920 }
3921 }
3922 }
3923 /* XXX: avoid using doubles ? */
3924 cpu_fprintf(f, "Translation buffer state:\n");
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003925 cpu_fprintf(f, "gen code size %td/%ld\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003926 code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02003927 cpu_fprintf(f, "TB count %d/%d\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003928 nb_tbs, code_gen_max_blocks);
3929 cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
3930 nb_tbs ? target_code_size / nb_tbs : 0,
3931 max_target_code_size);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003932 cpu_fprintf(f, "TB avg host size %td bytes (expansion ratio: %0.1f)\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003933 nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
3934 target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
3935 cpu_fprintf(f, "cross page TB count %d (%d%%)\n",
3936 cross_page,
3937 nb_tbs ? (cross_page * 100) / nb_tbs : 0);
3938 cpu_fprintf(f, "direct jump count %d (%d%%) (2 jumps=%d %d%%)\n",
3939 direct_jmp_count,
3940 nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
3941 direct_jmp2_count,
3942 nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
3943 cpu_fprintf(f, "\nStatistics:\n");
3944 cpu_fprintf(f, "TB flush count %d\n", tb_flush_count);
3945 cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
3946 cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count);
3947 tcg_dump_info(f, cpu_fprintf);
3948}
3949
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003950#define MMUSUFFIX _cmmu
3951#define GETPC() NULL
3952#define env cpu_single_env
3953#define SOFTMMU_CODE_ACCESS
3954
3955#define SHIFT 0
David 'Digit' Turner852088c2013-12-14 23:04:12 +01003956#include "exec/softmmu_template.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003957
3958#define SHIFT 1
David 'Digit' Turner852088c2013-12-14 23:04:12 +01003959#include "exec/softmmu_template.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003960
3961#define SHIFT 2
David 'Digit' Turner852088c2013-12-14 23:04:12 +01003962#include "exec/softmmu_template.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003963
3964#define SHIFT 3
David 'Digit' Turner852088c2013-12-14 23:04:12 +01003965#include "exec/softmmu_template.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003966
3967#undef env
3968
3969#endif