Statistics
| Branch: | Revision:

root / exec.c @ 86cc1ce0

History | View | Annotate | Download (77.6 kB)

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