blob: 64287e20c75aff7720705fed0ab9ac813891bd84 [file] [log] [blame]
bellard54936002003-05-13 00:25:15 +00001/*
bellardfd6ce8f2003-05-14 19:00:11 +00002 * virtual page mapping and translated block handling
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard54936002003-05-13 00:25:15 +00004 * 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
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
bellard67b915a2004-03-31 23:37:16 +000020#include "config.h"
bellardd5a8f072004-09-29 21:15:28 +000021#ifdef _WIN32
ths4fddf622007-12-17 04:42:29 +000022#define WIN32_LEAN_AND_MEAN
bellardd5a8f072004-09-29 21:15:28 +000023#include <windows.h>
24#else
bellarda98d49b2004-11-14 16:22:05 +000025#include <sys/types.h>
bellardd5a8f072004-09-29 21:15:28 +000026#include <sys/mman.h>
27#endif
bellard54936002003-05-13 00:25:15 +000028#include <stdlib.h>
29#include <stdio.h>
30#include <stdarg.h>
31#include <string.h>
32#include <errno.h>
33#include <unistd.h>
34#include <inttypes.h>
35
bellard6180a182003-09-30 21:04:53 +000036#include "cpu.h"
37#include "exec-all.h"
aurel32ca10f862008-04-11 21:35:42 +000038#include "qemu-common.h"
bellardb67d9a52008-05-23 09:57:34 +000039#include "tcg.h"
pbrook53a59602006-03-25 19:31:22 +000040#if defined(CONFIG_USER_ONLY)
41#include <qemu.h>
42#endif
bellard54936002003-05-13 00:25:15 +000043
bellardfd6ce8f2003-05-14 19:00:11 +000044//#define DEBUG_TB_INVALIDATE
bellard66e85a22003-06-24 13:28:12 +000045//#define DEBUG_FLUSH
bellard9fa3e852004-01-04 18:06:42 +000046//#define DEBUG_TLB
pbrook67d3b952006-12-18 05:03:52 +000047//#define DEBUG_UNASSIGNED
bellardfd6ce8f2003-05-14 19:00:11 +000048
49/* make various TB consistency checks */
ths5fafdf22007-09-16 21:08:06 +000050//#define DEBUG_TB_CHECK
51//#define DEBUG_TLB_CHECK
bellardfd6ce8f2003-05-14 19:00:11 +000052
ths1196be32007-03-17 15:17:58 +000053//#define DEBUG_IOPORT
blueswir1db7b5422007-05-26 17:36:03 +000054//#define DEBUG_SUBPAGE
ths1196be32007-03-17 15:17:58 +000055
pbrook99773bd2006-04-16 15:14:59 +000056#if !defined(CONFIG_USER_ONLY)
57/* TB consistency checks only implemented for usermode emulation. */
58#undef DEBUG_TB_CHECK
59#endif
60
bellard9fa3e852004-01-04 18:06:42 +000061#define SMC_BITMAP_USE_THRESHOLD 10
62
63#define MMAP_AREA_START 0x00000000
64#define MMAP_AREA_END 0xa8000000
bellardfd6ce8f2003-05-14 19:00:11 +000065
bellard108c49b2005-07-24 12:55:09 +000066#if defined(TARGET_SPARC64)
67#define TARGET_PHYS_ADDR_SPACE_BITS 41
blueswir15dcb6b92007-05-19 12:58:30 +000068#elif defined(TARGET_SPARC)
69#define TARGET_PHYS_ADDR_SPACE_BITS 36
j_mayerbedb69e2007-04-05 20:08:21 +000070#elif defined(TARGET_ALPHA)
71#define TARGET_PHYS_ADDR_SPACE_BITS 42
72#define TARGET_VIRT_ADDR_SPACE_BITS 42
bellard108c49b2005-07-24 12:55:09 +000073#elif defined(TARGET_PPC64)
74#define TARGET_PHYS_ADDR_SPACE_BITS 42
aurel3200f82b82008-04-27 21:12:55 +000075#elif defined(TARGET_X86_64) && !defined(USE_KQEMU)
76#define TARGET_PHYS_ADDR_SPACE_BITS 42
77#elif defined(TARGET_I386) && !defined(USE_KQEMU)
78#define TARGET_PHYS_ADDR_SPACE_BITS 36
bellard108c49b2005-07-24 12:55:09 +000079#else
80/* Note: for compatibility with kqemu, we use 32 bits for x86_64 */
81#define TARGET_PHYS_ADDR_SPACE_BITS 32
82#endif
83
pbrookfab94c02008-05-24 13:56:15 +000084TranslationBlock *tbs;
bellard26a5f132008-05-28 12:30:31 +000085int code_gen_max_blocks;
bellard9fa3e852004-01-04 18:06:42 +000086TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
bellardfd6ce8f2003-05-14 19:00:11 +000087int nb_tbs;
bellardeb51d102003-05-14 21:51:13 +000088/* any access to the tbs or the page table must use this lock */
89spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
bellardfd6ce8f2003-05-14 19:00:11 +000090
bellard7cb69ca2008-05-10 10:55:51 +000091uint8_t code_gen_prologue[1024] __attribute__((aligned (32)));
bellard26a5f132008-05-28 12:30:31 +000092uint8_t *code_gen_buffer;
93unsigned long code_gen_buffer_size;
94/* threshold to flush the translated code buffer */
95unsigned long code_gen_buffer_max_size;
bellardfd6ce8f2003-05-14 19:00:11 +000096uint8_t *code_gen_ptr;
97
pbrooke2eef172008-06-08 01:09:01 +000098#if !defined(CONFIG_USER_ONLY)
aurel3200f82b82008-04-27 21:12:55 +000099ram_addr_t phys_ram_size;
bellard9fa3e852004-01-04 18:06:42 +0000100int phys_ram_fd;
101uint8_t *phys_ram_base;
bellard1ccde1c2004-02-06 19:46:14 +0000102uint8_t *phys_ram_dirty;
bellarde9a1ab12007-02-08 23:08:38 +0000103static ram_addr_t phys_ram_alloc_offset = 0;
pbrooke2eef172008-06-08 01:09:01 +0000104#endif
bellard9fa3e852004-01-04 18:06:42 +0000105
bellard6a00d602005-11-21 23:25:50 +0000106CPUState *first_cpu;
107/* current CPU in the current thread. It is only valid inside
108 cpu_exec() */
ths5fafdf22007-09-16 21:08:06 +0000109CPUState *cpu_single_env;
bellard6a00d602005-11-21 23:25:50 +0000110
bellard54936002003-05-13 00:25:15 +0000111typedef struct PageDesc {
bellard92e873b2004-05-21 14:52:29 +0000112 /* list of TBs intersecting this ram page */
bellardfd6ce8f2003-05-14 19:00:11 +0000113 TranslationBlock *first_tb;
bellard9fa3e852004-01-04 18:06:42 +0000114 /* 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
bellard54936002003-05-13 00:25:15 +0000121} PageDesc;
122
bellard92e873b2004-05-21 14:52:29 +0000123typedef struct PhysPageDesc {
pbrook0f459d12008-06-09 00:20:13 +0000124 /* offset in host memory of the page + io_index in the low bits */
aurel3200f82b82008-04-27 21:12:55 +0000125 ram_addr_t phys_offset;
bellard92e873b2004-05-21 14:52:29 +0000126} PhysPageDesc;
127
bellard54936002003-05-13 00:25:15 +0000128#define L2_BITS 10
j_mayerbedb69e2007-04-05 20:08:21 +0000129#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
130/* XXX: this is a temporary hack for alpha target.
131 * In the future, this is to be replaced by a multi-level table
132 * to actually be able to handle the complete 64 bits address space.
133 */
134#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
135#else
aurel3203875442008-04-22 20:45:18 +0000136#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
j_mayerbedb69e2007-04-05 20:08:21 +0000137#endif
bellard54936002003-05-13 00:25:15 +0000138
139#define L1_SIZE (1 << L1_BITS)
140#define L2_SIZE (1 << L2_BITS)
141
bellard83fb7ad2004-07-05 21:25:26 +0000142unsigned long qemu_real_host_page_size;
143unsigned long qemu_host_page_bits;
144unsigned long qemu_host_page_size;
145unsigned long qemu_host_page_mask;
bellard54936002003-05-13 00:25:15 +0000146
bellard92e873b2004-05-21 14:52:29 +0000147/* XXX: for system emulation, it could just be an array */
bellard54936002003-05-13 00:25:15 +0000148static PageDesc *l1_map[L1_SIZE];
bellard0a962c02005-02-10 22:00:27 +0000149PhysPageDesc **l1_phys_map;
bellard54936002003-05-13 00:25:15 +0000150
pbrooke2eef172008-06-08 01:09:01 +0000151#if !defined(CONFIG_USER_ONLY)
152static void io_mem_init(void);
153
bellard33417e72003-08-10 21:47:01 +0000154/* io memory support */
bellard33417e72003-08-10 21:47:01 +0000155CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
156CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
bellarda4193c82004-06-03 14:01:43 +0000157void *io_mem_opaque[IO_MEM_NB_ENTRIES];
bellard33417e72003-08-10 21:47:01 +0000158static int io_mem_nb;
pbrook6658ffb2007-03-16 23:58:11 +0000159static int io_mem_watch;
160#endif
bellard33417e72003-08-10 21:47:01 +0000161
bellard34865132003-10-05 14:28:56 +0000162/* log support */
163char *logfilename = "/tmp/qemu.log";
164FILE *logfile;
165int loglevel;
pbrooke735b912007-06-30 13:53:24 +0000166static int log_append = 0;
bellard34865132003-10-05 14:28:56 +0000167
bellarde3db7222005-01-26 22:00:47 +0000168/* statistics */
169static int tlb_flush_count;
170static int tb_flush_count;
171static int tb_phys_invalidate_count;
172
blueswir1db7b5422007-05-26 17:36:03 +0000173#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
174typedef struct subpage_t {
175 target_phys_addr_t base;
blueswir13ee89922008-01-02 19:45:26 +0000176 CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE][4];
177 CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE][4];
178 void *opaque[TARGET_PAGE_SIZE][2][4];
blueswir1db7b5422007-05-26 17:36:03 +0000179} subpage_t;
180
bellard7cb69ca2008-05-10 10:55:51 +0000181#ifdef _WIN32
182static void map_exec(void *addr, long size)
183{
184 DWORD old_protect;
185 VirtualProtect(addr, size,
186 PAGE_EXECUTE_READWRITE, &old_protect);
187
188}
189#else
190static void map_exec(void *addr, long size)
191{
bellard43694152008-05-29 09:35:57 +0000192 unsigned long start, end, page_size;
bellard7cb69ca2008-05-10 10:55:51 +0000193
bellard43694152008-05-29 09:35:57 +0000194 page_size = getpagesize();
bellard7cb69ca2008-05-10 10:55:51 +0000195 start = (unsigned long)addr;
bellard43694152008-05-29 09:35:57 +0000196 start &= ~(page_size - 1);
bellard7cb69ca2008-05-10 10:55:51 +0000197
198 end = (unsigned long)addr + size;
bellard43694152008-05-29 09:35:57 +0000199 end += page_size - 1;
200 end &= ~(page_size - 1);
bellard7cb69ca2008-05-10 10:55:51 +0000201
202 mprotect((void *)start, end - start,
203 PROT_READ | PROT_WRITE | PROT_EXEC);
204}
205#endif
206
bellardb346ff42003-06-15 20:05:50 +0000207static void page_init(void)
bellard54936002003-05-13 00:25:15 +0000208{
bellard83fb7ad2004-07-05 21:25:26 +0000209 /* NOTE: we can always suppose that qemu_host_page_size >=
bellard54936002003-05-13 00:25:15 +0000210 TARGET_PAGE_SIZE */
bellard67b915a2004-03-31 23:37:16 +0000211#ifdef _WIN32
bellardd5a8f072004-09-29 21:15:28 +0000212 {
213 SYSTEM_INFO system_info;
214 DWORD old_protect;
ths3b46e622007-09-17 08:09:54 +0000215
bellardd5a8f072004-09-29 21:15:28 +0000216 GetSystemInfo(&system_info);
217 qemu_real_host_page_size = system_info.dwPageSize;
bellardd5a8f072004-09-29 21:15:28 +0000218 }
bellard67b915a2004-03-31 23:37:16 +0000219#else
bellard83fb7ad2004-07-05 21:25:26 +0000220 qemu_real_host_page_size = getpagesize();
bellard67b915a2004-03-31 23:37:16 +0000221#endif
bellard83fb7ad2004-07-05 21:25:26 +0000222 if (qemu_host_page_size == 0)
223 qemu_host_page_size = qemu_real_host_page_size;
224 if (qemu_host_page_size < TARGET_PAGE_SIZE)
225 qemu_host_page_size = TARGET_PAGE_SIZE;
226 qemu_host_page_bits = 0;
227 while ((1 << qemu_host_page_bits) < qemu_host_page_size)
228 qemu_host_page_bits++;
229 qemu_host_page_mask = ~(qemu_host_page_size - 1);
bellard108c49b2005-07-24 12:55:09 +0000230 l1_phys_map = qemu_vmalloc(L1_SIZE * sizeof(void *));
231 memset(l1_phys_map, 0, L1_SIZE * sizeof(void *));
balrog50a95692007-12-12 01:16:23 +0000232
233#if !defined(_WIN32) && defined(CONFIG_USER_ONLY)
234 {
235 long long startaddr, endaddr;
236 FILE *f;
237 int n;
238
pbrookc8a706f2008-06-02 16:16:42 +0000239 mmap_lock();
pbrook07765902008-05-31 16:33:53 +0000240 last_brk = (unsigned long)sbrk(0);
balrog50a95692007-12-12 01:16:23 +0000241 f = fopen("/proc/self/maps", "r");
242 if (f) {
243 do {
244 n = fscanf (f, "%llx-%llx %*[^\n]\n", &startaddr, &endaddr);
245 if (n == 2) {
blueswir1e0b8d652008-05-03 17:51:24 +0000246 startaddr = MIN(startaddr,
247 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
248 endaddr = MIN(endaddr,
249 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
pbrookb5fc9092008-05-29 13:56:10 +0000250 page_set_flags(startaddr & TARGET_PAGE_MASK,
balrog50a95692007-12-12 01:16:23 +0000251 TARGET_PAGE_ALIGN(endaddr),
252 PAGE_RESERVED);
253 }
254 } while (!feof(f));
255 fclose(f);
256 }
pbrookc8a706f2008-06-02 16:16:42 +0000257 mmap_unlock();
balrog50a95692007-12-12 01:16:23 +0000258 }
259#endif
bellard54936002003-05-13 00:25:15 +0000260}
261
aurel3200f82b82008-04-27 21:12:55 +0000262static inline PageDesc *page_find_alloc(target_ulong index)
bellard54936002003-05-13 00:25:15 +0000263{
bellard54936002003-05-13 00:25:15 +0000264 PageDesc **lp, *p;
265
bellard54936002003-05-13 00:25:15 +0000266 lp = &l1_map[index >> L2_BITS];
267 p = *lp;
268 if (!p) {
269 /* allocate if not found */
bellard59817cc2004-02-16 22:01:13 +0000270 p = qemu_malloc(sizeof(PageDesc) * L2_SIZE);
bellardfd6ce8f2003-05-14 19:00:11 +0000271 memset(p, 0, sizeof(PageDesc) * L2_SIZE);
bellard54936002003-05-13 00:25:15 +0000272 *lp = p;
273 }
274 return p + (index & (L2_SIZE - 1));
275}
276
aurel3200f82b82008-04-27 21:12:55 +0000277static inline PageDesc *page_find(target_ulong index)
bellard54936002003-05-13 00:25:15 +0000278{
bellard54936002003-05-13 00:25:15 +0000279 PageDesc *p;
280
bellard54936002003-05-13 00:25:15 +0000281 p = l1_map[index >> L2_BITS];
282 if (!p)
283 return 0;
bellardfd6ce8f2003-05-14 19:00:11 +0000284 return p + (index & (L2_SIZE - 1));
bellard54936002003-05-13 00:25:15 +0000285}
286
bellard108c49b2005-07-24 12:55:09 +0000287static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
bellard92e873b2004-05-21 14:52:29 +0000288{
bellard108c49b2005-07-24 12:55:09 +0000289 void **lp, **p;
pbrooke3f4e2a2006-04-08 20:02:06 +0000290 PhysPageDesc *pd;
bellard92e873b2004-05-21 14:52:29 +0000291
bellard108c49b2005-07-24 12:55:09 +0000292 p = (void **)l1_phys_map;
293#if TARGET_PHYS_ADDR_SPACE_BITS > 32
294
295#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
296#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
297#endif
298 lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1));
bellard92e873b2004-05-21 14:52:29 +0000299 p = *lp;
300 if (!p) {
301 /* allocate if not found */
bellard108c49b2005-07-24 12:55:09 +0000302 if (!alloc)
303 return NULL;
304 p = qemu_vmalloc(sizeof(void *) * L1_SIZE);
305 memset(p, 0, sizeof(void *) * L1_SIZE);
306 *lp = p;
307 }
308#endif
309 lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
pbrooke3f4e2a2006-04-08 20:02:06 +0000310 pd = *lp;
311 if (!pd) {
312 int i;
bellard108c49b2005-07-24 12:55:09 +0000313 /* allocate if not found */
314 if (!alloc)
315 return NULL;
pbrooke3f4e2a2006-04-08 20:02:06 +0000316 pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
317 *lp = pd;
318 for (i = 0; i < L2_SIZE; i++)
319 pd[i].phys_offset = IO_MEM_UNASSIGNED;
bellard92e873b2004-05-21 14:52:29 +0000320 }
pbrooke3f4e2a2006-04-08 20:02:06 +0000321 return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
bellard92e873b2004-05-21 14:52:29 +0000322}
323
bellard108c49b2005-07-24 12:55:09 +0000324static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
bellard92e873b2004-05-21 14:52:29 +0000325{
bellard108c49b2005-07-24 12:55:09 +0000326 return phys_page_find_alloc(index, 0);
bellard92e873b2004-05-21 14:52:29 +0000327}
328
bellard9fa3e852004-01-04 18:06:42 +0000329#if !defined(CONFIG_USER_ONLY)
bellard6a00d602005-11-21 23:25:50 +0000330static void tlb_protect_code(ram_addr_t ram_addr);
ths5fafdf22007-09-16 21:08:06 +0000331static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
bellard3a7d9292005-08-21 09:26:42 +0000332 target_ulong vaddr);
pbrookc8a706f2008-06-02 16:16:42 +0000333#define mmap_lock() do { } while(0)
334#define mmap_unlock() do { } while(0)
bellard9fa3e852004-01-04 18:06:42 +0000335#endif
bellardfd6ce8f2003-05-14 19:00:11 +0000336
bellard43694152008-05-29 09:35:57 +0000337#define DEFAULT_CODE_GEN_BUFFER_SIZE (32 * 1024 * 1024)
338
339#if defined(CONFIG_USER_ONLY)
340/* Currently it is not recommanded to allocate big chunks of data in
341 user mode. It will change when a dedicated libc will be used */
342#define USE_STATIC_CODE_GEN_BUFFER
343#endif
344
345#ifdef USE_STATIC_CODE_GEN_BUFFER
346static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE];
347#endif
348
bellard26a5f132008-05-28 12:30:31 +0000349void code_gen_alloc(unsigned long tb_size)
350{
bellard43694152008-05-29 09:35:57 +0000351#ifdef USE_STATIC_CODE_GEN_BUFFER
352 code_gen_buffer = static_code_gen_buffer;
353 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
354 map_exec(code_gen_buffer, code_gen_buffer_size);
355#else
bellard26a5f132008-05-28 12:30:31 +0000356 code_gen_buffer_size = tb_size;
357 if (code_gen_buffer_size == 0) {
bellard43694152008-05-29 09:35:57 +0000358#if defined(CONFIG_USER_ONLY)
359 /* in user mode, phys_ram_size is not meaningful */
360 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
361#else
bellard26a5f132008-05-28 12:30:31 +0000362 /* XXX: needs ajustments */
363 code_gen_buffer_size = (int)(phys_ram_size / 4);
bellard43694152008-05-29 09:35:57 +0000364#endif
bellard26a5f132008-05-28 12:30:31 +0000365 }
366 if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE)
367 code_gen_buffer_size = MIN_CODE_GEN_BUFFER_SIZE;
368 /* The code gen buffer location may have constraints depending on
369 the host cpu and OS */
370#if defined(__linux__)
371 {
372 int flags;
373 flags = MAP_PRIVATE | MAP_ANONYMOUS;
374#if defined(__x86_64__)
375 flags |= MAP_32BIT;
376 /* Cannot map more than that */
377 if (code_gen_buffer_size > (800 * 1024 * 1024))
378 code_gen_buffer_size = (800 * 1024 * 1024);
379#endif
380 code_gen_buffer = mmap(NULL, code_gen_buffer_size,
381 PROT_WRITE | PROT_READ | PROT_EXEC,
382 flags, -1, 0);
383 if (code_gen_buffer == MAP_FAILED) {
384 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
385 exit(1);
386 }
387 }
388#else
389 code_gen_buffer = qemu_malloc(code_gen_buffer_size);
390 if (!code_gen_buffer) {
391 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
392 exit(1);
393 }
394 map_exec(code_gen_buffer, code_gen_buffer_size);
395#endif
bellard43694152008-05-29 09:35:57 +0000396#endif /* !USE_STATIC_CODE_GEN_BUFFER */
bellard26a5f132008-05-28 12:30:31 +0000397 map_exec(code_gen_prologue, sizeof(code_gen_prologue));
398 code_gen_buffer_max_size = code_gen_buffer_size -
399 code_gen_max_block_size();
400 code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
401 tbs = qemu_malloc(code_gen_max_blocks * sizeof(TranslationBlock));
402}
403
404/* Must be called before using the QEMU cpus. 'tb_size' is the size
405 (in bytes) allocated to the translation buffer. Zero means default
406 size. */
407void cpu_exec_init_all(unsigned long tb_size)
408{
bellard26a5f132008-05-28 12:30:31 +0000409 cpu_gen_init();
410 code_gen_alloc(tb_size);
411 code_gen_ptr = code_gen_buffer;
bellard43694152008-05-29 09:35:57 +0000412 page_init();
pbrooke2eef172008-06-08 01:09:01 +0000413#if !defined(CONFIG_USER_ONLY)
bellard26a5f132008-05-28 12:30:31 +0000414 io_mem_init();
pbrooke2eef172008-06-08 01:09:01 +0000415#endif
bellard26a5f132008-05-28 12:30:31 +0000416}
417
bellard6a00d602005-11-21 23:25:50 +0000418void cpu_exec_init(CPUState *env)
bellardfd6ce8f2003-05-14 19:00:11 +0000419{
bellard6a00d602005-11-21 23:25:50 +0000420 CPUState **penv;
421 int cpu_index;
422
bellard6a00d602005-11-21 23:25:50 +0000423 env->next_cpu = NULL;
424 penv = &first_cpu;
425 cpu_index = 0;
426 while (*penv != NULL) {
427 penv = (CPUState **)&(*penv)->next_cpu;
428 cpu_index++;
429 }
430 env->cpu_index = cpu_index;
pbrook6658ffb2007-03-16 23:58:11 +0000431 env->nb_watchpoints = 0;
bellard6a00d602005-11-21 23:25:50 +0000432 *penv = env;
bellardfd6ce8f2003-05-14 19:00:11 +0000433}
434
bellard9fa3e852004-01-04 18:06:42 +0000435static inline void invalidate_page_bitmap(PageDesc *p)
436{
437 if (p->code_bitmap) {
bellard59817cc2004-02-16 22:01:13 +0000438 qemu_free(p->code_bitmap);
bellard9fa3e852004-01-04 18:06:42 +0000439 p->code_bitmap = NULL;
440 }
441 p->code_write_count = 0;
442}
443
bellardfd6ce8f2003-05-14 19:00:11 +0000444/* set to NULL all the 'first_tb' fields in all PageDescs */
445static void page_flush_tb(void)
446{
447 int i, j;
448 PageDesc *p;
449
450 for(i = 0; i < L1_SIZE; i++) {
451 p = l1_map[i];
452 if (p) {
bellard9fa3e852004-01-04 18:06:42 +0000453 for(j = 0; j < L2_SIZE; j++) {
454 p->first_tb = NULL;
455 invalidate_page_bitmap(p);
456 p++;
457 }
bellardfd6ce8f2003-05-14 19:00:11 +0000458 }
459 }
460}
461
462/* flush all the translation blocks */
bellardd4e81642003-05-25 16:46:15 +0000463/* XXX: tb_flush is currently not thread safe */
bellard6a00d602005-11-21 23:25:50 +0000464void tb_flush(CPUState *env1)
bellardfd6ce8f2003-05-14 19:00:11 +0000465{
bellard6a00d602005-11-21 23:25:50 +0000466 CPUState *env;
bellard01243112004-01-04 15:48:17 +0000467#if defined(DEBUG_FLUSH)
blueswir1ab3d1722007-11-04 07:31:40 +0000468 printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
469 (unsigned long)(code_gen_ptr - code_gen_buffer),
470 nb_tbs, nb_tbs > 0 ?
471 ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
bellardfd6ce8f2003-05-14 19:00:11 +0000472#endif
bellard26a5f132008-05-28 12:30:31 +0000473 if ((unsigned long)(code_gen_ptr - code_gen_buffer) > code_gen_buffer_size)
pbrooka208e542008-03-31 17:07:36 +0000474 cpu_abort(env1, "Internal error: code buffer overflow\n");
475
bellardfd6ce8f2003-05-14 19:00:11 +0000476 nb_tbs = 0;
ths3b46e622007-09-17 08:09:54 +0000477
bellard6a00d602005-11-21 23:25:50 +0000478 for(env = first_cpu; env != NULL; env = env->next_cpu) {
479 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
480 }
bellard9fa3e852004-01-04 18:06:42 +0000481
bellard8a8a6082004-10-03 13:36:49 +0000482 memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
bellardfd6ce8f2003-05-14 19:00:11 +0000483 page_flush_tb();
bellard9fa3e852004-01-04 18:06:42 +0000484
bellardfd6ce8f2003-05-14 19:00:11 +0000485 code_gen_ptr = code_gen_buffer;
bellardd4e81642003-05-25 16:46:15 +0000486 /* XXX: flush processor icache at this point if cache flush is
487 expensive */
bellarde3db7222005-01-26 22:00:47 +0000488 tb_flush_count++;
bellardfd6ce8f2003-05-14 19:00:11 +0000489}
490
491#ifdef DEBUG_TB_CHECK
492
j_mayerbc98a7e2007-04-04 07:55:12 +0000493static void tb_invalidate_check(target_ulong address)
bellardfd6ce8f2003-05-14 19:00:11 +0000494{
495 TranslationBlock *tb;
496 int i;
497 address &= TARGET_PAGE_MASK;
pbrook99773bd2006-04-16 15:14:59 +0000498 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
499 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
bellardfd6ce8f2003-05-14 19:00:11 +0000500 if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
501 address >= tb->pc + tb->size)) {
502 printf("ERROR invalidate: address=%08lx PC=%08lx size=%04x\n",
pbrook99773bd2006-04-16 15:14:59 +0000503 address, (long)tb->pc, tb->size);
bellardfd6ce8f2003-05-14 19:00:11 +0000504 }
505 }
506 }
507}
508
509/* verify that all the pages have correct rights for code */
510static void tb_page_check(void)
511{
512 TranslationBlock *tb;
513 int i, flags1, flags2;
ths3b46e622007-09-17 08:09:54 +0000514
pbrook99773bd2006-04-16 15:14:59 +0000515 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
516 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
bellardfd6ce8f2003-05-14 19:00:11 +0000517 flags1 = page_get_flags(tb->pc);
518 flags2 = page_get_flags(tb->pc + tb->size - 1);
519 if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
520 printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
pbrook99773bd2006-04-16 15:14:59 +0000521 (long)tb->pc, tb->size, flags1, flags2);
bellardfd6ce8f2003-05-14 19:00:11 +0000522 }
523 }
524 }
525}
526
bellardd4e81642003-05-25 16:46:15 +0000527void tb_jmp_check(TranslationBlock *tb)
528{
529 TranslationBlock *tb1;
530 unsigned int n1;
531
532 /* suppress any remaining jumps to this TB */
533 tb1 = tb->jmp_first;
534 for(;;) {
535 n1 = (long)tb1 & 3;
536 tb1 = (TranslationBlock *)((long)tb1 & ~3);
537 if (n1 == 2)
538 break;
539 tb1 = tb1->jmp_next[n1];
540 }
541 /* check end of list */
542 if (tb1 != tb) {
543 printf("ERROR: jmp_list from 0x%08lx\n", (long)tb);
544 }
545}
546
bellardfd6ce8f2003-05-14 19:00:11 +0000547#endif
548
549/* invalidate one TB */
550static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb,
551 int next_offset)
552{
553 TranslationBlock *tb1;
554 for(;;) {
555 tb1 = *ptb;
556 if (tb1 == tb) {
557 *ptb = *(TranslationBlock **)((char *)tb1 + next_offset);
558 break;
559 }
560 ptb = (TranslationBlock **)((char *)tb1 + next_offset);
561 }
562}
563
bellard9fa3e852004-01-04 18:06:42 +0000564static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
565{
566 TranslationBlock *tb1;
567 unsigned int n1;
568
569 for(;;) {
570 tb1 = *ptb;
571 n1 = (long)tb1 & 3;
572 tb1 = (TranslationBlock *)((long)tb1 & ~3);
573 if (tb1 == tb) {
574 *ptb = tb1->page_next[n1];
575 break;
576 }
577 ptb = &tb1->page_next[n1];
578 }
579}
580
bellardd4e81642003-05-25 16:46:15 +0000581static inline void tb_jmp_remove(TranslationBlock *tb, int n)
582{
583 TranslationBlock *tb1, **ptb;
584 unsigned int n1;
585
586 ptb = &tb->jmp_next[n];
587 tb1 = *ptb;
588 if (tb1) {
589 /* find tb(n) in circular list */
590 for(;;) {
591 tb1 = *ptb;
592 n1 = (long)tb1 & 3;
593 tb1 = (TranslationBlock *)((long)tb1 & ~3);
594 if (n1 == n && tb1 == tb)
595 break;
596 if (n1 == 2) {
597 ptb = &tb1->jmp_first;
598 } else {
599 ptb = &tb1->jmp_next[n1];
600 }
601 }
602 /* now we can suppress tb(n) from the list */
603 *ptb = tb->jmp_next[n];
604
605 tb->jmp_next[n] = NULL;
606 }
607}
608
609/* reset the jump entry 'n' of a TB so that it is not chained to
610 another TB */
611static inline void tb_reset_jump(TranslationBlock *tb, int n)
612{
613 tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
614}
615
aurel3200f82b82008-04-27 21:12:55 +0000616static inline void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr)
bellardfd6ce8f2003-05-14 19:00:11 +0000617{
bellard6a00d602005-11-21 23:25:50 +0000618 CPUState *env;
bellardfd6ce8f2003-05-14 19:00:11 +0000619 PageDesc *p;
bellard8a40a182005-11-20 10:35:40 +0000620 unsigned int h, n1;
aurel3200f82b82008-04-27 21:12:55 +0000621 target_phys_addr_t phys_pc;
bellard8a40a182005-11-20 10:35:40 +0000622 TranslationBlock *tb1, *tb2;
ths3b46e622007-09-17 08:09:54 +0000623
bellard9fa3e852004-01-04 18:06:42 +0000624 /* remove the TB from the hash list */
625 phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
626 h = tb_phys_hash_func(phys_pc);
ths5fafdf22007-09-16 21:08:06 +0000627 tb_remove(&tb_phys_hash[h], tb,
bellard9fa3e852004-01-04 18:06:42 +0000628 offsetof(TranslationBlock, phys_hash_next));
bellardfd6ce8f2003-05-14 19:00:11 +0000629
bellard9fa3e852004-01-04 18:06:42 +0000630 /* remove the TB from the page list */
631 if (tb->page_addr[0] != page_addr) {
632 p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
633 tb_page_remove(&p->first_tb, tb);
634 invalidate_page_bitmap(p);
635 }
636 if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
637 p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
638 tb_page_remove(&p->first_tb, tb);
639 invalidate_page_bitmap(p);
640 }
641
bellard8a40a182005-11-20 10:35:40 +0000642 tb_invalidated_flag = 1;
643
644 /* remove the TB from the hash list */
645 h = tb_jmp_cache_hash_func(tb->pc);
bellard6a00d602005-11-21 23:25:50 +0000646 for(env = first_cpu; env != NULL; env = env->next_cpu) {
647 if (env->tb_jmp_cache[h] == tb)
648 env->tb_jmp_cache[h] = NULL;
649 }
bellard8a40a182005-11-20 10:35:40 +0000650
651 /* suppress this TB from the two jump lists */
652 tb_jmp_remove(tb, 0);
653 tb_jmp_remove(tb, 1);
654
655 /* suppress any remaining jumps to this TB */
656 tb1 = tb->jmp_first;
657 for(;;) {
658 n1 = (long)tb1 & 3;
659 if (n1 == 2)
660 break;
661 tb1 = (TranslationBlock *)((long)tb1 & ~3);
662 tb2 = tb1->jmp_next[n1];
663 tb_reset_jump(tb1, n1);
664 tb1->jmp_next[n1] = NULL;
665 tb1 = tb2;
666 }
667 tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
668
bellarde3db7222005-01-26 22:00:47 +0000669 tb_phys_invalidate_count++;
bellard9fa3e852004-01-04 18:06:42 +0000670}
671
672static inline void set_bits(uint8_t *tab, int start, int len)
673{
674 int end, mask, end1;
675
676 end = start + len;
677 tab += start >> 3;
678 mask = 0xff << (start & 7);
679 if ((start & ~7) == (end & ~7)) {
680 if (start < end) {
681 mask &= ~(0xff << (end & 7));
682 *tab |= mask;
683 }
684 } else {
685 *tab++ |= mask;
686 start = (start + 8) & ~7;
687 end1 = end & ~7;
688 while (start < end1) {
689 *tab++ = 0xff;
690 start += 8;
691 }
692 if (start < end) {
693 mask = ~(0xff << (end & 7));
694 *tab |= mask;
695 }
696 }
697}
698
699static void build_page_bitmap(PageDesc *p)
700{
701 int n, tb_start, tb_end;
702 TranslationBlock *tb;
ths3b46e622007-09-17 08:09:54 +0000703
bellard59817cc2004-02-16 22:01:13 +0000704 p->code_bitmap = qemu_malloc(TARGET_PAGE_SIZE / 8);
bellard9fa3e852004-01-04 18:06:42 +0000705 if (!p->code_bitmap)
706 return;
707 memset(p->code_bitmap, 0, TARGET_PAGE_SIZE / 8);
708
709 tb = p->first_tb;
710 while (tb != NULL) {
711 n = (long)tb & 3;
712 tb = (TranslationBlock *)((long)tb & ~3);
713 /* NOTE: this is subtle as a TB may span two physical pages */
714 if (n == 0) {
715 /* NOTE: tb_end may be after the end of the page, but
716 it is not a problem */
717 tb_start = tb->pc & ~TARGET_PAGE_MASK;
718 tb_end = tb_start + tb->size;
719 if (tb_end > TARGET_PAGE_SIZE)
720 tb_end = TARGET_PAGE_SIZE;
721 } else {
722 tb_start = 0;
723 tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
724 }
725 set_bits(p->code_bitmap, tb_start, tb_end - tb_start);
726 tb = tb->page_next[n];
727 }
728}
729
bellardd720b932004-04-25 17:57:43 +0000730#ifdef TARGET_HAS_PRECISE_SMC
731
ths5fafdf22007-09-16 21:08:06 +0000732static void tb_gen_code(CPUState *env,
bellardd720b932004-04-25 17:57:43 +0000733 target_ulong pc, target_ulong cs_base, int flags,
734 int cflags)
735{
736 TranslationBlock *tb;
737 uint8_t *tc_ptr;
738 target_ulong phys_pc, phys_page2, virt_page2;
739 int code_gen_size;
740
bellardc27004e2005-01-03 23:35:10 +0000741 phys_pc = get_phys_addr_code(env, pc);
742 tb = tb_alloc(pc);
bellardd720b932004-04-25 17:57:43 +0000743 if (!tb) {
744 /* flush must be done */
745 tb_flush(env);
746 /* cannot fail at this point */
bellardc27004e2005-01-03 23:35:10 +0000747 tb = tb_alloc(pc);
bellardd720b932004-04-25 17:57:43 +0000748 }
749 tc_ptr = code_gen_ptr;
750 tb->tc_ptr = tc_ptr;
751 tb->cs_base = cs_base;
752 tb->flags = flags;
753 tb->cflags = cflags;
blueswir1d07bde82007-12-11 19:35:45 +0000754 cpu_gen_code(env, tb, &code_gen_size);
bellardd720b932004-04-25 17:57:43 +0000755 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
ths3b46e622007-09-17 08:09:54 +0000756
bellardd720b932004-04-25 17:57:43 +0000757 /* check next page if needed */
bellardc27004e2005-01-03 23:35:10 +0000758 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
bellardd720b932004-04-25 17:57:43 +0000759 phys_page2 = -1;
bellardc27004e2005-01-03 23:35:10 +0000760 if ((pc & TARGET_PAGE_MASK) != virt_page2) {
bellardd720b932004-04-25 17:57:43 +0000761 phys_page2 = get_phys_addr_code(env, virt_page2);
762 }
763 tb_link_phys(tb, phys_pc, phys_page2);
764}
765#endif
ths3b46e622007-09-17 08:09:54 +0000766
bellard9fa3e852004-01-04 18:06:42 +0000767/* invalidate all TBs which intersect with the target physical page
768 starting in range [start;end[. NOTE: start and end must refer to
bellardd720b932004-04-25 17:57:43 +0000769 the same physical page. 'is_cpu_write_access' should be true if called
770 from a real cpu write access: the virtual CPU will exit the current
771 TB if code is modified inside this TB. */
aurel3200f82b82008-04-27 21:12:55 +0000772void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t end,
bellardd720b932004-04-25 17:57:43 +0000773 int is_cpu_write_access)
bellard9fa3e852004-01-04 18:06:42 +0000774{
bellardd720b932004-04-25 17:57:43 +0000775 int n, current_tb_modified, current_tb_not_found, current_flags;
bellardd720b932004-04-25 17:57:43 +0000776 CPUState *env = cpu_single_env;
bellard9fa3e852004-01-04 18:06:42 +0000777 PageDesc *p;
bellardea1c1802004-06-14 18:56:36 +0000778 TranslationBlock *tb, *tb_next, *current_tb, *saved_tb;
bellard9fa3e852004-01-04 18:06:42 +0000779 target_ulong tb_start, tb_end;
bellardd720b932004-04-25 17:57:43 +0000780 target_ulong current_pc, current_cs_base;
bellard9fa3e852004-01-04 18:06:42 +0000781
782 p = page_find(start >> TARGET_PAGE_BITS);
ths5fafdf22007-09-16 21:08:06 +0000783 if (!p)
bellard9fa3e852004-01-04 18:06:42 +0000784 return;
ths5fafdf22007-09-16 21:08:06 +0000785 if (!p->code_bitmap &&
bellardd720b932004-04-25 17:57:43 +0000786 ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
787 is_cpu_write_access) {
bellard9fa3e852004-01-04 18:06:42 +0000788 /* build code bitmap */
789 build_page_bitmap(p);
790 }
791
792 /* we remove all the TBs in the range [start, end[ */
793 /* XXX: see if in some cases it could be faster to invalidate all the code */
bellardd720b932004-04-25 17:57:43 +0000794 current_tb_not_found = is_cpu_write_access;
795 current_tb_modified = 0;
796 current_tb = NULL; /* avoid warning */
797 current_pc = 0; /* avoid warning */
798 current_cs_base = 0; /* avoid warning */
799 current_flags = 0; /* avoid warning */
bellard9fa3e852004-01-04 18:06:42 +0000800 tb = p->first_tb;
801 while (tb != NULL) {
802 n = (long)tb & 3;
803 tb = (TranslationBlock *)((long)tb & ~3);
804 tb_next = tb->page_next[n];
805 /* NOTE: this is subtle as a TB may span two physical pages */
806 if (n == 0) {
807 /* NOTE: tb_end may be after the end of the page, but
808 it is not a problem */
809 tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
810 tb_end = tb_start + tb->size;
811 } else {
812 tb_start = tb->page_addr[1];
813 tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
814 }
815 if (!(tb_end <= start || tb_start >= end)) {
bellardd720b932004-04-25 17:57:43 +0000816#ifdef TARGET_HAS_PRECISE_SMC
817 if (current_tb_not_found) {
818 current_tb_not_found = 0;
819 current_tb = NULL;
820 if (env->mem_write_pc) {
821 /* now we have a real cpu fault */
822 current_tb = tb_find_pc(env->mem_write_pc);
823 }
824 }
825 if (current_tb == tb &&
826 !(current_tb->cflags & CF_SINGLE_INSN)) {
827 /* If we are modifying the current TB, we must stop
828 its execution. We could be more precise by checking
829 that the modification is after the current PC, but it
830 would require a specialized function to partially
831 restore the CPU state */
ths3b46e622007-09-17 08:09:54 +0000832
bellardd720b932004-04-25 17:57:43 +0000833 current_tb_modified = 1;
ths5fafdf22007-09-16 21:08:06 +0000834 cpu_restore_state(current_tb, env,
bellardd720b932004-04-25 17:57:43 +0000835 env->mem_write_pc, NULL);
836#if defined(TARGET_I386)
837 current_flags = env->hflags;
838 current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
839 current_cs_base = (target_ulong)env->segs[R_CS].base;
840 current_pc = current_cs_base + env->eip;
841#else
842#error unsupported CPU
843#endif
844 }
845#endif /* TARGET_HAS_PRECISE_SMC */
bellard6f5a9f72005-11-26 20:12:28 +0000846 /* we need to do that to handle the case where a signal
847 occurs while doing tb_phys_invalidate() */
848 saved_tb = NULL;
849 if (env) {
850 saved_tb = env->current_tb;
851 env->current_tb = NULL;
852 }
bellard9fa3e852004-01-04 18:06:42 +0000853 tb_phys_invalidate(tb, -1);
bellard6f5a9f72005-11-26 20:12:28 +0000854 if (env) {
855 env->current_tb = saved_tb;
856 if (env->interrupt_request && env->current_tb)
857 cpu_interrupt(env, env->interrupt_request);
858 }
bellard9fa3e852004-01-04 18:06:42 +0000859 }
860 tb = tb_next;
861 }
862#if !defined(CONFIG_USER_ONLY)
863 /* if no code remaining, no need to continue to use slow writes */
864 if (!p->first_tb) {
865 invalidate_page_bitmap(p);
bellardd720b932004-04-25 17:57:43 +0000866 if (is_cpu_write_access) {
867 tlb_unprotect_code_phys(env, start, env->mem_write_vaddr);
868 }
869 }
870#endif
871#ifdef TARGET_HAS_PRECISE_SMC
872 if (current_tb_modified) {
873 /* we generate a block containing just the instruction
874 modifying the memory. It will ensure that it cannot modify
875 itself */
bellardea1c1802004-06-14 18:56:36 +0000876 env->current_tb = NULL;
ths5fafdf22007-09-16 21:08:06 +0000877 tb_gen_code(env, current_pc, current_cs_base, current_flags,
bellardd720b932004-04-25 17:57:43 +0000878 CF_SINGLE_INSN);
879 cpu_resume_from_signal(env, NULL);
bellard9fa3e852004-01-04 18:06:42 +0000880 }
881#endif
882}
883
884/* len must be <= 8 and start must be a multiple of len */
aurel3200f82b82008-04-27 21:12:55 +0000885static inline void tb_invalidate_phys_page_fast(target_phys_addr_t start, int len)
bellard9fa3e852004-01-04 18:06:42 +0000886{
887 PageDesc *p;
888 int offset, b;
bellard59817cc2004-02-16 22:01:13 +0000889#if 0
bellarda4193c82004-06-03 14:01:43 +0000890 if (1) {
891 if (loglevel) {
ths5fafdf22007-09-16 21:08:06 +0000892 fprintf(logfile, "modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
893 cpu_single_env->mem_write_vaddr, len,
894 cpu_single_env->eip,
bellarda4193c82004-06-03 14:01:43 +0000895 cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
896 }
bellard59817cc2004-02-16 22:01:13 +0000897 }
898#endif
bellard9fa3e852004-01-04 18:06:42 +0000899 p = page_find(start >> TARGET_PAGE_BITS);
ths5fafdf22007-09-16 21:08:06 +0000900 if (!p)
bellard9fa3e852004-01-04 18:06:42 +0000901 return;
902 if (p->code_bitmap) {
903 offset = start & ~TARGET_PAGE_MASK;
904 b = p->code_bitmap[offset >> 3] >> (offset & 7);
905 if (b & ((1 << len) - 1))
906 goto do_invalidate;
907 } else {
908 do_invalidate:
bellardd720b932004-04-25 17:57:43 +0000909 tb_invalidate_phys_page_range(start, start + len, 1);
bellard9fa3e852004-01-04 18:06:42 +0000910 }
911}
912
bellard9fa3e852004-01-04 18:06:42 +0000913#if !defined(CONFIG_SOFTMMU)
aurel3200f82b82008-04-27 21:12:55 +0000914static void tb_invalidate_phys_page(target_phys_addr_t addr,
bellardd720b932004-04-25 17:57:43 +0000915 unsigned long pc, void *puc)
bellard9fa3e852004-01-04 18:06:42 +0000916{
bellardd720b932004-04-25 17:57:43 +0000917 int n, current_flags, current_tb_modified;
918 target_ulong current_pc, current_cs_base;
bellard9fa3e852004-01-04 18:06:42 +0000919 PageDesc *p;
bellardd720b932004-04-25 17:57:43 +0000920 TranslationBlock *tb, *current_tb;
921#ifdef TARGET_HAS_PRECISE_SMC
922 CPUState *env = cpu_single_env;
923#endif
bellard9fa3e852004-01-04 18:06:42 +0000924
925 addr &= TARGET_PAGE_MASK;
926 p = page_find(addr >> TARGET_PAGE_BITS);
ths5fafdf22007-09-16 21:08:06 +0000927 if (!p)
bellardfd6ce8f2003-05-14 19:00:11 +0000928 return;
929 tb = p->first_tb;
bellardd720b932004-04-25 17:57:43 +0000930 current_tb_modified = 0;
931 current_tb = NULL;
932 current_pc = 0; /* avoid warning */
933 current_cs_base = 0; /* avoid warning */
934 current_flags = 0; /* avoid warning */
935#ifdef TARGET_HAS_PRECISE_SMC
936 if (tb && pc != 0) {
937 current_tb = tb_find_pc(pc);
938 }
939#endif
bellardfd6ce8f2003-05-14 19:00:11 +0000940 while (tb != NULL) {
bellard9fa3e852004-01-04 18:06:42 +0000941 n = (long)tb & 3;
942 tb = (TranslationBlock *)((long)tb & ~3);
bellardd720b932004-04-25 17:57:43 +0000943#ifdef TARGET_HAS_PRECISE_SMC
944 if (current_tb == tb &&
945 !(current_tb->cflags & CF_SINGLE_INSN)) {
946 /* If we are modifying the current TB, we must stop
947 its execution. We could be more precise by checking
948 that the modification is after the current PC, but it
949 would require a specialized function to partially
950 restore the CPU state */
ths3b46e622007-09-17 08:09:54 +0000951
bellardd720b932004-04-25 17:57:43 +0000952 current_tb_modified = 1;
953 cpu_restore_state(current_tb, env, pc, puc);
954#if defined(TARGET_I386)
955 current_flags = env->hflags;
956 current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
957 current_cs_base = (target_ulong)env->segs[R_CS].base;
958 current_pc = current_cs_base + env->eip;
959#else
960#error unsupported CPU
961#endif
962 }
963#endif /* TARGET_HAS_PRECISE_SMC */
bellard9fa3e852004-01-04 18:06:42 +0000964 tb_phys_invalidate(tb, addr);
965 tb = tb->page_next[n];
bellardfd6ce8f2003-05-14 19:00:11 +0000966 }
967 p->first_tb = NULL;
bellardd720b932004-04-25 17:57:43 +0000968#ifdef TARGET_HAS_PRECISE_SMC
969 if (current_tb_modified) {
970 /* we generate a block containing just the instruction
971 modifying the memory. It will ensure that it cannot modify
972 itself */
bellardea1c1802004-06-14 18:56:36 +0000973 env->current_tb = NULL;
ths5fafdf22007-09-16 21:08:06 +0000974 tb_gen_code(env, current_pc, current_cs_base, current_flags,
bellardd720b932004-04-25 17:57:43 +0000975 CF_SINGLE_INSN);
976 cpu_resume_from_signal(env, puc);
977 }
978#endif
bellardfd6ce8f2003-05-14 19:00:11 +0000979}
bellard9fa3e852004-01-04 18:06:42 +0000980#endif
bellardfd6ce8f2003-05-14 19:00:11 +0000981
982/* add the tb in the target page and protect it if necessary */
ths5fafdf22007-09-16 21:08:06 +0000983static inline void tb_alloc_page(TranslationBlock *tb,
pbrook53a59602006-03-25 19:31:22 +0000984 unsigned int n, target_ulong page_addr)
bellardfd6ce8f2003-05-14 19:00:11 +0000985{
986 PageDesc *p;
bellard9fa3e852004-01-04 18:06:42 +0000987 TranslationBlock *last_first_tb;
bellardfd6ce8f2003-05-14 19:00:11 +0000988
bellard9fa3e852004-01-04 18:06:42 +0000989 tb->page_addr[n] = page_addr;
bellard3a7d9292005-08-21 09:26:42 +0000990 p = page_find_alloc(page_addr >> TARGET_PAGE_BITS);
bellard9fa3e852004-01-04 18:06:42 +0000991 tb->page_next[n] = p->first_tb;
992 last_first_tb = p->first_tb;
993 p->first_tb = (TranslationBlock *)((long)tb | n);
994 invalidate_page_bitmap(p);
995
bellard107db442004-06-22 18:48:46 +0000996#if defined(TARGET_HAS_SMC) || 1
bellardd720b932004-04-25 17:57:43 +0000997
bellard9fa3e852004-01-04 18:06:42 +0000998#if defined(CONFIG_USER_ONLY)
bellardfd6ce8f2003-05-14 19:00:11 +0000999 if (p->flags & PAGE_WRITE) {
pbrook53a59602006-03-25 19:31:22 +00001000 target_ulong addr;
1001 PageDesc *p2;
bellard9fa3e852004-01-04 18:06:42 +00001002 int prot;
1003
bellardfd6ce8f2003-05-14 19:00:11 +00001004 /* force the host page as non writable (writes will have a
1005 page fault + mprotect overhead) */
pbrook53a59602006-03-25 19:31:22 +00001006 page_addr &= qemu_host_page_mask;
bellardfd6ce8f2003-05-14 19:00:11 +00001007 prot = 0;
pbrook53a59602006-03-25 19:31:22 +00001008 for(addr = page_addr; addr < page_addr + qemu_host_page_size;
1009 addr += TARGET_PAGE_SIZE) {
1010
1011 p2 = page_find (addr >> TARGET_PAGE_BITS);
1012 if (!p2)
1013 continue;
1014 prot |= p2->flags;
1015 p2->flags &= ~PAGE_WRITE;
1016 page_get_flags(addr);
1017 }
ths5fafdf22007-09-16 21:08:06 +00001018 mprotect(g2h(page_addr), qemu_host_page_size,
bellardfd6ce8f2003-05-14 19:00:11 +00001019 (prot & PAGE_BITS) & ~PAGE_WRITE);
1020#ifdef DEBUG_TB_INVALIDATE
blueswir1ab3d1722007-11-04 07:31:40 +00001021 printf("protecting code page: 0x" TARGET_FMT_lx "\n",
pbrook53a59602006-03-25 19:31:22 +00001022 page_addr);
bellardfd6ce8f2003-05-14 19:00:11 +00001023#endif
bellardfd6ce8f2003-05-14 19:00:11 +00001024 }
bellard9fa3e852004-01-04 18:06:42 +00001025#else
1026 /* if some code is already present, then the pages are already
1027 protected. So we handle the case where only the first TB is
1028 allocated in a physical page */
1029 if (!last_first_tb) {
bellard6a00d602005-11-21 23:25:50 +00001030 tlb_protect_code(page_addr);
bellard9fa3e852004-01-04 18:06:42 +00001031 }
1032#endif
bellardd720b932004-04-25 17:57:43 +00001033
1034#endif /* TARGET_HAS_SMC */
bellardfd6ce8f2003-05-14 19:00:11 +00001035}
1036
1037/* Allocate a new translation block. Flush the translation buffer if
1038 too many translation blocks or too much generated code. */
bellardc27004e2005-01-03 23:35:10 +00001039TranslationBlock *tb_alloc(target_ulong pc)
bellardfd6ce8f2003-05-14 19:00:11 +00001040{
1041 TranslationBlock *tb;
bellardfd6ce8f2003-05-14 19:00:11 +00001042
bellard26a5f132008-05-28 12:30:31 +00001043 if (nb_tbs >= code_gen_max_blocks ||
1044 (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
bellardd4e81642003-05-25 16:46:15 +00001045 return NULL;
bellardfd6ce8f2003-05-14 19:00:11 +00001046 tb = &tbs[nb_tbs++];
1047 tb->pc = pc;
bellardb448f2f2004-02-25 23:24:04 +00001048 tb->cflags = 0;
bellardd4e81642003-05-25 16:46:15 +00001049 return tb;
1050}
1051
bellard9fa3e852004-01-04 18:06:42 +00001052/* add a new TB and link it to the physical page tables. phys_page2 is
1053 (-1) to indicate that only one page contains the TB. */
ths5fafdf22007-09-16 21:08:06 +00001054void tb_link_phys(TranslationBlock *tb,
bellard9fa3e852004-01-04 18:06:42 +00001055 target_ulong phys_pc, target_ulong phys_page2)
bellardd4e81642003-05-25 16:46:15 +00001056{
bellard9fa3e852004-01-04 18:06:42 +00001057 unsigned int h;
1058 TranslationBlock **ptb;
1059
pbrookc8a706f2008-06-02 16:16:42 +00001060 /* Grab the mmap lock to stop another thread invalidating this TB
1061 before we are done. */
1062 mmap_lock();
bellard9fa3e852004-01-04 18:06:42 +00001063 /* add in the physical hash table */
1064 h = tb_phys_hash_func(phys_pc);
1065 ptb = &tb_phys_hash[h];
1066 tb->phys_hash_next = *ptb;
1067 *ptb = tb;
bellardfd6ce8f2003-05-14 19:00:11 +00001068
1069 /* add in the page list */
bellard9fa3e852004-01-04 18:06:42 +00001070 tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK);
1071 if (phys_page2 != -1)
1072 tb_alloc_page(tb, 1, phys_page2);
1073 else
1074 tb->page_addr[1] = -1;
bellard9fa3e852004-01-04 18:06:42 +00001075
bellardd4e81642003-05-25 16:46:15 +00001076 tb->jmp_first = (TranslationBlock *)((long)tb | 2);
1077 tb->jmp_next[0] = NULL;
1078 tb->jmp_next[1] = NULL;
1079
1080 /* init original jump addresses */
1081 if (tb->tb_next_offset[0] != 0xffff)
1082 tb_reset_jump(tb, 0);
1083 if (tb->tb_next_offset[1] != 0xffff)
1084 tb_reset_jump(tb, 1);
bellard8a40a182005-11-20 10:35:40 +00001085
1086#ifdef DEBUG_TB_CHECK
1087 tb_page_check();
1088#endif
pbrookc8a706f2008-06-02 16:16:42 +00001089 mmap_unlock();
bellardfd6ce8f2003-05-14 19:00:11 +00001090}
1091
bellarda513fe12003-05-27 23:29:48 +00001092/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
1093 tb[1].tc_ptr. Return NULL if not found */
1094TranslationBlock *tb_find_pc(unsigned long tc_ptr)
1095{
1096 int m_min, m_max, m;
1097 unsigned long v;
1098 TranslationBlock *tb;
1099
1100 if (nb_tbs <= 0)
1101 return NULL;
1102 if (tc_ptr < (unsigned long)code_gen_buffer ||
1103 tc_ptr >= (unsigned long)code_gen_ptr)
1104 return NULL;
1105 /* binary search (cf Knuth) */
1106 m_min = 0;
1107 m_max = nb_tbs - 1;
1108 while (m_min <= m_max) {
1109 m = (m_min + m_max) >> 1;
1110 tb = &tbs[m];
1111 v = (unsigned long)tb->tc_ptr;
1112 if (v == tc_ptr)
1113 return tb;
1114 else if (tc_ptr < v) {
1115 m_max = m - 1;
1116 } else {
1117 m_min = m + 1;
1118 }
ths5fafdf22007-09-16 21:08:06 +00001119 }
bellarda513fe12003-05-27 23:29:48 +00001120 return &tbs[m_max];
1121}
bellard75012672003-06-21 13:11:07 +00001122
bellardea041c02003-06-25 16:16:50 +00001123static void tb_reset_jump_recursive(TranslationBlock *tb);
1124
1125static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
1126{
1127 TranslationBlock *tb1, *tb_next, **ptb;
1128 unsigned int n1;
1129
1130 tb1 = tb->jmp_next[n];
1131 if (tb1 != NULL) {
1132 /* find head of list */
1133 for(;;) {
1134 n1 = (long)tb1 & 3;
1135 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1136 if (n1 == 2)
1137 break;
1138 tb1 = tb1->jmp_next[n1];
1139 }
1140 /* we are now sure now that tb jumps to tb1 */
1141 tb_next = tb1;
1142
1143 /* remove tb from the jmp_first list */
1144 ptb = &tb_next->jmp_first;
1145 for(;;) {
1146 tb1 = *ptb;
1147 n1 = (long)tb1 & 3;
1148 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1149 if (n1 == n && tb1 == tb)
1150 break;
1151 ptb = &tb1->jmp_next[n1];
1152 }
1153 *ptb = tb->jmp_next[n];
1154 tb->jmp_next[n] = NULL;
ths3b46e622007-09-17 08:09:54 +00001155
bellardea041c02003-06-25 16:16:50 +00001156 /* suppress the jump to next tb in generated code */
1157 tb_reset_jump(tb, n);
1158
bellard01243112004-01-04 15:48:17 +00001159 /* suppress jumps in the tb on which we could have jumped */
bellardea041c02003-06-25 16:16:50 +00001160 tb_reset_jump_recursive(tb_next);
1161 }
1162}
1163
1164static void tb_reset_jump_recursive(TranslationBlock *tb)
1165{
1166 tb_reset_jump_recursive2(tb, 0);
1167 tb_reset_jump_recursive2(tb, 1);
1168}
1169
bellard1fddef42005-04-17 19:16:13 +00001170#if defined(TARGET_HAS_ICE)
bellardd720b932004-04-25 17:57:43 +00001171static void breakpoint_invalidate(CPUState *env, target_ulong pc)
1172{
j_mayer9b3c35e2007-04-07 11:21:28 +00001173 target_phys_addr_t addr;
1174 target_ulong pd;
pbrookc2f07f82006-04-08 17:14:56 +00001175 ram_addr_t ram_addr;
1176 PhysPageDesc *p;
bellardd720b932004-04-25 17:57:43 +00001177
pbrookc2f07f82006-04-08 17:14:56 +00001178 addr = cpu_get_phys_page_debug(env, pc);
1179 p = phys_page_find(addr >> TARGET_PAGE_BITS);
1180 if (!p) {
1181 pd = IO_MEM_UNASSIGNED;
1182 } else {
1183 pd = p->phys_offset;
1184 }
1185 ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
pbrook706cd4b2006-04-08 17:36:21 +00001186 tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
bellardd720b932004-04-25 17:57:43 +00001187}
bellardc27004e2005-01-03 23:35:10 +00001188#endif
bellardd720b932004-04-25 17:57:43 +00001189
pbrook6658ffb2007-03-16 23:58:11 +00001190/* Add a watchpoint. */
pbrook0f459d12008-06-09 00:20:13 +00001191int cpu_watchpoint_insert(CPUState *env, target_ulong addr, int type)
pbrook6658ffb2007-03-16 23:58:11 +00001192{
1193 int i;
1194
1195 for (i = 0; i < env->nb_watchpoints; i++) {
1196 if (addr == env->watchpoint[i].vaddr)
1197 return 0;
1198 }
1199 if (env->nb_watchpoints >= MAX_WATCHPOINTS)
1200 return -1;
1201
1202 i = env->nb_watchpoints++;
1203 env->watchpoint[i].vaddr = addr;
pbrook0f459d12008-06-09 00:20:13 +00001204 env->watchpoint[i].type = type;
pbrook6658ffb2007-03-16 23:58:11 +00001205 tlb_flush_page(env, addr);
1206 /* FIXME: This flush is needed because of the hack to make memory ops
1207 terminate the TB. It can be removed once the proper IO trap and
1208 re-execute bits are in. */
1209 tb_flush(env);
1210 return i;
1211}
1212
1213/* Remove a watchpoint. */
1214int cpu_watchpoint_remove(CPUState *env, target_ulong addr)
1215{
1216 int i;
1217
1218 for (i = 0; i < env->nb_watchpoints; i++) {
1219 if (addr == env->watchpoint[i].vaddr) {
1220 env->nb_watchpoints--;
1221 env->watchpoint[i] = env->watchpoint[env->nb_watchpoints];
1222 tlb_flush_page(env, addr);
1223 return 0;
1224 }
1225 }
1226 return -1;
1227}
1228
edgar_igl7d03f822008-05-17 18:58:29 +00001229/* Remove all watchpoints. */
1230void cpu_watchpoint_remove_all(CPUState *env) {
1231 int i;
1232
1233 for (i = 0; i < env->nb_watchpoints; i++) {
1234 tlb_flush_page(env, env->watchpoint[i].vaddr);
1235 }
1236 env->nb_watchpoints = 0;
1237}
1238
bellardc33a3462003-07-29 20:50:33 +00001239/* add a breakpoint. EXCP_DEBUG is returned by the CPU loop if a
1240 breakpoint is reached */
bellard2e126692004-04-25 21:28:44 +00001241int cpu_breakpoint_insert(CPUState *env, target_ulong pc)
bellard4c3a88a2003-07-26 12:06:08 +00001242{
bellard1fddef42005-04-17 19:16:13 +00001243#if defined(TARGET_HAS_ICE)
bellard4c3a88a2003-07-26 12:06:08 +00001244 int i;
ths3b46e622007-09-17 08:09:54 +00001245
bellard4c3a88a2003-07-26 12:06:08 +00001246 for(i = 0; i < env->nb_breakpoints; i++) {
1247 if (env->breakpoints[i] == pc)
1248 return 0;
1249 }
1250
1251 if (env->nb_breakpoints >= MAX_BREAKPOINTS)
1252 return -1;
1253 env->breakpoints[env->nb_breakpoints++] = pc;
ths3b46e622007-09-17 08:09:54 +00001254
bellardd720b932004-04-25 17:57:43 +00001255 breakpoint_invalidate(env, pc);
bellard4c3a88a2003-07-26 12:06:08 +00001256 return 0;
1257#else
1258 return -1;
1259#endif
1260}
1261
edgar_igl7d03f822008-05-17 18:58:29 +00001262/* remove all breakpoints */
1263void cpu_breakpoint_remove_all(CPUState *env) {
1264#if defined(TARGET_HAS_ICE)
1265 int i;
1266 for(i = 0; i < env->nb_breakpoints; i++) {
1267 breakpoint_invalidate(env, env->breakpoints[i]);
1268 }
1269 env->nb_breakpoints = 0;
1270#endif
1271}
1272
bellard4c3a88a2003-07-26 12:06:08 +00001273/* remove a breakpoint */
bellard2e126692004-04-25 21:28:44 +00001274int cpu_breakpoint_remove(CPUState *env, target_ulong pc)
bellard4c3a88a2003-07-26 12:06:08 +00001275{
bellard1fddef42005-04-17 19:16:13 +00001276#if defined(TARGET_HAS_ICE)
bellard4c3a88a2003-07-26 12:06:08 +00001277 int i;
1278 for(i = 0; i < env->nb_breakpoints; i++) {
1279 if (env->breakpoints[i] == pc)
1280 goto found;
1281 }
1282 return -1;
1283 found:
bellard4c3a88a2003-07-26 12:06:08 +00001284 env->nb_breakpoints--;
bellard1fddef42005-04-17 19:16:13 +00001285 if (i < env->nb_breakpoints)
1286 env->breakpoints[i] = env->breakpoints[env->nb_breakpoints];
bellardd720b932004-04-25 17:57:43 +00001287
1288 breakpoint_invalidate(env, pc);
bellard4c3a88a2003-07-26 12:06:08 +00001289 return 0;
1290#else
1291 return -1;
1292#endif
1293}
1294
bellardc33a3462003-07-29 20:50:33 +00001295/* enable or disable single step mode. EXCP_DEBUG is returned by the
1296 CPU loop after each instruction */
1297void cpu_single_step(CPUState *env, int enabled)
1298{
bellard1fddef42005-04-17 19:16:13 +00001299#if defined(TARGET_HAS_ICE)
bellardc33a3462003-07-29 20:50:33 +00001300 if (env->singlestep_enabled != enabled) {
1301 env->singlestep_enabled = enabled;
1302 /* must flush all the translated code to avoid inconsistancies */
bellard9fa3e852004-01-04 18:06:42 +00001303 /* XXX: only flush what is necessary */
bellard01243112004-01-04 15:48:17 +00001304 tb_flush(env);
bellardc33a3462003-07-29 20:50:33 +00001305 }
1306#endif
1307}
1308
bellard34865132003-10-05 14:28:56 +00001309/* enable or disable low levels log */
1310void cpu_set_log(int log_flags)
1311{
1312 loglevel = log_flags;
1313 if (loglevel && !logfile) {
pbrook11fcfab2007-07-01 18:21:11 +00001314 logfile = fopen(logfilename, log_append ? "a" : "w");
bellard34865132003-10-05 14:28:56 +00001315 if (!logfile) {
1316 perror(logfilename);
1317 _exit(1);
1318 }
bellard9fa3e852004-01-04 18:06:42 +00001319#if !defined(CONFIG_SOFTMMU)
1320 /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1321 {
1322 static uint8_t logfile_buf[4096];
1323 setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1324 }
1325#else
bellard34865132003-10-05 14:28:56 +00001326 setvbuf(logfile, NULL, _IOLBF, 0);
bellard9fa3e852004-01-04 18:06:42 +00001327#endif
pbrooke735b912007-06-30 13:53:24 +00001328 log_append = 1;
1329 }
1330 if (!loglevel && logfile) {
1331 fclose(logfile);
1332 logfile = NULL;
bellard34865132003-10-05 14:28:56 +00001333 }
1334}
1335
1336void cpu_set_log_filename(const char *filename)
1337{
1338 logfilename = strdup(filename);
pbrooke735b912007-06-30 13:53:24 +00001339 if (logfile) {
1340 fclose(logfile);
1341 logfile = NULL;
1342 }
1343 cpu_set_log(loglevel);
bellard34865132003-10-05 14:28:56 +00001344}
bellardc33a3462003-07-29 20:50:33 +00001345
bellard01243112004-01-04 15:48:17 +00001346/* mask must never be zero, except for A20 change call */
bellard68a79312003-06-30 13:12:32 +00001347void cpu_interrupt(CPUState *env, int mask)
bellardea041c02003-06-25 16:16:50 +00001348{
pbrookd5975362008-06-07 20:50:51 +00001349#if !defined(USE_NPTL)
bellardea041c02003-06-25 16:16:50 +00001350 TranslationBlock *tb;
aurel3215a51152008-03-28 22:29:15 +00001351 static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
pbrookd5975362008-06-07 20:50:51 +00001352#endif
bellard59817cc2004-02-16 22:01:13 +00001353
pbrookd5975362008-06-07 20:50:51 +00001354 /* FIXME: This is probably not threadsafe. A different thread could
1355 be in the mittle of a read-modify-write operation. */
bellard68a79312003-06-30 13:12:32 +00001356 env->interrupt_request |= mask;
pbrookd5975362008-06-07 20:50:51 +00001357#if defined(USE_NPTL)
1358 /* FIXME: TB unchaining isn't SMP safe. For now just ignore the
1359 problem and hope the cpu will stop of its own accord. For userspace
1360 emulation this often isn't actually as bad as it sounds. Often
1361 signals are used primarily to interrupt blocking syscalls. */
1362#else
bellardea041c02003-06-25 16:16:50 +00001363 /* if the cpu is currently executing code, we must unlink it and
1364 all the potentially executing TB */
1365 tb = env->current_tb;
bellardee8b7022004-02-03 23:35:10 +00001366 if (tb && !testandset(&interrupt_lock)) {
1367 env->current_tb = NULL;
bellardea041c02003-06-25 16:16:50 +00001368 tb_reset_jump_recursive(tb);
aurel3215a51152008-03-28 22:29:15 +00001369 resetlock(&interrupt_lock);
bellardea041c02003-06-25 16:16:50 +00001370 }
pbrookd5975362008-06-07 20:50:51 +00001371#endif
bellardea041c02003-06-25 16:16:50 +00001372}
1373
bellardb54ad042004-05-20 13:42:52 +00001374void cpu_reset_interrupt(CPUState *env, int mask)
1375{
1376 env->interrupt_request &= ~mask;
1377}
1378
bellardf193c792004-03-21 17:06:25 +00001379CPULogItem cpu_log_items[] = {
ths5fafdf22007-09-16 21:08:06 +00001380 { CPU_LOG_TB_OUT_ASM, "out_asm",
bellardf193c792004-03-21 17:06:25 +00001381 "show generated host assembly code for each compiled TB" },
1382 { CPU_LOG_TB_IN_ASM, "in_asm",
1383 "show target assembly code for each compiled TB" },
ths5fafdf22007-09-16 21:08:06 +00001384 { CPU_LOG_TB_OP, "op",
bellard57fec1f2008-02-01 10:50:11 +00001385 "show micro ops for each compiled TB" },
bellardf193c792004-03-21 17:06:25 +00001386 { CPU_LOG_TB_OP_OPT, "op_opt",
blueswir1e01a1152008-03-14 17:37:11 +00001387 "show micro ops "
1388#ifdef TARGET_I386
1389 "before eflags optimization and "
bellardf193c792004-03-21 17:06:25 +00001390#endif
blueswir1e01a1152008-03-14 17:37:11 +00001391 "after liveness analysis" },
bellardf193c792004-03-21 17:06:25 +00001392 { CPU_LOG_INT, "int",
1393 "show interrupts/exceptions in short format" },
1394 { CPU_LOG_EXEC, "exec",
1395 "show trace before each executed TB (lots of logs)" },
bellard9fddaa02004-05-21 12:59:32 +00001396 { CPU_LOG_TB_CPU, "cpu",
thse91c8a72007-06-03 13:35:16 +00001397 "show CPU state before block translation" },
bellardf193c792004-03-21 17:06:25 +00001398#ifdef TARGET_I386
1399 { CPU_LOG_PCALL, "pcall",
1400 "show protected mode far calls/returns/exceptions" },
1401#endif
bellard8e3a9fd2004-10-09 17:32:58 +00001402#ifdef DEBUG_IOPORT
bellardfd872592004-05-12 19:11:15 +00001403 { CPU_LOG_IOPORT, "ioport",
1404 "show all i/o ports accesses" },
bellard8e3a9fd2004-10-09 17:32:58 +00001405#endif
bellardf193c792004-03-21 17:06:25 +00001406 { 0, NULL, NULL },
1407};
1408
1409static int cmp1(const char *s1, int n, const char *s2)
1410{
1411 if (strlen(s2) != n)
1412 return 0;
1413 return memcmp(s1, s2, n) == 0;
1414}
ths3b46e622007-09-17 08:09:54 +00001415
bellardf193c792004-03-21 17:06:25 +00001416/* takes a comma separated list of log masks. Return 0 if error. */
1417int cpu_str_to_log_mask(const char *str)
1418{
1419 CPULogItem *item;
1420 int mask;
1421 const char *p, *p1;
1422
1423 p = str;
1424 mask = 0;
1425 for(;;) {
1426 p1 = strchr(p, ',');
1427 if (!p1)
1428 p1 = p + strlen(p);
bellard8e3a9fd2004-10-09 17:32:58 +00001429 if(cmp1(p,p1-p,"all")) {
1430 for(item = cpu_log_items; item->mask != 0; item++) {
1431 mask |= item->mask;
1432 }
1433 } else {
bellardf193c792004-03-21 17:06:25 +00001434 for(item = cpu_log_items; item->mask != 0; item++) {
1435 if (cmp1(p, p1 - p, item->name))
1436 goto found;
1437 }
1438 return 0;
bellard8e3a9fd2004-10-09 17:32:58 +00001439 }
bellardf193c792004-03-21 17:06:25 +00001440 found:
1441 mask |= item->mask;
1442 if (*p1 != ',')
1443 break;
1444 p = p1 + 1;
1445 }
1446 return mask;
1447}
bellardea041c02003-06-25 16:16:50 +00001448
bellard75012672003-06-21 13:11:07 +00001449void cpu_abort(CPUState *env, const char *fmt, ...)
1450{
1451 va_list ap;
pbrook493ae1f2007-11-23 16:53:59 +00001452 va_list ap2;
bellard75012672003-06-21 13:11:07 +00001453
1454 va_start(ap, fmt);
pbrook493ae1f2007-11-23 16:53:59 +00001455 va_copy(ap2, ap);
bellard75012672003-06-21 13:11:07 +00001456 fprintf(stderr, "qemu: fatal: ");
1457 vfprintf(stderr, fmt, ap);
1458 fprintf(stderr, "\n");
1459#ifdef TARGET_I386
bellard7fe48482004-10-09 18:08:01 +00001460 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1461#else
1462 cpu_dump_state(env, stderr, fprintf, 0);
bellard75012672003-06-21 13:11:07 +00001463#endif
balrog924edca2007-06-10 14:07:13 +00001464 if (logfile) {
j_mayerf9373292007-09-29 12:18:20 +00001465 fprintf(logfile, "qemu: fatal: ");
pbrook493ae1f2007-11-23 16:53:59 +00001466 vfprintf(logfile, fmt, ap2);
j_mayerf9373292007-09-29 12:18:20 +00001467 fprintf(logfile, "\n");
1468#ifdef TARGET_I386
1469 cpu_dump_state(env, logfile, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1470#else
1471 cpu_dump_state(env, logfile, fprintf, 0);
1472#endif
balrog924edca2007-06-10 14:07:13 +00001473 fflush(logfile);
1474 fclose(logfile);
1475 }
pbrook493ae1f2007-11-23 16:53:59 +00001476 va_end(ap2);
j_mayerf9373292007-09-29 12:18:20 +00001477 va_end(ap);
bellard75012672003-06-21 13:11:07 +00001478 abort();
1479}
1480
thsc5be9f02007-02-28 20:20:53 +00001481CPUState *cpu_copy(CPUState *env)
1482{
ths01ba9812007-12-09 02:22:57 +00001483 CPUState *new_env = cpu_init(env->cpu_model_str);
thsc5be9f02007-02-28 20:20:53 +00001484 /* preserve chaining and index */
1485 CPUState *next_cpu = new_env->next_cpu;
1486 int cpu_index = new_env->cpu_index;
1487 memcpy(new_env, env, sizeof(CPUState));
1488 new_env->next_cpu = next_cpu;
1489 new_env->cpu_index = cpu_index;
1490 return new_env;
1491}
1492
bellard01243112004-01-04 15:48:17 +00001493#if !defined(CONFIG_USER_ONLY)
1494
edgar_igl5c751e92008-05-06 08:44:21 +00001495static inline void tlb_flush_jmp_cache(CPUState *env, target_ulong addr)
1496{
1497 unsigned int i;
1498
1499 /* Discard jump cache entries for any tb which might potentially
1500 overlap the flushed page. */
1501 i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
1502 memset (&env->tb_jmp_cache[i], 0,
1503 TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
1504
1505 i = tb_jmp_cache_hash_page(addr);
1506 memset (&env->tb_jmp_cache[i], 0,
1507 TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
1508}
1509
bellardee8b7022004-02-03 23:35:10 +00001510/* NOTE: if flush_global is true, also flush global entries (not
1511 implemented yet) */
1512void tlb_flush(CPUState *env, int flush_global)
bellard33417e72003-08-10 21:47:01 +00001513{
bellard33417e72003-08-10 21:47:01 +00001514 int i;
bellard01243112004-01-04 15:48:17 +00001515
bellard9fa3e852004-01-04 18:06:42 +00001516#if defined(DEBUG_TLB)
1517 printf("tlb_flush:\n");
1518#endif
bellard01243112004-01-04 15:48:17 +00001519 /* must reset current TB so that interrupts cannot modify the
1520 links while we are modifying them */
1521 env->current_tb = NULL;
1522
bellard33417e72003-08-10 21:47:01 +00001523 for(i = 0; i < CPU_TLB_SIZE; i++) {
bellard84b7b8e2005-11-28 21:19:04 +00001524 env->tlb_table[0][i].addr_read = -1;
1525 env->tlb_table[0][i].addr_write = -1;
1526 env->tlb_table[0][i].addr_code = -1;
1527 env->tlb_table[1][i].addr_read = -1;
1528 env->tlb_table[1][i].addr_write = -1;
1529 env->tlb_table[1][i].addr_code = -1;
j_mayer6fa4cea2007-04-05 06:43:27 +00001530#if (NB_MMU_MODES >= 3)
1531 env->tlb_table[2][i].addr_read = -1;
1532 env->tlb_table[2][i].addr_write = -1;
1533 env->tlb_table[2][i].addr_code = -1;
1534#if (NB_MMU_MODES == 4)
1535 env->tlb_table[3][i].addr_read = -1;
1536 env->tlb_table[3][i].addr_write = -1;
1537 env->tlb_table[3][i].addr_code = -1;
1538#endif
1539#endif
bellard33417e72003-08-10 21:47:01 +00001540 }
bellard9fa3e852004-01-04 18:06:42 +00001541
bellard8a40a182005-11-20 10:35:40 +00001542 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
bellard9fa3e852004-01-04 18:06:42 +00001543
bellard0a962c02005-02-10 22:00:27 +00001544#ifdef USE_KQEMU
1545 if (env->kqemu_enabled) {
1546 kqemu_flush(env, flush_global);
1547 }
1548#endif
bellarde3db7222005-01-26 22:00:47 +00001549 tlb_flush_count++;
bellard33417e72003-08-10 21:47:01 +00001550}
1551
bellard274da6b2004-05-20 21:56:27 +00001552static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
bellard61382a52003-10-27 21:22:23 +00001553{
ths5fafdf22007-09-16 21:08:06 +00001554 if (addr == (tlb_entry->addr_read &
bellard84b7b8e2005-11-28 21:19:04 +00001555 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
ths5fafdf22007-09-16 21:08:06 +00001556 addr == (tlb_entry->addr_write &
bellard84b7b8e2005-11-28 21:19:04 +00001557 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
ths5fafdf22007-09-16 21:08:06 +00001558 addr == (tlb_entry->addr_code &
bellard84b7b8e2005-11-28 21:19:04 +00001559 (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1560 tlb_entry->addr_read = -1;
1561 tlb_entry->addr_write = -1;
1562 tlb_entry->addr_code = -1;
1563 }
bellard61382a52003-10-27 21:22:23 +00001564}
1565
bellard2e126692004-04-25 21:28:44 +00001566void tlb_flush_page(CPUState *env, target_ulong addr)
bellard33417e72003-08-10 21:47:01 +00001567{
bellard8a40a182005-11-20 10:35:40 +00001568 int i;
bellard01243112004-01-04 15:48:17 +00001569
bellard9fa3e852004-01-04 18:06:42 +00001570#if defined(DEBUG_TLB)
bellard108c49b2005-07-24 12:55:09 +00001571 printf("tlb_flush_page: " TARGET_FMT_lx "\n", addr);
bellard9fa3e852004-01-04 18:06:42 +00001572#endif
bellard01243112004-01-04 15:48:17 +00001573 /* must reset current TB so that interrupts cannot modify the
1574 links while we are modifying them */
1575 env->current_tb = NULL;
bellard33417e72003-08-10 21:47:01 +00001576
bellard61382a52003-10-27 21:22:23 +00001577 addr &= TARGET_PAGE_MASK;
bellard33417e72003-08-10 21:47:01 +00001578 i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
bellard84b7b8e2005-11-28 21:19:04 +00001579 tlb_flush_entry(&env->tlb_table[0][i], addr);
1580 tlb_flush_entry(&env->tlb_table[1][i], addr);
j_mayer6fa4cea2007-04-05 06:43:27 +00001581#if (NB_MMU_MODES >= 3)
1582 tlb_flush_entry(&env->tlb_table[2][i], addr);
1583#if (NB_MMU_MODES == 4)
1584 tlb_flush_entry(&env->tlb_table[3][i], addr);
1585#endif
1586#endif
bellard01243112004-01-04 15:48:17 +00001587
edgar_igl5c751e92008-05-06 08:44:21 +00001588 tlb_flush_jmp_cache(env, addr);
bellard9fa3e852004-01-04 18:06:42 +00001589
bellard0a962c02005-02-10 22:00:27 +00001590#ifdef USE_KQEMU
1591 if (env->kqemu_enabled) {
1592 kqemu_flush_page(env, addr);
1593 }
1594#endif
bellard9fa3e852004-01-04 18:06:42 +00001595}
1596
bellard9fa3e852004-01-04 18:06:42 +00001597/* update the TLBs so that writes to code in the virtual page 'addr'
1598 can be detected */
bellard6a00d602005-11-21 23:25:50 +00001599static void tlb_protect_code(ram_addr_t ram_addr)
bellard61382a52003-10-27 21:22:23 +00001600{
ths5fafdf22007-09-16 21:08:06 +00001601 cpu_physical_memory_reset_dirty(ram_addr,
bellard6a00d602005-11-21 23:25:50 +00001602 ram_addr + TARGET_PAGE_SIZE,
1603 CODE_DIRTY_FLAG);
bellard9fa3e852004-01-04 18:06:42 +00001604}
1605
bellard9fa3e852004-01-04 18:06:42 +00001606/* update the TLB so that writes in physical page 'phys_addr' are no longer
bellard3a7d9292005-08-21 09:26:42 +00001607 tested for self modifying code */
ths5fafdf22007-09-16 21:08:06 +00001608static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
bellard3a7d9292005-08-21 09:26:42 +00001609 target_ulong vaddr)
bellard9fa3e852004-01-04 18:06:42 +00001610{
bellard3a7d9292005-08-21 09:26:42 +00001611 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] |= CODE_DIRTY_FLAG;
bellard1ccde1c2004-02-06 19:46:14 +00001612}
1613
ths5fafdf22007-09-16 21:08:06 +00001614static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
bellard1ccde1c2004-02-06 19:46:14 +00001615 unsigned long start, unsigned long length)
1616{
1617 unsigned long addr;
bellard84b7b8e2005-11-28 21:19:04 +00001618 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1619 addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
bellard1ccde1c2004-02-06 19:46:14 +00001620 if ((addr - start) < length) {
pbrook0f459d12008-06-09 00:20:13 +00001621 tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
bellard1ccde1c2004-02-06 19:46:14 +00001622 }
1623 }
1624}
1625
bellard3a7d9292005-08-21 09:26:42 +00001626void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
bellard0a962c02005-02-10 22:00:27 +00001627 int dirty_flags)
bellard1ccde1c2004-02-06 19:46:14 +00001628{
1629 CPUState *env;
bellard4f2ac232004-04-26 19:44:02 +00001630 unsigned long length, start1;
bellard0a962c02005-02-10 22:00:27 +00001631 int i, mask, len;
1632 uint8_t *p;
bellard1ccde1c2004-02-06 19:46:14 +00001633
1634 start &= TARGET_PAGE_MASK;
1635 end = TARGET_PAGE_ALIGN(end);
1636
1637 length = end - start;
1638 if (length == 0)
1639 return;
bellard0a962c02005-02-10 22:00:27 +00001640 len = length >> TARGET_PAGE_BITS;
bellard3a7d9292005-08-21 09:26:42 +00001641#ifdef USE_KQEMU
bellard6a00d602005-11-21 23:25:50 +00001642 /* XXX: should not depend on cpu context */
1643 env = first_cpu;
bellard3a7d9292005-08-21 09:26:42 +00001644 if (env->kqemu_enabled) {
bellardf23db162005-08-21 19:12:28 +00001645 ram_addr_t addr;
1646 addr = start;
1647 for(i = 0; i < len; i++) {
1648 kqemu_set_notdirty(env, addr);
1649 addr += TARGET_PAGE_SIZE;
1650 }
bellard3a7d9292005-08-21 09:26:42 +00001651 }
1652#endif
bellardf23db162005-08-21 19:12:28 +00001653 mask = ~dirty_flags;
1654 p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
1655 for(i = 0; i < len; i++)
1656 p[i] &= mask;
1657
bellard1ccde1c2004-02-06 19:46:14 +00001658 /* we modify the TLB cache so that the dirty bit will be set again
1659 when accessing the range */
bellard59817cc2004-02-16 22:01:13 +00001660 start1 = start + (unsigned long)phys_ram_base;
bellard6a00d602005-11-21 23:25:50 +00001661 for(env = first_cpu; env != NULL; env = env->next_cpu) {
1662 for(i = 0; i < CPU_TLB_SIZE; i++)
bellard84b7b8e2005-11-28 21:19:04 +00001663 tlb_reset_dirty_range(&env->tlb_table[0][i], start1, length);
bellard6a00d602005-11-21 23:25:50 +00001664 for(i = 0; i < CPU_TLB_SIZE; i++)
bellard84b7b8e2005-11-28 21:19:04 +00001665 tlb_reset_dirty_range(&env->tlb_table[1][i], start1, length);
j_mayer6fa4cea2007-04-05 06:43:27 +00001666#if (NB_MMU_MODES >= 3)
1667 for(i = 0; i < CPU_TLB_SIZE; i++)
1668 tlb_reset_dirty_range(&env->tlb_table[2][i], start1, length);
1669#if (NB_MMU_MODES == 4)
1670 for(i = 0; i < CPU_TLB_SIZE; i++)
1671 tlb_reset_dirty_range(&env->tlb_table[3][i], start1, length);
1672#endif
1673#endif
bellard6a00d602005-11-21 23:25:50 +00001674 }
bellard1ccde1c2004-02-06 19:46:14 +00001675}
1676
bellard3a7d9292005-08-21 09:26:42 +00001677static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1678{
1679 ram_addr_t ram_addr;
1680
bellard84b7b8e2005-11-28 21:19:04 +00001681 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
ths5fafdf22007-09-16 21:08:06 +00001682 ram_addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) +
bellard3a7d9292005-08-21 09:26:42 +00001683 tlb_entry->addend - (unsigned long)phys_ram_base;
1684 if (!cpu_physical_memory_is_dirty(ram_addr)) {
pbrook0f459d12008-06-09 00:20:13 +00001685 tlb_entry->addr_write |= TLB_NOTDIRTY;
bellard3a7d9292005-08-21 09:26:42 +00001686 }
1687 }
1688}
1689
1690/* update the TLB according to the current state of the dirty bits */
1691void cpu_tlb_update_dirty(CPUState *env)
1692{
1693 int i;
1694 for(i = 0; i < CPU_TLB_SIZE; i++)
bellard84b7b8e2005-11-28 21:19:04 +00001695 tlb_update_dirty(&env->tlb_table[0][i]);
bellard3a7d9292005-08-21 09:26:42 +00001696 for(i = 0; i < CPU_TLB_SIZE; i++)
bellard84b7b8e2005-11-28 21:19:04 +00001697 tlb_update_dirty(&env->tlb_table[1][i]);
j_mayer6fa4cea2007-04-05 06:43:27 +00001698#if (NB_MMU_MODES >= 3)
1699 for(i = 0; i < CPU_TLB_SIZE; i++)
1700 tlb_update_dirty(&env->tlb_table[2][i]);
1701#if (NB_MMU_MODES == 4)
1702 for(i = 0; i < CPU_TLB_SIZE; i++)
1703 tlb_update_dirty(&env->tlb_table[3][i]);
1704#endif
1705#endif
bellard3a7d9292005-08-21 09:26:42 +00001706}
1707
pbrook0f459d12008-06-09 00:20:13 +00001708static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, target_ulong vaddr)
bellard1ccde1c2004-02-06 19:46:14 +00001709{
pbrook0f459d12008-06-09 00:20:13 +00001710 if (tlb_entry->addr_write == (vaddr | TLB_NOTDIRTY))
1711 tlb_entry->addr_write = vaddr;
bellard1ccde1c2004-02-06 19:46:14 +00001712}
1713
pbrook0f459d12008-06-09 00:20:13 +00001714/* update the TLB corresponding to virtual page vaddr
1715 so that it is no longer dirty */
1716static inline void tlb_set_dirty(CPUState *env, target_ulong vaddr)
bellard1ccde1c2004-02-06 19:46:14 +00001717{
bellard1ccde1c2004-02-06 19:46:14 +00001718 int i;
1719
pbrook0f459d12008-06-09 00:20:13 +00001720 vaddr &= TARGET_PAGE_MASK;
bellard1ccde1c2004-02-06 19:46:14 +00001721 i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
pbrook0f459d12008-06-09 00:20:13 +00001722 tlb_set_dirty1(&env->tlb_table[0][i], vaddr);
1723 tlb_set_dirty1(&env->tlb_table[1][i], vaddr);
j_mayer6fa4cea2007-04-05 06:43:27 +00001724#if (NB_MMU_MODES >= 3)
pbrook0f459d12008-06-09 00:20:13 +00001725 tlb_set_dirty1(&env->tlb_table[2][i], vaddr);
j_mayer6fa4cea2007-04-05 06:43:27 +00001726#if (NB_MMU_MODES == 4)
pbrook0f459d12008-06-09 00:20:13 +00001727 tlb_set_dirty1(&env->tlb_table[3][i], vaddr);
j_mayer6fa4cea2007-04-05 06:43:27 +00001728#endif
1729#endif
bellard9fa3e852004-01-04 18:06:42 +00001730}
1731
bellard59817cc2004-02-16 22:01:13 +00001732/* add a new TLB entry. At most one entry for a given virtual address
1733 is permitted. Return 0 if OK or 2 if the page could not be mapped
1734 (can only happen in non SOFTMMU mode for I/O pages or pages
1735 conflicting with the host address space). */
ths5fafdf22007-09-16 21:08:06 +00001736int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
1737 target_phys_addr_t paddr, int prot,
j_mayer6ebbf392007-10-14 07:07:08 +00001738 int mmu_idx, int is_softmmu)
bellard9fa3e852004-01-04 18:06:42 +00001739{
bellard92e873b2004-05-21 14:52:29 +00001740 PhysPageDesc *p;
bellard4f2ac232004-04-26 19:44:02 +00001741 unsigned long pd;
bellard9fa3e852004-01-04 18:06:42 +00001742 unsigned int index;
bellard4f2ac232004-04-26 19:44:02 +00001743 target_ulong address;
pbrook0f459d12008-06-09 00:20:13 +00001744 target_ulong code_address;
bellard108c49b2005-07-24 12:55:09 +00001745 target_phys_addr_t addend;
bellard9fa3e852004-01-04 18:06:42 +00001746 int ret;
bellard84b7b8e2005-11-28 21:19:04 +00001747 CPUTLBEntry *te;
pbrook6658ffb2007-03-16 23:58:11 +00001748 int i;
pbrook0f459d12008-06-09 00:20:13 +00001749 target_phys_addr_t iotlb;
bellard9fa3e852004-01-04 18:06:42 +00001750
bellard92e873b2004-05-21 14:52:29 +00001751 p = phys_page_find(paddr >> TARGET_PAGE_BITS);
bellard9fa3e852004-01-04 18:06:42 +00001752 if (!p) {
1753 pd = IO_MEM_UNASSIGNED;
bellard9fa3e852004-01-04 18:06:42 +00001754 } else {
1755 pd = p->phys_offset;
bellard9fa3e852004-01-04 18:06:42 +00001756 }
1757#if defined(DEBUG_TLB)
j_mayer6ebbf392007-10-14 07:07:08 +00001758 printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x idx=%d smmu=%d pd=0x%08lx\n",
1759 vaddr, (int)paddr, prot, mmu_idx, is_softmmu, pd);
bellard9fa3e852004-01-04 18:06:42 +00001760#endif
1761
1762 ret = 0;
pbrook0f459d12008-06-09 00:20:13 +00001763 address = vaddr;
1764 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
1765 /* IO memory case (romd handled later) */
1766 address |= TLB_MMIO;
1767 }
1768 addend = (unsigned long)phys_ram_base + (pd & TARGET_PAGE_MASK);
1769 if ((pd & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
1770 /* Normal RAM. */
1771 iotlb = pd & TARGET_PAGE_MASK;
1772 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM)
1773 iotlb |= IO_MEM_NOTDIRTY;
1774 else
1775 iotlb |= IO_MEM_ROM;
1776 } else {
1777 /* IO handlers are currently passed a phsical address.
1778 It would be nice to pass an offset from the base address
1779 of that region. This would avoid having to special case RAM,
1780 and avoid full address decoding in every device.
1781 We can't use the high bits of pd for this because
1782 IO_MEM_ROMD uses these as a ram address. */
1783 iotlb = (pd & ~TARGET_PAGE_MASK) + paddr;
1784 }
pbrook6658ffb2007-03-16 23:58:11 +00001785
pbrook0f459d12008-06-09 00:20:13 +00001786 code_address = address;
1787 /* Make accesses to pages with watchpoints go via the
1788 watchpoint trap routines. */
1789 for (i = 0; i < env->nb_watchpoints; i++) {
1790 if (vaddr == (env->watchpoint[i].vaddr & TARGET_PAGE_MASK)) {
1791 iotlb = io_mem_watch + paddr;
1792 /* TODO: The memory case can be optimized by not trapping
1793 reads of pages with a write breakpoint. */
1794 address |= TLB_MMIO;
pbrook6658ffb2007-03-16 23:58:11 +00001795 }
pbrook0f459d12008-06-09 00:20:13 +00001796 }
balrogd79acba2007-06-26 20:01:13 +00001797
pbrook0f459d12008-06-09 00:20:13 +00001798 index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1799 env->iotlb[mmu_idx][index] = iotlb - vaddr;
1800 te = &env->tlb_table[mmu_idx][index];
1801 te->addend = addend - vaddr;
1802 if (prot & PAGE_READ) {
1803 te->addr_read = address;
1804 } else {
1805 te->addr_read = -1;
1806 }
edgar_igl5c751e92008-05-06 08:44:21 +00001807
pbrook0f459d12008-06-09 00:20:13 +00001808 if (prot & PAGE_EXEC) {
1809 te->addr_code = code_address;
1810 } else {
1811 te->addr_code = -1;
1812 }
1813 if (prot & PAGE_WRITE) {
1814 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM ||
1815 (pd & IO_MEM_ROMD)) {
1816 /* Write access calls the I/O callback. */
1817 te->addr_write = address | TLB_MMIO;
1818 } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
1819 !cpu_physical_memory_is_dirty(pd)) {
1820 te->addr_write = address | TLB_NOTDIRTY;
bellard84b7b8e2005-11-28 21:19:04 +00001821 } else {
pbrook0f459d12008-06-09 00:20:13 +00001822 te->addr_write = address;
bellard9fa3e852004-01-04 18:06:42 +00001823 }
pbrook0f459d12008-06-09 00:20:13 +00001824 } else {
1825 te->addr_write = -1;
bellard9fa3e852004-01-04 18:06:42 +00001826 }
bellard9fa3e852004-01-04 18:06:42 +00001827 return ret;
1828}
1829
bellard01243112004-01-04 15:48:17 +00001830#else
1831
bellardee8b7022004-02-03 23:35:10 +00001832void tlb_flush(CPUState *env, int flush_global)
bellard01243112004-01-04 15:48:17 +00001833{
1834}
1835
bellard2e126692004-04-25 21:28:44 +00001836void tlb_flush_page(CPUState *env, target_ulong addr)
bellard01243112004-01-04 15:48:17 +00001837{
1838}
1839
ths5fafdf22007-09-16 21:08:06 +00001840int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
1841 target_phys_addr_t paddr, int prot,
j_mayer6ebbf392007-10-14 07:07:08 +00001842 int mmu_idx, int is_softmmu)
bellard33417e72003-08-10 21:47:01 +00001843{
bellard9fa3e852004-01-04 18:06:42 +00001844 return 0;
1845}
bellard33417e72003-08-10 21:47:01 +00001846
bellard9fa3e852004-01-04 18:06:42 +00001847/* dump memory mappings */
1848void page_dump(FILE *f)
1849{
1850 unsigned long start, end;
1851 int i, j, prot, prot1;
1852 PageDesc *p;
1853
1854 fprintf(f, "%-8s %-8s %-8s %s\n",
1855 "start", "end", "size", "prot");
1856 start = -1;
1857 end = -1;
1858 prot = 0;
1859 for(i = 0; i <= L1_SIZE; i++) {
1860 if (i < L1_SIZE)
1861 p = l1_map[i];
1862 else
1863 p = NULL;
1864 for(j = 0;j < L2_SIZE; j++) {
1865 if (!p)
1866 prot1 = 0;
1867 else
1868 prot1 = p[j].flags;
1869 if (prot1 != prot) {
1870 end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
1871 if (start != -1) {
1872 fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
ths5fafdf22007-09-16 21:08:06 +00001873 start, end, end - start,
bellard9fa3e852004-01-04 18:06:42 +00001874 prot & PAGE_READ ? 'r' : '-',
1875 prot & PAGE_WRITE ? 'w' : '-',
1876 prot & PAGE_EXEC ? 'x' : '-');
1877 }
1878 if (prot1 != 0)
1879 start = end;
1880 else
1881 start = -1;
1882 prot = prot1;
1883 }
1884 if (!p)
1885 break;
1886 }
bellard33417e72003-08-10 21:47:01 +00001887 }
bellard33417e72003-08-10 21:47:01 +00001888}
1889
pbrook53a59602006-03-25 19:31:22 +00001890int page_get_flags(target_ulong address)
bellard33417e72003-08-10 21:47:01 +00001891{
bellard9fa3e852004-01-04 18:06:42 +00001892 PageDesc *p;
1893
1894 p = page_find(address >> TARGET_PAGE_BITS);
bellard33417e72003-08-10 21:47:01 +00001895 if (!p)
bellard9fa3e852004-01-04 18:06:42 +00001896 return 0;
1897 return p->flags;
bellard33417e72003-08-10 21:47:01 +00001898}
1899
bellard9fa3e852004-01-04 18:06:42 +00001900/* modify the flags of a page and invalidate the code if
1901 necessary. The flag PAGE_WRITE_ORG is positionned automatically
1902 depending on PAGE_WRITE */
pbrook53a59602006-03-25 19:31:22 +00001903void page_set_flags(target_ulong start, target_ulong end, int flags)
bellard9fa3e852004-01-04 18:06:42 +00001904{
1905 PageDesc *p;
pbrook53a59602006-03-25 19:31:22 +00001906 target_ulong addr;
bellard9fa3e852004-01-04 18:06:42 +00001907
pbrookc8a706f2008-06-02 16:16:42 +00001908 /* mmap_lock should already be held. */
bellard9fa3e852004-01-04 18:06:42 +00001909 start = start & TARGET_PAGE_MASK;
1910 end = TARGET_PAGE_ALIGN(end);
1911 if (flags & PAGE_WRITE)
1912 flags |= PAGE_WRITE_ORG;
bellard9fa3e852004-01-04 18:06:42 +00001913 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1914 p = page_find_alloc(addr >> TARGET_PAGE_BITS);
1915 /* if the write protection is set, then we invalidate the code
1916 inside */
ths5fafdf22007-09-16 21:08:06 +00001917 if (!(p->flags & PAGE_WRITE) &&
bellard9fa3e852004-01-04 18:06:42 +00001918 (flags & PAGE_WRITE) &&
1919 p->first_tb) {
bellardd720b932004-04-25 17:57:43 +00001920 tb_invalidate_phys_page(addr, 0, NULL);
bellard9fa3e852004-01-04 18:06:42 +00001921 }
1922 p->flags = flags;
1923 }
bellard9fa3e852004-01-04 18:06:42 +00001924}
1925
ths3d97b402007-11-02 19:02:07 +00001926int page_check_range(target_ulong start, target_ulong len, int flags)
1927{
1928 PageDesc *p;
1929 target_ulong end;
1930 target_ulong addr;
1931
1932 end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
1933 start = start & TARGET_PAGE_MASK;
1934
1935 if( end < start )
1936 /* we've wrapped around */
1937 return -1;
1938 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1939 p = page_find(addr >> TARGET_PAGE_BITS);
1940 if( !p )
1941 return -1;
1942 if( !(p->flags & PAGE_VALID) )
1943 return -1;
1944
bellarddae32702007-11-14 10:51:00 +00001945 if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
ths3d97b402007-11-02 19:02:07 +00001946 return -1;
bellarddae32702007-11-14 10:51:00 +00001947 if (flags & PAGE_WRITE) {
1948 if (!(p->flags & PAGE_WRITE_ORG))
1949 return -1;
1950 /* unprotect the page if it was put read-only because it
1951 contains translated code */
1952 if (!(p->flags & PAGE_WRITE)) {
1953 if (!page_unprotect(addr, 0, NULL))
1954 return -1;
1955 }
1956 return 0;
1957 }
ths3d97b402007-11-02 19:02:07 +00001958 }
1959 return 0;
1960}
1961
bellard9fa3e852004-01-04 18:06:42 +00001962/* called from signal handler: invalidate the code and unprotect the
1963 page. Return TRUE if the fault was succesfully handled. */
pbrook53a59602006-03-25 19:31:22 +00001964int page_unprotect(target_ulong address, unsigned long pc, void *puc)
bellard9fa3e852004-01-04 18:06:42 +00001965{
1966 unsigned int page_index, prot, pindex;
1967 PageDesc *p, *p1;
pbrook53a59602006-03-25 19:31:22 +00001968 target_ulong host_start, host_end, addr;
bellard9fa3e852004-01-04 18:06:42 +00001969
pbrookc8a706f2008-06-02 16:16:42 +00001970 /* Technically this isn't safe inside a signal handler. However we
1971 know this only ever happens in a synchronous SEGV handler, so in
1972 practice it seems to be ok. */
1973 mmap_lock();
1974
bellard83fb7ad2004-07-05 21:25:26 +00001975 host_start = address & qemu_host_page_mask;
bellard9fa3e852004-01-04 18:06:42 +00001976 page_index = host_start >> TARGET_PAGE_BITS;
1977 p1 = page_find(page_index);
pbrookc8a706f2008-06-02 16:16:42 +00001978 if (!p1) {
1979 mmap_unlock();
bellard9fa3e852004-01-04 18:06:42 +00001980 return 0;
pbrookc8a706f2008-06-02 16:16:42 +00001981 }
bellard83fb7ad2004-07-05 21:25:26 +00001982 host_end = host_start + qemu_host_page_size;
bellard9fa3e852004-01-04 18:06:42 +00001983 p = p1;
1984 prot = 0;
1985 for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
1986 prot |= p->flags;
1987 p++;
1988 }
1989 /* if the page was really writable, then we change its
1990 protection back to writable */
1991 if (prot & PAGE_WRITE_ORG) {
1992 pindex = (address - host_start) >> TARGET_PAGE_BITS;
1993 if (!(p1[pindex].flags & PAGE_WRITE)) {
ths5fafdf22007-09-16 21:08:06 +00001994 mprotect((void *)g2h(host_start), qemu_host_page_size,
bellard9fa3e852004-01-04 18:06:42 +00001995 (prot & PAGE_BITS) | PAGE_WRITE);
1996 p1[pindex].flags |= PAGE_WRITE;
1997 /* and since the content will be modified, we must invalidate
1998 the corresponding translated code. */
bellardd720b932004-04-25 17:57:43 +00001999 tb_invalidate_phys_page(address, pc, puc);
bellard9fa3e852004-01-04 18:06:42 +00002000#ifdef DEBUG_TB_CHECK
2001 tb_invalidate_check(address);
2002#endif
pbrookc8a706f2008-06-02 16:16:42 +00002003 mmap_unlock();
bellard9fa3e852004-01-04 18:06:42 +00002004 return 1;
2005 }
2006 }
pbrookc8a706f2008-06-02 16:16:42 +00002007 mmap_unlock();
bellard9fa3e852004-01-04 18:06:42 +00002008 return 0;
2009}
2010
bellard6a00d602005-11-21 23:25:50 +00002011static inline void tlb_set_dirty(CPUState *env,
2012 unsigned long addr, target_ulong vaddr)
bellard1ccde1c2004-02-06 19:46:14 +00002013{
2014}
bellard9fa3e852004-01-04 18:06:42 +00002015#endif /* defined(CONFIG_USER_ONLY) */
2016
pbrooke2eef172008-06-08 01:09:01 +00002017#if !defined(CONFIG_USER_ONLY)
blueswir1db7b5422007-05-26 17:36:03 +00002018static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
aurel3200f82b82008-04-27 21:12:55 +00002019 ram_addr_t memory);
2020static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
2021 ram_addr_t orig_memory);
blueswir1db7b5422007-05-26 17:36:03 +00002022#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
2023 need_subpage) \
2024 do { \
2025 if (addr > start_addr) \
2026 start_addr2 = 0; \
2027 else { \
2028 start_addr2 = start_addr & ~TARGET_PAGE_MASK; \
2029 if (start_addr2 > 0) \
2030 need_subpage = 1; \
2031 } \
2032 \
blueswir149e9fba2007-05-30 17:25:06 +00002033 if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE) \
blueswir1db7b5422007-05-26 17:36:03 +00002034 end_addr2 = TARGET_PAGE_SIZE - 1; \
2035 else { \
2036 end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
2037 if (end_addr2 < TARGET_PAGE_SIZE - 1) \
2038 need_subpage = 1; \
2039 } \
2040 } while (0)
2041
bellard33417e72003-08-10 21:47:01 +00002042/* register physical memory. 'size' must be a multiple of the target
2043 page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
2044 io memory page */
ths5fafdf22007-09-16 21:08:06 +00002045void cpu_register_physical_memory(target_phys_addr_t start_addr,
aurel3200f82b82008-04-27 21:12:55 +00002046 ram_addr_t size,
2047 ram_addr_t phys_offset)
bellard33417e72003-08-10 21:47:01 +00002048{
bellard108c49b2005-07-24 12:55:09 +00002049 target_phys_addr_t addr, end_addr;
bellard92e873b2004-05-21 14:52:29 +00002050 PhysPageDesc *p;
bellard9d420372006-06-25 22:25:22 +00002051 CPUState *env;
aurel3200f82b82008-04-27 21:12:55 +00002052 ram_addr_t orig_size = size;
blueswir1db7b5422007-05-26 17:36:03 +00002053 void *subpage;
bellard33417e72003-08-10 21:47:01 +00002054
bellardda260242008-05-30 20:48:25 +00002055#ifdef USE_KQEMU
2056 /* XXX: should not depend on cpu context */
2057 env = first_cpu;
2058 if (env->kqemu_enabled) {
2059 kqemu_set_phys_mem(start_addr, size, phys_offset);
2060 }
2061#endif
bellard5fd386f2004-05-23 21:11:22 +00002062 size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
blueswir149e9fba2007-05-30 17:25:06 +00002063 end_addr = start_addr + (target_phys_addr_t)size;
2064 for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
blueswir1db7b5422007-05-26 17:36:03 +00002065 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2066 if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
aurel3200f82b82008-04-27 21:12:55 +00002067 ram_addr_t orig_memory = p->phys_offset;
blueswir1db7b5422007-05-26 17:36:03 +00002068 target_phys_addr_t start_addr2, end_addr2;
2069 int need_subpage = 0;
2070
2071 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2072 need_subpage);
blueswir14254fab2008-01-01 16:57:19 +00002073 if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
blueswir1db7b5422007-05-26 17:36:03 +00002074 if (!(orig_memory & IO_MEM_SUBPAGE)) {
2075 subpage = subpage_init((addr & TARGET_PAGE_MASK),
2076 &p->phys_offset, orig_memory);
2077 } else {
2078 subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
2079 >> IO_MEM_SHIFT];
2080 }
2081 subpage_register(subpage, start_addr2, end_addr2, phys_offset);
2082 } else {
2083 p->phys_offset = phys_offset;
2084 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2085 (phys_offset & IO_MEM_ROMD))
2086 phys_offset += TARGET_PAGE_SIZE;
2087 }
2088 } else {
2089 p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2090 p->phys_offset = phys_offset;
2091 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2092 (phys_offset & IO_MEM_ROMD))
2093 phys_offset += TARGET_PAGE_SIZE;
2094 else {
2095 target_phys_addr_t start_addr2, end_addr2;
2096 int need_subpage = 0;
2097
2098 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2099 end_addr2, need_subpage);
2100
blueswir14254fab2008-01-01 16:57:19 +00002101 if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
blueswir1db7b5422007-05-26 17:36:03 +00002102 subpage = subpage_init((addr & TARGET_PAGE_MASK),
2103 &p->phys_offset, IO_MEM_UNASSIGNED);
2104 subpage_register(subpage, start_addr2, end_addr2,
2105 phys_offset);
2106 }
2107 }
2108 }
bellard33417e72003-08-10 21:47:01 +00002109 }
ths3b46e622007-09-17 08:09:54 +00002110
bellard9d420372006-06-25 22:25:22 +00002111 /* since each CPU stores ram addresses in its TLB cache, we must
2112 reset the modified entries */
2113 /* XXX: slow ! */
2114 for(env = first_cpu; env != NULL; env = env->next_cpu) {
2115 tlb_flush(env, 1);
2116 }
bellard33417e72003-08-10 21:47:01 +00002117}
2118
bellardba863452006-09-24 18:41:10 +00002119/* XXX: temporary until new memory mapping API */
aurel3200f82b82008-04-27 21:12:55 +00002120ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr)
bellardba863452006-09-24 18:41:10 +00002121{
2122 PhysPageDesc *p;
2123
2124 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2125 if (!p)
2126 return IO_MEM_UNASSIGNED;
2127 return p->phys_offset;
2128}
2129
bellarde9a1ab12007-02-08 23:08:38 +00002130/* XXX: better than nothing */
aurel3200f82b82008-04-27 21:12:55 +00002131ram_addr_t qemu_ram_alloc(ram_addr_t size)
bellarde9a1ab12007-02-08 23:08:38 +00002132{
2133 ram_addr_t addr;
balrog7fb4fdc2008-04-24 17:59:27 +00002134 if ((phys_ram_alloc_offset + size) > phys_ram_size) {
bellarded441462008-05-23 11:56:45 +00002135 fprintf(stderr, "Not enough memory (requested_size = %" PRIu64 ", max memory = %" PRIu64 "\n",
2136 (uint64_t)size, (uint64_t)phys_ram_size);
bellarde9a1ab12007-02-08 23:08:38 +00002137 abort();
2138 }
2139 addr = phys_ram_alloc_offset;
2140 phys_ram_alloc_offset = TARGET_PAGE_ALIGN(phys_ram_alloc_offset + size);
2141 return addr;
2142}
2143
2144void qemu_ram_free(ram_addr_t addr)
2145{
2146}
2147
bellarda4193c82004-06-03 14:01:43 +00002148static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
bellard33417e72003-08-10 21:47:01 +00002149{
pbrook67d3b952006-12-18 05:03:52 +00002150#ifdef DEBUG_UNASSIGNED
blueswir1ab3d1722007-11-04 07:31:40 +00002151 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
pbrook67d3b952006-12-18 05:03:52 +00002152#endif
blueswir1b4f0a312007-05-06 17:59:24 +00002153#ifdef TARGET_SPARC
blueswir16c36d3f2007-05-17 19:30:10 +00002154 do_unassigned_access(addr, 0, 0, 0);
thsf1ccf902007-10-08 13:16:14 +00002155#elif TARGET_CRIS
2156 do_unassigned_access(addr, 0, 0, 0);
blueswir1b4f0a312007-05-06 17:59:24 +00002157#endif
bellard33417e72003-08-10 21:47:01 +00002158 return 0;
2159}
2160
bellarda4193c82004-06-03 14:01:43 +00002161static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
bellard33417e72003-08-10 21:47:01 +00002162{
pbrook67d3b952006-12-18 05:03:52 +00002163#ifdef DEBUG_UNASSIGNED
blueswir1ab3d1722007-11-04 07:31:40 +00002164 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
pbrook67d3b952006-12-18 05:03:52 +00002165#endif
blueswir1b4f0a312007-05-06 17:59:24 +00002166#ifdef TARGET_SPARC
blueswir16c36d3f2007-05-17 19:30:10 +00002167 do_unassigned_access(addr, 1, 0, 0);
thsf1ccf902007-10-08 13:16:14 +00002168#elif TARGET_CRIS
2169 do_unassigned_access(addr, 1, 0, 0);
blueswir1b4f0a312007-05-06 17:59:24 +00002170#endif
bellard33417e72003-08-10 21:47:01 +00002171}
2172
2173static CPUReadMemoryFunc *unassigned_mem_read[3] = {
2174 unassigned_mem_readb,
2175 unassigned_mem_readb,
2176 unassigned_mem_readb,
2177};
2178
2179static CPUWriteMemoryFunc *unassigned_mem_write[3] = {
2180 unassigned_mem_writeb,
2181 unassigned_mem_writeb,
2182 unassigned_mem_writeb,
2183};
2184
pbrook0f459d12008-06-09 00:20:13 +00002185static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr,
2186 uint32_t val)
bellard1ccde1c2004-02-06 19:46:14 +00002187{
bellard3a7d9292005-08-21 09:26:42 +00002188 int dirty_flags;
bellard3a7d9292005-08-21 09:26:42 +00002189 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2190 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2191#if !defined(CONFIG_USER_ONLY)
2192 tb_invalidate_phys_page_fast(ram_addr, 1);
2193 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2194#endif
2195 }
pbrook0f459d12008-06-09 00:20:13 +00002196 stb_p(phys_ram_base + ram_addr, val);
bellardf32fc642006-02-08 22:43:39 +00002197#ifdef USE_KQEMU
2198 if (cpu_single_env->kqemu_enabled &&
2199 (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2200 kqemu_modify_page(cpu_single_env, ram_addr);
2201#endif
bellardf23db162005-08-21 19:12:28 +00002202 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2203 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2204 /* we remove the notdirty callback only if the code has been
2205 flushed */
2206 if (dirty_flags == 0xff)
pbrook0f459d12008-06-09 00:20:13 +00002207 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_write_vaddr);
bellard1ccde1c2004-02-06 19:46:14 +00002208}
2209
pbrook0f459d12008-06-09 00:20:13 +00002210static void notdirty_mem_writew(void *opaque, target_phys_addr_t ram_addr,
2211 uint32_t val)
bellard1ccde1c2004-02-06 19:46:14 +00002212{
bellard3a7d9292005-08-21 09:26:42 +00002213 int dirty_flags;
bellard3a7d9292005-08-21 09:26:42 +00002214 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2215 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2216#if !defined(CONFIG_USER_ONLY)
2217 tb_invalidate_phys_page_fast(ram_addr, 2);
2218 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2219#endif
2220 }
pbrook0f459d12008-06-09 00:20:13 +00002221 stw_p(phys_ram_base + ram_addr, val);
bellardf32fc642006-02-08 22:43:39 +00002222#ifdef USE_KQEMU
2223 if (cpu_single_env->kqemu_enabled &&
2224 (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2225 kqemu_modify_page(cpu_single_env, ram_addr);
2226#endif
bellardf23db162005-08-21 19:12:28 +00002227 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2228 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2229 /* we remove the notdirty callback only if the code has been
2230 flushed */
2231 if (dirty_flags == 0xff)
pbrook0f459d12008-06-09 00:20:13 +00002232 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_write_vaddr);
bellard1ccde1c2004-02-06 19:46:14 +00002233}
2234
pbrook0f459d12008-06-09 00:20:13 +00002235static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr,
2236 uint32_t val)
bellard1ccde1c2004-02-06 19:46:14 +00002237{
bellard3a7d9292005-08-21 09:26:42 +00002238 int dirty_flags;
bellard3a7d9292005-08-21 09:26:42 +00002239 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2240 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2241#if !defined(CONFIG_USER_ONLY)
2242 tb_invalidate_phys_page_fast(ram_addr, 4);
2243 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2244#endif
2245 }
pbrook0f459d12008-06-09 00:20:13 +00002246 stl_p(phys_ram_base + ram_addr, val);
bellardf32fc642006-02-08 22:43:39 +00002247#ifdef USE_KQEMU
2248 if (cpu_single_env->kqemu_enabled &&
2249 (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2250 kqemu_modify_page(cpu_single_env, ram_addr);
2251#endif
bellardf23db162005-08-21 19:12:28 +00002252 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2253 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2254 /* we remove the notdirty callback only if the code has been
2255 flushed */
2256 if (dirty_flags == 0xff)
pbrook0f459d12008-06-09 00:20:13 +00002257 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_write_vaddr);
bellard1ccde1c2004-02-06 19:46:14 +00002258}
2259
bellard3a7d9292005-08-21 09:26:42 +00002260static CPUReadMemoryFunc *error_mem_read[3] = {
2261 NULL, /* never used */
2262 NULL, /* never used */
2263 NULL, /* never used */
2264};
2265
bellard1ccde1c2004-02-06 19:46:14 +00002266static CPUWriteMemoryFunc *notdirty_mem_write[3] = {
2267 notdirty_mem_writeb,
2268 notdirty_mem_writew,
2269 notdirty_mem_writel,
2270};
2271
pbrook0f459d12008-06-09 00:20:13 +00002272/* Generate a debug exception if a watchpoint has been hit. */
2273static void check_watchpoint(int offset, int flags)
2274{
2275 CPUState *env = cpu_single_env;
2276 target_ulong vaddr;
2277 int i;
2278
2279 vaddr = (env->mem_write_vaddr & TARGET_PAGE_MASK) + offset;
2280 for (i = 0; i < env->nb_watchpoints; i++) {
2281 if (vaddr == env->watchpoint[i].vaddr
2282 && (env->watchpoint[i].type & flags)) {
2283 env->watchpoint_hit = i + 1;
2284 cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2285 break;
2286 }
2287 }
2288}
2289
pbrook6658ffb2007-03-16 23:58:11 +00002290/* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
2291 so these check for a hit then pass through to the normal out-of-line
2292 phys routines. */
2293static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
2294{
pbrook0f459d12008-06-09 00:20:13 +00002295 check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ);
pbrook6658ffb2007-03-16 23:58:11 +00002296 return ldub_phys(addr);
2297}
2298
2299static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
2300{
pbrook0f459d12008-06-09 00:20:13 +00002301 check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ);
pbrook6658ffb2007-03-16 23:58:11 +00002302 return lduw_phys(addr);
2303}
2304
2305static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
2306{
pbrook0f459d12008-06-09 00:20:13 +00002307 check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ);
pbrook6658ffb2007-03-16 23:58:11 +00002308 return ldl_phys(addr);
2309}
2310
pbrook6658ffb2007-03-16 23:58:11 +00002311static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
2312 uint32_t val)
2313{
pbrook0f459d12008-06-09 00:20:13 +00002314 check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE);
pbrook6658ffb2007-03-16 23:58:11 +00002315 stb_phys(addr, val);
2316}
2317
2318static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
2319 uint32_t val)
2320{
pbrook0f459d12008-06-09 00:20:13 +00002321 check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE);
pbrook6658ffb2007-03-16 23:58:11 +00002322 stw_phys(addr, val);
2323}
2324
2325static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
2326 uint32_t val)
2327{
pbrook0f459d12008-06-09 00:20:13 +00002328 check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE);
pbrook6658ffb2007-03-16 23:58:11 +00002329 stl_phys(addr, val);
2330}
2331
2332static CPUReadMemoryFunc *watch_mem_read[3] = {
2333 watch_mem_readb,
2334 watch_mem_readw,
2335 watch_mem_readl,
2336};
2337
2338static CPUWriteMemoryFunc *watch_mem_write[3] = {
2339 watch_mem_writeb,
2340 watch_mem_writew,
2341 watch_mem_writel,
2342};
pbrook6658ffb2007-03-16 23:58:11 +00002343
blueswir1db7b5422007-05-26 17:36:03 +00002344static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr,
2345 unsigned int len)
2346{
blueswir1db7b5422007-05-26 17:36:03 +00002347 uint32_t ret;
2348 unsigned int idx;
2349
2350 idx = SUBPAGE_IDX(addr - mmio->base);
2351#if defined(DEBUG_SUBPAGE)
2352 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
2353 mmio, len, addr, idx);
2354#endif
blueswir13ee89922008-01-02 19:45:26 +00002355 ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len], addr);
blueswir1db7b5422007-05-26 17:36:03 +00002356
2357 return ret;
2358}
2359
2360static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
2361 uint32_t value, unsigned int len)
2362{
blueswir1db7b5422007-05-26 17:36:03 +00002363 unsigned int idx;
2364
2365 idx = SUBPAGE_IDX(addr - mmio->base);
2366#if defined(DEBUG_SUBPAGE)
2367 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
2368 mmio, len, addr, idx, value);
2369#endif
blueswir13ee89922008-01-02 19:45:26 +00002370 (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len], addr, value);
blueswir1db7b5422007-05-26 17:36:03 +00002371}
2372
2373static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
2374{
2375#if defined(DEBUG_SUBPAGE)
2376 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2377#endif
2378
2379 return subpage_readlen(opaque, addr, 0);
2380}
2381
2382static void subpage_writeb (void *opaque, target_phys_addr_t addr,
2383 uint32_t value)
2384{
2385#if defined(DEBUG_SUBPAGE)
2386 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2387#endif
2388 subpage_writelen(opaque, addr, value, 0);
2389}
2390
2391static uint32_t subpage_readw (void *opaque, target_phys_addr_t addr)
2392{
2393#if defined(DEBUG_SUBPAGE)
2394 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2395#endif
2396
2397 return subpage_readlen(opaque, addr, 1);
2398}
2399
2400static void subpage_writew (void *opaque, target_phys_addr_t addr,
2401 uint32_t value)
2402{
2403#if defined(DEBUG_SUBPAGE)
2404 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2405#endif
2406 subpage_writelen(opaque, addr, value, 1);
2407}
2408
2409static uint32_t subpage_readl (void *opaque, target_phys_addr_t addr)
2410{
2411#if defined(DEBUG_SUBPAGE)
2412 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2413#endif
2414
2415 return subpage_readlen(opaque, addr, 2);
2416}
2417
2418static void subpage_writel (void *opaque,
2419 target_phys_addr_t addr, uint32_t value)
2420{
2421#if defined(DEBUG_SUBPAGE)
2422 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2423#endif
2424 subpage_writelen(opaque, addr, value, 2);
2425}
2426
2427static CPUReadMemoryFunc *subpage_read[] = {
2428 &subpage_readb,
2429 &subpage_readw,
2430 &subpage_readl,
2431};
2432
2433static CPUWriteMemoryFunc *subpage_write[] = {
2434 &subpage_writeb,
2435 &subpage_writew,
2436 &subpage_writel,
2437};
2438
2439static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
aurel3200f82b82008-04-27 21:12:55 +00002440 ram_addr_t memory)
blueswir1db7b5422007-05-26 17:36:03 +00002441{
2442 int idx, eidx;
blueswir14254fab2008-01-01 16:57:19 +00002443 unsigned int i;
blueswir1db7b5422007-05-26 17:36:03 +00002444
2445 if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
2446 return -1;
2447 idx = SUBPAGE_IDX(start);
2448 eidx = SUBPAGE_IDX(end);
2449#if defined(DEBUG_SUBPAGE)
2450 printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %d\n", __func__,
2451 mmio, start, end, idx, eidx, memory);
2452#endif
2453 memory >>= IO_MEM_SHIFT;
2454 for (; idx <= eidx; idx++) {
blueswir14254fab2008-01-01 16:57:19 +00002455 for (i = 0; i < 4; i++) {
blueswir13ee89922008-01-02 19:45:26 +00002456 if (io_mem_read[memory][i]) {
2457 mmio->mem_read[idx][i] = &io_mem_read[memory][i];
2458 mmio->opaque[idx][0][i] = io_mem_opaque[memory];
2459 }
2460 if (io_mem_write[memory][i]) {
2461 mmio->mem_write[idx][i] = &io_mem_write[memory][i];
2462 mmio->opaque[idx][1][i] = io_mem_opaque[memory];
2463 }
blueswir14254fab2008-01-01 16:57:19 +00002464 }
blueswir1db7b5422007-05-26 17:36:03 +00002465 }
2466
2467 return 0;
2468}
2469
aurel3200f82b82008-04-27 21:12:55 +00002470static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
2471 ram_addr_t orig_memory)
blueswir1db7b5422007-05-26 17:36:03 +00002472{
2473 subpage_t *mmio;
2474 int subpage_memory;
2475
2476 mmio = qemu_mallocz(sizeof(subpage_t));
2477 if (mmio != NULL) {
2478 mmio->base = base;
2479 subpage_memory = cpu_register_io_memory(0, subpage_read, subpage_write, mmio);
2480#if defined(DEBUG_SUBPAGE)
2481 printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
2482 mmio, base, TARGET_PAGE_SIZE, subpage_memory);
2483#endif
2484 *phys = subpage_memory | IO_MEM_SUBPAGE;
2485 subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory);
2486 }
2487
2488 return mmio;
2489}
2490
bellard33417e72003-08-10 21:47:01 +00002491static void io_mem_init(void)
2492{
bellard3a7d9292005-08-21 09:26:42 +00002493 cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read, unassigned_mem_write, NULL);
bellarda4193c82004-06-03 14:01:43 +00002494 cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write, NULL);
bellard3a7d9292005-08-21 09:26:42 +00002495 cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read, notdirty_mem_write, NULL);
bellard1ccde1c2004-02-06 19:46:14 +00002496 io_mem_nb = 5;
2497
pbrook0f459d12008-06-09 00:20:13 +00002498 io_mem_watch = cpu_register_io_memory(0, watch_mem_read,
pbrook6658ffb2007-03-16 23:58:11 +00002499 watch_mem_write, NULL);
bellard1ccde1c2004-02-06 19:46:14 +00002500 /* alloc dirty bits array */
bellard0a962c02005-02-10 22:00:27 +00002501 phys_ram_dirty = qemu_vmalloc(phys_ram_size >> TARGET_PAGE_BITS);
bellard3a7d9292005-08-21 09:26:42 +00002502 memset(phys_ram_dirty, 0xff, phys_ram_size >> TARGET_PAGE_BITS);
bellard33417e72003-08-10 21:47:01 +00002503}
2504
2505/* mem_read and mem_write are arrays of functions containing the
2506 function to access byte (index 0), word (index 1) and dword (index
blueswir13ee89922008-01-02 19:45:26 +00002507 2). Functions can be omitted with a NULL function pointer. The
2508 registered functions may be modified dynamically later.
2509 If io_index is non zero, the corresponding io zone is
blueswir14254fab2008-01-01 16:57:19 +00002510 modified. If it is zero, a new io zone is allocated. The return
2511 value can be used with cpu_register_physical_memory(). (-1) is
2512 returned if error. */
bellard33417e72003-08-10 21:47:01 +00002513int cpu_register_io_memory(int io_index,
2514 CPUReadMemoryFunc **mem_read,
bellarda4193c82004-06-03 14:01:43 +00002515 CPUWriteMemoryFunc **mem_write,
2516 void *opaque)
bellard33417e72003-08-10 21:47:01 +00002517{
blueswir14254fab2008-01-01 16:57:19 +00002518 int i, subwidth = 0;
bellard33417e72003-08-10 21:47:01 +00002519
2520 if (io_index <= 0) {
bellardb5ff1b32005-11-26 10:38:39 +00002521 if (io_mem_nb >= IO_MEM_NB_ENTRIES)
bellard33417e72003-08-10 21:47:01 +00002522 return -1;
2523 io_index = io_mem_nb++;
2524 } else {
2525 if (io_index >= IO_MEM_NB_ENTRIES)
2526 return -1;
2527 }
bellardb5ff1b32005-11-26 10:38:39 +00002528
bellard33417e72003-08-10 21:47:01 +00002529 for(i = 0;i < 3; i++) {
blueswir14254fab2008-01-01 16:57:19 +00002530 if (!mem_read[i] || !mem_write[i])
2531 subwidth = IO_MEM_SUBWIDTH;
bellard33417e72003-08-10 21:47:01 +00002532 io_mem_read[io_index][i] = mem_read[i];
2533 io_mem_write[io_index][i] = mem_write[i];
2534 }
bellarda4193c82004-06-03 14:01:43 +00002535 io_mem_opaque[io_index] = opaque;
blueswir14254fab2008-01-01 16:57:19 +00002536 return (io_index << IO_MEM_SHIFT) | subwidth;
bellard33417e72003-08-10 21:47:01 +00002537}
bellard61382a52003-10-27 21:22:23 +00002538
bellard8926b512004-10-10 15:14:20 +00002539CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index)
2540{
2541 return io_mem_write[io_index >> IO_MEM_SHIFT];
2542}
2543
2544CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index)
2545{
2546 return io_mem_read[io_index >> IO_MEM_SHIFT];
2547}
2548
pbrooke2eef172008-06-08 01:09:01 +00002549#endif /* !defined(CONFIG_USER_ONLY) */
2550
bellard13eb76e2004-01-24 15:23:36 +00002551/* physical memory access (slow version, mainly for debug) */
2552#if defined(CONFIG_USER_ONLY)
ths5fafdf22007-09-16 21:08:06 +00002553void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
bellard13eb76e2004-01-24 15:23:36 +00002554 int len, int is_write)
2555{
2556 int l, flags;
2557 target_ulong page;
pbrook53a59602006-03-25 19:31:22 +00002558 void * p;
bellard13eb76e2004-01-24 15:23:36 +00002559
2560 while (len > 0) {
2561 page = addr & TARGET_PAGE_MASK;
2562 l = (page + TARGET_PAGE_SIZE) - addr;
2563 if (l > len)
2564 l = len;
2565 flags = page_get_flags(page);
2566 if (!(flags & PAGE_VALID))
2567 return;
2568 if (is_write) {
2569 if (!(flags & PAGE_WRITE))
2570 return;
bellard579a97f2007-11-11 14:26:47 +00002571 /* XXX: this code should not depend on lock_user */
aurel3272fb7da2008-04-27 23:53:45 +00002572 if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
bellard579a97f2007-11-11 14:26:47 +00002573 /* FIXME - should this return an error rather than just fail? */
2574 return;
aurel3272fb7da2008-04-27 23:53:45 +00002575 memcpy(p, buf, l);
2576 unlock_user(p, addr, l);
bellard13eb76e2004-01-24 15:23:36 +00002577 } else {
2578 if (!(flags & PAGE_READ))
2579 return;
bellard579a97f2007-11-11 14:26:47 +00002580 /* XXX: this code should not depend on lock_user */
aurel3272fb7da2008-04-27 23:53:45 +00002581 if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
bellard579a97f2007-11-11 14:26:47 +00002582 /* FIXME - should this return an error rather than just fail? */
2583 return;
aurel3272fb7da2008-04-27 23:53:45 +00002584 memcpy(buf, p, l);
aurel325b257572008-04-28 08:54:59 +00002585 unlock_user(p, addr, 0);
bellard13eb76e2004-01-24 15:23:36 +00002586 }
2587 len -= l;
2588 buf += l;
2589 addr += l;
2590 }
2591}
bellard8df1cd02005-01-28 22:37:22 +00002592
bellard13eb76e2004-01-24 15:23:36 +00002593#else
ths5fafdf22007-09-16 21:08:06 +00002594void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
bellard13eb76e2004-01-24 15:23:36 +00002595 int len, int is_write)
2596{
2597 int l, io_index;
2598 uint8_t *ptr;
2599 uint32_t val;
bellard2e126692004-04-25 21:28:44 +00002600 target_phys_addr_t page;
2601 unsigned long pd;
bellard92e873b2004-05-21 14:52:29 +00002602 PhysPageDesc *p;
ths3b46e622007-09-17 08:09:54 +00002603
bellard13eb76e2004-01-24 15:23:36 +00002604 while (len > 0) {
2605 page = addr & TARGET_PAGE_MASK;
2606 l = (page + TARGET_PAGE_SIZE) - addr;
2607 if (l > len)
2608 l = len;
bellard92e873b2004-05-21 14:52:29 +00002609 p = phys_page_find(page >> TARGET_PAGE_BITS);
bellard13eb76e2004-01-24 15:23:36 +00002610 if (!p) {
2611 pd = IO_MEM_UNASSIGNED;
2612 } else {
2613 pd = p->phys_offset;
2614 }
ths3b46e622007-09-17 08:09:54 +00002615
bellard13eb76e2004-01-24 15:23:36 +00002616 if (is_write) {
bellard3a7d9292005-08-21 09:26:42 +00002617 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
bellard13eb76e2004-01-24 15:23:36 +00002618 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
bellard6a00d602005-11-21 23:25:50 +00002619 /* XXX: could force cpu_single_env to NULL to avoid
2620 potential bugs */
bellard13eb76e2004-01-24 15:23:36 +00002621 if (l >= 4 && ((addr & 3) == 0)) {
bellard1c213d12005-09-03 10:49:04 +00002622 /* 32 bit write access */
bellardc27004e2005-01-03 23:35:10 +00002623 val = ldl_p(buf);
bellarda4193c82004-06-03 14:01:43 +00002624 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
bellard13eb76e2004-01-24 15:23:36 +00002625 l = 4;
2626 } else if (l >= 2 && ((addr & 1) == 0)) {
bellard1c213d12005-09-03 10:49:04 +00002627 /* 16 bit write access */
bellardc27004e2005-01-03 23:35:10 +00002628 val = lduw_p(buf);
bellarda4193c82004-06-03 14:01:43 +00002629 io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
bellard13eb76e2004-01-24 15:23:36 +00002630 l = 2;
2631 } else {
bellard1c213d12005-09-03 10:49:04 +00002632 /* 8 bit write access */
bellardc27004e2005-01-03 23:35:10 +00002633 val = ldub_p(buf);
bellarda4193c82004-06-03 14:01:43 +00002634 io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val);
bellard13eb76e2004-01-24 15:23:36 +00002635 l = 1;
2636 }
2637 } else {
bellardb448f2f2004-02-25 23:24:04 +00002638 unsigned long addr1;
2639 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
bellard13eb76e2004-01-24 15:23:36 +00002640 /* RAM case */
bellardb448f2f2004-02-25 23:24:04 +00002641 ptr = phys_ram_base + addr1;
bellard13eb76e2004-01-24 15:23:36 +00002642 memcpy(ptr, buf, l);
bellard3a7d9292005-08-21 09:26:42 +00002643 if (!cpu_physical_memory_is_dirty(addr1)) {
2644 /* invalidate code */
2645 tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
2646 /* set dirty bit */
ths5fafdf22007-09-16 21:08:06 +00002647 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
bellardf23db162005-08-21 19:12:28 +00002648 (0xff & ~CODE_DIRTY_FLAG);
bellard3a7d9292005-08-21 09:26:42 +00002649 }
bellard13eb76e2004-01-24 15:23:36 +00002650 }
2651 } else {
ths5fafdf22007-09-16 21:08:06 +00002652 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
bellard2a4188a2006-06-25 21:54:59 +00002653 !(pd & IO_MEM_ROMD)) {
bellard13eb76e2004-01-24 15:23:36 +00002654 /* I/O case */
2655 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2656 if (l >= 4 && ((addr & 3) == 0)) {
2657 /* 32 bit read access */
bellarda4193c82004-06-03 14:01:43 +00002658 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
bellardc27004e2005-01-03 23:35:10 +00002659 stl_p(buf, val);
bellard13eb76e2004-01-24 15:23:36 +00002660 l = 4;
2661 } else if (l >= 2 && ((addr & 1) == 0)) {
2662 /* 16 bit read access */
bellarda4193c82004-06-03 14:01:43 +00002663 val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
bellardc27004e2005-01-03 23:35:10 +00002664 stw_p(buf, val);
bellard13eb76e2004-01-24 15:23:36 +00002665 l = 2;
2666 } else {
bellard1c213d12005-09-03 10:49:04 +00002667 /* 8 bit read access */
bellarda4193c82004-06-03 14:01:43 +00002668 val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr);
bellardc27004e2005-01-03 23:35:10 +00002669 stb_p(buf, val);
bellard13eb76e2004-01-24 15:23:36 +00002670 l = 1;
2671 }
2672 } else {
2673 /* RAM case */
ths5fafdf22007-09-16 21:08:06 +00002674 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
bellard13eb76e2004-01-24 15:23:36 +00002675 (addr & ~TARGET_PAGE_MASK);
2676 memcpy(buf, ptr, l);
2677 }
2678 }
2679 len -= l;
2680 buf += l;
2681 addr += l;
2682 }
2683}
bellard8df1cd02005-01-28 22:37:22 +00002684
bellardd0ecd2a2006-04-23 17:14:48 +00002685/* used for ROM loading : can write in RAM and ROM */
ths5fafdf22007-09-16 21:08:06 +00002686void cpu_physical_memory_write_rom(target_phys_addr_t addr,
bellardd0ecd2a2006-04-23 17:14:48 +00002687 const uint8_t *buf, int len)
2688{
2689 int l;
2690 uint8_t *ptr;
2691 target_phys_addr_t page;
2692 unsigned long pd;
2693 PhysPageDesc *p;
ths3b46e622007-09-17 08:09:54 +00002694
bellardd0ecd2a2006-04-23 17:14:48 +00002695 while (len > 0) {
2696 page = addr & TARGET_PAGE_MASK;
2697 l = (page + TARGET_PAGE_SIZE) - addr;
2698 if (l > len)
2699 l = len;
2700 p = phys_page_find(page >> TARGET_PAGE_BITS);
2701 if (!p) {
2702 pd = IO_MEM_UNASSIGNED;
2703 } else {
2704 pd = p->phys_offset;
2705 }
ths3b46e622007-09-17 08:09:54 +00002706
bellardd0ecd2a2006-04-23 17:14:48 +00002707 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
bellard2a4188a2006-06-25 21:54:59 +00002708 (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
2709 !(pd & IO_MEM_ROMD)) {
bellardd0ecd2a2006-04-23 17:14:48 +00002710 /* do nothing */
2711 } else {
2712 unsigned long addr1;
2713 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2714 /* ROM/RAM case */
2715 ptr = phys_ram_base + addr1;
2716 memcpy(ptr, buf, l);
2717 }
2718 len -= l;
2719 buf += l;
2720 addr += l;
2721 }
2722}
2723
2724
bellard8df1cd02005-01-28 22:37:22 +00002725/* warning: addr must be aligned */
2726uint32_t ldl_phys(target_phys_addr_t addr)
2727{
2728 int io_index;
2729 uint8_t *ptr;
2730 uint32_t val;
2731 unsigned long pd;
2732 PhysPageDesc *p;
2733
2734 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2735 if (!p) {
2736 pd = IO_MEM_UNASSIGNED;
2737 } else {
2738 pd = p->phys_offset;
2739 }
ths3b46e622007-09-17 08:09:54 +00002740
ths5fafdf22007-09-16 21:08:06 +00002741 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
bellard2a4188a2006-06-25 21:54:59 +00002742 !(pd & IO_MEM_ROMD)) {
bellard8df1cd02005-01-28 22:37:22 +00002743 /* I/O case */
2744 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2745 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2746 } else {
2747 /* RAM case */
ths5fafdf22007-09-16 21:08:06 +00002748 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
bellard8df1cd02005-01-28 22:37:22 +00002749 (addr & ~TARGET_PAGE_MASK);
2750 val = ldl_p(ptr);
2751 }
2752 return val;
2753}
2754
bellard84b7b8e2005-11-28 21:19:04 +00002755/* warning: addr must be aligned */
2756uint64_t ldq_phys(target_phys_addr_t addr)
2757{
2758 int io_index;
2759 uint8_t *ptr;
2760 uint64_t val;
2761 unsigned long pd;
2762 PhysPageDesc *p;
2763
2764 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2765 if (!p) {
2766 pd = IO_MEM_UNASSIGNED;
2767 } else {
2768 pd = p->phys_offset;
2769 }
ths3b46e622007-09-17 08:09:54 +00002770
bellard2a4188a2006-06-25 21:54:59 +00002771 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
2772 !(pd & IO_MEM_ROMD)) {
bellard84b7b8e2005-11-28 21:19:04 +00002773 /* I/O case */
2774 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2775#ifdef TARGET_WORDS_BIGENDIAN
2776 val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
2777 val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
2778#else
2779 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2780 val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
2781#endif
2782 } else {
2783 /* RAM case */
ths5fafdf22007-09-16 21:08:06 +00002784 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
bellard84b7b8e2005-11-28 21:19:04 +00002785 (addr & ~TARGET_PAGE_MASK);
2786 val = ldq_p(ptr);
2787 }
2788 return val;
2789}
2790
bellardaab33092005-10-30 20:48:42 +00002791/* XXX: optimize */
2792uint32_t ldub_phys(target_phys_addr_t addr)
2793{
2794 uint8_t val;
2795 cpu_physical_memory_read(addr, &val, 1);
2796 return val;
2797}
2798
2799/* XXX: optimize */
2800uint32_t lduw_phys(target_phys_addr_t addr)
2801{
2802 uint16_t val;
2803 cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
2804 return tswap16(val);
2805}
2806
bellard8df1cd02005-01-28 22:37:22 +00002807/* warning: addr must be aligned. The ram page is not masked as dirty
2808 and the code inside is not invalidated. It is useful if the dirty
2809 bits are used to track modified PTEs */
2810void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
2811{
2812 int io_index;
2813 uint8_t *ptr;
2814 unsigned long pd;
2815 PhysPageDesc *p;
2816
2817 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2818 if (!p) {
2819 pd = IO_MEM_UNASSIGNED;
2820 } else {
2821 pd = p->phys_offset;
2822 }
ths3b46e622007-09-17 08:09:54 +00002823
bellard3a7d9292005-08-21 09:26:42 +00002824 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
bellard8df1cd02005-01-28 22:37:22 +00002825 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2826 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2827 } else {
ths5fafdf22007-09-16 21:08:06 +00002828 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
bellard8df1cd02005-01-28 22:37:22 +00002829 (addr & ~TARGET_PAGE_MASK);
2830 stl_p(ptr, val);
2831 }
2832}
2833
j_mayerbc98a7e2007-04-04 07:55:12 +00002834void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
2835{
2836 int io_index;
2837 uint8_t *ptr;
2838 unsigned long pd;
2839 PhysPageDesc *p;
2840
2841 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2842 if (!p) {
2843 pd = IO_MEM_UNASSIGNED;
2844 } else {
2845 pd = p->phys_offset;
2846 }
ths3b46e622007-09-17 08:09:54 +00002847
j_mayerbc98a7e2007-04-04 07:55:12 +00002848 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2849 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2850#ifdef TARGET_WORDS_BIGENDIAN
2851 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
2852 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
2853#else
2854 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2855 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
2856#endif
2857 } else {
ths5fafdf22007-09-16 21:08:06 +00002858 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
j_mayerbc98a7e2007-04-04 07:55:12 +00002859 (addr & ~TARGET_PAGE_MASK);
2860 stq_p(ptr, val);
2861 }
2862}
2863
bellard8df1cd02005-01-28 22:37:22 +00002864/* warning: addr must be aligned */
bellard8df1cd02005-01-28 22:37:22 +00002865void stl_phys(target_phys_addr_t addr, uint32_t val)
2866{
2867 int io_index;
2868 uint8_t *ptr;
2869 unsigned long pd;
2870 PhysPageDesc *p;
2871
2872 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2873 if (!p) {
2874 pd = IO_MEM_UNASSIGNED;
2875 } else {
2876 pd = p->phys_offset;
2877 }
ths3b46e622007-09-17 08:09:54 +00002878
bellard3a7d9292005-08-21 09:26:42 +00002879 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
bellard8df1cd02005-01-28 22:37:22 +00002880 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2881 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2882 } else {
2883 unsigned long addr1;
2884 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2885 /* RAM case */
2886 ptr = phys_ram_base + addr1;
2887 stl_p(ptr, val);
bellard3a7d9292005-08-21 09:26:42 +00002888 if (!cpu_physical_memory_is_dirty(addr1)) {
2889 /* invalidate code */
2890 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
2891 /* set dirty bit */
bellardf23db162005-08-21 19:12:28 +00002892 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
2893 (0xff & ~CODE_DIRTY_FLAG);
bellard3a7d9292005-08-21 09:26:42 +00002894 }
bellard8df1cd02005-01-28 22:37:22 +00002895 }
2896}
2897
bellardaab33092005-10-30 20:48:42 +00002898/* XXX: optimize */
2899void stb_phys(target_phys_addr_t addr, uint32_t val)
2900{
2901 uint8_t v = val;
2902 cpu_physical_memory_write(addr, &v, 1);
2903}
2904
2905/* XXX: optimize */
2906void stw_phys(target_phys_addr_t addr, uint32_t val)
2907{
2908 uint16_t v = tswap16(val);
2909 cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
2910}
2911
2912/* XXX: optimize */
2913void stq_phys(target_phys_addr_t addr, uint64_t val)
2914{
2915 val = tswap64(val);
2916 cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
2917}
2918
bellard13eb76e2004-01-24 15:23:36 +00002919#endif
2920
2921/* virtual memory access for debug */
ths5fafdf22007-09-16 21:08:06 +00002922int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
bellardb448f2f2004-02-25 23:24:04 +00002923 uint8_t *buf, int len, int is_write)
bellard13eb76e2004-01-24 15:23:36 +00002924{
2925 int l;
j_mayer9b3c35e2007-04-07 11:21:28 +00002926 target_phys_addr_t phys_addr;
2927 target_ulong page;
bellard13eb76e2004-01-24 15:23:36 +00002928
2929 while (len > 0) {
2930 page = addr & TARGET_PAGE_MASK;
2931 phys_addr = cpu_get_phys_page_debug(env, page);
2932 /* if no physical page mapped, return an error */
2933 if (phys_addr == -1)
2934 return -1;
2935 l = (page + TARGET_PAGE_SIZE) - addr;
2936 if (l > len)
2937 l = len;
ths5fafdf22007-09-16 21:08:06 +00002938 cpu_physical_memory_rw(phys_addr + (addr & ~TARGET_PAGE_MASK),
bellardb448f2f2004-02-25 23:24:04 +00002939 buf, l, is_write);
bellard13eb76e2004-01-24 15:23:36 +00002940 len -= l;
2941 buf += l;
2942 addr += l;
2943 }
2944 return 0;
2945}
2946
bellarde3db7222005-01-26 22:00:47 +00002947void dump_exec_info(FILE *f,
2948 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2949{
2950 int i, target_code_size, max_target_code_size;
2951 int direct_jmp_count, direct_jmp2_count, cross_page;
2952 TranslationBlock *tb;
ths3b46e622007-09-17 08:09:54 +00002953
bellarde3db7222005-01-26 22:00:47 +00002954 target_code_size = 0;
2955 max_target_code_size = 0;
2956 cross_page = 0;
2957 direct_jmp_count = 0;
2958 direct_jmp2_count = 0;
2959 for(i = 0; i < nb_tbs; i++) {
2960 tb = &tbs[i];
2961 target_code_size += tb->size;
2962 if (tb->size > max_target_code_size)
2963 max_target_code_size = tb->size;
2964 if (tb->page_addr[1] != -1)
2965 cross_page++;
2966 if (tb->tb_next_offset[0] != 0xffff) {
2967 direct_jmp_count++;
2968 if (tb->tb_next_offset[1] != 0xffff) {
2969 direct_jmp2_count++;
2970 }
2971 }
2972 }
2973 /* XXX: avoid using doubles ? */
bellard57fec1f2008-02-01 10:50:11 +00002974 cpu_fprintf(f, "Translation buffer state:\n");
bellard26a5f132008-05-28 12:30:31 +00002975 cpu_fprintf(f, "gen code size %ld/%ld\n",
2976 code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size);
2977 cpu_fprintf(f, "TB count %d/%d\n",
2978 nb_tbs, code_gen_max_blocks);
ths5fafdf22007-09-16 21:08:06 +00002979 cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
bellarde3db7222005-01-26 22:00:47 +00002980 nb_tbs ? target_code_size / nb_tbs : 0,
2981 max_target_code_size);
ths5fafdf22007-09-16 21:08:06 +00002982 cpu_fprintf(f, "TB avg host size %d bytes (expansion ratio: %0.1f)\n",
bellarde3db7222005-01-26 22:00:47 +00002983 nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
2984 target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
ths5fafdf22007-09-16 21:08:06 +00002985 cpu_fprintf(f, "cross page TB count %d (%d%%)\n",
2986 cross_page,
bellarde3db7222005-01-26 22:00:47 +00002987 nb_tbs ? (cross_page * 100) / nb_tbs : 0);
2988 cpu_fprintf(f, "direct jump count %d (%d%%) (2 jumps=%d %d%%)\n",
ths5fafdf22007-09-16 21:08:06 +00002989 direct_jmp_count,
bellarde3db7222005-01-26 22:00:47 +00002990 nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
2991 direct_jmp2_count,
2992 nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
bellard57fec1f2008-02-01 10:50:11 +00002993 cpu_fprintf(f, "\nStatistics:\n");
bellarde3db7222005-01-26 22:00:47 +00002994 cpu_fprintf(f, "TB flush count %d\n", tb_flush_count);
2995 cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
2996 cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count);
bellardb67d9a52008-05-23 09:57:34 +00002997 tcg_dump_info(f, cpu_fprintf);
bellarde3db7222005-01-26 22:00:47 +00002998}
2999
ths5fafdf22007-09-16 21:08:06 +00003000#if !defined(CONFIG_USER_ONLY)
bellard61382a52003-10-27 21:22:23 +00003001
3002#define MMUSUFFIX _cmmu
3003#define GETPC() NULL
3004#define env cpu_single_env
bellardb769d8f2004-10-03 15:07:13 +00003005#define SOFTMMU_CODE_ACCESS
bellard61382a52003-10-27 21:22:23 +00003006
3007#define SHIFT 0
3008#include "softmmu_template.h"
3009
3010#define SHIFT 1
3011#include "softmmu_template.h"
3012
3013#define SHIFT 2
3014#include "softmmu_template.h"
3015
3016#define SHIFT 3
3017#include "softmmu_template.h"
3018
3019#undef env
3020
3021#endif