Statistics
| Branch: | Revision:

root / target-i386 / arch_memory_mapping.c @ 444ba679

History | View | Annotate | Download (8 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 bff63471 Qiao Nuohan
        start_vaddr = start_line_addr | ((i & 0x1ff) << 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 fbc2ed95 Luiz Capitulino
#define PLM4_ADDR_MASK 0xffffffffff000 /* selects bits 51:12 */
79 fbc2ed95 Luiz Capitulino
80 a8170e5e Avi Kivity
static void walk_pde(MemoryMappingList *list, hwaddr pde_start_addr,
81 fae001f5 Wen Congyang
                     int32_t a20_mask, target_ulong start_line_addr)
82 fae001f5 Wen Congyang
{
83 a8170e5e Avi Kivity
    hwaddr pde_addr, pte_start_addr, start_paddr;
84 fae001f5 Wen Congyang
    uint64_t pde;
85 fae001f5 Wen Congyang
    target_ulong line_addr, start_vaddr;
86 fae001f5 Wen Congyang
    int i;
87 fae001f5 Wen Congyang
88 fae001f5 Wen Congyang
    for (i = 0; i < 512; i++) {
89 fae001f5 Wen Congyang
        pde_addr = (pde_start_addr + i * 8) & a20_mask;
90 fae001f5 Wen Congyang
        pde = ldq_phys(pde_addr);
91 fae001f5 Wen Congyang
        if (!(pde & PG_PRESENT_MASK)) {
92 fae001f5 Wen Congyang
            /* not present */
93 fae001f5 Wen Congyang
            continue;
94 fae001f5 Wen Congyang
        }
95 fae001f5 Wen Congyang
96 fae001f5 Wen Congyang
        line_addr = start_line_addr | ((i & 0x1ff) << 21);
97 fae001f5 Wen Congyang
        if (pde & PG_PSE_MASK) {
98 fae001f5 Wen Congyang
            /* 2 MB page */
99 fae001f5 Wen Congyang
            start_paddr = (pde & ~0x1fffff) & ~(0x1ULL << 63);
100 fae001f5 Wen Congyang
            if (cpu_physical_memory_is_io(start_paddr)) {
101 fae001f5 Wen Congyang
                /* I/O region */
102 fae001f5 Wen Congyang
                continue;
103 fae001f5 Wen Congyang
            }
104 fae001f5 Wen Congyang
            start_vaddr = line_addr;
105 fae001f5 Wen Congyang
            memory_mapping_list_add_merge_sorted(list, start_paddr,
106 fae001f5 Wen Congyang
                                                 start_vaddr, 1 << 21);
107 fae001f5 Wen Congyang
            continue;
108 fae001f5 Wen Congyang
        }
109 fae001f5 Wen Congyang
110 fbc2ed95 Luiz Capitulino
        pte_start_addr = (pde & PLM4_ADDR_MASK) & a20_mask;
111 fae001f5 Wen Congyang
        walk_pte(list, pte_start_addr, a20_mask, line_addr);
112 fae001f5 Wen Congyang
    }
113 fae001f5 Wen Congyang
}
114 fae001f5 Wen Congyang
115 fae001f5 Wen Congyang
/* 32-bit Paging */
116 fae001f5 Wen Congyang
static void walk_pde2(MemoryMappingList *list,
117 a8170e5e Avi Kivity
                      hwaddr pde_start_addr, int32_t a20_mask,
118 fae001f5 Wen Congyang
                      bool pse)
119 fae001f5 Wen Congyang
{
120 6ad53bdf Wen Congyang
    hwaddr pde_addr, pte_start_addr, start_paddr, high_paddr;
121 fae001f5 Wen Congyang
    uint32_t pde;
122 fae001f5 Wen Congyang
    target_ulong line_addr, start_vaddr;
123 fae001f5 Wen Congyang
    int i;
124 fae001f5 Wen Congyang
125 fae001f5 Wen Congyang
    for (i = 0; i < 1024; i++) {
126 fae001f5 Wen Congyang
        pde_addr = (pde_start_addr + i * 4) & a20_mask;
127 fae001f5 Wen Congyang
        pde = ldl_phys(pde_addr);
128 fae001f5 Wen Congyang
        if (!(pde & PG_PRESENT_MASK)) {
129 fae001f5 Wen Congyang
            /* not present */
130 fae001f5 Wen Congyang
            continue;
131 fae001f5 Wen Congyang
        }
132 fae001f5 Wen Congyang
133 fae001f5 Wen Congyang
        line_addr = (((unsigned int)i & 0x3ff) << 22);
134 fae001f5 Wen Congyang
        if ((pde & PG_PSE_MASK) && pse) {
135 6ad53bdf Wen Congyang
            /*
136 6ad53bdf Wen Congyang
             * 4 MB page:
137 6ad53bdf Wen Congyang
             * bits 39:32 are bits 20:13 of the PDE
138 6ad53bdf Wen Congyang
             * bit3 31:22 are bits 31:22 of the PDE
139 6ad53bdf Wen Congyang
             */
140 6ad53bdf Wen Congyang
            high_paddr = ((hwaddr)(pde & 0x1fe000) << 19);
141 6ad53bdf Wen Congyang
            start_paddr = (pde & ~0x3fffff) | high_paddr;
142 fae001f5 Wen Congyang
            if (cpu_physical_memory_is_io(start_paddr)) {
143 fae001f5 Wen Congyang
                /* I/O region */
144 fae001f5 Wen Congyang
                continue;
145 fae001f5 Wen Congyang
            }
146 fae001f5 Wen Congyang
            start_vaddr = line_addr;
147 fae001f5 Wen Congyang
            memory_mapping_list_add_merge_sorted(list, start_paddr,
148 fae001f5 Wen Congyang
                                                 start_vaddr, 1 << 22);
149 fae001f5 Wen Congyang
            continue;
150 fae001f5 Wen Congyang
        }
151 fae001f5 Wen Congyang
152 fae001f5 Wen Congyang
        pte_start_addr = (pde & ~0xfff) & a20_mask;
153 fae001f5 Wen Congyang
        walk_pte2(list, pte_start_addr, a20_mask, line_addr);
154 fae001f5 Wen Congyang
    }
155 fae001f5 Wen Congyang
}
156 fae001f5 Wen Congyang
157 fae001f5 Wen Congyang
/* PAE Paging */
158 fae001f5 Wen Congyang
static void walk_pdpe2(MemoryMappingList *list,
159 a8170e5e Avi Kivity
                       hwaddr pdpe_start_addr, int32_t a20_mask)
160 fae001f5 Wen Congyang
{
161 a8170e5e Avi Kivity
    hwaddr pdpe_addr, pde_start_addr;
162 fae001f5 Wen Congyang
    uint64_t pdpe;
163 fae001f5 Wen Congyang
    target_ulong line_addr;
164 fae001f5 Wen Congyang
    int i;
165 fae001f5 Wen Congyang
166 fae001f5 Wen Congyang
    for (i = 0; i < 4; i++) {
167 fae001f5 Wen Congyang
        pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
168 fae001f5 Wen Congyang
        pdpe = ldq_phys(pdpe_addr);
169 fae001f5 Wen Congyang
        if (!(pdpe & PG_PRESENT_MASK)) {
170 fae001f5 Wen Congyang
            /* not present */
171 fae001f5 Wen Congyang
            continue;
172 fae001f5 Wen Congyang
        }
173 fae001f5 Wen Congyang
174 fae001f5 Wen Congyang
        line_addr = (((unsigned int)i & 0x3) << 30);
175 fae001f5 Wen Congyang
        pde_start_addr = (pdpe & ~0xfff) & a20_mask;
176 fae001f5 Wen Congyang
        walk_pde(list, pde_start_addr, a20_mask, line_addr);
177 fae001f5 Wen Congyang
    }
178 fae001f5 Wen Congyang
}
179 fae001f5 Wen Congyang
180 fae001f5 Wen Congyang
#ifdef TARGET_X86_64
181 fae001f5 Wen Congyang
/* IA-32e Paging */
182 fae001f5 Wen Congyang
static void walk_pdpe(MemoryMappingList *list,
183 a8170e5e Avi Kivity
                      hwaddr pdpe_start_addr, int32_t a20_mask,
184 fae001f5 Wen Congyang
                      target_ulong start_line_addr)
185 fae001f5 Wen Congyang
{
186 a8170e5e Avi Kivity
    hwaddr pdpe_addr, pde_start_addr, start_paddr;
187 fae001f5 Wen Congyang
    uint64_t pdpe;
188 fae001f5 Wen Congyang
    target_ulong line_addr, start_vaddr;
189 fae001f5 Wen Congyang
    int i;
190 fae001f5 Wen Congyang
191 fae001f5 Wen Congyang
    for (i = 0; i < 512; i++) {
192 fae001f5 Wen Congyang
        pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
193 fae001f5 Wen Congyang
        pdpe = ldq_phys(pdpe_addr);
194 fae001f5 Wen Congyang
        if (!(pdpe & PG_PRESENT_MASK)) {
195 fae001f5 Wen Congyang
            /* not present */
196 fae001f5 Wen Congyang
            continue;
197 fae001f5 Wen Congyang
        }
198 fae001f5 Wen Congyang
199 fae001f5 Wen Congyang
        line_addr = start_line_addr | ((i & 0x1ffULL) << 30);
200 fae001f5 Wen Congyang
        if (pdpe & PG_PSE_MASK) {
201 fae001f5 Wen Congyang
            /* 1 GB page */
202 fae001f5 Wen Congyang
            start_paddr = (pdpe & ~0x3fffffff) & ~(0x1ULL << 63);
203 fae001f5 Wen Congyang
            if (cpu_physical_memory_is_io(start_paddr)) {
204 fae001f5 Wen Congyang
                /* I/O region */
205 fae001f5 Wen Congyang
                continue;
206 fae001f5 Wen Congyang
            }
207 fae001f5 Wen Congyang
            start_vaddr = line_addr;
208 fae001f5 Wen Congyang
            memory_mapping_list_add_merge_sorted(list, start_paddr,
209 fae001f5 Wen Congyang
                                                 start_vaddr, 1 << 30);
210 fae001f5 Wen Congyang
            continue;
211 fae001f5 Wen Congyang
        }
212 fae001f5 Wen Congyang
213 fbc2ed95 Luiz Capitulino
        pde_start_addr = (pdpe & PLM4_ADDR_MASK) & a20_mask;
214 fae001f5 Wen Congyang
        walk_pde(list, pde_start_addr, a20_mask, line_addr);
215 fae001f5 Wen Congyang
    }
216 fae001f5 Wen Congyang
}
217 fae001f5 Wen Congyang
218 fae001f5 Wen Congyang
/* IA-32e Paging */
219 fae001f5 Wen Congyang
static void walk_pml4e(MemoryMappingList *list,
220 a8170e5e Avi Kivity
                       hwaddr pml4e_start_addr, int32_t a20_mask)
221 fae001f5 Wen Congyang
{
222 a8170e5e Avi Kivity
    hwaddr pml4e_addr, pdpe_start_addr;
223 fae001f5 Wen Congyang
    uint64_t pml4e;
224 fae001f5 Wen Congyang
    target_ulong line_addr;
225 fae001f5 Wen Congyang
    int i;
226 fae001f5 Wen Congyang
227 fae001f5 Wen Congyang
    for (i = 0; i < 512; i++) {
228 fae001f5 Wen Congyang
        pml4e_addr = (pml4e_start_addr + i * 8) & a20_mask;
229 fae001f5 Wen Congyang
        pml4e = ldq_phys(pml4e_addr);
230 fae001f5 Wen Congyang
        if (!(pml4e & PG_PRESENT_MASK)) {
231 fae001f5 Wen Congyang
            /* not present */
232 fae001f5 Wen Congyang
            continue;
233 fae001f5 Wen Congyang
        }
234 fae001f5 Wen Congyang
235 fae001f5 Wen Congyang
        line_addr = ((i & 0x1ffULL) << 39) | (0xffffULL << 48);
236 fbc2ed95 Luiz Capitulino
        pdpe_start_addr = (pml4e & PLM4_ADDR_MASK) & a20_mask;
237 fae001f5 Wen Congyang
        walk_pdpe(list, pdpe_start_addr, a20_mask, line_addr);
238 fae001f5 Wen Congyang
    }
239 fae001f5 Wen Congyang
}
240 fae001f5 Wen Congyang
#endif
241 fae001f5 Wen Congyang
242 a23bbfda Andreas Färber
void x86_cpu_get_memory_mapping(CPUState *cs, MemoryMappingList *list,
243 a23bbfda Andreas Färber
                                Error **errp)
244 fae001f5 Wen Congyang
{
245 a23bbfda Andreas Färber
    X86CPU *cpu = X86_CPU(cs);
246 a23bbfda Andreas Färber
    CPUX86State *env = &cpu->env;
247 a23bbfda Andreas Färber
248 a23bbfda Andreas Färber
    if (!cpu_paging_enabled(cs)) {
249 fae001f5 Wen Congyang
        /* paging is disabled */
250 a23bbfda Andreas Färber
        return;
251 fae001f5 Wen Congyang
    }
252 fae001f5 Wen Congyang
253 fae001f5 Wen Congyang
    if (env->cr[4] & CR4_PAE_MASK) {
254 fae001f5 Wen Congyang
#ifdef TARGET_X86_64
255 fae001f5 Wen Congyang
        if (env->hflags & HF_LMA_MASK) {
256 a8170e5e Avi Kivity
            hwaddr pml4e_addr;
257 fae001f5 Wen Congyang
258 fbc2ed95 Luiz Capitulino
            pml4e_addr = (env->cr[3] & PLM4_ADDR_MASK) & env->a20_mask;
259 fae001f5 Wen Congyang
            walk_pml4e(list, pml4e_addr, env->a20_mask);
260 fae001f5 Wen Congyang
        } else
261 fae001f5 Wen Congyang
#endif
262 fae001f5 Wen Congyang
        {
263 a8170e5e Avi Kivity
            hwaddr pdpe_addr;
264 fae001f5 Wen Congyang
265 fae001f5 Wen Congyang
            pdpe_addr = (env->cr[3] & ~0x1f) & env->a20_mask;
266 fae001f5 Wen Congyang
            walk_pdpe2(list, pdpe_addr, env->a20_mask);
267 fae001f5 Wen Congyang
        }
268 fae001f5 Wen Congyang
    } else {
269 a8170e5e Avi Kivity
        hwaddr pde_addr;
270 fae001f5 Wen Congyang
        bool pse;
271 fae001f5 Wen Congyang
272 fae001f5 Wen Congyang
        pde_addr = (env->cr[3] & ~0xfff) & env->a20_mask;
273 fae001f5 Wen Congyang
        pse = !!(env->cr[4] & CR4_PSE_MASK);
274 fae001f5 Wen Congyang
        walk_pde2(list, pde_addr, env->a20_mask, pse);
275 fae001f5 Wen Congyang
    }
276 fae001f5 Wen Congyang
}