Statistics
| Branch: | Revision:

root / exec.c @ eb38c52c

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