diff options
author | Mark Wenning <wenning@us.ibm.com> | 2012-05-09 17:19:03 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2012-05-21 12:59:00 -0500 |
commit | 487669b2da18343f648b4984765c36bb11f59b14 (patch) | |
tree | 38b47ee244c34deef4abc879ea95c9bcd2362ae4 /src/build | |
parent | 8277968ad48681189bf58cb785ebf01c5d6fdf37 (diff) | |
download | talos-hostboot-487669b2da18343f648b4984765c36bb11f59b14.tar.gz talos-hostboot-487669b2da18343f648b4984765c36bb11f59b14.zip |
hb-istep in debug framework
Change-Id: I21d95952e526e3ade6399c2f7e022e0897ae4610
RTC: 38308
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/959
Tested-by: Jenkins Server
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/build')
-rwxr-xr-x | src/build/debug/Hostboot/Istep.pm | 1017 | ||||
-rwxr-xr-x | src/build/debug/Hostboot/_DebugFramework.pm | 32 | ||||
-rwxr-xr-x | src/build/debug/simics-debug-framework.pl | 130 | ||||
-rwxr-xr-x | src/build/debug/simics-debug-framework.py | 64 | ||||
-rwxr-xr-x | src/build/debug/vpo-debug-framework.pl | 207 | ||||
-rwxr-xr-x | src/build/simics/hb-simdebug.py | 570 |
6 files changed, 1443 insertions, 577 deletions
diff --git a/src/build/debug/Hostboot/Istep.pm b/src/build/debug/Hostboot/Istep.pm new file mode 100755 index 000000000..e014e26fd --- /dev/null +++ b/src/build/debug/Hostboot/Istep.pm @@ -0,0 +1,1017 @@ +#!/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 - 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_TAG +# +# Purpose: This perl script works in concert with do_sprint to +# implement isteps on AWAN. +# +# Description: +# The do_sprint 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 (spless or FSP). +# 2) hb_Istep [--]command +# Periodically call ::executeInstrCycles() to step through HostBoot. +# Checks for status from previous Isteps, and reports status. +# +# Author: Mark Wenning +# +# DEVELOPER NOTES: +# Do NOT put prints or printf's in this script!!! +# simics-debug-framework.pl and simics-debug-framework.py communicate +# (recvIPCmsg and sendIPCmsg) overstdin and stdout - +# if you print to STDOUT you will inadvertently send an empty/corrupted +# "IPC" message to python/simics which will usually cause ugly crashes. +# + +#------------------------------------------------------------------------------ +# Specify perl modules to use +#------------------------------------------------------------------------------ +use strict; +use POSIX; # isdigit + +## 64-bit input +use bigint; +no warnings 'portable'; + + +## declare Istep package +package Hostboot::Istep; +use Exporter; +our @EXPORT_OK = ('main'); + +#------------------------------------------------------------------------------ +# Constants +#------------------------------------------------------------------------------ +## @todo extract these from splesscommon.H +use constant SPLESS_MODE_SIGNATURE => 0x4057b0074057b007; +use constant FSP_MODE_SIGNATURE => 0x700b7504700b7504; +use constant RUN_ALL_MODE_SIGNATURE => 0xBADC0FFEE0DDF00D; + +use constant SPLESS_SINGLE_ISTEP_CMD => 0x00; +use constant SPLESS_RESUME_ISTEP_CMD => 0x01; +use constant SPLESS_CLEAR_TRACE_CMD => 0x02; +use constant SPLESS_SHUTDOWN_CMD => 0x03; + + +use constant MAX_ISTEPS => 25; +use constant MAX_SUBSTEPS => 25; + +## Mailbox Scratchpad regs +use constant MBOX_SCRATCH0 => 0x00050038; +use constant MBOX_SCRATCH1 => 0x00050039; +use constant MBOX_SCRATCH2 => 0x0005003a; +use constant MBOX_SCRATCH3 => 0x0005003b; + +#------------------------------------------------------------------------------ +# Globals +#------------------------------------------------------------------------------ +my $opt_debug = 0; +my $opt_splessmode = 0; +my $opt_fspmode = 0; +my $opt_command = 0; +my $opt_list = 0; +my $opt_resume = 0; +my $opt_clear_trace = 0; + +## deprecated - keep around for now +my $opt_istepmode = 0; + +my $command = ""; + + +## initialize inList to "undefined" +my @inList; +$inList[MAX_ISTEPS][MAX_SUBSTEPS] = (); +for( my $i = 0; $i < MAX_ISTEPS; $i++) +{ + for(my $j = 0; $j < MAX_SUBSTEPS; $j++) + { + undef( $inList[$i][$j] ); + } +} + +## initialize the sequence number - 6 bit field, { 0 - 63 } +my $g_SeqNum = int(rand(64)); + +my $THREAD = "0"; + + +## -------------------------------------------------------------------------- +## get any environment variables +## -------------------------------------------------------------------------- + +## @todo make this an enviroment var? +## NOTE: this is the # cycles used for simics, it is multiplied by 100 +## in vpo-debug-framework.pl +## my $hbDefaultCycles = 50000; +my $hbDefaultCycles = 5000000; + +my $hbCount = $ENV{'HB_COUNT'}; +if ( !defined( $hbCount ) || ( $hbCount eq "" ) ) +{ + ## set default + $hbCount = 0xffffffff; ## effectively infinite ... +} + + +## fetch all the symbols we need. +my $IstepModeReg = getSymbol( "SPLESS::g_SPLess_IStepMode_Reg" ); +my $ShutDownFlag = getSymbol( "CpuManager::cv_shutdown_requested" ); +my $ShutDownSts = getSymbol( "CpuManager::cv_shutdown_status" ); + +## @todo deprecated, fetch anyway for now +my $CommandReg = getSymbol( "SPLESS::g_SPLess_Command_Reg" ); +my $StatusReg = getSymbol( "SPLESS::g_SPLess_Status_Reg" ); + + +######################################################################## +## MAIN ROUTINE, called from debug framework +######################################################################## +sub main +{ + ## $packName is the name of the selected tool + ## $args is a hashref to all the command-line arguments + my ($packName,$args) = @_; + + + ## debug - save + while ( my ($k,$v) = each %$args ) + { + ::userDisplay "args: $k => $v\n"; + } + + ::userDisplay "Welcome to hb-Istep 3.3 .\n"; + ::userDisplay "Note that in simics, multiple options must be in quotes\n\n"; + ## fetch the istep list + get_istep_list(); + + ## $$ debug, dump all the environment vars that we are interested in + dumpEnvVar( "HB_TOOLS" ); + dumpEnvVar( "HB_IMGDIR" ); + dumpEnvVar( "HB_VBUTOOLS" ); + dumpEnvVar( "HB_COUNT" ); + + ##-------------------------------------------------------------------------- + ## Start processing options + ## process the "flag" standard options, then use a loop to go through + ## the rest + ##-------------------------------------------------------------------------- + ## Get all the command line options in an array + my @options = ( keys %$args ); + + if ( !(@options) ) + { + ::userDisplay "type \"help hb-istep\" for help\n"; + exit; + } + + ## find all the standard options, set their flag, and remove them from + ## the options list. + ## vpo and simics have used difference command-line styles, simics + ## wanted you to say "hb-istep debug s4", and vpo wanted you to say + ## "hb-istep --debug --command s4" . This should accept both styles. + ## + for ( my $i=0; $i <= $#options; $i++ ) + { + $_ = $options[$i]; + + if ( m/\-{0,2}debug/ ) + { + $opt_debug = 1; + $options[$i] = ""; + } + if ( m/\-{0,2}list/ ) + { + $opt_list = 1; + $options[$i] = ""; + } + if ( m/\-{0,2}istepmode/ ) + { + $opt_istepmode = 1; + $options[$i] = ""; + } + if ( m/\-{0,2}splessmode/ ) + { + $opt_splessmode = 1; + $options[$i] = ""; + } + if ( m/\-{0,2}fspmode/ ) + { + $opt_fspmode = 1; + $options[$i] = ""; + } + if ( m/\-{0,2}command/ ) + { + ## doesn't do much, just eats the option + $opt_command = 1; + $options[$i] = ""; + } + if ( m/\-{0,2}resume/ ) + { + $opt_resume = 1; + $options[$i] = ""; + } + if ( m/\-{0,2}clear-trace/ ) + { + $opt_clear_trace = 1; + $options[$i] = ""; + } + } ## endfor + + ## if there's anything left after this, assume it is a command + $command = join( "", @options ); + chomp $command; + + ## print out debug info + if ( $opt_debug ) + { + ::userDisplay "\n----- DEBUG: ------------------------------- \n"; + ::userDisplay "debug = $opt_debug\n"; + ::userDisplay "list = $opt_list\n"; + ::userDisplay "splessmode = $opt_splessmode\n"; + ::userDisplay "fspmode = $opt_fspmode\n"; + + ::userDisplay "resume = $opt_resume\n"; + ::userDisplay "clear-trace = $opt_clear_trace\n"; + ::userDisplay "command flag = $opt_command\n"; + ::userDisplay "command = \"$command\"\n"; + + ::userDisplay "g_SeqNum = ", sprintf("0x%x",$g_SeqNum), "\n"; + ::userDisplay "IstepModeReg = ", sprintf("0x%x",$IstepModeReg), "\n"; + ::userDisplay "CommandReg = ", sprintf("0x%x",$CommandReg), "\n"; + ::userDisplay "StatusReg = ", sprintf("0x%x",$StatusReg), "\n"; + ::userDisplay "ShutDownFlag = ", sprintf("0x%x",$ShutDownFlag), "\n"; + ::userDisplay "ShutDownSts = ", sprintf("0x%x",$ShutDownSts), "\n"; + + ::userDisplay "hbCount = ", sprintf("0x%x",$hbCount), "\n"; + + ::userDisplay "\n"; + } + + if ( $opt_debug ) { ::userDisplay "=== check ShutDown Status...\n"; } + if ( isShutDown() ) + { + ::userDisplay "Cannot run hb-Istep.\n"; + exit; + } + + ## ---------------------------------------------------------------- + ## finally, run some commands. + ## ---------------------------------------------------------------- + + if ( $opt_list ) + { + ::userDisplay "List isteps\n"; + print_istep_list(); + exit; + } + + if ( $opt_istepmode ) + { + ::userDisplay "istepmode no longer used - use splessmode, or fspmode\n"; + exit; + } + + if ( $opt_splessmode ) + { + ::userDisplay "ENable splessmode\n"; + setMode( "spless" ); + exit; + } + + if ( $opt_fspmode ) + { + ::userDisplay "ENable fspmode\n"; + setMode( "fsp" ); + exit; + } + + ## don't do any other commands unless ready bit is on. + if ( ! isReadyBitOn() ) + { + ::userDisplay "Ready bit is off, must run splessmode or fspmode first.\n"; + exit; + } + + if ( $opt_clear_trace ) + { + ::userDisplay "Clear Trace\n"; + clear_trace(); + exit; + } + + if ( $opt_resume ) + { + ::userDisplay "Resume\n"; + resume_istep(); + exit; + } + + if ( $opt_command || ( $command ne "" ) ) + { + ::userDisplay "Process command \"$command\"\n"; + process_command( $command ); + exit; + } + + ::userDisplay "Done.\n"; + exit 0; +} ## end main + +######################################################################## +## SUBROUTINES +######################################################################## +## + + +sub helpInfo +{ + my %info = ( + name => "Istep", + intro => ["Executes isteps."], + options => { "list" => [" list out all supported isteps "], + "splessmode" => ["enable istep mode"], + "fspmode" => ["enable istep mode"], + "resume" => ["resume an istep that is at a break point"], + "clear-trace" => ["clear trace buffers before starting"], + "sN" => ["run istep N"], + "sN..M" => ["run isteps N through M"], + "<foo>" => ["run named istep \"foo\""], + "<foo>..<bar>" => ["run named isteps \"foo\" through \"bar\""], + } + ); +} + + +## Increment the sequence number, rolling over at 64 +## --------------------------------------------------------------------------- +sub bumpSeqNum() +{ + + $g_SeqNum++; + + $g_SeqNum %= 64; + + return $g_SeqNum; +} + +## --------------------------------------------------------------------------- +## Dump environment variable specified. +## --------------------------------------------------------------------------- +sub dumpEnvVar( $ ) +{ + my $envvar = shift; + + if ( defined( $ENV{$envvar} ) ) + { + ::userDisplay "$envvar = $ENV{$envvar}\n"; + } +} + +## +## Get symbol address from hbotSymsFile +## +sub getSymbol( ) +{ + my $symbol = shift; + my ($symAddr, $symSize) = ::findSymbolAddress( $symbol ) ; + + if ( not defined( $symAddr ) ) + { + ::userDisplay "Cannot find $symbol.\n"; die; + } + + return $symAddr; +} + +## +## read in file with csv istep list and store in inList +## +sub get_istep_list() +{ + my $istep, my $substep, my $name ; + + my @isteplist = ::getIstepList(); + + foreach( @isteplist ) + { + chomp; + + ( $istep, $substep, $name) = split( ",", $_ ); + chomp $name; + + ## ::userDisplay "$_, $istep, $substep, $name\n" ; + + if ( defined($name) && ( $name ne "" ) ) + { + $inList[$istep][$substep] = $name; + } + } + +} + + +## +## print the istep list to the screen. +## +sub print_istep_list( ) +{ + my $hdrflag = 1; + + ::userDisplay " IStep Name\n"; + ::userDisplay "---------------------------------------------------\n"; + + for(my $i = 4; $i < MAX_ISTEPS; $i++) + { + for(my $j = 0; $j < MAX_SUBSTEPS; $j++) + { + ## print all substeps + if ( defined( $inList[$i][$j] ) ) + { + if ( $hdrflag ) + { + ::userDisplay " -- IStep $i -- \n"; + $hdrflag = 0; + } + ::userDisplay " $inList[$i][$j]\n" ; + } + } ## end for $j + + $hdrflag=1; + } ## end for $i +} + + +## +## Find istep name in inList array. +## +## @param[in] - name +## +## @return - istep #, substep #, found flag = true for success +## false for not found +## +sub find_in_inList( $ ) +{ + my ( $substepname ) = @_; + + for(my $i = 0; $i < MAX_ISTEPS; $i++) + { + for(my $j = 0; $j < MAX_SUBSTEPS; $j++) + { + if ( defined($inList[$i][$j]) && ($inList[$i][$j] eq $substepname ) ) + { + return ($i, $j, 1 ); + } + } + } + + return ( MAX_ISTEPS, MAX_SUBSTEPS, 0 ) +} + +## +## When HostBoot goes into singlestep mode, it turns on the ready bit in the +## status reg. +## +## @return nonzero if ready bit is on, else 0 +## +sub isReadyBitOn() +{ + my $result = 0; + my $readybit = 0; + + $result = getStatus( ); + $readybit = ( ( $result & 0x4000000000000000 ) >> 62 ); + + if ( $opt_debug ) { ::userDisplay "=== readybit: $readybit\n"; } + + if ( $readybit ) + { + return 1; + } + + return 0; +} + + + + +## +## Check if HostBoot has already run and shutdown. +## +## @return nonzero if it has, 0 otherwise +## +sub isShutDown() +{ + + my $flag = ::read64( $ShutDownFlag ); + my $status = ::read64( $ShutDownSts ); + + if ( $opt_debug ) + { + ::userDisplay "=== isShutDown : Shutdown Flag = $flag\n"; + ::userDisplay "=== isShutDown : Shutdown Status = $status\n"; + } + + if ( $flag ) + { + ::userDisplay "HostBoot has shut down with status $status.\n"; + return 1; + } + + return 0; +} + +## +## Write to the IstepMode reg in memory. This will not be changed to scom +## +## @param[in] - 64-bit value to write to the IstepModeReg +## +sub writeIstepModeReg( $ ) +{ + my $data = shift; + + if ( $opt_debug ) + { ::userDisplay "=== writeIstepmodeReg ", sprintf("0x%x",$data), "\n"; } + + ::write64( $IstepModeReg, $data ); + +} + + +## +## Read IStepModeReg from memory. This will not be changed to scom. +## +## @return 64-bit value read from IStepModeReg +## +sub readIstepModeReg( ) +{ + my $data = 0; + + $data = ::read64( $IstepModeReg ); + + if ( $opt_debug ) + { ::userDisplay "=== readIstepmodeReg ", sprintf("0x%x",$data), "\n"; } + + return $data; +} + +## -------------------------------------------------------------------- +## Write command reg +## +## @param[in] - HEX STRING containing the 64-bit command word +## +## @return none +## +## -------------------------------------------------------------------- +sub sendCommand( $ ) +{ + my $data = shift; + + if ( $opt_debug ) + { ::userDisplay "=== sendCommand( $data )\n"; } + + ## convert to binary before sending to writescom + my $bindata = ( hex $data ); + + ## now write the data + ::writeScom( MBOX_SCRATCH3, 8, $bindata ); + + if ( $opt_debug ) + { + ## sanity check + ::executeInstrCycles( 10); + my $readback = ::readScom( MBOX_SCRATCH3, 8 ); + ::userDisplay "=== sendCommand readback: $readback\n"; + } + +} + + +## -------------------------------------------------------------------- +## read status reg +## +## Note - mbox scratchpad regs are only 32 bits, so HostBoot will return +## status in mbox 2 (hi32 bits) and mbox 1 (lo32 bits). +## mbox 0 is reserved for continuous trace. +## +## +## +## @return binary 64-bit value +## -------------------------------------------------------------------- +sub getStatus() +{ + my $status = 0; + my $statusHi = ""; + my $statusLo = ""; + + $statusHi = ::readScom( MBOX_SCRATCH2, 8 ); + if ( $opt_debug ) { ::userDisplay "=== statusHi: $statusHi \n"; } + + $statusLo = ::readScom( MBOX_SCRATCH1, 8 ); + if ( $opt_debug ) { ::userDisplay "=== statusLo: $statusLo \n"; } + + $status = ( ( (hex $statusHi) & 0xffffffff00000000 ) + | (( (hex $statusLo) & 0xffffffff00000000 ) >> 32) + ); + + if ( $opt_debug ) + { + ::userDisplay "=== getStatus() returned ", (sprintf( "0x%lx", $status ) ), "\n"; + } + + return $status; +} + + +## +## keep trying to get status until seqnum syncs up +## +sub getSyncStatus( ) +{ + # set # of retries + my $count = $hbCount ; + my $result = 0; + my $seqnum = 0; + my $running = 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. + ::executeInstrCycles( $hbDefaultCycles ); + + + ## check to see if we need to dump trace - no-op in simics + ##::checkContTrace(); + + $result = getStatus(); + $seqnum = ( ( $result & 0x3f00000000000000 ) >> 56 ); + $running = ( ( $result & 0x8000000000000000 ) >> 63 ); + + ## @todo great place to add some debug, check running bit BEFORE + ## starting the clock (should be off), then run (relatively) small + ## number of clocks till the bit turns on. + ## If it doesn't go on, command was never received. If so, + ## come here to wait for it to go back off again. + ## if ( ( $running == 0 ) + ## && ( $seqnum == $g_SeqNum ) + if ( $seqnum == $g_SeqNum ) + { + return $result; + } + + if ( $count <= 0) + { + ::userDisplay "TIMEOUT waiting for seqnum=$g_SeqNum\n"; + return -1; + } + + $count--; + + } ## endwhile + +} + + +## +## Run an istep +## +sub runIStep( $$ ) +{ + my ( $istep, $substep) = @_; + my $byte0, my $command; + my $cmd; + my $result; + + + ## bump the seqnum + bumpSeqNum() ; + + ::userDisplay "run $istep.$substep $inList[$istep][$substep]:\n" ; + + $byte0 = 0x80 + $g_SeqNum; ## gobit + seqnum + $command = SPLESS_SINGLE_ISTEP_CMD; + $cmd = sprintf( "0x%2.2x%2.2x%2.2x%2.2x00000000", $byte0, $command, $istep, $substep ); + + sendCommand( $cmd ); + + + $result = getSyncStatus(); + + ## if result is -1 we have a timeout + if ( $result == -1 ) + { + ::userDisplay "-----------------------------------------------------------------\n"; + } + else + { + my $taskStatus = ( ( $result & 0x00ff000000000000 ) >> 48 ); + my $stsIStep = ( ( $result & 0x0000ff0000000000 ) >> 40 ); + my $stsSubstep = ( ( $result & 0x000000ff00000000 ) >> 32 ); + my $istepStatus = ( ( $result & 0x00000000ffffffff ) ); + + ::userDisplay "---------------------------------\n"; + if ( $taskStatus != 0 ) + { + ::userDisplay "Istep $stsIStep.$stsSubstep FAILED to launch, task status is $taskStatus\n" ; + } + else + { + ::userDisplay "Istep $stsIStep.$stsSubstep $inList[$istep][$substep] returned Status: ", + sprintf("0x%x",$istepStatus), + "\n" ; + if ( $istepStatus == 0xa ) + { + ::userDisplay ": not implemented yet.\n"; + } + } + ::userDisplay "------------------------------------------------------- SeqNum: $g_SeqNum\n"; + } +} + +## +## run command = "sN" +## +sub sCommand( $ ) +{ + my ( $scommand ) = @_; + + my $i = $scommand; + my $j = 0; + + # execute all the substeps in the IStep + for( $j=0; $j<MAX_SUBSTEPS; $j++ ) + { + + + if ( defined( $inList[$i][$j] ) ) + { + runIStep( $i, $j ); + } + } +} + + +## +## parse --command [command] option and execute it. +## +sub process_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) { ::userDisplay "=== s command \"$command\" \n"; } + substr( $command, 0, 1, "" ); + + if ( POSIX::isdigit($command) ) + { + # command = "sN" + if ($opt_debug) { ::userDisplay "=== single IStep: ", $command, "\n"; } + sCommand( $command ); + } + else + { + # list of substeps = "sM..N" + ( $M, $N ) = split( /\.\./, $command ); + + if ($opt_debug) { ::userDisplay "=== 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) { ::userDisplay "=== named commands : ", @ss_list, "\n"; } + + ( $istepM, $substepM, $foundit) = find_in_inList( $ss_list[0] ); + $istepN = $istepM; + $substepN = $substepM; + if ( ! $foundit ) + { + ::userDisplay "Invalid substep ", $ss_list[0], "\n" ; + return -1; + } + + + if ( $#ss_list > 0 ) + { + ( $istepN, $substepN, $foundit) = find_in_inList( $ss_list[1] ); + if ( ! $foundit ) + { + ::userDisplay "Invalid substep $ss_list[1] \n" ; + return -1; + } + } + + + for( my $x=$istepM; $x<$istepN+1; $x++ ) + { + for( my $y=$substepM; $y<$substepN+1; $y++ ) + { + runIStep( $x, $y ); + } + } + + } +} + + +## +## write to mem to set istep or normal mode, check return status +## +## Note that this only happens once at the beginning, when "splessmode" +## or "fsplessmode" is run. +## +sub setMode( $ ) +{ + my ( $cmd ) = @_; + my $count = 0; + my $expected = 0; + my $readybit = 0; + my $result = 0; + + if ( $cmd eq "spless" ) + { + writeIstepModeReg( SPLESS_MODE_SIGNATURE ); + $expected = 1; + } + elsif ( $cmd eq "fsp" ) + { + writeIstepModeReg( FSP_MODE_SIGNATURE ); + $expected = 1; + } + else + { + ::userDisplay "invalid setMode command: $cmd\n" ; + return -1; + } + + if ( $opt_debug ) + { + ## readback and display + $result = readIstepModeReg( ); + ::userDisplay "=== IstepModeReg readback: ", sprintf("0x%x", $result), "\n" ; + } + + + ## Loop, advancing clock, and wait for readybit + $count = $hbCount ; + while(1) + { + ## advance HostBoot code by a certain # of cycles, then check the + ## sequence number to see if it has changed. rinse and repeat. + ::executeInstrCycles( $hbDefaultCycles ); + + ## check to see if it's time to dump trace - no-op in simics + ::checkContTrace(); + + ## check for system crash + if ( isShutDown( ) ) + { + ::userDisplay "Cannot run HostBoot\n"; + return -1; + } + + if ( isReadyBitOn() ) + { + return 0; + } + + if ( $count <= 0 ) + { + ::userDisplay "TIMEOUT waiting for readybit, status=$result\n" ; + return -1; + } + + $count--; + } +} + + +sub resume_istep() +{ + my $byte0; + my $command; + my $cmd; + my $result; + + bumpSeqNum(); + + ::userDisplay "resume istep\n"; + + $byte0 = 0x80 + $g_SeqNum; ## gobit + seqnum + $command = SPLESS_RESUME_ISTEP_CMD; + $cmd = sprintf( "0x%2.2x%2.2x000000000000", $byte0, $command ); + sendCommand( $cmd ); + + $result = getSyncStatus(); + + ## if result is -1 we have a timeout + if ( $result == -1 ) + { + ::userDisplay "-----------------------------------------------------------------\n"; + } + else + { + my $taskStatus = ( ( $result & 0x00ff000000000000 ) >> 48 ); + + ::userDisplay "-----------------------------------------------------------------\n"; + if ( $taskStatus != 0 ) + { + # This probably means istep was not at a breakpoint. + ::userDisplay "resume istep FAILED, task status is $taskStatus\n", $taskStatus ; + } + else + { + ::userDisplay "resume istep returned success\n" ; + } + ::userDisplay "-----------------------------------------------------------------\n"; + } +} + +sub clear_trace( ) +{ + my $byte0, my $command; + my $cmd; + my $result; + + + ## bump the seqnum + bumpSeqNum(); + + $byte0 = 0x80 + $g_SeqNum; ## gobit + seqnum + $command = SPLESS_CLEAR_TRACE_CMD; + $cmd = sprintf( "0x%2.2x%2.2x%2.2x%2.2x00000000", $byte0, $command, 0, 0 ); + sendCommand( $cmd ); + + $result = getSyncStatus(); + + ## if result is -1 we have a timeout + if ( $result == -1 ) + { + ::userDisplay "-----------------------------------------------------------------\n"; + } + else + { + my $taskStatus = ( ( $result & 0x00ff000000000000 ) >> 48 ); + my $stsIStep = ( ( $result & 0x0000ff0000000000 ) >> 40 ); + my $stsSubstep = ( ( $result & 0x000000ff00000000 ) >> 32 ); + my $istepStatus = ( ( $result & 0x00000000ffffffff ) ); + + ::userDisplay "-----------------------------------------------------------------\n"; + if ( $taskStatus != 0 ) + { + ::userDisplay "Clear Trace FAILED, task status is taskStatus\n" ; + } + else + { + ::userDisplay "Clear Trace returned Status: $istepStatus\n" ; + } + ::userDisplay "-----------------------------------------------------------------\n"; + } +} + + +__END__ + diff --git a/src/build/debug/Hostboot/_DebugFramework.pm b/src/build/debug/Hostboot/_DebugFramework.pm index ae8ef6573..6b7ee622a 100755 --- a/src/build/debug/Hostboot/_DebugFramework.pm +++ b/src/build/debug/Hostboot/_DebugFramework.pm @@ -6,7 +6,7 @@ # # IBM CONFIDENTIAL # -# COPYRIGHT International Business Machines Corp. 2011 +# COPYRIGHT International Business Machines Corp. 2011 - 2012 # # p1 # @@ -20,8 +20,7 @@ # # Origin: 30 # -# IBM_PROLOG_END - +# IBM_PROLOG_END_TAG # _DebugFramework.pm # # This module is a set of utility functions for the debug framework, which @@ -49,7 +48,8 @@ our @EXPORT = ( 'callToolModule', 'callToolModuleHelp', 'callToolModuleHelpInfo' 'findModuleByAddress', 'listModules', 'littleendian', 'read64', 'read32', 'read16', 'read8', 'readStr', - 'write64', 'write32', 'write16', 'write8' + 'write64', 'write32', 'write16', 'write8', + 'getIstepList' ); our ($parsedSymbolFile, %symbolAddress, %symbolTOC, @@ -586,4 +586,28 @@ sub write8 my $result = ::writeData($addr, 1, $value); } +# @sub getIstepList +# +# get an array of all the supported istep names from the +# "isteplist.csv" file +# +# @return array of lines in the file +# +sub getIstepList +{ + my $isteplistFile = ::getImgPath(); + + $isteplistFile = $isteplistFile . "isteplist.csv"; + + open(FILE, "< $isteplistFile") + or die "Cannot open isteplist file $isteplistFile"; + + my @isteplist = <FILE>; + + close FILE or die "cannot close isteplist file"; + + + return @isteplist; +} + __END__ diff --git a/src/build/debug/simics-debug-framework.pl b/src/build/debug/simics-debug-framework.pl index 90a7822a9..6c23b1efd 100755 --- a/src/build/debug/simics-debug-framework.pl +++ b/src/build/debug/simics-debug-framework.pl @@ -6,7 +6,7 @@ # # IBM CONFIDENTIAL # -# COPYRIGHT International Business Machines Corp. 2011 +# COPYRIGHT International Business Machines Corp. 2011 - 2012 # # p1 # @@ -20,8 +20,7 @@ # # Origin: 30 # -# IBM_PROLOG_END - +# IBM_PROLOG_END_TAG # @file simics-debug-framework.pl # @brief Implementation of the common debug framework for running in simics. # @@ -157,6 +156,131 @@ sub getIsTest } +# @sub getEnv +# +# Return the environment that we are running in, simics or vpo +# +sub getEnv +{ + return "simics"; +} + +# +# @sub translateAddr +# Do scom -> "phys_mem.read" address translation here. +# The xscom address looks like this: +# // Layout of XSCOM address parts +# union +# { +# uint64_t mMmioAddress; // mMmio address +# struct +# { +# uint64_t mReserved1:18; // Not currently used (0:17) +# uint64_t mBaseAddress:5; // Base address (18:22) +# uint64_t mNodeId:3; // Node where target resides (23:25) +# uint64_t mChipId:3; // Targeted chip ID (26:28) +# uint64_t mSComAddrHi:27; // PCB Address High (29:55) +# uint64_t mCacheLine:1; // Cached line (56) +# uint64_t mSComAddrLo:4; // PCB Address low (57:60) +# uint64_t mAlign:3; // Align (61:63) +# } mAddressParts; +# +# @param[in] - 64-bit scom address +# +# @return = address to send to python to do mm.read +# +# @note: "host_xscom_device_mm.read/write " doesn't seem to work with this +# translated address, use "phys_mem.read/write " (in python) instead. +# +sub translateAddr +{ + my $addr = shift; + my $simicsaddr = 0; + + my $mSComAddrHi = ( $addr >> 4 ); + my $mSComAddrLo = ( $addr & 0x000000000000000f ) ; + + $simicsaddr = ( 0x0000300000000000 ## Base addr + | (($mSComAddrHi & 0x0000000007ffffff) << 8 ) ## 27 bits, shift 8 + | (($mSComAddrLo & 0x000000000000000f) << 3 ) ## 4 bits, shift 3 + ); + + return $simicsaddr; +} + + +# @sub readScom +# @brief Send a 'read-scom' type message to Python. +# +# @param[in] scom address to read +# @param[in] data size IN BYTES +# +# @return hex string containing data read +# +# @todo: handle littleendian +# +sub readScom +{ + my $addr = shift; + my $size = shift; + + my $simicsaddr = translateAddr( $addr); + + ## debug + ## ::userDisplay "--- readScom: ", (sprintf("0x%x-->0x%x, 0x%x",$addr,$simicsaddr,$size)), "\n"; + + sendIPCMsg("read-scom", "$simicsaddr,$size"); + + my ($type, $data) = recvIPCMsg(); + + return $data; +} + +# @sub writeScom +# @brief Send a 'write-scom' type message to Python. +# +# @param[in] - xscom address +# @param[in] - data size IN BYTES +# @param[in] - binary data value. Scom value is aways assumed to be 64bits +# +# @return none +# +# @todo: handle littleendian +# +sub writeScom +{ + my $addr = shift; + my $size = shift; + my $value = shift; + + my $simicsaddr = translateAddr( $addr); + + ## debug + ## ::userDisplay "--- writeScom: ", (sprintf("0x%x-->0x%x, 0x%x, 0x%x",$addr,$simicsaddr,$size,$value)), "\n"; + + my $ipctype = "write-scom"; + my $ipcdata = "$simicsaddr,$size,$value"; + + + sendIPCMsg( $ipctype, $ipcdata ); + + ## $$ debug + ## $$my $debugstr = "[ \"$ipctype\", \"".unpack("H*",$ipcdata)."\" ]\n"; + ## $$::userDisplay "--- $debugstr\n"; + + return; +} + + +## +## Dummy module to match continuous trace call in VPO +## +sub checkContTrace() +{ + +} + + # Get tool name. sendIPCMsg("get-tool",""); my ($unused, $tool) = recvIPCMsg(); diff --git a/src/build/debug/simics-debug-framework.py b/src/build/debug/simics-debug-framework.py index 39a186666..edf5f0bdd 100755 --- a/src/build/debug/simics-debug-framework.py +++ b/src/build/debug/simics-debug-framework.py @@ -6,7 +6,7 @@ # # IBM CONFIDENTIAL # -# COPYRIGHT International Business Machines Corp. 2011 +# COPYRIGHT International Business Machines Corp. 2011 - 2012 # # p1 # @@ -20,8 +20,7 @@ # # Origin: 30 # -# IBM_PROLOG_END - +# IBM_PROLOG_END_TAG # @file simics-debug-framework.py # @brief Simics/Python implementation of the common debug framework. # @@ -72,9 +71,12 @@ class DebugFrameworkIPCMessage: def loads(self,string): pattern = re.compile("\[ \"([^\"]+)\", \"([0-9a-f]*)\" ]") match = pattern.search(string) - - self.msgtype = match.group(1) - self.msg = match.group(2).decode("hex") + if match is None: + print "error: empty message >%s< received from perl"%(string) + print " Check for print's in your perl script!!!" + else: + self.msgtype = match.group(1) + self.msg = match.group(2).decode("hex") # @class DebugFrameworkProcess # @brief Provides a wrapper to the 'subprocess' interface and IPC bridge. @@ -188,6 +190,36 @@ class DebugFrameworkProcess: def get_img_path(self,data): self.sendMsg("data-response", self.imgPath) + # Read data from xscom address. + # This message has data of the format "0dADDRESS,0dSIZE". + def read_xscom(self,data): + pattern = re.compile("([0-9]+),([0-9]+)") + match = pattern.search(data) + + addr = int(match.group(1)) + size = int(match.group(2)) + + ## read the register using xscom reg addresses + runStr = "phys_mem.read 0x%x 0x%x"%(addr, size) + ( result, out ) = quiet_run_command( runStr, output_modes.regular ) + ## DEBUG print ">> %s: "%(runStr) + "0x%16.16x"%(result) + " : " + out + self.sendMsg("data-response", "%16.16x"%(result) ) + + + # Write data to xscom address.. + # This message has data of the format "0dADDR,0dSIZE,hDATA". + def write_xscom(self,data): + pattern = re.compile("([0-9]+),([0-9]+),([0-9]+)") + match = pattern.search(data) + + addr = int(match.group(1)) + size = int(match.group(2)) + data = int(match.group(3) ) + + runStr = "phys_mem.write 0x%x 0x%x 0x%x"%(addr, data, size) + ( result, out ) = quiet_run_command( runStr, output_modes.regular ) + ## DEBUG print ">> %s : "%(runStr) + " 0x%16.16x"%(result) + " : " + out + # @fn run_hb_debug_framework # @brief Wrapper function to execute a tool module. # @@ -213,6 +245,8 @@ def run_hb_debug_framework(tool = "Printk", toolOpts = "", "get-tool" : DebugFrameworkProcess.get_tool, "get-tool-options" : DebugFrameworkProcess.get_tool_options, "get-img-path" : DebugFrameworkProcess.get_img_path, + "write-scom" : DebugFrameworkProcess.write_xscom, + "read-scom" : DebugFrameworkProcess.read_xscom, "exit" : DebugFrameworkProcess.endProcess, } operations[msg[0]](fp,msg[1]) @@ -266,9 +300,9 @@ def register_hb_debug_framework_tools(): # Return a number/address built from the input list elements. Each element -# in the input is a string representation of a byte-sized hex number, for +# in the input is a string representation of a byte-sized hex number, for # example '0x2b' or '0x0' or '0xa'. This does no endian conversion, thus -# the input needs to be big endian. The length of the input list can be +# the input needs to be big endian. The length of the input list can be # any size, usually 2, 4, or 8. def hexDumpToNumber(hexlist): strNumber="" @@ -284,7 +318,7 @@ def hexDumpToNumber(hexlist): # Read simics memory and return a list of strings such as ['0x0','0x2b','0x8'] # representing the data read from simics. The list returned may be handed -# to hexDumpToNumber() to turn the list into a number. +# to hexDumpToNumber() to turn the list into a number. def dumpSimicsMemory(address,bytecount): hexlist = map(hex,conf.phys_mem.memory[[address,address+bytecount-1]]) return hexlist @@ -325,7 +359,7 @@ def writeLongLong(address,n): writeSimicsMemory(address,intToList(n,8)) -# MAGIC_INSTRUCTION hap handler +# MAGIC_INSTRUCTION hap handler # arg contains the integer parameter n passed to MAGIC_INSTRUCTION(n) # See src/include/arch/ppc.H for the definitions of the magic args. # Hostboot magic args should range 7000..7999. @@ -333,15 +367,15 @@ def magic_instruction_callback(user_arg, cpu, arg): if arg == 7006: # MAGIC_SHUTDOWN # KernelMisc::shutdown() print "KernelMisc::shutdown() called." - # Could break/stop/pause the simics run, but presently + # Could break/stop/pause the simics run, but presently # shutdown() is called four times. --Monte Jan 2012 # SIM_break_simulation( "Shutdown. Simulation stopped." ) if arg == 7007: # MAGIC_BREAK - # Stop the simulation, much like a hard-coded breakpoint + # Stop the simulation, much like a hard-coded breakpoint SIM_break_simulation( "Simulation stopped. (hap 7007)" ) - if arg == 7055: # MAGIC_CONTINUOUS_TRACE + if arg == 7055: # MAGIC_CONTINUOUS_TRACE # Set execution environment flag to 0 writeLongLong(contTraceTrigInfo+32,0) # Continuous trace. @@ -370,10 +404,10 @@ def magic_instruction_callback(user_arg, cpu, arg): # Run fsp-trace on tracBINARY file (implied), append output to tracMERG os.system( "fsp-trace ./ -s hbotStringFile >>tracMERG 2>/dev/null" ) -# Continuous trace: Open the symbols and find the address for +# Continuous trace: Open the symbols and find the address for # "g_tracBinaryInfo" Convert to a number and save in tracBinaryInfoAddr # The layout of g_tracBinaryInfo is a 64-bit pointer to the mixed buffer -# followed by a 64-bit count of bytes used in the buffer. See +# followed by a 64-bit count of bytes used in the buffer. See # src/usr/trace/trace.C and mixed_trace_info_t. for line in open('hbicore.syms'): if "g_tracBinaryInfo" in line: diff --git a/src/build/debug/vpo-debug-framework.pl b/src/build/debug/vpo-debug-framework.pl index 057e847b1..12cee677c 100755 --- a/src/build/debug/vpo-debug-framework.pl +++ b/src/build/debug/vpo-debug-framework.pl @@ -20,7 +20,7 @@ # # Origin: 30 # -# IBM_PROLOG_END +# IBM_PROLOG_END_TAG # @file vpo-debug-framework.pl # @brief Implementation of the common debug framework for running in vpo. # @@ -69,6 +69,7 @@ my %optionInfo = ( #-------------------------------------------------------------------------------- my $name = "vpo-debug-framework.pl"; my $self = ($0 =~ m/$name/); #flag showing whether script invoked using a different name; i.e symlink +my $callmodule = $0; my $tool = ""; my $testImage = 0; my $outPath = ""; @@ -96,6 +97,7 @@ if (defined ($vbuToolDir)) } my $imgPath = ""; + my $hbDir = $ENV{'HB_IMGDIR'}; if (defined ($hbDir)) { @@ -105,6 +107,16 @@ if (defined ($hbDir)) } } +## we need hbToolsDir for checkContTrace() (vpo only) +my $pgmDir = `dirname $0`; +chomp( $pgmDir ); +my $hbToolsDir = $ENV{'HB_TOOLS'}; +if ( ! defined( $hbToolsDir) || ( $hbToolsDir eq "" ) ) +{ + $hbToolsDir = $pgmDir; ## Set to tool directory +} + + Getopt::Long::Configure ("bundling"); if ($self) @@ -125,7 +137,7 @@ if ($self) "s=i" => \&processEcmdOpts, "p=i" => \&processEcmdOpts, "c=i" => \&processEcmdOpts) || pod2usage(-verbose => 0); - + pod2usage(-verbose => 1) if ($cfgHelp && $self); pod2usage(-verbose => 2) if ($cfgMan && $self); pod2usage(-verbose => 0) if (($tool eq "") && $self); @@ -200,7 +212,7 @@ callToolModule($tool); if (!$nosavestates) { restoreThreadStates(); -} +} if (!$mute) { @@ -270,7 +282,9 @@ sub flushL2 if (0 == $l2Flushed) { #stop instructions - stopInstructions("all"); + ## @todo problems with the model, just use thread 0 for now + ## $$ stopInstructions("all"); + stopInstructions("0"); my $command = "$vbuToolDir/proc_l2_flush_wrap.x86 @ecmdOpt $flag"; die "ERROR: cannot flush L2" if (system("$command") != 0); @@ -404,7 +418,7 @@ sub stopInstructions if ($debug) { - print "$command\n"; + print "--- stopInstructions: run $command\n"; } die "ERROR: cannot stop instructions" if (system("$command") != 0); @@ -420,7 +434,7 @@ sub startInstructions if ($debug) { - print "$command\n"; + print "--- startInstructions: run $command\n"; } if (system("$command") != 0) @@ -432,7 +446,7 @@ sub startInstructions else { if ($debug) - { + { print "Cannot start instructions since Hostboot has shutdown"; } } @@ -449,6 +463,11 @@ sub queryThreadState my $thread = shift; my $command = "$vbuToolDir/proc_thread_control_wrap.x86 @ecmdOpt -query -t$thread"; + if ($debug) + { + print STDERR "--- queryThreadState: run $command\n"; + } + my $result = `$command`; if ($debug) @@ -539,12 +558,26 @@ sub executeInstrCycles } #start instructions - startInstructions("all"); + ## @todo problems with the model - use just thread 0 for now + ## $$ startInstructions("all"); + startInstructions("0"); # run clock cycles my $cycles = shift; - $cycles = $cycles * 100; #increase cycles since VBU takes longer + + ## for Istep.pm, the number of cycles should be approximately + ## the same between vpo and simics. + ## callFunc needs a multiplier of 100. + ## Add tweaks for any other module here. + if ( !($callmodule =~ m/Istep/) ) + { + $cycles = $cycles * 100; #increase cycles since VBU takes longer + } my $command = "simclock $cycles $flag"; + if ($debug) + { + print "--- executeInstrCycles: run $command\n"; + } my $noshow = shift; if (!$noshow) { @@ -697,6 +730,162 @@ sub displayToolModuleHelp } } + +# @sub getEnv +# +# Return the environment that we are running in, simics or vpo +# +sub getEnv +{ + + return "vpo"; +} + +# @sub translateAddr +# +# @param[in] - 64-bit scom address +# +# @return = GET/STK FAC string to apply to VPO +sub translateAddr +{ + my $addr = shift; + + my $vpoaddr = ""; + + if ( $addr == 0x00050038 ) + { + ## 50038 is mbox scratch 0 xscom addr + $vpoaddr = "GMB2E0"; + } + elsif ( $addr == 0x00050039 ) + { + ## 50039 is mbox scratch 1 xscom addr + $vpoaddr = "GMB2E4"; + } + elsif ( $addr == 0x0005003a ) + { + ## 5003a is mbox scratch 2 xscom addr + $vpoaddr = "GMB2E8"; + } + elsif ( $addr == 0x0005003b ) + { + ## 5003b is mbox scratch 3 xscom addr + $vpoaddr = "GMB2EC"; + } + else + { + die "invalid mailbox reg: $addr\n"; + } + + return $vpoaddr; +} + + +# @sub readScom +# @brief Read a scom address in VPO +# Scom size is always 64-bit +# +# @param[in] scom address to read +# @param[in] data size IN BYTES - currently ignored, assumed to be 8 +# +# @return hex string containing data read +# +# @todo: handle littleendian +# +sub readScom +{ + my $addr = shift; + my $size = shift; + + my $vpoaddr = ::translateAddr( $addr ); + + my $cmd = "simGETFAC " . + "B0.C0.S0.P0.E8.TPC.FSI.FSI_MAILBOX.FSXCOMP." . + "FSXLOG.LBUS_MAILBOX.Q_$vpoaddr.NLC.L2 32"; + + my $result = `$cmd`; + + if ( $? ) { die "$cmd failed with $? : $!"; } + + $result =~ s/.*\n0xr(.*)\n.*/$1/g; + $result =~ s/\n//g; + + ## debug + ## ::userDisplay "--- readScom: ", + ## (sprintf("0x%x-->%s, 0x%x : %s", $addr,$vpoaddr,$size,$result)), "\n"; + + ## comes in as a 32-bit #, need to shift 32 to match simics + return ( "0x" . $result . "00000000" ); +} + +# @sub writeScom +# @brief Write a scom address in VPO. +# +# @param[in] - scom address +# @param[in] - data size IN BYTES - ignored, assumed to be 8 +# @param[in] - binary data value. Scom value is aways assumed to be 64bits +# +# @return none +# +# @todo: handle littleendian +# +sub writeScom +{ + my $addr = shift; + my $size = shift; + my $value = shift; + + my $cmd = ""; + + my $vpoaddr = ::translateAddr( $addr ); + + ## vpo takes a 32 bit value in the lower 32 bits + my $value32 = ( ( $value >> 32 ) & 0x00000000ffffffff ); + my $valuestr = sprintf( "0x%x", $value32 ); + + ## debug + ## ::userDisplay "--- writeScom: ", + ## (sprintf("0x%x-->%s, 0x%x, %s",$addr,$vpoaddr,$size,$valuestr)), "\n"; + + ## now go ahead and write the real value + $cmd = "simSTKFAC " . + "B0.C0.S0.P0.E8.TPC.FSI.FSI_MAILBOX.FSXCOMP." . + "FSXLOG.LBUS_MAILBOX.Q_$vpoaddr.NLC.L2 $valuestr 32 -quiet"; + + ( system( $cmd ) == 0 ) + or die "$cmd failed, $? : $! \n"; + + return; +} + +## +## Special case: only used in VPO +## Check the continuous trace Scom reg to see if we need to dump +## trace. +## This has to be executed as an external procedure so that it goes to the +## proper output file. +## +sub checkContTrace() +{ + my $SCRATCH_MBOX0 = 0x00050038; + my $contTrace = ""; + + $contTrace = ::readScom( $SCRATCH_MBOX0, 8 ); + if ( ( hex $contTrace ) != 0 ) + { + ## activate continuous trace + system ("$hbToolsDir/hb-ContTrace --mute > /dev/null" ); + system ("cat hb-ContTrace.output >> tracMERG"); + + ## ContTrace might leave instructions stopped, turn them + ## back on here to make sure. + ## @todo problems with the model, use just thread 0 for now + ::startInstructions("0"); + } + +} + + __END__ =head1 NAME diff --git a/src/build/simics/hb-simdebug.py b/src/build/simics/hb-simdebug.py index e0c9a0a38..9b779dd67 100755 --- a/src/build/simics/hb-simdebug.py +++ b/src/build/simics/hb-simdebug.py @@ -5,7 +5,7 @@ # # IBM CONFIDENTIAL # -# COPYRIGHT International Business Machines Corp. 2011 +# COPYRIGHT International Business Machines Corp. 2011 - 2012 # # p1 # @@ -19,8 +19,7 @@ # # Origin: 30 # -# IBM_PROLOG_END - +# IBM_PROLOG_END_TAG import os,sys import conf import configuration @@ -54,524 +53,12 @@ def dumpL3(): return - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -# 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 and the SPless user console." - ##print " normalmode - enable IStep Mode and the FSP interface. " - print " splessmode - enable IStep Mode and the SPless user console." - print " fspmode - enable IStep Mode and the FSP interface. " - print " list - list all named isteps" - print " sN - execute IStep N" - print " sN..M - execute IStep N through M" - print " <name1>..<name2> - execute named isteps name1 through name2" - print " debug - enable debugging messages" - print " resume - Resume istep execution from break point" - return None - -## declare GLOBAL g_SeqNum var, & a routine to manipulate it. -## TODO: make this into a class, etc. to do it The Python Way. -##g_SeqNum = 0 -g_SeqNum = random.randint(0, 63) -print "g_SeqNum = %d"%(g_SeqNum) -def bump_g_SeqNum() : - global g_SeqNum - g_SeqNum = ( (g_SeqNum +1) & 0x3f) - return g_SeqNum - -## clock a certain amount of CPU cycles so the IStep will run (this will be -## different for each simulation environment) and then return. -## simics clock is a somewhat arbitrary value, may need to be adjusted. -## -## Handle following environments: -## 1. [x] simics value = 100,000 (from Patrick) -## 2. VPO value = ??? (don't know yet) -## 3. hardware value = ??? ( ditto) -## -def runClocks() : - - SIM_continue( 250000 ) - return None - -## -## send a command to the SPLess Command register (scratchpad reg 1) -## cmd is passed in as a 64-bit ppc formatted hex string, i.e. -## "0x80000000_00000000" -## -## Handle following environments: -## 1. [x] simics -## 2. VPO -## 3. hardware -def sendCommand( cmd ): - global g_IStep_DEBUG - ## CommandStr = "cpu0_0_0_1->scratch=%s"%(cmd) - CommandStr = "phys_mem.write 0x%8.8x %s 8"%(g_SPLess_Command_Reg, cmd ) - - ## send command to Hostboot - if ( g_IStep_DEBUG ) : - print CommandStr - (result, out) = quiet_run_command(CommandStr, output_modes.regular ) - - if ( g_IStep_DEBUG ) : - print "sendCommand( \"%s\" ) returns : "%(cmd) + "0x%x"%(result) + " : " + out - - return result - -def printStsHdr( status ): - - runningbit = ( ( status & 0x8000000000000000 ) >> 63 ) - readybit = ( ( status & 0x4000000000000000 ) >> 62 ) - seqnum = ( ( status & 0x3f00000000000000 ) >> 56 ) - taskStatus = ( ( status & 0x00ff000000000000 ) >> 48 ) - - print "runningbit = 0x%x, readybit=0x%x, seqnum=0x%x, taskStatus=0x%x"%(runningbit, readybit, seqnum, taskStatus ) - return None - -## get status from the SPLess Status Register (scratchpad reg 2) -## returns a 64-bit int. -## -## Handle following environments: -## 1. [x] simics -## 2. VPO -## 3. hardware -## -def getStatus(): - global g_IStep_DEBUG - - ## StatusStr = "cpu0_0_0_2->scratch" - 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 ) : - print ">> getStatus(): " + "0x%x"%(result) + " : " + out - ## printStsHdr(result) - - return result - - -## check for status, waiting for the readybit and the sent g_SeqNum. -## default is to check the readybit, in rare cases we want to skip this. -def getSyncStatus( ) : - # set # of retries - ## @todo revisit - count = 1000 - - ## get response. sendCmd() should have bumped g_SeqNum, so we will sit - ## here for a reasonable amount of time waiting for the correct sequence - ## number to come back. - while True : - - ## advance HostBoot code by a certain # of cycles, then check the - ## running bit and sequence number to see if they have changed. - ## IstepDisp will set running bit ASAP and then turn it off when - ## the command is complete. - runClocks() - - ## print a dot (with no carriage return) so that the user knows that - ## it's still doing something - # print "." , - - result = getStatus() - - runningbit = ( ( result & 0x8000000000000000 ) >> 63 ) - seqnum = ( ( result & 0x3f00000000000000 ) >> 56 ) - - if ( ( runningbit == 0 ) - and ( seqnum == g_SeqNum ) ) : - # print # print a final carriage return - return result - - if ( count <= 0 ): - print # print a final carriage return - print "TIMEOUT waiting for seqnum=%d"%( g_SeqNum ) - return -1 - count -= 1 - -## write to istepmode reg to set istep or fsp mode, check return status -def setMode( cmd ) : - 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" - - SPlessModeStr = "phys_mem.write 0x%8.8x 0x4057b007_4057b007 8"%(g_SPLess_IStepMode_Reg) - FSPModeStr = "phys_mem.write 0x%8.8x 0x700b7504_700b7504 8"%(g_SPLess_IStepMode_Reg) - - ## @todo revisit - count = 1000 - - if ( cmd == "spless" ) : - (result, out) = quiet_run_command( SPlessModeStr ) - expected = 1 - elif ( cmd == "fsp" ) : - (result, out) = quiet_run_command( FSPModeStr ) - expected = 1 - else : - print "invalid setMode command: %s"%(cmd) - return None - - print "setMode: %s :"%( cmd ) - - ## Loop, advancing clock, and wait for readybit - while True : - runClocks() - - result = getStatus() - readybit = ( ( result & 0x4000000000000000 ) >> 62 ) - if ( g_IStep_DEBUG ) : - print "Setting %s mode, readybit=%d..."%( cmd, readybit ) - if ( readybit == expected ) : - print "Set %s Mode success."%(cmd) - return 0 - - if ( count <= 0 ): - print "TIMEOUT waiting for readybit, status=0x%x"%( result ) - return -1 - count -= 1 - - -## read in file with csv istep list and store in inList -def get_istep_list( inList ): - istep_file = open('./isteplist.csv') - for line in istep_file.readlines(): - ( istep, substep, name) = line.split(',') - i = int(istep) - j = int(substep) - - ## print ":: %d %d %s"%(i, j, name) - if ( name.strip() != "" ): - inList[i][j] = name.strip() - - istep_file.close() - - return None - - -def print_istep_list( inList ): - hdrflag = 1 - print "IStep\tSubStep\tName" - print "---------------------------------------------------" - for i in range(0,len(inList)) : - for j in range( 0, len(inList[i])) : - # print "%d %d"%(i,j) - if ( inList[i][j] != None ) : - if ( hdrflag ) : - print "-- %d"%(i) - hdrflag = 0 - ## print "%d\t%d\t%s"%( i,j, inList[i][j] ) - print "%s"%( inList[i][j] ) - - hdrflag = 1 - - - print " " - return None - - -def runIStep( istep, substep, inList ): - global g_SeqNum - - bump_g_SeqNum() - - print "run %d.%d %s :"%( istep, substep, inList[istep][substep] ) - ## print " istep # = 0x%x / substep # = 0x%x :"%(istep, substep) - - byte0 = 0x80 + g_SeqNum ## gobit + seqnum - command = 0x00 - cmd = "0x%2.2x%2.2x%2.2x%2.2x_00000000"%(byte0, command, istep, substep ); - sendCommand( cmd ) - - result = getSyncStatus() - - ## getSyncStatus waits for seqNum in status to be what last cmd sent - - ## if result is -1 we have a timeout - if ( result == -1 ) : - print "-----------------------------------------------------------------" - else : - taskStatus = ( ( result & 0x00ff000000000000 ) >> 48 ) - stsIStep = ( ( result & 0x0000ff0000000000 ) >> 40 ) - stsSubstep = ( ( result & 0x000000ff00000000 ) >> 32 ) - istepStatus = ( ( result & 0x00000000ffffffff ) ) - - - print "-----------------------------------------------------------------" - - ## printStsHdr(result) - ## print "Istep 0x%x / Substep 0x%x Status: 0x%x"%( stsIStep, stsSubstep, istepStatus ) - if ( taskStatus != 0 ) : - # check for break point - if ( taskStatus == 11 ) : - print "At breakpoint 0x%x"%( istepStatus ) - else : - print "Istep %d.%d FAILED to launch, task status is %d"%( stsIStep, stsSubstep, taskStatus ) - else: - print "Istep %d.%d returned Status: 0x%x"%( stsIStep, stsSubstep, istepStatus ) - if ( istepStatus == 0xa ) : - print " (not supported yet)" - print "-------------------------------------------------------------- %d"%(g_SeqNum) - - return - -def resume_istep(): - - bump_g_SeqNum() - - print "resume from breakpoint" - - byte0 = 0x80 + g_SeqNum ## gobit + seqnum - command = 0x01 - cmd = "0x%2.2x%2.2x_000000000000"%(byte0, command) - sendCommand( cmd ) - - while True : - result = getSyncStatus() - - ## if result is -1 we have a timeout - if ( result == -1 ) : - break; - else : - taskStatus = ( ( result & 0x00ff000000000000 ) >> 48 ) - stsIStep = ( ( result & 0x0000ff0000000000 ) >> 40 ) - stsSubstep = ( ( result & 0x000000ff00000000 ) >> 32 ) - istepStatus = ( ( result & 0x00000000ffffffff ) ) - running = ( ( result & 0x8000000000000000 ) >> 63 ) - readybit = ( ( result & 0x4000000000000000 ) >> 62 ) - print "-----------------------------------------------------------------" - - ## At this point the status is: - ## 1) hostboot code was not at a breakpoint - resume ignored (result == 12) - ## 2) hostboot resumed from breakpoint, but has not reached the end of - ## the istep. (running flag on, result is 0) - ## 3) hostboot resumed, but is at a new breakpoint - ## 4) hostboot resumed and is at the end of the istep - ## (running flag off, result is rc from istep - - - if ( taskStatus != 0 ) : - if (taskStatus == 11 ) : - # at new breakpoint bail-out - print " At breakpoint 0x%x."%( istepStatus ) - break - elif ( taskStatus == 12 ) : - print "resume Istep ignored. Not at breakpoint" - break - else : - # all other errors must have come from the result of the istep - print "Istep %d.%d returned Status: 0x%x"%( stsIStep, stsSubstep, istepStatus ) - break - else: - if(running == 0) : - print "Istep %d.%d returned Status: 0x%x"%( stsIStep, stsSubstep, istepStatus ) - break - elif (readybit == 0) : - # not in istep mode - leave (mainly for unit testing) - print "Istep resume was successful" - break - - # still waiting for istep to complete - # continue - print "-----------------------------------------------------------------" - - - return - - - -## run command = "sN" -def sCommand( inList, scommand ) : - - i = int(scommand) - - # execute all the substeps in the IStep - for j in range( 0, len(inList[i]) ) : - ## print "-----------------" - ## print "$$$$ run IStep %d %d ..."%(i, j) - ##print "-----------------" - if ( inList[i][j] != None ) : - runIStep( i, j, inList ) - return - - -def find_in_inList( inList, substepname) : - for i in range(0,len(inList)) : - for j in range( 0, len(inList[i])) : - #print "%d %d"%(i,j) - if ( inList[i][j] == substepname ) : - #print "%s %d %d"%( inList[i][j], i, j ) - return (i,j, True ) - break; - - return ( len(inList), len(inList[i]), False ) - -## --------------------------------------------------------------------------- -## High Level Routine for ISteps. -## --------------------------------------------------------------------------- -## possible commands: -## list -## splessmode -## fspmode -## sN -## sN..M -## <substepname1>..<substepname2> -## resume - -## declare GLOBAL g_IStep_DEBUG & SPLess memory mapped regs -g_IStep_DEBUG = 0 -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; - - ## start with empty inList. Put some dummy isteps in istep4 for debug. - n = 25 ## size of inlist array - - inList = [[None]*n for x in xrange(n)] ## init to nothing - - ## bump seqnum - bump_g_SeqNum() - - ## print "run istepHB...." - - if ( str_arg1 == "debug" ) : - print "enable istep debug - restart simics to reset" - g_IStep_DEBUG = 1 - return - - if ( str_arg1 == "istepmode" ): - # print "Set Istep Mode" - print "istepmode no longer used - use splessmode, or fspmode" - return - - if ( str_arg1 == "splessmode" ): - # print "Start Istep on SPless console" - setMode( "spless" ) - return - - if ( str_arg1 == "fspmode" ): - # print "Start Istep on FSP " - setMode( "fsp" ) - return - - ## get readybit to see if we are running in IStep Mode. - StatusReg = getStatus() - readybit = ( ( StatusReg & 0x4000000000000000 ) >> 62 ) - if ( not readybit ): - print "ERROR: HostBoot Status reg is 0x%16.16x"%( StatusReg ) - print " Ready bit is not on, did you remember to run hb-istep spless ??" - print " " - hb_istep_usage() - return None - - if ( str_arg1 == "resume" ): ## resume from break point - resume_istep() - return None - - ## get the list of isteps from HostBoot... - # print"get istep list" - get_istep_list( inList ) - - if ( str_arg1 == "list" ): ## dump command list - print_istep_list( inList ) - return - - - ## check to see if we have an 's' command (string starts with 's' and a number) - if ( re.match("^s+[0-9].*", str_arg1 ) ): - ## run "s" command - # print "s command" - scommand = str_arg1.lstrip('s') - - if scommand.isdigit(): - # command = "sN" - # print "single IStep: " + scommand - sCommand( inList, scommand ) - else: - # list of substeps = "sM..N" - (M, N) = scommand.split('..') - # print "multiple ISteps: " + M + "-" + N - for x in range( (int(M,16)), (int(N,16)+1) ) : - sCommand( inList, x ) - return - else: - ## substep name .. substep name - ## print "named istep(s) : " + str_arg1 - ## (ss_nameM, ss_nameN) = str_arg1.split("..") - ss_list = str_arg1.split("..") - - (istepM, substepM, foundit) = find_in_inList( inList, ss_list[0] ) - istepN = istepM - substepN = substepM - if ( not foundit ) : - print( "Invalid substep %s"%(ss_list[0] ) ) - return - - if ( len(ss_list) > 1 ) : - (istepN, substepN, foundit) = find_in_inList( inList, ss_list[1] ) - if ( not foundit ) : - print( "Invalid substep %s"%(ss_list[1] ) ) - return - - ## @todo - this does not work correctly across istep boundaries - for x in range( istepM, istepN+1 ) : - for y in range( substepM, substepN+1 ) : - if ( inList[x][y] != None ) : - runIStep( x, y, inList ) - return - - #=============================================================================== # HOSTBOOT Commands #=============================================================================== default_syms = "hbicore.syms" default_stringFile = "hbotStringFile" - #------------------------------------------------ #------------------------------------------------ new_command("hb-trace", @@ -641,44 +128,35 @@ Examples: \n hb-dump \n """) + #------------------------------------------------ -# implement isteps +# Disable for now, need to pass in lots of options #------------------------------------------------ -def hb_istep(str_arg1): - - syms = default_syms - - if ( str_arg1 == None): - hb_istep_usage() - else: - ## print "args=%s" % str(str_arg1) - istepHB( syms, str_arg1 ) - - return None - new_command("hb-istep", - hb_istep, - [ arg(str_t, "syms", "?", None), - # arg(flag_t,"-s", "?", None), - ], - type = ["hostboot-commands"], - see_also = [ ], - short = "Run IStep commands using the SPLess HostBoot interface", - doc = """ + lambda istep: run_hb_debug_framework("Istep", istep, + outputFile = "hb-istep.output"), + [ arg( str_t, "istep", "?", "") ], + type = ["hostboot-commands"], + see_also = [ ], + short = "Run IStep commands", + doc = """ Parameters: \n - + Defaults: \n Examples: \n - hb-istep \n - hb-istep -s4 \n - hb-istep -s4..N - hb-istep -4.1 - hb-istep -4.1..4.3 \n - hb-istep poweron \n - hb-istep poweron..clock_frequency_set /n - """) - + hb-istep \n + hb-istep list \n + hb-istep splessmode \n + hb-istep fspmode \n + hb-istep clear-trace \n + hb-istep resume \n + hb-istep s4 \n + hb-istep s4..N + hb-istep poweron \n + hb-istep poweron..clock_frequency_set /n + """) + #------------------------------------------------ #------------------------------------------------ new_command("hb-errl", |