mca_asm.S 26 KB

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