Statistics
| Branch: | Revision:

root / exec.c @ b3c7724c

History | View | Annotate | Download (93.8 kB)

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