blob: fa5b619cab2b3588d1f2dee4ea612778177ecec0 [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
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
bellard54936002003-05-13 00:25:15 +000018 */
bellard67b915a2004-03-31 23:37:16 +000019#include "config.h"
bellardd5a8f072004-09-29 21:15:28 +000020#ifdef _WIN32
21#include <windows.h>
22#else
bellarda98d49b2004-11-14 16:22:05 +000023#include <sys/types.h>
bellardd5a8f072004-09-29 21:15:28 +000024#include <sys/mman.h>
25#endif
bellard54936002003-05-13 00:25:15 +000026#include <stdlib.h>
27#include <stdio.h>
28#include <stdarg.h>
29#include <string.h>
30#include <errno.h>
31#include <unistd.h>
32#include <inttypes.h>
33
bellard6180a182003-09-30 21:04:53 +000034#include "cpu.h"
35#include "exec-all.h"
aurel32ca10f862008-04-11 21:35:42 +000036#include "qemu-common.h"
bellardb67d9a52008-05-23 09:57:34 +000037#include "tcg.h"
pbrookb3c77242008-06-30 16:31:04 +000038#include "hw/hw.h"
aliguori74576192008-10-06 14:02:03 +000039#include "osdep.h"
aliguori7ba1e612008-11-05 16:04:33 +000040#include "kvm.h"
pbrook53a59602006-03-25 19:31:22 +000041#if defined(CONFIG_USER_ONLY)
42#include <qemu.h>
43#endif
bellard54936002003-05-13 00:25:15 +000044
bellardfd6ce8f2003-05-14 19:00:11 +000045//#define DEBUG_TB_INVALIDATE
bellard66e85a22003-06-24 13:28:12 +000046//#define DEBUG_FLUSH
bellard9fa3e852004-01-04 18:06:42 +000047//#define DEBUG_TLB
pbrook67d3b952006-12-18 05:03:52 +000048//#define DEBUG_UNASSIGNED
bellardfd6ce8f2003-05-14 19:00:11 +000049
50/* make various TB consistency checks */
ths5fafdf22007-09-16 21:08:06 +000051//#define DEBUG_TB_CHECK
52//#define DEBUG_TLB_CHECK
bellardfd6ce8f2003-05-14 19:00:11 +000053
ths1196be32007-03-17 15:17:58 +000054//#define DEBUG_IOPORT
blueswir1db7b5422007-05-26 17:36:03 +000055//#define DEBUG_SUBPAGE
ths1196be32007-03-17 15:17:58 +000056
pbrook99773bd2006-04-16 15:14:59 +000057#if !defined(CONFIG_USER_ONLY)
58/* TB consistency checks only implemented for usermode emulation. */
59#undef DEBUG_TB_CHECK
60#endif
61
bellard9fa3e852004-01-04 18:06:42 +000062#define SMC_BITMAP_USE_THRESHOLD 10
63
bellard108c49b2005-07-24 12:55:09 +000064#if defined(TARGET_SPARC64)
65#define TARGET_PHYS_ADDR_SPACE_BITS 41
blueswir15dcb6b92007-05-19 12:58:30 +000066#elif defined(TARGET_SPARC)
67#define TARGET_PHYS_ADDR_SPACE_BITS 36
j_mayerbedb69e2007-04-05 20:08:21 +000068#elif defined(TARGET_ALPHA)
69#define TARGET_PHYS_ADDR_SPACE_BITS 42
70#define TARGET_VIRT_ADDR_SPACE_BITS 42
bellard108c49b2005-07-24 12:55:09 +000071#elif defined(TARGET_PPC64)
72#define TARGET_PHYS_ADDR_SPACE_BITS 42
blueswir1640f42e2009-04-19 10:18:01 +000073#elif defined(TARGET_X86_64) && !defined(CONFIG_KQEMU)
aurel3200f82b82008-04-27 21:12:55 +000074#define TARGET_PHYS_ADDR_SPACE_BITS 42
blueswir1640f42e2009-04-19 10:18:01 +000075#elif defined(TARGET_I386) && !defined(CONFIG_KQEMU)
aurel3200f82b82008-04-27 21:12:55 +000076#define TARGET_PHYS_ADDR_SPACE_BITS 36
bellard108c49b2005-07-24 12:55:09 +000077#else
78/* Note: for compatibility with kqemu, we use 32 bits for x86_64 */
79#define TARGET_PHYS_ADDR_SPACE_BITS 32
80#endif
81
blueswir1bdaf78e2008-10-04 07:24:27 +000082static TranslationBlock *tbs;
bellard26a5f132008-05-28 12:30:31 +000083int code_gen_max_blocks;
bellard9fa3e852004-01-04 18:06:42 +000084TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
blueswir1bdaf78e2008-10-04 07:24:27 +000085static int nb_tbs;
bellardeb51d102003-05-14 21:51:13 +000086/* any access to the tbs or the page table must use this lock */
87spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
bellardfd6ce8f2003-05-14 19:00:11 +000088
blueswir1141ac462008-07-26 15:05:57 +000089#if defined(__arm__) || defined(__sparc_v9__)
90/* The prologue must be reachable with a direct jump. ARM and Sparc64
91 have limited branch ranges (possibly also PPC) so place it in a
blueswir1d03d8602008-07-10 17:21:31 +000092 section close to code segment. */
93#define code_gen_section \
94 __attribute__((__section__(".gen_code"))) \
95 __attribute__((aligned (32)))
Stefan Weilf8e2af12009-06-18 23:04:48 +020096#elif defined(_WIN32)
97/* Maximum alignment for Win32 is 16. */
98#define code_gen_section \
99 __attribute__((aligned (16)))
blueswir1d03d8602008-07-10 17:21:31 +0000100#else
101#define code_gen_section \
102 __attribute__((aligned (32)))
103#endif
104
105uint8_t code_gen_prologue[1024] code_gen_section;
blueswir1bdaf78e2008-10-04 07:24:27 +0000106static uint8_t *code_gen_buffer;
107static unsigned long code_gen_buffer_size;
bellard26a5f132008-05-28 12:30:31 +0000108/* threshold to flush the translated code buffer */
blueswir1bdaf78e2008-10-04 07:24:27 +0000109static unsigned long code_gen_buffer_max_size;
bellardfd6ce8f2003-05-14 19:00:11 +0000110uint8_t *code_gen_ptr;
111
pbrooke2eef172008-06-08 01:09:01 +0000112#if !defined(CONFIG_USER_ONLY)
bellard9fa3e852004-01-04 18:06:42 +0000113int phys_ram_fd;
bellard1ccde1c2004-02-06 19:46:14 +0000114uint8_t *phys_ram_dirty;
aliguori74576192008-10-06 14:02:03 +0000115static int in_migration;
pbrook94a6b542009-04-11 17:15:54 +0000116
117typedef struct RAMBlock {
118 uint8_t *host;
119 ram_addr_t offset;
120 ram_addr_t length;
121 struct RAMBlock *next;
122} RAMBlock;
123
124static RAMBlock *ram_blocks;
125/* TODO: When we implement (and use) ram deallocation (e.g. for hotplug)
Stuart Bradyccbb4d42009-05-03 12:15:06 +0100126 then we can no longer assume contiguous ram offsets, and external uses
pbrook94a6b542009-04-11 17:15:54 +0000127 of this variable will break. */
128ram_addr_t last_ram_offset;
pbrooke2eef172008-06-08 01:09:01 +0000129#endif
bellard9fa3e852004-01-04 18:06:42 +0000130
bellard6a00d602005-11-21 23:25:50 +0000131CPUState *first_cpu;
132/* current CPU in the current thread. It is only valid inside
133 cpu_exec() */
ths5fafdf22007-09-16 21:08:06 +0000134CPUState *cpu_single_env;
pbrook2e70f6e2008-06-29 01:03:05 +0000135/* 0 = Do not count executed instructions.
thsbf20dc02008-06-30 17:22:19 +0000136 1 = Precise instruction counting.
pbrook2e70f6e2008-06-29 01:03:05 +0000137 2 = Adaptive rate instruction counting. */
138int use_icount = 0;
139/* Current instruction counter. While executing translated code this may
140 include some instructions that have not yet been executed. */
141int64_t qemu_icount;
bellard6a00d602005-11-21 23:25:50 +0000142
bellard54936002003-05-13 00:25:15 +0000143typedef struct PageDesc {
bellard92e873b2004-05-21 14:52:29 +0000144 /* list of TBs intersecting this ram page */
bellardfd6ce8f2003-05-14 19:00:11 +0000145 TranslationBlock *first_tb;
bellard9fa3e852004-01-04 18:06:42 +0000146 /* in order to optimize self modifying code, we count the number
147 of lookups we do to a given page to use a bitmap */
148 unsigned int code_write_count;
149 uint8_t *code_bitmap;
150#if defined(CONFIG_USER_ONLY)
151 unsigned long flags;
152#endif
bellard54936002003-05-13 00:25:15 +0000153} PageDesc;
154
bellard92e873b2004-05-21 14:52:29 +0000155typedef struct PhysPageDesc {
pbrook0f459d12008-06-09 00:20:13 +0000156 /* offset in host memory of the page + io_index in the low bits */
aurel3200f82b82008-04-27 21:12:55 +0000157 ram_addr_t phys_offset;
pbrook8da3ff12008-12-01 18:59:50 +0000158 ram_addr_t region_offset;
bellard92e873b2004-05-21 14:52:29 +0000159} PhysPageDesc;
160
bellard54936002003-05-13 00:25:15 +0000161#define L2_BITS 10
j_mayerbedb69e2007-04-05 20:08:21 +0000162#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
163/* XXX: this is a temporary hack for alpha target.
164 * In the future, this is to be replaced by a multi-level table
165 * to actually be able to handle the complete 64 bits address space.
166 */
167#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
168#else
aurel3203875442008-04-22 20:45:18 +0000169#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
j_mayerbedb69e2007-04-05 20:08:21 +0000170#endif
bellard54936002003-05-13 00:25:15 +0000171
172#define L1_SIZE (1 << L1_BITS)
173#define L2_SIZE (1 << L2_BITS)
174
bellard83fb7ad2004-07-05 21:25:26 +0000175unsigned long qemu_real_host_page_size;
176unsigned long qemu_host_page_bits;
177unsigned long qemu_host_page_size;
178unsigned long qemu_host_page_mask;
bellard54936002003-05-13 00:25:15 +0000179
bellard92e873b2004-05-21 14:52:29 +0000180/* XXX: for system emulation, it could just be an array */
bellard54936002003-05-13 00:25:15 +0000181static PageDesc *l1_map[L1_SIZE];
blueswir1bdaf78e2008-10-04 07:24:27 +0000182static PhysPageDesc **l1_phys_map;
bellard54936002003-05-13 00:25:15 +0000183
pbrooke2eef172008-06-08 01:09:01 +0000184#if !defined(CONFIG_USER_ONLY)
185static void io_mem_init(void);
186
bellard33417e72003-08-10 21:47:01 +0000187/* io memory support */
bellard33417e72003-08-10 21:47:01 +0000188CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
189CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
bellarda4193c82004-06-03 14:01:43 +0000190void *io_mem_opaque[IO_MEM_NB_ENTRIES];
blueswir1511d2b12009-03-07 15:32:56 +0000191static char io_mem_used[IO_MEM_NB_ENTRIES];
pbrook6658ffb2007-03-16 23:58:11 +0000192static int io_mem_watch;
193#endif
bellard33417e72003-08-10 21:47:01 +0000194
bellard34865132003-10-05 14:28:56 +0000195/* log support */
blueswir1d9b630f2008-10-05 09:57:08 +0000196static const char *logfilename = "/tmp/qemu.log";
bellard34865132003-10-05 14:28:56 +0000197FILE *logfile;
198int loglevel;
pbrooke735b912007-06-30 13:53:24 +0000199static int log_append = 0;
bellard34865132003-10-05 14:28:56 +0000200
bellarde3db7222005-01-26 22:00:47 +0000201/* statistics */
202static int tlb_flush_count;
203static int tb_flush_count;
204static int tb_phys_invalidate_count;
205
blueswir1db7b5422007-05-26 17:36:03 +0000206#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
207typedef struct subpage_t {
208 target_phys_addr_t base;
blueswir13ee89922008-01-02 19:45:26 +0000209 CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE][4];
210 CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE][4];
211 void *opaque[TARGET_PAGE_SIZE][2][4];
pbrook8da3ff12008-12-01 18:59:50 +0000212 ram_addr_t region_offset[TARGET_PAGE_SIZE][2][4];
blueswir1db7b5422007-05-26 17:36:03 +0000213} subpage_t;
214
bellard7cb69ca2008-05-10 10:55:51 +0000215#ifdef _WIN32
216static void map_exec(void *addr, long size)
217{
218 DWORD old_protect;
219 VirtualProtect(addr, size,
220 PAGE_EXECUTE_READWRITE, &old_protect);
221
222}
223#else
224static void map_exec(void *addr, long size)
225{
bellard43694152008-05-29 09:35:57 +0000226 unsigned long start, end, page_size;
bellard7cb69ca2008-05-10 10:55:51 +0000227
bellard43694152008-05-29 09:35:57 +0000228 page_size = getpagesize();
bellard7cb69ca2008-05-10 10:55:51 +0000229 start = (unsigned long)addr;
bellard43694152008-05-29 09:35:57 +0000230 start &= ~(page_size - 1);
bellard7cb69ca2008-05-10 10:55:51 +0000231
232 end = (unsigned long)addr + size;
bellard43694152008-05-29 09:35:57 +0000233 end += page_size - 1;
234 end &= ~(page_size - 1);
bellard7cb69ca2008-05-10 10:55:51 +0000235
236 mprotect((void *)start, end - start,
237 PROT_READ | PROT_WRITE | PROT_EXEC);
238}
239#endif
240
bellardb346ff42003-06-15 20:05:50 +0000241static void page_init(void)
bellard54936002003-05-13 00:25:15 +0000242{
bellard83fb7ad2004-07-05 21:25:26 +0000243 /* NOTE: we can always suppose that qemu_host_page_size >=
bellard54936002003-05-13 00:25:15 +0000244 TARGET_PAGE_SIZE */
aliguoric2b48b62008-11-11 22:06:42 +0000245#ifdef _WIN32
246 {
247 SYSTEM_INFO system_info;
248
249 GetSystemInfo(&system_info);
250 qemu_real_host_page_size = system_info.dwPageSize;
251 }
252#else
253 qemu_real_host_page_size = getpagesize();
254#endif
bellard83fb7ad2004-07-05 21:25:26 +0000255 if (qemu_host_page_size == 0)
256 qemu_host_page_size = qemu_real_host_page_size;
257 if (qemu_host_page_size < TARGET_PAGE_SIZE)
258 qemu_host_page_size = TARGET_PAGE_SIZE;
259 qemu_host_page_bits = 0;
260 while ((1 << qemu_host_page_bits) < qemu_host_page_size)
261 qemu_host_page_bits++;
262 qemu_host_page_mask = ~(qemu_host_page_size - 1);
bellard108c49b2005-07-24 12:55:09 +0000263 l1_phys_map = qemu_vmalloc(L1_SIZE * sizeof(void *));
264 memset(l1_phys_map, 0, L1_SIZE * sizeof(void *));
balrog50a95692007-12-12 01:16:23 +0000265
266#if !defined(_WIN32) && defined(CONFIG_USER_ONLY)
267 {
268 long long startaddr, endaddr;
269 FILE *f;
270 int n;
271
pbrookc8a706f2008-06-02 16:16:42 +0000272 mmap_lock();
pbrook07765902008-05-31 16:33:53 +0000273 last_brk = (unsigned long)sbrk(0);
balrog50a95692007-12-12 01:16:23 +0000274 f = fopen("/proc/self/maps", "r");
275 if (f) {
276 do {
277 n = fscanf (f, "%llx-%llx %*[^\n]\n", &startaddr, &endaddr);
278 if (n == 2) {
blueswir1e0b8d652008-05-03 17:51:24 +0000279 startaddr = MIN(startaddr,
280 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
281 endaddr = MIN(endaddr,
282 (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
pbrookb5fc9092008-05-29 13:56:10 +0000283 page_set_flags(startaddr & TARGET_PAGE_MASK,
balrog50a95692007-12-12 01:16:23 +0000284 TARGET_PAGE_ALIGN(endaddr),
285 PAGE_RESERVED);
286 }
287 } while (!feof(f));
288 fclose(f);
289 }
pbrookc8a706f2008-06-02 16:16:42 +0000290 mmap_unlock();
balrog50a95692007-12-12 01:16:23 +0000291 }
292#endif
bellard54936002003-05-13 00:25:15 +0000293}
294
aliguori434929b2008-09-15 15:56:30 +0000295static inline PageDesc **page_l1_map(target_ulong index)
bellard54936002003-05-13 00:25:15 +0000296{
pbrook17e23772008-06-09 13:47:45 +0000297#if TARGET_LONG_BITS > 32
298 /* Host memory outside guest VM. For 32-bit targets we have already
299 excluded high addresses. */
thsd8173e02008-08-29 13:10:00 +0000300 if (index > ((target_ulong)L2_SIZE * L1_SIZE))
pbrook17e23772008-06-09 13:47:45 +0000301 return NULL;
302#endif
aliguori434929b2008-09-15 15:56:30 +0000303 return &l1_map[index >> L2_BITS];
304}
305
306static inline PageDesc *page_find_alloc(target_ulong index)
307{
308 PageDesc **lp, *p;
309 lp = page_l1_map(index);
310 if (!lp)
311 return NULL;
312
bellard54936002003-05-13 00:25:15 +0000313 p = *lp;
314 if (!p) {
315 /* allocate if not found */
pbrook17e23772008-06-09 13:47:45 +0000316#if defined(CONFIG_USER_ONLY)
pbrook17e23772008-06-09 13:47:45 +0000317 size_t len = sizeof(PageDesc) * L2_SIZE;
318 /* Don't use qemu_malloc because it may recurse. */
Blue Swirl660f11b2009-07-31 21:16:51 +0000319 p = mmap(NULL, len, PROT_READ | PROT_WRITE,
pbrook17e23772008-06-09 13:47:45 +0000320 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
bellard54936002003-05-13 00:25:15 +0000321 *lp = p;
aurel32fb1c2cd2008-12-08 18:12:26 +0000322 if (h2g_valid(p)) {
323 unsigned long addr = h2g(p);
pbrook17e23772008-06-09 13:47:45 +0000324 page_set_flags(addr & TARGET_PAGE_MASK,
325 TARGET_PAGE_ALIGN(addr + len),
326 PAGE_RESERVED);
327 }
328#else
329 p = qemu_mallocz(sizeof(PageDesc) * L2_SIZE);
330 *lp = p;
331#endif
bellard54936002003-05-13 00:25:15 +0000332 }
333 return p + (index & (L2_SIZE - 1));
334}
335
aurel3200f82b82008-04-27 21:12:55 +0000336static inline PageDesc *page_find(target_ulong index)
bellard54936002003-05-13 00:25:15 +0000337{
aliguori434929b2008-09-15 15:56:30 +0000338 PageDesc **lp, *p;
339 lp = page_l1_map(index);
340 if (!lp)
341 return NULL;
bellard54936002003-05-13 00:25:15 +0000342
aliguori434929b2008-09-15 15:56:30 +0000343 p = *lp;
Blue Swirl660f11b2009-07-31 21:16:51 +0000344 if (!p) {
345 return NULL;
346 }
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)) {
Blue Swirl0bf9e312009-07-20 17:19:25 +0000659 printf("ERROR invalidate: address=" TARGET_FMT_lx
660 " PC=%08lx size=%04x\n",
pbrook99773bd2006-04-16 15:14:59 +0000661 address, (long)tb->pc, tb->size);
bellardfd6ce8f2003-05-14 19:00:11 +0000662 }
663 }
664 }
665}
666
667/* verify that all the pages have correct rights for code */
668static void tb_page_check(void)
669{
670 TranslationBlock *tb;
671 int i, flags1, flags2;
ths3b46e622007-09-17 08:09:54 +0000672
pbrook99773bd2006-04-16 15:14:59 +0000673 for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
674 for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
bellardfd6ce8f2003-05-14 19:00:11 +0000675 flags1 = page_get_flags(tb->pc);
676 flags2 = page_get_flags(tb->pc + tb->size - 1);
677 if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
678 printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
pbrook99773bd2006-04-16 15:14:59 +0000679 (long)tb->pc, tb->size, flags1, flags2);
bellardfd6ce8f2003-05-14 19:00:11 +0000680 }
681 }
682 }
683}
684
685#endif
686
687/* invalidate one TB */
688static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb,
689 int next_offset)
690{
691 TranslationBlock *tb1;
692 for(;;) {
693 tb1 = *ptb;
694 if (tb1 == tb) {
695 *ptb = *(TranslationBlock **)((char *)tb1 + next_offset);
696 break;
697 }
698 ptb = (TranslationBlock **)((char *)tb1 + next_offset);
699 }
700}
701
bellard9fa3e852004-01-04 18:06:42 +0000702static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
703{
704 TranslationBlock *tb1;
705 unsigned int n1;
706
707 for(;;) {
708 tb1 = *ptb;
709 n1 = (long)tb1 & 3;
710 tb1 = (TranslationBlock *)((long)tb1 & ~3);
711 if (tb1 == tb) {
712 *ptb = tb1->page_next[n1];
713 break;
714 }
715 ptb = &tb1->page_next[n1];
716 }
717}
718
bellardd4e81642003-05-25 16:46:15 +0000719static inline void tb_jmp_remove(TranslationBlock *tb, int n)
720{
721 TranslationBlock *tb1, **ptb;
722 unsigned int n1;
723
724 ptb = &tb->jmp_next[n];
725 tb1 = *ptb;
726 if (tb1) {
727 /* find tb(n) in circular list */
728 for(;;) {
729 tb1 = *ptb;
730 n1 = (long)tb1 & 3;
731 tb1 = (TranslationBlock *)((long)tb1 & ~3);
732 if (n1 == n && tb1 == tb)
733 break;
734 if (n1 == 2) {
735 ptb = &tb1->jmp_first;
736 } else {
737 ptb = &tb1->jmp_next[n1];
738 }
739 }
740 /* now we can suppress tb(n) from the list */
741 *ptb = tb->jmp_next[n];
742
743 tb->jmp_next[n] = NULL;
744 }
745}
746
747/* reset the jump entry 'n' of a TB so that it is not chained to
748 another TB */
749static inline void tb_reset_jump(TranslationBlock *tb, int n)
750{
751 tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
752}
753
pbrook2e70f6e2008-06-29 01:03:05 +0000754void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr)
bellardfd6ce8f2003-05-14 19:00:11 +0000755{
bellard6a00d602005-11-21 23:25:50 +0000756 CPUState *env;
bellardfd6ce8f2003-05-14 19:00:11 +0000757 PageDesc *p;
bellard8a40a182005-11-20 10:35:40 +0000758 unsigned int h, n1;
aurel3200f82b82008-04-27 21:12:55 +0000759 target_phys_addr_t phys_pc;
bellard8a40a182005-11-20 10:35:40 +0000760 TranslationBlock *tb1, *tb2;
ths3b46e622007-09-17 08:09:54 +0000761
bellard9fa3e852004-01-04 18:06:42 +0000762 /* remove the TB from the hash list */
763 phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
764 h = tb_phys_hash_func(phys_pc);
ths5fafdf22007-09-16 21:08:06 +0000765 tb_remove(&tb_phys_hash[h], tb,
bellard9fa3e852004-01-04 18:06:42 +0000766 offsetof(TranslationBlock, phys_hash_next));
bellardfd6ce8f2003-05-14 19:00:11 +0000767
bellard9fa3e852004-01-04 18:06:42 +0000768 /* remove the TB from the page list */
769 if (tb->page_addr[0] != page_addr) {
770 p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
771 tb_page_remove(&p->first_tb, tb);
772 invalidate_page_bitmap(p);
773 }
774 if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
775 p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
776 tb_page_remove(&p->first_tb, tb);
777 invalidate_page_bitmap(p);
778 }
779
bellard8a40a182005-11-20 10:35:40 +0000780 tb_invalidated_flag = 1;
781
782 /* remove the TB from the hash list */
783 h = tb_jmp_cache_hash_func(tb->pc);
bellard6a00d602005-11-21 23:25:50 +0000784 for(env = first_cpu; env != NULL; env = env->next_cpu) {
785 if (env->tb_jmp_cache[h] == tb)
786 env->tb_jmp_cache[h] = NULL;
787 }
bellard8a40a182005-11-20 10:35:40 +0000788
789 /* suppress this TB from the two jump lists */
790 tb_jmp_remove(tb, 0);
791 tb_jmp_remove(tb, 1);
792
793 /* suppress any remaining jumps to this TB */
794 tb1 = tb->jmp_first;
795 for(;;) {
796 n1 = (long)tb1 & 3;
797 if (n1 == 2)
798 break;
799 tb1 = (TranslationBlock *)((long)tb1 & ~3);
800 tb2 = tb1->jmp_next[n1];
801 tb_reset_jump(tb1, n1);
802 tb1->jmp_next[n1] = NULL;
803 tb1 = tb2;
804 }
805 tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
806
bellarde3db7222005-01-26 22:00:47 +0000807 tb_phys_invalidate_count++;
bellard9fa3e852004-01-04 18:06:42 +0000808}
809
810static inline void set_bits(uint8_t *tab, int start, int len)
811{
812 int end, mask, end1;
813
814 end = start + len;
815 tab += start >> 3;
816 mask = 0xff << (start & 7);
817 if ((start & ~7) == (end & ~7)) {
818 if (start < end) {
819 mask &= ~(0xff << (end & 7));
820 *tab |= mask;
821 }
822 } else {
823 *tab++ |= mask;
824 start = (start + 8) & ~7;
825 end1 = end & ~7;
826 while (start < end1) {
827 *tab++ = 0xff;
828 start += 8;
829 }
830 if (start < end) {
831 mask = ~(0xff << (end & 7));
832 *tab |= mask;
833 }
834 }
835}
836
837static void build_page_bitmap(PageDesc *p)
838{
839 int n, tb_start, tb_end;
840 TranslationBlock *tb;
ths3b46e622007-09-17 08:09:54 +0000841
pbrookb2a70812008-06-09 13:57:23 +0000842 p->code_bitmap = qemu_mallocz(TARGET_PAGE_SIZE / 8);
bellard9fa3e852004-01-04 18:06:42 +0000843
844 tb = p->first_tb;
845 while (tb != NULL) {
846 n = (long)tb & 3;
847 tb = (TranslationBlock *)((long)tb & ~3);
848 /* NOTE: this is subtle as a TB may span two physical pages */
849 if (n == 0) {
850 /* NOTE: tb_end may be after the end of the page, but
851 it is not a problem */
852 tb_start = tb->pc & ~TARGET_PAGE_MASK;
853 tb_end = tb_start + tb->size;
854 if (tb_end > TARGET_PAGE_SIZE)
855 tb_end = TARGET_PAGE_SIZE;
856 } else {
857 tb_start = 0;
858 tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
859 }
860 set_bits(p->code_bitmap, tb_start, tb_end - tb_start);
861 tb = tb->page_next[n];
862 }
863}
864
pbrook2e70f6e2008-06-29 01:03:05 +0000865TranslationBlock *tb_gen_code(CPUState *env,
866 target_ulong pc, target_ulong cs_base,
867 int flags, int cflags)
bellardd720b932004-04-25 17:57:43 +0000868{
869 TranslationBlock *tb;
870 uint8_t *tc_ptr;
871 target_ulong phys_pc, phys_page2, virt_page2;
872 int code_gen_size;
873
bellardc27004e2005-01-03 23:35:10 +0000874 phys_pc = get_phys_addr_code(env, pc);
875 tb = tb_alloc(pc);
bellardd720b932004-04-25 17:57:43 +0000876 if (!tb) {
877 /* flush must be done */
878 tb_flush(env);
879 /* cannot fail at this point */
bellardc27004e2005-01-03 23:35:10 +0000880 tb = tb_alloc(pc);
pbrook2e70f6e2008-06-29 01:03:05 +0000881 /* Don't forget to invalidate previous TB info. */
882 tb_invalidated_flag = 1;
bellardd720b932004-04-25 17:57:43 +0000883 }
884 tc_ptr = code_gen_ptr;
885 tb->tc_ptr = tc_ptr;
886 tb->cs_base = cs_base;
887 tb->flags = flags;
888 tb->cflags = cflags;
blueswir1d07bde82007-12-11 19:35:45 +0000889 cpu_gen_code(env, tb, &code_gen_size);
bellardd720b932004-04-25 17:57:43 +0000890 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 +0000891
bellardd720b932004-04-25 17:57:43 +0000892 /* check next page if needed */
bellardc27004e2005-01-03 23:35:10 +0000893 virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
bellardd720b932004-04-25 17:57:43 +0000894 phys_page2 = -1;
bellardc27004e2005-01-03 23:35:10 +0000895 if ((pc & TARGET_PAGE_MASK) != virt_page2) {
bellardd720b932004-04-25 17:57:43 +0000896 phys_page2 = get_phys_addr_code(env, virt_page2);
897 }
898 tb_link_phys(tb, phys_pc, phys_page2);
pbrook2e70f6e2008-06-29 01:03:05 +0000899 return tb;
bellardd720b932004-04-25 17:57:43 +0000900}
ths3b46e622007-09-17 08:09:54 +0000901
bellard9fa3e852004-01-04 18:06:42 +0000902/* invalidate all TBs which intersect with the target physical page
903 starting in range [start;end[. NOTE: start and end must refer to
bellardd720b932004-04-25 17:57:43 +0000904 the same physical page. 'is_cpu_write_access' should be true if called
905 from a real cpu write access: the virtual CPU will exit the current
906 TB if code is modified inside this TB. */
aurel3200f82b82008-04-27 21:12:55 +0000907void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t end,
bellardd720b932004-04-25 17:57:43 +0000908 int is_cpu_write_access)
bellard9fa3e852004-01-04 18:06:42 +0000909{
aliguori6b917542008-11-18 19:46:41 +0000910 TranslationBlock *tb, *tb_next, *saved_tb;
bellardd720b932004-04-25 17:57:43 +0000911 CPUState *env = cpu_single_env;
bellard9fa3e852004-01-04 18:06:42 +0000912 target_ulong tb_start, tb_end;
aliguori6b917542008-11-18 19:46:41 +0000913 PageDesc *p;
914 int n;
915#ifdef TARGET_HAS_PRECISE_SMC
916 int current_tb_not_found = is_cpu_write_access;
917 TranslationBlock *current_tb = NULL;
918 int current_tb_modified = 0;
919 target_ulong current_pc = 0;
920 target_ulong current_cs_base = 0;
921 int current_flags = 0;
922#endif /* TARGET_HAS_PRECISE_SMC */
bellard9fa3e852004-01-04 18:06:42 +0000923
924 p = page_find(start >> TARGET_PAGE_BITS);
ths5fafdf22007-09-16 21:08:06 +0000925 if (!p)
bellard9fa3e852004-01-04 18:06:42 +0000926 return;
ths5fafdf22007-09-16 21:08:06 +0000927 if (!p->code_bitmap &&
bellardd720b932004-04-25 17:57:43 +0000928 ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
929 is_cpu_write_access) {
bellard9fa3e852004-01-04 18:06:42 +0000930 /* build code bitmap */
931 build_page_bitmap(p);
932 }
933
934 /* we remove all the TBs in the range [start, end[ */
935 /* XXX: see if in some cases it could be faster to invalidate all the code */
936 tb = p->first_tb;
937 while (tb != NULL) {
938 n = (long)tb & 3;
939 tb = (TranslationBlock *)((long)tb & ~3);
940 tb_next = tb->page_next[n];
941 /* NOTE: this is subtle as a TB may span two physical pages */
942 if (n == 0) {
943 /* NOTE: tb_end may be after the end of the page, but
944 it is not a problem */
945 tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
946 tb_end = tb_start + tb->size;
947 } else {
948 tb_start = tb->page_addr[1];
949 tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
950 }
951 if (!(tb_end <= start || tb_start >= end)) {
bellardd720b932004-04-25 17:57:43 +0000952#ifdef TARGET_HAS_PRECISE_SMC
953 if (current_tb_not_found) {
954 current_tb_not_found = 0;
955 current_tb = NULL;
pbrook2e70f6e2008-06-29 01:03:05 +0000956 if (env->mem_io_pc) {
bellardd720b932004-04-25 17:57:43 +0000957 /* now we have a real cpu fault */
pbrook2e70f6e2008-06-29 01:03:05 +0000958 current_tb = tb_find_pc(env->mem_io_pc);
bellardd720b932004-04-25 17:57:43 +0000959 }
960 }
961 if (current_tb == tb &&
pbrook2e70f6e2008-06-29 01:03:05 +0000962 (current_tb->cflags & CF_COUNT_MASK) != 1) {
bellardd720b932004-04-25 17:57:43 +0000963 /* If we are modifying the current TB, we must stop
964 its execution. We could be more precise by checking
965 that the modification is after the current PC, but it
966 would require a specialized function to partially
967 restore the CPU state */
ths3b46e622007-09-17 08:09:54 +0000968
bellardd720b932004-04-25 17:57:43 +0000969 current_tb_modified = 1;
ths5fafdf22007-09-16 21:08:06 +0000970 cpu_restore_state(current_tb, env,
pbrook2e70f6e2008-06-29 01:03:05 +0000971 env->mem_io_pc, NULL);
aliguori6b917542008-11-18 19:46:41 +0000972 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
973 &current_flags);
bellardd720b932004-04-25 17:57:43 +0000974 }
975#endif /* TARGET_HAS_PRECISE_SMC */
bellard6f5a9f72005-11-26 20:12:28 +0000976 /* we need to do that to handle the case where a signal
977 occurs while doing tb_phys_invalidate() */
978 saved_tb = NULL;
979 if (env) {
980 saved_tb = env->current_tb;
981 env->current_tb = NULL;
982 }
bellard9fa3e852004-01-04 18:06:42 +0000983 tb_phys_invalidate(tb, -1);
bellard6f5a9f72005-11-26 20:12:28 +0000984 if (env) {
985 env->current_tb = saved_tb;
986 if (env->interrupt_request && env->current_tb)
987 cpu_interrupt(env, env->interrupt_request);
988 }
bellard9fa3e852004-01-04 18:06:42 +0000989 }
990 tb = tb_next;
991 }
992#if !defined(CONFIG_USER_ONLY)
993 /* if no code remaining, no need to continue to use slow writes */
994 if (!p->first_tb) {
995 invalidate_page_bitmap(p);
bellardd720b932004-04-25 17:57:43 +0000996 if (is_cpu_write_access) {
pbrook2e70f6e2008-06-29 01:03:05 +0000997 tlb_unprotect_code_phys(env, start, env->mem_io_vaddr);
bellardd720b932004-04-25 17:57:43 +0000998 }
999 }
1000#endif
1001#ifdef TARGET_HAS_PRECISE_SMC
1002 if (current_tb_modified) {
1003 /* we generate a block containing just the instruction
1004 modifying the memory. It will ensure that it cannot modify
1005 itself */
bellardea1c1802004-06-14 18:56:36 +00001006 env->current_tb = NULL;
pbrook2e70f6e2008-06-29 01:03:05 +00001007 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
bellardd720b932004-04-25 17:57:43 +00001008 cpu_resume_from_signal(env, NULL);
bellard9fa3e852004-01-04 18:06:42 +00001009 }
1010#endif
1011}
1012
1013/* len must be <= 8 and start must be a multiple of len */
aurel3200f82b82008-04-27 21:12:55 +00001014static inline void tb_invalidate_phys_page_fast(target_phys_addr_t start, int len)
bellard9fa3e852004-01-04 18:06:42 +00001015{
1016 PageDesc *p;
1017 int offset, b;
bellard59817cc2004-02-16 22:01:13 +00001018#if 0
bellarda4193c82004-06-03 14:01:43 +00001019 if (1) {
aliguori93fcfe32009-01-15 22:34:14 +00001020 qemu_log("modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
1021 cpu_single_env->mem_io_vaddr, len,
1022 cpu_single_env->eip,
1023 cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
bellard59817cc2004-02-16 22:01:13 +00001024 }
1025#endif
bellard9fa3e852004-01-04 18:06:42 +00001026 p = page_find(start >> TARGET_PAGE_BITS);
ths5fafdf22007-09-16 21:08:06 +00001027 if (!p)
bellard9fa3e852004-01-04 18:06:42 +00001028 return;
1029 if (p->code_bitmap) {
1030 offset = start & ~TARGET_PAGE_MASK;
1031 b = p->code_bitmap[offset >> 3] >> (offset & 7);
1032 if (b & ((1 << len) - 1))
1033 goto do_invalidate;
1034 } else {
1035 do_invalidate:
bellardd720b932004-04-25 17:57:43 +00001036 tb_invalidate_phys_page_range(start, start + len, 1);
bellard9fa3e852004-01-04 18:06:42 +00001037 }
1038}
1039
bellard9fa3e852004-01-04 18:06:42 +00001040#if !defined(CONFIG_SOFTMMU)
aurel3200f82b82008-04-27 21:12:55 +00001041static void tb_invalidate_phys_page(target_phys_addr_t addr,
bellardd720b932004-04-25 17:57:43 +00001042 unsigned long pc, void *puc)
bellard9fa3e852004-01-04 18:06:42 +00001043{
aliguori6b917542008-11-18 19:46:41 +00001044 TranslationBlock *tb;
bellard9fa3e852004-01-04 18:06:42 +00001045 PageDesc *p;
aliguori6b917542008-11-18 19:46:41 +00001046 int n;
bellardd720b932004-04-25 17:57:43 +00001047#ifdef TARGET_HAS_PRECISE_SMC
aliguori6b917542008-11-18 19:46:41 +00001048 TranslationBlock *current_tb = NULL;
bellardd720b932004-04-25 17:57:43 +00001049 CPUState *env = cpu_single_env;
aliguori6b917542008-11-18 19:46:41 +00001050 int current_tb_modified = 0;
1051 target_ulong current_pc = 0;
1052 target_ulong current_cs_base = 0;
1053 int current_flags = 0;
bellardd720b932004-04-25 17:57:43 +00001054#endif
bellard9fa3e852004-01-04 18:06:42 +00001055
1056 addr &= TARGET_PAGE_MASK;
1057 p = page_find(addr >> TARGET_PAGE_BITS);
ths5fafdf22007-09-16 21:08:06 +00001058 if (!p)
bellardfd6ce8f2003-05-14 19:00:11 +00001059 return;
1060 tb = p->first_tb;
bellardd720b932004-04-25 17:57:43 +00001061#ifdef TARGET_HAS_PRECISE_SMC
1062 if (tb && pc != 0) {
1063 current_tb = tb_find_pc(pc);
1064 }
1065#endif
bellardfd6ce8f2003-05-14 19:00:11 +00001066 while (tb != NULL) {
bellard9fa3e852004-01-04 18:06:42 +00001067 n = (long)tb & 3;
1068 tb = (TranslationBlock *)((long)tb & ~3);
bellardd720b932004-04-25 17:57:43 +00001069#ifdef TARGET_HAS_PRECISE_SMC
1070 if (current_tb == tb &&
pbrook2e70f6e2008-06-29 01:03:05 +00001071 (current_tb->cflags & CF_COUNT_MASK) != 1) {
bellardd720b932004-04-25 17:57:43 +00001072 /* If we are modifying the current TB, we must stop
1073 its execution. We could be more precise by checking
1074 that the modification is after the current PC, but it
1075 would require a specialized function to partially
1076 restore the CPU state */
ths3b46e622007-09-17 08:09:54 +00001077
bellardd720b932004-04-25 17:57:43 +00001078 current_tb_modified = 1;
1079 cpu_restore_state(current_tb, env, pc, puc);
aliguori6b917542008-11-18 19:46:41 +00001080 cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
1081 &current_flags);
bellardd720b932004-04-25 17:57:43 +00001082 }
1083#endif /* TARGET_HAS_PRECISE_SMC */
bellard9fa3e852004-01-04 18:06:42 +00001084 tb_phys_invalidate(tb, addr);
1085 tb = tb->page_next[n];
bellardfd6ce8f2003-05-14 19:00:11 +00001086 }
1087 p->first_tb = NULL;
bellardd720b932004-04-25 17:57:43 +00001088#ifdef TARGET_HAS_PRECISE_SMC
1089 if (current_tb_modified) {
1090 /* we generate a block containing just the instruction
1091 modifying the memory. It will ensure that it cannot modify
1092 itself */
bellardea1c1802004-06-14 18:56:36 +00001093 env->current_tb = NULL;
pbrook2e70f6e2008-06-29 01:03:05 +00001094 tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
bellardd720b932004-04-25 17:57:43 +00001095 cpu_resume_from_signal(env, puc);
1096 }
1097#endif
bellardfd6ce8f2003-05-14 19:00:11 +00001098}
bellard9fa3e852004-01-04 18:06:42 +00001099#endif
bellardfd6ce8f2003-05-14 19:00:11 +00001100
1101/* add the tb in the target page and protect it if necessary */
ths5fafdf22007-09-16 21:08:06 +00001102static inline void tb_alloc_page(TranslationBlock *tb,
pbrook53a59602006-03-25 19:31:22 +00001103 unsigned int n, target_ulong page_addr)
bellardfd6ce8f2003-05-14 19:00:11 +00001104{
1105 PageDesc *p;
bellard9fa3e852004-01-04 18:06:42 +00001106 TranslationBlock *last_first_tb;
bellardfd6ce8f2003-05-14 19:00:11 +00001107
bellard9fa3e852004-01-04 18:06:42 +00001108 tb->page_addr[n] = page_addr;
bellard3a7d9292005-08-21 09:26:42 +00001109 p = page_find_alloc(page_addr >> TARGET_PAGE_BITS);
bellard9fa3e852004-01-04 18:06:42 +00001110 tb->page_next[n] = p->first_tb;
1111 last_first_tb = p->first_tb;
1112 p->first_tb = (TranslationBlock *)((long)tb | n);
1113 invalidate_page_bitmap(p);
1114
bellard107db442004-06-22 18:48:46 +00001115#if defined(TARGET_HAS_SMC) || 1
bellardd720b932004-04-25 17:57:43 +00001116
bellard9fa3e852004-01-04 18:06:42 +00001117#if defined(CONFIG_USER_ONLY)
bellardfd6ce8f2003-05-14 19:00:11 +00001118 if (p->flags & PAGE_WRITE) {
pbrook53a59602006-03-25 19:31:22 +00001119 target_ulong addr;
1120 PageDesc *p2;
bellard9fa3e852004-01-04 18:06:42 +00001121 int prot;
1122
bellardfd6ce8f2003-05-14 19:00:11 +00001123 /* force the host page as non writable (writes will have a
1124 page fault + mprotect overhead) */
pbrook53a59602006-03-25 19:31:22 +00001125 page_addr &= qemu_host_page_mask;
bellardfd6ce8f2003-05-14 19:00:11 +00001126 prot = 0;
pbrook53a59602006-03-25 19:31:22 +00001127 for(addr = page_addr; addr < page_addr + qemu_host_page_size;
1128 addr += TARGET_PAGE_SIZE) {
1129
1130 p2 = page_find (addr >> TARGET_PAGE_BITS);
1131 if (!p2)
1132 continue;
1133 prot |= p2->flags;
1134 p2->flags &= ~PAGE_WRITE;
1135 page_get_flags(addr);
1136 }
ths5fafdf22007-09-16 21:08:06 +00001137 mprotect(g2h(page_addr), qemu_host_page_size,
bellardfd6ce8f2003-05-14 19:00:11 +00001138 (prot & PAGE_BITS) & ~PAGE_WRITE);
1139#ifdef DEBUG_TB_INVALIDATE
blueswir1ab3d1722007-11-04 07:31:40 +00001140 printf("protecting code page: 0x" TARGET_FMT_lx "\n",
pbrook53a59602006-03-25 19:31:22 +00001141 page_addr);
bellardfd6ce8f2003-05-14 19:00:11 +00001142#endif
bellardfd6ce8f2003-05-14 19:00:11 +00001143 }
bellard9fa3e852004-01-04 18:06:42 +00001144#else
1145 /* if some code is already present, then the pages are already
1146 protected. So we handle the case where only the first TB is
1147 allocated in a physical page */
1148 if (!last_first_tb) {
bellard6a00d602005-11-21 23:25:50 +00001149 tlb_protect_code(page_addr);
bellard9fa3e852004-01-04 18:06:42 +00001150 }
1151#endif
bellardd720b932004-04-25 17:57:43 +00001152
1153#endif /* TARGET_HAS_SMC */
bellardfd6ce8f2003-05-14 19:00:11 +00001154}
1155
1156/* Allocate a new translation block. Flush the translation buffer if
1157 too many translation blocks or too much generated code. */
bellardc27004e2005-01-03 23:35:10 +00001158TranslationBlock *tb_alloc(target_ulong pc)
bellardfd6ce8f2003-05-14 19:00:11 +00001159{
1160 TranslationBlock *tb;
bellardfd6ce8f2003-05-14 19:00:11 +00001161
bellard26a5f132008-05-28 12:30:31 +00001162 if (nb_tbs >= code_gen_max_blocks ||
1163 (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
bellardd4e81642003-05-25 16:46:15 +00001164 return NULL;
bellardfd6ce8f2003-05-14 19:00:11 +00001165 tb = &tbs[nb_tbs++];
1166 tb->pc = pc;
bellardb448f2f2004-02-25 23:24:04 +00001167 tb->cflags = 0;
bellardd4e81642003-05-25 16:46:15 +00001168 return tb;
1169}
1170
pbrook2e70f6e2008-06-29 01:03:05 +00001171void tb_free(TranslationBlock *tb)
1172{
thsbf20dc02008-06-30 17:22:19 +00001173 /* In practice this is mostly used for single use temporary TB
pbrook2e70f6e2008-06-29 01:03:05 +00001174 Ignore the hard cases and just back up if this TB happens to
1175 be the last one generated. */
1176 if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) {
1177 code_gen_ptr = tb->tc_ptr;
1178 nb_tbs--;
1179 }
1180}
1181
bellard9fa3e852004-01-04 18:06:42 +00001182/* add a new TB and link it to the physical page tables. phys_page2 is
1183 (-1) to indicate that only one page contains the TB. */
ths5fafdf22007-09-16 21:08:06 +00001184void tb_link_phys(TranslationBlock *tb,
bellard9fa3e852004-01-04 18:06:42 +00001185 target_ulong phys_pc, target_ulong phys_page2)
bellardd4e81642003-05-25 16:46:15 +00001186{
bellard9fa3e852004-01-04 18:06:42 +00001187 unsigned int h;
1188 TranslationBlock **ptb;
1189
pbrookc8a706f2008-06-02 16:16:42 +00001190 /* Grab the mmap lock to stop another thread invalidating this TB
1191 before we are done. */
1192 mmap_lock();
bellard9fa3e852004-01-04 18:06:42 +00001193 /* add in the physical hash table */
1194 h = tb_phys_hash_func(phys_pc);
1195 ptb = &tb_phys_hash[h];
1196 tb->phys_hash_next = *ptb;
1197 *ptb = tb;
bellardfd6ce8f2003-05-14 19:00:11 +00001198
1199 /* add in the page list */
bellard9fa3e852004-01-04 18:06:42 +00001200 tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK);
1201 if (phys_page2 != -1)
1202 tb_alloc_page(tb, 1, phys_page2);
1203 else
1204 tb->page_addr[1] = -1;
bellard9fa3e852004-01-04 18:06:42 +00001205
bellardd4e81642003-05-25 16:46:15 +00001206 tb->jmp_first = (TranslationBlock *)((long)tb | 2);
1207 tb->jmp_next[0] = NULL;
1208 tb->jmp_next[1] = NULL;
1209
1210 /* init original jump addresses */
1211 if (tb->tb_next_offset[0] != 0xffff)
1212 tb_reset_jump(tb, 0);
1213 if (tb->tb_next_offset[1] != 0xffff)
1214 tb_reset_jump(tb, 1);
bellard8a40a182005-11-20 10:35:40 +00001215
1216#ifdef DEBUG_TB_CHECK
1217 tb_page_check();
1218#endif
pbrookc8a706f2008-06-02 16:16:42 +00001219 mmap_unlock();
bellardfd6ce8f2003-05-14 19:00:11 +00001220}
1221
bellarda513fe12003-05-27 23:29:48 +00001222/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
1223 tb[1].tc_ptr. Return NULL if not found */
1224TranslationBlock *tb_find_pc(unsigned long tc_ptr)
1225{
1226 int m_min, m_max, m;
1227 unsigned long v;
1228 TranslationBlock *tb;
1229
1230 if (nb_tbs <= 0)
1231 return NULL;
1232 if (tc_ptr < (unsigned long)code_gen_buffer ||
1233 tc_ptr >= (unsigned long)code_gen_ptr)
1234 return NULL;
1235 /* binary search (cf Knuth) */
1236 m_min = 0;
1237 m_max = nb_tbs - 1;
1238 while (m_min <= m_max) {
1239 m = (m_min + m_max) >> 1;
1240 tb = &tbs[m];
1241 v = (unsigned long)tb->tc_ptr;
1242 if (v == tc_ptr)
1243 return tb;
1244 else if (tc_ptr < v) {
1245 m_max = m - 1;
1246 } else {
1247 m_min = m + 1;
1248 }
ths5fafdf22007-09-16 21:08:06 +00001249 }
bellarda513fe12003-05-27 23:29:48 +00001250 return &tbs[m_max];
1251}
bellard75012672003-06-21 13:11:07 +00001252
bellardea041c02003-06-25 16:16:50 +00001253static void tb_reset_jump_recursive(TranslationBlock *tb);
1254
1255static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
1256{
1257 TranslationBlock *tb1, *tb_next, **ptb;
1258 unsigned int n1;
1259
1260 tb1 = tb->jmp_next[n];
1261 if (tb1 != NULL) {
1262 /* find head of list */
1263 for(;;) {
1264 n1 = (long)tb1 & 3;
1265 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1266 if (n1 == 2)
1267 break;
1268 tb1 = tb1->jmp_next[n1];
1269 }
1270 /* we are now sure now that tb jumps to tb1 */
1271 tb_next = tb1;
1272
1273 /* remove tb from the jmp_first list */
1274 ptb = &tb_next->jmp_first;
1275 for(;;) {
1276 tb1 = *ptb;
1277 n1 = (long)tb1 & 3;
1278 tb1 = (TranslationBlock *)((long)tb1 & ~3);
1279 if (n1 == n && tb1 == tb)
1280 break;
1281 ptb = &tb1->jmp_next[n1];
1282 }
1283 *ptb = tb->jmp_next[n];
1284 tb->jmp_next[n] = NULL;
ths3b46e622007-09-17 08:09:54 +00001285
bellardea041c02003-06-25 16:16:50 +00001286 /* suppress the jump to next tb in generated code */
1287 tb_reset_jump(tb, n);
1288
bellard01243112004-01-04 15:48:17 +00001289 /* suppress jumps in the tb on which we could have jumped */
bellardea041c02003-06-25 16:16:50 +00001290 tb_reset_jump_recursive(tb_next);
1291 }
1292}
1293
1294static void tb_reset_jump_recursive(TranslationBlock *tb)
1295{
1296 tb_reset_jump_recursive2(tb, 0);
1297 tb_reset_jump_recursive2(tb, 1);
1298}
1299
bellard1fddef42005-04-17 19:16:13 +00001300#if defined(TARGET_HAS_ICE)
bellardd720b932004-04-25 17:57:43 +00001301static void breakpoint_invalidate(CPUState *env, target_ulong pc)
1302{
j_mayer9b3c35e2007-04-07 11:21:28 +00001303 target_phys_addr_t addr;
1304 target_ulong pd;
pbrookc2f07f82006-04-08 17:14:56 +00001305 ram_addr_t ram_addr;
1306 PhysPageDesc *p;
bellardd720b932004-04-25 17:57:43 +00001307
pbrookc2f07f82006-04-08 17:14:56 +00001308 addr = cpu_get_phys_page_debug(env, pc);
1309 p = phys_page_find(addr >> TARGET_PAGE_BITS);
1310 if (!p) {
1311 pd = IO_MEM_UNASSIGNED;
1312 } else {
1313 pd = p->phys_offset;
1314 }
1315 ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
pbrook706cd4b2006-04-08 17:36:21 +00001316 tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
bellardd720b932004-04-25 17:57:43 +00001317}
bellardc27004e2005-01-03 23:35:10 +00001318#endif
bellardd720b932004-04-25 17:57:43 +00001319
pbrook6658ffb2007-03-16 23:58:11 +00001320/* Add a watchpoint. */
aliguoria1d1bb32008-11-18 20:07:32 +00001321int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
1322 int flags, CPUWatchpoint **watchpoint)
pbrook6658ffb2007-03-16 23:58:11 +00001323{
aliguorib4051332008-11-18 20:14:20 +00001324 target_ulong len_mask = ~(len - 1);
aliguoric0ce9982008-11-25 22:13:57 +00001325 CPUWatchpoint *wp;
pbrook6658ffb2007-03-16 23:58:11 +00001326
aliguorib4051332008-11-18 20:14:20 +00001327 /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
1328 if ((len != 1 && len != 2 && len != 4 && len != 8) || (addr & ~len_mask)) {
1329 fprintf(stderr, "qemu: tried to set invalid watchpoint at "
1330 TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
1331 return -EINVAL;
1332 }
aliguoria1d1bb32008-11-18 20:07:32 +00001333 wp = qemu_malloc(sizeof(*wp));
pbrook6658ffb2007-03-16 23:58:11 +00001334
aliguoria1d1bb32008-11-18 20:07:32 +00001335 wp->vaddr = addr;
aliguorib4051332008-11-18 20:14:20 +00001336 wp->len_mask = len_mask;
aliguoria1d1bb32008-11-18 20:07:32 +00001337 wp->flags = flags;
1338
aliguori2dc9f412008-11-18 20:56:59 +00001339 /* keep all GDB-injected watchpoints in front */
aliguoric0ce9982008-11-25 22:13:57 +00001340 if (flags & BP_GDB)
1341 TAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
1342 else
1343 TAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
aliguoria1d1bb32008-11-18 20:07:32 +00001344
pbrook6658ffb2007-03-16 23:58:11 +00001345 tlb_flush_page(env, addr);
aliguoria1d1bb32008-11-18 20:07:32 +00001346
1347 if (watchpoint)
1348 *watchpoint = wp;
1349 return 0;
pbrook6658ffb2007-03-16 23:58:11 +00001350}
1351
aliguoria1d1bb32008-11-18 20:07:32 +00001352/* Remove a specific watchpoint. */
1353int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len,
1354 int flags)
pbrook6658ffb2007-03-16 23:58:11 +00001355{
aliguorib4051332008-11-18 20:14:20 +00001356 target_ulong len_mask = ~(len - 1);
aliguoria1d1bb32008-11-18 20:07:32 +00001357 CPUWatchpoint *wp;
pbrook6658ffb2007-03-16 23:58:11 +00001358
aliguoric0ce9982008-11-25 22:13:57 +00001359 TAILQ_FOREACH(wp, &env->watchpoints, entry) {
aliguorib4051332008-11-18 20:14:20 +00001360 if (addr == wp->vaddr && len_mask == wp->len_mask
aliguori6e140f22008-11-18 20:37:55 +00001361 && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
aliguoria1d1bb32008-11-18 20:07:32 +00001362 cpu_watchpoint_remove_by_ref(env, wp);
pbrook6658ffb2007-03-16 23:58:11 +00001363 return 0;
1364 }
1365 }
aliguoria1d1bb32008-11-18 20:07:32 +00001366 return -ENOENT;
pbrook6658ffb2007-03-16 23:58:11 +00001367}
1368
aliguoria1d1bb32008-11-18 20:07:32 +00001369/* Remove a specific watchpoint by reference. */
1370void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint)
1371{
aliguoric0ce9982008-11-25 22:13:57 +00001372 TAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
edgar_igl7d03f822008-05-17 18:58:29 +00001373
aliguoria1d1bb32008-11-18 20:07:32 +00001374 tlb_flush_page(env, watchpoint->vaddr);
1375
1376 qemu_free(watchpoint);
edgar_igl7d03f822008-05-17 18:58:29 +00001377}
1378
aliguoria1d1bb32008-11-18 20:07:32 +00001379/* Remove all matching watchpoints. */
1380void cpu_watchpoint_remove_all(CPUState *env, int mask)
1381{
aliguoric0ce9982008-11-25 22:13:57 +00001382 CPUWatchpoint *wp, *next;
aliguoria1d1bb32008-11-18 20:07:32 +00001383
aliguoric0ce9982008-11-25 22:13:57 +00001384 TAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
aliguoria1d1bb32008-11-18 20:07:32 +00001385 if (wp->flags & mask)
1386 cpu_watchpoint_remove_by_ref(env, wp);
aliguoric0ce9982008-11-25 22:13:57 +00001387 }
aliguoria1d1bb32008-11-18 20:07:32 +00001388}
1389
1390/* Add a breakpoint. */
1391int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
1392 CPUBreakpoint **breakpoint)
bellard4c3a88a2003-07-26 12:06:08 +00001393{
bellard1fddef42005-04-17 19:16:13 +00001394#if defined(TARGET_HAS_ICE)
aliguoric0ce9982008-11-25 22:13:57 +00001395 CPUBreakpoint *bp;
ths3b46e622007-09-17 08:09:54 +00001396
aliguoria1d1bb32008-11-18 20:07:32 +00001397 bp = qemu_malloc(sizeof(*bp));
aliguoria1d1bb32008-11-18 20:07:32 +00001398
1399 bp->pc = pc;
1400 bp->flags = flags;
1401
aliguori2dc9f412008-11-18 20:56:59 +00001402 /* keep all GDB-injected breakpoints in front */
aliguoric0ce9982008-11-25 22:13:57 +00001403 if (flags & BP_GDB)
1404 TAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
1405 else
1406 TAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
aliguoria1d1bb32008-11-18 20:07:32 +00001407
1408 breakpoint_invalidate(env, pc);
1409
1410 if (breakpoint)
1411 *breakpoint = bp;
1412 return 0;
1413#else
1414 return -ENOSYS;
1415#endif
1416}
1417
1418/* Remove a specific breakpoint. */
1419int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags)
1420{
1421#if defined(TARGET_HAS_ICE)
1422 CPUBreakpoint *bp;
1423
aliguoric0ce9982008-11-25 22:13:57 +00001424 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
aliguoria1d1bb32008-11-18 20:07:32 +00001425 if (bp->pc == pc && bp->flags == flags) {
1426 cpu_breakpoint_remove_by_ref(env, bp);
bellard4c3a88a2003-07-26 12:06:08 +00001427 return 0;
aliguoria1d1bb32008-11-18 20:07:32 +00001428 }
bellard4c3a88a2003-07-26 12:06:08 +00001429 }
aliguoria1d1bb32008-11-18 20:07:32 +00001430 return -ENOENT;
bellard4c3a88a2003-07-26 12:06:08 +00001431#else
aliguoria1d1bb32008-11-18 20:07:32 +00001432 return -ENOSYS;
bellard4c3a88a2003-07-26 12:06:08 +00001433#endif
1434}
1435
aliguoria1d1bb32008-11-18 20:07:32 +00001436/* Remove a specific breakpoint by reference. */
1437void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint)
bellard4c3a88a2003-07-26 12:06:08 +00001438{
bellard1fddef42005-04-17 19:16:13 +00001439#if defined(TARGET_HAS_ICE)
aliguoric0ce9982008-11-25 22:13:57 +00001440 TAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
bellardd720b932004-04-25 17:57:43 +00001441
aliguoria1d1bb32008-11-18 20:07:32 +00001442 breakpoint_invalidate(env, breakpoint->pc);
1443
1444 qemu_free(breakpoint);
1445#endif
1446}
1447
1448/* Remove all matching breakpoints. */
1449void cpu_breakpoint_remove_all(CPUState *env, int mask)
1450{
1451#if defined(TARGET_HAS_ICE)
aliguoric0ce9982008-11-25 22:13:57 +00001452 CPUBreakpoint *bp, *next;
aliguoria1d1bb32008-11-18 20:07:32 +00001453
aliguoric0ce9982008-11-25 22:13:57 +00001454 TAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
aliguoria1d1bb32008-11-18 20:07:32 +00001455 if (bp->flags & mask)
1456 cpu_breakpoint_remove_by_ref(env, bp);
aliguoric0ce9982008-11-25 22:13:57 +00001457 }
bellard4c3a88a2003-07-26 12:06:08 +00001458#endif
1459}
1460
bellardc33a3462003-07-29 20:50:33 +00001461/* enable or disable single step mode. EXCP_DEBUG is returned by the
1462 CPU loop after each instruction */
1463void cpu_single_step(CPUState *env, int enabled)
1464{
bellard1fddef42005-04-17 19:16:13 +00001465#if defined(TARGET_HAS_ICE)
bellardc33a3462003-07-29 20:50:33 +00001466 if (env->singlestep_enabled != enabled) {
1467 env->singlestep_enabled = enabled;
aliguorie22a25c2009-03-12 20:12:48 +00001468 if (kvm_enabled())
1469 kvm_update_guest_debug(env, 0);
1470 else {
Stuart Bradyccbb4d42009-05-03 12:15:06 +01001471 /* must flush all the translated code to avoid inconsistencies */
aliguorie22a25c2009-03-12 20:12:48 +00001472 /* XXX: only flush what is necessary */
1473 tb_flush(env);
1474 }
bellardc33a3462003-07-29 20:50:33 +00001475 }
1476#endif
1477}
1478
bellard34865132003-10-05 14:28:56 +00001479/* enable or disable low levels log */
1480void cpu_set_log(int log_flags)
1481{
1482 loglevel = log_flags;
1483 if (loglevel && !logfile) {
pbrook11fcfab2007-07-01 18:21:11 +00001484 logfile = fopen(logfilename, log_append ? "a" : "w");
bellard34865132003-10-05 14:28:56 +00001485 if (!logfile) {
1486 perror(logfilename);
1487 _exit(1);
1488 }
bellard9fa3e852004-01-04 18:06:42 +00001489#if !defined(CONFIG_SOFTMMU)
1490 /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1491 {
blueswir1b55266b2008-09-20 08:07:15 +00001492 static char logfile_buf[4096];
bellard9fa3e852004-01-04 18:06:42 +00001493 setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1494 }
Filip Navarabf65f532009-07-27 10:02:04 -05001495#elif !defined(_WIN32)
1496 /* Win32 doesn't support line-buffering and requires size >= 2 */
bellard34865132003-10-05 14:28:56 +00001497 setvbuf(logfile, NULL, _IOLBF, 0);
bellard9fa3e852004-01-04 18:06:42 +00001498#endif
pbrooke735b912007-06-30 13:53:24 +00001499 log_append = 1;
1500 }
1501 if (!loglevel && logfile) {
1502 fclose(logfile);
1503 logfile = NULL;
bellard34865132003-10-05 14:28:56 +00001504 }
1505}
1506
1507void cpu_set_log_filename(const char *filename)
1508{
1509 logfilename = strdup(filename);
pbrooke735b912007-06-30 13:53:24 +00001510 if (logfile) {
1511 fclose(logfile);
1512 logfile = NULL;
1513 }
1514 cpu_set_log(loglevel);
bellard34865132003-10-05 14:28:56 +00001515}
bellardc33a3462003-07-29 20:50:33 +00001516
aurel323098dba2009-03-07 21:28:24 +00001517static void cpu_unlink_tb(CPUState *env)
bellardea041c02003-06-25 16:16:50 +00001518{
Juan Quintela2f7bb872009-07-27 16:13:24 +02001519#if defined(CONFIG_USE_NPTL)
pbrookd5975362008-06-07 20:50:51 +00001520 /* FIXME: TB unchaining isn't SMP safe. For now just ignore the
1521 problem and hope the cpu will stop of its own accord. For userspace
1522 emulation this often isn't actually as bad as it sounds. Often
1523 signals are used primarily to interrupt blocking syscalls. */
1524#else
aurel323098dba2009-03-07 21:28:24 +00001525 TranslationBlock *tb;
1526 static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
1527
1528 tb = env->current_tb;
1529 /* if the cpu is currently executing code, we must unlink it and
1530 all the potentially executing TB */
1531 if (tb && !testandset(&interrupt_lock)) {
1532 env->current_tb = NULL;
1533 tb_reset_jump_recursive(tb);
1534 resetlock(&interrupt_lock);
1535 }
1536#endif
1537}
1538
1539/* mask must never be zero, except for A20 change call */
1540void cpu_interrupt(CPUState *env, int mask)
1541{
1542 int old_mask;
1543
1544 old_mask = env->interrupt_request;
1545 env->interrupt_request |= mask;
1546
aliguori8edac962009-04-24 18:03:45 +00001547#ifndef CONFIG_USER_ONLY
1548 /*
1549 * If called from iothread context, wake the target cpu in
1550 * case its halted.
1551 */
1552 if (!qemu_cpu_self(env)) {
1553 qemu_cpu_kick(env);
1554 return;
1555 }
1556#endif
1557
pbrook2e70f6e2008-06-29 01:03:05 +00001558 if (use_icount) {
pbrook266910c2008-07-09 15:31:50 +00001559 env->icount_decr.u16.high = 0xffff;
pbrook2e70f6e2008-06-29 01:03:05 +00001560#ifndef CONFIG_USER_ONLY
pbrook2e70f6e2008-06-29 01:03:05 +00001561 if (!can_do_io(env)
aurel32be214e62009-03-06 21:48:00 +00001562 && (mask & ~old_mask) != 0) {
pbrook2e70f6e2008-06-29 01:03:05 +00001563 cpu_abort(env, "Raised interrupt while not in I/O function");
1564 }
1565#endif
1566 } else {
aurel323098dba2009-03-07 21:28:24 +00001567 cpu_unlink_tb(env);
bellardea041c02003-06-25 16:16:50 +00001568 }
1569}
1570
bellardb54ad042004-05-20 13:42:52 +00001571void cpu_reset_interrupt(CPUState *env, int mask)
1572{
1573 env->interrupt_request &= ~mask;
1574}
1575
aurel323098dba2009-03-07 21:28:24 +00001576void cpu_exit(CPUState *env)
1577{
1578 env->exit_request = 1;
1579 cpu_unlink_tb(env);
1580}
1581
blueswir1c7cd6a32008-10-02 18:27:46 +00001582const CPULogItem cpu_log_items[] = {
ths5fafdf22007-09-16 21:08:06 +00001583 { CPU_LOG_TB_OUT_ASM, "out_asm",
bellardf193c792004-03-21 17:06:25 +00001584 "show generated host assembly code for each compiled TB" },
1585 { CPU_LOG_TB_IN_ASM, "in_asm",
1586 "show target assembly code for each compiled TB" },
ths5fafdf22007-09-16 21:08:06 +00001587 { CPU_LOG_TB_OP, "op",
bellard57fec1f2008-02-01 10:50:11 +00001588 "show micro ops for each compiled TB" },
bellardf193c792004-03-21 17:06:25 +00001589 { CPU_LOG_TB_OP_OPT, "op_opt",
blueswir1e01a1152008-03-14 17:37:11 +00001590 "show micro ops "
1591#ifdef TARGET_I386
1592 "before eflags optimization and "
bellardf193c792004-03-21 17:06:25 +00001593#endif
blueswir1e01a1152008-03-14 17:37:11 +00001594 "after liveness analysis" },
bellardf193c792004-03-21 17:06:25 +00001595 { CPU_LOG_INT, "int",
1596 "show interrupts/exceptions in short format" },
1597 { CPU_LOG_EXEC, "exec",
1598 "show trace before each executed TB (lots of logs)" },
bellard9fddaa02004-05-21 12:59:32 +00001599 { CPU_LOG_TB_CPU, "cpu",
thse91c8a72007-06-03 13:35:16 +00001600 "show CPU state before block translation" },
bellardf193c792004-03-21 17:06:25 +00001601#ifdef TARGET_I386
1602 { CPU_LOG_PCALL, "pcall",
1603 "show protected mode far calls/returns/exceptions" },
aliguorieca1bdf2009-01-26 19:54:31 +00001604 { CPU_LOG_RESET, "cpu_reset",
1605 "show CPU state before CPU resets" },
bellardf193c792004-03-21 17:06:25 +00001606#endif
bellard8e3a9fd2004-10-09 17:32:58 +00001607#ifdef DEBUG_IOPORT
bellardfd872592004-05-12 19:11:15 +00001608 { CPU_LOG_IOPORT, "ioport",
1609 "show all i/o ports accesses" },
bellard8e3a9fd2004-10-09 17:32:58 +00001610#endif
bellardf193c792004-03-21 17:06:25 +00001611 { 0, NULL, NULL },
1612};
1613
1614static int cmp1(const char *s1, int n, const char *s2)
1615{
1616 if (strlen(s2) != n)
1617 return 0;
1618 return memcmp(s1, s2, n) == 0;
1619}
ths3b46e622007-09-17 08:09:54 +00001620
bellardf193c792004-03-21 17:06:25 +00001621/* takes a comma separated list of log masks. Return 0 if error. */
1622int cpu_str_to_log_mask(const char *str)
1623{
blueswir1c7cd6a32008-10-02 18:27:46 +00001624 const CPULogItem *item;
bellardf193c792004-03-21 17:06:25 +00001625 int mask;
1626 const char *p, *p1;
1627
1628 p = str;
1629 mask = 0;
1630 for(;;) {
1631 p1 = strchr(p, ',');
1632 if (!p1)
1633 p1 = p + strlen(p);
bellard8e3a9fd2004-10-09 17:32:58 +00001634 if(cmp1(p,p1-p,"all")) {
1635 for(item = cpu_log_items; item->mask != 0; item++) {
1636 mask |= item->mask;
1637 }
1638 } else {
bellardf193c792004-03-21 17:06:25 +00001639 for(item = cpu_log_items; item->mask != 0; item++) {
1640 if (cmp1(p, p1 - p, item->name))
1641 goto found;
1642 }
1643 return 0;
bellard8e3a9fd2004-10-09 17:32:58 +00001644 }
bellardf193c792004-03-21 17:06:25 +00001645 found:
1646 mask |= item->mask;
1647 if (*p1 != ',')
1648 break;
1649 p = p1 + 1;
1650 }
1651 return mask;
1652}
bellardea041c02003-06-25 16:16:50 +00001653
bellard75012672003-06-21 13:11:07 +00001654void cpu_abort(CPUState *env, const char *fmt, ...)
1655{
1656 va_list ap;
pbrook493ae1f2007-11-23 16:53:59 +00001657 va_list ap2;
bellard75012672003-06-21 13:11:07 +00001658
1659 va_start(ap, fmt);
pbrook493ae1f2007-11-23 16:53:59 +00001660 va_copy(ap2, ap);
bellard75012672003-06-21 13:11:07 +00001661 fprintf(stderr, "qemu: fatal: ");
1662 vfprintf(stderr, fmt, ap);
1663 fprintf(stderr, "\n");
1664#ifdef TARGET_I386
bellard7fe48482004-10-09 18:08:01 +00001665 cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1666#else
1667 cpu_dump_state(env, stderr, fprintf, 0);
bellard75012672003-06-21 13:11:07 +00001668#endif
aliguori93fcfe32009-01-15 22:34:14 +00001669 if (qemu_log_enabled()) {
1670 qemu_log("qemu: fatal: ");
1671 qemu_log_vprintf(fmt, ap2);
1672 qemu_log("\n");
j_mayerf9373292007-09-29 12:18:20 +00001673#ifdef TARGET_I386
aliguori93fcfe32009-01-15 22:34:14 +00001674 log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
j_mayerf9373292007-09-29 12:18:20 +00001675#else
aliguori93fcfe32009-01-15 22:34:14 +00001676 log_cpu_state(env, 0);
j_mayerf9373292007-09-29 12:18:20 +00001677#endif
aliguori31b1a7b2009-01-15 22:35:09 +00001678 qemu_log_flush();
aliguori93fcfe32009-01-15 22:34:14 +00001679 qemu_log_close();
balrog924edca2007-06-10 14:07:13 +00001680 }
pbrook493ae1f2007-11-23 16:53:59 +00001681 va_end(ap2);
j_mayerf9373292007-09-29 12:18:20 +00001682 va_end(ap);
bellard75012672003-06-21 13:11:07 +00001683 abort();
1684}
1685
thsc5be9f02007-02-28 20:20:53 +00001686CPUState *cpu_copy(CPUState *env)
1687{
ths01ba9812007-12-09 02:22:57 +00001688 CPUState *new_env = cpu_init(env->cpu_model_str);
thsc5be9f02007-02-28 20:20:53 +00001689 CPUState *next_cpu = new_env->next_cpu;
1690 int cpu_index = new_env->cpu_index;
aliguori5a38f082009-01-15 20:16:51 +00001691#if defined(TARGET_HAS_ICE)
1692 CPUBreakpoint *bp;
1693 CPUWatchpoint *wp;
1694#endif
1695
thsc5be9f02007-02-28 20:20:53 +00001696 memcpy(new_env, env, sizeof(CPUState));
aliguori5a38f082009-01-15 20:16:51 +00001697
1698 /* Preserve chaining and index. */
thsc5be9f02007-02-28 20:20:53 +00001699 new_env->next_cpu = next_cpu;
1700 new_env->cpu_index = cpu_index;
aliguori5a38f082009-01-15 20:16:51 +00001701
1702 /* Clone all break/watchpoints.
1703 Note: Once we support ptrace with hw-debug register access, make sure
1704 BP_CPU break/watchpoints are handled correctly on clone. */
1705 TAILQ_INIT(&env->breakpoints);
1706 TAILQ_INIT(&env->watchpoints);
1707#if defined(TARGET_HAS_ICE)
1708 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
1709 cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
1710 }
1711 TAILQ_FOREACH(wp, &env->watchpoints, entry) {
1712 cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
1713 wp->flags, NULL);
1714 }
1715#endif
1716
thsc5be9f02007-02-28 20:20:53 +00001717 return new_env;
1718}
1719
bellard01243112004-01-04 15:48:17 +00001720#if !defined(CONFIG_USER_ONLY)
1721
edgar_igl5c751e92008-05-06 08:44:21 +00001722static inline void tlb_flush_jmp_cache(CPUState *env, target_ulong addr)
1723{
1724 unsigned int i;
1725
1726 /* Discard jump cache entries for any tb which might potentially
1727 overlap the flushed page. */
1728 i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
1729 memset (&env->tb_jmp_cache[i], 0,
1730 TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
1731
1732 i = tb_jmp_cache_hash_page(addr);
1733 memset (&env->tb_jmp_cache[i], 0,
1734 TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
1735}
1736
Igor Kovalenko08738982009-07-12 02:15:40 +04001737static CPUTLBEntry s_cputlb_empty_entry = {
1738 .addr_read = -1,
1739 .addr_write = -1,
1740 .addr_code = -1,
1741 .addend = -1,
1742};
1743
bellardee8b7022004-02-03 23:35:10 +00001744/* NOTE: if flush_global is true, also flush global entries (not
1745 implemented yet) */
1746void tlb_flush(CPUState *env, int flush_global)
bellard33417e72003-08-10 21:47:01 +00001747{
bellard33417e72003-08-10 21:47:01 +00001748 int i;
bellard01243112004-01-04 15:48:17 +00001749
bellard9fa3e852004-01-04 18:06:42 +00001750#if defined(DEBUG_TLB)
1751 printf("tlb_flush:\n");
1752#endif
bellard01243112004-01-04 15:48:17 +00001753 /* must reset current TB so that interrupts cannot modify the
1754 links while we are modifying them */
1755 env->current_tb = NULL;
1756
bellard33417e72003-08-10 21:47:01 +00001757 for(i = 0; i < CPU_TLB_SIZE; i++) {
Isaku Yamahatacfde4bd2009-05-20 11:31:43 +09001758 int mmu_idx;
1759 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
Igor Kovalenko08738982009-07-12 02:15:40 +04001760 env->tlb_table[mmu_idx][i] = s_cputlb_empty_entry;
Isaku Yamahatacfde4bd2009-05-20 11:31:43 +09001761 }
bellard33417e72003-08-10 21:47:01 +00001762 }
bellard9fa3e852004-01-04 18:06:42 +00001763
bellard8a40a182005-11-20 10:35:40 +00001764 memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
bellard9fa3e852004-01-04 18:06:42 +00001765
blueswir1640f42e2009-04-19 10:18:01 +00001766#ifdef CONFIG_KQEMU
bellard0a962c02005-02-10 22:00:27 +00001767 if (env->kqemu_enabled) {
1768 kqemu_flush(env, flush_global);
1769 }
1770#endif
bellarde3db7222005-01-26 22:00:47 +00001771 tlb_flush_count++;
bellard33417e72003-08-10 21:47:01 +00001772}
1773
bellard274da6b2004-05-20 21:56:27 +00001774static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
bellard61382a52003-10-27 21:22:23 +00001775{
ths5fafdf22007-09-16 21:08:06 +00001776 if (addr == (tlb_entry->addr_read &
bellard84b7b8e2005-11-28 21:19:04 +00001777 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
ths5fafdf22007-09-16 21:08:06 +00001778 addr == (tlb_entry->addr_write &
bellard84b7b8e2005-11-28 21:19:04 +00001779 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
ths5fafdf22007-09-16 21:08:06 +00001780 addr == (tlb_entry->addr_code &
bellard84b7b8e2005-11-28 21:19:04 +00001781 (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
Igor Kovalenko08738982009-07-12 02:15:40 +04001782 *tlb_entry = s_cputlb_empty_entry;
bellard84b7b8e2005-11-28 21:19:04 +00001783 }
bellard61382a52003-10-27 21:22:23 +00001784}
1785
bellard2e126692004-04-25 21:28:44 +00001786void tlb_flush_page(CPUState *env, target_ulong addr)
bellard33417e72003-08-10 21:47:01 +00001787{
bellard8a40a182005-11-20 10:35:40 +00001788 int i;
Isaku Yamahatacfde4bd2009-05-20 11:31:43 +09001789 int mmu_idx;
bellard01243112004-01-04 15:48:17 +00001790
bellard9fa3e852004-01-04 18:06:42 +00001791#if defined(DEBUG_TLB)
bellard108c49b2005-07-24 12:55:09 +00001792 printf("tlb_flush_page: " TARGET_FMT_lx "\n", addr);
bellard9fa3e852004-01-04 18:06:42 +00001793#endif
bellard01243112004-01-04 15:48:17 +00001794 /* must reset current TB so that interrupts cannot modify the
1795 links while we are modifying them */
1796 env->current_tb = NULL;
bellard33417e72003-08-10 21:47:01 +00001797
bellard61382a52003-10-27 21:22:23 +00001798 addr &= TARGET_PAGE_MASK;
bellard33417e72003-08-10 21:47:01 +00001799 i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
Isaku Yamahatacfde4bd2009-05-20 11:31:43 +09001800 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++)
1801 tlb_flush_entry(&env->tlb_table[mmu_idx][i], addr);
bellard01243112004-01-04 15:48:17 +00001802
edgar_igl5c751e92008-05-06 08:44:21 +00001803 tlb_flush_jmp_cache(env, addr);
bellard9fa3e852004-01-04 18:06:42 +00001804
blueswir1640f42e2009-04-19 10:18:01 +00001805#ifdef CONFIG_KQEMU
bellard0a962c02005-02-10 22:00:27 +00001806 if (env->kqemu_enabled) {
1807 kqemu_flush_page(env, addr);
1808 }
1809#endif
bellard9fa3e852004-01-04 18:06:42 +00001810}
1811
bellard9fa3e852004-01-04 18:06:42 +00001812/* update the TLBs so that writes to code in the virtual page 'addr'
1813 can be detected */
bellard6a00d602005-11-21 23:25:50 +00001814static void tlb_protect_code(ram_addr_t ram_addr)
bellard61382a52003-10-27 21:22:23 +00001815{
ths5fafdf22007-09-16 21:08:06 +00001816 cpu_physical_memory_reset_dirty(ram_addr,
bellard6a00d602005-11-21 23:25:50 +00001817 ram_addr + TARGET_PAGE_SIZE,
1818 CODE_DIRTY_FLAG);
bellard9fa3e852004-01-04 18:06:42 +00001819}
1820
bellard9fa3e852004-01-04 18:06:42 +00001821/* update the TLB so that writes in physical page 'phys_addr' are no longer
bellard3a7d9292005-08-21 09:26:42 +00001822 tested for self modifying code */
ths5fafdf22007-09-16 21:08:06 +00001823static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
bellard3a7d9292005-08-21 09:26:42 +00001824 target_ulong vaddr)
bellard9fa3e852004-01-04 18:06:42 +00001825{
bellard3a7d9292005-08-21 09:26:42 +00001826 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] |= CODE_DIRTY_FLAG;
bellard1ccde1c2004-02-06 19:46:14 +00001827}
1828
ths5fafdf22007-09-16 21:08:06 +00001829static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
bellard1ccde1c2004-02-06 19:46:14 +00001830 unsigned long start, unsigned long length)
1831{
1832 unsigned long addr;
bellard84b7b8e2005-11-28 21:19:04 +00001833 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1834 addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
bellard1ccde1c2004-02-06 19:46:14 +00001835 if ((addr - start) < length) {
pbrook0f459d12008-06-09 00:20:13 +00001836 tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
bellard1ccde1c2004-02-06 19:46:14 +00001837 }
1838 }
1839}
1840
pbrook5579c7f2009-04-11 14:47:08 +00001841/* Note: start and end must be within the same ram block. */
bellard3a7d9292005-08-21 09:26:42 +00001842void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
bellard0a962c02005-02-10 22:00:27 +00001843 int dirty_flags)
bellard1ccde1c2004-02-06 19:46:14 +00001844{
1845 CPUState *env;
bellard4f2ac232004-04-26 19:44:02 +00001846 unsigned long length, start1;
bellard0a962c02005-02-10 22:00:27 +00001847 int i, mask, len;
1848 uint8_t *p;
bellard1ccde1c2004-02-06 19:46:14 +00001849
1850 start &= TARGET_PAGE_MASK;
1851 end = TARGET_PAGE_ALIGN(end);
1852
1853 length = end - start;
1854 if (length == 0)
1855 return;
bellard0a962c02005-02-10 22:00:27 +00001856 len = length >> TARGET_PAGE_BITS;
blueswir1640f42e2009-04-19 10:18:01 +00001857#ifdef CONFIG_KQEMU
bellard6a00d602005-11-21 23:25:50 +00001858 /* XXX: should not depend on cpu context */
1859 env = first_cpu;
bellard3a7d9292005-08-21 09:26:42 +00001860 if (env->kqemu_enabled) {
bellardf23db162005-08-21 19:12:28 +00001861 ram_addr_t addr;
1862 addr = start;
1863 for(i = 0; i < len; i++) {
1864 kqemu_set_notdirty(env, addr);
1865 addr += TARGET_PAGE_SIZE;
1866 }
bellard3a7d9292005-08-21 09:26:42 +00001867 }
1868#endif
bellardf23db162005-08-21 19:12:28 +00001869 mask = ~dirty_flags;
1870 p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
1871 for(i = 0; i < len; i++)
1872 p[i] &= mask;
1873
bellard1ccde1c2004-02-06 19:46:14 +00001874 /* we modify the TLB cache so that the dirty bit will be set again
1875 when accessing the range */
pbrook5579c7f2009-04-11 14:47:08 +00001876 start1 = (unsigned long)qemu_get_ram_ptr(start);
1877 /* Chek that we don't span multiple blocks - this breaks the
1878 address comparisons below. */
1879 if ((unsigned long)qemu_get_ram_ptr(end - 1) - start1
1880 != (end - 1) - start) {
1881 abort();
1882 }
1883
bellard6a00d602005-11-21 23:25:50 +00001884 for(env = first_cpu; env != NULL; env = env->next_cpu) {
Isaku Yamahatacfde4bd2009-05-20 11:31:43 +09001885 int mmu_idx;
1886 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1887 for(i = 0; i < CPU_TLB_SIZE; i++)
1888 tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
1889 start1, length);
1890 }
bellard6a00d602005-11-21 23:25:50 +00001891 }
bellard1ccde1c2004-02-06 19:46:14 +00001892}
1893
aliguori74576192008-10-06 14:02:03 +00001894int cpu_physical_memory_set_dirty_tracking(int enable)
1895{
1896 in_migration = enable;
Jan Kiszkab0a46a32009-05-02 00:22:51 +02001897 if (kvm_enabled()) {
1898 return kvm_set_migration_log(enable);
1899 }
aliguori74576192008-10-06 14:02:03 +00001900 return 0;
1901}
1902
1903int cpu_physical_memory_get_dirty_tracking(void)
1904{
1905 return in_migration;
1906}
1907
Jan Kiszka151f7742009-05-01 20:52:47 +02001908int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
1909 target_phys_addr_t end_addr)
aliguori2bec46d2008-11-24 20:21:41 +00001910{
Jan Kiszka151f7742009-05-01 20:52:47 +02001911 int ret = 0;
1912
aliguori2bec46d2008-11-24 20:21:41 +00001913 if (kvm_enabled())
Jan Kiszka151f7742009-05-01 20:52:47 +02001914 ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
1915 return ret;
aliguori2bec46d2008-11-24 20:21:41 +00001916}
1917
bellard3a7d9292005-08-21 09:26:42 +00001918static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1919{
1920 ram_addr_t ram_addr;
pbrook5579c7f2009-04-11 14:47:08 +00001921 void *p;
bellard3a7d9292005-08-21 09:26:42 +00001922
bellard84b7b8e2005-11-28 21:19:04 +00001923 if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
pbrook5579c7f2009-04-11 14:47:08 +00001924 p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
1925 + tlb_entry->addend);
1926 ram_addr = qemu_ram_addr_from_host(p);
bellard3a7d9292005-08-21 09:26:42 +00001927 if (!cpu_physical_memory_is_dirty(ram_addr)) {
pbrook0f459d12008-06-09 00:20:13 +00001928 tlb_entry->addr_write |= TLB_NOTDIRTY;
bellard3a7d9292005-08-21 09:26:42 +00001929 }
1930 }
1931}
1932
1933/* update the TLB according to the current state of the dirty bits */
1934void cpu_tlb_update_dirty(CPUState *env)
1935{
1936 int i;
Isaku Yamahatacfde4bd2009-05-20 11:31:43 +09001937 int mmu_idx;
1938 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1939 for(i = 0; i < CPU_TLB_SIZE; i++)
1940 tlb_update_dirty(&env->tlb_table[mmu_idx][i]);
1941 }
bellard3a7d9292005-08-21 09:26:42 +00001942}
1943
pbrook0f459d12008-06-09 00:20:13 +00001944static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, target_ulong vaddr)
bellard1ccde1c2004-02-06 19:46:14 +00001945{
pbrook0f459d12008-06-09 00:20:13 +00001946 if (tlb_entry->addr_write == (vaddr | TLB_NOTDIRTY))
1947 tlb_entry->addr_write = vaddr;
bellard1ccde1c2004-02-06 19:46:14 +00001948}
1949
pbrook0f459d12008-06-09 00:20:13 +00001950/* update the TLB corresponding to virtual page vaddr
1951 so that it is no longer dirty */
1952static inline void tlb_set_dirty(CPUState *env, target_ulong vaddr)
bellard1ccde1c2004-02-06 19:46:14 +00001953{
bellard1ccde1c2004-02-06 19:46:14 +00001954 int i;
Isaku Yamahatacfde4bd2009-05-20 11:31:43 +09001955 int mmu_idx;
bellard1ccde1c2004-02-06 19:46:14 +00001956
pbrook0f459d12008-06-09 00:20:13 +00001957 vaddr &= TARGET_PAGE_MASK;
bellard1ccde1c2004-02-06 19:46:14 +00001958 i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
Isaku Yamahatacfde4bd2009-05-20 11:31:43 +09001959 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++)
1960 tlb_set_dirty1(&env->tlb_table[mmu_idx][i], vaddr);
bellard9fa3e852004-01-04 18:06:42 +00001961}
1962
bellard59817cc2004-02-16 22:01:13 +00001963/* add a new TLB entry. At most one entry for a given virtual address
1964 is permitted. Return 0 if OK or 2 if the page could not be mapped
1965 (can only happen in non SOFTMMU mode for I/O pages or pages
1966 conflicting with the host address space). */
ths5fafdf22007-09-16 21:08:06 +00001967int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
1968 target_phys_addr_t paddr, int prot,
j_mayer6ebbf392007-10-14 07:07:08 +00001969 int mmu_idx, int is_softmmu)
bellard9fa3e852004-01-04 18:06:42 +00001970{
bellard92e873b2004-05-21 14:52:29 +00001971 PhysPageDesc *p;
bellard4f2ac232004-04-26 19:44:02 +00001972 unsigned long pd;
bellard9fa3e852004-01-04 18:06:42 +00001973 unsigned int index;
bellard4f2ac232004-04-26 19:44:02 +00001974 target_ulong address;
pbrook0f459d12008-06-09 00:20:13 +00001975 target_ulong code_address;
bellard108c49b2005-07-24 12:55:09 +00001976 target_phys_addr_t addend;
bellard9fa3e852004-01-04 18:06:42 +00001977 int ret;
bellard84b7b8e2005-11-28 21:19:04 +00001978 CPUTLBEntry *te;
aliguoria1d1bb32008-11-18 20:07:32 +00001979 CPUWatchpoint *wp;
pbrook0f459d12008-06-09 00:20:13 +00001980 target_phys_addr_t iotlb;
bellard9fa3e852004-01-04 18:06:42 +00001981
bellard92e873b2004-05-21 14:52:29 +00001982 p = phys_page_find(paddr >> TARGET_PAGE_BITS);
bellard9fa3e852004-01-04 18:06:42 +00001983 if (!p) {
1984 pd = IO_MEM_UNASSIGNED;
bellard9fa3e852004-01-04 18:06:42 +00001985 } else {
1986 pd = p->phys_offset;
bellard9fa3e852004-01-04 18:06:42 +00001987 }
1988#if defined(DEBUG_TLB)
j_mayer6ebbf392007-10-14 07:07:08 +00001989 printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x idx=%d smmu=%d pd=0x%08lx\n",
1990 vaddr, (int)paddr, prot, mmu_idx, is_softmmu, pd);
bellard9fa3e852004-01-04 18:06:42 +00001991#endif
1992
1993 ret = 0;
pbrook0f459d12008-06-09 00:20:13 +00001994 address = vaddr;
1995 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
1996 /* IO memory case (romd handled later) */
1997 address |= TLB_MMIO;
1998 }
pbrook5579c7f2009-04-11 14:47:08 +00001999 addend = (unsigned long)qemu_get_ram_ptr(pd & TARGET_PAGE_MASK);
pbrook0f459d12008-06-09 00:20:13 +00002000 if ((pd & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
2001 /* Normal RAM. */
2002 iotlb = pd & TARGET_PAGE_MASK;
2003 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM)
2004 iotlb |= IO_MEM_NOTDIRTY;
2005 else
2006 iotlb |= IO_MEM_ROM;
2007 } else {
Stuart Bradyccbb4d42009-05-03 12:15:06 +01002008 /* IO handlers are currently passed a physical address.
pbrook0f459d12008-06-09 00:20:13 +00002009 It would be nice to pass an offset from the base address
2010 of that region. This would avoid having to special case RAM,
2011 and avoid full address decoding in every device.
2012 We can't use the high bits of pd for this because
2013 IO_MEM_ROMD uses these as a ram address. */
pbrook8da3ff12008-12-01 18:59:50 +00002014 iotlb = (pd & ~TARGET_PAGE_MASK);
2015 if (p) {
pbrook8da3ff12008-12-01 18:59:50 +00002016 iotlb += p->region_offset;
2017 } else {
2018 iotlb += paddr;
2019 }
pbrook0f459d12008-06-09 00:20:13 +00002020 }
pbrook6658ffb2007-03-16 23:58:11 +00002021
pbrook0f459d12008-06-09 00:20:13 +00002022 code_address = address;
2023 /* Make accesses to pages with watchpoints go via the
2024 watchpoint trap routines. */
aliguoric0ce9982008-11-25 22:13:57 +00002025 TAILQ_FOREACH(wp, &env->watchpoints, entry) {
aliguoria1d1bb32008-11-18 20:07:32 +00002026 if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) {
pbrook0f459d12008-06-09 00:20:13 +00002027 iotlb = io_mem_watch + paddr;
2028 /* TODO: The memory case can be optimized by not trapping
2029 reads of pages with a write breakpoint. */
2030 address |= TLB_MMIO;
pbrook6658ffb2007-03-16 23:58:11 +00002031 }
pbrook0f459d12008-06-09 00:20:13 +00002032 }
balrogd79acba2007-06-26 20:01:13 +00002033
pbrook0f459d12008-06-09 00:20:13 +00002034 index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
2035 env->iotlb[mmu_idx][index] = iotlb - vaddr;
2036 te = &env->tlb_table[mmu_idx][index];
2037 te->addend = addend - vaddr;
2038 if (prot & PAGE_READ) {
2039 te->addr_read = address;
2040 } else {
2041 te->addr_read = -1;
2042 }
edgar_igl5c751e92008-05-06 08:44:21 +00002043
pbrook0f459d12008-06-09 00:20:13 +00002044 if (prot & PAGE_EXEC) {
2045 te->addr_code = code_address;
2046 } else {
2047 te->addr_code = -1;
2048 }
2049 if (prot & PAGE_WRITE) {
2050 if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM ||
2051 (pd & IO_MEM_ROMD)) {
2052 /* Write access calls the I/O callback. */
2053 te->addr_write = address | TLB_MMIO;
2054 } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
2055 !cpu_physical_memory_is_dirty(pd)) {
2056 te->addr_write = address | TLB_NOTDIRTY;
bellard84b7b8e2005-11-28 21:19:04 +00002057 } else {
pbrook0f459d12008-06-09 00:20:13 +00002058 te->addr_write = address;
bellard9fa3e852004-01-04 18:06:42 +00002059 }
pbrook0f459d12008-06-09 00:20:13 +00002060 } else {
2061 te->addr_write = -1;
bellard9fa3e852004-01-04 18:06:42 +00002062 }
bellard9fa3e852004-01-04 18:06:42 +00002063 return ret;
2064}
2065
bellard01243112004-01-04 15:48:17 +00002066#else
2067
bellardee8b7022004-02-03 23:35:10 +00002068void tlb_flush(CPUState *env, int flush_global)
bellard01243112004-01-04 15:48:17 +00002069{
2070}
2071
bellard2e126692004-04-25 21:28:44 +00002072void tlb_flush_page(CPUState *env, target_ulong addr)
bellard01243112004-01-04 15:48:17 +00002073{
2074}
2075
ths5fafdf22007-09-16 21:08:06 +00002076int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
2077 target_phys_addr_t paddr, int prot,
j_mayer6ebbf392007-10-14 07:07:08 +00002078 int mmu_idx, int is_softmmu)
bellard33417e72003-08-10 21:47:01 +00002079{
bellard9fa3e852004-01-04 18:06:42 +00002080 return 0;
2081}
bellard33417e72003-08-10 21:47:01 +00002082
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002083/*
2084 * Walks guest process memory "regions" one by one
2085 * and calls callback function 'fn' for each region.
2086 */
2087int walk_memory_regions(void *priv,
2088 int (*fn)(void *, unsigned long, unsigned long, unsigned long))
bellard9fa3e852004-01-04 18:06:42 +00002089{
2090 unsigned long start, end;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002091 PageDesc *p = NULL;
bellard9fa3e852004-01-04 18:06:42 +00002092 int i, j, prot, prot1;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002093 int rc = 0;
bellard9fa3e852004-01-04 18:06:42 +00002094
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002095 start = end = -1;
bellard9fa3e852004-01-04 18:06:42 +00002096 prot = 0;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002097
2098 for (i = 0; i <= L1_SIZE; i++) {
2099 p = (i < L1_SIZE) ? l1_map[i] : NULL;
2100 for (j = 0; j < L2_SIZE; j++) {
2101 prot1 = (p == NULL) ? 0 : p[j].flags;
2102 /*
2103 * "region" is one continuous chunk of memory
2104 * that has same protection flags set.
2105 */
bellard9fa3e852004-01-04 18:06:42 +00002106 if (prot1 != prot) {
2107 end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
2108 if (start != -1) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002109 rc = (*fn)(priv, start, end, prot);
2110 /* callback can stop iteration by returning != 0 */
2111 if (rc != 0)
2112 return (rc);
bellard9fa3e852004-01-04 18:06:42 +00002113 }
2114 if (prot1 != 0)
2115 start = end;
2116 else
2117 start = -1;
2118 prot = prot1;
2119 }
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002120 if (p == NULL)
bellard9fa3e852004-01-04 18:06:42 +00002121 break;
2122 }
bellard33417e72003-08-10 21:47:01 +00002123 }
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002124 return (rc);
2125}
2126
2127static int dump_region(void *priv, unsigned long start,
2128 unsigned long end, unsigned long prot)
2129{
2130 FILE *f = (FILE *)priv;
2131
2132 (void) fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
2133 start, end, end - start,
2134 ((prot & PAGE_READ) ? 'r' : '-'),
2135 ((prot & PAGE_WRITE) ? 'w' : '-'),
2136 ((prot & PAGE_EXEC) ? 'x' : '-'));
2137
2138 return (0);
2139}
2140
2141/* dump memory mappings */
2142void page_dump(FILE *f)
2143{
2144 (void) fprintf(f, "%-8s %-8s %-8s %s\n",
2145 "start", "end", "size", "prot");
2146 walk_memory_regions(f, dump_region);
bellard33417e72003-08-10 21:47:01 +00002147}
2148
pbrook53a59602006-03-25 19:31:22 +00002149int page_get_flags(target_ulong address)
bellard33417e72003-08-10 21:47:01 +00002150{
bellard9fa3e852004-01-04 18:06:42 +00002151 PageDesc *p;
2152
2153 p = page_find(address >> TARGET_PAGE_BITS);
bellard33417e72003-08-10 21:47:01 +00002154 if (!p)
bellard9fa3e852004-01-04 18:06:42 +00002155 return 0;
2156 return p->flags;
bellard33417e72003-08-10 21:47:01 +00002157}
2158
bellard9fa3e852004-01-04 18:06:42 +00002159/* modify the flags of a page and invalidate the code if
Stuart Bradyccbb4d42009-05-03 12:15:06 +01002160 necessary. The flag PAGE_WRITE_ORG is positioned automatically
bellard9fa3e852004-01-04 18:06:42 +00002161 depending on PAGE_WRITE */
pbrook53a59602006-03-25 19:31:22 +00002162void page_set_flags(target_ulong start, target_ulong end, int flags)
bellard9fa3e852004-01-04 18:06:42 +00002163{
2164 PageDesc *p;
pbrook53a59602006-03-25 19:31:22 +00002165 target_ulong addr;
bellard9fa3e852004-01-04 18:06:42 +00002166
pbrookc8a706f2008-06-02 16:16:42 +00002167 /* mmap_lock should already be held. */
bellard9fa3e852004-01-04 18:06:42 +00002168 start = start & TARGET_PAGE_MASK;
2169 end = TARGET_PAGE_ALIGN(end);
2170 if (flags & PAGE_WRITE)
2171 flags |= PAGE_WRITE_ORG;
bellard9fa3e852004-01-04 18:06:42 +00002172 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2173 p = page_find_alloc(addr >> TARGET_PAGE_BITS);
pbrook17e23772008-06-09 13:47:45 +00002174 /* We may be called for host regions that are outside guest
2175 address space. */
2176 if (!p)
2177 return;
bellard9fa3e852004-01-04 18:06:42 +00002178 /* if the write protection is set, then we invalidate the code
2179 inside */
ths5fafdf22007-09-16 21:08:06 +00002180 if (!(p->flags & PAGE_WRITE) &&
bellard9fa3e852004-01-04 18:06:42 +00002181 (flags & PAGE_WRITE) &&
2182 p->first_tb) {
bellardd720b932004-04-25 17:57:43 +00002183 tb_invalidate_phys_page(addr, 0, NULL);
bellard9fa3e852004-01-04 18:06:42 +00002184 }
2185 p->flags = flags;
2186 }
bellard9fa3e852004-01-04 18:06:42 +00002187}
2188
ths3d97b402007-11-02 19:02:07 +00002189int page_check_range(target_ulong start, target_ulong len, int flags)
2190{
2191 PageDesc *p;
2192 target_ulong end;
2193 target_ulong addr;
2194
balrog55f280c2008-10-28 10:24:11 +00002195 if (start + len < start)
2196 /* we've wrapped around */
2197 return -1;
2198
ths3d97b402007-11-02 19:02:07 +00002199 end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
2200 start = start & TARGET_PAGE_MASK;
2201
ths3d97b402007-11-02 19:02:07 +00002202 for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2203 p = page_find(addr >> TARGET_PAGE_BITS);
2204 if( !p )
2205 return -1;
2206 if( !(p->flags & PAGE_VALID) )
2207 return -1;
2208
bellarddae32702007-11-14 10:51:00 +00002209 if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
ths3d97b402007-11-02 19:02:07 +00002210 return -1;
bellarddae32702007-11-14 10:51:00 +00002211 if (flags & PAGE_WRITE) {
2212 if (!(p->flags & PAGE_WRITE_ORG))
2213 return -1;
2214 /* unprotect the page if it was put read-only because it
2215 contains translated code */
2216 if (!(p->flags & PAGE_WRITE)) {
2217 if (!page_unprotect(addr, 0, NULL))
2218 return -1;
2219 }
2220 return 0;
2221 }
ths3d97b402007-11-02 19:02:07 +00002222 }
2223 return 0;
2224}
2225
bellard9fa3e852004-01-04 18:06:42 +00002226/* called from signal handler: invalidate the code and unprotect the
Stuart Bradyccbb4d42009-05-03 12:15:06 +01002227 page. Return TRUE if the fault was successfully handled. */
pbrook53a59602006-03-25 19:31:22 +00002228int page_unprotect(target_ulong address, unsigned long pc, void *puc)
bellard9fa3e852004-01-04 18:06:42 +00002229{
2230 unsigned int page_index, prot, pindex;
2231 PageDesc *p, *p1;
pbrook53a59602006-03-25 19:31:22 +00002232 target_ulong host_start, host_end, addr;
bellard9fa3e852004-01-04 18:06:42 +00002233
pbrookc8a706f2008-06-02 16:16:42 +00002234 /* Technically this isn't safe inside a signal handler. However we
2235 know this only ever happens in a synchronous SEGV handler, so in
2236 practice it seems to be ok. */
2237 mmap_lock();
2238
bellard83fb7ad2004-07-05 21:25:26 +00002239 host_start = address & qemu_host_page_mask;
bellard9fa3e852004-01-04 18:06:42 +00002240 page_index = host_start >> TARGET_PAGE_BITS;
2241 p1 = page_find(page_index);
pbrookc8a706f2008-06-02 16:16:42 +00002242 if (!p1) {
2243 mmap_unlock();
bellard9fa3e852004-01-04 18:06:42 +00002244 return 0;
pbrookc8a706f2008-06-02 16:16:42 +00002245 }
bellard83fb7ad2004-07-05 21:25:26 +00002246 host_end = host_start + qemu_host_page_size;
bellard9fa3e852004-01-04 18:06:42 +00002247 p = p1;
2248 prot = 0;
2249 for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
2250 prot |= p->flags;
2251 p++;
2252 }
2253 /* if the page was really writable, then we change its
2254 protection back to writable */
2255 if (prot & PAGE_WRITE_ORG) {
2256 pindex = (address - host_start) >> TARGET_PAGE_BITS;
2257 if (!(p1[pindex].flags & PAGE_WRITE)) {
ths5fafdf22007-09-16 21:08:06 +00002258 mprotect((void *)g2h(host_start), qemu_host_page_size,
bellard9fa3e852004-01-04 18:06:42 +00002259 (prot & PAGE_BITS) | PAGE_WRITE);
2260 p1[pindex].flags |= PAGE_WRITE;
2261 /* and since the content will be modified, we must invalidate
2262 the corresponding translated code. */
bellardd720b932004-04-25 17:57:43 +00002263 tb_invalidate_phys_page(address, pc, puc);
bellard9fa3e852004-01-04 18:06:42 +00002264#ifdef DEBUG_TB_CHECK
2265 tb_invalidate_check(address);
2266#endif
pbrookc8a706f2008-06-02 16:16:42 +00002267 mmap_unlock();
bellard9fa3e852004-01-04 18:06:42 +00002268 return 1;
2269 }
2270 }
pbrookc8a706f2008-06-02 16:16:42 +00002271 mmap_unlock();
bellard9fa3e852004-01-04 18:06:42 +00002272 return 0;
2273}
2274
bellard6a00d602005-11-21 23:25:50 +00002275static inline void tlb_set_dirty(CPUState *env,
2276 unsigned long addr, target_ulong vaddr)
bellard1ccde1c2004-02-06 19:46:14 +00002277{
2278}
bellard9fa3e852004-01-04 18:06:42 +00002279#endif /* defined(CONFIG_USER_ONLY) */
2280
pbrooke2eef172008-06-08 01:09:01 +00002281#if !defined(CONFIG_USER_ONLY)
pbrook8da3ff12008-12-01 18:59:50 +00002282
blueswir1db7b5422007-05-26 17:36:03 +00002283static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
pbrook8da3ff12008-12-01 18:59:50 +00002284 ram_addr_t memory, ram_addr_t region_offset);
aurel3200f82b82008-04-27 21:12:55 +00002285static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
pbrook8da3ff12008-12-01 18:59:50 +00002286 ram_addr_t orig_memory, ram_addr_t region_offset);
blueswir1db7b5422007-05-26 17:36:03 +00002287#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
2288 need_subpage) \
2289 do { \
2290 if (addr > start_addr) \
2291 start_addr2 = 0; \
2292 else { \
2293 start_addr2 = start_addr & ~TARGET_PAGE_MASK; \
2294 if (start_addr2 > 0) \
2295 need_subpage = 1; \
2296 } \
2297 \
blueswir149e9fba2007-05-30 17:25:06 +00002298 if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE) \
blueswir1db7b5422007-05-26 17:36:03 +00002299 end_addr2 = TARGET_PAGE_SIZE - 1; \
2300 else { \
2301 end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
2302 if (end_addr2 < TARGET_PAGE_SIZE - 1) \
2303 need_subpage = 1; \
2304 } \
2305 } while (0)
2306
bellard33417e72003-08-10 21:47:01 +00002307/* register physical memory. 'size' must be a multiple of the target
2308 page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
pbrook8da3ff12008-12-01 18:59:50 +00002309 io memory page. The address used when calling the IO function is
2310 the offset from the start of the region, plus region_offset. Both
Stuart Bradyccbb4d42009-05-03 12:15:06 +01002311 start_addr and region_offset are rounded down to a page boundary
pbrook8da3ff12008-12-01 18:59:50 +00002312 before calculating this offset. This should not be a problem unless
2313 the low bits of start_addr and region_offset differ. */
2314void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
2315 ram_addr_t size,
2316 ram_addr_t phys_offset,
2317 ram_addr_t region_offset)
bellard33417e72003-08-10 21:47:01 +00002318{
bellard108c49b2005-07-24 12:55:09 +00002319 target_phys_addr_t addr, end_addr;
bellard92e873b2004-05-21 14:52:29 +00002320 PhysPageDesc *p;
bellard9d420372006-06-25 22:25:22 +00002321 CPUState *env;
aurel3200f82b82008-04-27 21:12:55 +00002322 ram_addr_t orig_size = size;
blueswir1db7b5422007-05-26 17:36:03 +00002323 void *subpage;
bellard33417e72003-08-10 21:47:01 +00002324
blueswir1640f42e2009-04-19 10:18:01 +00002325#ifdef CONFIG_KQEMU
bellardda260242008-05-30 20:48:25 +00002326 /* XXX: should not depend on cpu context */
2327 env = first_cpu;
2328 if (env->kqemu_enabled) {
2329 kqemu_set_phys_mem(start_addr, size, phys_offset);
2330 }
2331#endif
aliguori7ba1e612008-11-05 16:04:33 +00002332 if (kvm_enabled())
2333 kvm_set_phys_mem(start_addr, size, phys_offset);
2334
pbrook67c4d232009-02-23 13:16:07 +00002335 if (phys_offset == IO_MEM_UNASSIGNED) {
2336 region_offset = start_addr;
2337 }
pbrook8da3ff12008-12-01 18:59:50 +00002338 region_offset &= TARGET_PAGE_MASK;
bellard5fd386f2004-05-23 21:11:22 +00002339 size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
blueswir149e9fba2007-05-30 17:25:06 +00002340 end_addr = start_addr + (target_phys_addr_t)size;
2341 for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
blueswir1db7b5422007-05-26 17:36:03 +00002342 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2343 if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
aurel3200f82b82008-04-27 21:12:55 +00002344 ram_addr_t orig_memory = p->phys_offset;
blueswir1db7b5422007-05-26 17:36:03 +00002345 target_phys_addr_t start_addr2, end_addr2;
2346 int need_subpage = 0;
2347
2348 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2349 need_subpage);
blueswir14254fab2008-01-01 16:57:19 +00002350 if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
blueswir1db7b5422007-05-26 17:36:03 +00002351 if (!(orig_memory & IO_MEM_SUBPAGE)) {
2352 subpage = subpage_init((addr & TARGET_PAGE_MASK),
pbrook8da3ff12008-12-01 18:59:50 +00002353 &p->phys_offset, orig_memory,
2354 p->region_offset);
blueswir1db7b5422007-05-26 17:36:03 +00002355 } else {
2356 subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
2357 >> IO_MEM_SHIFT];
2358 }
pbrook8da3ff12008-12-01 18:59:50 +00002359 subpage_register(subpage, start_addr2, end_addr2, phys_offset,
2360 region_offset);
2361 p->region_offset = 0;
blueswir1db7b5422007-05-26 17:36:03 +00002362 } else {
2363 p->phys_offset = phys_offset;
2364 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2365 (phys_offset & IO_MEM_ROMD))
2366 phys_offset += TARGET_PAGE_SIZE;
2367 }
2368 } else {
2369 p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2370 p->phys_offset = phys_offset;
pbrook8da3ff12008-12-01 18:59:50 +00002371 p->region_offset = region_offset;
blueswir1db7b5422007-05-26 17:36:03 +00002372 if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
pbrook8da3ff12008-12-01 18:59:50 +00002373 (phys_offset & IO_MEM_ROMD)) {
blueswir1db7b5422007-05-26 17:36:03 +00002374 phys_offset += TARGET_PAGE_SIZE;
pbrook0e8f0962008-12-02 09:02:15 +00002375 } else {
blueswir1db7b5422007-05-26 17:36:03 +00002376 target_phys_addr_t start_addr2, end_addr2;
2377 int need_subpage = 0;
2378
2379 CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2380 end_addr2, need_subpage);
2381
blueswir14254fab2008-01-01 16:57:19 +00002382 if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
blueswir1db7b5422007-05-26 17:36:03 +00002383 subpage = subpage_init((addr & TARGET_PAGE_MASK),
pbrook8da3ff12008-12-01 18:59:50 +00002384 &p->phys_offset, IO_MEM_UNASSIGNED,
pbrook67c4d232009-02-23 13:16:07 +00002385 addr & TARGET_PAGE_MASK);
blueswir1db7b5422007-05-26 17:36:03 +00002386 subpage_register(subpage, start_addr2, end_addr2,
pbrook8da3ff12008-12-01 18:59:50 +00002387 phys_offset, region_offset);
2388 p->region_offset = 0;
blueswir1db7b5422007-05-26 17:36:03 +00002389 }
2390 }
2391 }
pbrook8da3ff12008-12-01 18:59:50 +00002392 region_offset += TARGET_PAGE_SIZE;
bellard33417e72003-08-10 21:47:01 +00002393 }
ths3b46e622007-09-17 08:09:54 +00002394
bellard9d420372006-06-25 22:25:22 +00002395 /* since each CPU stores ram addresses in its TLB cache, we must
2396 reset the modified entries */
2397 /* XXX: slow ! */
2398 for(env = first_cpu; env != NULL; env = env->next_cpu) {
2399 tlb_flush(env, 1);
2400 }
bellard33417e72003-08-10 21:47:01 +00002401}
2402
bellardba863452006-09-24 18:41:10 +00002403/* XXX: temporary until new memory mapping API */
aurel3200f82b82008-04-27 21:12:55 +00002404ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr)
bellardba863452006-09-24 18:41:10 +00002405{
2406 PhysPageDesc *p;
2407
2408 p = phys_page_find(addr >> TARGET_PAGE_BITS);
2409 if (!p)
2410 return IO_MEM_UNASSIGNED;
2411 return p->phys_offset;
2412}
2413
aliguorif65ed4c2008-12-09 20:09:57 +00002414void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
2415{
2416 if (kvm_enabled())
2417 kvm_coalesce_mmio_region(addr, size);
2418}
2419
2420void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
2421{
2422 if (kvm_enabled())
2423 kvm_uncoalesce_mmio_region(addr, size);
2424}
2425
blueswir1640f42e2009-04-19 10:18:01 +00002426#ifdef CONFIG_KQEMU
bellarde9a1ab12007-02-08 23:08:38 +00002427/* XXX: better than nothing */
pbrook94a6b542009-04-11 17:15:54 +00002428static ram_addr_t kqemu_ram_alloc(ram_addr_t size)
bellarde9a1ab12007-02-08 23:08:38 +00002429{
2430 ram_addr_t addr;
pbrook94a6b542009-04-11 17:15:54 +00002431 if ((last_ram_offset + size) > kqemu_phys_ram_size) {
ths012a7042008-10-02 17:34:21 +00002432 fprintf(stderr, "Not enough memory (requested_size = %" PRIu64 ", max memory = %" PRIu64 ")\n",
pbrook94a6b542009-04-11 17:15:54 +00002433 (uint64_t)size, (uint64_t)kqemu_phys_ram_size);
bellarde9a1ab12007-02-08 23:08:38 +00002434 abort();
2435 }
pbrook94a6b542009-04-11 17:15:54 +00002436 addr = last_ram_offset;
2437 last_ram_offset = TARGET_PAGE_ALIGN(last_ram_offset + size);
bellarde9a1ab12007-02-08 23:08:38 +00002438 return addr;
2439}
pbrook94a6b542009-04-11 17:15:54 +00002440#endif
2441
2442ram_addr_t qemu_ram_alloc(ram_addr_t size)
2443{
2444 RAMBlock *new_block;
2445
blueswir1640f42e2009-04-19 10:18:01 +00002446#ifdef CONFIG_KQEMU
pbrook94a6b542009-04-11 17:15:54 +00002447 if (kqemu_phys_ram_base) {
2448 return kqemu_ram_alloc(size);
2449 }
2450#endif
2451
2452 size = TARGET_PAGE_ALIGN(size);
2453 new_block = qemu_malloc(sizeof(*new_block));
2454
2455 new_block->host = qemu_vmalloc(size);
2456 new_block->offset = last_ram_offset;
2457 new_block->length = size;
2458
2459 new_block->next = ram_blocks;
2460 ram_blocks = new_block;
2461
2462 phys_ram_dirty = qemu_realloc(phys_ram_dirty,
2463 (last_ram_offset + size) >> TARGET_PAGE_BITS);
2464 memset(phys_ram_dirty + (last_ram_offset >> TARGET_PAGE_BITS),
2465 0xff, size >> TARGET_PAGE_BITS);
2466
2467 last_ram_offset += size;
2468
Jan Kiszka6f0437e2009-04-26 18:03:40 +02002469 if (kvm_enabled())
2470 kvm_setup_guest_memory(new_block->host, size);
2471
pbrook94a6b542009-04-11 17:15:54 +00002472 return new_block->offset;
2473}
bellarde9a1ab12007-02-08 23:08:38 +00002474
2475void qemu_ram_free(ram_addr_t addr)
2476{
pbrook94a6b542009-04-11 17:15:54 +00002477 /* TODO: implement this. */
bellarde9a1ab12007-02-08 23:08:38 +00002478}
2479
pbrookdc828ca2009-04-09 22:21:07 +00002480/* Return a host pointer to ram allocated with qemu_ram_alloc.
pbrook5579c7f2009-04-11 14:47:08 +00002481 With the exception of the softmmu code in this file, this should
2482 only be used for local memory (e.g. video ram) that the device owns,
2483 and knows it isn't going to access beyond the end of the block.
2484
2485 It should not be used for general purpose DMA.
2486 Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
2487 */
pbrookdc828ca2009-04-09 22:21:07 +00002488void *qemu_get_ram_ptr(ram_addr_t addr)
2489{
pbrook94a6b542009-04-11 17:15:54 +00002490 RAMBlock *prev;
2491 RAMBlock **prevp;
2492 RAMBlock *block;
2493
blueswir1640f42e2009-04-19 10:18:01 +00002494#ifdef CONFIG_KQEMU
pbrook94a6b542009-04-11 17:15:54 +00002495 if (kqemu_phys_ram_base) {
2496 return kqemu_phys_ram_base + addr;
2497 }
2498#endif
2499
2500 prev = NULL;
2501 prevp = &ram_blocks;
2502 block = ram_blocks;
2503 while (block && (block->offset > addr
2504 || block->offset + block->length <= addr)) {
2505 if (prev)
2506 prevp = &prev->next;
2507 prev = block;
2508 block = block->next;
2509 }
2510 if (!block) {
2511 fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2512 abort();
2513 }
2514 /* Move this entry to to start of the list. */
2515 if (prev) {
2516 prev->next = block->next;
2517 block->next = *prevp;
2518 *prevp = block;
2519 }
2520 return block->host + (addr - block->offset);
pbrookdc828ca2009-04-09 22:21:07 +00002521}
2522
pbrook5579c7f2009-04-11 14:47:08 +00002523/* Some of the softmmu routines need to translate from a host pointer
2524 (typically a TLB entry) back to a ram offset. */
2525ram_addr_t qemu_ram_addr_from_host(void *ptr)
2526{
pbrook94a6b542009-04-11 17:15:54 +00002527 RAMBlock *prev;
2528 RAMBlock **prevp;
2529 RAMBlock *block;
2530 uint8_t *host = ptr;
2531
blueswir1640f42e2009-04-19 10:18:01 +00002532#ifdef CONFIG_KQEMU
pbrook94a6b542009-04-11 17:15:54 +00002533 if (kqemu_phys_ram_base) {
2534 return host - kqemu_phys_ram_base;
2535 }
2536#endif
2537
2538 prev = NULL;
2539 prevp = &ram_blocks;
2540 block = ram_blocks;
2541 while (block && (block->host > host
2542 || block->host + block->length <= host)) {
2543 if (prev)
2544 prevp = &prev->next;
2545 prev = block;
2546 block = block->next;
2547 }
2548 if (!block) {
2549 fprintf(stderr, "Bad ram pointer %p\n", ptr);
2550 abort();
2551 }
2552 return block->offset + (host - block->host);
pbrook5579c7f2009-04-11 14:47:08 +00002553}
2554
bellarda4193c82004-06-03 14:01:43 +00002555static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
bellard33417e72003-08-10 21:47:01 +00002556{
pbrook67d3b952006-12-18 05:03:52 +00002557#ifdef DEBUG_UNASSIGNED
blueswir1ab3d1722007-11-04 07:31:40 +00002558 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
pbrook67d3b952006-12-18 05:03:52 +00002559#endif
edgar_igl0a6f8a62008-12-29 14:39:57 +00002560#if defined(TARGET_SPARC)
blueswir1e18231a2008-10-06 18:46:28 +00002561 do_unassigned_access(addr, 0, 0, 0, 1);
2562#endif
2563 return 0;
2564}
2565
2566static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr)
2567{
2568#ifdef DEBUG_UNASSIGNED
2569 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2570#endif
edgar_igl0a6f8a62008-12-29 14:39:57 +00002571#if defined(TARGET_SPARC)
blueswir1e18231a2008-10-06 18:46:28 +00002572 do_unassigned_access(addr, 0, 0, 0, 2);
2573#endif
2574 return 0;
2575}
2576
2577static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr)
2578{
2579#ifdef DEBUG_UNASSIGNED
2580 printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2581#endif
edgar_igl0a6f8a62008-12-29 14:39:57 +00002582#if defined(TARGET_SPARC)
blueswir1e18231a2008-10-06 18:46:28 +00002583 do_unassigned_access(addr, 0, 0, 0, 4);
blueswir1b4f0a312007-05-06 17:59:24 +00002584#endif
bellard33417e72003-08-10 21:47:01 +00002585 return 0;
2586}
2587
bellarda4193c82004-06-03 14:01:43 +00002588static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
bellard33417e72003-08-10 21:47:01 +00002589{
pbrook67d3b952006-12-18 05:03:52 +00002590#ifdef DEBUG_UNASSIGNED
blueswir1ab3d1722007-11-04 07:31:40 +00002591 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
pbrook67d3b952006-12-18 05:03:52 +00002592#endif
edgar_igl0a6f8a62008-12-29 14:39:57 +00002593#if defined(TARGET_SPARC)
blueswir1e18231a2008-10-06 18:46:28 +00002594 do_unassigned_access(addr, 1, 0, 0, 1);
2595#endif
2596}
2597
2598static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
2599{
2600#ifdef DEBUG_UNASSIGNED
2601 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2602#endif
edgar_igl0a6f8a62008-12-29 14:39:57 +00002603#if defined(TARGET_SPARC)
blueswir1e18231a2008-10-06 18:46:28 +00002604 do_unassigned_access(addr, 1, 0, 0, 2);
2605#endif
2606}
2607
2608static void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
2609{
2610#ifdef DEBUG_UNASSIGNED
2611 printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2612#endif
edgar_igl0a6f8a62008-12-29 14:39:57 +00002613#if defined(TARGET_SPARC)
blueswir1e18231a2008-10-06 18:46:28 +00002614 do_unassigned_access(addr, 1, 0, 0, 4);
blueswir1b4f0a312007-05-06 17:59:24 +00002615#endif
bellard33417e72003-08-10 21:47:01 +00002616}
2617
2618static CPUReadMemoryFunc *unassigned_mem_read[3] = {
2619 unassigned_mem_readb,
blueswir1e18231a2008-10-06 18:46:28 +00002620 unassigned_mem_readw,
2621 unassigned_mem_readl,
bellard33417e72003-08-10 21:47:01 +00002622};
2623
2624static CPUWriteMemoryFunc *unassigned_mem_write[3] = {
2625 unassigned_mem_writeb,
blueswir1e18231a2008-10-06 18:46:28 +00002626 unassigned_mem_writew,
2627 unassigned_mem_writel,
bellard33417e72003-08-10 21:47:01 +00002628};
2629
pbrook0f459d12008-06-09 00:20:13 +00002630static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr,
2631 uint32_t val)
bellard1ccde1c2004-02-06 19:46:14 +00002632{
bellard3a7d9292005-08-21 09:26:42 +00002633 int dirty_flags;
bellard3a7d9292005-08-21 09:26:42 +00002634 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2635 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2636#if !defined(CONFIG_USER_ONLY)
2637 tb_invalidate_phys_page_fast(ram_addr, 1);
2638 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2639#endif
2640 }
pbrook5579c7f2009-04-11 14:47:08 +00002641 stb_p(qemu_get_ram_ptr(ram_addr), val);
blueswir1640f42e2009-04-19 10:18:01 +00002642#ifdef CONFIG_KQEMU
bellardf32fc642006-02-08 22:43:39 +00002643 if (cpu_single_env->kqemu_enabled &&
2644 (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2645 kqemu_modify_page(cpu_single_env, ram_addr);
2646#endif
bellardf23db162005-08-21 19:12:28 +00002647 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2648 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2649 /* we remove the notdirty callback only if the code has been
2650 flushed */
2651 if (dirty_flags == 0xff)
pbrook2e70f6e2008-06-29 01:03:05 +00002652 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
bellard1ccde1c2004-02-06 19:46:14 +00002653}
2654
pbrook0f459d12008-06-09 00:20:13 +00002655static void notdirty_mem_writew(void *opaque, target_phys_addr_t ram_addr,
2656 uint32_t val)
bellard1ccde1c2004-02-06 19:46:14 +00002657{
bellard3a7d9292005-08-21 09:26:42 +00002658 int dirty_flags;
bellard3a7d9292005-08-21 09:26:42 +00002659 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2660 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2661#if !defined(CONFIG_USER_ONLY)
2662 tb_invalidate_phys_page_fast(ram_addr, 2);
2663 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2664#endif
2665 }
pbrook5579c7f2009-04-11 14:47:08 +00002666 stw_p(qemu_get_ram_ptr(ram_addr), val);
blueswir1640f42e2009-04-19 10:18:01 +00002667#ifdef CONFIG_KQEMU
bellardf32fc642006-02-08 22:43:39 +00002668 if (cpu_single_env->kqemu_enabled &&
2669 (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2670 kqemu_modify_page(cpu_single_env, ram_addr);
2671#endif
bellardf23db162005-08-21 19:12:28 +00002672 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2673 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2674 /* we remove the notdirty callback only if the code has been
2675 flushed */
2676 if (dirty_flags == 0xff)
pbrook2e70f6e2008-06-29 01:03:05 +00002677 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
bellard1ccde1c2004-02-06 19:46:14 +00002678}
2679
pbrook0f459d12008-06-09 00:20:13 +00002680static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr,
2681 uint32_t val)
bellard1ccde1c2004-02-06 19:46:14 +00002682{
bellard3a7d9292005-08-21 09:26:42 +00002683 int dirty_flags;
bellard3a7d9292005-08-21 09:26:42 +00002684 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2685 if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2686#if !defined(CONFIG_USER_ONLY)
2687 tb_invalidate_phys_page_fast(ram_addr, 4);
2688 dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2689#endif
2690 }
pbrook5579c7f2009-04-11 14:47:08 +00002691 stl_p(qemu_get_ram_ptr(ram_addr), val);
blueswir1640f42e2009-04-19 10:18:01 +00002692#ifdef CONFIG_KQEMU
bellardf32fc642006-02-08 22:43:39 +00002693 if (cpu_single_env->kqemu_enabled &&
2694 (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2695 kqemu_modify_page(cpu_single_env, ram_addr);
2696#endif
bellardf23db162005-08-21 19:12:28 +00002697 dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2698 phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2699 /* we remove the notdirty callback only if the code has been
2700 flushed */
2701 if (dirty_flags == 0xff)
pbrook2e70f6e2008-06-29 01:03:05 +00002702 tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
bellard1ccde1c2004-02-06 19:46:14 +00002703}
2704
bellard3a7d9292005-08-21 09:26:42 +00002705static CPUReadMemoryFunc *error_mem_read[3] = {
2706 NULL, /* never used */
2707 NULL, /* never used */
2708 NULL, /* never used */
2709};
2710
bellard1ccde1c2004-02-06 19:46:14 +00002711static CPUWriteMemoryFunc *notdirty_mem_write[3] = {
2712 notdirty_mem_writeb,
2713 notdirty_mem_writew,
2714 notdirty_mem_writel,
2715};
2716
pbrook0f459d12008-06-09 00:20:13 +00002717/* Generate a debug exception if a watchpoint has been hit. */
aliguorib4051332008-11-18 20:14:20 +00002718static void check_watchpoint(int offset, int len_mask, int flags)
pbrook0f459d12008-06-09 00:20:13 +00002719{
2720 CPUState *env = cpu_single_env;
aliguori06d55cc2008-11-18 20:24:06 +00002721 target_ulong pc, cs_base;
2722 TranslationBlock *tb;
pbrook0f459d12008-06-09 00:20:13 +00002723 target_ulong vaddr;
aliguoria1d1bb32008-11-18 20:07:32 +00002724 CPUWatchpoint *wp;
aliguori06d55cc2008-11-18 20:24:06 +00002725 int cpu_flags;
pbrook0f459d12008-06-09 00:20:13 +00002726
aliguori06d55cc2008-11-18 20:24:06 +00002727 if (env->watchpoint_hit) {
2728 /* We re-entered the check after replacing the TB. Now raise
2729 * the debug interrupt so that is will trigger after the
2730 * current instruction. */
2731 cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2732 return;
2733 }
pbrook2e70f6e2008-06-29 01:03:05 +00002734 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
aliguoric0ce9982008-11-25 22:13:57 +00002735 TAILQ_FOREACH(wp, &env->watchpoints, entry) {
aliguorib4051332008-11-18 20:14:20 +00002736 if ((vaddr == (wp->vaddr & len_mask) ||
2737 (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
aliguori6e140f22008-11-18 20:37:55 +00002738 wp->flags |= BP_WATCHPOINT_HIT;
2739 if (!env->watchpoint_hit) {
2740 env->watchpoint_hit = wp;
2741 tb = tb_find_pc(env->mem_io_pc);
2742 if (!tb) {
2743 cpu_abort(env, "check_watchpoint: could not find TB for "
2744 "pc=%p", (void *)env->mem_io_pc);
2745 }
2746 cpu_restore_state(tb, env, env->mem_io_pc, NULL);
2747 tb_phys_invalidate(tb, -1);
2748 if (wp->flags & BP_STOP_BEFORE_ACCESS) {
2749 env->exception_index = EXCP_DEBUG;
2750 } else {
2751 cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
2752 tb_gen_code(env, pc, cs_base, cpu_flags, 1);
2753 }
2754 cpu_resume_from_signal(env, NULL);
aliguori06d55cc2008-11-18 20:24:06 +00002755 }
aliguori6e140f22008-11-18 20:37:55 +00002756 } else {
2757 wp->flags &= ~BP_WATCHPOINT_HIT;
pbrook0f459d12008-06-09 00:20:13 +00002758 }
2759 }
2760}
2761
pbrook6658ffb2007-03-16 23:58:11 +00002762/* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
2763 so these check for a hit then pass through to the normal out-of-line
2764 phys routines. */
2765static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
2766{
aliguorib4051332008-11-18 20:14:20 +00002767 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ);
pbrook6658ffb2007-03-16 23:58:11 +00002768 return ldub_phys(addr);
2769}
2770
2771static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
2772{
aliguorib4051332008-11-18 20:14:20 +00002773 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ);
pbrook6658ffb2007-03-16 23:58:11 +00002774 return lduw_phys(addr);
2775}
2776
2777static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
2778{
aliguorib4051332008-11-18 20:14:20 +00002779 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ);
pbrook6658ffb2007-03-16 23:58:11 +00002780 return ldl_phys(addr);
2781}
2782
pbrook6658ffb2007-03-16 23:58:11 +00002783static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
2784 uint32_t val)
2785{
aliguorib4051332008-11-18 20:14:20 +00002786 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_WRITE);
pbrook6658ffb2007-03-16 23:58:11 +00002787 stb_phys(addr, val);
2788}
2789
2790static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
2791 uint32_t val)
2792{
aliguorib4051332008-11-18 20:14:20 +00002793 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_WRITE);
pbrook6658ffb2007-03-16 23:58:11 +00002794 stw_phys(addr, val);
2795}
2796
2797static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
2798 uint32_t val)
2799{
aliguorib4051332008-11-18 20:14:20 +00002800 check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE);
pbrook6658ffb2007-03-16 23:58:11 +00002801 stl_phys(addr, val);
2802}
2803
2804static CPUReadMemoryFunc *watch_mem_read[3] = {
2805 watch_mem_readb,
2806 watch_mem_readw,
2807 watch_mem_readl,
2808};
2809
2810static CPUWriteMemoryFunc *watch_mem_write[3] = {
2811 watch_mem_writeb,
2812 watch_mem_writew,
2813 watch_mem_writel,
2814};
pbrook6658ffb2007-03-16 23:58:11 +00002815
blueswir1db7b5422007-05-26 17:36:03 +00002816static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr,
2817 unsigned int len)
2818{
blueswir1db7b5422007-05-26 17:36:03 +00002819 uint32_t ret;
2820 unsigned int idx;
2821
pbrook8da3ff12008-12-01 18:59:50 +00002822 idx = SUBPAGE_IDX(addr);
blueswir1db7b5422007-05-26 17:36:03 +00002823#if defined(DEBUG_SUBPAGE)
2824 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
2825 mmio, len, addr, idx);
2826#endif
pbrook8da3ff12008-12-01 18:59:50 +00002827 ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len],
2828 addr + mmio->region_offset[idx][0][len]);
blueswir1db7b5422007-05-26 17:36:03 +00002829
2830 return ret;
2831}
2832
2833static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
2834 uint32_t value, unsigned int len)
2835{
blueswir1db7b5422007-05-26 17:36:03 +00002836 unsigned int idx;
2837
pbrook8da3ff12008-12-01 18:59:50 +00002838 idx = SUBPAGE_IDX(addr);
blueswir1db7b5422007-05-26 17:36:03 +00002839#if defined(DEBUG_SUBPAGE)
2840 printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
2841 mmio, len, addr, idx, value);
2842#endif
pbrook8da3ff12008-12-01 18:59:50 +00002843 (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len],
2844 addr + mmio->region_offset[idx][1][len],
2845 value);
blueswir1db7b5422007-05-26 17:36:03 +00002846}
2847
2848static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
2849{
2850#if defined(DEBUG_SUBPAGE)
2851 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2852#endif
2853
2854 return subpage_readlen(opaque, addr, 0);
2855}
2856
2857static void subpage_writeb (void *opaque, target_phys_addr_t addr,
2858 uint32_t value)
2859{
2860#if defined(DEBUG_SUBPAGE)
2861 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2862#endif
2863 subpage_writelen(opaque, addr, value, 0);
2864}
2865
2866static uint32_t subpage_readw (void *opaque, target_phys_addr_t addr)
2867{
2868#if defined(DEBUG_SUBPAGE)
2869 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2870#endif
2871
2872 return subpage_readlen(opaque, addr, 1);
2873}
2874
2875static void subpage_writew (void *opaque, target_phys_addr_t addr,
2876 uint32_t value)
2877{
2878#if defined(DEBUG_SUBPAGE)
2879 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2880#endif
2881 subpage_writelen(opaque, addr, value, 1);
2882}
2883
2884static uint32_t subpage_readl (void *opaque, target_phys_addr_t addr)
2885{
2886#if defined(DEBUG_SUBPAGE)
2887 printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2888#endif
2889
2890 return subpage_readlen(opaque, addr, 2);
2891}
2892
2893static void subpage_writel (void *opaque,
2894 target_phys_addr_t addr, uint32_t value)
2895{
2896#if defined(DEBUG_SUBPAGE)
2897 printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2898#endif
2899 subpage_writelen(opaque, addr, value, 2);
2900}
2901
2902static CPUReadMemoryFunc *subpage_read[] = {
2903 &subpage_readb,
2904 &subpage_readw,
2905 &subpage_readl,
2906};
2907
2908static CPUWriteMemoryFunc *subpage_write[] = {
2909 &subpage_writeb,
2910 &subpage_writew,
2911 &subpage_writel,
2912};
2913
2914static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
pbrook8da3ff12008-12-01 18:59:50 +00002915 ram_addr_t memory, ram_addr_t region_offset)
blueswir1db7b5422007-05-26 17:36:03 +00002916{
2917 int idx, eidx;
blueswir14254fab2008-01-01 16:57:19 +00002918 unsigned int i;
blueswir1db7b5422007-05-26 17:36:03 +00002919
2920 if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
2921 return -1;
2922 idx = SUBPAGE_IDX(start);
2923 eidx = SUBPAGE_IDX(end);
2924#if defined(DEBUG_SUBPAGE)
Blue Swirl0bf9e312009-07-20 17:19:25 +00002925 printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__,
blueswir1db7b5422007-05-26 17:36:03 +00002926 mmio, start, end, idx, eidx, memory);
2927#endif
2928 memory >>= IO_MEM_SHIFT;
2929 for (; idx <= eidx; idx++) {
blueswir14254fab2008-01-01 16:57:19 +00002930 for (i = 0; i < 4; i++) {
blueswir13ee89922008-01-02 19:45:26 +00002931 if (io_mem_read[memory][i]) {
2932 mmio->mem_read[idx][i] = &io_mem_read[memory][i];
2933 mmio->opaque[idx][0][i] = io_mem_opaque[memory];
pbrook8da3ff12008-12-01 18:59:50 +00002934 mmio->region_offset[idx][0][i] = region_offset;
blueswir13ee89922008-01-02 19:45:26 +00002935 }
2936 if (io_mem_write[memory][i]) {
2937 mmio->mem_write[idx][i] = &io_mem_write[memory][i];
2938 mmio->opaque[idx][1][i] = io_mem_opaque[memory];
pbrook8da3ff12008-12-01 18:59:50 +00002939 mmio->region_offset[idx][1][i] = region_offset;
blueswir13ee89922008-01-02 19:45:26 +00002940 }
blueswir14254fab2008-01-01 16:57:19 +00002941 }
blueswir1db7b5422007-05-26 17:36:03 +00002942 }
2943
2944 return 0;
2945}
2946
aurel3200f82b82008-04-27 21:12:55 +00002947static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
pbrook8da3ff12008-12-01 18:59:50 +00002948 ram_addr_t orig_memory, ram_addr_t region_offset)
blueswir1db7b5422007-05-26 17:36:03 +00002949{
2950 subpage_t *mmio;
2951 int subpage_memory;
2952
2953 mmio = qemu_mallocz(sizeof(subpage_t));
aliguori1eec6142009-02-05 22:06:18 +00002954
2955 mmio->base = base;
Avi Kivity1eed09c2009-06-14 11:38:51 +03002956 subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
blueswir1db7b5422007-05-26 17:36:03 +00002957#if defined(DEBUG_SUBPAGE)
aliguori1eec6142009-02-05 22:06:18 +00002958 printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
2959 mmio, base, TARGET_PAGE_SIZE, subpage_memory);
blueswir1db7b5422007-05-26 17:36:03 +00002960#endif
aliguori1eec6142009-02-05 22:06:18 +00002961 *phys = subpage_memory | IO_MEM_SUBPAGE;
2962 subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
pbrook8da3ff12008-12-01 18:59:50 +00002963 region_offset);
blueswir1db7b5422007-05-26 17:36:03 +00002964
2965 return mmio;
2966}
2967
aliguori88715652009-02-11 15:20:58 +00002968static int get_free_io_mem_idx(void)
2969{
2970 int i;
2971
2972 for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
2973 if (!io_mem_used[i]) {
2974 io_mem_used[i] = 1;
2975 return i;
2976 }
2977
2978 return -1;
2979}
2980
bellard33417e72003-08-10 21:47:01 +00002981/* mem_read and mem_write are arrays of functions containing the
2982 function to access byte (index 0), word (index 1) and dword (index
Paul Brook0b4e6e32009-04-30 18:37:55 +01002983 2). Functions can be omitted with a NULL function pointer.
blueswir13ee89922008-01-02 19:45:26 +00002984 If io_index is non zero, the corresponding io zone is
blueswir14254fab2008-01-01 16:57:19 +00002985 modified. If it is zero, a new io zone is allocated. The return
2986 value can be used with cpu_register_physical_memory(). (-1) is
2987 returned if error. */
Avi Kivity1eed09c2009-06-14 11:38:51 +03002988static int cpu_register_io_memory_fixed(int io_index,
2989 CPUReadMemoryFunc **mem_read,
2990 CPUWriteMemoryFunc **mem_write,
2991 void *opaque)
bellard33417e72003-08-10 21:47:01 +00002992{
blueswir14254fab2008-01-01 16:57:19 +00002993 int i, subwidth = 0;
bellard33417e72003-08-10 21:47:01 +00002994
2995 if (io_index <= 0) {
aliguori88715652009-02-11 15:20:58 +00002996 io_index = get_free_io_mem_idx();
2997 if (io_index == -1)
2998 return io_index;
bellard33417e72003-08-10 21:47:01 +00002999 } else {
Avi Kivity1eed09c2009-06-14 11:38:51 +03003000 io_index >>= IO_MEM_SHIFT;
bellard33417e72003-08-10 21:47:01 +00003001 if (io_index >= IO_MEM_NB_ENTRIES)
3002 return -1;
3003 }
bellardb5ff1b32005-11-26 10:38:39 +00003004
bellard33417e72003-08-10 21:47:01 +00003005 for(i = 0;i < 3; i++) {
blueswir14254fab2008-01-01 16:57:19 +00003006 if (!mem_read[i] || !mem_write[i])
3007 subwidth = IO_MEM_SUBWIDTH;
bellard33417e72003-08-10 21:47:01 +00003008 io_mem_read[io_index][i] = mem_read[i];
3009 io_mem_write[io_index][i] = mem_write[i];
3010 }
bellarda4193c82004-06-03 14:01:43 +00003011 io_mem_opaque[io_index] = opaque;
blueswir14254fab2008-01-01 16:57:19 +00003012 return (io_index << IO_MEM_SHIFT) | subwidth;
bellard33417e72003-08-10 21:47:01 +00003013}
bellard61382a52003-10-27 21:22:23 +00003014
Avi Kivity1eed09c2009-06-14 11:38:51 +03003015int cpu_register_io_memory(CPUReadMemoryFunc **mem_read,
3016 CPUWriteMemoryFunc **mem_write,
3017 void *opaque)
3018{
3019 return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
3020}
3021
aliguori88715652009-02-11 15:20:58 +00003022void cpu_unregister_io_memory(int io_table_address)
3023{
3024 int i;
3025 int io_index = io_table_address >> IO_MEM_SHIFT;
3026
3027 for (i=0;i < 3; i++) {
3028 io_mem_read[io_index][i] = unassigned_mem_read[i];
3029 io_mem_write[io_index][i] = unassigned_mem_write[i];
3030 }
3031 io_mem_opaque[io_index] = NULL;
3032 io_mem_used[io_index] = 0;
3033}
3034
Avi Kivitye9179ce2009-06-14 11:38:52 +03003035static void io_mem_init(void)
3036{
3037 int i;
3038
3039 cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read, unassigned_mem_write, NULL);
3040 cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read, unassigned_mem_write, NULL);
3041 cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read, notdirty_mem_write, NULL);
3042 for (i=0; i<5; i++)
3043 io_mem_used[i] = 1;
3044
3045 io_mem_watch = cpu_register_io_memory(watch_mem_read,
3046 watch_mem_write, NULL);
3047#ifdef CONFIG_KQEMU
3048 if (kqemu_phys_ram_base) {
3049 /* alloc dirty bits array */
3050 phys_ram_dirty = qemu_vmalloc(kqemu_phys_ram_size >> TARGET_PAGE_BITS);
3051 memset(phys_ram_dirty, 0xff, kqemu_phys_ram_size >> TARGET_PAGE_BITS);
3052 }
3053#endif
3054}
3055
pbrooke2eef172008-06-08 01:09:01 +00003056#endif /* !defined(CONFIG_USER_ONLY) */
3057
bellard13eb76e2004-01-24 15:23:36 +00003058/* physical memory access (slow version, mainly for debug) */
3059#if defined(CONFIG_USER_ONLY)
ths5fafdf22007-09-16 21:08:06 +00003060void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
bellard13eb76e2004-01-24 15:23:36 +00003061 int len, int is_write)
3062{
3063 int l, flags;
3064 target_ulong page;
pbrook53a59602006-03-25 19:31:22 +00003065 void * p;
bellard13eb76e2004-01-24 15:23:36 +00003066
3067 while (len > 0) {
3068 page = addr & TARGET_PAGE_MASK;
3069 l = (page + TARGET_PAGE_SIZE) - addr;
3070 if (l > len)
3071 l = len;
3072 flags = page_get_flags(page);
3073 if (!(flags & PAGE_VALID))
3074 return;
3075 if (is_write) {
3076 if (!(flags & PAGE_WRITE))
3077 return;
bellard579a97f2007-11-11 14:26:47 +00003078 /* XXX: this code should not depend on lock_user */
aurel3272fb7da2008-04-27 23:53:45 +00003079 if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
bellard579a97f2007-11-11 14:26:47 +00003080 /* FIXME - should this return an error rather than just fail? */
3081 return;
aurel3272fb7da2008-04-27 23:53:45 +00003082 memcpy(p, buf, l);
3083 unlock_user(p, addr, l);
bellard13eb76e2004-01-24 15:23:36 +00003084 } else {
3085 if (!(flags & PAGE_READ))
3086 return;
bellard579a97f2007-11-11 14:26:47 +00003087 /* XXX: this code should not depend on lock_user */
aurel3272fb7da2008-04-27 23:53:45 +00003088 if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
bellard579a97f2007-11-11 14:26:47 +00003089 /* FIXME - should this return an error rather than just fail? */
3090 return;
aurel3272fb7da2008-04-27 23:53:45 +00003091 memcpy(buf, p, l);
aurel325b257572008-04-28 08:54:59 +00003092 unlock_user(p, addr, 0);
bellard13eb76e2004-01-24 15:23:36 +00003093 }
3094 len -= l;
3095 buf += l;
3096 addr += l;
3097 }
3098}
bellard8df1cd02005-01-28 22:37:22 +00003099
bellard13eb76e2004-01-24 15:23:36 +00003100#else
ths5fafdf22007-09-16 21:08:06 +00003101void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
bellard13eb76e2004-01-24 15:23:36 +00003102 int len, int is_write)
3103{
3104 int l, io_index;
3105 uint8_t *ptr;
3106 uint32_t val;
bellard2e126692004-04-25 21:28:44 +00003107 target_phys_addr_t page;
3108 unsigned long pd;
bellard92e873b2004-05-21 14:52:29 +00003109 PhysPageDesc *p;
ths3b46e622007-09-17 08:09:54 +00003110
bellard13eb76e2004-01-24 15:23:36 +00003111 while (len > 0) {
3112 page = addr & TARGET_PAGE_MASK;
3113 l = (page + TARGET_PAGE_SIZE) - addr;
3114 if (l > len)
3115 l = len;
bellard92e873b2004-05-21 14:52:29 +00003116 p = phys_page_find(page >> TARGET_PAGE_BITS);
bellard13eb76e2004-01-24 15:23:36 +00003117 if (!p) {
3118 pd = IO_MEM_UNASSIGNED;
3119 } else {
3120 pd = p->phys_offset;
3121 }
ths3b46e622007-09-17 08:09:54 +00003122
bellard13eb76e2004-01-24 15:23:36 +00003123 if (is_write) {
bellard3a7d9292005-08-21 09:26:42 +00003124 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
aurel326c2934d2009-02-18 21:37:17 +00003125 target_phys_addr_t addr1 = addr;
bellard13eb76e2004-01-24 15:23:36 +00003126 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
pbrook8da3ff12008-12-01 18:59:50 +00003127 if (p)
aurel326c2934d2009-02-18 21:37:17 +00003128 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
bellard6a00d602005-11-21 23:25:50 +00003129 /* XXX: could force cpu_single_env to NULL to avoid
3130 potential bugs */
aurel326c2934d2009-02-18 21:37:17 +00003131 if (l >= 4 && ((addr1 & 3) == 0)) {
bellard1c213d12005-09-03 10:49:04 +00003132 /* 32 bit write access */
bellardc27004e2005-01-03 23:35:10 +00003133 val = ldl_p(buf);
aurel326c2934d2009-02-18 21:37:17 +00003134 io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, val);
bellard13eb76e2004-01-24 15:23:36 +00003135 l = 4;
aurel326c2934d2009-02-18 21:37:17 +00003136 } else if (l >= 2 && ((addr1 & 1) == 0)) {
bellard1c213d12005-09-03 10:49:04 +00003137 /* 16 bit write access */
bellardc27004e2005-01-03 23:35:10 +00003138 val = lduw_p(buf);
aurel326c2934d2009-02-18 21:37:17 +00003139 io_mem_write[io_index][1](io_mem_opaque[io_index], addr1, val);
bellard13eb76e2004-01-24 15:23:36 +00003140 l = 2;
3141 } else {
bellard1c213d12005-09-03 10:49:04 +00003142 /* 8 bit write access */
bellardc27004e2005-01-03 23:35:10 +00003143 val = ldub_p(buf);
aurel326c2934d2009-02-18 21:37:17 +00003144 io_mem_write[io_index][0](io_mem_opaque[io_index], addr1, val);
bellard13eb76e2004-01-24 15:23:36 +00003145 l = 1;
3146 }
3147 } else {
bellardb448f2f2004-02-25 23:24:04 +00003148 unsigned long addr1;
3149 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
bellard13eb76e2004-01-24 15:23:36 +00003150 /* RAM case */
pbrook5579c7f2009-04-11 14:47:08 +00003151 ptr = qemu_get_ram_ptr(addr1);
bellard13eb76e2004-01-24 15:23:36 +00003152 memcpy(ptr, buf, l);
bellard3a7d9292005-08-21 09:26:42 +00003153 if (!cpu_physical_memory_is_dirty(addr1)) {
3154 /* invalidate code */
3155 tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
3156 /* set dirty bit */
ths5fafdf22007-09-16 21:08:06 +00003157 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
bellardf23db162005-08-21 19:12:28 +00003158 (0xff & ~CODE_DIRTY_FLAG);
bellard3a7d9292005-08-21 09:26:42 +00003159 }
bellard13eb76e2004-01-24 15:23:36 +00003160 }
3161 } else {
ths5fafdf22007-09-16 21:08:06 +00003162 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
bellard2a4188a2006-06-25 21:54:59 +00003163 !(pd & IO_MEM_ROMD)) {
aurel326c2934d2009-02-18 21:37:17 +00003164 target_phys_addr_t addr1 = addr;
bellard13eb76e2004-01-24 15:23:36 +00003165 /* I/O case */
3166 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
pbrook8da3ff12008-12-01 18:59:50 +00003167 if (p)
aurel326c2934d2009-02-18 21:37:17 +00003168 addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3169 if (l >= 4 && ((addr1 & 3) == 0)) {
bellard13eb76e2004-01-24 15:23:36 +00003170 /* 32 bit read access */
aurel326c2934d2009-02-18 21:37:17 +00003171 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
bellardc27004e2005-01-03 23:35:10 +00003172 stl_p(buf, val);
bellard13eb76e2004-01-24 15:23:36 +00003173 l = 4;
aurel326c2934d2009-02-18 21:37:17 +00003174 } else if (l >= 2 && ((addr1 & 1) == 0)) {
bellard13eb76e2004-01-24 15:23:36 +00003175 /* 16 bit read access */
aurel326c2934d2009-02-18 21:37:17 +00003176 val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr1);
bellardc27004e2005-01-03 23:35:10 +00003177 stw_p(buf, val);
bellard13eb76e2004-01-24 15:23:36 +00003178 l = 2;
3179 } else {
bellard1c213d12005-09-03 10:49:04 +00003180 /* 8 bit read access */
aurel326c2934d2009-02-18 21:37:17 +00003181 val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr1);
bellardc27004e2005-01-03 23:35:10 +00003182 stb_p(buf, val);
bellard13eb76e2004-01-24 15:23:36 +00003183 l = 1;
3184 }
3185 } else {
3186 /* RAM case */
pbrook5579c7f2009-04-11 14:47:08 +00003187 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
bellard13eb76e2004-01-24 15:23:36 +00003188 (addr & ~TARGET_PAGE_MASK);
3189 memcpy(buf, ptr, l);
3190 }
3191 }
3192 len -= l;
3193 buf += l;
3194 addr += l;
3195 }
3196}
bellard8df1cd02005-01-28 22:37:22 +00003197
bellardd0ecd2a2006-04-23 17:14:48 +00003198/* used for ROM loading : can write in RAM and ROM */
ths5fafdf22007-09-16 21:08:06 +00003199void cpu_physical_memory_write_rom(target_phys_addr_t addr,
bellardd0ecd2a2006-04-23 17:14:48 +00003200 const uint8_t *buf, int len)
3201{
3202 int l;
3203 uint8_t *ptr;
3204 target_phys_addr_t page;
3205 unsigned long pd;
3206 PhysPageDesc *p;
ths3b46e622007-09-17 08:09:54 +00003207
bellardd0ecd2a2006-04-23 17:14:48 +00003208 while (len > 0) {
3209 page = addr & TARGET_PAGE_MASK;
3210 l = (page + TARGET_PAGE_SIZE) - addr;
3211 if (l > len)
3212 l = len;
3213 p = phys_page_find(page >> TARGET_PAGE_BITS);
3214 if (!p) {
3215 pd = IO_MEM_UNASSIGNED;
3216 } else {
3217 pd = p->phys_offset;
3218 }
ths3b46e622007-09-17 08:09:54 +00003219
bellardd0ecd2a2006-04-23 17:14:48 +00003220 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
bellard2a4188a2006-06-25 21:54:59 +00003221 (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
3222 !(pd & IO_MEM_ROMD)) {
bellardd0ecd2a2006-04-23 17:14:48 +00003223 /* do nothing */
3224 } else {
3225 unsigned long addr1;
3226 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3227 /* ROM/RAM case */
pbrook5579c7f2009-04-11 14:47:08 +00003228 ptr = qemu_get_ram_ptr(addr1);
bellardd0ecd2a2006-04-23 17:14:48 +00003229 memcpy(ptr, buf, l);
3230 }
3231 len -= l;
3232 buf += l;
3233 addr += l;
3234 }
3235}
3236
aliguori6d16c2f2009-01-22 16:59:11 +00003237typedef struct {
3238 void *buffer;
3239 target_phys_addr_t addr;
3240 target_phys_addr_t len;
3241} BounceBuffer;
3242
3243static BounceBuffer bounce;
3244
aliguoriba223c22009-01-22 16:59:16 +00003245typedef struct MapClient {
3246 void *opaque;
3247 void (*callback)(void *opaque);
3248 LIST_ENTRY(MapClient) link;
3249} MapClient;
3250
3251static LIST_HEAD(map_client_list, MapClient) map_client_list
3252 = LIST_HEAD_INITIALIZER(map_client_list);
3253
3254void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
3255{
3256 MapClient *client = qemu_malloc(sizeof(*client));
3257
3258 client->opaque = opaque;
3259 client->callback = callback;
3260 LIST_INSERT_HEAD(&map_client_list, client, link);
3261 return client;
3262}
3263
3264void cpu_unregister_map_client(void *_client)
3265{
3266 MapClient *client = (MapClient *)_client;
3267
3268 LIST_REMOVE(client, link);
Isaku Yamahata34d5e942009-06-26 18:57:18 +09003269 qemu_free(client);
aliguoriba223c22009-01-22 16:59:16 +00003270}
3271
3272static void cpu_notify_map_clients(void)
3273{
3274 MapClient *client;
3275
3276 while (!LIST_EMPTY(&map_client_list)) {
3277 client = LIST_FIRST(&map_client_list);
3278 client->callback(client->opaque);
Isaku Yamahata34d5e942009-06-26 18:57:18 +09003279 cpu_unregister_map_client(client);
aliguoriba223c22009-01-22 16:59:16 +00003280 }
3281}
3282
aliguori6d16c2f2009-01-22 16:59:11 +00003283/* Map a physical memory region into a host virtual address.
3284 * May map a subset of the requested range, given by and returned in *plen.
3285 * May return NULL if resources needed to perform the mapping are exhausted.
3286 * Use only for reads OR writes - not for read-modify-write operations.
aliguoriba223c22009-01-22 16:59:16 +00003287 * Use cpu_register_map_client() to know when retrying the map operation is
3288 * likely to succeed.
aliguori6d16c2f2009-01-22 16:59:11 +00003289 */
3290void *cpu_physical_memory_map(target_phys_addr_t addr,
3291 target_phys_addr_t *plen,
3292 int is_write)
3293{
3294 target_phys_addr_t len = *plen;
3295 target_phys_addr_t done = 0;
3296 int l;
3297 uint8_t *ret = NULL;
3298 uint8_t *ptr;
3299 target_phys_addr_t page;
3300 unsigned long pd;
3301 PhysPageDesc *p;
3302 unsigned long addr1;
3303
3304 while (len > 0) {
3305 page = addr & TARGET_PAGE_MASK;
3306 l = (page + TARGET_PAGE_SIZE) - addr;
3307 if (l > len)
3308 l = len;
3309 p = phys_page_find(page >> TARGET_PAGE_BITS);
3310 if (!p) {
3311 pd = IO_MEM_UNASSIGNED;
3312 } else {
3313 pd = p->phys_offset;
3314 }
3315
3316 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3317 if (done || bounce.buffer) {
3318 break;
3319 }
3320 bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
3321 bounce.addr = addr;
3322 bounce.len = l;
3323 if (!is_write) {
3324 cpu_physical_memory_rw(addr, bounce.buffer, l, 0);
3325 }
3326 ptr = bounce.buffer;
3327 } else {
3328 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
pbrook5579c7f2009-04-11 14:47:08 +00003329 ptr = qemu_get_ram_ptr(addr1);
aliguori6d16c2f2009-01-22 16:59:11 +00003330 }
3331 if (!done) {
3332 ret = ptr;
3333 } else if (ret + done != ptr) {
3334 break;
3335 }
3336
3337 len -= l;
3338 addr += l;
3339 done += l;
3340 }
3341 *plen = done;
3342 return ret;
3343}
3344
3345/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
3346 * Will also mark the memory as dirty if is_write == 1. access_len gives
3347 * the amount of memory that was actually read or written by the caller.
3348 */
3349void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
3350 int is_write, target_phys_addr_t access_len)
3351{
3352 if (buffer != bounce.buffer) {
3353 if (is_write) {
pbrook5579c7f2009-04-11 14:47:08 +00003354 ram_addr_t addr1 = qemu_ram_addr_from_host(buffer);
aliguori6d16c2f2009-01-22 16:59:11 +00003355 while (access_len) {
3356 unsigned l;
3357 l = TARGET_PAGE_SIZE;
3358 if (l > access_len)
3359 l = access_len;
3360 if (!cpu_physical_memory_is_dirty(addr1)) {
3361 /* invalidate code */
3362 tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
3363 /* set dirty bit */
3364 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3365 (0xff & ~CODE_DIRTY_FLAG);
3366 }
3367 addr1 += l;
3368 access_len -= l;
3369 }
3370 }
3371 return;
3372 }
3373 if (is_write) {
3374 cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
3375 }
3376 qemu_free(bounce.buffer);
3377 bounce.buffer = NULL;
aliguoriba223c22009-01-22 16:59:16 +00003378 cpu_notify_map_clients();
aliguori6d16c2f2009-01-22 16:59:11 +00003379}
bellardd0ecd2a2006-04-23 17:14:48 +00003380
bellard8df1cd02005-01-28 22:37:22 +00003381/* warning: addr must be aligned */
3382uint32_t ldl_phys(target_phys_addr_t addr)
3383{
3384 int io_index;
3385 uint8_t *ptr;
3386 uint32_t val;
3387 unsigned long pd;
3388 PhysPageDesc *p;
3389
3390 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3391 if (!p) {
3392 pd = IO_MEM_UNASSIGNED;
3393 } else {
3394 pd = p->phys_offset;
3395 }
ths3b46e622007-09-17 08:09:54 +00003396
ths5fafdf22007-09-16 21:08:06 +00003397 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
bellard2a4188a2006-06-25 21:54:59 +00003398 !(pd & IO_MEM_ROMD)) {
bellard8df1cd02005-01-28 22:37:22 +00003399 /* I/O case */
3400 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
pbrook8da3ff12008-12-01 18:59:50 +00003401 if (p)
3402 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
bellard8df1cd02005-01-28 22:37:22 +00003403 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3404 } else {
3405 /* RAM case */
pbrook5579c7f2009-04-11 14:47:08 +00003406 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
bellard8df1cd02005-01-28 22:37:22 +00003407 (addr & ~TARGET_PAGE_MASK);
3408 val = ldl_p(ptr);
3409 }
3410 return val;
3411}
3412
bellard84b7b8e2005-11-28 21:19:04 +00003413/* warning: addr must be aligned */
3414uint64_t ldq_phys(target_phys_addr_t addr)
3415{
3416 int io_index;
3417 uint8_t *ptr;
3418 uint64_t val;
3419 unsigned long pd;
3420 PhysPageDesc *p;
3421
3422 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3423 if (!p) {
3424 pd = IO_MEM_UNASSIGNED;
3425 } else {
3426 pd = p->phys_offset;
3427 }
ths3b46e622007-09-17 08:09:54 +00003428
bellard2a4188a2006-06-25 21:54:59 +00003429 if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3430 !(pd & IO_MEM_ROMD)) {
bellard84b7b8e2005-11-28 21:19:04 +00003431 /* I/O case */
3432 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
pbrook8da3ff12008-12-01 18:59:50 +00003433 if (p)
3434 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
bellard84b7b8e2005-11-28 21:19:04 +00003435#ifdef TARGET_WORDS_BIGENDIAN
3436 val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
3437 val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
3438#else
3439 val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3440 val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
3441#endif
3442 } else {
3443 /* RAM case */
pbrook5579c7f2009-04-11 14:47:08 +00003444 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
bellard84b7b8e2005-11-28 21:19:04 +00003445 (addr & ~TARGET_PAGE_MASK);
3446 val = ldq_p(ptr);
3447 }
3448 return val;
3449}
3450
bellardaab33092005-10-30 20:48:42 +00003451/* XXX: optimize */
3452uint32_t ldub_phys(target_phys_addr_t addr)
3453{
3454 uint8_t val;
3455 cpu_physical_memory_read(addr, &val, 1);
3456 return val;
3457}
3458
3459/* XXX: optimize */
3460uint32_t lduw_phys(target_phys_addr_t addr)
3461{
3462 uint16_t val;
3463 cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
3464 return tswap16(val);
3465}
3466
bellard8df1cd02005-01-28 22:37:22 +00003467/* warning: addr must be aligned. The ram page is not masked as dirty
3468 and the code inside is not invalidated. It is useful if the dirty
3469 bits are used to track modified PTEs */
3470void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
3471{
3472 int io_index;
3473 uint8_t *ptr;
3474 unsigned long pd;
3475 PhysPageDesc *p;
3476
3477 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3478 if (!p) {
3479 pd = IO_MEM_UNASSIGNED;
3480 } else {
3481 pd = p->phys_offset;
3482 }
ths3b46e622007-09-17 08:09:54 +00003483
bellard3a7d9292005-08-21 09:26:42 +00003484 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
bellard8df1cd02005-01-28 22:37:22 +00003485 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
pbrook8da3ff12008-12-01 18:59:50 +00003486 if (p)
3487 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
bellard8df1cd02005-01-28 22:37:22 +00003488 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3489 } else {
aliguori74576192008-10-06 14:02:03 +00003490 unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
pbrook5579c7f2009-04-11 14:47:08 +00003491 ptr = qemu_get_ram_ptr(addr1);
bellard8df1cd02005-01-28 22:37:22 +00003492 stl_p(ptr, val);
aliguori74576192008-10-06 14:02:03 +00003493
3494 if (unlikely(in_migration)) {
3495 if (!cpu_physical_memory_is_dirty(addr1)) {
3496 /* invalidate code */
3497 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3498 /* set dirty bit */
3499 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3500 (0xff & ~CODE_DIRTY_FLAG);
3501 }
3502 }
bellard8df1cd02005-01-28 22:37:22 +00003503 }
3504}
3505
j_mayerbc98a7e2007-04-04 07:55:12 +00003506void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
3507{
3508 int io_index;
3509 uint8_t *ptr;
3510 unsigned long pd;
3511 PhysPageDesc *p;
3512
3513 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3514 if (!p) {
3515 pd = IO_MEM_UNASSIGNED;
3516 } else {
3517 pd = p->phys_offset;
3518 }
ths3b46e622007-09-17 08:09:54 +00003519
j_mayerbc98a7e2007-04-04 07:55:12 +00003520 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3521 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
pbrook8da3ff12008-12-01 18:59:50 +00003522 if (p)
3523 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
j_mayerbc98a7e2007-04-04 07:55:12 +00003524#ifdef TARGET_WORDS_BIGENDIAN
3525 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
3526 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
3527#else
3528 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3529 io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
3530#endif
3531 } else {
pbrook5579c7f2009-04-11 14:47:08 +00003532 ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
j_mayerbc98a7e2007-04-04 07:55:12 +00003533 (addr & ~TARGET_PAGE_MASK);
3534 stq_p(ptr, val);
3535 }
3536}
3537
bellard8df1cd02005-01-28 22:37:22 +00003538/* warning: addr must be aligned */
bellard8df1cd02005-01-28 22:37:22 +00003539void stl_phys(target_phys_addr_t addr, uint32_t val)
3540{
3541 int io_index;
3542 uint8_t *ptr;
3543 unsigned long pd;
3544 PhysPageDesc *p;
3545
3546 p = phys_page_find(addr >> TARGET_PAGE_BITS);
3547 if (!p) {
3548 pd = IO_MEM_UNASSIGNED;
3549 } else {
3550 pd = p->phys_offset;
3551 }
ths3b46e622007-09-17 08:09:54 +00003552
bellard3a7d9292005-08-21 09:26:42 +00003553 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
bellard8df1cd02005-01-28 22:37:22 +00003554 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
pbrook8da3ff12008-12-01 18:59:50 +00003555 if (p)
3556 addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
bellard8df1cd02005-01-28 22:37:22 +00003557 io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3558 } else {
3559 unsigned long addr1;
3560 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3561 /* RAM case */
pbrook5579c7f2009-04-11 14:47:08 +00003562 ptr = qemu_get_ram_ptr(addr1);
bellard8df1cd02005-01-28 22:37:22 +00003563 stl_p(ptr, val);
bellard3a7d9292005-08-21 09:26:42 +00003564 if (!cpu_physical_memory_is_dirty(addr1)) {
3565 /* invalidate code */
3566 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3567 /* set dirty bit */
bellardf23db162005-08-21 19:12:28 +00003568 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3569 (0xff & ~CODE_DIRTY_FLAG);
bellard3a7d9292005-08-21 09:26:42 +00003570 }
bellard8df1cd02005-01-28 22:37:22 +00003571 }
3572}
3573
bellardaab33092005-10-30 20:48:42 +00003574/* XXX: optimize */
3575void stb_phys(target_phys_addr_t addr, uint32_t val)
3576{
3577 uint8_t v = val;
3578 cpu_physical_memory_write(addr, &v, 1);
3579}
3580
3581/* XXX: optimize */
3582void stw_phys(target_phys_addr_t addr, uint32_t val)
3583{
3584 uint16_t v = tswap16(val);
3585 cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
3586}
3587
3588/* XXX: optimize */
3589void stq_phys(target_phys_addr_t addr, uint64_t val)
3590{
3591 val = tswap64(val);
3592 cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
3593}
3594
bellard13eb76e2004-01-24 15:23:36 +00003595#endif
3596
aliguori5e2972f2009-03-28 17:51:36 +00003597/* virtual memory access for debug (includes writing to ROM) */
ths5fafdf22007-09-16 21:08:06 +00003598int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
bellardb448f2f2004-02-25 23:24:04 +00003599 uint8_t *buf, int len, int is_write)
bellard13eb76e2004-01-24 15:23:36 +00003600{
3601 int l;
j_mayer9b3c35e2007-04-07 11:21:28 +00003602 target_phys_addr_t phys_addr;
3603 target_ulong page;
bellard13eb76e2004-01-24 15:23:36 +00003604
3605 while (len > 0) {
3606 page = addr & TARGET_PAGE_MASK;
3607 phys_addr = cpu_get_phys_page_debug(env, page);
3608 /* if no physical page mapped, return an error */
3609 if (phys_addr == -1)
3610 return -1;
3611 l = (page + TARGET_PAGE_SIZE) - addr;
3612 if (l > len)
3613 l = len;
aliguori5e2972f2009-03-28 17:51:36 +00003614 phys_addr += (addr & ~TARGET_PAGE_MASK);
3615#if !defined(CONFIG_USER_ONLY)
3616 if (is_write)
3617 cpu_physical_memory_write_rom(phys_addr, buf, l);
3618 else
3619#endif
3620 cpu_physical_memory_rw(phys_addr, buf, l, is_write);
bellard13eb76e2004-01-24 15:23:36 +00003621 len -= l;
3622 buf += l;
3623 addr += l;
3624 }
3625 return 0;
3626}
3627
pbrook2e70f6e2008-06-29 01:03:05 +00003628/* in deterministic execution mode, instructions doing device I/Os
3629 must be at the end of the TB */
3630void cpu_io_recompile(CPUState *env, void *retaddr)
3631{
3632 TranslationBlock *tb;
3633 uint32_t n, cflags;
3634 target_ulong pc, cs_base;
3635 uint64_t flags;
3636
3637 tb = tb_find_pc((unsigned long)retaddr);
3638 if (!tb) {
3639 cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p",
3640 retaddr);
3641 }
3642 n = env->icount_decr.u16.low + tb->icount;
3643 cpu_restore_state(tb, env, (unsigned long)retaddr, NULL);
3644 /* Calculate how many instructions had been executed before the fault
thsbf20dc02008-06-30 17:22:19 +00003645 occurred. */
pbrook2e70f6e2008-06-29 01:03:05 +00003646 n = n - env->icount_decr.u16.low;
3647 /* Generate a new TB ending on the I/O insn. */
3648 n++;
3649 /* On MIPS and SH, delay slot instructions can only be restarted if
3650 they were already the first instruction in the TB. If this is not
thsbf20dc02008-06-30 17:22:19 +00003651 the first instruction in a TB then re-execute the preceding
pbrook2e70f6e2008-06-29 01:03:05 +00003652 branch. */
3653#if defined(TARGET_MIPS)
3654 if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) {
3655 env->active_tc.PC -= 4;
3656 env->icount_decr.u16.low++;
3657 env->hflags &= ~MIPS_HFLAG_BMASK;
3658 }
3659#elif defined(TARGET_SH4)
3660 if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
3661 && n > 1) {
3662 env->pc -= 2;
3663 env->icount_decr.u16.low++;
3664 env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
3665 }
3666#endif
3667 /* This should never happen. */
3668 if (n > CF_COUNT_MASK)
3669 cpu_abort(env, "TB too big during recompile");
3670
3671 cflags = n | CF_LAST_IO;
3672 pc = tb->pc;
3673 cs_base = tb->cs_base;
3674 flags = tb->flags;
3675 tb_phys_invalidate(tb, -1);
3676 /* FIXME: In theory this could raise an exception. In practice
3677 we have already translated the block once so it's probably ok. */
3678 tb_gen_code(env, pc, cs_base, flags, cflags);
thsbf20dc02008-06-30 17:22:19 +00003679 /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
pbrook2e70f6e2008-06-29 01:03:05 +00003680 the first in the TB) then we end up generating a whole new TB and
3681 repeating the fault, which is horribly inefficient.
3682 Better would be to execute just this insn uncached, or generate a
3683 second new TB. */
3684 cpu_resume_from_signal(env, NULL);
3685}
3686
bellarde3db7222005-01-26 22:00:47 +00003687void dump_exec_info(FILE *f,
3688 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
3689{
3690 int i, target_code_size, max_target_code_size;
3691 int direct_jmp_count, direct_jmp2_count, cross_page;
3692 TranslationBlock *tb;
ths3b46e622007-09-17 08:09:54 +00003693
bellarde3db7222005-01-26 22:00:47 +00003694 target_code_size = 0;
3695 max_target_code_size = 0;
3696 cross_page = 0;
3697 direct_jmp_count = 0;
3698 direct_jmp2_count = 0;
3699 for(i = 0; i < nb_tbs; i++) {
3700 tb = &tbs[i];
3701 target_code_size += tb->size;
3702 if (tb->size > max_target_code_size)
3703 max_target_code_size = tb->size;
3704 if (tb->page_addr[1] != -1)
3705 cross_page++;
3706 if (tb->tb_next_offset[0] != 0xffff) {
3707 direct_jmp_count++;
3708 if (tb->tb_next_offset[1] != 0xffff) {
3709 direct_jmp2_count++;
3710 }
3711 }
3712 }
3713 /* XXX: avoid using doubles ? */
bellard57fec1f2008-02-01 10:50:11 +00003714 cpu_fprintf(f, "Translation buffer state:\n");
bellard26a5f132008-05-28 12:30:31 +00003715 cpu_fprintf(f, "gen code size %ld/%ld\n",
3716 code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size);
3717 cpu_fprintf(f, "TB count %d/%d\n",
3718 nb_tbs, code_gen_max_blocks);
ths5fafdf22007-09-16 21:08:06 +00003719 cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
bellarde3db7222005-01-26 22:00:47 +00003720 nb_tbs ? target_code_size / nb_tbs : 0,
3721 max_target_code_size);
ths5fafdf22007-09-16 21:08:06 +00003722 cpu_fprintf(f, "TB avg host size %d bytes (expansion ratio: %0.1f)\n",
bellarde3db7222005-01-26 22:00:47 +00003723 nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
3724 target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
ths5fafdf22007-09-16 21:08:06 +00003725 cpu_fprintf(f, "cross page TB count %d (%d%%)\n",
3726 cross_page,
bellarde3db7222005-01-26 22:00:47 +00003727 nb_tbs ? (cross_page * 100) / nb_tbs : 0);
3728 cpu_fprintf(f, "direct jump count %d (%d%%) (2 jumps=%d %d%%)\n",
ths5fafdf22007-09-16 21:08:06 +00003729 direct_jmp_count,
bellarde3db7222005-01-26 22:00:47 +00003730 nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
3731 direct_jmp2_count,
3732 nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
bellard57fec1f2008-02-01 10:50:11 +00003733 cpu_fprintf(f, "\nStatistics:\n");
bellarde3db7222005-01-26 22:00:47 +00003734 cpu_fprintf(f, "TB flush count %d\n", tb_flush_count);
3735 cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
3736 cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count);
bellardb67d9a52008-05-23 09:57:34 +00003737 tcg_dump_info(f, cpu_fprintf);
bellarde3db7222005-01-26 22:00:47 +00003738}
3739
ths5fafdf22007-09-16 21:08:06 +00003740#if !defined(CONFIG_USER_ONLY)
bellard61382a52003-10-27 21:22:23 +00003741
3742#define MMUSUFFIX _cmmu
3743#define GETPC() NULL
3744#define env cpu_single_env
bellardb769d8f2004-10-03 15:07:13 +00003745#define SOFTMMU_CODE_ACCESS
bellard61382a52003-10-27 21:22:23 +00003746
3747#define SHIFT 0
3748#include "softmmu_template.h"
3749
3750#define SHIFT 1
3751#include "softmmu_template.h"
3752
3753#define SHIFT 2
3754#include "softmmu_template.h"
3755
3756#define SHIFT 3
3757#include "softmmu_template.h"
3758
3759#undef env
3760
3761#endif