diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/sparc64/kernel/dtlb_base.S |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/sparc64/kernel/dtlb_base.S')
-rw-r--r-- | arch/sparc64/kernel/dtlb_base.S | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/arch/sparc64/kernel/dtlb_base.S b/arch/sparc64/kernel/dtlb_base.S new file mode 100644 index 000000000000..ded2fed23fcc --- /dev/null +++ b/arch/sparc64/kernel/dtlb_base.S | |||
@@ -0,0 +1,113 @@ | |||
1 | /* $Id: dtlb_base.S,v 1.17 2001/10/11 22:33:52 davem Exp $ | ||
2 | * dtlb_base.S: Front end to DTLB miss replacement strategy. | ||
3 | * This is included directly into the trap table. | ||
4 | * | ||
5 | * Copyright (C) 1996,1998 David S. Miller (davem@redhat.com) | ||
6 | * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz) | ||
7 | */ | ||
8 | |||
9 | #include <asm/pgtable.h> | ||
10 | #include <asm/mmu.h> | ||
11 | |||
12 | /* %g1 TLB_SFSR (%g1 + %g1 == TLB_TAG_ACCESS) | ||
13 | * %g2 (KERN_HIGHBITS | KERN_LOWBITS) | ||
14 | * %g3 VPTE base (0xfffffffe00000000) Spitfire/Blackbird (44-bit VA space) | ||
15 | * (0xffe0000000000000) Cheetah (64-bit VA space) | ||
16 | * %g7 __pa(current->mm->pgd) | ||
17 | * | ||
18 | * The VPTE base value is completely magic, but note that | ||
19 | * few places in the kernel other than these TLB miss | ||
20 | * handlers know anything about the VPTE mechanism or | ||
21 | * how it works (see VPTE_SIZE, TASK_SIZE and PTRS_PER_PGD). | ||
22 | * Consider the 44-bit VADDR Ultra-I/II case as an example: | ||
23 | * | ||
24 | * VA[0 : (1<<43)] produce VPTE index [%g3 : 0] | ||
25 | * VA[0 : -(1<<43)] produce VPTE index [%g3-(1<<(43-PAGE_SHIFT+3)) : %g3] | ||
26 | * | ||
27 | * For Cheetah's 64-bit VADDR space this is: | ||
28 | * | ||
29 | * VA[0 : (1<<63)] produce VPTE index [%g3 : 0] | ||
30 | * VA[0 : -(1<<63)] produce VPTE index [%g3-(1<<(63-PAGE_SHIFT+3)) : %g3] | ||
31 | * | ||
32 | * If you're paying attention you'll notice that this means half of | ||
33 | * the VPTE table is above %g3 and half is below, low VA addresses | ||
34 | * map progressively upwards from %g3, and high VA addresses map | ||
35 | * progressively upwards towards %g3. This trick was needed to make | ||
36 | * the same 8 instruction handler work both for Spitfire/Blackbird's | ||
37 | * peculiar VA space hole configuration and the full 64-bit VA space | ||
38 | * one of Cheetah at the same time. | ||
39 | */ | ||
40 | |||
41 | /* Ways we can get here: | ||
42 | * | ||
43 | * 1) Nucleus loads and stores to/from PA-->VA direct mappings. | ||
44 | * 2) Nucleus loads and stores to/from vmalloc() areas. | ||
45 | * 3) User loads and stores. | ||
46 | * 4) User space accesses by nucleus at tl0 | ||
47 | */ | ||
48 | |||
49 | #if PAGE_SHIFT == 13 | ||
50 | /* | ||
51 | * To compute vpte offset, we need to do ((addr >> 13) << 3), | ||
52 | * which can be optimized to (addr >> 10) if bits 10/11/12 can | ||
53 | * be guaranteed to be 0 ... mmu_context.h does guarantee this | ||
54 | * by only using 10 bits in the hwcontext value. | ||
55 | */ | ||
56 | #define CREATE_VPTE_OFFSET1(r1, r2) | ||
57 | #define CREATE_VPTE_OFFSET2(r1, r2) \ | ||
58 | srax r1, 10, r2 | ||
59 | #define CREATE_VPTE_NOP nop | ||
60 | #else | ||
61 | #define CREATE_VPTE_OFFSET1(r1, r2) \ | ||
62 | srax r1, PAGE_SHIFT, r2 | ||
63 | #define CREATE_VPTE_OFFSET2(r1, r2) \ | ||
64 | sllx r2, 3, r2 | ||
65 | #define CREATE_VPTE_NOP | ||
66 | #endif | ||
67 | |||
68 | /* DTLB ** ICACHE line 1: Quick user TLB misses */ | ||
69 | ldxa [%g1 + %g1] ASI_DMMU, %g4 ! Get TAG_ACCESS | ||
70 | andcc %g4, TAG_CONTEXT_BITS, %g0 ! From Nucleus? | ||
71 | from_tl1_trap: | ||
72 | rdpr %tl, %g5 ! For TL==3 test | ||
73 | CREATE_VPTE_OFFSET1(%g4, %g6) ! Create VPTE offset | ||
74 | be,pn %xcc, 3f ! Yep, special processing | ||
75 | CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset | ||
76 | cmp %g5, 4 ! Last trap level? | ||
77 | be,pn %xcc, longpath ! Yep, cannot risk VPTE miss | ||
78 | nop ! delay slot | ||
79 | |||
80 | /* DTLB ** ICACHE line 2: User finish + quick kernel TLB misses */ | ||
81 | ldxa [%g3 + %g6] ASI_S, %g5 ! Load VPTE | ||
82 | 1: brgez,pn %g5, longpath ! Invalid, branch out | ||
83 | nop ! Delay-slot | ||
84 | 9: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB | ||
85 | retry ! Trap return | ||
86 | 3: brlz,pt %g4, 9b ! Kernel virtual map? | ||
87 | xor %g2, %g4, %g5 ! Finish bit twiddles | ||
88 | ba,a,pt %xcc, kvmap ! Yep, go check for obp/vmalloc | ||
89 | |||
90 | /* DTLB ** ICACHE line 3: winfixups+real_faults */ | ||
91 | longpath: | ||
92 | rdpr %pstate, %g5 ! Move into alternate globals | ||
93 | wrpr %g5, PSTATE_AG|PSTATE_MG, %pstate | ||
94 | rdpr %tl, %g4 ! See where we came from. | ||
95 | cmp %g4, 1 ! Is etrap/rtrap window fault? | ||
96 | mov TLB_TAG_ACCESS, %g4 ! Prepare for fault processing | ||
97 | ldxa [%g4] ASI_DMMU, %g5 ! Load faulting VA page | ||
98 | be,pt %xcc, sparc64_realfault_common ! Jump to normal fault handling | ||
99 | mov FAULT_CODE_DTLB, %g4 ! It was read from DTLB | ||
100 | |||
101 | /* DTLB ** ICACHE line 4: Unused... */ | ||
102 | ba,a,pt %xcc, winfix_trampoline ! Call window fixup code | ||
103 | nop | ||
104 | nop | ||
105 | nop | ||
106 | nop | ||
107 | nop | ||
108 | nop | ||
109 | CREATE_VPTE_NOP | ||
110 | |||
111 | #undef CREATE_VPTE_OFFSET1 | ||
112 | #undef CREATE_VPTE_OFFSET2 | ||
113 | #undef CREATE_VPTE_NOP | ||