@@ -19,6 +19,7 @@
************** code hook implementations for x86 ***********
*/
+/* PAE Paging or IA-32e Paging */
#define PML4_ADDR_MASK 0xffffffffff000ULL /* selects bits 51:12 */
/**
@@ -365,301 +366,66 @@ x86_pte_child(CPUState *cs, PTE_t *pte, int height)
return -1;
}
-/* PAE Paging or IA-32e Paging */
-static void walk_pte(MemoryMappingList *list, AddressSpace *as,
- hwaddr pte_start_addr,
- int32_t a20_mask, target_ulong start_line_addr)
-{
- hwaddr pte_addr, start_paddr;
- uint64_t pte;
- target_ulong start_vaddr;
- int i;
-
- for (i = 0; i < 512; i++) {
- pte_addr = (pte_start_addr + i * 8) & a20_mask;
- pte = address_space_ldq(as, pte_addr, MEMTXATTRS_UNSPECIFIED, NULL);
- if (!(pte & PG_PRESENT_MASK)) {
- /* not present */
- continue;
- }
-
- start_paddr = (pte & ~0xfff) & ~(0x1ULL << 63);
- if (cpu_physical_memory_is_io(start_paddr)) {
- /* I/O region */
- continue;
- }
-
- start_vaddr = start_line_addr | ((i & 0x1ff) << 12);
- memory_mapping_list_add_merge_sorted(list, start_paddr,
- start_vaddr, 1 << 12);
- }
-}
-
-/* 32-bit Paging */
-static void walk_pte2(MemoryMappingList *list, AddressSpace *as,
- hwaddr pte_start_addr, int32_t a20_mask,
- target_ulong start_line_addr)
-{
- hwaddr pte_addr, start_paddr;
- uint32_t pte;
- target_ulong start_vaddr;
- int i;
-
- for (i = 0; i < 1024; i++) {
- pte_addr = (pte_start_addr + i * 4) & a20_mask;
- pte = address_space_ldl(as, pte_addr, MEMTXATTRS_UNSPECIFIED, NULL);
- if (!(pte & PG_PRESENT_MASK)) {
- /* not present */
- continue;
- }
-
- start_paddr = pte & ~0xfff;
- if (cpu_physical_memory_is_io(start_paddr)) {
- /* I/O region */
- continue;
- }
-
- start_vaddr = start_line_addr | ((i & 0x3ff) << 12);
- memory_mapping_list_add_merge_sorted(list, start_paddr,
- start_vaddr, 1 << 12);
- }
-}
-
-/* PAE Paging or IA-32e Paging */
-#define PLM4_ADDR_MASK 0xffffffffff000ULL /* selects bits 51:12 */
+/**
+ * Back to x86 hooks
+ */
+struct memory_mapping_data {
+ MemoryMappingList *list;
+};
-static void walk_pde(MemoryMappingList *list, AddressSpace *as,
- hwaddr pde_start_addr,
- int32_t a20_mask, target_ulong start_line_addr)
+static int add_memory_mapping_to_list(CPUState *cs, void *data, PTE_t *pte,
+ vaddr vaddr_in, int height,
+ int offset)
{
- hwaddr pde_addr, pte_start_addr, start_paddr;
- uint64_t pde;
- target_ulong line_addr, start_vaddr;
- int i;
-
- for (i = 0; i < 512; i++) {
- pde_addr = (pde_start_addr + i * 8) & a20_mask;
- pde = address_space_ldq(as, pde_addr, MEMTXATTRS_UNSPECIFIED, NULL);
- if (!(pde & PG_PRESENT_MASK)) {
- /* not present */
- continue;
- }
-
- line_addr = start_line_addr | ((i & 0x1ff) << 21);
- if (pde & PG_PSE_MASK) {
- /* 2 MB page */
- start_paddr = (pde & ~0x1fffff) & ~(0x1ULL << 63);
- if (cpu_physical_memory_is_io(start_paddr)) {
- /* I/O region */
- continue;
- }
- start_vaddr = line_addr;
- memory_mapping_list_add_merge_sorted(list, start_paddr,
- start_vaddr, 1 << 21);
- continue;
- }
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
- pte_start_addr = (pde & PLM4_ADDR_MASK) & a20_mask;
- walk_pte(list, as, pte_start_addr, a20_mask, line_addr);
- }
-}
+ struct memory_mapping_data *mm_data = (struct memory_mapping_data *) data;
-/* 32-bit Paging */
-static void walk_pde2(MemoryMappingList *list, AddressSpace *as,
- hwaddr pde_start_addr, int32_t a20_mask,
- bool pse)
-{
- hwaddr pde_addr, pte_start_addr, start_paddr, high_paddr;
- uint32_t pde;
- target_ulong line_addr, start_vaddr;
- int i;
-
- for (i = 0; i < 1024; i++) {
- pde_addr = (pde_start_addr + i * 4) & a20_mask;
- pde = address_space_ldl(as, pde_addr, MEMTXATTRS_UNSPECIFIED, NULL);
- if (!(pde & PG_PRESENT_MASK)) {
- /* not present */
- continue;
+ hwaddr start_paddr = 0;
+ size_t pg_size = x86_pte_leaf_page_size(cs, height);
+ switch (height) {
+ case 1:
+ start_paddr = pte->pte64_t & ~0xfff;
+ if (env->cr[4] & CR4_PAE_MASK) {
+ start_paddr &= ~(0x1ULL << 63);
}
-
- line_addr = (((unsigned int)i & 0x3ff) << 22);
- if ((pde & PG_PSE_MASK) && pse) {
+ break;
+ case 2:
+ if (env->cr[4] & CR4_PAE_MASK) {
+ start_paddr = (pte->pte64_t & ~0x1fffff) & ~(0x1ULL << 63);
+ } else {
+ assert(!!(env->cr[4] & CR4_PSE_MASK));
/*
* 4 MB page:
* bits 39:32 are bits 20:13 of the PDE
* bit3 31:22 are bits 31:22 of the PDE
*/
- high_paddr = ((hwaddr)(pde & 0x1fe000) << 19);
- start_paddr = (pde & ~0x3fffff) | high_paddr;
- if (cpu_physical_memory_is_io(start_paddr)) {
- /* I/O region */
- continue;
- }
- start_vaddr = line_addr;
- memory_mapping_list_add_merge_sorted(list, start_paddr,
- start_vaddr, 1 << 22);
- continue;
- }
-
- pte_start_addr = (pde & ~0xfff) & a20_mask;
- walk_pte2(list, as, pte_start_addr, a20_mask, line_addr);
- }
-}
-
-/* PAE Paging */
-static void walk_pdpe2(MemoryMappingList *list, AddressSpace *as,
- hwaddr pdpe_start_addr, int32_t a20_mask)
-{
- hwaddr pdpe_addr, pde_start_addr;
- uint64_t pdpe;
- target_ulong line_addr;
- int i;
-
- for (i = 0; i < 4; i++) {
- pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
- pdpe = address_space_ldq(as, pdpe_addr, MEMTXATTRS_UNSPECIFIED, NULL);
- if (!(pdpe & PG_PRESENT_MASK)) {
- /* not present */
- continue;
- }
-
- line_addr = (((unsigned int)i & 0x3) << 30);
- pde_start_addr = (pdpe & ~0xfff) & a20_mask;
- walk_pde(list, as, pde_start_addr, a20_mask, line_addr);
- }
-}
-
-#ifdef TARGET_X86_64
-/* IA-32e Paging */
-static void walk_pdpe(MemoryMappingList *list, AddressSpace *as,
- hwaddr pdpe_start_addr, int32_t a20_mask,
- target_ulong start_line_addr)
-{
- hwaddr pdpe_addr, pde_start_addr, start_paddr;
- uint64_t pdpe;
- target_ulong line_addr, start_vaddr;
- int i;
-
- for (i = 0; i < 512; i++) {
- pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
- pdpe = address_space_ldq(as, pdpe_addr, MEMTXATTRS_UNSPECIFIED, NULL);
- if (!(pdpe & PG_PRESENT_MASK)) {
- /* not present */
- continue;
- }
-
- line_addr = start_line_addr | ((i & 0x1ffULL) << 30);
- if (pdpe & PG_PSE_MASK) {
- /* 1 GB page */
- start_paddr = (pdpe & ~0x3fffffff) & ~(0x1ULL << 63);
- if (cpu_physical_memory_is_io(start_paddr)) {
- /* I/O region */
- continue;
- }
- start_vaddr = line_addr;
- memory_mapping_list_add_merge_sorted(list, start_paddr,
- start_vaddr, 1 << 30);
- continue;
+ hwaddr high_paddr = ((hwaddr)(pte->pte64_t & 0x1fe000) << 19);
+ start_paddr = (pte->pte64_t & ~0x3fffff) | high_paddr;
}
-
- pde_start_addr = (pdpe & PLM4_ADDR_MASK) & a20_mask;
- walk_pde(list, as, pde_start_addr, a20_mask, line_addr);
+ break;
+ case 3:
+ /* Select bits 30--51 */
+ start_paddr = (pte->pte64_t & 0xfffffc0000000);
+ break;
+ default:
+ g_assert_not_reached();
}
-}
-
-/* IA-32e Paging */
-static void walk_pml4e(MemoryMappingList *list, AddressSpace *as,
- hwaddr pml4e_start_addr, int32_t a20_mask,
- target_ulong start_line_addr)
-{
- hwaddr pml4e_addr, pdpe_start_addr;
- uint64_t pml4e;
- target_ulong line_addr;
- int i;
-
- for (i = 0; i < 512; i++) {
- pml4e_addr = (pml4e_start_addr + i * 8) & a20_mask;
- pml4e = address_space_ldq(as, pml4e_addr, MEMTXATTRS_UNSPECIFIED,
- NULL);
- if (!(pml4e & PG_PRESENT_MASK)) {
- /* not present */
- continue;
- }
- line_addr = start_line_addr | ((i & 0x1ffULL) << 39);
- pdpe_start_addr = (pml4e & PLM4_ADDR_MASK) & a20_mask;
- walk_pdpe(list, as, pdpe_start_addr, a20_mask, line_addr);
+ /* This hook skips mappings for the I/O region */
+ if (cpu_physical_memory_is_io(start_paddr)) {
+ /* I/O region */
+ return 0;
}
-}
-static void walk_pml5e(MemoryMappingList *list, AddressSpace *as,
- hwaddr pml5e_start_addr, int32_t a20_mask)
-{
- hwaddr pml5e_addr, pml4e_start_addr;
- uint64_t pml5e;
- target_ulong line_addr;
- int i;
-
- for (i = 0; i < 512; i++) {
- pml5e_addr = (pml5e_start_addr + i * 8) & a20_mask;
- pml5e = address_space_ldq(as, pml5e_addr, MEMTXATTRS_UNSPECIFIED,
- NULL);
- if (!(pml5e & PG_PRESENT_MASK)) {
- /* not present */
- continue;
- }
-
- line_addr = (0x7fULL << 57) | ((i & 0x1ffULL) << 48);
- pml4e_start_addr = (pml5e & PLM4_ADDR_MASK) & a20_mask;
- walk_pml4e(list, as, pml4e_start_addr, a20_mask, line_addr);
- }
+ memory_mapping_list_add_merge_sorted(mm_data->list, start_paddr,
+ vaddr_in, pg_size);
+ return 0;
}
-#endif
bool x86_cpu_get_memory_mapping(CPUState *cs, MemoryMappingList *list,
Error **errp)
{
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
- int32_t a20_mask;
-
- if (!cpu_paging_enabled(cs)) {
- /* paging is disabled */
- return true;
- }
-
- a20_mask = x86_get_a20_mask(env);
- if (env->cr[4] & CR4_PAE_MASK) {
-#ifdef TARGET_X86_64
- if (env->hflags & HF_LMA_MASK) {
- if (env->cr[4] & CR4_LA57_MASK) {
- hwaddr pml5e_addr;
-
- pml5e_addr = (env->cr[3] & PLM4_ADDR_MASK) & a20_mask;
- walk_pml5e(list, cs->as, pml5e_addr, a20_mask);
- } else {
- hwaddr pml4e_addr;
-
- pml4e_addr = (env->cr[3] & PLM4_ADDR_MASK) & a20_mask;
- walk_pml4e(list, cs->as, pml4e_addr, a20_mask,
- 0xffffULL << 48);
- }
- } else
-#endif
- {
- hwaddr pdpe_addr;
-
- pdpe_addr = (env->cr[3] & ~0x1f) & a20_mask;
- walk_pdpe2(list, cs->as, pdpe_addr, a20_mask);
- }
- } else {
- hwaddr pde_addr;
- bool pse;
-
- pde_addr = (env->cr[3] & ~0xfff) & a20_mask;
- pse = !!(env->cr[4] & CR4_PSE_MASK);
- walk_pde2(list, cs->as, pde_addr, a20_mask, pse);
- }
-
- return true;
+ return for_each_pte(cs, &add_memory_mapping_to_list, list, false, false);
}
Signed-off-by: Don Porter <porter@cs.unc.edu> --- target/i386/arch_memory_mapping.c | 320 ++++-------------------------- 1 file changed, 43 insertions(+), 277 deletions(-)