Statistics
| Branch: | Revision:

root / exec.c @ 46dc3881

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