Commit 12de9a396acbc95e25c5d60ed097cc55777eaaed

Authored by j_mayer
1 parent 5bfb56b2

Full implementation of PowerPC 64 MMU, just missing support for 1 TB

memory segments.
Remove the PowerPC 64 "bridge" MMU model and implement segment registers
  emulation using SLB entries instead.
Make SLB area size implementation dependant.
Improve TLB & SLB search debug traces.
Temporary hack to make PowerPC 970 boot from ROM instead of RAM.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3335 c046a42c-6fe2-441c-8c8c-71466251a162
target-ppc/cpu.h
... ... @@ -105,10 +105,8 @@ enum {
105 105 /* BookE FSL MMU model */
106 106 POWERPC_MMU_BOOKE_FSL,
107 107 #if defined(TARGET_PPC64)
108   - /* Standard 64 bits PowerPC MMU */
  108 + /* 64 bits PowerPC MMU */
109 109 POWERPC_MMU_64B,
110   - /* 64 bits "bridge" PowerPC MMU */
111   - POWERPC_MMU_64BRIDGE,
112 110 #endif /* defined(TARGET_PPC64) */
113 111 };
114 112  
... ... @@ -514,6 +512,8 @@ struct CPUPPCState {
514 512 ppc_tlb_t *tlb; /* TLB is optional. Allocate them only if needed */
515 513 /* 403 dedicated access protection registers */
516 514 target_ulong pb[4];
  515 + /* PowerPC 64 SLB area */
  516 + int slb_nr;
517 517  
518 518 int dcache_line_size;
519 519 int icache_line_size;
... ... @@ -606,10 +606,14 @@ void do_store_sdr1 (CPUPPCState *env, target_ulong value);
606 606 #if defined(TARGET_PPC64)
607 607 target_ulong ppc_load_asr (CPUPPCState *env);
608 608 void ppc_store_asr (CPUPPCState *env, target_ulong value);
609   -#endif
  609 +target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr);
  610 +void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs);
  611 +#endif /* defined(TARGET_PPC64) */
  612 +#if 0 // Unused
610 613 target_ulong do_load_sr (CPUPPCState *env, int srnum);
611   -void do_store_sr (CPUPPCState *env, int srnum, target_ulong value);
612 614 #endif
  615 +void do_store_sr (CPUPPCState *env, int srnum, target_ulong value);
  616 +#endif /* !defined(CONFIG_USER_ONLY) */
613 617 target_ulong ppc_load_xer (CPUPPCState *env);
614 618 void ppc_store_xer (CPUPPCState *env, target_ulong value);
615 619 target_ulong do_load_msr (CPUPPCState *env);
... ...
target-ppc/helper.c
... ... @@ -501,21 +501,31 @@ static inline int _find_pte (mmu_ctx_t *ctx, int is_64b, int h, int rw)
501 501 pte0 = ldq_phys(base + (i * 16));
502 502 pte1 = ldq_phys(base + (i * 16) + 8);
503 503 r = pte64_check(ctx, pte0, pte1, h, rw);
  504 +#if defined (DEBUG_MMU)
  505 + if (loglevel != 0) {
  506 + fprintf(logfile, "Load pte from 0x" ADDRX " => 0x" ADDRX
  507 + " 0x" ADDRX " %d %d %d 0x" ADDRX "\n",
  508 + base + (i * 16), pte0, pte1,
  509 + (int)(pte0 & 1), h, (int)((pte0 >> 1) & 1),
  510 + ctx->ptem);
  511 + }
  512 +#endif
504 513 } else
505 514 #endif
506 515 {
507 516 pte0 = ldl_phys(base + (i * 8));
508 517 pte1 = ldl_phys(base + (i * 8) + 4);
509 518 r = pte32_check(ctx, pte0, pte1, h, rw);
510   - }
511 519 #if defined (DEBUG_MMU)
512   - if (loglevel != 0) {
513   - fprintf(logfile, "Load pte from 0x" ADDRX " => 0x" ADDRX
514   - " 0x" ADDRX " %d %d %d 0x" ADDRX "\n",
515   - base + (i * 8), pte0, pte1,
516   - (int)(pte0 >> 31), h, (int)((pte0 >> 6) & 1), ctx->ptem);
517   - }
  520 + if (loglevel != 0) {
  521 + fprintf(logfile, "Load pte from 0x" ADDRX " => 0x" ADDRX
  522 + " 0x" ADDRX " %d %d %d 0x" ADDRX "\n",
  523 + base + (i * 8), pte0, pte1,
  524 + (int)(pte0 >> 31), h, (int)((pte0 >> 6) & 1),
  525 + ctx->ptem);
  526 + }
518 527 #endif
  528 + }
519 529 switch (r) {
520 530 case -3:
521 531 /* PTE inconsistency */
... ... @@ -581,24 +591,15 @@ static int find_pte64 (mmu_ctx_t *ctx, int h, int rw)
581 591 static inline int find_pte (CPUState *env, mmu_ctx_t *ctx, int h, int rw)
582 592 {
583 593 #if defined(TARGET_PPC64)
584   - if (env->mmu_model == POWERPC_MMU_64B ||
585   - env->mmu_model == POWERPC_MMU_64BRIDGE)
  594 + if (env->mmu_model == POWERPC_MMU_64B)
586 595 return find_pte64(ctx, h, rw);
587 596 #endif
588 597  
589 598 return find_pte32(ctx, h, rw);
590 599 }
591 600  
592   -static inline target_phys_addr_t get_pgaddr (target_phys_addr_t sdr1,
593   - int sdr_sh,
594   - target_phys_addr_t hash,
595   - target_phys_addr_t mask)
596   -{
597   - return (sdr1 & ((target_ulong)(-1ULL) << sdr_sh)) | (hash & mask);
598   -}
599   -
600 601 #if defined(TARGET_PPC64)
601   -static int slb_lookup (CPUState *env, target_ulong eaddr,
  602 +static int slb_lookup (CPUPPCState *env, target_ulong eaddr,
602 603 target_ulong *vsid, target_ulong *page_mask, int *attr)
603 604 {
604 605 target_phys_addr_t sr_base;
... ... @@ -610,14 +611,23 @@ static int slb_lookup (CPUState *env, target_ulong eaddr,
610 611  
611 612 ret = -5;
612 613 sr_base = env->spr[SPR_ASR];
  614 +#if defined(DEBUG_SLB)
  615 + if (loglevel != 0) {
  616 + fprintf(logfile, "%s: eaddr " ADDRX " base " PADDRX "\n",
  617 + __func__, eaddr, sr_base);
  618 + }
  619 +#endif
613 620 mask = 0x0000000000000000ULL; /* Avoid gcc warning */
614   -#if 0 /* XXX: Fix this */
615 621 slb_nr = env->slb_nr;
616   -#else
617   - slb_nr = 32;
618   -#endif
619 622 for (n = 0; n < slb_nr; n++) {
620 623 tmp64 = ldq_phys(sr_base);
  624 + tmp = ldl_phys(sr_base + 8);
  625 +#if defined(DEBUG_SLB)
  626 + if (loglevel != 0) {
  627 + fprintf(logfile, "%s: seg %d " PADDRX " %016" PRIx64 " %08" PRIx32 "\n",
  628 + __func__, n, sr_base, tmp64, tmp);
  629 + }
  630 +#endif
621 631 if (tmp64 & 0x0000000008000000ULL) {
622 632 /* SLB entry is valid */
623 633 switch (tmp64 & 0x0000000006000000ULL) {
... ... @@ -636,7 +646,6 @@ static int slb_lookup (CPUState *env, target_ulong eaddr,
636 646 }
637 647 if ((eaddr & mask) == (tmp64 & mask)) {
638 648 /* SLB match */
639   - tmp = ldl_phys(sr_base + 8);
640 649 *vsid = ((tmp64 << 24) | (tmp >> 8)) & 0x0003FFFFFFFFFFFFULL;
641 650 *page_mask = ~mask;
642 651 *attr = tmp & 0xFF;
... ... @@ -649,13 +658,80 @@ static int slb_lookup (CPUState *env, target_ulong eaddr,
649 658  
650 659 return ret;
651 660 }
  661 +
  662 +target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr)
  663 +{
  664 + target_phys_addr_t sr_base;
  665 + target_ulong rt;
  666 + uint64_t tmp64;
  667 + uint32_t tmp;
  668 +
  669 + sr_base = env->spr[SPR_ASR];
  670 + sr_base += 12 * slb_nr;
  671 + tmp64 = ldq_phys(sr_base);
  672 + tmp = ldl_phys(sr_base + 8);
  673 + if (tmp64 & 0x0000000008000000ULL) {
  674 + /* SLB entry is valid */
  675 + /* Copy SLB bits 62:88 to Rt 37:63 (VSID 23:49) */
  676 + rt = tmp >> 8; /* 65:88 => 40:63 */
  677 + rt |= (tmp64 & 0x7) << 24; /* 62:64 => 37:39 */
  678 + /* Copy SLB bits 89:92 to Rt 33:36 (KsKpNL) */
  679 + rt |= ((tmp >> 4) & 0xF) << 27;
  680 + } else {
  681 + rt = 0;
  682 + }
  683 +#if defined(DEBUG_SLB)
  684 + if (loglevel != 0) {
  685 + fprintf(logfile, "%s: " PADDRX " %016" PRIx64 " %08" PRIx32 " => %d "
  686 + ADDRX "\n", __func__, sr_base, tmp64, tmp, slb_nr, rt);
  687 + }
  688 +#endif
  689 +
  690 + return rt;
  691 +}
  692 +
  693 +void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs)
  694 +{
  695 + target_phys_addr_t sr_base;
  696 + uint64_t tmp64;
  697 + uint32_t tmp;
  698 +
  699 + sr_base = env->spr[SPR_ASR];
  700 + sr_base += 12 * slb_nr;
  701 + /* Copy Rs bits 37:63 to SLB 62:88 */
  702 + tmp = rs << 8;
  703 + tmp64 = (rs >> 24) & 0x7;
  704 + /* Copy Rs bits 33:36 to SLB 89:92 */
  705 + tmp |= ((rs >> 27) & 0xF) << 4;
  706 + /* Set the valid bit */
  707 + tmp64 |= 1 << 27;
  708 + /* Set ESID */
  709 + tmp64 |= (uint32_t)slb_nr << 28;
  710 +#if defined(DEBUG_SLB)
  711 + if (loglevel != 0) {
  712 + fprintf(logfile, "%s: %d " ADDRX " => " PADDRX " %016" PRIx64 " %08"
  713 + PRIx32 "\n", __func__, slb_nr, rs, sr_base, tmp64, tmp);
  714 + }
  715 +#endif
  716 + /* Write SLB entry to memory */
  717 + stq_phys(sr_base, tmp64);
  718 + stl_phys(sr_base + 8, tmp);
  719 +}
652 720 #endif /* defined(TARGET_PPC64) */
653 721  
654 722 /* Perform segment based translation */
  723 +static inline target_phys_addr_t get_pgaddr (target_phys_addr_t sdr1,
  724 + int sdr_sh,
  725 + target_phys_addr_t hash,
  726 + target_phys_addr_t mask)
  727 +{
  728 + return (sdr1 & ((target_ulong)(-1ULL) << sdr_sh)) | (hash & mask);
  729 +}
  730 +
655 731 static int get_segment (CPUState *env, mmu_ctx_t *ctx,
656 732 target_ulong eaddr, int rw, int type)
657 733 {
658   - target_phys_addr_t sdr, hash, mask, sdr_mask;
  734 + target_phys_addr_t sdr, hash, mask, sdr_mask, htab_mask;
659 735 target_ulong sr, vsid, vsid_mask, pgidx, page_mask;
660 736 #if defined(TARGET_PPC64)
661 737 int attr;
... ... @@ -664,8 +740,12 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx,
664 740 int ret, ret2;
665 741  
666 742 #if defined(TARGET_PPC64)
667   - if (env->mmu_model == POWERPC_MMU_64B ||
668   - env->mmu_model == POWERPC_MMU_64BRIDGE) {
  743 + if (env->mmu_model == POWERPC_MMU_64B) {
  744 +#if defined (DEBUG_MMU)
  745 + if (loglevel != 0) {
  746 + fprintf(logfile, "Check SLBs\n");
  747 + }
  748 +#endif
669 749 ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr);
670 750 if (ret < 0)
671 751 return ret;
... ... @@ -699,29 +779,53 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx,
699 779 eaddr, (int)(eaddr >> 28), sr, env->nip,
700 780 env->lr, msr_ir, msr_dr, msr_pr, rw, type);
701 781 }
702   - if (!ds && loglevel != 0) {
703   - fprintf(logfile, "pte segment: key=%d n=0x" ADDRX "\n",
704   - ctx->key, sr & 0x10000000);
705   - }
706 782 #endif
707 783 }
  784 +#if defined (DEBUG_MMU)
  785 + if (loglevel != 0) {
  786 + fprintf(logfile, "pte segment: key=%d ds %d nx %d vsid " ADDRX "\n",
  787 + ctx->key, ds, nx, vsid);
  788 + }
  789 +#endif
708 790 ret = -1;
709 791 if (!ds) {
710 792 /* Check if instruction fetch is allowed, if needed */
711 793 if (type != ACCESS_CODE || nx == 0) {
712 794 /* Page address translation */
713   - pgidx = (eaddr & page_mask) >> TARGET_PAGE_BITS;
714   - hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
715 795 /* Primary table address */
716 796 sdr = env->sdr1;
717   - mask = ((sdr & 0x000001FF) << sdr_sh) | sdr_mask;
  797 + pgidx = (eaddr & page_mask) >> TARGET_PAGE_BITS;
  798 +#if defined(TARGET_PPC64)
  799 + if (env->mmu_model == POWERPC_MMU_64B) {
  800 + htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F));
  801 + /* XXX: this is false for 1 TB segments */
  802 + hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
  803 + } else
  804 +#endif
  805 + {
  806 + htab_mask = sdr & 0x000001FF;
  807 + hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
  808 + }
  809 + mask = (htab_mask << sdr_sh) | sdr_mask;
  810 +#if defined (DEBUG_MMU)
  811 + if (loglevel != 0) {
  812 + fprintf(logfile, "sdr " PADDRX " sh %d hash " PADDRX " mask "
  813 + PADDRX " " ADDRX "\n", sdr, sdr_sh, hash, mask,
  814 + page_mask);
  815 + }
  816 +#endif
718 817 ctx->pg_addr[0] = get_pgaddr(sdr, sdr_sh, hash, mask);
719 818 /* Secondary table address */
720 819 hash = (~hash) & vsid_mask;
  820 +#if defined (DEBUG_MMU)
  821 + if (loglevel != 0) {
  822 + fprintf(logfile, "sdr " PADDRX " sh %d hash " PADDRX " mask "
  823 + PADDRX "\n", sdr, sdr_sh, hash, mask);
  824 + }
  825 +#endif
721 826 ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask);
722 827 #if defined(TARGET_PPC64)
723   - if (env->mmu_model == POWERPC_MMU_64B ||
724   - env->mmu_model == POWERPC_MMU_64BRIDGE) {
  828 + if (env->mmu_model == POWERPC_MMU_64B) {
725 829 /* Only 5 bits of the page index are used in the AVPN */
726 830 ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80);
727 831 } else
... ... @@ -762,6 +866,27 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx,
762 866 ret = ret2;
763 867 }
764 868 }
  869 +#if defined (DEBUG_MMU)
  870 + if (loglevel != 0) {
  871 + target_phys_addr_t curaddr;
  872 + uint32_t a0, a1, a2, a3;
  873 + fprintf(logfile,
  874 + "Page table: " PADDRX " len " PADDRX "\n",
  875 + sdr, mask + 0x80);
  876 + for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
  877 + curaddr += 16) {
  878 + a0 = ldl_phys(curaddr);
  879 + a1 = ldl_phys(curaddr + 4);
  880 + a2 = ldl_phys(curaddr + 8);
  881 + a3 = ldl_phys(curaddr + 12);
  882 + if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
  883 + fprintf(logfile,
  884 + PADDRX ": %08x %08x %08x %08x\n",
  885 + curaddr, a0, a1, a2, a3);
  886 + }
  887 + }
  888 + }
  889 +#endif
765 890 } else {
766 891 #if defined (DEBUG_MMU)
767 892 if (loglevel != 0)
... ... @@ -1103,7 +1228,6 @@ static int check_physical (CPUState *env, mmu_ctx_t *ctx,
1103 1228 break;
1104 1229 #if defined(TARGET_PPC64)
1105 1230 case POWERPC_MMU_64B:
1106   - case POWERPC_MMU_64BRIDGE:
1107 1231 /* Real address are 60 bits long */
1108 1232 ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1109 1233 ctx->prot |= PAGE_WRITE;
... ... @@ -1170,7 +1294,6 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1170 1294 /* No break here */
1171 1295 #if defined(TARGET_PPC64)
1172 1296 case POWERPC_MMU_64B:
1173   - case POWERPC_MMU_64BRIDGE:
1174 1297 #endif
1175 1298 if (ret < 0) {
1176 1299 /* We didn't match any BAT entry or don't have BATs */
... ... @@ -1275,7 +1398,6 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1275 1398 case POWERPC_MMU_32B:
1276 1399 #if defined(TARGET_PPC64)
1277 1400 case POWERPC_MMU_64B:
1278   - case POWERPC_MMU_64BRIDGE:
1279 1401 #endif
1280 1402 env->exception_index = POWERPC_EXCP_ISI;
1281 1403 env->error_code = 0x40000000;
... ... @@ -1371,7 +1493,6 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1371 1493 case POWERPC_MMU_32B:
1372 1494 #if defined(TARGET_PPC64)
1373 1495 case POWERPC_MMU_64B:
1374   - case POWERPC_MMU_64BRIDGE:
1375 1496 #endif
1376 1497 env->exception_index = POWERPC_EXCP_DSI;
1377 1498 env->error_code = 0;
... ... @@ -1622,13 +1743,12 @@ void ppc_tlb_invalidate_all (CPUPPCState *env)
1622 1743 case POWERPC_MMU_32B:
1623 1744 #if defined(TARGET_PPC64)
1624 1745 case POWERPC_MMU_64B:
1625   - case POWERPC_MMU_64BRIDGE:
1626 1746 #endif /* defined(TARGET_PPC64) */
1627 1747 tlb_flush(env, 1);
1628 1748 break;
1629 1749 default:
1630 1750 /* XXX: TODO */
1631   - cpu_abort(env, "Unknown MMU model %d\n", env->mmu_model);
  1751 + cpu_abort(env, "Unknown MMU model\n");
1632 1752 break;
1633 1753 }
1634 1754 }
... ... @@ -1688,7 +1808,6 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
1688 1808 break;
1689 1809 #if defined(TARGET_PPC64)
1690 1810 case POWERPC_MMU_64B:
1691   - case POWERPC_MMU_64BRIDGE:
1692 1811 /* tlbie invalidate TLBs for all segments */
1693 1812 /* XXX: given the fact that there are too many segments to invalidate,
1694 1813 * and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
... ... @@ -1699,7 +1818,7 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
1699 1818 #endif /* defined(TARGET_PPC64) */
1700 1819 default:
1701 1820 /* XXX: TODO */
1702   - cpu_abort(env, "Unknown MMU model 2\n");
  1821 + cpu_abort(env, "Unknown MMU model\n");
1703 1822 break;
1704 1823 }
1705 1824 #else
... ... @@ -1752,15 +1871,20 @@ void do_store_sdr1 (CPUPPCState *env, target_ulong value)
1752 1871 }
1753 1872 #endif
1754 1873 if (env->sdr1 != value) {
  1874 + /* XXX: for PowerPC 64, should check that the HTABSIZE value
  1875 + * is <= 28
  1876 + */
1755 1877 env->sdr1 = value;
1756 1878 tlb_flush(env, 1);
1757 1879 }
1758 1880 }
1759 1881  
  1882 +#if 0 // Unused
1760 1883 target_ulong do_load_sr (CPUPPCState *env, int srnum)
1761 1884 {
1762 1885 return env->sr[srnum];
1763 1886 }
  1887 +#endif
1764 1888  
1765 1889 void do_store_sr (CPUPPCState *env, int srnum, target_ulong value)
1766 1890 {
... ...
target-ppc/op.c
... ... @@ -317,6 +317,20 @@ void OPPROTO op_store_sr (void)
317 317 RETURN();
318 318 }
319 319  
  320 +#if defined(TARGET_PPC64)
  321 +void OPPROTO op_load_slb (void)
  322 +{
  323 + T0 = ppc_load_slb(env, T1);
  324 + RETURN();
  325 +}
  326 +
  327 +void OPPROTO op_store_slb (void)
  328 +{
  329 + ppc_store_slb(env, T1, T0);
  330 + RETURN();
  331 +}
  332 +#endif /* defined(TARGET_PPC64) */
  333 +
320 334 void OPPROTO op_load_sdr1 (void)
321 335 {
322 336 T0 = env->sdr1;
... ...
target-ppc/translate.c
... ... @@ -385,107 +385,107 @@ static inline target_ulong MASK (uint32_t start, uint32_t end)
385 385 /* PowerPC Instructions types definitions */
386 386 enum {
387 387 PPC_NONE = 0x0000000000000000ULL,
388   - /* integer operations instructions */
389   - /* flow control instructions */
390   - /* virtual memory instructions */
391   - /* ld/st with reservation instructions */
392   - /* cache control instructions */
393   - /* spr/msr access instructions */
  388 + /* PowerPC base instructions set */
394 389 PPC_INSNS_BASE = 0x0000000000000001ULL,
  390 + /* integer operations instructions */
395 391 #define PPC_INTEGER PPC_INSNS_BASE
  392 + /* flow control instructions */
396 393 #define PPC_FLOW PPC_INSNS_BASE
  394 + /* virtual memory instructions */
397 395 #define PPC_MEM PPC_INSNS_BASE
  396 + /* ld/st with reservation instructions */
398 397 #define PPC_RES PPC_INSNS_BASE
  398 + /* cache control instructions */
399 399 #define PPC_CACHE PPC_INSNS_BASE
  400 + /* spr/msr access instructions */
400 401 #define PPC_MISC PPC_INSNS_BASE
401   - /* Optional floating point instructions */
  402 + /* Optional floating point instructions */
402 403 PPC_FLOAT = 0x0000000000000002ULL,
403 404 PPC_FLOAT_FSQRT = 0x0000000000000004ULL,
404 405 PPC_FLOAT_FRES = 0x0000000000000008ULL,
405 406 PPC_FLOAT_FRSQRTE = 0x0000000000000010ULL,
406 407 PPC_FLOAT_FSEL = 0x0000000000000020ULL,
407 408 PPC_FLOAT_STFIWX = 0x0000000000000040ULL,
408   - /* external control instructions */
  409 + /* external control instructions */
409 410 PPC_EXTERN = 0x0000000000000080ULL,
410   - /* segment register access instructions */
  411 + /* segment register access instructions */
411 412 PPC_SEGMENT = 0x0000000000000100ULL,
412   - /* Optional cache control instruction */
  413 + /* Optional cache control instruction */
413 414 PPC_CACHE_DCBA = 0x0000000000000200ULL,
414   - /* Optional memory control instructions */
  415 + /* Optional memory control instructions */
415 416 PPC_MEM_TLBIA = 0x0000000000000400ULL,
416 417 PPC_MEM_TLBIE = 0x0000000000000800ULL,
417 418 PPC_MEM_TLBSYNC = 0x0000000000001000ULL,
418   - /* eieio & sync */
  419 + /* eieio & sync */
419 420 PPC_MEM_SYNC = 0x0000000000002000ULL,
420   - /* PowerPC 6xx TLB management instructions */
  421 + /* PowerPC 6xx TLB management instructions */
421 422 PPC_6xx_TLB = 0x0000000000004000ULL,
422   - /* Altivec support */
  423 + /* Altivec support */
423 424 PPC_ALTIVEC = 0x0000000000008000ULL,
424   - /* Time base mftb instruction */
  425 + /* Time base mftb instruction */
425 426 PPC_MFTB = 0x0000000000010000ULL,
426   - /* Embedded PowerPC dedicated instructions */
  427 + /* Embedded PowerPC dedicated instructions */
427 428 PPC_EMB_COMMON = 0x0000000000020000ULL,
428   - /* PowerPC 40x exception model */
  429 + /* PowerPC 40x exception model */
429 430 PPC_40x_EXCP = 0x0000000000040000ULL,
430   - /* PowerPC 40x TLB management instructions */
  431 + /* PowerPC 40x TLB management instructions */
431 432 PPC_40x_TLB = 0x0000000000080000ULL,
432   - /* PowerPC 405 Mac instructions */
  433 + /* PowerPC 405 Mac instructions */
433 434 PPC_405_MAC = 0x0000000000100000ULL,
434   - /* PowerPC 440 specific instructions */
  435 + /* PowerPC 440 specific instructions */
435 436 PPC_440_SPEC = 0x0000000000200000ULL,
436   - /* Power-to-PowerPC bridge (601) */
  437 + /* Power-to-PowerPC bridge (601) */
437 438 PPC_POWER_BR = 0x0000000000400000ULL,
438   - /* PowerPC 602 specific */
  439 + /* PowerPC 602 specific */
439 440 PPC_602_SPEC = 0x0000000000800000ULL,
440   - /* Deprecated instructions */
441   - /* Original POWER instruction set */
  441 + /* Deprecated instructions */
  442 + /* Original POWER instruction set */
442 443 PPC_POWER = 0x0000000001000000ULL,
443   - /* POWER2 instruction set extension */
  444 + /* POWER2 instruction set extension */
444 445 PPC_POWER2 = 0x0000000002000000ULL,
445   - /* Power RTC support */
  446 + /* Power RTC support */
446 447 PPC_POWER_RTC = 0x0000000004000000ULL,
447   - /* 64 bits PowerPC instructions */
448   - /* 64 bits PowerPC instruction set */
  448 + /* 64 bits PowerPC instruction set */
449 449 PPC_64B = 0x0000000008000000ULL,
450   - /* 64 bits hypervisor extensions */
  450 + /* 64 bits hypervisor extensions */
451 451 PPC_64H = 0x0000000010000000ULL,
452   - /* 64 bits PowerPC "bridge" features */
453   - PPC_64_BRIDGE = 0x0000000020000000ULL,
454   - /* BookE (embedded) PowerPC specification */
  452 + /* segment register access instructions for PowerPC 64 "bridge" */
  453 + PPC_SEGMENT_64B = 0x0000000020000000ULL,
  454 + /* BookE (embedded) PowerPC specification */
455 455 PPC_BOOKE = 0x0000000040000000ULL,
456   - /* eieio */
  456 + /* eieio */
457 457 PPC_MEM_EIEIO = 0x0000000080000000ULL,
458   - /* e500 vector instructions */
  458 + /* e500 vector instructions */
459 459 PPC_E500_VECTOR = 0x0000000100000000ULL,
460   - /* PowerPC 4xx dedicated instructions */
  460 + /* PowerPC 4xx dedicated instructions */
461 461 PPC_4xx_COMMON = 0x0000000200000000ULL,
462   - /* PowerPC 2.03 specification extensions */
  462 + /* PowerPC 2.03 specification extensions */
463 463 PPC_203 = 0x0000000400000000ULL,
464   - /* PowerPC 2.03 SPE extension */
  464 + /* PowerPC 2.03 SPE extension */
465 465 PPC_SPE = 0x0000000800000000ULL,
466   - /* PowerPC 2.03 SPE floating-point extension */
  466 + /* PowerPC 2.03 SPE floating-point extension */
467 467 PPC_SPEFPU = 0x0000001000000000ULL,
468   - /* SLB management */
  468 + /* SLB management */
469 469 PPC_SLBI = 0x0000002000000000ULL,
470   - /* PowerPC 40x ibct instructions */
  470 + /* PowerPC 40x ibct instructions */
471 471 PPC_40x_ICBT = 0x0000004000000000ULL,
472   - /* PowerPC 74xx TLB management instructions */
  472 + /* PowerPC 74xx TLB management instructions */
473 473 PPC_74xx_TLB = 0x0000008000000000ULL,
474   - /* More BookE (embedded) instructions... */
  474 + /* More BookE (embedded) instructions... */
475 475 PPC_BOOKE_EXT = 0x0000010000000000ULL,
476   - /* rfmci is not implemented in all BookE PowerPC */
  476 + /* rfmci is not implemented in all BookE PowerPC */
477 477 PPC_RFMCI = 0x0000020000000000ULL,
478   - /* user-mode DCR access, implemented in PowerPC 460 */
  478 + /* user-mode DCR access, implemented in PowerPC 460 */
479 479 PPC_DCRUX = 0x0000040000000000ULL,
480   - /* New floating-point extensions (PowerPC 2.0x) */
  480 + /* New floating-point extensions (PowerPC 2.0x) */
481 481 PPC_FLOAT_EXT = 0x0000080000000000ULL,
482   - /* New wait instruction (PowerPC 2.0x) */
  482 + /* New wait instruction (PowerPC 2.0x) */
483 483 PPC_WAIT = 0x0000100000000000ULL,
484   - /* New 64 bits extensions (PowerPC 2.0x) */
  484 + /* New 64 bits extensions (PowerPC 2.0x) */
485 485 PPC_64BX = 0x0000200000000000ULL,
486   - /* dcbz instruction with fixed cache line size */
  486 + /* dcbz instruction with fixed cache line size */
487 487 PPC_CACHE_DCBZ = 0x0000400000000000ULL,
488   - /* dcbz instruction with tunable cache line size */
  488 + /* dcbz instruction with tunable cache line size */
489 489 PPC_CACHE_DCBZT = 0x0000800000000000ULL,
490 490 };
491 491  
... ... @@ -3931,6 +3931,75 @@ GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
3931 3931 #endif
3932 3932 }
3933 3933  
  3934 +#if defined(TARGET_PPC64)
  3935 +/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
  3936 +/* mfsr */
  3937 +GEN_HANDLER(mfsr_64b, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B)
  3938 +{
  3939 +#if defined(CONFIG_USER_ONLY)
  3940 + GEN_EXCP_PRIVREG(ctx);
  3941 +#else
  3942 + if (unlikely(!ctx->supervisor)) {
  3943 + GEN_EXCP_PRIVREG(ctx);
  3944 + return;
  3945 + }
  3946 + gen_op_set_T1(SR(ctx->opcode));
  3947 + gen_op_load_slb();
  3948 + gen_op_store_T0_gpr(rD(ctx->opcode));
  3949 +#endif
  3950 +}
  3951 +
  3952 +/* mfsrin */
  3953 +GEN_HANDLER(mfsrin_64b, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT_64B)
  3954 +{
  3955 +#if defined(CONFIG_USER_ONLY)
  3956 + GEN_EXCP_PRIVREG(ctx);
  3957 +#else
  3958 + if (unlikely(!ctx->supervisor)) {
  3959 + GEN_EXCP_PRIVREG(ctx);
  3960 + return;
  3961 + }
  3962 + gen_op_load_gpr_T1(rB(ctx->opcode));
  3963 + gen_op_srli_T1(28);
  3964 + gen_op_load_slb();
  3965 + gen_op_store_T0_gpr(rD(ctx->opcode));
  3966 +#endif
  3967 +}
  3968 +
  3969 +/* mtsr */
  3970 +GEN_HANDLER(mtsr_64b, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B)
  3971 +{
  3972 +#if defined(CONFIG_USER_ONLY)
  3973 + GEN_EXCP_PRIVREG(ctx);
  3974 +#else
  3975 + if (unlikely(!ctx->supervisor)) {
  3976 + GEN_EXCP_PRIVREG(ctx);
  3977 + return;
  3978 + }
  3979 + gen_op_load_gpr_T0(rS(ctx->opcode));
  3980 + gen_op_set_T1(SR(ctx->opcode));
  3981 + gen_op_store_slb();
  3982 +#endif
  3983 +}
  3984 +
  3985 +/* mtsrin */
  3986 +GEN_HANDLER(mtsrin_64b, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT_64B)
  3987 +{
  3988 +#if defined(CONFIG_USER_ONLY)
  3989 + GEN_EXCP_PRIVREG(ctx);
  3990 +#else
  3991 + if (unlikely(!ctx->supervisor)) {
  3992 + GEN_EXCP_PRIVREG(ctx);
  3993 + return;
  3994 + }
  3995 + gen_op_load_gpr_T0(rS(ctx->opcode));
  3996 + gen_op_load_gpr_T1(rB(ctx->opcode));
  3997 + gen_op_srli_T1(28);
  3998 + gen_op_store_slb();
  3999 +#endif
  4000 +}
  4001 +#endif /* defined(TARGET_PPC64) */
  4002 +
3934 4003 /*** Lookaside buffer management ***/
3935 4004 /* Optional & supervisor only: */
3936 4005 /* tlbia */
... ...
target-ppc/translate_init.c
... ... @@ -3095,12 +3095,13 @@ static void init_proc_e500 (CPUPPCState *env)
3095 3095 /* Non-embedded PowerPC */
3096 3096 /* Base instructions set for all 6xx/7xx/74xx/970 PowerPC */
3097 3097 #define POWERPC_INSNS_6xx (PPC_INSNS_BASE | PPC_FLOAT | PPC_MEM_SYNC | \
3098   - PPC_MEM_EIEIO | PPC_SEGMENT | PPC_MEM_TLBIE)
  3098 + PPC_MEM_EIEIO | PPC_MEM_TLBIE)
3099 3099 /* Instructions common to all 6xx/7xx/74xx/970 PowerPC except 601 & 602 */
3100 3100 #define POWERPC_INSNS_WORKS (POWERPC_INSNS_6xx | PPC_FLOAT_FSQRT | \
3101 3101 PPC_FLOAT_FRES | PPC_FLOAT_FRSQRTE | \
3102 3102 PPC_FLOAT_FSEL | PPC_FLOAT_STFIWX | \
3103   - PPC_MEM_TLBSYNC | PPC_CACHE_DCBZ | PPC_MFTB)
  3103 + PPC_MEM_TLBSYNC | PPC_CACHE_DCBZ | PPC_MFTB | \
  3104 + PPC_SEGMENT)
3104 3105  
3105 3106 /* POWER : same as 601, without mfmsr, mfsr */
3106 3107 #if defined(TODO)
... ... @@ -3111,7 +3112,7 @@ static void init_proc_e500 (CPUPPCState *env)
3111 3112  
3112 3113 /* PowerPC 601 */
3113 3114 #define POWERPC_INSNS_601 (POWERPC_INSNS_6xx | PPC_CACHE_DCBZ | \
3114   - PPC_EXTERN | PPC_POWER_BR)
  3115 + PPC_SEGMENT | PPC_EXTERN | PPC_POWER_BR)
3115 3116 #define POWERPC_MSRM_601 (0x000000000000FE70ULL)
3116 3117 //#define POWERPC_MMU_601 (POWERPC_MMU_601)
3117 3118 //#define POWERPC_EXCP_601 (POWERPC_EXCP_601)
... ... @@ -3164,7 +3165,7 @@ static void init_proc_601 (CPUPPCState *env)
3164 3165 PPC_FLOAT_FRES | PPC_FLOAT_FRSQRTE | \
3165 3166 PPC_FLOAT_FSEL | PPC_FLOAT_STFIWX | \
3166 3167 PPC_6xx_TLB | PPC_MEM_TLBSYNC | PPC_CACHE_DCBZ |\
3167   - PPC_602_SPEC)
  3168 + PPC_SEGMENT | PPC_602_SPEC)
3168 3169 #define POWERPC_MSRM_602 (0x000000000033FF73ULL)
3169 3170 #define POWERPC_MMU_602 (POWERPC_MMU_SOFT_6xx)
3170 3171 //#define POWERPC_EXCP_602 (POWERPC_EXCP_602)
... ... @@ -3942,15 +3943,15 @@ static void init_proc_7455 (CPUPPCState *env)
3942 3943  
3943 3944 #if defined (TARGET_PPC64)
3944 3945 #define POWERPC_INSNS_WORK64 (POWERPC_INSNS_6xx | PPC_FLOAT_FSQRT | \
3945   - PPC_FLOAT_FRES | PPC_FLOAT_FRSQRTE | \
3946   - PPC_FLOAT_FSEL | PPC_FLOAT_STFIWX | \
3947   - PPC_MEM_TLBSYNC | PPC_CACHE_DCBZT | PPC_MFTB)
  3946 + PPC_FLOAT_FRES | PPC_FLOAT_FRSQRTE | \
  3947 + PPC_FLOAT_FSEL | PPC_FLOAT_STFIWX | \
  3948 + PPC_MEM_TLBSYNC | PPC_CACHE_DCBZT | PPC_MFTB)
3948 3949 /* PowerPC 970 */
3949 3950 #define POWERPC_INSNS_970 (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT | \
3950 3951 PPC_64B | PPC_ALTIVEC | \
3951   - PPC_64_BRIDGE | PPC_SLBI)
  3952 + PPC_SEGMENT_64B | PPC_SLBI)
3952 3953 #define POWERPC_MSRM_970 (0x900000000204FF36ULL)
3953   -#define POWERPC_MMU_970 (POWERPC_MMU_64BRIDGE)
  3954 +#define POWERPC_MMU_970 (POWERPC_MMU_64B)
3954 3955 //#define POWERPC_EXCP_970 (POWERPC_EXCP_970)
3955 3956 #define POWERPC_INPUT_970 (PPC_FLAGS_INPUT_970)
3956 3957 #define POWERPC_BFDM_970 (bfd_mach_ppc64)
... ... @@ -3990,9 +3991,24 @@ static void init_proc_970 (CPUPPCState *env)
3990 3991 /* Memory management */
3991 3992 /* XXX: not correct */
3992 3993 gen_low_BATs(env);
3993   -#if 0 // TODO
3994   - env->slb_nr = 32;
  3994 + /* XXX : not implemented */
  3995 + spr_register(env, SPR_MMUCFG, "MMUCFG",
  3996 + SPR_NOACCESS, SPR_NOACCESS,
  3997 + &spr_read_generic, SPR_NOACCESS,
  3998 + 0x00000000); /* TOFIX */
  3999 + /* XXX : not implemented */
  4000 + spr_register(env, SPR_MMUCSR0, "MMUCSR0",
  4001 + SPR_NOACCESS, SPR_NOACCESS,
  4002 + &spr_read_generic, &spr_write_generic,
  4003 + 0x00000000); /* TOFIX */
  4004 + spr_register(env, SPR_HIOR, "SPR_HIOR",
  4005 + SPR_NOACCESS, SPR_NOACCESS,
  4006 + &spr_read_generic, &spr_write_generic,
  4007 + 0xFFF00000); /* XXX: This is a hack */
  4008 +#if !defined(CONFIG_USER_ONLY)
  4009 + env->excp_prefix = 0xFFF00000;
3995 4010 #endif
  4011 + env->slb_nr = 32;
3996 4012 init_excp_970(env);
3997 4013 env->dcache_line_size = 128;
3998 4014 env->icache_line_size = 128;
... ... @@ -4003,9 +4019,9 @@ static void init_proc_970 (CPUPPCState *env)
4003 4019 /* PowerPC 970FX (aka G5) */
4004 4020 #define POWERPC_INSNS_970FX (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT | \
4005 4021 PPC_64B | PPC_ALTIVEC | \
4006   - PPC_64_BRIDGE | PPC_SLBI)
  4022 + PPC_SEGMENT_64B | PPC_SLBI)
4007 4023 #define POWERPC_MSRM_970FX (0x800000000204FF36ULL)
4008   -#define POWERPC_MMU_970FX (POWERPC_MMU_64BRIDGE)
  4024 +#define POWERPC_MMU_970FX (POWERPC_MMU_64B)
4009 4025 #define POWERPC_EXCP_970FX (POWERPC_EXCP_970)
4010 4026 #define POWERPC_INPUT_970FX (PPC_FLAGS_INPUT_970)
4011 4027 #define POWERPC_BFDM_970FX (bfd_mach_ppc64)
... ... @@ -4045,9 +4061,24 @@ static void init_proc_970FX (CPUPPCState *env)
4045 4061 /* Memory management */
4046 4062 /* XXX: not correct */
4047 4063 gen_low_BATs(env);
4048   -#if 0 // TODO
4049   - env->slb_nr = 32;
  4064 + /* XXX : not implemented */
  4065 + spr_register(env, SPR_MMUCFG, "MMUCFG",
  4066 + SPR_NOACCESS, SPR_NOACCESS,
  4067 + &spr_read_generic, SPR_NOACCESS,
  4068 + 0x00000000); /* TOFIX */
  4069 + /* XXX : not implemented */
  4070 + spr_register(env, SPR_MMUCSR0, "MMUCSR0",
  4071 + SPR_NOACCESS, SPR_NOACCESS,
  4072 + &spr_read_generic, &spr_write_generic,
  4073 + 0x00000000); /* TOFIX */
  4074 + spr_register(env, SPR_HIOR, "SPR_HIOR",
  4075 + SPR_NOACCESS, SPR_NOACCESS,
  4076 + &spr_read_generic, &spr_write_generic,
  4077 + 0xFFF00000); /* XXX: This is a hack */
  4078 +#if !defined(CONFIG_USER_ONLY)
  4079 + env->excp_prefix = 0xFFF00000;
4050 4080 #endif
  4081 + env->slb_nr = 32;
4051 4082 init_excp_970(env);
4052 4083 env->dcache_line_size = 128;
4053 4084 env->icache_line_size = 128;
... ... @@ -4058,9 +4089,9 @@ static void init_proc_970FX (CPUPPCState *env)
4058 4089 /* PowerPC 970 GX */
4059 4090 #define POWERPC_INSNS_970GX (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT | \
4060 4091 PPC_64B | PPC_ALTIVEC | \
4061   - PPC_64_BRIDGE | PPC_SLBI)
  4092 + PPC_SEGMENT_64B | PPC_SLBI)
4062 4093 #define POWERPC_MSRM_970GX (0x800000000204FF36ULL)
4063   -#define POWERPC_MMU_970GX (POWERPC_MMU_64BRIDGE)
  4094 +#define POWERPC_MMU_970GX (POWERPC_MMU_64B)
4064 4095 #define POWERPC_EXCP_970GX (POWERPC_EXCP_970)
4065 4096 #define POWERPC_INPUT_970GX (PPC_FLAGS_INPUT_970)
4066 4097 #define POWERPC_BFDM_970GX (bfd_mach_ppc64)
... ... @@ -4100,9 +4131,24 @@ static void init_proc_970GX (CPUPPCState *env)
4100 4131 /* Memory management */
4101 4132 /* XXX: not correct */
4102 4133 gen_low_BATs(env);
4103   -#if 0 // TODO
4104   - env->slb_nr = 32;
  4134 + /* XXX : not implemented */
  4135 + spr_register(env, SPR_MMUCFG, "MMUCFG",
  4136 + SPR_NOACCESS, SPR_NOACCESS,
  4137 + &spr_read_generic, SPR_NOACCESS,
  4138 + 0x00000000); /* TOFIX */
  4139 + /* XXX : not implemented */
  4140 + spr_register(env, SPR_MMUCSR0, "MMUCSR0",
  4141 + SPR_NOACCESS, SPR_NOACCESS,
  4142 + &spr_read_generic, &spr_write_generic,
  4143 + 0x00000000); /* TOFIX */
  4144 + spr_register(env, SPR_HIOR, "SPR_HIOR",
  4145 + SPR_NOACCESS, SPR_NOACCESS,
  4146 + &spr_read_generic, &spr_write_generic,
  4147 + 0xFFF00000); /* XXX: This is a hack */
  4148 +#if !defined(CONFIG_USER_ONLY)
  4149 + env->excp_prefix = 0xFFF00000;
4105 4150 #endif
  4151 + env->slb_nr = 32;
4106 4152 init_excp_970(env);
4107 4153 env->dcache_line_size = 128;
4108 4154 env->icache_line_size = 128;
... ... @@ -6010,9 +6056,6 @@ int cpu_ppc_register (CPUPPCState *env, ppc_def_t *def)
6010 6056 case POWERPC_MMU_64B:
6011 6057 mmu_model = "PowerPC 64";
6012 6058 break;
6013   - case POWERPC_MMU_64BRIDGE:
6014   - mmu_model = "PowerPC 64 bridge";
6015   - break;
6016 6059 #endif
6017 6060 default:
6018 6061 mmu_model = "Unknown or invalid";
... ...