Statistics
| Branch: | Revision:

root / exec.c @ a8d3431a

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