Statistics
| Branch: | Revision:

root / exec.c @ 4efbe58f

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