Statistics
| Branch: | Revision:

root / exec.c @ 046d6672

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