aboutsummaryrefslogblamecommitdiff
path: root/sys/ia64/ia64/exception.S
blob: bc51603b1020ca21b2eb517d7f467938aa01dfbb (plain) (tree)
1
2
   
                                      



























                                                                             
                        


                  



                                

   























































































































                                                                         

                                                                        
                                                       
                                                                        




                                                      
                                       

















































































































































































































































































































































                                                               
                         















                                                                        
                                 
                               










                                                                 
                                       

                                       
                                                              


            
                                 



                                   


















                                      

                                                                  





                                                                      
   




















                                                 











                                                 
                          
 








                                                                  
                                        

                  
                                   
                       
                         
 
                                  





                          
                                              

                                                          

                                                         

                              



                                                     

                              


                                                      




                                                                     

                                                       




                                                       

                                                                     









                                                                       
          
                                                     









                                                                  
          
                                                           

                                                             
           
 
                                                        

                                                     
                                               

                                                             



                      
                                                                
                        
 
                           





                          
                                              

                                                          

                                                         

                              



                                                     

                              


                                                      




                                                                     

                                                       




                                                       

                                                                     









                                                                       
          
                                                     









                                                                  
          
                                                           

                                                             
           
 
                                                        

                                                     
                                               

                                                             



                      
                                                                
                 
 
                                            
                                                              



                                                            


                                                             
          

                                                                     


                                                               
                                                                




                                                             
                                                             
                       
                                  
 
                                     




                                                              


                                                             
          

                                                                     


                                                               
                                                                




                                                             
                                                             
                       
                           
 
                                  














                                                                           
          

            
              



































































                                                                 
          
                       
          
                       
                                                          






                                                                     

                                                       




                                                       

                                                                     

                                                   
                               
          
                                                                 
          
                                                     







                                                                       
          
                                                     









                                                                  
          
                                                           

                                                             
           
 





                                                             
                                                       
                  
 
                                         

                          
          
                       
          
                       


                                                          
          



                                                                     

                                                       




                                                       

                                                                     





                                                           

                                                     






                                                                       
          
                                                     









                                                                  
          
                                                           

                                                             
                                                                       
 





                                                             
                       
                               
 
                                  

                          
          
                       
          
                       
                                                          
          
                                                      
          



                                                                     

                                                       




                                                       

                                                                     





                                                           
                                                     







                                                                       
          
                                                     









                                                                  
          
                                                           

                                                             
                                                                       
 





                                                             
                        
                        
 
                                    







                                          
          







                                  
          






                                         
                          
 
                                     





                                                                           
                                          
                                   
          



                                                               
          




                                                                           
                                                                  
          


                                                             

              



                                                            

              


                         
                                                                 

                                                        
          

  
            
                                  

                                         







                                         
                           
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                   
                        
                         
 
                                 
                        
                       
 
                                            
                        
                                  
 
                                     
                        
                           
 
                                    
                        
                          
 
                                       
                        
                             
 
                                  
                        
                        
 
                              
                        
                    
 
                                
                        
                      
 
                        
                        
              
 
                                      
                        
                            
 
                                             
                        
                                   
 
                                       
                        
                             
 
                                      
                        
                            
 
                                                
                        
                                      
 
                                    
                        
                          
 
                                   
                        
                         
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                  
                        
                        
 
                                  
                        
                        
 
                                  
                        
                        
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
 
                                
                        
                      
/*-
 * Copyright (c) 2003 Marcel Moolenaar
 * Copyright (c) 2000 Doug Rabson
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	$FreeBSD$
 */

#include <machine/asm.h>
#include <machine/pte.h>
#include <assym.s>

/*
 * ar.k7 = kernel memory stack
 * ar.k6 = kernel register stack
 * ar.k5 = EPC gateway page
 * ar.k4 = PCPU data
 */

	.text

/*
 * exception_save: save interrupted state
 *
 * Arguments:
 *	r16	address of bundle that contains the branch. The
 *		return address will be the next bundle.
 *	r17	the value to save as ifa in the trapframe. This
 *		normally is cr.ifa, but some interruptions set
 *		set cr.iim and not cr.ifa.
 *
 * Returns:
 *	p15	interrupted from user stack
 *	p14	interrupted from kernel stack
 *	p13	interrupted from user backing store
 *	p12	interrupted from kernel backing store
 *	p11	interrupts were enabled
 *	p10	interrupts were disabled
 */
ENTRY(exception_save, 0)
{	.mii
	mov		r20=ar.unat
	extr.u		r31=sp,61,3
	mov		r18=pr
	;;
}
{	.mmi
	cmp.le		p14,p15=5,r31
	;;
(p15)	mov		r23=ar.k7		// kernel memory stack
(p14)	mov		r23=sp
	;;
}
{	.mii
	mov		r21=ar.rsc
	add		r30=-SIZEOF_TRAPFRAME,r23
	;;
	dep		r30=0,r30,0,10
	;;
}
{	.mmi
	mov		ar.rsc=0
	sub		r19=r23,r30
	add		r31=8,r30
	;;
}
{	.mlx
	mov		r22=cr.iip
	movl		r26=exception_save_restart
	;;
}

	/*
	 * We have a 1KB aligned trapframe, pointed to by sp. If we write
	 * to the trapframe, we may trigger a data nested TLB fault. By
	 * aligning the trapframe on a 1KB boundary, we guarantee that if
	 * we get a data nested TLB fault, it will be on the very first
	 * write. Since the data nested TLB fault does not preserve any
	 * state, we have to be careful what we clobber. Consequently, we
	 * have to be careful what we use here. Below a list of registers
	 * that are currently alive:
	 *	r16,r17=arguments
	 *	r18=pr, r19=length, r20=unat, r21=rsc, r22=iip, r23=TOS
	 *	r26=restart point
	 *	r30,r31=trapframe pointers
	 *	p14,p15=memory stack switch
	 */
exception_save_restart:
{	.mmi
	st8		[r30]=r19,16		// length
	st8		[r31]=r0,16		// flags
	add		r19=16,r19
	;;
}
{	.mmi
	st8.spill	[r30]=sp,16		// sp
	st8		[r31]=r20,16		// unat
	sub		sp=r23,r19
	;;
}
{	.mmi
	mov		r19=ar.rnat
	mov		r20=ar.bspstore
	mov		r23=rp
	;;
}
	// r18=pr, r19=rnat, r20=bspstore, r21=rsc, r22=iip, r23=rp
{	.mmi
	st8		[r30]=r23,16		// rp
	st8		[r31]=r18,16		// pr
	mov		r24=ar.pfs
	;;
}
{	.mmb
	st8		[r30]=r24,16		// pfs
	st8		[r31]=r20,16		// bspstore
	cover
	;;
}
{	.mmi
	mov		r18=ar.fpsr
	mov		r23=cr.ipsr
	extr.u		r24=r20,61,3
	;;
}
	// r18=fpsr, r19=rnat, r20=bspstore, r21=rsc, r22=iip, r23=ipsr
{	.mmi
	st8		[r30]=r19,16		// rnat
	st8		[r31]=r0,16		// __spare
	cmp.le		p12,p13=5,r24
	;;
}
{	.mmi
	st8.spill	[r30]=r13,16		// tp
	st8		[r31]=r21,16		// rsc
	tbit.nz		p11,p10=r23,14		// p11=interrupts enabled
	;;
}
{	.mmi
(p13)	mov		r21=ar.k6		// kernel register stack
	;;
	st8		[r30]=r18,16		// fpsr
(p13)	dep		r20=r20,r21,0,9		// align dirty registers
	;;
}
	// r20=bspstore, r22=iip, r23=ipsr
{	.mmi
	st8		[r31]=r23,16		// psr
(p13)	mov		ar.bspstore=r20
	nop		0
	;;
}
{	.mmi
	mov		r18=ar.bsp
	;;
	mov		r19=cr.ifs
	sub		r18=r18,r20
	;;
}
{	.mmi
	st8.spill	[r30]=gp,16		// gp
	st8		[r31]=r18,16		// ndirty
	nop		0
	;;
}
	// r19=ifs, r22=iip
{	.mmi
	st8		[r30]=r19,16		// cfm
	st8		[r31]=r22,16		// iip
	nop		0
	;;
}
{	.mmi
	st8		[r30]=r17		// ifa
	mov		r18=cr.isr
	add		r29=16,r30
	;;
}
{	.mmi
	st8		[r31]=r18		// isr
	add		r30=8,r29
	add		r31=16,r29
	;;
}
{	.mmi
	.mem.offset	0,0
	st8.spill	[r30]=r2,16		// r2
	.mem.offset	8,0
	st8.spill	[r31]=r3,16		// r3
	add		r2=9*8,r29
	;;
}
{	.mmi
	.mem.offset	0,0
	st8.spill	[r30]=r8,16		// r8
	.mem.offset	8,0
	st8.spill	[r31]=r9,16		// r9
	add		r3=8,r2
	;;
}
{	.mmi
	.mem.offset	0,0
	st8.spill	[r30]=r10,16		// r10
	.mem.offset	8,0
	st8.spill	[r31]=r11,16		// r11
	add		r8=16,r16
	;;
}
{	.mmi
	.mem.offset	0,0
	st8.spill	[r30]=r14		// r14
	.mem.offset	8,0
	st8.spill	[r31]=r15		// r15
	mov		r9=r29
}
{	.mmb
	mov		r10=ar.csd
	mov		r11=ar.ssd
	bsw.1
	;;
}
{	.mmi
	.mem.offset	0,0
	st8.spill	[r2]=r16,16		// r16
	.mem.offset	8,0
	st8.spill	[r3]=r17,16		// r17
	mov		r14=b6
	;;
}
{	.mmi
	.mem.offset	0,0
	st8.spill	[r2]=r18,16		// r18
	.mem.offset	8,0
	st8.spill	[r3]=r19,16		// r19
	mov		r15=b7
	;;
}
{	.mmi
	.mem.offset	0,0
	st8.spill	[r2]=r20,16		// r20
	.mem.offset	8,0
	st8.spill	[r3]=r21,16		// r21
	mov		b7=r8
	;;
}
{	.mmi
	.mem.offset	0,0
	st8.spill	[r2]=r22,16		// r22
	.mem.offset	8,0
	st8.spill	[r3]=r23,16		// r23
	;;
}

	.mem.offset	0,0
	st8.spill	[r2]=r24,16		// r24
	.mem.offset	8,0
	st8.spill	[r3]=r25,16		// r25
	;;
	.mem.offset	0,0
	st8.spill	[r2]=r26,16		// r26
	.mem.offset	8,0
	st8.spill	[r3]=r27,16		// r27
	;;
	.mem.offset	0,0
	st8.spill	[r2]=r28,16		// r28
	.mem.offset	8,0
	st8.spill	[r3]=r29,16		// r29
	;;
	.mem.offset	0,0
	st8.spill	[r2]=r30,16		// r30
	.mem.offset	8,0
	st8.spill	[r3]=r31,16		// r31
	;;

{	.mmi
	st8		[r2]=r14,16		// b6
	mov		r17=ar.unat
	nop		0
	;;
}
{	.mmi
	st8		[r3]=r15,16		// b7
	mov		r16=ar.ccv
	nop		0
	;;
}
{	.mmi
	st8		[r2]=r16,16		// ccv
	st8		[r3]=r10,16		// csd
	nop		0
	;;
}
{	.mmi
	st8		[r2]=r11,24		// ssd
	st8		[r9]=r17
	nop		0
	;;
}

	stf.spill	[r3]=f6,32		// f6
	stf.spill	[r2]=f7,32		// f7
	;;
	stf.spill	[r3]=f8,32		// f8
	stf.spill	[r2]=f9,32		// f9
	;;
	stf.spill	[r3]=f10,32		// f10
	stf.spill	[r2]=f11,32		// f11
	;;
	stf.spill	[r3]=f12,32		// f12
	stf.spill	[r2]=f13,32		// f13
	;;
	stf.spill	[r3]=f14		// f14
	stf.spill	[r2]=f15		// f15
	;;
{	.mmi
	mov		ar.rsc=3
	mov		r13=ar.k4
	nop		0
	;;
}
{	.mlx
	ssm		psr.ic|psr.dfh
	movl		gp=__gp
	;;
}
{	.mfb
	srlz.d
	nop		0
	br.sptk		b7
	;;
}
END(exception_save)

/*
 * exception_restore:	restore interrupted state
 *
 * Arguments:
 *	sp+16	trapframe pointer
 */
ENTRY(exception_restore, 0)
{	.mmi
	rsm		psr.i
	add		sp=16,sp
	nop		0
	;;
}
{	.mmi
	add		r3=SIZEOF_TRAPFRAME-32,sp
	add		r2=SIZEOF_TRAPFRAME-16,sp
	add		r8=SIZEOF_SPECIAL+16,sp
	;;
}
	// The next load can trap. Let it be...
	ldf.fill	f15=[r2],-32		// f15
	ldf.fill	f14=[r3],-32		// f14
	;;
	ldf.fill	f13=[r2],-32		// f13
	ldf.fill	f12=[r3],-32		// f12
	;;
	ldf.fill	f11=[r2],-32		// f11
	ldf.fill	f10=[r3],-32		// f10
	;;
	ldf.fill	f9=[r2],-32		// f9
	ldf.fill	f8=[r3],-32		// f8
	;;
	ldf.fill	f7=[r2],-24		// f7
	ldf.fill	f6=[r3],-16		// f6
	;;

{	.mmi
	ld8		r8=[r8]			// unat (after)
	;;
	mov		ar.unat=r8
	nop		0
	;;
}

	ld8		r10=[r2],-16		// ssd
	ld8		r11=[r3],-16		// csd
	;;
	mov		ar.ssd=r10
	mov		ar.csd=r11

	ld8		r14=[r2],-16		// ccv
	ld8		r15=[r3],-16		// b7
	;;

{	.mmi
	mov		ar.ccv=r14
	ld8		r8=[r2],-16		// b6
	mov		b7=r15
	;;
}
{	.mmi
	ld8.fill	r31=[r3],-16		// r31
	ld8.fill	r30=[r2],-16		// r30
	mov		b6=r8
	;;
}

	ld8.fill	r29=[r3],-16		// r29
	ld8.fill	r28=[r2],-16		// r28
	;;
	ld8.fill	r27=[r3],-16		// r27
	ld8.fill	r26=[r2],-16		// r26
	;;
	ld8.fill	r25=[r3],-16		// r25
	ld8.fill	r24=[r2],-16		// r24
	;;
	ld8.fill	r23=[r3],-16		// r23
	ld8.fill	r22=[r2],-16		// r22
	;;
	ld8.fill	r21=[r3],-16		// r21
	ld8.fill	r20=[r2],-16		// r20
	;;
	ld8.fill	r19=[r3],-16		// r19
	ld8.fill	r18=[r2],-16		// r18
	;;

{	.mmb
	ld8.fill	r17=[r3],-16		// r17
	ld8.fill	r16=[r2],-16		// r16
	bsw.0
	;;
}
{	.mmi
	ld8.fill	r15=[r3],-16		// r15
	ld8.fill	r14=[r2],-16		// r14
	add		r31=16,sp
	;;
}
{	.mmi
	ld8		r16=[sp]		// tf_length
	ld8.fill	r11=[r3],-16		// r11
	add		r30=24,sp
	;;
}
{	.mmi
	ld8.fill	r10=[r2],-16		// r10
	ld8.fill	r9=[r3],-16		// r9
	add		r16=r16,sp		// ar.k7
	;;
}
{	.mmi
	ld8.fill	r8=[r2],-16		// r8
	ld8.fill	r3=[r3]			// r3
	;;
}
	// We want nested TLB faults from here on...
	rsm		psr.ic|psr.i
	ld8.fill	r2=[r2]			// r2
	nop		0
	;;
	srlz.d
	ld8.fill	sp=[r31],16		// sp
	nop		0
	;;

	ld8		r17=[r30],16		// unat
	ld8		r29=[r31],16		// rp
	;;
	ld8		r18=[r30],16		// pr
	ld8		r28=[r31],16		// pfs
	mov		rp=r29
	;;
	ld8		r20=[r30],24		// bspstore
	ld8		r21=[r31],24		// rnat
	mov		ar.pfs=r28
	;;
	ld8.fill	r29=[r30],16		// tp
	ld8		r22=[r31],16		// rsc
	;;
{	.mmi
	ld8		r23=[r30],16		// fpsr
	ld8		r24=[r31],16		// psr
	extr.u		r28=r20,61,3
	;;
}
{	.mmi
	ld8.fill	r1=[r30],16		// gp
	ld8		r25=[r31],16		// ndirty
	cmp.le		p14,p15=5,r28
	;;
}
{	.mmb
	ld8		r26=[r30]		// cfm
	ld8		r19=[r31]		// ip
	nop		0
	;;
}
{	.mib
	// Switch register stack
	alloc		r30=ar.pfs,0,0,0,0	// discard current frame
	shl		r31=r25,16		// value for ar.rsc
	nop		0
	;;
}
	// The loadrs can fault if the backing store is not currently
	// mapped. We assured forward progress by getting everything we
	// need from the trapframe so that we don't care if the CPU
	// purges that translation when it needs to insert a new one for
	// the backing store.
{	.mmi
	mov		ar.rsc=r31		// setup for loadrs
	mov		ar.k7=r16
(p15)	mov		r13=r29
	;;
}
exception_restore_restart:
{	.mmi
	mov		r30=ar.bspstore
	;;
	loadrs					// load user regs
	nop		0
	;;
}
{	.mmi
	mov		r31=ar.bspstore
	;;
	mov		ar.bspstore=r20
	dep		r31=0,r31,0,13		// 8KB aligned
	;;
}
{	.mmb
	mov		ar.k6=r31
	mov		ar.rnat=r21
	nop		0
	;;
}
{	.mmb
	mov		ar.unat=r17
	mov		cr.iip=r19
	nop		0
}
{	.mmi
	mov		cr.ipsr=r24
	mov		cr.ifs=r26
	mov		pr=r18,0x1fffe
	;;
}
{	.mmb
	mov		ar.rsc=r22
	mov		ar.fpsr=r23
	rfi
	;;
}
END(exception_restore)

/*
 * Call exception_save_regs to preserve the interrupted state in a
 * trapframe. Note that we don't use a call instruction because we
 * must be careful not to lose track of the RSE state. We then call
 * trap() with the value of _n_ as an argument to handle the
 * exception. We arrange for trap() to return to exception_restore
 * which will restore the interrupted state before executing an rfi to
 * resume it.
 */
#define TRAP(_n_, _ifa_)			\
{	.mib ;					\
	mov		r17=_ifa_ ;		\
	mov		r16=ip ;		\
	br.sptk		exception_save ;	\
} ;						\
{	.mmi ;					\
(p11)	ssm		psr.i ;;		\
	alloc		r15=ar.pfs,0,0,2,0 ;	\
	mov		out0=_n_ ;;		\
} ;						\
{	.mfb ;					\
	add		out1=16,sp ;		\
	nop		0 ;			\
	br.call.sptk	rp=trap ;		\
} ;						\
{	.mfb ;					\
	nop		0 ;			\
	nop		0 ;			\
	br.sptk		exception_restore ;	\
}

#define	IVT_ENTRY(name, offset)			\
	.org	ia64_vector_table + offset;	\
	.global	ivt_##name;			\
	.proc	ivt_##name;			\
	.prologue;				\
	.unwabi	@svr4, 'I';			\
	.save	rp, r0;				\
	.body;					\
ivt_##name:

#define	IVT_END(name)				\
	.endp	ivt_##name

/*
 * The IA64 Interrupt Vector Table (IVT) contains 20 slots with 64
 * bundles per vector and 48 slots with 16 bundles per vector.
 */

	.section .text.ivt,"ax"

	.align	32768
	.global ia64_vector_table
	.size	ia64_vector_table, 32768
ia64_vector_table:

IVT_ENTRY(VHPT_Translation, 0x0000)
	TRAP(0, cr.ifa)
IVT_END(VHPT_Translation)

IVT_ENTRY(Instruction_TLB, 0x0400)
	mov	r16=cr.ifa
	mov	r17=pr
	;;
	thash	r18=r16
	ttag	r19=r16
	;;
	add	r21=16,r18		// tag
	add	r20=24,r18		// collision chain
	;; 
	ld8	r21=[r21]		// check VHPT tag
	;;
	cmp.ne	p15,p0=r21,r19
(p15)	br.dpnt.few 1f
	;;
	ld8	r21=[r18]		// read pte
	;;
	itc.i	r21			// insert pte
	;;
	mov	pr=r17,0x1ffff
	rfi				// done
	;;
1:	ld8	r20=[r20]		// first entry
	;; 
	rsm	psr.dt			// turn off data translations
	;;
	srlz.d				// serialize
	;;
2:	cmp.eq	p15,p0=r0,r20		// done?
(p15)	br.cond.spnt.few 9f		// bail if done
	;;
	add	r21=16,r20		// tag location
	;;
	ld8	r21=[r21]		// read tag
	;;
	cmp.ne	p15,p0=r21,r19		// compare tags
(p15)	br.cond.sptk.few 3f		// if not, read next in chain
	;;
	ld8	r21=[r20],8		// read pte
	;; 
	ld8	r22=[r20]		// read rest of pte
	;;
	dep	r18=0,r18,61,3		// convert vhpt ptr to physical
	;;
	add	r20=16,r18		// address of tag
	;;
	ld8.acq	r23=[r20]		// read old tag
	;;
	dep	r23=-1,r23,63,1		// set ti bit
	;;
	st8.rel	[r20]=r23		// store old tag + ti
	;;
	mf				// make sure everyone sees
	;;
	st8	[r18]=r21,8		// store pte
	;;
	st8	[r18]=r22,8
	;;
	st8.rel	[r18]=r19		// store new tag
	;;
	itc.i	r21			// and place in TLB
	;; 
	mov	pr=r17,0x1ffff		// restore predicates
	rfi

3:	add	r20=24,r20		// next in chain
	;;
	ld8	r20=[r20]		// read chain
	br.cond.sptk.few 2b		// loop

9:	mov	pr=r17,0x1ffff		// restore predicates
	ssm	psr.dt
	;;
	srlz.d
	;; 
	TRAP(20, cr.ifa)		// Page Not Present trap
IVT_END(Instruction_TLB)

IVT_ENTRY(Data_TLB, 0x0800)
	mov	r16=cr.ifa
	mov	r17=pr
	;;
	thash	r18=r16
	ttag	r19=r16
	;;
	add	r21=16,r18		// tag
	add	r20=24,r18		// collision chain
	;; 
	ld8	r21=[r21]		// check VHPT tag
	;;
	cmp.ne	p15,p0=r21,r19
(p15)	br.dpnt.few 1f
	;;
	ld8	r21=[r18]		// read pte
	;;
	itc.d	r21			// insert pte
	;;
	mov	pr=r17,0x1ffff
	rfi				// done
	;;
1:	ld8	r20=[r20]		// first entry
	;; 
	rsm	psr.dt			// turn off data translations
	;;
	srlz.d				// serialize
	;;
2:	cmp.eq	p15,p0=r0,r20		// done?
(p15)	br.cond.spnt.few 9f		// bail if done
	;;
	add	r21=16,r20		// tag location
	;;
	ld8	r21=[r21]		// read tag
	;;
	cmp.ne	p15,p0=r21,r19		// compare tags
(p15)	br.cond.sptk.few 3f		// if not, read next in chain
	;;
	ld8	r21=[r20],8		// read pte
	;; 
	ld8	r22=[r20]		// read rest of pte
	;;
	dep	r18=0,r18,61,3		// convert vhpt ptr to physical
	;;
	add	r20=16,r18		// address of tag
	;;
	ld8.acq	r23=[r20]		// read old tag
	;;
	dep	r23=-1,r23,63,1		// set ti bit
	;;
	st8.rel	[r20]=r23		// store old tag + ti
	;;
	mf				// make sure everyone sees
	;;
	st8	[r18]=r21,8		// store pte
	;;
	st8	[r18]=r22,8
	;;
	st8.rel	[r18]=r19		// store new tag
	;;
	itc.d	r21			// and place in TLB
	;; 
	mov	pr=r17,0x1ffff		// restore predicates
	rfi

3:	add	r20=24,r20		// next in chain
	;;
	ld8	r20=[r20]		// read chain
	br.cond.sptk.few 2b		// loop

9:	mov	pr=r17,0x1ffff		// restore predicates
	ssm	psr.dt
	;;
	srlz.d
	;; 
	TRAP(20, cr.ifa)		// Page Not Present trap
IVT_END(Data_TLB)

IVT_ENTRY(Alternate_Instruction_TLB, 0x0c00)
	mov	r16=cr.ifa		// where did it happen
	mov	r18=pr			// save predicates
	;;
	extr.u	r17=r16,61,3		// get region number
	;;
	cmp.ge	p13,p0=5,r17		// RR0-RR5?
	cmp.eq	p15,p14=7,r17		// RR7->p15, RR6->p14
(p13)	br.spnt	9f
	;;
(p15)	movl	r17=PTE_P+PTE_MA_WB+PTE_A+PTE_D+PTE_PL_KERN+PTE_AR_RX
(p14)	movl	r17=PTE_P+PTE_MA_UC+PTE_A+PTE_D+PTE_PL_KERN+PTE_AR_RX
	;;
	dep	r16=0,r16,50,14		// clear bits above PPN
	;;
	dep	r16=r17,r16,0,12	// put pte bits in 0..11
	;;
	itc.i	r16
	mov	pr=r18,0x1ffff		// restore predicates
	;;
	rfi
9:	mov	pr=r18,0x1ffff		// restore predicates
	TRAP(3, cr.ifa)
IVT_END(Alternate_Instruction_TLB)

IVT_ENTRY(Alternate_Data_TLB, 0x1000)
	mov	r16=cr.ifa		// where did it happen
	mov	r18=pr			// save predicates
	;;
	extr.u	r17=r16,61,3		// get region number
	;;
	cmp.ge	p13,p0=5,r17		// RR0-RR5?
	cmp.eq	p15,p14=7,r17		// RR7->p15, RR6->p14
(p13)	br.spnt	9f
	;;
(p15)	movl	r17=PTE_P+PTE_MA_WB+PTE_A+PTE_D+PTE_PL_KERN+PTE_AR_RW
(p14)	movl	r17=PTE_P+PTE_MA_UC+PTE_A+PTE_D+PTE_PL_KERN+PTE_AR_RW
	;;
	dep	r16=0,r16,50,14		// clear bits above PPN
	;;
	dep	r16=r17,r16,0,12	// put pte bits in 0..11
	;;
	itc.d	r16
	mov	pr=r18,0x1ffff		// restore predicates
	;;
	rfi
9:	mov	pr=r18,0x1ffff		// restore predicates
	TRAP(4, cr.ifa)
IVT_END(Alternate_Data_TLB)

IVT_ENTRY(Data_Nested_TLB, 0x1400)
	// See exception_save_restart and exception_restore_restart for the
	// contexts that may cause a data nested TLB. We can only use the
	// banked general registers and predicates, but don't use:
	//	p14 & p15	-	Set in exception save
	//	r16 & r17	-	Arguments to exception save
	//	r30		-	Faulting address (modulo page size)
	// We assume r30 has the virtual addresses that relate to the data
	// nested TLB fault. The address does not have to be exact, as long
	// as it's in the same page. We use physical addressing to avoid
	// double nested faults. Since all virtual addresses we encounter
	// here are direct mapped region 7 addresses, we have no problem
	// constructing physical addresses.
{	.mlx
	rsm		psr.dt
	movl		r27=ia64_kptdir
	;;
}
{	.mii
	srlz.d
	dep		r27=0,r27,61,3
	extr.u		r28=r30,PAGE_SHIFT,61-PAGE_SHIFT
	;;
}
{	.mii
	ld8		r27=[r27]
	shr.u		r29=r28,PAGE_SHIFT-5	// dir index
	extr.u		r28=r28,0,PAGE_SHIFT-5	// pte index
	;;
}
{	.mmi
	shladd		r27=r29,3,r27
	;;
	mov		cr.ifa=r30
	dep		r27=0,r27,61,3
	;;
}
{	.mmi
	ld8		r27=[r27]
	mov		r29=rr[r30]
	shl		r28=r28,5
	;;
}
{	.mii
	add		r27=r27,r28		// address of pte
	dep		r29=0,r29,0,2
	;;
	dep		r27=0,r27,61,3
	;;
}
{	.mmi
	ld8		r28=[r27]
	;;
	mov		cr.itir=r29
	or		r28=PTE_D|PTE_A,r28
	;;
}
{	.mlx
	st8		[r27]=r28
	movl		r29=exception_save_restart
	;;
}
{	.mmi
	itc.d		r28
	;;
	ssm		psr.dt
	cmp.eq		p12,p13=r26,r29
	;;
}
{	.mbb
	srlz.d
(p12)	br.sptk		exception_save_restart
(p13)	br.sptk		exception_restore_restart
	;;
}
IVT_END(Data_Nested_TLB)

IVT_ENTRY(Instruction_Key_Miss, 0x1800)
	TRAP(6, cr.ifa)
IVT_END(Instruction_Key_Miss)

IVT_ENTRY(Data_Key_Miss, 0x1c00)
	TRAP(7, cr.ifa)
IVT_END(Data_Key_Miss)

IVT_ENTRY(Dirty_Bit, 0x2000)
	mov	r16=cr.ifa
	mov	r17=pr
	;;
	thash	r18=r16
	;;
	ttag	r19=r16
	add	r20=24,r18		// collision chain
	;; 
	ld8	r20=[r20]		// first entry
	;; 
	rsm	psr.dt			// turn off data translations
	;;
	srlz.d				// serialize
	;;
1:	cmp.eq	p15,p0=r0,r20		// done?
(p15)	br.cond.spnt.few 9f		// bail if done
	;;
	add	r21=16,r20		// tag location
	;;
	ld8	r21=[r21]		// read tag
	;;
	cmp.ne	p15,p0=r21,r19		// compare tags
(p15)	br.cond.sptk.few 2f		// if not, read next in chain
	;;
	ld8	r21=[r20]		// read pte
	mov	r22=PTE_D|PTE_A
	;;
	or	r21=r22,r21		// set dirty & access bit
	;;
	st8	[r20]=r21,8		// store back
	;; 
	ld8	r22=[r20]		// read rest of pte
	;;
	dep	r18=0,r18,61,3		// convert vhpt ptr to physical
	;;
	add	r20=16,r18		// address of tag
	;;
	ld8.acq	r23=[r20]		// read old tag
	;;
	dep	r23=-1,r23,63,1		// set ti bit
	;;
	st8.rel	[r20]=r23		// store old tag + ti
	;;
	mf				// make sure everyone sees
	;;
	st8	[r18]=r21,8		// store pte
	;;
	st8	[r18]=r22,8
	;;
	st8.rel	[r18]=r19		// store new tag
	;;
	itc.d	r21			// and place in TLB
	;; 
	mov	pr=r17,0x1ffff		// restore predicates
	rfi

2:	add	r20=24,r20		// next in chain
	;;
	ld8	r20=[r20]		// read chain
	br.cond.sptk.few 1b		// loop

9:	mov	pr=r17,0x1ffff		// restore predicates
	TRAP(8, cr.ifa)			// die horribly
IVT_END(Dirty_Bit)

IVT_ENTRY(Instruction_Access_Bit, 0x2400)
	mov	r16=cr.ifa
	mov	r17=pr
	;;
	thash	r18=r16
	;;
	ttag	r19=r16
	add	r20=24,r18		// collision chain
	;; 
	ld8	r20=[r20]		// first entry
	;;
	rsm	psr.dt			// turn off data translations
	;;
	srlz.d				// serialize
	;;
1:	cmp.eq	p15,p0=r0,r20		// done?
(p15)	br.cond.spnt.few 9f		// bail if done
	;;
	add	r21=16,r20		// tag location
	;;
	ld8	r21=[r21]		// read tag
	;;
	cmp.ne	p15,p0=r21,r19		// compare tags
(p15)	br.cond.sptk.few 2f		// if not, read next in chain
	;;
	ld8	r21=[r20]		// read pte
	mov	r22=PTE_A
	;;
	or	r21=r22,r21		// set accessed bit
	;;
	st8	[r20]=r21,8		// store back
	;;
	ld8	r22=[r20]		// read rest of pte
	;;
	dep	r18=0,r18,61,3		// convert vhpt ptr to physical
	;;
	add	r20=16,r18		// address of tag
	;;
	ld8.acq	r23=[r20]		// read old tag
	;;
	dep	r23=-1,r23,63,1		// set ti bit
	;;
	st8.rel	[r20]=r23		// store old tag + ti
	;;
	mf				// make sure everyone sees
	;;
	st8	[r18]=r21,8		// store pte
	;;
	st8	[r18]=r22,8
	;;
	st8.rel	[r18]=r19		// store new tag
	;;
	itc.i	r21			// and place in TLB
	;; 
	mov	pr=r17,0x1ffff		// restore predicates
	rfi				// walker will retry the access

2:	add	r20=24,r20		// next in chain
	;;
	ld8	r20=[r20]		// read chain
	br.cond.sptk.few 1b		// loop

9:	mov	pr=r17,0x1ffff		// restore predicates
	TRAP(9, cr.ifa)
IVT_END(Instruction_Access_Bit)

IVT_ENTRY(Data_Access_Bit, 0x2800)
	mov	r16=cr.ifa
	mov	r17=pr
	;;
	thash	r18=r16
	;;
	ttag	r19=r16
	add	r20=24,r18		// collision chain
	;;
	ld8	r20=[r20]		// first entry
	;;
	rsm	psr.dt			// turn off data translations
	;;
	srlz.d				// serialize
	;;
1:	cmp.eq	p15,p0=r0,r20		// done?
(p15)	br.cond.spnt.few 9f		// bail if done
	;;
	add	r21=16,r20		// tag location
	;;
	ld8	r21=[r21]		// read tag
	;;
	cmp.ne	p15,p0=r21,r19		// compare tags
(p15)	br.cond.sptk.few 2f		// if not, read next in chain
	;;
	ld8	r21=[r20]		// read pte
	mov	r22=PTE_A
	;;
	or	r21=r22,r21		// set accessed bit
	;;
	st8	[r20]=r21,8		// store back
	;; 
	ld8	r22=[r20]		// read rest of pte
	;;
	dep	r18=0,r18,61,3		// convert vhpt ptr to physical
	;;
	add	r20=16,r18		// address of tag
	;;
	ld8.acq	r23=[r20]		// read old tag
	;;
	dep	r23=-1,r23,63,1		// set ti bit
	;;
	st8.rel	[r20]=r23		// store old tag + ti
	;;
	mf				// make sure everyone sees
	;;
	st8	[r18]=r21,8		// store pte
	;;
	st8	[r18]=r22,8
	;;
	st8.rel	[r18]=r19		// store new tag
	;;
	itc.d	r21			// and place in TLB
	;; 
	mov	pr=r17,0x1ffff		// restore predicates
	rfi				// walker will retry the access

2:	add	r20=24,r20		// next in chain
	;;
	ld8	r20=[r20]		// read chain
	br.cond.sptk.few 1b		// loop

9:	mov	pr=r17,0x1ffff		// restore predicates
	TRAP(10, cr.ifa)
IVT_END(Data_Access_Bit)

IVT_ENTRY(Break_Instruction, 0x2c00)
{	.mib
	mov		r17=cr.iim
	mov		r16=ip
	br.sptk		exception_save
	;;
}
{	.mmi
	alloc		r15=ar.pfs,0,0,2,0
	;;
	flushrs
	mov		out0=11
	;;
}
{	.mib
(p11)	ssm		psr.i
	add		out1=16,sp
	br.call.sptk	rp=trap
	;;
}
{	.mfb
	nop		0
	nop		0
	br.sptk		exception_restore
	;;
}
IVT_END(Break_Instruction)

IVT_ENTRY(External_Interrupt, 0x3000)
{	.mib
	mov		r17=cr.lid	// cr.iim and cr.ifa are undefined.
	mov		r16=ip
	br.sptk		exception_save
	;;
}
	alloc		r14=ar.pfs,0,0,2,0
	cmp4.eq		p14,p0=0,r0
	;;
1:
{	.mii
	mov		out0=cr.ivr	// Get interrupt vector
	add		out1=16,sp
	;;
	cmp.eq		p15,p0=15,out0	// check for spurious vector number
}
{	.mbb
	ssm		psr.i		// re-enable interrupts
(p15)	br.dpnt.few 2f			// if spurious, we are done
	br.call.sptk.many rp=interrupt	// call high-level handler
	;;
}
{	.mmi
	rsm		psr.i		// disable interrupts
	;;
	srlz.d
	nop		0
}
{	.mmi
	mov		cr.eoi=r0	// ack the interrupt
	;;
	srlz.d
	nop		0
}
{	.mfb
	cmp4.eq		p14,p0=0,r8	// Return to kernel mode?
	nop		0
	br.sptk		1b		// loop for more
	;;
}
2:
{	.mbb
	add		out0=16,sp
(p14)	br.sptk		exception_restore
	br.call.sptk	rp=do_ast
	;;
}
{	.mfb
	nop		0
	nop		0
	br.sptk		exception_restore
	;;
}
IVT_END(External_Interrupt)

IVT_ENTRY(Reserved_3400, 0x3400)
	TRAP(13, cr.ifa)
IVT_END(Reserved_3400)

IVT_ENTRY(Reserved_3800, 0x3800)
	TRAP(14, cr.ifa)
IVT_END(Reserved_3800)

IVT_ENTRY(Reserved_3c00, 0x3c00)
	TRAP(15, cr.ifa)
IVT_END(Reserved_3c00)

IVT_ENTRY(Reserved_4000, 0x4000)
	TRAP(16, cr.ifa)
IVT_END(Reserved_4000)

IVT_ENTRY(Reserved_4400, 0x4400)
	TRAP(17, cr.ifa)
IVT_END(Reserved_4400)

IVT_ENTRY(Reserved_4800, 0x4800)
	TRAP(18, cr.ifa)
IVT_END(Reserved_4800)

IVT_ENTRY(Reserved_4c00, 0x4c00)
	TRAP(19, cr.ifa)
IVT_END(Reserved_4c00)

IVT_ENTRY(Page_Not_Present, 0x5000)
	TRAP(20, cr.ifa)
IVT_END(Page_Not_Present)

IVT_ENTRY(Key_Permission, 0x5100)
	TRAP(21, cr.ifa)
IVT_END(Key_Permission)

IVT_ENTRY(Instruction_Access_Rights, 0x5200)
	TRAP(22, cr.ifa)
IVT_END(Instruction_Access_Rights)

IVT_ENTRY(Data_Access_Rights, 0x5300)
	TRAP(23, cr.ifa)
IVT_END(Data_Access_Rights)

IVT_ENTRY(General_Exception, 0x5400)
	TRAP(24, cr.ifa)
IVT_END(General_Exception)

IVT_ENTRY(Disabled_FP_Register, 0x5500)
	TRAP(25, cr.ifa)
IVT_END(Disabled_FP_Register)

IVT_ENTRY(NaT_Consumption, 0x5600)
	TRAP(26, cr.ifa)
IVT_END(NaT_Consumption)

IVT_ENTRY(Speculation, 0x5700)
	TRAP(27, cr.iim)
IVT_END(Speculation)

IVT_ENTRY(Reserved_5800, 0x5800)
	TRAP(28, cr.ifa)
IVT_END(Reserved_5800)

IVT_ENTRY(Debug, 0x5900)
	TRAP(29, cr.ifa)
IVT_END(Debug)

IVT_ENTRY(Unaligned_Reference, 0x5a00)
	TRAP(30, cr.ifa)
IVT_END(Unaligned_Reference)

IVT_ENTRY(Unsupported_Data_Reference, 0x5b00)
	TRAP(31, cr.ifa)
IVT_END(Unsupported_Data_Reference)

IVT_ENTRY(Floating_Point_Fault, 0x5c00)
	TRAP(32, cr.ifa)
IVT_END(Floating_Point_Fault)

IVT_ENTRY(Floating_Point_Trap, 0x5d00)
	TRAP(33, cr.ifa)
IVT_END(Floating_Point_Trap)

IVT_ENTRY(Lower_Privilege_Transfer_Trap, 0x5e00)
	TRAP(34, cr.ifa)
IVT_END(Lower_Privilege_Transfer_Trap)

IVT_ENTRY(Taken_Branch_Trap, 0x5f00)
	TRAP(35, cr.ifa)
IVT_END(Taken_Branch_Trap)

IVT_ENTRY(Single_Step_Trap, 0x6000)
	TRAP(36, cr.ifa)
IVT_END(Single_Step_Trap)

IVT_ENTRY(Reserved_6100, 0x6100)
	TRAP(37, cr.ifa)
IVT_END(Reserved_6100)

IVT_ENTRY(Reserved_6200, 0x6200)
	TRAP(38, cr.ifa)
IVT_END(Reserved_6200)

IVT_ENTRY(Reserved_6300, 0x6300)
	TRAP(39, cr.ifa)
IVT_END(Reserved_6300)

IVT_ENTRY(Reserved_6400, 0x6400)
	TRAP(40, cr.ifa)
IVT_END(Reserved_6400)

IVT_ENTRY(Reserved_6500, 0x6500)
	TRAP(41, cr.ifa)
IVT_END(Reserved_6500)

IVT_ENTRY(Reserved_6600, 0x6600)
	TRAP(42, cr.ifa)
IVT_END(Reserved_6600)

IVT_ENTRY(Reserved_6700, 0x6700)
	TRAP(43, cr.ifa)
IVT_END(Reserved_6700)

IVT_ENTRY(Reserved_6800, 0x6800)
	TRAP(44, cr.ifa)
IVT_END(Reserved_6800)

IVT_ENTRY(IA_32_Exception, 0x6900)
	TRAP(45, cr.ifa)
IVT_END(IA_32_Exception)

IVT_ENTRY(IA_32_Intercept, 0x6a00)
	TRAP(46, cr.iim)
IVT_END(IA_32_Intercept)

IVT_ENTRY(IA_32_Interrupt, 0x6b00)
	TRAP(47, cr.ifa)
IVT_END(IA_32_Interrupt)

IVT_ENTRY(Reserved_6c00, 0x6c00)
	TRAP(48, cr.ifa)
IVT_END(Reserved_6c00)

IVT_ENTRY(Reserved_6d00, 0x6d00)
	TRAP(49, cr.ifa)
IVT_END(Reserved_6d00)

IVT_ENTRY(Reserved_6e00, 0x6e00)
	TRAP(50, cr.ifa)
IVT_END(Reserved_6e00)

IVT_ENTRY(Reserved_6f00, 0x6f00)
	TRAP(51, cr.ifa)
IVT_END(Reserved_6f00)

IVT_ENTRY(Reserved_7000, 0x7000)
	TRAP(52, cr.ifa)
IVT_END(Reserved_7000)

IVT_ENTRY(Reserved_7100, 0x7100)
	TRAP(53, cr.ifa)
IVT_END(Reserved_7100)

IVT_ENTRY(Reserved_7200, 0x7200)
	TRAP(54, cr.ifa)
IVT_END(Reserved_7200)

IVT_ENTRY(Reserved_7300, 0x7300)
	TRAP(55, cr.ifa)
IVT_END(Reserved_7300)

IVT_ENTRY(Reserved_7400, 0x7400)
	TRAP(56, cr.ifa)
IVT_END(Reserved_7400)

IVT_ENTRY(Reserved_7500, 0x7500)
	TRAP(57, cr.ifa)
IVT_END(Reserved_7500)

IVT_ENTRY(Reserved_7600, 0x7600)
	TRAP(58, cr.ifa)
IVT_END(Reserved_7600)

IVT_ENTRY(Reserved_7700, 0x7700)
	TRAP(59, cr.ifa)
IVT_END(Reserved_7700)

IVT_ENTRY(Reserved_7800, 0x7800)
	TRAP(60, cr.ifa)
IVT_END(Reserved_7800)

IVT_ENTRY(Reserved_7900, 0x7900)
	TRAP(61, cr.ifa)
IVT_END(Reserved_7900)

IVT_ENTRY(Reserved_7a00, 0x7a00)
	TRAP(62, cr.ifa)
IVT_END(Reserved_7a00)

IVT_ENTRY(Reserved_7b00, 0x7b00)
	TRAP(63, cr.ifa)
IVT_END(Reserved_7b00)

IVT_ENTRY(Reserved_7c00, 0x7c00)
	TRAP(64, cr.ifa)
IVT_END(Reserved_7c00)

IVT_ENTRY(Reserved_7d00, 0x7d00)
	TRAP(65, cr.ifa)
IVT_END(Reserved_7d00)

IVT_ENTRY(Reserved_7e00, 0x7e00)
	TRAP(66, cr.ifa)
IVT_END(Reserved_7e00)

IVT_ENTRY(Reserved_7f00, 0x7f00)
	TRAP(67, cr.ifa)
IVT_END(Reserved_7f00)