Revision 256cebe5 target-ppc/helper.c
b/target-ppc/helper.c | ||
---|---|---|
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) |
Also available in: Unified diff