Statistics
| Branch: | Revision:

root / target-i386 / arch_memory_mapping.c @ d7582078

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 fae001f5 Wen Congyang
#include "cpu-all.h"
16 5f86146f Paolo Bonzini
#include "memory_mapping.h"
17 fae001f5 Wen Congyang
18 fae001f5 Wen Congyang
/* PAE Paging or IA-32e Paging */
19 fae001f5 Wen Congyang
static void walk_pte(MemoryMappingList *list, target_phys_addr_t pte_start_addr,
20 fae001f5 Wen Congyang
                     int32_t a20_mask, target_ulong start_line_addr)
21 fae001f5 Wen Congyang
{
22 fae001f5 Wen Congyang
    target_phys_addr_t 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 fae001f5 Wen Congyang
                      target_phys_addr_t pte_start_addr, int32_t a20_mask,
50 fae001f5 Wen Congyang
                      target_ulong start_line_addr)
51 fae001f5 Wen Congyang
{
52 fae001f5 Wen Congyang
    target_phys_addr_t 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 fae001f5 Wen Congyang
static void walk_pde(MemoryMappingList *list, target_phys_addr_t pde_start_addr,
79 fae001f5 Wen Congyang
                     int32_t a20_mask, target_ulong start_line_addr)
80 fae001f5 Wen Congyang
{
81 fae001f5 Wen Congyang
    target_phys_addr_t 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 fae001f5 Wen Congyang
                      target_phys_addr_t pde_start_addr, int32_t a20_mask,
116 fae001f5 Wen Congyang
                      bool pse)
117 fae001f5 Wen Congyang
{
118 fae001f5 Wen Congyang
    target_phys_addr_t pde_addr, pte_start_addr, start_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 fae001f5 Wen Congyang
            /* 4 MB page */
134 fae001f5 Wen Congyang
            start_paddr = (pde & ~0x3fffff) | ((pde & 0x1fe000) << 19);
135 fae001f5 Wen Congyang
            if (cpu_physical_memory_is_io(start_paddr)) {
136 fae001f5 Wen Congyang
                /* I/O region */
137 fae001f5 Wen Congyang
                continue;
138 fae001f5 Wen Congyang
            }
139 fae001f5 Wen Congyang
            start_vaddr = line_addr;
140 fae001f5 Wen Congyang
            memory_mapping_list_add_merge_sorted(list, start_paddr,
141 fae001f5 Wen Congyang
                                                 start_vaddr, 1 << 22);
142 fae001f5 Wen Congyang
            continue;
143 fae001f5 Wen Congyang
        }
144 fae001f5 Wen Congyang
145 fae001f5 Wen Congyang
        pte_start_addr = (pde & ~0xfff) & a20_mask;
146 fae001f5 Wen Congyang
        walk_pte2(list, pte_start_addr, a20_mask, line_addr);
147 fae001f5 Wen Congyang
    }
148 fae001f5 Wen Congyang
}
149 fae001f5 Wen Congyang
150 fae001f5 Wen Congyang
/* PAE Paging */
151 fae001f5 Wen Congyang
static void walk_pdpe2(MemoryMappingList *list,
152 fae001f5 Wen Congyang
                       target_phys_addr_t pdpe_start_addr, int32_t a20_mask)
153 fae001f5 Wen Congyang
{
154 fae001f5 Wen Congyang
    target_phys_addr_t pdpe_addr, pde_start_addr;
155 fae001f5 Wen Congyang
    uint64_t pdpe;
156 fae001f5 Wen Congyang
    target_ulong line_addr;
157 fae001f5 Wen Congyang
    int i;
158 fae001f5 Wen Congyang
159 fae001f5 Wen Congyang
    for (i = 0; i < 4; i++) {
160 fae001f5 Wen Congyang
        pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
161 fae001f5 Wen Congyang
        pdpe = ldq_phys(pdpe_addr);
162 fae001f5 Wen Congyang
        if (!(pdpe & PG_PRESENT_MASK)) {
163 fae001f5 Wen Congyang
            /* not present */
164 fae001f5 Wen Congyang
            continue;
165 fae001f5 Wen Congyang
        }
166 fae001f5 Wen Congyang
167 fae001f5 Wen Congyang
        line_addr = (((unsigned int)i & 0x3) << 30);
168 fae001f5 Wen Congyang
        pde_start_addr = (pdpe & ~0xfff) & a20_mask;
169 fae001f5 Wen Congyang
        walk_pde(list, pde_start_addr, a20_mask, line_addr);
170 fae001f5 Wen Congyang
    }
171 fae001f5 Wen Congyang
}
172 fae001f5 Wen Congyang
173 fae001f5 Wen Congyang
#ifdef TARGET_X86_64
174 fae001f5 Wen Congyang
/* IA-32e Paging */
175 fae001f5 Wen Congyang
static void walk_pdpe(MemoryMappingList *list,
176 fae001f5 Wen Congyang
                      target_phys_addr_t pdpe_start_addr, int32_t a20_mask,
177 fae001f5 Wen Congyang
                      target_ulong start_line_addr)
178 fae001f5 Wen Congyang
{
179 fae001f5 Wen Congyang
    target_phys_addr_t pdpe_addr, pde_start_addr, start_paddr;
180 fae001f5 Wen Congyang
    uint64_t pdpe;
181 fae001f5 Wen Congyang
    target_ulong line_addr, start_vaddr;
182 fae001f5 Wen Congyang
    int i;
183 fae001f5 Wen Congyang
184 fae001f5 Wen Congyang
    for (i = 0; i < 512; i++) {
185 fae001f5 Wen Congyang
        pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
186 fae001f5 Wen Congyang
        pdpe = ldq_phys(pdpe_addr);
187 fae001f5 Wen Congyang
        if (!(pdpe & PG_PRESENT_MASK)) {
188 fae001f5 Wen Congyang
            /* not present */
189 fae001f5 Wen Congyang
            continue;
190 fae001f5 Wen Congyang
        }
191 fae001f5 Wen Congyang
192 fae001f5 Wen Congyang
        line_addr = start_line_addr | ((i & 0x1ffULL) << 30);
193 fae001f5 Wen Congyang
        if (pdpe & PG_PSE_MASK) {
194 fae001f5 Wen Congyang
            /* 1 GB page */
195 fae001f5 Wen Congyang
            start_paddr = (pdpe & ~0x3fffffff) & ~(0x1ULL << 63);
196 fae001f5 Wen Congyang
            if (cpu_physical_memory_is_io(start_paddr)) {
197 fae001f5 Wen Congyang
                /* I/O region */
198 fae001f5 Wen Congyang
                continue;
199 fae001f5 Wen Congyang
            }
200 fae001f5 Wen Congyang
            start_vaddr = line_addr;
201 fae001f5 Wen Congyang
            memory_mapping_list_add_merge_sorted(list, start_paddr,
202 fae001f5 Wen Congyang
                                                 start_vaddr, 1 << 30);
203 fae001f5 Wen Congyang
            continue;
204 fae001f5 Wen Congyang
        }
205 fae001f5 Wen Congyang
206 fae001f5 Wen Congyang
        pde_start_addr = (pdpe & ~0xfff) & a20_mask;
207 fae001f5 Wen Congyang
        walk_pde(list, pde_start_addr, a20_mask, line_addr);
208 fae001f5 Wen Congyang
    }
209 fae001f5 Wen Congyang
}
210 fae001f5 Wen Congyang
211 fae001f5 Wen Congyang
/* IA-32e Paging */
212 fae001f5 Wen Congyang
static void walk_pml4e(MemoryMappingList *list,
213 fae001f5 Wen Congyang
                       target_phys_addr_t pml4e_start_addr, int32_t a20_mask)
214 fae001f5 Wen Congyang
{
215 fae001f5 Wen Congyang
    target_phys_addr_t pml4e_addr, pdpe_start_addr;
216 fae001f5 Wen Congyang
    uint64_t pml4e;
217 fae001f5 Wen Congyang
    target_ulong line_addr;
218 fae001f5 Wen Congyang
    int i;
219 fae001f5 Wen Congyang
220 fae001f5 Wen Congyang
    for (i = 0; i < 512; i++) {
221 fae001f5 Wen Congyang
        pml4e_addr = (pml4e_start_addr + i * 8) & a20_mask;
222 fae001f5 Wen Congyang
        pml4e = ldq_phys(pml4e_addr);
223 fae001f5 Wen Congyang
        if (!(pml4e & PG_PRESENT_MASK)) {
224 fae001f5 Wen Congyang
            /* not present */
225 fae001f5 Wen Congyang
            continue;
226 fae001f5 Wen Congyang
        }
227 fae001f5 Wen Congyang
228 fae001f5 Wen Congyang
        line_addr = ((i & 0x1ffULL) << 39) | (0xffffULL << 48);
229 fae001f5 Wen Congyang
        pdpe_start_addr = (pml4e & ~0xfff) & a20_mask;
230 fae001f5 Wen Congyang
        walk_pdpe(list, pdpe_start_addr, a20_mask, line_addr);
231 fae001f5 Wen Congyang
    }
232 fae001f5 Wen Congyang
}
233 fae001f5 Wen Congyang
#endif
234 fae001f5 Wen Congyang
235 fae001f5 Wen Congyang
int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env)
236 fae001f5 Wen Congyang
{
237 31a2207a Wen Congyang
    if (!cpu_paging_enabled(env)) {
238 fae001f5 Wen Congyang
        /* paging is disabled */
239 fae001f5 Wen Congyang
        return 0;
240 fae001f5 Wen Congyang
    }
241 fae001f5 Wen Congyang
242 fae001f5 Wen Congyang
    if (env->cr[4] & CR4_PAE_MASK) {
243 fae001f5 Wen Congyang
#ifdef TARGET_X86_64
244 fae001f5 Wen Congyang
        if (env->hflags & HF_LMA_MASK) {
245 fae001f5 Wen Congyang
            target_phys_addr_t pml4e_addr;
246 fae001f5 Wen Congyang
247 fae001f5 Wen Congyang
            pml4e_addr = (env->cr[3] & ~0xfff) & env->a20_mask;
248 fae001f5 Wen Congyang
            walk_pml4e(list, pml4e_addr, env->a20_mask);
249 fae001f5 Wen Congyang
        } else
250 fae001f5 Wen Congyang
#endif
251 fae001f5 Wen Congyang
        {
252 fae001f5 Wen Congyang
            target_phys_addr_t pdpe_addr;
253 fae001f5 Wen Congyang
254 fae001f5 Wen Congyang
            pdpe_addr = (env->cr[3] & ~0x1f) & env->a20_mask;
255 fae001f5 Wen Congyang
            walk_pdpe2(list, pdpe_addr, env->a20_mask);
256 fae001f5 Wen Congyang
        }
257 fae001f5 Wen Congyang
    } else {
258 fae001f5 Wen Congyang
        target_phys_addr_t pde_addr;
259 fae001f5 Wen Congyang
        bool pse;
260 fae001f5 Wen Congyang
261 fae001f5 Wen Congyang
        pde_addr = (env->cr[3] & ~0xfff) & env->a20_mask;
262 fae001f5 Wen Congyang
        pse = !!(env->cr[4] & CR4_PSE_MASK);
263 fae001f5 Wen Congyang
        walk_pde2(list, pde_addr, env->a20_mask, pse);
264 fae001f5 Wen Congyang
    }
265 fae001f5 Wen Congyang
266 fae001f5 Wen Congyang
    return 0;
267 fae001f5 Wen Congyang
}
268 31a2207a Wen Congyang
269 31a2207a Wen Congyang
bool cpu_paging_enabled(CPUArchState *env)
270 31a2207a Wen Congyang
{
271 31a2207a Wen Congyang
    return env->cr[0] & CR0_PG_MASK;
272 31a2207a Wen Congyang
}