Commit eacc324914c2dc7aecec3b4ea920252b685b5c8e
1 parent
a01d8cad
Implement PowerPC 64 SLB invalidation helpers.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3391 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
63 additions
and
19 deletions
target-ppc/helper.c
| @@ -601,6 +601,16 @@ static always_inline int find_pte (CPUState *env, mmu_ctx_t *ctx, | @@ -601,6 +601,16 @@ static always_inline int find_pte (CPUState *env, mmu_ctx_t *ctx, | ||
| 601 | } | 601 | } |
| 602 | 602 | ||
| 603 | #if defined(TARGET_PPC64) | 603 | #if defined(TARGET_PPC64) |
| 604 | +static inline int slb_is_valid (uint64_t slb64) | ||
| 605 | +{ | ||
| 606 | + return slb64 & 0x0000000008000000ULL ? 1 : 0; | ||
| 607 | +} | ||
| 608 | + | ||
| 609 | +static inline void slb_invalidate (uint64_t *slb64) | ||
| 610 | +{ | ||
| 611 | + *slb64 &= ~0x0000000008000000ULL; | ||
| 612 | +} | ||
| 613 | + | ||
| 604 | static int slb_lookup (CPUPPCState *env, target_ulong eaddr, | 614 | static int slb_lookup (CPUPPCState *env, target_ulong eaddr, |
| 605 | target_ulong *vsid, target_ulong *page_mask, int *attr) | 615 | target_ulong *vsid, target_ulong *page_mask, int *attr) |
| 606 | { | 616 | { |
| @@ -609,7 +619,6 @@ static int slb_lookup (CPUPPCState *env, target_ulong eaddr, | @@ -609,7 +619,6 @@ static int slb_lookup (CPUPPCState *env, target_ulong eaddr, | ||
| 609 | uint64_t tmp64; | 619 | uint64_t tmp64; |
| 610 | uint32_t tmp; | 620 | uint32_t tmp; |
| 611 | int n, ret; | 621 | int n, ret; |
| 612 | - int slb_nr; | ||
| 613 | 622 | ||
| 614 | ret = -5; | 623 | ret = -5; |
| 615 | sr_base = env->spr[SPR_ASR]; | 624 | sr_base = env->spr[SPR_ASR]; |
| @@ -620,8 +629,7 @@ static int slb_lookup (CPUPPCState *env, target_ulong eaddr, | @@ -620,8 +629,7 @@ static int slb_lookup (CPUPPCState *env, target_ulong eaddr, | ||
| 620 | } | 629 | } |
| 621 | #endif | 630 | #endif |
| 622 | mask = 0x0000000000000000ULL; /* Avoid gcc warning */ | 631 | mask = 0x0000000000000000ULL; /* Avoid gcc warning */ |
| 623 | - slb_nr = env->slb_nr; | ||
| 624 | - for (n = 0; n < slb_nr; n++) { | 632 | + for (n = 0; n < env->slb_nr; n++) { |
| 625 | tmp64 = ldq_phys(sr_base); | 633 | tmp64 = ldq_phys(sr_base); |
| 626 | tmp = ldl_phys(sr_base + 8); | 634 | tmp = ldl_phys(sr_base + 8); |
| 627 | #if defined(DEBUG_SLB) | 635 | #if defined(DEBUG_SLB) |
| @@ -630,7 +638,7 @@ static int slb_lookup (CPUPPCState *env, target_ulong eaddr, | @@ -630,7 +638,7 @@ static int slb_lookup (CPUPPCState *env, target_ulong eaddr, | ||
| 630 | PRIx32 "\n", __func__, n, sr_base, tmp64, tmp); | 638 | PRIx32 "\n", __func__, n, sr_base, tmp64, tmp); |
| 631 | } | 639 | } |
| 632 | #endif | 640 | #endif |
| 633 | - if (tmp64 & 0x0000000008000000ULL) { | 641 | + if (slb_is_valid(tmp64)) { |
| 634 | /* SLB entry is valid */ | 642 | /* SLB entry is valid */ |
| 635 | switch (tmp64 & 0x0000000006000000ULL) { | 643 | switch (tmp64 & 0x0000000006000000ULL) { |
| 636 | case 0x0000000000000000ULL: | 644 | case 0x0000000000000000ULL: |
| @@ -651,7 +659,7 @@ static int slb_lookup (CPUPPCState *env, target_ulong eaddr, | @@ -651,7 +659,7 @@ static int slb_lookup (CPUPPCState *env, target_ulong eaddr, | ||
| 651 | *vsid = ((tmp64 << 24) | (tmp >> 8)) & 0x0003FFFFFFFFFFFFULL; | 659 | *vsid = ((tmp64 << 24) | (tmp >> 8)) & 0x0003FFFFFFFFFFFFULL; |
| 652 | *page_mask = ~mask; | 660 | *page_mask = ~mask; |
| 653 | *attr = tmp & 0xFF; | 661 | *attr = tmp & 0xFF; |
| 654 | - ret = 0; | 662 | + ret = n; |
| 655 | break; | 663 | break; |
| 656 | } | 664 | } |
| 657 | } | 665 | } |
| @@ -661,6 +669,56 @@ static int slb_lookup (CPUPPCState *env, target_ulong eaddr, | @@ -661,6 +669,56 @@ static int slb_lookup (CPUPPCState *env, target_ulong eaddr, | ||
| 661 | return ret; | 669 | return ret; |
| 662 | } | 670 | } |
| 663 | 671 | ||
| 672 | +void ppc_slb_invalidate_all (CPUPPCState *env) | ||
| 673 | +{ | ||
| 674 | + target_phys_addr_t sr_base; | ||
| 675 | + uint64_t tmp64; | ||
| 676 | + int n, do_invalidate; | ||
| 677 | + | ||
| 678 | + do_invalidate = 0; | ||
| 679 | + sr_base = env->spr[SPR_ASR]; | ||
| 680 | + for (n = 0; n < env->slb_nr; n++) { | ||
| 681 | + tmp64 = ldq_phys(sr_base); | ||
| 682 | + if (slb_is_valid(tmp64)) { | ||
| 683 | + slb_invalidate(&tmp64); | ||
| 684 | + stq_phys(sr_base, tmp64); | ||
| 685 | + /* XXX: given the fact that segment size is 256 MB or 1TB, | ||
| 686 | + * and we still don't have a tlb_flush_mask(env, n, mask) | ||
| 687 | + * in Qemu, we just invalidate all TLBs | ||
| 688 | + */ | ||
| 689 | + do_invalidate = 1; | ||
| 690 | + } | ||
| 691 | + sr_base += 12; | ||
| 692 | + } | ||
| 693 | + if (do_invalidate) | ||
| 694 | + tlb_flush(env, 1); | ||
| 695 | +} | ||
| 696 | + | ||
| 697 | +void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0) | ||
| 698 | +{ | ||
| 699 | + target_phys_addr_t sr_base; | ||
| 700 | + target_ulong vsid, page_mask; | ||
| 701 | + uint64_t tmp64; | ||
| 702 | + int attr; | ||
| 703 | + int n; | ||
| 704 | + | ||
| 705 | + n = slb_lookup(env, T0, &vsid, &page_mask, &attr); | ||
| 706 | + if (n >= 0) { | ||
| 707 | + sr_base = env->spr[SPR_ASR]; | ||
| 708 | + sr_base += 12 * n; | ||
| 709 | + tmp64 = ldq_phys(sr_base); | ||
| 710 | + if (slb_is_valid(tmp64)) { | ||
| 711 | + slb_invalidate(&tmp64); | ||
| 712 | + stq_phys(sr_base, tmp64); | ||
| 713 | + /* XXX: given the fact that segment size is 256 MB or 1TB, | ||
| 714 | + * and we still don't have a tlb_flush_mask(env, n, mask) | ||
| 715 | + * in Qemu, we just invalidate all TLBs | ||
| 716 | + */ | ||
| 717 | + tlb_flush(env, 1); | ||
| 718 | + } | ||
| 719 | + } | ||
| 720 | +} | ||
| 721 | + | ||
| 664 | target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr) | 722 | target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr) |
| 665 | { | 723 | { |
| 666 | target_phys_addr_t sr_base; | 724 | target_phys_addr_t sr_base; |
| @@ -1828,20 +1886,6 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr) | @@ -1828,20 +1886,6 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr) | ||
| 1828 | #endif | 1886 | #endif |
| 1829 | } | 1887 | } |
| 1830 | 1888 | ||
| 1831 | -#if defined(TARGET_PPC64) | ||
| 1832 | -void ppc_slb_invalidate_all (CPUPPCState *env) | ||
| 1833 | -{ | ||
| 1834 | - /* XXX: TODO */ | ||
| 1835 | - tlb_flush(env, 1); | ||
| 1836 | -} | ||
| 1837 | - | ||
| 1838 | -void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0) | ||
| 1839 | -{ | ||
| 1840 | - /* XXX: TODO */ | ||
| 1841 | - tlb_flush(env, 1); | ||
| 1842 | -} | ||
| 1843 | -#endif | ||
| 1844 | - | ||
| 1845 | /*****************************************************************************/ | 1889 | /*****************************************************************************/ |
| 1846 | /* Special registers manipulation */ | 1890 | /* Special registers manipulation */ |
| 1847 | #if defined(TARGET_PPC64) | 1891 | #if defined(TARGET_PPC64) |