Commit 0ba5f006bb143ea5ef5cac1746f52bbbf529c836

Authored by aurel32
1 parent 967032c3

x86/x86-64 MMU PAE fixes

This patch fixes MMU emulation in PAE mode for > 4GB physical addresses:
- a20_mask should have the correct size to not clear the high part of
  the addresses.
- PHYS_ADDR_MASK should not clear the high part of the addresses.
- pdpe, pde and pte could be located anywhere in memory on x86-64, but
  only in the first 4GB on x86, define their pointer to as target_ulong.
- pml4e_addr could be located anywhere in memory, define its pointer
  as uint64_t.
- paddr represents a physical address and thus should be of type
  target_phys_addr_t.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4239 c046a42c-6fe2-441c-8c8c-71466251a162
target-i386/cpu.h
@@ -499,7 +499,7 @@ typedef struct CPUX86State { @@ -499,7 +499,7 @@ typedef struct CPUX86State {
499 SegmentCache idt; /* only base and limit are used */ 499 SegmentCache idt; /* only base and limit are used */
500 500
501 target_ulong cr[9]; /* NOTE: cr1, cr5-7 are unused */ 501 target_ulong cr[9]; /* NOTE: cr1, cr5-7 are unused */
502 - uint32_t a20_mask; 502 + uint64_t a20_mask;
503 503
504 /* FPU state */ 504 /* FPU state */
505 unsigned int fpstt; /* top of stack index */ 505 unsigned int fpstt; /* top of stack index */
target-i386/helper2.c
@@ -377,7 +377,7 @@ void cpu_reset(CPUX86State *env) @@ -377,7 +377,7 @@ void cpu_reset(CPUX86State *env)
377 env->hflags |= HF_GIF_MASK; 377 env->hflags |= HF_GIF_MASK;
378 378
379 cpu_x86_update_cr0(env, 0x60000010); 379 cpu_x86_update_cr0(env, 0x60000010);
380 - env->a20_mask = 0xffffffff; 380 + env->a20_mask = ~0x0;
381 env->smbase = 0x30000; 381 env->smbase = 0x30000;
382 382
383 env->idt.limit = 0xffff; 383 env->idt.limit = 0xffff;
@@ -695,7 +695,7 @@ void cpu_x86_set_a20(CPUX86State *env, int a20_state) @@ -695,7 +695,7 @@ void cpu_x86_set_a20(CPUX86State *env, int a20_state)
695 /* when a20 is changed, all the MMU mappings are invalid, so 695 /* when a20 is changed, all the MMU mappings are invalid, so
696 we must flush everything */ 696 we must flush everything */
697 tlb_flush(env, 1); 697 tlb_flush(env, 1);
698 - env->a20_mask = 0xffefffff | (a20_state << 20); 698 + env->a20_mask = (~0x100000) | (a20_state << 20);
699 } 699 }
700 } 700 }
701 701
@@ -800,7 +800,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) @@ -800,7 +800,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
800 800
801 #else 801 #else
802 802
803 -#define PHYS_ADDR_MASK 0xfffff000 803 +#define PHYS_ADDR_MASK (~0xfff)
804 804
805 /* return value: 805 /* return value:
806 -1 = cannot handle fault 806 -1 = cannot handle fault
@@ -812,9 +812,10 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, @@ -812,9 +812,10 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
812 int is_write1, int mmu_idx, int is_softmmu) 812 int is_write1, int mmu_idx, int is_softmmu)
813 { 813 {
814 uint64_t ptep, pte; 814 uint64_t ptep, pte;
815 - uint32_t pdpe_addr, pde_addr, pte_addr; 815 + target_ulong pde_addr, pte_addr;
816 int error_code, is_dirty, prot, page_size, ret, is_write, is_user; 816 int error_code, is_dirty, prot, page_size, ret, is_write, is_user;
817 - unsigned long paddr, page_offset; 817 + target_phys_addr_t paddr;
  818 + uint32_t page_offset;
818 target_ulong vaddr, virt_addr; 819 target_ulong vaddr, virt_addr;
819 820
820 is_user = mmu_idx == MMU_USER_IDX; 821 is_user = mmu_idx == MMU_USER_IDX;
@@ -834,12 +835,11 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, @@ -834,12 +835,11 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
834 835
835 if (env->cr[4] & CR4_PAE_MASK) { 836 if (env->cr[4] & CR4_PAE_MASK) {
836 uint64_t pde, pdpe; 837 uint64_t pde, pdpe;
  838 + target_ulong pdpe_addr;
837 839
838 - /* XXX: we only use 32 bit physical addresses */  
839 #ifdef TARGET_X86_64 840 #ifdef TARGET_X86_64
840 if (env->hflags & HF_LMA_MASK) { 841 if (env->hflags & HF_LMA_MASK) {
841 - uint32_t pml4e_addr;  
842 - uint64_t pml4e; 842 + uint64_t pml4e_addr, pml4e;
843 int32_t sext; 843 int32_t sext;
844 844
845 /* test virtual address sign extension */ 845 /* test virtual address sign extension */
@@ -1101,17 +1101,19 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, @@ -1101,17 +1101,19 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
1101 1101
1102 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) 1102 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1103 { 1103 {
1104 - uint32_t pde_addr, pte_addr;  
1105 - uint32_t pde, pte, paddr, page_offset, page_size; 1104 + target_ulong pde_addr, pte_addr;
  1105 + uint64_t pte;
  1106 + target_phys_addr_t paddr;
  1107 + uint32_t page_offset;
  1108 + int page_size;
1106 1109
1107 if (env->cr[4] & CR4_PAE_MASK) { 1110 if (env->cr[4] & CR4_PAE_MASK) {
1108 - uint32_t pdpe_addr, pde_addr, pte_addr;  
1109 - uint32_t pdpe; 1111 + target_ulong pdpe_addr;
  1112 + uint64_t pde, pdpe;
1110 1113
1111 - /* XXX: we only use 32 bit physical addresses */  
1112 #ifdef TARGET_X86_64 1114 #ifdef TARGET_X86_64
1113 if (env->hflags & HF_LMA_MASK) { 1115 if (env->hflags & HF_LMA_MASK) {
1114 - uint32_t pml4e_addr, pml4e; 1116 + uint64_t pml4e_addr, pml4e;
1115 int32_t sext; 1117 int32_t sext;
1116 1118
1117 /* test virtual address sign extension */ 1119 /* test virtual address sign extension */
@@ -1121,13 +1123,13 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) @@ -1121,13 +1123,13 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1121 1123
1122 pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) & 1124 pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &
1123 env->a20_mask; 1125 env->a20_mask;
1124 - pml4e = ldl_phys(pml4e_addr); 1126 + pml4e = ldq_phys(pml4e_addr);
1125 if (!(pml4e & PG_PRESENT_MASK)) 1127 if (!(pml4e & PG_PRESENT_MASK))
1126 return -1; 1128 return -1;
1127 1129
1128 pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) & 1130 pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) &
1129 env->a20_mask; 1131 env->a20_mask;
1130 - pdpe = ldl_phys(pdpe_addr); 1132 + pdpe = ldq_phys(pdpe_addr);
1131 if (!(pdpe & PG_PRESENT_MASK)) 1133 if (!(pdpe & PG_PRESENT_MASK))
1132 return -1; 1134 return -1;
1133 } else 1135 } else
@@ -1135,14 +1137,14 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) @@ -1135,14 +1137,14 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1135 { 1137 {
1136 pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) & 1138 pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &
1137 env->a20_mask; 1139 env->a20_mask;
1138 - pdpe = ldl_phys(pdpe_addr); 1140 + pdpe = ldq_phys(pdpe_addr);
1139 if (!(pdpe & PG_PRESENT_MASK)) 1141 if (!(pdpe & PG_PRESENT_MASK))
1140 return -1; 1142 return -1;
1141 } 1143 }
1142 1144
1143 pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) & 1145 pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) &
1144 env->a20_mask; 1146 env->a20_mask;
1145 - pde = ldl_phys(pde_addr); 1147 + pde = ldq_phys(pde_addr);
1146 if (!(pde & PG_PRESENT_MASK)) { 1148 if (!(pde & PG_PRESENT_MASK)) {
1147 return -1; 1149 return -1;
1148 } 1150 }
@@ -1155,9 +1157,11 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) @@ -1155,9 +1157,11 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1155 pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) & 1157 pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) &
1156 env->a20_mask; 1158 env->a20_mask;
1157 page_size = 4096; 1159 page_size = 4096;
1158 - pte = ldl_phys(pte_addr); 1160 + pte = ldq_phys(pte_addr);
1159 } 1161 }
1160 } else { 1162 } else {
  1163 + uint32_t pde;
  1164 +
1161 if (!(env->cr[0] & CR0_PG_MASK)) { 1165 if (!(env->cr[0] & CR0_PG_MASK)) {
1162 pte = addr; 1166 pte = addr;
1163 page_size = 4096; 1167 page_size = 4096;