mca_asm.S 26 KB

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