diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-05-13 00:25:15 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-05-13 00:25:15 +0000 |
commit | 54936004fddc52c321cb3f9a9a51140e782bed5d (patch) | |
tree | c7640924fd504c24529a1f6ec0b77bb947589682 /exec.c | |
parent | 74c95119f2bceb73c1695ffee08a934cddabe830 (diff) |
mmap emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@158 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'exec.c')
-rw-r--r-- | exec.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/exec.c b/exec.c new file mode 100644 index 0000000000..a917143d60 --- /dev/null +++ b/exec.c @@ -0,0 +1,148 @@ +/* + * virtual page mapping + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <inttypes.h> + +#include "cpu-i386.h" + +/* XXX: pack the flags in the low bits of the pointer ? */ +typedef struct PageDesc { + struct TranslationBlock *first_tb; + unsigned long flags; +} PageDesc; + +#define L2_BITS 10 +#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS) + +#define L1_SIZE (1 << L1_BITS) +#define L2_SIZE (1 << L2_BITS) + +unsigned long real_host_page_size; +unsigned long host_page_bits; +unsigned long host_page_size; +unsigned long host_page_mask; + +static PageDesc *l1_map[L1_SIZE]; + +void page_init(void) +{ + /* NOTE: we can always suppose that host_page_size >= + TARGET_PAGE_SIZE */ + real_host_page_size = getpagesize(); + if (host_page_size == 0) + host_page_size = real_host_page_size; + if (host_page_size < TARGET_PAGE_SIZE) + host_page_size = TARGET_PAGE_SIZE; + host_page_bits = 0; + while ((1 << host_page_bits) < host_page_size) + host_page_bits++; + host_page_mask = ~(host_page_size - 1); +} + +/* dump memory mappings */ +void page_dump(FILE *f) +{ + unsigned long start, end; + int i, j, prot, prot1; + PageDesc *p; + + fprintf(f, "%-8s %-8s %-8s %s\n", + "start", "end", "size", "prot"); + start = -1; + end = -1; + prot = 0; + for(i = 0; i <= L1_SIZE; i++) { + if (i < L1_SIZE) + p = l1_map[i]; + else + p = NULL; + for(j = 0;j < L2_SIZE; j++) { + if (!p) + prot1 = 0; + else + prot1 = p[j].flags; + if (prot1 != prot) { + end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS); + if (start != -1) { + fprintf(f, "%08lx-%08lx %08lx %c%c%c\n", + start, end, end - start, + prot & PAGE_READ ? 'r' : '-', + prot & PAGE_WRITE ? 'w' : '-', + prot & PAGE_EXEC ? 'x' : '-'); + } + if (prot1 != 0) + start = end; + else + start = -1; + prot = prot1; + } + if (!p) + break; + } + } +} + + +static inline PageDesc *page_find_alloc(unsigned long address) +{ + unsigned int index; + PageDesc **lp, *p; + + index = address >> TARGET_PAGE_BITS; + lp = &l1_map[index >> L2_BITS]; + p = *lp; + if (!p) { + /* allocate if not found */ + p = malloc(sizeof(PageDesc) * L2_SIZE); + memset(p, 0, sizeof(sizeof(PageDesc) * L2_SIZE)); + *lp = p; + } + return p + (index & (L2_SIZE - 1)); +} + +int page_get_flags(unsigned long address) +{ + unsigned int index; + PageDesc *p; + + index = address >> TARGET_PAGE_BITS; + p = l1_map[index >> L2_BITS]; + if (!p) + return 0; + return p[index & (L2_SIZE - 1)].flags; +} + +void page_set_flags(unsigned long start, unsigned long end, int flags) +{ + PageDesc *p; + unsigned long addr; + + start = start & TARGET_PAGE_MASK; + end = TARGET_PAGE_ALIGN(end); + for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) { + p = page_find_alloc(addr); + p->flags = flags; + } +} |