Statistics
| Branch: | Revision:

root / exec.c @ a9049a07

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