127 |
/* currently not enabled for std i386 because not fully tested */ |
/* currently not enabled for std i386 because not fully tested */ |
128 |
env->cpuid_features |= CPUID_APIC; |
env->cpuid_features |= CPUID_APIC; |
129 |
env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF); |
env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF); |
130 |
env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL; |
env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX; |
131 |
env->cpuid_xlevel = 0x80000008; |
env->cpuid_xlevel = 0x80000008; |
132 |
|
|
133 |
/* these features are needed for Win64 and aren't fully implemented */ |
/* these features are needed for Win64 and aren't fully implemented */ |
576 |
|
|
577 |
#else |
#else |
578 |
|
|
579 |
|
#define PHYS_ADDR_MASK 0xfffff000 |
580 |
|
|
581 |
/* return value: |
/* return value: |
582 |
-1 = cannot handle fault |
-1 = cannot handle fault |
583 |
0 = nothing more to do |
0 = nothing more to do |
585 |
2 = soft MMU activation required for this block |
2 = soft MMU activation required for this block |
586 |
*/ |
*/ |
587 |
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, |
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, |
588 |
int is_write, int is_user, int is_softmmu) |
int is_write1, int is_user, int is_softmmu) |
589 |
{ |
{ |
590 |
|
uint64_t ptep, pte; |
591 |
uint32_t pdpe_addr, pde_addr, pte_addr; |
uint32_t pdpe_addr, pde_addr, pte_addr; |
592 |
uint32_t pde, pte, ptep, pdpe; |
int error_code, is_dirty, prot, page_size, ret, is_write; |
|
int error_code, is_dirty, prot, page_size, ret; |
|
593 |
unsigned long paddr, page_offset; |
unsigned long paddr, page_offset; |
594 |
target_ulong vaddr, virt_addr; |
target_ulong vaddr, virt_addr; |
595 |
|
|
596 |
#if defined(DEBUG_MMU) |
#if defined(DEBUG_MMU) |
597 |
printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n", |
printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n", |
598 |
addr, is_write, is_user, env->eip); |
addr, is_write1, is_user, env->eip); |
599 |
#endif |
#endif |
600 |
is_write &= 1; |
is_write = is_write1 & 1; |
601 |
|
|
602 |
if (!(env->cr[0] & CR0_PG_MASK)) { |
if (!(env->cr[0] & CR0_PG_MASK)) { |
603 |
pte = addr; |
pte = addr; |
604 |
virt_addr = addr & TARGET_PAGE_MASK; |
virt_addr = addr & TARGET_PAGE_MASK; |
605 |
prot = PAGE_READ | PAGE_WRITE; |
prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; |
606 |
page_size = 4096; |
page_size = 4096; |
607 |
goto do_mapping; |
goto do_mapping; |
608 |
} |
} |
609 |
|
|
610 |
if (env->cr[4] & CR4_PAE_MASK) { |
if (env->cr[4] & CR4_PAE_MASK) { |
611 |
|
uint64_t pde, pdpe; |
612 |
|
|
613 |
/* XXX: we only use 32 bit physical addresses */ |
/* XXX: we only use 32 bit physical addresses */ |
614 |
#ifdef TARGET_X86_64 |
#ifdef TARGET_X86_64 |
615 |
if (env->hflags & HF_LMA_MASK) { |
if (env->hflags & HF_LMA_MASK) { |
616 |
uint32_t pml4e_addr, pml4e; |
uint32_t pml4e_addr; |
617 |
|
uint64_t pml4e; |
618 |
int32_t sext; |
int32_t sext; |
619 |
|
|
|
/* XXX: handle user + rw rights */ |
|
|
/* XXX: handle NX flag */ |
|
620 |
/* test virtual address sign extension */ |
/* test virtual address sign extension */ |
621 |
sext = (int64_t)addr >> 47; |
sext = (int64_t)addr >> 47; |
622 |
if (sext != 0 && sext != -1) { |
if (sext != 0 && sext != -1) { |
626 |
|
|
627 |
pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) & |
pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) & |
628 |
env->a20_mask; |
env->a20_mask; |
629 |
pml4e = ldl_phys(pml4e_addr); |
pml4e = ldq_phys(pml4e_addr); |
630 |
if (!(pml4e & PG_PRESENT_MASK)) { |
if (!(pml4e & PG_PRESENT_MASK)) { |
631 |
error_code = 0; |
error_code = 0; |
632 |
goto do_fault; |
goto do_fault; |
633 |
} |
} |
634 |
|
if (!(env->efer & MSR_EFER_NXE) && (pml4e & PG_NX_MASK)) { |
635 |
|
error_code = PG_ERROR_RSVD_MASK; |
636 |
|
goto do_fault; |
637 |
|
} |
638 |
if (!(pml4e & PG_ACCESSED_MASK)) { |
if (!(pml4e & PG_ACCESSED_MASK)) { |
639 |
pml4e |= PG_ACCESSED_MASK; |
pml4e |= PG_ACCESSED_MASK; |
640 |
stl_phys_notdirty(pml4e_addr, pml4e); |
stl_phys_notdirty(pml4e_addr, pml4e); |
641 |
} |
} |
642 |
|
ptep = pml4e ^ PG_NX_MASK; |
643 |
pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) & |
pdpe_addr = ((pml4e & PHYS_ADDR_MASK) + (((addr >> 30) & 0x1ff) << 3)) & |
644 |
env->a20_mask; |
env->a20_mask; |
645 |
pdpe = ldl_phys(pdpe_addr); |
pdpe = ldq_phys(pdpe_addr); |
646 |
if (!(pdpe & PG_PRESENT_MASK)) { |
if (!(pdpe & PG_PRESENT_MASK)) { |
647 |
error_code = 0; |
error_code = 0; |
648 |
goto do_fault; |
goto do_fault; |
649 |
} |
} |
650 |
|
if (!(env->efer & MSR_EFER_NXE) && (pdpe & PG_NX_MASK)) { |
651 |
|
error_code = PG_ERROR_RSVD_MASK; |
652 |
|
goto do_fault; |
653 |
|
} |
654 |
|
ptep &= pdpe ^ PG_NX_MASK; |
655 |
if (!(pdpe & PG_ACCESSED_MASK)) { |
if (!(pdpe & PG_ACCESSED_MASK)) { |
656 |
pdpe |= PG_ACCESSED_MASK; |
pdpe |= PG_ACCESSED_MASK; |
657 |
stl_phys_notdirty(pdpe_addr, pdpe); |
stl_phys_notdirty(pdpe_addr, pdpe); |
658 |
} |
} |
659 |
} else |
} else |
660 |
#endif |
#endif |
661 |
{ |
{ |
662 |
|
/* XXX: load them when cr3 is loaded ? */ |
663 |
pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 30) << 3)) & |
pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 30) << 3)) & |
664 |
env->a20_mask; |
env->a20_mask; |
665 |
pdpe = ldl_phys(pdpe_addr); |
pdpe = ldq_phys(pdpe_addr); |
666 |
if (!(pdpe & PG_PRESENT_MASK)) { |
if (!(pdpe & PG_PRESENT_MASK)) { |
667 |
error_code = 0; |
error_code = 0; |
668 |
goto do_fault; |
goto do_fault; |
669 |
} |
} |
670 |
|
ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK; |
671 |
} |
} |
672 |
|
|
673 |
pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) & |
pde_addr = ((pdpe & PHYS_ADDR_MASK) + (((addr >> 21) & 0x1ff) << 3)) & |
674 |
env->a20_mask; |
env->a20_mask; |
675 |
pde = ldl_phys(pde_addr); |
pde = ldq_phys(pde_addr); |
676 |
if (!(pde & PG_PRESENT_MASK)) { |
if (!(pde & PG_PRESENT_MASK)) { |
677 |
error_code = 0; |
error_code = 0; |
678 |
goto do_fault; |
goto do_fault; |
679 |
} |
} |
680 |
|
if (!(env->efer & MSR_EFER_NXE) && (pde & PG_NX_MASK)) { |
681 |
|
error_code = PG_ERROR_RSVD_MASK; |
682 |
|
goto do_fault; |
683 |
|
} |
684 |
|
ptep &= pde ^ PG_NX_MASK; |
685 |
if (pde & PG_PSE_MASK) { |
if (pde & PG_PSE_MASK) { |
686 |
/* 2 MB page */ |
/* 2 MB page */ |
687 |
page_size = 2048 * 1024; |
page_size = 2048 * 1024; |
688 |
goto handle_big_page; |
ptep ^= PG_NX_MASK; |
689 |
|
if ((ptep & PG_NX_MASK) && is_write1 == 2) |
690 |
|
goto do_fault_protect; |
691 |
|
if (is_user) { |
692 |
|
if (!(ptep & PG_USER_MASK)) |
693 |
|
goto do_fault_protect; |
694 |
|
if (is_write && !(ptep & PG_RW_MASK)) |
695 |
|
goto do_fault_protect; |
696 |
|
} else { |
697 |
|
if ((env->cr[0] & CR0_WP_MASK) && |
698 |
|
is_write && !(ptep & PG_RW_MASK)) |
699 |
|
goto do_fault_protect; |
700 |
|
} |
701 |
|
is_dirty = is_write && !(pde & PG_DIRTY_MASK); |
702 |
|
if (!(pde & PG_ACCESSED_MASK) || is_dirty) { |
703 |
|
pde |= PG_ACCESSED_MASK; |
704 |
|
if (is_dirty) |
705 |
|
pde |= PG_DIRTY_MASK; |
706 |
|
stl_phys_notdirty(pde_addr, pde); |
707 |
|
} |
708 |
|
/* align to page_size */ |
709 |
|
pte = pde & ((PHYS_ADDR_MASK & ~(page_size - 1)) | 0xfff); |
710 |
|
virt_addr = addr & ~(page_size - 1); |
711 |
} else { |
} else { |
712 |
/* 4 KB page */ |
/* 4 KB page */ |
713 |
if (!(pde & PG_ACCESSED_MASK)) { |
if (!(pde & PG_ACCESSED_MASK)) { |
714 |
pde |= PG_ACCESSED_MASK; |
pde |= PG_ACCESSED_MASK; |
715 |
stl_phys_notdirty(pde_addr, pde); |
stl_phys_notdirty(pde_addr, pde); |
716 |
} |
} |
717 |
pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) & |
pte_addr = ((pde & PHYS_ADDR_MASK) + (((addr >> 12) & 0x1ff) << 3)) & |
718 |
env->a20_mask; |
env->a20_mask; |
719 |
goto handle_4k_page; |
pte = ldq_phys(pte_addr); |
720 |
|
if (!(pte & PG_PRESENT_MASK)) { |
721 |
|
error_code = 0; |
722 |
|
goto do_fault; |
723 |
|
} |
724 |
|
if (!(env->efer & MSR_EFER_NXE) && (pte & PG_NX_MASK)) { |
725 |
|
error_code = PG_ERROR_RSVD_MASK; |
726 |
|
goto do_fault; |
727 |
|
} |
728 |
|
/* combine pde and pte nx, user and rw protections */ |
729 |
|
ptep &= pte ^ PG_NX_MASK; |
730 |
|
ptep ^= PG_NX_MASK; |
731 |
|
if ((ptep & PG_NX_MASK) && is_write1 == 2) |
732 |
|
goto do_fault_protect; |
733 |
|
if (is_user) { |
734 |
|
if (!(ptep & PG_USER_MASK)) |
735 |
|
goto do_fault_protect; |
736 |
|
if (is_write && !(ptep & PG_RW_MASK)) |
737 |
|
goto do_fault_protect; |
738 |
|
} else { |
739 |
|
if ((env->cr[0] & CR0_WP_MASK) && |
740 |
|
is_write && !(ptep & PG_RW_MASK)) |
741 |
|
goto do_fault_protect; |
742 |
|
} |
743 |
|
is_dirty = is_write && !(pte & PG_DIRTY_MASK); |
744 |
|
if (!(pte & PG_ACCESSED_MASK) || is_dirty) { |
745 |
|
pte |= PG_ACCESSED_MASK; |
746 |
|
if (is_dirty) |
747 |
|
pte |= PG_DIRTY_MASK; |
748 |
|
stl_phys_notdirty(pte_addr, pte); |
749 |
|
} |
750 |
|
page_size = 4096; |
751 |
|
virt_addr = addr & ~0xfff; |
752 |
|
pte = pte & (PHYS_ADDR_MASK | 0xfff); |
753 |
} |
} |
754 |
} else { |
} else { |
755 |
|
uint32_t pde; |
756 |
|
|
757 |
/* page directory entry */ |
/* page directory entry */ |
758 |
pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & |
pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & |
759 |
env->a20_mask; |
env->a20_mask; |
765 |
/* if PSE bit is set, then we use a 4MB page */ |
/* if PSE bit is set, then we use a 4MB page */ |
766 |
if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) { |
if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) { |
767 |
page_size = 4096 * 1024; |
page_size = 4096 * 1024; |
|
handle_big_page: |
|
768 |
if (is_user) { |
if (is_user) { |
769 |
if (!(pde & PG_USER_MASK)) |
if (!(pde & PG_USER_MASK)) |
770 |
goto do_fault_protect; |
goto do_fault_protect; |
795 |
/* page directory entry */ |
/* page directory entry */ |
796 |
pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & |
pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & |
797 |
env->a20_mask; |
env->a20_mask; |
|
handle_4k_page: |
|
798 |
pte = ldl_phys(pte_addr); |
pte = ldl_phys(pte_addr); |
799 |
if (!(pte & PG_PRESENT_MASK)) { |
if (!(pte & PG_PRESENT_MASK)) { |
800 |
error_code = 0; |
error_code = 0; |
822 |
page_size = 4096; |
page_size = 4096; |
823 |
virt_addr = addr & ~0xfff; |
virt_addr = addr & ~0xfff; |
824 |
} |
} |
825 |
|
} |
826 |
/* the page can be put in the TLB */ |
/* the page can be put in the TLB */ |
827 |
prot = PAGE_READ; |
prot = PAGE_READ; |
828 |
if (pte & PG_DIRTY_MASK) { |
if (!(ptep & PG_NX_MASK)) |
829 |
/* only set write access if already dirty... otherwise wait |
prot |= PAGE_EXEC; |
830 |
for dirty access */ |
if (pte & PG_DIRTY_MASK) { |
831 |
if (is_user) { |
/* only set write access if already dirty... otherwise wait |
832 |
if (ptep & PG_RW_MASK) |
for dirty access */ |
833 |
prot |= PAGE_WRITE; |
if (is_user) { |
834 |
} else { |
if (ptep & PG_RW_MASK) |
835 |
if (!(env->cr[0] & CR0_WP_MASK) || |
prot |= PAGE_WRITE; |
836 |
(ptep & PG_RW_MASK)) |
} else { |
837 |
prot |= PAGE_WRITE; |
if (!(env->cr[0] & CR0_WP_MASK) || |
838 |
} |
(ptep & PG_RW_MASK)) |
839 |
|
prot |= PAGE_WRITE; |
840 |
} |
} |
841 |
} |
} |
842 |
do_mapping: |
do_mapping: |
848 |
paddr = (pte & TARGET_PAGE_MASK) + page_offset; |
paddr = (pte & TARGET_PAGE_MASK) + page_offset; |
849 |
vaddr = virt_addr + page_offset; |
vaddr = virt_addr + page_offset; |
850 |
|
|
851 |
ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu); |
ret = tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu); |
852 |
return ret; |
return ret; |
853 |
do_fault_protect: |
do_fault_protect: |
854 |
error_code = PG_ERROR_P_MASK; |
error_code = PG_ERROR_P_MASK; |
855 |
do_fault: |
do_fault: |
856 |
env->cr[2] = addr; |
env->cr[2] = addr; |
857 |
env->error_code = (is_write << PG_ERROR_W_BIT) | error_code; |
error_code |= (is_write << PG_ERROR_W_BIT); |
858 |
if (is_user) |
if (is_user) |
859 |
env->error_code |= PG_ERROR_U_MASK; |
error_code |= PG_ERROR_U_MASK; |
860 |
|
if (is_write1 == 2 && |
861 |
|
(env->efer & MSR_EFER_NXE) && |
862 |
|
(env->cr[4] & CR4_PAE_MASK)) |
863 |
|
error_code |= PG_ERROR_I_D_MASK; |
864 |
|
env->error_code = error_code; |
865 |
return 1; |
return 1; |
866 |
} |
} |
867 |
|
|