Statistics
| Branch: | Revision:

root / exec.c @ d656469f

History | View | Annotate | Download (88.5 kB)

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