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