mca_asm.S 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103
  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. add temp4=MCA_SOS_OFFSET+SOS(OS_GP), r3
  942. mov b0=r2 // save return address
  943. GET_IA64_MCA_DATA(temp1)
  944. ;;
  945. add temp4=temp4, temp1 // &struct ia64_sal_os_state.os_gp
  946. add r12=temp1, temp3 // kernel stack pointer on MCA/INIT stack
  947. add r13=temp1, r3 // set current to start of MCA/INIT stack
  948. add r20=temp1, r3 // physical start of MCA/INIT stack
  949. ;;
  950. ld8 r1=[temp4] // OS GP from SAL OS state
  951. ;;
  952. DATA_PA_TO_VA(r1,temp1)
  953. DATA_PA_TO_VA(r12,temp2)
  954. DATA_PA_TO_VA(r13,temp3)
  955. ;;
  956. mov IA64_KR(CURRENT)=r13
  957. /* Wire IA64_TR_CURRENT_STACK to the MCA/INIT handler stack. To avoid
  958. * any dependencies on the algorithm in ia64_switch_to(), just purge
  959. * any existing CURRENT_STACK mapping and insert the new one.
  960. */
  961. mov r16=IA64_KR(CURRENT_STACK) // physical granule mapped by IA64_TR_CURRENT_STACK
  962. ;;
  963. shl r16=r16,IA64_GRANULE_SHIFT
  964. ;;
  965. dep r16=-1,r16,61,3 // virtual granule
  966. mov r18=IA64_GRANULE_SHIFT<<2 // for cr.itir.ps
  967. ;;
  968. ptr.d r16,r18
  969. ;;
  970. srlz.d
  971. shr.u r16=r20,IA64_GRANULE_SHIFT // r20 = physical start of MCA/INIT stack
  972. movl r21=PAGE_KERNEL // page properties
  973. ;;
  974. mov IA64_KR(CURRENT_STACK)=r16
  975. or r21=r20,r21 // construct PA | page properties
  976. ;;
  977. mov cr.itir=r18
  978. mov cr.ifa=r13
  979. mov r20=IA64_TR_CURRENT_STACK
  980. ;;
  981. itr.d dtr[r20]=r21
  982. ;;
  983. srlz.d
  984. br.sptk b0
  985. //EndStub//////////////////////////////////////////////////////////////////////
  986. #undef ms
  987. #undef regs
  988. #undef temp1
  989. #undef temp2
  990. #undef temp3
  991. #undef temp4
  992. // Support function for mca.c, it is here to avoid using inline asm. Given the
  993. // address of an rnat slot, if that address is below the current ar.bspstore
  994. // then return the contents of that slot, otherwise return the contents of
  995. // ar.rnat.
  996. GLOBAL_ENTRY(ia64_get_rnat)
  997. alloc r14=ar.pfs,1,0,0,0
  998. mov ar.rsc=0
  999. ;;
  1000. mov r14=ar.bspstore
  1001. ;;
  1002. cmp.lt p6,p7=in0,r14
  1003. ;;
  1004. (p6) ld8 r8=[in0]
  1005. (p7) mov r8=ar.rnat
  1006. mov ar.rsc=3
  1007. br.ret.sptk.many rp
  1008. END(ia64_get_rnat)