blob: e77490a44f740484e5825bc37bafc4cde63e8570 [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' Turner0e8e7482014-02-17 20:25:52 +010040#include "hw/xen/xen.h"
David 'Digit' Turner84569132013-12-13 17:34:07 +010041#include "qemu/osdep.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +010042#include "sysemu/kvm.h"
David 'Digit' Turner3dc53fc2014-01-17 01:23:40 +010043#include "exec/cputlb.h"
David 'Digit' Turnere1e03df2013-12-15 00:42:21 +010044#include "exec/hax.h"
David 'Digit' Turner7a78db72013-12-14 11:46:01 +010045#include "qemu/timer.h"
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080046#if defined(CONFIG_USER_ONLY)
47#include <qemu.h>
48#endif
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -080049#ifdef CONFIG_MEMCHECK
50#include "memcheck/memcheck_api.h"
51#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080052
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080053//#define DEBUG_SUBPAGE
54
55#if !defined(CONFIG_USER_ONLY)
56/* TB consistency checks only implemented for usermode emulation. */
57#undef DEBUG_TB_CHECK
58#endif
59
60#define SMC_BITMAP_USE_THRESHOLD 10
61
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080062int code_gen_max_blocks;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080063/* any access to the tbs or the page table must use this lock */
64spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
65
66#if defined(__arm__) || defined(__sparc_v9__)
67/* The prologue must be reachable with a direct jump. ARM and Sparc64
68 have limited branch ranges (possibly also PPC) so place it in a
69 section close to code segment. */
70#define code_gen_section \
71 __attribute__((__section__(".gen_code"))) \
72 __attribute__((aligned (32)))
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070073#elif defined(_WIN32)
74/* Maximum alignment for Win32 is 16. */
75#define code_gen_section \
76 __attribute__((aligned (16)))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080077#else
78#define code_gen_section \
79 __attribute__((aligned (32)))
80#endif
81
82uint8_t code_gen_prologue[1024] code_gen_section;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070083static uint8_t *code_gen_buffer;
84static unsigned long code_gen_buffer_size;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080085/* threshold to flush the translated code buffer */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070086static unsigned long code_gen_buffer_max_size;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080087uint8_t *code_gen_ptr;
88
89#if !defined(CONFIG_USER_ONLY)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080090int phys_ram_fd;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070091static int in_migration;
92
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +010093RAMList ram_list = { .blocks = QTAILQ_HEAD_INITIALIZER(ram_list.blocks) };
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080094#endif
95
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +010096CPUArchState *first_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080097/* current CPU in the current thread. It is only valid inside
98 cpu_exec() */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +010099CPUArchState *cpu_single_env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800100/* 0 = Do not count executed instructions.
101 1 = Precise instruction counting.
102 2 = Adaptive rate instruction counting. */
103int use_icount = 0;
104/* Current instruction counter. While executing translated code this may
105 include some instructions that have not yet been executed. */
106int64_t qemu_icount;
107
108typedef struct PageDesc {
109 /* list of TBs intersecting this ram page */
110 TranslationBlock *first_tb;
111 /* in order to optimize self modifying code, we count the number
112 of lookups we do to a given page to use a bitmap */
113 unsigned int code_write_count;
114 uint8_t *code_bitmap;
115#if defined(CONFIG_USER_ONLY)
116 unsigned long flags;
117#endif
118} PageDesc;
119
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800120#define L2_BITS 10
121#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
122/* XXX: this is a temporary hack for alpha target.
123 * In the future, this is to be replaced by a multi-level table
124 * to actually be able to handle the complete 64 bits address space.
125 */
126#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
127#else
128#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
129#endif
130
131#define L1_SIZE (1 << L1_BITS)
132#define L2_SIZE (1 << L2_BITS)
133
David 'Digit' Turnerf0729c72014-01-13 16:10:10 +0100134uintptr_t qemu_real_host_page_size;
David 'Digit' Turnerf0729c72014-01-13 16:10:10 +0100135uintptr_t qemu_host_page_size;
136uintptr_t qemu_host_page_mask;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800137
138/* XXX: for system emulation, it could just be an array */
139static PageDesc *l1_map[L1_SIZE];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700140static PhysPageDesc **l1_phys_map;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800141
142#if !defined(CONFIG_USER_ONLY)
143static void io_mem_init(void);
144
145/* io memory support */
146CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
147CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
148void *io_mem_opaque[IO_MEM_NB_ENTRIES];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700149static char io_mem_used[IO_MEM_NB_ENTRIES];
David 'Digit' Turner3dc53fc2014-01-17 01:23:40 +0100150int io_mem_watch;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800151#endif
152
153/* log support */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700154#ifdef WIN32
155static const char *logfilename = "qemu.log";
156#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700157static const char *logfilename = "/tmp/qemu.log";
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700158#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800159FILE *logfile;
160int loglevel;
161static int log_append = 0;
162
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800163#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
164typedef struct subpage_t {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100165 hwaddr base;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800166 CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE][4];
167 CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE][4];
168 void *opaque[TARGET_PAGE_SIZE][2][4];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700169 ram_addr_t region_offset[TARGET_PAGE_SIZE][2][4];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800170} subpage_t;
171
172#ifdef _WIN32
173static void map_exec(void *addr, long size)
174{
175 DWORD old_protect;
176 VirtualProtect(addr, size,
177 PAGE_EXECUTE_READWRITE, &old_protect);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200178
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800179}
180#else
181static void map_exec(void *addr, long size)
182{
183 unsigned long start, end, page_size;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200184
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800185 page_size = getpagesize();
186 start = (unsigned long)addr;
187 start &= ~(page_size - 1);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200188
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800189 end = (unsigned long)addr + size;
190 end += page_size - 1;
191 end &= ~(page_size - 1);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200192
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800193 mprotect((void *)start, end - start,
194 PROT_READ | PROT_WRITE | PROT_EXEC);
195}
196#endif
197
198static void page_init(void)
199{
200 /* NOTE: we can always suppose that qemu_host_page_size >=
201 TARGET_PAGE_SIZE */
202#ifdef _WIN32
203 {
204 SYSTEM_INFO system_info;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800205
206 GetSystemInfo(&system_info);
207 qemu_real_host_page_size = system_info.dwPageSize;
208 }
209#else
210 qemu_real_host_page_size = getpagesize();
211#endif
212 if (qemu_host_page_size == 0)
213 qemu_host_page_size = qemu_real_host_page_size;
214 if (qemu_host_page_size < TARGET_PAGE_SIZE)
215 qemu_host_page_size = TARGET_PAGE_SIZE;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800216 qemu_host_page_mask = ~(qemu_host_page_size - 1);
217 l1_phys_map = qemu_vmalloc(L1_SIZE * sizeof(void *));
218 memset(l1_phys_map, 0, L1_SIZE * sizeof(void *));
219
220#if !defined(_WIN32) && defined(CONFIG_USER_ONLY)
221 {
222 long long startaddr, endaddr;
223 FILE *f;
224 int n;
225
226 mmap_lock();
227 last_brk = (unsigned long)sbrk(0);
228 f = fopen("/proc/self/maps", "r");
229 if (f) {
230 do {
231 n = fscanf (f, "%llx-%llx %*[^\n]\n", &startaddr, &endaddr);
232 if (n == 2) {
233 startaddr = MIN(startaddr,
234 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
235 endaddr = MIN(endaddr,
236 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
237 page_set_flags(startaddr & TARGET_PAGE_MASK,
238 TARGET_PAGE_ALIGN(endaddr),
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800239 PAGE_RESERVED);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800240 }
241 } while (!feof(f));
242 fclose(f);
243 }
244 mmap_unlock();
245 }
246#endif
247}
248
249static inline PageDesc **page_l1_map(target_ulong index)
250{
251#if TARGET_LONG_BITS > 32
252 /* Host memory outside guest VM. For 32-bit targets we have already
253 excluded high addresses. */
254 if (index > ((target_ulong)L2_SIZE * L1_SIZE))
255 return NULL;
256#endif
257 return &l1_map[index >> L2_BITS];
258}
259
260static inline PageDesc *page_find_alloc(target_ulong index)
261{
262 PageDesc **lp, *p;
263 lp = page_l1_map(index);
264 if (!lp)
265 return NULL;
266
267 p = *lp;
268 if (!p) {
269 /* allocate if not found */
270#if defined(CONFIG_USER_ONLY)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800271 size_t len = sizeof(PageDesc) * L2_SIZE;
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100272 /* Don't use g_malloc because it may recurse. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700273 p = mmap(NULL, len, PROT_READ | PROT_WRITE,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800274 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
275 *lp = p;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700276 if (h2g_valid(p)) {
277 unsigned long addr = h2g(p);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800278 page_set_flags(addr & TARGET_PAGE_MASK,
279 TARGET_PAGE_ALIGN(addr + len),
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800280 PAGE_RESERVED);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800281 }
282#else
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100283 p = g_malloc0(sizeof(PageDesc) * L2_SIZE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800284 *lp = p;
285#endif
286 }
287 return p + (index & (L2_SIZE - 1));
288}
289
290static inline PageDesc *page_find(target_ulong index)
291{
292 PageDesc **lp, *p;
293 lp = page_l1_map(index);
294 if (!lp)
295 return NULL;
296
297 p = *lp;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700298 if (!p) {
299 return NULL;
300 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800301 return p + (index & (L2_SIZE - 1));
302}
303
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100304static PhysPageDesc *phys_page_find_alloc(hwaddr index, int alloc)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800305{
306 void **lp, **p;
307 PhysPageDesc *pd;
308
309 p = (void **)l1_phys_map;
310#if TARGET_PHYS_ADDR_SPACE_BITS > 32
311
312#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
313#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
314#endif
315 lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1));
316 p = *lp;
317 if (!p) {
318 /* allocate if not found */
319 if (!alloc)
320 return NULL;
321 p = qemu_vmalloc(sizeof(void *) * L1_SIZE);
322 memset(p, 0, sizeof(void *) * L1_SIZE);
323 *lp = p;
324 }
325#endif
326 lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
327 pd = *lp;
328 if (!pd) {
329 int i;
330 /* allocate if not found */
331 if (!alloc)
332 return NULL;
333 pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
334 *lp = pd;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700335 for (i = 0; i < L2_SIZE; i++) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800336 pd[i].phys_offset = IO_MEM_UNASSIGNED;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700337 pd[i].region_offset = (index + i) << TARGET_PAGE_BITS;
338 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800339 }
340 return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
341}
342
David 'Digit' Turner3dc53fc2014-01-17 01:23:40 +0100343PhysPageDesc *phys_page_find(hwaddr index)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800344{
345 return phys_page_find_alloc(index, 0);
346}
347
348#if !defined(CONFIG_USER_ONLY)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800349#define mmap_lock() do { } while(0)
350#define mmap_unlock() do { } while(0)
351#endif
352
353#define DEFAULT_CODE_GEN_BUFFER_SIZE (32 * 1024 * 1024)
354
355#if defined(CONFIG_USER_ONLY)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700356/* Currently it is not recommended to allocate big chunks of data in
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800357 user mode. It will change when a dedicated libc will be used */
358#define USE_STATIC_CODE_GEN_BUFFER
359#endif
360
361#ifdef USE_STATIC_CODE_GEN_BUFFER
362static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE];
363#endif
364
365static void code_gen_alloc(unsigned long tb_size)
366{
367#ifdef USE_STATIC_CODE_GEN_BUFFER
368 code_gen_buffer = static_code_gen_buffer;
369 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
370 map_exec(code_gen_buffer, code_gen_buffer_size);
371#else
372 code_gen_buffer_size = tb_size;
373 if (code_gen_buffer_size == 0) {
374#if defined(CONFIG_USER_ONLY)
375 /* in user mode, phys_ram_size is not meaningful */
376 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
377#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700378 /* XXX: needs adjustments */
379 code_gen_buffer_size = (unsigned long)(ram_size / 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800380#endif
381 }
382 if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE)
383 code_gen_buffer_size = MIN_CODE_GEN_BUFFER_SIZE;
384 /* The code gen buffer location may have constraints depending on
385 the host cpu and OS */
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200386#if defined(__linux__)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800387 {
388 int flags;
389 void *start = NULL;
390
391 flags = MAP_PRIVATE | MAP_ANONYMOUS;
392#if defined(__x86_64__)
393 flags |= MAP_32BIT;
394 /* Cannot map more than that */
395 if (code_gen_buffer_size > (800 * 1024 * 1024))
396 code_gen_buffer_size = (800 * 1024 * 1024);
397#elif defined(__sparc_v9__)
398 // Map the buffer below 2G, so we can use direct calls and branches
399 flags |= MAP_FIXED;
400 start = (void *) 0x60000000UL;
401 if (code_gen_buffer_size > (512 * 1024 * 1024))
402 code_gen_buffer_size = (512 * 1024 * 1024);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700403#elif defined(__arm__)
404 /* Map the buffer below 32M, so we can use direct calls and branches */
405 flags |= MAP_FIXED;
406 start = (void *) 0x01000000UL;
407 if (code_gen_buffer_size > 16 * 1024 * 1024)
408 code_gen_buffer_size = 16 * 1024 * 1024;
David 'Digit' Turner36411062010-12-22 17:34:53 +0100409#elif defined(__s390x__)
410 /* Map the buffer so that we can use direct calls and branches. */
411 /* We have a +- 4GB range on the branches; leave some slop. */
412 if (code_gen_buffer_size > (3ul * 1024 * 1024 * 1024)) {
413 code_gen_buffer_size = 3ul * 1024 * 1024 * 1024;
414 }
415 start = (void *)0x90000000UL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800416#endif
417 code_gen_buffer = mmap(start, code_gen_buffer_size,
418 PROT_WRITE | PROT_READ | PROT_EXEC,
419 flags, -1, 0);
420 if (code_gen_buffer == MAP_FAILED) {
421 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
422 exit(1);
423 }
424 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200425#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \
426 || defined(__DragonFly__) || defined(__OpenBSD__)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700427 {
428 int flags;
429 void *addr = NULL;
430 flags = MAP_PRIVATE | MAP_ANONYMOUS;
431#if defined(__x86_64__)
432 /* FreeBSD doesn't have MAP_32BIT, use MAP_FIXED and assume
433 * 0x40000000 is free */
434 flags |= MAP_FIXED;
435 addr = (void *)0x40000000;
436 /* Cannot map more than that */
437 if (code_gen_buffer_size > (800 * 1024 * 1024))
438 code_gen_buffer_size = (800 * 1024 * 1024);
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200439#elif defined(__sparc_v9__)
440 // Map the buffer below 2G, so we can use direct calls and branches
441 flags |= MAP_FIXED;
442 addr = (void *) 0x60000000UL;
443 if (code_gen_buffer_size > (512 * 1024 * 1024)) {
444 code_gen_buffer_size = (512 * 1024 * 1024);
445 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700446#endif
447 code_gen_buffer = mmap(addr, code_gen_buffer_size,
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200448 PROT_WRITE | PROT_READ | PROT_EXEC,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700449 flags, -1, 0);
450 if (code_gen_buffer == MAP_FAILED) {
451 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
452 exit(1);
453 }
454 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800455#else
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100456 code_gen_buffer = g_malloc(code_gen_buffer_size);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800457 map_exec(code_gen_buffer, code_gen_buffer_size);
458#endif
459#endif /* !USE_STATIC_CODE_GEN_BUFFER */
460 map_exec(code_gen_prologue, sizeof(code_gen_prologue));
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800461 code_gen_buffer_max_size = code_gen_buffer_size -
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800462 code_gen_max_block_size();
463 code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
David 'Digit' Turner13487772014-02-17 21:16:46 +0100464 tcg_ctx.tb_ctx.tbs = g_malloc(code_gen_max_blocks * sizeof(TranslationBlock));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800465}
466
467/* Must be called before using the QEMU cpus. 'tb_size' is the size
468 (in bytes) allocated to the translation buffer. Zero means default
469 size. */
470void cpu_exec_init_all(unsigned long tb_size)
471{
472 cpu_gen_init();
473 code_gen_alloc(tb_size);
474 code_gen_ptr = code_gen_buffer;
475 page_init();
476#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +0100477 qemu_mutex_init(&ram_list.mutex);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800478 io_mem_init();
479#endif
David 'Digit' Turnerf1d9bf12011-05-11 18:19:41 +0200480#if !defined(CONFIG_USER_ONLY) || !defined(CONFIG_USE_GUEST_BASE)
481 /* There's no guest base to take into account, so go ahead and
482 initialize the prologue now. */
483 tcg_prologue_init(&tcg_ctx);
484#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800485}
486
487#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
488
489#define CPU_COMMON_SAVE_VERSION 1
490
491static void cpu_common_save(QEMUFile *f, void *opaque)
492{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100493 CPUOldState *env = opaque;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800494
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700495 cpu_synchronize_state(env, 0);
496
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800497 qemu_put_be32s(f, &env->halted);
498 qemu_put_be32s(f, &env->interrupt_request);
499}
500
501static int cpu_common_load(QEMUFile *f, void *opaque, int version_id)
502{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100503 CPUOldState *env = opaque;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800504
505 if (version_id != CPU_COMMON_SAVE_VERSION)
506 return -EINVAL;
507
508 qemu_get_be32s(f, &env->halted);
509 qemu_get_be32s(f, &env->interrupt_request);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700510 /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
511 version_id is increased. */
512 env->interrupt_request &= ~0x01;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800513 tlb_flush(env, 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700514 cpu_synchronize_state(env, 1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800515
516 return 0;
517}
518#endif
519
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100520CPUArchState *qemu_get_cpu(int cpu)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700521{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100522 CPUArchState *env = first_cpu;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700523
524 while (env) {
525 if (env->cpu_index == cpu)
526 break;
527 env = env->next_cpu;
528 }
529
530 return env;
531}
532
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100533void cpu_exec_init(CPUArchState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800534{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100535 CPUArchState **penv;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800536 int cpu_index;
537
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700538#if defined(CONFIG_USER_ONLY)
539 cpu_list_lock();
540#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800541 env->next_cpu = NULL;
542 penv = &first_cpu;
543 cpu_index = 0;
544 while (*penv != NULL) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700545 penv = &(*penv)->next_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800546 cpu_index++;
547 }
548 env->cpu_index = cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700549 env->numa_node = 0;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700550 QTAILQ_INIT(&env->breakpoints);
551 QTAILQ_INIT(&env->watchpoints);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800552 *penv = env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700553#if defined(CONFIG_USER_ONLY)
554 cpu_list_unlock();
555#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800556#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
David 'Digit' Turner5cb5c0b2014-02-17 16:04:03 +0100557 register_savevm(NULL,
558 "cpu_common",
559 cpu_index,
560 CPU_COMMON_SAVE_VERSION,
561 cpu_common_save,
562 cpu_common_load,
563 env);
564 register_savevm(NULL,
565 "cpu",
566 cpu_index,
567 CPU_SAVE_VERSION,
568 cpu_save,
569 cpu_load,
570 env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800571#endif
572}
573
574static inline void invalidate_page_bitmap(PageDesc *p)
575{
576 if (p->code_bitmap) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100577 g_free(p->code_bitmap);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800578 p->code_bitmap = NULL;
579 }
580 p->code_write_count = 0;
581}
582
583/* set to NULL all the 'first_tb' fields in all PageDescs */
584static void page_flush_tb(void)
585{
586 int i, j;
587 PageDesc *p;
588
589 for(i = 0; i < L1_SIZE; i++) {
590 p = l1_map[i];
591 if (p) {
592 for(j = 0; j < L2_SIZE; j++) {
593 p->first_tb = NULL;
594 invalidate_page_bitmap(p);
595 p++;
596 }
597 }
598 }
599}
600
601/* flush all the translation blocks */
602/* XXX: tb_flush is currently not thread safe */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100603void tb_flush(CPUArchState *env1)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800604{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100605 CPUArchState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800606#if defined(DEBUG_FLUSH)
607 printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
608 (unsigned long)(code_gen_ptr - code_gen_buffer),
609 nb_tbs, nb_tbs > 0 ?
610 ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
611#endif
612 if ((unsigned long)(code_gen_ptr - code_gen_buffer) > code_gen_buffer_size)
613 cpu_abort(env1, "Internal error: code buffer overflow\n");
614
David 'Digit' Turner13487772014-02-17 21:16:46 +0100615 tcg_ctx.tb_ctx.nb_tbs = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800616
617 for(env = first_cpu; env != NULL; env = env->next_cpu) {
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800618#ifdef CONFIG_MEMCHECK
619 int tb_to_clean;
620 for (tb_to_clean = 0; tb_to_clean < TB_JMP_CACHE_SIZE; tb_to_clean++) {
621 if (env->tb_jmp_cache[tb_to_clean] != NULL &&
622 env->tb_jmp_cache[tb_to_clean]->tpc2gpc != NULL) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100623 g_free(env->tb_jmp_cache[tb_to_clean]->tpc2gpc);
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800624 env->tb_jmp_cache[tb_to_clean]->tpc2gpc = NULL;
625 env->tb_jmp_cache[tb_to_clean]->tpc2gpc_pairs = 0;
626 }
627 }
628#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800629 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
630 }
631
David 'Digit' Turner13487772014-02-17 21:16:46 +0100632 memset (tcg_ctx.tb_ctx.tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800633 page_flush_tb();
634
635 code_gen_ptr = code_gen_buffer;
636 /* XXX: flush processor icache at this point if cache flush is
637 expensive */
David 'Digit' Turner13487772014-02-17 21:16:46 +0100638 tcg_ctx.tb_ctx.tb_flush_count++;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800639}
640
641#ifdef DEBUG_TB_CHECK
642
643static void tb_invalidate_check(target_ulong address)
644{
645 TranslationBlock *tb;
646 int i;
647 address &= TARGET_PAGE_MASK;
648 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
649 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
650 if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
651 address >= tb->pc + tb->size)) {
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700652 printf("ERROR invalidate: address=" TARGET_FMT_lx
653 " PC=%08lx size=%04x\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800654 address, (long)tb->pc, tb->size);
655 }
656 }
657 }
658}
659
660/* verify that all the pages have correct rights for code */
661static void tb_page_check(void)
662{
663 TranslationBlock *tb;
664 int i, flags1, flags2;
665
666 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
667 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
668 flags1 = page_get_flags(tb->pc);
669 flags2 = page_get_flags(tb->pc + tb->size - 1);
670 if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
671 printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
672 (long)tb->pc, tb->size, flags1, flags2);
673 }
674 }
675 }
676}
677
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800678#endif
679
680/* invalidate one TB */
681static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb,
682 int next_offset)
683{
684 TranslationBlock *tb1;
685 for(;;) {
686 tb1 = *ptb;
687 if (tb1 == tb) {
688 *ptb = *(TranslationBlock **)((char *)tb1 + next_offset);
689 break;
690 }
691 ptb = (TranslationBlock **)((char *)tb1 + next_offset);
692 }
693}
694
695static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
696{
697 TranslationBlock *tb1;
698 unsigned int n1;
699
700 for(;;) {
701 tb1 = *ptb;
702 n1 = (long)tb1 & 3;
703 tb1 = (TranslationBlock *)((long)tb1 & ~3);
704 if (tb1 == tb) {
705 *ptb = tb1->page_next[n1];
706 break;
707 }
708 ptb = &tb1->page_next[n1];
709 }
710}
711
712static inline void tb_jmp_remove(TranslationBlock *tb, int n)
713{
714 TranslationBlock *tb1, **ptb;
715 unsigned int n1;
716
717 ptb = &tb->jmp_next[n];
718 tb1 = *ptb;
719 if (tb1) {
720 /* find tb(n) in circular list */
721 for(;;) {
722 tb1 = *ptb;
723 n1 = (long)tb1 & 3;
724 tb1 = (TranslationBlock *)((long)tb1 & ~3);
725 if (n1 == n && tb1 == tb)
726 break;
727 if (n1 == 2) {
728 ptb = &tb1->jmp_first;
729 } else {
730 ptb = &tb1->jmp_next[n1];
731 }
732 }
733 /* now we can suppress tb(n) from the list */
734 *ptb = tb->jmp_next[n];
735
736 tb->jmp_next[n] = NULL;
737 }
738}
739
740/* reset the jump entry 'n' of a TB so that it is not chained to
741 another TB */
742static inline void tb_reset_jump(TranslationBlock *tb, int n)
743{
744 tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
745}
746
David 'Digit' Turner85c62202014-02-16 20:53:40 +0100747void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800748{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100749 CPUArchState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800750 PageDesc *p;
751 unsigned int h, n1;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100752 hwaddr phys_pc;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800753 TranslationBlock *tb1, *tb2;
754
755 /* remove the TB from the hash list */
756 phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
757 h = tb_phys_hash_func(phys_pc);
David 'Digit' Turner13487772014-02-17 21:16:46 +0100758 tb_remove(&tcg_ctx.tb_ctx.tb_phys_hash[h], tb,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800759 offsetof(TranslationBlock, phys_hash_next));
760
761 /* remove the TB from the page list */
762 if (tb->page_addr[0] != page_addr) {
763 p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
764 tb_page_remove(&p->first_tb, tb);
765 invalidate_page_bitmap(p);
766 }
767 if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
768 p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
769 tb_page_remove(&p->first_tb, tb);
770 invalidate_page_bitmap(p);
771 }
772
David 'Digit' Turner13487772014-02-17 21:16:46 +0100773 tcg_ctx.tb_ctx.tb_invalidated_flag = 1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800774
775 /* remove the TB from the hash list */
776 h = tb_jmp_cache_hash_func(tb->pc);
777 for(env = first_cpu; env != NULL; env = env->next_cpu) {
778 if (env->tb_jmp_cache[h] == tb)
779 env->tb_jmp_cache[h] = NULL;
780 }
781
782 /* suppress this TB from the two jump lists */
783 tb_jmp_remove(tb, 0);
784 tb_jmp_remove(tb, 1);
785
786 /* suppress any remaining jumps to this TB */
787 tb1 = tb->jmp_first;
788 for(;;) {
789 n1 = (long)tb1 & 3;
790 if (n1 == 2)
791 break;
792 tb1 = (TranslationBlock *)((long)tb1 & ~3);
793 tb2 = tb1->jmp_next[n1];
794 tb_reset_jump(tb1, n1);
795 tb1->jmp_next[n1] = NULL;
796 tb1 = tb2;
797 }
798 tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
799
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800800#ifdef CONFIG_MEMCHECK
801 if (tb->tpc2gpc != NULL) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100802 g_free(tb->tpc2gpc);
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800803 tb->tpc2gpc = NULL;
804 tb->tpc2gpc_pairs = 0;
805 }
806#endif // CONFIG_MEMCHECK
807
David 'Digit' Turner13487772014-02-17 21:16:46 +0100808 tcg_ctx.tb_ctx.tb_phys_invalidate_count++;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800809}
810
811static inline void set_bits(uint8_t *tab, int start, int len)
812{
813 int end, mask, end1;
814
815 end = start + len;
816 tab += start >> 3;
817 mask = 0xff << (start & 7);
818 if ((start & ~7) == (end & ~7)) {
819 if (start < end) {
820 mask &= ~(0xff << (end & 7));
821 *tab |= mask;
822 }
823 } else {
824 *tab++ |= mask;
825 start = (start + 8) & ~7;
826 end1 = end & ~7;
827 while (start < end1) {
828 *tab++ = 0xff;
829 start += 8;
830 }
831 if (start < end) {
832 mask = ~(0xff << (end & 7));
833 *tab |= mask;
834 }
835 }
836}
837
838static void build_page_bitmap(PageDesc *p)
839{
840 int n, tb_start, tb_end;
841 TranslationBlock *tb;
842
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100843 p->code_bitmap = g_malloc0(TARGET_PAGE_SIZE / 8);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800844
845 tb = p->first_tb;
846 while (tb != NULL) {
847 n = (long)tb & 3;
848 tb = (TranslationBlock *)((long)tb & ~3);
849 /* NOTE: this is subtle as a TB may span two physical pages */
850 if (n == 0) {
851 /* NOTE: tb_end may be after the end of the page, but
852 it is not a problem */
853 tb_start = tb->pc & ~TARGET_PAGE_MASK;
854 tb_end = tb_start + tb->size;
855 if (tb_end > TARGET_PAGE_SIZE)
856 tb_end = TARGET_PAGE_SIZE;
857 } else {
858 tb_start = 0;
859 tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
860 }
861 set_bits(p->code_bitmap, tb_start, tb_end - tb_start);
862 tb = tb->page_next[n];
863 }
864}
865
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100866TranslationBlock *tb_gen_code(CPUArchState *env,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800867 target_ulong pc, target_ulong cs_base,
868 int flags, int cflags)
869{
870 TranslationBlock *tb;
871 uint8_t *tc_ptr;
872 target_ulong phys_pc, phys_page2, virt_page2;
873 int code_gen_size;
874
David 'Digit' Turner13487772014-02-17 21:16:46 +0100875 phys_pc = get_page_addr_code(env, pc);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800876 tb = tb_alloc(pc);
877 if (!tb) {
878 /* flush must be done */
879 tb_flush(env);
880 /* cannot fail at this point */
881 tb = tb_alloc(pc);
882 /* Don't forget to invalidate previous TB info. */
David 'Digit' Turner13487772014-02-17 21:16:46 +0100883 tcg_ctx.tb_ctx.tb_invalidated_flag = 1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800884 }
885 tc_ptr = code_gen_ptr;
886 tb->tc_ptr = tc_ptr;
887 tb->cs_base = cs_base;
888 tb->flags = flags;
889 tb->cflags = cflags;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800890 cpu_gen_code(env, tb, &code_gen_size);
891 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
892
893 /* check next page if needed */
894 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
895 phys_page2 = -1;
896 if ((pc & TARGET_PAGE_MASK) != virt_page2) {
David 'Digit' Turner13487772014-02-17 21:16:46 +0100897 phys_page2 = get_page_addr_code(env, virt_page2);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800898 }
899 tb_link_phys(tb, phys_pc, phys_page2);
900 return tb;
901}
902
903/* invalidate all TBs which intersect with the target physical page
904 starting in range [start;end[. NOTE: start and end must refer to
905 the same physical page. 'is_cpu_write_access' should be true if called
906 from a real cpu write access: the virtual CPU will exit the current
907 TB if code is modified inside this TB. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100908void tb_invalidate_phys_page_range(hwaddr start, hwaddr end,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800909 int is_cpu_write_access)
910{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700911 TranslationBlock *tb, *tb_next, *saved_tb;
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100912 CPUArchState *env = cpu_single_env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800913 target_ulong tb_start, tb_end;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700914 PageDesc *p;
915 int n;
916#ifdef TARGET_HAS_PRECISE_SMC
917 int current_tb_not_found = is_cpu_write_access;
918 TranslationBlock *current_tb = NULL;
919 int current_tb_modified = 0;
920 target_ulong current_pc = 0;
921 target_ulong current_cs_base = 0;
922 int current_flags = 0;
923#endif /* TARGET_HAS_PRECISE_SMC */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800924
925 p = page_find(start >> TARGET_PAGE_BITS);
926 if (!p)
927 return;
928 if (!p->code_bitmap &&
929 ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
930 is_cpu_write_access) {
931 /* build code bitmap */
932 build_page_bitmap(p);
933 }
934
935 /* we remove all the TBs in the range [start, end[ */
936 /* 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 -0800937 tb = p->first_tb;
938 while (tb != NULL) {
939 n = (long)tb & 3;
940 tb = (TranslationBlock *)((long)tb & ~3);
941 tb_next = tb->page_next[n];
942 /* NOTE: this is subtle as a TB may span two physical pages */
943 if (n == 0) {
944 /* NOTE: tb_end may be after the end of the page, but
945 it is not a problem */
946 tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
947 tb_end = tb_start + tb->size;
948 } else {
949 tb_start = tb->page_addr[1];
950 tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
951 }
952 if (!(tb_end <= start || tb_start >= end)) {
953#ifdef TARGET_HAS_PRECISE_SMC
954 if (current_tb_not_found) {
955 current_tb_not_found = 0;
956 current_tb = NULL;
957 if (env->mem_io_pc) {
958 /* now we have a real cpu fault */
959 current_tb = tb_find_pc(env->mem_io_pc);
960 }
961 }
962 if (current_tb == tb &&
963 (current_tb->cflags & CF_COUNT_MASK) != 1) {
964 /* If we are modifying the current TB, we must stop
965 its execution. We could be more precise by checking
966 that the modification is after the current PC, but it
967 would require a specialized function to partially
968 restore the CPU state */
969
970 current_tb_modified = 1;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200971 cpu_restore_state(current_tb, env, env->mem_io_pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700972 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
973 &current_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800974 }
975#endif /* TARGET_HAS_PRECISE_SMC */
976 /* we need to do that to handle the case where a signal
977 occurs while doing tb_phys_invalidate() */
978 saved_tb = NULL;
979 if (env) {
980 saved_tb = env->current_tb;
981 env->current_tb = NULL;
982 }
983 tb_phys_invalidate(tb, -1);
984 if (env) {
985 env->current_tb = saved_tb;
986 if (env->interrupt_request && env->current_tb)
987 cpu_interrupt(env, env->interrupt_request);
988 }
989 }
990 tb = tb_next;
991 }
992#if !defined(CONFIG_USER_ONLY)
993 /* if no code remaining, no need to continue to use slow writes */
994 if (!p->first_tb) {
995 invalidate_page_bitmap(p);
996 if (is_cpu_write_access) {
997 tlb_unprotect_code_phys(env, start, env->mem_io_vaddr);
998 }
999 }
1000#endif
1001#ifdef TARGET_HAS_PRECISE_SMC
1002 if (current_tb_modified) {
1003 /* we generate a block containing just the instruction
1004 modifying the memory. It will ensure that it cannot modify
1005 itself */
1006 env->current_tb = NULL;
1007 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1008 cpu_resume_from_signal(env, NULL);
1009 }
1010#endif
1011}
1012
1013/* len must be <= 8 and start must be a multiple of len */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001014static inline void tb_invalidate_phys_page_fast(hwaddr start, int len)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001015{
1016 PageDesc *p;
1017 int offset, b;
1018#if 0
1019 if (1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001020 qemu_log("modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
1021 cpu_single_env->mem_io_vaddr, len,
1022 cpu_single_env->eip,
1023 cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001024 }
1025#endif
1026 p = page_find(start >> TARGET_PAGE_BITS);
1027 if (!p)
1028 return;
1029 if (p->code_bitmap) {
1030 offset = start & ~TARGET_PAGE_MASK;
1031 b = p->code_bitmap[offset >> 3] >> (offset & 7);
1032 if (b & ((1 << len) - 1))
1033 goto do_invalidate;
1034 } else {
1035 do_invalidate:
1036 tb_invalidate_phys_page_range(start, start + len, 1);
1037 }
1038}
1039
1040#if !defined(CONFIG_SOFTMMU)
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001041static void tb_invalidate_phys_page(hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001042 unsigned long pc, void *puc)
1043{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001044 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001045 PageDesc *p;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001046 int n;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001047#ifdef TARGET_HAS_PRECISE_SMC
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001048 TranslationBlock *current_tb = NULL;
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001049 CPUArchState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001050 int current_tb_modified = 0;
1051 target_ulong current_pc = 0;
1052 target_ulong current_cs_base = 0;
1053 int current_flags = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001054#endif
1055
1056 addr &= TARGET_PAGE_MASK;
1057 p = page_find(addr >> TARGET_PAGE_BITS);
1058 if (!p)
1059 return;
1060 tb = p->first_tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001061#ifdef TARGET_HAS_PRECISE_SMC
1062 if (tb && pc != 0) {
1063 current_tb = tb_find_pc(pc);
1064 }
1065#endif
1066 while (tb != NULL) {
1067 n = (long)tb & 3;
1068 tb = (TranslationBlock *)((long)tb & ~3);
1069#ifdef TARGET_HAS_PRECISE_SMC
1070 if (current_tb == tb &&
1071 (current_tb->cflags & CF_COUNT_MASK) != 1) {
1072 /* If we are modifying the current TB, we must stop
1073 its execution. We could be more precise by checking
1074 that the modification is after the current PC, but it
1075 would require a specialized function to partially
1076 restore the CPU state */
1077
1078 current_tb_modified = 1;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02001079 cpu_restore_state(current_tb, env, pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001080 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
1081 &current_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001082 }
1083#endif /* TARGET_HAS_PRECISE_SMC */
1084 tb_phys_invalidate(tb, addr);
1085 tb = tb->page_next[n];
1086 }
1087 p->first_tb = NULL;
1088#ifdef TARGET_HAS_PRECISE_SMC
1089 if (current_tb_modified) {
1090 /* we generate a block containing just the instruction
1091 modifying the memory. It will ensure that it cannot modify
1092 itself */
1093 env->current_tb = NULL;
1094 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1095 cpu_resume_from_signal(env, puc);
1096 }
1097#endif
1098}
1099#endif
1100
1101/* add the tb in the target page and protect it if necessary */
1102static inline void tb_alloc_page(TranslationBlock *tb,
1103 unsigned int n, target_ulong page_addr)
1104{
1105 PageDesc *p;
1106 TranslationBlock *last_first_tb;
1107
1108 tb->page_addr[n] = page_addr;
1109 p = page_find_alloc(page_addr >> TARGET_PAGE_BITS);
1110 tb->page_next[n] = p->first_tb;
1111 last_first_tb = p->first_tb;
1112 p->first_tb = (TranslationBlock *)((long)tb | n);
1113 invalidate_page_bitmap(p);
1114
1115#if defined(TARGET_HAS_SMC) || 1
1116
1117#if defined(CONFIG_USER_ONLY)
1118 if (p->flags & PAGE_WRITE) {
1119 target_ulong addr;
1120 PageDesc *p2;
1121 int prot;
1122
1123 /* force the host page as non writable (writes will have a
1124 page fault + mprotect overhead) */
1125 page_addr &= qemu_host_page_mask;
1126 prot = 0;
1127 for(addr = page_addr; addr < page_addr + qemu_host_page_size;
1128 addr += TARGET_PAGE_SIZE) {
1129
1130 p2 = page_find (addr >> TARGET_PAGE_BITS);
1131 if (!p2)
1132 continue;
1133 prot |= p2->flags;
1134 p2->flags &= ~PAGE_WRITE;
1135 page_get_flags(addr);
1136 }
1137 mprotect(g2h(page_addr), qemu_host_page_size,
1138 (prot & PAGE_BITS) & ~PAGE_WRITE);
1139#ifdef DEBUG_TB_INVALIDATE
1140 printf("protecting code page: 0x" TARGET_FMT_lx "\n",
1141 page_addr);
1142#endif
1143 }
1144#else
1145 /* if some code is already present, then the pages are already
1146 protected. So we handle the case where only the first TB is
1147 allocated in a physical page */
1148 if (!last_first_tb) {
1149 tlb_protect_code(page_addr);
1150 }
1151#endif
1152
1153#endif /* TARGET_HAS_SMC */
1154}
1155
1156/* Allocate a new translation block. Flush the translation buffer if
1157 too many translation blocks or too much generated code. */
1158TranslationBlock *tb_alloc(target_ulong pc)
1159{
1160 TranslationBlock *tb;
1161
David 'Digit' Turner13487772014-02-17 21:16:46 +01001162 if (tcg_ctx.tb_ctx.nb_tbs >= code_gen_max_blocks ||
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001163 (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
1164 return NULL;
David 'Digit' Turner13487772014-02-17 21:16:46 +01001165 tb = &tcg_ctx.tb_ctx.tbs[tcg_ctx.tb_ctx.nb_tbs++];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001166 tb->pc = pc;
1167 tb->cflags = 0;
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -08001168#ifdef CONFIG_MEMCHECK
1169 tb->tpc2gpc = NULL;
1170 tb->tpc2gpc_pairs = 0;
1171#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001172 return tb;
1173}
1174
1175void tb_free(TranslationBlock *tb)
1176{
1177 /* In practice this is mostly used for single use temporary TB
1178 Ignore the hard cases and just back up if this TB happens to
1179 be the last one generated. */
David 'Digit' Turner13487772014-02-17 21:16:46 +01001180 if (tcg_ctx.tb_ctx.nb_tbs > 0 && tb == &tcg_ctx.tb_ctx.tbs[tcg_ctx.tb_ctx.nb_tbs - 1]) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001181 code_gen_ptr = tb->tc_ptr;
David 'Digit' Turner13487772014-02-17 21:16:46 +01001182 tcg_ctx.tb_ctx.nb_tbs--;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001183 }
1184}
1185
1186/* add a new TB and link it to the physical page tables. phys_page2 is
1187 (-1) to indicate that only one page contains the TB. */
1188void tb_link_phys(TranslationBlock *tb,
1189 target_ulong phys_pc, target_ulong phys_page2)
1190{
1191 unsigned int h;
1192 TranslationBlock **ptb;
1193
1194 /* Grab the mmap lock to stop another thread invalidating this TB
1195 before we are done. */
1196 mmap_lock();
1197 /* add in the physical hash table */
1198 h = tb_phys_hash_func(phys_pc);
David 'Digit' Turner13487772014-02-17 21:16:46 +01001199 ptb = &tcg_ctx.tb_ctx.tb_phys_hash[h];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001200 tb->phys_hash_next = *ptb;
1201 *ptb = tb;
1202
1203 /* add in the page list */
1204 tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK);
1205 if (phys_page2 != -1)
1206 tb_alloc_page(tb, 1, phys_page2);
1207 else
1208 tb->page_addr[1] = -1;
1209
1210 tb->jmp_first = (TranslationBlock *)((long)tb | 2);
1211 tb->jmp_next[0] = NULL;
1212 tb->jmp_next[1] = NULL;
1213
1214 /* init original jump addresses */
1215 if (tb->tb_next_offset[0] != 0xffff)
1216 tb_reset_jump(tb, 0);
1217 if (tb->tb_next_offset[1] != 0xffff)
1218 tb_reset_jump(tb, 1);
1219
1220#ifdef DEBUG_TB_CHECK
1221 tb_page_check();
1222#endif
1223 mmap_unlock();
1224}
1225
1226/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
1227 tb[1].tc_ptr. Return NULL if not found */
1228TranslationBlock *tb_find_pc(unsigned long tc_ptr)
1229{
1230 int m_min, m_max, m;
1231 unsigned long v;
1232 TranslationBlock *tb;
1233
David 'Digit' Turner13487772014-02-17 21:16:46 +01001234 if (tcg_ctx.tb_ctx.nb_tbs <= 0)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001235 return NULL;
1236 if (tc_ptr < (unsigned long)code_gen_buffer ||
1237 tc_ptr >= (unsigned long)code_gen_ptr)
1238 return NULL;
1239 /* binary search (cf Knuth) */
1240 m_min = 0;
David 'Digit' Turner13487772014-02-17 21:16:46 +01001241 m_max = tcg_ctx.tb_ctx.nb_tbs - 1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001242 while (m_min <= m_max) {
1243 m = (m_min + m_max) >> 1;
David 'Digit' Turner13487772014-02-17 21:16:46 +01001244 tb = &tcg_ctx.tb_ctx.tbs[m];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001245 v = (unsigned long)tb->tc_ptr;
1246 if (v == tc_ptr)
1247 return tb;
1248 else if (tc_ptr < v) {
1249 m_max = m - 1;
1250 } else {
1251 m_min = m + 1;
1252 }
1253 }
David 'Digit' Turner13487772014-02-17 21:16:46 +01001254 return &tcg_ctx.tb_ctx.tbs[m_max];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001255}
1256
1257static void tb_reset_jump_recursive(TranslationBlock *tb);
1258
1259static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
1260{
1261 TranslationBlock *tb1, *tb_next, **ptb;
1262 unsigned int n1;
1263
1264 tb1 = tb->jmp_next[n];
1265 if (tb1 != NULL) {
1266 /* find head of list */
1267 for(;;) {
1268 n1 = (long)tb1 & 3;
1269 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1270 if (n1 == 2)
1271 break;
1272 tb1 = tb1->jmp_next[n1];
1273 }
1274 /* we are now sure now that tb jumps to tb1 */
1275 tb_next = tb1;
1276
1277 /* remove tb from the jmp_first list */
1278 ptb = &tb_next->jmp_first;
1279 for(;;) {
1280 tb1 = *ptb;
1281 n1 = (long)tb1 & 3;
1282 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1283 if (n1 == n && tb1 == tb)
1284 break;
1285 ptb = &tb1->jmp_next[n1];
1286 }
1287 *ptb = tb->jmp_next[n];
1288 tb->jmp_next[n] = NULL;
1289
1290 /* suppress the jump to next tb in generated code */
1291 tb_reset_jump(tb, n);
1292
1293 /* suppress jumps in the tb on which we could have jumped */
1294 tb_reset_jump_recursive(tb_next);
1295 }
1296}
1297
1298static void tb_reset_jump_recursive(TranslationBlock *tb)
1299{
1300 tb_reset_jump_recursive2(tb, 0);
1301 tb_reset_jump_recursive2(tb, 1);
1302}
1303
1304#if defined(TARGET_HAS_ICE)
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001305static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001306{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001307 hwaddr addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001308 target_ulong pd;
1309 ram_addr_t ram_addr;
1310 PhysPageDesc *p;
1311
1312 addr = cpu_get_phys_page_debug(env, pc);
1313 p = phys_page_find(addr >> TARGET_PAGE_BITS);
1314 if (!p) {
1315 pd = IO_MEM_UNASSIGNED;
1316 } else {
1317 pd = p->phys_offset;
1318 }
1319 ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
1320 tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
1321}
1322#endif
1323
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001324#if defined(CONFIG_USER_ONLY)
1325void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
1326
1327{
1328}
1329
1330int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
1331 int flags, CPUWatchpoint **watchpoint)
1332{
1333 return -ENOSYS;
1334}
1335#else
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001336/* Add a watchpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001337int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001338 int flags, CPUWatchpoint **watchpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001339{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001340 target_ulong len_mask = ~(len - 1);
1341 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001342
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001343 /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001344 if ((len & (len - 1)) || (addr & ~len_mask) ||
1345 len == 0 || len > TARGET_PAGE_SIZE) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001346 fprintf(stderr, "qemu: tried to set invalid watchpoint at "
1347 TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
1348 return -EINVAL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001349 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001350 wp = g_malloc(sizeof(*wp));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001351
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001352 wp->vaddr = addr;
1353 wp->len_mask = len_mask;
1354 wp->flags = flags;
1355
1356 /* keep all GDB-injected watchpoints in front */
1357 if (flags & BP_GDB)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001358 QTAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001359 else
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001360 QTAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001361
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001362 tlb_flush_page(env, addr);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001363
1364 if (watchpoint)
1365 *watchpoint = wp;
1366 return 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001367}
1368
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001369/* Remove a specific watchpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001370int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, target_ulong len,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001371 int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001372{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001373 target_ulong len_mask = ~(len - 1);
1374 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001375
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001376 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001377 if (addr == wp->vaddr && len_mask == wp->len_mask
1378 && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
1379 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001380 return 0;
1381 }
1382 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001383 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001384}
1385
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001386/* Remove a specific watchpoint by reference. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001387void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001388{
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001389 QTAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001390
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001391 tlb_flush_page(env, watchpoint->vaddr);
1392
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001393 g_free(watchpoint);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001394}
1395
1396/* Remove all matching watchpoints. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001397void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001398{
1399 CPUWatchpoint *wp, *next;
1400
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001401 QTAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001402 if (wp->flags & mask)
1403 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001404 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001405}
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001406#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001407
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001408/* Add a breakpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001409int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001410 CPUBreakpoint **breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001411{
1412#if defined(TARGET_HAS_ICE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001413 CPUBreakpoint *bp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001414
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001415 bp = g_malloc(sizeof(*bp));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001416
1417 bp->pc = pc;
1418 bp->flags = flags;
1419
1420 /* keep all GDB-injected breakpoints in front */
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001421 if (flags & BP_GDB) {
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001422 QTAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001423 } else {
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001424 QTAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001425 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001426
1427 breakpoint_invalidate(env, pc);
1428
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001429 if (breakpoint) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001430 *breakpoint = bp;
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001431 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001432 return 0;
1433#else
1434 return -ENOSYS;
1435#endif
1436}
1437
1438/* Remove a specific breakpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001439int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001440{
1441#if defined(TARGET_HAS_ICE)
1442 CPUBreakpoint *bp;
1443
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001444 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001445 if (bp->pc == pc && bp->flags == flags) {
1446 cpu_breakpoint_remove_by_ref(env, bp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001447 return 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001448 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001449 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001450 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001451#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001452 return -ENOSYS;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001453#endif
1454}
1455
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001456/* Remove a specific breakpoint by reference. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001457void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001458{
1459#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001460 QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001461
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001462 breakpoint_invalidate(env, breakpoint->pc);
1463
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001464 g_free(breakpoint);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001465#endif
1466}
1467
1468/* Remove all matching breakpoints. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001469void cpu_breakpoint_remove_all(CPUArchState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001470{
1471#if defined(TARGET_HAS_ICE)
1472 CPUBreakpoint *bp, *next;
1473
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001474 QTAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001475 if (bp->flags & mask)
1476 cpu_breakpoint_remove_by_ref(env, bp);
1477 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001478#endif
1479}
1480
1481/* enable or disable single step mode. EXCP_DEBUG is returned by the
1482 CPU loop after each instruction */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001483void cpu_single_step(CPUOldState *env, int enabled)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001484{
1485#if defined(TARGET_HAS_ICE)
1486 if (env->singlestep_enabled != enabled) {
1487 env->singlestep_enabled = enabled;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001488 if (kvm_enabled())
1489 kvm_update_guest_debug(env, 0);
1490 else {
1491 /* must flush all the translated code to avoid inconsistencies */
1492 /* XXX: only flush what is necessary */
1493 tb_flush(env);
1494 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001495 }
1496#endif
1497}
1498
1499/* enable or disable low levels log */
1500void cpu_set_log(int log_flags)
1501{
1502 loglevel = log_flags;
1503 if (loglevel && !logfile) {
1504 logfile = fopen(logfilename, log_append ? "a" : "w");
1505 if (!logfile) {
1506 perror(logfilename);
Iliyan Malchev4a2c9dd2012-04-02 08:20:56 -07001507 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001508 }
1509#if !defined(CONFIG_SOFTMMU)
1510 /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1511 {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001512 static char logfile_buf[4096];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001513 setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1514 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001515#elif !defined(_WIN32)
1516 /* Win32 doesn't support line-buffering and requires size >= 2 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001517 setvbuf(logfile, NULL, _IOLBF, 0);
1518#endif
1519 log_append = 1;
1520 }
1521 if (!loglevel && logfile) {
1522 fclose(logfile);
1523 logfile = NULL;
1524 }
1525}
1526
1527void cpu_set_log_filename(const char *filename)
1528{
1529 logfilename = strdup(filename);
1530 if (logfile) {
1531 fclose(logfile);
1532 logfile = NULL;
1533 }
1534 cpu_set_log(loglevel);
1535}
1536
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001537static void cpu_unlink_tb(CPUOldState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001538{
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001539 /* FIXME: TB unchaining isn't SMP safe. For now just ignore the
1540 problem and hope the cpu will stop of its own accord. For userspace
1541 emulation this often isn't actually as bad as it sounds. Often
1542 signals are used primarily to interrupt blocking syscalls. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001543 TranslationBlock *tb;
1544 static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
1545
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001546 spin_lock(&interrupt_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001547 tb = env->current_tb;
1548 /* if the cpu is currently executing code, we must unlink it and
1549 all the potentially executing TB */
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001550 if (tb) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001551 env->current_tb = NULL;
1552 tb_reset_jump_recursive(tb);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001553 }
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001554 spin_unlock(&interrupt_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001555}
1556
1557/* mask must never be zero, except for A20 change call */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001558void cpu_interrupt(CPUOldState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001559{
1560 int old_mask;
1561
1562 old_mask = env->interrupt_request;
1563 env->interrupt_request |= mask;
1564
1565#ifndef CONFIG_USER_ONLY
1566 /*
1567 * If called from iothread context, wake the target cpu in
1568 * case its halted.
1569 */
1570 if (!qemu_cpu_self(env)) {
1571 qemu_cpu_kick(env);
1572 return;
1573 }
1574#endif
1575
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001576 if (use_icount) {
1577 env->icount_decr.u16.high = 0xffff;
1578#ifndef CONFIG_USER_ONLY
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001579 if (!can_do_io(env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001580 && (mask & ~old_mask) != 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001581 cpu_abort(env, "Raised interrupt while not in I/O function");
1582 }
1583#endif
1584 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001585 cpu_unlink_tb(env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001586 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001587}
1588
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001589void cpu_reset_interrupt(CPUOldState *env, int mask)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001590{
1591 env->interrupt_request &= ~mask;
1592}
1593
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001594void cpu_exit(CPUOldState *env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001595{
1596 env->exit_request = 1;
1597 cpu_unlink_tb(env);
1598}
1599
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001600void cpu_abort(CPUArchState *env, const char *fmt, ...)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001601{
1602 va_list ap;
1603 va_list ap2;
1604
1605 va_start(ap, fmt);
1606 va_copy(ap2, ap);
1607 fprintf(stderr, "qemu: fatal: ");
1608 vfprintf(stderr, fmt, ap);
1609 fprintf(stderr, "\n");
1610#ifdef TARGET_I386
1611 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1612#else
1613 cpu_dump_state(env, stderr, fprintf, 0);
1614#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001615 if (qemu_log_enabled()) {
1616 qemu_log("qemu: fatal: ");
1617 qemu_log_vprintf(fmt, ap2);
1618 qemu_log("\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001619#ifdef TARGET_I386
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001620 log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001621#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001622 log_cpu_state(env, 0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001623#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001624 qemu_log_flush();
1625 qemu_log_close();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001626 }
1627 va_end(ap2);
1628 va_end(ap);
David 'Digit' Turner36411062010-12-22 17:34:53 +01001629#if defined(CONFIG_USER_ONLY)
1630 {
1631 struct sigaction act;
1632 sigfillset(&act.sa_mask);
1633 act.sa_handler = SIG_DFL;
1634 sigaction(SIGABRT, &act, NULL);
1635 }
1636#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001637 abort();
1638}
1639
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001640CPUArchState *cpu_copy(CPUOldState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001641{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001642 CPUArchState *new_env = cpu_init(env->cpu_model_str);
1643 CPUArchState *next_cpu = new_env->next_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001644 int cpu_index = new_env->cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001645#if defined(TARGET_HAS_ICE)
1646 CPUBreakpoint *bp;
1647 CPUWatchpoint *wp;
1648#endif
1649
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001650 memcpy(new_env, env, sizeof(CPUOldState));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001651
1652 /* Preserve chaining and index. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001653 new_env->next_cpu = next_cpu;
1654 new_env->cpu_index = cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001655
1656 /* Clone all break/watchpoints.
1657 Note: Once we support ptrace with hw-debug register access, make sure
1658 BP_CPU break/watchpoints are handled correctly on clone. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001659 QTAILQ_INIT(&env->breakpoints);
1660 QTAILQ_INIT(&env->watchpoints);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001661#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001662 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001663 cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
1664 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001665 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001666 cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
1667 wp->flags, NULL);
1668 }
1669#endif
1670
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001671 return new_env;
1672}
1673
1674#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001675static RAMBlock *qemu_get_ram_block(ram_addr_t addr)
1676{
1677 RAMBlock *block;
1678
1679 /* The list is protected by the iothread lock here. */
1680 block = ram_list.mru_block;
1681 if (block && addr - block->offset < block->length) {
1682 goto found;
1683 }
1684 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
1685 if (addr - block->offset < block->length) {
1686 goto found;
1687 }
1688 }
1689
1690 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
1691 abort();
1692
1693found:
1694 ram_list.mru_block = block;
1695 return block;
1696}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001697
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001698/* Note: start and end must be within the same ram block. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001699void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
1700 int dirty_flags)
1701{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001702 CPUOldState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001703 unsigned long length, start1;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001704 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001705
1706 start &= TARGET_PAGE_MASK;
1707 end = TARGET_PAGE_ALIGN(end);
1708
1709 length = end - start;
1710 if (length == 0)
1711 return;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001712 cpu_physical_memory_mask_dirty_range(start, length, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001713
1714 /* we modify the TLB cache so that the dirty bit will be set again
1715 when accessing the range */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001716 start1 = (unsigned long)qemu_safe_ram_ptr(start);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001717 /* Chek that we don't span multiple blocks - this breaks the
1718 address comparisons below. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001719 if ((unsigned long)qemu_safe_ram_ptr(end - 1) - start1
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001720 != (end - 1) - start) {
1721 abort();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001722 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001723
1724 for(env = first_cpu; env != NULL; env = env->next_cpu) {
1725 int mmu_idx;
1726 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1727 for(i = 0; i < CPU_TLB_SIZE; i++)
1728 tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
1729 start1, length);
1730 }
1731 }
1732}
1733
1734int cpu_physical_memory_set_dirty_tracking(int enable)
1735{
1736 in_migration = enable;
1737 if (kvm_enabled()) {
1738 return kvm_set_migration_log(enable);
1739 }
1740 return 0;
1741}
1742
1743int cpu_physical_memory_get_dirty_tracking(void)
1744{
1745 return in_migration;
1746}
1747
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001748int cpu_physical_sync_dirty_bitmap(hwaddr start_addr,
1749 hwaddr end_addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001750{
1751 int ret = 0;
1752
1753 if (kvm_enabled())
1754 ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
1755 return ret;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001756}
1757
1758static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1759{
1760 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001761 void *p;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001762
1763 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001764 p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
1765 + tlb_entry->addend);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001766 ram_addr = qemu_ram_addr_from_host_nofail(p);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001767 if (!cpu_physical_memory_is_dirty(ram_addr)) {
1768 tlb_entry->addr_write |= TLB_NOTDIRTY;
1769 }
1770 }
1771}
1772
1773/* update the TLB according to the current state of the dirty bits */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001774void cpu_tlb_update_dirty(CPUArchState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001775{
1776 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001777 int mmu_idx;
1778 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1779 for(i = 0; i < CPU_TLB_SIZE; i++)
1780 tlb_update_dirty(&env->tlb_table[mmu_idx][i]);
1781 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001782}
1783
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001784
1785#else
1786
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001787void tlb_flush(CPUArchState *env, int flush_global)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001788{
1789}
1790
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001791void tlb_flush_page(CPUArchState *env, target_ulong addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001792{
1793}
1794
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001795int tlb_set_page_exec(CPUArchState *env, target_ulong vaddr,
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001796 hwaddr paddr, int prot,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001797 int mmu_idx, int is_softmmu)
1798{
1799 return 0;
1800}
1801
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001802/*
1803 * Walks guest process memory "regions" one by one
1804 * and calls callback function 'fn' for each region.
1805 */
1806int walk_memory_regions(void *priv,
1807 int (*fn)(void *, unsigned long, unsigned long, unsigned long))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001808{
1809 unsigned long start, end;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001810 PageDesc *p = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001811 int i, j, prot, prot1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001812 int rc = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001813
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001814 start = end = -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001815 prot = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001816
1817 for (i = 0; i <= L1_SIZE; i++) {
1818 p = (i < L1_SIZE) ? l1_map[i] : NULL;
1819 for (j = 0; j < L2_SIZE; j++) {
1820 prot1 = (p == NULL) ? 0 : p[j].flags;
1821 /*
1822 * "region" is one continuous chunk of memory
1823 * that has same protection flags set.
1824 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001825 if (prot1 != prot) {
1826 end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
1827 if (start != -1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001828 rc = (*fn)(priv, start, end, prot);
1829 /* callback can stop iteration by returning != 0 */
1830 if (rc != 0)
1831 return (rc);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001832 }
1833 if (prot1 != 0)
1834 start = end;
1835 else
1836 start = -1;
1837 prot = prot1;
1838 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001839 if (p == NULL)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001840 break;
1841 }
1842 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001843 return (rc);
1844}
1845
1846static int dump_region(void *priv, unsigned long start,
1847 unsigned long end, unsigned long prot)
1848{
1849 FILE *f = (FILE *)priv;
1850
1851 (void) fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
1852 start, end, end - start,
1853 ((prot & PAGE_READ) ? 'r' : '-'),
1854 ((prot & PAGE_WRITE) ? 'w' : '-'),
1855 ((prot & PAGE_EXEC) ? 'x' : '-'));
1856
1857 return (0);
1858}
1859
1860/* dump memory mappings */
1861void page_dump(FILE *f)
1862{
1863 (void) fprintf(f, "%-8s %-8s %-8s %s\n",
1864 "start", "end", "size", "prot");
1865 walk_memory_regions(f, dump_region);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001866}
1867
1868int page_get_flags(target_ulong address)
1869{
1870 PageDesc *p;
1871
1872 p = page_find(address >> TARGET_PAGE_BITS);
1873 if (!p)
1874 return 0;
1875 return p->flags;
1876}
1877
David 'Digit' Turner36411062010-12-22 17:34:53 +01001878/* Modify the flags of a page and invalidate the code if necessary.
1879 The flag PAGE_WRITE_ORG is positioned automatically depending
1880 on PAGE_WRITE. The mmap_lock should already be held. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001881void page_set_flags(target_ulong start, target_ulong end, int flags)
1882{
1883 PageDesc *p;
1884 target_ulong addr;
1885
1886 /* mmap_lock should already be held. */
1887 start = start & TARGET_PAGE_MASK;
1888 end = TARGET_PAGE_ALIGN(end);
1889 if (flags & PAGE_WRITE)
1890 flags |= PAGE_WRITE_ORG;
1891 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1892 p = page_find_alloc(addr >> TARGET_PAGE_BITS);
1893 /* We may be called for host regions that are outside guest
1894 address space. */
1895 if (!p)
1896 return;
1897 /* if the write protection is set, then we invalidate the code
1898 inside */
1899 if (!(p->flags & PAGE_WRITE) &&
1900 (flags & PAGE_WRITE) &&
1901 p->first_tb) {
1902 tb_invalidate_phys_page(addr, 0, NULL);
1903 }
1904 p->flags = flags;
1905 }
1906}
1907
1908int page_check_range(target_ulong start, target_ulong len, int flags)
1909{
1910 PageDesc *p;
1911 target_ulong end;
1912 target_ulong addr;
1913
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001914 if (start + len < start)
1915 /* we've wrapped around */
1916 return -1;
1917
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001918 end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
1919 start = start & TARGET_PAGE_MASK;
1920
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001921 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1922 p = page_find(addr >> TARGET_PAGE_BITS);
1923 if( !p )
1924 return -1;
1925 if( !(p->flags & PAGE_VALID) )
1926 return -1;
1927
1928 if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
1929 return -1;
1930 if (flags & PAGE_WRITE) {
1931 if (!(p->flags & PAGE_WRITE_ORG))
1932 return -1;
1933 /* unprotect the page if it was put read-only because it
1934 contains translated code */
1935 if (!(p->flags & PAGE_WRITE)) {
1936 if (!page_unprotect(addr, 0, NULL))
1937 return -1;
1938 }
1939 return 0;
1940 }
1941 }
1942 return 0;
1943}
1944
1945/* called from signal handler: invalidate the code and unprotect the
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001946 page. Return TRUE if the fault was successfully handled. */
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001947int page_unprotect(target_ulong address, uintptr_t pc, void *puc)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001948{
1949 unsigned int page_index, prot, pindex;
1950 PageDesc *p, *p1;
1951 target_ulong host_start, host_end, addr;
1952
1953 /* Technically this isn't safe inside a signal handler. However we
1954 know this only ever happens in a synchronous SEGV handler, so in
1955 practice it seems to be ok. */
1956 mmap_lock();
1957
1958 host_start = address & qemu_host_page_mask;
1959 page_index = host_start >> TARGET_PAGE_BITS;
1960 p1 = page_find(page_index);
1961 if (!p1) {
1962 mmap_unlock();
1963 return 0;
1964 }
1965 host_end = host_start + qemu_host_page_size;
1966 p = p1;
1967 prot = 0;
1968 for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
1969 prot |= p->flags;
1970 p++;
1971 }
1972 /* if the page was really writable, then we change its
1973 protection back to writable */
1974 if (prot & PAGE_WRITE_ORG) {
1975 pindex = (address - host_start) >> TARGET_PAGE_BITS;
1976 if (!(p1[pindex].flags & PAGE_WRITE)) {
1977 mprotect((void *)g2h(host_start), qemu_host_page_size,
1978 (prot & PAGE_BITS) | PAGE_WRITE);
1979 p1[pindex].flags |= PAGE_WRITE;
1980 /* and since the content will be modified, we must invalidate
1981 the corresponding translated code. */
1982 tb_invalidate_phys_page(address, pc, puc);
1983#ifdef DEBUG_TB_CHECK
1984 tb_invalidate_check(address);
1985#endif
1986 mmap_unlock();
1987 return 1;
1988 }
1989 }
1990 mmap_unlock();
1991 return 0;
1992}
1993
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001994static inline void tlb_set_dirty(CPUOldState *env,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001995 unsigned long addr, target_ulong vaddr)
1996{
1997}
1998#endif /* defined(CONFIG_USER_ONLY) */
1999
2000#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002001
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002002static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002003 ram_addr_t memory, ram_addr_t region_offset);
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002004static void *subpage_init (hwaddr base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002005 ram_addr_t orig_memory, ram_addr_t region_offset);
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002006
2007static void *(*phys_mem_alloc)(size_t size) = qemu_anon_ram_alloc;
2008
2009/*
2010 * Set a custom physical guest memory alloator.
2011 * Accelerators with unusual needs may need this. Hopefully, we can
2012 * get rid of it eventually.
2013 */
2014void phys_mem_set_alloc(void *(*alloc)(size_t))
2015{
2016 phys_mem_alloc = alloc;
2017}
2018
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002019#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
2020 need_subpage) \
2021 do { \
2022 if (addr > start_addr) \
2023 start_addr2 = 0; \
2024 else { \
2025 start_addr2 = start_addr & ~TARGET_PAGE_MASK; \
2026 if (start_addr2 > 0) \
2027 need_subpage = 1; \
2028 } \
2029 \
2030 if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE) \
2031 end_addr2 = TARGET_PAGE_SIZE - 1; \
2032 else { \
2033 end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
2034 if (end_addr2 < TARGET_PAGE_SIZE - 1) \
2035 need_subpage = 1; \
2036 } \
2037 } while (0)
2038
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002039/* register physical memory.
2040 For RAM, 'size' must be a multiple of the target page size.
2041 If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002042 io memory page. The address used when calling the IO function is
2043 the offset from the start of the region, plus region_offset. Both
2044 start_addr and region_offset are rounded down to a page boundary
2045 before calculating this offset. This should not be a problem unless
2046 the low bits of start_addr and region_offset differ. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002047void cpu_register_physical_memory_log(hwaddr start_addr,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002048 ram_addr_t size,
2049 ram_addr_t phys_offset,
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002050 ram_addr_t region_offset,
2051 bool log_dirty)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002052{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002053 hwaddr addr, end_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002054 PhysPageDesc *p;
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002055 CPUOldState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002056 ram_addr_t orig_size = size;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002057 subpage_t *subpage;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002058
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002059 if (kvm_enabled())
2060 kvm_set_phys_mem(start_addr, size, phys_offset);
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002061#ifdef CONFIG_HAX
2062 if (hax_enabled())
2063 hax_set_phys_mem(start_addr, size, phys_offset);
2064#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002065
2066 if (phys_offset == IO_MEM_UNASSIGNED) {
2067 region_offset = start_addr;
2068 }
2069 region_offset &= TARGET_PAGE_MASK;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002070 size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002071 end_addr = start_addr + (hwaddr)size;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002072
2073 addr = start_addr;
2074 do {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002075 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2076 if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
2077 ram_addr_t orig_memory = p->phys_offset;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002078 hwaddr start_addr2, end_addr2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002079 int need_subpage = 0;
2080
2081 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2082 need_subpage);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002083 if (need_subpage) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002084 if (!(orig_memory & IO_MEM_SUBPAGE)) {
2085 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002086 &p->phys_offset, orig_memory,
2087 p->region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002088 } else {
2089 subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
2090 >> IO_MEM_SHIFT];
2091 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002092 subpage_register(subpage, start_addr2, end_addr2, phys_offset,
2093 region_offset);
2094 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002095 } else {
2096 p->phys_offset = phys_offset;
2097 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2098 (phys_offset & IO_MEM_ROMD))
2099 phys_offset += TARGET_PAGE_SIZE;
2100 }
2101 } else {
2102 p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2103 p->phys_offset = phys_offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002104 p->region_offset = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002105 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002106 (phys_offset & IO_MEM_ROMD)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002107 phys_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002108 } else {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002109 hwaddr start_addr2, end_addr2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002110 int need_subpage = 0;
2111
2112 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2113 end_addr2, need_subpage);
2114
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002115 if (need_subpage) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002116 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002117 &p->phys_offset, IO_MEM_UNASSIGNED,
2118 addr & TARGET_PAGE_MASK);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002119 subpage_register(subpage, start_addr2, end_addr2,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002120 phys_offset, region_offset);
2121 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002122 }
2123 }
2124 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002125 region_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002126 addr += TARGET_PAGE_SIZE;
2127 } while (addr != end_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002128
2129 /* since each CPU stores ram addresses in its TLB cache, we must
2130 reset the modified entries */
2131 /* XXX: slow ! */
2132 for(env = first_cpu; env != NULL; env = env->next_cpu) {
2133 tlb_flush(env, 1);
2134 }
2135}
2136
2137/* XXX: temporary until new memory mapping API */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002138ram_addr_t cpu_get_physical_page_desc(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002139{
2140 PhysPageDesc *p;
2141
2142 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2143 if (!p)
2144 return IO_MEM_UNASSIGNED;
2145 return p->phys_offset;
2146}
2147
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002148void qemu_register_coalesced_mmio(hwaddr addr, ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002149{
2150 if (kvm_enabled())
2151 kvm_coalesce_mmio_region(addr, size);
2152}
2153
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002154void qemu_unregister_coalesced_mmio(hwaddr addr, ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002155{
2156 if (kvm_enabled())
2157 kvm_uncoalesce_mmio_region(addr, size);
2158}
2159
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002160void qemu_mutex_lock_ramlist(void)
2161{
2162 qemu_mutex_lock(&ram_list.mutex);
2163}
2164
2165void qemu_mutex_unlock_ramlist(void)
2166{
2167 qemu_mutex_unlock(&ram_list.mutex);
2168}
2169
2170#if defined(__linux__) && !defined(CONFIG_ANDROID)
2171
2172#include <sys/vfs.h>
2173
2174#define HUGETLBFS_MAGIC 0x958458f6
2175
2176static long gethugepagesize(const char *path)
2177{
2178 struct statfs fs;
2179 int ret;
2180
2181 do {
2182 ret = statfs(path, &fs);
2183 } while (ret != 0 && errno == EINTR);
2184
2185 if (ret != 0) {
2186 perror(path);
2187 return 0;
2188 }
2189
2190 if (fs.f_type != HUGETLBFS_MAGIC)
2191 fprintf(stderr, "Warning: path not on HugeTLBFS: %s\n", path);
2192
2193 return fs.f_bsize;
2194}
2195
2196static sigjmp_buf sigjump;
2197
2198static void sigbus_handler(int signal)
2199{
2200 siglongjmp(sigjump, 1);
2201}
2202
2203static void *file_ram_alloc(RAMBlock *block,
2204 ram_addr_t memory,
2205 const char *path)
2206{
2207 char *filename;
2208 char *sanitized_name;
2209 char *c;
2210 void *area;
2211 int fd;
2212 unsigned long hpagesize;
2213
2214 hpagesize = gethugepagesize(path);
2215 if (!hpagesize) {
2216 return NULL;
2217 }
2218
2219 if (memory < hpagesize) {
2220 return NULL;
2221 }
2222
2223 if (kvm_enabled() && !kvm_has_sync_mmu()) {
2224 fprintf(stderr, "host lacks kvm mmu notifiers, -mem-path unsupported\n");
2225 return NULL;
2226 }
2227
2228 /* Make name safe to use with mkstemp by replacing '/' with '_'. */
2229 sanitized_name = g_strdup(block->mr->name);
2230 for (c = sanitized_name; *c != '\0'; c++) {
2231 if (*c == '/')
2232 *c = '_';
2233 }
2234
2235 filename = g_strdup_printf("%s/qemu_back_mem.%s.XXXXXX", path,
2236 sanitized_name);
2237 g_free(sanitized_name);
2238
2239 fd = mkstemp(filename);
2240 if (fd < 0) {
2241 perror("unable to create backing store for hugepages");
2242 g_free(filename);
2243 return NULL;
2244 }
2245 unlink(filename);
2246 g_free(filename);
2247
2248 memory = (memory+hpagesize-1) & ~(hpagesize-1);
2249
2250 /*
2251 * ftruncate is not supported by hugetlbfs in older
2252 * hosts, so don't bother bailing out on errors.
2253 * If anything goes wrong with it under other filesystems,
2254 * mmap will fail.
2255 */
2256 if (ftruncate(fd, memory))
2257 perror("ftruncate");
2258
2259 area = mmap(0, memory, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
2260 if (area == MAP_FAILED) {
2261 perror("file_ram_alloc: can't mmap RAM pages");
2262 close(fd);
2263 return (NULL);
2264 }
2265
2266 if (mem_prealloc) {
2267 int ret, i;
2268 struct sigaction act, oldact;
2269 sigset_t set, oldset;
2270
2271 memset(&act, 0, sizeof(act));
2272 act.sa_handler = &sigbus_handler;
2273 act.sa_flags = 0;
2274
2275 ret = sigaction(SIGBUS, &act, &oldact);
2276 if (ret) {
2277 perror("file_ram_alloc: failed to install signal handler");
2278 exit(1);
2279 }
2280
2281 /* unblock SIGBUS */
2282 sigemptyset(&set);
2283 sigaddset(&set, SIGBUS);
2284 pthread_sigmask(SIG_UNBLOCK, &set, &oldset);
2285
2286 if (sigsetjmp(sigjump, 1)) {
2287 fprintf(stderr, "file_ram_alloc: failed to preallocate pages\n");
2288 exit(1);
2289 }
2290
2291 /* MAP_POPULATE silently ignores failures */
2292 for (i = 0; i < (memory/hpagesize)-1; i++) {
2293 memset(area + (hpagesize*i), 0, 1);
2294 }
2295
2296 ret = sigaction(SIGBUS, &oldact, NULL);
2297 if (ret) {
2298 perror("file_ram_alloc: failed to reinstall signal handler");
2299 exit(1);
2300 }
2301
2302 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
2303 }
2304
2305 block->fd = fd;
2306 return area;
2307}
2308#else
2309static void *file_ram_alloc(RAMBlock *block,
2310 ram_addr_t memory,
2311 const char *path)
2312{
2313 fprintf(stderr, "-mem-path not supported on this host\n");
2314 exit(1);
2315}
2316#endif
2317
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002318static ram_addr_t find_ram_offset(ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002319{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002320 RAMBlock *block, *next_block;
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002321 ram_addr_t offset = RAM_ADDR_MAX, mingap = RAM_ADDR_MAX;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002322
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002323 assert(size != 0); /* it would hand out same offset multiple times */
2324
2325 if (QTAILQ_EMPTY(&ram_list.blocks))
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002326 return 0;
2327
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002328 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
2329 ram_addr_t end, next = RAM_ADDR_MAX;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002330
2331 end = block->offset + block->length;
2332
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002333 QTAILQ_FOREACH(next_block, &ram_list.blocks, next) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002334 if (next_block->offset >= end) {
2335 next = MIN(next, next_block->offset);
2336 }
2337 }
2338 if (next - end >= size && next - end < mingap) {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002339 offset = end;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002340 mingap = next - end;
2341 }
2342 }
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002343
2344 if (offset == RAM_ADDR_MAX) {
2345 fprintf(stderr, "Failed to find gap of requested size: %" PRIu64 "\n",
2346 (uint64_t)size);
2347 abort();
2348 }
2349
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002350 return offset;
2351}
2352
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002353ram_addr_t last_ram_offset(void)
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002354{
2355 RAMBlock *block;
2356 ram_addr_t last = 0;
2357
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002358 QTAILQ_FOREACH(block, &ram_list.blocks, next)
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002359 last = MAX(last, block->offset + block->length);
2360
2361 return last;
2362}
2363
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002364static void qemu_ram_setup_dump(void *addr, ram_addr_t size)
2365{
2366#ifndef CONFIG_ANDROID
2367 int ret;
2368
2369 /* Use MADV_DONTDUMP, if user doesn't want the guest memory in the core */
2370 if (!qemu_opt_get_bool(qemu_get_machine_opts(),
2371 "dump-guest-core", true)) {
2372 ret = qemu_madvise(addr, size, QEMU_MADV_DONTDUMP);
2373 if (ret) {
2374 perror("qemu_madvise");
2375 fprintf(stderr, "madvise doesn't support MADV_DONTDUMP, "
2376 "but dump_guest_core=off specified\n");
2377 }
2378 }
2379#endif // !CONFIG_ANDROID
2380}
2381
2382void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev)
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002383{
2384 RAMBlock *new_block, *block;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002385
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002386 new_block = NULL;
2387 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
2388 if (block->offset == addr) {
2389 new_block = block;
2390 break;
2391 }
2392 }
2393 assert(new_block);
2394 assert(!new_block->idstr[0]);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002395
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002396 if (dev) {
2397 char *id = qdev_get_dev_path(dev);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002398 if (id) {
2399 snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002400 g_free(id);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002401 }
2402 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002403 pstrcat(new_block->idstr, sizeof(new_block->idstr), name);
2404
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002405 /* This assumes the iothread lock is taken here too. */
2406 qemu_mutex_lock_ramlist();
2407 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
2408 if (block != new_block && !strcmp(block->idstr, new_block->idstr)) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002409 fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n",
2410 new_block->idstr);
2411 abort();
2412 }
2413 }
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002414 qemu_mutex_unlock_ramlist();
2415}
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002416
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002417static int memory_try_enable_merging(void *addr, size_t len)
2418{
2419#ifndef CONFIG_ANDROID
2420 if (!qemu_opt_get_bool(qemu_get_machine_opts(), "mem-merge", true)) {
2421 /* disabled by the user */
2422 return 0;
2423 }
2424
2425 return qemu_madvise(addr, len, QEMU_MADV_MERGEABLE);
2426#else // CONFIG_ANDROID
2427 return qemu_madvise(addr, len, QEMU_MADV_MERGEABLE);
2428#endif // CONFIG_ANDROID
2429}
2430
2431ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
2432 ram_addr_t size, void *host)
2433{
2434 RAMBlock *block, *new_block;
2435
2436 size = TARGET_PAGE_ALIGN(size);
2437 new_block = g_malloc0(sizeof(*new_block));
2438 new_block->fd = -1;
2439
2440 /* This assumes the iothread lock is taken here too. */
2441 qemu_mutex_lock_ramlist();
2442 //new_block->mr = mr;
2443 new_block->offset = find_ram_offset(size);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002444 if (host) {
2445 new_block->host = host;
2446 new_block->flags |= RAM_PREALLOC_MASK;
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002447 } else if (xen_enabled()) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002448 if (mem_path) {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002449 fprintf(stderr, "-mem-path not supported with Xen\n");
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002450 exit(1);
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002451 }
2452 //xen_ram_alloc(new_block->offset, size, mr);
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002453#ifdef CONFIG_HAX
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002454 } else if (hax_enabled()) {
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002455 /*
2456 * In HAX, qemu allocates the virtual address, and HAX kernel
2457 * module populates the region with physical memory. Currently
2458 * we don’t populate guest memory on demand, thus we should
2459 * make sure that sufficient amount of memory is available in
2460 * advance.
2461 */
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002462 int ret = hax_populate_ram(
2463 (uint64_t)(uintptr_t)new_block->host,
2464 (uint32_t)size);
2465 if (ret < 0) {
2466 fprintf(stderr, "Hax failed to populate ram\n");
2467 exit(-1);
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002468 }
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002469#endif // CONFIG_HAX
2470 } else {
2471 if (mem_path) {
2472 if (phys_mem_alloc != qemu_anon_ram_alloc) {
2473 /*
2474 * file_ram_alloc() needs to allocate just like
2475 * phys_mem_alloc, but we haven't bothered to provide
2476 * a hook there.
2477 */
2478 fprintf(stderr,
2479 "-mem-path not supported with this accelerator\n");
2480 exit(1);
2481 }
2482 new_block->host = file_ram_alloc(new_block, size, mem_path);
2483 }
2484 if (!new_block->host) {
2485 new_block->host = phys_mem_alloc(size);
2486 if (!new_block->host) {
2487 fprintf(stderr, "Cannot set up guest memory '%s': %s\n",
2488 name, strerror(errno));
2489 exit(1);
2490 }
2491 memory_try_enable_merging(new_block->host, size);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002492 }
2493 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002494 new_block->length = size;
2495
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002496 /* Keep the list sorted from biggest to smallest block. */
2497 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
2498 if (block->length < new_block->length) {
2499 break;
2500 }
2501 }
2502 if (block) {
2503 QTAILQ_INSERT_BEFORE(block, new_block, next);
2504 } else {
2505 QTAILQ_INSERT_TAIL(&ram_list.blocks, new_block, next);
2506 }
2507 ram_list.mru_block = NULL;
2508
2509 ram_list.version++;
2510 qemu_mutex_unlock_ramlist();
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002511
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002512 ram_list.phys_dirty = g_realloc(ram_list.phys_dirty,
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002513 last_ram_offset() >> TARGET_PAGE_BITS);
2514 memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002515 0xff, size >> TARGET_PAGE_BITS);
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002516 //cpu_physical_memory_set_dirty_range(new_block->offset, size, 0xff);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002517
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002518 //qemu_ram_setup_dump(new_block->host, size);
2519 //qemu_madvise(new_block->host, size, QEMU_MADV_HUGEPAGE);
2520 //qemu_madvise(new_block->host, size, QEMU_MADV_DONTFORK);
2521
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002522 if (kvm_enabled())
2523 kvm_setup_guest_memory(new_block->host, size);
2524
2525 return new_block->offset;
2526}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002527
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002528ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
2529{
2530 return qemu_ram_alloc_from_ptr(dev, name, size, NULL);
2531}
2532
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002533void qemu_ram_free_from_ptr(ram_addr_t addr)
2534{
2535 RAMBlock *block;
2536
2537 /* This assumes the iothread lock is taken here too. */
2538 qemu_mutex_lock_ramlist();
2539 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
2540 if (addr == block->offset) {
2541 QTAILQ_REMOVE(&ram_list.blocks, block, next);
2542 ram_list.mru_block = NULL;
2543 ram_list.version++;
2544 g_free(block);
2545 break;
2546 }
2547 }
2548 qemu_mutex_unlock_ramlist();
2549}
2550
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002551void qemu_ram_free(ram_addr_t addr)
2552{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002553 RAMBlock *block;
2554
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002555 /* This assumes the iothread lock is taken here too. */
2556 qemu_mutex_lock_ramlist();
2557 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002558 if (addr == block->offset) {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002559 QTAILQ_REMOVE(&ram_list.blocks, block, next);
2560 ram_list.mru_block = NULL;
2561 ram_list.version++;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002562 if (block->flags & RAM_PREALLOC_MASK) {
2563 ;
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002564 } else if (xen_enabled()) {
2565 //xen_invalidate_map_cache_entry(block->host);
2566#ifndef _WIN32
2567 } else if (block->fd >= 0) {
2568 munmap(block->host, block->length);
2569 close(block->fd);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002570#endif
2571 } else {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002572 qemu_anon_ram_free(block->host, block->length);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002573 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002574 g_free(block);
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002575 break;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002576 }
2577 }
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002578 qemu_mutex_unlock_ramlist();
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002579
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002580}
2581
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002582#ifndef _WIN32
2583void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
2584{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002585 RAMBlock *block;
2586 ram_addr_t offset;
2587 int flags;
2588 void *area, *vaddr;
2589
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002590 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002591 offset = addr - block->offset;
2592 if (offset < block->length) {
2593 vaddr = block->host + offset;
2594 if (block->flags & RAM_PREALLOC_MASK) {
2595 ;
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002596 } else if (xen_enabled()) {
2597 abort();
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002598 } else {
2599 flags = MAP_FIXED;
2600 munmap(vaddr, length);
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002601 if (block->fd >= 0) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002602#ifdef MAP_POPULATE
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002603 flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED :
2604 MAP_PRIVATE;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002605#else
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002606 flags |= MAP_PRIVATE;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002607#endif
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002608 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2609 flags, block->fd, offset);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002610 } else {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002611 /*
2612 * Remap needs to match alloc. Accelerators that
2613 * set phys_mem_alloc never remap. If they did,
2614 * we'd need a remap hook here.
2615 */
2616 assert(phys_mem_alloc == qemu_anon_ram_alloc);
2617
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002618 flags |= MAP_PRIVATE | MAP_ANONYMOUS;
2619 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2620 flags, -1, 0);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002621 }
2622 if (area != vaddr) {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002623 fprintf(stderr, "Could not remap addr: "
2624 RAM_ADDR_FMT "@" RAM_ADDR_FMT "\n",
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002625 length, addr);
2626 exit(1);
2627 }
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002628 memory_try_enable_merging(vaddr, length);
2629 qemu_ram_setup_dump(vaddr, length);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002630 }
2631 return;
2632 }
2633 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002634}
2635#endif /* !_WIN32 */
2636
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002637/* Return a host pointer to ram allocated with qemu_ram_alloc.
2638 With the exception of the softmmu code in this file, this should
2639 only be used for local memory (e.g. video ram) that the device owns,
2640 and knows it isn't going to access beyond the end of the block.
2641
2642 It should not be used for general purpose DMA.
2643 Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
2644 */
2645void *qemu_get_ram_ptr(ram_addr_t addr)
2646{
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002647 RAMBlock *block = qemu_get_ram_block(addr);
2648#if 0
2649 if (xen_enabled()) {
2650 /* We need to check if the requested address is in the RAM
2651 * because we don't want to map the entire memory in QEMU.
2652 * In that case just map until the end of the page.
2653 */
2654 if (block->offset == 0) {
2655 return xen_map_cache(addr, 0, 0);
2656 } else if (block->host == NULL) {
2657 block->host =
2658 xen_map_cache(block->offset, block->length, 1);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002659 }
2660 }
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002661#endif
2662 return block->host + (addr - block->offset);
2663}
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002664
2665/* Return a host pointer to ram allocated with qemu_ram_alloc.
2666 * Same as qemu_get_ram_ptr but avoid reordering ramblocks.
2667 */
2668void *qemu_safe_ram_ptr(ram_addr_t addr)
2669{
2670 RAMBlock *block;
2671
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002672 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002673 if (addr - block->offset < block->length) {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002674 return block->host + (addr - block->offset);
2675 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002676 }
2677
2678 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2679 abort();
2680
2681 return NULL;
2682}
2683
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002684/* Some of the softmmu routines need to translate from a host pointer
2685 (typically a TLB entry) back to a ram offset. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002686int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
2687{
2688 RAMBlock *block;
2689 uint8_t *host = ptr;
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002690#if 0
2691 if (xen_enabled()) {
2692 *ram_addr = xen_ram_addr_from_mapcache(ptr);
2693 return qemu_get_ram_block(*ram_addr)->mr;
2694 }
2695#endif
2696 block = ram_list.mru_block;
2697 if (block && block->host && host - block->host < block->length) {
2698 goto found;
2699 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002700
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002701 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
2702 /* This case append when the block is not mapped. */
2703 if (block->host == NULL) {
2704 continue;
2705 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002706 if (host - block->host < block->length) {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002707 goto found;
2708 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002709 }
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002710
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002711 return -1;
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002712
2713found:
2714 *ram_addr = block->offset + (host - block->host);
2715 return 0;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002716}
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002717
2718/* Some of the softmmu routines need to translate from a host pointer
2719 (typically a TLB entry) back to a ram offset. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002720ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002721{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002722 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002723
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002724 if (qemu_ram_addr_from_host(ptr, &ram_addr)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002725 fprintf(stderr, "Bad ram pointer %p\n", ptr);
2726 abort();
2727 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002728 return ram_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002729}
2730
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002731static uint32_t unassigned_mem_readb(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002732{
2733#ifdef DEBUG_UNASSIGNED
2734 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2735#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002736#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002737 do_unassigned_access(addr, 0, 0, 0, 1);
2738#endif
2739 return 0;
2740}
2741
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002742static uint32_t unassigned_mem_readw(void *opaque, hwaddr addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002743{
2744#ifdef DEBUG_UNASSIGNED
2745 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2746#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002747#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002748 do_unassigned_access(addr, 0, 0, 0, 2);
2749#endif
2750 return 0;
2751}
2752
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002753static uint32_t unassigned_mem_readl(void *opaque, hwaddr addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002754{
2755#ifdef DEBUG_UNASSIGNED
2756 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2757#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002758#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002759 do_unassigned_access(addr, 0, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002760#endif
2761 return 0;
2762}
2763
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002764static void unassigned_mem_writeb(void *opaque, hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002765{
2766#ifdef DEBUG_UNASSIGNED
2767 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2768#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002769#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002770 do_unassigned_access(addr, 1, 0, 0, 1);
2771#endif
2772}
2773
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002774static void unassigned_mem_writew(void *opaque, hwaddr addr, uint32_t val)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002775{
2776#ifdef DEBUG_UNASSIGNED
2777 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2778#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002779#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002780 do_unassigned_access(addr, 1, 0, 0, 2);
2781#endif
2782}
2783
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002784static void unassigned_mem_writel(void *opaque, hwaddr addr, uint32_t val)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002785{
2786#ifdef DEBUG_UNASSIGNED
2787 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2788#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002789#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002790 do_unassigned_access(addr, 1, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002791#endif
2792}
2793
David 'Digit' Turner36411062010-12-22 17:34:53 +01002794static CPUReadMemoryFunc * const unassigned_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002795 unassigned_mem_readb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002796 unassigned_mem_readw,
2797 unassigned_mem_readl,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002798};
2799
David 'Digit' Turner36411062010-12-22 17:34:53 +01002800static CPUWriteMemoryFunc * const unassigned_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002801 unassigned_mem_writeb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002802 unassigned_mem_writew,
2803 unassigned_mem_writel,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002804};
2805
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002806static void notdirty_mem_writeb(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002807 uint32_t val)
2808{
2809 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002810 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002811 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2812#if !defined(CONFIG_USER_ONLY)
2813 tb_invalidate_phys_page_fast(ram_addr, 1);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002814 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002815#endif
2816 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002817 stb_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002818 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002819 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002820 /* we remove the notdirty callback only if the code has been
2821 flushed */
2822 if (dirty_flags == 0xff)
2823 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2824}
2825
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002826static void notdirty_mem_writew(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002827 uint32_t val)
2828{
2829 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002830 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002831 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2832#if !defined(CONFIG_USER_ONLY)
2833 tb_invalidate_phys_page_fast(ram_addr, 2);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002834 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002835#endif
2836 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002837 stw_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002838 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002839 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002840 /* we remove the notdirty callback only if the code has been
2841 flushed */
2842 if (dirty_flags == 0xff)
2843 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2844}
2845
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002846static void notdirty_mem_writel(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002847 uint32_t val)
2848{
2849 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002850 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002851 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2852#if !defined(CONFIG_USER_ONLY)
2853 tb_invalidate_phys_page_fast(ram_addr, 4);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002854 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002855#endif
2856 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002857 stl_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002858 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002859 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002860 /* we remove the notdirty callback only if the code has been
2861 flushed */
2862 if (dirty_flags == 0xff)
2863 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2864}
2865
David 'Digit' Turner36411062010-12-22 17:34:53 +01002866static CPUReadMemoryFunc * const error_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002867 NULL, /* never used */
2868 NULL, /* never used */
2869 NULL, /* never used */
2870};
2871
David 'Digit' Turner36411062010-12-22 17:34:53 +01002872static CPUWriteMemoryFunc * const notdirty_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002873 notdirty_mem_writeb,
2874 notdirty_mem_writew,
2875 notdirty_mem_writel,
2876};
2877
2878/* Generate a debug exception if a watchpoint has been hit. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002879static void check_watchpoint(int offset, int len_mask, int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002880{
David 'Digit' Turner85c62202014-02-16 20:53:40 +01002881 CPUArchState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002882 target_ulong pc, cs_base;
2883 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002884 target_ulong vaddr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002885 CPUWatchpoint *wp;
2886 int cpu_flags;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002887
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002888 if (env->watchpoint_hit) {
2889 /* We re-entered the check after replacing the TB. Now raise
2890 * the debug interrupt so that is will trigger after the
2891 * current instruction. */
2892 cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2893 return;
2894 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002895 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002896 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002897 if ((vaddr == (wp->vaddr & len_mask) ||
2898 (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
2899 wp->flags |= BP_WATCHPOINT_HIT;
2900 if (!env->watchpoint_hit) {
2901 env->watchpoint_hit = wp;
2902 tb = tb_find_pc(env->mem_io_pc);
2903 if (!tb) {
2904 cpu_abort(env, "check_watchpoint: could not find TB for "
2905 "pc=%p", (void *)env->mem_io_pc);
2906 }
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02002907 cpu_restore_state(tb, env, env->mem_io_pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002908 tb_phys_invalidate(tb, -1);
2909 if (wp->flags & BP_STOP_BEFORE_ACCESS) {
2910 env->exception_index = EXCP_DEBUG;
David 'Digit' Turner85c62202014-02-16 20:53:40 +01002911 cpu_loop_exit(env);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002912 } else {
2913 cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
2914 tb_gen_code(env, pc, cs_base, cpu_flags, 1);
David 'Digit' Turner85c62202014-02-16 20:53:40 +01002915 cpu_resume_from_signal(env, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002916 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002917 }
2918 } else {
2919 wp->flags &= ~BP_WATCHPOINT_HIT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002920 }
2921 }
2922}
2923
2924/* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
2925 so these check for a hit then pass through to the normal out-of-line
2926 phys routines. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002927static uint32_t watch_mem_readb(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002928{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002929 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002930 return ldub_phys(addr);
2931}
2932
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002933static uint32_t watch_mem_readw(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002934{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002935 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002936 return lduw_phys(addr);
2937}
2938
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002939static uint32_t watch_mem_readl(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002940{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002941 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002942 return ldl_phys(addr);
2943}
2944
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002945static void watch_mem_writeb(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002946 uint32_t val)
2947{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002948 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002949 stb_phys(addr, val);
2950}
2951
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002952static void watch_mem_writew(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002953 uint32_t val)
2954{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002955 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002956 stw_phys(addr, val);
2957}
2958
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002959static void watch_mem_writel(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002960 uint32_t val)
2961{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002962 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002963 stl_phys(addr, val);
2964}
2965
David 'Digit' Turner36411062010-12-22 17:34:53 +01002966static CPUReadMemoryFunc * const watch_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002967 watch_mem_readb,
2968 watch_mem_readw,
2969 watch_mem_readl,
2970};
2971
David 'Digit' Turner36411062010-12-22 17:34:53 +01002972static CPUWriteMemoryFunc * const watch_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002973 watch_mem_writeb,
2974 watch_mem_writew,
2975 watch_mem_writel,
2976};
2977
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002978static inline uint32_t subpage_readlen (subpage_t *mmio, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002979 unsigned int len)
2980{
2981 uint32_t ret;
2982 unsigned int idx;
2983
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002984 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002985#if defined(DEBUG_SUBPAGE)
2986 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
2987 mmio, len, addr, idx);
2988#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002989 ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len],
2990 addr + mmio->region_offset[idx][0][len]);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002991
2992 return ret;
2993}
2994
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002995static inline void subpage_writelen (subpage_t *mmio, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002996 uint32_t value, unsigned int len)
2997{
2998 unsigned int idx;
2999
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003000 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003001#if defined(DEBUG_SUBPAGE)
3002 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
3003 mmio, len, addr, idx, value);
3004#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003005 (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len],
3006 addr + mmio->region_offset[idx][1][len],
3007 value);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003008}
3009
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003010static uint32_t subpage_readb (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003011{
3012#if defined(DEBUG_SUBPAGE)
3013 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
3014#endif
3015
3016 return subpage_readlen(opaque, addr, 0);
3017}
3018
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003019static void subpage_writeb (void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003020 uint32_t value)
3021{
3022#if defined(DEBUG_SUBPAGE)
3023 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
3024#endif
3025 subpage_writelen(opaque, addr, value, 0);
3026}
3027
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003028static uint32_t subpage_readw (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003029{
3030#if defined(DEBUG_SUBPAGE)
3031 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
3032#endif
3033
3034 return subpage_readlen(opaque, addr, 1);
3035}
3036
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003037static void subpage_writew (void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003038 uint32_t value)
3039{
3040#if defined(DEBUG_SUBPAGE)
3041 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
3042#endif
3043 subpage_writelen(opaque, addr, value, 1);
3044}
3045
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003046static uint32_t subpage_readl (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003047{
3048#if defined(DEBUG_SUBPAGE)
3049 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
3050#endif
3051
3052 return subpage_readlen(opaque, addr, 2);
3053}
3054
3055static void subpage_writel (void *opaque,
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003056 hwaddr addr, uint32_t value)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003057{
3058#if defined(DEBUG_SUBPAGE)
3059 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
3060#endif
3061 subpage_writelen(opaque, addr, value, 2);
3062}
3063
David 'Digit' Turner36411062010-12-22 17:34:53 +01003064static CPUReadMemoryFunc * const subpage_read[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003065 &subpage_readb,
3066 &subpage_readw,
3067 &subpage_readl,
3068};
3069
David 'Digit' Turner36411062010-12-22 17:34:53 +01003070static CPUWriteMemoryFunc * const subpage_write[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003071 &subpage_writeb,
3072 &subpage_writew,
3073 &subpage_writel,
3074};
3075
3076static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003077 ram_addr_t memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003078{
3079 int idx, eidx;
3080 unsigned int i;
3081
3082 if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
3083 return -1;
3084 idx = SUBPAGE_IDX(start);
3085 eidx = SUBPAGE_IDX(end);
3086#if defined(DEBUG_SUBPAGE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003087 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 -08003088 mmio, start, end, idx, eidx, memory);
3089#endif
3090 memory >>= IO_MEM_SHIFT;
3091 for (; idx <= eidx; idx++) {
3092 for (i = 0; i < 4; i++) {
3093 if (io_mem_read[memory][i]) {
3094 mmio->mem_read[idx][i] = &io_mem_read[memory][i];
3095 mmio->opaque[idx][0][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003096 mmio->region_offset[idx][0][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003097 }
3098 if (io_mem_write[memory][i]) {
3099 mmio->mem_write[idx][i] = &io_mem_write[memory][i];
3100 mmio->opaque[idx][1][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003101 mmio->region_offset[idx][1][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003102 }
3103 }
3104 }
3105
3106 return 0;
3107}
3108
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003109static void *subpage_init (hwaddr base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003110 ram_addr_t orig_memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003111{
3112 subpage_t *mmio;
3113 int subpage_memory;
3114
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01003115 mmio = g_malloc0(sizeof(subpage_t));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003116
3117 mmio->base = base;
3118 subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003119#if defined(DEBUG_SUBPAGE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003120 printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
3121 mmio, base, TARGET_PAGE_SIZE, subpage_memory);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003122#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003123 *phys = subpage_memory | IO_MEM_SUBPAGE;
3124 subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
3125 region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003126
3127 return mmio;
3128}
3129
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003130static int get_free_io_mem_idx(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003131{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003132 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003133
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003134 for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
3135 if (!io_mem_used[i]) {
3136 io_mem_used[i] = 1;
3137 return i;
3138 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003139 fprintf(stderr, "RAN out out io_mem_idx, max %d !\n", IO_MEM_NB_ENTRIES);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003140 return -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003141}
3142
3143/* mem_read and mem_write are arrays of functions containing the
3144 function to access byte (index 0), word (index 1) and dword (index
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003145 2). Functions can be omitted with a NULL function pointer.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003146 If io_index is non zero, the corresponding io zone is
3147 modified. If it is zero, a new io zone is allocated. The return
3148 value can be used with cpu_register_physical_memory(). (-1) is
3149 returned if error. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003150static int cpu_register_io_memory_fixed(int io_index,
David 'Digit' Turner36411062010-12-22 17:34:53 +01003151 CPUReadMemoryFunc * const *mem_read,
3152 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003153 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003154{
3155 int i, subwidth = 0;
3156
3157 if (io_index <= 0) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003158 io_index = get_free_io_mem_idx();
3159 if (io_index == -1)
3160 return io_index;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003161 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003162 io_index >>= IO_MEM_SHIFT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003163 if (io_index >= IO_MEM_NB_ENTRIES)
3164 return -1;
3165 }
3166
3167 for(i = 0;i < 3; i++) {
3168 if (!mem_read[i] || !mem_write[i])
3169 subwidth = IO_MEM_SUBWIDTH;
3170 io_mem_read[io_index][i] = mem_read[i];
3171 io_mem_write[io_index][i] = mem_write[i];
3172 }
3173 io_mem_opaque[io_index] = opaque;
3174 return (io_index << IO_MEM_SHIFT) | subwidth;
3175}
3176
David 'Digit' Turner36411062010-12-22 17:34:53 +01003177int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
3178 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003179 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003180{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003181 return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003182}
3183
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003184void cpu_unregister_io_memory(int io_table_address)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003185{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003186 int i;
3187 int io_index = io_table_address >> IO_MEM_SHIFT;
3188
3189 for (i=0;i < 3; i++) {
3190 io_mem_read[io_index][i] = unassigned_mem_read[i];
3191 io_mem_write[io_index][i] = unassigned_mem_write[i];
3192 }
3193 io_mem_opaque[io_index] = NULL;
3194 io_mem_used[io_index] = 0;
3195}
3196
3197static void io_mem_init(void)
3198{
3199 int i;
3200
3201 cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read, unassigned_mem_write, NULL);
3202 cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read, unassigned_mem_write, NULL);
3203 cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read, notdirty_mem_write, NULL);
3204 for (i=0; i<5; i++)
3205 io_mem_used[i] = 1;
3206
3207 io_mem_watch = cpu_register_io_memory(watch_mem_read,
3208 watch_mem_write, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003209}
3210
3211#endif /* !defined(CONFIG_USER_ONLY) */
3212
3213/* physical memory access (slow version, mainly for debug) */
3214#if defined(CONFIG_USER_ONLY)
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003215void cpu_physical_memory_rw(hwaddr addr, void *buf,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003216 int len, int is_write)
3217{
3218 int l, flags;
3219 target_ulong page;
3220 void * p;
3221
3222 while (len > 0) {
3223 page = addr & TARGET_PAGE_MASK;
3224 l = (page + TARGET_PAGE_SIZE) - addr;
3225 if (l > len)
3226 l = len;
3227 flags = page_get_flags(page);
3228 if (!(flags & PAGE_VALID))
3229 return;
3230 if (is_write) {
3231 if (!(flags & PAGE_WRITE))
3232 return;
3233 /* XXX: this code should not depend on lock_user */
3234 if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
3235 /* FIXME - should this return an error rather than just fail? */
3236 return;
3237 memcpy(p, buf, l);
3238 unlock_user(p, addr, l);
3239 } else {
3240 if (!(flags & PAGE_READ))
3241 return;
3242 /* XXX: this code should not depend on lock_user */
3243 if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
3244 /* FIXME - should this return an error rather than just fail? */
3245 return;
3246 memcpy(buf, p, l);
3247 unlock_user(p, addr, 0);
3248 }
3249 len -= l;
3250 buf += l;
3251 addr += l;
3252 }
3253}
3254
3255#else
Pete Delaneyd09d7662013-03-28 19:53:13 -07003256
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003257static void invalidate_and_set_dirty(hwaddr addr,
3258 hwaddr length)
Pete Delaneyd09d7662013-03-28 19:53:13 -07003259{
3260 if (!cpu_physical_memory_is_dirty(addr)) {
3261 /* invalidate code */
3262 tb_invalidate_phys_page_range(addr, addr + length, 0);
3263 /* set dirty bit */
3264 cpu_physical_memory_set_dirty_flags(addr, (0xff & ~CODE_DIRTY_FLAG));
3265 }
3266}
3267
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003268void cpu_physical_memory_rw(hwaddr addr, void *buf,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003269 int len, int is_write)
3270{
3271 int l, io_index;
3272 uint8_t *ptr;
3273 uint32_t val;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003274 hwaddr page;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003275 unsigned long pd;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003276 uint8_t* buf8 = (uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003277 PhysPageDesc *p;
3278
3279 while (len > 0) {
3280 page = addr & TARGET_PAGE_MASK;
3281 l = (page + TARGET_PAGE_SIZE) - addr;
3282 if (l > len)
3283 l = len;
3284 p = phys_page_find(page >> TARGET_PAGE_BITS);
3285 if (!p) {
3286 pd = IO_MEM_UNASSIGNED;
3287 } else {
3288 pd = p->phys_offset;
3289 }
3290
3291 if (is_write) {
3292 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003293 hwaddr addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003294 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003295 if (p)
3296 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003297 /* XXX: could force cpu_single_env to NULL to avoid
3298 potential bugs */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003299 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003300 /* 32 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003301 val = ldl_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003302 io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003303 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003304 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003305 /* 16 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003306 val = lduw_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003307 io_mem_write[io_index][1](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003308 l = 2;
3309 } else {
3310 /* 8 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003311 val = ldub_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003312 io_mem_write[io_index][0](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003313 l = 1;
3314 }
3315 } else {
3316 unsigned long addr1;
3317 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3318 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003319 ptr = qemu_get_ram_ptr(addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003320 memcpy(ptr, buf8, l);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003321 invalidate_and_set_dirty(addr1, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003322 }
3323 } else {
3324 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3325 !(pd & IO_MEM_ROMD)) {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003326 hwaddr addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003327 /* I/O case */
3328 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003329 if (p)
3330 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3331 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003332 /* 32 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003333 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003334 stl_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003335 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003336 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003337 /* 16 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003338 val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003339 stw_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003340 l = 2;
3341 } else {
3342 /* 8 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003343 val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003344 stb_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003345 l = 1;
3346 }
3347 } else {
3348 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003349 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003350 (addr & ~TARGET_PAGE_MASK);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003351 memcpy(buf8, ptr, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003352 }
3353 }
3354 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003355 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003356 addr += l;
3357 }
3358}
3359
3360/* used for ROM loading : can write in RAM and ROM */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003361void cpu_physical_memory_write_rom(hwaddr addr,
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003362 const void *buf, int len)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003363{
3364 int l;
3365 uint8_t *ptr;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003366 hwaddr page;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003367 unsigned long pd;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003368 const uint8_t* buf8 = (const uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003369 PhysPageDesc *p;
3370
3371 while (len > 0) {
3372 page = addr & TARGET_PAGE_MASK;
3373 l = (page + TARGET_PAGE_SIZE) - addr;
3374 if (l > len)
3375 l = len;
3376 p = phys_page_find(page >> TARGET_PAGE_BITS);
3377 if (!p) {
3378 pd = IO_MEM_UNASSIGNED;
3379 } else {
3380 pd = p->phys_offset;
3381 }
3382
3383 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
3384 (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
3385 !(pd & IO_MEM_ROMD)) {
3386 /* do nothing */
3387 } else {
3388 unsigned long addr1;
3389 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3390 /* ROM/RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003391 ptr = qemu_get_ram_ptr(addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003392 memcpy(ptr, buf8, l);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003393 invalidate_and_set_dirty(addr1, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003394 }
3395 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003396 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003397 addr += l;
3398 }
3399}
3400
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003401typedef struct {
3402 void *buffer;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003403 hwaddr addr;
3404 hwaddr len;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003405} BounceBuffer;
3406
3407static BounceBuffer bounce;
3408
3409typedef struct MapClient {
3410 void *opaque;
3411 void (*callback)(void *opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003412 QLIST_ENTRY(MapClient) link;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003413} MapClient;
3414
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003415static QLIST_HEAD(map_client_list, MapClient) map_client_list
3416 = QLIST_HEAD_INITIALIZER(map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003417
3418void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
3419{
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01003420 MapClient *client = g_malloc(sizeof(*client));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003421
3422 client->opaque = opaque;
3423 client->callback = callback;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003424 QLIST_INSERT_HEAD(&map_client_list, client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003425 return client;
3426}
3427
3428void cpu_unregister_map_client(void *_client)
3429{
3430 MapClient *client = (MapClient *)_client;
3431
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003432 QLIST_REMOVE(client, link);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01003433 g_free(client);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003434}
3435
3436static void cpu_notify_map_clients(void)
3437{
3438 MapClient *client;
3439
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003440 while (!QLIST_EMPTY(&map_client_list)) {
3441 client = QLIST_FIRST(&map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003442 client->callback(client->opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003443 QLIST_REMOVE(client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003444 }
3445}
3446
3447/* Map a physical memory region into a host virtual address.
3448 * May map a subset of the requested range, given by and returned in *plen.
3449 * May return NULL if resources needed to perform the mapping are exhausted.
3450 * Use only for reads OR writes - not for read-modify-write operations.
3451 * Use cpu_register_map_client() to know when retrying the map operation is
3452 * likely to succeed.
3453 */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003454void *cpu_physical_memory_map(hwaddr addr,
3455 hwaddr *plen,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003456 int is_write)
3457{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003458 hwaddr len = *plen;
3459 hwaddr done = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003460 int l;
3461 uint8_t *ret = NULL;
3462 uint8_t *ptr;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003463 hwaddr page;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003464 unsigned long pd;
3465 PhysPageDesc *p;
3466 unsigned long addr1;
3467
3468 while (len > 0) {
3469 page = addr & TARGET_PAGE_MASK;
3470 l = (page + TARGET_PAGE_SIZE) - addr;
3471 if (l > len)
3472 l = len;
3473 p = phys_page_find(page >> TARGET_PAGE_BITS);
3474 if (!p) {
3475 pd = IO_MEM_UNASSIGNED;
3476 } else {
3477 pd = p->phys_offset;
3478 }
3479
3480 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3481 if (done || bounce.buffer) {
3482 break;
3483 }
3484 bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
3485 bounce.addr = addr;
3486 bounce.len = l;
3487 if (!is_write) {
3488 cpu_physical_memory_rw(addr, bounce.buffer, l, 0);
3489 }
3490 ptr = bounce.buffer;
3491 } else {
3492 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3493 ptr = qemu_get_ram_ptr(addr1);
3494 }
3495 if (!done) {
3496 ret = ptr;
3497 } else if (ret + done != ptr) {
3498 break;
3499 }
3500
3501 len -= l;
3502 addr += l;
3503 done += l;
3504 }
3505 *plen = done;
3506 return ret;
3507}
3508
3509/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
3510 * Will also mark the memory as dirty if is_write == 1. access_len gives
3511 * the amount of memory that was actually read or written by the caller.
3512 */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003513void cpu_physical_memory_unmap(void *buffer, hwaddr len,
3514 int is_write, hwaddr access_len)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003515{
3516 if (buffer != bounce.buffer) {
3517 if (is_write) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003518 ram_addr_t addr1 = qemu_ram_addr_from_host_nofail(buffer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003519 while (access_len) {
3520 unsigned l;
3521 l = TARGET_PAGE_SIZE;
3522 if (l > access_len)
3523 l = access_len;
Pete Delaneyd09d7662013-03-28 19:53:13 -07003524 invalidate_and_set_dirty(addr1, l);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003525 addr1 += l;
3526 access_len -= l;
3527 }
3528 }
3529 return;
3530 }
3531 if (is_write) {
3532 cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
3533 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003534 qemu_vfree(bounce.buffer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003535 bounce.buffer = NULL;
3536 cpu_notify_map_clients();
3537}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003538
3539/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003540uint32_t ldl_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003541{
3542 int io_index;
3543 uint8_t *ptr;
3544 uint32_t val;
3545 unsigned long pd;
3546 PhysPageDesc *p;
3547
3548 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3549 if (!p) {
3550 pd = IO_MEM_UNASSIGNED;
3551 } else {
3552 pd = p->phys_offset;
3553 }
3554
3555 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3556 !(pd & IO_MEM_ROMD)) {
3557 /* I/O case */
3558 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003559 if (p)
3560 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003561 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3562 } else {
3563 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003564 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003565 (addr & ~TARGET_PAGE_MASK);
3566 val = ldl_p(ptr);
3567 }
3568 return val;
3569}
3570
3571/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003572uint64_t ldq_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003573{
3574 int io_index;
3575 uint8_t *ptr;
3576 uint64_t val;
3577 unsigned long pd;
3578 PhysPageDesc *p;
3579
3580 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3581 if (!p) {
3582 pd = IO_MEM_UNASSIGNED;
3583 } else {
3584 pd = p->phys_offset;
3585 }
3586
3587 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3588 !(pd & IO_MEM_ROMD)) {
3589 /* I/O case */
3590 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003591 if (p)
3592 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003593#ifdef TARGET_WORDS_BIGENDIAN
3594 val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
3595 val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
3596#else
3597 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3598 val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
3599#endif
3600 } else {
3601 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003602 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003603 (addr & ~TARGET_PAGE_MASK);
3604 val = ldq_p(ptr);
3605 }
3606 return val;
3607}
3608
3609/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003610uint32_t ldub_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003611{
3612 uint8_t val;
3613 cpu_physical_memory_read(addr, &val, 1);
3614 return val;
3615}
3616
3617/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003618uint32_t lduw_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003619{
3620 uint16_t val;
3621 cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
3622 return tswap16(val);
3623}
3624
3625/* warning: addr must be aligned. The ram page is not masked as dirty
3626 and the code inside is not invalidated. It is useful if the dirty
3627 bits are used to track modified PTEs */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003628void stl_phys_notdirty(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003629{
3630 int io_index;
3631 uint8_t *ptr;
3632 unsigned long pd;
3633 PhysPageDesc *p;
3634
3635 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3636 if (!p) {
3637 pd = IO_MEM_UNASSIGNED;
3638 } else {
3639 pd = p->phys_offset;
3640 }
3641
3642 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3643 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003644 if (p)
3645 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003646 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3647 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003648 unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3649 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003650 stl_p(ptr, val);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003651
3652 if (unlikely(in_migration)) {
3653 if (!cpu_physical_memory_is_dirty(addr1)) {
3654 /* invalidate code */
3655 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3656 /* set dirty bit */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003657 cpu_physical_memory_set_dirty_flags(
3658 addr1, (0xff & ~CODE_DIRTY_FLAG));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003659 }
3660 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003661 }
3662}
3663
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003664void stq_phys_notdirty(hwaddr addr, uint64_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003665{
3666 int io_index;
3667 uint8_t *ptr;
3668 unsigned long pd;
3669 PhysPageDesc *p;
3670
3671 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3672 if (!p) {
3673 pd = IO_MEM_UNASSIGNED;
3674 } else {
3675 pd = p->phys_offset;
3676 }
3677
3678 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3679 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003680 if (p)
3681 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003682#ifdef TARGET_WORDS_BIGENDIAN
3683 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
3684 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
3685#else
3686 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3687 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
3688#endif
3689 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003690 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003691 (addr & ~TARGET_PAGE_MASK);
3692 stq_p(ptr, val);
3693 }
3694}
3695
3696/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003697void stl_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003698{
3699 int io_index;
3700 uint8_t *ptr;
3701 unsigned long pd;
3702 PhysPageDesc *p;
3703
3704 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3705 if (!p) {
3706 pd = IO_MEM_UNASSIGNED;
3707 } else {
3708 pd = p->phys_offset;
3709 }
3710
3711 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3712 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003713 if (p)
3714 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003715 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3716 } else {
3717 unsigned long addr1;
3718 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3719 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003720 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003721 stl_p(ptr, val);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003722 invalidate_and_set_dirty(addr1, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003723 }
3724}
3725
3726/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003727void stb_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003728{
3729 uint8_t v = val;
3730 cpu_physical_memory_write(addr, &v, 1);
3731}
3732
3733/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003734void stw_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003735{
3736 uint16_t v = tswap16(val);
3737 cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
3738}
3739
3740/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003741void stq_phys(hwaddr addr, uint64_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003742{
3743 val = tswap64(val);
3744 cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
3745}
3746
3747#endif
3748
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003749/* virtual memory access for debug (includes writing to ROM) */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003750int cpu_memory_rw_debug(CPUOldState *env, target_ulong addr,
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003751 void *buf, int len, int is_write)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003752{
3753 int l;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003754 hwaddr phys_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003755 target_ulong page;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003756 uint8_t* buf8 = (uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003757
3758 while (len > 0) {
3759 page = addr & TARGET_PAGE_MASK;
3760 phys_addr = cpu_get_phys_page_debug(env, page);
3761 /* if no physical page mapped, return an error */
3762 if (phys_addr == -1)
3763 return -1;
3764 l = (page + TARGET_PAGE_SIZE) - addr;
3765 if (l > len)
3766 l = len;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003767 phys_addr += (addr & ~TARGET_PAGE_MASK);
3768#if !defined(CONFIG_USER_ONLY)
3769 if (is_write)
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003770 cpu_physical_memory_write_rom(phys_addr, buf8, l);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003771 else
3772#endif
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003773 cpu_physical_memory_rw(phys_addr, buf8, l, is_write);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003774 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003775 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003776 addr += l;
3777 }
3778 return 0;
3779}
3780
3781/* in deterministic execution mode, instructions doing device I/Os
3782 must be at the end of the TB */
David 'Digit' Turner85c62202014-02-16 20:53:40 +01003783void cpu_io_recompile(CPUArchState *env, uintptr_t retaddr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003784{
3785 TranslationBlock *tb;
3786 uint32_t n, cflags;
3787 target_ulong pc, cs_base;
3788 uint64_t flags;
3789
David 'Digit' Turner85c62202014-02-16 20:53:40 +01003790 tb = tb_find_pc(retaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003791 if (!tb) {
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02003792 cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p",
David 'Digit' Turner85c62202014-02-16 20:53:40 +01003793 (void*)retaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003794 }
3795 n = env->icount_decr.u16.low + tb->icount;
David 'Digit' Turner85c62202014-02-16 20:53:40 +01003796 cpu_restore_state(tb, env, retaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003797 /* Calculate how many instructions had been executed before the fault
3798 occurred. */
3799 n = n - env->icount_decr.u16.low;
3800 /* Generate a new TB ending on the I/O insn. */
3801 n++;
3802 /* On MIPS and SH, delay slot instructions can only be restarted if
3803 they were already the first instruction in the TB. If this is not
3804 the first instruction in a TB then re-execute the preceding
3805 branch. */
3806#if defined(TARGET_MIPS)
3807 if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) {
3808 env->active_tc.PC -= 4;
3809 env->icount_decr.u16.low++;
3810 env->hflags &= ~MIPS_HFLAG_BMASK;
3811 }
3812#elif defined(TARGET_SH4)
3813 if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
3814 && n > 1) {
3815 env->pc -= 2;
3816 env->icount_decr.u16.low++;
3817 env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
3818 }
3819#endif
3820 /* This should never happen. */
3821 if (n > CF_COUNT_MASK)
3822 cpu_abort(env, "TB too big during recompile");
3823
3824 cflags = n | CF_LAST_IO;
3825 pc = tb->pc;
3826 cs_base = tb->cs_base;
3827 flags = tb->flags;
3828 tb_phys_invalidate(tb, -1);
3829 /* FIXME: In theory this could raise an exception. In practice
3830 we have already translated the block once so it's probably ok. */
3831 tb_gen_code(env, pc, cs_base, flags, cflags);
3832 /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
3833 the first in the TB) then we end up generating a whole new TB and
3834 repeating the fault, which is horribly inefficient.
3835 Better would be to execute just this insn uncached, or generate a
3836 second new TB. */
3837 cpu_resume_from_signal(env, NULL);
3838}
3839
David 'Digit' Turner36411062010-12-22 17:34:53 +01003840#if !defined(CONFIG_USER_ONLY)
3841
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003842void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003843{
3844 int i, target_code_size, max_target_code_size;
3845 int direct_jmp_count, direct_jmp2_count, cross_page;
3846 TranslationBlock *tb;
3847
3848 target_code_size = 0;
3849 max_target_code_size = 0;
3850 cross_page = 0;
3851 direct_jmp_count = 0;
3852 direct_jmp2_count = 0;
David 'Digit' Turner13487772014-02-17 21:16:46 +01003853 for(i = 0; i < tcg_ctx.tb_ctx.nb_tbs; i++) {
3854 tb = &tcg_ctx.tb_ctx.tbs[i];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003855 target_code_size += tb->size;
3856 if (tb->size > max_target_code_size)
3857 max_target_code_size = tb->size;
3858 if (tb->page_addr[1] != -1)
3859 cross_page++;
3860 if (tb->tb_next_offset[0] != 0xffff) {
3861 direct_jmp_count++;
3862 if (tb->tb_next_offset[1] != 0xffff) {
3863 direct_jmp2_count++;
3864 }
3865 }
3866 }
3867 /* XXX: avoid using doubles ? */
3868 cpu_fprintf(f, "Translation buffer state:\n");
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003869 cpu_fprintf(f, "gen code size %td/%ld\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003870 code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02003871 cpu_fprintf(f, "TB count %d/%d\n",
David 'Digit' Turner13487772014-02-17 21:16:46 +01003872 tcg_ctx.tb_ctx.nb_tbs, code_gen_max_blocks);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003873 cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
David 'Digit' Turner13487772014-02-17 21:16:46 +01003874 tcg_ctx.tb_ctx.nb_tbs ? target_code_size / tcg_ctx.tb_ctx.nb_tbs : 0,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003875 max_target_code_size);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003876 cpu_fprintf(f, "TB avg host size %td bytes (expansion ratio: %0.1f)\n",
David 'Digit' Turner13487772014-02-17 21:16:46 +01003877 tcg_ctx.tb_ctx.nb_tbs ? (code_gen_ptr - code_gen_buffer) / tcg_ctx.tb_ctx.nb_tbs : 0,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003878 target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
3879 cpu_fprintf(f, "cross page TB count %d (%d%%)\n",
3880 cross_page,
David 'Digit' Turner13487772014-02-17 21:16:46 +01003881 tcg_ctx.tb_ctx.nb_tbs ? (cross_page * 100) / tcg_ctx.tb_ctx.nb_tbs : 0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003882 cpu_fprintf(f, "direct jump count %d (%d%%) (2 jumps=%d %d%%)\n",
3883 direct_jmp_count,
David 'Digit' Turner13487772014-02-17 21:16:46 +01003884 tcg_ctx.tb_ctx.nb_tbs ? (direct_jmp_count * 100) / tcg_ctx.tb_ctx.nb_tbs : 0,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003885 direct_jmp2_count,
David 'Digit' Turner13487772014-02-17 21:16:46 +01003886 tcg_ctx.tb_ctx.nb_tbs ? (direct_jmp2_count * 100) / tcg_ctx.tb_ctx.nb_tbs : 0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003887 cpu_fprintf(f, "\nStatistics:\n");
David 'Digit' Turner13487772014-02-17 21:16:46 +01003888 cpu_fprintf(f, "TB flush count %d\n", tcg_ctx.tb_ctx.tb_flush_count);
3889 cpu_fprintf(f, "TB invalidate count %d\n", tcg_ctx.tb_ctx.tb_phys_invalidate_count);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003890 cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count);
3891 tcg_dump_info(f, cpu_fprintf);
3892}
3893
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003894#endif