Statistics
| Branch: | Revision:

root / exec.c @ 50d3eeae

History | View | Annotate | Download (75.5 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 53a5960a pbrook
#if defined(CONFIG_USER_ONLY)
38 53a5960a pbrook
#include <qemu.h>
39 53a5960a pbrook
#endif
40 54936004 bellard
41 fd6ce8f6 bellard
//#define DEBUG_TB_INVALIDATE
42 66e85a21 bellard
//#define DEBUG_FLUSH
43 9fa3e853 bellard
//#define DEBUG_TLB
44 67d3b957 pbrook
//#define DEBUG_UNASSIGNED
45 fd6ce8f6 bellard
46 fd6ce8f6 bellard
/* make various TB consistency checks */
47 fd6ce8f6 bellard
//#define DEBUG_TB_CHECK 
48 98857888 bellard
//#define DEBUG_TLB_CHECK 
49 fd6ce8f6 bellard
50 1196be37 ths
//#define DEBUG_IOPORT
51 1196be37 ths
52 99773bd4 pbrook
#if !defined(CONFIG_USER_ONLY)
53 99773bd4 pbrook
/* TB consistency checks only implemented for usermode emulation.  */
54 99773bd4 pbrook
#undef DEBUG_TB_CHECK
55 99773bd4 pbrook
#endif
56 99773bd4 pbrook
57 fd6ce8f6 bellard
/* threshold to flush the translated code buffer */
58 fd6ce8f6 bellard
#define CODE_GEN_BUFFER_MAX_SIZE (CODE_GEN_BUFFER_SIZE - CODE_GEN_MAX_SIZE)
59 fd6ce8f6 bellard
60 9fa3e853 bellard
#define SMC_BITMAP_USE_THRESHOLD 10
61 9fa3e853 bellard
62 9fa3e853 bellard
#define MMAP_AREA_START        0x00000000
63 9fa3e853 bellard
#define MMAP_AREA_END          0xa8000000
64 fd6ce8f6 bellard
65 108c49b8 bellard
#if defined(TARGET_SPARC64)
66 108c49b8 bellard
#define TARGET_PHYS_ADDR_SPACE_BITS 41
67 108c49b8 bellard
#elif defined(TARGET_PPC64)
68 108c49b8 bellard
#define TARGET_PHYS_ADDR_SPACE_BITS 42
69 108c49b8 bellard
#else
70 108c49b8 bellard
/* Note: for compatibility with kqemu, we use 32 bits for x86_64 */
71 108c49b8 bellard
#define TARGET_PHYS_ADDR_SPACE_BITS 32
72 108c49b8 bellard
#endif
73 108c49b8 bellard
74 fd6ce8f6 bellard
TranslationBlock tbs[CODE_GEN_MAX_BLOCKS];
75 9fa3e853 bellard
TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
76 fd6ce8f6 bellard
int nb_tbs;
77 eb51d102 bellard
/* any access to the tbs or the page table must use this lock */
78 eb51d102 bellard
spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
79 fd6ce8f6 bellard
80 b8076a74 bellard
uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE] __attribute__((aligned (32)));
81 fd6ce8f6 bellard
uint8_t *code_gen_ptr;
82 fd6ce8f6 bellard
83 9fa3e853 bellard
int phys_ram_size;
84 9fa3e853 bellard
int phys_ram_fd;
85 9fa3e853 bellard
uint8_t *phys_ram_base;
86 1ccde1cb bellard
uint8_t *phys_ram_dirty;
87 e9a1ab19 bellard
static ram_addr_t phys_ram_alloc_offset = 0;
88 9fa3e853 bellard
89 6a00d601 bellard
CPUState *first_cpu;
90 6a00d601 bellard
/* current CPU in the current thread. It is only valid inside
91 6a00d601 bellard
   cpu_exec() */
92 6a00d601 bellard
CPUState *cpu_single_env; 
93 6a00d601 bellard
94 54936004 bellard
typedef struct PageDesc {
95 92e873b9 bellard
    /* list of TBs intersecting this ram page */
96 fd6ce8f6 bellard
    TranslationBlock *first_tb;
97 9fa3e853 bellard
    /* in order to optimize self modifying code, we count the number
98 9fa3e853 bellard
       of lookups we do to a given page to use a bitmap */
99 9fa3e853 bellard
    unsigned int code_write_count;
100 9fa3e853 bellard
    uint8_t *code_bitmap;
101 9fa3e853 bellard
#if defined(CONFIG_USER_ONLY)
102 9fa3e853 bellard
    unsigned long flags;
103 9fa3e853 bellard
#endif
104 54936004 bellard
} PageDesc;
105 54936004 bellard
106 92e873b9 bellard
typedef struct PhysPageDesc {
107 92e873b9 bellard
    /* offset in host memory of the page + io_index in the low 12 bits */
108 e04f40b5 bellard
    uint32_t phys_offset;
109 92e873b9 bellard
} PhysPageDesc;
110 92e873b9 bellard
111 54936004 bellard
#define L2_BITS 10
112 54936004 bellard
#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
113 54936004 bellard
114 54936004 bellard
#define L1_SIZE (1 << L1_BITS)
115 54936004 bellard
#define L2_SIZE (1 << L2_BITS)
116 54936004 bellard
117 33417e70 bellard
static void io_mem_init(void);
118 fd6ce8f6 bellard
119 83fb7adf bellard
unsigned long qemu_real_host_page_size;
120 83fb7adf bellard
unsigned long qemu_host_page_bits;
121 83fb7adf bellard
unsigned long qemu_host_page_size;
122 83fb7adf bellard
unsigned long qemu_host_page_mask;
123 54936004 bellard
124 92e873b9 bellard
/* XXX: for system emulation, it could just be an array */
125 54936004 bellard
static PageDesc *l1_map[L1_SIZE];
126 0a962c02 bellard
PhysPageDesc **l1_phys_map;
127 54936004 bellard
128 33417e70 bellard
/* io memory support */
129 33417e70 bellard
CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
130 33417e70 bellard
CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
131 a4193c8a bellard
void *io_mem_opaque[IO_MEM_NB_ENTRIES];
132 33417e70 bellard
static int io_mem_nb;
133 6658ffb8 pbrook
#if defined(CONFIG_SOFTMMU)
134 6658ffb8 pbrook
static int io_mem_watch;
135 6658ffb8 pbrook
#endif
136 33417e70 bellard
137 34865134 bellard
/* log support */
138 34865134 bellard
char *logfilename = "/tmp/qemu.log";
139 34865134 bellard
FILE *logfile;
140 34865134 bellard
int loglevel;
141 34865134 bellard
142 e3db7226 bellard
/* statistics */
143 e3db7226 bellard
static int tlb_flush_count;
144 e3db7226 bellard
static int tb_flush_count;
145 e3db7226 bellard
static int tb_phys_invalidate_count;
146 e3db7226 bellard
147 b346ff46 bellard
static void page_init(void)
148 54936004 bellard
{
149 83fb7adf bellard
    /* NOTE: we can always suppose that qemu_host_page_size >=
150 54936004 bellard
       TARGET_PAGE_SIZE */
151 67b915a5 bellard
#ifdef _WIN32
152 d5a8f07c bellard
    {
153 d5a8f07c bellard
        SYSTEM_INFO system_info;
154 d5a8f07c bellard
        DWORD old_protect;
155 d5a8f07c bellard
        
156 d5a8f07c bellard
        GetSystemInfo(&system_info);
157 d5a8f07c bellard
        qemu_real_host_page_size = system_info.dwPageSize;
158 d5a8f07c bellard
        
159 d5a8f07c bellard
        VirtualProtect(code_gen_buffer, sizeof(code_gen_buffer),
160 d5a8f07c bellard
                       PAGE_EXECUTE_READWRITE, &old_protect);
161 d5a8f07c bellard
    }
162 67b915a5 bellard
#else
163 83fb7adf bellard
    qemu_real_host_page_size = getpagesize();
164 d5a8f07c bellard
    {
165 d5a8f07c bellard
        unsigned long start, end;
166 d5a8f07c bellard
167 d5a8f07c bellard
        start = (unsigned long)code_gen_buffer;
168 d5a8f07c bellard
        start &= ~(qemu_real_host_page_size - 1);
169 d5a8f07c bellard
        
170 d5a8f07c bellard
        end = (unsigned long)code_gen_buffer + sizeof(code_gen_buffer);
171 d5a8f07c bellard
        end += qemu_real_host_page_size - 1;
172 d5a8f07c bellard
        end &= ~(qemu_real_host_page_size - 1);
173 d5a8f07c bellard
        
174 d5a8f07c bellard
        mprotect((void *)start, end - start, 
175 d5a8f07c bellard
                 PROT_READ | PROT_WRITE | PROT_EXEC);
176 d5a8f07c bellard
    }
177 67b915a5 bellard
#endif
178 d5a8f07c bellard
179 83fb7adf bellard
    if (qemu_host_page_size == 0)
180 83fb7adf bellard
        qemu_host_page_size = qemu_real_host_page_size;
181 83fb7adf bellard
    if (qemu_host_page_size < TARGET_PAGE_SIZE)
182 83fb7adf bellard
        qemu_host_page_size = TARGET_PAGE_SIZE;
183 83fb7adf bellard
    qemu_host_page_bits = 0;
184 83fb7adf bellard
    while ((1 << qemu_host_page_bits) < qemu_host_page_size)
185 83fb7adf bellard
        qemu_host_page_bits++;
186 83fb7adf bellard
    qemu_host_page_mask = ~(qemu_host_page_size - 1);
187 108c49b8 bellard
    l1_phys_map = qemu_vmalloc(L1_SIZE * sizeof(void *));
188 108c49b8 bellard
    memset(l1_phys_map, 0, L1_SIZE * sizeof(void *));
189 54936004 bellard
}
190 54936004 bellard
191 fd6ce8f6 bellard
static inline PageDesc *page_find_alloc(unsigned int index)
192 54936004 bellard
{
193 54936004 bellard
    PageDesc **lp, *p;
194 54936004 bellard
195 54936004 bellard
    lp = &l1_map[index >> L2_BITS];
196 54936004 bellard
    p = *lp;
197 54936004 bellard
    if (!p) {
198 54936004 bellard
        /* allocate if not found */
199 59817ccb bellard
        p = qemu_malloc(sizeof(PageDesc) * L2_SIZE);
200 fd6ce8f6 bellard
        memset(p, 0, sizeof(PageDesc) * L2_SIZE);
201 54936004 bellard
        *lp = p;
202 54936004 bellard
    }
203 54936004 bellard
    return p + (index & (L2_SIZE - 1));
204 54936004 bellard
}
205 54936004 bellard
206 fd6ce8f6 bellard
static inline PageDesc *page_find(unsigned int index)
207 54936004 bellard
{
208 54936004 bellard
    PageDesc *p;
209 54936004 bellard
210 54936004 bellard
    p = l1_map[index >> L2_BITS];
211 54936004 bellard
    if (!p)
212 54936004 bellard
        return 0;
213 fd6ce8f6 bellard
    return p + (index & (L2_SIZE - 1));
214 fd6ce8f6 bellard
}
215 fd6ce8f6 bellard
216 108c49b8 bellard
static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
217 92e873b9 bellard
{
218 108c49b8 bellard
    void **lp, **p;
219 e3f4e2a4 pbrook
    PhysPageDesc *pd;
220 92e873b9 bellard
221 108c49b8 bellard
    p = (void **)l1_phys_map;
222 108c49b8 bellard
#if TARGET_PHYS_ADDR_SPACE_BITS > 32
223 108c49b8 bellard
224 108c49b8 bellard
#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
225 108c49b8 bellard
#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
226 108c49b8 bellard
#endif
227 108c49b8 bellard
    lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1));
228 92e873b9 bellard
    p = *lp;
229 92e873b9 bellard
    if (!p) {
230 92e873b9 bellard
        /* allocate if not found */
231 108c49b8 bellard
        if (!alloc)
232 108c49b8 bellard
            return NULL;
233 108c49b8 bellard
        p = qemu_vmalloc(sizeof(void *) * L1_SIZE);
234 108c49b8 bellard
        memset(p, 0, sizeof(void *) * L1_SIZE);
235 108c49b8 bellard
        *lp = p;
236 108c49b8 bellard
    }
237 108c49b8 bellard
#endif
238 108c49b8 bellard
    lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
239 e3f4e2a4 pbrook
    pd = *lp;
240 e3f4e2a4 pbrook
    if (!pd) {
241 e3f4e2a4 pbrook
        int i;
242 108c49b8 bellard
        /* allocate if not found */
243 108c49b8 bellard
        if (!alloc)
244 108c49b8 bellard
            return NULL;
245 e3f4e2a4 pbrook
        pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
246 e3f4e2a4 pbrook
        *lp = pd;
247 e3f4e2a4 pbrook
        for (i = 0; i < L2_SIZE; i++)
248 e3f4e2a4 pbrook
          pd[i].phys_offset = IO_MEM_UNASSIGNED;
249 92e873b9 bellard
    }
250 e3f4e2a4 pbrook
    return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
251 92e873b9 bellard
}
252 92e873b9 bellard
253 108c49b8 bellard
static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
254 92e873b9 bellard
{
255 108c49b8 bellard
    return phys_page_find_alloc(index, 0);
256 92e873b9 bellard
}
257 92e873b9 bellard
258 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
259 6a00d601 bellard
static void tlb_protect_code(ram_addr_t ram_addr);
260 3a7d929e bellard
static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr, 
261 3a7d929e bellard
                                    target_ulong vaddr);
262 9fa3e853 bellard
#endif
263 fd6ce8f6 bellard
264 6a00d601 bellard
void cpu_exec_init(CPUState *env)
265 fd6ce8f6 bellard
{
266 6a00d601 bellard
    CPUState **penv;
267 6a00d601 bellard
    int cpu_index;
268 6a00d601 bellard
269 fd6ce8f6 bellard
    if (!code_gen_ptr) {
270 fd6ce8f6 bellard
        code_gen_ptr = code_gen_buffer;
271 b346ff46 bellard
        page_init();
272 33417e70 bellard
        io_mem_init();
273 fd6ce8f6 bellard
    }
274 6a00d601 bellard
    env->next_cpu = NULL;
275 6a00d601 bellard
    penv = &first_cpu;
276 6a00d601 bellard
    cpu_index = 0;
277 6a00d601 bellard
    while (*penv != NULL) {
278 6a00d601 bellard
        penv = (CPUState **)&(*penv)->next_cpu;
279 6a00d601 bellard
        cpu_index++;
280 6a00d601 bellard
    }
281 6a00d601 bellard
    env->cpu_index = cpu_index;
282 6658ffb8 pbrook
    env->nb_watchpoints = 0;
283 6a00d601 bellard
    *penv = env;
284 fd6ce8f6 bellard
}
285 fd6ce8f6 bellard
286 9fa3e853 bellard
static inline void invalidate_page_bitmap(PageDesc *p)
287 9fa3e853 bellard
{
288 9fa3e853 bellard
    if (p->code_bitmap) {
289 59817ccb bellard
        qemu_free(p->code_bitmap);
290 9fa3e853 bellard
        p->code_bitmap = NULL;
291 9fa3e853 bellard
    }
292 9fa3e853 bellard
    p->code_write_count = 0;
293 9fa3e853 bellard
}
294 9fa3e853 bellard
295 fd6ce8f6 bellard
/* set to NULL all the 'first_tb' fields in all PageDescs */
296 fd6ce8f6 bellard
static void page_flush_tb(void)
297 fd6ce8f6 bellard
{
298 fd6ce8f6 bellard
    int i, j;
299 fd6ce8f6 bellard
    PageDesc *p;
300 fd6ce8f6 bellard
301 fd6ce8f6 bellard
    for(i = 0; i < L1_SIZE; i++) {
302 fd6ce8f6 bellard
        p = l1_map[i];
303 fd6ce8f6 bellard
        if (p) {
304 9fa3e853 bellard
            for(j = 0; j < L2_SIZE; j++) {
305 9fa3e853 bellard
                p->first_tb = NULL;
306 9fa3e853 bellard
                invalidate_page_bitmap(p);
307 9fa3e853 bellard
                p++;
308 9fa3e853 bellard
            }
309 fd6ce8f6 bellard
        }
310 fd6ce8f6 bellard
    }
311 fd6ce8f6 bellard
}
312 fd6ce8f6 bellard
313 fd6ce8f6 bellard
/* flush all the translation blocks */
314 d4e8164f bellard
/* XXX: tb_flush is currently not thread safe */
315 6a00d601 bellard
void tb_flush(CPUState *env1)
316 fd6ce8f6 bellard
{
317 6a00d601 bellard
    CPUState *env;
318 0124311e bellard
#if defined(DEBUG_FLUSH)
319 fd6ce8f6 bellard
    printf("qemu: flush code_size=%d nb_tbs=%d avg_tb_size=%d\n", 
320 fd6ce8f6 bellard
           code_gen_ptr - code_gen_buffer, 
321 fd6ce8f6 bellard
           nb_tbs, 
322 0124311e bellard
           nb_tbs > 0 ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0);
323 fd6ce8f6 bellard
#endif
324 fd6ce8f6 bellard
    nb_tbs = 0;
325 6a00d601 bellard
    
326 6a00d601 bellard
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
327 6a00d601 bellard
        memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
328 6a00d601 bellard
    }
329 9fa3e853 bellard
330 8a8a608f bellard
    memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
331 fd6ce8f6 bellard
    page_flush_tb();
332 9fa3e853 bellard
333 fd6ce8f6 bellard
    code_gen_ptr = code_gen_buffer;
334 d4e8164f bellard
    /* XXX: flush processor icache at this point if cache flush is
335 d4e8164f bellard
       expensive */
336 e3db7226 bellard
    tb_flush_count++;
337 fd6ce8f6 bellard
}
338 fd6ce8f6 bellard
339 fd6ce8f6 bellard
#ifdef DEBUG_TB_CHECK
340 fd6ce8f6 bellard
341 fd6ce8f6 bellard
static void tb_invalidate_check(unsigned long address)
342 fd6ce8f6 bellard
{
343 fd6ce8f6 bellard
    TranslationBlock *tb;
344 fd6ce8f6 bellard
    int i;
345 fd6ce8f6 bellard
    address &= TARGET_PAGE_MASK;
346 99773bd4 pbrook
    for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
347 99773bd4 pbrook
        for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
348 fd6ce8f6 bellard
            if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
349 fd6ce8f6 bellard
                  address >= tb->pc + tb->size)) {
350 fd6ce8f6 bellard
                printf("ERROR invalidate: address=%08lx PC=%08lx size=%04x\n",
351 99773bd4 pbrook
                       address, (long)tb->pc, tb->size);
352 fd6ce8f6 bellard
            }
353 fd6ce8f6 bellard
        }
354 fd6ce8f6 bellard
    }
355 fd6ce8f6 bellard
}
356 fd6ce8f6 bellard
357 fd6ce8f6 bellard
/* verify that all the pages have correct rights for code */
358 fd6ce8f6 bellard
static void tb_page_check(void)
359 fd6ce8f6 bellard
{
360 fd6ce8f6 bellard
    TranslationBlock *tb;
361 fd6ce8f6 bellard
    int i, flags1, flags2;
362 fd6ce8f6 bellard
    
363 99773bd4 pbrook
    for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
364 99773bd4 pbrook
        for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
365 fd6ce8f6 bellard
            flags1 = page_get_flags(tb->pc);
366 fd6ce8f6 bellard
            flags2 = page_get_flags(tb->pc + tb->size - 1);
367 fd6ce8f6 bellard
            if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
368 fd6ce8f6 bellard
                printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
369 99773bd4 pbrook
                       (long)tb->pc, tb->size, flags1, flags2);
370 fd6ce8f6 bellard
            }
371 fd6ce8f6 bellard
        }
372 fd6ce8f6 bellard
    }
373 fd6ce8f6 bellard
}
374 fd6ce8f6 bellard
375 d4e8164f bellard
void tb_jmp_check(TranslationBlock *tb)
376 d4e8164f bellard
{
377 d4e8164f bellard
    TranslationBlock *tb1;
378 d4e8164f bellard
    unsigned int n1;
379 d4e8164f bellard
380 d4e8164f bellard
    /* suppress any remaining jumps to this TB */
381 d4e8164f bellard
    tb1 = tb->jmp_first;
382 d4e8164f bellard
    for(;;) {
383 d4e8164f bellard
        n1 = (long)tb1 & 3;
384 d4e8164f bellard
        tb1 = (TranslationBlock *)((long)tb1 & ~3);
385 d4e8164f bellard
        if (n1 == 2)
386 d4e8164f bellard
            break;
387 d4e8164f bellard
        tb1 = tb1->jmp_next[n1];
388 d4e8164f bellard
    }
389 d4e8164f bellard
    /* check end of list */
390 d4e8164f bellard
    if (tb1 != tb) {
391 d4e8164f bellard
        printf("ERROR: jmp_list from 0x%08lx\n", (long)tb);
392 d4e8164f bellard
    }
393 d4e8164f bellard
}
394 d4e8164f bellard
395 fd6ce8f6 bellard
#endif
396 fd6ce8f6 bellard
397 fd6ce8f6 bellard
/* invalidate one TB */
398 fd6ce8f6 bellard
static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb,
399 fd6ce8f6 bellard
                             int next_offset)
400 fd6ce8f6 bellard
{
401 fd6ce8f6 bellard
    TranslationBlock *tb1;
402 fd6ce8f6 bellard
    for(;;) {
403 fd6ce8f6 bellard
        tb1 = *ptb;
404 fd6ce8f6 bellard
        if (tb1 == tb) {
405 fd6ce8f6 bellard
            *ptb = *(TranslationBlock **)((char *)tb1 + next_offset);
406 fd6ce8f6 bellard
            break;
407 fd6ce8f6 bellard
        }
408 fd6ce8f6 bellard
        ptb = (TranslationBlock **)((char *)tb1 + next_offset);
409 fd6ce8f6 bellard
    }
410 fd6ce8f6 bellard
}
411 fd6ce8f6 bellard
412 9fa3e853 bellard
static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
413 9fa3e853 bellard
{
414 9fa3e853 bellard
    TranslationBlock *tb1;
415 9fa3e853 bellard
    unsigned int n1;
416 9fa3e853 bellard
417 9fa3e853 bellard
    for(;;) {
418 9fa3e853 bellard
        tb1 = *ptb;
419 9fa3e853 bellard
        n1 = (long)tb1 & 3;
420 9fa3e853 bellard
        tb1 = (TranslationBlock *)((long)tb1 & ~3);
421 9fa3e853 bellard
        if (tb1 == tb) {
422 9fa3e853 bellard
            *ptb = tb1->page_next[n1];
423 9fa3e853 bellard
            break;
424 9fa3e853 bellard
        }
425 9fa3e853 bellard
        ptb = &tb1->page_next[n1];
426 9fa3e853 bellard
    }
427 9fa3e853 bellard
}
428 9fa3e853 bellard
429 d4e8164f bellard
static inline void tb_jmp_remove(TranslationBlock *tb, int n)
430 d4e8164f bellard
{
431 d4e8164f bellard
    TranslationBlock *tb1, **ptb;
432 d4e8164f bellard
    unsigned int n1;
433 d4e8164f bellard
434 d4e8164f bellard
    ptb = &tb->jmp_next[n];
435 d4e8164f bellard
    tb1 = *ptb;
436 d4e8164f bellard
    if (tb1) {
437 d4e8164f bellard
        /* find tb(n) in circular list */
438 d4e8164f bellard
        for(;;) {
439 d4e8164f bellard
            tb1 = *ptb;
440 d4e8164f bellard
            n1 = (long)tb1 & 3;
441 d4e8164f bellard
            tb1 = (TranslationBlock *)((long)tb1 & ~3);
442 d4e8164f bellard
            if (n1 == n && tb1 == tb)
443 d4e8164f bellard
                break;
444 d4e8164f bellard
            if (n1 == 2) {
445 d4e8164f bellard
                ptb = &tb1->jmp_first;
446 d4e8164f bellard
            } else {
447 d4e8164f bellard
                ptb = &tb1->jmp_next[n1];
448 d4e8164f bellard
            }
449 d4e8164f bellard
        }
450 d4e8164f bellard
        /* now we can suppress tb(n) from the list */
451 d4e8164f bellard
        *ptb = tb->jmp_next[n];
452 d4e8164f bellard
453 d4e8164f bellard
        tb->jmp_next[n] = NULL;
454 d4e8164f bellard
    }
455 d4e8164f bellard
}
456 d4e8164f bellard
457 d4e8164f bellard
/* reset the jump entry 'n' of a TB so that it is not chained to
458 d4e8164f bellard
   another TB */
459 d4e8164f bellard
static inline void tb_reset_jump(TranslationBlock *tb, int n)
460 d4e8164f bellard
{
461 d4e8164f bellard
    tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
462 d4e8164f bellard
}
463 d4e8164f bellard
464 8a40a180 bellard
static inline void tb_phys_invalidate(TranslationBlock *tb, unsigned int page_addr)
465 fd6ce8f6 bellard
{
466 6a00d601 bellard
    CPUState *env;
467 8a40a180 bellard
    PageDesc *p;
468 d4e8164f bellard
    unsigned int h, n1;
469 8a40a180 bellard
    target_ulong phys_pc;
470 8a40a180 bellard
    TranslationBlock *tb1, *tb2;
471 d4e8164f bellard
    
472 8a40a180 bellard
    /* remove the TB from the hash list */
473 8a40a180 bellard
    phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
474 8a40a180 bellard
    h = tb_phys_hash_func(phys_pc);
475 8a40a180 bellard
    tb_remove(&tb_phys_hash[h], tb, 
476 8a40a180 bellard
              offsetof(TranslationBlock, phys_hash_next));
477 8a40a180 bellard
478 8a40a180 bellard
    /* remove the TB from the page list */
479 8a40a180 bellard
    if (tb->page_addr[0] != page_addr) {
480 8a40a180 bellard
        p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
481 8a40a180 bellard
        tb_page_remove(&p->first_tb, tb);
482 8a40a180 bellard
        invalidate_page_bitmap(p);
483 8a40a180 bellard
    }
484 8a40a180 bellard
    if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
485 8a40a180 bellard
        p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
486 8a40a180 bellard
        tb_page_remove(&p->first_tb, tb);
487 8a40a180 bellard
        invalidate_page_bitmap(p);
488 8a40a180 bellard
    }
489 8a40a180 bellard
490 36bdbe54 bellard
    tb_invalidated_flag = 1;
491 59817ccb bellard
492 fd6ce8f6 bellard
    /* remove the TB from the hash list */
493 8a40a180 bellard
    h = tb_jmp_cache_hash_func(tb->pc);
494 6a00d601 bellard
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
495 6a00d601 bellard
        if (env->tb_jmp_cache[h] == tb)
496 6a00d601 bellard
            env->tb_jmp_cache[h] = NULL;
497 6a00d601 bellard
    }
498 d4e8164f bellard
499 d4e8164f bellard
    /* suppress this TB from the two jump lists */
500 d4e8164f bellard
    tb_jmp_remove(tb, 0);
501 d4e8164f bellard
    tb_jmp_remove(tb, 1);
502 d4e8164f bellard
503 d4e8164f bellard
    /* suppress any remaining jumps to this TB */
504 d4e8164f bellard
    tb1 = tb->jmp_first;
505 d4e8164f bellard
    for(;;) {
506 d4e8164f bellard
        n1 = (long)tb1 & 3;
507 d4e8164f bellard
        if (n1 == 2)
508 d4e8164f bellard
            break;
509 d4e8164f bellard
        tb1 = (TranslationBlock *)((long)tb1 & ~3);
510 d4e8164f bellard
        tb2 = tb1->jmp_next[n1];
511 d4e8164f bellard
        tb_reset_jump(tb1, n1);
512 d4e8164f bellard
        tb1->jmp_next[n1] = NULL;
513 d4e8164f bellard
        tb1 = tb2;
514 d4e8164f bellard
    }
515 d4e8164f bellard
    tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
516 9fa3e853 bellard
517 e3db7226 bellard
    tb_phys_invalidate_count++;
518 9fa3e853 bellard
}
519 9fa3e853 bellard
520 9fa3e853 bellard
static inline void set_bits(uint8_t *tab, int start, int len)
521 9fa3e853 bellard
{
522 9fa3e853 bellard
    int end, mask, end1;
523 9fa3e853 bellard
524 9fa3e853 bellard
    end = start + len;
525 9fa3e853 bellard
    tab += start >> 3;
526 9fa3e853 bellard
    mask = 0xff << (start & 7);
527 9fa3e853 bellard
    if ((start & ~7) == (end & ~7)) {
528 9fa3e853 bellard
        if (start < end) {
529 9fa3e853 bellard
            mask &= ~(0xff << (end & 7));
530 9fa3e853 bellard
            *tab |= mask;
531 9fa3e853 bellard
        }
532 9fa3e853 bellard
    } else {
533 9fa3e853 bellard
        *tab++ |= mask;
534 9fa3e853 bellard
        start = (start + 8) & ~7;
535 9fa3e853 bellard
        end1 = end & ~7;
536 9fa3e853 bellard
        while (start < end1) {
537 9fa3e853 bellard
            *tab++ = 0xff;
538 9fa3e853 bellard
            start += 8;
539 9fa3e853 bellard
        }
540 9fa3e853 bellard
        if (start < end) {
541 9fa3e853 bellard
            mask = ~(0xff << (end & 7));
542 9fa3e853 bellard
            *tab |= mask;
543 9fa3e853 bellard
        }
544 9fa3e853 bellard
    }
545 9fa3e853 bellard
}
546 9fa3e853 bellard
547 9fa3e853 bellard
static void build_page_bitmap(PageDesc *p)
548 9fa3e853 bellard
{
549 9fa3e853 bellard
    int n, tb_start, tb_end;
550 9fa3e853 bellard
    TranslationBlock *tb;
551 9fa3e853 bellard
    
552 59817ccb bellard
    p->code_bitmap = qemu_malloc(TARGET_PAGE_SIZE / 8);
553 9fa3e853 bellard
    if (!p->code_bitmap)
554 9fa3e853 bellard
        return;
555 9fa3e853 bellard
    memset(p->code_bitmap, 0, TARGET_PAGE_SIZE / 8);
556 9fa3e853 bellard
557 9fa3e853 bellard
    tb = p->first_tb;
558 9fa3e853 bellard
    while (tb != NULL) {
559 9fa3e853 bellard
        n = (long)tb & 3;
560 9fa3e853 bellard
        tb = (TranslationBlock *)((long)tb & ~3);
561 9fa3e853 bellard
        /* NOTE: this is subtle as a TB may span two physical pages */
562 9fa3e853 bellard
        if (n == 0) {
563 9fa3e853 bellard
            /* NOTE: tb_end may be after the end of the page, but
564 9fa3e853 bellard
               it is not a problem */
565 9fa3e853 bellard
            tb_start = tb->pc & ~TARGET_PAGE_MASK;
566 9fa3e853 bellard
            tb_end = tb_start + tb->size;
567 9fa3e853 bellard
            if (tb_end > TARGET_PAGE_SIZE)
568 9fa3e853 bellard
                tb_end = TARGET_PAGE_SIZE;
569 9fa3e853 bellard
        } else {
570 9fa3e853 bellard
            tb_start = 0;
571 9fa3e853 bellard
            tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
572 9fa3e853 bellard
        }
573 9fa3e853 bellard
        set_bits(p->code_bitmap, tb_start, tb_end - tb_start);
574 9fa3e853 bellard
        tb = tb->page_next[n];
575 9fa3e853 bellard
    }
576 9fa3e853 bellard
}
577 9fa3e853 bellard
578 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
579 d720b93d bellard
580 d720b93d bellard
static void tb_gen_code(CPUState *env, 
581 d720b93d bellard
                        target_ulong pc, target_ulong cs_base, int flags,
582 d720b93d bellard
                        int cflags)
583 d720b93d bellard
{
584 d720b93d bellard
    TranslationBlock *tb;
585 d720b93d bellard
    uint8_t *tc_ptr;
586 d720b93d bellard
    target_ulong phys_pc, phys_page2, virt_page2;
587 d720b93d bellard
    int code_gen_size;
588 d720b93d bellard
589 c27004ec bellard
    phys_pc = get_phys_addr_code(env, pc);
590 c27004ec bellard
    tb = tb_alloc(pc);
591 d720b93d bellard
    if (!tb) {
592 d720b93d bellard
        /* flush must be done */
593 d720b93d bellard
        tb_flush(env);
594 d720b93d bellard
        /* cannot fail at this point */
595 c27004ec bellard
        tb = tb_alloc(pc);
596 d720b93d bellard
    }
597 d720b93d bellard
    tc_ptr = code_gen_ptr;
598 d720b93d bellard
    tb->tc_ptr = tc_ptr;
599 d720b93d bellard
    tb->cs_base = cs_base;
600 d720b93d bellard
    tb->flags = flags;
601 d720b93d bellard
    tb->cflags = cflags;
602 d720b93d bellard
    cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size);
603 d720b93d bellard
    code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
604 d720b93d bellard
    
605 d720b93d bellard
    /* check next page if needed */
606 c27004ec bellard
    virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
607 d720b93d bellard
    phys_page2 = -1;
608 c27004ec bellard
    if ((pc & TARGET_PAGE_MASK) != virt_page2) {
609 d720b93d bellard
        phys_page2 = get_phys_addr_code(env, virt_page2);
610 d720b93d bellard
    }
611 d720b93d bellard
    tb_link_phys(tb, phys_pc, phys_page2);
612 d720b93d bellard
}
613 d720b93d bellard
#endif
614 d720b93d bellard
    
615 9fa3e853 bellard
/* invalidate all TBs which intersect with the target physical page
616 9fa3e853 bellard
   starting in range [start;end[. NOTE: start and end must refer to
617 d720b93d bellard
   the same physical page. 'is_cpu_write_access' should be true if called
618 d720b93d bellard
   from a real cpu write access: the virtual CPU will exit the current
619 d720b93d bellard
   TB if code is modified inside this TB. */
620 d720b93d bellard
void tb_invalidate_phys_page_range(target_ulong start, target_ulong end, 
621 d720b93d bellard
                                   int is_cpu_write_access)
622 d720b93d bellard
{
623 d720b93d bellard
    int n, current_tb_modified, current_tb_not_found, current_flags;
624 d720b93d bellard
    CPUState *env = cpu_single_env;
625 9fa3e853 bellard
    PageDesc *p;
626 ea1c1802 bellard
    TranslationBlock *tb, *tb_next, *current_tb, *saved_tb;
627 9fa3e853 bellard
    target_ulong tb_start, tb_end;
628 d720b93d bellard
    target_ulong current_pc, current_cs_base;
629 9fa3e853 bellard
630 9fa3e853 bellard
    p = page_find(start >> TARGET_PAGE_BITS);
631 9fa3e853 bellard
    if (!p) 
632 9fa3e853 bellard
        return;
633 9fa3e853 bellard
    if (!p->code_bitmap && 
634 d720b93d bellard
        ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
635 d720b93d bellard
        is_cpu_write_access) {
636 9fa3e853 bellard
        /* build code bitmap */
637 9fa3e853 bellard
        build_page_bitmap(p);
638 9fa3e853 bellard
    }
639 9fa3e853 bellard
640 9fa3e853 bellard
    /* we remove all the TBs in the range [start, end[ */
641 9fa3e853 bellard
    /* XXX: see if in some cases it could be faster to invalidate all the code */
642 d720b93d bellard
    current_tb_not_found = is_cpu_write_access;
643 d720b93d bellard
    current_tb_modified = 0;
644 d720b93d bellard
    current_tb = NULL; /* avoid warning */
645 d720b93d bellard
    current_pc = 0; /* avoid warning */
646 d720b93d bellard
    current_cs_base = 0; /* avoid warning */
647 d720b93d bellard
    current_flags = 0; /* avoid warning */
648 9fa3e853 bellard
    tb = p->first_tb;
649 9fa3e853 bellard
    while (tb != NULL) {
650 9fa3e853 bellard
        n = (long)tb & 3;
651 9fa3e853 bellard
        tb = (TranslationBlock *)((long)tb & ~3);
652 9fa3e853 bellard
        tb_next = tb->page_next[n];
653 9fa3e853 bellard
        /* NOTE: this is subtle as a TB may span two physical pages */
654 9fa3e853 bellard
        if (n == 0) {
655 9fa3e853 bellard
            /* NOTE: tb_end may be after the end of the page, but
656 9fa3e853 bellard
               it is not a problem */
657 9fa3e853 bellard
            tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
658 9fa3e853 bellard
            tb_end = tb_start + tb->size;
659 9fa3e853 bellard
        } else {
660 9fa3e853 bellard
            tb_start = tb->page_addr[1];
661 9fa3e853 bellard
            tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
662 9fa3e853 bellard
        }
663 9fa3e853 bellard
        if (!(tb_end <= start || tb_start >= end)) {
664 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
665 d720b93d bellard
            if (current_tb_not_found) {
666 d720b93d bellard
                current_tb_not_found = 0;
667 d720b93d bellard
                current_tb = NULL;
668 d720b93d bellard
                if (env->mem_write_pc) {
669 d720b93d bellard
                    /* now we have a real cpu fault */
670 d720b93d bellard
                    current_tb = tb_find_pc(env->mem_write_pc);
671 d720b93d bellard
                }
672 d720b93d bellard
            }
673 d720b93d bellard
            if (current_tb == tb &&
674 d720b93d bellard
                !(current_tb->cflags & CF_SINGLE_INSN)) {
675 d720b93d bellard
                /* If we are modifying the current TB, we must stop
676 d720b93d bellard
                its execution. We could be more precise by checking
677 d720b93d bellard
                that the modification is after the current PC, but it
678 d720b93d bellard
                would require a specialized function to partially
679 d720b93d bellard
                restore the CPU state */
680 d720b93d bellard
                
681 d720b93d bellard
                current_tb_modified = 1;
682 d720b93d bellard
                cpu_restore_state(current_tb, env, 
683 d720b93d bellard
                                  env->mem_write_pc, NULL);
684 d720b93d bellard
#if defined(TARGET_I386)
685 d720b93d bellard
                current_flags = env->hflags;
686 d720b93d bellard
                current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
687 d720b93d bellard
                current_cs_base = (target_ulong)env->segs[R_CS].base;
688 d720b93d bellard
                current_pc = current_cs_base + env->eip;
689 d720b93d bellard
#else
690 d720b93d bellard
#error unsupported CPU
691 d720b93d bellard
#endif
692 d720b93d bellard
            }
693 d720b93d bellard
#endif /* TARGET_HAS_PRECISE_SMC */
694 6f5a9f7e bellard
            /* we need to do that to handle the case where a signal
695 6f5a9f7e bellard
               occurs while doing tb_phys_invalidate() */
696 6f5a9f7e bellard
            saved_tb = NULL;
697 6f5a9f7e bellard
            if (env) {
698 6f5a9f7e bellard
                saved_tb = env->current_tb;
699 6f5a9f7e bellard
                env->current_tb = NULL;
700 6f5a9f7e bellard
            }
701 9fa3e853 bellard
            tb_phys_invalidate(tb, -1);
702 6f5a9f7e bellard
            if (env) {
703 6f5a9f7e bellard
                env->current_tb = saved_tb;
704 6f5a9f7e bellard
                if (env->interrupt_request && env->current_tb)
705 6f5a9f7e bellard
                    cpu_interrupt(env, env->interrupt_request);
706 6f5a9f7e bellard
            }
707 9fa3e853 bellard
        }
708 9fa3e853 bellard
        tb = tb_next;
709 9fa3e853 bellard
    }
710 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
711 9fa3e853 bellard
    /* if no code remaining, no need to continue to use slow writes */
712 9fa3e853 bellard
    if (!p->first_tb) {
713 9fa3e853 bellard
        invalidate_page_bitmap(p);
714 d720b93d bellard
        if (is_cpu_write_access) {
715 d720b93d bellard
            tlb_unprotect_code_phys(env, start, env->mem_write_vaddr);
716 d720b93d bellard
        }
717 d720b93d bellard
    }
718 d720b93d bellard
#endif
719 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
720 d720b93d bellard
    if (current_tb_modified) {
721 d720b93d bellard
        /* we generate a block containing just the instruction
722 d720b93d bellard
           modifying the memory. It will ensure that it cannot modify
723 d720b93d bellard
           itself */
724 ea1c1802 bellard
        env->current_tb = NULL;
725 d720b93d bellard
        tb_gen_code(env, current_pc, current_cs_base, current_flags, 
726 d720b93d bellard
                    CF_SINGLE_INSN);
727 d720b93d bellard
        cpu_resume_from_signal(env, NULL);
728 9fa3e853 bellard
    }
729 fd6ce8f6 bellard
#endif
730 9fa3e853 bellard
}
731 fd6ce8f6 bellard
732 9fa3e853 bellard
/* len must be <= 8 and start must be a multiple of len */
733 d720b93d bellard
static inline void tb_invalidate_phys_page_fast(target_ulong start, int len)
734 9fa3e853 bellard
{
735 9fa3e853 bellard
    PageDesc *p;
736 9fa3e853 bellard
    int offset, b;
737 59817ccb bellard
#if 0
738 a4193c8a bellard
    if (1) {
739 a4193c8a bellard
        if (loglevel) {
740 a4193c8a bellard
            fprintf(logfile, "modifying code at 0x%x size=%d EIP=%x PC=%08x\n", 
741 a4193c8a bellard
                   cpu_single_env->mem_write_vaddr, len, 
742 a4193c8a bellard
                   cpu_single_env->eip, 
743 a4193c8a bellard
                   cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
744 a4193c8a bellard
        }
745 59817ccb bellard
    }
746 59817ccb bellard
#endif
747 9fa3e853 bellard
    p = page_find(start >> TARGET_PAGE_BITS);
748 9fa3e853 bellard
    if (!p) 
749 9fa3e853 bellard
        return;
750 9fa3e853 bellard
    if (p->code_bitmap) {
751 9fa3e853 bellard
        offset = start & ~TARGET_PAGE_MASK;
752 9fa3e853 bellard
        b = p->code_bitmap[offset >> 3] >> (offset & 7);
753 9fa3e853 bellard
        if (b & ((1 << len) - 1))
754 9fa3e853 bellard
            goto do_invalidate;
755 9fa3e853 bellard
    } else {
756 9fa3e853 bellard
    do_invalidate:
757 d720b93d bellard
        tb_invalidate_phys_page_range(start, start + len, 1);
758 9fa3e853 bellard
    }
759 9fa3e853 bellard
}
760 9fa3e853 bellard
761 9fa3e853 bellard
#if !defined(CONFIG_SOFTMMU)
762 d720b93d bellard
static void tb_invalidate_phys_page(target_ulong addr, 
763 d720b93d bellard
                                    unsigned long pc, void *puc)
764 9fa3e853 bellard
{
765 d720b93d bellard
    int n, current_flags, current_tb_modified;
766 d720b93d bellard
    target_ulong current_pc, current_cs_base;
767 9fa3e853 bellard
    PageDesc *p;
768 d720b93d bellard
    TranslationBlock *tb, *current_tb;
769 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
770 d720b93d bellard
    CPUState *env = cpu_single_env;
771 d720b93d bellard
#endif
772 9fa3e853 bellard
773 9fa3e853 bellard
    addr &= TARGET_PAGE_MASK;
774 9fa3e853 bellard
    p = page_find(addr >> TARGET_PAGE_BITS);
775 9fa3e853 bellard
    if (!p) 
776 9fa3e853 bellard
        return;
777 9fa3e853 bellard
    tb = p->first_tb;
778 d720b93d bellard
    current_tb_modified = 0;
779 d720b93d bellard
    current_tb = NULL;
780 d720b93d bellard
    current_pc = 0; /* avoid warning */
781 d720b93d bellard
    current_cs_base = 0; /* avoid warning */
782 d720b93d bellard
    current_flags = 0; /* avoid warning */
783 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
784 d720b93d bellard
    if (tb && pc != 0) {
785 d720b93d bellard
        current_tb = tb_find_pc(pc);
786 d720b93d bellard
    }
787 d720b93d bellard
#endif
788 9fa3e853 bellard
    while (tb != NULL) {
789 9fa3e853 bellard
        n = (long)tb & 3;
790 9fa3e853 bellard
        tb = (TranslationBlock *)((long)tb & ~3);
791 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
792 d720b93d bellard
        if (current_tb == tb &&
793 d720b93d bellard
            !(current_tb->cflags & CF_SINGLE_INSN)) {
794 d720b93d bellard
                /* If we are modifying the current TB, we must stop
795 d720b93d bellard
                   its execution. We could be more precise by checking
796 d720b93d bellard
                   that the modification is after the current PC, but it
797 d720b93d bellard
                   would require a specialized function to partially
798 d720b93d bellard
                   restore the CPU state */
799 d720b93d bellard
            
800 d720b93d bellard
            current_tb_modified = 1;
801 d720b93d bellard
            cpu_restore_state(current_tb, env, pc, puc);
802 d720b93d bellard
#if defined(TARGET_I386)
803 d720b93d bellard
            current_flags = env->hflags;
804 d720b93d bellard
            current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
805 d720b93d bellard
            current_cs_base = (target_ulong)env->segs[R_CS].base;
806 d720b93d bellard
            current_pc = current_cs_base + env->eip;
807 d720b93d bellard
#else
808 d720b93d bellard
#error unsupported CPU
809 d720b93d bellard
#endif
810 d720b93d bellard
        }
811 d720b93d bellard
#endif /* TARGET_HAS_PRECISE_SMC */
812 9fa3e853 bellard
        tb_phys_invalidate(tb, addr);
813 9fa3e853 bellard
        tb = tb->page_next[n];
814 9fa3e853 bellard
    }
815 fd6ce8f6 bellard
    p->first_tb = NULL;
816 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
817 d720b93d bellard
    if (current_tb_modified) {
818 d720b93d bellard
        /* we generate a block containing just the instruction
819 d720b93d bellard
           modifying the memory. It will ensure that it cannot modify
820 d720b93d bellard
           itself */
821 ea1c1802 bellard
        env->current_tb = NULL;
822 d720b93d bellard
        tb_gen_code(env, current_pc, current_cs_base, current_flags, 
823 d720b93d bellard
                    CF_SINGLE_INSN);
824 d720b93d bellard
        cpu_resume_from_signal(env, puc);
825 d720b93d bellard
    }
826 d720b93d bellard
#endif
827 fd6ce8f6 bellard
}
828 9fa3e853 bellard
#endif
829 fd6ce8f6 bellard
830 fd6ce8f6 bellard
/* add the tb in the target page and protect it if necessary */
831 9fa3e853 bellard
static inline void tb_alloc_page(TranslationBlock *tb, 
832 53a5960a pbrook
                                 unsigned int n, target_ulong page_addr)
833 fd6ce8f6 bellard
{
834 fd6ce8f6 bellard
    PageDesc *p;
835 9fa3e853 bellard
    TranslationBlock *last_first_tb;
836 9fa3e853 bellard
837 9fa3e853 bellard
    tb->page_addr[n] = page_addr;
838 3a7d929e bellard
    p = page_find_alloc(page_addr >> TARGET_PAGE_BITS);
839 9fa3e853 bellard
    tb->page_next[n] = p->first_tb;
840 9fa3e853 bellard
    last_first_tb = p->first_tb;
841 9fa3e853 bellard
    p->first_tb = (TranslationBlock *)((long)tb | n);
842 9fa3e853 bellard
    invalidate_page_bitmap(p);
843 fd6ce8f6 bellard
844 107db443 bellard
#if defined(TARGET_HAS_SMC) || 1
845 d720b93d bellard
846 9fa3e853 bellard
#if defined(CONFIG_USER_ONLY)
847 fd6ce8f6 bellard
    if (p->flags & PAGE_WRITE) {
848 53a5960a pbrook
        target_ulong addr;
849 53a5960a pbrook
        PageDesc *p2;
850 9fa3e853 bellard
        int prot;
851 9fa3e853 bellard
852 fd6ce8f6 bellard
        /* force the host page as non writable (writes will have a
853 fd6ce8f6 bellard
           page fault + mprotect overhead) */
854 53a5960a pbrook
        page_addr &= qemu_host_page_mask;
855 fd6ce8f6 bellard
        prot = 0;
856 53a5960a pbrook
        for(addr = page_addr; addr < page_addr + qemu_host_page_size;
857 53a5960a pbrook
            addr += TARGET_PAGE_SIZE) {
858 53a5960a pbrook
859 53a5960a pbrook
            p2 = page_find (addr >> TARGET_PAGE_BITS);
860 53a5960a pbrook
            if (!p2)
861 53a5960a pbrook
                continue;
862 53a5960a pbrook
            prot |= p2->flags;
863 53a5960a pbrook
            p2->flags &= ~PAGE_WRITE;
864 53a5960a pbrook
            page_get_flags(addr);
865 53a5960a pbrook
          }
866 53a5960a pbrook
        mprotect(g2h(page_addr), qemu_host_page_size, 
867 fd6ce8f6 bellard
                 (prot & PAGE_BITS) & ~PAGE_WRITE);
868 fd6ce8f6 bellard
#ifdef DEBUG_TB_INVALIDATE
869 fd6ce8f6 bellard
        printf("protecting code page: 0x%08lx\n", 
870 53a5960a pbrook
               page_addr);
871 fd6ce8f6 bellard
#endif
872 fd6ce8f6 bellard
    }
873 9fa3e853 bellard
#else
874 9fa3e853 bellard
    /* if some code is already present, then the pages are already
875 9fa3e853 bellard
       protected. So we handle the case where only the first TB is
876 9fa3e853 bellard
       allocated in a physical page */
877 9fa3e853 bellard
    if (!last_first_tb) {
878 6a00d601 bellard
        tlb_protect_code(page_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 c27004ec bellard
TranslationBlock *tb_alloc(target_ulong 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 9fa3e853 bellard
921 d4e8164f bellard
    tb->jmp_first = (TranslationBlock *)((long)tb | 2);
922 d4e8164f bellard
    tb->jmp_next[0] = NULL;
923 d4e8164f bellard
    tb->jmp_next[1] = NULL;
924 b448f2f3 bellard
#ifdef USE_CODE_COPY
925 b448f2f3 bellard
    tb->cflags &= ~CF_FP_USED;
926 b448f2f3 bellard
    if (tb->cflags & CF_TB_FP_USED)
927 b448f2f3 bellard
        tb->cflags |= CF_FP_USED;
928 b448f2f3 bellard
#endif
929 d4e8164f bellard
930 d4e8164f bellard
    /* init original jump addresses */
931 d4e8164f bellard
    if (tb->tb_next_offset[0] != 0xffff)
932 d4e8164f bellard
        tb_reset_jump(tb, 0);
933 d4e8164f bellard
    if (tb->tb_next_offset[1] != 0xffff)
934 d4e8164f bellard
        tb_reset_jump(tb, 1);
935 8a40a180 bellard
936 8a40a180 bellard
#ifdef DEBUG_TB_CHECK
937 8a40a180 bellard
    tb_page_check();
938 8a40a180 bellard
#endif
939 fd6ce8f6 bellard
}
940 fd6ce8f6 bellard
941 9fa3e853 bellard
/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
942 9fa3e853 bellard
   tb[1].tc_ptr. Return NULL if not found */
943 9fa3e853 bellard
TranslationBlock *tb_find_pc(unsigned long tc_ptr)
944 fd6ce8f6 bellard
{
945 9fa3e853 bellard
    int m_min, m_max, m;
946 9fa3e853 bellard
    unsigned long v;
947 9fa3e853 bellard
    TranslationBlock *tb;
948 a513fe19 bellard
949 a513fe19 bellard
    if (nb_tbs <= 0)
950 a513fe19 bellard
        return NULL;
951 a513fe19 bellard
    if (tc_ptr < (unsigned long)code_gen_buffer ||
952 a513fe19 bellard
        tc_ptr >= (unsigned long)code_gen_ptr)
953 a513fe19 bellard
        return NULL;
954 a513fe19 bellard
    /* binary search (cf Knuth) */
955 a513fe19 bellard
    m_min = 0;
956 a513fe19 bellard
    m_max = nb_tbs - 1;
957 a513fe19 bellard
    while (m_min <= m_max) {
958 a513fe19 bellard
        m = (m_min + m_max) >> 1;
959 a513fe19 bellard
        tb = &tbs[m];
960 a513fe19 bellard
        v = (unsigned long)tb->tc_ptr;
961 a513fe19 bellard
        if (v == tc_ptr)
962 a513fe19 bellard
            return tb;
963 a513fe19 bellard
        else if (tc_ptr < v) {
964 a513fe19 bellard
            m_max = m - 1;
965 a513fe19 bellard
        } else {
966 a513fe19 bellard
            m_min = m + 1;
967 a513fe19 bellard
        }
968 a513fe19 bellard
    } 
969 a513fe19 bellard
    return &tbs[m_max];
970 a513fe19 bellard
}
971 7501267e bellard
972 ea041c0e bellard
static void tb_reset_jump_recursive(TranslationBlock *tb);
973 ea041c0e bellard
974 ea041c0e bellard
static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
975 ea041c0e bellard
{
976 ea041c0e bellard
    TranslationBlock *tb1, *tb_next, **ptb;
977 ea041c0e bellard
    unsigned int n1;
978 ea041c0e bellard
979 ea041c0e bellard
    tb1 = tb->jmp_next[n];
980 ea041c0e bellard
    if (tb1 != NULL) {
981 ea041c0e bellard
        /* find head of list */
982 ea041c0e bellard
        for(;;) {
983 ea041c0e bellard
            n1 = (long)tb1 & 3;
984 ea041c0e bellard
            tb1 = (TranslationBlock *)((long)tb1 & ~3);
985 ea041c0e bellard
            if (n1 == 2)
986 ea041c0e bellard
                break;
987 ea041c0e bellard
            tb1 = tb1->jmp_next[n1];
988 ea041c0e bellard
        }
989 ea041c0e bellard
        /* we are now sure now that tb jumps to tb1 */
990 ea041c0e bellard
        tb_next = tb1;
991 ea041c0e bellard
992 ea041c0e bellard
        /* remove tb from the jmp_first list */
993 ea041c0e bellard
        ptb = &tb_next->jmp_first;
994 ea041c0e bellard
        for(;;) {
995 ea041c0e bellard
            tb1 = *ptb;
996 ea041c0e bellard
            n1 = (long)tb1 & 3;
997 ea041c0e bellard
            tb1 = (TranslationBlock *)((long)tb1 & ~3);
998 ea041c0e bellard
            if (n1 == n && tb1 == tb)
999 ea041c0e bellard
                break;
1000 ea041c0e bellard
            ptb = &tb1->jmp_next[n1];
1001 ea041c0e bellard
        }
1002 ea041c0e bellard
        *ptb = tb->jmp_next[n];
1003 ea041c0e bellard
        tb->jmp_next[n] = NULL;
1004 ea041c0e bellard
        
1005 ea041c0e bellard
        /* suppress the jump to next tb in generated code */
1006 ea041c0e bellard
        tb_reset_jump(tb, n);
1007 ea041c0e bellard
1008 0124311e bellard
        /* suppress jumps in the tb on which we could have jumped */
1009 ea041c0e bellard
        tb_reset_jump_recursive(tb_next);
1010 ea041c0e bellard
    }
1011 ea041c0e bellard
}
1012 ea041c0e bellard
1013 ea041c0e bellard
static void tb_reset_jump_recursive(TranslationBlock *tb)
1014 ea041c0e bellard
{
1015 ea041c0e bellard
    tb_reset_jump_recursive2(tb, 0);
1016 ea041c0e bellard
    tb_reset_jump_recursive2(tb, 1);
1017 ea041c0e bellard
}
1018 ea041c0e bellard
1019 1fddef4b bellard
#if defined(TARGET_HAS_ICE)
1020 d720b93d bellard
static void breakpoint_invalidate(CPUState *env, target_ulong pc)
1021 d720b93d bellard
{
1022 c2f07f81 pbrook
    target_ulong addr, pd;
1023 c2f07f81 pbrook
    ram_addr_t ram_addr;
1024 c2f07f81 pbrook
    PhysPageDesc *p;
1025 d720b93d bellard
1026 c2f07f81 pbrook
    addr = cpu_get_phys_page_debug(env, pc);
1027 c2f07f81 pbrook
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
1028 c2f07f81 pbrook
    if (!p) {
1029 c2f07f81 pbrook
        pd = IO_MEM_UNASSIGNED;
1030 c2f07f81 pbrook
    } else {
1031 c2f07f81 pbrook
        pd = p->phys_offset;
1032 c2f07f81 pbrook
    }
1033 c2f07f81 pbrook
    ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
1034 706cd4b5 pbrook
    tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
1035 d720b93d bellard
}
1036 c27004ec bellard
#endif
1037 d720b93d bellard
1038 6658ffb8 pbrook
/* Add a watchpoint.  */
1039 6658ffb8 pbrook
int  cpu_watchpoint_insert(CPUState *env, target_ulong addr)
1040 6658ffb8 pbrook
{
1041 6658ffb8 pbrook
    int i;
1042 6658ffb8 pbrook
1043 6658ffb8 pbrook
    for (i = 0; i < env->nb_watchpoints; i++) {
1044 6658ffb8 pbrook
        if (addr == env->watchpoint[i].vaddr)
1045 6658ffb8 pbrook
            return 0;
1046 6658ffb8 pbrook
    }
1047 6658ffb8 pbrook
    if (env->nb_watchpoints >= MAX_WATCHPOINTS)
1048 6658ffb8 pbrook
        return -1;
1049 6658ffb8 pbrook
1050 6658ffb8 pbrook
    i = env->nb_watchpoints++;
1051 6658ffb8 pbrook
    env->watchpoint[i].vaddr = addr;
1052 6658ffb8 pbrook
    tlb_flush_page(env, addr);
1053 6658ffb8 pbrook
    /* FIXME: This flush is needed because of the hack to make memory ops
1054 6658ffb8 pbrook
       terminate the TB.  It can be removed once the proper IO trap and
1055 6658ffb8 pbrook
       re-execute bits are in.  */
1056 6658ffb8 pbrook
    tb_flush(env);
1057 6658ffb8 pbrook
    return i;
1058 6658ffb8 pbrook
}
1059 6658ffb8 pbrook
1060 6658ffb8 pbrook
/* Remove a watchpoint.  */
1061 6658ffb8 pbrook
int cpu_watchpoint_remove(CPUState *env, target_ulong addr)
1062 6658ffb8 pbrook
{
1063 6658ffb8 pbrook
    int i;
1064 6658ffb8 pbrook
1065 6658ffb8 pbrook
    for (i = 0; i < env->nb_watchpoints; i++) {
1066 6658ffb8 pbrook
        if (addr == env->watchpoint[i].vaddr) {
1067 6658ffb8 pbrook
            env->nb_watchpoints--;
1068 6658ffb8 pbrook
            env->watchpoint[i] = env->watchpoint[env->nb_watchpoints];
1069 6658ffb8 pbrook
            tlb_flush_page(env, addr);
1070 6658ffb8 pbrook
            return 0;
1071 6658ffb8 pbrook
        }
1072 6658ffb8 pbrook
    }
1073 6658ffb8 pbrook
    return -1;
1074 6658ffb8 pbrook
}
1075 6658ffb8 pbrook
1076 c33a346e bellard
/* add a breakpoint. EXCP_DEBUG is returned by the CPU loop if a
1077 c33a346e bellard
   breakpoint is reached */
1078 2e12669a bellard
int cpu_breakpoint_insert(CPUState *env, target_ulong pc)
1079 4c3a88a2 bellard
{
1080 1fddef4b bellard
#if defined(TARGET_HAS_ICE)
1081 4c3a88a2 bellard
    int i;
1082 d720b93d bellard
    
1083 4c3a88a2 bellard
    for(i = 0; i < env->nb_breakpoints; i++) {
1084 4c3a88a2 bellard
        if (env->breakpoints[i] == pc)
1085 4c3a88a2 bellard
            return 0;
1086 4c3a88a2 bellard
    }
1087 4c3a88a2 bellard
1088 4c3a88a2 bellard
    if (env->nb_breakpoints >= MAX_BREAKPOINTS)
1089 4c3a88a2 bellard
        return -1;
1090 4c3a88a2 bellard
    env->breakpoints[env->nb_breakpoints++] = pc;
1091 d720b93d bellard
    
1092 d720b93d bellard
    breakpoint_invalidate(env, pc);
1093 4c3a88a2 bellard
    return 0;
1094 4c3a88a2 bellard
#else
1095 4c3a88a2 bellard
    return -1;
1096 4c3a88a2 bellard
#endif
1097 4c3a88a2 bellard
}
1098 4c3a88a2 bellard
1099 4c3a88a2 bellard
/* remove a breakpoint */
1100 2e12669a bellard
int cpu_breakpoint_remove(CPUState *env, target_ulong pc)
1101 4c3a88a2 bellard
{
1102 1fddef4b bellard
#if defined(TARGET_HAS_ICE)
1103 4c3a88a2 bellard
    int i;
1104 4c3a88a2 bellard
    for(i = 0; i < env->nb_breakpoints; i++) {
1105 4c3a88a2 bellard
        if (env->breakpoints[i] == pc)
1106 4c3a88a2 bellard
            goto found;
1107 4c3a88a2 bellard
    }
1108 4c3a88a2 bellard
    return -1;
1109 4c3a88a2 bellard
 found:
1110 4c3a88a2 bellard
    env->nb_breakpoints--;
1111 1fddef4b bellard
    if (i < env->nb_breakpoints)
1112 1fddef4b bellard
      env->breakpoints[i] = env->breakpoints[env->nb_breakpoints];
1113 d720b93d bellard
1114 d720b93d bellard
    breakpoint_invalidate(env, pc);
1115 4c3a88a2 bellard
    return 0;
1116 4c3a88a2 bellard
#else
1117 4c3a88a2 bellard
    return -1;
1118 4c3a88a2 bellard
#endif
1119 4c3a88a2 bellard
}
1120 4c3a88a2 bellard
1121 c33a346e bellard
/* enable or disable single step mode. EXCP_DEBUG is returned by the
1122 c33a346e bellard
   CPU loop after each instruction */
1123 c33a346e bellard
void cpu_single_step(CPUState *env, int enabled)
1124 c33a346e bellard
{
1125 1fddef4b bellard
#if defined(TARGET_HAS_ICE)
1126 c33a346e bellard
    if (env->singlestep_enabled != enabled) {
1127 c33a346e bellard
        env->singlestep_enabled = enabled;
1128 c33a346e bellard
        /* must flush all the translated code to avoid inconsistancies */
1129 9fa3e853 bellard
        /* XXX: only flush what is necessary */
1130 0124311e bellard
        tb_flush(env);
1131 c33a346e bellard
    }
1132 c33a346e bellard
#endif
1133 c33a346e bellard
}
1134 c33a346e bellard
1135 34865134 bellard
/* enable or disable low levels log */
1136 34865134 bellard
void cpu_set_log(int log_flags)
1137 34865134 bellard
{
1138 34865134 bellard
    loglevel = log_flags;
1139 34865134 bellard
    if (loglevel && !logfile) {
1140 34865134 bellard
        logfile = fopen(logfilename, "w");
1141 34865134 bellard
        if (!logfile) {
1142 34865134 bellard
            perror(logfilename);
1143 34865134 bellard
            _exit(1);
1144 34865134 bellard
        }
1145 9fa3e853 bellard
#if !defined(CONFIG_SOFTMMU)
1146 9fa3e853 bellard
        /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1147 9fa3e853 bellard
        {
1148 9fa3e853 bellard
            static uint8_t logfile_buf[4096];
1149 9fa3e853 bellard
            setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1150 9fa3e853 bellard
        }
1151 9fa3e853 bellard
#else
1152 34865134 bellard
        setvbuf(logfile, NULL, _IOLBF, 0);
1153 9fa3e853 bellard
#endif
1154 34865134 bellard
    }
1155 34865134 bellard
}
1156 34865134 bellard
1157 34865134 bellard
void cpu_set_log_filename(const char *filename)
1158 34865134 bellard
{
1159 34865134 bellard
    logfilename = strdup(filename);
1160 34865134 bellard
}
1161 c33a346e bellard
1162 0124311e bellard
/* mask must never be zero, except for A20 change call */
1163 68a79315 bellard
void cpu_interrupt(CPUState *env, int mask)
1164 ea041c0e bellard
{
1165 ea041c0e bellard
    TranslationBlock *tb;
1166 ee8b7021 bellard
    static int interrupt_lock;
1167 59817ccb bellard
1168 68a79315 bellard
    env->interrupt_request |= mask;
1169 ea041c0e bellard
    /* if the cpu is currently executing code, we must unlink it and
1170 ea041c0e bellard
       all the potentially executing TB */
1171 ea041c0e bellard
    tb = env->current_tb;
1172 ee8b7021 bellard
    if (tb && !testandset(&interrupt_lock)) {
1173 ee8b7021 bellard
        env->current_tb = NULL;
1174 ea041c0e bellard
        tb_reset_jump_recursive(tb);
1175 ee8b7021 bellard
        interrupt_lock = 0;
1176 ea041c0e bellard
    }
1177 ea041c0e bellard
}
1178 ea041c0e bellard
1179 b54ad049 bellard
void cpu_reset_interrupt(CPUState *env, int mask)
1180 b54ad049 bellard
{
1181 b54ad049 bellard
    env->interrupt_request &= ~mask;
1182 b54ad049 bellard
}
1183 b54ad049 bellard
1184 f193c797 bellard
CPULogItem cpu_log_items[] = {
1185 f193c797 bellard
    { CPU_LOG_TB_OUT_ASM, "out_asm", 
1186 f193c797 bellard
      "show generated host assembly code for each compiled TB" },
1187 f193c797 bellard
    { CPU_LOG_TB_IN_ASM, "in_asm",
1188 f193c797 bellard
      "show target assembly code for each compiled TB" },
1189 f193c797 bellard
    { CPU_LOG_TB_OP, "op", 
1190 f193c797 bellard
      "show micro ops for each compiled TB (only usable if 'in_asm' used)" },
1191 f193c797 bellard
#ifdef TARGET_I386
1192 f193c797 bellard
    { CPU_LOG_TB_OP_OPT, "op_opt",
1193 f193c797 bellard
      "show micro ops after optimization for each compiled TB" },
1194 f193c797 bellard
#endif
1195 f193c797 bellard
    { CPU_LOG_INT, "int",
1196 f193c797 bellard
      "show interrupts/exceptions in short format" },
1197 f193c797 bellard
    { CPU_LOG_EXEC, "exec",
1198 f193c797 bellard
      "show trace before each executed TB (lots of logs)" },
1199 9fddaa0c bellard
    { CPU_LOG_TB_CPU, "cpu",
1200 9fddaa0c bellard
      "show CPU state before bloc translation" },
1201 f193c797 bellard
#ifdef TARGET_I386
1202 f193c797 bellard
    { CPU_LOG_PCALL, "pcall",
1203 f193c797 bellard
      "show protected mode far calls/returns/exceptions" },
1204 f193c797 bellard
#endif
1205 8e3a9fd2 bellard
#ifdef DEBUG_IOPORT
1206 fd872598 bellard
    { CPU_LOG_IOPORT, "ioport",
1207 fd872598 bellard
      "show all i/o ports accesses" },
1208 8e3a9fd2 bellard
#endif
1209 f193c797 bellard
    { 0, NULL, NULL },
1210 f193c797 bellard
};
1211 f193c797 bellard
1212 f193c797 bellard
static int cmp1(const char *s1, int n, const char *s2)
1213 f193c797 bellard
{
1214 f193c797 bellard
    if (strlen(s2) != n)
1215 f193c797 bellard
        return 0;
1216 f193c797 bellard
    return memcmp(s1, s2, n) == 0;
1217 f193c797 bellard
}
1218 f193c797 bellard
      
1219 f193c797 bellard
/* takes a comma separated list of log masks. Return 0 if error. */
1220 f193c797 bellard
int cpu_str_to_log_mask(const char *str)
1221 f193c797 bellard
{
1222 f193c797 bellard
    CPULogItem *item;
1223 f193c797 bellard
    int mask;
1224 f193c797 bellard
    const char *p, *p1;
1225 f193c797 bellard
1226 f193c797 bellard
    p = str;
1227 f193c797 bellard
    mask = 0;
1228 f193c797 bellard
    for(;;) {
1229 f193c797 bellard
        p1 = strchr(p, ',');
1230 f193c797 bellard
        if (!p1)
1231 f193c797 bellard
            p1 = p + strlen(p);
1232 8e3a9fd2 bellard
        if(cmp1(p,p1-p,"all")) {
1233 8e3a9fd2 bellard
                for(item = cpu_log_items; item->mask != 0; item++) {
1234 8e3a9fd2 bellard
                        mask |= item->mask;
1235 8e3a9fd2 bellard
                }
1236 8e3a9fd2 bellard
        } else {
1237 f193c797 bellard
        for(item = cpu_log_items; item->mask != 0; item++) {
1238 f193c797 bellard
            if (cmp1(p, p1 - p, item->name))
1239 f193c797 bellard
                goto found;
1240 f193c797 bellard
        }
1241 f193c797 bellard
        return 0;
1242 8e3a9fd2 bellard
        }
1243 f193c797 bellard
    found:
1244 f193c797 bellard
        mask |= item->mask;
1245 f193c797 bellard
        if (*p1 != ',')
1246 f193c797 bellard
            break;
1247 f193c797 bellard
        p = p1 + 1;
1248 f193c797 bellard
    }
1249 f193c797 bellard
    return mask;
1250 f193c797 bellard
}
1251 ea041c0e bellard
1252 7501267e bellard
void cpu_abort(CPUState *env, const char *fmt, ...)
1253 7501267e bellard
{
1254 7501267e bellard
    va_list ap;
1255 7501267e bellard
1256 7501267e bellard
    va_start(ap, fmt);
1257 7501267e bellard
    fprintf(stderr, "qemu: fatal: ");
1258 7501267e bellard
    vfprintf(stderr, fmt, ap);
1259 7501267e bellard
    fprintf(stderr, "\n");
1260 7501267e bellard
#ifdef TARGET_I386
1261 7fe48483 bellard
    cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1262 7fe48483 bellard
#else
1263 7fe48483 bellard
    cpu_dump_state(env, stderr, fprintf, 0);
1264 7501267e bellard
#endif
1265 7501267e bellard
    va_end(ap);
1266 7501267e bellard
    abort();
1267 7501267e bellard
}
1268 7501267e bellard
1269 c5be9f08 ths
CPUState *cpu_copy(CPUState *env)
1270 c5be9f08 ths
{
1271 c5be9f08 ths
    CPUState *new_env = cpu_init();
1272 c5be9f08 ths
    /* preserve chaining and index */
1273 c5be9f08 ths
    CPUState *next_cpu = new_env->next_cpu;
1274 c5be9f08 ths
    int cpu_index = new_env->cpu_index;
1275 c5be9f08 ths
    memcpy(new_env, env, sizeof(CPUState));
1276 c5be9f08 ths
    new_env->next_cpu = next_cpu;
1277 c5be9f08 ths
    new_env->cpu_index = cpu_index;
1278 c5be9f08 ths
    return new_env;
1279 c5be9f08 ths
}
1280 c5be9f08 ths
1281 0124311e bellard
#if !defined(CONFIG_USER_ONLY)
1282 0124311e bellard
1283 ee8b7021 bellard
/* NOTE: if flush_global is true, also flush global entries (not
1284 ee8b7021 bellard
   implemented yet) */
1285 ee8b7021 bellard
void tlb_flush(CPUState *env, int flush_global)
1286 33417e70 bellard
{
1287 33417e70 bellard
    int i;
1288 0124311e bellard
1289 9fa3e853 bellard
#if defined(DEBUG_TLB)
1290 9fa3e853 bellard
    printf("tlb_flush:\n");
1291 9fa3e853 bellard
#endif
1292 0124311e bellard
    /* must reset current TB so that interrupts cannot modify the
1293 0124311e bellard
       links while we are modifying them */
1294 0124311e bellard
    env->current_tb = NULL;
1295 0124311e bellard
1296 33417e70 bellard
    for(i = 0; i < CPU_TLB_SIZE; i++) {
1297 84b7b8e7 bellard
        env->tlb_table[0][i].addr_read = -1;
1298 84b7b8e7 bellard
        env->tlb_table[0][i].addr_write = -1;
1299 84b7b8e7 bellard
        env->tlb_table[0][i].addr_code = -1;
1300 84b7b8e7 bellard
        env->tlb_table[1][i].addr_read = -1;
1301 84b7b8e7 bellard
        env->tlb_table[1][i].addr_write = -1;
1302 84b7b8e7 bellard
        env->tlb_table[1][i].addr_code = -1;
1303 33417e70 bellard
    }
1304 9fa3e853 bellard
1305 8a40a180 bellard
    memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
1306 9fa3e853 bellard
1307 9fa3e853 bellard
#if !defined(CONFIG_SOFTMMU)
1308 9fa3e853 bellard
    munmap((void *)MMAP_AREA_START, MMAP_AREA_END - MMAP_AREA_START);
1309 9fa3e853 bellard
#endif
1310 0a962c02 bellard
#ifdef USE_KQEMU
1311 0a962c02 bellard
    if (env->kqemu_enabled) {
1312 0a962c02 bellard
        kqemu_flush(env, flush_global);
1313 0a962c02 bellard
    }
1314 0a962c02 bellard
#endif
1315 e3db7226 bellard
    tlb_flush_count++;
1316 33417e70 bellard
}
1317 33417e70 bellard
1318 274da6b2 bellard
static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
1319 61382a50 bellard
{
1320 84b7b8e7 bellard
    if (addr == (tlb_entry->addr_read & 
1321 84b7b8e7 bellard
                 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1322 84b7b8e7 bellard
        addr == (tlb_entry->addr_write & 
1323 84b7b8e7 bellard
                 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1324 84b7b8e7 bellard
        addr == (tlb_entry->addr_code & 
1325 84b7b8e7 bellard
                 (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1326 84b7b8e7 bellard
        tlb_entry->addr_read = -1;
1327 84b7b8e7 bellard
        tlb_entry->addr_write = -1;
1328 84b7b8e7 bellard
        tlb_entry->addr_code = -1;
1329 84b7b8e7 bellard
    }
1330 61382a50 bellard
}
1331 61382a50 bellard
1332 2e12669a bellard
void tlb_flush_page(CPUState *env, target_ulong addr)
1333 33417e70 bellard
{
1334 8a40a180 bellard
    int i;
1335 9fa3e853 bellard
    TranslationBlock *tb;
1336 0124311e bellard
1337 9fa3e853 bellard
#if defined(DEBUG_TLB)
1338 108c49b8 bellard
    printf("tlb_flush_page: " TARGET_FMT_lx "\n", addr);
1339 9fa3e853 bellard
#endif
1340 0124311e bellard
    /* must reset current TB so that interrupts cannot modify the
1341 0124311e bellard
       links while we are modifying them */
1342 0124311e bellard
    env->current_tb = NULL;
1343 61382a50 bellard
1344 61382a50 bellard
    addr &= TARGET_PAGE_MASK;
1345 61382a50 bellard
    i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1346 84b7b8e7 bellard
    tlb_flush_entry(&env->tlb_table[0][i], addr);
1347 84b7b8e7 bellard
    tlb_flush_entry(&env->tlb_table[1][i], addr);
1348 0124311e bellard
1349 b362e5e0 pbrook
    /* Discard jump cache entries for any tb which might potentially
1350 b362e5e0 pbrook
       overlap the flushed page.  */
1351 b362e5e0 pbrook
    i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
1352 b362e5e0 pbrook
    memset (&env->tb_jmp_cache[i], 0, TB_JMP_PAGE_SIZE * sizeof(tb));
1353 b362e5e0 pbrook
1354 b362e5e0 pbrook
    i = tb_jmp_cache_hash_page(addr);
1355 b362e5e0 pbrook
    memset (&env->tb_jmp_cache[i], 0, TB_JMP_PAGE_SIZE * sizeof(tb));
1356 9fa3e853 bellard
1357 0124311e bellard
#if !defined(CONFIG_SOFTMMU)
1358 9fa3e853 bellard
    if (addr < MMAP_AREA_END)
1359 0124311e bellard
        munmap((void *)addr, TARGET_PAGE_SIZE);
1360 61382a50 bellard
#endif
1361 0a962c02 bellard
#ifdef USE_KQEMU
1362 0a962c02 bellard
    if (env->kqemu_enabled) {
1363 0a962c02 bellard
        kqemu_flush_page(env, addr);
1364 0a962c02 bellard
    }
1365 0a962c02 bellard
#endif
1366 9fa3e853 bellard
}
1367 9fa3e853 bellard
1368 9fa3e853 bellard
/* update the TLBs so that writes to code in the virtual page 'addr'
1369 9fa3e853 bellard
   can be detected */
1370 6a00d601 bellard
static void tlb_protect_code(ram_addr_t ram_addr)
1371 9fa3e853 bellard
{
1372 6a00d601 bellard
    cpu_physical_memory_reset_dirty(ram_addr, 
1373 6a00d601 bellard
                                    ram_addr + TARGET_PAGE_SIZE,
1374 6a00d601 bellard
                                    CODE_DIRTY_FLAG);
1375 9fa3e853 bellard
}
1376 9fa3e853 bellard
1377 9fa3e853 bellard
/* update the TLB so that writes in physical page 'phys_addr' are no longer
1378 3a7d929e bellard
   tested for self modifying code */
1379 3a7d929e bellard
static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr, 
1380 3a7d929e bellard
                                    target_ulong vaddr)
1381 9fa3e853 bellard
{
1382 3a7d929e bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] |= CODE_DIRTY_FLAG;
1383 1ccde1cb bellard
}
1384 1ccde1cb bellard
1385 1ccde1cb bellard
static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, 
1386 1ccde1cb bellard
                                         unsigned long start, unsigned long length)
1387 1ccde1cb bellard
{
1388 1ccde1cb bellard
    unsigned long addr;
1389 84b7b8e7 bellard
    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1390 84b7b8e7 bellard
        addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
1391 1ccde1cb bellard
        if ((addr - start) < length) {
1392 84b7b8e7 bellard
            tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | IO_MEM_NOTDIRTY;
1393 1ccde1cb bellard
        }
1394 1ccde1cb bellard
    }
1395 1ccde1cb bellard
}
1396 1ccde1cb bellard
1397 3a7d929e bellard
void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
1398 0a962c02 bellard
                                     int dirty_flags)
1399 1ccde1cb bellard
{
1400 1ccde1cb bellard
    CPUState *env;
1401 4f2ac237 bellard
    unsigned long length, start1;
1402 0a962c02 bellard
    int i, mask, len;
1403 0a962c02 bellard
    uint8_t *p;
1404 1ccde1cb bellard
1405 1ccde1cb bellard
    start &= TARGET_PAGE_MASK;
1406 1ccde1cb bellard
    end = TARGET_PAGE_ALIGN(end);
1407 1ccde1cb bellard
1408 1ccde1cb bellard
    length = end - start;
1409 1ccde1cb bellard
    if (length == 0)
1410 1ccde1cb bellard
        return;
1411 0a962c02 bellard
    len = length >> TARGET_PAGE_BITS;
1412 3a7d929e bellard
#ifdef USE_KQEMU
1413 6a00d601 bellard
    /* XXX: should not depend on cpu context */
1414 6a00d601 bellard
    env = first_cpu;
1415 3a7d929e bellard
    if (env->kqemu_enabled) {
1416 f23db169 bellard
        ram_addr_t addr;
1417 f23db169 bellard
        addr = start;
1418 f23db169 bellard
        for(i = 0; i < len; i++) {
1419 f23db169 bellard
            kqemu_set_notdirty(env, addr);
1420 f23db169 bellard
            addr += TARGET_PAGE_SIZE;
1421 f23db169 bellard
        }
1422 3a7d929e bellard
    }
1423 3a7d929e bellard
#endif
1424 f23db169 bellard
    mask = ~dirty_flags;
1425 f23db169 bellard
    p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
1426 f23db169 bellard
    for(i = 0; i < len; i++)
1427 f23db169 bellard
        p[i] &= mask;
1428 f23db169 bellard
1429 1ccde1cb bellard
    /* we modify the TLB cache so that the dirty bit will be set again
1430 1ccde1cb bellard
       when accessing the range */
1431 59817ccb bellard
    start1 = start + (unsigned long)phys_ram_base;
1432 6a00d601 bellard
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
1433 6a00d601 bellard
        for(i = 0; i < CPU_TLB_SIZE; i++)
1434 84b7b8e7 bellard
            tlb_reset_dirty_range(&env->tlb_table[0][i], start1, length);
1435 6a00d601 bellard
        for(i = 0; i < CPU_TLB_SIZE; i++)
1436 84b7b8e7 bellard
            tlb_reset_dirty_range(&env->tlb_table[1][i], start1, length);
1437 6a00d601 bellard
    }
1438 59817ccb bellard
1439 59817ccb bellard
#if !defined(CONFIG_SOFTMMU)
1440 59817ccb bellard
    /* XXX: this is expensive */
1441 59817ccb bellard
    {
1442 59817ccb bellard
        VirtPageDesc *p;
1443 59817ccb bellard
        int j;
1444 59817ccb bellard
        target_ulong addr;
1445 59817ccb bellard
1446 59817ccb bellard
        for(i = 0; i < L1_SIZE; i++) {
1447 59817ccb bellard
            p = l1_virt_map[i];
1448 59817ccb bellard
            if (p) {
1449 59817ccb bellard
                addr = i << (TARGET_PAGE_BITS + L2_BITS);
1450 59817ccb bellard
                for(j = 0; j < L2_SIZE; j++) {
1451 59817ccb bellard
                    if (p->valid_tag == virt_valid_tag &&
1452 59817ccb bellard
                        p->phys_addr >= start && p->phys_addr < end &&
1453 59817ccb bellard
                        (p->prot & PROT_WRITE)) {
1454 59817ccb bellard
                        if (addr < MMAP_AREA_END) {
1455 59817ccb bellard
                            mprotect((void *)addr, TARGET_PAGE_SIZE, 
1456 59817ccb bellard
                                     p->prot & ~PROT_WRITE);
1457 59817ccb bellard
                        }
1458 59817ccb bellard
                    }
1459 59817ccb bellard
                    addr += TARGET_PAGE_SIZE;
1460 59817ccb bellard
                    p++;
1461 59817ccb bellard
                }
1462 59817ccb bellard
            }
1463 59817ccb bellard
        }
1464 59817ccb bellard
    }
1465 59817ccb bellard
#endif
1466 1ccde1cb bellard
}
1467 1ccde1cb bellard
1468 3a7d929e bellard
static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1469 3a7d929e bellard
{
1470 3a7d929e bellard
    ram_addr_t ram_addr;
1471 3a7d929e bellard
1472 84b7b8e7 bellard
    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1473 84b7b8e7 bellard
        ram_addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + 
1474 3a7d929e bellard
            tlb_entry->addend - (unsigned long)phys_ram_base;
1475 3a7d929e bellard
        if (!cpu_physical_memory_is_dirty(ram_addr)) {
1476 84b7b8e7 bellard
            tlb_entry->addr_write |= IO_MEM_NOTDIRTY;
1477 3a7d929e bellard
        }
1478 3a7d929e bellard
    }
1479 3a7d929e bellard
}
1480 3a7d929e bellard
1481 3a7d929e bellard
/* update the TLB according to the current state of the dirty bits */
1482 3a7d929e bellard
void cpu_tlb_update_dirty(CPUState *env)
1483 3a7d929e bellard
{
1484 3a7d929e bellard
    int i;
1485 3a7d929e bellard
    for(i = 0; i < CPU_TLB_SIZE; i++)
1486 84b7b8e7 bellard
        tlb_update_dirty(&env->tlb_table[0][i]);
1487 3a7d929e bellard
    for(i = 0; i < CPU_TLB_SIZE; i++)
1488 84b7b8e7 bellard
        tlb_update_dirty(&env->tlb_table[1][i]);
1489 3a7d929e bellard
}
1490 3a7d929e bellard
1491 1ccde1cb bellard
static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, 
1492 108c49b8 bellard
                                  unsigned long start)
1493 1ccde1cb bellard
{
1494 1ccde1cb bellard
    unsigned long addr;
1495 84b7b8e7 bellard
    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_NOTDIRTY) {
1496 84b7b8e7 bellard
        addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
1497 1ccde1cb bellard
        if (addr == start) {
1498 84b7b8e7 bellard
            tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | IO_MEM_RAM;
1499 1ccde1cb bellard
        }
1500 1ccde1cb bellard
    }
1501 1ccde1cb bellard
}
1502 1ccde1cb bellard
1503 1ccde1cb bellard
/* update the TLB corresponding to virtual page vaddr and phys addr
1504 1ccde1cb bellard
   addr so that it is no longer dirty */
1505 6a00d601 bellard
static inline void tlb_set_dirty(CPUState *env,
1506 6a00d601 bellard
                                 unsigned long addr, target_ulong vaddr)
1507 1ccde1cb bellard
{
1508 1ccde1cb bellard
    int i;
1509 1ccde1cb bellard
1510 1ccde1cb bellard
    addr &= TARGET_PAGE_MASK;
1511 1ccde1cb bellard
    i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1512 84b7b8e7 bellard
    tlb_set_dirty1(&env->tlb_table[0][i], addr);
1513 84b7b8e7 bellard
    tlb_set_dirty1(&env->tlb_table[1][i], addr);
1514 9fa3e853 bellard
}
1515 9fa3e853 bellard
1516 59817ccb bellard
/* add a new TLB entry. At most one entry for a given virtual address
1517 59817ccb bellard
   is permitted. Return 0 if OK or 2 if the page could not be mapped
1518 59817ccb bellard
   (can only happen in non SOFTMMU mode for I/O pages or pages
1519 59817ccb bellard
   conflicting with the host address space). */
1520 84b7b8e7 bellard
int tlb_set_page_exec(CPUState *env, target_ulong vaddr, 
1521 84b7b8e7 bellard
                      target_phys_addr_t paddr, int prot, 
1522 84b7b8e7 bellard
                      int is_user, int is_softmmu)
1523 9fa3e853 bellard
{
1524 92e873b9 bellard
    PhysPageDesc *p;
1525 4f2ac237 bellard
    unsigned long pd;
1526 9fa3e853 bellard
    unsigned int index;
1527 4f2ac237 bellard
    target_ulong address;
1528 108c49b8 bellard
    target_phys_addr_t addend;
1529 9fa3e853 bellard
    int ret;
1530 84b7b8e7 bellard
    CPUTLBEntry *te;
1531 6658ffb8 pbrook
    int i;
1532 9fa3e853 bellard
1533 92e873b9 bellard
    p = phys_page_find(paddr >> TARGET_PAGE_BITS);
1534 9fa3e853 bellard
    if (!p) {
1535 9fa3e853 bellard
        pd = IO_MEM_UNASSIGNED;
1536 9fa3e853 bellard
    } else {
1537 9fa3e853 bellard
        pd = p->phys_offset;
1538 9fa3e853 bellard
    }
1539 9fa3e853 bellard
#if defined(DEBUG_TLB)
1540 3a7d929e bellard
    printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x u=%d smmu=%d pd=0x%08lx\n",
1541 84b7b8e7 bellard
           vaddr, (int)paddr, prot, is_user, is_softmmu, pd);
1542 9fa3e853 bellard
#endif
1543 9fa3e853 bellard
1544 9fa3e853 bellard
    ret = 0;
1545 9fa3e853 bellard
#if !defined(CONFIG_SOFTMMU)
1546 9fa3e853 bellard
    if (is_softmmu) 
1547 9fa3e853 bellard
#endif
1548 9fa3e853 bellard
    {
1549 2a4188a3 bellard
        if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
1550 9fa3e853 bellard
            /* IO memory case */
1551 9fa3e853 bellard
            address = vaddr | pd;
1552 9fa3e853 bellard
            addend = paddr;
1553 9fa3e853 bellard
        } else {
1554 9fa3e853 bellard
            /* standard memory */
1555 9fa3e853 bellard
            address = vaddr;
1556 9fa3e853 bellard
            addend = (unsigned long)phys_ram_base + (pd & TARGET_PAGE_MASK);
1557 9fa3e853 bellard
        }
1558 6658ffb8 pbrook
1559 6658ffb8 pbrook
        /* Make accesses to pages with watchpoints go via the
1560 6658ffb8 pbrook
           watchpoint trap routines.  */
1561 6658ffb8 pbrook
        for (i = 0; i < env->nb_watchpoints; i++) {
1562 6658ffb8 pbrook
            if (vaddr == (env->watchpoint[i].vaddr & TARGET_PAGE_MASK)) {
1563 6658ffb8 pbrook
                if (address & ~TARGET_PAGE_MASK) {
1564 6658ffb8 pbrook
                    env->watchpoint[i].is_ram = 0;
1565 6658ffb8 pbrook
                    address = vaddr | io_mem_watch;
1566 6658ffb8 pbrook
                } else {
1567 6658ffb8 pbrook
                    env->watchpoint[i].is_ram = 1;
1568 6658ffb8 pbrook
                    /* TODO: Figure out how to make read watchpoints coexist
1569 6658ffb8 pbrook
                       with code.  */
1570 6658ffb8 pbrook
                    pd = (pd & TARGET_PAGE_MASK) | io_mem_watch | IO_MEM_ROMD;
1571 6658ffb8 pbrook
                }
1572 6658ffb8 pbrook
            }
1573 6658ffb8 pbrook
        }
1574 9fa3e853 bellard
        
1575 90f18422 bellard
        index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1576 9fa3e853 bellard
        addend -= vaddr;
1577 84b7b8e7 bellard
        te = &env->tlb_table[is_user][index];
1578 84b7b8e7 bellard
        te->addend = addend;
1579 67b915a5 bellard
        if (prot & PAGE_READ) {
1580 84b7b8e7 bellard
            te->addr_read = address;
1581 84b7b8e7 bellard
        } else {
1582 84b7b8e7 bellard
            te->addr_read = -1;
1583 84b7b8e7 bellard
        }
1584 84b7b8e7 bellard
        if (prot & PAGE_EXEC) {
1585 84b7b8e7 bellard
            te->addr_code = address;
1586 9fa3e853 bellard
        } else {
1587 84b7b8e7 bellard
            te->addr_code = -1;
1588 9fa3e853 bellard
        }
1589 67b915a5 bellard
        if (prot & PAGE_WRITE) {
1590 856074ec bellard
            if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM || 
1591 856074ec bellard
                (pd & IO_MEM_ROMD)) {
1592 856074ec bellard
                /* write access calls the I/O callback */
1593 856074ec bellard
                te->addr_write = vaddr | 
1594 856074ec bellard
                    (pd & ~(TARGET_PAGE_MASK | IO_MEM_ROMD));
1595 3a7d929e bellard
            } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM && 
1596 1ccde1cb bellard
                       !cpu_physical_memory_is_dirty(pd)) {
1597 84b7b8e7 bellard
                te->addr_write = vaddr | IO_MEM_NOTDIRTY;
1598 9fa3e853 bellard
            } else {
1599 84b7b8e7 bellard
                te->addr_write = address;
1600 9fa3e853 bellard
            }
1601 9fa3e853 bellard
        } else {
1602 84b7b8e7 bellard
            te->addr_write = -1;
1603 9fa3e853 bellard
        }
1604 9fa3e853 bellard
    }
1605 9fa3e853 bellard
#if !defined(CONFIG_SOFTMMU)
1606 9fa3e853 bellard
    else {
1607 9fa3e853 bellard
        if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
1608 9fa3e853 bellard
            /* IO access: no mapping is done as it will be handled by the
1609 9fa3e853 bellard
               soft MMU */
1610 9fa3e853 bellard
            if (!(env->hflags & HF_SOFTMMU_MASK))
1611 9fa3e853 bellard
                ret = 2;
1612 9fa3e853 bellard
        } else {
1613 9fa3e853 bellard
            void *map_addr;
1614 59817ccb bellard
1615 59817ccb bellard
            if (vaddr >= MMAP_AREA_END) {
1616 59817ccb bellard
                ret = 2;
1617 59817ccb bellard
            } else {
1618 59817ccb bellard
                if (prot & PROT_WRITE) {
1619 59817ccb bellard
                    if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM || 
1620 d720b93d bellard
#if defined(TARGET_HAS_SMC) || 1
1621 59817ccb bellard
                        first_tb ||
1622 d720b93d bellard
#endif
1623 59817ccb bellard
                        ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM && 
1624 59817ccb bellard
                         !cpu_physical_memory_is_dirty(pd))) {
1625 59817ccb bellard
                        /* ROM: we do as if code was inside */
1626 59817ccb bellard
                        /* if code is present, we only map as read only and save the
1627 59817ccb bellard
                           original mapping */
1628 59817ccb bellard
                        VirtPageDesc *vp;
1629 59817ccb bellard
                        
1630 90f18422 bellard
                        vp = virt_page_find_alloc(vaddr >> TARGET_PAGE_BITS, 1);
1631 59817ccb bellard
                        vp->phys_addr = pd;
1632 59817ccb bellard
                        vp->prot = prot;
1633 59817ccb bellard
                        vp->valid_tag = virt_valid_tag;
1634 59817ccb bellard
                        prot &= ~PAGE_WRITE;
1635 59817ccb bellard
                    }
1636 59817ccb bellard
                }
1637 59817ccb bellard
                map_addr = mmap((void *)vaddr, TARGET_PAGE_SIZE, prot, 
1638 59817ccb bellard
                                MAP_SHARED | MAP_FIXED, phys_ram_fd, (pd & TARGET_PAGE_MASK));
1639 59817ccb bellard
                if (map_addr == MAP_FAILED) {
1640 59817ccb bellard
                    cpu_abort(env, "mmap failed when mapped physical address 0x%08x to virtual address 0x%08x\n",
1641 59817ccb bellard
                              paddr, vaddr);
1642 9fa3e853 bellard
                }
1643 9fa3e853 bellard
            }
1644 9fa3e853 bellard
        }
1645 9fa3e853 bellard
    }
1646 9fa3e853 bellard
#endif
1647 9fa3e853 bellard
    return ret;
1648 9fa3e853 bellard
}
1649 9fa3e853 bellard
1650 9fa3e853 bellard
/* called from signal handler: invalidate the code and unprotect the
1651 9fa3e853 bellard
   page. Return TRUE if the fault was succesfully handled. */
1652 53a5960a pbrook
int page_unprotect(target_ulong addr, unsigned long pc, void *puc)
1653 9fa3e853 bellard
{
1654 9fa3e853 bellard
#if !defined(CONFIG_SOFTMMU)
1655 9fa3e853 bellard
    VirtPageDesc *vp;
1656 9fa3e853 bellard
1657 9fa3e853 bellard
#if defined(DEBUG_TLB)
1658 9fa3e853 bellard
    printf("page_unprotect: addr=0x%08x\n", addr);
1659 9fa3e853 bellard
#endif
1660 9fa3e853 bellard
    addr &= TARGET_PAGE_MASK;
1661 59817ccb bellard
1662 59817ccb bellard
    /* if it is not mapped, no need to worry here */
1663 59817ccb bellard
    if (addr >= MMAP_AREA_END)
1664 59817ccb bellard
        return 0;
1665 9fa3e853 bellard
    vp = virt_page_find(addr >> TARGET_PAGE_BITS);
1666 9fa3e853 bellard
    if (!vp)
1667 9fa3e853 bellard
        return 0;
1668 9fa3e853 bellard
    /* NOTE: in this case, validate_tag is _not_ tested as it
1669 9fa3e853 bellard
       validates only the code TLB */
1670 9fa3e853 bellard
    if (vp->valid_tag != virt_valid_tag)
1671 9fa3e853 bellard
        return 0;
1672 9fa3e853 bellard
    if (!(vp->prot & PAGE_WRITE))
1673 9fa3e853 bellard
        return 0;
1674 9fa3e853 bellard
#if defined(DEBUG_TLB)
1675 9fa3e853 bellard
    printf("page_unprotect: addr=0x%08x phys_addr=0x%08x prot=%x\n", 
1676 9fa3e853 bellard
           addr, vp->phys_addr, vp->prot);
1677 9fa3e853 bellard
#endif
1678 59817ccb bellard
    if (mprotect((void *)addr, TARGET_PAGE_SIZE, vp->prot) < 0)
1679 59817ccb bellard
        cpu_abort(cpu_single_env, "error mprotect addr=0x%lx prot=%d\n",
1680 59817ccb bellard
                  (unsigned long)addr, vp->prot);
1681 d720b93d bellard
    /* set the dirty bit */
1682 0a962c02 bellard
    phys_ram_dirty[vp->phys_addr >> TARGET_PAGE_BITS] = 0xff;
1683 d720b93d bellard
    /* flush the code inside */
1684 d720b93d bellard
    tb_invalidate_phys_page(vp->phys_addr, pc, puc);
1685 9fa3e853 bellard
    return 1;
1686 9fa3e853 bellard
#else
1687 9fa3e853 bellard
    return 0;
1688 9fa3e853 bellard
#endif
1689 33417e70 bellard
}
1690 33417e70 bellard
1691 0124311e bellard
#else
1692 0124311e bellard
1693 ee8b7021 bellard
void tlb_flush(CPUState *env, int flush_global)
1694 0124311e bellard
{
1695 0124311e bellard
}
1696 0124311e bellard
1697 2e12669a bellard
void tlb_flush_page(CPUState *env, target_ulong addr)
1698 0124311e bellard
{
1699 0124311e bellard
}
1700 0124311e bellard
1701 84b7b8e7 bellard
int tlb_set_page_exec(CPUState *env, target_ulong vaddr, 
1702 84b7b8e7 bellard
                      target_phys_addr_t paddr, int prot, 
1703 84b7b8e7 bellard
                      int is_user, int is_softmmu)
1704 9fa3e853 bellard
{
1705 9fa3e853 bellard
    return 0;
1706 9fa3e853 bellard
}
1707 0124311e bellard
1708 9fa3e853 bellard
/* dump memory mappings */
1709 9fa3e853 bellard
void page_dump(FILE *f)
1710 33417e70 bellard
{
1711 9fa3e853 bellard
    unsigned long start, end;
1712 9fa3e853 bellard
    int i, j, prot, prot1;
1713 9fa3e853 bellard
    PageDesc *p;
1714 33417e70 bellard
1715 9fa3e853 bellard
    fprintf(f, "%-8s %-8s %-8s %s\n",
1716 9fa3e853 bellard
            "start", "end", "size", "prot");
1717 9fa3e853 bellard
    start = -1;
1718 9fa3e853 bellard
    end = -1;
1719 9fa3e853 bellard
    prot = 0;
1720 9fa3e853 bellard
    for(i = 0; i <= L1_SIZE; i++) {
1721 9fa3e853 bellard
        if (i < L1_SIZE)
1722 9fa3e853 bellard
            p = l1_map[i];
1723 9fa3e853 bellard
        else
1724 9fa3e853 bellard
            p = NULL;
1725 9fa3e853 bellard
        for(j = 0;j < L2_SIZE; j++) {
1726 9fa3e853 bellard
            if (!p)
1727 9fa3e853 bellard
                prot1 = 0;
1728 9fa3e853 bellard
            else
1729 9fa3e853 bellard
                prot1 = p[j].flags;
1730 9fa3e853 bellard
            if (prot1 != prot) {
1731 9fa3e853 bellard
                end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
1732 9fa3e853 bellard
                if (start != -1) {
1733 9fa3e853 bellard
                    fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
1734 9fa3e853 bellard
                            start, end, end - start, 
1735 9fa3e853 bellard
                            prot & PAGE_READ ? 'r' : '-',
1736 9fa3e853 bellard
                            prot & PAGE_WRITE ? 'w' : '-',
1737 9fa3e853 bellard
                            prot & PAGE_EXEC ? 'x' : '-');
1738 9fa3e853 bellard
                }
1739 9fa3e853 bellard
                if (prot1 != 0)
1740 9fa3e853 bellard
                    start = end;
1741 9fa3e853 bellard
                else
1742 9fa3e853 bellard
                    start = -1;
1743 9fa3e853 bellard
                prot = prot1;
1744 9fa3e853 bellard
            }
1745 9fa3e853 bellard
            if (!p)
1746 9fa3e853 bellard
                break;
1747 9fa3e853 bellard
        }
1748 33417e70 bellard
    }
1749 33417e70 bellard
}
1750 33417e70 bellard
1751 53a5960a pbrook
int page_get_flags(target_ulong address)
1752 33417e70 bellard
{
1753 9fa3e853 bellard
    PageDesc *p;
1754 9fa3e853 bellard
1755 9fa3e853 bellard
    p = page_find(address >> TARGET_PAGE_BITS);
1756 33417e70 bellard
    if (!p)
1757 9fa3e853 bellard
        return 0;
1758 9fa3e853 bellard
    return p->flags;
1759 9fa3e853 bellard
}
1760 9fa3e853 bellard
1761 9fa3e853 bellard
/* modify the flags of a page and invalidate the code if
1762 9fa3e853 bellard
   necessary. The flag PAGE_WRITE_ORG is positionned automatically
1763 9fa3e853 bellard
   depending on PAGE_WRITE */
1764 53a5960a pbrook
void page_set_flags(target_ulong start, target_ulong end, int flags)
1765 9fa3e853 bellard
{
1766 9fa3e853 bellard
    PageDesc *p;
1767 53a5960a pbrook
    target_ulong addr;
1768 9fa3e853 bellard
1769 9fa3e853 bellard
    start = start & TARGET_PAGE_MASK;
1770 9fa3e853 bellard
    end = TARGET_PAGE_ALIGN(end);
1771 9fa3e853 bellard
    if (flags & PAGE_WRITE)
1772 9fa3e853 bellard
        flags |= PAGE_WRITE_ORG;
1773 9fa3e853 bellard
    spin_lock(&tb_lock);
1774 9fa3e853 bellard
    for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1775 9fa3e853 bellard
        p = page_find_alloc(addr >> TARGET_PAGE_BITS);
1776 9fa3e853 bellard
        /* if the write protection is set, then we invalidate the code
1777 9fa3e853 bellard
           inside */
1778 9fa3e853 bellard
        if (!(p->flags & PAGE_WRITE) && 
1779 9fa3e853 bellard
            (flags & PAGE_WRITE) &&
1780 9fa3e853 bellard
            p->first_tb) {
1781 d720b93d bellard
            tb_invalidate_phys_page(addr, 0, NULL);
1782 9fa3e853 bellard
        }
1783 9fa3e853 bellard
        p->flags = flags;
1784 9fa3e853 bellard
    }
1785 9fa3e853 bellard
    spin_unlock(&tb_lock);
1786 33417e70 bellard
}
1787 33417e70 bellard
1788 9fa3e853 bellard
/* called from signal handler: invalidate the code and unprotect the
1789 9fa3e853 bellard
   page. Return TRUE if the fault was succesfully handled. */
1790 53a5960a pbrook
int page_unprotect(target_ulong address, unsigned long pc, void *puc)
1791 9fa3e853 bellard
{
1792 9fa3e853 bellard
    unsigned int page_index, prot, pindex;
1793 9fa3e853 bellard
    PageDesc *p, *p1;
1794 53a5960a pbrook
    target_ulong host_start, host_end, addr;
1795 9fa3e853 bellard
1796 83fb7adf bellard
    host_start = address & qemu_host_page_mask;
1797 9fa3e853 bellard
    page_index = host_start >> TARGET_PAGE_BITS;
1798 9fa3e853 bellard
    p1 = page_find(page_index);
1799 9fa3e853 bellard
    if (!p1)
1800 9fa3e853 bellard
        return 0;
1801 83fb7adf bellard
    host_end = host_start + qemu_host_page_size;
1802 9fa3e853 bellard
    p = p1;
1803 9fa3e853 bellard
    prot = 0;
1804 9fa3e853 bellard
    for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
1805 9fa3e853 bellard
        prot |= p->flags;
1806 9fa3e853 bellard
        p++;
1807 9fa3e853 bellard
    }
1808 9fa3e853 bellard
    /* if the page was really writable, then we change its
1809 9fa3e853 bellard
       protection back to writable */
1810 9fa3e853 bellard
    if (prot & PAGE_WRITE_ORG) {
1811 9fa3e853 bellard
        pindex = (address - host_start) >> TARGET_PAGE_BITS;
1812 9fa3e853 bellard
        if (!(p1[pindex].flags & PAGE_WRITE)) {
1813 53a5960a pbrook
            mprotect((void *)g2h(host_start), qemu_host_page_size, 
1814 9fa3e853 bellard
                     (prot & PAGE_BITS) | PAGE_WRITE);
1815 9fa3e853 bellard
            p1[pindex].flags |= PAGE_WRITE;
1816 9fa3e853 bellard
            /* and since the content will be modified, we must invalidate
1817 9fa3e853 bellard
               the corresponding translated code. */
1818 d720b93d bellard
            tb_invalidate_phys_page(address, pc, puc);
1819 9fa3e853 bellard
#ifdef DEBUG_TB_CHECK
1820 9fa3e853 bellard
            tb_invalidate_check(address);
1821 9fa3e853 bellard
#endif
1822 9fa3e853 bellard
            return 1;
1823 9fa3e853 bellard
        }
1824 9fa3e853 bellard
    }
1825 9fa3e853 bellard
    return 0;
1826 9fa3e853 bellard
}
1827 9fa3e853 bellard
1828 9fa3e853 bellard
/* call this function when system calls directly modify a memory area */
1829 53a5960a pbrook
/* ??? This should be redundant now we have lock_user.  */
1830 53a5960a pbrook
void page_unprotect_range(target_ulong data, target_ulong data_size)
1831 9fa3e853 bellard
{
1832 53a5960a pbrook
    target_ulong start, end, addr;
1833 9fa3e853 bellard
1834 53a5960a pbrook
    start = data;
1835 9fa3e853 bellard
    end = start + data_size;
1836 9fa3e853 bellard
    start &= TARGET_PAGE_MASK;
1837 9fa3e853 bellard
    end = TARGET_PAGE_ALIGN(end);
1838 9fa3e853 bellard
    for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1839 d720b93d bellard
        page_unprotect(addr, 0, NULL);
1840 9fa3e853 bellard
    }
1841 9fa3e853 bellard
}
1842 9fa3e853 bellard
1843 6a00d601 bellard
static inline void tlb_set_dirty(CPUState *env,
1844 6a00d601 bellard
                                 unsigned long addr, target_ulong vaddr)
1845 1ccde1cb bellard
{
1846 1ccde1cb bellard
}
1847 9fa3e853 bellard
#endif /* defined(CONFIG_USER_ONLY) */
1848 9fa3e853 bellard
1849 33417e70 bellard
/* register physical memory. 'size' must be a multiple of the target
1850 33417e70 bellard
   page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
1851 33417e70 bellard
   io memory page */
1852 2e12669a bellard
void cpu_register_physical_memory(target_phys_addr_t start_addr, 
1853 2e12669a bellard
                                  unsigned long size,
1854 2e12669a bellard
                                  unsigned long phys_offset)
1855 33417e70 bellard
{
1856 108c49b8 bellard
    target_phys_addr_t addr, end_addr;
1857 92e873b9 bellard
    PhysPageDesc *p;
1858 9d42037b bellard
    CPUState *env;
1859 33417e70 bellard
1860 5fd386f6 bellard
    size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
1861 33417e70 bellard
    end_addr = start_addr + size;
1862 5fd386f6 bellard
    for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
1863 108c49b8 bellard
        p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
1864 9fa3e853 bellard
        p->phys_offset = phys_offset;
1865 2a4188a3 bellard
        if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
1866 2a4188a3 bellard
            (phys_offset & IO_MEM_ROMD))
1867 33417e70 bellard
            phys_offset += TARGET_PAGE_SIZE;
1868 33417e70 bellard
    }
1869 9d42037b bellard
    
1870 9d42037b bellard
    /* since each CPU stores ram addresses in its TLB cache, we must
1871 9d42037b bellard
       reset the modified entries */
1872 9d42037b bellard
    /* XXX: slow ! */
1873 9d42037b bellard
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
1874 9d42037b bellard
        tlb_flush(env, 1);
1875 9d42037b bellard
    }
1876 33417e70 bellard
}
1877 33417e70 bellard
1878 ba863458 bellard
/* XXX: temporary until new memory mapping API */
1879 ba863458 bellard
uint32_t cpu_get_physical_page_desc(target_phys_addr_t addr)
1880 ba863458 bellard
{
1881 ba863458 bellard
    PhysPageDesc *p;
1882 ba863458 bellard
1883 ba863458 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
1884 ba863458 bellard
    if (!p)
1885 ba863458 bellard
        return IO_MEM_UNASSIGNED;
1886 ba863458 bellard
    return p->phys_offset;
1887 ba863458 bellard
}
1888 ba863458 bellard
1889 e9a1ab19 bellard
/* XXX: better than nothing */
1890 e9a1ab19 bellard
ram_addr_t qemu_ram_alloc(unsigned int size)
1891 e9a1ab19 bellard
{
1892 e9a1ab19 bellard
    ram_addr_t addr;
1893 e9a1ab19 bellard
    if ((phys_ram_alloc_offset + size) >= phys_ram_size) {
1894 e9a1ab19 bellard
        fprintf(stderr, "Not enough memory (requested_size = %u, max memory = %d)\n", 
1895 e9a1ab19 bellard
                size, phys_ram_size);
1896 e9a1ab19 bellard
        abort();
1897 e9a1ab19 bellard
    }
1898 e9a1ab19 bellard
    addr = phys_ram_alloc_offset;
1899 e9a1ab19 bellard
    phys_ram_alloc_offset = TARGET_PAGE_ALIGN(phys_ram_alloc_offset + size);
1900 e9a1ab19 bellard
    return addr;
1901 e9a1ab19 bellard
}
1902 e9a1ab19 bellard
1903 e9a1ab19 bellard
void qemu_ram_free(ram_addr_t addr)
1904 e9a1ab19 bellard
{
1905 e9a1ab19 bellard
}
1906 e9a1ab19 bellard
1907 a4193c8a bellard
static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
1908 33417e70 bellard
{
1909 67d3b957 pbrook
#ifdef DEBUG_UNASSIGNED
1910 67d3b957 pbrook
    printf("Unassigned mem read  0x%08x\n", (int)addr);
1911 67d3b957 pbrook
#endif
1912 33417e70 bellard
    return 0;
1913 33417e70 bellard
}
1914 33417e70 bellard
1915 a4193c8a bellard
static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
1916 33417e70 bellard
{
1917 67d3b957 pbrook
#ifdef DEBUG_UNASSIGNED
1918 67d3b957 pbrook
    printf("Unassigned mem write 0x%08x = 0x%x\n", (int)addr, val);
1919 67d3b957 pbrook
#endif
1920 33417e70 bellard
}
1921 33417e70 bellard
1922 33417e70 bellard
static CPUReadMemoryFunc *unassigned_mem_read[3] = {
1923 33417e70 bellard
    unassigned_mem_readb,
1924 33417e70 bellard
    unassigned_mem_readb,
1925 33417e70 bellard
    unassigned_mem_readb,
1926 33417e70 bellard
};
1927 33417e70 bellard
1928 33417e70 bellard
static CPUWriteMemoryFunc *unassigned_mem_write[3] = {
1929 33417e70 bellard
    unassigned_mem_writeb,
1930 33417e70 bellard
    unassigned_mem_writeb,
1931 33417e70 bellard
    unassigned_mem_writeb,
1932 33417e70 bellard
};
1933 33417e70 bellard
1934 3a7d929e bellard
static void notdirty_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
1935 9fa3e853 bellard
{
1936 3a7d929e bellard
    unsigned long ram_addr;
1937 3a7d929e bellard
    int dirty_flags;
1938 3a7d929e bellard
    ram_addr = addr - (unsigned long)phys_ram_base;
1939 3a7d929e bellard
    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
1940 3a7d929e bellard
    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
1941 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
1942 3a7d929e bellard
        tb_invalidate_phys_page_fast(ram_addr, 1);
1943 3a7d929e bellard
        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
1944 9fa3e853 bellard
#endif
1945 3a7d929e bellard
    }
1946 c27004ec bellard
    stb_p((uint8_t *)(long)addr, val);
1947 f32fc648 bellard
#ifdef USE_KQEMU
1948 f32fc648 bellard
    if (cpu_single_env->kqemu_enabled &&
1949 f32fc648 bellard
        (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
1950 f32fc648 bellard
        kqemu_modify_page(cpu_single_env, ram_addr);
1951 f32fc648 bellard
#endif
1952 f23db169 bellard
    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
1953 f23db169 bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
1954 f23db169 bellard
    /* we remove the notdirty callback only if the code has been
1955 f23db169 bellard
       flushed */
1956 f23db169 bellard
    if (dirty_flags == 0xff)
1957 6a00d601 bellard
        tlb_set_dirty(cpu_single_env, addr, cpu_single_env->mem_write_vaddr);
1958 9fa3e853 bellard
}
1959 9fa3e853 bellard
1960 3a7d929e bellard
static void notdirty_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
1961 9fa3e853 bellard
{
1962 3a7d929e bellard
    unsigned long ram_addr;
1963 3a7d929e bellard
    int dirty_flags;
1964 3a7d929e bellard
    ram_addr = addr - (unsigned long)phys_ram_base;
1965 3a7d929e bellard
    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
1966 3a7d929e bellard
    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
1967 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
1968 3a7d929e bellard
        tb_invalidate_phys_page_fast(ram_addr, 2);
1969 3a7d929e bellard
        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
1970 9fa3e853 bellard
#endif
1971 3a7d929e bellard
    }
1972 c27004ec bellard
    stw_p((uint8_t *)(long)addr, val);
1973 f32fc648 bellard
#ifdef USE_KQEMU
1974 f32fc648 bellard
    if (cpu_single_env->kqemu_enabled &&
1975 f32fc648 bellard
        (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
1976 f32fc648 bellard
        kqemu_modify_page(cpu_single_env, ram_addr);
1977 f32fc648 bellard
#endif
1978 f23db169 bellard
    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
1979 f23db169 bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
1980 f23db169 bellard
    /* we remove the notdirty callback only if the code has been
1981 f23db169 bellard
       flushed */
1982 f23db169 bellard
    if (dirty_flags == 0xff)
1983 6a00d601 bellard
        tlb_set_dirty(cpu_single_env, addr, cpu_single_env->mem_write_vaddr);
1984 9fa3e853 bellard
}
1985 9fa3e853 bellard
1986 3a7d929e bellard
static void notdirty_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
1987 9fa3e853 bellard
{
1988 3a7d929e bellard
    unsigned long ram_addr;
1989 3a7d929e bellard
    int dirty_flags;
1990 3a7d929e bellard
    ram_addr = addr - (unsigned long)phys_ram_base;
1991 3a7d929e bellard
    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
1992 3a7d929e bellard
    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
1993 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
1994 3a7d929e bellard
        tb_invalidate_phys_page_fast(ram_addr, 4);
1995 3a7d929e bellard
        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
1996 9fa3e853 bellard
#endif
1997 3a7d929e bellard
    }
1998 c27004ec bellard
    stl_p((uint8_t *)(long)addr, val);
1999 f32fc648 bellard
#ifdef USE_KQEMU
2000 f32fc648 bellard
    if (cpu_single_env->kqemu_enabled &&
2001 f32fc648 bellard
        (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2002 f32fc648 bellard
        kqemu_modify_page(cpu_single_env, ram_addr);
2003 f32fc648 bellard
#endif
2004 f23db169 bellard
    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2005 f23db169 bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2006 f23db169 bellard
    /* we remove the notdirty callback only if the code has been
2007 f23db169 bellard
       flushed */
2008 f23db169 bellard
    if (dirty_flags == 0xff)
2009 6a00d601 bellard
        tlb_set_dirty(cpu_single_env, addr, cpu_single_env->mem_write_vaddr);
2010 9fa3e853 bellard
}
2011 9fa3e853 bellard
2012 3a7d929e bellard
static CPUReadMemoryFunc *error_mem_read[3] = {
2013 9fa3e853 bellard
    NULL, /* never used */
2014 9fa3e853 bellard
    NULL, /* never used */
2015 9fa3e853 bellard
    NULL, /* never used */
2016 9fa3e853 bellard
};
2017 9fa3e853 bellard
2018 1ccde1cb bellard
static CPUWriteMemoryFunc *notdirty_mem_write[3] = {
2019 1ccde1cb bellard
    notdirty_mem_writeb,
2020 1ccde1cb bellard
    notdirty_mem_writew,
2021 1ccde1cb bellard
    notdirty_mem_writel,
2022 1ccde1cb bellard
};
2023 1ccde1cb bellard
2024 6658ffb8 pbrook
#if defined(CONFIG_SOFTMMU)
2025 6658ffb8 pbrook
/* Watchpoint access routines.  Watchpoints are inserted using TLB tricks,
2026 6658ffb8 pbrook
   so these check for a hit then pass through to the normal out-of-line
2027 6658ffb8 pbrook
   phys routines.  */
2028 6658ffb8 pbrook
static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
2029 6658ffb8 pbrook
{
2030 6658ffb8 pbrook
    return ldub_phys(addr);
2031 6658ffb8 pbrook
}
2032 6658ffb8 pbrook
2033 6658ffb8 pbrook
static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
2034 6658ffb8 pbrook
{
2035 6658ffb8 pbrook
    return lduw_phys(addr);
2036 6658ffb8 pbrook
}
2037 6658ffb8 pbrook
2038 6658ffb8 pbrook
static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
2039 6658ffb8 pbrook
{
2040 6658ffb8 pbrook
    return ldl_phys(addr);
2041 6658ffb8 pbrook
}
2042 6658ffb8 pbrook
2043 6658ffb8 pbrook
/* Generate a debug exception if a watchpoint has been hit.
2044 6658ffb8 pbrook
   Returns the real physical address of the access.  addr will be a host
2045 6658ffb8 pbrook
   address in the is_ram case.  */
2046 6658ffb8 pbrook
static target_ulong check_watchpoint(target_phys_addr_t addr)
2047 6658ffb8 pbrook
{
2048 6658ffb8 pbrook
    CPUState *env = cpu_single_env;
2049 6658ffb8 pbrook
    target_ulong watch;
2050 6658ffb8 pbrook
    target_ulong retaddr;
2051 6658ffb8 pbrook
    int i;
2052 6658ffb8 pbrook
2053 6658ffb8 pbrook
    retaddr = addr;
2054 6658ffb8 pbrook
    for (i = 0; i < env->nb_watchpoints; i++) {
2055 6658ffb8 pbrook
        watch = env->watchpoint[i].vaddr;
2056 6658ffb8 pbrook
        if (((env->mem_write_vaddr ^ watch) & TARGET_PAGE_MASK) == 0) {
2057 6658ffb8 pbrook
            if (env->watchpoint[i].is_ram)
2058 6658ffb8 pbrook
                retaddr = addr - (unsigned long)phys_ram_base;
2059 6658ffb8 pbrook
            if (((addr ^ watch) & ~TARGET_PAGE_MASK) == 0) {
2060 6658ffb8 pbrook
                cpu_single_env->watchpoint_hit = i + 1;
2061 6658ffb8 pbrook
                cpu_interrupt(cpu_single_env, CPU_INTERRUPT_DEBUG);
2062 6658ffb8 pbrook
                break;
2063 6658ffb8 pbrook
            }
2064 6658ffb8 pbrook
        }
2065 6658ffb8 pbrook
    }
2066 6658ffb8 pbrook
    return retaddr;
2067 6658ffb8 pbrook
}
2068 6658ffb8 pbrook
2069 6658ffb8 pbrook
static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
2070 6658ffb8 pbrook
                             uint32_t val)
2071 6658ffb8 pbrook
{
2072 6658ffb8 pbrook
    addr = check_watchpoint(addr);
2073 6658ffb8 pbrook
    stb_phys(addr, val);
2074 6658ffb8 pbrook
}
2075 6658ffb8 pbrook
2076 6658ffb8 pbrook
static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
2077 6658ffb8 pbrook
                             uint32_t val)
2078 6658ffb8 pbrook
{
2079 6658ffb8 pbrook
    addr = check_watchpoint(addr);
2080 6658ffb8 pbrook
    stw_phys(addr, val);
2081 6658ffb8 pbrook
}
2082 6658ffb8 pbrook
2083 6658ffb8 pbrook
static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
2084 6658ffb8 pbrook
                             uint32_t val)
2085 6658ffb8 pbrook
{
2086 6658ffb8 pbrook
    addr = check_watchpoint(addr);
2087 6658ffb8 pbrook
    stl_phys(addr, val);
2088 6658ffb8 pbrook
}
2089 6658ffb8 pbrook
2090 6658ffb8 pbrook
static CPUReadMemoryFunc *watch_mem_read[3] = {
2091 6658ffb8 pbrook
    watch_mem_readb,
2092 6658ffb8 pbrook
    watch_mem_readw,
2093 6658ffb8 pbrook
    watch_mem_readl,
2094 6658ffb8 pbrook
};
2095 6658ffb8 pbrook
2096 6658ffb8 pbrook
static CPUWriteMemoryFunc *watch_mem_write[3] = {
2097 6658ffb8 pbrook
    watch_mem_writeb,
2098 6658ffb8 pbrook
    watch_mem_writew,
2099 6658ffb8 pbrook
    watch_mem_writel,
2100 6658ffb8 pbrook
};
2101 6658ffb8 pbrook
#endif
2102 6658ffb8 pbrook
2103 33417e70 bellard
static void io_mem_init(void)
2104 33417e70 bellard
{
2105 3a7d929e bellard
    cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read, unassigned_mem_write, NULL);
2106 a4193c8a bellard
    cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write, NULL);
2107 3a7d929e bellard
    cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read, notdirty_mem_write, NULL);
2108 1ccde1cb bellard
    io_mem_nb = 5;
2109 1ccde1cb bellard
2110 6658ffb8 pbrook
#if defined(CONFIG_SOFTMMU)
2111 6658ffb8 pbrook
    io_mem_watch = cpu_register_io_memory(-1, watch_mem_read,
2112 6658ffb8 pbrook
                                          watch_mem_write, NULL);
2113 6658ffb8 pbrook
#endif
2114 1ccde1cb bellard
    /* alloc dirty bits array */
2115 0a962c02 bellard
    phys_ram_dirty = qemu_vmalloc(phys_ram_size >> TARGET_PAGE_BITS);
2116 3a7d929e bellard
    memset(phys_ram_dirty, 0xff, phys_ram_size >> TARGET_PAGE_BITS);
2117 33417e70 bellard
}
2118 33417e70 bellard
2119 33417e70 bellard
/* mem_read and mem_write are arrays of functions containing the
2120 33417e70 bellard
   function to access byte (index 0), word (index 1) and dword (index
2121 33417e70 bellard
   2). All functions must be supplied. If io_index is non zero, the
2122 33417e70 bellard
   corresponding io zone is modified. If it is zero, a new io zone is
2123 33417e70 bellard
   allocated. The return value can be used with
2124 33417e70 bellard
   cpu_register_physical_memory(). (-1) is returned if error. */
2125 33417e70 bellard
int cpu_register_io_memory(int io_index,
2126 33417e70 bellard
                           CPUReadMemoryFunc **mem_read,
2127 a4193c8a bellard
                           CPUWriteMemoryFunc **mem_write,
2128 a4193c8a bellard
                           void *opaque)
2129 33417e70 bellard
{
2130 33417e70 bellard
    int i;
2131 33417e70 bellard
2132 33417e70 bellard
    if (io_index <= 0) {
2133 b5ff1b31 bellard
        if (io_mem_nb >= IO_MEM_NB_ENTRIES)
2134 33417e70 bellard
            return -1;
2135 33417e70 bellard
        io_index = io_mem_nb++;
2136 33417e70 bellard
    } else {
2137 33417e70 bellard
        if (io_index >= IO_MEM_NB_ENTRIES)
2138 33417e70 bellard
            return -1;
2139 33417e70 bellard
    }
2140 b5ff1b31 bellard
2141 33417e70 bellard
    for(i = 0;i < 3; i++) {
2142 33417e70 bellard
        io_mem_read[io_index][i] = mem_read[i];
2143 33417e70 bellard
        io_mem_write[io_index][i] = mem_write[i];
2144 33417e70 bellard
    }
2145 a4193c8a bellard
    io_mem_opaque[io_index] = opaque;
2146 33417e70 bellard
    return io_index << IO_MEM_SHIFT;
2147 33417e70 bellard
}
2148 61382a50 bellard
2149 8926b517 bellard
CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index)
2150 8926b517 bellard
{
2151 8926b517 bellard
    return io_mem_write[io_index >> IO_MEM_SHIFT];
2152 8926b517 bellard
}
2153 8926b517 bellard
2154 8926b517 bellard
CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index)
2155 8926b517 bellard
{
2156 8926b517 bellard
    return io_mem_read[io_index >> IO_MEM_SHIFT];
2157 8926b517 bellard
}
2158 8926b517 bellard
2159 13eb76e0 bellard
/* physical memory access (slow version, mainly for debug) */
2160 13eb76e0 bellard
#if defined(CONFIG_USER_ONLY)
2161 2e12669a bellard
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, 
2162 13eb76e0 bellard
                            int len, int is_write)
2163 13eb76e0 bellard
{
2164 13eb76e0 bellard
    int l, flags;
2165 13eb76e0 bellard
    target_ulong page;
2166 53a5960a pbrook
    void * p;
2167 13eb76e0 bellard
2168 13eb76e0 bellard
    while (len > 0) {
2169 13eb76e0 bellard
        page = addr & TARGET_PAGE_MASK;
2170 13eb76e0 bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
2171 13eb76e0 bellard
        if (l > len)
2172 13eb76e0 bellard
            l = len;
2173 13eb76e0 bellard
        flags = page_get_flags(page);
2174 13eb76e0 bellard
        if (!(flags & PAGE_VALID))
2175 13eb76e0 bellard
            return;
2176 13eb76e0 bellard
        if (is_write) {
2177 13eb76e0 bellard
            if (!(flags & PAGE_WRITE))
2178 13eb76e0 bellard
                return;
2179 53a5960a pbrook
            p = lock_user(addr, len, 0);
2180 53a5960a pbrook
            memcpy(p, buf, len);
2181 53a5960a pbrook
            unlock_user(p, addr, len);
2182 13eb76e0 bellard
        } else {
2183 13eb76e0 bellard
            if (!(flags & PAGE_READ))
2184 13eb76e0 bellard
                return;
2185 53a5960a pbrook
            p = lock_user(addr, len, 1);
2186 53a5960a pbrook
            memcpy(buf, p, len);
2187 53a5960a pbrook
            unlock_user(p, addr, 0);
2188 13eb76e0 bellard
        }
2189 13eb76e0 bellard
        len -= l;
2190 13eb76e0 bellard
        buf += l;
2191 13eb76e0 bellard
        addr += l;
2192 13eb76e0 bellard
    }
2193 13eb76e0 bellard
}
2194 8df1cd07 bellard
2195 13eb76e0 bellard
#else
2196 2e12669a bellard
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, 
2197 13eb76e0 bellard
                            int len, int is_write)
2198 13eb76e0 bellard
{
2199 13eb76e0 bellard
    int l, io_index;
2200 13eb76e0 bellard
    uint8_t *ptr;
2201 13eb76e0 bellard
    uint32_t val;
2202 2e12669a bellard
    target_phys_addr_t page;
2203 2e12669a bellard
    unsigned long pd;
2204 92e873b9 bellard
    PhysPageDesc *p;
2205 13eb76e0 bellard
    
2206 13eb76e0 bellard
    while (len > 0) {
2207 13eb76e0 bellard
        page = addr & TARGET_PAGE_MASK;
2208 13eb76e0 bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
2209 13eb76e0 bellard
        if (l > len)
2210 13eb76e0 bellard
            l = len;
2211 92e873b9 bellard
        p = phys_page_find(page >> TARGET_PAGE_BITS);
2212 13eb76e0 bellard
        if (!p) {
2213 13eb76e0 bellard
            pd = IO_MEM_UNASSIGNED;
2214 13eb76e0 bellard
        } else {
2215 13eb76e0 bellard
            pd = p->phys_offset;
2216 13eb76e0 bellard
        }
2217 13eb76e0 bellard
        
2218 13eb76e0 bellard
        if (is_write) {
2219 3a7d929e bellard
            if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2220 13eb76e0 bellard
                io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2221 6a00d601 bellard
                /* XXX: could force cpu_single_env to NULL to avoid
2222 6a00d601 bellard
                   potential bugs */
2223 13eb76e0 bellard
                if (l >= 4 && ((addr & 3) == 0)) {
2224 1c213d19 bellard
                    /* 32 bit write access */
2225 c27004ec bellard
                    val = ldl_p(buf);
2226 a4193c8a bellard
                    io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2227 13eb76e0 bellard
                    l = 4;
2228 13eb76e0 bellard
                } else if (l >= 2 && ((addr & 1) == 0)) {
2229 1c213d19 bellard
                    /* 16 bit write access */
2230 c27004ec bellard
                    val = lduw_p(buf);
2231 a4193c8a bellard
                    io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
2232 13eb76e0 bellard
                    l = 2;
2233 13eb76e0 bellard
                } else {
2234 1c213d19 bellard
                    /* 8 bit write access */
2235 c27004ec bellard
                    val = ldub_p(buf);
2236 a4193c8a bellard
                    io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val);
2237 13eb76e0 bellard
                    l = 1;
2238 13eb76e0 bellard
                }
2239 13eb76e0 bellard
            } else {
2240 b448f2f3 bellard
                unsigned long addr1;
2241 b448f2f3 bellard
                addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2242 13eb76e0 bellard
                /* RAM case */
2243 b448f2f3 bellard
                ptr = phys_ram_base + addr1;
2244 13eb76e0 bellard
                memcpy(ptr, buf, l);
2245 3a7d929e bellard
                if (!cpu_physical_memory_is_dirty(addr1)) {
2246 3a7d929e bellard
                    /* invalidate code */
2247 3a7d929e bellard
                    tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
2248 3a7d929e bellard
                    /* set dirty bit */
2249 f23db169 bellard
                    phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |= 
2250 f23db169 bellard
                        (0xff & ~CODE_DIRTY_FLAG);
2251 3a7d929e bellard
                }
2252 13eb76e0 bellard
            }
2253 13eb76e0 bellard
        } else {
2254 2a4188a3 bellard
            if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && 
2255 2a4188a3 bellard
                !(pd & IO_MEM_ROMD)) {
2256 13eb76e0 bellard
                /* I/O case */
2257 13eb76e0 bellard
                io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2258 13eb76e0 bellard
                if (l >= 4 && ((addr & 3) == 0)) {
2259 13eb76e0 bellard
                    /* 32 bit read access */
2260 a4193c8a bellard
                    val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2261 c27004ec bellard
                    stl_p(buf, val);
2262 13eb76e0 bellard
                    l = 4;
2263 13eb76e0 bellard
                } else if (l >= 2 && ((addr & 1) == 0)) {
2264 13eb76e0 bellard
                    /* 16 bit read access */
2265 a4193c8a bellard
                    val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
2266 c27004ec bellard
                    stw_p(buf, val);
2267 13eb76e0 bellard
                    l = 2;
2268 13eb76e0 bellard
                } else {
2269 1c213d19 bellard
                    /* 8 bit read access */
2270 a4193c8a bellard
                    val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr);
2271 c27004ec bellard
                    stb_p(buf, val);
2272 13eb76e0 bellard
                    l = 1;
2273 13eb76e0 bellard
                }
2274 13eb76e0 bellard
            } else {
2275 13eb76e0 bellard
                /* RAM case */
2276 13eb76e0 bellard
                ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
2277 13eb76e0 bellard
                    (addr & ~TARGET_PAGE_MASK);
2278 13eb76e0 bellard
                memcpy(buf, ptr, l);
2279 13eb76e0 bellard
            }
2280 13eb76e0 bellard
        }
2281 13eb76e0 bellard
        len -= l;
2282 13eb76e0 bellard
        buf += l;
2283 13eb76e0 bellard
        addr += l;
2284 13eb76e0 bellard
    }
2285 13eb76e0 bellard
}
2286 8df1cd07 bellard
2287 d0ecd2aa bellard
/* used for ROM loading : can write in RAM and ROM */
2288 d0ecd2aa bellard
void cpu_physical_memory_write_rom(target_phys_addr_t addr, 
2289 d0ecd2aa bellard
                                   const uint8_t *buf, int len)
2290 d0ecd2aa bellard
{
2291 d0ecd2aa bellard
    int l;
2292 d0ecd2aa bellard
    uint8_t *ptr;
2293 d0ecd2aa bellard
    target_phys_addr_t page;
2294 d0ecd2aa bellard
    unsigned long pd;
2295 d0ecd2aa bellard
    PhysPageDesc *p;
2296 d0ecd2aa bellard
    
2297 d0ecd2aa bellard
    while (len > 0) {
2298 d0ecd2aa bellard
        page = addr & TARGET_PAGE_MASK;
2299 d0ecd2aa bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
2300 d0ecd2aa bellard
        if (l > len)
2301 d0ecd2aa bellard
            l = len;
2302 d0ecd2aa bellard
        p = phys_page_find(page >> TARGET_PAGE_BITS);
2303 d0ecd2aa bellard
        if (!p) {
2304 d0ecd2aa bellard
            pd = IO_MEM_UNASSIGNED;
2305 d0ecd2aa bellard
        } else {
2306 d0ecd2aa bellard
            pd = p->phys_offset;
2307 d0ecd2aa bellard
        }
2308 d0ecd2aa bellard
        
2309 d0ecd2aa bellard
        if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
2310 2a4188a3 bellard
            (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
2311 2a4188a3 bellard
            !(pd & IO_MEM_ROMD)) {
2312 d0ecd2aa bellard
            /* do nothing */
2313 d0ecd2aa bellard
        } else {
2314 d0ecd2aa bellard
            unsigned long addr1;
2315 d0ecd2aa bellard
            addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2316 d0ecd2aa bellard
            /* ROM/RAM case */
2317 d0ecd2aa bellard
            ptr = phys_ram_base + addr1;
2318 d0ecd2aa bellard
            memcpy(ptr, buf, l);
2319 d0ecd2aa bellard
        }
2320 d0ecd2aa bellard
        len -= l;
2321 d0ecd2aa bellard
        buf += l;
2322 d0ecd2aa bellard
        addr += l;
2323 d0ecd2aa bellard
    }
2324 d0ecd2aa bellard
}
2325 d0ecd2aa bellard
2326 d0ecd2aa bellard
2327 8df1cd07 bellard
/* warning: addr must be aligned */
2328 8df1cd07 bellard
uint32_t ldl_phys(target_phys_addr_t addr)
2329 8df1cd07 bellard
{
2330 8df1cd07 bellard
    int io_index;
2331 8df1cd07 bellard
    uint8_t *ptr;
2332 8df1cd07 bellard
    uint32_t val;
2333 8df1cd07 bellard
    unsigned long pd;
2334 8df1cd07 bellard
    PhysPageDesc *p;
2335 8df1cd07 bellard
2336 8df1cd07 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2337 8df1cd07 bellard
    if (!p) {
2338 8df1cd07 bellard
        pd = IO_MEM_UNASSIGNED;
2339 8df1cd07 bellard
    } else {
2340 8df1cd07 bellard
        pd = p->phys_offset;
2341 8df1cd07 bellard
    }
2342 8df1cd07 bellard
        
2343 2a4188a3 bellard
    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && 
2344 2a4188a3 bellard
        !(pd & IO_MEM_ROMD)) {
2345 8df1cd07 bellard
        /* I/O case */
2346 8df1cd07 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2347 8df1cd07 bellard
        val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2348 8df1cd07 bellard
    } else {
2349 8df1cd07 bellard
        /* RAM case */
2350 8df1cd07 bellard
        ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
2351 8df1cd07 bellard
            (addr & ~TARGET_PAGE_MASK);
2352 8df1cd07 bellard
        val = ldl_p(ptr);
2353 8df1cd07 bellard
    }
2354 8df1cd07 bellard
    return val;
2355 8df1cd07 bellard
}
2356 8df1cd07 bellard
2357 84b7b8e7 bellard
/* warning: addr must be aligned */
2358 84b7b8e7 bellard
uint64_t ldq_phys(target_phys_addr_t addr)
2359 84b7b8e7 bellard
{
2360 84b7b8e7 bellard
    int io_index;
2361 84b7b8e7 bellard
    uint8_t *ptr;
2362 84b7b8e7 bellard
    uint64_t val;
2363 84b7b8e7 bellard
    unsigned long pd;
2364 84b7b8e7 bellard
    PhysPageDesc *p;
2365 84b7b8e7 bellard
2366 84b7b8e7 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2367 84b7b8e7 bellard
    if (!p) {
2368 84b7b8e7 bellard
        pd = IO_MEM_UNASSIGNED;
2369 84b7b8e7 bellard
    } else {
2370 84b7b8e7 bellard
        pd = p->phys_offset;
2371 84b7b8e7 bellard
    }
2372 84b7b8e7 bellard
        
2373 2a4188a3 bellard
    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
2374 2a4188a3 bellard
        !(pd & IO_MEM_ROMD)) {
2375 84b7b8e7 bellard
        /* I/O case */
2376 84b7b8e7 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2377 84b7b8e7 bellard
#ifdef TARGET_WORDS_BIGENDIAN
2378 84b7b8e7 bellard
        val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
2379 84b7b8e7 bellard
        val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
2380 84b7b8e7 bellard
#else
2381 84b7b8e7 bellard
        val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2382 84b7b8e7 bellard
        val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
2383 84b7b8e7 bellard
#endif
2384 84b7b8e7 bellard
    } else {
2385 84b7b8e7 bellard
        /* RAM case */
2386 84b7b8e7 bellard
        ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
2387 84b7b8e7 bellard
            (addr & ~TARGET_PAGE_MASK);
2388 84b7b8e7 bellard
        val = ldq_p(ptr);
2389 84b7b8e7 bellard
    }
2390 84b7b8e7 bellard
    return val;
2391 84b7b8e7 bellard
}
2392 84b7b8e7 bellard
2393 aab33094 bellard
/* XXX: optimize */
2394 aab33094 bellard
uint32_t ldub_phys(target_phys_addr_t addr)
2395 aab33094 bellard
{
2396 aab33094 bellard
    uint8_t val;
2397 aab33094 bellard
    cpu_physical_memory_read(addr, &val, 1);
2398 aab33094 bellard
    return val;
2399 aab33094 bellard
}
2400 aab33094 bellard
2401 aab33094 bellard
/* XXX: optimize */
2402 aab33094 bellard
uint32_t lduw_phys(target_phys_addr_t addr)
2403 aab33094 bellard
{
2404 aab33094 bellard
    uint16_t val;
2405 aab33094 bellard
    cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
2406 aab33094 bellard
    return tswap16(val);
2407 aab33094 bellard
}
2408 aab33094 bellard
2409 8df1cd07 bellard
/* warning: addr must be aligned. The ram page is not masked as dirty
2410 8df1cd07 bellard
   and the code inside is not invalidated. It is useful if the dirty
2411 8df1cd07 bellard
   bits are used to track modified PTEs */
2412 8df1cd07 bellard
void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
2413 8df1cd07 bellard
{
2414 8df1cd07 bellard
    int io_index;
2415 8df1cd07 bellard
    uint8_t *ptr;
2416 8df1cd07 bellard
    unsigned long pd;
2417 8df1cd07 bellard
    PhysPageDesc *p;
2418 8df1cd07 bellard
2419 8df1cd07 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2420 8df1cd07 bellard
    if (!p) {
2421 8df1cd07 bellard
        pd = IO_MEM_UNASSIGNED;
2422 8df1cd07 bellard
    } else {
2423 8df1cd07 bellard
        pd = p->phys_offset;
2424 8df1cd07 bellard
    }
2425 8df1cd07 bellard
        
2426 3a7d929e bellard
    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2427 8df1cd07 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2428 8df1cd07 bellard
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2429 8df1cd07 bellard
    } else {
2430 8df1cd07 bellard
        ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
2431 8df1cd07 bellard
            (addr & ~TARGET_PAGE_MASK);
2432 8df1cd07 bellard
        stl_p(ptr, val);
2433 8df1cd07 bellard
    }
2434 8df1cd07 bellard
}
2435 8df1cd07 bellard
2436 8df1cd07 bellard
/* warning: addr must be aligned */
2437 8df1cd07 bellard
void stl_phys(target_phys_addr_t addr, uint32_t val)
2438 8df1cd07 bellard
{
2439 8df1cd07 bellard
    int io_index;
2440 8df1cd07 bellard
    uint8_t *ptr;
2441 8df1cd07 bellard
    unsigned long pd;
2442 8df1cd07 bellard
    PhysPageDesc *p;
2443 8df1cd07 bellard
2444 8df1cd07 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2445 8df1cd07 bellard
    if (!p) {
2446 8df1cd07 bellard
        pd = IO_MEM_UNASSIGNED;
2447 8df1cd07 bellard
    } else {
2448 8df1cd07 bellard
        pd = p->phys_offset;
2449 8df1cd07 bellard
    }
2450 8df1cd07 bellard
        
2451 3a7d929e bellard
    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2452 8df1cd07 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2453 8df1cd07 bellard
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2454 8df1cd07 bellard
    } else {
2455 8df1cd07 bellard
        unsigned long addr1;
2456 8df1cd07 bellard
        addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2457 8df1cd07 bellard
        /* RAM case */
2458 8df1cd07 bellard
        ptr = phys_ram_base + addr1;
2459 8df1cd07 bellard
        stl_p(ptr, val);
2460 3a7d929e bellard
        if (!cpu_physical_memory_is_dirty(addr1)) {
2461 3a7d929e bellard
            /* invalidate code */
2462 3a7d929e bellard
            tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
2463 3a7d929e bellard
            /* set dirty bit */
2464 f23db169 bellard
            phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
2465 f23db169 bellard
                (0xff & ~CODE_DIRTY_FLAG);
2466 3a7d929e bellard
        }
2467 8df1cd07 bellard
    }
2468 8df1cd07 bellard
}
2469 8df1cd07 bellard
2470 aab33094 bellard
/* XXX: optimize */
2471 aab33094 bellard
void stb_phys(target_phys_addr_t addr, uint32_t val)
2472 aab33094 bellard
{
2473 aab33094 bellard
    uint8_t v = val;
2474 aab33094 bellard
    cpu_physical_memory_write(addr, &v, 1);
2475 aab33094 bellard
}
2476 aab33094 bellard
2477 aab33094 bellard
/* XXX: optimize */
2478 aab33094 bellard
void stw_phys(target_phys_addr_t addr, uint32_t val)
2479 aab33094 bellard
{
2480 aab33094 bellard
    uint16_t v = tswap16(val);
2481 aab33094 bellard
    cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
2482 aab33094 bellard
}
2483 aab33094 bellard
2484 aab33094 bellard
/* XXX: optimize */
2485 aab33094 bellard
void stq_phys(target_phys_addr_t addr, uint64_t val)
2486 aab33094 bellard
{
2487 aab33094 bellard
    val = tswap64(val);
2488 aab33094 bellard
    cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
2489 aab33094 bellard
}
2490 aab33094 bellard
2491 13eb76e0 bellard
#endif
2492 13eb76e0 bellard
2493 13eb76e0 bellard
/* virtual memory access for debug */
2494 b448f2f3 bellard
int cpu_memory_rw_debug(CPUState *env, target_ulong addr, 
2495 b448f2f3 bellard
                        uint8_t *buf, int len, int is_write)
2496 13eb76e0 bellard
{
2497 13eb76e0 bellard
    int l;
2498 13eb76e0 bellard
    target_ulong page, phys_addr;
2499 13eb76e0 bellard
2500 13eb76e0 bellard
    while (len > 0) {
2501 13eb76e0 bellard
        page = addr & TARGET_PAGE_MASK;
2502 13eb76e0 bellard
        phys_addr = cpu_get_phys_page_debug(env, page);
2503 13eb76e0 bellard
        /* if no physical page mapped, return an error */
2504 13eb76e0 bellard
        if (phys_addr == -1)
2505 13eb76e0 bellard
            return -1;
2506 13eb76e0 bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
2507 13eb76e0 bellard
        if (l > len)
2508 13eb76e0 bellard
            l = len;
2509 b448f2f3 bellard
        cpu_physical_memory_rw(phys_addr + (addr & ~TARGET_PAGE_MASK), 
2510 b448f2f3 bellard
                               buf, l, is_write);
2511 13eb76e0 bellard
        len -= l;
2512 13eb76e0 bellard
        buf += l;
2513 13eb76e0 bellard
        addr += l;
2514 13eb76e0 bellard
    }
2515 13eb76e0 bellard
    return 0;
2516 13eb76e0 bellard
}
2517 13eb76e0 bellard
2518 e3db7226 bellard
void dump_exec_info(FILE *f,
2519 e3db7226 bellard
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2520 e3db7226 bellard
{
2521 e3db7226 bellard
    int i, target_code_size, max_target_code_size;
2522 e3db7226 bellard
    int direct_jmp_count, direct_jmp2_count, cross_page;
2523 e3db7226 bellard
    TranslationBlock *tb;
2524 e3db7226 bellard
    
2525 e3db7226 bellard
    target_code_size = 0;
2526 e3db7226 bellard
    max_target_code_size = 0;
2527 e3db7226 bellard
    cross_page = 0;
2528 e3db7226 bellard
    direct_jmp_count = 0;
2529 e3db7226 bellard
    direct_jmp2_count = 0;
2530 e3db7226 bellard
    for(i = 0; i < nb_tbs; i++) {
2531 e3db7226 bellard
        tb = &tbs[i];
2532 e3db7226 bellard
        target_code_size += tb->size;
2533 e3db7226 bellard
        if (tb->size > max_target_code_size)
2534 e3db7226 bellard
            max_target_code_size = tb->size;
2535 e3db7226 bellard
        if (tb->page_addr[1] != -1)
2536 e3db7226 bellard
            cross_page++;
2537 e3db7226 bellard
        if (tb->tb_next_offset[0] != 0xffff) {
2538 e3db7226 bellard
            direct_jmp_count++;
2539 e3db7226 bellard
            if (tb->tb_next_offset[1] != 0xffff) {
2540 e3db7226 bellard
                direct_jmp2_count++;
2541 e3db7226 bellard
            }
2542 e3db7226 bellard
        }
2543 e3db7226 bellard
    }
2544 e3db7226 bellard
    /* XXX: avoid using doubles ? */
2545 e3db7226 bellard
    cpu_fprintf(f, "TB count            %d\n", nb_tbs);
2546 e3db7226 bellard
    cpu_fprintf(f, "TB avg target size  %d max=%d bytes\n", 
2547 e3db7226 bellard
                nb_tbs ? target_code_size / nb_tbs : 0,
2548 e3db7226 bellard
                max_target_code_size);
2549 e3db7226 bellard
    cpu_fprintf(f, "TB avg host size    %d bytes (expansion ratio: %0.1f)\n", 
2550 e3db7226 bellard
                nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
2551 e3db7226 bellard
                target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
2552 e3db7226 bellard
    cpu_fprintf(f, "cross page TB count %d (%d%%)\n", 
2553 e3db7226 bellard
            cross_page, 
2554 e3db7226 bellard
            nb_tbs ? (cross_page * 100) / nb_tbs : 0);
2555 e3db7226 bellard
    cpu_fprintf(f, "direct jump count   %d (%d%%) (2 jumps=%d %d%%)\n",
2556 e3db7226 bellard
                direct_jmp_count, 
2557 e3db7226 bellard
                nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
2558 e3db7226 bellard
                direct_jmp2_count,
2559 e3db7226 bellard
                nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
2560 e3db7226 bellard
    cpu_fprintf(f, "TB flush count      %d\n", tb_flush_count);
2561 e3db7226 bellard
    cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
2562 e3db7226 bellard
    cpu_fprintf(f, "TLB flush count     %d\n", tlb_flush_count);
2563 e3db7226 bellard
}
2564 e3db7226 bellard
2565 61382a50 bellard
#if !defined(CONFIG_USER_ONLY) 
2566 61382a50 bellard
2567 61382a50 bellard
#define MMUSUFFIX _cmmu
2568 61382a50 bellard
#define GETPC() NULL
2569 61382a50 bellard
#define env cpu_single_env
2570 b769d8fe bellard
#define SOFTMMU_CODE_ACCESS
2571 61382a50 bellard
2572 61382a50 bellard
#define SHIFT 0
2573 61382a50 bellard
#include "softmmu_template.h"
2574 61382a50 bellard
2575 61382a50 bellard
#define SHIFT 1
2576 61382a50 bellard
#include "softmmu_template.h"
2577 61382a50 bellard
2578 61382a50 bellard
#define SHIFT 2
2579 61382a50 bellard
#include "softmmu_template.h"
2580 61382a50 bellard
2581 61382a50 bellard
#define SHIFT 3
2582 61382a50 bellard
#include "softmmu_template.h"
2583 61382a50 bellard
2584 61382a50 bellard
#undef env
2585 61382a50 bellard
2586 61382a50 bellard
#endif