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