| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | // | 
|  | 2 | // assembly portion of the IA64 MCA handling | 
|  | 3 | // | 
|  | 4 | // Mods by cfleck to integrate into kernel build | 
|  | 5 | // 00/03/15 davidm Added various stop bits to get a clean compile | 
|  | 6 | // | 
|  | 7 | // 00/03/29 cfleck Added code to save INIT handoff state in pt_regs format, switch to temp | 
|  | 8 | //		   kstack, switch modes, jump to C INIT handler | 
|  | 9 | // | 
|  | 10 | // 02/01/04 J.Hall <jenna.s.hall@intel.com> | 
|  | 11 | //		   Before entering virtual mode code: | 
|  | 12 | //		   1. Check for TLB CPU error | 
|  | 13 | //		   2. Restore current thread pointer to kr6 | 
|  | 14 | //		   3. Move stack ptr 16 bytes to conform to C calling convention | 
|  | 15 | // | 
|  | 16 | // 04/11/12 Russ Anderson <rja@sgi.com> | 
|  | 17 | //		   Added per cpu MCA/INIT stack save areas. | 
|  | 18 | // | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 19 | // 12/08/05 Keith Owens <kaos@sgi.com> | 
|  | 20 | //		   Use per cpu MCA/INIT stacks for all data. | 
|  | 21 | // | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 22 | #include <linux/threads.h> | 
|  | 23 |  | 
|  | 24 | #include <asm/asmmacro.h> | 
|  | 25 | #include <asm/pgtable.h> | 
|  | 26 | #include <asm/processor.h> | 
|  | 27 | #include <asm/mca_asm.h> | 
|  | 28 | #include <asm/mca.h> | 
|  | 29 |  | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 30 | #include "entry.h" | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 31 |  | 
|  | 32 | #define GET_IA64_MCA_DATA(reg)						\ | 
|  | 33 | GET_THIS_PADDR(reg, ia64_mca_data)				\ | 
|  | 34 | ;;								\ | 
|  | 35 | ld8 reg=[reg] | 
|  | 36 |  | 
| Ashok Raj | b8d8b88 | 2005-04-22 14:44:40 -0700 | [diff] [blame] | 37 | .global ia64_do_tlb_purge | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 38 | .global ia64_os_mca_dispatch | 
|  | 39 | .global ia64_os_init_dispatch_monarch | 
|  | 40 | .global ia64_os_init_dispatch_slave | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 41 |  | 
|  | 42 | .text | 
|  | 43 | .align 16 | 
|  | 44 |  | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 45 | //StartMain//////////////////////////////////////////////////////////////////// | 
|  | 46 |  | 
| Ashok Raj | b8d8b88 | 2005-04-22 14:44:40 -0700 | [diff] [blame] | 47 | /* | 
|  | 48 | * Just the TLB purge part is moved to a separate function | 
|  | 49 | * so we can re-use the code for cpu hotplug code as well | 
|  | 50 | * Caller should now setup b1, so we can branch once the | 
|  | 51 | * tlb flush is complete. | 
|  | 52 | */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 53 |  | 
| Ashok Raj | b8d8b88 | 2005-04-22 14:44:40 -0700 | [diff] [blame] | 54 | ia64_do_tlb_purge: | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 55 | #define O(member)	IA64_CPUINFO_##member##_OFFSET | 
|  | 56 |  | 
|  | 57 | GET_THIS_PADDR(r2, cpu_info)	// load phys addr of cpu_info into r2 | 
|  | 58 | ;; | 
|  | 59 | addl r17=O(PTCE_STRIDE),r2 | 
|  | 60 | addl r2=O(PTCE_BASE),r2 | 
|  | 61 | ;; | 
|  | 62 | ld8 r18=[r2],(O(PTCE_COUNT)-O(PTCE_BASE));;	// r18=ptce_base | 
|  | 63 | ld4 r19=[r2],4					// r19=ptce_count[0] | 
|  | 64 | ld4 r21=[r17],4					// r21=ptce_stride[0] | 
|  | 65 | ;; | 
|  | 66 | ld4 r20=[r2]					// r20=ptce_count[1] | 
|  | 67 | ld4 r22=[r17]					// r22=ptce_stride[1] | 
|  | 68 | mov r24=0 | 
|  | 69 | ;; | 
|  | 70 | adds r20=-1,r20 | 
|  | 71 | ;; | 
|  | 72 | #undef O | 
|  | 73 |  | 
|  | 74 | 2: | 
|  | 75 | cmp.ltu p6,p7=r24,r19 | 
|  | 76 | (p7)	br.cond.dpnt.few 4f | 
|  | 77 | mov ar.lc=r20 | 
|  | 78 | 3: | 
|  | 79 | ptc.e r18 | 
|  | 80 | ;; | 
|  | 81 | add r18=r22,r18 | 
|  | 82 | br.cloop.sptk.few 3b | 
|  | 83 | ;; | 
|  | 84 | add r18=r21,r18 | 
|  | 85 | add r24=1,r24 | 
|  | 86 | ;; | 
|  | 87 | br.sptk.few 2b | 
|  | 88 | 4: | 
|  | 89 | srlz.i 			// srlz.i implies srlz.d | 
|  | 90 | ;; | 
|  | 91 |  | 
|  | 92 | // Now purge addresses formerly mapped by TR registers | 
|  | 93 | // 1. Purge ITR&DTR for kernel. | 
|  | 94 | movl r16=KERNEL_START | 
|  | 95 | mov r18=KERNEL_TR_PAGE_SHIFT<<2 | 
|  | 96 | ;; | 
|  | 97 | ptr.i r16, r18 | 
|  | 98 | ptr.d r16, r18 | 
|  | 99 | ;; | 
|  | 100 | srlz.i | 
|  | 101 | ;; | 
|  | 102 | srlz.d | 
|  | 103 | ;; | 
|  | 104 | // 2. Purge DTR for PERCPU data. | 
|  | 105 | movl r16=PERCPU_ADDR | 
|  | 106 | mov r18=PERCPU_PAGE_SHIFT<<2 | 
|  | 107 | ;; | 
|  | 108 | ptr.d r16,r18 | 
|  | 109 | ;; | 
|  | 110 | srlz.d | 
|  | 111 | ;; | 
|  | 112 | // 3. Purge ITR for PAL code. | 
|  | 113 | GET_THIS_PADDR(r2, ia64_mca_pal_base) | 
|  | 114 | ;; | 
|  | 115 | ld8 r16=[r2] | 
|  | 116 | mov r18=IA64_GRANULE_SHIFT<<2 | 
|  | 117 | ;; | 
|  | 118 | ptr.i r16,r18 | 
|  | 119 | ;; | 
|  | 120 | srlz.i | 
|  | 121 | ;; | 
|  | 122 | // 4. Purge DTR for stack. | 
|  | 123 | mov r16=IA64_KR(CURRENT_STACK) | 
|  | 124 | ;; | 
|  | 125 | shl r16=r16,IA64_GRANULE_SHIFT | 
|  | 126 | movl r19=PAGE_OFFSET | 
|  | 127 | ;; | 
|  | 128 | add r16=r19,r16 | 
|  | 129 | mov r18=IA64_GRANULE_SHIFT<<2 | 
|  | 130 | ;; | 
|  | 131 | ptr.d r16,r18 | 
|  | 132 | ;; | 
|  | 133 | srlz.i | 
|  | 134 | ;; | 
| Ashok Raj | b8d8b88 | 2005-04-22 14:44:40 -0700 | [diff] [blame] | 135 | // Now branch away to caller. | 
|  | 136 | br.sptk.many b1 | 
|  | 137 | ;; | 
|  | 138 |  | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 139 | //EndMain////////////////////////////////////////////////////////////////////// | 
| Ashok Raj | b8d8b88 | 2005-04-22 14:44:40 -0700 | [diff] [blame] | 140 |  | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 141 | //StartMain//////////////////////////////////////////////////////////////////// | 
|  | 142 |  | 
|  | 143 | ia64_os_mca_dispatch: | 
| Ashok Raj | b8d8b88 | 2005-04-22 14:44:40 -0700 | [diff] [blame] | 144 | // Serialize all MCA processing | 
|  | 145 | mov	r3=1;; | 
|  | 146 | LOAD_PHYSICAL(p0,r2,ia64_mca_serialize);; | 
|  | 147 | ia64_os_mca_spin: | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 148 | xchg4	r4=[r2],r3;; | 
| Ashok Raj | b8d8b88 | 2005-04-22 14:44:40 -0700 | [diff] [blame] | 149 | cmp.ne	p6,p0=r4,r0 | 
|  | 150 | (p6)	br ia64_os_mca_spin | 
|  | 151 |  | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 152 | mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET	// use the MCA stack | 
|  | 153 | LOAD_PHYSICAL(p0,r2,1f)			// return address | 
|  | 154 | mov r19=1				// All MCA events are treated as monarch (for now) | 
|  | 155 | br.sptk ia64_state_save			// save the state that is not in minstate | 
|  | 156 | 1: | 
|  | 157 |  | 
|  | 158 | GET_IA64_MCA_DATA(r2) | 
|  | 159 | // Using MCA stack, struct ia64_sal_os_state, variable proc_state_param | 
| Ashok Raj | b8d8b88 | 2005-04-22 14:44:40 -0700 | [diff] [blame] | 160 | ;; | 
| Keith Owens | d270acb | 2006-04-07 18:08:11 +1000 | [diff] [blame] | 161 | add r3=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SOS_OFFSET+SOS(PROC_STATE_PARAM), r2 | 
| Ashok Raj | b8d8b88 | 2005-04-22 14:44:40 -0700 | [diff] [blame] | 162 | ;; | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 163 | ld8 r18=[r3]				// Get processor state parameter on existing PALE_CHECK. | 
| Ashok Raj | b8d8b88 | 2005-04-22 14:44:40 -0700 | [diff] [blame] | 164 | ;; | 
|  | 165 | tbit.nz p6,p7=r18,60 | 
|  | 166 | (p7)	br.spnt done_tlb_purge_and_reload | 
|  | 167 |  | 
|  | 168 | // The following code purges TC and TR entries. Then reload all TC entries. | 
|  | 169 | // Purge percpu data TC entries. | 
|  | 170 | begin_tlb_purge_and_reload: | 
|  | 171 | movl r18=ia64_reload_tr;; | 
|  | 172 | LOAD_PHYSICAL(p0,r18,ia64_reload_tr);; | 
|  | 173 | mov b1=r18;; | 
|  | 174 | br.sptk.many ia64_do_tlb_purge;; | 
|  | 175 |  | 
|  | 176 | ia64_reload_tr: | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 177 | // Finally reload the TR registers. | 
|  | 178 | // 1. Reload DTR/ITR registers for kernel. | 
|  | 179 | mov r18=KERNEL_TR_PAGE_SHIFT<<2 | 
|  | 180 | movl r17=KERNEL_START | 
|  | 181 | ;; | 
|  | 182 | mov cr.itir=r18 | 
|  | 183 | mov cr.ifa=r17 | 
|  | 184 | mov r16=IA64_TR_KERNEL | 
|  | 185 | mov r19=ip | 
|  | 186 | movl r18=PAGE_KERNEL | 
|  | 187 | ;; | 
|  | 188 | dep r17=0,r19,0, KERNEL_TR_PAGE_SHIFT | 
|  | 189 | ;; | 
|  | 190 | or r18=r17,r18 | 
|  | 191 | ;; | 
|  | 192 | itr.i itr[r16]=r18 | 
|  | 193 | ;; | 
|  | 194 | itr.d dtr[r16]=r18 | 
|  | 195 | ;; | 
|  | 196 | srlz.i | 
|  | 197 | srlz.d | 
|  | 198 | ;; | 
|  | 199 | // 2. Reload DTR register for PERCPU data. | 
|  | 200 | GET_THIS_PADDR(r2, ia64_mca_per_cpu_pte) | 
|  | 201 | ;; | 
|  | 202 | movl r16=PERCPU_ADDR		// vaddr | 
|  | 203 | movl r18=PERCPU_PAGE_SHIFT<<2 | 
|  | 204 | ;; | 
|  | 205 | mov cr.itir=r18 | 
|  | 206 | mov cr.ifa=r16 | 
|  | 207 | ;; | 
|  | 208 | ld8 r18=[r2]			// load per-CPU PTE | 
|  | 209 | mov r16=IA64_TR_PERCPU_DATA; | 
|  | 210 | ;; | 
|  | 211 | itr.d dtr[r16]=r18 | 
|  | 212 | ;; | 
|  | 213 | srlz.d | 
|  | 214 | ;; | 
|  | 215 | // 3. Reload ITR for PAL code. | 
|  | 216 | GET_THIS_PADDR(r2, ia64_mca_pal_pte) | 
|  | 217 | ;; | 
|  | 218 | ld8 r18=[r2]			// load PAL PTE | 
|  | 219 | ;; | 
|  | 220 | GET_THIS_PADDR(r2, ia64_mca_pal_base) | 
|  | 221 | ;; | 
|  | 222 | ld8 r16=[r2]			// load PAL vaddr | 
|  | 223 | mov r19=IA64_GRANULE_SHIFT<<2 | 
|  | 224 | ;; | 
|  | 225 | mov cr.itir=r19 | 
|  | 226 | mov cr.ifa=r16 | 
|  | 227 | mov r20=IA64_TR_PALCODE | 
|  | 228 | ;; | 
|  | 229 | itr.i itr[r20]=r18 | 
|  | 230 | ;; | 
|  | 231 | srlz.i | 
|  | 232 | ;; | 
|  | 233 | // 4. Reload DTR for stack. | 
|  | 234 | mov r16=IA64_KR(CURRENT_STACK) | 
|  | 235 | ;; | 
|  | 236 | shl r16=r16,IA64_GRANULE_SHIFT | 
|  | 237 | movl r19=PAGE_OFFSET | 
|  | 238 | ;; | 
|  | 239 | add r18=r19,r16 | 
|  | 240 | movl r20=PAGE_KERNEL | 
|  | 241 | ;; | 
|  | 242 | add r16=r20,r16 | 
|  | 243 | mov r19=IA64_GRANULE_SHIFT<<2 | 
|  | 244 | ;; | 
|  | 245 | mov cr.itir=r19 | 
|  | 246 | mov cr.ifa=r18 | 
|  | 247 | mov r20=IA64_TR_CURRENT_STACK | 
|  | 248 | ;; | 
|  | 249 | itr.d dtr[r20]=r16 | 
|  | 250 | ;; | 
|  | 251 | srlz.d | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 252 |  | 
|  | 253 | done_tlb_purge_and_reload: | 
|  | 254 |  | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 255 | // switch to per cpu MCA stack | 
|  | 256 | mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET	// use the MCA stack | 
|  | 257 | LOAD_PHYSICAL(p0,r2,1f)			// return address | 
|  | 258 | br.sptk ia64_new_stack | 
|  | 259 | 1: | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 260 |  | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 261 | // everything saved, now we can set the kernel registers | 
|  | 262 | mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET	// use the MCA stack | 
|  | 263 | LOAD_PHYSICAL(p0,r2,1f)			// return address | 
|  | 264 | br.sptk ia64_set_kernel_registers | 
|  | 265 | 1: | 
|  | 266 |  | 
|  | 267 | // This must be done in physical mode | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 268 | GET_IA64_MCA_DATA(r2) | 
|  | 269 | ;; | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 270 | mov r7=r2 | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 271 |  | 
|  | 272 | // Enter virtual mode from physical mode | 
|  | 273 | VIRTUAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_begin, r4) | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 274 |  | 
|  | 275 | // This code returns to SAL via SOS r2, in general SAL has no unwind | 
|  | 276 | // data.  To get a clean termination when backtracing the C MCA/INIT | 
|  | 277 | // handler, set a dummy return address of 0 in this routine.  That | 
|  | 278 | // requires that ia64_os_mca_virtual_begin be a global function. | 
|  | 279 | ENTRY(ia64_os_mca_virtual_begin) | 
|  | 280 | .prologue | 
|  | 281 | .save rp,r0 | 
|  | 282 | .body | 
|  | 283 |  | 
|  | 284 | mov ar.rsc=3				// set eager mode for C handler | 
|  | 285 | mov r2=r7				// see GET_IA64_MCA_DATA above | 
|  | 286 | ;; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 287 |  | 
|  | 288 | // Call virtual mode handler | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 289 | alloc r14=ar.pfs,0,0,3,0 | 
|  | 290 | ;; | 
|  | 291 | DATA_PA_TO_VA(r2,r7) | 
|  | 292 | ;; | 
|  | 293 | add out0=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_PT_REGS_OFFSET, r2 | 
|  | 294 | add out1=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SWITCH_STACK_OFFSET, r2 | 
|  | 295 | add out2=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SOS_OFFSET, r2 | 
|  | 296 | br.call.sptk.many    b0=ia64_mca_handler | 
|  | 297 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 298 | // Revert back to physical mode before going back to SAL | 
|  | 299 | PHYSICAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_end, r4) | 
|  | 300 | ia64_os_mca_virtual_end: | 
|  | 301 |  | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 302 | END(ia64_os_mca_virtual_begin) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 303 |  | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 304 | // switch back to previous stack | 
|  | 305 | alloc r14=ar.pfs,0,0,0,0		// remove the MCA handler frame | 
|  | 306 | mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET	// use the MCA stack | 
|  | 307 | LOAD_PHYSICAL(p0,r2,1f)			// return address | 
|  | 308 | br.sptk ia64_old_stack | 
|  | 309 | 1: | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 310 |  | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 311 | mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET	// use the MCA stack | 
|  | 312 | LOAD_PHYSICAL(p0,r2,1f)			// return address | 
|  | 313 | br.sptk ia64_state_restore		// restore the SAL state | 
|  | 314 | 1: | 
|  | 315 |  | 
|  | 316 | mov		b0=r12			// SAL_CHECK return address | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 317 |  | 
|  | 318 | // release lock | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 319 | LOAD_PHYSICAL(p0,r3,ia64_mca_serialize);; | 
|  | 320 | st4.rel		[r3]=r0 | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 321 |  | 
|  | 322 | br		b0 | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 323 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 324 | //EndMain////////////////////////////////////////////////////////////////////// | 
|  | 325 |  | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 326 | //StartMain//////////////////////////////////////////////////////////////////// | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 327 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 328 | // | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 329 | // SAL to OS entry point for INIT on all processors.  This has been defined for | 
|  | 330 | // registration purposes with SAL as a part of ia64_mca_init.  Monarch and | 
|  | 331 | // slave INIT have identical processing, except for the value of the | 
|  | 332 | // sos->monarch flag in r19. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 333 | // | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 334 |  | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 335 | ia64_os_init_dispatch_monarch: | 
|  | 336 | mov r19=1				// Bow, bow, ye lower middle classes! | 
|  | 337 | br.sptk ia64_os_init_dispatch | 
|  | 338 |  | 
|  | 339 | ia64_os_init_dispatch_slave: | 
|  | 340 | mov r19=0				// <igor>yeth, mathter</igor> | 
|  | 341 |  | 
|  | 342 | ia64_os_init_dispatch: | 
|  | 343 |  | 
|  | 344 | mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET	// use the INIT stack | 
|  | 345 | LOAD_PHYSICAL(p0,r2,1f)			// return address | 
|  | 346 | br.sptk ia64_state_save			// save the state that is not in minstate | 
|  | 347 | 1: | 
|  | 348 |  | 
|  | 349 | // switch to per cpu INIT stack | 
|  | 350 | mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET	// use the INIT stack | 
|  | 351 | LOAD_PHYSICAL(p0,r2,1f)			// return address | 
|  | 352 | br.sptk ia64_new_stack | 
|  | 353 | 1: | 
|  | 354 |  | 
|  | 355 | // everything saved, now we can set the kernel registers | 
|  | 356 | mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET	// use the INIT stack | 
|  | 357 | LOAD_PHYSICAL(p0,r2,1f)			// return address | 
|  | 358 | br.sptk ia64_set_kernel_registers | 
|  | 359 | 1: | 
|  | 360 |  | 
|  | 361 | // This must be done in physical mode | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 362 | GET_IA64_MCA_DATA(r2) | 
|  | 363 | ;; | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 364 | mov r7=r2 | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 365 |  | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 366 | // Enter virtual mode from physical mode | 
|  | 367 | VIRTUAL_MODE_ENTER(r2, r3, ia64_os_init_virtual_begin, r4) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 368 |  | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 369 | // This code returns to SAL via SOS r2, in general SAL has no unwind | 
|  | 370 | // data.  To get a clean termination when backtracing the C MCA/INIT | 
|  | 371 | // handler, set a dummy return address of 0 in this routine.  That | 
|  | 372 | // requires that ia64_os_init_virtual_begin be a global function. | 
|  | 373 | ENTRY(ia64_os_init_virtual_begin) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 374 | .prologue | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 375 | .save rp,r0 | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 376 | .body | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 377 |  | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 378 | mov ar.rsc=3				// set eager mode for C handler | 
|  | 379 | mov r2=r7				// see GET_IA64_MCA_DATA above | 
|  | 380 | ;; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 381 |  | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 382 | // Call virtual mode handler | 
|  | 383 | alloc r14=ar.pfs,0,0,3,0 | 
|  | 384 | ;; | 
|  | 385 | DATA_PA_TO_VA(r2,r7) | 
|  | 386 | ;; | 
|  | 387 | add out0=IA64_MCA_CPU_INIT_STACK_OFFSET+MCA_PT_REGS_OFFSET, r2 | 
|  | 388 | add out1=IA64_MCA_CPU_INIT_STACK_OFFSET+MCA_SWITCH_STACK_OFFSET, r2 | 
|  | 389 | add out2=IA64_MCA_CPU_INIT_STACK_OFFSET+MCA_SOS_OFFSET, r2 | 
|  | 390 | br.call.sptk.many    b0=ia64_init_handler | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 391 |  | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 392 | // Revert back to physical mode before going back to SAL | 
|  | 393 | PHYSICAL_MODE_ENTER(r2, r3, ia64_os_init_virtual_end, r4) | 
|  | 394 | ia64_os_init_virtual_end: | 
|  | 395 |  | 
|  | 396 | END(ia64_os_init_virtual_begin) | 
|  | 397 |  | 
|  | 398 | mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET	// use the INIT stack | 
|  | 399 | LOAD_PHYSICAL(p0,r2,1f)			// return address | 
|  | 400 | br.sptk ia64_state_restore		// restore the SAL state | 
|  | 401 | 1: | 
|  | 402 |  | 
|  | 403 | // switch back to previous stack | 
|  | 404 | alloc r14=ar.pfs,0,0,0,0		// remove the INIT handler frame | 
|  | 405 | mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET	// use the INIT stack | 
|  | 406 | LOAD_PHYSICAL(p0,r2,1f)			// return address | 
|  | 407 | br.sptk ia64_old_stack | 
|  | 408 | 1: | 
|  | 409 |  | 
|  | 410 | mov		b0=r12			// SAL_CHECK return address | 
|  | 411 | br		b0 | 
|  | 412 |  | 
|  | 413 | //EndMain////////////////////////////////////////////////////////////////////// | 
|  | 414 |  | 
|  | 415 | // common defines for the stubs | 
|  | 416 | #define	ms		r4 | 
|  | 417 | #define	regs		r5 | 
|  | 418 | #define	temp1		r2	/* careful, it overlaps with input registers */ | 
|  | 419 | #define	temp2		r3	/* careful, it overlaps with input registers */ | 
|  | 420 | #define	temp3		r7 | 
|  | 421 | #define	temp4		r14 | 
|  | 422 |  | 
|  | 423 |  | 
|  | 424 | //++ | 
|  | 425 | // Name: | 
|  | 426 | //	ia64_state_save() | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 427 | // | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 428 | // Stub Description: | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 429 | // | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 430 | //	Save the state that is not in minstate.  This is sensitive to the layout of | 
|  | 431 | //	struct ia64_sal_os_state in mca.h. | 
|  | 432 | // | 
|  | 433 | //	r2 contains the return address, r3 contains either | 
|  | 434 | //	IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET. | 
|  | 435 | // | 
|  | 436 | //	The OS to SAL section of struct ia64_sal_os_state is set to a default | 
|  | 437 | //	value of cold boot (MCA) or warm boot (INIT) and return to the same | 
|  | 438 | //	context.  ia64_sal_os_state is also used to hold some registers that | 
|  | 439 | //	need to be saved and restored across the stack switches. | 
|  | 440 | // | 
|  | 441 | //	Most input registers to this stub come from PAL/SAL | 
|  | 442 | //	r1  os gp, physical | 
|  | 443 | //	r8  pal_proc entry point | 
|  | 444 | //	r9  sal_proc entry point | 
|  | 445 | //	r10 sal gp | 
|  | 446 | //	r11 MCA - rendevzous state, INIT - reason code | 
|  | 447 | //	r12 sal return address | 
|  | 448 | //	r17 pal min_state | 
|  | 449 | //	r18 processor state parameter | 
|  | 450 | //	r19 monarch flag, set by the caller of this routine | 
|  | 451 | // | 
|  | 452 | //	In addition to the SAL to OS state, this routine saves all the | 
|  | 453 | //	registers that appear in struct pt_regs and struct switch_stack, | 
|  | 454 | //	excluding those that are already in the PAL minstate area.  This | 
|  | 455 | //	results in a partial pt_regs and switch_stack, the C code copies the | 
|  | 456 | //	remaining registers from PAL minstate to pt_regs and switch_stack.  The | 
|  | 457 | //	resulting structures contain all the state of the original process when | 
|  | 458 | //	MCA/INIT occurred. | 
|  | 459 | // | 
|  | 460 | //-- | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 461 |  | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 462 | ia64_state_save: | 
|  | 463 | add regs=MCA_SOS_OFFSET, r3 | 
|  | 464 | add ms=MCA_SOS_OFFSET+8, r3 | 
|  | 465 | mov b0=r2		// save return address | 
|  | 466 | cmp.eq p1,p2=IA64_MCA_CPU_MCA_STACK_OFFSET, r3 | 
|  | 467 | ;; | 
|  | 468 | GET_IA64_MCA_DATA(temp2) | 
|  | 469 | ;; | 
|  | 470 | add temp1=temp2, regs	// struct ia64_sal_os_state on MCA or INIT stack | 
|  | 471 | add temp2=temp2, ms	// struct ia64_sal_os_state+8 on MCA or INIT stack | 
|  | 472 | ;; | 
|  | 473 | mov regs=temp1		// save the start of sos | 
|  | 474 | st8 [temp1]=r1,16	// os_gp | 
|  | 475 | st8 [temp2]=r8,16	// pal_proc | 
|  | 476 | ;; | 
|  | 477 | st8 [temp1]=r9,16	// sal_proc | 
|  | 478 | st8 [temp2]=r11,16	// rv_rc | 
|  | 479 | mov r11=cr.iipa | 
|  | 480 | ;; | 
| Keith Owens | d270acb | 2006-04-07 18:08:11 +1000 | [diff] [blame] | 481 | st8 [temp1]=r18		// proc_state_param | 
|  | 482 | st8 [temp2]=r19		// monarch | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 483 | mov r6=IA64_KR(CURRENT) | 
| Keith Owens | d270acb | 2006-04-07 18:08:11 +1000 | [diff] [blame] | 484 | add temp1=SOS(SAL_RA), regs | 
|  | 485 | add temp2=SOS(SAL_GP), regs | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 486 | ;; | 
|  | 487 | st8 [temp1]=r12,16	// sal_ra | 
|  | 488 | st8 [temp2]=r10,16	// sal_gp | 
|  | 489 | mov r12=cr.isr | 
|  | 490 | ;; | 
|  | 491 | st8 [temp1]=r17,16	// pal_min_state | 
|  | 492 | st8 [temp2]=r6,16	// prev_IA64_KR_CURRENT | 
| Keith Owens | 20bb868 | 2005-09-22 18:49:15 +1000 | [diff] [blame] | 493 | mov r6=IA64_KR(CURRENT_STACK) | 
|  | 494 | ;; | 
|  | 495 | st8 [temp1]=r6,16	// prev_IA64_KR_CURRENT_STACK | 
|  | 496 | st8 [temp2]=r0,16	// prev_task, starts off as NULL | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 497 | mov r6=cr.ifa | 
|  | 498 | ;; | 
| Keith Owens | 20bb868 | 2005-09-22 18:49:15 +1000 | [diff] [blame] | 499 | st8 [temp1]=r12,16	// cr.isr | 
|  | 500 | st8 [temp2]=r6,16	// cr.ifa | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 501 | mov r12=cr.itir | 
|  | 502 | ;; | 
| Keith Owens | 20bb868 | 2005-09-22 18:49:15 +1000 | [diff] [blame] | 503 | st8 [temp1]=r12,16	// cr.itir | 
|  | 504 | st8 [temp2]=r11,16	// cr.iipa | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 505 | mov r12=cr.iim | 
|  | 506 | ;; | 
| Keith Owens | d270acb | 2006-04-07 18:08:11 +1000 | [diff] [blame] | 507 | st8 [temp1]=r12		// cr.iim | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 508 | (p1)	mov r12=IA64_MCA_COLD_BOOT | 
|  | 509 | (p2)	mov r12=IA64_INIT_WARM_BOOT | 
| Keith Owens | 20bb868 | 2005-09-22 18:49:15 +1000 | [diff] [blame] | 510 | mov r6=cr.iha | 
| Keith Owens | d270acb | 2006-04-07 18:08:11 +1000 | [diff] [blame] | 511 | add temp1=SOS(OS_STATUS), regs | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 512 | ;; | 
| Keith Owens | d270acb | 2006-04-07 18:08:11 +1000 | [diff] [blame] | 513 | st8 [temp2]=r6		// cr.iha | 
|  | 514 | add temp2=SOS(CONTEXT), regs | 
| Keith Owens | 20bb868 | 2005-09-22 18:49:15 +1000 | [diff] [blame] | 515 | st8 [temp1]=r12		// os_status, default is cold boot | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 516 | mov r6=IA64_MCA_SAME_CONTEXT | 
|  | 517 | ;; | 
| Keith Owens | 2a79205 | 2006-01-24 12:31:26 +1100 | [diff] [blame] | 518 | st8 [temp2]=r6		// context, default is same context | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 519 |  | 
|  | 520 | // Save the pt_regs data that is not in minstate.  The previous code | 
|  | 521 | // left regs at sos. | 
|  | 522 | add regs=MCA_PT_REGS_OFFSET-MCA_SOS_OFFSET, regs | 
|  | 523 | ;; | 
|  | 524 | add temp1=PT(B6), regs | 
|  | 525 | mov temp3=b6 | 
|  | 526 | mov temp4=b7 | 
|  | 527 | add temp2=PT(B7), regs | 
|  | 528 | ;; | 
|  | 529 | st8 [temp1]=temp3,PT(AR_CSD)-PT(B6)		// save b6 | 
|  | 530 | st8 [temp2]=temp4,PT(AR_SSD)-PT(B7)		// save b7 | 
|  | 531 | mov temp3=ar.csd | 
|  | 532 | mov temp4=ar.ssd | 
|  | 533 | cover						// must be last in group | 
|  | 534 | ;; | 
|  | 535 | st8 [temp1]=temp3,PT(AR_UNAT)-PT(AR_CSD)	// save ar.csd | 
|  | 536 | st8 [temp2]=temp4,PT(AR_PFS)-PT(AR_SSD)		// save ar.ssd | 
|  | 537 | mov temp3=ar.unat | 
|  | 538 | mov temp4=ar.pfs | 
|  | 539 | ;; | 
|  | 540 | st8 [temp1]=temp3,PT(AR_RNAT)-PT(AR_UNAT)	// save ar.unat | 
|  | 541 | st8 [temp2]=temp4,PT(AR_BSPSTORE)-PT(AR_PFS)	// save ar.pfs | 
|  | 542 | mov temp3=ar.rnat | 
|  | 543 | mov temp4=ar.bspstore | 
|  | 544 | ;; | 
|  | 545 | st8 [temp1]=temp3,PT(LOADRS)-PT(AR_RNAT)	// save ar.rnat | 
|  | 546 | st8 [temp2]=temp4,PT(AR_FPSR)-PT(AR_BSPSTORE)	// save ar.bspstore | 
|  | 547 | mov temp3=ar.bsp | 
|  | 548 | ;; | 
|  | 549 | sub temp3=temp3, temp4	// ar.bsp - ar.bspstore | 
|  | 550 | mov temp4=ar.fpsr | 
|  | 551 | ;; | 
|  | 552 | shl temp3=temp3,16	// compute ar.rsc to be used for "loadrs" | 
|  | 553 | ;; | 
|  | 554 | st8 [temp1]=temp3,PT(AR_CCV)-PT(LOADRS)		// save loadrs | 
|  | 555 | st8 [temp2]=temp4,PT(F6)-PT(AR_FPSR)		// save ar.fpsr | 
|  | 556 | mov temp3=ar.ccv | 
|  | 557 | ;; | 
|  | 558 | st8 [temp1]=temp3,PT(F7)-PT(AR_CCV)		// save ar.ccv | 
|  | 559 | stf.spill [temp2]=f6,PT(F8)-PT(F6) | 
|  | 560 | ;; | 
|  | 561 | stf.spill [temp1]=f7,PT(F9)-PT(F7) | 
|  | 562 | stf.spill [temp2]=f8,PT(F10)-PT(F8) | 
|  | 563 | ;; | 
|  | 564 | stf.spill [temp1]=f9,PT(F11)-PT(F9) | 
|  | 565 | stf.spill [temp2]=f10 | 
|  | 566 | ;; | 
|  | 567 | stf.spill [temp1]=f11 | 
|  | 568 |  | 
|  | 569 | // Save the switch_stack data that is not in minstate nor pt_regs.  The | 
|  | 570 | // previous code left regs at pt_regs. | 
|  | 571 | add regs=MCA_SWITCH_STACK_OFFSET-MCA_PT_REGS_OFFSET, regs | 
|  | 572 | ;; | 
|  | 573 | add temp1=SW(F2), regs | 
|  | 574 | add temp2=SW(F3), regs | 
|  | 575 | ;; | 
|  | 576 | stf.spill [temp1]=f2,32 | 
|  | 577 | stf.spill [temp2]=f3,32 | 
|  | 578 | ;; | 
|  | 579 | stf.spill [temp1]=f4,32 | 
|  | 580 | stf.spill [temp2]=f5,32 | 
|  | 581 | ;; | 
|  | 582 | stf.spill [temp1]=f12,32 | 
|  | 583 | stf.spill [temp2]=f13,32 | 
|  | 584 | ;; | 
|  | 585 | stf.spill [temp1]=f14,32 | 
|  | 586 | stf.spill [temp2]=f15,32 | 
|  | 587 | ;; | 
|  | 588 | stf.spill [temp1]=f16,32 | 
|  | 589 | stf.spill [temp2]=f17,32 | 
|  | 590 | ;; | 
|  | 591 | stf.spill [temp1]=f18,32 | 
|  | 592 | stf.spill [temp2]=f19,32 | 
|  | 593 | ;; | 
|  | 594 | stf.spill [temp1]=f20,32 | 
|  | 595 | stf.spill [temp2]=f21,32 | 
|  | 596 | ;; | 
|  | 597 | stf.spill [temp1]=f22,32 | 
|  | 598 | stf.spill [temp2]=f23,32 | 
|  | 599 | ;; | 
|  | 600 | stf.spill [temp1]=f24,32 | 
|  | 601 | stf.spill [temp2]=f25,32 | 
|  | 602 | ;; | 
|  | 603 | stf.spill [temp1]=f26,32 | 
|  | 604 | stf.spill [temp2]=f27,32 | 
|  | 605 | ;; | 
|  | 606 | stf.spill [temp1]=f28,32 | 
|  | 607 | stf.spill [temp2]=f29,32 | 
|  | 608 | ;; | 
|  | 609 | stf.spill [temp1]=f30,SW(B2)-SW(F30) | 
|  | 610 | stf.spill [temp2]=f31,SW(B3)-SW(F31) | 
|  | 611 | mov temp3=b2 | 
|  | 612 | mov temp4=b3 | 
|  | 613 | ;; | 
|  | 614 | st8 [temp1]=temp3,16	// save b2 | 
|  | 615 | st8 [temp2]=temp4,16	// save b3 | 
|  | 616 | mov temp3=b4 | 
|  | 617 | mov temp4=b5 | 
|  | 618 | ;; | 
|  | 619 | st8 [temp1]=temp3,SW(AR_LC)-SW(B4)	// save b4 | 
|  | 620 | st8 [temp2]=temp4	// save b5 | 
|  | 621 | mov temp3=ar.lc | 
|  | 622 | ;; | 
|  | 623 | st8 [temp1]=temp3	// save ar.lc | 
|  | 624 |  | 
|  | 625 | // FIXME: Some proms are incorrectly accessing the minstate area as | 
|  | 626 | // cached data.  The C code uses region 6, uncached virtual.  Ensure | 
|  | 627 | // that there is no cache data lying around for the first 1K of the | 
|  | 628 | // minstate area. | 
|  | 629 | // Remove this code in September 2006, that gives platforms a year to | 
|  | 630 | // fix their proms and get their customers updated. | 
|  | 631 |  | 
|  | 632 | add r1=32*1,r17 | 
|  | 633 | add r2=32*2,r17 | 
|  | 634 | add r3=32*3,r17 | 
|  | 635 | add r4=32*4,r17 | 
|  | 636 | add r5=32*5,r17 | 
|  | 637 | add r6=32*6,r17 | 
|  | 638 | add r7=32*7,r17 | 
|  | 639 | ;; | 
|  | 640 | fc r17 | 
|  | 641 | fc r1 | 
|  | 642 | fc r2 | 
|  | 643 | fc r3 | 
|  | 644 | fc r4 | 
|  | 645 | fc r5 | 
|  | 646 | fc r6 | 
|  | 647 | fc r7 | 
|  | 648 | add r17=32*8,r17 | 
|  | 649 | add r1=32*8,r1 | 
|  | 650 | add r2=32*8,r2 | 
|  | 651 | add r3=32*8,r3 | 
|  | 652 | add r4=32*8,r4 | 
|  | 653 | add r5=32*8,r5 | 
|  | 654 | add r6=32*8,r6 | 
|  | 655 | add r7=32*8,r7 | 
|  | 656 | ;; | 
|  | 657 | fc r17 | 
|  | 658 | fc r1 | 
|  | 659 | fc r2 | 
|  | 660 | fc r3 | 
|  | 661 | fc r4 | 
|  | 662 | fc r5 | 
|  | 663 | fc r6 | 
|  | 664 | fc r7 | 
|  | 665 | add r17=32*8,r17 | 
|  | 666 | add r1=32*8,r1 | 
|  | 667 | add r2=32*8,r2 | 
|  | 668 | add r3=32*8,r3 | 
|  | 669 | add r4=32*8,r4 | 
|  | 670 | add r5=32*8,r5 | 
|  | 671 | add r6=32*8,r6 | 
|  | 672 | add r7=32*8,r7 | 
|  | 673 | ;; | 
|  | 674 | fc r17 | 
|  | 675 | fc r1 | 
|  | 676 | fc r2 | 
|  | 677 | fc r3 | 
|  | 678 | fc r4 | 
|  | 679 | fc r5 | 
|  | 680 | fc r6 | 
|  | 681 | fc r7 | 
|  | 682 | add r17=32*8,r17 | 
|  | 683 | add r1=32*8,r1 | 
|  | 684 | add r2=32*8,r2 | 
|  | 685 | add r3=32*8,r3 | 
|  | 686 | add r4=32*8,r4 | 
|  | 687 | add r5=32*8,r5 | 
|  | 688 | add r6=32*8,r6 | 
|  | 689 | add r7=32*8,r7 | 
|  | 690 | ;; | 
|  | 691 | fc r17 | 
|  | 692 | fc r1 | 
|  | 693 | fc r2 | 
|  | 694 | fc r3 | 
|  | 695 | fc r4 | 
|  | 696 | fc r5 | 
|  | 697 | fc r6 | 
|  | 698 | fc r7 | 
|  | 699 |  | 
|  | 700 | br.sptk b0 | 
|  | 701 |  | 
|  | 702 | //EndStub////////////////////////////////////////////////////////////////////// | 
|  | 703 |  | 
|  | 704 |  | 
|  | 705 | //++ | 
|  | 706 | // Name: | 
|  | 707 | //	ia64_state_restore() | 
|  | 708 | // | 
|  | 709 | // Stub Description: | 
|  | 710 | // | 
|  | 711 | //	Restore the SAL/OS state.  This is sensitive to the layout of struct | 
|  | 712 | //	ia64_sal_os_state in mca.h. | 
|  | 713 | // | 
|  | 714 | //	r2 contains the return address, r3 contains either | 
|  | 715 | //	IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET. | 
|  | 716 | // | 
|  | 717 | //	In addition to the SAL to OS state, this routine restores all the | 
|  | 718 | //	registers that appear in struct pt_regs and struct switch_stack, | 
|  | 719 | //	excluding those in the PAL minstate area. | 
|  | 720 | // | 
|  | 721 | //-- | 
|  | 722 |  | 
|  | 723 | ia64_state_restore: | 
|  | 724 | // Restore the switch_stack data that is not in minstate nor pt_regs. | 
|  | 725 | add regs=MCA_SWITCH_STACK_OFFSET, r3 | 
|  | 726 | mov b0=r2		// save return address | 
|  | 727 | ;; | 
|  | 728 | GET_IA64_MCA_DATA(temp2) | 
|  | 729 | ;; | 
|  | 730 | add regs=temp2, regs | 
|  | 731 | ;; | 
|  | 732 | add temp1=SW(F2), regs | 
|  | 733 | add temp2=SW(F3), regs | 
|  | 734 | ;; | 
|  | 735 | ldf.fill f2=[temp1],32 | 
|  | 736 | ldf.fill f3=[temp2],32 | 
|  | 737 | ;; | 
|  | 738 | ldf.fill f4=[temp1],32 | 
|  | 739 | ldf.fill f5=[temp2],32 | 
|  | 740 | ;; | 
|  | 741 | ldf.fill f12=[temp1],32 | 
|  | 742 | ldf.fill f13=[temp2],32 | 
|  | 743 | ;; | 
|  | 744 | ldf.fill f14=[temp1],32 | 
|  | 745 | ldf.fill f15=[temp2],32 | 
|  | 746 | ;; | 
|  | 747 | ldf.fill f16=[temp1],32 | 
|  | 748 | ldf.fill f17=[temp2],32 | 
|  | 749 | ;; | 
|  | 750 | ldf.fill f18=[temp1],32 | 
|  | 751 | ldf.fill f19=[temp2],32 | 
|  | 752 | ;; | 
|  | 753 | ldf.fill f20=[temp1],32 | 
|  | 754 | ldf.fill f21=[temp2],32 | 
|  | 755 | ;; | 
|  | 756 | ldf.fill f22=[temp1],32 | 
|  | 757 | ldf.fill f23=[temp2],32 | 
|  | 758 | ;; | 
|  | 759 | ldf.fill f24=[temp1],32 | 
|  | 760 | ldf.fill f25=[temp2],32 | 
|  | 761 | ;; | 
|  | 762 | ldf.fill f26=[temp1],32 | 
|  | 763 | ldf.fill f27=[temp2],32 | 
|  | 764 | ;; | 
|  | 765 | ldf.fill f28=[temp1],32 | 
|  | 766 | ldf.fill f29=[temp2],32 | 
|  | 767 | ;; | 
|  | 768 | ldf.fill f30=[temp1],SW(B2)-SW(F30) | 
|  | 769 | ldf.fill f31=[temp2],SW(B3)-SW(F31) | 
|  | 770 | ;; | 
|  | 771 | ld8 temp3=[temp1],16	// restore b2 | 
|  | 772 | ld8 temp4=[temp2],16	// restore b3 | 
|  | 773 | ;; | 
|  | 774 | mov b2=temp3 | 
|  | 775 | mov b3=temp4 | 
|  | 776 | ld8 temp3=[temp1],SW(AR_LC)-SW(B4)	// restore b4 | 
|  | 777 | ld8 temp4=[temp2]	// restore b5 | 
|  | 778 | ;; | 
|  | 779 | mov b4=temp3 | 
|  | 780 | mov b5=temp4 | 
|  | 781 | ld8 temp3=[temp1]	// restore ar.lc | 
|  | 782 | ;; | 
|  | 783 | mov ar.lc=temp3 | 
|  | 784 |  | 
|  | 785 | // Restore the pt_regs data that is not in minstate.  The previous code | 
|  | 786 | // left regs at switch_stack. | 
|  | 787 | add regs=MCA_PT_REGS_OFFSET-MCA_SWITCH_STACK_OFFSET, regs | 
|  | 788 | ;; | 
|  | 789 | add temp1=PT(B6), regs | 
|  | 790 | add temp2=PT(B7), regs | 
|  | 791 | ;; | 
|  | 792 | ld8 temp3=[temp1],PT(AR_CSD)-PT(B6)		// restore b6 | 
|  | 793 | ld8 temp4=[temp2],PT(AR_SSD)-PT(B7)		// restore b7 | 
|  | 794 | ;; | 
|  | 795 | mov b6=temp3 | 
|  | 796 | mov b7=temp4 | 
|  | 797 | ld8 temp3=[temp1],PT(AR_UNAT)-PT(AR_CSD)	// restore ar.csd | 
|  | 798 | ld8 temp4=[temp2],PT(AR_PFS)-PT(AR_SSD)		// restore ar.ssd | 
|  | 799 | ;; | 
|  | 800 | mov ar.csd=temp3 | 
|  | 801 | mov ar.ssd=temp4 | 
|  | 802 | ld8 temp3=[temp1]				// restore ar.unat | 
|  | 803 | add temp1=PT(AR_CCV)-PT(AR_UNAT), temp1 | 
|  | 804 | ld8 temp4=[temp2],PT(AR_FPSR)-PT(AR_PFS)	// restore ar.pfs | 
|  | 805 | ;; | 
|  | 806 | mov ar.unat=temp3 | 
|  | 807 | mov ar.pfs=temp4 | 
|  | 808 | // ar.rnat, ar.bspstore, loadrs are restore in ia64_old_stack. | 
|  | 809 | ld8 temp3=[temp1],PT(F6)-PT(AR_CCV)		// restore ar.ccv | 
|  | 810 | ld8 temp4=[temp2],PT(F7)-PT(AR_FPSR)		// restore ar.fpsr | 
|  | 811 | ;; | 
|  | 812 | mov ar.ccv=temp3 | 
|  | 813 | mov ar.fpsr=temp4 | 
|  | 814 | ldf.fill f6=[temp1],PT(F8)-PT(F6) | 
|  | 815 | ldf.fill f7=[temp2],PT(F9)-PT(F7) | 
|  | 816 | ;; | 
|  | 817 | ldf.fill f8=[temp1],PT(F10)-PT(F8) | 
|  | 818 | ldf.fill f9=[temp2],PT(F11)-PT(F9) | 
|  | 819 | ;; | 
|  | 820 | ldf.fill f10=[temp1] | 
|  | 821 | ldf.fill f11=[temp2] | 
|  | 822 |  | 
|  | 823 | // Restore the SAL to OS state. The previous code left regs at pt_regs. | 
|  | 824 | add regs=MCA_SOS_OFFSET-MCA_PT_REGS_OFFSET, regs | 
|  | 825 | ;; | 
| Keith Owens | d270acb | 2006-04-07 18:08:11 +1000 | [diff] [blame] | 826 | add temp1=SOS(SAL_RA), regs | 
|  | 827 | add temp2=SOS(SAL_GP), regs | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 828 | ;; | 
|  | 829 | ld8 r12=[temp1],16	// sal_ra | 
|  | 830 | ld8 r9=[temp2],16	// sal_gp | 
|  | 831 | ;; | 
| Keith Owens | 20bb868 | 2005-09-22 18:49:15 +1000 | [diff] [blame] | 832 | ld8 r22=[temp1],16	// pal_min_state, virtual | 
| Keith Owens | 8cab7cc | 2006-04-07 16:34:34 +1000 | [diff] [blame] | 833 | ld8 r13=[temp2],16	// prev_IA64_KR_CURRENT | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 834 | ;; | 
| Keith Owens | 20bb868 | 2005-09-22 18:49:15 +1000 | [diff] [blame] | 835 | ld8 r16=[temp1],16	// prev_IA64_KR_CURRENT_STACK | 
|  | 836 | ld8 r20=[temp2],16	// prev_task | 
|  | 837 | ;; | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 838 | ld8 temp3=[temp1],16	// cr.isr | 
|  | 839 | ld8 temp4=[temp2],16	// cr.ifa | 
|  | 840 | ;; | 
|  | 841 | mov cr.isr=temp3 | 
|  | 842 | mov cr.ifa=temp4 | 
|  | 843 | ld8 temp3=[temp1],16	// cr.itir | 
|  | 844 | ld8 temp4=[temp2],16	// cr.iipa | 
|  | 845 | ;; | 
|  | 846 | mov cr.itir=temp3 | 
|  | 847 | mov cr.iipa=temp4 | 
| Keith Owens | d270acb | 2006-04-07 18:08:11 +1000 | [diff] [blame] | 848 | ld8 temp3=[temp1]	// cr.iim | 
|  | 849 | ld8 temp4=[temp2]		// cr.iha | 
|  | 850 | add temp1=SOS(OS_STATUS), regs | 
|  | 851 | add temp2=SOS(CONTEXT), regs | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 852 | ;; | 
|  | 853 | mov cr.iim=temp3 | 
|  | 854 | mov cr.iha=temp4 | 
| Francois Wellenrieter | 8a4b7b6 | 2006-01-13 14:01:01 -0800 | [diff] [blame] | 855 | dep r22=0,r22,62,1	// pal_min_state, physical, uncached | 
| Keith Owens | 8cab7cc | 2006-04-07 16:34:34 +1000 | [diff] [blame] | 856 | mov IA64_KR(CURRENT)=r13 | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 857 | ld8 r8=[temp1]		// os_status | 
|  | 858 | ld8 r10=[temp2]		// context | 
|  | 859 |  | 
| Keith Owens | 20bb868 | 2005-09-22 18:49:15 +1000 | [diff] [blame] | 860 | /* Wire IA64_TR_CURRENT_STACK to the stack that we are resuming to.  To | 
|  | 861 | * avoid any dependencies on the algorithm in ia64_switch_to(), just | 
|  | 862 | * purge any existing CURRENT_STACK mapping and insert the new one. | 
|  | 863 | * | 
| Keith Owens | 8cab7cc | 2006-04-07 16:34:34 +1000 | [diff] [blame] | 864 | * r16 contains prev_IA64_KR_CURRENT_STACK, r13 contains | 
| Keith Owens | 20bb868 | 2005-09-22 18:49:15 +1000 | [diff] [blame] | 865 | * prev_IA64_KR_CURRENT, these values may have been changed by the C | 
|  | 866 | * code.  Do not use r8, r9, r10, r22, they contain values ready for | 
|  | 867 | * the return to SAL. | 
|  | 868 | */ | 
|  | 869 |  | 
|  | 870 | mov r15=IA64_KR(CURRENT_STACK)		// physical granule mapped by IA64_TR_CURRENT_STACK | 
|  | 871 | ;; | 
|  | 872 | shl r15=r15,IA64_GRANULE_SHIFT | 
|  | 873 | ;; | 
|  | 874 | dep r15=-1,r15,61,3			// virtual granule | 
|  | 875 | mov r18=IA64_GRANULE_SHIFT<<2		// for cr.itir.ps | 
|  | 876 | ;; | 
|  | 877 | ptr.d r15,r18 | 
|  | 878 | ;; | 
|  | 879 | srlz.d | 
|  | 880 |  | 
| Keith Owens | 8cab7cc | 2006-04-07 16:34:34 +1000 | [diff] [blame] | 881 | extr.u r19=r13,61,3			// r13 = prev_IA64_KR_CURRENT | 
| Keith Owens | 20bb868 | 2005-09-22 18:49:15 +1000 | [diff] [blame] | 882 | shl r20=r16,IA64_GRANULE_SHIFT		// r16 = prev_IA64_KR_CURRENT_STACK | 
|  | 883 | movl r21=PAGE_KERNEL			// page properties | 
|  | 884 | ;; | 
|  | 885 | mov IA64_KR(CURRENT_STACK)=r16 | 
|  | 886 | cmp.ne p6,p0=RGN_KERNEL,r19		// new stack is in the kernel region? | 
|  | 887 | or r21=r20,r21				// construct PA | page properties | 
|  | 888 | (p6)	br.spnt 1f				// the dreaded cpu 0 idle task in region 5:( | 
|  | 889 | ;; | 
|  | 890 | mov cr.itir=r18 | 
| Keith Owens | 8cab7cc | 2006-04-07 16:34:34 +1000 | [diff] [blame] | 891 | mov cr.ifa=r13 | 
| Keith Owens | 20bb868 | 2005-09-22 18:49:15 +1000 | [diff] [blame] | 892 | mov r20=IA64_TR_CURRENT_STACK | 
|  | 893 | ;; | 
|  | 894 | itr.d dtr[r20]=r21 | 
|  | 895 | ;; | 
|  | 896 | srlz.d | 
|  | 897 | 1: | 
|  | 898 |  | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 899 | br.sptk b0 | 
|  | 900 |  | 
|  | 901 | //EndStub////////////////////////////////////////////////////////////////////// | 
|  | 902 |  | 
|  | 903 |  | 
|  | 904 | //++ | 
|  | 905 | // Name: | 
|  | 906 | //	ia64_new_stack() | 
|  | 907 | // | 
|  | 908 | // Stub Description: | 
|  | 909 | // | 
|  | 910 | //	Switch to the MCA/INIT stack. | 
|  | 911 | // | 
|  | 912 | //	r2 contains the return address, r3 contains either | 
|  | 913 | //	IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET. | 
|  | 914 | // | 
|  | 915 | //	On entry RBS is still on the original stack, this routine switches RBS | 
|  | 916 | //	to use the MCA/INIT stack. | 
|  | 917 | // | 
|  | 918 | //	On entry, sos->pal_min_state is physical, on exit it is virtual. | 
|  | 919 | // | 
|  | 920 | //-- | 
|  | 921 |  | 
|  | 922 | ia64_new_stack: | 
|  | 923 | add regs=MCA_PT_REGS_OFFSET, r3 | 
| Keith Owens | d270acb | 2006-04-07 18:08:11 +1000 | [diff] [blame] | 924 | add temp2=MCA_SOS_OFFSET+SOS(PAL_MIN_STATE), r3 | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 925 | mov b0=r2			// save return address | 
|  | 926 | GET_IA64_MCA_DATA(temp1) | 
|  | 927 | invala | 
|  | 928 | ;; | 
|  | 929 | add temp2=temp2, temp1		// struct ia64_sal_os_state.pal_min_state on MCA or INIT stack | 
|  | 930 | add regs=regs, temp1		// struct pt_regs on MCA or INIT stack | 
|  | 931 | ;; | 
|  | 932 | // Address of minstate area provided by PAL is physical, uncacheable. | 
|  | 933 | // Convert to Linux virtual address in region 6 for C code. | 
|  | 934 | ld8 ms=[temp2]			// pal_min_state, physical | 
|  | 935 | ;; | 
|  | 936 | dep temp1=-1,ms,62,2		// set region 6 | 
|  | 937 | mov temp3=IA64_RBS_OFFSET-MCA_PT_REGS_OFFSET | 
|  | 938 | ;; | 
|  | 939 | st8 [temp2]=temp1		// pal_min_state, virtual | 
|  | 940 |  | 
|  | 941 | add temp4=temp3, regs		// start of bspstore on new stack | 
|  | 942 | ;; | 
|  | 943 | mov ar.bspstore=temp4		// switch RBS to MCA/INIT stack | 
|  | 944 | ;; | 
|  | 945 | flushrs				// must be first in group | 
|  | 946 | br.sptk b0 | 
|  | 947 |  | 
|  | 948 | //EndStub////////////////////////////////////////////////////////////////////// | 
|  | 949 |  | 
|  | 950 |  | 
|  | 951 | //++ | 
|  | 952 | // Name: | 
|  | 953 | //	ia64_old_stack() | 
|  | 954 | // | 
|  | 955 | // Stub Description: | 
|  | 956 | // | 
|  | 957 | //	Switch to the old stack. | 
|  | 958 | // | 
|  | 959 | //	r2 contains the return address, r3 contains either | 
|  | 960 | //	IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET. | 
|  | 961 | // | 
|  | 962 | //	On entry, pal_min_state is virtual, on exit it is physical. | 
|  | 963 | // | 
|  | 964 | //	On entry RBS is on the MCA/INIT stack, this routine switches RBS | 
|  | 965 | //	back to the previous stack. | 
|  | 966 | // | 
|  | 967 | //	The psr is set to all zeroes.  SAL return requires either all zeroes or | 
|  | 968 | //	just psr.mc set.  Leaving psr.mc off allows INIT to be issued if this | 
|  | 969 | //	code does not perform correctly. | 
|  | 970 | // | 
|  | 971 | //	The dirty registers at the time of the event were flushed to the | 
|  | 972 | //	MCA/INIT stack in ia64_pt_regs_save().  Restore the dirty registers | 
|  | 973 | //	before reverting to the previous bspstore. | 
|  | 974 | //-- | 
|  | 975 |  | 
|  | 976 | ia64_old_stack: | 
|  | 977 | add regs=MCA_PT_REGS_OFFSET, r3 | 
|  | 978 | mov b0=r2			// save return address | 
|  | 979 | GET_IA64_MCA_DATA(temp2) | 
|  | 980 | LOAD_PHYSICAL(p0,temp1,1f) | 
|  | 981 | ;; | 
|  | 982 | mov cr.ipsr=r0 | 
|  | 983 | mov cr.ifs=r0 | 
|  | 984 | mov cr.iip=temp1 | 
|  | 985 | ;; | 
|  | 986 | invala | 
|  | 987 | rfi | 
|  | 988 | 1: | 
|  | 989 |  | 
|  | 990 | add regs=regs, temp2		// struct pt_regs on MCA or INIT stack | 
|  | 991 | ;; | 
|  | 992 | add temp1=PT(LOADRS), regs | 
|  | 993 | ;; | 
|  | 994 | ld8 temp2=[temp1],PT(AR_BSPSTORE)-PT(LOADRS)	// restore loadrs | 
|  | 995 | ;; | 
|  | 996 | ld8 temp3=[temp1],PT(AR_RNAT)-PT(AR_BSPSTORE)	// restore ar.bspstore | 
|  | 997 | mov ar.rsc=temp2 | 
|  | 998 | ;; | 
|  | 999 | loadrs | 
|  | 1000 | ld8 temp4=[temp1]		// restore ar.rnat | 
|  | 1001 | ;; | 
|  | 1002 | mov ar.bspstore=temp3		// back to old stack | 
|  | 1003 | ;; | 
|  | 1004 | mov ar.rnat=temp4 | 
|  | 1005 | ;; | 
|  | 1006 |  | 
|  | 1007 | br.sptk b0 | 
|  | 1008 |  | 
|  | 1009 | //EndStub////////////////////////////////////////////////////////////////////// | 
|  | 1010 |  | 
|  | 1011 |  | 
|  | 1012 | //++ | 
|  | 1013 | // Name: | 
|  | 1014 | //	ia64_set_kernel_registers() | 
|  | 1015 | // | 
|  | 1016 | // Stub Description: | 
|  | 1017 | // | 
|  | 1018 | //	Set the registers that are required by the C code in order to run on an | 
|  | 1019 | //	MCA/INIT stack. | 
|  | 1020 | // | 
|  | 1021 | //	r2 contains the return address, r3 contains either | 
|  | 1022 | //	IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET. | 
|  | 1023 | // | 
|  | 1024 | //-- | 
|  | 1025 |  | 
|  | 1026 | ia64_set_kernel_registers: | 
|  | 1027 | add temp3=MCA_SP_OFFSET, r3 | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 1028 | mov b0=r2		// save return address | 
|  | 1029 | GET_IA64_MCA_DATA(temp1) | 
|  | 1030 | ;; | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 1031 | add r12=temp1, temp3	// kernel stack pointer on MCA/INIT stack | 
|  | 1032 | add r13=temp1, r3	// set current to start of MCA/INIT stack | 
| Keith Owens | 20bb868 | 2005-09-22 18:49:15 +1000 | [diff] [blame] | 1033 | add r20=temp1, r3	// physical start of MCA/INIT stack | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 1034 | ;; | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 1035 | DATA_PA_TO_VA(r12,temp2) | 
|  | 1036 | DATA_PA_TO_VA(r13,temp3) | 
|  | 1037 | ;; | 
|  | 1038 | mov IA64_KR(CURRENT)=r13 | 
|  | 1039 |  | 
| Keith Owens | 20bb868 | 2005-09-22 18:49:15 +1000 | [diff] [blame] | 1040 | /* Wire IA64_TR_CURRENT_STACK to the MCA/INIT handler stack.  To avoid | 
|  | 1041 | * any dependencies on the algorithm in ia64_switch_to(), just purge | 
|  | 1042 | * any existing CURRENT_STACK mapping and insert the new one. | 
|  | 1043 | */ | 
|  | 1044 |  | 
|  | 1045 | mov r16=IA64_KR(CURRENT_STACK)		// physical granule mapped by IA64_TR_CURRENT_STACK | 
|  | 1046 | ;; | 
|  | 1047 | shl r16=r16,IA64_GRANULE_SHIFT | 
|  | 1048 | ;; | 
|  | 1049 | dep r16=-1,r16,61,3			// virtual granule | 
|  | 1050 | mov r18=IA64_GRANULE_SHIFT<<2		// for cr.itir.ps | 
|  | 1051 | ;; | 
|  | 1052 | ptr.d r16,r18 | 
|  | 1053 | ;; | 
|  | 1054 | srlz.d | 
|  | 1055 |  | 
|  | 1056 | shr.u r16=r20,IA64_GRANULE_SHIFT	// r20 = physical start of MCA/INIT stack | 
|  | 1057 | movl r21=PAGE_KERNEL			// page properties | 
|  | 1058 | ;; | 
|  | 1059 | mov IA64_KR(CURRENT_STACK)=r16 | 
|  | 1060 | or r21=r20,r21				// construct PA | page properties | 
|  | 1061 | ;; | 
|  | 1062 | mov cr.itir=r18 | 
|  | 1063 | mov cr.ifa=r13 | 
|  | 1064 | mov r20=IA64_TR_CURRENT_STACK | 
| Russ Anderson | 8f9e146 | 2006-09-18 18:37:15 -0500 | [diff] [blame] | 1065 |  | 
|  | 1066 | movl r17=FPSR_DEFAULT | 
|  | 1067 | ;; | 
|  | 1068 | mov.m ar.fpsr=r17			// set ar.fpsr to kernel default value | 
| Keith Owens | 20bb868 | 2005-09-22 18:49:15 +1000 | [diff] [blame] | 1069 | ;; | 
|  | 1070 | itr.d dtr[r20]=r21 | 
|  | 1071 | ;; | 
|  | 1072 | srlz.d | 
| Keith Owens | 7f613c7 | 2005-09-11 17:22:53 +1000 | [diff] [blame] | 1073 |  | 
|  | 1074 | br.sptk b0 | 
|  | 1075 |  | 
|  | 1076 | //EndStub////////////////////////////////////////////////////////////////////// | 
|  | 1077 |  | 
|  | 1078 | #undef	ms | 
|  | 1079 | #undef	regs | 
|  | 1080 | #undef	temp1 | 
|  | 1081 | #undef	temp2 | 
|  | 1082 | #undef	temp3 | 
|  | 1083 | #undef	temp4 | 
|  | 1084 |  | 
|  | 1085 |  | 
|  | 1086 | // Support function for mca.c, it is here to avoid using inline asm.  Given the | 
|  | 1087 | // address of an rnat slot, if that address is below the current ar.bspstore | 
|  | 1088 | // then return the contents of that slot, otherwise return the contents of | 
|  | 1089 | // ar.rnat. | 
|  | 1090 | GLOBAL_ENTRY(ia64_get_rnat) | 
|  | 1091 | alloc r14=ar.pfs,1,0,0,0 | 
|  | 1092 | mov ar.rsc=0 | 
|  | 1093 | ;; | 
|  | 1094 | mov r14=ar.bspstore | 
|  | 1095 | ;; | 
|  | 1096 | cmp.lt p6,p7=in0,r14 | 
|  | 1097 | ;; | 
|  | 1098 | (p6)	ld8 r8=[in0] | 
|  | 1099 | (p7)	mov r8=ar.rnat | 
|  | 1100 | mov ar.rsc=3 | 
|  | 1101 | br.ret.sptk.many rp | 
|  | 1102 | END(ia64_get_rnat) |