Statistics
| Branch: | Revision:

root / exec.c @ 40d0591e

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