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