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