Statistics
| Branch: | Revision:

root / exec.c @ d0ecd2aa

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