Statistics
| Branch: | Revision:

root / exec.c @ d3219c7b

History | View | Annotate | Download (110.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 8167ee88 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 54936004 bellard
 */
19 67b915a5 bellard
#include "config.h"
20 d5a8f07c bellard
#ifdef _WIN32
21 d5a8f07c bellard
#include <windows.h>
22 d5a8f07c bellard
#else
23 a98d49b1 bellard
#include <sys/types.h>
24 d5a8f07c bellard
#include <sys/mman.h>
25 d5a8f07c bellard
#endif
26 54936004 bellard
#include <stdlib.h>
27 54936004 bellard
#include <stdio.h>
28 54936004 bellard
#include <stdarg.h>
29 54936004 bellard
#include <string.h>
30 54936004 bellard
#include <errno.h>
31 54936004 bellard
#include <unistd.h>
32 54936004 bellard
#include <inttypes.h>
33 54936004 bellard
34 6180a181 bellard
#include "cpu.h"
35 6180a181 bellard
#include "exec-all.h"
36 ca10f867 aurel32
#include "qemu-common.h"
37 b67d9a52 bellard
#include "tcg.h"
38 b3c7724c pbrook
#include "hw/hw.h"
39 74576198 aliguori
#include "osdep.h"
40 7ba1e619 aliguori
#include "kvm.h"
41 53a5960a pbrook
#if defined(CONFIG_USER_ONLY)
42 53a5960a pbrook
#include <qemu.h>
43 d3219c7b Riku Voipio
#include <signal.h>
44 53a5960a pbrook
#endif
45 54936004 bellard
46 fd6ce8f6 bellard
//#define DEBUG_TB_INVALIDATE
47 66e85a21 bellard
//#define DEBUG_FLUSH
48 9fa3e853 bellard
//#define DEBUG_TLB
49 67d3b957 pbrook
//#define DEBUG_UNASSIGNED
50 fd6ce8f6 bellard
51 fd6ce8f6 bellard
/* make various TB consistency checks */
52 5fafdf24 ths
//#define DEBUG_TB_CHECK
53 5fafdf24 ths
//#define DEBUG_TLB_CHECK
54 fd6ce8f6 bellard
55 1196be37 ths
//#define DEBUG_IOPORT
56 db7b5426 blueswir1
//#define DEBUG_SUBPAGE
57 1196be37 ths
58 99773bd4 pbrook
#if !defined(CONFIG_USER_ONLY)
59 99773bd4 pbrook
/* TB consistency checks only implemented for usermode emulation.  */
60 99773bd4 pbrook
#undef DEBUG_TB_CHECK
61 99773bd4 pbrook
#endif
62 99773bd4 pbrook
63 9fa3e853 bellard
#define SMC_BITMAP_USE_THRESHOLD 10
64 9fa3e853 bellard
65 108c49b8 bellard
#if defined(TARGET_SPARC64)
66 108c49b8 bellard
#define TARGET_PHYS_ADDR_SPACE_BITS 41
67 5dcb6b91 blueswir1
#elif defined(TARGET_SPARC)
68 5dcb6b91 blueswir1
#define TARGET_PHYS_ADDR_SPACE_BITS 36
69 bedb69ea j_mayer
#elif defined(TARGET_ALPHA)
70 bedb69ea j_mayer
#define TARGET_PHYS_ADDR_SPACE_BITS 42
71 bedb69ea j_mayer
#define TARGET_VIRT_ADDR_SPACE_BITS 42
72 108c49b8 bellard
#elif defined(TARGET_PPC64)
73 108c49b8 bellard
#define TARGET_PHYS_ADDR_SPACE_BITS 42
74 4a1418e0 Anthony Liguori
#elif defined(TARGET_X86_64)
75 00f82b8a aurel32
#define TARGET_PHYS_ADDR_SPACE_BITS 42
76 4a1418e0 Anthony Liguori
#elif defined(TARGET_I386)
77 00f82b8a aurel32
#define TARGET_PHYS_ADDR_SPACE_BITS 36
78 108c49b8 bellard
#else
79 108c49b8 bellard
#define TARGET_PHYS_ADDR_SPACE_BITS 32
80 108c49b8 bellard
#endif
81 108c49b8 bellard
82 bdaf78e0 blueswir1
static TranslationBlock *tbs;
83 26a5f13b bellard
int code_gen_max_blocks;
84 9fa3e853 bellard
TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
85 bdaf78e0 blueswir1
static int nb_tbs;
86 eb51d102 bellard
/* any access to the tbs or the page table must use this lock */
87 c227f099 Anthony Liguori
spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
88 fd6ce8f6 bellard
89 141ac468 blueswir1
#if defined(__arm__) || defined(__sparc_v9__)
90 141ac468 blueswir1
/* The prologue must be reachable with a direct jump. ARM and Sparc64
91 141ac468 blueswir1
 have limited branch ranges (possibly also PPC) so place it in a
92 d03d860b blueswir1
 section close to code segment. */
93 d03d860b blueswir1
#define code_gen_section                                \
94 d03d860b blueswir1
    __attribute__((__section__(".gen_code")))           \
95 d03d860b blueswir1
    __attribute__((aligned (32)))
96 f8e2af11 Stefan Weil
#elif defined(_WIN32)
97 f8e2af11 Stefan Weil
/* Maximum alignment for Win32 is 16. */
98 f8e2af11 Stefan Weil
#define code_gen_section                                \
99 f8e2af11 Stefan Weil
    __attribute__((aligned (16)))
100 d03d860b blueswir1
#else
101 d03d860b blueswir1
#define code_gen_section                                \
102 d03d860b blueswir1
    __attribute__((aligned (32)))
103 d03d860b blueswir1
#endif
104 d03d860b blueswir1
105 d03d860b blueswir1
uint8_t code_gen_prologue[1024] code_gen_section;
106 bdaf78e0 blueswir1
static uint8_t *code_gen_buffer;
107 bdaf78e0 blueswir1
static unsigned long code_gen_buffer_size;
108 26a5f13b bellard
/* threshold to flush the translated code buffer */
109 bdaf78e0 blueswir1
static unsigned long code_gen_buffer_max_size;
110 fd6ce8f6 bellard
uint8_t *code_gen_ptr;
111 fd6ce8f6 bellard
112 e2eef170 pbrook
#if !defined(CONFIG_USER_ONLY)
113 9fa3e853 bellard
int phys_ram_fd;
114 1ccde1cb bellard
uint8_t *phys_ram_dirty;
115 74576198 aliguori
static int in_migration;
116 94a6b54f pbrook
117 94a6b54f pbrook
typedef struct RAMBlock {
118 94a6b54f pbrook
    uint8_t *host;
119 c227f099 Anthony Liguori
    ram_addr_t offset;
120 c227f099 Anthony Liguori
    ram_addr_t length;
121 94a6b54f pbrook
    struct RAMBlock *next;
122 94a6b54f pbrook
} RAMBlock;
123 94a6b54f pbrook
124 94a6b54f pbrook
static RAMBlock *ram_blocks;
125 94a6b54f pbrook
/* TODO: When we implement (and use) ram deallocation (e.g. for hotplug)
126 ccbb4d44 Stuart Brady
   then we can no longer assume contiguous ram offsets, and external uses
127 94a6b54f pbrook
   of this variable will break.  */
128 c227f099 Anthony Liguori
ram_addr_t last_ram_offset;
129 e2eef170 pbrook
#endif
130 9fa3e853 bellard
131 6a00d601 bellard
CPUState *first_cpu;
132 6a00d601 bellard
/* current CPU in the current thread. It is only valid inside
133 6a00d601 bellard
   cpu_exec() */
134 5fafdf24 ths
CPUState *cpu_single_env;
135 2e70f6ef pbrook
/* 0 = Do not count executed instructions.
136 bf20dc07 ths
   1 = Precise instruction counting.
137 2e70f6ef pbrook
   2 = Adaptive rate instruction counting.  */
138 2e70f6ef pbrook
int use_icount = 0;
139 2e70f6ef pbrook
/* Current instruction counter.  While executing translated code this may
140 2e70f6ef pbrook
   include some instructions that have not yet been executed.  */
141 2e70f6ef pbrook
int64_t qemu_icount;
142 6a00d601 bellard
143 54936004 bellard
typedef struct PageDesc {
144 92e873b9 bellard
    /* list of TBs intersecting this ram page */
145 fd6ce8f6 bellard
    TranslationBlock *first_tb;
146 9fa3e853 bellard
    /* in order to optimize self modifying code, we count the number
147 9fa3e853 bellard
       of lookups we do to a given page to use a bitmap */
148 9fa3e853 bellard
    unsigned int code_write_count;
149 9fa3e853 bellard
    uint8_t *code_bitmap;
150 9fa3e853 bellard
#if defined(CONFIG_USER_ONLY)
151 9fa3e853 bellard
    unsigned long flags;
152 9fa3e853 bellard
#endif
153 54936004 bellard
} PageDesc;
154 54936004 bellard
155 92e873b9 bellard
typedef struct PhysPageDesc {
156 0f459d16 pbrook
    /* offset in host memory of the page + io_index in the low bits */
157 c227f099 Anthony Liguori
    ram_addr_t phys_offset;
158 c227f099 Anthony Liguori
    ram_addr_t region_offset;
159 92e873b9 bellard
} PhysPageDesc;
160 92e873b9 bellard
161 54936004 bellard
#define L2_BITS 10
162 bedb69ea j_mayer
#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
163 bedb69ea j_mayer
/* XXX: this is a temporary hack for alpha target.
164 bedb69ea j_mayer
 *      In the future, this is to be replaced by a multi-level table
165 bedb69ea j_mayer
 *      to actually be able to handle the complete 64 bits address space.
166 bedb69ea j_mayer
 */
167 bedb69ea j_mayer
#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
168 bedb69ea j_mayer
#else
169 03875444 aurel32
#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
170 bedb69ea j_mayer
#endif
171 54936004 bellard
172 54936004 bellard
#define L1_SIZE (1 << L1_BITS)
173 54936004 bellard
#define L2_SIZE (1 << L2_BITS)
174 54936004 bellard
175 83fb7adf bellard
unsigned long qemu_real_host_page_size;
176 83fb7adf bellard
unsigned long qemu_host_page_bits;
177 83fb7adf bellard
unsigned long qemu_host_page_size;
178 83fb7adf bellard
unsigned long qemu_host_page_mask;
179 54936004 bellard
180 92e873b9 bellard
/* XXX: for system emulation, it could just be an array */
181 54936004 bellard
static PageDesc *l1_map[L1_SIZE];
182 bdaf78e0 blueswir1
static PhysPageDesc **l1_phys_map;
183 54936004 bellard
184 e2eef170 pbrook
#if !defined(CONFIG_USER_ONLY)
185 e2eef170 pbrook
static void io_mem_init(void);
186 e2eef170 pbrook
187 33417e70 bellard
/* io memory support */
188 33417e70 bellard
CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
189 33417e70 bellard
CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
190 a4193c8a bellard
void *io_mem_opaque[IO_MEM_NB_ENTRIES];
191 511d2b14 blueswir1
static char io_mem_used[IO_MEM_NB_ENTRIES];
192 6658ffb8 pbrook
static int io_mem_watch;
193 6658ffb8 pbrook
#endif
194 33417e70 bellard
195 34865134 bellard
/* log support */
196 1e8b27ca Juha Riihimรคki
#ifdef WIN32
197 1e8b27ca Juha Riihimรคki
static const char *logfilename = "qemu.log";
198 1e8b27ca Juha Riihimรคki
#else
199 d9b630fd blueswir1
static const char *logfilename = "/tmp/qemu.log";
200 1e8b27ca Juha Riihimรคki
#endif
201 34865134 bellard
FILE *logfile;
202 34865134 bellard
int loglevel;
203 e735b91c pbrook
static int log_append = 0;
204 34865134 bellard
205 e3db7226 bellard
/* statistics */
206 e3db7226 bellard
static int tlb_flush_count;
207 e3db7226 bellard
static int tb_flush_count;
208 e3db7226 bellard
static int tb_phys_invalidate_count;
209 e3db7226 bellard
210 db7b5426 blueswir1
#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
211 c227f099 Anthony Liguori
typedef struct subpage_t {
212 c227f099 Anthony Liguori
    target_phys_addr_t base;
213 d60efc6b Blue Swirl
    CPUReadMemoryFunc * const *mem_read[TARGET_PAGE_SIZE][4];
214 d60efc6b Blue Swirl
    CPUWriteMemoryFunc * const *mem_write[TARGET_PAGE_SIZE][4];
215 3ee89922 blueswir1
    void *opaque[TARGET_PAGE_SIZE][2][4];
216 c227f099 Anthony Liguori
    ram_addr_t region_offset[TARGET_PAGE_SIZE][2][4];
217 c227f099 Anthony Liguori
} subpage_t;
218 db7b5426 blueswir1
219 7cb69cae bellard
#ifdef _WIN32
220 7cb69cae bellard
static void map_exec(void *addr, long size)
221 7cb69cae bellard
{
222 7cb69cae bellard
    DWORD old_protect;
223 7cb69cae bellard
    VirtualProtect(addr, size,
224 7cb69cae bellard
                   PAGE_EXECUTE_READWRITE, &old_protect);
225 7cb69cae bellard
    
226 7cb69cae bellard
}
227 7cb69cae bellard
#else
228 7cb69cae bellard
static void map_exec(void *addr, long size)
229 7cb69cae bellard
{
230 4369415f bellard
    unsigned long start, end, page_size;
231 7cb69cae bellard
    
232 4369415f bellard
    page_size = getpagesize();
233 7cb69cae bellard
    start = (unsigned long)addr;
234 4369415f bellard
    start &= ~(page_size - 1);
235 7cb69cae bellard
    
236 7cb69cae bellard
    end = (unsigned long)addr + size;
237 4369415f bellard
    end += page_size - 1;
238 4369415f bellard
    end &= ~(page_size - 1);
239 7cb69cae bellard
    
240 7cb69cae bellard
    mprotect((void *)start, end - start,
241 7cb69cae bellard
             PROT_READ | PROT_WRITE | PROT_EXEC);
242 7cb69cae bellard
}
243 7cb69cae bellard
#endif
244 7cb69cae bellard
245 b346ff46 bellard
static void page_init(void)
246 54936004 bellard
{
247 83fb7adf bellard
    /* NOTE: we can always suppose that qemu_host_page_size >=
248 54936004 bellard
       TARGET_PAGE_SIZE */
249 c2b48b69 aliguori
#ifdef _WIN32
250 c2b48b69 aliguori
    {
251 c2b48b69 aliguori
        SYSTEM_INFO system_info;
252 c2b48b69 aliguori
253 c2b48b69 aliguori
        GetSystemInfo(&system_info);
254 c2b48b69 aliguori
        qemu_real_host_page_size = system_info.dwPageSize;
255 c2b48b69 aliguori
    }
256 c2b48b69 aliguori
#else
257 c2b48b69 aliguori
    qemu_real_host_page_size = getpagesize();
258 c2b48b69 aliguori
#endif
259 83fb7adf bellard
    if (qemu_host_page_size == 0)
260 83fb7adf bellard
        qemu_host_page_size = qemu_real_host_page_size;
261 83fb7adf bellard
    if (qemu_host_page_size < TARGET_PAGE_SIZE)
262 83fb7adf bellard
        qemu_host_page_size = TARGET_PAGE_SIZE;
263 83fb7adf bellard
    qemu_host_page_bits = 0;
264 83fb7adf bellard
    while ((1 << qemu_host_page_bits) < qemu_host_page_size)
265 83fb7adf bellard
        qemu_host_page_bits++;
266 83fb7adf bellard
    qemu_host_page_mask = ~(qemu_host_page_size - 1);
267 108c49b8 bellard
    l1_phys_map = qemu_vmalloc(L1_SIZE * sizeof(void *));
268 108c49b8 bellard
    memset(l1_phys_map, 0, L1_SIZE * sizeof(void *));
269 50a9569b balrog
270 50a9569b balrog
#if !defined(_WIN32) && defined(CONFIG_USER_ONLY)
271 50a9569b balrog
    {
272 50a9569b balrog
        long long startaddr, endaddr;
273 50a9569b balrog
        FILE *f;
274 50a9569b balrog
        int n;
275 50a9569b balrog
276 c8a706fe pbrook
        mmap_lock();
277 0776590d pbrook
        last_brk = (unsigned long)sbrk(0);
278 50a9569b balrog
        f = fopen("/proc/self/maps", "r");
279 50a9569b balrog
        if (f) {
280 50a9569b balrog
            do {
281 50a9569b balrog
                n = fscanf (f, "%llx-%llx %*[^\n]\n", &startaddr, &endaddr);
282 50a9569b balrog
                if (n == 2) {
283 e0b8d65a blueswir1
                    startaddr = MIN(startaddr,
284 e0b8d65a blueswir1
                                    (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
285 e0b8d65a blueswir1
                    endaddr = MIN(endaddr,
286 e0b8d65a blueswir1
                                    (1ULL << TARGET_PHYS_ADDR_SPACE_BITS) - 1);
287 b5fc909e pbrook
                    page_set_flags(startaddr & TARGET_PAGE_MASK,
288 50a9569b balrog
                                   TARGET_PAGE_ALIGN(endaddr),
289 50a9569b balrog
                                   PAGE_RESERVED); 
290 50a9569b balrog
                }
291 50a9569b balrog
            } while (!feof(f));
292 50a9569b balrog
            fclose(f);
293 50a9569b balrog
        }
294 c8a706fe pbrook
        mmap_unlock();
295 50a9569b balrog
    }
296 50a9569b balrog
#endif
297 54936004 bellard
}
298 54936004 bellard
299 434929bf aliguori
static inline PageDesc **page_l1_map(target_ulong index)
300 54936004 bellard
{
301 17e2377a pbrook
#if TARGET_LONG_BITS > 32
302 17e2377a pbrook
    /* Host memory outside guest VM.  For 32-bit targets we have already
303 17e2377a pbrook
       excluded high addresses.  */
304 d8173e0f ths
    if (index > ((target_ulong)L2_SIZE * L1_SIZE))
305 17e2377a pbrook
        return NULL;
306 17e2377a pbrook
#endif
307 434929bf aliguori
    return &l1_map[index >> L2_BITS];
308 434929bf aliguori
}
309 434929bf aliguori
310 434929bf aliguori
static inline PageDesc *page_find_alloc(target_ulong index)
311 434929bf aliguori
{
312 434929bf aliguori
    PageDesc **lp, *p;
313 434929bf aliguori
    lp = page_l1_map(index);
314 434929bf aliguori
    if (!lp)
315 434929bf aliguori
        return NULL;
316 434929bf aliguori
317 54936004 bellard
    p = *lp;
318 54936004 bellard
    if (!p) {
319 54936004 bellard
        /* allocate if not found */
320 17e2377a pbrook
#if defined(CONFIG_USER_ONLY)
321 17e2377a pbrook
        size_t len = sizeof(PageDesc) * L2_SIZE;
322 17e2377a pbrook
        /* Don't use qemu_malloc because it may recurse.  */
323 660f11be Blue Swirl
        p = mmap(NULL, len, PROT_READ | PROT_WRITE,
324 17e2377a pbrook
                 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
325 54936004 bellard
        *lp = p;
326 fb1c2cd7 aurel32
        if (h2g_valid(p)) {
327 fb1c2cd7 aurel32
            unsigned long addr = h2g(p);
328 17e2377a pbrook
            page_set_flags(addr & TARGET_PAGE_MASK,
329 17e2377a pbrook
                           TARGET_PAGE_ALIGN(addr + len),
330 17e2377a pbrook
                           PAGE_RESERVED); 
331 17e2377a pbrook
        }
332 17e2377a pbrook
#else
333 17e2377a pbrook
        p = qemu_mallocz(sizeof(PageDesc) * L2_SIZE);
334 17e2377a pbrook
        *lp = p;
335 17e2377a pbrook
#endif
336 54936004 bellard
    }
337 54936004 bellard
    return p + (index & (L2_SIZE - 1));
338 54936004 bellard
}
339 54936004 bellard
340 00f82b8a aurel32
static inline PageDesc *page_find(target_ulong index)
341 54936004 bellard
{
342 434929bf aliguori
    PageDesc **lp, *p;
343 434929bf aliguori
    lp = page_l1_map(index);
344 434929bf aliguori
    if (!lp)
345 434929bf aliguori
        return NULL;
346 54936004 bellard
347 434929bf aliguori
    p = *lp;
348 660f11be Blue Swirl
    if (!p) {
349 660f11be Blue Swirl
        return NULL;
350 660f11be Blue Swirl
    }
351 fd6ce8f6 bellard
    return p + (index & (L2_SIZE - 1));
352 fd6ce8f6 bellard
}
353 fd6ce8f6 bellard
354 c227f099 Anthony Liguori
static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
355 92e873b9 bellard
{
356 108c49b8 bellard
    void **lp, **p;
357 e3f4e2a4 pbrook
    PhysPageDesc *pd;
358 92e873b9 bellard
359 108c49b8 bellard
    p = (void **)l1_phys_map;
360 108c49b8 bellard
#if TARGET_PHYS_ADDR_SPACE_BITS > 32
361 108c49b8 bellard
362 108c49b8 bellard
#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
363 108c49b8 bellard
#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
364 108c49b8 bellard
#endif
365 108c49b8 bellard
    lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1));
366 92e873b9 bellard
    p = *lp;
367 92e873b9 bellard
    if (!p) {
368 92e873b9 bellard
        /* allocate if not found */
369 108c49b8 bellard
        if (!alloc)
370 108c49b8 bellard
            return NULL;
371 108c49b8 bellard
        p = qemu_vmalloc(sizeof(void *) * L1_SIZE);
372 108c49b8 bellard
        memset(p, 0, sizeof(void *) * L1_SIZE);
373 108c49b8 bellard
        *lp = p;
374 108c49b8 bellard
    }
375 108c49b8 bellard
#endif
376 108c49b8 bellard
    lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
377 e3f4e2a4 pbrook
    pd = *lp;
378 e3f4e2a4 pbrook
    if (!pd) {
379 e3f4e2a4 pbrook
        int i;
380 108c49b8 bellard
        /* allocate if not found */
381 108c49b8 bellard
        if (!alloc)
382 108c49b8 bellard
            return NULL;
383 e3f4e2a4 pbrook
        pd = qemu_vmalloc(sizeof(PhysPageDesc) * L2_SIZE);
384 e3f4e2a4 pbrook
        *lp = pd;
385 67c4d23c pbrook
        for (i = 0; i < L2_SIZE; i++) {
386 e3f4e2a4 pbrook
          pd[i].phys_offset = IO_MEM_UNASSIGNED;
387 67c4d23c pbrook
          pd[i].region_offset = (index + i) << TARGET_PAGE_BITS;
388 67c4d23c pbrook
        }
389 92e873b9 bellard
    }
390 e3f4e2a4 pbrook
    return ((PhysPageDesc *)pd) + (index & (L2_SIZE - 1));
391 92e873b9 bellard
}
392 92e873b9 bellard
393 c227f099 Anthony Liguori
static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
394 92e873b9 bellard
{
395 108c49b8 bellard
    return phys_page_find_alloc(index, 0);
396 92e873b9 bellard
}
397 92e873b9 bellard
398 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
399 c227f099 Anthony Liguori
static void tlb_protect_code(ram_addr_t ram_addr);
400 c227f099 Anthony Liguori
static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
401 3a7d929e bellard
                                    target_ulong vaddr);
402 c8a706fe pbrook
#define mmap_lock() do { } while(0)
403 c8a706fe pbrook
#define mmap_unlock() do { } while(0)
404 9fa3e853 bellard
#endif
405 fd6ce8f6 bellard
406 4369415f bellard
#define DEFAULT_CODE_GEN_BUFFER_SIZE (32 * 1024 * 1024)
407 4369415f bellard
408 4369415f bellard
#if defined(CONFIG_USER_ONLY)
409 ccbb4d44 Stuart Brady
/* Currently it is not recommended to allocate big chunks of data in
410 4369415f bellard
   user mode. It will change when a dedicated libc will be used */
411 4369415f bellard
#define USE_STATIC_CODE_GEN_BUFFER
412 4369415f bellard
#endif
413 4369415f bellard
414 4369415f bellard
#ifdef USE_STATIC_CODE_GEN_BUFFER
415 4369415f bellard
static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE];
416 4369415f bellard
#endif
417 4369415f bellard
418 8fcd3692 blueswir1
static void code_gen_alloc(unsigned long tb_size)
419 26a5f13b bellard
{
420 4369415f bellard
#ifdef USE_STATIC_CODE_GEN_BUFFER
421 4369415f bellard
    code_gen_buffer = static_code_gen_buffer;
422 4369415f bellard
    code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
423 4369415f bellard
    map_exec(code_gen_buffer, code_gen_buffer_size);
424 4369415f bellard
#else
425 26a5f13b bellard
    code_gen_buffer_size = tb_size;
426 26a5f13b bellard
    if (code_gen_buffer_size == 0) {
427 4369415f bellard
#if defined(CONFIG_USER_ONLY)
428 4369415f bellard
        /* in user mode, phys_ram_size is not meaningful */
429 4369415f bellard
        code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
430 4369415f bellard
#else
431 ccbb4d44 Stuart Brady
        /* XXX: needs adjustments */
432 94a6b54f pbrook
        code_gen_buffer_size = (unsigned long)(ram_size / 4);
433 4369415f bellard
#endif
434 26a5f13b bellard
    }
435 26a5f13b bellard
    if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE)
436 26a5f13b bellard
        code_gen_buffer_size = MIN_CODE_GEN_BUFFER_SIZE;
437 26a5f13b bellard
    /* The code gen buffer location may have constraints depending on
438 26a5f13b bellard
       the host cpu and OS */
439 26a5f13b bellard
#if defined(__linux__) 
440 26a5f13b bellard
    {
441 26a5f13b bellard
        int flags;
442 141ac468 blueswir1
        void *start = NULL;
443 141ac468 blueswir1
444 26a5f13b bellard
        flags = MAP_PRIVATE | MAP_ANONYMOUS;
445 26a5f13b bellard
#if defined(__x86_64__)
446 26a5f13b bellard
        flags |= MAP_32BIT;
447 26a5f13b bellard
        /* Cannot map more than that */
448 26a5f13b bellard
        if (code_gen_buffer_size > (800 * 1024 * 1024))
449 26a5f13b bellard
            code_gen_buffer_size = (800 * 1024 * 1024);
450 141ac468 blueswir1
#elif defined(__sparc_v9__)
451 141ac468 blueswir1
        // Map the buffer below 2G, so we can use direct calls and branches
452 141ac468 blueswir1
        flags |= MAP_FIXED;
453 141ac468 blueswir1
        start = (void *) 0x60000000UL;
454 141ac468 blueswir1
        if (code_gen_buffer_size > (512 * 1024 * 1024))
455 141ac468 blueswir1
            code_gen_buffer_size = (512 * 1024 * 1024);
456 1cb0661e balrog
#elif defined(__arm__)
457 63d41246 balrog
        /* Map the buffer below 32M, so we can use direct calls and branches */
458 1cb0661e balrog
        flags |= MAP_FIXED;
459 1cb0661e balrog
        start = (void *) 0x01000000UL;
460 1cb0661e balrog
        if (code_gen_buffer_size > 16 * 1024 * 1024)
461 1cb0661e balrog
            code_gen_buffer_size = 16 * 1024 * 1024;
462 26a5f13b bellard
#endif
463 141ac468 blueswir1
        code_gen_buffer = mmap(start, code_gen_buffer_size,
464 141ac468 blueswir1
                               PROT_WRITE | PROT_READ | PROT_EXEC,
465 26a5f13b bellard
                               flags, -1, 0);
466 26a5f13b bellard
        if (code_gen_buffer == MAP_FAILED) {
467 26a5f13b bellard
            fprintf(stderr, "Could not allocate dynamic translator buffer\n");
468 26a5f13b bellard
            exit(1);
469 26a5f13b bellard
        }
470 26a5f13b bellard
    }
471 a167ba50 Aurelien Jarno
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
472 06e67a82 aliguori
    {
473 06e67a82 aliguori
        int flags;
474 06e67a82 aliguori
        void *addr = NULL;
475 06e67a82 aliguori
        flags = MAP_PRIVATE | MAP_ANONYMOUS;
476 06e67a82 aliguori
#if defined(__x86_64__)
477 06e67a82 aliguori
        /* FreeBSD doesn't have MAP_32BIT, use MAP_FIXED and assume
478 06e67a82 aliguori
         * 0x40000000 is free */
479 06e67a82 aliguori
        flags |= MAP_FIXED;
480 06e67a82 aliguori
        addr = (void *)0x40000000;
481 06e67a82 aliguori
        /* Cannot map more than that */
482 06e67a82 aliguori
        if (code_gen_buffer_size > (800 * 1024 * 1024))
483 06e67a82 aliguori
            code_gen_buffer_size = (800 * 1024 * 1024);
484 06e67a82 aliguori
#endif
485 06e67a82 aliguori
        code_gen_buffer = mmap(addr, code_gen_buffer_size,
486 06e67a82 aliguori
                               PROT_WRITE | PROT_READ | PROT_EXEC, 
487 06e67a82 aliguori
                               flags, -1, 0);
488 06e67a82 aliguori
        if (code_gen_buffer == MAP_FAILED) {
489 06e67a82 aliguori
            fprintf(stderr, "Could not allocate dynamic translator buffer\n");
490 06e67a82 aliguori
            exit(1);
491 06e67a82 aliguori
        }
492 06e67a82 aliguori
    }
493 26a5f13b bellard
#else
494 26a5f13b bellard
    code_gen_buffer = qemu_malloc(code_gen_buffer_size);
495 26a5f13b bellard
    map_exec(code_gen_buffer, code_gen_buffer_size);
496 26a5f13b bellard
#endif
497 4369415f bellard
#endif /* !USE_STATIC_CODE_GEN_BUFFER */
498 26a5f13b bellard
    map_exec(code_gen_prologue, sizeof(code_gen_prologue));
499 26a5f13b bellard
    code_gen_buffer_max_size = code_gen_buffer_size - 
500 26a5f13b bellard
        code_gen_max_block_size();
501 26a5f13b bellard
    code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
502 26a5f13b bellard
    tbs = qemu_malloc(code_gen_max_blocks * sizeof(TranslationBlock));
503 26a5f13b bellard
}
504 26a5f13b bellard
505 26a5f13b bellard
/* Must be called before using the QEMU cpus. 'tb_size' is the size
506 26a5f13b bellard
   (in bytes) allocated to the translation buffer. Zero means default
507 26a5f13b bellard
   size. */
508 26a5f13b bellard
void cpu_exec_init_all(unsigned long tb_size)
509 26a5f13b bellard
{
510 26a5f13b bellard
    cpu_gen_init();
511 26a5f13b bellard
    code_gen_alloc(tb_size);
512 26a5f13b bellard
    code_gen_ptr = code_gen_buffer;
513 4369415f bellard
    page_init();
514 e2eef170 pbrook
#if !defined(CONFIG_USER_ONLY)
515 26a5f13b bellard
    io_mem_init();
516 e2eef170 pbrook
#endif
517 26a5f13b bellard
}
518 26a5f13b bellard
519 9656f324 pbrook
#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
520 9656f324 pbrook
521 d4bfa4d7 Juan Quintela
static void cpu_common_pre_save(void *opaque)
522 9656f324 pbrook
{
523 d4bfa4d7 Juan Quintela
    CPUState *env = opaque;
524 9656f324 pbrook
525 4c0960c0 Avi Kivity
    cpu_synchronize_state(env);
526 9656f324 pbrook
}
527 9656f324 pbrook
528 e7f4eff7 Juan Quintela
static int cpu_common_pre_load(void *opaque)
529 9656f324 pbrook
{
530 9656f324 pbrook
    CPUState *env = opaque;
531 9656f324 pbrook
532 4c0960c0 Avi Kivity
    cpu_synchronize_state(env);
533 e7f4eff7 Juan Quintela
    return 0;
534 e7f4eff7 Juan Quintela
}
535 e7f4eff7 Juan Quintela
536 e59fb374 Juan Quintela
static int cpu_common_post_load(void *opaque, int version_id)
537 e7f4eff7 Juan Quintela
{
538 e7f4eff7 Juan Quintela
    CPUState *env = opaque;
539 9656f324 pbrook
540 3098dba0 aurel32
    /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
541 3098dba0 aurel32
       version_id is increased. */
542 3098dba0 aurel32
    env->interrupt_request &= ~0x01;
543 9656f324 pbrook
    tlb_flush(env, 1);
544 9656f324 pbrook
545 9656f324 pbrook
    return 0;
546 9656f324 pbrook
}
547 e7f4eff7 Juan Quintela
548 e7f4eff7 Juan Quintela
static const VMStateDescription vmstate_cpu_common = {
549 e7f4eff7 Juan Quintela
    .name = "cpu_common",
550 e7f4eff7 Juan Quintela
    .version_id = 1,
551 e7f4eff7 Juan Quintela
    .minimum_version_id = 1,
552 e7f4eff7 Juan Quintela
    .minimum_version_id_old = 1,
553 e7f4eff7 Juan Quintela
    .pre_save = cpu_common_pre_save,
554 e7f4eff7 Juan Quintela
    .pre_load = cpu_common_pre_load,
555 e7f4eff7 Juan Quintela
    .post_load = cpu_common_post_load,
556 e7f4eff7 Juan Quintela
    .fields      = (VMStateField []) {
557 e7f4eff7 Juan Quintela
        VMSTATE_UINT32(halted, CPUState),
558 e7f4eff7 Juan Quintela
        VMSTATE_UINT32(interrupt_request, CPUState),
559 e7f4eff7 Juan Quintela
        VMSTATE_END_OF_LIST()
560 e7f4eff7 Juan Quintela
    }
561 e7f4eff7 Juan Quintela
};
562 9656f324 pbrook
#endif
563 9656f324 pbrook
564 950f1472 Glauber Costa
CPUState *qemu_get_cpu(int cpu)
565 950f1472 Glauber Costa
{
566 950f1472 Glauber Costa
    CPUState *env = first_cpu;
567 950f1472 Glauber Costa
568 950f1472 Glauber Costa
    while (env) {
569 950f1472 Glauber Costa
        if (env->cpu_index == cpu)
570 950f1472 Glauber Costa
            break;
571 950f1472 Glauber Costa
        env = env->next_cpu;
572 950f1472 Glauber Costa
    }
573 950f1472 Glauber Costa
574 950f1472 Glauber Costa
    return env;
575 950f1472 Glauber Costa
}
576 950f1472 Glauber Costa
577 6a00d601 bellard
void cpu_exec_init(CPUState *env)
578 fd6ce8f6 bellard
{
579 6a00d601 bellard
    CPUState **penv;
580 6a00d601 bellard
    int cpu_index;
581 6a00d601 bellard
582 c2764719 pbrook
#if defined(CONFIG_USER_ONLY)
583 c2764719 pbrook
    cpu_list_lock();
584 c2764719 pbrook
#endif
585 6a00d601 bellard
    env->next_cpu = NULL;
586 6a00d601 bellard
    penv = &first_cpu;
587 6a00d601 bellard
    cpu_index = 0;
588 6a00d601 bellard
    while (*penv != NULL) {
589 1e9fa730 Nathan Froyd
        penv = &(*penv)->next_cpu;
590 6a00d601 bellard
        cpu_index++;
591 6a00d601 bellard
    }
592 6a00d601 bellard
    env->cpu_index = cpu_index;
593 268a362c aliguori
    env->numa_node = 0;
594 72cf2d4f Blue Swirl
    QTAILQ_INIT(&env->breakpoints);
595 72cf2d4f Blue Swirl
    QTAILQ_INIT(&env->watchpoints);
596 6a00d601 bellard
    *penv = env;
597 c2764719 pbrook
#if defined(CONFIG_USER_ONLY)
598 c2764719 pbrook
    cpu_list_unlock();
599 c2764719 pbrook
#endif
600 b3c7724c pbrook
#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
601 e7f4eff7 Juan Quintela
    vmstate_register(cpu_index, &vmstate_cpu_common, env);
602 b3c7724c pbrook
    register_savevm("cpu", cpu_index, CPU_SAVE_VERSION,
603 b3c7724c pbrook
                    cpu_save, cpu_load, env);
604 b3c7724c pbrook
#endif
605 fd6ce8f6 bellard
}
606 fd6ce8f6 bellard
607 9fa3e853 bellard
static inline void invalidate_page_bitmap(PageDesc *p)
608 9fa3e853 bellard
{
609 9fa3e853 bellard
    if (p->code_bitmap) {
610 59817ccb bellard
        qemu_free(p->code_bitmap);
611 9fa3e853 bellard
        p->code_bitmap = NULL;
612 9fa3e853 bellard
    }
613 9fa3e853 bellard
    p->code_write_count = 0;
614 9fa3e853 bellard
}
615 9fa3e853 bellard
616 fd6ce8f6 bellard
/* set to NULL all the 'first_tb' fields in all PageDescs */
617 fd6ce8f6 bellard
static void page_flush_tb(void)
618 fd6ce8f6 bellard
{
619 fd6ce8f6 bellard
    int i, j;
620 fd6ce8f6 bellard
    PageDesc *p;
621 fd6ce8f6 bellard
622 fd6ce8f6 bellard
    for(i = 0; i < L1_SIZE; i++) {
623 fd6ce8f6 bellard
        p = l1_map[i];
624 fd6ce8f6 bellard
        if (p) {
625 9fa3e853 bellard
            for(j = 0; j < L2_SIZE; j++) {
626 9fa3e853 bellard
                p->first_tb = NULL;
627 9fa3e853 bellard
                invalidate_page_bitmap(p);
628 9fa3e853 bellard
                p++;
629 9fa3e853 bellard
            }
630 fd6ce8f6 bellard
        }
631 fd6ce8f6 bellard
    }
632 fd6ce8f6 bellard
}
633 fd6ce8f6 bellard
634 fd6ce8f6 bellard
/* flush all the translation blocks */
635 d4e8164f bellard
/* XXX: tb_flush is currently not thread safe */
636 6a00d601 bellard
void tb_flush(CPUState *env1)
637 fd6ce8f6 bellard
{
638 6a00d601 bellard
    CPUState *env;
639 0124311e bellard
#if defined(DEBUG_FLUSH)
640 ab3d1727 blueswir1
    printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
641 ab3d1727 blueswir1
           (unsigned long)(code_gen_ptr - code_gen_buffer),
642 ab3d1727 blueswir1
           nb_tbs, nb_tbs > 0 ?
643 ab3d1727 blueswir1
           ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
644 fd6ce8f6 bellard
#endif
645 26a5f13b bellard
    if ((unsigned long)(code_gen_ptr - code_gen_buffer) > code_gen_buffer_size)
646 a208e54a pbrook
        cpu_abort(env1, "Internal error: code buffer overflow\n");
647 a208e54a pbrook
648 fd6ce8f6 bellard
    nb_tbs = 0;
649 3b46e624 ths
650 6a00d601 bellard
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
651 6a00d601 bellard
        memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
652 6a00d601 bellard
    }
653 9fa3e853 bellard
654 8a8a608f bellard
    memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
655 fd6ce8f6 bellard
    page_flush_tb();
656 9fa3e853 bellard
657 fd6ce8f6 bellard
    code_gen_ptr = code_gen_buffer;
658 d4e8164f bellard
    /* XXX: flush processor icache at this point if cache flush is
659 d4e8164f bellard
       expensive */
660 e3db7226 bellard
    tb_flush_count++;
661 fd6ce8f6 bellard
}
662 fd6ce8f6 bellard
663 fd6ce8f6 bellard
#ifdef DEBUG_TB_CHECK
664 fd6ce8f6 bellard
665 bc98a7ef j_mayer
static void tb_invalidate_check(target_ulong address)
666 fd6ce8f6 bellard
{
667 fd6ce8f6 bellard
    TranslationBlock *tb;
668 fd6ce8f6 bellard
    int i;
669 fd6ce8f6 bellard
    address &= TARGET_PAGE_MASK;
670 99773bd4 pbrook
    for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
671 99773bd4 pbrook
        for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
672 fd6ce8f6 bellard
            if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
673 fd6ce8f6 bellard
                  address >= tb->pc + tb->size)) {
674 0bf9e31a Blue Swirl
                printf("ERROR invalidate: address=" TARGET_FMT_lx
675 0bf9e31a Blue Swirl
                       " PC=%08lx size=%04x\n",
676 99773bd4 pbrook
                       address, (long)tb->pc, tb->size);
677 fd6ce8f6 bellard
            }
678 fd6ce8f6 bellard
        }
679 fd6ce8f6 bellard
    }
680 fd6ce8f6 bellard
}
681 fd6ce8f6 bellard
682 fd6ce8f6 bellard
/* verify that all the pages have correct rights for code */
683 fd6ce8f6 bellard
static void tb_page_check(void)
684 fd6ce8f6 bellard
{
685 fd6ce8f6 bellard
    TranslationBlock *tb;
686 fd6ce8f6 bellard
    int i, flags1, flags2;
687 3b46e624 ths
688 99773bd4 pbrook
    for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
689 99773bd4 pbrook
        for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
690 fd6ce8f6 bellard
            flags1 = page_get_flags(tb->pc);
691 fd6ce8f6 bellard
            flags2 = page_get_flags(tb->pc + tb->size - 1);
692 fd6ce8f6 bellard
            if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
693 fd6ce8f6 bellard
                printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
694 99773bd4 pbrook
                       (long)tb->pc, tb->size, flags1, flags2);
695 fd6ce8f6 bellard
            }
696 fd6ce8f6 bellard
        }
697 fd6ce8f6 bellard
    }
698 fd6ce8f6 bellard
}
699 fd6ce8f6 bellard
700 fd6ce8f6 bellard
#endif
701 fd6ce8f6 bellard
702 fd6ce8f6 bellard
/* invalidate one TB */
703 fd6ce8f6 bellard
static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb,
704 fd6ce8f6 bellard
                             int next_offset)
705 fd6ce8f6 bellard
{
706 fd6ce8f6 bellard
    TranslationBlock *tb1;
707 fd6ce8f6 bellard
    for(;;) {
708 fd6ce8f6 bellard
        tb1 = *ptb;
709 fd6ce8f6 bellard
        if (tb1 == tb) {
710 fd6ce8f6 bellard
            *ptb = *(TranslationBlock **)((char *)tb1 + next_offset);
711 fd6ce8f6 bellard
            break;
712 fd6ce8f6 bellard
        }
713 fd6ce8f6 bellard
        ptb = (TranslationBlock **)((char *)tb1 + next_offset);
714 fd6ce8f6 bellard
    }
715 fd6ce8f6 bellard
}
716 fd6ce8f6 bellard
717 9fa3e853 bellard
static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
718 9fa3e853 bellard
{
719 9fa3e853 bellard
    TranslationBlock *tb1;
720 9fa3e853 bellard
    unsigned int n1;
721 9fa3e853 bellard
722 9fa3e853 bellard
    for(;;) {
723 9fa3e853 bellard
        tb1 = *ptb;
724 9fa3e853 bellard
        n1 = (long)tb1 & 3;
725 9fa3e853 bellard
        tb1 = (TranslationBlock *)((long)tb1 & ~3);
726 9fa3e853 bellard
        if (tb1 == tb) {
727 9fa3e853 bellard
            *ptb = tb1->page_next[n1];
728 9fa3e853 bellard
            break;
729 9fa3e853 bellard
        }
730 9fa3e853 bellard
        ptb = &tb1->page_next[n1];
731 9fa3e853 bellard
    }
732 9fa3e853 bellard
}
733 9fa3e853 bellard
734 d4e8164f bellard
static inline void tb_jmp_remove(TranslationBlock *tb, int n)
735 d4e8164f bellard
{
736 d4e8164f bellard
    TranslationBlock *tb1, **ptb;
737 d4e8164f bellard
    unsigned int n1;
738 d4e8164f bellard
739 d4e8164f bellard
    ptb = &tb->jmp_next[n];
740 d4e8164f bellard
    tb1 = *ptb;
741 d4e8164f bellard
    if (tb1) {
742 d4e8164f bellard
        /* find tb(n) in circular list */
743 d4e8164f bellard
        for(;;) {
744 d4e8164f bellard
            tb1 = *ptb;
745 d4e8164f bellard
            n1 = (long)tb1 & 3;
746 d4e8164f bellard
            tb1 = (TranslationBlock *)((long)tb1 & ~3);
747 d4e8164f bellard
            if (n1 == n && tb1 == tb)
748 d4e8164f bellard
                break;
749 d4e8164f bellard
            if (n1 == 2) {
750 d4e8164f bellard
                ptb = &tb1->jmp_first;
751 d4e8164f bellard
            } else {
752 d4e8164f bellard
                ptb = &tb1->jmp_next[n1];
753 d4e8164f bellard
            }
754 d4e8164f bellard
        }
755 d4e8164f bellard
        /* now we can suppress tb(n) from the list */
756 d4e8164f bellard
        *ptb = tb->jmp_next[n];
757 d4e8164f bellard
758 d4e8164f bellard
        tb->jmp_next[n] = NULL;
759 d4e8164f bellard
    }
760 d4e8164f bellard
}
761 d4e8164f bellard
762 d4e8164f bellard
/* reset the jump entry 'n' of a TB so that it is not chained to
763 d4e8164f bellard
   another TB */
764 d4e8164f bellard
static inline void tb_reset_jump(TranslationBlock *tb, int n)
765 d4e8164f bellard
{
766 d4e8164f bellard
    tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
767 d4e8164f bellard
}
768 d4e8164f bellard
769 2e70f6ef pbrook
void tb_phys_invalidate(TranslationBlock *tb, target_ulong page_addr)
770 fd6ce8f6 bellard
{
771 6a00d601 bellard
    CPUState *env;
772 8a40a180 bellard
    PageDesc *p;
773 d4e8164f bellard
    unsigned int h, n1;
774 c227f099 Anthony Liguori
    target_phys_addr_t phys_pc;
775 8a40a180 bellard
    TranslationBlock *tb1, *tb2;
776 3b46e624 ths
777 8a40a180 bellard
    /* remove the TB from the hash list */
778 8a40a180 bellard
    phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
779 8a40a180 bellard
    h = tb_phys_hash_func(phys_pc);
780 5fafdf24 ths
    tb_remove(&tb_phys_hash[h], tb,
781 8a40a180 bellard
              offsetof(TranslationBlock, phys_hash_next));
782 8a40a180 bellard
783 8a40a180 bellard
    /* remove the TB from the page list */
784 8a40a180 bellard
    if (tb->page_addr[0] != page_addr) {
785 8a40a180 bellard
        p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
786 8a40a180 bellard
        tb_page_remove(&p->first_tb, tb);
787 8a40a180 bellard
        invalidate_page_bitmap(p);
788 8a40a180 bellard
    }
789 8a40a180 bellard
    if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
790 8a40a180 bellard
        p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
791 8a40a180 bellard
        tb_page_remove(&p->first_tb, tb);
792 8a40a180 bellard
        invalidate_page_bitmap(p);
793 8a40a180 bellard
    }
794 8a40a180 bellard
795 36bdbe54 bellard
    tb_invalidated_flag = 1;
796 59817ccb bellard
797 fd6ce8f6 bellard
    /* remove the TB from the hash list */
798 8a40a180 bellard
    h = tb_jmp_cache_hash_func(tb->pc);
799 6a00d601 bellard
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
800 6a00d601 bellard
        if (env->tb_jmp_cache[h] == tb)
801 6a00d601 bellard
            env->tb_jmp_cache[h] = NULL;
802 6a00d601 bellard
    }
803 d4e8164f bellard
804 d4e8164f bellard
    /* suppress this TB from the two jump lists */
805 d4e8164f bellard
    tb_jmp_remove(tb, 0);
806 d4e8164f bellard
    tb_jmp_remove(tb, 1);
807 d4e8164f bellard
808 d4e8164f bellard
    /* suppress any remaining jumps to this TB */
809 d4e8164f bellard
    tb1 = tb->jmp_first;
810 d4e8164f bellard
    for(;;) {
811 d4e8164f bellard
        n1 = (long)tb1 & 3;
812 d4e8164f bellard
        if (n1 == 2)
813 d4e8164f bellard
            break;
814 d4e8164f bellard
        tb1 = (TranslationBlock *)((long)tb1 & ~3);
815 d4e8164f bellard
        tb2 = tb1->jmp_next[n1];
816 d4e8164f bellard
        tb_reset_jump(tb1, n1);
817 d4e8164f bellard
        tb1->jmp_next[n1] = NULL;
818 d4e8164f bellard
        tb1 = tb2;
819 d4e8164f bellard
    }
820 d4e8164f bellard
    tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
821 9fa3e853 bellard
822 e3db7226 bellard
    tb_phys_invalidate_count++;
823 9fa3e853 bellard
}
824 9fa3e853 bellard
825 9fa3e853 bellard
static inline void set_bits(uint8_t *tab, int start, int len)
826 9fa3e853 bellard
{
827 9fa3e853 bellard
    int end, mask, end1;
828 9fa3e853 bellard
829 9fa3e853 bellard
    end = start + len;
830 9fa3e853 bellard
    tab += start >> 3;
831 9fa3e853 bellard
    mask = 0xff << (start & 7);
832 9fa3e853 bellard
    if ((start & ~7) == (end & ~7)) {
833 9fa3e853 bellard
        if (start < end) {
834 9fa3e853 bellard
            mask &= ~(0xff << (end & 7));
835 9fa3e853 bellard
            *tab |= mask;
836 9fa3e853 bellard
        }
837 9fa3e853 bellard
    } else {
838 9fa3e853 bellard
        *tab++ |= mask;
839 9fa3e853 bellard
        start = (start + 8) & ~7;
840 9fa3e853 bellard
        end1 = end & ~7;
841 9fa3e853 bellard
        while (start < end1) {
842 9fa3e853 bellard
            *tab++ = 0xff;
843 9fa3e853 bellard
            start += 8;
844 9fa3e853 bellard
        }
845 9fa3e853 bellard
        if (start < end) {
846 9fa3e853 bellard
            mask = ~(0xff << (end & 7));
847 9fa3e853 bellard
            *tab |= mask;
848 9fa3e853 bellard
        }
849 9fa3e853 bellard
    }
850 9fa3e853 bellard
}
851 9fa3e853 bellard
852 9fa3e853 bellard
static void build_page_bitmap(PageDesc *p)
853 9fa3e853 bellard
{
854 9fa3e853 bellard
    int n, tb_start, tb_end;
855 9fa3e853 bellard
    TranslationBlock *tb;
856 3b46e624 ths
857 b2a7081a pbrook
    p->code_bitmap = qemu_mallocz(TARGET_PAGE_SIZE / 8);
858 9fa3e853 bellard
859 9fa3e853 bellard
    tb = p->first_tb;
860 9fa3e853 bellard
    while (tb != NULL) {
861 9fa3e853 bellard
        n = (long)tb & 3;
862 9fa3e853 bellard
        tb = (TranslationBlock *)((long)tb & ~3);
863 9fa3e853 bellard
        /* NOTE: this is subtle as a TB may span two physical pages */
864 9fa3e853 bellard
        if (n == 0) {
865 9fa3e853 bellard
            /* NOTE: tb_end may be after the end of the page, but
866 9fa3e853 bellard
               it is not a problem */
867 9fa3e853 bellard
            tb_start = tb->pc & ~TARGET_PAGE_MASK;
868 9fa3e853 bellard
            tb_end = tb_start + tb->size;
869 9fa3e853 bellard
            if (tb_end > TARGET_PAGE_SIZE)
870 9fa3e853 bellard
                tb_end = TARGET_PAGE_SIZE;
871 9fa3e853 bellard
        } else {
872 9fa3e853 bellard
            tb_start = 0;
873 9fa3e853 bellard
            tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
874 9fa3e853 bellard
        }
875 9fa3e853 bellard
        set_bits(p->code_bitmap, tb_start, tb_end - tb_start);
876 9fa3e853 bellard
        tb = tb->page_next[n];
877 9fa3e853 bellard
    }
878 9fa3e853 bellard
}
879 9fa3e853 bellard
880 2e70f6ef pbrook
TranslationBlock *tb_gen_code(CPUState *env,
881 2e70f6ef pbrook
                              target_ulong pc, target_ulong cs_base,
882 2e70f6ef pbrook
                              int flags, int cflags)
883 d720b93d bellard
{
884 d720b93d bellard
    TranslationBlock *tb;
885 d720b93d bellard
    uint8_t *tc_ptr;
886 d720b93d bellard
    target_ulong phys_pc, phys_page2, virt_page2;
887 d720b93d bellard
    int code_gen_size;
888 d720b93d bellard
889 c27004ec bellard
    phys_pc = get_phys_addr_code(env, pc);
890 c27004ec bellard
    tb = tb_alloc(pc);
891 d720b93d bellard
    if (!tb) {
892 d720b93d bellard
        /* flush must be done */
893 d720b93d bellard
        tb_flush(env);
894 d720b93d bellard
        /* cannot fail at this point */
895 c27004ec bellard
        tb = tb_alloc(pc);
896 2e70f6ef pbrook
        /* Don't forget to invalidate previous TB info.  */
897 2e70f6ef pbrook
        tb_invalidated_flag = 1;
898 d720b93d bellard
    }
899 d720b93d bellard
    tc_ptr = code_gen_ptr;
900 d720b93d bellard
    tb->tc_ptr = tc_ptr;
901 d720b93d bellard
    tb->cs_base = cs_base;
902 d720b93d bellard
    tb->flags = flags;
903 d720b93d bellard
    tb->cflags = cflags;
904 d07bde88 blueswir1
    cpu_gen_code(env, tb, &code_gen_size);
905 d720b93d bellard
    code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
906 3b46e624 ths
907 d720b93d bellard
    /* check next page if needed */
908 c27004ec bellard
    virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
909 d720b93d bellard
    phys_page2 = -1;
910 c27004ec bellard
    if ((pc & TARGET_PAGE_MASK) != virt_page2) {
911 d720b93d bellard
        phys_page2 = get_phys_addr_code(env, virt_page2);
912 d720b93d bellard
    }
913 d720b93d bellard
    tb_link_phys(tb, phys_pc, phys_page2);
914 2e70f6ef pbrook
    return tb;
915 d720b93d bellard
}
916 3b46e624 ths
917 9fa3e853 bellard
/* invalidate all TBs which intersect with the target physical page
918 9fa3e853 bellard
   starting in range [start;end[. NOTE: start and end must refer to
919 d720b93d bellard
   the same physical page. 'is_cpu_write_access' should be true if called
920 d720b93d bellard
   from a real cpu write access: the virtual CPU will exit the current
921 d720b93d bellard
   TB if code is modified inside this TB. */
922 c227f099 Anthony Liguori
void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t end,
923 d720b93d bellard
                                   int is_cpu_write_access)
924 d720b93d bellard
{
925 6b917547 aliguori
    TranslationBlock *tb, *tb_next, *saved_tb;
926 d720b93d bellard
    CPUState *env = cpu_single_env;
927 9fa3e853 bellard
    target_ulong tb_start, tb_end;
928 6b917547 aliguori
    PageDesc *p;
929 6b917547 aliguori
    int n;
930 6b917547 aliguori
#ifdef TARGET_HAS_PRECISE_SMC
931 6b917547 aliguori
    int current_tb_not_found = is_cpu_write_access;
932 6b917547 aliguori
    TranslationBlock *current_tb = NULL;
933 6b917547 aliguori
    int current_tb_modified = 0;
934 6b917547 aliguori
    target_ulong current_pc = 0;
935 6b917547 aliguori
    target_ulong current_cs_base = 0;
936 6b917547 aliguori
    int current_flags = 0;
937 6b917547 aliguori
#endif /* TARGET_HAS_PRECISE_SMC */
938 9fa3e853 bellard
939 9fa3e853 bellard
    p = page_find(start >> TARGET_PAGE_BITS);
940 5fafdf24 ths
    if (!p)
941 9fa3e853 bellard
        return;
942 5fafdf24 ths
    if (!p->code_bitmap &&
943 d720b93d bellard
        ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
944 d720b93d bellard
        is_cpu_write_access) {
945 9fa3e853 bellard
        /* build code bitmap */
946 9fa3e853 bellard
        build_page_bitmap(p);
947 9fa3e853 bellard
    }
948 9fa3e853 bellard
949 9fa3e853 bellard
    /* we remove all the TBs in the range [start, end[ */
950 9fa3e853 bellard
    /* XXX: see if in some cases it could be faster to invalidate all the code */
951 9fa3e853 bellard
    tb = p->first_tb;
952 9fa3e853 bellard
    while (tb != NULL) {
953 9fa3e853 bellard
        n = (long)tb & 3;
954 9fa3e853 bellard
        tb = (TranslationBlock *)((long)tb & ~3);
955 9fa3e853 bellard
        tb_next = tb->page_next[n];
956 9fa3e853 bellard
        /* NOTE: this is subtle as a TB may span two physical pages */
957 9fa3e853 bellard
        if (n == 0) {
958 9fa3e853 bellard
            /* NOTE: tb_end may be after the end of the page, but
959 9fa3e853 bellard
               it is not a problem */
960 9fa3e853 bellard
            tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
961 9fa3e853 bellard
            tb_end = tb_start + tb->size;
962 9fa3e853 bellard
        } else {
963 9fa3e853 bellard
            tb_start = tb->page_addr[1];
964 9fa3e853 bellard
            tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
965 9fa3e853 bellard
        }
966 9fa3e853 bellard
        if (!(tb_end <= start || tb_start >= end)) {
967 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
968 d720b93d bellard
            if (current_tb_not_found) {
969 d720b93d bellard
                current_tb_not_found = 0;
970 d720b93d bellard
                current_tb = NULL;
971 2e70f6ef pbrook
                if (env->mem_io_pc) {
972 d720b93d bellard
                    /* now we have a real cpu fault */
973 2e70f6ef pbrook
                    current_tb = tb_find_pc(env->mem_io_pc);
974 d720b93d bellard
                }
975 d720b93d bellard
            }
976 d720b93d bellard
            if (current_tb == tb &&
977 2e70f6ef pbrook
                (current_tb->cflags & CF_COUNT_MASK) != 1) {
978 d720b93d bellard
                /* If we are modifying the current TB, we must stop
979 d720b93d bellard
                its execution. We could be more precise by checking
980 d720b93d bellard
                that the modification is after the current PC, but it
981 d720b93d bellard
                would require a specialized function to partially
982 d720b93d bellard
                restore the CPU state */
983 3b46e624 ths
984 d720b93d bellard
                current_tb_modified = 1;
985 5fafdf24 ths
                cpu_restore_state(current_tb, env,
986 2e70f6ef pbrook
                                  env->mem_io_pc, NULL);
987 6b917547 aliguori
                cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
988 6b917547 aliguori
                                     &current_flags);
989 d720b93d bellard
            }
990 d720b93d bellard
#endif /* TARGET_HAS_PRECISE_SMC */
991 6f5a9f7e bellard
            /* we need to do that to handle the case where a signal
992 6f5a9f7e bellard
               occurs while doing tb_phys_invalidate() */
993 6f5a9f7e bellard
            saved_tb = NULL;
994 6f5a9f7e bellard
            if (env) {
995 6f5a9f7e bellard
                saved_tb = env->current_tb;
996 6f5a9f7e bellard
                env->current_tb = NULL;
997 6f5a9f7e bellard
            }
998 9fa3e853 bellard
            tb_phys_invalidate(tb, -1);
999 6f5a9f7e bellard
            if (env) {
1000 6f5a9f7e bellard
                env->current_tb = saved_tb;
1001 6f5a9f7e bellard
                if (env->interrupt_request && env->current_tb)
1002 6f5a9f7e bellard
                    cpu_interrupt(env, env->interrupt_request);
1003 6f5a9f7e bellard
            }
1004 9fa3e853 bellard
        }
1005 9fa3e853 bellard
        tb = tb_next;
1006 9fa3e853 bellard
    }
1007 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
1008 9fa3e853 bellard
    /* if no code remaining, no need to continue to use slow writes */
1009 9fa3e853 bellard
    if (!p->first_tb) {
1010 9fa3e853 bellard
        invalidate_page_bitmap(p);
1011 d720b93d bellard
        if (is_cpu_write_access) {
1012 2e70f6ef pbrook
            tlb_unprotect_code_phys(env, start, env->mem_io_vaddr);
1013 d720b93d bellard
        }
1014 d720b93d bellard
    }
1015 d720b93d bellard
#endif
1016 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
1017 d720b93d bellard
    if (current_tb_modified) {
1018 d720b93d bellard
        /* we generate a block containing just the instruction
1019 d720b93d bellard
           modifying the memory. It will ensure that it cannot modify
1020 d720b93d bellard
           itself */
1021 ea1c1802 bellard
        env->current_tb = NULL;
1022 2e70f6ef pbrook
        tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1023 d720b93d bellard
        cpu_resume_from_signal(env, NULL);
1024 9fa3e853 bellard
    }
1025 fd6ce8f6 bellard
#endif
1026 9fa3e853 bellard
}
1027 fd6ce8f6 bellard
1028 9fa3e853 bellard
/* len must be <= 8 and start must be a multiple of len */
1029 c227f099 Anthony Liguori
static inline void tb_invalidate_phys_page_fast(target_phys_addr_t start, int len)
1030 9fa3e853 bellard
{
1031 9fa3e853 bellard
    PageDesc *p;
1032 9fa3e853 bellard
    int offset, b;
1033 59817ccb bellard
#if 0
1034 a4193c8a bellard
    if (1) {
1035 93fcfe39 aliguori
        qemu_log("modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
1036 93fcfe39 aliguori
                  cpu_single_env->mem_io_vaddr, len,
1037 93fcfe39 aliguori
                  cpu_single_env->eip,
1038 93fcfe39 aliguori
                  cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
1039 59817ccb bellard
    }
1040 59817ccb bellard
#endif
1041 9fa3e853 bellard
    p = page_find(start >> TARGET_PAGE_BITS);
1042 5fafdf24 ths
    if (!p)
1043 9fa3e853 bellard
        return;
1044 9fa3e853 bellard
    if (p->code_bitmap) {
1045 9fa3e853 bellard
        offset = start & ~TARGET_PAGE_MASK;
1046 9fa3e853 bellard
        b = p->code_bitmap[offset >> 3] >> (offset & 7);
1047 9fa3e853 bellard
        if (b & ((1 << len) - 1))
1048 9fa3e853 bellard
            goto do_invalidate;
1049 9fa3e853 bellard
    } else {
1050 9fa3e853 bellard
    do_invalidate:
1051 d720b93d bellard
        tb_invalidate_phys_page_range(start, start + len, 1);
1052 9fa3e853 bellard
    }
1053 9fa3e853 bellard
}
1054 9fa3e853 bellard
1055 9fa3e853 bellard
#if !defined(CONFIG_SOFTMMU)
1056 c227f099 Anthony Liguori
static void tb_invalidate_phys_page(target_phys_addr_t addr,
1057 d720b93d bellard
                                    unsigned long pc, void *puc)
1058 9fa3e853 bellard
{
1059 6b917547 aliguori
    TranslationBlock *tb;
1060 9fa3e853 bellard
    PageDesc *p;
1061 6b917547 aliguori
    int n;
1062 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
1063 6b917547 aliguori
    TranslationBlock *current_tb = NULL;
1064 d720b93d bellard
    CPUState *env = cpu_single_env;
1065 6b917547 aliguori
    int current_tb_modified = 0;
1066 6b917547 aliguori
    target_ulong current_pc = 0;
1067 6b917547 aliguori
    target_ulong current_cs_base = 0;
1068 6b917547 aliguori
    int current_flags = 0;
1069 d720b93d bellard
#endif
1070 9fa3e853 bellard
1071 9fa3e853 bellard
    addr &= TARGET_PAGE_MASK;
1072 9fa3e853 bellard
    p = page_find(addr >> TARGET_PAGE_BITS);
1073 5fafdf24 ths
    if (!p)
1074 9fa3e853 bellard
        return;
1075 9fa3e853 bellard
    tb = p->first_tb;
1076 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
1077 d720b93d bellard
    if (tb && pc != 0) {
1078 d720b93d bellard
        current_tb = tb_find_pc(pc);
1079 d720b93d bellard
    }
1080 d720b93d bellard
#endif
1081 9fa3e853 bellard
    while (tb != NULL) {
1082 9fa3e853 bellard
        n = (long)tb & 3;
1083 9fa3e853 bellard
        tb = (TranslationBlock *)((long)tb & ~3);
1084 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
1085 d720b93d bellard
        if (current_tb == tb &&
1086 2e70f6ef pbrook
            (current_tb->cflags & CF_COUNT_MASK) != 1) {
1087 d720b93d bellard
                /* If we are modifying the current TB, we must stop
1088 d720b93d bellard
                   its execution. We could be more precise by checking
1089 d720b93d bellard
                   that the modification is after the current PC, but it
1090 d720b93d bellard
                   would require a specialized function to partially
1091 d720b93d bellard
                   restore the CPU state */
1092 3b46e624 ths
1093 d720b93d bellard
            current_tb_modified = 1;
1094 d720b93d bellard
            cpu_restore_state(current_tb, env, pc, puc);
1095 6b917547 aliguori
            cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
1096 6b917547 aliguori
                                 &current_flags);
1097 d720b93d bellard
        }
1098 d720b93d bellard
#endif /* TARGET_HAS_PRECISE_SMC */
1099 9fa3e853 bellard
        tb_phys_invalidate(tb, addr);
1100 9fa3e853 bellard
        tb = tb->page_next[n];
1101 9fa3e853 bellard
    }
1102 fd6ce8f6 bellard
    p->first_tb = NULL;
1103 d720b93d bellard
#ifdef TARGET_HAS_PRECISE_SMC
1104 d720b93d bellard
    if (current_tb_modified) {
1105 d720b93d bellard
        /* we generate a block containing just the instruction
1106 d720b93d bellard
           modifying the memory. It will ensure that it cannot modify
1107 d720b93d bellard
           itself */
1108 ea1c1802 bellard
        env->current_tb = NULL;
1109 2e70f6ef pbrook
        tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
1110 d720b93d bellard
        cpu_resume_from_signal(env, puc);
1111 d720b93d bellard
    }
1112 d720b93d bellard
#endif
1113 fd6ce8f6 bellard
}
1114 9fa3e853 bellard
#endif
1115 fd6ce8f6 bellard
1116 fd6ce8f6 bellard
/* add the tb in the target page and protect it if necessary */
1117 5fafdf24 ths
static inline void tb_alloc_page(TranslationBlock *tb,
1118 53a5960a pbrook
                                 unsigned int n, target_ulong page_addr)
1119 fd6ce8f6 bellard
{
1120 fd6ce8f6 bellard
    PageDesc *p;
1121 9fa3e853 bellard
    TranslationBlock *last_first_tb;
1122 9fa3e853 bellard
1123 9fa3e853 bellard
    tb->page_addr[n] = page_addr;
1124 3a7d929e bellard
    p = page_find_alloc(page_addr >> TARGET_PAGE_BITS);
1125 9fa3e853 bellard
    tb->page_next[n] = p->first_tb;
1126 9fa3e853 bellard
    last_first_tb = p->first_tb;
1127 9fa3e853 bellard
    p->first_tb = (TranslationBlock *)((long)tb | n);
1128 9fa3e853 bellard
    invalidate_page_bitmap(p);
1129 fd6ce8f6 bellard
1130 107db443 bellard
#if defined(TARGET_HAS_SMC) || 1
1131 d720b93d bellard
1132 9fa3e853 bellard
#if defined(CONFIG_USER_ONLY)
1133 fd6ce8f6 bellard
    if (p->flags & PAGE_WRITE) {
1134 53a5960a pbrook
        target_ulong addr;
1135 53a5960a pbrook
        PageDesc *p2;
1136 9fa3e853 bellard
        int prot;
1137 9fa3e853 bellard
1138 fd6ce8f6 bellard
        /* force the host page as non writable (writes will have a
1139 fd6ce8f6 bellard
           page fault + mprotect overhead) */
1140 53a5960a pbrook
        page_addr &= qemu_host_page_mask;
1141 fd6ce8f6 bellard
        prot = 0;
1142 53a5960a pbrook
        for(addr = page_addr; addr < page_addr + qemu_host_page_size;
1143 53a5960a pbrook
            addr += TARGET_PAGE_SIZE) {
1144 53a5960a pbrook
1145 53a5960a pbrook
            p2 = page_find (addr >> TARGET_PAGE_BITS);
1146 53a5960a pbrook
            if (!p2)
1147 53a5960a pbrook
                continue;
1148 53a5960a pbrook
            prot |= p2->flags;
1149 53a5960a pbrook
            p2->flags &= ~PAGE_WRITE;
1150 53a5960a pbrook
            page_get_flags(addr);
1151 53a5960a pbrook
          }
1152 5fafdf24 ths
        mprotect(g2h(page_addr), qemu_host_page_size,
1153 fd6ce8f6 bellard
                 (prot & PAGE_BITS) & ~PAGE_WRITE);
1154 fd6ce8f6 bellard
#ifdef DEBUG_TB_INVALIDATE
1155 ab3d1727 blueswir1
        printf("protecting code page: 0x" TARGET_FMT_lx "\n",
1156 53a5960a pbrook
               page_addr);
1157 fd6ce8f6 bellard
#endif
1158 fd6ce8f6 bellard
    }
1159 9fa3e853 bellard
#else
1160 9fa3e853 bellard
    /* if some code is already present, then the pages are already
1161 9fa3e853 bellard
       protected. So we handle the case where only the first TB is
1162 9fa3e853 bellard
       allocated in a physical page */
1163 9fa3e853 bellard
    if (!last_first_tb) {
1164 6a00d601 bellard
        tlb_protect_code(page_addr);
1165 9fa3e853 bellard
    }
1166 9fa3e853 bellard
#endif
1167 d720b93d bellard
1168 d720b93d bellard
#endif /* TARGET_HAS_SMC */
1169 fd6ce8f6 bellard
}
1170 fd6ce8f6 bellard
1171 fd6ce8f6 bellard
/* Allocate a new translation block. Flush the translation buffer if
1172 fd6ce8f6 bellard
   too many translation blocks or too much generated code. */
1173 c27004ec bellard
TranslationBlock *tb_alloc(target_ulong pc)
1174 fd6ce8f6 bellard
{
1175 fd6ce8f6 bellard
    TranslationBlock *tb;
1176 fd6ce8f6 bellard
1177 26a5f13b bellard
    if (nb_tbs >= code_gen_max_blocks ||
1178 26a5f13b bellard
        (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
1179 d4e8164f bellard
        return NULL;
1180 fd6ce8f6 bellard
    tb = &tbs[nb_tbs++];
1181 fd6ce8f6 bellard
    tb->pc = pc;
1182 b448f2f3 bellard
    tb->cflags = 0;
1183 d4e8164f bellard
    return tb;
1184 d4e8164f bellard
}
1185 d4e8164f bellard
1186 2e70f6ef pbrook
void tb_free(TranslationBlock *tb)
1187 2e70f6ef pbrook
{
1188 bf20dc07 ths
    /* In practice this is mostly used for single use temporary TB
1189 2e70f6ef pbrook
       Ignore the hard cases and just back up if this TB happens to
1190 2e70f6ef pbrook
       be the last one generated.  */
1191 2e70f6ef pbrook
    if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) {
1192 2e70f6ef pbrook
        code_gen_ptr = tb->tc_ptr;
1193 2e70f6ef pbrook
        nb_tbs--;
1194 2e70f6ef pbrook
    }
1195 2e70f6ef pbrook
}
1196 2e70f6ef pbrook
1197 9fa3e853 bellard
/* add a new TB and link it to the physical page tables. phys_page2 is
1198 9fa3e853 bellard
   (-1) to indicate that only one page contains the TB. */
1199 5fafdf24 ths
void tb_link_phys(TranslationBlock *tb,
1200 9fa3e853 bellard
                  target_ulong phys_pc, target_ulong phys_page2)
1201 d4e8164f bellard
{
1202 9fa3e853 bellard
    unsigned int h;
1203 9fa3e853 bellard
    TranslationBlock **ptb;
1204 9fa3e853 bellard
1205 c8a706fe pbrook
    /* Grab the mmap lock to stop another thread invalidating this TB
1206 c8a706fe pbrook
       before we are done.  */
1207 c8a706fe pbrook
    mmap_lock();
1208 9fa3e853 bellard
    /* add in the physical hash table */
1209 9fa3e853 bellard
    h = tb_phys_hash_func(phys_pc);
1210 9fa3e853 bellard
    ptb = &tb_phys_hash[h];
1211 9fa3e853 bellard
    tb->phys_hash_next = *ptb;
1212 9fa3e853 bellard
    *ptb = tb;
1213 fd6ce8f6 bellard
1214 fd6ce8f6 bellard
    /* add in the page list */
1215 9fa3e853 bellard
    tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK);
1216 9fa3e853 bellard
    if (phys_page2 != -1)
1217 9fa3e853 bellard
        tb_alloc_page(tb, 1, phys_page2);
1218 9fa3e853 bellard
    else
1219 9fa3e853 bellard
        tb->page_addr[1] = -1;
1220 9fa3e853 bellard
1221 d4e8164f bellard
    tb->jmp_first = (TranslationBlock *)((long)tb | 2);
1222 d4e8164f bellard
    tb->jmp_next[0] = NULL;
1223 d4e8164f bellard
    tb->jmp_next[1] = NULL;
1224 d4e8164f bellard
1225 d4e8164f bellard
    /* init original jump addresses */
1226 d4e8164f bellard
    if (tb->tb_next_offset[0] != 0xffff)
1227 d4e8164f bellard
        tb_reset_jump(tb, 0);
1228 d4e8164f bellard
    if (tb->tb_next_offset[1] != 0xffff)
1229 d4e8164f bellard
        tb_reset_jump(tb, 1);
1230 8a40a180 bellard
1231 8a40a180 bellard
#ifdef DEBUG_TB_CHECK
1232 8a40a180 bellard
    tb_page_check();
1233 8a40a180 bellard
#endif
1234 c8a706fe pbrook
    mmap_unlock();
1235 fd6ce8f6 bellard
}
1236 fd6ce8f6 bellard
1237 9fa3e853 bellard
/* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
1238 9fa3e853 bellard
   tb[1].tc_ptr. Return NULL if not found */
1239 9fa3e853 bellard
TranslationBlock *tb_find_pc(unsigned long tc_ptr)
1240 fd6ce8f6 bellard
{
1241 9fa3e853 bellard
    int m_min, m_max, m;
1242 9fa3e853 bellard
    unsigned long v;
1243 9fa3e853 bellard
    TranslationBlock *tb;
1244 a513fe19 bellard
1245 a513fe19 bellard
    if (nb_tbs <= 0)
1246 a513fe19 bellard
        return NULL;
1247 a513fe19 bellard
    if (tc_ptr < (unsigned long)code_gen_buffer ||
1248 a513fe19 bellard
        tc_ptr >= (unsigned long)code_gen_ptr)
1249 a513fe19 bellard
        return NULL;
1250 a513fe19 bellard
    /* binary search (cf Knuth) */
1251 a513fe19 bellard
    m_min = 0;
1252 a513fe19 bellard
    m_max = nb_tbs - 1;
1253 a513fe19 bellard
    while (m_min <= m_max) {
1254 a513fe19 bellard
        m = (m_min + m_max) >> 1;
1255 a513fe19 bellard
        tb = &tbs[m];
1256 a513fe19 bellard
        v = (unsigned long)tb->tc_ptr;
1257 a513fe19 bellard
        if (v == tc_ptr)
1258 a513fe19 bellard
            return tb;
1259 a513fe19 bellard
        else if (tc_ptr < v) {
1260 a513fe19 bellard
            m_max = m - 1;
1261 a513fe19 bellard
        } else {
1262 a513fe19 bellard
            m_min = m + 1;
1263 a513fe19 bellard
        }
1264 5fafdf24 ths
    }
1265 a513fe19 bellard
    return &tbs[m_max];
1266 a513fe19 bellard
}
1267 7501267e bellard
1268 ea041c0e bellard
static void tb_reset_jump_recursive(TranslationBlock *tb);
1269 ea041c0e bellard
1270 ea041c0e bellard
static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
1271 ea041c0e bellard
{
1272 ea041c0e bellard
    TranslationBlock *tb1, *tb_next, **ptb;
1273 ea041c0e bellard
    unsigned int n1;
1274 ea041c0e bellard
1275 ea041c0e bellard
    tb1 = tb->jmp_next[n];
1276 ea041c0e bellard
    if (tb1 != NULL) {
1277 ea041c0e bellard
        /* find head of list */
1278 ea041c0e bellard
        for(;;) {
1279 ea041c0e bellard
            n1 = (long)tb1 & 3;
1280 ea041c0e bellard
            tb1 = (TranslationBlock *)((long)tb1 & ~3);
1281 ea041c0e bellard
            if (n1 == 2)
1282 ea041c0e bellard
                break;
1283 ea041c0e bellard
            tb1 = tb1->jmp_next[n1];
1284 ea041c0e bellard
        }
1285 ea041c0e bellard
        /* we are now sure now that tb jumps to tb1 */
1286 ea041c0e bellard
        tb_next = tb1;
1287 ea041c0e bellard
1288 ea041c0e bellard
        /* remove tb from the jmp_first list */
1289 ea041c0e bellard
        ptb = &tb_next->jmp_first;
1290 ea041c0e bellard
        for(;;) {
1291 ea041c0e bellard
            tb1 = *ptb;
1292 ea041c0e bellard
            n1 = (long)tb1 & 3;
1293 ea041c0e bellard
            tb1 = (TranslationBlock *)((long)tb1 & ~3);
1294 ea041c0e bellard
            if (n1 == n && tb1 == tb)
1295 ea041c0e bellard
                break;
1296 ea041c0e bellard
            ptb = &tb1->jmp_next[n1];
1297 ea041c0e bellard
        }
1298 ea041c0e bellard
        *ptb = tb->jmp_next[n];
1299 ea041c0e bellard
        tb->jmp_next[n] = NULL;
1300 3b46e624 ths
1301 ea041c0e bellard
        /* suppress the jump to next tb in generated code */
1302 ea041c0e bellard
        tb_reset_jump(tb, n);
1303 ea041c0e bellard
1304 0124311e bellard
        /* suppress jumps in the tb on which we could have jumped */
1305 ea041c0e bellard
        tb_reset_jump_recursive(tb_next);
1306 ea041c0e bellard
    }
1307 ea041c0e bellard
}
1308 ea041c0e bellard
1309 ea041c0e bellard
static void tb_reset_jump_recursive(TranslationBlock *tb)
1310 ea041c0e bellard
{
1311 ea041c0e bellard
    tb_reset_jump_recursive2(tb, 0);
1312 ea041c0e bellard
    tb_reset_jump_recursive2(tb, 1);
1313 ea041c0e bellard
}
1314 ea041c0e bellard
1315 1fddef4b bellard
#if defined(TARGET_HAS_ICE)
1316 d720b93d bellard
static void breakpoint_invalidate(CPUState *env, target_ulong pc)
1317 d720b93d bellard
{
1318 c227f099 Anthony Liguori
    target_phys_addr_t addr;
1319 9b3c35e0 j_mayer
    target_ulong pd;
1320 c227f099 Anthony Liguori
    ram_addr_t ram_addr;
1321 c2f07f81 pbrook
    PhysPageDesc *p;
1322 d720b93d bellard
1323 c2f07f81 pbrook
    addr = cpu_get_phys_page_debug(env, pc);
1324 c2f07f81 pbrook
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
1325 c2f07f81 pbrook
    if (!p) {
1326 c2f07f81 pbrook
        pd = IO_MEM_UNASSIGNED;
1327 c2f07f81 pbrook
    } else {
1328 c2f07f81 pbrook
        pd = p->phys_offset;
1329 c2f07f81 pbrook
    }
1330 c2f07f81 pbrook
    ram_addr = (pd & TARGET_PAGE_MASK) | (pc & ~TARGET_PAGE_MASK);
1331 706cd4b5 pbrook
    tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0);
1332 d720b93d bellard
}
1333 c27004ec bellard
#endif
1334 d720b93d bellard
1335 6658ffb8 pbrook
/* Add a watchpoint.  */
1336 a1d1bb31 aliguori
int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
1337 a1d1bb31 aliguori
                          int flags, CPUWatchpoint **watchpoint)
1338 6658ffb8 pbrook
{
1339 b4051334 aliguori
    target_ulong len_mask = ~(len - 1);
1340 c0ce998e aliguori
    CPUWatchpoint *wp;
1341 6658ffb8 pbrook
1342 b4051334 aliguori
    /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
1343 b4051334 aliguori
    if ((len != 1 && len != 2 && len != 4 && len != 8) || (addr & ~len_mask)) {
1344 b4051334 aliguori
        fprintf(stderr, "qemu: tried to set invalid watchpoint at "
1345 b4051334 aliguori
                TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
1346 b4051334 aliguori
        return -EINVAL;
1347 b4051334 aliguori
    }
1348 a1d1bb31 aliguori
    wp = qemu_malloc(sizeof(*wp));
1349 a1d1bb31 aliguori
1350 a1d1bb31 aliguori
    wp->vaddr = addr;
1351 b4051334 aliguori
    wp->len_mask = len_mask;
1352 a1d1bb31 aliguori
    wp->flags = flags;
1353 a1d1bb31 aliguori
1354 2dc9f411 aliguori
    /* keep all GDB-injected watchpoints in front */
1355 c0ce998e aliguori
    if (flags & BP_GDB)
1356 72cf2d4f Blue Swirl
        QTAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
1357 c0ce998e aliguori
    else
1358 72cf2d4f Blue Swirl
        QTAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
1359 6658ffb8 pbrook
1360 6658ffb8 pbrook
    tlb_flush_page(env, addr);
1361 a1d1bb31 aliguori
1362 a1d1bb31 aliguori
    if (watchpoint)
1363 a1d1bb31 aliguori
        *watchpoint = wp;
1364 a1d1bb31 aliguori
    return 0;
1365 6658ffb8 pbrook
}
1366 6658ffb8 pbrook
1367 a1d1bb31 aliguori
/* Remove a specific watchpoint.  */
1368 a1d1bb31 aliguori
int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len,
1369 a1d1bb31 aliguori
                          int flags)
1370 6658ffb8 pbrook
{
1371 b4051334 aliguori
    target_ulong len_mask = ~(len - 1);
1372 a1d1bb31 aliguori
    CPUWatchpoint *wp;
1373 6658ffb8 pbrook
1374 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
1375 b4051334 aliguori
        if (addr == wp->vaddr && len_mask == wp->len_mask
1376 6e140f28 aliguori
                && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
1377 a1d1bb31 aliguori
            cpu_watchpoint_remove_by_ref(env, wp);
1378 6658ffb8 pbrook
            return 0;
1379 6658ffb8 pbrook
        }
1380 6658ffb8 pbrook
    }
1381 a1d1bb31 aliguori
    return -ENOENT;
1382 6658ffb8 pbrook
}
1383 6658ffb8 pbrook
1384 a1d1bb31 aliguori
/* Remove a specific watchpoint by reference.  */
1385 a1d1bb31 aliguori
void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint)
1386 a1d1bb31 aliguori
{
1387 72cf2d4f Blue Swirl
    QTAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
1388 7d03f82f edgar_igl
1389 a1d1bb31 aliguori
    tlb_flush_page(env, watchpoint->vaddr);
1390 a1d1bb31 aliguori
1391 a1d1bb31 aliguori
    qemu_free(watchpoint);
1392 a1d1bb31 aliguori
}
1393 a1d1bb31 aliguori
1394 a1d1bb31 aliguori
/* Remove all matching watchpoints.  */
1395 a1d1bb31 aliguori
void cpu_watchpoint_remove_all(CPUState *env, int mask)
1396 a1d1bb31 aliguori
{
1397 c0ce998e aliguori
    CPUWatchpoint *wp, *next;
1398 a1d1bb31 aliguori
1399 72cf2d4f Blue Swirl
    QTAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
1400 a1d1bb31 aliguori
        if (wp->flags & mask)
1401 a1d1bb31 aliguori
            cpu_watchpoint_remove_by_ref(env, wp);
1402 c0ce998e aliguori
    }
1403 7d03f82f edgar_igl
}
1404 7d03f82f edgar_igl
1405 a1d1bb31 aliguori
/* Add a breakpoint.  */
1406 a1d1bb31 aliguori
int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
1407 a1d1bb31 aliguori
                          CPUBreakpoint **breakpoint)
1408 4c3a88a2 bellard
{
1409 1fddef4b bellard
#if defined(TARGET_HAS_ICE)
1410 c0ce998e aliguori
    CPUBreakpoint *bp;
1411 3b46e624 ths
1412 a1d1bb31 aliguori
    bp = qemu_malloc(sizeof(*bp));
1413 4c3a88a2 bellard
1414 a1d1bb31 aliguori
    bp->pc = pc;
1415 a1d1bb31 aliguori
    bp->flags = flags;
1416 a1d1bb31 aliguori
1417 2dc9f411 aliguori
    /* keep all GDB-injected breakpoints in front */
1418 c0ce998e aliguori
    if (flags & BP_GDB)
1419 72cf2d4f Blue Swirl
        QTAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
1420 c0ce998e aliguori
    else
1421 72cf2d4f Blue Swirl
        QTAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
1422 3b46e624 ths
1423 d720b93d bellard
    breakpoint_invalidate(env, pc);
1424 a1d1bb31 aliguori
1425 a1d1bb31 aliguori
    if (breakpoint)
1426 a1d1bb31 aliguori
        *breakpoint = bp;
1427 4c3a88a2 bellard
    return 0;
1428 4c3a88a2 bellard
#else
1429 a1d1bb31 aliguori
    return -ENOSYS;
1430 4c3a88a2 bellard
#endif
1431 4c3a88a2 bellard
}
1432 4c3a88a2 bellard
1433 a1d1bb31 aliguori
/* Remove a specific breakpoint.  */
1434 a1d1bb31 aliguori
int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags)
1435 a1d1bb31 aliguori
{
1436 7d03f82f edgar_igl
#if defined(TARGET_HAS_ICE)
1437 a1d1bb31 aliguori
    CPUBreakpoint *bp;
1438 a1d1bb31 aliguori
1439 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1440 a1d1bb31 aliguori
        if (bp->pc == pc && bp->flags == flags) {
1441 a1d1bb31 aliguori
            cpu_breakpoint_remove_by_ref(env, bp);
1442 a1d1bb31 aliguori
            return 0;
1443 a1d1bb31 aliguori
        }
1444 7d03f82f edgar_igl
    }
1445 a1d1bb31 aliguori
    return -ENOENT;
1446 a1d1bb31 aliguori
#else
1447 a1d1bb31 aliguori
    return -ENOSYS;
1448 7d03f82f edgar_igl
#endif
1449 7d03f82f edgar_igl
}
1450 7d03f82f edgar_igl
1451 a1d1bb31 aliguori
/* Remove a specific breakpoint by reference.  */
1452 a1d1bb31 aliguori
void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint)
1453 4c3a88a2 bellard
{
1454 1fddef4b bellard
#if defined(TARGET_HAS_ICE)
1455 72cf2d4f Blue Swirl
    QTAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
1456 d720b93d bellard
1457 a1d1bb31 aliguori
    breakpoint_invalidate(env, breakpoint->pc);
1458 a1d1bb31 aliguori
1459 a1d1bb31 aliguori
    qemu_free(breakpoint);
1460 a1d1bb31 aliguori
#endif
1461 a1d1bb31 aliguori
}
1462 a1d1bb31 aliguori
1463 a1d1bb31 aliguori
/* Remove all matching breakpoints. */
1464 a1d1bb31 aliguori
void cpu_breakpoint_remove_all(CPUState *env, int mask)
1465 a1d1bb31 aliguori
{
1466 a1d1bb31 aliguori
#if defined(TARGET_HAS_ICE)
1467 c0ce998e aliguori
    CPUBreakpoint *bp, *next;
1468 a1d1bb31 aliguori
1469 72cf2d4f Blue Swirl
    QTAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
1470 a1d1bb31 aliguori
        if (bp->flags & mask)
1471 a1d1bb31 aliguori
            cpu_breakpoint_remove_by_ref(env, bp);
1472 c0ce998e aliguori
    }
1473 4c3a88a2 bellard
#endif
1474 4c3a88a2 bellard
}
1475 4c3a88a2 bellard
1476 c33a346e bellard
/* enable or disable single step mode. EXCP_DEBUG is returned by the
1477 c33a346e bellard
   CPU loop after each instruction */
1478 c33a346e bellard
void cpu_single_step(CPUState *env, int enabled)
1479 c33a346e bellard
{
1480 1fddef4b bellard
#if defined(TARGET_HAS_ICE)
1481 c33a346e bellard
    if (env->singlestep_enabled != enabled) {
1482 c33a346e bellard
        env->singlestep_enabled = enabled;
1483 e22a25c9 aliguori
        if (kvm_enabled())
1484 e22a25c9 aliguori
            kvm_update_guest_debug(env, 0);
1485 e22a25c9 aliguori
        else {
1486 ccbb4d44 Stuart Brady
            /* must flush all the translated code to avoid inconsistencies */
1487 e22a25c9 aliguori
            /* XXX: only flush what is necessary */
1488 e22a25c9 aliguori
            tb_flush(env);
1489 e22a25c9 aliguori
        }
1490 c33a346e bellard
    }
1491 c33a346e bellard
#endif
1492 c33a346e bellard
}
1493 c33a346e bellard
1494 34865134 bellard
/* enable or disable low levels log */
1495 34865134 bellard
void cpu_set_log(int log_flags)
1496 34865134 bellard
{
1497 34865134 bellard
    loglevel = log_flags;
1498 34865134 bellard
    if (loglevel && !logfile) {
1499 11fcfab4 pbrook
        logfile = fopen(logfilename, log_append ? "a" : "w");
1500 34865134 bellard
        if (!logfile) {
1501 34865134 bellard
            perror(logfilename);
1502 34865134 bellard
            _exit(1);
1503 34865134 bellard
        }
1504 9fa3e853 bellard
#if !defined(CONFIG_SOFTMMU)
1505 9fa3e853 bellard
        /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1506 9fa3e853 bellard
        {
1507 b55266b5 blueswir1
            static char logfile_buf[4096];
1508 9fa3e853 bellard
            setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1509 9fa3e853 bellard
        }
1510 bf65f53f Filip Navara
#elif !defined(_WIN32)
1511 bf65f53f Filip Navara
        /* Win32 doesn't support line-buffering and requires size >= 2 */
1512 34865134 bellard
        setvbuf(logfile, NULL, _IOLBF, 0);
1513 9fa3e853 bellard
#endif
1514 e735b91c pbrook
        log_append = 1;
1515 e735b91c pbrook
    }
1516 e735b91c pbrook
    if (!loglevel && logfile) {
1517 e735b91c pbrook
        fclose(logfile);
1518 e735b91c pbrook
        logfile = NULL;
1519 34865134 bellard
    }
1520 34865134 bellard
}
1521 34865134 bellard
1522 34865134 bellard
void cpu_set_log_filename(const char *filename)
1523 34865134 bellard
{
1524 34865134 bellard
    logfilename = strdup(filename);
1525 e735b91c pbrook
    if (logfile) {
1526 e735b91c pbrook
        fclose(logfile);
1527 e735b91c pbrook
        logfile = NULL;
1528 e735b91c pbrook
    }
1529 e735b91c pbrook
    cpu_set_log(loglevel);
1530 34865134 bellard
}
1531 c33a346e bellard
1532 3098dba0 aurel32
static void cpu_unlink_tb(CPUState *env)
1533 ea041c0e bellard
{
1534 3098dba0 aurel32
    /* FIXME: TB unchaining isn't SMP safe.  For now just ignore the
1535 3098dba0 aurel32
       problem and hope the cpu will stop of its own accord.  For userspace
1536 3098dba0 aurel32
       emulation this often isn't actually as bad as it sounds.  Often
1537 3098dba0 aurel32
       signals are used primarily to interrupt blocking syscalls.  */
1538 ea041c0e bellard
    TranslationBlock *tb;
1539 c227f099 Anthony Liguori
    static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
1540 59817ccb bellard
1541 26bc95a0 Riku Voipio
    spin_lock(&interrupt_lock);
1542 3098dba0 aurel32
    tb = env->current_tb;
1543 3098dba0 aurel32
    /* if the cpu is currently executing code, we must unlink it and
1544 3098dba0 aurel32
       all the potentially executing TB */
1545 f76cfe56 Riku Voipio
    if (tb) {
1546 3098dba0 aurel32
        env->current_tb = NULL;
1547 3098dba0 aurel32
        tb_reset_jump_recursive(tb);
1548 be214e6c aurel32
    }
1549 26bc95a0 Riku Voipio
    spin_unlock(&interrupt_lock);
1550 3098dba0 aurel32
}
1551 3098dba0 aurel32
1552 3098dba0 aurel32
/* mask must never be zero, except for A20 change call */
1553 3098dba0 aurel32
void cpu_interrupt(CPUState *env, int mask)
1554 3098dba0 aurel32
{
1555 3098dba0 aurel32
    int old_mask;
1556 be214e6c aurel32
1557 2e70f6ef pbrook
    old_mask = env->interrupt_request;
1558 68a79315 bellard
    env->interrupt_request |= mask;
1559 3098dba0 aurel32
1560 8edac960 aliguori
#ifndef CONFIG_USER_ONLY
1561 8edac960 aliguori
    /*
1562 8edac960 aliguori
     * If called from iothread context, wake the target cpu in
1563 8edac960 aliguori
     * case its halted.
1564 8edac960 aliguori
     */
1565 8edac960 aliguori
    if (!qemu_cpu_self(env)) {
1566 8edac960 aliguori
        qemu_cpu_kick(env);
1567 8edac960 aliguori
        return;
1568 8edac960 aliguori
    }
1569 8edac960 aliguori
#endif
1570 8edac960 aliguori
1571 2e70f6ef pbrook
    if (use_icount) {
1572 266910c4 pbrook
        env->icount_decr.u16.high = 0xffff;
1573 2e70f6ef pbrook
#ifndef CONFIG_USER_ONLY
1574 2e70f6ef pbrook
        if (!can_do_io(env)
1575 be214e6c aurel32
            && (mask & ~old_mask) != 0) {
1576 2e70f6ef pbrook
            cpu_abort(env, "Raised interrupt while not in I/O function");
1577 2e70f6ef pbrook
        }
1578 2e70f6ef pbrook
#endif
1579 2e70f6ef pbrook
    } else {
1580 3098dba0 aurel32
        cpu_unlink_tb(env);
1581 ea041c0e bellard
    }
1582 ea041c0e bellard
}
1583 ea041c0e bellard
1584 b54ad049 bellard
void cpu_reset_interrupt(CPUState *env, int mask)
1585 b54ad049 bellard
{
1586 b54ad049 bellard
    env->interrupt_request &= ~mask;
1587 b54ad049 bellard
}
1588 b54ad049 bellard
1589 3098dba0 aurel32
void cpu_exit(CPUState *env)
1590 3098dba0 aurel32
{
1591 3098dba0 aurel32
    env->exit_request = 1;
1592 3098dba0 aurel32
    cpu_unlink_tb(env);
1593 3098dba0 aurel32
}
1594 3098dba0 aurel32
1595 c7cd6a37 blueswir1
const CPULogItem cpu_log_items[] = {
1596 5fafdf24 ths
    { CPU_LOG_TB_OUT_ASM, "out_asm",
1597 f193c797 bellard
      "show generated host assembly code for each compiled TB" },
1598 f193c797 bellard
    { CPU_LOG_TB_IN_ASM, "in_asm",
1599 f193c797 bellard
      "show target assembly code for each compiled TB" },
1600 5fafdf24 ths
    { CPU_LOG_TB_OP, "op",
1601 57fec1fe bellard
      "show micro ops for each compiled TB" },
1602 f193c797 bellard
    { CPU_LOG_TB_OP_OPT, "op_opt",
1603 e01a1157 blueswir1
      "show micro ops "
1604 e01a1157 blueswir1
#ifdef TARGET_I386
1605 e01a1157 blueswir1
      "before eflags optimization and "
1606 f193c797 bellard
#endif
1607 e01a1157 blueswir1
      "after liveness analysis" },
1608 f193c797 bellard
    { CPU_LOG_INT, "int",
1609 f193c797 bellard
      "show interrupts/exceptions in short format" },
1610 f193c797 bellard
    { CPU_LOG_EXEC, "exec",
1611 f193c797 bellard
      "show trace before each executed TB (lots of logs)" },
1612 9fddaa0c bellard
    { CPU_LOG_TB_CPU, "cpu",
1613 e91c8a77 ths
      "show CPU state before block translation" },
1614 f193c797 bellard
#ifdef TARGET_I386
1615 f193c797 bellard
    { CPU_LOG_PCALL, "pcall",
1616 f193c797 bellard
      "show protected mode far calls/returns/exceptions" },
1617 eca1bdf4 aliguori
    { CPU_LOG_RESET, "cpu_reset",
1618 eca1bdf4 aliguori
      "show CPU state before CPU resets" },
1619 f193c797 bellard
#endif
1620 8e3a9fd2 bellard
#ifdef DEBUG_IOPORT
1621 fd872598 bellard
    { CPU_LOG_IOPORT, "ioport",
1622 fd872598 bellard
      "show all i/o ports accesses" },
1623 8e3a9fd2 bellard
#endif
1624 f193c797 bellard
    { 0, NULL, NULL },
1625 f193c797 bellard
};
1626 f193c797 bellard
1627 f193c797 bellard
static int cmp1(const char *s1, int n, const char *s2)
1628 f193c797 bellard
{
1629 f193c797 bellard
    if (strlen(s2) != n)
1630 f193c797 bellard
        return 0;
1631 f193c797 bellard
    return memcmp(s1, s2, n) == 0;
1632 f193c797 bellard
}
1633 3b46e624 ths
1634 f193c797 bellard
/* takes a comma separated list of log masks. Return 0 if error. */
1635 f193c797 bellard
int cpu_str_to_log_mask(const char *str)
1636 f193c797 bellard
{
1637 c7cd6a37 blueswir1
    const CPULogItem *item;
1638 f193c797 bellard
    int mask;
1639 f193c797 bellard
    const char *p, *p1;
1640 f193c797 bellard
1641 f193c797 bellard
    p = str;
1642 f193c797 bellard
    mask = 0;
1643 f193c797 bellard
    for(;;) {
1644 f193c797 bellard
        p1 = strchr(p, ',');
1645 f193c797 bellard
        if (!p1)
1646 f193c797 bellard
            p1 = p + strlen(p);
1647 8e3a9fd2 bellard
        if(cmp1(p,p1-p,"all")) {
1648 8e3a9fd2 bellard
                for(item = cpu_log_items; item->mask != 0; item++) {
1649 8e3a9fd2 bellard
                        mask |= item->mask;
1650 8e3a9fd2 bellard
                }
1651 8e3a9fd2 bellard
        } else {
1652 f193c797 bellard
        for(item = cpu_log_items; item->mask != 0; item++) {
1653 f193c797 bellard
            if (cmp1(p, p1 - p, item->name))
1654 f193c797 bellard
                goto found;
1655 f193c797 bellard
        }
1656 f193c797 bellard
        return 0;
1657 8e3a9fd2 bellard
        }
1658 f193c797 bellard
    found:
1659 f193c797 bellard
        mask |= item->mask;
1660 f193c797 bellard
        if (*p1 != ',')
1661 f193c797 bellard
            break;
1662 f193c797 bellard
        p = p1 + 1;
1663 f193c797 bellard
    }
1664 f193c797 bellard
    return mask;
1665 f193c797 bellard
}
1666 ea041c0e bellard
1667 7501267e bellard
void cpu_abort(CPUState *env, const char *fmt, ...)
1668 7501267e bellard
{
1669 7501267e bellard
    va_list ap;
1670 493ae1f0 pbrook
    va_list ap2;
1671 7501267e bellard
1672 7501267e bellard
    va_start(ap, fmt);
1673 493ae1f0 pbrook
    va_copy(ap2, ap);
1674 7501267e bellard
    fprintf(stderr, "qemu: fatal: ");
1675 7501267e bellard
    vfprintf(stderr, fmt, ap);
1676 7501267e bellard
    fprintf(stderr, "\n");
1677 7501267e bellard
#ifdef TARGET_I386
1678 7fe48483 bellard
    cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1679 7fe48483 bellard
#else
1680 7fe48483 bellard
    cpu_dump_state(env, stderr, fprintf, 0);
1681 7501267e bellard
#endif
1682 93fcfe39 aliguori
    if (qemu_log_enabled()) {
1683 93fcfe39 aliguori
        qemu_log("qemu: fatal: ");
1684 93fcfe39 aliguori
        qemu_log_vprintf(fmt, ap2);
1685 93fcfe39 aliguori
        qemu_log("\n");
1686 f9373291 j_mayer
#ifdef TARGET_I386
1687 93fcfe39 aliguori
        log_cpu_state(env, X86_DUMP_FPU | X86_DUMP_CCOP);
1688 f9373291 j_mayer
#else
1689 93fcfe39 aliguori
        log_cpu_state(env, 0);
1690 f9373291 j_mayer
#endif
1691 31b1a7b4 aliguori
        qemu_log_flush();
1692 93fcfe39 aliguori
        qemu_log_close();
1693 924edcae balrog
    }
1694 493ae1f0 pbrook
    va_end(ap2);
1695 f9373291 j_mayer
    va_end(ap);
1696 d3219c7b Riku Voipio
#if defined(CONFIG_USER_ONLY)
1697 d3219c7b Riku Voipio
    {
1698 d3219c7b Riku Voipio
        struct sigaction act;
1699 d3219c7b Riku Voipio
        sigfillset(&act.sa_mask);
1700 d3219c7b Riku Voipio
        act.sa_handler = SIG_DFL;
1701 d3219c7b Riku Voipio
        sigaction(SIGABRT, &act, NULL);
1702 d3219c7b Riku Voipio
    }
1703 d3219c7b Riku Voipio
#endif
1704 7501267e bellard
    abort();
1705 7501267e bellard
}
1706 7501267e bellard
1707 c5be9f08 ths
CPUState *cpu_copy(CPUState *env)
1708 c5be9f08 ths
{
1709 01ba9816 ths
    CPUState *new_env = cpu_init(env->cpu_model_str);
1710 c5be9f08 ths
    CPUState *next_cpu = new_env->next_cpu;
1711 c5be9f08 ths
    int cpu_index = new_env->cpu_index;
1712 5a38f081 aliguori
#if defined(TARGET_HAS_ICE)
1713 5a38f081 aliguori
    CPUBreakpoint *bp;
1714 5a38f081 aliguori
    CPUWatchpoint *wp;
1715 5a38f081 aliguori
#endif
1716 5a38f081 aliguori
1717 c5be9f08 ths
    memcpy(new_env, env, sizeof(CPUState));
1718 5a38f081 aliguori
1719 5a38f081 aliguori
    /* Preserve chaining and index. */
1720 c5be9f08 ths
    new_env->next_cpu = next_cpu;
1721 c5be9f08 ths
    new_env->cpu_index = cpu_index;
1722 5a38f081 aliguori
1723 5a38f081 aliguori
    /* Clone all break/watchpoints.
1724 5a38f081 aliguori
       Note: Once we support ptrace with hw-debug register access, make sure
1725 5a38f081 aliguori
       BP_CPU break/watchpoints are handled correctly on clone. */
1726 72cf2d4f Blue Swirl
    QTAILQ_INIT(&env->breakpoints);
1727 72cf2d4f Blue Swirl
    QTAILQ_INIT(&env->watchpoints);
1728 5a38f081 aliguori
#if defined(TARGET_HAS_ICE)
1729 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1730 5a38f081 aliguori
        cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
1731 5a38f081 aliguori
    }
1732 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
1733 5a38f081 aliguori
        cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
1734 5a38f081 aliguori
                              wp->flags, NULL);
1735 5a38f081 aliguori
    }
1736 5a38f081 aliguori
#endif
1737 5a38f081 aliguori
1738 c5be9f08 ths
    return new_env;
1739 c5be9f08 ths
}
1740 c5be9f08 ths
1741 0124311e bellard
#if !defined(CONFIG_USER_ONLY)
1742 0124311e bellard
1743 5c751e99 edgar_igl
static inline void tlb_flush_jmp_cache(CPUState *env, target_ulong addr)
1744 5c751e99 edgar_igl
{
1745 5c751e99 edgar_igl
    unsigned int i;
1746 5c751e99 edgar_igl
1747 5c751e99 edgar_igl
    /* Discard jump cache entries for any tb which might potentially
1748 5c751e99 edgar_igl
       overlap the flushed page.  */
1749 5c751e99 edgar_igl
    i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
1750 5c751e99 edgar_igl
    memset (&env->tb_jmp_cache[i], 0, 
1751 5c751e99 edgar_igl
            TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
1752 5c751e99 edgar_igl
1753 5c751e99 edgar_igl
    i = tb_jmp_cache_hash_page(addr);
1754 5c751e99 edgar_igl
    memset (&env->tb_jmp_cache[i], 0, 
1755 5c751e99 edgar_igl
            TB_JMP_PAGE_SIZE * sizeof(TranslationBlock *));
1756 5c751e99 edgar_igl
}
1757 5c751e99 edgar_igl
1758 08738984 Igor Kovalenko
static CPUTLBEntry s_cputlb_empty_entry = {
1759 08738984 Igor Kovalenko
    .addr_read  = -1,
1760 08738984 Igor Kovalenko
    .addr_write = -1,
1761 08738984 Igor Kovalenko
    .addr_code  = -1,
1762 08738984 Igor Kovalenko
    .addend     = -1,
1763 08738984 Igor Kovalenko
};
1764 08738984 Igor Kovalenko
1765 ee8b7021 bellard
/* NOTE: if flush_global is true, also flush global entries (not
1766 ee8b7021 bellard
   implemented yet) */
1767 ee8b7021 bellard
void tlb_flush(CPUState *env, int flush_global)
1768 33417e70 bellard
{
1769 33417e70 bellard
    int i;
1770 0124311e bellard
1771 9fa3e853 bellard
#if defined(DEBUG_TLB)
1772 9fa3e853 bellard
    printf("tlb_flush:\n");
1773 9fa3e853 bellard
#endif
1774 0124311e bellard
    /* must reset current TB so that interrupts cannot modify the
1775 0124311e bellard
       links while we are modifying them */
1776 0124311e bellard
    env->current_tb = NULL;
1777 0124311e bellard
1778 33417e70 bellard
    for(i = 0; i < CPU_TLB_SIZE; i++) {
1779 cfde4bd9 Isaku Yamahata
        int mmu_idx;
1780 cfde4bd9 Isaku Yamahata
        for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1781 08738984 Igor Kovalenko
            env->tlb_table[mmu_idx][i] = s_cputlb_empty_entry;
1782 cfde4bd9 Isaku Yamahata
        }
1783 33417e70 bellard
    }
1784 9fa3e853 bellard
1785 8a40a180 bellard
    memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
1786 9fa3e853 bellard
1787 e3db7226 bellard
    tlb_flush_count++;
1788 33417e70 bellard
}
1789 33417e70 bellard
1790 274da6b2 bellard
static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
1791 61382a50 bellard
{
1792 5fafdf24 ths
    if (addr == (tlb_entry->addr_read &
1793 84b7b8e7 bellard
                 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1794 5fafdf24 ths
        addr == (tlb_entry->addr_write &
1795 84b7b8e7 bellard
                 (TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
1796 5fafdf24 ths
        addr == (tlb_entry->addr_code &
1797 84b7b8e7 bellard
                 (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
1798 08738984 Igor Kovalenko
        *tlb_entry = s_cputlb_empty_entry;
1799 84b7b8e7 bellard
    }
1800 61382a50 bellard
}
1801 61382a50 bellard
1802 2e12669a bellard
void tlb_flush_page(CPUState *env, target_ulong addr)
1803 33417e70 bellard
{
1804 8a40a180 bellard
    int i;
1805 cfde4bd9 Isaku Yamahata
    int mmu_idx;
1806 0124311e bellard
1807 9fa3e853 bellard
#if defined(DEBUG_TLB)
1808 108c49b8 bellard
    printf("tlb_flush_page: " TARGET_FMT_lx "\n", addr);
1809 9fa3e853 bellard
#endif
1810 0124311e bellard
    /* must reset current TB so that interrupts cannot modify the
1811 0124311e bellard
       links while we are modifying them */
1812 0124311e bellard
    env->current_tb = NULL;
1813 61382a50 bellard
1814 61382a50 bellard
    addr &= TARGET_PAGE_MASK;
1815 61382a50 bellard
    i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1816 cfde4bd9 Isaku Yamahata
    for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++)
1817 cfde4bd9 Isaku Yamahata
        tlb_flush_entry(&env->tlb_table[mmu_idx][i], addr);
1818 0124311e bellard
1819 5c751e99 edgar_igl
    tlb_flush_jmp_cache(env, addr);
1820 9fa3e853 bellard
}
1821 9fa3e853 bellard
1822 9fa3e853 bellard
/* update the TLBs so that writes to code in the virtual page 'addr'
1823 9fa3e853 bellard
   can be detected */
1824 c227f099 Anthony Liguori
static void tlb_protect_code(ram_addr_t ram_addr)
1825 9fa3e853 bellard
{
1826 5fafdf24 ths
    cpu_physical_memory_reset_dirty(ram_addr,
1827 6a00d601 bellard
                                    ram_addr + TARGET_PAGE_SIZE,
1828 6a00d601 bellard
                                    CODE_DIRTY_FLAG);
1829 9fa3e853 bellard
}
1830 9fa3e853 bellard
1831 9fa3e853 bellard
/* update the TLB so that writes in physical page 'phys_addr' are no longer
1832 3a7d929e bellard
   tested for self modifying code */
1833 c227f099 Anthony Liguori
static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
1834 3a7d929e bellard
                                    target_ulong vaddr)
1835 9fa3e853 bellard
{
1836 3a7d929e bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] |= CODE_DIRTY_FLAG;
1837 1ccde1cb bellard
}
1838 1ccde1cb bellard
1839 5fafdf24 ths
static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
1840 1ccde1cb bellard
                                         unsigned long start, unsigned long length)
1841 1ccde1cb bellard
{
1842 1ccde1cb bellard
    unsigned long addr;
1843 84b7b8e7 bellard
    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1844 84b7b8e7 bellard
        addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
1845 1ccde1cb bellard
        if ((addr - start) < length) {
1846 0f459d16 pbrook
            tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
1847 1ccde1cb bellard
        }
1848 1ccde1cb bellard
    }
1849 1ccde1cb bellard
}
1850 1ccde1cb bellard
1851 5579c7f3 pbrook
/* Note: start and end must be within the same ram block.  */
1852 c227f099 Anthony Liguori
void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
1853 0a962c02 bellard
                                     int dirty_flags)
1854 1ccde1cb bellard
{
1855 1ccde1cb bellard
    CPUState *env;
1856 4f2ac237 bellard
    unsigned long length, start1;
1857 0a962c02 bellard
    int i, mask, len;
1858 0a962c02 bellard
    uint8_t *p;
1859 1ccde1cb bellard
1860 1ccde1cb bellard
    start &= TARGET_PAGE_MASK;
1861 1ccde1cb bellard
    end = TARGET_PAGE_ALIGN(end);
1862 1ccde1cb bellard
1863 1ccde1cb bellard
    length = end - start;
1864 1ccde1cb bellard
    if (length == 0)
1865 1ccde1cb bellard
        return;
1866 0a962c02 bellard
    len = length >> TARGET_PAGE_BITS;
1867 f23db169 bellard
    mask = ~dirty_flags;
1868 f23db169 bellard
    p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
1869 f23db169 bellard
    for(i = 0; i < len; i++)
1870 f23db169 bellard
        p[i] &= mask;
1871 f23db169 bellard
1872 1ccde1cb bellard
    /* we modify the TLB cache so that the dirty bit will be set again
1873 1ccde1cb bellard
       when accessing the range */
1874 5579c7f3 pbrook
    start1 = (unsigned long)qemu_get_ram_ptr(start);
1875 5579c7f3 pbrook
    /* Chek that we don't span multiple blocks - this breaks the
1876 5579c7f3 pbrook
       address comparisons below.  */
1877 5579c7f3 pbrook
    if ((unsigned long)qemu_get_ram_ptr(end - 1) - start1
1878 5579c7f3 pbrook
            != (end - 1) - start) {
1879 5579c7f3 pbrook
        abort();
1880 5579c7f3 pbrook
    }
1881 5579c7f3 pbrook
1882 6a00d601 bellard
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
1883 cfde4bd9 Isaku Yamahata
        int mmu_idx;
1884 cfde4bd9 Isaku Yamahata
        for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1885 cfde4bd9 Isaku Yamahata
            for(i = 0; i < CPU_TLB_SIZE; i++)
1886 cfde4bd9 Isaku Yamahata
                tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
1887 cfde4bd9 Isaku Yamahata
                                      start1, length);
1888 cfde4bd9 Isaku Yamahata
        }
1889 6a00d601 bellard
    }
1890 1ccde1cb bellard
}
1891 1ccde1cb bellard
1892 74576198 aliguori
int cpu_physical_memory_set_dirty_tracking(int enable)
1893 74576198 aliguori
{
1894 74576198 aliguori
    in_migration = enable;
1895 b0a46a33 Jan Kiszka
    if (kvm_enabled()) {
1896 b0a46a33 Jan Kiszka
        return kvm_set_migration_log(enable);
1897 b0a46a33 Jan Kiszka
    }
1898 74576198 aliguori
    return 0;
1899 74576198 aliguori
}
1900 74576198 aliguori
1901 74576198 aliguori
int cpu_physical_memory_get_dirty_tracking(void)
1902 74576198 aliguori
{
1903 74576198 aliguori
    return in_migration;
1904 74576198 aliguori
}
1905 74576198 aliguori
1906 c227f099 Anthony Liguori
int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
1907 c227f099 Anthony Liguori
                                   target_phys_addr_t end_addr)
1908 2bec46dc aliguori
{
1909 151f7749 Jan Kiszka
    int ret = 0;
1910 151f7749 Jan Kiszka
1911 2bec46dc aliguori
    if (kvm_enabled())
1912 151f7749 Jan Kiszka
        ret = kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
1913 151f7749 Jan Kiszka
    return ret;
1914 2bec46dc aliguori
}
1915 2bec46dc aliguori
1916 3a7d929e bellard
static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
1917 3a7d929e bellard
{
1918 c227f099 Anthony Liguori
    ram_addr_t ram_addr;
1919 5579c7f3 pbrook
    void *p;
1920 3a7d929e bellard
1921 84b7b8e7 bellard
    if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1922 5579c7f3 pbrook
        p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
1923 5579c7f3 pbrook
            + tlb_entry->addend);
1924 5579c7f3 pbrook
        ram_addr = qemu_ram_addr_from_host(p);
1925 3a7d929e bellard
        if (!cpu_physical_memory_is_dirty(ram_addr)) {
1926 0f459d16 pbrook
            tlb_entry->addr_write |= TLB_NOTDIRTY;
1927 3a7d929e bellard
        }
1928 3a7d929e bellard
    }
1929 3a7d929e bellard
}
1930 3a7d929e bellard
1931 3a7d929e bellard
/* update the TLB according to the current state of the dirty bits */
1932 3a7d929e bellard
void cpu_tlb_update_dirty(CPUState *env)
1933 3a7d929e bellard
{
1934 3a7d929e bellard
    int i;
1935 cfde4bd9 Isaku Yamahata
    int mmu_idx;
1936 cfde4bd9 Isaku Yamahata
    for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
1937 cfde4bd9 Isaku Yamahata
        for(i = 0; i < CPU_TLB_SIZE; i++)
1938 cfde4bd9 Isaku Yamahata
            tlb_update_dirty(&env->tlb_table[mmu_idx][i]);
1939 cfde4bd9 Isaku Yamahata
    }
1940 3a7d929e bellard
}
1941 3a7d929e bellard
1942 0f459d16 pbrook
static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, target_ulong vaddr)
1943 1ccde1cb bellard
{
1944 0f459d16 pbrook
    if (tlb_entry->addr_write == (vaddr | TLB_NOTDIRTY))
1945 0f459d16 pbrook
        tlb_entry->addr_write = vaddr;
1946 1ccde1cb bellard
}
1947 1ccde1cb bellard
1948 0f459d16 pbrook
/* update the TLB corresponding to virtual page vaddr
1949 0f459d16 pbrook
   so that it is no longer dirty */
1950 0f459d16 pbrook
static inline void tlb_set_dirty(CPUState *env, target_ulong vaddr)
1951 1ccde1cb bellard
{
1952 1ccde1cb bellard
    int i;
1953 cfde4bd9 Isaku Yamahata
    int mmu_idx;
1954 1ccde1cb bellard
1955 0f459d16 pbrook
    vaddr &= TARGET_PAGE_MASK;
1956 1ccde1cb bellard
    i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1957 cfde4bd9 Isaku Yamahata
    for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++)
1958 cfde4bd9 Isaku Yamahata
        tlb_set_dirty1(&env->tlb_table[mmu_idx][i], vaddr);
1959 9fa3e853 bellard
}
1960 9fa3e853 bellard
1961 59817ccb bellard
/* add a new TLB entry. At most one entry for a given virtual address
1962 59817ccb bellard
   is permitted. Return 0 if OK or 2 if the page could not be mapped
1963 59817ccb bellard
   (can only happen in non SOFTMMU mode for I/O pages or pages
1964 59817ccb bellard
   conflicting with the host address space). */
1965 5fafdf24 ths
int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
1966 c227f099 Anthony Liguori
                      target_phys_addr_t paddr, int prot,
1967 6ebbf390 j_mayer
                      int mmu_idx, int is_softmmu)
1968 9fa3e853 bellard
{
1969 92e873b9 bellard
    PhysPageDesc *p;
1970 4f2ac237 bellard
    unsigned long pd;
1971 9fa3e853 bellard
    unsigned int index;
1972 4f2ac237 bellard
    target_ulong address;
1973 0f459d16 pbrook
    target_ulong code_address;
1974 c227f099 Anthony Liguori
    target_phys_addr_t addend;
1975 9fa3e853 bellard
    int ret;
1976 84b7b8e7 bellard
    CPUTLBEntry *te;
1977 a1d1bb31 aliguori
    CPUWatchpoint *wp;
1978 c227f099 Anthony Liguori
    target_phys_addr_t iotlb;
1979 9fa3e853 bellard
1980 92e873b9 bellard
    p = phys_page_find(paddr >> TARGET_PAGE_BITS);
1981 9fa3e853 bellard
    if (!p) {
1982 9fa3e853 bellard
        pd = IO_MEM_UNASSIGNED;
1983 9fa3e853 bellard
    } else {
1984 9fa3e853 bellard
        pd = p->phys_offset;
1985 9fa3e853 bellard
    }
1986 9fa3e853 bellard
#if defined(DEBUG_TLB)
1987 6ebbf390 j_mayer
    printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x%08x prot=%x idx=%d smmu=%d pd=0x%08lx\n",
1988 6ebbf390 j_mayer
           vaddr, (int)paddr, prot, mmu_idx, is_softmmu, pd);
1989 9fa3e853 bellard
#endif
1990 9fa3e853 bellard
1991 9fa3e853 bellard
    ret = 0;
1992 0f459d16 pbrook
    address = vaddr;
1993 0f459d16 pbrook
    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
1994 0f459d16 pbrook
        /* IO memory case (romd handled later) */
1995 0f459d16 pbrook
        address |= TLB_MMIO;
1996 0f459d16 pbrook
    }
1997 5579c7f3 pbrook
    addend = (unsigned long)qemu_get_ram_ptr(pd & TARGET_PAGE_MASK);
1998 0f459d16 pbrook
    if ((pd & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
1999 0f459d16 pbrook
        /* Normal RAM.  */
2000 0f459d16 pbrook
        iotlb = pd & TARGET_PAGE_MASK;
2001 0f459d16 pbrook
        if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM)
2002 0f459d16 pbrook
            iotlb |= IO_MEM_NOTDIRTY;
2003 0f459d16 pbrook
        else
2004 0f459d16 pbrook
            iotlb |= IO_MEM_ROM;
2005 0f459d16 pbrook
    } else {
2006 ccbb4d44 Stuart Brady
        /* IO handlers are currently passed a physical address.
2007 0f459d16 pbrook
           It would be nice to pass an offset from the base address
2008 0f459d16 pbrook
           of that region.  This would avoid having to special case RAM,
2009 0f459d16 pbrook
           and avoid full address decoding in every device.
2010 0f459d16 pbrook
           We can't use the high bits of pd for this because
2011 0f459d16 pbrook
           IO_MEM_ROMD uses these as a ram address.  */
2012 8da3ff18 pbrook
        iotlb = (pd & ~TARGET_PAGE_MASK);
2013 8da3ff18 pbrook
        if (p) {
2014 8da3ff18 pbrook
            iotlb += p->region_offset;
2015 8da3ff18 pbrook
        } else {
2016 8da3ff18 pbrook
            iotlb += paddr;
2017 8da3ff18 pbrook
        }
2018 0f459d16 pbrook
    }
2019 0f459d16 pbrook
2020 0f459d16 pbrook
    code_address = address;
2021 0f459d16 pbrook
    /* Make accesses to pages with watchpoints go via the
2022 0f459d16 pbrook
       watchpoint trap routines.  */
2023 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
2024 a1d1bb31 aliguori
        if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) {
2025 0f459d16 pbrook
            iotlb = io_mem_watch + paddr;
2026 0f459d16 pbrook
            /* TODO: The memory case can be optimized by not trapping
2027 0f459d16 pbrook
               reads of pages with a write breakpoint.  */
2028 0f459d16 pbrook
            address |= TLB_MMIO;
2029 6658ffb8 pbrook
        }
2030 0f459d16 pbrook
    }
2031 d79acba4 balrog
2032 0f459d16 pbrook
    index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
2033 0f459d16 pbrook
    env->iotlb[mmu_idx][index] = iotlb - vaddr;
2034 0f459d16 pbrook
    te = &env->tlb_table[mmu_idx][index];
2035 0f459d16 pbrook
    te->addend = addend - vaddr;
2036 0f459d16 pbrook
    if (prot & PAGE_READ) {
2037 0f459d16 pbrook
        te->addr_read = address;
2038 0f459d16 pbrook
    } else {
2039 0f459d16 pbrook
        te->addr_read = -1;
2040 0f459d16 pbrook
    }
2041 5c751e99 edgar_igl
2042 0f459d16 pbrook
    if (prot & PAGE_EXEC) {
2043 0f459d16 pbrook
        te->addr_code = code_address;
2044 0f459d16 pbrook
    } else {
2045 0f459d16 pbrook
        te->addr_code = -1;
2046 0f459d16 pbrook
    }
2047 0f459d16 pbrook
    if (prot & PAGE_WRITE) {
2048 0f459d16 pbrook
        if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM ||
2049 0f459d16 pbrook
            (pd & IO_MEM_ROMD)) {
2050 0f459d16 pbrook
            /* Write access calls the I/O callback.  */
2051 0f459d16 pbrook
            te->addr_write = address | TLB_MMIO;
2052 0f459d16 pbrook
        } else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
2053 0f459d16 pbrook
                   !cpu_physical_memory_is_dirty(pd)) {
2054 0f459d16 pbrook
            te->addr_write = address | TLB_NOTDIRTY;
2055 9fa3e853 bellard
        } else {
2056 0f459d16 pbrook
            te->addr_write = address;
2057 9fa3e853 bellard
        }
2058 0f459d16 pbrook
    } else {
2059 0f459d16 pbrook
        te->addr_write = -1;
2060 9fa3e853 bellard
    }
2061 9fa3e853 bellard
    return ret;
2062 9fa3e853 bellard
}
2063 9fa3e853 bellard
2064 0124311e bellard
#else
2065 0124311e bellard
2066 ee8b7021 bellard
void tlb_flush(CPUState *env, int flush_global)
2067 0124311e bellard
{
2068 0124311e bellard
}
2069 0124311e bellard
2070 2e12669a bellard
void tlb_flush_page(CPUState *env, target_ulong addr)
2071 0124311e bellard
{
2072 0124311e bellard
}
2073 0124311e bellard
2074 5fafdf24 ths
int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
2075 c227f099 Anthony Liguori
                      target_phys_addr_t paddr, int prot,
2076 6ebbf390 j_mayer
                      int mmu_idx, int is_softmmu)
2077 9fa3e853 bellard
{
2078 9fa3e853 bellard
    return 0;
2079 9fa3e853 bellard
}
2080 0124311e bellard
2081 edf8e2af Mika Westerberg
/*
2082 edf8e2af Mika Westerberg
 * Walks guest process memory "regions" one by one
2083 edf8e2af Mika Westerberg
 * and calls callback function 'fn' for each region.
2084 edf8e2af Mika Westerberg
 */
2085 edf8e2af Mika Westerberg
int walk_memory_regions(void *priv,
2086 edf8e2af Mika Westerberg
    int (*fn)(void *, unsigned long, unsigned long, unsigned long))
2087 33417e70 bellard
{
2088 9fa3e853 bellard
    unsigned long start, end;
2089 edf8e2af Mika Westerberg
    PageDesc *p = NULL;
2090 9fa3e853 bellard
    int i, j, prot, prot1;
2091 edf8e2af Mika Westerberg
    int rc = 0;
2092 33417e70 bellard
2093 edf8e2af Mika Westerberg
    start = end = -1;
2094 9fa3e853 bellard
    prot = 0;
2095 edf8e2af Mika Westerberg
2096 edf8e2af Mika Westerberg
    for (i = 0; i <= L1_SIZE; i++) {
2097 edf8e2af Mika Westerberg
        p = (i < L1_SIZE) ? l1_map[i] : NULL;
2098 edf8e2af Mika Westerberg
        for (j = 0; j < L2_SIZE; j++) {
2099 edf8e2af Mika Westerberg
            prot1 = (p == NULL) ? 0 : p[j].flags;
2100 edf8e2af Mika Westerberg
            /*
2101 edf8e2af Mika Westerberg
             * "region" is one continuous chunk of memory
2102 edf8e2af Mika Westerberg
             * that has same protection flags set.
2103 edf8e2af Mika Westerberg
             */
2104 9fa3e853 bellard
            if (prot1 != prot) {
2105 9fa3e853 bellard
                end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
2106 9fa3e853 bellard
                if (start != -1) {
2107 edf8e2af Mika Westerberg
                    rc = (*fn)(priv, start, end, prot);
2108 edf8e2af Mika Westerberg
                    /* callback can stop iteration by returning != 0 */
2109 edf8e2af Mika Westerberg
                    if (rc != 0)
2110 edf8e2af Mika Westerberg
                        return (rc);
2111 9fa3e853 bellard
                }
2112 9fa3e853 bellard
                if (prot1 != 0)
2113 9fa3e853 bellard
                    start = end;
2114 9fa3e853 bellard
                else
2115 9fa3e853 bellard
                    start = -1;
2116 9fa3e853 bellard
                prot = prot1;
2117 9fa3e853 bellard
            }
2118 edf8e2af Mika Westerberg
            if (p == NULL)
2119 9fa3e853 bellard
                break;
2120 9fa3e853 bellard
        }
2121 33417e70 bellard
    }
2122 edf8e2af Mika Westerberg
    return (rc);
2123 edf8e2af Mika Westerberg
}
2124 edf8e2af Mika Westerberg
2125 edf8e2af Mika Westerberg
static int dump_region(void *priv, unsigned long start,
2126 edf8e2af Mika Westerberg
    unsigned long end, unsigned long prot)
2127 edf8e2af Mika Westerberg
{
2128 edf8e2af Mika Westerberg
    FILE *f = (FILE *)priv;
2129 edf8e2af Mika Westerberg
2130 edf8e2af Mika Westerberg
    (void) fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
2131 edf8e2af Mika Westerberg
        start, end, end - start,
2132 edf8e2af Mika Westerberg
        ((prot & PAGE_READ) ? 'r' : '-'),
2133 edf8e2af Mika Westerberg
        ((prot & PAGE_WRITE) ? 'w' : '-'),
2134 edf8e2af Mika Westerberg
        ((prot & PAGE_EXEC) ? 'x' : '-'));
2135 edf8e2af Mika Westerberg
2136 edf8e2af Mika Westerberg
    return (0);
2137 edf8e2af Mika Westerberg
}
2138 edf8e2af Mika Westerberg
2139 edf8e2af Mika Westerberg
/* dump memory mappings */
2140 edf8e2af Mika Westerberg
void page_dump(FILE *f)
2141 edf8e2af Mika Westerberg
{
2142 edf8e2af Mika Westerberg
    (void) fprintf(f, "%-8s %-8s %-8s %s\n",
2143 edf8e2af Mika Westerberg
            "start", "end", "size", "prot");
2144 edf8e2af Mika Westerberg
    walk_memory_regions(f, dump_region);
2145 33417e70 bellard
}
2146 33417e70 bellard
2147 53a5960a pbrook
int page_get_flags(target_ulong address)
2148 33417e70 bellard
{
2149 9fa3e853 bellard
    PageDesc *p;
2150 9fa3e853 bellard
2151 9fa3e853 bellard
    p = page_find(address >> TARGET_PAGE_BITS);
2152 33417e70 bellard
    if (!p)
2153 9fa3e853 bellard
        return 0;
2154 9fa3e853 bellard
    return p->flags;
2155 9fa3e853 bellard
}
2156 9fa3e853 bellard
2157 9fa3e853 bellard
/* modify the flags of a page and invalidate the code if
2158 ccbb4d44 Stuart Brady
   necessary. The flag PAGE_WRITE_ORG is positioned automatically
2159 9fa3e853 bellard
   depending on PAGE_WRITE */
2160 53a5960a pbrook
void page_set_flags(target_ulong start, target_ulong end, int flags)
2161 9fa3e853 bellard
{
2162 9fa3e853 bellard
    PageDesc *p;
2163 53a5960a pbrook
    target_ulong addr;
2164 9fa3e853 bellard
2165 c8a706fe pbrook
    /* mmap_lock should already be held.  */
2166 9fa3e853 bellard
    start = start & TARGET_PAGE_MASK;
2167 9fa3e853 bellard
    end = TARGET_PAGE_ALIGN(end);
2168 9fa3e853 bellard
    if (flags & PAGE_WRITE)
2169 9fa3e853 bellard
        flags |= PAGE_WRITE_ORG;
2170 9fa3e853 bellard
    for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2171 9fa3e853 bellard
        p = page_find_alloc(addr >> TARGET_PAGE_BITS);
2172 17e2377a pbrook
        /* We may be called for host regions that are outside guest
2173 17e2377a pbrook
           address space.  */
2174 17e2377a pbrook
        if (!p)
2175 17e2377a pbrook
            return;
2176 9fa3e853 bellard
        /* if the write protection is set, then we invalidate the code
2177 9fa3e853 bellard
           inside */
2178 5fafdf24 ths
        if (!(p->flags & PAGE_WRITE) &&
2179 9fa3e853 bellard
            (flags & PAGE_WRITE) &&
2180 9fa3e853 bellard
            p->first_tb) {
2181 d720b93d bellard
            tb_invalidate_phys_page(addr, 0, NULL);
2182 9fa3e853 bellard
        }
2183 9fa3e853 bellard
        p->flags = flags;
2184 9fa3e853 bellard
    }
2185 33417e70 bellard
}
2186 33417e70 bellard
2187 3d97b40b ths
int page_check_range(target_ulong start, target_ulong len, int flags)
2188 3d97b40b ths
{
2189 3d97b40b ths
    PageDesc *p;
2190 3d97b40b ths
    target_ulong end;
2191 3d97b40b ths
    target_ulong addr;
2192 3d97b40b ths
2193 55f280c9 balrog
    if (start + len < start)
2194 55f280c9 balrog
        /* we've wrapped around */
2195 55f280c9 balrog
        return -1;
2196 55f280c9 balrog
2197 3d97b40b ths
    end = TARGET_PAGE_ALIGN(start+len); /* must do before we loose bits in the next step */
2198 3d97b40b ths
    start = start & TARGET_PAGE_MASK;
2199 3d97b40b ths
2200 3d97b40b ths
    for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
2201 3d97b40b ths
        p = page_find(addr >> TARGET_PAGE_BITS);
2202 3d97b40b ths
        if( !p )
2203 3d97b40b ths
            return -1;
2204 3d97b40b ths
        if( !(p->flags & PAGE_VALID) )
2205 3d97b40b ths
            return -1;
2206 3d97b40b ths
2207 dae3270c bellard
        if ((flags & PAGE_READ) && !(p->flags & PAGE_READ))
2208 3d97b40b ths
            return -1;
2209 dae3270c bellard
        if (flags & PAGE_WRITE) {
2210 dae3270c bellard
            if (!(p->flags & PAGE_WRITE_ORG))
2211 dae3270c bellard
                return -1;
2212 dae3270c bellard
            /* unprotect the page if it was put read-only because it
2213 dae3270c bellard
               contains translated code */
2214 dae3270c bellard
            if (!(p->flags & PAGE_WRITE)) {
2215 dae3270c bellard
                if (!page_unprotect(addr, 0, NULL))
2216 dae3270c bellard
                    return -1;
2217 dae3270c bellard
            }
2218 dae3270c bellard
            return 0;
2219 dae3270c bellard
        }
2220 3d97b40b ths
    }
2221 3d97b40b ths
    return 0;
2222 3d97b40b ths
}
2223 3d97b40b ths
2224 9fa3e853 bellard
/* called from signal handler: invalidate the code and unprotect the
2225 ccbb4d44 Stuart Brady
   page. Return TRUE if the fault was successfully handled. */
2226 53a5960a pbrook
int page_unprotect(target_ulong address, unsigned long pc, void *puc)
2227 9fa3e853 bellard
{
2228 9fa3e853 bellard
    unsigned int page_index, prot, pindex;
2229 9fa3e853 bellard
    PageDesc *p, *p1;
2230 53a5960a pbrook
    target_ulong host_start, host_end, addr;
2231 9fa3e853 bellard
2232 c8a706fe pbrook
    /* Technically this isn't safe inside a signal handler.  However we
2233 c8a706fe pbrook
       know this only ever happens in a synchronous SEGV handler, so in
2234 c8a706fe pbrook
       practice it seems to be ok.  */
2235 c8a706fe pbrook
    mmap_lock();
2236 c8a706fe pbrook
2237 83fb7adf bellard
    host_start = address & qemu_host_page_mask;
2238 9fa3e853 bellard
    page_index = host_start >> TARGET_PAGE_BITS;
2239 9fa3e853 bellard
    p1 = page_find(page_index);
2240 c8a706fe pbrook
    if (!p1) {
2241 c8a706fe pbrook
        mmap_unlock();
2242 9fa3e853 bellard
        return 0;
2243 c8a706fe pbrook
    }
2244 83fb7adf bellard
    host_end = host_start + qemu_host_page_size;
2245 9fa3e853 bellard
    p = p1;
2246 9fa3e853 bellard
    prot = 0;
2247 9fa3e853 bellard
    for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
2248 9fa3e853 bellard
        prot |= p->flags;
2249 9fa3e853 bellard
        p++;
2250 9fa3e853 bellard
    }
2251 9fa3e853 bellard
    /* if the page was really writable, then we change its
2252 9fa3e853 bellard
       protection back to writable */
2253 9fa3e853 bellard
    if (prot & PAGE_WRITE_ORG) {
2254 9fa3e853 bellard
        pindex = (address - host_start) >> TARGET_PAGE_BITS;
2255 9fa3e853 bellard
        if (!(p1[pindex].flags & PAGE_WRITE)) {
2256 5fafdf24 ths
            mprotect((void *)g2h(host_start), qemu_host_page_size,
2257 9fa3e853 bellard
                     (prot & PAGE_BITS) | PAGE_WRITE);
2258 9fa3e853 bellard
            p1[pindex].flags |= PAGE_WRITE;
2259 9fa3e853 bellard
            /* and since the content will be modified, we must invalidate
2260 9fa3e853 bellard
               the corresponding translated code. */
2261 d720b93d bellard
            tb_invalidate_phys_page(address, pc, puc);
2262 9fa3e853 bellard
#ifdef DEBUG_TB_CHECK
2263 9fa3e853 bellard
            tb_invalidate_check(address);
2264 9fa3e853 bellard
#endif
2265 c8a706fe pbrook
            mmap_unlock();
2266 9fa3e853 bellard
            return 1;
2267 9fa3e853 bellard
        }
2268 9fa3e853 bellard
    }
2269 c8a706fe pbrook
    mmap_unlock();
2270 9fa3e853 bellard
    return 0;
2271 9fa3e853 bellard
}
2272 9fa3e853 bellard
2273 6a00d601 bellard
static inline void tlb_set_dirty(CPUState *env,
2274 6a00d601 bellard
                                 unsigned long addr, target_ulong vaddr)
2275 1ccde1cb bellard
{
2276 1ccde1cb bellard
}
2277 9fa3e853 bellard
#endif /* defined(CONFIG_USER_ONLY) */
2278 9fa3e853 bellard
2279 e2eef170 pbrook
#if !defined(CONFIG_USER_ONLY)
2280 8da3ff18 pbrook
2281 c227f099 Anthony Liguori
static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
2282 c227f099 Anthony Liguori
                             ram_addr_t memory, ram_addr_t region_offset);
2283 c227f099 Anthony Liguori
static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
2284 c227f099 Anthony Liguori
                           ram_addr_t orig_memory, ram_addr_t region_offset);
2285 db7b5426 blueswir1
#define CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, \
2286 db7b5426 blueswir1
                      need_subpage)                                     \
2287 db7b5426 blueswir1
    do {                                                                \
2288 db7b5426 blueswir1
        if (addr > start_addr)                                          \
2289 db7b5426 blueswir1
            start_addr2 = 0;                                            \
2290 db7b5426 blueswir1
        else {                                                          \
2291 db7b5426 blueswir1
            start_addr2 = start_addr & ~TARGET_PAGE_MASK;               \
2292 db7b5426 blueswir1
            if (start_addr2 > 0)                                        \
2293 db7b5426 blueswir1
                need_subpage = 1;                                       \
2294 db7b5426 blueswir1
        }                                                               \
2295 db7b5426 blueswir1
                                                                        \
2296 49e9fba2 blueswir1
        if ((start_addr + orig_size) - addr >= TARGET_PAGE_SIZE)        \
2297 db7b5426 blueswir1
            end_addr2 = TARGET_PAGE_SIZE - 1;                           \
2298 db7b5426 blueswir1
        else {                                                          \
2299 db7b5426 blueswir1
            end_addr2 = (start_addr + orig_size - 1) & ~TARGET_PAGE_MASK; \
2300 db7b5426 blueswir1
            if (end_addr2 < TARGET_PAGE_SIZE - 1)                       \
2301 db7b5426 blueswir1
                need_subpage = 1;                                       \
2302 db7b5426 blueswir1
        }                                                               \
2303 db7b5426 blueswir1
    } while (0)
2304 db7b5426 blueswir1
2305 8f2498f9 Michael S. Tsirkin
/* register physical memory.
2306 8f2498f9 Michael S. Tsirkin
   For RAM, 'size' must be a multiple of the target page size.
2307 8f2498f9 Michael S. Tsirkin
   If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
2308 8da3ff18 pbrook
   io memory page.  The address used when calling the IO function is
2309 8da3ff18 pbrook
   the offset from the start of the region, plus region_offset.  Both
2310 ccbb4d44 Stuart Brady
   start_addr and region_offset are rounded down to a page boundary
2311 8da3ff18 pbrook
   before calculating this offset.  This should not be a problem unless
2312 8da3ff18 pbrook
   the low bits of start_addr and region_offset differ.  */
2313 c227f099 Anthony Liguori
void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
2314 c227f099 Anthony Liguori
                                         ram_addr_t size,
2315 c227f099 Anthony Liguori
                                         ram_addr_t phys_offset,
2316 c227f099 Anthony Liguori
                                         ram_addr_t region_offset)
2317 33417e70 bellard
{
2318 c227f099 Anthony Liguori
    target_phys_addr_t addr, end_addr;
2319 92e873b9 bellard
    PhysPageDesc *p;
2320 9d42037b bellard
    CPUState *env;
2321 c227f099 Anthony Liguori
    ram_addr_t orig_size = size;
2322 db7b5426 blueswir1
    void *subpage;
2323 33417e70 bellard
2324 7ba1e619 aliguori
    if (kvm_enabled())
2325 7ba1e619 aliguori
        kvm_set_phys_mem(start_addr, size, phys_offset);
2326 7ba1e619 aliguori
2327 67c4d23c pbrook
    if (phys_offset == IO_MEM_UNASSIGNED) {
2328 67c4d23c pbrook
        region_offset = start_addr;
2329 67c4d23c pbrook
    }
2330 8da3ff18 pbrook
    region_offset &= TARGET_PAGE_MASK;
2331 5fd386f6 bellard
    size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
2332 c227f099 Anthony Liguori
    end_addr = start_addr + (target_phys_addr_t)size;
2333 49e9fba2 blueswir1
    for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
2334 db7b5426 blueswir1
        p = phys_page_find(addr >> TARGET_PAGE_BITS);
2335 db7b5426 blueswir1
        if (p && p->phys_offset != IO_MEM_UNASSIGNED) {
2336 c227f099 Anthony Liguori
            ram_addr_t orig_memory = p->phys_offset;
2337 c227f099 Anthony Liguori
            target_phys_addr_t start_addr2, end_addr2;
2338 db7b5426 blueswir1
            int need_subpage = 0;
2339 db7b5426 blueswir1
2340 db7b5426 blueswir1
            CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
2341 db7b5426 blueswir1
                          need_subpage);
2342 4254fab8 blueswir1
            if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
2343 db7b5426 blueswir1
                if (!(orig_memory & IO_MEM_SUBPAGE)) {
2344 db7b5426 blueswir1
                    subpage = subpage_init((addr & TARGET_PAGE_MASK),
2345 8da3ff18 pbrook
                                           &p->phys_offset, orig_memory,
2346 8da3ff18 pbrook
                                           p->region_offset);
2347 db7b5426 blueswir1
                } else {
2348 db7b5426 blueswir1
                    subpage = io_mem_opaque[(orig_memory & ~TARGET_PAGE_MASK)
2349 db7b5426 blueswir1
                                            >> IO_MEM_SHIFT];
2350 db7b5426 blueswir1
                }
2351 8da3ff18 pbrook
                subpage_register(subpage, start_addr2, end_addr2, phys_offset,
2352 8da3ff18 pbrook
                                 region_offset);
2353 8da3ff18 pbrook
                p->region_offset = 0;
2354 db7b5426 blueswir1
            } else {
2355 db7b5426 blueswir1
                p->phys_offset = phys_offset;
2356 db7b5426 blueswir1
                if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2357 db7b5426 blueswir1
                    (phys_offset & IO_MEM_ROMD))
2358 db7b5426 blueswir1
                    phys_offset += TARGET_PAGE_SIZE;
2359 db7b5426 blueswir1
            }
2360 db7b5426 blueswir1
        } else {
2361 db7b5426 blueswir1
            p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
2362 db7b5426 blueswir1
            p->phys_offset = phys_offset;
2363 8da3ff18 pbrook
            p->region_offset = region_offset;
2364 db7b5426 blueswir1
            if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
2365 8da3ff18 pbrook
                (phys_offset & IO_MEM_ROMD)) {
2366 db7b5426 blueswir1
                phys_offset += TARGET_PAGE_SIZE;
2367 0e8f0967 pbrook
            } else {
2368 c227f099 Anthony Liguori
                target_phys_addr_t start_addr2, end_addr2;
2369 db7b5426 blueswir1
                int need_subpage = 0;
2370 db7b5426 blueswir1
2371 db7b5426 blueswir1
                CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
2372 db7b5426 blueswir1
                              end_addr2, need_subpage);
2373 db7b5426 blueswir1
2374 4254fab8 blueswir1
                if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
2375 db7b5426 blueswir1
                    subpage = subpage_init((addr & TARGET_PAGE_MASK),
2376 8da3ff18 pbrook
                                           &p->phys_offset, IO_MEM_UNASSIGNED,
2377 67c4d23c pbrook
                                           addr & TARGET_PAGE_MASK);
2378 db7b5426 blueswir1
                    subpage_register(subpage, start_addr2, end_addr2,
2379 8da3ff18 pbrook
                                     phys_offset, region_offset);
2380 8da3ff18 pbrook
                    p->region_offset = 0;
2381 db7b5426 blueswir1
                }
2382 db7b5426 blueswir1
            }
2383 db7b5426 blueswir1
        }
2384 8da3ff18 pbrook
        region_offset += TARGET_PAGE_SIZE;
2385 33417e70 bellard
    }
2386 3b46e624 ths
2387 9d42037b bellard
    /* since each CPU stores ram addresses in its TLB cache, we must
2388 9d42037b bellard
       reset the modified entries */
2389 9d42037b bellard
    /* XXX: slow ! */
2390 9d42037b bellard
    for(env = first_cpu; env != NULL; env = env->next_cpu) {
2391 9d42037b bellard
        tlb_flush(env, 1);
2392 9d42037b bellard
    }
2393 33417e70 bellard
}
2394 33417e70 bellard
2395 ba863458 bellard
/* XXX: temporary until new memory mapping API */
2396 c227f099 Anthony Liguori
ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr)
2397 ba863458 bellard
{
2398 ba863458 bellard
    PhysPageDesc *p;
2399 ba863458 bellard
2400 ba863458 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
2401 ba863458 bellard
    if (!p)
2402 ba863458 bellard
        return IO_MEM_UNASSIGNED;
2403 ba863458 bellard
    return p->phys_offset;
2404 ba863458 bellard
}
2405 ba863458 bellard
2406 c227f099 Anthony Liguori
void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
2407 f65ed4c1 aliguori
{
2408 f65ed4c1 aliguori
    if (kvm_enabled())
2409 f65ed4c1 aliguori
        kvm_coalesce_mmio_region(addr, size);
2410 f65ed4c1 aliguori
}
2411 f65ed4c1 aliguori
2412 c227f099 Anthony Liguori
void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size)
2413 f65ed4c1 aliguori
{
2414 f65ed4c1 aliguori
    if (kvm_enabled())
2415 f65ed4c1 aliguori
        kvm_uncoalesce_mmio_region(addr, size);
2416 f65ed4c1 aliguori
}
2417 f65ed4c1 aliguori
2418 c227f099 Anthony Liguori
ram_addr_t qemu_ram_alloc(ram_addr_t size)
2419 94a6b54f pbrook
{
2420 94a6b54f pbrook
    RAMBlock *new_block;
2421 94a6b54f pbrook
2422 94a6b54f pbrook
    size = TARGET_PAGE_ALIGN(size);
2423 94a6b54f pbrook
    new_block = qemu_malloc(sizeof(*new_block));
2424 94a6b54f pbrook
2425 6b02494d Alexander Graf
#if defined(TARGET_S390X) && defined(CONFIG_KVM)
2426 6b02494d Alexander Graf
    /* XXX S390 KVM requires the topmost vma of the RAM to be < 256GB */
2427 6b02494d Alexander Graf
    new_block->host = mmap((void*)0x1000000, size, PROT_EXEC|PROT_READ|PROT_WRITE,
2428 6b02494d Alexander Graf
                           MAP_SHARED | MAP_ANONYMOUS, -1, 0);
2429 6b02494d Alexander Graf
#else
2430 94a6b54f pbrook
    new_block->host = qemu_vmalloc(size);
2431 6b02494d Alexander Graf
#endif
2432 ccb167e9 Izik Eidus
#ifdef MADV_MERGEABLE
2433 ccb167e9 Izik Eidus
    madvise(new_block->host, size, MADV_MERGEABLE);
2434 ccb167e9 Izik Eidus
#endif
2435 94a6b54f pbrook
    new_block->offset = last_ram_offset;
2436 94a6b54f pbrook
    new_block->length = size;
2437 94a6b54f pbrook
2438 94a6b54f pbrook
    new_block->next = ram_blocks;
2439 94a6b54f pbrook
    ram_blocks = new_block;
2440 94a6b54f pbrook
2441 94a6b54f pbrook
    phys_ram_dirty = qemu_realloc(phys_ram_dirty,
2442 94a6b54f pbrook
        (last_ram_offset + size) >> TARGET_PAGE_BITS);
2443 94a6b54f pbrook
    memset(phys_ram_dirty + (last_ram_offset >> TARGET_PAGE_BITS),
2444 94a6b54f pbrook
           0xff, size >> TARGET_PAGE_BITS);
2445 94a6b54f pbrook
2446 94a6b54f pbrook
    last_ram_offset += size;
2447 94a6b54f pbrook
2448 6f0437e8 Jan Kiszka
    if (kvm_enabled())
2449 6f0437e8 Jan Kiszka
        kvm_setup_guest_memory(new_block->host, size);
2450 6f0437e8 Jan Kiszka
2451 94a6b54f pbrook
    return new_block->offset;
2452 94a6b54f pbrook
}
2453 e9a1ab19 bellard
2454 c227f099 Anthony Liguori
void qemu_ram_free(ram_addr_t addr)
2455 e9a1ab19 bellard
{
2456 94a6b54f pbrook
    /* TODO: implement this.  */
2457 e9a1ab19 bellard
}
2458 e9a1ab19 bellard
2459 dc828ca1 pbrook
/* Return a host pointer to ram allocated with qemu_ram_alloc.
2460 5579c7f3 pbrook
   With the exception of the softmmu code in this file, this should
2461 5579c7f3 pbrook
   only be used for local memory (e.g. video ram) that the device owns,
2462 5579c7f3 pbrook
   and knows it isn't going to access beyond the end of the block.
2463 5579c7f3 pbrook

2464 5579c7f3 pbrook
   It should not be used for general purpose DMA.
2465 5579c7f3 pbrook
   Use cpu_physical_memory_map/cpu_physical_memory_rw instead.
2466 5579c7f3 pbrook
 */
2467 c227f099 Anthony Liguori
void *qemu_get_ram_ptr(ram_addr_t addr)
2468 dc828ca1 pbrook
{
2469 94a6b54f pbrook
    RAMBlock *prev;
2470 94a6b54f pbrook
    RAMBlock **prevp;
2471 94a6b54f pbrook
    RAMBlock *block;
2472 94a6b54f pbrook
2473 94a6b54f pbrook
    prev = NULL;
2474 94a6b54f pbrook
    prevp = &ram_blocks;
2475 94a6b54f pbrook
    block = ram_blocks;
2476 94a6b54f pbrook
    while (block && (block->offset > addr
2477 94a6b54f pbrook
                     || block->offset + block->length <= addr)) {
2478 94a6b54f pbrook
        if (prev)
2479 94a6b54f pbrook
          prevp = &prev->next;
2480 94a6b54f pbrook
        prev = block;
2481 94a6b54f pbrook
        block = block->next;
2482 94a6b54f pbrook
    }
2483 94a6b54f pbrook
    if (!block) {
2484 94a6b54f pbrook
        fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
2485 94a6b54f pbrook
        abort();
2486 94a6b54f pbrook
    }
2487 94a6b54f pbrook
    /* Move this entry to to start of the list.  */
2488 94a6b54f pbrook
    if (prev) {
2489 94a6b54f pbrook
        prev->next = block->next;
2490 94a6b54f pbrook
        block->next = *prevp;
2491 94a6b54f pbrook
        *prevp = block;
2492 94a6b54f pbrook
    }
2493 94a6b54f pbrook
    return block->host + (addr - block->offset);
2494 dc828ca1 pbrook
}
2495 dc828ca1 pbrook
2496 5579c7f3 pbrook
/* Some of the softmmu routines need to translate from a host pointer
2497 5579c7f3 pbrook
   (typically a TLB entry) back to a ram offset.  */
2498 c227f099 Anthony Liguori
ram_addr_t qemu_ram_addr_from_host(void *ptr)
2499 5579c7f3 pbrook
{
2500 94a6b54f pbrook
    RAMBlock *prev;
2501 94a6b54f pbrook
    RAMBlock **prevp;
2502 94a6b54f pbrook
    RAMBlock *block;
2503 94a6b54f pbrook
    uint8_t *host = ptr;
2504 94a6b54f pbrook
2505 94a6b54f pbrook
    prev = NULL;
2506 94a6b54f pbrook
    prevp = &ram_blocks;
2507 94a6b54f pbrook
    block = ram_blocks;
2508 94a6b54f pbrook
    while (block && (block->host > host
2509 94a6b54f pbrook
                     || block->host + block->length <= host)) {
2510 94a6b54f pbrook
        if (prev)
2511 94a6b54f pbrook
          prevp = &prev->next;
2512 94a6b54f pbrook
        prev = block;
2513 94a6b54f pbrook
        block = block->next;
2514 94a6b54f pbrook
    }
2515 94a6b54f pbrook
    if (!block) {
2516 94a6b54f pbrook
        fprintf(stderr, "Bad ram pointer %p\n", ptr);
2517 94a6b54f pbrook
        abort();
2518 94a6b54f pbrook
    }
2519 94a6b54f pbrook
    return block->offset + (host - block->host);
2520 5579c7f3 pbrook
}
2521 5579c7f3 pbrook
2522 c227f099 Anthony Liguori
static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
2523 33417e70 bellard
{
2524 67d3b957 pbrook
#ifdef DEBUG_UNASSIGNED
2525 ab3d1727 blueswir1
    printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2526 67d3b957 pbrook
#endif
2527 faed1c2a Edgar E. Iglesias
#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
2528 e18231a3 blueswir1
    do_unassigned_access(addr, 0, 0, 0, 1);
2529 e18231a3 blueswir1
#endif
2530 e18231a3 blueswir1
    return 0;
2531 e18231a3 blueswir1
}
2532 e18231a3 blueswir1
2533 c227f099 Anthony Liguori
static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr)
2534 e18231a3 blueswir1
{
2535 e18231a3 blueswir1
#ifdef DEBUG_UNASSIGNED
2536 e18231a3 blueswir1
    printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2537 e18231a3 blueswir1
#endif
2538 faed1c2a Edgar E. Iglesias
#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
2539 e18231a3 blueswir1
    do_unassigned_access(addr, 0, 0, 0, 2);
2540 e18231a3 blueswir1
#endif
2541 e18231a3 blueswir1
    return 0;
2542 e18231a3 blueswir1
}
2543 e18231a3 blueswir1
2544 c227f099 Anthony Liguori
static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr)
2545 e18231a3 blueswir1
{
2546 e18231a3 blueswir1
#ifdef DEBUG_UNASSIGNED
2547 e18231a3 blueswir1
    printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
2548 e18231a3 blueswir1
#endif
2549 faed1c2a Edgar E. Iglesias
#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
2550 e18231a3 blueswir1
    do_unassigned_access(addr, 0, 0, 0, 4);
2551 b4f0a316 blueswir1
#endif
2552 33417e70 bellard
    return 0;
2553 33417e70 bellard
}
2554 33417e70 bellard
2555 c227f099 Anthony Liguori
static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
2556 33417e70 bellard
{
2557 67d3b957 pbrook
#ifdef DEBUG_UNASSIGNED
2558 ab3d1727 blueswir1
    printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2559 67d3b957 pbrook
#endif
2560 faed1c2a Edgar E. Iglesias
#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
2561 e18231a3 blueswir1
    do_unassigned_access(addr, 1, 0, 0, 1);
2562 e18231a3 blueswir1
#endif
2563 e18231a3 blueswir1
}
2564 e18231a3 blueswir1
2565 c227f099 Anthony Liguori
static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
2566 e18231a3 blueswir1
{
2567 e18231a3 blueswir1
#ifdef DEBUG_UNASSIGNED
2568 e18231a3 blueswir1
    printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2569 e18231a3 blueswir1
#endif
2570 faed1c2a Edgar E. Iglesias
#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
2571 e18231a3 blueswir1
    do_unassigned_access(addr, 1, 0, 0, 2);
2572 e18231a3 blueswir1
#endif
2573 e18231a3 blueswir1
}
2574 e18231a3 blueswir1
2575 c227f099 Anthony Liguori
static void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
2576 e18231a3 blueswir1
{
2577 e18231a3 blueswir1
#ifdef DEBUG_UNASSIGNED
2578 e18231a3 blueswir1
    printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
2579 e18231a3 blueswir1
#endif
2580 faed1c2a Edgar E. Iglesias
#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
2581 e18231a3 blueswir1
    do_unassigned_access(addr, 1, 0, 0, 4);
2582 b4f0a316 blueswir1
#endif
2583 33417e70 bellard
}
2584 33417e70 bellard
2585 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const unassigned_mem_read[3] = {
2586 33417e70 bellard
    unassigned_mem_readb,
2587 e18231a3 blueswir1
    unassigned_mem_readw,
2588 e18231a3 blueswir1
    unassigned_mem_readl,
2589 33417e70 bellard
};
2590 33417e70 bellard
2591 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const unassigned_mem_write[3] = {
2592 33417e70 bellard
    unassigned_mem_writeb,
2593 e18231a3 blueswir1
    unassigned_mem_writew,
2594 e18231a3 blueswir1
    unassigned_mem_writel,
2595 33417e70 bellard
};
2596 33417e70 bellard
2597 c227f099 Anthony Liguori
static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr,
2598 0f459d16 pbrook
                                uint32_t val)
2599 9fa3e853 bellard
{
2600 3a7d929e bellard
    int dirty_flags;
2601 3a7d929e bellard
    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2602 3a7d929e bellard
    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2603 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
2604 3a7d929e bellard
        tb_invalidate_phys_page_fast(ram_addr, 1);
2605 3a7d929e bellard
        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2606 9fa3e853 bellard
#endif
2607 3a7d929e bellard
    }
2608 5579c7f3 pbrook
    stb_p(qemu_get_ram_ptr(ram_addr), val);
2609 f23db169 bellard
    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2610 f23db169 bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2611 f23db169 bellard
    /* we remove the notdirty callback only if the code has been
2612 f23db169 bellard
       flushed */
2613 f23db169 bellard
    if (dirty_flags == 0xff)
2614 2e70f6ef pbrook
        tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2615 9fa3e853 bellard
}
2616 9fa3e853 bellard
2617 c227f099 Anthony Liguori
static void notdirty_mem_writew(void *opaque, target_phys_addr_t ram_addr,
2618 0f459d16 pbrook
                                uint32_t val)
2619 9fa3e853 bellard
{
2620 3a7d929e bellard
    int dirty_flags;
2621 3a7d929e bellard
    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2622 3a7d929e bellard
    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2623 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
2624 3a7d929e bellard
        tb_invalidate_phys_page_fast(ram_addr, 2);
2625 3a7d929e bellard
        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2626 9fa3e853 bellard
#endif
2627 3a7d929e bellard
    }
2628 5579c7f3 pbrook
    stw_p(qemu_get_ram_ptr(ram_addr), val);
2629 f23db169 bellard
    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2630 f23db169 bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2631 f23db169 bellard
    /* we remove the notdirty callback only if the code has been
2632 f23db169 bellard
       flushed */
2633 f23db169 bellard
    if (dirty_flags == 0xff)
2634 2e70f6ef pbrook
        tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2635 9fa3e853 bellard
}
2636 9fa3e853 bellard
2637 c227f099 Anthony Liguori
static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr,
2638 0f459d16 pbrook
                                uint32_t val)
2639 9fa3e853 bellard
{
2640 3a7d929e bellard
    int dirty_flags;
2641 3a7d929e bellard
    dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2642 3a7d929e bellard
    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
2643 9fa3e853 bellard
#if !defined(CONFIG_USER_ONLY)
2644 3a7d929e bellard
        tb_invalidate_phys_page_fast(ram_addr, 4);
2645 3a7d929e bellard
        dirty_flags = phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS];
2646 9fa3e853 bellard
#endif
2647 3a7d929e bellard
    }
2648 5579c7f3 pbrook
    stl_p(qemu_get_ram_ptr(ram_addr), val);
2649 f23db169 bellard
    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
2650 f23db169 bellard
    phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
2651 f23db169 bellard
    /* we remove the notdirty callback only if the code has been
2652 f23db169 bellard
       flushed */
2653 f23db169 bellard
    if (dirty_flags == 0xff)
2654 2e70f6ef pbrook
        tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr);
2655 9fa3e853 bellard
}
2656 9fa3e853 bellard
2657 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const error_mem_read[3] = {
2658 9fa3e853 bellard
    NULL, /* never used */
2659 9fa3e853 bellard
    NULL, /* never used */
2660 9fa3e853 bellard
    NULL, /* never used */
2661 9fa3e853 bellard
};
2662 9fa3e853 bellard
2663 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const notdirty_mem_write[3] = {
2664 1ccde1cb bellard
    notdirty_mem_writeb,
2665 1ccde1cb bellard
    notdirty_mem_writew,
2666 1ccde1cb bellard
    notdirty_mem_writel,
2667 1ccde1cb bellard
};
2668 1ccde1cb bellard
2669 0f459d16 pbrook
/* Generate a debug exception if a watchpoint has been hit.  */
2670 b4051334 aliguori
static void check_watchpoint(int offset, int len_mask, int flags)
2671 0f459d16 pbrook
{
2672 0f459d16 pbrook
    CPUState *env = cpu_single_env;
2673 06d55cc1 aliguori
    target_ulong pc, cs_base;
2674 06d55cc1 aliguori
    TranslationBlock *tb;
2675 0f459d16 pbrook
    target_ulong vaddr;
2676 a1d1bb31 aliguori
    CPUWatchpoint *wp;
2677 06d55cc1 aliguori
    int cpu_flags;
2678 0f459d16 pbrook
2679 06d55cc1 aliguori
    if (env->watchpoint_hit) {
2680 06d55cc1 aliguori
        /* We re-entered the check after replacing the TB. Now raise
2681 06d55cc1 aliguori
         * the debug interrupt so that is will trigger after the
2682 06d55cc1 aliguori
         * current instruction. */
2683 06d55cc1 aliguori
        cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2684 06d55cc1 aliguori
        return;
2685 06d55cc1 aliguori
    }
2686 2e70f6ef pbrook
    vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
2687 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
2688 b4051334 aliguori
        if ((vaddr == (wp->vaddr & len_mask) ||
2689 b4051334 aliguori
             (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
2690 6e140f28 aliguori
            wp->flags |= BP_WATCHPOINT_HIT;
2691 6e140f28 aliguori
            if (!env->watchpoint_hit) {
2692 6e140f28 aliguori
                env->watchpoint_hit = wp;
2693 6e140f28 aliguori
                tb = tb_find_pc(env->mem_io_pc);
2694 6e140f28 aliguori
                if (!tb) {
2695 6e140f28 aliguori
                    cpu_abort(env, "check_watchpoint: could not find TB for "
2696 6e140f28 aliguori
                              "pc=%p", (void *)env->mem_io_pc);
2697 6e140f28 aliguori
                }
2698 6e140f28 aliguori
                cpu_restore_state(tb, env, env->mem_io_pc, NULL);
2699 6e140f28 aliguori
                tb_phys_invalidate(tb, -1);
2700 6e140f28 aliguori
                if (wp->flags & BP_STOP_BEFORE_ACCESS) {
2701 6e140f28 aliguori
                    env->exception_index = EXCP_DEBUG;
2702 6e140f28 aliguori
                } else {
2703 6e140f28 aliguori
                    cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
2704 6e140f28 aliguori
                    tb_gen_code(env, pc, cs_base, cpu_flags, 1);
2705 6e140f28 aliguori
                }
2706 6e140f28 aliguori
                cpu_resume_from_signal(env, NULL);
2707 06d55cc1 aliguori
            }
2708 6e140f28 aliguori
        } else {
2709 6e140f28 aliguori
            wp->flags &= ~BP_WATCHPOINT_HIT;
2710 0f459d16 pbrook
        }
2711 0f459d16 pbrook
    }
2712 0f459d16 pbrook
}
2713 0f459d16 pbrook
2714 6658ffb8 pbrook
/* Watchpoint access routines.  Watchpoints are inserted using TLB tricks,
2715 6658ffb8 pbrook
   so these check for a hit then pass through to the normal out-of-line
2716 6658ffb8 pbrook
   phys routines.  */
2717 c227f099 Anthony Liguori
static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
2718 6658ffb8 pbrook
{
2719 b4051334 aliguori
    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_READ);
2720 6658ffb8 pbrook
    return ldub_phys(addr);
2721 6658ffb8 pbrook
}
2722 6658ffb8 pbrook
2723 c227f099 Anthony Liguori
static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
2724 6658ffb8 pbrook
{
2725 b4051334 aliguori
    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_READ);
2726 6658ffb8 pbrook
    return lduw_phys(addr);
2727 6658ffb8 pbrook
}
2728 6658ffb8 pbrook
2729 c227f099 Anthony Liguori
static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
2730 6658ffb8 pbrook
{
2731 b4051334 aliguori
    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_READ);
2732 6658ffb8 pbrook
    return ldl_phys(addr);
2733 6658ffb8 pbrook
}
2734 6658ffb8 pbrook
2735 c227f099 Anthony Liguori
static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
2736 6658ffb8 pbrook
                             uint32_t val)
2737 6658ffb8 pbrook
{
2738 b4051334 aliguori
    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x0, BP_MEM_WRITE);
2739 6658ffb8 pbrook
    stb_phys(addr, val);
2740 6658ffb8 pbrook
}
2741 6658ffb8 pbrook
2742 c227f099 Anthony Liguori
static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
2743 6658ffb8 pbrook
                             uint32_t val)
2744 6658ffb8 pbrook
{
2745 b4051334 aliguori
    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x1, BP_MEM_WRITE);
2746 6658ffb8 pbrook
    stw_phys(addr, val);
2747 6658ffb8 pbrook
}
2748 6658ffb8 pbrook
2749 c227f099 Anthony Liguori
static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
2750 6658ffb8 pbrook
                             uint32_t val)
2751 6658ffb8 pbrook
{
2752 b4051334 aliguori
    check_watchpoint(addr & ~TARGET_PAGE_MASK, ~0x3, BP_MEM_WRITE);
2753 6658ffb8 pbrook
    stl_phys(addr, val);
2754 6658ffb8 pbrook
}
2755 6658ffb8 pbrook
2756 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const watch_mem_read[3] = {
2757 6658ffb8 pbrook
    watch_mem_readb,
2758 6658ffb8 pbrook
    watch_mem_readw,
2759 6658ffb8 pbrook
    watch_mem_readl,
2760 6658ffb8 pbrook
};
2761 6658ffb8 pbrook
2762 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const watch_mem_write[3] = {
2763 6658ffb8 pbrook
    watch_mem_writeb,
2764 6658ffb8 pbrook
    watch_mem_writew,
2765 6658ffb8 pbrook
    watch_mem_writel,
2766 6658ffb8 pbrook
};
2767 6658ffb8 pbrook
2768 c227f099 Anthony Liguori
static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr,
2769 db7b5426 blueswir1
                                 unsigned int len)
2770 db7b5426 blueswir1
{
2771 db7b5426 blueswir1
    uint32_t ret;
2772 db7b5426 blueswir1
    unsigned int idx;
2773 db7b5426 blueswir1
2774 8da3ff18 pbrook
    idx = SUBPAGE_IDX(addr);
2775 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2776 db7b5426 blueswir1
    printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
2777 db7b5426 blueswir1
           mmio, len, addr, idx);
2778 db7b5426 blueswir1
#endif
2779 8da3ff18 pbrook
    ret = (**mmio->mem_read[idx][len])(mmio->opaque[idx][0][len],
2780 8da3ff18 pbrook
                                       addr + mmio->region_offset[idx][0][len]);
2781 db7b5426 blueswir1
2782 db7b5426 blueswir1
    return ret;
2783 db7b5426 blueswir1
}
2784 db7b5426 blueswir1
2785 c227f099 Anthony Liguori
static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
2786 db7b5426 blueswir1
                              uint32_t value, unsigned int len)
2787 db7b5426 blueswir1
{
2788 db7b5426 blueswir1
    unsigned int idx;
2789 db7b5426 blueswir1
2790 8da3ff18 pbrook
    idx = SUBPAGE_IDX(addr);
2791 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2792 db7b5426 blueswir1
    printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
2793 db7b5426 blueswir1
           mmio, len, addr, idx, value);
2794 db7b5426 blueswir1
#endif
2795 8da3ff18 pbrook
    (**mmio->mem_write[idx][len])(mmio->opaque[idx][1][len],
2796 8da3ff18 pbrook
                                  addr + mmio->region_offset[idx][1][len],
2797 8da3ff18 pbrook
                                  value);
2798 db7b5426 blueswir1
}
2799 db7b5426 blueswir1
2800 c227f099 Anthony Liguori
static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
2801 db7b5426 blueswir1
{
2802 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2803 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2804 db7b5426 blueswir1
#endif
2805 db7b5426 blueswir1
2806 db7b5426 blueswir1
    return subpage_readlen(opaque, addr, 0);
2807 db7b5426 blueswir1
}
2808 db7b5426 blueswir1
2809 c227f099 Anthony Liguori
static void subpage_writeb (void *opaque, target_phys_addr_t addr,
2810 db7b5426 blueswir1
                            uint32_t value)
2811 db7b5426 blueswir1
{
2812 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2813 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2814 db7b5426 blueswir1
#endif
2815 db7b5426 blueswir1
    subpage_writelen(opaque, addr, value, 0);
2816 db7b5426 blueswir1
}
2817 db7b5426 blueswir1
2818 c227f099 Anthony Liguori
static uint32_t subpage_readw (void *opaque, target_phys_addr_t addr)
2819 db7b5426 blueswir1
{
2820 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2821 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2822 db7b5426 blueswir1
#endif
2823 db7b5426 blueswir1
2824 db7b5426 blueswir1
    return subpage_readlen(opaque, addr, 1);
2825 db7b5426 blueswir1
}
2826 db7b5426 blueswir1
2827 c227f099 Anthony Liguori
static void subpage_writew (void *opaque, target_phys_addr_t addr,
2828 db7b5426 blueswir1
                            uint32_t value)
2829 db7b5426 blueswir1
{
2830 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2831 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2832 db7b5426 blueswir1
#endif
2833 db7b5426 blueswir1
    subpage_writelen(opaque, addr, value, 1);
2834 db7b5426 blueswir1
}
2835 db7b5426 blueswir1
2836 c227f099 Anthony Liguori
static uint32_t subpage_readl (void *opaque, target_phys_addr_t addr)
2837 db7b5426 blueswir1
{
2838 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2839 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
2840 db7b5426 blueswir1
#endif
2841 db7b5426 blueswir1
2842 db7b5426 blueswir1
    return subpage_readlen(opaque, addr, 2);
2843 db7b5426 blueswir1
}
2844 db7b5426 blueswir1
2845 db7b5426 blueswir1
static void subpage_writel (void *opaque,
2846 c227f099 Anthony Liguori
                         target_phys_addr_t addr, uint32_t value)
2847 db7b5426 blueswir1
{
2848 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2849 db7b5426 blueswir1
    printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
2850 db7b5426 blueswir1
#endif
2851 db7b5426 blueswir1
    subpage_writelen(opaque, addr, value, 2);
2852 db7b5426 blueswir1
}
2853 db7b5426 blueswir1
2854 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const subpage_read[] = {
2855 db7b5426 blueswir1
    &subpage_readb,
2856 db7b5426 blueswir1
    &subpage_readw,
2857 db7b5426 blueswir1
    &subpage_readl,
2858 db7b5426 blueswir1
};
2859 db7b5426 blueswir1
2860 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const subpage_write[] = {
2861 db7b5426 blueswir1
    &subpage_writeb,
2862 db7b5426 blueswir1
    &subpage_writew,
2863 db7b5426 blueswir1
    &subpage_writel,
2864 db7b5426 blueswir1
};
2865 db7b5426 blueswir1
2866 c227f099 Anthony Liguori
static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
2867 c227f099 Anthony Liguori
                             ram_addr_t memory, ram_addr_t region_offset)
2868 db7b5426 blueswir1
{
2869 db7b5426 blueswir1
    int idx, eidx;
2870 4254fab8 blueswir1
    unsigned int i;
2871 db7b5426 blueswir1
2872 db7b5426 blueswir1
    if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
2873 db7b5426 blueswir1
        return -1;
2874 db7b5426 blueswir1
    idx = SUBPAGE_IDX(start);
2875 db7b5426 blueswir1
    eidx = SUBPAGE_IDX(end);
2876 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2877 0bf9e31a Blue Swirl
    printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__,
2878 db7b5426 blueswir1
           mmio, start, end, idx, eidx, memory);
2879 db7b5426 blueswir1
#endif
2880 db7b5426 blueswir1
    memory >>= IO_MEM_SHIFT;
2881 db7b5426 blueswir1
    for (; idx <= eidx; idx++) {
2882 4254fab8 blueswir1
        for (i = 0; i < 4; i++) {
2883 3ee89922 blueswir1
            if (io_mem_read[memory][i]) {
2884 3ee89922 blueswir1
                mmio->mem_read[idx][i] = &io_mem_read[memory][i];
2885 3ee89922 blueswir1
                mmio->opaque[idx][0][i] = io_mem_opaque[memory];
2886 8da3ff18 pbrook
                mmio->region_offset[idx][0][i] = region_offset;
2887 3ee89922 blueswir1
            }
2888 3ee89922 blueswir1
            if (io_mem_write[memory][i]) {
2889 3ee89922 blueswir1
                mmio->mem_write[idx][i] = &io_mem_write[memory][i];
2890 3ee89922 blueswir1
                mmio->opaque[idx][1][i] = io_mem_opaque[memory];
2891 8da3ff18 pbrook
                mmio->region_offset[idx][1][i] = region_offset;
2892 3ee89922 blueswir1
            }
2893 4254fab8 blueswir1
        }
2894 db7b5426 blueswir1
    }
2895 db7b5426 blueswir1
2896 db7b5426 blueswir1
    return 0;
2897 db7b5426 blueswir1
}
2898 db7b5426 blueswir1
2899 c227f099 Anthony Liguori
static void *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
2900 c227f099 Anthony Liguori
                           ram_addr_t orig_memory, ram_addr_t region_offset)
2901 db7b5426 blueswir1
{
2902 c227f099 Anthony Liguori
    subpage_t *mmio;
2903 db7b5426 blueswir1
    int subpage_memory;
2904 db7b5426 blueswir1
2905 c227f099 Anthony Liguori
    mmio = qemu_mallocz(sizeof(subpage_t));
2906 1eec614b aliguori
2907 1eec614b aliguori
    mmio->base = base;
2908 1eed09cb Avi Kivity
    subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
2909 db7b5426 blueswir1
#if defined(DEBUG_SUBPAGE)
2910 1eec614b aliguori
    printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
2911 1eec614b aliguori
           mmio, base, TARGET_PAGE_SIZE, subpage_memory);
2912 db7b5426 blueswir1
#endif
2913 1eec614b aliguori
    *phys = subpage_memory | IO_MEM_SUBPAGE;
2914 1eec614b aliguori
    subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory,
2915 8da3ff18 pbrook
                         region_offset);
2916 db7b5426 blueswir1
2917 db7b5426 blueswir1
    return mmio;
2918 db7b5426 blueswir1
}
2919 db7b5426 blueswir1
2920 88715657 aliguori
static int get_free_io_mem_idx(void)
2921 88715657 aliguori
{
2922 88715657 aliguori
    int i;
2923 88715657 aliguori
2924 88715657 aliguori
    for (i = 0; i<IO_MEM_NB_ENTRIES; i++)
2925 88715657 aliguori
        if (!io_mem_used[i]) {
2926 88715657 aliguori
            io_mem_used[i] = 1;
2927 88715657 aliguori
            return i;
2928 88715657 aliguori
        }
2929 c6703b47 Riku Voipio
    fprintf(stderr, "RAN out out io_mem_idx, max %d !\n", IO_MEM_NB_ENTRIES);
2930 88715657 aliguori
    return -1;
2931 88715657 aliguori
}
2932 88715657 aliguori
2933 33417e70 bellard
/* mem_read and mem_write are arrays of functions containing the
2934 33417e70 bellard
   function to access byte (index 0), word (index 1) and dword (index
2935 0b4e6e3e Paul Brook
   2). Functions can be omitted with a NULL function pointer.
2936 3ee89922 blueswir1
   If io_index is non zero, the corresponding io zone is
2937 4254fab8 blueswir1
   modified. If it is zero, a new io zone is allocated. The return
2938 4254fab8 blueswir1
   value can be used with cpu_register_physical_memory(). (-1) is
2939 4254fab8 blueswir1
   returned if error. */
2940 1eed09cb Avi Kivity
static int cpu_register_io_memory_fixed(int io_index,
2941 d60efc6b Blue Swirl
                                        CPUReadMemoryFunc * const *mem_read,
2942 d60efc6b Blue Swirl
                                        CPUWriteMemoryFunc * const *mem_write,
2943 1eed09cb Avi Kivity
                                        void *opaque)
2944 33417e70 bellard
{
2945 4254fab8 blueswir1
    int i, subwidth = 0;
2946 33417e70 bellard
2947 33417e70 bellard
    if (io_index <= 0) {
2948 88715657 aliguori
        io_index = get_free_io_mem_idx();
2949 88715657 aliguori
        if (io_index == -1)
2950 88715657 aliguori
            return io_index;
2951 33417e70 bellard
    } else {
2952 1eed09cb Avi Kivity
        io_index >>= IO_MEM_SHIFT;
2953 33417e70 bellard
        if (io_index >= IO_MEM_NB_ENTRIES)
2954 33417e70 bellard
            return -1;
2955 33417e70 bellard
    }
2956 b5ff1b31 bellard
2957 33417e70 bellard
    for(i = 0;i < 3; i++) {
2958 4254fab8 blueswir1
        if (!mem_read[i] || !mem_write[i])
2959 4254fab8 blueswir1
            subwidth = IO_MEM_SUBWIDTH;
2960 33417e70 bellard
        io_mem_read[io_index][i] = mem_read[i];
2961 33417e70 bellard
        io_mem_write[io_index][i] = mem_write[i];
2962 33417e70 bellard
    }
2963 a4193c8a bellard
    io_mem_opaque[io_index] = opaque;
2964 4254fab8 blueswir1
    return (io_index << IO_MEM_SHIFT) | subwidth;
2965 33417e70 bellard
}
2966 61382a50 bellard
2967 d60efc6b Blue Swirl
int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
2968 d60efc6b Blue Swirl
                           CPUWriteMemoryFunc * const *mem_write,
2969 1eed09cb Avi Kivity
                           void *opaque)
2970 1eed09cb Avi Kivity
{
2971 1eed09cb Avi Kivity
    return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
2972 1eed09cb Avi Kivity
}
2973 1eed09cb Avi Kivity
2974 88715657 aliguori
void cpu_unregister_io_memory(int io_table_address)
2975 88715657 aliguori
{
2976 88715657 aliguori
    int i;
2977 88715657 aliguori
    int io_index = io_table_address >> IO_MEM_SHIFT;
2978 88715657 aliguori
2979 88715657 aliguori
    for (i=0;i < 3; i++) {
2980 88715657 aliguori
        io_mem_read[io_index][i] = unassigned_mem_read[i];
2981 88715657 aliguori
        io_mem_write[io_index][i] = unassigned_mem_write[i];
2982 88715657 aliguori
    }
2983 88715657 aliguori
    io_mem_opaque[io_index] = NULL;
2984 88715657 aliguori
    io_mem_used[io_index] = 0;
2985 88715657 aliguori
}
2986 88715657 aliguori
2987 e9179ce1 Avi Kivity
static void io_mem_init(void)
2988 e9179ce1 Avi Kivity
{
2989 e9179ce1 Avi Kivity
    int i;
2990 e9179ce1 Avi Kivity
2991 e9179ce1 Avi Kivity
    cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read, unassigned_mem_write, NULL);
2992 e9179ce1 Avi Kivity
    cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read, unassigned_mem_write, NULL);
2993 e9179ce1 Avi Kivity
    cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read, notdirty_mem_write, NULL);
2994 e9179ce1 Avi Kivity
    for (i=0; i<5; i++)
2995 e9179ce1 Avi Kivity
        io_mem_used[i] = 1;
2996 e9179ce1 Avi Kivity
2997 e9179ce1 Avi Kivity
    io_mem_watch = cpu_register_io_memory(watch_mem_read,
2998 e9179ce1 Avi Kivity
                                          watch_mem_write, NULL);
2999 e9179ce1 Avi Kivity
}
3000 e9179ce1 Avi Kivity
3001 e2eef170 pbrook
#endif /* !defined(CONFIG_USER_ONLY) */
3002 e2eef170 pbrook
3003 13eb76e0 bellard
/* physical memory access (slow version, mainly for debug) */
3004 13eb76e0 bellard
#if defined(CONFIG_USER_ONLY)
3005 c227f099 Anthony Liguori
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
3006 13eb76e0 bellard
                            int len, int is_write)
3007 13eb76e0 bellard
{
3008 13eb76e0 bellard
    int l, flags;
3009 13eb76e0 bellard
    target_ulong page;
3010 53a5960a pbrook
    void * p;
3011 13eb76e0 bellard
3012 13eb76e0 bellard
    while (len > 0) {
3013 13eb76e0 bellard
        page = addr & TARGET_PAGE_MASK;
3014 13eb76e0 bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
3015 13eb76e0 bellard
        if (l > len)
3016 13eb76e0 bellard
            l = len;
3017 13eb76e0 bellard
        flags = page_get_flags(page);
3018 13eb76e0 bellard
        if (!(flags & PAGE_VALID))
3019 13eb76e0 bellard
            return;
3020 13eb76e0 bellard
        if (is_write) {
3021 13eb76e0 bellard
            if (!(flags & PAGE_WRITE))
3022 13eb76e0 bellard
                return;
3023 579a97f7 bellard
            /* XXX: this code should not depend on lock_user */
3024 72fb7daa aurel32
            if (!(p = lock_user(VERIFY_WRITE, addr, l, 0)))
3025 579a97f7 bellard
                /* FIXME - should this return an error rather than just fail? */
3026 579a97f7 bellard
                return;
3027 72fb7daa aurel32
            memcpy(p, buf, l);
3028 72fb7daa aurel32
            unlock_user(p, addr, l);
3029 13eb76e0 bellard
        } else {
3030 13eb76e0 bellard
            if (!(flags & PAGE_READ))
3031 13eb76e0 bellard
                return;
3032 579a97f7 bellard
            /* XXX: this code should not depend on lock_user */
3033 72fb7daa aurel32
            if (!(p = lock_user(VERIFY_READ, addr, l, 1)))
3034 579a97f7 bellard
                /* FIXME - should this return an error rather than just fail? */
3035 579a97f7 bellard
                return;
3036 72fb7daa aurel32
            memcpy(buf, p, l);
3037 5b257578 aurel32
            unlock_user(p, addr, 0);
3038 13eb76e0 bellard
        }
3039 13eb76e0 bellard
        len -= l;
3040 13eb76e0 bellard
        buf += l;
3041 13eb76e0 bellard
        addr += l;
3042 13eb76e0 bellard
    }
3043 13eb76e0 bellard
}
3044 8df1cd07 bellard
3045 13eb76e0 bellard
#else
3046 c227f099 Anthony Liguori
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
3047 13eb76e0 bellard
                            int len, int is_write)
3048 13eb76e0 bellard
{
3049 13eb76e0 bellard
    int l, io_index;
3050 13eb76e0 bellard
    uint8_t *ptr;
3051 13eb76e0 bellard
    uint32_t val;
3052 c227f099 Anthony Liguori
    target_phys_addr_t page;
3053 2e12669a bellard
    unsigned long pd;
3054 92e873b9 bellard
    PhysPageDesc *p;
3055 3b46e624 ths
3056 13eb76e0 bellard
    while (len > 0) {
3057 13eb76e0 bellard
        page = addr & TARGET_PAGE_MASK;
3058 13eb76e0 bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
3059 13eb76e0 bellard
        if (l > len)
3060 13eb76e0 bellard
            l = len;
3061 92e873b9 bellard
        p = phys_page_find(page >> TARGET_PAGE_BITS);
3062 13eb76e0 bellard
        if (!p) {
3063 13eb76e0 bellard
            pd = IO_MEM_UNASSIGNED;
3064 13eb76e0 bellard
        } else {
3065 13eb76e0 bellard
            pd = p->phys_offset;
3066 13eb76e0 bellard
        }
3067 3b46e624 ths
3068 13eb76e0 bellard
        if (is_write) {
3069 3a7d929e bellard
            if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3070 c227f099 Anthony Liguori
                target_phys_addr_t addr1 = addr;
3071 13eb76e0 bellard
                io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
3072 8da3ff18 pbrook
                if (p)
3073 6c2934db aurel32
                    addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3074 6a00d601 bellard
                /* XXX: could force cpu_single_env to NULL to avoid
3075 6a00d601 bellard
                   potential bugs */
3076 6c2934db aurel32
                if (l >= 4 && ((addr1 & 3) == 0)) {
3077 1c213d19 bellard
                    /* 32 bit write access */
3078 c27004ec bellard
                    val = ldl_p(buf);
3079 6c2934db aurel32
                    io_mem_write[io_index][2](io_mem_opaque[io_index], addr1, val);
3080 13eb76e0 bellard
                    l = 4;
3081 6c2934db aurel32
                } else if (l >= 2 && ((addr1 & 1) == 0)) {
3082 1c213d19 bellard
                    /* 16 bit write access */
3083 c27004ec bellard
                    val = lduw_p(buf);
3084 6c2934db aurel32
                    io_mem_write[io_index][1](io_mem_opaque[io_index], addr1, val);
3085 13eb76e0 bellard
                    l = 2;
3086 13eb76e0 bellard
                } else {
3087 1c213d19 bellard
                    /* 8 bit write access */
3088 c27004ec bellard
                    val = ldub_p(buf);
3089 6c2934db aurel32
                    io_mem_write[io_index][0](io_mem_opaque[io_index], addr1, val);
3090 13eb76e0 bellard
                    l = 1;
3091 13eb76e0 bellard
                }
3092 13eb76e0 bellard
            } else {
3093 b448f2f3 bellard
                unsigned long addr1;
3094 b448f2f3 bellard
                addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3095 13eb76e0 bellard
                /* RAM case */
3096 5579c7f3 pbrook
                ptr = qemu_get_ram_ptr(addr1);
3097 13eb76e0 bellard
                memcpy(ptr, buf, l);
3098 3a7d929e bellard
                if (!cpu_physical_memory_is_dirty(addr1)) {
3099 3a7d929e bellard
                    /* invalidate code */
3100 3a7d929e bellard
                    tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
3101 3a7d929e bellard
                    /* set dirty bit */
3102 5fafdf24 ths
                    phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3103 f23db169 bellard
                        (0xff & ~CODE_DIRTY_FLAG);
3104 3a7d929e bellard
                }
3105 13eb76e0 bellard
            }
3106 13eb76e0 bellard
        } else {
3107 5fafdf24 ths
            if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3108 2a4188a3 bellard
                !(pd & IO_MEM_ROMD)) {
3109 c227f099 Anthony Liguori
                target_phys_addr_t addr1 = addr;
3110 13eb76e0 bellard
                /* I/O case */
3111 13eb76e0 bellard
                io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
3112 8da3ff18 pbrook
                if (p)
3113 6c2934db aurel32
                    addr1 = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3114 6c2934db aurel32
                if (l >= 4 && ((addr1 & 3) == 0)) {
3115 13eb76e0 bellard
                    /* 32 bit read access */
3116 6c2934db aurel32
                    val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr1);
3117 c27004ec bellard
                    stl_p(buf, val);
3118 13eb76e0 bellard
                    l = 4;
3119 6c2934db aurel32
                } else if (l >= 2 && ((addr1 & 1) == 0)) {
3120 13eb76e0 bellard
                    /* 16 bit read access */
3121 6c2934db aurel32
                    val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr1);
3122 c27004ec bellard
                    stw_p(buf, val);
3123 13eb76e0 bellard
                    l = 2;
3124 13eb76e0 bellard
                } else {
3125 1c213d19 bellard
                    /* 8 bit read access */
3126 6c2934db aurel32
                    val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr1);
3127 c27004ec bellard
                    stb_p(buf, val);
3128 13eb76e0 bellard
                    l = 1;
3129 13eb76e0 bellard
                }
3130 13eb76e0 bellard
            } else {
3131 13eb76e0 bellard
                /* RAM case */
3132 5579c7f3 pbrook
                ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
3133 13eb76e0 bellard
                    (addr & ~TARGET_PAGE_MASK);
3134 13eb76e0 bellard
                memcpy(buf, ptr, l);
3135 13eb76e0 bellard
            }
3136 13eb76e0 bellard
        }
3137 13eb76e0 bellard
        len -= l;
3138 13eb76e0 bellard
        buf += l;
3139 13eb76e0 bellard
        addr += l;
3140 13eb76e0 bellard
    }
3141 13eb76e0 bellard
}
3142 8df1cd07 bellard
3143 d0ecd2aa bellard
/* used for ROM loading : can write in RAM and ROM */
3144 c227f099 Anthony Liguori
void cpu_physical_memory_write_rom(target_phys_addr_t addr,
3145 d0ecd2aa bellard
                                   const uint8_t *buf, int len)
3146 d0ecd2aa bellard
{
3147 d0ecd2aa bellard
    int l;
3148 d0ecd2aa bellard
    uint8_t *ptr;
3149 c227f099 Anthony Liguori
    target_phys_addr_t page;
3150 d0ecd2aa bellard
    unsigned long pd;
3151 d0ecd2aa bellard
    PhysPageDesc *p;
3152 3b46e624 ths
3153 d0ecd2aa bellard
    while (len > 0) {
3154 d0ecd2aa bellard
        page = addr & TARGET_PAGE_MASK;
3155 d0ecd2aa bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
3156 d0ecd2aa bellard
        if (l > len)
3157 d0ecd2aa bellard
            l = len;
3158 d0ecd2aa bellard
        p = phys_page_find(page >> TARGET_PAGE_BITS);
3159 d0ecd2aa bellard
        if (!p) {
3160 d0ecd2aa bellard
            pd = IO_MEM_UNASSIGNED;
3161 d0ecd2aa bellard
        } else {
3162 d0ecd2aa bellard
            pd = p->phys_offset;
3163 d0ecd2aa bellard
        }
3164 3b46e624 ths
3165 d0ecd2aa bellard
        if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
3166 2a4188a3 bellard
            (pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
3167 2a4188a3 bellard
            !(pd & IO_MEM_ROMD)) {
3168 d0ecd2aa bellard
            /* do nothing */
3169 d0ecd2aa bellard
        } else {
3170 d0ecd2aa bellard
            unsigned long addr1;
3171 d0ecd2aa bellard
            addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3172 d0ecd2aa bellard
            /* ROM/RAM case */
3173 5579c7f3 pbrook
            ptr = qemu_get_ram_ptr(addr1);
3174 d0ecd2aa bellard
            memcpy(ptr, buf, l);
3175 d0ecd2aa bellard
        }
3176 d0ecd2aa bellard
        len -= l;
3177 d0ecd2aa bellard
        buf += l;
3178 d0ecd2aa bellard
        addr += l;
3179 d0ecd2aa bellard
    }
3180 d0ecd2aa bellard
}
3181 d0ecd2aa bellard
3182 6d16c2f8 aliguori
typedef struct {
3183 6d16c2f8 aliguori
    void *buffer;
3184 c227f099 Anthony Liguori
    target_phys_addr_t addr;
3185 c227f099 Anthony Liguori
    target_phys_addr_t len;
3186 6d16c2f8 aliguori
} BounceBuffer;
3187 6d16c2f8 aliguori
3188 6d16c2f8 aliguori
static BounceBuffer bounce;
3189 6d16c2f8 aliguori
3190 ba223c29 aliguori
typedef struct MapClient {
3191 ba223c29 aliguori
    void *opaque;
3192 ba223c29 aliguori
    void (*callback)(void *opaque);
3193 72cf2d4f Blue Swirl
    QLIST_ENTRY(MapClient) link;
3194 ba223c29 aliguori
} MapClient;
3195 ba223c29 aliguori
3196 72cf2d4f Blue Swirl
static QLIST_HEAD(map_client_list, MapClient) map_client_list
3197 72cf2d4f Blue Swirl
    = QLIST_HEAD_INITIALIZER(map_client_list);
3198 ba223c29 aliguori
3199 ba223c29 aliguori
void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque))
3200 ba223c29 aliguori
{
3201 ba223c29 aliguori
    MapClient *client = qemu_malloc(sizeof(*client));
3202 ba223c29 aliguori
3203 ba223c29 aliguori
    client->opaque = opaque;
3204 ba223c29 aliguori
    client->callback = callback;
3205 72cf2d4f Blue Swirl
    QLIST_INSERT_HEAD(&map_client_list, client, link);
3206 ba223c29 aliguori
    return client;
3207 ba223c29 aliguori
}
3208 ba223c29 aliguori
3209 ba223c29 aliguori
void cpu_unregister_map_client(void *_client)
3210 ba223c29 aliguori
{
3211 ba223c29 aliguori
    MapClient *client = (MapClient *)_client;
3212 ba223c29 aliguori
3213 72cf2d4f Blue Swirl
    QLIST_REMOVE(client, link);
3214 34d5e948 Isaku Yamahata
    qemu_free(client);
3215 ba223c29 aliguori
}
3216 ba223c29 aliguori
3217 ba223c29 aliguori
static void cpu_notify_map_clients(void)
3218 ba223c29 aliguori
{
3219 ba223c29 aliguori
    MapClient *client;
3220 ba223c29 aliguori
3221 72cf2d4f Blue Swirl
    while (!QLIST_EMPTY(&map_client_list)) {
3222 72cf2d4f Blue Swirl
        client = QLIST_FIRST(&map_client_list);
3223 ba223c29 aliguori
        client->callback(client->opaque);
3224 34d5e948 Isaku Yamahata
        cpu_unregister_map_client(client);
3225 ba223c29 aliguori
    }
3226 ba223c29 aliguori
}
3227 ba223c29 aliguori
3228 6d16c2f8 aliguori
/* Map a physical memory region into a host virtual address.
3229 6d16c2f8 aliguori
 * May map a subset of the requested range, given by and returned in *plen.
3230 6d16c2f8 aliguori
 * May return NULL if resources needed to perform the mapping are exhausted.
3231 6d16c2f8 aliguori
 * Use only for reads OR writes - not for read-modify-write operations.
3232 ba223c29 aliguori
 * Use cpu_register_map_client() to know when retrying the map operation is
3233 ba223c29 aliguori
 * likely to succeed.
3234 6d16c2f8 aliguori
 */
3235 c227f099 Anthony Liguori
void *cpu_physical_memory_map(target_phys_addr_t addr,
3236 c227f099 Anthony Liguori
                              target_phys_addr_t *plen,
3237 6d16c2f8 aliguori
                              int is_write)
3238 6d16c2f8 aliguori
{
3239 c227f099 Anthony Liguori
    target_phys_addr_t len = *plen;
3240 c227f099 Anthony Liguori
    target_phys_addr_t done = 0;
3241 6d16c2f8 aliguori
    int l;
3242 6d16c2f8 aliguori
    uint8_t *ret = NULL;
3243 6d16c2f8 aliguori
    uint8_t *ptr;
3244 c227f099 Anthony Liguori
    target_phys_addr_t page;
3245 6d16c2f8 aliguori
    unsigned long pd;
3246 6d16c2f8 aliguori
    PhysPageDesc *p;
3247 6d16c2f8 aliguori
    unsigned long addr1;
3248 6d16c2f8 aliguori
3249 6d16c2f8 aliguori
    while (len > 0) {
3250 6d16c2f8 aliguori
        page = addr & TARGET_PAGE_MASK;
3251 6d16c2f8 aliguori
        l = (page + TARGET_PAGE_SIZE) - addr;
3252 6d16c2f8 aliguori
        if (l > len)
3253 6d16c2f8 aliguori
            l = len;
3254 6d16c2f8 aliguori
        p = phys_page_find(page >> TARGET_PAGE_BITS);
3255 6d16c2f8 aliguori
        if (!p) {
3256 6d16c2f8 aliguori
            pd = IO_MEM_UNASSIGNED;
3257 6d16c2f8 aliguori
        } else {
3258 6d16c2f8 aliguori
            pd = p->phys_offset;
3259 6d16c2f8 aliguori
        }
3260 6d16c2f8 aliguori
3261 6d16c2f8 aliguori
        if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3262 6d16c2f8 aliguori
            if (done || bounce.buffer) {
3263 6d16c2f8 aliguori
                break;
3264 6d16c2f8 aliguori
            }
3265 6d16c2f8 aliguori
            bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);
3266 6d16c2f8 aliguori
            bounce.addr = addr;
3267 6d16c2f8 aliguori
            bounce.len = l;
3268 6d16c2f8 aliguori
            if (!is_write) {
3269 6d16c2f8 aliguori
                cpu_physical_memory_rw(addr, bounce.buffer, l, 0);
3270 6d16c2f8 aliguori
            }
3271 6d16c2f8 aliguori
            ptr = bounce.buffer;
3272 6d16c2f8 aliguori
        } else {
3273 6d16c2f8 aliguori
            addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3274 5579c7f3 pbrook
            ptr = qemu_get_ram_ptr(addr1);
3275 6d16c2f8 aliguori
        }
3276 6d16c2f8 aliguori
        if (!done) {
3277 6d16c2f8 aliguori
            ret = ptr;
3278 6d16c2f8 aliguori
        } else if (ret + done != ptr) {
3279 6d16c2f8 aliguori
            break;
3280 6d16c2f8 aliguori
        }
3281 6d16c2f8 aliguori
3282 6d16c2f8 aliguori
        len -= l;
3283 6d16c2f8 aliguori
        addr += l;
3284 6d16c2f8 aliguori
        done += l;
3285 6d16c2f8 aliguori
    }
3286 6d16c2f8 aliguori
    *plen = done;
3287 6d16c2f8 aliguori
    return ret;
3288 6d16c2f8 aliguori
}
3289 6d16c2f8 aliguori
3290 6d16c2f8 aliguori
/* Unmaps a memory region previously mapped by cpu_physical_memory_map().
3291 6d16c2f8 aliguori
 * Will also mark the memory as dirty if is_write == 1.  access_len gives
3292 6d16c2f8 aliguori
 * the amount of memory that was actually read or written by the caller.
3293 6d16c2f8 aliguori
 */
3294 c227f099 Anthony Liguori
void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
3295 c227f099 Anthony Liguori
                               int is_write, target_phys_addr_t access_len)
3296 6d16c2f8 aliguori
{
3297 6d16c2f8 aliguori
    if (buffer != bounce.buffer) {
3298 6d16c2f8 aliguori
        if (is_write) {
3299 c227f099 Anthony Liguori
            ram_addr_t addr1 = qemu_ram_addr_from_host(buffer);
3300 6d16c2f8 aliguori
            while (access_len) {
3301 6d16c2f8 aliguori
                unsigned l;
3302 6d16c2f8 aliguori
                l = TARGET_PAGE_SIZE;
3303 6d16c2f8 aliguori
                if (l > access_len)
3304 6d16c2f8 aliguori
                    l = access_len;
3305 6d16c2f8 aliguori
                if (!cpu_physical_memory_is_dirty(addr1)) {
3306 6d16c2f8 aliguori
                    /* invalidate code */
3307 6d16c2f8 aliguori
                    tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
3308 6d16c2f8 aliguori
                    /* set dirty bit */
3309 6d16c2f8 aliguori
                    phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3310 6d16c2f8 aliguori
                        (0xff & ~CODE_DIRTY_FLAG);
3311 6d16c2f8 aliguori
                }
3312 6d16c2f8 aliguori
                addr1 += l;
3313 6d16c2f8 aliguori
                access_len -= l;
3314 6d16c2f8 aliguori
            }
3315 6d16c2f8 aliguori
        }
3316 6d16c2f8 aliguori
        return;
3317 6d16c2f8 aliguori
    }
3318 6d16c2f8 aliguori
    if (is_write) {
3319 6d16c2f8 aliguori
        cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
3320 6d16c2f8 aliguori
    }
3321 f8a83245 Herve Poussineau
    qemu_vfree(bounce.buffer);
3322 6d16c2f8 aliguori
    bounce.buffer = NULL;
3323 ba223c29 aliguori
    cpu_notify_map_clients();
3324 6d16c2f8 aliguori
}
3325 d0ecd2aa bellard
3326 8df1cd07 bellard
/* warning: addr must be aligned */
3327 c227f099 Anthony Liguori
uint32_t ldl_phys(target_phys_addr_t addr)
3328 8df1cd07 bellard
{
3329 8df1cd07 bellard
    int io_index;
3330 8df1cd07 bellard
    uint8_t *ptr;
3331 8df1cd07 bellard
    uint32_t val;
3332 8df1cd07 bellard
    unsigned long pd;
3333 8df1cd07 bellard
    PhysPageDesc *p;
3334 8df1cd07 bellard
3335 8df1cd07 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
3336 8df1cd07 bellard
    if (!p) {
3337 8df1cd07 bellard
        pd = IO_MEM_UNASSIGNED;
3338 8df1cd07 bellard
    } else {
3339 8df1cd07 bellard
        pd = p->phys_offset;
3340 8df1cd07 bellard
    }
3341 3b46e624 ths
3342 5fafdf24 ths
    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3343 2a4188a3 bellard
        !(pd & IO_MEM_ROMD)) {
3344 8df1cd07 bellard
        /* I/O case */
3345 8df1cd07 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
3346 8da3ff18 pbrook
        if (p)
3347 8da3ff18 pbrook
            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3348 8df1cd07 bellard
        val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3349 8df1cd07 bellard
    } else {
3350 8df1cd07 bellard
        /* RAM case */
3351 5579c7f3 pbrook
        ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
3352 8df1cd07 bellard
            (addr & ~TARGET_PAGE_MASK);
3353 8df1cd07 bellard
        val = ldl_p(ptr);
3354 8df1cd07 bellard
    }
3355 8df1cd07 bellard
    return val;
3356 8df1cd07 bellard
}
3357 8df1cd07 bellard
3358 84b7b8e7 bellard
/* warning: addr must be aligned */
3359 c227f099 Anthony Liguori
uint64_t ldq_phys(target_phys_addr_t addr)
3360 84b7b8e7 bellard
{
3361 84b7b8e7 bellard
    int io_index;
3362 84b7b8e7 bellard
    uint8_t *ptr;
3363 84b7b8e7 bellard
    uint64_t val;
3364 84b7b8e7 bellard
    unsigned long pd;
3365 84b7b8e7 bellard
    PhysPageDesc *p;
3366 84b7b8e7 bellard
3367 84b7b8e7 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
3368 84b7b8e7 bellard
    if (!p) {
3369 84b7b8e7 bellard
        pd = IO_MEM_UNASSIGNED;
3370 84b7b8e7 bellard
    } else {
3371 84b7b8e7 bellard
        pd = p->phys_offset;
3372 84b7b8e7 bellard
    }
3373 3b46e624 ths
3374 2a4188a3 bellard
    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
3375 2a4188a3 bellard
        !(pd & IO_MEM_ROMD)) {
3376 84b7b8e7 bellard
        /* I/O case */
3377 84b7b8e7 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
3378 8da3ff18 pbrook
        if (p)
3379 8da3ff18 pbrook
            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3380 84b7b8e7 bellard
#ifdef TARGET_WORDS_BIGENDIAN
3381 84b7b8e7 bellard
        val = (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr) << 32;
3382 84b7b8e7 bellard
        val |= io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4);
3383 84b7b8e7 bellard
#else
3384 84b7b8e7 bellard
        val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
3385 84b7b8e7 bellard
        val |= (uint64_t)io_mem_read[io_index][2](io_mem_opaque[io_index], addr + 4) << 32;
3386 84b7b8e7 bellard
#endif
3387 84b7b8e7 bellard
    } else {
3388 84b7b8e7 bellard
        /* RAM case */
3389 5579c7f3 pbrook
        ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
3390 84b7b8e7 bellard
            (addr & ~TARGET_PAGE_MASK);
3391 84b7b8e7 bellard
        val = ldq_p(ptr);
3392 84b7b8e7 bellard
    }
3393 84b7b8e7 bellard
    return val;
3394 84b7b8e7 bellard
}
3395 84b7b8e7 bellard
3396 aab33094 bellard
/* XXX: optimize */
3397 c227f099 Anthony Liguori
uint32_t ldub_phys(target_phys_addr_t addr)
3398 aab33094 bellard
{
3399 aab33094 bellard
    uint8_t val;
3400 aab33094 bellard
    cpu_physical_memory_read(addr, &val, 1);
3401 aab33094 bellard
    return val;
3402 aab33094 bellard
}
3403 aab33094 bellard
3404 aab33094 bellard
/* XXX: optimize */
3405 c227f099 Anthony Liguori
uint32_t lduw_phys(target_phys_addr_t addr)
3406 aab33094 bellard
{
3407 aab33094 bellard
    uint16_t val;
3408 aab33094 bellard
    cpu_physical_memory_read(addr, (uint8_t *)&val, 2);
3409 aab33094 bellard
    return tswap16(val);
3410 aab33094 bellard
}
3411 aab33094 bellard
3412 8df1cd07 bellard
/* warning: addr must be aligned. The ram page is not masked as dirty
3413 8df1cd07 bellard
   and the code inside is not invalidated. It is useful if the dirty
3414 8df1cd07 bellard
   bits are used to track modified PTEs */
3415 c227f099 Anthony Liguori
void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
3416 8df1cd07 bellard
{
3417 8df1cd07 bellard
    int io_index;
3418 8df1cd07 bellard
    uint8_t *ptr;
3419 8df1cd07 bellard
    unsigned long pd;
3420 8df1cd07 bellard
    PhysPageDesc *p;
3421 8df1cd07 bellard
3422 8df1cd07 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
3423 8df1cd07 bellard
    if (!p) {
3424 8df1cd07 bellard
        pd = IO_MEM_UNASSIGNED;
3425 8df1cd07 bellard
    } else {
3426 8df1cd07 bellard
        pd = p->phys_offset;
3427 8df1cd07 bellard
    }
3428 3b46e624 ths
3429 3a7d929e bellard
    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3430 8df1cd07 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
3431 8da3ff18 pbrook
        if (p)
3432 8da3ff18 pbrook
            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3433 8df1cd07 bellard
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3434 8df1cd07 bellard
    } else {
3435 74576198 aliguori
        unsigned long addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3436 5579c7f3 pbrook
        ptr = qemu_get_ram_ptr(addr1);
3437 8df1cd07 bellard
        stl_p(ptr, val);
3438 74576198 aliguori
3439 74576198 aliguori
        if (unlikely(in_migration)) {
3440 74576198 aliguori
            if (!cpu_physical_memory_is_dirty(addr1)) {
3441 74576198 aliguori
                /* invalidate code */
3442 74576198 aliguori
                tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3443 74576198 aliguori
                /* set dirty bit */
3444 74576198 aliguori
                phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3445 74576198 aliguori
                    (0xff & ~CODE_DIRTY_FLAG);
3446 74576198 aliguori
            }
3447 74576198 aliguori
        }
3448 8df1cd07 bellard
    }
3449 8df1cd07 bellard
}
3450 8df1cd07 bellard
3451 c227f099 Anthony Liguori
void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
3452 bc98a7ef j_mayer
{
3453 bc98a7ef j_mayer
    int io_index;
3454 bc98a7ef j_mayer
    uint8_t *ptr;
3455 bc98a7ef j_mayer
    unsigned long pd;
3456 bc98a7ef j_mayer
    PhysPageDesc *p;
3457 bc98a7ef j_mayer
3458 bc98a7ef j_mayer
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
3459 bc98a7ef j_mayer
    if (!p) {
3460 bc98a7ef j_mayer
        pd = IO_MEM_UNASSIGNED;
3461 bc98a7ef j_mayer
    } else {
3462 bc98a7ef j_mayer
        pd = p->phys_offset;
3463 bc98a7ef j_mayer
    }
3464 3b46e624 ths
3465 bc98a7ef j_mayer
    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3466 bc98a7ef j_mayer
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
3467 8da3ff18 pbrook
        if (p)
3468 8da3ff18 pbrook
            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3469 bc98a7ef j_mayer
#ifdef TARGET_WORDS_BIGENDIAN
3470 bc98a7ef j_mayer
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
3471 bc98a7ef j_mayer
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
3472 bc98a7ef j_mayer
#else
3473 bc98a7ef j_mayer
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3474 bc98a7ef j_mayer
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
3475 bc98a7ef j_mayer
#endif
3476 bc98a7ef j_mayer
    } else {
3477 5579c7f3 pbrook
        ptr = qemu_get_ram_ptr(pd & TARGET_PAGE_MASK) +
3478 bc98a7ef j_mayer
            (addr & ~TARGET_PAGE_MASK);
3479 bc98a7ef j_mayer
        stq_p(ptr, val);
3480 bc98a7ef j_mayer
    }
3481 bc98a7ef j_mayer
}
3482 bc98a7ef j_mayer
3483 8df1cd07 bellard
/* warning: addr must be aligned */
3484 c227f099 Anthony Liguori
void stl_phys(target_phys_addr_t addr, uint32_t val)
3485 8df1cd07 bellard
{
3486 8df1cd07 bellard
    int io_index;
3487 8df1cd07 bellard
    uint8_t *ptr;
3488 8df1cd07 bellard
    unsigned long pd;
3489 8df1cd07 bellard
    PhysPageDesc *p;
3490 8df1cd07 bellard
3491 8df1cd07 bellard
    p = phys_page_find(addr >> TARGET_PAGE_BITS);
3492 8df1cd07 bellard
    if (!p) {
3493 8df1cd07 bellard
        pd = IO_MEM_UNASSIGNED;
3494 8df1cd07 bellard
    } else {
3495 8df1cd07 bellard
        pd = p->phys_offset;
3496 8df1cd07 bellard
    }
3497 3b46e624 ths
3498 3a7d929e bellard
    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
3499 8df1cd07 bellard
        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
3500 8da3ff18 pbrook
        if (p)
3501 8da3ff18 pbrook
            addr = (addr & ~TARGET_PAGE_MASK) + p->region_offset;
3502 8df1cd07 bellard
        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
3503 8df1cd07 bellard
    } else {
3504 8df1cd07 bellard
        unsigned long addr1;
3505 8df1cd07 bellard
        addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
3506 8df1cd07 bellard
        /* RAM case */
3507 5579c7f3 pbrook
        ptr = qemu_get_ram_ptr(addr1);
3508 8df1cd07 bellard
        stl_p(ptr, val);
3509 3a7d929e bellard
        if (!cpu_physical_memory_is_dirty(addr1)) {
3510 3a7d929e bellard
            /* invalidate code */
3511 3a7d929e bellard
            tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
3512 3a7d929e bellard
            /* set dirty bit */
3513 f23db169 bellard
            phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
3514 f23db169 bellard
                (0xff & ~CODE_DIRTY_FLAG);
3515 3a7d929e bellard
        }
3516 8df1cd07 bellard
    }
3517 8df1cd07 bellard
}
3518 8df1cd07 bellard
3519 aab33094 bellard
/* XXX: optimize */
3520 c227f099 Anthony Liguori
void stb_phys(target_phys_addr_t addr, uint32_t val)
3521 aab33094 bellard
{
3522 aab33094 bellard
    uint8_t v = val;
3523 aab33094 bellard
    cpu_physical_memory_write(addr, &v, 1);
3524 aab33094 bellard
}
3525 aab33094 bellard
3526 aab33094 bellard
/* XXX: optimize */
3527 c227f099 Anthony Liguori
void stw_phys(target_phys_addr_t addr, uint32_t val)
3528 aab33094 bellard
{
3529 aab33094 bellard
    uint16_t v = tswap16(val);
3530 aab33094 bellard
    cpu_physical_memory_write(addr, (const uint8_t *)&v, 2);
3531 aab33094 bellard
}
3532 aab33094 bellard
3533 aab33094 bellard
/* XXX: optimize */
3534 c227f099 Anthony Liguori
void stq_phys(target_phys_addr_t addr, uint64_t val)
3535 aab33094 bellard
{
3536 aab33094 bellard
    val = tswap64(val);
3537 aab33094 bellard
    cpu_physical_memory_write(addr, (const uint8_t *)&val, 8);
3538 aab33094 bellard
}
3539 aab33094 bellard
3540 13eb76e0 bellard
#endif
3541 13eb76e0 bellard
3542 5e2972fd aliguori
/* virtual memory access for debug (includes writing to ROM) */
3543 5fafdf24 ths
int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
3544 b448f2f3 bellard
                        uint8_t *buf, int len, int is_write)
3545 13eb76e0 bellard
{
3546 13eb76e0 bellard
    int l;
3547 c227f099 Anthony Liguori
    target_phys_addr_t phys_addr;
3548 9b3c35e0 j_mayer
    target_ulong page;
3549 13eb76e0 bellard
3550 13eb76e0 bellard
    while (len > 0) {
3551 13eb76e0 bellard
        page = addr & TARGET_PAGE_MASK;
3552 13eb76e0 bellard
        phys_addr = cpu_get_phys_page_debug(env, page);
3553 13eb76e0 bellard
        /* if no physical page mapped, return an error */
3554 13eb76e0 bellard
        if (phys_addr == -1)
3555 13eb76e0 bellard
            return -1;
3556 13eb76e0 bellard
        l = (page + TARGET_PAGE_SIZE) - addr;
3557 13eb76e0 bellard
        if (l > len)
3558 13eb76e0 bellard
            l = len;
3559 5e2972fd aliguori
        phys_addr += (addr & ~TARGET_PAGE_MASK);
3560 5e2972fd aliguori
#if !defined(CONFIG_USER_ONLY)
3561 5e2972fd aliguori
        if (is_write)
3562 5e2972fd aliguori
            cpu_physical_memory_write_rom(phys_addr, buf, l);
3563 5e2972fd aliguori
        else
3564 5e2972fd aliguori
#endif
3565 5e2972fd aliguori
            cpu_physical_memory_rw(phys_addr, buf, l, is_write);
3566 13eb76e0 bellard
        len -= l;
3567 13eb76e0 bellard
        buf += l;
3568 13eb76e0 bellard
        addr += l;
3569 13eb76e0 bellard
    }
3570 13eb76e0 bellard
    return 0;
3571 13eb76e0 bellard
}
3572 13eb76e0 bellard
3573 2e70f6ef pbrook
/* in deterministic execution mode, instructions doing device I/Os
3574 2e70f6ef pbrook
   must be at the end of the TB */
3575 2e70f6ef pbrook
void cpu_io_recompile(CPUState *env, void *retaddr)
3576 2e70f6ef pbrook
{
3577 2e70f6ef pbrook
    TranslationBlock *tb;
3578 2e70f6ef pbrook
    uint32_t n, cflags;
3579 2e70f6ef pbrook
    target_ulong pc, cs_base;
3580 2e70f6ef pbrook
    uint64_t flags;
3581 2e70f6ef pbrook
3582 2e70f6ef pbrook
    tb = tb_find_pc((unsigned long)retaddr);
3583 2e70f6ef pbrook
    if (!tb) {
3584 2e70f6ef pbrook
        cpu_abort(env, "cpu_io_recompile: could not find TB for pc=%p", 
3585 2e70f6ef pbrook
                  retaddr);
3586 2e70f6ef pbrook
    }
3587 2e70f6ef pbrook
    n = env->icount_decr.u16.low + tb->icount;
3588 2e70f6ef pbrook
    cpu_restore_state(tb, env, (unsigned long)retaddr, NULL);
3589 2e70f6ef pbrook
    /* Calculate how many instructions had been executed before the fault
3590 bf20dc07 ths
       occurred.  */
3591 2e70f6ef pbrook
    n = n - env->icount_decr.u16.low;
3592 2e70f6ef pbrook
    /* Generate a new TB ending on the I/O insn.  */
3593 2e70f6ef pbrook
    n++;
3594 2e70f6ef pbrook
    /* On MIPS and SH, delay slot instructions can only be restarted if
3595 2e70f6ef pbrook
       they were already the first instruction in the TB.  If this is not
3596 bf20dc07 ths
       the first instruction in a TB then re-execute the preceding
3597 2e70f6ef pbrook
       branch.  */
3598 2e70f6ef pbrook
#if defined(TARGET_MIPS)
3599 2e70f6ef pbrook
    if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) {
3600 2e70f6ef pbrook
        env->active_tc.PC -= 4;
3601 2e70f6ef pbrook
        env->icount_decr.u16.low++;
3602 2e70f6ef pbrook
        env->hflags &= ~MIPS_HFLAG_BMASK;
3603 2e70f6ef pbrook
    }
3604 2e70f6ef pbrook
#elif defined(TARGET_SH4)
3605 2e70f6ef pbrook
    if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
3606 2e70f6ef pbrook
            && n > 1) {
3607 2e70f6ef pbrook
        env->pc -= 2;
3608 2e70f6ef pbrook
        env->icount_decr.u16.low++;
3609 2e70f6ef pbrook
        env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
3610 2e70f6ef pbrook
    }
3611 2e70f6ef pbrook
#endif
3612 2e70f6ef pbrook
    /* This should never happen.  */
3613 2e70f6ef pbrook
    if (n > CF_COUNT_MASK)
3614 2e70f6ef pbrook
        cpu_abort(env, "TB too big during recompile");
3615 2e70f6ef pbrook
3616 2e70f6ef pbrook
    cflags = n | CF_LAST_IO;
3617 2e70f6ef pbrook
    pc = tb->pc;
3618 2e70f6ef pbrook
    cs_base = tb->cs_base;
3619 2e70f6ef pbrook
    flags = tb->flags;
3620 2e70f6ef pbrook
    tb_phys_invalidate(tb, -1);
3621 2e70f6ef pbrook
    /* FIXME: In theory this could raise an exception.  In practice
3622 2e70f6ef pbrook
       we have already translated the block once so it's probably ok.  */
3623 2e70f6ef pbrook
    tb_gen_code(env, pc, cs_base, flags, cflags);
3624 bf20dc07 ths
    /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
3625 2e70f6ef pbrook
       the first in the TB) then we end up generating a whole new TB and
3626 2e70f6ef pbrook
       repeating the fault, which is horribly inefficient.
3627 2e70f6ef pbrook
       Better would be to execute just this insn uncached, or generate a
3628 2e70f6ef pbrook
       second new TB.  */
3629 2e70f6ef pbrook
    cpu_resume_from_signal(env, NULL);
3630 2e70f6ef pbrook
}
3631 2e70f6ef pbrook
3632 e3db7226 bellard
void dump_exec_info(FILE *f,
3633 e3db7226 bellard
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
3634 e3db7226 bellard
{
3635 e3db7226 bellard
    int i, target_code_size, max_target_code_size;
3636 e3db7226 bellard
    int direct_jmp_count, direct_jmp2_count, cross_page;
3637 e3db7226 bellard
    TranslationBlock *tb;
3638 3b46e624 ths
3639 e3db7226 bellard
    target_code_size = 0;
3640 e3db7226 bellard
    max_target_code_size = 0;
3641 e3db7226 bellard
    cross_page = 0;
3642 e3db7226 bellard
    direct_jmp_count = 0;
3643 e3db7226 bellard
    direct_jmp2_count = 0;
3644 e3db7226 bellard
    for(i = 0; i < nb_tbs; i++) {
3645 e3db7226 bellard
        tb = &tbs[i];
3646 e3db7226 bellard
        target_code_size += tb->size;
3647 e3db7226 bellard
        if (tb->size > max_target_code_size)
3648 e3db7226 bellard
            max_target_code_size = tb->size;
3649 e3db7226 bellard
        if (tb->page_addr[1] != -1)
3650 e3db7226 bellard
            cross_page++;
3651 e3db7226 bellard
        if (tb->tb_next_offset[0] != 0xffff) {
3652 e3db7226 bellard
            direct_jmp_count++;
3653 e3db7226 bellard
            if (tb->tb_next_offset[1] != 0xffff) {
3654 e3db7226 bellard
                direct_jmp2_count++;
3655 e3db7226 bellard
            }
3656 e3db7226 bellard
        }
3657 e3db7226 bellard
    }
3658 e3db7226 bellard
    /* XXX: avoid using doubles ? */
3659 57fec1fe bellard
    cpu_fprintf(f, "Translation buffer state:\n");
3660 26a5f13b bellard
    cpu_fprintf(f, "gen code size       %ld/%ld\n",
3661 26a5f13b bellard
                code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size);
3662 26a5f13b bellard
    cpu_fprintf(f, "TB count            %d/%d\n", 
3663 26a5f13b bellard
                nb_tbs, code_gen_max_blocks);
3664 5fafdf24 ths
    cpu_fprintf(f, "TB avg target size  %d max=%d bytes\n",
3665 e3db7226 bellard
                nb_tbs ? target_code_size / nb_tbs : 0,
3666 e3db7226 bellard
                max_target_code_size);
3667 5fafdf24 ths
    cpu_fprintf(f, "TB avg host size    %d bytes (expansion ratio: %0.1f)\n",
3668 e3db7226 bellard
                nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0,
3669 e3db7226 bellard
                target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0);
3670 5fafdf24 ths
    cpu_fprintf(f, "cross page TB count %d (%d%%)\n",
3671 5fafdf24 ths
            cross_page,
3672 e3db7226 bellard
            nb_tbs ? (cross_page * 100) / nb_tbs : 0);
3673 e3db7226 bellard
    cpu_fprintf(f, "direct jump count   %d (%d%%) (2 jumps=%d %d%%)\n",
3674 5fafdf24 ths
                direct_jmp_count,
3675 e3db7226 bellard
                nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
3676 e3db7226 bellard
                direct_jmp2_count,
3677 e3db7226 bellard
                nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
3678 57fec1fe bellard
    cpu_fprintf(f, "\nStatistics:\n");
3679 e3db7226 bellard
    cpu_fprintf(f, "TB flush count      %d\n", tb_flush_count);
3680 e3db7226 bellard
    cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
3681 e3db7226 bellard
    cpu_fprintf(f, "TLB flush count     %d\n", tlb_flush_count);
3682 b67d9a52 bellard
    tcg_dump_info(f, cpu_fprintf);
3683 e3db7226 bellard
}
3684 e3db7226 bellard
3685 5fafdf24 ths
#if !defined(CONFIG_USER_ONLY)
3686 61382a50 bellard
3687 61382a50 bellard
#define MMUSUFFIX _cmmu
3688 61382a50 bellard
#define GETPC() NULL
3689 61382a50 bellard
#define env cpu_single_env
3690 b769d8fe bellard
#define SOFTMMU_CODE_ACCESS
3691 61382a50 bellard
3692 61382a50 bellard
#define SHIFT 0
3693 61382a50 bellard
#include "softmmu_template.h"
3694 61382a50 bellard
3695 61382a50 bellard
#define SHIFT 1
3696 61382a50 bellard
#include "softmmu_template.h"
3697 61382a50 bellard
3698 61382a50 bellard
#define SHIFT 2
3699 61382a50 bellard
#include "softmmu_template.h"
3700 61382a50 bellard
3701 61382a50 bellard
#define SHIFT 3
3702 61382a50 bellard
#include "softmmu_template.h"
3703 61382a50 bellard
3704 61382a50 bellard
#undef env
3705 61382a50 bellard
3706 61382a50 bellard
#endif