int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,

                             int is_write1, int mmu_idx)

{

    uint64_t ptep, pte;

    target_ulong pde_addr, pte_addr;

    int error_code, is_dirty, prot, page_size, is_write, is_user;

    target_phys_addr_t paddr;

    uint32_t page_offset;

    target_ulong vaddr, virt_addr;



    is_user = mmu_idx == MMU_USER_IDX;

#if defined(DEBUG_MMU)

    printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",

           addr, is_write1, is_user, env->eip);

#endif

    is_write = is_write1 & 1;



    if (!(env->cr[0] & CR0_PG_MASK)) {

        pte = addr;

        virt_addr = addr & TARGET_PAGE_MASK;

        prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;

        page_size = 4096;

        goto do_mapping;

    }



    if (env->cr[4] & CR4_PAE_MASK) {

        uint64_t pde, pdpe;

        target_ulong pdpe_addr;



#ifdef TARGET_X86_64

        if (env->hflags & HF_LMA_MASK) {

            uint64_t pml4e_addr, pml4e;

            int32_t sext;



            /* test virtual address sign extension */

            sext = (int64_t)addr >> 47;

            if (sext != 0 && sext != -1) {

                env->error_code = 0;

                env->exception_index = EXCP0D_GPF;

                return 1;

            }



            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &

                env->a20_mask;

            pml4e = ldq_phys(pml4e_addr);

            if (!(pml4e & PG_PRESENT_MASK)) {

                error_code = 0;

                goto do_fault;

            }

            if (!(env->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) {

                error_code = PG_ERROR_RSVD_MASK;

                goto do_fault;

            }

            if (!(pml4e & PG_ACCESSED_MASK)) {

                pml4e |= PG_ACCESSED_MASK;

                stl_phys_notdirty(pml4e_addr, pml4e);

            }

            ptep = pml4e ^ PG_NX_MASK;

            pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((addr >> 30) & 0x1ff) << 3)) &

                env->a20_mask;

            pdpe = ldq_phys(pdpe_addr);

            if (!(pdpe & PG_PRESENT_MASK)) {

                error_code = 0;

                goto do_fault;

            }

            if (!(env->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) {

                error_code = PG_ERROR_RSVD_MASK;

                goto do_fault;

            }

            ptep &= pdpe ^ PG_NX_MASK;

            if (!(pdpe & PG_ACCESSED_MASK)) {

                pdpe |= PG_ACCESSED_MASK;

                stl_phys_notdirty(pdpe_addr, pdpe);

            }

        } else

#endif

        {

            /* XXX: load them when cr3 is loaded ? */

            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &

                env->a20_mask;

            pdpe = ldq_phys(pdpe_addr);

            if (!(pdpe & PG_PRESENT_MASK)) {

                error_code = 0;

                goto do_fault;

            }

            ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;

        }



        pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((addr >> 21) & 0x1ff) << 3)) &

            env->a20_mask;

        pde = ldq_phys(pde_addr);

        if (!(pde & PG_PRESENT_MASK)) {

            error_code = 0;

            goto do_fault;

        }

        if (!(env->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) {

            error_code = PG_ERROR_RSVD_MASK;

            goto do_fault;

        }

        ptep &= pde ^ PG_NX_MASK;

        if (pde & PG_PSE_MASK) {

            /* 2 MB page */

            page_size = 2048 * 1024;

            ptep ^= PG_NX_MASK;

            if ((ptep & PG_NX_MASK) && is_write1 == 2)

                goto do_fault_protect;

            if (is_user) {

                if (!(ptep & PG_USER_MASK))

                    goto do_fault_protect;

                if (is_write && !(ptep & PG_RW_MASK))

                    goto do_fault_protect;

            } else {

                if ((env->cr[0] & CR0_WP_MASK) &&

                    is_write && !(ptep & PG_RW_MASK))

                    goto do_fault_protect;

            }

            is_dirty = is_write && !(pde & PG_DIRTY_MASK);

            if (!(pde & PG_ACCESSED_MASK) || is_dirty) {

                pde |= PG_ACCESSED_MASK;

                if (is_dirty)

                    pde |= PG_DIRTY_MASK;

                stl_phys_notdirty(pde_addr, pde);

            }

            /* align to page_size */

            pte = pde & ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff);

            virt_addr = addr & ~(page_size - 1);

        } else {

            /* 4 KB page */

            if (!(pde & PG_ACCESSED_MASK)) {

                pde |= PG_ACCESSED_MASK;

                stl_phys_notdirty(pde_addr, pde);

            }

            pte_addr = ((pde & PHYS_ADDR_MASK) + (((addr >> 12) & 0x1ff) << 3)) &

                env->a20_mask;

            pte = ldq_phys(pte_addr);

            if (!(pte & PG_PRESENT_MASK)) {

                error_code = 0;

                goto do_fault;

            }

            if (!(env->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) {

                error_code = PG_ERROR_RSVD_MASK;

                goto do_fault;

            }

            /* combine pde and pte nx, user and rw protections */

            ptep &= pte ^ PG_NX_MASK;

            ptep ^= PG_NX_MASK;

            if ((ptep & PG_NX_MASK) && is_write1 == 2)

                goto do_fault_protect;

            if (is_user) {

                if (!(ptep & PG_USER_MASK))

                    goto do_fault_protect;

                if (is_write && !(ptep & PG_RW_MASK))

                    goto do_fault_protect;

            } else {

                if ((env->cr[0] & CR0_WP_MASK) &&

                    is_write && !(ptep & PG_RW_MASK))

                    goto do_fault_protect;

            }

            is_dirty = is_write && !(pte & PG_DIRTY_MASK);

            if (!(pte & PG_ACCESSED_MASK) || is_dirty) {

                pte |= PG_ACCESSED_MASK;

                if (is_dirty)

                    pte |= PG_DIRTY_MASK;

                stl_phys_notdirty(pte_addr, pte);

            }

            page_size = 4096;

            virt_addr = addr & ~0xfff;

            pte = pte & (PHYS_ADDR_MASK | 0xfff);

        }

    } else {

        uint32_t pde;



        /* page directory entry */

        pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &

            env->a20_mask;

        pde = ldl_phys(pde_addr);

        if (!(pde & PG_PRESENT_MASK)) {

            error_code = 0;

            goto do_fault;

        }

        /* if PSE bit is set, then we use a 4MB page */

        if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {

            page_size = 4096 * 1024;

            if (is_user) {

                if (!(pde & PG_USER_MASK))

                    goto do_fault_protect;

                if (is_write && !(pde & PG_RW_MASK))

                    goto do_fault_protect;

            } else {

                if ((env->cr[0] & CR0_WP_MASK) &&

                    is_write && !(pde & PG_RW_MASK))

                    goto do_fault_protect;

            }

            is_dirty = is_write && !(pde & PG_DIRTY_MASK);

            if (!(pde & PG_ACCESSED_MASK) || is_dirty) {

                pde |= PG_ACCESSED_MASK;

                if (is_dirty)

                    pde |= PG_DIRTY_MASK;

                stl_phys_notdirty(pde_addr, pde);

            }



            pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */

            ptep = pte;

            virt_addr = addr & ~(page_size - 1);

        } else {

            if (!(pde & PG_ACCESSED_MASK)) {

                pde |= PG_ACCESSED_MASK;

                stl_phys_notdirty(pde_addr, pde);

            }



            /* page directory entry */

            pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &

                env->a20_mask;

            pte = ldl_phys(pte_addr);

            if (!(pte & PG_PRESENT_MASK)) {

                error_code = 0;

                goto do_fault;

            }

            /* combine pde and pte user and rw protections */

            ptep = pte & pde;

            if (is_user) {

                if (!(ptep & PG_USER_MASK))

                    goto do_fault_protect;

                if (is_write && !(ptep & PG_RW_MASK))

                    goto do_fault_protect;

            } else {

                if ((env->cr[0] & CR0_WP_MASK) &&

                    is_write && !(ptep & PG_RW_MASK))

                    goto do_fault_protect;

            }

            is_dirty = is_write && !(pte & PG_DIRTY_MASK);

            if (!(pte & PG_ACCESSED_MASK) || is_dirty) {

                pte |= PG_ACCESSED_MASK;

                if (is_dirty)

                    pte |= PG_DIRTY_MASK;

                stl_phys_notdirty(pte_addr, pte);

            }

            page_size = 4096;

            virt_addr = addr & ~0xfff;

        }

    }

    /* the page can be put in the TLB */

    prot = PAGE_READ;

    if (!(ptep & PG_NX_MASK))

        prot |= PAGE_EXEC;

    if (pte & PG_DIRTY_MASK) {

        /* only set write access if already dirty... otherwise wait

           for dirty access */

        if (is_user) {

            if (ptep & PG_RW_MASK)

                prot |= PAGE_WRITE;

        } else {

            if (!(env->cr[0] & CR0_WP_MASK) ||

                (ptep & PG_RW_MASK))

                prot |= PAGE_WRITE;

        }

    }

 do_mapping:

    pte = pte & env->a20_mask;



    /* Even if 4MB pages, we map only one 4KB page in the cache to

       avoid filling it too fast */

    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);

    paddr = (pte & TARGET_PAGE_MASK) + page_offset;

    vaddr = virt_addr + page_offset;



    tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);

    return 0;

 do_fault_protect:

    error_code = PG_ERROR_P_MASK;

 do_fault:

    error_code |= (is_write << PG_ERROR_W_BIT);

    if (is_user)

        error_code |= PG_ERROR_U_MASK;

    if (is_write1 == 2 &&

        (env->efer & MSR_EFER_NXE) &&

        (env->cr[4] & CR4_PAE_MASK))

        error_code |= PG_ERROR_I_D_MASK;

    if (env->intercept_exceptions & (1 << EXCP0E_PAGE)) {

        /* cr2 is not modified in case of exceptions */

        stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 

                 addr);

    } else {

        env->cr[2] = addr;

    }

    env->error_code = error_code;

    env->exception_index = EXCP0E_PAGE;

    return 1;

}

int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,

                             int is_write1, int mmu_idx)

{

    uint64_t ptep, pte;

    target_ulong pde_addr, pte_addr;

    int error_code, is_dirty, prot, page_size, is_write, is_user;

    target_phys_addr_t paddr;

    uint32_t page_offset;

    target_ulong vaddr, virt_addr;



    is_user = mmu_idx == MMU_USER_IDX;

#if defined(DEBUG_MMU)

    printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",

           addr, is_write1, is_user, env->eip);

#endif

    is_write = is_write1 & 1;



    if (!(env->cr[0] & CR0_PG_MASK)) {

        pte = addr;

        virt_addr = addr & TARGET_PAGE_MASK;

        prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;

        page_size = 4096;

        goto do_mapping;

    }



    if (env->cr[4] & CR4_PAE_MASK) {

        uint64_t pde, pdpe;

        target_ulong pdpe_addr;



#ifdef TARGET_X86_64

        if (env->hflags & HF_LMA_MASK) {

            uint64_t pml4e_addr, pml4e;

            int32_t sext;



            

            sext = (int64_t)addr >> 47;

            if (sext != 0 && sext != -1) {

                env->error_code = 0;

                env->exception_index = EXCP0D_GPF;

                return 1;

            }



            pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) &

                env->a20_mask;

            pml4e = ldq_phys(pml4e_addr);

            if (!(pml4e & PG_PRESENT_MASK)) {

                error_code = 0;

                goto do_fault;

            }

            if (!(env->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) {

                error_code = PG_ERROR_RSVD_MASK;

                goto do_fault;

            }

            if (!(pml4e & PG_ACCESSED_MASK)) {

                pml4e |= PG_ACCESSED_MASK;

                stl_phys_notdirty(pml4e_addr, pml4e);

            }

            ptep = pml4e ^ PG_NX_MASK;

            pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((addr >> 30) & 0x1ff) << 3)) &

                env->a20_mask;

            pdpe = ldq_phys(pdpe_addr);

            if (!(pdpe & PG_PRESENT_MASK)) {

                error_code = 0;

                goto do_fault;

            }

            if (!(env->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) {

                error_code = PG_ERROR_RSVD_MASK;

                goto do_fault;

            }

            ptep &= pdpe ^ PG_NX_MASK;

            if (!(pdpe & PG_ACCESSED_MASK)) {

                pdpe |= PG_ACCESSED_MASK;

                stl_phys_notdirty(pdpe_addr, pdpe);

            }

        } else

#endif

        {

            

            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) &

                env->a20_mask;

            pdpe = ldq_phys(pdpe_addr);

            if (!(pdpe & PG_PRESENT_MASK)) {

                error_code = 0;

                goto do_fault;

            }

            ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;

        }



        pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((addr >> 21) & 0x1ff) << 3)) &

            env->a20_mask;

        pde = ldq_phys(pde_addr);

        if (!(pde & PG_PRESENT_MASK)) {

            error_code = 0;

            goto do_fault;

        }

        if (!(env->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) {

            error_code = PG_ERROR_RSVD_MASK;

            goto do_fault;

        }

        ptep &= pde ^ PG_NX_MASK;

        if (pde & PG_PSE_MASK) {

            

            page_size = 2048 * 1024;

            ptep ^= PG_NX_MASK;

            if ((ptep & PG_NX_MASK) && is_write1 == 2)

                goto do_fault_protect;

            if (is_user) {

                if (!(ptep & PG_USER_MASK))

                    goto do_fault_protect;

                if (is_write && !(ptep & PG_RW_MASK))

                    goto do_fault_protect;

            } else {

                if ((env->cr[0] & CR0_WP_MASK) &&

                    is_write && !(ptep & PG_RW_MASK))

                    goto do_fault_protect;

            }

            is_dirty = is_write && !(pde & PG_DIRTY_MASK);

            if (!(pde & PG_ACCESSED_MASK) || is_dirty) {

                pde |= PG_ACCESSED_MASK;

                if (is_dirty)

                    pde |= PG_DIRTY_MASK;

                stl_phys_notdirty(pde_addr, pde);

            }

            

            pte = pde & ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff);

            virt_addr = addr & ~(page_size - 1);

        } else {

            

            if (!(pde & PG_ACCESSED_MASK)) {

                pde |= PG_ACCESSED_MASK;

                stl_phys_notdirty(pde_addr, pde);

            }

            pte_addr = ((pde & PHYS_ADDR_MASK) + (((addr >> 12) & 0x1ff) << 3)) &

                env->a20_mask;

            pte = ldq_phys(pte_addr);

            if (!(pte & PG_PRESENT_MASK)) {

                error_code = 0;

                goto do_fault;

            }

            if (!(env->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) {

                error_code = PG_ERROR_RSVD_MASK;

                goto do_fault;

            }

            

            ptep &= pte ^ PG_NX_MASK;

            ptep ^= PG_NX_MASK;

            if ((ptep & PG_NX_MASK) && is_write1 == 2)

                goto do_fault_protect;

            if (is_user) {

                if (!(ptep & PG_USER_MASK))

                    goto do_fault_protect;

                if (is_write && !(ptep & PG_RW_MASK))

                    goto do_fault_protect;

            } else {

                if ((env->cr[0] & CR0_WP_MASK) &&

                    is_write && !(ptep & PG_RW_MASK))

                    goto do_fault_protect;

            }

            is_dirty = is_write && !(pte & PG_DIRTY_MASK);

            if (!(pte & PG_ACCESSED_MASK) || is_dirty) {

                pte |= PG_ACCESSED_MASK;

                if (is_dirty)

                    pte |= PG_DIRTY_MASK;

                stl_phys_notdirty(pte_addr, pte);

            }

            page_size = 4096;

            virt_addr = addr & ~0xfff;

            pte = pte & (PHYS_ADDR_MASK | 0xfff);

        }

    } else {

        uint32_t pde;



        

        pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) &

            env->a20_mask;

        pde = ldl_phys(pde_addr);

        if (!(pde & PG_PRESENT_MASK)) {

            error_code = 0;

            goto do_fault;

        }

        

        if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {

            page_size = 4096 * 1024;

            if (is_user) {

                if (!(pde & PG_USER_MASK))

                    goto do_fault_protect;

                if (is_write && !(pde & PG_RW_MASK))

                    goto do_fault_protect;

            } else {

                if ((env->cr[0] & CR0_WP_MASK) &&

                    is_write && !(pde & PG_RW_MASK))

                    goto do_fault_protect;

            }

            is_dirty = is_write && !(pde & PG_DIRTY_MASK);

            if (!(pde & PG_ACCESSED_MASK) || is_dirty) {

                pde |= PG_ACCESSED_MASK;

                if (is_dirty)

                    pde |= PG_DIRTY_MASK;

                stl_phys_notdirty(pde_addr, pde);

            }



            pte = pde & ~( (page_size - 1) & ~0xfff); 

            ptep = pte;

            virt_addr = addr & ~(page_size - 1);

        } else {

            if (!(pde & PG_ACCESSED_MASK)) {

                pde |= PG_ACCESSED_MASK;

                stl_phys_notdirty(pde_addr, pde);

            }



            

            pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) &

                env->a20_mask;

            pte = ldl_phys(pte_addr);

            if (!(pte & PG_PRESENT_MASK)) {

                error_code = 0;

                goto do_fault;

            }

            

            ptep = pte & pde;

            if (is_user) {

                if (!(ptep & PG_USER_MASK))

                    goto do_fault_protect;

                if (is_write && !(ptep & PG_RW_MASK))

                    goto do_fault_protect;

            } else {

                if ((env->cr[0] & CR0_WP_MASK) &&

                    is_write && !(ptep & PG_RW_MASK))

                    goto do_fault_protect;

            }

            is_dirty = is_write && !(pte & PG_DIRTY_MASK);

            if (!(pte & PG_ACCESSED_MASK) || is_dirty) {

                pte |= PG_ACCESSED_MASK;

                if (is_dirty)

                    pte |= PG_DIRTY_MASK;

                stl_phys_notdirty(pte_addr, pte);

            }

            page_size = 4096;

            virt_addr = addr & ~0xfff;

        }

    }

    

    prot = PAGE_READ;

    if (!(ptep & PG_NX_MASK))

        prot |= PAGE_EXEC;

    if (pte & PG_DIRTY_MASK) {

        



        if (is_user) {

            if (ptep & PG_RW_MASK)

                prot |= PAGE_WRITE;

        } else {

            if (!(env->cr[0] & CR0_WP_MASK) ||

                (ptep & PG_RW_MASK))

                prot |= PAGE_WRITE;

        }

    }

 do_mapping:

    pte = pte & env->a20_mask;



    



    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);

    paddr = (pte & TARGET_PAGE_MASK) + page_offset;

    vaddr = virt_addr + page_offset;



    tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);

    return 0;

 do_fault_protect:

    error_code = PG_ERROR_P_MASK;

 do_fault:

    error_code |= (is_write << PG_ERROR_W_BIT);

    if (is_user)

        error_code |= PG_ERROR_U_MASK;

    if (is_write1 == 2 &&

        (env->efer & MSR_EFER_NXE) &&

        (env->cr[4] & CR4_PAE_MASK))

        error_code |= PG_ERROR_I_D_MASK;

    if (env->intercept_exceptions & (1 << EXCP0E_PAGE)) {

        

        stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 

                 addr);

    } else {

        env->cr[2] = addr;

    }

    env->error_code = error_code;

    env->exception_index = EXCP0E_PAGE;

    return 1;

}

int FUNC_0(CPUX86State *VAR_0, target_ulong VAR_1,

                             int VAR_2, int VAR_3)

{

    uint64_t ptep, pte;

    target_ulong pde_addr, pte_addr;

    int VAR_4, VAR_5, VAR_6, VAR_7, VAR_8, VAR_9;

    target_phys_addr_t paddr;

    uint32_t page_offset;

    target_ulong vaddr, virt_addr;



    VAR_9 = VAR_3 == MMU_USER_IDX;

#if defined(DEBUG_MMU)

    printf("MMU fault: VAR_1=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",

           VAR_1, VAR_2, VAR_9, VAR_0->eip);

#endif

    VAR_8 = VAR_2 & 1;



    if (!(VAR_0->cr[0] & CR0_PG_MASK)) {

        pte = VAR_1;

        virt_addr = VAR_1 & TARGET_PAGE_MASK;

        VAR_6 = PAGE_READ | PAGE_WRITE | PAGE_EXEC;

        VAR_7 = 4096;

        goto do_mapping;

    }



    if (VAR_0->cr[4] & CR4_PAE_MASK) {

        uint64_t pde, pdpe;

        target_ulong pdpe_addr;



#ifdef TARGET_X86_64

        if (VAR_0->hflags & HF_LMA_MASK) {

            uint64_t pml4e_addr, pml4e;

            int32_t sext;



            

            sext = (int64_t)VAR_1 >> 47;

            if (sext != 0 && sext != -1) {

                VAR_0->VAR_4 = 0;

                VAR_0->exception_index = EXCP0D_GPF;

                return 1;

            }



            pml4e_addr = ((VAR_0->cr[3] & ~0xfff) + (((VAR_1 >> 39) & 0x1ff) << 3)) &

                VAR_0->a20_mask;

            pml4e = ldq_phys(pml4e_addr);

            if (!(pml4e & PG_PRESENT_MASK)) {

                VAR_4 = 0;

                goto do_fault;

            }

            if (!(VAR_0->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) {

                VAR_4 = PG_ERROR_RSVD_MASK;

                goto do_fault;

            }

            if (!(pml4e & PG_ACCESSED_MASK)) {

                pml4e |= PG_ACCESSED_MASK;

                stl_phys_notdirty(pml4e_addr, pml4e);

            }

            ptep = pml4e ^ PG_NX_MASK;

            pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((VAR_1 >> 30) & 0x1ff) << 3)) &

                VAR_0->a20_mask;

            pdpe = ldq_phys(pdpe_addr);

            if (!(pdpe & PG_PRESENT_MASK)) {

                VAR_4 = 0;

                goto do_fault;

            }

            if (!(VAR_0->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) {

                VAR_4 = PG_ERROR_RSVD_MASK;

                goto do_fault;

            }

            ptep &= pdpe ^ PG_NX_MASK;

            if (!(pdpe & PG_ACCESSED_MASK)) {

                pdpe |= PG_ACCESSED_MASK;

                stl_phys_notdirty(pdpe_addr, pdpe);

            }

        } else

#endif

        {

            

            pdpe_addr = ((VAR_0->cr[3] & ~0x1f) + ((VAR_1 >> 27) & 0x18)) &

                VAR_0->a20_mask;

            pdpe = ldq_phys(pdpe_addr);

            if (!(pdpe & PG_PRESENT_MASK)) {

                VAR_4 = 0;

                goto do_fault;

            }

            ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK;

        }



        pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((VAR_1 >> 21) & 0x1ff) << 3)) &

            VAR_0->a20_mask;

        pde = ldq_phys(pde_addr);

        if (!(pde & PG_PRESENT_MASK)) {

            VAR_4 = 0;

            goto do_fault;

        }

        if (!(VAR_0->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) {

            VAR_4 = PG_ERROR_RSVD_MASK;

            goto do_fault;

        }

        ptep &= pde ^ PG_NX_MASK;

        if (pde & PG_PSE_MASK) {

            

            VAR_7 = 2048 * 1024;

            ptep ^= PG_NX_MASK;

            if ((ptep & PG_NX_MASK) && VAR_2 == 2)

                goto do_fault_protect;

            if (VAR_9) {

                if (!(ptep & PG_USER_MASK))

                    goto do_fault_protect;

                if (VAR_8 && !(ptep & PG_RW_MASK))

                    goto do_fault_protect;

            } else {

                if ((VAR_0->cr[0] & CR0_WP_MASK) &&

                    VAR_8 && !(ptep & PG_RW_MASK))

                    goto do_fault_protect;

            }

            VAR_5 = VAR_8 && !(pde & PG_DIRTY_MASK);

            if (!(pde & PG_ACCESSED_MASK) || VAR_5) {

                pde |= PG_ACCESSED_MASK;

                if (VAR_5)

                    pde |= PG_DIRTY_MASK;

                stl_phys_notdirty(pde_addr, pde);

            }

            

            pte = pde & ((PHYS_ADDR_MASK & ~(VAR_7 - 1)) | 0xfff);

            virt_addr = VAR_1 & ~(VAR_7 - 1);

        } else {

            

            if (!(pde & PG_ACCESSED_MASK)) {

                pde |= PG_ACCESSED_MASK;

                stl_phys_notdirty(pde_addr, pde);

            }

            pte_addr = ((pde & PHYS_ADDR_MASK) + (((VAR_1 >> 12) & 0x1ff) << 3)) &

                VAR_0->a20_mask;

            pte = ldq_phys(pte_addr);

            if (!(pte & PG_PRESENT_MASK)) {

                VAR_4 = 0;

                goto do_fault;

            }

            if (!(VAR_0->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) {

                VAR_4 = PG_ERROR_RSVD_MASK;

                goto do_fault;

            }

            

            ptep &= pte ^ PG_NX_MASK;

            ptep ^= PG_NX_MASK;

            if ((ptep & PG_NX_MASK) && VAR_2 == 2)

                goto do_fault_protect;

            if (VAR_9) {

                if (!(ptep & PG_USER_MASK))

                    goto do_fault_protect;

                if (VAR_8 && !(ptep & PG_RW_MASK))

                    goto do_fault_protect;

            } else {

                if ((VAR_0->cr[0] & CR0_WP_MASK) &&

                    VAR_8 && !(ptep & PG_RW_MASK))

                    goto do_fault_protect;

            }

            VAR_5 = VAR_8 && !(pte & PG_DIRTY_MASK);

            if (!(pte & PG_ACCESSED_MASK) || VAR_5) {

                pte |= PG_ACCESSED_MASK;

                if (VAR_5)

                    pte |= PG_DIRTY_MASK;

                stl_phys_notdirty(pte_addr, pte);

            }

            VAR_7 = 4096;

            virt_addr = VAR_1 & ~0xfff;

            pte = pte & (PHYS_ADDR_MASK | 0xfff);

        }

    } else {

        uint32_t pde;



        

        pde_addr = ((VAR_0->cr[3] & ~0xfff) + ((VAR_1 >> 20) & 0xffc)) &

            VAR_0->a20_mask;

        pde = ldl_phys(pde_addr);

        if (!(pde & PG_PRESENT_MASK)) {

            VAR_4 = 0;

            goto do_fault;

        }

        

        if ((pde & PG_PSE_MASK) && (VAR_0->cr[4] & CR4_PSE_MASK)) {

            VAR_7 = 4096 * 1024;

            if (VAR_9) {

                if (!(pde & PG_USER_MASK))

                    goto do_fault_protect;

                if (VAR_8 && !(pde & PG_RW_MASK))

                    goto do_fault_protect;

            } else {

                if ((VAR_0->cr[0] & CR0_WP_MASK) &&

                    VAR_8 && !(pde & PG_RW_MASK))

                    goto do_fault_protect;

            }

            VAR_5 = VAR_8 && !(pde & PG_DIRTY_MASK);

            if (!(pde & PG_ACCESSED_MASK) || VAR_5) {

                pde |= PG_ACCESSED_MASK;

                if (VAR_5)

                    pde |= PG_DIRTY_MASK;

                stl_phys_notdirty(pde_addr, pde);

            }



            pte = pde & ~( (VAR_7 - 1) & ~0xfff); 

            ptep = pte;

            virt_addr = VAR_1 & ~(VAR_7 - 1);

        } else {

            if (!(pde & PG_ACCESSED_MASK)) {

                pde |= PG_ACCESSED_MASK;

                stl_phys_notdirty(pde_addr, pde);

            }



            

            pte_addr = ((pde & ~0xfff) + ((VAR_1 >> 10) & 0xffc)) &

                VAR_0->a20_mask;

            pte = ldl_phys(pte_addr);

            if (!(pte & PG_PRESENT_MASK)) {

                VAR_4 = 0;

                goto do_fault;

            }

            

            ptep = pte & pde;

            if (VAR_9) {

                if (!(ptep & PG_USER_MASK))

                    goto do_fault_protect;

                if (VAR_8 && !(ptep & PG_RW_MASK))

                    goto do_fault_protect;

            } else {

                if ((VAR_0->cr[0] & CR0_WP_MASK) &&

                    VAR_8 && !(ptep & PG_RW_MASK))

                    goto do_fault_protect;

            }

            VAR_5 = VAR_8 && !(pte & PG_DIRTY_MASK);

            if (!(pte & PG_ACCESSED_MASK) || VAR_5) {

                pte |= PG_ACCESSED_MASK;

                if (VAR_5)

                    pte |= PG_DIRTY_MASK;

                stl_phys_notdirty(pte_addr, pte);

            }

            VAR_7 = 4096;

            virt_addr = VAR_1 & ~0xfff;

        }

    }

    

    VAR_6 = PAGE_READ;

    if (!(ptep & PG_NX_MASK))

        VAR_6 |= PAGE_EXEC;

    if (pte & PG_DIRTY_MASK) {

        



        if (VAR_9) {

            if (ptep & PG_RW_MASK)

                VAR_6 |= PAGE_WRITE;

        } else {

            if (!(VAR_0->cr[0] & CR0_WP_MASK) ||

                (ptep & PG_RW_MASK))

                VAR_6 |= PAGE_WRITE;

        }

    }

 do_mapping:

    pte = pte & VAR_0->a20_mask;



    



    page_offset = (VAR_1 & TARGET_PAGE_MASK) & (VAR_7 - 1);

    paddr = (pte & TARGET_PAGE_MASK) + page_offset;

    vaddr = virt_addr + page_offset;



    tlb_set_page(VAR_0, vaddr, paddr, VAR_6, VAR_3, VAR_7);

    return 0;

 do_fault_protect:

    VAR_4 = PG_ERROR_P_MASK;

 do_fault:

    VAR_4 |= (VAR_8 << PG_ERROR_W_BIT);

    if (VAR_9)

        VAR_4 |= PG_ERROR_U_MASK;

    if (VAR_2 == 2 &&

        (VAR_0->efer & MSR_EFER_NXE) &&

        (VAR_0->cr[4] & CR4_PAE_MASK))

        VAR_4 |= PG_ERROR_I_D_MASK;

    if (VAR_0->intercept_exceptions & (1 << EXCP0E_PAGE)) {

        

        stq_phys(VAR_0->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), 

                 VAR_1);

    } else {

        VAR_0->cr[2] = VAR_1;

    }

    VAR_0->VAR_4 = VAR_4;

    VAR_0->exception_index = EXCP0E_PAGE;

    return 1;

}

int FUNC_0(CPUX86State *VAR_0, target_ulong VAR_1,
int VAR_2, int VAR_3)
{ uint64_t ptep, pte; target_ulong pde_addr, pte_addr; int VAR_4, VAR_5, VAR_6, VAR_7, VAR_8, VAR_9; target_phys_addr_t paddr; uint32_t page_offset; target_ulong vaddr, virt_addr; VAR_9 = VAR_3 == MMU_USER_IDX; #if defined(DEBUG_MMU)
printf("MMU fault: VAR_1=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n",
VAR_1, VAR_2, VAR_9, VAR_0->eip); #endif
VAR_8 = VAR_2 & 1; if (!(VAR_0->cr[0] & CR0_PG_MASK)) { pte = VAR_1; virt_addr = VAR_1 & TARGET_PAGE_MASK; VAR_6 = PAGE_READ | PAGE_WRITE | PAGE_EXEC; VAR_7 = 4096; goto do_mapping; } if (VAR_0->cr[4] & CR4_PAE_MASK) { uint64_t pde, pdpe; target_ulong pdpe_addr; #ifdef TARGET_X86_64
if (VAR_0->hflags & HF_LMA_MASK) { uint64_t pml4e_addr, pml4e; int32_t sext; sext = (int64_t)VAR_1 >> 47; if (sext != 0 && sext != -1) { VAR_0->VAR_4 = 0; VAR_0->exception_index = EXCP0D_GPF; return 1; } pml4e_addr = ((VAR_0->cr[3] & ~0xfff) + (((VAR_1 >> 39) & 0x1ff) << 3)) &
VAR_0->a20_mask; pml4e = ldq_phys(pml4e_addr); if (!(pml4e & PG_PRESENT_MASK)) { VAR_4 = 0; goto do_fault; } if (!(VAR_0->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) { VAR_4 = PG_ERROR_RSVD_MASK; goto do_fault; } if (!(pml4e & PG_ACCESSED_MASK)) { pml4e |= PG_ACCESSED_MASK; stl_phys_notdirty(pml4e_addr, pml4e); } ptep = pml4e ^ PG_NX_MASK; pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((VAR_1 >> 30) & 0x1ff) << 3)) &
VAR_0->a20_mask; pdpe = ldq_phys(pdpe_addr); if (!(pdpe & PG_PRESENT_MASK)) { VAR_4 = 0; goto do_fault; } if (!(VAR_0->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) { VAR_4 = PG_ERROR_RSVD_MASK; goto do_fault; } ptep &= pdpe ^ PG_NX_MASK; if (!(pdpe & PG_ACCESSED_MASK)) { pdpe |= PG_ACCESSED_MASK; stl_phys_notdirty(pdpe_addr, pdpe); } } else #endif
{ pdpe_addr = ((VAR_0->cr[3] & ~0x1f) + ((VAR_1 >> 27) & 0x18)) &
VAR_0->a20_mask; pdpe = ldq_phys(pdpe_addr); if (!(pdpe & PG_PRESENT_MASK)) { VAR_4 = 0; goto do_fault; } ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK; } pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((VAR_1 >> 21) & 0x1ff) << 3)) &
VAR_0->a20_mask; pde = ldq_phys(pde_addr); if (!(pde & PG_PRESENT_MASK)) { VAR_4 = 0; goto do_fault; } if (!(VAR_0->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) { VAR_4 = PG_ERROR_RSVD_MASK; goto do_fault; } ptep &= pde ^ PG_NX_MASK; if (pde & PG_PSE_MASK) { VAR_7 = 2048 * 1024; ptep ^= PG_NX_MASK; if ((ptep & PG_NX_MASK) && VAR_2 == 2)
goto do_fault_protect; if (VAR_9) { if (!(ptep & PG_USER_MASK))
goto do_fault_protect; if (VAR_8 && !(ptep & PG_RW_MASK))
goto do_fault_protect; } else { if ((VAR_0->cr[0] & CR0_WP_MASK) &&
VAR_8 && !(ptep & PG_RW_MASK))
goto do_fault_protect; } VAR_5 = VAR_8 && !(pde & PG_DIRTY_MASK); if (!(pde & PG_ACCESSED_MASK) || VAR_5) { pde |= PG_ACCESSED_MASK; if (VAR_5)
pde |= PG_DIRTY_MASK; stl_phys_notdirty(pde_addr, pde); } pte = pde & ((PHYS_ADDR_MASK & ~(VAR_7 - 1)) | 0xfff); virt_addr = VAR_1 & ~(VAR_7 - 1); } else { if (!(pde & PG_ACCESSED_MASK)) { pde |= PG_ACCESSED_MASK; stl_phys_notdirty(pde_addr, pde); } pte_addr = ((pde & PHYS_ADDR_MASK) + (((VAR_1 >> 12) & 0x1ff) << 3)) &
VAR_0->a20_mask; pte = ldq_phys(pte_addr); if (!(pte & PG_PRESENT_MASK)) { VAR_4 = 0; goto do_fault; } if (!(VAR_0->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) { VAR_4 = PG_ERROR_RSVD_MASK; goto do_fault; } ptep &= pte ^ PG_NX_MASK; ptep ^= PG_NX_MASK; if ((ptep & PG_NX_MASK) && VAR_2 == 2)
goto do_fault_protect; if (VAR_9) { if (!(ptep & PG_USER_MASK))
goto do_fault_protect; if (VAR_8 && !(ptep & PG_RW_MASK))
goto do_fault_protect; } else { if ((VAR_0->cr[0] & CR0_WP_MASK) &&
VAR_8 && !(ptep & PG_RW_MASK))
goto do_fault_protect; } VAR_5 = VAR_8 && !(pte & PG_DIRTY_MASK); if (!(pte & PG_ACCESSED_MASK) || VAR_5) { pte |= PG_ACCESSED_MASK; if (VAR_5)
pte |= PG_DIRTY_MASK; stl_phys_notdirty(pte_addr, pte); } VAR_7 = 4096; virt_addr = VAR_1 & ~0xfff; pte = pte & (PHYS_ADDR_MASK | 0xfff); } } else { uint32_t pde; pde_addr = ((VAR_0->cr[3] & ~0xfff) + ((VAR_1 >> 20) & 0xffc)) &
VAR_0->a20_mask; pde = ldl_phys(pde_addr); if (!(pde & PG_PRESENT_MASK)) { VAR_4 = 0; goto do_fault; } if ((pde & PG_PSE_MASK) && (VAR_0->cr[4] & CR4_PSE_MASK)) { VAR_7 = 4096 * 1024; if (VAR_9) { if (!(pde & PG_USER_MASK))
goto do_fault_protect; if (VAR_8 && !(pde & PG_RW_MASK))
goto do_fault_protect; } else { if ((VAR_0->cr[0] & CR0_WP_MASK) &&
VAR_8 && !(pde & PG_RW_MASK))
goto do_fault_protect; } VAR_5 = VAR_8 && !(pde & PG_DIRTY_MASK); if (!(pde & PG_ACCESSED_MASK) || VAR_5) { pde |= PG_ACCESSED_MASK; if (VAR_5)
pde |= PG_DIRTY_MASK; stl_phys_notdirty(pde_addr, pde); } pte = pde & ~( (VAR_7 - 1) & ~0xfff); ptep = pte; virt_addr = VAR_1 & ~(VAR_7 - 1); } else { if (!(pde & PG_ACCESSED_MASK)) { pde |= PG_ACCESSED_MASK; stl_phys_notdirty(pde_addr, pde); } pte_addr = ((pde & ~0xfff) + ((VAR_1 >> 10) & 0xffc)) &
VAR_0->a20_mask; pte = ldl_phys(pte_addr); if (!(pte & PG_PRESENT_MASK)) { VAR_4 = 0; goto do_fault; } ptep = pte & pde; if (VAR_9) { if (!(ptep & PG_USER_MASK))
goto do_fault_protect; if (VAR_8 && !(ptep & PG_RW_MASK))
goto do_fault_protect; } else { if ((VAR_0->cr[0] & CR0_WP_MASK) &&
VAR_8 && !(ptep & PG_RW_MASK))
goto do_fault_protect; } VAR_5 = VAR_8 && !(pte & PG_DIRTY_MASK); if (!(pte & PG_ACCESSED_MASK) || VAR_5) { pte |= PG_ACCESSED_MASK; if (VAR_5)
pte |= PG_DIRTY_MASK; stl_phys_notdirty(pte_addr, pte); } VAR_7 = 4096; virt_addr = VAR_1 & ~0xfff; } } VAR_6 = PAGE_READ; if (!(ptep & PG_NX_MASK))
VAR_6 |= PAGE_EXEC; if (pte & PG_DIRTY_MASK) { if (VAR_9) { if (ptep & PG_RW_MASK)
VAR_6 |= PAGE_WRITE; } else { if (!(VAR_0->cr[0] & CR0_WP_MASK) ||
(ptep & PG_RW_MASK))
VAR_6 |= PAGE_WRITE; } } do_mapping:
pte = pte & VAR_0->a20_mask; page_offset = (VAR_1 & TARGET_PAGE_MASK) & (VAR_7 - 1); paddr = (pte & TARGET_PAGE_MASK) + page_offset; vaddr = virt_addr + page_offset; tlb_set_page(VAR_0, vaddr, paddr, VAR_6, VAR_3, VAR_7); return 0; do_fault_protect:
VAR_4 = PG_ERROR_P_MASK; do_fault:
VAR_4 |= (VAR_8 << PG_ERROR_W_BIT); if (VAR_9)
VAR_4 |= PG_ERROR_U_MASK; if (VAR_2 == 2 &&
(VAR_0->efer & MSR_EFER_NXE) &&
(VAR_0->cr[4] & CR4_PAE_MASK))
VAR_4 |= PG_ERROR_I_D_MASK; if (VAR_0->intercept_exceptions & (1 << EXCP0E_PAGE)) { stq_phys(VAR_0->vm_vmcb + offsetof(struct vmcb, control.exit_info_2),
VAR_1); } else { VAR_0->cr[2] = VAR_1; } VAR_0->VAR_4 = VAR_4; VAR_0->exception_index = EXCP0E_PAGE; return 1; }