Statistics
| Branch: | Revision:

root / exec.c @ cbeb0857

History | View | Annotate | Download (78 kB)

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