Statistics
| Branch: | Revision:

root / target-i386 / arch_memory_mapping.c @ 7feb640c

History | View | Annotate | Download (7.9 kB)

1 fae001f5 Wen Congyang
/*
2 fae001f5 Wen Congyang
 * i386 memory mapping
3 fae001f5 Wen Congyang
 *
4 fae001f5 Wen Congyang
 * Copyright Fujitsu, Corp. 2011, 2012
5 fae001f5 Wen Congyang
 *
6 fae001f5 Wen Congyang
 * Authors:
7 fae001f5 Wen Congyang
 *     Wen Congyang <wency@cn.fujitsu.com>
8 fae001f5 Wen Congyang
 *
9 fc0608ac Stefan Weil
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 fc0608ac Stefan Weil
 * See the COPYING file in the top-level directory.
11 fae001f5 Wen Congyang
 *
12 fae001f5 Wen Congyang
 */
13 fae001f5 Wen Congyang
14 fae001f5 Wen Congyang
#include "cpu.h"
15 022c62cb Paolo Bonzini
#include "exec/cpu-all.h"
16 9c17d615 Paolo Bonzini
#include "sysemu/memory_mapping.h"
17 fae001f5 Wen Congyang
18 fae001f5 Wen Congyang
/* PAE Paging or IA-32e Paging */
19 a8170e5e Avi Kivity
static void walk_pte(MemoryMappingList *list, hwaddr pte_start_addr,
20 fae001f5 Wen Congyang
                     int32_t a20_mask, target_ulong start_line_addr)
21 fae001f5 Wen Congyang
{
22 a8170e5e Avi Kivity
    hwaddr pte_addr, start_paddr;
23 fae001f5 Wen Congyang
    uint64_t pte;
24 fae001f5 Wen Congyang
    target_ulong start_vaddr;
25 fae001f5 Wen Congyang
    int i;
26 fae001f5 Wen Congyang
27 fae001f5 Wen Congyang
    for (i = 0; i < 512; i++) {
28 fae001f5 Wen Congyang
        pte_addr = (pte_start_addr + i * 8) & a20_mask;
29 fae001f5 Wen Congyang
        pte = ldq_phys(pte_addr);
30 fae001f5 Wen Congyang
        if (!(pte & PG_PRESENT_MASK)) {
31 fae001f5 Wen Congyang
            /* not present */
32 fae001f5 Wen Congyang
            continue;
33 fae001f5 Wen Congyang
        }
34 fae001f5 Wen Congyang
35 fae001f5 Wen Congyang
        start_paddr = (pte & ~0xfff) & ~(0x1ULL << 63);
36 fae001f5 Wen Congyang
        if (cpu_physical_memory_is_io(start_paddr)) {
37 fae001f5 Wen Congyang
            /* I/O region */
38 fae001f5 Wen Congyang
            continue;
39 fae001f5 Wen Congyang
        }
40 fae001f5 Wen Congyang
41 fae001f5 Wen Congyang
        start_vaddr = start_line_addr | ((i & 0x1fff) << 12);
42 fae001f5 Wen Congyang
        memory_mapping_list_add_merge_sorted(list, start_paddr,
43 fae001f5 Wen Congyang
                                             start_vaddr, 1 << 12);
44 fae001f5 Wen Congyang
    }
45 fae001f5 Wen Congyang
}
46 fae001f5 Wen Congyang
47 fae001f5 Wen Congyang
/* 32-bit Paging */
48 fae001f5 Wen Congyang
static void walk_pte2(MemoryMappingList *list,
49 a8170e5e Avi Kivity
                      hwaddr pte_start_addr, int32_t a20_mask,
50 fae001f5 Wen Congyang
                      target_ulong start_line_addr)
51 fae001f5 Wen Congyang
{
52 a8170e5e Avi Kivity
    hwaddr pte_addr, start_paddr;
53 fae001f5 Wen Congyang
    uint32_t pte;
54 fae001f5 Wen Congyang
    target_ulong start_vaddr;
55 fae001f5 Wen Congyang
    int i;
56 fae001f5 Wen Congyang
57 fae001f5 Wen Congyang
    for (i = 0; i < 1024; i++) {
58 fae001f5 Wen Congyang
        pte_addr = (pte_start_addr + i * 4) & a20_mask;
59 fae001f5 Wen Congyang
        pte = ldl_phys(pte_addr);
60 fae001f5 Wen Congyang
        if (!(pte & PG_PRESENT_MASK)) {
61 fae001f5 Wen Congyang
            /* not present */
62 fae001f5 Wen Congyang
            continue;
63 fae001f5 Wen Congyang
        }
64 fae001f5 Wen Congyang
65 fae001f5 Wen Congyang
        start_paddr = pte & ~0xfff;
66 fae001f5 Wen Congyang
        if (cpu_physical_memory_is_io(start_paddr)) {
67 fae001f5 Wen Congyang
            /* I/O region */
68 fae001f5 Wen Congyang
            continue;
69 fae001f5 Wen Congyang
        }
70 fae001f5 Wen Congyang
71 fae001f5 Wen Congyang
        start_vaddr = start_line_addr | ((i & 0x3ff) << 12);
72 fae001f5 Wen Congyang
        memory_mapping_list_add_merge_sorted(list, start_paddr,
73 fae001f5 Wen Congyang
                                             start_vaddr, 1 << 12);
74 fae001f5 Wen Congyang
    }
75 fae001f5 Wen Congyang
}
76 fae001f5 Wen Congyang
77 fae001f5 Wen Congyang
/* PAE Paging or IA-32e Paging */
78 a8170e5e Avi Kivity
static void walk_pde(MemoryMappingList *list, hwaddr pde_start_addr,
79 fae001f5 Wen Congyang
                     int32_t a20_mask, target_ulong start_line_addr)
80 fae001f5 Wen Congyang
{
81 a8170e5e Avi Kivity
    hwaddr pde_addr, pte_start_addr, start_paddr;
82 fae001f5 Wen Congyang
    uint64_t pde;
83 fae001f5 Wen Congyang
    target_ulong line_addr, start_vaddr;
84 fae001f5 Wen Congyang
    int i;
85 fae001f5 Wen Congyang
86 fae001f5 Wen Congyang
    for (i = 0; i < 512; i++) {
87 fae001f5 Wen Congyang
        pde_addr = (pde_start_addr + i * 8) & a20_mask;
88 fae001f5 Wen Congyang
        pde = ldq_phys(pde_addr);
89 fae001f5 Wen Congyang
        if (!(pde & PG_PRESENT_MASK)) {
90 fae001f5 Wen Congyang
            /* not present */
91 fae001f5 Wen Congyang
            continue;
92 fae001f5 Wen Congyang
        }
93 fae001f5 Wen Congyang
94 fae001f5 Wen Congyang
        line_addr = start_line_addr | ((i & 0x1ff) << 21);
95 fae001f5 Wen Congyang
        if (pde & PG_PSE_MASK) {
96 fae001f5 Wen Congyang
            /* 2 MB page */
97 fae001f5 Wen Congyang
            start_paddr = (pde & ~0x1fffff) & ~(0x1ULL << 63);
98 fae001f5 Wen Congyang
            if (cpu_physical_memory_is_io(start_paddr)) {
99 fae001f5 Wen Congyang
                /* I/O region */
100 fae001f5 Wen Congyang
                continue;
101 fae001f5 Wen Congyang
            }
102 fae001f5 Wen Congyang
            start_vaddr = line_addr;
103 fae001f5 Wen Congyang
            memory_mapping_list_add_merge_sorted(list, start_paddr,
104 fae001f5 Wen Congyang
                                                 start_vaddr, 1 << 21);
105 fae001f5 Wen Congyang
            continue;
106 fae001f5 Wen Congyang
        }
107 fae001f5 Wen Congyang
108 fae001f5 Wen Congyang
        pte_start_addr = (pde & ~0xfff) & a20_mask;
109 fae001f5 Wen Congyang
        walk_pte(list, pte_start_addr, a20_mask, line_addr);
110 fae001f5 Wen Congyang
    }
111 fae001f5 Wen Congyang
}
112 fae001f5 Wen Congyang
113 fae001f5 Wen Congyang
/* 32-bit Paging */
114 fae001f5 Wen Congyang
static void walk_pde2(MemoryMappingList *list,
115 a8170e5e Avi Kivity
                      hwaddr pde_start_addr, int32_t a20_mask,
116 fae001f5 Wen Congyang
                      bool pse)
117 fae001f5 Wen Congyang
{
118 6ad53bdf Wen Congyang
    hwaddr pde_addr, pte_start_addr, start_paddr, high_paddr;
119 fae001f5 Wen Congyang
    uint32_t pde;
120 fae001f5 Wen Congyang
    target_ulong line_addr, start_vaddr;
121 fae001f5 Wen Congyang
    int i;
122 fae001f5 Wen Congyang
123 fae001f5 Wen Congyang
    for (i = 0; i < 1024; i++) {
124 fae001f5 Wen Congyang
        pde_addr = (pde_start_addr + i * 4) & a20_mask;
125 fae001f5 Wen Congyang
        pde = ldl_phys(pde_addr);
126 fae001f5 Wen Congyang
        if (!(pde & PG_PRESENT_MASK)) {
127 fae001f5 Wen Congyang
            /* not present */
128 fae001f5 Wen Congyang
            continue;
129 fae001f5 Wen Congyang
        }
130 fae001f5 Wen Congyang
131 fae001f5 Wen Congyang
        line_addr = (((unsigned int)i & 0x3ff) << 22);
132 fae001f5 Wen Congyang
        if ((pde & PG_PSE_MASK) && pse) {
133 6ad53bdf Wen Congyang
            /*
134 6ad53bdf Wen Congyang
             * 4 MB page:
135 6ad53bdf Wen Congyang
             * bits 39:32 are bits 20:13 of the PDE
136 6ad53bdf Wen Congyang
             * bit3 31:22 are bits 31:22 of the PDE
137 6ad53bdf Wen Congyang
             */
138 6ad53bdf Wen Congyang
            high_paddr = ((hwaddr)(pde & 0x1fe000) << 19);
139 6ad53bdf Wen Congyang
            start_paddr = (pde & ~0x3fffff) | high_paddr;
140 fae001f5 Wen Congyang
            if (cpu_physical_memory_is_io(start_paddr)) {
141 fae001f5 Wen Congyang
                /* I/O region */
142 fae001f5 Wen Congyang
                continue;
143 fae001f5 Wen Congyang
            }
144 fae001f5 Wen Congyang
            start_vaddr = line_addr;
145 fae001f5 Wen Congyang
            memory_mapping_list_add_merge_sorted(list, start_paddr,
146 fae001f5 Wen Congyang
                                                 start_vaddr, 1 << 22);
147 fae001f5 Wen Congyang
            continue;
148 fae001f5 Wen Congyang
        }
149 fae001f5 Wen Congyang
150 fae001f5 Wen Congyang
        pte_start_addr = (pde & ~0xfff) & a20_mask;
151 fae001f5 Wen Congyang
        walk_pte2(list, pte_start_addr, a20_mask, line_addr);
152 fae001f5 Wen Congyang
    }
153 fae001f5 Wen Congyang
}
154 fae001f5 Wen Congyang
155 fae001f5 Wen Congyang
/* PAE Paging */
156 fae001f5 Wen Congyang
static void walk_pdpe2(MemoryMappingList *list,
157 a8170e5e Avi Kivity
                       hwaddr pdpe_start_addr, int32_t a20_mask)
158 fae001f5 Wen Congyang
{
159 a8170e5e Avi Kivity
    hwaddr pdpe_addr, pde_start_addr;
160 fae001f5 Wen Congyang
    uint64_t pdpe;
161 fae001f5 Wen Congyang
    target_ulong line_addr;
162 fae001f5 Wen Congyang
    int i;
163 fae001f5 Wen Congyang
164 fae001f5 Wen Congyang
    for (i = 0; i < 4; i++) {
165 fae001f5 Wen Congyang
        pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
166 fae001f5 Wen Congyang
        pdpe = ldq_phys(pdpe_addr);
167 fae001f5 Wen Congyang
        if (!(pdpe & PG_PRESENT_MASK)) {
168 fae001f5 Wen Congyang
            /* not present */
169 fae001f5 Wen Congyang
            continue;
170 fae001f5 Wen Congyang
        }
171 fae001f5 Wen Congyang
172 fae001f5 Wen Congyang
        line_addr = (((unsigned int)i & 0x3) << 30);
173 fae001f5 Wen Congyang
        pde_start_addr = (pdpe & ~0xfff) & a20_mask;
174 fae001f5 Wen Congyang
        walk_pde(list, pde_start_addr, a20_mask, line_addr);
175 fae001f5 Wen Congyang
    }
176 fae001f5 Wen Congyang
}
177 fae001f5 Wen Congyang
178 fae001f5 Wen Congyang
#ifdef TARGET_X86_64
179 fae001f5 Wen Congyang
/* IA-32e Paging */
180 fae001f5 Wen Congyang
static void walk_pdpe(MemoryMappingList *list,
181 a8170e5e Avi Kivity
                      hwaddr pdpe_start_addr, int32_t a20_mask,
182 fae001f5 Wen Congyang
                      target_ulong start_line_addr)
183 fae001f5 Wen Congyang
{
184 a8170e5e Avi Kivity
    hwaddr pdpe_addr, pde_start_addr, start_paddr;
185 fae001f5 Wen Congyang
    uint64_t pdpe;
186 fae001f5 Wen Congyang
    target_ulong line_addr, start_vaddr;
187 fae001f5 Wen Congyang
    int i;
188 fae001f5 Wen Congyang
189 fae001f5 Wen Congyang
    for (i = 0; i < 512; i++) {
190 fae001f5 Wen Congyang
        pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
191 fae001f5 Wen Congyang
        pdpe = ldq_phys(pdpe_addr);
192 fae001f5 Wen Congyang
        if (!(pdpe & PG_PRESENT_MASK)) {
193 fae001f5 Wen Congyang
            /* not present */
194 fae001f5 Wen Congyang
            continue;
195 fae001f5 Wen Congyang
        }
196 fae001f5 Wen Congyang
197 fae001f5 Wen Congyang
        line_addr = start_line_addr | ((i & 0x1ffULL) << 30);
198 fae001f5 Wen Congyang
        if (pdpe & PG_PSE_MASK) {
199 fae001f5 Wen Congyang
            /* 1 GB page */
200 fae001f5 Wen Congyang
            start_paddr = (pdpe & ~0x3fffffff) & ~(0x1ULL << 63);
201 fae001f5 Wen Congyang
            if (cpu_physical_memory_is_io(start_paddr)) {
202 fae001f5 Wen Congyang
                /* I/O region */
203 fae001f5 Wen Congyang
                continue;
204 fae001f5 Wen Congyang
            }
205 fae001f5 Wen Congyang
            start_vaddr = line_addr;
206 fae001f5 Wen Congyang
            memory_mapping_list_add_merge_sorted(list, start_paddr,
207 fae001f5 Wen Congyang
                                                 start_vaddr, 1 << 30);
208 fae001f5 Wen Congyang
            continue;
209 fae001f5 Wen Congyang
        }
210 fae001f5 Wen Congyang
211 fae001f5 Wen Congyang
        pde_start_addr = (pdpe & ~0xfff) & a20_mask;
212 fae001f5 Wen Congyang
        walk_pde(list, pde_start_addr, a20_mask, line_addr);
213 fae001f5 Wen Congyang
    }
214 fae001f5 Wen Congyang
}
215 fae001f5 Wen Congyang
216 fae001f5 Wen Congyang
/* IA-32e Paging */
217 fae001f5 Wen Congyang
static void walk_pml4e(MemoryMappingList *list,
218 a8170e5e Avi Kivity
                       hwaddr pml4e_start_addr, int32_t a20_mask)
219 fae001f5 Wen Congyang
{
220 a8170e5e Avi Kivity
    hwaddr pml4e_addr, pdpe_start_addr;
221 fae001f5 Wen Congyang
    uint64_t pml4e;
222 fae001f5 Wen Congyang
    target_ulong line_addr;
223 fae001f5 Wen Congyang
    int i;
224 fae001f5 Wen Congyang
225 fae001f5 Wen Congyang
    for (i = 0; i < 512; i++) {
226 fae001f5 Wen Congyang
        pml4e_addr = (pml4e_start_addr + i * 8) & a20_mask;
227 fae001f5 Wen Congyang
        pml4e = ldq_phys(pml4e_addr);
228 fae001f5 Wen Congyang
        if (!(pml4e & PG_PRESENT_MASK)) {
229 fae001f5 Wen Congyang
            /* not present */
230 fae001f5 Wen Congyang
            continue;
231 fae001f5 Wen Congyang
        }
232 fae001f5 Wen Congyang
233 fae001f5 Wen Congyang
        line_addr = ((i & 0x1ffULL) << 39) | (0xffffULL << 48);
234 fae001f5 Wen Congyang
        pdpe_start_addr = (pml4e & ~0xfff) & a20_mask;
235 fae001f5 Wen Congyang
        walk_pdpe(list, pdpe_start_addr, a20_mask, line_addr);
236 fae001f5 Wen Congyang
    }
237 fae001f5 Wen Congyang
}
238 fae001f5 Wen Congyang
#endif
239 fae001f5 Wen Congyang
240 fae001f5 Wen Congyang
int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env)
241 fae001f5 Wen Congyang
{
242 31a2207a Wen Congyang
    if (!cpu_paging_enabled(env)) {
243 fae001f5 Wen Congyang
        /* paging is disabled */
244 fae001f5 Wen Congyang
        return 0;
245 fae001f5 Wen Congyang
    }
246 fae001f5 Wen Congyang
247 fae001f5 Wen Congyang
    if (env->cr[4] & CR4_PAE_MASK) {
248 fae001f5 Wen Congyang
#ifdef TARGET_X86_64
249 fae001f5 Wen Congyang
        if (env->hflags & HF_LMA_MASK) {
250 a8170e5e Avi Kivity
            hwaddr pml4e_addr;
251 fae001f5 Wen Congyang
252 fae001f5 Wen Congyang
            pml4e_addr = (env->cr[3] & ~0xfff) & env->a20_mask;
253 fae001f5 Wen Congyang
            walk_pml4e(list, pml4e_addr, env->a20_mask);
254 fae001f5 Wen Congyang
        } else
255 fae001f5 Wen Congyang
#endif
256 fae001f5 Wen Congyang
        {
257 a8170e5e Avi Kivity
            hwaddr pdpe_addr;
258 fae001f5 Wen Congyang
259 fae001f5 Wen Congyang
            pdpe_addr = (env->cr[3] & ~0x1f) & env->a20_mask;
260 fae001f5 Wen Congyang
            walk_pdpe2(list, pdpe_addr, env->a20_mask);
261 fae001f5 Wen Congyang
        }
262 fae001f5 Wen Congyang
    } else {
263 a8170e5e Avi Kivity
        hwaddr pde_addr;
264 fae001f5 Wen Congyang
        bool pse;
265 fae001f5 Wen Congyang
266 fae001f5 Wen Congyang
        pde_addr = (env->cr[3] & ~0xfff) & env->a20_mask;
267 fae001f5 Wen Congyang
        pse = !!(env->cr[4] & CR4_PSE_MASK);
268 fae001f5 Wen Congyang
        walk_pde2(list, pde_addr, env->a20_mask, pse);
269 fae001f5 Wen Congyang
    }
270 fae001f5 Wen Congyang
271 fae001f5 Wen Congyang
    return 0;
272 fae001f5 Wen Congyang
}
273 31a2207a Wen Congyang
274 31a2207a Wen Congyang
bool cpu_paging_enabled(CPUArchState *env)
275 31a2207a Wen Congyang
{
276 31a2207a Wen Congyang
    return env->cr[0] & CR0_PG_MASK;
277 31a2207a Wen Congyang
}