Statistics
| Branch: | Revision:

root / exec.c @ 724db118

History | View | Annotate | Download (90.6 kB)

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