mca_asm.S 27 KB

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