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