Statistics
| Branch: | Revision:

root / exec.c @ d1d9f421

History | View | Annotate | Download (62.1 kB)

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