Statistics
| Branch: | Revision:

root / exec.c @ 6f5a9f7e

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