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 | 742 | #else |
| 743 | 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 | 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 | 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 | 805 | } else { |
| 762 | 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 | 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 | 826 | page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1); |
| 773 | 827 | paddr = (pte & TARGET_PAGE_MASK) + page_offset; |
| 774 | 828 | return paddr; | ... | ... |