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
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>
11 * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
16 #define __ASSEMBLY__ 1
17 #include <linux/config.h>
18 #include <asm/processor.h>
19 #include <asm/sn/addrs.h>
20 #include <asm/sn/sn2/shub_mmr.h>
23 * This file contains additional set up code that is needed to get going on
24 * Medusa. This code should disappear once real hw is available.
26 * On entry to this routine, the following register values are assumed:
29 * pr[9] - kernel entry address
30 * pr[10] - cpu number on the node
33 * This FPROM may be loaded/executed at an address different from the
34 * address that it was linked at. The FPROM is linked to run on node 0
35 * at address 0x100000. If the code in loaded into another node, it
36 * must be loaded at offset 0x100000 of the node. In addition, the
37 * FPROM does the following things:
38 * - determine the base address of the node it is loaded on
39 * - add the node base to _gp.
40 * - add the node base to all addresses derived from "movl"
41 * instructions. (I couldnt get GPREL addressing to work)
42 * (maybe newer versions of the tools will support this)
43 * - scan the .got section and add the node base to all
44 * pointers in this section.
45 * - add the node base to all physical addresses in the
46 * SAL/PAL/EFI table built by the C code. (This is done
47 * in the C code - not here)
48 * - add the node base to the TLB entries for vmlinux
51 #define KERNEL_BASE 0xe000000000000000
52 #define BOOT_PARAM_ADDR 0x40000
56 * ar.k0 gets set to IOPB_PA value, on 460gx chipset it should
57 * be 0x00000ffffc000000, but on snia we use the (inverse swizzled)
61 #define IOPB_PA 0xc000000fcc000000
68 // ====================================================================================
75 // Setup psr and rse for system init
83 // Isolate node number we are running on.
86 shr r5 = r6,38 // r5 = node number
87 dep r6 = 0,r6,0,36 // r6 = base memory address of node
93 movl r1= __gp;; // Add base memory address
94 or r1 = r1,r6 // Relocate to boot node
96 // Lets figure out who we are & put it in the LID register.
98 // On SN2, we (currently) pass the cpu number in r10 at boot
100 movl r16=0x8000008110000400 // Allow IPIs
103 movl r16=0x8000008110060580;; // SHUB_ID
105 extr.u r27=r27,32,11;;
106 shl r26=r25,28;; // Align local cpu# to lid.eid
107 shl r27=r27,16;; // Align NASID to lid.id
108 or r26=r26,r27;; // build the LID
110 // The BR_PI_SELF_CPU_NUM register gives us a value of 0-3.
111 // This identifies the cpu on the node.
112 // Merge the cpu number with the NASID to generate the LID.
113 movl r24=0x80000a0001000020;; // BR_PI_SELF_CPU_NUM
114 ld8 r25=[r24] // Fetch PI_SELF
115 movl r27=0x80000a0001600000;; // Fetch REVID to get local NASID
117 extr.u r27=r27,32,8;;
118 shl r26=r25,16;; // Align local cpu# to lid.eid
119 shl r27=r27,24;; // Align NASID to lid.id
120 or r26=r26,r27;; // build the LID
122 mov cr.lid=r26 // Now put in in the LID register
124 movl r2=FPSR_DEFAULT;;
126 movl sp = bootstacke-16;;
127 or sp = sp,r6 // Relocate to boot node
129 // Save the NASID that we are loaded on.
130 movl r2=base_nasid;; // Save base_nasid for C code
131 or r2 = r2,r6;; // Relocate to boot node
132 st8 [r2]=r5 // Uncond st8 - same on all cpus
134 // Save the kernel entry address. It is passed in r9 on one of
138 or r2 = r2,r6;; // Relocate to boot node
139 (p6) st8 [r2]=r9 // Uncond st8 - same on all cpus
142 // The following can ONLY be done by 1 cpu. Lets set a lock - the
143 // cpu that gets it does the initilization. The rest just spin waiting
144 // til initilization is complete.
145 movl r22 = initlock;;
146 or r22 = r22,r6 // Relocate to boot node
148 xchg8 r23 = [r22],r23;;
150 (p6) br.cond.spnt.few init
156 // Add base address of node memory to each pointer in the .got section.
157 init: movl r16 = _GLOBAL_OFFSET_TABLE_;;
158 or r16 = r16,r6;; // Relocate to boot node
161 (p6) br.cond.sptk.few.clr 2f;;
162 or r17 = r17,r6;; // Relocate to boot node
166 mov r23 = 2;; // All done, release the spinning cpus
171 // I/O-port space base address:
177 // Now call main & pass it the current LID value.
178 alloc r2=ar.pfs,0,0,2,0
181 br.call.sptk.few rp=fmain
183 // Initialize Region Registers
188 1: cmp4.gtu p6,p7 = 7, r3
189 dep r10 = r3, r10, 61, 3
190 dep r2 = r3, r2, RR_RID, 4;;
191 (p7) dep r2 = 0, r2, 0, 1;;
192 (p6) dep r2 = -1, r2, 0, 1;;
196 cmp4.gtu p6,p0 = 8, r3
197 (p6) br.cond.sptk.few.clr 1b
200 // Return value indicates if we are the BSP or AP.
204 (p6) br.cond.spnt slave
207 // Go to kernel C startup routines
208 // Need to do a "rfi" in order set "it" and "ed" bits in the PSR.
209 // This is the only way to set them.
211 movl r28=BOOT_PARAM_ADDR
212 movl r2=bsp_entry_pc;;
213 or r28 = r28,r6;; // Relocate to boot node
214 or r2 = r2,r6;; // Relocate to boot node
217 dep r2=0,r2,61,3;; // convert to phys mode
220 // Turn on address translation, interrupt collection, psr.ed, protection key.
221 // Interrupts (PSR.i) are still off here.
224 movl r3 = ( IA64_PSR_BN | \
234 // Go to kernel C startup routines
235 // Need to do a "rfi" in order set "it" and "ed" bits in the PSR.
236 // This is the only way to set them.
250 // Slave processors come here to spin til they get an interrupt. Then they launch themselves to
251 // the place ap_entry points. No initialization is necessary - the kernel makes no
252 // assumptions about state on this entry.
253 // Note: should verify that the interrupt we got was really the ap_wakeup
254 // interrupt but this should not be an issue on medusa
256 nop.i 0x8beef // Medusa - put cpu to sleep til interrupt occurs
257 mov r8=cr.irr0;; // Check for interrupt pending.
259 (p6) br.cond.sptk slave;;
261 mov r8=cr.ivr;; // Got one. Must read ivr to accept it
263 mov cr.eoi=r0;; // must write eoi to clear
264 movl r8=ap_entry;; // now jump to kernel entry
265 or r8 = r8,r6;; // Relocate to boot node
271 // Here is the kernel stack used for the fake PROM
282 //////////////////////////////////////////////////////////////////////////////////////////////////////////
283 // This code emulates the PAL. Only essential interfaces are emulated.
294 cmp.gtu p6,p7=r9,r28 /* r28 <= 255? */
295 (p6) br.cond.sptk.few static
300 (p6) br.cond.sptk.few stacked
303 static: cmp.eq p6,p7=6,r28 /* PAL_PTCE_INFO */
304 (p7) br.cond.sptk.few 1f
305 movl r8=0 /* status = 0 */
306 movl r9=0x100000000 /* tc.base */
307 movl r10=0x0000000200000003 /* count[0], count[1] */
308 movl r11=0x1000000000002000 /* stride[0], stride[1] */
311 1: cmp.eq p6,p7=14,r28 /* PAL_FREQ_RATIOS */
312 (p7) br.cond.sptk.few 1f
313 movl r8=0 /* status = 0 */
314 movl r9 =0x100000064 /* proc_ratio (1/100) */
315 movl r10=0x100000100 /* bus_ratio<<32 (1/256) */
316 movl r11=0x10000000a /* itc_ratio<<32 (1/100) */
319 1: cmp.eq p6,p7=8,r28 /* PAL_VM_SUMMARY */
320 (p7) br.cond.sptk.few 1f
323 movl r9=0x0203083001151065
329 1: cmp.eq p6,p7=19,r28 /* PAL_RSE_INFO */
330 (p7) br.cond.sptk.few 1f
337 1: cmp.eq p6,p7=15,r28 /* PAL_PERF_MON_INFO */
338 (p7) br.cond.sptk.few 1f
348 br.cloop.sptk.few 5b;;
351 movl r2=0x1fff;; /* PMC regs */
354 movl r2=0x3ffff;; /* PMD regs */
357 movl r2=0xf0;; /* cycle regs */
360 movl r2=0x10;; /* retired regs */
364 1: cmp.eq p6,p7=19,r28 /* PAL_RSE_INFO */
365 (p7) br.cond.sptk.few 1f
366 movl r8=0 /* status = 0 */
367 movl r9=96 /* num phys stacked */
368 movl r10=0 /* hints */
372 1: cmp.eq p6,p7=1,r28 /* PAL_CACHE_FLUSH */
373 (p7) br.cond.sptk.few 1f
375 movl r8=524288 /* flush 512k million cache lines (16MB) */
378 movl r8=0xe000000000000000
382 br.cloop.sptk.few .loop
389 1: br.cond.sptk.few rp