Statistics
| Branch: | Revision:

root / exec.c @ 14ce26e7

History | View | Annotate | Download (63.4 kB)

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