Statistics
| Branch: | Revision:

root / exec.c @ 55489a17

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