Commit 574b9dd4 authored by Jack Steiner's avatar Jack Steiner Committed by Tony Luck

[IA64-SGI] The SN2 fakeprom directories/files should be deleted.

Signed-off-by: default avatarJack Steiner <steiner@sgi.com>
Signed-off-by: default avatarTony Luck <tony.luck@intel.com>
parent 5bb1af25
# arch/ia64/sn/fakeprom/Makefile
#
# 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.
#
# Copyright (c) 2000-2003 Silicon Graphics, Inc. All rights reserved.
#
# Medusa fake PROM support
#
EXTRA_TARGETS := fpromasm.o main.o fw-emu.o fpmem.o klgraph_init.o \
fprom vmlinux.sym
OBJS := $(obj)/fpromasm.o $(obj)/main.o $(obj)/fw-emu.o $(obj)/fpmem.o \
$(obj)/klgraph_init.o
LDFLAGS_fprom = -static -T
.PHONY: fprom
fprom: $(obj)/fprom
$(obj)/fprom: $(src)/fprom.lds $(OBJS) arch/ia64/lib/lib.a FORCE
$(call if_changed,ld)
$(obj)/vmlinux.sym: $(src)/make_textsym System.map
$(src)/make_textsym vmlinux > vmlinux.sym
$(call cmd,cptotop)
/*
* 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.
*
* Copyright (c) 2002-2003 Silicon Graphics, Inc. All Rights Reserved.
*/
This directory contains the files required to build
the fake PROM image that is currently being used to
boot IA64 kernels running under the SGI Medusa kernel.
The FPROM currently provides the following functions:
- PAL emulation for all PAL calls we've made so far.
- SAL emulation for all SAL calls we've made so far.
- EFI emulation for all EFI calls we've made so far.
- builds the "ia64_bootparam" structure that is
passed to the kernel from SAL. This structure
shows the cpu & memory configurations.
- supports medusa boottime options for changing
the number of cpus present
- supports medusa boottime options for changing
the memory configuration.
At some point, this fake PROM will be replaced by the
real PROM.
To build a fake PROM, cd to this directory & type:
make
This will (or should) build a fake PROM named "fprom".
Use this fprom image when booting the Medusa simulator. The
control file used to boot Medusa should include the
following lines:
load fprom
load vmlinux
sr pc 0x100000
sr g 9 <address of kernel _start function> #(currently 0xe000000000520000)
NOTE: There is a script "runsim" in this directory that can be used to
simplify setting up an environment for running under Medusa.
The following parameters may be passed to the fake PROM to
control the PAL/SAL/EFI parameters passed to the kernel:
GR[8] = # of cpus
GR[9] = address of primary entry point into the kernel
GR[20] = memory configuration for node 0
GR[21] = memory configuration for node 1
GR[22] = memory configuration for node 2
GR[23] = memory configuration for node 3
Registers GR[20] - GR[23] contain information to specify the
amount of memory present on nodes 0-3.
- if nothing is specified (all registers are 0), the configuration
defaults to 8 MB on node 0.
- a mem config entry for node N is passed in GR[20+N]
- a mem config entry consists of 8 hex digits. Each digit gives the
amount of physical memory available on the node starting at
1GB*<dn>, where dn is the digit number. The amount of memory
is 8MB*2**<d>. (If <d> = 0, the memory size is 0).
SN1 doesn't support dimms this small but small memory systems
boot faster on Medusa.
An example helps a lot. The following specifies that node 0 has
physical memory 0 to 8MB and 1GB to 1GB+32MB, and that node 1 has
64MB starting at address 0 of the node which is 8GB.
gr[20] = 0x21 # 0 to 8MB, 1GB to 1GB+32MB
gr[21] = 0x4 # 8GB to 8GB+64MB
/*
*
* 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.
*
* Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
/*
* FPROM EFI memory descriptor build routines
*
* - Routines to build the EFI memory descriptor map
* - Should also be usable by the SGI prom to convert
* klconfig to efi_memmap
*/
#include <linux/config.h>
#include <linux/efi.h>
#include "fpmem.h"
/*
* args points to a layout in memory like this
*
* 32 bit 32 bit
*
* numnodes numcpus
*
* 16 bit 16 bit 32 bit
* nasid0 cpuconf membankdesc0
* nasid1 cpuconf membankdesc1
* .
* .
* .
* .
* .
*/
sn_memmap_t *sn_memmap ;
sn_config_t *sn_config ;
/*
* There is a hole in the node 0 address space. Dont put it
* in the memory map
*/
#define NODE0_HOLE_SIZE (20*MB)
#define NODE0_HOLE_END (4UL*GB)
#define MB (1024*1024)
#define GB (1024*MB)
#define KERNEL_SIZE (4*MB)
#define PROMRESERVED_SIZE (1*MB)
#ifdef SGI_SN2
#define PHYS_ADDRESS(_n, _x) (((long)_n<<38) | (long)_x | 0x3000000000UL)
#define MD_BANK_SHFT 34
#endif
/*
* For SN, this may not take an arg and gets the numnodes from
* the prom variable or by traversing klcfg or promcfg
*/
int
GetNumNodes(void)
{
return sn_config->nodes;
}
int
GetNumCpus(void)
{
return sn_config->cpus;
}
/* For SN, get the index th nasid */
int
GetNasid(int index)
{
return sn_memmap[index].nasid ;
}
node_memmap_t
GetMemBankInfo(int index)
{
return sn_memmap[index].node_memmap ;
}
int
IsCpuPresent(int cnode, int cpu)
{
return sn_memmap[cnode].cpuconfig & (1UL<<cpu);
}
/*
* Made this into an explicit case statement so that
* we can assign specific properties to banks like bank0
* actually disabled etc.
*/
#ifdef SGI_SN2
int
IsBankPresent(int index, node_memmap_t nmemmap)
{
switch (index) {
case 0:return BankPresent(nmemmap.b0size);
case 1:return BankPresent(nmemmap.b1size);
case 2:return BankPresent(nmemmap.b2size);
case 3:return BankPresent(nmemmap.b3size);
default:return -1 ;
}
}
int
GetBankSize(int index, node_memmap_t nmemmap)
{
/*
* Add 2 because there are 4 dimms per bank.
*/
switch (index) {
case 0:return 2 + ((long)nmemmap.b0size + nmemmap.b0dou);
case 1:return 2 + ((long)nmemmap.b1size + nmemmap.b1dou);
case 2:return 2 + ((long)nmemmap.b2size + nmemmap.b2dou);
case 3:return 2 + ((long)nmemmap.b3size + nmemmap.b3dou);
default:return -1 ;
}
}
#endif
void
build_mem_desc(efi_memory_desc_t *md, int type, long paddr, long numbytes, long attr)
{
md->type = type;
md->phys_addr = paddr;
md->virt_addr = 0;
md->num_pages = numbytes >> 12;
md->attribute = attr;
}
int
build_efi_memmap(void *md, int mdsize)
{
int numnodes = GetNumNodes() ;
int cnode,bank ;
int nasid ;
node_memmap_t membank_info ;
int bsize;
int count = 0 ;
long paddr, hole, numbytes;
for (cnode=0;cnode<numnodes;cnode++) {
nasid = GetNasid(cnode) ;
membank_info = GetMemBankInfo(cnode) ;
for (bank=0;bank<MD_BANKS_PER_NODE;bank++) {
if (IsBankPresent(bank, membank_info)) {
bsize = GetBankSize(bank, membank_info) ;
paddr = PHYS_ADDRESS(nasid, (long)bank<<MD_BANK_SHFT);
numbytes = BankSizeBytes(bsize);
#ifdef SGI_SN2
/*
* Ignore directory.
* Shorten memory chunk by 1 page - makes a better
* testcase & is more like the real PROM.
*/
numbytes = numbytes * 31 / 32;
#endif
/*
* Only emulate the memory prom grabs
* if we have lots of memory, to allow
* us to simulate smaller memory configs than
* we can actually run on h/w. Otherwise,
* linux throws away a whole "granule".
*/
if (cnode == 0 && bank == 0 &&
numbytes > 128*1024*1024) {
numbytes -= 1000;
}
/*
* Check for the node 0 hole. Since banks cant
* span the hole, we only need to check if the end of
* the range is the end of the hole.
*/
if (paddr+numbytes == NODE0_HOLE_END)
numbytes -= NODE0_HOLE_SIZE;
/*
* UGLY hack - we must skip overr the kernel and
* PROM runtime services but we dont exactly where it is.
* So lets just reserve:
* node 0
* 0-1MB for PAL
* 1-4MB for SAL
* node 1-N
* 0-1 for SAL
*/
if (bank == 0) {
if (cnode == 0) {
hole = 2*1024*1024;
build_mem_desc(md, EFI_PAL_CODE, paddr, hole, EFI_MEMORY_WB|EFI_MEMORY_WB);
numbytes -= hole;
paddr += hole;
count++ ;
md += mdsize;
hole = 1*1024*1024;
build_mem_desc(md, EFI_CONVENTIONAL_MEMORY, paddr, hole, EFI_MEMORY_UC);
numbytes -= hole;
paddr += hole;
count++ ;
md += mdsize;
hole = 1*1024*1024;
build_mem_desc(md, EFI_RUNTIME_SERVICES_DATA, paddr, hole, EFI_MEMORY_WB|EFI_MEMORY_WB);
numbytes -= hole;
paddr += hole;
count++ ;
md += mdsize;
} else {
hole = 2*1024*1024;
build_mem_desc(md, EFI_RUNTIME_SERVICES_DATA, paddr, hole, EFI_MEMORY_WB|EFI_MEMORY_WB);
numbytes -= hole;
paddr += hole;
count++ ;
md += mdsize;
hole = 2*1024*1024;
build_mem_desc(md, EFI_RUNTIME_SERVICES_DATA, paddr, hole, EFI_MEMORY_UC);
numbytes -= hole;
paddr += hole;
count++ ;
md += mdsize;
}
}
build_mem_desc(md, EFI_CONVENTIONAL_MEMORY, paddr, numbytes, EFI_MEMORY_WB|EFI_MEMORY_WB);
md += mdsize ;
count++ ;
}
}
}
return count ;
}
void
build_init(unsigned long args)
{
sn_config = (sn_config_t *) (args);
sn_memmap = (sn_memmap_t *)(args + 8) ; /* SN equiv for this is */
/* init to klconfig start */
}
/*
*
* 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.
*
* Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/config.h>
/*
* Structure of the mem config of the node as a SN MI reg
* Medusa supports this reg config.
*
* BankSize nibble to bank size mapping
*
* 1 - 64 MB
* 2 - 128 MB
* 3 - 256 MB
* 4 - 512 MB
* 5 - 1024 MB (1GB)
*/
#define MBSHIFT 20
#ifdef SGI_SN2
typedef struct node_memmap_s
{
unsigned int b0size :3, /* 0-2 bank 0 size */
b0dou :1, /* 3 bank 0 is 2-sided */
ena0 :1, /* 4 bank 0 enabled */
r0 :3, /* 5-7 reserved */
b1size :3, /* 8-10 bank 1 size */
b1dou :1, /* 11 bank 1 is 2-sided */
ena1 :1, /* 12 bank 1 enabled */
r1 :3, /* 13-15 reserved */
b2size :3, /* 16-18 bank 2 size */
b2dou :1, /* 19 bank 1 is 2-sided */
ena2 :1, /* 20 bank 2 enabled */
r2 :3, /* 21-23 reserved */
b3size :3, /* 24-26 bank 3 size */
b3dou :1, /* 27 bank 3 is 2-sided */
ena3 :1, /* 28 bank 3 enabled */
r3 :3; /* 29-31 reserved */
} node_memmap_t ;
#define SN2_BANK_SIZE_SHIFT (MBSHIFT+6) /* 64 MB */
#define BankPresent(bsize) (bsize<6)
#define BankSizeBytes(bsize) (BankPresent(bsize) ? 1UL<<((bsize)+SN2_BANK_SIZE_SHIFT) : 0)
#define MD_BANKS_PER_NODE 4
#define MD_BANKSIZE (1UL << 34)
#endif
typedef struct sn_memmap_s
{
short nasid ;
short cpuconfig;
node_memmap_t node_memmap ;
} sn_memmap_t ;
typedef struct sn_config_s
{
int cpus;
int nodes;
sn_memmap_t memmap[1]; /* start of array */
} sn_config_t;
extern void build_init(unsigned long);
extern int build_efi_memmap(void *, int);
extern int GetNumNodes(void);
extern int GetNumCpus(void);
extern int IsCpuPresent(int, int);
extern int GetNasid(int);
/*
* 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.
*
* Copyright (c) 2002-2003 Silicon Graphics, Inc. All Rights Reserved.
*/
OUTPUT_FORMAT("elf64-ia64-little")
OUTPUT_ARCH(ia64)
ENTRY(_start)
SECTIONS
{
v = 0x0000000000000000 ; /* this symbol is here to make debugging with kdb easier... */
. = (0x000000000000000 + 0x100000) ;
_text = .;
.text : AT(ADDR(.text) - 0x0000000000000000 )
{
*(__ivt_section)
/* these are not really text pages, but the zero page needs to be in a fixed location: */
*(__special_page_section)
__start_gate_section = .;
*(__gate_section)
__stop_gate_section = .;
*(.text)
}
/* Global data */
_data = .;
.rodata : AT(ADDR(.rodata) - 0x0000000000000000 )
{ *(.rodata) *(.rodata.*) }
.opd : AT(ADDR(.opd) - 0x0000000000000000 )
{ *(.opd) }
.data : AT(ADDR(.data) - 0x0000000000000000 )
{ *(.data) *(.gnu.linkonce.d*) CONSTRUCTORS }
__gp = ALIGN (8) + 0x200000;
.got : AT(ADDR(.got) - 0x0000000000000000 )
{ *(.got.plt) *(.got) }
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
.sdata : AT(ADDR(.sdata) - 0x0000000000000000 )
{ *(.sdata) }
_edata = .;
_bss = .;
.sbss : AT(ADDR(.sbss) - 0x0000000000000000 )
{ *(.sbss) *(.scommon) }
.bss : AT(ADDR(.bss) - 0x0000000000000000 )
{ *(.bss) *(COMMON) }
. = ALIGN(64 / 8);
_end = .;
/* Sections to be discarded */
/DISCARD/ : {
*(.text.exit)
*(.data.exit)
}
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* These must appear regardless of . */
/* Discard them for now since Intel SoftSDV cannot handle them.
.comment 0 : { *(.comment) }
.note 0 : { *(.note) }
*/
/DISCARD/ : { *(.comment) }
/DISCARD/ : { *(.note) }
}
/*
*
* 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-2003 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 SGI_SN2
#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 SGI_SN2
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 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 init
1: 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 node
1: 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 1b
2:
mov r23 = 2;; // All done, release the spinning cpus
st4 [r22] = r23
initx:
//
// I/O-port space base address:
//
movl r2 = IOPB_PA;;
mov ar.k0 = r2
// Now call main & pass it the current LID value.
alloc r2=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 medusa
slave:
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 16384
bootstack:
.skip 16384
bootstacke:
initlock:
data4
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// This code emulates the PAL. Only essential interfaces are emulated.
.text
.global pal_emulator
.proc pal_emulator
pal_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 SGI_SN2
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=r0
1: br.cond.sptk.few rp
stacked:
br.ret.sptk.few rp
.endp pal_emulator
/*
* PAL & SAL emulation.
*
* Copyright (C) 1998-2000 Hewlett-Packard Co
* Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
*
*
* Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/NoticeExplan
*/
#include <linux/config.h>
#include <linux/efi.h>
#include <linux/kernel.h>
#include <asm/pal.h>
#include <asm/sal.h>
#include <asm/sn/sn_sal.h>
#include <asm/processor.h>
#include <asm/sn/sn_cpuid.h>
#ifdef SGI_SN2
#include <asm/sn/sn2/addrs.h>
#include <asm/sn/sn2/shub_mmr.h>
#endif
#include <linux/acpi.h>
#include "fpmem.h"
#define RSDP_NAME "RSDP"
#define RSDP_SIG "RSD PTR " /* RSDT Pointer signature */
#define APIC_SIG "APIC" /* Multiple APIC Description Table */
#define DSDT_SIG "DSDT" /* Differentiated System Description Table */
#define FADT_SIG "FACP" /* Fixed ACPI Description Table */
#define FACS_SIG "FACS" /* Firmware ACPI Control Structure */
#define PSDT_SIG "PSDT" /* Persistent System Description Table */
#define RSDT_SIG "RSDT" /* Root System Description Table */
#define XSDT_SIG "XSDT" /* Extended System Description Table */
#define SSDT_SIG "SSDT" /* Secondary System Description Table */
#define SBST_SIG "SBST" /* Smart Battery Specification Table */
#define SPIC_SIG "SPIC" /* IOSAPIC table */
#define SRAT_SIG "SRAT" /* SRAT table */
#define SLIT_SIG "SLIT" /* SLIT table */
#define BOOT_SIG "BOOT" /* Boot table */
#define ACPI_SRAT_REVISION 1
#define ACPI_SLIT_REVISION 1
#define OEMID "SGI"
#ifdef SGI_SN2
#define PRODUCT "SN2"
#define PROXIMITY_DOMAIN(nasid) (((nasid)>>1) & 255)
#endif
#define MB (1024*1024UL)
#define GB (MB*1024UL)
#define BOOT_PARAM_ADDR 0x40000
#define MAX(i,j) ((i) > (j) ? (i) : (j))
#define MIN(i,j) ((i) < (j) ? (i) : (j))
#define ALIGN8(p) (((long)(p) +7) & ~7)
#define FPROM_BUG() do {while (1);} while (0)
#define MAX_SN_NODES 128
#define MAX_LSAPICS 512
#define MAX_CPUS 512
#define MAX_CPUS_NODE 4
#define CPUS_PER_NODE 4
#define CPUS_PER_FSB 2
#define CPUS_PER_FSB_MASK (CPUS_PER_FSB-1)
#define NUM_EFI_DESCS 2
#define RSDP_CHECKSUM_LENGTH 20
typedef union ia64_nasid_va {
struct {
#if defined(SGI_SN2)
unsigned long off : 36; /* intra-region offset */
unsigned long attr : 2;
unsigned long nasid : 11; /* NASID */
unsigned long off2 : 12; /* fill */
unsigned long reg : 3; /* region number */
#endif
} f;
unsigned long l;
void *p;
} ia64_nasid_va;
typedef struct {
unsigned long pc;
unsigned long gp;
} func_ptr_t;
#define IS_VIRTUAL_MODE() ({struct ia64_psr psr; asm("mov %0=psr" : "=r"(psr)); psr.dt;})
#define ADDR_OF(p) (IS_VIRTUAL_MODE() ? ((void*)((long)(p)+PAGE_OFFSET)) : ((void*) (p)))
#if defined(SGI_SN2)
#define __fwtab_pa(n,x) ({ia64_nasid_va _v; _v.l = (long) (x); _v.f.nasid = (x) ? (n) : 0; _v.f.reg = 0; _v.f.attr = 3; _v.l;})
#endif
/*
* The following variables are passed thru registersfrom the configuration file and
* are set via the _start function.
*/
long base_nasid;
long num_cpus;
long bsp_entry_pc=0;
long num_nodes;
long app_entry_pc;
int bsp_lid;
func_ptr_t ap_entry;
extern void pal_emulator(void);
static efi_runtime_services_t *efi_runtime_p;
static char fw_mem[( sizeof(efi_system_table_t)
+ sizeof(efi_runtime_services_t)
+ NUM_EFI_DESCS*sizeof(efi_config_table_t)
+ sizeof(struct ia64_sal_systab)
+ sizeof(struct ia64_sal_desc_entry_point)
+ sizeof(struct ia64_sal_desc_ap_wakeup)
+ sizeof(struct acpi20_table_rsdp)
+ sizeof(struct acpi_table_xsdt)
+ sizeof(struct acpi_table_slit)
+ MAX_SN_NODES*MAX_SN_NODES+8
+ sizeof(struct acpi_table_madt)
+ 16*MAX_CPUS
+ (1+8*MAX_SN_NODES)*(sizeof(efi_memory_desc_t))
+ sizeof(struct acpi_table_srat)
+ MAX_CPUS*sizeof(struct acpi_table_processor_affinity)
+ MAX_SN_NODES*sizeof(struct acpi_table_memory_affinity)
+ sizeof(ia64_sal_desc_ptc_t) +
+ MAX_SN_NODES*sizeof(ia64_sal_ptc_domain_info_t) +
+ MAX_CPUS*sizeof(ia64_sal_ptc_domain_proc_entry_t) +
+ 1024)] __attribute__ ((aligned (8)));
static efi_status_t
efi_get_time (efi_time_t *tm, efi_time_cap_t *tc)
{
if (tm) {
memset(tm, 0, sizeof(*tm));
tm->year = 2000;
tm->month = 2;
tm->day = 13;
tm->hour = 10;
tm->minute = 11;
tm->second = 12;
}
if (tc) {
tc->resolution = 10;
tc->accuracy = 12;
tc->sets_to_zero = 1;
}
return EFI_SUCCESS;
}
static void
efi_reset_system (int reset_type, efi_status_t status, unsigned long data_size, efi_char16_t *data)
{
while(1); /* Is there a pseudo-op to stop medusa */
}
static efi_status_t
efi_success (void)
{
return EFI_SUCCESS;
}
static efi_status_t
efi_unimplemented (void)
{
return EFI_UNSUPPORTED;
}
#ifdef SGI_SN2
#undef cpu_physical_id
#define cpu_physical_id(cpuid) ((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff)
void
fprom_send_cpei(void) {
long *p, val;
long physid;
long nasid, slice;
physid = cpu_physical_id(0);
nasid = cpu_physical_id_to_nasid(physid);
slice = cpu_physical_id_to_slice(physid);
p = (long*)GLOBAL_MMR_ADDR(nasid, SH_IPI_INT);
val = (1UL<<SH_IPI_INT_SEND_SHFT) |
(physid<<SH_IPI_INT_PID_SHFT) |
((long)0<<SH_IPI_INT_TYPE_SHFT) |
((long)0x1e<<SH_IPI_INT_IDX_SHFT) |
(0x000feeUL<<SH_IPI_INT_BASE_SHFT);
*p = val;
}
#endif
static struct sal_ret_values
sal_emulator (long index, unsigned long in1, unsigned long in2,
unsigned long in3, unsigned long in4, unsigned long in5,
unsigned long in6, unsigned long in7)
{
long r9 = 0;
long r10 = 0;
long r11 = 0;
long status;
/*
* Don't do a "switch" here since that gives us code that
* isn't self-relocatable.
*/
status = 0;
if (index == SAL_FREQ_BASE) {
switch (in1) {
case SAL_FREQ_BASE_PLATFORM:
r9 = 500000000;
break;
case SAL_FREQ_BASE_INTERVAL_TIMER:
/*
* Is this supposed to be the cr.itc frequency
* or something platform specific? The SAL
* doc ain't exactly clear on this...
*/
r9 = 700000000;
break;
case SAL_FREQ_BASE_REALTIME_CLOCK:
r9 = 50000000;
break;
default:
status = -1;
break;
}
} else if (index == SAL_SET_VECTORS) {
if (in1 == SAL_VECTOR_OS_BOOT_RENDEZ) {
func_ptr_t *fp;
fp = ADDR_OF(&ap_entry);
fp->pc = in2;
fp->gp = in3;
} else if (in1 == SAL_VECTOR_OS_MCA || in1 == SAL_VECTOR_OS_INIT) {
} else {
status = -1;
}
;
} else if (index == SAL_GET_STATE_INFO) {
;
} else if (index == SAL_GET_STATE_INFO_SIZE) {
r9 = 10000;
;
} else if (index == SAL_CLEAR_STATE_INFO) {
;
} else if (index == SAL_MC_RENDEZ) {
;
} else if (index == SAL_MC_SET_PARAMS) {
;
} else if (index == SAL_CACHE_FLUSH) {
;
} else if (index == SAL_CACHE_INIT) {
;
} else if (index == SAL_UPDATE_PAL) {
;
#ifdef SGI_SN2
} else if (index == SN_SAL_LOG_CE) {
#ifdef ajmtestcpei
fprom_send_cpei();
#else /* ajmtestcpei */
;
#endif /* ajmtestcpei */
#endif
} else if (index == SN_SAL_PROBE) {
r9 = 0UL;
if (in2 == 4) {
r9 = *(unsigned *)in1;
if (r9 == -1) {
status = 1;
}
} else if (in2 == 2) {
r9 = *(unsigned short *)in1;
if (r9 == -1) {
status = 1;
}
} else if (in2 == 1) {
r9 = *(unsigned char *)in1;
if (r9 == -1) {
status = 1;
}
} else if (in2 == 8) {
r9 = *(unsigned long *)in1;
if (r9 == -1) {
status = 1;
}
} else {
status = 2;
}
} else if (index == SN_SAL_GET_KLCONFIG_ADDR) {
r9 = 0x30000;
} else if (index == SN_SAL_CONSOLE_PUTC) {
status = -1;
} else if (index == SN_SAL_CONSOLE_GETC) {
status = -1;
} else if (index == SN_SAL_CONSOLE_POLL) {
status = -1;
} else if (index == SN_SAL_SYSCTL_IOBRICK_MODULE_GET) {
status = -1;
} else {
status = -1;
}
asm volatile ("" :: "r"(r9), "r"(r10), "r"(r11));
return ((struct sal_ret_values) {status, r9, r10, r11});
}
/*
* This is here to work around a bug in egcs-1.1.1b that causes the
* compiler to crash (seems like a bug in the new alias analysis code.
*/
void *
id (long addr)
{
return (void *) addr;
}
/*
* Fix the addresses in a function pointer by adding base node address
* to pc & gp.
*/
void
fix_function_pointer(void *fp)
{
func_ptr_t *_fp;
_fp = fp;
_fp->pc = __fwtab_pa(base_nasid, _fp->pc);
_fp->gp = __fwtab_pa(base_nasid, _fp->gp);
}
void
fix_virt_function_pointer(void **fptr)
{
func_ptr_t *fp;
long *p;
p = (long*)fptr;
fp = *fptr;
fp->pc = fp->pc | PAGE_OFFSET;
fp->gp = fp->gp | PAGE_OFFSET;
*p |= PAGE_OFFSET;
}
int
efi_set_virtual_address_map(void)
{
efi_runtime_services_t *runtime;
runtime = efi_runtime_p;
fix_virt_function_pointer((void**)&runtime->get_time);
fix_virt_function_pointer((void**)&runtime->set_time);
fix_virt_function_pointer((void**)&runtime->get_wakeup_time);
fix_virt_function_pointer((void**)&runtime->set_wakeup_time);
fix_virt_function_pointer((void**)&runtime->set_virtual_address_map);
fix_virt_function_pointer((void**)&runtime->get_variable);
fix_virt_function_pointer((void**)&runtime->get_next_variable);
fix_virt_function_pointer((void**)&runtime->set_variable);
fix_virt_function_pointer((void**)&runtime->get_next_high_mono_count);
fix_virt_function_pointer((void**)&runtime->reset_system);
return EFI_SUCCESS;
}
void
acpi_table_initx(struct acpi_table_header *p, char *sig, int siglen, int revision, int oem_revision)
{
memcpy(p->signature, sig, siglen);
memcpy(p->oem_id, OEMID, 6);
memcpy(p->oem_table_id, sig, 4);
memcpy(p->oem_table_id+4, PRODUCT, 4);
p->revision = revision;
p->oem_revision = (revision<<16) + oem_revision;
memcpy(p->asl_compiler_id, "FPRM", 4);
p->asl_compiler_revision = 1;
}
void
acpi_checksum(struct acpi_table_header *p, int length)
{
u8 *cp, *cpe, checksum;
p->checksum = 0;
p->length = length;
checksum = 0;
for (cp=(u8*)p, cpe=cp+p->length; cp<cpe; cp++)
checksum += *cp;
p->checksum = -checksum;
}
void
acpi_checksum_rsdp20(struct acpi20_table_rsdp *p, int length)
{
u8 *cp, *cpe, checksum;
p->checksum = 0;
p->ext_checksum = 0;
p->length = length;
checksum = 0;
for (cp=(u8*)p, cpe=cp+20; cp<cpe; cp++)
checksum += *cp;
p->checksum = -checksum;
checksum = 0;
for (cp=(u8*)p, cpe=cp+length; cp<cpe; cp++)
checksum += *cp;
p->ext_checksum = -checksum;
}
int
nasid_present(int nasid)
{
int cnode;
for (cnode=0; cnode<num_nodes; cnode++)
if (GetNasid(cnode) == nasid)
return 1;
return 0;
}
void
sys_fw_init (const char *args, int arglen, int bsp)
{
/*
* Use static variables to keep from overflowing the RSE stack
*/
static efi_system_table_t *efi_systab;
static efi_runtime_services_t *efi_runtime;
static efi_config_table_t *efi_tables;
static ia64_sal_desc_ptc_t *sal_ptc;
static ia64_sal_ptc_domain_info_t *sal_ptcdi;
static ia64_sal_ptc_domain_proc_entry_t *sal_ptclid;
static struct acpi20_table_rsdp *acpi20_rsdp;
static struct acpi_table_xsdt *acpi_xsdt;
static struct acpi_table_slit *acpi_slit;
static struct acpi_table_madt *acpi_madt;
static struct acpi_table_lsapic *lsapic20;
static struct ia64_sal_systab *sal_systab;
static struct acpi_table_srat *acpi_srat;
static struct acpi_table_processor_affinity *srat_cpu_affinity;
static struct acpi_table_memory_affinity *srat_memory_affinity;
static efi_memory_desc_t *efi_memmap, *md;
static unsigned long *pal_desc, *sal_desc;
static struct ia64_sal_desc_entry_point *sal_ed;
static struct ia64_boot_param *bp;
static struct ia64_sal_desc_ap_wakeup *sal_apwake;
static unsigned char checksum;
static char *cp, *cmd_line, *vendor;
static void *ptr;
static int mdsize, domain, last_domain ;
static int i, j, cnode, max_nasid, nasid, cpu, num_memmd, cpus_found;
/*
* Pass the parameter base address to the build_efi_xxx routines.
*/
#if defined(SGI_SN2)
build_init(0x3000000000UL | ((long)base_nasid<<38));
#endif
num_nodes = GetNumNodes();
num_cpus = GetNumCpus();
for (max_nasid=0, cnode=0; cnode<num_nodes; cnode++)
max_nasid = MAX(max_nasid, GetNasid(cnode));
memset(fw_mem, 0, sizeof(fw_mem));
pal_desc = (unsigned long *) &pal_emulator;
sal_desc = (unsigned long *) &sal_emulator;
fix_function_pointer(&pal_emulator);
fix_function_pointer(&sal_emulator);
/* Align this to 16 bytes, probably EFI does this */
mdsize = (sizeof(efi_memory_desc_t) + 15) & ~15 ;
cp = fw_mem;
efi_systab = (void *) cp; cp += ALIGN8(sizeof(*efi_systab));
efi_runtime_p = efi_runtime = (void *) cp; cp += ALIGN8(sizeof(*efi_runtime));
efi_tables = (void *) cp; cp += ALIGN8(NUM_EFI_DESCS*sizeof(*efi_tables));
sal_systab = (void *) cp; cp += ALIGN8(sizeof(*sal_systab));
sal_ed = (void *) cp; cp += ALIGN8(sizeof(*sal_ed));
sal_ptc = (void *) cp; cp += ALIGN8(sizeof(*sal_ptc));
sal_apwake = (void *) cp; cp += ALIGN8(sizeof(*sal_apwake));
acpi20_rsdp = (void *) cp; cp += ALIGN8(sizeof(*acpi20_rsdp));
acpi_xsdt = (void *) cp; cp += ALIGN8(sizeof(*acpi_xsdt) + 64);
/* save space for more OS defined table pointers. */
acpi_slit = (void *) cp; cp += ALIGN8(sizeof(*acpi_slit) + 8 + (max_nasid+1)*(max_nasid+1));
acpi_madt = (void *) cp; cp += ALIGN8(sizeof(*acpi_madt) + sizeof(struct acpi_table_lsapic) * (num_cpus+1));
acpi_srat = (void *) cp; cp += ALIGN8(sizeof(struct acpi_table_srat));
cp += sizeof(struct acpi_table_processor_affinity)*num_cpus + sizeof(struct acpi_table_memory_affinity)*num_nodes;
vendor = (char *) cp; cp += ALIGN8(40);
efi_memmap = (void *) cp; cp += ALIGN8(8*32*sizeof(*efi_memmap));
sal_ptcdi = (void *) cp; cp += ALIGN8(CPUS_PER_FSB*(1+num_nodes)*sizeof(*sal_ptcdi));
sal_ptclid = (void *) cp; cp += ALIGN8(((3+num_cpus)*sizeof(*sal_ptclid)+7)/8*8);
cmd_line = (void *) cp;
if (args) {
if (arglen >= 1024)
arglen = 1023;
memcpy(cmd_line, args, arglen);
} else {
arglen = 0;
}
cmd_line[arglen] = '\0';
/*
* For now, just bring up bash.
* If you want to execute all the startup scripts, delete the "init=..".
* You can also edit this line to pass other arguments to the kernel.
* Note: disable kernel text replication.
*/
strcpy(cmd_line, "init=/bin/bash console=ttyS0");
memset(efi_systab, 0, sizeof(efi_systab));
efi_systab->hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE;
efi_systab->hdr.revision = EFI_SYSTEM_TABLE_REVISION;
efi_systab->hdr.headersize = sizeof(efi_systab->hdr);
efi_systab->fw_vendor = __fwtab_pa(base_nasid, vendor);
efi_systab->fw_revision = 1;
efi_systab->runtime = __fwtab_pa(base_nasid, efi_runtime);
efi_systab->nr_tables = 2;
efi_systab->tables = __fwtab_pa(base_nasid, efi_tables);
memcpy(vendor, "S\0i\0l\0i\0c\0o\0n\0-\0G\0r\0a\0p\0h\0i\0c\0s\0\0", 40);
efi_runtime->hdr.signature = EFI_RUNTIME_SERVICES_SIGNATURE;
efi_runtime->hdr.revision = EFI_RUNTIME_SERVICES_REVISION;
efi_runtime->hdr.headersize = sizeof(efi_runtime->hdr);
efi_runtime->get_time = __fwtab_pa(base_nasid, &efi_get_time);
efi_runtime->set_time = __fwtab_pa(base_nasid, &efi_unimplemented);
efi_runtime->get_wakeup_time = __fwtab_pa(base_nasid, &efi_unimplemented);
efi_runtime->set_wakeup_time = __fwtab_pa(base_nasid, &efi_unimplemented);
efi_runtime->set_virtual_address_map = __fwtab_pa(base_nasid, &efi_set_virtual_address_map);
efi_runtime->get_variable = __fwtab_pa(base_nasid, &efi_unimplemented);
efi_runtime->get_next_variable = __fwtab_pa(base_nasid, &efi_unimplemented);
efi_runtime->set_variable = __fwtab_pa(base_nasid, &efi_unimplemented);
efi_runtime->get_next_high_mono_count = __fwtab_pa(base_nasid, &efi_unimplemented);
efi_runtime->reset_system = __fwtab_pa(base_nasid, &efi_reset_system);
efi_tables->guid = SAL_SYSTEM_TABLE_GUID;
efi_tables->table = __fwtab_pa(base_nasid, sal_systab);
efi_tables++;
efi_tables->guid = ACPI_20_TABLE_GUID;
efi_tables->table = __fwtab_pa(base_nasid, acpi20_rsdp);
efi_tables++;
fix_function_pointer(&efi_unimplemented);
fix_function_pointer(&efi_get_time);
fix_function_pointer(&efi_success);
fix_function_pointer(&efi_reset_system);
fix_function_pointer(&efi_set_virtual_address_map);
/* fill in the ACPI20 system table - has a pointer to the ACPI table header */
memcpy(acpi20_rsdp->signature, "RSD PTR ", 8);
acpi20_rsdp->xsdt_address = (u64)__fwtab_pa(base_nasid, acpi_xsdt);
acpi20_rsdp->revision = 2;
acpi_checksum_rsdp20(acpi20_rsdp, sizeof(struct acpi20_table_rsdp));
/* Set up the XSDT table - contains pointers to the other ACPI tables */
acpi_table_initx(&acpi_xsdt->header, XSDT_SIG, 4, 1, 1);
acpi_xsdt->entry[0] = __fwtab_pa(base_nasid, acpi_madt);
acpi_xsdt->entry[1] = __fwtab_pa(base_nasid, acpi_slit);
acpi_xsdt->entry[2] = __fwtab_pa(base_nasid, acpi_srat);
acpi_checksum(&acpi_xsdt->header, sizeof(struct acpi_table_xsdt) + 16);
/* Set up the APIC table */
acpi_table_initx(&acpi_madt->header, APIC_SIG, 4, 1, 1);
lsapic20 = (struct acpi_table_lsapic*) (acpi_madt + 1);
for (cnode=0; cnode<num_nodes; cnode++) {
nasid = GetNasid(cnode);
for(cpu=0; cpu<CPUS_PER_NODE; cpu++) {
if (!IsCpuPresent(cnode, cpu))
continue;
lsapic20->header.type = ACPI_MADT_LSAPIC;
lsapic20->header.length = sizeof(struct acpi_table_lsapic);
lsapic20->acpi_id = cnode*4+cpu;
lsapic20->flags.enabled = 1;
#if defined(SGI_SN2)
lsapic20->eid = nasid&0xffff;
lsapic20->id = (cpu<<4) | (nasid>>16);
#endif
lsapic20 = (struct acpi_table_lsapic*) ((long)lsapic20+sizeof(struct acpi_table_lsapic));
}
}
acpi_checksum(&acpi_madt->header, (char*)lsapic20 - (char*)acpi_madt);
/* Set up the SRAT table */
acpi_table_initx(&acpi_srat->header, SRAT_SIG, 4, ACPI_SRAT_REVISION, 1);
ptr = acpi_srat+1;
for (cnode=0; cnode<num_nodes; cnode++) {
nasid = GetNasid(cnode);
srat_memory_affinity = ptr;
ptr = srat_memory_affinity+1;
srat_memory_affinity->header.type = ACPI_SRAT_MEMORY_AFFINITY;
srat_memory_affinity->header.length = sizeof(struct acpi_table_memory_affinity);
srat_memory_affinity->proximity_domain = PROXIMITY_DOMAIN(nasid);
srat_memory_affinity->base_addr_lo = 0;
srat_memory_affinity->length_lo = 0;
#if defined(SGI_SN2)
srat_memory_affinity->base_addr_hi = (nasid<<6) | (3<<4);
srat_memory_affinity->length_hi = (MD_BANKSIZE*MD_BANKS_PER_NODE)>>32;
#endif
srat_memory_affinity->memory_type = ACPI_ADDRESS_RANGE_MEMORY;
srat_memory_affinity->flags.enabled = 1;
}
for (cnode=0; cnode<num_nodes; cnode++) {
nasid = GetNasid(cnode);
for(cpu=0; cpu<CPUS_PER_NODE; cpu++) {
if (!IsCpuPresent(cnode, cpu))
continue;
srat_cpu_affinity = ptr;
ptr = srat_cpu_affinity + 1;
srat_cpu_affinity->header.type = ACPI_SRAT_PROCESSOR_AFFINITY;
srat_cpu_affinity->header.length = sizeof(struct acpi_table_processor_affinity);
srat_cpu_affinity->proximity_domain = PROXIMITY_DOMAIN(nasid);
srat_cpu_affinity->flags.enabled = 1;
#if defined(SGI_SN2)
srat_cpu_affinity->lsapic_eid = nasid&0xffff;
srat_cpu_affinity->apic_id = (cpu<<4) | (nasid>>16);
#endif
}
}
acpi_checksum(&acpi_srat->header, (char*)ptr - (char*)acpi_srat);
/* Set up the SLIT table */
acpi_table_initx(&acpi_slit->header, SLIT_SIG, 4, ACPI_SLIT_REVISION, 1);
acpi_slit->localities = PROXIMITY_DOMAIN(max_nasid)+1;
cp=acpi_slit->entry;
memset(cp, 255, acpi_slit->localities*acpi_slit->localities);
for (i=0; i<=max_nasid; i++)
for (j=0; j<=max_nasid; j++)
if (nasid_present(i) && nasid_present(j))
*(cp+PROXIMITY_DOMAIN(i)*acpi_slit->localities+PROXIMITY_DOMAIN(j)) = 10 + MIN(254, 5*abs(i-j));
cp = acpi_slit->entry + acpi_slit->localities*acpi_slit->localities;
acpi_checksum(&acpi_slit->header, cp - (char*)acpi_slit);
/* fill in the SAL system table: */
memcpy(sal_systab->signature, "SST_", 4);
sal_systab->size = sizeof(*sal_systab);
sal_systab->sal_rev_minor = 1;
sal_systab->sal_rev_major = 0;
sal_systab->entry_count = 3;
sal_systab->sal_b_rev_major = 0x1; /* set the SN SAL rev to */
sal_systab->sal_b_rev_minor = 0x0; /* 1.00 */
strcpy(sal_systab->oem_id, "SGI");
strcpy(sal_systab->product_id, "SN2");
/* fill in an entry point: */
sal_ed->type = SAL_DESC_ENTRY_POINT;
sal_ed->pal_proc = __fwtab_pa(base_nasid, pal_desc[0]);
sal_ed->sal_proc = __fwtab_pa(base_nasid, sal_desc[0]);
sal_ed->gp = __fwtab_pa(base_nasid, sal_desc[1]);
/* kludge the PTC domain info */
sal_ptc->type = SAL_DESC_PTC;
sal_ptc->num_domains = 0;
sal_ptc->domain_info = __fwtab_pa(base_nasid, sal_ptcdi);
cpus_found = 0;
last_domain = -1;
sal_ptcdi--;
for (cnode=0; cnode<num_nodes; cnode++) {
nasid = GetNasid(cnode);
for(cpu=0; cpu<CPUS_PER_NODE; cpu++) {
if (IsCpuPresent(cnode, cpu)) {
domain = cnode*CPUS_PER_NODE + cpu/CPUS_PER_FSB;
if (domain != last_domain) {
sal_ptc->num_domains++;
sal_ptcdi++;
sal_ptcdi->proc_count = 0;
sal_ptcdi->proc_list = __fwtab_pa(base_nasid, sal_ptclid);
last_domain = domain;
}
sal_ptcdi->proc_count++;
sal_ptclid->id = nasid;
sal_ptclid->eid = cpu;
sal_ptclid++;
cpus_found++;
}
}
}
if (cpus_found != num_cpus)
FPROM_BUG();
/* Make the AP WAKEUP entry */
sal_apwake->type = SAL_DESC_AP_WAKEUP;
sal_apwake->mechanism = IA64_SAL_AP_EXTERNAL_INT;
sal_apwake->vector = 18;
for (checksum=0, cp=(char*)sal_systab; cp < (char *)efi_memmap; ++cp)
checksum += *cp;
sal_systab->checksum = -checksum;
/* If the checksum is correct, the kernel tries to use the
* table. We dont build enough table & the kernel aborts.
* Note that the PROM hasd thhhe same problem!!
*/
md = &efi_memmap[0];
num_memmd = build_efi_memmap((void *)md, mdsize) ;
bp = (struct ia64_boot_param*) __fwtab_pa(base_nasid, BOOT_PARAM_ADDR);
bp->efi_systab = __fwtab_pa(base_nasid, &fw_mem);
bp->efi_memmap = __fwtab_pa(base_nasid, efi_memmap);
bp->efi_memmap_size = num_memmd*mdsize;
bp->efi_memdesc_size = mdsize;
bp->efi_memdesc_version = 0x101;
bp->command_line = __fwtab_pa(base_nasid, cmd_line);
bp->console_info.num_cols = 80;
bp->console_info.num_rows = 25;
bp->console_info.orig_x = 0;
bp->console_info.orig_y = 24;
bp->fpswa = 0;
/*
* Now pick the BSP & store it LID value in
* a global variable. Note if BSP is greater than last cpu,
* pick the last cpu.
*/
for (cnode=0; cnode<num_nodes; cnode++) {
for(cpu=0; cpu<CPUS_PER_NODE; cpu++) {
if (!IsCpuPresent(cnode, cpu))
continue;
#ifdef SGI_SN2
bsp_lid = (GetNasid(cnode)<<16) | (cpu<<28);
#endif
if (bsp-- > 0)
continue;
return;
}
}
}
/* $Id: klgraph_init.c,v 1.1 2002/02/28 17:31:25 marcelo Exp $
*
* 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.
*
* Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
*/
/*
* This is a temporary file that statically initializes the expected
* initial klgraph information that is normally provided by prom.
*/
#include <linux/types.h>
#include <linux/config.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <asm/sn/sgi.h>
#include <asm/sn/io.h>
#include <asm/sn/driver.h>
#include <asm/sn/iograph.h>
#include <asm/param.h>
#include <asm/sn/pio.h>
#include <asm/sn/xtalk/xwidget.h>
#include <asm/sn/sn_private.h>
#include <asm/sn/addrs.h>
#include <asm/sn/invent.h>
#include <asm/sn/hcl.h>
#include <asm/sn/hcl_util.h>
#include <asm/sn/intr.h>
#include <asm/sn/xtalk/xtalkaddrs.h>
#include <asm/sn/klconfig.h>
#define SYNERGY_WIDGET ((char *)0xc0000e0000000000)
#define SYNERGY_SWIZZLE ((char *)0xc0000e0000000400)
#define HUBREG ((char *)0xc0000a0001e00000)
#define WIDGET0 ((char *)0xc0000a0000000000)
#define WIDGET4 ((char *)0xc0000a0000000004)
#define SYNERGY_WIDGET ((char *)0xc0000e0000000000)
#define SYNERGY_SWIZZLE ((char *)0xc0000e0000000400)
#define HUBREG ((char *)0xc0000a0001e00000)
#define WIDGET0 ((char *)0xc0000a0000000000)
#define convert(a,b,c) temp = (u64 *)a; *temp = b; temp++; *temp = c
void
klgraph_init(void)
{
u64 *temp;
/*
* Initialize some hub/xbow registers that allows access to
* Xbridge etc. These are normally done in PROM.
*/
/* Write IOERR clear to clear the CRAZY bit in the status */
*(volatile uint64_t *)0xc000000801c001f8 = (uint64_t)0xffffffff;
/* set widget control register...setting bedrock widget id to a */
*(volatile uint64_t *)0xc000000801c00020 = (uint64_t)0x801a;
/* set io outbound widget access...allow all */
*(volatile uint64_t *)0xc000000801c00110 = (uint64_t)0xff01;
/* set io inbound widget access...allow all */
*(volatile uint64_t *)0xc000000801c00118 = (uint64_t)0xff01;
/* set io crb timeout to max */
*(volatile uint64_t *)0xc000000801c003c0 = (uint64_t)0xffffff;
*(volatile uint64_t *)0xc000000801c003c0 = (uint64_t)0xffffff;
/* set local block io permission...allow all */
// [LB] *(volatile uint64_t *)0xc000000801e04010 = (uint64_t)0xfffffffffffffff;
/* clear any errors */
/* clear_ii_error(); medusa should have cleared these */
/* set default read response buffers in bridge */
// [PI] *(volatile u32 *)0xc00000080f000280L = 0xba98;
// [PI] *(volatile u32 *)0xc00000080f000288L = 0xba98;
/*
* klconfig entries initialization - mankato
*/
convert(0xe000003000030000, 0x00000000beedbabe, 0x0000004800000000);
convert(0xe000003000030010, 0x0003007000000018, 0x800002000f820178);
convert(0xe000003000030020, 0x80000a000f024000, 0x800002000f800000);
convert(0xe000003000030030, 0x0300fafa00012580, 0x00000000040f0000);
convert(0xe000003000030040, 0x0000000000000000, 0x0003097000030070);
convert(0xe000003000030050, 0x00030970000303b0, 0x0003181000033f70);
convert(0xe000003000030060, 0x0003d51000037570, 0x0000000000038330);
convert(0xe000003000030070, 0x0203110100030140, 0x0001000000000101);
convert(0xe000003000030080, 0x0900000000000000, 0x000000004e465e67);
convert(0xe000003000030090, 0x0003097000000000, 0x00030b1000030a40);
convert(0xe0000030000300a0, 0x00030cb000030be0, 0x000315a0000314d0);
convert(0xe0000030000300b0, 0x0003174000031670, 0x0000000000000000);
convert(0xe000003000030100, 0x000000000000001a, 0x3350490000000000);
convert(0xe000003000030110, 0x0000000000000037, 0x0000000000000000);
convert(0xe000003000030140, 0x0002420100030210, 0x0001000000000101);
convert(0xe000003000030150, 0x0100000000000000, 0xffffffffffffffff);
convert(0xe000003000030160, 0x00030d8000000000, 0x0000000000030e50);
convert(0xe0000030000301c0, 0x0000000000000000, 0x0000000000030070);
convert(0xe0000030000301d0, 0x0000000000000025, 0x424f490000000000);
convert(0xe0000030000301e0, 0x000000004b434952, 0x0000000000000000);
convert(0xe000003000030210, 0x00027101000302e0, 0x00010000000e4101);
convert(0xe000003000030220, 0x0200000000000000, 0xffffffffffffffff);
convert(0xe000003000030230, 0x00030f2000000000, 0x0000000000030ff0);
convert(0xe000003000030290, 0x0000000000000000, 0x0000000000030140);
convert(0xe0000030000302a0, 0x0000000000000026, 0x7262490000000000);
convert(0xe0000030000302b0, 0x00000000006b6369, 0x0000000000000000);
convert(0xe0000030000302e0, 0x0002710100000000, 0x00010000000f3101);
convert(0xe0000030000302f0, 0x0500000000000000, 0xffffffffffffffff);
convert(0xe000003000030300, 0x000310c000000000, 0x0003126000031190);
convert(0xe000003000030310, 0x0003140000031330, 0x0000000000000000);
convert(0xe000003000030360, 0x0000000000000000, 0x0000000000030140);
convert(0xe000003000030370, 0x0000000000000029, 0x7262490000000000);
convert(0xe000003000030380, 0x00000000006b6369, 0x0000000000000000);
convert(0xe000003000030970, 0x0000000002010102, 0x0000000000000000);
convert(0xe000003000030980, 0x000000004e465e67, 0xffffffff00000000);
/* convert(0x00000000000309a0, 0x0000000000037570, 0x0000000100000000); */
convert(0xe0000030000309a0, 0x0000000000037570, 0xffffffff00000000);
convert(0xe0000030000309b0, 0x0000000000030070, 0x0000000000000000);
convert(0xe0000030000309c0, 0x000000000003f420, 0x0000000000000000);
convert(0xe000003000030a40, 0x0000000002010125, 0x0000000000000000);
convert(0xe000003000030a50, 0xffffffffffffffff, 0xffffffff00000000);
convert(0xe000003000030a70, 0x0000000000037b78, 0x0000000000000000);
convert(0xe000003000030b10, 0x0000000002010125, 0x0000000000000000);
convert(0xe000003000030b20, 0xffffffffffffffff, 0xffffffff00000000);
convert(0xe000003000030b40, 0x0000000000037d30, 0x0000000000000001);
convert(0xe000003000030be0, 0x00000000ff010203, 0x0000000000000000);
convert(0xe000003000030bf0, 0xffffffffffffffff, 0xffffffff000000ff);
convert(0xe000003000030c10, 0x0000000000037ee8, 0x0100010000000200);
convert(0xe000003000030cb0, 0x00000000ff310111, 0x0000000000000000);
convert(0xe000003000030cc0, 0xffffffffffffffff, 0x0000000000000000);
convert(0xe000003000030d80, 0x0000000002010104, 0x0000000000000000);
convert(0xe000003000030d90, 0xffffffffffffffff, 0x00000000000000ff);
convert(0xe000003000030db0, 0x0000000000037f18, 0x0000000000000000);
convert(0xe000003000030dc0, 0x0000000000000000, 0x0003007000060000);
convert(0xe000003000030de0, 0x0000000000000000, 0x0003021000050000);
convert(0xe000003000030df0, 0x000302e000050000, 0x0000000000000000);
convert(0xe000003000030e30, 0x0000000000000000, 0x000000000000000a);
convert(0xe000003000030e50, 0x00000000ff00011a, 0x0000000000000000);
convert(0xe000003000030e60, 0xffffffffffffffff, 0x0000000000000000);
convert(0xe000003000030e80, 0x0000000000037fe0, 0x9e6e9e9e9e9e9e9e);
convert(0xe000003000030e90, 0x000000000000bc6e, 0x0000000000000000);
convert(0xe000003000030f20, 0x0000000002010205, 0x00000000d0020000);
convert(0xe000003000030f30, 0xffffffffffffffff, 0x0000000e0000000e);
convert(0xe000003000030f40, 0x000000000000000e, 0x0000000000000000);
convert(0xe000003000030f50, 0x0000000000038010, 0x00000000000007ff);
convert(0xe000003000030f70, 0x0000000000000000, 0x0000000022001077);
convert(0xe000003000030fa0, 0x0000000000000000, 0x000000000003f4a8);
convert(0xe000003000030ff0, 0x0000000000310120, 0x0000000000000000);
convert(0xe000003000031000, 0xffffffffffffffff, 0xffffffff00000002);
convert(0xe000003000031010, 0x000000000000000e, 0x0000000000000000);
convert(0xe000003000031020, 0x0000000000038088, 0x0000000000000000);
convert(0xe0000030000310c0, 0x0000000002010205, 0x00000000d0020000);
convert(0xe0000030000310d0, 0xffffffffffffffff, 0x0000000f0000000f);
convert(0xe0000030000310e0, 0x000000000000000f, 0x0000000000000000);
convert(0xe0000030000310f0, 0x00000000000380b8, 0x00000000000007ff);
convert(0xe000003000031120, 0x0000000022001077, 0x00000000000310a9);
convert(0xe000003000031130, 0x00000000580211c1, 0x000000008009104c);
convert(0xe000003000031140, 0x0000000000000000, 0x000000000003f4c0);
convert(0xe000003000031190, 0x0000000000310120, 0x0000000000000000);
convert(0xe0000030000311a0, 0xffffffffffffffff, 0xffffffff00000003);
convert(0xe0000030000311b0, 0x000000000000000f, 0x0000000000000000);
convert(0xe0000030000311c0, 0x0000000000038130, 0x0000000000000000);
convert(0xe000003000031260, 0x0000000000110106, 0x0000000000000000);
convert(0xe000003000031270, 0xffffffffffffffff, 0xffffffff00000004);
convert(0xe000003000031270, 0xffffffffffffffff, 0xffffffff00000004);
convert(0xe000003000031280, 0x000000000000000f, 0x0000000000000000);
convert(0xe0000030000312a0, 0x00000000ff110013, 0x0000000000000000);
convert(0xe0000030000312b0, 0xffffffffffffffff, 0xffffffff00000000);
convert(0xe0000030000312c0, 0x000000000000000f, 0x0000000000000000);
convert(0xe0000030000312e0, 0x0000000000110012, 0x0000000000000000);
convert(0xe0000030000312f0, 0xffffffffffffffff, 0xffffffff00000000);
convert(0xe000003000031300, 0x000000000000000f, 0x0000000000000000);
convert(0xe000003000031310, 0x0000000000038160, 0x0000000000000000);
convert(0xe000003000031330, 0x00000000ff310122, 0x0000000000000000);
convert(0xe000003000031340, 0xffffffffffffffff, 0xffffffff00000005);
convert(0xe000003000031350, 0x000000000000000f, 0x0000000000000000);
convert(0xe000003000031360, 0x0000000000038190, 0x0000000000000000);
convert(0xe000003000031400, 0x0000000000310121, 0x0000000000000000);
convert(0xe000003000031400, 0x0000000000310121, 0x0000000000000000);
convert(0xe000003000031410, 0xffffffffffffffff, 0xffffffff00000006);
convert(0xe000003000031420, 0x000000000000000f, 0x0000000000000000);
convert(0xe000003000031430, 0x00000000000381c0, 0x0000000000000000);
convert(0xe0000030000314d0, 0x00000000ff010201, 0x0000000000000000);
convert(0xe0000030000314e0, 0xffffffffffffffff, 0xffffffff00000000);
convert(0xe000003000031500, 0x00000000000381f0, 0x000030430000ffff);
convert(0xe000003000031510, 0x000000000000ffff, 0x0000000000000000);
convert(0xe0000030000315a0, 0x00000020ff000201, 0x0000000000000000);
convert(0xe0000030000315b0, 0xffffffffffffffff, 0xffffffff00000001);
convert(0xe0000030000315d0, 0x0000000000038240, 0x00003f3f0000ffff);
convert(0xe0000030000315e0, 0x000000000000ffff, 0x0000000000000000);
convert(0xe000003000031670, 0x00000000ff010201, 0x0000000000000000);
convert(0xe000003000031680, 0xffffffffffffffff, 0x0000000100000002);
convert(0xe0000030000316a0, 0x0000000000038290, 0x000030430000ffff);
convert(0xe0000030000316b0, 0x000000000000ffff, 0x0000000000000000);
convert(0xe000003000031740, 0x00000020ff000201, 0x0000000000000000);
convert(0xe000003000031750, 0xffffffffffffffff, 0x0000000500000003);
convert(0xe000003000031770, 0x00000000000382e0, 0x00003f3f0000ffff);
convert(0xe000003000031780, 0x000000000000ffff, 0x0000000000000000);
}
/*
*
* 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.
*
* Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/config.h>
#include <linux/types.h>
#include <asm/bitops.h>
extern void klgraph_init(void);
void bedrock_init(int);
void synergy_init(int, int);
void sys_fw_init (const char *args, int arglen, int bsp);
volatile int bootmaster=0; /* Used to pick bootmaster */
volatile int nasidmaster[128]={0}; /* Used to pick node/synergy masters */
int init_done=0;
extern int bsp_lid;
#define get_bit(b,p) (((*p)>>(b))&1)
int
fmain(int lid, int bsp) {
int syn, nasid, cpu;
/*
* First lets figure out who we are. This is done from the
* LID passed to us.
*/
nasid = (lid>>16)&0xfff;
cpu = (lid>>28)&3;
syn = 0;
/*
* Now pick a nasid master to initialize Bedrock registers.
*/
if (test_and_set_bit(8, &nasidmaster[nasid]) == 0) {
bedrock_init(nasid);
test_and_set_bit(9, &nasidmaster[nasid]);
} else
while (get_bit(9, &nasidmaster[nasid]) == 0);
/*
* Now pick a BSP & finish init.
*/
if (test_and_set_bit(0, &bootmaster) == 0) {
sys_fw_init(0, 0, bsp);
test_and_set_bit(1, &bootmaster);
} else
while (get_bit(1, &bootmaster) == 0);
return (lid == bsp_lid);
}
void
bedrock_init(int nasid)
{
nasid = nasid; /* to quiet gcc */
#if 0
/*
* Undef if you need fprom to generate a 1 node klgraph
* information .. only works for 1 node for nasid 0.
*/
klgraph_init();
#endif
}
void
synergy_init(int nasid, int syn)
{
long *base;
long off;
/*
* Enable all FSB flashed interrupts.
* I'd really like defines for this......
*/
base = (long*)0x80000e0000000000LL; /* base of synergy regs */
for (off = 0x2a0; off < 0x2e0; off+=8) /* offset for VEC_MASK_{0-3}_A/B */
*(base+off/8) = -1LL;
/*
* Set the NASID in the FSB_CONFIG register.
*/
base = (long*)0x80000e0000000450LL;
*base = (long)((nasid<<16)|(syn<<9));
}
/* Why isnt there a bcopy/memcpy in lib64.a */
void*
memcpy(void * dest, const void *src, size_t count)
{
char *s, *se, *d;
for(d=dest, s=(char*)src, se=s+count; s<se; s++, d++)
*d = *s;
return dest;
}
#!/bin/sh
#
# Build a textsym file for use in the Arium ITP probe.
#
#
# 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.
#
# Copyright (c) 2001-2003 Silicon Graphics, Inc. All rights reserved.
#
help() {
cat <<END
Build a WinDD "symtxt" file for use with the Arium ECM-30 probe.
Usage: $0 [<vmlinux file> [<output file>]]
If no input file is specified, it defaults to vmlinux.
If no output file name is specified, it defaults to "textsym".
END
exit 1
}
err () {
echo "ERROR - $*" >&2
exit 1
}
OPTS="H"
while getopts "$OPTS" c ; do
case $c in
H) help;;
\?) help;;
esac
done
shift `expr $OPTIND - 1`
#OBJDUMP=/usr/bin/ia64-linux-objdump
LINUX=${1:-vmlinux}
TEXTSYM=${2:-${LINUX}.sym}
TMPSYM=${2:-${LINUX}.sym.tmp}
trap "/bin/rm -f $TMPSYM" 0
[ -f $VMLINUX ] || help
$OBJDUMP -t $LINUX | egrep -v '__ks' | sort > $TMPSYM
SN1=`egrep "dig_setup|Synergy_da_indr" $TMPSYM|wc -l`
# Dataprefix and textprefix correspond to the VGLOBAL_BASE and VPERNODE_BASE.
# Eventually, these values should be:
# dataprefix ffffffff
# textprefix fffffffe
# but right now they're still changing, so make them dynamic.
dataprefix=`awk ' / \.data / { print substr($1, 0, 8) ; exit ; }' $TMPSYM`
textprefix=`awk ' / \.text / { print substr($1, 0, 8) ; exit ; }' $TMPSYM`
# pipe everything thru sort
echo "TEXTSYM V1.0"
(cat <<END
GLOBAL | ${textprefix}00000000 | CODE | VEC_VHPT_Translation_0000
GLOBAL | ${textprefix}00000400 | CODE | VEC_ITLB_0400
GLOBAL | ${textprefix}00000800 | CODE | VEC_DTLB_0800
GLOBAL | ${textprefix}00000c00 | CODE | VEC_Alt_ITLB_0c00
GLOBAL | ${textprefix}00001000 | CODE | VEC_Alt_DTLB_1000
GLOBAL | ${textprefix}00001400 | CODE | VEC_Data_nested_TLB_1400
GLOBAL | ${textprefix}00001800 | CODE | VEC_Instruction_Key_Miss_1800
GLOBAL | ${textprefix}00001c00 | CODE | VEC_Data_Key_Miss_1c00
GLOBAL | ${textprefix}00002000 | CODE | VEC_Dirty-bit_2000
GLOBAL | ${textprefix}00002400 | CODE | VEC_Instruction_Access-bit_2400
GLOBAL | ${textprefix}00002800 | CODE | VEC_Data_Access-bit_2800
GLOBAL | ${textprefix}00002c00 | CODE | VEC_Break_instruction_2c00
GLOBAL | ${textprefix}00003000 | CODE | VEC_External_Interrupt_3000
GLOBAL | ${textprefix}00003400 | CODE | VEC_Reserved_3400
GLOBAL | ${textprefix}00003800 | CODE | VEC_Reserved_3800
GLOBAL | ${textprefix}00003c00 | CODE | VEC_Reserved_3c00
GLOBAL | ${textprefix}00004000 | CODE | VEC_Reserved_4000
GLOBAL | ${textprefix}00004400 | CODE | VEC_Reserved_4400
GLOBAL | ${textprefix}00004800 | CODE | VEC_Reserved_4800
GLOBAL | ${textprefix}00004c00 | CODE | VEC_Reserved_4c00
GLOBAL | ${textprefix}00005000 | CODE | VEC_Page_Not_Present_5000
GLOBAL | ${textprefix}00005100 | CODE | VEC_Key_Permission_5100
GLOBAL | ${textprefix}00005200 | CODE | VEC_Instruction_Access_Rights_5200
GLOBAL | ${textprefix}00005300 | CODE | VEC_Data_Access_Rights_5300
GLOBAL | ${textprefix}00005400 | CODE | VEC_General_Exception_5400
GLOBAL | ${textprefix}00005500 | CODE | VEC_Disabled_FP-Register_5500
GLOBAL | ${textprefix}00005600 | CODE | VEC_Nat_Consumption_5600
GLOBAL | ${textprefix}00005700 | CODE | VEC_Speculation_5700
GLOBAL | ${textprefix}00005800 | CODE | VEC_Reserved_5800
GLOBAL | ${textprefix}00005900 | CODE | VEC_Debug_5900
GLOBAL | ${textprefix}00005a00 | CODE | VEC_Unaligned_Reference_5a00
GLOBAL | ${textprefix}00005b00 | CODE | VEC_Unsupported_Data_Reference_5b00
GLOBAL | ${textprefix}00005c00 | CODE | VEC_Floating-Point_Fault_5c00
GLOBAL | ${textprefix}00005d00 | CODE | VEC_Floating_Point_Trap_5d00
GLOBAL | ${textprefix}00005e00 | CODE | VEC_Lower_Privilege_Tranfer_Trap_5e00
GLOBAL | ${textprefix}00005f00 | CODE | VEC_Taken_Branch_Trap_5f00
GLOBAL | ${textprefix}00006000 | CODE | VEC_Single_Step_Trap_6000
GLOBAL | ${textprefix}00006100 | CODE | VEC_Reserved_6100
GLOBAL | ${textprefix}00006200 | CODE | VEC_Reserved_6200
GLOBAL | ${textprefix}00006300 | CODE | VEC_Reserved_6300
GLOBAL | ${textprefix}00006400 | CODE | VEC_Reserved_6400
GLOBAL | ${textprefix}00006500 | CODE | VEC_Reserved_6500
GLOBAL | ${textprefix}00006600 | CODE | VEC_Reserved_6600
GLOBAL | ${textprefix}00006700 | CODE | VEC_Reserved_6700
GLOBAL | ${textprefix}00006800 | CODE | VEC_Reserved_6800
GLOBAL | ${textprefix}00006900 | CODE | VEC_IA-32_Exeception_6900
GLOBAL | ${textprefix}00006a00 | CODE | VEC_IA-32_Intercept_6a00
GLOBAL | ${textprefix}00006b00 | CODE | VEC_IA-32_Interrupt_6b00
GLOBAL | ${textprefix}00006c00 | CODE | VEC_Reserved_6c00
GLOBAL | ${textprefix}00006d00 | CODE | VEC_Reserved_6d00
GLOBAL | ${textprefix}00006e00 | CODE | VEC_Reserved_6e00
GLOBAL | ${textprefix}00006f00 | CODE | VEC_Reserved_6f00
GLOBAL | ${textprefix}00007000 | CODE | VEC_Reserved_7000
GLOBAL | ${textprefix}00007100 | CODE | VEC_Reserved_7100
GLOBAL | ${textprefix}00007200 | CODE | VEC_Reserved_7200
GLOBAL | ${textprefix}00007300 | CODE | VEC_Reserved_7300
GLOBAL | ${textprefix}00007400 | CODE | VEC_Reserved_7400
GLOBAL | ${textprefix}00007500 | CODE | VEC_Reserved_7500
GLOBAL | ${textprefix}00007600 | CODE | VEC_Reserved_7600
GLOBAL | ${textprefix}00007700 | CODE | VEC_Reserved_7700
GLOBAL | ${textprefix}00007800 | CODE | VEC_Reserved_7800
GLOBAL | ${textprefix}00007900 | CODE | VEC_Reserved_7900
GLOBAL | ${textprefix}00007a00 | CODE | VEC_Reserved_7a00
GLOBAL | ${textprefix}00007b00 | CODE | VEC_Reserved_7b00
GLOBAL | ${textprefix}00007c00 | CODE | VEC_Reserved_7c00
GLOBAL | ${textprefix}00007d00 | CODE | VEC_Reserved_7d00
GLOBAL | ${textprefix}00007e00 | CODE | VEC_Reserved_7e00
GLOBAL | ${textprefix}00007f00 | CODE | VEC_Reserved_7f00
END
awk '
/ _start$/ {start=1}
/ start_ap$/ {start=1}
/__start_gate_section/ {start=1}
/^'${dataprefix}\|${textprefix}'/ {
if ($4 == ".kdb")
next
if (start && substr($NF,1,1) != "0") {
type = substr($0,26,5)
if (type == ".text")
printf "GLOBAL | %s | CODE | %s\n", $1, $NF
else {
n = 0
s = $(NF-1)
while (length(s) > 0) {
n = n*16 + (index("0123456789abcdef", substr(s,1,1)) - 1)
s = substr(s,2)
}
printf "GLOBAL | %s | DATA | %s | %d\n", $1, $NF, n
}
}
if($NF == "_end")
exit
}
' $TMPSYM ) | egrep -v " __device| __vendor" | awk -v sn1="$SN1" '
/GLOBAL/ {
print $0
if (sn1 != 0) {
/* 32 bits of sn1 physical addrs, */
print substr($0,1,9) "04" substr($0,20,16) "Phy_" substr($0,36)
} else {
/* 38 bits of sn2 physical addrs, need addr space bits */
print substr($0,1,9) "3004" substr($0,20,16) "Phy_" substr($0,36)
}
} ' | sort -k3
N=`wc -l $TEXTSYM|awk '{print $1}'`
echo "Generated TEXTSYM file" >&2
echo " $LINUX --> $TEXTSYM" >&2
echo " Found $N symbols" >&2
#!/bin/sh
# Script for running PROMs and LINUX kernwls on medusa.
# Type "sim -H" for instructions.
MEDUSA=${MEDUSA:-/home/rickc/official_medusa/medusa}
# ------------------ err -----------------------
err() {
echo "ERROR - $1"
exit 1
}
# ---------------- help ----------------------
help() {
cat <<END
Script for running a PROM or LINUX kernel under medusa.
This script creates a control file, creates links to the appropriate
linux/prom files, and/or calls medusa to make simulation runs.
Usage:
Initial setup:
sim [-c <config_file>] <-p> | <-k> [<work_dir>]
-p Create PROM control file & links
-k Create LINUX control file & links
-c<cf> Control file name [Default: cf]
<work_dir> Path to directory that contains the linux or PROM files.
The directory can be any of the following:
(linux simulations)
worktree
worktree/linux
any directory with vmlinux, vmlinux.sym & fprom files
(prom simulations)
worktree
worktree/stand/arcs/IP37prom/dev
any directory with fw.bin & fw.sim files
Simulations:
sim [-X <n>] [-o <output>] [-M] [<config_file>]
-c<cf> Control file name [Default: cf]
-M Pipe output thru fmtmedusa
-o Output filename (copy of all commands/output) [Default: simout]
-X Specifies number of instructions to execute [Default: 0]
(Used only in auto test mode - not described here)
Examples:
sim -p <promtree> # create control file (cf) & links for prom simulations
sim -k <linuxtree> # create control file (cf) & links for linux simulations
sim -p -c cfprom # create a prom control file (cfprom) only. No links are made.
sim # run medusa using previously created links &
# control file (cf).
END
exit 1
}
# ----------------------- create control file header --------------------
create_cf_header() {
cat <<END >>$CF
#
# Template for a control file for running linux kernels under medusa.
# You probably want to make mods here but this is a good starting point.
#
# Preferences
setenv cpu_stepping A
setenv exceptionPrint off
setenv interrupt_messages off
setenv lastPCsize 100000
setenv low_power_mode on
setenv partialIntelChipSet on
setenv printIntelMessages off
setenv prom_write_action halt
setenv prom_write_messages on
setenv step_quantum 100
setenv swizzling on
setenv tsconsole on
setenv uart_echo on
symbols on
# IDE disk params
setenv diskCylinders 611
setenv bootDrive C
setenv diskHeads 16
setenv diskPath idedisk
setenv diskPresent 1
setenv diskSpt 63
# Hardware config
setenv coherency_type nasid
setenv cpu_cache_type default
setenv synergy_cache_type syn_cac_64m_8w
setenv l4_uc_snoop off
# Numalink config
setenv route_enable on
setenv network_type router # Select [xbar|router]
setenv network_warning 0xff
END
}
# ------------------ create control file entries for linux simulations -------------
create_cf_linux() {
cat <<END >>$CF
# Kernel specific options
setenv calias_size 0
setenv mca_on_memory_failure off
setenv LOADPC 0x00100000 # FPROM load address/entry point (8 digits!)
setenv symbol_table vmlinux.sym
load fprom
load vmlinux
# Useful breakpoints to always have set. Add more if desired.
break 0xe000000000505e00 all # dispatch_to_fault_handler
break panic all # stop on panic
break die_if_kernel all # may as well stop
END
}
# ------------------ create control file entries for prom simulations ---------------
create_cf_prom() {
SYM2=""
ADDR="0x80000000ff800000"
[ "$EMBEDDED_LINUX" != "0" ] || SYM2="setenv symbol_table2 vmlinux.sym"
[ "$SIZE" = "8MB" ] || ADDR="0x80000000ffc00000"
cat <<END >>$CF
# PROM specific options
setenv mca_on_memory_failure on
setenv LOADPC 0x80000000ffffffb0
setenv promFile fw.bin
setenv promAddr $ADDR
setenv symbol_table fw.sym
$SYM2
# Useful breakpoints to always have set. Add more if desired.
break ivt_gexx all
break ivt_brk all
break PROM_Panic_Spin all
break PROM_Panic all
break PROM_C_Panic all
break fled_die all
break ResetNow all
break zzzbkpt all
END
}
# ------------------ create control file entries for memory configuration -------------
create_cf_memory() {
cat <<END >>$CF
# CPU/Memory map format:
# setenv nodeN_memory_config 0xBSBSBSBS
# B=banksize (0=unused, 1=64M, 2=128M, .., 5-1G, c=8M, d=16M, e=32M)
# S=bank enable (0=both disable, 3=both enable, 2=bank1 enable, 1=bank0 enable)
# rightmost digits are for bank 0, the lowest address.
# setenv nodeN_nasid <nasid>
# specifies the NASID for the node. This is used ONLY if booting the kernel.
# On PROM configurations, set to 0 - PROM will change it later.
# setenv nodeN_cpu_config <cpu_mask>
# Set bit number N to 1 to enable cpu N. Ex., a value of 5 enables cpu 0 & 2.
#
# Repeat the above 3 commands for each node.
#
# For kernel, default to 32MB. Although this is not a valid hardware configuration,
# it runs faster on medusa. For PROM, 64MB is smallest allowed value.
setenv node0_cpu_config 0x1 # Enable only cpu 0 on the node
END
if [ $LINUX -eq 1 ] ; then
cat <<END >>$CF
setenv node0_nasid 0 # cnode 0 has NASID 0
setenv node0_memory_config 0xe1 # 32MB
END
else
cat <<END >>$CF
setenv node0_memory_config 0x31 # 256MB
END
fi
}
# -------------------- set links to linux files -------------------------
set_linux_links() {
if [ -d $D/linux/arch ] ; then
D=$D/linux
elif [ -d $D/arch -o -e vmlinux.sym -o -e $D/vmlinux ] ; then
D=$D
else
err "cant determine directory for linux binaries"
fi
rm -rf vmlinux vmlinux.sym fprom
ln -s $D/vmlinux vmlinux
if [ -f $D/vmlinux.sym ] ; then
ln -s $D/vmlinux.sym vmlinux.sym
elif [ -f $D/System.map ] ; then
ln -s $D/System.map vmlinux.sym
fi
if [ -d $D/arch ] ; then
ln -s $D/arch/ia64/sn/fprom/fprom fprom
else
ln -s $D/fprom fprom
fi
echo " .. Created links to linux files"
}
# -------------------- set links to prom files -------------------------
set_prom_links() {
if [ -d $D/stand ] ; then
D=$D/stand/arcs/IP37prom/dev
elif [ -d $D/sal ] ; then
D=$D
else
err "cant determine directory for PROM binaries"
fi
SETUP="/tmp/tmp.$$"
rm -r -f $SETUP
sed 's/export/setenv/' < $D/../../../../.setup | sed 's/=/ /' >$SETUP
egrep -q '^ *setenv *PROMSIZE *8MB|^ *export' $SETUP
if [ $? -eq 0 ] ; then
SIZE="8MB"
else
SIZE="4MB"
fi
grep -q '^ *setenv *LAUNCH_VMLINUX' $SETUP
EMBEDDED_LINUX=$?
PRODUCT=`grep '^ *setenv *PRODUCT' $SETUP | cut -d" " -f3`
rm -f fw.bin fw.map fw.sym vmlinux vmlinux.sym fprom $SETUP
SDIR="${PRODUCT}${SIZE}.O"
BIN="${PRODUCT}ip37prom${SIZE}"
ln -s $D/$SDIR/$BIN.bin fw.bin
ln -s $D/$SDIR/$BIN.map fw.map
ln -s $D/$SDIR/$BIN.sym fw.sym
echo " .. Created links to $SIZE prom files"
if [ $EMBEDDED_LINUX -eq 0 ] ; then
ln -s $D/linux/vmlinux vmlinux
ln -s $D/linux/vmlinux.sym vmlinux.sym
if [ -d linux/arch ] ; then
ln -s $D/linux/arch/ia64/sn/fprom/fprom fprom
else
ln -s $D/linux/fprom fprom
fi
echo " .. Created links to embedded linux files in prom tree"
fi
}
# --------------- start of shell script --------------------------------
OUT="simout"
FMTMED=0
STEPCNT=0
PROM=0
LINUX=0
NCF="cf"
while getopts "HMX:c:o:pk" c ; do
case ${c} in
H) help;;
M) FMTMED=1;;
X) STEPCNT=${OPTARG};;
c) NCF=${OPTARG};;
k) PROM=0;LINUX=1;;
p) PROM=1;LINUX=0;;
o) OUT=${OPTARG};;
\?) exit 1;;
esac
done
shift `expr ${OPTIND} - 1`
# Check if command is for creating control file and/or links to images.
if [ $PROM -eq 1 -o $LINUX -eq 1 ] ; then
CF=$NCF
[ ! -f $CF ] || err "wont overwrite an existing control file ($CF)"
if [ $# -gt 0 ] ; then
D=$1
[ -d $D ] || err "cannot find directory $D"
[ $PROM -eq 0 ] || set_prom_links
[ $LINUX -eq 0 ] || set_linux_links
fi
create_cf_header
[ $PROM -eq 0 ] || create_cf_prom
[ $LINUX -eq 0 ] || create_cf_linux
[ ! -f ../idedisk ] || ln -s ../idedisk .
create_cf_memory
echo " .. Basic control file created (in $CF). You might want to edit"
echo " this file (at least, look at it)."
exit 0
fi
# Verify that the control file exists
CF=${1:-$NCF}
[ -f $CF ] || err "No control file exists. For help, type: $0 -H"
# Build the .cf files from the user control file. The .cf file is
# identical except that the actual start & load addresses are inserted
# into the file. In addition, the FPROM commands for configuring memory
# and LIDs are generated.
rm -f .cf .cf1 .cf2
awk '
function strtonum(n) {
if (substr(n,1,2) != "0x")
return int(n)
n = substr(n,3)
r=0
while (length(n) > 0) {
r = r*16+(index("0123456789abcdef", substr(n,1,1))-1)
n = substr(n,2)
}
return r
}
/^#/ {next}
/^$/ {next}
/^setenv *LOADPC/ {loadpc = $3; next}
/^setenv *node.._cpu_config/ {n=int(substr($2,5,2)); cpuconf[n] = strtonum($3); print; next}
/^setenv *node.._memory_config/ {n=int(substr($2,5,2)); memconf[n] = strtonum($3); print; next}
/^setenv *node.._nasid/ {n=int(substr($2,5,2)); nasid[n] = strtonum($3); print; next}
/^setenv *node._cpu_config/ {n=int(substr($2,5,1)); cpuconf[n] = strtonum($3); print; next}
/^setenv *node._memory_config/ {n=int(substr($2,5,1)); memconf[n] = strtonum($3); print; next}
/^setenv *node._nasid/ {n=int(substr($2,5,1)); nasid[n] = strtonum($3); print; next}
{print}
END {
# Generate the memmap info that starts at the beginning of
# the node the kernel was loaded on.
loadnasid = nasid[0]
cnode = 0
for (i=0; i<128; i++) {
if (memconf[i] != "") {
printf "sm 0x%x%08x 0x%x%04x%04x\n",
2*loadnasid, 8*cnodes+8, memconf[i], cpuconf[i], nasid[i]
cnodes++
cpus += substr("0112122312232334", cpuconf[i]+1,1)
}
}
printf "sm 0x%x00000000 0x%x%08x\n", 2*loadnasid, cnodes, cpus
printf "setenv number_of_nodes %d\n", cnodes
# Now set the starting PC for each cpu.
cnode = 0
lowcpu=-1
for (i=0; i<128; i++) {
if (memconf[i] != "") {
printf "setnode %d\n", cnode
conf = cpuconf[i]
for (j=0; j<4; j++) {
if (conf != int(conf/2)*2) {
printf "setcpu %d\n", j
if (length(loadpc) == 18)
printf "sr pc %s\n", loadpc
else
printf "sr pc 0x%x%s\n", 2*loadnasid, substr(loadpc,3)
if (lowcpu == -1)
lowcpu = j
}
conf = int(conf/2)
}
cnode++
}
}
printf "setnode 0\n"
printf "setcpu %d\n", lowcpu
}
' <$CF >.cf
# Now build the .cf1 & .cf2 control files.
CF2_LINES="^sm |^break |^run |^si |^quit |^symbols "
egrep "$CF2_LINES" .cf >.cf2
egrep -v "$CF2_LINES" .cf >.cf1
if [ $STEPCNT -ne 0 ] ; then
echo "s $STEPCNT" >>.cf2
echo "lastpc 1000" >>.cf2
echo "q" >>.cf2
fi
if [ -f vmlinux.sym ] ; then
awk '/ _start$/ {print "sr g 9 0x" $3}' < vmlinux.sym >> .cf2
fi
echo "script-on $OUT" >>.cf2
# Now start medusa....
if [ $FMTMED -ne 0 ] ; then
$MEDUSA -system mpsn1 -c .cf1 -i .cf2 | fmtmedusa
elif [ $STEPCNT -eq 0 ] ; then
$MEDUSA -system mpsn1 -c .cf1 -i .cf2
else
$MEDUSA -system mpsn1 -c .cf1 -i .cf2 2>&1
fi
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment