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; | ... | ... |