fpromasm.S
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:10k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* 
  2.  *
  3.  * This file is subject to the terms and conditions of the GNU General Public
  4.  * License.  See the file "COPYING" in the main directory of this archive
  5.  * for more details.
  6.  *
  7.  *   (Code copied from or=ther files)
  8.  * Copyright (C) 1998-2000 Hewlett-Packard Co
  9.  * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
  10.  *
  11.  * Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved.
  12.  */
  13. #define __ASSEMBLY__ 1
  14. #include <linux/config.h>
  15. #include <asm/processor.h>
  16. #include <asm/sn/addrs.h>
  17. #include <asm/sn/sn2/shub_mmr.h>
  18. /*
  19.  * This file contains additional set up code that is needed to get going on
  20.  * Medusa.  This code should disappear once real hw is available.
  21.  *
  22.  * On entry to this routine, the following register values are assumed:
  23.  *
  24.  * gr[8] - BSP cpu
  25.  * pr[9] - kernel entry address
  26.  * pr[10] - cpu number on the node
  27.  *
  28.  * NOTE:
  29.  *   This FPROM may be loaded/executed at an address different from the
  30.  *   address that it was linked at. The FPROM is linked to run on node 0
  31.  *   at address 0x100000. If the code in loaded into another node, it
  32.  *   must be loaded at offset 0x100000 of the node. In addition, the
  33.  *   FPROM does the following things:
  34.  * - determine the base address of the node it is loaded on
  35.  * - add the node base to _gp.
  36.  * - add the node base to all addresses derived from "movl" 
  37.  *   instructions. (I couldnt get GPREL addressing to work)
  38.  *   (maybe newer versions of the tools will support this)
  39.  * - scan the .got section and add the node base to all
  40.  *   pointers in this section.
  41.  * - add the node base to all physical addresses in the
  42.  *   SAL/PAL/EFI table built by the C code. (This is done
  43.  *   in the C code - not here)
  44.  * - add the node base to the TLB entries for vmlinux
  45.  */
  46. #define KERNEL_BASE 0xe000000000000000
  47. #define BOOT_PARAM_ADDR 0x40000
  48. /* 
  49.  * ar.k0 gets set to IOPB_PA value, on 460gx chipset it should 
  50.  * be 0x00000ffffc000000, but on snia we use the (inverse swizzled)
  51.  * IOSPEC_BASE value
  52.  */
  53. #ifdef CONFIG_IA64_SGI_SN1
  54. #define IOPB_PA 0xc0000FFFFC000000
  55. #else
  56. #define IOPB_PA 0xc000000fcc000000
  57. #endif
  58. #define RR_RID 8
  59. // ====================================================================================
  60.         .text
  61.         .align 16
  62. .global _start
  63. .proc _start
  64. _start:
  65. // Setup psr and rse for system init
  66. mov psr.l = r0;;
  67. srlz.d;;
  68. invala
  69. mov ar.rsc = r0;;
  70. loadrs
  71. ;;
  72. // Isolate node number we are running on.
  73. mov r6 = ip;;
  74. #ifdef CONFIG_IA64_SGI_SN1
  75. shr r5 = r6,33;; // r5 = node number
  76. shl r6 = r5,33 // r6 = base memory address of node
  77. #else
  78. shr r5 = r6,38 // r5 = node number
  79. dep r6 = 0,r6,0,36 // r6 = base memory address of node
  80. #endif
  81. // Set & relocate gp.
  82. movl r1= __gp;; // Add base memory address
  83. or  r1 = r1,r6 // Relocate to boot node
  84. // Lets figure out who we are & put it in the LID register.
  85. #ifdef CONFIG_IA64_SGI_SN2
  86. // On SN2, we (currently) pass the cpu number in r10 at boot
  87. and r25=3,r10;;
  88. movl r16=0x8000008110000400 // Allow IPIs
  89. mov r17=-1;;
  90. st8 [r16]=r17
  91. movl r16=0x8000008110060580;; // SHUB_ID
  92. ld8 r27=[r16];;
  93. extr.u r27=r27,32,11;;
  94. shl  r26=r25,28;; // Align local cpu# to lid.eid
  95. shl  r27=r27,16;; // Align NASID to lid.id
  96. or   r26=r26,r27;; // build the LID
  97. #else
  98. // The BR_PI_SELF_CPU_NUM register gives us a value of 0-3.
  99. // This identifies the cpu on the node. 
  100. // Merge the cpu number with the NASID to generate the LID.
  101. movl r24=0x80000a0001000020;; // BR_PI_SELF_CPU_NUM
  102. ld8  r25=[r24] // Fetch PI_SELF
  103. movl r27=0x80000a0001600000;; // Fetch REVID to get local NASID
  104. ld8  r27=[r27];;
  105. extr.u r27=r27,32,8;;
  106. shl  r26=r25,16;; // Align local cpu# to lid.eid
  107. shl  r27=r27,24;; // Align NASID to lid.id
  108. or   r26=r26,r27;; // build the LID
  109. #endif
  110. mov  cr.lid=r26 // Now put in in the LID register
  111. movl r2=FPSR_DEFAULT;;
  112. mov  ar.fpsr=r2
  113. movl sp = bootstacke-16;;
  114. or  sp = sp,r6 // Relocate to boot node
  115. // Save the NASID that we are loaded on.
  116. movl r2=base_nasid;; // Save base_nasid for C code
  117. or  r2 = r2,r6;; // Relocate to boot node
  118.    st8  [r2]=r5 // Uncond st8 - same on all cpus
  119. // Save the kernel entry address. It is passed in r9 on one of
  120. // the cpus.
  121. movl r2=bsp_entry_pc
  122. cmp.ne p6,p0=r9,r0;;
  123. or  r2 = r2,r6;; // Relocate to boot node
  124. (p6)   st8  [r2]=r9 // Uncond st8 - same on all cpus
  125. // The following can ONLY be done by 1 cpu. Lets set a lock - the
  126. // cpu that gets it does the initilization. The rest just spin waiting
  127. // til initilization is complete.
  128. movl r22 = initlock;;
  129. or r22 = r22,r6 // Relocate to boot node
  130. mov r23 = 1;;
  131. xchg8 r23 = [r22],r23;;
  132. cmp.eq  p6,p0 = 0,r23
  133. (p6) br.cond.spnt.few init
  134. 1: ld4 r23 = [r22];;
  135. cmp.eq p6,p0 = 1,r23
  136. (p6) br.cond.sptk 1b
  137. br initx
  138. // Add base address of node memory to each pointer in the .got section.
  139. init: movl r16 = _GLOBAL_OFFSET_TABLE_;;
  140. or r16 = r16,r6;; // Relocate to boot node
  141. 1:  ld8 r17 = [r16];;
  142. cmp.eq p6,p7=0,r17
  143. (p6) br.cond.sptk.few.clr 2f;;
  144. or r17 = r17,r6;; // Relocate to boot node
  145. st8 [r16] = r17,8
  146. br 1b
  147. 2:
  148. mov r23 = 2;; // All done, release the spinning cpus
  149. st4 [r22] = r23
  150. initx:
  151. //
  152. // I/O-port space base address:
  153. //
  154. movl r2 = IOPB_PA;;
  155. mov ar.k0 = r2
  156. // Now call main & pass it the current LID value.
  157. alloc  r0=ar.pfs,0,0,2,0
  158. mov     r32=r26
  159. mov    r33=r8;;
  160. br.call.sptk.few rp=fmain
  161. // Initialize Region Registers
  162. //
  163.         mov             r10 = r0
  164.         mov             r2 = (13<<2)
  165.         mov             r3 = r0;;
  166. 1:      cmp4.gtu        p6,p7 = 7, r3
  167.         dep             r10 = r3, r10, 61, 3
  168.         dep             r2 = r3, r2, RR_RID, 4;;
  169. (p7)    dep             r2 = 0, r2, 0, 1;;
  170. (p6)    dep             r2 = -1, r2, 0, 1;;
  171.         mov             rr[r10] = r2
  172.         add             r3 = 1, r3;;
  173.         srlz.d;;
  174.         cmp4.gtu        p6,p0 = 8, r3
  175. (p6)    br.cond.sptk.few.clr 1b
  176. //
  177. // Return value indicates if we are the BSP or AP.
  178. //     1 = BSP, 0 = AP
  179. mov             cr.tpr=r0;;
  180. cmp.eq p6,p0=r8,r0
  181. (p6) br.cond.spnt slave
  182. //
  183. // Go to kernel C startup routines
  184. // Need to do a "rfi" in order set "it" and "ed" bits in the PSR.
  185. // This is the only way to set them.
  186. movl r28=BOOT_PARAM_ADDR
  187. movl r2=bsp_entry_pc;;
  188. or  r28 = r28,r6;; // Relocate to boot node
  189. or  r2 = r2,r6;; // Relocate to boot node
  190. ld8 r2=[r2];;
  191. or r2=r2,r6;;
  192. dep r2=0,r2,61,3;; // convert to phys mode
  193. //
  194. // Turn on address translation, interrupt collection, psr.ed, protection key.
  195. // Interrupts (PSR.i) are still off here.
  196. //
  197.         movl            r3 = (  IA64_PSR_BN | 
  198.                                 IA64_PSR_AC | 
  199.                                 IA64_PSR_DB | 
  200.                                 IA64_PSR_DA | 
  201.                                 IA64_PSR_IC   
  202.                              )
  203.         ;;
  204.         mov             cr.ipsr = r3
  205. //
  206. // Go to kernel C startup routines
  207. //      Need to do a "rfi" in order set "it" and "ed" bits in the PSR.
  208. //      This is the only way to set them.
  209. mov r8=r28;;
  210. bsw.1 ;;
  211. mov r28=r8;;
  212. bsw.0 ;;
  213.         mov             cr.iip = r2
  214.         srlz.d;;
  215.         rfi;;
  216. .endp _start
  217. // Slave processors come here to spin til they get an interrupt. Then they launch themselves to
  218. // the place ap_entry points. No initialization is necessary - the kernel makes no
  219. // assumptions about state on this entry.
  220. // Note: should verify that the interrupt we got was really the ap_wakeup
  221. //       interrupt but this should not be an issue on medusa
  222. slave:
  223. nop.i 0x8beef // Medusa - put cpu to sleep til interrupt occurs
  224. mov r8=cr.irr0;; // Check for interrupt pending.
  225. cmp.eq p6,p0=r8,r0
  226. (p6) br.cond.sptk slave;;
  227. mov r8=cr.ivr;; // Got one. Must read ivr to accept it
  228. srlz.d;;
  229. mov cr.eoi=r0;; // must write eoi to clear
  230. movl r8=ap_entry;; // now jump to kernel entry
  231. or  r8 = r8,r6;; // Relocate to boot node
  232. ld8 r9=[r8],8;;
  233. ld8 r1=[r8]
  234. mov b0=r9;;
  235. br b0
  236. // Here is the kernel stack used for the fake PROM
  237. .bss
  238. .align 16384
  239. bootstack:
  240. .skip 16384
  241. bootstacke:
  242. initlock:
  243. data4
  244. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  245. // This code emulates the PAL. Only essential interfaces are emulated.
  246. .text
  247. .global pal_emulator
  248. .proc pal_emulator
  249. pal_emulator:
  250. mov r8=-1
  251. mov r9=256
  252. ;;
  253. cmp.gtu p6,p7=r9,r28 /* r28 <= 255? */
  254. (p6) br.cond.sptk.few static
  255. ;;
  256. mov r9=512
  257. ;;
  258. cmp.gtu p6,p7=r9,r28
  259. (p6) br.cond.sptk.few stacked
  260. ;;
  261. static: cmp.eq p6,p7=6,r28 /* PAL_PTCE_INFO */
  262. (p7) br.cond.sptk.few 1f
  263. movl r8=0 /* status = 0 */
  264. movl r9=0x100000000 /* tc.base */
  265. movl r10=0x0000000200000003 /* count[0], count[1] */
  266. movl r11=0x1000000000002000 /* stride[0], stride[1] */
  267. ;;
  268. 1: cmp.eq p6,p7=14,r28 /* PAL_FREQ_RATIOS */
  269. (p7) br.cond.sptk.few 1f
  270. movl r8=0 /* status = 0 */
  271. movl r9 =0x100000064 /* proc_ratio (1/100) */
  272. movl r10=0x100000100 /* bus_ratio<<32 (1/256) */
  273. movl r11=0x10000000a /* itc_ratio<<32 (1/100) */
  274. ;;
  275. 1: cmp.eq p6,p7=8,r28 /* PAL_VM_SUMMARY */
  276. (p7) br.cond.sptk.few 1f
  277. movl r8=0
  278. #ifdef CONFIG_IA64_SGI_SN1
  279. movl r9=0x0203083001151059
  280. movl r10=0x1232
  281. #else
  282. movl r9=0x0203083001151065
  283. movl r10=0x183f
  284. #endif
  285. movl r11=0
  286. ;;
  287. 1: cmp.eq p6,p7=19,r28 /* PAL_RSE_INFO */
  288. (p7) br.cond.sptk.few 1f
  289. movl r8=0
  290. movl r9=0x60
  291. movl r10=0x0
  292. movl r11=0
  293. ;;
  294. 1: cmp.eq p6,p7=15,r28 /* PAL_PERF_MON_INFO */
  295. (p7) br.cond.sptk.few 1f
  296. movl r8=0
  297. movl r9=0x08122004
  298. movl r10=0x0
  299. movl r11=0
  300. mov r2=ar.lc
  301. mov r3=16;;
  302. mov ar.lc=r3
  303. mov r3=r29;;
  304. 5: st8 [r3]=r0,8
  305. br.cloop.sptk.few 5b;;
  306. mov ar.lc=r2
  307. mov r3=r29
  308. movl r2=0x1fff;; /* PMC regs */
  309. st8 [r3]=r2
  310. add r3=32,r3
  311. movl r2=0x3ffff;; /* PMD regs */
  312. st8 [r3]=r2
  313. add r3=32,r3
  314. movl r2=0xf0;; /* cycle regs */
  315. st8 [r3]=r2
  316. add r3=32,r3
  317. movl r2=0x10;; /* retired regs */
  318. st8 [r3]=r2
  319. ;;
  320. 1: cmp.eq p6,p7=19,r28 /* PAL_RSE_INFO */
  321. (p7) br.cond.sptk.few 1f
  322. movl r8=0 /* status = 0 */
  323. movl r9=96 /* num phys stacked */
  324. movl r10=0 /* hints */
  325. movl r11=0
  326. ;;
  327. 1: cmp.eq p6,p7=1,r28 /* PAL_CACHE_FLUSH */
  328. (p7) br.cond.sptk.few 1f
  329. mov r9=ar.lc
  330. movl r8=524288 /* flush 512k million cache lines (16MB) */
  331. ;;
  332. mov ar.lc=r8
  333. movl r8=0xe000000000000000
  334. ;;
  335. .loop: fc r8
  336. add r8=32,r8
  337. br.cloop.sptk.few .loop
  338. sync.i
  339. ;;
  340. srlz.i
  341. ;;
  342. mov ar.lc=r9
  343. mov r8=r0
  344. 1: br.cond.sptk.few rp
  345. stacked:
  346. br.ret.sptk.few rp
  347. .endp pal_emulator