Statistics
| Branch: | Revision:

root / exec.c @ 90f18422

History | View | Annotate | Download (70.2 kB)

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