Statistics
| Branch: | Revision:

root / exec.c @ 6cc721cf

History | View | Annotate | Download (70.9 kB)

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