diff options
-rwxr-xr-x | src/build/simics/hb-simdebug.py | 533 | ||||
-rwxr-xr-x | src/build/tools/cpfiles.pl | 1 | ||||
-rw-r--r-- | src/include/usr/initservice/initsvcstructs.H | 21 | ||||
-rw-r--r-- | src/include/usr/isteps/istep4list.H | 22 | ||||
-rw-r--r-- | src/usr/initservice/build/makefile | 52 | ||||
-rwxr-xr-x | src/usr/initservice/build/scanistepnames.pl | 185 | ||||
-rw-r--r-- | src/usr/initservice/istepdispatcher/istepdispatcher.C | 378 | ||||
-rw-r--r-- | src/usr/initservice/istepdispatcher/istepdispatcher.H | 14 | ||||
-rw-r--r-- | src/usr/initservice/istepdispatcher/makefile | 2 | ||||
-rw-r--r-- | src/usr/initservice/istepdispatcher/splesscommon.H | 275 | ||||
-rw-r--r-- | src/usr/initservice/makefile | 2 | ||||
-rw-r--r-- | src/usr/initservice/test/splesstest.H | 396 |
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 - |