Statistics
| Branch: | Revision:

root / exec.c @ ea80b906

History | View | Annotate | Download (109.3 kB)

1 54936004 bellard
/*
2 fd6ce8f6 bellard
 *  virtual page mapping and translated block handling
3 5fafdf24 ths
 *
4 54936004 bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 54936004 bellard
 *
6 54936004 bellard
 * This library is free software; you can redistribute it and/or
7 54936004 bellard
 * modify it under the terms of the GNU Lesser General Public
8 54936004 bellard
 * License as published by the Free Software Foundation; either
9 54936004 bellard
 * version 2 of the License, or (at your option) any later version.
10 54936004 bellard
 *
11 54936004 bellard
 * This library is distributed in the hope that it will be useful,
12 54936004 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 54936004 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 54936004 bellard
 * Lesser General Public License for more details.
15 54936004 bellard
 *
16 54936004 bellard
 * You should have received a copy of the GNU Lesser General Public
17 8167ee88 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 54936004 bellard
 */
19 67b915a5 bellard
#include "config.h"
20 d5a8f07c bellard
#ifdef _WIN32
21 d5a8f07c bellard
#include <windows.h>
22 d5a8f07c bellard
#else
23 a98d49b1 bellard
#include <sys/types.h>
24 d5a8f07c bellard
#include <sys/mman.h>
25 d5a8f07c bellard
#endif
26 54936004 bellard
#include <stdlib.h>
27 54936004 bellard
#include <stdio.h>
28 54936004 bellard
#include <stdarg.h>
29 54936004 bellard
#include <string.h>
30 54936004 bellard
#include <errno.h>
31 54936004 bellard
#include <unistd.h>
32 54936004 bellard
#include <inttypes.h>
33 54936004 bellard
34 6180a181 bellard
#include "cpu.h"
35 6180a181 bellard
#include "exec-all.h"
36 ca10f867 aurel32
#include "qemu-common.h"
37 b67d9a52 bellard
#include "tcg.h"
38 b3c7724c pbrook
#include "hw/hw.h"
39 74576198 aliguori
#include "osdep.h"
40 7ba1e619 aliguori
#include "kvm.h"
41 53a5960a pbrook
#if defined(CONFIG_USER_ONLY)
42 53a5960a pbrook
#include <qemu.h>
43 53a5960a pbrook
#endif
44 54936004 bellard
45 fd6ce8f6 bellard
//#define DEBUG_TB_INVALIDATE
46 66e85a21 bellard
//#define DEBUG_FLUSH
47 9fa3e853 bellard
//#define DEBUG_TLB
48 67d3b957 pbrook
//#define DEBUG_UNASSIGNED
49 fd6ce8f6 bellard
50 fd6ce8f6 bellard
/* make various TB consistency checks */
51 5fafdf24 ths
//#define DEBUG_TB_CHECK
52 5fafdf24 ths
//#define DEBUG_TLB_CHECK
53 fd6ce8f6 bellard
54 1196be37 ths
//#define DEBUG_IOPORT
55 db7b5426 blueswir1
//#define DEBUG_SUBPAGE
56 1196be37 ths
57 99773bd4 pbrook
#if !defined(CONFIG_USER_ONLY)
58 99773bd4 pbrook
/* TB consistency checks only implemented for usermode emulation.  */
59 99773bd4 pbrook
#undef DEBUG_TB_CHECK
60 99773bd4 pbrook
#endif
61 99773bd4 pbrook
62 9fa3e853 bellard
#define SMC_BITMAP_USE_THRESHOLD 10
63 9fa3e853 bellard
64 108c49b8 bellard
#if defined(TARGET_SPARC64)
65 108c49b8 bellard
#define TARGET_PHYS_ADDR_SPACE_BITS 41
66 5dcb6b91 blueswir1
#elif defined(TARGET_SPARC)
67 5dcb6b91 blueswir1
#define TARGET_PHYS_ADDR_SPACE_BITS 36
68 bedb69ea j_mayer
#elif defined(TARGET_ALPHA)
69 bedb69ea j_mayer
#define TARGET_PHYS_ADDR_SPACE_BITS 42
70 bedb69ea j_mayer
#define TARGET_VIRT_ADDR_SPACE_BITS 42
71 108c49b8 bellard
#elif defined(TARGET_PPC64)
72 108c49b8 bellard
#define TARGET_PHYS_ADDR_SPACE_BITS 42
73 4a1418e0 Anthony Liguori
#elif defined(TARGET_X86_64)
74 00f82b8a aurel32
#define TARGET_PHYS_ADDR_SPACE_BITS 42
75 4a1418e0 Anthony Liguori
#elif defined(TARGET_I386)
76 00f82b8a aurel32
#define TARGET_PHYS_ADDR_SPACE_BITS 36
77 108c49b8 bellard
#else
78 108c49b8 bellard
#define TARGET_PHYS_ADDR_SPACE_BITS 32
79 108c49b8 bellard
#endif
80 108c49b8 bellard
81 bdaf78e0 blueswir1
static TranslationBlock *tbs;
82 26a5f13b bellard
int code_gen_max_blocks;
83 9fa3e853 bellard
TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
84 bdaf78e0 blueswir1
static int nb_tbs;
85 eb51d102 bellard
/* any access to the tbs or the page table must use this lock */
86 eb51d102 bellard
spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
87 fd6ce8f6 bellard
88 141ac468 blueswir1
#if defined(__arm__) || defined(__sparc_v9__)
89 141ac468 blueswir1
/* The prologue must be reachable with a direct jump. ARM and Sparc64
90 141ac468 blueswir1
 have limited branch ranges (possibly also PPC) so place it in a
91 d03d860b blueswir1
 section close to code segment. */
92 d03d860b blueswir1
#define code_gen_section                                \
93 d03d860b blueswir1
    __attribute__((__section__(".gen_code")))           \
94 d03d860b blueswir1
    __attribute__((aligned (32)))
95 f8e2af11 Stefan Weil
#elif defined(_WIN32)
96 f8e2af11 Stefan Weil
/* Maximum alignment for Win32 is 16. */
97 f8e2af11 Stefan Weil
#define code_gen_section                                \
98 f8e2af11 Stefan Weil
    __attribute__((aligned (16)))
99 d03d860b blueswir1
#else
100 d03d860b blueswir1
#define code_gen_section                                \
101 d03d860b blueswir1
    __attribute__((aligned (32)))
102 d03d860b blueswir1
#endif
103 d03d860b blueswir1
104 d03d860b blueswir1
uint8_t code_gen_prologue[1024] code_gen_section;
105 bdaf78e0 blueswir1
static uint8_t *code_gen_buffer;
106 bdaf78e0 blueswir1
static unsigned long code_gen_buffer_size;
107 26a5f13b bellard
/* threshold to flush the translated code buffer */
108 bdaf78e0 blueswir1
static unsigned long code_gen_buffer_max_size;
109 fd6ce8f6 bellard
uint8_t *code_gen_ptr;
110 fd6ce8f6 bellard
111 e2eef170 pbrook
#if !defined(CONFIG_USER_ONLY)
112 9fa3e853 bellard
int phys_ram_fd;
113 1ccde1cb bellard
uint8_t *phys_ram_dirty;
114 74576198 aliguori
static int in_migration;
115 94a6b54f pbrook
116 94a6b54f pbrook
typedef struct RAMBlock {
117 94a6b54f pbrook
    uint8_t *host;
118 94a6b54f pbrook
    ram_addr_t offset;
119 94a6b54f pbrook
    ram_addr_t length;
120 94a6b54f pbrook
    struct RAMBlock *next;
121 94a6b54f pbrook
} RAMBlock;
122 94a6b54f pbrook
123 94a6b54f pbrook
static RAMBlock *ram_blocks;
124 94a6b54f pbrook
/* TODO: When we implement (and use) ram deallocation (e.g. for hotplug)
125 ccbb4d44 Stuart Brady
   then we can no longer assume contiguous ram offsets, and external uses
126 94a6b54f pbrook
   of this variable will break.  */
127 94a6b54f pbrook
ram_addr_t last_ram_offset;
128 e2eef170 pbrook
#endif
129 9fa3e853 bellard
130 6a00d601 bellard
CPUState *first_cpu;
131 6a00d601 bellard
/* current CPU in the current thread. It is only valid inside
132 6a00d601 bellard
   cpu_exec() */
133 5fafdf24 ths
CPUState *cpu_single_env;
134 2e70f6ef pbrook
/* 0 = Do not count executed instructions.
135 bf20dc07 ths
   1 = Precise instruction counting.
136 2e70f6ef pbrook
   2 = Adaptive rate instruction counting.  */
137 2e70f6ef pbrook
int use_icount = 0;
138 2e70f6ef pbrook
/* Current instruction counter.  While executing translated code this may
139 2e70f6ef pbrook
   include some instructions that have not yet been executed.  */
140 2e70f6ef pbrook
int64_t qemu_icount;
141 6a00d601 bellard
142 54936004 bellard
typedef struct PageDesc {
143 92e873b9 bellard
    /* list of TBs intersecting this ram page */
144 fd6ce8f6 bellard
    TranslationBlock *first_tb;
145 9fa3e853 bellard
    /* in order to optimize self modifying code, we count the number
146 9fa3e853 bellard
       of lookups we do to a given page to use a bitmap */
147 9fa3e853 bellard
    unsigned int code_write_count;
148 9fa3e853 bellard
    uint8_t *code_bitmap;
149 9fa3e853 bellard
#if defined(CONFIG_USER_ONLY)
150 9fa3e853 bellard
    unsigned long flags;
151 9fa3e853 bellard
#endif
152 54936004 bellard
} PageDesc;
153 54936004 bellard
154 92e873b9 bellard
typedef struct PhysPageDesc {
155 0f459d16 pbrook
    /* offset in host memory of the page + io_index in the low bits */
156 00f82b8a aurel32
    ram_addr_t phys_offset;
157 8da3ff18 pbrook
    ram_addr_t region_offset;
158 92e873b9 bellard
} PhysPageDesc;
159 92e873b9 bellard
160 54936004 bellard
#define L2_BITS 10
161 bedb69ea j_mayer
#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
162 bedb69ea j_mayer
/* XXX: this is a temporary hack for alpha target.
163 bedb69ea j_mayer
 *      In the future, this is to be replaced by a multi-level table
164 bedb69ea j_mayer
 *      to actually be able to handle the complete 64 bits address space.
165 bedb69ea j_mayer
 */
166 bedb69ea j_mayer
#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
167 bedb69ea j_mayer
#else
168 03875444 aurel32
#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
169 bedb69ea j_mayer
#endif
170 54936004 bellard
171 54936004 bellard
#define L1_SIZE (1 << L1_BITS)
172 54936004 bellard
#define L2_SIZE (1 << L2_BITS)
173 54936004 bellard
174 83fb7adf bellard
unsigned long qemu_real_host_page_size;
175 83fb7adf bellard
unsigned long qemu_host_page_bits;
176 83fb7adf bellard
unsigned long qemu_host_page_size;
177 83fb7adf bellard
unsigned long qemu_host_page_mask;
178 54936004 bellard
179 92e873b9 bellard
/* XXX: for system emulation, it could just be an array */
180 54936004 bellard
static PageDesc *l1_map[L1_SIZE];
181 bdaf78e0 blueswir1
static PhysPageDesc **l1_phys_map;
182 54936004 bellard
183 e2eef170 pbrook
#if !defined(CONFIG_USER_ONLY)
184 e2eef170 pbrook
static void io_mem_init(void);
185 e2eef170 pbrook
186 33417e70 bellard
/* io memory support */
187 33417e70 bellard
CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
188 33417e70 bellard
CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
189 a4193c8a bellard
void *io_mem_opaque[IO_MEM_NB_ENTRIES];
190 511d2b14 blueswir1
static char io_mem_used[IO_MEM_NB_ENTRIES];
191 6658ffb8 pbrook
static int io_mem_watch;
192 6658ffb8 pbrook
#endif
193 33417e70 bellard
194 34865134 bellard
/* log support */
195 d9b630fd blueswir1
static const char *logfilename = "/tmp/qemu.log";
196 34865134 bellard
FILE *logfile;
197 34865134 bellard
int loglevel;
198 e735b91c pbrook
static int log_append = 0;
199 34865134 bellard
200 e3db7226 bellard
/* statistics */
201 e3db7226 bellard
static int tlb_flush_count;
202 e3db7226 bellard
static int tb_flush_count;
203 e3db7226 bellard
static int tb_phys_invalidate_count;
204 e3db7226 bellard
205 db7b5426 blueswir1
#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
206 db7b5426 blueswir1
typedef struct subpage_t {
207 db7b5426 blueswir1
    target_phys_addr_t base;
208 d60efc6b Blue Swirl
    CPUReadMemoryFunc * const *mem_read[TARGET_PAGE_SIZE][4];
209 d60efc6b Blue Swirl
    CPUWriteMemoryFunc * const *mem_write[TARGET_PAGE_SIZE][4];
210 3ee89922 blueswir1
    void *opaque[TARGET_PAGE_SIZE][2][4];
211 8da3ff18 pbrook
    ram_addr_t region_offset[TARGET_PAGE_SIZE][2][4];
212 db7b5426 blueswir1
} subpage_t;
213 db7b5426 blueswir1
214 7cb69cae bellard
#ifdef _WIN32
215 7cb69cae bellard
static void map_exec(void *addr, long size)
216 7cb69cae bellard
{
217 7cb69cae bellard
    DWORD old_protect;
218 7cb69cae bellard
    VirtualProtect(addr, size,
219 7cb69cae bellard
                   PAGE_EXECUTE_READWRITE, &old_protect);
220 7cb69cae bellard
    
221 7cb69cae bellard
}
222 7cb69cae bellard
#else
223 7cb69cae bellard
static void map_exec(void *addr, long size)
224 7cb69cae bellard
{
225 4369415f bellard
    unsigned long start, end, page_size;
226 7cb69cae bellard
    
227 4369415f bellard
    page_size = getpagesize();
228 7cb69cae bellard
    start = (unsigned long)addr;
229 4369415f bellard
    start &= ~(page_size - 1);
230 7cb69cae bellard
    
231 7cb69cae bellard
    end = (unsigned long)addr + size;
232 4369415f bellard
    end += page_size - 1;
233 4369415f bellard
    end &= ~(page_size - 1);
234 7cb69cae bellard
    
235 7cb69cae bellard
    mprotect((void *)start, end - start,
236 7cb69cae bellard
             PROT_READ | PROT_WRITE | PROT_EXEC);
237 7cb69cae bellard
}
238 7cb69cae bellard
#endif
239 7cb69cae bellard
240 b346ff46 bellard
static void page_init(void)
241 54936004 bellard
{
242 83fb7adf bellard
    /* NOTE: we can always suppose that qemu_host_page_size >=
243 54936004 bellard
       TARGET_PAGE_SIZE */
244 c2b48b69 aliguori
#ifdef _WIN32
245 c2b48b69 aliguori
    {
246 c2b48b69 aliguori
        SYSTEM_INFO system_info;
247 c2b48b69 aliguori
248 c2b48b69 aliguori
        GetSystemInfo(&system_info);
249 c2b48b69 aliguori
        qemu_real_host_page_size = system_info.dwPageSize;
250 c2b48b69 aliguori
    }
251 c2b48b69 aliguori
#else
252 c2b48b69 aliguori
    qemu_real_host_page_size = getpagesize();
253 c2b48b69 aliguori
#endif
254 83fb7adf bellard
    if (qemu_host_page_size == 0)
255 83fb7adf bellard
        qemu_host_page_size = qemu_real_host_page_size;
256 83fb7adf bellard
    if (qemu_host_page_size < TARGET_PAGE_SIZE)
257 83fb7adf bellard
        qemu_host_page_size = TARGET_PAGE_SIZE;
258 83fb7adf bellard
    qemu_host_page_bits = 0;
259 83fb7adf bellard
    while ((1 << qemu_host_page_bits) < qemu_host_page_size)
260 83fb7adf bellard
        qemu_host_page_bits++;
261 83fb7adf bellard
    qemu_host_page_mask = ~(qemu_host_page_size - 1);
262 108c49b8 bellard
    l1_phys_map = qemu_vmalloc(L1_SIZE * sizeof(void *));
263 108c49b8 bellard
    memset(l1_phys_map, 0, L1_SIZE * sizeof(void *));
264 50a9569b balrog
265 50a9569b balrog
#if !defined(_WIN32) && defined(CONFIG_USER_ONLY)
266 50a9569b balrog
    {
267 50a9569b balrog
        long long startaddr, endaddr;
268 50a9569b balrog
        FILE *f;
269 50a9569b balrog
        int n;
270 50a9569b balrog
271 c8a706fe pbrook
        mmap_lock();
272 0776590d pbrook
        last_brk = (unsigned long)sbrk(0);
273 50a9569b balrog
        f = fopen("/proc/self/maps", "r");
274 50a9569b balrog
        if (f) {
275 50a9569b balrog
            do {
276 50a9569b balrog
                n = fscanf (f, "%llx-%llx %*[^\n]\n", &startaddr, &endaddr);
277 50a9569b balrog
                if (n == 2) {
278 e0b8d65a blueswir1
                    startaddr = MIN(startaddr,
279 e0b8d65a blueswir1
                                    (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
280 e0b8d65a blueswir1
                    endaddr = MIN(endaddr,
281 e0b8d65a blueswir1
                                    (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
282 b5fc909e pbrook
                    page_set_flags(startaddr & TARGET_PAGE_MASK,
283 50a9569b balrog
                                   TARGET_PAGE_ALIGN(endaddr),
284 50a9569b balrog
                                   PAGE_RESERVED); 
285 50a9569b balrog
                }
286 50a9569b balrog
            } while (!feof(f));
287 50a9569b balrog
            fclose(f);
288 50a9569b balrog
        }
289 c8a706fe pbrook
        mmap_unlock();
290 50a9569b balrog
    }
291 50a9569b balrog
#endif
292 54936004 bellard
}
293 54936004 bellard
294 434929bf aliguori
static inline PageDesc **page_l1_map(target_ulong index)
295 54936004 bellard
{
296 17e2377a pbrook
#if TARGET_LONG_BITS > 32
297 17e2377a pbrook
    /* Host memory outside guest VM.  For 32-bit targets we have already
298 17e2377a pbrook
       excluded high addresses.  */
299 d8173e0f ths
    if (index > ((target_ulong)L2_SIZE * L1_SIZE))
300 17e2377a pbrook
        return NULL;
301 17e2377a pbrook
#endif
302 434929bf aliguori
    return &l1_map[index >> L2_BITS];
303 434929bf aliguori
}
304 434929bf aliguori
305 434929bf aliguori
static inline PageDesc *page_find_alloc(target_ulong index)
306 434929bf aliguori
{
307 434929bf aliguori
    PageDesc **lp, *p;
308 434929bf aliguori
    lp = page_l1_map(index);
309 434929bf aliguori
    if (!lp)
310 434929bf aliguori
        return NULL;
311 434929bf aliguori
312 54936004 bellard
    p = *lp;
313 54936004 bellard
    if (!p) {
314 54936004 bellard
        /* allocate if not found */
315 17e2377a pbrook
#if defined(CONFIG_USER_ONLY)
316 17e2377a pbrook
        size_t len = sizeof(PageDesc) * L2_SIZE;
317 17e2377a pbrook
        /* Don't use qemu_malloc because it may recurse.  */
318 660f11be Blue Swirl
        p = mmap(NULL, len, PROT_READ | PROT_WRITE,
319 17e2377a pbrook
                 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
320 54936004 bellard
        *lp = p;
321 fb1c2cd7 aurel32
        if (h2g_valid(p)) {
322 fb1c2cd7 aurel32
            unsigned long addr = h2g(p);
323 17e2377a pbrook
            page_set_flags(addr & TARGET_PAGE_MASK,
324 17e2377a pbrook
                           TARGET_PAGE_ALIGN(addr + len),
325 17e2377a pbrook
                           PAGE_RESERVED); 
326 17e2377a pbrook
        }
327 17e2377a pbrook
#else
328 17e2377a pbrook
        p = qemu_mallocz(sizeof(PageDesc) * L2_SIZE);
329 17e2377a pbrook
        *lp = p;
330 17e2377a pbrook
#endif
331 54936004 bellard
    }
332 54936004 bellard
    return p + (index & (L2_SIZE - 1));
333 54936004 bellard
}
334 54936004 bellard
335 00f82b8a aurel32
static inline PageDesc *page_find(target_ulong index)
336 54936004 bellard
{
337 434929bf aliguori
    PageDesc **lp, *p;
338 434929bf aliguori
    lp = page_l1_map(index);
339 434929bf aliguori
    if (!lp)
340 434929bf aliguori
        return NULL;
341 54936004 bellard
342 434929bf aliguori
    p = *lp;
343 660f11be Blue Swirl
    if (!p) {
344 660f11be Blue Swirl
        return NULL;
345 660f11be Blue Swirl
    }
346 fd6ce8f6 bellard
    return p + (index & (L2_SIZE - 1));
347 fd6ce8f6 bellard
}
348 fd6ce8f6 bellard
349 108c49b8 bellard
static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
350 92e873b9 bellard
{
351 108c49b8 bellard
    void **lp, **p;
352 e3f4e2a4 pbrook
    PhysPageDesc *pd;
353 92e873b9 bellard
354 108c49b8 bellard
    p = (void **)l1_phys_map;
355 108c49b8 bellard
#if TARGET_PHYS_ADDR_SPACE_BITS > 32
356 108c49b8 bellard
357 108c49b8 bellard
#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
358 108c49b8 bellard
#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
359 108c49b8 bellard
#endif
360 108c49b8 bellard
    lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1));
361 92e873b9 bellard
    p = *lp;
362 92e873b9 bellard
    if (!p) {
363 92e873b9 bellard
        /* allocate if not found */
364 108c49b8 bellard
        if (!alloc)
365 108c49b8 bellard
            return NULL;
366 108c49b8 bellard
        p = qemu_vmalloc(sizeof(void *) * L1_SIZE);
367 108c49b8 bellard
        memset(p, 0, sizeof(void *) * L1_SIZE);
368 108c49b8 bellard
        *lp = p;
369 108c49b8 bellard
    }
370 108c49b8 bellard
#endif
371 108c49b8 bellard
    lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
372 e3f4e2a4 pbrook
    pd = *lp;
373 e3f4e2a4 pbrook
    if (!pd) {
374 e3f4e2a4 pbrook
        int i;
375 108c49b8 bellard
        /* allocate if not found */
376 108c49b8 bellard
        if (!alloc)
377 108c49b8 bellard
            return NULL;
378 e3f4e2a4 pbrook
        pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
379 e3f4e2a4 pbrook
        *lp = pd;
380 67c4d23c pbrook
        for (i = 0; i < L2_SIZE; i++) {
381 e3f4e2a4 pbrook
          pd[i].phys_offset = IO_MEM_UNASSIGNED;
382 67c4d23c pbrook
          pd[i].region_offset = (index + i) << TARGET_PAGE_BITS;
383 67c4d23c pbrook
        }
384 92e873b9 bellard
    }
385 e3f4e2a4 pbrook
    return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
386 92e873b9 bellard
}
387 92e873b9 bellard
388 108c49b8 bellard
static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
389 92e873b9 bellard
{
390 108c49b8 bellard
    return phys_page_find_alloc(index, 0);
391 92e873b9 bellard
}
392 92e873b9 bellard
393 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
394 6a00d601 bellard
static void tlb_protect_code(ram_addr_t ram_addr);
395 5fafdf24 ths
static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
396 3a7d929e bellard
                                    target_ulong vaddr);
397 c8a706fe pbrook
#define mmap_lock() do { } while(0)
398 c8a706fe pbrook
#define mmap_unlock() do { } while(0)
399 9fa3e853 bellard
#endif
400 fd6ce8f6 bellard
401 4369415f bellard
#define DEFAULT_CODE_GEN_BUFFER_SIZE (32 * 1024 * 1024)
402 4369415f bellard
403 4369415f bellard
#if defined(CONFIG_USER_ONLY)
404 ccbb4d44 Stuart Brady
/* Currently it is not recommended to allocate big chunks of data in
405 4369415f bellard
   user mode. It will change when a dedicated libc will be used */
406 4369415f bellard
#define USE_STATIC_CODE_GEN_BUFFER
407 4369415f bellard
#endif
408 4369415f bellard
409 4369415f bellard
#ifdef USE_STATIC_CODE_GEN_BUFFER
410 4369415f bellard
static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE];
411 4369415f bellard
#endif
412 4369415f bellard
413 8fcd3692 blueswir1
static void code_gen_alloc(unsigned long tb_size)
414 26a5f13b bellard
{
415 4369415f bellard
#ifdef USE_STATIC_CODE_GEN_BUFFER
416 4369415f bellard
    code_gen_buffer = static_code_gen_buffer;
417 4369415f bellard
    code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
418 4369415f bellard
    map_exec(code_gen_buffer, code_gen_buffer_size);
419 4369415f bellard
#else
420 26a5f13b bellard
    code_gen_buffer_size = tb_size;
421 26a5f13b bellard
    if (code_gen_buffer_size == 0) {
422 4369415f bellard
#if defined(CONFIG_USER_ONLY)
423 4369415f bellard
        /* in user mode, phys_ram_size is not meaningful */
424 4369415f bellard
        code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
425 4369415f bellard
#else
426 ccbb4d44 Stuart Brady
        /* XXX: needs adjustments */
427 94a6b54f pbrook
        code_gen_buffer_size = (unsigned long)(ram_size / 4);
428 4369415f bellard
#endif
429 26a5f13b bellard
    }
430 26a5f13b bellard
    if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE)
431 26a5f13b bellard
        code_gen_buffer_size = MIN_CODE_GEN_BUFFER_SIZE;
432 26a5f13b bellard
    /* The code gen buffer location may have constraints depending on
433 26a5f13b bellard
       the host cpu and OS */
434 26a5f13b bellard
#if defined(__linux__) 
435 26a5f13b bellard
    {
436 26a5f13b bellard
        int flags;
437 141ac468 blueswir1
        void *start = NULL;
438 141ac468 blueswir1
439 26a5f13b bellard
        flags = MAP_PRIVATE | MAP_ANONYMOUS;
440 26a5f13b bellard
#if defined(__x86_64__)
441 26a5f13b bellard
        flags |= MAP_32BIT;
442 26a5f13b bellard
        /* Cannot map more than that */
443 26a5f13b bellard
        if (code_gen_buffer_size > (800 * 1024 * 1024))
444 26a5f13b bellard
            code_gen_buffer_size = (800 * 1024 * 1024);
445 141ac468 blueswir1
#elif defined(__sparc_v9__)
446 141ac468 blueswir1
        // Map the buffer below 2G, so we can use direct calls and branches
447 141ac468 blueswir1
        flags |= MAP_FIXED;
448 141ac468 blueswir1
        start = (void *) 0x60000000UL;
449 141ac468 blueswir1
        if (code_gen_buffer_size > (512 * 1024 * 1024))
450 141ac468 blueswir1
            code_gen_buffer_size = (512 * 1024 * 1024);
451 1cb0661e balrog
#elif defined(__arm__)
452 63d41246 balrog
        /* Map the buffer below 32M, so we can use direct calls and branches */
453 1cb0661e balrog
        flags |= MAP_FIXED;
454 1cb0661e balrog
        start = (void *) 0x01000000UL;
455 1cb0661e balrog
        if (code_gen_buffer_size > 16 * 1024 * 1024)
456 1cb0661e balrog
            code_gen_buffer_size = 16 * 1024 * 1024;
457 26a5f13b bellard
#endif
458 141ac468 blueswir1
        code_gen_buffer = mmap(start, code_gen_buffer_size,
459 141ac468 blueswir1
                               PROT_WRITE | PROT_READ | PROT_EXEC,
460 26a5f13b bellard
                               flags, -1, 0);
461 26a5f13b bellard
        if (code_gen_buffer == MAP_FAILED) {
462 26a5f13b bellard
            fprintf(stderr, "Could not allocate dynamic translator buffer\n");
463 26a5f13b bellard
            exit(1);
464 26a5f13b bellard
        }
465 26a5f13b bellard
    }
466 c5e97233 blueswir1
#elif defined(__FreeBSD__) || defined(__DragonFly__)
467 06e67a82 aliguori
    {
468 06e67a82 aliguori
        int flags;
469 06e67a82 aliguori
        void *addr = NULL;
470 06e67a82 aliguori
        flags = MAP_PRIVATE | MAP_ANONYMOUS;
471 06e67a82 aliguori
#if defined(__x86_64__)
472 06e67a82 aliguori
        /* FreeBSD doesn't have MAP_32BIT, use MAP_FIXED and assume
473 06e67a82 aliguori
         * 0x40000000 is free */
474 06e67a82 aliguori
        flags |= MAP_FIXED;
475 06e67a82 aliguori
        addr = (void *)0x40000000;
476 06e67a82 aliguori
        /* Cannot map more than that */
477 06e67a82 aliguori
        if (code_gen_buffer_size > (800 * 1024 * 1024))
478 06e67a82 aliguori
            code_gen_buffer_size = (800 * 1024 * 1024);
479 06e67a82 aliguori
#endif
480 06e67a82 aliguori
        code_gen_buffer = mmap(addr, code_gen_buffer_size,
481 06e67a82 aliguori
                               PROT_WRITE | PROT_READ | PROT_EXEC, 
482 06e67a82 aliguori
                               flags, -1, 0);
483 06e67a82 aliguori
        if (code_gen_buffer == MAP_FAILED) {
484 06e67a82 aliguori
            fprintf(stderr, "Could not allocate dynamic translator buffer\n");
485 06e67a82 aliguori
            exit(1);
486 06e67a82 aliguori
        }
487 06e67a82 aliguori
    }
488 26a5f13b bellard
#else
489 26a5f13b bellard
    code_gen_buffer = qemu_malloc(code_gen_buffer_size);
490 26a5f13b bellard
    map_exec(code_gen_buffer, code_gen_buffer_size);
491 26a5f13b bellard
#endif
492 4369415f bellard
#endif /* !USE_STATIC_CODE_GEN_BUFFER */
493 26a5f13b bellard
    map_exec(code_gen_prologue, sizeof(code_gen_prologue));
494 26a5f13b bellard
    code_gen_buffer_max_size = code_gen_buffer_size - 
495 26a5f13b bellard
        code_gen_max_block_size();
496 26a5f13b bellard
    code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
497 26a5f13b bellard
    tbs = qemu_malloc(code_gen_max_blocks * sizeof(TranslationBlock));
498 26a5f13b bellard
}
499 26a5f13b bellard
500 26a5f13b bellard
/* Must be called before using the QEMU cpus. 'tb_size' is the size
501 26a5f13b bellard
   (in bytes) allocated to the translation buffer. Zero means default
502 26a5f13b bellard
   size. */
503 26a5f13b bellard
void cpu_exec_init_all(unsigned long tb_size)
504 26a5f13b bellard
{
505 26a5f13b bellard
    cpu_gen_init();
506 26a5f13b bellard
    code_gen_alloc(tb_size);
507 26a5f13b bellard
    code_gen_ptr = code_gen_buffer;
508 4369415f bellard
    page_init();
509 e2eef170 pbrook
#if !defined(CONFIG_USER_ONLY)
510 26a5f13b bellard
    io_mem_init();
511 e2eef170 pbrook
#endif
512 26a5f13b bellard
}
513 26a5f13b bellard
514 9656f324 pbrook
#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
515 9656f324 pbrook
516 9656f324 pbrook
#define CPU_COMMON_SAVE_VERSION 1
517 9656f324 pbrook
518 9656f324 pbrook
static void cpu_common_save(QEMUFile *f, void *opaque)
519 9656f324 pbrook
{
520 9656f324 pbrook
    CPUState *env = opaque;
521 9656f324 pbrook
522 4c0960c0 Avi Kivity
    cpu_synchronize_state(env);
523 b0a46a33 Jan Kiszka
524 9656f324 pbrook
    qemu_put_be32s(f, &env->halted);
525 9656f324 pbrook
    qemu_put_be32s(f, &env->interrupt_request);
526 9656f324 pbrook
}
527 9656f324 pbrook
528 9656f324 pbrook
static int cpu_common_load(QEMUFile *f, void *opaque, int version_id)
529 9656f324 pbrook
{
530 9656f324 pbrook
    CPUState *env = opaque;
531 9656f324 pbrook
532 4c0960c0 Avi Kivity
    cpu_synchronize_state(env);
533 9656f324 pbrook
    if (version_id != CPU_COMMON_SAVE_VERSION)
534 9656f324 pbrook
        return -EINVAL;
535 9656f324 pbrook
536 9656f324 pbrook
    qemu_get_be32s(f, &env->halted);
537 75f482ae pbrook
    qemu_get_be32s(f, &env->interrupt_request);
538 3098dba0 aurel32
    /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
539 3098dba0 aurel32
       version_id is increased. */
540 3098dba0 aurel32
    env->interrupt_request &= ~0x01;
541 9656f324 pbrook
    tlb_flush(env, 1);
542 9656f324 pbrook
543 9656f324 pbrook
    return 0;
544 9656f324 pbrook
}
545 9656f324 pbrook
#endif
546 9656f324 pbrook
547 950f1472 Glauber Costa
CPUState *qemu_get_cpu(int cpu)
548 950f1472 Glauber Costa
{
549 950f1472 Glauber Costa
    CPUState *env = first_cpu;
550 950f1472 Glauber Costa
551 950f1472 Glauber Costa
    while (env) {
552 950f1472 Glauber Costa
        if (env->cpu_index == cpu)
553 950f1472 Glauber Costa
            break;
554 950f1472 Glauber Costa
        env = env->next_cpu;
555 950f1472 Glauber Costa
    }
556 950f1472 Glauber Costa
557 950f1472 Glauber Costa
    return env;
558 950f1472 Glauber Costa
}
559 950f1472 Glauber Costa
560 6a00d601 bellard
void cpu_exec_init(CPUState *env)
561 fd6ce8f6 bellard
{
562 6a00d601 bellard
    CPUState **penv;
563 6a00d601 bellard
    int cpu_index;
564 6a00d601 bellard
565 c2764719 pbrook
#if defined(CONFIG_USER_ONLY)
566 c2764719 pbrook
    cpu_list_lock();
567 c2764719 pbrook
#endif
568 6a00d601 bellard
    env->next_cpu = NULL;
569 6a00d601 bellard
    penv = &first_cpu;
570 6a00d601 bellard
    cpu_index = 0;
571 6a00d601 bellard
    while (*penv != NULL) {
572 1e9fa730 Nathan Froyd
        penv = &(*penv)->next_cpu;
573 6a00d601 bellard
        cpu_index++;
574 6a00d601 bellard
    }
575 6a00d601 bellard
    env->cpu_index = cpu_index;
576 268a362c aliguori
    env->numa_node = 0;
577 c0ce998e aliguori
    TAILQ_INIT(&env->breakpoints);
578 c0ce998e aliguori
    TAILQ_INIT(&env->watchpoints);
579 6a00d601 bellard
    *penv = env;
580 c2764719 pbrook
#if defined(CONFIG_USER_ONLY)
581 c2764719 pbrook
    cpu_list_unlock();
582 c2764719 pbrook
#endif
583 b3c7724c pbrook
#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
584 9656f324 pbrook
    register_savevm("cpu_common", cpu_index, CPU_COMMON_SAVE_VERSION,
585 9656f324 pbrook
                    cpu_common_save, cpu_common_load, env);
586 b3c7724c pbrook
    register_savevm("cpu", cpu_index, CPU_SAVE_VERSION,
587 b3c7724c pbrook
                    cpu_save, cpu_load, env);
588 b3c7724c pbrook
#endif
589 fd6ce8f6 bellard
}
590 fd6ce8f6 bellard
591 9fa3e853 bellard
static inline void invalidate_page_bitmap(PageDesc *p)
592 9fa3e853 bellard
{
593 9fa3e853 bellard
    if (p->code_bitmap) {
594 59817ccb bellard
        qemu_free(p->code_bitmap);
595 9fa3e853 bellard
        p->code_bitmap = NULL;
596 9fa3e853 bellard
    }
597 9fa3e853 bellard
    p->code_write_count = 0;
598 9fa3e853 bellard
}
599 9fa3e853 bellard
600 fd6ce8f6 bellard
/* set to NULL all the 'first_tb' fields in all PageDescs */
601 fd6ce8f6 bellard
static void page_flush_tb(void)
602 fd6ce8f6 bellard
{
603 fd6ce8f6 bellard
    int i, j;
604 fd6ce8f6 bellard
    PageDesc *p;
605 fd6ce8f6 bellard
606 fd6ce8f6 bellard
    for(i = 0; i < L1_SIZE; i++) {
607 fd6ce8f6 bellard
        p = l1_map[i];
608 fd6ce8f6 bellard
        if (p) {
609 9fa3e853 bellard
            for(j = 0; j < L2_SIZE; j++) {
610 9fa3e853 bellard
                p->first_tb = NULL;
611 9fa3e853 bellard
                invalidate_page_bitmap(p);
612 9fa3e853 bellard
                p++;
613 9fa3e853 bellard
            }
614 fd6ce8f6 bellard
        }
615 fd6ce8f6 bellard
    }
616 fd6ce8f6 bellard
}
617 fd6ce8f6 bellard
618 fd6ce8f6 bellard
/* flush all the translation blocks */
619 d4e8164f bellard
/* XXX: tb_flush is currently not thread safe */
620 6a00d601 bellard
void tb_flush(CPUState *env1)
621 fd6ce8f6 bellard
{
622 6a00d601 bellard
    CPUState *env;
623 0124311e bellard
#if defined(DEBUG_FLUSH)
624 ab3d1727 blueswir1
    printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
625 ab3d1727 blueswir1
           (unsigned long)(code_gen_ptr - code_gen_buffer),
626 ab3d1727 blueswir1
           nb_tbs, nb_tbs > 0 ?
627 ab3d1727 blueswir1
           ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
628 fd6ce8f6 bellard
#endif
629 26a5f13b bellard
    if ((unsigned long)(code_gen_ptr - code_gen_buffer) > code_gen_buffer_size)
630 a208e54a pbrook
        cpu_abort(env1, "Internal error: code buffer overflow\n");
631 a208e54a pbrook
632 fd6ce8f6 bellard
    nb_tbs = 0;
633 3b46e624 ths
634 6a00d601 bellard
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
635 6a00d601 bellard
        memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
636 6a00d601 bellard
    }
637 9fa3e853 bellard
638 8a8a608f bellard
    memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
639 fd6ce8f6 bellard
    page_flush_tb();
640 9fa3e853 bellard
641 fd6ce8f6 bellard
    code_gen_ptr = code_gen_buffer;
642 d4e8164f bellard
    /* XXX: flush processor icache at this point if cache flush is
643 d4e8164f bellard
       expensive */
644 e3db7226 bellard
    tb_flush_count++;
645 fd6ce8f6 bellard
}
646 fd6ce8f6 bellard
647 fd6ce8f6 bellard
#ifdef DEBUG_TB_CHECK
648 fd6ce8f6 bellard
649 bc98a7ef j_mayer
static void tb_invalidate_check(target_ulong address)
650 fd6ce8f6 bellard
{
651 fd6ce8f6 bellard
    TranslationBlock *tb;
652 fd6ce8f6 bellard
    int i;
653 fd6ce8f6 bellard
    address &= TARGET_PAGE_MASK;
654 99773bd4 pbrook
    for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
655 99773bd4 pbrook
        for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
656 fd6ce8f6 bellard
            if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
657 fd6ce8f6 bellard
                  address >= tb->pc + tb->size)) {
658 0bf9e31a Blue Swirl
                printf("ERROR invalidate: address=" TARGET_FMT_lx
659 0bf9e31a Blue Swirl
                       " PC=%08lx size=%04x\n",
660 99773bd4 pbrook
                       address, (long)tb->pc, tb->size);
661 fd6ce8f6 bellard
            }
662 fd6ce8f6 bellard
        }
663 fd6ce8f6 bellard
    }
664 fd6ce8f6 bellard
}
665 fd6ce8f6 bellard
666 fd6ce8f6 bellard
/* verify that all the pages have correct rights for code */
667 fd6ce8f6 bellard
static void tb_page_check(void)
668 fd6ce8f6 bellard
{
669 fd6ce8f6 bellard
    TranslationBlock *tb;
670 fd6ce8f6 bellard
    int i, flags1, flags2;
671 3b46e624 ths
672 99773bd4 pbrook
    for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
673 99773bd4 pbrook
        for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
674 fd6ce8f6 bellard
            flags1 = page_get_flags(tb->pc);
675 fd6ce8f6 bellard
            flags2 = page_get_flags(tb->pc + tb->size - 1);
676 fd6ce8f6 bellard
            if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
677 fd6ce8f6 bellard
                printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
678 99773bd4 pbrook
                       (long)tb->pc, tb->size, flags1, flags2);
679 fd6ce8f6 bellard
            }
680 fd6ce8f6 bellard
        }
681 fd6ce8f6 bellard
    }
682 fd6ce8f6 bellard
}
683 fd6ce8f6 bellard
684 fd6ce8f6 bellard
#endif
685 fd6ce8f6 bellard
686 fd6ce8f6 bellard
/* invalidate one TB */
687 fd6ce8f6 bellard
static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb,
688 fd6ce8f6 bellard
                             int next_offset)
689 fd6ce8f6 bellard
{
690 fd6ce8f6 bellard
    TranslationBlock *tb1;
691 fd6ce8f6 bellard
    for(;;) {
692 fd6ce8f6 bellard
        tb1 = *ptb;
693 fd6ce8f6 bellard
        if (tb1 == tb) {
694 fd6ce8f6 bellard
            *ptb = *(TranslationBlock **)((char *)tb1 + next_offset);
695 fd6ce8f6 bellard
            break;
696 fd6ce8f6 bellard
        }
697 fd6ce8f6 bellard
        ptb = (TranslationBlock **)((char *)tb1 + next_offset);
698 fd6ce8f6 bellard
    }
699 fd6ce8f6 bellard
}
700 fd6ce8f6 bellard
701 9fa3e853 bellard
static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
702 9fa3e853 bellard
{
703 9fa3e853 bellard
    TranslationBlock *tb1;
704 9fa3e853 bellard
    unsigned int n1;
705 9fa3e853 bellard
706 9fa3e853 bellard
    for(;;) {
707 9fa3e853 bellard
        tb1 = *ptb;
708 9fa3e853 bellard
        n1 = (long)tb1 & 3;
709 9fa3e853 bellard
        tb1 = (TranslationBlock *)((long)tb1 & ~3);
710 9fa3e853 bellard
        if (tb1 == tb) {
711 9fa3e853 bellard
            *ptb = tb1->page_next[n1];
712 9fa3e853 bellard
            break;
713 9fa3e853 bellard
        }
714 9fa3e853 bellard
        ptb = &tb1->page_next[n1];
715 9fa3e853 bellard
    }
716 9fa3e853 bellard
}
717 9fa3e853 bellard
718 d4e8164f bellard
static inline void tb_jmp_remove(TranslationBlock *tb, int n)
719 d4e8164f bellard
{
720 d4e8164f bellard
    TranslationBlock *tb1, **ptb;
721 d4e8164f bellard
    unsigned int n1;
722 d4e8164f bellard
723 d4e8164f bellard
    ptb = &tb->jmp_next[n];
724 d4e8164f bellard
    tb1 = *ptb;
725 d4e8164f bellard
    if (tb1) {
726 d4e8164f bellard
        /* find tb(n) in circular list */
727 d4e8164f bellard
        for(;;) {
728 d4e8164f bellard
            tb1 = *ptb;
729 d4e8164f bellard
            n1 = (long)tb1 & 3;
730 d4e8164f bellard
            tb1 = (TranslationBlock *)((long)tb1 & ~3);
731 d4e8164f bellard
            if (n1 == n && tb1 == tb)
732 d4e8164f bellard
                break;
733 d4e8164f bellard
            if (n1 == 2) {
734 d4e8164f bellard
                ptb = &tb1->jmp_first;
735 d4e8164f bellard
            } else {
736 d4e8164f bellard
                ptb = &tb1->jmp_next[n1];
737 d4e8164f bellard
            }
738 d4e8164f bellard
        }
739 d4e8164f bellard
        /* now we can suppress tb(n) from the list */
740 d4e8164f bellard
        *ptb = tb->jmp_next[n];
741 d4e8164f bellard
742 d4e8164f bellard
        tb->jmp_next[n] = NULL;
743 d4e8164f bellard
    }
744 d4e8164f bellard
}
745 d4e8164f bellard
746 d4e8164f bellard
/* reset the jump entry 'n' of a TB so that it is not chained to
747 d4e8164f bellard
   another TB */
748 d4e8164f bellard
static inline void tb_reset_jump(TranslationBlock *tb, int n)
749 d4e8164f bellard
{
750 d4e8164f bellard
    tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
751 d4e8164f bellard
}
752 d4e8164f bellard
753 2e70f6ef pbrook
void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr)
754 fd6ce8f6 bellard
{
755 6a00d601 bellard
    CPUState *env;
756 8a40a180 bellard
    PageDesc *p;
757 d4e8164f bellard
    unsigned int h, n1;
758 00f82b8a aurel32
    target_phys_addr_t phys_pc;
759 8a40a180 bellard
    TranslationBlock *tb1, *tb2;
760 3b46e624 ths
761 8a40a180 bellard
    /* remove the TB from the hash list */
762 8a40a180 bellard
    phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
763 8a40a180 bellard
    h = tb_phys_hash_func(phys_pc);
764 5fafdf24 ths
    tb_remove(&tb_phys_hash[h], tb,
765 8a40a180 bellard
              offsetof(TranslationBlock, phys_hash_next));
766 8a40a180 bellard
767 8a40a180 bellard
    /* remove the TB from the page list */
768 8a40a180 bellard
    if (tb->page_addr[0] != page_addr) {
769 8a40a180 bellard
        p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
770 8a40a180 bellard
        tb_page_remove(&p->first_tb, tb);
771 8a40a180 bellard
        invalidate_page_bitmap(p);
772 8a40a180 bellard
    }
773 8a40a180 bellard
    if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
774 8a40a180 bellard
        p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
775 8a40a180 bellard
        tb_page_remove(&p->first_tb, tb);
776 8a40a180 bellard
        invalidate_page_bitmap(p);
777 8a40a180 bellard
    }
778 8a40a180 bellard
779 36bdbe54 bellard
    tb_invalidated_flag = 1;
780 59817ccb bellard
781 fd6ce8f6 bellard
    /* remove the TB from the hash list */
782 8a40a180 bellard
    h = tb_jmp_cache_hash_func(tb->pc);
783 6a00d601 bellard
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
784 6a00d601 bellard
        if (env->tb_jmp_cache[h] == tb)
785 6a00d601 bellard
            env->tb_jmp_cache[h] = NULL;
786 6a00d601 bellard
    }
787 d4e8164f bellard
788 d4e8164f bellard
    /* suppress this TB from the two jump lists */
789 d4e8164f bellard
    tb_jmp_remove(tb, 0);
790 d4e8164f bellard
    tb_jmp_remove(tb, 1);
791 d4e8164f bellard
792 d4e8164f bellard
    /* suppress any remaining jumps to this TB */
793 d4e8164f bellard
    tb1 = tb->jmp_first;
794 d4e8164f bellard
    for(;;) {
795 d4e8164f bellard
        n1 = (long)tb1 & 3;
796 d4e8164f bellard
        if (n1 == 2)
797 d4e8164f bellard
            break;
798 d4e8164f bellard
        tb1 = (TranslationBlock *)((long)tb1 & ~3);
799 d4e8164f bellard
        tb2 = tb1->jmp_next[n1];
800 d4e8164f bellard
        tb_reset_jump(tb1, n1);
801 d4e8164f bellard
        tb1->jmp_next[n1] = NULL;
802 d4e8164f bellard
        tb1 = tb2;
803 d4e8164f bellard
    }
804 d4e8164f bellard
    tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
805 9fa3e853 bellard
806 e3db7226 bellard
    tb_phys_invalidate_count++;
807 9fa3e853 bellard
}
808 9fa3e853 bellard
809 9fa3e853 bellard
static inline void set_bits(uint8_t *tab, int start, int len)
810 9fa3e853 bellard
{
811 9fa3e853 bellard
    int end, mask, end1;
812 9fa3e853 bellard
813 9fa3e853 bellard
    end = start + len;
814 9fa3e853 bellard
    tab += start >> 3;
815 9fa3e853 bellard
    mask = 0xff << (start & 7);
816 9fa3e853 bellard
    if ((start & ~7) == (end & ~7)) {
817 9fa3e853 bellard
        if (start < end) {
818 9fa3e853 bellard
            mask &= ~(0xff << (end & 7));
819 9fa3e853 bellard
            *tab |= mask;
820 9fa3e853 bellard
        }
821 9fa3e853 bellard
    } else {
822 9fa3e853 bellard
        *tab++ |= mask;
823 9fa3e853 bellard
        start = (start + 8) & ~7;
824 9fa3e853 bellard
        end1 = end & ~7;
825 9fa3e853 bellard
        while (start < end1) {
826 9fa3e853 bellard
            *tab++ = 0xff;
827 9fa3e853 bellard
            start += 8;
828 9fa3e853 bellard
        }
829 9fa3e853 bellard
        if (start < end) {
830 9fa3e853 bellard
            mask = ~(0xff << (end & 7));
831 9fa3e853 bellard
            *tab |= mask;
832 9fa3e853 bellard
        }
833 9fa3e853 bellard
    }
834 9fa3e853 bellard
}
835 9fa3e853 bellard
836 9fa3e853 bellard
static void build_page_bitmap(PageDesc *p)
837 9fa3e853 bellard
{
838 9fa3e853 bellard
    int n, tb_start, tb_end;
839 9fa3e853 bellard
    TranslationBlock *tb;
840 3b46e624 ths
841 b2a7081a pbrook
    p->code_bitmap = qemu_mallocz(TARGET_PAGE_SIZE / 8);
842 9fa3e853 bellard
843 9fa3e853 bellard
    tb = p->first_tb;
844 9fa3e853 bellard
    while (tb != NULL) {
845 9fa3e853 bellard
        n = (long)tb & 3;
846 9fa3e853 bellard
        tb = (TranslationBlock *)((long)tb & ~3);
847 9fa3e853 bellard
        /* NOTE: this is subtle as a TB may span two physical pages */
848 9fa3e853 bellard
        if (n == 0) {
849 9fa3e853 bellard
            /* NOTE: tb_end may be after the end of the page, but
850 9fa3e853 bellard
               it is not a problem */
851 9fa3e853 bellard
            tb_start = tb->pc & ~TARGET_PAGE_MASK;
852 9fa3e853 bellard
            tb_end = tb_start + tb->size;
853 9fa3e853 bellard
            if (tb_end > TARGET_PAGE_SIZE)
854 9fa3e853 bellard
                tb_end = TARGET_PAGE_SIZE;
855 9fa3e853 bellard
        } else {
856 9fa3e853 bellard
            tb_start = 0;
857 9fa3e853 bellard
            tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
858 9fa3e853 bellard
        }
859 9fa3e853 bellard
        set_bits(p->code_bitmap, tb_start, tb_end - tb_start);
860 9fa3e853 bellard
        tb = tb->page_next[n];
861 9fa3e853 bellard
    }
862 9fa3e853 bellard
}
863 9fa3e853 bellard
864 2e70f6ef pbrook
TranslationBlock *tb_gen_code(CPUState *env,
865 2e70f6ef pbrook
                              target_ulong pc, target_ulong cs_base,
866 2e70f6ef pbrook
                              int flags, int cflags)
867 d720b93d bellard
{
868 d720b93d bellard
    TranslationBlock *tb;
869 d720b93d bellard
    uint8_t *tc_ptr;
870 d720b93d bellard
    target_ulong phys_pc, phys_page2, virt_page2;
871 d720b93d bellard
    int code_gen_size;
872 d720b93d bellard
873 c27004ec bellard
    phys_pc = get_phys_addr_code(env, pc);
874 c27004ec bellard
    tb = tb_alloc(pc);
875 d720b93d bellard
    if (!tb) {
876 d720b93d bellard
        /* flush must be done */
877 d720b93d bellard
        tb_flush(env);
878 d720b93d bellard
        /* cannot fail at this point */
879 c27004ec bellard
        tb = tb_alloc(pc);
880 2e70f6ef pbrook
        /* Don't forget to invalidate previous TB info.  */
881 2e70f6ef pbrook
        tb_invalidated_flag = 1;
882 d720b93d bellard
    }
883 d720b93d bellard
    tc_ptr = code_gen_ptr;
884 d720b93d bellard
    tb->tc_ptr = tc_ptr;
885 d720b93d bellard
    tb->cs_base = cs_base;
886 d720b93d bellard
    tb->flags = flags;
887 d720b93d bellard
    tb->cflags = cflags;
888 d07bde88 blueswir1
    cpu_gen_code(env, tb, &code_gen_size);
889 d720b93d bellard
    code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
890 3b46e624 ths
891 d720b93d bellard
    /* check next page if needed */
892 c27004ec bellard
    virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
893 d720b93d bellard
    phys_page2 = -1;
894 c27004ec bellard
    if ((pc & TARGET_PAGE_MASK) != virt_page2) {
895 d720b93d bellard
        phys_page2 = get_phys_addr_code(env, virt_page2);
896 d720b93d bellard
    }
897 d720b93d bellard
    tb_link_phys(tb, phys_pc, phys_page2);
898 2e70f6ef pbrook
    return tb;
899 d720b93d bellard
}
900 3b46e624 ths
901 9fa3e853 bellard
/* invalidate all TBs which intersect with the target physical page
902 9fa3e853 bellard
   starting in range [start;end[. NOTE: start and end must refer to
903 d720b93d bellard
   the same physical page. 'is_cpu_write_access' should be true if called
904 d720b93d bellard
   from a real cpu write access: the virtual CPU will exit the current
905 d720b93d bellard
   TB if code is modified inside this TB. */
906 00f82b8a aurel32
void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t end,
907 d720b93d bellard
                                   int is_cpu_write_access)
908 d720b93d bellard
{
909 6b917547 aliguori
    TranslationBlock *tb, *tb_next, *saved_tb;
910 d720b93d bellard
    CPUState *env = cpu_single_env;
911 9fa3e853 bellard
    target_ulong tb_start, tb_end;
912 6b917547 aliguori
    PageDesc *p;
913 6b917547 aliguori
    int n;
914 6b917547 aliguori
#ifdef TARGET_HAS_PRECISE_SMC
915 6b917547 aliguori
    int current_tb_not_found = is_cpu_write_access;
916 6b917547 aliguori
    TranslationBlock *current_tb = NULL;
917 6b917547 aliguori
    int current_tb_modified = 0;
918 6b917547 aliguori
    target_ulong current_pc = 0;
919 6b917547 aliguori
    target_ulong current_cs_base = 0;
920 6b917547 aliguori
    int current_flags = 0;
921 6b917547 aliguori
#endif /* TARGET_HAS_PRECISE_SMC */
922 9fa3e853 bellard
923 9fa3e853 bellard
    p = page_find(start >> TARGET_PAGE_BITS);
924 5fafdf24 ths
    if (!p)
925 9fa3e853 bellard
        return;
926 5fafdf24 ths
    if (!p->code_bitmap &&
927 d720b93d bellard
        ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
928 d720b93d bellard
        is_cpu_write_access) {
929 9fa3e853 bellard
        /* build code bitmap */
930 9fa3e853 bellard
        build_page_bitmap(p);
931 9fa3e853 bellard
    }
932 9fa3e853 bellard
933 9fa3e853 bellard
    /* we remove all the TBs in the range [start, end[ */
934 9fa3e853 bellard
    /* XXX: see if in some cases it could be faster to invalidate all the code */
935 9fa3e853 bellard
    tb = p->first_tb;
936 9fa3e853 bellard
    while (tb != NULL) {
937 9fa3e853 bellard
        n = (long)tb & 3;
938 9fa3e853 bellard
        tb = (TranslationBlock *)((long)tb & ~3);
939 9fa3e853 bellard
        tb_next = tb->page_next[n];
940 9fa3e853 bellard
        /* NOTE: this is subtle as a TB may span two physical pages */
941 9fa3e853 bellard
        if (n == 0) {
942 9fa3e853 bellard
            /* NOTE: tb_end may be after the end of the page, but
943 9fa3e853 bellard
               it is not a problem */
944 9fa3e853 bellard
            tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
945 9fa3e853 bellard
            tb_end = tb_start + tb->size;
946 9fa3e853 bellard
        } else {
947 9fa3e853 bellard
            tb_start = tb->page_addr[1];
948 9fa3e853 bellard
            tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
949 9fa3e853 bellard
        }
950 9fa3e853 bellard
        if (!(tb_end <= start || tb_start >= end)) {
951 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
952 d720b93d bellard
            if (current_tb_not_found) {
953 d720b93d bellard
                current_tb_not_found = 0;
954 d720b93d bellard
                current_tb = NULL;
955 2e70f6ef pbrook
                if (env->mem_io_pc) {
956 d720b93d bellard
                    /* now we have a real cpu fault */
957 2e70f6ef pbrook
                    current_tb = tb_find_pc(env->mem_io_pc);
958 d720b93d bellard
                }
959 d720b93d bellard
            }
960 d720b93d bellard
            if (current_tb == tb &&
961 2e70f6ef pbrook
                (current_tb->cflags & CF_COUNT_MASK) != 1) {
962 d720b93d bellard
                /* If we are modifying the current TB, we must stop
963 d720b93d bellard
                its execution. We could be more precise by checking
964 d720b93d bellard
                that the modification is after the current PC, but it
965 d720b93d bellard
                would require a specialized function to partially
966 d720b93d bellard
                restore the CPU state */
967 3b46e624 ths
968 d720b93d bellard
                current_tb_modified = 1;
969 5fafdf24 ths
                cpu_restore_state(current_tb, env,
970 2e70f6ef pbrook
                                  env->mem_io_pc, NULL);
971 6b917547 aliguori
                cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
972 6b917547 aliguori
                                     &current_flags);
973 d720b93d bellard
            }
974 d720b93d bellard
#endif /* TARGET_HAS_PRECISE_SMC */
975 6f5a9f7e bellard
            /* we need to do that to handle the case where a signal
976 6f5a9f7e bellard
               occurs while doing tb_phys_invalidate() */
977 6f5a9f7e bellard
            saved_tb = NULL;
978 6f5a9f7e bellard
            if (env) {
979 6f5a9f7e bellard
                saved_tb = env->current_tb;
980 6f5a9f7e bellard
                env->current_tb = NULL;
981 6f5a9f7e bellard
            }
982 9fa3e853 bellard
            tb_phys_invalidate(tb, -1);
983 6f5a9f7e bellard
            if (env) {
984 6f5a9f7e bellard
                env->current_tb = saved_tb;
985 6f5a9f7e bellard
                if (env->interrupt_request && env->current_tb)
986 6f5a9f7e bellard
                    cpu_interrupt(env, env->interrupt_request);
987 6f5a9f7e bellard
            }
988 9fa3e853 bellard
        }
989 9fa3e853 bellard
        tb = tb_next;
990 9fa3e853 bellard
    }
991 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
992 9fa3e853 bellard
    /* if no code remaining, no need to continue to use slow writes */
993 9fa3e853 bellard
    if (!p->first_tb) {
994 9fa3e853 bellard
        invalidate_page_bitmap(p);
995 d720b93d bellard
        if (is_cpu_write_access) {
996 2e70f6ef pbrook
            tlb_unprotect_code_phys(env, start, env->mem_io_vaddr);
997 d720b93d bellard
        }
998 d720b93d bellard
    }
999 d720b93d bellard
#endif
1000 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
1001 d720b93d bellard
    if (current_tb_modified) {
1002 d720b93d bellard
        /* we generate a block containing just the instruction
1003 d720b93d bellard
           modifying the memory. It will ensure that it cannot modify
1004 d720b93d bellard
           itself */
1005 ea1c1802 bellard
        env->current_tb = NULL;
1006 2e70f6ef pbrook
        tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1007 d720b93d bellard
        cpu_resume_from_signal(env, NULL);
1008 9fa3e853 bellard
    }
1009 fd6ce8f6 bellard
#endif
1010 9fa3e853 bellard
}
1011 fd6ce8f6 bellard
1012 9fa3e853 bellard
/* len must be <= 8 and start must be a multiple of len */
1013 00f82b8a aurel32
static inline void tb_invalidate_phys_page_fast(target_phys_addr_t start, int len)
1014 9fa3e853 bellard
{
1015 9fa3e853 bellard
    PageDesc *p;
1016 9fa3e853 bellard
    int offset, b;
1017 59817ccb bellard
#if 0
1018 a4193c8a bellard
    if (1) {
1019 93fcfe39 aliguori
        qemu_log("modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
1020 93fcfe39 aliguori
                  cpu_single_env->mem_io_vaddr, len,
1021 93fcfe39 aliguori
                  cpu_single_env->eip,
1022 93fcfe39 aliguori
                  cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
1023 59817ccb bellard
    }
1024 59817ccb bellard
#endif
1025 9fa3e853 bellard
    p = page_find(start >> TARGET_PAGE_BITS);
1026 5fafdf24 ths
    if (!p)
1027 9fa3e853 bellard
        return;
1028 9fa3e853 bellard
    if (p->code_bitmap) {
1029 9fa3e853 bellard
        offset = start & ~TARGET_PAGE_MASK;
1030 9fa3e853 bellard
        b = p->code_bitmap[offset >> 3] >> (offset & 7);
1031 9fa3e853 bellard
        if (b & ((1 << len) - 1))
1032 9fa3e853 bellard
            goto do_invalidate;
1033 9fa3e853 bellard
    } else {
1034 9fa3e853 bellard
    do_invalidate:
1035 d720b93d bellard
        tb_invalidate_phys_page_range(start, start + len, 1);
1036 9fa3e853 bellard
    }
1037 9fa3e853 bellard
}
1038 9fa3e853 bellard
1039 9fa3e853 bellard
#if !defined(CONFIG_SOFTMMU)
1040 00f82b8a aurel32
static void tb_invalidate_phys_page(target_phys_addr_t addr,
1041 d720b93d bellard
                                    unsigned long pc, void *puc)
1042 9fa3e853 bellard
{
1043 6b917547 aliguori
    TranslationBlock *tb;
1044 9fa3e853 bellard
    PageDesc *p;
1045 6b917547 aliguori
    int n;
1046 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
1047 6b917547 aliguori
    TranslationBlock *current_tb = NULL;
1048 d720b93d bellard
    CPUState *env = cpu_single_env;
1049 6b917547 aliguori
    int current_tb_modified = 0;
1050 6b917547 aliguori
    target_ulong current_pc = 0;
1051 6b917547 aliguori
    target_ulong current_cs_base = 0;
1052 6b917547 aliguori
    int current_flags = 0;
1053 d720b93d bellard
#endif
1054 9fa3e853 bellard
1055 9fa3e853 bellard
    addr &= TARGET_PAGE_MASK;
1056 9fa3e853 bellard
    p = page_find(addr >> TARGET_PAGE_BITS);
1057 5fafdf24 ths
    if (!p)
1058 9fa3e853 bellard
        return;
1059 9fa3e853 bellard
    tb = p->first_tb;
1060 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
1061 d720b93d bellard
    if (tb && pc != 0) {
1062 d720b93d bellard
        current_tb = tb_find_pc(pc);
1063 d720b93d bellard
    }
1064 d720b93d bellard
#endif
1065 9fa3e853 bellard
    while (tb != NULL) {
1066 9fa3e853 bellard
        n = (long)tb & 3;
1067 9fa3e853 bellard
        tb = (TranslationBlock *)((long)tb & ~3);
1068 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
1069 d720b93d bellard
        if (current_tb == tb &&
1070 2e70f6ef pbrook
            (current_tb->cflags & CF_COUNT_MASK) != 1) {
1071 d720b93d bellard
                /* If we are modifying the current TB, we must stop
1072 d720b93d bellard
                   its execution. We could be more precise by checking
1073 d720b93d bellard
                   that the modification is after the current PC, but it
1074 d720b93d bellard
                   would require a specialized function to partially
1075 d720b93d bellard
                   restore the CPU state */
1076 3b46e624 ths
1077 d720b93d bellard
            current_tb_modified = 1;
1078 d720b93d bellard
            cpu_restore_state(current_tb, env, pc, puc);
1079 6b917547 aliguori
            cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
1080 6b917547 aliguori
                                 &current_flags);
1081 d720b93d bellard
        }
1082 d720b93d bellard
#endif /* TARGET_HAS_PRECISE_SMC */
1083 9fa3e853 bellard
        tb_phys_invalidate(tb, addr);
1084 9fa3e853 bellard
        tb = tb->page_next[n];
1085 9fa3e853 bellard
    }
1086 fd6ce8f6 bellard
    p->first_tb = NULL;
1087 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
1088 d720b93d bellard
    if (current_tb_modified) {
1089 d720b93d bellard
        /* we generate a block containing just the instruction
1090 d720b93d bellard
           modifying the memory. It will ensure that it cannot modify
1091 d720b93d bellard
           itself */
1092 ea1c1802 bellard
        env->current_tb = NULL;
1093 2e70f6ef pbrook
        tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1094 d720b93d bellard
        cpu_resume_from_signal(env, puc);
1095 d720b93d bellard
    }
1096 d720b93d bellard
#endif
1097 fd6ce8f6 bellard
}
1098 9fa3e853 bellard
#endif
1099 fd6ce8f6 bellard
1100 fd6ce8f6 bellard
/* add the tb in the target page and protect it if necessary */
1101 5fafdf24 ths
static inline void tb_alloc_page(TranslationBlock *tb,
1102 53a5960a pbrook
                                 unsigned int n, target_ulong page_addr)
1103 fd6ce8f6 bellard
{
1104 fd6ce8f6 bellard
    PageDesc *p;
1105 9fa3e853 bellard
    TranslationBlock *last_first_tb;
1106 9fa3e853 bellard
1107 9fa3e853 bellard
    tb->page_addr[n] = page_addr;
1108 3a7d929e bellard
    p = page_find_alloc(page_addr >> TARGET_PAGE_BITS);
1109 9fa3e853 bellard
    tb->page_next[n] = p->first_tb;
1110 9fa3e853 bellard
    last_first_tb = p->first_tb;
1111 9fa3e853 bellard
    p->first_tb = (TranslationBlock *)((long)tb | n);
1112 9fa3e853 bellard
    invalidate_page_bitmap(p);
1113 fd6ce8f6 bellard
1114 107db443 bellard
#if defined(TARGET_HAS_SMC) || 1
1115 d720b93d bellard
1116 9fa3e853 bellard
#if defined(CONFIG_USER_ONLY)
1117 fd6ce8f6 bellard
    if (p->flags & PAGE_WRITE) {
1118 53a5960a pbrook
        target_ulong addr;
1119 53a5960a pbrook
        PageDesc *p2;
1120 9fa3e853 bellard
        int prot;
1121 9fa3e853 bellard
1122 fd6ce8f6 bellard
        /* force the host page as non writable (writes will have a
1123 fd6ce8f6 bellard
           page fault + mprotect overhead) */
1124 53a5960a pbrook
        page_addr &= qemu_host_page_mask;
1125 fd6ce8f6 bellard
        prot = 0;
1126 53a5960a pbrook
        for(addr = page_addr; addr < page_addr + qemu_host_page_size;
1127 53a5960a pbrook
            addr += TARGET_PAGE_SIZE) {
1128 53a5960a pbrook
1129 53a5960a pbrook
            p2 = page_find (addr >> TARGET_PAGE_BITS);
1130 53a5960a pbrook
            if (!p2)
1131 53a5960a pbrook
                continue;
1132 53a5960a pbrook
            prot |= p2->flags;
1133 53a5960a pbrook
            p2->flags &= ~PAGE_WRITE;
1134 53a5960a pbrook
            page_get_flags(addr);
1135 53a5960a pbrook
          }
1136 5fafdf24 ths
        mprotect(g2h(page_addr), qemu_host_page_size,
1137 fd6ce8f6 bellard
                 (prot & PAGE_BITS) & ~PAGE_WRITE);
1138 fd6ce8f6 bellard
#ifdef DEBUG_TB_INVALIDATE
1139 ab3d1727 blueswir1
        printf("protecting code page: 0x" TARGET_FMT_lx "\n",
1140 53a5960a pbrook
               page_addr);
1141 fd6ce8f6 bellard
#endif
1142 fd6ce8f6 bellard
    }
1143 9fa3e853 bellard
#else
1144 9fa3e853 bellard
    /* if some code is already present, then the pages are already
1145 9fa3e853 bellard
       protected. So we handle the case where only the first TB is
1146 9fa3e853 bellard
       allocated in a physical page */
1147 9fa3e853 bellard
    if (!last_first_tb) {
1148 6a00d601 bellard
        tlb_protect_code(page_addr);
1149 9fa3e853 bellard
    }
1150 9fa3e853 bellard
#endif
1151 d720b93d bellard
1152 d720b93d bellard
#endif /* TARGET_HAS_SMC */
1153 fd6ce8f6 bellard
}
1154 fd6ce8f6 bellard
1155 fd6ce8f6 bellard
/* Allocate a new translation block. Flush the translation buffer if
1156 fd6ce8f6 bellard
   too many translation blocks or too much generated code. */
1157 c27004ec bellard
TranslationBlock *tb_alloc(target_ulong pc)
1158 fd6ce8f6 bellard
{
1159 fd6ce8f6 bellard
    TranslationBlock *tb;
1160 fd6ce8f6 bellard
1161 26a5f13b bellard
    if (nb_tbs >= code_gen_max_blocks ||
1162 26a5f13b bellard
        (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
1163 d4e8164f bellard
        return NULL;
1164 fd6ce8f6 bellard
    tb = &tbs[nb_tbs++];
1165 fd6ce8f6 bellard
    tb->pc = pc;
1166 b448f2f3 bellard
    tb->cflags = 0;
1167 d4e8164f bellard
    return tb;
1168 d4e8164f bellard
}
1169 d4e8164f bellard
1170 2e70f6ef pbrook
void tb_free(TranslationBlock *tb)
1171 2e70f6ef pbrook
{
1172 bf20dc07 ths
    /* In practice this is mostly used for single use temporary TB
1173 2e70f6ef pbrook
       Ignore the hard cases and just back up if this TB happens to
1174 2e70f6ef pbrook
       be the last one generated.  */
1175 2e70f6ef pbrook
    if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) {
1176 2e70f6ef pbrook
        code_gen_ptr = tb->tc_ptr;
1177 2e70f6ef pbrook
        nb_tbs--;
1178 2e70f6ef pbrook
    }
1179 2e70f6ef pbrook
}
1180 2e70f6ef pbrook
1181 9fa3e853 bellard
/* add a new TB and link it to the physical page tables. phys_page2 is
1182 9fa3e853 bellard
   (-1) to indicate that only one page contains the TB. */
1183 5fafdf24 ths
void tb_link_phys(TranslationBlock *tb,
1184 9fa3e853 bellard
                  target_ulong phys_pc, target_ulong phys_page2)
1185 d4e8164f bellard
{
1186 9fa3e853 bellard
    unsigned int h;
1187 9fa3e853 bellard
    TranslationBlock **ptb;
1188 9fa3e853 bellard
1189 c8a706fe pbrook
    /* Grab the mmap lock to stop another thread invalidating this TB
1190 c8a706fe pbrook
       before we are done.  */
1191 c8a706fe pbrook
    mmap_lock();
1192 9fa3e853 bellard
    /* add in the physical hash table */
1193 9fa3e853 bellard
    h = tb_phys_hash_func(phys_pc);
1194 9fa3e853 bellard
    ptb = &tb_phys_hash[h];
1195 9fa3e853 bellard
    tb->phys_hash_next = *ptb;
1196 9fa3e853 bellard
    *ptb = tb;
1197 fd6ce8f6 bellard
1198 fd6ce8f6 bellard
    /* add in the page list */
1199 9fa3e853 bellard
    tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK);
1200 9fa3e853 bellard
    if (phys_page2 != -1)
1201 9fa3e853 bellard
        tb_alloc_page(tb, 1, phys_page2);
1202 9fa3e853 bellard
    else
1203 9fa3e853 bellard
        tb->page_addr[1] = -1;
1204 9fa3e853 bellard
1205 d4e8164f bellard
    tb->jmp_first = (TranslationBlock *)((long)tb | 2);
1206 d4e8164f bellard
    tb->jmp_next[0] = NULL;
1207 d4e8164f bellard
    tb->jmp_next[1] = NULL;
1208 d4e8164f bellard
1209 d4e8164f bellard
    /* init original jump addresses */
1210 d4e8164f bellard
    if (tb->tb_next_offset[0] != 0xffff)
1211 d4e8164f bellard
        tb_reset_jump(tb, 0);
1212 d4e8164f bellard
    if (tb->tb_next_offset[1] != 0xffff)
1213 d4e8164f bellard
        tb_reset_jump(tb, 1);
1214 8a40a180 bellard
1215 8a40a180 bellard
#ifdef DEBUG_TB_CHECK
1216 8a40a180 bellard
    tb_page_check();
1217 8a40a180 bellard
#endif
1218 c8a706fe pbrook
    mmap_unlock();
1219 fd6ce8f6 bellard
}
1220 fd6ce8f6 bellard
1221 9fa3e853 bellard
/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
1222 9fa3e853 bellard
   tb[1].tc_ptr. Return NULL if not found */
1223 9fa3e853 bellard
TranslationBlock *tb_find_pc(unsigned long tc_ptr)
1224 fd6ce8f6 bellard
{
1225 9fa3e853 bellard
    int m_min, m_max, m;
1226 9fa3e853 bellard
    unsigned long v;
1227 9fa3e853 bellard
    TranslationBlock *tb;
1228 a513fe19 bellard
1229 a513fe19 bellard
    if (nb_tbs <= 0)
1230 a513fe19 bellard
        return NULL;
1231 a513fe19 bellard
    if (tc_ptr < (unsigned long)code_gen_buffer ||
1232 a513fe19 bellard
        tc_ptr >= (unsigned long)code_gen_ptr)
1233 a513fe19 bellard
        return NULL;
1234 a513fe19 bellard
    /* binary search (cf Knuth) */
1235 a513fe19 bellard
    m_min = 0;
1236 a513fe19 bellard
    m_max = nb_tbs - 1;
1237 a513fe19 bellard
    while (m_min <= m_max) {
1238 a513fe19 bellard
        m = (m_min + m_max) >> 1;
1239 a513fe19 bellard
        tb = &tbs[m];
1240 a513fe19 bellard
        v = (unsigned long)tb->tc_ptr;
1241 a513fe19 bellard
        if (v == tc_ptr)
1242 a513fe19 bellard
            return tb;
1243 a513fe19 bellard
        else if (tc_ptr < v) {
1244 a513fe19 bellard
            m_max = m - 1;
1245 a513fe19 bellard
        } else {
1246 a513fe19 bellard
            m_min = m + 1;
1247 a513fe19 bellard
        }
1248 5fafdf24 ths
    }
1249 a513fe19 bellard
    return &tbs[m_max];
1250 a513fe19 bellard
}
1251 7501267e bellard
1252 ea041c0e bellard
static void tb_reset_jump_recursive(TranslationBlock *tb);
1253 ea041c0e bellard
1254 ea041c0e bellard
static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
1255 ea041c0e bellard
{
1256 ea041c0e bellard
    TranslationBlock *tb1, *tb_next, **ptb;
1257 ea041c0e bellard
    unsigned int n1;
1258 ea041c0e bellard
1259 ea041c0e bellard
    tb1 = tb->jmp_next[n];
1260 ea041c0e bellard
    if (tb1 != NULL) {
1261 ea041c0e bellard
        /* find head of list */
1262 ea041c0e bellard
        for(;;) {
1263 ea041c0e bellard
            n1 = (long)tb1 & 3;
1264 ea041c0e bellard
            tb1 = (TranslationBlock *)((long)tb1 & ~3);
1265 ea041c0e bellard
            if (n1 == 2)
1266 ea041c0e bellard
                break;
1267 ea041c0e bellard
            tb1 = tb1->jmp_next[n1];
1268 ea041c0e bellard
        }
1269 ea041c0e bellard
        /* we are now sure now that tb jumps to tb1 */
1270 ea041c0e bellard
        tb_next = tb1;
1271 ea041c0e bellard
1272 ea041c0e bellard
        /* remove tb from the jmp_first list */
1273 ea041c0e bellard
        ptb = &tb_next->jmp_first;
1274 ea041c0e bellard
        for(;;) {
1275 ea041c0e bellard
            tb1 = *ptb;
1276 ea041c0e bellard
            n1 = (long)tb1 & 3;
1277 ea041c0e bellard
            tb1 = (TranslationBlock *)((long)tb1 & ~3);
1278 ea041c0e bellard
            if (n1 == n && tb1 == tb)
1279 ea041c0e bellard
                break;
1280 ea041c0e bellard
            ptb = &tb1->jmp_next[n1];
1281 ea041c0e bellard
        }
1282 ea041c0e bellard
        *ptb = tb->jmp_next[n];
1283 ea041c0e bellard
        tb->jmp_next[n] = NULL;
1284 3b46e624 ths
1285 ea041c0e bellard
        /* suppress the jump to next tb in generated code */
1286 ea041c0e bellard
        tb_reset_jump(tb, n);
1287 ea041c0e bellard
1288 0124311e bellard
        /* suppress jumps in the tb on which we could have jumped */
1289 ea041c0e bellard
        tb_reset_jump_recursive(tb_next);
1290 ea041c0e bellard
    }
1291 ea041c0e bellard
}
1292 ea041c0e bellard
1293 ea041c0e bellard
static void tb_reset_jump_recursive(TranslationBlock *tb)
1294 ea041c0e bellard
{
1295 ea041c0e bellard
    tb_reset_jump_recursive2(tb, 0);
1296 ea041c0e bellard
    tb_reset_jump_recursive2(tb, 1);
1297 ea041c0e bellard
}
1298 ea041c0e bellard
1299 1fddef4b bellard
#if defined(TARGET_HAS_ICE)
1300 d720b93d bellard
static void breakpoint_invalidate(CPUState *env, target_ulong pc)
1301 d720b93d bellard
{
1302 9b3c35e0 j_mayer
    target_phys_addr_t addr;
1303 9b3c35e0 j_mayer
    target_ulong pd;
1304 c2f07f81 pbrook
    ram_addr_t ram_addr;
1305 c2f07f81 pbrook
    PhysPageDesc *p;
1306 d720b93d bellard
1307 c2f07f81 pbrook
    addr = cpu_get_phys_page_debug(env, pc);
1308 c2f07f81 pbrook
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
1309 c2f07f81 pbrook
    if (!p) {
1310 c2f07f81 pbrook
        pd = IO_MEM_UNASSIGNED;
1311 c2f07f81 pbrook
    } else {
1312 c2f07f81 pbrook
        pd = p->phys_offset;
1313 c2f07f81 pbrook
    }
1314 c2f07f81 pbrook
    ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
1315 706cd4b5 pbrook
    tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
1316 d720b93d bellard
}
1317 c27004ec bellard
#endif
1318 d720b93d bellard
1319 6658ffb8 pbrook
/* Add a watchpoint.  */
1320 a1d1bb31 aliguori
int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
1321 a1d1bb31 aliguori
                          int flags, CPUWatchpoint **watchpoint)
1322 6658ffb8 pbrook
{
1323 b4051334 aliguori
    target_ulong len_mask = ~(len - 1);
1324 c0ce998e aliguori
    CPUWatchpoint *wp;
1325 6658ffb8 pbrook
1326 b4051334 aliguori
    /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
1327 b4051334 aliguori
    if ((len != 1 && len != 2 && len != 4 && len != 8) || (addr & ~len_mask)) {
1328 b4051334 aliguori
        fprintf(stderr, "qemu: tried to set invalid watchpoint at "
1329 b4051334 aliguori
                TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
1330 b4051334 aliguori
        return -EINVAL;
1331 b4051334 aliguori
    }
1332 a1d1bb31 aliguori
    wp = qemu_malloc(sizeof(*wp));
1333 a1d1bb31 aliguori
1334 a1d1bb31 aliguori
    wp->vaddr = addr;
1335 b4051334 aliguori
    wp->len_mask = len_mask;
1336 a1d1bb31 aliguori
    wp->flags = flags;
1337 a1d1bb31 aliguori
1338 2dc9f411 aliguori
    /* keep all GDB-injected watchpoints in front */
1339 c0ce998e aliguori
    if (flags & BP_GDB)
1340 c0ce998e aliguori
        TAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
1341 c0ce998e aliguori
    else
1342 c0ce998e aliguori
        TAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
1343 6658ffb8 pbrook
1344 6658ffb8 pbrook
    tlb_flush_page(env, addr);
1345 a1d1bb31 aliguori
1346 a1d1bb31 aliguori
    if (watchpoint)
1347 a1d1bb31 aliguori
        *watchpoint = wp;
1348 a1d1bb31 aliguori
    return 0;
1349 6658ffb8 pbrook
}
1350 6658ffb8 pbrook
1351 a1d1bb31 aliguori
/* Remove a specific watchpoint.  */
1352 a1d1bb31 aliguori
int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len,
1353 a1d1bb31 aliguori
                          int flags)
1354 6658ffb8 pbrook
{
1355 b4051334 aliguori
    target_ulong len_mask = ~(len - 1);
1356 a1d1bb31 aliguori
    CPUWatchpoint *wp;
1357 6658ffb8 pbrook
1358 c0ce998e aliguori
    TAILQ_FOREACH(wp, &env->watchpoints, entry) {
1359 b4051334 aliguori
        if (addr == wp->vaddr && len_mask == wp->len_mask
1360 6e140f28 aliguori
                && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
1361 a1d1bb31 aliguori
            cpu_watchpoint_remove_by_ref(env, wp);
1362 6658ffb8 pbrook
            return 0;
1363 6658ffb8 pbrook
        }
1364 6658ffb8 pbrook
    }
1365 a1d1bb31 aliguori
    return -ENOENT;
1366 6658ffb8 pbrook
}
1367 6658ffb8 pbrook
1368 a1d1bb31 aliguori
/* Remove a specific watchpoint by reference.  */
1369 a1d1bb31 aliguori
void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint)
1370 a1d1bb31 aliguori
{
1371 c0ce998e aliguori
    TAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
1372 7d03f82f edgar_igl
1373 a1d1bb31 aliguori
    tlb_flush_page(env, watchpoint->vaddr);
1374 a1d1bb31 aliguori
1375 a1d1bb31 aliguori
    qemu_free(watchpoint);
1376 a1d1bb31 aliguori
}
1377 a1d1bb31 aliguori
1378 a1d1bb31 aliguori
/* Remove all matching watchpoints.  */
1379 a1d1bb31 aliguori
void cpu_watchpoint_remove_all(CPUState *env, int mask)
1380 a1d1bb31 aliguori
{
1381 c0ce998e aliguori
    CPUWatchpoint *wp, *next;
1382 a1d1bb31 aliguori
1383 c0ce998e aliguori
    TAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
1384 a1d1bb31 aliguori
        if (wp->flags & mask)
1385 a1d1bb31 aliguori
            cpu_watchpoint_remove_by_ref(env, wp);
1386 c0ce998e aliguori
    }
1387 7d03f82f edgar_igl
}
1388 7d03f82f edgar_igl
1389 a1d1bb31 aliguori
/* Add a breakpoint.  */
1390 a1d1bb31 aliguori
int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
1391 a1d1bb31 aliguori
                          CPUBreakpoint **breakpoint)
1392 4c3a88a2 bellard
{
1393 1fddef4b bellard
#if defined(TARGET_HAS_ICE)
1394 c0ce998e aliguori
    CPUBreakpoint *bp;
1395 3b46e624 ths
1396 a1d1bb31 aliguori
    bp = qemu_malloc(sizeof(*bp));
1397 4c3a88a2 bellard
1398 a1d1bb31 aliguori
    bp->pc = pc;
1399 a1d1bb31 aliguori
    bp->flags = flags;
1400 a1d1bb31 aliguori
1401 2dc9f411 aliguori
    /* keep all GDB-injected breakpoints in front */
1402 c0ce998e aliguori
    if (flags & BP_GDB)
1403 c0ce998e aliguori
        TAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
1404 c0ce998e aliguori
    else
1405 c0ce998e aliguori
        TAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
1406 3b46e624 ths
1407 d720b93d bellard
    breakpoint_invalidate(env, pc);
1408 a1d1bb31 aliguori
1409 a1d1bb31 aliguori
    if (breakpoint)
1410 a1d1bb31 aliguori
        *breakpoint = bp;
1411 4c3a88a2 bellard
    return 0;
1412 4c3a88a2 bellard
#else
1413 a1d1bb31 aliguori
    return -ENOSYS;
1414 4c3a88a2 bellard
#endif
1415 4c3a88a2 bellard
}
1416 4c3a88a2 bellard
1417 a1d1bb31 aliguori
/* Remove a specific breakpoint.  */
1418 a1d1bb31 aliguori
int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags)
1419 a1d1bb31 aliguori
{
1420 7d03f82f edgar_igl
#if defined(TARGET_HAS_ICE)
1421 a1d1bb31 aliguori
    CPUBreakpoint *bp;
1422 a1d1bb31 aliguori
1423 c0ce998e aliguori
    TAILQ_FOREACH(bp, &env->breakpoints, entry) {
1424 a1d1bb31 aliguori
        if (bp->pc == pc && bp->flags == flags) {
1425 a1d1bb31 aliguori
            cpu_breakpoint_remove_by_ref(env, bp);
1426 a1d1bb31 aliguori
            return 0;
1427 a1d1bb31 aliguori
        }
1428 7d03f82f edgar_igl
    }
1429 a1d1bb31 aliguori
    return -ENOENT;
1430 a1d1bb31 aliguori
#else
1431 a1d1bb31 aliguori
    return -ENOSYS;
1432 7d03f82f edgar_igl
#endif
1433 7d03f82f edgar_igl
}
1434 7d03f82f edgar_igl
1435 a1d1bb31 aliguori
/* Remove a specific breakpoint by reference.  */
1436 a1d1bb31 aliguori
void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint)
1437 4c3a88a2 bellard
{
1438 1fddef4b bellard
#if defined(TARGET_HAS_ICE)
1439 c0ce998e aliguori
    TAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
1440 d720b93d bellard
1441 a1d1bb31 aliguori
    breakpoint_invalidate(env, breakpoint->pc);
1442 a1d1bb31 aliguori
1443 a1d1bb31 aliguori
    qemu_free(breakpoint);
1444 a1d1bb31 aliguori
#endif
1445 a1d1bb31 aliguori
}
1446 a1d1bb31 aliguori
1447 a1d1bb31 aliguori
/* Remove all matching breakpoints. */
1448 a1d1bb31 aliguori
void cpu_breakpoint_remove_all(CPUState *env, int mask)
1449 a1d1bb31 aliguori
{
1450 a1d1bb31 aliguori
#if defined(TARGET_HAS_ICE)
1451 c0ce998e aliguori
    CPUBreakpoint *bp, *next;
1452 a1d1bb31 aliguori
1453 c0ce998e aliguori
    TAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
1454 a1d1bb31 aliguori
        if (bp->flags & mask)
1455 a1d1bb31 aliguori
            cpu_breakpoint_remove_by_ref(env, bp);
1456 c0ce998e aliguori
    }
1457 4c3a88a2 bellard
#endif
1458 4c3a88a2 bellard
}
1459 4c3a88a2 bellard
1460 c33a346e bellard
/* enable or disable single step mode. EXCP_DEBUG is returned by the
1461 c33a346e bellard
   CPU loop after each instruction */
1462 c33a346e bellard
void cpu_single_step(CPUState *env, int enabled)
1463 c33a346e bellard
{
1464 1fddef4b bellard
#if defined(TARGET_HAS_ICE)
1465 c33a346e bellard
    if (env->singlestep_enabled != enabled) {
1466 c33a346e bellard
        env->singlestep_enabled = enabled;
1467 e22a25c9 aliguori
        if (kvm_enabled())
1468 e22a25c9 aliguori
            kvm_update_guest_debug(env, 0);
1469 e22a25c9 aliguori
        else {
1470 ccbb4d44 Stuart Brady
            /* must flush all the translated code to avoid inconsistencies */
1471 e22a25c9 aliguori
            /* XXX: only flush what is necessary */
1472 e22a25c9 aliguori
            tb_flush(env);
1473 e22a25c9 aliguori
        }
1474 c33a346e bellard
    }
1475 c33a346e bellard
#endif
1476 c33a346e bellard
}
1477 c33a346e bellard
1478 34865134 bellard
/* enable or disable low levels log */
1479 34865134 bellard
void cpu_set_log(int log_flags)
1480 34865134 bellard
{
1481 34865134 bellard
    loglevel = log_flags;
1482 34865134 bellard
    if (loglevel && !logfile) {
1483 11fcfab4 pbrook
        logfile = fopen(logfilename, log_append ? "a" : "w");
1484 34865134 bellard
        if (!logfile) {
1485 34865134 bellard
            perror(logfilename);
1486 34865134 bellard
            _exit(1);
1487 34865134 bellard
        }
1488 9fa3e853 bellard
#if !defined(CONFIG_SOFTMMU)
1489 9fa3e853 bellard
        /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1490 9fa3e853 bellard
        {
1491 b55266b5 blueswir1
            static char logfile_buf[4096];
1492 9fa3e853 bellard
            setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1493 9fa3e853 bellard
        }
1494 bf65f53f Filip Navara
#elif !defined(_WIN32)
1495 bf65f53f Filip Navara
        /* Win32 doesn't support line-buffering and requires size >= 2 */
1496 34865134 bellard
        setvbuf(logfile, NULL, _IOLBF, 0);
1497 9fa3e853 bellard
#endif
1498 e735b91c pbrook
        log_append = 1;
1499 e735b91c pbrook
    }
1500 e735b91c pbrook
    if (!loglevel && logfile) {
1501 e735b91c pbrook
        fclose(logfile);
1502 e735b91c pbrook
        logfile = NULL;
1503 34865134 bellard
    }
1504 34865134 bellard
}
1505 34865134 bellard
1506 34865134 bellard
void cpu_set_log_filename(const char *filename)
1507 34865134 bellard
{
1508 34865134 bellard
    logfilename = strdup(filename);
1509 e735b91c pbrook
    if (logfile) {
1510 e735b91c pbrook
        fclose(logfile);
1511 e735b91c pbrook
        logfile = NULL;
1512 e735b91c pbrook
    }
1513 e735b91c pbrook
    cpu_set_log(loglevel);
1514 34865134 bellard
}
1515 c33a346e bellard
1516 3098dba0 aurel32
static void cpu_unlink_tb(CPUState *env)
1517 ea041c0e bellard
{
1518 2f7bb878 Juan Quintela
#if defined(CONFIG_USE_NPTL)
1519 3098dba0 aurel32
    /* FIXME: TB unchaining isn't SMP safe.  For now just ignore the
1520 3098dba0 aurel32
       problem and hope the cpu will stop of its own accord.  For userspace
1521 3098dba0 aurel32
       emulation this often isn't actually as bad as it sounds.  Often
1522 3098dba0 aurel32
       signals are used primarily to interrupt blocking syscalls.  */
1523 3098dba0 aurel32
#else
1524 ea041c0e bellard
    TranslationBlock *tb;
1525 15a51156 aurel32
    static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
1526 59817ccb bellard
1527 3098dba0 aurel32
    tb = env->current_tb;
1528 3098dba0 aurel32
    /* if the cpu is currently executing code, we must unlink it and
1529 3098dba0 aurel32
       all the potentially executing TB */
1530 3098dba0 aurel32
    if (tb && !testandset(&interrupt_lock)) {
1531 3098dba0 aurel32
        env->current_tb = NULL;
1532 3098dba0 aurel32
        tb_reset_jump_recursive(tb);
1533 3098dba0 aurel32
        resetlock(&interrupt_lock);
1534 be214e6c aurel32
    }
1535 3098dba0 aurel32
#endif
1536 3098dba0 aurel32
}
1537 3098dba0 aurel32
1538 3098dba0 aurel32
/* mask must never be zero, except for A20 change call */
1539 3098dba0 aurel32
void cpu_interrupt(CPUState *env, int mask)
1540 3098dba0 aurel32
{
1541 3098dba0 aurel32
    int old_mask;
1542 be214e6c aurel32
1543 2e70f6ef pbrook
    old_mask = env->interrupt_request;
1544 68a79315 bellard
    env->interrupt_request |= mask;
1545 3098dba0 aurel32
1546 8edac960 aliguori
#ifndef CONFIG_USER_ONLY
1547 8edac960 aliguori
    /*
1548 8edac960 aliguori
     * If called from iothread context, wake the target cpu in
1549 8edac960 aliguori
     * case its halted.
1550 8edac960 aliguori
     */
1551 8edac960 aliguori
    if (!qemu_cpu_self(env)) {
1552 8edac960 aliguori
        qemu_cpu_kick(env);
1553 8edac960 aliguori
        return;
1554 8edac960 aliguori
    }
1555 8edac960 aliguori
#endif
1556 8edac960 aliguori
1557 2e70f6ef pbrook
    if (use_icount) {
1558 266910c4 pbrook
        env->icount_decr.u16.high = 0xffff;
1559 2e70f6ef pbrook
#ifndef CONFIG_USER_ONLY
1560 2e70f6ef pbrook
        if (!can_do_io(env)
1561 be214e6c aurel32
            && (mask & ~old_mask) != 0) {
1562 2e70f6ef pbrook
            cpu_abort(env, "Raised interrupt while not in I/O function");
1563 2e70f6ef pbrook
        }
1564 2e70f6ef pbrook
#endif
1565 2e70f6ef pbrook
    } else {
1566 3098dba0 aurel32
        cpu_unlink_tb(env);
1567 ea041c0e bellard
    }
1568 ea041c0e bellard
}
1569 ea041c0e bellard
1570 b54ad049 bellard
void cpu_reset_interrupt(CPUState *env, int mask)
1571 b54ad049 bellard
{
1572 b54ad049 bellard
    env->interrupt_request &= ~mask;
1573 b54ad049 bellard
}
1574 b54ad049 bellard
1575 3098dba0 aurel32
void cpu_exit(CPUState *env)
1576 3098dba0 aurel32
{
1577 3098dba0 aurel32
    env->exit_request = 1;
1578 3098dba0 aurel32
    cpu_unlink_tb(env);
1579 3098dba0 aurel32
}
1580 3098dba0 aurel32
1581 c7cd6a37 blueswir1
const CPULogItem cpu_log_items[] = {
1582 5fafdf24 ths
    { CPU_LOG_TB_OUT_ASM, "out_asm",
1583 f193c797 bellard
      "show generated host assembly code for each compiled TB" },
1584 f193c797 bellard
    { CPU_LOG_TB_IN_ASM, "in_asm",
1585 f193c797 bellard
      "show target assembly code for each compiled TB" },
1586 5fafdf24 ths
    { CPU_LOG_TB_OP, "op",
1587 57fec1fe bellard
      "show micro ops for each compiled TB" },
1588 f193c797 bellard
    { CPU_LOG_TB_OP_OPT, "op_opt",
1589 e01a1157 blueswir1
      "show micro ops "
1590 e01a1157 blueswir1
#ifdef TARGET_I386
1591 e01a1157 blueswir1
      "before eflags optimization and "
1592 f193c797 bellard
#endif
1593 e01a1157 blueswir1
      "after liveness analysis" },
1594 f193c797 bellard
    { CPU_LOG_INT, "int",
1595 f193c797 bellard
      "show interrupts/exceptions in short format" },
1596 f193c797 bellard
    { CPU_LOG_EXEC, "exec",
1597 f193c797 bellard
      "show trace before each executed TB (lots of logs)" },
1598 9fddaa0c bellard
    { CPU_LOG_TB_CPU, "cpu",
1599 e91c8a77 ths
      "show CPU state before block translation" },
1600 f193c797 bellard
#ifdef TARGET_I386
1601 f193c797 bellard
    { CPU_LOG_PCALL, "pcall",
1602 f193c797 bellard
      "show protected mode far calls/returns/exceptions" },
1603 eca1bdf4 aliguori
    { CPU_LOG_RESET, "cpu_reset",
1604 eca1bdf4 aliguori
      "show CPU state before CPU resets" },
1605 f193c797 bellard
#endif
1606 8e3a9fd2 bellard
#ifdef DEBUG_IOPORT
1607 fd872598 bellard
    { CPU_LOG_IOPORT, "ioport",
1608 fd872598 bellard
      "show all i/o ports accesses" },
1609 8e3a9fd2 bellard
#endif
1610 f193c797 bellard
    { 0, NULL, NULL },
1611 f193c797 bellard
};
1612 f193c797 bellard
1613 f193c797 bellard
static int cmp1(const char *s1, int n, const char *s2)
1614 f193c797 bellard
{
1615 f193c797 bellard
    if (strlen(s2) != n)
1616 f193c797 bellard
        return 0;
1617 f193c797 bellard
    return memcmp(s1, s2, n) == 0;
1618 f193c797 bellard
}
1619 3b46e624 ths
1620 f193c797 bellard
/* takes a comma separated list of log masks. Return 0 if error. */
1621 f193c797 bellard
int cpu_str_to_log_mask(const char *str)
1622 f193c797 bellard
{
1623 c7cd6a37 blueswir1
    const CPULogItem *item;
1624 f193c797 bellard
    int mask;
1625 f193c797 bellard
    const char *p, *p1;
1626 f193c797 bellard
1627 f193c797 bellard
    p = str;
1628 f193c797 bellard
    mask = 0;
1629 f193c797 bellard
    for(;;) {
1630 f193c797 bellard
        p1 = strchr(p, ',');
1631 f193c797 bellard
        if (!p1)
1632 f193c797 bellard
            p1 = p + strlen(p);
1633 8e3a9fd2 bellard
        if(cmp1(p,p1-p,"all")) {
1634 8e3a9fd2 bellard
                for(item = cpu_log_items; item->mask != 0; item++) {
1635 8e3a9fd2 bellard
                        mask |= item->mask;
1636 8e3a9fd2 bellard
                }
1637 8e3a9fd2 bellard
        } else {
1638 f193c797 bellard
        for(item = cpu_log_items; item->mask != 0; item++) {
1639 f193c797 bellard
            if (cmp1(p, p1 - p, item->name))
1640 f193c797 bellard
                goto found;
1641 f193c797 bellard
        }
1642 f193c797 bellard
        return 0;
1643 8e3a9fd2 bellard
        }
1644 f193c797 bellard
    found:
1645 f193c797 bellard
        mask |= item->mask;
1646 f193c797 bellard
        if (*p1 != ',')
1647 f193c797 bellard
            break;
1648 f193c797 bellard
        p = p1 + 1;
1649 f193c797 bellard
    }
1650 f193c797 bellard
    return mask;
1651 f193c797 bellard
}
1652 ea041c0e bellard
1653 7501267e bellard
void cpu_abort(CPUState *env, const char *fmt, ...)
1654 7501267e bellard
{
1655 7501267e bellard
    va_list ap;
1656 493ae1f0 pbrook
    va_list ap2;
1657 7501267e bellard
1658 7501267e bellard
    va_start(ap, fmt);
1659 493ae1f0 pbrook
    va_copy(ap2, ap);
1660 7501267e bellard
    fprintf(stderr, "qemu: fatal: ");
1661 7501267e bellard
    vfprintf(stderr, fmt, ap);
1662 7501267e bellard
    fprintf(stderr, "\n");
1663 7501267e bellard
#ifdef TARGET_I386
1664 7fe48483 bellard
    cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1665 7fe48483 bellard
#else
1666 7fe48483 bellard
    cpu_dump_state(env, stderr, fprintf, 0);
1667 7501267e bellard
#endif
1668 93fcfe39 aliguori
    if (qemu_log_enabled()) {
1669 93fcfe39 aliguori
        qemu_log("qemu: fatal: ");
1670 93fcfe39 aliguori
        qemu_log_vprintf(fmt, ap2);
1671 93fcfe39 aliguori
        qemu_log("\n");
1672 f9373291 j_mayer
#ifdef TARGET_I386
1673 93fcfe39 aliguori
        log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
1674 f9373291 j_mayer
#else
1675 93fcfe39 aliguori
        log_cpu_state(env, 0);
1676 f9373291 j_mayer
#endif
1677 31b1a7b4 aliguori
        qemu_log_flush();
1678 93fcfe39 aliguori
        qemu_log_close();
1679 924edcae balrog
    }
1680 493ae1f0 pbrook
    va_end(ap2);
1681 f9373291 j_mayer
    va_end(ap);
1682 7501267e bellard
    abort();
1683 7501267e bellard
}
1684 7501267e bellard
1685 c5be9f08 ths
CPUState *cpu_copy(CPUState *env)
1686 c5be9f08 ths
{
1687 01ba9816 ths
    CPUState *new_env = cpu_init(env->cpu_model_str);
1688 c5be9f08 ths
    CPUState *next_cpu = new_env->next_cpu;
1689 c5be9f08 ths
    int cpu_index = new_env->cpu_index;
1690 5a38f081 aliguori
#if defined(TARGET_HAS_ICE)
1691 5a38f081 aliguori
    CPUBreakpoint *bp;
1692 5a38f081 aliguori
    CPUWatchpoint *wp;
1693 5a38f081 aliguori
#endif
1694 5a38f081 aliguori
1695 c5be9f08 ths
    memcpy(new_env, env, sizeof(CPUState));
1696 5a38f081 aliguori
1697 5a38f081 aliguori
    /* Preserve chaining and index. */
1698 c5be9f08 ths
    new_env->next_cpu = next_cpu;
1699 c5be9f08 ths
    new_env->cpu_index = cpu_index;
1700 5a38f081 aliguori
1701 5a38f081 aliguori
    /* Clone all break/watchpoints.
1702 5a38f081 aliguori
       Note: Once we support ptrace with hw-debug register access, make sure
1703 5a38f081 aliguori
       BP_CPU break/watchpoints are handled correctly on clone. */
1704 5a38f081 aliguori
    TAILQ_INIT(&env->breakpoints);
1705 5a38f081 aliguori
    TAILQ_INIT(&env->watchpoints);
1706 5a38f081 aliguori
#if defined(TARGET_HAS_ICE)
1707 5a38f081 aliguori
    TAILQ_FOREACH(bp, &env->breakpoints, entry) {
1708 5a38f081 aliguori
        cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
1709 5a38f081 aliguori
    }
1710 5a38f081 aliguori
    TAILQ_FOREACH(wp, &env->watchpoints, entry) {
1711 5a38f081 aliguori
        cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
1712 5a38f081 aliguori
                              wp->flags, NULL);
1713 5a38f081 aliguori
    }
1714 5a38f081 aliguori
#endif
1715 5a38f081 aliguori
1716 c5be9f08 ths
    return new_env;
1717 c5be9f08 ths
}
1718 c5be9f08 ths
1719 0124311e bellard
#if !defined(CONFIG_USER_ONLY)
1720 0124311e bellard
1721 5c751e99 edgar_igl
static inline void tlb_flush_jmp_cache(CPUState *env, target_ulong addr)
1722 5c751e99 edgar_igl
{
1723 5c751e99 edgar_igl
    unsigned int i;
1724 5c751e99 edgar_igl
1725 5c751e99 edgar_igl
    /* Discard jump cache entries for any tb which might potentially
1726 5c751e99 edgar_igl
       overlap the flushed page.  */
1727 5c751e99 edgar_igl
    i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
1728 5c751e99 edgar_igl
    memset (&env->tb_jmp_cache[i], 0, 
1729 5c751e99 edgar_igl
            TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
1730 5c751e99 edgar_igl
1731 5c751e99 edgar_igl
    i = tb_jmp_cache_hash_page(addr);
1732 5c751e99 edgar_igl
    memset (&env->tb_jmp_cache[i], 0, 
1733 5c751e99 edgar_igl
            TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
1734 5c751e99 edgar_igl
}
1735 5c751e99 edgar_igl
1736 08738984 Igor Kovalenko
static CPUTLBEntry s_cputlb_empty_entry = {
1737 08738984 Igor Kovalenko
    .addr_read  = -1,
1738 08738984 Igor Kovalenko
    .addr_write = -1,
1739 08738984 Igor Kovalenko
    .addr_code  = -1,
1740 08738984 Igor Kovalenko
    .addend     = -1,
1741 08738984 Igor Kovalenko
};
1742 08738984 Igor Kovalenko
1743 ee8b7021 bellard
/* NOTE: if flush_global is true, also flush global entries (not
1744 ee8b7021 bellard
   implemented yet) */
1745 ee8b7021 bellard
void tlb_flush(CPUState *env, int flush_global)
1746 33417e70 bellard
{
1747 33417e70 bellard
    int i;
1748 0124311e bellard
1749 9fa3e853 bellard
#if defined(DEBUG_TLB)
1750 9fa3e853 bellard
    printf("tlb_flush:\n");
1751 9fa3e853 bellard
#endif
1752 0124311e bellard
    /* must reset current TB so that interrupts cannot modify the
1753 0124311e bellard
       links while we are modifying them */
1754 0124311e bellard
    env->current_tb = NULL;
1755 0124311e bellard
1756 33417e70 bellard
    for(i = 0; i < CPU_TLB_SIZE; i++) {
1757 cfde4bd9 Isaku Yamahata
        int mmu_idx;
1758 cfde4bd9 Isaku Yamahata
        for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1759 08738984 Igor Kovalenko
            env->tlb_table[mmu_idx][i] = s_cputlb_empty_entry;
1760 cfde4bd9 Isaku Yamahata
        }
1761 33417e70 bellard
    }
1762 9fa3e853 bellard
1763 8a40a180 bellard
    memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
1764 9fa3e853 bellard
1765 e3db7226 bellard
    tlb_flush_count++;
1766 33417e70 bellard
}
1767 33417e70 bellard
1768 274da6b2 bellard
static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
1769 61382a50 bellard
{
1770 5fafdf24 ths
    if (addr == (tlb_entry->addr_read &
1771 84b7b8e7 bellard
                 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1772 5fafdf24 ths
        addr == (tlb_entry->addr_write &
1773 84b7b8e7 bellard
                 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1774 5fafdf24 ths
        addr == (tlb_entry->addr_code &
1775 84b7b8e7 bellard
                 (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1776 08738984 Igor Kovalenko
        *tlb_entry = s_cputlb_empty_entry;
1777 84b7b8e7 bellard
    }
1778 61382a50 bellard
}
1779 61382a50 bellard
1780 2e12669a bellard
void tlb_flush_page(CPUState *env, target_ulong addr)
1781 33417e70 bellard
{
1782 8a40a180 bellard
    int i;
1783 cfde4bd9 Isaku Yamahata
    int mmu_idx;
1784 0124311e bellard
1785 9fa3e853 bellard
#if defined(DEBUG_TLB)
1786 108c49b8 bellard
    printf("tlb_flush_page: " TARGET_FMT_lx "\n", addr);
1787 9fa3e853 bellard
#endif
1788 0124311e bellard
    /* must reset current TB so that interrupts cannot modify the
1789 0124311e bellard
       links while we are modifying them */
1790 0124311e bellard
    env->current_tb = NULL;
1791 61382a50 bellard
1792 61382a50 bellard
    addr &= TARGET_PAGE_MASK;
1793 61382a50 bellard
    i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1794 cfde4bd9 Isaku Yamahata
    for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++)
1795 cfde4bd9 Isaku Yamahata
        tlb_flush_entry(&env->tlb_table[mmu_idx][i], addr);
1796 0124311e bellard
1797 5c751e99 edgar_igl
    tlb_flush_jmp_cache(env, addr);
1798 9fa3e853 bellard
}
1799 9fa3e853 bellard
1800 9fa3e853 bellard
/* update the TLBs so that writes to code in the virtual page 'addr'
1801 9fa3e853 bellard
   can be detected */
1802 6a00d601 bellard
static void tlb_protect_code(ram_addr_t ram_addr)
1803 9fa3e853 bellard
{
1804 5fafdf24 ths
    cpu_physical_memory_reset_dirty(ram_addr,
1805 6a00d601 bellard
                                    ram_addr + TARGET_PAGE_SIZE,
1806 6a00d601 bellard
                                    CODE_DIRTY_FLAG);
1807 9fa3e853 bellard
}
1808 9fa3e853 bellard
1809 9fa3e853 bellard
/* update the TLB so that writes in physical page 'phys_addr' are no longer
1810 3a7d929e bellard
   tested for self modifying code */
1811 5fafdf24 ths
static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
1812 3a7d929e bellard
                                    target_ulong vaddr)
1813 9fa3e853 bellard
{
1814 3a7d929e bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] |= CODE_DIRTY_FLAG;
1815 1ccde1cb bellard
}
1816 1ccde1cb bellard
1817 5fafdf24 ths
static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
1818 1ccde1cb bellard
                                         unsigned long start, unsigned long length)
1819 1ccde1cb bellard
{
1820 1ccde1cb bellard
    unsigned long addr;
1821 84b7b8e7 bellard
    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1822 84b7b8e7 bellard
        addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
1823 1ccde1cb bellard
        if ((addr - start) < length) {
1824 0f459d16 pbrook
            tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
1825 1ccde1cb bellard
        }
1826 1ccde1cb bellard
    }
1827 1ccde1cb bellard
}
1828 1ccde1cb bellard
1829 5579c7f3 pbrook
/* Note: start and end must be within the same ram block.  */
1830 3a7d929e bellard
void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
1831 0a962c02 bellard
                                     int dirty_flags)
1832 1ccde1cb bellard
{
1833 1ccde1cb bellard
    CPUState *env;
1834 4f2ac237 bellard
    unsigned long length, start1;
1835 0a962c02 bellard
    int i, mask, len;
1836 0a962c02 bellard
    uint8_t *p;
1837 1ccde1cb bellard
1838 1ccde1cb bellard
    start &= TARGET_PAGE_MASK;
1839 1ccde1cb bellard
    end = TARGET_PAGE_ALIGN(end);
1840 1ccde1cb bellard
1841 1ccde1cb bellard
    length = end - start;
1842 1ccde1cb bellard
    if (length == 0)
1843 1ccde1cb bellard
        return;
1844 0a962c02 bellard
    len = length >> TARGET_PAGE_BITS;
1845 f23db169 bellard
    mask = ~dirty_flags;
1846 f23db169 bellard
    p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
1847 f23db169 bellard
    for(i = 0; i < len; i++)
1848 f23db169 bellard
        p[i] &= mask;
1849 f23db169 bellard
1850 1ccde1cb bellard
    /* we modify the TLB cache so that the dirty bit will be set again
1851 1ccde1cb bellard
       when accessing the range */
1852 5579c7f3 pbrook
    start1 = (unsigned long)qemu_get_ram_ptr(start);
1853 5579c7f3 pbrook
    /* Chek that we don't span multiple blocks - this breaks the
1854 5579c7f3 pbrook
       address comparisons below.  */
1855 5579c7f3 pbrook
    if ((unsigned long)qemu_get_ram_ptr(end - 1) - start1
1856 5579c7f3 pbrook
            != (end - 1) - start) {
1857 5579c7f3 pbrook
        abort();
1858 5579c7f3 pbrook
    }
1859 5579c7f3 pbrook
1860 6a00d601 bellard
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
1861 cfde4bd9 Isaku Yamahata
        int mmu_idx;
1862 cfde4bd9 Isaku Yamahata
        for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1863 cfde4bd9 Isaku Yamahata
            for(i = 0; i < CPU_TLB_SIZE; i++)
1864 cfde4bd9 Isaku Yamahata
                tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
1865 cfde4bd9 Isaku Yamahata
                                      start1, length);
1866 cfde4bd9 Isaku Yamahata
        }
1867 6a00d601 bellard
    }
1868 1ccde1cb bellard
}
1869 1ccde1cb bellard
1870 74576198 aliguori
int cpu_physical_memory_set_dirty_tracking(int enable)
1871 74576198 aliguori
{
1872 74576198 aliguori
    in_migration = enable;
1873 b0a46a33 Jan Kiszka
    if (kvm_enabled()) {
1874 b0a46a33 Jan Kiszka
        return kvm_set_migration_log(enable);
1875 b0a46a33 Jan Kiszka
    }
1876 74576198 aliguori
    return 0;
1877 74576198 aliguori
}
1878 74576198 aliguori
1879 74576198 aliguori
int cpu_physical_memory_get_dirty_tracking(void)
1880 74576198 aliguori
{
1881 74576198 aliguori
    return in_migration;
1882 74576198 aliguori
}
1883 74576198 aliguori
1884 151f7749 Jan Kiszka
int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
1885 151f7749 Jan Kiszka
                                   target_phys_addr_t end_addr)
1886 2bec46dc aliguori
{
1887 151f7749 Jan Kiszka
    int ret = 0;
1888 151f7749 Jan Kiszka
1889 2bec46dc aliguori
    if (kvm_enabled())
1890 151f7749 Jan Kiszka
        ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
1891 151f7749 Jan Kiszka
    return ret;
1892 2bec46dc aliguori
}
1893 2bec46dc aliguori
1894 3a7d929e bellard
static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1895 3a7d929e bellard
{
1896 3a7d929e bellard
    ram_addr_t ram_addr;
1897 5579c7f3 pbrook
    void *p;
1898 3a7d929e bellard
1899 84b7b8e7 bellard
    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1900 5579c7f3 pbrook
        p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
1901 5579c7f3 pbrook
            + tlb_entry->addend);
1902 5579c7f3 pbrook
        ram_addr = qemu_ram_addr_from_host(p);
1903 3a7d929e bellard
        if (!cpu_physical_memory_is_dirty(ram_addr)) {
1904 0f459d16 pbrook
            tlb_entry->addr_write |= TLB_NOTDIRTY;
1905 3a7d929e bellard
        }
1906 3a7d929e bellard
    }
1907 3a7d929e bellard
}
1908 3a7d929e bellard
1909 3a7d929e bellard
/* update the TLB according to the current state of the dirty bits */
1910 3a7d929e bellard
void cpu_tlb_update_dirty(CPUState *env)
1911 3a7d929e bellard
{
1912 3a7d929e bellard
    int i;
1913 cfde4bd9 Isaku Yamahata
    int mmu_idx;
1914 cfde4bd9 Isaku Yamahata
    for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1915 cfde4bd9 Isaku Yamahata
        for(i = 0; i < CPU_TLB_SIZE; i++)
1916 cfde4bd9 Isaku Yamahata
            tlb_update_dirty(&env->tlb_table[mmu_idx][i]);
1917 cfde4bd9 Isaku Yamahata
    }
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 cfde4bd9 Isaku Yamahata
    int mmu_idx;
1932 1ccde1cb bellard
1933 0f459d16 pbrook
    vaddr &= TARGET_PAGE_MASK;
1934 1ccde1cb bellard
    i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1935 cfde4bd9 Isaku Yamahata
    for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++)
1936 cfde4bd9 Isaku Yamahata
        tlb_set_dirty1(&env->tlb_table[mmu_idx][i], vaddr);
1937 9fa3e853 bellard
}
1938 9fa3e853 bellard
1939 59817ccb bellard
/* add a new TLB entry. At most one entry for a given virtual address
1940 59817ccb bellard
   is permitted. Return 0 if OK or 2 if the page could not be mapped
1941 59817ccb bellard
   (can only happen in non SOFTMMU mode for I/O pages or pages
1942 59817ccb bellard
   conflicting with the host address space). */
1943 5fafdf24 ths
int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
1944 5fafdf24 ths
                      target_phys_addr_t paddr, int prot,
1945 6ebbf390 j_mayer
                      int mmu_idx, int is_softmmu)
1946 9fa3e853 bellard
{
1947 92e873b9 bellard
    PhysPageDesc *p;
1948 4f2ac237 bellard
    unsigned long pd;
1949 9fa3e853 bellard
    unsigned int index;
1950 4f2ac237 bellard
    target_ulong address;
1951 0f459d16 pbrook
    target_ulong code_address;
1952 108c49b8 bellard
    target_phys_addr_t addend;
1953 9fa3e853 bellard
    int ret;
1954 84b7b8e7 bellard
    CPUTLBEntry *te;
1955 a1d1bb31 aliguori
    CPUWatchpoint *wp;
1956 0f459d16 pbrook
    target_phys_addr_t iotlb;
1957 9fa3e853 bellard
1958 92e873b9 bellard
    p = phys_page_find(paddr >> TARGET_PAGE_BITS);
1959 9fa3e853 bellard
    if (!p) {
1960 9fa3e853 bellard
        pd = IO_MEM_UNASSIGNED;
1961 9fa3e853 bellard
    } else {
1962 9fa3e853 bellard
        pd = p->phys_offset;
1963 9fa3e853 bellard
    }
1964 9fa3e853 bellard
#if defined(DEBUG_TLB)
1965 6ebbf390 j_mayer
    printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x idx=%d smmu=%d pd=0x%08lx\n",
1966 6ebbf390 j_mayer
           vaddr, (int)paddr, prot, mmu_idx, is_softmmu, pd);
1967 9fa3e853 bellard
#endif
1968 9fa3e853 bellard
1969 9fa3e853 bellard
    ret = 0;
1970 0f459d16 pbrook
    address = vaddr;
1971 0f459d16 pbrook
    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
1972 0f459d16 pbrook
        /* IO memory case (romd handled later) */
1973 0f459d16 pbrook
        address |= TLB_MMIO;
1974 0f459d16 pbrook
    }
1975 5579c7f3 pbrook
    addend = (unsigned long)qemu_get_ram_ptr(pd & TARGET_PAGE_MASK);
1976 0f459d16 pbrook
    if ((pd & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
1977 0f459d16 pbrook
        /* Normal RAM.  */
1978 0f459d16 pbrook
        iotlb = pd & TARGET_PAGE_MASK;
1979 0f459d16 pbrook
        if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM)
1980 0f459d16 pbrook
            iotlb |= IO_MEM_NOTDIRTY;
1981 0f459d16 pbrook
        else
1982 0f459d16 pbrook
            iotlb |= IO_MEM_ROM;
1983 0f459d16 pbrook
    } else {
1984 ccbb4d44 Stuart Brady
        /* IO handlers are currently passed a physical address.
1985 0f459d16 pbrook
           It would be nice to pass an offset from the base address
1986 0f459d16 pbrook
           of that region.  This would avoid having to special case RAM,
1987 0f459d16 pbrook
           and avoid full address decoding in every device.
1988 0f459d16 pbrook
           We can't use the high bits of pd for this because
1989 0f459d16 pbrook
           IO_MEM_ROMD uses these as a ram address.  */
1990 8da3ff18 pbrook
        iotlb = (pd & ~TARGET_PAGE_MASK);
1991 8da3ff18 pbrook
        if (p) {
1992 8da3ff18 pbrook
            iotlb += p->region_offset;
1993 8da3ff18 pbrook
        } else {
1994 8da3ff18 pbrook
            iotlb += paddr;
1995 8da3ff18 pbrook
        }
1996 0f459d16 pbrook
    }
1997 0f459d16 pbrook
1998 0f459d16 pbrook
    code_address = address;
1999 0f459d16 pbrook
    /* Make accesses to pages with watchpoints go via the
2000 0f459d16 pbrook
       watchpoint trap routines.  */
2001 c0ce998e aliguori
    TAILQ_FOREACH(wp, &env->watchpoints, entry) {
2002 a1d1bb31 aliguori
        if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) {
2003 0f459d16 pbrook
            iotlb = io_mem_watch + paddr;
2004 0f459d16 pbrook
            /* TODO: The memory case can be optimized by not trapping
2005 0f459d16 pbrook
               reads of pages with a write breakpoint.  */
2006 0f459d16 pbrook
            address |= TLB_MMIO;
2007 6658ffb8 pbrook
        }
2008 0f459d16 pbrook
    }
2009 d79acba4 balrog
2010 0f459d16 pbrook
    index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
2011 0f459d16 pbrook
    env->iotlb[mmu_idx][index] = iotlb - vaddr;
2012 0f459d16 pbrook
    te = &env->tlb_table[mmu_idx][index];
2013 0f459d16 pbrook
    te->addend = addend - vaddr;
2014 0f459d16 pbrook
    if (prot & PAGE_READ) {
2015 0f459d16 pbrook
        te->addr_read = address;
2016 0f459d16 pbrook
    } else {
2017 0f459d16 pbrook
        te->addr_read = -1;
2018 0f459d16 pbrook
    }
2019 5c751e99 edgar_igl
2020 0f459d16 pbrook
    if (prot & PAGE_EXEC) {
2021 0f459d16 pbrook
        te->addr_code = code_address;
2022 0f459d16 pbrook
    } else {
2023 0f459d16 pbrook
        te->addr_code = -1;
2024 0f459d16 pbrook
    }
2025 0f459d16 pbrook
    if (prot & PAGE_WRITE) {
2026 0f459d16 pbrook
        if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM ||
2027 0f459d16 pbrook
            (pd & IO_MEM_ROMD)) {
2028 0f459d16 pbrook
            /* Write access calls the I/O callback.  */
2029 0f459d16 pbrook
            te->addr_write = address | TLB_MMIO;
2030 0f459d16 pbrook
        } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
2031 0f459d16 pbrook
                   !cpu_physical_memory_is_dirty(pd)) {
2032 0f459d16 pbrook
            te->addr_write = address | TLB_NOTDIRTY;
2033 9fa3e853 bellard
        } else {
2034 0f459d16 pbrook
            te->addr_write = address;
2035 9fa3e853 bellard
        }
2036 0f459d16 pbrook
    } else {
2037 0f459d16 pbrook
        te->addr_write = -1;
2038 9fa3e853 bellard
    }
2039 9fa3e853 bellard
    return ret;
2040 9fa3e853 bellard
}
2041 9fa3e853 bellard
2042 0124311e bellard
#else
2043 0124311e bellard
2044 ee8b7021 bellard
void tlb_flush(CPUState *env, int flush_global)
2045 0124311e bellard
{
2046 0124311e bellard
}
2047 0124311e bellard
2048 2e12669a bellard
void tlb_flush_page(CPUState *env, target_ulong addr)
2049 0124311e bellard
{
2050 0124311e bellard
}
2051 0124311e bellard
2052 5fafdf24 ths
int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
2053 5fafdf24 ths
                      target_phys_addr_t paddr, int prot,
2054 6ebbf390 j_mayer
                      int mmu_idx, int is_softmmu)
2055 9fa3e853 bellard
{
2056 9fa3e853 bellard
    return 0;
2057 9fa3e853 bellard
}
2058 0124311e bellard
2059 edf8e2af Mika Westerberg
/*
2060 edf8e2af Mika Westerberg
 * Walks guest process memory "regions" one by one
2061 edf8e2af Mika Westerberg
 * and calls callback function 'fn' for each region.
2062 edf8e2af Mika Westerberg
 */
2063 edf8e2af Mika Westerberg
int walk_memory_regions(void *priv,
2064 edf8e2af Mika Westerberg
    int (*fn)(void *, unsigned long, unsigned long, unsigned long))
2065 33417e70 bellard
{
2066 9fa3e853 bellard
    unsigned long start, end;
2067 edf8e2af Mika Westerberg
    PageDesc *p = NULL;
2068 9fa3e853 bellard
    int i, j, prot, prot1;
2069 edf8e2af Mika Westerberg
    int rc = 0;
2070 33417e70 bellard
2071 edf8e2af Mika Westerberg
    start = end = -1;
2072 9fa3e853 bellard
    prot = 0;
2073 edf8e2af Mika Westerberg
2074 edf8e2af Mika Westerberg
    for (i = 0; i <= L1_SIZE; i++) {
2075 edf8e2af Mika Westerberg
        p = (i < L1_SIZE) ? l1_map[i] : NULL;
2076 edf8e2af Mika Westerberg
        for (j = 0; j < L2_SIZE; j++) {
2077 edf8e2af Mika Westerberg
            prot1 = (p == NULL) ? 0 : p[j].flags;
2078 edf8e2af Mika Westerberg
            /*
2079 edf8e2af Mika Westerberg
             * "region" is one continuous chunk of memory
2080 edf8e2af Mika Westerberg
             * that has same protection flags set.
2081 edf8e2af Mika Westerberg
             */
2082 9fa3e853 bellard
            if (prot1 != prot) {
2083 9fa3e853 bellard
                end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
2084 9fa3e853 bellard
                if (start != -1) {
2085 edf8e2af Mika Westerberg
                    rc = (*fn)(priv, start, end, prot);
2086 edf8e2af Mika Westerberg
                    /* callback can stop iteration by returning != 0 */
2087 edf8e2af Mika Westerberg
                    if (rc != 0)
2088 edf8e2af Mika Westerberg
                        return (rc);
2089 9fa3e853 bellard
                }
2090 9fa3e853 bellard
                if (prot1 != 0)
2091 9fa3e853 bellard
                    start = end;
2092 9fa3e853 bellard
                else
2093 9fa3e853 bellard
                    start = -1;
2094 9fa3e853 bellard
                prot = prot1;
2095 9fa3e853 bellard
            }
2096 edf8e2af Mika Westerberg
            if (p == NULL)
2097 9fa3e853 bellard
                break;
2098 9fa3e853 bellard
        }
2099 33417e70 bellard
    }
2100 edf8e2af Mika Westerberg
    return (rc);
2101 edf8e2af Mika Westerberg
}
2102 edf8e2af Mika Westerberg
2103 edf8e2af Mika Westerberg
static int dump_region(void *priv, unsigned long start,
2104 edf8e2af Mika Westerberg
    unsigned long end, unsigned long prot)
2105 edf8e2af Mika Westerberg
{
2106 edf8e2af Mika Westerberg
    FILE *f = (FILE *)priv;
2107 edf8e2af Mika Westerberg
2108 edf8e2af Mika Westerberg
    (void) fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
2109 edf8e2af Mika Westerberg
        start, end, end - start,
2110 edf8e2af Mika Westerberg
        ((prot & PAGE_READ) ? 'r' : '-'),
2111 edf8e2af Mika Westerberg
        ((prot & PAGE_WRITE) ? 'w' : '-'),
2112 edf8e2af Mika Westerberg
        ((prot & PAGE_EXEC) ? 'x' : '-'));
2113 edf8e2af Mika Westerberg
2114 edf8e2af Mika Westerberg
    return (0);
2115 edf8e2af Mika Westerberg
}
2116 edf8e2af Mika Westerberg
2117 edf8e2af Mika Westerberg
/* dump memory mappings */
2118 edf8e2af Mika Westerberg
void page_dump(FILE *f)
2119 edf8e2af Mika Westerberg
{
2120 edf8e2af Mika Westerberg
    (void) fprintf(f, "%-8s %-8s %-8s %s\n",
2121 edf8e2af Mika Westerberg
            "start", "end", "size", "prot");
2122 edf8e2af Mika Westerberg
    walk_memory_regions(f, dump_region);
2123 33417e70 bellard
}
2124 33417e70 bellard
2125 53a5960a pbrook
int page_get_flags(target_ulong address)
2126 33417e70 bellard
{
2127 9fa3e853 bellard
    PageDesc *p;
2128 9fa3e853 bellard
2129 9fa3e853 bellard
    p = page_find(address >> TARGET_PAGE_BITS);
2130 33417e70 bellard
    if (!p)
2131 9fa3e853 bellard
        return 0;
2132 9fa3e853 bellard
    return p->flags;
2133 9fa3e853 bellard
}
2134 9fa3e853 bellard
2135 9fa3e853 bellard
/* modify the flags of a page and invalidate the code if
2136 ccbb4d44 Stuart Brady
   necessary. The flag PAGE_WRITE_ORG is positioned automatically
2137 9fa3e853 bellard
   depending on PAGE_WRITE */
2138 53a5960a pbrook
void page_set_flags(target_ulong start, target_ulong end, int flags)
2139 9fa3e853 bellard
{
2140 9fa3e853 bellard
    PageDesc *p;
2141 53a5960a pbrook
    target_ulong addr;
2142 9fa3e853 bellard
2143 c8a706fe pbrook
    /* mmap_lock should already be held.  */
2144 9fa3e853 bellard
    start = start & TARGET_PAGE_MASK;
2145 9fa3e853 bellard
    end = TARGET_PAGE_ALIGN(end);
2146 9fa3e853 bellard
    if (flags & PAGE_WRITE)
2147 9fa3e853 bellard
        flags |= PAGE_WRITE_ORG;
2148 9fa3e853 bellard
    for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2149 9fa3e853 bellard
        p = page_find_alloc(addr >> TARGET_PAGE_BITS);
2150 17e2377a pbrook
        /* We may be called for host regions that are outside guest
2151 17e2377a pbrook
           address space.  */
2152 17e2377a pbrook
        if (!p)
2153 17e2377a pbrook
            return;
2154 9fa3e853 bellard
        /* if the write protection is set, then we invalidate the code
2155 9fa3e853 bellard
           inside */
2156 5fafdf24 ths
        if (!(p->flags & PAGE_WRITE) &&
2157 9fa3e853 bellard
            (flags & PAGE_WRITE) &&
2158 9fa3e853 bellard
            p->first_tb) {
2159 d720b93d bellard
            tb_invalidate_phys_page(addr, 0, NULL);
2160 9fa3e853 bellard
        }
2161 9fa3e853 bellard
        p->flags = flags;
2162 9fa3e853 bellard
    }
2163 33417e70 bellard
}
2164 33417e70 bellard
2165 3d97b40b ths
int page_check_range(target_ulong start, target_ulong len, int flags)
2166 3d97b40b ths
{
2167 3d97b40b ths
    PageDesc *p;
2168 3d97b40b ths
    target_ulong end;
2169 3d97b40b ths
    target_ulong addr;
2170 3d97b40b ths
2171 55f280c9 balrog
    if (start + len < start)
2172 55f280c9 balrog
        /* we've wrapped around */
2173 55f280c9 balrog
        return -1;
2174 55f280c9 balrog
2175 3d97b40b ths
    end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
2176 3d97b40b ths
    start = start & TARGET_PAGE_MASK;
2177 3d97b40b ths
2178 3d97b40b ths
    for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2179 3d97b40b ths
        p = page_find(addr >> TARGET_PAGE_BITS);
2180 3d97b40b ths
        if( !p )
2181 3d97b40b ths
            return -1;
2182 3d97b40b ths
        if( !(p->flags & PAGE_VALID) )
2183 3d97b40b ths
            return -1;
2184 3d97b40b ths
2185 dae3270c bellard
        if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
2186 3d97b40b ths
            return -1;
2187 dae3270c bellard
        if (flags & PAGE_WRITE) {
2188 dae3270c bellard
            if (!(p->flags & PAGE_WRITE_ORG))
2189 dae3270c bellard
                return -1;
2190 dae3270c bellard
            /* unprotect the page if it was put read-only because it
2191 dae3270c bellard
               contains translated code */
2192 dae3270c bellard
            if (!(p->flags & PAGE_WRITE)) {
2193 dae3270c bellard
                if (!page_unprotect(addr, 0, NULL))
2194 dae3270c bellard
                    return -1;
2195 dae3270c bellard
            }
2196 dae3270c bellard
            return 0;
2197 dae3270c bellard
        }
2198 3d97b40b ths
    }
2199 3d97b40b ths
    return 0;
2200 3d97b40b ths
}
2201 3d97b40b ths
2202 9fa3e853 bellard
/* called from signal handler: invalidate the code and unprotect the
2203 ccbb4d44 Stuart Brady
   page. Return TRUE if the fault was successfully handled. */
2204 53a5960a pbrook
int page_unprotect(target_ulong address, unsigned long pc, void *puc)
2205 9fa3e853 bellard
{
2206 9fa3e853 bellard
    unsigned int page_index, prot, pindex;
2207 9fa3e853 bellard
    PageDesc *p, *p1;
2208 53a5960a pbrook
    target_ulong host_start, host_end, addr;
2209 9fa3e853 bellard
2210 c8a706fe pbrook
    /* Technically this isn't safe inside a signal handler.  However we
2211 c8a706fe pbrook
       know this only ever happens in a synchronous SEGV handler, so in
2212 c8a706fe pbrook
       practice it seems to be ok.  */
2213 c8a706fe pbrook
    mmap_lock();
2214 c8a706fe pbrook
2215 83fb7adf bellard
    host_start = address & qemu_host_page_mask;
2216 9fa3e853 bellard
    page_index = host_start >> TARGET_PAGE_BITS;
2217 9fa3e853 bellard
    p1 = page_find(page_index);
2218 c8a706fe pbrook
    if (!p1) {
2219 c8a706fe pbrook
        mmap_unlock();
2220 9fa3e853 bellard
        return 0;
2221 c8a706fe pbrook
    }
2222 83fb7adf bellard
    host_end = host_start + qemu_host_page_size;
2223 9fa3e853 bellard
    p = p1;
2224 9fa3e853 bellard
    prot = 0;
2225 9fa3e853 bellard
    for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
2226 9fa3e853 bellard
        prot |= p->flags;
2227 9fa3e853 bellard
        p++;
2228 9fa3e853 bellard
    }
2229 9fa3e853 bellard
    /* if the page was really writable, then we change its
2230 9fa3e853 bellard
       protection back to writable */
2231 9fa3e853 bellard
    if (prot & PAGE_WRITE_ORG) {
2232 9fa3e853 bellard
        pindex = (address - host_start) >> TARGET_PAGE_BITS;
2233 9fa3e853 bellard
        if (!(p1[pindex].flags & PAGE_WRITE)) {
2234 5fafdf24 ths
            mprotect((void *)g2h(host_start), qemu_host_page_size,
2235 9fa3e853 bellard
                     (prot & PAGE_BITS) | PAGE_WRITE);
2236 9fa3e853 bellard
            p1[pindex].flags |= PAGE_WRITE;
2237 9fa3e853 bellard
            /* and since the content will be modified, we must invalidate
2238 9fa3e853 bellard
               the corresponding translated code. */
2239 d720b93d bellard
            tb_invalidate_phys_page(address, pc, puc);
2240 9fa3e853 bellard
#ifdef DEBUG_TB_CHECK
2241 9fa3e853 bellard
            tb_invalidate_check(address);
2242 9fa3e853 bellard
#endif
2243 c8a706fe pbrook
            mmap_unlock();
2244 9fa3e853 bellard
            return 1;
2245 9fa3e853 bellard
        }
2246 9fa3e853 bellard
    }
2247 c8a706fe pbrook
    mmap_unlock();
2248 9fa3e853 bellard
    return 0;
2249 9fa3e853 bellard
}
2250 9fa3e853 bellard
2251 6a00d601 bellard
static inline void tlb_set_dirty(CPUState *env,
2252 6a00d601 bellard
                                 unsigned long addr, target_ulong vaddr)
2253 1ccde1cb bellard
{
2254 1ccde1cb bellard
}
2255 9fa3e853 bellard
#endif /* defined(CONFIG_USER_ONLY) */
2256 9fa3e853 bellard
2257 e2eef170 pbrook
#if !defined(CONFIG_USER_ONLY)
2258 8da3ff18 pbrook
2259 db7b5426 blueswir1
static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
2260 8da3ff18 pbrook
                             ram_addr_t memory, ram_addr_t region_offset);
2261 00f82b8a aurel32
static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
2262 8da3ff18 pbrook
                           ram_addr_t orig_memory, ram_addr_t region_offset);
2263 db7b5426 blueswir1
#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
2264 db7b5426 blueswir1
                      need_subpage)                                     \
2265 db7b5426 blueswir1
    do {                                                                \
2266 db7b5426 blueswir1
        if (addr > start_addr)                                          \
2267 db7b5426 blueswir1
            start_addr2 = 0;                                            \
2268 db7b5426 blueswir1
        else {                                                          \
2269 db7b5426 blueswir1
            start_addr2 = start_addr & ~TARGET_PAGE_MASK;               \
2270 db7b5426 blueswir1
            if (start_addr2 > 0)                                        \
2271 db7b5426 blueswir1
                need_subpage = 1;                                       \
2272 db7b5426 blueswir1
        }                                                               \
2273 db7b5426 blueswir1
                                                                        \
2274 49e9fba2 blueswir1
        if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE)        \
2275 db7b5426 blueswir1
            end_addr2 = TARGET_PAGE_SIZE - 1;                           \
2276 db7b5426 blueswir1
        else {                                                          \
2277 db7b5426 blueswir1
            end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
2278 db7b5426 blueswir1
            if (end_addr2 < TARGET_PAGE_SIZE - 1)                       \
2279 db7b5426 blueswir1
                need_subpage = 1;                                       \
2280 db7b5426 blueswir1
        }                                                               \
2281 db7b5426 blueswir1
    } while (0)
2282 db7b5426 blueswir1
2283 33417e70 bellard
/* register physical memory. 'size' must be a multiple of the target
2284 33417e70 bellard
   page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
2285 8da3ff18 pbrook
   io memory page.  The address used when calling the IO function is
2286 8da3ff18 pbrook
   the offset from the start of the region, plus region_offset.  Both
2287 ccbb4d44 Stuart Brady
   start_addr and region_offset are rounded down to a page boundary
2288 8da3ff18 pbrook
   before calculating this offset.  This should not be a problem unless
2289 8da3ff18 pbrook
   the low bits of start_addr and region_offset differ.  */
2290 8da3ff18 pbrook
void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
2291 8da3ff18 pbrook
                                         ram_addr_t size,
2292 8da3ff18 pbrook
                                         ram_addr_t phys_offset,
2293 8da3ff18 pbrook
                                         ram_addr_t region_offset)
2294 33417e70 bellard
{
2295 108c49b8 bellard
    target_phys_addr_t addr, end_addr;
2296 92e873b9 bellard
    PhysPageDesc *p;
2297 9d42037b bellard
    CPUState *env;
2298 00f82b8a aurel32
    ram_addr_t orig_size = size;
2299 db7b5426 blueswir1
    void *subpage;
2300 33417e70 bellard
2301 7ba1e619 aliguori
    if (kvm_enabled())
2302 7ba1e619 aliguori
        kvm_set_phys_mem(start_addr, size, phys_offset);
2303 7ba1e619 aliguori
2304 67c4d23c pbrook
    if (phys_offset == IO_MEM_UNASSIGNED) {
2305 67c4d23c pbrook
        region_offset = start_addr;
2306 67c4d23c pbrook
    }
2307 8da3ff18 pbrook
    region_offset &= TARGET_PAGE_MASK;
2308 5fd386f6 bellard
    size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
2309 49e9fba2 blueswir1
    end_addr = start_addr + (target_phys_addr_t)size;
2310 49e9fba2 blueswir1
    for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
2311 db7b5426 blueswir1
        p = phys_page_find(addr >> TARGET_PAGE_BITS);
2312 db7b5426 blueswir1
        if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
2313 00f82b8a aurel32
            ram_addr_t orig_memory = p->phys_offset;
2314 db7b5426 blueswir1
            target_phys_addr_t start_addr2, end_addr2;
2315 db7b5426 blueswir1
            int need_subpage = 0;
2316 db7b5426 blueswir1
2317 db7b5426 blueswir1
            CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2318 db7b5426 blueswir1
                          need_subpage);
2319 4254fab8 blueswir1
            if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
2320 db7b5426 blueswir1
                if (!(orig_memory & IO_MEM_SUBPAGE)) {
2321 db7b5426 blueswir1
                    subpage = subpage_init((addr & TARGET_PAGE_MASK),
2322 8da3ff18 pbrook
                                           &p->phys_offset, orig_memory,
2323 8da3ff18 pbrook
                                           p->region_offset);
2324 db7b5426 blueswir1
                } else {
2325 db7b5426 blueswir1
                    subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
2326 db7b5426 blueswir1
                                            >> IO_MEM_SHIFT];
2327 db7b5426 blueswir1
                }
2328 8da3ff18 pbrook
                subpage_register(subpage, start_addr2, end_addr2, phys_offset,
2329 8da3ff18 pbrook
                                 region_offset);
2330 8da3ff18 pbrook
                p->region_offset = 0;
2331 db7b5426 blueswir1
            } else {
2332 db7b5426 blueswir1
                p->phys_offset = phys_offset;
2333 db7b5426 blueswir1
                if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2334 db7b5426 blueswir1
                    (phys_offset & IO_MEM_ROMD))
2335 db7b5426 blueswir1
                    phys_offset += TARGET_PAGE_SIZE;
2336 db7b5426 blueswir1
            }
2337 db7b5426 blueswir1
        } else {
2338 db7b5426 blueswir1
            p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2339 db7b5426 blueswir1
            p->phys_offset = phys_offset;
2340 8da3ff18 pbrook
            p->region_offset = region_offset;
2341 db7b5426 blueswir1
            if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2342 8da3ff18 pbrook
                (phys_offset & IO_MEM_ROMD)) {
2343 db7b5426 blueswir1
                phys_offset += TARGET_PAGE_SIZE;
2344 0e8f0967 pbrook
            } else {
2345 db7b5426 blueswir1
                target_phys_addr_t start_addr2, end_addr2;
2346 db7b5426 blueswir1
                int need_subpage = 0;
2347 db7b5426 blueswir1
2348 db7b5426 blueswir1
                CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2349 db7b5426 blueswir1
                              end_addr2, need_subpage);
2350 db7b5426 blueswir1
2351 4254fab8 blueswir1
                if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
2352 db7b5426 blueswir1
                    subpage = subpage_init((addr & TARGET_PAGE_MASK),
2353 8da3ff18 pbrook
                                           &p->phys_offset, IO_MEM_UNASSIGNED,
2354 67c4d23c pbrook
                                           addr & TARGET_PAGE_MASK);
2355 db7b5426 blueswir1
                    subpage_register(subpage, start_addr2, end_addr2,
2356 8da3ff18 pbrook
                                     phys_offset, region_offset);
2357 8da3ff18 pbrook
                    p->region_offset = 0;
2358 db7b5426 blueswir1
                }
2359 db7b5426 blueswir1
            }
2360 db7b5426 blueswir1
        }
2361 8da3ff18 pbrook
        region_offset += TARGET_PAGE_SIZE;
2362 33417e70 bellard
    }
2363 3b46e624 ths
2364 9d42037b bellard
    /* since each CPU stores ram addresses in its TLB cache, we must
2365 9d42037b bellard
       reset the modified entries */
2366 9d42037b bellard
    /* XXX: slow ! */
2367 9d42037b bellard
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
2368 9d42037b bellard
        tlb_flush(env, 1);
2369 9d42037b bellard
    }
2370 33417e70 bellard
}
2371 33417e70 bellard
2372 ba863458 bellard
/* XXX: temporary until new memory mapping API */
2373 00f82b8a aurel32
ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr)
2374 ba863458 bellard
{
2375 ba863458 bellard
    PhysPageDesc *p;
2376 ba863458 bellard
2377 ba863458 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2378 ba863458 bellard
    if (!p)
2379 ba863458 bellard
        return IO_MEM_UNASSIGNED;
2380 ba863458 bellard
    return p->phys_offset;
2381 ba863458 bellard
}
2382 ba863458 bellard
2383 f65ed4c1 aliguori
void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
2384 f65ed4c1 aliguori
{
2385 f65ed4c1 aliguori
    if (kvm_enabled())
2386 f65ed4c1 aliguori
        kvm_coalesce_mmio_region(addr, size);
2387 f65ed4c1 aliguori
}
2388 f65ed4c1 aliguori
2389 f65ed4c1 aliguori
void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
2390 f65ed4c1 aliguori
{
2391 f65ed4c1 aliguori
    if (kvm_enabled())
2392 f65ed4c1 aliguori
        kvm_uncoalesce_mmio_region(addr, size);
2393 f65ed4c1 aliguori
}
2394 f65ed4c1 aliguori
2395 94a6b54f pbrook
ram_addr_t qemu_ram_alloc(ram_addr_t size)
2396 94a6b54f pbrook
{
2397 94a6b54f pbrook
    RAMBlock *new_block;
2398 94a6b54f pbrook
2399 94a6b54f pbrook
    size = TARGET_PAGE_ALIGN(size);
2400 94a6b54f pbrook
    new_block = qemu_malloc(sizeof(*new_block));
2401 94a6b54f pbrook
2402 94a6b54f pbrook
    new_block->host = qemu_vmalloc(size);
2403 94a6b54f pbrook
    new_block->offset = last_ram_offset;
2404 94a6b54f pbrook
    new_block->length = size;
2405 94a6b54f pbrook
2406 94a6b54f pbrook
    new_block->next = ram_blocks;
2407 94a6b54f pbrook
    ram_blocks = new_block;
2408 94a6b54f pbrook
2409 94a6b54f pbrook
    phys_ram_dirty = qemu_realloc(phys_ram_dirty,
2410 94a6b54f pbrook
        (last_ram_offset + size) >> TARGET_PAGE_BITS);
2411 94a6b54f pbrook
    memset(phys_ram_dirty + (last_ram_offset >> TARGET_PAGE_BITS),
2412 94a6b54f pbrook
           0xff, size >> TARGET_PAGE_BITS);
2413 94a6b54f pbrook
2414 94a6b54f pbrook
    last_ram_offset += size;
2415 94a6b54f pbrook
2416 6f0437e8 Jan Kiszka
    if (kvm_enabled())
2417 6f0437e8 Jan Kiszka
        kvm_setup_guest_memory(new_block->host, size);
2418 6f0437e8 Jan Kiszka
2419 94a6b54f pbrook
    return new_block->offset;
2420 94a6b54f pbrook
}
2421 e9a1ab19 bellard
2422 e9a1ab19 bellard
void qemu_ram_free(ram_addr_t addr)
2423 e9a1ab19 bellard
{
2424 94a6b54f pbrook
    /* TODO: implement this.  */
2425 e9a1ab19 bellard
}
2426 e9a1ab19 bellard
2427 dc828ca1 pbrook
/* Return a host pointer to ram allocated with qemu_ram_alloc.
2428 5579c7f3 pbrook
   With the exception of the softmmu code in this file, this should
2429 5579c7f3 pbrook
   only be used for local memory (e.g. video ram) that the device owns,
2430 5579c7f3 pbrook
   and knows it isn't going to access beyond the end of the block.
2431 5579c7f3 pbrook

2432 5579c7f3 pbrook
   It should not be used for general purpose DMA.
2433 5579c7f3 pbrook
   Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
2434 5579c7f3 pbrook
 */
2435 dc828ca1 pbrook
void *qemu_get_ram_ptr(ram_addr_t addr)
2436 dc828ca1 pbrook
{
2437 94a6b54f pbrook
    RAMBlock *prev;
2438 94a6b54f pbrook
    RAMBlock **prevp;
2439 94a6b54f pbrook
    RAMBlock *block;
2440 94a6b54f pbrook
2441 94a6b54f pbrook
    prev = NULL;
2442 94a6b54f pbrook
    prevp = &ram_blocks;
2443 94a6b54f pbrook
    block = ram_blocks;
2444 94a6b54f pbrook
    while (block && (block->offset > addr
2445 94a6b54f pbrook
                     || block->offset + block->length <= addr)) {
2446 94a6b54f pbrook
        if (prev)
2447 94a6b54f pbrook
          prevp = &prev->next;
2448 94a6b54f pbrook
        prev = block;
2449 94a6b54f pbrook
        block = block->next;
2450 94a6b54f pbrook
    }
2451 94a6b54f pbrook
    if (!block) {
2452 94a6b54f pbrook
        fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2453 94a6b54f pbrook
        abort();
2454 94a6b54f pbrook
    }
2455 94a6b54f pbrook
    /* Move this entry to to start of the list.  */
2456 94a6b54f pbrook
    if (prev) {
2457 94a6b54f pbrook
        prev->next = block->next;
2458 94a6b54f pbrook
        block->next = *prevp;
2459 94a6b54f pbrook
        *prevp = block;
2460 94a6b54f pbrook
    }
2461 94a6b54f pbrook
    return block->host + (addr - block->offset);
2462 dc828ca1 pbrook
}
2463 dc828ca1 pbrook
2464 5579c7f3 pbrook
/* Some of the softmmu routines need to translate from a host pointer
2465 5579c7f3 pbrook
   (typically a TLB entry) back to a ram offset.  */
2466 5579c7f3 pbrook
ram_addr_t qemu_ram_addr_from_host(void *ptr)
2467 5579c7f3 pbrook
{
2468 94a6b54f pbrook
    RAMBlock *prev;
2469 94a6b54f pbrook
    RAMBlock **prevp;
2470 94a6b54f pbrook
    RAMBlock *block;
2471 94a6b54f pbrook
    uint8_t *host = ptr;
2472 94a6b54f pbrook
2473 94a6b54f pbrook
    prev = NULL;
2474 94a6b54f pbrook
    prevp = &ram_blocks;
2475 94a6b54f pbrook
    block = ram_blocks;
2476 94a6b54f pbrook
    while (block && (block->host > host
2477 94a6b54f pbrook
                     || block->host + block->length <= host)) {
2478 94a6b54f pbrook
        if (prev)
2479 94a6b54f pbrook
          prevp = &prev->next;
2480 94a6b54f pbrook
        prev = block;
2481 94a6b54f pbrook
        block = block->next;
2482 94a6b54f pbrook
    }
2483 94a6b54f pbrook
    if (!block) {
2484 94a6b54f pbrook
        fprintf(stderr, "Bad ram pointer %p\n", ptr);
2485 94a6b54f pbrook
        abort();
2486 94a6b54f pbrook
    }
2487 94a6b54f pbrook
    return block->offset + (host - block->host);
2488 5579c7f3 pbrook
}
2489 5579c7f3 pbrook
2490 a4193c8a bellard
static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
2491 33417e70 bellard
{
2492 67d3b957 pbrook
#ifdef DEBUG_UNASSIGNED
2493 ab3d1727 blueswir1
    printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2494 67d3b957 pbrook
#endif
2495 faed1c2a Edgar E. Iglesias
#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
2496 e18231a3 blueswir1
    do_unassigned_access(addr, 0, 0, 0, 1);
2497 e18231a3 blueswir1
#endif
2498 e18231a3 blueswir1
    return 0;
2499 e18231a3 blueswir1
}
2500 e18231a3 blueswir1
2501 e18231a3 blueswir1
static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr)
2502 e18231a3 blueswir1
{
2503 e18231a3 blueswir1
#ifdef DEBUG_UNASSIGNED
2504 e18231a3 blueswir1
    printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2505 e18231a3 blueswir1
#endif
2506 faed1c2a Edgar E. Iglesias
#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
2507 e18231a3 blueswir1
    do_unassigned_access(addr, 0, 0, 0, 2);
2508 e18231a3 blueswir1
#endif
2509 e18231a3 blueswir1
    return 0;
2510 e18231a3 blueswir1
}
2511 e18231a3 blueswir1
2512 e18231a3 blueswir1
static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr)
2513 e18231a3 blueswir1
{
2514 e18231a3 blueswir1
#ifdef DEBUG_UNASSIGNED
2515 e18231a3 blueswir1
    printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2516 e18231a3 blueswir1
#endif
2517 faed1c2a Edgar E. Iglesias
#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
2518 e18231a3 blueswir1
    do_unassigned_access(addr, 0, 0, 0, 4);
2519 b4f0a316 blueswir1
#endif
2520 33417e70 bellard
    return 0;
2521 33417e70 bellard
}
2522 33417e70 bellard
2523 a4193c8a bellard
static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
2524 33417e70 bellard
{
2525 67d3b957 pbrook
#ifdef DEBUG_UNASSIGNED
2526 ab3d1727 blueswir1
    printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2527 67d3b957 pbrook
#endif
2528 faed1c2a Edgar E. Iglesias
#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
2529 e18231a3 blueswir1
    do_unassigned_access(addr, 1, 0, 0, 1);
2530 e18231a3 blueswir1
#endif
2531 e18231a3 blueswir1
}
2532 e18231a3 blueswir1
2533 e18231a3 blueswir1
static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
2534 e18231a3 blueswir1
{
2535 e18231a3 blueswir1
#ifdef DEBUG_UNASSIGNED
2536 e18231a3 blueswir1
    printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2537 e18231a3 blueswir1
#endif
2538 faed1c2a Edgar E. Iglesias
#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
2539 e18231a3 blueswir1
    do_unassigned_access(addr, 1, 0, 0, 2);
2540 e18231a3 blueswir1
#endif
2541 e18231a3 blueswir1
}
2542 e18231a3 blueswir1
2543 e18231a3 blueswir1
static void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
2544 e18231a3 blueswir1
{
2545 e18231a3 blueswir1
#ifdef DEBUG_UNASSIGNED
2546 e18231a3 blueswir1
    printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2547 e18231a3 blueswir1
#endif
2548 faed1c2a Edgar E. Iglesias
#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
2549 e18231a3 blueswir1
    do_unassigned_access(addr, 1, 0, 0, 4);
2550 b4f0a316 blueswir1
#endif
2551 33417e70 bellard
}
2552 33417e70 bellard
2553 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const unassigned_mem_read[3] = {
2554 33417e70 bellard
    unassigned_mem_readb,
2555 e18231a3 blueswir1
    unassigned_mem_readw,
2556 e18231a3 blueswir1
    unassigned_mem_readl,
2557 33417e70 bellard
};
2558 33417e70 bellard
2559 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const unassigned_mem_write[3] = {
2560 33417e70 bellard
    unassigned_mem_writeb,
2561 e18231a3 blueswir1
    unassigned_mem_writew,
2562 e18231a3 blueswir1
    unassigned_mem_writel,
2563 33417e70 bellard
};
2564 33417e70 bellard
2565 0f459d16 pbrook
static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr,
2566 0f459d16 pbrook
                                uint32_t val)
2567 9fa3e853 bellard
{
2568 3a7d929e bellard
    int dirty_flags;
2569 3a7d929e bellard
    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2570 3a7d929e bellard
    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2571 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
2572 3a7d929e bellard
        tb_invalidate_phys_page_fast(ram_addr, 1);
2573 3a7d929e bellard
        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2574 9fa3e853 bellard
#endif
2575 3a7d929e bellard
    }
2576 5579c7f3 pbrook
    stb_p(qemu_get_ram_ptr(ram_addr), val);
2577 f23db169 bellard
    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2578 f23db169 bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2579 f23db169 bellard
    /* we remove the notdirty callback only if the code has been
2580 f23db169 bellard
       flushed */
2581 f23db169 bellard
    if (dirty_flags == 0xff)
2582 2e70f6ef pbrook
        tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2583 9fa3e853 bellard
}
2584 9fa3e853 bellard
2585 0f459d16 pbrook
static void notdirty_mem_writew(void *opaque, target_phys_addr_t ram_addr,
2586 0f459d16 pbrook
                                uint32_t val)
2587 9fa3e853 bellard
{
2588 3a7d929e bellard
    int dirty_flags;
2589 3a7d929e bellard
    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2590 3a7d929e bellard
    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2591 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
2592 3a7d929e bellard
        tb_invalidate_phys_page_fast(ram_addr, 2);
2593 3a7d929e bellard
        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2594 9fa3e853 bellard
#endif
2595 3a7d929e bellard
    }
2596 5579c7f3 pbrook
    stw_p(qemu_get_ram_ptr(ram_addr), val);
2597 f23db169 bellard
    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2598 f23db169 bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2599 f23db169 bellard
    /* we remove the notdirty callback only if the code has been
2600 f23db169 bellard
       flushed */
2601 f23db169 bellard
    if (dirty_flags == 0xff)
2602 2e70f6ef pbrook
        tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2603 9fa3e853 bellard
}
2604 9fa3e853 bellard
2605 0f459d16 pbrook
static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr,
2606 0f459d16 pbrook
                                uint32_t val)
2607 9fa3e853 bellard
{
2608 3a7d929e bellard
    int dirty_flags;
2609 3a7d929e bellard
    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2610 3a7d929e bellard
    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2611 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
2612 3a7d929e bellard
        tb_invalidate_phys_page_fast(ram_addr, 4);
2613 3a7d929e bellard
        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2614 9fa3e853 bellard
#endif
2615 3a7d929e bellard
    }
2616 5579c7f3 pbrook
    stl_p(qemu_get_ram_ptr(ram_addr), val);
2617 f23db169 bellard
    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2618 f23db169 bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2619 f23db169 bellard
    /* we remove the notdirty callback only if the code has been
2620 f23db169 bellard
       flushed */
2621 f23db169 bellard
    if (dirty_flags == 0xff)
2622 2e70f6ef pbrook
        tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2623 9fa3e853 bellard
}
2624 9fa3e853 bellard
2625 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const error_mem_read[3] = {
2626 9fa3e853 bellard
    NULL, /* never used */
2627 9fa3e853 bellard
    NULL, /* never used */
2628 9fa3e853 bellard
    NULL, /* never used */
2629 9fa3e853 bellard
};
2630 9fa3e853 bellard
2631 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const notdirty_mem_write[3] = {
2632 1ccde1cb bellard
    notdirty_mem_writeb,
2633 1ccde1cb bellard
    notdirty_mem_writew,
2634 1ccde1cb bellard
    notdirty_mem_writel,
2635 1ccde1cb bellard
};
2636 1ccde1cb bellard
2637 0f459d16 pbrook
/* Generate a debug exception if a watchpoint has been hit.  */
2638 b4051334 aliguori
static void check_watchpoint(int offset, int len_mask, int flags)
2639 0f459d16 pbrook
{
2640 0f459d16 pbrook
    CPUState *env = cpu_single_env;
2641 06d55cc1 aliguori
    target_ulong pc, cs_base;
2642 06d55cc1 aliguori
    TranslationBlock *tb;
2643 0f459d16 pbrook
    target_ulong vaddr;
2644 a1d1bb31 aliguori
    CPUWatchpoint *wp;
2645 06d55cc1 aliguori
    int cpu_flags;
2646 0f459d16 pbrook
2647 06d55cc1 aliguori
    if (env->watchpoint_hit) {
2648 06d55cc1 aliguori
        /* We re-entered the check after replacing the TB. Now raise
2649 06d55cc1 aliguori
         * the debug interrupt so that is will trigger after the
2650 06d55cc1 aliguori
         * current instruction. */
2651 06d55cc1 aliguori
        cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2652 06d55cc1 aliguori
        return;
2653 06d55cc1 aliguori
    }
2654 2e70f6ef pbrook
    vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
2655 c0ce998e aliguori
    TAILQ_FOREACH(wp, &env->watchpoints, entry) {
2656 b4051334 aliguori
        if ((vaddr == (wp->vaddr & len_mask) ||
2657 b4051334 aliguori
             (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
2658 6e140f28 aliguori
            wp->flags |= BP_WATCHPOINT_HIT;
2659 6e140f28 aliguori
            if (!env->watchpoint_hit) {
2660 6e140f28 aliguori
                env->watchpoint_hit = wp;
2661 6e140f28 aliguori
                tb = tb_find_pc(env->mem_io_pc);
2662 6e140f28 aliguori
                if (!tb) {
2663 6e140f28 aliguori
                    cpu_abort(env, "check_watchpoint: could not find TB for "
2664 6e140f28 aliguori
                              "pc=%p", (void *)env->mem_io_pc);
2665 6e140f28 aliguori
                }
2666 6e140f28 aliguori
                cpu_restore_state(tb, env, env->mem_io_pc, NULL);
2667 6e140f28 aliguori
                tb_phys_invalidate(tb, -1);
2668 6e140f28 aliguori
                if (wp->flags & BP_STOP_BEFORE_ACCESS) {
2669 6e140f28 aliguori
                    env->exception_index = EXCP_DEBUG;
2670 6e140f28 aliguori
                } else {
2671 6e140f28 aliguori
                    cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
2672 6e140f28 aliguori
                    tb_gen_code(env, pc, cs_base, cpu_flags, 1);
2673 6e140f28 aliguori
                }
2674 6e140f28 aliguori
                cpu_resume_from_signal(env, NULL);
2675 06d55cc1 aliguori
            }
2676 6e140f28 aliguori
        } else {
2677 6e140f28 aliguori
            wp->flags &= ~BP_WATCHPOINT_HIT;
2678 0f459d16 pbrook
        }
2679 0f459d16 pbrook
    }
2680 0f459d16 pbrook
}
2681 0f459d16 pbrook
2682 6658ffb8 pbrook
/* Watchpoint access routines.  Watchpoints are inserted using TLB tricks,
2683 6658ffb8 pbrook
   so these check for a hit then pass through to the normal out-of-line
2684 6658ffb8 pbrook
   phys routines.  */
2685 6658ffb8 pbrook
static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
2686 6658ffb8 pbrook
{
2687 b4051334 aliguori
    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ);
2688 6658ffb8 pbrook
    return ldub_phys(addr);
2689 6658ffb8 pbrook
}
2690 6658ffb8 pbrook
2691 6658ffb8 pbrook
static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
2692 6658ffb8 pbrook
{
2693 b4051334 aliguori
    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ);
2694 6658ffb8 pbrook
    return lduw_phys(addr);
2695 6658ffb8 pbrook
}
2696 6658ffb8 pbrook
2697 6658ffb8 pbrook
static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
2698 6658ffb8 pbrook
{
2699 b4051334 aliguori
    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ);
2700 6658ffb8 pbrook
    return ldl_phys(addr);
2701 6658ffb8 pbrook
}
2702 6658ffb8 pbrook
2703 6658ffb8 pbrook
static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
2704 6658ffb8 pbrook
                             uint32_t val)
2705 6658ffb8 pbrook
{
2706 b4051334 aliguori
    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_WRITE);
2707 6658ffb8 pbrook
    stb_phys(addr, val);
2708 6658ffb8 pbrook
}
2709 6658ffb8 pbrook
2710 6658ffb8 pbrook
static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
2711 6658ffb8 pbrook
                             uint32_t val)
2712 6658ffb8 pbrook
{
2713 b4051334 aliguori
    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_WRITE);
2714 6658ffb8 pbrook
    stw_phys(addr, val);
2715 6658ffb8 pbrook
}
2716 6658ffb8 pbrook
2717 6658ffb8 pbrook
static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
2718 6658ffb8 pbrook
                             uint32_t val)
2719 6658ffb8 pbrook
{
2720 b4051334 aliguori
    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE);
2721 6658ffb8 pbrook
    stl_phys(addr, val);
2722 6658ffb8 pbrook
}
2723 6658ffb8 pbrook
2724 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const watch_mem_read[3] = {
2725 6658ffb8 pbrook
    watch_mem_readb,
2726 6658ffb8 pbrook
    watch_mem_readw,
2727 6658ffb8 pbrook
    watch_mem_readl,
2728 6658ffb8 pbrook
};
2729 6658ffb8 pbrook
2730 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const watch_mem_write[3] = {
2731 6658ffb8 pbrook
    watch_mem_writeb,
2732 6658ffb8 pbrook
    watch_mem_writew,
2733 6658ffb8 pbrook
    watch_mem_writel,
2734 6658ffb8 pbrook
};
2735 6658ffb8 pbrook
2736 db7b5426 blueswir1
static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr,
2737 db7b5426 blueswir1
                                 unsigned int len)
2738 db7b5426 blueswir1
{
2739 db7b5426 blueswir1
    uint32_t ret;
2740 db7b5426 blueswir1
    unsigned int idx;
2741 db7b5426 blueswir1
2742 8da3ff18 pbrook
    idx = SUBPAGE_IDX(addr);
2743 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2744 db7b5426 blueswir1
    printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
2745 db7b5426 blueswir1
           mmio, len, addr, idx);
2746 db7b5426 blueswir1
#endif
2747 8da3ff18 pbrook
    ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len],
2748 8da3ff18 pbrook
                                       addr + mmio->region_offset[idx][0][len]);
2749 db7b5426 blueswir1
2750 db7b5426 blueswir1
    return ret;
2751 db7b5426 blueswir1
}
2752 db7b5426 blueswir1
2753 db7b5426 blueswir1
static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
2754 db7b5426 blueswir1
                              uint32_t value, unsigned int len)
2755 db7b5426 blueswir1
{
2756 db7b5426 blueswir1
    unsigned int idx;
2757 db7b5426 blueswir1
2758 8da3ff18 pbrook
    idx = SUBPAGE_IDX(addr);
2759 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2760 db7b5426 blueswir1
    printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
2761 db7b5426 blueswir1
           mmio, len, addr, idx, value);
2762 db7b5426 blueswir1
#endif
2763 8da3ff18 pbrook
    (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len],
2764 8da3ff18 pbrook
                                  addr + mmio->region_offset[idx][1][len],
2765 8da3ff18 pbrook
                                  value);
2766 db7b5426 blueswir1
}
2767 db7b5426 blueswir1
2768 db7b5426 blueswir1
static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
2769 db7b5426 blueswir1
{
2770 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2771 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2772 db7b5426 blueswir1
#endif
2773 db7b5426 blueswir1
2774 db7b5426 blueswir1
    return subpage_readlen(opaque, addr, 0);
2775 db7b5426 blueswir1
}
2776 db7b5426 blueswir1
2777 db7b5426 blueswir1
static void subpage_writeb (void *opaque, target_phys_addr_t addr,
2778 db7b5426 blueswir1
                            uint32_t value)
2779 db7b5426 blueswir1
{
2780 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2781 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2782 db7b5426 blueswir1
#endif
2783 db7b5426 blueswir1
    subpage_writelen(opaque, addr, value, 0);
2784 db7b5426 blueswir1
}
2785 db7b5426 blueswir1
2786 db7b5426 blueswir1
static uint32_t subpage_readw (void *opaque, target_phys_addr_t addr)
2787 db7b5426 blueswir1
{
2788 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2789 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2790 db7b5426 blueswir1
#endif
2791 db7b5426 blueswir1
2792 db7b5426 blueswir1
    return subpage_readlen(opaque, addr, 1);
2793 db7b5426 blueswir1
}
2794 db7b5426 blueswir1
2795 db7b5426 blueswir1
static void subpage_writew (void *opaque, target_phys_addr_t addr,
2796 db7b5426 blueswir1
                            uint32_t value)
2797 db7b5426 blueswir1
{
2798 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2799 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2800 db7b5426 blueswir1
#endif
2801 db7b5426 blueswir1
    subpage_writelen(opaque, addr, value, 1);
2802 db7b5426 blueswir1
}
2803 db7b5426 blueswir1
2804 db7b5426 blueswir1
static uint32_t subpage_readl (void *opaque, target_phys_addr_t addr)
2805 db7b5426 blueswir1
{
2806 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2807 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2808 db7b5426 blueswir1
#endif
2809 db7b5426 blueswir1
2810 db7b5426 blueswir1
    return subpage_readlen(opaque, addr, 2);
2811 db7b5426 blueswir1
}
2812 db7b5426 blueswir1
2813 db7b5426 blueswir1
static void subpage_writel (void *opaque,
2814 db7b5426 blueswir1
                         target_phys_addr_t addr, uint32_t value)
2815 db7b5426 blueswir1
{
2816 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2817 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2818 db7b5426 blueswir1
#endif
2819 db7b5426 blueswir1
    subpage_writelen(opaque, addr, value, 2);
2820 db7b5426 blueswir1
}
2821 db7b5426 blueswir1
2822 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const subpage_read[] = {
2823 db7b5426 blueswir1
    &subpage_readb,
2824 db7b5426 blueswir1
    &subpage_readw,
2825 db7b5426 blueswir1
    &subpage_readl,
2826 db7b5426 blueswir1
};
2827 db7b5426 blueswir1
2828 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const subpage_write[] = {
2829 db7b5426 blueswir1
    &subpage_writeb,
2830 db7b5426 blueswir1
    &subpage_writew,
2831 db7b5426 blueswir1
    &subpage_writel,
2832 db7b5426 blueswir1
};
2833 db7b5426 blueswir1
2834 db7b5426 blueswir1
static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
2835 8da3ff18 pbrook
                             ram_addr_t memory, ram_addr_t region_offset)
2836 db7b5426 blueswir1
{
2837 db7b5426 blueswir1
    int idx, eidx;
2838 4254fab8 blueswir1
    unsigned int i;
2839 db7b5426 blueswir1
2840 db7b5426 blueswir1
    if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
2841 db7b5426 blueswir1
        return -1;
2842 db7b5426 blueswir1
    idx = SUBPAGE_IDX(start);
2843 db7b5426 blueswir1
    eidx = SUBPAGE_IDX(end);
2844 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2845 0bf9e31a Blue Swirl
    printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__,
2846 db7b5426 blueswir1
           mmio, start, end, idx, eidx, memory);
2847 db7b5426 blueswir1
#endif
2848 db7b5426 blueswir1
    memory >>= IO_MEM_SHIFT;
2849 db7b5426 blueswir1
    for (; idx <= eidx; idx++) {
2850 4254fab8 blueswir1
        for (i = 0; i < 4; i++) {
2851 3ee89922 blueswir1
            if (io_mem_read[memory][i]) {
2852 3ee89922 blueswir1
                mmio->mem_read[idx][i] = &io_mem_read[memory][i];
2853 3ee89922 blueswir1
                mmio->opaque[idx][0][i] = io_mem_opaque[memory];
2854 8da3ff18 pbrook
                mmio->region_offset[idx][0][i] = region_offset;
2855 3ee89922 blueswir1
            }
2856 3ee89922 blueswir1
            if (io_mem_write[memory][i]) {
2857 3ee89922 blueswir1
                mmio->mem_write[idx][i] = &io_mem_write[memory][i];
2858 3ee89922 blueswir1
                mmio->opaque[idx][1][i] = io_mem_opaque[memory];
2859 8da3ff18 pbrook
                mmio->region_offset[idx][1][i] = region_offset;
2860 3ee89922 blueswir1
            }
2861 4254fab8 blueswir1
        }
2862 db7b5426 blueswir1
    }
2863 db7b5426 blueswir1
2864 db7b5426 blueswir1
    return 0;
2865 db7b5426 blueswir1
}
2866 db7b5426 blueswir1
2867 00f82b8a aurel32
static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
2868 8da3ff18 pbrook
                           ram_addr_t orig_memory, ram_addr_t region_offset)
2869 db7b5426 blueswir1
{
2870 db7b5426 blueswir1
    subpage_t *mmio;
2871 db7b5426 blueswir1
    int subpage_memory;
2872 db7b5426 blueswir1
2873 db7b5426 blueswir1
    mmio = qemu_mallocz(sizeof(subpage_t));
2874 1eec614b aliguori
2875 1eec614b aliguori
    mmio->base = base;
2876 1eed09cb Avi Kivity
    subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
2877 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2878 1eec614b aliguori
    printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
2879 1eec614b aliguori
           mmio, base, TARGET_PAGE_SIZE, subpage_memory);
2880 db7b5426 blueswir1
#endif
2881 1eec614b aliguori
    *phys = subpage_memory | IO_MEM_SUBPAGE;
2882 1eec614b aliguori
    subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
2883 8da3ff18 pbrook
                         region_offset);
2884 db7b5426 blueswir1
2885 db7b5426 blueswir1
    return mmio;
2886 db7b5426 blueswir1
}
2887 db7b5426 blueswir1
2888 88715657 aliguori
static int get_free_io_mem_idx(void)
2889 88715657 aliguori
{
2890 88715657 aliguori
    int i;
2891 88715657 aliguori
2892 88715657 aliguori
    for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
2893 88715657 aliguori
        if (!io_mem_used[i]) {
2894 88715657 aliguori
            io_mem_used[i] = 1;
2895 88715657 aliguori
            return i;
2896 88715657 aliguori
        }
2897 88715657 aliguori
2898 88715657 aliguori
    return -1;
2899 88715657 aliguori
}
2900 88715657 aliguori
2901 33417e70 bellard
/* mem_read and mem_write are arrays of functions containing the
2902 33417e70 bellard
   function to access byte (index 0), word (index 1) and dword (index
2903 0b4e6e3e Paul Brook
   2). Functions can be omitted with a NULL function pointer.
2904 3ee89922 blueswir1
   If io_index is non zero, the corresponding io zone is
2905 4254fab8 blueswir1
   modified. If it is zero, a new io zone is allocated. The return
2906 4254fab8 blueswir1
   value can be used with cpu_register_physical_memory(). (-1) is
2907 4254fab8 blueswir1
   returned if error. */
2908 1eed09cb Avi Kivity
static int cpu_register_io_memory_fixed(int io_index,
2909 d60efc6b Blue Swirl
                                        CPUReadMemoryFunc * const *mem_read,
2910 d60efc6b Blue Swirl
                                        CPUWriteMemoryFunc * const *mem_write,
2911 1eed09cb Avi Kivity
                                        void *opaque)
2912 33417e70 bellard
{
2913 4254fab8 blueswir1
    int i, subwidth = 0;
2914 33417e70 bellard
2915 33417e70 bellard
    if (io_index <= 0) {
2916 88715657 aliguori
        io_index = get_free_io_mem_idx();
2917 88715657 aliguori
        if (io_index == -1)
2918 88715657 aliguori
            return io_index;
2919 33417e70 bellard
    } else {
2920 1eed09cb Avi Kivity
        io_index >>= IO_MEM_SHIFT;
2921 33417e70 bellard
        if (io_index >= IO_MEM_NB_ENTRIES)
2922 33417e70 bellard
            return -1;
2923 33417e70 bellard
    }
2924 b5ff1b31 bellard
2925 33417e70 bellard
    for(i = 0;i < 3; i++) {
2926 4254fab8 blueswir1
        if (!mem_read[i] || !mem_write[i])
2927 4254fab8 blueswir1
            subwidth = IO_MEM_SUBWIDTH;
2928 33417e70 bellard
        io_mem_read[io_index][i] = mem_read[i];
2929 33417e70 bellard
        io_mem_write[io_index][i] = mem_write[i];
2930 33417e70 bellard
    }
2931 a4193c8a bellard
    io_mem_opaque[io_index] = opaque;
2932 4254fab8 blueswir1
    return (io_index << IO_MEM_SHIFT) | subwidth;
2933 33417e70 bellard
}
2934 61382a50 bellard
2935 d60efc6b Blue Swirl
int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
2936 d60efc6b Blue Swirl
                           CPUWriteMemoryFunc * const *mem_write,
2937 1eed09cb Avi Kivity
                           void *opaque)
2938 1eed09cb Avi Kivity
{
2939 1eed09cb Avi Kivity
    return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
2940 1eed09cb Avi Kivity
}
2941 1eed09cb Avi Kivity
2942 88715657 aliguori
void cpu_unregister_io_memory(int io_table_address)
2943 88715657 aliguori
{
2944 88715657 aliguori
    int i;
2945 88715657 aliguori
    int io_index = io_table_address >> IO_MEM_SHIFT;
2946 88715657 aliguori
2947 88715657 aliguori
    for (i=0;i < 3; i++) {
2948 88715657 aliguori
        io_mem_read[io_index][i] = unassigned_mem_read[i];
2949 88715657 aliguori
        io_mem_write[io_index][i] = unassigned_mem_write[i];
2950 88715657 aliguori
    }
2951 88715657 aliguori
    io_mem_opaque[io_index] = NULL;
2952 88715657 aliguori
    io_mem_used[io_index] = 0;
2953 88715657 aliguori
}
2954 88715657 aliguori
2955 e9179ce1 Avi Kivity
static void io_mem_init(void)
2956 e9179ce1 Avi Kivity
{
2957 e9179ce1 Avi Kivity
    int i;
2958 e9179ce1 Avi Kivity
2959 e9179ce1 Avi Kivity
    cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read, unassigned_mem_write, NULL);
2960 e9179ce1 Avi Kivity
    cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read, unassigned_mem_write, NULL);
2961 e9179ce1 Avi Kivity
    cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read, notdirty_mem_write, NULL);
2962 e9179ce1 Avi Kivity
    for (i=0; i<5; i++)
2963 e9179ce1 Avi Kivity
        io_mem_used[i] = 1;
2964 e9179ce1 Avi Kivity
2965 e9179ce1 Avi Kivity
    io_mem_watch = cpu_register_io_memory(watch_mem_read,
2966 e9179ce1 Avi Kivity
                                          watch_mem_write, NULL);
2967 e9179ce1 Avi Kivity
}
2968 e9179ce1 Avi Kivity
2969 e2eef170 pbrook
#endif /* !defined(CONFIG_USER_ONLY) */
2970 e2eef170 pbrook
2971 13eb76e0 bellard
/* physical memory access (slow version, mainly for debug) */
2972 13eb76e0 bellard
#if defined(CONFIG_USER_ONLY)
2973 5fafdf24 ths
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
2974 13eb76e0 bellard
                            int len, int is_write)
2975 13eb76e0 bellard
{
2976 13eb76e0 bellard
    int l, flags;
2977 13eb76e0 bellard
    target_ulong page;
2978 53a5960a pbrook
    void * p;
2979 13eb76e0 bellard
2980 13eb76e0 bellard
    while (len > 0) {
2981 13eb76e0 bellard
        page = addr & TARGET_PAGE_MASK;
2982 13eb76e0 bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
2983 13eb76e0 bellard
        if (l > len)
2984 13eb76e0 bellard
            l = len;
2985 13eb76e0 bellard
        flags = page_get_flags(page);
2986 13eb76e0 bellard
        if (!(flags & PAGE_VALID))
2987 13eb76e0 bellard
            return;
2988 13eb76e0 bellard
        if (is_write) {
2989 13eb76e0 bellard
            if (!(flags & PAGE_WRITE))
2990 13eb76e0 bellard
                return;
2991 579a97f7 bellard
            /* XXX: this code should not depend on lock_user */
2992 72fb7daa aurel32
            if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
2993 579a97f7 bellard
                /* FIXME - should this return an error rather than just fail? */
2994 579a97f7 bellard
                return;
2995 72fb7daa aurel32
            memcpy(p, buf, l);
2996 72fb7daa aurel32
            unlock_user(p, addr, l);
2997 13eb76e0 bellard
        } else {
2998 13eb76e0 bellard
            if (!(flags & PAGE_READ))
2999 13eb76e0 bellard
                return;
3000 579a97f7 bellard
            /* XXX: this code should not depend on lock_user */
3001 72fb7daa aurel32
            if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
3002 579a97f7 bellard
                /* FIXME - should this return an error rather than just fail? */
3003 579a97f7 bellard
                return;
3004 72fb7daa aurel32
            memcpy(buf, p, l);
3005 5b257578 aurel32
            unlock_user(p, addr, 0);
3006 13eb76e0 bellard
        }
3007 13eb76e0 bellard
        len -= l;
3008 13eb76e0 bellard
        buf += l;
3009 13eb76e0 bellard
        addr += l;
3010 13eb76e0 bellard
    }
3011 13eb76e0 bellard
}
3012 8df1cd07 bellard
3013 13eb76e0 bellard
#else
3014 5fafdf24 ths
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
3015 13eb76e0 bellard
                            int len, int is_write)
3016 13eb76e0 bellard
{
3017 13eb76e0 bellard
    int l, io_index;
3018 13eb76e0 bellard
    uint8_t *ptr;
3019 13eb76e0 bellard
    uint32_t val;
3020 2e12669a bellard
    target_phys_addr_t page;
3021 2e12669a bellard
    unsigned long pd;
3022 92e873b9 bellard
    PhysPageDesc *p;
3023 3b46e624 ths
3024 13eb76e0 bellard
    while (len > 0) {
3025 13eb76e0 bellard
        page = addr & TARGET_PAGE_MASK;
3026 13eb76e0 bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
3027 13eb76e0 bellard
        if (l > len)
3028 13eb76e0 bellard
            l = len;
3029 92e873b9 bellard
        p = phys_page_find(page >> TARGET_PAGE_BITS);
3030 13eb76e0 bellard
        if (!p) {
3031 13eb76e0 bellard
            pd = IO_MEM_UNASSIGNED;
3032 13eb76e0 bellard
        } else {
3033 13eb76e0 bellard
            pd = p->phys_offset;
3034 13eb76e0 bellard
        }
3035 3b46e624 ths
3036 13eb76e0 bellard
        if (is_write) {
3037 3a7d929e bellard
            if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3038 6c2934db aurel32
                target_phys_addr_t addr1 = addr;
3039 13eb76e0 bellard
                io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
3040 8da3ff18 pbrook
                if (p)
3041 6c2934db aurel32
                    addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3042 6a00d601 bellard
                /* XXX: could force cpu_single_env to NULL to avoid
3043 6a00d601 bellard
                   potential bugs */
3044 6c2934db aurel32
                if (l >= 4 && ((addr1 & 3) == 0)) {
3045 1c213d19 bellard
                    /* 32 bit write access */
3046 c27004ec bellard
                    val = ldl_p(buf);
3047 6c2934db aurel32
                    io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, val);
3048 13eb76e0 bellard
                    l = 4;
3049 6c2934db aurel32
                } else if (l >= 2 && ((addr1 & 1) == 0)) {
3050 1c213d19 bellard
                    /* 16 bit write access */
3051 c27004ec bellard
                    val = lduw_p(buf);
3052 6c2934db aurel32
                    io_mem_write[io_index][1](io_mem_opaque[io_index], addr1, val);
3053 13eb76e0 bellard
                    l = 2;
3054 13eb76e0 bellard
                } else {
3055 1c213d19 bellard
                    /* 8 bit write access */
3056 c27004ec bellard
                    val = ldub_p(buf);
3057 6c2934db aurel32
                    io_mem_write[io_index][0](io_mem_opaque[io_index], addr1, val);
3058 13eb76e0 bellard
                    l = 1;
3059 13eb76e0 bellard
                }
3060 13eb76e0 bellard
            } else {
3061 b448f2f3 bellard
                unsigned long addr1;
3062 b448f2f3 bellard
                addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3063 13eb76e0 bellard
                /* RAM case */
3064 5579c7f3 pbrook
                ptr = qemu_get_ram_ptr(addr1);
3065 13eb76e0 bellard
                memcpy(ptr, buf, l);
3066 3a7d929e bellard
                if (!cpu_physical_memory_is_dirty(addr1)) {
3067 3a7d929e bellard
                    /* invalidate code */
3068 3a7d929e bellard
                    tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
3069 3a7d929e bellard
                    /* set dirty bit */
3070 5fafdf24 ths
                    phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3071 f23db169 bellard
                        (0xff & ~CODE_DIRTY_FLAG);
3072 3a7d929e bellard
                }
3073 13eb76e0 bellard
            }
3074 13eb76e0 bellard
        } else {
3075 5fafdf24 ths
            if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3076 2a4188a3 bellard
                !(pd & IO_MEM_ROMD)) {
3077 6c2934db aurel32
                target_phys_addr_t addr1 = addr;
3078 13eb76e0 bellard
                /* I/O case */
3079 13eb76e0 bellard
                io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
3080 8da3ff18 pbrook
                if (p)
3081 6c2934db aurel32
                    addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3082 6c2934db aurel32
                if (l >= 4 && ((addr1 & 3) == 0)) {
3083 13eb76e0 bellard
                    /* 32 bit read access */
3084 6c2934db aurel32
                    val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
3085 c27004ec bellard
                    stl_p(buf, val);
3086 13eb76e0 bellard
                    l = 4;
3087 6c2934db aurel32
                } else if (l >= 2 && ((addr1 & 1) == 0)) {
3088 13eb76e0 bellard
                    /* 16 bit read access */
3089 6c2934db aurel32
                    val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr1);
3090 c27004ec bellard
                    stw_p(buf, val);
3091 13eb76e0 bellard
                    l = 2;
3092 13eb76e0 bellard
                } else {
3093 1c213d19 bellard
                    /* 8 bit read access */
3094 6c2934db aurel32
                    val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr1);
3095 c27004ec bellard
                    stb_p(buf, val);
3096 13eb76e0 bellard
                    l = 1;
3097 13eb76e0 bellard
                }
3098 13eb76e0 bellard
            } else {
3099 13eb76e0 bellard
                /* RAM case */
3100 5579c7f3 pbrook
                ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
3101 13eb76e0 bellard
                    (addr & ~TARGET_PAGE_MASK);
3102 13eb76e0 bellard
                memcpy(buf, ptr, l);
3103 13eb76e0 bellard
            }
3104 13eb76e0 bellard
        }
3105 13eb76e0 bellard
        len -= l;
3106 13eb76e0 bellard
        buf += l;
3107 13eb76e0 bellard
        addr += l;
3108 13eb76e0 bellard
    }
3109 13eb76e0 bellard
}
3110 8df1cd07 bellard
3111 d0ecd2aa bellard
/* used for ROM loading : can write in RAM and ROM */
3112 5fafdf24 ths
void cpu_physical_memory_write_rom(target_phys_addr_t addr,
3113 d0ecd2aa bellard
                                   const uint8_t *buf, int len)
3114 d0ecd2aa bellard
{
3115 d0ecd2aa bellard
    int l;
3116 d0ecd2aa bellard
    uint8_t *ptr;
3117 d0ecd2aa bellard
    target_phys_addr_t page;
3118 d0ecd2aa bellard
    unsigned long pd;
3119 d0ecd2aa bellard
    PhysPageDesc *p;
3120 3b46e624 ths
3121 d0ecd2aa bellard
    while (len > 0) {
3122 d0ecd2aa bellard
        page = addr & TARGET_PAGE_MASK;
3123 d0ecd2aa bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
3124 d0ecd2aa bellard
        if (l > len)
3125 d0ecd2aa bellard
            l = len;
3126 d0ecd2aa bellard
        p = phys_page_find(page >> TARGET_PAGE_BITS);
3127 d0ecd2aa bellard
        if (!p) {
3128 d0ecd2aa bellard
            pd = IO_MEM_UNASSIGNED;
3129 d0ecd2aa bellard
        } else {
3130 d0ecd2aa bellard
            pd = p->phys_offset;
3131 d0ecd2aa bellard
        }
3132 3b46e624 ths
3133 d0ecd2aa bellard
        if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
3134 2a4188a3 bellard
            (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
3135 2a4188a3 bellard
            !(pd & IO_MEM_ROMD)) {
3136 d0ecd2aa bellard
            /* do nothing */
3137 d0ecd2aa bellard
        } else {
3138 d0ecd2aa bellard
            unsigned long addr1;
3139 d0ecd2aa bellard
            addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3140 d0ecd2aa bellard
            /* ROM/RAM case */
3141 5579c7f3 pbrook
            ptr = qemu_get_ram_ptr(addr1);
3142 d0ecd2aa bellard
            memcpy(ptr, buf, l);
3143 d0ecd2aa bellard
        }
3144 d0ecd2aa bellard
        len -= l;
3145 d0ecd2aa bellard
        buf += l;
3146 d0ecd2aa bellard
        addr += l;
3147 d0ecd2aa bellard
    }
3148 d0ecd2aa bellard
}
3149 d0ecd2aa bellard
3150 6d16c2f8 aliguori
typedef struct {
3151 6d16c2f8 aliguori
    void *buffer;
3152 6d16c2f8 aliguori
    target_phys_addr_t addr;
3153 6d16c2f8 aliguori
    target_phys_addr_t len;
3154 6d16c2f8 aliguori
} BounceBuffer;
3155 6d16c2f8 aliguori
3156 6d16c2f8 aliguori
static BounceBuffer bounce;
3157 6d16c2f8 aliguori
3158 ba223c29 aliguori
typedef struct MapClient {
3159 ba223c29 aliguori
    void *opaque;
3160 ba223c29 aliguori
    void (*callback)(void *opaque);
3161 ba223c29 aliguori
    LIST_ENTRY(MapClient) link;
3162 ba223c29 aliguori
} MapClient;
3163 ba223c29 aliguori
3164 ba223c29 aliguori
static LIST_HEAD(map_client_list, MapClient) map_client_list
3165 ba223c29 aliguori
    = LIST_HEAD_INITIALIZER(map_client_list);
3166 ba223c29 aliguori
3167 ba223c29 aliguori
void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
3168 ba223c29 aliguori
{
3169 ba223c29 aliguori
    MapClient *client = qemu_malloc(sizeof(*client));
3170 ba223c29 aliguori
3171 ba223c29 aliguori
    client->opaque = opaque;
3172 ba223c29 aliguori
    client->callback = callback;
3173 ba223c29 aliguori
    LIST_INSERT_HEAD(&map_client_list, client, link);
3174 ba223c29 aliguori
    return client;
3175 ba223c29 aliguori
}
3176 ba223c29 aliguori
3177 ba223c29 aliguori
void cpu_unregister_map_client(void *_client)
3178 ba223c29 aliguori
{
3179 ba223c29 aliguori
    MapClient *client = (MapClient *)_client;
3180 ba223c29 aliguori
3181 ba223c29 aliguori
    LIST_REMOVE(client, link);
3182 34d5e948 Isaku Yamahata
    qemu_free(client);
3183 ba223c29 aliguori
}
3184 ba223c29 aliguori
3185 ba223c29 aliguori
static void cpu_notify_map_clients(void)
3186 ba223c29 aliguori
{
3187 ba223c29 aliguori
    MapClient *client;
3188 ba223c29 aliguori
3189 ba223c29 aliguori
    while (!LIST_EMPTY(&map_client_list)) {
3190 ba223c29 aliguori
        client = LIST_FIRST(&map_client_list);
3191 ba223c29 aliguori
        client->callback(client->opaque);
3192 34d5e948 Isaku Yamahata
        cpu_unregister_map_client(client);
3193 ba223c29 aliguori
    }
3194 ba223c29 aliguori
}
3195 ba223c29 aliguori
3196 6d16c2f8 aliguori
/* Map a physical memory region into a host virtual address.
3197 6d16c2f8 aliguori
 * May map a subset of the requested range, given by and returned in *plen.
3198 6d16c2f8 aliguori
 * May return NULL if resources needed to perform the mapping are exhausted.
3199 6d16c2f8 aliguori
 * Use only for reads OR writes - not for read-modify-write operations.
3200 ba223c29 aliguori
 * Use cpu_register_map_client() to know when retrying the map operation is
3201 ba223c29 aliguori
 * likely to succeed.
3202 6d16c2f8 aliguori
 */
3203 6d16c2f8 aliguori
void *cpu_physical_memory_map(target_phys_addr_t addr,
3204 6d16c2f8 aliguori
                              target_phys_addr_t *plen,
3205 6d16c2f8 aliguori
                              int is_write)
3206 6d16c2f8 aliguori
{
3207 6d16c2f8 aliguori
    target_phys_addr_t len = *plen;
3208 6d16c2f8 aliguori
    target_phys_addr_t done = 0;
3209 6d16c2f8 aliguori
    int l;
3210 6d16c2f8 aliguori
    uint8_t *ret = NULL;
3211 6d16c2f8 aliguori
    uint8_t *ptr;
3212 6d16c2f8 aliguori
    target_phys_addr_t page;
3213 6d16c2f8 aliguori
    unsigned long pd;
3214 6d16c2f8 aliguori
    PhysPageDesc *p;
3215 6d16c2f8 aliguori
    unsigned long addr1;
3216 6d16c2f8 aliguori
3217 6d16c2f8 aliguori
    while (len > 0) {
3218 6d16c2f8 aliguori
        page = addr & TARGET_PAGE_MASK;
3219 6d16c2f8 aliguori
        l = (page + TARGET_PAGE_SIZE) - addr;
3220 6d16c2f8 aliguori
        if (l > len)
3221 6d16c2f8 aliguori
            l = len;
3222 6d16c2f8 aliguori
        p = phys_page_find(page >> TARGET_PAGE_BITS);
3223 6d16c2f8 aliguori
        if (!p) {
3224 6d16c2f8 aliguori
            pd = IO_MEM_UNASSIGNED;
3225 6d16c2f8 aliguori
        } else {
3226 6d16c2f8 aliguori
            pd = p->phys_offset;
3227 6d16c2f8 aliguori
        }
3228 6d16c2f8 aliguori
3229 6d16c2f8 aliguori
        if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3230 6d16c2f8 aliguori
            if (done || bounce.buffer) {
3231 6d16c2f8 aliguori
                break;
3232 6d16c2f8 aliguori
            }
3233 6d16c2f8 aliguori
            bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
3234 6d16c2f8 aliguori
            bounce.addr = addr;
3235 6d16c2f8 aliguori
            bounce.len = l;
3236 6d16c2f8 aliguori
            if (!is_write) {
3237 6d16c2f8 aliguori
                cpu_physical_memory_rw(addr, bounce.buffer, l, 0);
3238 6d16c2f8 aliguori
            }
3239 6d16c2f8 aliguori
            ptr = bounce.buffer;
3240 6d16c2f8 aliguori
        } else {
3241 6d16c2f8 aliguori
            addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3242 5579c7f3 pbrook
            ptr = qemu_get_ram_ptr(addr1);
3243 6d16c2f8 aliguori
        }
3244 6d16c2f8 aliguori
        if (!done) {
3245 6d16c2f8 aliguori
            ret = ptr;
3246 6d16c2f8 aliguori
        } else if (ret + done != ptr) {
3247 6d16c2f8 aliguori
            break;
3248 6d16c2f8 aliguori
        }
3249 6d16c2f8 aliguori
3250 6d16c2f8 aliguori
        len -= l;
3251 6d16c2f8 aliguori
        addr += l;
3252 6d16c2f8 aliguori
        done += l;
3253 6d16c2f8 aliguori
    }
3254 6d16c2f8 aliguori
    *plen = done;
3255 6d16c2f8 aliguori
    return ret;
3256 6d16c2f8 aliguori
}
3257 6d16c2f8 aliguori
3258 6d16c2f8 aliguori
/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
3259 6d16c2f8 aliguori
 * Will also mark the memory as dirty if is_write == 1.  access_len gives
3260 6d16c2f8 aliguori
 * the amount of memory that was actually read or written by the caller.
3261 6d16c2f8 aliguori
 */
3262 6d16c2f8 aliguori
void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
3263 6d16c2f8 aliguori
                               int is_write, target_phys_addr_t access_len)
3264 6d16c2f8 aliguori
{
3265 6d16c2f8 aliguori
    if (buffer != bounce.buffer) {
3266 6d16c2f8 aliguori
        if (is_write) {
3267 5579c7f3 pbrook
            ram_addr_t addr1 = qemu_ram_addr_from_host(buffer);
3268 6d16c2f8 aliguori
            while (access_len) {
3269 6d16c2f8 aliguori
                unsigned l;
3270 6d16c2f8 aliguori
                l = TARGET_PAGE_SIZE;
3271 6d16c2f8 aliguori
                if (l > access_len)
3272 6d16c2f8 aliguori
                    l = access_len;
3273 6d16c2f8 aliguori
                if (!cpu_physical_memory_is_dirty(addr1)) {
3274 6d16c2f8 aliguori
                    /* invalidate code */
3275 6d16c2f8 aliguori
                    tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
3276 6d16c2f8 aliguori
                    /* set dirty bit */
3277 6d16c2f8 aliguori
                    phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3278 6d16c2f8 aliguori
                        (0xff & ~CODE_DIRTY_FLAG);
3279 6d16c2f8 aliguori
                }
3280 6d16c2f8 aliguori
                addr1 += l;
3281 6d16c2f8 aliguori
                access_len -= l;
3282 6d16c2f8 aliguori
            }
3283 6d16c2f8 aliguori
        }
3284 6d16c2f8 aliguori
        return;
3285 6d16c2f8 aliguori
    }
3286 6d16c2f8 aliguori
    if (is_write) {
3287 6d16c2f8 aliguori
        cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
3288 6d16c2f8 aliguori
    }
3289 6d16c2f8 aliguori
    qemu_free(bounce.buffer);
3290 6d16c2f8 aliguori
    bounce.buffer = NULL;
3291 ba223c29 aliguori
    cpu_notify_map_clients();
3292 6d16c2f8 aliguori
}
3293 d0ecd2aa bellard
3294 8df1cd07 bellard
/* warning: addr must be aligned */
3295 8df1cd07 bellard
uint32_t ldl_phys(target_phys_addr_t addr)
3296 8df1cd07 bellard
{
3297 8df1cd07 bellard
    int io_index;
3298 8df1cd07 bellard
    uint8_t *ptr;
3299 8df1cd07 bellard
    uint32_t val;
3300 8df1cd07 bellard
    unsigned long pd;
3301 8df1cd07 bellard
    PhysPageDesc *p;
3302 8df1cd07 bellard
3303 8df1cd07 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
3304 8df1cd07 bellard
    if (!p) {
3305 8df1cd07 bellard
        pd = IO_MEM_UNASSIGNED;
3306 8df1cd07 bellard
    } else {
3307 8df1cd07 bellard
        pd = p->phys_offset;
3308 8df1cd07 bellard
    }
3309 3b46e624 ths
3310 5fafdf24 ths
    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3311 2a4188a3 bellard
        !(pd & IO_MEM_ROMD)) {
3312 8df1cd07 bellard
        /* I/O case */
3313 8df1cd07 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
3314 8da3ff18 pbrook
        if (p)
3315 8da3ff18 pbrook
            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3316 8df1cd07 bellard
        val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3317 8df1cd07 bellard
    } else {
3318 8df1cd07 bellard
        /* RAM case */
3319 5579c7f3 pbrook
        ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
3320 8df1cd07 bellard
            (addr & ~TARGET_PAGE_MASK);
3321 8df1cd07 bellard
        val = ldl_p(ptr);
3322 8df1cd07 bellard
    }
3323 8df1cd07 bellard
    return val;
3324 8df1cd07 bellard
}
3325 8df1cd07 bellard
3326 84b7b8e7 bellard
/* warning: addr must be aligned */
3327 84b7b8e7 bellard
uint64_t ldq_phys(target_phys_addr_t addr)
3328 84b7b8e7 bellard
{
3329 84b7b8e7 bellard
    int io_index;
3330 84b7b8e7 bellard
    uint8_t *ptr;
3331 84b7b8e7 bellard
    uint64_t val;
3332 84b7b8e7 bellard
    unsigned long pd;
3333 84b7b8e7 bellard
    PhysPageDesc *p;
3334 84b7b8e7 bellard
3335 84b7b8e7 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
3336 84b7b8e7 bellard
    if (!p) {
3337 84b7b8e7 bellard
        pd = IO_MEM_UNASSIGNED;
3338 84b7b8e7 bellard
    } else {
3339 84b7b8e7 bellard
        pd = p->phys_offset;
3340 84b7b8e7 bellard
    }
3341 3b46e624 ths
3342 2a4188a3 bellard
    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3343 2a4188a3 bellard
        !(pd & IO_MEM_ROMD)) {
3344 84b7b8e7 bellard
        /* I/O case */
3345 84b7b8e7 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
3346 8da3ff18 pbrook
        if (p)
3347 8da3ff18 pbrook
            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3348 84b7b8e7 bellard
#ifdef TARGET_WORDS_BIGENDIAN
3349 84b7b8e7 bellard
        val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
3350 84b7b8e7 bellard
        val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
3351 84b7b8e7 bellard
#else
3352 84b7b8e7 bellard
        val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3353 84b7b8e7 bellard
        val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
3354 84b7b8e7 bellard
#endif
3355 84b7b8e7 bellard
    } else {
3356 84b7b8e7 bellard
        /* RAM case */
3357 5579c7f3 pbrook
        ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
3358 84b7b8e7 bellard
            (addr & ~TARGET_PAGE_MASK);
3359 84b7b8e7 bellard
        val = ldq_p(ptr);
3360 84b7b8e7 bellard
    }
3361 84b7b8e7 bellard
    return val;
3362 84b7b8e7 bellard
}
3363 84b7b8e7 bellard
3364 aab33094 bellard
/* XXX: optimize */
3365 aab33094 bellard
uint32_t ldub_phys(target_phys_addr_t addr)
3366 aab33094 bellard
{
3367 aab33094 bellard
    uint8_t val;
3368 aab33094 bellard
    cpu_physical_memory_read(addr, &val, 1);
3369 aab33094 bellard
    return val;
3370 aab33094 bellard
}
3371 aab33094 bellard
3372 aab33094 bellard
/* XXX: optimize */
3373 aab33094 bellard
uint32_t lduw_phys(target_phys_addr_t addr)
3374 aab33094 bellard
{
3375 aab33094 bellard
    uint16_t val;
3376 aab33094 bellard
    cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
3377 aab33094 bellard
    return tswap16(val);
3378 aab33094 bellard
}
3379 aab33094 bellard
3380 8df1cd07 bellard
/* warning: addr must be aligned. The ram page is not masked as dirty
3381 8df1cd07 bellard
   and the code inside is not invalidated. It is useful if the dirty
3382 8df1cd07 bellard
   bits are used to track modified PTEs */
3383 8df1cd07 bellard
void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
3384 8df1cd07 bellard
{
3385 8df1cd07 bellard
    int io_index;
3386 8df1cd07 bellard
    uint8_t *ptr;
3387 8df1cd07 bellard
    unsigned long pd;
3388 8df1cd07 bellard
    PhysPageDesc *p;
3389 8df1cd07 bellard
3390 8df1cd07 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
3391 8df1cd07 bellard
    if (!p) {
3392 8df1cd07 bellard
        pd = IO_MEM_UNASSIGNED;
3393 8df1cd07 bellard
    } else {
3394 8df1cd07 bellard
        pd = p->phys_offset;
3395 8df1cd07 bellard
    }
3396 3b46e624 ths
3397 3a7d929e bellard
    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3398 8df1cd07 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
3399 8da3ff18 pbrook
        if (p)
3400 8da3ff18 pbrook
            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3401 8df1cd07 bellard
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3402 8df1cd07 bellard
    } else {
3403 74576198 aliguori
        unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3404 5579c7f3 pbrook
        ptr = qemu_get_ram_ptr(addr1);
3405 8df1cd07 bellard
        stl_p(ptr, val);
3406 74576198 aliguori
3407 74576198 aliguori
        if (unlikely(in_migration)) {
3408 74576198 aliguori
            if (!cpu_physical_memory_is_dirty(addr1)) {
3409 74576198 aliguori
                /* invalidate code */
3410 74576198 aliguori
                tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3411 74576198 aliguori
                /* set dirty bit */
3412 74576198 aliguori
                phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3413 74576198 aliguori
                    (0xff & ~CODE_DIRTY_FLAG);
3414 74576198 aliguori
            }
3415 74576198 aliguori
        }
3416 8df1cd07 bellard
    }
3417 8df1cd07 bellard
}
3418 8df1cd07 bellard
3419 bc98a7ef j_mayer
void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
3420 bc98a7ef j_mayer
{
3421 bc98a7ef j_mayer
    int io_index;
3422 bc98a7ef j_mayer
    uint8_t *ptr;
3423 bc98a7ef j_mayer
    unsigned long pd;
3424 bc98a7ef j_mayer
    PhysPageDesc *p;
3425 bc98a7ef j_mayer
3426 bc98a7ef j_mayer
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
3427 bc98a7ef j_mayer
    if (!p) {
3428 bc98a7ef j_mayer
        pd = IO_MEM_UNASSIGNED;
3429 bc98a7ef j_mayer
    } else {
3430 bc98a7ef j_mayer
        pd = p->phys_offset;
3431 bc98a7ef j_mayer
    }
3432 3b46e624 ths
3433 bc98a7ef j_mayer
    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3434 bc98a7ef j_mayer
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
3435 8da3ff18 pbrook
        if (p)
3436 8da3ff18 pbrook
            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3437 bc98a7ef j_mayer
#ifdef TARGET_WORDS_BIGENDIAN
3438 bc98a7ef j_mayer
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
3439 bc98a7ef j_mayer
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
3440 bc98a7ef j_mayer
#else
3441 bc98a7ef j_mayer
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3442 bc98a7ef j_mayer
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
3443 bc98a7ef j_mayer
#endif
3444 bc98a7ef j_mayer
    } else {
3445 5579c7f3 pbrook
        ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
3446 bc98a7ef j_mayer
            (addr & ~TARGET_PAGE_MASK);
3447 bc98a7ef j_mayer
        stq_p(ptr, val);
3448 bc98a7ef j_mayer
    }
3449 bc98a7ef j_mayer
}
3450 bc98a7ef j_mayer
3451 8df1cd07 bellard
/* warning: addr must be aligned */
3452 8df1cd07 bellard
void stl_phys(target_phys_addr_t addr, uint32_t val)
3453 8df1cd07 bellard
{
3454 8df1cd07 bellard
    int io_index;
3455 8df1cd07 bellard
    uint8_t *ptr;
3456 8df1cd07 bellard
    unsigned long pd;
3457 8df1cd07 bellard
    PhysPageDesc *p;
3458 8df1cd07 bellard
3459 8df1cd07 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
3460 8df1cd07 bellard
    if (!p) {
3461 8df1cd07 bellard
        pd = IO_MEM_UNASSIGNED;
3462 8df1cd07 bellard
    } else {
3463 8df1cd07 bellard
        pd = p->phys_offset;
3464 8df1cd07 bellard
    }
3465 3b46e624 ths
3466 3a7d929e bellard
    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3467 8df1cd07 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
3468 8da3ff18 pbrook
        if (p)
3469 8da3ff18 pbrook
            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3470 8df1cd07 bellard
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3471 8df1cd07 bellard
    } else {
3472 8df1cd07 bellard
        unsigned long addr1;
3473 8df1cd07 bellard
        addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3474 8df1cd07 bellard
        /* RAM case */
3475 5579c7f3 pbrook
        ptr = qemu_get_ram_ptr(addr1);
3476 8df1cd07 bellard
        stl_p(ptr, val);
3477 3a7d929e bellard
        if (!cpu_physical_memory_is_dirty(addr1)) {
3478 3a7d929e bellard
            /* invalidate code */
3479 3a7d929e bellard
            tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3480 3a7d929e bellard
            /* set dirty bit */
3481 f23db169 bellard
            phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3482 f23db169 bellard
                (0xff & ~CODE_DIRTY_FLAG);
3483 3a7d929e bellard
        }
3484 8df1cd07 bellard
    }
3485 8df1cd07 bellard
}
3486 8df1cd07 bellard
3487 aab33094 bellard
/* XXX: optimize */
3488 aab33094 bellard
void stb_phys(target_phys_addr_t addr, uint32_t val)
3489 aab33094 bellard
{
3490 aab33094 bellard
    uint8_t v = val;
3491 aab33094 bellard
    cpu_physical_memory_write(addr, &v, 1);
3492 aab33094 bellard
}
3493 aab33094 bellard
3494 aab33094 bellard
/* XXX: optimize */
3495 aab33094 bellard
void stw_phys(target_phys_addr_t addr, uint32_t val)
3496 aab33094 bellard
{
3497 aab33094 bellard
    uint16_t v = tswap16(val);
3498 aab33094 bellard
    cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
3499 aab33094 bellard
}
3500 aab33094 bellard
3501 aab33094 bellard
/* XXX: optimize */
3502 aab33094 bellard
void stq_phys(target_phys_addr_t addr, uint64_t val)
3503 aab33094 bellard
{
3504 aab33094 bellard
    val = tswap64(val);
3505 aab33094 bellard
    cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
3506 aab33094 bellard
}
3507 aab33094 bellard
3508 13eb76e0 bellard
#endif
3509 13eb76e0 bellard
3510 5e2972fd aliguori
/* virtual memory access for debug (includes writing to ROM) */
3511 5fafdf24 ths
int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
3512 b448f2f3 bellard
                        uint8_t *buf, int len, int is_write)
3513 13eb76e0 bellard
{
3514 13eb76e0 bellard
    int l;
3515 9b3c35e0 j_mayer
    target_phys_addr_t phys_addr;
3516 9b3c35e0 j_mayer
    target_ulong page;
3517 13eb76e0 bellard
3518 13eb76e0 bellard
    while (len > 0) {
3519 13eb76e0 bellard
        page = addr & TARGET_PAGE_MASK;
3520 13eb76e0 bellard
        phys_addr = cpu_get_phys_page_debug(env, page);
3521 13eb76e0 bellard
        /* if no physical page mapped, return an error */
3522 13eb76e0 bellard
        if (phys_addr == -1)
3523 13eb76e0 bellard
            return -1;
3524 13eb76e0 bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
3525 13eb76e0 bellard
        if (l > len)
3526 13eb76e0 bellard
            l = len;
3527 5e2972fd aliguori
        phys_addr += (addr & ~TARGET_PAGE_MASK);
3528 5e2972fd aliguori
#if !defined(CONFIG_USER_ONLY)
3529 5e2972fd aliguori
        if (is_write)
3530 5e2972fd aliguori
            cpu_physical_memory_write_rom(phys_addr, buf, l);
3531 5e2972fd aliguori
        else
3532 5e2972fd aliguori
#endif
3533 5e2972fd aliguori
            cpu_physical_memory_rw(phys_addr, buf, l, is_write);
3534 13eb76e0 bellard
        len -= l;
3535 13eb76e0 bellard
        buf += l;
3536 13eb76e0 bellard
        addr += l;
3537 13eb76e0 bellard
    }
3538 13eb76e0 bellard
    return 0;
3539 13eb76e0 bellard
}
3540 13eb76e0 bellard
3541 2e70f6ef pbrook
/* in deterministic execution mode, instructions doing device I/Os
3542 2e70f6ef pbrook
   must be at the end of the TB */
3543 2e70f6ef pbrook
void cpu_io_recompile(CPUState *env, void *retaddr)
3544 2e70f6ef pbrook
{
3545 2e70f6ef pbrook
    TranslationBlock *tb;
3546 2e70f6ef pbrook
    uint32_t n, cflags;
3547 2e70f6ef pbrook
    target_ulong pc, cs_base;
3548 2e70f6ef pbrook
    uint64_t flags;
3549 2e70f6ef pbrook
3550 2e70f6ef pbrook
    tb = tb_find_pc((unsigned long)retaddr);
3551 2e70f6ef pbrook
    if (!tb) {
3552 2e70f6ef pbrook
        cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p", 
3553 2e70f6ef pbrook
                  retaddr);
3554 2e70f6ef pbrook
    }
3555 2e70f6ef pbrook
    n = env->icount_decr.u16.low + tb->icount;
3556 2e70f6ef pbrook
    cpu_restore_state(tb, env, (unsigned long)retaddr, NULL);
3557 2e70f6ef pbrook
    /* Calculate how many instructions had been executed before the fault
3558 bf20dc07 ths
       occurred.  */
3559 2e70f6ef pbrook
    n = n - env->icount_decr.u16.low;
3560 2e70f6ef pbrook
    /* Generate a new TB ending on the I/O insn.  */
3561 2e70f6ef pbrook
    n++;
3562 2e70f6ef pbrook
    /* On MIPS and SH, delay slot instructions can only be restarted if
3563 2e70f6ef pbrook
       they were already the first instruction in the TB.  If this is not
3564 bf20dc07 ths
       the first instruction in a TB then re-execute the preceding
3565 2e70f6ef pbrook
       branch.  */
3566 2e70f6ef pbrook
#if defined(TARGET_MIPS)
3567 2e70f6ef pbrook
    if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) {
3568 2e70f6ef pbrook
        env->active_tc.PC -= 4;
3569 2e70f6ef pbrook
        env->icount_decr.u16.low++;
3570 2e70f6ef pbrook
        env->hflags &= ~MIPS_HFLAG_BMASK;
3571 2e70f6ef pbrook
    }
3572 2e70f6ef pbrook
#elif defined(TARGET_SH4)
3573 2e70f6ef pbrook
    if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
3574 2e70f6ef pbrook
            && n > 1) {
3575 2e70f6ef pbrook
        env->pc -= 2;
3576 2e70f6ef pbrook
        env->icount_decr.u16.low++;
3577 2e70f6ef pbrook
        env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
3578 2e70f6ef pbrook
    }
3579 2e70f6ef pbrook
#endif
3580 2e70f6ef pbrook
    /* This should never happen.  */
3581 2e70f6ef pbrook
    if (n > CF_COUNT_MASK)
3582 2e70f6ef pbrook
        cpu_abort(env, "TB too big during recompile");
3583 2e70f6ef pbrook
3584 2e70f6ef pbrook
    cflags = n | CF_LAST_IO;
3585 2e70f6ef pbrook
    pc = tb->pc;
3586 2e70f6ef pbrook
    cs_base = tb->cs_base;
3587 2e70f6ef pbrook
    flags = tb->flags;
3588 2e70f6ef pbrook
    tb_phys_invalidate(tb, -1);
3589 2e70f6ef pbrook
    /* FIXME: In theory this could raise an exception.  In practice
3590 2e70f6ef pbrook
       we have already translated the block once so it's probably ok.  */
3591 2e70f6ef pbrook
    tb_gen_code(env, pc, cs_base, flags, cflags);
3592 bf20dc07 ths
    /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
3593 2e70f6ef pbrook
       the first in the TB) then we end up generating a whole new TB and
3594 2e70f6ef pbrook
       repeating the fault, which is horribly inefficient.
3595 2e70f6ef pbrook
       Better would be to execute just this insn uncached, or generate a
3596 2e70f6ef pbrook
       second new TB.  */
3597 2e70f6ef pbrook
    cpu_resume_from_signal(env, NULL);
3598 2e70f6ef pbrook
}
3599 2e70f6ef pbrook
3600 e3db7226 bellard
void dump_exec_info(FILE *f,
3601 e3db7226 bellard
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
3602 e3db7226 bellard
{
3603 e3db7226 bellard
    int i, target_code_size, max_target_code_size;
3604 e3db7226 bellard
    int direct_jmp_count, direct_jmp2_count, cross_page;
3605 e3db7226 bellard
    TranslationBlock *tb;
3606 3b46e624 ths
3607 e3db7226 bellard
    target_code_size = 0;
3608 e3db7226 bellard
    max_target_code_size = 0;
3609 e3db7226 bellard
    cross_page = 0;
3610 e3db7226 bellard
    direct_jmp_count = 0;
3611 e3db7226 bellard
    direct_jmp2_count = 0;
3612 e3db7226 bellard
    for(i = 0; i < nb_tbs; i++) {
3613 e3db7226 bellard
        tb = &tbs[i];
3614 e3db7226 bellard
        target_code_size += tb->size;
3615 e3db7226 bellard
        if (tb->size > max_target_code_size)
3616 e3db7226 bellard
            max_target_code_size = tb->size;
3617 e3db7226 bellard
        if (tb->page_addr[1] != -1)
3618 e3db7226 bellard
            cross_page++;
3619 e3db7226 bellard
        if (tb->tb_next_offset[0] != 0xffff) {
3620 e3db7226 bellard
            direct_jmp_count++;
3621 e3db7226 bellard
            if (tb->tb_next_offset[1] != 0xffff) {
3622 e3db7226 bellard
                direct_jmp2_count++;
3623 e3db7226 bellard
            }
3624 e3db7226 bellard
        }
3625 e3db7226 bellard
    }
3626 e3db7226 bellard
    /* XXX: avoid using doubles ? */
3627 57fec1fe bellard
    cpu_fprintf(f, "Translation buffer state:\n");
3628 26a5f13b bellard
    cpu_fprintf(f, "gen code size       %ld/%ld\n",
3629 26a5f13b bellard
                code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size);
3630 26a5f13b bellard
    cpu_fprintf(f, "TB count            %d/%d\n", 
3631 26a5f13b bellard
                nb_tbs, code_gen_max_blocks);
3632 5fafdf24 ths
    cpu_fprintf(f, "TB avg target size  %d max=%d bytes\n",
3633 e3db7226 bellard
                nb_tbs ? target_code_size / nb_tbs : 0,
3634 e3db7226 bellard
                max_target_code_size);
3635 5fafdf24 ths
    cpu_fprintf(f, "TB avg host size    %d bytes (expansion ratio: %0.1f)\n",
3636 e3db7226 bellard
                nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
3637 e3db7226 bellard
                target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
3638 5fafdf24 ths
    cpu_fprintf(f, "cross page TB count %d (%d%%)\n",
3639 5fafdf24 ths
            cross_page,
3640 e3db7226 bellard
            nb_tbs ? (cross_page * 100) / nb_tbs : 0);
3641 e3db7226 bellard
    cpu_fprintf(f, "direct jump count   %d (%d%%) (2 jumps=%d %d%%)\n",
3642 5fafdf24 ths
                direct_jmp_count,
3643 e3db7226 bellard
                nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
3644 e3db7226 bellard
                direct_jmp2_count,
3645 e3db7226 bellard
                nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
3646 57fec1fe bellard
    cpu_fprintf(f, "\nStatistics:\n");
3647 e3db7226 bellard
    cpu_fprintf(f, "TB flush count      %d\n", tb_flush_count);
3648 e3db7226 bellard
    cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
3649 e3db7226 bellard
    cpu_fprintf(f, "TLB flush count     %d\n", tlb_flush_count);
3650 b67d9a52 bellard
    tcg_dump_info(f, cpu_fprintf);
3651 e3db7226 bellard
}
3652 e3db7226 bellard
3653 5fafdf24 ths
#if !defined(CONFIG_USER_ONLY)
3654 61382a50 bellard
3655 61382a50 bellard
#define MMUSUFFIX _cmmu
3656 61382a50 bellard
#define GETPC() NULL
3657 61382a50 bellard
#define env cpu_single_env
3658 b769d8fe bellard
#define SOFTMMU_CODE_ACCESS
3659 61382a50 bellard
3660 61382a50 bellard
#define SHIFT 0
3661 61382a50 bellard
#include "softmmu_template.h"
3662 61382a50 bellard
3663 61382a50 bellard
#define SHIFT 1
3664 61382a50 bellard
#include "softmmu_template.h"
3665 61382a50 bellard
3666 61382a50 bellard
#define SHIFT 2
3667 61382a50 bellard
#include "softmmu_template.h"
3668 61382a50 bellard
3669 61382a50 bellard
#define SHIFT 3
3670 61382a50 bellard
#include "softmmu_template.h"
3671 61382a50 bellard
3672 61382a50 bellard
#undef env
3673 61382a50 bellard
3674 61382a50 bellard
#endif