[PATCH] ppc64: Make eeh_init function again
[linux-2.6] / arch / frv / mm / tlb-miss.S
1 /* tlb-miss.S: TLB miss handlers
2  *
3  * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version
9  * 2 of the License, or (at your option) any later version.
10  */
11
12 #include <linux/sys.h>
13 #include <linux/config.h>
14 #include <linux/linkage.h>
15 #include <asm/page.h>
16 #include <asm/pgtable.h>
17 #include <asm/highmem.h>
18 #include <asm/spr-regs.h>
19
20         .section        .text
21         .balign         4
22
23         .globl          __entry_insn_mmu_miss
24 __entry_insn_mmu_miss:
25         break
26         nop
27
28         .globl          __entry_insn_mmu_exception
29 __entry_insn_mmu_exception:
30         break
31         nop
32
33         .globl          __entry_data_mmu_miss
34 __entry_data_mmu_miss:
35         break
36         nop
37
38         .globl          __entry_data_mmu_exception
39 __entry_data_mmu_exception:
40         break
41         nop
42
43 ###############################################################################
44 #
45 # handle a lookup failure of one sort or another in a kernel TLB handler
46 # On entry:
47 #   GR29 - faulting address
48 #   SCR2 - saved CCR
49 #
50 ###############################################################################
51         .type           __tlb_kernel_fault,@function
52 __tlb_kernel_fault:
53         # see if we're supposed to re-enable single-step mode upon return
54         sethi.p         %hi(__break_tlb_miss_return_break),gr30
55         setlo           %lo(__break_tlb_miss_return_break),gr30
56         movsg           pcsr,gr31
57
58         subcc           gr31,gr30,gr0,icc0
59         beq             icc0,#0,__tlb_kernel_fault_sstep
60
61         movsg           scr2,gr30
62         movgs           gr30,ccr
63         movgs           gr29,scr2                       /* save EAR0 value */
64         sethi.p         %hi(__kernel_current_task),gr29
65         setlo           %lo(__kernel_current_task),gr29
66         ldi.p           @(gr29,#0),gr29                 /* restore GR29 */
67
68         bra             __entry_kernel_handle_mmu_fault
69
70         # we've got to re-enable single-stepping
71 __tlb_kernel_fault_sstep:
72         sethi.p         %hi(__break_tlb_miss_real_return_info),gr30
73         setlo           %lo(__break_tlb_miss_real_return_info),gr30
74         lddi            @(gr30,0),gr30
75         movgs           gr30,pcsr
76         movgs           gr31,psr
77
78         movsg           scr2,gr30
79         movgs           gr30,ccr
80         movgs           gr29,scr2                       /* save EAR0 value */
81         sethi.p         %hi(__kernel_current_task),gr29
82         setlo           %lo(__kernel_current_task),gr29
83         ldi.p           @(gr29,#0),gr29                 /* restore GR29 */
84         bra             __entry_kernel_handle_mmu_fault_sstep
85
86         .size           __tlb_kernel_fault, .-__tlb_kernel_fault
87
88 ###############################################################################
89 #
90 # handle a lookup failure of one sort or another in a user TLB handler
91 # On entry:
92 #   GR28 - faulting address
93 #   SCR2 - saved CCR
94 #
95 ###############################################################################
96         .type           __tlb_user_fault,@function
97 __tlb_user_fault:
98         # see if we're supposed to re-enable single-step mode upon return
99         sethi.p         %hi(__break_tlb_miss_return_break),gr30
100         setlo           %lo(__break_tlb_miss_return_break),gr30
101         movsg           pcsr,gr31
102         subcc           gr31,gr30,gr0,icc0
103         beq             icc0,#0,__tlb_user_fault_sstep
104
105         movsg           scr2,gr30
106         movgs           gr30,ccr
107         bra             __entry_uspace_handle_mmu_fault
108
109         # we've got to re-enable single-stepping
110 __tlb_user_fault_sstep:
111         sethi.p         %hi(__break_tlb_miss_real_return_info),gr30
112         setlo           %lo(__break_tlb_miss_real_return_info),gr30
113         lddi            @(gr30,0),gr30
114         movgs           gr30,pcsr
115         movgs           gr31,psr
116         movsg           scr2,gr30
117         movgs           gr30,ccr
118         bra             __entry_uspace_handle_mmu_fault_sstep
119
120         .size           __tlb_user_fault, .-__tlb_user_fault
121
122 ###############################################################################
123 #
124 # Kernel instruction TLB miss handler
125 # On entry:
126 #   GR1   - kernel stack pointer
127 #   GR28  - saved exception frame pointer
128 #   GR29  - faulting address
129 #   GR31  - EAR0 ^ SCR0
130 #   SCR0  - base of virtual range covered by cached PGE from last ITLB miss (or 0xffffffff)
131 #   DAMR3 - mapped page directory
132 #   DAMR4 - mapped page table as matched by SCR0
133 #
134 ###############################################################################
135         .globl          __entry_kernel_insn_tlb_miss
136         .type           __entry_kernel_insn_tlb_miss,@function
137 __entry_kernel_insn_tlb_miss:
138 #if 0
139         sethi.p         %hi(0xe1200004),gr30
140         setlo           %lo(0xe1200004),gr30
141         st              gr0,@(gr30,gr0)
142         sethi.p         %hi(0xffc00100),gr30
143         setlo           %lo(0xffc00100),gr30
144         sth             gr30,@(gr30,gr0)
145         membar
146 #endif
147
148         movsg           ccr,gr30                        /* save CCR */
149         movgs           gr30,scr2
150
151         # see if the cached page table mapping is appropriate
152         srlicc.p        gr31,#26,gr0,icc0
153         setlos          0x3ffc,gr30
154         srli.p          gr29,#12,gr31                   /* use EAR0[25:14] as PTE index */
155         bne             icc0,#0,__itlb_k_PTD_miss
156
157 __itlb_k_PTD_mapped:
158         # access the PTD with EAR0[25:14]
159         # - DAMLR4 points to the virtual address of the appropriate page table
160         # - the PTD holds 4096 PTEs
161         # - the PTD must be accessed uncached
162         # - the PTE must be marked accessed if it was valid
163         #
164         and             gr31,gr30,gr31
165         movsg           damlr4,gr30
166         add             gr30,gr31,gr31
167         ldi             @(gr31,#0),gr30                 /* fetch the PTE */
168         andicc          gr30,#_PAGE_PRESENT,gr0,icc0
169         ori.p           gr30,#_PAGE_ACCESSED,gr30
170         beq             icc0,#0,__tlb_kernel_fault      /* jump if PTE invalid */
171         sti.p           gr30,@(gr31,#0)                 /* update the PTE */
172         andi            gr30,#~_PAGE_ACCESSED,gr30
173
174         # we're using IAMR1 as an extra TLB entry
175         # - punt the entry here (if valid) to the real TLB and then replace with the new PTE
176         # - need to check DAMR1 lest we cause an multiple-DAT-hit exception
177         # - IAMPR1 has no WP bit, and we mustn't lose WP information
178         movsg           iampr1,gr31
179         andicc          gr31,#xAMPRx_V,gr0,icc0
180         setlos.p        0xfffff000,gr31
181         beq             icc0,#0,__itlb_k_nopunt         /* punt not required */
182
183         movsg           iamlr1,gr31
184         movgs           gr31,tplr                       /* set TPLR.CXN */
185         tlbpr           gr31,gr0,#4,#0                  /* delete matches from TLB, IAMR1, DAMR1 */
186
187         movsg           dampr1,gr31
188         ori             gr31,#xAMPRx_V,gr31             /* entry was invalidated by tlbpr #4 */
189         movgs           gr31,tppr
190         movsg           iamlr1,gr31                     /* set TPLR.CXN */
191         movgs           gr31,tplr
192         tlbpr           gr31,gr0,#2,#0                  /* save to the TLB */
193         movsg           tpxr,gr31                       /* check the TLB write error flag */
194         andicc.p        gr31,#TPXR_E,gr0,icc0
195         setlos          #0xfffff000,gr31
196         bne             icc0,#0,__tlb_kernel_fault
197
198 __itlb_k_nopunt:
199
200         # assemble the new TLB entry
201         and             gr29,gr31,gr29
202         movsg           cxnr,gr31
203         or              gr29,gr31,gr29
204         movgs           gr29,iamlr1                     /* xAMLR = address | context number */
205         movgs           gr30,iampr1
206         movgs           gr29,damlr1
207         movgs           gr30,dampr1
208
209         # return, restoring registers
210         movsg           scr2,gr30
211         movgs           gr30,ccr
212         sethi.p         %hi(__kernel_current_task),gr29
213         setlo           %lo(__kernel_current_task),gr29
214         ldi             @(gr29,#0),gr29
215         rett            #0
216         beq             icc0,#3,0                       /* prevent icache prefetch */
217
218         # the PTE we want wasn't in the PTD we have mapped, so we need to go looking for a more
219         # appropriate page table and map that instead
220         #   - access the PGD with EAR0[31:26]
221         #   - DAMLR3 points to the virtual address of the page directory
222         #   - the PGD holds 64 PGEs and each PGE/PME points to a set of page tables
223 __itlb_k_PTD_miss:
224         srli            gr29,#26,gr31                   /* calculate PGE offset */
225         slli            gr31,#8,gr31                    /* and clear bottom bits */
226
227         movsg           damlr3,gr30
228         ld              @(gr31,gr30),gr30               /* access the PGE */
229
230         andicc.p        gr30,#_PAGE_PRESENT,gr0,icc0
231         andicc          gr30,#xAMPRx_SS,gr0,icc1
232
233         # map this PTD instead and record coverage address
234         ori.p           gr30,#xAMPRx_L|xAMPRx_SS_16Kb|xAMPRx_S|xAMPRx_C|xAMPRx_V,gr30
235         beq             icc0,#0,__tlb_kernel_fault      /* jump if PGE not present */
236         slli.p          gr31,#18,gr31
237         bne             icc1,#0,__itlb_k_bigpage
238         movgs           gr30,dampr4
239         movgs           gr31,scr0
240
241         # we can now resume normal service
242         setlos          0x3ffc,gr30
243         srli.p          gr29,#12,gr31                   /* use EAR0[25:14] as PTE index */
244         bra             __itlb_k_PTD_mapped
245
246 __itlb_k_bigpage:
247         break
248         nop
249
250         .size           __entry_kernel_insn_tlb_miss, .-__entry_kernel_insn_tlb_miss
251
252 ###############################################################################
253 #
254 # Kernel data TLB miss handler
255 # On entry:
256 #   GR1   - kernel stack pointer
257 #   GR28  - saved exception frame pointer
258 #   GR29  - faulting address
259 #   GR31  - EAR0 ^ SCR1
260 #   SCR1  - base of virtual range covered by cached PGE from last DTLB miss (or 0xffffffff)
261 #   DAMR3 - mapped page directory
262 #   DAMR5 - mapped page table as matched by SCR1
263 #
264 ###############################################################################
265         .globl          __entry_kernel_data_tlb_miss
266         .type           __entry_kernel_data_tlb_miss,@function
267 __entry_kernel_data_tlb_miss:
268 #if 0
269         sethi.p         %hi(0xe1200004),gr30
270         setlo           %lo(0xe1200004),gr30
271         st              gr0,@(gr30,gr0)
272         sethi.p         %hi(0xffc00100),gr30
273         setlo           %lo(0xffc00100),gr30
274         sth             gr30,@(gr30,gr0)
275         membar
276 #endif
277
278         movsg           ccr,gr30                        /* save CCR */
279         movgs           gr30,scr2
280
281         # see if the cached page table mapping is appropriate
282         srlicc.p        gr31,#26,gr0,icc0
283         setlos          0x3ffc,gr30
284         srli.p          gr29,#12,gr31                   /* use EAR0[25:14] as PTE index */
285         bne             icc0,#0,__dtlb_k_PTD_miss
286
287 __dtlb_k_PTD_mapped:
288         # access the PTD with EAR0[25:14]
289         # - DAMLR5 points to the virtual address of the appropriate page table
290         # - the PTD holds 4096 PTEs
291         # - the PTD must be accessed uncached
292         # - the PTE must be marked accessed if it was valid
293         #
294         and             gr31,gr30,gr31
295         movsg           damlr5,gr30
296         add             gr30,gr31,gr31
297         ldi             @(gr31,#0),gr30                 /* fetch the PTE */
298         andicc          gr30,#_PAGE_PRESENT,gr0,icc0
299         ori.p           gr30,#_PAGE_ACCESSED,gr30
300         beq             icc0,#0,__tlb_kernel_fault      /* jump if PTE invalid */
301         sti.p           gr30,@(gr31,#0)                 /* update the PTE */
302         andi            gr30,#~_PAGE_ACCESSED,gr30
303
304         # we're using DAMR1 as an extra TLB entry
305         # - punt the entry here (if valid) to the real TLB and then replace with the new PTE
306         # - need to check IAMR1 lest we cause an multiple-DAT-hit exception
307         movsg           dampr1,gr31
308         andicc          gr31,#xAMPRx_V,gr0,icc0
309         setlos.p        0xfffff000,gr31
310         beq             icc0,#0,__dtlb_k_nopunt         /* punt not required */
311
312         movsg           damlr1,gr31
313         movgs           gr31,tplr                       /* set TPLR.CXN */
314         tlbpr           gr31,gr0,#4,#0                  /* delete matches from TLB, IAMR1, DAMR1 */
315
316         movsg           dampr1,gr31
317         ori             gr31,#xAMPRx_V,gr31             /* entry was invalidated by tlbpr #4 */
318         movgs           gr31,tppr
319         movsg           damlr1,gr31                     /* set TPLR.CXN */
320         movgs           gr31,tplr
321         tlbpr           gr31,gr0,#2,#0                  /* save to the TLB */
322         movsg           tpxr,gr31                       /* check the TLB write error flag */
323         andicc.p        gr31,#TPXR_E,gr0,icc0
324         setlos          #0xfffff000,gr31
325         bne             icc0,#0,__tlb_kernel_fault
326
327 __dtlb_k_nopunt:
328
329         # assemble the new TLB entry
330         and             gr29,gr31,gr29
331         movsg           cxnr,gr31
332         or              gr29,gr31,gr29
333         movgs           gr29,iamlr1                     /* xAMLR = address | context number */
334         movgs           gr30,iampr1
335         movgs           gr29,damlr1
336         movgs           gr30,dampr1
337
338         # return, restoring registers
339         movsg           scr2,gr30
340         movgs           gr30,ccr
341         sethi.p         %hi(__kernel_current_task),gr29
342         setlo           %lo(__kernel_current_task),gr29
343         ldi             @(gr29,#0),gr29
344         rett            #0
345         beq             icc0,#3,0                       /* prevent icache prefetch */
346
347         # the PTE we want wasn't in the PTD we have mapped, so we need to go looking for a more
348         # appropriate page table and map that instead
349         #   - access the PGD with EAR0[31:26]
350         #   - DAMLR3 points to the virtual address of the page directory
351         #   - the PGD holds 64 PGEs and each PGE/PME points to a set of page tables
352 __dtlb_k_PTD_miss:
353         srli            gr29,#26,gr31                   /* calculate PGE offset */
354         slli            gr31,#8,gr31                    /* and clear bottom bits */
355
356         movsg           damlr3,gr30
357         ld              @(gr31,gr30),gr30               /* access the PGE */
358
359         andicc.p        gr30,#_PAGE_PRESENT,gr0,icc0
360         andicc          gr30,#xAMPRx_SS,gr0,icc1
361
362         # map this PTD instead and record coverage address
363         ori.p           gr30,#xAMPRx_L|xAMPRx_SS_16Kb|xAMPRx_S|xAMPRx_C|xAMPRx_V,gr30
364         beq             icc0,#0,__tlb_kernel_fault      /* jump if PGE not present */
365         slli.p          gr31,#18,gr31
366         bne             icc1,#0,__dtlb_k_bigpage
367         movgs           gr30,dampr5
368         movgs           gr31,scr1
369
370         # we can now resume normal service
371         setlos          0x3ffc,gr30
372         srli.p          gr29,#12,gr31                   /* use EAR0[25:14] as PTE index */
373         bra             __dtlb_k_PTD_mapped
374
375 __dtlb_k_bigpage:
376         break
377         nop
378
379         .size           __entry_kernel_data_tlb_miss, .-__entry_kernel_data_tlb_miss
380
381 ###############################################################################
382 #
383 # Userspace instruction TLB miss handler (with PGE prediction)
384 # On entry:
385 #   GR28  - faulting address
386 #   GR31  - EAR0 ^ SCR0
387 #   SCR0  - base of virtual range covered by cached PGE from last ITLB miss (or 0xffffffff)
388 #   DAMR3 - mapped page directory
389 #   DAMR4 - mapped page table as matched by SCR0
390 #
391 ###############################################################################
392         .globl          __entry_user_insn_tlb_miss
393         .type           __entry_user_insn_tlb_miss,@function
394 __entry_user_insn_tlb_miss:
395 #if 0
396         sethi.p         %hi(0xe1200004),gr30
397         setlo           %lo(0xe1200004),gr30
398         st              gr0,@(gr30,gr0)
399         sethi.p         %hi(0xffc00100),gr30
400         setlo           %lo(0xffc00100),gr30
401         sth             gr30,@(gr30,gr0)
402         membar
403 #endif
404
405         movsg           ccr,gr30                        /* save CCR */
406         movgs           gr30,scr2
407
408         # see if the cached page table mapping is appropriate
409         srlicc.p        gr31,#26,gr0,icc0
410         setlos          0x3ffc,gr30
411         srli.p          gr28,#12,gr31                   /* use EAR0[25:14] as PTE index */
412         bne             icc0,#0,__itlb_u_PTD_miss
413
414 __itlb_u_PTD_mapped:
415         # access the PTD with EAR0[25:14]
416         # - DAMLR4 points to the virtual address of the appropriate page table
417         # - the PTD holds 4096 PTEs
418         # - the PTD must be accessed uncached
419         # - the PTE must be marked accessed if it was valid
420         #
421         and             gr31,gr30,gr31
422         movsg           damlr4,gr30
423         add             gr30,gr31,gr31
424         ldi             @(gr31,#0),gr30                 /* fetch the PTE */
425         andicc          gr30,#_PAGE_PRESENT,gr0,icc0
426         ori.p           gr30,#_PAGE_ACCESSED,gr30
427         beq             icc0,#0,__tlb_user_fault        /* jump if PTE invalid */
428         sti.p           gr30,@(gr31,#0)                 /* update the PTE */
429         andi            gr30,#~_PAGE_ACCESSED,gr30
430
431         # we're using IAMR1/DAMR1 as an extra TLB entry
432         # - punt the entry here (if valid) to the real TLB and then replace with the new PTE
433         movsg           dampr1,gr31
434         andicc          gr31,#xAMPRx_V,gr0,icc0
435         setlos.p        0xfffff000,gr31
436         beq             icc0,#0,__itlb_u_nopunt         /* punt not required */
437
438         movsg           dampr1,gr31
439         movgs           gr31,tppr
440         movsg           damlr1,gr31                     /* set TPLR.CXN */
441         movgs           gr31,tplr
442         tlbpr           gr31,gr0,#2,#0                  /* save to the TLB */
443         movsg           tpxr,gr31                       /* check the TLB write error flag */
444         andicc.p        gr31,#TPXR_E,gr0,icc0
445         setlos          #0xfffff000,gr31
446         bne             icc0,#0,__tlb_user_fault
447
448 __itlb_u_nopunt:
449
450         # assemble the new TLB entry
451         and             gr28,gr31,gr28
452         movsg           cxnr,gr31
453         or              gr28,gr31,gr28
454         movgs           gr28,iamlr1                     /* xAMLR = address | context number */
455         movgs           gr30,iampr1
456         movgs           gr28,damlr1
457         movgs           gr30,dampr1
458
459         # return, restoring registers
460         movsg           scr2,gr30
461         movgs           gr30,ccr
462         rett            #0
463         beq             icc0,#3,0                       /* prevent icache prefetch */
464
465         # the PTE we want wasn't in the PTD we have mapped, so we need to go looking for a more
466         # appropriate page table and map that instead
467         #   - access the PGD with EAR0[31:26]
468         #   - DAMLR3 points to the virtual address of the page directory
469         #   - the PGD holds 64 PGEs and each PGE/PME points to a set of page tables
470 __itlb_u_PTD_miss:
471         srli            gr28,#26,gr31                   /* calculate PGE offset */
472         slli            gr31,#8,gr31                    /* and clear bottom bits */
473
474         movsg           damlr3,gr30
475         ld              @(gr31,gr30),gr30               /* access the PGE */
476
477         andicc.p        gr30,#_PAGE_PRESENT,gr0,icc0
478         andicc          gr30,#xAMPRx_SS,gr0,icc1
479
480         # map this PTD instead and record coverage address
481         ori.p           gr30,#xAMPRx_L|xAMPRx_SS_16Kb|xAMPRx_S|xAMPRx_C|xAMPRx_V,gr30
482         beq             icc0,#0,__tlb_user_fault        /* jump if PGE not present */
483         slli.p          gr31,#18,gr31
484         bne             icc1,#0,__itlb_u_bigpage
485         movgs           gr30,dampr4
486         movgs           gr31,scr0
487
488         # we can now resume normal service
489         setlos          0x3ffc,gr30
490         srli.p          gr28,#12,gr31                   /* use EAR0[25:14] as PTE index */
491         bra             __itlb_u_PTD_mapped
492
493 __itlb_u_bigpage:
494         break
495         nop
496
497         .size           __entry_user_insn_tlb_miss, .-__entry_user_insn_tlb_miss
498
499 ###############################################################################
500 #
501 # Userspace data TLB miss handler
502 # On entry:
503 #   GR28  - faulting address
504 #   GR31  - EAR0 ^ SCR1
505 #   SCR1  - base of virtual range covered by cached PGE from last DTLB miss (or 0xffffffff)
506 #   DAMR3 - mapped page directory
507 #   DAMR5 - mapped page table as matched by SCR1
508 #
509 ###############################################################################
510         .globl          __entry_user_data_tlb_miss
511         .type           __entry_user_data_tlb_miss,@function
512 __entry_user_data_tlb_miss:
513 #if 0
514         sethi.p         %hi(0xe1200004),gr30
515         setlo           %lo(0xe1200004),gr30
516         st              gr0,@(gr30,gr0)
517         sethi.p         %hi(0xffc00100),gr30
518         setlo           %lo(0xffc00100),gr30
519         sth             gr30,@(gr30,gr0)
520         membar
521 #endif
522
523         movsg           ccr,gr30                        /* save CCR */
524         movgs           gr30,scr2
525
526         # see if the cached page table mapping is appropriate
527         srlicc.p        gr31,#26,gr0,icc0
528         setlos          0x3ffc,gr30
529         srli.p          gr28,#12,gr31                   /* use EAR0[25:14] as PTE index */
530         bne             icc0,#0,__dtlb_u_PTD_miss
531
532 __dtlb_u_PTD_mapped:
533         # access the PTD with EAR0[25:14]
534         # - DAMLR5 points to the virtual address of the appropriate page table
535         # - the PTD holds 4096 PTEs
536         # - the PTD must be accessed uncached
537         # - the PTE must be marked accessed if it was valid
538         #
539         and             gr31,gr30,gr31
540         movsg           damlr5,gr30
541
542 __dtlb_u_using_iPTD:
543         add             gr30,gr31,gr31
544         ldi             @(gr31,#0),gr30                 /* fetch the PTE */
545         andicc          gr30,#_PAGE_PRESENT,gr0,icc0
546         ori.p           gr30,#_PAGE_ACCESSED,gr30
547         beq             icc0,#0,__tlb_user_fault        /* jump if PTE invalid */
548         sti.p           gr30,@(gr31,#0)                 /* update the PTE */
549         andi            gr30,#~_PAGE_ACCESSED,gr30
550
551         # we're using DAMR1 as an extra TLB entry
552         # - punt the entry here (if valid) to the real TLB and then replace with the new PTE
553         movsg           dampr1,gr31
554         andicc          gr31,#xAMPRx_V,gr0,icc0
555         setlos.p        0xfffff000,gr31
556         beq             icc0,#0,__dtlb_u_nopunt         /* punt not required */
557
558         movsg           dampr1,gr31
559         movgs           gr31,tppr
560         movsg           damlr1,gr31                     /* set TPLR.CXN */
561         movgs           gr31,tplr
562         tlbpr           gr31,gr0,#2,#0                  /* save to the TLB */
563         movsg           tpxr,gr31                       /* check the TLB write error flag */
564         andicc.p        gr31,#TPXR_E,gr0,icc0
565         setlos          #0xfffff000,gr31
566         bne             icc0,#0,__tlb_user_fault
567
568 __dtlb_u_nopunt:
569
570         # assemble the new TLB entry
571         and             gr28,gr31,gr28
572         movsg           cxnr,gr31
573         or              gr28,gr31,gr28
574         movgs           gr28,iamlr1                     /* xAMLR = address | context number */
575         movgs           gr30,iampr1
576         movgs           gr28,damlr1
577         movgs           gr30,dampr1
578
579         # return, restoring registers
580         movsg           scr2,gr30
581         movgs           gr30,ccr
582         rett            #0
583         beq             icc0,#3,0                       /* prevent icache prefetch */
584
585         # the PTE we want wasn't in the PTD we have mapped, so we need to go looking for a more
586         # appropriate page table and map that instead
587         #   - first of all, check the insn PGE cache - we may well get a hit there
588         #   - access the PGD with EAR0[31:26]
589         #   - DAMLR3 points to the virtual address of the page directory
590         #   - the PGD holds 64 PGEs and each PGE/PME points to a set of page tables
591 __dtlb_u_PTD_miss:
592         movsg           scr0,gr31                       /* consult the insn-PGE-cache key */
593         xor             gr28,gr31,gr31
594         srlicc          gr31,#26,gr0,icc0
595         srli            gr28,#12,gr31                   /* use EAR0[25:14] as PTE index */
596         bne             icc0,#0,__dtlb_u_iPGE_miss
597
598         # what we're looking for is covered by the insn-PGE-cache
599         setlos          0x3ffc,gr30
600         and             gr31,gr30,gr31
601         movsg           damlr4,gr30
602         bra             __dtlb_u_using_iPTD
603
604 __dtlb_u_iPGE_miss:
605         srli            gr28,#26,gr31                   /* calculate PGE offset */
606         slli            gr31,#8,gr31                    /* and clear bottom bits */
607
608         movsg           damlr3,gr30
609         ld              @(gr31,gr30),gr30               /* access the PGE */
610
611         andicc.p        gr30,#_PAGE_PRESENT,gr0,icc0
612         andicc          gr30,#xAMPRx_SS,gr0,icc1
613
614         # map this PTD instead and record coverage address
615         ori.p           gr30,#xAMPRx_L|xAMPRx_SS_16Kb|xAMPRx_S|xAMPRx_C|xAMPRx_V,gr30
616         beq             icc0,#0,__tlb_user_fault        /* jump if PGE not present */
617         slli.p          gr31,#18,gr31
618         bne             icc1,#0,__dtlb_u_bigpage
619         movgs           gr30,dampr5
620         movgs           gr31,scr1
621
622         # we can now resume normal service
623         setlos          0x3ffc,gr30
624         srli.p          gr28,#12,gr31                   /* use EAR0[25:14] as PTE index */
625         bra             __dtlb_u_PTD_mapped
626
627 __dtlb_u_bigpage:
628         break
629         nop
630
631         .size           __entry_user_data_tlb_miss, .-__entry_user_data_tlb_miss