Statistics
| Branch: | Revision:

root / exec.c @ d64477af

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