exec.c revision 993c76af63e99635bda98e2fa1ff71ee842107ba
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * virtual page mapping and translated block handling
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Copyright (c) 2003 Fabrice Bellard
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This library is free software; you can redistribute it and/or
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * modify it under the terms of the GNU Lesser General Public
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * License as published by the Free Software Foundation; either
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * version 2 of the License, or (at your option) any later version.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This library is distributed in the hope that it will be useful,
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * but WITHOUT ANY WARRANTY; without even the implied warranty of
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Lesser General Public License for more details.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * You should have received a copy of the GNU Lesser General Public
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * License along with this library; if not, see <http://www.gnu.org/licenses/>.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * a choice of LGPL license versions is made available with the language indicating
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * that LGPLv2 or any later version may be used, or where a choice of which version
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * of the LGPL is applied is otherwise unspecified.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#else /* VBOX */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# include <VBox/vmm/pgm.h> /* PGM_DYNAMIC_RAM_ALLOC */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* !VBOX */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define sigqueue sigqueue_freebsd /* avoid redefinition */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync//#define DEBUG_TB_INVALIDATE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync//#define DEBUG_FLUSH
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync//#define DEBUG_TLB
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync//#define DEBUG_UNASSIGNED
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* make various TB consistency checks */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync//#define DEBUG_TB_CHECK
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync//#define DEBUG_TLB_CHECK
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync//#define DEBUG_IOPORT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync//#define DEBUG_SUBPAGE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* TB consistency checks only implemented for usermode emulation. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncTranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* any access to the tbs or the page table must use this lock */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* The prologue must be reachable with a direct jump. ARM and Sparc64
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync have limited branch ranges (possibly also PPC) so place it in a
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync section close to code segment. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Maximum alignment for Win32 is 16. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#else /* VBOX */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic unsigned long code_gen_buffer_size;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* threshold to flush the translated code buffer */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic unsigned long code_gen_buffer_max_size;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# endif /* !VBOX */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list) };
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* current CPU in the current thread. It is only valid inside
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync cpu_exec() */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* 0 = Do not count executed instructions.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync 1 = Precise instruction counting.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync 2 = Adaptive rate instruction counting. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Current instruction counter. While executing translated code this may
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync include some instructions that have not yet been executed. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsynctypedef struct PageDesc {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* list of TBs intersecting this ram page */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* in order to optimize self modifying code, we count the number
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync of lookups we do to a given page to use a bitmap */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync unsigned long flags;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* In system mode we want L1_MAP to be based on ram offsets,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync while in user mode we want it to be based on virtual addresses. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# define L1_MAP_ADDR_SPACE_BITS TARGET_PHYS_ADDR_SPACE_BITS
6565c2fb4f10f47bcb5436630d2dc35e5a4f28e2vboxsync# define L1_MAP_ADDR_SPACE_BITS TARGET_VIRT_ADDR_SPACE_BITS
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Size of the L2 (and L3, etc) page tables. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* The bits remaining after N lower levels of page tables. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ((TARGET_PHYS_ADDR_SPACE_BITS - TARGET_PAGE_BITS) % L2_BITS)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ((L1_MAP_ADDR_SPACE_BITS - TARGET_PAGE_BITS) % L2_BITS)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Size of the L1 page table. Avoid silly small sizes. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define P_L1_SIZE ((target_phys_addr_t)1 << P_L1_BITS)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define P_L1_SHIFT (TARGET_PHYS_ADDR_SPACE_BITS - TARGET_PAGE_BITS - P_L1_BITS)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define V_L1_SHIFT (L1_MAP_ADDR_SPACE_BITS - TARGET_PAGE_BITS - V_L1_BITS)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* This is a multi-level map on the virtual address space.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync The bottom level has pointers to PageDesc. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsynctypedef struct PhysPageDesc {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* offset in host memory of the page + io_index in the low bits */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* This is a multi-level map on the physical address space.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync The bottom level has pointers to PhysPageDesc. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic void io_mem_init(void);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* io memory support */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncCPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncCPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* log support */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* !VBOX */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int log_append = 0;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* !VBOX */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* statistics */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#else /* VBOX - Resettable U32 stats, see VBoxRecompiler.c. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#else /* VBOX */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTMEM_PROT_EXEC | RTMEM_PROT_READ | RTMEM_PROT_WRITE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic void page_init(void)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* NOTE: we can always suppose that qemu_host_page_size >=
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync TARGET_PAGE_SIZE */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTMemProtect(code_gen_buffer, sizeof(code_gen_buffer),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTMEM_PROT_EXEC | RTMEM_PROT_READ | RTMEM_PROT_WRITE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#else /* !VBOX */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* !VBOX */
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync while ((1 << qemu_host_page_bits) < VBOX_ONLY((int))qemu_host_page_size)
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync#ifndef VBOX /* We use other means to set reserved bit on our pages */
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync#if defined(CONFIG_BSD) && defined(CONFIG_USER_ONLY)
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync for (i = 0; i < cnt; i++) {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync n = fscanf (f, "%lx-%lx %*[^\n]\n", &startaddr, &endaddr);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync } while (!feof(f));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* !VBOX */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic PageDesc *page_find_alloc(tb_page_addr_t index, int alloc)
1bc5a31ae6d57c2b4731a23205f3958678b60193vboxsync /* We can't use qemu_malloc because it may recurse into a locked mutex. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync } while (0)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Level 1. Always allocated. */
1bc5a31ae6d57c2b4731a23205f3958678b60193vboxsync lp = l1_map + ((index >> V_L1_SHIFT) & (V_L1_SIZE - 1));
1bc5a31ae6d57c2b4731a23205f3958678b60193vboxsync /* Level 2..N-1. */
1bc5a31ae6d57c2b4731a23205f3958678b60193vboxsync void **p = *lp;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (p == NULL) {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync lp = p + ((index >> (i * L2_BITS)) & (L2_SIZE - 1));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic inline PageDesc *page_find(tb_page_addr_t index)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
6565c2fb4f10f47bcb5436630d2dc35e5a4f28e2vboxsync /* Level 1. Always allocated. */
6565c2fb4f10f47bcb5436630d2dc35e5a4f28e2vboxsync lp = l1_phys_map + ((index >> P_L1_SHIFT) & (P_L1_SIZE - 1));
6565c2fb4f10f47bcb5436630d2dc35e5a4f28e2vboxsync /* Level 2..N-1. */
6565c2fb4f10f47bcb5436630d2dc35e5a4f28e2vboxsync void **p = *lp;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (p == NULL) {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync lp = p + ((index >> (i * L2_BITS)) & (L2_SIZE - 1));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *lp = pd = qemu_malloc(sizeof(PhysPageDesc) * L2_SIZE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (i = 0; i < L2_SIZE; i++) {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pd[i].region_offset = (index + i) << TARGET_PAGE_BITS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define mmap_lock() do { } while(0)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define mmap_unlock() do { } while(0)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#ifdef VBOX /* We don't need such huge codegen buffer size, as execute
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync most of the code in raw or hwacc mode. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define DEFAULT_CODE_GEN_BUFFER_SIZE (8 * 1024 * 1024)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#else /* !VBOX */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define DEFAULT_CODE_GEN_BUFFER_SIZE (32 * 1024 * 1024)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* !VBOX */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Currently it is not recommended to allocate big chunks of data in
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync user mode. It will change when a dedicated libc will be used */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#if defined(VBOX) && defined(USE_STATIC_CODE_GEN_BUFFER)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE]
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* We cannot use phys_ram_size here, as it's 0 now,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * it only gets initialized once RAM registration callback
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * (REMR3NotifyPhysRamRegister()) called.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# else /* !VBOX */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* in user mode, phys_ram_size is not meaningful */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* XXX: needs adjustments */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync code_gen_buffer_size = (unsigned long)(ram_size / 4);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# endif /* !VBOX */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* The code gen buffer location may have constraints depending on
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync the host cpu and OS */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync code_gen_buffer = RTMemExecAlloc(code_gen_buffer_size);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogRel(("REM: failed allocate codegen buffer %lld\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# else /* !VBOX */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Cannot map more than that */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync // Map the buffer below 2G, so we can use direct calls and branches
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Map the buffer below 32M, so we can use direct calls and branches */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Map the buffer so that we can use direct calls and branches. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* We have a +- 4GB range on the branches; leave some slop. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (code_gen_buffer_size > (3ul * 1024 * 1024 * 1024)) {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync code_gen_buffer = mmap(start, code_gen_buffer_size,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fprintf(stderr, "Could not allocate dynamic translator buffer\n");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
int flags;
#if defined(__x86_64__)
cpu_gen_init();
page_init();
#if !defined(CONFIG_USER_ONLY)
io_mem_init();
#ifndef VBOX
while (env) {
return env;
int cpu_index;
#if defined(CONFIG_USER_ONLY)
cpu_index = 0;
cpu_index++;
#ifndef VBOX
#if defined(CONFIG_USER_ONLY)
if (p->code_bitmap) {
p->code_write_count = 0;
if (level == 0) {
for (i = 0; i < L2_SIZE; ++i) {
for (i = 0; i < L2_SIZE; ++i) {
static void page_flush_tb(void)
for (i = 0; i < V_L1_SIZE; i++) {
#ifdef VBOX
#if defined(DEBUG_FLUSH)
nb_tbs = 0;
#ifdef VBOX
#ifdef DEBUG_TB_CHECK
for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
static void tb_page_check(void)
for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
int next_offset)
unsigned int n1;
unsigned int n1;
if (tb1) {
PageDesc *p;
unsigned int h, n1;
#ifdef VBOX
flags);
if(tb)
# ifdef DEBUG
# ifdef VBOX_STRICT
return p ? p->phys_offset : 0;
tb_start = 0;
int code_gen_size;
if (!tb) {
code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
return tb;
int is_cpu_write_access)
PageDesc *p;
#ifdef TARGET_HAS_PRECISE_SMC
int current_tb_modified = 0;
int current_flags = 0;
if (!p->code_bitmap &&
#ifdef TARGET_HAS_PRECISE_SMC
if (current_tb_not_found) {
current_tb_not_found = 0;
if (env) {
if (env) {
#if !defined(CONFIG_USER_ONLY)
if (!p->first_tb) {
if (is_cpu_write_access) {
#ifdef TARGET_HAS_PRECISE_SMC
if (current_tb_modified) {
PageDesc *p;
int offset, b;
if (p->code_bitmap) {
goto do_invalidate;
#if !defined(CONFIG_SOFTMMU)
PageDesc *p;
#ifdef TARGET_HAS_PRECISE_SMC
int current_tb_modified = 0;
int current_flags = 0;
#ifdef TARGET_HAS_PRECISE_SMC
#ifdef TARGET_HAS_PRECISE_SMC
#ifdef TARGET_HAS_PRECISE_SMC
if (current_tb_modified) {
PageDesc *p;
#if defined(CONFIG_USER_ONLY)
int prot;
prot = 0;
if (!p2)
#ifdef DEBUG_TB_INVALIDATE
if (!last_first_tb) {
return NULL;
return tb;
nb_tbs--;
mmap_lock();
#ifdef DEBUG_TB_CHECK
mmap_unlock();
if (nb_tbs <= 0)
return NULL;
return NULL;
m_min = 0;
if (v == tc_ptr)
return tb;
else if (tc_ptr < v) {
unsigned int n1;
#if defined(TARGET_HAS_ICE)
#if defined(CONFIG_USER_ONLY)
PhysPageDesc *p;
#if defined(CONFIG_USER_ONLY)
return -ENOSYS;
#ifndef VBOX
return -EINVAL;
return VERR_INVALID_PARAMETER;
if (watchpoint)
int flags)
#ifndef VBOX
return -ENOENT;
return VERR_NOT_FOUND;
#if defined(TARGET_HAS_ICE)
if (breakpoint)
return -ENOSYS;
#if defined(TARGET_HAS_ICE)
# ifndef VBOX
return -ENOENT;
return VERR_NOT_FOUND;
return -ENOSYS;
#if defined(TARGET_HAS_ICE)
#if defined(TARGET_HAS_ICE)
#if defined(TARGET_HAS_ICE)
if (kvm_enabled())
#ifndef VBOX
if (!logfile) {
#if !defined(CONFIG_SOFTMMU)
if (logfile) {
if (tb) {
int old_mask;
#ifndef VBOX
#ifndef VBOX
#ifndef CONFIG_USER_ONLY
if (use_icount) {
#ifndef CONFIG_USER_ONLY
#ifdef VBOX
* Note: the current implementation can be executed by another thread without problems; make sure this remains true
#ifndef VBOX
#ifdef TARGET_I386
"show interrupts/exceptions in short format" },
#ifdef TARGET_I386
"show protected mode far calls/returns/exceptions" },
#ifdef DEBUG_IOPORT
#ifndef CONFIG_USER_ONLY
if (level == 0) {
for (i = 0; i < L2_SIZE; ++i) {
for (i = 0; i < L2_SIZE; ++i) {
for (i = 0; i < P_L1_SIZE; ++i) {
int mask;
const char *p, *p1;
p = str;
mask = 0;
if (!p1)
goto found;
return mask;
#ifdef TARGET_I386
if (qemu_log_enabled()) {
#ifdef TARGET_I386
#if defined(CONFIG_USER_ONLY)
abort();
#if defined(TARGET_HAS_ICE)
/* Clone all break/watchpoints.
BP_CPU break/watchpoints are handled correctly on clone. */
#if defined(TARGET_HAS_ICE)
return new_env;
#if !defined(CONFIG_USER_ONLY)
#ifdef VBOX
#ifdef VBOX
#if defined(DEBUG_TLB)
for(i = 0; i < CPU_TLB_SIZE; i++) {
int mmu_idx;
#ifdef VBOX
int mmu_idx;
#if defined(DEBUG_TLB)
#if defined(DEBUG_TLB)
unsigned long addr;
#ifdef VBOX
int dirty_flags)
if (length == 0)
abort();
start1 = (unsigned long)remR3TlbGCPhys2Ptr(first_cpu, start, 1 /*fWritable*/); /** @todo page replacing (sharing or read only) may cause trouble, fix interface/whatever. */
int mmu_idx;
for(i = 0; i < CPU_TLB_SIZE; i++)
#ifndef VBOX
int ret = 0;
return ret;
int cpu_physical_memory_get_dirty_tracking(void)
return in_migration;
#ifndef VBOX
int ret;
return ret;
int mmu_idx;
for(i = 0; i < CPU_TLB_SIZE; i++)
int mmu_idx;
PhysPageDesc *p;
unsigned long pd;
unsigned int index;
unsigned long addend;
#if defined(DEBUG_TLB)
printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x idx=%d size=" TARGET_FMT_lx " pd=0x%08lx\n",
#ifdef VBOX
struct walk_memory_regions_data
void *priv;
unsigned long start;
int prot;
if (rc != 0) {
return rc;
int i, rc;
if (level == 0) {
for (i = 0; i < L2_SIZE; ++i) {
if (rc != 0) {
return rc;
for (i = 0; i < L2_SIZE; ++i) {
if (rc != 0) {
return rc;
for (i = 0; i < V_L1_SIZE; i++) {
if (rc != 0) {
return rc;
PageDesc *p;
return p->flags;
#ifdef VBOX
AssertMsgFailed(("We shouldn't be here, and if we should, we must have an env to do the proper locking!\n"));
len != 0;
p->first_tb) {
PageDesc *p;
if (len == 0) {
len != 0;
unsigned int prot;
PageDesc *p;
mmap_lock();
mmap_unlock();
prot = 0;
#ifdef DEBUG_TB_CHECK
mmap_unlock();
mmap_unlock();
#if !defined(CONFIG_USER_ONLY)
typedef struct subpage_t {
} subpage_t;
need_subpage) \
start_addr2 = 0; \
if (start_addr2 > 0) \
PhysPageDesc *p;
#ifndef VBOX
int need_subpage = 0;
if (need_subpage) {
p->region_offset);
>> IO_MEM_SHIFT];
p->region_offset = 0;
int need_subpage = 0;
if (need_subpage) {
p->region_offset = 0;
#ifndef VBOX
PhysPageDesc *p;
return IO_MEM_UNASSIGNED;
return p->phys_offset;
#ifndef VBOX
if (kvm_enabled())
if (kvm_enabled())
void qemu_flush_coalesced_mmio_buffer(void)
if (kvm_enabled())
int ret;
if (ret != 0) {
const char *path)
char *filename;
void *area;
int fd;
#ifdef MAP_POPULATE
int flags;
unsigned long hpagesize;
if (!hpagesize) {
return NULL;
return NULL;
return NULL;
return NULL;
if (fd < 0) {
return NULL;
#ifdef MAP_POPULATE
return (NULL);
return area;
return offset;
return last;
if (id) {
abort();
if (kvm_enabled())
if (id) {
abort();
if (mem_path) {
#ifdef MADV_MERGEABLE
#ifdef MADV_MERGEABLE
if (kvm_enabled())
if (mem_path) {
Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
abort();
return NULL;
abort();
#ifdef DEBUG_UNASSIGNED
#ifdef DEBUG_UNASSIGNED
#ifdef DEBUG_UNASSIGNED
#ifdef DEBUG_UNASSIGNED
#ifdef DEBUG_UNASSIGNED
#ifdef DEBUG_UNASSIGNED
int dirty_flags;
#if !defined(CONFIG_USER_ONLY)
int dirty_flags;
#if !defined(CONFIG_USER_ONLY)
int dirty_flags;
#if !defined(CONFIG_USER_ONLY)
int cpu_flags;
if (!tb) {
unsigned int len)
#if defined(DEBUG_SUBPAGE)
#if defined(DEBUG_SUBPAGE)
#if defined(DEBUG_SUBPAGE)
int subpage_memory;
#if defined(DEBUG_SUBPAGE)
return mmio;
static int get_free_io_mem_idx(void)
for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
if (!io_mem_used[i]) {
void *opaque)
if (io_index <= 0) {
return io_index;
void *opaque)
static void io_mem_init(void)
#if defined(CONFIG_USER_ONLY)
int l, flags;
while (len > 0) {
if (l > len)
l = len;
if (is_write) {
len -= l;
buf += l;
addr += l;
int l, io_index;
unsigned long pd;
PhysPageDesc *p;
while (len > 0) {
if (l > len)
l = len;
if (is_write) {
unsigned long addr1;
#ifdef VBOX
#ifdef VBOX
len -= l;
buf += l;
addr += l;
#ifndef VBOX
unsigned long pd;
PhysPageDesc *p;
while (len > 0) {
if (l > len)
l = len;
unsigned long addr1;
len -= l;
buf += l;
addr += l;
void *buffer;
} BounceBuffer;
typedef struct MapClient {
void *opaque;
} MapClient;
return client;
static void cpu_notify_map_clients(void)
int is_write)
unsigned long pd;
PhysPageDesc *p;
unsigned long addr1;
while (len > 0) {
if (l > len)
l = len;
if (!is_write) {
if (!done) {
len -= l;
addr += l;
done += l;
return ret;
if (is_write) {
while (access_len) {
l = TARGET_PAGE_SIZE;
if (l > access_len)
l = access_len;
addr1 += l;
access_len -= l;
if (is_write) {
int io_index;
unsigned long pd;
PhysPageDesc *p;
#ifndef VBOX
return val;
int io_index;
unsigned long pd;
PhysPageDesc *p;
#ifdef TARGET_WORDS_BIGENDIAN
#ifndef VBOX
return val;
return val;
int io_index;
unsigned long pd;
PhysPageDesc *p;
#ifndef VBOX
return val;
int io_index;
unsigned long pd;
PhysPageDesc *p;
#ifndef VBOX
#ifndef VBOX
int io_index;
unsigned long pd;
PhysPageDesc *p;
#ifdef TARGET_WORDS_BIGENDIAN
#ifndef VBOX
int io_index;
unsigned long pd;
PhysPageDesc *p;
unsigned long addr1;
#ifndef VBOX
int io_index;
unsigned long pd;
PhysPageDesc *p;
unsigned long addr1;
#ifndef VBOX
#ifndef VBOX
while (len > 0) {
if (l > len)
l = len;
if (is_write)
len -= l;
buf += l;
addr += l;
if (!tb) {
retaddr);
#if defined(TARGET_MIPS)
if (n > CF_COUNT_MASK)
#if !defined(CONFIG_USER_ONLY)
#ifndef VBOX
target_code_size = 0;
max_target_code_size = 0;
cross_page = 0;
direct_jmp_count = 0;
direct_jmp2_count = 0;
for(i = 0; i < nb_tbs; i++) {
cross_page++;
#define SOFTMMU_CODE_ACCESS
#define SHIFT 0
#include "softmmu_template.h"
#include "softmmu_template.h"
#include "softmmu_template.h"
#include "softmmu_template.h"