blob: d204134ecdff3486e0fc43e016125803c73d624d [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
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070062static TranslationBlock *tbs;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080063int code_gen_max_blocks;
64TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070065static int nb_tbs;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080066/* any access to the tbs or the page table must use this lock */
67spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
68
69#if defined(__arm__) || defined(__sparc_v9__)
70/* The prologue must be reachable with a direct jump. ARM and Sparc64
71 have limited branch ranges (possibly also PPC) so place it in a
72 section close to code segment. */
73#define code_gen_section \
74 __attribute__((__section__(".gen_code"))) \
75 __attribute__((aligned (32)))
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070076#elif defined(_WIN32)
77/* Maximum alignment for Win32 is 16. */
78#define code_gen_section \
79 __attribute__((aligned (16)))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080080#else
81#define code_gen_section \
82 __attribute__((aligned (32)))
83#endif
84
85uint8_t code_gen_prologue[1024] code_gen_section;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070086static uint8_t *code_gen_buffer;
87static unsigned long code_gen_buffer_size;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080088/* threshold to flush the translated code buffer */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070089static unsigned long code_gen_buffer_max_size;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080090uint8_t *code_gen_ptr;
91
92#if !defined(CONFIG_USER_ONLY)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080093int phys_ram_fd;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070094static int in_migration;
95
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +010096RAMList ram_list = { .blocks = QTAILQ_HEAD_INITIALIZER(ram_list.blocks) };
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080097#endif
98
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +010099CPUArchState *first_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800100/* current CPU in the current thread. It is only valid inside
101 cpu_exec() */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100102CPUArchState *cpu_single_env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800103/* 0 = Do not count executed instructions.
104 1 = Precise instruction counting.
105 2 = Adaptive rate instruction counting. */
106int use_icount = 0;
107/* Current instruction counter. While executing translated code this may
108 include some instructions that have not yet been executed. */
109int64_t qemu_icount;
110
111typedef struct PageDesc {
112 /* list of TBs intersecting this ram page */
113 TranslationBlock *first_tb;
114 /* in order to optimize self modifying code, we count the number
115 of lookups we do to a given page to use a bitmap */
116 unsigned int code_write_count;
117 uint8_t *code_bitmap;
118#if defined(CONFIG_USER_ONLY)
119 unsigned long flags;
120#endif
121} PageDesc;
122
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800123#define L2_BITS 10
124#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
125/* XXX: this is a temporary hack for alpha target.
126 * In the future, this is to be replaced by a multi-level table
127 * to actually be able to handle the complete 64 bits address space.
128 */
129#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
130#else
131#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
132#endif
133
134#define L1_SIZE (1 << L1_BITS)
135#define L2_SIZE (1 << L2_BITS)
136
David 'Digit' Turnerf0729c72014-01-13 16:10:10 +0100137uintptr_t qemu_real_host_page_size;
David 'Digit' Turnerf0729c72014-01-13 16:10:10 +0100138uintptr_t qemu_host_page_size;
139uintptr_t qemu_host_page_mask;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800140
141/* XXX: for system emulation, it could just be an array */
142static PageDesc *l1_map[L1_SIZE];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700143static PhysPageDesc **l1_phys_map;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800144
145#if !defined(CONFIG_USER_ONLY)
146static void io_mem_init(void);
147
148/* io memory support */
149CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
150CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
151void *io_mem_opaque[IO_MEM_NB_ENTRIES];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700152static char io_mem_used[IO_MEM_NB_ENTRIES];
David 'Digit' Turner3dc53fc2014-01-17 01:23:40 +0100153int io_mem_watch;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800154#endif
155
156/* log support */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700157#ifdef WIN32
158static const char *logfilename = "qemu.log";
159#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700160static const char *logfilename = "/tmp/qemu.log";
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700161#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800162FILE *logfile;
163int loglevel;
164static int log_append = 0;
165
166/* statistics */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800167static int tb_flush_count;
168static int tb_phys_invalidate_count;
169
170#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
171typedef struct subpage_t {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100172 hwaddr base;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800173 CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE][4];
174 CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE][4];
175 void *opaque[TARGET_PAGE_SIZE][2][4];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700176 ram_addr_t region_offset[TARGET_PAGE_SIZE][2][4];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800177} subpage_t;
178
179#ifdef _WIN32
180static void map_exec(void *addr, long size)
181{
182 DWORD old_protect;
183 VirtualProtect(addr, size,
184 PAGE_EXECUTE_READWRITE, &old_protect);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200185
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800186}
187#else
188static void map_exec(void *addr, long size)
189{
190 unsigned long start, end, page_size;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200191
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800192 page_size = getpagesize();
193 start = (unsigned long)addr;
194 start &= ~(page_size - 1);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200195
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800196 end = (unsigned long)addr + size;
197 end += page_size - 1;
198 end &= ~(page_size - 1);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200199
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800200 mprotect((void *)start, end - start,
201 PROT_READ | PROT_WRITE | PROT_EXEC);
202}
203#endif
204
205static void page_init(void)
206{
207 /* NOTE: we can always suppose that qemu_host_page_size >=
208 TARGET_PAGE_SIZE */
209#ifdef _WIN32
210 {
211 SYSTEM_INFO system_info;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800212
213 GetSystemInfo(&system_info);
214 qemu_real_host_page_size = system_info.dwPageSize;
215 }
216#else
217 qemu_real_host_page_size = getpagesize();
218#endif
219 if (qemu_host_page_size == 0)
220 qemu_host_page_size = qemu_real_host_page_size;
221 if (qemu_host_page_size < TARGET_PAGE_SIZE)
222 qemu_host_page_size = TARGET_PAGE_SIZE;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800223 qemu_host_page_mask = ~(qemu_host_page_size - 1);
224 l1_phys_map = qemu_vmalloc(L1_SIZE * sizeof(void *));
225 memset(l1_phys_map, 0, L1_SIZE * sizeof(void *));
226
227#if !defined(_WIN32) && defined(CONFIG_USER_ONLY)
228 {
229 long long startaddr, endaddr;
230 FILE *f;
231 int n;
232
233 mmap_lock();
234 last_brk = (unsigned long)sbrk(0);
235 f = fopen("/proc/self/maps", "r");
236 if (f) {
237 do {
238 n = fscanf (f, "%llx-%llx %*[^\n]\n", &startaddr, &endaddr);
239 if (n == 2) {
240 startaddr = MIN(startaddr,
241 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
242 endaddr = MIN(endaddr,
243 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
244 page_set_flags(startaddr & TARGET_PAGE_MASK,
245 TARGET_PAGE_ALIGN(endaddr),
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800246 PAGE_RESERVED);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800247 }
248 } while (!feof(f));
249 fclose(f);
250 }
251 mmap_unlock();
252 }
253#endif
254}
255
256static inline PageDesc **page_l1_map(target_ulong index)
257{
258#if TARGET_LONG_BITS > 32
259 /* Host memory outside guest VM. For 32-bit targets we have already
260 excluded high addresses. */
261 if (index > ((target_ulong)L2_SIZE * L1_SIZE))
262 return NULL;
263#endif
264 return &l1_map[index >> L2_BITS];
265}
266
267static inline PageDesc *page_find_alloc(target_ulong index)
268{
269 PageDesc **lp, *p;
270 lp = page_l1_map(index);
271 if (!lp)
272 return NULL;
273
274 p = *lp;
275 if (!p) {
276 /* allocate if not found */
277#if defined(CONFIG_USER_ONLY)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800278 size_t len = sizeof(PageDesc) * L2_SIZE;
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100279 /* Don't use g_malloc because it may recurse. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700280 p = mmap(NULL, len, PROT_READ | PROT_WRITE,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800281 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
282 *lp = p;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700283 if (h2g_valid(p)) {
284 unsigned long addr = h2g(p);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800285 page_set_flags(addr & TARGET_PAGE_MASK,
286 TARGET_PAGE_ALIGN(addr + len),
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800287 PAGE_RESERVED);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800288 }
289#else
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100290 p = g_malloc0(sizeof(PageDesc) * L2_SIZE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800291 *lp = p;
292#endif
293 }
294 return p + (index & (L2_SIZE - 1));
295}
296
297static inline PageDesc *page_find(target_ulong index)
298{
299 PageDesc **lp, *p;
300 lp = page_l1_map(index);
301 if (!lp)
302 return NULL;
303
304 p = *lp;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700305 if (!p) {
306 return NULL;
307 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800308 return p + (index & (L2_SIZE - 1));
309}
310
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100311static PhysPageDesc *phys_page_find_alloc(hwaddr index, int alloc)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800312{
313 void **lp, **p;
314 PhysPageDesc *pd;
315
316 p = (void **)l1_phys_map;
317#if TARGET_PHYS_ADDR_SPACE_BITS > 32
318
319#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
320#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
321#endif
322 lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1));
323 p = *lp;
324 if (!p) {
325 /* allocate if not found */
326 if (!alloc)
327 return NULL;
328 p = qemu_vmalloc(sizeof(void *) * L1_SIZE);
329 memset(p, 0, sizeof(void *) * L1_SIZE);
330 *lp = p;
331 }
332#endif
333 lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
334 pd = *lp;
335 if (!pd) {
336 int i;
337 /* allocate if not found */
338 if (!alloc)
339 return NULL;
340 pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
341 *lp = pd;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700342 for (i = 0; i < L2_SIZE; i++) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800343 pd[i].phys_offset = IO_MEM_UNASSIGNED;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700344 pd[i].region_offset = (index + i) << TARGET_PAGE_BITS;
345 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800346 }
347 return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
348}
349
David 'Digit' Turner3dc53fc2014-01-17 01:23:40 +0100350PhysPageDesc *phys_page_find(hwaddr index)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800351{
352 return phys_page_find_alloc(index, 0);
353}
354
355#if !defined(CONFIG_USER_ONLY)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800356#define mmap_lock() do { } while(0)
357#define mmap_unlock() do { } while(0)
358#endif
359
360#define DEFAULT_CODE_GEN_BUFFER_SIZE (32 * 1024 * 1024)
361
362#if defined(CONFIG_USER_ONLY)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700363/* Currently it is not recommended to allocate big chunks of data in
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800364 user mode. It will change when a dedicated libc will be used */
365#define USE_STATIC_CODE_GEN_BUFFER
366#endif
367
368#ifdef USE_STATIC_CODE_GEN_BUFFER
369static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE];
370#endif
371
372static void code_gen_alloc(unsigned long tb_size)
373{
374#ifdef USE_STATIC_CODE_GEN_BUFFER
375 code_gen_buffer = static_code_gen_buffer;
376 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
377 map_exec(code_gen_buffer, code_gen_buffer_size);
378#else
379 code_gen_buffer_size = tb_size;
380 if (code_gen_buffer_size == 0) {
381#if defined(CONFIG_USER_ONLY)
382 /* in user mode, phys_ram_size is not meaningful */
383 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
384#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700385 /* XXX: needs adjustments */
386 code_gen_buffer_size = (unsigned long)(ram_size / 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800387#endif
388 }
389 if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE)
390 code_gen_buffer_size = MIN_CODE_GEN_BUFFER_SIZE;
391 /* The code gen buffer location may have constraints depending on
392 the host cpu and OS */
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200393#if defined(__linux__)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800394 {
395 int flags;
396 void *start = NULL;
397
398 flags = MAP_PRIVATE | MAP_ANONYMOUS;
399#if defined(__x86_64__)
400 flags |= MAP_32BIT;
401 /* Cannot map more than that */
402 if (code_gen_buffer_size > (800 * 1024 * 1024))
403 code_gen_buffer_size = (800 * 1024 * 1024);
404#elif defined(__sparc_v9__)
405 // Map the buffer below 2G, so we can use direct calls and branches
406 flags |= MAP_FIXED;
407 start = (void *) 0x60000000UL;
408 if (code_gen_buffer_size > (512 * 1024 * 1024))
409 code_gen_buffer_size = (512 * 1024 * 1024);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700410#elif defined(__arm__)
411 /* Map the buffer below 32M, so we can use direct calls and branches */
412 flags |= MAP_FIXED;
413 start = (void *) 0x01000000UL;
414 if (code_gen_buffer_size > 16 * 1024 * 1024)
415 code_gen_buffer_size = 16 * 1024 * 1024;
David 'Digit' Turner36411062010-12-22 17:34:53 +0100416#elif defined(__s390x__)
417 /* Map the buffer so that we can use direct calls and branches. */
418 /* We have a +- 4GB range on the branches; leave some slop. */
419 if (code_gen_buffer_size > (3ul * 1024 * 1024 * 1024)) {
420 code_gen_buffer_size = 3ul * 1024 * 1024 * 1024;
421 }
422 start = (void *)0x90000000UL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800423#endif
424 code_gen_buffer = mmap(start, code_gen_buffer_size,
425 PROT_WRITE | PROT_READ | PROT_EXEC,
426 flags, -1, 0);
427 if (code_gen_buffer == MAP_FAILED) {
428 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
429 exit(1);
430 }
431 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200432#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \
433 || defined(__DragonFly__) || defined(__OpenBSD__)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700434 {
435 int flags;
436 void *addr = NULL;
437 flags = MAP_PRIVATE | MAP_ANONYMOUS;
438#if defined(__x86_64__)
439 /* FreeBSD doesn't have MAP_32BIT, use MAP_FIXED and assume
440 * 0x40000000 is free */
441 flags |= MAP_FIXED;
442 addr = (void *)0x40000000;
443 /* Cannot map more than that */
444 if (code_gen_buffer_size > (800 * 1024 * 1024))
445 code_gen_buffer_size = (800 * 1024 * 1024);
David 'Digit' Turner280afa02011-05-11 17:37:44 +0200446#elif defined(__sparc_v9__)
447 // Map the buffer below 2G, so we can use direct calls and branches
448 flags |= MAP_FIXED;
449 addr = (void *) 0x60000000UL;
450 if (code_gen_buffer_size > (512 * 1024 * 1024)) {
451 code_gen_buffer_size = (512 * 1024 * 1024);
452 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700453#endif
454 code_gen_buffer = mmap(addr, code_gen_buffer_size,
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200455 PROT_WRITE | PROT_READ | PROT_EXEC,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700456 flags, -1, 0);
457 if (code_gen_buffer == MAP_FAILED) {
458 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
459 exit(1);
460 }
461 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800462#else
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100463 code_gen_buffer = g_malloc(code_gen_buffer_size);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800464 map_exec(code_gen_buffer, code_gen_buffer_size);
465#endif
466#endif /* !USE_STATIC_CODE_GEN_BUFFER */
467 map_exec(code_gen_prologue, sizeof(code_gen_prologue));
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800468 code_gen_buffer_max_size = code_gen_buffer_size -
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800469 code_gen_max_block_size();
470 code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100471 tbs = g_malloc(code_gen_max_blocks * sizeof(TranslationBlock));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800472}
473
474/* Must be called before using the QEMU cpus. 'tb_size' is the size
475 (in bytes) allocated to the translation buffer. Zero means default
476 size. */
477void cpu_exec_init_all(unsigned long tb_size)
478{
479 cpu_gen_init();
480 code_gen_alloc(tb_size);
481 code_gen_ptr = code_gen_buffer;
482 page_init();
483#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +0100484 qemu_mutex_init(&ram_list.mutex);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800485 io_mem_init();
486#endif
David 'Digit' Turnerf1d9bf12011-05-11 18:19:41 +0200487#if !defined(CONFIG_USER_ONLY) || !defined(CONFIG_USE_GUEST_BASE)
488 /* There's no guest base to take into account, so go ahead and
489 initialize the prologue now. */
490 tcg_prologue_init(&tcg_ctx);
491#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800492}
493
494#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
495
496#define CPU_COMMON_SAVE_VERSION 1
497
498static void cpu_common_save(QEMUFile *f, void *opaque)
499{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100500 CPUOldState *env = opaque;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800501
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700502 cpu_synchronize_state(env, 0);
503
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800504 qemu_put_be32s(f, &env->halted);
505 qemu_put_be32s(f, &env->interrupt_request);
506}
507
508static int cpu_common_load(QEMUFile *f, void *opaque, int version_id)
509{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100510 CPUOldState *env = opaque;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800511
512 if (version_id != CPU_COMMON_SAVE_VERSION)
513 return -EINVAL;
514
515 qemu_get_be32s(f, &env->halted);
516 qemu_get_be32s(f, &env->interrupt_request);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700517 /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
518 version_id is increased. */
519 env->interrupt_request &= ~0x01;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800520 tlb_flush(env, 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700521 cpu_synchronize_state(env, 1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800522
523 return 0;
524}
525#endif
526
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100527CPUArchState *qemu_get_cpu(int cpu)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700528{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100529 CPUArchState *env = first_cpu;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700530
531 while (env) {
532 if (env->cpu_index == cpu)
533 break;
534 env = env->next_cpu;
535 }
536
537 return env;
538}
539
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100540void cpu_exec_init(CPUArchState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800541{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100542 CPUArchState **penv;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800543 int cpu_index;
544
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700545#if defined(CONFIG_USER_ONLY)
546 cpu_list_lock();
547#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800548 env->next_cpu = NULL;
549 penv = &first_cpu;
550 cpu_index = 0;
551 while (*penv != NULL) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700552 penv = &(*penv)->next_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800553 cpu_index++;
554 }
555 env->cpu_index = cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700556 env->numa_node = 0;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700557 QTAILQ_INIT(&env->breakpoints);
558 QTAILQ_INIT(&env->watchpoints);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800559 *penv = env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700560#if defined(CONFIG_USER_ONLY)
561 cpu_list_unlock();
562#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800563#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
David 'Digit' Turner5cb5c0b2014-02-17 16:04:03 +0100564 register_savevm(NULL,
565 "cpu_common",
566 cpu_index,
567 CPU_COMMON_SAVE_VERSION,
568 cpu_common_save,
569 cpu_common_load,
570 env);
571 register_savevm(NULL,
572 "cpu",
573 cpu_index,
574 CPU_SAVE_VERSION,
575 cpu_save,
576 cpu_load,
577 env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800578#endif
579}
580
581static inline void invalidate_page_bitmap(PageDesc *p)
582{
583 if (p->code_bitmap) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100584 g_free(p->code_bitmap);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800585 p->code_bitmap = NULL;
586 }
587 p->code_write_count = 0;
588}
589
590/* set to NULL all the 'first_tb' fields in all PageDescs */
591static void page_flush_tb(void)
592{
593 int i, j;
594 PageDesc *p;
595
596 for(i = 0; i < L1_SIZE; i++) {
597 p = l1_map[i];
598 if (p) {
599 for(j = 0; j < L2_SIZE; j++) {
600 p->first_tb = NULL;
601 invalidate_page_bitmap(p);
602 p++;
603 }
604 }
605 }
606}
607
608/* flush all the translation blocks */
609/* XXX: tb_flush is currently not thread safe */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100610void tb_flush(CPUArchState *env1)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800611{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100612 CPUArchState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800613#if defined(DEBUG_FLUSH)
614 printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
615 (unsigned long)(code_gen_ptr - code_gen_buffer),
616 nb_tbs, nb_tbs > 0 ?
617 ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
618#endif
619 if ((unsigned long)(code_gen_ptr - code_gen_buffer) > code_gen_buffer_size)
620 cpu_abort(env1, "Internal error: code buffer overflow\n");
621
622 nb_tbs = 0;
623
624 for(env = first_cpu; env != NULL; env = env->next_cpu) {
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800625#ifdef CONFIG_MEMCHECK
626 int tb_to_clean;
627 for (tb_to_clean = 0; tb_to_clean < TB_JMP_CACHE_SIZE; tb_to_clean++) {
628 if (env->tb_jmp_cache[tb_to_clean] != NULL &&
629 env->tb_jmp_cache[tb_to_clean]->tpc2gpc != NULL) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100630 g_free(env->tb_jmp_cache[tb_to_clean]->tpc2gpc);
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800631 env->tb_jmp_cache[tb_to_clean]->tpc2gpc = NULL;
632 env->tb_jmp_cache[tb_to_clean]->tpc2gpc_pairs = 0;
633 }
634 }
635#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800636 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
637 }
638
639 memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
640 page_flush_tb();
641
642 code_gen_ptr = code_gen_buffer;
643 /* XXX: flush processor icache at this point if cache flush is
644 expensive */
645 tb_flush_count++;
646}
647
648#ifdef DEBUG_TB_CHECK
649
650static void tb_invalidate_check(target_ulong address)
651{
652 TranslationBlock *tb;
653 int i;
654 address &= TARGET_PAGE_MASK;
655 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
656 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
657 if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
658 address >= tb->pc + tb->size)) {
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700659 printf("ERROR invalidate: address=" TARGET_FMT_lx
660 " PC=%08lx size=%04x\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800661 address, (long)tb->pc, tb->size);
662 }
663 }
664 }
665}
666
667/* verify that all the pages have correct rights for code */
668static void tb_page_check(void)
669{
670 TranslationBlock *tb;
671 int i, flags1, flags2;
672
673 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
674 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
675 flags1 = page_get_flags(tb->pc);
676 flags2 = page_get_flags(tb->pc + tb->size - 1);
677 if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
678 printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
679 (long)tb->pc, tb->size, flags1, flags2);
680 }
681 }
682 }
683}
684
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800685#endif
686
687/* invalidate one TB */
688static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb,
689 int next_offset)
690{
691 TranslationBlock *tb1;
692 for(;;) {
693 tb1 = *ptb;
694 if (tb1 == tb) {
695 *ptb = *(TranslationBlock **)((char *)tb1 + next_offset);
696 break;
697 }
698 ptb = (TranslationBlock **)((char *)tb1 + next_offset);
699 }
700}
701
702static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
703{
704 TranslationBlock *tb1;
705 unsigned int n1;
706
707 for(;;) {
708 tb1 = *ptb;
709 n1 = (long)tb1 & 3;
710 tb1 = (TranslationBlock *)((long)tb1 & ~3);
711 if (tb1 == tb) {
712 *ptb = tb1->page_next[n1];
713 break;
714 }
715 ptb = &tb1->page_next[n1];
716 }
717}
718
719static inline void tb_jmp_remove(TranslationBlock *tb, int n)
720{
721 TranslationBlock *tb1, **ptb;
722 unsigned int n1;
723
724 ptb = &tb->jmp_next[n];
725 tb1 = *ptb;
726 if (tb1) {
727 /* find tb(n) in circular list */
728 for(;;) {
729 tb1 = *ptb;
730 n1 = (long)tb1 & 3;
731 tb1 = (TranslationBlock *)((long)tb1 & ~3);
732 if (n1 == n && tb1 == tb)
733 break;
734 if (n1 == 2) {
735 ptb = &tb1->jmp_first;
736 } else {
737 ptb = &tb1->jmp_next[n1];
738 }
739 }
740 /* now we can suppress tb(n) from the list */
741 *ptb = tb->jmp_next[n];
742
743 tb->jmp_next[n] = NULL;
744 }
745}
746
747/* reset the jump entry 'n' of a TB so that it is not chained to
748 another TB */
749static inline void tb_reset_jump(TranslationBlock *tb, int n)
750{
751 tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
752}
753
David 'Digit' Turner85c62202014-02-16 20:53:40 +0100754void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800755{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100756 CPUArchState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800757 PageDesc *p;
758 unsigned int h, n1;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100759 hwaddr phys_pc;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800760 TranslationBlock *tb1, *tb2;
761
762 /* remove the TB from the hash list */
763 phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
764 h = tb_phys_hash_func(phys_pc);
765 tb_remove(&tb_phys_hash[h], tb,
766 offsetof(TranslationBlock, phys_hash_next));
767
768 /* remove the TB from the page list */
769 if (tb->page_addr[0] != page_addr) {
770 p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
771 tb_page_remove(&p->first_tb, tb);
772 invalidate_page_bitmap(p);
773 }
774 if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
775 p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
776 tb_page_remove(&p->first_tb, tb);
777 invalidate_page_bitmap(p);
778 }
779
780 tb_invalidated_flag = 1;
781
782 /* remove the TB from the hash list */
783 h = tb_jmp_cache_hash_func(tb->pc);
784 for(env = first_cpu; env != NULL; env = env->next_cpu) {
785 if (env->tb_jmp_cache[h] == tb)
786 env->tb_jmp_cache[h] = NULL;
787 }
788
789 /* suppress this TB from the two jump lists */
790 tb_jmp_remove(tb, 0);
791 tb_jmp_remove(tb, 1);
792
793 /* suppress any remaining jumps to this TB */
794 tb1 = tb->jmp_first;
795 for(;;) {
796 n1 = (long)tb1 & 3;
797 if (n1 == 2)
798 break;
799 tb1 = (TranslationBlock *)((long)tb1 & ~3);
800 tb2 = tb1->jmp_next[n1];
801 tb_reset_jump(tb1, n1);
802 tb1->jmp_next[n1] = NULL;
803 tb1 = tb2;
804 }
805 tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
806
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800807#ifdef CONFIG_MEMCHECK
808 if (tb->tpc2gpc != NULL) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100809 g_free(tb->tpc2gpc);
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -0800810 tb->tpc2gpc = NULL;
811 tb->tpc2gpc_pairs = 0;
812 }
813#endif // CONFIG_MEMCHECK
814
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800815 tb_phys_invalidate_count++;
816}
817
818static inline void set_bits(uint8_t *tab, int start, int len)
819{
820 int end, mask, end1;
821
822 end = start + len;
823 tab += start >> 3;
824 mask = 0xff << (start & 7);
825 if ((start & ~7) == (end & ~7)) {
826 if (start < end) {
827 mask &= ~(0xff << (end & 7));
828 *tab |= mask;
829 }
830 } else {
831 *tab++ |= mask;
832 start = (start + 8) & ~7;
833 end1 = end & ~7;
834 while (start < end1) {
835 *tab++ = 0xff;
836 start += 8;
837 }
838 if (start < end) {
839 mask = ~(0xff << (end & 7));
840 *tab |= mask;
841 }
842 }
843}
844
845static void build_page_bitmap(PageDesc *p)
846{
847 int n, tb_start, tb_end;
848 TranslationBlock *tb;
849
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100850 p->code_bitmap = g_malloc0(TARGET_PAGE_SIZE / 8);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800851
852 tb = p->first_tb;
853 while (tb != NULL) {
854 n = (long)tb & 3;
855 tb = (TranslationBlock *)((long)tb & ~3);
856 /* NOTE: this is subtle as a TB may span two physical pages */
857 if (n == 0) {
858 /* NOTE: tb_end may be after the end of the page, but
859 it is not a problem */
860 tb_start = tb->pc & ~TARGET_PAGE_MASK;
861 tb_end = tb_start + tb->size;
862 if (tb_end > TARGET_PAGE_SIZE)
863 tb_end = TARGET_PAGE_SIZE;
864 } else {
865 tb_start = 0;
866 tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
867 }
868 set_bits(p->code_bitmap, tb_start, tb_end - tb_start);
869 tb = tb->page_next[n];
870 }
871}
872
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100873TranslationBlock *tb_gen_code(CPUArchState *env,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800874 target_ulong pc, target_ulong cs_base,
875 int flags, int cflags)
876{
877 TranslationBlock *tb;
878 uint8_t *tc_ptr;
879 target_ulong phys_pc, phys_page2, virt_page2;
880 int code_gen_size;
881
882 phys_pc = get_phys_addr_code(env, pc);
883 tb = tb_alloc(pc);
884 if (!tb) {
885 /* flush must be done */
886 tb_flush(env);
887 /* cannot fail at this point */
888 tb = tb_alloc(pc);
889 /* Don't forget to invalidate previous TB info. */
890 tb_invalidated_flag = 1;
891 }
892 tc_ptr = code_gen_ptr;
893 tb->tc_ptr = tc_ptr;
894 tb->cs_base = cs_base;
895 tb->flags = flags;
896 tb->cflags = cflags;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800897 cpu_gen_code(env, tb, &code_gen_size);
898 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
899
900 /* check next page if needed */
901 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
902 phys_page2 = -1;
903 if ((pc & TARGET_PAGE_MASK) != virt_page2) {
904 phys_page2 = get_phys_addr_code(env, virt_page2);
905 }
906 tb_link_phys(tb, phys_pc, phys_page2);
907 return tb;
908}
909
910/* invalidate all TBs which intersect with the target physical page
911 starting in range [start;end[. NOTE: start and end must refer to
912 the same physical page. 'is_cpu_write_access' should be true if called
913 from a real cpu write access: the virtual CPU will exit the current
914 TB if code is modified inside this TB. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +0100915void tb_invalidate_phys_page_range(hwaddr start, hwaddr end,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800916 int is_cpu_write_access)
917{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700918 TranslationBlock *tb, *tb_next, *saved_tb;
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +0100919 CPUArchState *env = cpu_single_env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800920 target_ulong tb_start, tb_end;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700921 PageDesc *p;
922 int n;
923#ifdef TARGET_HAS_PRECISE_SMC
924 int current_tb_not_found = is_cpu_write_access;
925 TranslationBlock *current_tb = NULL;
926 int current_tb_modified = 0;
927 target_ulong current_pc = 0;
928 target_ulong current_cs_base = 0;
929 int current_flags = 0;
930#endif /* TARGET_HAS_PRECISE_SMC */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800931
932 p = page_find(start >> TARGET_PAGE_BITS);
933 if (!p)
934 return;
935 if (!p->code_bitmap &&
936 ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
937 is_cpu_write_access) {
938 /* build code bitmap */
939 build_page_bitmap(p);
940 }
941
942 /* we remove all the TBs in the range [start, end[ */
943 /* 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 -0800944 tb = p->first_tb;
945 while (tb != NULL) {
946 n = (long)tb & 3;
947 tb = (TranslationBlock *)((long)tb & ~3);
948 tb_next = tb->page_next[n];
949 /* NOTE: this is subtle as a TB may span two physical pages */
950 if (n == 0) {
951 /* NOTE: tb_end may be after the end of the page, but
952 it is not a problem */
953 tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
954 tb_end = tb_start + tb->size;
955 } else {
956 tb_start = tb->page_addr[1];
957 tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
958 }
959 if (!(tb_end <= start || tb_start >= end)) {
960#ifdef TARGET_HAS_PRECISE_SMC
961 if (current_tb_not_found) {
962 current_tb_not_found = 0;
963 current_tb = NULL;
964 if (env->mem_io_pc) {
965 /* now we have a real cpu fault */
966 current_tb = tb_find_pc(env->mem_io_pc);
967 }
968 }
969 if (current_tb == tb &&
970 (current_tb->cflags & CF_COUNT_MASK) != 1) {
971 /* If we are modifying the current TB, we must stop
972 its execution. We could be more precise by checking
973 that the modification is after the current PC, but it
974 would require a specialized function to partially
975 restore the CPU state */
976
977 current_tb_modified = 1;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +0200978 cpu_restore_state(current_tb, env, env->mem_io_pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700979 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
980 &current_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800981 }
982#endif /* TARGET_HAS_PRECISE_SMC */
983 /* we need to do that to handle the case where a signal
984 occurs while doing tb_phys_invalidate() */
985 saved_tb = NULL;
986 if (env) {
987 saved_tb = env->current_tb;
988 env->current_tb = NULL;
989 }
990 tb_phys_invalidate(tb, -1);
991 if (env) {
992 env->current_tb = saved_tb;
993 if (env->interrupt_request && env->current_tb)
994 cpu_interrupt(env, env->interrupt_request);
995 }
996 }
997 tb = tb_next;
998 }
999#if !defined(CONFIG_USER_ONLY)
1000 /* if no code remaining, no need to continue to use slow writes */
1001 if (!p->first_tb) {
1002 invalidate_page_bitmap(p);
1003 if (is_cpu_write_access) {
1004 tlb_unprotect_code_phys(env, start, env->mem_io_vaddr);
1005 }
1006 }
1007#endif
1008#ifdef TARGET_HAS_PRECISE_SMC
1009 if (current_tb_modified) {
1010 /* we generate a block containing just the instruction
1011 modifying the memory. It will ensure that it cannot modify
1012 itself */
1013 env->current_tb = NULL;
1014 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1015 cpu_resume_from_signal(env, NULL);
1016 }
1017#endif
1018}
1019
1020/* len must be <= 8 and start must be a multiple of len */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001021static inline void tb_invalidate_phys_page_fast(hwaddr start, int len)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001022{
1023 PageDesc *p;
1024 int offset, b;
1025#if 0
1026 if (1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001027 qemu_log("modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
1028 cpu_single_env->mem_io_vaddr, len,
1029 cpu_single_env->eip,
1030 cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001031 }
1032#endif
1033 p = page_find(start >> TARGET_PAGE_BITS);
1034 if (!p)
1035 return;
1036 if (p->code_bitmap) {
1037 offset = start & ~TARGET_PAGE_MASK;
1038 b = p->code_bitmap[offset >> 3] >> (offset & 7);
1039 if (b & ((1 << len) - 1))
1040 goto do_invalidate;
1041 } else {
1042 do_invalidate:
1043 tb_invalidate_phys_page_range(start, start + len, 1);
1044 }
1045}
1046
1047#if !defined(CONFIG_SOFTMMU)
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001048static void tb_invalidate_phys_page(hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001049 unsigned long pc, void *puc)
1050{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001051 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001052 PageDesc *p;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001053 int n;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001054#ifdef TARGET_HAS_PRECISE_SMC
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001055 TranslationBlock *current_tb = NULL;
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001056 CPUArchState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001057 int current_tb_modified = 0;
1058 target_ulong current_pc = 0;
1059 target_ulong current_cs_base = 0;
1060 int current_flags = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001061#endif
1062
1063 addr &= TARGET_PAGE_MASK;
1064 p = page_find(addr >> TARGET_PAGE_BITS);
1065 if (!p)
1066 return;
1067 tb = p->first_tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001068#ifdef TARGET_HAS_PRECISE_SMC
1069 if (tb && pc != 0) {
1070 current_tb = tb_find_pc(pc);
1071 }
1072#endif
1073 while (tb != NULL) {
1074 n = (long)tb & 3;
1075 tb = (TranslationBlock *)((long)tb & ~3);
1076#ifdef TARGET_HAS_PRECISE_SMC
1077 if (current_tb == tb &&
1078 (current_tb->cflags & CF_COUNT_MASK) != 1) {
1079 /* If we are modifying the current TB, we must stop
1080 its execution. We could be more precise by checking
1081 that the modification is after the current PC, but it
1082 would require a specialized function to partially
1083 restore the CPU state */
1084
1085 current_tb_modified = 1;
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02001086 cpu_restore_state(current_tb, env, pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001087 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
1088 &current_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001089 }
1090#endif /* TARGET_HAS_PRECISE_SMC */
1091 tb_phys_invalidate(tb, addr);
1092 tb = tb->page_next[n];
1093 }
1094 p->first_tb = NULL;
1095#ifdef TARGET_HAS_PRECISE_SMC
1096 if (current_tb_modified) {
1097 /* we generate a block containing just the instruction
1098 modifying the memory. It will ensure that it cannot modify
1099 itself */
1100 env->current_tb = NULL;
1101 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1102 cpu_resume_from_signal(env, puc);
1103 }
1104#endif
1105}
1106#endif
1107
1108/* add the tb in the target page and protect it if necessary */
1109static inline void tb_alloc_page(TranslationBlock *tb,
1110 unsigned int n, target_ulong page_addr)
1111{
1112 PageDesc *p;
1113 TranslationBlock *last_first_tb;
1114
1115 tb->page_addr[n] = page_addr;
1116 p = page_find_alloc(page_addr >> TARGET_PAGE_BITS);
1117 tb->page_next[n] = p->first_tb;
1118 last_first_tb = p->first_tb;
1119 p->first_tb = (TranslationBlock *)((long)tb | n);
1120 invalidate_page_bitmap(p);
1121
1122#if defined(TARGET_HAS_SMC) || 1
1123
1124#if defined(CONFIG_USER_ONLY)
1125 if (p->flags & PAGE_WRITE) {
1126 target_ulong addr;
1127 PageDesc *p2;
1128 int prot;
1129
1130 /* force the host page as non writable (writes will have a
1131 page fault + mprotect overhead) */
1132 page_addr &= qemu_host_page_mask;
1133 prot = 0;
1134 for(addr = page_addr; addr < page_addr + qemu_host_page_size;
1135 addr += TARGET_PAGE_SIZE) {
1136
1137 p2 = page_find (addr >> TARGET_PAGE_BITS);
1138 if (!p2)
1139 continue;
1140 prot |= p2->flags;
1141 p2->flags &= ~PAGE_WRITE;
1142 page_get_flags(addr);
1143 }
1144 mprotect(g2h(page_addr), qemu_host_page_size,
1145 (prot & PAGE_BITS) & ~PAGE_WRITE);
1146#ifdef DEBUG_TB_INVALIDATE
1147 printf("protecting code page: 0x" TARGET_FMT_lx "\n",
1148 page_addr);
1149#endif
1150 }
1151#else
1152 /* if some code is already present, then the pages are already
1153 protected. So we handle the case where only the first TB is
1154 allocated in a physical page */
1155 if (!last_first_tb) {
1156 tlb_protect_code(page_addr);
1157 }
1158#endif
1159
1160#endif /* TARGET_HAS_SMC */
1161}
1162
1163/* Allocate a new translation block. Flush the translation buffer if
1164 too many translation blocks or too much generated code. */
1165TranslationBlock *tb_alloc(target_ulong pc)
1166{
1167 TranslationBlock *tb;
1168
1169 if (nb_tbs >= code_gen_max_blocks ||
1170 (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
1171 return NULL;
1172 tb = &tbs[nb_tbs++];
1173 tb->pc = pc;
1174 tb->cflags = 0;
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -08001175#ifdef CONFIG_MEMCHECK
1176 tb->tpc2gpc = NULL;
1177 tb->tpc2gpc_pairs = 0;
1178#endif // CONFIG_MEMCHECK
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001179 return tb;
1180}
1181
1182void tb_free(TranslationBlock *tb)
1183{
1184 /* In practice this is mostly used for single use temporary TB
1185 Ignore the hard cases and just back up if this TB happens to
1186 be the last one generated. */
1187 if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) {
1188 code_gen_ptr = tb->tc_ptr;
1189 nb_tbs--;
1190 }
1191}
1192
1193/* add a new TB and link it to the physical page tables. phys_page2 is
1194 (-1) to indicate that only one page contains the TB. */
1195void tb_link_phys(TranslationBlock *tb,
1196 target_ulong phys_pc, target_ulong phys_page2)
1197{
1198 unsigned int h;
1199 TranslationBlock **ptb;
1200
1201 /* Grab the mmap lock to stop another thread invalidating this TB
1202 before we are done. */
1203 mmap_lock();
1204 /* add in the physical hash table */
1205 h = tb_phys_hash_func(phys_pc);
1206 ptb = &tb_phys_hash[h];
1207 tb->phys_hash_next = *ptb;
1208 *ptb = tb;
1209
1210 /* add in the page list */
1211 tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK);
1212 if (phys_page2 != -1)
1213 tb_alloc_page(tb, 1, phys_page2);
1214 else
1215 tb->page_addr[1] = -1;
1216
1217 tb->jmp_first = (TranslationBlock *)((long)tb | 2);
1218 tb->jmp_next[0] = NULL;
1219 tb->jmp_next[1] = NULL;
1220
1221 /* init original jump addresses */
1222 if (tb->tb_next_offset[0] != 0xffff)
1223 tb_reset_jump(tb, 0);
1224 if (tb->tb_next_offset[1] != 0xffff)
1225 tb_reset_jump(tb, 1);
1226
1227#ifdef DEBUG_TB_CHECK
1228 tb_page_check();
1229#endif
1230 mmap_unlock();
1231}
1232
1233/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
1234 tb[1].tc_ptr. Return NULL if not found */
1235TranslationBlock *tb_find_pc(unsigned long tc_ptr)
1236{
1237 int m_min, m_max, m;
1238 unsigned long v;
1239 TranslationBlock *tb;
1240
1241 if (nb_tbs <= 0)
1242 return NULL;
1243 if (tc_ptr < (unsigned long)code_gen_buffer ||
1244 tc_ptr >= (unsigned long)code_gen_ptr)
1245 return NULL;
1246 /* binary search (cf Knuth) */
1247 m_min = 0;
1248 m_max = nb_tbs - 1;
1249 while (m_min <= m_max) {
1250 m = (m_min + m_max) >> 1;
1251 tb = &tbs[m];
1252 v = (unsigned long)tb->tc_ptr;
1253 if (v == tc_ptr)
1254 return tb;
1255 else if (tc_ptr < v) {
1256 m_max = m - 1;
1257 } else {
1258 m_min = m + 1;
1259 }
1260 }
1261 return &tbs[m_max];
1262}
1263
1264static void tb_reset_jump_recursive(TranslationBlock *tb);
1265
1266static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
1267{
1268 TranslationBlock *tb1, *tb_next, **ptb;
1269 unsigned int n1;
1270
1271 tb1 = tb->jmp_next[n];
1272 if (tb1 != NULL) {
1273 /* find head of list */
1274 for(;;) {
1275 n1 = (long)tb1 & 3;
1276 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1277 if (n1 == 2)
1278 break;
1279 tb1 = tb1->jmp_next[n1];
1280 }
1281 /* we are now sure now that tb jumps to tb1 */
1282 tb_next = tb1;
1283
1284 /* remove tb from the jmp_first list */
1285 ptb = &tb_next->jmp_first;
1286 for(;;) {
1287 tb1 = *ptb;
1288 n1 = (long)tb1 & 3;
1289 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1290 if (n1 == n && tb1 == tb)
1291 break;
1292 ptb = &tb1->jmp_next[n1];
1293 }
1294 *ptb = tb->jmp_next[n];
1295 tb->jmp_next[n] = NULL;
1296
1297 /* suppress the jump to next tb in generated code */
1298 tb_reset_jump(tb, n);
1299
1300 /* suppress jumps in the tb on which we could have jumped */
1301 tb_reset_jump_recursive(tb_next);
1302 }
1303}
1304
1305static void tb_reset_jump_recursive(TranslationBlock *tb)
1306{
1307 tb_reset_jump_recursive2(tb, 0);
1308 tb_reset_jump_recursive2(tb, 1);
1309}
1310
1311#if defined(TARGET_HAS_ICE)
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001312static void breakpoint_invalidate(CPUArchState *env, target_ulong pc)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001313{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001314 hwaddr addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001315 target_ulong pd;
1316 ram_addr_t ram_addr;
1317 PhysPageDesc *p;
1318
1319 addr = cpu_get_phys_page_debug(env, pc);
1320 p = phys_page_find(addr >> TARGET_PAGE_BITS);
1321 if (!p) {
1322 pd = IO_MEM_UNASSIGNED;
1323 } else {
1324 pd = p->phys_offset;
1325 }
1326 ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
1327 tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
1328}
1329#endif
1330
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001331#if defined(CONFIG_USER_ONLY)
1332void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
1333
1334{
1335}
1336
1337int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
1338 int flags, CPUWatchpoint **watchpoint)
1339{
1340 return -ENOSYS;
1341}
1342#else
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001343/* Add a watchpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001344int cpu_watchpoint_insert(CPUArchState *env, target_ulong addr, target_ulong len,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001345 int flags, CPUWatchpoint **watchpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001346{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001347 target_ulong len_mask = ~(len - 1);
1348 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001349
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001350 /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001351 if ((len & (len - 1)) || (addr & ~len_mask) ||
1352 len == 0 || len > TARGET_PAGE_SIZE) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001353 fprintf(stderr, "qemu: tried to set invalid watchpoint at "
1354 TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
1355 return -EINVAL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001356 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001357 wp = g_malloc(sizeof(*wp));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001358
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001359 wp->vaddr = addr;
1360 wp->len_mask = len_mask;
1361 wp->flags = flags;
1362
1363 /* keep all GDB-injected watchpoints in front */
1364 if (flags & BP_GDB)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001365 QTAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001366 else
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001367 QTAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001368
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001369 tlb_flush_page(env, addr);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001370
1371 if (watchpoint)
1372 *watchpoint = wp;
1373 return 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001374}
1375
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001376/* Remove a specific watchpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001377int cpu_watchpoint_remove(CPUArchState *env, target_ulong addr, target_ulong len,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001378 int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001379{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001380 target_ulong len_mask = ~(len - 1);
1381 CPUWatchpoint *wp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001382
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001383 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001384 if (addr == wp->vaddr && len_mask == wp->len_mask
1385 && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
1386 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001387 return 0;
1388 }
1389 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001390 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001391}
1392
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001393/* Remove a specific watchpoint by reference. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001394void cpu_watchpoint_remove_by_ref(CPUArchState *env, CPUWatchpoint *watchpoint)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001395{
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001396 QTAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001397
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001398 tlb_flush_page(env, watchpoint->vaddr);
1399
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001400 g_free(watchpoint);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001401}
1402
1403/* Remove all matching watchpoints. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001404void cpu_watchpoint_remove_all(CPUArchState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001405{
1406 CPUWatchpoint *wp, *next;
1407
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001408 QTAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001409 if (wp->flags & mask)
1410 cpu_watchpoint_remove_by_ref(env, wp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001411 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001412}
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001413#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001414
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001415/* Add a breakpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001416int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001417 CPUBreakpoint **breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001418{
1419#if defined(TARGET_HAS_ICE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001420 CPUBreakpoint *bp;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001421
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001422 bp = g_malloc(sizeof(*bp));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001423
1424 bp->pc = pc;
1425 bp->flags = flags;
1426
1427 /* keep all GDB-injected breakpoints in front */
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001428 if (flags & BP_GDB) {
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001429 QTAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001430 } else {
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001431 QTAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001432 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001433
1434 breakpoint_invalidate(env, pc);
1435
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001436 if (breakpoint) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001437 *breakpoint = bp;
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001438 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001439 return 0;
1440#else
1441 return -ENOSYS;
1442#endif
1443}
1444
1445/* Remove a specific breakpoint. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001446int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001447{
1448#if defined(TARGET_HAS_ICE)
1449 CPUBreakpoint *bp;
1450
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001451 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001452 if (bp->pc == pc && bp->flags == flags) {
1453 cpu_breakpoint_remove_by_ref(env, bp);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001454 return 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001455 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001456 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001457 return -ENOENT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001458#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001459 return -ENOSYS;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001460#endif
1461}
1462
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001463/* Remove a specific breakpoint by reference. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001464void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001465{
1466#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001467 QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001468
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001469 breakpoint_invalidate(env, breakpoint->pc);
1470
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01001471 g_free(breakpoint);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001472#endif
1473}
1474
1475/* Remove all matching breakpoints. */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001476void cpu_breakpoint_remove_all(CPUArchState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001477{
1478#if defined(TARGET_HAS_ICE)
1479 CPUBreakpoint *bp, *next;
1480
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001481 QTAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001482 if (bp->flags & mask)
1483 cpu_breakpoint_remove_by_ref(env, bp);
1484 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001485#endif
1486}
1487
1488/* enable or disable single step mode. EXCP_DEBUG is returned by the
1489 CPU loop after each instruction */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001490void cpu_single_step(CPUOldState *env, int enabled)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001491{
1492#if defined(TARGET_HAS_ICE)
1493 if (env->singlestep_enabled != enabled) {
1494 env->singlestep_enabled = enabled;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001495 if (kvm_enabled())
1496 kvm_update_guest_debug(env, 0);
1497 else {
1498 /* must flush all the translated code to avoid inconsistencies */
1499 /* XXX: only flush what is necessary */
1500 tb_flush(env);
1501 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001502 }
1503#endif
1504}
1505
1506/* enable or disable low levels log */
1507void cpu_set_log(int log_flags)
1508{
1509 loglevel = log_flags;
1510 if (loglevel && !logfile) {
1511 logfile = fopen(logfilename, log_append ? "a" : "w");
1512 if (!logfile) {
1513 perror(logfilename);
Iliyan Malchev4a2c9dd2012-04-02 08:20:56 -07001514 exit(1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001515 }
1516#if !defined(CONFIG_SOFTMMU)
1517 /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1518 {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001519 static char logfile_buf[4096];
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001520 setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1521 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001522#elif !defined(_WIN32)
1523 /* Win32 doesn't support line-buffering and requires size >= 2 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001524 setvbuf(logfile, NULL, _IOLBF, 0);
1525#endif
1526 log_append = 1;
1527 }
1528 if (!loglevel && logfile) {
1529 fclose(logfile);
1530 logfile = NULL;
1531 }
1532}
1533
1534void cpu_set_log_filename(const char *filename)
1535{
1536 logfilename = strdup(filename);
1537 if (logfile) {
1538 fclose(logfile);
1539 logfile = NULL;
1540 }
1541 cpu_set_log(loglevel);
1542}
1543
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001544static void cpu_unlink_tb(CPUOldState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001545{
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001546 /* FIXME: TB unchaining isn't SMP safe. For now just ignore the
1547 problem and hope the cpu will stop of its own accord. For userspace
1548 emulation this often isn't actually as bad as it sounds. Often
1549 signals are used primarily to interrupt blocking syscalls. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001550 TranslationBlock *tb;
1551 static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
1552
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001553 spin_lock(&interrupt_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001554 tb = env->current_tb;
1555 /* if the cpu is currently executing code, we must unlink it and
1556 all the potentially executing TB */
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001557 if (tb) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001558 env->current_tb = NULL;
1559 tb_reset_jump_recursive(tb);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001560 }
David 'Digit' Turner795bb192011-05-09 15:20:22 +02001561 spin_unlock(&interrupt_lock);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001562}
1563
1564/* mask must never be zero, except for A20 change call */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001565void cpu_interrupt(CPUOldState *env, int mask)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001566{
1567 int old_mask;
1568
1569 old_mask = env->interrupt_request;
1570 env->interrupt_request |= mask;
1571
1572#ifndef CONFIG_USER_ONLY
1573 /*
1574 * If called from iothread context, wake the target cpu in
1575 * case its halted.
1576 */
1577 if (!qemu_cpu_self(env)) {
1578 qemu_cpu_kick(env);
1579 return;
1580 }
1581#endif
1582
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001583 if (use_icount) {
1584 env->icount_decr.u16.high = 0xffff;
1585#ifndef CONFIG_USER_ONLY
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001586 if (!can_do_io(env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001587 && (mask & ~old_mask) != 0) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001588 cpu_abort(env, "Raised interrupt while not in I/O function");
1589 }
1590#endif
1591 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001592 cpu_unlink_tb(env);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001593 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001594}
1595
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001596void cpu_reset_interrupt(CPUOldState *env, int mask)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001597{
1598 env->interrupt_request &= ~mask;
1599}
1600
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001601void cpu_exit(CPUOldState *env)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001602{
1603 env->exit_request = 1;
1604 cpu_unlink_tb(env);
1605}
1606
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001607void cpu_abort(CPUArchState *env, const char *fmt, ...)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001608{
1609 va_list ap;
1610 va_list ap2;
1611
1612 va_start(ap, fmt);
1613 va_copy(ap2, ap);
1614 fprintf(stderr, "qemu: fatal: ");
1615 vfprintf(stderr, fmt, ap);
1616 fprintf(stderr, "\n");
1617#ifdef TARGET_I386
1618 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1619#else
1620 cpu_dump_state(env, stderr, fprintf, 0);
1621#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001622 if (qemu_log_enabled()) {
1623 qemu_log("qemu: fatal: ");
1624 qemu_log_vprintf(fmt, ap2);
1625 qemu_log("\n");
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001626#ifdef TARGET_I386
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001627 log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001628#else
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001629 log_cpu_state(env, 0);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001630#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001631 qemu_log_flush();
1632 qemu_log_close();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001633 }
1634 va_end(ap2);
1635 va_end(ap);
David 'Digit' Turner36411062010-12-22 17:34:53 +01001636#if defined(CONFIG_USER_ONLY)
1637 {
1638 struct sigaction act;
1639 sigfillset(&act.sa_mask);
1640 act.sa_handler = SIG_DFL;
1641 sigaction(SIGABRT, &act, NULL);
1642 }
1643#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001644 abort();
1645}
1646
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001647CPUArchState *cpu_copy(CPUOldState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001648{
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001649 CPUArchState *new_env = cpu_init(env->cpu_model_str);
1650 CPUArchState *next_cpu = new_env->next_cpu;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001651 int cpu_index = new_env->cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001652#if defined(TARGET_HAS_ICE)
1653 CPUBreakpoint *bp;
1654 CPUWatchpoint *wp;
1655#endif
1656
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001657 memcpy(new_env, env, sizeof(CPUOldState));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001658
1659 /* Preserve chaining and index. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001660 new_env->next_cpu = next_cpu;
1661 new_env->cpu_index = cpu_index;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001662
1663 /* Clone all break/watchpoints.
1664 Note: Once we support ptrace with hw-debug register access, make sure
1665 BP_CPU break/watchpoints are handled correctly on clone. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001666 QTAILQ_INIT(&env->breakpoints);
1667 QTAILQ_INIT(&env->watchpoints);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001668#if defined(TARGET_HAS_ICE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001669 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001670 cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
1671 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07001672 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001673 cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
1674 wp->flags, NULL);
1675 }
1676#endif
1677
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001678 return new_env;
1679}
1680
1681#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01001682static RAMBlock *qemu_get_ram_block(ram_addr_t addr)
1683{
1684 RAMBlock *block;
1685
1686 /* The list is protected by the iothread lock here. */
1687 block = ram_list.mru_block;
1688 if (block && addr - block->offset < block->length) {
1689 goto found;
1690 }
1691 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
1692 if (addr - block->offset < block->length) {
1693 goto found;
1694 }
1695 }
1696
1697 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
1698 abort();
1699
1700found:
1701 ram_list.mru_block = block;
1702 return block;
1703}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001704
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001705/* Note: start and end must be within the same ram block. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001706void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
1707 int dirty_flags)
1708{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01001709 CPUOldState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001710 unsigned long length, start1;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001711 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001712
1713 start &= TARGET_PAGE_MASK;
1714 end = TARGET_PAGE_ALIGN(end);
1715
1716 length = end - start;
1717 if (length == 0)
1718 return;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001719 cpu_physical_memory_mask_dirty_range(start, length, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001720
1721 /* we modify the TLB cache so that the dirty bit will be set again
1722 when accessing the range */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001723 start1 = (unsigned long)qemu_safe_ram_ptr(start);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001724 /* Chek that we don't span multiple blocks - this breaks the
1725 address comparisons below. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001726 if ((unsigned long)qemu_safe_ram_ptr(end - 1) - start1
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001727 != (end - 1) - start) {
1728 abort();
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001729 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001730
1731 for(env = first_cpu; env != NULL; env = env->next_cpu) {
1732 int mmu_idx;
1733 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1734 for(i = 0; i < CPU_TLB_SIZE; i++)
1735 tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
1736 start1, length);
1737 }
1738 }
1739}
1740
1741int cpu_physical_memory_set_dirty_tracking(int enable)
1742{
1743 in_migration = enable;
1744 if (kvm_enabled()) {
1745 return kvm_set_migration_log(enable);
1746 }
1747 return 0;
1748}
1749
1750int cpu_physical_memory_get_dirty_tracking(void)
1751{
1752 return in_migration;
1753}
1754
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001755int cpu_physical_sync_dirty_bitmap(hwaddr start_addr,
1756 hwaddr end_addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001757{
1758 int ret = 0;
1759
1760 if (kvm_enabled())
1761 ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
1762 return ret;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001763}
1764
1765static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1766{
1767 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001768 void *p;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001769
1770 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001771 p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
1772 + tlb_entry->addend);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02001773 ram_addr = qemu_ram_addr_from_host_nofail(p);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001774 if (!cpu_physical_memory_is_dirty(ram_addr)) {
1775 tlb_entry->addr_write |= TLB_NOTDIRTY;
1776 }
1777 }
1778}
1779
1780/* update the TLB according to the current state of the dirty bits */
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001781void cpu_tlb_update_dirty(CPUArchState *env)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001782{
1783 int i;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001784 int mmu_idx;
1785 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1786 for(i = 0; i < CPU_TLB_SIZE; i++)
1787 tlb_update_dirty(&env->tlb_table[mmu_idx][i]);
1788 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001789}
1790
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001791
1792#else
1793
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001794void tlb_flush(CPUArchState *env, int flush_global)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001795{
1796}
1797
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001798void tlb_flush_page(CPUArchState *env, target_ulong addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001799{
1800}
1801
David 'Digit' Turner4d6613c2014-01-22 18:19:00 +01001802int tlb_set_page_exec(CPUArchState *env, target_ulong vaddr,
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01001803 hwaddr paddr, int prot,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001804 int mmu_idx, int is_softmmu)
1805{
1806 return 0;
1807}
1808
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001809/*
1810 * Walks guest process memory "regions" one by one
1811 * and calls callback function 'fn' for each region.
1812 */
1813int walk_memory_regions(void *priv,
1814 int (*fn)(void *, unsigned long, unsigned long, unsigned long))
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001815{
1816 unsigned long start, end;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001817 PageDesc *p = NULL;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001818 int i, j, prot, prot1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001819 int rc = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001820
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001821 start = end = -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001822 prot = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001823
1824 for (i = 0; i <= L1_SIZE; i++) {
1825 p = (i < L1_SIZE) ? l1_map[i] : NULL;
1826 for (j = 0; j < L2_SIZE; j++) {
1827 prot1 = (p == NULL) ? 0 : p[j].flags;
1828 /*
1829 * "region" is one continuous chunk of memory
1830 * that has same protection flags set.
1831 */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001832 if (prot1 != prot) {
1833 end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
1834 if (start != -1) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001835 rc = (*fn)(priv, start, end, prot);
1836 /* callback can stop iteration by returning != 0 */
1837 if (rc != 0)
1838 return (rc);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001839 }
1840 if (prot1 != 0)
1841 start = end;
1842 else
1843 start = -1;
1844 prot = prot1;
1845 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001846 if (p == NULL)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001847 break;
1848 }
1849 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001850 return (rc);
1851}
1852
1853static int dump_region(void *priv, unsigned long start,
1854 unsigned long end, unsigned long prot)
1855{
1856 FILE *f = (FILE *)priv;
1857
1858 (void) fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
1859 start, end, end - start,
1860 ((prot & PAGE_READ) ? 'r' : '-'),
1861 ((prot & PAGE_WRITE) ? 'w' : '-'),
1862 ((prot & PAGE_EXEC) ? 'x' : '-'));
1863
1864 return (0);
1865}
1866
1867/* dump memory mappings */
1868void page_dump(FILE *f)
1869{
1870 (void) fprintf(f, "%-8s %-8s %-8s %s\n",
1871 "start", "end", "size", "prot");
1872 walk_memory_regions(f, dump_region);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001873}
1874
1875int page_get_flags(target_ulong address)
1876{
1877 PageDesc *p;
1878
1879 p = page_find(address >> TARGET_PAGE_BITS);
1880 if (!p)
1881 return 0;
1882 return p->flags;
1883}
1884
David 'Digit' Turner36411062010-12-22 17:34:53 +01001885/* Modify the flags of a page and invalidate the code if necessary.
1886 The flag PAGE_WRITE_ORG is positioned automatically depending
1887 on PAGE_WRITE. The mmap_lock should already be held. */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001888void page_set_flags(target_ulong start, target_ulong end, int flags)
1889{
1890 PageDesc *p;
1891 target_ulong addr;
1892
1893 /* mmap_lock should already be held. */
1894 start = start & TARGET_PAGE_MASK;
1895 end = TARGET_PAGE_ALIGN(end);
1896 if (flags & PAGE_WRITE)
1897 flags |= PAGE_WRITE_ORG;
1898 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1899 p = page_find_alloc(addr >> TARGET_PAGE_BITS);
1900 /* We may be called for host regions that are outside guest
1901 address space. */
1902 if (!p)
1903 return;
1904 /* if the write protection is set, then we invalidate the code
1905 inside */
1906 if (!(p->flags & PAGE_WRITE) &&
1907 (flags & PAGE_WRITE) &&
1908 p->first_tb) {
1909 tb_invalidate_phys_page(addr, 0, NULL);
1910 }
1911 p->flags = flags;
1912 }
1913}
1914
1915int page_check_range(target_ulong start, target_ulong len, int flags)
1916{
1917 PageDesc *p;
1918 target_ulong end;
1919 target_ulong addr;
1920
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001921 if (start + len < start)
1922 /* we've wrapped around */
1923 return -1;
1924
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001925 end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
1926 start = start & TARGET_PAGE_MASK;
1927
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001928 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1929 p = page_find(addr >> TARGET_PAGE_BITS);
1930 if( !p )
1931 return -1;
1932 if( !(p->flags & PAGE_VALID) )
1933 return -1;
1934
1935 if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
1936 return -1;
1937 if (flags & PAGE_WRITE) {
1938 if (!(p->flags & PAGE_WRITE_ORG))
1939 return -1;
1940 /* unprotect the page if it was put read-only because it
1941 contains translated code */
1942 if (!(p->flags & PAGE_WRITE)) {
1943 if (!page_unprotect(addr, 0, NULL))
1944 return -1;
1945 }
1946 return 0;
1947 }
1948 }
1949 return 0;
1950}
1951
1952/* called from signal handler: invalidate the code and unprotect the
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001953 page. Return TRUE if the fault was successfully handled. */
David 'Digit' Turner85c62202014-02-16 20:53:40 +01001954int page_unprotect(target_ulong address, uintptr_t pc, void *puc)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001955{
1956 unsigned int page_index, prot, pindex;
1957 PageDesc *p, *p1;
1958 target_ulong host_start, host_end, addr;
1959
1960 /* Technically this isn't safe inside a signal handler. However we
1961 know this only ever happens in a synchronous SEGV handler, so in
1962 practice it seems to be ok. */
1963 mmap_lock();
1964
1965 host_start = address & qemu_host_page_mask;
1966 page_index = host_start >> TARGET_PAGE_BITS;
1967 p1 = page_find(page_index);
1968 if (!p1) {
1969 mmap_unlock();
1970 return 0;
1971 }
1972 host_end = host_start + qemu_host_page_size;
1973 p = p1;
1974 prot = 0;
1975 for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
1976 prot |= p->flags;
1977 p++;
1978 }
1979 /* if the page was really writable, then we change its
1980 protection back to writable */
1981 if (prot & PAGE_WRITE_ORG) {
1982 pindex = (address - host_start) >> TARGET_PAGE_BITS;
1983 if (!(p1[pindex].flags & PAGE_WRITE)) {
1984 mprotect((void *)g2h(host_start), qemu_host_page_size,
1985 (prot & PAGE_BITS) | PAGE_WRITE);
1986 p1[pindex].flags |= PAGE_WRITE;
1987 /* and since the content will be modified, we must invalidate
1988 the corresponding translated code. */
1989 tb_invalidate_phys_page(address, pc, puc);
1990#ifdef DEBUG_TB_CHECK
1991 tb_invalidate_check(address);
1992#endif
1993 mmap_unlock();
1994 return 1;
1995 }
1996 }
1997 mmap_unlock();
1998 return 0;
1999}
2000
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002001static inline void tlb_set_dirty(CPUOldState *env,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002002 unsigned long addr, target_ulong vaddr)
2003{
2004}
2005#endif /* defined(CONFIG_USER_ONLY) */
2006
2007#if !defined(CONFIG_USER_ONLY)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002008
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002009static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002010 ram_addr_t memory, ram_addr_t region_offset);
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002011static void *subpage_init (hwaddr base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002012 ram_addr_t orig_memory, ram_addr_t region_offset);
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002013
2014static void *(*phys_mem_alloc)(size_t size) = qemu_anon_ram_alloc;
2015
2016/*
2017 * Set a custom physical guest memory alloator.
2018 * Accelerators with unusual needs may need this. Hopefully, we can
2019 * get rid of it eventually.
2020 */
2021void phys_mem_set_alloc(void *(*alloc)(size_t))
2022{
2023 phys_mem_alloc = alloc;
2024}
2025
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002026#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
2027 need_subpage) \
2028 do { \
2029 if (addr > start_addr) \
2030 start_addr2 = 0; \
2031 else { \
2032 start_addr2 = start_addr & ~TARGET_PAGE_MASK; \
2033 if (start_addr2 > 0) \
2034 need_subpage = 1; \
2035 } \
2036 \
2037 if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE) \
2038 end_addr2 = TARGET_PAGE_SIZE - 1; \
2039 else { \
2040 end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
2041 if (end_addr2 < TARGET_PAGE_SIZE - 1) \
2042 need_subpage = 1; \
2043 } \
2044 } while (0)
2045
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002046/* register physical memory.
2047 For RAM, 'size' must be a multiple of the target page size.
2048 If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002049 io memory page. The address used when calling the IO function is
2050 the offset from the start of the region, plus region_offset. Both
2051 start_addr and region_offset are rounded down to a page boundary
2052 before calculating this offset. This should not be a problem unless
2053 the low bits of start_addr and region_offset differ. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002054void cpu_register_physical_memory_log(hwaddr start_addr,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002055 ram_addr_t size,
2056 ram_addr_t phys_offset,
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002057 ram_addr_t region_offset,
2058 bool log_dirty)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002059{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002060 hwaddr addr, end_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002061 PhysPageDesc *p;
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01002062 CPUOldState *env;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002063 ram_addr_t orig_size = size;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002064 subpage_t *subpage;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002065
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002066 if (kvm_enabled())
2067 kvm_set_phys_mem(start_addr, size, phys_offset);
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002068#ifdef CONFIG_HAX
2069 if (hax_enabled())
2070 hax_set_phys_mem(start_addr, size, phys_offset);
2071#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002072
2073 if (phys_offset == IO_MEM_UNASSIGNED) {
2074 region_offset = start_addr;
2075 }
2076 region_offset &= TARGET_PAGE_MASK;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002077 size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002078 end_addr = start_addr + (hwaddr)size;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002079
2080 addr = start_addr;
2081 do {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002082 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2083 if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
2084 ram_addr_t orig_memory = p->phys_offset;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002085 hwaddr start_addr2, end_addr2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002086 int need_subpage = 0;
2087
2088 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2089 need_subpage);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002090 if (need_subpage) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002091 if (!(orig_memory & IO_MEM_SUBPAGE)) {
2092 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002093 &p->phys_offset, orig_memory,
2094 p->region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002095 } else {
2096 subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
2097 >> IO_MEM_SHIFT];
2098 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002099 subpage_register(subpage, start_addr2, end_addr2, phys_offset,
2100 region_offset);
2101 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002102 } else {
2103 p->phys_offset = phys_offset;
2104 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2105 (phys_offset & IO_MEM_ROMD))
2106 phys_offset += TARGET_PAGE_SIZE;
2107 }
2108 } else {
2109 p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2110 p->phys_offset = phys_offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002111 p->region_offset = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002112 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002113 (phys_offset & IO_MEM_ROMD)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002114 phys_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002115 } else {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002116 hwaddr start_addr2, end_addr2;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002117 int need_subpage = 0;
2118
2119 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2120 end_addr2, need_subpage);
2121
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002122 if (need_subpage) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002123 subpage = subpage_init((addr & TARGET_PAGE_MASK),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002124 &p->phys_offset, IO_MEM_UNASSIGNED,
2125 addr & TARGET_PAGE_MASK);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002126 subpage_register(subpage, start_addr2, end_addr2,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002127 phys_offset, region_offset);
2128 p->region_offset = 0;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002129 }
2130 }
2131 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002132 region_offset += TARGET_PAGE_SIZE;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002133 addr += TARGET_PAGE_SIZE;
2134 } while (addr != end_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002135
2136 /* since each CPU stores ram addresses in its TLB cache, we must
2137 reset the modified entries */
2138 /* XXX: slow ! */
2139 for(env = first_cpu; env != NULL; env = env->next_cpu) {
2140 tlb_flush(env, 1);
2141 }
2142}
2143
2144/* XXX: temporary until new memory mapping API */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002145ram_addr_t cpu_get_physical_page_desc(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002146{
2147 PhysPageDesc *p;
2148
2149 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2150 if (!p)
2151 return IO_MEM_UNASSIGNED;
2152 return p->phys_offset;
2153}
2154
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002155void qemu_register_coalesced_mmio(hwaddr addr, ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002156{
2157 if (kvm_enabled())
2158 kvm_coalesce_mmio_region(addr, size);
2159}
2160
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002161void qemu_unregister_coalesced_mmio(hwaddr addr, ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002162{
2163 if (kvm_enabled())
2164 kvm_uncoalesce_mmio_region(addr, size);
2165}
2166
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002167void qemu_mutex_lock_ramlist(void)
2168{
2169 qemu_mutex_lock(&ram_list.mutex);
2170}
2171
2172void qemu_mutex_unlock_ramlist(void)
2173{
2174 qemu_mutex_unlock(&ram_list.mutex);
2175}
2176
2177#if defined(__linux__) && !defined(CONFIG_ANDROID)
2178
2179#include <sys/vfs.h>
2180
2181#define HUGETLBFS_MAGIC 0x958458f6
2182
2183static long gethugepagesize(const char *path)
2184{
2185 struct statfs fs;
2186 int ret;
2187
2188 do {
2189 ret = statfs(path, &fs);
2190 } while (ret != 0 && errno == EINTR);
2191
2192 if (ret != 0) {
2193 perror(path);
2194 return 0;
2195 }
2196
2197 if (fs.f_type != HUGETLBFS_MAGIC)
2198 fprintf(stderr, "Warning: path not on HugeTLBFS: %s\n", path);
2199
2200 return fs.f_bsize;
2201}
2202
2203static sigjmp_buf sigjump;
2204
2205static void sigbus_handler(int signal)
2206{
2207 siglongjmp(sigjump, 1);
2208}
2209
2210static void *file_ram_alloc(RAMBlock *block,
2211 ram_addr_t memory,
2212 const char *path)
2213{
2214 char *filename;
2215 char *sanitized_name;
2216 char *c;
2217 void *area;
2218 int fd;
2219 unsigned long hpagesize;
2220
2221 hpagesize = gethugepagesize(path);
2222 if (!hpagesize) {
2223 return NULL;
2224 }
2225
2226 if (memory < hpagesize) {
2227 return NULL;
2228 }
2229
2230 if (kvm_enabled() && !kvm_has_sync_mmu()) {
2231 fprintf(stderr, "host lacks kvm mmu notifiers, -mem-path unsupported\n");
2232 return NULL;
2233 }
2234
2235 /* Make name safe to use with mkstemp by replacing '/' with '_'. */
2236 sanitized_name = g_strdup(block->mr->name);
2237 for (c = sanitized_name; *c != '\0'; c++) {
2238 if (*c == '/')
2239 *c = '_';
2240 }
2241
2242 filename = g_strdup_printf("%s/qemu_back_mem.%s.XXXXXX", path,
2243 sanitized_name);
2244 g_free(sanitized_name);
2245
2246 fd = mkstemp(filename);
2247 if (fd < 0) {
2248 perror("unable to create backing store for hugepages");
2249 g_free(filename);
2250 return NULL;
2251 }
2252 unlink(filename);
2253 g_free(filename);
2254
2255 memory = (memory+hpagesize-1) & ~(hpagesize-1);
2256
2257 /*
2258 * ftruncate is not supported by hugetlbfs in older
2259 * hosts, so don't bother bailing out on errors.
2260 * If anything goes wrong with it under other filesystems,
2261 * mmap will fail.
2262 */
2263 if (ftruncate(fd, memory))
2264 perror("ftruncate");
2265
2266 area = mmap(0, memory, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
2267 if (area == MAP_FAILED) {
2268 perror("file_ram_alloc: can't mmap RAM pages");
2269 close(fd);
2270 return (NULL);
2271 }
2272
2273 if (mem_prealloc) {
2274 int ret, i;
2275 struct sigaction act, oldact;
2276 sigset_t set, oldset;
2277
2278 memset(&act, 0, sizeof(act));
2279 act.sa_handler = &sigbus_handler;
2280 act.sa_flags = 0;
2281
2282 ret = sigaction(SIGBUS, &act, &oldact);
2283 if (ret) {
2284 perror("file_ram_alloc: failed to install signal handler");
2285 exit(1);
2286 }
2287
2288 /* unblock SIGBUS */
2289 sigemptyset(&set);
2290 sigaddset(&set, SIGBUS);
2291 pthread_sigmask(SIG_UNBLOCK, &set, &oldset);
2292
2293 if (sigsetjmp(sigjump, 1)) {
2294 fprintf(stderr, "file_ram_alloc: failed to preallocate pages\n");
2295 exit(1);
2296 }
2297
2298 /* MAP_POPULATE silently ignores failures */
2299 for (i = 0; i < (memory/hpagesize)-1; i++) {
2300 memset(area + (hpagesize*i), 0, 1);
2301 }
2302
2303 ret = sigaction(SIGBUS, &oldact, NULL);
2304 if (ret) {
2305 perror("file_ram_alloc: failed to reinstall signal handler");
2306 exit(1);
2307 }
2308
2309 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
2310 }
2311
2312 block->fd = fd;
2313 return area;
2314}
2315#else
2316static void *file_ram_alloc(RAMBlock *block,
2317 ram_addr_t memory,
2318 const char *path)
2319{
2320 fprintf(stderr, "-mem-path not supported on this host\n");
2321 exit(1);
2322}
2323#endif
2324
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002325static ram_addr_t find_ram_offset(ram_addr_t size)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002326{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002327 RAMBlock *block, *next_block;
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002328 ram_addr_t offset = RAM_ADDR_MAX, mingap = RAM_ADDR_MAX;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002329
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002330 assert(size != 0); /* it would hand out same offset multiple times */
2331
2332 if (QTAILQ_EMPTY(&ram_list.blocks))
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002333 return 0;
2334
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002335 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
2336 ram_addr_t end, next = RAM_ADDR_MAX;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002337
2338 end = block->offset + block->length;
2339
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002340 QTAILQ_FOREACH(next_block, &ram_list.blocks, next) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002341 if (next_block->offset >= end) {
2342 next = MIN(next, next_block->offset);
2343 }
2344 }
2345 if (next - end >= size && next - end < mingap) {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002346 offset = end;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002347 mingap = next - end;
2348 }
2349 }
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002350
2351 if (offset == RAM_ADDR_MAX) {
2352 fprintf(stderr, "Failed to find gap of requested size: %" PRIu64 "\n",
2353 (uint64_t)size);
2354 abort();
2355 }
2356
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002357 return offset;
2358}
2359
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002360ram_addr_t last_ram_offset(void)
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002361{
2362 RAMBlock *block;
2363 ram_addr_t last = 0;
2364
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002365 QTAILQ_FOREACH(block, &ram_list.blocks, next)
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002366 last = MAX(last, block->offset + block->length);
2367
2368 return last;
2369}
2370
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002371static void qemu_ram_setup_dump(void *addr, ram_addr_t size)
2372{
2373#ifndef CONFIG_ANDROID
2374 int ret;
2375
2376 /* Use MADV_DONTDUMP, if user doesn't want the guest memory in the core */
2377 if (!qemu_opt_get_bool(qemu_get_machine_opts(),
2378 "dump-guest-core", true)) {
2379 ret = qemu_madvise(addr, size, QEMU_MADV_DONTDUMP);
2380 if (ret) {
2381 perror("qemu_madvise");
2382 fprintf(stderr, "madvise doesn't support MADV_DONTDUMP, "
2383 "but dump_guest_core=off specified\n");
2384 }
2385 }
2386#endif // !CONFIG_ANDROID
2387}
2388
2389void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev)
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002390{
2391 RAMBlock *new_block, *block;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002392
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002393 new_block = NULL;
2394 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
2395 if (block->offset == addr) {
2396 new_block = block;
2397 break;
2398 }
2399 }
2400 assert(new_block);
2401 assert(!new_block->idstr[0]);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002402
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002403 if (dev) {
2404 char *id = qdev_get_dev_path(dev);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002405 if (id) {
2406 snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002407 g_free(id);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002408 }
2409 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002410 pstrcat(new_block->idstr, sizeof(new_block->idstr), name);
2411
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002412 /* This assumes the iothread lock is taken here too. */
2413 qemu_mutex_lock_ramlist();
2414 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
2415 if (block != new_block && !strcmp(block->idstr, new_block->idstr)) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002416 fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n",
2417 new_block->idstr);
2418 abort();
2419 }
2420 }
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002421 qemu_mutex_unlock_ramlist();
2422}
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002423
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002424static int memory_try_enable_merging(void *addr, size_t len)
2425{
2426#ifndef CONFIG_ANDROID
2427 if (!qemu_opt_get_bool(qemu_get_machine_opts(), "mem-merge", true)) {
2428 /* disabled by the user */
2429 return 0;
2430 }
2431
2432 return qemu_madvise(addr, len, QEMU_MADV_MERGEABLE);
2433#else // CONFIG_ANDROID
2434 return qemu_madvise(addr, len, QEMU_MADV_MERGEABLE);
2435#endif // CONFIG_ANDROID
2436}
2437
2438ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
2439 ram_addr_t size, void *host)
2440{
2441 RAMBlock *block, *new_block;
2442
2443 size = TARGET_PAGE_ALIGN(size);
2444 new_block = g_malloc0(sizeof(*new_block));
2445 new_block->fd = -1;
2446
2447 /* This assumes the iothread lock is taken here too. */
2448 qemu_mutex_lock_ramlist();
2449 //new_block->mr = mr;
2450 new_block->offset = find_ram_offset(size);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002451 if (host) {
2452 new_block->host = host;
2453 new_block->flags |= RAM_PREALLOC_MASK;
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002454 } else if (xen_enabled()) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002455 if (mem_path) {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002456 fprintf(stderr, "-mem-path not supported with Xen\n");
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002457 exit(1);
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002458 }
2459 //xen_ram_alloc(new_block->offset, size, mr);
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002460#ifdef CONFIG_HAX
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002461 } else if (hax_enabled()) {
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002462 /*
2463 * In HAX, qemu allocates the virtual address, and HAX kernel
2464 * module populates the region with physical memory. Currently
2465 * we don’t populate guest memory on demand, thus we should
2466 * make sure that sufficient amount of memory is available in
2467 * advance.
2468 */
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002469 int ret = hax_populate_ram(
2470 (uint64_t)(uintptr_t)new_block->host,
2471 (uint32_t)size);
2472 if (ret < 0) {
2473 fprintf(stderr, "Hax failed to populate ram\n");
2474 exit(-1);
Jun Nakajimaa381ef02011-12-17 19:13:25 -08002475 }
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002476#endif // CONFIG_HAX
2477 } else {
2478 if (mem_path) {
2479 if (phys_mem_alloc != qemu_anon_ram_alloc) {
2480 /*
2481 * file_ram_alloc() needs to allocate just like
2482 * phys_mem_alloc, but we haven't bothered to provide
2483 * a hook there.
2484 */
2485 fprintf(stderr,
2486 "-mem-path not supported with this accelerator\n");
2487 exit(1);
2488 }
2489 new_block->host = file_ram_alloc(new_block, size, mem_path);
2490 }
2491 if (!new_block->host) {
2492 new_block->host = phys_mem_alloc(size);
2493 if (!new_block->host) {
2494 fprintf(stderr, "Cannot set up guest memory '%s': %s\n",
2495 name, strerror(errno));
2496 exit(1);
2497 }
2498 memory_try_enable_merging(new_block->host, size);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002499 }
2500 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002501 new_block->length = size;
2502
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002503 /* Keep the list sorted from biggest to smallest block. */
2504 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
2505 if (block->length < new_block->length) {
2506 break;
2507 }
2508 }
2509 if (block) {
2510 QTAILQ_INSERT_BEFORE(block, new_block, next);
2511 } else {
2512 QTAILQ_INSERT_TAIL(&ram_list.blocks, new_block, next);
2513 }
2514 ram_list.mru_block = NULL;
2515
2516 ram_list.version++;
2517 qemu_mutex_unlock_ramlist();
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002518
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002519 ram_list.phys_dirty = g_realloc(ram_list.phys_dirty,
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002520 last_ram_offset() >> TARGET_PAGE_BITS);
2521 memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002522 0xff, size >> TARGET_PAGE_BITS);
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002523 //cpu_physical_memory_set_dirty_range(new_block->offset, size, 0xff);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002524
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002525 //qemu_ram_setup_dump(new_block->host, size);
2526 //qemu_madvise(new_block->host, size, QEMU_MADV_HUGEPAGE);
2527 //qemu_madvise(new_block->host, size, QEMU_MADV_DONTFORK);
2528
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002529 if (kvm_enabled())
2530 kvm_setup_guest_memory(new_block->host, size);
2531
2532 return new_block->offset;
2533}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002534
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002535ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)
2536{
2537 return qemu_ram_alloc_from_ptr(dev, name, size, NULL);
2538}
2539
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002540void qemu_ram_free_from_ptr(ram_addr_t addr)
2541{
2542 RAMBlock *block;
2543
2544 /* This assumes the iothread lock is taken here too. */
2545 qemu_mutex_lock_ramlist();
2546 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
2547 if (addr == block->offset) {
2548 QTAILQ_REMOVE(&ram_list.blocks, block, next);
2549 ram_list.mru_block = NULL;
2550 ram_list.version++;
2551 g_free(block);
2552 break;
2553 }
2554 }
2555 qemu_mutex_unlock_ramlist();
2556}
2557
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002558void qemu_ram_free(ram_addr_t addr)
2559{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002560 RAMBlock *block;
2561
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002562 /* This assumes the iothread lock is taken here too. */
2563 qemu_mutex_lock_ramlist();
2564 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002565 if (addr == block->offset) {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002566 QTAILQ_REMOVE(&ram_list.blocks, block, next);
2567 ram_list.mru_block = NULL;
2568 ram_list.version++;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002569 if (block->flags & RAM_PREALLOC_MASK) {
2570 ;
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002571 } else if (xen_enabled()) {
2572 //xen_invalidate_map_cache_entry(block->host);
2573#ifndef _WIN32
2574 } else if (block->fd >= 0) {
2575 munmap(block->host, block->length);
2576 close(block->fd);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002577#endif
2578 } else {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002579 qemu_anon_ram_free(block->host, block->length);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002580 }
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01002581 g_free(block);
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002582 break;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002583 }
2584 }
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002585 qemu_mutex_unlock_ramlist();
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002586
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002587}
2588
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002589#ifndef _WIN32
2590void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
2591{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002592 RAMBlock *block;
2593 ram_addr_t offset;
2594 int flags;
2595 void *area, *vaddr;
2596
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002597 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002598 offset = addr - block->offset;
2599 if (offset < block->length) {
2600 vaddr = block->host + offset;
2601 if (block->flags & RAM_PREALLOC_MASK) {
2602 ;
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002603 } else if (xen_enabled()) {
2604 abort();
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002605 } else {
2606 flags = MAP_FIXED;
2607 munmap(vaddr, length);
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002608 if (block->fd >= 0) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002609#ifdef MAP_POPULATE
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002610 flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED :
2611 MAP_PRIVATE;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002612#else
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002613 flags |= MAP_PRIVATE;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002614#endif
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002615 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2616 flags, block->fd, offset);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002617 } else {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002618 /*
2619 * Remap needs to match alloc. Accelerators that
2620 * set phys_mem_alloc never remap. If they did,
2621 * we'd need a remap hook here.
2622 */
2623 assert(phys_mem_alloc == qemu_anon_ram_alloc);
2624
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002625 flags |= MAP_PRIVATE | MAP_ANONYMOUS;
2626 area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
2627 flags, -1, 0);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002628 }
2629 if (area != vaddr) {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002630 fprintf(stderr, "Could not remap addr: "
2631 RAM_ADDR_FMT "@" RAM_ADDR_FMT "\n",
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002632 length, addr);
2633 exit(1);
2634 }
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002635 memory_try_enable_merging(vaddr, length);
2636 qemu_ram_setup_dump(vaddr, length);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002637 }
2638 return;
2639 }
2640 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002641}
2642#endif /* !_WIN32 */
2643
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002644/* Return a host pointer to ram allocated with qemu_ram_alloc.
2645 With the exception of the softmmu code in this file, this should
2646 only be used for local memory (e.g. video ram) that the device owns,
2647 and knows it isn't going to access beyond the end of the block.
2648
2649 It should not be used for general purpose DMA.
2650 Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
2651 */
2652void *qemu_get_ram_ptr(ram_addr_t addr)
2653{
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002654 RAMBlock *block = qemu_get_ram_block(addr);
2655#if 0
2656 if (xen_enabled()) {
2657 /* We need to check if the requested address is in the RAM
2658 * because we don't want to map the entire memory in QEMU.
2659 * In that case just map until the end of the page.
2660 */
2661 if (block->offset == 0) {
2662 return xen_map_cache(addr, 0, 0);
2663 } else if (block->host == NULL) {
2664 block->host =
2665 xen_map_cache(block->offset, block->length, 1);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002666 }
2667 }
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002668#endif
2669 return block->host + (addr - block->offset);
2670}
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002671
2672/* Return a host pointer to ram allocated with qemu_ram_alloc.
2673 * Same as qemu_get_ram_ptr but avoid reordering ramblocks.
2674 */
2675void *qemu_safe_ram_ptr(ram_addr_t addr)
2676{
2677 RAMBlock *block;
2678
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002679 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002680 if (addr - block->offset < block->length) {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002681 return block->host + (addr - block->offset);
2682 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002683 }
2684
2685 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2686 abort();
2687
2688 return NULL;
2689}
2690
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002691/* Some of the softmmu routines need to translate from a host pointer
2692 (typically a TLB entry) back to a ram offset. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002693int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr)
2694{
2695 RAMBlock *block;
2696 uint8_t *host = ptr;
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002697#if 0
2698 if (xen_enabled()) {
2699 *ram_addr = xen_ram_addr_from_mapcache(ptr);
2700 return qemu_get_ram_block(*ram_addr)->mr;
2701 }
2702#endif
2703 block = ram_list.mru_block;
2704 if (block && block->host && host - block->host < block->length) {
2705 goto found;
2706 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002707
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002708 QTAILQ_FOREACH(block, &ram_list.blocks, next) {
2709 /* This case append when the block is not mapped. */
2710 if (block->host == NULL) {
2711 continue;
2712 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002713 if (host - block->host < block->length) {
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002714 goto found;
2715 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002716 }
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002717
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002718 return -1;
David 'Digit' Turner0e8e7482014-02-17 20:25:52 +01002719
2720found:
2721 *ram_addr = block->offset + (host - block->host);
2722 return 0;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002723}
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002724
2725/* Some of the softmmu routines need to translate from a host pointer
2726 (typically a TLB entry) back to a ram offset. */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002727ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002728{
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002729 ram_addr_t ram_addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002730
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002731 if (qemu_ram_addr_from_host(ptr, &ram_addr)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002732 fprintf(stderr, "Bad ram pointer %p\n", ptr);
2733 abort();
2734 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002735 return ram_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002736}
2737
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002738static uint32_t unassigned_mem_readb(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002739{
2740#ifdef DEBUG_UNASSIGNED
2741 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2742#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002743#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002744 do_unassigned_access(addr, 0, 0, 0, 1);
2745#endif
2746 return 0;
2747}
2748
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002749static uint32_t unassigned_mem_readw(void *opaque, hwaddr addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002750{
2751#ifdef DEBUG_UNASSIGNED
2752 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2753#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002754#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002755 do_unassigned_access(addr, 0, 0, 0, 2);
2756#endif
2757 return 0;
2758}
2759
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002760static uint32_t unassigned_mem_readl(void *opaque, hwaddr addr)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002761{
2762#ifdef DEBUG_UNASSIGNED
2763 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2764#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002765#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002766 do_unassigned_access(addr, 0, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002767#endif
2768 return 0;
2769}
2770
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002771static void unassigned_mem_writeb(void *opaque, hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002772{
2773#ifdef DEBUG_UNASSIGNED
2774 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2775#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002776#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002777 do_unassigned_access(addr, 1, 0, 0, 1);
2778#endif
2779}
2780
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002781static void unassigned_mem_writew(void *opaque, hwaddr addr, uint32_t val)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002782{
2783#ifdef DEBUG_UNASSIGNED
2784 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2785#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002786#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002787 do_unassigned_access(addr, 1, 0, 0, 2);
2788#endif
2789}
2790
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002791static void unassigned_mem_writel(void *opaque, hwaddr addr, uint32_t val)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002792{
2793#ifdef DEBUG_UNASSIGNED
2794 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2795#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002796#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002797 do_unassigned_access(addr, 1, 0, 0, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002798#endif
2799}
2800
David 'Digit' Turner36411062010-12-22 17:34:53 +01002801static CPUReadMemoryFunc * const unassigned_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002802 unassigned_mem_readb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002803 unassigned_mem_readw,
2804 unassigned_mem_readl,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002805};
2806
David 'Digit' Turner36411062010-12-22 17:34:53 +01002807static CPUWriteMemoryFunc * const unassigned_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002808 unassigned_mem_writeb,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002809 unassigned_mem_writew,
2810 unassigned_mem_writel,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002811};
2812
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002813static void notdirty_mem_writeb(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002814 uint32_t val)
2815{
2816 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002817 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002818 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2819#if !defined(CONFIG_USER_ONLY)
2820 tb_invalidate_phys_page_fast(ram_addr, 1);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002821 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002822#endif
2823 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002824 stb_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002825 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002826 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002827 /* we remove the notdirty callback only if the code has been
2828 flushed */
2829 if (dirty_flags == 0xff)
2830 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2831}
2832
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002833static void notdirty_mem_writew(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002834 uint32_t val)
2835{
2836 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002837 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002838 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2839#if !defined(CONFIG_USER_ONLY)
2840 tb_invalidate_phys_page_fast(ram_addr, 2);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002841 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002842#endif
2843 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002844 stw_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002845 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002846 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002847 /* we remove the notdirty callback only if the code has been
2848 flushed */
2849 if (dirty_flags == 0xff)
2850 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2851}
2852
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002853static void notdirty_mem_writel(void *opaque, hwaddr ram_addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002854 uint32_t val)
2855{
2856 int dirty_flags;
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002857 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002858 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2859#if !defined(CONFIG_USER_ONLY)
2860 tb_invalidate_phys_page_fast(ram_addr, 4);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002861 dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002862#endif
2863 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002864 stl_p(qemu_get_ram_ptr(ram_addr), val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002865 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02002866 cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002867 /* we remove the notdirty callback only if the code has been
2868 flushed */
2869 if (dirty_flags == 0xff)
2870 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2871}
2872
David 'Digit' Turner36411062010-12-22 17:34:53 +01002873static CPUReadMemoryFunc * const error_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002874 NULL, /* never used */
2875 NULL, /* never used */
2876 NULL, /* never used */
2877};
2878
David 'Digit' Turner36411062010-12-22 17:34:53 +01002879static CPUWriteMemoryFunc * const notdirty_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002880 notdirty_mem_writeb,
2881 notdirty_mem_writew,
2882 notdirty_mem_writel,
2883};
2884
2885/* Generate a debug exception if a watchpoint has been hit. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002886static void check_watchpoint(int offset, int len_mask, int flags)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002887{
David 'Digit' Turner85c62202014-02-16 20:53:40 +01002888 CPUArchState *env = cpu_single_env;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002889 target_ulong pc, cs_base;
2890 TranslationBlock *tb;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002891 target_ulong vaddr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002892 CPUWatchpoint *wp;
2893 int cpu_flags;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002894
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002895 if (env->watchpoint_hit) {
2896 /* We re-entered the check after replacing the TB. Now raise
2897 * the debug interrupt so that is will trigger after the
2898 * current instruction. */
2899 cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2900 return;
2901 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002902 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07002903 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002904 if ((vaddr == (wp->vaddr & len_mask) ||
2905 (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
2906 wp->flags |= BP_WATCHPOINT_HIT;
2907 if (!env->watchpoint_hit) {
2908 env->watchpoint_hit = wp;
2909 tb = tb_find_pc(env->mem_io_pc);
2910 if (!tb) {
2911 cpu_abort(env, "check_watchpoint: could not find TB for "
2912 "pc=%p", (void *)env->mem_io_pc);
2913 }
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02002914 cpu_restore_state(tb, env, env->mem_io_pc);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002915 tb_phys_invalidate(tb, -1);
2916 if (wp->flags & BP_STOP_BEFORE_ACCESS) {
2917 env->exception_index = EXCP_DEBUG;
David 'Digit' Turner85c62202014-02-16 20:53:40 +01002918 cpu_loop_exit(env);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002919 } else {
2920 cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
2921 tb_gen_code(env, pc, cs_base, cpu_flags, 1);
David 'Digit' Turner85c62202014-02-16 20:53:40 +01002922 cpu_resume_from_signal(env, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002923 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002924 }
2925 } else {
2926 wp->flags &= ~BP_WATCHPOINT_HIT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002927 }
2928 }
2929}
2930
2931/* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
2932 so these check for a hit then pass through to the normal out-of-line
2933 phys routines. */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002934static uint32_t watch_mem_readb(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002935{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002936 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002937 return ldub_phys(addr);
2938}
2939
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002940static uint32_t watch_mem_readw(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002941{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002942 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002943 return lduw_phys(addr);
2944}
2945
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002946static uint32_t watch_mem_readl(void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002947{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002948 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002949 return ldl_phys(addr);
2950}
2951
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002952static void watch_mem_writeb(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, ~0x0, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002956 stb_phys(addr, val);
2957}
2958
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002959static void watch_mem_writew(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, ~0x1, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002963 stw_phys(addr, val);
2964}
2965
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002966static void watch_mem_writel(void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002967 uint32_t val)
2968{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002969 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002970 stl_phys(addr, val);
2971}
2972
David 'Digit' Turner36411062010-12-22 17:34:53 +01002973static CPUReadMemoryFunc * const watch_mem_read[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002974 watch_mem_readb,
2975 watch_mem_readw,
2976 watch_mem_readl,
2977};
2978
David 'Digit' Turner36411062010-12-22 17:34:53 +01002979static CPUWriteMemoryFunc * const watch_mem_write[3] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002980 watch_mem_writeb,
2981 watch_mem_writew,
2982 watch_mem_writel,
2983};
2984
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01002985static inline uint32_t subpage_readlen (subpage_t *mmio, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002986 unsigned int len)
2987{
2988 uint32_t ret;
2989 unsigned int idx;
2990
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002991 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002992#if defined(DEBUG_SUBPAGE)
2993 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
2994 mmio, len, addr, idx);
2995#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07002996 ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len],
2997 addr + mmio->region_offset[idx][0][len]);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08002998
2999 return ret;
3000}
3001
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003002static inline void subpage_writelen (subpage_t *mmio, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003003 uint32_t value, unsigned int len)
3004{
3005 unsigned int idx;
3006
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003007 idx = SUBPAGE_IDX(addr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003008#if defined(DEBUG_SUBPAGE)
3009 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
3010 mmio, len, addr, idx, value);
3011#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003012 (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len],
3013 addr + mmio->region_offset[idx][1][len],
3014 value);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003015}
3016
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003017static uint32_t subpage_readb (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003018{
3019#if defined(DEBUG_SUBPAGE)
3020 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
3021#endif
3022
3023 return subpage_readlen(opaque, addr, 0);
3024}
3025
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003026static void subpage_writeb (void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003027 uint32_t value)
3028{
3029#if defined(DEBUG_SUBPAGE)
3030 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
3031#endif
3032 subpage_writelen(opaque, addr, value, 0);
3033}
3034
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003035static uint32_t subpage_readw (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003036{
3037#if defined(DEBUG_SUBPAGE)
3038 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
3039#endif
3040
3041 return subpage_readlen(opaque, addr, 1);
3042}
3043
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003044static void subpage_writew (void *opaque, hwaddr addr,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003045 uint32_t value)
3046{
3047#if defined(DEBUG_SUBPAGE)
3048 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
3049#endif
3050 subpage_writelen(opaque, addr, value, 1);
3051}
3052
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003053static uint32_t subpage_readl (void *opaque, hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003054{
3055#if defined(DEBUG_SUBPAGE)
3056 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
3057#endif
3058
3059 return subpage_readlen(opaque, addr, 2);
3060}
3061
3062static void subpage_writel (void *opaque,
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003063 hwaddr addr, uint32_t value)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003064{
3065#if defined(DEBUG_SUBPAGE)
3066 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
3067#endif
3068 subpage_writelen(opaque, addr, value, 2);
3069}
3070
David 'Digit' Turner36411062010-12-22 17:34:53 +01003071static CPUReadMemoryFunc * const subpage_read[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003072 &subpage_readb,
3073 &subpage_readw,
3074 &subpage_readl,
3075};
3076
David 'Digit' Turner36411062010-12-22 17:34:53 +01003077static CPUWriteMemoryFunc * const subpage_write[] = {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003078 &subpage_writeb,
3079 &subpage_writew,
3080 &subpage_writel,
3081};
3082
3083static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003084 ram_addr_t memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003085{
3086 int idx, eidx;
3087 unsigned int i;
3088
3089 if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
3090 return -1;
3091 idx = SUBPAGE_IDX(start);
3092 eidx = SUBPAGE_IDX(end);
3093#if defined(DEBUG_SUBPAGE)
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003094 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 -08003095 mmio, start, end, idx, eidx, memory);
3096#endif
3097 memory >>= IO_MEM_SHIFT;
3098 for (; idx <= eidx; idx++) {
3099 for (i = 0; i < 4; i++) {
3100 if (io_mem_read[memory][i]) {
3101 mmio->mem_read[idx][i] = &io_mem_read[memory][i];
3102 mmio->opaque[idx][0][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003103 mmio->region_offset[idx][0][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003104 }
3105 if (io_mem_write[memory][i]) {
3106 mmio->mem_write[idx][i] = &io_mem_write[memory][i];
3107 mmio->opaque[idx][1][i] = io_mem_opaque[memory];
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003108 mmio->region_offset[idx][1][i] = region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003109 }
3110 }
3111 }
3112
3113 return 0;
3114}
3115
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003116static void *subpage_init (hwaddr base, ram_addr_t *phys,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003117 ram_addr_t orig_memory, ram_addr_t region_offset)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003118{
3119 subpage_t *mmio;
3120 int subpage_memory;
3121
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01003122 mmio = g_malloc0(sizeof(subpage_t));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003123
3124 mmio->base = base;
3125 subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003126#if defined(DEBUG_SUBPAGE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003127 printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
3128 mmio, base, TARGET_PAGE_SIZE, subpage_memory);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003129#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003130 *phys = subpage_memory | IO_MEM_SUBPAGE;
3131 subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
3132 region_offset);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003133
3134 return mmio;
3135}
3136
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003137static int get_free_io_mem_idx(void)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003138{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003139 int i;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003140
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003141 for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
3142 if (!io_mem_used[i]) {
3143 io_mem_used[i] = 1;
3144 return i;
3145 }
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003146 fprintf(stderr, "RAN out out io_mem_idx, max %d !\n", IO_MEM_NB_ENTRIES);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003147 return -1;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003148}
3149
3150/* mem_read and mem_write are arrays of functions containing the
3151 function to access byte (index 0), word (index 1) and dword (index
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003152 2). Functions can be omitted with a NULL function pointer.
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003153 If io_index is non zero, the corresponding io zone is
3154 modified. If it is zero, a new io zone is allocated. The return
3155 value can be used with cpu_register_physical_memory(). (-1) is
3156 returned if error. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003157static int cpu_register_io_memory_fixed(int io_index,
David 'Digit' Turner36411062010-12-22 17:34:53 +01003158 CPUReadMemoryFunc * const *mem_read,
3159 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003160 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003161{
3162 int i, subwidth = 0;
3163
3164 if (io_index <= 0) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003165 io_index = get_free_io_mem_idx();
3166 if (io_index == -1)
3167 return io_index;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003168 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003169 io_index >>= IO_MEM_SHIFT;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003170 if (io_index >= IO_MEM_NB_ENTRIES)
3171 return -1;
3172 }
3173
3174 for(i = 0;i < 3; i++) {
3175 if (!mem_read[i] || !mem_write[i])
3176 subwidth = IO_MEM_SUBWIDTH;
3177 io_mem_read[io_index][i] = mem_read[i];
3178 io_mem_write[io_index][i] = mem_write[i];
3179 }
3180 io_mem_opaque[io_index] = opaque;
3181 return (io_index << IO_MEM_SHIFT) | subwidth;
3182}
3183
David 'Digit' Turner36411062010-12-22 17:34:53 +01003184int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
3185 CPUWriteMemoryFunc * const *mem_write,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003186 void *opaque)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003187{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003188 return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003189}
3190
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003191void cpu_unregister_io_memory(int io_table_address)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003192{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003193 int i;
3194 int io_index = io_table_address >> IO_MEM_SHIFT;
3195
3196 for (i=0;i < 3; i++) {
3197 io_mem_read[io_index][i] = unassigned_mem_read[i];
3198 io_mem_write[io_index][i] = unassigned_mem_write[i];
3199 }
3200 io_mem_opaque[io_index] = NULL;
3201 io_mem_used[io_index] = 0;
3202}
3203
3204static void io_mem_init(void)
3205{
3206 int i;
3207
3208 cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read, unassigned_mem_write, NULL);
3209 cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read, unassigned_mem_write, NULL);
3210 cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read, notdirty_mem_write, NULL);
3211 for (i=0; i<5; i++)
3212 io_mem_used[i] = 1;
3213
3214 io_mem_watch = cpu_register_io_memory(watch_mem_read,
3215 watch_mem_write, NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003216}
3217
3218#endif /* !defined(CONFIG_USER_ONLY) */
3219
3220/* physical memory access (slow version, mainly for debug) */
3221#if defined(CONFIG_USER_ONLY)
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003222void cpu_physical_memory_rw(hwaddr addr, void *buf,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003223 int len, int is_write)
3224{
3225 int l, flags;
3226 target_ulong page;
3227 void * p;
3228
3229 while (len > 0) {
3230 page = addr & TARGET_PAGE_MASK;
3231 l = (page + TARGET_PAGE_SIZE) - addr;
3232 if (l > len)
3233 l = len;
3234 flags = page_get_flags(page);
3235 if (!(flags & PAGE_VALID))
3236 return;
3237 if (is_write) {
3238 if (!(flags & PAGE_WRITE))
3239 return;
3240 /* XXX: this code should not depend on lock_user */
3241 if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
3242 /* FIXME - should this return an error rather than just fail? */
3243 return;
3244 memcpy(p, buf, l);
3245 unlock_user(p, addr, l);
3246 } else {
3247 if (!(flags & PAGE_READ))
3248 return;
3249 /* XXX: this code should not depend on lock_user */
3250 if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
3251 /* FIXME - should this return an error rather than just fail? */
3252 return;
3253 memcpy(buf, p, l);
3254 unlock_user(p, addr, 0);
3255 }
3256 len -= l;
3257 buf += l;
3258 addr += l;
3259 }
3260}
3261
3262#else
Pete Delaneyd09d7662013-03-28 19:53:13 -07003263
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003264static void invalidate_and_set_dirty(hwaddr addr,
3265 hwaddr length)
Pete Delaneyd09d7662013-03-28 19:53:13 -07003266{
3267 if (!cpu_physical_memory_is_dirty(addr)) {
3268 /* invalidate code */
3269 tb_invalidate_phys_page_range(addr, addr + length, 0);
3270 /* set dirty bit */
3271 cpu_physical_memory_set_dirty_flags(addr, (0xff & ~CODE_DIRTY_FLAG));
3272 }
3273}
3274
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003275void cpu_physical_memory_rw(hwaddr addr, void *buf,
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003276 int len, int is_write)
3277{
3278 int l, io_index;
3279 uint8_t *ptr;
3280 uint32_t val;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003281 hwaddr page;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003282 unsigned long pd;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003283 uint8_t* buf8 = (uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003284 PhysPageDesc *p;
3285
3286 while (len > 0) {
3287 page = addr & TARGET_PAGE_MASK;
3288 l = (page + TARGET_PAGE_SIZE) - addr;
3289 if (l > len)
3290 l = len;
3291 p = phys_page_find(page >> TARGET_PAGE_BITS);
3292 if (!p) {
3293 pd = IO_MEM_UNASSIGNED;
3294 } else {
3295 pd = p->phys_offset;
3296 }
3297
3298 if (is_write) {
3299 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003300 hwaddr addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003301 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003302 if (p)
3303 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003304 /* XXX: could force cpu_single_env to NULL to avoid
3305 potential bugs */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003306 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003307 /* 32 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003308 val = ldl_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003309 io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003310 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003311 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003312 /* 16 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003313 val = lduw_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003314 io_mem_write[io_index][1](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003315 l = 2;
3316 } else {
3317 /* 8 bit write access */
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003318 val = ldub_p(buf8);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003319 io_mem_write[io_index][0](io_mem_opaque[io_index], addr1, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003320 l = 1;
3321 }
3322 } else {
3323 unsigned long addr1;
3324 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3325 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003326 ptr = qemu_get_ram_ptr(addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003327 memcpy(ptr, buf8, l);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003328 invalidate_and_set_dirty(addr1, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003329 }
3330 } else {
3331 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3332 !(pd & IO_MEM_ROMD)) {
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003333 hwaddr addr1 = addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003334 /* I/O case */
3335 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003336 if (p)
3337 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3338 if (l >= 4 && ((addr1 & 3) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003339 /* 32 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003340 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003341 stl_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003342 l = 4;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003343 } else if (l >= 2 && ((addr1 & 1) == 0)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003344 /* 16 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003345 val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003346 stw_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003347 l = 2;
3348 } else {
3349 /* 8 bit read access */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003350 val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003351 stb_p(buf8, val);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003352 l = 1;
3353 }
3354 } else {
3355 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003356 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003357 (addr & ~TARGET_PAGE_MASK);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003358 memcpy(buf8, ptr, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003359 }
3360 }
3361 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003362 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003363 addr += l;
3364 }
3365}
3366
3367/* used for ROM loading : can write in RAM and ROM */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003368void cpu_physical_memory_write_rom(hwaddr addr,
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003369 const void *buf, int len)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003370{
3371 int l;
3372 uint8_t *ptr;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003373 hwaddr page;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003374 unsigned long pd;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003375 const uint8_t* buf8 = (const uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003376 PhysPageDesc *p;
3377
3378 while (len > 0) {
3379 page = addr & TARGET_PAGE_MASK;
3380 l = (page + TARGET_PAGE_SIZE) - addr;
3381 if (l > len)
3382 l = len;
3383 p = phys_page_find(page >> TARGET_PAGE_BITS);
3384 if (!p) {
3385 pd = IO_MEM_UNASSIGNED;
3386 } else {
3387 pd = p->phys_offset;
3388 }
3389
3390 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
3391 (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
3392 !(pd & IO_MEM_ROMD)) {
3393 /* do nothing */
3394 } else {
3395 unsigned long addr1;
3396 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3397 /* ROM/RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003398 ptr = qemu_get_ram_ptr(addr1);
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003399 memcpy(ptr, buf8, l);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003400 invalidate_and_set_dirty(addr1, l);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003401 }
3402 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003403 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003404 addr += l;
3405 }
3406}
3407
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003408typedef struct {
3409 void *buffer;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003410 hwaddr addr;
3411 hwaddr len;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003412} BounceBuffer;
3413
3414static BounceBuffer bounce;
3415
3416typedef struct MapClient {
3417 void *opaque;
3418 void (*callback)(void *opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003419 QLIST_ENTRY(MapClient) link;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003420} MapClient;
3421
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003422static QLIST_HEAD(map_client_list, MapClient) map_client_list
3423 = QLIST_HEAD_INITIALIZER(map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003424
3425void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
3426{
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01003427 MapClient *client = g_malloc(sizeof(*client));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003428
3429 client->opaque = opaque;
3430 client->callback = callback;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003431 QLIST_INSERT_HEAD(&map_client_list, client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003432 return client;
3433}
3434
3435void cpu_unregister_map_client(void *_client)
3436{
3437 MapClient *client = (MapClient *)_client;
3438
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003439 QLIST_REMOVE(client, link);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +01003440 g_free(client);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003441}
3442
3443static void cpu_notify_map_clients(void)
3444{
3445 MapClient *client;
3446
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003447 while (!QLIST_EMPTY(&map_client_list)) {
3448 client = QLIST_FIRST(&map_client_list);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003449 client->callback(client->opaque);
David 'Digit' Turnera5d41202010-05-10 18:37:10 -07003450 QLIST_REMOVE(client, link);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003451 }
3452}
3453
3454/* Map a physical memory region into a host virtual address.
3455 * May map a subset of the requested range, given by and returned in *plen.
3456 * May return NULL if resources needed to perform the mapping are exhausted.
3457 * Use only for reads OR writes - not for read-modify-write operations.
3458 * Use cpu_register_map_client() to know when retrying the map operation is
3459 * likely to succeed.
3460 */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003461void *cpu_physical_memory_map(hwaddr addr,
3462 hwaddr *plen,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003463 int is_write)
3464{
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003465 hwaddr len = *plen;
3466 hwaddr done = 0;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003467 int l;
3468 uint8_t *ret = NULL;
3469 uint8_t *ptr;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003470 hwaddr page;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003471 unsigned long pd;
3472 PhysPageDesc *p;
3473 unsigned long addr1;
3474
3475 while (len > 0) {
3476 page = addr & TARGET_PAGE_MASK;
3477 l = (page + TARGET_PAGE_SIZE) - addr;
3478 if (l > len)
3479 l = len;
3480 p = phys_page_find(page >> TARGET_PAGE_BITS);
3481 if (!p) {
3482 pd = IO_MEM_UNASSIGNED;
3483 } else {
3484 pd = p->phys_offset;
3485 }
3486
3487 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3488 if (done || bounce.buffer) {
3489 break;
3490 }
3491 bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
3492 bounce.addr = addr;
3493 bounce.len = l;
3494 if (!is_write) {
3495 cpu_physical_memory_rw(addr, bounce.buffer, l, 0);
3496 }
3497 ptr = bounce.buffer;
3498 } else {
3499 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3500 ptr = qemu_get_ram_ptr(addr1);
3501 }
3502 if (!done) {
3503 ret = ptr;
3504 } else if (ret + done != ptr) {
3505 break;
3506 }
3507
3508 len -= l;
3509 addr += l;
3510 done += l;
3511 }
3512 *plen = done;
3513 return ret;
3514}
3515
3516/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
3517 * Will also mark the memory as dirty if is_write == 1. access_len gives
3518 * the amount of memory that was actually read or written by the caller.
3519 */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003520void cpu_physical_memory_unmap(void *buffer, hwaddr len,
3521 int is_write, hwaddr access_len)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003522{
3523 if (buffer != bounce.buffer) {
3524 if (is_write) {
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003525 ram_addr_t addr1 = qemu_ram_addr_from_host_nofail(buffer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003526 while (access_len) {
3527 unsigned l;
3528 l = TARGET_PAGE_SIZE;
3529 if (l > access_len)
3530 l = access_len;
Pete Delaneyd09d7662013-03-28 19:53:13 -07003531 invalidate_and_set_dirty(addr1, l);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003532 addr1 += l;
3533 access_len -= l;
3534 }
3535 }
3536 return;
3537 }
3538 if (is_write) {
3539 cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
3540 }
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003541 qemu_vfree(bounce.buffer);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003542 bounce.buffer = NULL;
3543 cpu_notify_map_clients();
3544}
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003545
3546/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003547uint32_t ldl_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003548{
3549 int io_index;
3550 uint8_t *ptr;
3551 uint32_t val;
3552 unsigned long pd;
3553 PhysPageDesc *p;
3554
3555 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3556 if (!p) {
3557 pd = IO_MEM_UNASSIGNED;
3558 } else {
3559 pd = p->phys_offset;
3560 }
3561
3562 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3563 !(pd & IO_MEM_ROMD)) {
3564 /* I/O case */
3565 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003566 if (p)
3567 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003568 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3569 } else {
3570 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003571 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003572 (addr & ~TARGET_PAGE_MASK);
3573 val = ldl_p(ptr);
3574 }
3575 return val;
3576}
3577
3578/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003579uint64_t ldq_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003580{
3581 int io_index;
3582 uint8_t *ptr;
3583 uint64_t val;
3584 unsigned long pd;
3585 PhysPageDesc *p;
3586
3587 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3588 if (!p) {
3589 pd = IO_MEM_UNASSIGNED;
3590 } else {
3591 pd = p->phys_offset;
3592 }
3593
3594 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3595 !(pd & IO_MEM_ROMD)) {
3596 /* I/O case */
3597 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003598 if (p)
3599 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003600#ifdef TARGET_WORDS_BIGENDIAN
3601 val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
3602 val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
3603#else
3604 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3605 val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
3606#endif
3607 } else {
3608 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003609 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003610 (addr & ~TARGET_PAGE_MASK);
3611 val = ldq_p(ptr);
3612 }
3613 return val;
3614}
3615
3616/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003617uint32_t ldub_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003618{
3619 uint8_t val;
3620 cpu_physical_memory_read(addr, &val, 1);
3621 return val;
3622}
3623
3624/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003625uint32_t lduw_phys(hwaddr addr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003626{
3627 uint16_t val;
3628 cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
3629 return tswap16(val);
3630}
3631
3632/* warning: addr must be aligned. The ram page is not masked as dirty
3633 and the code inside is not invalidated. It is useful if the dirty
3634 bits are used to track modified PTEs */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003635void stl_phys_notdirty(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003636{
3637 int io_index;
3638 uint8_t *ptr;
3639 unsigned long pd;
3640 PhysPageDesc *p;
3641
3642 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3643 if (!p) {
3644 pd = IO_MEM_UNASSIGNED;
3645 } else {
3646 pd = p->phys_offset;
3647 }
3648
3649 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3650 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003651 if (p)
3652 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003653 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3654 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003655 unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3656 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003657 stl_p(ptr, val);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003658
3659 if (unlikely(in_migration)) {
3660 if (!cpu_physical_memory_is_dirty(addr1)) {
3661 /* invalidate code */
3662 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3663 /* set dirty bit */
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003664 cpu_physical_memory_set_dirty_flags(
3665 addr1, (0xff & ~CODE_DIRTY_FLAG));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003666 }
3667 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003668 }
3669}
3670
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003671void stq_phys_notdirty(hwaddr addr, uint64_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003672{
3673 int io_index;
3674 uint8_t *ptr;
3675 unsigned long pd;
3676 PhysPageDesc *p;
3677
3678 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3679 if (!p) {
3680 pd = IO_MEM_UNASSIGNED;
3681 } else {
3682 pd = p->phys_offset;
3683 }
3684
3685 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3686 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003687 if (p)
3688 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003689#ifdef TARGET_WORDS_BIGENDIAN
3690 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
3691 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
3692#else
3693 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3694 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
3695#endif
3696 } else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003697 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003698 (addr & ~TARGET_PAGE_MASK);
3699 stq_p(ptr, val);
3700 }
3701}
3702
3703/* warning: addr must be aligned */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003704void stl_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003705{
3706 int io_index;
3707 uint8_t *ptr;
3708 unsigned long pd;
3709 PhysPageDesc *p;
3710
3711 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3712 if (!p) {
3713 pd = IO_MEM_UNASSIGNED;
3714 } else {
3715 pd = p->phys_offset;
3716 }
3717
3718 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3719 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003720 if (p)
3721 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003722 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3723 } else {
3724 unsigned long addr1;
3725 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3726 /* RAM case */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003727 ptr = qemu_get_ram_ptr(addr1);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003728 stl_p(ptr, val);
Pete Delaneyd09d7662013-03-28 19:53:13 -07003729 invalidate_and_set_dirty(addr1, 4);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003730 }
3731}
3732
3733/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003734void stb_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003735{
3736 uint8_t v = val;
3737 cpu_physical_memory_write(addr, &v, 1);
3738}
3739
3740/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003741void stw_phys(hwaddr addr, uint32_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003742{
3743 uint16_t v = tswap16(val);
3744 cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
3745}
3746
3747/* XXX: optimize */
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003748void stq_phys(hwaddr addr, uint64_t val)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003749{
3750 val = tswap64(val);
3751 cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
3752}
3753
3754#endif
3755
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003756/* virtual memory access for debug (includes writing to ROM) */
David 'Digit' Turnere2678e12014-01-16 15:56:43 +01003757int cpu_memory_rw_debug(CPUOldState *env, target_ulong addr,
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003758 void *buf, int len, int is_write)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003759{
3760 int l;
David 'Digit' Turnerbcde1092014-01-09 23:19:19 +01003761 hwaddr phys_addr;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003762 target_ulong page;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003763 uint8_t* buf8 = (uint8_t*)buf;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003764
3765 while (len > 0) {
3766 page = addr & TARGET_PAGE_MASK;
3767 phys_addr = cpu_get_phys_page_debug(env, page);
3768 /* if no physical page mapped, return an error */
3769 if (phys_addr == -1)
3770 return -1;
3771 l = (page + TARGET_PAGE_SIZE) - addr;
3772 if (l > len)
3773 l = len;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003774 phys_addr += (addr & ~TARGET_PAGE_MASK);
3775#if !defined(CONFIG_USER_ONLY)
3776 if (is_write)
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003777 cpu_physical_memory_write_rom(phys_addr, buf8, l);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07003778 else
3779#endif
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003780 cpu_physical_memory_rw(phys_addr, buf8, l, is_write);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003781 len -= l;
David 'Digit' Turnera2c14f92014-02-04 01:02:30 +01003782 buf8 += l;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003783 addr += l;
3784 }
3785 return 0;
3786}
3787
3788/* in deterministic execution mode, instructions doing device I/Os
3789 must be at the end of the TB */
David 'Digit' Turner85c62202014-02-16 20:53:40 +01003790void cpu_io_recompile(CPUArchState *env, uintptr_t retaddr)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003791{
3792 TranslationBlock *tb;
3793 uint32_t n, cflags;
3794 target_ulong pc, cs_base;
3795 uint64_t flags;
3796
David 'Digit' Turner85c62202014-02-16 20:53:40 +01003797 tb = tb_find_pc(retaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003798 if (!tb) {
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02003799 cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p",
David 'Digit' Turner85c62202014-02-16 20:53:40 +01003800 (void*)retaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003801 }
3802 n = env->icount_decr.u16.low + tb->icount;
David 'Digit' Turner85c62202014-02-16 20:53:40 +01003803 cpu_restore_state(tb, env, retaddr);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003804 /* Calculate how many instructions had been executed before the fault
3805 occurred. */
3806 n = n - env->icount_decr.u16.low;
3807 /* Generate a new TB ending on the I/O insn. */
3808 n++;
3809 /* On MIPS and SH, delay slot instructions can only be restarted if
3810 they were already the first instruction in the TB. If this is not
3811 the first instruction in a TB then re-execute the preceding
3812 branch. */
3813#if defined(TARGET_MIPS)
3814 if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) {
3815 env->active_tc.PC -= 4;
3816 env->icount_decr.u16.low++;
3817 env->hflags &= ~MIPS_HFLAG_BMASK;
3818 }
3819#elif defined(TARGET_SH4)
3820 if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
3821 && n > 1) {
3822 env->pc -= 2;
3823 env->icount_decr.u16.low++;
3824 env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
3825 }
3826#endif
3827 /* This should never happen. */
3828 if (n > CF_COUNT_MASK)
3829 cpu_abort(env, "TB too big during recompile");
3830
3831 cflags = n | CF_LAST_IO;
3832 pc = tb->pc;
3833 cs_base = tb->cs_base;
3834 flags = tb->flags;
3835 tb_phys_invalidate(tb, -1);
3836 /* FIXME: In theory this could raise an exception. In practice
3837 we have already translated the block once so it's probably ok. */
3838 tb_gen_code(env, pc, cs_base, flags, cflags);
3839 /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
3840 the first in the TB) then we end up generating a whole new TB and
3841 repeating the fault, which is horribly inefficient.
3842 Better would be to execute just this insn uncached, or generate a
3843 second new TB. */
3844 cpu_resume_from_signal(env, NULL);
3845}
3846
David 'Digit' Turner36411062010-12-22 17:34:53 +01003847#if !defined(CONFIG_USER_ONLY)
3848
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003849void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003850{
3851 int i, target_code_size, max_target_code_size;
3852 int direct_jmp_count, direct_jmp2_count, cross_page;
3853 TranslationBlock *tb;
3854
3855 target_code_size = 0;
3856 max_target_code_size = 0;
3857 cross_page = 0;
3858 direct_jmp_count = 0;
3859 direct_jmp2_count = 0;
3860 for(i = 0; i < nb_tbs; i++) {
3861 tb = &tbs[i];
3862 target_code_size += tb->size;
3863 if (tb->size > max_target_code_size)
3864 max_target_code_size = tb->size;
3865 if (tb->page_addr[1] != -1)
3866 cross_page++;
3867 if (tb->tb_next_offset[0] != 0xffff) {
3868 direct_jmp_count++;
3869 if (tb->tb_next_offset[1] != 0xffff) {
3870 direct_jmp2_count++;
3871 }
3872 }
3873 }
3874 /* XXX: avoid using doubles ? */
3875 cpu_fprintf(f, "Translation buffer state:\n");
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003876 cpu_fprintf(f, "gen code size %td/%ld\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003877 code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size);
David 'Digit' Turnerf645f7d2011-05-11 00:44:05 +02003878 cpu_fprintf(f, "TB count %d/%d\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003879 nb_tbs, code_gen_max_blocks);
3880 cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
3881 nb_tbs ? target_code_size / nb_tbs : 0,
3882 max_target_code_size);
David 'Digit' Turner280afa02011-05-11 17:37:44 +02003883 cpu_fprintf(f, "TB avg host size %td bytes (expansion ratio: %0.1f)\n",
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003884 nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
3885 target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
3886 cpu_fprintf(f, "cross page TB count %d (%d%%)\n",
3887 cross_page,
3888 nb_tbs ? (cross_page * 100) / nb_tbs : 0);
3889 cpu_fprintf(f, "direct jump count %d (%d%%) (2 jumps=%d %d%%)\n",
3890 direct_jmp_count,
3891 nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
3892 direct_jmp2_count,
3893 nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
3894 cpu_fprintf(f, "\nStatistics:\n");
3895 cpu_fprintf(f, "TB flush count %d\n", tb_flush_count);
3896 cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
3897 cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count);
3898 tcg_dump_info(f, cpu_fprintf);
3899}
3900
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08003901#endif