Statistics
| Branch: | Revision:

root / exec.c @ b5dc7732

History | View | Annotate | Download (90.3 kB)

1 54936004 bellard
/*
2 fd6ce8f6 bellard
 *  virtual page mapping and translated block handling
3 5fafdf24 ths
 *
4 54936004 bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 54936004 bellard
 *
6 54936004 bellard
 * This library is free software; you can redistribute it and/or
7 54936004 bellard
 * modify it under the terms of the GNU Lesser General Public
8 54936004 bellard
 * License as published by the Free Software Foundation; either
9 54936004 bellard
 * version 2 of the License, or (at your option) any later version.
10 54936004 bellard
 *
11 54936004 bellard
 * This library is distributed in the hope that it will be useful,
12 54936004 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 54936004 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 54936004 bellard
 * Lesser General Public License for more details.
15 54936004 bellard
 *
16 54936004 bellard
 * You should have received a copy of the GNU Lesser General Public
17 54936004 bellard
 * License along with this library; if not, write to the Free Software
18 54936004 bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 54936004 bellard
 */
20 67b915a5 bellard
#include "config.h"
21 d5a8f07c bellard
#ifdef _WIN32
22 4fddf62a ths
#define WIN32_LEAN_AND_MEAN
23 d5a8f07c bellard
#include <windows.h>
24 d5a8f07c bellard
#else
25 a98d49b1 bellard
#include <sys/types.h>
26 d5a8f07c bellard
#include <sys/mman.h>
27 d5a8f07c bellard
#endif
28 54936004 bellard
#include <stdlib.h>
29 54936004 bellard
#include <stdio.h>
30 54936004 bellard
#include <stdarg.h>
31 54936004 bellard
#include <string.h>
32 54936004 bellard
#include <errno.h>
33 54936004 bellard
#include <unistd.h>
34 54936004 bellard
#include <inttypes.h>
35 54936004 bellard
36 6180a181 bellard
#include "cpu.h"
37 6180a181 bellard
#include "exec-all.h"
38 ca10f867 aurel32
#include "qemu-common.h"
39 b67d9a52 bellard
#include "tcg.h"
40 53a5960a pbrook
#if defined(CONFIG_USER_ONLY)
41 53a5960a pbrook
#include <qemu.h>
42 53a5960a pbrook
#endif
43 54936004 bellard
44 fd6ce8f6 bellard
//#define DEBUG_TB_INVALIDATE
45 66e85a21 bellard
//#define DEBUG_FLUSH
46 9fa3e853 bellard
//#define DEBUG_TLB
47 67d3b957 pbrook
//#define DEBUG_UNASSIGNED
48 fd6ce8f6 bellard
49 fd6ce8f6 bellard
/* make various TB consistency checks */
50 5fafdf24 ths
//#define DEBUG_TB_CHECK
51 5fafdf24 ths
//#define DEBUG_TLB_CHECK
52 fd6ce8f6 bellard
53 1196be37 ths
//#define DEBUG_IOPORT
54 db7b5426 blueswir1
//#define DEBUG_SUBPAGE
55 1196be37 ths
56 99773bd4 pbrook
#if !defined(CONFIG_USER_ONLY)
57 99773bd4 pbrook
/* TB consistency checks only implemented for usermode emulation.  */
58 99773bd4 pbrook
#undef DEBUG_TB_CHECK
59 99773bd4 pbrook
#endif
60 99773bd4 pbrook
61 9fa3e853 bellard
#define SMC_BITMAP_USE_THRESHOLD 10
62 9fa3e853 bellard
63 9fa3e853 bellard
#define MMAP_AREA_START        0x00000000
64 9fa3e853 bellard
#define MMAP_AREA_END          0xa8000000
65 fd6ce8f6 bellard
66 108c49b8 bellard
#if defined(TARGET_SPARC64)
67 108c49b8 bellard
#define TARGET_PHYS_ADDR_SPACE_BITS 41
68 5dcb6b91 blueswir1
#elif defined(TARGET_SPARC)
69 5dcb6b91 blueswir1
#define TARGET_PHYS_ADDR_SPACE_BITS 36
70 bedb69ea j_mayer
#elif defined(TARGET_ALPHA)
71 bedb69ea j_mayer
#define TARGET_PHYS_ADDR_SPACE_BITS 42
72 bedb69ea j_mayer
#define TARGET_VIRT_ADDR_SPACE_BITS 42
73 108c49b8 bellard
#elif defined(TARGET_PPC64)
74 108c49b8 bellard
#define TARGET_PHYS_ADDR_SPACE_BITS 42
75 00f82b8a aurel32
#elif defined(TARGET_X86_64) && !defined(USE_KQEMU)
76 00f82b8a aurel32
#define TARGET_PHYS_ADDR_SPACE_BITS 42
77 00f82b8a aurel32
#elif defined(TARGET_I386) && !defined(USE_KQEMU)
78 00f82b8a aurel32
#define TARGET_PHYS_ADDR_SPACE_BITS 36
79 108c49b8 bellard
#else
80 108c49b8 bellard
/* Note: for compatibility with kqemu, we use 32 bits for x86_64 */
81 108c49b8 bellard
#define TARGET_PHYS_ADDR_SPACE_BITS 32
82 108c49b8 bellard
#endif
83 108c49b8 bellard
84 fab94c0e pbrook
TranslationBlock *tbs;
85 26a5f13b bellard
int code_gen_max_blocks;
86 9fa3e853 bellard
TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
87 fd6ce8f6 bellard
int nb_tbs;
88 eb51d102 bellard
/* any access to the tbs or the page table must use this lock */
89 eb51d102 bellard
spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
90 fd6ce8f6 bellard
91 7cb69cae bellard
uint8_t code_gen_prologue[1024] __attribute__((aligned (32)));
92 26a5f13b bellard
uint8_t *code_gen_buffer;
93 26a5f13b bellard
unsigned long code_gen_buffer_size;
94 26a5f13b bellard
/* threshold to flush the translated code buffer */
95 26a5f13b bellard
unsigned long code_gen_buffer_max_size; 
96 fd6ce8f6 bellard
uint8_t *code_gen_ptr;
97 fd6ce8f6 bellard
98 e2eef170 pbrook
#if !defined(CONFIG_USER_ONLY)
99 00f82b8a aurel32
ram_addr_t phys_ram_size;
100 9fa3e853 bellard
int phys_ram_fd;
101 9fa3e853 bellard
uint8_t *phys_ram_base;
102 1ccde1cb bellard
uint8_t *phys_ram_dirty;
103 e9a1ab19 bellard
static ram_addr_t phys_ram_alloc_offset = 0;
104 e2eef170 pbrook
#endif
105 9fa3e853 bellard
106 6a00d601 bellard
CPUState *first_cpu;
107 6a00d601 bellard
/* current CPU in the current thread. It is only valid inside
108 6a00d601 bellard
   cpu_exec() */
109 5fafdf24 ths
CPUState *cpu_single_env;
110 6a00d601 bellard
111 54936004 bellard
typedef struct PageDesc {
112 92e873b9 bellard
    /* list of TBs intersecting this ram page */
113 fd6ce8f6 bellard
    TranslationBlock *first_tb;
114 9fa3e853 bellard
    /* in order to optimize self modifying code, we count the number
115 9fa3e853 bellard
       of lookups we do to a given page to use a bitmap */
116 9fa3e853 bellard
    unsigned int code_write_count;
117 9fa3e853 bellard
    uint8_t *code_bitmap;
118 9fa3e853 bellard
#if defined(CONFIG_USER_ONLY)
119 9fa3e853 bellard
    unsigned long flags;
120 9fa3e853 bellard
#endif
121 54936004 bellard
} PageDesc;
122 54936004 bellard
123 92e873b9 bellard
typedef struct PhysPageDesc {
124 0f459d16 pbrook
    /* offset in host memory of the page + io_index in the low bits */
125 00f82b8a aurel32
    ram_addr_t phys_offset;
126 92e873b9 bellard
} PhysPageDesc;
127 92e873b9 bellard
128 54936004 bellard
#define L2_BITS 10
129 bedb69ea j_mayer
#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
130 bedb69ea j_mayer
/* XXX: this is a temporary hack for alpha target.
131 bedb69ea j_mayer
 *      In the future, this is to be replaced by a multi-level table
132 bedb69ea j_mayer
 *      to actually be able to handle the complete 64 bits address space.
133 bedb69ea j_mayer
 */
134 bedb69ea j_mayer
#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
135 bedb69ea j_mayer
#else
136 03875444 aurel32
#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
137 bedb69ea j_mayer
#endif
138 54936004 bellard
139 54936004 bellard
#define L1_SIZE (1 << L1_BITS)
140 54936004 bellard
#define L2_SIZE (1 << L2_BITS)
141 54936004 bellard
142 83fb7adf bellard
unsigned long qemu_real_host_page_size;
143 83fb7adf bellard
unsigned long qemu_host_page_bits;
144 83fb7adf bellard
unsigned long qemu_host_page_size;
145 83fb7adf bellard
unsigned long qemu_host_page_mask;
146 54936004 bellard
147 92e873b9 bellard
/* XXX: for system emulation, it could just be an array */
148 54936004 bellard
static PageDesc *l1_map[L1_SIZE];
149 0a962c02 bellard
PhysPageDesc **l1_phys_map;
150 54936004 bellard
151 e2eef170 pbrook
#if !defined(CONFIG_USER_ONLY)
152 e2eef170 pbrook
static void io_mem_init(void);
153 e2eef170 pbrook
154 33417e70 bellard
/* io memory support */
155 33417e70 bellard
CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
156 33417e70 bellard
CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
157 a4193c8a bellard
void *io_mem_opaque[IO_MEM_NB_ENTRIES];
158 33417e70 bellard
static int io_mem_nb;
159 6658ffb8 pbrook
static int io_mem_watch;
160 6658ffb8 pbrook
#endif
161 33417e70 bellard
162 34865134 bellard
/* log support */
163 34865134 bellard
char *logfilename = "/tmp/qemu.log";
164 34865134 bellard
FILE *logfile;
165 34865134 bellard
int loglevel;
166 e735b91c pbrook
static int log_append = 0;
167 34865134 bellard
168 e3db7226 bellard
/* statistics */
169 e3db7226 bellard
static int tlb_flush_count;
170 e3db7226 bellard
static int tb_flush_count;
171 e3db7226 bellard
static int tb_phys_invalidate_count;
172 e3db7226 bellard
173 db7b5426 blueswir1
#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
174 db7b5426 blueswir1
typedef struct subpage_t {
175 db7b5426 blueswir1
    target_phys_addr_t base;
176 3ee89922 blueswir1
    CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE][4];
177 3ee89922 blueswir1
    CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE][4];
178 3ee89922 blueswir1
    void *opaque[TARGET_PAGE_SIZE][2][4];
179 db7b5426 blueswir1
} subpage_t;
180 db7b5426 blueswir1
181 7cb69cae bellard
#ifdef _WIN32
182 7cb69cae bellard
static void map_exec(void *addr, long size)
183 7cb69cae bellard
{
184 7cb69cae bellard
    DWORD old_protect;
185 7cb69cae bellard
    VirtualProtect(addr, size,
186 7cb69cae bellard
                   PAGE_EXECUTE_READWRITE, &old_protect);
187 7cb69cae bellard
    
188 7cb69cae bellard
}
189 7cb69cae bellard
#else
190 7cb69cae bellard
static void map_exec(void *addr, long size)
191 7cb69cae bellard
{
192 4369415f bellard
    unsigned long start, end, page_size;
193 7cb69cae bellard
    
194 4369415f bellard
    page_size = getpagesize();
195 7cb69cae bellard
    start = (unsigned long)addr;
196 4369415f bellard
    start &= ~(page_size - 1);
197 7cb69cae bellard
    
198 7cb69cae bellard
    end = (unsigned long)addr + size;
199 4369415f bellard
    end += page_size - 1;
200 4369415f bellard
    end &= ~(page_size - 1);
201 7cb69cae bellard
    
202 7cb69cae bellard
    mprotect((void *)start, end - start,
203 7cb69cae bellard
             PROT_READ | PROT_WRITE | PROT_EXEC);
204 7cb69cae bellard
}
205 7cb69cae bellard
#endif
206 7cb69cae bellard
207 b346ff46 bellard
static void page_init(void)
208 54936004 bellard
{
209 83fb7adf bellard
    /* NOTE: we can always suppose that qemu_host_page_size >=
210 54936004 bellard
       TARGET_PAGE_SIZE */
211 67b915a5 bellard
#ifdef _WIN32
212 d5a8f07c bellard
    {
213 d5a8f07c bellard
        SYSTEM_INFO system_info;
214 d5a8f07c bellard
        DWORD old_protect;
215 3b46e624 ths
216 d5a8f07c bellard
        GetSystemInfo(&system_info);
217 d5a8f07c bellard
        qemu_real_host_page_size = system_info.dwPageSize;
218 d5a8f07c bellard
    }
219 67b915a5 bellard
#else
220 83fb7adf bellard
    qemu_real_host_page_size = getpagesize();
221 67b915a5 bellard
#endif
222 83fb7adf bellard
    if (qemu_host_page_size == 0)
223 83fb7adf bellard
        qemu_host_page_size = qemu_real_host_page_size;
224 83fb7adf bellard
    if (qemu_host_page_size < TARGET_PAGE_SIZE)
225 83fb7adf bellard
        qemu_host_page_size = TARGET_PAGE_SIZE;
226 83fb7adf bellard
    qemu_host_page_bits = 0;
227 83fb7adf bellard
    while ((1 << qemu_host_page_bits) < qemu_host_page_size)
228 83fb7adf bellard
        qemu_host_page_bits++;
229 83fb7adf bellard
    qemu_host_page_mask = ~(qemu_host_page_size - 1);
230 108c49b8 bellard
    l1_phys_map = qemu_vmalloc(L1_SIZE * sizeof(void *));
231 108c49b8 bellard
    memset(l1_phys_map, 0, L1_SIZE * sizeof(void *));
232 50a9569b balrog
233 50a9569b balrog
#if !defined(_WIN32) && defined(CONFIG_USER_ONLY)
234 50a9569b balrog
    {
235 50a9569b balrog
        long long startaddr, endaddr;
236 50a9569b balrog
        FILE *f;
237 50a9569b balrog
        int n;
238 50a9569b balrog
239 c8a706fe pbrook
        mmap_lock();
240 0776590d pbrook
        last_brk = (unsigned long)sbrk(0);
241 50a9569b balrog
        f = fopen("/proc/self/maps", "r");
242 50a9569b balrog
        if (f) {
243 50a9569b balrog
            do {
244 50a9569b balrog
                n = fscanf (f, "%llx-%llx %*[^\n]\n", &startaddr, &endaddr);
245 50a9569b balrog
                if (n == 2) {
246 e0b8d65a blueswir1
                    startaddr = MIN(startaddr,
247 e0b8d65a blueswir1
                                    (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
248 e0b8d65a blueswir1
                    endaddr = MIN(endaddr,
249 e0b8d65a blueswir1
                                    (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
250 b5fc909e pbrook
                    page_set_flags(startaddr & TARGET_PAGE_MASK,
251 50a9569b balrog
                                   TARGET_PAGE_ALIGN(endaddr),
252 50a9569b balrog
                                   PAGE_RESERVED); 
253 50a9569b balrog
                }
254 50a9569b balrog
            } while (!feof(f));
255 50a9569b balrog
            fclose(f);
256 50a9569b balrog
        }
257 c8a706fe pbrook
        mmap_unlock();
258 50a9569b balrog
    }
259 50a9569b balrog
#endif
260 54936004 bellard
}
261 54936004 bellard
262 00f82b8a aurel32
static inline PageDesc *page_find_alloc(target_ulong index)
263 54936004 bellard
{
264 54936004 bellard
    PageDesc **lp, *p;
265 54936004 bellard
266 17e2377a pbrook
#if TARGET_LONG_BITS > 32
267 17e2377a pbrook
    /* Host memory outside guest VM.  For 32-bit targets we have already
268 17e2377a pbrook
       excluded high addresses.  */
269 17e2377a pbrook
    if (index > ((target_ulong)L2_SIZE * L1_SIZE * TARGET_PAGE_SIZE))
270 17e2377a pbrook
        return NULL;
271 17e2377a pbrook
#endif
272 54936004 bellard
    lp = &l1_map[index >> L2_BITS];
273 54936004 bellard
    p = *lp;
274 54936004 bellard
    if (!p) {
275 54936004 bellard
        /* allocate if not found */
276 17e2377a pbrook
#if defined(CONFIG_USER_ONLY)
277 17e2377a pbrook
        unsigned long addr;
278 17e2377a pbrook
        size_t len = sizeof(PageDesc) * L2_SIZE;
279 17e2377a pbrook
        /* Don't use qemu_malloc because it may recurse.  */
280 17e2377a pbrook
        p = mmap(0, len, PROT_READ | PROT_WRITE,
281 17e2377a pbrook
                 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
282 54936004 bellard
        *lp = p;
283 17e2377a pbrook
        addr = h2g(p);
284 17e2377a pbrook
        if (addr == (target_ulong)addr) {
285 17e2377a pbrook
            page_set_flags(addr & TARGET_PAGE_MASK,
286 17e2377a pbrook
                           TARGET_PAGE_ALIGN(addr + len),
287 17e2377a pbrook
                           PAGE_RESERVED); 
288 17e2377a pbrook
        }
289 17e2377a pbrook
#else
290 17e2377a pbrook
        p = qemu_mallocz(sizeof(PageDesc) * L2_SIZE);
291 17e2377a pbrook
        *lp = p;
292 17e2377a pbrook
#endif
293 54936004 bellard
    }
294 54936004 bellard
    return p + (index & (L2_SIZE - 1));
295 54936004 bellard
}
296 54936004 bellard
297 00f82b8a aurel32
static inline PageDesc *page_find(target_ulong index)
298 54936004 bellard
{
299 54936004 bellard
    PageDesc *p;
300 54936004 bellard
301 54936004 bellard
    p = l1_map[index >> L2_BITS];
302 54936004 bellard
    if (!p)
303 54936004 bellard
        return 0;
304 fd6ce8f6 bellard
    return p + (index & (L2_SIZE - 1));
305 fd6ce8f6 bellard
}
306 fd6ce8f6 bellard
307 108c49b8 bellard
static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
308 92e873b9 bellard
{
309 108c49b8 bellard
    void **lp, **p;
310 e3f4e2a4 pbrook
    PhysPageDesc *pd;
311 92e873b9 bellard
312 108c49b8 bellard
    p = (void **)l1_phys_map;
313 108c49b8 bellard
#if TARGET_PHYS_ADDR_SPACE_BITS > 32
314 108c49b8 bellard
315 108c49b8 bellard
#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
316 108c49b8 bellard
#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
317 108c49b8 bellard
#endif
318 108c49b8 bellard
    lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1));
319 92e873b9 bellard
    p = *lp;
320 92e873b9 bellard
    if (!p) {
321 92e873b9 bellard
        /* allocate if not found */
322 108c49b8 bellard
        if (!alloc)
323 108c49b8 bellard
            return NULL;
324 108c49b8 bellard
        p = qemu_vmalloc(sizeof(void *) * L1_SIZE);
325 108c49b8 bellard
        memset(p, 0, sizeof(void *) * L1_SIZE);
326 108c49b8 bellard
        *lp = p;
327 108c49b8 bellard
    }
328 108c49b8 bellard
#endif
329 108c49b8 bellard
    lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
330 e3f4e2a4 pbrook
    pd = *lp;
331 e3f4e2a4 pbrook
    if (!pd) {
332 e3f4e2a4 pbrook
        int i;
333 108c49b8 bellard
        /* allocate if not found */
334 108c49b8 bellard
        if (!alloc)
335 108c49b8 bellard
            return NULL;
336 e3f4e2a4 pbrook
        pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
337 e3f4e2a4 pbrook
        *lp = pd;
338 e3f4e2a4 pbrook
        for (i = 0; i < L2_SIZE; i++)
339 e3f4e2a4 pbrook
          pd[i].phys_offset = IO_MEM_UNASSIGNED;
340 92e873b9 bellard
    }
341 e3f4e2a4 pbrook
    return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
342 92e873b9 bellard
}
343 92e873b9 bellard
344 108c49b8 bellard
static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
345 92e873b9 bellard
{
346 108c49b8 bellard
    return phys_page_find_alloc(index, 0);
347 92e873b9 bellard
}
348 92e873b9 bellard
349 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
350 6a00d601 bellard
static void tlb_protect_code(ram_addr_t ram_addr);
351 5fafdf24 ths
static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
352 3a7d929e bellard
                                    target_ulong vaddr);
353 c8a706fe pbrook
#define mmap_lock() do { } while(0)
354 c8a706fe pbrook
#define mmap_unlock() do { } while(0)
355 9fa3e853 bellard
#endif
356 fd6ce8f6 bellard
357 4369415f bellard
#define DEFAULT_CODE_GEN_BUFFER_SIZE (32 * 1024 * 1024)
358 4369415f bellard
359 4369415f bellard
#if defined(CONFIG_USER_ONLY)
360 4369415f bellard
/* Currently it is not recommanded to allocate big chunks of data in
361 4369415f bellard
   user mode. It will change when a dedicated libc will be used */
362 4369415f bellard
#define USE_STATIC_CODE_GEN_BUFFER
363 4369415f bellard
#endif
364 4369415f bellard
365 4369415f bellard
#ifdef USE_STATIC_CODE_GEN_BUFFER
366 4369415f bellard
static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE];
367 4369415f bellard
#endif
368 4369415f bellard
369 26a5f13b bellard
void code_gen_alloc(unsigned long tb_size)
370 26a5f13b bellard
{
371 4369415f bellard
#ifdef USE_STATIC_CODE_GEN_BUFFER
372 4369415f bellard
    code_gen_buffer = static_code_gen_buffer;
373 4369415f bellard
    code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
374 4369415f bellard
    map_exec(code_gen_buffer, code_gen_buffer_size);
375 4369415f bellard
#else
376 26a5f13b bellard
    code_gen_buffer_size = tb_size;
377 26a5f13b bellard
    if (code_gen_buffer_size == 0) {
378 4369415f bellard
#if defined(CONFIG_USER_ONLY)
379 4369415f bellard
        /* in user mode, phys_ram_size is not meaningful */
380 4369415f bellard
        code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
381 4369415f bellard
#else
382 26a5f13b bellard
        /* XXX: needs ajustments */
383 26a5f13b bellard
        code_gen_buffer_size = (int)(phys_ram_size / 4);
384 4369415f bellard
#endif
385 26a5f13b bellard
    }
386 26a5f13b bellard
    if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE)
387 26a5f13b bellard
        code_gen_buffer_size = MIN_CODE_GEN_BUFFER_SIZE;
388 26a5f13b bellard
    /* The code gen buffer location may have constraints depending on
389 26a5f13b bellard
       the host cpu and OS */
390 26a5f13b bellard
#if defined(__linux__) 
391 26a5f13b bellard
    {
392 26a5f13b bellard
        int flags;
393 26a5f13b bellard
        flags = MAP_PRIVATE | MAP_ANONYMOUS;
394 26a5f13b bellard
#if defined(__x86_64__)
395 26a5f13b bellard
        flags |= MAP_32BIT;
396 26a5f13b bellard
        /* Cannot map more than that */
397 26a5f13b bellard
        if (code_gen_buffer_size > (800 * 1024 * 1024))
398 26a5f13b bellard
            code_gen_buffer_size = (800 * 1024 * 1024);
399 26a5f13b bellard
#endif
400 26a5f13b bellard
        code_gen_buffer = mmap(NULL, code_gen_buffer_size,
401 26a5f13b bellard
                               PROT_WRITE | PROT_READ | PROT_EXEC, 
402 26a5f13b bellard
                               flags, -1, 0);
403 26a5f13b bellard
        if (code_gen_buffer == MAP_FAILED) {
404 26a5f13b bellard
            fprintf(stderr, "Could not allocate dynamic translator buffer\n");
405 26a5f13b bellard
            exit(1);
406 26a5f13b bellard
        }
407 26a5f13b bellard
    }
408 26a5f13b bellard
#else
409 26a5f13b bellard
    code_gen_buffer = qemu_malloc(code_gen_buffer_size);
410 26a5f13b bellard
    if (!code_gen_buffer) {
411 26a5f13b bellard
        fprintf(stderr, "Could not allocate dynamic translator buffer\n");
412 26a5f13b bellard
        exit(1);
413 26a5f13b bellard
    }
414 26a5f13b bellard
    map_exec(code_gen_buffer, code_gen_buffer_size);
415 26a5f13b bellard
#endif
416 4369415f bellard
#endif /* !USE_STATIC_CODE_GEN_BUFFER */
417 26a5f13b bellard
    map_exec(code_gen_prologue, sizeof(code_gen_prologue));
418 26a5f13b bellard
    code_gen_buffer_max_size = code_gen_buffer_size - 
419 26a5f13b bellard
        code_gen_max_block_size();
420 26a5f13b bellard
    code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
421 26a5f13b bellard
    tbs = qemu_malloc(code_gen_max_blocks * sizeof(TranslationBlock));
422 26a5f13b bellard
}
423 26a5f13b bellard
424 26a5f13b bellard
/* Must be called before using the QEMU cpus. 'tb_size' is the size
425 26a5f13b bellard
   (in bytes) allocated to the translation buffer. Zero means default
426 26a5f13b bellard
   size. */
427 26a5f13b bellard
void cpu_exec_init_all(unsigned long tb_size)
428 26a5f13b bellard
{
429 26a5f13b bellard
    cpu_gen_init();
430 26a5f13b bellard
    code_gen_alloc(tb_size);
431 26a5f13b bellard
    code_gen_ptr = code_gen_buffer;
432 4369415f bellard
    page_init();
433 e2eef170 pbrook
#if !defined(CONFIG_USER_ONLY)
434 26a5f13b bellard
    io_mem_init();
435 e2eef170 pbrook
#endif
436 26a5f13b bellard
}
437 26a5f13b bellard
438 6a00d601 bellard
void cpu_exec_init(CPUState *env)
439 fd6ce8f6 bellard
{
440 6a00d601 bellard
    CPUState **penv;
441 6a00d601 bellard
    int cpu_index;
442 6a00d601 bellard
443 6a00d601 bellard
    env->next_cpu = NULL;
444 6a00d601 bellard
    penv = &first_cpu;
445 6a00d601 bellard
    cpu_index = 0;
446 6a00d601 bellard
    while (*penv != NULL) {
447 6a00d601 bellard
        penv = (CPUState **)&(*penv)->next_cpu;
448 6a00d601 bellard
        cpu_index++;
449 6a00d601 bellard
    }
450 6a00d601 bellard
    env->cpu_index = cpu_index;
451 6658ffb8 pbrook
    env->nb_watchpoints = 0;
452 6a00d601 bellard
    *penv = env;
453 fd6ce8f6 bellard
}
454 fd6ce8f6 bellard
455 9fa3e853 bellard
static inline void invalidate_page_bitmap(PageDesc *p)
456 9fa3e853 bellard
{
457 9fa3e853 bellard
    if (p->code_bitmap) {
458 59817ccb bellard
        qemu_free(p->code_bitmap);
459 9fa3e853 bellard
        p->code_bitmap = NULL;
460 9fa3e853 bellard
    }
461 9fa3e853 bellard
    p->code_write_count = 0;
462 9fa3e853 bellard
}
463 9fa3e853 bellard
464 fd6ce8f6 bellard
/* set to NULL all the 'first_tb' fields in all PageDescs */
465 fd6ce8f6 bellard
static void page_flush_tb(void)
466 fd6ce8f6 bellard
{
467 fd6ce8f6 bellard
    int i, j;
468 fd6ce8f6 bellard
    PageDesc *p;
469 fd6ce8f6 bellard
470 fd6ce8f6 bellard
    for(i = 0; i < L1_SIZE; i++) {
471 fd6ce8f6 bellard
        p = l1_map[i];
472 fd6ce8f6 bellard
        if (p) {
473 9fa3e853 bellard
            for(j = 0; j < L2_SIZE; j++) {
474 9fa3e853 bellard
                p->first_tb = NULL;
475 9fa3e853 bellard
                invalidate_page_bitmap(p);
476 9fa3e853 bellard
                p++;
477 9fa3e853 bellard
            }
478 fd6ce8f6 bellard
        }
479 fd6ce8f6 bellard
    }
480 fd6ce8f6 bellard
}
481 fd6ce8f6 bellard
482 fd6ce8f6 bellard
/* flush all the translation blocks */
483 d4e8164f bellard
/* XXX: tb_flush is currently not thread safe */
484 6a00d601 bellard
void tb_flush(CPUState *env1)
485 fd6ce8f6 bellard
{
486 6a00d601 bellard
    CPUState *env;
487 0124311e bellard
#if defined(DEBUG_FLUSH)
488 ab3d1727 blueswir1
    printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
489 ab3d1727 blueswir1
           (unsigned long)(code_gen_ptr - code_gen_buffer),
490 ab3d1727 blueswir1
           nb_tbs, nb_tbs > 0 ?
491 ab3d1727 blueswir1
           ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
492 fd6ce8f6 bellard
#endif
493 26a5f13b bellard
    if ((unsigned long)(code_gen_ptr - code_gen_buffer) > code_gen_buffer_size)
494 a208e54a pbrook
        cpu_abort(env1, "Internal error: code buffer overflow\n");
495 a208e54a pbrook
496 fd6ce8f6 bellard
    nb_tbs = 0;
497 3b46e624 ths
498 6a00d601 bellard
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
499 6a00d601 bellard
        memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
500 6a00d601 bellard
    }
501 9fa3e853 bellard
502 8a8a608f bellard
    memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
503 fd6ce8f6 bellard
    page_flush_tb();
504 9fa3e853 bellard
505 fd6ce8f6 bellard
    code_gen_ptr = code_gen_buffer;
506 d4e8164f bellard
    /* XXX: flush processor icache at this point if cache flush is
507 d4e8164f bellard
       expensive */
508 e3db7226 bellard
    tb_flush_count++;
509 fd6ce8f6 bellard
}
510 fd6ce8f6 bellard
511 fd6ce8f6 bellard
#ifdef DEBUG_TB_CHECK
512 fd6ce8f6 bellard
513 bc98a7ef j_mayer
static void tb_invalidate_check(target_ulong address)
514 fd6ce8f6 bellard
{
515 fd6ce8f6 bellard
    TranslationBlock *tb;
516 fd6ce8f6 bellard
    int i;
517 fd6ce8f6 bellard
    address &= TARGET_PAGE_MASK;
518 99773bd4 pbrook
    for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
519 99773bd4 pbrook
        for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
520 fd6ce8f6 bellard
            if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
521 fd6ce8f6 bellard
                  address >= tb->pc + tb->size)) {
522 fd6ce8f6 bellard
                printf("ERROR invalidate: address=%08lx PC=%08lx size=%04x\n",
523 99773bd4 pbrook
                       address, (long)tb->pc, tb->size);
524 fd6ce8f6 bellard
            }
525 fd6ce8f6 bellard
        }
526 fd6ce8f6 bellard
    }
527 fd6ce8f6 bellard
}
528 fd6ce8f6 bellard
529 fd6ce8f6 bellard
/* verify that all the pages have correct rights for code */
530 fd6ce8f6 bellard
static void tb_page_check(void)
531 fd6ce8f6 bellard
{
532 fd6ce8f6 bellard
    TranslationBlock *tb;
533 fd6ce8f6 bellard
    int i, flags1, flags2;
534 3b46e624 ths
535 99773bd4 pbrook
    for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
536 99773bd4 pbrook
        for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
537 fd6ce8f6 bellard
            flags1 = page_get_flags(tb->pc);
538 fd6ce8f6 bellard
            flags2 = page_get_flags(tb->pc + tb->size - 1);
539 fd6ce8f6 bellard
            if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
540 fd6ce8f6 bellard
                printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
541 99773bd4 pbrook
                       (long)tb->pc, tb->size, flags1, flags2);
542 fd6ce8f6 bellard
            }
543 fd6ce8f6 bellard
        }
544 fd6ce8f6 bellard
    }
545 fd6ce8f6 bellard
}
546 fd6ce8f6 bellard
547 d4e8164f bellard
void tb_jmp_check(TranslationBlock *tb)
548 d4e8164f bellard
{
549 d4e8164f bellard
    TranslationBlock *tb1;
550 d4e8164f bellard
    unsigned int n1;
551 d4e8164f bellard
552 d4e8164f bellard
    /* suppress any remaining jumps to this TB */
553 d4e8164f bellard
    tb1 = tb->jmp_first;
554 d4e8164f bellard
    for(;;) {
555 d4e8164f bellard
        n1 = (long)tb1 & 3;
556 d4e8164f bellard
        tb1 = (TranslationBlock *)((long)tb1 & ~3);
557 d4e8164f bellard
        if (n1 == 2)
558 d4e8164f bellard
            break;
559 d4e8164f bellard
        tb1 = tb1->jmp_next[n1];
560 d4e8164f bellard
    }
561 d4e8164f bellard
    /* check end of list */
562 d4e8164f bellard
    if (tb1 != tb) {
563 d4e8164f bellard
        printf("ERROR: jmp_list from 0x%08lx\n", (long)tb);
564 d4e8164f bellard
    }
565 d4e8164f bellard
}
566 d4e8164f bellard
567 fd6ce8f6 bellard
#endif
568 fd6ce8f6 bellard
569 fd6ce8f6 bellard
/* invalidate one TB */
570 fd6ce8f6 bellard
static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb,
571 fd6ce8f6 bellard
                             int next_offset)
572 fd6ce8f6 bellard
{
573 fd6ce8f6 bellard
    TranslationBlock *tb1;
574 fd6ce8f6 bellard
    for(;;) {
575 fd6ce8f6 bellard
        tb1 = *ptb;
576 fd6ce8f6 bellard
        if (tb1 == tb) {
577 fd6ce8f6 bellard
            *ptb = *(TranslationBlock **)((char *)tb1 + next_offset);
578 fd6ce8f6 bellard
            break;
579 fd6ce8f6 bellard
        }
580 fd6ce8f6 bellard
        ptb = (TranslationBlock **)((char *)tb1 + next_offset);
581 fd6ce8f6 bellard
    }
582 fd6ce8f6 bellard
}
583 fd6ce8f6 bellard
584 9fa3e853 bellard
static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
585 9fa3e853 bellard
{
586 9fa3e853 bellard
    TranslationBlock *tb1;
587 9fa3e853 bellard
    unsigned int n1;
588 9fa3e853 bellard
589 9fa3e853 bellard
    for(;;) {
590 9fa3e853 bellard
        tb1 = *ptb;
591 9fa3e853 bellard
        n1 = (long)tb1 & 3;
592 9fa3e853 bellard
        tb1 = (TranslationBlock *)((long)tb1 & ~3);
593 9fa3e853 bellard
        if (tb1 == tb) {
594 9fa3e853 bellard
            *ptb = tb1->page_next[n1];
595 9fa3e853 bellard
            break;
596 9fa3e853 bellard
        }
597 9fa3e853 bellard
        ptb = &tb1->page_next[n1];
598 9fa3e853 bellard
    }
599 9fa3e853 bellard
}
600 9fa3e853 bellard
601 d4e8164f bellard
static inline void tb_jmp_remove(TranslationBlock *tb, int n)
602 d4e8164f bellard
{
603 d4e8164f bellard
    TranslationBlock *tb1, **ptb;
604 d4e8164f bellard
    unsigned int n1;
605 d4e8164f bellard
606 d4e8164f bellard
    ptb = &tb->jmp_next[n];
607 d4e8164f bellard
    tb1 = *ptb;
608 d4e8164f bellard
    if (tb1) {
609 d4e8164f bellard
        /* find tb(n) in circular list */
610 d4e8164f bellard
        for(;;) {
611 d4e8164f bellard
            tb1 = *ptb;
612 d4e8164f bellard
            n1 = (long)tb1 & 3;
613 d4e8164f bellard
            tb1 = (TranslationBlock *)((long)tb1 & ~3);
614 d4e8164f bellard
            if (n1 == n && tb1 == tb)
615 d4e8164f bellard
                break;
616 d4e8164f bellard
            if (n1 == 2) {
617 d4e8164f bellard
                ptb = &tb1->jmp_first;
618 d4e8164f bellard
            } else {
619 d4e8164f bellard
                ptb = &tb1->jmp_next[n1];
620 d4e8164f bellard
            }
621 d4e8164f bellard
        }
622 d4e8164f bellard
        /* now we can suppress tb(n) from the list */
623 d4e8164f bellard
        *ptb = tb->jmp_next[n];
624 d4e8164f bellard
625 d4e8164f bellard
        tb->jmp_next[n] = NULL;
626 d4e8164f bellard
    }
627 d4e8164f bellard
}
628 d4e8164f bellard
629 d4e8164f bellard
/* reset the jump entry 'n' of a TB so that it is not chained to
630 d4e8164f bellard
   another TB */
631 d4e8164f bellard
static inline void tb_reset_jump(TranslationBlock *tb, int n)
632 d4e8164f bellard
{
633 d4e8164f bellard
    tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
634 d4e8164f bellard
}
635 d4e8164f bellard
636 00f82b8a aurel32
static inline void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr)
637 fd6ce8f6 bellard
{
638 6a00d601 bellard
    CPUState *env;
639 8a40a180 bellard
    PageDesc *p;
640 d4e8164f bellard
    unsigned int h, n1;
641 00f82b8a aurel32
    target_phys_addr_t phys_pc;
642 8a40a180 bellard
    TranslationBlock *tb1, *tb2;
643 3b46e624 ths
644 8a40a180 bellard
    /* remove the TB from the hash list */
645 8a40a180 bellard
    phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
646 8a40a180 bellard
    h = tb_phys_hash_func(phys_pc);
647 5fafdf24 ths
    tb_remove(&tb_phys_hash[h], tb,
648 8a40a180 bellard
              offsetof(TranslationBlock, phys_hash_next));
649 8a40a180 bellard
650 8a40a180 bellard
    /* remove the TB from the page list */
651 8a40a180 bellard
    if (tb->page_addr[0] != page_addr) {
652 8a40a180 bellard
        p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
653 8a40a180 bellard
        tb_page_remove(&p->first_tb, tb);
654 8a40a180 bellard
        invalidate_page_bitmap(p);
655 8a40a180 bellard
    }
656 8a40a180 bellard
    if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
657 8a40a180 bellard
        p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
658 8a40a180 bellard
        tb_page_remove(&p->first_tb, tb);
659 8a40a180 bellard
        invalidate_page_bitmap(p);
660 8a40a180 bellard
    }
661 8a40a180 bellard
662 36bdbe54 bellard
    tb_invalidated_flag = 1;
663 59817ccb bellard
664 fd6ce8f6 bellard
    /* remove the TB from the hash list */
665 8a40a180 bellard
    h = tb_jmp_cache_hash_func(tb->pc);
666 6a00d601 bellard
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
667 6a00d601 bellard
        if (env->tb_jmp_cache[h] == tb)
668 6a00d601 bellard
            env->tb_jmp_cache[h] = NULL;
669 6a00d601 bellard
    }
670 d4e8164f bellard
671 d4e8164f bellard
    /* suppress this TB from the two jump lists */
672 d4e8164f bellard
    tb_jmp_remove(tb, 0);
673 d4e8164f bellard
    tb_jmp_remove(tb, 1);
674 d4e8164f bellard
675 d4e8164f bellard
    /* suppress any remaining jumps to this TB */
676 d4e8164f bellard
    tb1 = tb->jmp_first;
677 d4e8164f bellard
    for(;;) {
678 d4e8164f bellard
        n1 = (long)tb1 & 3;
679 d4e8164f bellard
        if (n1 == 2)
680 d4e8164f bellard
            break;
681 d4e8164f bellard
        tb1 = (TranslationBlock *)((long)tb1 & ~3);
682 d4e8164f bellard
        tb2 = tb1->jmp_next[n1];
683 d4e8164f bellard
        tb_reset_jump(tb1, n1);
684 d4e8164f bellard
        tb1->jmp_next[n1] = NULL;
685 d4e8164f bellard
        tb1 = tb2;
686 d4e8164f bellard
    }
687 d4e8164f bellard
    tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
688 9fa3e853 bellard
689 e3db7226 bellard
    tb_phys_invalidate_count++;
690 9fa3e853 bellard
}
691 9fa3e853 bellard
692 9fa3e853 bellard
static inline void set_bits(uint8_t *tab, int start, int len)
693 9fa3e853 bellard
{
694 9fa3e853 bellard
    int end, mask, end1;
695 9fa3e853 bellard
696 9fa3e853 bellard
    end = start + len;
697 9fa3e853 bellard
    tab += start >> 3;
698 9fa3e853 bellard
    mask = 0xff << (start & 7);
699 9fa3e853 bellard
    if ((start & ~7) == (end & ~7)) {
700 9fa3e853 bellard
        if (start < end) {
701 9fa3e853 bellard
            mask &= ~(0xff << (end & 7));
702 9fa3e853 bellard
            *tab |= mask;
703 9fa3e853 bellard
        }
704 9fa3e853 bellard
    } else {
705 9fa3e853 bellard
        *tab++ |= mask;
706 9fa3e853 bellard
        start = (start + 8) & ~7;
707 9fa3e853 bellard
        end1 = end & ~7;
708 9fa3e853 bellard
        while (start < end1) {
709 9fa3e853 bellard
            *tab++ = 0xff;
710 9fa3e853 bellard
            start += 8;
711 9fa3e853 bellard
        }
712 9fa3e853 bellard
        if (start < end) {
713 9fa3e853 bellard
            mask = ~(0xff << (end & 7));
714 9fa3e853 bellard
            *tab |= mask;
715 9fa3e853 bellard
        }
716 9fa3e853 bellard
    }
717 9fa3e853 bellard
}
718 9fa3e853 bellard
719 9fa3e853 bellard
static void build_page_bitmap(PageDesc *p)
720 9fa3e853 bellard
{
721 9fa3e853 bellard
    int n, tb_start, tb_end;
722 9fa3e853 bellard
    TranslationBlock *tb;
723 3b46e624 ths
724 b2a7081a pbrook
    p->code_bitmap = qemu_mallocz(TARGET_PAGE_SIZE / 8);
725 9fa3e853 bellard
    if (!p->code_bitmap)
726 9fa3e853 bellard
        return;
727 9fa3e853 bellard
728 9fa3e853 bellard
    tb = p->first_tb;
729 9fa3e853 bellard
    while (tb != NULL) {
730 9fa3e853 bellard
        n = (long)tb & 3;
731 9fa3e853 bellard
        tb = (TranslationBlock *)((long)tb & ~3);
732 9fa3e853 bellard
        /* NOTE: this is subtle as a TB may span two physical pages */
733 9fa3e853 bellard
        if (n == 0) {
734 9fa3e853 bellard
            /* NOTE: tb_end may be after the end of the page, but
735 9fa3e853 bellard
               it is not a problem */
736 9fa3e853 bellard
            tb_start = tb->pc & ~TARGET_PAGE_MASK;
737 9fa3e853 bellard
            tb_end = tb_start + tb->size;
738 9fa3e853 bellard
            if (tb_end > TARGET_PAGE_SIZE)
739 9fa3e853 bellard
                tb_end = TARGET_PAGE_SIZE;
740 9fa3e853 bellard
        } else {
741 9fa3e853 bellard
            tb_start = 0;
742 9fa3e853 bellard
            tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
743 9fa3e853 bellard
        }
744 9fa3e853 bellard
        set_bits(p->code_bitmap, tb_start, tb_end - tb_start);
745 9fa3e853 bellard
        tb = tb->page_next[n];
746 9fa3e853 bellard
    }
747 9fa3e853 bellard
}
748 9fa3e853 bellard
749 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
750 d720b93d bellard
751 5fafdf24 ths
static void tb_gen_code(CPUState *env,
752 d720b93d bellard
                        target_ulong pc, target_ulong cs_base, int flags,
753 d720b93d bellard
                        int cflags)
754 d720b93d bellard
{
755 d720b93d bellard
    TranslationBlock *tb;
756 d720b93d bellard
    uint8_t *tc_ptr;
757 d720b93d bellard
    target_ulong phys_pc, phys_page2, virt_page2;
758 d720b93d bellard
    int code_gen_size;
759 d720b93d bellard
760 c27004ec bellard
    phys_pc = get_phys_addr_code(env, pc);
761 c27004ec bellard
    tb = tb_alloc(pc);
762 d720b93d bellard
    if (!tb) {
763 d720b93d bellard
        /* flush must be done */
764 d720b93d bellard
        tb_flush(env);
765 d720b93d bellard
        /* cannot fail at this point */
766 c27004ec bellard
        tb = tb_alloc(pc);
767 d720b93d bellard
    }
768 d720b93d bellard
    tc_ptr = code_gen_ptr;
769 d720b93d bellard
    tb->tc_ptr = tc_ptr;
770 d720b93d bellard
    tb->cs_base = cs_base;
771 d720b93d bellard
    tb->flags = flags;
772 d720b93d bellard
    tb->cflags = cflags;
773 d07bde88 blueswir1
    cpu_gen_code(env, tb, &code_gen_size);
774 d720b93d bellard
    code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
775 3b46e624 ths
776 d720b93d bellard
    /* check next page if needed */
777 c27004ec bellard
    virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
778 d720b93d bellard
    phys_page2 = -1;
779 c27004ec bellard
    if ((pc & TARGET_PAGE_MASK) != virt_page2) {
780 d720b93d bellard
        phys_page2 = get_phys_addr_code(env, virt_page2);
781 d720b93d bellard
    }
782 d720b93d bellard
    tb_link_phys(tb, phys_pc, phys_page2);
783 d720b93d bellard
}
784 d720b93d bellard
#endif
785 3b46e624 ths
786 9fa3e853 bellard
/* invalidate all TBs which intersect with the target physical page
787 9fa3e853 bellard
   starting in range [start;end[. NOTE: start and end must refer to
788 d720b93d bellard
   the same physical page. 'is_cpu_write_access' should be true if called
789 d720b93d bellard
   from a real cpu write access: the virtual CPU will exit the current
790 d720b93d bellard
   TB if code is modified inside this TB. */
791 00f82b8a aurel32
void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t end,
792 d720b93d bellard
                                   int is_cpu_write_access)
793 d720b93d bellard
{
794 d720b93d bellard
    int n, current_tb_modified, current_tb_not_found, current_flags;
795 d720b93d bellard
    CPUState *env = cpu_single_env;
796 9fa3e853 bellard
    PageDesc *p;
797 ea1c1802 bellard
    TranslationBlock *tb, *tb_next, *current_tb, *saved_tb;
798 9fa3e853 bellard
    target_ulong tb_start, tb_end;
799 d720b93d bellard
    target_ulong current_pc, current_cs_base;
800 9fa3e853 bellard
801 9fa3e853 bellard
    p = page_find(start >> TARGET_PAGE_BITS);
802 5fafdf24 ths
    if (!p)
803 9fa3e853 bellard
        return;
804 5fafdf24 ths
    if (!p->code_bitmap &&
805 d720b93d bellard
        ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
806 d720b93d bellard
        is_cpu_write_access) {
807 9fa3e853 bellard
        /* build code bitmap */
808 9fa3e853 bellard
        build_page_bitmap(p);
809 9fa3e853 bellard
    }
810 9fa3e853 bellard
811 9fa3e853 bellard
    /* we remove all the TBs in the range [start, end[ */
812 9fa3e853 bellard
    /* XXX: see if in some cases it could be faster to invalidate all the code */
813 d720b93d bellard
    current_tb_not_found = is_cpu_write_access;
814 d720b93d bellard
    current_tb_modified = 0;
815 d720b93d bellard
    current_tb = NULL; /* avoid warning */
816 d720b93d bellard
    current_pc = 0; /* avoid warning */
817 d720b93d bellard
    current_cs_base = 0; /* avoid warning */
818 d720b93d bellard
    current_flags = 0; /* avoid warning */
819 9fa3e853 bellard
    tb = p->first_tb;
820 9fa3e853 bellard
    while (tb != NULL) {
821 9fa3e853 bellard
        n = (long)tb & 3;
822 9fa3e853 bellard
        tb = (TranslationBlock *)((long)tb & ~3);
823 9fa3e853 bellard
        tb_next = tb->page_next[n];
824 9fa3e853 bellard
        /* NOTE: this is subtle as a TB may span two physical pages */
825 9fa3e853 bellard
        if (n == 0) {
826 9fa3e853 bellard
            /* NOTE: tb_end may be after the end of the page, but
827 9fa3e853 bellard
               it is not a problem */
828 9fa3e853 bellard
            tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
829 9fa3e853 bellard
            tb_end = tb_start + tb->size;
830 9fa3e853 bellard
        } else {
831 9fa3e853 bellard
            tb_start = tb->page_addr[1];
832 9fa3e853 bellard
            tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
833 9fa3e853 bellard
        }
834 9fa3e853 bellard
        if (!(tb_end <= start || tb_start >= end)) {
835 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
836 d720b93d bellard
            if (current_tb_not_found) {
837 d720b93d bellard
                current_tb_not_found = 0;
838 d720b93d bellard
                current_tb = NULL;
839 d720b93d bellard
                if (env->mem_write_pc) {
840 d720b93d bellard
                    /* now we have a real cpu fault */
841 d720b93d bellard
                    current_tb = tb_find_pc(env->mem_write_pc);
842 d720b93d bellard
                }
843 d720b93d bellard
            }
844 d720b93d bellard
            if (current_tb == tb &&
845 d720b93d bellard
                !(current_tb->cflags & CF_SINGLE_INSN)) {
846 d720b93d bellard
                /* If we are modifying the current TB, we must stop
847 d720b93d bellard
                its execution. We could be more precise by checking
848 d720b93d bellard
                that the modification is after the current PC, but it
849 d720b93d bellard
                would require a specialized function to partially
850 d720b93d bellard
                restore the CPU state */
851 3b46e624 ths
852 d720b93d bellard
                current_tb_modified = 1;
853 5fafdf24 ths
                cpu_restore_state(current_tb, env,
854 d720b93d bellard
                                  env->mem_write_pc, NULL);
855 d720b93d bellard
#if defined(TARGET_I386)
856 d720b93d bellard
                current_flags = env->hflags;
857 d720b93d bellard
                current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
858 d720b93d bellard
                current_cs_base = (target_ulong)env->segs[R_CS].base;
859 d720b93d bellard
                current_pc = current_cs_base + env->eip;
860 d720b93d bellard
#else
861 d720b93d bellard
#error unsupported CPU
862 d720b93d bellard
#endif
863 d720b93d bellard
            }
864 d720b93d bellard
#endif /* TARGET_HAS_PRECISE_SMC */
865 6f5a9f7e bellard
            /* we need to do that to handle the case where a signal
866 6f5a9f7e bellard
               occurs while doing tb_phys_invalidate() */
867 6f5a9f7e bellard
            saved_tb = NULL;
868 6f5a9f7e bellard
            if (env) {
869 6f5a9f7e bellard
                saved_tb = env->current_tb;
870 6f5a9f7e bellard
                env->current_tb = NULL;
871 6f5a9f7e bellard
            }
872 9fa3e853 bellard
            tb_phys_invalidate(tb, -1);
873 6f5a9f7e bellard
            if (env) {
874 6f5a9f7e bellard
                env->current_tb = saved_tb;
875 6f5a9f7e bellard
                if (env->interrupt_request && env->current_tb)
876 6f5a9f7e bellard
                    cpu_interrupt(env, env->interrupt_request);
877 6f5a9f7e bellard
            }
878 9fa3e853 bellard
        }
879 9fa3e853 bellard
        tb = tb_next;
880 9fa3e853 bellard
    }
881 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
882 9fa3e853 bellard
    /* if no code remaining, no need to continue to use slow writes */
883 9fa3e853 bellard
    if (!p->first_tb) {
884 9fa3e853 bellard
        invalidate_page_bitmap(p);
885 d720b93d bellard
        if (is_cpu_write_access) {
886 d720b93d bellard
            tlb_unprotect_code_phys(env, start, env->mem_write_vaddr);
887 d720b93d bellard
        }
888 d720b93d bellard
    }
889 d720b93d bellard
#endif
890 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
891 d720b93d bellard
    if (current_tb_modified) {
892 d720b93d bellard
        /* we generate a block containing just the instruction
893 d720b93d bellard
           modifying the memory. It will ensure that it cannot modify
894 d720b93d bellard
           itself */
895 ea1c1802 bellard
        env->current_tb = NULL;
896 5fafdf24 ths
        tb_gen_code(env, current_pc, current_cs_base, current_flags,
897 d720b93d bellard
                    CF_SINGLE_INSN);
898 d720b93d bellard
        cpu_resume_from_signal(env, NULL);
899 9fa3e853 bellard
    }
900 fd6ce8f6 bellard
#endif
901 9fa3e853 bellard
}
902 fd6ce8f6 bellard
903 9fa3e853 bellard
/* len must be <= 8 and start must be a multiple of len */
904 00f82b8a aurel32
static inline void tb_invalidate_phys_page_fast(target_phys_addr_t start, int len)
905 9fa3e853 bellard
{
906 9fa3e853 bellard
    PageDesc *p;
907 9fa3e853 bellard
    int offset, b;
908 59817ccb bellard
#if 0
909 a4193c8a bellard
    if (1) {
910 a4193c8a bellard
        if (loglevel) {
911 5fafdf24 ths
            fprintf(logfile, "modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
912 5fafdf24 ths
                   cpu_single_env->mem_write_vaddr, len,
913 5fafdf24 ths
                   cpu_single_env->eip,
914 a4193c8a bellard
                   cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
915 a4193c8a bellard
        }
916 59817ccb bellard
    }
917 59817ccb bellard
#endif
918 9fa3e853 bellard
    p = page_find(start >> TARGET_PAGE_BITS);
919 5fafdf24 ths
    if (!p)
920 9fa3e853 bellard
        return;
921 9fa3e853 bellard
    if (p->code_bitmap) {
922 9fa3e853 bellard
        offset = start & ~TARGET_PAGE_MASK;
923 9fa3e853 bellard
        b = p->code_bitmap[offset >> 3] >> (offset & 7);
924 9fa3e853 bellard
        if (b & ((1 << len) - 1))
925 9fa3e853 bellard
            goto do_invalidate;
926 9fa3e853 bellard
    } else {
927 9fa3e853 bellard
    do_invalidate:
928 d720b93d bellard
        tb_invalidate_phys_page_range(start, start + len, 1);
929 9fa3e853 bellard
    }
930 9fa3e853 bellard
}
931 9fa3e853 bellard
932 9fa3e853 bellard
#if !defined(CONFIG_SOFTMMU)
933 00f82b8a aurel32
static void tb_invalidate_phys_page(target_phys_addr_t addr,
934 d720b93d bellard
                                    unsigned long pc, void *puc)
935 9fa3e853 bellard
{
936 d720b93d bellard
    int n, current_flags, current_tb_modified;
937 d720b93d bellard
    target_ulong current_pc, current_cs_base;
938 9fa3e853 bellard
    PageDesc *p;
939 d720b93d bellard
    TranslationBlock *tb, *current_tb;
940 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
941 d720b93d bellard
    CPUState *env = cpu_single_env;
942 d720b93d bellard
#endif
943 9fa3e853 bellard
944 9fa3e853 bellard
    addr &= TARGET_PAGE_MASK;
945 9fa3e853 bellard
    p = page_find(addr >> TARGET_PAGE_BITS);
946 5fafdf24 ths
    if (!p)
947 9fa3e853 bellard
        return;
948 9fa3e853 bellard
    tb = p->first_tb;
949 d720b93d bellard
    current_tb_modified = 0;
950 d720b93d bellard
    current_tb = NULL;
951 d720b93d bellard
    current_pc = 0; /* avoid warning */
952 d720b93d bellard
    current_cs_base = 0; /* avoid warning */
953 d720b93d bellard
    current_flags = 0; /* avoid warning */
954 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
955 d720b93d bellard
    if (tb && pc != 0) {
956 d720b93d bellard
        current_tb = tb_find_pc(pc);
957 d720b93d bellard
    }
958 d720b93d bellard
#endif
959 9fa3e853 bellard
    while (tb != NULL) {
960 9fa3e853 bellard
        n = (long)tb & 3;
961 9fa3e853 bellard
        tb = (TranslationBlock *)((long)tb & ~3);
962 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
963 d720b93d bellard
        if (current_tb == tb &&
964 d720b93d bellard
            !(current_tb->cflags & CF_SINGLE_INSN)) {
965 d720b93d bellard
                /* If we are modifying the current TB, we must stop
966 d720b93d bellard
                   its execution. We could be more precise by checking
967 d720b93d bellard
                   that the modification is after the current PC, but it
968 d720b93d bellard
                   would require a specialized function to partially
969 d720b93d bellard
                   restore the CPU state */
970 3b46e624 ths
971 d720b93d bellard
            current_tb_modified = 1;
972 d720b93d bellard
            cpu_restore_state(current_tb, env, pc, puc);
973 d720b93d bellard
#if defined(TARGET_I386)
974 d720b93d bellard
            current_flags = env->hflags;
975 d720b93d bellard
            current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
976 d720b93d bellard
            current_cs_base = (target_ulong)env->segs[R_CS].base;
977 d720b93d bellard
            current_pc = current_cs_base + env->eip;
978 d720b93d bellard
#else
979 d720b93d bellard
#error unsupported CPU
980 d720b93d bellard
#endif
981 d720b93d bellard
        }
982 d720b93d bellard
#endif /* TARGET_HAS_PRECISE_SMC */
983 9fa3e853 bellard
        tb_phys_invalidate(tb, addr);
984 9fa3e853 bellard
        tb = tb->page_next[n];
985 9fa3e853 bellard
    }
986 fd6ce8f6 bellard
    p->first_tb = NULL;
987 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
988 d720b93d bellard
    if (current_tb_modified) {
989 d720b93d bellard
        /* we generate a block containing just the instruction
990 d720b93d bellard
           modifying the memory. It will ensure that it cannot modify
991 d720b93d bellard
           itself */
992 ea1c1802 bellard
        env->current_tb = NULL;
993 5fafdf24 ths
        tb_gen_code(env, current_pc, current_cs_base, current_flags,
994 d720b93d bellard
                    CF_SINGLE_INSN);
995 d720b93d bellard
        cpu_resume_from_signal(env, puc);
996 d720b93d bellard
    }
997 d720b93d bellard
#endif
998 fd6ce8f6 bellard
}
999 9fa3e853 bellard
#endif
1000 fd6ce8f6 bellard
1001 fd6ce8f6 bellard
/* add the tb in the target page and protect it if necessary */
1002 5fafdf24 ths
static inline void tb_alloc_page(TranslationBlock *tb,
1003 53a5960a pbrook
                                 unsigned int n, target_ulong page_addr)
1004 fd6ce8f6 bellard
{
1005 fd6ce8f6 bellard
    PageDesc *p;
1006 9fa3e853 bellard
    TranslationBlock *last_first_tb;
1007 9fa3e853 bellard
1008 9fa3e853 bellard
    tb->page_addr[n] = page_addr;
1009 3a7d929e bellard
    p = page_find_alloc(page_addr >> TARGET_PAGE_BITS);
1010 9fa3e853 bellard
    tb->page_next[n] = p->first_tb;
1011 9fa3e853 bellard
    last_first_tb = p->first_tb;
1012 9fa3e853 bellard
    p->first_tb = (TranslationBlock *)((long)tb | n);
1013 9fa3e853 bellard
    invalidate_page_bitmap(p);
1014 fd6ce8f6 bellard
1015 107db443 bellard
#if defined(TARGET_HAS_SMC) || 1
1016 d720b93d bellard
1017 9fa3e853 bellard
#if defined(CONFIG_USER_ONLY)
1018 fd6ce8f6 bellard
    if (p->flags & PAGE_WRITE) {
1019 53a5960a pbrook
        target_ulong addr;
1020 53a5960a pbrook
        PageDesc *p2;
1021 9fa3e853 bellard
        int prot;
1022 9fa3e853 bellard
1023 fd6ce8f6 bellard
        /* force the host page as non writable (writes will have a
1024 fd6ce8f6 bellard
           page fault + mprotect overhead) */
1025 53a5960a pbrook
        page_addr &= qemu_host_page_mask;
1026 fd6ce8f6 bellard
        prot = 0;
1027 53a5960a pbrook
        for(addr = page_addr; addr < page_addr + qemu_host_page_size;
1028 53a5960a pbrook
            addr += TARGET_PAGE_SIZE) {
1029 53a5960a pbrook
1030 53a5960a pbrook
            p2 = page_find (addr >> TARGET_PAGE_BITS);
1031 53a5960a pbrook
            if (!p2)
1032 53a5960a pbrook
                continue;
1033 53a5960a pbrook
            prot |= p2->flags;
1034 53a5960a pbrook
            p2->flags &= ~PAGE_WRITE;
1035 53a5960a pbrook
            page_get_flags(addr);
1036 53a5960a pbrook
          }
1037 5fafdf24 ths
        mprotect(g2h(page_addr), qemu_host_page_size,
1038 fd6ce8f6 bellard
                 (prot & PAGE_BITS) & ~PAGE_WRITE);
1039 fd6ce8f6 bellard
#ifdef DEBUG_TB_INVALIDATE
1040 ab3d1727 blueswir1
        printf("protecting code page: 0x" TARGET_FMT_lx "\n",
1041 53a5960a pbrook
               page_addr);
1042 fd6ce8f6 bellard
#endif
1043 fd6ce8f6 bellard
    }
1044 9fa3e853 bellard
#else
1045 9fa3e853 bellard
    /* if some code is already present, then the pages are already
1046 9fa3e853 bellard
       protected. So we handle the case where only the first TB is
1047 9fa3e853 bellard
       allocated in a physical page */
1048 9fa3e853 bellard
    if (!last_first_tb) {
1049 6a00d601 bellard
        tlb_protect_code(page_addr);
1050 9fa3e853 bellard
    }
1051 9fa3e853 bellard
#endif
1052 d720b93d bellard
1053 d720b93d bellard
#endif /* TARGET_HAS_SMC */
1054 fd6ce8f6 bellard
}
1055 fd6ce8f6 bellard
1056 fd6ce8f6 bellard
/* Allocate a new translation block. Flush the translation buffer if
1057 fd6ce8f6 bellard
   too many translation blocks or too much generated code. */
1058 c27004ec bellard
TranslationBlock *tb_alloc(target_ulong pc)
1059 fd6ce8f6 bellard
{
1060 fd6ce8f6 bellard
    TranslationBlock *tb;
1061 fd6ce8f6 bellard
1062 26a5f13b bellard
    if (nb_tbs >= code_gen_max_blocks ||
1063 26a5f13b bellard
        (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
1064 d4e8164f bellard
        return NULL;
1065 fd6ce8f6 bellard
    tb = &tbs[nb_tbs++];
1066 fd6ce8f6 bellard
    tb->pc = pc;
1067 b448f2f3 bellard
    tb->cflags = 0;
1068 d4e8164f bellard
    return tb;
1069 d4e8164f bellard
}
1070 d4e8164f bellard
1071 9fa3e853 bellard
/* add a new TB and link it to the physical page tables. phys_page2 is
1072 9fa3e853 bellard
   (-1) to indicate that only one page contains the TB. */
1073 5fafdf24 ths
void tb_link_phys(TranslationBlock *tb,
1074 9fa3e853 bellard
                  target_ulong phys_pc, target_ulong phys_page2)
1075 d4e8164f bellard
{
1076 9fa3e853 bellard
    unsigned int h;
1077 9fa3e853 bellard
    TranslationBlock **ptb;
1078 9fa3e853 bellard
1079 c8a706fe pbrook
    /* Grab the mmap lock to stop another thread invalidating this TB
1080 c8a706fe pbrook
       before we are done.  */
1081 c8a706fe pbrook
    mmap_lock();
1082 9fa3e853 bellard
    /* add in the physical hash table */
1083 9fa3e853 bellard
    h = tb_phys_hash_func(phys_pc);
1084 9fa3e853 bellard
    ptb = &tb_phys_hash[h];
1085 9fa3e853 bellard
    tb->phys_hash_next = *ptb;
1086 9fa3e853 bellard
    *ptb = tb;
1087 fd6ce8f6 bellard
1088 fd6ce8f6 bellard
    /* add in the page list */
1089 9fa3e853 bellard
    tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK);
1090 9fa3e853 bellard
    if (phys_page2 != -1)
1091 9fa3e853 bellard
        tb_alloc_page(tb, 1, phys_page2);
1092 9fa3e853 bellard
    else
1093 9fa3e853 bellard
        tb->page_addr[1] = -1;
1094 9fa3e853 bellard
1095 d4e8164f bellard
    tb->jmp_first = (TranslationBlock *)((long)tb | 2);
1096 d4e8164f bellard
    tb->jmp_next[0] = NULL;
1097 d4e8164f bellard
    tb->jmp_next[1] = NULL;
1098 d4e8164f bellard
1099 d4e8164f bellard
    /* init original jump addresses */
1100 d4e8164f bellard
    if (tb->tb_next_offset[0] != 0xffff)
1101 d4e8164f bellard
        tb_reset_jump(tb, 0);
1102 d4e8164f bellard
    if (tb->tb_next_offset[1] != 0xffff)
1103 d4e8164f bellard
        tb_reset_jump(tb, 1);
1104 8a40a180 bellard
1105 8a40a180 bellard
#ifdef DEBUG_TB_CHECK
1106 8a40a180 bellard
    tb_page_check();
1107 8a40a180 bellard
#endif
1108 c8a706fe pbrook
    mmap_unlock();
1109 fd6ce8f6 bellard
}
1110 fd6ce8f6 bellard
1111 9fa3e853 bellard
/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
1112 9fa3e853 bellard
   tb[1].tc_ptr. Return NULL if not found */
1113 9fa3e853 bellard
TranslationBlock *tb_find_pc(unsigned long tc_ptr)
1114 fd6ce8f6 bellard
{
1115 9fa3e853 bellard
    int m_min, m_max, m;
1116 9fa3e853 bellard
    unsigned long v;
1117 9fa3e853 bellard
    TranslationBlock *tb;
1118 a513fe19 bellard
1119 a513fe19 bellard
    if (nb_tbs <= 0)
1120 a513fe19 bellard
        return NULL;
1121 a513fe19 bellard
    if (tc_ptr < (unsigned long)code_gen_buffer ||
1122 a513fe19 bellard
        tc_ptr >= (unsigned long)code_gen_ptr)
1123 a513fe19 bellard
        return NULL;
1124 a513fe19 bellard
    /* binary search (cf Knuth) */
1125 a513fe19 bellard
    m_min = 0;
1126 a513fe19 bellard
    m_max = nb_tbs - 1;
1127 a513fe19 bellard
    while (m_min <= m_max) {
1128 a513fe19 bellard
        m = (m_min + m_max) >> 1;
1129 a513fe19 bellard
        tb = &tbs[m];
1130 a513fe19 bellard
        v = (unsigned long)tb->tc_ptr;
1131 a513fe19 bellard
        if (v == tc_ptr)
1132 a513fe19 bellard
            return tb;
1133 a513fe19 bellard
        else if (tc_ptr < v) {
1134 a513fe19 bellard
            m_max = m - 1;
1135 a513fe19 bellard
        } else {
1136 a513fe19 bellard
            m_min = m + 1;
1137 a513fe19 bellard
        }
1138 5fafdf24 ths
    }
1139 a513fe19 bellard
    return &tbs[m_max];
1140 a513fe19 bellard
}
1141 7501267e bellard
1142 ea041c0e bellard
static void tb_reset_jump_recursive(TranslationBlock *tb);
1143 ea041c0e bellard
1144 ea041c0e bellard
static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
1145 ea041c0e bellard
{
1146 ea041c0e bellard
    TranslationBlock *tb1, *tb_next, **ptb;
1147 ea041c0e bellard
    unsigned int n1;
1148 ea041c0e bellard
1149 ea041c0e bellard
    tb1 = tb->jmp_next[n];
1150 ea041c0e bellard
    if (tb1 != NULL) {
1151 ea041c0e bellard
        /* find head of list */
1152 ea041c0e bellard
        for(;;) {
1153 ea041c0e bellard
            n1 = (long)tb1 & 3;
1154 ea041c0e bellard
            tb1 = (TranslationBlock *)((long)tb1 & ~3);
1155 ea041c0e bellard
            if (n1 == 2)
1156 ea041c0e bellard
                break;
1157 ea041c0e bellard
            tb1 = tb1->jmp_next[n1];
1158 ea041c0e bellard
        }
1159 ea041c0e bellard
        /* we are now sure now that tb jumps to tb1 */
1160 ea041c0e bellard
        tb_next = tb1;
1161 ea041c0e bellard
1162 ea041c0e bellard
        /* remove tb from the jmp_first list */
1163 ea041c0e bellard
        ptb = &tb_next->jmp_first;
1164 ea041c0e bellard
        for(;;) {
1165 ea041c0e bellard
            tb1 = *ptb;
1166 ea041c0e bellard
            n1 = (long)tb1 & 3;
1167 ea041c0e bellard
            tb1 = (TranslationBlock *)((long)tb1 & ~3);
1168 ea041c0e bellard
            if (n1 == n && tb1 == tb)
1169 ea041c0e bellard
                break;
1170 ea041c0e bellard
            ptb = &tb1->jmp_next[n1];
1171 ea041c0e bellard
        }
1172 ea041c0e bellard
        *ptb = tb->jmp_next[n];
1173 ea041c0e bellard
        tb->jmp_next[n] = NULL;
1174 3b46e624 ths
1175 ea041c0e bellard
        /* suppress the jump to next tb in generated code */
1176 ea041c0e bellard
        tb_reset_jump(tb, n);
1177 ea041c0e bellard
1178 0124311e bellard
        /* suppress jumps in the tb on which we could have jumped */
1179 ea041c0e bellard
        tb_reset_jump_recursive(tb_next);
1180 ea041c0e bellard
    }
1181 ea041c0e bellard
}
1182 ea041c0e bellard
1183 ea041c0e bellard
static void tb_reset_jump_recursive(TranslationBlock *tb)
1184 ea041c0e bellard
{
1185 ea041c0e bellard
    tb_reset_jump_recursive2(tb, 0);
1186 ea041c0e bellard
    tb_reset_jump_recursive2(tb, 1);
1187 ea041c0e bellard
}
1188 ea041c0e bellard
1189 1fddef4b bellard
#if defined(TARGET_HAS_ICE)
1190 d720b93d bellard
static void breakpoint_invalidate(CPUState *env, target_ulong pc)
1191 d720b93d bellard
{
1192 9b3c35e0 j_mayer
    target_phys_addr_t addr;
1193 9b3c35e0 j_mayer
    target_ulong pd;
1194 c2f07f81 pbrook
    ram_addr_t ram_addr;
1195 c2f07f81 pbrook
    PhysPageDesc *p;
1196 d720b93d bellard
1197 c2f07f81 pbrook
    addr = cpu_get_phys_page_debug(env, pc);
1198 c2f07f81 pbrook
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
1199 c2f07f81 pbrook
    if (!p) {
1200 c2f07f81 pbrook
        pd = IO_MEM_UNASSIGNED;
1201 c2f07f81 pbrook
    } else {
1202 c2f07f81 pbrook
        pd = p->phys_offset;
1203 c2f07f81 pbrook
    }
1204 c2f07f81 pbrook
    ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
1205 706cd4b5 pbrook
    tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
1206 d720b93d bellard
}
1207 c27004ec bellard
#endif
1208 d720b93d bellard
1209 6658ffb8 pbrook
/* Add a watchpoint.  */
1210 0f459d16 pbrook
int cpu_watchpoint_insert(CPUState *env, target_ulong addr, int type)
1211 6658ffb8 pbrook
{
1212 6658ffb8 pbrook
    int i;
1213 6658ffb8 pbrook
1214 6658ffb8 pbrook
    for (i = 0; i < env->nb_watchpoints; i++) {
1215 6658ffb8 pbrook
        if (addr == env->watchpoint[i].vaddr)
1216 6658ffb8 pbrook
            return 0;
1217 6658ffb8 pbrook
    }
1218 6658ffb8 pbrook
    if (env->nb_watchpoints >= MAX_WATCHPOINTS)
1219 6658ffb8 pbrook
        return -1;
1220 6658ffb8 pbrook
1221 6658ffb8 pbrook
    i = env->nb_watchpoints++;
1222 6658ffb8 pbrook
    env->watchpoint[i].vaddr = addr;
1223 0f459d16 pbrook
    env->watchpoint[i].type = type;
1224 6658ffb8 pbrook
    tlb_flush_page(env, addr);
1225 6658ffb8 pbrook
    /* FIXME: This flush is needed because of the hack to make memory ops
1226 6658ffb8 pbrook
       terminate the TB.  It can be removed once the proper IO trap and
1227 6658ffb8 pbrook
       re-execute bits are in.  */
1228 6658ffb8 pbrook
    tb_flush(env);
1229 6658ffb8 pbrook
    return i;
1230 6658ffb8 pbrook
}
1231 6658ffb8 pbrook
1232 6658ffb8 pbrook
/* Remove a watchpoint.  */
1233 6658ffb8 pbrook
int cpu_watchpoint_remove(CPUState *env, target_ulong addr)
1234 6658ffb8 pbrook
{
1235 6658ffb8 pbrook
    int i;
1236 6658ffb8 pbrook
1237 6658ffb8 pbrook
    for (i = 0; i < env->nb_watchpoints; i++) {
1238 6658ffb8 pbrook
        if (addr == env->watchpoint[i].vaddr) {
1239 6658ffb8 pbrook
            env->nb_watchpoints--;
1240 6658ffb8 pbrook
            env->watchpoint[i] = env->watchpoint[env->nb_watchpoints];
1241 6658ffb8 pbrook
            tlb_flush_page(env, addr);
1242 6658ffb8 pbrook
            return 0;
1243 6658ffb8 pbrook
        }
1244 6658ffb8 pbrook
    }
1245 6658ffb8 pbrook
    return -1;
1246 6658ffb8 pbrook
}
1247 6658ffb8 pbrook
1248 7d03f82f edgar_igl
/* Remove all watchpoints. */
1249 7d03f82f edgar_igl
void cpu_watchpoint_remove_all(CPUState *env) {
1250 7d03f82f edgar_igl
    int i;
1251 7d03f82f edgar_igl
1252 7d03f82f edgar_igl
    for (i = 0; i < env->nb_watchpoints; i++) {
1253 7d03f82f edgar_igl
        tlb_flush_page(env, env->watchpoint[i].vaddr);
1254 7d03f82f edgar_igl
    }
1255 7d03f82f edgar_igl
    env->nb_watchpoints = 0;
1256 7d03f82f edgar_igl
}
1257 7d03f82f edgar_igl
1258 c33a346e bellard
/* add a breakpoint. EXCP_DEBUG is returned by the CPU loop if a
1259 c33a346e bellard
   breakpoint is reached */
1260 2e12669a bellard
int cpu_breakpoint_insert(CPUState *env, target_ulong pc)
1261 4c3a88a2 bellard
{
1262 1fddef4b bellard
#if defined(TARGET_HAS_ICE)
1263 4c3a88a2 bellard
    int i;
1264 3b46e624 ths
1265 4c3a88a2 bellard
    for(i = 0; i < env->nb_breakpoints; i++) {
1266 4c3a88a2 bellard
        if (env->breakpoints[i] == pc)
1267 4c3a88a2 bellard
            return 0;
1268 4c3a88a2 bellard
    }
1269 4c3a88a2 bellard
1270 4c3a88a2 bellard
    if (env->nb_breakpoints >= MAX_BREAKPOINTS)
1271 4c3a88a2 bellard
        return -1;
1272 4c3a88a2 bellard
    env->breakpoints[env->nb_breakpoints++] = pc;
1273 3b46e624 ths
1274 d720b93d bellard
    breakpoint_invalidate(env, pc);
1275 4c3a88a2 bellard
    return 0;
1276 4c3a88a2 bellard
#else
1277 4c3a88a2 bellard
    return -1;
1278 4c3a88a2 bellard
#endif
1279 4c3a88a2 bellard
}
1280 4c3a88a2 bellard
1281 7d03f82f edgar_igl
/* remove all breakpoints */
1282 7d03f82f edgar_igl
void cpu_breakpoint_remove_all(CPUState *env) {
1283 7d03f82f edgar_igl
#if defined(TARGET_HAS_ICE)
1284 7d03f82f edgar_igl
    int i;
1285 7d03f82f edgar_igl
    for(i = 0; i < env->nb_breakpoints; i++) {
1286 7d03f82f edgar_igl
        breakpoint_invalidate(env, env->breakpoints[i]);
1287 7d03f82f edgar_igl
    }
1288 7d03f82f edgar_igl
    env->nb_breakpoints = 0;
1289 7d03f82f edgar_igl
#endif
1290 7d03f82f edgar_igl
}
1291 7d03f82f edgar_igl
1292 4c3a88a2 bellard
/* remove a breakpoint */
1293 2e12669a bellard
int cpu_breakpoint_remove(CPUState *env, target_ulong pc)
1294 4c3a88a2 bellard
{
1295 1fddef4b bellard
#if defined(TARGET_HAS_ICE)
1296 4c3a88a2 bellard
    int i;
1297 4c3a88a2 bellard
    for(i = 0; i < env->nb_breakpoints; i++) {
1298 4c3a88a2 bellard
        if (env->breakpoints[i] == pc)
1299 4c3a88a2 bellard
            goto found;
1300 4c3a88a2 bellard
    }
1301 4c3a88a2 bellard
    return -1;
1302 4c3a88a2 bellard
 found:
1303 4c3a88a2 bellard
    env->nb_breakpoints--;
1304 1fddef4b bellard
    if (i < env->nb_breakpoints)
1305 1fddef4b bellard
      env->breakpoints[i] = env->breakpoints[env->nb_breakpoints];
1306 d720b93d bellard
1307 d720b93d bellard
    breakpoint_invalidate(env, pc);
1308 4c3a88a2 bellard
    return 0;
1309 4c3a88a2 bellard
#else
1310 4c3a88a2 bellard
    return -1;
1311 4c3a88a2 bellard
#endif
1312 4c3a88a2 bellard
}
1313 4c3a88a2 bellard
1314 c33a346e bellard
/* enable or disable single step mode. EXCP_DEBUG is returned by the
1315 c33a346e bellard
   CPU loop after each instruction */
1316 c33a346e bellard
void cpu_single_step(CPUState *env, int enabled)
1317 c33a346e bellard
{
1318 1fddef4b bellard
#if defined(TARGET_HAS_ICE)
1319 c33a346e bellard
    if (env->singlestep_enabled != enabled) {
1320 c33a346e bellard
        env->singlestep_enabled = enabled;
1321 c33a346e bellard
        /* must flush all the translated code to avoid inconsistancies */
1322 9fa3e853 bellard
        /* XXX: only flush what is necessary */
1323 0124311e bellard
        tb_flush(env);
1324 c33a346e bellard
    }
1325 c33a346e bellard
#endif
1326 c33a346e bellard
}
1327 c33a346e bellard
1328 34865134 bellard
/* enable or disable low levels log */
1329 34865134 bellard
void cpu_set_log(int log_flags)
1330 34865134 bellard
{
1331 34865134 bellard
    loglevel = log_flags;
1332 34865134 bellard
    if (loglevel && !logfile) {
1333 11fcfab4 pbrook
        logfile = fopen(logfilename, log_append ? "a" : "w");
1334 34865134 bellard
        if (!logfile) {
1335 34865134 bellard
            perror(logfilename);
1336 34865134 bellard
            _exit(1);
1337 34865134 bellard
        }
1338 9fa3e853 bellard
#if !defined(CONFIG_SOFTMMU)
1339 9fa3e853 bellard
        /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1340 9fa3e853 bellard
        {
1341 9fa3e853 bellard
            static uint8_t logfile_buf[4096];
1342 9fa3e853 bellard
            setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1343 9fa3e853 bellard
        }
1344 9fa3e853 bellard
#else
1345 34865134 bellard
        setvbuf(logfile, NULL, _IOLBF, 0);
1346 9fa3e853 bellard
#endif
1347 e735b91c pbrook
        log_append = 1;
1348 e735b91c pbrook
    }
1349 e735b91c pbrook
    if (!loglevel && logfile) {
1350 e735b91c pbrook
        fclose(logfile);
1351 e735b91c pbrook
        logfile = NULL;
1352 34865134 bellard
    }
1353 34865134 bellard
}
1354 34865134 bellard
1355 34865134 bellard
void cpu_set_log_filename(const char *filename)
1356 34865134 bellard
{
1357 34865134 bellard
    logfilename = strdup(filename);
1358 e735b91c pbrook
    if (logfile) {
1359 e735b91c pbrook
        fclose(logfile);
1360 e735b91c pbrook
        logfile = NULL;
1361 e735b91c pbrook
    }
1362 e735b91c pbrook
    cpu_set_log(loglevel);
1363 34865134 bellard
}
1364 c33a346e bellard
1365 0124311e bellard
/* mask must never be zero, except for A20 change call */
1366 68a79315 bellard
void cpu_interrupt(CPUState *env, int mask)
1367 ea041c0e bellard
{
1368 d5975363 pbrook
#if !defined(USE_NPTL)
1369 ea041c0e bellard
    TranslationBlock *tb;
1370 15a51156 aurel32
    static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
1371 d5975363 pbrook
#endif
1372 59817ccb bellard
1373 d5975363 pbrook
    /* FIXME: This is probably not threadsafe.  A different thread could
1374 d5975363 pbrook
       be in the mittle of a read-modify-write operation.  */
1375 68a79315 bellard
    env->interrupt_request |= mask;
1376 d5975363 pbrook
#if defined(USE_NPTL)
1377 d5975363 pbrook
    /* FIXME: TB unchaining isn't SMP safe.  For now just ignore the
1378 d5975363 pbrook
       problem and hope the cpu will stop of its own accord.  For userspace
1379 d5975363 pbrook
       emulation this often isn't actually as bad as it sounds.  Often
1380 d5975363 pbrook
       signals are used primarily to interrupt blocking syscalls.  */
1381 d5975363 pbrook
#else
1382 ea041c0e bellard
    /* if the cpu is currently executing code, we must unlink it and
1383 ea041c0e bellard
       all the potentially executing TB */
1384 ea041c0e bellard
    tb = env->current_tb;
1385 ee8b7021 bellard
    if (tb && !testandset(&interrupt_lock)) {
1386 ee8b7021 bellard
        env->current_tb = NULL;
1387 ea041c0e bellard
        tb_reset_jump_recursive(tb);
1388 15a51156 aurel32
        resetlock(&interrupt_lock);
1389 ea041c0e bellard
    }
1390 d5975363 pbrook
#endif
1391 ea041c0e bellard
}
1392 ea041c0e bellard
1393 b54ad049 bellard
void cpu_reset_interrupt(CPUState *env, int mask)
1394 b54ad049 bellard
{
1395 b54ad049 bellard
    env->interrupt_request &= ~mask;
1396 b54ad049 bellard
}
1397 b54ad049 bellard
1398 f193c797 bellard
CPULogItem cpu_log_items[] = {
1399 5fafdf24 ths
    { CPU_LOG_TB_OUT_ASM, "out_asm",
1400 f193c797 bellard
      "show generated host assembly code for each compiled TB" },
1401 f193c797 bellard
    { CPU_LOG_TB_IN_ASM, "in_asm",
1402 f193c797 bellard
      "show target assembly code for each compiled TB" },
1403 5fafdf24 ths
    { CPU_LOG_TB_OP, "op",
1404 57fec1fe bellard
      "show micro ops for each compiled TB" },
1405 f193c797 bellard
    { CPU_LOG_TB_OP_OPT, "op_opt",
1406 e01a1157 blueswir1
      "show micro ops "
1407 e01a1157 blueswir1
#ifdef TARGET_I386
1408 e01a1157 blueswir1
      "before eflags optimization and "
1409 f193c797 bellard
#endif
1410 e01a1157 blueswir1
      "after liveness analysis" },
1411 f193c797 bellard
    { CPU_LOG_INT, "int",
1412 f193c797 bellard
      "show interrupts/exceptions in short format" },
1413 f193c797 bellard
    { CPU_LOG_EXEC, "exec",
1414 f193c797 bellard
      "show trace before each executed TB (lots of logs)" },
1415 9fddaa0c bellard
    { CPU_LOG_TB_CPU, "cpu",
1416 e91c8a77 ths
      "show CPU state before block translation" },
1417 f193c797 bellard
#ifdef TARGET_I386
1418 f193c797 bellard
    { CPU_LOG_PCALL, "pcall",
1419 f193c797 bellard
      "show protected mode far calls/returns/exceptions" },
1420 f193c797 bellard
#endif
1421 8e3a9fd2 bellard
#ifdef DEBUG_IOPORT
1422 fd872598 bellard
    { CPU_LOG_IOPORT, "ioport",
1423 fd872598 bellard
      "show all i/o ports accesses" },
1424 8e3a9fd2 bellard
#endif
1425 f193c797 bellard
    { 0, NULL, NULL },
1426 f193c797 bellard
};
1427 f193c797 bellard
1428 f193c797 bellard
static int cmp1(const char *s1, int n, const char *s2)
1429 f193c797 bellard
{
1430 f193c797 bellard
    if (strlen(s2) != n)
1431 f193c797 bellard
        return 0;
1432 f193c797 bellard
    return memcmp(s1, s2, n) == 0;
1433 f193c797 bellard
}
1434 3b46e624 ths
1435 f193c797 bellard
/* takes a comma separated list of log masks. Return 0 if error. */
1436 f193c797 bellard
int cpu_str_to_log_mask(const char *str)
1437 f193c797 bellard
{
1438 f193c797 bellard
    CPULogItem *item;
1439 f193c797 bellard
    int mask;
1440 f193c797 bellard
    const char *p, *p1;
1441 f193c797 bellard
1442 f193c797 bellard
    p = str;
1443 f193c797 bellard
    mask = 0;
1444 f193c797 bellard
    for(;;) {
1445 f193c797 bellard
        p1 = strchr(p, ',');
1446 f193c797 bellard
        if (!p1)
1447 f193c797 bellard
            p1 = p + strlen(p);
1448 8e3a9fd2 bellard
        if(cmp1(p,p1-p,"all")) {
1449 8e3a9fd2 bellard
                for(item = cpu_log_items; item->mask != 0; item++) {
1450 8e3a9fd2 bellard
                        mask |= item->mask;
1451 8e3a9fd2 bellard
                }
1452 8e3a9fd2 bellard
        } else {
1453 f193c797 bellard
        for(item = cpu_log_items; item->mask != 0; item++) {
1454 f193c797 bellard
            if (cmp1(p, p1 - p, item->name))
1455 f193c797 bellard
                goto found;
1456 f193c797 bellard
        }
1457 f193c797 bellard
        return 0;
1458 8e3a9fd2 bellard
        }
1459 f193c797 bellard
    found:
1460 f193c797 bellard
        mask |= item->mask;
1461 f193c797 bellard
        if (*p1 != ',')
1462 f193c797 bellard
            break;
1463 f193c797 bellard
        p = p1 + 1;
1464 f193c797 bellard
    }
1465 f193c797 bellard
    return mask;
1466 f193c797 bellard
}
1467 ea041c0e bellard
1468 7501267e bellard
void cpu_abort(CPUState *env, const char *fmt, ...)
1469 7501267e bellard
{
1470 7501267e bellard
    va_list ap;
1471 493ae1f0 pbrook
    va_list ap2;
1472 7501267e bellard
1473 7501267e bellard
    va_start(ap, fmt);
1474 493ae1f0 pbrook
    va_copy(ap2, ap);
1475 7501267e bellard
    fprintf(stderr, "qemu: fatal: ");
1476 7501267e bellard
    vfprintf(stderr, fmt, ap);
1477 7501267e bellard
    fprintf(stderr, "\n");
1478 7501267e bellard
#ifdef TARGET_I386
1479 7fe48483 bellard
    cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1480 7fe48483 bellard
#else
1481 7fe48483 bellard
    cpu_dump_state(env, stderr, fprintf, 0);
1482 7501267e bellard
#endif
1483 924edcae balrog
    if (logfile) {
1484 f9373291 j_mayer
        fprintf(logfile, "qemu: fatal: ");
1485 493ae1f0 pbrook
        vfprintf(logfile, fmt, ap2);
1486 f9373291 j_mayer
        fprintf(logfile, "\n");
1487 f9373291 j_mayer
#ifdef TARGET_I386
1488 f9373291 j_mayer
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1489 f9373291 j_mayer
#else
1490 f9373291 j_mayer
        cpu_dump_state(env, logfile, fprintf, 0);
1491 f9373291 j_mayer
#endif
1492 924edcae balrog
        fflush(logfile);
1493 924edcae balrog
        fclose(logfile);
1494 924edcae balrog
    }
1495 493ae1f0 pbrook
    va_end(ap2);
1496 f9373291 j_mayer
    va_end(ap);
1497 7501267e bellard
    abort();
1498 7501267e bellard
}
1499 7501267e bellard
1500 c5be9f08 ths
CPUState *cpu_copy(CPUState *env)
1501 c5be9f08 ths
{
1502 01ba9816 ths
    CPUState *new_env = cpu_init(env->cpu_model_str);
1503 c5be9f08 ths
    /* preserve chaining and index */
1504 c5be9f08 ths
    CPUState *next_cpu = new_env->next_cpu;
1505 c5be9f08 ths
    int cpu_index = new_env->cpu_index;
1506 c5be9f08 ths
    memcpy(new_env, env, sizeof(CPUState));
1507 c5be9f08 ths
    new_env->next_cpu = next_cpu;
1508 c5be9f08 ths
    new_env->cpu_index = cpu_index;
1509 c5be9f08 ths
    return new_env;
1510 c5be9f08 ths
}
1511 c5be9f08 ths
1512 0124311e bellard
#if !defined(CONFIG_USER_ONLY)
1513 0124311e bellard
1514 5c751e99 edgar_igl
static inline void tlb_flush_jmp_cache(CPUState *env, target_ulong addr)
1515 5c751e99 edgar_igl
{
1516 5c751e99 edgar_igl
    unsigned int i;
1517 5c751e99 edgar_igl
1518 5c751e99 edgar_igl
    /* Discard jump cache entries for any tb which might potentially
1519 5c751e99 edgar_igl
       overlap the flushed page.  */
1520 5c751e99 edgar_igl
    i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
1521 5c751e99 edgar_igl
    memset (&env->tb_jmp_cache[i], 0, 
1522 5c751e99 edgar_igl
            TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
1523 5c751e99 edgar_igl
1524 5c751e99 edgar_igl
    i = tb_jmp_cache_hash_page(addr);
1525 5c751e99 edgar_igl
    memset (&env->tb_jmp_cache[i], 0, 
1526 5c751e99 edgar_igl
            TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
1527 5c751e99 edgar_igl
}
1528 5c751e99 edgar_igl
1529 ee8b7021 bellard
/* NOTE: if flush_global is true, also flush global entries (not
1530 ee8b7021 bellard
   implemented yet) */
1531 ee8b7021 bellard
void tlb_flush(CPUState *env, int flush_global)
1532 33417e70 bellard
{
1533 33417e70 bellard
    int i;
1534 0124311e bellard
1535 9fa3e853 bellard
#if defined(DEBUG_TLB)
1536 9fa3e853 bellard
    printf("tlb_flush:\n");
1537 9fa3e853 bellard
#endif
1538 0124311e bellard
    /* must reset current TB so that interrupts cannot modify the
1539 0124311e bellard
       links while we are modifying them */
1540 0124311e bellard
    env->current_tb = NULL;
1541 0124311e bellard
1542 33417e70 bellard
    for(i = 0; i < CPU_TLB_SIZE; i++) {
1543 84b7b8e7 bellard
        env->tlb_table[0][i].addr_read = -1;
1544 84b7b8e7 bellard
        env->tlb_table[0][i].addr_write = -1;
1545 84b7b8e7 bellard
        env->tlb_table[0][i].addr_code = -1;
1546 84b7b8e7 bellard
        env->tlb_table[1][i].addr_read = -1;
1547 84b7b8e7 bellard
        env->tlb_table[1][i].addr_write = -1;
1548 84b7b8e7 bellard
        env->tlb_table[1][i].addr_code = -1;
1549 6fa4cea9 j_mayer
#if (NB_MMU_MODES >= 3)
1550 6fa4cea9 j_mayer
        env->tlb_table[2][i].addr_read = -1;
1551 6fa4cea9 j_mayer
        env->tlb_table[2][i].addr_write = -1;
1552 6fa4cea9 j_mayer
        env->tlb_table[2][i].addr_code = -1;
1553 6fa4cea9 j_mayer
#if (NB_MMU_MODES == 4)
1554 6fa4cea9 j_mayer
        env->tlb_table[3][i].addr_read = -1;
1555 6fa4cea9 j_mayer
        env->tlb_table[3][i].addr_write = -1;
1556 6fa4cea9 j_mayer
        env->tlb_table[3][i].addr_code = -1;
1557 6fa4cea9 j_mayer
#endif
1558 6fa4cea9 j_mayer
#endif
1559 33417e70 bellard
    }
1560 9fa3e853 bellard
1561 8a40a180 bellard
    memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
1562 9fa3e853 bellard
1563 0a962c02 bellard
#ifdef USE_KQEMU
1564 0a962c02 bellard
    if (env->kqemu_enabled) {
1565 0a962c02 bellard
        kqemu_flush(env, flush_global);
1566 0a962c02 bellard
    }
1567 0a962c02 bellard
#endif
1568 e3db7226 bellard
    tlb_flush_count++;
1569 33417e70 bellard
}
1570 33417e70 bellard
1571 274da6b2 bellard
static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
1572 61382a50 bellard
{
1573 5fafdf24 ths
    if (addr == (tlb_entry->addr_read &
1574 84b7b8e7 bellard
                 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1575 5fafdf24 ths
        addr == (tlb_entry->addr_write &
1576 84b7b8e7 bellard
                 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1577 5fafdf24 ths
        addr == (tlb_entry->addr_code &
1578 84b7b8e7 bellard
                 (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1579 84b7b8e7 bellard
        tlb_entry->addr_read = -1;
1580 84b7b8e7 bellard
        tlb_entry->addr_write = -1;
1581 84b7b8e7 bellard
        tlb_entry->addr_code = -1;
1582 84b7b8e7 bellard
    }
1583 61382a50 bellard
}
1584 61382a50 bellard
1585 2e12669a bellard
void tlb_flush_page(CPUState *env, target_ulong addr)
1586 33417e70 bellard
{
1587 8a40a180 bellard
    int i;
1588 0124311e bellard
1589 9fa3e853 bellard
#if defined(DEBUG_TLB)
1590 108c49b8 bellard
    printf("tlb_flush_page: " TARGET_FMT_lx "\n", addr);
1591 9fa3e853 bellard
#endif
1592 0124311e bellard
    /* must reset current TB so that interrupts cannot modify the
1593 0124311e bellard
       links while we are modifying them */
1594 0124311e bellard
    env->current_tb = NULL;
1595 61382a50 bellard
1596 61382a50 bellard
    addr &= TARGET_PAGE_MASK;
1597 61382a50 bellard
    i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1598 84b7b8e7 bellard
    tlb_flush_entry(&env->tlb_table[0][i], addr);
1599 84b7b8e7 bellard
    tlb_flush_entry(&env->tlb_table[1][i], addr);
1600 6fa4cea9 j_mayer
#if (NB_MMU_MODES >= 3)
1601 6fa4cea9 j_mayer
    tlb_flush_entry(&env->tlb_table[2][i], addr);
1602 6fa4cea9 j_mayer
#if (NB_MMU_MODES == 4)
1603 6fa4cea9 j_mayer
    tlb_flush_entry(&env->tlb_table[3][i], addr);
1604 6fa4cea9 j_mayer
#endif
1605 6fa4cea9 j_mayer
#endif
1606 0124311e bellard
1607 5c751e99 edgar_igl
    tlb_flush_jmp_cache(env, addr);
1608 9fa3e853 bellard
1609 0a962c02 bellard
#ifdef USE_KQEMU
1610 0a962c02 bellard
    if (env->kqemu_enabled) {
1611 0a962c02 bellard
        kqemu_flush_page(env, addr);
1612 0a962c02 bellard
    }
1613 0a962c02 bellard
#endif
1614 9fa3e853 bellard
}
1615 9fa3e853 bellard
1616 9fa3e853 bellard
/* update the TLBs so that writes to code in the virtual page 'addr'
1617 9fa3e853 bellard
   can be detected */
1618 6a00d601 bellard
static void tlb_protect_code(ram_addr_t ram_addr)
1619 9fa3e853 bellard
{
1620 5fafdf24 ths
    cpu_physical_memory_reset_dirty(ram_addr,
1621 6a00d601 bellard
                                    ram_addr + TARGET_PAGE_SIZE,
1622 6a00d601 bellard
                                    CODE_DIRTY_FLAG);
1623 9fa3e853 bellard
}
1624 9fa3e853 bellard
1625 9fa3e853 bellard
/* update the TLB so that writes in physical page 'phys_addr' are no longer
1626 3a7d929e bellard
   tested for self modifying code */
1627 5fafdf24 ths
static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
1628 3a7d929e bellard
                                    target_ulong vaddr)
1629 9fa3e853 bellard
{
1630 3a7d929e bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] |= CODE_DIRTY_FLAG;
1631 1ccde1cb bellard
}
1632 1ccde1cb bellard
1633 5fafdf24 ths
static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
1634 1ccde1cb bellard
                                         unsigned long start, unsigned long length)
1635 1ccde1cb bellard
{
1636 1ccde1cb bellard
    unsigned long addr;
1637 84b7b8e7 bellard
    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1638 84b7b8e7 bellard
        addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
1639 1ccde1cb bellard
        if ((addr - start) < length) {
1640 0f459d16 pbrook
            tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
1641 1ccde1cb bellard
        }
1642 1ccde1cb bellard
    }
1643 1ccde1cb bellard
}
1644 1ccde1cb bellard
1645 3a7d929e bellard
void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
1646 0a962c02 bellard
                                     int dirty_flags)
1647 1ccde1cb bellard
{
1648 1ccde1cb bellard
    CPUState *env;
1649 4f2ac237 bellard
    unsigned long length, start1;
1650 0a962c02 bellard
    int i, mask, len;
1651 0a962c02 bellard
    uint8_t *p;
1652 1ccde1cb bellard
1653 1ccde1cb bellard
    start &= TARGET_PAGE_MASK;
1654 1ccde1cb bellard
    end = TARGET_PAGE_ALIGN(end);
1655 1ccde1cb bellard
1656 1ccde1cb bellard
    length = end - start;
1657 1ccde1cb bellard
    if (length == 0)
1658 1ccde1cb bellard
        return;
1659 0a962c02 bellard
    len = length >> TARGET_PAGE_BITS;
1660 3a7d929e bellard
#ifdef USE_KQEMU
1661 6a00d601 bellard
    /* XXX: should not depend on cpu context */
1662 6a00d601 bellard
    env = first_cpu;
1663 3a7d929e bellard
    if (env->kqemu_enabled) {
1664 f23db169 bellard
        ram_addr_t addr;
1665 f23db169 bellard
        addr = start;
1666 f23db169 bellard
        for(i = 0; i < len; i++) {
1667 f23db169 bellard
            kqemu_set_notdirty(env, addr);
1668 f23db169 bellard
            addr += TARGET_PAGE_SIZE;
1669 f23db169 bellard
        }
1670 3a7d929e bellard
    }
1671 3a7d929e bellard
#endif
1672 f23db169 bellard
    mask = ~dirty_flags;
1673 f23db169 bellard
    p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
1674 f23db169 bellard
    for(i = 0; i < len; i++)
1675 f23db169 bellard
        p[i] &= mask;
1676 f23db169 bellard
1677 1ccde1cb bellard
    /* we modify the TLB cache so that the dirty bit will be set again
1678 1ccde1cb bellard
       when accessing the range */
1679 59817ccb bellard
    start1 = start + (unsigned long)phys_ram_base;
1680 6a00d601 bellard
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
1681 6a00d601 bellard
        for(i = 0; i < CPU_TLB_SIZE; i++)
1682 84b7b8e7 bellard
            tlb_reset_dirty_range(&env->tlb_table[0][i], start1, length);
1683 6a00d601 bellard
        for(i = 0; i < CPU_TLB_SIZE; i++)
1684 84b7b8e7 bellard
            tlb_reset_dirty_range(&env->tlb_table[1][i], start1, length);
1685 6fa4cea9 j_mayer
#if (NB_MMU_MODES >= 3)
1686 6fa4cea9 j_mayer
        for(i = 0; i < CPU_TLB_SIZE; i++)
1687 6fa4cea9 j_mayer
            tlb_reset_dirty_range(&env->tlb_table[2][i], start1, length);
1688 6fa4cea9 j_mayer
#if (NB_MMU_MODES == 4)
1689 6fa4cea9 j_mayer
        for(i = 0; i < CPU_TLB_SIZE; i++)
1690 6fa4cea9 j_mayer
            tlb_reset_dirty_range(&env->tlb_table[3][i], start1, length);
1691 6fa4cea9 j_mayer
#endif
1692 6fa4cea9 j_mayer
#endif
1693 6a00d601 bellard
    }
1694 1ccde1cb bellard
}
1695 1ccde1cb bellard
1696 3a7d929e bellard
static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1697 3a7d929e bellard
{
1698 3a7d929e bellard
    ram_addr_t ram_addr;
1699 3a7d929e bellard
1700 84b7b8e7 bellard
    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1701 5fafdf24 ths
        ram_addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) +
1702 3a7d929e bellard
            tlb_entry->addend - (unsigned long)phys_ram_base;
1703 3a7d929e bellard
        if (!cpu_physical_memory_is_dirty(ram_addr)) {
1704 0f459d16 pbrook
            tlb_entry->addr_write |= TLB_NOTDIRTY;
1705 3a7d929e bellard
        }
1706 3a7d929e bellard
    }
1707 3a7d929e bellard
}
1708 3a7d929e bellard
1709 3a7d929e bellard
/* update the TLB according to the current state of the dirty bits */
1710 3a7d929e bellard
void cpu_tlb_update_dirty(CPUState *env)
1711 3a7d929e bellard
{
1712 3a7d929e bellard
    int i;
1713 3a7d929e bellard
    for(i = 0; i < CPU_TLB_SIZE; i++)
1714 84b7b8e7 bellard
        tlb_update_dirty(&env->tlb_table[0][i]);
1715 3a7d929e bellard
    for(i = 0; i < CPU_TLB_SIZE; i++)
1716 84b7b8e7 bellard
        tlb_update_dirty(&env->tlb_table[1][i]);
1717 6fa4cea9 j_mayer
#if (NB_MMU_MODES >= 3)
1718 6fa4cea9 j_mayer
    for(i = 0; i < CPU_TLB_SIZE; i++)
1719 6fa4cea9 j_mayer
        tlb_update_dirty(&env->tlb_table[2][i]);
1720 6fa4cea9 j_mayer
#if (NB_MMU_MODES == 4)
1721 6fa4cea9 j_mayer
    for(i = 0; i < CPU_TLB_SIZE; i++)
1722 6fa4cea9 j_mayer
        tlb_update_dirty(&env->tlb_table[3][i]);
1723 6fa4cea9 j_mayer
#endif
1724 6fa4cea9 j_mayer
#endif
1725 3a7d929e bellard
}
1726 3a7d929e bellard
1727 0f459d16 pbrook
static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, target_ulong vaddr)
1728 1ccde1cb bellard
{
1729 0f459d16 pbrook
    if (tlb_entry->addr_write == (vaddr | TLB_NOTDIRTY))
1730 0f459d16 pbrook
        tlb_entry->addr_write = vaddr;
1731 1ccde1cb bellard
}
1732 1ccde1cb bellard
1733 0f459d16 pbrook
/* update the TLB corresponding to virtual page vaddr
1734 0f459d16 pbrook
   so that it is no longer dirty */
1735 0f459d16 pbrook
static inline void tlb_set_dirty(CPUState *env, target_ulong vaddr)
1736 1ccde1cb bellard
{
1737 1ccde1cb bellard
    int i;
1738 1ccde1cb bellard
1739 0f459d16 pbrook
    vaddr &= TARGET_PAGE_MASK;
1740 1ccde1cb bellard
    i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1741 0f459d16 pbrook
    tlb_set_dirty1(&env->tlb_table[0][i], vaddr);
1742 0f459d16 pbrook
    tlb_set_dirty1(&env->tlb_table[1][i], vaddr);
1743 6fa4cea9 j_mayer
#if (NB_MMU_MODES >= 3)
1744 0f459d16 pbrook
    tlb_set_dirty1(&env->tlb_table[2][i], vaddr);
1745 6fa4cea9 j_mayer
#if (NB_MMU_MODES == 4)
1746 0f459d16 pbrook
    tlb_set_dirty1(&env->tlb_table[3][i], vaddr);
1747 6fa4cea9 j_mayer
#endif
1748 6fa4cea9 j_mayer
#endif
1749 9fa3e853 bellard
}
1750 9fa3e853 bellard
1751 59817ccb bellard
/* add a new TLB entry. At most one entry for a given virtual address
1752 59817ccb bellard
   is permitted. Return 0 if OK or 2 if the page could not be mapped
1753 59817ccb bellard
   (can only happen in non SOFTMMU mode for I/O pages or pages
1754 59817ccb bellard
   conflicting with the host address space). */
1755 5fafdf24 ths
int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
1756 5fafdf24 ths
                      target_phys_addr_t paddr, int prot,
1757 6ebbf390 j_mayer
                      int mmu_idx, int is_softmmu)
1758 9fa3e853 bellard
{
1759 92e873b9 bellard
    PhysPageDesc *p;
1760 4f2ac237 bellard
    unsigned long pd;
1761 9fa3e853 bellard
    unsigned int index;
1762 4f2ac237 bellard
    target_ulong address;
1763 0f459d16 pbrook
    target_ulong code_address;
1764 108c49b8 bellard
    target_phys_addr_t addend;
1765 9fa3e853 bellard
    int ret;
1766 84b7b8e7 bellard
    CPUTLBEntry *te;
1767 6658ffb8 pbrook
    int i;
1768 0f459d16 pbrook
    target_phys_addr_t iotlb;
1769 9fa3e853 bellard
1770 92e873b9 bellard
    p = phys_page_find(paddr >> TARGET_PAGE_BITS);
1771 9fa3e853 bellard
    if (!p) {
1772 9fa3e853 bellard
        pd = IO_MEM_UNASSIGNED;
1773 9fa3e853 bellard
    } else {
1774 9fa3e853 bellard
        pd = p->phys_offset;
1775 9fa3e853 bellard
    }
1776 9fa3e853 bellard
#if defined(DEBUG_TLB)
1777 6ebbf390 j_mayer
    printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x idx=%d smmu=%d pd=0x%08lx\n",
1778 6ebbf390 j_mayer
           vaddr, (int)paddr, prot, mmu_idx, is_softmmu, pd);
1779 9fa3e853 bellard
#endif
1780 9fa3e853 bellard
1781 9fa3e853 bellard
    ret = 0;
1782 0f459d16 pbrook
    address = vaddr;
1783 0f459d16 pbrook
    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
1784 0f459d16 pbrook
        /* IO memory case (romd handled later) */
1785 0f459d16 pbrook
        address |= TLB_MMIO;
1786 0f459d16 pbrook
    }
1787 0f459d16 pbrook
    addend = (unsigned long)phys_ram_base + (pd & TARGET_PAGE_MASK);
1788 0f459d16 pbrook
    if ((pd & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
1789 0f459d16 pbrook
        /* Normal RAM.  */
1790 0f459d16 pbrook
        iotlb = pd & TARGET_PAGE_MASK;
1791 0f459d16 pbrook
        if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM)
1792 0f459d16 pbrook
            iotlb |= IO_MEM_NOTDIRTY;
1793 0f459d16 pbrook
        else
1794 0f459d16 pbrook
            iotlb |= IO_MEM_ROM;
1795 0f459d16 pbrook
    } else {
1796 0f459d16 pbrook
        /* IO handlers are currently passed a phsical address.
1797 0f459d16 pbrook
           It would be nice to pass an offset from the base address
1798 0f459d16 pbrook
           of that region.  This would avoid having to special case RAM,
1799 0f459d16 pbrook
           and avoid full address decoding in every device.
1800 0f459d16 pbrook
           We can't use the high bits of pd for this because
1801 0f459d16 pbrook
           IO_MEM_ROMD uses these as a ram address.  */
1802 0f459d16 pbrook
        iotlb = (pd & ~TARGET_PAGE_MASK) + paddr;
1803 0f459d16 pbrook
    }
1804 0f459d16 pbrook
1805 0f459d16 pbrook
    code_address = address;
1806 0f459d16 pbrook
    /* Make accesses to pages with watchpoints go via the
1807 0f459d16 pbrook
       watchpoint trap routines.  */
1808 0f459d16 pbrook
    for (i = 0; i < env->nb_watchpoints; i++) {
1809 0f459d16 pbrook
        if (vaddr == (env->watchpoint[i].vaddr & TARGET_PAGE_MASK)) {
1810 0f459d16 pbrook
            iotlb = io_mem_watch + paddr;
1811 0f459d16 pbrook
            /* TODO: The memory case can be optimized by not trapping
1812 0f459d16 pbrook
               reads of pages with a write breakpoint.  */
1813 0f459d16 pbrook
            address |= TLB_MMIO;
1814 6658ffb8 pbrook
        }
1815 0f459d16 pbrook
    }
1816 d79acba4 balrog
1817 0f459d16 pbrook
    index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1818 0f459d16 pbrook
    env->iotlb[mmu_idx][index] = iotlb - vaddr;
1819 0f459d16 pbrook
    te = &env->tlb_table[mmu_idx][index];
1820 0f459d16 pbrook
    te->addend = addend - vaddr;
1821 0f459d16 pbrook
    if (prot & PAGE_READ) {
1822 0f459d16 pbrook
        te->addr_read = address;
1823 0f459d16 pbrook
    } else {
1824 0f459d16 pbrook
        te->addr_read = -1;
1825 0f459d16 pbrook
    }
1826 5c751e99 edgar_igl
1827 0f459d16 pbrook
    if (prot & PAGE_EXEC) {
1828 0f459d16 pbrook
        te->addr_code = code_address;
1829 0f459d16 pbrook
    } else {
1830 0f459d16 pbrook
        te->addr_code = -1;
1831 0f459d16 pbrook
    }
1832 0f459d16 pbrook
    if (prot & PAGE_WRITE) {
1833 0f459d16 pbrook
        if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM ||
1834 0f459d16 pbrook
            (pd & IO_MEM_ROMD)) {
1835 0f459d16 pbrook
            /* Write access calls the I/O callback.  */
1836 0f459d16 pbrook
            te->addr_write = address | TLB_MMIO;
1837 0f459d16 pbrook
        } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
1838 0f459d16 pbrook
                   !cpu_physical_memory_is_dirty(pd)) {
1839 0f459d16 pbrook
            te->addr_write = address | TLB_NOTDIRTY;
1840 9fa3e853 bellard
        } else {
1841 0f459d16 pbrook
            te->addr_write = address;
1842 9fa3e853 bellard
        }
1843 0f459d16 pbrook
    } else {
1844 0f459d16 pbrook
        te->addr_write = -1;
1845 9fa3e853 bellard
    }
1846 9fa3e853 bellard
    return ret;
1847 9fa3e853 bellard
}
1848 9fa3e853 bellard
1849 0124311e bellard
#else
1850 0124311e bellard
1851 ee8b7021 bellard
void tlb_flush(CPUState *env, int flush_global)
1852 0124311e bellard
{
1853 0124311e bellard
}
1854 0124311e bellard
1855 2e12669a bellard
void tlb_flush_page(CPUState *env, target_ulong addr)
1856 0124311e bellard
{
1857 0124311e bellard
}
1858 0124311e bellard
1859 5fafdf24 ths
int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
1860 5fafdf24 ths
                      target_phys_addr_t paddr, int prot,
1861 6ebbf390 j_mayer
                      int mmu_idx, int is_softmmu)
1862 9fa3e853 bellard
{
1863 9fa3e853 bellard
    return 0;
1864 9fa3e853 bellard
}
1865 0124311e bellard
1866 9fa3e853 bellard
/* dump memory mappings */
1867 9fa3e853 bellard
void page_dump(FILE *f)
1868 33417e70 bellard
{
1869 9fa3e853 bellard
    unsigned long start, end;
1870 9fa3e853 bellard
    int i, j, prot, prot1;
1871 9fa3e853 bellard
    PageDesc *p;
1872 33417e70 bellard
1873 9fa3e853 bellard
    fprintf(f, "%-8s %-8s %-8s %s\n",
1874 9fa3e853 bellard
            "start", "end", "size", "prot");
1875 9fa3e853 bellard
    start = -1;
1876 9fa3e853 bellard
    end = -1;
1877 9fa3e853 bellard
    prot = 0;
1878 9fa3e853 bellard
    for(i = 0; i <= L1_SIZE; i++) {
1879 9fa3e853 bellard
        if (i < L1_SIZE)
1880 9fa3e853 bellard
            p = l1_map[i];
1881 9fa3e853 bellard
        else
1882 9fa3e853 bellard
            p = NULL;
1883 9fa3e853 bellard
        for(j = 0;j < L2_SIZE; j++) {
1884 9fa3e853 bellard
            if (!p)
1885 9fa3e853 bellard
                prot1 = 0;
1886 9fa3e853 bellard
            else
1887 9fa3e853 bellard
                prot1 = p[j].flags;
1888 9fa3e853 bellard
            if (prot1 != prot) {
1889 9fa3e853 bellard
                end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
1890 9fa3e853 bellard
                if (start != -1) {
1891 9fa3e853 bellard
                    fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
1892 5fafdf24 ths
                            start, end, end - start,
1893 9fa3e853 bellard
                            prot & PAGE_READ ? 'r' : '-',
1894 9fa3e853 bellard
                            prot & PAGE_WRITE ? 'w' : '-',
1895 9fa3e853 bellard
                            prot & PAGE_EXEC ? 'x' : '-');
1896 9fa3e853 bellard
                }
1897 9fa3e853 bellard
                if (prot1 != 0)
1898 9fa3e853 bellard
                    start = end;
1899 9fa3e853 bellard
                else
1900 9fa3e853 bellard
                    start = -1;
1901 9fa3e853 bellard
                prot = prot1;
1902 9fa3e853 bellard
            }
1903 9fa3e853 bellard
            if (!p)
1904 9fa3e853 bellard
                break;
1905 9fa3e853 bellard
        }
1906 33417e70 bellard
    }
1907 33417e70 bellard
}
1908 33417e70 bellard
1909 53a5960a pbrook
int page_get_flags(target_ulong address)
1910 33417e70 bellard
{
1911 9fa3e853 bellard
    PageDesc *p;
1912 9fa3e853 bellard
1913 9fa3e853 bellard
    p = page_find(address >> TARGET_PAGE_BITS);
1914 33417e70 bellard
    if (!p)
1915 9fa3e853 bellard
        return 0;
1916 9fa3e853 bellard
    return p->flags;
1917 9fa3e853 bellard
}
1918 9fa3e853 bellard
1919 9fa3e853 bellard
/* modify the flags of a page and invalidate the code if
1920 9fa3e853 bellard
   necessary. The flag PAGE_WRITE_ORG is positionned automatically
1921 9fa3e853 bellard
   depending on PAGE_WRITE */
1922 53a5960a pbrook
void page_set_flags(target_ulong start, target_ulong end, int flags)
1923 9fa3e853 bellard
{
1924 9fa3e853 bellard
    PageDesc *p;
1925 53a5960a pbrook
    target_ulong addr;
1926 9fa3e853 bellard
1927 c8a706fe pbrook
    /* mmap_lock should already be held.  */
1928 9fa3e853 bellard
    start = start & TARGET_PAGE_MASK;
1929 9fa3e853 bellard
    end = TARGET_PAGE_ALIGN(end);
1930 9fa3e853 bellard
    if (flags & PAGE_WRITE)
1931 9fa3e853 bellard
        flags |= PAGE_WRITE_ORG;
1932 9fa3e853 bellard
    for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1933 9fa3e853 bellard
        p = page_find_alloc(addr >> TARGET_PAGE_BITS);
1934 17e2377a pbrook
        /* We may be called for host regions that are outside guest
1935 17e2377a pbrook
           address space.  */
1936 17e2377a pbrook
        if (!p)
1937 17e2377a pbrook
            return;
1938 9fa3e853 bellard
        /* if the write protection is set, then we invalidate the code
1939 9fa3e853 bellard
           inside */
1940 5fafdf24 ths
        if (!(p->flags & PAGE_WRITE) &&
1941 9fa3e853 bellard
            (flags & PAGE_WRITE) &&
1942 9fa3e853 bellard
            p->first_tb) {
1943 d720b93d bellard
            tb_invalidate_phys_page(addr, 0, NULL);
1944 9fa3e853 bellard
        }
1945 9fa3e853 bellard
        p->flags = flags;
1946 9fa3e853 bellard
    }
1947 33417e70 bellard
}
1948 33417e70 bellard
1949 3d97b40b ths
int page_check_range(target_ulong start, target_ulong len, int flags)
1950 3d97b40b ths
{
1951 3d97b40b ths
    PageDesc *p;
1952 3d97b40b ths
    target_ulong end;
1953 3d97b40b ths
    target_ulong addr;
1954 3d97b40b ths
1955 3d97b40b ths
    end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
1956 3d97b40b ths
    start = start & TARGET_PAGE_MASK;
1957 3d97b40b ths
1958 3d97b40b ths
    if( end < start )
1959 3d97b40b ths
        /* we've wrapped around */
1960 3d97b40b ths
        return -1;
1961 3d97b40b ths
    for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1962 3d97b40b ths
        p = page_find(addr >> TARGET_PAGE_BITS);
1963 3d97b40b ths
        if( !p )
1964 3d97b40b ths
            return -1;
1965 3d97b40b ths
        if( !(p->flags & PAGE_VALID) )
1966 3d97b40b ths
            return -1;
1967 3d97b40b ths
1968 dae3270c bellard
        if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
1969 3d97b40b ths
            return -1;
1970 dae3270c bellard
        if (flags & PAGE_WRITE) {
1971 dae3270c bellard
            if (!(p->flags & PAGE_WRITE_ORG))
1972 dae3270c bellard
                return -1;
1973 dae3270c bellard
            /* unprotect the page if it was put read-only because it
1974 dae3270c bellard
               contains translated code */
1975 dae3270c bellard
            if (!(p->flags & PAGE_WRITE)) {
1976 dae3270c bellard
                if (!page_unprotect(addr, 0, NULL))
1977 dae3270c bellard
                    return -1;
1978 dae3270c bellard
            }
1979 dae3270c bellard
            return 0;
1980 dae3270c bellard
        }
1981 3d97b40b ths
    }
1982 3d97b40b ths
    return 0;
1983 3d97b40b ths
}
1984 3d97b40b ths
1985 9fa3e853 bellard
/* called from signal handler: invalidate the code and unprotect the
1986 9fa3e853 bellard
   page. Return TRUE if the fault was succesfully handled. */
1987 53a5960a pbrook
int page_unprotect(target_ulong address, unsigned long pc, void *puc)
1988 9fa3e853 bellard
{
1989 9fa3e853 bellard
    unsigned int page_index, prot, pindex;
1990 9fa3e853 bellard
    PageDesc *p, *p1;
1991 53a5960a pbrook
    target_ulong host_start, host_end, addr;
1992 9fa3e853 bellard
1993 c8a706fe pbrook
    /* Technically this isn't safe inside a signal handler.  However we
1994 c8a706fe pbrook
       know this only ever happens in a synchronous SEGV handler, so in
1995 c8a706fe pbrook
       practice it seems to be ok.  */
1996 c8a706fe pbrook
    mmap_lock();
1997 c8a706fe pbrook
1998 83fb7adf bellard
    host_start = address & qemu_host_page_mask;
1999 9fa3e853 bellard
    page_index = host_start >> TARGET_PAGE_BITS;
2000 9fa3e853 bellard
    p1 = page_find(page_index);
2001 c8a706fe pbrook
    if (!p1) {
2002 c8a706fe pbrook
        mmap_unlock();
2003 9fa3e853 bellard
        return 0;
2004 c8a706fe pbrook
    }
2005 83fb7adf bellard
    host_end = host_start + qemu_host_page_size;
2006 9fa3e853 bellard
    p = p1;
2007 9fa3e853 bellard
    prot = 0;
2008 9fa3e853 bellard
    for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
2009 9fa3e853 bellard
        prot |= p->flags;
2010 9fa3e853 bellard
        p++;
2011 9fa3e853 bellard
    }
2012 9fa3e853 bellard
    /* if the page was really writable, then we change its
2013 9fa3e853 bellard
       protection back to writable */
2014 9fa3e853 bellard
    if (prot & PAGE_WRITE_ORG) {
2015 9fa3e853 bellard
        pindex = (address - host_start) >> TARGET_PAGE_BITS;
2016 9fa3e853 bellard
        if (!(p1[pindex].flags & PAGE_WRITE)) {
2017 5fafdf24 ths
            mprotect((void *)g2h(host_start), qemu_host_page_size,
2018 9fa3e853 bellard
                     (prot & PAGE_BITS) | PAGE_WRITE);
2019 9fa3e853 bellard
            p1[pindex].flags |= PAGE_WRITE;
2020 9fa3e853 bellard
            /* and since the content will be modified, we must invalidate
2021 9fa3e853 bellard
               the corresponding translated code. */
2022 d720b93d bellard
            tb_invalidate_phys_page(address, pc, puc);
2023 9fa3e853 bellard
#ifdef DEBUG_TB_CHECK
2024 9fa3e853 bellard
            tb_invalidate_check(address);
2025 9fa3e853 bellard
#endif
2026 c8a706fe pbrook
            mmap_unlock();
2027 9fa3e853 bellard
            return 1;
2028 9fa3e853 bellard
        }
2029 9fa3e853 bellard
    }
2030 c8a706fe pbrook
    mmap_unlock();
2031 9fa3e853 bellard
    return 0;
2032 9fa3e853 bellard
}
2033 9fa3e853 bellard
2034 6a00d601 bellard
static inline void tlb_set_dirty(CPUState *env,
2035 6a00d601 bellard
                                 unsigned long addr, target_ulong vaddr)
2036 1ccde1cb bellard
{
2037 1ccde1cb bellard
}
2038 9fa3e853 bellard
#endif /* defined(CONFIG_USER_ONLY) */
2039 9fa3e853 bellard
2040 e2eef170 pbrook
#if !defined(CONFIG_USER_ONLY)
2041 db7b5426 blueswir1
static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
2042 00f82b8a aurel32
                             ram_addr_t memory);
2043 00f82b8a aurel32
static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
2044 00f82b8a aurel32
                           ram_addr_t orig_memory);
2045 db7b5426 blueswir1
#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
2046 db7b5426 blueswir1
                      need_subpage)                                     \
2047 db7b5426 blueswir1
    do {                                                                \
2048 db7b5426 blueswir1
        if (addr > start_addr)                                          \
2049 db7b5426 blueswir1
            start_addr2 = 0;                                            \
2050 db7b5426 blueswir1
        else {                                                          \
2051 db7b5426 blueswir1
            start_addr2 = start_addr & ~TARGET_PAGE_MASK;               \
2052 db7b5426 blueswir1
            if (start_addr2 > 0)                                        \
2053 db7b5426 blueswir1
                need_subpage = 1;                                       \
2054 db7b5426 blueswir1
        }                                                               \
2055 db7b5426 blueswir1
                                                                        \
2056 49e9fba2 blueswir1
        if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE)        \
2057 db7b5426 blueswir1
            end_addr2 = TARGET_PAGE_SIZE - 1;                           \
2058 db7b5426 blueswir1
        else {                                                          \
2059 db7b5426 blueswir1
            end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
2060 db7b5426 blueswir1
            if (end_addr2 < TARGET_PAGE_SIZE - 1)                       \
2061 db7b5426 blueswir1
                need_subpage = 1;                                       \
2062 db7b5426 blueswir1
        }                                                               \
2063 db7b5426 blueswir1
    } while (0)
2064 db7b5426 blueswir1
2065 33417e70 bellard
/* register physical memory. 'size' must be a multiple of the target
2066 33417e70 bellard
   page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
2067 33417e70 bellard
   io memory page */
2068 5fafdf24 ths
void cpu_register_physical_memory(target_phys_addr_t start_addr,
2069 00f82b8a aurel32
                                  ram_addr_t size,
2070 00f82b8a aurel32
                                  ram_addr_t phys_offset)
2071 33417e70 bellard
{
2072 108c49b8 bellard
    target_phys_addr_t addr, end_addr;
2073 92e873b9 bellard
    PhysPageDesc *p;
2074 9d42037b bellard
    CPUState *env;
2075 00f82b8a aurel32
    ram_addr_t orig_size = size;
2076 db7b5426 blueswir1
    void *subpage;
2077 33417e70 bellard
2078 da260249 bellard
#ifdef USE_KQEMU
2079 da260249 bellard
    /* XXX: should not depend on cpu context */
2080 da260249 bellard
    env = first_cpu;
2081 da260249 bellard
    if (env->kqemu_enabled) {
2082 da260249 bellard
        kqemu_set_phys_mem(start_addr, size, phys_offset);
2083 da260249 bellard
    }
2084 da260249 bellard
#endif
2085 5fd386f6 bellard
    size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
2086 49e9fba2 blueswir1
    end_addr = start_addr + (target_phys_addr_t)size;
2087 49e9fba2 blueswir1
    for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
2088 db7b5426 blueswir1
        p = phys_page_find(addr >> TARGET_PAGE_BITS);
2089 db7b5426 blueswir1
        if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
2090 00f82b8a aurel32
            ram_addr_t orig_memory = p->phys_offset;
2091 db7b5426 blueswir1
            target_phys_addr_t start_addr2, end_addr2;
2092 db7b5426 blueswir1
            int need_subpage = 0;
2093 db7b5426 blueswir1
2094 db7b5426 blueswir1
            CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2095 db7b5426 blueswir1
                          need_subpage);
2096 4254fab8 blueswir1
            if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
2097 db7b5426 blueswir1
                if (!(orig_memory & IO_MEM_SUBPAGE)) {
2098 db7b5426 blueswir1
                    subpage = subpage_init((addr & TARGET_PAGE_MASK),
2099 db7b5426 blueswir1
                                           &p->phys_offset, orig_memory);
2100 db7b5426 blueswir1
                } else {
2101 db7b5426 blueswir1
                    subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
2102 db7b5426 blueswir1
                                            >> IO_MEM_SHIFT];
2103 db7b5426 blueswir1
                }
2104 db7b5426 blueswir1
                subpage_register(subpage, start_addr2, end_addr2, phys_offset);
2105 db7b5426 blueswir1
            } else {
2106 db7b5426 blueswir1
                p->phys_offset = phys_offset;
2107 db7b5426 blueswir1
                if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2108 db7b5426 blueswir1
                    (phys_offset & IO_MEM_ROMD))
2109 db7b5426 blueswir1
                    phys_offset += TARGET_PAGE_SIZE;
2110 db7b5426 blueswir1
            }
2111 db7b5426 blueswir1
        } else {
2112 db7b5426 blueswir1
            p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2113 db7b5426 blueswir1
            p->phys_offset = phys_offset;
2114 db7b5426 blueswir1
            if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2115 db7b5426 blueswir1
                (phys_offset & IO_MEM_ROMD))
2116 db7b5426 blueswir1
                phys_offset += TARGET_PAGE_SIZE;
2117 db7b5426 blueswir1
            else {
2118 db7b5426 blueswir1
                target_phys_addr_t start_addr2, end_addr2;
2119 db7b5426 blueswir1
                int need_subpage = 0;
2120 db7b5426 blueswir1
2121 db7b5426 blueswir1
                CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2122 db7b5426 blueswir1
                              end_addr2, need_subpage);
2123 db7b5426 blueswir1
2124 4254fab8 blueswir1
                if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
2125 db7b5426 blueswir1
                    subpage = subpage_init((addr & TARGET_PAGE_MASK),
2126 db7b5426 blueswir1
                                           &p->phys_offset, IO_MEM_UNASSIGNED);
2127 db7b5426 blueswir1
                    subpage_register(subpage, start_addr2, end_addr2,
2128 db7b5426 blueswir1
                                     phys_offset);
2129 db7b5426 blueswir1
                }
2130 db7b5426 blueswir1
            }
2131 db7b5426 blueswir1
        }
2132 33417e70 bellard
    }
2133 3b46e624 ths
2134 9d42037b bellard
    /* since each CPU stores ram addresses in its TLB cache, we must
2135 9d42037b bellard
       reset the modified entries */
2136 9d42037b bellard
    /* XXX: slow ! */
2137 9d42037b bellard
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
2138 9d42037b bellard
        tlb_flush(env, 1);
2139 9d42037b bellard
    }
2140 33417e70 bellard
}
2141 33417e70 bellard
2142 ba863458 bellard
/* XXX: temporary until new memory mapping API */
2143 00f82b8a aurel32
ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr)
2144 ba863458 bellard
{
2145 ba863458 bellard
    PhysPageDesc *p;
2146 ba863458 bellard
2147 ba863458 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2148 ba863458 bellard
    if (!p)
2149 ba863458 bellard
        return IO_MEM_UNASSIGNED;
2150 ba863458 bellard
    return p->phys_offset;
2151 ba863458 bellard
}
2152 ba863458 bellard
2153 e9a1ab19 bellard
/* XXX: better than nothing */
2154 00f82b8a aurel32
ram_addr_t qemu_ram_alloc(ram_addr_t size)
2155 e9a1ab19 bellard
{
2156 e9a1ab19 bellard
    ram_addr_t addr;
2157 7fb4fdcf balrog
    if ((phys_ram_alloc_offset + size) > phys_ram_size) {
2158 ed441467 bellard
        fprintf(stderr, "Not enough memory (requested_size = %" PRIu64 ", max memory = %" PRIu64 "\n",
2159 ed441467 bellard
                (uint64_t)size, (uint64_t)phys_ram_size);
2160 e9a1ab19 bellard
        abort();
2161 e9a1ab19 bellard
    }
2162 e9a1ab19 bellard
    addr = phys_ram_alloc_offset;
2163 e9a1ab19 bellard
    phys_ram_alloc_offset = TARGET_PAGE_ALIGN(phys_ram_alloc_offset + size);
2164 e9a1ab19 bellard
    return addr;
2165 e9a1ab19 bellard
}
2166 e9a1ab19 bellard
2167 e9a1ab19 bellard
void qemu_ram_free(ram_addr_t addr)
2168 e9a1ab19 bellard
{
2169 e9a1ab19 bellard
}
2170 e9a1ab19 bellard
2171 a4193c8a bellard
static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
2172 33417e70 bellard
{
2173 67d3b957 pbrook
#ifdef DEBUG_UNASSIGNED
2174 ab3d1727 blueswir1
    printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2175 67d3b957 pbrook
#endif
2176 b4f0a316 blueswir1
#ifdef TARGET_SPARC
2177 6c36d3fa blueswir1
    do_unassigned_access(addr, 0, 0, 0);
2178 f1ccf904 ths
#elif TARGET_CRIS
2179 f1ccf904 ths
    do_unassigned_access(addr, 0, 0, 0);
2180 b4f0a316 blueswir1
#endif
2181 33417e70 bellard
    return 0;
2182 33417e70 bellard
}
2183 33417e70 bellard
2184 a4193c8a bellard
static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
2185 33417e70 bellard
{
2186 67d3b957 pbrook
#ifdef DEBUG_UNASSIGNED
2187 ab3d1727 blueswir1
    printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2188 67d3b957 pbrook
#endif
2189 b4f0a316 blueswir1
#ifdef TARGET_SPARC
2190 6c36d3fa blueswir1
    do_unassigned_access(addr, 1, 0, 0);
2191 f1ccf904 ths
#elif TARGET_CRIS
2192 f1ccf904 ths
    do_unassigned_access(addr, 1, 0, 0);
2193 b4f0a316 blueswir1
#endif
2194 33417e70 bellard
}
2195 33417e70 bellard
2196 33417e70 bellard
static CPUReadMemoryFunc *unassigned_mem_read[3] = {
2197 33417e70 bellard
    unassigned_mem_readb,
2198 33417e70 bellard
    unassigned_mem_readb,
2199 33417e70 bellard
    unassigned_mem_readb,
2200 33417e70 bellard
};
2201 33417e70 bellard
2202 33417e70 bellard
static CPUWriteMemoryFunc *unassigned_mem_write[3] = {
2203 33417e70 bellard
    unassigned_mem_writeb,
2204 33417e70 bellard
    unassigned_mem_writeb,
2205 33417e70 bellard
    unassigned_mem_writeb,
2206 33417e70 bellard
};
2207 33417e70 bellard
2208 0f459d16 pbrook
static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr,
2209 0f459d16 pbrook
                                uint32_t val)
2210 9fa3e853 bellard
{
2211 3a7d929e bellard
    int dirty_flags;
2212 3a7d929e bellard
    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2213 3a7d929e bellard
    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2214 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
2215 3a7d929e bellard
        tb_invalidate_phys_page_fast(ram_addr, 1);
2216 3a7d929e bellard
        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2217 9fa3e853 bellard
#endif
2218 3a7d929e bellard
    }
2219 0f459d16 pbrook
    stb_p(phys_ram_base + ram_addr, val);
2220 f32fc648 bellard
#ifdef USE_KQEMU
2221 f32fc648 bellard
    if (cpu_single_env->kqemu_enabled &&
2222 f32fc648 bellard
        (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2223 f32fc648 bellard
        kqemu_modify_page(cpu_single_env, ram_addr);
2224 f32fc648 bellard
#endif
2225 f23db169 bellard
    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2226 f23db169 bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2227 f23db169 bellard
    /* we remove the notdirty callback only if the code has been
2228 f23db169 bellard
       flushed */
2229 f23db169 bellard
    if (dirty_flags == 0xff)
2230 0f459d16 pbrook
        tlb_set_dirty(cpu_single_env, cpu_single_env->mem_write_vaddr);
2231 9fa3e853 bellard
}
2232 9fa3e853 bellard
2233 0f459d16 pbrook
static void notdirty_mem_writew(void *opaque, target_phys_addr_t ram_addr,
2234 0f459d16 pbrook
                                uint32_t val)
2235 9fa3e853 bellard
{
2236 3a7d929e bellard
    int dirty_flags;
2237 3a7d929e bellard
    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2238 3a7d929e bellard
    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2239 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
2240 3a7d929e bellard
        tb_invalidate_phys_page_fast(ram_addr, 2);
2241 3a7d929e bellard
        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2242 9fa3e853 bellard
#endif
2243 3a7d929e bellard
    }
2244 0f459d16 pbrook
    stw_p(phys_ram_base + ram_addr, val);
2245 f32fc648 bellard
#ifdef USE_KQEMU
2246 f32fc648 bellard
    if (cpu_single_env->kqemu_enabled &&
2247 f32fc648 bellard
        (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2248 f32fc648 bellard
        kqemu_modify_page(cpu_single_env, ram_addr);
2249 f32fc648 bellard
#endif
2250 f23db169 bellard
    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2251 f23db169 bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2252 f23db169 bellard
    /* we remove the notdirty callback only if the code has been
2253 f23db169 bellard
       flushed */
2254 f23db169 bellard
    if (dirty_flags == 0xff)
2255 0f459d16 pbrook
        tlb_set_dirty(cpu_single_env, cpu_single_env->mem_write_vaddr);
2256 9fa3e853 bellard
}
2257 9fa3e853 bellard
2258 0f459d16 pbrook
static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr,
2259 0f459d16 pbrook
                                uint32_t val)
2260 9fa3e853 bellard
{
2261 3a7d929e bellard
    int dirty_flags;
2262 3a7d929e bellard
    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2263 3a7d929e bellard
    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2264 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
2265 3a7d929e bellard
        tb_invalidate_phys_page_fast(ram_addr, 4);
2266 3a7d929e bellard
        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2267 9fa3e853 bellard
#endif
2268 3a7d929e bellard
    }
2269 0f459d16 pbrook
    stl_p(phys_ram_base + ram_addr, val);
2270 f32fc648 bellard
#ifdef USE_KQEMU
2271 f32fc648 bellard
    if (cpu_single_env->kqemu_enabled &&
2272 f32fc648 bellard
        (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2273 f32fc648 bellard
        kqemu_modify_page(cpu_single_env, ram_addr);
2274 f32fc648 bellard
#endif
2275 f23db169 bellard
    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2276 f23db169 bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2277 f23db169 bellard
    /* we remove the notdirty callback only if the code has been
2278 f23db169 bellard
       flushed */
2279 f23db169 bellard
    if (dirty_flags == 0xff)
2280 0f459d16 pbrook
        tlb_set_dirty(cpu_single_env, cpu_single_env->mem_write_vaddr);
2281 9fa3e853 bellard
}
2282 9fa3e853 bellard
2283 3a7d929e bellard
static CPUReadMemoryFunc *error_mem_read[3] = {
2284 9fa3e853 bellard
    NULL, /* never used */
2285 9fa3e853 bellard
    NULL, /* never used */
2286 9fa3e853 bellard
    NULL, /* never used */
2287 9fa3e853 bellard
};
2288 9fa3e853 bellard
2289 1ccde1cb bellard
static CPUWriteMemoryFunc *notdirty_mem_write[3] = {
2290 1ccde1cb bellard
    notdirty_mem_writeb,
2291 1ccde1cb bellard
    notdirty_mem_writew,
2292 1ccde1cb bellard
    notdirty_mem_writel,
2293 1ccde1cb bellard
};
2294 1ccde1cb bellard
2295 0f459d16 pbrook
/* Generate a debug exception if a watchpoint has been hit.  */
2296 0f459d16 pbrook
static void check_watchpoint(int offset, int flags)
2297 0f459d16 pbrook
{
2298 0f459d16 pbrook
    CPUState *env = cpu_single_env;
2299 0f459d16 pbrook
    target_ulong vaddr;
2300 0f459d16 pbrook
    int i;
2301 0f459d16 pbrook
2302 0f459d16 pbrook
    vaddr = (env->mem_write_vaddr & TARGET_PAGE_MASK) + offset;
2303 0f459d16 pbrook
    for (i = 0; i < env->nb_watchpoints; i++) {
2304 0f459d16 pbrook
        if (vaddr == env->watchpoint[i].vaddr
2305 0f459d16 pbrook
                && (env->watchpoint[i].type & flags)) {
2306 0f459d16 pbrook
            env->watchpoint_hit = i + 1;
2307 0f459d16 pbrook
            cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2308 0f459d16 pbrook
            break;
2309 0f459d16 pbrook
        }
2310 0f459d16 pbrook
    }
2311 0f459d16 pbrook
}
2312 0f459d16 pbrook
2313 6658ffb8 pbrook
/* Watchpoint access routines.  Watchpoints are inserted using TLB tricks,
2314 6658ffb8 pbrook
   so these check for a hit then pass through to the normal out-of-line
2315 6658ffb8 pbrook
   phys routines.  */
2316 6658ffb8 pbrook
static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
2317 6658ffb8 pbrook
{
2318 0f459d16 pbrook
    check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ);
2319 6658ffb8 pbrook
    return ldub_phys(addr);
2320 6658ffb8 pbrook
}
2321 6658ffb8 pbrook
2322 6658ffb8 pbrook
static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
2323 6658ffb8 pbrook
{
2324 0f459d16 pbrook
    check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ);
2325 6658ffb8 pbrook
    return lduw_phys(addr);
2326 6658ffb8 pbrook
}
2327 6658ffb8 pbrook
2328 6658ffb8 pbrook
static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
2329 6658ffb8 pbrook
{
2330 0f459d16 pbrook
    check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ);
2331 6658ffb8 pbrook
    return ldl_phys(addr);
2332 6658ffb8 pbrook
}
2333 6658ffb8 pbrook
2334 6658ffb8 pbrook
static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
2335 6658ffb8 pbrook
                             uint32_t val)
2336 6658ffb8 pbrook
{
2337 0f459d16 pbrook
    check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE);
2338 6658ffb8 pbrook
    stb_phys(addr, val);
2339 6658ffb8 pbrook
}
2340 6658ffb8 pbrook
2341 6658ffb8 pbrook
static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
2342 6658ffb8 pbrook
                             uint32_t val)
2343 6658ffb8 pbrook
{
2344 0f459d16 pbrook
    check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE);
2345 6658ffb8 pbrook
    stw_phys(addr, val);
2346 6658ffb8 pbrook
}
2347 6658ffb8 pbrook
2348 6658ffb8 pbrook
static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
2349 6658ffb8 pbrook
                             uint32_t val)
2350 6658ffb8 pbrook
{
2351 0f459d16 pbrook
    check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE);
2352 6658ffb8 pbrook
    stl_phys(addr, val);
2353 6658ffb8 pbrook
}
2354 6658ffb8 pbrook
2355 6658ffb8 pbrook
static CPUReadMemoryFunc *watch_mem_read[3] = {
2356 6658ffb8 pbrook
    watch_mem_readb,
2357 6658ffb8 pbrook
    watch_mem_readw,
2358 6658ffb8 pbrook
    watch_mem_readl,
2359 6658ffb8 pbrook
};
2360 6658ffb8 pbrook
2361 6658ffb8 pbrook
static CPUWriteMemoryFunc *watch_mem_write[3] = {
2362 6658ffb8 pbrook
    watch_mem_writeb,
2363 6658ffb8 pbrook
    watch_mem_writew,
2364 6658ffb8 pbrook
    watch_mem_writel,
2365 6658ffb8 pbrook
};
2366 6658ffb8 pbrook
2367 db7b5426 blueswir1
static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr,
2368 db7b5426 blueswir1
                                 unsigned int len)
2369 db7b5426 blueswir1
{
2370 db7b5426 blueswir1
    uint32_t ret;
2371 db7b5426 blueswir1
    unsigned int idx;
2372 db7b5426 blueswir1
2373 db7b5426 blueswir1
    idx = SUBPAGE_IDX(addr - mmio->base);
2374 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2375 db7b5426 blueswir1
    printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
2376 db7b5426 blueswir1
           mmio, len, addr, idx);
2377 db7b5426 blueswir1
#endif
2378 3ee89922 blueswir1
    ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len], addr);
2379 db7b5426 blueswir1
2380 db7b5426 blueswir1
    return ret;
2381 db7b5426 blueswir1
}
2382 db7b5426 blueswir1
2383 db7b5426 blueswir1
static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
2384 db7b5426 blueswir1
                              uint32_t value, unsigned int len)
2385 db7b5426 blueswir1
{
2386 db7b5426 blueswir1
    unsigned int idx;
2387 db7b5426 blueswir1
2388 db7b5426 blueswir1
    idx = SUBPAGE_IDX(addr - mmio->base);
2389 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2390 db7b5426 blueswir1
    printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
2391 db7b5426 blueswir1
           mmio, len, addr, idx, value);
2392 db7b5426 blueswir1
#endif
2393 3ee89922 blueswir1
    (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len], addr, value);
2394 db7b5426 blueswir1
}
2395 db7b5426 blueswir1
2396 db7b5426 blueswir1
static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
2397 db7b5426 blueswir1
{
2398 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2399 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2400 db7b5426 blueswir1
#endif
2401 db7b5426 blueswir1
2402 db7b5426 blueswir1
    return subpage_readlen(opaque, addr, 0);
2403 db7b5426 blueswir1
}
2404 db7b5426 blueswir1
2405 db7b5426 blueswir1
static void subpage_writeb (void *opaque, target_phys_addr_t addr,
2406 db7b5426 blueswir1
                            uint32_t value)
2407 db7b5426 blueswir1
{
2408 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2409 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2410 db7b5426 blueswir1
#endif
2411 db7b5426 blueswir1
    subpage_writelen(opaque, addr, value, 0);
2412 db7b5426 blueswir1
}
2413 db7b5426 blueswir1
2414 db7b5426 blueswir1
static uint32_t subpage_readw (void *opaque, target_phys_addr_t addr)
2415 db7b5426 blueswir1
{
2416 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2417 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2418 db7b5426 blueswir1
#endif
2419 db7b5426 blueswir1
2420 db7b5426 blueswir1
    return subpage_readlen(opaque, addr, 1);
2421 db7b5426 blueswir1
}
2422 db7b5426 blueswir1
2423 db7b5426 blueswir1
static void subpage_writew (void *opaque, target_phys_addr_t addr,
2424 db7b5426 blueswir1
                            uint32_t value)
2425 db7b5426 blueswir1
{
2426 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2427 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2428 db7b5426 blueswir1
#endif
2429 db7b5426 blueswir1
    subpage_writelen(opaque, addr, value, 1);
2430 db7b5426 blueswir1
}
2431 db7b5426 blueswir1
2432 db7b5426 blueswir1
static uint32_t subpage_readl (void *opaque, target_phys_addr_t addr)
2433 db7b5426 blueswir1
{
2434 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2435 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2436 db7b5426 blueswir1
#endif
2437 db7b5426 blueswir1
2438 db7b5426 blueswir1
    return subpage_readlen(opaque, addr, 2);
2439 db7b5426 blueswir1
}
2440 db7b5426 blueswir1
2441 db7b5426 blueswir1
static void subpage_writel (void *opaque,
2442 db7b5426 blueswir1
                         target_phys_addr_t addr, uint32_t value)
2443 db7b5426 blueswir1
{
2444 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2445 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2446 db7b5426 blueswir1
#endif
2447 db7b5426 blueswir1
    subpage_writelen(opaque, addr, value, 2);
2448 db7b5426 blueswir1
}
2449 db7b5426 blueswir1
2450 db7b5426 blueswir1
static CPUReadMemoryFunc *subpage_read[] = {
2451 db7b5426 blueswir1
    &subpage_readb,
2452 db7b5426 blueswir1
    &subpage_readw,
2453 db7b5426 blueswir1
    &subpage_readl,
2454 db7b5426 blueswir1
};
2455 db7b5426 blueswir1
2456 db7b5426 blueswir1
static CPUWriteMemoryFunc *subpage_write[] = {
2457 db7b5426 blueswir1
    &subpage_writeb,
2458 db7b5426 blueswir1
    &subpage_writew,
2459 db7b5426 blueswir1
    &subpage_writel,
2460 db7b5426 blueswir1
};
2461 db7b5426 blueswir1
2462 db7b5426 blueswir1
static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
2463 00f82b8a aurel32
                             ram_addr_t memory)
2464 db7b5426 blueswir1
{
2465 db7b5426 blueswir1
    int idx, eidx;
2466 4254fab8 blueswir1
    unsigned int i;
2467 db7b5426 blueswir1
2468 db7b5426 blueswir1
    if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
2469 db7b5426 blueswir1
        return -1;
2470 db7b5426 blueswir1
    idx = SUBPAGE_IDX(start);
2471 db7b5426 blueswir1
    eidx = SUBPAGE_IDX(end);
2472 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2473 db7b5426 blueswir1
    printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %d\n", __func__,
2474 db7b5426 blueswir1
           mmio, start, end, idx, eidx, memory);
2475 db7b5426 blueswir1
#endif
2476 db7b5426 blueswir1
    memory >>= IO_MEM_SHIFT;
2477 db7b5426 blueswir1
    for (; idx <= eidx; idx++) {
2478 4254fab8 blueswir1
        for (i = 0; i < 4; i++) {
2479 3ee89922 blueswir1
            if (io_mem_read[memory][i]) {
2480 3ee89922 blueswir1
                mmio->mem_read[idx][i] = &io_mem_read[memory][i];
2481 3ee89922 blueswir1
                mmio->opaque[idx][0][i] = io_mem_opaque[memory];
2482 3ee89922 blueswir1
            }
2483 3ee89922 blueswir1
            if (io_mem_write[memory][i]) {
2484 3ee89922 blueswir1
                mmio->mem_write[idx][i] = &io_mem_write[memory][i];
2485 3ee89922 blueswir1
                mmio->opaque[idx][1][i] = io_mem_opaque[memory];
2486 3ee89922 blueswir1
            }
2487 4254fab8 blueswir1
        }
2488 db7b5426 blueswir1
    }
2489 db7b5426 blueswir1
2490 db7b5426 blueswir1
    return 0;
2491 db7b5426 blueswir1
}
2492 db7b5426 blueswir1
2493 00f82b8a aurel32
static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
2494 00f82b8a aurel32
                           ram_addr_t orig_memory)
2495 db7b5426 blueswir1
{
2496 db7b5426 blueswir1
    subpage_t *mmio;
2497 db7b5426 blueswir1
    int subpage_memory;
2498 db7b5426 blueswir1
2499 db7b5426 blueswir1
    mmio = qemu_mallocz(sizeof(subpage_t));
2500 db7b5426 blueswir1
    if (mmio != NULL) {
2501 db7b5426 blueswir1
        mmio->base = base;
2502 db7b5426 blueswir1
        subpage_memory = cpu_register_io_memory(0, subpage_read, subpage_write, mmio);
2503 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2504 db7b5426 blueswir1
        printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
2505 db7b5426 blueswir1
               mmio, base, TARGET_PAGE_SIZE, subpage_memory);
2506 db7b5426 blueswir1
#endif
2507 db7b5426 blueswir1
        *phys = subpage_memory | IO_MEM_SUBPAGE;
2508 db7b5426 blueswir1
        subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory);
2509 db7b5426 blueswir1
    }
2510 db7b5426 blueswir1
2511 db7b5426 blueswir1
    return mmio;
2512 db7b5426 blueswir1
}
2513 db7b5426 blueswir1
2514 33417e70 bellard
static void io_mem_init(void)
2515 33417e70 bellard
{
2516 3a7d929e bellard
    cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read, unassigned_mem_write, NULL);
2517 a4193c8a bellard
    cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write, NULL);
2518 3a7d929e bellard
    cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read, notdirty_mem_write, NULL);
2519 1ccde1cb bellard
    io_mem_nb = 5;
2520 1ccde1cb bellard
2521 0f459d16 pbrook
    io_mem_watch = cpu_register_io_memory(0, watch_mem_read,
2522 6658ffb8 pbrook
                                          watch_mem_write, NULL);
2523 1ccde1cb bellard
    /* alloc dirty bits array */
2524 0a962c02 bellard
    phys_ram_dirty = qemu_vmalloc(phys_ram_size >> TARGET_PAGE_BITS);
2525 3a7d929e bellard
    memset(phys_ram_dirty, 0xff, phys_ram_size >> TARGET_PAGE_BITS);
2526 33417e70 bellard
}
2527 33417e70 bellard
2528 33417e70 bellard
/* mem_read and mem_write are arrays of functions containing the
2529 33417e70 bellard
   function to access byte (index 0), word (index 1) and dword (index
2530 3ee89922 blueswir1
   2). Functions can be omitted with a NULL function pointer. The
2531 3ee89922 blueswir1
   registered functions may be modified dynamically later.
2532 3ee89922 blueswir1
   If io_index is non zero, the corresponding io zone is
2533 4254fab8 blueswir1
   modified. If it is zero, a new io zone is allocated. The return
2534 4254fab8 blueswir1
   value can be used with cpu_register_physical_memory(). (-1) is
2535 4254fab8 blueswir1
   returned if error. */
2536 33417e70 bellard
int cpu_register_io_memory(int io_index,
2537 33417e70 bellard
                           CPUReadMemoryFunc **mem_read,
2538 a4193c8a bellard
                           CPUWriteMemoryFunc **mem_write,
2539 a4193c8a bellard
                           void *opaque)
2540 33417e70 bellard
{
2541 4254fab8 blueswir1
    int i, subwidth = 0;
2542 33417e70 bellard
2543 33417e70 bellard
    if (io_index <= 0) {
2544 b5ff1b31 bellard
        if (io_mem_nb >= IO_MEM_NB_ENTRIES)
2545 33417e70 bellard
            return -1;
2546 33417e70 bellard
        io_index = io_mem_nb++;
2547 33417e70 bellard
    } else {
2548 33417e70 bellard
        if (io_index >= IO_MEM_NB_ENTRIES)
2549 33417e70 bellard
            return -1;
2550 33417e70 bellard
    }
2551 b5ff1b31 bellard
2552 33417e70 bellard
    for(i = 0;i < 3; i++) {
2553 4254fab8 blueswir1
        if (!mem_read[i] || !mem_write[i])
2554 4254fab8 blueswir1
            subwidth = IO_MEM_SUBWIDTH;
2555 33417e70 bellard
        io_mem_read[io_index][i] = mem_read[i];
2556 33417e70 bellard
        io_mem_write[io_index][i] = mem_write[i];
2557 33417e70 bellard
    }
2558 a4193c8a bellard
    io_mem_opaque[io_index] = opaque;
2559 4254fab8 blueswir1
    return (io_index << IO_MEM_SHIFT) | subwidth;
2560 33417e70 bellard
}
2561 61382a50 bellard
2562 8926b517 bellard
CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index)
2563 8926b517 bellard
{
2564 8926b517 bellard
    return io_mem_write[io_index >> IO_MEM_SHIFT];
2565 8926b517 bellard
}
2566 8926b517 bellard
2567 8926b517 bellard
CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index)
2568 8926b517 bellard
{
2569 8926b517 bellard
    return io_mem_read[io_index >> IO_MEM_SHIFT];
2570 8926b517 bellard
}
2571 8926b517 bellard
2572 e2eef170 pbrook
#endif /* !defined(CONFIG_USER_ONLY) */
2573 e2eef170 pbrook
2574 13eb76e0 bellard
/* physical memory access (slow version, mainly for debug) */
2575 13eb76e0 bellard
#if defined(CONFIG_USER_ONLY)
2576 5fafdf24 ths
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
2577 13eb76e0 bellard
                            int len, int is_write)
2578 13eb76e0 bellard
{
2579 13eb76e0 bellard
    int l, flags;
2580 13eb76e0 bellard
    target_ulong page;
2581 53a5960a pbrook
    void * p;
2582 13eb76e0 bellard
2583 13eb76e0 bellard
    while (len > 0) {
2584 13eb76e0 bellard
        page = addr & TARGET_PAGE_MASK;
2585 13eb76e0 bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
2586 13eb76e0 bellard
        if (l > len)
2587 13eb76e0 bellard
            l = len;
2588 13eb76e0 bellard
        flags = page_get_flags(page);
2589 13eb76e0 bellard
        if (!(flags & PAGE_VALID))
2590 13eb76e0 bellard
            return;
2591 13eb76e0 bellard
        if (is_write) {
2592 13eb76e0 bellard
            if (!(flags & PAGE_WRITE))
2593 13eb76e0 bellard
                return;
2594 579a97f7 bellard
            /* XXX: this code should not depend on lock_user */
2595 72fb7daa aurel32
            if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
2596 579a97f7 bellard
                /* FIXME - should this return an error rather than just fail? */
2597 579a97f7 bellard
                return;
2598 72fb7daa aurel32
            memcpy(p, buf, l);
2599 72fb7daa aurel32
            unlock_user(p, addr, l);
2600 13eb76e0 bellard
        } else {
2601 13eb76e0 bellard
            if (!(flags & PAGE_READ))
2602 13eb76e0 bellard
                return;
2603 579a97f7 bellard
            /* XXX: this code should not depend on lock_user */
2604 72fb7daa aurel32
            if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
2605 579a97f7 bellard
                /* FIXME - should this return an error rather than just fail? */
2606 579a97f7 bellard
                return;
2607 72fb7daa aurel32
            memcpy(buf, p, l);
2608 5b257578 aurel32
            unlock_user(p, addr, 0);
2609 13eb76e0 bellard
        }
2610 13eb76e0 bellard
        len -= l;
2611 13eb76e0 bellard
        buf += l;
2612 13eb76e0 bellard
        addr += l;
2613 13eb76e0 bellard
    }
2614 13eb76e0 bellard
}
2615 8df1cd07 bellard
2616 13eb76e0 bellard
#else
2617 5fafdf24 ths
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
2618 13eb76e0 bellard
                            int len, int is_write)
2619 13eb76e0 bellard
{
2620 13eb76e0 bellard
    int l, io_index;
2621 13eb76e0 bellard
    uint8_t *ptr;
2622 13eb76e0 bellard
    uint32_t val;
2623 2e12669a bellard
    target_phys_addr_t page;
2624 2e12669a bellard
    unsigned long pd;
2625 92e873b9 bellard
    PhysPageDesc *p;
2626 3b46e624 ths
2627 13eb76e0 bellard
    while (len > 0) {
2628 13eb76e0 bellard
        page = addr & TARGET_PAGE_MASK;
2629 13eb76e0 bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
2630 13eb76e0 bellard
        if (l > len)
2631 13eb76e0 bellard
            l = len;
2632 92e873b9 bellard
        p = phys_page_find(page >> TARGET_PAGE_BITS);
2633 13eb76e0 bellard
        if (!p) {
2634 13eb76e0 bellard
            pd = IO_MEM_UNASSIGNED;
2635 13eb76e0 bellard
        } else {
2636 13eb76e0 bellard
            pd = p->phys_offset;
2637 13eb76e0 bellard
        }
2638 3b46e624 ths
2639 13eb76e0 bellard
        if (is_write) {
2640 3a7d929e bellard
            if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2641 13eb76e0 bellard
                io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2642 6a00d601 bellard
                /* XXX: could force cpu_single_env to NULL to avoid
2643 6a00d601 bellard
                   potential bugs */
2644 13eb76e0 bellard
                if (l >= 4 && ((addr & 3) == 0)) {
2645 1c213d19 bellard
                    /* 32 bit write access */
2646 c27004ec bellard
                    val = ldl_p(buf);
2647 a4193c8a bellard
                    io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2648 13eb76e0 bellard
                    l = 4;
2649 13eb76e0 bellard
                } else if (l >= 2 && ((addr & 1) == 0)) {
2650 1c213d19 bellard
                    /* 16 bit write access */
2651 c27004ec bellard
                    val = lduw_p(buf);
2652 a4193c8a bellard
                    io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
2653 13eb76e0 bellard
                    l = 2;
2654 13eb76e0 bellard
                } else {
2655 1c213d19 bellard
                    /* 8 bit write access */
2656 c27004ec bellard
                    val = ldub_p(buf);
2657 a4193c8a bellard
                    io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val);
2658 13eb76e0 bellard
                    l = 1;
2659 13eb76e0 bellard
                }
2660 13eb76e0 bellard
            } else {
2661 b448f2f3 bellard
                unsigned long addr1;
2662 b448f2f3 bellard
                addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2663 13eb76e0 bellard
                /* RAM case */
2664 b448f2f3 bellard
                ptr = phys_ram_base + addr1;
2665 13eb76e0 bellard
                memcpy(ptr, buf, l);
2666 3a7d929e bellard
                if (!cpu_physical_memory_is_dirty(addr1)) {
2667 3a7d929e bellard
                    /* invalidate code */
2668 3a7d929e bellard
                    tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
2669 3a7d929e bellard
                    /* set dirty bit */
2670 5fafdf24 ths
                    phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
2671 f23db169 bellard
                        (0xff & ~CODE_DIRTY_FLAG);
2672 3a7d929e bellard
                }
2673 13eb76e0 bellard
            }
2674 13eb76e0 bellard
        } else {
2675 5fafdf24 ths
            if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
2676 2a4188a3 bellard
                !(pd & IO_MEM_ROMD)) {
2677 13eb76e0 bellard
                /* I/O case */
2678 13eb76e0 bellard
                io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2679 13eb76e0 bellard
                if (l >= 4 && ((addr & 3) == 0)) {
2680 13eb76e0 bellard
                    /* 32 bit read access */
2681 a4193c8a bellard
                    val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2682 c27004ec bellard
                    stl_p(buf, val);
2683 13eb76e0 bellard
                    l = 4;
2684 13eb76e0 bellard
                } else if (l >= 2 && ((addr & 1) == 0)) {
2685 13eb76e0 bellard
                    /* 16 bit read access */
2686 a4193c8a bellard
                    val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
2687 c27004ec bellard
                    stw_p(buf, val);
2688 13eb76e0 bellard
                    l = 2;
2689 13eb76e0 bellard
                } else {
2690 1c213d19 bellard
                    /* 8 bit read access */
2691 a4193c8a bellard
                    val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr);
2692 c27004ec bellard
                    stb_p(buf, val);
2693 13eb76e0 bellard
                    l = 1;
2694 13eb76e0 bellard
                }
2695 13eb76e0 bellard
            } else {
2696 13eb76e0 bellard
                /* RAM case */
2697 5fafdf24 ths
                ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
2698 13eb76e0 bellard
                    (addr & ~TARGET_PAGE_MASK);
2699 13eb76e0 bellard
                memcpy(buf, ptr, l);
2700 13eb76e0 bellard
            }
2701 13eb76e0 bellard
        }
2702 13eb76e0 bellard
        len -= l;
2703 13eb76e0 bellard
        buf += l;
2704 13eb76e0 bellard
        addr += l;
2705 13eb76e0 bellard
    }
2706 13eb76e0 bellard
}
2707 8df1cd07 bellard
2708 d0ecd2aa bellard
/* used for ROM loading : can write in RAM and ROM */
2709 5fafdf24 ths
void cpu_physical_memory_write_rom(target_phys_addr_t addr,
2710 d0ecd2aa bellard
                                   const uint8_t *buf, int len)
2711 d0ecd2aa bellard
{
2712 d0ecd2aa bellard
    int l;
2713 d0ecd2aa bellard
    uint8_t *ptr;
2714 d0ecd2aa bellard
    target_phys_addr_t page;
2715 d0ecd2aa bellard
    unsigned long pd;
2716 d0ecd2aa bellard
    PhysPageDesc *p;
2717 3b46e624 ths
2718 d0ecd2aa bellard
    while (len > 0) {
2719 d0ecd2aa bellard
        page = addr & TARGET_PAGE_MASK;
2720 d0ecd2aa bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
2721 d0ecd2aa bellard
        if (l > len)
2722 d0ecd2aa bellard
            l = len;
2723 d0ecd2aa bellard
        p = phys_page_find(page >> TARGET_PAGE_BITS);
2724 d0ecd2aa bellard
        if (!p) {
2725 d0ecd2aa bellard
            pd = IO_MEM_UNASSIGNED;
2726 d0ecd2aa bellard
        } else {
2727 d0ecd2aa bellard
            pd = p->phys_offset;
2728 d0ecd2aa bellard
        }
2729 3b46e624 ths
2730 d0ecd2aa bellard
        if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
2731 2a4188a3 bellard
            (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
2732 2a4188a3 bellard
            !(pd & IO_MEM_ROMD)) {
2733 d0ecd2aa bellard
            /* do nothing */
2734 d0ecd2aa bellard
        } else {
2735 d0ecd2aa bellard
            unsigned long addr1;
2736 d0ecd2aa bellard
            addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2737 d0ecd2aa bellard
            /* ROM/RAM case */
2738 d0ecd2aa bellard
            ptr = phys_ram_base + addr1;
2739 d0ecd2aa bellard
            memcpy(ptr, buf, l);
2740 d0ecd2aa bellard
        }
2741 d0ecd2aa bellard
        len -= l;
2742 d0ecd2aa bellard
        buf += l;
2743 d0ecd2aa bellard
        addr += l;
2744 d0ecd2aa bellard
    }
2745 d0ecd2aa bellard
}
2746 d0ecd2aa bellard
2747 d0ecd2aa bellard
2748 8df1cd07 bellard
/* warning: addr must be aligned */
2749 8df1cd07 bellard
uint32_t ldl_phys(target_phys_addr_t addr)
2750 8df1cd07 bellard
{
2751 8df1cd07 bellard
    int io_index;
2752 8df1cd07 bellard
    uint8_t *ptr;
2753 8df1cd07 bellard
    uint32_t val;
2754 8df1cd07 bellard
    unsigned long pd;
2755 8df1cd07 bellard
    PhysPageDesc *p;
2756 8df1cd07 bellard
2757 8df1cd07 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2758 8df1cd07 bellard
    if (!p) {
2759 8df1cd07 bellard
        pd = IO_MEM_UNASSIGNED;
2760 8df1cd07 bellard
    } else {
2761 8df1cd07 bellard
        pd = p->phys_offset;
2762 8df1cd07 bellard
    }
2763 3b46e624 ths
2764 5fafdf24 ths
    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
2765 2a4188a3 bellard
        !(pd & IO_MEM_ROMD)) {
2766 8df1cd07 bellard
        /* I/O case */
2767 8df1cd07 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2768 8df1cd07 bellard
        val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2769 8df1cd07 bellard
    } else {
2770 8df1cd07 bellard
        /* RAM case */
2771 5fafdf24 ths
        ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
2772 8df1cd07 bellard
            (addr & ~TARGET_PAGE_MASK);
2773 8df1cd07 bellard
        val = ldl_p(ptr);
2774 8df1cd07 bellard
    }
2775 8df1cd07 bellard
    return val;
2776 8df1cd07 bellard
}
2777 8df1cd07 bellard
2778 84b7b8e7 bellard
/* warning: addr must be aligned */
2779 84b7b8e7 bellard
uint64_t ldq_phys(target_phys_addr_t addr)
2780 84b7b8e7 bellard
{
2781 84b7b8e7 bellard
    int io_index;
2782 84b7b8e7 bellard
    uint8_t *ptr;
2783 84b7b8e7 bellard
    uint64_t val;
2784 84b7b8e7 bellard
    unsigned long pd;
2785 84b7b8e7 bellard
    PhysPageDesc *p;
2786 84b7b8e7 bellard
2787 84b7b8e7 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2788 84b7b8e7 bellard
    if (!p) {
2789 84b7b8e7 bellard
        pd = IO_MEM_UNASSIGNED;
2790 84b7b8e7 bellard
    } else {
2791 84b7b8e7 bellard
        pd = p->phys_offset;
2792 84b7b8e7 bellard
    }
2793 3b46e624 ths
2794 2a4188a3 bellard
    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
2795 2a4188a3 bellard
        !(pd & IO_MEM_ROMD)) {
2796 84b7b8e7 bellard
        /* I/O case */
2797 84b7b8e7 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2798 84b7b8e7 bellard
#ifdef TARGET_WORDS_BIGENDIAN
2799 84b7b8e7 bellard
        val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
2800 84b7b8e7 bellard
        val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
2801 84b7b8e7 bellard
#else
2802 84b7b8e7 bellard
        val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2803 84b7b8e7 bellard
        val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
2804 84b7b8e7 bellard
#endif
2805 84b7b8e7 bellard
    } else {
2806 84b7b8e7 bellard
        /* RAM case */
2807 5fafdf24 ths
        ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
2808 84b7b8e7 bellard
            (addr & ~TARGET_PAGE_MASK);
2809 84b7b8e7 bellard
        val = ldq_p(ptr);
2810 84b7b8e7 bellard
    }
2811 84b7b8e7 bellard
    return val;
2812 84b7b8e7 bellard
}
2813 84b7b8e7 bellard
2814 aab33094 bellard
/* XXX: optimize */
2815 aab33094 bellard
uint32_t ldub_phys(target_phys_addr_t addr)
2816 aab33094 bellard
{
2817 aab33094 bellard
    uint8_t val;
2818 aab33094 bellard
    cpu_physical_memory_read(addr, &val, 1);
2819 aab33094 bellard
    return val;
2820 aab33094 bellard
}
2821 aab33094 bellard
2822 aab33094 bellard
/* XXX: optimize */
2823 aab33094 bellard
uint32_t lduw_phys(target_phys_addr_t addr)
2824 aab33094 bellard
{
2825 aab33094 bellard
    uint16_t val;
2826 aab33094 bellard
    cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
2827 aab33094 bellard
    return tswap16(val);
2828 aab33094 bellard
}
2829 aab33094 bellard
2830 8df1cd07 bellard
/* warning: addr must be aligned. The ram page is not masked as dirty
2831 8df1cd07 bellard
   and the code inside is not invalidated. It is useful if the dirty
2832 8df1cd07 bellard
   bits are used to track modified PTEs */
2833 8df1cd07 bellard
void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
2834 8df1cd07 bellard
{
2835 8df1cd07 bellard
    int io_index;
2836 8df1cd07 bellard
    uint8_t *ptr;
2837 8df1cd07 bellard
    unsigned long pd;
2838 8df1cd07 bellard
    PhysPageDesc *p;
2839 8df1cd07 bellard
2840 8df1cd07 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2841 8df1cd07 bellard
    if (!p) {
2842 8df1cd07 bellard
        pd = IO_MEM_UNASSIGNED;
2843 8df1cd07 bellard
    } else {
2844 8df1cd07 bellard
        pd = p->phys_offset;
2845 8df1cd07 bellard
    }
2846 3b46e624 ths
2847 3a7d929e bellard
    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2848 8df1cd07 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2849 8df1cd07 bellard
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2850 8df1cd07 bellard
    } else {
2851 5fafdf24 ths
        ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
2852 8df1cd07 bellard
            (addr & ~TARGET_PAGE_MASK);
2853 8df1cd07 bellard
        stl_p(ptr, val);
2854 8df1cd07 bellard
    }
2855 8df1cd07 bellard
}
2856 8df1cd07 bellard
2857 bc98a7ef j_mayer
void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
2858 bc98a7ef j_mayer
{
2859 bc98a7ef j_mayer
    int io_index;
2860 bc98a7ef j_mayer
    uint8_t *ptr;
2861 bc98a7ef j_mayer
    unsigned long pd;
2862 bc98a7ef j_mayer
    PhysPageDesc *p;
2863 bc98a7ef j_mayer
2864 bc98a7ef j_mayer
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2865 bc98a7ef j_mayer
    if (!p) {
2866 bc98a7ef j_mayer
        pd = IO_MEM_UNASSIGNED;
2867 bc98a7ef j_mayer
    } else {
2868 bc98a7ef j_mayer
        pd = p->phys_offset;
2869 bc98a7ef j_mayer
    }
2870 3b46e624 ths
2871 bc98a7ef j_mayer
    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2872 bc98a7ef j_mayer
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2873 bc98a7ef j_mayer
#ifdef TARGET_WORDS_BIGENDIAN
2874 bc98a7ef j_mayer
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
2875 bc98a7ef j_mayer
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
2876 bc98a7ef j_mayer
#else
2877 bc98a7ef j_mayer
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2878 bc98a7ef j_mayer
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
2879 bc98a7ef j_mayer
#endif
2880 bc98a7ef j_mayer
    } else {
2881 5fafdf24 ths
        ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
2882 bc98a7ef j_mayer
            (addr & ~TARGET_PAGE_MASK);
2883 bc98a7ef j_mayer
        stq_p(ptr, val);
2884 bc98a7ef j_mayer
    }
2885 bc98a7ef j_mayer
}
2886 bc98a7ef j_mayer
2887 8df1cd07 bellard
/* warning: addr must be aligned */
2888 8df1cd07 bellard
void stl_phys(target_phys_addr_t addr, uint32_t val)
2889 8df1cd07 bellard
{
2890 8df1cd07 bellard
    int io_index;
2891 8df1cd07 bellard
    uint8_t *ptr;
2892 8df1cd07 bellard
    unsigned long pd;
2893 8df1cd07 bellard
    PhysPageDesc *p;
2894 8df1cd07 bellard
2895 8df1cd07 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2896 8df1cd07 bellard
    if (!p) {
2897 8df1cd07 bellard
        pd = IO_MEM_UNASSIGNED;
2898 8df1cd07 bellard
    } else {
2899 8df1cd07 bellard
        pd = p->phys_offset;
2900 8df1cd07 bellard
    }
2901 3b46e624 ths
2902 3a7d929e bellard
    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2903 8df1cd07 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2904 8df1cd07 bellard
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2905 8df1cd07 bellard
    } else {
2906 8df1cd07 bellard
        unsigned long addr1;
2907 8df1cd07 bellard
        addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2908 8df1cd07 bellard
        /* RAM case */
2909 8df1cd07 bellard
        ptr = phys_ram_base + addr1;
2910 8df1cd07 bellard
        stl_p(ptr, val);
2911 3a7d929e bellard
        if (!cpu_physical_memory_is_dirty(addr1)) {
2912 3a7d929e bellard
            /* invalidate code */
2913 3a7d929e bellard
            tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
2914 3a7d929e bellard
            /* set dirty bit */
2915 f23db169 bellard
            phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
2916 f23db169 bellard
                (0xff & ~CODE_DIRTY_FLAG);
2917 3a7d929e bellard
        }
2918 8df1cd07 bellard
    }
2919 8df1cd07 bellard
}
2920 8df1cd07 bellard
2921 aab33094 bellard
/* XXX: optimize */
2922 aab33094 bellard
void stb_phys(target_phys_addr_t addr, uint32_t val)
2923 aab33094 bellard
{
2924 aab33094 bellard
    uint8_t v = val;
2925 aab33094 bellard
    cpu_physical_memory_write(addr, &v, 1);
2926 aab33094 bellard
}
2927 aab33094 bellard
2928 aab33094 bellard
/* XXX: optimize */
2929 aab33094 bellard
void stw_phys(target_phys_addr_t addr, uint32_t val)
2930 aab33094 bellard
{
2931 aab33094 bellard
    uint16_t v = tswap16(val);
2932 aab33094 bellard
    cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
2933 aab33094 bellard
}
2934 aab33094 bellard
2935 aab33094 bellard
/* XXX: optimize */
2936 aab33094 bellard
void stq_phys(target_phys_addr_t addr, uint64_t val)
2937 aab33094 bellard
{
2938 aab33094 bellard
    val = tswap64(val);
2939 aab33094 bellard
    cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
2940 aab33094 bellard
}
2941 aab33094 bellard
2942 13eb76e0 bellard
#endif
2943 13eb76e0 bellard
2944 13eb76e0 bellard
/* virtual memory access for debug */
2945 5fafdf24 ths
int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
2946 b448f2f3 bellard
                        uint8_t *buf, int len, int is_write)
2947 13eb76e0 bellard
{
2948 13eb76e0 bellard
    int l;
2949 9b3c35e0 j_mayer
    target_phys_addr_t phys_addr;
2950 9b3c35e0 j_mayer
    target_ulong page;
2951 13eb76e0 bellard
2952 13eb76e0 bellard
    while (len > 0) {
2953 13eb76e0 bellard
        page = addr & TARGET_PAGE_MASK;
2954 13eb76e0 bellard
        phys_addr = cpu_get_phys_page_debug(env, page);
2955 13eb76e0 bellard
        /* if no physical page mapped, return an error */
2956 13eb76e0 bellard
        if (phys_addr == -1)
2957 13eb76e0 bellard
            return -1;
2958 13eb76e0 bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
2959 13eb76e0 bellard
        if (l > len)
2960 13eb76e0 bellard
            l = len;
2961 5fafdf24 ths
        cpu_physical_memory_rw(phys_addr + (addr & ~TARGET_PAGE_MASK),
2962 b448f2f3 bellard
                               buf, l, is_write);
2963 13eb76e0 bellard
        len -= l;
2964 13eb76e0 bellard
        buf += l;
2965 13eb76e0 bellard
        addr += l;
2966 13eb76e0 bellard
    }
2967 13eb76e0 bellard
    return 0;
2968 13eb76e0 bellard
}
2969 13eb76e0 bellard
2970 e3db7226 bellard
void dump_exec_info(FILE *f,
2971 e3db7226 bellard
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2972 e3db7226 bellard
{
2973 e3db7226 bellard
    int i, target_code_size, max_target_code_size;
2974 e3db7226 bellard
    int direct_jmp_count, direct_jmp2_count, cross_page;
2975 e3db7226 bellard
    TranslationBlock *tb;
2976 3b46e624 ths
2977 e3db7226 bellard
    target_code_size = 0;
2978 e3db7226 bellard
    max_target_code_size = 0;
2979 e3db7226 bellard
    cross_page = 0;
2980 e3db7226 bellard
    direct_jmp_count = 0;
2981 e3db7226 bellard
    direct_jmp2_count = 0;
2982 e3db7226 bellard
    for(i = 0; i < nb_tbs; i++) {
2983 e3db7226 bellard
        tb = &tbs[i];
2984 e3db7226 bellard
        target_code_size += tb->size;
2985 e3db7226 bellard
        if (tb->size > max_target_code_size)
2986 e3db7226 bellard
            max_target_code_size = tb->size;
2987 e3db7226 bellard
        if (tb->page_addr[1] != -1)
2988 e3db7226 bellard
            cross_page++;
2989 e3db7226 bellard
        if (tb->tb_next_offset[0] != 0xffff) {
2990 e3db7226 bellard
            direct_jmp_count++;
2991 e3db7226 bellard
            if (tb->tb_next_offset[1] != 0xffff) {
2992 e3db7226 bellard
                direct_jmp2_count++;
2993 e3db7226 bellard
            }
2994 e3db7226 bellard
        }
2995 e3db7226 bellard
    }
2996 e3db7226 bellard
    /* XXX: avoid using doubles ? */
2997 57fec1fe bellard
    cpu_fprintf(f, "Translation buffer state:\n");
2998 26a5f13b bellard
    cpu_fprintf(f, "gen code size       %ld/%ld\n",
2999 26a5f13b bellard
                code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size);
3000 26a5f13b bellard
    cpu_fprintf(f, "TB count            %d/%d\n", 
3001 26a5f13b bellard
                nb_tbs, code_gen_max_blocks);
3002 5fafdf24 ths
    cpu_fprintf(f, "TB avg target size  %d max=%d bytes\n",
3003 e3db7226 bellard
                nb_tbs ? target_code_size / nb_tbs : 0,
3004 e3db7226 bellard
                max_target_code_size);
3005 5fafdf24 ths
    cpu_fprintf(f, "TB avg host size    %d bytes (expansion ratio: %0.1f)\n",
3006 e3db7226 bellard
                nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
3007 e3db7226 bellard
                target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
3008 5fafdf24 ths
    cpu_fprintf(f, "cross page TB count %d (%d%%)\n",
3009 5fafdf24 ths
            cross_page,
3010 e3db7226 bellard
            nb_tbs ? (cross_page * 100) / nb_tbs : 0);
3011 e3db7226 bellard
    cpu_fprintf(f, "direct jump count   %d (%d%%) (2 jumps=%d %d%%)\n",
3012 5fafdf24 ths
                direct_jmp_count,
3013 e3db7226 bellard
                nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
3014 e3db7226 bellard
                direct_jmp2_count,
3015 e3db7226 bellard
                nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
3016 57fec1fe bellard
    cpu_fprintf(f, "\nStatistics:\n");
3017 e3db7226 bellard
    cpu_fprintf(f, "TB flush count      %d\n", tb_flush_count);
3018 e3db7226 bellard
    cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
3019 e3db7226 bellard
    cpu_fprintf(f, "TLB flush count     %d\n", tlb_flush_count);
3020 b67d9a52 bellard
    tcg_dump_info(f, cpu_fprintf);
3021 e3db7226 bellard
}
3022 e3db7226 bellard
3023 5fafdf24 ths
#if !defined(CONFIG_USER_ONLY)
3024 61382a50 bellard
3025 61382a50 bellard
#define MMUSUFFIX _cmmu
3026 61382a50 bellard
#define GETPC() NULL
3027 61382a50 bellard
#define env cpu_single_env
3028 b769d8fe bellard
#define SOFTMMU_CODE_ACCESS
3029 61382a50 bellard
3030 61382a50 bellard
#define SHIFT 0
3031 61382a50 bellard
#include "softmmu_template.h"
3032 61382a50 bellard
3033 61382a50 bellard
#define SHIFT 1
3034 61382a50 bellard
#include "softmmu_template.h"
3035 61382a50 bellard
3036 61382a50 bellard
#define SHIFT 2
3037 61382a50 bellard
#include "softmmu_template.h"
3038 61382a50 bellard
3039 61382a50 bellard
#define SHIFT 3
3040 61382a50 bellard
#include "softmmu_template.h"
3041 61382a50 bellard
3042 61382a50 bellard
#undef env
3043 61382a50 bellard
3044 61382a50 bellard
#endif