Statistics
| Branch: | Revision:

root / exec.c @ ea785922

History | View | Annotate | Download (71.2 kB)

1 54936004 bellard
/*
2 fd6ce8f6 bellard
 *  virtual page mapping and translated block handling
3 54936004 bellard
 * 
4 54936004 bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 54936004 bellard
 *
6 54936004 bellard
 * This library is free software; you can redistribute it and/or
7 54936004 bellard
 * modify it under the terms of the GNU Lesser General Public
8 54936004 bellard
 * License as published by the Free Software Foundation; either
9 54936004 bellard
 * version 2 of the License, or (at your option) any later version.
10 54936004 bellard
 *
11 54936004 bellard
 * This library is distributed in the hope that it will be useful,
12 54936004 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 54936004 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 54936004 bellard
 * Lesser General Public License for more details.
15 54936004 bellard
 *
16 54936004 bellard
 * You should have received a copy of the GNU Lesser General Public
17 54936004 bellard
 * License along with this library; if not, write to the Free Software
18 54936004 bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 54936004 bellard
 */
20 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 0124311e bellard
#if !defined(CONFIG_USER_ONLY)
1226 0124311e bellard
1227 ee8b7021 bellard
/* NOTE: if flush_global is true, also flush global entries (not
1228 ee8b7021 bellard
   implemented yet) */
1229 ee8b7021 bellard
void tlb_flush(CPUState *env, int flush_global)
1230 33417e70 bellard
{
1231 33417e70 bellard
    int i;
1232 0124311e bellard
1233 9fa3e853 bellard
#if defined(DEBUG_TLB)
1234 9fa3e853 bellard
    printf("tlb_flush:\n");
1235 9fa3e853 bellard
#endif
1236 0124311e bellard
    /* must reset current TB so that interrupts cannot modify the
1237 0124311e bellard
       links while we are modifying them */
1238 0124311e bellard
    env->current_tb = NULL;
1239 0124311e bellard
1240 33417e70 bellard
    for(i = 0; i < CPU_TLB_SIZE; i++) {
1241 84b7b8e7 bellard
        env->tlb_table[0][i].addr_read = -1;
1242 84b7b8e7 bellard
        env->tlb_table[0][i].addr_write = -1;
1243 84b7b8e7 bellard
        env->tlb_table[0][i].addr_code = -1;
1244 84b7b8e7 bellard
        env->tlb_table[1][i].addr_read = -1;
1245 84b7b8e7 bellard
        env->tlb_table[1][i].addr_write = -1;
1246 84b7b8e7 bellard
        env->tlb_table[1][i].addr_code = -1;
1247 33417e70 bellard
    }
1248 9fa3e853 bellard
1249 8a40a180 bellard
    memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
1250 9fa3e853 bellard
1251 9fa3e853 bellard
#if !defined(CONFIG_SOFTMMU)
1252 9fa3e853 bellard
    munmap((void *)MMAP_AREA_START, MMAP_AREA_END - MMAP_AREA_START);
1253 9fa3e853 bellard
#endif
1254 0a962c02 bellard
#ifdef USE_KQEMU
1255 0a962c02 bellard
    if (env->kqemu_enabled) {
1256 0a962c02 bellard
        kqemu_flush(env, flush_global);
1257 0a962c02 bellard
    }
1258 0a962c02 bellard
#endif
1259 e3db7226 bellard
    tlb_flush_count++;
1260 33417e70 bellard
}
1261 33417e70 bellard
1262 274da6b2 bellard
static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
1263 61382a50 bellard
{
1264 84b7b8e7 bellard
    if (addr == (tlb_entry->addr_read & 
1265 84b7b8e7 bellard
                 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1266 84b7b8e7 bellard
        addr == (tlb_entry->addr_write & 
1267 84b7b8e7 bellard
                 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1268 84b7b8e7 bellard
        addr == (tlb_entry->addr_code & 
1269 84b7b8e7 bellard
                 (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1270 84b7b8e7 bellard
        tlb_entry->addr_read = -1;
1271 84b7b8e7 bellard
        tlb_entry->addr_write = -1;
1272 84b7b8e7 bellard
        tlb_entry->addr_code = -1;
1273 84b7b8e7 bellard
    }
1274 61382a50 bellard
}
1275 61382a50 bellard
1276 2e12669a bellard
void tlb_flush_page(CPUState *env, target_ulong addr)
1277 33417e70 bellard
{
1278 8a40a180 bellard
    int i;
1279 9fa3e853 bellard
    TranslationBlock *tb;
1280 0124311e bellard
1281 9fa3e853 bellard
#if defined(DEBUG_TLB)
1282 108c49b8 bellard
    printf("tlb_flush_page: " TARGET_FMT_lx "\n", addr);
1283 9fa3e853 bellard
#endif
1284 0124311e bellard
    /* must reset current TB so that interrupts cannot modify the
1285 0124311e bellard
       links while we are modifying them */
1286 0124311e bellard
    env->current_tb = NULL;
1287 61382a50 bellard
1288 61382a50 bellard
    addr &= TARGET_PAGE_MASK;
1289 61382a50 bellard
    i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1290 84b7b8e7 bellard
    tlb_flush_entry(&env->tlb_table[0][i], addr);
1291 84b7b8e7 bellard
    tlb_flush_entry(&env->tlb_table[1][i], addr);
1292 0124311e bellard
1293 b362e5e0 pbrook
    /* Discard jump cache entries for any tb which might potentially
1294 b362e5e0 pbrook
       overlap the flushed page.  */
1295 b362e5e0 pbrook
    i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
1296 b362e5e0 pbrook
    memset (&env->tb_jmp_cache[i], 0, TB_JMP_PAGE_SIZE * sizeof(tb));
1297 b362e5e0 pbrook
1298 b362e5e0 pbrook
    i = tb_jmp_cache_hash_page(addr);
1299 b362e5e0 pbrook
    memset (&env->tb_jmp_cache[i], 0, TB_JMP_PAGE_SIZE * sizeof(tb));
1300 9fa3e853 bellard
1301 0124311e bellard
#if !defined(CONFIG_SOFTMMU)
1302 9fa3e853 bellard
    if (addr < MMAP_AREA_END)
1303 0124311e bellard
        munmap((void *)addr, TARGET_PAGE_SIZE);
1304 61382a50 bellard
#endif
1305 0a962c02 bellard
#ifdef USE_KQEMU
1306 0a962c02 bellard
    if (env->kqemu_enabled) {
1307 0a962c02 bellard
        kqemu_flush_page(env, addr);
1308 0a962c02 bellard
    }
1309 0a962c02 bellard
#endif
1310 9fa3e853 bellard
}
1311 9fa3e853 bellard
1312 9fa3e853 bellard
/* update the TLBs so that writes to code in the virtual page 'addr'
1313 9fa3e853 bellard
   can be detected */
1314 6a00d601 bellard
static void tlb_protect_code(ram_addr_t ram_addr)
1315 9fa3e853 bellard
{
1316 6a00d601 bellard
    cpu_physical_memory_reset_dirty(ram_addr, 
1317 6a00d601 bellard
                                    ram_addr + TARGET_PAGE_SIZE,
1318 6a00d601 bellard
                                    CODE_DIRTY_FLAG);
1319 9fa3e853 bellard
}
1320 9fa3e853 bellard
1321 9fa3e853 bellard
/* update the TLB so that writes in physical page 'phys_addr' are no longer
1322 3a7d929e bellard
   tested for self modifying code */
1323 3a7d929e bellard
static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr, 
1324 3a7d929e bellard
                                    target_ulong vaddr)
1325 9fa3e853 bellard
{
1326 3a7d929e bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] |= CODE_DIRTY_FLAG;
1327 1ccde1cb bellard
}
1328 1ccde1cb bellard
1329 1ccde1cb bellard
static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, 
1330 1ccde1cb bellard
                                         unsigned long start, unsigned long length)
1331 1ccde1cb bellard
{
1332 1ccde1cb bellard
    unsigned long addr;
1333 84b7b8e7 bellard
    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1334 84b7b8e7 bellard
        addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
1335 1ccde1cb bellard
        if ((addr - start) < length) {
1336 84b7b8e7 bellard
            tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | IO_MEM_NOTDIRTY;
1337 1ccde1cb bellard
        }
1338 1ccde1cb bellard
    }
1339 1ccde1cb bellard
}
1340 1ccde1cb bellard
1341 3a7d929e bellard
void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
1342 0a962c02 bellard
                                     int dirty_flags)
1343 1ccde1cb bellard
{
1344 1ccde1cb bellard
    CPUState *env;
1345 4f2ac237 bellard
    unsigned long length, start1;
1346 0a962c02 bellard
    int i, mask, len;
1347 0a962c02 bellard
    uint8_t *p;
1348 1ccde1cb bellard
1349 1ccde1cb bellard
    start &= TARGET_PAGE_MASK;
1350 1ccde1cb bellard
    end = TARGET_PAGE_ALIGN(end);
1351 1ccde1cb bellard
1352 1ccde1cb bellard
    length = end - start;
1353 1ccde1cb bellard
    if (length == 0)
1354 1ccde1cb bellard
        return;
1355 0a962c02 bellard
    len = length >> TARGET_PAGE_BITS;
1356 3a7d929e bellard
#ifdef USE_KQEMU
1357 6a00d601 bellard
    /* XXX: should not depend on cpu context */
1358 6a00d601 bellard
    env = first_cpu;
1359 3a7d929e bellard
    if (env->kqemu_enabled) {
1360 f23db169 bellard
        ram_addr_t addr;
1361 f23db169 bellard
        addr = start;
1362 f23db169 bellard
        for(i = 0; i < len; i++) {
1363 f23db169 bellard
            kqemu_set_notdirty(env, addr);
1364 f23db169 bellard
            addr += TARGET_PAGE_SIZE;
1365 f23db169 bellard
        }
1366 3a7d929e bellard
    }
1367 3a7d929e bellard
#endif
1368 f23db169 bellard
    mask = ~dirty_flags;
1369 f23db169 bellard
    p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
1370 f23db169 bellard
    for(i = 0; i < len; i++)
1371 f23db169 bellard
        p[i] &= mask;
1372 f23db169 bellard
1373 1ccde1cb bellard
    /* we modify the TLB cache so that the dirty bit will be set again
1374 1ccde1cb bellard
       when accessing the range */
1375 59817ccb bellard
    start1 = start + (unsigned long)phys_ram_base;
1376 6a00d601 bellard
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
1377 6a00d601 bellard
        for(i = 0; i < CPU_TLB_SIZE; i++)
1378 84b7b8e7 bellard
            tlb_reset_dirty_range(&env->tlb_table[0][i], start1, length);
1379 6a00d601 bellard
        for(i = 0; i < CPU_TLB_SIZE; i++)
1380 84b7b8e7 bellard
            tlb_reset_dirty_range(&env->tlb_table[1][i], start1, length);
1381 6a00d601 bellard
    }
1382 59817ccb bellard
1383 59817ccb bellard
#if !defined(CONFIG_SOFTMMU)
1384 59817ccb bellard
    /* XXX: this is expensive */
1385 59817ccb bellard
    {
1386 59817ccb bellard
        VirtPageDesc *p;
1387 59817ccb bellard
        int j;
1388 59817ccb bellard
        target_ulong addr;
1389 59817ccb bellard
1390 59817ccb bellard
        for(i = 0; i < L1_SIZE; i++) {
1391 59817ccb bellard
            p = l1_virt_map[i];
1392 59817ccb bellard
            if (p) {
1393 59817ccb bellard
                addr = i << (TARGET_PAGE_BITS + L2_BITS);
1394 59817ccb bellard
                for(j = 0; j < L2_SIZE; j++) {
1395 59817ccb bellard
                    if (p->valid_tag == virt_valid_tag &&
1396 59817ccb bellard
                        p->phys_addr >= start && p->phys_addr < end &&
1397 59817ccb bellard
                        (p->prot & PROT_WRITE)) {
1398 59817ccb bellard
                        if (addr < MMAP_AREA_END) {
1399 59817ccb bellard
                            mprotect((void *)addr, TARGET_PAGE_SIZE, 
1400 59817ccb bellard
                                     p->prot & ~PROT_WRITE);
1401 59817ccb bellard
                        }
1402 59817ccb bellard
                    }
1403 59817ccb bellard
                    addr += TARGET_PAGE_SIZE;
1404 59817ccb bellard
                    p++;
1405 59817ccb bellard
                }
1406 59817ccb bellard
            }
1407 59817ccb bellard
        }
1408 59817ccb bellard
    }
1409 59817ccb bellard
#endif
1410 1ccde1cb bellard
}
1411 1ccde1cb bellard
1412 3a7d929e bellard
static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1413 3a7d929e bellard
{
1414 3a7d929e bellard
    ram_addr_t ram_addr;
1415 3a7d929e bellard
1416 84b7b8e7 bellard
    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1417 84b7b8e7 bellard
        ram_addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + 
1418 3a7d929e bellard
            tlb_entry->addend - (unsigned long)phys_ram_base;
1419 3a7d929e bellard
        if (!cpu_physical_memory_is_dirty(ram_addr)) {
1420 84b7b8e7 bellard
            tlb_entry->addr_write |= IO_MEM_NOTDIRTY;
1421 3a7d929e bellard
        }
1422 3a7d929e bellard
    }
1423 3a7d929e bellard
}
1424 3a7d929e bellard
1425 3a7d929e bellard
/* update the TLB according to the current state of the dirty bits */
1426 3a7d929e bellard
void cpu_tlb_update_dirty(CPUState *env)
1427 3a7d929e bellard
{
1428 3a7d929e bellard
    int i;
1429 3a7d929e bellard
    for(i = 0; i < CPU_TLB_SIZE; i++)
1430 84b7b8e7 bellard
        tlb_update_dirty(&env->tlb_table[0][i]);
1431 3a7d929e bellard
    for(i = 0; i < CPU_TLB_SIZE; i++)
1432 84b7b8e7 bellard
        tlb_update_dirty(&env->tlb_table[1][i]);
1433 3a7d929e bellard
}
1434 3a7d929e bellard
1435 1ccde1cb bellard
static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, 
1436 108c49b8 bellard
                                  unsigned long start)
1437 1ccde1cb bellard
{
1438 1ccde1cb bellard
    unsigned long addr;
1439 84b7b8e7 bellard
    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_NOTDIRTY) {
1440 84b7b8e7 bellard
        addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
1441 1ccde1cb bellard
        if (addr == start) {
1442 84b7b8e7 bellard
            tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | IO_MEM_RAM;
1443 1ccde1cb bellard
        }
1444 1ccde1cb bellard
    }
1445 1ccde1cb bellard
}
1446 1ccde1cb bellard
1447 1ccde1cb bellard
/* update the TLB corresponding to virtual page vaddr and phys addr
1448 1ccde1cb bellard
   addr so that it is no longer dirty */
1449 6a00d601 bellard
static inline void tlb_set_dirty(CPUState *env,
1450 6a00d601 bellard
                                 unsigned long addr, target_ulong vaddr)
1451 1ccde1cb bellard
{
1452 1ccde1cb bellard
    int i;
1453 1ccde1cb bellard
1454 1ccde1cb bellard
    addr &= TARGET_PAGE_MASK;
1455 1ccde1cb bellard
    i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1456 84b7b8e7 bellard
    tlb_set_dirty1(&env->tlb_table[0][i], addr);
1457 84b7b8e7 bellard
    tlb_set_dirty1(&env->tlb_table[1][i], addr);
1458 9fa3e853 bellard
}
1459 9fa3e853 bellard
1460 59817ccb bellard
/* add a new TLB entry. At most one entry for a given virtual address
1461 59817ccb bellard
   is permitted. Return 0 if OK or 2 if the page could not be mapped
1462 59817ccb bellard
   (can only happen in non SOFTMMU mode for I/O pages or pages
1463 59817ccb bellard
   conflicting with the host address space). */
1464 84b7b8e7 bellard
int tlb_set_page_exec(CPUState *env, target_ulong vaddr, 
1465 84b7b8e7 bellard
                      target_phys_addr_t paddr, int prot, 
1466 84b7b8e7 bellard
                      int is_user, int is_softmmu)
1467 9fa3e853 bellard
{
1468 92e873b9 bellard
    PhysPageDesc *p;
1469 4f2ac237 bellard
    unsigned long pd;
1470 9fa3e853 bellard
    unsigned int index;
1471 4f2ac237 bellard
    target_ulong address;
1472 108c49b8 bellard
    target_phys_addr_t addend;
1473 9fa3e853 bellard
    int ret;
1474 84b7b8e7 bellard
    CPUTLBEntry *te;
1475 9fa3e853 bellard
1476 92e873b9 bellard
    p = phys_page_find(paddr >> TARGET_PAGE_BITS);
1477 9fa3e853 bellard
    if (!p) {
1478 9fa3e853 bellard
        pd = IO_MEM_UNASSIGNED;
1479 9fa3e853 bellard
    } else {
1480 9fa3e853 bellard
        pd = p->phys_offset;
1481 9fa3e853 bellard
    }
1482 9fa3e853 bellard
#if defined(DEBUG_TLB)
1483 3a7d929e bellard
    printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x u=%d smmu=%d pd=0x%08lx\n",
1484 84b7b8e7 bellard
           vaddr, (int)paddr, prot, is_user, is_softmmu, pd);
1485 9fa3e853 bellard
#endif
1486 9fa3e853 bellard
1487 9fa3e853 bellard
    ret = 0;
1488 9fa3e853 bellard
#if !defined(CONFIG_SOFTMMU)
1489 9fa3e853 bellard
    if (is_softmmu) 
1490 9fa3e853 bellard
#endif
1491 9fa3e853 bellard
    {
1492 2a4188a3 bellard
        if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
1493 9fa3e853 bellard
            /* IO memory case */
1494 9fa3e853 bellard
            address = vaddr | pd;
1495 9fa3e853 bellard
            addend = paddr;
1496 9fa3e853 bellard
        } else {
1497 9fa3e853 bellard
            /* standard memory */
1498 9fa3e853 bellard
            address = vaddr;
1499 9fa3e853 bellard
            addend = (unsigned long)phys_ram_base + (pd & TARGET_PAGE_MASK);
1500 9fa3e853 bellard
        }
1501 9fa3e853 bellard
        
1502 90f18422 bellard
        index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1503 9fa3e853 bellard
        addend -= vaddr;
1504 84b7b8e7 bellard
        te = &env->tlb_table[is_user][index];
1505 84b7b8e7 bellard
        te->addend = addend;
1506 67b915a5 bellard
        if (prot & PAGE_READ) {
1507 84b7b8e7 bellard
            te->addr_read = address;
1508 84b7b8e7 bellard
        } else {
1509 84b7b8e7 bellard
            te->addr_read = -1;
1510 84b7b8e7 bellard
        }
1511 84b7b8e7 bellard
        if (prot & PAGE_EXEC) {
1512 84b7b8e7 bellard
            te->addr_code = address;
1513 9fa3e853 bellard
        } else {
1514 84b7b8e7 bellard
            te->addr_code = -1;
1515 9fa3e853 bellard
        }
1516 67b915a5 bellard
        if (prot & PAGE_WRITE) {
1517 856074ec bellard
            if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM || 
1518 856074ec bellard
                (pd & IO_MEM_ROMD)) {
1519 856074ec bellard
                /* write access calls the I/O callback */
1520 856074ec bellard
                te->addr_write = vaddr | 
1521 856074ec bellard
                    (pd & ~(TARGET_PAGE_MASK | IO_MEM_ROMD));
1522 3a7d929e bellard
            } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM && 
1523 1ccde1cb bellard
                       !cpu_physical_memory_is_dirty(pd)) {
1524 84b7b8e7 bellard
                te->addr_write = vaddr | IO_MEM_NOTDIRTY;
1525 9fa3e853 bellard
            } else {
1526 84b7b8e7 bellard
                te->addr_write = address;
1527 9fa3e853 bellard
            }
1528 9fa3e853 bellard
        } else {
1529 84b7b8e7 bellard
            te->addr_write = -1;
1530 9fa3e853 bellard
        }
1531 9fa3e853 bellard
    }
1532 9fa3e853 bellard
#if !defined(CONFIG_SOFTMMU)
1533 9fa3e853 bellard
    else {
1534 9fa3e853 bellard
        if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
1535 9fa3e853 bellard
            /* IO access: no mapping is done as it will be handled by the
1536 9fa3e853 bellard
               soft MMU */
1537 9fa3e853 bellard
            if (!(env->hflags & HF_SOFTMMU_MASK))
1538 9fa3e853 bellard
                ret = 2;
1539 9fa3e853 bellard
        } else {
1540 9fa3e853 bellard
            void *map_addr;
1541 59817ccb bellard
1542 59817ccb bellard
            if (vaddr >= MMAP_AREA_END) {
1543 59817ccb bellard
                ret = 2;
1544 59817ccb bellard
            } else {
1545 59817ccb bellard
                if (prot & PROT_WRITE) {
1546 59817ccb bellard
                    if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM || 
1547 d720b93d bellard
#if defined(TARGET_HAS_SMC) || 1
1548 59817ccb bellard
                        first_tb ||
1549 d720b93d bellard
#endif
1550 59817ccb bellard
                        ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM && 
1551 59817ccb bellard
                         !cpu_physical_memory_is_dirty(pd))) {
1552 59817ccb bellard
                        /* ROM: we do as if code was inside */
1553 59817ccb bellard
                        /* if code is present, we only map as read only and save the
1554 59817ccb bellard
                           original mapping */
1555 59817ccb bellard
                        VirtPageDesc *vp;
1556 59817ccb bellard
                        
1557 90f18422 bellard
                        vp = virt_page_find_alloc(vaddr >> TARGET_PAGE_BITS, 1);
1558 59817ccb bellard
                        vp->phys_addr = pd;
1559 59817ccb bellard
                        vp->prot = prot;
1560 59817ccb bellard
                        vp->valid_tag = virt_valid_tag;
1561 59817ccb bellard
                        prot &= ~PAGE_WRITE;
1562 59817ccb bellard
                    }
1563 59817ccb bellard
                }
1564 59817ccb bellard
                map_addr = mmap((void *)vaddr, TARGET_PAGE_SIZE, prot, 
1565 59817ccb bellard
                                MAP_SHARED | MAP_FIXED, phys_ram_fd, (pd & TARGET_PAGE_MASK));
1566 59817ccb bellard
                if (map_addr == MAP_FAILED) {
1567 59817ccb bellard
                    cpu_abort(env, "mmap failed when mapped physical address 0x%08x to virtual address 0x%08x\n",
1568 59817ccb bellard
                              paddr, vaddr);
1569 9fa3e853 bellard
                }
1570 9fa3e853 bellard
            }
1571 9fa3e853 bellard
        }
1572 9fa3e853 bellard
    }
1573 9fa3e853 bellard
#endif
1574 9fa3e853 bellard
    return ret;
1575 9fa3e853 bellard
}
1576 9fa3e853 bellard
1577 9fa3e853 bellard
/* called from signal handler: invalidate the code and unprotect the
1578 9fa3e853 bellard
   page. Return TRUE if the fault was succesfully handled. */
1579 53a5960a pbrook
int page_unprotect(target_ulong addr, unsigned long pc, void *puc)
1580 9fa3e853 bellard
{
1581 9fa3e853 bellard
#if !defined(CONFIG_SOFTMMU)
1582 9fa3e853 bellard
    VirtPageDesc *vp;
1583 9fa3e853 bellard
1584 9fa3e853 bellard
#if defined(DEBUG_TLB)
1585 9fa3e853 bellard
    printf("page_unprotect: addr=0x%08x\n", addr);
1586 9fa3e853 bellard
#endif
1587 9fa3e853 bellard
    addr &= TARGET_PAGE_MASK;
1588 59817ccb bellard
1589 59817ccb bellard
    /* if it is not mapped, no need to worry here */
1590 59817ccb bellard
    if (addr >= MMAP_AREA_END)
1591 59817ccb bellard
        return 0;
1592 9fa3e853 bellard
    vp = virt_page_find(addr >> TARGET_PAGE_BITS);
1593 9fa3e853 bellard
    if (!vp)
1594 9fa3e853 bellard
        return 0;
1595 9fa3e853 bellard
    /* NOTE: in this case, validate_tag is _not_ tested as it
1596 9fa3e853 bellard
       validates only the code TLB */
1597 9fa3e853 bellard
    if (vp->valid_tag != virt_valid_tag)
1598 9fa3e853 bellard
        return 0;
1599 9fa3e853 bellard
    if (!(vp->prot & PAGE_WRITE))
1600 9fa3e853 bellard
        return 0;
1601 9fa3e853 bellard
#if defined(DEBUG_TLB)
1602 9fa3e853 bellard
    printf("page_unprotect: addr=0x%08x phys_addr=0x%08x prot=%x\n", 
1603 9fa3e853 bellard
           addr, vp->phys_addr, vp->prot);
1604 9fa3e853 bellard
#endif
1605 59817ccb bellard
    if (mprotect((void *)addr, TARGET_PAGE_SIZE, vp->prot) < 0)
1606 59817ccb bellard
        cpu_abort(cpu_single_env, "error mprotect addr=0x%lx prot=%d\n",
1607 59817ccb bellard
                  (unsigned long)addr, vp->prot);
1608 d720b93d bellard
    /* set the dirty bit */
1609 0a962c02 bellard
    phys_ram_dirty[vp->phys_addr >> TARGET_PAGE_BITS] = 0xff;
1610 d720b93d bellard
    /* flush the code inside */
1611 d720b93d bellard
    tb_invalidate_phys_page(vp->phys_addr, pc, puc);
1612 9fa3e853 bellard
    return 1;
1613 9fa3e853 bellard
#else
1614 9fa3e853 bellard
    return 0;
1615 9fa3e853 bellard
#endif
1616 33417e70 bellard
}
1617 33417e70 bellard
1618 0124311e bellard
#else
1619 0124311e bellard
1620 ee8b7021 bellard
void tlb_flush(CPUState *env, int flush_global)
1621 0124311e bellard
{
1622 0124311e bellard
}
1623 0124311e bellard
1624 2e12669a bellard
void tlb_flush_page(CPUState *env, target_ulong addr)
1625 0124311e bellard
{
1626 0124311e bellard
}
1627 0124311e bellard
1628 84b7b8e7 bellard
int tlb_set_page_exec(CPUState *env, target_ulong vaddr, 
1629 84b7b8e7 bellard
                      target_phys_addr_t paddr, int prot, 
1630 84b7b8e7 bellard
                      int is_user, int is_softmmu)
1631 9fa3e853 bellard
{
1632 9fa3e853 bellard
    return 0;
1633 9fa3e853 bellard
}
1634 0124311e bellard
1635 9fa3e853 bellard
/* dump memory mappings */
1636 9fa3e853 bellard
void page_dump(FILE *f)
1637 33417e70 bellard
{
1638 9fa3e853 bellard
    unsigned long start, end;
1639 9fa3e853 bellard
    int i, j, prot, prot1;
1640 9fa3e853 bellard
    PageDesc *p;
1641 33417e70 bellard
1642 9fa3e853 bellard
    fprintf(f, "%-8s %-8s %-8s %s\n",
1643 9fa3e853 bellard
            "start", "end", "size", "prot");
1644 9fa3e853 bellard
    start = -1;
1645 9fa3e853 bellard
    end = -1;
1646 9fa3e853 bellard
    prot = 0;
1647 9fa3e853 bellard
    for(i = 0; i <= L1_SIZE; i++) {
1648 9fa3e853 bellard
        if (i < L1_SIZE)
1649 9fa3e853 bellard
            p = l1_map[i];
1650 9fa3e853 bellard
        else
1651 9fa3e853 bellard
            p = NULL;
1652 9fa3e853 bellard
        for(j = 0;j < L2_SIZE; j++) {
1653 9fa3e853 bellard
            if (!p)
1654 9fa3e853 bellard
                prot1 = 0;
1655 9fa3e853 bellard
            else
1656 9fa3e853 bellard
                prot1 = p[j].flags;
1657 9fa3e853 bellard
            if (prot1 != prot) {
1658 9fa3e853 bellard
                end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
1659 9fa3e853 bellard
                if (start != -1) {
1660 9fa3e853 bellard
                    fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
1661 9fa3e853 bellard
                            start, end, end - start, 
1662 9fa3e853 bellard
                            prot & PAGE_READ ? 'r' : '-',
1663 9fa3e853 bellard
                            prot & PAGE_WRITE ? 'w' : '-',
1664 9fa3e853 bellard
                            prot & PAGE_EXEC ? 'x' : '-');
1665 9fa3e853 bellard
                }
1666 9fa3e853 bellard
                if (prot1 != 0)
1667 9fa3e853 bellard
                    start = end;
1668 9fa3e853 bellard
                else
1669 9fa3e853 bellard
                    start = -1;
1670 9fa3e853 bellard
                prot = prot1;
1671 9fa3e853 bellard
            }
1672 9fa3e853 bellard
            if (!p)
1673 9fa3e853 bellard
                break;
1674 9fa3e853 bellard
        }
1675 33417e70 bellard
    }
1676 33417e70 bellard
}
1677 33417e70 bellard
1678 53a5960a pbrook
int page_get_flags(target_ulong address)
1679 33417e70 bellard
{
1680 9fa3e853 bellard
    PageDesc *p;
1681 9fa3e853 bellard
1682 9fa3e853 bellard
    p = page_find(address >> TARGET_PAGE_BITS);
1683 33417e70 bellard
    if (!p)
1684 9fa3e853 bellard
        return 0;
1685 9fa3e853 bellard
    return p->flags;
1686 9fa3e853 bellard
}
1687 9fa3e853 bellard
1688 9fa3e853 bellard
/* modify the flags of a page and invalidate the code if
1689 9fa3e853 bellard
   necessary. The flag PAGE_WRITE_ORG is positionned automatically
1690 9fa3e853 bellard
   depending on PAGE_WRITE */
1691 53a5960a pbrook
void page_set_flags(target_ulong start, target_ulong end, int flags)
1692 9fa3e853 bellard
{
1693 9fa3e853 bellard
    PageDesc *p;
1694 53a5960a pbrook
    target_ulong addr;
1695 9fa3e853 bellard
1696 9fa3e853 bellard
    start = start & TARGET_PAGE_MASK;
1697 9fa3e853 bellard
    end = TARGET_PAGE_ALIGN(end);
1698 9fa3e853 bellard
    if (flags & PAGE_WRITE)
1699 9fa3e853 bellard
        flags |= PAGE_WRITE_ORG;
1700 9fa3e853 bellard
    spin_lock(&tb_lock);
1701 9fa3e853 bellard
    for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1702 9fa3e853 bellard
        p = page_find_alloc(addr >> TARGET_PAGE_BITS);
1703 9fa3e853 bellard
        /* if the write protection is set, then we invalidate the code
1704 9fa3e853 bellard
           inside */
1705 9fa3e853 bellard
        if (!(p->flags & PAGE_WRITE) && 
1706 9fa3e853 bellard
            (flags & PAGE_WRITE) &&
1707 9fa3e853 bellard
            p->first_tb) {
1708 d720b93d bellard
            tb_invalidate_phys_page(addr, 0, NULL);
1709 9fa3e853 bellard
        }
1710 9fa3e853 bellard
        p->flags = flags;
1711 9fa3e853 bellard
    }
1712 9fa3e853 bellard
    spin_unlock(&tb_lock);
1713 33417e70 bellard
}
1714 33417e70 bellard
1715 9fa3e853 bellard
/* called from signal handler: invalidate the code and unprotect the
1716 9fa3e853 bellard
   page. Return TRUE if the fault was succesfully handled. */
1717 53a5960a pbrook
int page_unprotect(target_ulong address, unsigned long pc, void *puc)
1718 9fa3e853 bellard
{
1719 9fa3e853 bellard
    unsigned int page_index, prot, pindex;
1720 9fa3e853 bellard
    PageDesc *p, *p1;
1721 53a5960a pbrook
    target_ulong host_start, host_end, addr;
1722 9fa3e853 bellard
1723 83fb7adf bellard
    host_start = address & qemu_host_page_mask;
1724 9fa3e853 bellard
    page_index = host_start >> TARGET_PAGE_BITS;
1725 9fa3e853 bellard
    p1 = page_find(page_index);
1726 9fa3e853 bellard
    if (!p1)
1727 9fa3e853 bellard
        return 0;
1728 83fb7adf bellard
    host_end = host_start + qemu_host_page_size;
1729 9fa3e853 bellard
    p = p1;
1730 9fa3e853 bellard
    prot = 0;
1731 9fa3e853 bellard
    for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
1732 9fa3e853 bellard
        prot |= p->flags;
1733 9fa3e853 bellard
        p++;
1734 9fa3e853 bellard
    }
1735 9fa3e853 bellard
    /* if the page was really writable, then we change its
1736 9fa3e853 bellard
       protection back to writable */
1737 9fa3e853 bellard
    if (prot & PAGE_WRITE_ORG) {
1738 9fa3e853 bellard
        pindex = (address - host_start) >> TARGET_PAGE_BITS;
1739 9fa3e853 bellard
        if (!(p1[pindex].flags & PAGE_WRITE)) {
1740 53a5960a pbrook
            mprotect((void *)g2h(host_start), qemu_host_page_size, 
1741 9fa3e853 bellard
                     (prot & PAGE_BITS) | PAGE_WRITE);
1742 9fa3e853 bellard
            p1[pindex].flags |= PAGE_WRITE;
1743 9fa3e853 bellard
            /* and since the content will be modified, we must invalidate
1744 9fa3e853 bellard
               the corresponding translated code. */
1745 d720b93d bellard
            tb_invalidate_phys_page(address, pc, puc);
1746 9fa3e853 bellard
#ifdef DEBUG_TB_CHECK
1747 9fa3e853 bellard
            tb_invalidate_check(address);
1748 9fa3e853 bellard
#endif
1749 9fa3e853 bellard
            return 1;
1750 9fa3e853 bellard
        }
1751 9fa3e853 bellard
    }
1752 9fa3e853 bellard
    return 0;
1753 9fa3e853 bellard
}
1754 9fa3e853 bellard
1755 9fa3e853 bellard
/* call this function when system calls directly modify a memory area */
1756 53a5960a pbrook
/* ??? This should be redundant now we have lock_user.  */
1757 53a5960a pbrook
void page_unprotect_range(target_ulong data, target_ulong data_size)
1758 9fa3e853 bellard
{
1759 53a5960a pbrook
    target_ulong start, end, addr;
1760 9fa3e853 bellard
1761 53a5960a pbrook
    start = data;
1762 9fa3e853 bellard
    end = start + data_size;
1763 9fa3e853 bellard
    start &= TARGET_PAGE_MASK;
1764 9fa3e853 bellard
    end = TARGET_PAGE_ALIGN(end);
1765 9fa3e853 bellard
    for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1766 d720b93d bellard
        page_unprotect(addr, 0, NULL);
1767 9fa3e853 bellard
    }
1768 9fa3e853 bellard
}
1769 9fa3e853 bellard
1770 6a00d601 bellard
static inline void tlb_set_dirty(CPUState *env,
1771 6a00d601 bellard
                                 unsigned long addr, target_ulong vaddr)
1772 1ccde1cb bellard
{
1773 1ccde1cb bellard
}
1774 9fa3e853 bellard
#endif /* defined(CONFIG_USER_ONLY) */
1775 9fa3e853 bellard
1776 33417e70 bellard
/* register physical memory. 'size' must be a multiple of the target
1777 33417e70 bellard
   page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
1778 33417e70 bellard
   io memory page */
1779 2e12669a bellard
void cpu_register_physical_memory(target_phys_addr_t start_addr, 
1780 2e12669a bellard
                                  unsigned long size,
1781 2e12669a bellard
                                  unsigned long phys_offset)
1782 33417e70 bellard
{
1783 108c49b8 bellard
    target_phys_addr_t addr, end_addr;
1784 92e873b9 bellard
    PhysPageDesc *p;
1785 9d42037b bellard
    CPUState *env;
1786 33417e70 bellard
1787 5fd386f6 bellard
    size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
1788 33417e70 bellard
    end_addr = start_addr + size;
1789 5fd386f6 bellard
    for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
1790 108c49b8 bellard
        p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
1791 9fa3e853 bellard
        p->phys_offset = phys_offset;
1792 2a4188a3 bellard
        if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
1793 2a4188a3 bellard
            (phys_offset & IO_MEM_ROMD))
1794 33417e70 bellard
            phys_offset += TARGET_PAGE_SIZE;
1795 33417e70 bellard
    }
1796 9d42037b bellard
    
1797 9d42037b bellard
    /* since each CPU stores ram addresses in its TLB cache, we must
1798 9d42037b bellard
       reset the modified entries */
1799 9d42037b bellard
    /* XXX: slow ! */
1800 9d42037b bellard
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
1801 9d42037b bellard
        tlb_flush(env, 1);
1802 9d42037b bellard
    }
1803 33417e70 bellard
}
1804 33417e70 bellard
1805 ba863458 bellard
/* XXX: temporary until new memory mapping API */
1806 ba863458 bellard
uint32_t cpu_get_physical_page_desc(target_phys_addr_t addr)
1807 ba863458 bellard
{
1808 ba863458 bellard
    PhysPageDesc *p;
1809 ba863458 bellard
1810 ba863458 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
1811 ba863458 bellard
    if (!p)
1812 ba863458 bellard
        return IO_MEM_UNASSIGNED;
1813 ba863458 bellard
    return p->phys_offset;
1814 ba863458 bellard
}
1815 ba863458 bellard
1816 e9a1ab19 bellard
/* XXX: better than nothing */
1817 e9a1ab19 bellard
ram_addr_t qemu_ram_alloc(unsigned int size)
1818 e9a1ab19 bellard
{
1819 e9a1ab19 bellard
    ram_addr_t addr;
1820 e9a1ab19 bellard
    if ((phys_ram_alloc_offset + size) >= phys_ram_size) {
1821 e9a1ab19 bellard
        fprintf(stderr, "Not enough memory (requested_size = %u, max memory = %d)\n", 
1822 e9a1ab19 bellard
                size, phys_ram_size);
1823 e9a1ab19 bellard
        abort();
1824 e9a1ab19 bellard
    }
1825 e9a1ab19 bellard
    addr = phys_ram_alloc_offset;
1826 e9a1ab19 bellard
    phys_ram_alloc_offset = TARGET_PAGE_ALIGN(phys_ram_alloc_offset + size);
1827 e9a1ab19 bellard
    return addr;
1828 e9a1ab19 bellard
}
1829 e9a1ab19 bellard
1830 e9a1ab19 bellard
void qemu_ram_free(ram_addr_t addr)
1831 e9a1ab19 bellard
{
1832 e9a1ab19 bellard
}
1833 e9a1ab19 bellard
1834 a4193c8a bellard
static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
1835 33417e70 bellard
{
1836 67d3b957 pbrook
#ifdef DEBUG_UNASSIGNED
1837 67d3b957 pbrook
    printf("Unassigned mem read  0x%08x\n", (int)addr);
1838 67d3b957 pbrook
#endif
1839 33417e70 bellard
    return 0;
1840 33417e70 bellard
}
1841 33417e70 bellard
1842 a4193c8a bellard
static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
1843 33417e70 bellard
{
1844 67d3b957 pbrook
#ifdef DEBUG_UNASSIGNED
1845 67d3b957 pbrook
    printf("Unassigned mem write 0x%08x = 0x%x\n", (int)addr, val);
1846 67d3b957 pbrook
#endif
1847 33417e70 bellard
}
1848 33417e70 bellard
1849 33417e70 bellard
static CPUReadMemoryFunc *unassigned_mem_read[3] = {
1850 33417e70 bellard
    unassigned_mem_readb,
1851 33417e70 bellard
    unassigned_mem_readb,
1852 33417e70 bellard
    unassigned_mem_readb,
1853 33417e70 bellard
};
1854 33417e70 bellard
1855 33417e70 bellard
static CPUWriteMemoryFunc *unassigned_mem_write[3] = {
1856 33417e70 bellard
    unassigned_mem_writeb,
1857 33417e70 bellard
    unassigned_mem_writeb,
1858 33417e70 bellard
    unassigned_mem_writeb,
1859 33417e70 bellard
};
1860 33417e70 bellard
1861 3a7d929e bellard
static void notdirty_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
1862 9fa3e853 bellard
{
1863 3a7d929e bellard
    unsigned long ram_addr;
1864 3a7d929e bellard
    int dirty_flags;
1865 3a7d929e bellard
    ram_addr = addr - (unsigned long)phys_ram_base;
1866 3a7d929e bellard
    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
1867 3a7d929e bellard
    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
1868 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
1869 3a7d929e bellard
        tb_invalidate_phys_page_fast(ram_addr, 1);
1870 3a7d929e bellard
        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
1871 9fa3e853 bellard
#endif
1872 3a7d929e bellard
    }
1873 c27004ec bellard
    stb_p((uint8_t *)(long)addr, val);
1874 f32fc648 bellard
#ifdef USE_KQEMU
1875 f32fc648 bellard
    if (cpu_single_env->kqemu_enabled &&
1876 f32fc648 bellard
        (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
1877 f32fc648 bellard
        kqemu_modify_page(cpu_single_env, ram_addr);
1878 f32fc648 bellard
#endif
1879 f23db169 bellard
    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
1880 f23db169 bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
1881 f23db169 bellard
    /* we remove the notdirty callback only if the code has been
1882 f23db169 bellard
       flushed */
1883 f23db169 bellard
    if (dirty_flags == 0xff)
1884 6a00d601 bellard
        tlb_set_dirty(cpu_single_env, addr, cpu_single_env->mem_write_vaddr);
1885 9fa3e853 bellard
}
1886 9fa3e853 bellard
1887 3a7d929e bellard
static void notdirty_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
1888 9fa3e853 bellard
{
1889 3a7d929e bellard
    unsigned long ram_addr;
1890 3a7d929e bellard
    int dirty_flags;
1891 3a7d929e bellard
    ram_addr = addr - (unsigned long)phys_ram_base;
1892 3a7d929e bellard
    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
1893 3a7d929e bellard
    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
1894 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
1895 3a7d929e bellard
        tb_invalidate_phys_page_fast(ram_addr, 2);
1896 3a7d929e bellard
        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
1897 9fa3e853 bellard
#endif
1898 3a7d929e bellard
    }
1899 c27004ec bellard
    stw_p((uint8_t *)(long)addr, val);
1900 f32fc648 bellard
#ifdef USE_KQEMU
1901 f32fc648 bellard
    if (cpu_single_env->kqemu_enabled &&
1902 f32fc648 bellard
        (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
1903 f32fc648 bellard
        kqemu_modify_page(cpu_single_env, ram_addr);
1904 f32fc648 bellard
#endif
1905 f23db169 bellard
    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
1906 f23db169 bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
1907 f23db169 bellard
    /* we remove the notdirty callback only if the code has been
1908 f23db169 bellard
       flushed */
1909 f23db169 bellard
    if (dirty_flags == 0xff)
1910 6a00d601 bellard
        tlb_set_dirty(cpu_single_env, addr, cpu_single_env->mem_write_vaddr);
1911 9fa3e853 bellard
}
1912 9fa3e853 bellard
1913 3a7d929e bellard
static void notdirty_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
1914 9fa3e853 bellard
{
1915 3a7d929e bellard
    unsigned long ram_addr;
1916 3a7d929e bellard
    int dirty_flags;
1917 3a7d929e bellard
    ram_addr = addr - (unsigned long)phys_ram_base;
1918 3a7d929e bellard
    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
1919 3a7d929e bellard
    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
1920 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
1921 3a7d929e bellard
        tb_invalidate_phys_page_fast(ram_addr, 4);
1922 3a7d929e bellard
        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
1923 9fa3e853 bellard
#endif
1924 3a7d929e bellard
    }
1925 c27004ec bellard
    stl_p((uint8_t *)(long)addr, val);
1926 f32fc648 bellard
#ifdef USE_KQEMU
1927 f32fc648 bellard
    if (cpu_single_env->kqemu_enabled &&
1928 f32fc648 bellard
        (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
1929 f32fc648 bellard
        kqemu_modify_page(cpu_single_env, ram_addr);
1930 f32fc648 bellard
#endif
1931 f23db169 bellard
    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
1932 f23db169 bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
1933 f23db169 bellard
    /* we remove the notdirty callback only if the code has been
1934 f23db169 bellard
       flushed */
1935 f23db169 bellard
    if (dirty_flags == 0xff)
1936 6a00d601 bellard
        tlb_set_dirty(cpu_single_env, addr, cpu_single_env->mem_write_vaddr);
1937 9fa3e853 bellard
}
1938 9fa3e853 bellard
1939 3a7d929e bellard
static CPUReadMemoryFunc *error_mem_read[3] = {
1940 9fa3e853 bellard
    NULL, /* never used */
1941 9fa3e853 bellard
    NULL, /* never used */
1942 9fa3e853 bellard
    NULL, /* never used */
1943 9fa3e853 bellard
};
1944 9fa3e853 bellard
1945 1ccde1cb bellard
static CPUWriteMemoryFunc *notdirty_mem_write[3] = {
1946 1ccde1cb bellard
    notdirty_mem_writeb,
1947 1ccde1cb bellard
    notdirty_mem_writew,
1948 1ccde1cb bellard
    notdirty_mem_writel,
1949 1ccde1cb bellard
};
1950 1ccde1cb bellard
1951 33417e70 bellard
static void io_mem_init(void)
1952 33417e70 bellard
{
1953 3a7d929e bellard
    cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read, unassigned_mem_write, NULL);
1954 a4193c8a bellard
    cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write, NULL);
1955 3a7d929e bellard
    cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read, notdirty_mem_write, NULL);
1956 1ccde1cb bellard
    io_mem_nb = 5;
1957 1ccde1cb bellard
1958 1ccde1cb bellard
    /* alloc dirty bits array */
1959 0a962c02 bellard
    phys_ram_dirty = qemu_vmalloc(phys_ram_size >> TARGET_PAGE_BITS);
1960 3a7d929e bellard
    memset(phys_ram_dirty, 0xff, phys_ram_size >> TARGET_PAGE_BITS);
1961 33417e70 bellard
}
1962 33417e70 bellard
1963 33417e70 bellard
/* mem_read and mem_write are arrays of functions containing the
1964 33417e70 bellard
   function to access byte (index 0), word (index 1) and dword (index
1965 33417e70 bellard
   2). All functions must be supplied. If io_index is non zero, the
1966 33417e70 bellard
   corresponding io zone is modified. If it is zero, a new io zone is
1967 33417e70 bellard
   allocated. The return value can be used with
1968 33417e70 bellard
   cpu_register_physical_memory(). (-1) is returned if error. */
1969 33417e70 bellard
int cpu_register_io_memory(int io_index,
1970 33417e70 bellard
                           CPUReadMemoryFunc **mem_read,
1971 a4193c8a bellard
                           CPUWriteMemoryFunc **mem_write,
1972 a4193c8a bellard
                           void *opaque)
1973 33417e70 bellard
{
1974 33417e70 bellard
    int i;
1975 33417e70 bellard
1976 33417e70 bellard
    if (io_index <= 0) {
1977 b5ff1b31 bellard
        if (io_mem_nb >= IO_MEM_NB_ENTRIES)
1978 33417e70 bellard
            return -1;
1979 33417e70 bellard
        io_index = io_mem_nb++;
1980 33417e70 bellard
    } else {
1981 33417e70 bellard
        if (io_index >= IO_MEM_NB_ENTRIES)
1982 33417e70 bellard
            return -1;
1983 33417e70 bellard
    }
1984 b5ff1b31 bellard
1985 33417e70 bellard
    for(i = 0;i < 3; i++) {
1986 33417e70 bellard
        io_mem_read[io_index][i] = mem_read[i];
1987 33417e70 bellard
        io_mem_write[io_index][i] = mem_write[i];
1988 33417e70 bellard
    }
1989 a4193c8a bellard
    io_mem_opaque[io_index] = opaque;
1990 33417e70 bellard
    return io_index << IO_MEM_SHIFT;
1991 33417e70 bellard
}
1992 61382a50 bellard
1993 8926b517 bellard
CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index)
1994 8926b517 bellard
{
1995 8926b517 bellard
    return io_mem_write[io_index >> IO_MEM_SHIFT];
1996 8926b517 bellard
}
1997 8926b517 bellard
1998 8926b517 bellard
CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index)
1999 8926b517 bellard
{
2000 8926b517 bellard
    return io_mem_read[io_index >> IO_MEM_SHIFT];
2001 8926b517 bellard
}
2002 8926b517 bellard
2003 13eb76e0 bellard
/* physical memory access (slow version, mainly for debug) */
2004 13eb76e0 bellard
#if defined(CONFIG_USER_ONLY)
2005 2e12669a bellard
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, 
2006 13eb76e0 bellard
                            int len, int is_write)
2007 13eb76e0 bellard
{
2008 13eb76e0 bellard
    int l, flags;
2009 13eb76e0 bellard
    target_ulong page;
2010 53a5960a pbrook
    void * p;
2011 13eb76e0 bellard
2012 13eb76e0 bellard
    while (len > 0) {
2013 13eb76e0 bellard
        page = addr & TARGET_PAGE_MASK;
2014 13eb76e0 bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
2015 13eb76e0 bellard
        if (l > len)
2016 13eb76e0 bellard
            l = len;
2017 13eb76e0 bellard
        flags = page_get_flags(page);
2018 13eb76e0 bellard
        if (!(flags & PAGE_VALID))
2019 13eb76e0 bellard
            return;
2020 13eb76e0 bellard
        if (is_write) {
2021 13eb76e0 bellard
            if (!(flags & PAGE_WRITE))
2022 13eb76e0 bellard
                return;
2023 53a5960a pbrook
            p = lock_user(addr, len, 0);
2024 53a5960a pbrook
            memcpy(p, buf, len);
2025 53a5960a pbrook
            unlock_user(p, addr, len);
2026 13eb76e0 bellard
        } else {
2027 13eb76e0 bellard
            if (!(flags & PAGE_READ))
2028 13eb76e0 bellard
                return;
2029 53a5960a pbrook
            p = lock_user(addr, len, 1);
2030 53a5960a pbrook
            memcpy(buf, p, len);
2031 53a5960a pbrook
            unlock_user(p, addr, 0);
2032 13eb76e0 bellard
        }
2033 13eb76e0 bellard
        len -= l;
2034 13eb76e0 bellard
        buf += l;
2035 13eb76e0 bellard
        addr += l;
2036 13eb76e0 bellard
    }
2037 13eb76e0 bellard
}
2038 8df1cd07 bellard
2039 13eb76e0 bellard
#else
2040 2e12669a bellard
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, 
2041 13eb76e0 bellard
                            int len, int is_write)
2042 13eb76e0 bellard
{
2043 13eb76e0 bellard
    int l, io_index;
2044 13eb76e0 bellard
    uint8_t *ptr;
2045 13eb76e0 bellard
    uint32_t val;
2046 2e12669a bellard
    target_phys_addr_t page;
2047 2e12669a bellard
    unsigned long pd;
2048 92e873b9 bellard
    PhysPageDesc *p;
2049 13eb76e0 bellard
    
2050 13eb76e0 bellard
    while (len > 0) {
2051 13eb76e0 bellard
        page = addr & TARGET_PAGE_MASK;
2052 13eb76e0 bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
2053 13eb76e0 bellard
        if (l > len)
2054 13eb76e0 bellard
            l = len;
2055 92e873b9 bellard
        p = phys_page_find(page >> TARGET_PAGE_BITS);
2056 13eb76e0 bellard
        if (!p) {
2057 13eb76e0 bellard
            pd = IO_MEM_UNASSIGNED;
2058 13eb76e0 bellard
        } else {
2059 13eb76e0 bellard
            pd = p->phys_offset;
2060 13eb76e0 bellard
        }
2061 13eb76e0 bellard
        
2062 13eb76e0 bellard
        if (is_write) {
2063 3a7d929e bellard
            if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2064 13eb76e0 bellard
                io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2065 6a00d601 bellard
                /* XXX: could force cpu_single_env to NULL to avoid
2066 6a00d601 bellard
                   potential bugs */
2067 13eb76e0 bellard
                if (l >= 4 && ((addr & 3) == 0)) {
2068 1c213d19 bellard
                    /* 32 bit write access */
2069 c27004ec bellard
                    val = ldl_p(buf);
2070 a4193c8a bellard
                    io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2071 13eb76e0 bellard
                    l = 4;
2072 13eb76e0 bellard
                } else if (l >= 2 && ((addr & 1) == 0)) {
2073 1c213d19 bellard
                    /* 16 bit write access */
2074 c27004ec bellard
                    val = lduw_p(buf);
2075 a4193c8a bellard
                    io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
2076 13eb76e0 bellard
                    l = 2;
2077 13eb76e0 bellard
                } else {
2078 1c213d19 bellard
                    /* 8 bit write access */
2079 c27004ec bellard
                    val = ldub_p(buf);
2080 a4193c8a bellard
                    io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val);
2081 13eb76e0 bellard
                    l = 1;
2082 13eb76e0 bellard
                }
2083 13eb76e0 bellard
            } else {
2084 b448f2f3 bellard
                unsigned long addr1;
2085 b448f2f3 bellard
                addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2086 13eb76e0 bellard
                /* RAM case */
2087 b448f2f3 bellard
                ptr = phys_ram_base + addr1;
2088 13eb76e0 bellard
                memcpy(ptr, buf, l);
2089 3a7d929e bellard
                if (!cpu_physical_memory_is_dirty(addr1)) {
2090 3a7d929e bellard
                    /* invalidate code */
2091 3a7d929e bellard
                    tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
2092 3a7d929e bellard
                    /* set dirty bit */
2093 f23db169 bellard
                    phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |= 
2094 f23db169 bellard
                        (0xff & ~CODE_DIRTY_FLAG);
2095 3a7d929e bellard
                }
2096 13eb76e0 bellard
            }
2097 13eb76e0 bellard
        } else {
2098 2a4188a3 bellard
            if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && 
2099 2a4188a3 bellard
                !(pd & IO_MEM_ROMD)) {
2100 13eb76e0 bellard
                /* I/O case */
2101 13eb76e0 bellard
                io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2102 13eb76e0 bellard
                if (l >= 4 && ((addr & 3) == 0)) {
2103 13eb76e0 bellard
                    /* 32 bit read access */
2104 a4193c8a bellard
                    val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2105 c27004ec bellard
                    stl_p(buf, val);
2106 13eb76e0 bellard
                    l = 4;
2107 13eb76e0 bellard
                } else if (l >= 2 && ((addr & 1) == 0)) {
2108 13eb76e0 bellard
                    /* 16 bit read access */
2109 a4193c8a bellard
                    val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
2110 c27004ec bellard
                    stw_p(buf, val);
2111 13eb76e0 bellard
                    l = 2;
2112 13eb76e0 bellard
                } else {
2113 1c213d19 bellard
                    /* 8 bit read access */
2114 a4193c8a bellard
                    val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr);
2115 c27004ec bellard
                    stb_p(buf, val);
2116 13eb76e0 bellard
                    l = 1;
2117 13eb76e0 bellard
                }
2118 13eb76e0 bellard
            } else {
2119 13eb76e0 bellard
                /* RAM case */
2120 13eb76e0 bellard
                ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
2121 13eb76e0 bellard
                    (addr & ~TARGET_PAGE_MASK);
2122 13eb76e0 bellard
                memcpy(buf, ptr, l);
2123 13eb76e0 bellard
            }
2124 13eb76e0 bellard
        }
2125 13eb76e0 bellard
        len -= l;
2126 13eb76e0 bellard
        buf += l;
2127 13eb76e0 bellard
        addr += l;
2128 13eb76e0 bellard
    }
2129 13eb76e0 bellard
}
2130 8df1cd07 bellard
2131 d0ecd2aa bellard
/* used for ROM loading : can write in RAM and ROM */
2132 d0ecd2aa bellard
void cpu_physical_memory_write_rom(target_phys_addr_t addr, 
2133 d0ecd2aa bellard
                                   const uint8_t *buf, int len)
2134 d0ecd2aa bellard
{
2135 d0ecd2aa bellard
    int l;
2136 d0ecd2aa bellard
    uint8_t *ptr;
2137 d0ecd2aa bellard
    target_phys_addr_t page;
2138 d0ecd2aa bellard
    unsigned long pd;
2139 d0ecd2aa bellard
    PhysPageDesc *p;
2140 d0ecd2aa bellard
    
2141 d0ecd2aa bellard
    while (len > 0) {
2142 d0ecd2aa bellard
        page = addr & TARGET_PAGE_MASK;
2143 d0ecd2aa bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
2144 d0ecd2aa bellard
        if (l > len)
2145 d0ecd2aa bellard
            l = len;
2146 d0ecd2aa bellard
        p = phys_page_find(page >> TARGET_PAGE_BITS);
2147 d0ecd2aa bellard
        if (!p) {
2148 d0ecd2aa bellard
            pd = IO_MEM_UNASSIGNED;
2149 d0ecd2aa bellard
        } else {
2150 d0ecd2aa bellard
            pd = p->phys_offset;
2151 d0ecd2aa bellard
        }
2152 d0ecd2aa bellard
        
2153 d0ecd2aa bellard
        if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
2154 2a4188a3 bellard
            (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
2155 2a4188a3 bellard
            !(pd & IO_MEM_ROMD)) {
2156 d0ecd2aa bellard
            /* do nothing */
2157 d0ecd2aa bellard
        } else {
2158 d0ecd2aa bellard
            unsigned long addr1;
2159 d0ecd2aa bellard
            addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2160 d0ecd2aa bellard
            /* ROM/RAM case */
2161 d0ecd2aa bellard
            ptr = phys_ram_base + addr1;
2162 d0ecd2aa bellard
            memcpy(ptr, buf, l);
2163 d0ecd2aa bellard
        }
2164 d0ecd2aa bellard
        len -= l;
2165 d0ecd2aa bellard
        buf += l;
2166 d0ecd2aa bellard
        addr += l;
2167 d0ecd2aa bellard
    }
2168 d0ecd2aa bellard
}
2169 d0ecd2aa bellard
2170 d0ecd2aa bellard
2171 8df1cd07 bellard
/* warning: addr must be aligned */
2172 8df1cd07 bellard
uint32_t ldl_phys(target_phys_addr_t addr)
2173 8df1cd07 bellard
{
2174 8df1cd07 bellard
    int io_index;
2175 8df1cd07 bellard
    uint8_t *ptr;
2176 8df1cd07 bellard
    uint32_t val;
2177 8df1cd07 bellard
    unsigned long pd;
2178 8df1cd07 bellard
    PhysPageDesc *p;
2179 8df1cd07 bellard
2180 8df1cd07 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2181 8df1cd07 bellard
    if (!p) {
2182 8df1cd07 bellard
        pd = IO_MEM_UNASSIGNED;
2183 8df1cd07 bellard
    } else {
2184 8df1cd07 bellard
        pd = p->phys_offset;
2185 8df1cd07 bellard
    }
2186 8df1cd07 bellard
        
2187 2a4188a3 bellard
    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && 
2188 2a4188a3 bellard
        !(pd & IO_MEM_ROMD)) {
2189 8df1cd07 bellard
        /* I/O case */
2190 8df1cd07 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2191 8df1cd07 bellard
        val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2192 8df1cd07 bellard
    } else {
2193 8df1cd07 bellard
        /* RAM case */
2194 8df1cd07 bellard
        ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
2195 8df1cd07 bellard
            (addr & ~TARGET_PAGE_MASK);
2196 8df1cd07 bellard
        val = ldl_p(ptr);
2197 8df1cd07 bellard
    }
2198 8df1cd07 bellard
    return val;
2199 8df1cd07 bellard
}
2200 8df1cd07 bellard
2201 84b7b8e7 bellard
/* warning: addr must be aligned */
2202 84b7b8e7 bellard
uint64_t ldq_phys(target_phys_addr_t addr)
2203 84b7b8e7 bellard
{
2204 84b7b8e7 bellard
    int io_index;
2205 84b7b8e7 bellard
    uint8_t *ptr;
2206 84b7b8e7 bellard
    uint64_t val;
2207 84b7b8e7 bellard
    unsigned long pd;
2208 84b7b8e7 bellard
    PhysPageDesc *p;
2209 84b7b8e7 bellard
2210 84b7b8e7 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2211 84b7b8e7 bellard
    if (!p) {
2212 84b7b8e7 bellard
        pd = IO_MEM_UNASSIGNED;
2213 84b7b8e7 bellard
    } else {
2214 84b7b8e7 bellard
        pd = p->phys_offset;
2215 84b7b8e7 bellard
    }
2216 84b7b8e7 bellard
        
2217 2a4188a3 bellard
    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
2218 2a4188a3 bellard
        !(pd & IO_MEM_ROMD)) {
2219 84b7b8e7 bellard
        /* I/O case */
2220 84b7b8e7 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2221 84b7b8e7 bellard
#ifdef TARGET_WORDS_BIGENDIAN
2222 84b7b8e7 bellard
        val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
2223 84b7b8e7 bellard
        val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
2224 84b7b8e7 bellard
#else
2225 84b7b8e7 bellard
        val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2226 84b7b8e7 bellard
        val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
2227 84b7b8e7 bellard
#endif
2228 84b7b8e7 bellard
    } else {
2229 84b7b8e7 bellard
        /* RAM case */
2230 84b7b8e7 bellard
        ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
2231 84b7b8e7 bellard
            (addr & ~TARGET_PAGE_MASK);
2232 84b7b8e7 bellard
        val = ldq_p(ptr);
2233 84b7b8e7 bellard
    }
2234 84b7b8e7 bellard
    return val;
2235 84b7b8e7 bellard
}
2236 84b7b8e7 bellard
2237 aab33094 bellard
/* XXX: optimize */
2238 aab33094 bellard
uint32_t ldub_phys(target_phys_addr_t addr)
2239 aab33094 bellard
{
2240 aab33094 bellard
    uint8_t val;
2241 aab33094 bellard
    cpu_physical_memory_read(addr, &val, 1);
2242 aab33094 bellard
    return val;
2243 aab33094 bellard
}
2244 aab33094 bellard
2245 aab33094 bellard
/* XXX: optimize */
2246 aab33094 bellard
uint32_t lduw_phys(target_phys_addr_t addr)
2247 aab33094 bellard
{
2248 aab33094 bellard
    uint16_t val;
2249 aab33094 bellard
    cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
2250 aab33094 bellard
    return tswap16(val);
2251 aab33094 bellard
}
2252 aab33094 bellard
2253 8df1cd07 bellard
/* warning: addr must be aligned. The ram page is not masked as dirty
2254 8df1cd07 bellard
   and the code inside is not invalidated. It is useful if the dirty
2255 8df1cd07 bellard
   bits are used to track modified PTEs */
2256 8df1cd07 bellard
void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
2257 8df1cd07 bellard
{
2258 8df1cd07 bellard
    int io_index;
2259 8df1cd07 bellard
    uint8_t *ptr;
2260 8df1cd07 bellard
    unsigned long pd;
2261 8df1cd07 bellard
    PhysPageDesc *p;
2262 8df1cd07 bellard
2263 8df1cd07 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2264 8df1cd07 bellard
    if (!p) {
2265 8df1cd07 bellard
        pd = IO_MEM_UNASSIGNED;
2266 8df1cd07 bellard
    } else {
2267 8df1cd07 bellard
        pd = p->phys_offset;
2268 8df1cd07 bellard
    }
2269 8df1cd07 bellard
        
2270 3a7d929e bellard
    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2271 8df1cd07 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2272 8df1cd07 bellard
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2273 8df1cd07 bellard
    } else {
2274 8df1cd07 bellard
        ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
2275 8df1cd07 bellard
            (addr & ~TARGET_PAGE_MASK);
2276 8df1cd07 bellard
        stl_p(ptr, val);
2277 8df1cd07 bellard
    }
2278 8df1cd07 bellard
}
2279 8df1cd07 bellard
2280 8df1cd07 bellard
/* warning: addr must be aligned */
2281 8df1cd07 bellard
void stl_phys(target_phys_addr_t addr, uint32_t val)
2282 8df1cd07 bellard
{
2283 8df1cd07 bellard
    int io_index;
2284 8df1cd07 bellard
    uint8_t *ptr;
2285 8df1cd07 bellard
    unsigned long pd;
2286 8df1cd07 bellard
    PhysPageDesc *p;
2287 8df1cd07 bellard
2288 8df1cd07 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2289 8df1cd07 bellard
    if (!p) {
2290 8df1cd07 bellard
        pd = IO_MEM_UNASSIGNED;
2291 8df1cd07 bellard
    } else {
2292 8df1cd07 bellard
        pd = p->phys_offset;
2293 8df1cd07 bellard
    }
2294 8df1cd07 bellard
        
2295 3a7d929e bellard
    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2296 8df1cd07 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2297 8df1cd07 bellard
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2298 8df1cd07 bellard
    } else {
2299 8df1cd07 bellard
        unsigned long addr1;
2300 8df1cd07 bellard
        addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2301 8df1cd07 bellard
        /* RAM case */
2302 8df1cd07 bellard
        ptr = phys_ram_base + addr1;
2303 8df1cd07 bellard
        stl_p(ptr, val);
2304 3a7d929e bellard
        if (!cpu_physical_memory_is_dirty(addr1)) {
2305 3a7d929e bellard
            /* invalidate code */
2306 3a7d929e bellard
            tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
2307 3a7d929e bellard
            /* set dirty bit */
2308 f23db169 bellard
            phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
2309 f23db169 bellard
                (0xff & ~CODE_DIRTY_FLAG);
2310 3a7d929e bellard
        }
2311 8df1cd07 bellard
    }
2312 8df1cd07 bellard
}
2313 8df1cd07 bellard
2314 aab33094 bellard
/* XXX: optimize */
2315 aab33094 bellard
void stb_phys(target_phys_addr_t addr, uint32_t val)
2316 aab33094 bellard
{
2317 aab33094 bellard
    uint8_t v = val;
2318 aab33094 bellard
    cpu_physical_memory_write(addr, &v, 1);
2319 aab33094 bellard
}
2320 aab33094 bellard
2321 aab33094 bellard
/* XXX: optimize */
2322 aab33094 bellard
void stw_phys(target_phys_addr_t addr, uint32_t val)
2323 aab33094 bellard
{
2324 aab33094 bellard
    uint16_t v = tswap16(val);
2325 aab33094 bellard
    cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
2326 aab33094 bellard
}
2327 aab33094 bellard
2328 aab33094 bellard
/* XXX: optimize */
2329 aab33094 bellard
void stq_phys(target_phys_addr_t addr, uint64_t val)
2330 aab33094 bellard
{
2331 aab33094 bellard
    val = tswap64(val);
2332 aab33094 bellard
    cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
2333 aab33094 bellard
}
2334 aab33094 bellard
2335 13eb76e0 bellard
#endif
2336 13eb76e0 bellard
2337 13eb76e0 bellard
/* virtual memory access for debug */
2338 b448f2f3 bellard
int cpu_memory_rw_debug(CPUState *env, target_ulong addr, 
2339 b448f2f3 bellard
                        uint8_t *buf, int len, int is_write)
2340 13eb76e0 bellard
{
2341 13eb76e0 bellard
    int l;
2342 13eb76e0 bellard
    target_ulong page, phys_addr;
2343 13eb76e0 bellard
2344 13eb76e0 bellard
    while (len > 0) {
2345 13eb76e0 bellard
        page = addr & TARGET_PAGE_MASK;
2346 13eb76e0 bellard
        phys_addr = cpu_get_phys_page_debug(env, page);
2347 13eb76e0 bellard
        /* if no physical page mapped, return an error */
2348 13eb76e0 bellard
        if (phys_addr == -1)
2349 13eb76e0 bellard
            return -1;
2350 13eb76e0 bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
2351 13eb76e0 bellard
        if (l > len)
2352 13eb76e0 bellard
            l = len;
2353 b448f2f3 bellard
        cpu_physical_memory_rw(phys_addr + (addr & ~TARGET_PAGE_MASK), 
2354 b448f2f3 bellard
                               buf, l, is_write);
2355 13eb76e0 bellard
        len -= l;
2356 13eb76e0 bellard
        buf += l;
2357 13eb76e0 bellard
        addr += l;
2358 13eb76e0 bellard
    }
2359 13eb76e0 bellard
    return 0;
2360 13eb76e0 bellard
}
2361 13eb76e0 bellard
2362 e3db7226 bellard
void dump_exec_info(FILE *f,
2363 e3db7226 bellard
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2364 e3db7226 bellard
{
2365 e3db7226 bellard
    int i, target_code_size, max_target_code_size;
2366 e3db7226 bellard
    int direct_jmp_count, direct_jmp2_count, cross_page;
2367 e3db7226 bellard
    TranslationBlock *tb;
2368 e3db7226 bellard
    
2369 e3db7226 bellard
    target_code_size = 0;
2370 e3db7226 bellard
    max_target_code_size = 0;
2371 e3db7226 bellard
    cross_page = 0;
2372 e3db7226 bellard
    direct_jmp_count = 0;
2373 e3db7226 bellard
    direct_jmp2_count = 0;
2374 e3db7226 bellard
    for(i = 0; i < nb_tbs; i++) {
2375 e3db7226 bellard
        tb = &tbs[i];
2376 e3db7226 bellard
        target_code_size += tb->size;
2377 e3db7226 bellard
        if (tb->size > max_target_code_size)
2378 e3db7226 bellard
            max_target_code_size = tb->size;
2379 e3db7226 bellard
        if (tb->page_addr[1] != -1)
2380 e3db7226 bellard
            cross_page++;
2381 e3db7226 bellard
        if (tb->tb_next_offset[0] != 0xffff) {
2382 e3db7226 bellard
            direct_jmp_count++;
2383 e3db7226 bellard
            if (tb->tb_next_offset[1] != 0xffff) {
2384 e3db7226 bellard
                direct_jmp2_count++;
2385 e3db7226 bellard
            }
2386 e3db7226 bellard
        }
2387 e3db7226 bellard
    }
2388 e3db7226 bellard
    /* XXX: avoid using doubles ? */
2389 e3db7226 bellard
    cpu_fprintf(f, "TB count            %d\n", nb_tbs);
2390 e3db7226 bellard
    cpu_fprintf(f, "TB avg target size  %d max=%d bytes\n", 
2391 e3db7226 bellard
                nb_tbs ? target_code_size / nb_tbs : 0,
2392 e3db7226 bellard
                max_target_code_size);
2393 e3db7226 bellard
    cpu_fprintf(f, "TB avg host size    %d bytes (expansion ratio: %0.1f)\n", 
2394 e3db7226 bellard
                nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
2395 e3db7226 bellard
                target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
2396 e3db7226 bellard
    cpu_fprintf(f, "cross page TB count %d (%d%%)\n", 
2397 e3db7226 bellard
            cross_page, 
2398 e3db7226 bellard
            nb_tbs ? (cross_page * 100) / nb_tbs : 0);
2399 e3db7226 bellard
    cpu_fprintf(f, "direct jump count   %d (%d%%) (2 jumps=%d %d%%)\n",
2400 e3db7226 bellard
                direct_jmp_count, 
2401 e3db7226 bellard
                nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
2402 e3db7226 bellard
                direct_jmp2_count,
2403 e3db7226 bellard
                nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
2404 e3db7226 bellard
    cpu_fprintf(f, "TB flush count      %d\n", tb_flush_count);
2405 e3db7226 bellard
    cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
2406 e3db7226 bellard
    cpu_fprintf(f, "TLB flush count     %d\n", tlb_flush_count);
2407 e3db7226 bellard
}
2408 e3db7226 bellard
2409 61382a50 bellard
#if !defined(CONFIG_USER_ONLY) 
2410 61382a50 bellard
2411 61382a50 bellard
#define MMUSUFFIX _cmmu
2412 61382a50 bellard
#define GETPC() NULL
2413 61382a50 bellard
#define env cpu_single_env
2414 b769d8fe bellard
#define SOFTMMU_CODE_ACCESS
2415 61382a50 bellard
2416 61382a50 bellard
#define SHIFT 0
2417 61382a50 bellard
#include "softmmu_template.h"
2418 61382a50 bellard
2419 61382a50 bellard
#define SHIFT 1
2420 61382a50 bellard
#include "softmmu_template.h"
2421 61382a50 bellard
2422 61382a50 bellard
#define SHIFT 2
2423 61382a50 bellard
#include "softmmu_template.h"
2424 61382a50 bellard
2425 61382a50 bellard
#define SHIFT 3
2426 61382a50 bellard
#include "softmmu_template.h"
2427 61382a50 bellard
2428 61382a50 bellard
#undef env
2429 61382a50 bellard
2430 61382a50 bellard
#endif