diff options
author | Mark Wenning <wenning@us.ibm.com> | 2011-12-12 16:53:40 -0600 |
---|---|---|
committer | Mark W. Wenning <wenning@us.ibm.com> | 2012-01-20 16:42:41 -0600 |
commit | d62d15ecce724013e04106ad4cf217b9b341ccfc (patch) | |
tree | 9ca43d67fb2570e5afd85578ce03d2323a3fc725 /src | |
parent | 0408868bb339cab3222c5728012fca2306aa982b (diff) | |
download | talos-hostboot-d62d15ecce724013e04106ad4cf217b9b341ccfc.tar.gz talos-hostboot-d62d15ecce724013e04106ad4cf217b9b341ccfc.zip |
RTC4420 SPless on VPO
Modify SPLess code to use memory-mapped locations instead of SCOM
scratchpad regs - Debug Framework does not support this at this time.
VBU_Cacheline.pm is intended to be a module to read a single 64-bit
word (which will be the spless command, status, and istepmode regs)
from L3 memory within the AWAN model.
CLread() will read the cacheline (at 128-byte boundaries) and then
extract the quadword from the offet within the cacheline.
CLwrite() will read/modify/write the quadword and cacheline.
Note: There is a code block within VBU_Cacheline.pm called TEST -
this returns dummy values to CLread and CLwrite so that I can run
the perl script on a local system without connecting to simics or
AWAN. It is not normally used.
hb_istep is meant to be run after running a modified version of
Jim McGuire's do_p8vbu_script_hbi-Sprint7 . See my public directory
/gsa/ausgsa/home/w/e/wenning/Public/HBI/scripts for the modified
script. These changes will be merged back into Jim McGuire's
script later.
The modified version loads the binaries into L3, sets up all the rest
of the environment, and then exits BEFORE going into the execution
loop.
At that point, the user should run
hb-istep --istepmode
to set HostBoot up to run IStep SPLess (Single Step) .
The user can then run hb-istep commands to execute isteps, etc.
hb-istep use is documented on the wiki at
https://w3-connections.ibm.com/wikis/home?lang=en_US#/wiki/Host%20Boot/page/HB%20ISteps%20on%20AWAN
Please look there for updates.
- first commit, branch vbu2
- modify spless to use memory locations instead of SCOM regs
- add VBU_Cacheline.pm
- archive temporary version of do_p8vbu_script_hbi-mark
until we can get the hb-istep hooks into Jim McGuire's scripts
- add test calls to VBU_Cacheline.pm
- change flush call to Joe McGills "quiet" version
- add note that p8_ins* calls are in Jim McGuires dir and will
be replaced by the "official" ones soon.
- experiment with git notes command, sorry for the thrash
- add check to see if VPO is STOPPED before accessing anything
- partial review fixes - blocked on model: can't test
Change-Id: I07431dc525844c5c504175d92eae113457eac063
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/592
Tested-by: Jenkins Server
Reviewed-by: CAMVAN T. NGUYEN <ctnguyen@us.ibm.com>
Reviewed-by: Mark W. Wenning <wenning@us.ibm.com>
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 |