blob: f02abe068d4925332cf72a5fb1abd9498986dbf7 [file] [log] [blame]
bellard54936002003-05-13 00:25:15 +00001/*
bellardfd6ce8f2003-05-14 19:00:11 +00002 * virtual page mapping and translated block handling
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard54936002003-05-13 00:25:15 +00004 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
bellard67b915a2004-03-31 23:37:16 +000020#include "config.h"
bellardd5a8f072004-09-29 21:15:28 +000021#ifdef _WIN32
ths4fddf622007-12-17 04:42:29 +000022#define WIN32_LEAN_AND_MEAN
bellardd5a8f072004-09-29 21:15:28 +000023#include <windows.h>
24#else
bellarda98d49b2004-11-14 16:22:05 +000025#include <sys/types.h>
bellardd5a8f072004-09-29 21:15:28 +000026#include <sys/mman.h>
27#endif
bellard54936002003-05-13 00:25:15 +000028#include <stdlib.h>
29#include <stdio.h>
30#include <stdarg.h>
31#include <string.h>
32#include <errno.h>
33#include <unistd.h>
34#include <inttypes.h>
35
bellard6180a182003-09-30 21:04:53 +000036#include "cpu.h"
37#include "exec-all.h"
aurel32ca10f862008-04-11 21:35:42 +000038#include "qemu-common.h"
bellardb67d9a52008-05-23 09:57:34 +000039#include "tcg.h"
pbrookb3c77242008-06-30 16:31:04 +000040#include "hw/hw.h"
pbrook53a59602006-03-25 19:31:22 +000041#if defined(CONFIG_USER_ONLY)
42#include <qemu.h>
43#endif
bellard54936002003-05-13 00:25:15 +000044
bellardfd6ce8f2003-05-14 19:00:11 +000045//#define DEBUG_TB_INVALIDATE
bellard66e85a22003-06-24 13:28:12 +000046//#define DEBUG_FLUSH
bellard9fa3e852004-01-04 18:06:42 +000047//#define DEBUG_TLB
pbrook67d3b952006-12-18 05:03:52 +000048//#define DEBUG_UNASSIGNED
bellardfd6ce8f2003-05-14 19:00:11 +000049
50/* make various TB consistency checks */
ths5fafdf22007-09-16 21:08:06 +000051//#define DEBUG_TB_CHECK
52//#define DEBUG_TLB_CHECK
bellardfd6ce8f2003-05-14 19:00:11 +000053
ths1196be32007-03-17 15:17:58 +000054//#define DEBUG_IOPORT
blueswir1db7b5422007-05-26 17:36:03 +000055//#define DEBUG_SUBPAGE
ths1196be32007-03-17 15:17:58 +000056
pbrook99773bd2006-04-16 15:14:59 +000057#if !defined(CONFIG_USER_ONLY)
58/* TB consistency checks only implemented for usermode emulation. */
59#undef DEBUG_TB_CHECK
60#endif
61
bellard9fa3e852004-01-04 18:06:42 +000062#define SMC_BITMAP_USE_THRESHOLD 10
63
64#define MMAP_AREA_START 0x00000000
65#define MMAP_AREA_END 0xa8000000
bellardfd6ce8f2003-05-14 19:00:11 +000066
bellard108c49b2005-07-24 12:55:09 +000067#if defined(TARGET_SPARC64)
68#define TARGET_PHYS_ADDR_SPACE_BITS 41
blueswir15dcb6b92007-05-19 12:58:30 +000069#elif defined(TARGET_SPARC)
70#define TARGET_PHYS_ADDR_SPACE_BITS 36
j_mayerbedb69e2007-04-05 20:08:21 +000071#elif defined(TARGET_ALPHA)
72#define TARGET_PHYS_ADDR_SPACE_BITS 42
73#define TARGET_VIRT_ADDR_SPACE_BITS 42
bellard108c49b2005-07-24 12:55:09 +000074#elif defined(TARGET_PPC64)
75#define TARGET_PHYS_ADDR_SPACE_BITS 42
aurel3200f82b82008-04-27 21:12:55 +000076#elif defined(TARGET_X86_64) && !defined(USE_KQEMU)
77#define TARGET_PHYS_ADDR_SPACE_BITS 42
78#elif defined(TARGET_I386) && !defined(USE_KQEMU)
79#define TARGET_PHYS_ADDR_SPACE_BITS 36
bellard108c49b2005-07-24 12:55:09 +000080#else
81/* Note: for compatibility with kqemu, we use 32 bits for x86_64 */
82#define TARGET_PHYS_ADDR_SPACE_BITS 32
83#endif
84
pbrookfab94c02008-05-24 13:56:15 +000085TranslationBlock *tbs;
bellard26a5f132008-05-28 12:30:31 +000086int 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
bellard7cb69ca2008-05-10 10:55:51 +000092uint8_t code_gen_prologue[1024] __attribute__((aligned (32)));
bellard26a5f132008-05-28 12:30:31 +000093uint8_t *code_gen_buffer;
94unsigned long code_gen_buffer_size;
95/* threshold to flush the translated code buffer */
96unsigned long code_gen_buffer_max_size;
bellardfd6ce8f2003-05-14 19:00:11 +000097uint8_t *code_gen_ptr;
98
pbrooke2eef172008-06-08 01:09:01 +000099#if !defined(CONFIG_USER_ONLY)
aurel3200f82b82008-04-27 21:12:55 +0000100ram_addr_t phys_ram_size;
bellard9fa3e852004-01-04 18:06:42 +0000101int phys_ram_fd;
102uint8_t *phys_ram_base;
bellard1ccde1c2004-02-06 19:46:14 +0000103uint8_t *phys_ram_dirty;
bellarde9a1ab12007-02-08 23:08:38 +0000104static ram_addr_t phys_ram_alloc_offset = 0;
pbrooke2eef172008-06-08 01:09:01 +0000105#endif
bellard9fa3e852004-01-04 18:06:42 +0000106
bellard6a00d602005-11-21 23:25:50 +0000107CPUState *first_cpu;
108/* current CPU in the current thread. It is only valid inside
109 cpu_exec() */
ths5fafdf22007-09-16 21:08:06 +0000110CPUState *cpu_single_env;
pbrook2e70f6e2008-06-29 01:03:05 +0000111/* 0 = Do not count executed instructions.
thsbf20dc02008-06-30 17:22:19 +0000112 1 = Precise instruction counting.
pbrook2e70f6e2008-06-29 01:03:05 +0000113 2 = Adaptive rate instruction counting. */
114int use_icount = 0;
115/* Current instruction counter. While executing translated code this may
116 include some instructions that have not yet been executed. */
117int64_t qemu_icount;
bellard6a00d602005-11-21 23:25:50 +0000118
bellard54936002003-05-13 00:25:15 +0000119typedef struct PageDesc {
bellard92e873b2004-05-21 14:52:29 +0000120 /* list of TBs intersecting this ram page */
bellardfd6ce8f2003-05-14 19:00:11 +0000121 TranslationBlock *first_tb;
bellard9fa3e852004-01-04 18:06:42 +0000122 /* in order to optimize self modifying code, we count the number
123 of lookups we do to a given page to use a bitmap */
124 unsigned int code_write_count;
125 uint8_t *code_bitmap;
126#if defined(CONFIG_USER_ONLY)
127 unsigned long flags;
128#endif
bellard54936002003-05-13 00:25:15 +0000129} PageDesc;
130
bellard92e873b2004-05-21 14:52:29 +0000131typedef struct PhysPageDesc {
pbrook0f459d12008-06-09 00:20:13 +0000132 /* offset in host memory of the page + io_index in the low bits */
aurel3200f82b82008-04-27 21:12:55 +0000133 ram_addr_t phys_offset;
bellard92e873b2004-05-21 14:52:29 +0000134} PhysPageDesc;
135
bellard54936002003-05-13 00:25:15 +0000136#define L2_BITS 10
j_mayerbedb69e2007-04-05 20:08:21 +0000137#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
138/* XXX: this is a temporary hack for alpha target.
139 * In the future, this is to be replaced by a multi-level table
140 * to actually be able to handle the complete 64 bits address space.
141 */
142#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
143#else
aurel3203875442008-04-22 20:45:18 +0000144#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
j_mayerbedb69e2007-04-05 20:08:21 +0000145#endif
bellard54936002003-05-13 00:25:15 +0000146
147#define L1_SIZE (1 << L1_BITS)
148#define L2_SIZE (1 << L2_BITS)
149
bellard83fb7ad2004-07-05 21:25:26 +0000150unsigned long qemu_real_host_page_size;
151unsigned long qemu_host_page_bits;
152unsigned long qemu_host_page_size;
153unsigned long qemu_host_page_mask;
bellard54936002003-05-13 00:25:15 +0000154
bellard92e873b2004-05-21 14:52:29 +0000155/* XXX: for system emulation, it could just be an array */
bellard54936002003-05-13 00:25:15 +0000156static PageDesc *l1_map[L1_SIZE];
bellard0a962c02005-02-10 22:00:27 +0000157PhysPageDesc **l1_phys_map;
bellard54936002003-05-13 00:25:15 +0000158
pbrooke2eef172008-06-08 01:09:01 +0000159#if !defined(CONFIG_USER_ONLY)
160static void io_mem_init(void);
161
bellard33417e72003-08-10 21:47:01 +0000162/* io memory support */
bellard33417e72003-08-10 21:47:01 +0000163CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
164CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
bellarda4193c82004-06-03 14:01:43 +0000165void *io_mem_opaque[IO_MEM_NB_ENTRIES];
bellard33417e72003-08-10 21:47:01 +0000166static int io_mem_nb;
pbrook6658ffb2007-03-16 23:58:11 +0000167static int io_mem_watch;
168#endif
bellard33417e72003-08-10 21:47:01 +0000169
bellard34865132003-10-05 14:28:56 +0000170/* log support */
171char *logfilename = "/tmp/qemu.log";
172FILE *logfile;
173int loglevel;
pbrooke735b912007-06-30 13:53:24 +0000174static int log_append = 0;
bellard34865132003-10-05 14:28:56 +0000175
bellarde3db7222005-01-26 22:00:47 +0000176/* statistics */
177static int tlb_flush_count;
178static int tb_flush_count;
179static int tb_phys_invalidate_count;
180
blueswir1db7b5422007-05-26 17:36:03 +0000181#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
182typedef struct subpage_t {
183 target_phys_addr_t base;
blueswir13ee89922008-01-02 19:45:26 +0000184 CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE][4];
185 CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE][4];
186 void *opaque[TARGET_PAGE_SIZE][2][4];
blueswir1db7b5422007-05-26 17:36:03 +0000187} subpage_t;
188
bellard7cb69ca2008-05-10 10:55:51 +0000189#ifdef _WIN32
190static void map_exec(void *addr, long size)
191{
192 DWORD old_protect;
193 VirtualProtect(addr, size,
194 PAGE_EXECUTE_READWRITE, &old_protect);
195
196}
197#else
198static void map_exec(void *addr, long size)
199{
bellard43694152008-05-29 09:35:57 +0000200 unsigned long start, end, page_size;
bellard7cb69ca2008-05-10 10:55:51 +0000201
bellard43694152008-05-29 09:35:57 +0000202 page_size = getpagesize();
bellard7cb69ca2008-05-10 10:55:51 +0000203 start = (unsigned long)addr;
bellard43694152008-05-29 09:35:57 +0000204 start &= ~(page_size - 1);
bellard7cb69ca2008-05-10 10:55:51 +0000205
206 end = (unsigned long)addr + size;
bellard43694152008-05-29 09:35:57 +0000207 end += page_size - 1;
208 end &= ~(page_size - 1);
bellard7cb69ca2008-05-10 10:55:51 +0000209
210 mprotect((void *)start, end - start,
211 PROT_READ | PROT_WRITE | PROT_EXEC);
212}
213#endif
214
bellardb346ff42003-06-15 20:05:50 +0000215static void page_init(void)
bellard54936002003-05-13 00:25:15 +0000216{
bellard83fb7ad2004-07-05 21:25:26 +0000217 /* NOTE: we can always suppose that qemu_host_page_size >=
bellard54936002003-05-13 00:25:15 +0000218 TARGET_PAGE_SIZE */
bellard67b915a2004-03-31 23:37:16 +0000219#ifdef _WIN32
bellardd5a8f072004-09-29 21:15:28 +0000220 {
221 SYSTEM_INFO system_info;
222 DWORD old_protect;
ths3b46e622007-09-17 08:09:54 +0000223
bellardd5a8f072004-09-29 21:15:28 +0000224 GetSystemInfo(&system_info);
225 qemu_real_host_page_size = system_info.dwPageSize;
bellardd5a8f072004-09-29 21:15:28 +0000226 }
bellard67b915a2004-03-31 23:37:16 +0000227#else
bellard83fb7ad2004-07-05 21:25:26 +0000228 qemu_real_host_page_size = getpagesize();
bellard67b915a2004-03-31 23:37:16 +0000229#endif
bellard83fb7ad2004-07-05 21:25:26 +0000230 if (qemu_host_page_size == 0)
231 qemu_host_page_size = qemu_real_host_page_size;
232 if (qemu_host_page_size < TARGET_PAGE_SIZE)
233 qemu_host_page_size = TARGET_PAGE_SIZE;
234 qemu_host_page_bits = 0;
235 while ((1 << qemu_host_page_bits) < qemu_host_page_size)
236 qemu_host_page_bits++;
237 qemu_host_page_mask = ~(qemu_host_page_size - 1);
bellard108c49b2005-07-24 12:55:09 +0000238 l1_phys_map = qemu_vmalloc(L1_SIZE * sizeof(void *));
239 memset(l1_phys_map, 0, L1_SIZE * sizeof(void *));
balrog50a95692007-12-12 01:16:23 +0000240
241#if !defined(_WIN32) && defined(CONFIG_USER_ONLY)
242 {
243 long long startaddr, endaddr;
244 FILE *f;
245 int n;
246
pbrookc8a706f2008-06-02 16:16:42 +0000247 mmap_lock();
pbrook07765902008-05-31 16:33:53 +0000248 last_brk = (unsigned long)sbrk(0);
balrog50a95692007-12-12 01:16:23 +0000249 f = fopen("/proc/self/maps", "r");
250 if (f) {
251 do {
252 n = fscanf (f, "%llx-%llx %*[^\n]\n", &startaddr, &endaddr);
253 if (n == 2) {
blueswir1e0b8d652008-05-03 17:51:24 +0000254 startaddr = MIN(startaddr,
255 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
256 endaddr = MIN(endaddr,
257 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
pbrookb5fc9092008-05-29 13:56:10 +0000258 page_set_flags(startaddr & TARGET_PAGE_MASK,
balrog50a95692007-12-12 01:16:23 +0000259 TARGET_PAGE_ALIGN(endaddr),
260 PAGE_RESERVED);
261 }
262 } while (!feof(f));
263 fclose(f);
264 }
pbrookc8a706f2008-06-02 16:16:42 +0000265 mmap_unlock();
balrog50a95692007-12-12 01:16:23 +0000266 }
267#endif
bellard54936002003-05-13 00:25:15 +0000268}
269
aurel3200f82b82008-04-27 21:12:55 +0000270static inline PageDesc *page_find_alloc(target_ulong index)
bellard54936002003-05-13 00:25:15 +0000271{
bellard54936002003-05-13 00:25:15 +0000272 PageDesc **lp, *p;
273
pbrook17e23772008-06-09 13:47:45 +0000274#if TARGET_LONG_BITS > 32
275 /* Host memory outside guest VM. For 32-bit targets we have already
276 excluded high addresses. */
277 if (index > ((target_ulong)L2_SIZE * L1_SIZE * TARGET_PAGE_SIZE))
278 return NULL;
279#endif
bellard54936002003-05-13 00:25:15 +0000280 lp = &l1_map[index >> L2_BITS];
281 p = *lp;
282 if (!p) {
283 /* allocate if not found */
pbrook17e23772008-06-09 13:47:45 +0000284#if defined(CONFIG_USER_ONLY)
285 unsigned long addr;
286 size_t len = sizeof(PageDesc) * L2_SIZE;
287 /* Don't use qemu_malloc because it may recurse. */
288 p = mmap(0, len, PROT_READ | PROT_WRITE,
289 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
bellard54936002003-05-13 00:25:15 +0000290 *lp = p;
pbrook17e23772008-06-09 13:47:45 +0000291 addr = h2g(p);
292 if (addr == (target_ulong)addr) {
293 page_set_flags(addr & TARGET_PAGE_MASK,
294 TARGET_PAGE_ALIGN(addr + len),
295 PAGE_RESERVED);
296 }
297#else
298 p = qemu_mallocz(sizeof(PageDesc) * L2_SIZE);
299 *lp = p;
300#endif
bellard54936002003-05-13 00:25:15 +0000301 }
302 return p + (index & (L2_SIZE - 1));
303}
304
aurel3200f82b82008-04-27 21:12:55 +0000305static inline PageDesc *page_find(target_ulong index)
bellard54936002003-05-13 00:25:15 +0000306{
bellard54936002003-05-13 00:25:15 +0000307 PageDesc *p;
308
bellard54936002003-05-13 00:25:15 +0000309 p = l1_map[index >> L2_BITS];
310 if (!p)
311 return 0;
bellardfd6ce8f2003-05-14 19:00:11 +0000312 return p + (index & (L2_SIZE - 1));
bellard54936002003-05-13 00:25:15 +0000313}
314
bellard108c49b2005-07-24 12:55:09 +0000315static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
bellard92e873b2004-05-21 14:52:29 +0000316{
bellard108c49b2005-07-24 12:55:09 +0000317 void **lp, **p;
pbrooke3f4e2a2006-04-08 20:02:06 +0000318 PhysPageDesc *pd;
bellard92e873b2004-05-21 14:52:29 +0000319
bellard108c49b2005-07-24 12:55:09 +0000320 p = (void **)l1_phys_map;
321#if TARGET_PHYS_ADDR_SPACE_BITS > 32
322
323#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
324#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
325#endif
326 lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1));
bellard92e873b2004-05-21 14:52:29 +0000327 p = *lp;
328 if (!p) {
329 /* allocate if not found */
bellard108c49b2005-07-24 12:55:09 +0000330 if (!alloc)
331 return NULL;
332 p = qemu_vmalloc(sizeof(void *) * L1_SIZE);
333 memset(p, 0, sizeof(void *) * L1_SIZE);
334 *lp = p;
335 }
336#endif
337 lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
pbrooke3f4e2a2006-04-08 20:02:06 +0000338 pd = *lp;
339 if (!pd) {
340 int i;
bellard108c49b2005-07-24 12:55:09 +0000341 /* allocate if not found */
342 if (!alloc)
343 return NULL;
pbrooke3f4e2a2006-04-08 20:02:06 +0000344 pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
345 *lp = pd;
346 for (i = 0; i < L2_SIZE; i++)
347 pd[i].phys_offset = IO_MEM_UNASSIGNED;
bellard92e873b2004-05-21 14:52:29 +0000348 }
pbrooke3f4e2a2006-04-08 20:02:06 +0000349 return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
bellard92e873b2004-05-21 14:52:29 +0000350}
351
bellard108c49b2005-07-24 12:55:09 +0000352static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
bellard92e873b2004-05-21 14:52:29 +0000353{
bellard108c49b2005-07-24 12:55:09 +0000354 return phys_page_find_alloc(index, 0);
bellard92e873b2004-05-21 14:52:29 +0000355}
356
bellard9fa3e852004-01-04 18:06:42 +0000357#if !defined(CONFIG_USER_ONLY)
bellard6a00d602005-11-21 23:25:50 +0000358static void tlb_protect_code(ram_addr_t ram_addr);
ths5fafdf22007-09-16 21:08:06 +0000359static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
bellard3a7d9292005-08-21 09:26:42 +0000360 target_ulong vaddr);
pbrookc8a706f2008-06-02 16:16:42 +0000361#define mmap_lock() do { } while(0)
362#define mmap_unlock() do { } while(0)
bellard9fa3e852004-01-04 18:06:42 +0000363#endif
bellardfd6ce8f2003-05-14 19:00:11 +0000364
bellard43694152008-05-29 09:35:57 +0000365#define DEFAULT_CODE_GEN_BUFFER_SIZE (32 * 1024 * 1024)
366
367#if defined(CONFIG_USER_ONLY)
368/* Currently it is not recommanded to allocate big chunks of data in
369 user mode. It will change when a dedicated libc will be used */
370#define USE_STATIC_CODE_GEN_BUFFER
371#endif
372
373#ifdef USE_STATIC_CODE_GEN_BUFFER
374static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE];
375#endif
376
bellard26a5f132008-05-28 12:30:31 +0000377void code_gen_alloc(unsigned long tb_size)
378{
bellard43694152008-05-29 09:35:57 +0000379#ifdef USE_STATIC_CODE_GEN_BUFFER
380 code_gen_buffer = static_code_gen_buffer;
381 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
382 map_exec(code_gen_buffer, code_gen_buffer_size);
383#else
bellard26a5f132008-05-28 12:30:31 +0000384 code_gen_buffer_size = tb_size;
385 if (code_gen_buffer_size == 0) {
bellard43694152008-05-29 09:35:57 +0000386#if defined(CONFIG_USER_ONLY)
387 /* in user mode, phys_ram_size is not meaningful */
388 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
389#else
bellard26a5f132008-05-28 12:30:31 +0000390 /* XXX: needs ajustments */
391 code_gen_buffer_size = (int)(phys_ram_size / 4);
bellard43694152008-05-29 09:35:57 +0000392#endif
bellard26a5f132008-05-28 12:30:31 +0000393 }
394 if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE)
395 code_gen_buffer_size = MIN_CODE_GEN_BUFFER_SIZE;
396 /* The code gen buffer location may have constraints depending on
397 the host cpu and OS */
398#if defined(__linux__)
399 {
400 int flags;
401 flags = MAP_PRIVATE | MAP_ANONYMOUS;
402#if defined(__x86_64__)
403 flags |= MAP_32BIT;
404 /* Cannot map more than that */
405 if (code_gen_buffer_size > (800 * 1024 * 1024))
406 code_gen_buffer_size = (800 * 1024 * 1024);
407#endif
408 code_gen_buffer = mmap(NULL, code_gen_buffer_size,
409 PROT_WRITE | PROT_READ | PROT_EXEC,
410 flags, -1, 0);
411 if (code_gen_buffer == MAP_FAILED) {
412 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
413 exit(1);
414 }
415 }
416#else
417 code_gen_buffer = qemu_malloc(code_gen_buffer_size);
418 if (!code_gen_buffer) {
419 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
420 exit(1);
421 }
422 map_exec(code_gen_buffer, code_gen_buffer_size);
423#endif
bellard43694152008-05-29 09:35:57 +0000424#endif /* !USE_STATIC_CODE_GEN_BUFFER */
bellard26a5f132008-05-28 12:30:31 +0000425 map_exec(code_gen_prologue, sizeof(code_gen_prologue));
426 code_gen_buffer_max_size = code_gen_buffer_size -
427 code_gen_max_block_size();
428 code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
429 tbs = qemu_malloc(code_gen_max_blocks * sizeof(TranslationBlock));
430}
431
432/* Must be called before using the QEMU cpus. 'tb_size' is the size
433 (in bytes) allocated to the translation buffer. Zero means default
434 size. */
435void cpu_exec_init_all(unsigned long tb_size)
436{
bellard26a5f132008-05-28 12:30:31 +0000437 cpu_gen_init();
438 code_gen_alloc(tb_size);
439 code_gen_ptr = code_gen_buffer;
bellard43694152008-05-29 09:35:57 +0000440 page_init();
pbrooke2eef172008-06-08 01:09:01 +0000441#if !defined(CONFIG_USER_ONLY)
bellard26a5f132008-05-28 12:30:31 +0000442 io_mem_init();
pbrooke2eef172008-06-08 01:09:01 +0000443#endif
bellard26a5f132008-05-28 12:30:31 +0000444}
445
pbrook9656f322008-07-01 20:01:19 +0000446#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
447
448#define CPU_COMMON_SAVE_VERSION 1
449
450static void cpu_common_save(QEMUFile *f, void *opaque)
451{
452 CPUState *env = opaque;
453
454 qemu_put_be32s(f, &env->halted);
455 qemu_put_be32s(f, &env->interrupt_request);
456}
457
458static int cpu_common_load(QEMUFile *f, void *opaque, int version_id)
459{
460 CPUState *env = opaque;
461
462 if (version_id != CPU_COMMON_SAVE_VERSION)
463 return -EINVAL;
464
465 qemu_get_be32s(f, &env->halted);
466 qemu_put_be32s(f, &env->interrupt_request);
467 tlb_flush(env, 1);
468
469 return 0;
470}
471#endif
472
bellard6a00d602005-11-21 23:25:50 +0000473void cpu_exec_init(CPUState *env)
bellardfd6ce8f2003-05-14 19:00:11 +0000474{
bellard6a00d602005-11-21 23:25:50 +0000475 CPUState **penv;
476 int cpu_index;
477
bellard6a00d602005-11-21 23:25:50 +0000478 env->next_cpu = NULL;
479 penv = &first_cpu;
480 cpu_index = 0;
481 while (*penv != NULL) {
482 penv = (CPUState **)&(*penv)->next_cpu;
483 cpu_index++;
484 }
485 env->cpu_index = cpu_index;
pbrook6658ffb2007-03-16 23:58:11 +0000486 env->nb_watchpoints = 0;
bellard6a00d602005-11-21 23:25:50 +0000487 *penv = env;
pbrookb3c77242008-06-30 16:31:04 +0000488#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
pbrook9656f322008-07-01 20:01:19 +0000489 register_savevm("cpu_common", cpu_index, CPU_COMMON_SAVE_VERSION,
490 cpu_common_save, cpu_common_load, env);
pbrookb3c77242008-06-30 16:31:04 +0000491 register_savevm("cpu", cpu_index, CPU_SAVE_VERSION,
492 cpu_save, cpu_load, env);
493#endif
bellardfd6ce8f2003-05-14 19:00:11 +0000494}
495
bellard9fa3e852004-01-04 18:06:42 +0000496static inline void invalidate_page_bitmap(PageDesc *p)
497{
498 if (p->code_bitmap) {
bellard59817cc2004-02-16 22:01:13 +0000499 qemu_free(p->code_bitmap);
bellard9fa3e852004-01-04 18:06:42 +0000500 p->code_bitmap = NULL;
501 }
502 p->code_write_count = 0;
503}
504
bellardfd6ce8f2003-05-14 19:00:11 +0000505/* set to NULL all the 'first_tb' fields in all PageDescs */
506static void page_flush_tb(void)
507{
508 int i, j;
509 PageDesc *p;
510
511 for(i = 0; i < L1_SIZE; i++) {
512 p = l1_map[i];
513 if (p) {
bellard9fa3e852004-01-04 18:06:42 +0000514 for(j = 0; j < L2_SIZE; j++) {
515 p->first_tb = NULL;
516 invalidate_page_bitmap(p);
517 p++;
518 }
bellardfd6ce8f2003-05-14 19:00:11 +0000519 }
520 }
521}
522
523/* flush all the translation blocks */
bellardd4e81642003-05-25 16:46:15 +0000524/* XXX: tb_flush is currently not thread safe */
bellard6a00d602005-11-21 23:25:50 +0000525void tb_flush(CPUState *env1)
bellardfd6ce8f2003-05-14 19:00:11 +0000526{
bellard6a00d602005-11-21 23:25:50 +0000527 CPUState *env;
bellard01243112004-01-04 15:48:17 +0000528#if defined(DEBUG_FLUSH)
blueswir1ab3d1722007-11-04 07:31:40 +0000529 printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
530 (unsigned long)(code_gen_ptr - code_gen_buffer),
531 nb_tbs, nb_tbs > 0 ?
532 ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
bellardfd6ce8f2003-05-14 19:00:11 +0000533#endif
bellard26a5f132008-05-28 12:30:31 +0000534 if ((unsigned long)(code_gen_ptr - code_gen_buffer) > code_gen_buffer_size)
pbrooka208e542008-03-31 17:07:36 +0000535 cpu_abort(env1, "Internal error: code buffer overflow\n");
536
bellardfd6ce8f2003-05-14 19:00:11 +0000537 nb_tbs = 0;
ths3b46e622007-09-17 08:09:54 +0000538
bellard6a00d602005-11-21 23:25:50 +0000539 for(env = first_cpu; env != NULL; env = env->next_cpu) {
540 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
541 }
bellard9fa3e852004-01-04 18:06:42 +0000542
bellard8a8a6082004-10-03 13:36:49 +0000543 memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
bellardfd6ce8f2003-05-14 19:00:11 +0000544 page_flush_tb();
bellard9fa3e852004-01-04 18:06:42 +0000545
bellardfd6ce8f2003-05-14 19:00:11 +0000546 code_gen_ptr = code_gen_buffer;
bellardd4e81642003-05-25 16:46:15 +0000547 /* XXX: flush processor icache at this point if cache flush is
548 expensive */
bellarde3db7222005-01-26 22:00:47 +0000549 tb_flush_count++;
bellardfd6ce8f2003-05-14 19:00:11 +0000550}
551
552#ifdef DEBUG_TB_CHECK
553
j_mayerbc98a7e2007-04-04 07:55:12 +0000554static void tb_invalidate_check(target_ulong address)
bellardfd6ce8f2003-05-14 19:00:11 +0000555{
556 TranslationBlock *tb;
557 int i;
558 address &= TARGET_PAGE_MASK;
pbrook99773bd2006-04-16 15:14:59 +0000559 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
560 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
bellardfd6ce8f2003-05-14 19:00:11 +0000561 if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
562 address >= tb->pc + tb->size)) {
563 printf("ERROR invalidate: address=%08lx PC=%08lx size=%04x\n",
pbrook99773bd2006-04-16 15:14:59 +0000564 address, (long)tb->pc, tb->size);
bellardfd6ce8f2003-05-14 19:00:11 +0000565 }
566 }
567 }
568}
569
570/* verify that all the pages have correct rights for code */
571static void tb_page_check(void)
572{
573 TranslationBlock *tb;
574 int i, flags1, flags2;
ths3b46e622007-09-17 08:09:54 +0000575
pbrook99773bd2006-04-16 15:14:59 +0000576 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
577 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
bellardfd6ce8f2003-05-14 19:00:11 +0000578 flags1 = page_get_flags(tb->pc);
579 flags2 = page_get_flags(tb->pc + tb->size - 1);
580 if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
581 printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
pbrook99773bd2006-04-16 15:14:59 +0000582 (long)tb->pc, tb->size, flags1, flags2);
bellardfd6ce8f2003-05-14 19:00:11 +0000583 }
584 }
585 }
586}
587
bellardd4e81642003-05-25 16:46:15 +0000588void tb_jmp_check(TranslationBlock *tb)
589{
590 TranslationBlock *tb1;
591 unsigned int n1;
592
593 /* suppress any remaining jumps to this TB */
594 tb1 = tb->jmp_first;
595 for(;;) {
596 n1 = (long)tb1 & 3;
597 tb1 = (TranslationBlock *)((long)tb1 & ~3);
598 if (n1 == 2)
599 break;
600 tb1 = tb1->jmp_next[n1];
601 }
602 /* check end of list */
603 if (tb1 != tb) {
604 printf("ERROR: jmp_list from 0x%08lx\n", (long)tb);
605 }
606}
607
bellardfd6ce8f2003-05-14 19:00:11 +0000608#endif
609
610/* invalidate one TB */
611static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb,
612 int next_offset)
613{
614 TranslationBlock *tb1;
615 for(;;) {
616 tb1 = *ptb;
617 if (tb1 == tb) {
618 *ptb = *(TranslationBlock **)((char *)tb1 + next_offset);
619 break;
620 }
621 ptb = (TranslationBlock **)((char *)tb1 + next_offset);
622 }
623}
624
bellard9fa3e852004-01-04 18:06:42 +0000625static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
626{
627 TranslationBlock *tb1;
628 unsigned int n1;
629
630 for(;;) {
631 tb1 = *ptb;
632 n1 = (long)tb1 & 3;
633 tb1 = (TranslationBlock *)((long)tb1 & ~3);
634 if (tb1 == tb) {
635 *ptb = tb1->page_next[n1];
636 break;
637 }
638 ptb = &tb1->page_next[n1];
639 }
640}
641
bellardd4e81642003-05-25 16:46:15 +0000642static inline void tb_jmp_remove(TranslationBlock *tb, int n)
643{
644 TranslationBlock *tb1, **ptb;
645 unsigned int n1;
646
647 ptb = &tb->jmp_next[n];
648 tb1 = *ptb;
649 if (tb1) {
650 /* find tb(n) in circular list */
651 for(;;) {
652 tb1 = *ptb;
653 n1 = (long)tb1 & 3;
654 tb1 = (TranslationBlock *)((long)tb1 & ~3);
655 if (n1 == n && tb1 == tb)
656 break;
657 if (n1 == 2) {
658 ptb = &tb1->jmp_first;
659 } else {
660 ptb = &tb1->jmp_next[n1];
661 }
662 }
663 /* now we can suppress tb(n) from the list */
664 *ptb = tb->jmp_next[n];
665
666 tb->jmp_next[n] = NULL;
667 }
668}
669
670/* reset the jump entry 'n' of a TB so that it is not chained to
671 another TB */
672static inline void tb_reset_jump(TranslationBlock *tb, int n)
673{
674 tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
675}
676
pbrook2e70f6e2008-06-29 01:03:05 +0000677void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr)
bellardfd6ce8f2003-05-14 19:00:11 +0000678{
bellard6a00d602005-11-21 23:25:50 +0000679 CPUState *env;
bellardfd6ce8f2003-05-14 19:00:11 +0000680 PageDesc *p;
bellard8a40a182005-11-20 10:35:40 +0000681 unsigned int h, n1;
aurel3200f82b82008-04-27 21:12:55 +0000682 target_phys_addr_t phys_pc;
bellard8a40a182005-11-20 10:35:40 +0000683 TranslationBlock *tb1, *tb2;
ths3b46e622007-09-17 08:09:54 +0000684
bellard9fa3e852004-01-04 18:06:42 +0000685 /* remove the TB from the hash list */
686 phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
687 h = tb_phys_hash_func(phys_pc);
ths5fafdf22007-09-16 21:08:06 +0000688 tb_remove(&tb_phys_hash[h], tb,
bellard9fa3e852004-01-04 18:06:42 +0000689 offsetof(TranslationBlock, phys_hash_next));
bellardfd6ce8f2003-05-14 19:00:11 +0000690
bellard9fa3e852004-01-04 18:06:42 +0000691 /* remove the TB from the page list */
692 if (tb->page_addr[0] != page_addr) {
693 p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
694 tb_page_remove(&p->first_tb, tb);
695 invalidate_page_bitmap(p);
696 }
697 if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
698 p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
699 tb_page_remove(&p->first_tb, tb);
700 invalidate_page_bitmap(p);
701 }
702
bellard8a40a182005-11-20 10:35:40 +0000703 tb_invalidated_flag = 1;
704
705 /* remove the TB from the hash list */
706 h = tb_jmp_cache_hash_func(tb->pc);
bellard6a00d602005-11-21 23:25:50 +0000707 for(env = first_cpu; env != NULL; env = env->next_cpu) {
708 if (env->tb_jmp_cache[h] == tb)
709 env->tb_jmp_cache[h] = NULL;
710 }
bellard8a40a182005-11-20 10:35:40 +0000711
712 /* suppress this TB from the two jump lists */
713 tb_jmp_remove(tb, 0);
714 tb_jmp_remove(tb, 1);
715
716 /* suppress any remaining jumps to this TB */
717 tb1 = tb->jmp_first;
718 for(;;) {
719 n1 = (long)tb1 & 3;
720 if (n1 == 2)
721 break;
722 tb1 = (TranslationBlock *)((long)tb1 & ~3);
723 tb2 = tb1->jmp_next[n1];
724 tb_reset_jump(tb1, n1);
725 tb1->jmp_next[n1] = NULL;
726 tb1 = tb2;
727 }
728 tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
729
bellarde3db7222005-01-26 22:00:47 +0000730 tb_phys_invalidate_count++;
bellard9fa3e852004-01-04 18:06:42 +0000731}
732
733static inline void set_bits(uint8_t *tab, int start, int len)
734{
735 int end, mask, end1;
736
737 end = start + len;
738 tab += start >> 3;
739 mask = 0xff << (start & 7);
740 if ((start & ~7) == (end & ~7)) {
741 if (start < end) {
742 mask &= ~(0xff << (end & 7));
743 *tab |= mask;
744 }
745 } else {
746 *tab++ |= mask;
747 start = (start + 8) & ~7;
748 end1 = end & ~7;
749 while (start < end1) {
750 *tab++ = 0xff;
751 start += 8;
752 }
753 if (start < end) {
754 mask = ~(0xff << (end & 7));
755 *tab |= mask;
756 }
757 }
758}
759
760static void build_page_bitmap(PageDesc *p)
761{
762 int n, tb_start, tb_end;
763 TranslationBlock *tb;
ths3b46e622007-09-17 08:09:54 +0000764
pbrookb2a70812008-06-09 13:57:23 +0000765 p->code_bitmap = qemu_mallocz(TARGET_PAGE_SIZE / 8);
bellard9fa3e852004-01-04 18:06:42 +0000766 if (!p->code_bitmap)
767 return;
bellard9fa3e852004-01-04 18:06:42 +0000768
769 tb = p->first_tb;
770 while (tb != NULL) {
771 n = (long)tb & 3;
772 tb = (TranslationBlock *)((long)tb & ~3);
773 /* NOTE: this is subtle as a TB may span two physical pages */
774 if (n == 0) {
775 /* NOTE: tb_end may be after the end of the page, but
776 it is not a problem */
777 tb_start = tb->pc & ~TARGET_PAGE_MASK;
778 tb_end = tb_start + tb->size;
779 if (tb_end > TARGET_PAGE_SIZE)
780 tb_end = TARGET_PAGE_SIZE;
781 } else {
782 tb_start = 0;
783 tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
784 }
785 set_bits(p->code_bitmap, tb_start, tb_end - tb_start);
786 tb = tb->page_next[n];
787 }
788}
789
pbrook2e70f6e2008-06-29 01:03:05 +0000790TranslationBlock *tb_gen_code(CPUState *env,
791 target_ulong pc, target_ulong cs_base,
792 int flags, int cflags)
bellardd720b932004-04-25 17:57:43 +0000793{
794 TranslationBlock *tb;
795 uint8_t *tc_ptr;
796 target_ulong phys_pc, phys_page2, virt_page2;
797 int code_gen_size;
798
bellardc27004e2005-01-03 23:35:10 +0000799 phys_pc = get_phys_addr_code(env, pc);
800 tb = tb_alloc(pc);
bellardd720b932004-04-25 17:57:43 +0000801 if (!tb) {
802 /* flush must be done */
803 tb_flush(env);
804 /* cannot fail at this point */
bellardc27004e2005-01-03 23:35:10 +0000805 tb = tb_alloc(pc);
pbrook2e70f6e2008-06-29 01:03:05 +0000806 /* Don't forget to invalidate previous TB info. */
807 tb_invalidated_flag = 1;
bellardd720b932004-04-25 17:57:43 +0000808 }
809 tc_ptr = code_gen_ptr;
810 tb->tc_ptr = tc_ptr;
811 tb->cs_base = cs_base;
812 tb->flags = flags;
813 tb->cflags = cflags;
blueswir1d07bde82007-12-11 19:35:45 +0000814 cpu_gen_code(env, tb, &code_gen_size);
bellardd720b932004-04-25 17:57:43 +0000815 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 +0000816
bellardd720b932004-04-25 17:57:43 +0000817 /* check next page if needed */
bellardc27004e2005-01-03 23:35:10 +0000818 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
bellardd720b932004-04-25 17:57:43 +0000819 phys_page2 = -1;
bellardc27004e2005-01-03 23:35:10 +0000820 if ((pc & TARGET_PAGE_MASK) != virt_page2) {
bellardd720b932004-04-25 17:57:43 +0000821 phys_page2 = get_phys_addr_code(env, virt_page2);
822 }
823 tb_link_phys(tb, phys_pc, phys_page2);
pbrook2e70f6e2008-06-29 01:03:05 +0000824 return tb;
bellardd720b932004-04-25 17:57:43 +0000825}
ths3b46e622007-09-17 08:09:54 +0000826
bellard9fa3e852004-01-04 18:06:42 +0000827/* invalidate all TBs which intersect with the target physical page
828 starting in range [start;end[. NOTE: start and end must refer to
bellardd720b932004-04-25 17:57:43 +0000829 the same physical page. 'is_cpu_write_access' should be true if called
830 from a real cpu write access: the virtual CPU will exit the current
831 TB if code is modified inside this TB. */
aurel3200f82b82008-04-27 21:12:55 +0000832void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t end,
bellardd720b932004-04-25 17:57:43 +0000833 int is_cpu_write_access)
bellard9fa3e852004-01-04 18:06:42 +0000834{
bellardd720b932004-04-25 17:57:43 +0000835 int n, current_tb_modified, current_tb_not_found, current_flags;
bellardd720b932004-04-25 17:57:43 +0000836 CPUState *env = cpu_single_env;
bellard9fa3e852004-01-04 18:06:42 +0000837 PageDesc *p;
bellardea1c1802004-06-14 18:56:36 +0000838 TranslationBlock *tb, *tb_next, *current_tb, *saved_tb;
bellard9fa3e852004-01-04 18:06:42 +0000839 target_ulong tb_start, tb_end;
bellardd720b932004-04-25 17:57:43 +0000840 target_ulong current_pc, current_cs_base;
bellard9fa3e852004-01-04 18:06:42 +0000841
842 p = page_find(start >> TARGET_PAGE_BITS);
ths5fafdf22007-09-16 21:08:06 +0000843 if (!p)
bellard9fa3e852004-01-04 18:06:42 +0000844 return;
ths5fafdf22007-09-16 21:08:06 +0000845 if (!p->code_bitmap &&
bellardd720b932004-04-25 17:57:43 +0000846 ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
847 is_cpu_write_access) {
bellard9fa3e852004-01-04 18:06:42 +0000848 /* build code bitmap */
849 build_page_bitmap(p);
850 }
851
852 /* we remove all the TBs in the range [start, end[ */
853 /* XXX: see if in some cases it could be faster to invalidate all the code */
bellardd720b932004-04-25 17:57:43 +0000854 current_tb_not_found = is_cpu_write_access;
855 current_tb_modified = 0;
856 current_tb = NULL; /* avoid warning */
857 current_pc = 0; /* avoid warning */
858 current_cs_base = 0; /* avoid warning */
859 current_flags = 0; /* avoid warning */
bellard9fa3e852004-01-04 18:06:42 +0000860 tb = p->first_tb;
861 while (tb != NULL) {
862 n = (long)tb & 3;
863 tb = (TranslationBlock *)((long)tb & ~3);
864 tb_next = tb->page_next[n];
865 /* NOTE: this is subtle as a TB may span two physical pages */
866 if (n == 0) {
867 /* NOTE: tb_end may be after the end of the page, but
868 it is not a problem */
869 tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
870 tb_end = tb_start + tb->size;
871 } else {
872 tb_start = tb->page_addr[1];
873 tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
874 }
875 if (!(tb_end <= start || tb_start >= end)) {
bellardd720b932004-04-25 17:57:43 +0000876#ifdef TARGET_HAS_PRECISE_SMC
877 if (current_tb_not_found) {
878 current_tb_not_found = 0;
879 current_tb = NULL;
pbrook2e70f6e2008-06-29 01:03:05 +0000880 if (env->mem_io_pc) {
bellardd720b932004-04-25 17:57:43 +0000881 /* now we have a real cpu fault */
pbrook2e70f6e2008-06-29 01:03:05 +0000882 current_tb = tb_find_pc(env->mem_io_pc);
bellardd720b932004-04-25 17:57:43 +0000883 }
884 }
885 if (current_tb == tb &&
pbrook2e70f6e2008-06-29 01:03:05 +0000886 (current_tb->cflags & CF_COUNT_MASK) != 1) {
bellardd720b932004-04-25 17:57:43 +0000887 /* If we are modifying the current TB, we must stop
888 its execution. We could be more precise by checking
889 that the modification is after the current PC, but it
890 would require a specialized function to partially
891 restore the CPU state */
ths3b46e622007-09-17 08:09:54 +0000892
bellardd720b932004-04-25 17:57:43 +0000893 current_tb_modified = 1;
ths5fafdf22007-09-16 21:08:06 +0000894 cpu_restore_state(current_tb, env,
pbrook2e70f6e2008-06-29 01:03:05 +0000895 env->mem_io_pc, NULL);
bellardd720b932004-04-25 17:57:43 +0000896#if defined(TARGET_I386)
897 current_flags = env->hflags;
898 current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
899 current_cs_base = (target_ulong)env->segs[R_CS].base;
900 current_pc = current_cs_base + env->eip;
901#else
902#error unsupported CPU
903#endif
904 }
905#endif /* TARGET_HAS_PRECISE_SMC */
bellard6f5a9f72005-11-26 20:12:28 +0000906 /* we need to do that to handle the case where a signal
907 occurs while doing tb_phys_invalidate() */
908 saved_tb = NULL;
909 if (env) {
910 saved_tb = env->current_tb;
911 env->current_tb = NULL;
912 }
bellard9fa3e852004-01-04 18:06:42 +0000913 tb_phys_invalidate(tb, -1);
bellard6f5a9f72005-11-26 20:12:28 +0000914 if (env) {
915 env->current_tb = saved_tb;
916 if (env->interrupt_request && env->current_tb)
917 cpu_interrupt(env, env->interrupt_request);
918 }
bellard9fa3e852004-01-04 18:06:42 +0000919 }
920 tb = tb_next;
921 }
922#if !defined(CONFIG_USER_ONLY)
923 /* if no code remaining, no need to continue to use slow writes */
924 if (!p->first_tb) {
925 invalidate_page_bitmap(p);
bellardd720b932004-04-25 17:57:43 +0000926 if (is_cpu_write_access) {
pbrook2e70f6e2008-06-29 01:03:05 +0000927 tlb_unprotect_code_phys(env, start, env->mem_io_vaddr);
bellardd720b932004-04-25 17:57:43 +0000928 }
929 }
930#endif
931#ifdef TARGET_HAS_PRECISE_SMC
932 if (current_tb_modified) {
933 /* we generate a block containing just the instruction
934 modifying the memory. It will ensure that it cannot modify
935 itself */
bellardea1c1802004-06-14 18:56:36 +0000936 env->current_tb = NULL;
pbrook2e70f6e2008-06-29 01:03:05 +0000937 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
bellardd720b932004-04-25 17:57:43 +0000938 cpu_resume_from_signal(env, NULL);
bellard9fa3e852004-01-04 18:06:42 +0000939 }
940#endif
941}
942
943/* len must be <= 8 and start must be a multiple of len */
aurel3200f82b82008-04-27 21:12:55 +0000944static inline void tb_invalidate_phys_page_fast(target_phys_addr_t start, int len)
bellard9fa3e852004-01-04 18:06:42 +0000945{
946 PageDesc *p;
947 int offset, b;
bellard59817cc2004-02-16 22:01:13 +0000948#if 0
bellarda4193c82004-06-03 14:01:43 +0000949 if (1) {
950 if (loglevel) {
ths5fafdf22007-09-16 21:08:06 +0000951 fprintf(logfile, "modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
pbrook2e70f6e2008-06-29 01:03:05 +0000952 cpu_single_env->mem_io_vaddr, len,
ths5fafdf22007-09-16 21:08:06 +0000953 cpu_single_env->eip,
bellarda4193c82004-06-03 14:01:43 +0000954 cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
955 }
bellard59817cc2004-02-16 22:01:13 +0000956 }
957#endif
bellard9fa3e852004-01-04 18:06:42 +0000958 p = page_find(start >> TARGET_PAGE_BITS);
ths5fafdf22007-09-16 21:08:06 +0000959 if (!p)
bellard9fa3e852004-01-04 18:06:42 +0000960 return;
961 if (p->code_bitmap) {
962 offset = start & ~TARGET_PAGE_MASK;
963 b = p->code_bitmap[offset >> 3] >> (offset & 7);
964 if (b & ((1 << len) - 1))
965 goto do_invalidate;
966 } else {
967 do_invalidate:
bellardd720b932004-04-25 17:57:43 +0000968 tb_invalidate_phys_page_range(start, start + len, 1);
bellard9fa3e852004-01-04 18:06:42 +0000969 }
970}
971
bellard9fa3e852004-01-04 18:06:42 +0000972#if !defined(CONFIG_SOFTMMU)
aurel3200f82b82008-04-27 21:12:55 +0000973static void tb_invalidate_phys_page(target_phys_addr_t addr,
bellardd720b932004-04-25 17:57:43 +0000974 unsigned long pc, void *puc)
bellard9fa3e852004-01-04 18:06:42 +0000975{
bellardd720b932004-04-25 17:57:43 +0000976 int n, current_flags, current_tb_modified;
977 target_ulong current_pc, current_cs_base;
bellard9fa3e852004-01-04 18:06:42 +0000978 PageDesc *p;
bellardd720b932004-04-25 17:57:43 +0000979 TranslationBlock *tb, *current_tb;
980#ifdef TARGET_HAS_PRECISE_SMC
981 CPUState *env = cpu_single_env;
982#endif
bellard9fa3e852004-01-04 18:06:42 +0000983
984 addr &= TARGET_PAGE_MASK;
985 p = page_find(addr >> TARGET_PAGE_BITS);
ths5fafdf22007-09-16 21:08:06 +0000986 if (!p)
bellardfd6ce8f2003-05-14 19:00:11 +0000987 return;
988 tb = p->first_tb;
bellardd720b932004-04-25 17:57:43 +0000989 current_tb_modified = 0;
990 current_tb = NULL;
991 current_pc = 0; /* avoid warning */
992 current_cs_base = 0; /* avoid warning */
993 current_flags = 0; /* avoid warning */
994#ifdef TARGET_HAS_PRECISE_SMC
995 if (tb && pc != 0) {
996 current_tb = tb_find_pc(pc);
997 }
998#endif
bellardfd6ce8f2003-05-14 19:00:11 +0000999 while (tb != NULL) {
bellard9fa3e852004-01-04 18:06:42 +00001000 n = (long)tb & 3;
1001 tb = (TranslationBlock *)((long)tb & ~3);
bellardd720b932004-04-25 17:57:43 +00001002#ifdef TARGET_HAS_PRECISE_SMC
1003 if (current_tb == tb &&
pbrook2e70f6e2008-06-29 01:03:05 +00001004 (current_tb->cflags & CF_COUNT_MASK) != 1) {
bellardd720b932004-04-25 17:57:43 +00001005 /* If we are modifying the current TB, we must stop
1006 its execution. We could be more precise by checking
1007 that the modification is after the current PC, but it
1008 would require a specialized function to partially
1009 restore the CPU state */
ths3b46e622007-09-17 08:09:54 +00001010
bellardd720b932004-04-25 17:57:43 +00001011 current_tb_modified = 1;
1012 cpu_restore_state(current_tb, env, pc, puc);
1013#if defined(TARGET_I386)
1014 current_flags = env->hflags;
1015 current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
1016 current_cs_base = (target_ulong)env->segs[R_CS].base;
1017 current_pc = current_cs_base + env->eip;
1018#else
1019#error unsupported CPU
1020#endif
1021 }
1022#endif /* TARGET_HAS_PRECISE_SMC */
bellard9fa3e852004-01-04 18:06:42 +00001023 tb_phys_invalidate(tb, addr);
1024 tb = tb->page_next[n];
bellardfd6ce8f2003-05-14 19:00:11 +00001025 }
1026 p->first_tb = NULL;
bellardd720b932004-04-25 17:57:43 +00001027#ifdef TARGET_HAS_PRECISE_SMC
1028 if (current_tb_modified) {
1029 /* we generate a block containing just the instruction
1030 modifying the memory. It will ensure that it cannot modify
1031 itself */
bellardea1c1802004-06-14 18:56:36 +00001032 env->current_tb = NULL;
pbrook2e70f6e2008-06-29 01:03:05 +00001033 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
bellardd720b932004-04-25 17:57:43 +00001034 cpu_resume_from_signal(env, puc);
1035 }
1036#endif
bellardfd6ce8f2003-05-14 19:00:11 +00001037}
bellard9fa3e852004-01-04 18:06:42 +00001038#endif
bellardfd6ce8f2003-05-14 19:00:11 +00001039
1040/* add the tb in the target page and protect it if necessary */
ths5fafdf22007-09-16 21:08:06 +00001041static inline void tb_alloc_page(TranslationBlock *tb,
pbrook53a59602006-03-25 19:31:22 +00001042 unsigned int n, target_ulong page_addr)
bellardfd6ce8f2003-05-14 19:00:11 +00001043{
1044 PageDesc *p;
bellard9fa3e852004-01-04 18:06:42 +00001045 TranslationBlock *last_first_tb;
bellardfd6ce8f2003-05-14 19:00:11 +00001046
bellard9fa3e852004-01-04 18:06:42 +00001047 tb->page_addr[n] = page_addr;
bellard3a7d9292005-08-21 09:26:42 +00001048 p = page_find_alloc(page_addr >> TARGET_PAGE_BITS);
bellard9fa3e852004-01-04 18:06:42 +00001049 tb->page_next[n] = p->first_tb;
1050 last_first_tb = p->first_tb;
1051 p->first_tb = (TranslationBlock *)((long)tb | n);
1052 invalidate_page_bitmap(p);
1053
bellard107db442004-06-22 18:48:46 +00001054#if defined(TARGET_HAS_SMC) || 1
bellardd720b932004-04-25 17:57:43 +00001055
bellard9fa3e852004-01-04 18:06:42 +00001056#if defined(CONFIG_USER_ONLY)
bellardfd6ce8f2003-05-14 19:00:11 +00001057 if (p->flags & PAGE_WRITE) {
pbrook53a59602006-03-25 19:31:22 +00001058 target_ulong addr;
1059 PageDesc *p2;
bellard9fa3e852004-01-04 18:06:42 +00001060 int prot;
1061
bellardfd6ce8f2003-05-14 19:00:11 +00001062 /* force the host page as non writable (writes will have a
1063 page fault + mprotect overhead) */
pbrook53a59602006-03-25 19:31:22 +00001064 page_addr &= qemu_host_page_mask;
bellardfd6ce8f2003-05-14 19:00:11 +00001065 prot = 0;
pbrook53a59602006-03-25 19:31:22 +00001066 for(addr = page_addr; addr < page_addr + qemu_host_page_size;
1067 addr += TARGET_PAGE_SIZE) {
1068
1069 p2 = page_find (addr >> TARGET_PAGE_BITS);
1070 if (!p2)
1071 continue;
1072 prot |= p2->flags;
1073 p2->flags &= ~PAGE_WRITE;
1074 page_get_flags(addr);
1075 }
ths5fafdf22007-09-16 21:08:06 +00001076 mprotect(g2h(page_addr), qemu_host_page_size,
bellardfd6ce8f2003-05-14 19:00:11 +00001077 (prot & PAGE_BITS) & ~PAGE_WRITE);
1078#ifdef DEBUG_TB_INVALIDATE
blueswir1ab3d1722007-11-04 07:31:40 +00001079 printf("protecting code page: 0x" TARGET_FMT_lx "\n",
pbrook53a59602006-03-25 19:31:22 +00001080 page_addr);
bellardfd6ce8f2003-05-14 19:00:11 +00001081#endif
bellardfd6ce8f2003-05-14 19:00:11 +00001082 }
bellard9fa3e852004-01-04 18:06:42 +00001083#else
1084 /* if some code is already present, then the pages are already
1085 protected. So we handle the case where only the first TB is
1086 allocated in a physical page */
1087 if (!last_first_tb) {
bellard6a00d602005-11-21 23:25:50 +00001088 tlb_protect_code(page_addr);
bellard9fa3e852004-01-04 18:06:42 +00001089 }
1090#endif
bellardd720b932004-04-25 17:57:43 +00001091
1092#endif /* TARGET_HAS_SMC */
bellardfd6ce8f2003-05-14 19:00:11 +00001093}
1094
1095/* Allocate a new translation block. Flush the translation buffer if
1096 too many translation blocks or too much generated code. */
bellardc27004e2005-01-03 23:35:10 +00001097TranslationBlock *tb_alloc(target_ulong pc)
bellardfd6ce8f2003-05-14 19:00:11 +00001098{
1099 TranslationBlock *tb;
bellardfd6ce8f2003-05-14 19:00:11 +00001100
bellard26a5f132008-05-28 12:30:31 +00001101 if (nb_tbs >= code_gen_max_blocks ||
1102 (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
bellardd4e81642003-05-25 16:46:15 +00001103 return NULL;
bellardfd6ce8f2003-05-14 19:00:11 +00001104 tb = &tbs[nb_tbs++];
1105 tb->pc = pc;
bellardb448f2f2004-02-25 23:24:04 +00001106 tb->cflags = 0;
bellardd4e81642003-05-25 16:46:15 +00001107 return tb;
1108}
1109
pbrook2e70f6e2008-06-29 01:03:05 +00001110void tb_free(TranslationBlock *tb)
1111{
thsbf20dc02008-06-30 17:22:19 +00001112 /* In practice this is mostly used for single use temporary TB
pbrook2e70f6e2008-06-29 01:03:05 +00001113 Ignore the hard cases and just back up if this TB happens to
1114 be the last one generated. */
1115 if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) {
1116 code_gen_ptr = tb->tc_ptr;
1117 nb_tbs--;
1118 }
1119}
1120
bellard9fa3e852004-01-04 18:06:42 +00001121/* add a new TB and link it to the physical page tables. phys_page2 is
1122 (-1) to indicate that only one page contains the TB. */
ths5fafdf22007-09-16 21:08:06 +00001123void tb_link_phys(TranslationBlock *tb,
bellard9fa3e852004-01-04 18:06:42 +00001124 target_ulong phys_pc, target_ulong phys_page2)
bellardd4e81642003-05-25 16:46:15 +00001125{
bellard9fa3e852004-01-04 18:06:42 +00001126 unsigned int h;
1127 TranslationBlock **ptb;
1128
pbrookc8a706f2008-06-02 16:16:42 +00001129 /* Grab the mmap lock to stop another thread invalidating this TB
1130 before we are done. */
1131 mmap_lock();
bellard9fa3e852004-01-04 18:06:42 +00001132 /* add in the physical hash table */
1133 h = tb_phys_hash_func(phys_pc);
1134 ptb = &tb_phys_hash[h];
1135 tb->phys_hash_next = *ptb;
1136 *ptb = tb;
bellardfd6ce8f2003-05-14 19:00:11 +00001137
1138 /* add in the page list */
bellard9fa3e852004-01-04 18:06:42 +00001139 tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK);
1140 if (phys_page2 != -1)
1141 tb_alloc_page(tb, 1, phys_page2);
1142 else
1143 tb->page_addr[1] = -1;
bellard9fa3e852004-01-04 18:06:42 +00001144
bellardd4e81642003-05-25 16:46:15 +00001145 tb->jmp_first = (TranslationBlock *)((long)tb | 2);
1146 tb->jmp_next[0] = NULL;
1147 tb->jmp_next[1] = NULL;
1148
1149 /* init original jump addresses */
1150 if (tb->tb_next_offset[0] != 0xffff)
1151 tb_reset_jump(tb, 0);
1152 if (tb->tb_next_offset[1] != 0xffff)
1153 tb_reset_jump(tb, 1);
bellard8a40a182005-11-20 10:35:40 +00001154
1155#ifdef DEBUG_TB_CHECK
1156 tb_page_check();
1157#endif
pbrookc8a706f2008-06-02 16:16:42 +00001158 mmap_unlock();
bellardfd6ce8f2003-05-14 19:00:11 +00001159}
1160
bellarda513fe12003-05-27 23:29:48 +00001161/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
1162 tb[1].tc_ptr. Return NULL if not found */
1163TranslationBlock *tb_find_pc(unsigned long tc_ptr)
1164{
1165 int m_min, m_max, m;
1166 unsigned long v;
1167 TranslationBlock *tb;
1168
1169 if (nb_tbs <= 0)
1170 return NULL;
1171 if (tc_ptr < (unsigned long)code_gen_buffer ||
1172 tc_ptr >= (unsigned long)code_gen_ptr)
1173 return NULL;
1174 /* binary search (cf Knuth) */
1175 m_min = 0;
1176 m_max = nb_tbs - 1;
1177 while (m_min <= m_max) {
1178 m = (m_min + m_max) >> 1;
1179 tb = &tbs[m];
1180 v = (unsigned long)tb->tc_ptr;
1181 if (v == tc_ptr)
1182 return tb;
1183 else if (tc_ptr < v) {
1184 m_max = m - 1;
1185 } else {
1186 m_min = m + 1;
1187 }
ths5fafdf22007-09-16 21:08:06 +00001188 }
bellarda513fe12003-05-27 23:29:48 +00001189 return &tbs[m_max];
1190}
bellard75012672003-06-21 13:11:07 +00001191
bellardea041c02003-06-25 16:16:50 +00001192static void tb_reset_jump_recursive(TranslationBlock *tb);
1193
1194static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
1195{
1196 TranslationBlock *tb1, *tb_next, **ptb;
1197 unsigned int n1;
1198
1199 tb1 = tb->jmp_next[n];
1200 if (tb1 != NULL) {
1201 /* find head of list */
1202 for(;;) {
1203 n1 = (long)tb1 & 3;
1204 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1205 if (n1 == 2)
1206 break;
1207 tb1 = tb1->jmp_next[n1];
1208 }
1209 /* we are now sure now that tb jumps to tb1 */
1210 tb_next = tb1;
1211
1212 /* remove tb from the jmp_first list */
1213 ptb = &tb_next->jmp_first;
1214 for(;;) {
1215 tb1 = *ptb;
1216 n1 = (long)tb1 & 3;
1217 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1218 if (n1 == n && tb1 == tb)
1219 break;
1220 ptb = &tb1->jmp_next[n1];
1221 }
1222 *ptb = tb->jmp_next[n];
1223 tb->jmp_next[n] = NULL;
ths3b46e622007-09-17 08:09:54 +00001224
bellardea041c02003-06-25 16:16:50 +00001225 /* suppress the jump to next tb in generated code */
1226 tb_reset_jump(tb, n);
1227
bellard01243112004-01-04 15:48:17 +00001228 /* suppress jumps in the tb on which we could have jumped */
bellardea041c02003-06-25 16:16:50 +00001229 tb_reset_jump_recursive(tb_next);
1230 }
1231}
1232
1233static void tb_reset_jump_recursive(TranslationBlock *tb)
1234{
1235 tb_reset_jump_recursive2(tb, 0);
1236 tb_reset_jump_recursive2(tb, 1);
1237}
1238
bellard1fddef42005-04-17 19:16:13 +00001239#if defined(TARGET_HAS_ICE)
bellardd720b932004-04-25 17:57:43 +00001240static void breakpoint_invalidate(CPUState *env, target_ulong pc)
1241{
j_mayer9b3c35e2007-04-07 11:21:28 +00001242 target_phys_addr_t addr;
1243 target_ulong pd;
pbrookc2f07f82006-04-08 17:14:56 +00001244 ram_addr_t ram_addr;
1245 PhysPageDesc *p;
bellardd720b932004-04-25 17:57:43 +00001246
pbrookc2f07f82006-04-08 17:14:56 +00001247 addr = cpu_get_phys_page_debug(env, pc);
1248 p = phys_page_find(addr >> TARGET_PAGE_BITS);
1249 if (!p) {
1250 pd = IO_MEM_UNASSIGNED;
1251 } else {
1252 pd = p->phys_offset;
1253 }
1254 ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
pbrook706cd4b2006-04-08 17:36:21 +00001255 tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
bellardd720b932004-04-25 17:57:43 +00001256}
bellardc27004e2005-01-03 23:35:10 +00001257#endif
bellardd720b932004-04-25 17:57:43 +00001258
pbrook6658ffb2007-03-16 23:58:11 +00001259/* Add a watchpoint. */
pbrook0f459d12008-06-09 00:20:13 +00001260int cpu_watchpoint_insert(CPUState *env, target_ulong addr, int type)
pbrook6658ffb2007-03-16 23:58:11 +00001261{
1262 int i;
1263
1264 for (i = 0; i < env->nb_watchpoints; i++) {
1265 if (addr == env->watchpoint[i].vaddr)
1266 return 0;
1267 }
1268 if (env->nb_watchpoints >= MAX_WATCHPOINTS)
1269 return -1;
1270
1271 i = env->nb_watchpoints++;
1272 env->watchpoint[i].vaddr = addr;
pbrook0f459d12008-06-09 00:20:13 +00001273 env->watchpoint[i].type = type;
pbrook6658ffb2007-03-16 23:58:11 +00001274 tlb_flush_page(env, addr);
1275 /* FIXME: This flush is needed because of the hack to make memory ops
1276 terminate the TB. It can be removed once the proper IO trap and
1277 re-execute bits are in. */
1278 tb_flush(env);
1279 return i;
1280}
1281
1282/* Remove a watchpoint. */
1283int cpu_watchpoint_remove(CPUState *env, target_ulong addr)
1284{
1285 int i;
1286
1287 for (i = 0; i < env->nb_watchpoints; i++) {
1288 if (addr == env->watchpoint[i].vaddr) {
1289 env->nb_watchpoints--;
1290 env->watchpoint[i] = env->watchpoint[env->nb_watchpoints];
1291 tlb_flush_page(env, addr);
1292 return 0;
1293 }
1294 }
1295 return -1;
1296}
1297
edgar_igl7d03f822008-05-17 18:58:29 +00001298/* Remove all watchpoints. */
1299void cpu_watchpoint_remove_all(CPUState *env) {
1300 int i;
1301
1302 for (i = 0; i < env->nb_watchpoints; i++) {
1303 tlb_flush_page(env, env->watchpoint[i].vaddr);
1304 }
1305 env->nb_watchpoints = 0;
1306}
1307
bellardc33a3462003-07-29 20:50:33 +00001308/* add a breakpoint. EXCP_DEBUG is returned by the CPU loop if a
1309 breakpoint is reached */
bellard2e126692004-04-25 21:28:44 +00001310int cpu_breakpoint_insert(CPUState *env, target_ulong pc)
bellard4c3a88a2003-07-26 12:06:08 +00001311{
bellard1fddef42005-04-17 19:16:13 +00001312#if defined(TARGET_HAS_ICE)
bellard4c3a88a2003-07-26 12:06:08 +00001313 int i;
ths3b46e622007-09-17 08:09:54 +00001314
bellard4c3a88a2003-07-26 12:06:08 +00001315 for(i = 0; i < env->nb_breakpoints; i++) {
1316 if (env->breakpoints[i] == pc)
1317 return 0;
1318 }
1319
1320 if (env->nb_breakpoints >= MAX_BREAKPOINTS)
1321 return -1;
1322 env->breakpoints[env->nb_breakpoints++] = pc;
ths3b46e622007-09-17 08:09:54 +00001323
bellardd720b932004-04-25 17:57:43 +00001324 breakpoint_invalidate(env, pc);
bellard4c3a88a2003-07-26 12:06:08 +00001325 return 0;
1326#else
1327 return -1;
1328#endif
1329}
1330
edgar_igl7d03f822008-05-17 18:58:29 +00001331/* remove all breakpoints */
1332void cpu_breakpoint_remove_all(CPUState *env) {
1333#if defined(TARGET_HAS_ICE)
1334 int i;
1335 for(i = 0; i < env->nb_breakpoints; i++) {
1336 breakpoint_invalidate(env, env->breakpoints[i]);
1337 }
1338 env->nb_breakpoints = 0;
1339#endif
1340}
1341
bellard4c3a88a2003-07-26 12:06:08 +00001342/* remove a breakpoint */
bellard2e126692004-04-25 21:28:44 +00001343int cpu_breakpoint_remove(CPUState *env, target_ulong pc)
bellard4c3a88a2003-07-26 12:06:08 +00001344{
bellard1fddef42005-04-17 19:16:13 +00001345#if defined(TARGET_HAS_ICE)
bellard4c3a88a2003-07-26 12:06:08 +00001346 int i;
1347 for(i = 0; i < env->nb_breakpoints; i++) {
1348 if (env->breakpoints[i] == pc)
1349 goto found;
1350 }
1351 return -1;
1352 found:
bellard4c3a88a2003-07-26 12:06:08 +00001353 env->nb_breakpoints--;
bellard1fddef42005-04-17 19:16:13 +00001354 if (i < env->nb_breakpoints)
1355 env->breakpoints[i] = env->breakpoints[env->nb_breakpoints];
bellardd720b932004-04-25 17:57:43 +00001356
1357 breakpoint_invalidate(env, pc);
bellard4c3a88a2003-07-26 12:06:08 +00001358 return 0;
1359#else
1360 return -1;
1361#endif
1362}
1363
bellardc33a3462003-07-29 20:50:33 +00001364/* enable or disable single step mode. EXCP_DEBUG is returned by the
1365 CPU loop after each instruction */
1366void cpu_single_step(CPUState *env, int enabled)
1367{
bellard1fddef42005-04-17 19:16:13 +00001368#if defined(TARGET_HAS_ICE)
bellardc33a3462003-07-29 20:50:33 +00001369 if (env->singlestep_enabled != enabled) {
1370 env->singlestep_enabled = enabled;
1371 /* must flush all the translated code to avoid inconsistancies */
bellard9fa3e852004-01-04 18:06:42 +00001372 /* XXX: only flush what is necessary */
bellard01243112004-01-04 15:48:17 +00001373 tb_flush(env);
bellardc33a3462003-07-29 20:50:33 +00001374 }
1375#endif
1376}
1377
bellard34865132003-10-05 14:28:56 +00001378/* enable or disable low levels log */
1379void cpu_set_log(int log_flags)
1380{
1381 loglevel = log_flags;
1382 if (loglevel && !logfile) {
pbrook11fcfab2007-07-01 18:21:11 +00001383 logfile = fopen(logfilename, log_append ? "a" : "w");
bellard34865132003-10-05 14:28:56 +00001384 if (!logfile) {
1385 perror(logfilename);
1386 _exit(1);
1387 }
bellard9fa3e852004-01-04 18:06:42 +00001388#if !defined(CONFIG_SOFTMMU)
1389 /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1390 {
1391 static uint8_t logfile_buf[4096];
1392 setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1393 }
1394#else
bellard34865132003-10-05 14:28:56 +00001395 setvbuf(logfile, NULL, _IOLBF, 0);
bellard9fa3e852004-01-04 18:06:42 +00001396#endif
pbrooke735b912007-06-30 13:53:24 +00001397 log_append = 1;
1398 }
1399 if (!loglevel && logfile) {
1400 fclose(logfile);
1401 logfile = NULL;
bellard34865132003-10-05 14:28:56 +00001402 }
1403}
1404
1405void cpu_set_log_filename(const char *filename)
1406{
1407 logfilename = strdup(filename);
pbrooke735b912007-06-30 13:53:24 +00001408 if (logfile) {
1409 fclose(logfile);
1410 logfile = NULL;
1411 }
1412 cpu_set_log(loglevel);
bellard34865132003-10-05 14:28:56 +00001413}
bellardc33a3462003-07-29 20:50:33 +00001414
bellard01243112004-01-04 15:48:17 +00001415/* mask must never be zero, except for A20 change call */
bellard68a79312003-06-30 13:12:32 +00001416void cpu_interrupt(CPUState *env, int mask)
bellardea041c02003-06-25 16:16:50 +00001417{
pbrookd5975362008-06-07 20:50:51 +00001418#if !defined(USE_NPTL)
bellardea041c02003-06-25 16:16:50 +00001419 TranslationBlock *tb;
aurel3215a51152008-03-28 22:29:15 +00001420 static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
pbrookd5975362008-06-07 20:50:51 +00001421#endif
pbrook2e70f6e2008-06-29 01:03:05 +00001422 int old_mask;
bellard59817cc2004-02-16 22:01:13 +00001423
pbrook2e70f6e2008-06-29 01:03:05 +00001424 old_mask = env->interrupt_request;
pbrookd5975362008-06-07 20:50:51 +00001425 /* FIXME: This is probably not threadsafe. A different thread could
thsbf20dc02008-06-30 17:22:19 +00001426 be in the middle of a read-modify-write operation. */
bellard68a79312003-06-30 13:12:32 +00001427 env->interrupt_request |= mask;
pbrookd5975362008-06-07 20:50:51 +00001428#if defined(USE_NPTL)
1429 /* FIXME: TB unchaining isn't SMP safe. For now just ignore the
1430 problem and hope the cpu will stop of its own accord. For userspace
1431 emulation this often isn't actually as bad as it sounds. Often
1432 signals are used primarily to interrupt blocking syscalls. */
1433#else
pbrook2e70f6e2008-06-29 01:03:05 +00001434 if (use_icount) {
1435 env->icount_decr.u16.high = 0x8000;
1436#ifndef CONFIG_USER_ONLY
1437 /* CPU_INTERRUPT_EXIT isn't a real interrupt. It just means
1438 an async event happened and we need to process it. */
1439 if (!can_do_io(env)
1440 && (mask & ~(old_mask | CPU_INTERRUPT_EXIT)) != 0) {
1441 cpu_abort(env, "Raised interrupt while not in I/O function");
1442 }
1443#endif
1444 } else {
1445 tb = env->current_tb;
1446 /* if the cpu is currently executing code, we must unlink it and
1447 all the potentially executing TB */
1448 if (tb && !testandset(&interrupt_lock)) {
1449 env->current_tb = NULL;
1450 tb_reset_jump_recursive(tb);
1451 resetlock(&interrupt_lock);
1452 }
bellardea041c02003-06-25 16:16:50 +00001453 }
pbrookd5975362008-06-07 20:50:51 +00001454#endif
bellardea041c02003-06-25 16:16:50 +00001455}
1456
bellardb54ad042004-05-20 13:42:52 +00001457void cpu_reset_interrupt(CPUState *env, int mask)
1458{
1459 env->interrupt_request &= ~mask;
1460}
1461
bellardf193c792004-03-21 17:06:25 +00001462CPULogItem cpu_log_items[] = {
ths5fafdf22007-09-16 21:08:06 +00001463 { CPU_LOG_TB_OUT_ASM, "out_asm",
bellardf193c792004-03-21 17:06:25 +00001464 "show generated host assembly code for each compiled TB" },
1465 { CPU_LOG_TB_IN_ASM, "in_asm",
1466 "show target assembly code for each compiled TB" },
ths5fafdf22007-09-16 21:08:06 +00001467 { CPU_LOG_TB_OP, "op",
bellard57fec1f2008-02-01 10:50:11 +00001468 "show micro ops for each compiled TB" },
bellardf193c792004-03-21 17:06:25 +00001469 { CPU_LOG_TB_OP_OPT, "op_opt",
blueswir1e01a1152008-03-14 17:37:11 +00001470 "show micro ops "
1471#ifdef TARGET_I386
1472 "before eflags optimization and "
bellardf193c792004-03-21 17:06:25 +00001473#endif
blueswir1e01a1152008-03-14 17:37:11 +00001474 "after liveness analysis" },
bellardf193c792004-03-21 17:06:25 +00001475 { CPU_LOG_INT, "int",
1476 "show interrupts/exceptions in short format" },
1477 { CPU_LOG_EXEC, "exec",
1478 "show trace before each executed TB (lots of logs)" },
bellard9fddaa02004-05-21 12:59:32 +00001479 { CPU_LOG_TB_CPU, "cpu",
thse91c8a72007-06-03 13:35:16 +00001480 "show CPU state before block translation" },
bellardf193c792004-03-21 17:06:25 +00001481#ifdef TARGET_I386
1482 { CPU_LOG_PCALL, "pcall",
1483 "show protected mode far calls/returns/exceptions" },
1484#endif
bellard8e3a9fd2004-10-09 17:32:58 +00001485#ifdef DEBUG_IOPORT
bellardfd872592004-05-12 19:11:15 +00001486 { CPU_LOG_IOPORT, "ioport",
1487 "show all i/o ports accesses" },
bellard8e3a9fd2004-10-09 17:32:58 +00001488#endif
bellardf193c792004-03-21 17:06:25 +00001489 { 0, NULL, NULL },
1490};
1491
1492static int cmp1(const char *s1, int n, const char *s2)
1493{
1494 if (strlen(s2) != n)
1495 return 0;
1496 return memcmp(s1, s2, n) == 0;
1497}
ths3b46e622007-09-17 08:09:54 +00001498
bellardf193c792004-03-21 17:06:25 +00001499/* takes a comma separated list of log masks. Return 0 if error. */
1500int cpu_str_to_log_mask(const char *str)
1501{
1502 CPULogItem *item;
1503 int mask;
1504 const char *p, *p1;
1505
1506 p = str;
1507 mask = 0;
1508 for(;;) {
1509 p1 = strchr(p, ',');
1510 if (!p1)
1511 p1 = p + strlen(p);
bellard8e3a9fd2004-10-09 17:32:58 +00001512 if(cmp1(p,p1-p,"all")) {
1513 for(item = cpu_log_items; item->mask != 0; item++) {
1514 mask |= item->mask;
1515 }
1516 } else {
bellardf193c792004-03-21 17:06:25 +00001517 for(item = cpu_log_items; item->mask != 0; item++) {
1518 if (cmp1(p, p1 - p, item->name))
1519 goto found;
1520 }
1521 return 0;
bellard8e3a9fd2004-10-09 17:32:58 +00001522 }
bellardf193c792004-03-21 17:06:25 +00001523 found:
1524 mask |= item->mask;
1525 if (*p1 != ',')
1526 break;
1527 p = p1 + 1;
1528 }
1529 return mask;
1530}
bellardea041c02003-06-25 16:16:50 +00001531
bellard75012672003-06-21 13:11:07 +00001532void cpu_abort(CPUState *env, const char *fmt, ...)
1533{
1534 va_list ap;
pbrook493ae1f2007-11-23 16:53:59 +00001535 va_list ap2;
bellard75012672003-06-21 13:11:07 +00001536
1537 va_start(ap, fmt);
pbrook493ae1f2007-11-23 16:53:59 +00001538 va_copy(ap2, ap);
bellard75012672003-06-21 13:11:07 +00001539 fprintf(stderr, "qemu: fatal: ");
1540 vfprintf(stderr, fmt, ap);
1541 fprintf(stderr, "\n");
1542#ifdef TARGET_I386
bellard7fe48482004-10-09 18:08:01 +00001543 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1544#else
1545 cpu_dump_state(env, stderr, fprintf, 0);
bellard75012672003-06-21 13:11:07 +00001546#endif
balrog924edca2007-06-10 14:07:13 +00001547 if (logfile) {
j_mayerf9373292007-09-29 12:18:20 +00001548 fprintf(logfile, "qemu: fatal: ");
pbrook493ae1f2007-11-23 16:53:59 +00001549 vfprintf(logfile, fmt, ap2);
j_mayerf9373292007-09-29 12:18:20 +00001550 fprintf(logfile, "\n");
1551#ifdef TARGET_I386
1552 cpu_dump_state(env, logfile, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1553#else
1554 cpu_dump_state(env, logfile, fprintf, 0);
1555#endif
balrog924edca2007-06-10 14:07:13 +00001556 fflush(logfile);
1557 fclose(logfile);
1558 }
pbrook493ae1f2007-11-23 16:53:59 +00001559 va_end(ap2);
j_mayerf9373292007-09-29 12:18:20 +00001560 va_end(ap);
bellard75012672003-06-21 13:11:07 +00001561 abort();
1562}
1563
thsc5be9f02007-02-28 20:20:53 +00001564CPUState *cpu_copy(CPUState *env)
1565{
ths01ba9812007-12-09 02:22:57 +00001566 CPUState *new_env = cpu_init(env->cpu_model_str);
thsc5be9f02007-02-28 20:20:53 +00001567 /* preserve chaining and index */
1568 CPUState *next_cpu = new_env->next_cpu;
1569 int cpu_index = new_env->cpu_index;
1570 memcpy(new_env, env, sizeof(CPUState));
1571 new_env->next_cpu = next_cpu;
1572 new_env->cpu_index = cpu_index;
1573 return new_env;
1574}
1575
bellard01243112004-01-04 15:48:17 +00001576#if !defined(CONFIG_USER_ONLY)
1577
edgar_igl5c751e92008-05-06 08:44:21 +00001578static inline void tlb_flush_jmp_cache(CPUState *env, target_ulong addr)
1579{
1580 unsigned int i;
1581
1582 /* Discard jump cache entries for any tb which might potentially
1583 overlap the flushed page. */
1584 i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
1585 memset (&env->tb_jmp_cache[i], 0,
1586 TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
1587
1588 i = tb_jmp_cache_hash_page(addr);
1589 memset (&env->tb_jmp_cache[i], 0,
1590 TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
1591}
1592
bellardee8b7022004-02-03 23:35:10 +00001593/* NOTE: if flush_global is true, also flush global entries (not
1594 implemented yet) */
1595void tlb_flush(CPUState *env, int flush_global)
bellard33417e72003-08-10 21:47:01 +00001596{
bellard33417e72003-08-10 21:47:01 +00001597 int i;
bellard01243112004-01-04 15:48:17 +00001598
bellard9fa3e852004-01-04 18:06:42 +00001599#if defined(DEBUG_TLB)
1600 printf("tlb_flush:\n");
1601#endif
bellard01243112004-01-04 15:48:17 +00001602 /* must reset current TB so that interrupts cannot modify the
1603 links while we are modifying them */
1604 env->current_tb = NULL;
1605
bellard33417e72003-08-10 21:47:01 +00001606 for(i = 0; i < CPU_TLB_SIZE; i++) {
bellard84b7b8e2005-11-28 21:19:04 +00001607 env->tlb_table[0][i].addr_read = -1;
1608 env->tlb_table[0][i].addr_write = -1;
1609 env->tlb_table[0][i].addr_code = -1;
1610 env->tlb_table[1][i].addr_read = -1;
1611 env->tlb_table[1][i].addr_write = -1;
1612 env->tlb_table[1][i].addr_code = -1;
j_mayer6fa4cea2007-04-05 06:43:27 +00001613#if (NB_MMU_MODES >= 3)
1614 env->tlb_table[2][i].addr_read = -1;
1615 env->tlb_table[2][i].addr_write = -1;
1616 env->tlb_table[2][i].addr_code = -1;
1617#if (NB_MMU_MODES == 4)
1618 env->tlb_table[3][i].addr_read = -1;
1619 env->tlb_table[3][i].addr_write = -1;
1620 env->tlb_table[3][i].addr_code = -1;
1621#endif
1622#endif
bellard33417e72003-08-10 21:47:01 +00001623 }
bellard9fa3e852004-01-04 18:06:42 +00001624
bellard8a40a182005-11-20 10:35:40 +00001625 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
bellard9fa3e852004-01-04 18:06:42 +00001626
bellard0a962c02005-02-10 22:00:27 +00001627#ifdef USE_KQEMU
1628 if (env->kqemu_enabled) {
1629 kqemu_flush(env, flush_global);
1630 }
1631#endif
bellarde3db7222005-01-26 22:00:47 +00001632 tlb_flush_count++;
bellard33417e72003-08-10 21:47:01 +00001633}
1634
bellard274da6b2004-05-20 21:56:27 +00001635static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
bellard61382a52003-10-27 21:22:23 +00001636{
ths5fafdf22007-09-16 21:08:06 +00001637 if (addr == (tlb_entry->addr_read &
bellard84b7b8e2005-11-28 21:19:04 +00001638 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
ths5fafdf22007-09-16 21:08:06 +00001639 addr == (tlb_entry->addr_write &
bellard84b7b8e2005-11-28 21:19:04 +00001640 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
ths5fafdf22007-09-16 21:08:06 +00001641 addr == (tlb_entry->addr_code &
bellard84b7b8e2005-11-28 21:19:04 +00001642 (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1643 tlb_entry->addr_read = -1;
1644 tlb_entry->addr_write = -1;
1645 tlb_entry->addr_code = -1;
1646 }
bellard61382a52003-10-27 21:22:23 +00001647}
1648
bellard2e126692004-04-25 21:28:44 +00001649void tlb_flush_page(CPUState *env, target_ulong addr)
bellard33417e72003-08-10 21:47:01 +00001650{
bellard8a40a182005-11-20 10:35:40 +00001651 int i;
bellard01243112004-01-04 15:48:17 +00001652
bellard9fa3e852004-01-04 18:06:42 +00001653#if defined(DEBUG_TLB)
bellard108c49b2005-07-24 12:55:09 +00001654 printf("tlb_flush_page: " TARGET_FMT_lx "\n", addr);
bellard9fa3e852004-01-04 18:06:42 +00001655#endif
bellard01243112004-01-04 15:48:17 +00001656 /* must reset current TB so that interrupts cannot modify the
1657 links while we are modifying them */
1658 env->current_tb = NULL;
bellard33417e72003-08-10 21:47:01 +00001659
bellard61382a52003-10-27 21:22:23 +00001660 addr &= TARGET_PAGE_MASK;
bellard33417e72003-08-10 21:47:01 +00001661 i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
bellard84b7b8e2005-11-28 21:19:04 +00001662 tlb_flush_entry(&env->tlb_table[0][i], addr);
1663 tlb_flush_entry(&env->tlb_table[1][i], addr);
j_mayer6fa4cea2007-04-05 06:43:27 +00001664#if (NB_MMU_MODES >= 3)
1665 tlb_flush_entry(&env->tlb_table[2][i], addr);
1666#if (NB_MMU_MODES == 4)
1667 tlb_flush_entry(&env->tlb_table[3][i], addr);
1668#endif
1669#endif
bellard01243112004-01-04 15:48:17 +00001670
edgar_igl5c751e92008-05-06 08:44:21 +00001671 tlb_flush_jmp_cache(env, addr);
bellard9fa3e852004-01-04 18:06:42 +00001672
bellard0a962c02005-02-10 22:00:27 +00001673#ifdef USE_KQEMU
1674 if (env->kqemu_enabled) {
1675 kqemu_flush_page(env, addr);
1676 }
1677#endif
bellard9fa3e852004-01-04 18:06:42 +00001678}
1679
bellard9fa3e852004-01-04 18:06:42 +00001680/* update the TLBs so that writes to code in the virtual page 'addr'
1681 can be detected */
bellard6a00d602005-11-21 23:25:50 +00001682static void tlb_protect_code(ram_addr_t ram_addr)
bellard61382a52003-10-27 21:22:23 +00001683{
ths5fafdf22007-09-16 21:08:06 +00001684 cpu_physical_memory_reset_dirty(ram_addr,
bellard6a00d602005-11-21 23:25:50 +00001685 ram_addr + TARGET_PAGE_SIZE,
1686 CODE_DIRTY_FLAG);
bellard9fa3e852004-01-04 18:06:42 +00001687}
1688
bellard9fa3e852004-01-04 18:06:42 +00001689/* update the TLB so that writes in physical page 'phys_addr' are no longer
bellard3a7d9292005-08-21 09:26:42 +00001690 tested for self modifying code */
ths5fafdf22007-09-16 21:08:06 +00001691static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
bellard3a7d9292005-08-21 09:26:42 +00001692 target_ulong vaddr)
bellard9fa3e852004-01-04 18:06:42 +00001693{
bellard3a7d9292005-08-21 09:26:42 +00001694 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] |= CODE_DIRTY_FLAG;
bellard1ccde1c2004-02-06 19:46:14 +00001695}
1696
ths5fafdf22007-09-16 21:08:06 +00001697static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
bellard1ccde1c2004-02-06 19:46:14 +00001698 unsigned long start, unsigned long length)
1699{
1700 unsigned long addr;
bellard84b7b8e2005-11-28 21:19:04 +00001701 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1702 addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
bellard1ccde1c2004-02-06 19:46:14 +00001703 if ((addr - start) < length) {
pbrook0f459d12008-06-09 00:20:13 +00001704 tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
bellard1ccde1c2004-02-06 19:46:14 +00001705 }
1706 }
1707}
1708
bellard3a7d9292005-08-21 09:26:42 +00001709void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
bellard0a962c02005-02-10 22:00:27 +00001710 int dirty_flags)
bellard1ccde1c2004-02-06 19:46:14 +00001711{
1712 CPUState *env;
bellard4f2ac232004-04-26 19:44:02 +00001713 unsigned long length, start1;
bellard0a962c02005-02-10 22:00:27 +00001714 int i, mask, len;
1715 uint8_t *p;
bellard1ccde1c2004-02-06 19:46:14 +00001716
1717 start &= TARGET_PAGE_MASK;
1718 end = TARGET_PAGE_ALIGN(end);
1719
1720 length = end - start;
1721 if (length == 0)
1722 return;
bellard0a962c02005-02-10 22:00:27 +00001723 len = length >> TARGET_PAGE_BITS;
bellard3a7d9292005-08-21 09:26:42 +00001724#ifdef USE_KQEMU
bellard6a00d602005-11-21 23:25:50 +00001725 /* XXX: should not depend on cpu context */
1726 env = first_cpu;
bellard3a7d9292005-08-21 09:26:42 +00001727 if (env->kqemu_enabled) {
bellardf23db162005-08-21 19:12:28 +00001728 ram_addr_t addr;
1729 addr = start;
1730 for(i = 0; i < len; i++) {
1731 kqemu_set_notdirty(env, addr);
1732 addr += TARGET_PAGE_SIZE;
1733 }
bellard3a7d9292005-08-21 09:26:42 +00001734 }
1735#endif
bellardf23db162005-08-21 19:12:28 +00001736 mask = ~dirty_flags;
1737 p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
1738 for(i = 0; i < len; i++)
1739 p[i] &= mask;
1740
bellard1ccde1c2004-02-06 19:46:14 +00001741 /* we modify the TLB cache so that the dirty bit will be set again
1742 when accessing the range */
bellard59817cc2004-02-16 22:01:13 +00001743 start1 = start + (unsigned long)phys_ram_base;
bellard6a00d602005-11-21 23:25:50 +00001744 for(env = first_cpu; env != NULL; env = env->next_cpu) {
1745 for(i = 0; i < CPU_TLB_SIZE; i++)
bellard84b7b8e2005-11-28 21:19:04 +00001746 tlb_reset_dirty_range(&env->tlb_table[0][i], start1, length);
bellard6a00d602005-11-21 23:25:50 +00001747 for(i = 0; i < CPU_TLB_SIZE; i++)
bellard84b7b8e2005-11-28 21:19:04 +00001748 tlb_reset_dirty_range(&env->tlb_table[1][i], start1, length);
j_mayer6fa4cea2007-04-05 06:43:27 +00001749#if (NB_MMU_MODES >= 3)
1750 for(i = 0; i < CPU_TLB_SIZE; i++)
1751 tlb_reset_dirty_range(&env->tlb_table[2][i], start1, length);
1752#if (NB_MMU_MODES == 4)
1753 for(i = 0; i < CPU_TLB_SIZE; i++)
1754 tlb_reset_dirty_range(&env->tlb_table[3][i], start1, length);
1755#endif
1756#endif
bellard6a00d602005-11-21 23:25:50 +00001757 }
bellard1ccde1c2004-02-06 19:46:14 +00001758}
1759
bellard3a7d9292005-08-21 09:26:42 +00001760static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1761{
1762 ram_addr_t ram_addr;
1763
bellard84b7b8e2005-11-28 21:19:04 +00001764 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
ths5fafdf22007-09-16 21:08:06 +00001765 ram_addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) +
bellard3a7d9292005-08-21 09:26:42 +00001766 tlb_entry->addend - (unsigned long)phys_ram_base;
1767 if (!cpu_physical_memory_is_dirty(ram_addr)) {
pbrook0f459d12008-06-09 00:20:13 +00001768 tlb_entry->addr_write |= TLB_NOTDIRTY;
bellard3a7d9292005-08-21 09:26:42 +00001769 }
1770 }
1771}
1772
1773/* update the TLB according to the current state of the dirty bits */
1774void cpu_tlb_update_dirty(CPUState *env)
1775{
1776 int i;
1777 for(i = 0; i < CPU_TLB_SIZE; i++)
bellard84b7b8e2005-11-28 21:19:04 +00001778 tlb_update_dirty(&env->tlb_table[0][i]);
bellard3a7d9292005-08-21 09:26:42 +00001779 for(i = 0; i < CPU_TLB_SIZE; i++)
bellard84b7b8e2005-11-28 21:19:04 +00001780 tlb_update_dirty(&env->tlb_table[1][i]);
j_mayer6fa4cea2007-04-05 06:43:27 +00001781#if (NB_MMU_MODES >= 3)
1782 for(i = 0; i < CPU_TLB_SIZE; i++)
1783 tlb_update_dirty(&env->tlb_table[2][i]);
1784#if (NB_MMU_MODES == 4)
1785 for(i = 0; i < CPU_TLB_SIZE; i++)
1786 tlb_update_dirty(&env->tlb_table[3][i]);
1787#endif
1788#endif
bellard3a7d9292005-08-21 09:26:42 +00001789}
1790
pbrook0f459d12008-06-09 00:20:13 +00001791static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, target_ulong vaddr)
bellard1ccde1c2004-02-06 19:46:14 +00001792{
pbrook0f459d12008-06-09 00:20:13 +00001793 if (tlb_entry->addr_write == (vaddr | TLB_NOTDIRTY))
1794 tlb_entry->addr_write = vaddr;
bellard1ccde1c2004-02-06 19:46:14 +00001795}
1796
pbrook0f459d12008-06-09 00:20:13 +00001797/* update the TLB corresponding to virtual page vaddr
1798 so that it is no longer dirty */
1799static inline void tlb_set_dirty(CPUState *env, target_ulong vaddr)
bellard1ccde1c2004-02-06 19:46:14 +00001800{
bellard1ccde1c2004-02-06 19:46:14 +00001801 int i;
1802
pbrook0f459d12008-06-09 00:20:13 +00001803 vaddr &= TARGET_PAGE_MASK;
bellard1ccde1c2004-02-06 19:46:14 +00001804 i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
pbrook0f459d12008-06-09 00:20:13 +00001805 tlb_set_dirty1(&env->tlb_table[0][i], vaddr);
1806 tlb_set_dirty1(&env->tlb_table[1][i], vaddr);
j_mayer6fa4cea2007-04-05 06:43:27 +00001807#if (NB_MMU_MODES >= 3)
pbrook0f459d12008-06-09 00:20:13 +00001808 tlb_set_dirty1(&env->tlb_table[2][i], vaddr);
j_mayer6fa4cea2007-04-05 06:43:27 +00001809#if (NB_MMU_MODES == 4)
pbrook0f459d12008-06-09 00:20:13 +00001810 tlb_set_dirty1(&env->tlb_table[3][i], vaddr);
j_mayer6fa4cea2007-04-05 06:43:27 +00001811#endif
1812#endif
bellard9fa3e852004-01-04 18:06:42 +00001813}
1814
bellard59817cc2004-02-16 22:01:13 +00001815/* add a new TLB entry. At most one entry for a given virtual address
1816 is permitted. Return 0 if OK or 2 if the page could not be mapped
1817 (can only happen in non SOFTMMU mode for I/O pages or pages
1818 conflicting with the host address space). */
ths5fafdf22007-09-16 21:08:06 +00001819int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
1820 target_phys_addr_t paddr, int prot,
j_mayer6ebbf392007-10-14 07:07:08 +00001821 int mmu_idx, int is_softmmu)
bellard9fa3e852004-01-04 18:06:42 +00001822{
bellard92e873b2004-05-21 14:52:29 +00001823 PhysPageDesc *p;
bellard4f2ac232004-04-26 19:44:02 +00001824 unsigned long pd;
bellard9fa3e852004-01-04 18:06:42 +00001825 unsigned int index;
bellard4f2ac232004-04-26 19:44:02 +00001826 target_ulong address;
pbrook0f459d12008-06-09 00:20:13 +00001827 target_ulong code_address;
bellard108c49b2005-07-24 12:55:09 +00001828 target_phys_addr_t addend;
bellard9fa3e852004-01-04 18:06:42 +00001829 int ret;
bellard84b7b8e2005-11-28 21:19:04 +00001830 CPUTLBEntry *te;
pbrook6658ffb2007-03-16 23:58:11 +00001831 int i;
pbrook0f459d12008-06-09 00:20:13 +00001832 target_phys_addr_t iotlb;
bellard9fa3e852004-01-04 18:06:42 +00001833
bellard92e873b2004-05-21 14:52:29 +00001834 p = phys_page_find(paddr >> TARGET_PAGE_BITS);
bellard9fa3e852004-01-04 18:06:42 +00001835 if (!p) {
1836 pd = IO_MEM_UNASSIGNED;
bellard9fa3e852004-01-04 18:06:42 +00001837 } else {
1838 pd = p->phys_offset;
bellard9fa3e852004-01-04 18:06:42 +00001839 }
1840#if defined(DEBUG_TLB)
j_mayer6ebbf392007-10-14 07:07:08 +00001841 printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x idx=%d smmu=%d pd=0x%08lx\n",
1842 vaddr, (int)paddr, prot, mmu_idx, is_softmmu, pd);
bellard9fa3e852004-01-04 18:06:42 +00001843#endif
1844
1845 ret = 0;
pbrook0f459d12008-06-09 00:20:13 +00001846 address = vaddr;
1847 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
1848 /* IO memory case (romd handled later) */
1849 address |= TLB_MMIO;
1850 }
1851 addend = (unsigned long)phys_ram_base + (pd & TARGET_PAGE_MASK);
1852 if ((pd & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
1853 /* Normal RAM. */
1854 iotlb = pd & TARGET_PAGE_MASK;
1855 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM)
1856 iotlb |= IO_MEM_NOTDIRTY;
1857 else
1858 iotlb |= IO_MEM_ROM;
1859 } else {
1860 /* IO handlers are currently passed a phsical address.
1861 It would be nice to pass an offset from the base address
1862 of that region. This would avoid having to special case RAM,
1863 and avoid full address decoding in every device.
1864 We can't use the high bits of pd for this because
1865 IO_MEM_ROMD uses these as a ram address. */
1866 iotlb = (pd & ~TARGET_PAGE_MASK) + paddr;
1867 }
pbrook6658ffb2007-03-16 23:58:11 +00001868
pbrook0f459d12008-06-09 00:20:13 +00001869 code_address = address;
1870 /* Make accesses to pages with watchpoints go via the
1871 watchpoint trap routines. */
1872 for (i = 0; i < env->nb_watchpoints; i++) {
1873 if (vaddr == (env->watchpoint[i].vaddr & TARGET_PAGE_MASK)) {
1874 iotlb = io_mem_watch + paddr;
1875 /* TODO: The memory case can be optimized by not trapping
1876 reads of pages with a write breakpoint. */
1877 address |= TLB_MMIO;
pbrook6658ffb2007-03-16 23:58:11 +00001878 }
pbrook0f459d12008-06-09 00:20:13 +00001879 }
balrogd79acba2007-06-26 20:01:13 +00001880
pbrook0f459d12008-06-09 00:20:13 +00001881 index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1882 env->iotlb[mmu_idx][index] = iotlb - vaddr;
1883 te = &env->tlb_table[mmu_idx][index];
1884 te->addend = addend - vaddr;
1885 if (prot & PAGE_READ) {
1886 te->addr_read = address;
1887 } else {
1888 te->addr_read = -1;
1889 }
edgar_igl5c751e92008-05-06 08:44:21 +00001890
pbrook0f459d12008-06-09 00:20:13 +00001891 if (prot & PAGE_EXEC) {
1892 te->addr_code = code_address;
1893 } else {
1894 te->addr_code = -1;
1895 }
1896 if (prot & PAGE_WRITE) {
1897 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM ||
1898 (pd & IO_MEM_ROMD)) {
1899 /* Write access calls the I/O callback. */
1900 te->addr_write = address | TLB_MMIO;
1901 } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
1902 !cpu_physical_memory_is_dirty(pd)) {
1903 te->addr_write = address | TLB_NOTDIRTY;
bellard84b7b8e2005-11-28 21:19:04 +00001904 } else {
pbrook0f459d12008-06-09 00:20:13 +00001905 te->addr_write = address;
bellard9fa3e852004-01-04 18:06:42 +00001906 }
pbrook0f459d12008-06-09 00:20:13 +00001907 } else {
1908 te->addr_write = -1;
bellard9fa3e852004-01-04 18:06:42 +00001909 }
bellard9fa3e852004-01-04 18:06:42 +00001910 return ret;
1911}
1912
bellard01243112004-01-04 15:48:17 +00001913#else
1914
bellardee8b7022004-02-03 23:35:10 +00001915void tlb_flush(CPUState *env, int flush_global)
bellard01243112004-01-04 15:48:17 +00001916{
1917}
1918
bellard2e126692004-04-25 21:28:44 +00001919void tlb_flush_page(CPUState *env, target_ulong addr)
bellard01243112004-01-04 15:48:17 +00001920{
1921}
1922
ths5fafdf22007-09-16 21:08:06 +00001923int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
1924 target_phys_addr_t paddr, int prot,
j_mayer6ebbf392007-10-14 07:07:08 +00001925 int mmu_idx, int is_softmmu)
bellard33417e72003-08-10 21:47:01 +00001926{
bellard9fa3e852004-01-04 18:06:42 +00001927 return 0;
1928}
bellard33417e72003-08-10 21:47:01 +00001929
bellard9fa3e852004-01-04 18:06:42 +00001930/* dump memory mappings */
1931void page_dump(FILE *f)
1932{
1933 unsigned long start, end;
1934 int i, j, prot, prot1;
1935 PageDesc *p;
1936
1937 fprintf(f, "%-8s %-8s %-8s %s\n",
1938 "start", "end", "size", "prot");
1939 start = -1;
1940 end = -1;
1941 prot = 0;
1942 for(i = 0; i <= L1_SIZE; i++) {
1943 if (i < L1_SIZE)
1944 p = l1_map[i];
1945 else
1946 p = NULL;
1947 for(j = 0;j < L2_SIZE; j++) {
1948 if (!p)
1949 prot1 = 0;
1950 else
1951 prot1 = p[j].flags;
1952 if (prot1 != prot) {
1953 end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
1954 if (start != -1) {
1955 fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
ths5fafdf22007-09-16 21:08:06 +00001956 start, end, end - start,
bellard9fa3e852004-01-04 18:06:42 +00001957 prot & PAGE_READ ? 'r' : '-',
1958 prot & PAGE_WRITE ? 'w' : '-',
1959 prot & PAGE_EXEC ? 'x' : '-');
1960 }
1961 if (prot1 != 0)
1962 start = end;
1963 else
1964 start = -1;
1965 prot = prot1;
1966 }
1967 if (!p)
1968 break;
1969 }
bellard33417e72003-08-10 21:47:01 +00001970 }
bellard33417e72003-08-10 21:47:01 +00001971}
1972
pbrook53a59602006-03-25 19:31:22 +00001973int page_get_flags(target_ulong address)
bellard33417e72003-08-10 21:47:01 +00001974{
bellard9fa3e852004-01-04 18:06:42 +00001975 PageDesc *p;
1976
1977 p = page_find(address >> TARGET_PAGE_BITS);
bellard33417e72003-08-10 21:47:01 +00001978 if (!p)
bellard9fa3e852004-01-04 18:06:42 +00001979 return 0;
1980 return p->flags;
bellard33417e72003-08-10 21:47:01 +00001981}
1982
bellard9fa3e852004-01-04 18:06:42 +00001983/* modify the flags of a page and invalidate the code if
1984 necessary. The flag PAGE_WRITE_ORG is positionned automatically
1985 depending on PAGE_WRITE */
pbrook53a59602006-03-25 19:31:22 +00001986void page_set_flags(target_ulong start, target_ulong end, int flags)
bellard9fa3e852004-01-04 18:06:42 +00001987{
1988 PageDesc *p;
pbrook53a59602006-03-25 19:31:22 +00001989 target_ulong addr;
bellard9fa3e852004-01-04 18:06:42 +00001990
pbrookc8a706f2008-06-02 16:16:42 +00001991 /* mmap_lock should already be held. */
bellard9fa3e852004-01-04 18:06:42 +00001992 start = start & TARGET_PAGE_MASK;
1993 end = TARGET_PAGE_ALIGN(end);
1994 if (flags & PAGE_WRITE)
1995 flags |= PAGE_WRITE_ORG;
bellard9fa3e852004-01-04 18:06:42 +00001996 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1997 p = page_find_alloc(addr >> TARGET_PAGE_BITS);
pbrook17e23772008-06-09 13:47:45 +00001998 /* We may be called for host regions that are outside guest
1999 address space. */
2000 if (!p)
2001 return;
bellard9fa3e852004-01-04 18:06:42 +00002002 /* if the write protection is set, then we invalidate the code
2003 inside */
ths5fafdf22007-09-16 21:08:06 +00002004 if (!(p->flags & PAGE_WRITE) &&
bellard9fa3e852004-01-04 18:06:42 +00002005 (flags & PAGE_WRITE) &&
2006 p->first_tb) {
bellardd720b932004-04-25 17:57:43 +00002007 tb_invalidate_phys_page(addr, 0, NULL);
bellard9fa3e852004-01-04 18:06:42 +00002008 }
2009 p->flags = flags;
2010 }
bellard9fa3e852004-01-04 18:06:42 +00002011}
2012
ths3d97b402007-11-02 19:02:07 +00002013int page_check_range(target_ulong start, target_ulong len, int flags)
2014{
2015 PageDesc *p;
2016 target_ulong end;
2017 target_ulong addr;
2018
2019 end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
2020 start = start & TARGET_PAGE_MASK;
2021
2022 if( end < start )
2023 /* we've wrapped around */
2024 return -1;
2025 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2026 p = page_find(addr >> TARGET_PAGE_BITS);
2027 if( !p )
2028 return -1;
2029 if( !(p->flags & PAGE_VALID) )
2030 return -1;
2031
bellarddae32702007-11-14 10:51:00 +00002032 if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
ths3d97b402007-11-02 19:02:07 +00002033 return -1;
bellarddae32702007-11-14 10:51:00 +00002034 if (flags & PAGE_WRITE) {
2035 if (!(p->flags & PAGE_WRITE_ORG))
2036 return -1;
2037 /* unprotect the page if it was put read-only because it
2038 contains translated code */
2039 if (!(p->flags & PAGE_WRITE)) {
2040 if (!page_unprotect(addr, 0, NULL))
2041 return -1;
2042 }
2043 return 0;
2044 }
ths3d97b402007-11-02 19:02:07 +00002045 }
2046 return 0;
2047}
2048
bellard9fa3e852004-01-04 18:06:42 +00002049/* called from signal handler: invalidate the code and unprotect the
2050 page. Return TRUE if the fault was succesfully handled. */
pbrook53a59602006-03-25 19:31:22 +00002051int page_unprotect(target_ulong address, unsigned long pc, void *puc)
bellard9fa3e852004-01-04 18:06:42 +00002052{
2053 unsigned int page_index, prot, pindex;
2054 PageDesc *p, *p1;
pbrook53a59602006-03-25 19:31:22 +00002055 target_ulong host_start, host_end, addr;
bellard9fa3e852004-01-04 18:06:42 +00002056
pbrookc8a706f2008-06-02 16:16:42 +00002057 /* Technically this isn't safe inside a signal handler. However we
2058 know this only ever happens in a synchronous SEGV handler, so in
2059 practice it seems to be ok. */
2060 mmap_lock();
2061
bellard83fb7ad2004-07-05 21:25:26 +00002062 host_start = address & qemu_host_page_mask;
bellard9fa3e852004-01-04 18:06:42 +00002063 page_index = host_start >> TARGET_PAGE_BITS;
2064 p1 = page_find(page_index);
pbrookc8a706f2008-06-02 16:16:42 +00002065 if (!p1) {
2066 mmap_unlock();
bellard9fa3e852004-01-04 18:06:42 +00002067 return 0;
pbrookc8a706f2008-06-02 16:16:42 +00002068 }
bellard83fb7ad2004-07-05 21:25:26 +00002069 host_end = host_start + qemu_host_page_size;
bellard9fa3e852004-01-04 18:06:42 +00002070 p = p1;
2071 prot = 0;
2072 for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
2073 prot |= p->flags;
2074 p++;
2075 }
2076 /* if the page was really writable, then we change its
2077 protection back to writable */
2078 if (prot & PAGE_WRITE_ORG) {
2079 pindex = (address - host_start) >> TARGET_PAGE_BITS;
2080 if (!(p1[pindex].flags & PAGE_WRITE)) {
ths5fafdf22007-09-16 21:08:06 +00002081 mprotect((void *)g2h(host_start), qemu_host_page_size,
bellard9fa3e852004-01-04 18:06:42 +00002082 (prot & PAGE_BITS) | PAGE_WRITE);
2083 p1[pindex].flags |= PAGE_WRITE;
2084 /* and since the content will be modified, we must invalidate
2085 the corresponding translated code. */
bellardd720b932004-04-25 17:57:43 +00002086 tb_invalidate_phys_page(address, pc, puc);
bellard9fa3e852004-01-04 18:06:42 +00002087#ifdef DEBUG_TB_CHECK
2088 tb_invalidate_check(address);
2089#endif
pbrookc8a706f2008-06-02 16:16:42 +00002090 mmap_unlock();
bellard9fa3e852004-01-04 18:06:42 +00002091 return 1;
2092 }
2093 }
pbrookc8a706f2008-06-02 16:16:42 +00002094 mmap_unlock();
bellard9fa3e852004-01-04 18:06:42 +00002095 return 0;
2096}
2097
bellard6a00d602005-11-21 23:25:50 +00002098static inline void tlb_set_dirty(CPUState *env,
2099 unsigned long addr, target_ulong vaddr)
bellard1ccde1c2004-02-06 19:46:14 +00002100{
2101}
bellard9fa3e852004-01-04 18:06:42 +00002102#endif /* defined(CONFIG_USER_ONLY) */
2103
pbrooke2eef172008-06-08 01:09:01 +00002104#if !defined(CONFIG_USER_ONLY)
blueswir1db7b5422007-05-26 17:36:03 +00002105static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
aurel3200f82b82008-04-27 21:12:55 +00002106 ram_addr_t memory);
2107static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
2108 ram_addr_t orig_memory);
blueswir1db7b5422007-05-26 17:36:03 +00002109#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
2110 need_subpage) \
2111 do { \
2112 if (addr > start_addr) \
2113 start_addr2 = 0; \
2114 else { \
2115 start_addr2 = start_addr & ~TARGET_PAGE_MASK; \
2116 if (start_addr2 > 0) \
2117 need_subpage = 1; \
2118 } \
2119 \
blueswir149e9fba2007-05-30 17:25:06 +00002120 if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE) \
blueswir1db7b5422007-05-26 17:36:03 +00002121 end_addr2 = TARGET_PAGE_SIZE - 1; \
2122 else { \
2123 end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
2124 if (end_addr2 < TARGET_PAGE_SIZE - 1) \
2125 need_subpage = 1; \
2126 } \
2127 } while (0)
2128
bellard33417e72003-08-10 21:47:01 +00002129/* register physical memory. 'size' must be a multiple of the target
2130 page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
2131 io memory page */
ths5fafdf22007-09-16 21:08:06 +00002132void cpu_register_physical_memory(target_phys_addr_t start_addr,
aurel3200f82b82008-04-27 21:12:55 +00002133 ram_addr_t size,
2134 ram_addr_t phys_offset)
bellard33417e72003-08-10 21:47:01 +00002135{
bellard108c49b2005-07-24 12:55:09 +00002136 target_phys_addr_t addr, end_addr;
bellard92e873b2004-05-21 14:52:29 +00002137 PhysPageDesc *p;
bellard9d420372006-06-25 22:25:22 +00002138 CPUState *env;
aurel3200f82b82008-04-27 21:12:55 +00002139 ram_addr_t orig_size = size;
blueswir1db7b5422007-05-26 17:36:03 +00002140 void *subpage;
bellard33417e72003-08-10 21:47:01 +00002141
bellardda260242008-05-30 20:48:25 +00002142#ifdef USE_KQEMU
2143 /* XXX: should not depend on cpu context */
2144 env = first_cpu;
2145 if (env->kqemu_enabled) {
2146 kqemu_set_phys_mem(start_addr, size, phys_offset);
2147 }
2148#endif
bellard5fd386f2004-05-23 21:11:22 +00002149 size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
blueswir149e9fba2007-05-30 17:25:06 +00002150 end_addr = start_addr + (target_phys_addr_t)size;
2151 for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
blueswir1db7b5422007-05-26 17:36:03 +00002152 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2153 if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
aurel3200f82b82008-04-27 21:12:55 +00002154 ram_addr_t orig_memory = p->phys_offset;
blueswir1db7b5422007-05-26 17:36:03 +00002155 target_phys_addr_t start_addr2, end_addr2;
2156 int need_subpage = 0;
2157
2158 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2159 need_subpage);
blueswir14254fab2008-01-01 16:57:19 +00002160 if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
blueswir1db7b5422007-05-26 17:36:03 +00002161 if (!(orig_memory & IO_MEM_SUBPAGE)) {
2162 subpage = subpage_init((addr & TARGET_PAGE_MASK),
2163 &p->phys_offset, orig_memory);
2164 } else {
2165 subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
2166 >> IO_MEM_SHIFT];
2167 }
2168 subpage_register(subpage, start_addr2, end_addr2, phys_offset);
2169 } else {
2170 p->phys_offset = phys_offset;
2171 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2172 (phys_offset & IO_MEM_ROMD))
2173 phys_offset += TARGET_PAGE_SIZE;
2174 }
2175 } else {
2176 p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2177 p->phys_offset = phys_offset;
2178 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2179 (phys_offset & IO_MEM_ROMD))
2180 phys_offset += TARGET_PAGE_SIZE;
2181 else {
2182 target_phys_addr_t start_addr2, end_addr2;
2183 int need_subpage = 0;
2184
2185 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2186 end_addr2, need_subpage);
2187
blueswir14254fab2008-01-01 16:57:19 +00002188 if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
blueswir1db7b5422007-05-26 17:36:03 +00002189 subpage = subpage_init((addr & TARGET_PAGE_MASK),
2190 &p->phys_offset, IO_MEM_UNASSIGNED);
2191 subpage_register(subpage, start_addr2, end_addr2,
2192 phys_offset);
2193 }
2194 }
2195 }
bellard33417e72003-08-10 21:47:01 +00002196 }
ths3b46e622007-09-17 08:09:54 +00002197
bellard9d420372006-06-25 22:25:22 +00002198 /* since each CPU stores ram addresses in its TLB cache, we must
2199 reset the modified entries */
2200 /* XXX: slow ! */
2201 for(env = first_cpu; env != NULL; env = env->next_cpu) {
2202 tlb_flush(env, 1);
2203 }
bellard33417e72003-08-10 21:47:01 +00002204}
2205
bellardba863452006-09-24 18:41:10 +00002206/* XXX: temporary until new memory mapping API */
aurel3200f82b82008-04-27 21:12:55 +00002207ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr)
bellardba863452006-09-24 18:41:10 +00002208{
2209 PhysPageDesc *p;
2210
2211 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2212 if (!p)
2213 return IO_MEM_UNASSIGNED;
2214 return p->phys_offset;
2215}
2216
bellarde9a1ab12007-02-08 23:08:38 +00002217/* XXX: better than nothing */
aurel3200f82b82008-04-27 21:12:55 +00002218ram_addr_t qemu_ram_alloc(ram_addr_t size)
bellarde9a1ab12007-02-08 23:08:38 +00002219{
2220 ram_addr_t addr;
balrog7fb4fdc2008-04-24 17:59:27 +00002221 if ((phys_ram_alloc_offset + size) > phys_ram_size) {
bellarded441462008-05-23 11:56:45 +00002222 fprintf(stderr, "Not enough memory (requested_size = %" PRIu64 ", max memory = %" PRIu64 "\n",
2223 (uint64_t)size, (uint64_t)phys_ram_size);
bellarde9a1ab12007-02-08 23:08:38 +00002224 abort();
2225 }
2226 addr = phys_ram_alloc_offset;
2227 phys_ram_alloc_offset = TARGET_PAGE_ALIGN(phys_ram_alloc_offset + size);
2228 return addr;
2229}
2230
2231void qemu_ram_free(ram_addr_t addr)
2232{
2233}
2234
bellarda4193c82004-06-03 14:01:43 +00002235static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
bellard33417e72003-08-10 21:47:01 +00002236{
pbrook67d3b952006-12-18 05:03:52 +00002237#ifdef DEBUG_UNASSIGNED
blueswir1ab3d1722007-11-04 07:31:40 +00002238 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
pbrook67d3b952006-12-18 05:03:52 +00002239#endif
blueswir1b4f0a312007-05-06 17:59:24 +00002240#ifdef TARGET_SPARC
blueswir16c36d3f2007-05-17 19:30:10 +00002241 do_unassigned_access(addr, 0, 0, 0);
thsf1ccf902007-10-08 13:16:14 +00002242#elif TARGET_CRIS
2243 do_unassigned_access(addr, 0, 0, 0);
blueswir1b4f0a312007-05-06 17:59:24 +00002244#endif
bellard33417e72003-08-10 21:47:01 +00002245 return 0;
2246}
2247
bellarda4193c82004-06-03 14:01:43 +00002248static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
bellard33417e72003-08-10 21:47:01 +00002249{
pbrook67d3b952006-12-18 05:03:52 +00002250#ifdef DEBUG_UNASSIGNED
blueswir1ab3d1722007-11-04 07:31:40 +00002251 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
pbrook67d3b952006-12-18 05:03:52 +00002252#endif
blueswir1b4f0a312007-05-06 17:59:24 +00002253#ifdef TARGET_SPARC
blueswir16c36d3f2007-05-17 19:30:10 +00002254 do_unassigned_access(addr, 1, 0, 0);
thsf1ccf902007-10-08 13:16:14 +00002255#elif TARGET_CRIS
2256 do_unassigned_access(addr, 1, 0, 0);
blueswir1b4f0a312007-05-06 17:59:24 +00002257#endif
bellard33417e72003-08-10 21:47:01 +00002258}
2259
2260static CPUReadMemoryFunc *unassigned_mem_read[3] = {
2261 unassigned_mem_readb,
2262 unassigned_mem_readb,
2263 unassigned_mem_readb,
2264};
2265
2266static CPUWriteMemoryFunc *unassigned_mem_write[3] = {
2267 unassigned_mem_writeb,
2268 unassigned_mem_writeb,
2269 unassigned_mem_writeb,
2270};
2271
pbrook0f459d12008-06-09 00:20:13 +00002272static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr,
2273 uint32_t val)
bellard1ccde1c2004-02-06 19:46:14 +00002274{
bellard3a7d9292005-08-21 09:26:42 +00002275 int dirty_flags;
bellard3a7d9292005-08-21 09:26:42 +00002276 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2277 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2278#if !defined(CONFIG_USER_ONLY)
2279 tb_invalidate_phys_page_fast(ram_addr, 1);
2280 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2281#endif
2282 }
pbrook0f459d12008-06-09 00:20:13 +00002283 stb_p(phys_ram_base + ram_addr, val);
bellardf32fc642006-02-08 22:43:39 +00002284#ifdef USE_KQEMU
2285 if (cpu_single_env->kqemu_enabled &&
2286 (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2287 kqemu_modify_page(cpu_single_env, ram_addr);
2288#endif
bellardf23db162005-08-21 19:12:28 +00002289 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2290 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2291 /* we remove the notdirty callback only if the code has been
2292 flushed */
2293 if (dirty_flags == 0xff)
pbrook2e70f6e2008-06-29 01:03:05 +00002294 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
bellard1ccde1c2004-02-06 19:46:14 +00002295}
2296
pbrook0f459d12008-06-09 00:20:13 +00002297static void notdirty_mem_writew(void *opaque, target_phys_addr_t ram_addr,
2298 uint32_t val)
bellard1ccde1c2004-02-06 19:46:14 +00002299{
bellard3a7d9292005-08-21 09:26:42 +00002300 int dirty_flags;
bellard3a7d9292005-08-21 09:26:42 +00002301 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2302 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2303#if !defined(CONFIG_USER_ONLY)
2304 tb_invalidate_phys_page_fast(ram_addr, 2);
2305 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2306#endif
2307 }
pbrook0f459d12008-06-09 00:20:13 +00002308 stw_p(phys_ram_base + ram_addr, val);
bellardf32fc642006-02-08 22:43:39 +00002309#ifdef USE_KQEMU
2310 if (cpu_single_env->kqemu_enabled &&
2311 (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2312 kqemu_modify_page(cpu_single_env, ram_addr);
2313#endif
bellardf23db162005-08-21 19:12:28 +00002314 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2315 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2316 /* we remove the notdirty callback only if the code has been
2317 flushed */
2318 if (dirty_flags == 0xff)
pbrook2e70f6e2008-06-29 01:03:05 +00002319 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
bellard1ccde1c2004-02-06 19:46:14 +00002320}
2321
pbrook0f459d12008-06-09 00:20:13 +00002322static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr,
2323 uint32_t val)
bellard1ccde1c2004-02-06 19:46:14 +00002324{
bellard3a7d9292005-08-21 09:26:42 +00002325 int dirty_flags;
bellard3a7d9292005-08-21 09:26:42 +00002326 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2327 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2328#if !defined(CONFIG_USER_ONLY)
2329 tb_invalidate_phys_page_fast(ram_addr, 4);
2330 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2331#endif
2332 }
pbrook0f459d12008-06-09 00:20:13 +00002333 stl_p(phys_ram_base + ram_addr, val);
bellardf32fc642006-02-08 22:43:39 +00002334#ifdef USE_KQEMU
2335 if (cpu_single_env->kqemu_enabled &&
2336 (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2337 kqemu_modify_page(cpu_single_env, ram_addr);
2338#endif
bellardf23db162005-08-21 19:12:28 +00002339 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2340 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2341 /* we remove the notdirty callback only if the code has been
2342 flushed */
2343 if (dirty_flags == 0xff)
pbrook2e70f6e2008-06-29 01:03:05 +00002344 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
bellard1ccde1c2004-02-06 19:46:14 +00002345}
2346
bellard3a7d9292005-08-21 09:26:42 +00002347static CPUReadMemoryFunc *error_mem_read[3] = {
2348 NULL, /* never used */
2349 NULL, /* never used */
2350 NULL, /* never used */
2351};
2352
bellard1ccde1c2004-02-06 19:46:14 +00002353static CPUWriteMemoryFunc *notdirty_mem_write[3] = {
2354 notdirty_mem_writeb,
2355 notdirty_mem_writew,
2356 notdirty_mem_writel,
2357};
2358
pbrook0f459d12008-06-09 00:20:13 +00002359/* Generate a debug exception if a watchpoint has been hit. */
2360static void check_watchpoint(int offset, int flags)
2361{
2362 CPUState *env = cpu_single_env;
2363 target_ulong vaddr;
2364 int i;
2365
pbrook2e70f6e2008-06-29 01:03:05 +00002366 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
pbrook0f459d12008-06-09 00:20:13 +00002367 for (i = 0; i < env->nb_watchpoints; i++) {
2368 if (vaddr == env->watchpoint[i].vaddr
2369 && (env->watchpoint[i].type & flags)) {
2370 env->watchpoint_hit = i + 1;
2371 cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2372 break;
2373 }
2374 }
2375}
2376
pbrook6658ffb2007-03-16 23:58:11 +00002377/* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
2378 so these check for a hit then pass through to the normal out-of-line
2379 phys routines. */
2380static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
2381{
pbrook0f459d12008-06-09 00:20:13 +00002382 check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ);
pbrook6658ffb2007-03-16 23:58:11 +00002383 return ldub_phys(addr);
2384}
2385
2386static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
2387{
pbrook0f459d12008-06-09 00:20:13 +00002388 check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ);
pbrook6658ffb2007-03-16 23:58:11 +00002389 return lduw_phys(addr);
2390}
2391
2392static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
2393{
pbrook0f459d12008-06-09 00:20:13 +00002394 check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ);
pbrook6658ffb2007-03-16 23:58:11 +00002395 return ldl_phys(addr);
2396}
2397
pbrook6658ffb2007-03-16 23:58:11 +00002398static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
2399 uint32_t val)
2400{
pbrook0f459d12008-06-09 00:20:13 +00002401 check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE);
pbrook6658ffb2007-03-16 23:58:11 +00002402 stb_phys(addr, val);
2403}
2404
2405static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
2406 uint32_t val)
2407{
pbrook0f459d12008-06-09 00:20:13 +00002408 check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE);
pbrook6658ffb2007-03-16 23:58:11 +00002409 stw_phys(addr, val);
2410}
2411
2412static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
2413 uint32_t val)
2414{
pbrook0f459d12008-06-09 00:20:13 +00002415 check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE);
pbrook6658ffb2007-03-16 23:58:11 +00002416 stl_phys(addr, val);
2417}
2418
2419static CPUReadMemoryFunc *watch_mem_read[3] = {
2420 watch_mem_readb,
2421 watch_mem_readw,
2422 watch_mem_readl,
2423};
2424
2425static CPUWriteMemoryFunc *watch_mem_write[3] = {
2426 watch_mem_writeb,
2427 watch_mem_writew,
2428 watch_mem_writel,
2429};
pbrook6658ffb2007-03-16 23:58:11 +00002430
blueswir1db7b5422007-05-26 17:36:03 +00002431static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr,
2432 unsigned int len)
2433{
blueswir1db7b5422007-05-26 17:36:03 +00002434 uint32_t ret;
2435 unsigned int idx;
2436
2437 idx = SUBPAGE_IDX(addr - mmio->base);
2438#if defined(DEBUG_SUBPAGE)
2439 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
2440 mmio, len, addr, idx);
2441#endif
blueswir13ee89922008-01-02 19:45:26 +00002442 ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len], addr);
blueswir1db7b5422007-05-26 17:36:03 +00002443
2444 return ret;
2445}
2446
2447static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
2448 uint32_t value, unsigned int len)
2449{
blueswir1db7b5422007-05-26 17:36:03 +00002450 unsigned int idx;
2451
2452 idx = SUBPAGE_IDX(addr - mmio->base);
2453#if defined(DEBUG_SUBPAGE)
2454 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
2455 mmio, len, addr, idx, value);
2456#endif
blueswir13ee89922008-01-02 19:45:26 +00002457 (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len], addr, value);
blueswir1db7b5422007-05-26 17:36:03 +00002458}
2459
2460static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
2461{
2462#if defined(DEBUG_SUBPAGE)
2463 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2464#endif
2465
2466 return subpage_readlen(opaque, addr, 0);
2467}
2468
2469static void subpage_writeb (void *opaque, target_phys_addr_t addr,
2470 uint32_t value)
2471{
2472#if defined(DEBUG_SUBPAGE)
2473 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2474#endif
2475 subpage_writelen(opaque, addr, value, 0);
2476}
2477
2478static uint32_t subpage_readw (void *opaque, target_phys_addr_t addr)
2479{
2480#if defined(DEBUG_SUBPAGE)
2481 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2482#endif
2483
2484 return subpage_readlen(opaque, addr, 1);
2485}
2486
2487static void subpage_writew (void *opaque, target_phys_addr_t addr,
2488 uint32_t value)
2489{
2490#if defined(DEBUG_SUBPAGE)
2491 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2492#endif
2493 subpage_writelen(opaque, addr, value, 1);
2494}
2495
2496static uint32_t subpage_readl (void *opaque, target_phys_addr_t addr)
2497{
2498#if defined(DEBUG_SUBPAGE)
2499 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2500#endif
2501
2502 return subpage_readlen(opaque, addr, 2);
2503}
2504
2505static void subpage_writel (void *opaque,
2506 target_phys_addr_t addr, uint32_t value)
2507{
2508#if defined(DEBUG_SUBPAGE)
2509 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2510#endif
2511 subpage_writelen(opaque, addr, value, 2);
2512}
2513
2514static CPUReadMemoryFunc *subpage_read[] = {
2515 &subpage_readb,
2516 &subpage_readw,
2517 &subpage_readl,
2518};
2519
2520static CPUWriteMemoryFunc *subpage_write[] = {
2521 &subpage_writeb,
2522 &subpage_writew,
2523 &subpage_writel,
2524};
2525
2526static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
aurel3200f82b82008-04-27 21:12:55 +00002527 ram_addr_t memory)
blueswir1db7b5422007-05-26 17:36:03 +00002528{
2529 int idx, eidx;
blueswir14254fab2008-01-01 16:57:19 +00002530 unsigned int i;
blueswir1db7b5422007-05-26 17:36:03 +00002531
2532 if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
2533 return -1;
2534 idx = SUBPAGE_IDX(start);
2535 eidx = SUBPAGE_IDX(end);
2536#if defined(DEBUG_SUBPAGE)
2537 printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %d\n", __func__,
2538 mmio, start, end, idx, eidx, memory);
2539#endif
2540 memory >>= IO_MEM_SHIFT;
2541 for (; idx <= eidx; idx++) {
blueswir14254fab2008-01-01 16:57:19 +00002542 for (i = 0; i < 4; i++) {
blueswir13ee89922008-01-02 19:45:26 +00002543 if (io_mem_read[memory][i]) {
2544 mmio->mem_read[idx][i] = &io_mem_read[memory][i];
2545 mmio->opaque[idx][0][i] = io_mem_opaque[memory];
2546 }
2547 if (io_mem_write[memory][i]) {
2548 mmio->mem_write[idx][i] = &io_mem_write[memory][i];
2549 mmio->opaque[idx][1][i] = io_mem_opaque[memory];
2550 }
blueswir14254fab2008-01-01 16:57:19 +00002551 }
blueswir1db7b5422007-05-26 17:36:03 +00002552 }
2553
2554 return 0;
2555}
2556
aurel3200f82b82008-04-27 21:12:55 +00002557static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
2558 ram_addr_t orig_memory)
blueswir1db7b5422007-05-26 17:36:03 +00002559{
2560 subpage_t *mmio;
2561 int subpage_memory;
2562
2563 mmio = qemu_mallocz(sizeof(subpage_t));
2564 if (mmio != NULL) {
2565 mmio->base = base;
2566 subpage_memory = cpu_register_io_memory(0, subpage_read, subpage_write, mmio);
2567#if defined(DEBUG_SUBPAGE)
2568 printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
2569 mmio, base, TARGET_PAGE_SIZE, subpage_memory);
2570#endif
2571 *phys = subpage_memory | IO_MEM_SUBPAGE;
2572 subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory);
2573 }
2574
2575 return mmio;
2576}
2577
bellard33417e72003-08-10 21:47:01 +00002578static void io_mem_init(void)
2579{
bellard3a7d9292005-08-21 09:26:42 +00002580 cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read, unassigned_mem_write, NULL);
bellarda4193c82004-06-03 14:01:43 +00002581 cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write, NULL);
bellard3a7d9292005-08-21 09:26:42 +00002582 cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read, notdirty_mem_write, NULL);
bellard1ccde1c2004-02-06 19:46:14 +00002583 io_mem_nb = 5;
2584
pbrook0f459d12008-06-09 00:20:13 +00002585 io_mem_watch = cpu_register_io_memory(0, watch_mem_read,
pbrook6658ffb2007-03-16 23:58:11 +00002586 watch_mem_write, NULL);
bellard1ccde1c2004-02-06 19:46:14 +00002587 /* alloc dirty bits array */
bellard0a962c02005-02-10 22:00:27 +00002588 phys_ram_dirty = qemu_vmalloc(phys_ram_size >> TARGET_PAGE_BITS);
bellard3a7d9292005-08-21 09:26:42 +00002589 memset(phys_ram_dirty, 0xff, phys_ram_size >> TARGET_PAGE_BITS);
bellard33417e72003-08-10 21:47:01 +00002590}
2591
2592/* mem_read and mem_write are arrays of functions containing the
2593 function to access byte (index 0), word (index 1) and dword (index
blueswir13ee89922008-01-02 19:45:26 +00002594 2). Functions can be omitted with a NULL function pointer. The
2595 registered functions may be modified dynamically later.
2596 If io_index is non zero, the corresponding io zone is
blueswir14254fab2008-01-01 16:57:19 +00002597 modified. If it is zero, a new io zone is allocated. The return
2598 value can be used with cpu_register_physical_memory(). (-1) is
2599 returned if error. */
bellard33417e72003-08-10 21:47:01 +00002600int cpu_register_io_memory(int io_index,
2601 CPUReadMemoryFunc **mem_read,
bellarda4193c82004-06-03 14:01:43 +00002602 CPUWriteMemoryFunc **mem_write,
2603 void *opaque)
bellard33417e72003-08-10 21:47:01 +00002604{
blueswir14254fab2008-01-01 16:57:19 +00002605 int i, subwidth = 0;
bellard33417e72003-08-10 21:47:01 +00002606
2607 if (io_index <= 0) {
bellardb5ff1b32005-11-26 10:38:39 +00002608 if (io_mem_nb >= IO_MEM_NB_ENTRIES)
bellard33417e72003-08-10 21:47:01 +00002609 return -1;
2610 io_index = io_mem_nb++;
2611 } else {
2612 if (io_index >= IO_MEM_NB_ENTRIES)
2613 return -1;
2614 }
bellardb5ff1b32005-11-26 10:38:39 +00002615
bellard33417e72003-08-10 21:47:01 +00002616 for(i = 0;i < 3; i++) {
blueswir14254fab2008-01-01 16:57:19 +00002617 if (!mem_read[i] || !mem_write[i])
2618 subwidth = IO_MEM_SUBWIDTH;
bellard33417e72003-08-10 21:47:01 +00002619 io_mem_read[io_index][i] = mem_read[i];
2620 io_mem_write[io_index][i] = mem_write[i];
2621 }
bellarda4193c82004-06-03 14:01:43 +00002622 io_mem_opaque[io_index] = opaque;
blueswir14254fab2008-01-01 16:57:19 +00002623 return (io_index << IO_MEM_SHIFT) | subwidth;
bellard33417e72003-08-10 21:47:01 +00002624}
bellard61382a52003-10-27 21:22:23 +00002625
bellard8926b512004-10-10 15:14:20 +00002626CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index)
2627{
2628 return io_mem_write[io_index >> IO_MEM_SHIFT];
2629}
2630
2631CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index)
2632{
2633 return io_mem_read[io_index >> IO_MEM_SHIFT];
2634}
2635
pbrooke2eef172008-06-08 01:09:01 +00002636#endif /* !defined(CONFIG_USER_ONLY) */
2637
bellard13eb76e2004-01-24 15:23:36 +00002638/* physical memory access (slow version, mainly for debug) */
2639#if defined(CONFIG_USER_ONLY)
ths5fafdf22007-09-16 21:08:06 +00002640void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
bellard13eb76e2004-01-24 15:23:36 +00002641 int len, int is_write)
2642{
2643 int l, flags;
2644 target_ulong page;
pbrook53a59602006-03-25 19:31:22 +00002645 void * p;
bellard13eb76e2004-01-24 15:23:36 +00002646
2647 while (len > 0) {
2648 page = addr & TARGET_PAGE_MASK;
2649 l = (page + TARGET_PAGE_SIZE) - addr;
2650 if (l > len)
2651 l = len;
2652 flags = page_get_flags(page);
2653 if (!(flags & PAGE_VALID))
2654 return;
2655 if (is_write) {
2656 if (!(flags & PAGE_WRITE))
2657 return;
bellard579a97f2007-11-11 14:26:47 +00002658 /* XXX: this code should not depend on lock_user */
aurel3272fb7da2008-04-27 23:53:45 +00002659 if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
bellard579a97f2007-11-11 14:26:47 +00002660 /* FIXME - should this return an error rather than just fail? */
2661 return;
aurel3272fb7da2008-04-27 23:53:45 +00002662 memcpy(p, buf, l);
2663 unlock_user(p, addr, l);
bellard13eb76e2004-01-24 15:23:36 +00002664 } else {
2665 if (!(flags & PAGE_READ))
2666 return;
bellard579a97f2007-11-11 14:26:47 +00002667 /* XXX: this code should not depend on lock_user */
aurel3272fb7da2008-04-27 23:53:45 +00002668 if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
bellard579a97f2007-11-11 14:26:47 +00002669 /* FIXME - should this return an error rather than just fail? */
2670 return;
aurel3272fb7da2008-04-27 23:53:45 +00002671 memcpy(buf, p, l);
aurel325b257572008-04-28 08:54:59 +00002672 unlock_user(p, addr, 0);
bellard13eb76e2004-01-24 15:23:36 +00002673 }
2674 len -= l;
2675 buf += l;
2676 addr += l;
2677 }
2678}
bellard8df1cd02005-01-28 22:37:22 +00002679
bellard13eb76e2004-01-24 15:23:36 +00002680#else
ths5fafdf22007-09-16 21:08:06 +00002681void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
bellard13eb76e2004-01-24 15:23:36 +00002682 int len, int is_write)
2683{
2684 int l, io_index;
2685 uint8_t *ptr;
2686 uint32_t val;
bellard2e126692004-04-25 21:28:44 +00002687 target_phys_addr_t page;
2688 unsigned long pd;
bellard92e873b2004-05-21 14:52:29 +00002689 PhysPageDesc *p;
ths3b46e622007-09-17 08:09:54 +00002690
bellard13eb76e2004-01-24 15:23:36 +00002691 while (len > 0) {
2692 page = addr & TARGET_PAGE_MASK;
2693 l = (page + TARGET_PAGE_SIZE) - addr;
2694 if (l > len)
2695 l = len;
bellard92e873b2004-05-21 14:52:29 +00002696 p = phys_page_find(page >> TARGET_PAGE_BITS);
bellard13eb76e2004-01-24 15:23:36 +00002697 if (!p) {
2698 pd = IO_MEM_UNASSIGNED;
2699 } else {
2700 pd = p->phys_offset;
2701 }
ths3b46e622007-09-17 08:09:54 +00002702
bellard13eb76e2004-01-24 15:23:36 +00002703 if (is_write) {
bellard3a7d9292005-08-21 09:26:42 +00002704 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
bellard13eb76e2004-01-24 15:23:36 +00002705 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
bellard6a00d602005-11-21 23:25:50 +00002706 /* XXX: could force cpu_single_env to NULL to avoid
2707 potential bugs */
bellard13eb76e2004-01-24 15:23:36 +00002708 if (l >= 4 && ((addr & 3) == 0)) {
bellard1c213d12005-09-03 10:49:04 +00002709 /* 32 bit write access */
bellardc27004e2005-01-03 23:35:10 +00002710 val = ldl_p(buf);
bellarda4193c82004-06-03 14:01:43 +00002711 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
bellard13eb76e2004-01-24 15:23:36 +00002712 l = 4;
2713 } else if (l >= 2 && ((addr & 1) == 0)) {
bellard1c213d12005-09-03 10:49:04 +00002714 /* 16 bit write access */
bellardc27004e2005-01-03 23:35:10 +00002715 val = lduw_p(buf);
bellarda4193c82004-06-03 14:01:43 +00002716 io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
bellard13eb76e2004-01-24 15:23:36 +00002717 l = 2;
2718 } else {
bellard1c213d12005-09-03 10:49:04 +00002719 /* 8 bit write access */
bellardc27004e2005-01-03 23:35:10 +00002720 val = ldub_p(buf);
bellarda4193c82004-06-03 14:01:43 +00002721 io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val);
bellard13eb76e2004-01-24 15:23:36 +00002722 l = 1;
2723 }
2724 } else {
bellardb448f2f2004-02-25 23:24:04 +00002725 unsigned long addr1;
2726 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
bellard13eb76e2004-01-24 15:23:36 +00002727 /* RAM case */
bellardb448f2f2004-02-25 23:24:04 +00002728 ptr = phys_ram_base + addr1;
bellard13eb76e2004-01-24 15:23:36 +00002729 memcpy(ptr, buf, l);
bellard3a7d9292005-08-21 09:26:42 +00002730 if (!cpu_physical_memory_is_dirty(addr1)) {
2731 /* invalidate code */
2732 tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
2733 /* set dirty bit */
ths5fafdf22007-09-16 21:08:06 +00002734 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
bellardf23db162005-08-21 19:12:28 +00002735 (0xff & ~CODE_DIRTY_FLAG);
bellard3a7d9292005-08-21 09:26:42 +00002736 }
bellard13eb76e2004-01-24 15:23:36 +00002737 }
2738 } else {
ths5fafdf22007-09-16 21:08:06 +00002739 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
bellard2a4188a2006-06-25 21:54:59 +00002740 !(pd & IO_MEM_ROMD)) {
bellard13eb76e2004-01-24 15:23:36 +00002741 /* I/O case */
2742 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2743 if (l >= 4 && ((addr & 3) == 0)) {
2744 /* 32 bit read access */
bellarda4193c82004-06-03 14:01:43 +00002745 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
bellardc27004e2005-01-03 23:35:10 +00002746 stl_p(buf, val);
bellard13eb76e2004-01-24 15:23:36 +00002747 l = 4;
2748 } else if (l >= 2 && ((addr & 1) == 0)) {
2749 /* 16 bit read access */
bellarda4193c82004-06-03 14:01:43 +00002750 val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
bellardc27004e2005-01-03 23:35:10 +00002751 stw_p(buf, val);
bellard13eb76e2004-01-24 15:23:36 +00002752 l = 2;
2753 } else {
bellard1c213d12005-09-03 10:49:04 +00002754 /* 8 bit read access */
bellarda4193c82004-06-03 14:01:43 +00002755 val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr);
bellardc27004e2005-01-03 23:35:10 +00002756 stb_p(buf, val);
bellard13eb76e2004-01-24 15:23:36 +00002757 l = 1;
2758 }
2759 } else {
2760 /* RAM case */
ths5fafdf22007-09-16 21:08:06 +00002761 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
bellard13eb76e2004-01-24 15:23:36 +00002762 (addr & ~TARGET_PAGE_MASK);
2763 memcpy(buf, ptr, l);
2764 }
2765 }
2766 len -= l;
2767 buf += l;
2768 addr += l;
2769 }
2770}
bellard8df1cd02005-01-28 22:37:22 +00002771
bellardd0ecd2a2006-04-23 17:14:48 +00002772/* used for ROM loading : can write in RAM and ROM */
ths5fafdf22007-09-16 21:08:06 +00002773void cpu_physical_memory_write_rom(target_phys_addr_t addr,
bellardd0ecd2a2006-04-23 17:14:48 +00002774 const uint8_t *buf, int len)
2775{
2776 int l;
2777 uint8_t *ptr;
2778 target_phys_addr_t page;
2779 unsigned long pd;
2780 PhysPageDesc *p;
ths3b46e622007-09-17 08:09:54 +00002781
bellardd0ecd2a2006-04-23 17:14:48 +00002782 while (len > 0) {
2783 page = addr & TARGET_PAGE_MASK;
2784 l = (page + TARGET_PAGE_SIZE) - addr;
2785 if (l > len)
2786 l = len;
2787 p = phys_page_find(page >> TARGET_PAGE_BITS);
2788 if (!p) {
2789 pd = IO_MEM_UNASSIGNED;
2790 } else {
2791 pd = p->phys_offset;
2792 }
ths3b46e622007-09-17 08:09:54 +00002793
bellardd0ecd2a2006-04-23 17:14:48 +00002794 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
bellard2a4188a2006-06-25 21:54:59 +00002795 (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
2796 !(pd & IO_MEM_ROMD)) {
bellardd0ecd2a2006-04-23 17:14:48 +00002797 /* do nothing */
2798 } else {
2799 unsigned long addr1;
2800 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2801 /* ROM/RAM case */
2802 ptr = phys_ram_base + addr1;
2803 memcpy(ptr, buf, l);
2804 }
2805 len -= l;
2806 buf += l;
2807 addr += l;
2808 }
2809}
2810
2811
bellard8df1cd02005-01-28 22:37:22 +00002812/* warning: addr must be aligned */
2813uint32_t ldl_phys(target_phys_addr_t addr)
2814{
2815 int io_index;
2816 uint8_t *ptr;
2817 uint32_t val;
2818 unsigned long pd;
2819 PhysPageDesc *p;
2820
2821 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2822 if (!p) {
2823 pd = IO_MEM_UNASSIGNED;
2824 } else {
2825 pd = p->phys_offset;
2826 }
ths3b46e622007-09-17 08:09:54 +00002827
ths5fafdf22007-09-16 21:08:06 +00002828 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
bellard2a4188a2006-06-25 21:54:59 +00002829 !(pd & IO_MEM_ROMD)) {
bellard8df1cd02005-01-28 22:37:22 +00002830 /* I/O case */
2831 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2832 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2833 } else {
2834 /* RAM case */
ths5fafdf22007-09-16 21:08:06 +00002835 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
bellard8df1cd02005-01-28 22:37:22 +00002836 (addr & ~TARGET_PAGE_MASK);
2837 val = ldl_p(ptr);
2838 }
2839 return val;
2840}
2841
bellard84b7b8e2005-11-28 21:19:04 +00002842/* warning: addr must be aligned */
2843uint64_t ldq_phys(target_phys_addr_t addr)
2844{
2845 int io_index;
2846 uint8_t *ptr;
2847 uint64_t val;
2848 unsigned long pd;
2849 PhysPageDesc *p;
2850
2851 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2852 if (!p) {
2853 pd = IO_MEM_UNASSIGNED;
2854 } else {
2855 pd = p->phys_offset;
2856 }
ths3b46e622007-09-17 08:09:54 +00002857
bellard2a4188a2006-06-25 21:54:59 +00002858 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
2859 !(pd & IO_MEM_ROMD)) {
bellard84b7b8e2005-11-28 21:19:04 +00002860 /* I/O case */
2861 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2862#ifdef TARGET_WORDS_BIGENDIAN
2863 val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
2864 val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
2865#else
2866 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2867 val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
2868#endif
2869 } else {
2870 /* RAM case */
ths5fafdf22007-09-16 21:08:06 +00002871 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
bellard84b7b8e2005-11-28 21:19:04 +00002872 (addr & ~TARGET_PAGE_MASK);
2873 val = ldq_p(ptr);
2874 }
2875 return val;
2876}
2877
bellardaab33092005-10-30 20:48:42 +00002878/* XXX: optimize */
2879uint32_t ldub_phys(target_phys_addr_t addr)
2880{
2881 uint8_t val;
2882 cpu_physical_memory_read(addr, &val, 1);
2883 return val;
2884}
2885
2886/* XXX: optimize */
2887uint32_t lduw_phys(target_phys_addr_t addr)
2888{
2889 uint16_t val;
2890 cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
2891 return tswap16(val);
2892}
2893
bellard8df1cd02005-01-28 22:37:22 +00002894/* warning: addr must be aligned. The ram page is not masked as dirty
2895 and the code inside is not invalidated. It is useful if the dirty
2896 bits are used to track modified PTEs */
2897void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
2898{
2899 int io_index;
2900 uint8_t *ptr;
2901 unsigned long pd;
2902 PhysPageDesc *p;
2903
2904 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2905 if (!p) {
2906 pd = IO_MEM_UNASSIGNED;
2907 } else {
2908 pd = p->phys_offset;
2909 }
ths3b46e622007-09-17 08:09:54 +00002910
bellard3a7d9292005-08-21 09:26:42 +00002911 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
bellard8df1cd02005-01-28 22:37:22 +00002912 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2913 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2914 } else {
ths5fafdf22007-09-16 21:08:06 +00002915 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
bellard8df1cd02005-01-28 22:37:22 +00002916 (addr & ~TARGET_PAGE_MASK);
2917 stl_p(ptr, val);
2918 }
2919}
2920
j_mayerbc98a7e2007-04-04 07:55:12 +00002921void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
2922{
2923 int io_index;
2924 uint8_t *ptr;
2925 unsigned long pd;
2926 PhysPageDesc *p;
2927
2928 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2929 if (!p) {
2930 pd = IO_MEM_UNASSIGNED;
2931 } else {
2932 pd = p->phys_offset;
2933 }
ths3b46e622007-09-17 08:09:54 +00002934
j_mayerbc98a7e2007-04-04 07:55:12 +00002935 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2936 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2937#ifdef TARGET_WORDS_BIGENDIAN
2938 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
2939 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
2940#else
2941 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2942 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
2943#endif
2944 } else {
ths5fafdf22007-09-16 21:08:06 +00002945 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
j_mayerbc98a7e2007-04-04 07:55:12 +00002946 (addr & ~TARGET_PAGE_MASK);
2947 stq_p(ptr, val);
2948 }
2949}
2950
bellard8df1cd02005-01-28 22:37:22 +00002951/* warning: addr must be aligned */
bellard8df1cd02005-01-28 22:37:22 +00002952void stl_phys(target_phys_addr_t addr, uint32_t val)
2953{
2954 int io_index;
2955 uint8_t *ptr;
2956 unsigned long pd;
2957 PhysPageDesc *p;
2958
2959 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2960 if (!p) {
2961 pd = IO_MEM_UNASSIGNED;
2962 } else {
2963 pd = p->phys_offset;
2964 }
ths3b46e622007-09-17 08:09:54 +00002965
bellard3a7d9292005-08-21 09:26:42 +00002966 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
bellard8df1cd02005-01-28 22:37:22 +00002967 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2968 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2969 } else {
2970 unsigned long addr1;
2971 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2972 /* RAM case */
2973 ptr = phys_ram_base + addr1;
2974 stl_p(ptr, val);
bellard3a7d9292005-08-21 09:26:42 +00002975 if (!cpu_physical_memory_is_dirty(addr1)) {
2976 /* invalidate code */
2977 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
2978 /* set dirty bit */
bellardf23db162005-08-21 19:12:28 +00002979 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
2980 (0xff & ~CODE_DIRTY_FLAG);
bellard3a7d9292005-08-21 09:26:42 +00002981 }
bellard8df1cd02005-01-28 22:37:22 +00002982 }
2983}
2984
bellardaab33092005-10-30 20:48:42 +00002985/* XXX: optimize */
2986void stb_phys(target_phys_addr_t addr, uint32_t val)
2987{
2988 uint8_t v = val;
2989 cpu_physical_memory_write(addr, &v, 1);
2990}
2991
2992/* XXX: optimize */
2993void stw_phys(target_phys_addr_t addr, uint32_t val)
2994{
2995 uint16_t v = tswap16(val);
2996 cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
2997}
2998
2999/* XXX: optimize */
3000void stq_phys(target_phys_addr_t addr, uint64_t val)
3001{
3002 val = tswap64(val);
3003 cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
3004}
3005
bellard13eb76e2004-01-24 15:23:36 +00003006#endif
3007
3008/* virtual memory access for debug */
ths5fafdf22007-09-16 21:08:06 +00003009int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
bellardb448f2f2004-02-25 23:24:04 +00003010 uint8_t *buf, int len, int is_write)
bellard13eb76e2004-01-24 15:23:36 +00003011{
3012 int l;
j_mayer9b3c35e2007-04-07 11:21:28 +00003013 target_phys_addr_t phys_addr;
3014 target_ulong page;
bellard13eb76e2004-01-24 15:23:36 +00003015
3016 while (len > 0) {
3017 page = addr & TARGET_PAGE_MASK;
3018 phys_addr = cpu_get_phys_page_debug(env, page);
3019 /* if no physical page mapped, return an error */
3020 if (phys_addr == -1)
3021 return -1;
3022 l = (page + TARGET_PAGE_SIZE) - addr;
3023 if (l > len)
3024 l = len;
ths5fafdf22007-09-16 21:08:06 +00003025 cpu_physical_memory_rw(phys_addr + (addr & ~TARGET_PAGE_MASK),
bellardb448f2f2004-02-25 23:24:04 +00003026 buf, l, is_write);
bellard13eb76e2004-01-24 15:23:36 +00003027 len -= l;
3028 buf += l;
3029 addr += l;
3030 }
3031 return 0;
3032}
3033
pbrook2e70f6e2008-06-29 01:03:05 +00003034/* in deterministic execution mode, instructions doing device I/Os
3035 must be at the end of the TB */
3036void cpu_io_recompile(CPUState *env, void *retaddr)
3037{
3038 TranslationBlock *tb;
3039 uint32_t n, cflags;
3040 target_ulong pc, cs_base;
3041 uint64_t flags;
3042
3043 tb = tb_find_pc((unsigned long)retaddr);
3044 if (!tb) {
3045 cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p",
3046 retaddr);
3047 }
3048 n = env->icount_decr.u16.low + tb->icount;
3049 cpu_restore_state(tb, env, (unsigned long)retaddr, NULL);
3050 /* Calculate how many instructions had been executed before the fault
thsbf20dc02008-06-30 17:22:19 +00003051 occurred. */
pbrook2e70f6e2008-06-29 01:03:05 +00003052 n = n - env->icount_decr.u16.low;
3053 /* Generate a new TB ending on the I/O insn. */
3054 n++;
3055 /* On MIPS and SH, delay slot instructions can only be restarted if
3056 they were already the first instruction in the TB. If this is not
thsbf20dc02008-06-30 17:22:19 +00003057 the first instruction in a TB then re-execute the preceding
pbrook2e70f6e2008-06-29 01:03:05 +00003058 branch. */
3059#if defined(TARGET_MIPS)
3060 if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) {
3061 env->active_tc.PC -= 4;
3062 env->icount_decr.u16.low++;
3063 env->hflags &= ~MIPS_HFLAG_BMASK;
3064 }
3065#elif defined(TARGET_SH4)
3066 if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
3067 && n > 1) {
3068 env->pc -= 2;
3069 env->icount_decr.u16.low++;
3070 env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
3071 }
3072#endif
3073 /* This should never happen. */
3074 if (n > CF_COUNT_MASK)
3075 cpu_abort(env, "TB too big during recompile");
3076
3077 cflags = n | CF_LAST_IO;
3078 pc = tb->pc;
3079 cs_base = tb->cs_base;
3080 flags = tb->flags;
3081 tb_phys_invalidate(tb, -1);
3082 /* FIXME: In theory this could raise an exception. In practice
3083 we have already translated the block once so it's probably ok. */
3084 tb_gen_code(env, pc, cs_base, flags, cflags);
thsbf20dc02008-06-30 17:22:19 +00003085 /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
pbrook2e70f6e2008-06-29 01:03:05 +00003086 the first in the TB) then we end up generating a whole new TB and
3087 repeating the fault, which is horribly inefficient.
3088 Better would be to execute just this insn uncached, or generate a
3089 second new TB. */
3090 cpu_resume_from_signal(env, NULL);
3091}
3092
bellarde3db7222005-01-26 22:00:47 +00003093void dump_exec_info(FILE *f,
3094 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
3095{
3096 int i, target_code_size, max_target_code_size;
3097 int direct_jmp_count, direct_jmp2_count, cross_page;
3098 TranslationBlock *tb;
ths3b46e622007-09-17 08:09:54 +00003099
bellarde3db7222005-01-26 22:00:47 +00003100 target_code_size = 0;
3101 max_target_code_size = 0;
3102 cross_page = 0;
3103 direct_jmp_count = 0;
3104 direct_jmp2_count = 0;
3105 for(i = 0; i < nb_tbs; i++) {
3106 tb = &tbs[i];
3107 target_code_size += tb->size;
3108 if (tb->size > max_target_code_size)
3109 max_target_code_size = tb->size;
3110 if (tb->page_addr[1] != -1)
3111 cross_page++;
3112 if (tb->tb_next_offset[0] != 0xffff) {
3113 direct_jmp_count++;
3114 if (tb->tb_next_offset[1] != 0xffff) {
3115 direct_jmp2_count++;
3116 }
3117 }
3118 }
3119 /* XXX: avoid using doubles ? */
bellard57fec1f2008-02-01 10:50:11 +00003120 cpu_fprintf(f, "Translation buffer state:\n");
bellard26a5f132008-05-28 12:30:31 +00003121 cpu_fprintf(f, "gen code size %ld/%ld\n",
3122 code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size);
3123 cpu_fprintf(f, "TB count %d/%d\n",
3124 nb_tbs, code_gen_max_blocks);
ths5fafdf22007-09-16 21:08:06 +00003125 cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
bellarde3db7222005-01-26 22:00:47 +00003126 nb_tbs ? target_code_size / nb_tbs : 0,
3127 max_target_code_size);
ths5fafdf22007-09-16 21:08:06 +00003128 cpu_fprintf(f, "TB avg host size %d bytes (expansion ratio: %0.1f)\n",
bellarde3db7222005-01-26 22:00:47 +00003129 nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
3130 target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
ths5fafdf22007-09-16 21:08:06 +00003131 cpu_fprintf(f, "cross page TB count %d (%d%%)\n",
3132 cross_page,
bellarde3db7222005-01-26 22:00:47 +00003133 nb_tbs ? (cross_page * 100) / nb_tbs : 0);
3134 cpu_fprintf(f, "direct jump count %d (%d%%) (2 jumps=%d %d%%)\n",
ths5fafdf22007-09-16 21:08:06 +00003135 direct_jmp_count,
bellarde3db7222005-01-26 22:00:47 +00003136 nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
3137 direct_jmp2_count,
3138 nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
bellard57fec1f2008-02-01 10:50:11 +00003139 cpu_fprintf(f, "\nStatistics:\n");
bellarde3db7222005-01-26 22:00:47 +00003140 cpu_fprintf(f, "TB flush count %d\n", tb_flush_count);
3141 cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
3142 cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count);
bellardb67d9a52008-05-23 09:57:34 +00003143 tcg_dump_info(f, cpu_fprintf);
bellarde3db7222005-01-26 22:00:47 +00003144}
3145
ths5fafdf22007-09-16 21:08:06 +00003146#if !defined(CONFIG_USER_ONLY)
bellard61382a52003-10-27 21:22:23 +00003147
3148#define MMUSUFFIX _cmmu
3149#define GETPC() NULL
3150#define env cpu_single_env
bellardb769d8f2004-10-03 15:07:13 +00003151#define SOFTMMU_CODE_ACCESS
bellard61382a52003-10-27 21:22:23 +00003152
3153#define SHIFT 0
3154#include "softmmu_template.h"
3155
3156#define SHIFT 1
3157#include "softmmu_template.h"
3158
3159#define SHIFT 2
3160#include "softmmu_template.h"
3161
3162#define SHIFT 3
3163#include "softmmu_template.h"
3164
3165#undef env
3166
3167#endif