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-2002 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)
60 #ifdef CONFIG_IA64_SGI_SN1
61 #define IOPB_PA 0xc0000FFFFC000000
63 #define IOPB_PA 0xc000000fcc000000
70 // ====================================================================================
77 // Setup psr and rse for system init
85 // Isolate node number we are running on.
87 #ifdef CONFIG_IA64_SGI_SN1
88 shr r5 = r6,33;; // r5 = node number
89 shl r6 = r5,33 // r6 = base memory address of node
91 shr r5 = r6,38 // r5 = node number
92 dep r6 = 0,r6,0,36 // r6 = base memory address of node
98 movl r1= __gp;; // Add base memory address
99 or r1 = r1,r6 // Relocate to boot node
101 // Lets figure out who we are & put it in the LID register.
102 #ifdef CONFIG_IA64_SGI_SN2
103 // On SN2, we (currently) pass the cpu number in r10 at boot
105 movl r16=0x8000008110000400 // Allow IPIs
108 movl r16=0x8000008110060580;; // SHUB_ID
110 extr.u r27=r27,32,11;;
111 shl r26=r25,28;; // Align local cpu# to lid.eid
112 shl r27=r27,16;; // Align NASID to lid.id
113 or r26=r26,r27;; // build the LID
115 // The BR_PI_SELF_CPU_NUM register gives us a value of 0-3.
116 // This identifies the cpu on the node.
117 // Merge the cpu number with the NASID to generate the LID.
118 movl r24=0x80000a0001000020;; // BR_PI_SELF_CPU_NUM
119 ld8 r25=[r24] // Fetch PI_SELF
120 movl r27=0x80000a0001600000;; // Fetch REVID to get local NASID
122 extr.u r27=r27,32,8;;
123 shl r26=r25,16;; // Align local cpu# to lid.eid
124 shl r27=r27,24;; // Align NASID to lid.id
125 or r26=r26,r27;; // build the LID
127 mov cr.lid=r26 // Now put in in the LID register
129 movl r2=FPSR_DEFAULT;;
131 movl sp = bootstacke-16;;
132 or sp = sp,r6 // Relocate to boot node
134 // Save the NASID that we are loaded on.
135 movl r2=base_nasid;; // Save base_nasid for C code
136 or r2 = r2,r6;; // Relocate to boot node
137 st8 [r2]=r5 // Uncond st8 - same on all cpus
139 // Save the kernel entry address. It is passed in r9 on one of
143 or r2 = r2,r6;; // Relocate to boot node
144 (p6) st8 [r2]=r9 // Uncond st8 - same on all cpus
147 // The following can ONLY be done by 1 cpu. Lets set a lock - the
148 // cpu that gets it does the initilization. The rest just spin waiting
149 // til initilization is complete.
150 movl r22 = initlock;;
151 or r22 = r22,r6 // Relocate to boot node
153 xchg8 r23 = [r22],r23;;
155 (p6) br.cond.spnt.few init
161 // Add base address of node memory to each pointer in the .got section.
162 init: movl r16 = _GLOBAL_OFFSET_TABLE_;;
163 or r16 = r16,r6;; // Relocate to boot node
166 (p6) br.cond.sptk.few.clr 2f;;
167 or r17 = r17,r6;; // Relocate to boot node
171 mov r23 = 2;; // All done, release the spinning cpus
176 // I/O-port space base address:
182 // Now call main & pass it the current LID value.
183 alloc r2=ar.pfs,0,0,2,0
186 br.call.sptk.few rp=fmain
188 // Initialize Region Registers
193 1: cmp4.gtu p6,p7 = 7, r3
194 dep r10 = r3, r10, 61, 3
195 dep r2 = r3, r2, RR_RID, 4;;
196 (p7) dep r2 = 0, r2, 0, 1;;
197 (p6) dep r2 = -1, r2, 0, 1;;
201 cmp4.gtu p6,p0 = 8, r3
202 (p6) br.cond.sptk.few.clr 1b
205 // Return value indicates if we are the BSP or AP.
209 (p6) br.cond.spnt slave
212 // Go to kernel C startup routines
213 // Need to do a "rfi" in order set "it" and "ed" bits in the PSR.
214 // This is the only way to set them.
216 movl r28=BOOT_PARAM_ADDR
217 movl r2=bsp_entry_pc;;
218 or r28 = r28,r6;; // Relocate to boot node
219 or r2 = r2,r6;; // Relocate to boot node
222 dep r2=0,r2,61,3;; // convert to phys mode
225 // Turn on address translation, interrupt collection, psr.ed, protection key.
226 // Interrupts (PSR.i) are still off here.
229 movl r3 = ( IA64_PSR_BN | \
239 // Go to kernel C startup routines
240 // Need to do a "rfi" in order set "it" and "ed" bits in the PSR.
241 // This is the only way to set them.
255 // Slave processors come here to spin til they get an interrupt. Then they launch themselves to
256 // the place ap_entry points. No initialization is necessary - the kernel makes no
257 // assumptions about state on this entry.
258 // Note: should verify that the interrupt we got was really the ap_wakeup
259 // interrupt but this should not be an issue on medusa
261 nop.i 0x8beef // Medusa - put cpu to sleep til interrupt occurs
262 mov r8=cr.irr0;; // Check for interrupt pending.
264 (p6) br.cond.sptk slave;;
266 mov r8=cr.ivr;; // Got one. Must read ivr to accept it
268 mov cr.eoi=r0;; // must write eoi to clear
269 movl r8=ap_entry;; // now jump to kernel entry
270 or r8 = r8,r6;; // Relocate to boot node
276 // Here is the kernel stack used for the fake PROM
287 //////////////////////////////////////////////////////////////////////////////////////////////////////////
288 // This code emulates the PAL. Only essential interfaces are emulated.
299 cmp.gtu p6,p7=r9,r28 /* r28 <= 255? */
300 (p6) br.cond.sptk.few static
305 (p6) br.cond.sptk.few stacked
308 static: cmp.eq p6,p7=6,r28 /* PAL_PTCE_INFO */
309 (p7) br.cond.sptk.few 1f
310 movl r8=0 /* status = 0 */
311 movl r9=0x100000000 /* tc.base */
312 movl r10=0x0000000200000003 /* count[0], count[1] */
313 movl r11=0x1000000000002000 /* stride[0], stride[1] */
316 1: cmp.eq p6,p7=14,r28 /* PAL_FREQ_RATIOS */
317 (p7) br.cond.sptk.few 1f
318 movl r8=0 /* status = 0 */
319 movl r9 =0x100000064 /* proc_ratio (1/100) */
320 movl r10=0x100000100 /* bus_ratio<<32 (1/256) */
321 movl r11=0x10000000a /* itc_ratio<<32 (1/100) */
324 1: cmp.eq p6,p7=8,r28 /* PAL_VM_SUMMARY */
325 (p7) br.cond.sptk.few 1f
327 #ifdef CONFIG_IA64_SGI_SN1
328 movl r9=0x0203083001151059
331 movl r9=0x0203083001151065
337 1: cmp.eq p6,p7=19,r28 /* PAL_RSE_INFO */
338 (p7) br.cond.sptk.few 1f
345 1: cmp.eq p6,p7=15,r28 /* PAL_PERF_MON_INFO */
346 (p7) br.cond.sptk.few 1f
356 br.cloop.sptk.few 5b;;
359 movl r2=0x1fff;; /* PMC regs */
362 movl r2=0x3ffff;; /* PMD regs */
365 movl r2=0xf0;; /* cycle regs */
368 movl r2=0x10;; /* retired regs */
372 1: cmp.eq p6,p7=19,r28 /* PAL_RSE_INFO */
373 (p7) br.cond.sptk.few 1f
374 movl r8=0 /* status = 0 */
375 movl r9=96 /* num phys stacked */
376 movl r10=0 /* hints */
380 1: cmp.eq p6,p7=1,r28 /* PAL_CACHE_FLUSH */
381 (p7) br.cond.sptk.few 1f
383 movl r8=524288 /* flush 512k million cache lines (16MB) */
386 movl r8=0xe000000000000000
390 br.cloop.sptk.few .loop
397 1: br.cond.sptk.few rp