0.6.2-alt1
[qemu] / qemu-snapshot-2004-11-28_23 / exec.c
1 /*
2  *  virtual page mapping and translated block handling
3  * 
4  *  Copyright (c) 2003 Fabrice Bellard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include "config.h"
21 #ifdef _WIN32
22 #include <windows.h>
23 #else
24 #include <sys/types.h>
25 #include <sys/mman.h>
26 #endif
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <stdarg.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <unistd.h>
33 #include <inttypes.h>
34
35 #include "cpu.h"
36 #include "exec-all.h"
37
38 //#define DEBUG_TB_INVALIDATE
39 //#define DEBUG_FLUSH
40 //#define DEBUG_TLB
41
42 /* make various TB consistency checks */
43 //#define DEBUG_TB_CHECK 
44 //#define DEBUG_TLB_CHECK 
45
46 /* threshold to flush the translated code buffer */
47 #define CODE_GEN_BUFFER_MAX_SIZE (CODE_GEN_BUFFER_SIZE - CODE_GEN_MAX_SIZE)
48
49 #define SMC_BITMAP_USE_THRESHOLD 10
50
51 #define MMAP_AREA_START        0x00000000
52 #define MMAP_AREA_END          0xa8000000
53
54 TranslationBlock tbs[CODE_GEN_MAX_BLOCKS];
55 TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
56 TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
57 int nb_tbs;
58 /* any access to the tbs or the page table must use this lock */
59 spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
60
61 uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
62 uint8_t *code_gen_ptr;
63
64 int phys_ram_size;
65 int phys_ram_fd;
66 uint8_t *phys_ram_base;
67 uint8_t *phys_ram_dirty;
68
69 typedef struct PageDesc {
70     /* list of TBs intersecting this ram page */
71     TranslationBlock *first_tb;
72     /* in order to optimize self modifying code, we count the number
73        of lookups we do to a given page to use a bitmap */
74     unsigned int code_write_count;
75     uint8_t *code_bitmap;
76 #if defined(CONFIG_USER_ONLY)
77     unsigned long flags;
78 #endif
79 } PageDesc;
80
81 typedef struct PhysPageDesc {
82     /* offset in host memory of the page + io_index in the low 12 bits */
83     unsigned long phys_offset;
84 } PhysPageDesc;
85
86 typedef struct VirtPageDesc {
87     /* physical address of code page. It is valid only if 'valid_tag'
88        matches 'virt_valid_tag' */ 
89     target_ulong phys_addr; 
90     unsigned int valid_tag;
91 #if !defined(CONFIG_SOFTMMU)
92     /* original page access rights. It is valid only if 'valid_tag'
93        matches 'virt_valid_tag' */
94     unsigned int prot;
95 #endif
96 } VirtPageDesc;
97
98 #define L2_BITS 10
99 #define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
100
101 #define L1_SIZE (1 << L1_BITS)
102 #define L2_SIZE (1 << L2_BITS)
103
104 static void io_mem_init(void);
105
106 unsigned long qemu_real_host_page_size;
107 unsigned long qemu_host_page_bits;
108 unsigned long qemu_host_page_size;
109 unsigned long qemu_host_page_mask;
110
111 /* XXX: for system emulation, it could just be an array */
112 static PageDesc *l1_map[L1_SIZE];
113 static PhysPageDesc *l1_phys_map[L1_SIZE];
114
115 #if !defined(CONFIG_USER_ONLY)
116 static VirtPageDesc *l1_virt_map[L1_SIZE];
117 static unsigned int virt_valid_tag;
118 #endif
119
120 /* io memory support */
121 CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
122 CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
123 void *io_mem_opaque[IO_MEM_NB_ENTRIES];
124 static int io_mem_nb;
125
126 /* log support */
127 char *logfilename = "/tmp/qemu.log";
128 FILE *logfile;
129 int loglevel;
130
131 static void page_init(void)
132 {
133     /* NOTE: we can always suppose that qemu_host_page_size >=
134        TARGET_PAGE_SIZE */
135 #ifdef _WIN32
136     {
137         SYSTEM_INFO system_info;
138         DWORD old_protect;
139         
140         GetSystemInfo(&system_info);
141         qemu_real_host_page_size = system_info.dwPageSize;
142         
143         VirtualProtect(code_gen_buffer, sizeof(code_gen_buffer),
144                        PAGE_EXECUTE_READWRITE, &old_protect);
145     }
146 #else
147     qemu_real_host_page_size = getpagesize();
148     {
149         unsigned long start, end;
150
151         start = (unsigned long)code_gen_buffer;
152         start &= ~(qemu_real_host_page_size - 1);
153         
154         end = (unsigned long)code_gen_buffer + sizeof(code_gen_buffer);
155         end += qemu_real_host_page_size - 1;
156         end &= ~(qemu_real_host_page_size - 1);
157         
158         mprotect((void *)start, end - start, 
159                  PROT_READ | PROT_WRITE | PROT_EXEC);
160     }
161 #endif
162
163     if (qemu_host_page_size == 0)
164         qemu_host_page_size = qemu_real_host_page_size;
165     if (qemu_host_page_size < TARGET_PAGE_SIZE)
166         qemu_host_page_size = TARGET_PAGE_SIZE;
167     qemu_host_page_bits = 0;
168     while ((1 << qemu_host_page_bits) < qemu_host_page_size)
169         qemu_host_page_bits++;
170     qemu_host_page_mask = ~(qemu_host_page_size - 1);
171 #if !defined(CONFIG_USER_ONLY)
172     virt_valid_tag = 1;
173 #endif
174 }
175
176 static inline PageDesc *page_find_alloc(unsigned int index)
177 {
178     PageDesc **lp, *p;
179
180     lp = &l1_map[index >> L2_BITS];
181     p = *lp;
182     if (!p) {
183         /* allocate if not found */
184         p = qemu_malloc(sizeof(PageDesc) * L2_SIZE);
185         memset(p, 0, sizeof(PageDesc) * L2_SIZE);
186         *lp = p;
187     }
188     return p + (index & (L2_SIZE - 1));
189 }
190
191 static inline PageDesc *page_find(unsigned int index)
192 {
193     PageDesc *p;
194
195     p = l1_map[index >> L2_BITS];
196     if (!p)
197         return 0;
198     return p + (index & (L2_SIZE - 1));
199 }
200
201 static inline PhysPageDesc *phys_page_find_alloc(unsigned int index)
202 {
203     PhysPageDesc **lp, *p;
204
205     lp = &l1_phys_map[index >> L2_BITS];
206     p = *lp;
207     if (!p) {
208         /* allocate if not found */
209         p = qemu_malloc(sizeof(PhysPageDesc) * L2_SIZE);
210         memset(p, 0, sizeof(PhysPageDesc) * L2_SIZE);
211         *lp = p;
212     }
213     return p + (index & (L2_SIZE - 1));
214 }
215
216 static inline PhysPageDesc *phys_page_find(unsigned int index)
217 {
218     PhysPageDesc *p;
219
220     p = l1_phys_map[index >> L2_BITS];
221     if (!p)
222         return 0;
223     return p + (index & (L2_SIZE - 1));
224 }
225
226 #if !defined(CONFIG_USER_ONLY)
227 static void tlb_protect_code(CPUState *env, target_ulong addr);
228 static void tlb_unprotect_code_phys(CPUState *env, unsigned long phys_addr, target_ulong vaddr);
229
230 static inline VirtPageDesc *virt_page_find_alloc(unsigned int index)
231 {
232     VirtPageDesc **lp, *p;
233
234     lp = &l1_virt_map[index >> L2_BITS];
235     p = *lp;
236     if (!p) {
237         /* allocate if not found */
238         p = qemu_malloc(sizeof(VirtPageDesc) * L2_SIZE);
239         memset(p, 0, sizeof(VirtPageDesc) * L2_SIZE);
240         *lp = p;
241     }
242     return p + (index & (L2_SIZE - 1));
243 }
244
245 static inline VirtPageDesc *virt_page_find(unsigned int index)
246 {
247     VirtPageDesc *p;
248
249     p = l1_virt_map[index >> L2_BITS];
250     if (!p)
251         return 0;
252     return p + (index & (L2_SIZE - 1));
253 }
254
255 static void virt_page_flush(void)
256 {
257     int i, j;
258     VirtPageDesc *p;
259     
260     virt_valid_tag++;
261
262     if (virt_valid_tag == 0) {
263         virt_valid_tag = 1;
264         for(i = 0; i < L1_SIZE; i++) {
265             p = l1_virt_map[i];
266             if (p) {
267                 for(j = 0; j < L2_SIZE; j++)
268                     p[j].valid_tag = 0;
269             }
270         }
271     }
272 }
273 #else
274 static void virt_page_flush(void)
275 {
276 }
277 #endif
278
279 void cpu_exec_init(void)
280 {
281     if (!code_gen_ptr) {
282         code_gen_ptr = code_gen_buffer;
283         page_init();
284         io_mem_init();
285     }
286 }
287
288 static inline void invalidate_page_bitmap(PageDesc *p)
289 {
290     if (p->code_bitmap) {
291         qemu_free(p->code_bitmap);
292         p->code_bitmap = NULL;
293     }
294     p->code_write_count = 0;
295 }
296
297 /* set to NULL all the 'first_tb' fields in all PageDescs */
298 static void page_flush_tb(void)
299 {
300     int i, j;
301     PageDesc *p;
302
303     for(i = 0; i < L1_SIZE; i++) {
304         p = l1_map[i];
305         if (p) {
306             for(j = 0; j < L2_SIZE; j++) {
307                 p->first_tb = NULL;
308                 invalidate_page_bitmap(p);
309                 p++;
310             }
311         }
312     }
313 }
314
315 /* flush all the translation blocks */
316 /* XXX: tb_flush is currently not thread safe */
317 void tb_flush(CPUState *env)
318 {
319 #if defined(DEBUG_FLUSH)
320     printf("qemu: flush code_size=%d nb_tbs=%d avg_tb_size=%d\n", 
321            code_gen_ptr - code_gen_buffer, 
322            nb_tbs, 
323            nb_tbs > 0 ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0);
324 #endif
325     nb_tbs = 0;
326     memset (tb_hash, 0, CODE_GEN_HASH_SIZE * sizeof (void *));
327     virt_page_flush();
328
329     memset (tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof (void *));
330     page_flush_tb();
331
332     code_gen_ptr = code_gen_buffer;
333     /* XXX: flush processor icache at this point if cache flush is
334        expensive */
335 }
336
337 #ifdef DEBUG_TB_CHECK
338
339 static void tb_invalidate_check(unsigned long address)
340 {
341     TranslationBlock *tb;
342     int i;
343     address &= TARGET_PAGE_MASK;
344     for(i = 0;i < CODE_GEN_HASH_SIZE; i++) {
345         for(tb = tb_hash[i]; tb != NULL; tb = tb->hash_next) {
346             if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
347                   address >= tb->pc + tb->size)) {
348                 printf("ERROR invalidate: address=%08lx PC=%08lx size=%04x\n",
349                        address, tb->pc, tb->size);
350             }
351         }
352     }
353 }
354
355 /* verify that all the pages have correct rights for code */
356 static void tb_page_check(void)
357 {
358     TranslationBlock *tb;
359     int i, flags1, flags2;
360     
361     for(i = 0;i < CODE_GEN_HASH_SIZE; i++) {
362         for(tb = tb_hash[i]; tb != NULL; tb = tb->hash_next) {
363             flags1 = page_get_flags(tb->pc);
364             flags2 = page_get_flags(tb->pc + tb->size - 1);
365             if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
366                 printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
367                        tb->pc, tb->size, flags1, flags2);
368             }
369         }
370     }
371 }
372
373 void tb_jmp_check(TranslationBlock *tb)
374 {
375     TranslationBlock *tb1;
376     unsigned int n1;
377
378     /* suppress any remaining jumps to this TB */
379     tb1 = tb->jmp_first;
380     for(;;) {
381         n1 = (long)tb1 & 3;
382         tb1 = (TranslationBlock *)((long)tb1 & ~3);
383         if (n1 == 2)
384             break;
385         tb1 = tb1->jmp_next[n1];
386     }
387     /* check end of list */
388     if (tb1 != tb) {
389         printf("ERROR: jmp_list from 0x%08lx\n", (long)tb);
390     }
391 }
392
393 #endif
394
395 /* invalidate one TB */
396 static inline void tb_remove(TranslationBlock **ptb, TranslationBlock *tb,
397                              int next_offset)
398 {
399     TranslationBlock *tb1;
400     for(;;) {
401         tb1 = *ptb;
402         if (tb1 == tb) {
403             *ptb = *(TranslationBlock **)((char *)tb1 + next_offset);
404             break;
405         }
406         ptb = (TranslationBlock **)((char *)tb1 + next_offset);
407     }
408 }
409
410 static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
411 {
412     TranslationBlock *tb1;
413     unsigned int n1;
414
415     for(;;) {
416         tb1 = *ptb;
417         n1 = (long)tb1 & 3;
418         tb1 = (TranslationBlock *)((long)tb1 & ~3);
419         if (tb1 == tb) {
420             *ptb = tb1->page_next[n1];
421             break;
422         }
423         ptb = &tb1->page_next[n1];
424     }
425 }
426
427 static inline void tb_jmp_remove(TranslationBlock *tb, int n)
428 {
429     TranslationBlock *tb1, **ptb;
430     unsigned int n1;
431
432     ptb = &tb->jmp_next[n];
433     tb1 = *ptb;
434     if (tb1) {
435         /* find tb(n) in circular list */
436         for(;;) {
437             tb1 = *ptb;
438             n1 = (long)tb1 & 3;
439             tb1 = (TranslationBlock *)((long)tb1 & ~3);
440             if (n1 == n && tb1 == tb)
441                 break;
442             if (n1 == 2) {
443                 ptb = &tb1->jmp_first;
444             } else {
445                 ptb = &tb1->jmp_next[n1];
446             }
447         }
448         /* now we can suppress tb(n) from the list */
449         *ptb = tb->jmp_next[n];
450
451         tb->jmp_next[n] = NULL;
452     }
453 }
454
455 /* reset the jump entry 'n' of a TB so that it is not chained to
456    another TB */
457 static inline void tb_reset_jump(TranslationBlock *tb, int n)
458 {
459     tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
460 }
461
462 static inline void tb_invalidate(TranslationBlock *tb)
463 {
464     unsigned int h, n1;
465     TranslationBlock *tb1, *tb2, **ptb;
466     
467     tb_invalidated_flag = 1;
468
469     /* remove the TB from the hash list */
470     h = tb_hash_func(tb->pc);
471     ptb = &tb_hash[h];
472     for(;;) {
473         tb1 = *ptb;
474         /* NOTE: the TB is not necessarily linked in the hash. It
475            indicates that it is not currently used */
476         if (tb1 == NULL)
477             return;
478         if (tb1 == tb) {
479             *ptb = tb1->hash_next;
480             break;
481         }
482         ptb = &tb1->hash_next;
483     }
484
485     /* suppress this TB from the two jump lists */
486     tb_jmp_remove(tb, 0);
487     tb_jmp_remove(tb, 1);
488
489     /* suppress any remaining jumps to this TB */
490     tb1 = tb->jmp_first;
491     for(;;) {
492         n1 = (long)tb1 & 3;
493         if (n1 == 2)
494             break;
495         tb1 = (TranslationBlock *)((long)tb1 & ~3);
496         tb2 = tb1->jmp_next[n1];
497         tb_reset_jump(tb1, n1);
498         tb1->jmp_next[n1] = NULL;
499         tb1 = tb2;
500     }
501     tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
502 }
503
504 static inline void tb_phys_invalidate(TranslationBlock *tb, unsigned int page_addr)
505 {
506     PageDesc *p;
507     unsigned int h;
508     target_ulong phys_pc;
509     
510     /* remove the TB from the hash list */
511     phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
512     h = tb_phys_hash_func(phys_pc);
513     tb_remove(&tb_phys_hash[h], tb, 
514               offsetof(TranslationBlock, phys_hash_next));
515
516     /* remove the TB from the page list */
517     if (tb->page_addr[0] != page_addr) {
518         p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
519         tb_page_remove(&p->first_tb, tb);
520         invalidate_page_bitmap(p);
521     }
522     if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
523         p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
524         tb_page_remove(&p->first_tb, tb);
525         invalidate_page_bitmap(p);
526     }
527
528     tb_invalidate(tb);
529 }
530
531 static inline void set_bits(uint8_t *tab, int start, int len)
532 {
533     int end, mask, end1;
534
535     end = start + len;
536     tab += start >> 3;
537     mask = 0xff << (start & 7);
538     if ((start & ~7) == (end & ~7)) {
539         if (start < end) {
540             mask &= ~(0xff << (end & 7));
541             *tab |= mask;
542         }
543     } else {
544         *tab++ |= mask;
545         start = (start + 8) & ~7;
546         end1 = end & ~7;
547         while (start < end1) {
548             *tab++ = 0xff;
549             start += 8;
550         }
551         if (start < end) {
552             mask = ~(0xff << (end & 7));
553             *tab |= mask;
554         }
555     }
556 }
557
558 static void build_page_bitmap(PageDesc *p)
559 {
560     int n, tb_start, tb_end;
561     TranslationBlock *tb;
562     
563     p->code_bitmap = qemu_malloc(TARGET_PAGE_SIZE / 8);
564     if (!p->code_bitmap)
565         return;
566     memset(p->code_bitmap, 0, TARGET_PAGE_SIZE / 8);
567
568     tb = p->first_tb;
569     while (tb != NULL) {
570         n = (long)tb & 3;
571         tb = (TranslationBlock *)((long)tb & ~3);
572         /* NOTE: this is subtle as a TB may span two physical pages */
573         if (n == 0) {
574             /* NOTE: tb_end may be after the end of the page, but
575                it is not a problem */
576             tb_start = tb->pc & ~TARGET_PAGE_MASK;
577             tb_end = tb_start + tb->size;
578             if (tb_end > TARGET_PAGE_SIZE)
579                 tb_end = TARGET_PAGE_SIZE;
580         } else {
581             tb_start = 0;
582             tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
583         }
584         set_bits(p->code_bitmap, tb_start, tb_end - tb_start);
585         tb = tb->page_next[n];
586     }
587 }
588
589 #ifdef TARGET_HAS_PRECISE_SMC
590
591 static void tb_gen_code(CPUState *env, 
592                         target_ulong pc, target_ulong cs_base, int flags,
593                         int cflags)
594 {
595     TranslationBlock *tb;
596     uint8_t *tc_ptr;
597     target_ulong phys_pc, phys_page2, virt_page2;
598     int code_gen_size;
599
600     phys_pc = get_phys_addr_code(env, (unsigned long)pc);
601     tb = tb_alloc((unsigned long)pc);
602     if (!tb) {
603         /* flush must be done */
604         tb_flush(env);
605         /* cannot fail at this point */
606         tb = tb_alloc((unsigned long)pc);
607     }
608     tc_ptr = code_gen_ptr;
609     tb->tc_ptr = tc_ptr;
610     tb->cs_base = cs_base;
611     tb->flags = flags;
612     tb->cflags = cflags;
613     cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size);
614     code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
615     
616     /* check next page if needed */
617     virt_page2 = ((unsigned long)pc + tb->size - 1) & TARGET_PAGE_MASK;
618     phys_page2 = -1;
619     if (((unsigned long)pc & TARGET_PAGE_MASK) != virt_page2) {
620         phys_page2 = get_phys_addr_code(env, virt_page2);
621     }
622     tb_link_phys(tb, phys_pc, phys_page2);
623 }
624 #endif
625     
626 /* invalidate all TBs which intersect with the target physical page
627    starting in range [start;end[. NOTE: start and end must refer to
628    the same physical page. 'is_cpu_write_access' should be true if called
629    from a real cpu write access: the virtual CPU will exit the current
630    TB if code is modified inside this TB. */
631 void tb_invalidate_phys_page_range(target_ulong start, target_ulong end, 
632                                    int is_cpu_write_access)
633 {
634     int n, current_tb_modified, current_tb_not_found, current_flags;
635     CPUState *env = cpu_single_env;
636     PageDesc *p;
637     TranslationBlock *tb, *tb_next, *current_tb, *saved_tb;
638     target_ulong tb_start, tb_end;
639     target_ulong current_pc, current_cs_base;
640
641     p = page_find(start >> TARGET_PAGE_BITS);
642     if (!p) 
643         return;
644     if (!p->code_bitmap && 
645         ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
646         is_cpu_write_access) {
647         /* build code bitmap */
648         build_page_bitmap(p);
649     }
650
651     /* we remove all the TBs in the range [start, end[ */
652     /* XXX: see if in some cases it could be faster to invalidate all the code */
653     current_tb_not_found = is_cpu_write_access;
654     current_tb_modified = 0;
655     current_tb = NULL; /* avoid warning */
656     current_pc = 0; /* avoid warning */
657     current_cs_base = 0; /* avoid warning */
658     current_flags = 0; /* avoid warning */
659     tb = p->first_tb;
660     while (tb != NULL) {
661         n = (long)tb & 3;
662         tb = (TranslationBlock *)((long)tb & ~3);
663         tb_next = tb->page_next[n];
664         /* NOTE: this is subtle as a TB may span two physical pages */
665         if (n == 0) {
666             /* NOTE: tb_end may be after the end of the page, but
667                it is not a problem */
668             tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
669             tb_end = tb_start + tb->size;
670         } else {
671             tb_start = tb->page_addr[1];
672             tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
673         }
674         if (!(tb_end <= start || tb_start >= end)) {
675 #ifdef TARGET_HAS_PRECISE_SMC
676             if (current_tb_not_found) {
677                 current_tb_not_found = 0;
678                 current_tb = NULL;
679                 if (env->mem_write_pc) {
680                     /* now we have a real cpu fault */
681                     current_tb = tb_find_pc(env->mem_write_pc);
682                 }
683             }
684             if (current_tb == tb &&
685                 !(current_tb->cflags & CF_SINGLE_INSN)) {
686                 /* If we are modifying the current TB, we must stop
687                 its execution. We could be more precise by checking
688                 that the modification is after the current PC, but it
689                 would require a specialized function to partially
690                 restore the CPU state */
691                 
692                 current_tb_modified = 1;
693                 cpu_restore_state(current_tb, env, 
694                                   env->mem_write_pc, NULL);
695 #if defined(TARGET_I386)
696                 current_flags = env->hflags;
697                 current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
698                 current_cs_base = (target_ulong)env->segs[R_CS].base;
699                 current_pc = current_cs_base + env->eip;
700 #else
701 #error unsupported CPU
702 #endif
703             }
704 #endif /* TARGET_HAS_PRECISE_SMC */
705             saved_tb = env->current_tb;
706             env->current_tb = NULL;
707             tb_phys_invalidate(tb, -1);
708             env->current_tb = saved_tb;
709             if (env->interrupt_request && env->current_tb)
710                 cpu_interrupt(env, env->interrupt_request);
711         }
712         tb = tb_next;
713     }
714 #if !defined(CONFIG_USER_ONLY)
715     /* if no code remaining, no need to continue to use slow writes */
716     if (!p->first_tb) {
717         invalidate_page_bitmap(p);
718         if (is_cpu_write_access) {
719             tlb_unprotect_code_phys(env, start, env->mem_write_vaddr);
720         }
721     }
722 #endif
723 #ifdef TARGET_HAS_PRECISE_SMC
724     if (current_tb_modified) {
725         /* we generate a block containing just the instruction
726            modifying the memory. It will ensure that it cannot modify
727            itself */
728         env->current_tb = NULL;
729         tb_gen_code(env, current_pc, current_cs_base, current_flags, 
730                     CF_SINGLE_INSN);
731         cpu_resume_from_signal(env, NULL);
732     }
733 #endif
734 }
735
736 /* len must be <= 8 and start must be a multiple of len */
737 static inline void tb_invalidate_phys_page_fast(target_ulong start, int len)
738 {
739     PageDesc *p;
740     int offset, b;
741 #if 0
742     if (1) {
743         if (loglevel) {
744             fprintf(logfile, "modifying code at 0x%x size=%d EIP=%x PC=%08x\n", 
745                    cpu_single_env->mem_write_vaddr, len, 
746                    cpu_single_env->eip, 
747                    cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
748         }
749     }
750 #endif
751     p = page_find(start >> TARGET_PAGE_BITS);
752     if (!p) 
753         return;
754     if (p->code_bitmap) {
755         offset = start & ~TARGET_PAGE_MASK;
756         b = p->code_bitmap[offset >> 3] >> (offset & 7);
757         if (b & ((1 << len) - 1))
758             goto do_invalidate;
759     } else {
760     do_invalidate:
761         tb_invalidate_phys_page_range(start, start + len, 1);
762     }
763 }
764
765 #if !defined(CONFIG_SOFTMMU)
766 static void tb_invalidate_phys_page(target_ulong addr, 
767                                     unsigned long pc, void *puc)
768 {
769     int n, current_flags, current_tb_modified;
770     target_ulong current_pc, current_cs_base;
771     PageDesc *p;
772     TranslationBlock *tb, *current_tb;
773 #ifdef TARGET_HAS_PRECISE_SMC
774     CPUState *env = cpu_single_env;
775 #endif
776
777     addr &= TARGET_PAGE_MASK;
778     p = page_find(addr >> TARGET_PAGE_BITS);
779     if (!p) 
780         return;
781     tb = p->first_tb;
782     current_tb_modified = 0;
783     current_tb = NULL;
784     current_pc = 0; /* avoid warning */
785     current_cs_base = 0; /* avoid warning */
786     current_flags = 0; /* avoid warning */
787 #ifdef TARGET_HAS_PRECISE_SMC
788     if (tb && pc != 0) {
789         current_tb = tb_find_pc(pc);
790     }
791 #endif
792     while (tb != NULL) {
793         n = (long)tb & 3;
794         tb = (TranslationBlock *)((long)tb & ~3);
795 #ifdef TARGET_HAS_PRECISE_SMC
796         if (current_tb == tb &&
797             !(current_tb->cflags & CF_SINGLE_INSN)) {
798                 /* If we are modifying the current TB, we must stop
799                    its execution. We could be more precise by checking
800                    that the modification is after the current PC, but it
801                    would require a specialized function to partially
802                    restore the CPU state */
803             
804             current_tb_modified = 1;
805             cpu_restore_state(current_tb, env, pc, puc);
806 #if defined(TARGET_I386)
807             current_flags = env->hflags;
808             current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
809             current_cs_base = (target_ulong)env->segs[R_CS].base;
810             current_pc = current_cs_base + env->eip;
811 #else
812 #error unsupported CPU
813 #endif
814         }
815 #endif /* TARGET_HAS_PRECISE_SMC */
816         tb_phys_invalidate(tb, addr);
817         tb = tb->page_next[n];
818     }
819     p->first_tb = NULL;
820 #ifdef TARGET_HAS_PRECISE_SMC
821     if (current_tb_modified) {
822         /* we generate a block containing just the instruction
823            modifying the memory. It will ensure that it cannot modify
824            itself */
825         env->current_tb = NULL;
826         tb_gen_code(env, current_pc, current_cs_base, current_flags, 
827                     CF_SINGLE_INSN);
828         cpu_resume_from_signal(env, puc);
829     }
830 #endif
831 }
832 #endif
833
834 /* add the tb in the target page and protect it if necessary */
835 static inline void tb_alloc_page(TranslationBlock *tb, 
836                                  unsigned int n, unsigned int page_addr)
837 {
838     PageDesc *p;
839     TranslationBlock *last_first_tb;
840
841     tb->page_addr[n] = page_addr;
842     p = page_find(page_addr >> TARGET_PAGE_BITS);
843     tb->page_next[n] = p->first_tb;
844     last_first_tb = p->first_tb;
845     p->first_tb = (TranslationBlock *)((long)tb | n);
846     invalidate_page_bitmap(p);
847
848 #if defined(TARGET_HAS_SMC) || 1
849
850 #if defined(CONFIG_USER_ONLY)
851     if (p->flags & PAGE_WRITE) {
852         unsigned long host_start, host_end, addr;
853         int prot;
854
855         /* force the host page as non writable (writes will have a
856            page fault + mprotect overhead) */
857         host_start = page_addr & qemu_host_page_mask;
858         host_end = host_start + qemu_host_page_size;
859         prot = 0;
860         for(addr = host_start; addr < host_end; addr += TARGET_PAGE_SIZE)
861             prot |= page_get_flags(addr);
862         mprotect((void *)host_start, qemu_host_page_size, 
863                  (prot & PAGE_BITS) & ~PAGE_WRITE);
864 #ifdef DEBUG_TB_INVALIDATE
865         printf("protecting code page: 0x%08lx\n", 
866                host_start);
867 #endif
868         p->flags &= ~PAGE_WRITE;
869     }
870 #else
871     /* if some code is already present, then the pages are already
872        protected. So we handle the case where only the first TB is
873        allocated in a physical page */
874     if (!last_first_tb) {
875         target_ulong virt_addr;
876
877         virt_addr = (tb->pc & TARGET_PAGE_MASK) + (n << TARGET_PAGE_BITS);
878         tlb_protect_code(cpu_single_env, virt_addr);        
879     }
880 #endif
881
882 #endif /* TARGET_HAS_SMC */
883 }
884
885 /* Allocate a new translation block. Flush the translation buffer if
886    too many translation blocks or too much generated code. */
887 TranslationBlock *tb_alloc(unsigned long pc)
888 {
889     TranslationBlock *tb;
890
891     if (nb_tbs >= CODE_GEN_MAX_BLOCKS || 
892         (code_gen_ptr - code_gen_buffer) >= CODE_GEN_BUFFER_MAX_SIZE)
893         return NULL;
894     tb = &tbs[nb_tbs++];
895     tb->pc = pc;
896     tb->cflags = 0;
897     return tb;
898 }
899
900 /* add a new TB and link it to the physical page tables. phys_page2 is
901    (-1) to indicate that only one page contains the TB. */
902 void tb_link_phys(TranslationBlock *tb, 
903                   target_ulong phys_pc, target_ulong phys_page2)
904 {
905     unsigned int h;
906     TranslationBlock **ptb;
907
908     /* add in the physical hash table */
909     h = tb_phys_hash_func(phys_pc);
910     ptb = &tb_phys_hash[h];
911     tb->phys_hash_next = *ptb;
912     *ptb = tb;
913
914     /* add in the page list */
915     tb_alloc_page(tb, 0, phys_pc & TARGET_PAGE_MASK);
916     if (phys_page2 != -1)
917         tb_alloc_page(tb, 1, phys_page2);
918     else
919         tb->page_addr[1] = -1;
920 #ifdef DEBUG_TB_CHECK
921     tb_page_check();
922 #endif
923 }
924
925 /* link the tb with the other TBs */
926 void tb_link(TranslationBlock *tb)
927 {
928 #if !defined(CONFIG_USER_ONLY)
929     {
930         VirtPageDesc *vp;
931         target_ulong addr;
932         
933         /* save the code memory mappings (needed to invalidate the code) */
934         addr = tb->pc & TARGET_PAGE_MASK;
935         vp = virt_page_find_alloc(addr >> TARGET_PAGE_BITS);
936 #ifdef DEBUG_TLB_CHECK 
937         if (vp->valid_tag == virt_valid_tag &&
938             vp->phys_addr != tb->page_addr[0]) {
939             printf("Error tb addr=0x%x phys=0x%x vp->phys_addr=0x%x\n",
940                    addr, tb->page_addr[0], vp->phys_addr);
941         }
942 #endif
943         vp->phys_addr = tb->page_addr[0];
944         if (vp->valid_tag != virt_valid_tag) {
945             vp->valid_tag = virt_valid_tag;
946 #if !defined(CONFIG_SOFTMMU)
947             vp->prot = 0;
948 #endif
949         }
950         
951         if (tb->page_addr[1] != -1) {
952             addr += TARGET_PAGE_SIZE;
953             vp = virt_page_find_alloc(addr >> TARGET_PAGE_BITS);
954 #ifdef DEBUG_TLB_CHECK 
955             if (vp->valid_tag == virt_valid_tag &&
956                 vp->phys_addr != tb->page_addr[1]) { 
957                 printf("Error tb addr=0x%x phys=0x%x vp->phys_addr=0x%x\n",
958                        addr, tb->page_addr[1], vp->phys_addr);
959             }
960 #endif
961             vp->phys_addr = tb->page_addr[1];
962             if (vp->valid_tag != virt_valid_tag) {
963                 vp->valid_tag = virt_valid_tag;
964 #if !defined(CONFIG_SOFTMMU)
965                 vp->prot = 0;
966 #endif
967             }
968         }
969     }
970 #endif
971
972     tb->jmp_first = (TranslationBlock *)((long)tb | 2);
973     tb->jmp_next[0] = NULL;
974     tb->jmp_next[1] = NULL;
975 #ifdef USE_CODE_COPY
976     tb->cflags &= ~CF_FP_USED;
977     if (tb->cflags & CF_TB_FP_USED)
978         tb->cflags |= CF_FP_USED;
979 #endif
980
981     /* init original jump addresses */
982     if (tb->tb_next_offset[0] != 0xffff)
983         tb_reset_jump(tb, 0);
984     if (tb->tb_next_offset[1] != 0xffff)
985         tb_reset_jump(tb, 1);
986 }
987
988 /* find the TB 'tb' such that tb[0].tc_ptr <= tc_ptr <
989    tb[1].tc_ptr. Return NULL if not found */
990 TranslationBlock *tb_find_pc(unsigned long tc_ptr)
991 {
992     int m_min, m_max, m;
993     unsigned long v;
994     TranslationBlock *tb;
995
996     if (nb_tbs <= 0)
997         return NULL;
998     if (tc_ptr < (unsigned long)code_gen_buffer ||
999         tc_ptr >= (unsigned long)code_gen_ptr)
1000         return NULL;
1001     /* binary search (cf Knuth) */
1002     m_min = 0;
1003     m_max = nb_tbs - 1;
1004     while (m_min <= m_max) {
1005         m = (m_min + m_max) >> 1;
1006         tb = &tbs[m];
1007         v = (unsigned long)tb->tc_ptr;
1008         if (v == tc_ptr)
1009             return tb;
1010         else if (tc_ptr < v) {
1011             m_max = m - 1;
1012         } else {
1013             m_min = m + 1;
1014         }
1015     } 
1016     return &tbs[m_max];
1017 }
1018
1019 static void tb_reset_jump_recursive(TranslationBlock *tb);
1020
1021 static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
1022 {
1023     TranslationBlock *tb1, *tb_next, **ptb;
1024     unsigned int n1;
1025
1026     tb1 = tb->jmp_next[n];
1027     if (tb1 != NULL) {
1028         /* find head of list */
1029         for(;;) {
1030             n1 = (long)tb1 & 3;
1031             tb1 = (TranslationBlock *)((long)tb1 & ~3);
1032             if (n1 == 2)
1033                 break;
1034             tb1 = tb1->jmp_next[n1];
1035         }
1036         /* we are now sure now that tb jumps to tb1 */
1037         tb_next = tb1;
1038
1039         /* remove tb from the jmp_first list */
1040         ptb = &tb_next->jmp_first;
1041         for(;;) {
1042             tb1 = *ptb;
1043             n1 = (long)tb1 & 3;
1044             tb1 = (TranslationBlock *)((long)tb1 & ~3);
1045             if (n1 == n && tb1 == tb)
1046                 break;
1047             ptb = &tb1->jmp_next[n1];
1048         }
1049         *ptb = tb->jmp_next[n];
1050         tb->jmp_next[n] = NULL;
1051         
1052         /* suppress the jump to next tb in generated code */
1053         tb_reset_jump(tb, n);
1054
1055         /* suppress jumps in the tb on which we could have jumped */
1056         tb_reset_jump_recursive(tb_next);
1057     }
1058 }
1059
1060 static void tb_reset_jump_recursive(TranslationBlock *tb)
1061 {
1062     tb_reset_jump_recursive2(tb, 0);
1063     tb_reset_jump_recursive2(tb, 1);
1064 }
1065
1066 static void breakpoint_invalidate(CPUState *env, target_ulong pc)
1067 {
1068     target_ulong phys_addr;
1069
1070     phys_addr = cpu_get_phys_page_debug(env, pc);
1071     tb_invalidate_phys_page_range(phys_addr, phys_addr + 1, 0);
1072 }
1073
1074 /* add a breakpoint. EXCP_DEBUG is returned by the CPU loop if a
1075    breakpoint is reached */
1076 int cpu_breakpoint_insert(CPUState *env, target_ulong pc)
1077 {
1078 #if defined(TARGET_I386) || defined(TARGET_PPC) || defined(TARGET_SPARC)
1079     int i;
1080     
1081     for(i = 0; i < env->nb_breakpoints; i++) {
1082         if (env->breakpoints[i] == pc)
1083             return 0;
1084     }
1085
1086     if (env->nb_breakpoints >= MAX_BREAKPOINTS)
1087         return -1;
1088     env->breakpoints[env->nb_breakpoints++] = pc;
1089     
1090     breakpoint_invalidate(env, pc);
1091     return 0;
1092 #else
1093     return -1;
1094 #endif
1095 }
1096
1097 /* remove a breakpoint */
1098 int cpu_breakpoint_remove(CPUState *env, target_ulong pc)
1099 {
1100 #if defined(TARGET_I386) || defined(TARGET_PPC) || defined(TARGET_SPARC)
1101     int i;
1102     for(i = 0; i < env->nb_breakpoints; i++) {
1103         if (env->breakpoints[i] == pc)
1104             goto found;
1105     }
1106     return -1;
1107  found:
1108     memmove(&env->breakpoints[i], &env->breakpoints[i + 1],
1109             (env->nb_breakpoints - (i + 1)) * sizeof(env->breakpoints[0]));
1110     env->nb_breakpoints--;
1111
1112     breakpoint_invalidate(env, pc);
1113     return 0;
1114 #else
1115     return -1;
1116 #endif
1117 }
1118
1119 /* enable or disable single step mode. EXCP_DEBUG is returned by the
1120    CPU loop after each instruction */
1121 void cpu_single_step(CPUState *env, int enabled)
1122 {
1123 #if defined(TARGET_I386) || defined(TARGET_PPC) || defined(TARGET_SPARC)
1124     if (env->singlestep_enabled != enabled) {
1125         env->singlestep_enabled = enabled;
1126         /* must flush all the translated code to avoid inconsistancies */
1127         /* XXX: only flush what is necessary */
1128         tb_flush(env);
1129     }
1130 #endif
1131 }
1132
1133 /* enable or disable low levels log */
1134 void cpu_set_log(int log_flags)
1135 {
1136     loglevel = log_flags;
1137     if (loglevel && !logfile) {
1138         logfile = fopen(logfilename, "w");
1139         if (!logfile) {
1140             perror(logfilename);
1141             _exit(1);
1142         }
1143 #if !defined(CONFIG_SOFTMMU)
1144         /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
1145         {
1146             static uint8_t logfile_buf[4096];
1147             setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
1148         }
1149 #else
1150         setvbuf(logfile, NULL, _IOLBF, 0);
1151 #endif
1152     }
1153 }
1154
1155 void cpu_set_log_filename(const char *filename)
1156 {
1157     logfilename = strdup(filename);
1158 }
1159
1160 /* mask must never be zero, except for A20 change call */
1161 void cpu_interrupt(CPUState *env, int mask)
1162 {
1163     TranslationBlock *tb;
1164     static int interrupt_lock;
1165
1166     env->interrupt_request |= mask;
1167     /* if the cpu is currently executing code, we must unlink it and
1168        all the potentially executing TB */
1169     tb = env->current_tb;
1170     if (tb && !testandset(&interrupt_lock)) {
1171         env->current_tb = NULL;
1172         tb_reset_jump_recursive(tb);
1173         interrupt_lock = 0;
1174     }
1175 }
1176
1177 void cpu_reset_interrupt(CPUState *env, int mask)
1178 {
1179     env->interrupt_request &= ~mask;
1180 }
1181
1182 CPULogItem cpu_log_items[] = {
1183     { CPU_LOG_TB_OUT_ASM, "out_asm", 
1184       "show generated host assembly code for each compiled TB" },
1185     { CPU_LOG_TB_IN_ASM, "in_asm",
1186       "show target assembly code for each compiled TB" },
1187     { CPU_LOG_TB_OP, "op", 
1188       "show micro ops for each compiled TB (only usable if 'in_asm' used)" },
1189 #ifdef TARGET_I386
1190     { CPU_LOG_TB_OP_OPT, "op_opt",
1191       "show micro ops after optimization for each compiled TB" },
1192 #endif
1193     { CPU_LOG_INT, "int",
1194       "show interrupts/exceptions in short format" },
1195     { CPU_LOG_EXEC, "exec",
1196       "show trace before each executed TB (lots of logs)" },
1197     { CPU_LOG_TB_CPU, "cpu",
1198       "show CPU state before bloc translation" },
1199 #ifdef TARGET_I386
1200     { CPU_LOG_PCALL, "pcall",
1201       "show protected mode far calls/returns/exceptions" },
1202 #endif
1203 #ifdef DEBUG_IOPORT
1204     { CPU_LOG_IOPORT, "ioport",
1205       "show all i/o ports accesses" },
1206 #endif
1207     { 0, NULL, NULL },
1208 };
1209
1210 static int cmp1(const char *s1, int n, const char *s2)
1211 {
1212     if (strlen(s2) != n)
1213         return 0;
1214     return memcmp(s1, s2, n) == 0;
1215 }
1216       
1217 /* takes a comma separated list of log masks. Return 0 if error. */
1218 int cpu_str_to_log_mask(const char *str)
1219 {
1220     CPULogItem *item;
1221     int mask;
1222     const char *p, *p1;
1223
1224     p = str;
1225     mask = 0;
1226     for(;;) {
1227         p1 = strchr(p, ',');
1228         if (!p1)
1229             p1 = p + strlen(p);
1230         if(cmp1(p,p1-p,"all")) {
1231                 for(item = cpu_log_items; item->mask != 0; item++) {
1232                         mask |= item->mask;
1233                 }
1234         } else {
1235         for(item = cpu_log_items; item->mask != 0; item++) {
1236             if (cmp1(p, p1 - p, item->name))
1237                 goto found;
1238         }
1239         return 0;
1240         }
1241     found:
1242         mask |= item->mask;
1243         if (*p1 != ',')
1244             break;
1245         p = p1 + 1;
1246     }
1247     return mask;
1248 }
1249
1250 void cpu_abort(CPUState *env, const char *fmt, ...)
1251 {
1252     va_list ap;
1253
1254     va_start(ap, fmt);
1255     fprintf(stderr, "qemu: fatal: ");
1256     vfprintf(stderr, fmt, ap);
1257     fprintf(stderr, "\n");
1258 #ifdef TARGET_I386
1259     cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
1260 #else
1261     cpu_dump_state(env, stderr, fprintf, 0);
1262 #endif
1263     va_end(ap);
1264     abort();
1265 }
1266
1267 #if !defined(CONFIG_USER_ONLY)
1268
1269 /* NOTE: if flush_global is true, also flush global entries (not
1270    implemented yet) */
1271 void tlb_flush(CPUState *env, int flush_global)
1272 {
1273     int i;
1274
1275 #if defined(DEBUG_TLB)
1276     printf("tlb_flush:\n");
1277 #endif
1278     /* must reset current TB so that interrupts cannot modify the
1279        links while we are modifying them */
1280     env->current_tb = NULL;
1281
1282     for(i = 0; i < CPU_TLB_SIZE; i++) {
1283         env->tlb_read[0][i].address = -1;
1284         env->tlb_write[0][i].address = -1;
1285         env->tlb_read[1][i].address = -1;
1286         env->tlb_write[1][i].address = -1;
1287     }
1288
1289     virt_page_flush();
1290     memset (tb_hash, 0, CODE_GEN_HASH_SIZE * sizeof (void *));
1291
1292 #if !defined(CONFIG_SOFTMMU)
1293     munmap((void *)MMAP_AREA_START, MMAP_AREA_END - MMAP_AREA_START);
1294 #endif
1295 }
1296
1297 static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
1298 {
1299     if (addr == (tlb_entry->address & 
1300                  (TARGET_PAGE_MASK | TLB_INVALID_MASK)))
1301         tlb_entry->address = -1;
1302 }
1303
1304 void tlb_flush_page(CPUState *env, target_ulong addr)
1305 {
1306     int i, n;
1307     VirtPageDesc *vp;
1308     PageDesc *p;
1309     TranslationBlock *tb;
1310
1311 #if defined(DEBUG_TLB)
1312     printf("tlb_flush_page: 0x%08x\n", addr);
1313 #endif
1314     /* must reset current TB so that interrupts cannot modify the
1315        links while we are modifying them */
1316     env->current_tb = NULL;
1317
1318     addr &= TARGET_PAGE_MASK;
1319     i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1320     tlb_flush_entry(&env->tlb_read[0][i], addr);
1321     tlb_flush_entry(&env->tlb_write[0][i], addr);
1322     tlb_flush_entry(&env->tlb_read[1][i], addr);
1323     tlb_flush_entry(&env->tlb_write[1][i], addr);
1324
1325     /* remove from the virtual pc hash table all the TB at this
1326        virtual address */
1327     
1328     vp = virt_page_find(addr >> TARGET_PAGE_BITS);
1329     if (vp && vp->valid_tag == virt_valid_tag) {
1330         p = page_find(vp->phys_addr >> TARGET_PAGE_BITS);
1331         if (p) {
1332             /* we remove all the links to the TBs in this virtual page */
1333             tb = p->first_tb;
1334             while (tb != NULL) {
1335                 n = (long)tb & 3;
1336                 tb = (TranslationBlock *)((long)tb & ~3);
1337                 if ((tb->pc & TARGET_PAGE_MASK) == addr ||
1338                     ((tb->pc + tb->size - 1) & TARGET_PAGE_MASK) == addr) {
1339                     tb_invalidate(tb);
1340                 }
1341                 tb = tb->page_next[n];
1342             }
1343         }
1344         vp->valid_tag = 0;
1345     }
1346
1347 #if !defined(CONFIG_SOFTMMU)
1348     if (addr < MMAP_AREA_END)
1349         munmap((void *)addr, TARGET_PAGE_SIZE);
1350 #endif
1351 }
1352
1353 static inline void tlb_protect_code1(CPUTLBEntry *tlb_entry, target_ulong addr)
1354 {
1355     if (addr == (tlb_entry->address & 
1356                  (TARGET_PAGE_MASK | TLB_INVALID_MASK)) &&
1357         (tlb_entry->address & ~TARGET_PAGE_MASK) != IO_MEM_CODE &&
1358         (tlb_entry->address & ~TARGET_PAGE_MASK) != IO_MEM_ROM) {
1359         tlb_entry->address = (tlb_entry->address & TARGET_PAGE_MASK) | IO_MEM_CODE;
1360     }
1361 }
1362
1363 /* update the TLBs so that writes to code in the virtual page 'addr'
1364    can be detected */
1365 static void tlb_protect_code(CPUState *env, target_ulong addr)
1366 {
1367     int i;
1368
1369     addr &= TARGET_PAGE_MASK;
1370     i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1371     tlb_protect_code1(&env->tlb_write[0][i], addr);
1372     tlb_protect_code1(&env->tlb_write[1][i], addr);
1373 #if !defined(CONFIG_SOFTMMU)
1374     /* NOTE: as we generated the code for this page, it is already at
1375        least readable */
1376     if (addr < MMAP_AREA_END)
1377         mprotect((void *)addr, TARGET_PAGE_SIZE, PROT_READ);
1378 #endif
1379 }
1380
1381 static inline void tlb_unprotect_code2(CPUTLBEntry *tlb_entry, 
1382                                        unsigned long phys_addr)
1383 {
1384     if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_CODE &&
1385         ((tlb_entry->address & TARGET_PAGE_MASK) + tlb_entry->addend) == phys_addr) {
1386         tlb_entry->address = (tlb_entry->address & TARGET_PAGE_MASK) | IO_MEM_NOTDIRTY;
1387     }
1388 }
1389
1390 /* update the TLB so that writes in physical page 'phys_addr' are no longer
1391    tested self modifying code */
1392 static void tlb_unprotect_code_phys(CPUState *env, unsigned long phys_addr, target_ulong vaddr)
1393 {
1394     int i;
1395
1396     phys_addr &= TARGET_PAGE_MASK;
1397     phys_addr += (long)phys_ram_base;
1398     i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1399     tlb_unprotect_code2(&env->tlb_write[0][i], phys_addr);
1400     tlb_unprotect_code2(&env->tlb_write[1][i], phys_addr);
1401 }
1402
1403 static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, 
1404                                          unsigned long start, unsigned long length)
1405 {
1406     unsigned long addr;
1407     if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
1408         addr = (tlb_entry->address & TARGET_PAGE_MASK) + tlb_entry->addend;
1409         if ((addr - start) < length) {
1410             tlb_entry->address = (tlb_entry->address & TARGET_PAGE_MASK) | IO_MEM_NOTDIRTY;
1411         }
1412     }
1413 }
1414
1415 void cpu_physical_memory_reset_dirty(target_ulong start, target_ulong end)
1416 {
1417     CPUState *env;
1418     unsigned long length, start1;
1419     int i;
1420
1421     start &= TARGET_PAGE_MASK;
1422     end = TARGET_PAGE_ALIGN(end);
1423
1424     length = end - start;
1425     if (length == 0)
1426         return;
1427     memset(phys_ram_dirty + (start >> TARGET_PAGE_BITS), 0, length >> TARGET_PAGE_BITS);
1428
1429     env = cpu_single_env;
1430     /* we modify the TLB cache so that the dirty bit will be set again
1431        when accessing the range */
1432     start1 = start + (unsigned long)phys_ram_base;
1433     for(i = 0; i < CPU_TLB_SIZE; i++)
1434         tlb_reset_dirty_range(&env->tlb_write[0][i], start1, length);
1435     for(i = 0; i < CPU_TLB_SIZE; i++)
1436         tlb_reset_dirty_range(&env->tlb_write[1][i], start1, length);
1437
1438 #if !defined(CONFIG_SOFTMMU)
1439     /* XXX: this is expensive */
1440     {
1441         VirtPageDesc *p;
1442         int j;
1443         target_ulong addr;
1444
1445         for(i = 0; i < L1_SIZE; i++) {
1446             p = l1_virt_map[i];
1447             if (p) {
1448                 addr = i << (TARGET_PAGE_BITS + L2_BITS);
1449                 for(j = 0; j < L2_SIZE; j++) {
1450                     if (p->valid_tag == virt_valid_tag &&
1451                         p->phys_addr >= start && p->phys_addr < end &&
1452                         (p->prot & PROT_WRITE)) {
1453                         if (addr < MMAP_AREA_END) {
1454                             mprotect((void *)addr, TARGET_PAGE_SIZE, 
1455                                      p->prot & ~PROT_WRITE);
1456                         }
1457                     }
1458                     addr += TARGET_PAGE_SIZE;
1459                     p++;
1460                 }
1461             }
1462         }
1463     }
1464 #endif
1465 }
1466
1467 static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, 
1468                                     unsigned long start)
1469 {
1470     unsigned long addr;
1471     if ((tlb_entry->address & ~TARGET_PAGE_MASK) == IO_MEM_NOTDIRTY) {
1472         addr = (tlb_entry->address & TARGET_PAGE_MASK) + tlb_entry->addend;
1473         if (addr == start) {
1474             tlb_entry->address = (tlb_entry->address & TARGET_PAGE_MASK) | IO_MEM_RAM;
1475         }
1476     }
1477 }
1478
1479 /* update the TLB corresponding to virtual page vaddr and phys addr
1480    addr so that it is no longer dirty */
1481 static inline void tlb_set_dirty(unsigned long addr, target_ulong vaddr)
1482 {
1483     CPUState *env = cpu_single_env;
1484     int i;
1485
1486     phys_ram_dirty[(addr - (unsigned long)phys_ram_base) >> TARGET_PAGE_BITS] = 1;
1487
1488     addr &= TARGET_PAGE_MASK;
1489     i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
1490     tlb_set_dirty1(&env->tlb_write[0][i], addr);
1491     tlb_set_dirty1(&env->tlb_write[1][i], addr);
1492 }
1493
1494 /* add a new TLB entry. At most one entry for a given virtual address
1495    is permitted. Return 0 if OK or 2 if the page could not be mapped
1496    (can only happen in non SOFTMMU mode for I/O pages or pages
1497    conflicting with the host address space). */
1498 int tlb_set_page(CPUState *env, target_ulong vaddr, 
1499                  target_phys_addr_t paddr, int prot, 
1500                  int is_user, int is_softmmu)
1501 {
1502     PhysPageDesc *p;
1503     unsigned long pd;
1504     TranslationBlock *first_tb;
1505     unsigned int index;
1506     target_ulong address;
1507     unsigned long addend;
1508     int ret;
1509
1510     p = phys_page_find(paddr >> TARGET_PAGE_BITS);
1511     first_tb = NULL;
1512     if (!p) {
1513         pd = IO_MEM_UNASSIGNED;
1514     } else {
1515         PageDesc *p1;
1516         pd = p->phys_offset;
1517         if ((pd & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
1518             /* NOTE: we also allocate the page at this stage */
1519             p1 = page_find_alloc(pd >> TARGET_PAGE_BITS);
1520             first_tb = p1->first_tb;
1521         }
1522     }
1523 #if defined(DEBUG_TLB)
1524     printf("tlb_set_page: vaddr=0x%08x paddr=0x%08x prot=%x u=%d c=%d smmu=%d pd=0x%08x\n",
1525            vaddr, paddr, prot, is_user, (first_tb != NULL), is_softmmu, pd);
1526 #endif
1527
1528     ret = 0;
1529 #if !defined(CONFIG_SOFTMMU)
1530     if (is_softmmu) 
1531 #endif
1532     {
1533         if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
1534             /* IO memory case */
1535             address = vaddr | pd;
1536             addend = paddr;
1537         } else {
1538             /* standard memory */
1539             address = vaddr;
1540             addend = (unsigned long)phys_ram_base + (pd & TARGET_PAGE_MASK);
1541         }
1542         
1543         index = (vaddr >> 12) & (CPU_TLB_SIZE - 1);
1544         addend -= vaddr;
1545         if (prot & PAGE_READ) {
1546             env->tlb_read[is_user][index].address = address;
1547             env->tlb_read[is_user][index].addend = addend;
1548         } else {
1549             env->tlb_read[is_user][index].address = -1;
1550             env->tlb_read[is_user][index].addend = -1;
1551         }
1552         if (prot & PAGE_WRITE) {
1553             if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM) {
1554                 /* ROM: access is ignored (same as unassigned) */
1555                 env->tlb_write[is_user][index].address = vaddr | IO_MEM_ROM;
1556                 env->tlb_write[is_user][index].addend = addend;
1557             } else 
1558                 /* XXX: the PowerPC code seems not ready to handle
1559                    self modifying code with DCBI */
1560 #if defined(TARGET_HAS_SMC) || 1
1561             if (first_tb) {
1562                 /* if code is present, we use a specific memory
1563                    handler. It works only for physical memory access */
1564                 env->tlb_write[is_user][index].address = vaddr | IO_MEM_CODE;
1565                 env->tlb_write[is_user][index].addend = addend;
1566             } else 
1567 #endif
1568             if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM && 
1569                        !cpu_physical_memory_is_dirty(pd)) {
1570                 env->tlb_write[is_user][index].address = vaddr | IO_MEM_NOTDIRTY;
1571                 env->tlb_write[is_user][index].addend = addend;
1572             } else {
1573                 env->tlb_write[is_user][index].address = address;
1574                 env->tlb_write[is_user][index].addend = addend;
1575             }
1576         } else {
1577             env->tlb_write[is_user][index].address = -1;
1578             env->tlb_write[is_user][index].addend = -1;
1579         }
1580     }
1581 #if !defined(CONFIG_SOFTMMU)
1582     else {
1583         if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
1584             /* IO access: no mapping is done as it will be handled by the
1585                soft MMU */
1586             if (!(env->hflags & HF_SOFTMMU_MASK))
1587                 ret = 2;
1588         } else {
1589             void *map_addr;
1590
1591             if (vaddr >= MMAP_AREA_END) {
1592                 ret = 2;
1593             } else {
1594                 if (prot & PROT_WRITE) {
1595                     if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM || 
1596 #if defined(TARGET_HAS_SMC) || 1
1597                         first_tb ||
1598 #endif
1599                         ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM && 
1600                          !cpu_physical_memory_is_dirty(pd))) {
1601                         /* ROM: we do as if code was inside */
1602                         /* if code is present, we only map as read only and save the
1603                            original mapping */
1604                         VirtPageDesc *vp;
1605                         
1606                         vp = virt_page_find_alloc(vaddr >> TARGET_PAGE_BITS);
1607                         vp->phys_addr = pd;
1608                         vp->prot = prot;
1609                         vp->valid_tag = virt_valid_tag;
1610                         prot &= ~PAGE_WRITE;
1611                     }
1612                 }
1613                 map_addr = mmap((void *)vaddr, TARGET_PAGE_SIZE, prot, 
1614                                 MAP_SHARED | MAP_FIXED, phys_ram_fd, (pd & TARGET_PAGE_MASK));
1615                 if (map_addr == MAP_FAILED) {
1616                     cpu_abort(env, "mmap failed when mapped physical address 0x%08x to virtual address 0x%08x\n",
1617                               paddr, vaddr);
1618                 }
1619             }
1620         }
1621     }
1622 #endif
1623     return ret;
1624 }
1625
1626 /* called from signal handler: invalidate the code and unprotect the
1627    page. Return TRUE if the fault was succesfully handled. */
1628 int page_unprotect(unsigned long addr, unsigned long pc, void *puc)
1629 {
1630 #if !defined(CONFIG_SOFTMMU)
1631     VirtPageDesc *vp;
1632
1633 #if defined(DEBUG_TLB)
1634     printf("page_unprotect: addr=0x%08x\n", addr);
1635 #endif
1636     addr &= TARGET_PAGE_MASK;
1637
1638     /* if it is not mapped, no need to worry here */
1639     if (addr >= MMAP_AREA_END)
1640         return 0;
1641     vp = virt_page_find(addr >> TARGET_PAGE_BITS);
1642     if (!vp)
1643         return 0;
1644     /* NOTE: in this case, validate_tag is _not_ tested as it
1645        validates only the code TLB */
1646     if (vp->valid_tag != virt_valid_tag)
1647         return 0;
1648     if (!(vp->prot & PAGE_WRITE))
1649         return 0;
1650 #if defined(DEBUG_TLB)
1651     printf("page_unprotect: addr=0x%08x phys_addr=0x%08x prot=%x\n", 
1652            addr, vp->phys_addr, vp->prot);
1653 #endif
1654     if (mprotect((void *)addr, TARGET_PAGE_SIZE, vp->prot) < 0)
1655         cpu_abort(cpu_single_env, "error mprotect addr=0x%lx prot=%d\n",
1656                   (unsigned long)addr, vp->prot);
1657     /* set the dirty bit */
1658     phys_ram_dirty[vp->phys_addr >> TARGET_PAGE_BITS] = 1;
1659     /* flush the code inside */
1660     tb_invalidate_phys_page(vp->phys_addr, pc, puc);
1661     return 1;
1662 #else
1663     return 0;
1664 #endif
1665 }
1666
1667 #else
1668
1669 void tlb_flush(CPUState *env, int flush_global)
1670 {
1671 }
1672
1673 void tlb_flush_page(CPUState *env, target_ulong addr)
1674 {
1675 }
1676
1677 int tlb_set_page(CPUState *env, target_ulong vaddr, 
1678                  target_phys_addr_t paddr, int prot, 
1679                  int is_user, int is_softmmu)
1680 {
1681     return 0;
1682 }
1683
1684 /* dump memory mappings */
1685 void page_dump(FILE *f)
1686 {
1687     unsigned long start, end;
1688     int i, j, prot, prot1;
1689     PageDesc *p;
1690
1691     fprintf(f, "%-8s %-8s %-8s %s\n",
1692             "start", "end", "size", "prot");
1693     start = -1;
1694     end = -1;
1695     prot = 0;
1696     for(i = 0; i <= L1_SIZE; i++) {
1697         if (i < L1_SIZE)
1698             p = l1_map[i];
1699         else
1700             p = NULL;
1701         for(j = 0;j < L2_SIZE; j++) {
1702             if (!p)
1703                 prot1 = 0;
1704             else
1705                 prot1 = p[j].flags;
1706             if (prot1 != prot) {
1707                 end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
1708                 if (start != -1) {
1709                     fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
1710                             start, end, end - start, 
1711                             prot & PAGE_READ ? 'r' : '-',
1712                             prot & PAGE_WRITE ? 'w' : '-',
1713                             prot & PAGE_EXEC ? 'x' : '-');
1714                 }
1715                 if (prot1 != 0)
1716                     start = end;
1717                 else
1718                     start = -1;
1719                 prot = prot1;
1720             }
1721             if (!p)
1722                 break;
1723         }
1724     }
1725 }
1726
1727 int page_get_flags(unsigned long address)
1728 {
1729     PageDesc *p;
1730
1731     p = page_find(address >> TARGET_PAGE_BITS);
1732     if (!p)
1733         return 0;
1734     return p->flags;
1735 }
1736
1737 /* modify the flags of a page and invalidate the code if
1738    necessary. The flag PAGE_WRITE_ORG is positionned automatically
1739    depending on PAGE_WRITE */
1740 void page_set_flags(unsigned long start, unsigned long end, int flags)
1741 {
1742     PageDesc *p;
1743     unsigned long addr;
1744
1745     start = start & TARGET_PAGE_MASK;
1746     end = TARGET_PAGE_ALIGN(end);
1747     if (flags & PAGE_WRITE)
1748         flags |= PAGE_WRITE_ORG;
1749     spin_lock(&tb_lock);
1750     for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1751         p = page_find_alloc(addr >> TARGET_PAGE_BITS);
1752         /* if the write protection is set, then we invalidate the code
1753            inside */
1754         if (!(p->flags & PAGE_WRITE) && 
1755             (flags & PAGE_WRITE) &&
1756             p->first_tb) {
1757             tb_invalidate_phys_page(addr, 0, NULL);
1758         }
1759         p->flags = flags;
1760     }
1761     spin_unlock(&tb_lock);
1762 }
1763
1764 /* called from signal handler: invalidate the code and unprotect the
1765    page. Return TRUE if the fault was succesfully handled. */
1766 int page_unprotect(unsigned long address, unsigned long pc, void *puc)
1767 {
1768     unsigned int page_index, prot, pindex;
1769     PageDesc *p, *p1;
1770     unsigned long host_start, host_end, addr;
1771
1772     host_start = address & qemu_host_page_mask;
1773     page_index = host_start >> TARGET_PAGE_BITS;
1774     p1 = page_find(page_index);
1775     if (!p1)
1776         return 0;
1777     host_end = host_start + qemu_host_page_size;
1778     p = p1;
1779     prot = 0;
1780     for(addr = host_start;addr < host_end; addr += TARGET_PAGE_SIZE) {
1781         prot |= p->flags;
1782         p++;
1783     }
1784     /* if the page was really writable, then we change its
1785        protection back to writable */
1786     if (prot & PAGE_WRITE_ORG) {
1787         pindex = (address - host_start) >> TARGET_PAGE_BITS;
1788         if (!(p1[pindex].flags & PAGE_WRITE)) {
1789             mprotect((void *)host_start, qemu_host_page_size, 
1790                      (prot & PAGE_BITS) | PAGE_WRITE);
1791             p1[pindex].flags |= PAGE_WRITE;
1792             /* and since the content will be modified, we must invalidate
1793                the corresponding translated code. */
1794             tb_invalidate_phys_page(address, pc, puc);
1795 #ifdef DEBUG_TB_CHECK
1796             tb_invalidate_check(address);
1797 #endif
1798             return 1;
1799         }
1800     }
1801     return 0;
1802 }
1803
1804 /* call this function when system calls directly modify a memory area */
1805 void page_unprotect_range(uint8_t *data, unsigned long data_size)
1806 {
1807     unsigned long start, end, addr;
1808
1809     start = (unsigned long)data;
1810     end = start + data_size;
1811     start &= TARGET_PAGE_MASK;
1812     end = TARGET_PAGE_ALIGN(end);
1813     for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
1814         page_unprotect(addr, 0, NULL);
1815     }
1816 }
1817
1818 static inline void tlb_set_dirty(unsigned long addr, target_ulong vaddr)
1819 {
1820 }
1821 #endif /* defined(CONFIG_USER_ONLY) */
1822
1823 /* register physical memory. 'size' must be a multiple of the target
1824    page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
1825    io memory page */
1826 void cpu_register_physical_memory(target_phys_addr_t start_addr, 
1827                                   unsigned long size,
1828                                   unsigned long phys_offset)
1829 {
1830     unsigned long addr, end_addr;
1831     PhysPageDesc *p;
1832
1833     size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
1834     end_addr = start_addr + size;
1835     for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
1836         p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS);
1837         p->phys_offset = phys_offset;
1838         if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM)
1839             phys_offset += TARGET_PAGE_SIZE;
1840     }
1841 }
1842
1843 static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
1844 {
1845     return 0;
1846 }
1847
1848 static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
1849 {
1850 }
1851
1852 static CPUReadMemoryFunc *unassigned_mem_read[3] = {
1853     unassigned_mem_readb,
1854     unassigned_mem_readb,
1855     unassigned_mem_readb,
1856 };
1857
1858 static CPUWriteMemoryFunc *unassigned_mem_write[3] = {
1859     unassigned_mem_writeb,
1860     unassigned_mem_writeb,
1861     unassigned_mem_writeb,
1862 };
1863
1864 /* self modifying code support in soft mmu mode : writing to a page
1865    containing code comes to these functions */
1866
1867 static void code_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
1868 {
1869     unsigned long phys_addr;
1870
1871     phys_addr = addr - (unsigned long)phys_ram_base;
1872 #if !defined(CONFIG_USER_ONLY)
1873     tb_invalidate_phys_page_fast(phys_addr, 1);
1874 #endif
1875     stb_raw((uint8_t *)addr, val);
1876     phys_ram_dirty[phys_addr >> TARGET_PAGE_BITS] = 1;
1877 }
1878
1879 static void code_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
1880 {
1881     unsigned long phys_addr;
1882
1883     phys_addr = addr - (unsigned long)phys_ram_base;
1884 #if !defined(CONFIG_USER_ONLY)
1885     tb_invalidate_phys_page_fast(phys_addr, 2);
1886 #endif
1887     stw_raw((uint8_t *)addr, val);
1888     phys_ram_dirty[phys_addr >> TARGET_PAGE_BITS] = 1;
1889 }
1890
1891 static void code_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
1892 {
1893     unsigned long phys_addr;
1894
1895     phys_addr = addr - (unsigned long)phys_ram_base;
1896 #if !defined(CONFIG_USER_ONLY)
1897     tb_invalidate_phys_page_fast(phys_addr, 4);
1898 #endif
1899     stl_raw((uint8_t *)addr, val);
1900     phys_ram_dirty[phys_addr >> TARGET_PAGE_BITS] = 1;
1901 }
1902
1903 static CPUReadMemoryFunc *code_mem_read[3] = {
1904     NULL, /* never used */
1905     NULL, /* never used */
1906     NULL, /* never used */
1907 };
1908
1909 static CPUWriteMemoryFunc *code_mem_write[3] = {
1910     code_mem_writeb,
1911     code_mem_writew,
1912     code_mem_writel,
1913 };
1914
1915 static void notdirty_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
1916 {
1917     stb_raw((uint8_t *)addr, val);
1918     tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr);
1919 }
1920
1921 static void notdirty_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
1922 {
1923     stw_raw((uint8_t *)addr, val);
1924     tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr);
1925 }
1926
1927 static void notdirty_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
1928 {
1929     stl_raw((uint8_t *)addr, val);
1930     tlb_set_dirty(addr, cpu_single_env->mem_write_vaddr);
1931 }
1932
1933 static CPUWriteMemoryFunc *notdirty_mem_write[3] = {
1934     notdirty_mem_writeb,
1935     notdirty_mem_writew,
1936     notdirty_mem_writel,
1937 };
1938
1939 static void io_mem_init(void)
1940 {
1941     cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, code_mem_read, unassigned_mem_write, NULL);
1942     cpu_register_io_memory(IO_MEM_UNASSIGNED >> IO_MEM_SHIFT, unassigned_mem_read, unassigned_mem_write, NULL);
1943     cpu_register_io_memory(IO_MEM_CODE >> IO_MEM_SHIFT, code_mem_read, code_mem_write, NULL);
1944     cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, code_mem_read, notdirty_mem_write, NULL);
1945     io_mem_nb = 5;
1946
1947     /* alloc dirty bits array */
1948     phys_ram_dirty = qemu_malloc(phys_ram_size >> TARGET_PAGE_BITS);
1949 }
1950
1951 /* mem_read and mem_write are arrays of functions containing the
1952    function to access byte (index 0), word (index 1) and dword (index
1953    2). All functions must be supplied. If io_index is non zero, the
1954    corresponding io zone is modified. If it is zero, a new io zone is
1955    allocated. The return value can be used with
1956    cpu_register_physical_memory(). (-1) is returned if error. */
1957 int cpu_register_io_memory(int io_index,
1958                            CPUReadMemoryFunc **mem_read,
1959                            CPUWriteMemoryFunc **mem_write,
1960                            void *opaque)
1961 {
1962     int i;
1963
1964     if (io_index <= 0) {
1965         if (io_index >= IO_MEM_NB_ENTRIES)
1966             return -1;
1967         io_index = io_mem_nb++;
1968     } else {
1969         if (io_index >= IO_MEM_NB_ENTRIES)
1970             return -1;
1971     }
1972     
1973     for(i = 0;i < 3; i++) {
1974         io_mem_read[io_index][i] = mem_read[i];
1975         io_mem_write[io_index][i] = mem_write[i];
1976     }
1977     io_mem_opaque[io_index] = opaque;
1978     return io_index << IO_MEM_SHIFT;
1979 }
1980
1981 CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index)
1982 {
1983     return io_mem_write[io_index >> IO_MEM_SHIFT];
1984 }
1985
1986 CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index)
1987 {
1988     return io_mem_read[io_index >> IO_MEM_SHIFT];
1989 }
1990
1991 /* physical memory access (slow version, mainly for debug) */
1992 #if defined(CONFIG_USER_ONLY)
1993 void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, 
1994                             int len, int is_write)
1995 {
1996     int l, flags;
1997     target_ulong page;
1998
1999     while (len > 0) {
2000         page = addr & TARGET_PAGE_MASK;
2001         l = (page + TARGET_PAGE_SIZE) - addr;
2002         if (l > len)
2003             l = len;
2004         flags = page_get_flags(page);
2005         if (!(flags & PAGE_VALID))
2006             return;
2007         if (is_write) {
2008             if (!(flags & PAGE_WRITE))
2009                 return;
2010             memcpy((uint8_t *)addr, buf, len);
2011         } else {
2012             if (!(flags & PAGE_READ))
2013                 return;
2014             memcpy(buf, (uint8_t *)addr, len);
2015         }
2016         len -= l;
2017         buf += l;
2018         addr += l;
2019     }
2020 }
2021 #else
2022 void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, 
2023                             int len, int is_write)
2024 {
2025     int l, io_index;
2026     uint8_t *ptr;
2027     uint32_t val;
2028     target_phys_addr_t page;
2029     unsigned long pd;
2030     PhysPageDesc *p;
2031     
2032     while (len > 0) {
2033         page = addr & TARGET_PAGE_MASK;
2034         l = (page + TARGET_PAGE_SIZE) - addr;
2035         if (l > len)
2036             l = len;
2037         p = phys_page_find(page >> TARGET_PAGE_BITS);
2038         if (!p) {
2039             pd = IO_MEM_UNASSIGNED;
2040         } else {
2041             pd = p->phys_offset;
2042         }
2043         
2044         if (is_write) {
2045             if ((pd & ~TARGET_PAGE_MASK) != 0) {
2046                 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2047                 if (l >= 4 && ((addr & 3) == 0)) {
2048                     /* 32 bit read access */
2049                     val = ldl_raw(buf);
2050                     io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
2051                     l = 4;
2052                 } else if (l >= 2 && ((addr & 1) == 0)) {
2053                     /* 16 bit read access */
2054                     val = lduw_raw(buf);
2055                     io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
2056                     l = 2;
2057                 } else {
2058                     /* 8 bit access */
2059                     val = ldub_raw(buf);
2060                     io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val);
2061                     l = 1;
2062                 }
2063             } else {
2064                 unsigned long addr1;
2065                 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
2066                 /* RAM case */
2067                 ptr = phys_ram_base + addr1;
2068                 memcpy(ptr, buf, l);
2069                 /* invalidate code */
2070                 tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
2071                 /* set dirty bit */
2072                 phys_ram_dirty[page >> TARGET_PAGE_BITS] = 1;                
2073             }
2074         } else {
2075             if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
2076                 (pd & ~TARGET_PAGE_MASK) != IO_MEM_CODE) {
2077                 /* I/O case */
2078                 io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
2079                 if (l >= 4 && ((addr & 3) == 0)) {
2080                     /* 32 bit read access */
2081                     val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
2082                     stl_raw(buf, val);
2083                     l = 4;
2084                 } else if (l >= 2 && ((addr & 1) == 0)) {
2085                     /* 16 bit read access */
2086                     val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
2087                     stw_raw(buf, val);
2088                     l = 2;
2089                 } else {
2090                     /* 8 bit access */
2091                     val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr);
2092                     stb_raw(buf, val);
2093                     l = 1;
2094                 }
2095             } else {
2096                 /* RAM case */
2097                 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
2098                     (addr & ~TARGET_PAGE_MASK);
2099                 memcpy(buf, ptr, l);
2100             }
2101         }
2102         len -= l;
2103         buf += l;
2104         addr += l;
2105     }
2106 }
2107 #endif
2108
2109 /* virtual memory access for debug */
2110 int cpu_memory_rw_debug(CPUState *env, target_ulong addr, 
2111                         uint8_t *buf, int len, int is_write)
2112 {
2113     int l;
2114     target_ulong page, phys_addr;
2115
2116     while (len > 0) {
2117         page = addr & TARGET_PAGE_MASK;
2118         phys_addr = cpu_get_phys_page_debug(env, page);
2119         /* if no physical page mapped, return an error */
2120         if (phys_addr == -1)
2121             return -1;
2122         l = (page + TARGET_PAGE_SIZE) - addr;
2123         if (l > len)
2124             l = len;
2125         cpu_physical_memory_rw(phys_addr + (addr & ~TARGET_PAGE_MASK), 
2126                                buf, l, is_write);
2127         len -= l;
2128         buf += l;
2129         addr += l;
2130     }
2131     return 0;
2132 }
2133
2134 #if !defined(CONFIG_USER_ONLY) 
2135
2136 #define MMUSUFFIX _cmmu
2137 #define GETPC() NULL
2138 #define env cpu_single_env
2139 #define SOFTMMU_CODE_ACCESS
2140
2141 #define SHIFT 0
2142 #include "softmmu_template.h"
2143
2144 #define SHIFT 1
2145 #include "softmmu_template.h"
2146
2147 #define SHIFT 2
2148 #include "softmmu_template.h"
2149
2150 #define SHIFT 3
2151 #include "softmmu_template.h"
2152
2153 #undef env
2154
2155 #endif