Revision bb593904 target-ppc/helper.c
b/target-ppc/helper.c | ||
---|---|---|
788 | 788 |
#endif /* defined(TARGET_PPC64) */ |
789 | 789 |
|
790 | 790 |
/* Perform segment based translation */ |
791 |
static inline target_phys_addr_t get_pgaddr(target_phys_addr_t sdr1, |
|
792 |
int sdr_sh, |
|
793 |
target_phys_addr_t hash, |
|
794 |
target_phys_addr_t mask) |
|
791 |
static inline target_phys_addr_t get_pgaddr(target_phys_addr_t htab_base, |
|
792 |
target_phys_addr_t htab_mask, |
|
793 |
target_phys_addr_t hash) |
|
795 | 794 |
{ |
796 |
return (sdr1 & ((target_phys_addr_t)(-1ULL) << sdr_sh)) | (hash & mask);
|
|
795 |
return htab_base | (hash & htab_mask);
|
|
797 | 796 |
} |
798 | 797 |
|
799 | 798 |
static inline int get_segment(CPUState *env, mmu_ctx_t *ctx, |
800 | 799 |
target_ulong eaddr, int rw, int type) |
801 | 800 |
{ |
802 |
target_phys_addr_t sdr, hash, mask, sdr_mask, htab_mask;
|
|
801 |
target_phys_addr_t hash;
|
|
803 | 802 |
target_ulong sr, vsid, vsid_mask, pgidx, page_mask; |
804 |
int ds, vsid_sh, sdr_sh, pr, target_page_bits;
|
|
803 |
int ds, vsid_sh, pr, target_page_bits; |
|
805 | 804 |
int ret, ret2; |
806 | 805 |
|
807 | 806 |
pr = msr_pr; |
... | ... | |
826 | 825 |
ctx->eaddr = eaddr; |
827 | 826 |
vsid_mask = 0x00003FFFFFFFFF80ULL; |
828 | 827 |
vsid_sh = 7; |
829 |
sdr_sh = 18; |
|
830 |
sdr_mask = 0x3FF80; |
|
831 | 828 |
} else |
832 | 829 |
#endif /* defined(TARGET_PPC64) */ |
833 | 830 |
{ |
... | ... | |
840 | 837 |
vsid = sr & 0x00FFFFFF; |
841 | 838 |
vsid_mask = 0x01FFFFC0; |
842 | 839 |
vsid_sh = 6; |
843 |
sdr_sh = 16; |
|
844 |
sdr_mask = 0xFFC0; |
|
845 | 840 |
target_page_bits = TARGET_PAGE_BITS; |
846 | 841 |
LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip=" |
847 | 842 |
TARGET_FMT_lx " lr=" TARGET_FMT_lx |
... | ... | |
857 | 852 |
if (type != ACCESS_CODE || ctx->nx == 0) { |
858 | 853 |
/* Page address translation */ |
859 | 854 |
/* Primary table address */ |
860 |
sdr = env->sdr1; |
|
861 | 855 |
pgidx = (eaddr & page_mask) >> target_page_bits; |
862 | 856 |
#if defined(TARGET_PPC64) |
863 | 857 |
if (env->mmu_model & POWERPC_MMU_64) { |
864 |
htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F)); |
|
865 | 858 |
/* XXX: this is false for 1 TB segments */ |
866 | 859 |
hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask; |
867 | 860 |
} else |
868 | 861 |
#endif |
869 | 862 |
{ |
870 |
htab_mask = sdr & 0x000001FF; |
|
871 | 863 |
hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask; |
872 | 864 |
} |
873 |
mask = (htab_mask << sdr_sh) | sdr_mask; |
|
874 |
LOG_MMU("sdr " TARGET_FMT_plx " sh %d hash " TARGET_FMT_plx |
|
875 |
" mask " TARGET_FMT_plx " " TARGET_FMT_lx "\n", |
|
876 |
sdr, sdr_sh, hash, mask, page_mask); |
|
877 |
ctx->pg_addr[0] = get_pgaddr(sdr, sdr_sh, hash, mask); |
|
865 |
LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx |
|
866 |
" hash " TARGET_FMT_plx "\n", |
|
867 |
env->htab_base, env->htab_mask, hash); |
|
868 |
ctx->pg_addr[0] = get_pgaddr(env->htab_base, env->htab_mask, hash); |
|
878 | 869 |
/* Secondary table address */ |
879 | 870 |
hash = (~hash) & vsid_mask; |
880 |
LOG_MMU("sdr " TARGET_FMT_plx " sh %d hash " TARGET_FMT_plx |
|
881 |
" mask " TARGET_FMT_plx "\n", sdr, sdr_sh, hash, mask); |
|
882 |
ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask); |
|
871 |
LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx |
|
872 |
" hash " TARGET_FMT_plx "\n", |
|
873 |
env->htab_base, env->htab_mask, hash); |
|
874 |
ctx->pg_addr[1] = get_pgaddr(env->htab_base, env->htab_mask, hash); |
|
883 | 875 |
#if defined(TARGET_PPC64) |
884 | 876 |
if (env->mmu_model & POWERPC_MMU_64) { |
885 | 877 |
/* Only 5 bits of the page index are used in the AVPN */ |
... | ... | |
901 | 893 |
/* Software TLB search */ |
902 | 894 |
ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type); |
903 | 895 |
} else { |
904 |
LOG_MMU("0 sdr1=" TARGET_FMT_plx " vsid=" TARGET_FMT_lx " " |
|
905 |
"api=" TARGET_FMT_lx " hash=" TARGET_FMT_plx |
|
906 |
" pg_addr=" TARGET_FMT_plx "\n", |
|
907 |
sdr, vsid, pgidx, hash, ctx->pg_addr[0]); |
|
896 |
LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx |
|
897 |
" vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx |
|
898 |
" hash=" TARGET_FMT_plx " pg_addr=" TARGET_FMT_plx "\n", |
|
899 |
env->htab_base, env->htab_mask, vsid, pgidx, hash, |
|
900 |
ctx->pg_addr[0]); |
|
908 | 901 |
/* Primary table lookup */ |
909 | 902 |
ret = find_pte(env, ctx, 0, rw, type, target_page_bits); |
910 | 903 |
if (ret < 0) { |
911 | 904 |
/* Secondary table lookup */ |
912 | 905 |
if (eaddr != 0xEFFFFFFF) |
913 |
LOG_MMU("1 sdr1=" TARGET_FMT_plx " vsid=" TARGET_FMT_lx " " |
|
914 |
"api=" TARGET_FMT_lx " hash=" TARGET_FMT_plx |
|
915 |
" pg_addr=" TARGET_FMT_plx "\n", sdr, vsid, |
|
916 |
pgidx, hash, ctx->pg_addr[1]); |
|
906 |
LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx |
|
907 |
" vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx |
|
908 |
" hash=" TARGET_FMT_plx " pg_addr=" |
|
909 |
TARGET_FMT_plx "\n", env->htab_base, |
|
910 |
env->htab_mask, vsid, pgidx, hash, |
|
911 |
ctx->pg_addr[1]); |
|
917 | 912 |
ret2 = find_pte(env, ctx, 1, rw, type, |
918 | 913 |
target_page_bits); |
919 | 914 |
if (ret2 != -1) |
... | ... | |
1919 | 1914 |
void ppc_store_sdr1 (CPUPPCState *env, target_ulong value) |
1920 | 1915 |
{ |
1921 | 1916 |
LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value); |
1922 |
if (env->sdr1 != value) { |
|
1923 |
/* XXX: for PowerPC 64, should check that the HTABSIZE value |
|
1924 |
* is <= 28 |
|
1925 |
*/ |
|
1926 |
env->sdr1 = value; |
|
1917 |
if (env->spr[SPR_SDR1] != value) { |
|
1918 |
env->spr[SPR_SDR1] = value; |
|
1919 |
#if defined(TARGET_PPC64) |
|
1920 |
if (env->mmu_model & POWERPC_MMU_64) { |
|
1921 |
target_ulong htabsize = value & SDR_64_HTABSIZE; |
|
1922 |
|
|
1923 |
if (htabsize > 28) { |
|
1924 |
fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx |
|
1925 |
" stored in SDR1\n", htabsize); |
|
1926 |
htabsize = 28; |
|
1927 |
} |
|
1928 |
env->htab_mask = (1ULL << (htabsize + 18)) - 1; |
|
1929 |
env->htab_base = value & SDR_64_HTABORG; |
|
1930 |
} else |
|
1931 |
#endif /* defined(TARGET_PPC64) */ |
|
1932 |
{ |
|
1933 |
/* FIXME: Should check for valid HTABMASK values */ |
|
1934 |
env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF; |
|
1935 |
env->htab_base = value & SDR_32_HTABORG; |
|
1936 |
} |
|
1927 | 1937 |
tlb_flush(env, 1); |
1928 | 1938 |
} |
1929 | 1939 |
} |
Also available in: Unified diff