summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Wenning <wenning@us.ibm.com>2011-11-29 09:33:26 -0600
committerMark W. Wenning <wenning@us.ibm.com>2011-12-06 18:22:18 -0600
commit16bc626758b6dc65c1178e387501cb045e6dcd1d (patch)
tree19a98575511945ddc0c634a405b8cb776bd27dfd
parent6a169ffdcc62a48667bb3c22b7547b019dd7e1bf (diff)
downloadtalos-hostboot-16bc626758b6dc65c1178e387501cb045e6dcd1d.tar.gz
talos-hostboot-16bc626758b6dc65c1178e387501cb045e6dcd1d.zip
RTC3594: Improve SPLess Operation
- branch spless3 - reorganize command and status regs - add seqnum - rewrite spless handler - add scanistepnames.pl code to extract istep names - modify hb-simdebug.py to read istep names - review fixes - add workaround for vbu Change-Id: I0f8f991ccbaa822ef5ab672279c3c206e6b7b2e3 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/523 Tested-by: Jenkins Server Reviewed-by: Mark W. Wenning <wenning@us.ibm.com>
-rwxr-xr-xsrc/build/simics/hb-simdebug.py533
-rwxr-xr-xsrc/build/tools/cpfiles.pl1
-rw-r--r--src/include/usr/initservice/initsvcstructs.H21
-rw-r--r--src/include/usr/isteps/istep4list.H22
-rw-r--r--src/usr/initservice/build/makefile52
-rwxr-xr-xsrc/usr/initservice/build/scanistepnames.pl185
-rw-r--r--src/usr/initservice/istepdispatcher/istepdispatcher.C378
-rw-r--r--src/usr/initservice/istepdispatcher/istepdispatcher.H14
-rw-r--r--src/usr/initservice/istepdispatcher/makefile2
-rw-r--r--src/usr/initservice/istepdispatcher/splesscommon.H275
-rw-r--r--src/usr/initservice/makefile2
-rw-r--r--src/usr/initservice/test/splesstest.H396
12 files changed, 975 insertions, 906 deletions
diff --git a/src/build/simics/hb-simdebug.py b/src/build/simics/hb-simdebug.py
index 4a5e690bc..0f5774a2e 100755
--- a/src/build/simics/hb-simdebug.py
+++ b/src/build/simics/hb-simdebug.py
@@ -55,110 +55,251 @@ def dumpL3():
#------------------------------------------------------------------------------
+#------------------------------------------------------------------------------
# Functions to run isteps
#------------------------------------------------------------------------------
-def print_istep_list( inList ):
-
- print
- print "istep commands:."
+#------------------------------------------------------------------------------
+def hb_istep_usage():
+ print "hb-istep usage:"
print " istepmode - enable IStep Mode. Must be executed before simics run command"
print " normalmode - disable IStep Mode. "
print " list - list all named isteps"
print " sN - execute IStep N"
print " sN..M - execute IStep N through M"
- print " <name1> - excute named istep name1"
print " <name1>..<name2> - execute named isteps name1 through name2"
- print
- print "-----------------------------------------------------------"
- print " Supported ISteps: "
- print " IStep\tSubStep\tStepName "
- print "-----------------------------------------------------------"
-
- ## print len(inList)
- for i in range(0,len(inList)) :
- ##print len(inList[i])
- for j in range( 0, len(inList[i])) :
- print "%d\t%d\t%s"%( i, j, inList[i][j] )
-
- return None
-
-
-# normally this would be a loop to watch for the runningbit.
-# currently simics dumps all sorts of error lines every time a SCOM is
-# read, so HostBoot only updates every 1 sec. at that rate we only
-# need to sleep for 2 sec and we are sure to get it.
-# redo later after simics is fixed ...
-def getStatusReg():
- ##StatusStr = "salerno_chip.regdump SCOM 0x13012685"
- ## -f <file> dumps the output to <file>_SCOM_0X13012685
- ## StatusStr = "salerno_chip.regdump SCOM 0x13012685 -f ./scom.out"
- StatusStr = "cpu0_0_0_2->scratch"
-
- ## get response
- # (result, statusOutput) = quiet_run_command( StatusStr, output_modes.regular )
- result = conf.cpu0_0_0_2.scratch
- print "0x%x"%(result)
-
- hiword = ( ( result & 0xffffffff00000000) >> 32 )
- loword = ( result & 0x00000000ffffffff )
-
- return (hiword, loword)
-
-
-
-# normally this would be a loop to watch for the runningbit.
-# currently simics dumps all sorts of error lines every time a SCOM is
-# read, so HostBoot only updates every 1 sec. at that rate we only
-# need to sleep for 2 sec and we are sure to get it.
-# redo later after simics is fixed ...
-def runIStep( istep, substep, inList ):
- print "------------------------------------------------------------------"
- print "run %s :"%( inList[istep][substep] )
- print " istep # = 0x%x / substep # = 0x%x :"%(istep, substep)
-
- ## CommandStr = "salerno_chip.regwrite SCOM 0x13012684 \"0x80000000_%4.4x%4.4x\" 64"%(istep,substep)
- CommandStr = "cpu0_0_0_1->scratch=0x80000000_%4.4x%4.4x"%(istep,substep)
-
- #result = run_command( "run" )
-
+ print " debug - enable debugging messages"
+ return None
+
+## declare GLOBAL g_SeqNum var, & a routine to manipulate it.
+## TODO: make this into a class, etc. to do it The Python Way.
+g_SeqNum = 0
+def bump_g_SeqNum() :
+ global g_SeqNum
+ g_SeqNum = ( (g_SeqNum +1) & 0x3f)
+ return None
+
+## clock a certain amount of CPU cycles so the IStep will run (this will be
+## different for each simulation environment) and then return.
+## simics clock is a somewhat arbitrary value, may need to be adjusted.
+##
+## Handle following environments:
+## 1. [x] simics value = 100,000 (from Patrick)
+## 2. VPO value = ??? (don't know yet)
+## 3. hardware value = ??? ( ditto)
+##
+def runClocks() :
+
+ SIM_continue( 100000 )
+ return None
+
+##
+## send a command to the SPLess Command register (scratchpad reg 1)
+## cmd is passed in as a 64-bit ppc formatted hex string, i.e.
+## "0x80000000_00000000"
+##
+## Handle following environments:
+## 1. [x] simics
+## 2. VPO
+## 3. hardware
+def sendCommand( cmd ):
+ global g_IStep_DEBUG
+ CommandStr = "cpu0_0_0_1->scratch=%s"%(cmd)
+
## send command to Hostboot
- # print CommandStr
+ ## print CommandStr
(result, out) = quiet_run_command(CommandStr, output_modes.regular )
- #print result
- time.sleep(2)
-
- # result = run_command( "stop" )
+ if ( g_IStep_DEBUG ) :
+ print "sendCommand( 0x%x ) returns : " + "0x%x"%(cmd, result) + " : " + out
+
+ return result
+
+def printStsHdr( status ):
+
+ runningbit = ( ( status & 0x8000000000000000 ) >> 63 )
+ readybit = ( ( status & 0x4000000000000000 ) >> 62 )
+ seqnum = ( ( status & 0x3f00000000000000 ) >> 56 )
+ taskStatus = ( ( status & 0x00ff000000000000 ) >> 48 )
+
+ print "runningbit = 0x%x, readybit=0x%x, seqnum=0x%x, taskStatus=0x%x"%(runningbit, readybit, seqnum, taskStatus )
+ return None
+
+## get status from the SPLess Status Register (scratchpad reg 2)
+## returns a 64-bit int.
+##
+## Handle following environments:
+## 1. [x] simics
+## 2. VPO
+## 3. hardware
+##
+def getStatus():
+ global g_IStep_DEBUG
+ StatusStr = "cpu0_0_0_2->scratch"
+
+ ( result, out ) = quiet_run_command( StatusStr, output_modes.regular )
+ if ( g_IStep_DEBUG ) :
+ print ">> getStatus(): " + "0x%x"%(result) + " : " + out
+ ## printStsHdr(result)
+
+ return result
+
+
+## check for status, waiting for the readybit and the sent g_SeqNum.
+## default is to check the readybit, in rare cases we want to skip this.
+def getSyncStatus( ) :
+ # set # of retries
+ count = 100
+
+ ## 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 True :
+
+ ## advance HostBoot code by a certain # of cycles, then check the
+ ## sequence number to see if it has changed. rinse and repeat.
+ runClocks()
+
+ ## print a dot (with no carriage return) so that the user knows that
+ ## it's still doing something
+ print "." ,
+
+ result = getStatus()
+ seqnum = ( ( result & 0x3f00000000000000 ) >> 56 )
+ if ( seqnum == g_SeqNum ) :
+ print # print a final carriage return
+ return result
+
+ if ( count <= 0 ):
+ print # print a final carriage return
+ print "TIMEOUT waiting for seqnum=%d"%( g_SeqNum )
+ return -1
+ count -= 1
+
+## 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"
+
+
+ count = 10
+
+ if ( cmd == "istep" ) :
+ (result, out) = quiet_run_command( IStepModeStr )
+ # print "set istepmode returned 0x%x"%(result) + " : " + out
+ expected = 1
+ elif ( cmd == "normal" ) :
+ (result, out) = quiet_run_command( NormalModeStr )
+ # print "set normalmode returned 0x%x"%(result) + " : " + out
+ expected = 0
+ else :
+ print "invalid setMode command: %s"%(cmd)
+ return None
+
+ ## Loop, advancing clock, and wait for readybit
+ while True :
+ runClocks()
+
+ result = getStatus()
+ readybit = ( ( result & 0x4000000000000000 ) >> 62 )
+ print "Setting %s mode, readybit=%d..."%( cmd, readybit )
+ if ( readybit == expected ) :
+ print "Set %s Mode success."%(cmd)
+ return 0
+
+ if ( count <= 0 ):
+ print "TIMEOUT waiting for readybit, status=0x%x"%( result )
+ return -1
+ count -= 1
+
+
+## read in file with csv istep list and store in inList
+def get_istep_list( inList ):
+ istep_file = open('./isteplist.csv')
+ for line in istep_file.readlines():
+ ( istep, substep, name) = line.split(',')
+ i = int(istep)
+ j = int(substep)
+
+ ## print ":: %d %d %s"%(i, j, name)
+ if ( name.strip() != "" ):
+ inList[i][j] = name.strip()
+
+ istep_file.close()
- (hiword, loword) = getStatusReg()
+ return None
- runningbit = ( ( hiword & 0x80000000 ) >> 31 )
- readybit = ( ( hiword & 0x40000000 ) >> 30 )
- stsIStep = ( ( hiword & 0x3fff0000 ) >> 16 )
- stsSubstep = ( ( hiword & 0x0000ffff ) )
+
- taskStatus = ( ( loword & 0xffff0000 ) >> 16 )
- istepStatus = ( ( loword & 0x0000ffff ) )
- print
- print "%s : returned Status 0x%8.8x_%8.8x : "%( inList[istep][substep], hiword, loword )
- print "runningbit = 0x%x, readybit=0x%x"%(runningbit, readybit)
- print "Istep 0x%x / Substep 0x%x Status: 0x%x 0x%x"%( stsIStep, stsSubstep, taskStatus, istepStatus )
- print "-----------------------------------------------------------------"
-
- # result = run_command( "run" )
+def print_istep_list( inList ):
+ print "IStep\tSubStep\tName"
+ print "---------------------------------------------------"
+ for i in range(0,len(inList)) :
+ for j in range( 0, len(inList[i])) :
+ # print "%d %d"%(i,j)
+ if ( inList[i][j] != None ) :
+ print "%d\t%d\t%s"%( i,j, inList[i][j] )
+
+ print " "
+ return None
+
-## run command = "sN"
+def runIStep( istep, substep, inList ):
+
+ bump_g_SeqNum()
+
+ print "run %d.%d %s :"%( istep, substep, inList[istep][substep] )
+ ## print " istep # = 0x%x / substep # = 0x%x :"%(istep, substep)
+
+ byte0 = 0x80 + g_SeqNum ## gobit + seqnum
+ command = 0x00
+ cmd = "0x%2.2x%2.2x%2.2x%2.2x_00000000"%(byte0, command, istep, substep );
+ sendCommand( cmd )
+
+ result = getSyncStatus()
+
+ ## if result is -1 we have a timeout
+ if ( result == -1 ) :
+ print "-----------------------------------------------------------------"
+ else :
+ taskStatus = ( ( result & 0x00ff000000000000 ) >> 48 )
+ stsIStep = ( ( result & 0x0000ff0000000000 ) >> 40 )
+ stsSubstep = ( ( result & 0x000000ff00000000 ) >> 32 )
+ istepStatus = ( ( result & 0x00000000ffffffff ) )
+
+ print "-----------------------------------------------------------------"
+ ## printStsHdr(result)
+ ## print "Istep 0x%x / Substep 0x%x Status: 0x%x"%( stsIStep, stsSubstep, istepStatus )
+ if ( taskStatus != 0 ) :
+ print "Istep %d.%d FAILED to launch, task status is %d"%( taskStatus )
+ else:
+ print "Istep %d.%d returned Status: 0x%x"%( stsIStep, stsSubstep, istepStatus )
+ print "-----------------------------------------------------------------"
+
+ return
+
+
+## run command = "sN"
def sCommand( inList, scommand ) :
+
i = int(scommand)
j = 0
+
+ # sanity check
+ if ( inList[i][0] == None ) :
+ print "IStep %d.0 does not exist."%( i )
+ return
+
+ # execute all the substeps in the IStep
for substep in inList[i] :
- ## print "-----------------"
+ ## print "-----------------"
##print "run IStep %d %s ..."%(i, substep)
- ##print "-----------------"
- runIStep( i, j, inList )
+ ##print "-----------------"
+ if ( inList[i][j] != None ) :
+ runIStep( i, j, inList )
j = j+1
- return
-
+ return
+
+
def find_in_inList( inList, substepname) :
for i in range(0,len(inList)) :
for j in range( 0, len(inList[i])) :
@@ -166,78 +307,120 @@ def find_in_inList( inList, substepname) :
if ( inList[i][j] == substepname ) :
#print "%s %d %d"%( inList[i][j], i, j )
return (i,j, True )
- break;
-
- return ( len(inList), len(inList[i]), False )
-
-
+ break;
+
+ return ( len(inList), len(inList[i]), False )
+
+## ---------------------------------------------------------------------------
+## High Level Routine for ISteps.
+## ---------------------------------------------------------------------------
## possible commands:
## list
## istepmode
+## normalmode
## sN
## sN..M
## <substepname1>..<substepname2>
-def istepHB( str_arg1, inList):
- IStepModeStr = "cpu0_0_0_3->scratch=0x4057b007_4057b007"
- NormalModeStr = "cpu0_0_0_3->scratch=0x700b7504_700b7504"
- print "run isteps...."
-
- if ( str_arg1 == "list" ): ## dump command list
- print_istep_list( inList)
+## declare GLOBAL g_IStep_DEBUG
+g_IStep_DEBUG = 0
+def istepHB( str_arg1 ):
+
+ ## 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;
+
+
+ ## 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
+ inList[4][0] = "i1"
+ inList[4][1] = "i2"
+ inList[4][2] = "i3"
+ inList[4][3] = "i4"
+
+
+ ## bump seqnum
+ bump_g_SeqNum()
+
+ ## print "run istepHB...."
+
+ if ( str_arg1 == "debug" ) :
+ print "enable istep debug - restart simics to reset"
+ g_IStep_DEBUG = 1
return
-
+
if ( str_arg1 == "istepmode" ): ## set IStep Mode in SCOM reg
- print "Set Istep Mode"
- (result, out) = quiet_run_command(IStepModeStr, output_modes.regular )
- # print result
+ # print "Set Istep Mode"
+ setMode( "istep" )
return
-
+
if ( str_arg1 == "normalmode" ): ## set Normal Mode in SCOM reg
- print "Set Normal Mode"
- (result, out) = quiet_run_command(NormalModeStr, output_modes.regular )
- # print result
+ # print "Set Normal Mode"
+ setMode( "normal" )
return
-
- ## check to see if we have an 's' command (string starts with 's')
- if ( str_arg1.startswith('s') ):
+
+
+ ## get readybit to see if we are running in IStep Mode.
+ StatusReg = getStatus()
+ readybit = ( ( StatusReg & 0x4000000000000000 ) >> 62 )
+ if ( not readybit ):
+ print "ERROR: HostBoot Status reg is 0x%16.16x"%( StatusReg )
+ print " Ready bit is not on, did you remember to run hb-istep istepmode ??"
+ print " "
+ hb_istep_usage()
+ return None
+
+ ## get the list of isteps from HostBoot...
+ # print"get istep list"
+ get_istep_list( inList )
+
+ if ( str_arg1 == "list" ): ## dump command list
+ print_istep_list( inList )
+ return
+
+ ## check to see if we have an 's' command (string starts with 's' and a number)
+ if ( re.match("^s+[0-9].*", str_arg1 ) ):
## run "s" command
+ # print "s command"
scommand = str_arg1.lstrip('s')
+
if scommand.isdigit():
# command = "sN"
+ # print "single IStep: " + scommand
sCommand( inList, scommand )
else:
- print "multiple ISteps:" + scommand
# list of substeps = "sM..N"
(M, N) = scommand.split('..')
- #print M + "-" + N
+ # print "multiple ISteps: " + M + "-" + N
for x in range( (int(M,16)), (int(N,16)+1) ) :
sCommand( inList, x )
return
- else:
- ## substep name
+ else:
+ ## substep name .. substep name
+ ## print "named istep(s) : " + str_arg1
## (ss_nameM, ss_nameN) = str_arg1.split("..")
- namelist = str_arg1.split("..")
- if ( len(namelist) == 1 ) :
- (istepM, substepM, foundit) = find_in_inList( inList, namelist[0] )
- if ( not foundit ) :
- print "Invalid substep %s"%( namelist[0] )
- return
- runIStep( istepM, substepM, inList )
- else:
- ## substep name .. substep name
- (istepM, substepM, foundit) = find_in_inList( inList, namelist[0] )
- if ( not foundit ) :
- print "Invalid substep %s"%( namelist[0] )
- return
- (istepN, substepN, foundit) = find_in_inList( inList, namelist[1] )
+ ss_list = str_arg1.split("..")
+
+ (istepM, substepM, foundit) = find_in_inList( inList, ss_list[0] )
+ istepN = istepM
+ substepN = substepM
+ if ( not foundit ) :
+ print( "Invalid substep %s"%(ss_list[0] ) )
+ return
+
+ if ( len(ss_list) > 1 ) :
+ (istepN, substepN, foundit) = find_in_inList( inList, ss_list[1] )
if ( not foundit ) :
- print( "Invalid substep %s"%( namelist[1]) )
- return
- for x in range( istepM, istepN+1 ) :
- for y in range( substepM, substepN+1) :
+ print( "Invalid substep %s"%(ss_list[1] ) )
+ return
+
+ for x in range( istepM, istepN+1 ) :
+ for y in range( substepM, substepN+1 ) :
runIStep( x, y, inList )
- return
+ return
#===============================================================================
@@ -246,6 +429,7 @@ def istepHB( str_arg1, inList):
default_syms = "hbicore.syms"
default_stringFile = "hbotStringFile"
+
#------------------------------------------------
#------------------------------------------------
new_command("hb-trace",
@@ -318,42 +502,16 @@ Examples: \n
#------------------------------------------------
# implement isteps
#------------------------------------------------
-def hb_istep(str_arg1):
-
- ## preprocess inputs,
- ## read in a file and translate to an inList
- ## TODO read in default file
- # TODO inPath = "istep_list.txt"
- # TODO inFile = open( inPath, 'rU')
- # TODO inList = inFile.readlines()
- # TODO inFile.close()
-
- ## set up demo inlist
- inList = [ [ "na" ], ## istep 0
- [ "na" ], ## istep 1
- [ "na" ], ## istep 2
- [ "na" ], ## istep 3
- [ "init_target_states", ## istep 4
- "init_fsi",
- "apply_fsi_info",
- "apply_dd_presence",
- "apply_pr_keyword_data",
- "apply_partial_bad",
- "apply_gard",
- "testHWP"
- ],
- ]
-
- ## print flag_t
-
- if str_arg1 == None:
- print_istep_list( inList )
+def hb_istep(str_arg1):
+
+ if ( str_arg1 == None):
+ hb_istep_usage()
else:
- print "args=%s" % str(str_arg1)
- istepHB( str_arg1, inList, )
-
+ ## print "args=%s" % str(str_arg1)
+ istepHB( str_arg1 )
+
return None
-
+
new_command("hb-istep",
hb_istep,
[ arg(str_t, "syms", "?", None),
@@ -364,17 +522,19 @@ new_command("hb-istep",
short = "Run IStep commands using the SPLess HostBoot interface",
doc = """
Parameters: \n
-
+
Defaults: \n
Examples: \n
hb-istep \n
- hb-istep -s0 \n
- hb-istep -s0..4
- hb-istep poweron
- hb-istep poweron..clock_frequency_set
- """)
-
+ hb-istep -s4 \n
+ hb-istep -s4..N
+ hb-istep -4.1
+ hb-istep -4.1..4.3 \n
+ hb-istep poweron \n
+ hb-istep poweron..clock_frequency_set /n
+ """)
+
#------------------------------------------------
#------------------------------------------------
new_command("hb-errl",
@@ -420,36 +580,3 @@ new_command("hb-singlethread",
alias = "hb-st",
type = ["hostboot-commands"],
short = "Disable all threads except cpu0_0_0_0.")
-
-
-#------------------------------------------------
-#------------------------------------------------
-new_command("hb-callfunc",
- (lambda function, args:
- eval(run_hb_debug_framework("CallFunc",
- ("function='"+function+"' arguments="+
- (",".join(map(str, args)))),
- outputToString = 1))),
- [
- arg(str_t, "function"),
- arg(list_t, "args", "?", [])
- ],
- type = ["hostboot-commands"],
- see_also = ["hb-debug-CallFunc"],
- short = "Interactively call a hostboot function.",
- doc = """
-Parameters: \n
- function = Function to execute.\n
- args = List of arguments.\n
-
-Defaults: \n
- args = [0]\n
-
-Examples: \n
- hb-callfunc "malloc" [8]\n
- hb-callfunc "free" [0x1234]\n
-
-Note:
- This function may only be called with simics stopped.
- """)
-
diff --git a/src/build/tools/cpfiles.pl b/src/build/tools/cpfiles.pl
index 8828ae7a7..3c71b55fa 100755
--- a/src/build/tools/cpfiles.pl
+++ b/src/build/tools/cpfiles.pl
@@ -77,6 +77,7 @@ my @files = ("src/build/tools/hb-parsedump.pl",
"img/simics_SALERNO_targeting.bin",
"img/simics_VENICE_targeting.bin",
"img/vbu_targeting.bin",
+ "img/isteplist.csv",
);
#Directories in base git repository
diff --git a/src/include/usr/initservice/initsvcstructs.H b/src/include/usr/initservice/initsvcstructs.H
index 92913eb9b..2e9644132 100644
--- a/src/include/usr/initservice/initsvcstructs.H
+++ b/src/include/usr/initservice/initsvcstructs.H
@@ -33,7 +33,9 @@
// Includes
/******************************************************************************/
#include <stdint.h>
-#include <sys/vfs.h> // VFS_MODULE_MAX
+#include <sys/vfs.h> // VFS_MODULE_NAME_MAX
+
+#include <initservice/initsvcreasoncodes.H>
namespace INITSERVICE
@@ -49,6 +51,23 @@ namespace INITSERVICE
/******************************************************************************/
/**
+ * @note istepname tag - this is a way to call out the istep, substep, and
+ * istep name for spless operation. scanistepnames.pl will run
+ * through this, find the istepnames, and publish it as a CVS file
+ * for use by the SPLess user console (python) code.
+ * Usage:
+ * @ISTEPNAME( 4, 0, "init_target_states" )
+ *
+ * This will be picked up by scanistepnames.pl and put in as the line
+ * 4,0,init_target_states
+ *
+ * HostBoot will see it as the string "init_target_states" in the
+ * istepNlist.H file
+ */
+#define ISTEPNAME( ISTEP, SUBSTEP, NAME ) NAME
+
+
+/**
* @enum TaskType
* - NONE == placeholder, no task
* - INIT_TASK == load and initialize task, but task has no _start()
diff --git a/src/include/usr/isteps/istep4list.H b/src/include/usr/isteps/istep4list.H
index f520452ec..4aa29e87e 100644
--- a/src/include/usr/isteps/istep4list.H
+++ b/src/include/usr/isteps/istep4list.H
@@ -28,9 +28,11 @@
*
* list of functions called by HWAS (ISTEP 4) - "named isteps"
*
+ * Please see the note in initsvcstructs.H for description of
+ * the ISTEPNAME macro.
+ *
*/
-
#include <initservice/initsvcstructs.H>
#include <initservice/initsvcreasoncodes.H>
@@ -60,7 +62,7 @@ namespace INITSERVICE
const TaskInfo g_istep4[] = {
{
- "init_target_states" , // substep name
+ ISTEPNAME(4,0,"init_target_states"), // substep name
HWAS::init_target_states, // pointer to fn
{
START_FN, // task type
@@ -69,7 +71,7 @@ const TaskInfo g_istep4[] = {
}
},
{
- "init_fsi" , // substep name
+ ISTEPNAME(4,1,"init_fsi"), // substep name
HWAS::init_fsi, // pointer to fn
{
START_FN, // task type
@@ -78,7 +80,7 @@ const TaskInfo g_istep4[] = {
}
},
{
- "apply_fsi_info" , // substep name
+ ISTEPNAME(4,2,"apply_fsi_info"), // substep name
HWAS::apply_fsi_info, // pointer to fn
{
START_FN, // task type
@@ -87,7 +89,7 @@ const TaskInfo g_istep4[] = {
}
},
{
- "apply_dd_presence" , // substep name
+ ISTEPNAME(4,3,"apply_dd_presence"), // substep name
HWAS::apply_dd_presence, // pointer to fn
{
START_FN, // task type
@@ -96,7 +98,7 @@ const TaskInfo g_istep4[] = {
}
},
{
- "apply_pr_keyword_data" , // substep name
+ ISTEPNAME(4,4,"apply_pr_keyword_data"), // substep name
HWAS::apply_pr_keyword_data, // pointer to fn
{
START_FN, // task type
@@ -105,7 +107,7 @@ const TaskInfo g_istep4[] = {
}
},
{
- "apply_partial_bad" , // substep name
+ ISTEPNAME(4,5,"apply_partial_bad"), // substep name
HWAS::apply_partial_bad, // pointer to fn
{
START_FN, // task type
@@ -114,7 +116,7 @@ const TaskInfo g_istep4[] = {
}
},
{
- "apply_gard" , // substep name
+ ISTEPNAME(4, 6, "apply_gard"), // substep name
HWAS::apply_gard, // pointer to fn
{
START_FN, // task type
@@ -123,8 +125,8 @@ const TaskInfo g_istep4[] = {
}
},
{
- "testHWP" , // substep name
- HWAS::testHWP, // pointer to fn
+ ISTEPNAME(4,7,"testHWP"), // substep name
+ HWAS::testHWP, // pointer to fn
{
START_FN, // task type
EXT_IMAGE, // Extended Module
diff --git a/src/usr/initservice/build/makefile b/src/usr/initservice/build/makefile
new file mode 100644
index 000000000..e2e029af3
--- /dev/null
+++ b/src/usr/initservice/build/makefile
@@ -0,0 +1,52 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/initservice/build/makefile $
+#
+# 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
+#
+# makefile for initialization service build tasks.
+# 1. create isteplist.csv file for spless
+#
+
+
+ROOTPATH=../../../..
+
+## pull in IMGDIR, etc.
+include ${ROOTPATH}/src/usr/parser.mk
+
+OBJFILES=
+
+all: gen_pass code_pass
+
+gen_pass:
+
+code_pass: ${IMGDIR}/isteplist.csv
+
+${IMGDIR}/isteplist.csv : ${ROOTPATH}/src/include/usr/isteps/*.H
+ ./scanistepnames.pl -b $(ROOTPATH)/src/include/usr/isteps -d -o $@
+
+clean:
+ rm -fr ${IMGDIR}/isteplist.csv
+ rm -fr *.o
+
+debug:
+ ls -l ${GENDIR}
+ ls -l ${OBJDIR}
+ ls -l ${IMGDIR}
diff --git a/src/usr/initservice/build/scanistepnames.pl b/src/usr/initservice/build/scanistepnames.pl
new file mode 100755
index 000000000..02435087c
--- /dev/null
+++ b/src/usr/initservice/build/scanistepnames.pl
@@ -0,0 +1,185 @@
+#!/usr/bin/perl
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/initservice/build/scanistepnames.pl $
+#
+# 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
+
+#
+# scan files in the src/include/usr/isteps dir for ISTEPSNAME macro. This
+# calls out ISTeps that are executed by the IStep Dispatcher.
+# This perl script will create an img/istepnames.csv file that contains a
+# list of Comma-Separated-Values of the istep, substep, and istep names
+# that the user console should support. For example:
+# 4,0,init_target_states
+# 4,1,init_fsi
+# 4,2,apply_fsi_info
+# 4,3,apply_dd_presence
+# 4,4,apply_pr_keyword_data
+# 4,5,apply_partial_bad
+# 4,6,apply_gard
+# 4,7,testHWP
+
+use strict;
+use File::Find ();
+use Time::localtime;
+use File::Path;
+
+# Variables
+my $DEBUG = 0;
+my $sandBase = $ENV{HOSTBOOTROOT};
+
+my $arg;
+my $argOutput = "";
+my $output = "";
+
+# Arrays
+my @fileList;
+
+while( $ARGV = shift )
+{
+ if( $ARGV =~ m/-b/ )
+ {
+ # set base input dir
+ $sandBase = shift;
+ }
+ elsif( $ARGV =~ m/-o/i )
+ {
+ # set output filename
+ $argOutput = shift;
+ }
+ elsif( $ARGV =~ m/-h/i )
+ {
+ # help
+ usage();
+ }
+ elsif( $ARGV =~ m/-d/i )
+ {
+ # debug flag
+ $DEBUG = 1;
+ }
+ else
+ {
+ usage();
+ }
+}
+
+# Variables depending on input parameters
+if( $argOutput eq "" )
+{
+ $output = "$sandBase/img/istepnames.csv";
+}
+else
+{
+ $output = $argOutput;
+}
+
+print "base input dir: $sandBase\n";
+print "output file name: $argOutput\n";
+print "debug flag: $DEBUG\n";
+
+#debugMsg( "Source Base Path: $sourcebasePath" );
+#debugMsg( "Sandbox Base Dir: $sandBase" );
+#debugMsg( "Output Dir: $output" );
+
+@fileList = getFiles( $sandBase );
+
+open( OUTFILE, "> $argOutput" ) or die( "Cannot open: $argOutput: $!" );
+
+my $infile;
+my $csv;
+my $junk;
+my $junk2;
+
+foreach $infile ( @fileList )
+{
+ print "Scanning file $sandBase/$infile...\n";
+ open(INFILE, "< $sandBase/$infile") or die("Cannot open: $infile: $!");
+
+ while( <INFILE> )
+ {
+ if ( m/^ *ISTEPNAME/ )
+ {
+ ( $junk, $csv, $junk2 ) = split /[\(\)]/ ;
+ $csv =~ s/[" ]//g;
+ print $csv, "\n";
+ print OUTFILE $csv, "\n";
+ }
+ }
+
+}
+
+close (INFILE);
+close (OUTFILE);
+
+
+## Subroutines ################################################################
+
+##
+## Print the Usage message
+##
+sub usage
+{
+ print "Usage: $0 < -b base > <-d> < -o output file >\"\n";
+ print "\n";
+ print "-b: base directory ( default is pwd )\n";
+ print "-o: Output file path for csv file\n";
+ print "-d Enable Debug messages.\n";
+ print "-h Display usage message.\n";
+ print "\n\n";
+ exit 1;
+}
+
+
+#
+# Print debug messages if $DEBUG is enabled.
+#
+sub debugMsg
+{
+ my ($msg) = @_;
+ if( $DEBUG )
+ {
+ print "DEBUG: $msg\n";
+ }
+}
+
+
+#
+# getFiles - find *.H or *.C files
+# This recursively searches the input directory passed in for all C/H files.
+#
+sub getFiles
+{
+ my ($l_input_dir) = @_;
+ my @dir_entry;
+ my $basefilename;
+ local *DH;
+
+ debugMsg( "Getting Files for dir: $l_input_dir" );
+
+ # Open the directory and read all entry names.
+ opendir(DH, $l_input_dir) or die("Cannot open $l_input_dir: $!");
+ # skip the dots
+ ## @dir_entry = grep { !/^\./ } readdir(DH);
+ @dir_entry = grep { /^*.[CH]/ } readdir(DH);
+ closedir(DH);
+
+ return( @dir_entry );
+}
diff --git a/src/usr/initservice/istepdispatcher/istepdispatcher.C b/src/usr/initservice/istepdispatcher/istepdispatcher.C
index d2d889e06..df3178f6f 100644
--- a/src/usr/initservice/istepdispatcher/istepdispatcher.C
+++ b/src/usr/initservice/istepdispatcher/istepdispatcher.C
@@ -116,6 +116,7 @@ namespace INITSERVICE
{
using namespace ERRORLOG; // IStepNameUserDetails
+using namespace SPLESS;
/******************************************************************************/
// Globals/Constants
@@ -123,6 +124,14 @@ using namespace ERRORLOG; // IStepNameUserDetails
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
*
@@ -136,6 +145,8 @@ enum {
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
};
/**
@@ -146,7 +157,6 @@ enum {
* @debug simics "feature" - set polling time to 1 sec for demo
*
*/
-
const uint64_t SINGLESTEP_PAUSE_S = 1;
const uint64_t SINGLESTEP_PAUSE_NS = 100000000;
@@ -314,32 +324,167 @@ void IStepDispatcher::initIStepMode( )
}
-void IStepDispatcher::singleStepISteps( void * io_ptr ) const
+
+
+/**
+ * @brief Command 0: Run the requested IStep/SubStep
+ *
+ * param[in] i_rcmd - ref to a filled in SPLessCmd struct
+ * param[out] o_sts - ref to a SPLessSts struct to be filled in
+ *
+ * @return none
+ */
+void IStepDispatcher::processSingleIStepCmd(
+ SPLessCmd &i_rrawcmd,
+ SPLessSts &o_rrawsts ) const
{
- errlHndl_t l_errl = NULL;
- TaskArgs::TaskArgs l_args;
- const TaskInfo *l_pistep = NULL;
- bool l_gobit = false;
- uint16_t l_nextIStep = 0;
- uint16_t l_nextSubstep = 0;
- uint16_t l_taskStatus = 0;
- uint16_t l_istepStatus = 0;
- uint32_t l_progresscode = 0;
- uint64_t l_isteprc = 0;
+ errlHndl_t l_errl = NULL;
+ uint64_t l_isteprc = NULL;
+ TaskArgs::TaskArgs l_taskargs;
+ const TaskInfo *l_pistep = NULL;
+ // init the command 0x00 struct to the incoming command reg values
+ SPLessSingleIStepCmd l_cmd( i_rrawcmd );
+ // create a cleared status 0x00 reg
+ SPLessSingleIStepSts l_sts;
+
+ // look up istep+substep
+ l_pistep = IStepDispatcher::getTheInstance().findTaskInfo(
+ l_cmd.istep,
+ l_cmd.substep );
+
+ do
+ {
+ if ( l_pistep == NULL )
+ {
+ // invalid istep, return error
+ l_sts.hdr.runningbit = false;
+ l_sts.hdr.readybit = true;
+ l_sts.hdr.status = SPLESS_TASKRC_INVALID_ISTEP;
+ l_sts.istep = l_cmd.istep;
+ l_sts.substep = l_cmd.substep;
+ l_sts.istepStatus = 0;
+
+ // return to caller to write back to user console
+ o_rrawsts.val64 = l_sts.val64;
+ break;
+ }
+
+
+ // set running bit, fill in istep and substep
+ l_sts.hdr.runningbit = true;
+ l_sts.hdr.readybit = true;
+ l_sts.hdr.status = 0;
+ l_sts.istep = l_cmd.istep;
+ l_sts.substep = l_cmd.substep;
+ l_sts.istepStatus = 0;
+
+ // write intermediate value back to user console
+ o_rrawsts.val64 = l_sts.val64;
+ writeSts( o_rrawsts );
+
+ /**
+ * @todo placeholder - set progress code before starting
+ * This will not be finalized until the progress code driver
+ * is designed and implemented.
+ */
+ uint64_t l_progresscode = ( (l_cmd.istep<<16) | l_cmd.substep );
+ InitService::getTheInstance().setProgressCode( l_progresscode );
+
+
+ // clear the TaskArgs struct
+ l_taskargs.clear();
+
+ // clear the status struct for the next step
+ l_sts.val64 = 0;
+
+ // launch the istep
+ l_errl = InitService::getTheInstance().executeFn( l_pistep,
+ &l_taskargs );
+ // filter errors returning from executeFn
+ if ( l_errl )
+ {
+ // handle an errorlog from the parent. This means the
+ // launch failed, set the task Status to Bad.
+ // no need to process child info, thus the else.
+ // set the taskStatus to LAUNCH_FAIL; this will fall
+ // out the bottom and be written to SPLESS Status
+ l_sts.hdr.status = SPLESS_TASKRC_LAUNCH_FAIL;
+ errlCommit( l_errl, INITSVC_COMP_ID );
+ }
+ else
+ {
+ // process information returned from the IStep.
+ // make local copies of the info; this has a secondary
+ // effect of clearing the errorlog pointer inside
+ // the TaskArgs struct.
+ l_isteprc = l_taskargs.getReturnCode(); // local copy
+ l_errl = l_taskargs.getErrorLog(); // local copy
+
+ // check for child errorlog
+ if ( l_errl )
+ {
+ // tell the user that the IStep returned an errorlog
+ l_sts.hdr.status = SPLESS_TASKRC_RETURNED_ERRLOG;
+ // go ahead and commit the child errorlog
+ errlCommit( l_errl, INITSVC_COMP_ID );
+ }
- TRACFCOMP( g_trac_initsvc, "Start IStep single-step.\n" );
+ // truncate IStep return status to 32 bits.
+ l_isteprc &= SPLESS_SINGLE_STEP_STS_MASK;
+ l_sts.istepStatus = static_cast<uint32_t>(l_isteprc);
+ } // end else parent errlog
+
+ // task status and istepStatus should be set correctly now,
+ // send it to the user console.
+ // clear runningbit, report status
+ // set running bit, fill in istep and substep
+ l_sts.hdr.runningbit = false;
+ l_sts.hdr.readybit = true;
+ // l_sts.hdr.seqnum = i_seqnum;
+ // task status set above
+ l_sts.istep = l_cmd.istep;
+ l_sts.substep = l_cmd.substep;
+ // istepStatus set above
+
+ // write to status reg, return to caller to write to user console
+ o_rrawsts.val64 = l_sts.val64;
+
+ break;
+
+ } while(0);
+
+}
+
+
+/**
+ * @brief singleStepISteps
+ *
+ * Stop and wait for SP to send the next IStep to run. Run that, then
+ * wait for the next one.
+ * This is not expected to return - errors etc are sent to the user to
+ * handle.
+ *
+ * @param[in,out] io_ptr - pointer to any args passed in from
+ * ExtInitSvc. This may be a pointer to an
+ * TaskArgs struct (or something else) which
+ * can be filled out on return
+ *
+ * @return none
+ */
+void IStepDispatcher::singleStepISteps( void * io_ptr ) const
+{
+ SPLessCmd l_cmd;
+ SPLessSts l_sts;
+ uint8_t l_seqnum = 0;
// initialize command reg
- SPLESSCMD::write( false, // go bit is false
- 0, // istep = 0
- 0 ); // substep = 0
+ l_cmd.val64 = 0;
+ writeCmd( l_cmd );
- SPLESSSTS::write( false, // running bit
- true, // ready bit
- 0, // istep running
- 0, // substep running
- 0, // task status
- 0 ); // istep status
+ // init status reg, enable ready bit
+ l_sts.val64 = 0;
+ l_sts.hdr.readybit = true;
+ writeSts( l_sts );
//
// @note Start the polling loop.
@@ -349,134 +494,59 @@ void IStepDispatcher::singleStepISteps( void * io_ptr ) const
//
while( 1 )
{
- // read command reg, updates l_gobit, l_nextIStep, l_nextSubstep
- SPLESSCMD::read( l_gobit,
- l_nextIStep,
- l_nextSubstep );
- // process any commands
- if ( l_gobit )
- {
- TRACDCOMP( g_trac_initsvc,
- "gobit turned on, istep=0x%x, substep=0x%x",
- l_nextIStep,
- l_nextSubstep );
+ // read command register from user console
+ readCmd( l_cmd );
- // look up istep+substep
- l_pistep = findTaskInfo( l_nextIStep,
- l_nextSubstep );
- if ( l_pistep == NULL )
- {
- // no istep TaskInfo returned, update status & drop to end.
- TRACFCOMP( g_trac_initsvc,
- "Invalid IStep 0x%x / substep 0x%x, try again.",
- l_nextIStep,
- l_nextSubstep );
- SPLESSSTS::write( false,
- true,
- l_nextIStep,
- l_nextSubstep,
- SPLESS_TASKRC_INVALID_ISTEP,
- 0 );
- }
- else
+ // get the sequence number
+ l_seqnum = l_cmd.hdr.seqnum;
+
+ // process any pending commands
+ if ( l_cmd.hdr.gobit )
+ {
+ switch( l_cmd.hdr.cmdnum )
{
- // set running bit, fill in istep and substep
- SPLESSSTS::write( true, // set running bit
- true, // ready bit
- l_nextIStep, // running istep
- l_nextSubstep, // running substep
- 0, // task status (=0)
- 0 ); // istep status(=0)
-
- /**
- * @todo placeholder - set progress code before starting
- * This will not be finalized until the progress code driver
- * is designed and implemented.
- */
- l_progresscode = ( (l_nextIStep<<16) | l_nextSubstep );
- InitService::getTheInstance().setProgressCode( l_progresscode );
-
- // launch the istep
- TRACDCOMP( g_trac_initsvc,
- "execute Istep=0x%x / Substep=0x%x",
- l_nextIStep,
- l_nextSubstep );
-
- // clear status, etc for the next istep
- l_taskStatus = 0;
- l_istepStatus = 0;
- l_args.clear();
-
- // launch the istep
- l_errl = InitService::getTheInstance().executeFn( l_pistep,
- &l_args );
- // filter errors returning from executeFn
- if ( l_errl )
- {
- // handle an errorlog from the parent. This means the
- // launch failed, set the task Status to Bad.
- // no need to process child info, thus the else.
- // set the taskStatus to LAUNCH_FAIL; this will fall
- // out the bottom and be written to SPLESS Status
- l_taskStatus = SPLESS_TASKRC_LAUNCH_FAIL;
- TRACFCOMP( g_trac_initsvc,
- "ERROR 0x%x: function launch FAIL",
- l_taskStatus );
- errlCommit( l_errl, INITSVC_COMP_ID );
- }
- else
- {
- // process information returned from the IStep.
- // make local copies of the info; this has a secondary
- // effect of clearing the errorlog pointer inside
- // the TaskArgs struct.
- l_isteprc = l_args.getReturnCode(); // local copy
- l_errl = l_args.getErrorLog(); // local copy
-
- TRACDCOMP( g_trac_initsvc,
- "IStep TaskArgs return 0x%llx, errlog=%p",
- l_isteprc,
- l_errl );
-
- // check for child errorlog
- if ( l_errl )
- {
- // tell the user that the IStep returned an errorlog
- l_taskStatus = SPLESS_TASKRC_RETURNED_ERRLOG;
- // go ahead and commit the child errorlog
- errlCommit( l_errl, INITSVC_COMP_ID);
- }
-
- // truncate IStep return status to 16 bits.
- l_isteprc &= 0x000000000000ffff;
- l_istepStatus = static_cast<uint16_t>(l_isteprc);
-
- } // end else parent errlog
-
- // l_taskStatus and l_istepStatus should be set correctly now,
- // send it to the user.
- // clear runningbit, report status
- TRACDCOMP( g_trac_initsvc,
- "Write IStep Status: istep=0x%x, substep=0x%x, taskstatus=0x%x, istepstatus=0x%x",
- l_nextIStep,
- l_nextSubstep,
- l_taskStatus,
- l_istepStatus );
- SPLESSSTS::write( false, // clear running bit
- true, // ready bit
- l_nextIStep, // running istep
- l_nextSubstep, // running substep
- l_taskStatus, // task status
- l_istepStatus // istepStatus
- );
-
- SPLESSCMD::setgobit( false ); // clear gobit
- } // end else l_pistep
+ case SPLESS_SINGLE_ISTEP_CMD:
+ // command 0: run istep/substep
+ processSingleIStepCmd( l_cmd, l_sts );
+ break;
+
+ default:
+ l_sts.hdr.status = SPLESS_INVALID_COMMAND;
+ } // endif switch
+
+ l_sts.hdr.seqnum = l_seqnum;
+ // status should be set now, write to Status Reg.
+ writeSts( l_sts );
+
+ // clear command reg, including go bit (i.e. set to false)
+ l_cmd.val64 = 0;
+ writeCmd( l_cmd );
} // endif gobit
+
// sleep, and wait for user to give us something else to do.
- nanosleep( SINGLESTEP_PAUSE_S, SINGLESTEP_PAUSE_NS );
+ /**
+ * @todo Need a common method of doing delays in HostBoot
+ * @VBU workaround
+ */
+ // Don't delay as long in VBU because it will take VERY long to
+ // run the simulator
+ TARGETING::EntityPath syspath(TARGETING::EntityPath::PATH_PHYSICAL);
+ syspath.addLast(TARGETING::TYPE_SYS,0);
+ TARGETING::Target* sys = TARGETING::targetService().toTarget(syspath);
+ uint8_t vpo_mode = 0;
+ if( sys
+ && sys->tryGetAttr<TARGETING::ATTR_VPO_MODE>(vpo_mode)
+ && (vpo_mode == 0) )
+ {
+ nanosleep( SINGLESTEP_PAUSE_S, SINGLESTEP_PAUSE_NS );
+ }
+ else
+ {
+ // VBU delay per Patrick
+ nanosleep(0,TEN_CTX_SWITCHES_NS);
+ }
} // endwhile
@@ -485,22 +555,10 @@ void IStepDispatcher::singleStepISteps( void * io_ptr ) const
// Currently this will never be reached. Later there may be
// a reason to break out of the loop, if this happens we want to
// disable the ready bit so the user knows.
- SPLESSSTS::write( false,
- false,
- 0,
- 0,
- SPLESS_TASKRC_TERMINATED,
- 0
- );
-
- // all errorlogs should have been committed in the loop, we should
- // not have any errorlogs still set.
- if ( l_errl )
- {
- // if we do then commit it and stop here.
- errlCommit( l_errl, INITSVC_COMP_ID );
- assert(0);
- }
+ l_sts.val64 = 0;
+ l_sts.hdr.status = SPLESS_TASKRC_TERMINATED;
+ l_sts.hdr.seqnum = l_seqnum;
+ writeSts( l_sts );
}
diff --git a/src/usr/initservice/istepdispatcher/istepdispatcher.H b/src/usr/initservice/istepdispatcher/istepdispatcher.H
index 70e9f2883..5add1008c 100644
--- a/src/usr/initservice/istepdispatcher/istepdispatcher.H
+++ b/src/usr/initservice/istepdispatcher/istepdispatcher.H
@@ -56,6 +56,8 @@
namespace INITSERVICE
{
+// using namespace SPLESS;
+
/******************************************************************************/
// Globals/Constants
/******************************************************************************/
@@ -158,6 +160,18 @@ private:
const TaskInfo *findTaskInfo( uint16_t i_IStep,
uint16_t i_SubStep ) const;
+ /**
+ * @brief Command 0: Run the requested IStep/SubStep
+ *
+ * param[in] i_rcmd - ref to a filled in SPLessCmd struct
+ * param[out] o_sts - ref to a SPLessSts struct to be filled in
+ *
+ * @return none
+ */
+ void processSingleIStepCmd(
+ SPLESS::SPLessCmd &i_rcmd,
+ SPLESS::SPLessSts &o_rsts ) const;
+
/**
* @brief singleStepISteps
diff --git a/src/usr/initservice/istepdispatcher/makefile b/src/usr/initservice/istepdispatcher/makefile
index d18adfc4f..43e064f00 100644
--- a/src/usr/initservice/istepdispatcher/makefile
+++ b/src/usr/initservice/istepdispatcher/makefile
@@ -24,7 +24,7 @@
ROOTPATH = ../../../..
MODULE = istepdisp
-OBJS = istepdispatcher.o splesscommand.o splessstatus.o
+OBJS = istepdispatcher.o
## SUBDIRS = test.d
diff --git a/src/usr/initservice/istepdispatcher/splesscommon.H b/src/usr/initservice/istepdispatcher/splesscommon.H
index d75ee1f83..d08b920c2 100644
--- a/src/usr/initservice/istepdispatcher/splesscommon.H
+++ b/src/usr/initservice/istepdispatcher/splesscommon.H
@@ -29,6 +29,9 @@
* Prototypes for routines to access SPLESS Command and
* and SPLESS Status interfaces
*
+ * Currently SPLess only supports the one command 0x00, this rewrite will
+ * allow support of other SPLess commands.
+ *
*/
/******************************************************************************/
@@ -38,11 +41,9 @@
#include <stdio.h>
#include <string.h>
-/******************************************************************************/
-// Globals/Constants
-/******************************************************************************/
+
/**
- * @note Since ISTEP_MODE attribute is nonvolitile (persists across boots),
+ * @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.
*/
@@ -57,115 +58,123 @@ const uint64_t ISTEP_MODE_OFF_SIGNATURE = 0x700b7504700b7504;
* @namespace SPLESSCMD
*
* Contains functions to manipulate the SPLESS Command Register
- * @todo overload these later to get command and seq fields
*
*/
-namespace SPLESSCMD
+namespace SPLESS
{
+const uint8_t SPLESS_SINGLE_ISTEP_CMD = 0x00;
+const uint64_t SPLESS_SINGLE_STEP_STS_MASK = 0x00000000ffffffff;
+
+
/**
- * @union InternalCommand
- *
- * define the fields within the 64-bit Command Register
+ * @struct CommandHdr
*
-
+ * Command Header for all SPless commands. 2 bytes long.
* Bit numbers are in ppc notation, where bit 0 is the most significant bit.
* Go Bit : bit 0 (ppc notation, msbit)
* - set to 1 by the user to start the IStep
* - cleared to 0 by HostBoot
* Reserved: bit 1: always 0
* Sequence #: bits 2-7
- * Command Number: bits 8:15 - always 0 (for now)
- * Reserved: bits 16:31
- * Reserved: bits 32:39 - always 0
- * IStep Number: bits 40:47
- * Substep Number: bits 48:63gobit:
+ * Command Number: bits 8:15
+ *
*
*/
-union InternalCommand
+struct CommandHdr
{
- uint64_t val64;
- struct
- {
- bool gobit:1;
- uint8_t reserved0:1;
- uint8_t seqnum:6;
- uint8_t cmdnum;
+ bool gobit:1;
+ uint8_t reserved0:1;
+ uint8_t seqnum:6;
+ uint8_t cmdnum;
- uint16_t reserved2;
+} __attribute__((packed));
- uint16_t reserved3:2;
- uint16_t istep:14;
- uint16_t substep;
- } f PACKED;
+/**
+ * @union SPLessCmd
+ *
+ * 64-bit "template" struct for the SPLess command.
+ * This will be read in and used to extract the header info, then "cast"
+ * to the correct command.
+ */
+union SPLessCmd
+{
+ uint64_t val64;
+ struct
+ {
+ CommandHdr hdr;
+ uint16_t reserved1;
+ uint32_t reserved2;
+ } __attribute__((packed));
// init struct to 0
- InternalCommand() : val64(0) {};
+ SPLessCmd() : val64(0) {};
} ;
/**
- * @brief Read the command register and return the necessary fields.
+ * @union SPLessSingleIStepCmd
*
- * @param[in,out] io_rgobit - ref to a gobit var that will be filled in
- * on return
- * @param[in,out] io_ristep - ref to a istep var that will be filled in
- * on return
- * @param[in,out] io_rsubstep - ref to a substep var that will be filled
- * in on return
+ * Implement Command 0x00, run Istep/Substep
*
- * @return pointer to errorlog
- * @retval NULL if success, filled-in errorlog if failure
+ * Send IStep and SubStep number(s) to run.
*
*/
-void read( bool &io_rgobit,
- uint16_t &io_ristep,
- uint16_t &io_rsubstep );
+union SPLessSingleIStepCmd
+{
+ uint64_t val64;
+ struct
+ {
+ CommandHdr hdr;
+ uint8_t istep;
+ uint8_t substep;
+ uint32_t reserved;
+ } __attribute__((packed));
+ SPLessSingleIStepCmd() : val64(0) {};
-/**
- * @brief Write all the necessary fields to the command reg.
- *
- * Normally the user writes the command reg; this is only used to
- * init the command reg at the beginning
- *
- * @param[in] i_gobit - gobit value to write
- * @param[in] i_istep - istep value to write
- * @param[in] i_substep - substep value to write
- *
- * @return errorlog pointer
- * @retval NULL if success, filled-in errorlog if failure
- *
- */
-void write( const bool i_gobit,
- const uint16_t i_istep,
- const uint16_t i_substep );
+
+ SPLessSingleIStepCmd( const SPLessCmd &i_cmd )
+ : val64(i_cmd.val64) { };
+
+private:
+ // disable assignment constructor
+ SPLessSingleIStepCmd& operator=(const SPLessSingleIStepCmd& i_right);
+
+} ;
/**
- * @brief Read the gobit from the command register
+ * @brief Read the command register and return a filled-in SPLessCmd struct
*
- * @param o_rgobit - ref to a gobit var that will be filled in
- * on return.
+ * @param[in,out] io_rcmd - reference to a SPLessCmd struct
*
- * @return errorlog pointer
- * @retval NULL if success, filled-in errorlog on failure
+ * @return none
*/
-void getgobit( bool &o_rgobit );
+inline void readCmd( SPLessCmd &io_rcmd )
+{
+
+ io_rcmd.val64 = mmio_scratch_read(MMIO_SCRATCH_IPLSTEP_COMMAND);
+}
/**
- * @brief Write the gobit to the command register
- *
- * @param i_gobit - gobit value to be written
- *
- * @return pointer to errlog
- * @retval NULL if success, filled-in errorlog on failure
- */
-void setgobit( const bool i_gobit ) ;
+ * @brief Write a filled-in command struct to the command reg.
+ *
+ * Normally the user writes the command reg; this is only used to
+ * init the command reg at the beginning
+ *
+ * @param[in] i_rcmd - reference to a filled-in SPLessCmd reg
+ *
+ * @return none
+ */
+inline void writeCmd( SPLessCmd &io_rcmd )
+{
+
+ mmio_scratch_write( MMIO_SCRATCH_IPLSTEP_COMMAND, io_rcmd.val64 );
+}
-} // namespace
/******************************************************************************/
@@ -173,20 +182,12 @@ void setgobit( const bool i_gobit ) ;
/******************************************************************************/
/**
- * @namespace SPLESSSTS
+ * @struct StatusHdr
*
- * Contains functions to manipulate the SPLESS Status Register
- * @todo overload these to get seq # later
+ * header for the Status Reg returned by all SPLess Commands.
*
- */
-namespace SPLESSSTS
-{
-
-/**
- * @union InternalStatus
- *
- * define the fields within the 64-bit status register
- * Running bit, bit 0 (ppc notation, msbit):
+ * Bit numbers are in ppc notation, where bit 0 is the most significant bit.
+ * * Running bit, bit 0 (ppc notation, msbit):
* = 1 when IStep is running
* = 0 when IStep is finished
* Ready bit, bit 1:
@@ -196,80 +197,86 @@ namespace SPLESSSTS
* - IStep Mode Flag = 0
* Sequence # : bits 2-7 - echoes the sequence number in the associated
* command frame.
- * IStep Running, bits 8:15 - the IStep number that is currently running.
- * Sub-step Running, bits 16:31 - the substep that is currently running.
- * Task Status, bits 32:47 - the status that IStep Dispatcher returns when
- * trying to run the task. For example:
+ * Status : returned status for the command, from IStepDisp.
+ * For example:
* -EINVAL IStep number is invalid
* -ENOENT, -ENOEXEC (return code from kernel) IStep could not
* be launched as a task or as a function within a task
- * IStep Status, bits 48:63 - status returned from the IStep.
+ */
+struct StatusHdr
+{
+ bool runningbit:1;
+ bool readybit:1;
+ uint8_t seqnum:6;
+ int8_t status;
+
+} __attribute__((packed));
+
+/**
+ * @union SPLessSts
+ *
+ * Send HostBoot Status to the user console
*
*/
-union InternalStatus {
+union SPLessSts {
uint64_t val64;
struct {
- bool runningbit:1; // |
- bool readybit:1; // |
- uint8_t seqnum:6; // |
- uint8_t istep; // | 16 bits
- uint16_t substep; // 16 bits
- uint16_t taskStatus; // 16 bits
- uint16_t istepStatus; // 16 bits
- } f PACKED;
+ StatusHdr hdr;
+ uint16_t reserved1;
+ uint32_t reserved2;
+ } __attribute__((packed));
// init struct to 0
- InternalStatus() : val64(0) {};
+ SPLessSts() : val64(0) {};
} ;
+/**
+ * @union SPLessSts0x00
+ *
+ * Return Status from IStep/Substep
+ *
+ */
+union SPLessSingleIStepSts {
+ uint64_t val64;
+ struct {
+ StatusHdr hdr;
+ uint8_t istep;
+ uint8_t substep;
+ uint32_t istepStatus;
+ } __attribute__((packed));
+
+ SPLessSingleIStepSts() : val64(0) {};
+} ;
+
/**
- * @brief Read the SPLess Status SCOM Reg and return all its fields
+ * @brief Read the SPLess Status reg and return a filled in struct.
*
- * @param[in,out] io_rrunningbit - ref to runningbit var, to be
- * filled in on return
- * @param[in,out] io_rreadybit - ref to readybit var, to be filled in
- * on return
- * @param[in,out] io_ristep - ref to istep var, to be filled in on
- * return
- * @param[in,out] io_rsubstep - ref to substep var, to be filled in
- * on return
- * @param[in,out] io_rtaskStatus - ref to taskStatus var, to be filled
- * in on return
- * @param[in,out] io_ristepStatus - ref to istepStatus var, to be filled
- * in on return
+ * @param[in,out] io_rsts - ref SPLessSts struct
*
* @return none.
*/
-void read( bool &io_rrunningbit,
- bool &io_rreadybit,
- uint16_t &io_ristep,
- uint16_t &io_rsubstep,
- uint16_t &io_rtaskStatus,
- uint16_t &io_ristepStatus );
+inline void readSts( SPLessSts &io_rsts )
+{
+
+ io_rsts.val64 = mmio_scratch_read(MMIO_SCRATCH_IPLSTEP_STATUS);
+}
/**
- * @brief write
+ * @brief Write a filled in SPLessSts struct to the SPLess Status Reg
*
- * Read the SPLess Status SCOM Reg and return all its fields
- *
- * @param[in] i_runningbit - runningbit val to write
- * @param[in] i_readybit - readybit val to write
- * @param[in] i_istep - istep val to write
- * @param[in] i_substep - substep val to write
- * @param[in] i_taskStatus - taskStatus val to write
- * @param[in] i_istepStatus - istepStatus val to write
+ * @param[in,out] io_rsts
*
* @return none
*/
-void write( const bool i_runningbit,
- const bool i_readybit,
- const uint16_t i_istep,
- const uint16_t i_substep,
- const uint16_t i_taskStatus,
- const uint16_t i_istepStatus );
+inline void writeSts( SPLessSts &io_rsts )
+{
+ mmio_scratch_write( MMIO_SCRATCH_IPLSTEP_STATUS, io_rsts.val64 );
+
+}
} // namespace
+
#endif
diff --git a/src/usr/initservice/makefile b/src/usr/initservice/makefile
index 28240f386..5bdac5fde 100644
--- a/src/usr/initservice/makefile
+++ b/src/usr/initservice/makefile
@@ -29,6 +29,6 @@ ROOTPATH = ../../..
# NOTE: initsvctasktest2 is a dummy module that is executed by
# unit test 2 in the test directory. Please do not rename.
SUBDIRS = baseinitsvc.d extinitsvc.d taskargs.d istepdispatcher.d \
- test.d initsvctasktest2.d
+ test.d initsvctasktest2.d build.d
include ${ROOTPATH}/config.mk
diff --git a/src/usr/initservice/test/splesstest.H b/src/usr/initservice/test/splesstest.H
deleted file mode 100644
index d1caf006b..000000000
--- a/src/usr/initservice/test/splesstest.H
+++ /dev/null
@@ -1,396 +0,0 @@
-// IBM_PROLOG_BEGIN_TAG
-// This is an automatically generated prolog.
-//
-// $Source: src/usr/initservice/test/splesstest.H $
-//
-// 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
-
-#ifndef __TEST_SPLESS_H
-#define __TEST_SPLESS_H
-
-/**
- * @file splesstest.H
- *
- * Test SP-less interface to
- */
-
-#include <sys/time.h> // nanosleep
-#include <sys/mmio.h> // mmio_scratch_write/read
-
-#include <cxxtest/TestSuite.H>
-#include <devicefw/userif.H>
-
-#include "../istepdispatcher/istepdispatcher.H"
-
-#include "../istepdispatcher/splesscommon.H"
-
-using namespace INITSERVICE; // SPLessCommand and SPLessStatus
-using namespace TARGETING; // getIStepMode()
-
-/**
- * @class SPLessTest
- *
- * attempts to run ISteps using the SP-Less interface
- *
- */
-class SPLessTest: public CxxTest::TestSuite
-{
-
-public:
- /**
- * @brief testSPLessTest1
- *
- * - test that IStep Mode is enabled
- * - read SPLess status:
- * - ready bit should be on
- * - running bit shold be off
- * - status should be 0
- *
- */
- void testSPLessTest1( )
- {
- bool l_runningbit = false;
- bool l_readybit = false;
- uint16_t l_IStep = 0;
- uint16_t l_Substep = 0;
- uint16_t l_taskStatus = 0;
- uint16_t l_istepStatus = 0;
-
- if ( ! checkIStepMode() )
- {
- // IStepMode is off, don't bother running this
- TS_TRACE("IStepMode disabled, can't run unit test" );
- return;
- }
-
- SPLESSSTS::read( l_runningbit,
- l_readybit,
- l_IStep,
- l_Substep,
- l_taskStatus,
- l_istepStatus );
- if ( l_readybit == false )
- {
- TS_FAIL( "Ready bit should be on");
- }
-
- if ( l_runningbit == true )
- {
- TS_FAIL( "Running bit should be off");
- }
-
- if ( ( l_IStep != 0 ) ||
- ( l_Substep != 0 )
-
- )
- {
- TS_FAIL( "IStep and SubStep fields should be 0");
- }
-
-
- if ( ( l_taskStatus != 0 ) ||
- ( l_istepStatus != 0 )
-
- )
- {
- TS_FAIL( "Status fields should be 0");
- }
-
- }
-
- /**
- * @brief testSPLessTest2
- *
- * - Execute IStep 0, substep 0
- *
- * - this should succeed.
- *
- */
- void testSPLessTest2( )
- {
- uint16_t l_taskStatus = 0;
- uint16_t l_istepStatus = 0;
- bool l_pass = false;
-
- if ( ! checkIStepMode() )
- {
- // IStepMode is off, don't bother running this
- TS_TRACE("IStepMode disabled, can't run unit test" );
- return;
- }
-
- if ( ! checkReadyBit() )
- {
- TS_FAIL( "readybit is not enabled");
- return;
- }
-
- //
- l_pass = runIStep( 0, // IStep = 0
- 0, // Substep=0
- l_taskStatus, // task status
- l_istepStatus // istep status
- );
-
- if ( !l_pass )
- {
- TS_FAIL( "FAILED to run IStep");
- // dump errorlog?
- }
-
- if ( l_taskStatus != 0 )
- {
- TS_FAIL( "bad status: taskStatus expected 0, got %d",
- l_taskStatus);
- }
-
-
- if ( l_istepStatus != 0 )
- {
- TS_FAIL( "bad status: istepStatus expected 0, got %d",
- l_istepStatus);
- }
-
-
- }
-
-
- /**
- * @brief testSPLessTest3
- *
- * - Execute Invalid IStep
- *
- */
- void testSPLessTest3( )
- {
- uint16_t l_taskStatus = 0;
- uint16_t l_istepStatus = 0;
- bool l_pass = false;
-
- if ( ! checkIStepMode() )
- {
- // IStepMode is off, don't bother running this
- TS_TRACE("IStepMode disabled, can't run unit test" );
- return;
- }
-
-
- if ( ! checkReadyBit() )
- {
- TS_FAIL( "readybit is not enabled");
- return;
- }
-
- // run invalid istep/substep
- l_pass = runIStep( 55, // IStep = 55
- 55, // Substep=55
- l_taskStatus, // return task status
- l_istepStatus // return istep status
- );
-
- if ( !l_pass )
- {
- TS_FAIL( "FAILED to run IStep");
- // dump errorlog?
- }
-
- if ( (l_taskStatus != 0 ) ||
- (l_istepStatus != 0 )
- )
- {
- TS_FAIL( "bad status: taskStatus expected 0, got %d",
- l_taskStatus);
- }
-
-
- if (
- (l_istepStatus != 0 )
- )
- {
- TS_FAIL( "bad status: istepStatus expected 0, got %d",
- l_istepStatus);
- }
-
- }
-
-
- /**
- * @brief testSPLessTest4
- *
- * - Execute Several ISteps
- *
- *
- *
- */
- void testSPLessTest4( )
- {
-
- }
-
-
-private:
-
- /**
- * @brief checkIStepMode
- *
- * check that IStepMode is enabled, by reading the IStepModeSCOM for
- * a signature value.
- *
- * @return bool
- * @retval true if IStepMode is on, false otherwise
- */
- bool checkIStepMode()
- {
- uint64_t l_readData = 0;
- bool l_flag = false;
-
- l_readData = mmio_scratch_read( MMIO_SCRATCH_IPLSTEP_CONFIG );
-
- // check for IStep Mode signature, this is temporary
- if ( l_readData == ISTEP_MODE_ON_SIGNATURE )
- {
- l_flag = true;
- }
- else
- {
- l_flag = false;
- }
-
-
- return l_flag;
- }
-
- /**
- * @brief checkReadyBit
- *
- * check if the ready bit is on before starting any ISteps.
- *
- * This calls TS_FAIL and returns false if it cannot read the SCOM.
- *
- * @return bool
- * @retval true if readybit is on, false otherwise
- */
- bool checkReadyBit( )
- {
- bool l_runningbit = false;
- bool l_readybit = false;
- uint16_t l_IStep = 0;
- uint16_t l_Substep = 0;
- uint16_t l_taskStatus = 0;
- uint16_t l_istepStatus = 0;
-
- SPLESSSTS::read( l_runningbit,
- l_readybit,
- l_IStep,
- l_Substep,
- l_taskStatus,
- l_istepStatus );
-
- return l_readybit;
- }
-
-
- /**
- * @brief runIStep
- *
- * run one IStep /substep and return results.
- *
- * Assumes that readybit is on (i.e. you should have checked it
- * before calling this)
- *
- * calls TS_FAIL and returns false if cannot read the SCOM regs
- * calls TS_FAIL and returns false if times out waiting for runningbit
- * calls TS_FAIL and returns false if ready bit goes off
- *
- * @param[in] i_IStep - IStep to run
- * @param[in] i_Substep - Substep to run
- * @param[out] o_taskStatus - taskStatus returned from IStep/substep
- * @param[out] o_istepStatus - istepStatus retured from IStep/substep
- *
- * @return bool
- * @retval true if IStep runs OK, false otherwise
- */
- bool runIStep( uint16_t i_IStep,
- uint16_t i_Substep,
- uint16_t &o_taskStatus,
- uint16_t &o_istepStatus
- )
- {
- bool l_runningbit = false;
- bool l_readybit = false;
- uint16_t l_IStep = 0;
- uint16_t l_Substep = 0;
- bool l_pass = false;
-
- // init outputs
-
- l_IStep = 0;
- l_Substep = 0;
- o_taskStatus = 0;
- o_istepStatus = 0;
-
- l_pass = true; // assume things will be OK
-
-
- // Write gobit, istep, substep
- //
- SPLESSCMD::write( true, // gobit
- i_IStep, // istep
- i_Substep // substep
- );
- // loop up waiting for test to finish
- int timeoutctr = 10;
- do {
- // give it 500 millseconds to finish
- nanosleep( 0, 500000000 );
-
- SPLESSSTS::read( l_runningbit,
- l_readybit,
- l_IStep,
- l_Substep,
- o_taskStatus,
- o_istepStatus
- );
-
- // timeout probably means the singlestep loop died.
- // do a TS_FAIL
- if ( --timeoutctr <= 0 )
- {
- TS_FAIL( "TIMEOUT waiting for runningbit to turn off");
- l_pass = false;
- }
-
- } while (l_runningbit);
-
- // check readybit - if it's off it means the singlestep loop died.
- // do a TS_FAIL
- if ( ! l_readybit )
- {
- TS_FAIL( "FAIL: readybit is off");
- l_pass = false;
- }
-
- return l_pass;
- }
-
-}; // class
-
-
-#endif
-
OpenPOWER on IntegriCloud