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 | 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) | ... | ... |