blob: d6e5d3c0c043e66706ed2f3fe78678297022ef54 [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
aurel32fad6cb12009-01-04 22:05:52 +000018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
bellard54936002003-05-13 00:25:15 +000019 */
bellard67b915a2004-03-31 23:37:16 +000020#include "config.h"
bellardd5a8f072004-09-29 21:15:28 +000021#ifdef _WIN32
22#include <windows.h>
23#else
bellarda98d49b2004-11-14 16:22:05 +000024#include <sys/types.h>
bellardd5a8f072004-09-29 21:15:28 +000025#include <sys/mman.h>
26#endif
bellard54936002003-05-13 00:25:15 +000027#include <stdlib.h>
28#include <stdio.h>
29#include <stdarg.h>
30#include <string.h>
31#include <errno.h>
32#include <unistd.h>
33#include <inttypes.h>
34
bellard6180a182003-09-30 21:04:53 +000035#include "cpu.h"
36#include "exec-all.h"
aurel32ca10f862008-04-11 21:35:42 +000037#include "qemu-common.h"
bellardb67d9a52008-05-23 09:57:34 +000038#include "tcg.h"
pbrookb3c77242008-06-30 16:31:04 +000039#include "hw/hw.h"
aliguori74576192008-10-06 14:02:03 +000040#include "osdep.h"
aliguori7ba1e612008-11-05 16:04:33 +000041#include "kvm.h"
pbrook53a59602006-03-25 19:31:22 +000042#if defined(CONFIG_USER_ONLY)
43#include <qemu.h>
44#endif
bellard54936002003-05-13 00:25:15 +000045
bellardfd6ce8f2003-05-14 19:00:11 +000046//#define DEBUG_TB_INVALIDATE
bellard66e85a22003-06-24 13:28:12 +000047//#define DEBUG_FLUSH
bellard9fa3e852004-01-04 18:06:42 +000048//#define DEBUG_TLB
pbrook67d3b952006-12-18 05:03:52 +000049//#define DEBUG_UNASSIGNED
bellardfd6ce8f2003-05-14 19:00:11 +000050
51/* make various TB consistency checks */
ths5fafdf22007-09-16 21:08:06 +000052//#define DEBUG_TB_CHECK
53//#define DEBUG_TLB_CHECK
bellardfd6ce8f2003-05-14 19:00:11 +000054
ths1196be32007-03-17 15:17:58 +000055//#define DEBUG_IOPORT
blueswir1db7b5422007-05-26 17:36:03 +000056//#define DEBUG_SUBPAGE
ths1196be32007-03-17 15:17:58 +000057
pbrook99773bd2006-04-16 15:14:59 +000058#if !defined(CONFIG_USER_ONLY)
59/* TB consistency checks only implemented for usermode emulation. */
60#undef DEBUG_TB_CHECK
61#endif
62
bellard9fa3e852004-01-04 18:06:42 +000063#define SMC_BITMAP_USE_THRESHOLD 10
64
bellard108c49b2005-07-24 12:55:09 +000065#if defined(TARGET_SPARC64)
66#define TARGET_PHYS_ADDR_SPACE_BITS 41
blueswir15dcb6b92007-05-19 12:58:30 +000067#elif defined(TARGET_SPARC)
68#define TARGET_PHYS_ADDR_SPACE_BITS 36
j_mayerbedb69e2007-04-05 20:08:21 +000069#elif defined(TARGET_ALPHA)
70#define TARGET_PHYS_ADDR_SPACE_BITS 42
71#define TARGET_VIRT_ADDR_SPACE_BITS 42
bellard108c49b2005-07-24 12:55:09 +000072#elif defined(TARGET_PPC64)
73#define TARGET_PHYS_ADDR_SPACE_BITS 42
blueswir1640f42e2009-04-19 10:18:01 +000074#elif defined(TARGET_X86_64) && !defined(CONFIG_KQEMU)
aurel3200f82b82008-04-27 21:12:55 +000075#define TARGET_PHYS_ADDR_SPACE_BITS 42
blueswir1640f42e2009-04-19 10:18:01 +000076#elif defined(TARGET_I386) && !defined(CONFIG_KQEMU)
aurel3200f82b82008-04-27 21:12:55 +000077#define TARGET_PHYS_ADDR_SPACE_BITS 36
bellard108c49b2005-07-24 12:55:09 +000078#else
79/* Note: for compatibility with kqemu, we use 32 bits for x86_64 */
80#define TARGET_PHYS_ADDR_SPACE_BITS 32
81#endif
82
blueswir1bdaf78e2008-10-04 07:24:27 +000083static TranslationBlock *tbs;
bellard26a5f132008-05-28 12:30:31 +000084int code_gen_max_blocks;
bellard9fa3e852004-01-04 18:06:42 +000085TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
blueswir1bdaf78e2008-10-04 07:24:27 +000086static int nb_tbs;
bellardeb51d102003-05-14 21:51:13 +000087/* any access to the tbs or the page table must use this lock */
88spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
bellardfd6ce8f2003-05-14 19:00:11 +000089
blueswir1141ac462008-07-26 15:05:57 +000090#if defined(__arm__) || defined(__sparc_v9__)
91/* The prologue must be reachable with a direct jump. ARM and Sparc64
92 have limited branch ranges (possibly also PPC) so place it in a
blueswir1d03d8602008-07-10 17:21:31 +000093 section close to code segment. */
94#define code_gen_section \
95 __attribute__((__section__(".gen_code"))) \
96 __attribute__((aligned (32)))
Stefan Weilf8e2af12009-06-18 23:04:48 +020097#elif defined(_WIN32)
98/* Maximum alignment for Win32 is 16. */
99#define code_gen_section \
100 __attribute__((aligned (16)))
blueswir1d03d8602008-07-10 17:21:31 +0000101#else
102#define code_gen_section \
103 __attribute__((aligned (32)))
104#endif
105
106uint8_t code_gen_prologue[1024] code_gen_section;
blueswir1bdaf78e2008-10-04 07:24:27 +0000107static uint8_t *code_gen_buffer;
108static unsigned long code_gen_buffer_size;
bellard26a5f132008-05-28 12:30:31 +0000109/* threshold to flush the translated code buffer */
blueswir1bdaf78e2008-10-04 07:24:27 +0000110static unsigned long code_gen_buffer_max_size;
bellardfd6ce8f2003-05-14 19:00:11 +0000111uint8_t *code_gen_ptr;
112
pbrooke2eef172008-06-08 01:09:01 +0000113#if !defined(CONFIG_USER_ONLY)
bellard9fa3e852004-01-04 18:06:42 +0000114int phys_ram_fd;
bellard1ccde1c2004-02-06 19:46:14 +0000115uint8_t *phys_ram_dirty;
aliguori74576192008-10-06 14:02:03 +0000116static int in_migration;
pbrook94a6b542009-04-11 17:15:54 +0000117
118typedef struct RAMBlock {
119 uint8_t *host;
120 ram_addr_t offset;
121 ram_addr_t length;
122 struct RAMBlock *next;
123} RAMBlock;
124
125static RAMBlock *ram_blocks;
126/* TODO: When we implement (and use) ram deallocation (e.g. for hotplug)
Stuart Bradyccbb4d42009-05-03 12:15:06 +0100127 then we can no longer assume contiguous ram offsets, and external uses
pbrook94a6b542009-04-11 17:15:54 +0000128 of this variable will break. */
129ram_addr_t last_ram_offset;
pbrooke2eef172008-06-08 01:09:01 +0000130#endif
bellard9fa3e852004-01-04 18:06:42 +0000131
bellard6a00d602005-11-21 23:25:50 +0000132CPUState *first_cpu;
133/* current CPU in the current thread. It is only valid inside
134 cpu_exec() */
ths5fafdf22007-09-16 21:08:06 +0000135CPUState *cpu_single_env;
pbrook2e70f6e2008-06-29 01:03:05 +0000136/* 0 = Do not count executed instructions.
thsbf20dc02008-06-30 17:22:19 +0000137 1 = Precise instruction counting.
pbrook2e70f6e2008-06-29 01:03:05 +0000138 2 = Adaptive rate instruction counting. */
139int use_icount = 0;
140/* Current instruction counter. While executing translated code this may
141 include some instructions that have not yet been executed. */
142int64_t qemu_icount;
bellard6a00d602005-11-21 23:25:50 +0000143
bellard54936002003-05-13 00:25:15 +0000144typedef struct PageDesc {
bellard92e873b2004-05-21 14:52:29 +0000145 /* list of TBs intersecting this ram page */
bellardfd6ce8f2003-05-14 19:00:11 +0000146 TranslationBlock *first_tb;
bellard9fa3e852004-01-04 18:06:42 +0000147 /* in order to optimize self modifying code, we count the number
148 of lookups we do to a given page to use a bitmap */
149 unsigned int code_write_count;
150 uint8_t *code_bitmap;
151#if defined(CONFIG_USER_ONLY)
152 unsigned long flags;
153#endif
bellard54936002003-05-13 00:25:15 +0000154} PageDesc;
155
bellard92e873b2004-05-21 14:52:29 +0000156typedef struct PhysPageDesc {
pbrook0f459d12008-06-09 00:20:13 +0000157 /* offset in host memory of the page + io_index in the low bits */
aurel3200f82b82008-04-27 21:12:55 +0000158 ram_addr_t phys_offset;
pbrook8da3ff12008-12-01 18:59:50 +0000159 ram_addr_t region_offset;
bellard92e873b2004-05-21 14:52:29 +0000160} PhysPageDesc;
161
bellard54936002003-05-13 00:25:15 +0000162#define L2_BITS 10
j_mayerbedb69e2007-04-05 20:08:21 +0000163#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
164/* XXX: this is a temporary hack for alpha target.
165 * In the future, this is to be replaced by a multi-level table
166 * to actually be able to handle the complete 64 bits address space.
167 */
168#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
169#else
aurel3203875442008-04-22 20:45:18 +0000170#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
j_mayerbedb69e2007-04-05 20:08:21 +0000171#endif
bellard54936002003-05-13 00:25:15 +0000172
173#define L1_SIZE (1 << L1_BITS)
174#define L2_SIZE (1 << L2_BITS)
175
bellard83fb7ad2004-07-05 21:25:26 +0000176unsigned long qemu_real_host_page_size;
177unsigned long qemu_host_page_bits;
178unsigned long qemu_host_page_size;
179unsigned long qemu_host_page_mask;
bellard54936002003-05-13 00:25:15 +0000180
bellard92e873b2004-05-21 14:52:29 +0000181/* XXX: for system emulation, it could just be an array */
bellard54936002003-05-13 00:25:15 +0000182static PageDesc *l1_map[L1_SIZE];
blueswir1bdaf78e2008-10-04 07:24:27 +0000183static PhysPageDesc **l1_phys_map;
bellard54936002003-05-13 00:25:15 +0000184
pbrooke2eef172008-06-08 01:09:01 +0000185#if !defined(CONFIG_USER_ONLY)
186static void io_mem_init(void);
187
bellard33417e72003-08-10 21:47:01 +0000188/* io memory support */
bellard33417e72003-08-10 21:47:01 +0000189CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
190CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
bellarda4193c82004-06-03 14:01:43 +0000191void *io_mem_opaque[IO_MEM_NB_ENTRIES];
blueswir1511d2b12009-03-07 15:32:56 +0000192static char io_mem_used[IO_MEM_NB_ENTRIES];
pbrook6658ffb2007-03-16 23:58:11 +0000193static int io_mem_watch;
194#endif
bellard33417e72003-08-10 21:47:01 +0000195
bellard34865132003-10-05 14:28:56 +0000196/* log support */
blueswir1d9b630f2008-10-05 09:57:08 +0000197static const char *logfilename = "/tmp/qemu.log";
bellard34865132003-10-05 14:28:56 +0000198FILE *logfile;
199int loglevel;
pbrooke735b912007-06-30 13:53:24 +0000200static int log_append = 0;
bellard34865132003-10-05 14:28:56 +0000201
bellarde3db7222005-01-26 22:00:47 +0000202/* statistics */
203static int tlb_flush_count;
204static int tb_flush_count;
205static int tb_phys_invalidate_count;
206
blueswir1db7b5422007-05-26 17:36:03 +0000207#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
208typedef struct subpage_t {
209 target_phys_addr_t base;
blueswir13ee89922008-01-02 19:45:26 +0000210 CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE][4];
211 CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE][4];
212 void *opaque[TARGET_PAGE_SIZE][2][4];
pbrook8da3ff12008-12-01 18:59:50 +0000213 ram_addr_t region_offset[TARGET_PAGE_SIZE][2][4];
blueswir1db7b5422007-05-26 17:36:03 +0000214} subpage_t;
215
bellard7cb69ca2008-05-10 10:55:51 +0000216#ifdef _WIN32
217static void map_exec(void *addr, long size)
218{
219 DWORD old_protect;
220 VirtualProtect(addr, size,
221 PAGE_EXECUTE_READWRITE, &old_protect);
222
223}
224#else
225static void map_exec(void *addr, long size)
226{
bellard43694152008-05-29 09:35:57 +0000227 unsigned long start, end, page_size;
bellard7cb69ca2008-05-10 10:55:51 +0000228
bellard43694152008-05-29 09:35:57 +0000229 page_size = getpagesize();
bellard7cb69ca2008-05-10 10:55:51 +0000230 start = (unsigned long)addr;
bellard43694152008-05-29 09:35:57 +0000231 start &= ~(page_size - 1);
bellard7cb69ca2008-05-10 10:55:51 +0000232
233 end = (unsigned long)addr + size;
bellard43694152008-05-29 09:35:57 +0000234 end += page_size - 1;
235 end &= ~(page_size - 1);
bellard7cb69ca2008-05-10 10:55:51 +0000236
237 mprotect((void *)start, end - start,
238 PROT_READ | PROT_WRITE | PROT_EXEC);
239}
240#endif
241
bellardb346ff42003-06-15 20:05:50 +0000242static void page_init(void)
bellard54936002003-05-13 00:25:15 +0000243{
bellard83fb7ad2004-07-05 21:25:26 +0000244 /* NOTE: we can always suppose that qemu_host_page_size >=
bellard54936002003-05-13 00:25:15 +0000245 TARGET_PAGE_SIZE */
aliguoric2b48b62008-11-11 22:06:42 +0000246#ifdef _WIN32
247 {
248 SYSTEM_INFO system_info;
249
250 GetSystemInfo(&system_info);
251 qemu_real_host_page_size = system_info.dwPageSize;
252 }
253#else
254 qemu_real_host_page_size = getpagesize();
255#endif
bellard83fb7ad2004-07-05 21:25:26 +0000256 if (qemu_host_page_size == 0)
257 qemu_host_page_size = qemu_real_host_page_size;
258 if (qemu_host_page_size < TARGET_PAGE_SIZE)
259 qemu_host_page_size = TARGET_PAGE_SIZE;
260 qemu_host_page_bits = 0;
261 while ((1 << qemu_host_page_bits) < qemu_host_page_size)
262 qemu_host_page_bits++;
263 qemu_host_page_mask = ~(qemu_host_page_size - 1);
bellard108c49b2005-07-24 12:55:09 +0000264 l1_phys_map = qemu_vmalloc(L1_SIZE * sizeof(void *));
265 memset(l1_phys_map, 0, L1_SIZE * sizeof(void *));
balrog50a95692007-12-12 01:16:23 +0000266
267#if !defined(_WIN32) && defined(CONFIG_USER_ONLY)
268 {
269 long long startaddr, endaddr;
270 FILE *f;
271 int n;
272
pbrookc8a706f2008-06-02 16:16:42 +0000273 mmap_lock();
pbrook07765902008-05-31 16:33:53 +0000274 last_brk = (unsigned long)sbrk(0);
balrog50a95692007-12-12 01:16:23 +0000275 f = fopen("/proc/self/maps", "r");
276 if (f) {
277 do {
278 n = fscanf (f, "%llx-%llx %*[^\n]\n", &startaddr, &endaddr);
279 if (n == 2) {
blueswir1e0b8d652008-05-03 17:51:24 +0000280 startaddr = MIN(startaddr,
281 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
282 endaddr = MIN(endaddr,
283 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
pbrookb5fc9092008-05-29 13:56:10 +0000284 page_set_flags(startaddr & TARGET_PAGE_MASK,
balrog50a95692007-12-12 01:16:23 +0000285 TARGET_PAGE_ALIGN(endaddr),
286 PAGE_RESERVED);
287 }
288 } while (!feof(f));
289 fclose(f);
290 }
pbrookc8a706f2008-06-02 16:16:42 +0000291 mmap_unlock();
balrog50a95692007-12-12 01:16:23 +0000292 }
293#endif
bellard54936002003-05-13 00:25:15 +0000294}
295
aliguori434929b2008-09-15 15:56:30 +0000296static inline PageDesc **page_l1_map(target_ulong index)
bellard54936002003-05-13 00:25:15 +0000297{
pbrook17e23772008-06-09 13:47:45 +0000298#if TARGET_LONG_BITS > 32
299 /* Host memory outside guest VM. For 32-bit targets we have already
300 excluded high addresses. */
thsd8173e02008-08-29 13:10:00 +0000301 if (index > ((target_ulong)L2_SIZE * L1_SIZE))
pbrook17e23772008-06-09 13:47:45 +0000302 return NULL;
303#endif
aliguori434929b2008-09-15 15:56:30 +0000304 return &l1_map[index >> L2_BITS];
305}
306
307static inline PageDesc *page_find_alloc(target_ulong index)
308{
309 PageDesc **lp, *p;
310 lp = page_l1_map(index);
311 if (!lp)
312 return NULL;
313
bellard54936002003-05-13 00:25:15 +0000314 p = *lp;
315 if (!p) {
316 /* allocate if not found */
pbrook17e23772008-06-09 13:47:45 +0000317#if defined(CONFIG_USER_ONLY)
pbrook17e23772008-06-09 13:47:45 +0000318 size_t len = sizeof(PageDesc) * L2_SIZE;
319 /* Don't use qemu_malloc because it may recurse. */
320 p = mmap(0, len, PROT_READ | PROT_WRITE,
321 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
bellard54936002003-05-13 00:25:15 +0000322 *lp = p;
aurel32fb1c2cd2008-12-08 18:12:26 +0000323 if (h2g_valid(p)) {
324 unsigned long addr = h2g(p);
pbrook17e23772008-06-09 13:47:45 +0000325 page_set_flags(addr & TARGET_PAGE_MASK,
326 TARGET_PAGE_ALIGN(addr + len),
327 PAGE_RESERVED);
328 }
329#else
330 p = qemu_mallocz(sizeof(PageDesc) * L2_SIZE);
331 *lp = p;
332#endif
bellard54936002003-05-13 00:25:15 +0000333 }
334 return p + (index & (L2_SIZE - 1));
335}
336
aurel3200f82b82008-04-27 21:12:55 +0000337static inline PageDesc *page_find(target_ulong index)
bellard54936002003-05-13 00:25:15 +0000338{
aliguori434929b2008-09-15 15:56:30 +0000339 PageDesc **lp, *p;
340 lp = page_l1_map(index);
341 if (!lp)
342 return NULL;
bellard54936002003-05-13 00:25:15 +0000343
aliguori434929b2008-09-15 15:56:30 +0000344 p = *lp;
bellard54936002003-05-13 00:25:15 +0000345 if (!p)
346 return 0;
bellardfd6ce8f2003-05-14 19:00:11 +0000347 return p + (index & (L2_SIZE - 1));
bellard54936002003-05-13 00:25:15 +0000348}
349
bellard108c49b2005-07-24 12:55:09 +0000350static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
bellard92e873b2004-05-21 14:52:29 +0000351{
bellard108c49b2005-07-24 12:55:09 +0000352 void **lp, **p;
pbrooke3f4e2a2006-04-08 20:02:06 +0000353 PhysPageDesc *pd;
bellard92e873b2004-05-21 14:52:29 +0000354
bellard108c49b2005-07-24 12:55:09 +0000355 p = (void **)l1_phys_map;
356#if TARGET_PHYS_ADDR_SPACE_BITS > 32
357
358#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
359#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
360#endif
361 lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1));
bellard92e873b2004-05-21 14:52:29 +0000362 p = *lp;
363 if (!p) {
364 /* allocate if not found */
bellard108c49b2005-07-24 12:55:09 +0000365 if (!alloc)
366 return NULL;
367 p = qemu_vmalloc(sizeof(void *) * L1_SIZE);
368 memset(p, 0, sizeof(void *) * L1_SIZE);
369 *lp = p;
370 }
371#endif
372 lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
pbrooke3f4e2a2006-04-08 20:02:06 +0000373 pd = *lp;
374 if (!pd) {
375 int i;
bellard108c49b2005-07-24 12:55:09 +0000376 /* allocate if not found */
377 if (!alloc)
378 return NULL;
pbrooke3f4e2a2006-04-08 20:02:06 +0000379 pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
380 *lp = pd;
pbrook67c4d232009-02-23 13:16:07 +0000381 for (i = 0; i < L2_SIZE; i++) {
pbrooke3f4e2a2006-04-08 20:02:06 +0000382 pd[i].phys_offset = IO_MEM_UNASSIGNED;
pbrook67c4d232009-02-23 13:16:07 +0000383 pd[i].region_offset = (index + i) << TARGET_PAGE_BITS;
384 }
bellard92e873b2004-05-21 14:52:29 +0000385 }
pbrooke3f4e2a2006-04-08 20:02:06 +0000386 return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
bellard92e873b2004-05-21 14:52:29 +0000387}
388
bellard108c49b2005-07-24 12:55:09 +0000389static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
bellard92e873b2004-05-21 14:52:29 +0000390{
bellard108c49b2005-07-24 12:55:09 +0000391 return phys_page_find_alloc(index, 0);
bellard92e873b2004-05-21 14:52:29 +0000392}
393
bellard9fa3e852004-01-04 18:06:42 +0000394#if !defined(CONFIG_USER_ONLY)
bellard6a00d602005-11-21 23:25:50 +0000395static void tlb_protect_code(ram_addr_t ram_addr);
ths5fafdf22007-09-16 21:08:06 +0000396static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
bellard3a7d9292005-08-21 09:26:42 +0000397 target_ulong vaddr);
pbrookc8a706f2008-06-02 16:16:42 +0000398#define mmap_lock() do { } while(0)
399#define mmap_unlock() do { } while(0)
bellard9fa3e852004-01-04 18:06:42 +0000400#endif
bellardfd6ce8f2003-05-14 19:00:11 +0000401
bellard43694152008-05-29 09:35:57 +0000402#define DEFAULT_CODE_GEN_BUFFER_SIZE (32 * 1024 * 1024)
403
404#if defined(CONFIG_USER_ONLY)
Stuart Bradyccbb4d42009-05-03 12:15:06 +0100405/* Currently it is not recommended to allocate big chunks of data in
bellard43694152008-05-29 09:35:57 +0000406 user mode. It will change when a dedicated libc will be used */
407#define USE_STATIC_CODE_GEN_BUFFER
408#endif
409
410#ifdef USE_STATIC_CODE_GEN_BUFFER
411static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE];
412#endif
413
blueswir18fcd3692008-08-17 20:26:25 +0000414static void code_gen_alloc(unsigned long tb_size)
bellard26a5f132008-05-28 12:30:31 +0000415{
bellard43694152008-05-29 09:35:57 +0000416#ifdef USE_STATIC_CODE_GEN_BUFFER
417 code_gen_buffer = static_code_gen_buffer;
418 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
419 map_exec(code_gen_buffer, code_gen_buffer_size);
420#else
bellard26a5f132008-05-28 12:30:31 +0000421 code_gen_buffer_size = tb_size;
422 if (code_gen_buffer_size == 0) {
bellard43694152008-05-29 09:35:57 +0000423#if defined(CONFIG_USER_ONLY)
424 /* in user mode, phys_ram_size is not meaningful */
425 code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
426#else
Stuart Bradyccbb4d42009-05-03 12:15:06 +0100427 /* XXX: needs adjustments */
pbrook94a6b542009-04-11 17:15:54 +0000428 code_gen_buffer_size = (unsigned long)(ram_size / 4);
bellard43694152008-05-29 09:35:57 +0000429#endif
bellard26a5f132008-05-28 12:30:31 +0000430 }
431 if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE)
432 code_gen_buffer_size = MIN_CODE_GEN_BUFFER_SIZE;
433 /* The code gen buffer location may have constraints depending on
434 the host cpu and OS */
435#if defined(__linux__)
436 {
437 int flags;
blueswir1141ac462008-07-26 15:05:57 +0000438 void *start = NULL;
439
bellard26a5f132008-05-28 12:30:31 +0000440 flags = MAP_PRIVATE | MAP_ANONYMOUS;
441#if defined(__x86_64__)
442 flags |= MAP_32BIT;
443 /* Cannot map more than that */
444 if (code_gen_buffer_size > (800 * 1024 * 1024))
445 code_gen_buffer_size = (800 * 1024 * 1024);
blueswir1141ac462008-07-26 15:05:57 +0000446#elif defined(__sparc_v9__)
447 // Map the buffer below 2G, so we can use direct calls and branches
448 flags |= MAP_FIXED;
449 start = (void *) 0x60000000UL;
450 if (code_gen_buffer_size > (512 * 1024 * 1024))
451 code_gen_buffer_size = (512 * 1024 * 1024);
balrog1cb06612008-12-01 02:10:17 +0000452#elif defined(__arm__)
balrog63d41242008-12-01 02:19:41 +0000453 /* Map the buffer below 32M, so we can use direct calls and branches */
balrog1cb06612008-12-01 02:10:17 +0000454 flags |= MAP_FIXED;
455 start = (void *) 0x01000000UL;
456 if (code_gen_buffer_size > 16 * 1024 * 1024)
457 code_gen_buffer_size = 16 * 1024 * 1024;
bellard26a5f132008-05-28 12:30:31 +0000458#endif
blueswir1141ac462008-07-26 15:05:57 +0000459 code_gen_buffer = mmap(start, code_gen_buffer_size,
460 PROT_WRITE | PROT_READ | PROT_EXEC,
bellard26a5f132008-05-28 12:30:31 +0000461 flags, -1, 0);
462 if (code_gen_buffer == MAP_FAILED) {
463 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
464 exit(1);
465 }
466 }
blueswir1c5e97232009-03-07 20:06:23 +0000467#elif defined(__FreeBSD__) || defined(__DragonFly__)
aliguori06e67a82008-09-27 15:32:41 +0000468 {
469 int flags;
470 void *addr = NULL;
471 flags = MAP_PRIVATE | MAP_ANONYMOUS;
472#if defined(__x86_64__)
473 /* FreeBSD doesn't have MAP_32BIT, use MAP_FIXED and assume
474 * 0x40000000 is free */
475 flags |= MAP_FIXED;
476 addr = (void *)0x40000000;
477 /* Cannot map more than that */
478 if (code_gen_buffer_size > (800 * 1024 * 1024))
479 code_gen_buffer_size = (800 * 1024 * 1024);
480#endif
481 code_gen_buffer = mmap(addr, code_gen_buffer_size,
482 PROT_WRITE | PROT_READ | PROT_EXEC,
483 flags, -1, 0);
484 if (code_gen_buffer == MAP_FAILED) {
485 fprintf(stderr, "Could not allocate dynamic translator buffer\n");
486 exit(1);
487 }
488 }
bellard26a5f132008-05-28 12:30:31 +0000489#else
490 code_gen_buffer = qemu_malloc(code_gen_buffer_size);
bellard26a5f132008-05-28 12:30:31 +0000491 map_exec(code_gen_buffer, code_gen_buffer_size);
492#endif
bellard43694152008-05-29 09:35:57 +0000493#endif /* !USE_STATIC_CODE_GEN_BUFFER */
bellard26a5f132008-05-28 12:30:31 +0000494 map_exec(code_gen_prologue, sizeof(code_gen_prologue));
495 code_gen_buffer_max_size = code_gen_buffer_size -
496 code_gen_max_block_size();
497 code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
498 tbs = qemu_malloc(code_gen_max_blocks * sizeof(TranslationBlock));
499}
500
501/* Must be called before using the QEMU cpus. 'tb_size' is the size
502 (in bytes) allocated to the translation buffer. Zero means default
503 size. */
504void cpu_exec_init_all(unsigned long tb_size)
505{
bellard26a5f132008-05-28 12:30:31 +0000506 cpu_gen_init();
507 code_gen_alloc(tb_size);
508 code_gen_ptr = code_gen_buffer;
bellard43694152008-05-29 09:35:57 +0000509 page_init();
pbrooke2eef172008-06-08 01:09:01 +0000510#if !defined(CONFIG_USER_ONLY)
bellard26a5f132008-05-28 12:30:31 +0000511 io_mem_init();
pbrooke2eef172008-06-08 01:09:01 +0000512#endif
bellard26a5f132008-05-28 12:30:31 +0000513}
514
pbrook9656f322008-07-01 20:01:19 +0000515#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
516
517#define CPU_COMMON_SAVE_VERSION 1
518
519static void cpu_common_save(QEMUFile *f, void *opaque)
520{
521 CPUState *env = opaque;
522
Jan Kiszkab0a46a32009-05-02 00:22:51 +0200523 cpu_synchronize_state(env, 0);
524
pbrook9656f322008-07-01 20:01:19 +0000525 qemu_put_be32s(f, &env->halted);
526 qemu_put_be32s(f, &env->interrupt_request);
527}
528
529static int cpu_common_load(QEMUFile *f, void *opaque, int version_id)
530{
531 CPUState *env = opaque;
532
533 if (version_id != CPU_COMMON_SAVE_VERSION)
534 return -EINVAL;
535
536 qemu_get_be32s(f, &env->halted);
pbrook75f482a2008-07-01 21:53:33 +0000537 qemu_get_be32s(f, &env->interrupt_request);
aurel323098dba2009-03-07 21:28:24 +0000538 /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
539 version_id is increased. */
540 env->interrupt_request &= ~0x01;
pbrook9656f322008-07-01 20:01:19 +0000541 tlb_flush(env, 1);
Jan Kiszkab0a46a32009-05-02 00:22:51 +0200542 cpu_synchronize_state(env, 1);
pbrook9656f322008-07-01 20:01:19 +0000543
544 return 0;
545}
546#endif
547
Glauber Costa950f1472009-06-09 12:15:18 -0400548CPUState *qemu_get_cpu(int cpu)
549{
550 CPUState *env = first_cpu;
551
552 while (env) {
553 if (env->cpu_index == cpu)
554 break;
555 env = env->next_cpu;
556 }
557
558 return env;
559}
560
bellard6a00d602005-11-21 23:25:50 +0000561void cpu_exec_init(CPUState *env)
bellardfd6ce8f2003-05-14 19:00:11 +0000562{
bellard6a00d602005-11-21 23:25:50 +0000563 CPUState **penv;
564 int cpu_index;
565
pbrookc2764712009-03-07 15:24:59 +0000566#if defined(CONFIG_USER_ONLY)
567 cpu_list_lock();
568#endif
bellard6a00d602005-11-21 23:25:50 +0000569 env->next_cpu = NULL;
570 penv = &first_cpu;
571 cpu_index = 0;
572 while (*penv != NULL) {
Nathan Froyd1e9fa732009-06-03 11:33:08 -0700573 penv = &(*penv)->next_cpu;
bellard6a00d602005-11-21 23:25:50 +0000574 cpu_index++;
575 }
576 env->cpu_index = cpu_index;
aliguori268a3622009-04-21 22:30:27 +0000577 env->numa_node = 0;
aliguoric0ce9982008-11-25 22:13:57 +0000578 TAILQ_INIT(&env->breakpoints);
579 TAILQ_INIT(&env->watchpoints);
bellard6a00d602005-11-21 23:25:50 +0000580 *penv = env;
pbrookc2764712009-03-07 15:24:59 +0000581#if defined(CONFIG_USER_ONLY)
582 cpu_list_unlock();
583#endif
pbrookb3c77242008-06-30 16:31:04 +0000584#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
pbrook9656f322008-07-01 20:01:19 +0000585 register_savevm("cpu_common", cpu_index, CPU_COMMON_SAVE_VERSION,
586 cpu_common_save, cpu_common_load, env);
pbrookb3c77242008-06-30 16:31:04 +0000587 register_savevm("cpu", cpu_index, CPU_SAVE_VERSION,
588 cpu_save, cpu_load, env);
589#endif
bellardfd6ce8f2003-05-14 19:00:11 +0000590}
591
bellard9fa3e852004-01-04 18:06:42 +0000592static inline void invalidate_page_bitmap(PageDesc *p)
593{
594 if (p->code_bitmap) {
bellard59817cc2004-02-16 22:01:13 +0000595 qemu_free(p->code_bitmap);
bellard9fa3e852004-01-04 18:06:42 +0000596 p->code_bitmap = NULL;
597 }
598 p->code_write_count = 0;
599}
600
bellardfd6ce8f2003-05-14 19:00:11 +0000601/* set to NULL all the 'first_tb' fields in all PageDescs */
602static void page_flush_tb(void)
603{
604 int i, j;
605 PageDesc *p;
606
607 for(i = 0; i < L1_SIZE; i++) {
608 p = l1_map[i];
609 if (p) {
bellard9fa3e852004-01-04 18:06:42 +0000610 for(j = 0; j < L2_SIZE; j++) {
611 p->first_tb = NULL;
612 invalidate_page_bitmap(p);
613 p++;
614 }
bellardfd6ce8f2003-05-14 19:00:11 +0000615 }
616 }
617}
618
619/* flush all the translation blocks */
bellardd4e81642003-05-25 16:46:15 +0000620/* XXX: tb_flush is currently not thread safe */
bellard6a00d602005-11-21 23:25:50 +0000621void tb_flush(CPUState *env1)
bellardfd6ce8f2003-05-14 19:00:11 +0000622{
bellard6a00d602005-11-21 23:25:50 +0000623 CPUState *env;
bellard01243112004-01-04 15:48:17 +0000624#if defined(DEBUG_FLUSH)
blueswir1ab3d1722007-11-04 07:31:40 +0000625 printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
626 (unsigned long)(code_gen_ptr - code_gen_buffer),
627 nb_tbs, nb_tbs > 0 ?
628 ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
bellardfd6ce8f2003-05-14 19:00:11 +0000629#endif
bellard26a5f132008-05-28 12:30:31 +0000630 if ((unsigned long)(code_gen_ptr - code_gen_buffer) > code_gen_buffer_size)
pbrooka208e542008-03-31 17:07:36 +0000631 cpu_abort(env1, "Internal error: code buffer overflow\n");
632
bellardfd6ce8f2003-05-14 19:00:11 +0000633 nb_tbs = 0;
ths3b46e622007-09-17 08:09:54 +0000634
bellard6a00d602005-11-21 23:25:50 +0000635 for(env = first_cpu; env != NULL; env = env->next_cpu) {
636 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
637 }
bellard9fa3e852004-01-04 18:06:42 +0000638
bellard8a8a6082004-10-03 13:36:49 +0000639 memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
bellardfd6ce8f2003-05-14 19:00:11 +0000640 page_flush_tb();
bellard9fa3e852004-01-04 18:06:42 +0000641
bellardfd6ce8f2003-05-14 19:00:11 +0000642 code_gen_ptr = code_gen_buffer;
bellardd4e81642003-05-25 16:46:15 +0000643 /* XXX: flush processor icache at this point if cache flush is
644 expensive */
bellarde3db7222005-01-26 22:00:47 +0000645 tb_flush_count++;
bellardfd6ce8f2003-05-14 19:00:11 +0000646}
647
648#ifdef DEBUG_TB_CHECK
649
j_mayerbc98a7e2007-04-04 07:55:12 +0000650static void tb_invalidate_check(target_ulong address)
bellardfd6ce8f2003-05-14 19:00:11 +0000651{
652 TranslationBlock *tb;
653 int i;
654 address &= TARGET_PAGE_MASK;
pbrook99773bd2006-04-16 15:14:59 +0000655 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
656 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
bellardfd6ce8f2003-05-14 19:00:11 +0000657 if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
658 address >= tb->pc + tb->size)) {
659 printf("ERROR invalidate: address=%08lx PC=%08lx size=%04x\n",
pbrook99773bd2006-04-16 15:14:59 +0000660 address, (long)tb->pc, tb->size);
bellardfd6ce8f2003-05-14 19:00:11 +0000661 }
662 }
663 }
664}
665
666/* verify that all the pages have correct rights for code */
667static void tb_page_check(void)
668{
669 TranslationBlock *tb;
670 int i, flags1, flags2;
ths3b46e622007-09-17 08:09:54 +0000671
pbrook99773bd2006-04-16 15:14:59 +0000672 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
673 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
bellardfd6ce8f2003-05-14 19:00:11 +0000674 flags1 = page_get_flags(tb->pc);
675 flags2 = page_get_flags(tb->pc + tb->size - 1);
676 if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
677 printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
pbrook99773bd2006-04-16 15:14:59 +0000678 (long)tb->pc, tb->size, flags1, flags2);
bellardfd6ce8f2003-05-14 19:00:11 +0000679 }
680 }
681 }
682}
683
blueswir1bdaf78e2008-10-04 07:24:27 +0000684static void tb_jmp_check(TranslationBlock *tb)
bellardd4e81642003-05-25 16:46:15 +0000685{
686 TranslationBlock *tb1;
687 unsigned int n1;
688
689 /* suppress any remaining jumps to this TB */
690 tb1 = tb->jmp_first;
691 for(;;) {
692 n1 = (long)tb1 & 3;
693 tb1 = (TranslationBlock *)((long)tb1 & ~3);
694 if (n1 == 2)
695 break;
696 tb1 = tb1->jmp_next[n1];
697 }
698 /* check end of list */
699 if (tb1 != tb) {
700 printf("ERROR: jmp_list from 0x%08lx\n", (long)tb);
701 }
702}
703
bellardfd6ce8f2003-05-14 19:00:11 +0000704#endif
705
706/* invalidate one TB */
707static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb,
708 int next_offset)
709{
710 TranslationBlock *tb1;
711 for(;;) {
712 tb1 = *ptb;
713 if (tb1 == tb) {
714 *ptb = *(TranslationBlock **)((char *)tb1 + next_offset);
715 break;
716 }
717 ptb = (TranslationBlock **)((char *)tb1 + next_offset);
718 }
719}
720
bellard9fa3e852004-01-04 18:06:42 +0000721static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
722{
723 TranslationBlock *tb1;
724 unsigned int n1;
725
726 for(;;) {
727 tb1 = *ptb;
728 n1 = (long)tb1 & 3;
729 tb1 = (TranslationBlock *)((long)tb1 & ~3);
730 if (tb1 == tb) {
731 *ptb = tb1->page_next[n1];
732 break;
733 }
734 ptb = &tb1->page_next[n1];
735 }
736}
737
bellardd4e81642003-05-25 16:46:15 +0000738static inline void tb_jmp_remove(TranslationBlock *tb, int n)
739{
740 TranslationBlock *tb1, **ptb;
741 unsigned int n1;
742
743 ptb = &tb->jmp_next[n];
744 tb1 = *ptb;
745 if (tb1) {
746 /* find tb(n) in circular list */
747 for(;;) {
748 tb1 = *ptb;
749 n1 = (long)tb1 & 3;
750 tb1 = (TranslationBlock *)((long)tb1 & ~3);
751 if (n1 == n && tb1 == tb)
752 break;
753 if (n1 == 2) {
754 ptb = &tb1->jmp_first;
755 } else {
756 ptb = &tb1->jmp_next[n1];
757 }
758 }
759 /* now we can suppress tb(n) from the list */
760 *ptb = tb->jmp_next[n];
761
762 tb->jmp_next[n] = NULL;
763 }
764}
765
766/* reset the jump entry 'n' of a TB so that it is not chained to
767 another TB */
768static inline void tb_reset_jump(TranslationBlock *tb, int n)
769{
770 tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
771}
772
pbrook2e70f6e2008-06-29 01:03:05 +0000773void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr)
bellardfd6ce8f2003-05-14 19:00:11 +0000774{
bellard6a00d602005-11-21 23:25:50 +0000775 CPUState *env;
bellardfd6ce8f2003-05-14 19:00:11 +0000776 PageDesc *p;
bellard8a40a182005-11-20 10:35:40 +0000777 unsigned int h, n1;
aurel3200f82b82008-04-27 21:12:55 +0000778 target_phys_addr_t phys_pc;
bellard8a40a182005-11-20 10:35:40 +0000779 TranslationBlock *tb1, *tb2;
ths3b46e622007-09-17 08:09:54 +0000780
bellard9fa3e852004-01-04 18:06:42 +0000781 /* remove the TB from the hash list */
782 phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
783 h = tb_phys_hash_func(phys_pc);
ths5fafdf22007-09-16 21:08:06 +0000784 tb_remove(&tb_phys_hash[h], tb,
bellard9fa3e852004-01-04 18:06:42 +0000785 offsetof(TranslationBlock, phys_hash_next));
bellardfd6ce8f2003-05-14 19:00:11 +0000786
bellard9fa3e852004-01-04 18:06:42 +0000787 /* remove the TB from the page list */
788 if (tb->page_addr[0] != page_addr) {
789 p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
790 tb_page_remove(&p->first_tb, tb);
791 invalidate_page_bitmap(p);
792 }
793 if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
794 p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
795 tb_page_remove(&p->first_tb, tb);
796 invalidate_page_bitmap(p);
797 }
798
bellard8a40a182005-11-20 10:35:40 +0000799 tb_invalidated_flag = 1;
800
801 /* remove the TB from the hash list */
802 h = tb_jmp_cache_hash_func(tb->pc);
bellard6a00d602005-11-21 23:25:50 +0000803 for(env = first_cpu; env != NULL; env = env->next_cpu) {
804 if (env->tb_jmp_cache[h] == tb)
805 env->tb_jmp_cache[h] = NULL;
806 }
bellard8a40a182005-11-20 10:35:40 +0000807
808 /* suppress this TB from the two jump lists */
809 tb_jmp_remove(tb, 0);
810 tb_jmp_remove(tb, 1);
811
812 /* suppress any remaining jumps to this TB */
813 tb1 = tb->jmp_first;
814 for(;;) {
815 n1 = (long)tb1 & 3;
816 if (n1 == 2)
817 break;
818 tb1 = (TranslationBlock *)((long)tb1 & ~3);
819 tb2 = tb1->jmp_next[n1];
820 tb_reset_jump(tb1, n1);
821 tb1->jmp_next[n1] = NULL;
822 tb1 = tb2;
823 }
824 tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
825
bellarde3db7222005-01-26 22:00:47 +0000826 tb_phys_invalidate_count++;
bellard9fa3e852004-01-04 18:06:42 +0000827}
828
829static inline void set_bits(uint8_t *tab, int start, int len)
830{
831 int end, mask, end1;
832
833 end = start + len;
834 tab += start >> 3;
835 mask = 0xff << (start & 7);
836 if ((start & ~7) == (end & ~7)) {
837 if (start < end) {
838 mask &= ~(0xff << (end & 7));
839 *tab |= mask;
840 }
841 } else {
842 *tab++ |= mask;
843 start = (start + 8) & ~7;
844 end1 = end & ~7;
845 while (start < end1) {
846 *tab++ = 0xff;
847 start += 8;
848 }
849 if (start < end) {
850 mask = ~(0xff << (end & 7));
851 *tab |= mask;
852 }
853 }
854}
855
856static void build_page_bitmap(PageDesc *p)
857{
858 int n, tb_start, tb_end;
859 TranslationBlock *tb;
ths3b46e622007-09-17 08:09:54 +0000860
pbrookb2a70812008-06-09 13:57:23 +0000861 p->code_bitmap = qemu_mallocz(TARGET_PAGE_SIZE / 8);
bellard9fa3e852004-01-04 18:06:42 +0000862
863 tb = p->first_tb;
864 while (tb != NULL) {
865 n = (long)tb & 3;
866 tb = (TranslationBlock *)((long)tb & ~3);
867 /* NOTE: this is subtle as a TB may span two physical pages */
868 if (n == 0) {
869 /* NOTE: tb_end may be after the end of the page, but
870 it is not a problem */
871 tb_start = tb->pc & ~TARGET_PAGE_MASK;
872 tb_end = tb_start + tb->size;
873 if (tb_end > TARGET_PAGE_SIZE)
874 tb_end = TARGET_PAGE_SIZE;
875 } else {
876 tb_start = 0;
877 tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
878 }
879 set_bits(p->code_bitmap, tb_start, tb_end - tb_start);
880 tb = tb->page_next[n];
881 }
882}
883
pbrook2e70f6e2008-06-29 01:03:05 +0000884TranslationBlock *tb_gen_code(CPUState *env,
885 target_ulong pc, target_ulong cs_base,
886 int flags, int cflags)
bellardd720b932004-04-25 17:57:43 +0000887{
888 TranslationBlock *tb;
889 uint8_t *tc_ptr;
890 target_ulong phys_pc, phys_page2, virt_page2;
891 int code_gen_size;
892
bellardc27004e2005-01-03 23:35:10 +0000893 phys_pc = get_phys_addr_code(env, pc);
894 tb = tb_alloc(pc);
bellardd720b932004-04-25 17:57:43 +0000895 if (!tb) {
896 /* flush must be done */
897 tb_flush(env);
898 /* cannot fail at this point */
bellardc27004e2005-01-03 23:35:10 +0000899 tb = tb_alloc(pc);
pbrook2e70f6e2008-06-29 01:03:05 +0000900 /* Don't forget to invalidate previous TB info. */
901 tb_invalidated_flag = 1;
bellardd720b932004-04-25 17:57:43 +0000902 }
903 tc_ptr = code_gen_ptr;
904 tb->tc_ptr = tc_ptr;
905 tb->cs_base = cs_base;
906 tb->flags = flags;
907 tb->cflags = cflags;
blueswir1d07bde82007-12-11 19:35:45 +0000908 cpu_gen_code(env, tb, &code_gen_size);
bellardd720b932004-04-25 17:57:43 +0000909 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 +0000910
bellardd720b932004-04-25 17:57:43 +0000911 /* check next page if needed */
bellardc27004e2005-01-03 23:35:10 +0000912 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
bellardd720b932004-04-25 17:57:43 +0000913 phys_page2 = -1;
bellardc27004e2005-01-03 23:35:10 +0000914 if ((pc & TARGET_PAGE_MASK) != virt_page2) {
bellardd720b932004-04-25 17:57:43 +0000915 phys_page2 = get_phys_addr_code(env, virt_page2);
916 }
917 tb_link_phys(tb, phys_pc, phys_page2);
pbrook2e70f6e2008-06-29 01:03:05 +0000918 return tb;
bellardd720b932004-04-25 17:57:43 +0000919}
ths3b46e622007-09-17 08:09:54 +0000920
bellard9fa3e852004-01-04 18:06:42 +0000921/* invalidate all TBs which intersect with the target physical page
922 starting in range [start;end[. NOTE: start and end must refer to
bellardd720b932004-04-25 17:57:43 +0000923 the same physical page. 'is_cpu_write_access' should be true if called
924 from a real cpu write access: the virtual CPU will exit the current
925 TB if code is modified inside this TB. */
aurel3200f82b82008-04-27 21:12:55 +0000926void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t end,
bellardd720b932004-04-25 17:57:43 +0000927 int is_cpu_write_access)
bellard9fa3e852004-01-04 18:06:42 +0000928{
aliguori6b917542008-11-18 19:46:41 +0000929 TranslationBlock *tb, *tb_next, *saved_tb;
bellardd720b932004-04-25 17:57:43 +0000930 CPUState *env = cpu_single_env;
bellard9fa3e852004-01-04 18:06:42 +0000931 target_ulong tb_start, tb_end;
aliguori6b917542008-11-18 19:46:41 +0000932 PageDesc *p;
933 int n;
934#ifdef TARGET_HAS_PRECISE_SMC
935 int current_tb_not_found = is_cpu_write_access;
936 TranslationBlock *current_tb = NULL;
937 int current_tb_modified = 0;
938 target_ulong current_pc = 0;
939 target_ulong current_cs_base = 0;
940 int current_flags = 0;
941#endif /* TARGET_HAS_PRECISE_SMC */
bellard9fa3e852004-01-04 18:06:42 +0000942
943 p = page_find(start >> TARGET_PAGE_BITS);
ths5fafdf22007-09-16 21:08:06 +0000944 if (!p)
bellard9fa3e852004-01-04 18:06:42 +0000945 return;
ths5fafdf22007-09-16 21:08:06 +0000946 if (!p->code_bitmap &&
bellardd720b932004-04-25 17:57:43 +0000947 ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
948 is_cpu_write_access) {
bellard9fa3e852004-01-04 18:06:42 +0000949 /* build code bitmap */
950 build_page_bitmap(p);
951 }
952
953 /* we remove all the TBs in the range [start, end[ */
954 /* XXX: see if in some cases it could be faster to invalidate all the code */
955 tb = p->first_tb;
956 while (tb != NULL) {
957 n = (long)tb & 3;
958 tb = (TranslationBlock *)((long)tb & ~3);
959 tb_next = tb->page_next[n];
960 /* NOTE: this is subtle as a TB may span two physical pages */
961 if (n == 0) {
962 /* NOTE: tb_end may be after the end of the page, but
963 it is not a problem */
964 tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
965 tb_end = tb_start + tb->size;
966 } else {
967 tb_start = tb->page_addr[1];
968 tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
969 }
970 if (!(tb_end <= start || tb_start >= end)) {
bellardd720b932004-04-25 17:57:43 +0000971#ifdef TARGET_HAS_PRECISE_SMC
972 if (current_tb_not_found) {
973 current_tb_not_found = 0;
974 current_tb = NULL;
pbrook2e70f6e2008-06-29 01:03:05 +0000975 if (env->mem_io_pc) {
bellardd720b932004-04-25 17:57:43 +0000976 /* now we have a real cpu fault */
pbrook2e70f6e2008-06-29 01:03:05 +0000977 current_tb = tb_find_pc(env->mem_io_pc);
bellardd720b932004-04-25 17:57:43 +0000978 }
979 }
980 if (current_tb == tb &&
pbrook2e70f6e2008-06-29 01:03:05 +0000981 (current_tb->cflags & CF_COUNT_MASK) != 1) {
bellardd720b932004-04-25 17:57:43 +0000982 /* If we are modifying the current TB, we must stop
983 its execution. We could be more precise by checking
984 that the modification is after the current PC, but it
985 would require a specialized function to partially
986 restore the CPU state */
ths3b46e622007-09-17 08:09:54 +0000987
bellardd720b932004-04-25 17:57:43 +0000988 current_tb_modified = 1;
ths5fafdf22007-09-16 21:08:06 +0000989 cpu_restore_state(current_tb, env,
pbrook2e70f6e2008-06-29 01:03:05 +0000990 env->mem_io_pc, NULL);
aliguori6b917542008-11-18 19:46:41 +0000991 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
992 &current_flags);
bellardd720b932004-04-25 17:57:43 +0000993 }
994#endif /* TARGET_HAS_PRECISE_SMC */
bellard6f5a9f72005-11-26 20:12:28 +0000995 /* we need to do that to handle the case where a signal
996 occurs while doing tb_phys_invalidate() */
997 saved_tb = NULL;
998 if (env) {
999 saved_tb = env->current_tb;
1000 env->current_tb = NULL;
1001 }
bellard9fa3e852004-01-04 18:06:42 +00001002 tb_phys_invalidate(tb, -1);
bellard6f5a9f72005-11-26 20:12:28 +00001003 if (env) {
1004 env->current_tb = saved_tb;
1005 if (env->interrupt_request && env->current_tb)
1006 cpu_interrupt(env, env->interrupt_request);
1007 }
bellard9fa3e852004-01-04 18:06:42 +00001008 }
1009 tb = tb_next;
1010 }
1011#if !defined(CONFIG_USER_ONLY)
1012 /* if no code remaining, no need to continue to use slow writes */
1013 if (!p->first_tb) {
1014 invalidate_page_bitmap(p);
bellardd720b932004-04-25 17:57:43 +00001015 if (is_cpu_write_access) {
pbrook2e70f6e2008-06-29 01:03:05 +00001016 tlb_unprotect_code_phys(env, start, env->mem_io_vaddr);
bellardd720b932004-04-25 17:57:43 +00001017 }
1018 }
1019#endif
1020#ifdef TARGET_HAS_PRECISE_SMC
1021 if (current_tb_modified) {
1022 /* we generate a block containing just the instruction
1023 modifying the memory. It will ensure that it cannot modify
1024 itself */
bellardea1c1802004-06-14 18:56:36 +00001025 env->current_tb = NULL;
pbrook2e70f6e2008-06-29 01:03:05 +00001026 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
bellardd720b932004-04-25 17:57:43 +00001027 cpu_resume_from_signal(env, NULL);
bellard9fa3e852004-01-04 18:06:42 +00001028 }
1029#endif
1030}
1031
1032/* len must be <= 8 and start must be a multiple of len */
aurel3200f82b82008-04-27 21:12:55 +00001033static inline void tb_invalidate_phys_page_fast(target_phys_addr_t start, int len)
bellard9fa3e852004-01-04 18:06:42 +00001034{
1035 PageDesc *p;
1036 int offset, b;
bellard59817cc2004-02-16 22:01:13 +00001037#if 0
bellarda4193c82004-06-03 14:01:43 +00001038 if (1) {
aliguori93fcfe32009-01-15 22:34:14 +00001039 qemu_log("modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
1040 cpu_single_env->mem_io_vaddr, len,
1041 cpu_single_env->eip,
1042 cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
bellard59817cc2004-02-16 22:01:13 +00001043 }
1044#endif
bellard9fa3e852004-01-04 18:06:42 +00001045 p = page_find(start >> TARGET_PAGE_BITS);
ths5fafdf22007-09-16 21:08:06 +00001046 if (!p)
bellard9fa3e852004-01-04 18:06:42 +00001047 return;
1048 if (p->code_bitmap) {
1049 offset = start & ~TARGET_PAGE_MASK;
1050 b = p->code_bitmap[offset >> 3] >> (offset & 7);
1051 if (b & ((1 << len) - 1))
1052 goto do_invalidate;
1053 } else {
1054 do_invalidate:
bellardd720b932004-04-25 17:57:43 +00001055 tb_invalidate_phys_page_range(start, start + len, 1);
bellard9fa3e852004-01-04 18:06:42 +00001056 }
1057}
1058
bellard9fa3e852004-01-04 18:06:42 +00001059#if !defined(CONFIG_SOFTMMU)
aurel3200f82b82008-04-27 21:12:55 +00001060static void tb_invalidate_phys_page(target_phys_addr_t addr,
bellardd720b932004-04-25 17:57:43 +00001061 unsigned long pc, void *puc)
bellard9fa3e852004-01-04 18:06:42 +00001062{
aliguori6b917542008-11-18 19:46:41 +00001063 TranslationBlock *tb;
bellard9fa3e852004-01-04 18:06:42 +00001064 PageDesc *p;
aliguori6b917542008-11-18 19:46:41 +00001065 int n;
bellardd720b932004-04-25 17:57:43 +00001066#ifdef TARGET_HAS_PRECISE_SMC
aliguori6b917542008-11-18 19:46:41 +00001067 TranslationBlock *current_tb = NULL;
bellardd720b932004-04-25 17:57:43 +00001068 CPUState *env = cpu_single_env;
aliguori6b917542008-11-18 19:46:41 +00001069 int current_tb_modified = 0;
1070 target_ulong current_pc = 0;
1071 target_ulong current_cs_base = 0;
1072 int current_flags = 0;
bellardd720b932004-04-25 17:57:43 +00001073#endif
bellard9fa3e852004-01-04 18:06:42 +00001074
1075 addr &= TARGET_PAGE_MASK;
1076 p = page_find(addr >> TARGET_PAGE_BITS);
ths5fafdf22007-09-16 21:08:06 +00001077 if (!p)
bellardfd6ce8f2003-05-14 19:00:11 +00001078 return;
1079 tb = p->first_tb;
bellardd720b932004-04-25 17:57:43 +00001080#ifdef TARGET_HAS_PRECISE_SMC
1081 if (tb && pc != 0) {
1082 current_tb = tb_find_pc(pc);
1083 }
1084#endif
bellardfd6ce8f2003-05-14 19:00:11 +00001085 while (tb != NULL) {
bellard9fa3e852004-01-04 18:06:42 +00001086 n = (long)tb & 3;
1087 tb = (TranslationBlock *)((long)tb & ~3);
bellardd720b932004-04-25 17:57:43 +00001088#ifdef TARGET_HAS_PRECISE_SMC
1089 if (current_tb == tb &&
pbrook2e70f6e2008-06-29 01:03:05 +00001090 (current_tb->cflags & CF_COUNT_MASK) != 1) {
bellardd720b932004-04-25 17:57:43 +00001091 /* If we are modifying the current TB, we must stop
1092 its execution. We could be more precise by checking
1093 that the modification is after the current PC, but it
1094 would require a specialized function to partially
1095 restore the CPU state */
ths3b46e622007-09-17 08:09:54 +00001096
bellardd720b932004-04-25 17:57:43 +00001097 current_tb_modified = 1;
1098 cpu_restore_state(current_tb, env, pc, puc);
aliguori6b917542008-11-18 19:46:41 +00001099 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
1100 &current_flags);
bellardd720b932004-04-25 17:57:43 +00001101 }
1102#endif /* TARGET_HAS_PRECISE_SMC */
bellard9fa3e852004-01-04 18:06:42 +00001103 tb_phys_invalidate(tb, addr);
1104 tb = tb->page_next[n];
bellardfd6ce8f2003-05-14 19:00:11 +00001105 }
1106 p->first_tb = NULL;
bellardd720b932004-04-25 17:57:43 +00001107#ifdef TARGET_HAS_PRECISE_SMC
1108 if (current_tb_modified) {
1109 /* we generate a block containing just the instruction
1110 modifying the memory. It will ensure that it cannot modify
1111 itself */
bellardea1c1802004-06-14 18:56:36 +00001112 env->current_tb = NULL;
pbrook2e70f6e2008-06-29 01:03:05 +00001113 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
bellardd720b932004-04-25 17:57:43 +00001114 cpu_resume_from_signal(env, puc);
1115 }
1116#endif
bellardfd6ce8f2003-05-14 19:00:11 +00001117}
bellard9fa3e852004-01-04 18:06:42 +00001118#endif
bellardfd6ce8f2003-05-14 19:00:11 +00001119
1120/* add the tb in the target page and protect it if necessary */
ths5fafdf22007-09-16 21:08:06 +00001121static inline void tb_alloc_page(TranslationBlock *tb,
pbrook53a59602006-03-25 19:31:22 +00001122 unsigned int n, target_ulong page_addr)
bellardfd6ce8f2003-05-14 19:00:11 +00001123{
1124 PageDesc *p;
bellard9fa3e852004-01-04 18:06:42 +00001125 TranslationBlock *last_first_tb;
bellardfd6ce8f2003-05-14 19:00:11 +00001126
bellard9fa3e852004-01-04 18:06:42 +00001127 tb->page_addr[n] = page_addr;
bellard3a7d9292005-08-21 09:26:42 +00001128 p = page_find_alloc(page_addr >> TARGET_PAGE_BITS);
bellard9fa3e852004-01-04 18:06:42 +00001129 tb->page_next[n] = p->first_tb;
1130 last_first_tb = p->first_tb;
1131 p->first_tb = (TranslationBlock *)((long)tb | n);
1132 invalidate_page_bitmap(p);
1133
bellard107db442004-06-22 18:48:46 +00001134#if defined(TARGET_HAS_SMC) || 1
bellardd720b932004-04-25 17:57:43 +00001135
bellard9fa3e852004-01-04 18:06:42 +00001136#if defined(CONFIG_USER_ONLY)
bellardfd6ce8f2003-05-14 19:00:11 +00001137 if (p->flags & PAGE_WRITE) {
pbrook53a59602006-03-25 19:31:22 +00001138 target_ulong addr;
1139 PageDesc *p2;
bellard9fa3e852004-01-04 18:06:42 +00001140 int prot;
1141
bellardfd6ce8f2003-05-14 19:00:11 +00001142 /* force the host page as non writable (writes will have a
1143 page fault + mprotect overhead) */
pbrook53a59602006-03-25 19:31:22 +00001144 page_addr &= qemu_host_page_mask;
bellardfd6ce8f2003-05-14 19:00:11 +00001145 prot = 0;
pbrook53a59602006-03-25 19:31:22 +00001146 for(addr = page_addr; addr < page_addr + qemu_host_page_size;
1147 addr += TARGET_PAGE_SIZE) {
1148
1149 p2 = page_find (addr >> TARGET_PAGE_BITS);
1150 if (!p2)
1151 continue;
1152 prot |= p2->flags;
1153 p2->flags &= ~PAGE_WRITE;
1154 page_get_flags(addr);
1155 }
ths5fafdf22007-09-16 21:08:06 +00001156 mprotect(g2h(page_addr), qemu_host_page_size,
bellardfd6ce8f2003-05-14 19:00:11 +00001157 (prot & PAGE_BITS) & ~PAGE_WRITE);
1158#ifdef DEBUG_TB_INVALIDATE
blueswir1ab3d1722007-11-04 07:31:40 +00001159 printf("protecting code page: 0x" TARGET_FMT_lx "\n",
pbrook53a59602006-03-25 19:31:22 +00001160 page_addr);
bellardfd6ce8f2003-05-14 19:00:11 +00001161#endif
bellardfd6ce8f2003-05-14 19:00:11 +00001162 }
bellard9fa3e852004-01-04 18:06:42 +00001163#else
1164 /* if some code is already present, then the pages are already
1165 protected. So we handle the case where only the first TB is
1166 allocated in a physical page */
1167 if (!last_first_tb) {
bellard6a00d602005-11-21 23:25:50 +00001168 tlb_protect_code(page_addr);
bellard9fa3e852004-01-04 18:06:42 +00001169 }
1170#endif
bellardd720b932004-04-25 17:57:43 +00001171
1172#endif /* TARGET_HAS_SMC */
bellardfd6ce8f2003-05-14 19:00:11 +00001173}
1174
1175/* Allocate a new translation block. Flush the translation buffer if
1176 too many translation blocks or too much generated code. */
bellardc27004e2005-01-03 23:35:10 +00001177TranslationBlock *tb_alloc(target_ulong pc)
bellardfd6ce8f2003-05-14 19:00:11 +00001178{
1179 TranslationBlock *tb;
bellardfd6ce8f2003-05-14 19:00:11 +00001180
bellard26a5f132008-05-28 12:30:31 +00001181 if (nb_tbs >= code_gen_max_blocks ||
1182 (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
bellardd4e81642003-05-25 16:46:15 +00001183 return NULL;
bellardfd6ce8f2003-05-14 19:00:11 +00001184 tb = &tbs[nb_tbs++];
1185 tb->pc = pc;
bellardb448f2f2004-02-25 23:24:04 +00001186 tb->cflags = 0;
bellardd4e81642003-05-25 16:46:15 +00001187 return tb;
1188}
1189
pbrook2e70f6e2008-06-29 01:03:05 +00001190void tb_free(TranslationBlock *tb)
1191{
thsbf20dc02008-06-30 17:22:19 +00001192 /* In practice this is mostly used for single use temporary TB
pbrook2e70f6e2008-06-29 01:03:05 +00001193 Ignore the hard cases and just back up if this TB happens to
1194 be the last one generated. */
1195 if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) {
1196 code_gen_ptr = tb->tc_ptr;
1197 nb_tbs--;
1198 }
1199}
1200
bellard9fa3e852004-01-04 18:06:42 +00001201/* add a new TB and link it to the physical page tables. phys_page2 is
1202 (-1) to indicate that only one page contains the TB. */
ths5fafdf22007-09-16 21:08:06 +00001203void tb_link_phys(TranslationBlock *tb,
bellard9fa3e852004-01-04 18:06:42 +00001204 target_ulong phys_pc, target_ulong phys_page2)
bellardd4e81642003-05-25 16:46:15 +00001205{
bellard9fa3e852004-01-04 18:06:42 +00001206 unsigned int h;
1207 TranslationBlock **ptb;
1208
pbrookc8a706f2008-06-02 16:16:42 +00001209 /* Grab the mmap lock to stop another thread invalidating this TB
1210 before we are done. */
1211 mmap_lock();
bellard9fa3e852004-01-04 18:06:42 +00001212 /* add in the physical hash table */
1213 h = tb_phys_hash_func(phys_pc);
1214 ptb = &tb_phys_hash[h];
1215 tb->phys_hash_next = *ptb;
1216 *ptb = tb;
bellardfd6ce8f2003-05-14 19:00:11 +00001217
1218 /* add in the page list */
bellard9fa3e852004-01-04 18:06:42 +00001219 tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK);
1220 if (phys_page2 != -1)
1221 tb_alloc_page(tb, 1, phys_page2);
1222 else
1223 tb->page_addr[1] = -1;
bellard9fa3e852004-01-04 18:06:42 +00001224
bellardd4e81642003-05-25 16:46:15 +00001225 tb->jmp_first = (TranslationBlock *)((long)tb | 2);
1226 tb->jmp_next[0] = NULL;
1227 tb->jmp_next[1] = NULL;
1228
1229 /* init original jump addresses */
1230 if (tb->tb_next_offset[0] != 0xffff)
1231 tb_reset_jump(tb, 0);
1232 if (tb->tb_next_offset[1] != 0xffff)
1233 tb_reset_jump(tb, 1);
bellard8a40a182005-11-20 10:35:40 +00001234
1235#ifdef DEBUG_TB_CHECK
1236 tb_page_check();
1237#endif
pbrookc8a706f2008-06-02 16:16:42 +00001238 mmap_unlock();
bellardfd6ce8f2003-05-14 19:00:11 +00001239}
1240
bellarda513fe12003-05-27 23:29:48 +00001241/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
1242 tb[1].tc_ptr. Return NULL if not found */
1243TranslationBlock *tb_find_pc(unsigned long tc_ptr)
1244{
1245 int m_min, m_max, m;
1246 unsigned long v;
1247 TranslationBlock *tb;
1248
1249 if (nb_tbs <= 0)
1250 return NULL;
1251 if (tc_ptr < (unsigned long)code_gen_buffer ||
1252 tc_ptr >= (unsigned long)code_gen_ptr)
1253 return NULL;
1254 /* binary search (cf Knuth) */
1255 m_min = 0;
1256 m_max = nb_tbs - 1;
1257 while (m_min <= m_max) {
1258 m = (m_min + m_max) >> 1;
1259 tb = &tbs[m];
1260 v = (unsigned long)tb->tc_ptr;
1261 if (v == tc_ptr)
1262 return tb;
1263 else if (tc_ptr < v) {
1264 m_max = m - 1;
1265 } else {
1266 m_min = m + 1;
1267 }
ths5fafdf22007-09-16 21:08:06 +00001268 }
bellarda513fe12003-05-27 23:29:48 +00001269 return &tbs[m_max];
1270}
bellard75012672003-06-21 13:11:07 +00001271
bellardea041c02003-06-25 16:16:50 +00001272static void tb_reset_jump_recursive(TranslationBlock *tb);
1273
1274static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
1275{
1276 TranslationBlock *tb1, *tb_next, **ptb;
1277 unsigned int n1;
1278
1279 tb1 = tb->jmp_next[n];
1280 if (tb1 != NULL) {
1281 /* find head of list */
1282 for(;;) {
1283 n1 = (long)tb1 & 3;
1284 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1285 if (n1 == 2)
1286 break;
1287 tb1 = tb1->jmp_next[n1];
1288 }
1289 /* we are now sure now that tb jumps to tb1 */
1290 tb_next = tb1;
1291
1292 /* remove tb from the jmp_first list */
1293 ptb = &tb_next->jmp_first;
1294 for(;;) {
1295 tb1 = *ptb;
1296 n1 = (long)tb1 & 3;
1297 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1298 if (n1 == n && tb1 == tb)
1299 break;
1300 ptb = &tb1->jmp_next[n1];
1301 }
1302 *ptb = tb->jmp_next[n];
1303 tb->jmp_next[n] = NULL;
ths3b46e622007-09-17 08:09:54 +00001304
bellardea041c02003-06-25 16:16:50 +00001305 /* suppress the jump to next tb in generated code */
1306 tb_reset_jump(tb, n);
1307
bellard01243112004-01-04 15:48:17 +00001308 /* suppress jumps in the tb on which we could have jumped */
bellardea041c02003-06-25 16:16:50 +00001309 tb_reset_jump_recursive(tb_next);
1310 }
1311}
1312
1313static void tb_reset_jump_recursive(TranslationBlock *tb)
1314{
1315 tb_reset_jump_recursive2(tb, 0);
1316 tb_reset_jump_recursive2(tb, 1);
1317}
1318
bellard1fddef42005-04-17 19:16:13 +00001319#if defined(TARGET_HAS_ICE)
bellardd720b932004-04-25 17:57:43 +00001320static void breakpoint_invalidate(CPUState *env, target_ulong pc)
1321{
j_mayer9b3c35e2007-04-07 11:21:28 +00001322 target_phys_addr_t addr;
1323 target_ulong pd;
pbrookc2f07f82006-04-08 17:14:56 +00001324 ram_addr_t ram_addr;
1325 PhysPageDesc *p;
bellardd720b932004-04-25 17:57:43 +00001326
pbrookc2f07f82006-04-08 17:14:56 +00001327 addr = cpu_get_phys_page_debug(env, pc);
1328 p = phys_page_find(addr >> TARGET_PAGE_BITS);
1329 if (!p) {
1330 pd = IO_MEM_UNASSIGNED;
1331 } else {
1332 pd = p->phys_offset;
1333 }
1334 ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
pbrook706cd4b2006-04-08 17:36:21 +00001335 tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
bellardd720b932004-04-25 17:57:43 +00001336}
bellardc27004e2005-01-03 23:35:10 +00001337#endif
bellardd720b932004-04-25 17:57:43 +00001338
pbrook6658ffb2007-03-16 23:58:11 +00001339/* Add a watchpoint. */
aliguoria1d1bb32008-11-18 20:07:32 +00001340int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
1341 int flags, CPUWatchpoint **watchpoint)
pbrook6658ffb2007-03-16 23:58:11 +00001342{
aliguorib4051332008-11-18 20:14:20 +00001343 target_ulong len_mask = ~(len - 1);
aliguoric0ce9982008-11-25 22:13:57 +00001344 CPUWatchpoint *wp;
pbrook6658ffb2007-03-16 23:58:11 +00001345
aliguorib4051332008-11-18 20:14:20 +00001346 /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
1347 if ((len != 1 && len != 2 && len != 4 && len != 8) || (addr & ~len_mask)) {
1348 fprintf(stderr, "qemu: tried to set invalid watchpoint at "
1349 TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
1350 return -EINVAL;
1351 }
aliguoria1d1bb32008-11-18 20:07:32 +00001352 wp = qemu_malloc(sizeof(*wp));
pbrook6658ffb2007-03-16 23:58:11 +00001353
aliguoria1d1bb32008-11-18 20:07:32 +00001354 wp->vaddr = addr;
aliguorib4051332008-11-18 20:14:20 +00001355 wp->len_mask = len_mask;
aliguoria1d1bb32008-11-18 20:07:32 +00001356 wp->flags = flags;
1357
aliguori2dc9f412008-11-18 20:56:59 +00001358 /* keep all GDB-injected watchpoints in front */
aliguoric0ce9982008-11-25 22:13:57 +00001359 if (flags & BP_GDB)
1360 TAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
1361 else
1362 TAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
aliguoria1d1bb32008-11-18 20:07:32 +00001363
pbrook6658ffb2007-03-16 23:58:11 +00001364 tlb_flush_page(env, addr);
aliguoria1d1bb32008-11-18 20:07:32 +00001365
1366 if (watchpoint)
1367 *watchpoint = wp;
1368 return 0;
pbrook6658ffb2007-03-16 23:58:11 +00001369}
1370
aliguoria1d1bb32008-11-18 20:07:32 +00001371/* Remove a specific watchpoint. */
1372int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len,
1373 int flags)
pbrook6658ffb2007-03-16 23:58:11 +00001374{
aliguorib4051332008-11-18 20:14:20 +00001375 target_ulong len_mask = ~(len - 1);
aliguoria1d1bb32008-11-18 20:07:32 +00001376 CPUWatchpoint *wp;
pbrook6658ffb2007-03-16 23:58:11 +00001377
aliguoric0ce9982008-11-25 22:13:57 +00001378 TAILQ_FOREACH(wp, &env->watchpoints, entry) {
aliguorib4051332008-11-18 20:14:20 +00001379 if (addr == wp->vaddr && len_mask == wp->len_mask
aliguori6e140f22008-11-18 20:37:55 +00001380 && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
aliguoria1d1bb32008-11-18 20:07:32 +00001381 cpu_watchpoint_remove_by_ref(env, wp);
pbrook6658ffb2007-03-16 23:58:11 +00001382 return 0;
1383 }
1384 }
aliguoria1d1bb32008-11-18 20:07:32 +00001385 return -ENOENT;
pbrook6658ffb2007-03-16 23:58:11 +00001386}
1387
aliguoria1d1bb32008-11-18 20:07:32 +00001388/* Remove a specific watchpoint by reference. */
1389void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint)
1390{
aliguoric0ce9982008-11-25 22:13:57 +00001391 TAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
edgar_igl7d03f822008-05-17 18:58:29 +00001392
aliguoria1d1bb32008-11-18 20:07:32 +00001393 tlb_flush_page(env, watchpoint->vaddr);
1394
1395 qemu_free(watchpoint);
edgar_igl7d03f822008-05-17 18:58:29 +00001396}
1397
aliguoria1d1bb32008-11-18 20:07:32 +00001398/* Remove all matching watchpoints. */
1399void cpu_watchpoint_remove_all(CPUState *env, int mask)
1400{
aliguoric0ce9982008-11-25 22:13:57 +00001401 CPUWatchpoint *wp, *next;
aliguoria1d1bb32008-11-18 20:07:32 +00001402
aliguoric0ce9982008-11-25 22:13:57 +00001403 TAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
aliguoria1d1bb32008-11-18 20:07:32 +00001404 if (wp->flags & mask)
1405 cpu_watchpoint_remove_by_ref(env, wp);
aliguoric0ce9982008-11-25 22:13:57 +00001406 }
aliguoria1d1bb32008-11-18 20:07:32 +00001407}
1408
1409/* Add a breakpoint. */
1410int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
1411 CPUBreakpoint **breakpoint)
bellard4c3a88a2003-07-26 12:06:08 +00001412{
bellard1fddef42005-04-17 19:16:13 +00001413#if defined(TARGET_HAS_ICE)
aliguoric0ce9982008-11-25 22:13:57 +00001414 CPUBreakpoint *bp;
ths3b46e622007-09-17 08:09:54 +00001415
aliguoria1d1bb32008-11-18 20:07:32 +00001416 bp = qemu_malloc(sizeof(*bp));
aliguoria1d1bb32008-11-18 20:07:32 +00001417
1418 bp->pc = pc;
1419 bp->flags = flags;
1420
aliguori2dc9f412008-11-18 20:56:59 +00001421 /* keep all GDB-injected breakpoints in front */
aliguoric0ce9982008-11-25 22:13:57 +00001422 if (flags & BP_GDB)
1423 TAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
1424 else
1425 TAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
aliguoria1d1bb32008-11-18 20:07:32 +00001426
1427 breakpoint_invalidate(env, pc);
1428
1429 if (breakpoint)
1430 *breakpoint = bp;
1431 return 0;
1432#else
1433 return -ENOSYS;
1434#endif
1435}
1436
1437/* Remove a specific breakpoint. */
1438int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags)
1439{
1440#if defined(TARGET_HAS_ICE)
1441 CPUBreakpoint *bp;
1442
aliguoric0ce9982008-11-25 22:13:57 +00001443 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
aliguoria1d1bb32008-11-18 20:07:32 +00001444 if (bp->pc == pc && bp->flags == flags) {
1445 cpu_breakpoint_remove_by_ref(env, bp);
bellard4c3a88a2003-07-26 12:06:08 +00001446 return 0;
aliguoria1d1bb32008-11-18 20:07:32 +00001447 }
bellard4c3a88a2003-07-26 12:06:08 +00001448 }
aliguoria1d1bb32008-11-18 20:07:32 +00001449 return -ENOENT;
bellard4c3a88a2003-07-26 12:06:08 +00001450#else
aliguoria1d1bb32008-11-18 20:07:32 +00001451 return -ENOSYS;
bellard4c3a88a2003-07-26 12:06:08 +00001452#endif
1453}
1454
aliguoria1d1bb32008-11-18 20:07:32 +00001455/* Remove a specific breakpoint by reference. */
1456void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint)
bellard4c3a88a2003-07-26 12:06:08 +00001457{
bellard1fddef42005-04-17 19:16:13 +00001458#if defined(TARGET_HAS_ICE)
aliguoric0ce9982008-11-25 22:13:57 +00001459 TAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
bellardd720b932004-04-25 17:57:43 +00001460
aliguoria1d1bb32008-11-18 20:07:32 +00001461 breakpoint_invalidate(env, breakpoint->pc);
1462
1463 qemu_free(breakpoint);
1464#endif
1465}
1466
1467/* Remove all matching breakpoints. */
1468void cpu_breakpoint_remove_all(CPUState *env, int mask)
1469{
1470#if defined(TARGET_HAS_ICE)
aliguoric0ce9982008-11-25 22:13:57 +00001471 CPUBreakpoint *bp, *next;
aliguoria1d1bb32008-11-18 20:07:32 +00001472
aliguoric0ce9982008-11-25 22:13:57 +00001473 TAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
aliguoria1d1bb32008-11-18 20:07:32 +00001474 if (bp->flags & mask)
1475 cpu_breakpoint_remove_by_ref(env, bp);
aliguoric0ce9982008-11-25 22:13:57 +00001476 }
bellard4c3a88a2003-07-26 12:06:08 +00001477#endif
1478}
1479
bellardc33a3462003-07-29 20:50:33 +00001480/* enable or disable single step mode. EXCP_DEBUG is returned by the
1481 CPU loop after each instruction */
1482void cpu_single_step(CPUState *env, int enabled)
1483{
bellard1fddef42005-04-17 19:16:13 +00001484#if defined(TARGET_HAS_ICE)
bellardc33a3462003-07-29 20:50:33 +00001485 if (env->singlestep_enabled != enabled) {
1486 env->singlestep_enabled = enabled;
aliguorie22a25c2009-03-12 20:12:48 +00001487 if (kvm_enabled())
1488 kvm_update_guest_debug(env, 0);
1489 else {
Stuart Bradyccbb4d42009-05-03 12:15:06 +01001490 /* must flush all the translated code to avoid inconsistencies */
aliguorie22a25c2009-03-12 20:12:48 +00001491 /* XXX: only flush what is necessary */
1492 tb_flush(env);
1493 }
bellardc33a3462003-07-29 20:50:33 +00001494 }
1495#endif
1496}
1497
bellard34865132003-10-05 14:28:56 +00001498/* enable or disable low levels log */
1499void cpu_set_log(int log_flags)
1500{
1501 loglevel = log_flags;
1502 if (loglevel && !logfile) {
pbrook11fcfab2007-07-01 18:21:11 +00001503 logfile = fopen(logfilename, log_append ? "a" : "w");
bellard34865132003-10-05 14:28:56 +00001504 if (!logfile) {
1505 perror(logfilename);
1506 _exit(1);
1507 }
bellard9fa3e852004-01-04 18:06:42 +00001508#if !defined(CONFIG_SOFTMMU)
1509 /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1510 {
blueswir1b55266b2008-09-20 08:07:15 +00001511 static char logfile_buf[4096];
bellard9fa3e852004-01-04 18:06:42 +00001512 setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1513 }
1514#else
bellard34865132003-10-05 14:28:56 +00001515 setvbuf(logfile, NULL, _IOLBF, 0);
bellard9fa3e852004-01-04 18:06:42 +00001516#endif
pbrooke735b912007-06-30 13:53:24 +00001517 log_append = 1;
1518 }
1519 if (!loglevel && logfile) {
1520 fclose(logfile);
1521 logfile = NULL;
bellard34865132003-10-05 14:28:56 +00001522 }
1523}
1524
1525void cpu_set_log_filename(const char *filename)
1526{
1527 logfilename = strdup(filename);
pbrooke735b912007-06-30 13:53:24 +00001528 if (logfile) {
1529 fclose(logfile);
1530 logfile = NULL;
1531 }
1532 cpu_set_log(loglevel);
bellard34865132003-10-05 14:28:56 +00001533}
bellardc33a3462003-07-29 20:50:33 +00001534
aurel323098dba2009-03-07 21:28:24 +00001535static void cpu_unlink_tb(CPUState *env)
bellardea041c02003-06-25 16:16:50 +00001536{
pbrookd5975362008-06-07 20:50:51 +00001537#if defined(USE_NPTL)
1538 /* FIXME: TB unchaining isn't SMP safe. For now just ignore the
1539 problem and hope the cpu will stop of its own accord. For userspace
1540 emulation this often isn't actually as bad as it sounds. Often
1541 signals are used primarily to interrupt blocking syscalls. */
1542#else
aurel323098dba2009-03-07 21:28:24 +00001543 TranslationBlock *tb;
1544 static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
1545
1546 tb = env->current_tb;
1547 /* if the cpu is currently executing code, we must unlink it and
1548 all the potentially executing TB */
1549 if (tb && !testandset(&interrupt_lock)) {
1550 env->current_tb = NULL;
1551 tb_reset_jump_recursive(tb);
1552 resetlock(&interrupt_lock);
1553 }
1554#endif
1555}
1556
1557/* mask must never be zero, except for A20 change call */
1558void cpu_interrupt(CPUState *env, int mask)
1559{
1560 int old_mask;
1561
1562 old_mask = env->interrupt_request;
1563 env->interrupt_request |= mask;
1564
aliguori8edac962009-04-24 18:03:45 +00001565#ifndef CONFIG_USER_ONLY
1566 /*
1567 * If called from iothread context, wake the target cpu in
1568 * case its halted.
1569 */
1570 if (!qemu_cpu_self(env)) {
1571 qemu_cpu_kick(env);
1572 return;
1573 }
1574#endif
1575
pbrook2e70f6e2008-06-29 01:03:05 +00001576 if (use_icount) {
pbrook266910c2008-07-09 15:31:50 +00001577 env->icount_decr.u16.high = 0xffff;
pbrook2e70f6e2008-06-29 01:03:05 +00001578#ifndef CONFIG_USER_ONLY
pbrook2e70f6e2008-06-29 01:03:05 +00001579 if (!can_do_io(env)
aurel32be214e62009-03-06 21:48:00 +00001580 && (mask & ~old_mask) != 0) {
pbrook2e70f6e2008-06-29 01:03:05 +00001581 cpu_abort(env, "Raised interrupt while not in I/O function");
1582 }
1583#endif
1584 } else {
aurel323098dba2009-03-07 21:28:24 +00001585 cpu_unlink_tb(env);
bellardea041c02003-06-25 16:16:50 +00001586 }
1587}
1588
bellardb54ad042004-05-20 13:42:52 +00001589void cpu_reset_interrupt(CPUState *env, int mask)
1590{
1591 env->interrupt_request &= ~mask;
1592}
1593
aurel323098dba2009-03-07 21:28:24 +00001594void cpu_exit(CPUState *env)
1595{
1596 env->exit_request = 1;
1597 cpu_unlink_tb(env);
1598}
1599
blueswir1c7cd6a32008-10-02 18:27:46 +00001600const CPULogItem cpu_log_items[] = {
ths5fafdf22007-09-16 21:08:06 +00001601 { CPU_LOG_TB_OUT_ASM, "out_asm",
bellardf193c792004-03-21 17:06:25 +00001602 "show generated host assembly code for each compiled TB" },
1603 { CPU_LOG_TB_IN_ASM, "in_asm",
1604 "show target assembly code for each compiled TB" },
ths5fafdf22007-09-16 21:08:06 +00001605 { CPU_LOG_TB_OP, "op",
bellard57fec1f2008-02-01 10:50:11 +00001606 "show micro ops for each compiled TB" },
bellardf193c792004-03-21 17:06:25 +00001607 { CPU_LOG_TB_OP_OPT, "op_opt",
blueswir1e01a1152008-03-14 17:37:11 +00001608 "show micro ops "
1609#ifdef TARGET_I386
1610 "before eflags optimization and "
bellardf193c792004-03-21 17:06:25 +00001611#endif
blueswir1e01a1152008-03-14 17:37:11 +00001612 "after liveness analysis" },
bellardf193c792004-03-21 17:06:25 +00001613 { CPU_LOG_INT, "int",
1614 "show interrupts/exceptions in short format" },
1615 { CPU_LOG_EXEC, "exec",
1616 "show trace before each executed TB (lots of logs)" },
bellard9fddaa02004-05-21 12:59:32 +00001617 { CPU_LOG_TB_CPU, "cpu",
thse91c8a72007-06-03 13:35:16 +00001618 "show CPU state before block translation" },
bellardf193c792004-03-21 17:06:25 +00001619#ifdef TARGET_I386
1620 { CPU_LOG_PCALL, "pcall",
1621 "show protected mode far calls/returns/exceptions" },
aliguorieca1bdf2009-01-26 19:54:31 +00001622 { CPU_LOG_RESET, "cpu_reset",
1623 "show CPU state before CPU resets" },
bellardf193c792004-03-21 17:06:25 +00001624#endif
bellard8e3a9fd2004-10-09 17:32:58 +00001625#ifdef DEBUG_IOPORT
bellardfd872592004-05-12 19:11:15 +00001626 { CPU_LOG_IOPORT, "ioport",
1627 "show all i/o ports accesses" },
bellard8e3a9fd2004-10-09 17:32:58 +00001628#endif
bellardf193c792004-03-21 17:06:25 +00001629 { 0, NULL, NULL },
1630};
1631
1632static int cmp1(const char *s1, int n, const char *s2)
1633{
1634 if (strlen(s2) != n)
1635 return 0;
1636 return memcmp(s1, s2, n) == 0;
1637}
ths3b46e622007-09-17 08:09:54 +00001638
bellardf193c792004-03-21 17:06:25 +00001639/* takes a comma separated list of log masks. Return 0 if error. */
1640int cpu_str_to_log_mask(const char *str)
1641{
blueswir1c7cd6a32008-10-02 18:27:46 +00001642 const CPULogItem *item;
bellardf193c792004-03-21 17:06:25 +00001643 int mask;
1644 const char *p, *p1;
1645
1646 p = str;
1647 mask = 0;
1648 for(;;) {
1649 p1 = strchr(p, ',');
1650 if (!p1)
1651 p1 = p + strlen(p);
bellard8e3a9fd2004-10-09 17:32:58 +00001652 if(cmp1(p,p1-p,"all")) {
1653 for(item = cpu_log_items; item->mask != 0; item++) {
1654 mask |= item->mask;
1655 }
1656 } else {
bellardf193c792004-03-21 17:06:25 +00001657 for(item = cpu_log_items; item->mask != 0; item++) {
1658 if (cmp1(p, p1 - p, item->name))
1659 goto found;
1660 }
1661 return 0;
bellard8e3a9fd2004-10-09 17:32:58 +00001662 }
bellardf193c792004-03-21 17:06:25 +00001663 found:
1664 mask |= item->mask;
1665 if (*p1 != ',')
1666 break;
1667 p = p1 + 1;
1668 }
1669 return mask;
1670}
bellardea041c02003-06-25 16:16:50 +00001671
bellard75012672003-06-21 13:11:07 +00001672void cpu_abort(CPUState *env, const char *fmt, ...)
1673{
1674 va_list ap;
pbrook493ae1f2007-11-23 16:53:59 +00001675 va_list ap2;
bellard75012672003-06-21 13:11:07 +00001676
1677 va_start(ap, fmt);
pbrook493ae1f2007-11-23 16:53:59 +00001678 va_copy(ap2, ap);
bellard75012672003-06-21 13:11:07 +00001679 fprintf(stderr, "qemu: fatal: ");
1680 vfprintf(stderr, fmt, ap);
1681 fprintf(stderr, "\n");
1682#ifdef TARGET_I386
bellard7fe48482004-10-09 18:08:01 +00001683 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1684#else
1685 cpu_dump_state(env, stderr, fprintf, 0);
bellard75012672003-06-21 13:11:07 +00001686#endif
aliguori93fcfe32009-01-15 22:34:14 +00001687 if (qemu_log_enabled()) {
1688 qemu_log("qemu: fatal: ");
1689 qemu_log_vprintf(fmt, ap2);
1690 qemu_log("\n");
j_mayerf9373292007-09-29 12:18:20 +00001691#ifdef TARGET_I386
aliguori93fcfe32009-01-15 22:34:14 +00001692 log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
j_mayerf9373292007-09-29 12:18:20 +00001693#else
aliguori93fcfe32009-01-15 22:34:14 +00001694 log_cpu_state(env, 0);
j_mayerf9373292007-09-29 12:18:20 +00001695#endif
aliguori31b1a7b2009-01-15 22:35:09 +00001696 qemu_log_flush();
aliguori93fcfe32009-01-15 22:34:14 +00001697 qemu_log_close();
balrog924edca2007-06-10 14:07:13 +00001698 }
pbrook493ae1f2007-11-23 16:53:59 +00001699 va_end(ap2);
j_mayerf9373292007-09-29 12:18:20 +00001700 va_end(ap);
bellard75012672003-06-21 13:11:07 +00001701 abort();
1702}
1703
thsc5be9f02007-02-28 20:20:53 +00001704CPUState *cpu_copy(CPUState *env)
1705{
ths01ba9812007-12-09 02:22:57 +00001706 CPUState *new_env = cpu_init(env->cpu_model_str);
thsc5be9f02007-02-28 20:20:53 +00001707 CPUState *next_cpu = new_env->next_cpu;
1708 int cpu_index = new_env->cpu_index;
aliguori5a38f082009-01-15 20:16:51 +00001709#if defined(TARGET_HAS_ICE)
1710 CPUBreakpoint *bp;
1711 CPUWatchpoint *wp;
1712#endif
1713
thsc5be9f02007-02-28 20:20:53 +00001714 memcpy(new_env, env, sizeof(CPUState));
aliguori5a38f082009-01-15 20:16:51 +00001715
1716 /* Preserve chaining and index. */
thsc5be9f02007-02-28 20:20:53 +00001717 new_env->next_cpu = next_cpu;
1718 new_env->cpu_index = cpu_index;
aliguori5a38f082009-01-15 20:16:51 +00001719
1720 /* Clone all break/watchpoints.
1721 Note: Once we support ptrace with hw-debug register access, make sure
1722 BP_CPU break/watchpoints are handled correctly on clone. */
1723 TAILQ_INIT(&env->breakpoints);
1724 TAILQ_INIT(&env->watchpoints);
1725#if defined(TARGET_HAS_ICE)
1726 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
1727 cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
1728 }
1729 TAILQ_FOREACH(wp, &env->watchpoints, entry) {
1730 cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
1731 wp->flags, NULL);
1732 }
1733#endif
1734
thsc5be9f02007-02-28 20:20:53 +00001735 return new_env;
1736}
1737
bellard01243112004-01-04 15:48:17 +00001738#if !defined(CONFIG_USER_ONLY)
1739
edgar_igl5c751e92008-05-06 08:44:21 +00001740static inline void tlb_flush_jmp_cache(CPUState *env, target_ulong addr)
1741{
1742 unsigned int i;
1743
1744 /* Discard jump cache entries for any tb which might potentially
1745 overlap the flushed page. */
1746 i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
1747 memset (&env->tb_jmp_cache[i], 0,
1748 TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
1749
1750 i = tb_jmp_cache_hash_page(addr);
1751 memset (&env->tb_jmp_cache[i], 0,
1752 TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
1753}
1754
bellardee8b7022004-02-03 23:35:10 +00001755/* NOTE: if flush_global is true, also flush global entries (not
1756 implemented yet) */
1757void tlb_flush(CPUState *env, int flush_global)
bellard33417e72003-08-10 21:47:01 +00001758{
bellard33417e72003-08-10 21:47:01 +00001759 int i;
bellard01243112004-01-04 15:48:17 +00001760
bellard9fa3e852004-01-04 18:06:42 +00001761#if defined(DEBUG_TLB)
1762 printf("tlb_flush:\n");
1763#endif
bellard01243112004-01-04 15:48:17 +00001764 /* must reset current TB so that interrupts cannot modify the
1765 links while we are modifying them */
1766 env->current_tb = NULL;
1767
bellard33417e72003-08-10 21:47:01 +00001768 for(i = 0; i < CPU_TLB_SIZE; i++) {
Isaku Yamahatacfde4bd2009-05-20 11:31:43 +09001769 int mmu_idx;
1770 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1771 env->tlb_table[mmu_idx][i].addr_read = -1;
1772 env->tlb_table[mmu_idx][i].addr_write = -1;
1773 env->tlb_table[mmu_idx][i].addr_code = -1;
1774 }
bellard33417e72003-08-10 21:47:01 +00001775 }
bellard9fa3e852004-01-04 18:06:42 +00001776
bellard8a40a182005-11-20 10:35:40 +00001777 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
bellard9fa3e852004-01-04 18:06:42 +00001778
blueswir1640f42e2009-04-19 10:18:01 +00001779#ifdef CONFIG_KQEMU
bellard0a962c02005-02-10 22:00:27 +00001780 if (env->kqemu_enabled) {
1781 kqemu_flush(env, flush_global);
1782 }
1783#endif
bellarde3db7222005-01-26 22:00:47 +00001784 tlb_flush_count++;
bellard33417e72003-08-10 21:47:01 +00001785}
1786
bellard274da6b2004-05-20 21:56:27 +00001787static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
bellard61382a52003-10-27 21:22:23 +00001788{
ths5fafdf22007-09-16 21:08:06 +00001789 if (addr == (tlb_entry->addr_read &
bellard84b7b8e2005-11-28 21:19:04 +00001790 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
ths5fafdf22007-09-16 21:08:06 +00001791 addr == (tlb_entry->addr_write &
bellard84b7b8e2005-11-28 21:19:04 +00001792 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
ths5fafdf22007-09-16 21:08:06 +00001793 addr == (tlb_entry->addr_code &
bellard84b7b8e2005-11-28 21:19:04 +00001794 (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1795 tlb_entry->addr_read = -1;
1796 tlb_entry->addr_write = -1;
1797 tlb_entry->addr_code = -1;
1798 }
bellard61382a52003-10-27 21:22:23 +00001799}
1800
bellard2e126692004-04-25 21:28:44 +00001801void tlb_flush_page(CPUState *env, target_ulong addr)
bellard33417e72003-08-10 21:47:01 +00001802{
bellard8a40a182005-11-20 10:35:40 +00001803 int i;
Isaku Yamahatacfde4bd2009-05-20 11:31:43 +09001804 int mmu_idx;
bellard01243112004-01-04 15:48:17 +00001805
bellard9fa3e852004-01-04 18:06:42 +00001806#if defined(DEBUG_TLB)
bellard108c49b2005-07-24 12:55:09 +00001807 printf("tlb_flush_page: " TARGET_FMT_lx "\n", addr);
bellard9fa3e852004-01-04 18:06:42 +00001808#endif
bellard01243112004-01-04 15:48:17 +00001809 /* must reset current TB so that interrupts cannot modify the
1810 links while we are modifying them */
1811 env->current_tb = NULL;
bellard33417e72003-08-10 21:47:01 +00001812
bellard61382a52003-10-27 21:22:23 +00001813 addr &= TARGET_PAGE_MASK;
bellard33417e72003-08-10 21:47:01 +00001814 i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
Isaku Yamahatacfde4bd2009-05-20 11:31:43 +09001815 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++)
1816 tlb_flush_entry(&env->tlb_table[mmu_idx][i], addr);
bellard01243112004-01-04 15:48:17 +00001817
edgar_igl5c751e92008-05-06 08:44:21 +00001818 tlb_flush_jmp_cache(env, addr);
bellard9fa3e852004-01-04 18:06:42 +00001819
blueswir1640f42e2009-04-19 10:18:01 +00001820#ifdef CONFIG_KQEMU
bellard0a962c02005-02-10 22:00:27 +00001821 if (env->kqemu_enabled) {
1822 kqemu_flush_page(env, addr);
1823 }
1824#endif
bellard9fa3e852004-01-04 18:06:42 +00001825}
1826
bellard9fa3e852004-01-04 18:06:42 +00001827/* update the TLBs so that writes to code in the virtual page 'addr'
1828 can be detected */
bellard6a00d602005-11-21 23:25:50 +00001829static void tlb_protect_code(ram_addr_t ram_addr)
bellard61382a52003-10-27 21:22:23 +00001830{
ths5fafdf22007-09-16 21:08:06 +00001831 cpu_physical_memory_reset_dirty(ram_addr,
bellard6a00d602005-11-21 23:25:50 +00001832 ram_addr + TARGET_PAGE_SIZE,
1833 CODE_DIRTY_FLAG);
bellard9fa3e852004-01-04 18:06:42 +00001834}
1835
bellard9fa3e852004-01-04 18:06:42 +00001836/* update the TLB so that writes in physical page 'phys_addr' are no longer
bellard3a7d9292005-08-21 09:26:42 +00001837 tested for self modifying code */
ths5fafdf22007-09-16 21:08:06 +00001838static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
bellard3a7d9292005-08-21 09:26:42 +00001839 target_ulong vaddr)
bellard9fa3e852004-01-04 18:06:42 +00001840{
bellard3a7d9292005-08-21 09:26:42 +00001841 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] |= CODE_DIRTY_FLAG;
bellard1ccde1c2004-02-06 19:46:14 +00001842}
1843
ths5fafdf22007-09-16 21:08:06 +00001844static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
bellard1ccde1c2004-02-06 19:46:14 +00001845 unsigned long start, unsigned long length)
1846{
1847 unsigned long addr;
bellard84b7b8e2005-11-28 21:19:04 +00001848 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1849 addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
bellard1ccde1c2004-02-06 19:46:14 +00001850 if ((addr - start) < length) {
pbrook0f459d12008-06-09 00:20:13 +00001851 tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
bellard1ccde1c2004-02-06 19:46:14 +00001852 }
1853 }
1854}
1855
pbrook5579c7f2009-04-11 14:47:08 +00001856/* Note: start and end must be within the same ram block. */
bellard3a7d9292005-08-21 09:26:42 +00001857void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
bellard0a962c02005-02-10 22:00:27 +00001858 int dirty_flags)
bellard1ccde1c2004-02-06 19:46:14 +00001859{
1860 CPUState *env;
bellard4f2ac232004-04-26 19:44:02 +00001861 unsigned long length, start1;
bellard0a962c02005-02-10 22:00:27 +00001862 int i, mask, len;
1863 uint8_t *p;
bellard1ccde1c2004-02-06 19:46:14 +00001864
1865 start &= TARGET_PAGE_MASK;
1866 end = TARGET_PAGE_ALIGN(end);
1867
1868 length = end - start;
1869 if (length == 0)
1870 return;
bellard0a962c02005-02-10 22:00:27 +00001871 len = length >> TARGET_PAGE_BITS;
blueswir1640f42e2009-04-19 10:18:01 +00001872#ifdef CONFIG_KQEMU
bellard6a00d602005-11-21 23:25:50 +00001873 /* XXX: should not depend on cpu context */
1874 env = first_cpu;
bellard3a7d9292005-08-21 09:26:42 +00001875 if (env->kqemu_enabled) {
bellardf23db162005-08-21 19:12:28 +00001876 ram_addr_t addr;
1877 addr = start;
1878 for(i = 0; i < len; i++) {
1879 kqemu_set_notdirty(env, addr);
1880 addr += TARGET_PAGE_SIZE;
1881 }
bellard3a7d9292005-08-21 09:26:42 +00001882 }
1883#endif
bellardf23db162005-08-21 19:12:28 +00001884 mask = ~dirty_flags;
1885 p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
1886 for(i = 0; i < len; i++)
1887 p[i] &= mask;
1888
bellard1ccde1c2004-02-06 19:46:14 +00001889 /* we modify the TLB cache so that the dirty bit will be set again
1890 when accessing the range */
pbrook5579c7f2009-04-11 14:47:08 +00001891 start1 = (unsigned long)qemu_get_ram_ptr(start);
1892 /* Chek that we don't span multiple blocks - this breaks the
1893 address comparisons below. */
1894 if ((unsigned long)qemu_get_ram_ptr(end - 1) - start1
1895 != (end - 1) - start) {
1896 abort();
1897 }
1898
bellard6a00d602005-11-21 23:25:50 +00001899 for(env = first_cpu; env != NULL; env = env->next_cpu) {
Isaku Yamahatacfde4bd2009-05-20 11:31:43 +09001900 int mmu_idx;
1901 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1902 for(i = 0; i < CPU_TLB_SIZE; i++)
1903 tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
1904 start1, length);
1905 }
bellard6a00d602005-11-21 23:25:50 +00001906 }
bellard1ccde1c2004-02-06 19:46:14 +00001907}
1908
aliguori74576192008-10-06 14:02:03 +00001909int cpu_physical_memory_set_dirty_tracking(int enable)
1910{
1911 in_migration = enable;
Jan Kiszkab0a46a32009-05-02 00:22:51 +02001912 if (kvm_enabled()) {
1913 return kvm_set_migration_log(enable);
1914 }
aliguori74576192008-10-06 14:02:03 +00001915 return 0;
1916}
1917
1918int cpu_physical_memory_get_dirty_tracking(void)
1919{
1920 return in_migration;
1921}
1922
Jan Kiszka151f7742009-05-01 20:52:47 +02001923int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
1924 target_phys_addr_t end_addr)
aliguori2bec46d2008-11-24 20:21:41 +00001925{
Jan Kiszka151f7742009-05-01 20:52:47 +02001926 int ret = 0;
1927
aliguori2bec46d2008-11-24 20:21:41 +00001928 if (kvm_enabled())
Jan Kiszka151f7742009-05-01 20:52:47 +02001929 ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
1930 return ret;
aliguori2bec46d2008-11-24 20:21:41 +00001931}
1932
bellard3a7d9292005-08-21 09:26:42 +00001933static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1934{
1935 ram_addr_t ram_addr;
pbrook5579c7f2009-04-11 14:47:08 +00001936 void *p;
bellard3a7d9292005-08-21 09:26:42 +00001937
bellard84b7b8e2005-11-28 21:19:04 +00001938 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
pbrook5579c7f2009-04-11 14:47:08 +00001939 p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
1940 + tlb_entry->addend);
1941 ram_addr = qemu_ram_addr_from_host(p);
bellard3a7d9292005-08-21 09:26:42 +00001942 if (!cpu_physical_memory_is_dirty(ram_addr)) {
pbrook0f459d12008-06-09 00:20:13 +00001943 tlb_entry->addr_write |= TLB_NOTDIRTY;
bellard3a7d9292005-08-21 09:26:42 +00001944 }
1945 }
1946}
1947
1948/* update the TLB according to the current state of the dirty bits */
1949void cpu_tlb_update_dirty(CPUState *env)
1950{
1951 int i;
Isaku Yamahatacfde4bd2009-05-20 11:31:43 +09001952 int mmu_idx;
1953 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1954 for(i = 0; i < CPU_TLB_SIZE; i++)
1955 tlb_update_dirty(&env->tlb_table[mmu_idx][i]);
1956 }
bellard3a7d9292005-08-21 09:26:42 +00001957}
1958
pbrook0f459d12008-06-09 00:20:13 +00001959static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, target_ulong vaddr)
bellard1ccde1c2004-02-06 19:46:14 +00001960{
pbrook0f459d12008-06-09 00:20:13 +00001961 if (tlb_entry->addr_write == (vaddr | TLB_NOTDIRTY))
1962 tlb_entry->addr_write = vaddr;
bellard1ccde1c2004-02-06 19:46:14 +00001963}
1964
pbrook0f459d12008-06-09 00:20:13 +00001965/* update the TLB corresponding to virtual page vaddr
1966 so that it is no longer dirty */
1967static inline void tlb_set_dirty(CPUState *env, target_ulong vaddr)
bellard1ccde1c2004-02-06 19:46:14 +00001968{
bellard1ccde1c2004-02-06 19:46:14 +00001969 int i;
Isaku Yamahatacfde4bd2009-05-20 11:31:43 +09001970 int mmu_idx;
bellard1ccde1c2004-02-06 19:46:14 +00001971
pbrook0f459d12008-06-09 00:20:13 +00001972 vaddr &= TARGET_PAGE_MASK;
bellard1ccde1c2004-02-06 19:46:14 +00001973 i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
Isaku Yamahatacfde4bd2009-05-20 11:31:43 +09001974 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++)
1975 tlb_set_dirty1(&env->tlb_table[mmu_idx][i], vaddr);
bellard9fa3e852004-01-04 18:06:42 +00001976}
1977
bellard59817cc2004-02-16 22:01:13 +00001978/* add a new TLB entry. At most one entry for a given virtual address
1979 is permitted. Return 0 if OK or 2 if the page could not be mapped
1980 (can only happen in non SOFTMMU mode for I/O pages or pages
1981 conflicting with the host address space). */
ths5fafdf22007-09-16 21:08:06 +00001982int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
1983 target_phys_addr_t paddr, int prot,
j_mayer6ebbf392007-10-14 07:07:08 +00001984 int mmu_idx, int is_softmmu)
bellard9fa3e852004-01-04 18:06:42 +00001985{
bellard92e873b2004-05-21 14:52:29 +00001986 PhysPageDesc *p;
bellard4f2ac232004-04-26 19:44:02 +00001987 unsigned long pd;
bellard9fa3e852004-01-04 18:06:42 +00001988 unsigned int index;
bellard4f2ac232004-04-26 19:44:02 +00001989 target_ulong address;
pbrook0f459d12008-06-09 00:20:13 +00001990 target_ulong code_address;
bellard108c49b2005-07-24 12:55:09 +00001991 target_phys_addr_t addend;
bellard9fa3e852004-01-04 18:06:42 +00001992 int ret;
bellard84b7b8e2005-11-28 21:19:04 +00001993 CPUTLBEntry *te;
aliguoria1d1bb32008-11-18 20:07:32 +00001994 CPUWatchpoint *wp;
pbrook0f459d12008-06-09 00:20:13 +00001995 target_phys_addr_t iotlb;
bellard9fa3e852004-01-04 18:06:42 +00001996
bellard92e873b2004-05-21 14:52:29 +00001997 p = phys_page_find(paddr >> TARGET_PAGE_BITS);
bellard9fa3e852004-01-04 18:06:42 +00001998 if (!p) {
1999 pd = IO_MEM_UNASSIGNED;
bellard9fa3e852004-01-04 18:06:42 +00002000 } else {
2001 pd = p->phys_offset;
bellard9fa3e852004-01-04 18:06:42 +00002002 }
2003#if defined(DEBUG_TLB)
j_mayer6ebbf392007-10-14 07:07:08 +00002004 printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x idx=%d smmu=%d pd=0x%08lx\n",
2005 vaddr, (int)paddr, prot, mmu_idx, is_softmmu, pd);
bellard9fa3e852004-01-04 18:06:42 +00002006#endif
2007
2008 ret = 0;
pbrook0f459d12008-06-09 00:20:13 +00002009 address = vaddr;
2010 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
2011 /* IO memory case (romd handled later) */
2012 address |= TLB_MMIO;
2013 }
pbrook5579c7f2009-04-11 14:47:08 +00002014 addend = (unsigned long)qemu_get_ram_ptr(pd & TARGET_PAGE_MASK);
pbrook0f459d12008-06-09 00:20:13 +00002015 if ((pd & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
2016 /* Normal RAM. */
2017 iotlb = pd & TARGET_PAGE_MASK;
2018 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM)
2019 iotlb |= IO_MEM_NOTDIRTY;
2020 else
2021 iotlb |= IO_MEM_ROM;
2022 } else {
Stuart Bradyccbb4d42009-05-03 12:15:06 +01002023 /* IO handlers are currently passed a physical address.
pbrook0f459d12008-06-09 00:20:13 +00002024 It would be nice to pass an offset from the base address
2025 of that region. This would avoid having to special case RAM,
2026 and avoid full address decoding in every device.
2027 We can't use the high bits of pd for this because
2028 IO_MEM_ROMD uses these as a ram address. */
pbrook8da3ff12008-12-01 18:59:50 +00002029 iotlb = (pd & ~TARGET_PAGE_MASK);
2030 if (p) {
pbrook8da3ff12008-12-01 18:59:50 +00002031 iotlb += p->region_offset;
2032 } else {
2033 iotlb += paddr;
2034 }
pbrook0f459d12008-06-09 00:20:13 +00002035 }
pbrook6658ffb2007-03-16 23:58:11 +00002036
pbrook0f459d12008-06-09 00:20:13 +00002037 code_address = address;
2038 /* Make accesses to pages with watchpoints go via the
2039 watchpoint trap routines. */
aliguoric0ce9982008-11-25 22:13:57 +00002040 TAILQ_FOREACH(wp, &env->watchpoints, entry) {
aliguoria1d1bb32008-11-18 20:07:32 +00002041 if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) {
pbrook0f459d12008-06-09 00:20:13 +00002042 iotlb = io_mem_watch + paddr;
2043 /* TODO: The memory case can be optimized by not trapping
2044 reads of pages with a write breakpoint. */
2045 address |= TLB_MMIO;
pbrook6658ffb2007-03-16 23:58:11 +00002046 }
pbrook0f459d12008-06-09 00:20:13 +00002047 }
balrogd79acba2007-06-26 20:01:13 +00002048
pbrook0f459d12008-06-09 00:20:13 +00002049 index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
2050 env->iotlb[mmu_idx][index] = iotlb - vaddr;
2051 te = &env->tlb_table[mmu_idx][index];
2052 te->addend = addend - vaddr;
2053 if (prot & PAGE_READ) {
2054 te->addr_read = address;
2055 } else {
2056 te->addr_read = -1;
2057 }
edgar_igl5c751e92008-05-06 08:44:21 +00002058
pbrook0f459d12008-06-09 00:20:13 +00002059 if (prot & PAGE_EXEC) {
2060 te->addr_code = code_address;
2061 } else {
2062 te->addr_code = -1;
2063 }
2064 if (prot & PAGE_WRITE) {
2065 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM ||
2066 (pd & IO_MEM_ROMD)) {
2067 /* Write access calls the I/O callback. */
2068 te->addr_write = address | TLB_MMIO;
2069 } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
2070 !cpu_physical_memory_is_dirty(pd)) {
2071 te->addr_write = address | TLB_NOTDIRTY;
bellard84b7b8e2005-11-28 21:19:04 +00002072 } else {
pbrook0f459d12008-06-09 00:20:13 +00002073 te->addr_write = address;
bellard9fa3e852004-01-04 18:06:42 +00002074 }
pbrook0f459d12008-06-09 00:20:13 +00002075 } else {
2076 te->addr_write = -1;
bellard9fa3e852004-01-04 18:06:42 +00002077 }
bellard9fa3e852004-01-04 18:06:42 +00002078 return ret;
2079}
2080
bellard01243112004-01-04 15:48:17 +00002081#else
2082
bellardee8b7022004-02-03 23:35:10 +00002083void tlb_flush(CPUState *env, int flush_global)
bellard01243112004-01-04 15:48:17 +00002084{
2085}
2086
bellard2e126692004-04-25 21:28:44 +00002087void tlb_flush_page(CPUState *env, target_ulong addr)
bellard01243112004-01-04 15:48:17 +00002088{
2089}
2090
ths5fafdf22007-09-16 21:08:06 +00002091int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
2092 target_phys_addr_t paddr, int prot,
j_mayer6ebbf392007-10-14 07:07:08 +00002093 int mmu_idx, int is_softmmu)
bellard33417e72003-08-10 21:47:01 +00002094{
bellard9fa3e852004-01-04 18:06:42 +00002095 return 0;
2096}
bellard33417e72003-08-10 21:47:01 +00002097
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002098/*
2099 * Walks guest process memory "regions" one by one
2100 * and calls callback function 'fn' for each region.
2101 */
2102int walk_memory_regions(void *priv,
2103 int (*fn)(void *, unsigned long, unsigned long, unsigned long))
bellard9fa3e852004-01-04 18:06:42 +00002104{
2105 unsigned long start, end;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002106 PageDesc *p = NULL;
bellard9fa3e852004-01-04 18:06:42 +00002107 int i, j, prot, prot1;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002108 int rc = 0;
bellard9fa3e852004-01-04 18:06:42 +00002109
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002110 start = end = -1;
bellard9fa3e852004-01-04 18:06:42 +00002111 prot = 0;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002112
2113 for (i = 0; i <= L1_SIZE; i++) {
2114 p = (i < L1_SIZE) ? l1_map[i] : NULL;
2115 for (j = 0; j < L2_SIZE; j++) {
2116 prot1 = (p == NULL) ? 0 : p[j].flags;
2117 /*
2118 * "region" is one continuous chunk of memory
2119 * that has same protection flags set.
2120 */
bellard9fa3e852004-01-04 18:06:42 +00002121 if (prot1 != prot) {
2122 end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
2123 if (start != -1) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002124 rc = (*fn)(priv, start, end, prot);
2125 /* callback can stop iteration by returning != 0 */
2126 if (rc != 0)
2127 return (rc);
bellard9fa3e852004-01-04 18:06:42 +00002128 }
2129 if (prot1 != 0)
2130 start = end;
2131 else
2132 start = -1;
2133 prot = prot1;
2134 }
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002135 if (p == NULL)
bellard9fa3e852004-01-04 18:06:42 +00002136 break;
2137 }
bellard33417e72003-08-10 21:47:01 +00002138 }
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002139 return (rc);
2140}
2141
2142static int dump_region(void *priv, unsigned long start,
2143 unsigned long end, unsigned long prot)
2144{
2145 FILE *f = (FILE *)priv;
2146
2147 (void) fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
2148 start, end, end - start,
2149 ((prot & PAGE_READ) ? 'r' : '-'),
2150 ((prot & PAGE_WRITE) ? 'w' : '-'),
2151 ((prot & PAGE_EXEC) ? 'x' : '-'));
2152
2153 return (0);
2154}
2155
2156/* dump memory mappings */
2157void page_dump(FILE *f)
2158{
2159 (void) fprintf(f, "%-8s %-8s %-8s %s\n",
2160 "start", "end", "size", "prot");
2161 walk_memory_regions(f, dump_region);
bellard33417e72003-08-10 21:47:01 +00002162}
2163
pbrook53a59602006-03-25 19:31:22 +00002164int page_get_flags(target_ulong address)
bellard33417e72003-08-10 21:47:01 +00002165{
bellard9fa3e852004-01-04 18:06:42 +00002166 PageDesc *p;
2167
2168 p = page_find(address >> TARGET_PAGE_BITS);
bellard33417e72003-08-10 21:47:01 +00002169 if (!p)
bellard9fa3e852004-01-04 18:06:42 +00002170 return 0;
2171 return p->flags;
bellard33417e72003-08-10 21:47:01 +00002172}
2173
bellard9fa3e852004-01-04 18:06:42 +00002174/* modify the flags of a page and invalidate the code if
Stuart Bradyccbb4d42009-05-03 12:15:06 +01002175 necessary. The flag PAGE_WRITE_ORG is positioned automatically
bellard9fa3e852004-01-04 18:06:42 +00002176 depending on PAGE_WRITE */
pbrook53a59602006-03-25 19:31:22 +00002177void page_set_flags(target_ulong start, target_ulong end, int flags)
bellard9fa3e852004-01-04 18:06:42 +00002178{
2179 PageDesc *p;
pbrook53a59602006-03-25 19:31:22 +00002180 target_ulong addr;
bellard9fa3e852004-01-04 18:06:42 +00002181
pbrookc8a706f2008-06-02 16:16:42 +00002182 /* mmap_lock should already be held. */
bellard9fa3e852004-01-04 18:06:42 +00002183 start = start & TARGET_PAGE_MASK;
2184 end = TARGET_PAGE_ALIGN(end);
2185 if (flags & PAGE_WRITE)
2186 flags |= PAGE_WRITE_ORG;
bellard9fa3e852004-01-04 18:06:42 +00002187 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2188 p = page_find_alloc(addr >> TARGET_PAGE_BITS);
pbrook17e23772008-06-09 13:47:45 +00002189 /* We may be called for host regions that are outside guest
2190 address space. */
2191 if (!p)
2192 return;
bellard9fa3e852004-01-04 18:06:42 +00002193 /* if the write protection is set, then we invalidate the code
2194 inside */
ths5fafdf22007-09-16 21:08:06 +00002195 if (!(p->flags & PAGE_WRITE) &&
bellard9fa3e852004-01-04 18:06:42 +00002196 (flags & PAGE_WRITE) &&
2197 p->first_tb) {
bellardd720b932004-04-25 17:57:43 +00002198 tb_invalidate_phys_page(addr, 0, NULL);
bellard9fa3e852004-01-04 18:06:42 +00002199 }
2200 p->flags = flags;
2201 }
bellard9fa3e852004-01-04 18:06:42 +00002202}
2203
ths3d97b402007-11-02 19:02:07 +00002204int page_check_range(target_ulong start, target_ulong len, int flags)
2205{
2206 PageDesc *p;
2207 target_ulong end;
2208 target_ulong addr;
2209
balrog55f280c2008-10-28 10:24:11 +00002210 if (start + len < start)
2211 /* we've wrapped around */
2212 return -1;
2213
ths3d97b402007-11-02 19:02:07 +00002214 end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
2215 start = start & TARGET_PAGE_MASK;
2216
ths3d97b402007-11-02 19:02:07 +00002217 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2218 p = page_find(addr >> TARGET_PAGE_BITS);
2219 if( !p )
2220 return -1;
2221 if( !(p->flags & PAGE_VALID) )
2222 return -1;
2223
bellarddae32702007-11-14 10:51:00 +00002224 if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
ths3d97b402007-11-02 19:02:07 +00002225 return -1;
bellarddae32702007-11-14 10:51:00 +00002226 if (flags & PAGE_WRITE) {
2227 if (!(p->flags & PAGE_WRITE_ORG))
2228 return -1;
2229 /* unprotect the page if it was put read-only because it
2230 contains translated code */
2231 if (!(p->flags & PAGE_WRITE)) {
2232 if (!page_unprotect(addr, 0, NULL))
2233 return -1;
2234 }
2235 return 0;
2236 }
ths3d97b402007-11-02 19:02:07 +00002237 }
2238 return 0;
2239}
2240
bellard9fa3e852004-01-04 18:06:42 +00002241/* called from signal handler: invalidate the code and unprotect the
Stuart Bradyccbb4d42009-05-03 12:15:06 +01002242 page. Return TRUE if the fault was successfully handled. */
pbrook53a59602006-03-25 19:31:22 +00002243int page_unprotect(target_ulong address, unsigned long pc, void *puc)
bellard9fa3e852004-01-04 18:06:42 +00002244{
2245 unsigned int page_index, prot, pindex;
2246 PageDesc *p, *p1;
pbrook53a59602006-03-25 19:31:22 +00002247 target_ulong host_start, host_end, addr;
bellard9fa3e852004-01-04 18:06:42 +00002248
pbrookc8a706f2008-06-02 16:16:42 +00002249 /* Technically this isn't safe inside a signal handler. However we
2250 know this only ever happens in a synchronous SEGV handler, so in
2251 practice it seems to be ok. */
2252 mmap_lock();
2253
bellard83fb7ad2004-07-05 21:25:26 +00002254 host_start = address & qemu_host_page_mask;
bellard9fa3e852004-01-04 18:06:42 +00002255 page_index = host_start >> TARGET_PAGE_BITS;
2256 p1 = page_find(page_index);
pbrookc8a706f2008-06-02 16:16:42 +00002257 if (!p1) {
2258 mmap_unlock();
bellard9fa3e852004-01-04 18:06:42 +00002259 return 0;
pbrookc8a706f2008-06-02 16:16:42 +00002260 }
bellard83fb7ad2004-07-05 21:25:26 +00002261 host_end = host_start + qemu_host_page_size;
bellard9fa3e852004-01-04 18:06:42 +00002262 p = p1;
2263 prot = 0;
2264 for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
2265 prot |= p->flags;
2266 p++;
2267 }
2268 /* if the page was really writable, then we change its
2269 protection back to writable */
2270 if (prot & PAGE_WRITE_ORG) {
2271 pindex = (address - host_start) >> TARGET_PAGE_BITS;
2272 if (!(p1[pindex].flags & PAGE_WRITE)) {
ths5fafdf22007-09-16 21:08:06 +00002273 mprotect((void *)g2h(host_start), qemu_host_page_size,
bellard9fa3e852004-01-04 18:06:42 +00002274 (prot & PAGE_BITS) | PAGE_WRITE);
2275 p1[pindex].flags |= PAGE_WRITE;
2276 /* and since the content will be modified, we must invalidate
2277 the corresponding translated code. */
bellardd720b932004-04-25 17:57:43 +00002278 tb_invalidate_phys_page(address, pc, puc);
bellard9fa3e852004-01-04 18:06:42 +00002279#ifdef DEBUG_TB_CHECK
2280 tb_invalidate_check(address);
2281#endif
pbrookc8a706f2008-06-02 16:16:42 +00002282 mmap_unlock();
bellard9fa3e852004-01-04 18:06:42 +00002283 return 1;
2284 }
2285 }
pbrookc8a706f2008-06-02 16:16:42 +00002286 mmap_unlock();
bellard9fa3e852004-01-04 18:06:42 +00002287 return 0;
2288}
2289
bellard6a00d602005-11-21 23:25:50 +00002290static inline void tlb_set_dirty(CPUState *env,
2291 unsigned long addr, target_ulong vaddr)
bellard1ccde1c2004-02-06 19:46:14 +00002292{
2293}
bellard9fa3e852004-01-04 18:06:42 +00002294#endif /* defined(CONFIG_USER_ONLY) */
2295
pbrooke2eef172008-06-08 01:09:01 +00002296#if !defined(CONFIG_USER_ONLY)
pbrook8da3ff12008-12-01 18:59:50 +00002297
blueswir1db7b5422007-05-26 17:36:03 +00002298static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
pbrook8da3ff12008-12-01 18:59:50 +00002299 ram_addr_t memory, ram_addr_t region_offset);
aurel3200f82b82008-04-27 21:12:55 +00002300static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
pbrook8da3ff12008-12-01 18:59:50 +00002301 ram_addr_t orig_memory, ram_addr_t region_offset);
blueswir1db7b5422007-05-26 17:36:03 +00002302#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
2303 need_subpage) \
2304 do { \
2305 if (addr > start_addr) \
2306 start_addr2 = 0; \
2307 else { \
2308 start_addr2 = start_addr & ~TARGET_PAGE_MASK; \
2309 if (start_addr2 > 0) \
2310 need_subpage = 1; \
2311 } \
2312 \
blueswir149e9fba2007-05-30 17:25:06 +00002313 if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE) \
blueswir1db7b5422007-05-26 17:36:03 +00002314 end_addr2 = TARGET_PAGE_SIZE - 1; \
2315 else { \
2316 end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
2317 if (end_addr2 < TARGET_PAGE_SIZE - 1) \
2318 need_subpage = 1; \
2319 } \
2320 } while (0)
2321
bellard33417e72003-08-10 21:47:01 +00002322/* register physical memory. 'size' must be a multiple of the target
2323 page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
pbrook8da3ff12008-12-01 18:59:50 +00002324 io memory page. The address used when calling the IO function is
2325 the offset from the start of the region, plus region_offset. Both
Stuart Bradyccbb4d42009-05-03 12:15:06 +01002326 start_addr and region_offset are rounded down to a page boundary
pbrook8da3ff12008-12-01 18:59:50 +00002327 before calculating this offset. This should not be a problem unless
2328 the low bits of start_addr and region_offset differ. */
2329void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
2330 ram_addr_t size,
2331 ram_addr_t phys_offset,
2332 ram_addr_t region_offset)
bellard33417e72003-08-10 21:47:01 +00002333{
bellard108c49b2005-07-24 12:55:09 +00002334 target_phys_addr_t addr, end_addr;
bellard92e873b2004-05-21 14:52:29 +00002335 PhysPageDesc *p;
bellard9d420372006-06-25 22:25:22 +00002336 CPUState *env;
aurel3200f82b82008-04-27 21:12:55 +00002337 ram_addr_t orig_size = size;
blueswir1db7b5422007-05-26 17:36:03 +00002338 void *subpage;
bellard33417e72003-08-10 21:47:01 +00002339
blueswir1640f42e2009-04-19 10:18:01 +00002340#ifdef CONFIG_KQEMU
bellardda260242008-05-30 20:48:25 +00002341 /* XXX: should not depend on cpu context */
2342 env = first_cpu;
2343 if (env->kqemu_enabled) {
2344 kqemu_set_phys_mem(start_addr, size, phys_offset);
2345 }
2346#endif
aliguori7ba1e612008-11-05 16:04:33 +00002347 if (kvm_enabled())
2348 kvm_set_phys_mem(start_addr, size, phys_offset);
2349
pbrook67c4d232009-02-23 13:16:07 +00002350 if (phys_offset == IO_MEM_UNASSIGNED) {
2351 region_offset = start_addr;
2352 }
pbrook8da3ff12008-12-01 18:59:50 +00002353 region_offset &= TARGET_PAGE_MASK;
bellard5fd386f2004-05-23 21:11:22 +00002354 size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
blueswir149e9fba2007-05-30 17:25:06 +00002355 end_addr = start_addr + (target_phys_addr_t)size;
2356 for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
blueswir1db7b5422007-05-26 17:36:03 +00002357 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2358 if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
aurel3200f82b82008-04-27 21:12:55 +00002359 ram_addr_t orig_memory = p->phys_offset;
blueswir1db7b5422007-05-26 17:36:03 +00002360 target_phys_addr_t start_addr2, end_addr2;
2361 int need_subpage = 0;
2362
2363 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2364 need_subpage);
blueswir14254fab2008-01-01 16:57:19 +00002365 if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
blueswir1db7b5422007-05-26 17:36:03 +00002366 if (!(orig_memory & IO_MEM_SUBPAGE)) {
2367 subpage = subpage_init((addr & TARGET_PAGE_MASK),
pbrook8da3ff12008-12-01 18:59:50 +00002368 &p->phys_offset, orig_memory,
2369 p->region_offset);
blueswir1db7b5422007-05-26 17:36:03 +00002370 } else {
2371 subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
2372 >> IO_MEM_SHIFT];
2373 }
pbrook8da3ff12008-12-01 18:59:50 +00002374 subpage_register(subpage, start_addr2, end_addr2, phys_offset,
2375 region_offset);
2376 p->region_offset = 0;
blueswir1db7b5422007-05-26 17:36:03 +00002377 } else {
2378 p->phys_offset = phys_offset;
2379 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2380 (phys_offset & IO_MEM_ROMD))
2381 phys_offset += TARGET_PAGE_SIZE;
2382 }
2383 } else {
2384 p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2385 p->phys_offset = phys_offset;
pbrook8da3ff12008-12-01 18:59:50 +00002386 p->region_offset = region_offset;
blueswir1db7b5422007-05-26 17:36:03 +00002387 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
pbrook8da3ff12008-12-01 18:59:50 +00002388 (phys_offset & IO_MEM_ROMD)) {
blueswir1db7b5422007-05-26 17:36:03 +00002389 phys_offset += TARGET_PAGE_SIZE;
pbrook0e8f0962008-12-02 09:02:15 +00002390 } else {
blueswir1db7b5422007-05-26 17:36:03 +00002391 target_phys_addr_t start_addr2, end_addr2;
2392 int need_subpage = 0;
2393
2394 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2395 end_addr2, need_subpage);
2396
blueswir14254fab2008-01-01 16:57:19 +00002397 if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
blueswir1db7b5422007-05-26 17:36:03 +00002398 subpage = subpage_init((addr & TARGET_PAGE_MASK),
pbrook8da3ff12008-12-01 18:59:50 +00002399 &p->phys_offset, IO_MEM_UNASSIGNED,
pbrook67c4d232009-02-23 13:16:07 +00002400 addr & TARGET_PAGE_MASK);
blueswir1db7b5422007-05-26 17:36:03 +00002401 subpage_register(subpage, start_addr2, end_addr2,
pbrook8da3ff12008-12-01 18:59:50 +00002402 phys_offset, region_offset);
2403 p->region_offset = 0;
blueswir1db7b5422007-05-26 17:36:03 +00002404 }
2405 }
2406 }
pbrook8da3ff12008-12-01 18:59:50 +00002407 region_offset += TARGET_PAGE_SIZE;
bellard33417e72003-08-10 21:47:01 +00002408 }
ths3b46e622007-09-17 08:09:54 +00002409
bellard9d420372006-06-25 22:25:22 +00002410 /* since each CPU stores ram addresses in its TLB cache, we must
2411 reset the modified entries */
2412 /* XXX: slow ! */
2413 for(env = first_cpu; env != NULL; env = env->next_cpu) {
2414 tlb_flush(env, 1);
2415 }
bellard33417e72003-08-10 21:47:01 +00002416}
2417
bellardba863452006-09-24 18:41:10 +00002418/* XXX: temporary until new memory mapping API */
aurel3200f82b82008-04-27 21:12:55 +00002419ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr)
bellardba863452006-09-24 18:41:10 +00002420{
2421 PhysPageDesc *p;
2422
2423 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2424 if (!p)
2425 return IO_MEM_UNASSIGNED;
2426 return p->phys_offset;
2427}
2428
aliguorif65ed4c2008-12-09 20:09:57 +00002429void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
2430{
2431 if (kvm_enabled())
2432 kvm_coalesce_mmio_region(addr, size);
2433}
2434
2435void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
2436{
2437 if (kvm_enabled())
2438 kvm_uncoalesce_mmio_region(addr, size);
2439}
2440
blueswir1640f42e2009-04-19 10:18:01 +00002441#ifdef CONFIG_KQEMU
bellarde9a1ab12007-02-08 23:08:38 +00002442/* XXX: better than nothing */
pbrook94a6b542009-04-11 17:15:54 +00002443static ram_addr_t kqemu_ram_alloc(ram_addr_t size)
bellarde9a1ab12007-02-08 23:08:38 +00002444{
2445 ram_addr_t addr;
pbrook94a6b542009-04-11 17:15:54 +00002446 if ((last_ram_offset + size) > kqemu_phys_ram_size) {
ths012a7042008-10-02 17:34:21 +00002447 fprintf(stderr, "Not enough memory (requested_size = %" PRIu64 ", max memory = %" PRIu64 ")\n",
pbrook94a6b542009-04-11 17:15:54 +00002448 (uint64_t)size, (uint64_t)kqemu_phys_ram_size);
bellarde9a1ab12007-02-08 23:08:38 +00002449 abort();
2450 }
pbrook94a6b542009-04-11 17:15:54 +00002451 addr = last_ram_offset;
2452 last_ram_offset = TARGET_PAGE_ALIGN(last_ram_offset + size);
bellarde9a1ab12007-02-08 23:08:38 +00002453 return addr;
2454}
pbrook94a6b542009-04-11 17:15:54 +00002455#endif
2456
2457ram_addr_t qemu_ram_alloc(ram_addr_t size)
2458{
2459 RAMBlock *new_block;
2460
blueswir1640f42e2009-04-19 10:18:01 +00002461#ifdef CONFIG_KQEMU
pbrook94a6b542009-04-11 17:15:54 +00002462 if (kqemu_phys_ram_base) {
2463 return kqemu_ram_alloc(size);
2464 }
2465#endif
2466
2467 size = TARGET_PAGE_ALIGN(size);
2468 new_block = qemu_malloc(sizeof(*new_block));
2469
2470 new_block->host = qemu_vmalloc(size);
2471 new_block->offset = last_ram_offset;
2472 new_block->length = size;
2473
2474 new_block->next = ram_blocks;
2475 ram_blocks = new_block;
2476
2477 phys_ram_dirty = qemu_realloc(phys_ram_dirty,
2478 (last_ram_offset + size) >> TARGET_PAGE_BITS);
2479 memset(phys_ram_dirty + (last_ram_offset >> TARGET_PAGE_BITS),
2480 0xff, size >> TARGET_PAGE_BITS);
2481
2482 last_ram_offset += size;
2483
Jan Kiszka6f0437e2009-04-26 18:03:40 +02002484 if (kvm_enabled())
2485 kvm_setup_guest_memory(new_block->host, size);
2486
pbrook94a6b542009-04-11 17:15:54 +00002487 return new_block->offset;
2488}
bellarde9a1ab12007-02-08 23:08:38 +00002489
2490void qemu_ram_free(ram_addr_t addr)
2491{
pbrook94a6b542009-04-11 17:15:54 +00002492 /* TODO: implement this. */
bellarde9a1ab12007-02-08 23:08:38 +00002493}
2494
pbrookdc828ca2009-04-09 22:21:07 +00002495/* Return a host pointer to ram allocated with qemu_ram_alloc.
pbrook5579c7f2009-04-11 14:47:08 +00002496 With the exception of the softmmu code in this file, this should
2497 only be used for local memory (e.g. video ram) that the device owns,
2498 and knows it isn't going to access beyond the end of the block.
2499
2500 It should not be used for general purpose DMA.
2501 Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
2502 */
pbrookdc828ca2009-04-09 22:21:07 +00002503void *qemu_get_ram_ptr(ram_addr_t addr)
2504{
pbrook94a6b542009-04-11 17:15:54 +00002505 RAMBlock *prev;
2506 RAMBlock **prevp;
2507 RAMBlock *block;
2508
blueswir1640f42e2009-04-19 10:18:01 +00002509#ifdef CONFIG_KQEMU
pbrook94a6b542009-04-11 17:15:54 +00002510 if (kqemu_phys_ram_base) {
2511 return kqemu_phys_ram_base + addr;
2512 }
2513#endif
2514
2515 prev = NULL;
2516 prevp = &ram_blocks;
2517 block = ram_blocks;
2518 while (block && (block->offset > addr
2519 || block->offset + block->length <= addr)) {
2520 if (prev)
2521 prevp = &prev->next;
2522 prev = block;
2523 block = block->next;
2524 }
2525 if (!block) {
2526 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2527 abort();
2528 }
2529 /* Move this entry to to start of the list. */
2530 if (prev) {
2531 prev->next = block->next;
2532 block->next = *prevp;
2533 *prevp = block;
2534 }
2535 return block->host + (addr - block->offset);
pbrookdc828ca2009-04-09 22:21:07 +00002536}
2537
pbrook5579c7f2009-04-11 14:47:08 +00002538/* Some of the softmmu routines need to translate from a host pointer
2539 (typically a TLB entry) back to a ram offset. */
2540ram_addr_t qemu_ram_addr_from_host(void *ptr)
2541{
pbrook94a6b542009-04-11 17:15:54 +00002542 RAMBlock *prev;
2543 RAMBlock **prevp;
2544 RAMBlock *block;
2545 uint8_t *host = ptr;
2546
blueswir1640f42e2009-04-19 10:18:01 +00002547#ifdef CONFIG_KQEMU
pbrook94a6b542009-04-11 17:15:54 +00002548 if (kqemu_phys_ram_base) {
2549 return host - kqemu_phys_ram_base;
2550 }
2551#endif
2552
2553 prev = NULL;
2554 prevp = &ram_blocks;
2555 block = ram_blocks;
2556 while (block && (block->host > host
2557 || block->host + block->length <= host)) {
2558 if (prev)
2559 prevp = &prev->next;
2560 prev = block;
2561 block = block->next;
2562 }
2563 if (!block) {
2564 fprintf(stderr, "Bad ram pointer %p\n", ptr);
2565 abort();
2566 }
2567 return block->offset + (host - block->host);
pbrook5579c7f2009-04-11 14:47:08 +00002568}
2569
bellarda4193c82004-06-03 14:01:43 +00002570static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
bellard33417e72003-08-10 21:47:01 +00002571{
pbrook67d3b952006-12-18 05:03:52 +00002572#ifdef DEBUG_UNASSIGNED
blueswir1ab3d1722007-11-04 07:31:40 +00002573 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
pbrook67d3b952006-12-18 05:03:52 +00002574#endif
edgar_igl0a6f8a62008-12-29 14:39:57 +00002575#if defined(TARGET_SPARC)
blueswir1e18231a2008-10-06 18:46:28 +00002576 do_unassigned_access(addr, 0, 0, 0, 1);
2577#endif
2578 return 0;
2579}
2580
2581static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr)
2582{
2583#ifdef DEBUG_UNASSIGNED
2584 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2585#endif
edgar_igl0a6f8a62008-12-29 14:39:57 +00002586#if defined(TARGET_SPARC)
blueswir1e18231a2008-10-06 18:46:28 +00002587 do_unassigned_access(addr, 0, 0, 0, 2);
2588#endif
2589 return 0;
2590}
2591
2592static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr)
2593{
2594#ifdef DEBUG_UNASSIGNED
2595 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2596#endif
edgar_igl0a6f8a62008-12-29 14:39:57 +00002597#if defined(TARGET_SPARC)
blueswir1e18231a2008-10-06 18:46:28 +00002598 do_unassigned_access(addr, 0, 0, 0, 4);
blueswir1b4f0a312007-05-06 17:59:24 +00002599#endif
bellard33417e72003-08-10 21:47:01 +00002600 return 0;
2601}
2602
bellarda4193c82004-06-03 14:01:43 +00002603static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
bellard33417e72003-08-10 21:47:01 +00002604{
pbrook67d3b952006-12-18 05:03:52 +00002605#ifdef DEBUG_UNASSIGNED
blueswir1ab3d1722007-11-04 07:31:40 +00002606 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
pbrook67d3b952006-12-18 05:03:52 +00002607#endif
edgar_igl0a6f8a62008-12-29 14:39:57 +00002608#if defined(TARGET_SPARC)
blueswir1e18231a2008-10-06 18:46:28 +00002609 do_unassigned_access(addr, 1, 0, 0, 1);
2610#endif
2611}
2612
2613static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
2614{
2615#ifdef DEBUG_UNASSIGNED
2616 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2617#endif
edgar_igl0a6f8a62008-12-29 14:39:57 +00002618#if defined(TARGET_SPARC)
blueswir1e18231a2008-10-06 18:46:28 +00002619 do_unassigned_access(addr, 1, 0, 0, 2);
2620#endif
2621}
2622
2623static void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
2624{
2625#ifdef DEBUG_UNASSIGNED
2626 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2627#endif
edgar_igl0a6f8a62008-12-29 14:39:57 +00002628#if defined(TARGET_SPARC)
blueswir1e18231a2008-10-06 18:46:28 +00002629 do_unassigned_access(addr, 1, 0, 0, 4);
blueswir1b4f0a312007-05-06 17:59:24 +00002630#endif
bellard33417e72003-08-10 21:47:01 +00002631}
2632
2633static CPUReadMemoryFunc *unassigned_mem_read[3] = {
2634 unassigned_mem_readb,
blueswir1e18231a2008-10-06 18:46:28 +00002635 unassigned_mem_readw,
2636 unassigned_mem_readl,
bellard33417e72003-08-10 21:47:01 +00002637};
2638
2639static CPUWriteMemoryFunc *unassigned_mem_write[3] = {
2640 unassigned_mem_writeb,
blueswir1e18231a2008-10-06 18:46:28 +00002641 unassigned_mem_writew,
2642 unassigned_mem_writel,
bellard33417e72003-08-10 21:47:01 +00002643};
2644
pbrook0f459d12008-06-09 00:20:13 +00002645static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr,
2646 uint32_t val)
bellard1ccde1c2004-02-06 19:46:14 +00002647{
bellard3a7d9292005-08-21 09:26:42 +00002648 int dirty_flags;
bellard3a7d9292005-08-21 09:26:42 +00002649 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2650 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2651#if !defined(CONFIG_USER_ONLY)
2652 tb_invalidate_phys_page_fast(ram_addr, 1);
2653 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2654#endif
2655 }
pbrook5579c7f2009-04-11 14:47:08 +00002656 stb_p(qemu_get_ram_ptr(ram_addr), val);
blueswir1640f42e2009-04-19 10:18:01 +00002657#ifdef CONFIG_KQEMU
bellardf32fc642006-02-08 22:43:39 +00002658 if (cpu_single_env->kqemu_enabled &&
2659 (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2660 kqemu_modify_page(cpu_single_env, ram_addr);
2661#endif
bellardf23db162005-08-21 19:12:28 +00002662 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2663 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2664 /* we remove the notdirty callback only if the code has been
2665 flushed */
2666 if (dirty_flags == 0xff)
pbrook2e70f6e2008-06-29 01:03:05 +00002667 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
bellard1ccde1c2004-02-06 19:46:14 +00002668}
2669
pbrook0f459d12008-06-09 00:20:13 +00002670static void notdirty_mem_writew(void *opaque, target_phys_addr_t ram_addr,
2671 uint32_t val)
bellard1ccde1c2004-02-06 19:46:14 +00002672{
bellard3a7d9292005-08-21 09:26:42 +00002673 int dirty_flags;
bellard3a7d9292005-08-21 09:26:42 +00002674 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2675 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2676#if !defined(CONFIG_USER_ONLY)
2677 tb_invalidate_phys_page_fast(ram_addr, 2);
2678 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2679#endif
2680 }
pbrook5579c7f2009-04-11 14:47:08 +00002681 stw_p(qemu_get_ram_ptr(ram_addr), val);
blueswir1640f42e2009-04-19 10:18:01 +00002682#ifdef CONFIG_KQEMU
bellardf32fc642006-02-08 22:43:39 +00002683 if (cpu_single_env->kqemu_enabled &&
2684 (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2685 kqemu_modify_page(cpu_single_env, ram_addr);
2686#endif
bellardf23db162005-08-21 19:12:28 +00002687 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2688 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2689 /* we remove the notdirty callback only if the code has been
2690 flushed */
2691 if (dirty_flags == 0xff)
pbrook2e70f6e2008-06-29 01:03:05 +00002692 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
bellard1ccde1c2004-02-06 19:46:14 +00002693}
2694
pbrook0f459d12008-06-09 00:20:13 +00002695static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr,
2696 uint32_t val)
bellard1ccde1c2004-02-06 19:46:14 +00002697{
bellard3a7d9292005-08-21 09:26:42 +00002698 int dirty_flags;
bellard3a7d9292005-08-21 09:26:42 +00002699 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2700 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2701#if !defined(CONFIG_USER_ONLY)
2702 tb_invalidate_phys_page_fast(ram_addr, 4);
2703 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2704#endif
2705 }
pbrook5579c7f2009-04-11 14:47:08 +00002706 stl_p(qemu_get_ram_ptr(ram_addr), val);
blueswir1640f42e2009-04-19 10:18:01 +00002707#ifdef CONFIG_KQEMU
bellardf32fc642006-02-08 22:43:39 +00002708 if (cpu_single_env->kqemu_enabled &&
2709 (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2710 kqemu_modify_page(cpu_single_env, ram_addr);
2711#endif
bellardf23db162005-08-21 19:12:28 +00002712 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2713 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2714 /* we remove the notdirty callback only if the code has been
2715 flushed */
2716 if (dirty_flags == 0xff)
pbrook2e70f6e2008-06-29 01:03:05 +00002717 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
bellard1ccde1c2004-02-06 19:46:14 +00002718}
2719
bellard3a7d9292005-08-21 09:26:42 +00002720static CPUReadMemoryFunc *error_mem_read[3] = {
2721 NULL, /* never used */
2722 NULL, /* never used */
2723 NULL, /* never used */
2724};
2725
bellard1ccde1c2004-02-06 19:46:14 +00002726static CPUWriteMemoryFunc *notdirty_mem_write[3] = {
2727 notdirty_mem_writeb,
2728 notdirty_mem_writew,
2729 notdirty_mem_writel,
2730};
2731
pbrook0f459d12008-06-09 00:20:13 +00002732/* Generate a debug exception if a watchpoint has been hit. */
aliguorib4051332008-11-18 20:14:20 +00002733static void check_watchpoint(int offset, int len_mask, int flags)
pbrook0f459d12008-06-09 00:20:13 +00002734{
2735 CPUState *env = cpu_single_env;
aliguori06d55cc2008-11-18 20:24:06 +00002736 target_ulong pc, cs_base;
2737 TranslationBlock *tb;
pbrook0f459d12008-06-09 00:20:13 +00002738 target_ulong vaddr;
aliguoria1d1bb32008-11-18 20:07:32 +00002739 CPUWatchpoint *wp;
aliguori06d55cc2008-11-18 20:24:06 +00002740 int cpu_flags;
pbrook0f459d12008-06-09 00:20:13 +00002741
aliguori06d55cc2008-11-18 20:24:06 +00002742 if (env->watchpoint_hit) {
2743 /* We re-entered the check after replacing the TB. Now raise
2744 * the debug interrupt so that is will trigger after the
2745 * current instruction. */
2746 cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2747 return;
2748 }
pbrook2e70f6e2008-06-29 01:03:05 +00002749 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
aliguoric0ce9982008-11-25 22:13:57 +00002750 TAILQ_FOREACH(wp, &env->watchpoints, entry) {
aliguorib4051332008-11-18 20:14:20 +00002751 if ((vaddr == (wp->vaddr & len_mask) ||
2752 (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
aliguori6e140f22008-11-18 20:37:55 +00002753 wp->flags |= BP_WATCHPOINT_HIT;
2754 if (!env->watchpoint_hit) {
2755 env->watchpoint_hit = wp;
2756 tb = tb_find_pc(env->mem_io_pc);
2757 if (!tb) {
2758 cpu_abort(env, "check_watchpoint: could not find TB for "
2759 "pc=%p", (void *)env->mem_io_pc);
2760 }
2761 cpu_restore_state(tb, env, env->mem_io_pc, NULL);
2762 tb_phys_invalidate(tb, -1);
2763 if (wp->flags & BP_STOP_BEFORE_ACCESS) {
2764 env->exception_index = EXCP_DEBUG;
2765 } else {
2766 cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
2767 tb_gen_code(env, pc, cs_base, cpu_flags, 1);
2768 }
2769 cpu_resume_from_signal(env, NULL);
aliguori06d55cc2008-11-18 20:24:06 +00002770 }
aliguori6e140f22008-11-18 20:37:55 +00002771 } else {
2772 wp->flags &= ~BP_WATCHPOINT_HIT;
pbrook0f459d12008-06-09 00:20:13 +00002773 }
2774 }
2775}
2776
pbrook6658ffb2007-03-16 23:58:11 +00002777/* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
2778 so these check for a hit then pass through to the normal out-of-line
2779 phys routines. */
2780static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
2781{
aliguorib4051332008-11-18 20:14:20 +00002782 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ);
pbrook6658ffb2007-03-16 23:58:11 +00002783 return ldub_phys(addr);
2784}
2785
2786static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
2787{
aliguorib4051332008-11-18 20:14:20 +00002788 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ);
pbrook6658ffb2007-03-16 23:58:11 +00002789 return lduw_phys(addr);
2790}
2791
2792static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
2793{
aliguorib4051332008-11-18 20:14:20 +00002794 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ);
pbrook6658ffb2007-03-16 23:58:11 +00002795 return ldl_phys(addr);
2796}
2797
pbrook6658ffb2007-03-16 23:58:11 +00002798static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
2799 uint32_t val)
2800{
aliguorib4051332008-11-18 20:14:20 +00002801 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_WRITE);
pbrook6658ffb2007-03-16 23:58:11 +00002802 stb_phys(addr, val);
2803}
2804
2805static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
2806 uint32_t val)
2807{
aliguorib4051332008-11-18 20:14:20 +00002808 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_WRITE);
pbrook6658ffb2007-03-16 23:58:11 +00002809 stw_phys(addr, val);
2810}
2811
2812static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
2813 uint32_t val)
2814{
aliguorib4051332008-11-18 20:14:20 +00002815 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE);
pbrook6658ffb2007-03-16 23:58:11 +00002816 stl_phys(addr, val);
2817}
2818
2819static CPUReadMemoryFunc *watch_mem_read[3] = {
2820 watch_mem_readb,
2821 watch_mem_readw,
2822 watch_mem_readl,
2823};
2824
2825static CPUWriteMemoryFunc *watch_mem_write[3] = {
2826 watch_mem_writeb,
2827 watch_mem_writew,
2828 watch_mem_writel,
2829};
pbrook6658ffb2007-03-16 23:58:11 +00002830
blueswir1db7b5422007-05-26 17:36:03 +00002831static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr,
2832 unsigned int len)
2833{
blueswir1db7b5422007-05-26 17:36:03 +00002834 uint32_t ret;
2835 unsigned int idx;
2836
pbrook8da3ff12008-12-01 18:59:50 +00002837 idx = SUBPAGE_IDX(addr);
blueswir1db7b5422007-05-26 17:36:03 +00002838#if defined(DEBUG_SUBPAGE)
2839 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
2840 mmio, len, addr, idx);
2841#endif
pbrook8da3ff12008-12-01 18:59:50 +00002842 ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len],
2843 addr + mmio->region_offset[idx][0][len]);
blueswir1db7b5422007-05-26 17:36:03 +00002844
2845 return ret;
2846}
2847
2848static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
2849 uint32_t value, unsigned int len)
2850{
blueswir1db7b5422007-05-26 17:36:03 +00002851 unsigned int idx;
2852
pbrook8da3ff12008-12-01 18:59:50 +00002853 idx = SUBPAGE_IDX(addr);
blueswir1db7b5422007-05-26 17:36:03 +00002854#if defined(DEBUG_SUBPAGE)
2855 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
2856 mmio, len, addr, idx, value);
2857#endif
pbrook8da3ff12008-12-01 18:59:50 +00002858 (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len],
2859 addr + mmio->region_offset[idx][1][len],
2860 value);
blueswir1db7b5422007-05-26 17:36:03 +00002861}
2862
2863static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
2864{
2865#if defined(DEBUG_SUBPAGE)
2866 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2867#endif
2868
2869 return subpage_readlen(opaque, addr, 0);
2870}
2871
2872static void subpage_writeb (void *opaque, target_phys_addr_t addr,
2873 uint32_t value)
2874{
2875#if defined(DEBUG_SUBPAGE)
2876 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2877#endif
2878 subpage_writelen(opaque, addr, value, 0);
2879}
2880
2881static uint32_t subpage_readw (void *opaque, target_phys_addr_t addr)
2882{
2883#if defined(DEBUG_SUBPAGE)
2884 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2885#endif
2886
2887 return subpage_readlen(opaque, addr, 1);
2888}
2889
2890static void subpage_writew (void *opaque, target_phys_addr_t addr,
2891 uint32_t value)
2892{
2893#if defined(DEBUG_SUBPAGE)
2894 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2895#endif
2896 subpage_writelen(opaque, addr, value, 1);
2897}
2898
2899static uint32_t subpage_readl (void *opaque, target_phys_addr_t addr)
2900{
2901#if defined(DEBUG_SUBPAGE)
2902 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2903#endif
2904
2905 return subpage_readlen(opaque, addr, 2);
2906}
2907
2908static void subpage_writel (void *opaque,
2909 target_phys_addr_t addr, uint32_t value)
2910{
2911#if defined(DEBUG_SUBPAGE)
2912 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2913#endif
2914 subpage_writelen(opaque, addr, value, 2);
2915}
2916
2917static CPUReadMemoryFunc *subpage_read[] = {
2918 &subpage_readb,
2919 &subpage_readw,
2920 &subpage_readl,
2921};
2922
2923static CPUWriteMemoryFunc *subpage_write[] = {
2924 &subpage_writeb,
2925 &subpage_writew,
2926 &subpage_writel,
2927};
2928
2929static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
pbrook8da3ff12008-12-01 18:59:50 +00002930 ram_addr_t memory, ram_addr_t region_offset)
blueswir1db7b5422007-05-26 17:36:03 +00002931{
2932 int idx, eidx;
blueswir14254fab2008-01-01 16:57:19 +00002933 unsigned int i;
blueswir1db7b5422007-05-26 17:36:03 +00002934
2935 if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
2936 return -1;
2937 idx = SUBPAGE_IDX(start);
2938 eidx = SUBPAGE_IDX(end);
2939#if defined(DEBUG_SUBPAGE)
2940 printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %d\n", __func__,
2941 mmio, start, end, idx, eidx, memory);
2942#endif
2943 memory >>= IO_MEM_SHIFT;
2944 for (; idx <= eidx; idx++) {
blueswir14254fab2008-01-01 16:57:19 +00002945 for (i = 0; i < 4; i++) {
blueswir13ee89922008-01-02 19:45:26 +00002946 if (io_mem_read[memory][i]) {
2947 mmio->mem_read[idx][i] = &io_mem_read[memory][i];
2948 mmio->opaque[idx][0][i] = io_mem_opaque[memory];
pbrook8da3ff12008-12-01 18:59:50 +00002949 mmio->region_offset[idx][0][i] = region_offset;
blueswir13ee89922008-01-02 19:45:26 +00002950 }
2951 if (io_mem_write[memory][i]) {
2952 mmio->mem_write[idx][i] = &io_mem_write[memory][i];
2953 mmio->opaque[idx][1][i] = io_mem_opaque[memory];
pbrook8da3ff12008-12-01 18:59:50 +00002954 mmio->region_offset[idx][1][i] = region_offset;
blueswir13ee89922008-01-02 19:45:26 +00002955 }
blueswir14254fab2008-01-01 16:57:19 +00002956 }
blueswir1db7b5422007-05-26 17:36:03 +00002957 }
2958
2959 return 0;
2960}
2961
aurel3200f82b82008-04-27 21:12:55 +00002962static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
pbrook8da3ff12008-12-01 18:59:50 +00002963 ram_addr_t orig_memory, ram_addr_t region_offset)
blueswir1db7b5422007-05-26 17:36:03 +00002964{
2965 subpage_t *mmio;
2966 int subpage_memory;
2967
2968 mmio = qemu_mallocz(sizeof(subpage_t));
aliguori1eec6142009-02-05 22:06:18 +00002969
2970 mmio->base = base;
Avi Kivity1eed09c2009-06-14 11:38:51 +03002971 subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
blueswir1db7b5422007-05-26 17:36:03 +00002972#if defined(DEBUG_SUBPAGE)
aliguori1eec6142009-02-05 22:06:18 +00002973 printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
2974 mmio, base, TARGET_PAGE_SIZE, subpage_memory);
blueswir1db7b5422007-05-26 17:36:03 +00002975#endif
aliguori1eec6142009-02-05 22:06:18 +00002976 *phys = subpage_memory | IO_MEM_SUBPAGE;
2977 subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
pbrook8da3ff12008-12-01 18:59:50 +00002978 region_offset);
blueswir1db7b5422007-05-26 17:36:03 +00002979
2980 return mmio;
2981}
2982
aliguori88715652009-02-11 15:20:58 +00002983static int get_free_io_mem_idx(void)
2984{
2985 int i;
2986
2987 for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
2988 if (!io_mem_used[i]) {
2989 io_mem_used[i] = 1;
2990 return i;
2991 }
2992
2993 return -1;
2994}
2995
bellard33417e72003-08-10 21:47:01 +00002996/* mem_read and mem_write are arrays of functions containing the
2997 function to access byte (index 0), word (index 1) and dword (index
Paul Brook0b4e6e32009-04-30 18:37:55 +01002998 2). Functions can be omitted with a NULL function pointer.
blueswir13ee89922008-01-02 19:45:26 +00002999 If io_index is non zero, the corresponding io zone is
blueswir14254fab2008-01-01 16:57:19 +00003000 modified. If it is zero, a new io zone is allocated. The return
3001 value can be used with cpu_register_physical_memory(). (-1) is
3002 returned if error. */
Avi Kivity1eed09c2009-06-14 11:38:51 +03003003static int cpu_register_io_memory_fixed(int io_index,
3004 CPUReadMemoryFunc **mem_read,
3005 CPUWriteMemoryFunc **mem_write,
3006 void *opaque)
bellard33417e72003-08-10 21:47:01 +00003007{
blueswir14254fab2008-01-01 16:57:19 +00003008 int i, subwidth = 0;
bellard33417e72003-08-10 21:47:01 +00003009
3010 if (io_index <= 0) {
aliguori88715652009-02-11 15:20:58 +00003011 io_index = get_free_io_mem_idx();
3012 if (io_index == -1)
3013 return io_index;
bellard33417e72003-08-10 21:47:01 +00003014 } else {
Avi Kivity1eed09c2009-06-14 11:38:51 +03003015 io_index >>= IO_MEM_SHIFT;
bellard33417e72003-08-10 21:47:01 +00003016 if (io_index >= IO_MEM_NB_ENTRIES)
3017 return -1;
3018 }
bellardb5ff1b32005-11-26 10:38:39 +00003019
bellard33417e72003-08-10 21:47:01 +00003020 for(i = 0;i < 3; i++) {
blueswir14254fab2008-01-01 16:57:19 +00003021 if (!mem_read[i] || !mem_write[i])
3022 subwidth = IO_MEM_SUBWIDTH;
bellard33417e72003-08-10 21:47:01 +00003023 io_mem_read[io_index][i] = mem_read[i];
3024 io_mem_write[io_index][i] = mem_write[i];
3025 }
bellarda4193c82004-06-03 14:01:43 +00003026 io_mem_opaque[io_index] = opaque;
blueswir14254fab2008-01-01 16:57:19 +00003027 return (io_index << IO_MEM_SHIFT) | subwidth;
bellard33417e72003-08-10 21:47:01 +00003028}
bellard61382a52003-10-27 21:22:23 +00003029
Avi Kivity1eed09c2009-06-14 11:38:51 +03003030int cpu_register_io_memory(CPUReadMemoryFunc **mem_read,
3031 CPUWriteMemoryFunc **mem_write,
3032 void *opaque)
3033{
3034 return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
3035}
3036
aliguori88715652009-02-11 15:20:58 +00003037void cpu_unregister_io_memory(int io_table_address)
3038{
3039 int i;
3040 int io_index = io_table_address >> IO_MEM_SHIFT;
3041
3042 for (i=0;i < 3; i++) {
3043 io_mem_read[io_index][i] = unassigned_mem_read[i];
3044 io_mem_write[io_index][i] = unassigned_mem_write[i];
3045 }
3046 io_mem_opaque[io_index] = NULL;
3047 io_mem_used[io_index] = 0;
3048}
3049
Avi Kivitye9179ce2009-06-14 11:38:52 +03003050static void io_mem_init(void)
3051{
3052 int i;
3053
3054 cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read, unassigned_mem_write, NULL);
3055 cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read, unassigned_mem_write, NULL);
3056 cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read, notdirty_mem_write, NULL);
3057 for (i=0; i<5; i++)
3058 io_mem_used[i] = 1;
3059
3060 io_mem_watch = cpu_register_io_memory(watch_mem_read,
3061 watch_mem_write, NULL);
3062#ifdef CONFIG_KQEMU
3063 if (kqemu_phys_ram_base) {
3064 /* alloc dirty bits array */
3065 phys_ram_dirty = qemu_vmalloc(kqemu_phys_ram_size >> TARGET_PAGE_BITS);
3066 memset(phys_ram_dirty, 0xff, kqemu_phys_ram_size >> TARGET_PAGE_BITS);
3067 }
3068#endif
3069}
3070
pbrooke2eef172008-06-08 01:09:01 +00003071#endif /* !defined(CONFIG_USER_ONLY) */
3072
bellard13eb76e2004-01-24 15:23:36 +00003073/* physical memory access (slow version, mainly for debug) */
3074#if defined(CONFIG_USER_ONLY)
ths5fafdf22007-09-16 21:08:06 +00003075void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
bellard13eb76e2004-01-24 15:23:36 +00003076 int len, int is_write)
3077{
3078 int l, flags;
3079 target_ulong page;
pbrook53a59602006-03-25 19:31:22 +00003080 void * p;
bellard13eb76e2004-01-24 15:23:36 +00003081
3082 while (len > 0) {
3083 page = addr & TARGET_PAGE_MASK;
3084 l = (page + TARGET_PAGE_SIZE) - addr;
3085 if (l > len)
3086 l = len;
3087 flags = page_get_flags(page);
3088 if (!(flags & PAGE_VALID))
3089 return;
3090 if (is_write) {
3091 if (!(flags & PAGE_WRITE))
3092 return;
bellard579a97f2007-11-11 14:26:47 +00003093 /* XXX: this code should not depend on lock_user */
aurel3272fb7da2008-04-27 23:53:45 +00003094 if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
bellard579a97f2007-11-11 14:26:47 +00003095 /* FIXME - should this return an error rather than just fail? */
3096 return;
aurel3272fb7da2008-04-27 23:53:45 +00003097 memcpy(p, buf, l);
3098 unlock_user(p, addr, l);
bellard13eb76e2004-01-24 15:23:36 +00003099 } else {
3100 if (!(flags & PAGE_READ))
3101 return;
bellard579a97f2007-11-11 14:26:47 +00003102 /* XXX: this code should not depend on lock_user */
aurel3272fb7da2008-04-27 23:53:45 +00003103 if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
bellard579a97f2007-11-11 14:26:47 +00003104 /* FIXME - should this return an error rather than just fail? */
3105 return;
aurel3272fb7da2008-04-27 23:53:45 +00003106 memcpy(buf, p, l);
aurel325b257572008-04-28 08:54:59 +00003107 unlock_user(p, addr, 0);
bellard13eb76e2004-01-24 15:23:36 +00003108 }
3109 len -= l;
3110 buf += l;
3111 addr += l;
3112 }
3113}
bellard8df1cd02005-01-28 22:37:22 +00003114
bellard13eb76e2004-01-24 15:23:36 +00003115#else
ths5fafdf22007-09-16 21:08:06 +00003116void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
bellard13eb76e2004-01-24 15:23:36 +00003117 int len, int is_write)
3118{
3119 int l, io_index;
3120 uint8_t *ptr;
3121 uint32_t val;
bellard2e126692004-04-25 21:28:44 +00003122 target_phys_addr_t page;
3123 unsigned long pd;
bellard92e873b2004-05-21 14:52:29 +00003124 PhysPageDesc *p;
ths3b46e622007-09-17 08:09:54 +00003125
bellard13eb76e2004-01-24 15:23:36 +00003126 while (len > 0) {
3127 page = addr & TARGET_PAGE_MASK;
3128 l = (page + TARGET_PAGE_SIZE) - addr;
3129 if (l > len)
3130 l = len;
bellard92e873b2004-05-21 14:52:29 +00003131 p = phys_page_find(page >> TARGET_PAGE_BITS);
bellard13eb76e2004-01-24 15:23:36 +00003132 if (!p) {
3133 pd = IO_MEM_UNASSIGNED;
3134 } else {
3135 pd = p->phys_offset;
3136 }
ths3b46e622007-09-17 08:09:54 +00003137
bellard13eb76e2004-01-24 15:23:36 +00003138 if (is_write) {
bellard3a7d9292005-08-21 09:26:42 +00003139 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
aurel326c2934d2009-02-18 21:37:17 +00003140 target_phys_addr_t addr1 = addr;
bellard13eb76e2004-01-24 15:23:36 +00003141 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
pbrook8da3ff12008-12-01 18:59:50 +00003142 if (p)
aurel326c2934d2009-02-18 21:37:17 +00003143 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
bellard6a00d602005-11-21 23:25:50 +00003144 /* XXX: could force cpu_single_env to NULL to avoid
3145 potential bugs */
aurel326c2934d2009-02-18 21:37:17 +00003146 if (l >= 4 && ((addr1 & 3) == 0)) {
bellard1c213d12005-09-03 10:49:04 +00003147 /* 32 bit write access */
bellardc27004e2005-01-03 23:35:10 +00003148 val = ldl_p(buf);
aurel326c2934d2009-02-18 21:37:17 +00003149 io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, val);
bellard13eb76e2004-01-24 15:23:36 +00003150 l = 4;
aurel326c2934d2009-02-18 21:37:17 +00003151 } else if (l >= 2 && ((addr1 & 1) == 0)) {
bellard1c213d12005-09-03 10:49:04 +00003152 /* 16 bit write access */
bellardc27004e2005-01-03 23:35:10 +00003153 val = lduw_p(buf);
aurel326c2934d2009-02-18 21:37:17 +00003154 io_mem_write[io_index][1](io_mem_opaque[io_index], addr1, val);
bellard13eb76e2004-01-24 15:23:36 +00003155 l = 2;
3156 } else {
bellard1c213d12005-09-03 10:49:04 +00003157 /* 8 bit write access */
bellardc27004e2005-01-03 23:35:10 +00003158 val = ldub_p(buf);
aurel326c2934d2009-02-18 21:37:17 +00003159 io_mem_write[io_index][0](io_mem_opaque[io_index], addr1, val);
bellard13eb76e2004-01-24 15:23:36 +00003160 l = 1;
3161 }
3162 } else {
bellardb448f2f2004-02-25 23:24:04 +00003163 unsigned long addr1;
3164 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
bellard13eb76e2004-01-24 15:23:36 +00003165 /* RAM case */
pbrook5579c7f2009-04-11 14:47:08 +00003166 ptr = qemu_get_ram_ptr(addr1);
bellard13eb76e2004-01-24 15:23:36 +00003167 memcpy(ptr, buf, l);
bellard3a7d9292005-08-21 09:26:42 +00003168 if (!cpu_physical_memory_is_dirty(addr1)) {
3169 /* invalidate code */
3170 tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
3171 /* set dirty bit */
ths5fafdf22007-09-16 21:08:06 +00003172 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
bellardf23db162005-08-21 19:12:28 +00003173 (0xff & ~CODE_DIRTY_FLAG);
bellard3a7d9292005-08-21 09:26:42 +00003174 }
bellard13eb76e2004-01-24 15:23:36 +00003175 }
3176 } else {
ths5fafdf22007-09-16 21:08:06 +00003177 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
bellard2a4188a2006-06-25 21:54:59 +00003178 !(pd & IO_MEM_ROMD)) {
aurel326c2934d2009-02-18 21:37:17 +00003179 target_phys_addr_t addr1 = addr;
bellard13eb76e2004-01-24 15:23:36 +00003180 /* I/O case */
3181 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
pbrook8da3ff12008-12-01 18:59:50 +00003182 if (p)
aurel326c2934d2009-02-18 21:37:17 +00003183 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3184 if (l >= 4 && ((addr1 & 3) == 0)) {
bellard13eb76e2004-01-24 15:23:36 +00003185 /* 32 bit read access */
aurel326c2934d2009-02-18 21:37:17 +00003186 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
bellardc27004e2005-01-03 23:35:10 +00003187 stl_p(buf, val);
bellard13eb76e2004-01-24 15:23:36 +00003188 l = 4;
aurel326c2934d2009-02-18 21:37:17 +00003189 } else if (l >= 2 && ((addr1 & 1) == 0)) {
bellard13eb76e2004-01-24 15:23:36 +00003190 /* 16 bit read access */
aurel326c2934d2009-02-18 21:37:17 +00003191 val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr1);
bellardc27004e2005-01-03 23:35:10 +00003192 stw_p(buf, val);
bellard13eb76e2004-01-24 15:23:36 +00003193 l = 2;
3194 } else {
bellard1c213d12005-09-03 10:49:04 +00003195 /* 8 bit read access */
aurel326c2934d2009-02-18 21:37:17 +00003196 val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr1);
bellardc27004e2005-01-03 23:35:10 +00003197 stb_p(buf, val);
bellard13eb76e2004-01-24 15:23:36 +00003198 l = 1;
3199 }
3200 } else {
3201 /* RAM case */
pbrook5579c7f2009-04-11 14:47:08 +00003202 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
bellard13eb76e2004-01-24 15:23:36 +00003203 (addr & ~TARGET_PAGE_MASK);
3204 memcpy(buf, ptr, l);
3205 }
3206 }
3207 len -= l;
3208 buf += l;
3209 addr += l;
3210 }
3211}
bellard8df1cd02005-01-28 22:37:22 +00003212
bellardd0ecd2a2006-04-23 17:14:48 +00003213/* used for ROM loading : can write in RAM and ROM */
ths5fafdf22007-09-16 21:08:06 +00003214void cpu_physical_memory_write_rom(target_phys_addr_t addr,
bellardd0ecd2a2006-04-23 17:14:48 +00003215 const uint8_t *buf, int len)
3216{
3217 int l;
3218 uint8_t *ptr;
3219 target_phys_addr_t page;
3220 unsigned long pd;
3221 PhysPageDesc *p;
ths3b46e622007-09-17 08:09:54 +00003222
bellardd0ecd2a2006-04-23 17:14:48 +00003223 while (len > 0) {
3224 page = addr & TARGET_PAGE_MASK;
3225 l = (page + TARGET_PAGE_SIZE) - addr;
3226 if (l > len)
3227 l = len;
3228 p = phys_page_find(page >> TARGET_PAGE_BITS);
3229 if (!p) {
3230 pd = IO_MEM_UNASSIGNED;
3231 } else {
3232 pd = p->phys_offset;
3233 }
ths3b46e622007-09-17 08:09:54 +00003234
bellardd0ecd2a2006-04-23 17:14:48 +00003235 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
bellard2a4188a2006-06-25 21:54:59 +00003236 (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
3237 !(pd & IO_MEM_ROMD)) {
bellardd0ecd2a2006-04-23 17:14:48 +00003238 /* do nothing */
3239 } else {
3240 unsigned long addr1;
3241 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3242 /* ROM/RAM case */
pbrook5579c7f2009-04-11 14:47:08 +00003243 ptr = qemu_get_ram_ptr(addr1);
bellardd0ecd2a2006-04-23 17:14:48 +00003244 memcpy(ptr, buf, l);
3245 }
3246 len -= l;
3247 buf += l;
3248 addr += l;
3249 }
3250}
3251
aliguori6d16c2f2009-01-22 16:59:11 +00003252typedef struct {
3253 void *buffer;
3254 target_phys_addr_t addr;
3255 target_phys_addr_t len;
3256} BounceBuffer;
3257
3258static BounceBuffer bounce;
3259
aliguoriba223c22009-01-22 16:59:16 +00003260typedef struct MapClient {
3261 void *opaque;
3262 void (*callback)(void *opaque);
3263 LIST_ENTRY(MapClient) link;
3264} MapClient;
3265
3266static LIST_HEAD(map_client_list, MapClient) map_client_list
3267 = LIST_HEAD_INITIALIZER(map_client_list);
3268
3269void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
3270{
3271 MapClient *client = qemu_malloc(sizeof(*client));
3272
3273 client->opaque = opaque;
3274 client->callback = callback;
3275 LIST_INSERT_HEAD(&map_client_list, client, link);
3276 return client;
3277}
3278
3279void cpu_unregister_map_client(void *_client)
3280{
3281 MapClient *client = (MapClient *)_client;
3282
3283 LIST_REMOVE(client, link);
Isaku Yamahata34d5e942009-06-26 18:57:18 +09003284 qemu_free(client);
aliguoriba223c22009-01-22 16:59:16 +00003285}
3286
3287static void cpu_notify_map_clients(void)
3288{
3289 MapClient *client;
3290
3291 while (!LIST_EMPTY(&map_client_list)) {
3292 client = LIST_FIRST(&map_client_list);
3293 client->callback(client->opaque);
Isaku Yamahata34d5e942009-06-26 18:57:18 +09003294 cpu_unregister_map_client(client);
aliguoriba223c22009-01-22 16:59:16 +00003295 }
3296}
3297
aliguori6d16c2f2009-01-22 16:59:11 +00003298/* Map a physical memory region into a host virtual address.
3299 * May map a subset of the requested range, given by and returned in *plen.
3300 * May return NULL if resources needed to perform the mapping are exhausted.
3301 * Use only for reads OR writes - not for read-modify-write operations.
aliguoriba223c22009-01-22 16:59:16 +00003302 * Use cpu_register_map_client() to know when retrying the map operation is
3303 * likely to succeed.
aliguori6d16c2f2009-01-22 16:59:11 +00003304 */
3305void *cpu_physical_memory_map(target_phys_addr_t addr,
3306 target_phys_addr_t *plen,
3307 int is_write)
3308{
3309 target_phys_addr_t len = *plen;
3310 target_phys_addr_t done = 0;
3311 int l;
3312 uint8_t *ret = NULL;
3313 uint8_t *ptr;
3314 target_phys_addr_t page;
3315 unsigned long pd;
3316 PhysPageDesc *p;
3317 unsigned long addr1;
3318
3319 while (len > 0) {
3320 page = addr & TARGET_PAGE_MASK;
3321 l = (page + TARGET_PAGE_SIZE) - addr;
3322 if (l > len)
3323 l = len;
3324 p = phys_page_find(page >> TARGET_PAGE_BITS);
3325 if (!p) {
3326 pd = IO_MEM_UNASSIGNED;
3327 } else {
3328 pd = p->phys_offset;
3329 }
3330
3331 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3332 if (done || bounce.buffer) {
3333 break;
3334 }
3335 bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
3336 bounce.addr = addr;
3337 bounce.len = l;
3338 if (!is_write) {
3339 cpu_physical_memory_rw(addr, bounce.buffer, l, 0);
3340 }
3341 ptr = bounce.buffer;
3342 } else {
3343 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
pbrook5579c7f2009-04-11 14:47:08 +00003344 ptr = qemu_get_ram_ptr(addr1);
aliguori6d16c2f2009-01-22 16:59:11 +00003345 }
3346 if (!done) {
3347 ret = ptr;
3348 } else if (ret + done != ptr) {
3349 break;
3350 }
3351
3352 len -= l;
3353 addr += l;
3354 done += l;
3355 }
3356 *plen = done;
3357 return ret;
3358}
3359
3360/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
3361 * Will also mark the memory as dirty if is_write == 1. access_len gives
3362 * the amount of memory that was actually read or written by the caller.
3363 */
3364void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
3365 int is_write, target_phys_addr_t access_len)
3366{
3367 if (buffer != bounce.buffer) {
3368 if (is_write) {
pbrook5579c7f2009-04-11 14:47:08 +00003369 ram_addr_t addr1 = qemu_ram_addr_from_host(buffer);
aliguori6d16c2f2009-01-22 16:59:11 +00003370 while (access_len) {
3371 unsigned l;
3372 l = TARGET_PAGE_SIZE;
3373 if (l > access_len)
3374 l = access_len;
3375 if (!cpu_physical_memory_is_dirty(addr1)) {
3376 /* invalidate code */
3377 tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
3378 /* set dirty bit */
3379 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3380 (0xff & ~CODE_DIRTY_FLAG);
3381 }
3382 addr1 += l;
3383 access_len -= l;
3384 }
3385 }
3386 return;
3387 }
3388 if (is_write) {
3389 cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
3390 }
3391 qemu_free(bounce.buffer);
3392 bounce.buffer = NULL;
aliguoriba223c22009-01-22 16:59:16 +00003393 cpu_notify_map_clients();
aliguori6d16c2f2009-01-22 16:59:11 +00003394}
bellardd0ecd2a2006-04-23 17:14:48 +00003395
bellard8df1cd02005-01-28 22:37:22 +00003396/* warning: addr must be aligned */
3397uint32_t ldl_phys(target_phys_addr_t addr)
3398{
3399 int io_index;
3400 uint8_t *ptr;
3401 uint32_t val;
3402 unsigned long pd;
3403 PhysPageDesc *p;
3404
3405 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3406 if (!p) {
3407 pd = IO_MEM_UNASSIGNED;
3408 } else {
3409 pd = p->phys_offset;
3410 }
ths3b46e622007-09-17 08:09:54 +00003411
ths5fafdf22007-09-16 21:08:06 +00003412 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
bellard2a4188a2006-06-25 21:54:59 +00003413 !(pd & IO_MEM_ROMD)) {
bellard8df1cd02005-01-28 22:37:22 +00003414 /* I/O case */
3415 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
pbrook8da3ff12008-12-01 18:59:50 +00003416 if (p)
3417 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
bellard8df1cd02005-01-28 22:37:22 +00003418 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3419 } else {
3420 /* RAM case */
pbrook5579c7f2009-04-11 14:47:08 +00003421 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
bellard8df1cd02005-01-28 22:37:22 +00003422 (addr & ~TARGET_PAGE_MASK);
3423 val = ldl_p(ptr);
3424 }
3425 return val;
3426}
3427
bellard84b7b8e2005-11-28 21:19:04 +00003428/* warning: addr must be aligned */
3429uint64_t ldq_phys(target_phys_addr_t addr)
3430{
3431 int io_index;
3432 uint8_t *ptr;
3433 uint64_t val;
3434 unsigned long pd;
3435 PhysPageDesc *p;
3436
3437 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3438 if (!p) {
3439 pd = IO_MEM_UNASSIGNED;
3440 } else {
3441 pd = p->phys_offset;
3442 }
ths3b46e622007-09-17 08:09:54 +00003443
bellard2a4188a2006-06-25 21:54:59 +00003444 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3445 !(pd & IO_MEM_ROMD)) {
bellard84b7b8e2005-11-28 21:19:04 +00003446 /* I/O case */
3447 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
pbrook8da3ff12008-12-01 18:59:50 +00003448 if (p)
3449 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
bellard84b7b8e2005-11-28 21:19:04 +00003450#ifdef TARGET_WORDS_BIGENDIAN
3451 val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
3452 val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
3453#else
3454 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3455 val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
3456#endif
3457 } else {
3458 /* RAM case */
pbrook5579c7f2009-04-11 14:47:08 +00003459 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
bellard84b7b8e2005-11-28 21:19:04 +00003460 (addr & ~TARGET_PAGE_MASK);
3461 val = ldq_p(ptr);
3462 }
3463 return val;
3464}
3465
bellardaab33092005-10-30 20:48:42 +00003466/* XXX: optimize */
3467uint32_t ldub_phys(target_phys_addr_t addr)
3468{
3469 uint8_t val;
3470 cpu_physical_memory_read(addr, &val, 1);
3471 return val;
3472}
3473
3474/* XXX: optimize */
3475uint32_t lduw_phys(target_phys_addr_t addr)
3476{
3477 uint16_t val;
3478 cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
3479 return tswap16(val);
3480}
3481
bellard8df1cd02005-01-28 22:37:22 +00003482/* warning: addr must be aligned. The ram page is not masked as dirty
3483 and the code inside is not invalidated. It is useful if the dirty
3484 bits are used to track modified PTEs */
3485void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
3486{
3487 int io_index;
3488 uint8_t *ptr;
3489 unsigned long pd;
3490 PhysPageDesc *p;
3491
3492 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3493 if (!p) {
3494 pd = IO_MEM_UNASSIGNED;
3495 } else {
3496 pd = p->phys_offset;
3497 }
ths3b46e622007-09-17 08:09:54 +00003498
bellard3a7d9292005-08-21 09:26:42 +00003499 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
bellard8df1cd02005-01-28 22:37:22 +00003500 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
pbrook8da3ff12008-12-01 18:59:50 +00003501 if (p)
3502 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
bellard8df1cd02005-01-28 22:37:22 +00003503 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3504 } else {
aliguori74576192008-10-06 14:02:03 +00003505 unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
pbrook5579c7f2009-04-11 14:47:08 +00003506 ptr = qemu_get_ram_ptr(addr1);
bellard8df1cd02005-01-28 22:37:22 +00003507 stl_p(ptr, val);
aliguori74576192008-10-06 14:02:03 +00003508
3509 if (unlikely(in_migration)) {
3510 if (!cpu_physical_memory_is_dirty(addr1)) {
3511 /* invalidate code */
3512 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3513 /* set dirty bit */
3514 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3515 (0xff & ~CODE_DIRTY_FLAG);
3516 }
3517 }
bellard8df1cd02005-01-28 22:37:22 +00003518 }
3519}
3520
j_mayerbc98a7e2007-04-04 07:55:12 +00003521void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
3522{
3523 int io_index;
3524 uint8_t *ptr;
3525 unsigned long pd;
3526 PhysPageDesc *p;
3527
3528 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3529 if (!p) {
3530 pd = IO_MEM_UNASSIGNED;
3531 } else {
3532 pd = p->phys_offset;
3533 }
ths3b46e622007-09-17 08:09:54 +00003534
j_mayerbc98a7e2007-04-04 07:55:12 +00003535 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3536 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
pbrook8da3ff12008-12-01 18:59:50 +00003537 if (p)
3538 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
j_mayerbc98a7e2007-04-04 07:55:12 +00003539#ifdef TARGET_WORDS_BIGENDIAN
3540 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
3541 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
3542#else
3543 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3544 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
3545#endif
3546 } else {
pbrook5579c7f2009-04-11 14:47:08 +00003547 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
j_mayerbc98a7e2007-04-04 07:55:12 +00003548 (addr & ~TARGET_PAGE_MASK);
3549 stq_p(ptr, val);
3550 }
3551}
3552
bellard8df1cd02005-01-28 22:37:22 +00003553/* warning: addr must be aligned */
bellard8df1cd02005-01-28 22:37:22 +00003554void stl_phys(target_phys_addr_t addr, uint32_t val)
3555{
3556 int io_index;
3557 uint8_t *ptr;
3558 unsigned long pd;
3559 PhysPageDesc *p;
3560
3561 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3562 if (!p) {
3563 pd = IO_MEM_UNASSIGNED;
3564 } else {
3565 pd = p->phys_offset;
3566 }
ths3b46e622007-09-17 08:09:54 +00003567
bellard3a7d9292005-08-21 09:26:42 +00003568 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
bellard8df1cd02005-01-28 22:37:22 +00003569 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
pbrook8da3ff12008-12-01 18:59:50 +00003570 if (p)
3571 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
bellard8df1cd02005-01-28 22:37:22 +00003572 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3573 } else {
3574 unsigned long addr1;
3575 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3576 /* RAM case */
pbrook5579c7f2009-04-11 14:47:08 +00003577 ptr = qemu_get_ram_ptr(addr1);
bellard8df1cd02005-01-28 22:37:22 +00003578 stl_p(ptr, val);
bellard3a7d9292005-08-21 09:26:42 +00003579 if (!cpu_physical_memory_is_dirty(addr1)) {
3580 /* invalidate code */
3581 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3582 /* set dirty bit */
bellardf23db162005-08-21 19:12:28 +00003583 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3584 (0xff & ~CODE_DIRTY_FLAG);
bellard3a7d9292005-08-21 09:26:42 +00003585 }
bellard8df1cd02005-01-28 22:37:22 +00003586 }
3587}
3588
bellardaab33092005-10-30 20:48:42 +00003589/* XXX: optimize */
3590void stb_phys(target_phys_addr_t addr, uint32_t val)
3591{
3592 uint8_t v = val;
3593 cpu_physical_memory_write(addr, &v, 1);
3594}
3595
3596/* XXX: optimize */
3597void stw_phys(target_phys_addr_t addr, uint32_t val)
3598{
3599 uint16_t v = tswap16(val);
3600 cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
3601}
3602
3603/* XXX: optimize */
3604void stq_phys(target_phys_addr_t addr, uint64_t val)
3605{
3606 val = tswap64(val);
3607 cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
3608}
3609
bellard13eb76e2004-01-24 15:23:36 +00003610#endif
3611
aliguori5e2972f2009-03-28 17:51:36 +00003612/* virtual memory access for debug (includes writing to ROM) */
ths5fafdf22007-09-16 21:08:06 +00003613int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
bellardb448f2f2004-02-25 23:24:04 +00003614 uint8_t *buf, int len, int is_write)
bellard13eb76e2004-01-24 15:23:36 +00003615{
3616 int l;
j_mayer9b3c35e2007-04-07 11:21:28 +00003617 target_phys_addr_t phys_addr;
3618 target_ulong page;
bellard13eb76e2004-01-24 15:23:36 +00003619
3620 while (len > 0) {
3621 page = addr & TARGET_PAGE_MASK;
3622 phys_addr = cpu_get_phys_page_debug(env, page);
3623 /* if no physical page mapped, return an error */
3624 if (phys_addr == -1)
3625 return -1;
3626 l = (page + TARGET_PAGE_SIZE) - addr;
3627 if (l > len)
3628 l = len;
aliguori5e2972f2009-03-28 17:51:36 +00003629 phys_addr += (addr & ~TARGET_PAGE_MASK);
3630#if !defined(CONFIG_USER_ONLY)
3631 if (is_write)
3632 cpu_physical_memory_write_rom(phys_addr, buf, l);
3633 else
3634#endif
3635 cpu_physical_memory_rw(phys_addr, buf, l, is_write);
bellard13eb76e2004-01-24 15:23:36 +00003636 len -= l;
3637 buf += l;
3638 addr += l;
3639 }
3640 return 0;
3641}
3642
pbrook2e70f6e2008-06-29 01:03:05 +00003643/* in deterministic execution mode, instructions doing device I/Os
3644 must be at the end of the TB */
3645void cpu_io_recompile(CPUState *env, void *retaddr)
3646{
3647 TranslationBlock *tb;
3648 uint32_t n, cflags;
3649 target_ulong pc, cs_base;
3650 uint64_t flags;
3651
3652 tb = tb_find_pc((unsigned long)retaddr);
3653 if (!tb) {
3654 cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p",
3655 retaddr);
3656 }
3657 n = env->icount_decr.u16.low + tb->icount;
3658 cpu_restore_state(tb, env, (unsigned long)retaddr, NULL);
3659 /* Calculate how many instructions had been executed before the fault
thsbf20dc02008-06-30 17:22:19 +00003660 occurred. */
pbrook2e70f6e2008-06-29 01:03:05 +00003661 n = n - env->icount_decr.u16.low;
3662 /* Generate a new TB ending on the I/O insn. */
3663 n++;
3664 /* On MIPS and SH, delay slot instructions can only be restarted if
3665 they were already the first instruction in the TB. If this is not
thsbf20dc02008-06-30 17:22:19 +00003666 the first instruction in a TB then re-execute the preceding
pbrook2e70f6e2008-06-29 01:03:05 +00003667 branch. */
3668#if defined(TARGET_MIPS)
3669 if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) {
3670 env->active_tc.PC -= 4;
3671 env->icount_decr.u16.low++;
3672 env->hflags &= ~MIPS_HFLAG_BMASK;
3673 }
3674#elif defined(TARGET_SH4)
3675 if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
3676 && n > 1) {
3677 env->pc -= 2;
3678 env->icount_decr.u16.low++;
3679 env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
3680 }
3681#endif
3682 /* This should never happen. */
3683 if (n > CF_COUNT_MASK)
3684 cpu_abort(env, "TB too big during recompile");
3685
3686 cflags = n | CF_LAST_IO;
3687 pc = tb->pc;
3688 cs_base = tb->cs_base;
3689 flags = tb->flags;
3690 tb_phys_invalidate(tb, -1);
3691 /* FIXME: In theory this could raise an exception. In practice
3692 we have already translated the block once so it's probably ok. */
3693 tb_gen_code(env, pc, cs_base, flags, cflags);
thsbf20dc02008-06-30 17:22:19 +00003694 /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
pbrook2e70f6e2008-06-29 01:03:05 +00003695 the first in the TB) then we end up generating a whole new TB and
3696 repeating the fault, which is horribly inefficient.
3697 Better would be to execute just this insn uncached, or generate a
3698 second new TB. */
3699 cpu_resume_from_signal(env, NULL);
3700}
3701
bellarde3db7222005-01-26 22:00:47 +00003702void dump_exec_info(FILE *f,
3703 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
3704{
3705 int i, target_code_size, max_target_code_size;
3706 int direct_jmp_count, direct_jmp2_count, cross_page;
3707 TranslationBlock *tb;
ths3b46e622007-09-17 08:09:54 +00003708
bellarde3db7222005-01-26 22:00:47 +00003709 target_code_size = 0;
3710 max_target_code_size = 0;
3711 cross_page = 0;
3712 direct_jmp_count = 0;
3713 direct_jmp2_count = 0;
3714 for(i = 0; i < nb_tbs; i++) {
3715 tb = &tbs[i];
3716 target_code_size += tb->size;
3717 if (tb->size > max_target_code_size)
3718 max_target_code_size = tb->size;
3719 if (tb->page_addr[1] != -1)
3720 cross_page++;
3721 if (tb->tb_next_offset[0] != 0xffff) {
3722 direct_jmp_count++;
3723 if (tb->tb_next_offset[1] != 0xffff) {
3724 direct_jmp2_count++;
3725 }
3726 }
3727 }
3728 /* XXX: avoid using doubles ? */
bellard57fec1f2008-02-01 10:50:11 +00003729 cpu_fprintf(f, "Translation buffer state:\n");
bellard26a5f132008-05-28 12:30:31 +00003730 cpu_fprintf(f, "gen code size %ld/%ld\n",
3731 code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size);
3732 cpu_fprintf(f, "TB count %d/%d\n",
3733 nb_tbs, code_gen_max_blocks);
ths5fafdf22007-09-16 21:08:06 +00003734 cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
bellarde3db7222005-01-26 22:00:47 +00003735 nb_tbs ? target_code_size / nb_tbs : 0,
3736 max_target_code_size);
ths5fafdf22007-09-16 21:08:06 +00003737 cpu_fprintf(f, "TB avg host size %d bytes (expansion ratio: %0.1f)\n",
bellarde3db7222005-01-26 22:00:47 +00003738 nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
3739 target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
ths5fafdf22007-09-16 21:08:06 +00003740 cpu_fprintf(f, "cross page TB count %d (%d%%)\n",
3741 cross_page,
bellarde3db7222005-01-26 22:00:47 +00003742 nb_tbs ? (cross_page * 100) / nb_tbs : 0);
3743 cpu_fprintf(f, "direct jump count %d (%d%%) (2 jumps=%d %d%%)\n",
ths5fafdf22007-09-16 21:08:06 +00003744 direct_jmp_count,
bellarde3db7222005-01-26 22:00:47 +00003745 nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
3746 direct_jmp2_count,
3747 nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
bellard57fec1f2008-02-01 10:50:11 +00003748 cpu_fprintf(f, "\nStatistics:\n");
bellarde3db7222005-01-26 22:00:47 +00003749 cpu_fprintf(f, "TB flush count %d\n", tb_flush_count);
3750 cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
3751 cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count);
bellardb67d9a52008-05-23 09:57:34 +00003752 tcg_dump_info(f, cpu_fprintf);
bellarde3db7222005-01-26 22:00:47 +00003753}
3754
ths5fafdf22007-09-16 21:08:06 +00003755#if !defined(CONFIG_USER_ONLY)
bellard61382a52003-10-27 21:22:23 +00003756
3757#define MMUSUFFIX _cmmu
3758#define GETPC() NULL
3759#define env cpu_single_env
bellardb769d8f2004-10-03 15:07:13 +00003760#define SOFTMMU_CODE_ACCESS
bellard61382a52003-10-27 21:22:23 +00003761
3762#define SHIFT 0
3763#include "softmmu_template.h"
3764
3765#define SHIFT 1
3766#include "softmmu_template.h"
3767
3768#define SHIFT 2
3769#include "softmmu_template.h"
3770
3771#define SHIFT 3
3772#include "softmmu_template.h"
3773
3774#undef env
3775
3776#endif