Statistics
| Branch: | Revision:

root / exec.c @ a98d49b1

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