blob: 47f35e5b2e7fbd092550ef2ea666b7f036c3f7c5 [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
blueswir1d03d8602008-07-10 17:21:31 +000092#if defined(__arm__)
93/* The prologue must be reachable with a direct jump. ARM has a
94 limited branch range (possibly also PPC and SPARC?) so place it in a
95 section close to code segment. */
96#define code_gen_section \
97 __attribute__((__section__(".gen_code"))) \
98 __attribute__((aligned (32)))
99#else
100#define code_gen_section \
101 __attribute__((aligned (32)))
102#endif
103
104uint8_t code_gen_prologue[1024] code_gen_section;
bellard26a5f132008-05-28 12:30:31 +0000105uint8_t *code_gen_buffer;
106unsigned long code_gen_buffer_size;
107/* threshold to flush the translated code buffer */
108unsigned long code_gen_buffer_max_size;
bellardfd6ce8f2003-05-14 19:00:11 +0000109uint8_t *code_gen_ptr;
110
pbrooke2eef172008-06-08 01:09:01 +0000111#if !defined(CONFIG_USER_ONLY)
aurel3200f82b82008-04-27 21:12:55 +0000112ram_addr_t phys_ram_size;
bellard9fa3e852004-01-04 18:06:42 +0000113int phys_ram_fd;
114uint8_t *phys_ram_base;
bellard1ccde1c2004-02-06 19:46:14 +0000115uint8_t *phys_ram_dirty;
bellarde9a1ab12007-02-08 23:08:38 +0000116static ram_addr_t phys_ram_alloc_offset = 0;
pbrooke2eef172008-06-08 01:09:01 +0000117#endif
bellard9fa3e852004-01-04 18:06:42 +0000118
bellard6a00d602005-11-21 23:25:50 +0000119CPUState *first_cpu;
120/* current CPU in the current thread. It is only valid inside
121 cpu_exec() */
ths5fafdf22007-09-16 21:08:06 +0000122CPUState *cpu_single_env;
pbrook2e70f6e2008-06-29 01:03:05 +0000123/* 0 = Do not count executed instructions.
thsbf20dc02008-06-30 17:22:19 +0000124 1 = Precise instruction counting.
pbrook2e70f6e2008-06-29 01:03:05 +0000125 2 = Adaptive rate instruction counting. */
126int use_icount = 0;
127/* Current instruction counter. While executing translated code this may
128 include some instructions that have not yet been executed. */
129int64_t qemu_icount;
bellard6a00d602005-11-21 23:25:50 +0000130
bellard54936002003-05-13 00:25:15 +0000131typedef struct PageDesc {
bellard92e873b2004-05-21 14:52:29 +0000132 /* list of TBs intersecting this ram page */
bellardfd6ce8f2003-05-14 19:00:11 +0000133 TranslationBlock *first_tb;
bellard9fa3e852004-01-04 18:06:42 +0000134 /* in order to optimize self modifying code, we count the number
135 of lookups we do to a given page to use a bitmap */
136 unsigned int code_write_count;
137 uint8_t *code_bitmap;
138#if defined(CONFIG_USER_ONLY)
139 unsigned long flags;
140#endif
bellard54936002003-05-13 00:25:15 +0000141} PageDesc;
142
bellard92e873b2004-05-21 14:52:29 +0000143typedef struct PhysPageDesc {
pbrook0f459d12008-06-09 00:20:13 +0000144 /* offset in host memory of the page + io_index in the low bits */
aurel3200f82b82008-04-27 21:12:55 +0000145 ram_addr_t phys_offset;
bellard92e873b2004-05-21 14:52:29 +0000146} PhysPageDesc;
147
bellard54936002003-05-13 00:25:15 +0000148#define L2_BITS 10
j_mayerbedb69e2007-04-05 20:08:21 +0000149#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
150/* XXX: this is a temporary hack for alpha target.
151 * In the future, this is to be replaced by a multi-level table
152 * to actually be able to handle the complete 64 bits address space.
153 */
154#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
155#else
aurel3203875442008-04-22 20:45:18 +0000156#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
j_mayerbedb69e2007-04-05 20:08:21 +0000157#endif
bellard54936002003-05-13 00:25:15 +0000158
159#define L1_SIZE (1 << L1_BITS)
160#define L2_SIZE (1 << L2_BITS)
161
bellard83fb7ad2004-07-05 21:25:26 +0000162unsigned long qemu_real_host_page_size;
163unsigned long qemu_host_page_bits;
164unsigned long qemu_host_page_size;
165unsigned long qemu_host_page_mask;
bellard54936002003-05-13 00:25:15 +0000166
bellard92e873b2004-05-21 14:52:29 +0000167/* XXX: for system emulation, it could just be an array */
bellard54936002003-05-13 00:25:15 +0000168static PageDesc *l1_map[L1_SIZE];
bellard0a962c02005-02-10 22:00:27 +0000169PhysPageDesc **l1_phys_map;
bellard54936002003-05-13 00:25:15 +0000170
pbrooke2eef172008-06-08 01:09:01 +0000171#if !defined(CONFIG_USER_ONLY)
172static void io_mem_init(void);
173
bellard33417e72003-08-10 21:47:01 +0000174/* io memory support */
bellard33417e72003-08-10 21:47:01 +0000175CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
176CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
bellarda4193c82004-06-03 14:01:43 +0000177void *io_mem_opaque[IO_MEM_NB_ENTRIES];
bellard33417e72003-08-10 21:47:01 +0000178static int io_mem_nb;
pbrook6658ffb2007-03-16 23:58:11 +0000179static int io_mem_watch;
180#endif
bellard33417e72003-08-10 21:47:01 +0000181
bellard34865132003-10-05 14:28:56 +0000182/* log support */
183char *logfilename = "/tmp/qemu.log";
184FILE *logfile;
185int loglevel;
pbrooke735b912007-06-30 13:53:24 +0000186static int log_append = 0;
bellard34865132003-10-05 14:28:56 +0000187
bellarde3db7222005-01-26 22:00:47 +0000188/* statistics */
189static int tlb_flush_count;
190static int tb_flush_count;
191static int tb_phys_invalidate_count;
192
blueswir1db7b5422007-05-26 17:36:03 +0000193#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
194typedef struct subpage_t {
195 target_phys_addr_t base;
blueswir13ee89922008-01-02 19:45:26 +0000196 CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE][4];
197 CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE][4];
198 void *opaque[TARGET_PAGE_SIZE][2][4];
blueswir1db7b5422007-05-26 17:36:03 +0000199} subpage_t;
200
bellard7cb69ca2008-05-10 10:55:51 +0000201#ifdef _WIN32
202static void map_exec(void *addr, long size)
203{
204 DWORD old_protect;
205 VirtualProtect(addr, size,
206 PAGE_EXECUTE_READWRITE, &old_protect);
207
208}
209#else
210static void map_exec(void *addr, long size)
211{
bellard43694152008-05-29 09:35:57 +0000212 unsigned long start, end, page_size;
bellard7cb69ca2008-05-10 10:55:51 +0000213
bellard43694152008-05-29 09:35:57 +0000214 page_size = getpagesize();
bellard7cb69ca2008-05-10 10:55:51 +0000215 start = (unsigned long)addr;
bellard43694152008-05-29 09:35:57 +0000216 start &= ~(page_size - 1);
bellard7cb69ca2008-05-10 10:55:51 +0000217
218 end = (unsigned long)addr + size;
bellard43694152008-05-29 09:35:57 +0000219 end += page_size - 1;
220 end &= ~(page_size - 1);
bellard7cb69ca2008-05-10 10:55:51 +0000221
222 mprotect((void *)start, end - start,
223 PROT_READ | PROT_WRITE | PROT_EXEC);
224}
225#endif
226
bellardb346ff42003-06-15 20:05:50 +0000227static void page_init(void)
bellard54936002003-05-13 00:25:15 +0000228{
bellard83fb7ad2004-07-05 21:25:26 +0000229 /* NOTE: we can always suppose that qemu_host_page_size >=
bellard54936002003-05-13 00:25:15 +0000230 TARGET_PAGE_SIZE */
bellard67b915a2004-03-31 23:37:16 +0000231#ifdef _WIN32
bellardd5a8f072004-09-29 21:15:28 +0000232 {
233 SYSTEM_INFO system_info;
234 DWORD old_protect;
ths3b46e622007-09-17 08:09:54 +0000235
bellardd5a8f072004-09-29 21:15:28 +0000236 GetSystemInfo(&system_info);
237 qemu_real_host_page_size = system_info.dwPageSize;
bellardd5a8f072004-09-29 21:15:28 +0000238 }
bellard67b915a2004-03-31 23:37:16 +0000239#else
bellard83fb7ad2004-07-05 21:25:26 +0000240 qemu_real_host_page_size = getpagesize();
bellard67b915a2004-03-31 23:37:16 +0000241#endif
bellard83fb7ad2004-07-05 21:25:26 +0000242 if (qemu_host_page_size == 0)
243 qemu_host_page_size = qemu_real_host_page_size;
244 if (qemu_host_page_size < TARGET_PAGE_SIZE)
245 qemu_host_page_size = TARGET_PAGE_SIZE;
246 qemu_host_page_bits = 0;
247 while ((1 << qemu_host_page_bits) < qemu_host_page_size)
248 qemu_host_page_bits++;
249 qemu_host_page_mask = ~(qemu_host_page_size - 1);
bellard108c49b2005-07-24 12:55:09 +0000250 l1_phys_map = qemu_vmalloc(L1_SIZE * sizeof(void *));
251 memset(l1_phys_map, 0, L1_SIZE * sizeof(void *));
balrog50a95692007-12-12 01:16:23 +0000252
253#if !defined(_WIN32) && defined(CONFIG_USER_ONLY)
254 {
255 long long startaddr, endaddr;
256 FILE *f;
257 int n;
258
pbrookc8a706f2008-06-02 16:16:42 +0000259 mmap_lock();
pbrook07765902008-05-31 16:33:53 +0000260 last_brk = (unsigned long)sbrk(0);
balrog50a95692007-12-12 01:16:23 +0000261 f = fopen("/proc/self/maps", "r");
262 if (f) {
263 do {
264 n = fscanf (f, "%llx-%llx %*[^\n]\n", &startaddr, &endaddr);
265 if (n == 2) {
blueswir1e0b8d652008-05-03 17:51:24 +0000266 startaddr = MIN(startaddr,
267 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
268 endaddr = MIN(endaddr,
269 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
pbrookb5fc9092008-05-29 13:56:10 +0000270 page_set_flags(startaddr & TARGET_PAGE_MASK,
balrog50a95692007-12-12 01:16:23 +0000271 TARGET_PAGE_ALIGN(endaddr),
272 PAGE_RESERVED);
273 }
274 } while (!feof(f));
275 fclose(f);
276 }
pbrookc8a706f2008-06-02 16:16:42 +0000277 mmap_unlock();
balrog50a95692007-12-12 01:16:23 +0000278 }
279#endif
bellard54936002003-05-13 00:25:15 +0000280}
281
aurel3200f82b82008-04-27 21:12:55 +0000282static inline PageDesc *page_find_alloc(target_ulong index)
bellard54936002003-05-13 00:25:15 +0000283{
bellard54936002003-05-13 00:25:15 +0000284 PageDesc **lp, *p;
285
pbrook17e23772008-06-09 13:47:45 +0000286#if TARGET_LONG_BITS > 32
287 /* Host memory outside guest VM. For 32-bit targets we have already
288 excluded high addresses. */
289 if (index > ((target_ulong)L2_SIZE * L1_SIZE * TARGET_PAGE_SIZE))
290 return NULL;
291#endif
bellard54936002003-05-13 00:25:15 +0000292 lp = &l1_map[index >> L2_BITS];
293 p = *lp;
294 if (!p) {
295 /* allocate if not found */
pbrook17e23772008-06-09 13:47:45 +0000296#if defined(CONFIG_USER_ONLY)
297 unsigned long addr;
298 size_t len = sizeof(PageDesc) * L2_SIZE;
299 /* Don't use qemu_malloc because it may recurse. */
300 p = mmap(0, len, PROT_READ | PROT_WRITE,
301 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
bellard54936002003-05-13 00:25:15 +0000302 *lp = p;
pbrook17e23772008-06-09 13:47:45 +0000303 addr = h2g(p);
304 if (addr == (target_ulong)addr) {
305 page_set_flags(addr & TARGET_PAGE_MASK,
306 TARGET_PAGE_ALIGN(addr + len),
307 PAGE_RESERVED);
308 }
309#else
310 p = qemu_mallocz(sizeof(PageDesc) * L2_SIZE);
311 *lp = p;
312#endif
bellard54936002003-05-13 00:25:15 +0000313 }
314 return p + (index & (L2_SIZE - 1));
315}
316
aurel3200f82b82008-04-27 21:12:55 +0000317static inline PageDesc *page_find(target_ulong index)
bellard54936002003-05-13 00:25:15 +0000318{
bellard54936002003-05-13 00:25:15 +0000319 PageDesc *p;
320
bellard54936002003-05-13 00:25:15 +0000321 p = l1_map[index >> L2_BITS];
322 if (!p)
323 return 0;
bellardfd6ce8f2003-05-14 19:00:11 +0000324 return p + (index & (L2_SIZE - 1));
bellard54936002003-05-13 00:25:15 +0000325}
326
bellard108c49b2005-07-24 12:55:09 +0000327static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
bellard92e873b2004-05-21 14:52:29 +0000328{
bellard108c49b2005-07-24 12:55:09 +0000329 void **lp, **p;
pbrooke3f4e2a2006-04-08 20:02:06 +0000330 PhysPageDesc *pd;
bellard92e873b2004-05-21 14:52:29 +0000331
bellard108c49b2005-07-24 12:55:09 +0000332 p = (void **)l1_phys_map;
333#if TARGET_PHYS_ADDR_SPACE_BITS > 32
334
335#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
336#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
337#endif
338 lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1));
bellard92e873b2004-05-21 14:52:29 +0000339 p = *lp;
340 if (!p) {
341 /* allocate if not found */
bellard108c49b2005-07-24 12:55:09 +0000342 if (!alloc)
343 return NULL;
344 p = qemu_vmalloc(sizeof(void *) * L1_SIZE);
345 memset(p, 0, sizeof(void *) * L1_SIZE);
346 *lp = p;
347 }
348#endif
349 lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
pbrooke3f4e2a2006-04-08 20:02:06 +0000350 pd = *lp;
351 if (!pd) {
352 int i;
bellard108c49b2005-07-24 12:55:09 +0000353 /* allocate if not found */
354 if (!alloc)
355 return NULL;
pbrooke3f4e2a2006-04-08 20:02:06 +0000356 pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
357 *lp = pd;
358 for (i = 0; i < L2_SIZE; i++)
359 pd[i].phys_offset = IO_MEM_UNASSIGNED;
bellard92e873b2004-05-21 14:52:29 +0000360 }
pbrooke3f4e2a2006-04-08 20:02:06 +0000361 return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
bellard92e873b2004-05-21 14:52:29 +0000362}
363
bellard108c49b2005-07-24 12:55:09 +0000364static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
bellard92e873b2004-05-21 14:52:29 +0000365{
bellard108c49b2005-07-24 12:55:09 +0000366 return phys_page_find_alloc(index, 0);
bellard92e873b2004-05-21 14:52:29 +0000367}
368
bellard9fa3e852004-01-04 18:06:42 +0000369#if !defined(CONFIG_USER_ONLY)
bellard6a00d602005-11-21 23:25:50 +0000370static void tlb_protect_code(ram_addr_t ram_addr);
ths5fafdf22007-09-16 21:08:06 +0000371static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
bellard3a7d9292005-08-21 09:26:42 +0000372 target_ulong vaddr);
pbrookc8a706f2008-06-02 16:16:42 +0000373#define mmap_lock() do { } while(0)
374#define mmap_unlock() do { } while(0)
bellard9fa3e852004-01-04 18:06:42 +0000375#endif
bellardfd6ce8f2003-05-14 19:00:11 +0000376
bellard43694152008-05-29 09:35:57 +0000377#define DEFAULT_CODE_GEN_BUFFER_SIZE (32 * 1024 * 1024)
378
379#if defined(CONFIG_USER_ONLY)
380/* Currently it is not recommanded to allocate big chunks of data in
381 user mode. It will change when a dedicated libc will be used */
382#define USE_STATIC_CODE_GEN_BUFFER
383#endif
384
385#ifdef USE_STATIC_CODE_GEN_BUFFER
386static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE];
387#endif
388
bellard26a5f132008-05-28 12:30:31 +0000389void code_gen_alloc(unsigned long tb_size)
390{
bellard43694152008-05-29 09:35:57 +0000391#ifdef USE_STATIC_CODE_GEN_BUFFER
392 code_gen_buffer = static_code_gen_buffer;
393 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
394 map_exec(code_gen_buffer, code_gen_buffer_size);
395#else
bellard26a5f132008-05-28 12:30:31 +0000396 code_gen_buffer_size = tb_size;
397 if (code_gen_buffer_size == 0) {
bellard43694152008-05-29 09:35:57 +0000398#if defined(CONFIG_USER_ONLY)
399 /* in user mode, phys_ram_size is not meaningful */
400 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
401#else
bellard26a5f132008-05-28 12:30:31 +0000402 /* XXX: needs ajustments */
403 code_gen_buffer_size = (int)(phys_ram_size / 4);
bellard43694152008-05-29 09:35:57 +0000404#endif
bellard26a5f132008-05-28 12:30:31 +0000405 }
406 if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE)
407 code_gen_buffer_size = MIN_CODE_GEN_BUFFER_SIZE;
408 /* The code gen buffer location may have constraints depending on
409 the host cpu and OS */
410#if defined(__linux__)
411 {
412 int flags;
413 flags = MAP_PRIVATE | MAP_ANONYMOUS;
414#if defined(__x86_64__)
415 flags |= MAP_32BIT;
416 /* Cannot map more than that */
417 if (code_gen_buffer_size > (800 * 1024 * 1024))
418 code_gen_buffer_size = (800 * 1024 * 1024);
419#endif
420 code_gen_buffer = mmap(NULL, code_gen_buffer_size,
421 PROT_WRITE | PROT_READ | PROT_EXEC,
422 flags, -1, 0);
423 if (code_gen_buffer == MAP_FAILED) {
424 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
425 exit(1);
426 }
427 }
428#else
429 code_gen_buffer = qemu_malloc(code_gen_buffer_size);
430 if (!code_gen_buffer) {
431 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
432 exit(1);
433 }
434 map_exec(code_gen_buffer, code_gen_buffer_size);
435#endif
bellard43694152008-05-29 09:35:57 +0000436#endif /* !USE_STATIC_CODE_GEN_BUFFER */
bellard26a5f132008-05-28 12:30:31 +0000437 map_exec(code_gen_prologue, sizeof(code_gen_prologue));
438 code_gen_buffer_max_size = code_gen_buffer_size -
439 code_gen_max_block_size();
440 code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
441 tbs = qemu_malloc(code_gen_max_blocks * sizeof(TranslationBlock));
442}
443
444/* Must be called before using the QEMU cpus. 'tb_size' is the size
445 (in bytes) allocated to the translation buffer. Zero means default
446 size. */
447void cpu_exec_init_all(unsigned long tb_size)
448{
bellard26a5f132008-05-28 12:30:31 +0000449 cpu_gen_init();
450 code_gen_alloc(tb_size);
451 code_gen_ptr = code_gen_buffer;
bellard43694152008-05-29 09:35:57 +0000452 page_init();
pbrooke2eef172008-06-08 01:09:01 +0000453#if !defined(CONFIG_USER_ONLY)
bellard26a5f132008-05-28 12:30:31 +0000454 io_mem_init();
pbrooke2eef172008-06-08 01:09:01 +0000455#endif
bellard26a5f132008-05-28 12:30:31 +0000456}
457
pbrook9656f322008-07-01 20:01:19 +0000458#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
459
460#define CPU_COMMON_SAVE_VERSION 1
461
462static void cpu_common_save(QEMUFile *f, void *opaque)
463{
464 CPUState *env = opaque;
465
466 qemu_put_be32s(f, &env->halted);
467 qemu_put_be32s(f, &env->interrupt_request);
468}
469
470static int cpu_common_load(QEMUFile *f, void *opaque, int version_id)
471{
472 CPUState *env = opaque;
473
474 if (version_id != CPU_COMMON_SAVE_VERSION)
475 return -EINVAL;
476
477 qemu_get_be32s(f, &env->halted);
pbrook75f482a2008-07-01 21:53:33 +0000478 qemu_get_be32s(f, &env->interrupt_request);
pbrook9656f322008-07-01 20:01:19 +0000479 tlb_flush(env, 1);
480
481 return 0;
482}
483#endif
484
bellard6a00d602005-11-21 23:25:50 +0000485void cpu_exec_init(CPUState *env)
bellardfd6ce8f2003-05-14 19:00:11 +0000486{
bellard6a00d602005-11-21 23:25:50 +0000487 CPUState **penv;
488 int cpu_index;
489
bellard6a00d602005-11-21 23:25:50 +0000490 env->next_cpu = NULL;
491 penv = &first_cpu;
492 cpu_index = 0;
493 while (*penv != NULL) {
494 penv = (CPUState **)&(*penv)->next_cpu;
495 cpu_index++;
496 }
497 env->cpu_index = cpu_index;
pbrook6658ffb2007-03-16 23:58:11 +0000498 env->nb_watchpoints = 0;
bellard6a00d602005-11-21 23:25:50 +0000499 *penv = env;
pbrookb3c77242008-06-30 16:31:04 +0000500#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
pbrook9656f322008-07-01 20:01:19 +0000501 register_savevm("cpu_common", cpu_index, CPU_COMMON_SAVE_VERSION,
502 cpu_common_save, cpu_common_load, env);
pbrookb3c77242008-06-30 16:31:04 +0000503 register_savevm("cpu", cpu_index, CPU_SAVE_VERSION,
504 cpu_save, cpu_load, env);
505#endif
bellardfd6ce8f2003-05-14 19:00:11 +0000506}
507
bellard9fa3e852004-01-04 18:06:42 +0000508static inline void invalidate_page_bitmap(PageDesc *p)
509{
510 if (p->code_bitmap) {
bellard59817cc2004-02-16 22:01:13 +0000511 qemu_free(p->code_bitmap);
bellard9fa3e852004-01-04 18:06:42 +0000512 p->code_bitmap = NULL;
513 }
514 p->code_write_count = 0;
515}
516
bellardfd6ce8f2003-05-14 19:00:11 +0000517/* set to NULL all the 'first_tb' fields in all PageDescs */
518static void page_flush_tb(void)
519{
520 int i, j;
521 PageDesc *p;
522
523 for(i = 0; i < L1_SIZE; i++) {
524 p = l1_map[i];
525 if (p) {
bellard9fa3e852004-01-04 18:06:42 +0000526 for(j = 0; j < L2_SIZE; j++) {
527 p->first_tb = NULL;
528 invalidate_page_bitmap(p);
529 p++;
530 }
bellardfd6ce8f2003-05-14 19:00:11 +0000531 }
532 }
533}
534
535/* flush all the translation blocks */
bellardd4e81642003-05-25 16:46:15 +0000536/* XXX: tb_flush is currently not thread safe */
bellard6a00d602005-11-21 23:25:50 +0000537void tb_flush(CPUState *env1)
bellardfd6ce8f2003-05-14 19:00:11 +0000538{
bellard6a00d602005-11-21 23:25:50 +0000539 CPUState *env;
bellard01243112004-01-04 15:48:17 +0000540#if defined(DEBUG_FLUSH)
blueswir1ab3d1722007-11-04 07:31:40 +0000541 printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
542 (unsigned long)(code_gen_ptr - code_gen_buffer),
543 nb_tbs, nb_tbs > 0 ?
544 ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
bellardfd6ce8f2003-05-14 19:00:11 +0000545#endif
bellard26a5f132008-05-28 12:30:31 +0000546 if ((unsigned long)(code_gen_ptr - code_gen_buffer) > code_gen_buffer_size)
pbrooka208e542008-03-31 17:07:36 +0000547 cpu_abort(env1, "Internal error: code buffer overflow\n");
548
bellardfd6ce8f2003-05-14 19:00:11 +0000549 nb_tbs = 0;
ths3b46e622007-09-17 08:09:54 +0000550
bellard6a00d602005-11-21 23:25:50 +0000551 for(env = first_cpu; env != NULL; env = env->next_cpu) {
552 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
553 }
bellard9fa3e852004-01-04 18:06:42 +0000554
bellard8a8a6082004-10-03 13:36:49 +0000555 memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
bellardfd6ce8f2003-05-14 19:00:11 +0000556 page_flush_tb();
bellard9fa3e852004-01-04 18:06:42 +0000557
bellardfd6ce8f2003-05-14 19:00:11 +0000558 code_gen_ptr = code_gen_buffer;
bellardd4e81642003-05-25 16:46:15 +0000559 /* XXX: flush processor icache at this point if cache flush is
560 expensive */
bellarde3db7222005-01-26 22:00:47 +0000561 tb_flush_count++;
bellardfd6ce8f2003-05-14 19:00:11 +0000562}
563
564#ifdef DEBUG_TB_CHECK
565
j_mayerbc98a7e2007-04-04 07:55:12 +0000566static void tb_invalidate_check(target_ulong address)
bellardfd6ce8f2003-05-14 19:00:11 +0000567{
568 TranslationBlock *tb;
569 int i;
570 address &= TARGET_PAGE_MASK;
pbrook99773bd2006-04-16 15:14:59 +0000571 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
572 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
bellardfd6ce8f2003-05-14 19:00:11 +0000573 if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
574 address >= tb->pc + tb->size)) {
575 printf("ERROR invalidate: address=%08lx PC=%08lx size=%04x\n",
pbrook99773bd2006-04-16 15:14:59 +0000576 address, (long)tb->pc, tb->size);
bellardfd6ce8f2003-05-14 19:00:11 +0000577 }
578 }
579 }
580}
581
582/* verify that all the pages have correct rights for code */
583static void tb_page_check(void)
584{
585 TranslationBlock *tb;
586 int i, flags1, flags2;
ths3b46e622007-09-17 08:09:54 +0000587
pbrook99773bd2006-04-16 15:14:59 +0000588 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
589 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
bellardfd6ce8f2003-05-14 19:00:11 +0000590 flags1 = page_get_flags(tb->pc);
591 flags2 = page_get_flags(tb->pc + tb->size - 1);
592 if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
593 printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
pbrook99773bd2006-04-16 15:14:59 +0000594 (long)tb->pc, tb->size, flags1, flags2);
bellardfd6ce8f2003-05-14 19:00:11 +0000595 }
596 }
597 }
598}
599
bellardd4e81642003-05-25 16:46:15 +0000600void tb_jmp_check(TranslationBlock *tb)
601{
602 TranslationBlock *tb1;
603 unsigned int n1;
604
605 /* suppress any remaining jumps to this TB */
606 tb1 = tb->jmp_first;
607 for(;;) {
608 n1 = (long)tb1 & 3;
609 tb1 = (TranslationBlock *)((long)tb1 & ~3);
610 if (n1 == 2)
611 break;
612 tb1 = tb1->jmp_next[n1];
613 }
614 /* check end of list */
615 if (tb1 != tb) {
616 printf("ERROR: jmp_list from 0x%08lx\n", (long)tb);
617 }
618}
619
bellardfd6ce8f2003-05-14 19:00:11 +0000620#endif
621
622/* invalidate one TB */
623static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb,
624 int next_offset)
625{
626 TranslationBlock *tb1;
627 for(;;) {
628 tb1 = *ptb;
629 if (tb1 == tb) {
630 *ptb = *(TranslationBlock **)((char *)tb1 + next_offset);
631 break;
632 }
633 ptb = (TranslationBlock **)((char *)tb1 + next_offset);
634 }
635}
636
bellard9fa3e852004-01-04 18:06:42 +0000637static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
638{
639 TranslationBlock *tb1;
640 unsigned int n1;
641
642 for(;;) {
643 tb1 = *ptb;
644 n1 = (long)tb1 & 3;
645 tb1 = (TranslationBlock *)((long)tb1 & ~3);
646 if (tb1 == tb) {
647 *ptb = tb1->page_next[n1];
648 break;
649 }
650 ptb = &tb1->page_next[n1];
651 }
652}
653
bellardd4e81642003-05-25 16:46:15 +0000654static inline void tb_jmp_remove(TranslationBlock *tb, int n)
655{
656 TranslationBlock *tb1, **ptb;
657 unsigned int n1;
658
659 ptb = &tb->jmp_next[n];
660 tb1 = *ptb;
661 if (tb1) {
662 /* find tb(n) in circular list */
663 for(;;) {
664 tb1 = *ptb;
665 n1 = (long)tb1 & 3;
666 tb1 = (TranslationBlock *)((long)tb1 & ~3);
667 if (n1 == n && tb1 == tb)
668 break;
669 if (n1 == 2) {
670 ptb = &tb1->jmp_first;
671 } else {
672 ptb = &tb1->jmp_next[n1];
673 }
674 }
675 /* now we can suppress tb(n) from the list */
676 *ptb = tb->jmp_next[n];
677
678 tb->jmp_next[n] = NULL;
679 }
680}
681
682/* reset the jump entry 'n' of a TB so that it is not chained to
683 another TB */
684static inline void tb_reset_jump(TranslationBlock *tb, int n)
685{
686 tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
687}
688
pbrook2e70f6e2008-06-29 01:03:05 +0000689void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr)
bellardfd6ce8f2003-05-14 19:00:11 +0000690{
bellard6a00d602005-11-21 23:25:50 +0000691 CPUState *env;
bellardfd6ce8f2003-05-14 19:00:11 +0000692 PageDesc *p;
bellard8a40a182005-11-20 10:35:40 +0000693 unsigned int h, n1;
aurel3200f82b82008-04-27 21:12:55 +0000694 target_phys_addr_t phys_pc;
bellard8a40a182005-11-20 10:35:40 +0000695 TranslationBlock *tb1, *tb2;
ths3b46e622007-09-17 08:09:54 +0000696
bellard9fa3e852004-01-04 18:06:42 +0000697 /* remove the TB from the hash list */
698 phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
699 h = tb_phys_hash_func(phys_pc);
ths5fafdf22007-09-16 21:08:06 +0000700 tb_remove(&tb_phys_hash[h], tb,
bellard9fa3e852004-01-04 18:06:42 +0000701 offsetof(TranslationBlock, phys_hash_next));
bellardfd6ce8f2003-05-14 19:00:11 +0000702
bellard9fa3e852004-01-04 18:06:42 +0000703 /* remove the TB from the page list */
704 if (tb->page_addr[0] != page_addr) {
705 p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
706 tb_page_remove(&p->first_tb, tb);
707 invalidate_page_bitmap(p);
708 }
709 if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
710 p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
711 tb_page_remove(&p->first_tb, tb);
712 invalidate_page_bitmap(p);
713 }
714
bellard8a40a182005-11-20 10:35:40 +0000715 tb_invalidated_flag = 1;
716
717 /* remove the TB from the hash list */
718 h = tb_jmp_cache_hash_func(tb->pc);
bellard6a00d602005-11-21 23:25:50 +0000719 for(env = first_cpu; env != NULL; env = env->next_cpu) {
720 if (env->tb_jmp_cache[h] == tb)
721 env->tb_jmp_cache[h] = NULL;
722 }
bellard8a40a182005-11-20 10:35:40 +0000723
724 /* suppress this TB from the two jump lists */
725 tb_jmp_remove(tb, 0);
726 tb_jmp_remove(tb, 1);
727
728 /* suppress any remaining jumps to this TB */
729 tb1 = tb->jmp_first;
730 for(;;) {
731 n1 = (long)tb1 & 3;
732 if (n1 == 2)
733 break;
734 tb1 = (TranslationBlock *)((long)tb1 & ~3);
735 tb2 = tb1->jmp_next[n1];
736 tb_reset_jump(tb1, n1);
737 tb1->jmp_next[n1] = NULL;
738 tb1 = tb2;
739 }
740 tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
741
bellarde3db7222005-01-26 22:00:47 +0000742 tb_phys_invalidate_count++;
bellard9fa3e852004-01-04 18:06:42 +0000743}
744
745static inline void set_bits(uint8_t *tab, int start, int len)
746{
747 int end, mask, end1;
748
749 end = start + len;
750 tab += start >> 3;
751 mask = 0xff << (start & 7);
752 if ((start & ~7) == (end & ~7)) {
753 if (start < end) {
754 mask &= ~(0xff << (end & 7));
755 *tab |= mask;
756 }
757 } else {
758 *tab++ |= mask;
759 start = (start + 8) & ~7;
760 end1 = end & ~7;
761 while (start < end1) {
762 *tab++ = 0xff;
763 start += 8;
764 }
765 if (start < end) {
766 mask = ~(0xff << (end & 7));
767 *tab |= mask;
768 }
769 }
770}
771
772static void build_page_bitmap(PageDesc *p)
773{
774 int n, tb_start, tb_end;
775 TranslationBlock *tb;
ths3b46e622007-09-17 08:09:54 +0000776
pbrookb2a70812008-06-09 13:57:23 +0000777 p->code_bitmap = qemu_mallocz(TARGET_PAGE_SIZE / 8);
bellard9fa3e852004-01-04 18:06:42 +0000778 if (!p->code_bitmap)
779 return;
bellard9fa3e852004-01-04 18:06:42 +0000780
781 tb = p->first_tb;
782 while (tb != NULL) {
783 n = (long)tb & 3;
784 tb = (TranslationBlock *)((long)tb & ~3);
785 /* NOTE: this is subtle as a TB may span two physical pages */
786 if (n == 0) {
787 /* NOTE: tb_end may be after the end of the page, but
788 it is not a problem */
789 tb_start = tb->pc & ~TARGET_PAGE_MASK;
790 tb_end = tb_start + tb->size;
791 if (tb_end > TARGET_PAGE_SIZE)
792 tb_end = TARGET_PAGE_SIZE;
793 } else {
794 tb_start = 0;
795 tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
796 }
797 set_bits(p->code_bitmap, tb_start, tb_end - tb_start);
798 tb = tb->page_next[n];
799 }
800}
801
pbrook2e70f6e2008-06-29 01:03:05 +0000802TranslationBlock *tb_gen_code(CPUState *env,
803 target_ulong pc, target_ulong cs_base,
804 int flags, int cflags)
bellardd720b932004-04-25 17:57:43 +0000805{
806 TranslationBlock *tb;
807 uint8_t *tc_ptr;
808 target_ulong phys_pc, phys_page2, virt_page2;
809 int code_gen_size;
810
bellardc27004e2005-01-03 23:35:10 +0000811 phys_pc = get_phys_addr_code(env, pc);
812 tb = tb_alloc(pc);
bellardd720b932004-04-25 17:57:43 +0000813 if (!tb) {
814 /* flush must be done */
815 tb_flush(env);
816 /* cannot fail at this point */
bellardc27004e2005-01-03 23:35:10 +0000817 tb = tb_alloc(pc);
pbrook2e70f6e2008-06-29 01:03:05 +0000818 /* Don't forget to invalidate previous TB info. */
819 tb_invalidated_flag = 1;
bellardd720b932004-04-25 17:57:43 +0000820 }
821 tc_ptr = code_gen_ptr;
822 tb->tc_ptr = tc_ptr;
823 tb->cs_base = cs_base;
824 tb->flags = flags;
825 tb->cflags = cflags;
blueswir1d07bde82007-12-11 19:35:45 +0000826 cpu_gen_code(env, tb, &code_gen_size);
bellardd720b932004-04-25 17:57:43 +0000827 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 +0000828
bellardd720b932004-04-25 17:57:43 +0000829 /* check next page if needed */
bellardc27004e2005-01-03 23:35:10 +0000830 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
bellardd720b932004-04-25 17:57:43 +0000831 phys_page2 = -1;
bellardc27004e2005-01-03 23:35:10 +0000832 if ((pc & TARGET_PAGE_MASK) != virt_page2) {
bellardd720b932004-04-25 17:57:43 +0000833 phys_page2 = get_phys_addr_code(env, virt_page2);
834 }
835 tb_link_phys(tb, phys_pc, phys_page2);
pbrook2e70f6e2008-06-29 01:03:05 +0000836 return tb;
bellardd720b932004-04-25 17:57:43 +0000837}
ths3b46e622007-09-17 08:09:54 +0000838
bellard9fa3e852004-01-04 18:06:42 +0000839/* invalidate all TBs which intersect with the target physical page
840 starting in range [start;end[. NOTE: start and end must refer to
bellardd720b932004-04-25 17:57:43 +0000841 the same physical page. 'is_cpu_write_access' should be true if called
842 from a real cpu write access: the virtual CPU will exit the current
843 TB if code is modified inside this TB. */
aurel3200f82b82008-04-27 21:12:55 +0000844void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t end,
bellardd720b932004-04-25 17:57:43 +0000845 int is_cpu_write_access)
bellard9fa3e852004-01-04 18:06:42 +0000846{
bellardd720b932004-04-25 17:57:43 +0000847 int n, current_tb_modified, current_tb_not_found, current_flags;
bellardd720b932004-04-25 17:57:43 +0000848 CPUState *env = cpu_single_env;
bellard9fa3e852004-01-04 18:06:42 +0000849 PageDesc *p;
bellardea1c1802004-06-14 18:56:36 +0000850 TranslationBlock *tb, *tb_next, *current_tb, *saved_tb;
bellard9fa3e852004-01-04 18:06:42 +0000851 target_ulong tb_start, tb_end;
bellardd720b932004-04-25 17:57:43 +0000852 target_ulong current_pc, current_cs_base;
bellard9fa3e852004-01-04 18:06:42 +0000853
854 p = page_find(start >> TARGET_PAGE_BITS);
ths5fafdf22007-09-16 21:08:06 +0000855 if (!p)
bellard9fa3e852004-01-04 18:06:42 +0000856 return;
ths5fafdf22007-09-16 21:08:06 +0000857 if (!p->code_bitmap &&
bellardd720b932004-04-25 17:57:43 +0000858 ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
859 is_cpu_write_access) {
bellard9fa3e852004-01-04 18:06:42 +0000860 /* build code bitmap */
861 build_page_bitmap(p);
862 }
863
864 /* we remove all the TBs in the range [start, end[ */
865 /* XXX: see if in some cases it could be faster to invalidate all the code */
bellardd720b932004-04-25 17:57:43 +0000866 current_tb_not_found = is_cpu_write_access;
867 current_tb_modified = 0;
868 current_tb = NULL; /* avoid warning */
869 current_pc = 0; /* avoid warning */
870 current_cs_base = 0; /* avoid warning */
871 current_flags = 0; /* avoid warning */
bellard9fa3e852004-01-04 18:06:42 +0000872 tb = p->first_tb;
873 while (tb != NULL) {
874 n = (long)tb & 3;
875 tb = (TranslationBlock *)((long)tb & ~3);
876 tb_next = tb->page_next[n];
877 /* NOTE: this is subtle as a TB may span two physical pages */
878 if (n == 0) {
879 /* NOTE: tb_end may be after the end of the page, but
880 it is not a problem */
881 tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
882 tb_end = tb_start + tb->size;
883 } else {
884 tb_start = tb->page_addr[1];
885 tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
886 }
887 if (!(tb_end <= start || tb_start >= end)) {
bellardd720b932004-04-25 17:57:43 +0000888#ifdef TARGET_HAS_PRECISE_SMC
889 if (current_tb_not_found) {
890 current_tb_not_found = 0;
891 current_tb = NULL;
pbrook2e70f6e2008-06-29 01:03:05 +0000892 if (env->mem_io_pc) {
bellardd720b932004-04-25 17:57:43 +0000893 /* now we have a real cpu fault */
pbrook2e70f6e2008-06-29 01:03:05 +0000894 current_tb = tb_find_pc(env->mem_io_pc);
bellardd720b932004-04-25 17:57:43 +0000895 }
896 }
897 if (current_tb == tb &&
pbrook2e70f6e2008-06-29 01:03:05 +0000898 (current_tb->cflags & CF_COUNT_MASK) != 1) {
bellardd720b932004-04-25 17:57:43 +0000899 /* If we are modifying the current TB, we must stop
900 its execution. We could be more precise by checking
901 that the modification is after the current PC, but it
902 would require a specialized function to partially
903 restore the CPU state */
ths3b46e622007-09-17 08:09:54 +0000904
bellardd720b932004-04-25 17:57:43 +0000905 current_tb_modified = 1;
ths5fafdf22007-09-16 21:08:06 +0000906 cpu_restore_state(current_tb, env,
pbrook2e70f6e2008-06-29 01:03:05 +0000907 env->mem_io_pc, NULL);
bellardd720b932004-04-25 17:57:43 +0000908#if defined(TARGET_I386)
909 current_flags = env->hflags;
910 current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
911 current_cs_base = (target_ulong)env->segs[R_CS].base;
912 current_pc = current_cs_base + env->eip;
913#else
914#error unsupported CPU
915#endif
916 }
917#endif /* TARGET_HAS_PRECISE_SMC */
bellard6f5a9f72005-11-26 20:12:28 +0000918 /* we need to do that to handle the case where a signal
919 occurs while doing tb_phys_invalidate() */
920 saved_tb = NULL;
921 if (env) {
922 saved_tb = env->current_tb;
923 env->current_tb = NULL;
924 }
bellard9fa3e852004-01-04 18:06:42 +0000925 tb_phys_invalidate(tb, -1);
bellard6f5a9f72005-11-26 20:12:28 +0000926 if (env) {
927 env->current_tb = saved_tb;
928 if (env->interrupt_request && env->current_tb)
929 cpu_interrupt(env, env->interrupt_request);
930 }
bellard9fa3e852004-01-04 18:06:42 +0000931 }
932 tb = tb_next;
933 }
934#if !defined(CONFIG_USER_ONLY)
935 /* if no code remaining, no need to continue to use slow writes */
936 if (!p->first_tb) {
937 invalidate_page_bitmap(p);
bellardd720b932004-04-25 17:57:43 +0000938 if (is_cpu_write_access) {
pbrook2e70f6e2008-06-29 01:03:05 +0000939 tlb_unprotect_code_phys(env, start, env->mem_io_vaddr);
bellardd720b932004-04-25 17:57:43 +0000940 }
941 }
942#endif
943#ifdef TARGET_HAS_PRECISE_SMC
944 if (current_tb_modified) {
945 /* we generate a block containing just the instruction
946 modifying the memory. It will ensure that it cannot modify
947 itself */
bellardea1c1802004-06-14 18:56:36 +0000948 env->current_tb = NULL;
pbrook2e70f6e2008-06-29 01:03:05 +0000949 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
bellardd720b932004-04-25 17:57:43 +0000950 cpu_resume_from_signal(env, NULL);
bellard9fa3e852004-01-04 18:06:42 +0000951 }
952#endif
953}
954
955/* len must be <= 8 and start must be a multiple of len */
aurel3200f82b82008-04-27 21:12:55 +0000956static inline void tb_invalidate_phys_page_fast(target_phys_addr_t start, int len)
bellard9fa3e852004-01-04 18:06:42 +0000957{
958 PageDesc *p;
959 int offset, b;
bellard59817cc2004-02-16 22:01:13 +0000960#if 0
bellarda4193c82004-06-03 14:01:43 +0000961 if (1) {
962 if (loglevel) {
ths5fafdf22007-09-16 21:08:06 +0000963 fprintf(logfile, "modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
pbrook2e70f6e2008-06-29 01:03:05 +0000964 cpu_single_env->mem_io_vaddr, len,
ths5fafdf22007-09-16 21:08:06 +0000965 cpu_single_env->eip,
bellarda4193c82004-06-03 14:01:43 +0000966 cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
967 }
bellard59817cc2004-02-16 22:01:13 +0000968 }
969#endif
bellard9fa3e852004-01-04 18:06:42 +0000970 p = page_find(start >> TARGET_PAGE_BITS);
ths5fafdf22007-09-16 21:08:06 +0000971 if (!p)
bellard9fa3e852004-01-04 18:06:42 +0000972 return;
973 if (p->code_bitmap) {
974 offset = start & ~TARGET_PAGE_MASK;
975 b = p->code_bitmap[offset >> 3] >> (offset & 7);
976 if (b & ((1 << len) - 1))
977 goto do_invalidate;
978 } else {
979 do_invalidate:
bellardd720b932004-04-25 17:57:43 +0000980 tb_invalidate_phys_page_range(start, start + len, 1);
bellard9fa3e852004-01-04 18:06:42 +0000981 }
982}
983
bellard9fa3e852004-01-04 18:06:42 +0000984#if !defined(CONFIG_SOFTMMU)
aurel3200f82b82008-04-27 21:12:55 +0000985static void tb_invalidate_phys_page(target_phys_addr_t addr,
bellardd720b932004-04-25 17:57:43 +0000986 unsigned long pc, void *puc)
bellard9fa3e852004-01-04 18:06:42 +0000987{
bellardd720b932004-04-25 17:57:43 +0000988 int n, current_flags, current_tb_modified;
989 target_ulong current_pc, current_cs_base;
bellard9fa3e852004-01-04 18:06:42 +0000990 PageDesc *p;
bellardd720b932004-04-25 17:57:43 +0000991 TranslationBlock *tb, *current_tb;
992#ifdef TARGET_HAS_PRECISE_SMC
993 CPUState *env = cpu_single_env;
994#endif
bellard9fa3e852004-01-04 18:06:42 +0000995
996 addr &= TARGET_PAGE_MASK;
997 p = page_find(addr >> TARGET_PAGE_BITS);
ths5fafdf22007-09-16 21:08:06 +0000998 if (!p)
bellardfd6ce8f2003-05-14 19:00:11 +0000999 return;
1000 tb = p->first_tb;
bellardd720b932004-04-25 17:57:43 +00001001 current_tb_modified = 0;
1002 current_tb = NULL;
1003 current_pc = 0; /* avoid warning */
1004 current_cs_base = 0; /* avoid warning */
1005 current_flags = 0; /* avoid warning */
1006#ifdef TARGET_HAS_PRECISE_SMC
1007 if (tb && pc != 0) {
1008 current_tb = tb_find_pc(pc);
1009 }
1010#endif
bellardfd6ce8f2003-05-14 19:00:11 +00001011 while (tb != NULL) {
bellard9fa3e852004-01-04 18:06:42 +00001012 n = (long)tb & 3;
1013 tb = (TranslationBlock *)((long)tb & ~3);
bellardd720b932004-04-25 17:57:43 +00001014#ifdef TARGET_HAS_PRECISE_SMC
1015 if (current_tb == tb &&
pbrook2e70f6e2008-06-29 01:03:05 +00001016 (current_tb->cflags & CF_COUNT_MASK) != 1) {
bellardd720b932004-04-25 17:57:43 +00001017 /* If we are modifying the current TB, we must stop
1018 its execution. We could be more precise by checking
1019 that the modification is after the current PC, but it
1020 would require a specialized function to partially
1021 restore the CPU state */
ths3b46e622007-09-17 08:09:54 +00001022
bellardd720b932004-04-25 17:57:43 +00001023 current_tb_modified = 1;
1024 cpu_restore_state(current_tb, env, pc, puc);
1025#if defined(TARGET_I386)
1026 current_flags = env->hflags;
1027 current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
1028 current_cs_base = (target_ulong)env->segs[R_CS].base;
1029 current_pc = current_cs_base + env->eip;
1030#else
1031#error unsupported CPU
1032#endif
1033 }
1034#endif /* TARGET_HAS_PRECISE_SMC */
bellard9fa3e852004-01-04 18:06:42 +00001035 tb_phys_invalidate(tb, addr);
1036 tb = tb->page_next[n];
bellardfd6ce8f2003-05-14 19:00:11 +00001037 }
1038 p->first_tb = NULL;
bellardd720b932004-04-25 17:57:43 +00001039#ifdef TARGET_HAS_PRECISE_SMC
1040 if (current_tb_modified) {
1041 /* we generate a block containing just the instruction
1042 modifying the memory. It will ensure that it cannot modify
1043 itself */
bellardea1c1802004-06-14 18:56:36 +00001044 env->current_tb = NULL;
pbrook2e70f6e2008-06-29 01:03:05 +00001045 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
bellardd720b932004-04-25 17:57:43 +00001046 cpu_resume_from_signal(env, puc);
1047 }
1048#endif
bellardfd6ce8f2003-05-14 19:00:11 +00001049}
bellard9fa3e852004-01-04 18:06:42 +00001050#endif
bellardfd6ce8f2003-05-14 19:00:11 +00001051
1052/* add the tb in the target page and protect it if necessary */
ths5fafdf22007-09-16 21:08:06 +00001053static inline void tb_alloc_page(TranslationBlock *tb,
pbrook53a59602006-03-25 19:31:22 +00001054 unsigned int n, target_ulong page_addr)
bellardfd6ce8f2003-05-14 19:00:11 +00001055{
1056 PageDesc *p;
bellard9fa3e852004-01-04 18:06:42 +00001057 TranslationBlock *last_first_tb;
bellardfd6ce8f2003-05-14 19:00:11 +00001058
bellard9fa3e852004-01-04 18:06:42 +00001059 tb->page_addr[n] = page_addr;
bellard3a7d9292005-08-21 09:26:42 +00001060 p = page_find_alloc(page_addr >> TARGET_PAGE_BITS);
bellard9fa3e852004-01-04 18:06:42 +00001061 tb->page_next[n] = p->first_tb;
1062 last_first_tb = p->first_tb;
1063 p->first_tb = (TranslationBlock *)((long)tb | n);
1064 invalidate_page_bitmap(p);
1065
bellard107db442004-06-22 18:48:46 +00001066#if defined(TARGET_HAS_SMC) || 1
bellardd720b932004-04-25 17:57:43 +00001067
bellard9fa3e852004-01-04 18:06:42 +00001068#if defined(CONFIG_USER_ONLY)
bellardfd6ce8f2003-05-14 19:00:11 +00001069 if (p->flags & PAGE_WRITE) {
pbrook53a59602006-03-25 19:31:22 +00001070 target_ulong addr;
1071 PageDesc *p2;
bellard9fa3e852004-01-04 18:06:42 +00001072 int prot;
1073
bellardfd6ce8f2003-05-14 19:00:11 +00001074 /* force the host page as non writable (writes will have a
1075 page fault + mprotect overhead) */
pbrook53a59602006-03-25 19:31:22 +00001076 page_addr &= qemu_host_page_mask;
bellardfd6ce8f2003-05-14 19:00:11 +00001077 prot = 0;
pbrook53a59602006-03-25 19:31:22 +00001078 for(addr = page_addr; addr < page_addr + qemu_host_page_size;
1079 addr += TARGET_PAGE_SIZE) {
1080
1081 p2 = page_find (addr >> TARGET_PAGE_BITS);
1082 if (!p2)
1083 continue;
1084 prot |= p2->flags;
1085 p2->flags &= ~PAGE_WRITE;
1086 page_get_flags(addr);
1087 }
ths5fafdf22007-09-16 21:08:06 +00001088 mprotect(g2h(page_addr), qemu_host_page_size,
bellardfd6ce8f2003-05-14 19:00:11 +00001089 (prot & PAGE_BITS) & ~PAGE_WRITE);
1090#ifdef DEBUG_TB_INVALIDATE
blueswir1ab3d1722007-11-04 07:31:40 +00001091 printf("protecting code page: 0x" TARGET_FMT_lx "\n",
pbrook53a59602006-03-25 19:31:22 +00001092 page_addr);
bellardfd6ce8f2003-05-14 19:00:11 +00001093#endif
bellardfd6ce8f2003-05-14 19:00:11 +00001094 }
bellard9fa3e852004-01-04 18:06:42 +00001095#else
1096 /* if some code is already present, then the pages are already
1097 protected. So we handle the case where only the first TB is
1098 allocated in a physical page */
1099 if (!last_first_tb) {
bellard6a00d602005-11-21 23:25:50 +00001100 tlb_protect_code(page_addr);
bellard9fa3e852004-01-04 18:06:42 +00001101 }
1102#endif
bellardd720b932004-04-25 17:57:43 +00001103
1104#endif /* TARGET_HAS_SMC */
bellardfd6ce8f2003-05-14 19:00:11 +00001105}
1106
1107/* Allocate a new translation block. Flush the translation buffer if
1108 too many translation blocks or too much generated code. */
bellardc27004e2005-01-03 23:35:10 +00001109TranslationBlock *tb_alloc(target_ulong pc)
bellardfd6ce8f2003-05-14 19:00:11 +00001110{
1111 TranslationBlock *tb;
bellardfd6ce8f2003-05-14 19:00:11 +00001112
bellard26a5f132008-05-28 12:30:31 +00001113 if (nb_tbs >= code_gen_max_blocks ||
1114 (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
bellardd4e81642003-05-25 16:46:15 +00001115 return NULL;
bellardfd6ce8f2003-05-14 19:00:11 +00001116 tb = &tbs[nb_tbs++];
1117 tb->pc = pc;
bellardb448f2f2004-02-25 23:24:04 +00001118 tb->cflags = 0;
bellardd4e81642003-05-25 16:46:15 +00001119 return tb;
1120}
1121
pbrook2e70f6e2008-06-29 01:03:05 +00001122void tb_free(TranslationBlock *tb)
1123{
thsbf20dc02008-06-30 17:22:19 +00001124 /* In practice this is mostly used for single use temporary TB
pbrook2e70f6e2008-06-29 01:03:05 +00001125 Ignore the hard cases and just back up if this TB happens to
1126 be the last one generated. */
1127 if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) {
1128 code_gen_ptr = tb->tc_ptr;
1129 nb_tbs--;
1130 }
1131}
1132
bellard9fa3e852004-01-04 18:06:42 +00001133/* add a new TB and link it to the physical page tables. phys_page2 is
1134 (-1) to indicate that only one page contains the TB. */
ths5fafdf22007-09-16 21:08:06 +00001135void tb_link_phys(TranslationBlock *tb,
bellard9fa3e852004-01-04 18:06:42 +00001136 target_ulong phys_pc, target_ulong phys_page2)
bellardd4e81642003-05-25 16:46:15 +00001137{
bellard9fa3e852004-01-04 18:06:42 +00001138 unsigned int h;
1139 TranslationBlock **ptb;
1140
pbrookc8a706f2008-06-02 16:16:42 +00001141 /* Grab the mmap lock to stop another thread invalidating this TB
1142 before we are done. */
1143 mmap_lock();
bellard9fa3e852004-01-04 18:06:42 +00001144 /* add in the physical hash table */
1145 h = tb_phys_hash_func(phys_pc);
1146 ptb = &tb_phys_hash[h];
1147 tb->phys_hash_next = *ptb;
1148 *ptb = tb;
bellardfd6ce8f2003-05-14 19:00:11 +00001149
1150 /* add in the page list */
bellard9fa3e852004-01-04 18:06:42 +00001151 tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK);
1152 if (phys_page2 != -1)
1153 tb_alloc_page(tb, 1, phys_page2);
1154 else
1155 tb->page_addr[1] = -1;
bellard9fa3e852004-01-04 18:06:42 +00001156
bellardd4e81642003-05-25 16:46:15 +00001157 tb->jmp_first = (TranslationBlock *)((long)tb | 2);
1158 tb->jmp_next[0] = NULL;
1159 tb->jmp_next[1] = NULL;
1160
1161 /* init original jump addresses */
1162 if (tb->tb_next_offset[0] != 0xffff)
1163 tb_reset_jump(tb, 0);
1164 if (tb->tb_next_offset[1] != 0xffff)
1165 tb_reset_jump(tb, 1);
bellard8a40a182005-11-20 10:35:40 +00001166
1167#ifdef DEBUG_TB_CHECK
1168 tb_page_check();
1169#endif
pbrookc8a706f2008-06-02 16:16:42 +00001170 mmap_unlock();
bellardfd6ce8f2003-05-14 19:00:11 +00001171}
1172
bellarda513fe12003-05-27 23:29:48 +00001173/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
1174 tb[1].tc_ptr. Return NULL if not found */
1175TranslationBlock *tb_find_pc(unsigned long tc_ptr)
1176{
1177 int m_min, m_max, m;
1178 unsigned long v;
1179 TranslationBlock *tb;
1180
1181 if (nb_tbs <= 0)
1182 return NULL;
1183 if (tc_ptr < (unsigned long)code_gen_buffer ||
1184 tc_ptr >= (unsigned long)code_gen_ptr)
1185 return NULL;
1186 /* binary search (cf Knuth) */
1187 m_min = 0;
1188 m_max = nb_tbs - 1;
1189 while (m_min <= m_max) {
1190 m = (m_min + m_max) >> 1;
1191 tb = &tbs[m];
1192 v = (unsigned long)tb->tc_ptr;
1193 if (v == tc_ptr)
1194 return tb;
1195 else if (tc_ptr < v) {
1196 m_max = m - 1;
1197 } else {
1198 m_min = m + 1;
1199 }
ths5fafdf22007-09-16 21:08:06 +00001200 }
bellarda513fe12003-05-27 23:29:48 +00001201 return &tbs[m_max];
1202}
bellard75012672003-06-21 13:11:07 +00001203
bellardea041c02003-06-25 16:16:50 +00001204static void tb_reset_jump_recursive(TranslationBlock *tb);
1205
1206static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
1207{
1208 TranslationBlock *tb1, *tb_next, **ptb;
1209 unsigned int n1;
1210
1211 tb1 = tb->jmp_next[n];
1212 if (tb1 != NULL) {
1213 /* find head of list */
1214 for(;;) {
1215 n1 = (long)tb1 & 3;
1216 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1217 if (n1 == 2)
1218 break;
1219 tb1 = tb1->jmp_next[n1];
1220 }
1221 /* we are now sure now that tb jumps to tb1 */
1222 tb_next = tb1;
1223
1224 /* remove tb from the jmp_first list */
1225 ptb = &tb_next->jmp_first;
1226 for(;;) {
1227 tb1 = *ptb;
1228 n1 = (long)tb1 & 3;
1229 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1230 if (n1 == n && tb1 == tb)
1231 break;
1232 ptb = &tb1->jmp_next[n1];
1233 }
1234 *ptb = tb->jmp_next[n];
1235 tb->jmp_next[n] = NULL;
ths3b46e622007-09-17 08:09:54 +00001236
bellardea041c02003-06-25 16:16:50 +00001237 /* suppress the jump to next tb in generated code */
1238 tb_reset_jump(tb, n);
1239
bellard01243112004-01-04 15:48:17 +00001240 /* suppress jumps in the tb on which we could have jumped */
bellardea041c02003-06-25 16:16:50 +00001241 tb_reset_jump_recursive(tb_next);
1242 }
1243}
1244
1245static void tb_reset_jump_recursive(TranslationBlock *tb)
1246{
1247 tb_reset_jump_recursive2(tb, 0);
1248 tb_reset_jump_recursive2(tb, 1);
1249}
1250
bellard1fddef42005-04-17 19:16:13 +00001251#if defined(TARGET_HAS_ICE)
bellardd720b932004-04-25 17:57:43 +00001252static void breakpoint_invalidate(CPUState *env, target_ulong pc)
1253{
j_mayer9b3c35e2007-04-07 11:21:28 +00001254 target_phys_addr_t addr;
1255 target_ulong pd;
pbrookc2f07f82006-04-08 17:14:56 +00001256 ram_addr_t ram_addr;
1257 PhysPageDesc *p;
bellardd720b932004-04-25 17:57:43 +00001258
pbrookc2f07f82006-04-08 17:14:56 +00001259 addr = cpu_get_phys_page_debug(env, pc);
1260 p = phys_page_find(addr >> TARGET_PAGE_BITS);
1261 if (!p) {
1262 pd = IO_MEM_UNASSIGNED;
1263 } else {
1264 pd = p->phys_offset;
1265 }
1266 ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
pbrook706cd4b2006-04-08 17:36:21 +00001267 tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
bellardd720b932004-04-25 17:57:43 +00001268}
bellardc27004e2005-01-03 23:35:10 +00001269#endif
bellardd720b932004-04-25 17:57:43 +00001270
pbrook6658ffb2007-03-16 23:58:11 +00001271/* Add a watchpoint. */
pbrook0f459d12008-06-09 00:20:13 +00001272int cpu_watchpoint_insert(CPUState *env, target_ulong addr, int type)
pbrook6658ffb2007-03-16 23:58:11 +00001273{
1274 int i;
1275
1276 for (i = 0; i < env->nb_watchpoints; i++) {
1277 if (addr == env->watchpoint[i].vaddr)
1278 return 0;
1279 }
1280 if (env->nb_watchpoints >= MAX_WATCHPOINTS)
1281 return -1;
1282
1283 i = env->nb_watchpoints++;
1284 env->watchpoint[i].vaddr = addr;
pbrook0f459d12008-06-09 00:20:13 +00001285 env->watchpoint[i].type = type;
pbrook6658ffb2007-03-16 23:58:11 +00001286 tlb_flush_page(env, addr);
1287 /* FIXME: This flush is needed because of the hack to make memory ops
1288 terminate the TB. It can be removed once the proper IO trap and
1289 re-execute bits are in. */
1290 tb_flush(env);
1291 return i;
1292}
1293
1294/* Remove a watchpoint. */
1295int cpu_watchpoint_remove(CPUState *env, target_ulong addr)
1296{
1297 int i;
1298
1299 for (i = 0; i < env->nb_watchpoints; i++) {
1300 if (addr == env->watchpoint[i].vaddr) {
1301 env->nb_watchpoints--;
1302 env->watchpoint[i] = env->watchpoint[env->nb_watchpoints];
1303 tlb_flush_page(env, addr);
1304 return 0;
1305 }
1306 }
1307 return -1;
1308}
1309
edgar_igl7d03f822008-05-17 18:58:29 +00001310/* Remove all watchpoints. */
1311void cpu_watchpoint_remove_all(CPUState *env) {
1312 int i;
1313
1314 for (i = 0; i < env->nb_watchpoints; i++) {
1315 tlb_flush_page(env, env->watchpoint[i].vaddr);
1316 }
1317 env->nb_watchpoints = 0;
1318}
1319
bellardc33a3462003-07-29 20:50:33 +00001320/* add a breakpoint. EXCP_DEBUG is returned by the CPU loop if a
1321 breakpoint is reached */
bellard2e126692004-04-25 21:28:44 +00001322int cpu_breakpoint_insert(CPUState *env, target_ulong pc)
bellard4c3a88a2003-07-26 12:06:08 +00001323{
bellard1fddef42005-04-17 19:16:13 +00001324#if defined(TARGET_HAS_ICE)
bellard4c3a88a2003-07-26 12:06:08 +00001325 int i;
ths3b46e622007-09-17 08:09:54 +00001326
bellard4c3a88a2003-07-26 12:06:08 +00001327 for(i = 0; i < env->nb_breakpoints; i++) {
1328 if (env->breakpoints[i] == pc)
1329 return 0;
1330 }
1331
1332 if (env->nb_breakpoints >= MAX_BREAKPOINTS)
1333 return -1;
1334 env->breakpoints[env->nb_breakpoints++] = pc;
ths3b46e622007-09-17 08:09:54 +00001335
bellardd720b932004-04-25 17:57:43 +00001336 breakpoint_invalidate(env, pc);
bellard4c3a88a2003-07-26 12:06:08 +00001337 return 0;
1338#else
1339 return -1;
1340#endif
1341}
1342
edgar_igl7d03f822008-05-17 18:58:29 +00001343/* remove all breakpoints */
1344void cpu_breakpoint_remove_all(CPUState *env) {
1345#if defined(TARGET_HAS_ICE)
1346 int i;
1347 for(i = 0; i < env->nb_breakpoints; i++) {
1348 breakpoint_invalidate(env, env->breakpoints[i]);
1349 }
1350 env->nb_breakpoints = 0;
1351#endif
1352}
1353
bellard4c3a88a2003-07-26 12:06:08 +00001354/* remove a breakpoint */
bellard2e126692004-04-25 21:28:44 +00001355int cpu_breakpoint_remove(CPUState *env, target_ulong pc)
bellard4c3a88a2003-07-26 12:06:08 +00001356{
bellard1fddef42005-04-17 19:16:13 +00001357#if defined(TARGET_HAS_ICE)
bellard4c3a88a2003-07-26 12:06:08 +00001358 int i;
1359 for(i = 0; i < env->nb_breakpoints; i++) {
1360 if (env->breakpoints[i] == pc)
1361 goto found;
1362 }
1363 return -1;
1364 found:
bellard4c3a88a2003-07-26 12:06:08 +00001365 env->nb_breakpoints--;
bellard1fddef42005-04-17 19:16:13 +00001366 if (i < env->nb_breakpoints)
1367 env->breakpoints[i] = env->breakpoints[env->nb_breakpoints];
bellardd720b932004-04-25 17:57:43 +00001368
1369 breakpoint_invalidate(env, pc);
bellard4c3a88a2003-07-26 12:06:08 +00001370 return 0;
1371#else
1372 return -1;
1373#endif
1374}
1375
bellardc33a3462003-07-29 20:50:33 +00001376/* enable or disable single step mode. EXCP_DEBUG is returned by the
1377 CPU loop after each instruction */
1378void cpu_single_step(CPUState *env, int enabled)
1379{
bellard1fddef42005-04-17 19:16:13 +00001380#if defined(TARGET_HAS_ICE)
bellardc33a3462003-07-29 20:50:33 +00001381 if (env->singlestep_enabled != enabled) {
1382 env->singlestep_enabled = enabled;
1383 /* must flush all the translated code to avoid inconsistancies */
bellard9fa3e852004-01-04 18:06:42 +00001384 /* XXX: only flush what is necessary */
bellard01243112004-01-04 15:48:17 +00001385 tb_flush(env);
bellardc33a3462003-07-29 20:50:33 +00001386 }
1387#endif
1388}
1389
bellard34865132003-10-05 14:28:56 +00001390/* enable or disable low levels log */
1391void cpu_set_log(int log_flags)
1392{
1393 loglevel = log_flags;
1394 if (loglevel && !logfile) {
pbrook11fcfab2007-07-01 18:21:11 +00001395 logfile = fopen(logfilename, log_append ? "a" : "w");
bellard34865132003-10-05 14:28:56 +00001396 if (!logfile) {
1397 perror(logfilename);
1398 _exit(1);
1399 }
bellard9fa3e852004-01-04 18:06:42 +00001400#if !defined(CONFIG_SOFTMMU)
1401 /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1402 {
1403 static uint8_t logfile_buf[4096];
1404 setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1405 }
1406#else
bellard34865132003-10-05 14:28:56 +00001407 setvbuf(logfile, NULL, _IOLBF, 0);
bellard9fa3e852004-01-04 18:06:42 +00001408#endif
pbrooke735b912007-06-30 13:53:24 +00001409 log_append = 1;
1410 }
1411 if (!loglevel && logfile) {
1412 fclose(logfile);
1413 logfile = NULL;
bellard34865132003-10-05 14:28:56 +00001414 }
1415}
1416
1417void cpu_set_log_filename(const char *filename)
1418{
1419 logfilename = strdup(filename);
pbrooke735b912007-06-30 13:53:24 +00001420 if (logfile) {
1421 fclose(logfile);
1422 logfile = NULL;
1423 }
1424 cpu_set_log(loglevel);
bellard34865132003-10-05 14:28:56 +00001425}
bellardc33a3462003-07-29 20:50:33 +00001426
bellard01243112004-01-04 15:48:17 +00001427/* mask must never be zero, except for A20 change call */
bellard68a79312003-06-30 13:12:32 +00001428void cpu_interrupt(CPUState *env, int mask)
bellardea041c02003-06-25 16:16:50 +00001429{
pbrookd5975362008-06-07 20:50:51 +00001430#if !defined(USE_NPTL)
bellardea041c02003-06-25 16:16:50 +00001431 TranslationBlock *tb;
aurel3215a51152008-03-28 22:29:15 +00001432 static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
pbrookd5975362008-06-07 20:50:51 +00001433#endif
pbrook2e70f6e2008-06-29 01:03:05 +00001434 int old_mask;
bellard59817cc2004-02-16 22:01:13 +00001435
pbrook2e70f6e2008-06-29 01:03:05 +00001436 old_mask = env->interrupt_request;
pbrookd5975362008-06-07 20:50:51 +00001437 /* FIXME: This is probably not threadsafe. A different thread could
thsbf20dc02008-06-30 17:22:19 +00001438 be in the middle of a read-modify-write operation. */
bellard68a79312003-06-30 13:12:32 +00001439 env->interrupt_request |= mask;
pbrookd5975362008-06-07 20:50:51 +00001440#if defined(USE_NPTL)
1441 /* FIXME: TB unchaining isn't SMP safe. For now just ignore the
1442 problem and hope the cpu will stop of its own accord. For userspace
1443 emulation this often isn't actually as bad as it sounds. Often
1444 signals are used primarily to interrupt blocking syscalls. */
1445#else
pbrook2e70f6e2008-06-29 01:03:05 +00001446 if (use_icount) {
pbrook266910c2008-07-09 15:31:50 +00001447 env->icount_decr.u16.high = 0xffff;
pbrook2e70f6e2008-06-29 01:03:05 +00001448#ifndef CONFIG_USER_ONLY
1449 /* CPU_INTERRUPT_EXIT isn't a real interrupt. It just means
1450 an async event happened and we need to process it. */
1451 if (!can_do_io(env)
1452 && (mask & ~(old_mask | CPU_INTERRUPT_EXIT)) != 0) {
1453 cpu_abort(env, "Raised interrupt while not in I/O function");
1454 }
1455#endif
1456 } else {
1457 tb = env->current_tb;
1458 /* if the cpu is currently executing code, we must unlink it and
1459 all the potentially executing TB */
1460 if (tb && !testandset(&interrupt_lock)) {
1461 env->current_tb = NULL;
1462 tb_reset_jump_recursive(tb);
1463 resetlock(&interrupt_lock);
1464 }
bellardea041c02003-06-25 16:16:50 +00001465 }
pbrookd5975362008-06-07 20:50:51 +00001466#endif
bellardea041c02003-06-25 16:16:50 +00001467}
1468
bellardb54ad042004-05-20 13:42:52 +00001469void cpu_reset_interrupt(CPUState *env, int mask)
1470{
1471 env->interrupt_request &= ~mask;
1472}
1473
bellardf193c792004-03-21 17:06:25 +00001474CPULogItem cpu_log_items[] = {
ths5fafdf22007-09-16 21:08:06 +00001475 { CPU_LOG_TB_OUT_ASM, "out_asm",
bellardf193c792004-03-21 17:06:25 +00001476 "show generated host assembly code for each compiled TB" },
1477 { CPU_LOG_TB_IN_ASM, "in_asm",
1478 "show target assembly code for each compiled TB" },
ths5fafdf22007-09-16 21:08:06 +00001479 { CPU_LOG_TB_OP, "op",
bellard57fec1f2008-02-01 10:50:11 +00001480 "show micro ops for each compiled TB" },
bellardf193c792004-03-21 17:06:25 +00001481 { CPU_LOG_TB_OP_OPT, "op_opt",
blueswir1e01a1152008-03-14 17:37:11 +00001482 "show micro ops "
1483#ifdef TARGET_I386
1484 "before eflags optimization and "
bellardf193c792004-03-21 17:06:25 +00001485#endif
blueswir1e01a1152008-03-14 17:37:11 +00001486 "after liveness analysis" },
bellardf193c792004-03-21 17:06:25 +00001487 { CPU_LOG_INT, "int",
1488 "show interrupts/exceptions in short format" },
1489 { CPU_LOG_EXEC, "exec",
1490 "show trace before each executed TB (lots of logs)" },
bellard9fddaa02004-05-21 12:59:32 +00001491 { CPU_LOG_TB_CPU, "cpu",
thse91c8a72007-06-03 13:35:16 +00001492 "show CPU state before block translation" },
bellardf193c792004-03-21 17:06:25 +00001493#ifdef TARGET_I386
1494 { CPU_LOG_PCALL, "pcall",
1495 "show protected mode far calls/returns/exceptions" },
1496#endif
bellard8e3a9fd2004-10-09 17:32:58 +00001497#ifdef DEBUG_IOPORT
bellardfd872592004-05-12 19:11:15 +00001498 { CPU_LOG_IOPORT, "ioport",
1499 "show all i/o ports accesses" },
bellard8e3a9fd2004-10-09 17:32:58 +00001500#endif
bellardf193c792004-03-21 17:06:25 +00001501 { 0, NULL, NULL },
1502};
1503
1504static int cmp1(const char *s1, int n, const char *s2)
1505{
1506 if (strlen(s2) != n)
1507 return 0;
1508 return memcmp(s1, s2, n) == 0;
1509}
ths3b46e622007-09-17 08:09:54 +00001510
bellardf193c792004-03-21 17:06:25 +00001511/* takes a comma separated list of log masks. Return 0 if error. */
1512int cpu_str_to_log_mask(const char *str)
1513{
1514 CPULogItem *item;
1515 int mask;
1516 const char *p, *p1;
1517
1518 p = str;
1519 mask = 0;
1520 for(;;) {
1521 p1 = strchr(p, ',');
1522 if (!p1)
1523 p1 = p + strlen(p);
bellard8e3a9fd2004-10-09 17:32:58 +00001524 if(cmp1(p,p1-p,"all")) {
1525 for(item = cpu_log_items; item->mask != 0; item++) {
1526 mask |= item->mask;
1527 }
1528 } else {
bellardf193c792004-03-21 17:06:25 +00001529 for(item = cpu_log_items; item->mask != 0; item++) {
1530 if (cmp1(p, p1 - p, item->name))
1531 goto found;
1532 }
1533 return 0;
bellard8e3a9fd2004-10-09 17:32:58 +00001534 }
bellardf193c792004-03-21 17:06:25 +00001535 found:
1536 mask |= item->mask;
1537 if (*p1 != ',')
1538 break;
1539 p = p1 + 1;
1540 }
1541 return mask;
1542}
bellardea041c02003-06-25 16:16:50 +00001543
bellard75012672003-06-21 13:11:07 +00001544void cpu_abort(CPUState *env, const char *fmt, ...)
1545{
1546 va_list ap;
pbrook493ae1f2007-11-23 16:53:59 +00001547 va_list ap2;
bellard75012672003-06-21 13:11:07 +00001548
1549 va_start(ap, fmt);
pbrook493ae1f2007-11-23 16:53:59 +00001550 va_copy(ap2, ap);
bellard75012672003-06-21 13:11:07 +00001551 fprintf(stderr, "qemu: fatal: ");
1552 vfprintf(stderr, fmt, ap);
1553 fprintf(stderr, "\n");
1554#ifdef TARGET_I386
bellard7fe48482004-10-09 18:08:01 +00001555 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1556#else
1557 cpu_dump_state(env, stderr, fprintf, 0);
bellard75012672003-06-21 13:11:07 +00001558#endif
balrog924edca2007-06-10 14:07:13 +00001559 if (logfile) {
j_mayerf9373292007-09-29 12:18:20 +00001560 fprintf(logfile, "qemu: fatal: ");
pbrook493ae1f2007-11-23 16:53:59 +00001561 vfprintf(logfile, fmt, ap2);
j_mayerf9373292007-09-29 12:18:20 +00001562 fprintf(logfile, "\n");
1563#ifdef TARGET_I386
1564 cpu_dump_state(env, logfile, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1565#else
1566 cpu_dump_state(env, logfile, fprintf, 0);
1567#endif
balrog924edca2007-06-10 14:07:13 +00001568 fflush(logfile);
1569 fclose(logfile);
1570 }
pbrook493ae1f2007-11-23 16:53:59 +00001571 va_end(ap2);
j_mayerf9373292007-09-29 12:18:20 +00001572 va_end(ap);
bellard75012672003-06-21 13:11:07 +00001573 abort();
1574}
1575
thsc5be9f02007-02-28 20:20:53 +00001576CPUState *cpu_copy(CPUState *env)
1577{
ths01ba9812007-12-09 02:22:57 +00001578 CPUState *new_env = cpu_init(env->cpu_model_str);
thsc5be9f02007-02-28 20:20:53 +00001579 /* preserve chaining and index */
1580 CPUState *next_cpu = new_env->next_cpu;
1581 int cpu_index = new_env->cpu_index;
1582 memcpy(new_env, env, sizeof(CPUState));
1583 new_env->next_cpu = next_cpu;
1584 new_env->cpu_index = cpu_index;
1585 return new_env;
1586}
1587
bellard01243112004-01-04 15:48:17 +00001588#if !defined(CONFIG_USER_ONLY)
1589
edgar_igl5c751e92008-05-06 08:44:21 +00001590static inline void tlb_flush_jmp_cache(CPUState *env, target_ulong addr)
1591{
1592 unsigned int i;
1593
1594 /* Discard jump cache entries for any tb which might potentially
1595 overlap the flushed page. */
1596 i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
1597 memset (&env->tb_jmp_cache[i], 0,
1598 TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
1599
1600 i = tb_jmp_cache_hash_page(addr);
1601 memset (&env->tb_jmp_cache[i], 0,
1602 TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
1603}
1604
bellardee8b7022004-02-03 23:35:10 +00001605/* NOTE: if flush_global is true, also flush global entries (not
1606 implemented yet) */
1607void tlb_flush(CPUState *env, int flush_global)
bellard33417e72003-08-10 21:47:01 +00001608{
bellard33417e72003-08-10 21:47:01 +00001609 int i;
bellard01243112004-01-04 15:48:17 +00001610
bellard9fa3e852004-01-04 18:06:42 +00001611#if defined(DEBUG_TLB)
1612 printf("tlb_flush:\n");
1613#endif
bellard01243112004-01-04 15:48:17 +00001614 /* must reset current TB so that interrupts cannot modify the
1615 links while we are modifying them */
1616 env->current_tb = NULL;
1617
bellard33417e72003-08-10 21:47:01 +00001618 for(i = 0; i < CPU_TLB_SIZE; i++) {
bellard84b7b8e2005-11-28 21:19:04 +00001619 env->tlb_table[0][i].addr_read = -1;
1620 env->tlb_table[0][i].addr_write = -1;
1621 env->tlb_table[0][i].addr_code = -1;
1622 env->tlb_table[1][i].addr_read = -1;
1623 env->tlb_table[1][i].addr_write = -1;
1624 env->tlb_table[1][i].addr_code = -1;
j_mayer6fa4cea2007-04-05 06:43:27 +00001625#if (NB_MMU_MODES >= 3)
1626 env->tlb_table[2][i].addr_read = -1;
1627 env->tlb_table[2][i].addr_write = -1;
1628 env->tlb_table[2][i].addr_code = -1;
1629#if (NB_MMU_MODES == 4)
1630 env->tlb_table[3][i].addr_read = -1;
1631 env->tlb_table[3][i].addr_write = -1;
1632 env->tlb_table[3][i].addr_code = -1;
1633#endif
1634#endif
bellard33417e72003-08-10 21:47:01 +00001635 }
bellard9fa3e852004-01-04 18:06:42 +00001636
bellard8a40a182005-11-20 10:35:40 +00001637 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
bellard9fa3e852004-01-04 18:06:42 +00001638
bellard0a962c02005-02-10 22:00:27 +00001639#ifdef USE_KQEMU
1640 if (env->kqemu_enabled) {
1641 kqemu_flush(env, flush_global);
1642 }
1643#endif
bellarde3db7222005-01-26 22:00:47 +00001644 tlb_flush_count++;
bellard33417e72003-08-10 21:47:01 +00001645}
1646
bellard274da6b2004-05-20 21:56:27 +00001647static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
bellard61382a52003-10-27 21:22:23 +00001648{
ths5fafdf22007-09-16 21:08:06 +00001649 if (addr == (tlb_entry->addr_read &
bellard84b7b8e2005-11-28 21:19:04 +00001650 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
ths5fafdf22007-09-16 21:08:06 +00001651 addr == (tlb_entry->addr_write &
bellard84b7b8e2005-11-28 21:19:04 +00001652 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
ths5fafdf22007-09-16 21:08:06 +00001653 addr == (tlb_entry->addr_code &
bellard84b7b8e2005-11-28 21:19:04 +00001654 (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1655 tlb_entry->addr_read = -1;
1656 tlb_entry->addr_write = -1;
1657 tlb_entry->addr_code = -1;
1658 }
bellard61382a52003-10-27 21:22:23 +00001659}
1660
bellard2e126692004-04-25 21:28:44 +00001661void tlb_flush_page(CPUState *env, target_ulong addr)
bellard33417e72003-08-10 21:47:01 +00001662{
bellard8a40a182005-11-20 10:35:40 +00001663 int i;
bellard01243112004-01-04 15:48:17 +00001664
bellard9fa3e852004-01-04 18:06:42 +00001665#if defined(DEBUG_TLB)
bellard108c49b2005-07-24 12:55:09 +00001666 printf("tlb_flush_page: " TARGET_FMT_lx "\n", addr);
bellard9fa3e852004-01-04 18:06:42 +00001667#endif
bellard01243112004-01-04 15:48:17 +00001668 /* must reset current TB so that interrupts cannot modify the
1669 links while we are modifying them */
1670 env->current_tb = NULL;
bellard33417e72003-08-10 21:47:01 +00001671
bellard61382a52003-10-27 21:22:23 +00001672 addr &= TARGET_PAGE_MASK;
bellard33417e72003-08-10 21:47:01 +00001673 i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
bellard84b7b8e2005-11-28 21:19:04 +00001674 tlb_flush_entry(&env->tlb_table[0][i], addr);
1675 tlb_flush_entry(&env->tlb_table[1][i], addr);
j_mayer6fa4cea2007-04-05 06:43:27 +00001676#if (NB_MMU_MODES >= 3)
1677 tlb_flush_entry(&env->tlb_table[2][i], addr);
1678#if (NB_MMU_MODES == 4)
1679 tlb_flush_entry(&env->tlb_table[3][i], addr);
1680#endif
1681#endif
bellard01243112004-01-04 15:48:17 +00001682
edgar_igl5c751e92008-05-06 08:44:21 +00001683 tlb_flush_jmp_cache(env, addr);
bellard9fa3e852004-01-04 18:06:42 +00001684
bellard0a962c02005-02-10 22:00:27 +00001685#ifdef USE_KQEMU
1686 if (env->kqemu_enabled) {
1687 kqemu_flush_page(env, addr);
1688 }
1689#endif
bellard9fa3e852004-01-04 18:06:42 +00001690}
1691
bellard9fa3e852004-01-04 18:06:42 +00001692/* update the TLBs so that writes to code in the virtual page 'addr'
1693 can be detected */
bellard6a00d602005-11-21 23:25:50 +00001694static void tlb_protect_code(ram_addr_t ram_addr)
bellard61382a52003-10-27 21:22:23 +00001695{
ths5fafdf22007-09-16 21:08:06 +00001696 cpu_physical_memory_reset_dirty(ram_addr,
bellard6a00d602005-11-21 23:25:50 +00001697 ram_addr + TARGET_PAGE_SIZE,
1698 CODE_DIRTY_FLAG);
bellard9fa3e852004-01-04 18:06:42 +00001699}
1700
bellard9fa3e852004-01-04 18:06:42 +00001701/* update the TLB so that writes in physical page 'phys_addr' are no longer
bellard3a7d9292005-08-21 09:26:42 +00001702 tested for self modifying code */
ths5fafdf22007-09-16 21:08:06 +00001703static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
bellard3a7d9292005-08-21 09:26:42 +00001704 target_ulong vaddr)
bellard9fa3e852004-01-04 18:06:42 +00001705{
bellard3a7d9292005-08-21 09:26:42 +00001706 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] |= CODE_DIRTY_FLAG;
bellard1ccde1c2004-02-06 19:46:14 +00001707}
1708
ths5fafdf22007-09-16 21:08:06 +00001709static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
bellard1ccde1c2004-02-06 19:46:14 +00001710 unsigned long start, unsigned long length)
1711{
1712 unsigned long addr;
bellard84b7b8e2005-11-28 21:19:04 +00001713 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1714 addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
bellard1ccde1c2004-02-06 19:46:14 +00001715 if ((addr - start) < length) {
pbrook0f459d12008-06-09 00:20:13 +00001716 tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
bellard1ccde1c2004-02-06 19:46:14 +00001717 }
1718 }
1719}
1720
bellard3a7d9292005-08-21 09:26:42 +00001721void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
bellard0a962c02005-02-10 22:00:27 +00001722 int dirty_flags)
bellard1ccde1c2004-02-06 19:46:14 +00001723{
1724 CPUState *env;
bellard4f2ac232004-04-26 19:44:02 +00001725 unsigned long length, start1;
bellard0a962c02005-02-10 22:00:27 +00001726 int i, mask, len;
1727 uint8_t *p;
bellard1ccde1c2004-02-06 19:46:14 +00001728
1729 start &= TARGET_PAGE_MASK;
1730 end = TARGET_PAGE_ALIGN(end);
1731
1732 length = end - start;
1733 if (length == 0)
1734 return;
bellard0a962c02005-02-10 22:00:27 +00001735 len = length >> TARGET_PAGE_BITS;
bellard3a7d9292005-08-21 09:26:42 +00001736#ifdef USE_KQEMU
bellard6a00d602005-11-21 23:25:50 +00001737 /* XXX: should not depend on cpu context */
1738 env = first_cpu;
bellard3a7d9292005-08-21 09:26:42 +00001739 if (env->kqemu_enabled) {
bellardf23db162005-08-21 19:12:28 +00001740 ram_addr_t addr;
1741 addr = start;
1742 for(i = 0; i < len; i++) {
1743 kqemu_set_notdirty(env, addr);
1744 addr += TARGET_PAGE_SIZE;
1745 }
bellard3a7d9292005-08-21 09:26:42 +00001746 }
1747#endif
bellardf23db162005-08-21 19:12:28 +00001748 mask = ~dirty_flags;
1749 p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
1750 for(i = 0; i < len; i++)
1751 p[i] &= mask;
1752
bellard1ccde1c2004-02-06 19:46:14 +00001753 /* we modify the TLB cache so that the dirty bit will be set again
1754 when accessing the range */
bellard59817cc2004-02-16 22:01:13 +00001755 start1 = start + (unsigned long)phys_ram_base;
bellard6a00d602005-11-21 23:25:50 +00001756 for(env = first_cpu; env != NULL; env = env->next_cpu) {
1757 for(i = 0; i < CPU_TLB_SIZE; i++)
bellard84b7b8e2005-11-28 21:19:04 +00001758 tlb_reset_dirty_range(&env->tlb_table[0][i], start1, length);
bellard6a00d602005-11-21 23:25:50 +00001759 for(i = 0; i < CPU_TLB_SIZE; i++)
bellard84b7b8e2005-11-28 21:19:04 +00001760 tlb_reset_dirty_range(&env->tlb_table[1][i], start1, length);
j_mayer6fa4cea2007-04-05 06:43:27 +00001761#if (NB_MMU_MODES >= 3)
1762 for(i = 0; i < CPU_TLB_SIZE; i++)
1763 tlb_reset_dirty_range(&env->tlb_table[2][i], start1, length);
1764#if (NB_MMU_MODES == 4)
1765 for(i = 0; i < CPU_TLB_SIZE; i++)
1766 tlb_reset_dirty_range(&env->tlb_table[3][i], start1, length);
1767#endif
1768#endif
bellard6a00d602005-11-21 23:25:50 +00001769 }
bellard1ccde1c2004-02-06 19:46:14 +00001770}
1771
bellard3a7d9292005-08-21 09:26:42 +00001772static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1773{
1774 ram_addr_t ram_addr;
1775
bellard84b7b8e2005-11-28 21:19:04 +00001776 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
ths5fafdf22007-09-16 21:08:06 +00001777 ram_addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) +
bellard3a7d9292005-08-21 09:26:42 +00001778 tlb_entry->addend - (unsigned long)phys_ram_base;
1779 if (!cpu_physical_memory_is_dirty(ram_addr)) {
pbrook0f459d12008-06-09 00:20:13 +00001780 tlb_entry->addr_write |= TLB_NOTDIRTY;
bellard3a7d9292005-08-21 09:26:42 +00001781 }
1782 }
1783}
1784
1785/* update the TLB according to the current state of the dirty bits */
1786void cpu_tlb_update_dirty(CPUState *env)
1787{
1788 int i;
1789 for(i = 0; i < CPU_TLB_SIZE; i++)
bellard84b7b8e2005-11-28 21:19:04 +00001790 tlb_update_dirty(&env->tlb_table[0][i]);
bellard3a7d9292005-08-21 09:26:42 +00001791 for(i = 0; i < CPU_TLB_SIZE; i++)
bellard84b7b8e2005-11-28 21:19:04 +00001792 tlb_update_dirty(&env->tlb_table[1][i]);
j_mayer6fa4cea2007-04-05 06:43:27 +00001793#if (NB_MMU_MODES >= 3)
1794 for(i = 0; i < CPU_TLB_SIZE; i++)
1795 tlb_update_dirty(&env->tlb_table[2][i]);
1796#if (NB_MMU_MODES == 4)
1797 for(i = 0; i < CPU_TLB_SIZE; i++)
1798 tlb_update_dirty(&env->tlb_table[3][i]);
1799#endif
1800#endif
bellard3a7d9292005-08-21 09:26:42 +00001801}
1802
pbrook0f459d12008-06-09 00:20:13 +00001803static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, target_ulong vaddr)
bellard1ccde1c2004-02-06 19:46:14 +00001804{
pbrook0f459d12008-06-09 00:20:13 +00001805 if (tlb_entry->addr_write == (vaddr | TLB_NOTDIRTY))
1806 tlb_entry->addr_write = vaddr;
bellard1ccde1c2004-02-06 19:46:14 +00001807}
1808
pbrook0f459d12008-06-09 00:20:13 +00001809/* update the TLB corresponding to virtual page vaddr
1810 so that it is no longer dirty */
1811static inline void tlb_set_dirty(CPUState *env, target_ulong vaddr)
bellard1ccde1c2004-02-06 19:46:14 +00001812{
bellard1ccde1c2004-02-06 19:46:14 +00001813 int i;
1814
pbrook0f459d12008-06-09 00:20:13 +00001815 vaddr &= TARGET_PAGE_MASK;
bellard1ccde1c2004-02-06 19:46:14 +00001816 i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
pbrook0f459d12008-06-09 00:20:13 +00001817 tlb_set_dirty1(&env->tlb_table[0][i], vaddr);
1818 tlb_set_dirty1(&env->tlb_table[1][i], vaddr);
j_mayer6fa4cea2007-04-05 06:43:27 +00001819#if (NB_MMU_MODES >= 3)
pbrook0f459d12008-06-09 00:20:13 +00001820 tlb_set_dirty1(&env->tlb_table[2][i], vaddr);
j_mayer6fa4cea2007-04-05 06:43:27 +00001821#if (NB_MMU_MODES == 4)
pbrook0f459d12008-06-09 00:20:13 +00001822 tlb_set_dirty1(&env->tlb_table[3][i], vaddr);
j_mayer6fa4cea2007-04-05 06:43:27 +00001823#endif
1824#endif
bellard9fa3e852004-01-04 18:06:42 +00001825}
1826
bellard59817cc2004-02-16 22:01:13 +00001827/* add a new TLB entry. At most one entry for a given virtual address
1828 is permitted. Return 0 if OK or 2 if the page could not be mapped
1829 (can only happen in non SOFTMMU mode for I/O pages or pages
1830 conflicting with the host address space). */
ths5fafdf22007-09-16 21:08:06 +00001831int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
1832 target_phys_addr_t paddr, int prot,
j_mayer6ebbf392007-10-14 07:07:08 +00001833 int mmu_idx, int is_softmmu)
bellard9fa3e852004-01-04 18:06:42 +00001834{
bellard92e873b2004-05-21 14:52:29 +00001835 PhysPageDesc *p;
bellard4f2ac232004-04-26 19:44:02 +00001836 unsigned long pd;
bellard9fa3e852004-01-04 18:06:42 +00001837 unsigned int index;
bellard4f2ac232004-04-26 19:44:02 +00001838 target_ulong address;
pbrook0f459d12008-06-09 00:20:13 +00001839 target_ulong code_address;
bellard108c49b2005-07-24 12:55:09 +00001840 target_phys_addr_t addend;
bellard9fa3e852004-01-04 18:06:42 +00001841 int ret;
bellard84b7b8e2005-11-28 21:19:04 +00001842 CPUTLBEntry *te;
pbrook6658ffb2007-03-16 23:58:11 +00001843 int i;
pbrook0f459d12008-06-09 00:20:13 +00001844 target_phys_addr_t iotlb;
bellard9fa3e852004-01-04 18:06:42 +00001845
bellard92e873b2004-05-21 14:52:29 +00001846 p = phys_page_find(paddr >> TARGET_PAGE_BITS);
bellard9fa3e852004-01-04 18:06:42 +00001847 if (!p) {
1848 pd = IO_MEM_UNASSIGNED;
bellard9fa3e852004-01-04 18:06:42 +00001849 } else {
1850 pd = p->phys_offset;
bellard9fa3e852004-01-04 18:06:42 +00001851 }
1852#if defined(DEBUG_TLB)
j_mayer6ebbf392007-10-14 07:07:08 +00001853 printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x idx=%d smmu=%d pd=0x%08lx\n",
1854 vaddr, (int)paddr, prot, mmu_idx, is_softmmu, pd);
bellard9fa3e852004-01-04 18:06:42 +00001855#endif
1856
1857 ret = 0;
pbrook0f459d12008-06-09 00:20:13 +00001858 address = vaddr;
1859 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
1860 /* IO memory case (romd handled later) */
1861 address |= TLB_MMIO;
1862 }
1863 addend = (unsigned long)phys_ram_base + (pd & TARGET_PAGE_MASK);
1864 if ((pd & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
1865 /* Normal RAM. */
1866 iotlb = pd & TARGET_PAGE_MASK;
1867 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM)
1868 iotlb |= IO_MEM_NOTDIRTY;
1869 else
1870 iotlb |= IO_MEM_ROM;
1871 } else {
1872 /* IO handlers are currently passed a phsical address.
1873 It would be nice to pass an offset from the base address
1874 of that region. This would avoid having to special case RAM,
1875 and avoid full address decoding in every device.
1876 We can't use the high bits of pd for this because
1877 IO_MEM_ROMD uses these as a ram address. */
1878 iotlb = (pd & ~TARGET_PAGE_MASK) + paddr;
1879 }
pbrook6658ffb2007-03-16 23:58:11 +00001880
pbrook0f459d12008-06-09 00:20:13 +00001881 code_address = address;
1882 /* Make accesses to pages with watchpoints go via the
1883 watchpoint trap routines. */
1884 for (i = 0; i < env->nb_watchpoints; i++) {
1885 if (vaddr == (env->watchpoint[i].vaddr & TARGET_PAGE_MASK)) {
1886 iotlb = io_mem_watch + paddr;
1887 /* TODO: The memory case can be optimized by not trapping
1888 reads of pages with a write breakpoint. */
1889 address |= TLB_MMIO;
pbrook6658ffb2007-03-16 23:58:11 +00001890 }
pbrook0f459d12008-06-09 00:20:13 +00001891 }
balrogd79acba2007-06-26 20:01:13 +00001892
pbrook0f459d12008-06-09 00:20:13 +00001893 index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1894 env->iotlb[mmu_idx][index] = iotlb - vaddr;
1895 te = &env->tlb_table[mmu_idx][index];
1896 te->addend = addend - vaddr;
1897 if (prot & PAGE_READ) {
1898 te->addr_read = address;
1899 } else {
1900 te->addr_read = -1;
1901 }
edgar_igl5c751e92008-05-06 08:44:21 +00001902
pbrook0f459d12008-06-09 00:20:13 +00001903 if (prot & PAGE_EXEC) {
1904 te->addr_code = code_address;
1905 } else {
1906 te->addr_code = -1;
1907 }
1908 if (prot & PAGE_WRITE) {
1909 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM ||
1910 (pd & IO_MEM_ROMD)) {
1911 /* Write access calls the I/O callback. */
1912 te->addr_write = address | TLB_MMIO;
1913 } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
1914 !cpu_physical_memory_is_dirty(pd)) {
1915 te->addr_write = address | TLB_NOTDIRTY;
bellard84b7b8e2005-11-28 21:19:04 +00001916 } else {
pbrook0f459d12008-06-09 00:20:13 +00001917 te->addr_write = address;
bellard9fa3e852004-01-04 18:06:42 +00001918 }
pbrook0f459d12008-06-09 00:20:13 +00001919 } else {
1920 te->addr_write = -1;
bellard9fa3e852004-01-04 18:06:42 +00001921 }
bellard9fa3e852004-01-04 18:06:42 +00001922 return ret;
1923}
1924
bellard01243112004-01-04 15:48:17 +00001925#else
1926
bellardee8b7022004-02-03 23:35:10 +00001927void tlb_flush(CPUState *env, int flush_global)
bellard01243112004-01-04 15:48:17 +00001928{
1929}
1930
bellard2e126692004-04-25 21:28:44 +00001931void tlb_flush_page(CPUState *env, target_ulong addr)
bellard01243112004-01-04 15:48:17 +00001932{
1933}
1934
ths5fafdf22007-09-16 21:08:06 +00001935int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
1936 target_phys_addr_t paddr, int prot,
j_mayer6ebbf392007-10-14 07:07:08 +00001937 int mmu_idx, int is_softmmu)
bellard33417e72003-08-10 21:47:01 +00001938{
bellard9fa3e852004-01-04 18:06:42 +00001939 return 0;
1940}
bellard33417e72003-08-10 21:47:01 +00001941
bellard9fa3e852004-01-04 18:06:42 +00001942/* dump memory mappings */
1943void page_dump(FILE *f)
1944{
1945 unsigned long start, end;
1946 int i, j, prot, prot1;
1947 PageDesc *p;
1948
1949 fprintf(f, "%-8s %-8s %-8s %s\n",
1950 "start", "end", "size", "prot");
1951 start = -1;
1952 end = -1;
1953 prot = 0;
1954 for(i = 0; i <= L1_SIZE; i++) {
1955 if (i < L1_SIZE)
1956 p = l1_map[i];
1957 else
1958 p = NULL;
1959 for(j = 0;j < L2_SIZE; j++) {
1960 if (!p)
1961 prot1 = 0;
1962 else
1963 prot1 = p[j].flags;
1964 if (prot1 != prot) {
1965 end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
1966 if (start != -1) {
1967 fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
ths5fafdf22007-09-16 21:08:06 +00001968 start, end, end - start,
bellard9fa3e852004-01-04 18:06:42 +00001969 prot & PAGE_READ ? 'r' : '-',
1970 prot & PAGE_WRITE ? 'w' : '-',
1971 prot & PAGE_EXEC ? 'x' : '-');
1972 }
1973 if (prot1 != 0)
1974 start = end;
1975 else
1976 start = -1;
1977 prot = prot1;
1978 }
1979 if (!p)
1980 break;
1981 }
bellard33417e72003-08-10 21:47:01 +00001982 }
bellard33417e72003-08-10 21:47:01 +00001983}
1984
pbrook53a59602006-03-25 19:31:22 +00001985int page_get_flags(target_ulong address)
bellard33417e72003-08-10 21:47:01 +00001986{
bellard9fa3e852004-01-04 18:06:42 +00001987 PageDesc *p;
1988
1989 p = page_find(address >> TARGET_PAGE_BITS);
bellard33417e72003-08-10 21:47:01 +00001990 if (!p)
bellard9fa3e852004-01-04 18:06:42 +00001991 return 0;
1992 return p->flags;
bellard33417e72003-08-10 21:47:01 +00001993}
1994
bellard9fa3e852004-01-04 18:06:42 +00001995/* modify the flags of a page and invalidate the code if
1996 necessary. The flag PAGE_WRITE_ORG is positionned automatically
1997 depending on PAGE_WRITE */
pbrook53a59602006-03-25 19:31:22 +00001998void page_set_flags(target_ulong start, target_ulong end, int flags)
bellard9fa3e852004-01-04 18:06:42 +00001999{
2000 PageDesc *p;
pbrook53a59602006-03-25 19:31:22 +00002001 target_ulong addr;
bellard9fa3e852004-01-04 18:06:42 +00002002
pbrookc8a706f2008-06-02 16:16:42 +00002003 /* mmap_lock should already be held. */
bellard9fa3e852004-01-04 18:06:42 +00002004 start = start & TARGET_PAGE_MASK;
2005 end = TARGET_PAGE_ALIGN(end);
2006 if (flags & PAGE_WRITE)
2007 flags |= PAGE_WRITE_ORG;
bellard9fa3e852004-01-04 18:06:42 +00002008 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2009 p = page_find_alloc(addr >> TARGET_PAGE_BITS);
pbrook17e23772008-06-09 13:47:45 +00002010 /* We may be called for host regions that are outside guest
2011 address space. */
2012 if (!p)
2013 return;
bellard9fa3e852004-01-04 18:06:42 +00002014 /* if the write protection is set, then we invalidate the code
2015 inside */
ths5fafdf22007-09-16 21:08:06 +00002016 if (!(p->flags & PAGE_WRITE) &&
bellard9fa3e852004-01-04 18:06:42 +00002017 (flags & PAGE_WRITE) &&
2018 p->first_tb) {
bellardd720b932004-04-25 17:57:43 +00002019 tb_invalidate_phys_page(addr, 0, NULL);
bellard9fa3e852004-01-04 18:06:42 +00002020 }
2021 p->flags = flags;
2022 }
bellard9fa3e852004-01-04 18:06:42 +00002023}
2024
ths3d97b402007-11-02 19:02:07 +00002025int page_check_range(target_ulong start, target_ulong len, int flags)
2026{
2027 PageDesc *p;
2028 target_ulong end;
2029 target_ulong addr;
2030
2031 end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
2032 start = start & TARGET_PAGE_MASK;
2033
2034 if( end < start )
2035 /* we've wrapped around */
2036 return -1;
2037 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2038 p = page_find(addr >> TARGET_PAGE_BITS);
2039 if( !p )
2040 return -1;
2041 if( !(p->flags & PAGE_VALID) )
2042 return -1;
2043
bellarddae32702007-11-14 10:51:00 +00002044 if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
ths3d97b402007-11-02 19:02:07 +00002045 return -1;
bellarddae32702007-11-14 10:51:00 +00002046 if (flags & PAGE_WRITE) {
2047 if (!(p->flags & PAGE_WRITE_ORG))
2048 return -1;
2049 /* unprotect the page if it was put read-only because it
2050 contains translated code */
2051 if (!(p->flags & PAGE_WRITE)) {
2052 if (!page_unprotect(addr, 0, NULL))
2053 return -1;
2054 }
2055 return 0;
2056 }
ths3d97b402007-11-02 19:02:07 +00002057 }
2058 return 0;
2059}
2060
bellard9fa3e852004-01-04 18:06:42 +00002061/* called from signal handler: invalidate the code and unprotect the
2062 page. Return TRUE if the fault was succesfully handled. */
pbrook53a59602006-03-25 19:31:22 +00002063int page_unprotect(target_ulong address, unsigned long pc, void *puc)
bellard9fa3e852004-01-04 18:06:42 +00002064{
2065 unsigned int page_index, prot, pindex;
2066 PageDesc *p, *p1;
pbrook53a59602006-03-25 19:31:22 +00002067 target_ulong host_start, host_end, addr;
bellard9fa3e852004-01-04 18:06:42 +00002068
pbrookc8a706f2008-06-02 16:16:42 +00002069 /* Technically this isn't safe inside a signal handler. However we
2070 know this only ever happens in a synchronous SEGV handler, so in
2071 practice it seems to be ok. */
2072 mmap_lock();
2073
bellard83fb7ad2004-07-05 21:25:26 +00002074 host_start = address & qemu_host_page_mask;
bellard9fa3e852004-01-04 18:06:42 +00002075 page_index = host_start >> TARGET_PAGE_BITS;
2076 p1 = page_find(page_index);
pbrookc8a706f2008-06-02 16:16:42 +00002077 if (!p1) {
2078 mmap_unlock();
bellard9fa3e852004-01-04 18:06:42 +00002079 return 0;
pbrookc8a706f2008-06-02 16:16:42 +00002080 }
bellard83fb7ad2004-07-05 21:25:26 +00002081 host_end = host_start + qemu_host_page_size;
bellard9fa3e852004-01-04 18:06:42 +00002082 p = p1;
2083 prot = 0;
2084 for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
2085 prot |= p->flags;
2086 p++;
2087 }
2088 /* if the page was really writable, then we change its
2089 protection back to writable */
2090 if (prot & PAGE_WRITE_ORG) {
2091 pindex = (address - host_start) >> TARGET_PAGE_BITS;
2092 if (!(p1[pindex].flags & PAGE_WRITE)) {
ths5fafdf22007-09-16 21:08:06 +00002093 mprotect((void *)g2h(host_start), qemu_host_page_size,
bellard9fa3e852004-01-04 18:06:42 +00002094 (prot & PAGE_BITS) | PAGE_WRITE);
2095 p1[pindex].flags |= PAGE_WRITE;
2096 /* and since the content will be modified, we must invalidate
2097 the corresponding translated code. */
bellardd720b932004-04-25 17:57:43 +00002098 tb_invalidate_phys_page(address, pc, puc);
bellard9fa3e852004-01-04 18:06:42 +00002099#ifdef DEBUG_TB_CHECK
2100 tb_invalidate_check(address);
2101#endif
pbrookc8a706f2008-06-02 16:16:42 +00002102 mmap_unlock();
bellard9fa3e852004-01-04 18:06:42 +00002103 return 1;
2104 }
2105 }
pbrookc8a706f2008-06-02 16:16:42 +00002106 mmap_unlock();
bellard9fa3e852004-01-04 18:06:42 +00002107 return 0;
2108}
2109
bellard6a00d602005-11-21 23:25:50 +00002110static inline void tlb_set_dirty(CPUState *env,
2111 unsigned long addr, target_ulong vaddr)
bellard1ccde1c2004-02-06 19:46:14 +00002112{
2113}
bellard9fa3e852004-01-04 18:06:42 +00002114#endif /* defined(CONFIG_USER_ONLY) */
2115
pbrooke2eef172008-06-08 01:09:01 +00002116#if !defined(CONFIG_USER_ONLY)
blueswir1db7b5422007-05-26 17:36:03 +00002117static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
aurel3200f82b82008-04-27 21:12:55 +00002118 ram_addr_t memory);
2119static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
2120 ram_addr_t orig_memory);
blueswir1db7b5422007-05-26 17:36:03 +00002121#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
2122 need_subpage) \
2123 do { \
2124 if (addr > start_addr) \
2125 start_addr2 = 0; \
2126 else { \
2127 start_addr2 = start_addr & ~TARGET_PAGE_MASK; \
2128 if (start_addr2 > 0) \
2129 need_subpage = 1; \
2130 } \
2131 \
blueswir149e9fba2007-05-30 17:25:06 +00002132 if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE) \
blueswir1db7b5422007-05-26 17:36:03 +00002133 end_addr2 = TARGET_PAGE_SIZE - 1; \
2134 else { \
2135 end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
2136 if (end_addr2 < TARGET_PAGE_SIZE - 1) \
2137 need_subpage = 1; \
2138 } \
2139 } while (0)
2140
bellard33417e72003-08-10 21:47:01 +00002141/* register physical memory. 'size' must be a multiple of the target
2142 page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
2143 io memory page */
ths5fafdf22007-09-16 21:08:06 +00002144void cpu_register_physical_memory(target_phys_addr_t start_addr,
aurel3200f82b82008-04-27 21:12:55 +00002145 ram_addr_t size,
2146 ram_addr_t phys_offset)
bellard33417e72003-08-10 21:47:01 +00002147{
bellard108c49b2005-07-24 12:55:09 +00002148 target_phys_addr_t addr, end_addr;
bellard92e873b2004-05-21 14:52:29 +00002149 PhysPageDesc *p;
bellard9d420372006-06-25 22:25:22 +00002150 CPUState *env;
aurel3200f82b82008-04-27 21:12:55 +00002151 ram_addr_t orig_size = size;
blueswir1db7b5422007-05-26 17:36:03 +00002152 void *subpage;
bellard33417e72003-08-10 21:47:01 +00002153
bellardda260242008-05-30 20:48:25 +00002154#ifdef USE_KQEMU
2155 /* XXX: should not depend on cpu context */
2156 env = first_cpu;
2157 if (env->kqemu_enabled) {
2158 kqemu_set_phys_mem(start_addr, size, phys_offset);
2159 }
2160#endif
bellard5fd386f2004-05-23 21:11:22 +00002161 size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
blueswir149e9fba2007-05-30 17:25:06 +00002162 end_addr = start_addr + (target_phys_addr_t)size;
2163 for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
blueswir1db7b5422007-05-26 17:36:03 +00002164 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2165 if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
aurel3200f82b82008-04-27 21:12:55 +00002166 ram_addr_t orig_memory = p->phys_offset;
blueswir1db7b5422007-05-26 17:36:03 +00002167 target_phys_addr_t start_addr2, end_addr2;
2168 int need_subpage = 0;
2169
2170 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2171 need_subpage);
blueswir14254fab2008-01-01 16:57:19 +00002172 if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
blueswir1db7b5422007-05-26 17:36:03 +00002173 if (!(orig_memory & IO_MEM_SUBPAGE)) {
2174 subpage = subpage_init((addr & TARGET_PAGE_MASK),
2175 &p->phys_offset, orig_memory);
2176 } else {
2177 subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
2178 >> IO_MEM_SHIFT];
2179 }
2180 subpage_register(subpage, start_addr2, end_addr2, phys_offset);
2181 } else {
2182 p->phys_offset = phys_offset;
2183 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2184 (phys_offset & IO_MEM_ROMD))
2185 phys_offset += TARGET_PAGE_SIZE;
2186 }
2187 } else {
2188 p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2189 p->phys_offset = phys_offset;
2190 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2191 (phys_offset & IO_MEM_ROMD))
2192 phys_offset += TARGET_PAGE_SIZE;
2193 else {
2194 target_phys_addr_t start_addr2, end_addr2;
2195 int need_subpage = 0;
2196
2197 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2198 end_addr2, need_subpage);
2199
blueswir14254fab2008-01-01 16:57:19 +00002200 if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
blueswir1db7b5422007-05-26 17:36:03 +00002201 subpage = subpage_init((addr & TARGET_PAGE_MASK),
2202 &p->phys_offset, IO_MEM_UNASSIGNED);
2203 subpage_register(subpage, start_addr2, end_addr2,
2204 phys_offset);
2205 }
2206 }
2207 }
bellard33417e72003-08-10 21:47:01 +00002208 }
ths3b46e622007-09-17 08:09:54 +00002209
bellard9d420372006-06-25 22:25:22 +00002210 /* since each CPU stores ram addresses in its TLB cache, we must
2211 reset the modified entries */
2212 /* XXX: slow ! */
2213 for(env = first_cpu; env != NULL; env = env->next_cpu) {
2214 tlb_flush(env, 1);
2215 }
bellard33417e72003-08-10 21:47:01 +00002216}
2217
bellardba863452006-09-24 18:41:10 +00002218/* XXX: temporary until new memory mapping API */
aurel3200f82b82008-04-27 21:12:55 +00002219ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr)
bellardba863452006-09-24 18:41:10 +00002220{
2221 PhysPageDesc *p;
2222
2223 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2224 if (!p)
2225 return IO_MEM_UNASSIGNED;
2226 return p->phys_offset;
2227}
2228
bellarde9a1ab12007-02-08 23:08:38 +00002229/* XXX: better than nothing */
aurel3200f82b82008-04-27 21:12:55 +00002230ram_addr_t qemu_ram_alloc(ram_addr_t size)
bellarde9a1ab12007-02-08 23:08:38 +00002231{
2232 ram_addr_t addr;
balrog7fb4fdc2008-04-24 17:59:27 +00002233 if ((phys_ram_alloc_offset + size) > phys_ram_size) {
bellarded441462008-05-23 11:56:45 +00002234 fprintf(stderr, "Not enough memory (requested_size = %" PRIu64 ", max memory = %" PRIu64 "\n",
2235 (uint64_t)size, (uint64_t)phys_ram_size);
bellarde9a1ab12007-02-08 23:08:38 +00002236 abort();
2237 }
2238 addr = phys_ram_alloc_offset;
2239 phys_ram_alloc_offset = TARGET_PAGE_ALIGN(phys_ram_alloc_offset + size);
2240 return addr;
2241}
2242
2243void qemu_ram_free(ram_addr_t addr)
2244{
2245}
2246
bellarda4193c82004-06-03 14:01:43 +00002247static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
bellard33417e72003-08-10 21:47:01 +00002248{
pbrook67d3b952006-12-18 05:03:52 +00002249#ifdef DEBUG_UNASSIGNED
blueswir1ab3d1722007-11-04 07:31:40 +00002250 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
pbrook67d3b952006-12-18 05:03:52 +00002251#endif
blueswir1b4f0a312007-05-06 17:59:24 +00002252#ifdef TARGET_SPARC
blueswir16c36d3f2007-05-17 19:30:10 +00002253 do_unassigned_access(addr, 0, 0, 0);
thsf1ccf902007-10-08 13:16:14 +00002254#elif TARGET_CRIS
2255 do_unassigned_access(addr, 0, 0, 0);
blueswir1b4f0a312007-05-06 17:59:24 +00002256#endif
bellard33417e72003-08-10 21:47:01 +00002257 return 0;
2258}
2259
bellarda4193c82004-06-03 14:01:43 +00002260static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
bellard33417e72003-08-10 21:47:01 +00002261{
pbrook67d3b952006-12-18 05:03:52 +00002262#ifdef DEBUG_UNASSIGNED
blueswir1ab3d1722007-11-04 07:31:40 +00002263 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
pbrook67d3b952006-12-18 05:03:52 +00002264#endif
blueswir1b4f0a312007-05-06 17:59:24 +00002265#ifdef TARGET_SPARC
blueswir16c36d3f2007-05-17 19:30:10 +00002266 do_unassigned_access(addr, 1, 0, 0);
thsf1ccf902007-10-08 13:16:14 +00002267#elif TARGET_CRIS
2268 do_unassigned_access(addr, 1, 0, 0);
blueswir1b4f0a312007-05-06 17:59:24 +00002269#endif
bellard33417e72003-08-10 21:47:01 +00002270}
2271
2272static CPUReadMemoryFunc *unassigned_mem_read[3] = {
2273 unassigned_mem_readb,
2274 unassigned_mem_readb,
2275 unassigned_mem_readb,
2276};
2277
2278static CPUWriteMemoryFunc *unassigned_mem_write[3] = {
2279 unassigned_mem_writeb,
2280 unassigned_mem_writeb,
2281 unassigned_mem_writeb,
2282};
2283
pbrook0f459d12008-06-09 00:20:13 +00002284static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr,
2285 uint32_t val)
bellard1ccde1c2004-02-06 19:46:14 +00002286{
bellard3a7d9292005-08-21 09:26:42 +00002287 int dirty_flags;
bellard3a7d9292005-08-21 09:26:42 +00002288 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2289 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2290#if !defined(CONFIG_USER_ONLY)
2291 tb_invalidate_phys_page_fast(ram_addr, 1);
2292 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2293#endif
2294 }
pbrook0f459d12008-06-09 00:20:13 +00002295 stb_p(phys_ram_base + ram_addr, val);
bellardf32fc642006-02-08 22:43:39 +00002296#ifdef USE_KQEMU
2297 if (cpu_single_env->kqemu_enabled &&
2298 (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2299 kqemu_modify_page(cpu_single_env, ram_addr);
2300#endif
bellardf23db162005-08-21 19:12:28 +00002301 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2302 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2303 /* we remove the notdirty callback only if the code has been
2304 flushed */
2305 if (dirty_flags == 0xff)
pbrook2e70f6e2008-06-29 01:03:05 +00002306 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
bellard1ccde1c2004-02-06 19:46:14 +00002307}
2308
pbrook0f459d12008-06-09 00:20:13 +00002309static void notdirty_mem_writew(void *opaque, target_phys_addr_t ram_addr,
2310 uint32_t val)
bellard1ccde1c2004-02-06 19:46:14 +00002311{
bellard3a7d9292005-08-21 09:26:42 +00002312 int dirty_flags;
bellard3a7d9292005-08-21 09:26:42 +00002313 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2314 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2315#if !defined(CONFIG_USER_ONLY)
2316 tb_invalidate_phys_page_fast(ram_addr, 2);
2317 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2318#endif
2319 }
pbrook0f459d12008-06-09 00:20:13 +00002320 stw_p(phys_ram_base + ram_addr, val);
bellardf32fc642006-02-08 22:43:39 +00002321#ifdef USE_KQEMU
2322 if (cpu_single_env->kqemu_enabled &&
2323 (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2324 kqemu_modify_page(cpu_single_env, ram_addr);
2325#endif
bellardf23db162005-08-21 19:12:28 +00002326 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2327 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2328 /* we remove the notdirty callback only if the code has been
2329 flushed */
2330 if (dirty_flags == 0xff)
pbrook2e70f6e2008-06-29 01:03:05 +00002331 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
bellard1ccde1c2004-02-06 19:46:14 +00002332}
2333
pbrook0f459d12008-06-09 00:20:13 +00002334static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr,
2335 uint32_t val)
bellard1ccde1c2004-02-06 19:46:14 +00002336{
bellard3a7d9292005-08-21 09:26:42 +00002337 int dirty_flags;
bellard3a7d9292005-08-21 09:26:42 +00002338 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2339 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2340#if !defined(CONFIG_USER_ONLY)
2341 tb_invalidate_phys_page_fast(ram_addr, 4);
2342 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2343#endif
2344 }
pbrook0f459d12008-06-09 00:20:13 +00002345 stl_p(phys_ram_base + ram_addr, val);
bellardf32fc642006-02-08 22:43:39 +00002346#ifdef USE_KQEMU
2347 if (cpu_single_env->kqemu_enabled &&
2348 (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2349 kqemu_modify_page(cpu_single_env, ram_addr);
2350#endif
bellardf23db162005-08-21 19:12:28 +00002351 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2352 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2353 /* we remove the notdirty callback only if the code has been
2354 flushed */
2355 if (dirty_flags == 0xff)
pbrook2e70f6e2008-06-29 01:03:05 +00002356 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
bellard1ccde1c2004-02-06 19:46:14 +00002357}
2358
bellard3a7d9292005-08-21 09:26:42 +00002359static CPUReadMemoryFunc *error_mem_read[3] = {
2360 NULL, /* never used */
2361 NULL, /* never used */
2362 NULL, /* never used */
2363};
2364
bellard1ccde1c2004-02-06 19:46:14 +00002365static CPUWriteMemoryFunc *notdirty_mem_write[3] = {
2366 notdirty_mem_writeb,
2367 notdirty_mem_writew,
2368 notdirty_mem_writel,
2369};
2370
pbrook0f459d12008-06-09 00:20:13 +00002371/* Generate a debug exception if a watchpoint has been hit. */
2372static void check_watchpoint(int offset, int flags)
2373{
2374 CPUState *env = cpu_single_env;
2375 target_ulong vaddr;
2376 int i;
2377
pbrook2e70f6e2008-06-29 01:03:05 +00002378 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
pbrook0f459d12008-06-09 00:20:13 +00002379 for (i = 0; i < env->nb_watchpoints; i++) {
2380 if (vaddr == env->watchpoint[i].vaddr
2381 && (env->watchpoint[i].type & flags)) {
2382 env->watchpoint_hit = i + 1;
2383 cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2384 break;
2385 }
2386 }
2387}
2388
pbrook6658ffb2007-03-16 23:58:11 +00002389/* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
2390 so these check for a hit then pass through to the normal out-of-line
2391 phys routines. */
2392static uint32_t watch_mem_readb(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 ldub_phys(addr);
2396}
2397
2398static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
2399{
pbrook0f459d12008-06-09 00:20:13 +00002400 check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ);
pbrook6658ffb2007-03-16 23:58:11 +00002401 return lduw_phys(addr);
2402}
2403
2404static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
2405{
pbrook0f459d12008-06-09 00:20:13 +00002406 check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ);
pbrook6658ffb2007-03-16 23:58:11 +00002407 return ldl_phys(addr);
2408}
2409
pbrook6658ffb2007-03-16 23:58:11 +00002410static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
2411 uint32_t val)
2412{
pbrook0f459d12008-06-09 00:20:13 +00002413 check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE);
pbrook6658ffb2007-03-16 23:58:11 +00002414 stb_phys(addr, val);
2415}
2416
2417static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
2418 uint32_t val)
2419{
pbrook0f459d12008-06-09 00:20:13 +00002420 check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE);
pbrook6658ffb2007-03-16 23:58:11 +00002421 stw_phys(addr, val);
2422}
2423
2424static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
2425 uint32_t val)
2426{
pbrook0f459d12008-06-09 00:20:13 +00002427 check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE);
pbrook6658ffb2007-03-16 23:58:11 +00002428 stl_phys(addr, val);
2429}
2430
2431static CPUReadMemoryFunc *watch_mem_read[3] = {
2432 watch_mem_readb,
2433 watch_mem_readw,
2434 watch_mem_readl,
2435};
2436
2437static CPUWriteMemoryFunc *watch_mem_write[3] = {
2438 watch_mem_writeb,
2439 watch_mem_writew,
2440 watch_mem_writel,
2441};
pbrook6658ffb2007-03-16 23:58:11 +00002442
blueswir1db7b5422007-05-26 17:36:03 +00002443static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr,
2444 unsigned int len)
2445{
blueswir1db7b5422007-05-26 17:36:03 +00002446 uint32_t ret;
2447 unsigned int idx;
2448
2449 idx = SUBPAGE_IDX(addr - mmio->base);
2450#if defined(DEBUG_SUBPAGE)
2451 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
2452 mmio, len, addr, idx);
2453#endif
blueswir13ee89922008-01-02 19:45:26 +00002454 ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len], addr);
blueswir1db7b5422007-05-26 17:36:03 +00002455
2456 return ret;
2457}
2458
2459static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
2460 uint32_t value, unsigned int len)
2461{
blueswir1db7b5422007-05-26 17:36:03 +00002462 unsigned int idx;
2463
2464 idx = SUBPAGE_IDX(addr - mmio->base);
2465#if defined(DEBUG_SUBPAGE)
2466 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
2467 mmio, len, addr, idx, value);
2468#endif
blueswir13ee89922008-01-02 19:45:26 +00002469 (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len], addr, value);
blueswir1db7b5422007-05-26 17:36:03 +00002470}
2471
2472static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
2473{
2474#if defined(DEBUG_SUBPAGE)
2475 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2476#endif
2477
2478 return subpage_readlen(opaque, addr, 0);
2479}
2480
2481static void subpage_writeb (void *opaque, target_phys_addr_t addr,
2482 uint32_t value)
2483{
2484#if defined(DEBUG_SUBPAGE)
2485 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2486#endif
2487 subpage_writelen(opaque, addr, value, 0);
2488}
2489
2490static uint32_t subpage_readw (void *opaque, target_phys_addr_t addr)
2491{
2492#if defined(DEBUG_SUBPAGE)
2493 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2494#endif
2495
2496 return subpage_readlen(opaque, addr, 1);
2497}
2498
2499static void subpage_writew (void *opaque, target_phys_addr_t addr,
2500 uint32_t value)
2501{
2502#if defined(DEBUG_SUBPAGE)
2503 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2504#endif
2505 subpage_writelen(opaque, addr, value, 1);
2506}
2507
2508static uint32_t subpage_readl (void *opaque, target_phys_addr_t addr)
2509{
2510#if defined(DEBUG_SUBPAGE)
2511 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2512#endif
2513
2514 return subpage_readlen(opaque, addr, 2);
2515}
2516
2517static void subpage_writel (void *opaque,
2518 target_phys_addr_t addr, uint32_t value)
2519{
2520#if defined(DEBUG_SUBPAGE)
2521 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2522#endif
2523 subpage_writelen(opaque, addr, value, 2);
2524}
2525
2526static CPUReadMemoryFunc *subpage_read[] = {
2527 &subpage_readb,
2528 &subpage_readw,
2529 &subpage_readl,
2530};
2531
2532static CPUWriteMemoryFunc *subpage_write[] = {
2533 &subpage_writeb,
2534 &subpage_writew,
2535 &subpage_writel,
2536};
2537
2538static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
aurel3200f82b82008-04-27 21:12:55 +00002539 ram_addr_t memory)
blueswir1db7b5422007-05-26 17:36:03 +00002540{
2541 int idx, eidx;
blueswir14254fab2008-01-01 16:57:19 +00002542 unsigned int i;
blueswir1db7b5422007-05-26 17:36:03 +00002543
2544 if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
2545 return -1;
2546 idx = SUBPAGE_IDX(start);
2547 eidx = SUBPAGE_IDX(end);
2548#if defined(DEBUG_SUBPAGE)
2549 printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %d\n", __func__,
2550 mmio, start, end, idx, eidx, memory);
2551#endif
2552 memory >>= IO_MEM_SHIFT;
2553 for (; idx <= eidx; idx++) {
blueswir14254fab2008-01-01 16:57:19 +00002554 for (i = 0; i < 4; i++) {
blueswir13ee89922008-01-02 19:45:26 +00002555 if (io_mem_read[memory][i]) {
2556 mmio->mem_read[idx][i] = &io_mem_read[memory][i];
2557 mmio->opaque[idx][0][i] = io_mem_opaque[memory];
2558 }
2559 if (io_mem_write[memory][i]) {
2560 mmio->mem_write[idx][i] = &io_mem_write[memory][i];
2561 mmio->opaque[idx][1][i] = io_mem_opaque[memory];
2562 }
blueswir14254fab2008-01-01 16:57:19 +00002563 }
blueswir1db7b5422007-05-26 17:36:03 +00002564 }
2565
2566 return 0;
2567}
2568
aurel3200f82b82008-04-27 21:12:55 +00002569static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
2570 ram_addr_t orig_memory)
blueswir1db7b5422007-05-26 17:36:03 +00002571{
2572 subpage_t *mmio;
2573 int subpage_memory;
2574
2575 mmio = qemu_mallocz(sizeof(subpage_t));
2576 if (mmio != NULL) {
2577 mmio->base = base;
2578 subpage_memory = cpu_register_io_memory(0, subpage_read, subpage_write, mmio);
2579#if defined(DEBUG_SUBPAGE)
2580 printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
2581 mmio, base, TARGET_PAGE_SIZE, subpage_memory);
2582#endif
2583 *phys = subpage_memory | IO_MEM_SUBPAGE;
2584 subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory);
2585 }
2586
2587 return mmio;
2588}
2589
bellard33417e72003-08-10 21:47:01 +00002590static void io_mem_init(void)
2591{
bellard3a7d9292005-08-21 09:26:42 +00002592 cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read, unassigned_mem_write, NULL);
bellarda4193c82004-06-03 14:01:43 +00002593 cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write, NULL);
bellard3a7d9292005-08-21 09:26:42 +00002594 cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read, notdirty_mem_write, NULL);
bellard1ccde1c2004-02-06 19:46:14 +00002595 io_mem_nb = 5;
2596
pbrook0f459d12008-06-09 00:20:13 +00002597 io_mem_watch = cpu_register_io_memory(0, watch_mem_read,
pbrook6658ffb2007-03-16 23:58:11 +00002598 watch_mem_write, NULL);
bellard1ccde1c2004-02-06 19:46:14 +00002599 /* alloc dirty bits array */
bellard0a962c02005-02-10 22:00:27 +00002600 phys_ram_dirty = qemu_vmalloc(phys_ram_size >> TARGET_PAGE_BITS);
bellard3a7d9292005-08-21 09:26:42 +00002601 memset(phys_ram_dirty, 0xff, phys_ram_size >> TARGET_PAGE_BITS);
bellard33417e72003-08-10 21:47:01 +00002602}
2603
2604/* mem_read and mem_write are arrays of functions containing the
2605 function to access byte (index 0), word (index 1) and dword (index
blueswir13ee89922008-01-02 19:45:26 +00002606 2). Functions can be omitted with a NULL function pointer. The
2607 registered functions may be modified dynamically later.
2608 If io_index is non zero, the corresponding io zone is
blueswir14254fab2008-01-01 16:57:19 +00002609 modified. If it is zero, a new io zone is allocated. The return
2610 value can be used with cpu_register_physical_memory(). (-1) is
2611 returned if error. */
bellard33417e72003-08-10 21:47:01 +00002612int cpu_register_io_memory(int io_index,
2613 CPUReadMemoryFunc **mem_read,
bellarda4193c82004-06-03 14:01:43 +00002614 CPUWriteMemoryFunc **mem_write,
2615 void *opaque)
bellard33417e72003-08-10 21:47:01 +00002616{
blueswir14254fab2008-01-01 16:57:19 +00002617 int i, subwidth = 0;
bellard33417e72003-08-10 21:47:01 +00002618
2619 if (io_index <= 0) {
bellardb5ff1b32005-11-26 10:38:39 +00002620 if (io_mem_nb >= IO_MEM_NB_ENTRIES)
bellard33417e72003-08-10 21:47:01 +00002621 return -1;
2622 io_index = io_mem_nb++;
2623 } else {
2624 if (io_index >= IO_MEM_NB_ENTRIES)
2625 return -1;
2626 }
bellardb5ff1b32005-11-26 10:38:39 +00002627
bellard33417e72003-08-10 21:47:01 +00002628 for(i = 0;i < 3; i++) {
blueswir14254fab2008-01-01 16:57:19 +00002629 if (!mem_read[i] || !mem_write[i])
2630 subwidth = IO_MEM_SUBWIDTH;
bellard33417e72003-08-10 21:47:01 +00002631 io_mem_read[io_index][i] = mem_read[i];
2632 io_mem_write[io_index][i] = mem_write[i];
2633 }
bellarda4193c82004-06-03 14:01:43 +00002634 io_mem_opaque[io_index] = opaque;
blueswir14254fab2008-01-01 16:57:19 +00002635 return (io_index << IO_MEM_SHIFT) | subwidth;
bellard33417e72003-08-10 21:47:01 +00002636}
bellard61382a52003-10-27 21:22:23 +00002637
bellard8926b512004-10-10 15:14:20 +00002638CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index)
2639{
2640 return io_mem_write[io_index >> IO_MEM_SHIFT];
2641}
2642
2643CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index)
2644{
2645 return io_mem_read[io_index >> IO_MEM_SHIFT];
2646}
2647
pbrooke2eef172008-06-08 01:09:01 +00002648#endif /* !defined(CONFIG_USER_ONLY) */
2649
bellard13eb76e2004-01-24 15:23:36 +00002650/* physical memory access (slow version, mainly for debug) */
2651#if defined(CONFIG_USER_ONLY)
ths5fafdf22007-09-16 21:08:06 +00002652void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
bellard13eb76e2004-01-24 15:23:36 +00002653 int len, int is_write)
2654{
2655 int l, flags;
2656 target_ulong page;
pbrook53a59602006-03-25 19:31:22 +00002657 void * p;
bellard13eb76e2004-01-24 15:23:36 +00002658
2659 while (len > 0) {
2660 page = addr & TARGET_PAGE_MASK;
2661 l = (page + TARGET_PAGE_SIZE) - addr;
2662 if (l > len)
2663 l = len;
2664 flags = page_get_flags(page);
2665 if (!(flags & PAGE_VALID))
2666 return;
2667 if (is_write) {
2668 if (!(flags & PAGE_WRITE))
2669 return;
bellard579a97f2007-11-11 14:26:47 +00002670 /* XXX: this code should not depend on lock_user */
aurel3272fb7da2008-04-27 23:53:45 +00002671 if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
bellard579a97f2007-11-11 14:26:47 +00002672 /* FIXME - should this return an error rather than just fail? */
2673 return;
aurel3272fb7da2008-04-27 23:53:45 +00002674 memcpy(p, buf, l);
2675 unlock_user(p, addr, l);
bellard13eb76e2004-01-24 15:23:36 +00002676 } else {
2677 if (!(flags & PAGE_READ))
2678 return;
bellard579a97f2007-11-11 14:26:47 +00002679 /* XXX: this code should not depend on lock_user */
aurel3272fb7da2008-04-27 23:53:45 +00002680 if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
bellard579a97f2007-11-11 14:26:47 +00002681 /* FIXME - should this return an error rather than just fail? */
2682 return;
aurel3272fb7da2008-04-27 23:53:45 +00002683 memcpy(buf, p, l);
aurel325b257572008-04-28 08:54:59 +00002684 unlock_user(p, addr, 0);
bellard13eb76e2004-01-24 15:23:36 +00002685 }
2686 len -= l;
2687 buf += l;
2688 addr += l;
2689 }
2690}
bellard8df1cd02005-01-28 22:37:22 +00002691
bellard13eb76e2004-01-24 15:23:36 +00002692#else
ths5fafdf22007-09-16 21:08:06 +00002693void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
bellard13eb76e2004-01-24 15:23:36 +00002694 int len, int is_write)
2695{
2696 int l, io_index;
2697 uint8_t *ptr;
2698 uint32_t val;
bellard2e126692004-04-25 21:28:44 +00002699 target_phys_addr_t page;
2700 unsigned long pd;
bellard92e873b2004-05-21 14:52:29 +00002701 PhysPageDesc *p;
ths3b46e622007-09-17 08:09:54 +00002702
bellard13eb76e2004-01-24 15:23:36 +00002703 while (len > 0) {
2704 page = addr & TARGET_PAGE_MASK;
2705 l = (page + TARGET_PAGE_SIZE) - addr;
2706 if (l > len)
2707 l = len;
bellard92e873b2004-05-21 14:52:29 +00002708 p = phys_page_find(page >> TARGET_PAGE_BITS);
bellard13eb76e2004-01-24 15:23:36 +00002709 if (!p) {
2710 pd = IO_MEM_UNASSIGNED;
2711 } else {
2712 pd = p->phys_offset;
2713 }
ths3b46e622007-09-17 08:09:54 +00002714
bellard13eb76e2004-01-24 15:23:36 +00002715 if (is_write) {
bellard3a7d9292005-08-21 09:26:42 +00002716 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
bellard13eb76e2004-01-24 15:23:36 +00002717 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
bellard6a00d602005-11-21 23:25:50 +00002718 /* XXX: could force cpu_single_env to NULL to avoid
2719 potential bugs */
bellard13eb76e2004-01-24 15:23:36 +00002720 if (l >= 4 && ((addr & 3) == 0)) {
bellard1c213d12005-09-03 10:49:04 +00002721 /* 32 bit write access */
bellardc27004e2005-01-03 23:35:10 +00002722 val = ldl_p(buf);
bellarda4193c82004-06-03 14:01:43 +00002723 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
bellard13eb76e2004-01-24 15:23:36 +00002724 l = 4;
2725 } else if (l >= 2 && ((addr & 1) == 0)) {
bellard1c213d12005-09-03 10:49:04 +00002726 /* 16 bit write access */
bellardc27004e2005-01-03 23:35:10 +00002727 val = lduw_p(buf);
bellarda4193c82004-06-03 14:01:43 +00002728 io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
bellard13eb76e2004-01-24 15:23:36 +00002729 l = 2;
2730 } else {
bellard1c213d12005-09-03 10:49:04 +00002731 /* 8 bit write access */
bellardc27004e2005-01-03 23:35:10 +00002732 val = ldub_p(buf);
bellarda4193c82004-06-03 14:01:43 +00002733 io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val);
bellard13eb76e2004-01-24 15:23:36 +00002734 l = 1;
2735 }
2736 } else {
bellardb448f2f2004-02-25 23:24:04 +00002737 unsigned long addr1;
2738 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
bellard13eb76e2004-01-24 15:23:36 +00002739 /* RAM case */
bellardb448f2f2004-02-25 23:24:04 +00002740 ptr = phys_ram_base + addr1;
bellard13eb76e2004-01-24 15:23:36 +00002741 memcpy(ptr, buf, l);
bellard3a7d9292005-08-21 09:26:42 +00002742 if (!cpu_physical_memory_is_dirty(addr1)) {
2743 /* invalidate code */
2744 tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
2745 /* set dirty bit */
ths5fafdf22007-09-16 21:08:06 +00002746 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
bellardf23db162005-08-21 19:12:28 +00002747 (0xff & ~CODE_DIRTY_FLAG);
bellard3a7d9292005-08-21 09:26:42 +00002748 }
bellard13eb76e2004-01-24 15:23:36 +00002749 }
2750 } else {
ths5fafdf22007-09-16 21:08:06 +00002751 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
bellard2a4188a2006-06-25 21:54:59 +00002752 !(pd & IO_MEM_ROMD)) {
bellard13eb76e2004-01-24 15:23:36 +00002753 /* I/O case */
2754 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2755 if (l >= 4 && ((addr & 3) == 0)) {
2756 /* 32 bit read access */
bellarda4193c82004-06-03 14:01:43 +00002757 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
bellardc27004e2005-01-03 23:35:10 +00002758 stl_p(buf, val);
bellard13eb76e2004-01-24 15:23:36 +00002759 l = 4;
2760 } else if (l >= 2 && ((addr & 1) == 0)) {
2761 /* 16 bit read access */
bellarda4193c82004-06-03 14:01:43 +00002762 val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
bellardc27004e2005-01-03 23:35:10 +00002763 stw_p(buf, val);
bellard13eb76e2004-01-24 15:23:36 +00002764 l = 2;
2765 } else {
bellard1c213d12005-09-03 10:49:04 +00002766 /* 8 bit read access */
bellarda4193c82004-06-03 14:01:43 +00002767 val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr);
bellardc27004e2005-01-03 23:35:10 +00002768 stb_p(buf, val);
bellard13eb76e2004-01-24 15:23:36 +00002769 l = 1;
2770 }
2771 } else {
2772 /* RAM case */
ths5fafdf22007-09-16 21:08:06 +00002773 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
bellard13eb76e2004-01-24 15:23:36 +00002774 (addr & ~TARGET_PAGE_MASK);
2775 memcpy(buf, ptr, l);
2776 }
2777 }
2778 len -= l;
2779 buf += l;
2780 addr += l;
2781 }
2782}
bellard8df1cd02005-01-28 22:37:22 +00002783
bellardd0ecd2a2006-04-23 17:14:48 +00002784/* used for ROM loading : can write in RAM and ROM */
ths5fafdf22007-09-16 21:08:06 +00002785void cpu_physical_memory_write_rom(target_phys_addr_t addr,
bellardd0ecd2a2006-04-23 17:14:48 +00002786 const uint8_t *buf, int len)
2787{
2788 int l;
2789 uint8_t *ptr;
2790 target_phys_addr_t page;
2791 unsigned long pd;
2792 PhysPageDesc *p;
ths3b46e622007-09-17 08:09:54 +00002793
bellardd0ecd2a2006-04-23 17:14:48 +00002794 while (len > 0) {
2795 page = addr & TARGET_PAGE_MASK;
2796 l = (page + TARGET_PAGE_SIZE) - addr;
2797 if (l > len)
2798 l = len;
2799 p = phys_page_find(page >> TARGET_PAGE_BITS);
2800 if (!p) {
2801 pd = IO_MEM_UNASSIGNED;
2802 } else {
2803 pd = p->phys_offset;
2804 }
ths3b46e622007-09-17 08:09:54 +00002805
bellardd0ecd2a2006-04-23 17:14:48 +00002806 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
bellard2a4188a2006-06-25 21:54:59 +00002807 (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
2808 !(pd & IO_MEM_ROMD)) {
bellardd0ecd2a2006-04-23 17:14:48 +00002809 /* do nothing */
2810 } else {
2811 unsigned long addr1;
2812 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2813 /* ROM/RAM case */
2814 ptr = phys_ram_base + addr1;
2815 memcpy(ptr, buf, l);
2816 }
2817 len -= l;
2818 buf += l;
2819 addr += l;
2820 }
2821}
2822
2823
bellard8df1cd02005-01-28 22:37:22 +00002824/* warning: addr must be aligned */
2825uint32_t ldl_phys(target_phys_addr_t addr)
2826{
2827 int io_index;
2828 uint8_t *ptr;
2829 uint32_t val;
2830 unsigned long pd;
2831 PhysPageDesc *p;
2832
2833 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2834 if (!p) {
2835 pd = IO_MEM_UNASSIGNED;
2836 } else {
2837 pd = p->phys_offset;
2838 }
ths3b46e622007-09-17 08:09:54 +00002839
ths5fafdf22007-09-16 21:08:06 +00002840 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
bellard2a4188a2006-06-25 21:54:59 +00002841 !(pd & IO_MEM_ROMD)) {
bellard8df1cd02005-01-28 22:37:22 +00002842 /* I/O case */
2843 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2844 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2845 } else {
2846 /* RAM case */
ths5fafdf22007-09-16 21:08:06 +00002847 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
bellard8df1cd02005-01-28 22:37:22 +00002848 (addr & ~TARGET_PAGE_MASK);
2849 val = ldl_p(ptr);
2850 }
2851 return val;
2852}
2853
bellard84b7b8e2005-11-28 21:19:04 +00002854/* warning: addr must be aligned */
2855uint64_t ldq_phys(target_phys_addr_t addr)
2856{
2857 int io_index;
2858 uint8_t *ptr;
2859 uint64_t val;
2860 unsigned long pd;
2861 PhysPageDesc *p;
2862
2863 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2864 if (!p) {
2865 pd = IO_MEM_UNASSIGNED;
2866 } else {
2867 pd = p->phys_offset;
2868 }
ths3b46e622007-09-17 08:09:54 +00002869
bellard2a4188a2006-06-25 21:54:59 +00002870 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
2871 !(pd & IO_MEM_ROMD)) {
bellard84b7b8e2005-11-28 21:19:04 +00002872 /* I/O case */
2873 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2874#ifdef TARGET_WORDS_BIGENDIAN
2875 val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
2876 val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
2877#else
2878 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2879 val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
2880#endif
2881 } else {
2882 /* RAM case */
ths5fafdf22007-09-16 21:08:06 +00002883 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
bellard84b7b8e2005-11-28 21:19:04 +00002884 (addr & ~TARGET_PAGE_MASK);
2885 val = ldq_p(ptr);
2886 }
2887 return val;
2888}
2889
bellardaab33092005-10-30 20:48:42 +00002890/* XXX: optimize */
2891uint32_t ldub_phys(target_phys_addr_t addr)
2892{
2893 uint8_t val;
2894 cpu_physical_memory_read(addr, &val, 1);
2895 return val;
2896}
2897
2898/* XXX: optimize */
2899uint32_t lduw_phys(target_phys_addr_t addr)
2900{
2901 uint16_t val;
2902 cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
2903 return tswap16(val);
2904}
2905
bellard8df1cd02005-01-28 22:37:22 +00002906/* warning: addr must be aligned. The ram page is not masked as dirty
2907 and the code inside is not invalidated. It is useful if the dirty
2908 bits are used to track modified PTEs */
2909void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
2910{
2911 int io_index;
2912 uint8_t *ptr;
2913 unsigned long pd;
2914 PhysPageDesc *p;
2915
2916 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2917 if (!p) {
2918 pd = IO_MEM_UNASSIGNED;
2919 } else {
2920 pd = p->phys_offset;
2921 }
ths3b46e622007-09-17 08:09:54 +00002922
bellard3a7d9292005-08-21 09:26:42 +00002923 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
bellard8df1cd02005-01-28 22:37:22 +00002924 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2925 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2926 } else {
ths5fafdf22007-09-16 21:08:06 +00002927 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
bellard8df1cd02005-01-28 22:37:22 +00002928 (addr & ~TARGET_PAGE_MASK);
2929 stl_p(ptr, val);
2930 }
2931}
2932
j_mayerbc98a7e2007-04-04 07:55:12 +00002933void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
2934{
2935 int io_index;
2936 uint8_t *ptr;
2937 unsigned long pd;
2938 PhysPageDesc *p;
2939
2940 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2941 if (!p) {
2942 pd = IO_MEM_UNASSIGNED;
2943 } else {
2944 pd = p->phys_offset;
2945 }
ths3b46e622007-09-17 08:09:54 +00002946
j_mayerbc98a7e2007-04-04 07:55:12 +00002947 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2948 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2949#ifdef TARGET_WORDS_BIGENDIAN
2950 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
2951 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
2952#else
2953 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2954 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
2955#endif
2956 } else {
ths5fafdf22007-09-16 21:08:06 +00002957 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
j_mayerbc98a7e2007-04-04 07:55:12 +00002958 (addr & ~TARGET_PAGE_MASK);
2959 stq_p(ptr, val);
2960 }
2961}
2962
bellard8df1cd02005-01-28 22:37:22 +00002963/* warning: addr must be aligned */
bellard8df1cd02005-01-28 22:37:22 +00002964void stl_phys(target_phys_addr_t addr, uint32_t val)
2965{
2966 int io_index;
2967 uint8_t *ptr;
2968 unsigned long pd;
2969 PhysPageDesc *p;
2970
2971 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2972 if (!p) {
2973 pd = IO_MEM_UNASSIGNED;
2974 } else {
2975 pd = p->phys_offset;
2976 }
ths3b46e622007-09-17 08:09:54 +00002977
bellard3a7d9292005-08-21 09:26:42 +00002978 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
bellard8df1cd02005-01-28 22:37:22 +00002979 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2980 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2981 } else {
2982 unsigned long addr1;
2983 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2984 /* RAM case */
2985 ptr = phys_ram_base + addr1;
2986 stl_p(ptr, val);
bellard3a7d9292005-08-21 09:26:42 +00002987 if (!cpu_physical_memory_is_dirty(addr1)) {
2988 /* invalidate code */
2989 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
2990 /* set dirty bit */
bellardf23db162005-08-21 19:12:28 +00002991 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
2992 (0xff & ~CODE_DIRTY_FLAG);
bellard3a7d9292005-08-21 09:26:42 +00002993 }
bellard8df1cd02005-01-28 22:37:22 +00002994 }
2995}
2996
bellardaab33092005-10-30 20:48:42 +00002997/* XXX: optimize */
2998void stb_phys(target_phys_addr_t addr, uint32_t val)
2999{
3000 uint8_t v = val;
3001 cpu_physical_memory_write(addr, &v, 1);
3002}
3003
3004/* XXX: optimize */
3005void stw_phys(target_phys_addr_t addr, uint32_t val)
3006{
3007 uint16_t v = tswap16(val);
3008 cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
3009}
3010
3011/* XXX: optimize */
3012void stq_phys(target_phys_addr_t addr, uint64_t val)
3013{
3014 val = tswap64(val);
3015 cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
3016}
3017
bellard13eb76e2004-01-24 15:23:36 +00003018#endif
3019
3020/* virtual memory access for debug */
ths5fafdf22007-09-16 21:08:06 +00003021int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
bellardb448f2f2004-02-25 23:24:04 +00003022 uint8_t *buf, int len, int is_write)
bellard13eb76e2004-01-24 15:23:36 +00003023{
3024 int l;
j_mayer9b3c35e2007-04-07 11:21:28 +00003025 target_phys_addr_t phys_addr;
3026 target_ulong page;
bellard13eb76e2004-01-24 15:23:36 +00003027
3028 while (len > 0) {
3029 page = addr & TARGET_PAGE_MASK;
3030 phys_addr = cpu_get_phys_page_debug(env, page);
3031 /* if no physical page mapped, return an error */
3032 if (phys_addr == -1)
3033 return -1;
3034 l = (page + TARGET_PAGE_SIZE) - addr;
3035 if (l > len)
3036 l = len;
ths5fafdf22007-09-16 21:08:06 +00003037 cpu_physical_memory_rw(phys_addr + (addr & ~TARGET_PAGE_MASK),
bellardb448f2f2004-02-25 23:24:04 +00003038 buf, l, is_write);
bellard13eb76e2004-01-24 15:23:36 +00003039 len -= l;
3040 buf += l;
3041 addr += l;
3042 }
3043 return 0;
3044}
3045
pbrook2e70f6e2008-06-29 01:03:05 +00003046/* in deterministic execution mode, instructions doing device I/Os
3047 must be at the end of the TB */
3048void cpu_io_recompile(CPUState *env, void *retaddr)
3049{
3050 TranslationBlock *tb;
3051 uint32_t n, cflags;
3052 target_ulong pc, cs_base;
3053 uint64_t flags;
3054
3055 tb = tb_find_pc((unsigned long)retaddr);
3056 if (!tb) {
3057 cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p",
3058 retaddr);
3059 }
3060 n = env->icount_decr.u16.low + tb->icount;
3061 cpu_restore_state(tb, env, (unsigned long)retaddr, NULL);
3062 /* Calculate how many instructions had been executed before the fault
thsbf20dc02008-06-30 17:22:19 +00003063 occurred. */
pbrook2e70f6e2008-06-29 01:03:05 +00003064 n = n - env->icount_decr.u16.low;
3065 /* Generate a new TB ending on the I/O insn. */
3066 n++;
3067 /* On MIPS and SH, delay slot instructions can only be restarted if
3068 they were already the first instruction in the TB. If this is not
thsbf20dc02008-06-30 17:22:19 +00003069 the first instruction in a TB then re-execute the preceding
pbrook2e70f6e2008-06-29 01:03:05 +00003070 branch. */
3071#if defined(TARGET_MIPS)
3072 if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) {
3073 env->active_tc.PC -= 4;
3074 env->icount_decr.u16.low++;
3075 env->hflags &= ~MIPS_HFLAG_BMASK;
3076 }
3077#elif defined(TARGET_SH4)
3078 if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
3079 && n > 1) {
3080 env->pc -= 2;
3081 env->icount_decr.u16.low++;
3082 env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
3083 }
3084#endif
3085 /* This should never happen. */
3086 if (n > CF_COUNT_MASK)
3087 cpu_abort(env, "TB too big during recompile");
3088
3089 cflags = n | CF_LAST_IO;
3090 pc = tb->pc;
3091 cs_base = tb->cs_base;
3092 flags = tb->flags;
3093 tb_phys_invalidate(tb, -1);
3094 /* FIXME: In theory this could raise an exception. In practice
3095 we have already translated the block once so it's probably ok. */
3096 tb_gen_code(env, pc, cs_base, flags, cflags);
thsbf20dc02008-06-30 17:22:19 +00003097 /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
pbrook2e70f6e2008-06-29 01:03:05 +00003098 the first in the TB) then we end up generating a whole new TB and
3099 repeating the fault, which is horribly inefficient.
3100 Better would be to execute just this insn uncached, or generate a
3101 second new TB. */
3102 cpu_resume_from_signal(env, NULL);
3103}
3104
bellarde3db7222005-01-26 22:00:47 +00003105void dump_exec_info(FILE *f,
3106 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
3107{
3108 int i, target_code_size, max_target_code_size;
3109 int direct_jmp_count, direct_jmp2_count, cross_page;
3110 TranslationBlock *tb;
ths3b46e622007-09-17 08:09:54 +00003111
bellarde3db7222005-01-26 22:00:47 +00003112 target_code_size = 0;
3113 max_target_code_size = 0;
3114 cross_page = 0;
3115 direct_jmp_count = 0;
3116 direct_jmp2_count = 0;
3117 for(i = 0; i < nb_tbs; i++) {
3118 tb = &tbs[i];
3119 target_code_size += tb->size;
3120 if (tb->size > max_target_code_size)
3121 max_target_code_size = tb->size;
3122 if (tb->page_addr[1] != -1)
3123 cross_page++;
3124 if (tb->tb_next_offset[0] != 0xffff) {
3125 direct_jmp_count++;
3126 if (tb->tb_next_offset[1] != 0xffff) {
3127 direct_jmp2_count++;
3128 }
3129 }
3130 }
3131 /* XXX: avoid using doubles ? */
bellard57fec1f2008-02-01 10:50:11 +00003132 cpu_fprintf(f, "Translation buffer state:\n");
bellard26a5f132008-05-28 12:30:31 +00003133 cpu_fprintf(f, "gen code size %ld/%ld\n",
3134 code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size);
3135 cpu_fprintf(f, "TB count %d/%d\n",
3136 nb_tbs, code_gen_max_blocks);
ths5fafdf22007-09-16 21:08:06 +00003137 cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
bellarde3db7222005-01-26 22:00:47 +00003138 nb_tbs ? target_code_size / nb_tbs : 0,
3139 max_target_code_size);
ths5fafdf22007-09-16 21:08:06 +00003140 cpu_fprintf(f, "TB avg host size %d bytes (expansion ratio: %0.1f)\n",
bellarde3db7222005-01-26 22:00:47 +00003141 nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
3142 target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
ths5fafdf22007-09-16 21:08:06 +00003143 cpu_fprintf(f, "cross page TB count %d (%d%%)\n",
3144 cross_page,
bellarde3db7222005-01-26 22:00:47 +00003145 nb_tbs ? (cross_page * 100) / nb_tbs : 0);
3146 cpu_fprintf(f, "direct jump count %d (%d%%) (2 jumps=%d %d%%)\n",
ths5fafdf22007-09-16 21:08:06 +00003147 direct_jmp_count,
bellarde3db7222005-01-26 22:00:47 +00003148 nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
3149 direct_jmp2_count,
3150 nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
bellard57fec1f2008-02-01 10:50:11 +00003151 cpu_fprintf(f, "\nStatistics:\n");
bellarde3db7222005-01-26 22:00:47 +00003152 cpu_fprintf(f, "TB flush count %d\n", tb_flush_count);
3153 cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
3154 cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count);
bellardb67d9a52008-05-23 09:57:34 +00003155 tcg_dump_info(f, cpu_fprintf);
bellarde3db7222005-01-26 22:00:47 +00003156}
3157
ths5fafdf22007-09-16 21:08:06 +00003158#if !defined(CONFIG_USER_ONLY)
bellard61382a52003-10-27 21:22:23 +00003159
3160#define MMUSUFFIX _cmmu
3161#define GETPC() NULL
3162#define env cpu_single_env
bellardb769d8f2004-10-03 15:07:13 +00003163#define SOFTMMU_CODE_ACCESS
bellard61382a52003-10-27 21:22:23 +00003164
3165#define SHIFT 0
3166#include "softmmu_template.h"
3167
3168#define SHIFT 1
3169#include "softmmu_template.h"
3170
3171#define SHIFT 2
3172#include "softmmu_template.h"
3173
3174#define SHIFT 3
3175#include "softmmu_template.h"
3176
3177#undef env
3178
3179#endif