Statistics
| Branch: | Revision:

root / exec.c @ 0497d2f4

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