Statistics
| Branch: | Revision:

root / exec.c @ 0fead125

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