661 |
661 |
return ret;
|
662 |
662 |
}
|
663 |
663 |
|
664 |
|
static inline int find_pte32(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
|
665 |
|
int type, int target_page_bits)
|
666 |
|
{
|
667 |
|
return _find_pte(env, ctx, 0, h, rw, type, target_page_bits);
|
668 |
|
}
|
669 |
|
|
670 |
|
#if defined(TARGET_PPC64)
|
671 |
|
static inline int find_pte64(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
|
672 |
|
int type, int target_page_bits)
|
673 |
|
{
|
674 |
|
return _find_pte(env, ctx, 1, h, rw, type, target_page_bits);
|
675 |
|
}
|
676 |
|
#endif
|
677 |
|
|
678 |
664 |
static inline int find_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
|
679 |
665 |
int type, int target_page_bits)
|
680 |
666 |
{
|
681 |
667 |
#if defined(TARGET_PPC64)
|
682 |
668 |
if (env->mmu_model & POWERPC_MMU_64)
|
683 |
|
return find_pte64(env, ctx, h, rw, type, target_page_bits);
|
|
669 |
return _find_pte(env, ctx, 1, h, rw, type, target_page_bits);
|
684 |
670 |
#endif
|
685 |
671 |
|
686 |
|
return find_pte32(env, ctx, h, rw, type, target_page_bits);
|
|
672 |
return _find_pte(env, ctx, 0, h, rw, type, target_page_bits);
|
687 |
673 |
}
|
688 |
674 |
|
689 |
675 |
#if defined(TARGET_PPC64)
|
... | ... | |
803 |
789 |
target_ulong eaddr, int rw, int type)
|
804 |
790 |
{
|
805 |
791 |
target_phys_addr_t hash;
|
806 |
|
target_ulong sr, vsid, pgidx, page_mask;
|
|
792 |
target_ulong vsid;
|
807 |
793 |
int ds, pr, target_page_bits;
|
808 |
794 |
int ret, ret2;
|
809 |
795 |
|
810 |
796 |
pr = msr_pr;
|
|
797 |
ctx->eaddr = eaddr;
|
811 |
798 |
#if defined(TARGET_PPC64)
|
812 |
799 |
if (env->mmu_model & POWERPC_MMU_64) {
|
813 |
800 |
ppc_slb_t *slb;
|
|
801 |
target_ulong pageaddr;
|
814 |
802 |
|
815 |
803 |
LOG_MMU("Check SLBs\n");
|
816 |
804 |
slb = slb_lookup(env, eaddr);
|
... | ... | |
819 |
807 |
}
|
820 |
808 |
|
821 |
809 |
vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
|
822 |
|
page_mask = ~SEGMENT_MASK_256M;
|
823 |
810 |
target_page_bits = (slb->vsid & SLB_VSID_L)
|
824 |
811 |
? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
|
825 |
812 |
ctx->key = !!(pr ? (slb->vsid & SLB_VSID_KP)
|
826 |
813 |
: (slb->vsid & SLB_VSID_KS));
|
827 |
814 |
ds = 0;
|
828 |
815 |
ctx->nx = !!(slb->vsid & SLB_VSID_N);
|
829 |
|
ctx->eaddr = eaddr;
|
|
816 |
|
|
817 |
pageaddr = eaddr & ((1ULL << 28) - (1ULL << target_page_bits));
|
|
818 |
/* XXX: this is false for 1 TB segments */
|
|
819 |
hash = vsid ^ (pageaddr >> target_page_bits);
|
|
820 |
/* Only 5 bits of the page index are used in the AVPN */
|
|
821 |
ctx->ptem = (slb->vsid & SLB_VSID_PTEM) | ((pageaddr >> 16) & 0x0F80);
|
830 |
822 |
} else
|
831 |
823 |
#endif /* defined(TARGET_PPC64) */
|
832 |
824 |
{
|
|
825 |
target_ulong sr, pgidx;
|
|
826 |
|
833 |
827 |
sr = env->sr[eaddr >> 28];
|
834 |
|
page_mask = 0x0FFFFFFF;
|
835 |
828 |
ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
|
836 |
829 |
((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
|
837 |
830 |
ds = sr & 0x80000000 ? 1 : 0;
|
... | ... | |
843 |
836 |
" ir=%d dr=%d pr=%d %d t=%d\n",
|
844 |
837 |
eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
|
845 |
838 |
(int)msr_dr, pr != 0 ? 1 : 0, rw, type);
|
|
839 |
pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
|
|
840 |
hash = vsid ^ pgidx;
|
|
841 |
ctx->ptem = (vsid << 7) | (pgidx >> 10);
|
846 |
842 |
}
|
847 |
843 |
LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
|
848 |
844 |
ctx->key, ds, ctx->nx, vsid);
|
... | ... | |
851 |
847 |
/* Check if instruction fetch is allowed, if needed */
|
852 |
848 |
if (type != ACCESS_CODE || ctx->nx == 0) {
|
853 |
849 |
/* Page address translation */
|
854 |
|
pgidx = (eaddr & page_mask) >> target_page_bits;
|
855 |
|
#if defined(TARGET_PPC64)
|
856 |
|
if (env->mmu_model & POWERPC_MMU_64) {
|
857 |
|
/* XXX: this is false for 1 TB segments */
|
858 |
|
hash = vsid ^ pgidx;
|
859 |
|
} else
|
860 |
|
#endif
|
861 |
|
{
|
862 |
|
hash = vsid ^ pgidx;
|
863 |
|
}
|
864 |
850 |
LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
|
865 |
851 |
" hash " TARGET_FMT_plx "\n",
|
866 |
852 |
env->htab_base, env->htab_mask, hash);
|
867 |
853 |
ctx->hash[0] = hash;
|
868 |
854 |
ctx->hash[1] = ~hash;
|
869 |
855 |
|
870 |
|
#if defined(TARGET_PPC64)
|
871 |
|
if (env->mmu_model & POWERPC_MMU_64) {
|
872 |
|
/* Only 5 bits of the page index are used in the AVPN */
|
873 |
|
if (target_page_bits > 23) {
|
874 |
|
ctx->ptem = (vsid << 12) |
|
875 |
|
((pgidx << (target_page_bits - 16)) & 0xF80);
|
876 |
|
} else {
|
877 |
|
ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80);
|
878 |
|
}
|
879 |
|
} else
|
880 |
|
#endif
|
881 |
|
{
|
882 |
|
ctx->ptem = (vsid << 7) | (pgidx >> 10);
|
883 |
|
}
|
884 |
856 |
/* Initialize real address with an invalid value */
|
885 |
857 |
ctx->raddr = (target_phys_addr_t)-1ULL;
|
886 |
858 |
if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
|
... | ... | |
889 |
861 |
ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
|
890 |
862 |
} else {
|
891 |
863 |
LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
|
892 |
|
" vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
|
|
864 |
" vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
|
893 |
865 |
" hash=" TARGET_FMT_plx "\n",
|
894 |
|
env->htab_base, env->htab_mask, vsid, pgidx,
|
|
866 |
env->htab_base, env->htab_mask, vsid, ctx->ptem,
|
895 |
867 |
ctx->hash[0]);
|
896 |
868 |
/* Primary table lookup */
|
897 |
869 |
ret = find_pte(env, ctx, 0, rw, type, target_page_bits);
|
... | ... | |
902 |
874 |
" vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
|
903 |
875 |
" hash=" TARGET_FMT_plx " pg_addr="
|
904 |
876 |
TARGET_FMT_plx "\n", env->htab_base,
|
905 |
|
env->htab_mask, vsid, pgidx, hash,
|
906 |
|
ctx->hash[1]);
|
|
877 |
env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
|
907 |
878 |
ret2 = find_pte(env, ctx, 1, rw, type,
|
908 |
879 |
target_page_bits);
|
909 |
880 |
if (ret2 != -1)
|