blob: 06ccf283bca435bee61def974ba554fe92cb2b73 [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"
pbrook53a59602006-03-25 19:31:22 +000039#if defined(CONFIG_USER_ONLY)
40#include <qemu.h>
41#endif
bellard54936002003-05-13 00:25:15 +000042
bellardfd6ce8f2003-05-14 19:00:11 +000043//#define DEBUG_TB_INVALIDATE
bellard66e85a22003-06-24 13:28:12 +000044//#define DEBUG_FLUSH
bellard9fa3e852004-01-04 18:06:42 +000045//#define DEBUG_TLB
pbrook67d3b952006-12-18 05:03:52 +000046//#define DEBUG_UNASSIGNED
bellardfd6ce8f2003-05-14 19:00:11 +000047
48/* make various TB consistency checks */
ths5fafdf22007-09-16 21:08:06 +000049//#define DEBUG_TB_CHECK
50//#define DEBUG_TLB_CHECK
bellardfd6ce8f2003-05-14 19:00:11 +000051
ths1196be32007-03-17 15:17:58 +000052//#define DEBUG_IOPORT
blueswir1db7b5422007-05-26 17:36:03 +000053//#define DEBUG_SUBPAGE
ths1196be32007-03-17 15:17:58 +000054
pbrook99773bd2006-04-16 15:14:59 +000055#if !defined(CONFIG_USER_ONLY)
56/* TB consistency checks only implemented for usermode emulation. */
57#undef DEBUG_TB_CHECK
58#endif
59
bellardfd6ce8f2003-05-14 19:00:11 +000060/* threshold to flush the translated code buffer */
blueswir1d07bde82007-12-11 19:35:45 +000061#define CODE_GEN_BUFFER_MAX_SIZE (CODE_GEN_BUFFER_SIZE - code_gen_max_block_size())
bellardfd6ce8f2003-05-14 19:00:11 +000062
bellard9fa3e852004-01-04 18:06:42 +000063#define SMC_BITMAP_USE_THRESHOLD 10
64
65#define MMAP_AREA_START 0x00000000
66#define MMAP_AREA_END 0xa8000000
bellardfd6ce8f2003-05-14 19:00:11 +000067
bellard108c49b2005-07-24 12:55:09 +000068#if defined(TARGET_SPARC64)
69#define TARGET_PHYS_ADDR_SPACE_BITS 41
blueswir15dcb6b92007-05-19 12:58:30 +000070#elif defined(TARGET_SPARC)
71#define TARGET_PHYS_ADDR_SPACE_BITS 36
j_mayerbedb69e2007-04-05 20:08:21 +000072#elif defined(TARGET_ALPHA)
73#define TARGET_PHYS_ADDR_SPACE_BITS 42
74#define TARGET_VIRT_ADDR_SPACE_BITS 42
bellard108c49b2005-07-24 12:55:09 +000075#elif defined(TARGET_PPC64)
76#define TARGET_PHYS_ADDR_SPACE_BITS 42
aurel32967032c2008-04-22 20:37:34 +000077#elif defined(TARGET_X86_64) && !defined(USE_KQEMU)
78#define TARGET_PHYS_ADDR_SPACE_BITS 40
79#elif defined(TARGET_I386) && !defined(USE_KQEMU)
80#define TARGET_PHYS_ADDR_SPACE_BITS 36
bellard108c49b2005-07-24 12:55:09 +000081#else
82/* Note: for compatibility with kqemu, we use 32 bits for x86_64 */
83#define TARGET_PHYS_ADDR_SPACE_BITS 32
84#endif
85
bellardfd6ce8f2003-05-14 19:00:11 +000086TranslationBlock tbs[CODE_GEN_MAX_BLOCKS];
bellard9fa3e852004-01-04 18:06:42 +000087TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
bellardfd6ce8f2003-05-14 19:00:11 +000088int nb_tbs;
bellardeb51d102003-05-14 21:51:13 +000089/* any access to the tbs or the page table must use this lock */
90spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
bellardfd6ce8f2003-05-14 19:00:11 +000091
bellardb8076a72005-04-07 22:20:31 +000092uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE] __attribute__((aligned (32)));
bellardfd6ce8f2003-05-14 19:00:11 +000093uint8_t *code_gen_ptr;
94
aurel32967032c2008-04-22 20:37:34 +000095ram_addr_t phys_ram_size;
bellard9fa3e852004-01-04 18:06:42 +000096int phys_ram_fd;
97uint8_t *phys_ram_base;
bellard1ccde1c2004-02-06 19:46:14 +000098uint8_t *phys_ram_dirty;
bellarde9a1ab12007-02-08 23:08:38 +000099static ram_addr_t phys_ram_alloc_offset = 0;
bellard9fa3e852004-01-04 18:06:42 +0000100
bellard6a00d602005-11-21 23:25:50 +0000101CPUState *first_cpu;
102/* current CPU in the current thread. It is only valid inside
103 cpu_exec() */
ths5fafdf22007-09-16 21:08:06 +0000104CPUState *cpu_single_env;
bellard6a00d602005-11-21 23:25:50 +0000105
bellard54936002003-05-13 00:25:15 +0000106typedef struct PageDesc {
bellard92e873b2004-05-21 14:52:29 +0000107 /* list of TBs intersecting this ram page */
bellardfd6ce8f2003-05-14 19:00:11 +0000108 TranslationBlock *first_tb;
bellard9fa3e852004-01-04 18:06:42 +0000109 /* in order to optimize self modifying code, we count the number
110 of lookups we do to a given page to use a bitmap */
111 unsigned int code_write_count;
112 uint8_t *code_bitmap;
113#if defined(CONFIG_USER_ONLY)
114 unsigned long flags;
115#endif
bellard54936002003-05-13 00:25:15 +0000116} PageDesc;
117
bellard92e873b2004-05-21 14:52:29 +0000118typedef struct PhysPageDesc {
119 /* offset in host memory of the page + io_index in the low 12 bits */
aurel32967032c2008-04-22 20:37:34 +0000120 ram_addr_t phys_offset;
bellard92e873b2004-05-21 14:52:29 +0000121} PhysPageDesc;
122
bellard54936002003-05-13 00:25:15 +0000123#define L2_BITS 10
j_mayerbedb69e2007-04-05 20:08:21 +0000124#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
125/* XXX: this is a temporary hack for alpha target.
126 * In the future, this is to be replaced by a multi-level table
127 * to actually be able to handle the complete 64 bits address space.
128 */
129#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
130#else
aurel32967032c2008-04-22 20:37:34 +0000131#define L1_BITS (TARGET_PHYS_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
j_mayerbedb69e2007-04-05 20:08:21 +0000132#endif
bellard54936002003-05-13 00:25:15 +0000133
aurel32967032c2008-04-22 20:37:34 +0000134#undef L1_BITS
135#undef L2_BITS
136#define L1_BITS 13
137#define L2_BITS 13
138
bellard54936002003-05-13 00:25:15 +0000139#define L1_SIZE (1 << L1_BITS)
140#define L2_SIZE (1 << L2_BITS)
141
bellard33417e72003-08-10 21:47:01 +0000142static void io_mem_init(void);
bellardfd6ce8f2003-05-14 19:00:11 +0000143
bellard83fb7ad2004-07-05 21:25:26 +0000144unsigned long qemu_real_host_page_size;
145unsigned long qemu_host_page_bits;
146unsigned long qemu_host_page_size;
147unsigned long qemu_host_page_mask;
bellard54936002003-05-13 00:25:15 +0000148
bellard92e873b2004-05-21 14:52:29 +0000149/* XXX: for system emulation, it could just be an array */
bellard54936002003-05-13 00:25:15 +0000150static PageDesc *l1_map[L1_SIZE];
bellard0a962c02005-02-10 22:00:27 +0000151PhysPageDesc **l1_phys_map;
bellard54936002003-05-13 00:25:15 +0000152
bellard33417e72003-08-10 21:47:01 +0000153/* io memory support */
bellard33417e72003-08-10 21:47:01 +0000154CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
155CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
bellarda4193c82004-06-03 14:01:43 +0000156void *io_mem_opaque[IO_MEM_NB_ENTRIES];
bellard33417e72003-08-10 21:47:01 +0000157static int io_mem_nb;
pbrook6658ffb2007-03-16 23:58:11 +0000158#if defined(CONFIG_SOFTMMU)
159static 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
bellardb346ff42003-06-15 20:05:50 +0000181static void page_init(void)
bellard54936002003-05-13 00:25:15 +0000182{
bellard83fb7ad2004-07-05 21:25:26 +0000183 /* NOTE: we can always suppose that qemu_host_page_size >=
bellard54936002003-05-13 00:25:15 +0000184 TARGET_PAGE_SIZE */
bellard67b915a2004-03-31 23:37:16 +0000185#ifdef _WIN32
bellardd5a8f072004-09-29 21:15:28 +0000186 {
187 SYSTEM_INFO system_info;
188 DWORD old_protect;
ths3b46e622007-09-17 08:09:54 +0000189
bellardd5a8f072004-09-29 21:15:28 +0000190 GetSystemInfo(&system_info);
191 qemu_real_host_page_size = system_info.dwPageSize;
ths3b46e622007-09-17 08:09:54 +0000192
bellardd5a8f072004-09-29 21:15:28 +0000193 VirtualProtect(code_gen_buffer, sizeof(code_gen_buffer),
194 PAGE_EXECUTE_READWRITE, &old_protect);
195 }
bellard67b915a2004-03-31 23:37:16 +0000196#else
bellard83fb7ad2004-07-05 21:25:26 +0000197 qemu_real_host_page_size = getpagesize();
bellardd5a8f072004-09-29 21:15:28 +0000198 {
199 unsigned long start, end;
200
201 start = (unsigned long)code_gen_buffer;
202 start &= ~(qemu_real_host_page_size - 1);
ths3b46e622007-09-17 08:09:54 +0000203
bellardd5a8f072004-09-29 21:15:28 +0000204 end = (unsigned long)code_gen_buffer + sizeof(code_gen_buffer);
205 end += qemu_real_host_page_size - 1;
206 end &= ~(qemu_real_host_page_size - 1);
ths3b46e622007-09-17 08:09:54 +0000207
ths5fafdf22007-09-16 21:08:06 +0000208 mprotect((void *)start, end - start,
bellardd5a8f072004-09-29 21:15:28 +0000209 PROT_READ | PROT_WRITE | PROT_EXEC);
210 }
bellard67b915a2004-03-31 23:37:16 +0000211#endif
bellardd5a8f072004-09-29 21:15:28 +0000212
bellard83fb7ad2004-07-05 21:25:26 +0000213 if (qemu_host_page_size == 0)
214 qemu_host_page_size = qemu_real_host_page_size;
215 if (qemu_host_page_size < TARGET_PAGE_SIZE)
216 qemu_host_page_size = TARGET_PAGE_SIZE;
217 qemu_host_page_bits = 0;
218 while ((1 << qemu_host_page_bits) < qemu_host_page_size)
219 qemu_host_page_bits++;
220 qemu_host_page_mask = ~(qemu_host_page_size - 1);
bellard108c49b2005-07-24 12:55:09 +0000221 l1_phys_map = qemu_vmalloc(L1_SIZE * sizeof(void *));
222 memset(l1_phys_map, 0, L1_SIZE * sizeof(void *));
balrog50a95692007-12-12 01:16:23 +0000223
224#if !defined(_WIN32) && defined(CONFIG_USER_ONLY)
225 {
226 long long startaddr, endaddr;
227 FILE *f;
228 int n;
229
230 f = fopen("/proc/self/maps", "r");
231 if (f) {
232 do {
233 n = fscanf (f, "%llx-%llx %*[^\n]\n", &startaddr, &endaddr);
234 if (n == 2) {
235 page_set_flags(TARGET_PAGE_ALIGN(startaddr),
236 TARGET_PAGE_ALIGN(endaddr),
237 PAGE_RESERVED);
238 }
239 } while (!feof(f));
240 fclose(f);
241 }
242 }
243#endif
bellard54936002003-05-13 00:25:15 +0000244}
245
aurel32967032c2008-04-22 20:37:34 +0000246static inline PageDesc *page_find_alloc(target_ulong index)
bellard54936002003-05-13 00:25:15 +0000247{
bellard54936002003-05-13 00:25:15 +0000248 PageDesc **lp, *p;
249
bellard54936002003-05-13 00:25:15 +0000250 lp = &l1_map[index >> L2_BITS];
251 p = *lp;
252 if (!p) {
253 /* allocate if not found */
bellard59817cc2004-02-16 22:01:13 +0000254 p = qemu_malloc(sizeof(PageDesc) * L2_SIZE);
bellardfd6ce8f2003-05-14 19:00:11 +0000255 memset(p, 0, sizeof(PageDesc) * L2_SIZE);
bellard54936002003-05-13 00:25:15 +0000256 *lp = p;
257 }
258 return p + (index & (L2_SIZE - 1));
259}
260
aurel32967032c2008-04-22 20:37:34 +0000261static inline PageDesc *page_find(target_ulong index)
bellard54936002003-05-13 00:25:15 +0000262{
bellard54936002003-05-13 00:25:15 +0000263 PageDesc *p;
264
bellard54936002003-05-13 00:25:15 +0000265 p = l1_map[index >> L2_BITS];
266 if (!p)
267 return 0;
bellardfd6ce8f2003-05-14 19:00:11 +0000268 return p + (index & (L2_SIZE - 1));
bellard54936002003-05-13 00:25:15 +0000269}
270
bellard108c49b2005-07-24 12:55:09 +0000271static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
bellard92e873b2004-05-21 14:52:29 +0000272{
bellard108c49b2005-07-24 12:55:09 +0000273 void **lp, **p;
pbrooke3f4e2a2006-04-08 20:02:06 +0000274 PhysPageDesc *pd;
bellard92e873b2004-05-21 14:52:29 +0000275
bellard108c49b2005-07-24 12:55:09 +0000276 p = (void **)l1_phys_map;
aurel32967032c2008-04-22 20:37:34 +0000277#if 0
bellard108c49b2005-07-24 12:55:09 +0000278#if TARGET_PHYS_ADDR_SPACE_BITS > 32
279
280#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
281#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
282#endif
283 lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1));
bellard92e873b2004-05-21 14:52:29 +0000284 p = *lp;
285 if (!p) {
286 /* allocate if not found */
bellard108c49b2005-07-24 12:55:09 +0000287 if (!alloc)
288 return NULL;
289 p = qemu_vmalloc(sizeof(void *) * L1_SIZE);
290 memset(p, 0, sizeof(void *) * L1_SIZE);
291 *lp = p;
292 }
293#endif
aurel32967032c2008-04-22 20:37:34 +0000294#endif
bellard108c49b2005-07-24 12:55:09 +0000295 lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
pbrooke3f4e2a2006-04-08 20:02:06 +0000296 pd = *lp;
297 if (!pd) {
298 int i;
bellard108c49b2005-07-24 12:55:09 +0000299 /* allocate if not found */
300 if (!alloc)
301 return NULL;
pbrooke3f4e2a2006-04-08 20:02:06 +0000302 pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
303 *lp = pd;
304 for (i = 0; i < L2_SIZE; i++)
305 pd[i].phys_offset = IO_MEM_UNASSIGNED;
bellard92e873b2004-05-21 14:52:29 +0000306 }
pbrooke3f4e2a2006-04-08 20:02:06 +0000307 return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
bellard92e873b2004-05-21 14:52:29 +0000308}
309
bellard108c49b2005-07-24 12:55:09 +0000310static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
bellard92e873b2004-05-21 14:52:29 +0000311{
bellard108c49b2005-07-24 12:55:09 +0000312 return phys_page_find_alloc(index, 0);
bellard92e873b2004-05-21 14:52:29 +0000313}
314
bellard9fa3e852004-01-04 18:06:42 +0000315#if !defined(CONFIG_USER_ONLY)
bellard6a00d602005-11-21 23:25:50 +0000316static void tlb_protect_code(ram_addr_t ram_addr);
ths5fafdf22007-09-16 21:08:06 +0000317static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
bellard3a7d9292005-08-21 09:26:42 +0000318 target_ulong vaddr);
bellard9fa3e852004-01-04 18:06:42 +0000319#endif
bellardfd6ce8f2003-05-14 19:00:11 +0000320
bellard6a00d602005-11-21 23:25:50 +0000321void cpu_exec_init(CPUState *env)
bellardfd6ce8f2003-05-14 19:00:11 +0000322{
bellard6a00d602005-11-21 23:25:50 +0000323 CPUState **penv;
324 int cpu_index;
325
bellardfd6ce8f2003-05-14 19:00:11 +0000326 if (!code_gen_ptr) {
bellard57fec1f2008-02-01 10:50:11 +0000327 cpu_gen_init();
bellardfd6ce8f2003-05-14 19:00:11 +0000328 code_gen_ptr = code_gen_buffer;
bellardb346ff42003-06-15 20:05:50 +0000329 page_init();
bellard33417e72003-08-10 21:47:01 +0000330 io_mem_init();
bellardfd6ce8f2003-05-14 19:00:11 +0000331 }
bellard6a00d602005-11-21 23:25:50 +0000332 env->next_cpu = NULL;
333 penv = &first_cpu;
334 cpu_index = 0;
335 while (*penv != NULL) {
336 penv = (CPUState **)&(*penv)->next_cpu;
337 cpu_index++;
338 }
339 env->cpu_index = cpu_index;
pbrook6658ffb2007-03-16 23:58:11 +0000340 env->nb_watchpoints = 0;
bellard6a00d602005-11-21 23:25:50 +0000341 *penv = env;
bellardfd6ce8f2003-05-14 19:00:11 +0000342}
343
bellard9fa3e852004-01-04 18:06:42 +0000344static inline void invalidate_page_bitmap(PageDesc *p)
345{
346 if (p->code_bitmap) {
bellard59817cc2004-02-16 22:01:13 +0000347 qemu_free(p->code_bitmap);
bellard9fa3e852004-01-04 18:06:42 +0000348 p->code_bitmap = NULL;
349 }
350 p->code_write_count = 0;
351}
352
bellardfd6ce8f2003-05-14 19:00:11 +0000353/* set to NULL all the 'first_tb' fields in all PageDescs */
354static void page_flush_tb(void)
355{
356 int i, j;
357 PageDesc *p;
358
359 for(i = 0; i < L1_SIZE; i++) {
360 p = l1_map[i];
361 if (p) {
bellard9fa3e852004-01-04 18:06:42 +0000362 for(j = 0; j < L2_SIZE; j++) {
363 p->first_tb = NULL;
364 invalidate_page_bitmap(p);
365 p++;
366 }
bellardfd6ce8f2003-05-14 19:00:11 +0000367 }
368 }
369}
370
371/* flush all the translation blocks */
bellardd4e81642003-05-25 16:46:15 +0000372/* XXX: tb_flush is currently not thread safe */
bellard6a00d602005-11-21 23:25:50 +0000373void tb_flush(CPUState *env1)
bellardfd6ce8f2003-05-14 19:00:11 +0000374{
bellard6a00d602005-11-21 23:25:50 +0000375 CPUState *env;
bellard01243112004-01-04 15:48:17 +0000376#if defined(DEBUG_FLUSH)
blueswir1ab3d1722007-11-04 07:31:40 +0000377 printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
378 (unsigned long)(code_gen_ptr - code_gen_buffer),
379 nb_tbs, nb_tbs > 0 ?
380 ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
bellardfd6ce8f2003-05-14 19:00:11 +0000381#endif
pbrooka208e542008-03-31 17:07:36 +0000382 if ((unsigned long)(code_gen_ptr - code_gen_buffer) > CODE_GEN_BUFFER_SIZE)
383 cpu_abort(env1, "Internal error: code buffer overflow\n");
384
bellardfd6ce8f2003-05-14 19:00:11 +0000385 nb_tbs = 0;
ths3b46e622007-09-17 08:09:54 +0000386
bellard6a00d602005-11-21 23:25:50 +0000387 for(env = first_cpu; env != NULL; env = env->next_cpu) {
388 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
389 }
bellard9fa3e852004-01-04 18:06:42 +0000390
bellard8a8a6082004-10-03 13:36:49 +0000391 memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
bellardfd6ce8f2003-05-14 19:00:11 +0000392 page_flush_tb();
bellard9fa3e852004-01-04 18:06:42 +0000393
bellardfd6ce8f2003-05-14 19:00:11 +0000394 code_gen_ptr = code_gen_buffer;
bellardd4e81642003-05-25 16:46:15 +0000395 /* XXX: flush processor icache at this point if cache flush is
396 expensive */
bellarde3db7222005-01-26 22:00:47 +0000397 tb_flush_count++;
bellardfd6ce8f2003-05-14 19:00:11 +0000398}
399
400#ifdef DEBUG_TB_CHECK
401
j_mayerbc98a7e2007-04-04 07:55:12 +0000402static void tb_invalidate_check(target_ulong address)
bellardfd6ce8f2003-05-14 19:00:11 +0000403{
404 TranslationBlock *tb;
405 int i;
406 address &= TARGET_PAGE_MASK;
pbrook99773bd2006-04-16 15:14:59 +0000407 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
408 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
bellardfd6ce8f2003-05-14 19:00:11 +0000409 if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
410 address >= tb->pc + tb->size)) {
411 printf("ERROR invalidate: address=%08lx PC=%08lx size=%04x\n",
pbrook99773bd2006-04-16 15:14:59 +0000412 address, (long)tb->pc, tb->size);
bellardfd6ce8f2003-05-14 19:00:11 +0000413 }
414 }
415 }
416}
417
418/* verify that all the pages have correct rights for code */
419static void tb_page_check(void)
420{
421 TranslationBlock *tb;
422 int i, flags1, flags2;
ths3b46e622007-09-17 08:09:54 +0000423
pbrook99773bd2006-04-16 15:14:59 +0000424 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
425 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
bellardfd6ce8f2003-05-14 19:00:11 +0000426 flags1 = page_get_flags(tb->pc);
427 flags2 = page_get_flags(tb->pc + tb->size - 1);
428 if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
429 printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
pbrook99773bd2006-04-16 15:14:59 +0000430 (long)tb->pc, tb->size, flags1, flags2);
bellardfd6ce8f2003-05-14 19:00:11 +0000431 }
432 }
433 }
434}
435
bellardd4e81642003-05-25 16:46:15 +0000436void tb_jmp_check(TranslationBlock *tb)
437{
438 TranslationBlock *tb1;
439 unsigned int n1;
440
441 /* suppress any remaining jumps to this TB */
442 tb1 = tb->jmp_first;
443 for(;;) {
444 n1 = (long)tb1 & 3;
445 tb1 = (TranslationBlock *)((long)tb1 & ~3);
446 if (n1 == 2)
447 break;
448 tb1 = tb1->jmp_next[n1];
449 }
450 /* check end of list */
451 if (tb1 != tb) {
452 printf("ERROR: jmp_list from 0x%08lx\n", (long)tb);
453 }
454}
455
bellardfd6ce8f2003-05-14 19:00:11 +0000456#endif
457
458/* invalidate one TB */
459static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb,
460 int next_offset)
461{
462 TranslationBlock *tb1;
463 for(;;) {
464 tb1 = *ptb;
465 if (tb1 == tb) {
466 *ptb = *(TranslationBlock **)((char *)tb1 + next_offset);
467 break;
468 }
469 ptb = (TranslationBlock **)((char *)tb1 + next_offset);
470 }
471}
472
bellard9fa3e852004-01-04 18:06:42 +0000473static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
474{
475 TranslationBlock *tb1;
476 unsigned int n1;
477
478 for(;;) {
479 tb1 = *ptb;
480 n1 = (long)tb1 & 3;
481 tb1 = (TranslationBlock *)((long)tb1 & ~3);
482 if (tb1 == tb) {
483 *ptb = tb1->page_next[n1];
484 break;
485 }
486 ptb = &tb1->page_next[n1];
487 }
488}
489
bellardd4e81642003-05-25 16:46:15 +0000490static inline void tb_jmp_remove(TranslationBlock *tb, int n)
491{
492 TranslationBlock *tb1, **ptb;
493 unsigned int n1;
494
495 ptb = &tb->jmp_next[n];
496 tb1 = *ptb;
497 if (tb1) {
498 /* find tb(n) in circular list */
499 for(;;) {
500 tb1 = *ptb;
501 n1 = (long)tb1 & 3;
502 tb1 = (TranslationBlock *)((long)tb1 & ~3);
503 if (n1 == n && tb1 == tb)
504 break;
505 if (n1 == 2) {
506 ptb = &tb1->jmp_first;
507 } else {
508 ptb = &tb1->jmp_next[n1];
509 }
510 }
511 /* now we can suppress tb(n) from the list */
512 *ptb = tb->jmp_next[n];
513
514 tb->jmp_next[n] = NULL;
515 }
516}
517
518/* reset the jump entry 'n' of a TB so that it is not chained to
519 another TB */
520static inline void tb_reset_jump(TranslationBlock *tb, int n)
521{
522 tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
523}
524
aurel32967032c2008-04-22 20:37:34 +0000525static inline void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr)
bellardfd6ce8f2003-05-14 19:00:11 +0000526{
bellard6a00d602005-11-21 23:25:50 +0000527 CPUState *env;
bellardfd6ce8f2003-05-14 19:00:11 +0000528 PageDesc *p;
bellard8a40a182005-11-20 10:35:40 +0000529 unsigned int h, n1;
aurel32967032c2008-04-22 20:37:34 +0000530 target_phys_addr_t phys_pc;
bellard8a40a182005-11-20 10:35:40 +0000531 TranslationBlock *tb1, *tb2;
ths3b46e622007-09-17 08:09:54 +0000532
bellard9fa3e852004-01-04 18:06:42 +0000533 /* remove the TB from the hash list */
534 phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
535 h = tb_phys_hash_func(phys_pc);
ths5fafdf22007-09-16 21:08:06 +0000536 tb_remove(&tb_phys_hash[h], tb,
bellard9fa3e852004-01-04 18:06:42 +0000537 offsetof(TranslationBlock, phys_hash_next));
bellardfd6ce8f2003-05-14 19:00:11 +0000538
bellard9fa3e852004-01-04 18:06:42 +0000539 /* remove the TB from the page list */
540 if (tb->page_addr[0] != page_addr) {
541 p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
542 tb_page_remove(&p->first_tb, tb);
543 invalidate_page_bitmap(p);
544 }
545 if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
546 p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
547 tb_page_remove(&p->first_tb, tb);
548 invalidate_page_bitmap(p);
549 }
550
bellard8a40a182005-11-20 10:35:40 +0000551 tb_invalidated_flag = 1;
552
553 /* remove the TB from the hash list */
554 h = tb_jmp_cache_hash_func(tb->pc);
bellard6a00d602005-11-21 23:25:50 +0000555 for(env = first_cpu; env != NULL; env = env->next_cpu) {
556 if (env->tb_jmp_cache[h] == tb)
557 env->tb_jmp_cache[h] = NULL;
558 }
bellard8a40a182005-11-20 10:35:40 +0000559
560 /* suppress this TB from the two jump lists */
561 tb_jmp_remove(tb, 0);
562 tb_jmp_remove(tb, 1);
563
564 /* suppress any remaining jumps to this TB */
565 tb1 = tb->jmp_first;
566 for(;;) {
567 n1 = (long)tb1 & 3;
568 if (n1 == 2)
569 break;
570 tb1 = (TranslationBlock *)((long)tb1 & ~3);
571 tb2 = tb1->jmp_next[n1];
572 tb_reset_jump(tb1, n1);
573 tb1->jmp_next[n1] = NULL;
574 tb1 = tb2;
575 }
576 tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
577
bellarde3db7222005-01-26 22:00:47 +0000578 tb_phys_invalidate_count++;
bellard9fa3e852004-01-04 18:06:42 +0000579}
580
581static inline void set_bits(uint8_t *tab, int start, int len)
582{
583 int end, mask, end1;
584
585 end = start + len;
586 tab += start >> 3;
587 mask = 0xff << (start & 7);
588 if ((start & ~7) == (end & ~7)) {
589 if (start < end) {
590 mask &= ~(0xff << (end & 7));
591 *tab |= mask;
592 }
593 } else {
594 *tab++ |= mask;
595 start = (start + 8) & ~7;
596 end1 = end & ~7;
597 while (start < end1) {
598 *tab++ = 0xff;
599 start += 8;
600 }
601 if (start < end) {
602 mask = ~(0xff << (end & 7));
603 *tab |= mask;
604 }
605 }
606}
607
608static void build_page_bitmap(PageDesc *p)
609{
610 int n, tb_start, tb_end;
611 TranslationBlock *tb;
ths3b46e622007-09-17 08:09:54 +0000612
bellard59817cc2004-02-16 22:01:13 +0000613 p->code_bitmap = qemu_malloc(TARGET_PAGE_SIZE / 8);
bellard9fa3e852004-01-04 18:06:42 +0000614 if (!p->code_bitmap)
615 return;
616 memset(p->code_bitmap, 0, TARGET_PAGE_SIZE / 8);
617
618 tb = p->first_tb;
619 while (tb != NULL) {
620 n = (long)tb & 3;
621 tb = (TranslationBlock *)((long)tb & ~3);
622 /* NOTE: this is subtle as a TB may span two physical pages */
623 if (n == 0) {
624 /* NOTE: tb_end may be after the end of the page, but
625 it is not a problem */
626 tb_start = tb->pc & ~TARGET_PAGE_MASK;
627 tb_end = tb_start + tb->size;
628 if (tb_end > TARGET_PAGE_SIZE)
629 tb_end = TARGET_PAGE_SIZE;
630 } else {
631 tb_start = 0;
632 tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
633 }
634 set_bits(p->code_bitmap, tb_start, tb_end - tb_start);
635 tb = tb->page_next[n];
636 }
637}
638
bellardd720b932004-04-25 17:57:43 +0000639#ifdef TARGET_HAS_PRECISE_SMC
640
ths5fafdf22007-09-16 21:08:06 +0000641static void tb_gen_code(CPUState *env,
bellardd720b932004-04-25 17:57:43 +0000642 target_ulong pc, target_ulong cs_base, int flags,
643 int cflags)
644{
645 TranslationBlock *tb;
646 uint8_t *tc_ptr;
647 target_ulong phys_pc, phys_page2, virt_page2;
648 int code_gen_size;
649
bellardc27004e2005-01-03 23:35:10 +0000650 phys_pc = get_phys_addr_code(env, pc);
651 tb = tb_alloc(pc);
bellardd720b932004-04-25 17:57:43 +0000652 if (!tb) {
653 /* flush must be done */
654 tb_flush(env);
655 /* cannot fail at this point */
bellardc27004e2005-01-03 23:35:10 +0000656 tb = tb_alloc(pc);
bellardd720b932004-04-25 17:57:43 +0000657 }
658 tc_ptr = code_gen_ptr;
659 tb->tc_ptr = tc_ptr;
660 tb->cs_base = cs_base;
661 tb->flags = flags;
662 tb->cflags = cflags;
blueswir1d07bde82007-12-11 19:35:45 +0000663 cpu_gen_code(env, tb, &code_gen_size);
bellardd720b932004-04-25 17:57:43 +0000664 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 +0000665
bellardd720b932004-04-25 17:57:43 +0000666 /* check next page if needed */
bellardc27004e2005-01-03 23:35:10 +0000667 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
bellardd720b932004-04-25 17:57:43 +0000668 phys_page2 = -1;
bellardc27004e2005-01-03 23:35:10 +0000669 if ((pc & TARGET_PAGE_MASK) != virt_page2) {
bellardd720b932004-04-25 17:57:43 +0000670 phys_page2 = get_phys_addr_code(env, virt_page2);
671 }
672 tb_link_phys(tb, phys_pc, phys_page2);
673}
674#endif
ths3b46e622007-09-17 08:09:54 +0000675
bellard9fa3e852004-01-04 18:06:42 +0000676/* invalidate all TBs which intersect with the target physical page
677 starting in range [start;end[. NOTE: start and end must refer to
bellardd720b932004-04-25 17:57:43 +0000678 the same physical page. 'is_cpu_write_access' should be true if called
679 from a real cpu write access: the virtual CPU will exit the current
680 TB if code is modified inside this TB. */
aurel32967032c2008-04-22 20:37:34 +0000681void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t end,
bellardd720b932004-04-25 17:57:43 +0000682 int is_cpu_write_access)
bellard9fa3e852004-01-04 18:06:42 +0000683{
bellardd720b932004-04-25 17:57:43 +0000684 int n, current_tb_modified, current_tb_not_found, current_flags;
bellardd720b932004-04-25 17:57:43 +0000685 CPUState *env = cpu_single_env;
bellard9fa3e852004-01-04 18:06:42 +0000686 PageDesc *p;
bellardea1c1802004-06-14 18:56:36 +0000687 TranslationBlock *tb, *tb_next, *current_tb, *saved_tb;
bellard9fa3e852004-01-04 18:06:42 +0000688 target_ulong tb_start, tb_end;
bellardd720b932004-04-25 17:57:43 +0000689 target_ulong current_pc, current_cs_base;
bellard9fa3e852004-01-04 18:06:42 +0000690
691 p = page_find(start >> TARGET_PAGE_BITS);
ths5fafdf22007-09-16 21:08:06 +0000692 if (!p)
bellard9fa3e852004-01-04 18:06:42 +0000693 return;
ths5fafdf22007-09-16 21:08:06 +0000694 if (!p->code_bitmap &&
bellardd720b932004-04-25 17:57:43 +0000695 ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
696 is_cpu_write_access) {
bellard9fa3e852004-01-04 18:06:42 +0000697 /* build code bitmap */
698 build_page_bitmap(p);
699 }
700
701 /* we remove all the TBs in the range [start, end[ */
702 /* XXX: see if in some cases it could be faster to invalidate all the code */
bellardd720b932004-04-25 17:57:43 +0000703 current_tb_not_found = is_cpu_write_access;
704 current_tb_modified = 0;
705 current_tb = NULL; /* avoid warning */
706 current_pc = 0; /* avoid warning */
707 current_cs_base = 0; /* avoid warning */
708 current_flags = 0; /* avoid warning */
bellard9fa3e852004-01-04 18:06:42 +0000709 tb = p->first_tb;
710 while (tb != NULL) {
711 n = (long)tb & 3;
712 tb = (TranslationBlock *)((long)tb & ~3);
713 tb_next = tb->page_next[n];
714 /* NOTE: this is subtle as a TB may span two physical pages */
715 if (n == 0) {
716 /* NOTE: tb_end may be after the end of the page, but
717 it is not a problem */
718 tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
719 tb_end = tb_start + tb->size;
720 } else {
721 tb_start = tb->page_addr[1];
722 tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
723 }
724 if (!(tb_end <= start || tb_start >= end)) {
bellardd720b932004-04-25 17:57:43 +0000725#ifdef TARGET_HAS_PRECISE_SMC
726 if (current_tb_not_found) {
727 current_tb_not_found = 0;
728 current_tb = NULL;
729 if (env->mem_write_pc) {
730 /* now we have a real cpu fault */
731 current_tb = tb_find_pc(env->mem_write_pc);
732 }
733 }
734 if (current_tb == tb &&
735 !(current_tb->cflags & CF_SINGLE_INSN)) {
736 /* If we are modifying the current TB, we must stop
737 its execution. We could be more precise by checking
738 that the modification is after the current PC, but it
739 would require a specialized function to partially
740 restore the CPU state */
ths3b46e622007-09-17 08:09:54 +0000741
bellardd720b932004-04-25 17:57:43 +0000742 current_tb_modified = 1;
ths5fafdf22007-09-16 21:08:06 +0000743 cpu_restore_state(current_tb, env,
bellardd720b932004-04-25 17:57:43 +0000744 env->mem_write_pc, NULL);
745#if defined(TARGET_I386)
746 current_flags = env->hflags;
747 current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
748 current_cs_base = (target_ulong)env->segs[R_CS].base;
749 current_pc = current_cs_base + env->eip;
750#else
751#error unsupported CPU
752#endif
753 }
754#endif /* TARGET_HAS_PRECISE_SMC */
bellard6f5a9f72005-11-26 20:12:28 +0000755 /* we need to do that to handle the case where a signal
756 occurs while doing tb_phys_invalidate() */
757 saved_tb = NULL;
758 if (env) {
759 saved_tb = env->current_tb;
760 env->current_tb = NULL;
761 }
bellard9fa3e852004-01-04 18:06:42 +0000762 tb_phys_invalidate(tb, -1);
bellard6f5a9f72005-11-26 20:12:28 +0000763 if (env) {
764 env->current_tb = saved_tb;
765 if (env->interrupt_request && env->current_tb)
766 cpu_interrupt(env, env->interrupt_request);
767 }
bellard9fa3e852004-01-04 18:06:42 +0000768 }
769 tb = tb_next;
770 }
771#if !defined(CONFIG_USER_ONLY)
772 /* if no code remaining, no need to continue to use slow writes */
773 if (!p->first_tb) {
774 invalidate_page_bitmap(p);
bellardd720b932004-04-25 17:57:43 +0000775 if (is_cpu_write_access) {
776 tlb_unprotect_code_phys(env, start, env->mem_write_vaddr);
777 }
778 }
779#endif
780#ifdef TARGET_HAS_PRECISE_SMC
781 if (current_tb_modified) {
782 /* we generate a block containing just the instruction
783 modifying the memory. It will ensure that it cannot modify
784 itself */
bellardea1c1802004-06-14 18:56:36 +0000785 env->current_tb = NULL;
ths5fafdf22007-09-16 21:08:06 +0000786 tb_gen_code(env, current_pc, current_cs_base, current_flags,
bellardd720b932004-04-25 17:57:43 +0000787 CF_SINGLE_INSN);
788 cpu_resume_from_signal(env, NULL);
bellard9fa3e852004-01-04 18:06:42 +0000789 }
790#endif
791}
792
793/* len must be <= 8 and start must be a multiple of len */
aurel32967032c2008-04-22 20:37:34 +0000794static inline void tb_invalidate_phys_page_fast(target_phys_addr_t start, int len)
bellard9fa3e852004-01-04 18:06:42 +0000795{
796 PageDesc *p;
797 int offset, b;
bellard59817cc2004-02-16 22:01:13 +0000798#if 0
bellarda4193c82004-06-03 14:01:43 +0000799 if (1) {
800 if (loglevel) {
ths5fafdf22007-09-16 21:08:06 +0000801 fprintf(logfile, "modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
802 cpu_single_env->mem_write_vaddr, len,
803 cpu_single_env->eip,
bellarda4193c82004-06-03 14:01:43 +0000804 cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
805 }
bellard59817cc2004-02-16 22:01:13 +0000806 }
807#endif
bellard9fa3e852004-01-04 18:06:42 +0000808 p = page_find(start >> TARGET_PAGE_BITS);
ths5fafdf22007-09-16 21:08:06 +0000809 if (!p)
bellard9fa3e852004-01-04 18:06:42 +0000810 return;
811 if (p->code_bitmap) {
812 offset = start & ~TARGET_PAGE_MASK;
813 b = p->code_bitmap[offset >> 3] >> (offset & 7);
814 if (b & ((1 << len) - 1))
815 goto do_invalidate;
816 } else {
817 do_invalidate:
bellardd720b932004-04-25 17:57:43 +0000818 tb_invalidate_phys_page_range(start, start + len, 1);
bellard9fa3e852004-01-04 18:06:42 +0000819 }
820}
821
bellard9fa3e852004-01-04 18:06:42 +0000822#if !defined(CONFIG_SOFTMMU)
aurel32967032c2008-04-22 20:37:34 +0000823static void tb_invalidate_phys_page(target_phys_addr_t addr,
bellardd720b932004-04-25 17:57:43 +0000824 unsigned long pc, void *puc)
bellard9fa3e852004-01-04 18:06:42 +0000825{
bellardd720b932004-04-25 17:57:43 +0000826 int n, current_flags, current_tb_modified;
827 target_ulong current_pc, current_cs_base;
bellard9fa3e852004-01-04 18:06:42 +0000828 PageDesc *p;
bellardd720b932004-04-25 17:57:43 +0000829 TranslationBlock *tb, *current_tb;
830#ifdef TARGET_HAS_PRECISE_SMC
831 CPUState *env = cpu_single_env;
832#endif
bellard9fa3e852004-01-04 18:06:42 +0000833
834 addr &= TARGET_PAGE_MASK;
835 p = page_find(addr >> TARGET_PAGE_BITS);
ths5fafdf22007-09-16 21:08:06 +0000836 if (!p)
bellardfd6ce8f2003-05-14 19:00:11 +0000837 return;
838 tb = p->first_tb;
bellardd720b932004-04-25 17:57:43 +0000839 current_tb_modified = 0;
840 current_tb = NULL;
841 current_pc = 0; /* avoid warning */
842 current_cs_base = 0; /* avoid warning */
843 current_flags = 0; /* avoid warning */
844#ifdef TARGET_HAS_PRECISE_SMC
845 if (tb && pc != 0) {
846 current_tb = tb_find_pc(pc);
847 }
848#endif
bellardfd6ce8f2003-05-14 19:00:11 +0000849 while (tb != NULL) {
bellard9fa3e852004-01-04 18:06:42 +0000850 n = (long)tb & 3;
851 tb = (TranslationBlock *)((long)tb & ~3);
bellardd720b932004-04-25 17:57:43 +0000852#ifdef TARGET_HAS_PRECISE_SMC
853 if (current_tb == tb &&
854 !(current_tb->cflags & CF_SINGLE_INSN)) {
855 /* If we are modifying the current TB, we must stop
856 its execution. We could be more precise by checking
857 that the modification is after the current PC, but it
858 would require a specialized function to partially
859 restore the CPU state */
ths3b46e622007-09-17 08:09:54 +0000860
bellardd720b932004-04-25 17:57:43 +0000861 current_tb_modified = 1;
862 cpu_restore_state(current_tb, env, pc, puc);
863#if defined(TARGET_I386)
864 current_flags = env->hflags;
865 current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
866 current_cs_base = (target_ulong)env->segs[R_CS].base;
867 current_pc = current_cs_base + env->eip;
868#else
869#error unsupported CPU
870#endif
871 }
872#endif /* TARGET_HAS_PRECISE_SMC */
bellard9fa3e852004-01-04 18:06:42 +0000873 tb_phys_invalidate(tb, addr);
874 tb = tb->page_next[n];
bellardfd6ce8f2003-05-14 19:00:11 +0000875 }
876 p->first_tb = NULL;
bellardd720b932004-04-25 17:57:43 +0000877#ifdef TARGET_HAS_PRECISE_SMC
878 if (current_tb_modified) {
879 /* we generate a block containing just the instruction
880 modifying the memory. It will ensure that it cannot modify
881 itself */
bellardea1c1802004-06-14 18:56:36 +0000882 env->current_tb = NULL;
ths5fafdf22007-09-16 21:08:06 +0000883 tb_gen_code(env, current_pc, current_cs_base, current_flags,
bellardd720b932004-04-25 17:57:43 +0000884 CF_SINGLE_INSN);
885 cpu_resume_from_signal(env, puc);
886 }
887#endif
bellardfd6ce8f2003-05-14 19:00:11 +0000888}
bellard9fa3e852004-01-04 18:06:42 +0000889#endif
bellardfd6ce8f2003-05-14 19:00:11 +0000890
891/* add the tb in the target page and protect it if necessary */
ths5fafdf22007-09-16 21:08:06 +0000892static inline void tb_alloc_page(TranslationBlock *tb,
pbrook53a59602006-03-25 19:31:22 +0000893 unsigned int n, target_ulong page_addr)
bellardfd6ce8f2003-05-14 19:00:11 +0000894{
895 PageDesc *p;
bellard9fa3e852004-01-04 18:06:42 +0000896 TranslationBlock *last_first_tb;
bellardfd6ce8f2003-05-14 19:00:11 +0000897
bellard9fa3e852004-01-04 18:06:42 +0000898 tb->page_addr[n] = page_addr;
bellard3a7d9292005-08-21 09:26:42 +0000899 p = page_find_alloc(page_addr >> TARGET_PAGE_BITS);
bellard9fa3e852004-01-04 18:06:42 +0000900 tb->page_next[n] = p->first_tb;
901 last_first_tb = p->first_tb;
902 p->first_tb = (TranslationBlock *)((long)tb | n);
903 invalidate_page_bitmap(p);
904
bellard107db442004-06-22 18:48:46 +0000905#if defined(TARGET_HAS_SMC) || 1
bellardd720b932004-04-25 17:57:43 +0000906
bellard9fa3e852004-01-04 18:06:42 +0000907#if defined(CONFIG_USER_ONLY)
bellardfd6ce8f2003-05-14 19:00:11 +0000908 if (p->flags & PAGE_WRITE) {
pbrook53a59602006-03-25 19:31:22 +0000909 target_ulong addr;
910 PageDesc *p2;
bellard9fa3e852004-01-04 18:06:42 +0000911 int prot;
912
bellardfd6ce8f2003-05-14 19:00:11 +0000913 /* force the host page as non writable (writes will have a
914 page fault + mprotect overhead) */
pbrook53a59602006-03-25 19:31:22 +0000915 page_addr &= qemu_host_page_mask;
bellardfd6ce8f2003-05-14 19:00:11 +0000916 prot = 0;
pbrook53a59602006-03-25 19:31:22 +0000917 for(addr = page_addr; addr < page_addr + qemu_host_page_size;
918 addr += TARGET_PAGE_SIZE) {
919
920 p2 = page_find (addr >> TARGET_PAGE_BITS);
921 if (!p2)
922 continue;
923 prot |= p2->flags;
924 p2->flags &= ~PAGE_WRITE;
925 page_get_flags(addr);
926 }
ths5fafdf22007-09-16 21:08:06 +0000927 mprotect(g2h(page_addr), qemu_host_page_size,
bellardfd6ce8f2003-05-14 19:00:11 +0000928 (prot & PAGE_BITS) & ~PAGE_WRITE);
929#ifdef DEBUG_TB_INVALIDATE
blueswir1ab3d1722007-11-04 07:31:40 +0000930 printf("protecting code page: 0x" TARGET_FMT_lx "\n",
pbrook53a59602006-03-25 19:31:22 +0000931 page_addr);
bellardfd6ce8f2003-05-14 19:00:11 +0000932#endif
bellardfd6ce8f2003-05-14 19:00:11 +0000933 }
bellard9fa3e852004-01-04 18:06:42 +0000934#else
935 /* if some code is already present, then the pages are already
936 protected. So we handle the case where only the first TB is
937 allocated in a physical page */
938 if (!last_first_tb) {
bellard6a00d602005-11-21 23:25:50 +0000939 tlb_protect_code(page_addr);
bellard9fa3e852004-01-04 18:06:42 +0000940 }
941#endif
bellardd720b932004-04-25 17:57:43 +0000942
943#endif /* TARGET_HAS_SMC */
bellardfd6ce8f2003-05-14 19:00:11 +0000944}
945
946/* Allocate a new translation block. Flush the translation buffer if
947 too many translation blocks or too much generated code. */
bellardc27004e2005-01-03 23:35:10 +0000948TranslationBlock *tb_alloc(target_ulong pc)
bellardfd6ce8f2003-05-14 19:00:11 +0000949{
950 TranslationBlock *tb;
bellardfd6ce8f2003-05-14 19:00:11 +0000951
ths5fafdf22007-09-16 21:08:06 +0000952 if (nb_tbs >= CODE_GEN_MAX_BLOCKS ||
bellardfd6ce8f2003-05-14 19:00:11 +0000953 (code_gen_ptr - code_gen_buffer) >= CODE_GEN_BUFFER_MAX_SIZE)
bellardd4e81642003-05-25 16:46:15 +0000954 return NULL;
bellardfd6ce8f2003-05-14 19:00:11 +0000955 tb = &tbs[nb_tbs++];
956 tb->pc = pc;
bellardb448f2f2004-02-25 23:24:04 +0000957 tb->cflags = 0;
bellardd4e81642003-05-25 16:46:15 +0000958 return tb;
959}
960
bellard9fa3e852004-01-04 18:06:42 +0000961/* add a new TB and link it to the physical page tables. phys_page2 is
962 (-1) to indicate that only one page contains the TB. */
ths5fafdf22007-09-16 21:08:06 +0000963void tb_link_phys(TranslationBlock *tb,
bellard9fa3e852004-01-04 18:06:42 +0000964 target_ulong phys_pc, target_ulong phys_page2)
bellardd4e81642003-05-25 16:46:15 +0000965{
bellard9fa3e852004-01-04 18:06:42 +0000966 unsigned int h;
967 TranslationBlock **ptb;
968
969 /* add in the physical hash table */
970 h = tb_phys_hash_func(phys_pc);
971 ptb = &tb_phys_hash[h];
972 tb->phys_hash_next = *ptb;
973 *ptb = tb;
bellardfd6ce8f2003-05-14 19:00:11 +0000974
975 /* add in the page list */
bellard9fa3e852004-01-04 18:06:42 +0000976 tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK);
977 if (phys_page2 != -1)
978 tb_alloc_page(tb, 1, phys_page2);
979 else
980 tb->page_addr[1] = -1;
bellard9fa3e852004-01-04 18:06:42 +0000981
bellardd4e81642003-05-25 16:46:15 +0000982 tb->jmp_first = (TranslationBlock *)((long)tb | 2);
983 tb->jmp_next[0] = NULL;
984 tb->jmp_next[1] = NULL;
985
986 /* init original jump addresses */
987 if (tb->tb_next_offset[0] != 0xffff)
988 tb_reset_jump(tb, 0);
989 if (tb->tb_next_offset[1] != 0xffff)
990 tb_reset_jump(tb, 1);
bellard8a40a182005-11-20 10:35:40 +0000991
992#ifdef DEBUG_TB_CHECK
993 tb_page_check();
994#endif
bellardfd6ce8f2003-05-14 19:00:11 +0000995}
996
bellarda513fe12003-05-27 23:29:48 +0000997/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
998 tb[1].tc_ptr. Return NULL if not found */
999TranslationBlock *tb_find_pc(unsigned long tc_ptr)
1000{
1001 int m_min, m_max, m;
1002 unsigned long v;
1003 TranslationBlock *tb;
1004
1005 if (nb_tbs <= 0)
1006 return NULL;
1007 if (tc_ptr < (unsigned long)code_gen_buffer ||
1008 tc_ptr >= (unsigned long)code_gen_ptr)
1009 return NULL;
1010 /* binary search (cf Knuth) */
1011 m_min = 0;
1012 m_max = nb_tbs - 1;
1013 while (m_min <= m_max) {
1014 m = (m_min + m_max) >> 1;
1015 tb = &tbs[m];
1016 v = (unsigned long)tb->tc_ptr;
1017 if (v == tc_ptr)
1018 return tb;
1019 else if (tc_ptr < v) {
1020 m_max = m - 1;
1021 } else {
1022 m_min = m + 1;
1023 }
ths5fafdf22007-09-16 21:08:06 +00001024 }
bellarda513fe12003-05-27 23:29:48 +00001025 return &tbs[m_max];
1026}
bellard75012672003-06-21 13:11:07 +00001027
bellardea041c02003-06-25 16:16:50 +00001028static void tb_reset_jump_recursive(TranslationBlock *tb);
1029
1030static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
1031{
1032 TranslationBlock *tb1, *tb_next, **ptb;
1033 unsigned int n1;
1034
1035 tb1 = tb->jmp_next[n];
1036 if (tb1 != NULL) {
1037 /* find head of list */
1038 for(;;) {
1039 n1 = (long)tb1 & 3;
1040 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1041 if (n1 == 2)
1042 break;
1043 tb1 = tb1->jmp_next[n1];
1044 }
1045 /* we are now sure now that tb jumps to tb1 */
1046 tb_next = tb1;
1047
1048 /* remove tb from the jmp_first list */
1049 ptb = &tb_next->jmp_first;
1050 for(;;) {
1051 tb1 = *ptb;
1052 n1 = (long)tb1 & 3;
1053 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1054 if (n1 == n && tb1 == tb)
1055 break;
1056 ptb = &tb1->jmp_next[n1];
1057 }
1058 *ptb = tb->jmp_next[n];
1059 tb->jmp_next[n] = NULL;
ths3b46e622007-09-17 08:09:54 +00001060
bellardea041c02003-06-25 16:16:50 +00001061 /* suppress the jump to next tb in generated code */
1062 tb_reset_jump(tb, n);
1063
bellard01243112004-01-04 15:48:17 +00001064 /* suppress jumps in the tb on which we could have jumped */
bellardea041c02003-06-25 16:16:50 +00001065 tb_reset_jump_recursive(tb_next);
1066 }
1067}
1068
1069static void tb_reset_jump_recursive(TranslationBlock *tb)
1070{
1071 tb_reset_jump_recursive2(tb, 0);
1072 tb_reset_jump_recursive2(tb, 1);
1073}
1074
bellard1fddef42005-04-17 19:16:13 +00001075#if defined(TARGET_HAS_ICE)
bellardd720b932004-04-25 17:57:43 +00001076static void breakpoint_invalidate(CPUState *env, target_ulong pc)
1077{
j_mayer9b3c35e2007-04-07 11:21:28 +00001078 target_phys_addr_t addr;
1079 target_ulong pd;
pbrookc2f07f82006-04-08 17:14:56 +00001080 ram_addr_t ram_addr;
1081 PhysPageDesc *p;
bellardd720b932004-04-25 17:57:43 +00001082
pbrookc2f07f82006-04-08 17:14:56 +00001083 addr = cpu_get_phys_page_debug(env, pc);
1084 p = phys_page_find(addr >> TARGET_PAGE_BITS);
1085 if (!p) {
1086 pd = IO_MEM_UNASSIGNED;
1087 } else {
1088 pd = p->phys_offset;
1089 }
1090 ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
pbrook706cd4b2006-04-08 17:36:21 +00001091 tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
bellardd720b932004-04-25 17:57:43 +00001092}
bellardc27004e2005-01-03 23:35:10 +00001093#endif
bellardd720b932004-04-25 17:57:43 +00001094
pbrook6658ffb2007-03-16 23:58:11 +00001095/* Add a watchpoint. */
1096int cpu_watchpoint_insert(CPUState *env, target_ulong addr)
1097{
1098 int i;
1099
1100 for (i = 0; i < env->nb_watchpoints; i++) {
1101 if (addr == env->watchpoint[i].vaddr)
1102 return 0;
1103 }
1104 if (env->nb_watchpoints >= MAX_WATCHPOINTS)
1105 return -1;
1106
1107 i = env->nb_watchpoints++;
1108 env->watchpoint[i].vaddr = addr;
1109 tlb_flush_page(env, addr);
1110 /* FIXME: This flush is needed because of the hack to make memory ops
1111 terminate the TB. It can be removed once the proper IO trap and
1112 re-execute bits are in. */
1113 tb_flush(env);
1114 return i;
1115}
1116
1117/* Remove a watchpoint. */
1118int cpu_watchpoint_remove(CPUState *env, target_ulong addr)
1119{
1120 int i;
1121
1122 for (i = 0; i < env->nb_watchpoints; i++) {
1123 if (addr == env->watchpoint[i].vaddr) {
1124 env->nb_watchpoints--;
1125 env->watchpoint[i] = env->watchpoint[env->nb_watchpoints];
1126 tlb_flush_page(env, addr);
1127 return 0;
1128 }
1129 }
1130 return -1;
1131}
1132
bellardc33a3462003-07-29 20:50:33 +00001133/* add a breakpoint. EXCP_DEBUG is returned by the CPU loop if a
1134 breakpoint is reached */
bellard2e126692004-04-25 21:28:44 +00001135int cpu_breakpoint_insert(CPUState *env, target_ulong pc)
bellard4c3a88a2003-07-26 12:06:08 +00001136{
bellard1fddef42005-04-17 19:16:13 +00001137#if defined(TARGET_HAS_ICE)
bellard4c3a88a2003-07-26 12:06:08 +00001138 int i;
ths3b46e622007-09-17 08:09:54 +00001139
bellard4c3a88a2003-07-26 12:06:08 +00001140 for(i = 0; i < env->nb_breakpoints; i++) {
1141 if (env->breakpoints[i] == pc)
1142 return 0;
1143 }
1144
1145 if (env->nb_breakpoints >= MAX_BREAKPOINTS)
1146 return -1;
1147 env->breakpoints[env->nb_breakpoints++] = pc;
ths3b46e622007-09-17 08:09:54 +00001148
bellardd720b932004-04-25 17:57:43 +00001149 breakpoint_invalidate(env, pc);
bellard4c3a88a2003-07-26 12:06:08 +00001150 return 0;
1151#else
1152 return -1;
1153#endif
1154}
1155
1156/* remove a breakpoint */
bellard2e126692004-04-25 21:28:44 +00001157int cpu_breakpoint_remove(CPUState *env, target_ulong pc)
bellard4c3a88a2003-07-26 12:06:08 +00001158{
bellard1fddef42005-04-17 19:16:13 +00001159#if defined(TARGET_HAS_ICE)
bellard4c3a88a2003-07-26 12:06:08 +00001160 int i;
1161 for(i = 0; i < env->nb_breakpoints; i++) {
1162 if (env->breakpoints[i] == pc)
1163 goto found;
1164 }
1165 return -1;
1166 found:
bellard4c3a88a2003-07-26 12:06:08 +00001167 env->nb_breakpoints--;
bellard1fddef42005-04-17 19:16:13 +00001168 if (i < env->nb_breakpoints)
1169 env->breakpoints[i] = env->breakpoints[env->nb_breakpoints];
bellardd720b932004-04-25 17:57:43 +00001170
1171 breakpoint_invalidate(env, pc);
bellard4c3a88a2003-07-26 12:06:08 +00001172 return 0;
1173#else
1174 return -1;
1175#endif
1176}
1177
bellardc33a3462003-07-29 20:50:33 +00001178/* enable or disable single step mode. EXCP_DEBUG is returned by the
1179 CPU loop after each instruction */
1180void cpu_single_step(CPUState *env, int enabled)
1181{
bellard1fddef42005-04-17 19:16:13 +00001182#if defined(TARGET_HAS_ICE)
bellardc33a3462003-07-29 20:50:33 +00001183 if (env->singlestep_enabled != enabled) {
1184 env->singlestep_enabled = enabled;
1185 /* must flush all the translated code to avoid inconsistancies */
bellard9fa3e852004-01-04 18:06:42 +00001186 /* XXX: only flush what is necessary */
bellard01243112004-01-04 15:48:17 +00001187 tb_flush(env);
bellardc33a3462003-07-29 20:50:33 +00001188 }
1189#endif
1190}
1191
bellard34865132003-10-05 14:28:56 +00001192/* enable or disable low levels log */
1193void cpu_set_log(int log_flags)
1194{
1195 loglevel = log_flags;
1196 if (loglevel && !logfile) {
pbrook11fcfab2007-07-01 18:21:11 +00001197 logfile = fopen(logfilename, log_append ? "a" : "w");
bellard34865132003-10-05 14:28:56 +00001198 if (!logfile) {
1199 perror(logfilename);
1200 _exit(1);
1201 }
bellard9fa3e852004-01-04 18:06:42 +00001202#if !defined(CONFIG_SOFTMMU)
1203 /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1204 {
1205 static uint8_t logfile_buf[4096];
1206 setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1207 }
1208#else
bellard34865132003-10-05 14:28:56 +00001209 setvbuf(logfile, NULL, _IOLBF, 0);
bellard9fa3e852004-01-04 18:06:42 +00001210#endif
pbrooke735b912007-06-30 13:53:24 +00001211 log_append = 1;
1212 }
1213 if (!loglevel && logfile) {
1214 fclose(logfile);
1215 logfile = NULL;
bellard34865132003-10-05 14:28:56 +00001216 }
1217}
1218
1219void cpu_set_log_filename(const char *filename)
1220{
1221 logfilename = strdup(filename);
pbrooke735b912007-06-30 13:53:24 +00001222 if (logfile) {
1223 fclose(logfile);
1224 logfile = NULL;
1225 }
1226 cpu_set_log(loglevel);
bellard34865132003-10-05 14:28:56 +00001227}
bellardc33a3462003-07-29 20:50:33 +00001228
bellard01243112004-01-04 15:48:17 +00001229/* mask must never be zero, except for A20 change call */
bellard68a79312003-06-30 13:12:32 +00001230void cpu_interrupt(CPUState *env, int mask)
bellardea041c02003-06-25 16:16:50 +00001231{
1232 TranslationBlock *tb;
aurel3215a51152008-03-28 22:29:15 +00001233 static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
bellard59817cc2004-02-16 22:01:13 +00001234
bellard68a79312003-06-30 13:12:32 +00001235 env->interrupt_request |= mask;
bellardea041c02003-06-25 16:16:50 +00001236 /* if the cpu is currently executing code, we must unlink it and
1237 all the potentially executing TB */
1238 tb = env->current_tb;
bellardee8b7022004-02-03 23:35:10 +00001239 if (tb && !testandset(&interrupt_lock)) {
1240 env->current_tb = NULL;
bellardea041c02003-06-25 16:16:50 +00001241 tb_reset_jump_recursive(tb);
aurel3215a51152008-03-28 22:29:15 +00001242 resetlock(&interrupt_lock);
bellardea041c02003-06-25 16:16:50 +00001243 }
1244}
1245
bellardb54ad042004-05-20 13:42:52 +00001246void cpu_reset_interrupt(CPUState *env, int mask)
1247{
1248 env->interrupt_request &= ~mask;
1249}
1250
bellardf193c792004-03-21 17:06:25 +00001251CPULogItem cpu_log_items[] = {
ths5fafdf22007-09-16 21:08:06 +00001252 { CPU_LOG_TB_OUT_ASM, "out_asm",
bellardf193c792004-03-21 17:06:25 +00001253 "show generated host assembly code for each compiled TB" },
1254 { CPU_LOG_TB_IN_ASM, "in_asm",
1255 "show target assembly code for each compiled TB" },
ths5fafdf22007-09-16 21:08:06 +00001256 { CPU_LOG_TB_OP, "op",
bellard57fec1f2008-02-01 10:50:11 +00001257 "show micro ops for each compiled TB" },
bellardf193c792004-03-21 17:06:25 +00001258 { CPU_LOG_TB_OP_OPT, "op_opt",
blueswir1e01a1152008-03-14 17:37:11 +00001259 "show micro ops "
1260#ifdef TARGET_I386
1261 "before eflags optimization and "
bellardf193c792004-03-21 17:06:25 +00001262#endif
blueswir1e01a1152008-03-14 17:37:11 +00001263 "after liveness analysis" },
bellardf193c792004-03-21 17:06:25 +00001264 { CPU_LOG_INT, "int",
1265 "show interrupts/exceptions in short format" },
1266 { CPU_LOG_EXEC, "exec",
1267 "show trace before each executed TB (lots of logs)" },
bellard9fddaa02004-05-21 12:59:32 +00001268 { CPU_LOG_TB_CPU, "cpu",
thse91c8a72007-06-03 13:35:16 +00001269 "show CPU state before block translation" },
bellardf193c792004-03-21 17:06:25 +00001270#ifdef TARGET_I386
1271 { CPU_LOG_PCALL, "pcall",
1272 "show protected mode far calls/returns/exceptions" },
1273#endif
bellard8e3a9fd2004-10-09 17:32:58 +00001274#ifdef DEBUG_IOPORT
bellardfd872592004-05-12 19:11:15 +00001275 { CPU_LOG_IOPORT, "ioport",
1276 "show all i/o ports accesses" },
bellard8e3a9fd2004-10-09 17:32:58 +00001277#endif
bellardf193c792004-03-21 17:06:25 +00001278 { 0, NULL, NULL },
1279};
1280
1281static int cmp1(const char *s1, int n, const char *s2)
1282{
1283 if (strlen(s2) != n)
1284 return 0;
1285 return memcmp(s1, s2, n) == 0;
1286}
ths3b46e622007-09-17 08:09:54 +00001287
bellardf193c792004-03-21 17:06:25 +00001288/* takes a comma separated list of log masks. Return 0 if error. */
1289int cpu_str_to_log_mask(const char *str)
1290{
1291 CPULogItem *item;
1292 int mask;
1293 const char *p, *p1;
1294
1295 p = str;
1296 mask = 0;
1297 for(;;) {
1298 p1 = strchr(p, ',');
1299 if (!p1)
1300 p1 = p + strlen(p);
bellard8e3a9fd2004-10-09 17:32:58 +00001301 if(cmp1(p,p1-p,"all")) {
1302 for(item = cpu_log_items; item->mask != 0; item++) {
1303 mask |= item->mask;
1304 }
1305 } else {
bellardf193c792004-03-21 17:06:25 +00001306 for(item = cpu_log_items; item->mask != 0; item++) {
1307 if (cmp1(p, p1 - p, item->name))
1308 goto found;
1309 }
1310 return 0;
bellard8e3a9fd2004-10-09 17:32:58 +00001311 }
bellardf193c792004-03-21 17:06:25 +00001312 found:
1313 mask |= item->mask;
1314 if (*p1 != ',')
1315 break;
1316 p = p1 + 1;
1317 }
1318 return mask;
1319}
bellardea041c02003-06-25 16:16:50 +00001320
bellard75012672003-06-21 13:11:07 +00001321void cpu_abort(CPUState *env, const char *fmt, ...)
1322{
1323 va_list ap;
pbrook493ae1f2007-11-23 16:53:59 +00001324 va_list ap2;
bellard75012672003-06-21 13:11:07 +00001325
1326 va_start(ap, fmt);
pbrook493ae1f2007-11-23 16:53:59 +00001327 va_copy(ap2, ap);
bellard75012672003-06-21 13:11:07 +00001328 fprintf(stderr, "qemu: fatal: ");
1329 vfprintf(stderr, fmt, ap);
1330 fprintf(stderr, "\n");
1331#ifdef TARGET_I386
ths0573fbf2007-09-23 15:28:04 +00001332 if(env->intercept & INTERCEPT_SVM_MASK) {
1333 /* most probably the virtual machine should not
1334 be shut down but rather caught by the VMM */
1335 vmexit(SVM_EXIT_SHUTDOWN, 0);
1336 }
bellard7fe48482004-10-09 18:08:01 +00001337 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1338#else
1339 cpu_dump_state(env, stderr, fprintf, 0);
bellard75012672003-06-21 13:11:07 +00001340#endif
balrog924edca2007-06-10 14:07:13 +00001341 if (logfile) {
j_mayerf9373292007-09-29 12:18:20 +00001342 fprintf(logfile, "qemu: fatal: ");
pbrook493ae1f2007-11-23 16:53:59 +00001343 vfprintf(logfile, fmt, ap2);
j_mayerf9373292007-09-29 12:18:20 +00001344 fprintf(logfile, "\n");
1345#ifdef TARGET_I386
1346 cpu_dump_state(env, logfile, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1347#else
1348 cpu_dump_state(env, logfile, fprintf, 0);
1349#endif
balrog924edca2007-06-10 14:07:13 +00001350 fflush(logfile);
1351 fclose(logfile);
1352 }
pbrook493ae1f2007-11-23 16:53:59 +00001353 va_end(ap2);
j_mayerf9373292007-09-29 12:18:20 +00001354 va_end(ap);
bellard75012672003-06-21 13:11:07 +00001355 abort();
1356}
1357
thsc5be9f02007-02-28 20:20:53 +00001358CPUState *cpu_copy(CPUState *env)
1359{
ths01ba9812007-12-09 02:22:57 +00001360 CPUState *new_env = cpu_init(env->cpu_model_str);
thsc5be9f02007-02-28 20:20:53 +00001361 /* preserve chaining and index */
1362 CPUState *next_cpu = new_env->next_cpu;
1363 int cpu_index = new_env->cpu_index;
1364 memcpy(new_env, env, sizeof(CPUState));
1365 new_env->next_cpu = next_cpu;
1366 new_env->cpu_index = cpu_index;
1367 return new_env;
1368}
1369
bellard01243112004-01-04 15:48:17 +00001370#if !defined(CONFIG_USER_ONLY)
1371
bellardee8b7022004-02-03 23:35:10 +00001372/* NOTE: if flush_global is true, also flush global entries (not
1373 implemented yet) */
1374void tlb_flush(CPUState *env, int flush_global)
bellard33417e72003-08-10 21:47:01 +00001375{
bellard33417e72003-08-10 21:47:01 +00001376 int i;
bellard01243112004-01-04 15:48:17 +00001377
bellard9fa3e852004-01-04 18:06:42 +00001378#if defined(DEBUG_TLB)
1379 printf("tlb_flush:\n");
1380#endif
bellard01243112004-01-04 15:48:17 +00001381 /* must reset current TB so that interrupts cannot modify the
1382 links while we are modifying them */
1383 env->current_tb = NULL;
1384
bellard33417e72003-08-10 21:47:01 +00001385 for(i = 0; i < CPU_TLB_SIZE; i++) {
bellard84b7b8e2005-11-28 21:19:04 +00001386 env->tlb_table[0][i].addr_read = -1;
1387 env->tlb_table[0][i].addr_write = -1;
1388 env->tlb_table[0][i].addr_code = -1;
1389 env->tlb_table[1][i].addr_read = -1;
1390 env->tlb_table[1][i].addr_write = -1;
1391 env->tlb_table[1][i].addr_code = -1;
j_mayer6fa4cea2007-04-05 06:43:27 +00001392#if (NB_MMU_MODES >= 3)
1393 env->tlb_table[2][i].addr_read = -1;
1394 env->tlb_table[2][i].addr_write = -1;
1395 env->tlb_table[2][i].addr_code = -1;
1396#if (NB_MMU_MODES == 4)
1397 env->tlb_table[3][i].addr_read = -1;
1398 env->tlb_table[3][i].addr_write = -1;
1399 env->tlb_table[3][i].addr_code = -1;
1400#endif
1401#endif
bellard33417e72003-08-10 21:47:01 +00001402 }
bellard9fa3e852004-01-04 18:06:42 +00001403
bellard8a40a182005-11-20 10:35:40 +00001404 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
bellard9fa3e852004-01-04 18:06:42 +00001405
1406#if !defined(CONFIG_SOFTMMU)
1407 munmap((void *)MMAP_AREA_START, MMAP_AREA_END - MMAP_AREA_START);
1408#endif
bellard0a962c02005-02-10 22:00:27 +00001409#ifdef USE_KQEMU
1410 if (env->kqemu_enabled) {
1411 kqemu_flush(env, flush_global);
1412 }
1413#endif
bellarde3db7222005-01-26 22:00:47 +00001414 tlb_flush_count++;
bellard33417e72003-08-10 21:47:01 +00001415}
1416
bellard274da6b2004-05-20 21:56:27 +00001417static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
bellard61382a52003-10-27 21:22:23 +00001418{
ths5fafdf22007-09-16 21:08:06 +00001419 if (addr == (tlb_entry->addr_read &
bellard84b7b8e2005-11-28 21:19:04 +00001420 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
ths5fafdf22007-09-16 21:08:06 +00001421 addr == (tlb_entry->addr_write &
bellard84b7b8e2005-11-28 21:19:04 +00001422 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
ths5fafdf22007-09-16 21:08:06 +00001423 addr == (tlb_entry->addr_code &
bellard84b7b8e2005-11-28 21:19:04 +00001424 (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1425 tlb_entry->addr_read = -1;
1426 tlb_entry->addr_write = -1;
1427 tlb_entry->addr_code = -1;
1428 }
bellard61382a52003-10-27 21:22:23 +00001429}
1430
bellard2e126692004-04-25 21:28:44 +00001431void tlb_flush_page(CPUState *env, target_ulong addr)
bellard33417e72003-08-10 21:47:01 +00001432{
bellard8a40a182005-11-20 10:35:40 +00001433 int i;
bellard9fa3e852004-01-04 18:06:42 +00001434 TranslationBlock *tb;
bellard01243112004-01-04 15:48:17 +00001435
bellard9fa3e852004-01-04 18:06:42 +00001436#if defined(DEBUG_TLB)
bellard108c49b2005-07-24 12:55:09 +00001437 printf("tlb_flush_page: " TARGET_FMT_lx "\n", addr);
bellard9fa3e852004-01-04 18:06:42 +00001438#endif
bellard01243112004-01-04 15:48:17 +00001439 /* must reset current TB so that interrupts cannot modify the
1440 links while we are modifying them */
1441 env->current_tb = NULL;
bellard33417e72003-08-10 21:47:01 +00001442
bellard61382a52003-10-27 21:22:23 +00001443 addr &= TARGET_PAGE_MASK;
bellard33417e72003-08-10 21:47:01 +00001444 i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
bellard84b7b8e2005-11-28 21:19:04 +00001445 tlb_flush_entry(&env->tlb_table[0][i], addr);
1446 tlb_flush_entry(&env->tlb_table[1][i], addr);
j_mayer6fa4cea2007-04-05 06:43:27 +00001447#if (NB_MMU_MODES >= 3)
1448 tlb_flush_entry(&env->tlb_table[2][i], addr);
1449#if (NB_MMU_MODES == 4)
1450 tlb_flush_entry(&env->tlb_table[3][i], addr);
1451#endif
1452#endif
bellard01243112004-01-04 15:48:17 +00001453
pbrookb362e5e2006-11-12 20:40:55 +00001454 /* Discard jump cache entries for any tb which might potentially
1455 overlap the flushed page. */
1456 i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
1457 memset (&env->tb_jmp_cache[i], 0, TB_JMP_PAGE_SIZE * sizeof(tb));
1458
1459 i = tb_jmp_cache_hash_page(addr);
1460 memset (&env->tb_jmp_cache[i], 0, TB_JMP_PAGE_SIZE * sizeof(tb));
bellard9fa3e852004-01-04 18:06:42 +00001461
bellard01243112004-01-04 15:48:17 +00001462#if !defined(CONFIG_SOFTMMU)
bellard9fa3e852004-01-04 18:06:42 +00001463 if (addr < MMAP_AREA_END)
bellard01243112004-01-04 15:48:17 +00001464 munmap((void *)addr, TARGET_PAGE_SIZE);
bellard61382a52003-10-27 21:22:23 +00001465#endif
bellard0a962c02005-02-10 22:00:27 +00001466#ifdef USE_KQEMU
1467 if (env->kqemu_enabled) {
1468 kqemu_flush_page(env, addr);
1469 }
1470#endif
bellard9fa3e852004-01-04 18:06:42 +00001471}
1472
bellard9fa3e852004-01-04 18:06:42 +00001473/* update the TLBs so that writes to code in the virtual page 'addr'
1474 can be detected */
bellard6a00d602005-11-21 23:25:50 +00001475static void tlb_protect_code(ram_addr_t ram_addr)
bellard61382a52003-10-27 21:22:23 +00001476{
ths5fafdf22007-09-16 21:08:06 +00001477 cpu_physical_memory_reset_dirty(ram_addr,
bellard6a00d602005-11-21 23:25:50 +00001478 ram_addr + TARGET_PAGE_SIZE,
1479 CODE_DIRTY_FLAG);
bellard9fa3e852004-01-04 18:06:42 +00001480}
1481
bellard9fa3e852004-01-04 18:06:42 +00001482/* update the TLB so that writes in physical page 'phys_addr' are no longer
bellard3a7d9292005-08-21 09:26:42 +00001483 tested for self modifying code */
ths5fafdf22007-09-16 21:08:06 +00001484static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
bellard3a7d9292005-08-21 09:26:42 +00001485 target_ulong vaddr)
bellard9fa3e852004-01-04 18:06:42 +00001486{
bellard3a7d9292005-08-21 09:26:42 +00001487 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] |= CODE_DIRTY_FLAG;
bellard1ccde1c2004-02-06 19:46:14 +00001488}
1489
ths5fafdf22007-09-16 21:08:06 +00001490static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
bellard1ccde1c2004-02-06 19:46:14 +00001491 unsigned long start, unsigned long length)
1492{
1493 unsigned long addr;
bellard84b7b8e2005-11-28 21:19:04 +00001494 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1495 addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
bellard1ccde1c2004-02-06 19:46:14 +00001496 if ((addr - start) < length) {
bellard84b7b8e2005-11-28 21:19:04 +00001497 tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | IO_MEM_NOTDIRTY;
bellard1ccde1c2004-02-06 19:46:14 +00001498 }
1499 }
1500}
1501
bellard3a7d9292005-08-21 09:26:42 +00001502void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
bellard0a962c02005-02-10 22:00:27 +00001503 int dirty_flags)
bellard1ccde1c2004-02-06 19:46:14 +00001504{
1505 CPUState *env;
bellard4f2ac232004-04-26 19:44:02 +00001506 unsigned long length, start1;
bellard0a962c02005-02-10 22:00:27 +00001507 int i, mask, len;
1508 uint8_t *p;
bellard1ccde1c2004-02-06 19:46:14 +00001509
1510 start &= TARGET_PAGE_MASK;
1511 end = TARGET_PAGE_ALIGN(end);
1512
1513 length = end - start;
1514 if (length == 0)
1515 return;
bellard0a962c02005-02-10 22:00:27 +00001516 len = length >> TARGET_PAGE_BITS;
bellard3a7d9292005-08-21 09:26:42 +00001517#ifdef USE_KQEMU
bellard6a00d602005-11-21 23:25:50 +00001518 /* XXX: should not depend on cpu context */
1519 env = first_cpu;
bellard3a7d9292005-08-21 09:26:42 +00001520 if (env->kqemu_enabled) {
bellardf23db162005-08-21 19:12:28 +00001521 ram_addr_t addr;
1522 addr = start;
1523 for(i = 0; i < len; i++) {
1524 kqemu_set_notdirty(env, addr);
1525 addr += TARGET_PAGE_SIZE;
1526 }
bellard3a7d9292005-08-21 09:26:42 +00001527 }
1528#endif
bellardf23db162005-08-21 19:12:28 +00001529 mask = ~dirty_flags;
1530 p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
1531 for(i = 0; i < len; i++)
1532 p[i] &= mask;
1533
bellard1ccde1c2004-02-06 19:46:14 +00001534 /* we modify the TLB cache so that the dirty bit will be set again
1535 when accessing the range */
bellard59817cc2004-02-16 22:01:13 +00001536 start1 = start + (unsigned long)phys_ram_base;
bellard6a00d602005-11-21 23:25:50 +00001537 for(env = first_cpu; env != NULL; env = env->next_cpu) {
1538 for(i = 0; i < CPU_TLB_SIZE; i++)
bellard84b7b8e2005-11-28 21:19:04 +00001539 tlb_reset_dirty_range(&env->tlb_table[0][i], start1, length);
bellard6a00d602005-11-21 23:25:50 +00001540 for(i = 0; i < CPU_TLB_SIZE; i++)
bellard84b7b8e2005-11-28 21:19:04 +00001541 tlb_reset_dirty_range(&env->tlb_table[1][i], start1, length);
j_mayer6fa4cea2007-04-05 06:43:27 +00001542#if (NB_MMU_MODES >= 3)
1543 for(i = 0; i < CPU_TLB_SIZE; i++)
1544 tlb_reset_dirty_range(&env->tlb_table[2][i], start1, length);
1545#if (NB_MMU_MODES == 4)
1546 for(i = 0; i < CPU_TLB_SIZE; i++)
1547 tlb_reset_dirty_range(&env->tlb_table[3][i], start1, length);
1548#endif
1549#endif
bellard6a00d602005-11-21 23:25:50 +00001550 }
bellard59817cc2004-02-16 22:01:13 +00001551
1552#if !defined(CONFIG_SOFTMMU)
1553 /* XXX: this is expensive */
1554 {
1555 VirtPageDesc *p;
1556 int j;
1557 target_ulong addr;
1558
1559 for(i = 0; i < L1_SIZE; i++) {
1560 p = l1_virt_map[i];
1561 if (p) {
1562 addr = i << (TARGET_PAGE_BITS + L2_BITS);
1563 for(j = 0; j < L2_SIZE; j++) {
1564 if (p->valid_tag == virt_valid_tag &&
1565 p->phys_addr >= start && p->phys_addr < end &&
1566 (p->prot & PROT_WRITE)) {
1567 if (addr < MMAP_AREA_END) {
ths5fafdf22007-09-16 21:08:06 +00001568 mprotect((void *)addr, TARGET_PAGE_SIZE,
bellard59817cc2004-02-16 22:01:13 +00001569 p->prot & ~PROT_WRITE);
1570 }
1571 }
1572 addr += TARGET_PAGE_SIZE;
1573 p++;
1574 }
1575 }
1576 }
1577 }
1578#endif
bellard1ccde1c2004-02-06 19:46:14 +00001579}
1580
bellard3a7d9292005-08-21 09:26:42 +00001581static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1582{
1583 ram_addr_t ram_addr;
1584
bellard84b7b8e2005-11-28 21:19:04 +00001585 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
ths5fafdf22007-09-16 21:08:06 +00001586 ram_addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) +
bellard3a7d9292005-08-21 09:26:42 +00001587 tlb_entry->addend - (unsigned long)phys_ram_base;
1588 if (!cpu_physical_memory_is_dirty(ram_addr)) {
bellard84b7b8e2005-11-28 21:19:04 +00001589 tlb_entry->addr_write |= IO_MEM_NOTDIRTY;
bellard3a7d9292005-08-21 09:26:42 +00001590 }
1591 }
1592}
1593
1594/* update the TLB according to the current state of the dirty bits */
1595void cpu_tlb_update_dirty(CPUState *env)
1596{
1597 int i;
1598 for(i = 0; i < CPU_TLB_SIZE; i++)
bellard84b7b8e2005-11-28 21:19:04 +00001599 tlb_update_dirty(&env->tlb_table[0][i]);
bellard3a7d9292005-08-21 09:26:42 +00001600 for(i = 0; i < CPU_TLB_SIZE; i++)
bellard84b7b8e2005-11-28 21:19:04 +00001601 tlb_update_dirty(&env->tlb_table[1][i]);
j_mayer6fa4cea2007-04-05 06:43:27 +00001602#if (NB_MMU_MODES >= 3)
1603 for(i = 0; i < CPU_TLB_SIZE; i++)
1604 tlb_update_dirty(&env->tlb_table[2][i]);
1605#if (NB_MMU_MODES == 4)
1606 for(i = 0; i < CPU_TLB_SIZE; i++)
1607 tlb_update_dirty(&env->tlb_table[3][i]);
1608#endif
1609#endif
bellard3a7d9292005-08-21 09:26:42 +00001610}
1611
ths5fafdf22007-09-16 21:08:06 +00001612static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry,
bellard108c49b2005-07-24 12:55:09 +00001613 unsigned long start)
bellard1ccde1c2004-02-06 19:46:14 +00001614{
1615 unsigned long addr;
bellard84b7b8e2005-11-28 21:19:04 +00001616 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_NOTDIRTY) {
1617 addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
bellard1ccde1c2004-02-06 19:46:14 +00001618 if (addr == start) {
bellard84b7b8e2005-11-28 21:19:04 +00001619 tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | IO_MEM_RAM;
bellard1ccde1c2004-02-06 19:46:14 +00001620 }
1621 }
1622}
1623
1624/* update the TLB corresponding to virtual page vaddr and phys addr
1625 addr so that it is no longer dirty */
bellard6a00d602005-11-21 23:25:50 +00001626static inline void tlb_set_dirty(CPUState *env,
1627 unsigned long addr, target_ulong vaddr)
bellard1ccde1c2004-02-06 19:46:14 +00001628{
bellard1ccde1c2004-02-06 19:46:14 +00001629 int i;
1630
bellard1ccde1c2004-02-06 19:46:14 +00001631 addr &= TARGET_PAGE_MASK;
1632 i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
bellard84b7b8e2005-11-28 21:19:04 +00001633 tlb_set_dirty1(&env->tlb_table[0][i], addr);
1634 tlb_set_dirty1(&env->tlb_table[1][i], addr);
j_mayer6fa4cea2007-04-05 06:43:27 +00001635#if (NB_MMU_MODES >= 3)
1636 tlb_set_dirty1(&env->tlb_table[2][i], addr);
1637#if (NB_MMU_MODES == 4)
1638 tlb_set_dirty1(&env->tlb_table[3][i], addr);
1639#endif
1640#endif
bellard9fa3e852004-01-04 18:06:42 +00001641}
1642
bellard59817cc2004-02-16 22:01:13 +00001643/* add a new TLB entry. At most one entry for a given virtual address
1644 is permitted. Return 0 if OK or 2 if the page could not be mapped
1645 (can only happen in non SOFTMMU mode for I/O pages or pages
1646 conflicting with the host address space). */
ths5fafdf22007-09-16 21:08:06 +00001647int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
1648 target_phys_addr_t paddr, int prot,
j_mayer6ebbf392007-10-14 07:07:08 +00001649 int mmu_idx, int is_softmmu)
bellard9fa3e852004-01-04 18:06:42 +00001650{
bellard92e873b2004-05-21 14:52:29 +00001651 PhysPageDesc *p;
bellard4f2ac232004-04-26 19:44:02 +00001652 unsigned long pd;
bellard9fa3e852004-01-04 18:06:42 +00001653 unsigned int index;
bellard4f2ac232004-04-26 19:44:02 +00001654 target_ulong address;
bellard108c49b2005-07-24 12:55:09 +00001655 target_phys_addr_t addend;
bellard9fa3e852004-01-04 18:06:42 +00001656 int ret;
bellard84b7b8e2005-11-28 21:19:04 +00001657 CPUTLBEntry *te;
pbrook6658ffb2007-03-16 23:58:11 +00001658 int i;
bellard9fa3e852004-01-04 18:06:42 +00001659
bellard92e873b2004-05-21 14:52:29 +00001660 p = phys_page_find(paddr >> TARGET_PAGE_BITS);
bellard9fa3e852004-01-04 18:06:42 +00001661 if (!p) {
1662 pd = IO_MEM_UNASSIGNED;
bellard9fa3e852004-01-04 18:06:42 +00001663 } else {
1664 pd = p->phys_offset;
bellard9fa3e852004-01-04 18:06:42 +00001665 }
1666#if defined(DEBUG_TLB)
j_mayer6ebbf392007-10-14 07:07:08 +00001667 printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x idx=%d smmu=%d pd=0x%08lx\n",
1668 vaddr, (int)paddr, prot, mmu_idx, is_softmmu, pd);
bellard9fa3e852004-01-04 18:06:42 +00001669#endif
1670
1671 ret = 0;
1672#if !defined(CONFIG_SOFTMMU)
ths5fafdf22007-09-16 21:08:06 +00001673 if (is_softmmu)
bellard9fa3e852004-01-04 18:06:42 +00001674#endif
1675 {
bellard2a4188a2006-06-25 21:54:59 +00001676 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
bellard9fa3e852004-01-04 18:06:42 +00001677 /* IO memory case */
1678 address = vaddr | pd;
1679 addend = paddr;
1680 } else {
1681 /* standard memory */
1682 address = vaddr;
1683 addend = (unsigned long)phys_ram_base + (pd & TARGET_PAGE_MASK);
1684 }
pbrook6658ffb2007-03-16 23:58:11 +00001685
1686 /* Make accesses to pages with watchpoints go via the
1687 watchpoint trap routines. */
1688 for (i = 0; i < env->nb_watchpoints; i++) {
1689 if (vaddr == (env->watchpoint[i].vaddr & TARGET_PAGE_MASK)) {
1690 if (address & ~TARGET_PAGE_MASK) {
balrogd79acba2007-06-26 20:01:13 +00001691 env->watchpoint[i].addend = 0;
pbrook6658ffb2007-03-16 23:58:11 +00001692 address = vaddr | io_mem_watch;
1693 } else {
balrogd79acba2007-06-26 20:01:13 +00001694 env->watchpoint[i].addend = pd - paddr +
1695 (unsigned long) phys_ram_base;
pbrook6658ffb2007-03-16 23:58:11 +00001696 /* TODO: Figure out how to make read watchpoints coexist
1697 with code. */
1698 pd = (pd & TARGET_PAGE_MASK) | io_mem_watch | IO_MEM_ROMD;
1699 }
1700 }
1701 }
balrogd79acba2007-06-26 20:01:13 +00001702
bellard90f18422005-07-24 10:17:31 +00001703 index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
bellard9fa3e852004-01-04 18:06:42 +00001704 addend -= vaddr;
j_mayer6ebbf392007-10-14 07:07:08 +00001705 te = &env->tlb_table[mmu_idx][index];
bellard84b7b8e2005-11-28 21:19:04 +00001706 te->addend = addend;
bellard67b915a2004-03-31 23:37:16 +00001707 if (prot & PAGE_READ) {
bellard84b7b8e2005-11-28 21:19:04 +00001708 te->addr_read = address;
bellard9fa3e852004-01-04 18:06:42 +00001709 } else {
bellard84b7b8e2005-11-28 21:19:04 +00001710 te->addr_read = -1;
1711 }
1712 if (prot & PAGE_EXEC) {
1713 te->addr_code = address;
1714 } else {
1715 te->addr_code = -1;
bellard9fa3e852004-01-04 18:06:42 +00001716 }
bellard67b915a2004-03-31 23:37:16 +00001717 if (prot & PAGE_WRITE) {
ths5fafdf22007-09-16 21:08:06 +00001718 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM ||
bellard856074e2006-07-04 09:47:34 +00001719 (pd & IO_MEM_ROMD)) {
1720 /* write access calls the I/O callback */
ths5fafdf22007-09-16 21:08:06 +00001721 te->addr_write = vaddr |
bellard856074e2006-07-04 09:47:34 +00001722 (pd & ~(TARGET_PAGE_MASK | IO_MEM_ROMD));
ths5fafdf22007-09-16 21:08:06 +00001723 } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
bellard1ccde1c2004-02-06 19:46:14 +00001724 !cpu_physical_memory_is_dirty(pd)) {
bellard84b7b8e2005-11-28 21:19:04 +00001725 te->addr_write = vaddr | IO_MEM_NOTDIRTY;
bellard9fa3e852004-01-04 18:06:42 +00001726 } else {
bellard84b7b8e2005-11-28 21:19:04 +00001727 te->addr_write = address;
bellard9fa3e852004-01-04 18:06:42 +00001728 }
1729 } else {
bellard84b7b8e2005-11-28 21:19:04 +00001730 te->addr_write = -1;
bellard9fa3e852004-01-04 18:06:42 +00001731 }
1732 }
1733#if !defined(CONFIG_SOFTMMU)
1734 else {
1735 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
1736 /* IO access: no mapping is done as it will be handled by the
1737 soft MMU */
1738 if (!(env->hflags & HF_SOFTMMU_MASK))
1739 ret = 2;
1740 } else {
1741 void *map_addr;
bellard9fa3e852004-01-04 18:06:42 +00001742
bellard59817cc2004-02-16 22:01:13 +00001743 if (vaddr >= MMAP_AREA_END) {
1744 ret = 2;
1745 } else {
1746 if (prot & PROT_WRITE) {
ths5fafdf22007-09-16 21:08:06 +00001747 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM ||
bellardd720b932004-04-25 17:57:43 +00001748#if defined(TARGET_HAS_SMC) || 1
bellard59817cc2004-02-16 22:01:13 +00001749 first_tb ||
bellardd720b932004-04-25 17:57:43 +00001750#endif
ths5fafdf22007-09-16 21:08:06 +00001751 ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
bellard59817cc2004-02-16 22:01:13 +00001752 !cpu_physical_memory_is_dirty(pd))) {
1753 /* ROM: we do as if code was inside */
1754 /* if code is present, we only map as read only and save the
1755 original mapping */
1756 VirtPageDesc *vp;
ths3b46e622007-09-17 08:09:54 +00001757
bellard90f18422005-07-24 10:17:31 +00001758 vp = virt_page_find_alloc(vaddr >> TARGET_PAGE_BITS, 1);
bellard59817cc2004-02-16 22:01:13 +00001759 vp->phys_addr = pd;
1760 vp->prot = prot;
1761 vp->valid_tag = virt_valid_tag;
1762 prot &= ~PAGE_WRITE;
1763 }
bellard9fa3e852004-01-04 18:06:42 +00001764 }
ths5fafdf22007-09-16 21:08:06 +00001765 map_addr = mmap((void *)vaddr, TARGET_PAGE_SIZE, prot,
bellard59817cc2004-02-16 22:01:13 +00001766 MAP_SHARED | MAP_FIXED, phys_ram_fd, (pd & TARGET_PAGE_MASK));
1767 if (map_addr == MAP_FAILED) {
1768 cpu_abort(env, "mmap failed when mapped physical address 0x%08x to virtual address 0x%08x\n",
1769 paddr, vaddr);
1770 }
bellard9fa3e852004-01-04 18:06:42 +00001771 }
1772 }
1773 }
1774#endif
1775 return ret;
1776}
1777
1778/* called from signal handler: invalidate the code and unprotect the
1779 page. Return TRUE if the fault was succesfully handled. */
pbrook53a59602006-03-25 19:31:22 +00001780int page_unprotect(target_ulong addr, unsigned long pc, void *puc)
bellard9fa3e852004-01-04 18:06:42 +00001781{
1782#if !defined(CONFIG_SOFTMMU)
1783 VirtPageDesc *vp;
1784
1785#if defined(DEBUG_TLB)
1786 printf("page_unprotect: addr=0x%08x\n", addr);
1787#endif
1788 addr &= TARGET_PAGE_MASK;
bellard59817cc2004-02-16 22:01:13 +00001789
1790 /* if it is not mapped, no need to worry here */
1791 if (addr >= MMAP_AREA_END)
1792 return 0;
bellard9fa3e852004-01-04 18:06:42 +00001793 vp = virt_page_find(addr >> TARGET_PAGE_BITS);
1794 if (!vp)
1795 return 0;
1796 /* NOTE: in this case, validate_tag is _not_ tested as it
1797 validates only the code TLB */
1798 if (vp->valid_tag != virt_valid_tag)
1799 return 0;
1800 if (!(vp->prot & PAGE_WRITE))
1801 return 0;
1802#if defined(DEBUG_TLB)
ths5fafdf22007-09-16 21:08:06 +00001803 printf("page_unprotect: addr=0x%08x phys_addr=0x%08x prot=%x\n",
bellard9fa3e852004-01-04 18:06:42 +00001804 addr, vp->phys_addr, vp->prot);
1805#endif
bellard59817cc2004-02-16 22:01:13 +00001806 if (mprotect((void *)addr, TARGET_PAGE_SIZE, vp->prot) < 0)
1807 cpu_abort(cpu_single_env, "error mprotect addr=0x%lx prot=%d\n",
1808 (unsigned long)addr, vp->prot);
bellardd720b932004-04-25 17:57:43 +00001809 /* set the dirty bit */
bellard0a962c02005-02-10 22:00:27 +00001810 phys_ram_dirty[vp->phys_addr >> TARGET_PAGE_BITS] = 0xff;
bellardd720b932004-04-25 17:57:43 +00001811 /* flush the code inside */
1812 tb_invalidate_phys_page(vp->phys_addr, pc, puc);
bellard9fa3e852004-01-04 18:06:42 +00001813 return 1;
1814#else
1815 return 0;
1816#endif
bellard33417e72003-08-10 21:47:01 +00001817}
1818
bellard01243112004-01-04 15:48:17 +00001819#else
1820
bellardee8b7022004-02-03 23:35:10 +00001821void tlb_flush(CPUState *env, int flush_global)
bellard01243112004-01-04 15:48:17 +00001822{
1823}
1824
bellard2e126692004-04-25 21:28:44 +00001825void tlb_flush_page(CPUState *env, target_ulong addr)
bellard01243112004-01-04 15:48:17 +00001826{
1827}
1828
ths5fafdf22007-09-16 21:08:06 +00001829int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
1830 target_phys_addr_t paddr, int prot,
j_mayer6ebbf392007-10-14 07:07:08 +00001831 int mmu_idx, int is_softmmu)
bellard33417e72003-08-10 21:47:01 +00001832{
bellard9fa3e852004-01-04 18:06:42 +00001833 return 0;
1834}
bellard33417e72003-08-10 21:47:01 +00001835
bellard9fa3e852004-01-04 18:06:42 +00001836/* dump memory mappings */
1837void page_dump(FILE *f)
1838{
1839 unsigned long start, end;
1840 int i, j, prot, prot1;
1841 PageDesc *p;
1842
1843 fprintf(f, "%-8s %-8s %-8s %s\n",
1844 "start", "end", "size", "prot");
1845 start = -1;
1846 end = -1;
1847 prot = 0;
1848 for(i = 0; i <= L1_SIZE; i++) {
1849 if (i < L1_SIZE)
1850 p = l1_map[i];
1851 else
1852 p = NULL;
1853 for(j = 0;j < L2_SIZE; j++) {
1854 if (!p)
1855 prot1 = 0;
1856 else
1857 prot1 = p[j].flags;
1858 if (prot1 != prot) {
1859 end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
1860 if (start != -1) {
1861 fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
ths5fafdf22007-09-16 21:08:06 +00001862 start, end, end - start,
bellard9fa3e852004-01-04 18:06:42 +00001863 prot & PAGE_READ ? 'r' : '-',
1864 prot & PAGE_WRITE ? 'w' : '-',
1865 prot & PAGE_EXEC ? 'x' : '-');
1866 }
1867 if (prot1 != 0)
1868 start = end;
1869 else
1870 start = -1;
1871 prot = prot1;
1872 }
1873 if (!p)
1874 break;
1875 }
bellard33417e72003-08-10 21:47:01 +00001876 }
bellard33417e72003-08-10 21:47:01 +00001877}
1878
pbrook53a59602006-03-25 19:31:22 +00001879int page_get_flags(target_ulong address)
bellard33417e72003-08-10 21:47:01 +00001880{
bellard9fa3e852004-01-04 18:06:42 +00001881 PageDesc *p;
1882
1883 p = page_find(address >> TARGET_PAGE_BITS);
bellard33417e72003-08-10 21:47:01 +00001884 if (!p)
bellard9fa3e852004-01-04 18:06:42 +00001885 return 0;
1886 return p->flags;
bellard33417e72003-08-10 21:47:01 +00001887}
1888
bellard9fa3e852004-01-04 18:06:42 +00001889/* modify the flags of a page and invalidate the code if
1890 necessary. The flag PAGE_WRITE_ORG is positionned automatically
1891 depending on PAGE_WRITE */
pbrook53a59602006-03-25 19:31:22 +00001892void page_set_flags(target_ulong start, target_ulong end, int flags)
bellard9fa3e852004-01-04 18:06:42 +00001893{
1894 PageDesc *p;
pbrook53a59602006-03-25 19:31:22 +00001895 target_ulong addr;
bellard9fa3e852004-01-04 18:06:42 +00001896
1897 start = start & TARGET_PAGE_MASK;
1898 end = TARGET_PAGE_ALIGN(end);
1899 if (flags & PAGE_WRITE)
1900 flags |= PAGE_WRITE_ORG;
1901 spin_lock(&tb_lock);
1902 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1903 p = page_find_alloc(addr >> TARGET_PAGE_BITS);
1904 /* if the write protection is set, then we invalidate the code
1905 inside */
ths5fafdf22007-09-16 21:08:06 +00001906 if (!(p->flags & PAGE_WRITE) &&
bellard9fa3e852004-01-04 18:06:42 +00001907 (flags & PAGE_WRITE) &&
1908 p->first_tb) {
bellardd720b932004-04-25 17:57:43 +00001909 tb_invalidate_phys_page(addr, 0, NULL);
bellard9fa3e852004-01-04 18:06:42 +00001910 }
1911 p->flags = flags;
1912 }
1913 spin_unlock(&tb_lock);
1914}
1915
ths3d97b402007-11-02 19:02:07 +00001916int page_check_range(target_ulong start, target_ulong len, int flags)
1917{
1918 PageDesc *p;
1919 target_ulong end;
1920 target_ulong addr;
1921
1922 end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
1923 start = start & TARGET_PAGE_MASK;
1924
1925 if( end < start )
1926 /* we've wrapped around */
1927 return -1;
1928 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1929 p = page_find(addr >> TARGET_PAGE_BITS);
1930 if( !p )
1931 return -1;
1932 if( !(p->flags & PAGE_VALID) )
1933 return -1;
1934
bellarddae32702007-11-14 10:51:00 +00001935 if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
ths3d97b402007-11-02 19:02:07 +00001936 return -1;
bellarddae32702007-11-14 10:51:00 +00001937 if (flags & PAGE_WRITE) {
1938 if (!(p->flags & PAGE_WRITE_ORG))
1939 return -1;
1940 /* unprotect the page if it was put read-only because it
1941 contains translated code */
1942 if (!(p->flags & PAGE_WRITE)) {
1943 if (!page_unprotect(addr, 0, NULL))
1944 return -1;
1945 }
1946 return 0;
1947 }
ths3d97b402007-11-02 19:02:07 +00001948 }
1949 return 0;
1950}
1951
bellard9fa3e852004-01-04 18:06:42 +00001952/* called from signal handler: invalidate the code and unprotect the
1953 page. Return TRUE if the fault was succesfully handled. */
pbrook53a59602006-03-25 19:31:22 +00001954int page_unprotect(target_ulong address, unsigned long pc, void *puc)
bellard9fa3e852004-01-04 18:06:42 +00001955{
1956 unsigned int page_index, prot, pindex;
1957 PageDesc *p, *p1;
pbrook53a59602006-03-25 19:31:22 +00001958 target_ulong host_start, host_end, addr;
bellard9fa3e852004-01-04 18:06:42 +00001959
bellard83fb7ad2004-07-05 21:25:26 +00001960 host_start = address & qemu_host_page_mask;
bellard9fa3e852004-01-04 18:06:42 +00001961 page_index = host_start >> TARGET_PAGE_BITS;
1962 p1 = page_find(page_index);
1963 if (!p1)
1964 return 0;
bellard83fb7ad2004-07-05 21:25:26 +00001965 host_end = host_start + qemu_host_page_size;
bellard9fa3e852004-01-04 18:06:42 +00001966 p = p1;
1967 prot = 0;
1968 for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
1969 prot |= p->flags;
1970 p++;
1971 }
1972 /* if the page was really writable, then we change its
1973 protection back to writable */
1974 if (prot & PAGE_WRITE_ORG) {
1975 pindex = (address - host_start) >> TARGET_PAGE_BITS;
1976 if (!(p1[pindex].flags & PAGE_WRITE)) {
ths5fafdf22007-09-16 21:08:06 +00001977 mprotect((void *)g2h(host_start), qemu_host_page_size,
bellard9fa3e852004-01-04 18:06:42 +00001978 (prot & PAGE_BITS) | PAGE_WRITE);
1979 p1[pindex].flags |= PAGE_WRITE;
1980 /* and since the content will be modified, we must invalidate
1981 the corresponding translated code. */
bellardd720b932004-04-25 17:57:43 +00001982 tb_invalidate_phys_page(address, pc, puc);
bellard9fa3e852004-01-04 18:06:42 +00001983#ifdef DEBUG_TB_CHECK
1984 tb_invalidate_check(address);
1985#endif
1986 return 1;
1987 }
1988 }
1989 return 0;
1990}
1991
bellard6a00d602005-11-21 23:25:50 +00001992static inline void tlb_set_dirty(CPUState *env,
1993 unsigned long addr, target_ulong vaddr)
bellard1ccde1c2004-02-06 19:46:14 +00001994{
1995}
bellard9fa3e852004-01-04 18:06:42 +00001996#endif /* defined(CONFIG_USER_ONLY) */
1997
blueswir1db7b5422007-05-26 17:36:03 +00001998static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
1999 int memory);
aurel32967032c2008-04-22 20:37:34 +00002000static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
blueswir1db7b5422007-05-26 17:36:03 +00002001 int orig_memory);
2002#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
2003 need_subpage) \
2004 do { \
2005 if (addr > start_addr) \
2006 start_addr2 = 0; \
2007 else { \
2008 start_addr2 = start_addr & ~TARGET_PAGE_MASK; \
2009 if (start_addr2 > 0) \
2010 need_subpage = 1; \
2011 } \
2012 \
blueswir149e9fba2007-05-30 17:25:06 +00002013 if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE) \
blueswir1db7b5422007-05-26 17:36:03 +00002014 end_addr2 = TARGET_PAGE_SIZE - 1; \
2015 else { \
2016 end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
2017 if (end_addr2 < TARGET_PAGE_SIZE - 1) \
2018 need_subpage = 1; \
2019 } \
2020 } while (0)
2021
bellard33417e72003-08-10 21:47:01 +00002022/* register physical memory. 'size' must be a multiple of the target
2023 page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
2024 io memory page */
ths5fafdf22007-09-16 21:08:06 +00002025void cpu_register_physical_memory(target_phys_addr_t start_addr,
aurel32967032c2008-04-22 20:37:34 +00002026 ram_addr_t size,
2027 ram_addr_t phys_offset)
bellard33417e72003-08-10 21:47:01 +00002028{
bellard108c49b2005-07-24 12:55:09 +00002029 target_phys_addr_t addr, end_addr;
bellard92e873b2004-05-21 14:52:29 +00002030 PhysPageDesc *p;
bellard9d420372006-06-25 22:25:22 +00002031 CPUState *env;
aurel32967032c2008-04-22 20:37:34 +00002032 ram_addr_t orig_size = size;
blueswir1db7b5422007-05-26 17:36:03 +00002033 void *subpage;
bellard33417e72003-08-10 21:47:01 +00002034
bellard5fd386f2004-05-23 21:11:22 +00002035 size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
blueswir149e9fba2007-05-30 17:25:06 +00002036 end_addr = start_addr + (target_phys_addr_t)size;
2037 for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
blueswir1db7b5422007-05-26 17:36:03 +00002038 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2039 if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
aurel32967032c2008-04-22 20:37:34 +00002040 ram_addr_t orig_memory = p->phys_offset;
blueswir1db7b5422007-05-26 17:36:03 +00002041 target_phys_addr_t start_addr2, end_addr2;
2042 int need_subpage = 0;
2043
2044 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2045 need_subpage);
blueswir14254fab2008-01-01 16:57:19 +00002046 if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
blueswir1db7b5422007-05-26 17:36:03 +00002047 if (!(orig_memory & IO_MEM_SUBPAGE)) {
2048 subpage = subpage_init((addr & TARGET_PAGE_MASK),
2049 &p->phys_offset, orig_memory);
2050 } else {
2051 subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
2052 >> IO_MEM_SHIFT];
2053 }
2054 subpage_register(subpage, start_addr2, end_addr2, phys_offset);
2055 } else {
2056 p->phys_offset = phys_offset;
2057 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2058 (phys_offset & IO_MEM_ROMD))
2059 phys_offset += TARGET_PAGE_SIZE;
2060 }
2061 } else {
2062 p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2063 p->phys_offset = phys_offset;
2064 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2065 (phys_offset & IO_MEM_ROMD))
2066 phys_offset += TARGET_PAGE_SIZE;
2067 else {
2068 target_phys_addr_t start_addr2, end_addr2;
2069 int need_subpage = 0;
2070
2071 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2072 end_addr2, need_subpage);
2073
blueswir14254fab2008-01-01 16:57:19 +00002074 if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
blueswir1db7b5422007-05-26 17:36:03 +00002075 subpage = subpage_init((addr & TARGET_PAGE_MASK),
2076 &p->phys_offset, IO_MEM_UNASSIGNED);
2077 subpage_register(subpage, start_addr2, end_addr2,
2078 phys_offset);
2079 }
2080 }
2081 }
bellard33417e72003-08-10 21:47:01 +00002082 }
ths3b46e622007-09-17 08:09:54 +00002083
bellard9d420372006-06-25 22:25:22 +00002084 /* since each CPU stores ram addresses in its TLB cache, we must
2085 reset the modified entries */
2086 /* XXX: slow ! */
2087 for(env = first_cpu; env != NULL; env = env->next_cpu) {
2088 tlb_flush(env, 1);
2089 }
bellard33417e72003-08-10 21:47:01 +00002090}
2091
bellardba863452006-09-24 18:41:10 +00002092/* XXX: temporary until new memory mapping API */
aurel32967032c2008-04-22 20:37:34 +00002093ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr)
bellardba863452006-09-24 18:41:10 +00002094{
2095 PhysPageDesc *p;
2096
2097 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2098 if (!p)
2099 return IO_MEM_UNASSIGNED;
2100 return p->phys_offset;
2101}
2102
bellarde9a1ab12007-02-08 23:08:38 +00002103/* XXX: better than nothing */
aurel32967032c2008-04-22 20:37:34 +00002104ram_addr_t qemu_ram_alloc(ram_addr_t size)
bellarde9a1ab12007-02-08 23:08:38 +00002105{
2106 ram_addr_t addr;
2107 if ((phys_ram_alloc_offset + size) >= phys_ram_size) {
aurel32967032c2008-04-22 20:37:34 +00002108 fprintf(stderr, "Not enough memory (requested_size = %lu, max memory = %" PRIu64 ")\n",
2109 size, (uint64_t)phys_ram_size);
bellarde9a1ab12007-02-08 23:08:38 +00002110 abort();
2111 }
2112 addr = phys_ram_alloc_offset;
2113 phys_ram_alloc_offset = TARGET_PAGE_ALIGN(phys_ram_alloc_offset + size);
2114 return addr;
2115}
2116
2117void qemu_ram_free(ram_addr_t addr)
2118{
2119}
2120
bellarda4193c82004-06-03 14:01:43 +00002121static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
bellard33417e72003-08-10 21:47:01 +00002122{
pbrook67d3b952006-12-18 05:03:52 +00002123#ifdef DEBUG_UNASSIGNED
blueswir1ab3d1722007-11-04 07:31:40 +00002124 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
pbrook67d3b952006-12-18 05:03:52 +00002125#endif
blueswir1b4f0a312007-05-06 17:59:24 +00002126#ifdef TARGET_SPARC
blueswir16c36d3f2007-05-17 19:30:10 +00002127 do_unassigned_access(addr, 0, 0, 0);
thsf1ccf902007-10-08 13:16:14 +00002128#elif TARGET_CRIS
2129 do_unassigned_access(addr, 0, 0, 0);
blueswir1b4f0a312007-05-06 17:59:24 +00002130#endif
bellard33417e72003-08-10 21:47:01 +00002131 return 0;
2132}
2133
bellarda4193c82004-06-03 14:01:43 +00002134static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
bellard33417e72003-08-10 21:47:01 +00002135{
pbrook67d3b952006-12-18 05:03:52 +00002136#ifdef DEBUG_UNASSIGNED
blueswir1ab3d1722007-11-04 07:31:40 +00002137 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
pbrook67d3b952006-12-18 05:03:52 +00002138#endif
blueswir1b4f0a312007-05-06 17:59:24 +00002139#ifdef TARGET_SPARC
blueswir16c36d3f2007-05-17 19:30:10 +00002140 do_unassigned_access(addr, 1, 0, 0);
thsf1ccf902007-10-08 13:16:14 +00002141#elif TARGET_CRIS
2142 do_unassigned_access(addr, 1, 0, 0);
blueswir1b4f0a312007-05-06 17:59:24 +00002143#endif
bellard33417e72003-08-10 21:47:01 +00002144}
2145
2146static CPUReadMemoryFunc *unassigned_mem_read[3] = {
2147 unassigned_mem_readb,
2148 unassigned_mem_readb,
2149 unassigned_mem_readb,
2150};
2151
2152static CPUWriteMemoryFunc *unassigned_mem_write[3] = {
2153 unassigned_mem_writeb,
2154 unassigned_mem_writeb,
2155 unassigned_mem_writeb,
2156};
2157
bellarda4193c82004-06-03 14:01:43 +00002158static void notdirty_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
bellard1ccde1c2004-02-06 19:46:14 +00002159{
bellard3a7d9292005-08-21 09:26:42 +00002160 unsigned long ram_addr;
2161 int dirty_flags;
2162 ram_addr = addr - (unsigned long)phys_ram_base;
2163 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2164 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2165#if !defined(CONFIG_USER_ONLY)
2166 tb_invalidate_phys_page_fast(ram_addr, 1);
2167 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2168#endif
2169 }
bellardc27004e2005-01-03 23:35:10 +00002170 stb_p((uint8_t *)(long)addr, val);
bellardf32fc642006-02-08 22:43:39 +00002171#ifdef USE_KQEMU
2172 if (cpu_single_env->kqemu_enabled &&
2173 (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2174 kqemu_modify_page(cpu_single_env, ram_addr);
2175#endif
bellardf23db162005-08-21 19:12:28 +00002176 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2177 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2178 /* we remove the notdirty callback only if the code has been
2179 flushed */
2180 if (dirty_flags == 0xff)
bellard6a00d602005-11-21 23:25:50 +00002181 tlb_set_dirty(cpu_single_env, addr, cpu_single_env->mem_write_vaddr);
bellard1ccde1c2004-02-06 19:46:14 +00002182}
2183
bellarda4193c82004-06-03 14:01:43 +00002184static void notdirty_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
bellard1ccde1c2004-02-06 19:46:14 +00002185{
bellard3a7d9292005-08-21 09:26:42 +00002186 unsigned long ram_addr;
2187 int dirty_flags;
2188 ram_addr = addr - (unsigned long)phys_ram_base;
2189 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, 2);
2193 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2194#endif
2195 }
bellardc27004e2005-01-03 23:35:10 +00002196 stw_p((uint8_t *)(long)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)
bellard6a00d602005-11-21 23:25:50 +00002207 tlb_set_dirty(cpu_single_env, addr, cpu_single_env->mem_write_vaddr);
bellard1ccde1c2004-02-06 19:46:14 +00002208}
2209
bellarda4193c82004-06-03 14:01:43 +00002210static void notdirty_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
bellard1ccde1c2004-02-06 19:46:14 +00002211{
bellard3a7d9292005-08-21 09:26:42 +00002212 unsigned long ram_addr;
2213 int dirty_flags;
2214 ram_addr = addr - (unsigned long)phys_ram_base;
2215 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2216 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2217#if !defined(CONFIG_USER_ONLY)
2218 tb_invalidate_phys_page_fast(ram_addr, 4);
2219 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2220#endif
2221 }
bellardc27004e2005-01-03 23:35:10 +00002222 stl_p((uint8_t *)(long)addr, val);
bellardf32fc642006-02-08 22:43:39 +00002223#ifdef USE_KQEMU
2224 if (cpu_single_env->kqemu_enabled &&
2225 (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2226 kqemu_modify_page(cpu_single_env, ram_addr);
2227#endif
bellardf23db162005-08-21 19:12:28 +00002228 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2229 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2230 /* we remove the notdirty callback only if the code has been
2231 flushed */
2232 if (dirty_flags == 0xff)
bellard6a00d602005-11-21 23:25:50 +00002233 tlb_set_dirty(cpu_single_env, addr, cpu_single_env->mem_write_vaddr);
bellard1ccde1c2004-02-06 19:46:14 +00002234}
2235
bellard3a7d9292005-08-21 09:26:42 +00002236static CPUReadMemoryFunc *error_mem_read[3] = {
2237 NULL, /* never used */
2238 NULL, /* never used */
2239 NULL, /* never used */
2240};
2241
bellard1ccde1c2004-02-06 19:46:14 +00002242static CPUWriteMemoryFunc *notdirty_mem_write[3] = {
2243 notdirty_mem_writeb,
2244 notdirty_mem_writew,
2245 notdirty_mem_writel,
2246};
2247
pbrook6658ffb2007-03-16 23:58:11 +00002248#if defined(CONFIG_SOFTMMU)
2249/* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
2250 so these check for a hit then pass through to the normal out-of-line
2251 phys routines. */
2252static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
2253{
2254 return ldub_phys(addr);
2255}
2256
2257static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
2258{
2259 return lduw_phys(addr);
2260}
2261
2262static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
2263{
2264 return ldl_phys(addr);
2265}
2266
2267/* Generate a debug exception if a watchpoint has been hit.
2268 Returns the real physical address of the access. addr will be a host
balrogd79acba2007-06-26 20:01:13 +00002269 address in case of a RAM location. */
pbrook6658ffb2007-03-16 23:58:11 +00002270static target_ulong check_watchpoint(target_phys_addr_t addr)
2271{
2272 CPUState *env = cpu_single_env;
2273 target_ulong watch;
2274 target_ulong retaddr;
2275 int i;
2276
2277 retaddr = addr;
2278 for (i = 0; i < env->nb_watchpoints; i++) {
2279 watch = env->watchpoint[i].vaddr;
2280 if (((env->mem_write_vaddr ^ watch) & TARGET_PAGE_MASK) == 0) {
balrogd79acba2007-06-26 20:01:13 +00002281 retaddr = addr - env->watchpoint[i].addend;
pbrook6658ffb2007-03-16 23:58:11 +00002282 if (((addr ^ watch) & ~TARGET_PAGE_MASK) == 0) {
2283 cpu_single_env->watchpoint_hit = i + 1;
2284 cpu_interrupt(cpu_single_env, CPU_INTERRUPT_DEBUG);
2285 break;
2286 }
2287 }
2288 }
2289 return retaddr;
2290}
2291
2292static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
2293 uint32_t val)
2294{
2295 addr = check_watchpoint(addr);
2296 stb_phys(addr, val);
2297}
2298
2299static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
2300 uint32_t val)
2301{
2302 addr = check_watchpoint(addr);
2303 stw_phys(addr, val);
2304}
2305
2306static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
2307 uint32_t val)
2308{
2309 addr = check_watchpoint(addr);
2310 stl_phys(addr, val);
2311}
2312
2313static CPUReadMemoryFunc *watch_mem_read[3] = {
2314 watch_mem_readb,
2315 watch_mem_readw,
2316 watch_mem_readl,
2317};
2318
2319static CPUWriteMemoryFunc *watch_mem_write[3] = {
2320 watch_mem_writeb,
2321 watch_mem_writew,
2322 watch_mem_writel,
2323};
2324#endif
2325
blueswir1db7b5422007-05-26 17:36:03 +00002326static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr,
2327 unsigned int len)
2328{
blueswir1db7b5422007-05-26 17:36:03 +00002329 uint32_t ret;
2330 unsigned int idx;
2331
2332 idx = SUBPAGE_IDX(addr - mmio->base);
2333#if defined(DEBUG_SUBPAGE)
2334 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
2335 mmio, len, addr, idx);
2336#endif
blueswir13ee89922008-01-02 19:45:26 +00002337 ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len], addr);
blueswir1db7b5422007-05-26 17:36:03 +00002338
2339 return ret;
2340}
2341
2342static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
2343 uint32_t value, unsigned int len)
2344{
blueswir1db7b5422007-05-26 17:36:03 +00002345 unsigned int idx;
2346
2347 idx = SUBPAGE_IDX(addr - mmio->base);
2348#if defined(DEBUG_SUBPAGE)
2349 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
2350 mmio, len, addr, idx, value);
2351#endif
blueswir13ee89922008-01-02 19:45:26 +00002352 (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len], addr, value);
blueswir1db7b5422007-05-26 17:36:03 +00002353}
2354
2355static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
2356{
2357#if defined(DEBUG_SUBPAGE)
2358 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2359#endif
2360
2361 return subpage_readlen(opaque, addr, 0);
2362}
2363
2364static void subpage_writeb (void *opaque, target_phys_addr_t addr,
2365 uint32_t value)
2366{
2367#if defined(DEBUG_SUBPAGE)
2368 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2369#endif
2370 subpage_writelen(opaque, addr, value, 0);
2371}
2372
2373static uint32_t subpage_readw (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, 1);
2380}
2381
2382static void subpage_writew (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, 1);
2389}
2390
2391static uint32_t subpage_readl (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, 2);
2398}
2399
2400static void subpage_writel (void *opaque,
2401 target_phys_addr_t addr, 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, 2);
2407}
2408
2409static CPUReadMemoryFunc *subpage_read[] = {
2410 &subpage_readb,
2411 &subpage_readw,
2412 &subpage_readl,
2413};
2414
2415static CPUWriteMemoryFunc *subpage_write[] = {
2416 &subpage_writeb,
2417 &subpage_writew,
2418 &subpage_writel,
2419};
2420
2421static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
2422 int memory)
2423{
2424 int idx, eidx;
blueswir14254fab2008-01-01 16:57:19 +00002425 unsigned int i;
blueswir1db7b5422007-05-26 17:36:03 +00002426
2427 if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
2428 return -1;
2429 idx = SUBPAGE_IDX(start);
2430 eidx = SUBPAGE_IDX(end);
2431#if defined(DEBUG_SUBPAGE)
2432 printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %d\n", __func__,
2433 mmio, start, end, idx, eidx, memory);
2434#endif
2435 memory >>= IO_MEM_SHIFT;
2436 for (; idx <= eidx; idx++) {
blueswir14254fab2008-01-01 16:57:19 +00002437 for (i = 0; i < 4; i++) {
blueswir13ee89922008-01-02 19:45:26 +00002438 if (io_mem_read[memory][i]) {
2439 mmio->mem_read[idx][i] = &io_mem_read[memory][i];
2440 mmio->opaque[idx][0][i] = io_mem_opaque[memory];
2441 }
2442 if (io_mem_write[memory][i]) {
2443 mmio->mem_write[idx][i] = &io_mem_write[memory][i];
2444 mmio->opaque[idx][1][i] = io_mem_opaque[memory];
2445 }
blueswir14254fab2008-01-01 16:57:19 +00002446 }
blueswir1db7b5422007-05-26 17:36:03 +00002447 }
2448
2449 return 0;
2450}
2451
aurel32967032c2008-04-22 20:37:34 +00002452static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
blueswir1db7b5422007-05-26 17:36:03 +00002453 int orig_memory)
2454{
2455 subpage_t *mmio;
2456 int subpage_memory;
2457
2458 mmio = qemu_mallocz(sizeof(subpage_t));
2459 if (mmio != NULL) {
2460 mmio->base = base;
2461 subpage_memory = cpu_register_io_memory(0, subpage_read, subpage_write, mmio);
2462#if defined(DEBUG_SUBPAGE)
2463 printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
2464 mmio, base, TARGET_PAGE_SIZE, subpage_memory);
2465#endif
2466 *phys = subpage_memory | IO_MEM_SUBPAGE;
2467 subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory);
2468 }
2469
2470 return mmio;
2471}
2472
bellard33417e72003-08-10 21:47:01 +00002473static void io_mem_init(void)
2474{
bellard3a7d9292005-08-21 09:26:42 +00002475 cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read, unassigned_mem_write, NULL);
bellarda4193c82004-06-03 14:01:43 +00002476 cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write, NULL);
bellard3a7d9292005-08-21 09:26:42 +00002477 cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read, notdirty_mem_write, NULL);
bellard1ccde1c2004-02-06 19:46:14 +00002478 io_mem_nb = 5;
2479
pbrook6658ffb2007-03-16 23:58:11 +00002480#if defined(CONFIG_SOFTMMU)
2481 io_mem_watch = cpu_register_io_memory(-1, watch_mem_read,
2482 watch_mem_write, NULL);
2483#endif
bellard1ccde1c2004-02-06 19:46:14 +00002484 /* alloc dirty bits array */
bellard0a962c02005-02-10 22:00:27 +00002485 phys_ram_dirty = qemu_vmalloc(phys_ram_size >> TARGET_PAGE_BITS);
bellard3a7d9292005-08-21 09:26:42 +00002486 memset(phys_ram_dirty, 0xff, phys_ram_size >> TARGET_PAGE_BITS);
bellard33417e72003-08-10 21:47:01 +00002487}
2488
2489/* mem_read and mem_write are arrays of functions containing the
2490 function to access byte (index 0), word (index 1) and dword (index
blueswir13ee89922008-01-02 19:45:26 +00002491 2). Functions can be omitted with a NULL function pointer. The
2492 registered functions may be modified dynamically later.
2493 If io_index is non zero, the corresponding io zone is
blueswir14254fab2008-01-01 16:57:19 +00002494 modified. If it is zero, a new io zone is allocated. The return
2495 value can be used with cpu_register_physical_memory(). (-1) is
2496 returned if error. */
bellard33417e72003-08-10 21:47:01 +00002497int cpu_register_io_memory(int io_index,
2498 CPUReadMemoryFunc **mem_read,
bellarda4193c82004-06-03 14:01:43 +00002499 CPUWriteMemoryFunc **mem_write,
2500 void *opaque)
bellard33417e72003-08-10 21:47:01 +00002501{
blueswir14254fab2008-01-01 16:57:19 +00002502 int i, subwidth = 0;
bellard33417e72003-08-10 21:47:01 +00002503
2504 if (io_index <= 0) {
bellardb5ff1b32005-11-26 10:38:39 +00002505 if (io_mem_nb >= IO_MEM_NB_ENTRIES)
bellard33417e72003-08-10 21:47:01 +00002506 return -1;
2507 io_index = io_mem_nb++;
2508 } else {
2509 if (io_index >= IO_MEM_NB_ENTRIES)
2510 return -1;
2511 }
bellardb5ff1b32005-11-26 10:38:39 +00002512
bellard33417e72003-08-10 21:47:01 +00002513 for(i = 0;i < 3; i++) {
blueswir14254fab2008-01-01 16:57:19 +00002514 if (!mem_read[i] || !mem_write[i])
2515 subwidth = IO_MEM_SUBWIDTH;
bellard33417e72003-08-10 21:47:01 +00002516 io_mem_read[io_index][i] = mem_read[i];
2517 io_mem_write[io_index][i] = mem_write[i];
2518 }
bellarda4193c82004-06-03 14:01:43 +00002519 io_mem_opaque[io_index] = opaque;
blueswir14254fab2008-01-01 16:57:19 +00002520 return (io_index << IO_MEM_SHIFT) | subwidth;
bellard33417e72003-08-10 21:47:01 +00002521}
bellard61382a52003-10-27 21:22:23 +00002522
bellard8926b512004-10-10 15:14:20 +00002523CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index)
2524{
2525 return io_mem_write[io_index >> IO_MEM_SHIFT];
2526}
2527
2528CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index)
2529{
2530 return io_mem_read[io_index >> IO_MEM_SHIFT];
2531}
2532
bellard13eb76e2004-01-24 15:23:36 +00002533/* physical memory access (slow version, mainly for debug) */
2534#if defined(CONFIG_USER_ONLY)
ths5fafdf22007-09-16 21:08:06 +00002535void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
bellard13eb76e2004-01-24 15:23:36 +00002536 int len, int is_write)
2537{
2538 int l, flags;
2539 target_ulong page;
pbrook53a59602006-03-25 19:31:22 +00002540 void * p;
bellard13eb76e2004-01-24 15:23:36 +00002541
2542 while (len > 0) {
2543 page = addr & TARGET_PAGE_MASK;
2544 l = (page + TARGET_PAGE_SIZE) - addr;
2545 if (l > len)
2546 l = len;
2547 flags = page_get_flags(page);
2548 if (!(flags & PAGE_VALID))
2549 return;
2550 if (is_write) {
2551 if (!(flags & PAGE_WRITE))
2552 return;
bellard579a97f2007-11-11 14:26:47 +00002553 /* XXX: this code should not depend on lock_user */
2554 if (!(p = lock_user(VERIFY_WRITE, addr, len, 0)))
2555 /* FIXME - should this return an error rather than just fail? */
2556 return;
pbrook53a59602006-03-25 19:31:22 +00002557 memcpy(p, buf, len);
2558 unlock_user(p, addr, len);
bellard13eb76e2004-01-24 15:23:36 +00002559 } else {
2560 if (!(flags & PAGE_READ))
2561 return;
bellard579a97f2007-11-11 14:26:47 +00002562 /* XXX: this code should not depend on lock_user */
2563 if (!(p = lock_user(VERIFY_READ, addr, len, 1)))
2564 /* FIXME - should this return an error rather than just fail? */
2565 return;
pbrook53a59602006-03-25 19:31:22 +00002566 memcpy(buf, p, len);
2567 unlock_user(p, addr, 0);
bellard13eb76e2004-01-24 15:23:36 +00002568 }
2569 len -= l;
2570 buf += l;
2571 addr += l;
2572 }
2573}
bellard8df1cd02005-01-28 22:37:22 +00002574
bellard13eb76e2004-01-24 15:23:36 +00002575#else
ths5fafdf22007-09-16 21:08:06 +00002576void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
bellard13eb76e2004-01-24 15:23:36 +00002577 int len, int is_write)
2578{
2579 int l, io_index;
2580 uint8_t *ptr;
2581 uint32_t val;
bellard2e126692004-04-25 21:28:44 +00002582 target_phys_addr_t page;
2583 unsigned long pd;
bellard92e873b2004-05-21 14:52:29 +00002584 PhysPageDesc *p;
ths3b46e622007-09-17 08:09:54 +00002585
bellard13eb76e2004-01-24 15:23:36 +00002586 while (len > 0) {
2587 page = addr & TARGET_PAGE_MASK;
2588 l = (page + TARGET_PAGE_SIZE) - addr;
2589 if (l > len)
2590 l = len;
bellard92e873b2004-05-21 14:52:29 +00002591 p = phys_page_find(page >> TARGET_PAGE_BITS);
bellard13eb76e2004-01-24 15:23:36 +00002592 if (!p) {
2593 pd = IO_MEM_UNASSIGNED;
2594 } else {
2595 pd = p->phys_offset;
2596 }
ths3b46e622007-09-17 08:09:54 +00002597
bellard13eb76e2004-01-24 15:23:36 +00002598 if (is_write) {
bellard3a7d9292005-08-21 09:26:42 +00002599 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
bellard13eb76e2004-01-24 15:23:36 +00002600 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
bellard6a00d602005-11-21 23:25:50 +00002601 /* XXX: could force cpu_single_env to NULL to avoid
2602 potential bugs */
bellard13eb76e2004-01-24 15:23:36 +00002603 if (l >= 4 && ((addr & 3) == 0)) {
bellard1c213d12005-09-03 10:49:04 +00002604 /* 32 bit write access */
bellardc27004e2005-01-03 23:35:10 +00002605 val = ldl_p(buf);
bellarda4193c82004-06-03 14:01:43 +00002606 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
bellard13eb76e2004-01-24 15:23:36 +00002607 l = 4;
2608 } else if (l >= 2 && ((addr & 1) == 0)) {
bellard1c213d12005-09-03 10:49:04 +00002609 /* 16 bit write access */
bellardc27004e2005-01-03 23:35:10 +00002610 val = lduw_p(buf);
bellarda4193c82004-06-03 14:01:43 +00002611 io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
bellard13eb76e2004-01-24 15:23:36 +00002612 l = 2;
2613 } else {
bellard1c213d12005-09-03 10:49:04 +00002614 /* 8 bit write access */
bellardc27004e2005-01-03 23:35:10 +00002615 val = ldub_p(buf);
bellarda4193c82004-06-03 14:01:43 +00002616 io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val);
bellard13eb76e2004-01-24 15:23:36 +00002617 l = 1;
2618 }
2619 } else {
bellardb448f2f2004-02-25 23:24:04 +00002620 unsigned long addr1;
2621 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
bellard13eb76e2004-01-24 15:23:36 +00002622 /* RAM case */
bellardb448f2f2004-02-25 23:24:04 +00002623 ptr = phys_ram_base + addr1;
bellard13eb76e2004-01-24 15:23:36 +00002624 memcpy(ptr, buf, l);
bellard3a7d9292005-08-21 09:26:42 +00002625 if (!cpu_physical_memory_is_dirty(addr1)) {
2626 /* invalidate code */
2627 tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
2628 /* set dirty bit */
ths5fafdf22007-09-16 21:08:06 +00002629 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
bellardf23db162005-08-21 19:12:28 +00002630 (0xff & ~CODE_DIRTY_FLAG);
bellard3a7d9292005-08-21 09:26:42 +00002631 }
bellard13eb76e2004-01-24 15:23:36 +00002632 }
2633 } else {
ths5fafdf22007-09-16 21:08:06 +00002634 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
bellard2a4188a2006-06-25 21:54:59 +00002635 !(pd & IO_MEM_ROMD)) {
bellard13eb76e2004-01-24 15:23:36 +00002636 /* I/O case */
2637 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2638 if (l >= 4 && ((addr & 3) == 0)) {
2639 /* 32 bit read access */
bellarda4193c82004-06-03 14:01:43 +00002640 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
bellardc27004e2005-01-03 23:35:10 +00002641 stl_p(buf, val);
bellard13eb76e2004-01-24 15:23:36 +00002642 l = 4;
2643 } else if (l >= 2 && ((addr & 1) == 0)) {
2644 /* 16 bit read access */
bellarda4193c82004-06-03 14:01:43 +00002645 val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
bellardc27004e2005-01-03 23:35:10 +00002646 stw_p(buf, val);
bellard13eb76e2004-01-24 15:23:36 +00002647 l = 2;
2648 } else {
bellard1c213d12005-09-03 10:49:04 +00002649 /* 8 bit read access */
bellarda4193c82004-06-03 14:01:43 +00002650 val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr);
bellardc27004e2005-01-03 23:35:10 +00002651 stb_p(buf, val);
bellard13eb76e2004-01-24 15:23:36 +00002652 l = 1;
2653 }
2654 } else {
2655 /* RAM case */
ths5fafdf22007-09-16 21:08:06 +00002656 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
bellard13eb76e2004-01-24 15:23:36 +00002657 (addr & ~TARGET_PAGE_MASK);
2658 memcpy(buf, ptr, l);
2659 }
2660 }
2661 len -= l;
2662 buf += l;
2663 addr += l;
2664 }
2665}
bellard8df1cd02005-01-28 22:37:22 +00002666
bellardd0ecd2a2006-04-23 17:14:48 +00002667/* used for ROM loading : can write in RAM and ROM */
ths5fafdf22007-09-16 21:08:06 +00002668void cpu_physical_memory_write_rom(target_phys_addr_t addr,
bellardd0ecd2a2006-04-23 17:14:48 +00002669 const uint8_t *buf, int len)
2670{
2671 int l;
2672 uint8_t *ptr;
2673 target_phys_addr_t page;
2674 unsigned long pd;
2675 PhysPageDesc *p;
ths3b46e622007-09-17 08:09:54 +00002676
bellardd0ecd2a2006-04-23 17:14:48 +00002677 while (len > 0) {
2678 page = addr & TARGET_PAGE_MASK;
2679 l = (page + TARGET_PAGE_SIZE) - addr;
2680 if (l > len)
2681 l = len;
2682 p = phys_page_find(page >> TARGET_PAGE_BITS);
2683 if (!p) {
2684 pd = IO_MEM_UNASSIGNED;
2685 } else {
2686 pd = p->phys_offset;
2687 }
ths3b46e622007-09-17 08:09:54 +00002688
bellardd0ecd2a2006-04-23 17:14:48 +00002689 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
bellard2a4188a2006-06-25 21:54:59 +00002690 (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
2691 !(pd & IO_MEM_ROMD)) {
bellardd0ecd2a2006-04-23 17:14:48 +00002692 /* do nothing */
2693 } else {
2694 unsigned long addr1;
2695 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2696 /* ROM/RAM case */
2697 ptr = phys_ram_base + addr1;
2698 memcpy(ptr, buf, l);
2699 }
2700 len -= l;
2701 buf += l;
2702 addr += l;
2703 }
2704}
2705
2706
bellard8df1cd02005-01-28 22:37:22 +00002707/* warning: addr must be aligned */
2708uint32_t ldl_phys(target_phys_addr_t addr)
2709{
2710 int io_index;
2711 uint8_t *ptr;
2712 uint32_t val;
2713 unsigned long pd;
2714 PhysPageDesc *p;
2715
2716 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2717 if (!p) {
2718 pd = IO_MEM_UNASSIGNED;
2719 } else {
2720 pd = p->phys_offset;
2721 }
ths3b46e622007-09-17 08:09:54 +00002722
ths5fafdf22007-09-16 21:08:06 +00002723 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
bellard2a4188a2006-06-25 21:54:59 +00002724 !(pd & IO_MEM_ROMD)) {
bellard8df1cd02005-01-28 22:37:22 +00002725 /* I/O case */
2726 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2727 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2728 } else {
2729 /* RAM case */
ths5fafdf22007-09-16 21:08:06 +00002730 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
bellard8df1cd02005-01-28 22:37:22 +00002731 (addr & ~TARGET_PAGE_MASK);
2732 val = ldl_p(ptr);
2733 }
2734 return val;
2735}
2736
bellard84b7b8e2005-11-28 21:19:04 +00002737/* warning: addr must be aligned */
2738uint64_t ldq_phys(target_phys_addr_t addr)
2739{
2740 int io_index;
2741 uint8_t *ptr;
2742 uint64_t val;
2743 unsigned long pd;
2744 PhysPageDesc *p;
2745
2746 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2747 if (!p) {
2748 pd = IO_MEM_UNASSIGNED;
2749 } else {
2750 pd = p->phys_offset;
2751 }
ths3b46e622007-09-17 08:09:54 +00002752
bellard2a4188a2006-06-25 21:54:59 +00002753 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
2754 !(pd & IO_MEM_ROMD)) {
bellard84b7b8e2005-11-28 21:19:04 +00002755 /* I/O case */
2756 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2757#ifdef TARGET_WORDS_BIGENDIAN
2758 val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
2759 val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
2760#else
2761 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2762 val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
2763#endif
2764 } else {
2765 /* RAM case */
ths5fafdf22007-09-16 21:08:06 +00002766 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
bellard84b7b8e2005-11-28 21:19:04 +00002767 (addr & ~TARGET_PAGE_MASK);
2768 val = ldq_p(ptr);
2769 }
2770 return val;
2771}
2772
bellardaab33092005-10-30 20:48:42 +00002773/* XXX: optimize */
2774uint32_t ldub_phys(target_phys_addr_t addr)
2775{
2776 uint8_t val;
2777 cpu_physical_memory_read(addr, &val, 1);
2778 return val;
2779}
2780
2781/* XXX: optimize */
2782uint32_t lduw_phys(target_phys_addr_t addr)
2783{
2784 uint16_t val;
2785 cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
2786 return tswap16(val);
2787}
2788
bellard8df1cd02005-01-28 22:37:22 +00002789/* warning: addr must be aligned. The ram page is not masked as dirty
2790 and the code inside is not invalidated. It is useful if the dirty
2791 bits are used to track modified PTEs */
2792void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
2793{
2794 int io_index;
2795 uint8_t *ptr;
2796 unsigned long pd;
2797 PhysPageDesc *p;
2798
2799 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2800 if (!p) {
2801 pd = IO_MEM_UNASSIGNED;
2802 } else {
2803 pd = p->phys_offset;
2804 }
ths3b46e622007-09-17 08:09:54 +00002805
bellard3a7d9292005-08-21 09:26:42 +00002806 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
bellard8df1cd02005-01-28 22:37:22 +00002807 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2808 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2809 } else {
ths5fafdf22007-09-16 21:08:06 +00002810 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
bellard8df1cd02005-01-28 22:37:22 +00002811 (addr & ~TARGET_PAGE_MASK);
2812 stl_p(ptr, val);
2813 }
2814}
2815
j_mayerbc98a7e2007-04-04 07:55:12 +00002816void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
2817{
2818 int io_index;
2819 uint8_t *ptr;
2820 unsigned long pd;
2821 PhysPageDesc *p;
2822
2823 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2824 if (!p) {
2825 pd = IO_MEM_UNASSIGNED;
2826 } else {
2827 pd = p->phys_offset;
2828 }
ths3b46e622007-09-17 08:09:54 +00002829
j_mayerbc98a7e2007-04-04 07:55:12 +00002830 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2831 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2832#ifdef TARGET_WORDS_BIGENDIAN
2833 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
2834 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
2835#else
2836 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2837 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
2838#endif
2839 } else {
ths5fafdf22007-09-16 21:08:06 +00002840 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
j_mayerbc98a7e2007-04-04 07:55:12 +00002841 (addr & ~TARGET_PAGE_MASK);
2842 stq_p(ptr, val);
2843 }
2844}
2845
bellard8df1cd02005-01-28 22:37:22 +00002846/* warning: addr must be aligned */
bellard8df1cd02005-01-28 22:37:22 +00002847void stl_phys(target_phys_addr_t addr, uint32_t val)
2848{
2849 int io_index;
2850 uint8_t *ptr;
2851 unsigned long pd;
2852 PhysPageDesc *p;
2853
2854 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2855 if (!p) {
2856 pd = IO_MEM_UNASSIGNED;
2857 } else {
2858 pd = p->phys_offset;
2859 }
ths3b46e622007-09-17 08:09:54 +00002860
bellard3a7d9292005-08-21 09:26:42 +00002861 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
bellard8df1cd02005-01-28 22:37:22 +00002862 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2863 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2864 } else {
2865 unsigned long addr1;
2866 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2867 /* RAM case */
2868 ptr = phys_ram_base + addr1;
2869 stl_p(ptr, val);
bellard3a7d9292005-08-21 09:26:42 +00002870 if (!cpu_physical_memory_is_dirty(addr1)) {
2871 /* invalidate code */
2872 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
2873 /* set dirty bit */
bellardf23db162005-08-21 19:12:28 +00002874 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
2875 (0xff & ~CODE_DIRTY_FLAG);
bellard3a7d9292005-08-21 09:26:42 +00002876 }
bellard8df1cd02005-01-28 22:37:22 +00002877 }
2878}
2879
bellardaab33092005-10-30 20:48:42 +00002880/* XXX: optimize */
2881void stb_phys(target_phys_addr_t addr, uint32_t val)
2882{
2883 uint8_t v = val;
2884 cpu_physical_memory_write(addr, &v, 1);
2885}
2886
2887/* XXX: optimize */
2888void stw_phys(target_phys_addr_t addr, uint32_t val)
2889{
2890 uint16_t v = tswap16(val);
2891 cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
2892}
2893
2894/* XXX: optimize */
2895void stq_phys(target_phys_addr_t addr, uint64_t val)
2896{
2897 val = tswap64(val);
2898 cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
2899}
2900
bellard13eb76e2004-01-24 15:23:36 +00002901#endif
2902
2903/* virtual memory access for debug */
ths5fafdf22007-09-16 21:08:06 +00002904int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
bellardb448f2f2004-02-25 23:24:04 +00002905 uint8_t *buf, int len, int is_write)
bellard13eb76e2004-01-24 15:23:36 +00002906{
2907 int l;
j_mayer9b3c35e2007-04-07 11:21:28 +00002908 target_phys_addr_t phys_addr;
2909 target_ulong page;
bellard13eb76e2004-01-24 15:23:36 +00002910
2911 while (len > 0) {
2912 page = addr & TARGET_PAGE_MASK;
2913 phys_addr = cpu_get_phys_page_debug(env, page);
2914 /* if no physical page mapped, return an error */
2915 if (phys_addr == -1)
2916 return -1;
2917 l = (page + TARGET_PAGE_SIZE) - addr;
2918 if (l > len)
2919 l = len;
ths5fafdf22007-09-16 21:08:06 +00002920 cpu_physical_memory_rw(phys_addr + (addr & ~TARGET_PAGE_MASK),
bellardb448f2f2004-02-25 23:24:04 +00002921 buf, l, is_write);
bellard13eb76e2004-01-24 15:23:36 +00002922 len -= l;
2923 buf += l;
2924 addr += l;
2925 }
2926 return 0;
2927}
2928
bellarde3db7222005-01-26 22:00:47 +00002929void dump_exec_info(FILE *f,
2930 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2931{
2932 int i, target_code_size, max_target_code_size;
2933 int direct_jmp_count, direct_jmp2_count, cross_page;
2934 TranslationBlock *tb;
ths3b46e622007-09-17 08:09:54 +00002935
bellarde3db7222005-01-26 22:00:47 +00002936 target_code_size = 0;
2937 max_target_code_size = 0;
2938 cross_page = 0;
2939 direct_jmp_count = 0;
2940 direct_jmp2_count = 0;
2941 for(i = 0; i < nb_tbs; i++) {
2942 tb = &tbs[i];
2943 target_code_size += tb->size;
2944 if (tb->size > max_target_code_size)
2945 max_target_code_size = tb->size;
2946 if (tb->page_addr[1] != -1)
2947 cross_page++;
2948 if (tb->tb_next_offset[0] != 0xffff) {
2949 direct_jmp_count++;
2950 if (tb->tb_next_offset[1] != 0xffff) {
2951 direct_jmp2_count++;
2952 }
2953 }
2954 }
2955 /* XXX: avoid using doubles ? */
bellard57fec1f2008-02-01 10:50:11 +00002956 cpu_fprintf(f, "Translation buffer state:\n");
bellarde3db7222005-01-26 22:00:47 +00002957 cpu_fprintf(f, "TB count %d\n", nb_tbs);
ths5fafdf22007-09-16 21:08:06 +00002958 cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
bellarde3db7222005-01-26 22:00:47 +00002959 nb_tbs ? target_code_size / nb_tbs : 0,
2960 max_target_code_size);
ths5fafdf22007-09-16 21:08:06 +00002961 cpu_fprintf(f, "TB avg host size %d bytes (expansion ratio: %0.1f)\n",
bellarde3db7222005-01-26 22:00:47 +00002962 nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
2963 target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
ths5fafdf22007-09-16 21:08:06 +00002964 cpu_fprintf(f, "cross page TB count %d (%d%%)\n",
2965 cross_page,
bellarde3db7222005-01-26 22:00:47 +00002966 nb_tbs ? (cross_page * 100) / nb_tbs : 0);
2967 cpu_fprintf(f, "direct jump count %d (%d%%) (2 jumps=%d %d%%)\n",
ths5fafdf22007-09-16 21:08:06 +00002968 direct_jmp_count,
bellarde3db7222005-01-26 22:00:47 +00002969 nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
2970 direct_jmp2_count,
2971 nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
bellard57fec1f2008-02-01 10:50:11 +00002972 cpu_fprintf(f, "\nStatistics:\n");
bellarde3db7222005-01-26 22:00:47 +00002973 cpu_fprintf(f, "TB flush count %d\n", tb_flush_count);
2974 cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
2975 cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count);
bellard57fec1f2008-02-01 10:50:11 +00002976#ifdef CONFIG_PROFILER
2977 {
2978 int64_t tot;
2979 tot = dyngen_interm_time + dyngen_code_time;
2980 cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2981 tot, tot / 2.4e9);
2982 cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
2983 dyngen_tb_count,
2984 dyngen_tb_count1 - dyngen_tb_count,
2985 dyngen_tb_count1 ? (double)(dyngen_tb_count1 - dyngen_tb_count) / dyngen_tb_count1 * 100.0 : 0);
2986 cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
2987 dyngen_tb_count ? (double)dyngen_op_count / dyngen_tb_count : 0, dyngen_op_count_max);
2988 cpu_fprintf(f, "old ops/total ops %0.1f%%\n",
2989 dyngen_op_count ? (double)dyngen_old_op_count / dyngen_op_count * 100.0 : 0);
2990 cpu_fprintf(f, "deleted ops/TB %0.2f\n",
2991 dyngen_tb_count ?
2992 (double)dyngen_tcg_del_op_count / dyngen_tb_count : 0);
2993 cpu_fprintf(f, "cycles/op %0.1f\n",
2994 dyngen_op_count ? (double)tot / dyngen_op_count : 0);
2995 cpu_fprintf(f, "cycles/in byte %0.1f\n",
2996 dyngen_code_in_len ? (double)tot / dyngen_code_in_len : 0);
2997 cpu_fprintf(f, "cycles/out byte %0.1f\n",
2998 dyngen_code_out_len ? (double)tot / dyngen_code_out_len : 0);
2999 if (tot == 0)
3000 tot = 1;
3001 cpu_fprintf(f, " gen_interm time %0.1f%%\n",
3002 (double)dyngen_interm_time / tot * 100.0);
3003 cpu_fprintf(f, " gen_code time %0.1f%%\n",
3004 (double)dyngen_code_time / tot * 100.0);
3005 cpu_fprintf(f, "cpu_restore count %" PRId64 "\n",
3006 dyngen_restore_count);
3007 cpu_fprintf(f, " avg cycles %0.1f\n",
3008 dyngen_restore_count ? (double)dyngen_restore_time / dyngen_restore_count : 0);
3009 {
3010 extern void dump_op_count(void);
3011 dump_op_count();
3012 }
3013 }
3014#endif
bellarde3db7222005-01-26 22:00:47 +00003015}
3016
ths5fafdf22007-09-16 21:08:06 +00003017#if !defined(CONFIG_USER_ONLY)
bellard61382a52003-10-27 21:22:23 +00003018
3019#define MMUSUFFIX _cmmu
3020#define GETPC() NULL
3021#define env cpu_single_env
bellardb769d8f2004-10-03 15:07:13 +00003022#define SOFTMMU_CODE_ACCESS
bellard61382a52003-10-27 21:22:23 +00003023
3024#define SHIFT 0
3025#include "softmmu_template.h"
3026
3027#define SHIFT 1
3028#include "softmmu_template.h"
3029
3030#define SHIFT 2
3031#include "softmmu_template.h"
3032
3033#define SHIFT 3
3034#include "softmmu_template.h"
3035
3036#undef env
3037
3038#endif