summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/build/simics/hb-simdebug.py81
-rwxr-xr-xsrc/build/tools/cpfiles.pl27
-rwxr-xr-xsrc/build/vpo/VBU_Cacheline.pm474
-rwxr-xr-xsrc/build/vpo/hb-istep565
-rwxr-xr-xsrc/build/vpo/hb-virtdebug.pl2
-rw-r--r--src/usr/initservice/baseinitsvc/initservice.C11
-rw-r--r--src/usr/initservice/baseinitsvc/initservicetaskentry.C2
-rw-r--r--src/usr/initservice/istepdispatcher/istepdispatcher.C111
-rw-r--r--src/usr/initservice/istepdispatcher/istepdispatcher.H14
-rw-r--r--src/usr/initservice/istepdispatcher/splesscommon.H168
10 files changed, 1330 insertions, 125 deletions
diff --git a/src/build/simics/hb-simdebug.py b/src/build/simics/hb-simdebug.py
index 0f5774a2e..4e5dbb2ee 100755
--- a/src/build/simics/hb-simdebug.py
+++ b/src/build/simics/hb-simdebug.py
@@ -59,6 +59,30 @@ def dumpL3():
# Functions to run isteps
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
+
+def findAddr( symsFile, symName ):
+
+
+ #Find location of the variable from the image's .syms file
+ for line in open(symsFile):
+ if symName in line : #if found
+ #print line
+ x = line.split(",")
+ addr = int(x[1],16)
+ #print "addr = 0x%x"%(addr)
+ size = int(x[3],16)
+ #print "size = 0x%x"%(size)
+ break
+
+ #print line
+ if symName not in line: #if not found
+ print "\nCannot find %s in %s"%( symName,symsFile)
+ return "0"
+
+ ## returns an int
+ return addr
+
+
def hb_istep_usage():
print "hb-istep usage:"
print " istepmode - enable IStep Mode. Must be executed before simics run command"
@@ -89,7 +113,7 @@ def bump_g_SeqNum() :
##
def runClocks() :
- SIM_continue( 100000 )
+ SIM_continue( 250000 )
return None
##
@@ -103,14 +127,16 @@ def runClocks() :
## 3. hardware
def sendCommand( cmd ):
global g_IStep_DEBUG
- CommandStr = "cpu0_0_0_1->scratch=%s"%(cmd)
+ ## CommandStr = "cpu0_0_0_1->scratch=%s"%(cmd)
+ CommandStr = "phys_mem.write 0x%8.8x %s 8"%(g_SPLess_Command_Reg, cmd )
## send command to Hostboot
- ## print CommandStr
+ if ( g_IStep_DEBUG ) :
+ print CommandStr
(result, out) = quiet_run_command(CommandStr, output_modes.regular )
if ( g_IStep_DEBUG ) :
- print "sendCommand( 0x%x ) returns : " + "0x%x"%(cmd, result) + " : " + out
+ print "sendCommand( \"%s\" ) returns : "%(cmd) + "0x%x"%(result) + " : " + out
return result
@@ -134,7 +160,9 @@ def printStsHdr( status ):
##
def getStatus():
global g_IStep_DEBUG
- StatusStr = "cpu0_0_0_2->scratch"
+
+ ## StatusStr = "cpu0_0_0_2->scratch"
+ StatusStr = "phys_mem.read 0x%8.8x 8"%(g_SPLess_Status_Reg )
( result, out ) = quiet_run_command( StatusStr, output_modes.regular )
if ( g_IStep_DEBUG ) :
@@ -177,14 +205,20 @@ def getSyncStatus( ) :
## write to scratch reg 3 to set istep or normal mode, check return status
def setMode( cmd ) :
- IStepModeStr = "cpu0_0_0_3->scratch=0x4057b007_4057b007"
- NormalModeStr = "cpu0_0_0_3->scratch=0x700b7504_700b7504"
+ global g_IStep_DEBUG
+ global g_SPLess_IStepMode_Reg
+
+ ##IStepModeStr = "cpu0_0_0_3->scratch=0x4057b007_4057b007"
+ ##NormalModeStr = "cpu0_0_0_3->scratch=0x700b7504_700b7504"
+ IStepModeStr = "phys_mem.write 0x%8.8x 0x4057b007_4057b007 8"%(g_SPLess_IStepMode_Reg)
+ NormalModeStr = "phys_mem.write 0x%8.8x 0x700b7504_700b7504 8"%(g_SPLess_IStepMode_Reg)
- count = 10
+ count = 50
if ( cmd == "istep" ) :
(result, out) = quiet_run_command( IStepModeStr )
+ # print IStepModeStr
# print "set istepmode returned 0x%x"%(result) + " : " + out
expected = 1
elif ( cmd == "normal" ) :
@@ -201,7 +235,8 @@ def setMode( cmd ) :
result = getStatus()
readybit = ( ( result & 0x4000000000000000 ) >> 62 )
- print "Setting %s mode, readybit=%d..."%( cmd, readybit )
+ if ( g_IStep_DEBUG ) :
+ print "Setting %s mode, readybit=%d..."%( cmd, readybit )
if ( readybit == expected ) :
print "Set %s Mode success."%(cmd)
return 0
@@ -229,7 +264,6 @@ def get_istep_list( inList ):
return None
-
def print_istep_list( inList ):
print "IStep\tSubStep\tName"
print "---------------------------------------------------"
@@ -322,17 +356,28 @@ def find_in_inList( inList, substepname) :
## sN..M
## <substepname1>..<substepname2>
-## declare GLOBAL g_IStep_DEBUG
+## declare GLOBAL g_IStep_DEBUG & SPLess memory mapped regs
g_IStep_DEBUG = 0
-def istepHB( str_arg1 ):
-
+g_SPLess_IStepMode_Reg = ""
+g_SPLess_Command_Reg = ""
+g_SPLess_Status_Reg = ""
+def istepHB( symsFile, str_arg1 ):
+ global g_IStep_DEBUG
+ global g_SPLess_IStepMode_Reg
+ global g_SPLess_Command_Reg
+ global g_SPLess_Status_Reg
+
+ ## find addresses of the memory-mapped SPLess regs in the image
+ g_SPLess_IStepMode_Reg = findAddr( symsFile, "SPLESS::g_SPLess_IStepMode_Reg" )
+ g_SPLess_Command_Reg = findAddr( symsFile, "SPLESS::g_SPLess_Command_Reg" )
+ g_SPLess_Status_Reg = findAddr( symsFile, "SPLESS::g_SPLess_Status_Reg" )
+
## simics cannot be running when we start, or SIM_continue() will not work
## and the Status reg will not be updated.
if ( SIM_simics_is_running() ) :
print "simics must be halted before issuing an istep command."
- return;
-
-
+ return;
+
## start with empty inList. Put some dummy isteps in istep4 for debug.
n = 10 ## size of inlist array
inList = [[None]*n for x in xrange(n)] ## init to nothing
@@ -503,12 +548,14 @@ Examples: \n
# implement isteps
#------------------------------------------------
def hb_istep(str_arg1):
+
+ syms = default_syms
if ( str_arg1 == None):
hb_istep_usage()
else:
## print "args=%s" % str(str_arg1)
- istepHB( str_arg1 )
+ istepHB( syms, str_arg1 )
return None
diff --git a/src/build/tools/cpfiles.pl b/src/build/tools/cpfiles.pl
index 3c71b55fa..520c6a1c1 100755
--- a/src/build/tools/cpfiles.pl
+++ b/src/build/tools/cpfiles.pl
@@ -79,6 +79,16 @@ my @files = ("src/build/tools/hb-parsedump.pl",
"img/vbu_targeting.bin",
"img/isteplist.csv",
);
+
+# copy vpo files into working dir for AWAN
+my @vpofiles = ("src/build/vpo/hb-dump",
+ "src/build/vpo/hb-errl",
+ "src/build/vpo/hb-istep",
+ "src/build/vpo/hb-printk",
+ "src/build/vpo/hb-trace",
+ "src/build/vpo/hb-virtdebug.pl",
+ "src/build/vpo/VBU_Cacheline.pm",
+ );
#Directories in base git repository
my @gitRepoDirs = ("img",
@@ -98,8 +108,9 @@ my $numArgs = $#ARGV + 1;
my $test = 0; #Flag to overwrite hbicore.<syms|bin|list> with the test versions
my $inDir = ""; #User specified directory to copy files to
+my $vpo = 0; # copy extra vpo files to inDir
-if ($numArgs > 2)
+if ($numArgs > 3)
{
#Print command line help
print ("ERROR: Too many arguments entered.\n");
@@ -121,6 +132,11 @@ else
#Set flag to copy hbicore_test.<syms|bin> to hbcore_test.<syms|bin>
$test = 1;
}
+ elsif ($_ eq "--vpo")
+ {
+ #Set flag to copy list of vpo files to $inDir
+ $vpo = 1;
+ }
else
{
#Save user specified directory
@@ -187,6 +203,14 @@ else
}
#------------------------------------------------------------------------------
+# If vpo flag is set, add the vpo files to the @files array
+#------------------------------------------------------------------------------
+if ( $vpo )
+{
+ push( @files, @vpofiles );
+}
+
+#------------------------------------------------------------------------------
# Get the base dir of the git repository
#------------------------------------------------------------------------------
my $cwd = getcwd();
@@ -322,5 +346,6 @@ sub printUsage()
print (" if it is defined.\n\n");
print (" --help: prints usage information\n");
print (" --test: Copy hbicore_test.<syms|bin|list> to hbicore.<syms|bin|list>\n");
+ print (" --vpo: Copy files in src/build/vpo to support vpo operation\n");
}
diff --git a/src/build/vpo/VBU_Cacheline.pm b/src/build/vpo/VBU_Cacheline.pm
new file mode 100755
index 000000000..23a1d30da
--- /dev/null
+++ b/src/build/vpo/VBU_Cacheline.pm
@@ -0,0 +1,474 @@
+#!/usr/bin/perl
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/build/vpo/VBU_Cacheline.pm $
+#
+# IBM CONFIDENTIAL
+#
+# COPYRIGHT International Business Machines Corp. 2011 - 2012
+#
+# p1
+#
+# Object Code Only (OCO) source materials
+# Licensed Internal Code Source Materials
+# IBM HostBoot Licensed Internal Code
+#
+# The source code for this program is not published or other-
+# wise divested of its trade secrets, irrespective of what has
+# been deposited with the U.S. Copyright Office.
+#
+# Origin: 30
+#
+# IBM_PROLOG_END
+#
+# Name: hb-modify-cacheline.pm
+#
+# Purpose: routines for reading and writing a 64-bit value into L3 in an
+# AWAN session. Accepts an address into L3, and 64-bit data hex word
+# (write).
+# VBU can only read/write to memory in 128-byte cachelines, so if
+# we want to write a memory location we must read in the entire
+# cacheline, modify the correct byte(s) and then write it back.
+# Called from shell script do_p8vbu_script_hbi*
+# Written in perl because that is what is being used for the debug
+# framework
+#
+# Author: Mark Wenning
+#
+
+package VBU_Cacheline;
+require Exporter;
+
+our @ISA = qw( Exporter );
+our @EXPORT = qw( CLread CLwrite RunClocks P8_Ins_Start P8_Ins_Stop P8_Ins_Query SetFlags);
+
+
+#------------------------------------------------------------------------------
+# Specify perl modules to use
+#------------------------------------------------------------------------------
+use strict;
+use warnings;
+use POSIX;
+use Fcntl;
+
+## 64-bit input
+use bigint;
+no warnings 'portable';
+
+#------------------------------------------------------------------------------
+# Forward declarations
+#------------------------------------------------------------------------------
+sub CLread;
+sub CLwrite;
+sub RunClocks;
+sub P8_Ins_Start;
+sub P8_Ins_Stop;
+sub P8_Ins_Query;
+sub P8_Flush_L2;
+sub SetFlags;
+
+
+############################################
+## constants
+## use constant MAX_NUM_TRACE_BUFFERS => 24;
+############################################
+my $CLfile = "./istepmodereg.dma";
+my $CORE = "-c3";
+my $SIM_CLOCKS = "4000000";
+
+## later...
+my $vbuToolsDir = "/gsa/ausgsa/projects/h/hostboot/vbutools";
+
+
+my $DUMPCMD = "/afs/awd/projects/eclipz/lab/p8/gsiexe/p8_dump_l3";
+my $LOADCMD = "/afs/awd/projects/eclipz/lab/p8/gsiexe/p8_load_l3";
+## my $FLUSHCMD = "/afs/awd/projects/eclipz/lab/p8/gsiexe/p8_l2_flush.x86 $CORE";
+my $FLUSHCMD = "/afs/awd/projects/eclipz/lab/p8/compiled_procs/procs/p8_l2_flush_wrap.x86 $CORE -quiet";
+my $FLUSHQUERY = "/afs/awd.austin.ibm.com/projects/eclipz/lab/p8/gsiexe/p8_check_l3";
+my $RUNCLKSCMD = "simclock";
+
+my $QUERYCMD = "/gsa/pokgsa/home/m/c/mcguirej/public/auto/rel/P8bin/p8_ins_query";
+my $STOPCMD = "/gsa/pokgsa/home/m/c/mcguirej/public/auto/rel/P8bin/p8_ins_stop";
+my $STARTCMD = "/gsa/pokgsa/home/m/c/mcguirej/public/auto/rel/P8bin/p8_ins_start";
+## ## later...
+## ## my $QUERYCMD = "/afs/awd/projects/eclipz/lab/p8/u/karm/ekb/eclipz/chips/p8/working/procedures/utils/p8_thread_control.x86 -query";
+## ## my $STOPCMD = "/afs/awd/projects/eclipz/lab/p8/u/karm/ekb/eclipz/chips/p8/working/procedures/utils/p8_thread_control.x86 -stop";
+## ## my $STARTCMD = "/afs/awd/projects/eclipz/lab/p8/u/karm/ekb/eclipz/chips/p8/working/procedures/utils/p8_thread_control.x86 -start";
+
+#############################################
+## Internal Globals
+#############################################
+my $CLdebug = 0;
+my $CLtest = 0;
+
+## flushed Flag, if 0, it means the L2 cache has not been flushed.
+## It must be flushed once before doing L3 reads
+my $L2_Flushed = 0;
+
+
+##
+#==============================================================================
+# SUBROUTINES
+#==============================================================================
+
+
+##
+## Read the cacheline at addr from L3 and dump it to a binary file.
+## Assumes that the input address is a binary addr on a 128 byte boundary
+##
+sub readcacheline( $ )
+{
+ my ( $addr ) = @_;
+ my $cmd;
+ ## my $hexaddr = sprintf( "0x%x", $addr );
+ my $hexaddr = sprintf( "%x", $addr );
+
+ if ( $CLdebug ) { print STDOUT "-- Read cacheline at $hexaddr...\n"; }
+
+ ## Stop simulation so we can read L3 properly
+ P8_Ins_Stop();
+
+ ## flush L2 if necessary
+ P8_Flush_L2();
+
+ $cmd = "$DUMPCMD $hexaddr 1 -f $CLfile -b $CORE";
+ if ( $CLdebug ) { print STDOUT "-- run $cmd ...\n"; }
+ ( system( $cmd ) == 0 )
+ or die "$cmd failed $? : $! \n";
+
+ ## Start simulation back up.
+ ## P8_Ins_Start();
+
+}
+
+
+##
+## derived from Perl Cookbook, 8.13
+## pack/unpack format is unsigned big endian 32-bit hi, lo
+## however, the input data from getopts still assumes that perl is compiled
+## for 64-bit #s
+##
+sub modifycacheline( $$ )
+{
+ my ( $offset, $data ) = @_;
+
+ my $typedef = 'N N'; # 2 32-bit network order
+ my $sizeof = length( pack($typedef,() ) );
+ my $filesize = -s $CLfile;
+ my $buffer;
+
+ open( FH, "+< $CLfile") or die "can't open $CLfile : $!";
+ binmode FH; ## not really necessary, but....
+ seek( FH, $offset, SEEK_SET) or die "seek $CLfile failed: $!";
+ read( FH, $buffer, $sizeof) == $sizeof or die "read failed: $!";
+
+ ( my $hi, my $lo ) = unpack($typedef, $buffer);
+
+ $hi = ($data >> 32) ;
+ $lo = ($data & 0x00000000ffffffff);
+
+ $buffer = pack($typedef, $hi, $lo );
+
+ # back up one record
+ seek( FH, -$sizeof, SEEK_CUR) or die "seek $CLfile failed: $!";
+
+ print FH $buffer;
+
+ close( FH ) or die "close $CLfile failed: $!";
+}
+
+##
+## Write modified file back to L3 cacheline.
+## This assumes that addr has already been converted to binary addr on a
+## 128 byte boundary
+##
+sub writecacheline( $ )
+{
+ my ( $addr ) = @_;
+ my $cmd;
+ ## my $hexaddr = sprintf( "0x%x", $addr );
+ my $hexaddr = sprintf( "%x", $addr );
+
+ ## Stop simulation so we can write L3
+ P8_Ins_Stop();
+
+ $cmd = "$LOADCMD -o $hexaddr -f $CLfile -b $CORE";
+ if ( $CLdebug ) { print STDOUT "-- run $cmd ...\n"; }
+ ( system( $cmd ) == 0 )
+ or die "$cmd failed, $? : $! \n";
+
+ ## Start sim back up
+ ## P8_Ins_Start();
+
+}
+
+
+##
+## Query the state of the simulator, "RUNNING" or "STOPPED".
+##
+sub P8_Ins_Query()
+{
+ my $cmd = "$QUERYCMD";
+ my $retstr = "";
+
+ if ( $CLdebug ) { print STDOUT "-- run $cmd ...\n"; }
+
+ ## execute it with backticks so we can get the output.
+ $retstr = `$cmd`;
+ if ( $? != 0 ) { die "$cmd failed $? : $! \n"; }
+
+ chomp( $retstr );
+
+ if ( $CLdebug ) { print STDOUT "-- P8_Ins_Query returned $retstr\n"; }
+
+ if ( ($retstr ne "STOPPED" )
+ && ($retstr ne "RUNNING" )
+ )
+ {
+ die "invalid string \"$retstr\" from P8_Ins_Query\n";
+ }
+
+ return $retstr;
+}
+
+
+##
+## Stop the simulation. Necessary to read and write L3 .
+##
+sub P8_Ins_Start()
+{
+ my $cmd = "$STARTCMD";
+
+ if ( P8_Ins_Query() eq "STOPPED" )
+ {
+ if ( $CLdebug ) { print STDOUT "-- run $cmd ...\n"; }
+
+ ( system( $cmd ) == 0 )
+ or die "$cmd failed $? : $! \n";
+
+
+ ## reset the flushFlag, need to flush again before a read.
+ $L2_Flushed = 0;
+ }
+ else
+ {
+ if ($CLdebug) { print STDOUT "-- P8_Ins_Start: already RUNNING\n"; }
+ }
+
+}
+
+
+##
+## Stop the simulation.
+##
+sub P8_Ins_Stop()
+{
+ my $cmd = "$STOPCMD";
+
+ if ( P8_Ins_Query() eq "RUNNING" )
+ {
+ if ( $CLdebug ) { print STDOUT "-- run $cmd ...\n"; }
+ ( system( $cmd ) == 0 )
+ or die "$cmd failed $? : $! \n";
+
+ }
+ else
+ {
+ if ($CLdebug) { print STDOUT "-- P8_Ins_Stop: already STOPPED\n"; }
+ }
+
+}
+
+##
+## Check if cache is flushed.
+## $TODO
+## p8_check_L3 will scan the L3 directory for unfilled cachelines and
+## return a string:
+## $ p8_check_l3 100 4 -c3 -f $labhome/foo -x -o
+## p8_check_l3 - address (0x100) not found in L3 directory.
+##
+## $ p8_check_l3 100 4 -c3 -f $labhome/foo -x -o
+## p8_check_l3 - all addresses found in L3 directory.
+##
+sub P8_Check_Flushed
+{
+ my ( $addr, $lines ) = @_;
+ my $tmpfile = "./tmpflush";
+ my $cmd = "$FLUSHQUERY";
+ my $rc = 0;
+
+ ## execute it with backticks so we can get the output.
+ my $retstr = `$cmd $CORE -f $tmpfile -x -o`;
+ if ( $? != 0 ) { die "$cmd failed $? : $! \n"; }
+
+ chomp( $retstr );
+
+ if ( $retstr =~ /^.*.all addresses.*/ )
+ {
+ $rc = 1;
+ }
+
+ return $rc;
+}
+
+##
+## Flush L2 Cache
+## This only needs to be done once after the clock is stopped,
+## thus the toggle flag
+##
+sub P8_Flush_L2()
+{
+ my $cmd = "$FLUSHCMD";
+
+ if ( !$L2_Flushed )
+ {
+ if ( $CLdebug ) { print STDOUT "-- run $cmd ...\n"; }
+ ( system( $cmd ) == 0 )
+ or die "$cmd failed $? : $! \n";
+
+ ## mark the CPU as flushed.
+ $L2_Flushed = 1;
+ }
+
+ if ($CLdebug) { print STDOUT "-- P8_FLush_L2 : $L2_Flushed\n"; }
+}
+
+
+##
+## tell the simulator to run for so many clock cycles.
+## If simulator is stopped, then start it up first.
+##
+sub RunClocks()
+{
+ my $cmd = 0;
+
+ if ( $CLdebug ) { printf STDOUT "-- RunClocks()\n"; }
+
+ ## Check, and start instructions if necessary
+ if ( P8_Ins_Query( ) ne "RUNNING" )
+ {
+
+ P8_Ins_Start();
+ }
+
+ $cmd = "$RUNCLKSCMD $SIM_CLOCKS -quiet";
+ if ( $CLdebug ) { print STDOUT "-- run $cmd ...\n"; }
+ ( system( $cmd ) == 0 )
+ or die "$cmd failed, $? : $! \n";
+
+}
+
+
+##
+## Read a 64-bit value from L3 at hex addr.
+## Input is expected to be a hex ascii string
+##
+sub CLread( $ )
+{
+ my ( $addr ) = @_;
+ my $cmd;
+ my $CLbase = ( hex($addr) & 0xffffff80);
+ my $CLoffset = ( hex($addr) & (~0xffffff80) );
+ my $result = 0; ## 64-bit hex
+
+ if ( $CLdebug ) { printf STDOUT "-- CLread( %s ) : CLbase=0x%x, CLoffset=0x%x\n", $addr, $CLbase, $CLoffset }
+
+ readcacheline( $CLbase );
+
+ ## extract quadword from cacheline file
+ my $typedef = 'N N'; # QuadWord
+ my $sizeof = length( pack($typedef,() ) );
+ my $filesize = -s $CLfile;
+ my $buffer;
+ open( FH, "+< $CLfile") or die "can't open $CLfile : $!";
+ binmode FH; ## not really necessary, but....
+ seek( FH, $CLoffset, SEEK_SET) or die "seek $CLfile failed: $!";
+ read( FH, $buffer, $sizeof) == $sizeof or die "read failed: $!";
+ close( FH ) or die "close $CLfile failed: $!";
+
+ ## unpack and reassemble as big-endian
+ ( my $hi, my $lo ) = unpack($typedef, $buffer);
+ $result = ( ( ( $hi << 32 ) & 0xffffffff00000000 ) | $lo );
+
+ if ( $CLdebug )
+ {
+ printf STDOUT "-- CLread( %s ) = 0x%lx ", $addr, $result;
+ dumpcacheline(" " );
+ }
+
+ return ( $result );
+}
+
+##
+## Write command byte to cacheline
+## Inputs are expected to be hex ascii strings
+##
+sub CLwrite( $$ )
+{
+ my ( $addr, $data ) = @_;
+ my $CLbase = ( hex($addr) & 0xffffff80 );
+ my $CLoffset = ( hex($addr) & (~0xffffff80) );
+ my $CLdata = hex($data);
+ my $result = 0;
+
+ if ( $CLdebug ) { printf STDOUT "-- CLwrite( %s, %s ) : CLbase=0x%x, CLoffset=0x%x, CLdata=0x%lx\n",
+ $addr, $data, $CLbase, $CLoffset, $CLdata; }
+
+ ## clear the cacheline file
+ system( "rm -f $CLfile" );
+
+ ## issue the command to dump the cacheline to a file
+ readcacheline( $CLbase );
+
+ ## dumpcacheline( "after read", $CLfile );
+
+ ## modify the cacheline file
+ modifycacheline( $CLoffset, $data );
+
+ ## dumpcacheline( "after modify", $CLfile );
+
+ ## write the cacheline back to L3
+ writecacheline( $CLbase );
+
+ if ( $CLdebug )
+ {
+ ## check, clear the cacheline file and read again
+ system( "rm -f $CLfile" );
+ readcacheline( $CLbase );
+ dumpcacheline( "Readback", $CLfile );
+ }
+
+}
+
+
+sub dumpcacheline()
+{
+ my ( $comment ) = @_;
+
+ if ( $CLdebug )
+ {
+ print STDOUT "-- $comment, dump cache file :\n";
+ system( "xxd $CLfile" );
+ }
+
+}
+
+sub SetFlags( $$ )
+{
+ my ( $debug, $test ) = @_;
+
+ $CLdebug = $debug;
+ $CLtest = $test;
+
+ if ( $CLdebug )
+ {
+ print STDOUT "-- CLdebug=$CLdebug, CLtest=$CLtest\n";
+ }
+}
+
+
+## required at the end of perl modules
+1;
+
+__END__
diff --git a/src/build/vpo/hb-istep b/src/build/vpo/hb-istep
new file mode 100755
index 000000000..2cae8e617
--- /dev/null
+++ b/src/build/vpo/hb-istep
@@ -0,0 +1,565 @@
+#!/usr/bin/perl
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/build/vpo/hb-istep $
+#
+# IBM CONFIDENTIAL
+#
+# COPYRIGHT International Business Machines Corp. 2011
+#
+# p1
+#
+# Object Code Only (OCO) source materials
+# Licensed Internal Code Source Materials
+# IBM HostBoot Licensed Internal Code
+#
+# The source code for this program is not published or other-
+# wise divested of its trade secrets, irrespective of what has
+# been deposited with the U.S. Copyright Office.
+#
+# Origin: 30
+#
+# IBM_PROLOG_END
+#
+# Purpose: This perl script works in concert with do_p8vbu_script_hbi_* to
+# implement isteps on AWAN.
+#
+# Description:
+# The do.. script will run first to set up the AWAN environment,
+# then call hb_istep twice:
+# 1) hb_istep --istepmode
+# called after loading but before starting HostBoot
+# this will check to see if the user has set istep mode, if so
+# it will write the Istep_mode signature to L3 memory to put
+# HostBoot mode into single-step mode.
+# 2) hb_istep --command
+# Periodically call RunClocks() to step through HostBoot.
+# Checks for status from previous Isteps, and reports status.
+#
+# Comments:
+#
+#
+# Author: Mark Wenning
+#
+
+#------------------------------------------------------------------------------
+# Specify perl modules to use
+#------------------------------------------------------------------------------
+use strict;
+use warnings;
+use POSIX;
+use Getopt::Long;
+
+## 64-bit input
+## argh, not compatable with GetOpt!! use bigint;
+no warnings 'portable';
+
+# read/write cachelines to L3
+use VBU_Cacheline;
+
+#------------------------------------------------------------------------------
+# Forward Declaration
+#------------------------------------------------------------------------------
+sub printUsage;
+sub get_istep_list;
+sub print_istep_list;
+sub find_in_inlist;
+sub parse_command;
+sub setMode;
+
+#------------------------------------------------------------------------------
+# Constants
+#------------------------------------------------------------------------------
+my $CSVfile = "isteplist.csv";
+my $hbSymsFile = "hbicore.syms"; #Use hbicore.syms
+my $CORE = "-c3";
+
+
+#------------------------------------------------------------------------------
+# Globals
+#------------------------------------------------------------------------------
+my $opt_debug = 0;
+my $opt_istepmode = 0;
+my $opt_normalmode = 0;
+my $opt_command = "";
+my $opt_list = 0;
+my $opt_help = 0;
+my $opt_cmdfile = 0; ## batchmode, later
+
+my @inList;
+$inList[10][10] = ();
+## initialize inList to "undefined"
+for( my $i = 0; $i <= $#inList; $i++)
+{
+ for(my $j = 0; $j <= $#inList; $j++)
+ {
+ undef( $inList[$i][$j] );
+ }
+}
+
+my $g_SeqNum = 0;
+
+
+#==============================================================================
+# MAIN
+#==============================================================================
+## get any environment variables
+
+my $hbDir = $ENV{'HBDIR'};
+if (defined ($hbDir))
+{
+ unless ($hbDir ne "")
+ {
+ $hbDir = '.'; #Set to current directory
+ }
+}
+else
+{
+ $hbDir = '.'; #Set to current directory
+}
+
+# print $#ARGV;
+if ( ($#ARGV < 0) or ($opt_help) )
+{
+ printUsage();
+ exit 0 ;
+}
+
+
+#------------------------------------------------------------------------------
+# Parse optional input arguments
+#------------------------------------------------------------------------------
+GetOptions( "help" => \$opt_help,
+ "istepmode" => \$opt_istepmode,
+ "normalmode" => \$opt_normalmode,
+ "list" => \$opt_list,
+ "command=s" => \$opt_command,
+ "cmdfile" => \$opt_cmdfile,
+
+ "debug" => \$opt_debug,
+ );
+
+##
+## find the istep mode, command, and status registers in the syms file
+##
+my $istepmodereg = `grep "SPLESS::g_SPLess_IStepMode_Reg" $hbDir/$hbSymsFile | awk -F"," '{print \$2}'`;
+chomp $istepmodereg;
+
+my $commandreg = `grep "SPLESS::g_SPLess_Command_Reg" $hbDir/$hbSymsFile | awk -F"," '{print \$2}'`;
+chomp $commandreg;
+
+my $statusreg = `grep "SPLESS::g_SPLess_Status_Reg" $hbDir/$hbSymsFile | awk -F"," '{print \$2}'` ;
+chomp $statusreg;
+
+if ( $opt_debug )
+{
+ print STDOUT "istepmode = $opt_istepmode\n";
+ print STDOUT "normalmode = $opt_normalmode\n";
+ print STDOUT "command = $opt_command\n";
+ print STDOUT "debug = $opt_debug\n";
+
+ print STDOUT "hbDir = $hbDir\n";
+ print STDOUT "hbSymsFile = $hbSymsFile\n";
+ print STDOUT "istepmodereg = $istepmodereg\n";
+ print STDOUT "commandreg = $commandreg\n";
+ print STDOUT "statusreg = $statusreg\n";
+
+ VBU_Cacheline::SetFlags( 1, 0 );
+
+}
+
+
+## fetch the ISTEP csv list
+get_istep_list();
+
+if ( $opt_list )
+{
+ print_istep_list();
+ exit;
+}
+
+ ## VPO cannot be running when we start.
+ my $qstr = VBU_Cacheline::P8_Ins_Query();
+ if ( $qstr ne "STOPPED" )
+ {
+ print STDOUT "VPO is \"$qstr\", setting to STOPPED.\n";
+ VBU_Cacheline::P8_Ins_Stop();
+ }
+
+##
+## process --Istep Mode command
+## IStepModeStr = "cpu0_0_0_3->scratch=0x4057b007_4057b007"
+## NormalModeStr = "cpu0_0_0_3->scratch=0x700b7504_700b7504"
+##
+if ( $opt_istepmode == 1 )
+{
+ print STDOUT "ENable istepmode\n";
+ setMode( "istep" );
+}
+
+if ( $opt_normalmode == 1 )
+{
+ print STDOUT "DISable istepmode\n";
+ setMode( "normal" );
+}
+
+##
+## Process other commands
+##
+if ( $opt_command ne "" )
+{
+ if ( $opt_debug ) { print STDOUT "== process command \"$opt_command\" \n"; }
+ parse_command( $opt_command );
+}
+
+
+#==============================================================================
+# SUBROUTINES
+#==============================================================================
+
+#------------------------------------------------------------------------------
+# Print command line help
+#------------------------------------------------------------------------------
+sub printUsage()
+{
+ print STDOUT "\nUsage: hb-istep [--help]\n";
+ print STDOUT " [--istepmode] (enable istep mode)\n" ;
+ print STDOUT " [--normalmode] (disable istep mode)\n" ;
+ print STDOUT " [--command sN] (run istep N)\n" ;
+ print STDOUT " [--command sN..M] (run isteps N through M)\n" ;
+ print STDOUT " [--command <foo>] (run named istep \"foo\")\n" ;
+ print STDOUT " [--command <foo>..<bar>] (run named isteps \"foo\" through \"bar\")\n" ;
+
+ print STDOUT "\n" ;
+
+}
+
+
+## read in file with csv istep list and store in inList
+sub get_istep_list()
+{
+ my $istep, my $substep, my $name ;
+
+ open( FH, "< $hbDir/$CSVfile") or die "can't open $hbDir/$CSVfile : $!";
+
+ while( <FH> )
+ {
+ chomp;
+
+ ( $istep, $substep, $name) = split( ",", $_ );
+ ## print STDERR "$_, $istep, $substep, $name\n" ;
+
+ $inList[$istep][$substep] = $name;
+ }
+
+ close( FH );
+}
+
+sub print_istep_list( )
+{
+ my $hdrflag = 1;
+
+ ## print STDOUT "IStep\tSubStep\tName\n";
+ print STDOUT " IStep Name\n";
+ print STDOUT "---------------------------------------------------\n";
+
+ for(my $i = 4; $i <= $#inList; $i++)
+ {
+ for(my $j = 0; $j <= $#inList; $j++)
+ {
+ ## print all substeps
+ # print "==$inList[$i][$j] \n";
+ if ( defined( $inList[$i][$j] ) )
+ {
+ if ( $hdrflag )
+ {
+ printf STDOUT " -- IStep $i -- \n";
+ $hdrflag = 0;
+ }
+ ## printf STDOUT "%d\t%d\t%s\n", $i, $j, $inList[$i][$j] ;
+ printf STDOUT " %s\n", $inList[$i][$j] ;
+ }
+ } ## end for $j
+ $hdrflag=1;
+ } ## end for $i
+}
+
+sub find_in_inList( $ )
+{
+ my ( $substepname ) = @_;
+
+ for(my $i = 0; $i <= $#inList; $i++)
+ {
+ for(my $j = 0; $j <= $#inList; $j++)
+ {
+ ## if ( defined($inList[$i][$j]) ) { print ".$inList[$i][$j]?$substepname. \n"; }
+
+ if ( defined($inList[$i][$j]) && ($inList[$i][$j] eq $substepname ) )
+ {
+ ## print "== $i $j $inList[$i][$j] \n";
+ return ($i, $j, 1 );
+ }
+ }
+ }
+
+ return ( $#inList, $#inList, 0 )
+}
+
+##
+## keep trying to get status until seqnum syncs up
+
+sub getSyncStatus( )
+{
+ # set # of retries
+ my $count = 100;
+ my $result = 0;
+ my $seqnum = 0;
+
+ ## get response. sendCmd() should have bumped g_SeqNum, so we will sit
+ ## here for a reasonable amount of time waiting for the correct sequence
+ ## number to come back.
+ while(1)
+ {
+
+ ## advance HostBoot code by a certain # of cycles, then check the
+ ## sequence number to see if it has changed. rinse and repeat.
+ VBU_Cacheline::RunClocks();
+
+ ## dump printk similar to the Jim McGuire's script
+ ## dumpPrintk();
+
+ $result = CLread( $statusreg );
+ $seqnum = ( ( $result & 0x3f00000000000000 ) >> 56 );
+ if ( $seqnum == $g_SeqNum )
+ {
+ return $result;
+ }
+
+ if ( $count <= 0 )
+ {
+ print STDOUT "TIMEOUT waiting for seqnum=$g_SeqNum\n";
+ return -1;
+ }
+ $count--;
+ } ## endwhile
+
+}
+
+sub runIStep( $$ )
+{
+ my ( $istep, $substep) = @_;
+ my $byte0, my $command;
+ my $cmd;
+ my $result;
+
+
+ ## bump the seqnum
+ $g_SeqNum++;
+
+ printf STDOUT "run %d.%d %s:\n", $istep, $substep, $inList[$istep][$substep];
+
+ $byte0 = 0x80 + $g_SeqNum; ## gobit + seqnum
+ $command = 0x00;
+ $cmd = sprintf( "0x%2.2x%2.2x%2.2x%2.2x00000000", $byte0, $command, $istep, $substep );
+ VBU_Cacheline::CLwrite( $commandreg, $cmd );
+
+ $result = getSyncStatus();
+
+ ## if result is -1 we have a timeout
+ if ( $result == -1 )
+ {
+ print "-----------------------------------------------------------------\n";
+ }
+ else
+ {
+ my $taskStatus = ( ( $result & 0x00ff000000000000 ) >> 48 );
+ my $stsIStep = ( ( $result & 0x0000ff0000000000 ) >> 40 );
+ my $stsSubstep = ( ( $result & 0x000000ff00000000 ) >> 32 );
+ my $istepStatus = ( ( $result & 0x00000000ffffffff ) );
+
+ print STDOUT "-----------------------------------------------------------------\n";
+ ## printf STDOUT "Istep %d.%d Status: 0x%x\n", $stsIStep, $stsSubstep, $istepStatus ;
+ if ( $taskStatus != 0 )
+ {
+ printf STDOUT "Istep %d.%d FAILED to launch, task status is %d\n", $stsIStep, $stsSubstep, $taskStatus ;
+ }
+ else
+ {
+ printf STDOUT "Istep %d.%d returned Status: 0x%x\n", $stsIStep, $stsSubstep, $istepStatus ;
+ }
+ print STDOUT "-----------------------------------------------------------------\n";
+ }
+
+}
+
+
+## run command = "sN"
+sub sCommand( $ )
+{
+ my ( $scommand ) = @_;
+
+ my $i = $scommand;
+ my $j = 0;
+
+ # sanity check
+ if ( !defined($inList[$i][0]) )
+ {
+ printf STDOUT "IStep %d.0 does not exist.\n", $i;
+ return -1;
+ }
+
+ # execute all the substeps in the IStep
+ for( $j=0; $j<$#inList; $j++ )
+ {
+ ## print "-----------------"
+ ##print STDOUT "run IStep %d %s ...\n", $i, $inList[$i][$j] );
+ ##print "-----------------"
+ if ( defined( $inList[$i][$j] ) )
+ {
+ runIStep( $i, $j );
+ }
+ }
+}
+
+
+sub parse_command()
+{
+ my ( $command ) = @_;
+ my @execlist;
+ my $istepM, my $substepM, my $foundit, my $istepN, my $substepN;
+ my $M, my $N, my $scommand;
+ my @ss_list;
+
+ ## check to see if we have an 's' command (string starts with 's' and a number)
+ chomp( $command);
+ if ( $command =~ m/^s+[0-9].*/ )
+ {
+ ## run "s" command
+ if ($opt_debug) { print STDOUT "===== s command : ", $command, ":\n"; }
+ substr( $command, 0, 1, "" );
+
+ if ( isdigit( $command ) )
+ {
+ # command = "sN"
+ if ($opt_debug) { print STDOUT "===== single IStep: ", $command, "\n"; }
+ sCommand( $command );
+ }
+ else
+ {
+ # list of substeps = "sM..N"
+ ( $M, $N ) = split( /\.\./, $command );
+
+ if ($opt_debug) { print STDOUT "===== multiple ISteps: ", $M, "-", $N, "\n"; }
+ for ( my $x=$M; $x<$N+1; $x++ )
+ {
+ sCommand( $x );
+ }
+ }
+ }
+ else
+ {
+ ## <substep name>, or <substep name>..<substep name>
+ @ss_list = split( /\.\./, $command );
+
+ if ($opt_debug) { print STDOUT "===== named commands : ", @ss_list, "\n"; }
+
+ ( $istepM, $substepM, $foundit) = find_in_inList( $ss_list[0] );
+ $istepN = $istepM;
+ $substepN = $substepM;
+ if ( ! $foundit )
+ {
+ print STDOUT "Invalid substep ", $ss_list[0], "\n" ;
+ return -1;
+ }
+
+
+ if ( $#ss_list > 0 )
+ {
+ ( $istepN, $substepN, $foundit) = find_in_inList( $ss_list[1] );
+ if ( ! $foundit )
+ {
+ print STDOUT "Invalid substep %s", $ss_list[1], "\n" ;
+ return -1;
+ }
+ }
+
+ ## print "got it, running isteps:\n";
+ for( my $x=$istepM; $x<$istepN+1; $x++ )
+ {
+ for( my $y=$substepM; $y<$substepN+1; $y++ )
+ {
+ ## print STDOUT "run $x $y $inList[$x][$y]\n";
+ runIStep( $x, $y );
+ }
+ }
+
+ }
+}
+
+## write to scratch reg 3 to set istep or normal mode, check return status
+sub setMode( )
+{
+ my ( $cmd ) = @_;
+ my $count = 0;
+ my $expected = 0;
+ my $readybit = 0;
+ my $result = 0;
+
+
+ if ( $cmd eq "istep" )
+ {
+ VBU_Cacheline::CLwrite( $istepmodereg, "0x4057b0074057b007" );
+ $expected = 1;
+ }
+ elsif ( $cmd eq "normal" )
+ {
+ VBU_Cacheline::CLwrite( $istepmodereg, "0x700b7504700b7504" );
+ $expected = 0;
+ }
+ else
+ {
+ print "invalid setMode command: %s\n", $cmd ;
+ return -1;
+ }
+
+ if ( $opt_debug )
+ {
+ ## readback and display
+ $result = CLread( $istepmodereg );
+ printf STDOUT "===== istepmodereg readback: 0x%lx\n", $result ;
+ }
+
+
+ ## Loop, advancing clock, and wait for readybit
+ $count = 30;
+ while(1)
+ {
+ ## advance HostBoot code by a certain # of cycles, then check the
+ ## sequence number to see if it has changed. rinse and repeat.
+ VBU_Cacheline::RunClocks();
+
+ $result = CLread( $statusreg );
+
+ $readybit = ( ( $result & 0x4000000000000000 ) >> 62 );
+
+ if ($opt_debug)
+ { printf STDOUT "===== setMode: count=%d, result=0x%lx, readybit=0x%x\n", $count, $result, $readybit }
+
+ if ( $readybit == $expected )
+ {
+ print STDOUT "Set $cmd Mode success.\n" ;
+ return 0;
+ }
+
+ if ( $count <= 0 )
+ {
+ print STDOUT "TIMEOUT waiting for readybit, status=0x%x\n", $result ;
+ return -1;
+ }
+
+ $count--;
+ }
+}
+
+__END__ \ No newline at end of file
diff --git a/src/build/vpo/hb-virtdebug.pl b/src/build/vpo/hb-virtdebug.pl
index 74013231c..19dc38d3f 100755
--- a/src/build/vpo/hb-virtdebug.pl
+++ b/src/build/vpo/hb-virtdebug.pl
@@ -568,6 +568,8 @@ if ($dumpAll)
}
+
+
#==============================================================================
# SUBROUTINES
#==============================================================================
diff --git a/src/usr/initservice/baseinitsvc/initservice.C b/src/usr/initservice/baseinitsvc/initservice.C
index aeda3deba..e2066ed0d 100644
--- a/src/usr/initservice/baseinitsvc/initservice.C
+++ b/src/usr/initservice/baseinitsvc/initservice.C
@@ -45,6 +45,17 @@
#include "initservice.H"
#include "initsvctasks.H"
+
+// ----- namespace SPLESS -----------------------------------------------
+namespace SPLESS
+{
+ // allocate space for SPLess Command regs
+ uint64_t g_SPLess_Command_Reg = 0;
+ uint64_t g_SPLess_Status_Reg = 0;
+ uint64_t g_SPLess_IStepMode_Reg = 0x123456789abcdef0;
+
+} // ----- end namespace SPLESS ---------------------------------------
+
namespace INITSERVICE
{
diff --git a/src/usr/initservice/baseinitsvc/initservicetaskentry.C b/src/usr/initservice/baseinitsvc/initservicetaskentry.C
index eec6eef96..68e5dfcae 100644
--- a/src/usr/initservice/baseinitsvc/initservicetaskentry.C
+++ b/src/usr/initservice/baseinitsvc/initservicetaskentry.C
@@ -61,6 +61,8 @@ void _start(void *ptr)
TRACFCOMP( g_trac_initsvc,
EXIT_MRK "return from Initialization Service module." );
+ printk( "Initialization Service terminated.\n" );
+
task_end();
}
diff --git a/src/usr/initservice/istepdispatcher/istepdispatcher.C b/src/usr/initservice/istepdispatcher/istepdispatcher.C
index 6ee6c18f5..0ad8333f2 100644
--- a/src/usr/initservice/istepdispatcher/istepdispatcher.C
+++ b/src/usr/initservice/istepdispatcher/istepdispatcher.C
@@ -44,7 +44,7 @@
#include <trace/interface.H> // trace support
#include <errl/errlentry.H> // errlHndl_t
#include <devicefw/userif.H> // targeting
-#include <sys/mmio.h> // mmio_scratch_read()
+
#include <initservice/taskargs.H> // TaskArgs structs
#include <errl/errluserdetails.H> // ErrlUserDetails base class
@@ -61,12 +61,13 @@
#include <isteps/istepmasterlist.H>
+// ----- namespace ERRORLOG -------------------------------------------
namespace ERRORLOG
{
/**
* @class IStepNameUserDetail
*
- * report the failing IStepName.
+ * report the failing IStepName to an errorlog
*
* @todo: get rid of magic numbers in version and subsection.
* set up tags, plugins, include files, etc.
@@ -108,15 +109,15 @@ IStepNameUserDetail(const IStepNameUserDetail &);
IStepNameUserDetail & operator=(const IStepNameUserDetail &);
};
-} // end namespace ERRORLOG
-
+} // ----- end namespace ERRORLOG -----------------------------------
+// ----- namespace INITSERVICE -------------------------------------------
namespace INITSERVICE
{
using namespace ERRORLOG; // IStepNameUserDetails
-using namespace SPLESS;
+using namespace SPLESS; // SingleStepMode
/******************************************************************************/
// Globals/Constants
@@ -124,41 +125,13 @@ using namespace SPLESS;
extern trace_desc_t *g_trac_initsvc;
/**
- * @note Since ISTEP_MODE attribute is nonvolatile (persists across boots),
- * we must have a way to turn the attribute both ON and OFF - we
- * cannot depend on the FSP to do it since we may not have a FSP.
- */
-const uint64_t ISTEP_MODE_ON_SIGNATURE = 0x4057b0074057b007;
-const uint64_t ISTEP_MODE_OFF_SIGNATURE = 0x700b7504700b7504;
-
-/**
- * @enum
- * SPLess Task return codes
- *
- * task return codes for SPless single step
- * @note future errors will be passed from task_create() and task_exec()
- * and should be documented in errno.h
- *
- */
-enum {
- SPLESS_TASKRC_INVALID_ISTEP = -3, // invalid istep or substep
- SPLESS_TASKRC_LAUNCH_FAIL = -4, // failed to launch the task
- SPLESS_TASKRC_RETURNED_ERRLOG = -5, // istep returned an errorlog
- SPLESS_TASKRC_TERMINATED = -6, // terminated the polling loop
-
- SPLESS_INVALID_COMMAND = 10, // invalid command from user console
-};
-
-/**
* @note SPLess PAUSE - These two constants are used in a nanosleep() call
* below to sleep between polls of the StatusReg. Typically this will
- * be about 100 ms - the actual value will be determined empirically.
- *
- * @debug simics "feature" - set polling time to 1 sec for demo
+ * be about 10 ms - the actual value will be determined empirically.
*
*/
-const uint64_t SINGLESTEP_PAUSE_S = 1;
-const uint64_t SINGLESTEP_PAUSE_NS = 100000000;
+const uint64_t SINGLESTEP_PAUSE_S = 0;
+const uint64_t SINGLESTEP_PAUSE_NS = 10000000;
/**
* @brief set up _start() task entry procedure using the macro in taskargs.H
@@ -241,7 +214,7 @@ void IStepDispatcher::init( void * io_ptr )
if ( getIStepMode() )
{
TRACFCOMP( g_trac_initsvc,
- "IStep single-step" );
+ "IStep single-step enable" );
// IStep single-step
singleStepISteps( io_ptr );
}
@@ -275,6 +248,7 @@ bool IStepDispatcher::getIStepMode( ) const
else
{
l_istepmodeflag = l_pTopLevel->getAttr<ATTR_ISTEP_MODE> ();
+ // printk( "IStep Mode flag = 0x%x\n", l_istepmodeflag );
}
@@ -282,50 +256,6 @@ bool IStepDispatcher::getIStepMode( ) const
}
-void IStepDispatcher::initIStepMode( )
-{
- using namespace TARGETING;
- uint64_t l_readData = 0;
- Target *l_pTopLevel = NULL;
- TargetService& l_targetService = targetService();
-
- (void) l_targetService.getTopLevelTarget(l_pTopLevel);
- if (l_pTopLevel == NULL)
- {
- TRACFCOMP( g_trac_initsvc, "Top level handle was NULL" );
- // drop through, default of attribute is is false
- }
- else
- {
- // got a pointer to Targeting, complete setting the flag
- l_readData = mmio_scratch_read( MMIO_SCRATCH_IPLSTEP_CONFIG );
-
- TRACDCOMP( g_trac_initsvc,
- "SCOM ScratchPad read, Offset 0x%x, Data 0x%llx",
- MMIO_SCRATCH_IPLSTEP_CONFIG,
- l_readData );
-
- // check for IStep Mode signature(s)
- if ( l_readData == ISTEP_MODE_ON_SIGNATURE )
- {
- l_pTopLevel->setAttr<ATTR_ISTEP_MODE> (true );
- TRACDCOMP( g_trac_initsvc,
- "ISTEP_MODE attribute set to TRUE." );
- }
-
- if ( l_readData == ISTEP_MODE_OFF_SIGNATURE )
- {
- l_pTopLevel->setAttr<ATTR_ISTEP_MODE> ( false );
- TRACDCOMP( g_trac_initsvc,
- "ISTEP_MODE attribute set to FALSE." );
- }
- }
-
-}
-
-
-
-
/**
* @brief Command 0: Run the requested IStep/SubStep
*
@@ -364,6 +294,14 @@ void IStepDispatcher::processSingleIStepCmd(
l_sts.substep = l_cmd.substep;
l_sts.istepStatus = 0;
+ /**
+ * @todo post informational errl here.
+ */
+ TRACFCOMP( g_trac_initsvc,
+ "processSingleIStepCmd: ERROR: Cannot find IStep=%d, SubStep=%d",
+ l_cmd.istep,
+ l_cmd.substep );
+
// return to caller to write back to user console
o_rrawsts.val64 = l_sts.val64;
break;
@@ -378,6 +316,12 @@ void IStepDispatcher::processSingleIStepCmd(
l_sts.substep = l_cmd.substep;
l_sts.istepStatus = 0;
+ TRACFCOMP( g_trac_initsvc,
+ "processSingleIStepCmd: Running IStep=%d, SubStep=%d",
+ l_cmd.istep,
+ l_cmd.substep );
+
+
// write intermediate value back to user console
o_rrawsts.val64 = l_sts.val64;
writeSts( o_rrawsts );
@@ -446,6 +390,11 @@ void IStepDispatcher::processSingleIStepCmd(
l_sts.substep = l_cmd.substep;
// istepStatus set above
+
+ /**
+ * @todo post informational errl here.
+ */
+
// write to status reg, return to caller to write to user console
o_rrawsts.val64 = l_sts.val64;
diff --git a/src/usr/initservice/istepdispatcher/istepdispatcher.H b/src/usr/initservice/istepdispatcher/istepdispatcher.H
index 5add1008c..48a8df18d 100644
--- a/src/usr/initservice/istepdispatcher/istepdispatcher.H
+++ b/src/usr/initservice/istepdispatcher/istepdispatcher.H
@@ -122,20 +122,6 @@ private:
/**
- * @brief init iv_istepmode flag, called in constructor
- *
- * Call into PNOR and fetch the "IStepMode flag" .
- *
- * @todo currently this calls into the kernel to get the value of
- * an SCOM Scratch Reg - this will change when PNOR is finished
- *
- * @return nothing
- *
- */
- void initIStepMode( );
-
-
- /**
* @brief getIStepMode - return value of IStep Mode
*
* @return bool - value of iv_istepmodeflag
diff --git a/src/usr/initservice/istepdispatcher/splesscommon.H b/src/usr/initservice/istepdispatcher/splesscommon.H
index d08b920c2..3cda0986c 100644
--- a/src/usr/initservice/istepdispatcher/splesscommon.H
+++ b/src/usr/initservice/istepdispatcher/splesscommon.H
@@ -41,6 +41,35 @@
#include <stdio.h>
#include <string.h>
+// undefine this before checking in....
+// #define SPLESS_DEBUG 1
+
+#ifdef SPLESS_DEBUG
+ #include <kernel/console.H> // printk DEBUG
+#endif
+
+#include <sys/mmio.h> // mmio_scratch_read()
+
+
+// external reference
+namespace INITSERVICE
+{
+ extern trace_desc_t *g_trac_initsvc;
+} // end namespace INITSERVICE
+
+
+/******************************************************************************/
+// SPLESS Command and Status Prototypes
+/******************************************************************************/
+
+/**
+ * @namespace SPLESSCMD
+ *
+ * Contains functions to manipulate the SPLESS Command Register
+ *
+ */
+namespace SPLESS
+{
/**
* @note Since ISTEP_MODE attribute is nonvolatile (persists across boots),
@@ -50,22 +79,122 @@
const uint64_t ISTEP_MODE_ON_SIGNATURE = 0x4057b0074057b007;
const uint64_t ISTEP_MODE_OFF_SIGNATURE = 0x700b7504700b7504;
-/******************************************************************************/
-// SPLESS Command Prototypes
-/******************************************************************************/
+/**
+ * @enum
+ * SPLess Task return codes
+ *
+ * task return codes for SPless single step
+ * @note future errors will be passed from task_create() and task_exec()
+ * and should be documented in errno.h
+ *
+ */
+enum {
+ SPLESS_TASKRC_INVALID_ISTEP = -3, // invalid istep or substep
+ SPLESS_TASKRC_LAUNCH_FAIL = -4, // failed to launch the task
+ SPLESS_TASKRC_RETURNED_ERRLOG = -5, // istep returned an errorlog
+ SPLESS_TASKRC_TERMINATED = -6, // terminated the polling loop
+
+ SPLESS_INVALID_COMMAND = 10, // invalid command from user console
+};
/**
- * @namespace SPLESSCMD
+ * @note declare global regs to implement SPLess.
+ * These replace the SCOM regs that are accessed by mmio; the reason we
+ * are changing this is that there is no support at present for read/writing
+ * SCOM in the Debug Framework.
+ * This will have to be modified again when we get to Secure Boot
*
- * Contains functions to manipulate the SPLESS Command Register
+ * @todo An review issue came up about when and how these are updated -
+ * While hostboot is running in SIMICS or VBU, the user console (i.e. a
+ * perl script, see src/build/vpo/hb_istep) will stop the instruction clock,
+ * write a command to g_SPLess_Command_Reg, and then restart the clock.
+ *
+ * Q1) In non-VPO mode (real FSP) are we always going to stop instructions
+ * to the processor to modify these variables?
+ * A: Yes, at this writing. If this changes, we should revisit this
+ * implementation.
+ *
+ * Q1a) Do these memory locations need to be accessed atomically (i.e. using
+ * __sync_add_and_fetch() and/or isync()/sync() )?
+ * A: No, not at this writing.
*
+ * Q2) When we stop instructions to the processor is the instruction pipeline
+ * and load/store queues flushed?
+ *
+ * A: No. The stop commands used in the simulator user console should
+ * quiesce the processor; this should guarantee that there are no
+ * outstanding loads or stores.
*/
-namespace SPLESS
-{
+extern uint64_t g_SPLess_Command_Reg;
+extern uint64_t g_SPLess_Status_Reg;
+extern uint64_t g_SPLess_IStepMode_Reg;
+/**
+ * @note SPLess commands, and masks for the status. Currently we only
+ * support one command through the SPLess interface.
+ *
+ */
const uint8_t SPLESS_SINGLE_ISTEP_CMD = 0x00;
const uint64_t SPLESS_SINGLE_STEP_STS_MASK = 0x00000000ffffffff;
+/**
+ * @brief init ISTEP_MODE attribute
+ *
+ * @return nothing
+ *
+ */
+inline void initIStepMode( )
+{
+ using namespace TARGETING;
+ uint64_t l_readData = 0;
+ Target *l_pTopLevel = NULL;
+ TargetService& l_targetService = targetService();
+
+ (void) l_targetService.getTopLevelTarget(l_pTopLevel);
+ if (l_pTopLevel == NULL)
+ {
+ TRACFCOMP( INITSERVICE::g_trac_initsvc, "Top level handle was NULL" );
+ // drop through, default of attribute is is false
+ }
+ else
+ {
+ // got a pointer to Targeting, complete setting the flag
+ // $$ save l_readData = mmio_scratch_read( MMIO_SCRATCH_IPLSTEP_CONFIG );
+ l_readData = g_SPLess_IStepMode_Reg;
+
+#ifdef SPLESS_DEBUG
+ printk( "IStepMode Reg = 0x%p, 0x%lx\n", &g_SPLess_IStepMode_Reg, l_readData );
+ printk( "Status Reg = 0x%p\n", &g_SPLess_Status_Reg );
+ printk( "Command Reg = 0x%p\n", &g_SPLess_Command_Reg );
+#endif
+ TRACDCOMP( INITSERVICE::g_trac_initsvc,
+ "IStepMode Reg = 0x%llx",
+ l_readData );
+
+ // check for IStep Mode signature(s)
+ if ( l_readData == ISTEP_MODE_ON_SIGNATURE )
+ {
+ l_pTopLevel->setAttr<ATTR_ISTEP_MODE> (true );
+
+ TRACDCOMP( INITSERVICE::g_trac_initsvc,
+ "ISTEP_MODE attribute set to TRUE." );
+ }
+ else if ( l_readData == ISTEP_MODE_OFF_SIGNATURE )
+ {
+ l_pTopLevel->setAttr<ATTR_ISTEP_MODE> ( false );
+
+ TRACDCOMP( INITSERVICE::g_trac_initsvc,
+ "ISTEP_MODE attribute set to FALSE." );
+ }
+ else
+ {
+ TRACFCOMP( INITSERVICE::g_trac_initsvc,
+ "unknown ISTEP_MODE signature: 0x%llx",
+ l_readData );
+ }
+ }
+
+}
/**
* @struct CommandHdr
@@ -155,7 +284,11 @@ private:
inline void readCmd( SPLessCmd &io_rcmd )
{
- io_rcmd.val64 = mmio_scratch_read(MMIO_SCRATCH_IPLSTEP_COMMAND);
+ // $$ save io_rcmd.val64 = mmio_scratch_read(MMIO_SCRATCH_IPLSTEP_COMMAND);
+ io_rcmd.val64 = g_SPLess_Command_Reg;
+#ifdef SPLESS_DEBUG
+ printk( "readCmd 0x%lx\n", g_SPLess_Command_Reg );
+#endif
}
@@ -172,7 +305,11 @@ inline void readCmd( SPLessCmd &io_rcmd )
inline void writeCmd( SPLessCmd &io_rcmd )
{
- mmio_scratch_write( MMIO_SCRATCH_IPLSTEP_COMMAND, io_rcmd.val64 );
+ // $$ save mmio_scratch_write( MMIO_SCRATCH_IPLSTEP_COMMAND, io_rcmd.val64 );
+ g_SPLess_Command_Reg = io_rcmd.val64;
+#ifdef SPLESS_DEBUG
+ printk( "writeCmd 0x%lx\n", g_SPLess_Command_Reg );
+#endif
}
@@ -260,7 +397,11 @@ union SPLessSingleIStepSts {
inline void readSts( SPLessSts &io_rsts )
{
- io_rsts.val64 = mmio_scratch_read(MMIO_SCRATCH_IPLSTEP_STATUS);
+ // $$ save io_rsts.val64 = mmio_scratch_read(MMIO_SCRATCH_IPLSTEP_STATUS);
+ io_rsts.val64 = g_SPLess_Status_Reg;
+#ifdef SPLESS_DEBUG
+ printk( "readSts 0x%lx\n", g_SPLess_Status_Reg );
+#endif
}
/**
@@ -272,8 +413,11 @@ inline void readSts( SPLessSts &io_rsts )
*/
inline void writeSts( SPLessSts &io_rsts )
{
- mmio_scratch_write( MMIO_SCRATCH_IPLSTEP_STATUS, io_rsts.val64 );
-
+ // $$ save mmio_scratch_write( MMIO_SCRATCH_IPLSTEP_STATUS, io_rsts.val64 );
+ g_SPLess_Status_Reg = io_rsts.val64;
+#ifdef SPLESS_DEBUG
+ printk( "writeSts 0x%lx\n", g_SPLess_Status_Reg );
+#endif
}
} // namespace
OpenPOWER on IntegriCloud