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