📄 fpromasm.s
字号:
/* * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * (Code copied from or=ther files) * Copyright (C) 1998-2000 Hewlett-Packard Co * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com> * * Copyright (C) 2000-2002 Silicon Graphics, Inc. All rights reserved. */#define __ASSEMBLY__ 1#include <linux/config.h>#include <asm/processor.h>#include <asm/sn/addrs.h>#include <asm/sn/sn2/shub_mmr.h>/* * This file contains additional set up code that is needed to get going on * Medusa. This code should disappear once real hw is available. * * On entry to this routine, the following register values are assumed: * * gr[8] - BSP cpu * pr[9] - kernel entry address * pr[10] - cpu number on the node * * NOTE: * This FPROM may be loaded/executed at an address different from the * address that it was linked at. The FPROM is linked to run on node 0 * at address 0x100000. If the code in loaded into another node, it * must be loaded at offset 0x100000 of the node. In addition, the * FPROM does the following things: * - determine the base address of the node it is loaded on * - add the node base to _gp. * - add the node base to all addresses derived from "movl" * instructions. (I couldnt get GPREL addressing to work) * (maybe newer versions of the tools will support this) * - scan the .got section and add the node base to all * pointers in this section. * - add the node base to all physical addresses in the * SAL/PAL/EFI table built by the C code. (This is done * in the C code - not here) * - add the node base to the TLB entries for vmlinux */#define KERNEL_BASE 0xe000000000000000#define BOOT_PARAM_ADDR 0x40000/* * ar.k0 gets set to IOPB_PA value, on 460gx chipset it should * be 0x00000ffffc000000, but on snia we use the (inverse swizzled) * IOSPEC_BASE value */#ifdef CONFIG_IA64_SGI_SN1#define IOPB_PA 0xc0000FFFFC000000#else#define IOPB_PA 0xc000000fcc000000#endif#define RR_RID 8// ==================================================================================== .text .align 16 .global _start .proc _start_start:// Setup psr and rse for system init mov psr.l = r0;; srlz.d;; invala mov ar.rsc = r0;; loadrs ;;// Isolate node number we are running on. mov r6 = ip;;#ifdef CONFIG_IA64_SGI_SN1 shr r5 = r6,33;; // r5 = node number shl r6 = r5,33 // r6 = base memory address of node#else shr r5 = r6,38 // r5 = node number dep r6 = 0,r6,0,36 // r6 = base memory address of node#endif// Set & relocate gp. movl r1= __gp;; // Add base memory address or r1 = r1,r6 // Relocate to boot node// Lets figure out who we are & put it in the LID register.#ifdef CONFIG_IA64_SGI_SN2// On SN2, we (currently) pass the cpu number in r10 at boot and r25=3,r10;; movl r16=0x8000008110000400 // Allow IPIs mov r17=-1;; st8 [r16]=r17 movl r16=0x8000008110060580;; // SHUB_ID ld8 r27=[r16];; extr.u r27=r27,32,11;; shl r26=r25,28;; // Align local cpu# to lid.eid shl r27=r27,16;; // Align NASID to lid.id or r26=r26,r27;; // build the LID#else// The BR_PI_SELF_CPU_NUM register gives us a value of 0-3.// This identifies the cpu on the node. // Merge the cpu number with the NASID to generate the LID. movl r24=0x80000a0001000020;; // BR_PI_SELF_CPU_NUM ld8 r25=[r24] // Fetch PI_SELF movl r27=0x80000a0001600000;; // Fetch REVID to get local NASID ld8 r27=[r27];; extr.u r27=r27,32,8;; shl r26=r25,16;; // Align local cpu# to lid.eid shl r27=r27,24;; // Align NASID to lid.id or r26=r26,r27;; // build the LID#endif mov cr.lid=r26 // Now put in in the LID register movl r2=FPSR_DEFAULT;; mov ar.fpsr=r2 movl sp = bootstacke-16;; or sp = sp,r6 // Relocate to boot node // Save the NASID that we are loaded on. movl r2=base_nasid;; // Save base_nasid for C code or r2 = r2,r6;; // Relocate to boot node st8 [r2]=r5 // Uncond st8 - same on all cpus// Save the kernel entry address. It is passed in r9 on one of// the cpus. movl r2=bsp_entry_pc cmp.ne p6,p0=r9,r0;; or r2 = r2,r6;; // Relocate to boot node(p6) st8 [r2]=r9 // Uncond st8 - same on all cpus// The following can ONLY be done by 1 cpu. Lets set a lock - the// cpu that gets it does the initilization. The rest just spin waiting// til initilization is complete. movl r22 = initlock;; or r22 = r22,r6 // Relocate to boot node mov r23 = 1;; xchg8 r23 = [r22],r23;; cmp.eq p6,p0 = 0,r23(p6) br.cond.spnt.few init1: ld4 r23 = [r22];; cmp.eq p6,p0 = 1,r23(p6) br.cond.sptk 1b br initx// Add base address of node memory to each pointer in the .got section.init: movl r16 = _GLOBAL_OFFSET_TABLE_;; or r16 = r16,r6;; // Relocate to boot node1: ld8 r17 = [r16];; cmp.eq p6,p7=0,r17(p6) br.cond.sptk.few.clr 2f;; or r17 = r17,r6;; // Relocate to boot node st8 [r16] = r17,8 br 1b2: mov r23 = 2;; // All done, release the spinning cpus st4 [r22] = r23initx://// I/O-port space base address:// movl r2 = IOPB_PA;; mov ar.k0 = r2// Now call main & pass it the current LID value. alloc r0=ar.pfs,0,0,2,0 mov r32=r26 mov r33=r8;; br.call.sptk.few rp=fmain // Initialize Region Registers// mov r10 = r0 mov r2 = (13<<2) mov r3 = r0;;1: cmp4.gtu p6,p7 = 7, r3 dep r10 = r3, r10, 61, 3 dep r2 = r3, r2, RR_RID, 4;;(p7) dep r2 = 0, r2, 0, 1;;(p6) dep r2 = -1, r2, 0, 1;; mov rr[r10] = r2 add r3 = 1, r3;; srlz.d;; cmp4.gtu p6,p0 = 8, r3(p6) br.cond.sptk.few.clr 1b//// Return value indicates if we are the BSP or AP.// 1 = BSP, 0 = AP mov cr.tpr=r0;; cmp.eq p6,p0=r8,r0(p6) br.cond.spnt slave//// Go to kernel C startup routines// Need to do a "rfi" in order set "it" and "ed" bits in the PSR.// This is the only way to set them. movl r28=BOOT_PARAM_ADDR movl r2=bsp_entry_pc;; or r28 = r28,r6;; // Relocate to boot node or r2 = r2,r6;; // Relocate to boot node ld8 r2=[r2];; or r2=r2,r6;; dep r2=0,r2,61,3;; // convert to phys mode//// Turn on address translation, interrupt collection, psr.ed, protection key.// Interrupts (PSR.i) are still off here.// movl r3 = ( IA64_PSR_BN | \ IA64_PSR_AC | \ IA64_PSR_DB | \ IA64_PSR_DA | \ IA64_PSR_IC \ ) ;; mov cr.ipsr = r3//// Go to kernel C startup routines// Need to do a "rfi" in order set "it" and "ed" bits in the PSR.// This is the only way to set them. mov r8=r28;; bsw.1 ;; mov r28=r8;; bsw.0 ;; mov cr.iip = r2 srlz.d;; rfi;; .endp _start// Slave processors come here to spin til they get an interrupt. Then they launch themselves to// the place ap_entry points. No initialization is necessary - the kernel makes no// assumptions about state on this entry.// Note: should verify that the interrupt we got was really the ap_wakeup// interrupt but this should not be an issue on medusaslave: nop.i 0x8beef // Medusa - put cpu to sleep til interrupt occurs mov r8=cr.irr0;; // Check for interrupt pending. cmp.eq p6,p0=r8,r0(p6) br.cond.sptk slave;; mov r8=cr.ivr;; // Got one. Must read ivr to accept it srlz.d;; mov cr.eoi=r0;; // must write eoi to clear movl r8=ap_entry;; // now jump to kernel entry or r8 = r8,r6;; // Relocate to boot node ld8 r9=[r8],8;; ld8 r1=[r8] mov b0=r9;; br b0// Here is the kernel stack used for the fake PROM .bss .align 16384bootstack: .skip 16384bootstacke:initlock: data4//////////////////////////////////////////////////////////////////////////////////////////////////////////// This code emulates the PAL. Only essential interfaces are emulated. .text .global pal_emulator .proc pal_emulatorpal_emulator: mov r8=-1 mov r9=256 ;; cmp.gtu p6,p7=r9,r28 /* r28 <= 255? */(p6) br.cond.sptk.few static ;; mov r9=512 ;; cmp.gtu p6,p7=r9,r28(p6) br.cond.sptk.few stacked ;;static: cmp.eq p6,p7=6,r28 /* PAL_PTCE_INFO */(p7) br.cond.sptk.few 1f movl r8=0 /* status = 0 */ movl r9=0x100000000 /* tc.base */ movl r10=0x0000000200000003 /* count[0], count[1] */ movl r11=0x1000000000002000 /* stride[0], stride[1] */ ;;1: cmp.eq p6,p7=14,r28 /* PAL_FREQ_RATIOS */(p7) br.cond.sptk.few 1f movl r8=0 /* status = 0 */ movl r9 =0x100000064 /* proc_ratio (1/100) */ movl r10=0x100000100 /* bus_ratio<<32 (1/256) */ movl r11=0x10000000a /* itc_ratio<<32 (1/100) */ ;;1: cmp.eq p6,p7=8,r28 /* PAL_VM_SUMMARY */(p7) br.cond.sptk.few 1f movl r8=0#ifdef CONFIG_IA64_SGI_SN1 movl r9=0x0203083001151059 movl r10=0x1232#else movl r9=0x0203083001151065 movl r10=0x183f#endif movl r11=0 ;;1: cmp.eq p6,p7=19,r28 /* PAL_RSE_INFO */(p7) br.cond.sptk.few 1f movl r8=0 movl r9=0x60 movl r10=0x0 movl r11=0 ;;1: cmp.eq p6,p7=15,r28 /* PAL_PERF_MON_INFO */(p7) br.cond.sptk.few 1f movl r8=0 movl r9=0x08122004 movl r10=0x0 movl r11=0 mov r2=ar.lc mov r3=16;; mov ar.lc=r3 mov r3=r29;;5: st8 [r3]=r0,8 br.cloop.sptk.few 5b;; mov ar.lc=r2 mov r3=r29 movl r2=0x1fff;; /* PMC regs */ st8 [r3]=r2 add r3=32,r3 movl r2=0x3ffff;; /* PMD regs */ st8 [r3]=r2 add r3=32,r3 movl r2=0xf0;; /* cycle regs */ st8 [r3]=r2 add r3=32,r3 movl r2=0x10;; /* retired regs */ st8 [r3]=r2 ;;1: cmp.eq p6,p7=19,r28 /* PAL_RSE_INFO */(p7) br.cond.sptk.few 1f movl r8=0 /* status = 0 */ movl r9=96 /* num phys stacked */ movl r10=0 /* hints */ movl r11=0 ;;1: cmp.eq p6,p7=1,r28 /* PAL_CACHE_FLUSH */(p7) br.cond.sptk.few 1f mov r9=ar.lc movl r8=524288 /* flush 512k million cache lines (16MB) */ ;; mov ar.lc=r8 movl r8=0xe000000000000000 ;;.loop: fc r8 add r8=32,r8 br.cloop.sptk.few .loop sync.i ;; srlz.i ;; mov ar.lc=r9 mov r8=r01: br.cond.sptk.few rpstacked: br.ret.sptk.few rp .endp pal_emulator
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -