Commit f51589dad53ff431d827f1326b5313b81488e0dc
1 parent
82e41634
Support resolving addresses in PAE mode in cpu_get_phys_page_debug
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1240 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
73 additions
and
19 deletions
target-i386/helper2.c
| @@ -742,33 +742,87 @@ target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr) | @@ -742,33 +742,87 @@ target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr) | ||
| 742 | #else | 742 | #else |
| 743 | target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr) | 743 | target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr) |
| 744 | { | 744 | { |
| 745 | - uint8_t *pde_ptr, *pte_ptr; | 745 | + uint32_t pde_addr, pte_addr; |
| 746 | uint32_t pde, pte, paddr, page_offset, page_size; | 746 | uint32_t pde, pte, paddr, page_offset, page_size; |
| 747 | 747 | ||
| 748 | - if (!(env->cr[0] & CR0_PG_MASK)) { | ||
| 749 | - pte = addr; | ||
| 750 | - page_size = 4096; | ||
| 751 | - } else { | ||
| 752 | - /* page directory entry */ | ||
| 753 | - pde_ptr = phys_ram_base + | ||
| 754 | - (((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & env->a20_mask); | ||
| 755 | - pde = ldl_raw(pde_ptr); | ||
| 756 | - if (!(pde & PG_PRESENT_MASK)) | 748 | + if (env->cr[4] & CR4_PAE_MASK) { |
| 749 | + uint32_t pdpe_addr, pde_addr, pte_addr; | ||
| 750 | + uint32_t pdpe; | ||
| 751 | + | ||
| 752 | + /* XXX: we only use 32 bit physical addresses */ | ||
| 753 | +#ifdef TARGET_X86_64 | ||
| 754 | + if (env->hflags & HF_LMA_MASK) { | ||
| 755 | + uint32_t pml4e_addr, pml4e; | ||
| 756 | + int32_t sext; | ||
| 757 | + | ||
| 758 | + /* test virtual address sign extension */ | ||
| 759 | + sext = (int64_t)addr >> 47; | ||
| 760 | + if (sext != 0 && sext != -1) | ||
| 761 | + return -1; | ||
| 762 | + | ||
| 763 | + pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) & | ||
| 764 | + env->a20_mask; | ||
| 765 | + pml4e = ldl_phys_aligned(pml4e_addr); | ||
| 766 | + if (!(pml4e & PG_PRESENT_MASK)) | ||
| 767 | + return -1; | ||
| 768 | + | ||
| 769 | + pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) & | ||
| 770 | + env->a20_mask; | ||
| 771 | + pdpe = ldl_phys_aligned(pdpe_addr); | ||
| 772 | + if (!(pdpe & PG_PRESENT_MASK)) | ||
| 773 | + return -1; | ||
| 774 | + } else | ||
| 775 | +#endif | ||
| 776 | + { | ||
| 777 | + pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 30) << 3)) & | ||
| 778 | + env->a20_mask; | ||
| 779 | + pdpe = ldl_phys_aligned(pdpe_addr); | ||
| 780 | + if (!(pdpe & PG_PRESENT_MASK)) | ||
| 781 | + return -1; | ||
| 782 | + } | ||
| 783 | + | ||
| 784 | + pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) & | ||
| 785 | + env->a20_mask; | ||
| 786 | + pde = ldl_phys_aligned(pde_addr); | ||
| 787 | + if (!(pde & PG_PRESENT_MASK)) { | ||
| 757 | return -1; | 788 | return -1; |
| 758 | - if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) { | ||
| 759 | - pte = pde & ~0x003ff000; /* align to 4MB */ | ||
| 760 | - page_size = 4096 * 1024; | 789 | + } |
| 790 | + if (pde & PG_PSE_MASK) { | ||
| 791 | + /* 2 MB page */ | ||
| 792 | + page_size = 2048 * 1024; | ||
| 793 | + pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */ | ||
| 794 | + } else { | ||
| 795 | + /* 4 KB page */ | ||
| 796 | + pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) & | ||
| 797 | + env->a20_mask; | ||
| 798 | + page_size = 4096; | ||
| 799 | + pte = ldl_phys_aligned(pte_addr); | ||
| 800 | + } | ||
| 801 | + } else { | ||
| 802 | + if (!(env->cr[0] & CR0_PG_MASK)) { | ||
| 803 | + pte = addr; | ||
| 804 | + page_size = 4096; | ||
| 761 | } else { | 805 | } else { |
| 762 | /* page directory entry */ | 806 | /* page directory entry */ |
| 763 | - pte_ptr = phys_ram_base + | ||
| 764 | - (((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask); | ||
| 765 | - pte = ldl_raw(pte_ptr); | ||
| 766 | - if (!(pte & PG_PRESENT_MASK)) | 807 | + pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & env->a20_mask; |
| 808 | + pde = ldl_phys_aligned(pde_addr); | ||
| 809 | + if (!(pde & PG_PRESENT_MASK)) | ||
| 767 | return -1; | 810 | return -1; |
| 768 | - page_size = 4096; | 811 | + if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) { |
| 812 | + pte = pde & ~0x003ff000; /* align to 4MB */ | ||
| 813 | + page_size = 4096 * 1024; | ||
| 814 | + } else { | ||
| 815 | + /* page directory entry */ | ||
| 816 | + pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask; | ||
| 817 | + pte = ldl_phys_aligned(pte_addr); | ||
| 818 | + if (!(pte & PG_PRESENT_MASK)) | ||
| 819 | + return -1; | ||
| 820 | + page_size = 4096; | ||
| 821 | + } | ||
| 769 | } | 822 | } |
| 823 | + pte = pte & env->a20_mask; | ||
| 770 | } | 824 | } |
| 771 | - pte = pte & env->a20_mask; | 825 | + |
| 772 | page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1); | 826 | page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1); |
| 773 | paddr = (pte & TARGET_PAGE_MASK) + page_offset; | 827 | paddr = (pte & TARGET_PAGE_MASK) + page_offset; |
| 774 | return paddr; | 828 | return paddr; |