diff options
Diffstat (limited to 'arch/sparc64/kernel/dtlb_backend.S')
-rw-r--r-- | arch/sparc64/kernel/dtlb_backend.S | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/arch/sparc64/kernel/dtlb_backend.S b/arch/sparc64/kernel/dtlb_backend.S new file mode 100644 index 000000000..b3d0a1eb7 --- /dev/null +++ b/arch/sparc64/kernel/dtlb_backend.S @@ -0,0 +1,69 @@ +/* $Id: dtlb_backend.S,v 1.4 1998/06/15 16:59:34 jj Exp $ + * dtlb_backend.S: Back end to DTLB miss replacement strategy. + * This is included directly into the trap table. + * + * Copyright (C) 1996,1998 David S. Miller (davem@dm.cobaltmicro.com) + * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz) + */ + +#define TAG_CONTEXT_BITS 0x3ff +#define VPTE_SHIFT (PAGE_SHIFT - 3) +#define PMD_SHIFT (23 - PAGE_SHIFT + 3) +#define PGD_SHIFT (34 - PAGE_SHIFT + 3) +#define VPTE_BITS (_PAGE_CP | _PAGE_P | _PAGE_W) + +/* Ways we can get here: + * + * 1) Nucleus loads and stores to/from PA-->VA direct mappings at tl>1. + * 2) Nucleus loads and stores to/from user/kernel window save areas. + * 3) VPTE misses from dtlb_base, dtlb_prot, and itlb_base. But this only + * happens for non-nucleus contexts. Nucleus VPTE's cannot work because + * of how OBP uses the same part of the address space in ctx 0. + */ + +/* TLB1 ** ICACHE line 1: tl1 DTLB and quick VPTE miss */ + ldxa [%g1 + %g1] ASI_DMMU, %g4 ! Get TAG_ACCESS + add %g3, %g3, %g5 ! Compute VPTE base + cmp %g4, %g5 ! VPTE miss? + blu,pn %xcc, .-0x4004 ! Fall to tl0 miss + andcc %g4, TAG_CONTEXT_BITS, %g5 ! From Nucleus? (for tl0 miss) + sllx %g6, VPTE_SHIFT, %g4 ! Position TAG_ACCESS + or %g4, %g5, %g4 ! Prepare TAG_ACCESS + mov TSB_REG, %g1 ! Grab TSB reg + +/* TLB1 ** ICACHE line 2: Quick VPTE miss */ + ldxa [%g1] ASI_DMMU, %g5 ! Doing PGD caching? + srlx %g6, (PMD_SHIFT - 1), %g1 ! Position PMD offset + be,pn %xcc, sparc64_vpte_nucleus ! Is it from Nucleus? + and %g1, 0xffe, %g1 ! Mask PMD offset bits + brnz,pt %g5, sparc64_vpte_continue ! Yep, go like smoke + nop ! Pipe bubble... + srlx %g6, (PGD_SHIFT - 2), %g5 ! Position PGD offset + and %g5, 0xffc, %g5 ! Mask PGD offset + +/* TLB1 ** ICACHE line 3: Quick VPTE miss */ + lduwa [%g7 + %g5] ASI_PHYS_USE_EC, %g5! Load PGD + brz,pn %g5, 2f ! Valid? +sparc64_vpte_continue: + add %g1, %g1, %g1 ! Position PMD offset once again + lduwa [%g5 + %g1] ASI_PHYS_USE_EC, %g5! Load PMD + brz,pn %g5, 2f ! Valid? + sllx %g2, 62, %g1 ! Put _PAGE_VALID into %g1 + or %g5, VPTE_BITS, %g5 ! Prepare VPTE data + or %g5, %g1, %g5 ! ... + +/* TLB1 ** ICACHE line 4: Quick VPTE miss */ + mov TLB_SFSR, %g1 ! Restore %g1 value + stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Load VPTE into TLB + membar #Sync ! Synchronize ASI stores + stxa %g4, [%g1 + %g1] ASI_DMMU ! Restore previous TAG_ACCESS + retry ! Load PTE once again +2: mov TLB_SFSR, %g1 ! Restore %g1 value + stxa %g4, [%g1 + %g1] ASI_DMMU ! Restore previous TAG_ACCESS + done ! Slick trick + +#undef TAG_CONTEXT_BITS +#undef VPTE_SHIFT +#undef PMD_SHIFT +#undef PGD_SHIFT +#undef VPTE_BITS |