mca_asm.S 26 KB

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