root / exec.c @ 2a29ca73
History | View | Annotate | Download (4 kB)
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 |
} |