root / exec.c @ 2a29ca73
History | View | Annotate | Download (4 kB)
1 | 54936004 | bellard | /*
|
---|---|---|---|
2 | 54936004 | bellard | * virtual page mapping
|
3 | 54936004 | bellard | *
|
4 | 54936004 | bellard | * Copyright (c) 2003 Fabrice Bellard
|
5 | 54936004 | bellard | *
|
6 | 54936004 | bellard | * This library is free software; you can redistribute it and/or
|
7 | 54936004 | bellard | * modify it under the terms of the GNU Lesser General Public
|
8 | 54936004 | bellard | * License as published by the Free Software Foundation; either
|
9 | 54936004 | bellard | * version 2 of the License, or (at your option) any later version.
|
10 | 54936004 | bellard | *
|
11 | 54936004 | bellard | * This library is distributed in the hope that it will be useful,
|
12 | 54936004 | bellard | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | 54936004 | bellard | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 | 54936004 | bellard | * Lesser General Public License for more details.
|
15 | 54936004 | bellard | *
|
16 | 54936004 | bellard | * You should have received a copy of the GNU Lesser General Public
|
17 | 54936004 | bellard | * License along with this library; if not, write to the Free Software
|
18 | 54936004 | bellard | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
19 | 54936004 | bellard | */
|
20 | 54936004 | bellard | #include <stdlib.h> |
21 | 54936004 | bellard | #include <stdio.h> |
22 | 54936004 | bellard | #include <stdarg.h> |
23 | 54936004 | bellard | #include <string.h> |
24 | 54936004 | bellard | #include <errno.h> |
25 | 54936004 | bellard | #include <unistd.h> |
26 | 54936004 | bellard | #include <inttypes.h> |
27 | 54936004 | bellard | |
28 | 54936004 | bellard | #include "cpu-i386.h" |
29 | 54936004 | bellard | |
30 | 54936004 | bellard | /* XXX: pack the flags in the low bits of the pointer ? */
|
31 | 54936004 | bellard | typedef struct PageDesc { |
32 | 54936004 | bellard | struct TranslationBlock *first_tb;
|
33 | 54936004 | bellard | unsigned long flags; |
34 | 54936004 | bellard | } PageDesc; |
35 | 54936004 | bellard | |
36 | 54936004 | bellard | #define L2_BITS 10 |
37 | 54936004 | bellard | #define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS) |
38 | 54936004 | bellard | |
39 | 54936004 | bellard | #define L1_SIZE (1 << L1_BITS) |
40 | 54936004 | bellard | #define L2_SIZE (1 << L2_BITS) |
41 | 54936004 | bellard | |
42 | 54936004 | bellard | unsigned long real_host_page_size; |
43 | 54936004 | bellard | unsigned long host_page_bits; |
44 | 54936004 | bellard | unsigned long host_page_size; |
45 | 54936004 | bellard | unsigned long host_page_mask; |
46 | 54936004 | bellard | |
47 | 54936004 | bellard | static PageDesc *l1_map[L1_SIZE];
|
48 | 54936004 | bellard | |
49 | 54936004 | bellard | void page_init(void) |
50 | 54936004 | bellard | { |
51 | 54936004 | bellard | /* NOTE: we can always suppose that host_page_size >=
|
52 | 54936004 | bellard | TARGET_PAGE_SIZE */
|
53 | 54936004 | bellard | real_host_page_size = getpagesize(); |
54 | 54936004 | bellard | if (host_page_size == 0) |
55 | 54936004 | bellard | host_page_size = real_host_page_size; |
56 | 54936004 | bellard | if (host_page_size < TARGET_PAGE_SIZE)
|
57 | 54936004 | bellard | host_page_size = TARGET_PAGE_SIZE; |
58 | 54936004 | bellard | host_page_bits = 0;
|
59 | 54936004 | bellard | while ((1 << host_page_bits) < host_page_size) |
60 | 54936004 | bellard | host_page_bits++; |
61 | 54936004 | bellard | host_page_mask = ~(host_page_size - 1);
|
62 | 54936004 | bellard | } |
63 | 54936004 | bellard | |
64 | 54936004 | bellard | /* dump memory mappings */
|
65 | 54936004 | bellard | void page_dump(FILE *f)
|
66 | 54936004 | bellard | { |
67 | 54936004 | bellard | unsigned long start, end; |
68 | 54936004 | bellard | int i, j, prot, prot1;
|
69 | 54936004 | bellard | PageDesc *p; |
70 | 54936004 | bellard | |
71 | 54936004 | bellard | fprintf(f, "%-8s %-8s %-8s %s\n",
|
72 | 54936004 | bellard | "start", "end", "size", "prot"); |
73 | 54936004 | bellard | start = -1;
|
74 | 54936004 | bellard | end = -1;
|
75 | 54936004 | bellard | prot = 0;
|
76 | 54936004 | bellard | for(i = 0; i <= L1_SIZE; i++) { |
77 | 54936004 | bellard | if (i < L1_SIZE)
|
78 | 54936004 | bellard | p = l1_map[i]; |
79 | 54936004 | bellard | else
|
80 | 54936004 | bellard | p = NULL;
|
81 | 54936004 | bellard | for(j = 0;j < L2_SIZE; j++) { |
82 | 54936004 | bellard | if (!p)
|
83 | 54936004 | bellard | prot1 = 0;
|
84 | 54936004 | bellard | else
|
85 | 54936004 | bellard | prot1 = p[j].flags; |
86 | 54936004 | bellard | if (prot1 != prot) {
|
87 | 54936004 | bellard | end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS);
|
88 | 54936004 | bellard | if (start != -1) { |
89 | 54936004 | bellard | fprintf(f, "%08lx-%08lx %08lx %c%c%c\n",
|
90 | 54936004 | bellard | start, end, end - start, |
91 | 54936004 | bellard | prot & PAGE_READ ? 'r' : '-', |
92 | 54936004 | bellard | prot & PAGE_WRITE ? 'w' : '-', |
93 | 54936004 | bellard | prot & PAGE_EXEC ? 'x' : '-'); |
94 | 54936004 | bellard | } |
95 | 54936004 | bellard | if (prot1 != 0) |
96 | 54936004 | bellard | start = end; |
97 | 54936004 | bellard | else
|
98 | 54936004 | bellard | start = -1;
|
99 | 54936004 | bellard | prot = prot1; |
100 | 54936004 | bellard | } |
101 | 54936004 | bellard | if (!p)
|
102 | 54936004 | bellard | break;
|
103 | 54936004 | bellard | } |
104 | 54936004 | bellard | } |
105 | 54936004 | bellard | } |
106 | 54936004 | bellard | |
107 | 54936004 | bellard | |
108 | 54936004 | bellard | static inline PageDesc *page_find_alloc(unsigned long address) |
109 | 54936004 | bellard | { |
110 | 54936004 | bellard | unsigned int index; |
111 | 54936004 | bellard | PageDesc **lp, *p; |
112 | 54936004 | bellard | |
113 | 54936004 | bellard | index = address >> TARGET_PAGE_BITS; |
114 | 54936004 | bellard | lp = &l1_map[index >> L2_BITS]; |
115 | 54936004 | bellard | p = *lp; |
116 | 54936004 | bellard | if (!p) {
|
117 | 54936004 | bellard | /* allocate if not found */
|
118 | 54936004 | bellard | p = malloc(sizeof(PageDesc) * L2_SIZE);
|
119 | 54936004 | bellard | memset(p, 0, sizeof(sizeof(PageDesc) * L2_SIZE)); |
120 | 54936004 | bellard | *lp = p; |
121 | 54936004 | bellard | } |
122 | 54936004 | bellard | return p + (index & (L2_SIZE - 1)); |
123 | 54936004 | bellard | } |
124 | 54936004 | bellard | |
125 | 54936004 | bellard | int page_get_flags(unsigned long address) |
126 | 54936004 | bellard | { |
127 | 54936004 | bellard | unsigned int index; |
128 | 54936004 | bellard | PageDesc *p; |
129 | 54936004 | bellard | |
130 | 54936004 | bellard | index = address >> TARGET_PAGE_BITS; |
131 | 54936004 | bellard | p = l1_map[index >> L2_BITS]; |
132 | 54936004 | bellard | if (!p)
|
133 | 54936004 | bellard | return 0; |
134 | 54936004 | bellard | return p[index & (L2_SIZE - 1)].flags; |
135 | 54936004 | bellard | } |
136 | 54936004 | bellard | |
137 | 54936004 | bellard | void page_set_flags(unsigned long start, unsigned long end, int flags) |
138 | 54936004 | bellard | { |
139 | 54936004 | bellard | PageDesc *p; |
140 | 54936004 | bellard | unsigned long addr; |
141 | 54936004 | bellard | |
142 | 54936004 | bellard | start = start & TARGET_PAGE_MASK; |
143 | 54936004 | bellard | end = TARGET_PAGE_ALIGN(end); |
144 | 54936004 | bellard | for(addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
|
145 | 54936004 | bellard | p = page_find_alloc(addr); |
146 | 54936004 | bellard | p->flags = flags; |
147 | 54936004 | bellard | } |
148 | 54936004 | bellard | } |