Statistics
| Branch: | Revision:

root / exec.c @ 1247c5f7

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