Revision f51589da

b/target-i386/helper2.c
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;

Also available in: Unified diff