Commit eacc324914c2dc7aecec3b4ea920252b685b5c8e

Authored by j_mayer
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 601 }
602 602  
603 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 614 static int slb_lookup (CPUPPCState *env, target_ulong eaddr,
605 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 619 uint64_t tmp64;
610 620 uint32_t tmp;
611 621 int n, ret;
612   - int slb_nr;
613 622  
614 623 ret = -5;
615 624 sr_base = env->spr[SPR_ASR];
... ... @@ -620,8 +629,7 @@ static int slb_lookup (CPUPPCState *env, target_ulong eaddr,
620 629 }
621 630 #endif
622 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 633 tmp64 = ldq_phys(sr_base);
626 634 tmp = ldl_phys(sr_base + 8);
627 635 #if defined(DEBUG_SLB)
... ... @@ -630,7 +638,7 @@ static int slb_lookup (CPUPPCState *env, target_ulong eaddr,
630 638 PRIx32 "\n", __func__, n, sr_base, tmp64, tmp);
631 639 }
632 640 #endif
633   - if (tmp64 & 0x0000000008000000ULL) {
  641 + if (slb_is_valid(tmp64)) {
634 642 /* SLB entry is valid */
635 643 switch (tmp64 & 0x0000000006000000ULL) {
636 644 case 0x0000000000000000ULL:
... ... @@ -651,7 +659,7 @@ static int slb_lookup (CPUPPCState *env, target_ulong eaddr,
651 659 *vsid = ((tmp64 << 24) | (tmp >> 8)) & 0x0003FFFFFFFFFFFFULL;
652 660 *page_mask = ~mask;
653 661 *attr = tmp & 0xFF;
654   - ret = 0;
  662 + ret = n;
655 663 break;
656 664 }
657 665 }
... ... @@ -661,6 +669,56 @@ static int slb_lookup (CPUPPCState *env, target_ulong eaddr,
661 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 722 target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr)
665 723 {
666 724 target_phys_addr_t sr_base;
... ... @@ -1828,20 +1886,6 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
1828 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 1890 /* Special registers manipulation */
1847 1891 #if defined(TARGET_PPC64)
... ...