Commit 12de9a396acbc95e25c5d60ed097cc55777eaaed
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
Showing
5 changed files
with
373 additions
and
119 deletions
target-ppc/cpu.h
| @@ -105,10 +105,8 @@ enum { | @@ -105,10 +105,8 @@ enum { | ||
| 105 | /* BookE FSL MMU model */ | 105 | /* BookE FSL MMU model */ |
| 106 | POWERPC_MMU_BOOKE_FSL, | 106 | POWERPC_MMU_BOOKE_FSL, |
| 107 | #if defined(TARGET_PPC64) | 107 | #if defined(TARGET_PPC64) |
| 108 | - /* Standard 64 bits PowerPC MMU */ | 108 | + /* 64 bits PowerPC MMU */ |
| 109 | POWERPC_MMU_64B, | 109 | POWERPC_MMU_64B, |
| 110 | - /* 64 bits "bridge" PowerPC MMU */ | ||
| 111 | - POWERPC_MMU_64BRIDGE, | ||
| 112 | #endif /* defined(TARGET_PPC64) */ | 110 | #endif /* defined(TARGET_PPC64) */ |
| 113 | }; | 111 | }; |
| 114 | 112 | ||
| @@ -514,6 +512,8 @@ struct CPUPPCState { | @@ -514,6 +512,8 @@ struct CPUPPCState { | ||
| 514 | ppc_tlb_t *tlb; /* TLB is optional. Allocate them only if needed */ | 512 | ppc_tlb_t *tlb; /* TLB is optional. Allocate them only if needed */ |
| 515 | /* 403 dedicated access protection registers */ | 513 | /* 403 dedicated access protection registers */ |
| 516 | target_ulong pb[4]; | 514 | target_ulong pb[4]; |
| 515 | + /* PowerPC 64 SLB area */ | ||
| 516 | + int slb_nr; | ||
| 517 | 517 | ||
| 518 | int dcache_line_size; | 518 | int dcache_line_size; |
| 519 | int icache_line_size; | 519 | int icache_line_size; |
| @@ -606,10 +606,14 @@ void do_store_sdr1 (CPUPPCState *env, target_ulong value); | @@ -606,10 +606,14 @@ void do_store_sdr1 (CPUPPCState *env, target_ulong value); | ||
| 606 | #if defined(TARGET_PPC64) | 606 | #if defined(TARGET_PPC64) |
| 607 | target_ulong ppc_load_asr (CPUPPCState *env); | 607 | target_ulong ppc_load_asr (CPUPPCState *env); |
| 608 | void ppc_store_asr (CPUPPCState *env, target_ulong value); | 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 | target_ulong do_load_sr (CPUPPCState *env, int srnum); | 613 | target_ulong do_load_sr (CPUPPCState *env, int srnum); |
| 611 | -void do_store_sr (CPUPPCState *env, int srnum, target_ulong value); | ||
| 612 | #endif | 614 | #endif |
| 615 | +void do_store_sr (CPUPPCState *env, int srnum, target_ulong value); | ||
| 616 | +#endif /* !defined(CONFIG_USER_ONLY) */ | ||
| 613 | target_ulong ppc_load_xer (CPUPPCState *env); | 617 | target_ulong ppc_load_xer (CPUPPCState *env); |
| 614 | void ppc_store_xer (CPUPPCState *env, target_ulong value); | 618 | void ppc_store_xer (CPUPPCState *env, target_ulong value); |
| 615 | target_ulong do_load_msr (CPUPPCState *env); | 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,21 +501,31 @@ static inline int _find_pte (mmu_ctx_t *ctx, int is_64b, int h, int rw) | ||
| 501 | pte0 = ldq_phys(base + (i * 16)); | 501 | pte0 = ldq_phys(base + (i * 16)); |
| 502 | pte1 = ldq_phys(base + (i * 16) + 8); | 502 | pte1 = ldq_phys(base + (i * 16) + 8); |
| 503 | r = pte64_check(ctx, pte0, pte1, h, rw); | 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 | } else | 513 | } else |
| 505 | #endif | 514 | #endif |
| 506 | { | 515 | { |
| 507 | pte0 = ldl_phys(base + (i * 8)); | 516 | pte0 = ldl_phys(base + (i * 8)); |
| 508 | pte1 = ldl_phys(base + (i * 8) + 4); | 517 | pte1 = ldl_phys(base + (i * 8) + 4); |
| 509 | r = pte32_check(ctx, pte0, pte1, h, rw); | 518 | r = pte32_check(ctx, pte0, pte1, h, rw); |
| 510 | - } | ||
| 511 | #if defined (DEBUG_MMU) | 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 | #endif | 527 | #endif |
| 528 | + } | ||
| 519 | switch (r) { | 529 | switch (r) { |
| 520 | case -3: | 530 | case -3: |
| 521 | /* PTE inconsistency */ | 531 | /* PTE inconsistency */ |
| @@ -581,24 +591,15 @@ static int find_pte64 (mmu_ctx_t *ctx, int h, int rw) | @@ -581,24 +591,15 @@ static int find_pte64 (mmu_ctx_t *ctx, int h, int rw) | ||
| 581 | static inline int find_pte (CPUState *env, mmu_ctx_t *ctx, int h, int rw) | 591 | static inline int find_pte (CPUState *env, mmu_ctx_t *ctx, int h, int rw) |
| 582 | { | 592 | { |
| 583 | #if defined(TARGET_PPC64) | 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 | return find_pte64(ctx, h, rw); | 595 | return find_pte64(ctx, h, rw); |
| 587 | #endif | 596 | #endif |
| 588 | 597 | ||
| 589 | return find_pte32(ctx, h, rw); | 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 | #if defined(TARGET_PPC64) | 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 | target_ulong *vsid, target_ulong *page_mask, int *attr) | 603 | target_ulong *vsid, target_ulong *page_mask, int *attr) |
| 603 | { | 604 | { |
| 604 | target_phys_addr_t sr_base; | 605 | target_phys_addr_t sr_base; |
| @@ -610,14 +611,23 @@ static int slb_lookup (CPUState *env, target_ulong eaddr, | @@ -610,14 +611,23 @@ static int slb_lookup (CPUState *env, target_ulong eaddr, | ||
| 610 | 611 | ||
| 611 | ret = -5; | 612 | ret = -5; |
| 612 | sr_base = env->spr[SPR_ASR]; | 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 | mask = 0x0000000000000000ULL; /* Avoid gcc warning */ | 620 | mask = 0x0000000000000000ULL; /* Avoid gcc warning */ |
| 614 | -#if 0 /* XXX: Fix this */ | ||
| 615 | slb_nr = env->slb_nr; | 621 | slb_nr = env->slb_nr; |
| 616 | -#else | ||
| 617 | - slb_nr = 32; | ||
| 618 | -#endif | ||
| 619 | for (n = 0; n < slb_nr; n++) { | 622 | for (n = 0; n < slb_nr; n++) { |
| 620 | tmp64 = ldq_phys(sr_base); | 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 | if (tmp64 & 0x0000000008000000ULL) { | 631 | if (tmp64 & 0x0000000008000000ULL) { |
| 622 | /* SLB entry is valid */ | 632 | /* SLB entry is valid */ |
| 623 | switch (tmp64 & 0x0000000006000000ULL) { | 633 | switch (tmp64 & 0x0000000006000000ULL) { |
| @@ -636,7 +646,6 @@ static int slb_lookup (CPUState *env, target_ulong eaddr, | @@ -636,7 +646,6 @@ static int slb_lookup (CPUState *env, target_ulong eaddr, | ||
| 636 | } | 646 | } |
| 637 | if ((eaddr & mask) == (tmp64 & mask)) { | 647 | if ((eaddr & mask) == (tmp64 & mask)) { |
| 638 | /* SLB match */ | 648 | /* SLB match */ |
| 639 | - tmp = ldl_phys(sr_base + 8); | ||
| 640 | *vsid = ((tmp64 << 24) | (tmp >> 8)) & 0x0003FFFFFFFFFFFFULL; | 649 | *vsid = ((tmp64 << 24) | (tmp >> 8)) & 0x0003FFFFFFFFFFFFULL; |
| 641 | *page_mask = ~mask; | 650 | *page_mask = ~mask; |
| 642 | *attr = tmp & 0xFF; | 651 | *attr = tmp & 0xFF; |
| @@ -649,13 +658,80 @@ static int slb_lookup (CPUState *env, target_ulong eaddr, | @@ -649,13 +658,80 @@ static int slb_lookup (CPUState *env, target_ulong eaddr, | ||
| 649 | 658 | ||
| 650 | return ret; | 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 | #endif /* defined(TARGET_PPC64) */ | 720 | #endif /* defined(TARGET_PPC64) */ |
| 653 | 721 | ||
| 654 | /* Perform segment based translation */ | 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 | static int get_segment (CPUState *env, mmu_ctx_t *ctx, | 731 | static int get_segment (CPUState *env, mmu_ctx_t *ctx, |
| 656 | target_ulong eaddr, int rw, int type) | 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 | target_ulong sr, vsid, vsid_mask, pgidx, page_mask; | 735 | target_ulong sr, vsid, vsid_mask, pgidx, page_mask; |
| 660 | #if defined(TARGET_PPC64) | 736 | #if defined(TARGET_PPC64) |
| 661 | int attr; | 737 | int attr; |
| @@ -664,8 +740,12 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx, | @@ -664,8 +740,12 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx, | ||
| 664 | int ret, ret2; | 740 | int ret, ret2; |
| 665 | 741 | ||
| 666 | #if defined(TARGET_PPC64) | 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 | ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr); | 749 | ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr); |
| 670 | if (ret < 0) | 750 | if (ret < 0) |
| 671 | return ret; | 751 | return ret; |
| @@ -699,29 +779,53 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx, | @@ -699,29 +779,53 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx, | ||
| 699 | eaddr, (int)(eaddr >> 28), sr, env->nip, | 779 | eaddr, (int)(eaddr >> 28), sr, env->nip, |
| 700 | env->lr, msr_ir, msr_dr, msr_pr, rw, type); | 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 | #endif | 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 | ret = -1; | 790 | ret = -1; |
| 709 | if (!ds) { | 791 | if (!ds) { |
| 710 | /* Check if instruction fetch is allowed, if needed */ | 792 | /* Check if instruction fetch is allowed, if needed */ |
| 711 | if (type != ACCESS_CODE || nx == 0) { | 793 | if (type != ACCESS_CODE || nx == 0) { |
| 712 | /* Page address translation */ | 794 | /* Page address translation */ |
| 713 | - pgidx = (eaddr & page_mask) >> TARGET_PAGE_BITS; | ||
| 714 | - hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask; | ||
| 715 | /* Primary table address */ | 795 | /* Primary table address */ |
| 716 | sdr = env->sdr1; | 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 | ctx->pg_addr[0] = get_pgaddr(sdr, sdr_sh, hash, mask); | 817 | ctx->pg_addr[0] = get_pgaddr(sdr, sdr_sh, hash, mask); |
| 719 | /* Secondary table address */ | 818 | /* Secondary table address */ |
| 720 | hash = (~hash) & vsid_mask; | 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 | ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask); | 826 | ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask); |
| 722 | #if defined(TARGET_PPC64) | 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 | /* Only 5 bits of the page index are used in the AVPN */ | 829 | /* Only 5 bits of the page index are used in the AVPN */ |
| 726 | ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80); | 830 | ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80); |
| 727 | } else | 831 | } else |
| @@ -762,6 +866,27 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx, | @@ -762,6 +866,27 @@ static int get_segment (CPUState *env, mmu_ctx_t *ctx, | ||
| 762 | ret = ret2; | 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 | } else { | 890 | } else { |
| 766 | #if defined (DEBUG_MMU) | 891 | #if defined (DEBUG_MMU) |
| 767 | if (loglevel != 0) | 892 | if (loglevel != 0) |
| @@ -1103,7 +1228,6 @@ static int check_physical (CPUState *env, mmu_ctx_t *ctx, | @@ -1103,7 +1228,6 @@ static int check_physical (CPUState *env, mmu_ctx_t *ctx, | ||
| 1103 | break; | 1228 | break; |
| 1104 | #if defined(TARGET_PPC64) | 1229 | #if defined(TARGET_PPC64) |
| 1105 | case POWERPC_MMU_64B: | 1230 | case POWERPC_MMU_64B: |
| 1106 | - case POWERPC_MMU_64BRIDGE: | ||
| 1107 | /* Real address are 60 bits long */ | 1231 | /* Real address are 60 bits long */ |
| 1108 | ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL; | 1232 | ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL; |
| 1109 | ctx->prot |= PAGE_WRITE; | 1233 | ctx->prot |= PAGE_WRITE; |
| @@ -1170,7 +1294,6 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr, | @@ -1170,7 +1294,6 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr, | ||
| 1170 | /* No break here */ | 1294 | /* No break here */ |
| 1171 | #if defined(TARGET_PPC64) | 1295 | #if defined(TARGET_PPC64) |
| 1172 | case POWERPC_MMU_64B: | 1296 | case POWERPC_MMU_64B: |
| 1173 | - case POWERPC_MMU_64BRIDGE: | ||
| 1174 | #endif | 1297 | #endif |
| 1175 | if (ret < 0) { | 1298 | if (ret < 0) { |
| 1176 | /* We didn't match any BAT entry or don't have BATs */ | 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,7 +1398,6 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
| 1275 | case POWERPC_MMU_32B: | 1398 | case POWERPC_MMU_32B: |
| 1276 | #if defined(TARGET_PPC64) | 1399 | #if defined(TARGET_PPC64) |
| 1277 | case POWERPC_MMU_64B: | 1400 | case POWERPC_MMU_64B: |
| 1278 | - case POWERPC_MMU_64BRIDGE: | ||
| 1279 | #endif | 1401 | #endif |
| 1280 | env->exception_index = POWERPC_EXCP_ISI; | 1402 | env->exception_index = POWERPC_EXCP_ISI; |
| 1281 | env->error_code = 0x40000000; | 1403 | env->error_code = 0x40000000; |
| @@ -1371,7 +1493,6 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | @@ -1371,7 +1493,6 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, | ||
| 1371 | case POWERPC_MMU_32B: | 1493 | case POWERPC_MMU_32B: |
| 1372 | #if defined(TARGET_PPC64) | 1494 | #if defined(TARGET_PPC64) |
| 1373 | case POWERPC_MMU_64B: | 1495 | case POWERPC_MMU_64B: |
| 1374 | - case POWERPC_MMU_64BRIDGE: | ||
| 1375 | #endif | 1496 | #endif |
| 1376 | env->exception_index = POWERPC_EXCP_DSI; | 1497 | env->exception_index = POWERPC_EXCP_DSI; |
| 1377 | env->error_code = 0; | 1498 | env->error_code = 0; |
| @@ -1622,13 +1743,12 @@ void ppc_tlb_invalidate_all (CPUPPCState *env) | @@ -1622,13 +1743,12 @@ void ppc_tlb_invalidate_all (CPUPPCState *env) | ||
| 1622 | case POWERPC_MMU_32B: | 1743 | case POWERPC_MMU_32B: |
| 1623 | #if defined(TARGET_PPC64) | 1744 | #if defined(TARGET_PPC64) |
| 1624 | case POWERPC_MMU_64B: | 1745 | case POWERPC_MMU_64B: |
| 1625 | - case POWERPC_MMU_64BRIDGE: | ||
| 1626 | #endif /* defined(TARGET_PPC64) */ | 1746 | #endif /* defined(TARGET_PPC64) */ |
| 1627 | tlb_flush(env, 1); | 1747 | tlb_flush(env, 1); |
| 1628 | break; | 1748 | break; |
| 1629 | default: | 1749 | default: |
| 1630 | /* XXX: TODO */ | 1750 | /* XXX: TODO */ |
| 1631 | - cpu_abort(env, "Unknown MMU model %d\n", env->mmu_model); | 1751 | + cpu_abort(env, "Unknown MMU model\n"); |
| 1632 | break; | 1752 | break; |
| 1633 | } | 1753 | } |
| 1634 | } | 1754 | } |
| @@ -1688,7 +1808,6 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr) | @@ -1688,7 +1808,6 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr) | ||
| 1688 | break; | 1808 | break; |
| 1689 | #if defined(TARGET_PPC64) | 1809 | #if defined(TARGET_PPC64) |
| 1690 | case POWERPC_MMU_64B: | 1810 | case POWERPC_MMU_64B: |
| 1691 | - case POWERPC_MMU_64BRIDGE: | ||
| 1692 | /* tlbie invalidate TLBs for all segments */ | 1811 | /* tlbie invalidate TLBs for all segments */ |
| 1693 | /* XXX: given the fact that there are too many segments to invalidate, | 1812 | /* XXX: given the fact that there are too many segments to invalidate, |
| 1694 | * and we still don't have a tlb_flush_mask(env, n, mask) in Qemu, | 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,7 +1818,7 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr) | ||
| 1699 | #endif /* defined(TARGET_PPC64) */ | 1818 | #endif /* defined(TARGET_PPC64) */ |
| 1700 | default: | 1819 | default: |
| 1701 | /* XXX: TODO */ | 1820 | /* XXX: TODO */ |
| 1702 | - cpu_abort(env, "Unknown MMU model 2\n"); | 1821 | + cpu_abort(env, "Unknown MMU model\n"); |
| 1703 | break; | 1822 | break; |
| 1704 | } | 1823 | } |
| 1705 | #else | 1824 | #else |
| @@ -1752,15 +1871,20 @@ void do_store_sdr1 (CPUPPCState *env, target_ulong value) | @@ -1752,15 +1871,20 @@ void do_store_sdr1 (CPUPPCState *env, target_ulong value) | ||
| 1752 | } | 1871 | } |
| 1753 | #endif | 1872 | #endif |
| 1754 | if (env->sdr1 != value) { | 1873 | if (env->sdr1 != value) { |
| 1874 | + /* XXX: for PowerPC 64, should check that the HTABSIZE value | ||
| 1875 | + * is <= 28 | ||
| 1876 | + */ | ||
| 1755 | env->sdr1 = value; | 1877 | env->sdr1 = value; |
| 1756 | tlb_flush(env, 1); | 1878 | tlb_flush(env, 1); |
| 1757 | } | 1879 | } |
| 1758 | } | 1880 | } |
| 1759 | 1881 | ||
| 1882 | +#if 0 // Unused | ||
| 1760 | target_ulong do_load_sr (CPUPPCState *env, int srnum) | 1883 | target_ulong do_load_sr (CPUPPCState *env, int srnum) |
| 1761 | { | 1884 | { |
| 1762 | return env->sr[srnum]; | 1885 | return env->sr[srnum]; |
| 1763 | } | 1886 | } |
| 1887 | +#endif | ||
| 1764 | 1888 | ||
| 1765 | void do_store_sr (CPUPPCState *env, int srnum, target_ulong value) | 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,6 +317,20 @@ void OPPROTO op_store_sr (void) | ||
| 317 | RETURN(); | 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 | void OPPROTO op_load_sdr1 (void) | 334 | void OPPROTO op_load_sdr1 (void) |
| 321 | { | 335 | { |
| 322 | T0 = env->sdr1; | 336 | T0 = env->sdr1; |
target-ppc/translate.c
| @@ -385,107 +385,107 @@ static inline target_ulong MASK (uint32_t start, uint32_t end) | @@ -385,107 +385,107 @@ static inline target_ulong MASK (uint32_t start, uint32_t end) | ||
| 385 | /* PowerPC Instructions types definitions */ | 385 | /* PowerPC Instructions types definitions */ |
| 386 | enum { | 386 | enum { |
| 387 | PPC_NONE = 0x0000000000000000ULL, | 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 | PPC_INSNS_BASE = 0x0000000000000001ULL, | 389 | PPC_INSNS_BASE = 0x0000000000000001ULL, |
| 390 | + /* integer operations instructions */ | ||
| 395 | #define PPC_INTEGER PPC_INSNS_BASE | 391 | #define PPC_INTEGER PPC_INSNS_BASE |
| 392 | + /* flow control instructions */ | ||
| 396 | #define PPC_FLOW PPC_INSNS_BASE | 393 | #define PPC_FLOW PPC_INSNS_BASE |
| 394 | + /* virtual memory instructions */ | ||
| 397 | #define PPC_MEM PPC_INSNS_BASE | 395 | #define PPC_MEM PPC_INSNS_BASE |
| 396 | + /* ld/st with reservation instructions */ | ||
| 398 | #define PPC_RES PPC_INSNS_BASE | 397 | #define PPC_RES PPC_INSNS_BASE |
| 398 | + /* cache control instructions */ | ||
| 399 | #define PPC_CACHE PPC_INSNS_BASE | 399 | #define PPC_CACHE PPC_INSNS_BASE |
| 400 | + /* spr/msr access instructions */ | ||
| 400 | #define PPC_MISC PPC_INSNS_BASE | 401 | #define PPC_MISC PPC_INSNS_BASE |
| 401 | - /* Optional floating point instructions */ | 402 | + /* Optional floating point instructions */ |
| 402 | PPC_FLOAT = 0x0000000000000002ULL, | 403 | PPC_FLOAT = 0x0000000000000002ULL, |
| 403 | PPC_FLOAT_FSQRT = 0x0000000000000004ULL, | 404 | PPC_FLOAT_FSQRT = 0x0000000000000004ULL, |
| 404 | PPC_FLOAT_FRES = 0x0000000000000008ULL, | 405 | PPC_FLOAT_FRES = 0x0000000000000008ULL, |
| 405 | PPC_FLOAT_FRSQRTE = 0x0000000000000010ULL, | 406 | PPC_FLOAT_FRSQRTE = 0x0000000000000010ULL, |
| 406 | PPC_FLOAT_FSEL = 0x0000000000000020ULL, | 407 | PPC_FLOAT_FSEL = 0x0000000000000020ULL, |
| 407 | PPC_FLOAT_STFIWX = 0x0000000000000040ULL, | 408 | PPC_FLOAT_STFIWX = 0x0000000000000040ULL, |
| 408 | - /* external control instructions */ | 409 | + /* external control instructions */ |
| 409 | PPC_EXTERN = 0x0000000000000080ULL, | 410 | PPC_EXTERN = 0x0000000000000080ULL, |
| 410 | - /* segment register access instructions */ | 411 | + /* segment register access instructions */ |
| 411 | PPC_SEGMENT = 0x0000000000000100ULL, | 412 | PPC_SEGMENT = 0x0000000000000100ULL, |
| 412 | - /* Optional cache control instruction */ | 413 | + /* Optional cache control instruction */ |
| 413 | PPC_CACHE_DCBA = 0x0000000000000200ULL, | 414 | PPC_CACHE_DCBA = 0x0000000000000200ULL, |
| 414 | - /* Optional memory control instructions */ | 415 | + /* Optional memory control instructions */ |
| 415 | PPC_MEM_TLBIA = 0x0000000000000400ULL, | 416 | PPC_MEM_TLBIA = 0x0000000000000400ULL, |
| 416 | PPC_MEM_TLBIE = 0x0000000000000800ULL, | 417 | PPC_MEM_TLBIE = 0x0000000000000800ULL, |
| 417 | PPC_MEM_TLBSYNC = 0x0000000000001000ULL, | 418 | PPC_MEM_TLBSYNC = 0x0000000000001000ULL, |
| 418 | - /* eieio & sync */ | 419 | + /* eieio & sync */ |
| 419 | PPC_MEM_SYNC = 0x0000000000002000ULL, | 420 | PPC_MEM_SYNC = 0x0000000000002000ULL, |
| 420 | - /* PowerPC 6xx TLB management instructions */ | 421 | + /* PowerPC 6xx TLB management instructions */ |
| 421 | PPC_6xx_TLB = 0x0000000000004000ULL, | 422 | PPC_6xx_TLB = 0x0000000000004000ULL, |
| 422 | - /* Altivec support */ | 423 | + /* Altivec support */ |
| 423 | PPC_ALTIVEC = 0x0000000000008000ULL, | 424 | PPC_ALTIVEC = 0x0000000000008000ULL, |
| 424 | - /* Time base mftb instruction */ | 425 | + /* Time base mftb instruction */ |
| 425 | PPC_MFTB = 0x0000000000010000ULL, | 426 | PPC_MFTB = 0x0000000000010000ULL, |
| 426 | - /* Embedded PowerPC dedicated instructions */ | 427 | + /* Embedded PowerPC dedicated instructions */ |
| 427 | PPC_EMB_COMMON = 0x0000000000020000ULL, | 428 | PPC_EMB_COMMON = 0x0000000000020000ULL, |
| 428 | - /* PowerPC 40x exception model */ | 429 | + /* PowerPC 40x exception model */ |
| 429 | PPC_40x_EXCP = 0x0000000000040000ULL, | 430 | PPC_40x_EXCP = 0x0000000000040000ULL, |
| 430 | - /* PowerPC 40x TLB management instructions */ | 431 | + /* PowerPC 40x TLB management instructions */ |
| 431 | PPC_40x_TLB = 0x0000000000080000ULL, | 432 | PPC_40x_TLB = 0x0000000000080000ULL, |
| 432 | - /* PowerPC 405 Mac instructions */ | 433 | + /* PowerPC 405 Mac instructions */ |
| 433 | PPC_405_MAC = 0x0000000000100000ULL, | 434 | PPC_405_MAC = 0x0000000000100000ULL, |
| 434 | - /* PowerPC 440 specific instructions */ | 435 | + /* PowerPC 440 specific instructions */ |
| 435 | PPC_440_SPEC = 0x0000000000200000ULL, | 436 | PPC_440_SPEC = 0x0000000000200000ULL, |
| 436 | - /* Power-to-PowerPC bridge (601) */ | 437 | + /* Power-to-PowerPC bridge (601) */ |
| 437 | PPC_POWER_BR = 0x0000000000400000ULL, | 438 | PPC_POWER_BR = 0x0000000000400000ULL, |
| 438 | - /* PowerPC 602 specific */ | 439 | + /* PowerPC 602 specific */ |
| 439 | PPC_602_SPEC = 0x0000000000800000ULL, | 440 | PPC_602_SPEC = 0x0000000000800000ULL, |
| 440 | - /* Deprecated instructions */ | ||
| 441 | - /* Original POWER instruction set */ | 441 | + /* Deprecated instructions */ |
| 442 | + /* Original POWER instruction set */ | ||
| 442 | PPC_POWER = 0x0000000001000000ULL, | 443 | PPC_POWER = 0x0000000001000000ULL, |
| 443 | - /* POWER2 instruction set extension */ | 444 | + /* POWER2 instruction set extension */ |
| 444 | PPC_POWER2 = 0x0000000002000000ULL, | 445 | PPC_POWER2 = 0x0000000002000000ULL, |
| 445 | - /* Power RTC support */ | 446 | + /* Power RTC support */ |
| 446 | PPC_POWER_RTC = 0x0000000004000000ULL, | 447 | PPC_POWER_RTC = 0x0000000004000000ULL, |
| 447 | - /* 64 bits PowerPC instructions */ | ||
| 448 | - /* 64 bits PowerPC instruction set */ | 448 | + /* 64 bits PowerPC instruction set */ |
| 449 | PPC_64B = 0x0000000008000000ULL, | 449 | PPC_64B = 0x0000000008000000ULL, |
| 450 | - /* 64 bits hypervisor extensions */ | 450 | + /* 64 bits hypervisor extensions */ |
| 451 | PPC_64H = 0x0000000010000000ULL, | 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 | PPC_BOOKE = 0x0000000040000000ULL, | 455 | PPC_BOOKE = 0x0000000040000000ULL, |
| 456 | - /* eieio */ | 456 | + /* eieio */ |
| 457 | PPC_MEM_EIEIO = 0x0000000080000000ULL, | 457 | PPC_MEM_EIEIO = 0x0000000080000000ULL, |
| 458 | - /* e500 vector instructions */ | 458 | + /* e500 vector instructions */ |
| 459 | PPC_E500_VECTOR = 0x0000000100000000ULL, | 459 | PPC_E500_VECTOR = 0x0000000100000000ULL, |
| 460 | - /* PowerPC 4xx dedicated instructions */ | 460 | + /* PowerPC 4xx dedicated instructions */ |
| 461 | PPC_4xx_COMMON = 0x0000000200000000ULL, | 461 | PPC_4xx_COMMON = 0x0000000200000000ULL, |
| 462 | - /* PowerPC 2.03 specification extensions */ | 462 | + /* PowerPC 2.03 specification extensions */ |
| 463 | PPC_203 = 0x0000000400000000ULL, | 463 | PPC_203 = 0x0000000400000000ULL, |
| 464 | - /* PowerPC 2.03 SPE extension */ | 464 | + /* PowerPC 2.03 SPE extension */ |
| 465 | PPC_SPE = 0x0000000800000000ULL, | 465 | PPC_SPE = 0x0000000800000000ULL, |
| 466 | - /* PowerPC 2.03 SPE floating-point extension */ | 466 | + /* PowerPC 2.03 SPE floating-point extension */ |
| 467 | PPC_SPEFPU = 0x0000001000000000ULL, | 467 | PPC_SPEFPU = 0x0000001000000000ULL, |
| 468 | - /* SLB management */ | 468 | + /* SLB management */ |
| 469 | PPC_SLBI = 0x0000002000000000ULL, | 469 | PPC_SLBI = 0x0000002000000000ULL, |
| 470 | - /* PowerPC 40x ibct instructions */ | 470 | + /* PowerPC 40x ibct instructions */ |
| 471 | PPC_40x_ICBT = 0x0000004000000000ULL, | 471 | PPC_40x_ICBT = 0x0000004000000000ULL, |
| 472 | - /* PowerPC 74xx TLB management instructions */ | 472 | + /* PowerPC 74xx TLB management instructions */ |
| 473 | PPC_74xx_TLB = 0x0000008000000000ULL, | 473 | PPC_74xx_TLB = 0x0000008000000000ULL, |
| 474 | - /* More BookE (embedded) instructions... */ | 474 | + /* More BookE (embedded) instructions... */ |
| 475 | PPC_BOOKE_EXT = 0x0000010000000000ULL, | 475 | PPC_BOOKE_EXT = 0x0000010000000000ULL, |
| 476 | - /* rfmci is not implemented in all BookE PowerPC */ | 476 | + /* rfmci is not implemented in all BookE PowerPC */ |
| 477 | PPC_RFMCI = 0x0000020000000000ULL, | 477 | PPC_RFMCI = 0x0000020000000000ULL, |
| 478 | - /* user-mode DCR access, implemented in PowerPC 460 */ | 478 | + /* user-mode DCR access, implemented in PowerPC 460 */ |
| 479 | PPC_DCRUX = 0x0000040000000000ULL, | 479 | PPC_DCRUX = 0x0000040000000000ULL, |
| 480 | - /* New floating-point extensions (PowerPC 2.0x) */ | 480 | + /* New floating-point extensions (PowerPC 2.0x) */ |
| 481 | PPC_FLOAT_EXT = 0x0000080000000000ULL, | 481 | PPC_FLOAT_EXT = 0x0000080000000000ULL, |
| 482 | - /* New wait instruction (PowerPC 2.0x) */ | 482 | + /* New wait instruction (PowerPC 2.0x) */ |
| 483 | PPC_WAIT = 0x0000100000000000ULL, | 483 | PPC_WAIT = 0x0000100000000000ULL, |
| 484 | - /* New 64 bits extensions (PowerPC 2.0x) */ | 484 | + /* New 64 bits extensions (PowerPC 2.0x) */ |
| 485 | PPC_64BX = 0x0000200000000000ULL, | 485 | PPC_64BX = 0x0000200000000000ULL, |
| 486 | - /* dcbz instruction with fixed cache line size */ | 486 | + /* dcbz instruction with fixed cache line size */ |
| 487 | PPC_CACHE_DCBZ = 0x0000400000000000ULL, | 487 | PPC_CACHE_DCBZ = 0x0000400000000000ULL, |
| 488 | - /* dcbz instruction with tunable cache line size */ | 488 | + /* dcbz instruction with tunable cache line size */ |
| 489 | PPC_CACHE_DCBZT = 0x0000800000000000ULL, | 489 | PPC_CACHE_DCBZT = 0x0000800000000000ULL, |
| 490 | }; | 490 | }; |
| 491 | 491 | ||
| @@ -3931,6 +3931,75 @@ GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT) | @@ -3931,6 +3931,75 @@ GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT) | ||
| 3931 | #endif | 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 | /*** Lookaside buffer management ***/ | 4003 | /*** Lookaside buffer management ***/ |
| 3935 | /* Optional & supervisor only: */ | 4004 | /* Optional & supervisor only: */ |
| 3936 | /* tlbia */ | 4005 | /* tlbia */ |
target-ppc/translate_init.c
| @@ -3095,12 +3095,13 @@ static void init_proc_e500 (CPUPPCState *env) | @@ -3095,12 +3095,13 @@ static void init_proc_e500 (CPUPPCState *env) | ||
| 3095 | /* Non-embedded PowerPC */ | 3095 | /* Non-embedded PowerPC */ |
| 3096 | /* Base instructions set for all 6xx/7xx/74xx/970 PowerPC */ | 3096 | /* Base instructions set for all 6xx/7xx/74xx/970 PowerPC */ |
| 3097 | #define POWERPC_INSNS_6xx (PPC_INSNS_BASE | PPC_FLOAT | PPC_MEM_SYNC | \ | 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 | /* Instructions common to all 6xx/7xx/74xx/970 PowerPC except 601 & 602 */ | 3099 | /* Instructions common to all 6xx/7xx/74xx/970 PowerPC except 601 & 602 */ |
| 3100 | #define POWERPC_INSNS_WORKS (POWERPC_INSNS_6xx | PPC_FLOAT_FSQRT | \ | 3100 | #define POWERPC_INSNS_WORKS (POWERPC_INSNS_6xx | PPC_FLOAT_FSQRT | \ |
| 3101 | PPC_FLOAT_FRES | PPC_FLOAT_FRSQRTE | \ | 3101 | PPC_FLOAT_FRES | PPC_FLOAT_FRSQRTE | \ |
| 3102 | PPC_FLOAT_FSEL | PPC_FLOAT_STFIWX | \ | 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 | /* POWER : same as 601, without mfmsr, mfsr */ | 3106 | /* POWER : same as 601, without mfmsr, mfsr */ |
| 3106 | #if defined(TODO) | 3107 | #if defined(TODO) |
| @@ -3111,7 +3112,7 @@ static void init_proc_e500 (CPUPPCState *env) | @@ -3111,7 +3112,7 @@ static void init_proc_e500 (CPUPPCState *env) | ||
| 3111 | 3112 | ||
| 3112 | /* PowerPC 601 */ | 3113 | /* PowerPC 601 */ |
| 3113 | #define POWERPC_INSNS_601 (POWERPC_INSNS_6xx | PPC_CACHE_DCBZ | \ | 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 | #define POWERPC_MSRM_601 (0x000000000000FE70ULL) | 3116 | #define POWERPC_MSRM_601 (0x000000000000FE70ULL) |
| 3116 | //#define POWERPC_MMU_601 (POWERPC_MMU_601) | 3117 | //#define POWERPC_MMU_601 (POWERPC_MMU_601) |
| 3117 | //#define POWERPC_EXCP_601 (POWERPC_EXCP_601) | 3118 | //#define POWERPC_EXCP_601 (POWERPC_EXCP_601) |
| @@ -3164,7 +3165,7 @@ static void init_proc_601 (CPUPPCState *env) | @@ -3164,7 +3165,7 @@ static void init_proc_601 (CPUPPCState *env) | ||
| 3164 | PPC_FLOAT_FRES | PPC_FLOAT_FRSQRTE | \ | 3165 | PPC_FLOAT_FRES | PPC_FLOAT_FRSQRTE | \ |
| 3165 | PPC_FLOAT_FSEL | PPC_FLOAT_STFIWX | \ | 3166 | PPC_FLOAT_FSEL | PPC_FLOAT_STFIWX | \ |
| 3166 | PPC_6xx_TLB | PPC_MEM_TLBSYNC | PPC_CACHE_DCBZ |\ | 3167 | PPC_6xx_TLB | PPC_MEM_TLBSYNC | PPC_CACHE_DCBZ |\ |
| 3167 | - PPC_602_SPEC) | 3168 | + PPC_SEGMENT | PPC_602_SPEC) |
| 3168 | #define POWERPC_MSRM_602 (0x000000000033FF73ULL) | 3169 | #define POWERPC_MSRM_602 (0x000000000033FF73ULL) |
| 3169 | #define POWERPC_MMU_602 (POWERPC_MMU_SOFT_6xx) | 3170 | #define POWERPC_MMU_602 (POWERPC_MMU_SOFT_6xx) |
| 3170 | //#define POWERPC_EXCP_602 (POWERPC_EXCP_602) | 3171 | //#define POWERPC_EXCP_602 (POWERPC_EXCP_602) |
| @@ -3942,15 +3943,15 @@ static void init_proc_7455 (CPUPPCState *env) | @@ -3942,15 +3943,15 @@ static void init_proc_7455 (CPUPPCState *env) | ||
| 3942 | 3943 | ||
| 3943 | #if defined (TARGET_PPC64) | 3944 | #if defined (TARGET_PPC64) |
| 3944 | #define POWERPC_INSNS_WORK64 (POWERPC_INSNS_6xx | PPC_FLOAT_FSQRT | \ | 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 | /* PowerPC 970 */ | 3949 | /* PowerPC 970 */ |
| 3949 | #define POWERPC_INSNS_970 (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT | \ | 3950 | #define POWERPC_INSNS_970 (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT | \ |
| 3950 | PPC_64B | PPC_ALTIVEC | \ | 3951 | PPC_64B | PPC_ALTIVEC | \ |
| 3951 | - PPC_64_BRIDGE | PPC_SLBI) | 3952 | + PPC_SEGMENT_64B | PPC_SLBI) |
| 3952 | #define POWERPC_MSRM_970 (0x900000000204FF36ULL) | 3953 | #define POWERPC_MSRM_970 (0x900000000204FF36ULL) |
| 3953 | -#define POWERPC_MMU_970 (POWERPC_MMU_64BRIDGE) | 3954 | +#define POWERPC_MMU_970 (POWERPC_MMU_64B) |
| 3954 | //#define POWERPC_EXCP_970 (POWERPC_EXCP_970) | 3955 | //#define POWERPC_EXCP_970 (POWERPC_EXCP_970) |
| 3955 | #define POWERPC_INPUT_970 (PPC_FLAGS_INPUT_970) | 3956 | #define POWERPC_INPUT_970 (PPC_FLAGS_INPUT_970) |
| 3956 | #define POWERPC_BFDM_970 (bfd_mach_ppc64) | 3957 | #define POWERPC_BFDM_970 (bfd_mach_ppc64) |
| @@ -3990,9 +3991,24 @@ static void init_proc_970 (CPUPPCState *env) | @@ -3990,9 +3991,24 @@ static void init_proc_970 (CPUPPCState *env) | ||
| 3990 | /* Memory management */ | 3991 | /* Memory management */ |
| 3991 | /* XXX: not correct */ | 3992 | /* XXX: not correct */ |
| 3992 | gen_low_BATs(env); | 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 | #endif | 4010 | #endif |
| 4011 | + env->slb_nr = 32; | ||
| 3996 | init_excp_970(env); | 4012 | init_excp_970(env); |
| 3997 | env->dcache_line_size = 128; | 4013 | env->dcache_line_size = 128; |
| 3998 | env->icache_line_size = 128; | 4014 | env->icache_line_size = 128; |
| @@ -4003,9 +4019,9 @@ static void init_proc_970 (CPUPPCState *env) | @@ -4003,9 +4019,9 @@ static void init_proc_970 (CPUPPCState *env) | ||
| 4003 | /* PowerPC 970FX (aka G5) */ | 4019 | /* PowerPC 970FX (aka G5) */ |
| 4004 | #define POWERPC_INSNS_970FX (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT | \ | 4020 | #define POWERPC_INSNS_970FX (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT | \ |
| 4005 | PPC_64B | PPC_ALTIVEC | \ | 4021 | PPC_64B | PPC_ALTIVEC | \ |
| 4006 | - PPC_64_BRIDGE | PPC_SLBI) | 4022 | + PPC_SEGMENT_64B | PPC_SLBI) |
| 4007 | #define POWERPC_MSRM_970FX (0x800000000204FF36ULL) | 4023 | #define POWERPC_MSRM_970FX (0x800000000204FF36ULL) |
| 4008 | -#define POWERPC_MMU_970FX (POWERPC_MMU_64BRIDGE) | 4024 | +#define POWERPC_MMU_970FX (POWERPC_MMU_64B) |
| 4009 | #define POWERPC_EXCP_970FX (POWERPC_EXCP_970) | 4025 | #define POWERPC_EXCP_970FX (POWERPC_EXCP_970) |
| 4010 | #define POWERPC_INPUT_970FX (PPC_FLAGS_INPUT_970) | 4026 | #define POWERPC_INPUT_970FX (PPC_FLAGS_INPUT_970) |
| 4011 | #define POWERPC_BFDM_970FX (bfd_mach_ppc64) | 4027 | #define POWERPC_BFDM_970FX (bfd_mach_ppc64) |
| @@ -4045,9 +4061,24 @@ static void init_proc_970FX (CPUPPCState *env) | @@ -4045,9 +4061,24 @@ static void init_proc_970FX (CPUPPCState *env) | ||
| 4045 | /* Memory management */ | 4061 | /* Memory management */ |
| 4046 | /* XXX: not correct */ | 4062 | /* XXX: not correct */ |
| 4047 | gen_low_BATs(env); | 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 | #endif | 4080 | #endif |
| 4081 | + env->slb_nr = 32; | ||
| 4051 | init_excp_970(env); | 4082 | init_excp_970(env); |
| 4052 | env->dcache_line_size = 128; | 4083 | env->dcache_line_size = 128; |
| 4053 | env->icache_line_size = 128; | 4084 | env->icache_line_size = 128; |
| @@ -4058,9 +4089,9 @@ static void init_proc_970FX (CPUPPCState *env) | @@ -4058,9 +4089,9 @@ static void init_proc_970FX (CPUPPCState *env) | ||
| 4058 | /* PowerPC 970 GX */ | 4089 | /* PowerPC 970 GX */ |
| 4059 | #define POWERPC_INSNS_970GX (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT | \ | 4090 | #define POWERPC_INSNS_970GX (POWERPC_INSNS_WORK64 | PPC_FLOAT_FSQRT | \ |
| 4060 | PPC_64B | PPC_ALTIVEC | \ | 4091 | PPC_64B | PPC_ALTIVEC | \ |
| 4061 | - PPC_64_BRIDGE | PPC_SLBI) | 4092 | + PPC_SEGMENT_64B | PPC_SLBI) |
| 4062 | #define POWERPC_MSRM_970GX (0x800000000204FF36ULL) | 4093 | #define POWERPC_MSRM_970GX (0x800000000204FF36ULL) |
| 4063 | -#define POWERPC_MMU_970GX (POWERPC_MMU_64BRIDGE) | 4094 | +#define POWERPC_MMU_970GX (POWERPC_MMU_64B) |
| 4064 | #define POWERPC_EXCP_970GX (POWERPC_EXCP_970) | 4095 | #define POWERPC_EXCP_970GX (POWERPC_EXCP_970) |
| 4065 | #define POWERPC_INPUT_970GX (PPC_FLAGS_INPUT_970) | 4096 | #define POWERPC_INPUT_970GX (PPC_FLAGS_INPUT_970) |
| 4066 | #define POWERPC_BFDM_970GX (bfd_mach_ppc64) | 4097 | #define POWERPC_BFDM_970GX (bfd_mach_ppc64) |
| @@ -4100,9 +4131,24 @@ static void init_proc_970GX (CPUPPCState *env) | @@ -4100,9 +4131,24 @@ static void init_proc_970GX (CPUPPCState *env) | ||
| 4100 | /* Memory management */ | 4131 | /* Memory management */ |
| 4101 | /* XXX: not correct */ | 4132 | /* XXX: not correct */ |
| 4102 | gen_low_BATs(env); | 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 | #endif | 4150 | #endif |
| 4151 | + env->slb_nr = 32; | ||
| 4106 | init_excp_970(env); | 4152 | init_excp_970(env); |
| 4107 | env->dcache_line_size = 128; | 4153 | env->dcache_line_size = 128; |
| 4108 | env->icache_line_size = 128; | 4154 | env->icache_line_size = 128; |
| @@ -6010,9 +6056,6 @@ int cpu_ppc_register (CPUPPCState *env, ppc_def_t *def) | @@ -6010,9 +6056,6 @@ int cpu_ppc_register (CPUPPCState *env, ppc_def_t *def) | ||
| 6010 | case POWERPC_MMU_64B: | 6056 | case POWERPC_MMU_64B: |
| 6011 | mmu_model = "PowerPC 64"; | 6057 | mmu_model = "PowerPC 64"; |
| 6012 | break; | 6058 | break; |
| 6013 | - case POWERPC_MMU_64BRIDGE: | ||
| 6014 | - mmu_model = "PowerPC 64 bridge"; | ||
| 6015 | - break; | ||
| 6016 | #endif | 6059 | #endif |
| 6017 | default: | 6060 | default: |
| 6018 | mmu_model = "Unknown or invalid"; | 6061 | mmu_model = "Unknown or invalid"; |