]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/sparc64/kernel/sun4v_tlb_miss.S
[SPARC64]: Deal with PTE layout differences in SUN4V.
[linux-2.6-omap-h63xx.git] / arch / sparc64 / kernel / sun4v_tlb_miss.S
1 /* sun4v_tlb_miss.S: Sun4v TLB miss handlers.
2  *
3  * Copyright (C) 2006 <davem@davemloft.net>
4  */
5
6         .text
7         .align  32
8
9         /* Load ITLB fault information into VADDR and CTX, using BASE.  */
10 #define LOAD_ITLB_INFO(BASE, VADDR, CTX) \
11         ldx     [BASE + HV_FAULT_I_ADDR_OFFSET], VADDR; \
12         ldx     [BASE + HV_FAULT_I_CTX_OFFSET], CTX;
13
14         /* Load DTLB fault information into VADDR and CTX, using BASE.  */
15 #define LOAD_DTLB_INFO(BASE, VADDR, CTX) \
16         ldx     [BASE + HV_FAULT_D_ADDR_OFFSET], VADDR; \
17         ldx     [BASE + HV_FAULT_D_CTX_OFFSET], CTX;
18
19         /* DEST = (CTX << 48) | (VADDR >> 22)
20          *
21          * Branch to ZERO_CTX_LABEL is context is zero.
22          */
23 #define COMPUTE_TAG_TARGET(DEST, VADDR, CTX, TMP, ZERO_CTX_LABEL) \
24         srlx    VADDR, 22, TMP; \
25         sllx    CTX, 48, DEST; \
26         brz,pn  CTX, ZERO_CTX_LABEL; \
27          or     DEST, TMP, DEST;
28
29         /* Create TSB pointer.  This is something like:
30          *
31          * index_mask = (512 << (tsb_reg & 0x7UL)) - 1UL;
32          * tsb_base = tsb_reg & ~0x7UL;
33          * tsb_index = ((vaddr >> PAGE_SHIFT) & tsb_mask);
34          * tsb_ptr = tsb_base + (tsb_index * 16);
35          */
36 #define COMPUTE_TSB_PTR(TSB_PTR, VADDR, TMP1, TMP2)     \
37         and     TSB_PTR, 0x7, TMP1;                     \
38         mov     512, TMP2;                              \
39         andn    TSB_PTR, 0x7, TSB_PTR;                  \
40         sllx    TMP2, TMP1, TMP2;                       \
41         srlx    VADDR, PAGE_SHIFT, TMP1;                \
42         sub     TMP2, 1, TMP2;                          \
43         and     TMP1, TMP2, TMP1;                       \
44         sllx    TMP1, 4, TMP1;                          \
45         add     TSB_PTR, TMP1, TSB_PTR;
46
47 sun4v_itlb_miss:
48         /* Load MMU Miss base into %g2.  */
49         ldxa    [%g0] ASI_SCRATCHPAD, %g2
50         
51         /* Load UTSB reg into %g1.  */
52         mov     SCRATCHPAD_UTSBREG1, %g1
53         ldxa    [%g1] ASI_SCRATCHPAD, %g1
54
55         LOAD_ITLB_INFO(%g2, %g4, %g5)
56         COMPUTE_TAG_TARGET(%g6, %g4, %g5, %g3, kvmap_itlb_4v)
57         COMPUTE_TSB_PTR(%g1, %g4, %g3, %g7)
58
59         /* Load TSB tag/pte into %g2/%g3 and compare the tag.  */
60         ldda    [%g1] ASI_QUAD_LDD_PHYS, %g2
61         cmp     %g2, %g6
62         sethi   %hi(PAGE_EXEC), %g7
63         ldx     [%g7 + %lo(PAGE_EXEC)], %g7
64         bne,a,pn %xcc, tsb_miss_page_table_walk
65          mov    FAULT_CODE_ITLB, %g3
66         andcc   %g3, %g7, %g0
67         be,a,pn %xcc, tsb_do_fault
68          mov    FAULT_CODE_ITLB, %g3
69
70         /* We have a valid entry, make hypervisor call to load
71          * I-TLB and return from trap.
72          *
73          * %g3: PTE
74          * %g4: vaddr
75          * %g6: TAG TARGET (only "CTX << 48" part matters)
76          */
77 sun4v_itlb_load:
78         mov     %o0, %g1                ! save %o0
79         mov     %o1, %g2                ! save %o1
80         mov     %o2, %g5                ! save %o2
81         mov     %o3, %g7                ! save %o3
82         mov     %g4, %o0                ! vaddr
83         srlx    %g6, 48, %o1            ! ctx
84         mov     %g3, %o2                ! PTE
85         mov     HV_MMU_IMMU, %o3        ! flags
86         ta      HV_MMU_MAP_ADDR_TRAP
87         mov     %g1, %o0                ! restore %o0
88         mov     %g2, %o1                ! restore %o1
89         mov     %g5, %o2                ! restore %o2
90         mov     %g7, %o3                ! restore %o3
91
92         retry
93
94 sun4v_dtlb_miss:
95         /* Load MMU Miss base into %g2.  */
96         ldxa    [%g0] ASI_SCRATCHPAD, %g2
97         
98         /* Load UTSB reg into %g1.  */
99         mov     SCRATCHPAD_UTSBREG1, %g1
100         ldxa    [%g1] ASI_SCRATCHPAD, %g1
101
102         LOAD_DTLB_INFO(%g2, %g4, %g5)
103         COMPUTE_TAG_TARGET(%g6, %g4, %g5, %g3, kvmap_dtlb_4v)
104         COMPUTE_TSB_PTR(%g1, %g4, %g3, %g7)
105
106         /* Load TSB tag/pte into %g2/%g3 and compare the tag.  */
107         ldda    [%g1] ASI_QUAD_LDD_PHYS, %g2
108         cmp     %g2, %g6
109         bne,a,pn %xcc, tsb_miss_page_table_walk
110          mov    FAULT_CODE_ITLB, %g3
111
112         /* We have a valid entry, make hypervisor call to load
113          * D-TLB and return from trap.
114          *
115          * %g3: PTE
116          * %g4: vaddr
117          * %g6: TAG TARGET (only "CTX << 48" part matters)
118          */
119 sun4v_dtlb_load:
120         mov     %o0, %g1                ! save %o0
121         mov     %o1, %g2                ! save %o1
122         mov     %o2, %g5                ! save %o2
123         mov     %o3, %g7                ! save %o3
124         mov     %g4, %o0                ! vaddr
125         srlx    %g6, 48, %o1            ! ctx
126         mov     %g3, %o2                ! PTE
127         mov     HV_MMU_DMMU, %o3        ! flags
128         ta      HV_MMU_MAP_ADDR_TRAP
129         mov     %g1, %o0                ! restore %o0
130         mov     %g2, %o1                ! restore %o1
131         mov     %g5, %o2                ! restore %o2
132         mov     %g7, %o3                ! restore %o3
133
134         retry
135
136 sun4v_dtlb_prot:
137         /* Load MMU Miss base into %g2.  */
138         ldxa    [%g0] ASI_SCRATCHPAD, %g2
139         
140         ldx     [%g2 + HV_FAULT_D_ADDR_OFFSET], %g5
141         rdpr    %tl, %g1
142         cmp     %g1, 1
143         bgu,pn          %xcc, winfix_trampoline
144          nop
145         ba,pt           %xcc, sparc64_realfault_common
146          mov            FAULT_CODE_DTLB | FAULT_CODE_WRITE, %g4
147
148         /* Called from trap table with TAG TARGET placed into
149          * %g6, SCRATCHPAD_UTSBREG1 contents in %g1, and
150          * SCRATCHPAD_MMU_MISS contents in %g2.
151          */
152 sun4v_itsb_miss:
153         mov     SCRATCHPAD_UTSBREG1, %g1
154         ldxa    [%g1] ASI_SCRATCHPAD, %g1
155         brz,pn  %g5, kvmap_itlb_4v
156          mov    FAULT_CODE_ITLB, %g3
157
158         /* Called from trap table with TAG TARGET placed into
159          * %g6 and SCRATCHPAD_UTSBREG1 contents in %g1.
160          */
161 sun4v_dtsb_miss:
162         mov     SCRATCHPAD_UTSBREG1, %g1
163         ldxa    [%g1] ASI_SCRATCHPAD, %g1
164         brz,pn  %g5, kvmap_dtlb_4v
165          mov    FAULT_CODE_DTLB, %g3
166
167         /* Create TSB pointer into %g1.  This is something like:
168          *
169          * index_mask = (512 << (tsb_reg & 0x7UL)) - 1UL;
170          * tsb_base = tsb_reg & ~0x7UL;
171          * tsb_index = ((vaddr >> PAGE_SHIFT) & tsb_mask);
172          * tsb_ptr = tsb_base + (tsb_index * 16);
173          */
174 sun4v_tsb_miss_common:
175         COMPUTE_TSB_PTR(%g1, %g4, %g5, %g7)
176
177         /* Branch directly to page table lookup.  We have SCRATCHPAD_MMU_MISS
178          * still in %g2, so it's quite trivial to get at the PGD PHYS value
179          * so we can preload it into %g7.
180          */
181         sub     %g2, TRAP_PER_CPU_FAULT_INFO, %g2
182         ba,pt   %xcc, tsb_miss_page_table_walk_sun4v_fastpath
183          ldx    [%g2 + TRAP_PER_CPU_PGD_PADDR], %g7
184
185         /* Instruction Access Exception, tl0. */
186 sun4v_iacc:
187         ldxa    [%g0] ASI_SCRATCHPAD, %g2
188         ldx     [%g2 + HV_FAULT_I_TYPE_OFFSET], %g3
189         ldx     [%g2 + HV_FAULT_I_ADDR_OFFSET], %g4
190         ldx     [%g2 + HV_FAULT_I_CTX_OFFSET], %g5
191         sllx    %g3, 16, %g3
192         or      %g5, %g3, %g5
193         ba,pt   %xcc, etrap
194          rd     %pc, %g7
195         mov     %l4, %o1
196         mov     %l5, %o2
197         call    sun4v_insn_access_exception
198          add    %sp, PTREGS_OFF, %o0
199         ba,a,pt %xcc, rtrap_clr_l6
200
201         /* Instruction Access Exception, tl1. */
202 sun4v_iacc_tl1:
203         ldxa    [%g0] ASI_SCRATCHPAD, %g2
204         ldx     [%g2 + HV_FAULT_I_TYPE_OFFSET], %g3
205         ldx     [%g2 + HV_FAULT_I_ADDR_OFFSET], %g4
206         ldx     [%g2 + HV_FAULT_I_CTX_OFFSET], %g5
207         sllx    %g3, 16, %g3
208         or      %g5, %g3, %g5
209         ba,pt   %xcc, etraptl1
210          rd     %pc, %g7
211         mov     %l4, %o1
212         mov     %l5, %o2
213         call    sun4v_insn_access_exception_tl1
214          add    %sp, PTREGS_OFF, %o0
215         ba,a,pt %xcc, rtrap_clr_l6
216
217         /* Data Access Exception, tl0. */
218 sun4v_dacc:
219         ldxa    [%g0] ASI_SCRATCHPAD, %g2
220         ldx     [%g2 + HV_FAULT_D_TYPE_OFFSET], %g3
221         ldx     [%g2 + HV_FAULT_D_ADDR_OFFSET], %g4
222         ldx     [%g2 + HV_FAULT_D_CTX_OFFSET], %g5
223         sllx    %g3, 16, %g3
224         or      %g5, %g3, %g5
225         ba,pt   %xcc, etrap
226          rd     %pc, %g7
227         mov     %l4, %o1
228         mov     %l5, %o2
229         call    sun4v_data_access_exception
230          add    %sp, PTREGS_OFF, %o0
231         ba,a,pt %xcc, rtrap_clr_l6
232
233         /* Data Access Exception, tl1. */
234 sun4v_dacc_tl1:
235         ldxa    [%g0] ASI_SCRATCHPAD, %g2
236         ldx     [%g2 + HV_FAULT_D_TYPE_OFFSET], %g3
237         ldx     [%g2 + HV_FAULT_D_ADDR_OFFSET], %g4
238         ldx     [%g2 + HV_FAULT_D_CTX_OFFSET], %g5
239         sllx    %g3, 16, %g3
240         or      %g5, %g3, %g5
241         ba,pt   %xcc, etraptl1
242          rd     %pc, %g7
243         mov     %l4, %o1
244         mov     %l5, %o2
245         call    sun4v_data_access_exception_tl1
246          add    %sp, PTREGS_OFF, %o0
247         ba,a,pt %xcc, rtrap_clr_l6
248
249         /* Memory Address Unaligned.  */
250 sun4v_mna:
251         ldxa    [%g0] ASI_SCRATCHPAD, %g2
252         mov     HV_FAULT_TYPE_UNALIGNED, %g3
253         ldx     [%g2 + HV_FAULT_D_ADDR_OFFSET], %g4
254         ldx     [%g2 + HV_FAULT_D_CTX_OFFSET], %g5
255         sllx    %g3, 16, %g3
256         or      %g5, %g3, %g5
257
258         /* Window fixup? */
259         rdpr    %tl, %g2
260         cmp     %g2, 1
261         bgu,pn  %icc, winfix_mna
262          rdpr   %tpc, %g3
263
264         ba,pt   %xcc, etrap
265          rd     %pc, %g7
266         mov     %l4, %o1
267         mov     %l5, %o2
268         call    sun4v_mna
269          add    %sp, PTREGS_OFF, %o0
270         ba,a,pt %xcc, rtrap_clr_l6
271
272         /* Privileged Action.  */
273 sun4v_privact:
274         ba,pt   %xcc, etrap
275          rd     %pc, %g7
276         call    do_privact
277          add    %sp, PTREGS_OFF, %o0
278         ba,a,pt %xcc, rtrap_clr_l6
279
280         /* Unaligned ldd float, tl0. */
281 sun4v_lddfmna:
282         ldxa    [%g0] ASI_SCRATCHPAD, %g2
283         ldx     [%g2 + HV_FAULT_D_TYPE_OFFSET], %g3
284         ldx     [%g2 + HV_FAULT_D_ADDR_OFFSET], %g4
285         ldx     [%g2 + HV_FAULT_D_CTX_OFFSET], %g5
286         sllx    %g3, 16, %g3
287         or      %g5, %g3, %g5
288         ba,pt   %xcc, etrap
289          rd     %pc, %g7
290         mov     %l4, %o1
291         mov     %l5, %o2
292         call    handle_lddfmna
293          add    %sp, PTREGS_OFF, %o0
294         ba,a,pt %xcc, rtrap_clr_l6
295
296         /* Unaligned std float, tl0. */
297 sun4v_stdfmna:
298         ldxa    [%g0] ASI_SCRATCHPAD, %g2
299         ldx     [%g2 + HV_FAULT_D_TYPE_OFFSET], %g3
300         ldx     [%g2 + HV_FAULT_D_ADDR_OFFSET], %g4
301         ldx     [%g2 + HV_FAULT_D_CTX_OFFSET], %g5
302         sllx    %g3, 16, %g3
303         or      %g5, %g3, %g5
304         ba,pt   %xcc, etrap
305          rd     %pc, %g7
306         mov     %l4, %o1
307         mov     %l5, %o2
308         call    handle_stdfmna
309          add    %sp, PTREGS_OFF, %o0
310         ba,a,pt %xcc, rtrap_clr_l6
311
312 #define BRANCH_ALWAYS   0x10680000
313 #define NOP             0x01000000
314 #define SUN4V_DO_PATCH(OLD, NEW)        \
315         sethi   %hi(NEW), %g1; \
316         or      %g1, %lo(NEW), %g1; \
317         sethi   %hi(OLD), %g2; \
318         or      %g2, %lo(OLD), %g2; \
319         sub     %g1, %g2, %g1; \
320         sethi   %hi(BRANCH_ALWAYS), %g3; \
321         sll     %g1, 11, %g1; \
322         srl     %g1, 11 + 2, %g1; \
323         or      %g3, %lo(BRANCH_ALWAYS), %g3; \
324         or      %g3, %g1, %g3; \
325         stw     %g3, [%g2]; \
326         sethi   %hi(NOP), %g3; \
327         or      %g3, %lo(NOP), %g3; \
328         stw     %g3, [%g2 + 0x4]; \
329         flush   %g2;
330
331         .globl  sun4v_patch_tlb_handlers
332         .type   sun4v_patch_tlb_handlers,#function
333 sun4v_patch_tlb_handlers:
334         SUN4V_DO_PATCH(tl0_iamiss, sun4v_itlb_miss)
335         SUN4V_DO_PATCH(tl1_iamiss, sun4v_itlb_miss)
336         SUN4V_DO_PATCH(tl0_damiss, sun4v_dtlb_miss)
337         SUN4V_DO_PATCH(tl1_damiss, sun4v_dtlb_miss)
338         SUN4V_DO_PATCH(tl0_daprot, sun4v_dtlb_prot)
339         SUN4V_DO_PATCH(tl1_daprot, sun4v_dtlb_prot)
340         SUN4V_DO_PATCH(tl0_iax, sun4v_iacc)
341         SUN4V_DO_PATCH(tl1_iax, sun4v_iacc_tl1)
342         SUN4V_DO_PATCH(tl0_dax, sun4v_dacc)
343         SUN4V_DO_PATCH(tl1_dax, sun4v_dacc_tl1)
344         SUN4V_DO_PATCH(tl0_mna, sun4v_mna)
345         SUN4V_DO_PATCH(tl1_mna, sun4v_mna)
346         SUN4V_DO_PATCH(tl0_lddfmna, sun4v_lddfmna)
347         SUN4V_DO_PATCH(tl0_stdfmna, sun4v_stdfmna)
348         SUN4V_DO_PATCH(tl0_privact, sun4v_privact)
349         retl
350          nop
351         .size   sun4v_patch_tlb_handlers,.-sun4v_patch_tlb_handlers