Statistics
| Branch: | Revision:

root / exec.c @ afc7df11

History | View | Annotate | Download (68.6 kB)

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