]> git.ipfire.org Git - thirdparty/qemu.git/blame - exec.c
mmap emulation
[thirdparty/qemu.git] / exec.c
CommitLineData
54936004
FB
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 ? */
31typedef 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
42unsigned long real_host_page_size;
43unsigned long host_page_bits;
44unsigned long host_page_size;
45unsigned long host_page_mask;
46
47static PageDesc *l1_map[L1_SIZE];
48
49void 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 */
65void 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
108static 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
125int 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
137void 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}