Statistics
| Branch: | Revision:

root / exec.c @ ce62e5ba

History | View | Annotate | Download (86.2 kB)

1 54936004 bellard
/*
2 fd6ce8f6 bellard
 *  virtual page mapping and translated block handling
3 54936004 bellard
 * 
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 fd6ce8f6 bellard
//#define DEBUG_TB_CHECK 
48 98857888 bellard
//#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 6a00d601 bellard
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 d5a8f07c bellard
        
179 d5a8f07c bellard
        GetSystemInfo(&system_info);
180 d5a8f07c bellard
        qemu_real_host_page_size = system_info.dwPageSize;
181 d5a8f07c bellard
        
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 d5a8f07c bellard
        
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 d5a8f07c bellard
        
197 d5a8f07c bellard
        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 3a7d929e bellard
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 fd6ce8f6 bellard
    printf("qemu: flush code_size=%d nb_tbs=%d avg_tb_size=%d\n", 
343 fd6ce8f6 bellard
           code_gen_ptr - code_gen_buffer, 
344 fd6ce8f6 bellard
           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 6a00d601 bellard
    
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 fd6ce8f6 bellard
    
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 d4e8164f bellard
    
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 8a40a180 bellard
    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 9fa3e853 bellard
    
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 d720b93d bellard
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 d720b93d bellard
    
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 d720b93d bellard
    
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 d720b93d bellard
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 9fa3e853 bellard
    if (!p) 
655 9fa3e853 bellard
        return;
656 9fa3e853 bellard
    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 d720b93d bellard
                
704 d720b93d bellard
                current_tb_modified = 1;
705 d720b93d bellard
                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 d720b93d bellard
        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 a4193c8a bellard
            fprintf(logfile, "modifying code at 0x%x size=%d EIP=%x PC=%08x\n", 
764 a4193c8a bellard
                   cpu_single_env->mem_write_vaddr, len, 
765 a4193c8a bellard
                   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 9fa3e853 bellard
    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 d720b93d bellard
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 9fa3e853 bellard
    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 d720b93d bellard
            
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 d720b93d bellard
        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 9fa3e853 bellard
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 53a5960a pbrook
        mprotect(g2h(page_addr), qemu_host_page_size, 
890 fd6ce8f6 bellard
                 (prot & PAGE_BITS) & ~PAGE_WRITE);
891 fd6ce8f6 bellard
#ifdef DEBUG_TB_INVALIDATE
892 fd6ce8f6 bellard
        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 fd6ce8f6 bellard
    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 9fa3e853 bellard
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 a513fe19 bellard
    } 
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 ea041c0e bellard
        
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 d720b93d bellard
    
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 d720b93d bellard
    
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 f193c797 bellard
    { 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 f193c797 bellard
    { 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 f193c797 bellard
      
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 7fe48483 bellard
    cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1296 7fe48483 bellard
#else
1297 7fe48483 bellard
    cpu_dump_state(env, stderr, fprintf, 0);
1298 7501267e bellard
#endif
1299 7501267e bellard
    va_end(ap);
1300 924edcae balrog
    if (logfile) {
1301 924edcae balrog
        fflush(logfile);
1302 924edcae balrog
        fclose(logfile);
1303 924edcae balrog
    }
1304 7501267e bellard
    abort();
1305 7501267e bellard
}
1306 7501267e bellard
1307 c5be9f08 ths
CPUState *cpu_copy(CPUState *env)
1308 c5be9f08 ths
{
1309 c5be9f08 ths
    CPUState *new_env = cpu_init();
1310 c5be9f08 ths
    /* preserve chaining and index */
1311 c5be9f08 ths
    CPUState *next_cpu = new_env->next_cpu;
1312 c5be9f08 ths
    int cpu_index = new_env->cpu_index;
1313 c5be9f08 ths
    memcpy(new_env, env, sizeof(CPUState));
1314 c5be9f08 ths
    new_env->next_cpu = next_cpu;
1315 c5be9f08 ths
    new_env->cpu_index = cpu_index;
1316 c5be9f08 ths
    return new_env;
1317 c5be9f08 ths
}
1318 c5be9f08 ths
1319 0124311e bellard
#if !defined(CONFIG_USER_ONLY)
1320 0124311e bellard
1321 ee8b7021 bellard
/* NOTE: if flush_global is true, also flush global entries (not
1322 ee8b7021 bellard
   implemented yet) */
1323 ee8b7021 bellard
void tlb_flush(CPUState *env, int flush_global)
1324 33417e70 bellard
{
1325 33417e70 bellard
    int i;
1326 0124311e bellard
1327 9fa3e853 bellard
#if defined(DEBUG_TLB)
1328 9fa3e853 bellard
    printf("tlb_flush:\n");
1329 9fa3e853 bellard
#endif
1330 0124311e bellard
    /* must reset current TB so that interrupts cannot modify the
1331 0124311e bellard
       links while we are modifying them */
1332 0124311e bellard
    env->current_tb = NULL;
1333 0124311e bellard
1334 33417e70 bellard
    for(i = 0; i < CPU_TLB_SIZE; i++) {
1335 84b7b8e7 bellard
        env->tlb_table[0][i].addr_read = -1;
1336 84b7b8e7 bellard
        env->tlb_table[0][i].addr_write = -1;
1337 84b7b8e7 bellard
        env->tlb_table[0][i].addr_code = -1;
1338 84b7b8e7 bellard
        env->tlb_table[1][i].addr_read = -1;
1339 84b7b8e7 bellard
        env->tlb_table[1][i].addr_write = -1;
1340 84b7b8e7 bellard
        env->tlb_table[1][i].addr_code = -1;
1341 6fa4cea9 j_mayer
#if (NB_MMU_MODES >= 3)
1342 6fa4cea9 j_mayer
        env->tlb_table[2][i].addr_read = -1;
1343 6fa4cea9 j_mayer
        env->tlb_table[2][i].addr_write = -1;
1344 6fa4cea9 j_mayer
        env->tlb_table[2][i].addr_code = -1;
1345 6fa4cea9 j_mayer
#if (NB_MMU_MODES == 4)
1346 6fa4cea9 j_mayer
        env->tlb_table[3][i].addr_read = -1;
1347 6fa4cea9 j_mayer
        env->tlb_table[3][i].addr_write = -1;
1348 6fa4cea9 j_mayer
        env->tlb_table[3][i].addr_code = -1;
1349 6fa4cea9 j_mayer
#endif
1350 6fa4cea9 j_mayer
#endif
1351 33417e70 bellard
    }
1352 9fa3e853 bellard
1353 8a40a180 bellard
    memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
1354 9fa3e853 bellard
1355 9fa3e853 bellard
#if !defined(CONFIG_SOFTMMU)
1356 9fa3e853 bellard
    munmap((void *)MMAP_AREA_START, MMAP_AREA_END - MMAP_AREA_START);
1357 9fa3e853 bellard
#endif
1358 0a962c02 bellard
#ifdef USE_KQEMU
1359 0a962c02 bellard
    if (env->kqemu_enabled) {
1360 0a962c02 bellard
        kqemu_flush(env, flush_global);
1361 0a962c02 bellard
    }
1362 0a962c02 bellard
#endif
1363 e3db7226 bellard
    tlb_flush_count++;
1364 33417e70 bellard
}
1365 33417e70 bellard
1366 274da6b2 bellard
static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
1367 61382a50 bellard
{
1368 84b7b8e7 bellard
    if (addr == (tlb_entry->addr_read & 
1369 84b7b8e7 bellard
                 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1370 84b7b8e7 bellard
        addr == (tlb_entry->addr_write & 
1371 84b7b8e7 bellard
                 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1372 84b7b8e7 bellard
        addr == (tlb_entry->addr_code & 
1373 84b7b8e7 bellard
                 (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1374 84b7b8e7 bellard
        tlb_entry->addr_read = -1;
1375 84b7b8e7 bellard
        tlb_entry->addr_write = -1;
1376 84b7b8e7 bellard
        tlb_entry->addr_code = -1;
1377 84b7b8e7 bellard
    }
1378 61382a50 bellard
}
1379 61382a50 bellard
1380 2e12669a bellard
void tlb_flush_page(CPUState *env, target_ulong addr)
1381 33417e70 bellard
{
1382 8a40a180 bellard
    int i;
1383 9fa3e853 bellard
    TranslationBlock *tb;
1384 0124311e bellard
1385 9fa3e853 bellard
#if defined(DEBUG_TLB)
1386 108c49b8 bellard
    printf("tlb_flush_page: " TARGET_FMT_lx "\n", addr);
1387 9fa3e853 bellard
#endif
1388 0124311e bellard
    /* must reset current TB so that interrupts cannot modify the
1389 0124311e bellard
       links while we are modifying them */
1390 0124311e bellard
    env->current_tb = NULL;
1391 61382a50 bellard
1392 61382a50 bellard
    addr &= TARGET_PAGE_MASK;
1393 61382a50 bellard
    i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1394 84b7b8e7 bellard
    tlb_flush_entry(&env->tlb_table[0][i], addr);
1395 84b7b8e7 bellard
    tlb_flush_entry(&env->tlb_table[1][i], addr);
1396 6fa4cea9 j_mayer
#if (NB_MMU_MODES >= 3)
1397 6fa4cea9 j_mayer
    tlb_flush_entry(&env->tlb_table[2][i], addr);
1398 6fa4cea9 j_mayer
#if (NB_MMU_MODES == 4)
1399 6fa4cea9 j_mayer
    tlb_flush_entry(&env->tlb_table[3][i], addr);
1400 6fa4cea9 j_mayer
#endif
1401 6fa4cea9 j_mayer
#endif
1402 0124311e bellard
1403 b362e5e0 pbrook
    /* Discard jump cache entries for any tb which might potentially
1404 b362e5e0 pbrook
       overlap the flushed page.  */
1405 b362e5e0 pbrook
    i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
1406 b362e5e0 pbrook
    memset (&env->tb_jmp_cache[i], 0, TB_JMP_PAGE_SIZE * sizeof(tb));
1407 b362e5e0 pbrook
1408 b362e5e0 pbrook
    i = tb_jmp_cache_hash_page(addr);
1409 b362e5e0 pbrook
    memset (&env->tb_jmp_cache[i], 0, TB_JMP_PAGE_SIZE * sizeof(tb));
1410 9fa3e853 bellard
1411 0124311e bellard
#if !defined(CONFIG_SOFTMMU)
1412 9fa3e853 bellard
    if (addr < MMAP_AREA_END)
1413 0124311e bellard
        munmap((void *)addr, TARGET_PAGE_SIZE);
1414 61382a50 bellard
#endif
1415 0a962c02 bellard
#ifdef USE_KQEMU
1416 0a962c02 bellard
    if (env->kqemu_enabled) {
1417 0a962c02 bellard
        kqemu_flush_page(env, addr);
1418 0a962c02 bellard
    }
1419 0a962c02 bellard
#endif
1420 9fa3e853 bellard
}
1421 9fa3e853 bellard
1422 9fa3e853 bellard
/* update the TLBs so that writes to code in the virtual page 'addr'
1423 9fa3e853 bellard
   can be detected */
1424 6a00d601 bellard
static void tlb_protect_code(ram_addr_t ram_addr)
1425 9fa3e853 bellard
{
1426 6a00d601 bellard
    cpu_physical_memory_reset_dirty(ram_addr, 
1427 6a00d601 bellard
                                    ram_addr + TARGET_PAGE_SIZE,
1428 6a00d601 bellard
                                    CODE_DIRTY_FLAG);
1429 9fa3e853 bellard
}
1430 9fa3e853 bellard
1431 9fa3e853 bellard
/* update the TLB so that writes in physical page 'phys_addr' are no longer
1432 3a7d929e bellard
   tested for self modifying code */
1433 3a7d929e bellard
static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr, 
1434 3a7d929e bellard
                                    target_ulong vaddr)
1435 9fa3e853 bellard
{
1436 3a7d929e bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] |= CODE_DIRTY_FLAG;
1437 1ccde1cb bellard
}
1438 1ccde1cb bellard
1439 1ccde1cb bellard
static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, 
1440 1ccde1cb bellard
                                         unsigned long start, unsigned long length)
1441 1ccde1cb bellard
{
1442 1ccde1cb bellard
    unsigned long addr;
1443 84b7b8e7 bellard
    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1444 84b7b8e7 bellard
        addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
1445 1ccde1cb bellard
        if ((addr - start) < length) {
1446 84b7b8e7 bellard
            tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | IO_MEM_NOTDIRTY;
1447 1ccde1cb bellard
        }
1448 1ccde1cb bellard
    }
1449 1ccde1cb bellard
}
1450 1ccde1cb bellard
1451 3a7d929e bellard
void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
1452 0a962c02 bellard
                                     int dirty_flags)
1453 1ccde1cb bellard
{
1454 1ccde1cb bellard
    CPUState *env;
1455 4f2ac237 bellard
    unsigned long length, start1;
1456 0a962c02 bellard
    int i, mask, len;
1457 0a962c02 bellard
    uint8_t *p;
1458 1ccde1cb bellard
1459 1ccde1cb bellard
    start &= TARGET_PAGE_MASK;
1460 1ccde1cb bellard
    end = TARGET_PAGE_ALIGN(end);
1461 1ccde1cb bellard
1462 1ccde1cb bellard
    length = end - start;
1463 1ccde1cb bellard
    if (length == 0)
1464 1ccde1cb bellard
        return;
1465 0a962c02 bellard
    len = length >> TARGET_PAGE_BITS;
1466 3a7d929e bellard
#ifdef USE_KQEMU
1467 6a00d601 bellard
    /* XXX: should not depend on cpu context */
1468 6a00d601 bellard
    env = first_cpu;
1469 3a7d929e bellard
    if (env->kqemu_enabled) {
1470 f23db169 bellard
        ram_addr_t addr;
1471 f23db169 bellard
        addr = start;
1472 f23db169 bellard
        for(i = 0; i < len; i++) {
1473 f23db169 bellard
            kqemu_set_notdirty(env, addr);
1474 f23db169 bellard
            addr += TARGET_PAGE_SIZE;
1475 f23db169 bellard
        }
1476 3a7d929e bellard
    }
1477 3a7d929e bellard
#endif
1478 f23db169 bellard
    mask = ~dirty_flags;
1479 f23db169 bellard
    p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
1480 f23db169 bellard
    for(i = 0; i < len; i++)
1481 f23db169 bellard
        p[i] &= mask;
1482 f23db169 bellard
1483 1ccde1cb bellard
    /* we modify the TLB cache so that the dirty bit will be set again
1484 1ccde1cb bellard
       when accessing the range */
1485 59817ccb bellard
    start1 = start + (unsigned long)phys_ram_base;
1486 6a00d601 bellard
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
1487 6a00d601 bellard
        for(i = 0; i < CPU_TLB_SIZE; i++)
1488 84b7b8e7 bellard
            tlb_reset_dirty_range(&env->tlb_table[0][i], start1, length);
1489 6a00d601 bellard
        for(i = 0; i < CPU_TLB_SIZE; i++)
1490 84b7b8e7 bellard
            tlb_reset_dirty_range(&env->tlb_table[1][i], start1, length);
1491 6fa4cea9 j_mayer
#if (NB_MMU_MODES >= 3)
1492 6fa4cea9 j_mayer
        for(i = 0; i < CPU_TLB_SIZE; i++)
1493 6fa4cea9 j_mayer
            tlb_reset_dirty_range(&env->tlb_table[2][i], start1, length);
1494 6fa4cea9 j_mayer
#if (NB_MMU_MODES == 4)
1495 6fa4cea9 j_mayer
        for(i = 0; i < CPU_TLB_SIZE; i++)
1496 6fa4cea9 j_mayer
            tlb_reset_dirty_range(&env->tlb_table[3][i], start1, length);
1497 6fa4cea9 j_mayer
#endif
1498 6fa4cea9 j_mayer
#endif
1499 6a00d601 bellard
    }
1500 59817ccb bellard
1501 59817ccb bellard
#if !defined(CONFIG_SOFTMMU)
1502 59817ccb bellard
    /* XXX: this is expensive */
1503 59817ccb bellard
    {
1504 59817ccb bellard
        VirtPageDesc *p;
1505 59817ccb bellard
        int j;
1506 59817ccb bellard
        target_ulong addr;
1507 59817ccb bellard
1508 59817ccb bellard
        for(i = 0; i < L1_SIZE; i++) {
1509 59817ccb bellard
            p = l1_virt_map[i];
1510 59817ccb bellard
            if (p) {
1511 59817ccb bellard
                addr = i << (TARGET_PAGE_BITS + L2_BITS);
1512 59817ccb bellard
                for(j = 0; j < L2_SIZE; j++) {
1513 59817ccb bellard
                    if (p->valid_tag == virt_valid_tag &&
1514 59817ccb bellard
                        p->phys_addr >= start && p->phys_addr < end &&
1515 59817ccb bellard
                        (p->prot & PROT_WRITE)) {
1516 59817ccb bellard
                        if (addr < MMAP_AREA_END) {
1517 59817ccb bellard
                            mprotect((void *)addr, TARGET_PAGE_SIZE, 
1518 59817ccb bellard
                                     p->prot & ~PROT_WRITE);
1519 59817ccb bellard
                        }
1520 59817ccb bellard
                    }
1521 59817ccb bellard
                    addr += TARGET_PAGE_SIZE;
1522 59817ccb bellard
                    p++;
1523 59817ccb bellard
                }
1524 59817ccb bellard
            }
1525 59817ccb bellard
        }
1526 59817ccb bellard
    }
1527 59817ccb bellard
#endif
1528 1ccde1cb bellard
}
1529 1ccde1cb bellard
1530 3a7d929e bellard
static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1531 3a7d929e bellard
{
1532 3a7d929e bellard
    ram_addr_t ram_addr;
1533 3a7d929e bellard
1534 84b7b8e7 bellard
    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1535 84b7b8e7 bellard
        ram_addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + 
1536 3a7d929e bellard
            tlb_entry->addend - (unsigned long)phys_ram_base;
1537 3a7d929e bellard
        if (!cpu_physical_memory_is_dirty(ram_addr)) {
1538 84b7b8e7 bellard
            tlb_entry->addr_write |= IO_MEM_NOTDIRTY;
1539 3a7d929e bellard
        }
1540 3a7d929e bellard
    }
1541 3a7d929e bellard
}
1542 3a7d929e bellard
1543 3a7d929e bellard
/* update the TLB according to the current state of the dirty bits */
1544 3a7d929e bellard
void cpu_tlb_update_dirty(CPUState *env)
1545 3a7d929e bellard
{
1546 3a7d929e bellard
    int i;
1547 3a7d929e bellard
    for(i = 0; i < CPU_TLB_SIZE; i++)
1548 84b7b8e7 bellard
        tlb_update_dirty(&env->tlb_table[0][i]);
1549 3a7d929e bellard
    for(i = 0; i < CPU_TLB_SIZE; i++)
1550 84b7b8e7 bellard
        tlb_update_dirty(&env->tlb_table[1][i]);
1551 6fa4cea9 j_mayer
#if (NB_MMU_MODES >= 3)
1552 6fa4cea9 j_mayer
    for(i = 0; i < CPU_TLB_SIZE; i++)
1553 6fa4cea9 j_mayer
        tlb_update_dirty(&env->tlb_table[2][i]);
1554 6fa4cea9 j_mayer
#if (NB_MMU_MODES == 4)
1555 6fa4cea9 j_mayer
    for(i = 0; i < CPU_TLB_SIZE; i++)
1556 6fa4cea9 j_mayer
        tlb_update_dirty(&env->tlb_table[3][i]);
1557 6fa4cea9 j_mayer
#endif
1558 6fa4cea9 j_mayer
#endif
1559 3a7d929e bellard
}
1560 3a7d929e bellard
1561 1ccde1cb bellard
static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, 
1562 108c49b8 bellard
                                  unsigned long start)
1563 1ccde1cb bellard
{
1564 1ccde1cb bellard
    unsigned long addr;
1565 84b7b8e7 bellard
    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_NOTDIRTY) {
1566 84b7b8e7 bellard
        addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
1567 1ccde1cb bellard
        if (addr == start) {
1568 84b7b8e7 bellard
            tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | IO_MEM_RAM;
1569 1ccde1cb bellard
        }
1570 1ccde1cb bellard
    }
1571 1ccde1cb bellard
}
1572 1ccde1cb bellard
1573 1ccde1cb bellard
/* update the TLB corresponding to virtual page vaddr and phys addr
1574 1ccde1cb bellard
   addr so that it is no longer dirty */
1575 6a00d601 bellard
static inline void tlb_set_dirty(CPUState *env,
1576 6a00d601 bellard
                                 unsigned long addr, target_ulong vaddr)
1577 1ccde1cb bellard
{
1578 1ccde1cb bellard
    int i;
1579 1ccde1cb bellard
1580 1ccde1cb bellard
    addr &= TARGET_PAGE_MASK;
1581 1ccde1cb bellard
    i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1582 84b7b8e7 bellard
    tlb_set_dirty1(&env->tlb_table[0][i], addr);
1583 84b7b8e7 bellard
    tlb_set_dirty1(&env->tlb_table[1][i], addr);
1584 6fa4cea9 j_mayer
#if (NB_MMU_MODES >= 3)
1585 6fa4cea9 j_mayer
    tlb_set_dirty1(&env->tlb_table[2][i], addr);
1586 6fa4cea9 j_mayer
#if (NB_MMU_MODES == 4)
1587 6fa4cea9 j_mayer
    tlb_set_dirty1(&env->tlb_table[3][i], addr);
1588 6fa4cea9 j_mayer
#endif
1589 6fa4cea9 j_mayer
#endif
1590 9fa3e853 bellard
}
1591 9fa3e853 bellard
1592 59817ccb bellard
/* add a new TLB entry. At most one entry for a given virtual address
1593 59817ccb bellard
   is permitted. Return 0 if OK or 2 if the page could not be mapped
1594 59817ccb bellard
   (can only happen in non SOFTMMU mode for I/O pages or pages
1595 59817ccb bellard
   conflicting with the host address space). */
1596 84b7b8e7 bellard
int tlb_set_page_exec(CPUState *env, target_ulong vaddr, 
1597 84b7b8e7 bellard
                      target_phys_addr_t paddr, int prot, 
1598 84b7b8e7 bellard
                      int is_user, int is_softmmu)
1599 9fa3e853 bellard
{
1600 92e873b9 bellard
    PhysPageDesc *p;
1601 4f2ac237 bellard
    unsigned long pd;
1602 9fa3e853 bellard
    unsigned int index;
1603 4f2ac237 bellard
    target_ulong address;
1604 108c49b8 bellard
    target_phys_addr_t addend;
1605 9fa3e853 bellard
    int ret;
1606 84b7b8e7 bellard
    CPUTLBEntry *te;
1607 6658ffb8 pbrook
    int i;
1608 9fa3e853 bellard
1609 92e873b9 bellard
    p = phys_page_find(paddr >> TARGET_PAGE_BITS);
1610 9fa3e853 bellard
    if (!p) {
1611 9fa3e853 bellard
        pd = IO_MEM_UNASSIGNED;
1612 9fa3e853 bellard
    } else {
1613 9fa3e853 bellard
        pd = p->phys_offset;
1614 9fa3e853 bellard
    }
1615 9fa3e853 bellard
#if defined(DEBUG_TLB)
1616 3a7d929e bellard
    printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x u=%d smmu=%d pd=0x%08lx\n",
1617 84b7b8e7 bellard
           vaddr, (int)paddr, prot, is_user, is_softmmu, pd);
1618 9fa3e853 bellard
#endif
1619 9fa3e853 bellard
1620 9fa3e853 bellard
    ret = 0;
1621 9fa3e853 bellard
#if !defined(CONFIG_SOFTMMU)
1622 9fa3e853 bellard
    if (is_softmmu) 
1623 9fa3e853 bellard
#endif
1624 9fa3e853 bellard
    {
1625 2a4188a3 bellard
        if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
1626 9fa3e853 bellard
            /* IO memory case */
1627 9fa3e853 bellard
            address = vaddr | pd;
1628 9fa3e853 bellard
            addend = paddr;
1629 9fa3e853 bellard
        } else {
1630 9fa3e853 bellard
            /* standard memory */
1631 9fa3e853 bellard
            address = vaddr;
1632 9fa3e853 bellard
            addend = (unsigned long)phys_ram_base + (pd & TARGET_PAGE_MASK);
1633 9fa3e853 bellard
        }
1634 6658ffb8 pbrook
1635 6658ffb8 pbrook
        /* Make accesses to pages with watchpoints go via the
1636 6658ffb8 pbrook
           watchpoint trap routines.  */
1637 6658ffb8 pbrook
        for (i = 0; i < env->nb_watchpoints; i++) {
1638 6658ffb8 pbrook
            if (vaddr == (env->watchpoint[i].vaddr & TARGET_PAGE_MASK)) {
1639 6658ffb8 pbrook
                if (address & ~TARGET_PAGE_MASK) {
1640 d79acba4 balrog
                    env->watchpoint[i].addend = 0;
1641 6658ffb8 pbrook
                    address = vaddr | io_mem_watch;
1642 6658ffb8 pbrook
                } else {
1643 d79acba4 balrog
                    env->watchpoint[i].addend = pd - paddr +
1644 d79acba4 balrog
                        (unsigned long) phys_ram_base;
1645 6658ffb8 pbrook
                    /* TODO: Figure out how to make read watchpoints coexist
1646 6658ffb8 pbrook
                       with code.  */
1647 6658ffb8 pbrook
                    pd = (pd & TARGET_PAGE_MASK) | io_mem_watch | IO_MEM_ROMD;
1648 6658ffb8 pbrook
                }
1649 6658ffb8 pbrook
            }
1650 6658ffb8 pbrook
        }
1651 d79acba4 balrog
1652 90f18422 bellard
        index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1653 9fa3e853 bellard
        addend -= vaddr;
1654 84b7b8e7 bellard
        te = &env->tlb_table[is_user][index];
1655 84b7b8e7 bellard
        te->addend = addend;
1656 67b915a5 bellard
        if (prot & PAGE_READ) {
1657 84b7b8e7 bellard
            te->addr_read = address;
1658 84b7b8e7 bellard
        } else {
1659 84b7b8e7 bellard
            te->addr_read = -1;
1660 84b7b8e7 bellard
        }
1661 84b7b8e7 bellard
        if (prot & PAGE_EXEC) {
1662 84b7b8e7 bellard
            te->addr_code = address;
1663 9fa3e853 bellard
        } else {
1664 84b7b8e7 bellard
            te->addr_code = -1;
1665 9fa3e853 bellard
        }
1666 67b915a5 bellard
        if (prot & PAGE_WRITE) {
1667 856074ec bellard
            if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM || 
1668 856074ec bellard
                (pd & IO_MEM_ROMD)) {
1669 856074ec bellard
                /* write access calls the I/O callback */
1670 856074ec bellard
                te->addr_write = vaddr | 
1671 856074ec bellard
                    (pd & ~(TARGET_PAGE_MASK | IO_MEM_ROMD));
1672 3a7d929e bellard
            } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM && 
1673 1ccde1cb bellard
                       !cpu_physical_memory_is_dirty(pd)) {
1674 84b7b8e7 bellard
                te->addr_write = vaddr | IO_MEM_NOTDIRTY;
1675 9fa3e853 bellard
            } else {
1676 84b7b8e7 bellard
                te->addr_write = address;
1677 9fa3e853 bellard
            }
1678 9fa3e853 bellard
        } else {
1679 84b7b8e7 bellard
            te->addr_write = -1;
1680 9fa3e853 bellard
        }
1681 9fa3e853 bellard
    }
1682 9fa3e853 bellard
#if !defined(CONFIG_SOFTMMU)
1683 9fa3e853 bellard
    else {
1684 9fa3e853 bellard
        if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
1685 9fa3e853 bellard
            /* IO access: no mapping is done as it will be handled by the
1686 9fa3e853 bellard
               soft MMU */
1687 9fa3e853 bellard
            if (!(env->hflags & HF_SOFTMMU_MASK))
1688 9fa3e853 bellard
                ret = 2;
1689 9fa3e853 bellard
        } else {
1690 9fa3e853 bellard
            void *map_addr;
1691 59817ccb bellard
1692 59817ccb bellard
            if (vaddr >= MMAP_AREA_END) {
1693 59817ccb bellard
                ret = 2;
1694 59817ccb bellard
            } else {
1695 59817ccb bellard
                if (prot & PROT_WRITE) {
1696 59817ccb bellard
                    if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM || 
1697 d720b93d bellard
#if defined(TARGET_HAS_SMC) || 1
1698 59817ccb bellard
                        first_tb ||
1699 d720b93d bellard
#endif
1700 59817ccb bellard
                        ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM && 
1701 59817ccb bellard
                         !cpu_physical_memory_is_dirty(pd))) {
1702 59817ccb bellard
                        /* ROM: we do as if code was inside */
1703 59817ccb bellard
                        /* if code is present, we only map as read only and save the
1704 59817ccb bellard
                           original mapping */
1705 59817ccb bellard
                        VirtPageDesc *vp;
1706 59817ccb bellard
                        
1707 90f18422 bellard
                        vp = virt_page_find_alloc(vaddr >> TARGET_PAGE_BITS, 1);
1708 59817ccb bellard
                        vp->phys_addr = pd;
1709 59817ccb bellard
                        vp->prot = prot;
1710 59817ccb bellard
                        vp->valid_tag = virt_valid_tag;
1711 59817ccb bellard
                        prot &= ~PAGE_WRITE;
1712 59817ccb bellard
                    }
1713 59817ccb bellard
                }
1714 59817ccb bellard
                map_addr = mmap((void *)vaddr, TARGET_PAGE_SIZE, prot, 
1715 59817ccb bellard
                                MAP_SHARED | MAP_FIXED, phys_ram_fd, (pd & TARGET_PAGE_MASK));
1716 59817ccb bellard
                if (map_addr == MAP_FAILED) {
1717 59817ccb bellard
                    cpu_abort(env, "mmap failed when mapped physical address 0x%08x to virtual address 0x%08x\n",
1718 59817ccb bellard
                              paddr, vaddr);
1719 9fa3e853 bellard
                }
1720 9fa3e853 bellard
            }
1721 9fa3e853 bellard
        }
1722 9fa3e853 bellard
    }
1723 9fa3e853 bellard
#endif
1724 9fa3e853 bellard
    return ret;
1725 9fa3e853 bellard
}
1726 9fa3e853 bellard
1727 9fa3e853 bellard
/* called from signal handler: invalidate the code and unprotect the
1728 9fa3e853 bellard
   page. Return TRUE if the fault was succesfully handled. */
1729 53a5960a pbrook
int page_unprotect(target_ulong addr, unsigned long pc, void *puc)
1730 9fa3e853 bellard
{
1731 9fa3e853 bellard
#if !defined(CONFIG_SOFTMMU)
1732 9fa3e853 bellard
    VirtPageDesc *vp;
1733 9fa3e853 bellard
1734 9fa3e853 bellard
#if defined(DEBUG_TLB)
1735 9fa3e853 bellard
    printf("page_unprotect: addr=0x%08x\n", addr);
1736 9fa3e853 bellard
#endif
1737 9fa3e853 bellard
    addr &= TARGET_PAGE_MASK;
1738 59817ccb bellard
1739 59817ccb bellard
    /* if it is not mapped, no need to worry here */
1740 59817ccb bellard
    if (addr >= MMAP_AREA_END)
1741 59817ccb bellard
        return 0;
1742 9fa3e853 bellard
    vp = virt_page_find(addr >> TARGET_PAGE_BITS);
1743 9fa3e853 bellard
    if (!vp)
1744 9fa3e853 bellard
        return 0;
1745 9fa3e853 bellard
    /* NOTE: in this case, validate_tag is _not_ tested as it
1746 9fa3e853 bellard
       validates only the code TLB */
1747 9fa3e853 bellard
    if (vp->valid_tag != virt_valid_tag)
1748 9fa3e853 bellard
        return 0;
1749 9fa3e853 bellard
    if (!(vp->prot & PAGE_WRITE))
1750 9fa3e853 bellard
        return 0;
1751 9fa3e853 bellard
#if defined(DEBUG_TLB)
1752 9fa3e853 bellard
    printf("page_unprotect: addr=0x%08x phys_addr=0x%08x prot=%x\n", 
1753 9fa3e853 bellard
           addr, vp->phys_addr, vp->prot);
1754 9fa3e853 bellard
#endif
1755 59817ccb bellard
    if (mprotect((void *)addr, TARGET_PAGE_SIZE, vp->prot) < 0)
1756 59817ccb bellard
        cpu_abort(cpu_single_env, "error mprotect addr=0x%lx prot=%d\n",
1757 59817ccb bellard
                  (unsigned long)addr, vp->prot);
1758 d720b93d bellard
    /* set the dirty bit */
1759 0a962c02 bellard
    phys_ram_dirty[vp->phys_addr >> TARGET_PAGE_BITS] = 0xff;
1760 d720b93d bellard
    /* flush the code inside */
1761 d720b93d bellard
    tb_invalidate_phys_page(vp->phys_addr, pc, puc);
1762 9fa3e853 bellard
    return 1;
1763 9fa3e853 bellard
#else
1764 9fa3e853 bellard
    return 0;
1765 9fa3e853 bellard
#endif
1766 33417e70 bellard
}
1767 33417e70 bellard
1768 0124311e bellard
#else
1769 0124311e bellard
1770 ee8b7021 bellard
void tlb_flush(CPUState *env, int flush_global)
1771 0124311e bellard
{
1772 0124311e bellard
}
1773 0124311e bellard
1774 2e12669a bellard
void tlb_flush_page(CPUState *env, target_ulong addr)
1775 0124311e bellard
{
1776 0124311e bellard
}
1777 0124311e bellard
1778 84b7b8e7 bellard
int tlb_set_page_exec(CPUState *env, target_ulong vaddr, 
1779 84b7b8e7 bellard
                      target_phys_addr_t paddr, int prot, 
1780 84b7b8e7 bellard
                      int is_user, int is_softmmu)
1781 9fa3e853 bellard
{
1782 9fa3e853 bellard
    return 0;
1783 9fa3e853 bellard
}
1784 0124311e bellard
1785 9fa3e853 bellard
/* dump memory mappings */
1786 9fa3e853 bellard
void page_dump(FILE *f)
1787 33417e70 bellard
{
1788 9fa3e853 bellard
    unsigned long start, end;
1789 9fa3e853 bellard
    int i, j, prot, prot1;
1790 9fa3e853 bellard
    PageDesc *p;
1791 33417e70 bellard
1792 9fa3e853 bellard
    fprintf(f, "%-8s %-8s %-8s %s\n",
1793 9fa3e853 bellard
            "start", "end", "size", "prot");
1794 9fa3e853 bellard
    start = -1;
1795 9fa3e853 bellard
    end = -1;
1796 9fa3e853 bellard
    prot = 0;
1797 9fa3e853 bellard
    for(i = 0; i <= L1_SIZE; i++) {
1798 9fa3e853 bellard
        if (i < L1_SIZE)
1799 9fa3e853 bellard
            p = l1_map[i];
1800 9fa3e853 bellard
        else
1801 9fa3e853 bellard
            p = NULL;
1802 9fa3e853 bellard
        for(j = 0;j < L2_SIZE; j++) {
1803 9fa3e853 bellard
            if (!p)
1804 9fa3e853 bellard
                prot1 = 0;
1805 9fa3e853 bellard
            else
1806 9fa3e853 bellard
                prot1 = p[j].flags;
1807 9fa3e853 bellard
            if (prot1 != prot) {
1808 9fa3e853 bellard
                end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
1809 9fa3e853 bellard
                if (start != -1) {
1810 9fa3e853 bellard
                    fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
1811 9fa3e853 bellard
                            start, end, end - start, 
1812 9fa3e853 bellard
                            prot & PAGE_READ ? 'r' : '-',
1813 9fa3e853 bellard
                            prot & PAGE_WRITE ? 'w' : '-',
1814 9fa3e853 bellard
                            prot & PAGE_EXEC ? 'x' : '-');
1815 9fa3e853 bellard
                }
1816 9fa3e853 bellard
                if (prot1 != 0)
1817 9fa3e853 bellard
                    start = end;
1818 9fa3e853 bellard
                else
1819 9fa3e853 bellard
                    start = -1;
1820 9fa3e853 bellard
                prot = prot1;
1821 9fa3e853 bellard
            }
1822 9fa3e853 bellard
            if (!p)
1823 9fa3e853 bellard
                break;
1824 9fa3e853 bellard
        }
1825 33417e70 bellard
    }
1826 33417e70 bellard
}
1827 33417e70 bellard
1828 53a5960a pbrook
int page_get_flags(target_ulong address)
1829 33417e70 bellard
{
1830 9fa3e853 bellard
    PageDesc *p;
1831 9fa3e853 bellard
1832 9fa3e853 bellard
    p = page_find(address >> TARGET_PAGE_BITS);
1833 33417e70 bellard
    if (!p)
1834 9fa3e853 bellard
        return 0;
1835 9fa3e853 bellard
    return p->flags;
1836 9fa3e853 bellard
}
1837 9fa3e853 bellard
1838 9fa3e853 bellard
/* modify the flags of a page and invalidate the code if
1839 9fa3e853 bellard
   necessary. The flag PAGE_WRITE_ORG is positionned automatically
1840 9fa3e853 bellard
   depending on PAGE_WRITE */
1841 53a5960a pbrook
void page_set_flags(target_ulong start, target_ulong end, int flags)
1842 9fa3e853 bellard
{
1843 9fa3e853 bellard
    PageDesc *p;
1844 53a5960a pbrook
    target_ulong addr;
1845 9fa3e853 bellard
1846 9fa3e853 bellard
    start = start & TARGET_PAGE_MASK;
1847 9fa3e853 bellard
    end = TARGET_PAGE_ALIGN(end);
1848 9fa3e853 bellard
    if (flags & PAGE_WRITE)
1849 9fa3e853 bellard
        flags |= PAGE_WRITE_ORG;
1850 9fa3e853 bellard
    spin_lock(&tb_lock);
1851 9fa3e853 bellard
    for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1852 9fa3e853 bellard
        p = page_find_alloc(addr >> TARGET_PAGE_BITS);
1853 9fa3e853 bellard
        /* if the write protection is set, then we invalidate the code
1854 9fa3e853 bellard
           inside */
1855 9fa3e853 bellard
        if (!(p->flags & PAGE_WRITE) && 
1856 9fa3e853 bellard
            (flags & PAGE_WRITE) &&
1857 9fa3e853 bellard
            p->first_tb) {
1858 d720b93d bellard
            tb_invalidate_phys_page(addr, 0, NULL);
1859 9fa3e853 bellard
        }
1860 9fa3e853 bellard
        p->flags = flags;
1861 9fa3e853 bellard
    }
1862 9fa3e853 bellard
    spin_unlock(&tb_lock);
1863 33417e70 bellard
}
1864 33417e70 bellard
1865 9fa3e853 bellard
/* called from signal handler: invalidate the code and unprotect the
1866 9fa3e853 bellard
   page. Return TRUE if the fault was succesfully handled. */
1867 53a5960a pbrook
int page_unprotect(target_ulong address, unsigned long pc, void *puc)
1868 9fa3e853 bellard
{
1869 9fa3e853 bellard
    unsigned int page_index, prot, pindex;
1870 9fa3e853 bellard
    PageDesc *p, *p1;
1871 53a5960a pbrook
    target_ulong host_start, host_end, addr;
1872 9fa3e853 bellard
1873 83fb7adf bellard
    host_start = address & qemu_host_page_mask;
1874 9fa3e853 bellard
    page_index = host_start >> TARGET_PAGE_BITS;
1875 9fa3e853 bellard
    p1 = page_find(page_index);
1876 9fa3e853 bellard
    if (!p1)
1877 9fa3e853 bellard
        return 0;
1878 83fb7adf bellard
    host_end = host_start + qemu_host_page_size;
1879 9fa3e853 bellard
    p = p1;
1880 9fa3e853 bellard
    prot = 0;
1881 9fa3e853 bellard
    for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
1882 9fa3e853 bellard
        prot |= p->flags;
1883 9fa3e853 bellard
        p++;
1884 9fa3e853 bellard
    }
1885 9fa3e853 bellard
    /* if the page was really writable, then we change its
1886 9fa3e853 bellard
       protection back to writable */
1887 9fa3e853 bellard
    if (prot & PAGE_WRITE_ORG) {
1888 9fa3e853 bellard
        pindex = (address - host_start) >> TARGET_PAGE_BITS;
1889 9fa3e853 bellard
        if (!(p1[pindex].flags & PAGE_WRITE)) {
1890 53a5960a pbrook
            mprotect((void *)g2h(host_start), qemu_host_page_size, 
1891 9fa3e853 bellard
                     (prot & PAGE_BITS) | PAGE_WRITE);
1892 9fa3e853 bellard
            p1[pindex].flags |= PAGE_WRITE;
1893 9fa3e853 bellard
            /* and since the content will be modified, we must invalidate
1894 9fa3e853 bellard
               the corresponding translated code. */
1895 d720b93d bellard
            tb_invalidate_phys_page(address, pc, puc);
1896 9fa3e853 bellard
#ifdef DEBUG_TB_CHECK
1897 9fa3e853 bellard
            tb_invalidate_check(address);
1898 9fa3e853 bellard
#endif
1899 9fa3e853 bellard
            return 1;
1900 9fa3e853 bellard
        }
1901 9fa3e853 bellard
    }
1902 9fa3e853 bellard
    return 0;
1903 9fa3e853 bellard
}
1904 9fa3e853 bellard
1905 9fa3e853 bellard
/* call this function when system calls directly modify a memory area */
1906 53a5960a pbrook
/* ??? This should be redundant now we have lock_user.  */
1907 53a5960a pbrook
void page_unprotect_range(target_ulong data, target_ulong data_size)
1908 9fa3e853 bellard
{
1909 53a5960a pbrook
    target_ulong start, end, addr;
1910 9fa3e853 bellard
1911 53a5960a pbrook
    start = data;
1912 9fa3e853 bellard
    end = start + data_size;
1913 9fa3e853 bellard
    start &= TARGET_PAGE_MASK;
1914 9fa3e853 bellard
    end = TARGET_PAGE_ALIGN(end);
1915 9fa3e853 bellard
    for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1916 d720b93d bellard
        page_unprotect(addr, 0, NULL);
1917 9fa3e853 bellard
    }
1918 9fa3e853 bellard
}
1919 9fa3e853 bellard
1920 6a00d601 bellard
static inline void tlb_set_dirty(CPUState *env,
1921 6a00d601 bellard
                                 unsigned long addr, target_ulong vaddr)
1922 1ccde1cb bellard
{
1923 1ccde1cb bellard
}
1924 9fa3e853 bellard
#endif /* defined(CONFIG_USER_ONLY) */
1925 9fa3e853 bellard
1926 db7b5426 blueswir1
static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
1927 db7b5426 blueswir1
                             int memory);
1928 db7b5426 blueswir1
static void *subpage_init (target_phys_addr_t base, uint32_t *phys,
1929 db7b5426 blueswir1
                           int orig_memory);
1930 db7b5426 blueswir1
#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
1931 db7b5426 blueswir1
                      need_subpage)                                     \
1932 db7b5426 blueswir1
    do {                                                                \
1933 db7b5426 blueswir1
        if (addr > start_addr)                                          \
1934 db7b5426 blueswir1
            start_addr2 = 0;                                            \
1935 db7b5426 blueswir1
        else {                                                          \
1936 db7b5426 blueswir1
            start_addr2 = start_addr & ~TARGET_PAGE_MASK;               \
1937 db7b5426 blueswir1
            if (start_addr2 > 0)                                        \
1938 db7b5426 blueswir1
                need_subpage = 1;                                       \
1939 db7b5426 blueswir1
        }                                                               \
1940 db7b5426 blueswir1
                                                                        \
1941 49e9fba2 blueswir1
        if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE)        \
1942 db7b5426 blueswir1
            end_addr2 = TARGET_PAGE_SIZE - 1;                           \
1943 db7b5426 blueswir1
        else {                                                          \
1944 db7b5426 blueswir1
            end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
1945 db7b5426 blueswir1
            if (end_addr2 < TARGET_PAGE_SIZE - 1)                       \
1946 db7b5426 blueswir1
                need_subpage = 1;                                       \
1947 db7b5426 blueswir1
        }                                                               \
1948 db7b5426 blueswir1
    } while (0)
1949 db7b5426 blueswir1
1950 33417e70 bellard
/* register physical memory. 'size' must be a multiple of the target
1951 33417e70 bellard
   page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
1952 33417e70 bellard
   io memory page */
1953 2e12669a bellard
void cpu_register_physical_memory(target_phys_addr_t start_addr, 
1954 2e12669a bellard
                                  unsigned long size,
1955 2e12669a bellard
                                  unsigned long phys_offset)
1956 33417e70 bellard
{
1957 108c49b8 bellard
    target_phys_addr_t addr, end_addr;
1958 92e873b9 bellard
    PhysPageDesc *p;
1959 9d42037b bellard
    CPUState *env;
1960 db7b5426 blueswir1
    unsigned long orig_size = size;
1961 db7b5426 blueswir1
    void *subpage;
1962 33417e70 bellard
1963 5fd386f6 bellard
    size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
1964 49e9fba2 blueswir1
    end_addr = start_addr + (target_phys_addr_t)size;
1965 49e9fba2 blueswir1
    for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
1966 db7b5426 blueswir1
        p = phys_page_find(addr >> TARGET_PAGE_BITS);
1967 db7b5426 blueswir1
        if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
1968 db7b5426 blueswir1
            unsigned long orig_memory = p->phys_offset;
1969 db7b5426 blueswir1
            target_phys_addr_t start_addr2, end_addr2;
1970 db7b5426 blueswir1
            int need_subpage = 0;
1971 db7b5426 blueswir1
1972 db7b5426 blueswir1
            CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
1973 db7b5426 blueswir1
                          need_subpage);
1974 db7b5426 blueswir1
            if (need_subpage) {
1975 db7b5426 blueswir1
                if (!(orig_memory & IO_MEM_SUBPAGE)) {
1976 db7b5426 blueswir1
                    subpage = subpage_init((addr & TARGET_PAGE_MASK),
1977 db7b5426 blueswir1
                                           &p->phys_offset, orig_memory);
1978 db7b5426 blueswir1
                } else {
1979 db7b5426 blueswir1
                    subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
1980 db7b5426 blueswir1
                                            >> IO_MEM_SHIFT];
1981 db7b5426 blueswir1
                }
1982 db7b5426 blueswir1
                subpage_register(subpage, start_addr2, end_addr2, phys_offset);
1983 db7b5426 blueswir1
            } else {
1984 db7b5426 blueswir1
                p->phys_offset = phys_offset;
1985 db7b5426 blueswir1
                if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
1986 db7b5426 blueswir1
                    (phys_offset & IO_MEM_ROMD))
1987 db7b5426 blueswir1
                    phys_offset += TARGET_PAGE_SIZE;
1988 db7b5426 blueswir1
            }
1989 db7b5426 blueswir1
        } else {
1990 db7b5426 blueswir1
            p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
1991 db7b5426 blueswir1
            p->phys_offset = phys_offset;
1992 db7b5426 blueswir1
            if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
1993 db7b5426 blueswir1
                (phys_offset & IO_MEM_ROMD))
1994 db7b5426 blueswir1
                phys_offset += TARGET_PAGE_SIZE;
1995 db7b5426 blueswir1
            else {
1996 db7b5426 blueswir1
                target_phys_addr_t start_addr2, end_addr2;
1997 db7b5426 blueswir1
                int need_subpage = 0;
1998 db7b5426 blueswir1
1999 db7b5426 blueswir1
                CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2000 db7b5426 blueswir1
                              end_addr2, need_subpage);
2001 db7b5426 blueswir1
2002 db7b5426 blueswir1
                if (need_subpage) {
2003 db7b5426 blueswir1
                    subpage = subpage_init((addr & TARGET_PAGE_MASK),
2004 db7b5426 blueswir1
                                           &p->phys_offset, IO_MEM_UNASSIGNED);
2005 db7b5426 blueswir1
                    subpage_register(subpage, start_addr2, end_addr2,
2006 db7b5426 blueswir1
                                     phys_offset);
2007 db7b5426 blueswir1
                }
2008 db7b5426 blueswir1
            }
2009 db7b5426 blueswir1
        }
2010 33417e70 bellard
    }
2011 9d42037b bellard
    
2012 9d42037b bellard
    /* since each CPU stores ram addresses in its TLB cache, we must
2013 9d42037b bellard
       reset the modified entries */
2014 9d42037b bellard
    /* XXX: slow ! */
2015 9d42037b bellard
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
2016 9d42037b bellard
        tlb_flush(env, 1);
2017 9d42037b bellard
    }
2018 33417e70 bellard
}
2019 33417e70 bellard
2020 ba863458 bellard
/* XXX: temporary until new memory mapping API */
2021 ba863458 bellard
uint32_t cpu_get_physical_page_desc(target_phys_addr_t addr)
2022 ba863458 bellard
{
2023 ba863458 bellard
    PhysPageDesc *p;
2024 ba863458 bellard
2025 ba863458 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2026 ba863458 bellard
    if (!p)
2027 ba863458 bellard
        return IO_MEM_UNASSIGNED;
2028 ba863458 bellard
    return p->phys_offset;
2029 ba863458 bellard
}
2030 ba863458 bellard
2031 e9a1ab19 bellard
/* XXX: better than nothing */
2032 e9a1ab19 bellard
ram_addr_t qemu_ram_alloc(unsigned int size)
2033 e9a1ab19 bellard
{
2034 e9a1ab19 bellard
    ram_addr_t addr;
2035 e9a1ab19 bellard
    if ((phys_ram_alloc_offset + size) >= phys_ram_size) {
2036 e9a1ab19 bellard
        fprintf(stderr, "Not enough memory (requested_size = %u, max memory = %d)\n", 
2037 e9a1ab19 bellard
                size, phys_ram_size);
2038 e9a1ab19 bellard
        abort();
2039 e9a1ab19 bellard
    }
2040 e9a1ab19 bellard
    addr = phys_ram_alloc_offset;
2041 e9a1ab19 bellard
    phys_ram_alloc_offset = TARGET_PAGE_ALIGN(phys_ram_alloc_offset + size);
2042 e9a1ab19 bellard
    return addr;
2043 e9a1ab19 bellard
}
2044 e9a1ab19 bellard
2045 e9a1ab19 bellard
void qemu_ram_free(ram_addr_t addr)
2046 e9a1ab19 bellard
{
2047 e9a1ab19 bellard
}
2048 e9a1ab19 bellard
2049 a4193c8a bellard
static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
2050 33417e70 bellard
{
2051 67d3b957 pbrook
#ifdef DEBUG_UNASSIGNED
2052 6c36d3fa blueswir1
    printf("Unassigned mem read " TARGET_FMT_lx "\n", addr);
2053 67d3b957 pbrook
#endif
2054 b4f0a316 blueswir1
#ifdef TARGET_SPARC
2055 6c36d3fa blueswir1
    do_unassigned_access(addr, 0, 0, 0);
2056 b4f0a316 blueswir1
#endif
2057 33417e70 bellard
    return 0;
2058 33417e70 bellard
}
2059 33417e70 bellard
2060 a4193c8a bellard
static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
2061 33417e70 bellard
{
2062 67d3b957 pbrook
#ifdef DEBUG_UNASSIGNED
2063 6c36d3fa blueswir1
    printf("Unassigned mem write " TARGET_FMT_lx " = 0x%x\n", addr, val);
2064 67d3b957 pbrook
#endif
2065 b4f0a316 blueswir1
#ifdef TARGET_SPARC
2066 6c36d3fa blueswir1
    do_unassigned_access(addr, 1, 0, 0);
2067 b4f0a316 blueswir1
#endif
2068 33417e70 bellard
}
2069 33417e70 bellard
2070 33417e70 bellard
static CPUReadMemoryFunc *unassigned_mem_read[3] = {
2071 33417e70 bellard
    unassigned_mem_readb,
2072 33417e70 bellard
    unassigned_mem_readb,
2073 33417e70 bellard
    unassigned_mem_readb,
2074 33417e70 bellard
};
2075 33417e70 bellard
2076 33417e70 bellard
static CPUWriteMemoryFunc *unassigned_mem_write[3] = {
2077 33417e70 bellard
    unassigned_mem_writeb,
2078 33417e70 bellard
    unassigned_mem_writeb,
2079 33417e70 bellard
    unassigned_mem_writeb,
2080 33417e70 bellard
};
2081 33417e70 bellard
2082 3a7d929e bellard
static void notdirty_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
2083 9fa3e853 bellard
{
2084 3a7d929e bellard
    unsigned long ram_addr;
2085 3a7d929e bellard
    int dirty_flags;
2086 3a7d929e bellard
    ram_addr = addr - (unsigned long)phys_ram_base;
2087 3a7d929e bellard
    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2088 3a7d929e bellard
    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2089 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
2090 3a7d929e bellard
        tb_invalidate_phys_page_fast(ram_addr, 1);
2091 3a7d929e bellard
        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2092 9fa3e853 bellard
#endif
2093 3a7d929e bellard
    }
2094 c27004ec bellard
    stb_p((uint8_t *)(long)addr, val);
2095 f32fc648 bellard
#ifdef USE_KQEMU
2096 f32fc648 bellard
    if (cpu_single_env->kqemu_enabled &&
2097 f32fc648 bellard
        (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2098 f32fc648 bellard
        kqemu_modify_page(cpu_single_env, ram_addr);
2099 f32fc648 bellard
#endif
2100 f23db169 bellard
    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2101 f23db169 bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2102 f23db169 bellard
    /* we remove the notdirty callback only if the code has been
2103 f23db169 bellard
       flushed */
2104 f23db169 bellard
    if (dirty_flags == 0xff)
2105 6a00d601 bellard
        tlb_set_dirty(cpu_single_env, addr, cpu_single_env->mem_write_vaddr);
2106 9fa3e853 bellard
}
2107 9fa3e853 bellard
2108 3a7d929e bellard
static void notdirty_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
2109 9fa3e853 bellard
{
2110 3a7d929e bellard
    unsigned long ram_addr;
2111 3a7d929e bellard
    int dirty_flags;
2112 3a7d929e bellard
    ram_addr = addr - (unsigned long)phys_ram_base;
2113 3a7d929e bellard
    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2114 3a7d929e bellard
    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2115 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
2116 3a7d929e bellard
        tb_invalidate_phys_page_fast(ram_addr, 2);
2117 3a7d929e bellard
        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2118 9fa3e853 bellard
#endif
2119 3a7d929e bellard
    }
2120 c27004ec bellard
    stw_p((uint8_t *)(long)addr, val);
2121 f32fc648 bellard
#ifdef USE_KQEMU
2122 f32fc648 bellard
    if (cpu_single_env->kqemu_enabled &&
2123 f32fc648 bellard
        (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2124 f32fc648 bellard
        kqemu_modify_page(cpu_single_env, ram_addr);
2125 f32fc648 bellard
#endif
2126 f23db169 bellard
    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2127 f23db169 bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2128 f23db169 bellard
    /* we remove the notdirty callback only if the code has been
2129 f23db169 bellard
       flushed */
2130 f23db169 bellard
    if (dirty_flags == 0xff)
2131 6a00d601 bellard
        tlb_set_dirty(cpu_single_env, addr, cpu_single_env->mem_write_vaddr);
2132 9fa3e853 bellard
}
2133 9fa3e853 bellard
2134 3a7d929e bellard
static void notdirty_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
2135 9fa3e853 bellard
{
2136 3a7d929e bellard
    unsigned long ram_addr;
2137 3a7d929e bellard
    int dirty_flags;
2138 3a7d929e bellard
    ram_addr = addr - (unsigned long)phys_ram_base;
2139 3a7d929e bellard
    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2140 3a7d929e bellard
    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2141 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
2142 3a7d929e bellard
        tb_invalidate_phys_page_fast(ram_addr, 4);
2143 3a7d929e bellard
        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2144 9fa3e853 bellard
#endif
2145 3a7d929e bellard
    }
2146 c27004ec bellard
    stl_p((uint8_t *)(long)addr, val);
2147 f32fc648 bellard
#ifdef USE_KQEMU
2148 f32fc648 bellard
    if (cpu_single_env->kqemu_enabled &&
2149 f32fc648 bellard
        (dirty_flags & KQEMU_MODIFY_PAGE_MASK) != KQEMU_MODIFY_PAGE_MASK)
2150 f32fc648 bellard
        kqemu_modify_page(cpu_single_env, ram_addr);
2151 f32fc648 bellard
#endif
2152 f23db169 bellard
    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2153 f23db169 bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2154 f23db169 bellard
    /* we remove the notdirty callback only if the code has been
2155 f23db169 bellard
       flushed */
2156 f23db169 bellard
    if (dirty_flags == 0xff)
2157 6a00d601 bellard
        tlb_set_dirty(cpu_single_env, addr, cpu_single_env->mem_write_vaddr);
2158 9fa3e853 bellard
}
2159 9fa3e853 bellard
2160 3a7d929e bellard
static CPUReadMemoryFunc *error_mem_read[3] = {
2161 9fa3e853 bellard
    NULL, /* never used */
2162 9fa3e853 bellard
    NULL, /* never used */
2163 9fa3e853 bellard
    NULL, /* never used */
2164 9fa3e853 bellard
};
2165 9fa3e853 bellard
2166 1ccde1cb bellard
static CPUWriteMemoryFunc *notdirty_mem_write[3] = {
2167 1ccde1cb bellard
    notdirty_mem_writeb,
2168 1ccde1cb bellard
    notdirty_mem_writew,
2169 1ccde1cb bellard
    notdirty_mem_writel,
2170 1ccde1cb bellard
};
2171 1ccde1cb bellard
2172 6658ffb8 pbrook
#if defined(CONFIG_SOFTMMU)
2173 6658ffb8 pbrook
/* Watchpoint access routines.  Watchpoints are inserted using TLB tricks,
2174 6658ffb8 pbrook
   so these check for a hit then pass through to the normal out-of-line
2175 6658ffb8 pbrook
   phys routines.  */
2176 6658ffb8 pbrook
static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
2177 6658ffb8 pbrook
{
2178 6658ffb8 pbrook
    return ldub_phys(addr);
2179 6658ffb8 pbrook
}
2180 6658ffb8 pbrook
2181 6658ffb8 pbrook
static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
2182 6658ffb8 pbrook
{
2183 6658ffb8 pbrook
    return lduw_phys(addr);
2184 6658ffb8 pbrook
}
2185 6658ffb8 pbrook
2186 6658ffb8 pbrook
static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
2187 6658ffb8 pbrook
{
2188 6658ffb8 pbrook
    return ldl_phys(addr);
2189 6658ffb8 pbrook
}
2190 6658ffb8 pbrook
2191 6658ffb8 pbrook
/* Generate a debug exception if a watchpoint has been hit.
2192 6658ffb8 pbrook
   Returns the real physical address of the access.  addr will be a host
2193 d79acba4 balrog
   address in case of a RAM location.  */
2194 6658ffb8 pbrook
static target_ulong check_watchpoint(target_phys_addr_t addr)
2195 6658ffb8 pbrook
{
2196 6658ffb8 pbrook
    CPUState *env = cpu_single_env;
2197 6658ffb8 pbrook
    target_ulong watch;
2198 6658ffb8 pbrook
    target_ulong retaddr;
2199 6658ffb8 pbrook
    int i;
2200 6658ffb8 pbrook
2201 6658ffb8 pbrook
    retaddr = addr;
2202 6658ffb8 pbrook
    for (i = 0; i < env->nb_watchpoints; i++) {
2203 6658ffb8 pbrook
        watch = env->watchpoint[i].vaddr;
2204 6658ffb8 pbrook
        if (((env->mem_write_vaddr ^ watch) & TARGET_PAGE_MASK) == 0) {
2205 d79acba4 balrog
            retaddr = addr - env->watchpoint[i].addend;
2206 6658ffb8 pbrook
            if (((addr ^ watch) & ~TARGET_PAGE_MASK) == 0) {
2207 6658ffb8 pbrook
                cpu_single_env->watchpoint_hit = i + 1;
2208 6658ffb8 pbrook
                cpu_interrupt(cpu_single_env, CPU_INTERRUPT_DEBUG);
2209 6658ffb8 pbrook
                break;
2210 6658ffb8 pbrook
            }
2211 6658ffb8 pbrook
        }
2212 6658ffb8 pbrook
    }
2213 6658ffb8 pbrook
    return retaddr;
2214 6658ffb8 pbrook
}
2215 6658ffb8 pbrook
2216 6658ffb8 pbrook
static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
2217 6658ffb8 pbrook
                             uint32_t val)
2218 6658ffb8 pbrook
{
2219 6658ffb8 pbrook
    addr = check_watchpoint(addr);
2220 6658ffb8 pbrook
    stb_phys(addr, val);
2221 6658ffb8 pbrook
}
2222 6658ffb8 pbrook
2223 6658ffb8 pbrook
static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
2224 6658ffb8 pbrook
                             uint32_t val)
2225 6658ffb8 pbrook
{
2226 6658ffb8 pbrook
    addr = check_watchpoint(addr);
2227 6658ffb8 pbrook
    stw_phys(addr, val);
2228 6658ffb8 pbrook
}
2229 6658ffb8 pbrook
2230 6658ffb8 pbrook
static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
2231 6658ffb8 pbrook
                             uint32_t val)
2232 6658ffb8 pbrook
{
2233 6658ffb8 pbrook
    addr = check_watchpoint(addr);
2234 6658ffb8 pbrook
    stl_phys(addr, val);
2235 6658ffb8 pbrook
}
2236 6658ffb8 pbrook
2237 6658ffb8 pbrook
static CPUReadMemoryFunc *watch_mem_read[3] = {
2238 6658ffb8 pbrook
    watch_mem_readb,
2239 6658ffb8 pbrook
    watch_mem_readw,
2240 6658ffb8 pbrook
    watch_mem_readl,
2241 6658ffb8 pbrook
};
2242 6658ffb8 pbrook
2243 6658ffb8 pbrook
static CPUWriteMemoryFunc *watch_mem_write[3] = {
2244 6658ffb8 pbrook
    watch_mem_writeb,
2245 6658ffb8 pbrook
    watch_mem_writew,
2246 6658ffb8 pbrook
    watch_mem_writel,
2247 6658ffb8 pbrook
};
2248 6658ffb8 pbrook
#endif
2249 6658ffb8 pbrook
2250 db7b5426 blueswir1
static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr,
2251 db7b5426 blueswir1
                                 unsigned int len)
2252 db7b5426 blueswir1
{
2253 db7b5426 blueswir1
    CPUReadMemoryFunc **mem_read;
2254 db7b5426 blueswir1
    uint32_t ret;
2255 db7b5426 blueswir1
    unsigned int idx;
2256 db7b5426 blueswir1
2257 db7b5426 blueswir1
    idx = SUBPAGE_IDX(addr - mmio->base);
2258 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2259 db7b5426 blueswir1
    printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
2260 db7b5426 blueswir1
           mmio, len, addr, idx);
2261 db7b5426 blueswir1
#endif
2262 db7b5426 blueswir1
    mem_read = mmio->mem_read[idx];
2263 db7b5426 blueswir1
    ret = (*mem_read[len])(mmio->opaque[idx], addr);
2264 db7b5426 blueswir1
2265 db7b5426 blueswir1
    return ret;
2266 db7b5426 blueswir1
}
2267 db7b5426 blueswir1
2268 db7b5426 blueswir1
static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
2269 db7b5426 blueswir1
                              uint32_t value, unsigned int len)
2270 db7b5426 blueswir1
{
2271 db7b5426 blueswir1
    CPUWriteMemoryFunc **mem_write;
2272 db7b5426 blueswir1
    unsigned int idx;
2273 db7b5426 blueswir1
2274 db7b5426 blueswir1
    idx = SUBPAGE_IDX(addr - mmio->base);
2275 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2276 db7b5426 blueswir1
    printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
2277 db7b5426 blueswir1
           mmio, len, addr, idx, value);
2278 db7b5426 blueswir1
#endif
2279 db7b5426 blueswir1
    mem_write = mmio->mem_write[idx];
2280 db7b5426 blueswir1
    (*mem_write[len])(mmio->opaque[idx], addr, value);
2281 db7b5426 blueswir1
}
2282 db7b5426 blueswir1
2283 db7b5426 blueswir1
static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
2284 db7b5426 blueswir1
{
2285 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2286 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2287 db7b5426 blueswir1
#endif
2288 db7b5426 blueswir1
2289 db7b5426 blueswir1
    return subpage_readlen(opaque, addr, 0);
2290 db7b5426 blueswir1
}
2291 db7b5426 blueswir1
2292 db7b5426 blueswir1
static void subpage_writeb (void *opaque, target_phys_addr_t addr,
2293 db7b5426 blueswir1
                            uint32_t value)
2294 db7b5426 blueswir1
{
2295 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2296 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2297 db7b5426 blueswir1
#endif
2298 db7b5426 blueswir1
    subpage_writelen(opaque, addr, value, 0);
2299 db7b5426 blueswir1
}
2300 db7b5426 blueswir1
2301 db7b5426 blueswir1
static uint32_t subpage_readw (void *opaque, target_phys_addr_t addr)
2302 db7b5426 blueswir1
{
2303 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2304 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2305 db7b5426 blueswir1
#endif
2306 db7b5426 blueswir1
2307 db7b5426 blueswir1
    return subpage_readlen(opaque, addr, 1);
2308 db7b5426 blueswir1
}
2309 db7b5426 blueswir1
2310 db7b5426 blueswir1
static void subpage_writew (void *opaque, target_phys_addr_t addr,
2311 db7b5426 blueswir1
                            uint32_t value)
2312 db7b5426 blueswir1
{
2313 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2314 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2315 db7b5426 blueswir1
#endif
2316 db7b5426 blueswir1
    subpage_writelen(opaque, addr, value, 1);
2317 db7b5426 blueswir1
}
2318 db7b5426 blueswir1
2319 db7b5426 blueswir1
static uint32_t subpage_readl (void *opaque, target_phys_addr_t addr)
2320 db7b5426 blueswir1
{
2321 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2322 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2323 db7b5426 blueswir1
#endif
2324 db7b5426 blueswir1
2325 db7b5426 blueswir1
    return subpage_readlen(opaque, addr, 2);
2326 db7b5426 blueswir1
}
2327 db7b5426 blueswir1
2328 db7b5426 blueswir1
static void subpage_writel (void *opaque,
2329 db7b5426 blueswir1
                         target_phys_addr_t addr, uint32_t value)
2330 db7b5426 blueswir1
{
2331 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2332 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2333 db7b5426 blueswir1
#endif
2334 db7b5426 blueswir1
    subpage_writelen(opaque, addr, value, 2);
2335 db7b5426 blueswir1
}
2336 db7b5426 blueswir1
2337 db7b5426 blueswir1
static CPUReadMemoryFunc *subpage_read[] = {
2338 db7b5426 blueswir1
    &subpage_readb,
2339 db7b5426 blueswir1
    &subpage_readw,
2340 db7b5426 blueswir1
    &subpage_readl,
2341 db7b5426 blueswir1
};
2342 db7b5426 blueswir1
2343 db7b5426 blueswir1
static CPUWriteMemoryFunc *subpage_write[] = {
2344 db7b5426 blueswir1
    &subpage_writeb,
2345 db7b5426 blueswir1
    &subpage_writew,
2346 db7b5426 blueswir1
    &subpage_writel,
2347 db7b5426 blueswir1
};
2348 db7b5426 blueswir1
2349 db7b5426 blueswir1
static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
2350 db7b5426 blueswir1
                             int memory)
2351 db7b5426 blueswir1
{
2352 db7b5426 blueswir1
    int idx, eidx;
2353 db7b5426 blueswir1
2354 db7b5426 blueswir1
    if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
2355 db7b5426 blueswir1
        return -1;
2356 db7b5426 blueswir1
    idx = SUBPAGE_IDX(start);
2357 db7b5426 blueswir1
    eidx = SUBPAGE_IDX(end);
2358 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2359 db7b5426 blueswir1
    printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %d\n", __func__,
2360 db7b5426 blueswir1
           mmio, start, end, idx, eidx, memory);
2361 db7b5426 blueswir1
#endif
2362 db7b5426 blueswir1
    memory >>= IO_MEM_SHIFT;
2363 db7b5426 blueswir1
    for (; idx <= eidx; idx++) {
2364 db7b5426 blueswir1
        mmio->mem_read[idx] = io_mem_read[memory];
2365 db7b5426 blueswir1
        mmio->mem_write[idx] = io_mem_write[memory];
2366 db7b5426 blueswir1
        mmio->opaque[idx] = io_mem_opaque[memory];
2367 db7b5426 blueswir1
    }
2368 db7b5426 blueswir1
2369 db7b5426 blueswir1
    return 0;
2370 db7b5426 blueswir1
}
2371 db7b5426 blueswir1
2372 db7b5426 blueswir1
static void *subpage_init (target_phys_addr_t base, uint32_t *phys,
2373 db7b5426 blueswir1
                           int orig_memory)
2374 db7b5426 blueswir1
{
2375 db7b5426 blueswir1
    subpage_t *mmio;
2376 db7b5426 blueswir1
    int subpage_memory;
2377 db7b5426 blueswir1
2378 db7b5426 blueswir1
    mmio = qemu_mallocz(sizeof(subpage_t));
2379 db7b5426 blueswir1
    if (mmio != NULL) {
2380 db7b5426 blueswir1
        mmio->base = base;
2381 db7b5426 blueswir1
        subpage_memory = cpu_register_io_memory(0, subpage_read, subpage_write, mmio);
2382 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2383 db7b5426 blueswir1
        printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
2384 db7b5426 blueswir1
               mmio, base, TARGET_PAGE_SIZE, subpage_memory);
2385 db7b5426 blueswir1
#endif
2386 db7b5426 blueswir1
        *phys = subpage_memory | IO_MEM_SUBPAGE;
2387 db7b5426 blueswir1
        subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory);
2388 db7b5426 blueswir1
    }
2389 db7b5426 blueswir1
2390 db7b5426 blueswir1
    return mmio;
2391 db7b5426 blueswir1
}
2392 db7b5426 blueswir1
2393 33417e70 bellard
static void io_mem_init(void)
2394 33417e70 bellard
{
2395 3a7d929e bellard
    cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read, unassigned_mem_write, NULL);
2396 a4193c8a bellard
    cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write, NULL);
2397 3a7d929e bellard
    cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read, notdirty_mem_write, NULL);
2398 1ccde1cb bellard
    io_mem_nb = 5;
2399 1ccde1cb bellard
2400 6658ffb8 pbrook
#if defined(CONFIG_SOFTMMU)
2401 6658ffb8 pbrook
    io_mem_watch = cpu_register_io_memory(-1, watch_mem_read,
2402 6658ffb8 pbrook
                                          watch_mem_write, NULL);
2403 6658ffb8 pbrook
#endif
2404 1ccde1cb bellard
    /* alloc dirty bits array */
2405 0a962c02 bellard
    phys_ram_dirty = qemu_vmalloc(phys_ram_size >> TARGET_PAGE_BITS);
2406 3a7d929e bellard
    memset(phys_ram_dirty, 0xff, phys_ram_size >> TARGET_PAGE_BITS);
2407 33417e70 bellard
}
2408 33417e70 bellard
2409 33417e70 bellard
/* mem_read and mem_write are arrays of functions containing the
2410 33417e70 bellard
   function to access byte (index 0), word (index 1) and dword (index
2411 33417e70 bellard
   2). All functions must be supplied. If io_index is non zero, the
2412 33417e70 bellard
   corresponding io zone is modified. If it is zero, a new io zone is
2413 33417e70 bellard
   allocated. The return value can be used with
2414 33417e70 bellard
   cpu_register_physical_memory(). (-1) is returned if error. */
2415 33417e70 bellard
int cpu_register_io_memory(int io_index,
2416 33417e70 bellard
                           CPUReadMemoryFunc **mem_read,
2417 a4193c8a bellard
                           CPUWriteMemoryFunc **mem_write,
2418 a4193c8a bellard
                           void *opaque)
2419 33417e70 bellard
{
2420 33417e70 bellard
    int i;
2421 33417e70 bellard
2422 33417e70 bellard
    if (io_index <= 0) {
2423 b5ff1b31 bellard
        if (io_mem_nb >= IO_MEM_NB_ENTRIES)
2424 33417e70 bellard
            return -1;
2425 33417e70 bellard
        io_index = io_mem_nb++;
2426 33417e70 bellard
    } else {
2427 33417e70 bellard
        if (io_index >= IO_MEM_NB_ENTRIES)
2428 33417e70 bellard
            return -1;
2429 33417e70 bellard
    }
2430 b5ff1b31 bellard
2431 33417e70 bellard
    for(i = 0;i < 3; i++) {
2432 33417e70 bellard
        io_mem_read[io_index][i] = mem_read[i];
2433 33417e70 bellard
        io_mem_write[io_index][i] = mem_write[i];
2434 33417e70 bellard
    }
2435 a4193c8a bellard
    io_mem_opaque[io_index] = opaque;
2436 33417e70 bellard
    return io_index << IO_MEM_SHIFT;
2437 33417e70 bellard
}
2438 61382a50 bellard
2439 8926b517 bellard
CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index)
2440 8926b517 bellard
{
2441 8926b517 bellard
    return io_mem_write[io_index >> IO_MEM_SHIFT];
2442 8926b517 bellard
}
2443 8926b517 bellard
2444 8926b517 bellard
CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index)
2445 8926b517 bellard
{
2446 8926b517 bellard
    return io_mem_read[io_index >> IO_MEM_SHIFT];
2447 8926b517 bellard
}
2448 8926b517 bellard
2449 13eb76e0 bellard
/* physical memory access (slow version, mainly for debug) */
2450 13eb76e0 bellard
#if defined(CONFIG_USER_ONLY)
2451 2e12669a bellard
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, 
2452 13eb76e0 bellard
                            int len, int is_write)
2453 13eb76e0 bellard
{
2454 13eb76e0 bellard
    int l, flags;
2455 13eb76e0 bellard
    target_ulong page;
2456 53a5960a pbrook
    void * p;
2457 13eb76e0 bellard
2458 13eb76e0 bellard
    while (len > 0) {
2459 13eb76e0 bellard
        page = addr & TARGET_PAGE_MASK;
2460 13eb76e0 bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
2461 13eb76e0 bellard
        if (l > len)
2462 13eb76e0 bellard
            l = len;
2463 13eb76e0 bellard
        flags = page_get_flags(page);
2464 13eb76e0 bellard
        if (!(flags & PAGE_VALID))
2465 13eb76e0 bellard
            return;
2466 13eb76e0 bellard
        if (is_write) {
2467 13eb76e0 bellard
            if (!(flags & PAGE_WRITE))
2468 13eb76e0 bellard
                return;
2469 53a5960a pbrook
            p = lock_user(addr, len, 0);
2470 53a5960a pbrook
            memcpy(p, buf, len);
2471 53a5960a pbrook
            unlock_user(p, addr, len);
2472 13eb76e0 bellard
        } else {
2473 13eb76e0 bellard
            if (!(flags & PAGE_READ))
2474 13eb76e0 bellard
                return;
2475 53a5960a pbrook
            p = lock_user(addr, len, 1);
2476 53a5960a pbrook
            memcpy(buf, p, len);
2477 53a5960a pbrook
            unlock_user(p, addr, 0);
2478 13eb76e0 bellard
        }
2479 13eb76e0 bellard
        len -= l;
2480 13eb76e0 bellard
        buf += l;
2481 13eb76e0 bellard
        addr += l;
2482 13eb76e0 bellard
    }
2483 13eb76e0 bellard
}
2484 8df1cd07 bellard
2485 13eb76e0 bellard
#else
2486 2e12669a bellard
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, 
2487 13eb76e0 bellard
                            int len, int is_write)
2488 13eb76e0 bellard
{
2489 13eb76e0 bellard
    int l, io_index;
2490 13eb76e0 bellard
    uint8_t *ptr;
2491 13eb76e0 bellard
    uint32_t val;
2492 2e12669a bellard
    target_phys_addr_t page;
2493 2e12669a bellard
    unsigned long pd;
2494 92e873b9 bellard
    PhysPageDesc *p;
2495 13eb76e0 bellard
    
2496 13eb76e0 bellard
    while (len > 0) {
2497 13eb76e0 bellard
        page = addr & TARGET_PAGE_MASK;
2498 13eb76e0 bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
2499 13eb76e0 bellard
        if (l > len)
2500 13eb76e0 bellard
            l = len;
2501 92e873b9 bellard
        p = phys_page_find(page >> TARGET_PAGE_BITS);
2502 13eb76e0 bellard
        if (!p) {
2503 13eb76e0 bellard
            pd = IO_MEM_UNASSIGNED;
2504 13eb76e0 bellard
        } else {
2505 13eb76e0 bellard
            pd = p->phys_offset;
2506 13eb76e0 bellard
        }
2507 13eb76e0 bellard
        
2508 13eb76e0 bellard
        if (is_write) {
2509 3a7d929e bellard
            if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2510 13eb76e0 bellard
                io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2511 6a00d601 bellard
                /* XXX: could force cpu_single_env to NULL to avoid
2512 6a00d601 bellard
                   potential bugs */
2513 13eb76e0 bellard
                if (l >= 4 && ((addr & 3) == 0)) {
2514 1c213d19 bellard
                    /* 32 bit write access */
2515 c27004ec bellard
                    val = ldl_p(buf);
2516 a4193c8a bellard
                    io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2517 13eb76e0 bellard
                    l = 4;
2518 13eb76e0 bellard
                } else if (l >= 2 && ((addr & 1) == 0)) {
2519 1c213d19 bellard
                    /* 16 bit write access */
2520 c27004ec bellard
                    val = lduw_p(buf);
2521 a4193c8a bellard
                    io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
2522 13eb76e0 bellard
                    l = 2;
2523 13eb76e0 bellard
                } else {
2524 1c213d19 bellard
                    /* 8 bit write access */
2525 c27004ec bellard
                    val = ldub_p(buf);
2526 a4193c8a bellard
                    io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val);
2527 13eb76e0 bellard
                    l = 1;
2528 13eb76e0 bellard
                }
2529 13eb76e0 bellard
            } else {
2530 b448f2f3 bellard
                unsigned long addr1;
2531 b448f2f3 bellard
                addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2532 13eb76e0 bellard
                /* RAM case */
2533 b448f2f3 bellard
                ptr = phys_ram_base + addr1;
2534 13eb76e0 bellard
                memcpy(ptr, buf, l);
2535 3a7d929e bellard
                if (!cpu_physical_memory_is_dirty(addr1)) {
2536 3a7d929e bellard
                    /* invalidate code */
2537 3a7d929e bellard
                    tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
2538 3a7d929e bellard
                    /* set dirty bit */
2539 f23db169 bellard
                    phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |= 
2540 f23db169 bellard
                        (0xff & ~CODE_DIRTY_FLAG);
2541 3a7d929e bellard
                }
2542 13eb76e0 bellard
            }
2543 13eb76e0 bellard
        } else {
2544 2a4188a3 bellard
            if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && 
2545 2a4188a3 bellard
                !(pd & IO_MEM_ROMD)) {
2546 13eb76e0 bellard
                /* I/O case */
2547 13eb76e0 bellard
                io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2548 13eb76e0 bellard
                if (l >= 4 && ((addr & 3) == 0)) {
2549 13eb76e0 bellard
                    /* 32 bit read access */
2550 a4193c8a bellard
                    val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2551 c27004ec bellard
                    stl_p(buf, val);
2552 13eb76e0 bellard
                    l = 4;
2553 13eb76e0 bellard
                } else if (l >= 2 && ((addr & 1) == 0)) {
2554 13eb76e0 bellard
                    /* 16 bit read access */
2555 a4193c8a bellard
                    val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
2556 c27004ec bellard
                    stw_p(buf, val);
2557 13eb76e0 bellard
                    l = 2;
2558 13eb76e0 bellard
                } else {
2559 1c213d19 bellard
                    /* 8 bit read access */
2560 a4193c8a bellard
                    val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr);
2561 c27004ec bellard
                    stb_p(buf, val);
2562 13eb76e0 bellard
                    l = 1;
2563 13eb76e0 bellard
                }
2564 13eb76e0 bellard
            } else {
2565 13eb76e0 bellard
                /* RAM case */
2566 13eb76e0 bellard
                ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
2567 13eb76e0 bellard
                    (addr & ~TARGET_PAGE_MASK);
2568 13eb76e0 bellard
                memcpy(buf, ptr, l);
2569 13eb76e0 bellard
            }
2570 13eb76e0 bellard
        }
2571 13eb76e0 bellard
        len -= l;
2572 13eb76e0 bellard
        buf += l;
2573 13eb76e0 bellard
        addr += l;
2574 13eb76e0 bellard
    }
2575 13eb76e0 bellard
}
2576 8df1cd07 bellard
2577 d0ecd2aa bellard
/* used for ROM loading : can write in RAM and ROM */
2578 d0ecd2aa bellard
void cpu_physical_memory_write_rom(target_phys_addr_t addr, 
2579 d0ecd2aa bellard
                                   const uint8_t *buf, int len)
2580 d0ecd2aa bellard
{
2581 d0ecd2aa bellard
    int l;
2582 d0ecd2aa bellard
    uint8_t *ptr;
2583 d0ecd2aa bellard
    target_phys_addr_t page;
2584 d0ecd2aa bellard
    unsigned long pd;
2585 d0ecd2aa bellard
    PhysPageDesc *p;
2586 d0ecd2aa bellard
    
2587 d0ecd2aa bellard
    while (len > 0) {
2588 d0ecd2aa bellard
        page = addr & TARGET_PAGE_MASK;
2589 d0ecd2aa bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
2590 d0ecd2aa bellard
        if (l > len)
2591 d0ecd2aa bellard
            l = len;
2592 d0ecd2aa bellard
        p = phys_page_find(page >> TARGET_PAGE_BITS);
2593 d0ecd2aa bellard
        if (!p) {
2594 d0ecd2aa bellard
            pd = IO_MEM_UNASSIGNED;
2595 d0ecd2aa bellard
        } else {
2596 d0ecd2aa bellard
            pd = p->phys_offset;
2597 d0ecd2aa bellard
        }
2598 d0ecd2aa bellard
        
2599 d0ecd2aa bellard
        if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
2600 2a4188a3 bellard
            (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
2601 2a4188a3 bellard
            !(pd & IO_MEM_ROMD)) {
2602 d0ecd2aa bellard
            /* do nothing */
2603 d0ecd2aa bellard
        } else {
2604 d0ecd2aa bellard
            unsigned long addr1;
2605 d0ecd2aa bellard
            addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2606 d0ecd2aa bellard
            /* ROM/RAM case */
2607 d0ecd2aa bellard
            ptr = phys_ram_base + addr1;
2608 d0ecd2aa bellard
            memcpy(ptr, buf, l);
2609 d0ecd2aa bellard
        }
2610 d0ecd2aa bellard
        len -= l;
2611 d0ecd2aa bellard
        buf += l;
2612 d0ecd2aa bellard
        addr += l;
2613 d0ecd2aa bellard
    }
2614 d0ecd2aa bellard
}
2615 d0ecd2aa bellard
2616 d0ecd2aa bellard
2617 8df1cd07 bellard
/* warning: addr must be aligned */
2618 8df1cd07 bellard
uint32_t ldl_phys(target_phys_addr_t addr)
2619 8df1cd07 bellard
{
2620 8df1cd07 bellard
    int io_index;
2621 8df1cd07 bellard
    uint8_t *ptr;
2622 8df1cd07 bellard
    uint32_t val;
2623 8df1cd07 bellard
    unsigned long pd;
2624 8df1cd07 bellard
    PhysPageDesc *p;
2625 8df1cd07 bellard
2626 8df1cd07 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2627 8df1cd07 bellard
    if (!p) {
2628 8df1cd07 bellard
        pd = IO_MEM_UNASSIGNED;
2629 8df1cd07 bellard
    } else {
2630 8df1cd07 bellard
        pd = p->phys_offset;
2631 8df1cd07 bellard
    }
2632 8df1cd07 bellard
        
2633 2a4188a3 bellard
    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && 
2634 2a4188a3 bellard
        !(pd & IO_MEM_ROMD)) {
2635 8df1cd07 bellard
        /* I/O case */
2636 8df1cd07 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2637 8df1cd07 bellard
        val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2638 8df1cd07 bellard
    } else {
2639 8df1cd07 bellard
        /* RAM case */
2640 8df1cd07 bellard
        ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
2641 8df1cd07 bellard
            (addr & ~TARGET_PAGE_MASK);
2642 8df1cd07 bellard
        val = ldl_p(ptr);
2643 8df1cd07 bellard
    }
2644 8df1cd07 bellard
    return val;
2645 8df1cd07 bellard
}
2646 8df1cd07 bellard
2647 84b7b8e7 bellard
/* warning: addr must be aligned */
2648 84b7b8e7 bellard
uint64_t ldq_phys(target_phys_addr_t addr)
2649 84b7b8e7 bellard
{
2650 84b7b8e7 bellard
    int io_index;
2651 84b7b8e7 bellard
    uint8_t *ptr;
2652 84b7b8e7 bellard
    uint64_t val;
2653 84b7b8e7 bellard
    unsigned long pd;
2654 84b7b8e7 bellard
    PhysPageDesc *p;
2655 84b7b8e7 bellard
2656 84b7b8e7 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2657 84b7b8e7 bellard
    if (!p) {
2658 84b7b8e7 bellard
        pd = IO_MEM_UNASSIGNED;
2659 84b7b8e7 bellard
    } else {
2660 84b7b8e7 bellard
        pd = p->phys_offset;
2661 84b7b8e7 bellard
    }
2662 84b7b8e7 bellard
        
2663 2a4188a3 bellard
    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
2664 2a4188a3 bellard
        !(pd & IO_MEM_ROMD)) {
2665 84b7b8e7 bellard
        /* I/O case */
2666 84b7b8e7 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2667 84b7b8e7 bellard
#ifdef TARGET_WORDS_BIGENDIAN
2668 84b7b8e7 bellard
        val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
2669 84b7b8e7 bellard
        val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
2670 84b7b8e7 bellard
#else
2671 84b7b8e7 bellard
        val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2672 84b7b8e7 bellard
        val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
2673 84b7b8e7 bellard
#endif
2674 84b7b8e7 bellard
    } else {
2675 84b7b8e7 bellard
        /* RAM case */
2676 84b7b8e7 bellard
        ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
2677 84b7b8e7 bellard
            (addr & ~TARGET_PAGE_MASK);
2678 84b7b8e7 bellard
        val = ldq_p(ptr);
2679 84b7b8e7 bellard
    }
2680 84b7b8e7 bellard
    return val;
2681 84b7b8e7 bellard
}
2682 84b7b8e7 bellard
2683 aab33094 bellard
/* XXX: optimize */
2684 aab33094 bellard
uint32_t ldub_phys(target_phys_addr_t addr)
2685 aab33094 bellard
{
2686 aab33094 bellard
    uint8_t val;
2687 aab33094 bellard
    cpu_physical_memory_read(addr, &val, 1);
2688 aab33094 bellard
    return val;
2689 aab33094 bellard
}
2690 aab33094 bellard
2691 aab33094 bellard
/* XXX: optimize */
2692 aab33094 bellard
uint32_t lduw_phys(target_phys_addr_t addr)
2693 aab33094 bellard
{
2694 aab33094 bellard
    uint16_t val;
2695 aab33094 bellard
    cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
2696 aab33094 bellard
    return tswap16(val);
2697 aab33094 bellard
}
2698 aab33094 bellard
2699 8df1cd07 bellard
/* warning: addr must be aligned. The ram page is not masked as dirty
2700 8df1cd07 bellard
   and the code inside is not invalidated. It is useful if the dirty
2701 8df1cd07 bellard
   bits are used to track modified PTEs */
2702 8df1cd07 bellard
void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
2703 8df1cd07 bellard
{
2704 8df1cd07 bellard
    int io_index;
2705 8df1cd07 bellard
    uint8_t *ptr;
2706 8df1cd07 bellard
    unsigned long pd;
2707 8df1cd07 bellard
    PhysPageDesc *p;
2708 8df1cd07 bellard
2709 8df1cd07 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2710 8df1cd07 bellard
    if (!p) {
2711 8df1cd07 bellard
        pd = IO_MEM_UNASSIGNED;
2712 8df1cd07 bellard
    } else {
2713 8df1cd07 bellard
        pd = p->phys_offset;
2714 8df1cd07 bellard
    }
2715 8df1cd07 bellard
        
2716 3a7d929e bellard
    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2717 8df1cd07 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2718 8df1cd07 bellard
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2719 8df1cd07 bellard
    } else {
2720 8df1cd07 bellard
        ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
2721 8df1cd07 bellard
            (addr & ~TARGET_PAGE_MASK);
2722 8df1cd07 bellard
        stl_p(ptr, val);
2723 8df1cd07 bellard
    }
2724 8df1cd07 bellard
}
2725 8df1cd07 bellard
2726 bc98a7ef j_mayer
void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
2727 bc98a7ef j_mayer
{
2728 bc98a7ef j_mayer
    int io_index;
2729 bc98a7ef j_mayer
    uint8_t *ptr;
2730 bc98a7ef j_mayer
    unsigned long pd;
2731 bc98a7ef j_mayer
    PhysPageDesc *p;
2732 bc98a7ef j_mayer
2733 bc98a7ef j_mayer
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2734 bc98a7ef j_mayer
    if (!p) {
2735 bc98a7ef j_mayer
        pd = IO_MEM_UNASSIGNED;
2736 bc98a7ef j_mayer
    } else {
2737 bc98a7ef j_mayer
        pd = p->phys_offset;
2738 bc98a7ef j_mayer
    }
2739 bc98a7ef j_mayer
        
2740 bc98a7ef j_mayer
    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2741 bc98a7ef j_mayer
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2742 bc98a7ef j_mayer
#ifdef TARGET_WORDS_BIGENDIAN
2743 bc98a7ef j_mayer
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
2744 bc98a7ef j_mayer
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
2745 bc98a7ef j_mayer
#else
2746 bc98a7ef j_mayer
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2747 bc98a7ef j_mayer
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
2748 bc98a7ef j_mayer
#endif
2749 bc98a7ef j_mayer
    } else {
2750 bc98a7ef j_mayer
        ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
2751 bc98a7ef j_mayer
            (addr & ~TARGET_PAGE_MASK);
2752 bc98a7ef j_mayer
        stq_p(ptr, val);
2753 bc98a7ef j_mayer
    }
2754 bc98a7ef j_mayer
}
2755 bc98a7ef j_mayer
2756 8df1cd07 bellard
/* warning: addr must be aligned */
2757 8df1cd07 bellard
void stl_phys(target_phys_addr_t addr, uint32_t val)
2758 8df1cd07 bellard
{
2759 8df1cd07 bellard
    int io_index;
2760 8df1cd07 bellard
    uint8_t *ptr;
2761 8df1cd07 bellard
    unsigned long pd;
2762 8df1cd07 bellard
    PhysPageDesc *p;
2763 8df1cd07 bellard
2764 8df1cd07 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2765 8df1cd07 bellard
    if (!p) {
2766 8df1cd07 bellard
        pd = IO_MEM_UNASSIGNED;
2767 8df1cd07 bellard
    } else {
2768 8df1cd07 bellard
        pd = p->phys_offset;
2769 8df1cd07 bellard
    }
2770 8df1cd07 bellard
        
2771 3a7d929e bellard
    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
2772 8df1cd07 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2773 8df1cd07 bellard
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2774 8df1cd07 bellard
    } else {
2775 8df1cd07 bellard
        unsigned long addr1;
2776 8df1cd07 bellard
        addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2777 8df1cd07 bellard
        /* RAM case */
2778 8df1cd07 bellard
        ptr = phys_ram_base + addr1;
2779 8df1cd07 bellard
        stl_p(ptr, val);
2780 3a7d929e bellard
        if (!cpu_physical_memory_is_dirty(addr1)) {
2781 3a7d929e bellard
            /* invalidate code */
2782 3a7d929e bellard
            tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
2783 3a7d929e bellard
            /* set dirty bit */
2784 f23db169 bellard
            phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
2785 f23db169 bellard
                (0xff & ~CODE_DIRTY_FLAG);
2786 3a7d929e bellard
        }
2787 8df1cd07 bellard
    }
2788 8df1cd07 bellard
}
2789 8df1cd07 bellard
2790 aab33094 bellard
/* XXX: optimize */
2791 aab33094 bellard
void stb_phys(target_phys_addr_t addr, uint32_t val)
2792 aab33094 bellard
{
2793 aab33094 bellard
    uint8_t v = val;
2794 aab33094 bellard
    cpu_physical_memory_write(addr, &v, 1);
2795 aab33094 bellard
}
2796 aab33094 bellard
2797 aab33094 bellard
/* XXX: optimize */
2798 aab33094 bellard
void stw_phys(target_phys_addr_t addr, uint32_t val)
2799 aab33094 bellard
{
2800 aab33094 bellard
    uint16_t v = tswap16(val);
2801 aab33094 bellard
    cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
2802 aab33094 bellard
}
2803 aab33094 bellard
2804 aab33094 bellard
/* XXX: optimize */
2805 aab33094 bellard
void stq_phys(target_phys_addr_t addr, uint64_t val)
2806 aab33094 bellard
{
2807 aab33094 bellard
    val = tswap64(val);
2808 aab33094 bellard
    cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
2809 aab33094 bellard
}
2810 aab33094 bellard
2811 13eb76e0 bellard
#endif
2812 13eb76e0 bellard
2813 13eb76e0 bellard
/* virtual memory access for debug */
2814 b448f2f3 bellard
int cpu_memory_rw_debug(CPUState *env, target_ulong addr, 
2815 b448f2f3 bellard
                        uint8_t *buf, int len, int is_write)
2816 13eb76e0 bellard
{
2817 13eb76e0 bellard
    int l;
2818 9b3c35e0 j_mayer
    target_phys_addr_t phys_addr;
2819 9b3c35e0 j_mayer
    target_ulong page;
2820 13eb76e0 bellard
2821 13eb76e0 bellard
    while (len > 0) {
2822 13eb76e0 bellard
        page = addr & TARGET_PAGE_MASK;
2823 13eb76e0 bellard
        phys_addr = cpu_get_phys_page_debug(env, page);
2824 13eb76e0 bellard
        /* if no physical page mapped, return an error */
2825 13eb76e0 bellard
        if (phys_addr == -1)
2826 13eb76e0 bellard
            return -1;
2827 13eb76e0 bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
2828 13eb76e0 bellard
        if (l > len)
2829 13eb76e0 bellard
            l = len;
2830 b448f2f3 bellard
        cpu_physical_memory_rw(phys_addr + (addr & ~TARGET_PAGE_MASK), 
2831 b448f2f3 bellard
                               buf, l, is_write);
2832 13eb76e0 bellard
        len -= l;
2833 13eb76e0 bellard
        buf += l;
2834 13eb76e0 bellard
        addr += l;
2835 13eb76e0 bellard
    }
2836 13eb76e0 bellard
    return 0;
2837 13eb76e0 bellard
}
2838 13eb76e0 bellard
2839 e3db7226 bellard
void dump_exec_info(FILE *f,
2840 e3db7226 bellard
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2841 e3db7226 bellard
{
2842 e3db7226 bellard
    int i, target_code_size, max_target_code_size;
2843 e3db7226 bellard
    int direct_jmp_count, direct_jmp2_count, cross_page;
2844 e3db7226 bellard
    TranslationBlock *tb;
2845 e3db7226 bellard
    
2846 e3db7226 bellard
    target_code_size = 0;
2847 e3db7226 bellard
    max_target_code_size = 0;
2848 e3db7226 bellard
    cross_page = 0;
2849 e3db7226 bellard
    direct_jmp_count = 0;
2850 e3db7226 bellard
    direct_jmp2_count = 0;
2851 e3db7226 bellard
    for(i = 0; i < nb_tbs; i++) {
2852 e3db7226 bellard
        tb = &tbs[i];
2853 e3db7226 bellard
        target_code_size += tb->size;
2854 e3db7226 bellard
        if (tb->size > max_target_code_size)
2855 e3db7226 bellard
            max_target_code_size = tb->size;
2856 e3db7226 bellard
        if (tb->page_addr[1] != -1)
2857 e3db7226 bellard
            cross_page++;
2858 e3db7226 bellard
        if (tb->tb_next_offset[0] != 0xffff) {
2859 e3db7226 bellard
            direct_jmp_count++;
2860 e3db7226 bellard
            if (tb->tb_next_offset[1] != 0xffff) {
2861 e3db7226 bellard
                direct_jmp2_count++;
2862 e3db7226 bellard
            }
2863 e3db7226 bellard
        }
2864 e3db7226 bellard
    }
2865 e3db7226 bellard
    /* XXX: avoid using doubles ? */
2866 e3db7226 bellard
    cpu_fprintf(f, "TB count            %d\n", nb_tbs);
2867 e3db7226 bellard
    cpu_fprintf(f, "TB avg target size  %d max=%d bytes\n", 
2868 e3db7226 bellard
                nb_tbs ? target_code_size / nb_tbs : 0,
2869 e3db7226 bellard
                max_target_code_size);
2870 e3db7226 bellard
    cpu_fprintf(f, "TB avg host size    %d bytes (expansion ratio: %0.1f)\n", 
2871 e3db7226 bellard
                nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
2872 e3db7226 bellard
                target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
2873 e3db7226 bellard
    cpu_fprintf(f, "cross page TB count %d (%d%%)\n", 
2874 e3db7226 bellard
            cross_page, 
2875 e3db7226 bellard
            nb_tbs ? (cross_page * 100) / nb_tbs : 0);
2876 e3db7226 bellard
    cpu_fprintf(f, "direct jump count   %d (%d%%) (2 jumps=%d %d%%)\n",
2877 e3db7226 bellard
                direct_jmp_count, 
2878 e3db7226 bellard
                nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
2879 e3db7226 bellard
                direct_jmp2_count,
2880 e3db7226 bellard
                nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
2881 e3db7226 bellard
    cpu_fprintf(f, "TB flush count      %d\n", tb_flush_count);
2882 e3db7226 bellard
    cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
2883 e3db7226 bellard
    cpu_fprintf(f, "TLB flush count     %d\n", tlb_flush_count);
2884 e3db7226 bellard
}
2885 e3db7226 bellard
2886 61382a50 bellard
#if !defined(CONFIG_USER_ONLY) 
2887 61382a50 bellard
2888 61382a50 bellard
#define MMUSUFFIX _cmmu
2889 61382a50 bellard
#define GETPC() NULL
2890 61382a50 bellard
#define env cpu_single_env
2891 b769d8fe bellard
#define SOFTMMU_CODE_ACCESS
2892 61382a50 bellard
2893 61382a50 bellard
#define SHIFT 0
2894 61382a50 bellard
#include "softmmu_template.h"
2895 61382a50 bellard
2896 61382a50 bellard
#define SHIFT 1
2897 61382a50 bellard
#include "softmmu_template.h"
2898 61382a50 bellard
2899 61382a50 bellard
#define SHIFT 2
2900 61382a50 bellard
#include "softmmu_template.h"
2901 61382a50 bellard
2902 61382a50 bellard
#define SHIFT 3
2903 61382a50 bellard
#include "softmmu_template.h"
2904 61382a50 bellard
2905 61382a50 bellard
#undef env
2906 61382a50 bellard
2907 61382a50 bellard
#endif