Statistics
| Branch: | Revision:

root / exec.c @ 4ad5b06d

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