mca_asm.S 26 KB

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