Revision daf4f96e target-ppc/helper.c
b/target-ppc/helper.c | ||
---|---|---|
237 | 237 |
return nr; |
238 | 238 |
} |
239 | 239 |
|
240 |
void ppc6xx_tlb_invalidate_all (CPUState *env) |
|
240 |
static void ppc6xx_tlb_invalidate_all (CPUState *env)
|
|
241 | 241 |
{ |
242 | 242 |
ppc6xx_tlb_t *tlb; |
243 | 243 |
int nr, max; |
... | ... | |
253 | 253 |
max *= 2; |
254 | 254 |
for (nr = 0; nr < max; nr++) { |
255 | 255 |
tlb = &env->tlb[nr].tlb6; |
256 |
#if !defined(FLUSH_ALL_TLBS) |
|
257 |
tlb_flush_page(env, tlb->EPN); |
|
258 |
#endif |
|
259 | 256 |
pte_invalidate(&tlb->pte0); |
260 | 257 |
} |
261 |
#if defined(FLUSH_ALL_TLBS) |
|
262 | 258 |
tlb_flush(env, 1); |
263 |
#endif |
|
264 | 259 |
} |
265 | 260 |
|
266 | 261 |
static inline void __ppc6xx_tlb_invalidate_virt (CPUState *env, |
... | ... | |
292 | 287 |
#endif |
293 | 288 |
} |
294 | 289 |
|
295 |
void ppc6xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr, |
|
296 |
int is_code) |
|
290 |
static void ppc6xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
|
|
291 |
int is_code)
|
|
297 | 292 |
{ |
298 | 293 |
__ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0); |
299 | 294 |
} |
... | ... | |
834 | 829 |
return -1; |
835 | 830 |
} |
836 | 831 |
mask = ~(tlb->size - 1); |
832 |
#if defined (DEBUG_SOFTWARE_TLB) |
|
837 | 833 |
if (loglevel != 0) { |
838 | 834 |
fprintf(logfile, "%s: TLB %d address " ADDRX " PID %d <=> " |
839 | 835 |
ADDRX " " ADDRX " %d\n", |
840 | 836 |
__func__, i, address, pid, tlb->EPN, mask, (int)tlb->PID); |
841 | 837 |
} |
838 |
#endif |
|
842 | 839 |
/* Check PID */ |
843 | 840 |
if (tlb->PID != 0 && tlb->PID != pid) |
844 | 841 |
return -1; |
... | ... | |
876 | 873 |
return ret; |
877 | 874 |
} |
878 | 875 |
|
879 |
void ppc4xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
|
|
880 |
uint32_t pid)
|
|
876 |
/* Helpers specific to PowerPC 40x implementations */
|
|
877 |
static void ppc4xx_tlb_invalidate_all (CPUState *env)
|
|
881 | 878 |
{ |
882 | 879 |
ppcemb_tlb_t *tlb; |
883 |
target_phys_addr_t raddr; |
|
884 |
target_ulong page, end; |
|
885 | 880 |
int i; |
886 | 881 |
|
887 | 882 |
for (i = 0; i < env->nb_tlb; i++) { |
888 | 883 |
tlb = &env->tlb[i].tlbe; |
889 |
if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) { |
|
890 |
end = tlb->EPN + tlb->size; |
|
891 |
for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) |
|
892 |
tlb_flush_page(env, page); |
|
893 |
tlb->prot &= ~PAGE_VALID; |
|
894 |
break; |
|
895 |
} |
|
884 |
tlb->prot &= ~PAGE_VALID; |
|
896 | 885 |
} |
886 |
tlb_flush(env, 1); |
|
897 | 887 |
} |
898 | 888 |
|
899 |
/* Helpers specific to PowerPC 40x implementations */
|
|
900 |
void ppc4xx_tlb_invalidate_all (CPUState *env)
|
|
889 |
static void ppc4xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
|
|
890 |
uint32_t pid)
|
|
901 | 891 |
{ |
892 |
#if !defined(FLUSH_ALL_TLBS) |
|
902 | 893 |
ppcemb_tlb_t *tlb; |
894 |
target_phys_addr_t raddr; |
|
895 |
target_ulong page, end; |
|
903 | 896 |
int i; |
904 | 897 |
|
905 | 898 |
for (i = 0; i < env->nb_tlb; i++) { |
906 | 899 |
tlb = &env->tlb[i].tlbe; |
907 |
if (tlb->prot & PAGE_VALID) { |
|
908 |
#if 0 // XXX: TLB have variable sizes then we flush all Qemu TLB. |
|
900 |
if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) { |
|
909 | 901 |
end = tlb->EPN + tlb->size; |
910 | 902 |
for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) |
911 | 903 |
tlb_flush_page(env, page); |
912 |
#endif |
|
913 | 904 |
tlb->prot &= ~PAGE_VALID; |
905 |
break; |
|
914 | 906 |
} |
915 | 907 |
} |
916 |
tlb_flush(env, 1); |
|
908 |
#else |
|
909 |
ppc4xx_tlb_invalidate_all(env); |
|
910 |
#endif |
|
917 | 911 |
} |
918 | 912 |
|
919 | 913 |
int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx, |
... | ... | |
932 | 926 |
continue; |
933 | 927 |
zsel = (tlb->attr >> 4) & 0xF; |
934 | 928 |
zpr = (env->spr[SPR_40x_ZPR] >> (28 - (2 * zsel))) & 0x3; |
929 |
#if defined (DEBUG_SOFTWARE_TLB) |
|
935 | 930 |
if (loglevel != 0) { |
936 | 931 |
fprintf(logfile, "%s: TLB %d zsel %d zpr %d rw %d attr %08x\n", |
937 | 932 |
__func__, i, zsel, zpr, rw, tlb->attr); |
938 | 933 |
} |
934 |
#endif |
|
939 | 935 |
if (access_type == ACCESS_CODE) { |
940 | 936 |
/* Check execute enable bit */ |
941 | 937 |
switch (zpr) { |
... | ... | |
1009 | 1005 |
} |
1010 | 1006 |
if (ret >= 0) { |
1011 | 1007 |
ctx->raddr = raddr; |
1008 |
#if defined (DEBUG_SOFTWARE_TLB) |
|
1012 | 1009 |
if (loglevel != 0) { |
1013 | 1010 |
fprintf(logfile, "%s: access granted " ADDRX " => " REGX |
1014 | 1011 |
" %d %d\n", __func__, address, ctx->raddr, ctx->prot, |
1015 | 1012 |
ret); |
1016 | 1013 |
} |
1014 |
#endif |
|
1017 | 1015 |
return 0; |
1018 | 1016 |
} |
1019 | 1017 |
} |
1018 |
#if defined (DEBUG_SOFTWARE_TLB) |
|
1020 | 1019 |
if (loglevel != 0) { |
1021 | 1020 |
fprintf(logfile, "%s: access refused " ADDRX " => " REGX |
1022 | 1021 |
" %d %d\n", __func__, address, raddr, ctx->prot, |
1023 | 1022 |
ret); |
1024 | 1023 |
} |
1024 |
#endif |
|
1025 | 1025 |
|
1026 | 1026 |
return ret; |
1027 | 1027 |
} |
... | ... | |
1569 | 1569 |
/* TLB management */ |
1570 | 1570 |
void ppc_tlb_invalidate_all (CPUPPCState *env) |
1571 | 1571 |
{ |
1572 |
if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx)) { |
|
1572 |
switch (env->mmu_model) { |
|
1573 |
case POWERPC_MMU_SOFT_6xx: |
|
1573 | 1574 |
ppc6xx_tlb_invalidate_all(env); |
1574 |
} else if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_4xx)) { |
|
1575 |
break; |
|
1576 |
case POWERPC_MMU_SOFT_4xx: |
|
1577 |
case POWERPC_MMU_SOFT_4xx_Z: |
|
1575 | 1578 |
ppc4xx_tlb_invalidate_all(env); |
1576 |
} else { |
|
1579 |
break; |
|
1580 |
default: |
|
1577 | 1581 |
tlb_flush(env, 1); |
1582 |
break; |
|
1583 |
} |
|
1584 |
} |
|
1585 |
|
|
1586 |
void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr) |
|
1587 |
{ |
|
1588 |
#if !defined(FLUSH_ALL_TLBS) |
|
1589 |
addr &= TARGET_PAGE_MASK; |
|
1590 |
switch (env->mmu_model) { |
|
1591 |
case POWERPC_MMU_SOFT_6xx: |
|
1592 |
ppc6xx_tlb_invalidate_virt(env, addr, 0); |
|
1593 |
if (env->id_tlbs == 1) |
|
1594 |
ppc6xx_tlb_invalidate_virt(env, addr, 1); |
|
1595 |
break; |
|
1596 |
case POWERPC_MMU_SOFT_4xx: |
|
1597 |
case POWERPC_MMU_SOFT_4xx_Z: |
|
1598 |
ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]); |
|
1599 |
break; |
|
1600 |
default: |
|
1601 |
/* tlbie invalidate TLBs for all segments */ |
|
1602 |
addr &= ~((target_ulong)-1 << 28); |
|
1603 |
/* XXX: this case should be optimized, |
|
1604 |
* giving a mask to tlb_flush_page |
|
1605 |
*/ |
|
1606 |
tlb_flush_page(env, addr | (0x0 << 28)); |
|
1607 |
tlb_flush_page(env, addr | (0x1 << 28)); |
|
1608 |
tlb_flush_page(env, addr | (0x2 << 28)); |
|
1609 |
tlb_flush_page(env, addr | (0x3 << 28)); |
|
1610 |
tlb_flush_page(env, addr | (0x4 << 28)); |
|
1611 |
tlb_flush_page(env, addr | (0x5 << 28)); |
|
1612 |
tlb_flush_page(env, addr | (0x6 << 28)); |
|
1613 |
tlb_flush_page(env, addr | (0x7 << 28)); |
|
1614 |
tlb_flush_page(env, addr | (0x8 << 28)); |
|
1615 |
tlb_flush_page(env, addr | (0x9 << 28)); |
|
1616 |
tlb_flush_page(env, addr | (0xA << 28)); |
|
1617 |
tlb_flush_page(env, addr | (0xB << 28)); |
|
1618 |
tlb_flush_page(env, addr | (0xC << 28)); |
|
1619 |
tlb_flush_page(env, addr | (0xD << 28)); |
|
1620 |
tlb_flush_page(env, addr | (0xE << 28)); |
|
1621 |
tlb_flush_page(env, addr | (0xF << 28)); |
|
1578 | 1622 |
} |
1623 |
#else |
|
1624 |
ppc_tlb_invalidate_all(env); |
|
1625 |
#endif |
|
1579 | 1626 |
} |
1580 | 1627 |
|
1628 |
#if defined(TARGET_PPC64) |
|
1629 |
void ppc_slb_invalidate_all (CPUPPCState *env) |
|
1630 |
{ |
|
1631 |
/* XXX: TODO */ |
|
1632 |
tlb_flush(env, 1); |
|
1633 |
} |
|
1634 |
|
|
1635 |
void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0) |
|
1636 |
{ |
|
1637 |
/* XXX: TODO */ |
|
1638 |
tlb_flush(env, 1); |
|
1639 |
} |
|
1640 |
#endif |
|
1641 |
|
|
1642 |
|
|
1581 | 1643 |
/*****************************************************************************/ |
1582 | 1644 |
/* Special registers manipulation */ |
1583 | 1645 |
#if defined(TARGET_PPC64) |
Also available in: Unified diff