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,11 +58,11 @@ LDFLAGS+=-p
58 main.o: CFLAGS+=-p 58 main.o: CFLAGS+=-p
59 endif 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 SRCS:= $(OBJS:.o=.c) 62 SRCS:= $(OBJS:.o=.c)
63 OBJS+= libqemu.a 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 # NOTE: the disassembler code is only needed for debugging 66 # NOTE: the disassembler code is only needed for debugging
67 LIBOBJS+=disas.o ppc-dis.o i386-dis.o alpha-dis.o dis-buf.o 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,6 +431,30 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
431 #define X86_DUMP_CCOP 0x0002 /* dump qemu flag cache */ 431 #define X86_DUMP_CCOP 0x0002 /* dump qemu flag cache */
432 void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags); 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 /* internal functions */ 458 /* internal functions */
435 459
436 #define GEN_FLAG_CODE32_SHIFT 0 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,5 +470,6 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
446 int *gen_code_size_ptr, 470 int *gen_code_size_ptr,
447 uint8_t *pc_start, uint8_t *cs_base, int flags); 471 uint8_t *pc_start, uint8_t *cs_base, int flags);
448 void cpu_x86_tblocks_init(void); 472 void cpu_x86_tblocks_init(void);
  473 +void page_init(void);
449 474
450 #endif /* CPU_I386_H */ 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,8 +95,6 @@ struct exec
95 #define ZMAGIC 0413 95 #define ZMAGIC 0413
96 #define QMAGIC 0314 96 #define QMAGIC 0314
97 97
98 -#define X86_STACK_TOP 0x7d000000  
99 -  
100 /* max code+data+bss space allocated to elf interpreter */ 98 /* max code+data+bss space allocated to elf interpreter */
101 #define INTERP_MAP_SIZE (32 * 1024 * 1024) 99 #define INTERP_MAP_SIZE (32 * 1024 * 1024)
102 100
@@ -123,23 +121,11 @@ struct exec @@ -123,23 +121,11 @@ struct exec
123 #define PER_XENIX (0x0007 | STICKY_TIMEOUTS) 121 #define PER_XENIX (0x0007 | STICKY_TIMEOUTS)
124 122
125 /* Necessary parameters */ 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 #define NGROUPS 32 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 #define INTERPRETER_NONE 0 130 #define INTERPRETER_NONE 0
145 #define INTERPRETER_AOUT 1 131 #define INTERPRETER_AOUT 1
@@ -160,9 +146,6 @@ static inline void memcpy_tofs(void * to, const void * from, unsigned long n) @@ -160,9 +146,6 @@ static inline void memcpy_tofs(void * to, const void * from, unsigned long n)
160 memcpy(to, from, n); 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 extern unsigned long x86_stack_size; 149 extern unsigned long x86_stack_size;
167 150
168 static int load_aout_interp(void * exptr, int interp_fd); 151 static int load_aout_interp(void * exptr, int interp_fd);
@@ -227,8 +210,8 @@ static void * get_free_page(void) @@ -227,8 +210,8 @@ static void * get_free_page(void)
227 /* User-space version of kernel get_free_page. Returns a page-aligned 210 /* User-space version of kernel get_free_page. Returns a page-aligned
228 * page-sized chunk of memory. 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 if((long)retval == -1) { 216 if((long)retval == -1) {
234 perror("get_free_page"); 217 perror("get_free_page");
@@ -241,7 +224,7 @@ static void * get_free_page(void) @@ -241,7 +224,7 @@ static void * get_free_page(void)
241 224
242 static void free_page(void * pageaddr) 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,9 +255,9 @@ static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
272 while (len) { 255 while (len) {
273 --p; --tmp; --len; 256 --p; --tmp; --len;
274 if (--offset < 0) { 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 (unsigned long *) get_free_page())) { 261 (unsigned long *) get_free_page())) {
279 return 0; 262 return 0;
280 } 263 }
@@ -390,21 +373,21 @@ unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm, @@ -390,21 +373,21 @@ unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm,
390 * it for args, we'll use it for something else... 373 * it for args, we'll use it for something else...
391 */ 374 */
392 size = x86_stack_size; 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 if (error == -1) { 383 if (error == -1) {
401 perror("stk mmap"); 384 perror("stk mmap");
402 exit(-1); 385 exit(-1);
403 } 386 }
404 /* we reserve one extra page at the top of the stack as guard */ 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 p += stack_base; 391 p += stack_base;
409 392
410 if (bprm->loader) { 393 if (bprm->loader) {
@@ -416,10 +399,10 @@ unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm, @@ -416,10 +399,10 @@ unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm,
416 if (bprm->page[i]) { 399 if (bprm->page[i]) {
417 info->rss++; 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 free_page((void *)bprm->page[i]); 403 free_page((void *)bprm->page[i]);
421 } 404 }
422 - stack_base += X86_PAGE_SIZE; 405 + stack_base += TARGET_PAGE_SIZE;
423 } 406 }
424 return p; 407 return p;
425 } 408 }
@@ -427,13 +410,13 @@ unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm, @@ -427,13 +410,13 @@ unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm,
427 static void set_brk(unsigned long start, unsigned long end) 410 static void set_brk(unsigned long start, unsigned long end)
428 { 411 {
429 /* page-align the start and end addresses... */ 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 if (end <= start) 415 if (end <= start)
433 return; 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 perror("cannot mmap brk"); 420 perror("cannot mmap brk");
438 exit(-1); 421 exit(-1);
439 } 422 }
@@ -451,9 +434,9 @@ static void padzero(unsigned long elf_bss) @@ -451,9 +434,9 @@ static void padzero(unsigned long elf_bss)
451 unsigned long nbyte; 434 unsigned long nbyte;
452 char * fpnt; 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 if (nbyte) { 438 if (nbyte) {
456 - nbyte = ALPHA_PAGE_SIZE - nbyte; 439 + nbyte = host_page_size - nbyte;
457 fpnt = (char *) elf_bss; 440 fpnt = (char *) elf_bss;
458 do { 441 do {
459 *fpnt++ = 0; 442 *fpnt++ = 0;
@@ -494,7 +477,7 @@ static unsigned int * create_elf_tables(char *p, int argc, int envc, @@ -494,7 +477,7 @@ static unsigned int * create_elf_tables(char *p, int argc, int envc,
494 NEW_AUX_ENT (AT_PHDR, (target_ulong)(load_addr + exec->e_phoff)); 477 NEW_AUX_ENT (AT_PHDR, (target_ulong)(load_addr + exec->e_phoff));
495 NEW_AUX_ENT (AT_PHENT, (target_ulong)(sizeof (struct elf_phdr))); 478 NEW_AUX_ENT (AT_PHENT, (target_ulong)(sizeof (struct elf_phdr)));
496 NEW_AUX_ENT (AT_PHNUM, (target_ulong)(exec->e_phnum)); 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 NEW_AUX_ENT (AT_BASE, (target_ulong)(interp_load_addr)); 481 NEW_AUX_ENT (AT_BASE, (target_ulong)(interp_load_addr));
499 NEW_AUX_ENT (AT_FLAGS, (target_ulong)0); 482 NEW_AUX_ENT (AT_FLAGS, (target_ulong)0);
500 NEW_AUX_ENT (AT_ENTRY, load_bias + exec->e_entry); 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,7 +537,7 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
554 537
555 /* Now read in all of the header information */ 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 return ~0UL; 541 return ~0UL;
559 542
560 elf_phdata = (struct elf_phdr *) 543 elf_phdata = (struct elf_phdr *)
@@ -594,9 +577,9 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, @@ -594,9 +577,9 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
594 if (interp_elf_ex->e_type == ET_DYN) { 577 if (interp_elf_ex->e_type == ET_DYN) {
595 /* in order to avoid harcoding the interpreter load 578 /* in order to avoid harcoding the interpreter load
596 address in qemu, we allocate a big enough memory zone */ 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 if (error == -1) { 583 if (error == -1) {
601 perror("mmap"); 584 perror("mmap");
602 exit(-1); 585 exit(-1);
@@ -620,12 +603,12 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, @@ -620,12 +603,12 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
620 elf_type |= MAP_FIXED; 603 elf_type |= MAP_FIXED;
621 vaddr = eppnt->p_vaddr; 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 elf_prot, 608 elf_prot,
626 elf_type, 609 elf_type,
627 interpreter_fd, 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 if (error > -1024UL) { 613 if (error > -1024UL) {
631 /* Real error */ 614 /* Real error */
@@ -665,13 +648,13 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, @@ -665,13 +648,13 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
665 * bss page. 648 * bss page.
666 */ 649 */
667 padzero(elf_bss); 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 /* Map the last of the bss segment */ 653 /* Map the last of the bss segment */
671 if (last_bss > elf_bss) { 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 free(elf_phdata); 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,7 +725,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r
742 unsigned int interpreter_type = INTERPRETER_NONE; 725 unsigned int interpreter_type = INTERPRETER_NONE;
743 unsigned char ibcs2_interpreter; 726 unsigned char ibcs2_interpreter;
744 int i; 727 int i;
745 - void * mapped_addr; 728 + unsigned long mapped_addr;
746 struct elf_phdr * elf_ppnt; 729 struct elf_phdr * elf_ppnt;
747 struct elf_phdr *elf_phdata; 730 struct elf_phdr *elf_phdata;
748 unsigned long elf_bss, k, elf_brk; 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,33 +962,32 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r
979 is because the brk will follow the loader, and is not movable. */ 962 is because the brk will follow the loader, and is not movable. */
980 /* NOTE: for qemu, we do a big mmap to get enough space 963 /* NOTE: for qemu, we do a big mmap to get enough space
981 without harcoding any address */ 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 if (error == -1) { 968 if (error == -1) {
986 perror("mmap"); 969 perror("mmap");
987 exit(-1); 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 if (error == -1) { 983 if (error == -1) {
1002 perror("mmap"); 984 perror("mmap");
1003 exit(-1); 985 exit(-1);
1004 } 986 }
1005 987
1006 #ifdef LOW_ELF_STACK 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 #endif 991 #endif
1010 992
1011 if (!load_addr_set) { 993 if (!load_addr_set) {
@@ -1013,7 +995,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r @@ -1013,7 +995,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r
1013 load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset; 995 load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
1014 if (elf_ex.e_type == ET_DYN) { 996 if (elf_ex.e_type == ET_DYN) {
1015 load_bias += error - 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 load_addr += load_bias; 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,8 +1090,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r
1108 and some applications "depend" upon this behavior. 1090 and some applications "depend" upon this behavior.
1109 Since we do not have the power to recompile these, we 1091 Since we do not have the power to recompile these, we
1110 emulate the SVr4 behavior. Sigh. */ 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 #ifdef ELF_PLAT_INIT 1097 #ifdef ELF_PLAT_INIT
@@ -1137,7 +1119,7 @@ int elf_exec(const char * filename, char ** argv, char ** envp, @@ -1137,7 +1119,7 @@ int elf_exec(const char * filename, char ** argv, char ** envp,
1137 int retval; 1119 int retval;
1138 int i; 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 for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */ 1123 for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
1142 bprm.page[i] = 0; 1124 bprm.page[i] = 0;
1143 retval = open(filename, O_RDONLY); 1125 retval = open(filename, O_RDONLY);
linux-user/main.c
@@ -231,13 +231,16 @@ void usage(void) @@ -231,13 +231,16 @@ void usage(void)
231 "usage: qemu [-h] [-d] [-L path] [-s size] program [arguments...]\n" 231 "usage: qemu [-h] [-d] [-L path] [-s size] program [arguments...]\n"
232 "Linux x86 emulator\n" 232 "Linux x86 emulator\n"
233 "\n" 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 interp_prefix, 241 interp_prefix,
240 - x86_stack_size); 242 + x86_stack_size,
  243 + DEBUG_LOGFILE);
241 _exit(1); 244 _exit(1);
242 } 245 }
243 246
@@ -284,6 +287,13 @@ int main(int argc, char **argv) @@ -284,6 +287,13 @@ int main(int argc, char **argv)
284 x86_stack_size *= 1024; 287 x86_stack_size *= 1024;
285 } else if (!strcmp(r, "L")) { 288 } else if (!strcmp(r, "L")) {
286 interp_prefix = argv[optind++]; 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 } else { 297 } else {
288 usage(); 298 usage();
289 } 299 }
@@ -311,12 +321,18 @@ int main(int argc, char **argv) @@ -311,12 +321,18 @@ int main(int argc, char **argv)
311 /* Scan interp_prefix dir for replacement files. */ 321 /* Scan interp_prefix dir for replacement files. */
312 init_paths(interp_prefix); 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 if (elf_exec(filename, argv+optind, environ, regs, info) != 0) { 328 if (elf_exec(filename, argv+optind, environ, regs, info) != 0) {
315 printf("Error loading %s\n", filename); 329 printf("Error loading %s\n", filename);
316 _exit(1); 330 _exit(1);
317 } 331 }
318 332
319 if (loglevel) { 333 if (loglevel) {
  334 + page_dump(logfile);
  335 +
320 fprintf(logfile, "start_brk 0x%08lx\n" , info->start_brk); 336 fprintf(logfile, "start_brk 0x%08lx\n" , info->start_brk);
321 fprintf(logfile, "end_code 0x%08lx\n" , info->end_code); 337 fprintf(logfile, "end_code 0x%08lx\n" , info->end_code);
322 fprintf(logfile, "start_code 0x%08lx\n" , info->start_code); 338 fprintf(logfile, "start_code 0x%08lx\n" , info->start_code);
@@ -331,7 +347,6 @@ int main(int argc, char **argv) @@ -331,7 +347,6 @@ int main(int argc, char **argv)
331 syscall_init(); 347 syscall_init();
332 signal_init(); 348 signal_init();
333 349
334 - env = cpu_x86_init();  
335 global_env = env; 350 global_env = env;
336 351
337 /* build Task State */ 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,4 +88,14 @@ void handle_vm86_fault(CPUX86State *env);
88 int do_vm86(CPUX86State *env, long subfunction, 88 int do_vm86(CPUX86State *env, long subfunction,
89 struct target_vm86plus_struct * target_v86); 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 #endif 101 #endif
linux-user/syscall.c
@@ -64,11 +64,6 @@ @@ -64,11 +64,6 @@
64 64
65 //#define DEBUG 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 //#include <linux/msdos_fs.h> 67 //#include <linux/msdos_fs.h>
73 #define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) 68 #define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
74 #define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2]) 69 #define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2])
@@ -153,7 +148,7 @@ static long do_brk(char *new_brk) @@ -153,7 +148,7 @@ static long do_brk(char *new_brk)
153 if (new_brk < target_original_brk) 148 if (new_brk < target_original_brk)
154 return -ENOMEM; 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 /* If the new brk is less than this, set it and we're done... */ 153 /* If the new brk is less than this, set it and we're done... */
159 if (new_brk < brk_page) { 154 if (new_brk < brk_page) {
@@ -162,11 +157,10 @@ static long do_brk(char *new_brk) @@ -162,11 +157,10 @@ static long do_brk(char *new_brk)
162 } 157 }
163 158
164 /* We need to allocate more memory after the brk... */ 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 if (is_error(mapped_addr)) { 164 if (is_error(mapped_addr)) {
171 return mapped_addr; 165 return mapped_addr;
172 } else { 166 } else {
@@ -1709,7 +1703,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1709,7 +1703,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1709 v4 = tswap32(vptr[3]); 1703 v4 = tswap32(vptr[3]);
1710 v5 = tswap32(vptr[4]); 1704 v5 = tswap32(vptr[4]);
1711 v6 = tswap32(vptr[5]); 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 break; 1708 break;
1715 #endif 1709 #endif
@@ -1718,16 +1712,16 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1718,16 +1712,16 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1718 #else 1712 #else
1719 case TARGET_NR_mmap: 1713 case TARGET_NR_mmap:
1720 #endif 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 break; 1716 break;
1723 case TARGET_NR_munmap: 1717 case TARGET_NR_munmap:
1724 - ret = get_errno(munmap((void *)arg1, arg2)); 1718 + ret = get_errno(target_munmap(arg1, arg2));
1725 break; 1719 break;
1726 case TARGET_NR_mprotect: 1720 case TARGET_NR_mprotect:
1727 - ret = get_errno(mprotect((void *)arg1, arg2, arg3)); 1721 + ret = get_errno(target_mprotect(arg1, arg2, arg3));
1728 break; 1722 break;
1729 case TARGET_NR_mremap: 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 break; 1725 break;
1732 case TARGET_NR_msync: 1726 case TARGET_NR_msync:
1733 ret = get_errno(msync((void *)arg1, arg2, arg3)); 1727 ret = get_errno(msync((void *)arg1, arg2, arg3));
translate-i386.c
@@ -3845,6 +3845,7 @@ CPUX86State *cpu_x86_init(void) @@ -3845,6 +3845,7 @@ CPUX86State *cpu_x86_init(void)
3845 if (!inited) { 3845 if (!inited) {
3846 inited = 1; 3846 inited = 1;
3847 optimize_flags_init(); 3847 optimize_flags_init();
  3848 + page_init();
3848 } 3849 }
3849 return env; 3850 return env;
3850 } 3851 }