mca_asm.S 27 KB

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