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