Statistics
| Branch: | Revision:

root / exec.c @ 07ce05ea

History | View | Annotate | Download (52.2 kB)

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