Statistics
| Branch: | Revision:

root / exec.c @ e2eef170

History | View | Annotate | Download (89.8 kB)

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