Statistics
| Branch: | Revision:

root / exec.c @ db7b5426

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