Commit 54936004fddc52c321cb3f9a9a51140e782bed5d

Authored by bellard
1 parent 74c95119

mmap emulation


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@158 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile
... ... @@ -58,11 +58,11 @@ LDFLAGS+=-p
58 58 main.o: CFLAGS+=-p
59 59 endif
60 60  
61   -OBJS= elfload.o main.o syscall.o signal.o vm86.o path.o
  61 +OBJS= elfload.o main.o syscall.o mmap.o signal.o vm86.o path.o
62 62 SRCS:= $(OBJS:.o=.c)
63 63 OBJS+= libqemu.a
64 64  
65   -LIBOBJS+=thunk.o translate-i386.o op-i386.o exec-i386.o
  65 +LIBOBJS+=thunk.o translate-i386.o op-i386.o exec-i386.o exec.o
66 66 # NOTE: the disassembler code is only needed for debugging
67 67 LIBOBJS+=disas.o ppc-dis.o i386-dis.o alpha-dis.o dis-buf.o
68 68  
... ...
cpu-i386.h
... ... @@ -431,6 +431,30 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
431 431 #define X86_DUMP_CCOP 0x0002 /* dump qemu flag cache */
432 432 void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags);
433 433  
  434 +/* page related stuff */
  435 +#define TARGET_PAGE_BITS 12
  436 +#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
  437 +#define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1)
  438 +#define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK)
  439 +
  440 +extern unsigned long real_host_page_size;
  441 +extern unsigned long host_page_bits;
  442 +extern unsigned long host_page_size;
  443 +extern unsigned long host_page_mask;
  444 +
  445 +#define HOST_PAGE_ALIGN(addr) (((addr) + host_page_size - 1) & host_page_mask)
  446 +
  447 +/* same as PROT_xxx */
  448 +#define PAGE_READ 0x0001
  449 +#define PAGE_WRITE 0x0002
  450 +#define PAGE_EXEC 0x0004
  451 +#define PAGE_BITS (PAGE_READ | PAGE_WRITE | PAGE_EXEC)
  452 +#define PAGE_VALID 0x0008
  453 +
  454 +void page_dump(FILE *f);
  455 +int page_get_flags(unsigned long address);
  456 +void page_set_flags(unsigned long start, unsigned long end, int flags);
  457 +
434 458 /* internal functions */
435 459  
436 460 #define GEN_FLAG_CODE32_SHIFT 0
... ... @@ -446,5 +470,6 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
446 470 int *gen_code_size_ptr,
447 471 uint8_t *pc_start, uint8_t *cs_base, int flags);
448 472 void cpu_x86_tblocks_init(void);
  473 +void page_init(void);
449 474  
450 475 #endif /* CPU_I386_H */
... ...
exec.c 0 → 100644
  1 +/*
  2 + * virtual page mapping
  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 <stdlib.h>
  21 +#include <stdio.h>
  22 +#include <stdarg.h>
  23 +#include <string.h>
  24 +#include <errno.h>
  25 +#include <unistd.h>
  26 +#include <inttypes.h>
  27 +
  28 +#include "cpu-i386.h"
  29 +
  30 +/* XXX: pack the flags in the low bits of the pointer ? */
  31 +typedef struct PageDesc {
  32 + struct TranslationBlock *first_tb;
  33 + unsigned long flags;
  34 +} PageDesc;
  35 +
  36 +#define L2_BITS 10
  37 +#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
  38 +
  39 +#define L1_SIZE (1 << L1_BITS)
  40 +#define L2_SIZE (1 << L2_BITS)
  41 +
  42 +unsigned long real_host_page_size;
  43 +unsigned long host_page_bits;
  44 +unsigned long host_page_size;
  45 +unsigned long host_page_mask;
  46 +
  47 +static PageDesc *l1_map[L1_SIZE];
  48 +
  49 +void page_init(void)
  50 +{
  51 + /* NOTE: we can always suppose that host_page_size >=
  52 + TARGET_PAGE_SIZE */
  53 + real_host_page_size = getpagesize();
  54 + if (host_page_size == 0)
  55 + host_page_size = real_host_page_size;
  56 + if (host_page_size < TARGET_PAGE_SIZE)
  57 + host_page_size = TARGET_PAGE_SIZE;
  58 + host_page_bits = 0;
  59 + while ((1 << host_page_bits) < host_page_size)
  60 + host_page_bits++;
  61 + host_page_mask = ~(host_page_size - 1);
  62 +}
  63 +
  64 +/* dump memory mappings */
  65 +void page_dump(FILE *f)
  66 +{
  67 + unsigned long start, end;
  68 + int i, j, prot, prot1;
  69 + PageDesc *p;
  70 +
  71 + fprintf(f, "%-8s %-8s %-8s %s\n",
  72 + "start", "end", "size", "prot");
  73 + start = -1;
  74 + end = -1;
  75 + prot = 0;
  76 + for(i = 0; i <= L1_SIZE; i++) {
  77 + if (i < L1_SIZE)
  78 + p = l1_map[i];
  79 + else
  80 + p = NULL;
  81 + for(j = 0;j < L2_SIZE; j++) {
  82 + if (!p)
  83 + prot1 = 0;
  84 + else
  85 + prot1 = p[j].flags;
  86 + if (prot1 != prot) {
  87 + end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
  88 + if (start != -1) {
  89 + fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
  90 + start, end, end - start,
  91 + prot & PAGE_READ ? 'r' : '-',
  92 + prot & PAGE_WRITE ? 'w' : '-',
  93 + prot & PAGE_EXEC ? 'x' : '-');
  94 + }
  95 + if (prot1 != 0)
  96 + start = end;
  97 + else
  98 + start = -1;
  99 + prot = prot1;
  100 + }
  101 + if (!p)
  102 + break;
  103 + }
  104 + }
  105 +}
  106 +
  107 +
  108 +static inline PageDesc *page_find_alloc(unsigned long address)
  109 +{
  110 + unsigned int index;
  111 + PageDesc **lp, *p;
  112 +
  113 + index = address >> TARGET_PAGE_BITS;
  114 + lp = &l1_map[index >> L2_BITS];
  115 + p = *lp;
  116 + if (!p) {
  117 + /* allocate if not found */
  118 + p = malloc(sizeof(PageDesc) * L2_SIZE);
  119 + memset(p, 0, sizeof(sizeof(PageDesc) * L2_SIZE));
  120 + *lp = p;
  121 + }
  122 + return p + (index & (L2_SIZE - 1));
  123 +}
  124 +
  125 +int page_get_flags(unsigned long address)
  126 +{
  127 + unsigned int index;
  128 + PageDesc *p;
  129 +
  130 + index = address >> TARGET_PAGE_BITS;
  131 + p = l1_map[index >> L2_BITS];
  132 + if (!p)
  133 + return 0;
  134 + return p[index & (L2_SIZE - 1)].flags;
  135 +}
  136 +
  137 +void page_set_flags(unsigned long start, unsigned long end, int flags)
  138 +{
  139 + PageDesc *p;
  140 + unsigned long addr;
  141 +
  142 + start = start & TARGET_PAGE_MASK;
  143 + end = TARGET_PAGE_ALIGN(end);
  144 + for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
  145 + p = page_find_alloc(addr);
  146 + p->flags = flags;
  147 + }
  148 +}
... ...
linux-user/elfload.c
... ... @@ -95,8 +95,6 @@ struct exec
95 95 #define ZMAGIC 0413
96 96 #define QMAGIC 0314
97 97  
98   -#define X86_STACK_TOP 0x7d000000
99   -
100 98 /* max code+data+bss space allocated to elf interpreter */
101 99 #define INTERP_MAP_SIZE (32 * 1024 * 1024)
102 100  
... ... @@ -123,23 +121,11 @@ struct exec
123 121 #define PER_XENIX (0x0007 | STICKY_TIMEOUTS)
124 122  
125 123 /* Necessary parameters */
126   -#define ALPHA_PAGE_SIZE 4096
127   -#define X86_PAGE_SIZE 4096
128   -
129   -#define ALPHA_PAGE_MASK (~(ALPHA_PAGE_SIZE-1))
130   -#define X86_PAGE_MASK (~(X86_PAGE_SIZE-1))
131   -
132   -#define ALPHA_PAGE_ALIGN(addr) ((((addr)+ALPHA_PAGE_SIZE)-1)&ALPHA_PAGE_MASK)
133   -#define X86_PAGE_ALIGN(addr) ((((addr)+X86_PAGE_SIZE)-1)&X86_PAGE_MASK)
134   -
135 124 #define NGROUPS 32
136 125  
137   -#define X86_ELF_EXEC_PAGESIZE X86_PAGE_SIZE
138   -#define X86_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(X86_ELF_EXEC_PAGESIZE-1))
139   -#define X86_ELF_PAGEOFFSET(_v) ((_v) & (X86_ELF_EXEC_PAGESIZE-1))
140   -
141   -#define ALPHA_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(ALPHA_PAGE_SIZE-1))
142   -#define ALPHA_ELF_PAGEOFFSET(_v) ((_v) & (ALPHA_PAGE_SIZE-1))
  126 +#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
  127 +#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
  128 +#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
143 129  
144 130 #define INTERPRETER_NONE 0
145 131 #define INTERPRETER_AOUT 1
... ... @@ -160,9 +146,6 @@ static inline void memcpy_tofs(void * to, const void * from, unsigned long n)
160 146 memcpy(to, from, n);
161 147 }
162 148  
163   -//extern void * mmap4k();
164   -#define mmap4k(a, b, c, d, e, f) mmap((void *)(a), b, c, d, e, f)
165   -
166 149 extern unsigned long x86_stack_size;
167 150  
168 151 static int load_aout_interp(void * exptr, int interp_fd);
... ... @@ -227,8 +210,8 @@ static void * get_free_page(void)
227 210 /* User-space version of kernel get_free_page. Returns a page-aligned
228 211 * page-sized chunk of memory.
229 212 */
230   - retval = mmap4k(0, ALPHA_PAGE_SIZE, PROT_READ|PROT_WRITE,
231   - MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
  213 + retval = (void *)target_mmap(0, host_page_size, PROT_READ|PROT_WRITE,
  214 + MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
232 215  
233 216 if((long)retval == -1) {
234 217 perror("get_free_page");
... ... @@ -241,7 +224,7 @@ static void * get_free_page(void)
241 224  
242 225 static void free_page(void * pageaddr)
243 226 {
244   - (void)munmap(pageaddr, ALPHA_PAGE_SIZE);
  227 + target_munmap((unsigned long)pageaddr, host_page_size);
245 228 }
246 229  
247 230 /*
... ... @@ -272,9 +255,9 @@ static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
272 255 while (len) {
273 256 --p; --tmp; --len;
274 257 if (--offset < 0) {
275   - offset = p % X86_PAGE_SIZE;
276   - if (!(pag = (char *) page[p/X86_PAGE_SIZE]) &&
277   - !(pag = (char *) page[p/X86_PAGE_SIZE] =
  258 + offset = p % TARGET_PAGE_SIZE;
  259 + if (!(pag = (char *) page[p/TARGET_PAGE_SIZE]) &&
  260 + !(pag = (char *) page[p/TARGET_PAGE_SIZE] =
278 261 (unsigned long *) get_free_page())) {
279 262 return 0;
280 263 }
... ... @@ -390,21 +373,21 @@ unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm,
390 373 * it for args, we'll use it for something else...
391 374 */
392 375 size = x86_stack_size;
393   - if (size < MAX_ARG_PAGES*X86_PAGE_SIZE)
394   - size = MAX_ARG_PAGES*X86_PAGE_SIZE;
395   - error = (unsigned long)mmap4k(NULL,
396   - size + X86_PAGE_SIZE,
397   - PROT_READ | PROT_WRITE,
398   - MAP_PRIVATE | MAP_ANONYMOUS,
399   - -1, 0);
  376 + if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE)
  377 + size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
  378 + error = target_mmap(0,
  379 + size + host_page_size,
  380 + PROT_READ | PROT_WRITE,
  381 + MAP_PRIVATE | MAP_ANONYMOUS,
  382 + -1, 0);
400 383 if (error == -1) {
401 384 perror("stk mmap");
402 385 exit(-1);
403 386 }
404 387 /* we reserve one extra page at the top of the stack as guard */
405   - mprotect((void *)(error + size), X86_PAGE_SIZE, PROT_NONE);
  388 + target_mprotect(error + size, host_page_size, PROT_NONE);
406 389  
407   - stack_base = error + size - MAX_ARG_PAGES*X86_PAGE_SIZE;
  390 + stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
408 391 p += stack_base;
409 392  
410 393 if (bprm->loader) {
... ... @@ -416,10 +399,10 @@ unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm,
416 399 if (bprm->page[i]) {
417 400 info->rss++;
418 401  
419   - memcpy((void *)stack_base, (void *)bprm->page[i], X86_PAGE_SIZE);
  402 + memcpy((void *)stack_base, (void *)bprm->page[i], TARGET_PAGE_SIZE);
420 403 free_page((void *)bprm->page[i]);
421 404 }
422   - stack_base += X86_PAGE_SIZE;
  405 + stack_base += TARGET_PAGE_SIZE;
423 406 }
424 407 return p;
425 408 }
... ... @@ -427,13 +410,13 @@ unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm,
427 410 static void set_brk(unsigned long start, unsigned long end)
428 411 {
429 412 /* page-align the start and end addresses... */
430   - start = ALPHA_PAGE_ALIGN(start);
431   - end = ALPHA_PAGE_ALIGN(end);
  413 + start = HOST_PAGE_ALIGN(start);
  414 + end = HOST_PAGE_ALIGN(end);
432 415 if (end <= start)
433 416 return;
434   - if((long)mmap4k(start, end - start,
435   - PROT_READ | PROT_WRITE | PROT_EXEC,
436   - MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
  417 + if(target_mmap(start, end - start,
  418 + PROT_READ | PROT_WRITE | PROT_EXEC,
  419 + MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
437 420 perror("cannot mmap brk");
438 421 exit(-1);
439 422 }
... ... @@ -451,9 +434,9 @@ static void padzero(unsigned long elf_bss)
451 434 unsigned long nbyte;
452 435 char * fpnt;
453 436  
454   - nbyte = elf_bss & (ALPHA_PAGE_SIZE-1); /* was X86_PAGE_SIZE - JRP */
  437 + nbyte = elf_bss & (host_page_size-1); /* was TARGET_PAGE_SIZE - JRP */
455 438 if (nbyte) {
456   - nbyte = ALPHA_PAGE_SIZE - nbyte;
  439 + nbyte = host_page_size - nbyte;
457 440 fpnt = (char *) elf_bss;
458 441 do {
459 442 *fpnt++ = 0;
... ... @@ -494,7 +477,7 @@ static unsigned int * create_elf_tables(char *p, int argc, int envc,
494 477 NEW_AUX_ENT (AT_PHDR, (target_ulong)(load_addr + exec->e_phoff));
495 478 NEW_AUX_ENT (AT_PHENT, (target_ulong)(sizeof (struct elf_phdr)));
496 479 NEW_AUX_ENT (AT_PHNUM, (target_ulong)(exec->e_phnum));
497   - NEW_AUX_ENT (AT_PAGESZ, (target_ulong)(ALPHA_PAGE_SIZE));
  480 + NEW_AUX_ENT (AT_PAGESZ, (target_ulong)(TARGET_PAGE_SIZE));
498 481 NEW_AUX_ENT (AT_BASE, (target_ulong)(interp_load_addr));
499 482 NEW_AUX_ENT (AT_FLAGS, (target_ulong)0);
500 483 NEW_AUX_ENT (AT_ENTRY, load_bias + exec->e_entry);
... ... @@ -554,7 +537,7 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
554 537  
555 538 /* Now read in all of the header information */
556 539  
557   - if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > X86_PAGE_SIZE)
  540 + if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
558 541 return ~0UL;
559 542  
560 543 elf_phdata = (struct elf_phdr *)
... ... @@ -594,9 +577,9 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
594 577 if (interp_elf_ex->e_type == ET_DYN) {
595 578 /* in order to avoid harcoding the interpreter load
596 579 address in qemu, we allocate a big enough memory zone */
597   - error = (unsigned long)mmap4k(NULL, INTERP_MAP_SIZE,
598   - PROT_NONE, MAP_PRIVATE | MAP_ANON,
599   - -1, 0);
  580 + error = target_mmap(0, INTERP_MAP_SIZE,
  581 + PROT_NONE, MAP_PRIVATE | MAP_ANON,
  582 + -1, 0);
600 583 if (error == -1) {
601 584 perror("mmap");
602 585 exit(-1);
... ... @@ -620,12 +603,12 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
620 603 elf_type |= MAP_FIXED;
621 604 vaddr = eppnt->p_vaddr;
622 605 }
623   - error = (unsigned long)mmap4k(load_addr+X86_ELF_PAGESTART(vaddr),
624   - eppnt->p_filesz + X86_ELF_PAGEOFFSET(eppnt->p_vaddr),
  606 + error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr),
  607 + eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
625 608 elf_prot,
626 609 elf_type,
627 610 interpreter_fd,
628   - eppnt->p_offset - X86_ELF_PAGEOFFSET(eppnt->p_vaddr));
  611 + eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
629 612  
630 613 if (error > -1024UL) {
631 614 /* Real error */
... ... @@ -665,13 +648,13 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
665 648 * bss page.
666 649 */
667 650 padzero(elf_bss);
668   - elf_bss = X86_ELF_PAGESTART(elf_bss + ALPHA_PAGE_SIZE - 1); /* What we have mapped so far */
  651 + elf_bss = TARGET_ELF_PAGESTART(elf_bss + host_page_size - 1); /* What we have mapped so far */
669 652  
670 653 /* Map the last of the bss segment */
671 654 if (last_bss > elf_bss) {
672   - mmap4k(elf_bss, last_bss-elf_bss,
673   - PROT_READ|PROT_WRITE|PROT_EXEC,
674   - MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
  655 + target_mmap(elf_bss, last_bss-elf_bss,
  656 + PROT_READ|PROT_WRITE|PROT_EXEC,
  657 + MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
675 658 }
676 659 free(elf_phdata);
677 660  
... ... @@ -742,7 +725,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r
742 725 unsigned int interpreter_type = INTERPRETER_NONE;
743 726 unsigned char ibcs2_interpreter;
744 727 int i;
745   - void * mapped_addr;
  728 + unsigned long mapped_addr;
746 729 struct elf_phdr * elf_ppnt;
747 730 struct elf_phdr *elf_phdata;
748 731 unsigned long elf_bss, k, elf_brk;
... ... @@ -979,33 +962,32 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r
979 962 is because the brk will follow the loader, and is not movable. */
980 963 /* NOTE: for qemu, we do a big mmap to get enough space
981 964 without harcoding any address */
982   - error = (unsigned long)mmap4k(NULL, ET_DYN_MAP_SIZE,
983   - PROT_NONE, MAP_PRIVATE | MAP_ANON,
984   - -1, 0);
  965 + error = target_mmap(0, ET_DYN_MAP_SIZE,
  966 + PROT_NONE, MAP_PRIVATE | MAP_ANON,
  967 + -1, 0);
985 968 if (error == -1) {
986 969 perror("mmap");
987 970 exit(-1);
988 971 }
989   - load_bias = X86_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
  972 + load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
990 973 }
991 974  
992   - error = (unsigned long)mmap4k(
993   - X86_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
994   - (elf_ppnt->p_filesz +
995   - X86_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
996   - elf_prot,
997   - (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
998   - bprm->fd,
999   - (elf_ppnt->p_offset -
1000   - X86_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
  975 + error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
  976 + (elf_ppnt->p_filesz +
  977 + TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
  978 + elf_prot,
  979 + (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
  980 + bprm->fd,
  981 + (elf_ppnt->p_offset -
  982 + TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
1001 983 if (error == -1) {
1002 984 perror("mmap");
1003 985 exit(-1);
1004 986 }
1005 987  
1006 988 #ifdef LOW_ELF_STACK
1007   - if (X86_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
1008   - elf_stack = X86_ELF_PAGESTART(elf_ppnt->p_vaddr);
  989 + if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
  990 + elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr);
1009 991 #endif
1010 992  
1011 993 if (!load_addr_set) {
... ... @@ -1013,7 +995,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r
1013 995 load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
1014 996 if (elf_ex.e_type == ET_DYN) {
1015 997 load_bias += error -
1016   - X86_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
  998 + TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
1017 999 load_addr += load_bias;
1018 1000 }
1019 1001 }
... ... @@ -1108,8 +1090,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r
1108 1090 and some applications "depend" upon this behavior.
1109 1091 Since we do not have the power to recompile these, we
1110 1092 emulate the SVr4 behavior. Sigh. */
1111   - mapped_addr = mmap4k(NULL, ALPHA_PAGE_SIZE, PROT_READ | PROT_EXEC,
1112   - MAP_FIXED | MAP_PRIVATE, -1, 0);
  1093 + mapped_addr = target_mmap(0, host_page_size, PROT_READ | PROT_EXEC,
  1094 + MAP_FIXED | MAP_PRIVATE, -1, 0);
1113 1095 }
1114 1096  
1115 1097 #ifdef ELF_PLAT_INIT
... ... @@ -1137,7 +1119,7 @@ int elf_exec(const char * filename, char ** argv, char ** envp,
1137 1119 int retval;
1138 1120 int i;
1139 1121  
1140   - bprm.p = X86_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
  1122 + bprm.p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
1141 1123 for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
1142 1124 bprm.page[i] = 0;
1143 1125 retval = open(filename, O_RDONLY);
... ...
linux-user/main.c
... ... @@ -231,13 +231,16 @@ void usage(void)
231 231 "usage: qemu [-h] [-d] [-L path] [-s size] program [arguments...]\n"
232 232 "Linux x86 emulator\n"
233 233 "\n"
234   - "-h print this help\n"
235   - "-d activate log (logfile=%s)\n"
236   - "-L path set the x86 elf interpreter prefix (default=%s)\n"
237   - "-s size set the x86 stack size in bytes (default=%ld)\n",
238   - DEBUG_LOGFILE,
  234 + "-h print this help\n"
  235 + "-L path set the x86 elf interpreter prefix (default=%s)\n"
  236 + "-s size set the x86 stack size in bytes (default=%ld)\n"
  237 + "\n"
  238 + "debug options:\n"
  239 + "-d activate log (logfile=%s)\n"
  240 + "-p pagesize set the host page size to 'pagesize'\n",
239 241 interp_prefix,
240   - x86_stack_size);
  242 + x86_stack_size,
  243 + DEBUG_LOGFILE);
241 244 _exit(1);
242 245 }
243 246  
... ... @@ -284,6 +287,13 @@ int main(int argc, char **argv)
284 287 x86_stack_size *= 1024;
285 288 } else if (!strcmp(r, "L")) {
286 289 interp_prefix = argv[optind++];
  290 + } else if (!strcmp(r, "p")) {
  291 + host_page_size = atoi(argv[optind++]);
  292 + if (host_page_size == 0 ||
  293 + (host_page_size & (host_page_size - 1)) != 0) {
  294 + fprintf(stderr, "page size must be a power of two\n");
  295 + exit(1);
  296 + }
287 297 } else {
288 298 usage();
289 299 }
... ... @@ -311,12 +321,18 @@ int main(int argc, char **argv)
311 321 /* Scan interp_prefix dir for replacement files. */
312 322 init_paths(interp_prefix);
313 323  
  324 + /* NOTE: we need to init the CPU at this stage to get the
  325 + host_page_size */
  326 + env = cpu_x86_init();
  327 +
314 328 if (elf_exec(filename, argv+optind, environ, regs, info) != 0) {
315 329 printf("Error loading %s\n", filename);
316 330 _exit(1);
317 331 }
318 332  
319 333 if (loglevel) {
  334 + page_dump(logfile);
  335 +
320 336 fprintf(logfile, "start_brk 0x%08lx\n" , info->start_brk);
321 337 fprintf(logfile, "end_code 0x%08lx\n" , info->end_code);
322 338 fprintf(logfile, "start_code 0x%08lx\n" , info->start_code);
... ... @@ -331,7 +347,6 @@ int main(int argc, char **argv)
331 347 syscall_init();
332 348 signal_init();
333 349  
334   - env = cpu_x86_init();
335 350 global_env = env;
336 351  
337 352 /* build Task State */
... ...
linux-user/mmap.c 0 → 100644
  1 +/*
  2 + * mmap support for qemu
  3 + *
  4 + * Copyright (c) 2003 Fabrice Bellard
  5 + *
  6 + * This program is free software; you can redistribute it and/or modify
  7 + * it under the terms of the GNU General Public License as published by
  8 + * the Free Software Foundation; either version 2 of the License, or
  9 + * (at your option) any later version.
  10 + *
  11 + * This program 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
  14 + * GNU General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU General Public License
  17 + * along with this program; if not, write to the Free Software
  18 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19 + */
  20 +#include <stdlib.h>
  21 +#include <stdio.h>
  22 +#include <stdarg.h>
  23 +#include <string.h>
  24 +#include <unistd.h>
  25 +#include <errno.h>
  26 +#include <sys/mman.h>
  27 +
  28 +#include "qemu.h"
  29 +
  30 +//#define DEBUG_MMAP
  31 +
  32 +/* NOTE: all the constants are the HOST ones */
  33 +int target_mprotect(unsigned long start, unsigned long len, int prot)
  34 +{
  35 + unsigned long end, host_start, host_end, addr;
  36 + int prot1, ret;
  37 +
  38 +#ifdef DEBUG_MMAP
  39 + printf("mprotect: start=0x%lx len=0x%lx prot=%c%c%c\n", start, len,
  40 + prot & PROT_READ ? 'r' : '-',
  41 + prot & PROT_WRITE ? 'w' : '-',
  42 + prot & PROT_EXEC ? 'x' : '-');
  43 +#endif
  44 +
  45 + if ((start & ~TARGET_PAGE_MASK) != 0)
  46 + return -EINVAL;
  47 + len = TARGET_PAGE_ALIGN(len);
  48 + end = start + len;
  49 + if (end < start)
  50 + return -EINVAL;
  51 + if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
  52 + return -EINVAL;
  53 + if (len == 0)
  54 + return 0;
  55 +
  56 + host_start = start & host_page_mask;
  57 + host_end = HOST_PAGE_ALIGN(end);
  58 + if (start > host_start) {
  59 + /* handle host page containing start */
  60 + prot1 = prot;
  61 + for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
  62 + prot1 |= page_get_flags(addr);
  63 + }
  64 + ret = mprotect((void *)host_start, host_page_size, prot1 & PAGE_BITS);
  65 + if (ret != 0)
  66 + return ret;
  67 + host_start += host_page_size;
  68 + }
  69 + if (end < host_end) {
  70 + /* handle host page containing end (can be the same as first page) */
  71 + prot1 = prot;
  72 + for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
  73 + prot1 |= page_get_flags(addr);
  74 + }
  75 + ret = mprotect((void *)(host_end - host_page_size), host_page_size,
  76 + prot1 & PAGE_BITS);
  77 + if (ret != 0)
  78 + return ret;
  79 + host_end -= host_page_size;
  80 + }
  81 +
  82 + /* handle the pages in the middle */
  83 + if (host_start < host_end) {
  84 + ret = mprotect((void *)host_start, host_end - host_start, prot);
  85 + if (ret != 0)
  86 + return ret;
  87 + }
  88 +
  89 + page_set_flags(start, start + len, prot | PAGE_VALID);
  90 + return 0;
  91 +}
  92 +
  93 +/* map an incomplete host page */
  94 +int mmap_frag(unsigned long host_start,
  95 + unsigned long start, unsigned long end,
  96 + int prot, int flags, int fd, unsigned long offset)
  97 +{
  98 + unsigned long host_end, ret, addr;
  99 + int prot1, prot_new;
  100 +
  101 + host_end = host_start + host_page_size;
  102 +
  103 + /* get the protection of the target pages outside the mapping */
  104 + prot1 = 0;
  105 + for(addr = host_start; addr < host_end; addr++) {
  106 + if (addr < start || addr >= end)
  107 + prot1 |= page_get_flags(addr);
  108 + }
  109 +
  110 + if (prot1 == 0) {
  111 + /* no page was there, so we allocate one */
  112 + ret = (long)mmap((void *)host_start, host_page_size, prot,
  113 + flags | MAP_ANONYMOUS, -1, 0);
  114 + if (ret == -1)
  115 + return ret;
  116 + }
  117 + prot1 &= PAGE_BITS;
  118 +
  119 + prot_new = prot | prot1;
  120 + if (!(flags & MAP_ANONYMOUS)) {
  121 + /* msync() won't work here, so we return an error if write is
  122 + possible while it is a shared mapping */
  123 + if ((flags & MAP_TYPE) == MAP_SHARED &&
  124 + (prot & PROT_WRITE))
  125 + return -EINVAL;
  126 +
  127 + /* adjust protection to be able to read */
  128 + if (!(prot1 & PROT_WRITE))
  129 + mprotect((void *)host_start, host_page_size, prot1 | PROT_WRITE);
  130 +
  131 + /* read the corresponding file data */
  132 + pread(fd, (void *)start, end - start, offset);
  133 +
  134 + /* put final protection */
  135 + if (prot_new != (prot1 | PROT_WRITE))
  136 + mprotect((void *)host_start, host_page_size, prot_new);
  137 + } else {
  138 + /* just update the protection */
  139 + if (prot_new != prot1) {
  140 + mprotect((void *)host_start, host_page_size, prot_new);
  141 + }
  142 + }
  143 + return 0;
  144 +}
  145 +
  146 +/* NOTE: all the constants are the HOST ones */
  147 +long target_mmap(unsigned long start, unsigned long len, int prot,
  148 + int flags, int fd, unsigned long offset)
  149 +{
  150 + unsigned long ret, end, host_start, host_end, retaddr, host_offset, host_len;
  151 +
  152 +#ifdef DEBUG_MMAP
  153 + {
  154 + printf("mmap: start=0x%lx len=0x%lx prot=%c%c%c flags=",
  155 + start, len,
  156 + prot & PROT_READ ? 'r' : '-',
  157 + prot & PROT_WRITE ? 'w' : '-',
  158 + prot & PROT_EXEC ? 'x' : '-');
  159 + if (flags & MAP_FIXED)
  160 + printf("MAP_FIXED ");
  161 + if (flags & MAP_ANONYMOUS)
  162 + printf("MAP_ANON ");
  163 + switch(flags & MAP_TYPE) {
  164 + case MAP_PRIVATE:
  165 + printf("MAP_PRIVATE ");
  166 + break;
  167 + case MAP_SHARED:
  168 + printf("MAP_SHARED ");
  169 + break;
  170 + default:
  171 + printf("[MAP_TYPE=0x%x] ", flags & MAP_TYPE);
  172 + break;
  173 + }
  174 + printf("fd=%d offset=%lx\n", fd, offset);
  175 + }
  176 +#endif
  177 +
  178 + if (offset & ~TARGET_PAGE_MASK)
  179 + return -EINVAL;
  180 +
  181 + len = TARGET_PAGE_ALIGN(len);
  182 + if (len == 0)
  183 + return start;
  184 + host_start = start & host_page_mask;
  185 +
  186 + if (!(flags & MAP_FIXED)) {
  187 + if (host_page_size != real_host_page_size) {
  188 + /* NOTE: this code is only for debugging with '-p' option */
  189 + /* reserve a memory area */
  190 + host_len = HOST_PAGE_ALIGN(len) + host_page_size - TARGET_PAGE_SIZE;
  191 + host_start = (long)mmap((void *)host_start, host_len, PROT_NONE,
  192 + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  193 + if (host_start == -1)
  194 + return host_start;
  195 + host_end = host_start + host_len;
  196 + start = HOST_PAGE_ALIGN(host_start);
  197 + end = start + HOST_PAGE_ALIGN(len);
  198 + if (start > host_start)
  199 + munmap((void *)host_start, start - host_start);
  200 + if (end < host_end)
  201 + munmap((void *)end, host_end - end);
  202 + /* use it as a fixed mapping */
  203 + flags |= MAP_FIXED;
  204 + } else {
  205 + /* if not fixed, no need to do anything */
  206 + host_offset = offset & host_page_mask;
  207 + host_len = len + offset - host_offset;
  208 + start = (long)mmap((void *)host_start, host_len,
  209 + prot, flags, fd, host_offset);
  210 + if (start == -1)
  211 + return start;
  212 + /* update start so that it points to the file position at 'offset' */
  213 + if (!(flags & MAP_ANONYMOUS))
  214 + start += offset - host_offset;
  215 + goto the_end1;
  216 + }
  217 + }
  218 +
  219 + if (start & ~TARGET_PAGE_MASK)
  220 + return -EINVAL;
  221 + end = start + len;
  222 + host_end = HOST_PAGE_ALIGN(end);
  223 +
  224 + /* worst case: we cannot map the file because the offset is not
  225 + aligned, so we read it */
  226 + if (!(flags & MAP_ANONYMOUS) &&
  227 + (offset & ~host_page_mask) != (start & ~host_page_mask)) {
  228 + /* msync() won't work here, so we return an error if write is
  229 + possible while it is a shared mapping */
  230 + if ((flags & MAP_TYPE) == MAP_SHARED &&
  231 + (prot & PROT_WRITE))
  232 + return -EINVAL;
  233 + retaddr = target_mmap(start, len, prot | PROT_WRITE,
  234 + MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
  235 + -1, 0);
  236 + if (retaddr == -1)
  237 + return retaddr;
  238 + pread(fd, (void *)start, len, offset);
  239 + if (!(prot & PROT_WRITE)) {
  240 + ret = target_mprotect(start, len, prot);
  241 + if (ret != 0)
  242 + return ret;
  243 + }
  244 + goto the_end;
  245 + }
  246 +
  247 + /* handle the start of the mapping */
  248 + if (start > host_start) {
  249 + if (host_end == host_start + host_page_size) {
  250 + /* one single host page */
  251 + ret = mmap_frag(host_start, start, end,
  252 + prot, flags, fd, offset);
  253 + if (ret == -1)
  254 + return ret;
  255 + goto the_end1;
  256 + }
  257 + ret = mmap_frag(host_start, start, host_start + host_page_size,
  258 + prot, flags, fd, offset);
  259 + if (ret == -1)
  260 + return ret;
  261 + host_start += host_page_size;
  262 + }
  263 + /* handle the end of the mapping */
  264 + if (end < host_end) {
  265 + ret = mmap_frag(host_end - host_page_size,
  266 + host_end - host_page_size, host_end,
  267 + prot, flags, fd,
  268 + offset + host_end - host_page_size - start);
  269 + if (ret == -1)
  270 + return ret;
  271 + host_end -= host_page_size;
  272 + }
  273 +
  274 + /* map the middle (easier) */
  275 + if (host_start < host_end) {
  276 + ret = (long)mmap((void *)host_start, host_end - host_start,
  277 + prot, flags, fd, offset + host_start - start);
  278 + if (ret == -1)
  279 + return ret;
  280 + }
  281 + the_end1:
  282 + page_set_flags(start, start + len, prot | PAGE_VALID);
  283 + the_end:
  284 +#ifdef DEBUG_MMAP
  285 + page_dump(stdout);
  286 + printf("\n");
  287 +#endif
  288 + return start;
  289 +}
  290 +
  291 +int target_munmap(unsigned long start, unsigned long len)
  292 +{
  293 + unsigned long end, host_start, host_end, addr;
  294 + int prot, ret;
  295 +
  296 +#ifdef DEBUG_MMAP
  297 + printf("munmap: start=0x%lx len=0x%lx\n", start, len);
  298 +#endif
  299 + if (start & ~TARGET_PAGE_MASK)
  300 + return -EINVAL;
  301 + len = TARGET_PAGE_ALIGN(len);
  302 + if (len == 0)
  303 + return -EINVAL;
  304 + end = start + len;
  305 + host_start = start & host_page_mask;
  306 + host_end = HOST_PAGE_ALIGN(end);
  307 +
  308 + if (start > host_start) {
  309 + /* handle host page containing start */
  310 + prot = 0;
  311 + for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
  312 + prot |= page_get_flags(addr);
  313 + }
  314 + if (prot != 0)
  315 + host_start += host_page_size;
  316 + }
  317 + if (end < host_end) {
  318 + /* handle host page containing end (can be the same as first page) */
  319 + prot = 0;
  320 + for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
  321 + prot |= page_get_flags(addr);
  322 + }
  323 + if (prot != 0)
  324 + host_end -= host_page_size;
  325 + }
  326 +
  327 + /* unmap what we can */
  328 + if (host_start < host_end) {
  329 + ret = munmap((void *)host_start, host_end - host_start);
  330 + if (ret != 0)
  331 + return ret;
  332 + }
  333 +
  334 + page_set_flags(start, start + len, 0);
  335 + return 0;
  336 +}
  337 +
  338 +/* XXX: currently, we only handle MAP_ANONYMOUS and not MAP_FIXED
  339 + blocks which have been allocated starting on a host page */
  340 +long target_mremap(unsigned long old_addr, unsigned long old_size,
  341 + unsigned long new_size, unsigned long flags,
  342 + unsigned long new_addr)
  343 +{
  344 + int prot;
  345 +
  346 + /* XXX: use 5 args syscall */
  347 + new_addr = (long)mremap((void *)old_addr, old_size, new_size, flags);
  348 + if (new_addr == -1)
  349 + return new_addr;
  350 + prot = page_get_flags(old_addr);
  351 + page_set_flags(old_addr, old_addr + old_size, 0);
  352 + page_set_flags(new_addr, new_addr + new_size, prot | PAGE_VALID);
  353 + return new_addr;
  354 +}
  355 +
  356 +int target_msync(unsigned long start, unsigned long len, int flags)
  357 +{
  358 + unsigned long end;
  359 +
  360 + if (start & ~TARGET_PAGE_MASK)
  361 + return -EINVAL;
  362 + len = TARGET_PAGE_ALIGN(len);
  363 + if (len == 0)
  364 + return 0;
  365 + end = start + len;
  366 +
  367 + start &= host_page_mask;
  368 + return msync((void *)start, len, flags);
  369 +}
  370 +
... ...
linux-user/qemu.h
... ... @@ -88,4 +88,14 @@ void handle_vm86_fault(CPUX86State *env);
88 88 int do_vm86(CPUX86State *env, long subfunction,
89 89 struct target_vm86plus_struct * target_v86);
90 90  
  91 +/* mmap.c */
  92 +int target_mprotect(unsigned long start, unsigned long len, int prot);
  93 +long target_mmap(unsigned long start, unsigned long len, int prot,
  94 + int flags, int fd, unsigned long offset);
  95 +int target_munmap(unsigned long start, unsigned long len);
  96 +long target_mremap(unsigned long old_addr, unsigned long old_size,
  97 + unsigned long new_size, unsigned long flags,
  98 + unsigned long new_addr);
  99 +int target_msync(unsigned long start, unsigned long len, int flags);
  100 +
91 101 #endif
... ...
linux-user/syscall.c
... ... @@ -64,11 +64,6 @@
64 64  
65 65 //#define DEBUG
66 66  
67   -#ifndef PAGE_SIZE
68   -#define PAGE_SIZE 4096
69   -#define PAGE_MASK ~(PAGE_SIZE - 1)
70   -#endif
71   -
72 67 //#include <linux/msdos_fs.h>
73 68 #define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
74 69 #define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2])
... ... @@ -153,7 +148,7 @@ static long do_brk(char *new_brk)
153 148 if (new_brk < target_original_brk)
154 149 return -ENOMEM;
155 150  
156   - brk_page = (char *)(((unsigned long)target_brk + PAGE_SIZE - 1) & PAGE_MASK);
  151 + brk_page = (char *)HOST_PAGE_ALIGN((unsigned long)target_brk);
157 152  
158 153 /* If the new brk is less than this, set it and we're done... */
159 154 if (new_brk < brk_page) {
... ... @@ -162,11 +157,10 @@ static long do_brk(char *new_brk)
162 157 }
163 158  
164 159 /* We need to allocate more memory after the brk... */
165   - new_alloc_size = ((new_brk - brk_page + 1)+(PAGE_SIZE-1)) & PAGE_MASK;
166   - mapped_addr = get_errno((long)mmap((caddr_t)brk_page, new_alloc_size,
167   - PROT_READ|PROT_WRITE,
168   - MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
169   -
  160 + new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
  161 + mapped_addr = get_errno(target_mmap((unsigned long)brk_page, new_alloc_size,
  162 + PROT_READ|PROT_WRITE,
  163 + MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
170 164 if (is_error(mapped_addr)) {
171 165 return mapped_addr;
172 166 } else {
... ... @@ -1709,7 +1703,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1709 1703 v4 = tswap32(vptr[3]);
1710 1704 v5 = tswap32(vptr[4]);
1711 1705 v6 = tswap32(vptr[5]);
1712   - ret = get_errno((long)mmap((void *)v1, v2, v3, v4, v5, v6));
  1706 + ret = get_errno(target_mmap(v1, v2, v3, v4, v5, v6));
1713 1707 }
1714 1708 break;
1715 1709 #endif
... ... @@ -1718,16 +1712,16 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1718 1712 #else
1719 1713 case TARGET_NR_mmap:
1720 1714 #endif
1721   - ret = get_errno((long)mmap((void *)arg1, arg2, arg3, arg4, arg5, arg6));
  1715 + ret = get_errno(target_mmap(arg1, arg2, arg3, arg4, arg5, arg6));
1722 1716 break;
1723 1717 case TARGET_NR_munmap:
1724   - ret = get_errno(munmap((void *)arg1, arg2));
  1718 + ret = get_errno(target_munmap(arg1, arg2));
1725 1719 break;
1726 1720 case TARGET_NR_mprotect:
1727   - ret = get_errno(mprotect((void *)arg1, arg2, arg3));
  1721 + ret = get_errno(target_mprotect(arg1, arg2, arg3));
1728 1722 break;
1729 1723 case TARGET_NR_mremap:
1730   - ret = get_errno((long)mremap((void *)arg1, arg2, arg3, arg4));
  1724 + ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
1731 1725 break;
1732 1726 case TARGET_NR_msync:
1733 1727 ret = get_errno(msync((void *)arg1, arg2, arg3));
... ...
translate-i386.c
... ... @@ -3845,6 +3845,7 @@ CPUX86State *cpu_x86_init(void)
3845 3845 if (!inited) {
3846 3846 inited = 1;
3847 3847 optimize_flags_init();
  3848 + page_init();
3848 3849 }
3849 3850 return env;
3850 3851 }
... ...