Revision fda6a0ec

b/target-ppc/cpu.h
367 367
#define SDR_64_HTABSIZE        0x000000000000001FULL
368 368
#endif /* defined(TARGET_PPC64 */
369 369

  
370
#define HASH_PTE_SIZE_32       8
371
#define HASH_PTE_SIZE_64       16
372

  
370 373
typedef struct ppc_slb_t ppc_slb_t;
371 374
struct ppc_slb_t {
372 375
    uint64_t esid;
......
744 747
    target_phys_addr_t raddr;      /* Real address              */
745 748
    target_phys_addr_t eaddr;      /* Effective address         */
746 749
    int prot;                      /* Protection bits           */
747
    target_phys_addr_t pg_addr[2]; /* PTE tables base addresses */
750
    target_phys_addr_t hash[2];    /* Pagetable hash values     */
748 751
    target_ulong ptem;             /* Virtual segment ID | API  */
749 752
    int key;                       /* Access key                */
750 753
    int nx;                        /* Non-execute area          */
b/target-ppc/helper.c
567 567
    return ret;
568 568
}
569 569

  
570
static inline target_phys_addr_t get_pteg_offset(CPUState *env,
571
                                                 target_phys_addr_t hash,
572
                                                 int pte_size)
573
{
574
    return (hash * pte_size * 8) & env->htab_mask;
575
}
576

  
570 577
/* PTE table lookup */
571
static inline int _find_pte(mmu_ctx_t *ctx, int is_64b, int h, int rw,
572
                            int type, int target_page_bits)
578
static inline int _find_pte(CPUState *env, mmu_ctx_t *ctx, int is_64b, int h,
579
                            int rw, int type, int target_page_bits)
573 580
{
574
    target_ulong base, pte0, pte1;
581
    target_phys_addr_t pteg_off;
582
    target_ulong pte0, pte1;
575 583
    int i, good = -1;
576 584
    int ret, r;
577 585

  
578 586
    ret = -1; /* No entry found */
579
    base = ctx->pg_addr[h];
587
    pteg_off = get_pteg_offset(env, ctx->hash[h],
588
                               is_64b ? HASH_PTE_SIZE_64 : HASH_PTE_SIZE_32);
580 589
    for (i = 0; i < 8; i++) {
581 590
#if defined(TARGET_PPC64)
582 591
        if (is_64b) {
583
            pte0 = ldq_phys(base + (i * 16));
584
            pte1 = ldq_phys(base + (i * 16) + 8);
592
            pte0 = ldq_phys(env->htab_base + pteg_off + (i * 16));
593
            pte1 = ldq_phys(env->htab_base + pteg_off + (i * 16) + 8);
585 594

  
586 595
            /* We have a TLB that saves 4K pages, so let's
587 596
             * split a huge page to 4k chunks */
......
592 601
            r = pte64_check(ctx, pte0, pte1, h, rw, type);
593 602
            LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
594 603
                    TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
595
                    base + (i * 16), pte0, pte1, (int)(pte0 & 1), h,
604
                    pteg_base + (i * 16), pte0, pte1, (int)(pte0 & 1), h,
596 605
                    (int)((pte0 >> 1) & 1), ctx->ptem);
597 606
        } else
598 607
#endif
599 608
        {
600
            pte0 = ldl_phys(base + (i * 8));
601
            pte1 =  ldl_phys(base + (i * 8) + 4);
609
            pte0 = ldl_phys(env->htab_base + pteg_off + (i * 8));
610
            pte1 =  ldl_phys(env->htab_base + pteg_off + (i * 8) + 4);
602 611
            r = pte32_check(ctx, pte0, pte1, h, rw, type);
603 612
            LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
604 613
                    TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
605
                    base + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
614
                    pteg_base + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
606 615
                    (int)((pte0 >> 6) & 1), ctx->ptem);
607 616
        }
608 617
        switch (r) {
......
638 647
        if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
639 648
#if defined(TARGET_PPC64)
640 649
            if (is_64b) {
641
                stq_phys_notdirty(base + (good * 16) + 8, pte1);
650
                stq_phys_notdirty(env->htab_base + pteg_off + (good * 16) + 8,
651
                                  pte1);
642 652
            } else
643 653
#endif
644 654
            {
645
                stl_phys_notdirty(base + (good * 8) + 4, pte1);
655
                stl_phys_notdirty(env->htab_base + pteg_off + (good * 8) + 4,
656
                                  pte1);
646 657
            }
647 658
        }
648 659
    }
......
650 661
    return ret;
651 662
}
652 663

  
653
static inline int find_pte32(mmu_ctx_t *ctx, int h, int rw, int type,
654
                             int target_page_bits)
664
static inline int find_pte32(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
665
                             int type, int target_page_bits)
655 666
{
656
    return _find_pte(ctx, 0, h, rw, type, target_page_bits);
667
    return _find_pte(env, ctx, 0, h, rw, type, target_page_bits);
657 668
}
658 669

  
659 670
#if defined(TARGET_PPC64)
660
static inline int find_pte64(mmu_ctx_t *ctx, int h, int rw, int type,
661
                             int target_page_bits)
671
static inline int find_pte64(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
672
                             int type, int target_page_bits)
662 673
{
663
    return _find_pte(ctx, 1, h, rw, type, target_page_bits);
674
    return _find_pte(env, ctx, 1, h, rw, type, target_page_bits);
664 675
}
665 676
#endif
666 677

  
......
669 680
{
670 681
#if defined(TARGET_PPC64)
671 682
    if (env->mmu_model & POWERPC_MMU_64)
672
        return find_pte64(ctx, h, rw, type, target_page_bits);
683
        return find_pte64(env, ctx, h, rw, type, target_page_bits);
673 684
#endif
674 685

  
675
    return find_pte32(ctx, h, rw, type, target_page_bits);
686
    return find_pte32(env, ctx, h, rw, type, target_page_bits);
676 687
}
677 688

  
678 689
#if defined(TARGET_PPC64)
......
788 799
#endif /* defined(TARGET_PPC64) */
789 800

  
790 801
/* Perform segment based translation */
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)
794
{
795
    return htab_base | (hash & htab_mask);
796
}
797

  
798 802
static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
799 803
                              target_ulong eaddr, int rw, int type)
800 804
{
801 805
    target_phys_addr_t hash;
802
    target_ulong sr, vsid, vsid_mask, pgidx, page_mask;
803
    int ds, vsid_sh, pr, target_page_bits;
806
    target_ulong sr, vsid, pgidx, page_mask;
807
    int ds, pr, target_page_bits;
804 808
    int ret, ret2;
805 809

  
806 810
    pr = msr_pr;
......
823 827
        ds = 0;
824 828
        ctx->nx = !!(slb->vsid & SLB_VSID_N);
825 829
        ctx->eaddr = eaddr;
826
        vsid_mask = 0x00003FFFFFFFFF80ULL;
827
        vsid_sh = 7;
828 830
    } else
829 831
#endif /* defined(TARGET_PPC64) */
830 832
    {
......
835 837
        ds = sr & 0x80000000 ? 1 : 0;
836 838
        ctx->nx = sr & 0x10000000 ? 1 : 0;
837 839
        vsid = sr & 0x00FFFFFF;
838
        vsid_mask = 0x01FFFFC0;
839
        vsid_sh = 6;
840 840
        target_page_bits = TARGET_PAGE_BITS;
841 841
        LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
842 842
                TARGET_FMT_lx " lr=" TARGET_FMT_lx
......
851 851
        /* Check if instruction fetch is allowed, if needed */
852 852
        if (type != ACCESS_CODE || ctx->nx == 0) {
853 853
            /* Page address translation */
854
            /* Primary table address */
855 854
            pgidx = (eaddr & page_mask) >> target_page_bits;
856 855
#if defined(TARGET_PPC64)
857 856
            if (env->mmu_model & POWERPC_MMU_64) {
858 857
                /* XXX: this is false for 1 TB segments */
859
                hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
858
                hash = vsid ^ pgidx;
860 859
            } else
861 860
#endif
862 861
            {
863
                hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
862
                hash = vsid ^ pgidx;
864 863
            }
865 864
            LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
866 865
                    " hash " TARGET_FMT_plx "\n",
867 866
                    env->htab_base, env->htab_mask, hash);
868
            ctx->pg_addr[0] = get_pgaddr(env->htab_base, env->htab_mask, hash);
869
            /* Secondary table address */
870
            hash = (~hash) & vsid_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);
867
            ctx->hash[0] = hash;
868
            ctx->hash[1] = ~hash;
869

  
875 870
#if defined(TARGET_PPC64)
876 871
            if (env->mmu_model & POWERPC_MMU_64) {
877 872
                /* Only 5 bits of the page index are used in the AVPN */
......
895 890
            } else {
896 891
                LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
897 892
                        " 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]);
893
                        " hash=" TARGET_FMT_plx "\n",
894
                        env->htab_base, env->htab_mask, vsid, pgidx,
895
                        ctx->hash[0]);
901 896
                /* Primary table lookup */
902 897
                ret = find_pte(env, ctx, 0, rw, type, target_page_bits);
903 898
                if (ret < 0) {
......
908 903
                                " hash=" TARGET_FMT_plx " pg_addr="
909 904
                                TARGET_FMT_plx "\n", env->htab_base,
910 905
                                env->htab_mask, vsid, pgidx, hash,
911
                                ctx->pg_addr[1]);
906
                                ctx->hash[1]);
912 907
                    ret2 = find_pte(env, ctx, 1, rw, type,
913 908
                                    target_page_bits);
914 909
                    if (ret2 != -1)
......
1460 1455
                    env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1461 1456
                tlb_miss:
1462 1457
                    env->error_code |= ctx.key << 19;
1463
                    env->spr[SPR_HASH1] = ctx.pg_addr[0];
1464
                    env->spr[SPR_HASH2] = ctx.pg_addr[1];
1458
                    env->spr[SPR_HASH1] = env->htab_base +
1459
                        get_pteg_offset(env, ctx.hash[0], HASH_PTE_SIZE_32);
1460
                    env->spr[SPR_HASH2] = env->htab_base +
1461
                        get_pteg_offset(env, ctx.hash[1], HASH_PTE_SIZE_32);
1465 1462
                    break;
1466 1463
                case POWERPC_MMU_SOFT_74xx:
1467 1464
                    if (rw == 1) {

Also available in: Unified diff