Revision eacc3249 target-ppc/helper.c
b/target-ppc/helper.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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 | 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) |
Also available in: Unified diff