Commit | Line | Data |
---|---|---|
74bf4312 DM |
1 | /* tsb.S: Sparc64 TSB table handling. |
2 | * | |
3 | * Copyright (C) 2006 David S. Miller <davem@davemloft.net> | |
4 | */ | |
5 | ||
6 | #include <asm/tsb.h> | |
7 | ||
8 | .text | |
9 | .align 32 | |
10 | ||
11 | /* Invoked from TLB miss handler, we are in the | |
12 | * MMU global registers and they are setup like | |
13 | * this: | |
14 | * | |
15 | * %g1: TSB entry pointer | |
16 | * %g2: available temporary | |
17 | * %g3: FAULT_CODE_{D,I}TLB | |
18 | * %g4: available temporary | |
19 | * %g5: available temporary | |
20 | * %g6: TAG TARGET | |
21 | * %g7: physical address base of the linux page | |
22 | * tables for the current address space | |
23 | */ | |
24 | .globl tsb_miss_dtlb | |
25 | tsb_miss_dtlb: | |
26 | mov TLB_TAG_ACCESS, %g4 | |
27 | ldxa [%g4] ASI_DMMU, %g4 | |
28 | ba,pt %xcc, tsb_miss_page_table_walk | |
29 | nop | |
30 | ||
31 | .globl tsb_miss_itlb | |
32 | tsb_miss_itlb: | |
33 | mov TLB_TAG_ACCESS, %g4 | |
34 | ldxa [%g4] ASI_IMMU, %g4 | |
35 | ba,pt %xcc, tsb_miss_page_table_walk | |
36 | nop | |
37 | ||
38 | tsb_miss_page_table_walk: | |
39 | USER_PGTABLE_WALK_TL1(%g4, %g7, %g5, %g2, tsb_do_fault) | |
40 | ||
41 | tsb_reload: | |
42 | TSB_LOCK_TAG(%g1, %g2, %g4) | |
43 | ||
44 | /* Load and check PTE. */ | |
45 | ldxa [%g5] ASI_PHYS_USE_EC, %g5 | |
46 | brgez,a,pn %g5, tsb_do_fault | |
47 | stx %g0, [%g1] | |
48 | ||
49 | TSB_WRITE(%g1, %g5, %g6) | |
50 | ||
51 | /* Finally, load TLB and return from trap. */ | |
52 | tsb_tlb_reload: | |
53 | cmp %g3, FAULT_CODE_DTLB | |
54 | bne,pn %xcc, tsb_itlb_load | |
55 | nop | |
56 | ||
57 | tsb_dtlb_load: | |
58 | stxa %g5, [%g0] ASI_DTLB_DATA_IN | |
59 | retry | |
60 | ||
61 | tsb_itlb_load: | |
62 | stxa %g5, [%g0] ASI_ITLB_DATA_IN | |
63 | retry | |
64 | ||
65 | /* No valid entry in the page tables, do full fault | |
66 | * processing. | |
67 | */ | |
68 | ||
69 | .globl tsb_do_fault | |
70 | tsb_do_fault: | |
71 | cmp %g3, FAULT_CODE_DTLB | |
72 | rdpr %pstate, %g5 | |
73 | bne,pn %xcc, tsb_do_itlb_fault | |
74 | wrpr %g5, PSTATE_AG | PSTATE_MG, %pstate | |
75 | ||
76 | tsb_do_dtlb_fault: | |
77 | rdpr %tl, %g4 | |
78 | cmp %g4, 1 | |
79 | mov TLB_TAG_ACCESS, %g4 | |
80 | ldxa [%g4] ASI_DMMU, %g5 | |
81 | be,pt %xcc, sparc64_realfault_common | |
82 | mov FAULT_CODE_DTLB, %g4 | |
83 | ba,pt %xcc, winfix_trampoline | |
84 | nop | |
85 | ||
86 | tsb_do_itlb_fault: | |
87 | rdpr %tpc, %g5 | |
88 | ba,pt %xcc, sparc64_realfault_common | |
89 | mov FAULT_CODE_ITLB, %g4 | |
90 | ||
91 | .globl sparc64_realfault_common | |
92 | sparc64_realfault_common: | |
93 | stb %g4, [%g6 + TI_FAULT_CODE] ! Save fault code | |
94 | stx %g5, [%g6 + TI_FAULT_ADDR] ! Save fault address | |
95 | ba,pt %xcc, etrap ! Save trap state | |
96 | 1: rd %pc, %g7 ! ... | |
97 | call do_sparc64_fault ! Call fault handler | |
98 | add %sp, PTREGS_OFF, %o0 ! Compute pt_regs arg | |
99 | ba,pt %xcc, rtrap_clr_l6 ! Restore cpu state | |
100 | nop ! Delay slot (fill me) | |
101 | ||
102 | .globl winfix_trampoline | |
103 | winfix_trampoline: | |
104 | rdpr %tpc, %g3 ! Prepare winfixup TNPC | |
105 | or %g3, 0x7c, %g3 ! Compute branch offset | |
106 | wrpr %g3, %tnpc ! Write it into TNPC | |
107 | done ! Trap return | |
108 | ||
109 | /* Reload MMU related context switch state at | |
110 | * schedule() time. | |
111 | * | |
112 | * %o0: page table physical address | |
113 | * %o1: TSB address | |
114 | */ | |
115 | .globl tsb_context_switch | |
116 | tsb_context_switch: | |
117 | wrpr %g0, PSTATE_MG | PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV, %pstate | |
118 | ||
119 | /* Set page table base alternate global. */ | |
120 | mov %o0, %g7 | |
121 | ||
122 | /* XXX can this happen? */ | |
123 | brz,pn %o1, 9f | |
124 | nop | |
125 | ||
126 | /* Lock TSB into D-TLB. */ | |
127 | sethi %hi(PAGE_SIZE), %o3 | |
128 | and %o3, %o1, %o3 | |
129 | sethi %hi(TSBMAP_BASE), %o2 | |
130 | add %o2, %o3, %o2 | |
131 | ||
132 | /* XXX handle PAGE_SIZE != 8K correctly... */ | |
133 | mov TSB_REG, %g1 | |
134 | stxa %o2, [%g1] ASI_DMMU | |
135 | membar #Sync | |
136 | ||
137 | stxa %o2, [%g1] ASI_IMMU | |
138 | membar #Sync | |
139 | ||
140 | #define KERN_HIGHBITS ((_PAGE_VALID|_PAGE_SZBITS)^0xfffff80000000000) | |
141 | #define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W | _PAGE_L) | |
142 | sethi %uhi(KERN_HIGHBITS), %g2 | |
143 | or %g2, %ulo(KERN_HIGHBITS), %g2 | |
144 | sllx %g2, 32, %g2 | |
145 | or %g2, KERN_LOWBITS, %g2 | |
146 | #undef KERN_HIGHBITS | |
147 | #undef KERN_LOWBITS | |
148 | ||
149 | xor %o1, %g2, %o1 | |
150 | ||
151 | /* We use entry 61 for this locked entry. This is the spitfire | |
152 | * TLB entry number, and luckily cheetah masks the value with | |
153 | * 15 ending us up with entry 13 which is what we want in that | |
154 | * case too. | |
155 | * | |
156 | * XXX Interactions with prom_world()... | |
157 | */ | |
158 | mov TLB_TAG_ACCESS, %g1 | |
159 | stxa %o2, [%g1] ASI_DMMU | |
160 | membar #Sync | |
161 | mov (61 << 3), %g1 | |
162 | stxa %o1, [%g1] ASI_DTLB_DATA_ACCESS | |
163 | membar #Sync | |
164 | ||
165 | 9: | |
166 | wrpr %g0, PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE, %pstate | |
167 | ||
168 | retl | |
169 | mov %o2, %o0 |