Statistics
| Branch: | Revision:

root / exec.c @ 8c5e95d8

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