Statistics
| Branch: | Revision:

root / exec.c @ 9c7e37e7

History | View | Annotate | Download (87.2 kB)

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