Statistics
| Branch: | Revision:

root / exec.c @ d4b55be5

History | View | Annotate | Download (102.3 kB)

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