From 0ec3f482259bdcc1867fb884eb89a4c0c5fc026d Mon Sep 17 00:00:00 2001 From: Andrew Geissler Date: Mon, 9 May 2011 14:51:09 -0500 Subject: Initial trace support for host boot Change-Id: Ib2450ae3d32549673ca8e1c814a7a11b5f1a0c09 Reviewed-on: http://gfwr801.rchland.ibm.com:8080/gerrit/69 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III --- config.mk | 2 +- src/build/trace/tracehash_hb.pl | 881 ++++++++++++++++++++++++++++++++++++++ src/include/trace_adal.h | 249 ----------- src/include/tracinterface.H | 315 -------------- src/include/usr/trace/interface.H | 350 +++++++++++++++ src/usr/example/example.C | 36 +- src/usr/trace/trace.C | 697 ++++++++++++++++++++++++++++-- src/usr/trace/trace.H | 132 ++++++ src/usr/trace/tracebuffer.C | 2 + 9 files changed, 2061 insertions(+), 603 deletions(-) create mode 100755 src/build/trace/tracehash_hb.pl delete mode 100644 src/include/trace_adal.h delete mode 100644 src/include/tracinterface.H create mode 100644 src/include/usr/trace/interface.H create mode 100644 src/usr/trace/trace.H diff --git a/config.mk b/config.mk index e24b30e3a..721dd71c6 100644 --- a/config.mk +++ b/config.mk @@ -98,7 +98,7 @@ ${OBJDIR}/%.dep : %.S rm -f $@.$$$$ ifdef MODULE -${IMGDIR}/%.so : ${OBJECTS} ${ROOTPATH}/src/module.ld ${MODULE_INIT} ${SUBDIRS} +${IMGDIR}/%.so : ${OBJECTS} ${ROOTPATH}/src/module.ld ${MODULE_INIT} ${LD} -shared -z now ${LDFLAGS} \ $(filter-out ${ROOTPATH}/src/module.ld,$^) \ -T ${ROOTPATH}/src/module.ld -o $@ diff --git a/src/build/trace/tracehash_hb.pl b/src/build/trace/tracehash_hb.pl new file mode 100755 index 000000000..7b5548463 --- /dev/null +++ b/src/build/trace/tracehash_hb.pl @@ -0,0 +1,881 @@ +#!/usr/bin/perl -w +# File tracehash.pl created by B J Zander. +# 05/08/2011 - Update by andrewg to work in host boot environment + +use strict; + +sub determine_args(); +sub launch_cpp_and_parse($$); +sub cpp_dir($); +sub read_string_file(); +sub collect_files($); +sub assimilate_file($); +sub hash_strings(); +sub write_string_file(); +sub help(); + +select (STDERR); +$| = 1; # Make all prints to STDERR flush the buffer immediately +select (STDOUT); +$| = 1; # Make all prints to STDOUT flush the buffer immediately + +# Constants +my $HEAD_SEP = "|||"; +my $HEAD_EYE_CATCHER = "#FSP_TRACE_v"; +my $HEAD_BUILD_FLAG = "BUILD:"; +my $HEAD_VER_FLAG = 2; +my $BB_STRING_FILE = "/opt/fsp/etc/BB_StringFile"; + +# Global Variables +my $debug = 0; +my $seperator = "&&&&"; +my $file_name = "trexStringFile"; +my $in_sand; +my ($backing) = $ENV{'bb'}; +my $hash_prog = "trexhash"; #default to in path +my $build = ""; +my ($sandbox) = $ENV{'SANDBOX'} || ""; +my ($context) = $ENV{'CONTEXT'} || ""; +my ($sandboxbase) = $ENV{'SANDBOXBASE'} || ""; +my ($bb); +my ($sourcebase) = "$sandboxbase/src"; +my ($version) = $HEAD_VER_FLAG; # default to oldest version +my ($collect) = 0; +my ($INCLUDE, $Arg, $file, $dir, $string_file); +my $args = ""; + +my $fail_on_collision = 0; # 1 = exit with error if hash collision occurs +my $hash_filename_too = 0; # 1 = hash is calculated over format string + filename + +print "sourcebase = $sourcebase\n" if $debug; +print "sandbox = $sandbox\n" if $debug; +print "backing = $backing\n" if $debug; +print "context = $context\n" if $debug; + +if ($context =~ /x86/) +{ + $bb = "i586-pc-linux-gnu"; +} +else +{ + $bb = "powerpc-linux"; +} + +if(($sourcebase =~ /\w+/) && ($sandbox =~ /\w+/)) +{ + $INCLUDE = "-I $sandboxbase/export/$context/fips/include -I $backing/export/$context/fips/include -I /opt/fsp/$bb/include/fsp -I/opt/fsp/$bb/include/ -include /opt/fsp/$bb/include/fsp/tracinterface.H"; +} +else +{ + print "Not in Sandbox so guessing Include Paths...\n" if $debug; + $INCLUDE = "-I/opt/fsp/i586-pc-linux-gnu/include/fsp -I/opt/fsp/i586-pc-linux-gnu/include/ -include /opt/fsp/i586-pc-linux-gnu/include/fsp/tracinterface.H"; +} + +# I/P Series work in ODE sandbox env. +if ($sandboxbase =~ /\w+/) +{ + $in_sand = 1; + print "backing = $backing\n" if $debug; +} +else +{ + $in_sand = 0; +} + + + +# Parse the input parameters. + +while (@ARGV) { + $Arg = shift; + + if ($Arg eq "-h" || $Arg eq "-H") { + help(); + exit(127); + } + if ($Arg eq "-f") { + $file = shift; + next; + } + if ($Arg eq "-d") { + $dir = shift; + next; + } + if ($Arg eq "-s") { + $string_file = shift; + next; + } + if ($Arg eq "-c") { + $collect = 1; + next; + } + if ($Arg eq "-v") { + $debug = 1; + print "debug on\n" if $debug; + next; + } + if ($Arg eq "-C") { # fail if a hash collision is detected + $fail_on_collision = 1; + next; + } + if ($Arg eq "-F") { # hash is calculated over format string + file name + $hash_filename_too = 1; + next; + } + if ($Arg eq "-S") { + $BB_STRING_FILE = ""; + next; + } + + #just pass it onto compiler + $args = $args . " " . $Arg; +} + +print "args = $args\n" if $debug; + +if (!$file && !$dir && !$in_sand) { + help(); + exit(127); +} + +################################# +# M A I N # +################################# + +my $clock = `date`; + +$build = $HEAD_EYE_CATCHER . "$HEAD_VER_FLAG" . $HEAD_SEP . $clock . $HEAD_SEP . $HEAD_BUILD_FLAG; + +$build =~ s/\n//g; + +# Global array to hold the parsed TRAC macro calls. +my @strings = (); + +# Assoc. arrays to hold hash|string values. +my %string_file_array = (); +my %hash_strings_array = (); + +# Check all provided arguments and look for defaults if not provided by user +determine_args(); + +# Scan the appropriate files or directories for TRAC macro calls. + +if (defined $dir) +{ + + $build = $build . $dir; # default to put at top of string file + if($collect) + { + collect_files($dir); + } + else + { + cpp_dir($dir); + # Hash the string that have been scanned. + %hash_strings_array = hash_strings(); + } +} +else +{ + $build = $build . $file; # default to put at top of string file + + if($collect) + { + assimilate_file($file); + } + else + { + # make sure include path includes directory that file is in + if($file =~ /^(.+)\/[^\/]+\.C$/) + { + + launch_cpp_and_parse($file,$1); + } + else + { + # No path in front of file so it has to be local dir + launch_cpp_and_parse($file,"./"); + } + # Hash the string that have been scanned. + %hash_strings_array = hash_strings(); + } +} + +# Read the existing string file into memory. +%string_file_array = read_string_file(); + +# Write out the new string file. check for collisions of new/old string here +write_string_file(); + +print "Hashing Started at $clock\n"; +$clock = `date`; +print "Hashing Finished at $clock\n"; + +exit 0; + + +################################# +# S U B R O U T I N E S # +################################# + +#============================================================================= +# Enhance usability by figuring out which build env. we are in +#============================================================================= +sub determine_args() { + + + # Find trexhash program + # but only if needed (i.e. not in collect mode) + if (!$collect) { + my $tmp = `which $hash_prog`; + chomp $tmp; + + if ($tmp eq '') { + print STDOUT "\nWarning: Program trexhash does not exist in path.\n" if $debug; + $hash_prog = "./trexhash"; + + $tmp = `which $hash_prog`; + chomp $tmp; + if ($tmp eq '') { + print STDOUT "\nError: Unable to find trexhash \n"; + exit(127); + } + } + } + + # Verify input values. + if ((!defined $file) && (!defined $dir)) { + if(!($in_sand)) + { + print STDOUT "\nError: No input directory or file provided as input to scan\n"; + exit(127); + } + + # Assume they want sandbox scanned + if($collect) + { + # collect all string files generated by tracepp and merge + $dir = "$sandboxbase/obj/"; + } + else + { + # generate our own string file by pre-compiling all source code + $dir = "$sandboxbase/src/"; + } + print STDOUT "\n-f or -d not found...scanning $dir by default\n\n"; + } + + if (!defined $string_file) + { + if ($in_sand) + { + + # Copy the current string file from backing build into our sandbox + system ("cp $backing/obj/$file_name $sandboxbase/obj/$file_name") + if !(-e "$sandboxbase/obj/$file_name"); + + $string_file = "$sandboxbase/obj/$file_name"; + } + else + { + $string_file = "./$file_name"; + } + print STDOUT "-sf not specified, using $string_file instead...\n\n" if $debug; + + } + + # Try Creating the string file + `touch $string_file`; + + if (! -f $string_file) { + print STDOUT "\nError: File $string_file does not exist. Current directory may not be writable.\n\n"; + help(); + exit(127); + } + + # Make sure trexStringFile is readable/writeable + system("chmod ugo+rw $string_file"); + +} + +#============================================================================= +# Launch cpp script and grab input from it looking for trace calls. +#============================================================================= +sub launch_cpp_and_parse($$) { + + my ($l_loc, $l_dir) = @_; + + print "Processing file $l_loc\n" if $debug; + my $cmd = "/usr/bin/cpp $INCLUDE -I $l_dir $args $l_loc|"; + print "$cmd\n" if $debug; + open(FH,"$cmd") + or die ("Cannot open $_:$!,stopped"); + + # Read through all lines in the file.. + my $line = ; + while (defined $line) + { + chop $line; # remove EOL + $line =~ s/^\s*//; # remove unneccesary beginning white space. + $line =~ s/\s*$//; # remove unneccesary ending white space. + # Look for lines that are trace macro calls. + #if (/(trace_adal_hash)(\()( *)(".+")(,)(\d)/) + #if ($line =~ /(.*?)(trace_adal_hash)(\()( *)(".+")(,)(\d)\)+(.*\d.*)/) + while($line =~ m/^(.*?)trace_adal_hash\s*\(\s*(("[^"]*"\s*)+),\s*(\d+)\s*\)(.*)$/) + { + my ($prefix, $strings, $salt, $suffix) = ($1, $2, $4, $5); + print STDOUT "$strings $salt\n" if $debug; + $strings =~ s/"\s*$//; # remove trailing " and space + $strings =~ s/^"//; # remove leading " + $strings =~ s/"\s*"//g; + # Check to see if it's contained on a single line, or if we + # have to combine lines to get a complete trace call. + + # Save the macro call so it can be hashed later.. + push (@strings, [$l_loc, $strings, $salt]); + $line = $suffix; # check rest of line for a second trace call + } + my $nextline = ; + last if !defined $nextline; + # if a trace call is spread over multiple lines we have to add the next + # line from the source. the only problem is the definition/declaration + # of trace_adal_hash: we have to ignore that. we catch that by requiring + # a " after the function name. hopefully nobody writes a comment with + # a " after the function declaration ... + if ($line =~ /trace_adal_hash.*"/) { + $line .= $nextline; + } else { + $line = $nextline; + } + } + close(FH); +} + +#============================================================================= +# run cpp on all files in this directory and return the output +#============================================================================= +sub cpp_dir($) { + + my ($l_dir) = @_; + my @dir_entry; + my $l_entry; + + # Open the directory and read all entry names. + opendir ( DH , "$l_dir") + or die ("Cannot open $l_dir: $!, stopped"); + + print STDOUT "Processing directory $l_dir\n" if $debug; + @dir_entry = readdir(DH); + closedir(DH); + + while (@dir_entry) { + $l_entry = shift(@dir_entry); + + if ($l_dir =~ m"/$") { + $l_entry = "$l_dir$l_entry"; + } + else { + $l_entry = "$l_dir/$l_entry"; + } + + # Is the entry a directory? + if (-d $l_entry) { + + if($l_entry =~ m"/?([^/]+)$") + { + # check dir we are going into + print "dir = $1\n" if $debug; + # should we recurse into this directory. + if ($1 =~ m/^(\.\.?|sim[ou]|bldv)$/) + { + next; # skip '.', '..' and some fips dirs + } + cpp_dir($l_entry); + } + else + { + # unable to determine name of dir (no / in filename) + # should we recurse into this directory. + if ($l_entry =~ m/^(\.\.?|sim[ou]|bldv)$/) + { + next; # skip '.', '..' and some fips dirs + } + cpp_dir($l_entry); + } + } + # Is the entry a file? + elsif ((-f $l_entry) && ($l_entry =~ m/\.C$/)) { + # it's a file so + launch_cpp_and_parse($l_entry,$l_dir); + } + else { + # Not a file or directory so ignore it... + } + } +} + +#============================================================================= +# Read in strings from the existing trace string file.... +#============================================================================= +sub read_string_file() { + + my %o_strings; + my ($line) = ""; + my ($l_hash) = ""; + my ($l_str) = ""; + my ($cur_build) = ""; + my ($l_file) = ""; + + + # Make sure we can open each file. + open ( FH , "<$string_file") + or die ("Cannot open $_: $!, stopped"); + + $line = ; + + print "first line in trexStringFile= $line\n" if $debug; + + if((defined $line) && ($line =~ /^$HEAD_EYE_CATCHER(\d)/)) + { + $version = $1; + + print "version = $version\n" if $debug; + + #Always put latest version in file + $line =~ s/^$HEAD_EYE_CATCHER\d/${HEAD_EYE_CATCHER}${HEAD_VER_FLAG}/; + + # Take previous version in file and use it. + $build = $line; + chomp($build); + $line = ; + + while (defined $line) { + chomp $line; # remove EOL + if($version eq "1") + { + ($l_hash, $l_file ,$l_str) = split(/\|\|/, $line); + } + elsif($version eq "2") + { + ($l_hash, $l_str ,$l_file) = split(/\|\|/, $line); + } + else + { + print "Unknown version of stringfile $version\n"; + exit(127); + } + $o_strings{$l_hash} = $l_str . "||" . $l_file; + $line = ; + } + + } + else + { # If there is a file then we are dealing with the first + # version of trexStringFile so don't look for file name. + if ($debug) { + print "version 0 stringfile detected: $string_file\n"; + } + + # there is a file and it doesn't have a header + $version = 0; + + while (defined $line) { + chomp $line; # remove EOL + ($l_hash,$l_str) = split(/\|\|/, $line); + $o_strings{$l_hash} =$l_str . "||" . "NO FILE"; + $line = ; + } + } + + close(FH); + + #Time to look for a building block string file + if($BB_STRING_FILE ne "" and $string_file ne $BB_STRING_FILE and -f $BB_STRING_FILE) + { + + # Make sure we can open the file. + open ( FH , "<$BB_STRING_FILE") + or die ("Cannot open $_: $!, stopped"); + + $line = ; + + print "first line in BB_StringFile = $line\n" if $debug; + if((defined $line) && ($line =~ /^$HEAD_EYE_CATCHER(\d)/)) + { + $version = $1; + + $line = ; + while (defined $line) + { + chop $line; # remove EOL + if($version eq "1") + { + ($l_hash, $l_file ,$l_str) = split(/\|\|/, $line); + } + elsif($version eq "2") + { + ($l_hash, $l_str ,$l_file) = split(/\|\|/, $line); + } + #($l_hash, $l_file ,$l_str) = split(/\|\|/, $line); + $o_strings{$l_hash} = $l_str . "||" . $l_file ; + $line = ; + } + } + else + { + print "*** ERROR: BB_StringFile '$BB_STRING_FILE' should always have version!!!\n" + } + + } + else + { + print "$BB_STRING_FILE is not available\n" if $debug; + } + #All files are latest version now. + $version = $HEAD_VER_FLAG; + return %o_strings; +} + +#============================================================================= +# Read in strings from the existing trace string file.... +#============================================================================= +sub collect_files($) { + + my ($l_dir) = @_; + my (@dir_entry); + my ($l_entry) = ""; + + # Open the directory and read all entry names. + opendir ( DH , "$l_dir") + or die ("Cannot open $l_dir: $!, stopped"); + + print STDOUT "Processing directory $l_dir\n" if $debug; + @dir_entry = readdir(DH); + closedir(DH); + + while (@dir_entry) { + $l_entry = shift(@dir_entry); + + if ($l_dir =~ m"/$") { + $l_entry = "$l_dir$l_entry"; + } + else { + $l_entry = "$l_dir/$l_entry"; + } + + # Is the entry a directory? + if (-d $l_entry) { + + # should we recurse into this directory. + if ($l_entry =~ m/\/(\.\.?|sim[ou]|bldv)$/) + { + next; # skip '.', '..' and some fips dirs + } + collect_files($l_entry); + } + # Is the entry a file? + elsif ((-f $l_entry) && ($l_entry =~ m"\.hash$")) { + # it's a file so + assimilate_file($l_entry); + } + else { + # Not a file or directory so ignore it... + } + } + +} + +#============================================================================= +# Read in data from file and add to master one +#============================================================================= +sub assimilate_file($) { + + my ($l_loc) = @_; + + my (%o_strings); + my ($line) = ""; + my ($l_hash) = ""; + my ($l_str) = ""; + my ($l_file) = ""; + + # Make sure we can open each file. + open ( FH , "<$l_loc") + or die ("Cannot open $_: $!, stopped"); + + $line = ; + + print "Assimilate: first line in $l_loc = $line" if $debug; + + if((defined $line) && ($line =~ /^$HEAD_EYE_CATCHER(\d)/)) + { + $version = $1; + if ($version eq "1") { + if ($hash_filename_too) { + print "*** ERROR: hash_filename_too (-F) isn't possible with trace version 1\n"; + print " please rebuild all .hash files and global trexStringFile\n"; + print " version 1 file is '$l_loc'\n"; + exit(127); + } + } elsif ($version ne "2") { + print "Unknown version of stringfile $version\n"; + exit(127); + } + + $line = ; + + while (defined $line) { + chop $line; # remove EOL + + # 64 bit support + $line =~ s/\%d/\%lld/; + $line =~ s/\%u/\%llu/; + $line =~ s/\%x/\%llx/; + $line =~ s/\%X/\%llX/; + #print "line: $line\n"; + + if($version eq "1") + { + ($l_hash, $l_file ,$l_str) = split(/\|\|/, $line); + } + elsif($version eq "2") + { + ($l_hash, $l_str ,$l_file) = split(/\|\|/, $line); + } + my $newstring = $l_str . "||" . $l_file; + if (exists $hash_strings_array{$l_hash}) { + my $hashstr1 = $hash_strings_array{$l_hash}; + my $hashstr2 = $newstring; + if (!$hash_filename_too) { + # hash was made over format string only, remove file name + $hashstr1 =~ s/\|\|.*$//; + $hashstr2 = $l_str; + } + if ($debug) { + print "a_f: compare $hashstr1\n", + " vs. $hashstr2\n"; + } + if ($hashstr1 ne $hashstr2) + { + print "*** ERROR: HASH Collision! (a_f)\n", + " Two different strings have the same hash value ($l_hash)\n", + " String 1: $hash_strings_array{$l_hash}\n", + " String 2: $newstring\n"; + if ($fail_on_collision) { + exit(1); + } + } + } + $hash_strings_array{$l_hash} = $newstring; + $line = ; + } + + } + else + { # If there is a file then we are dealing with the first + # version of trexStringFile so don't look for file name. + # these files shouldn't be there anymore. we don't check for collisions here + if ($debug) { + print "version 0 stringfile detected: $string_file\n"; + } + + if(defined $line) + { + # there is a file and it doesn't have a header + $version = 0; + } + + while (defined $line) { + chop $line; # remove EOL + ($l_hash,$l_str) = split(/\|\|/, $line); + $hash_strings_array{$l_hash} = $l_str . "||" . "NO FILE"; + $line = ; + } + } + $version = $HEAD_VER_FLAG; + close(FH); +} + +#============================================================================= + +#============================================================================= +sub hash_strings() { + + my ($hash_val, $l_key, $l_hash, %l_hash_strings); + my ($line_feed) = chr(10); + my ($l_file_name) = "NO FILENAME"; + print "\nHashing printf strings.\n\n"; + + foreach my $str (@strings) { + my $printf_string; + $l_file_name = $str->[0]; + $printf_string = $str->[1]; + $l_key = $str->[2]; + print "printf_string = $printf_string\n" if $debug; + $printf_string =~ s/"\s?"//g; #multi line traces will have extra " in them + $printf_string =~ s/`/\\`/g; # excape ' + $printf_string =~ s/\\n/$line_feed/g; # escape \n + if ($hash_filename_too) { + $printf_string .= "||" . $l_file_name; + } + + # call the hasher. + print "$hash_prog \"$printf_string\" $l_key\n" if $debug; + $hash_val = `$hash_prog \"$printf_string\" $l_key`; + if ($?) { + my ($hp_ret, $hp_sig) = ($? >> 8, $? & 127); + if ($hp_sig) { + print "*** ERROR: $hash_prog died with signal $hp_sig\n"; + } elsif ($hp_ret) { + print "*** ERROR: $hash_prog returned the error $hp_ret\n"; + if ($hash_val) { + print " error from $hash_prog:\n$hash_val"; + } + } + exit(1); + } + print "printf_string = $printf_string l_key = $l_key hash val = $hash_val\n" if $debug; + + # undo escaping + $printf_string =~ s/$line_feed/\\n/g; + $printf_string =~ s/\\`/`/g; + + if (exists $l_hash_strings{$hash_val}) + { + # hash val was found before. check if it's the same string + # else we have a hash collision + my $l_tmp = $l_hash_strings{$hash_val}; + if (!$hash_filename_too) { + $l_tmp =~ s/\|\|.*$//; + } + if ($l_tmp ne $printf_string) + { + print "*** ERROR: HASH Collision! (h_s)\n", + " Two different strings have the same hash value ($hash_val)\n", + " String 1: $l_hash_strings{$hash_val}\n", + " String 2: $printf_string (file $l_file_name)\n"; + if ($fail_on_collision) { + exit(1); + } + } + } + # this will overwrite an old string with a new one if a collision occurred + # but we might want to bail out in this case anyway + $printf_string = $printf_string . "||" . $l_file_name; + $l_hash_strings{$hash_val} = $printf_string; + } + return %l_hash_strings; +} +#============================================================================= + +#============================================================================= +sub write_string_file() { + + my (@keys) = (); + my ($l_key) = ""; + + # Combine the contents of the existing string file with the trace calls + # that we have just hashed. + print STDOUT "\nCombining Hash strings...\n\n"; + + @keys = keys(%hash_strings_array); + + foreach $l_key (@keys) { + my $l_tmp = $hash_strings_array{$l_key}; # freshly collected strings + if (exists $string_file_array{$l_key}) + { # hash exists in list from trexStringFile + my $l_tmp2 = $string_file_array{$l_key}; + if (!$hash_filename_too) { + $l_tmp =~ s/\|\|.*$//; + $l_tmp2 =~ s/\|\|.*$//; + } + + # Check for hash collisions. + if ($l_tmp ne $l_tmp2) + { + print "*** ERROR: HASH Collision! (w_s_f)\n", + " Two different strings have the same hash value ($l_key)\n", + " String 1: $hash_strings_array{$l_key}\n", + " String 2: $string_file_array{$l_key}\n"; + if ($fail_on_collision) { + exit(1); + } + # don't fail, write new one + } + } + if($version > 0) + { + # add/replace the new string to the string_file_array. + $string_file_array{$l_key} = $hash_strings_array{$l_key} + } + else + { + # old version so only write out format string (not file name to) + $string_file_array{$l_key} = $l_tmp; + } + } + + # Write out the updated string file. + print STDOUT "\nWriting updated hash||string file...\n\n"; + + @keys = sort(keys(%string_file_array)); + + open ( FH , ">$string_file") + or die ("Cannot open $_: $!, stopped"); + + if($version > 0) + { + print FH "$build\n"; # only print version if newer then version 0 + } + foreach $l_key (@keys) { + print FH "$l_key||$string_file_array{$l_key}\n"; + } + close FH; +} +#============================================================================= + +#============================================================================= +# Display command invokation help for this program... +#============================================================================= +sub help() { + print << "EOF"; +tracehash.pl - create a trace string file from sources or collect tracepp files +Usage: tracehash.pl [options] + General options: + -h - Print this help text. + -v - Be verbose, tell what's going on (debug output) + Operation modes + -c - Collect StringFiles created by tracepp and merge. + default - Scan source files for trace calls. + +Collect mode: tracehash.pl -c [-vFCS] [-d ] [-s ] + tracehash.pl -c [-vFCS] [-f ] [-s ] + Collect string files created by tracepp (.hash) from directory tree at + or read them from string file and write to file + , adding entries already in this file. + -f - String file to read and write/add to . + -d - Start of directory tree to scan for .hash files. Default = . + -s - File with trace strings (and hashes) to read from and write to + default = ./trexStringFile + -F - hash is calculated over trace string and source file name, + otherwise without source file name + -C - report an error if a hash collisions occurs + -S - don't read global FLD-2.2 string file ($BB_STRING_FILE) + If tracehash.pl is called in a FipS build sandbox without -d and -f + defaults for the sandbox will be used. + +Scan mode: tracehash.pl [-vFCS] [-d ] [-s ] [ccpopts] + tracehash.pl [-vFCS] [-f ] [-s ] [cppopts] + Scan all files in directory tree or scan file and write + strings to file . Strings already in this file will be merged. + -f - Source file to scan for trace entries. + -d - Source directory to scan for trace entries. + -s - File with trace strings (and hashes) to read from and write to. + default = ./trexStringFile + -F - hash for string was build from format string + source file name + -C - report an error if hash collisions occur + -S - don't read global FLD-2.2 string file ($BB_STRING_FILE) + All other arguments will be passed verbatim to cpp +EOF +} +#============================================================================= + diff --git a/src/include/trace_adal.h b/src/include/trace_adal.h deleted file mode 100644 index fb8e1501e..000000000 --- a/src/include/trace_adal.h +++ /dev/null @@ -1,249 +0,0 @@ -/****************************************************************************** - * IBM Confidential - * - * Licensed Internal Code Source Materials - * - * IBM Flexible Support Processor Licensed Internal Code - * - * (c) Copyright IBM Corp. 2004, 2009 - * - * The source code is for this program is not published or otherwise divested - * of its trade secrets, irrespective of what has been deposited with the - * U.S. Copyright Office. - ***************************************************************************** - * \file trace_adal.h - * \brief Contains header data for trace component.. - * - * The trace component allows an application to trace its execution into - * circular buffers (like a flight recorder) with low performance and - * memory usage impact. This implementation focuses on the Linux operating - * system running on embedded controllers. - * - * \note Please see the document trace_doc.lyx for full documentation on this - * \note component. - *****************************************************************************/ - - -#ifndef _TRACE_ADAL_H -#define _TRACE_ADAL_H - -#include - -/** - * @brief Maximum size of component name - * @note Make sure to also change in include/linux/trac.h - - * TRACER_FSP_TRACE_NAME_SIZE -*/ -#define TRACE_MAX_COMP_NAME_SIZE 16 - -#define TRACE_DEBUG_ON 1 //Set to this when debug trace on -#define TRACE_DEBUG_OFF 0 //Set to this when debug trace off -#define TRACE_DEBUG 1 //Pass this when trace is debug -#define TRACE_FIELD 0 //Pass this when trace is field - -#define TRACE_COMP_TRACE 0x434F //Identifies trace as a component trace (printf) -#define TRACE_BINARY_TRACE 0x4249 //Identifies trace as a binary trace -#define TRACE_INTERNAL_BLOCKED 0xFF42 //Identifies trace as an dd internal trace - -#define TRACE_BUFFER_VERSION 1 //Trace buffer version -#define TRACE_BUFFER_BINARY_VERSION 2 //Trace buffer version when collected by fsp-trace from pipe - -#define TRACE_DEFAULT_TD 0 //Default trace descriptor - - -/* - * Parsing and output modifier flags - */ - -/* When multiple buffers are given the traces of all buffers are sorted by timestamp and printed as one list. - * If this flag is not given the traces are printed separatly for each trace buffers (i.e. grouped by buffer). - */ -#define TRACE_MIX_BUFFERS 1 - -/* Show the name of a trace buffer for each trace. The buffer name will be inserted between timestamp and trace text. - * Only one of TRACE_APPEND_BUFFERNAME and TRACE_PREPEND_BUFFERNAME can be given. - */ -#define TRACE_PREPEND_BUFFERNAME 2 - -/* Show the name of a trace buffer for each trace. The buffer name will be appended at the end of the line - * (after trace text). Only one of TRACE_APPEND_BUFFERNAME and TRACE_PREPEND_BUFFERNAME can be given. - */ -#define TRACE_APPEND_BUFFERNAME 4 - -/* When set timestamps are translated to timeofday values (date/time). This needs "timeref" to be given. - * If timeref is not given the timestamps are treated as if the PPC timebase counter was started at epoch time - * (i.e. the printed timestamp will be the time since FSP boot time). - */ -#define TRACE_TIMEOFDAY 8 - -/* If a TIMEREF trace is found in a trace buffer and timeref is a valid - * pointer the values from the TIMEREF trace are written to timeref. This flag is independent of TRACE_TIMEOFDAY. - */ -#define TRACE_SET_TIMEOFDAY 16 - -/* Show the name of the source file that contains the trace statement for each trace. - * (at the end of the line, after buffer name if this is printed too). - */ -#define TRACE_FILENAME 32 -#define TRACE_VERBOSE 64 //some messages are printed to STDERR. -#define TRACE_IGNORE_VERSION 128 -#define TRACE_OVERWRITE 256 -#define TRACE_BINARY 512 - -/* When this is set trace pipe isn't turned off after pipe read - */ -#define TRACE_DONTSTOP 1024 - - -/* MSB of tid field is used as trace-in-irq flag - */ -#define TRACE_TID_IRQ (1<<31) -#define TRACE_TID_TID(tid) ((tid) & ~(TRACE_TID_IRQ)) - -/*! - * @brief Device driver fills in this structure for each trace entry. - * It will put this data first in the trace buffer. - */ -typedef struct trace_entry_stamp { - uint32_t tbh; /*!< timestamp upper part */ - uint32_t tbl; /*!< timestamp lower part */ - uint32_t tid; /*!< process/thread id */ -} trace_entry_stamp_t; - - -/* - * @brief Structure is used by adal app. layer to fill in trace info. - */ -typedef struct trace_entry_head { - uint16_t length; /*!< size of trace entry */ - uint16_t tag; /*!< type of entry: xTRACE xDUMP, (un)packed */ - uint32_t hash; /*!< a value for the (format) string */ - uint32_t line; /*!< source file line number of trace call */ - uint32_t args[0]; /*!< trace args or data of binary trace */ -} trace_entry_head_t; - - -/* - * @brief Structure is used to return current components tracing - */ -typedef struct trace_buf_list { - char name[TRACE_MAX_COMP_NAME_SIZE]; /*!< component name */ - size_t size; /*!< size of component trace buffer */ -} trace_buf_list_t; - - -typedef uint64_t trace_desc_t; //Type definition for users trace descriptor data type -typedef uint64_t tracDesc_t; //Type definition for older trace descriptor type -typedef unsigned long trace_strings_t; /* type for trace strings */ - - -/* - * @brief Will use this to hold hash value. - * - */ -enum trace_hash_val { trace_hash }; - -/* struct for time */ -struct trace_tbtime { - uint32_t high; - uint32_t low; -}; - - -/*----------------------------------------------------------------------------*/ -/* Constants */ -/*----------------------------------------------------------------------------*/ -/* only define if not defined by trace_dd.h (make different versions of - * these files compatible). check only for one define instead of all */ -#ifndef TRACE_FIELDTRACE - -/* a component trace of type field (non-debug): x4654 = "FT" */ -#define TRACE_FIELDTRACE 0x4654 -/* a component trace of type debug: x4454 = "DT" */ -#define TRACE_DEBUGTRACE 0x4454 -/* a binary trace of type field (non-debug): x4644 = "FD" */ -#define TRACE_FIELDBIN 0x4644 -/* a binary trace of type debug: x4644 = "DD" */ -#define TRACE_DEBUGBIN 0x4444 -/* a string trace of type field (non-debug): x4653 = "FS" */ -#define TRACE_FIELDSTRING 0x4653 -/* a string trace of type debug: x4453 = "DS" */ -#define TRACE_DEBUGSTRING 0x4453 - -#endif - -/*----------------------------------------------------------------------------*/ -/* Function Prototypes */ -/*----------------------------------------------------------------------------*/ - -#ifdef __cplusplus -extern "C" { -#endif - -/*! - * @brief Initialize a trace buffer for a component. - * - * @param td Device driver will assign caller a trace descriptor. - * @param comp Pointer to 16 character null terminated string. - * @param size Requested buffer size. - * - * @return 0 for success, negative value for failure. - * @retval #TRACE_INIT_BUFF_IOCTL_ERR device driver refused to create buffer - * @retval #TRACE_INIT_BUFF_NAME_ERR buffer name was too long, a buffer with the - name "BADN" was created instead - * @retval #TRACE_INIT_FD_ERR cannot open trace device (module not loaded?), errno set - */ -int32_t trace_adal_init_buffer(trace_desc_t *,const char *,const size_t); - -/*! - * @brief Set trace debug level - * - * @param td Assigned trace descriptor. - * @param level If 0 only field traces will be active. If > 0 debug traces - * with level <= 'level' will be active. - * - * @return 0 for success, negative value for failure. - * @retval #TRACE_SETDEBUG_IOCTL_ERR error from device driver, errno set - * @retval #TRACE_SETDEBUG_INV_PARM_ERR second parm must be TRACE_DEBUG_ON or TRACE_DEBUG_OFF - * @retval #TRACE_INIT_FD_ERR cannot open trace device (module not loaded?), errno set - */ -int32_t trace_adal_setdebug(const trace_desc_t, const int32_t); - -/*! - * @brief Write some data to trace buffer. - * - * @param td Assigned trace descriptor. - * @param debug Is it a debug trace or field. - * @param size Size of data. - * @param data Data to write to buffer. - * @param size2 Size of second data block. - * @param data2 Second data block to write to buffer. - * - * @return 0 for success, negative value for failure. - * @retval #TRACE_WRITE_IOCTL_ERR error from device driver, errno set - * @retval #TRACE_INIT_FD_ERR cannot open trace device (module not loaded?), errno set - */ -int32_t trace_adal_write2(const trace_desc_t, const int32_t, - const size_t,const void *,const size_t,const void *); - -/*! - * @brief Write trace data (can handle all data types) - * - * @return 0 for success, negative value for failure. - * @retval #TRACE_WRITE_ALL_IOCTL_ERR error from device driver, errno set - * @retval #TRACE_WRITE_NOT_INIT trying to trace without device driver - * @retval #TRACE_THREAD_LOCK_FAIL error locking thread lock - * @retval #TRACE_THREAD_UNLOCK_FAIL error unlocking thread lock - * @retval #TRACE_INIT_FD_ERR cannot open trace device (module not loaded?), errno set - * @retval #TRACE_WRITE_ALL_BAD_TD bad trace descriptor - */ -int32_t trace_adal_write_all(const trace_desc_t i_td,const enum trace_hash_val i_hash, - const char *i_fmt, - const uint32_t i_line, const int32_t i_type,...) - __attribute__ ((format (printf, 3, 6))); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/include/tracinterface.H b/src/include/tracinterface.H deleted file mode 100644 index a6d885314..000000000 --- a/src/include/tracinterface.H +++ /dev/null @@ -1,315 +0,0 @@ -/****************************************************************************** - * IBM Confidential - * - * Licensed Internal Code Source Materials - * - * IBM Flexible Support Processor Licensed Internal Code - * - * (c) Copyright IBM Corp. 2004, 2010 - * - * The source code is for this program is not published or otherwise divested - * of its trade secrets, irrespective of what has been deposited with the - * U.S. Copyright Office. - *****************************************************************************/ - -#ifndef TRACINTERFACE_H -#define TRACINTERFACE_H - -/*!@file tracinterface.H - * @brief Contains macros for trace interface - * - * This header file provides a common interface for the Trace - * mechanism. Trace is a way for developers to debug their code. They - * can use the trace Macro's to write to standar out, to wraparound files and - * to a wraparound buffer which will be stored in shared memory. - * - * There are two types of trace, debug and field, that you can use when tracing. - * Debug traces will be compiled out of the code when the system is released to the field. - * Field traces will be remain in the code permenantly. - * - * TRACxSYSn calls will always go to syslog - * - * There are three different environments trace will operate in. - * - * Unit Test / Simulation: All component traces (debug and field) are sent to standard out by default. - * The developer has the option to do define an evironmental variable: - * 'export FIPS_TRACE_PATH=""' where path is the location to write the files (ex. "./"). - * - * Lab: All component traces will, by default, follow the same implementation as the - * Unit Test / Simulation env. However, drivers flashed onto the system (built by the - * build team) will use the memory wrapping implementation. Code built in a local - * sandbox will continue to use the file wrapping implementation. This will give - * the developer the speed of the memory wrapping trace (for code they don't really - * care about) and ease of debug with the file wrapping code (for their own code). - * - * Field: Only component traces of type field will be sent to the shared memory wraparound - * buffer. Debug traces will be compiled out of the code. - * - * In Unit Test / Simulation, The file will have the name "trac" + 'component name'. - * For example the error logger component would be /tracERRL -*/ -/* Change Log *****************************************************************/ -/* */ -/* ch# Feat/def# Userid Date Description */ -/* --- ---------- -------- -------- ----------------------------------------*/ -/* 00 N/A andrewg 08/27/01 Created */ -/* 01 N/A andrewg 10/03/01 Removed duplicate copyright and other housekeeping */ -/* 02 N/A andrewg 10/17/01 Added deallocateBuffer flag to TRAC_FREE_BUFFER */ -/* 03 N/A andrewg 10/19/01 Added 'using namespace std;', vector.h -> vector */ -/* included iostream.h, printf bug. */ -/* 04 354052 andrewg 11/09/01 Took out file writing portion, only go to printf */ -/* ag05 354388 andrewg 11/14/01 Changed binary macro name and added typedef */ -/* ag06 354696 andrewg 11/19/01 Removed ag05 change flags, causing errors */ -/* n/a 355095 andrewg 11/28/01 Put common.h include first */ -/* ag07 354971 andrewg 11/28/01 Added file wrapping code */ -/* ag08 359225 andrewg 02/11/01 Added memory wrapping code, removed USE_PRINTF defined flag */ -/* ag09 360869 andrewg 03/04/02 Added persistant writing macro */ -/* ag10 361649 andrewg 03/08/02 Added the constants */ -/* n/a 363697 andrewg 03/28/02 Modified to use new file object */ -/* n/a 376324 andrewg 07/24/02 Fixed bad define of TRACDCOMP9 */ -/* ag11 382759 andrewg 09/09/02 Support compile flag to remove debug trace */ -/* n/a 385314 andrewg 09/27/02 Remove use of STL */ -/* n/a 388981 andrewg 11/12/02 Add new static variable constructor */ -/* n/a HBIBASE iawilllia 10/05/10 Removed a lot of stuff for HBI trace base. */ -/* End Change Log *************************************************************/ - -//--------------------------------------------------------------------// -// Constants // -//--------------------------------------------------------------------// -#define ENTER_MRK ">>" // -- ag10 -#define EXIT_MRK "<<" // -- ag10 -#define ERR_MRK "E>" // -- ag10 -#define INFO_MRK "I>" // -- ag10 -#define ARG_MRK "A>" // -- ag10 - -#ifndef NFP_CLIENT // dc99 -#include -#include -#else -typedef int tracDesc_t; -typedef int trace_desc_t; -#endif - -#if( defined(NFP_LIBRARY) || defined(NFP_CLIENT) ) // dc99 - -#define TRACSCOMP(des,printf_string,args...) do {} while(0) -#define TRACDCOMP(des,printf_string,args...) do {} while(0) -#define TRACDBIN(des,descString,address,length) do {} while(0) - -#define TRACFCOMP(des,printf_string,args...) \ - printf(printf_string "\n", ##args) -#define TRACFBIN(des,descString,address,length) \ - printf("%s pointer:%p size:%d\n",descString,address,length) - -#define TRAC_INIT_BUFFER(des,comp_name, bufferSize) \ - *(des) = 1 - -#define TRAC_INIT(des,comp_name, bufferSize) - -#define TRAC_FREE_BUFFER(des,deallocateBuff) do {} while(0) - -#else - -// check compatibility of header file/macros and preprocessor tracepp -// if tracepp was used -#define TRAC_MACROVER 1 -#ifdef TRAC_TRACEPP -#if !defined(TRAC_PPVER) -#warning fsptrace preprocessor version unknown, might be incompatible with header file -#elif TRAC_PPVER < TRAC_MACROVER -#error fsptrace header file version and preprocessor version dont fit -#endif -#endif - -//------------------------------------------------------------------------------ -// INCLUDES -//------------------------------------------------------------------------------ - -#include - -/* for any trace_adal_write_all call we need the printf_string in addition to - * the hash value. if tracepp is used it will add a (shortened) printf string, - * otherwise the macros has to add it - */ - -#ifdef TRAC_TRACEPP -#define __ALL_HASH(printf_string,num) trace_adal_hash(printf_string,num) -#else -#define __ALL_HASH(printf_string,num) trace_adal_hash(printf_string,num),printf_string -#endif - -#ifdef TRAC_DEBUG_OUT /* compile out everyones debug traces */ - -#define TRACDCOMP(des,printf_string,args...) do {} while(0) -#define TRACDBIN(des,descString,address,length) do {} while(0) - -#else /* direct them to real function calls */ - -/** - @fn void TRACDCOMP0(des, printf_string) - @brief Defines all Debug Component Traces - - The user can pass 0 to 9 parameters to the macro. In the field environment, - these trace calls will be compiled out of the code. Use these for early bringup - needs. These trace calls are written to a memory buffer. - @note If you are passing parameters then make sure 'printf_string' has the - @note necessary parameter formatting i.e. 'p1' = "hello" make sure - @note 'printf_string' has "%s" somewhere in it to corretcly format p1. - @return void The user will not be impacted by the failure of this function - @param des This is assigned by TRAC_INIT_BUFFER - @param printf_string string describing the trace entry and providing the formatting flags for any parameters passed. - @param p1,p2... Optional parameters -*/ - -/* a macro w/o the param number suffix. number is calculated from printf string */ -#define TRACDCOMP(des,printf_string,args...) \ - trace_adal_write_all((des),__ALL_HASH(printf_string,-1),__LINE__,TRACE_DEBUG, ##args) - -/** - @fn void TRACDBIN(des,descString,address,length) - @brief Defines debug binary trace - - The binary trace should be used to write out a section of memory. The debug - binary trace will be compiled out in the field environment so only use for early - bringup debug. When this is being written to a file, it will be displayed in - hexidecimal. - @return void The user will not be impacted by the failure of this function - @param des This is assigned by TRAC_INIT_BUFFER - @param descString A string that will be put in front of the binary dump, developer assigns anything they want. - @param address Address of beginning of data to dump. - @param length lenght of the binary data. -*/ -#define TRACDBIN(des,descString,address,len) \ - do{ trace_entry_head_t __e; \ - __e.tag = TRACE_DEBUGBIN; \ - __e.line = __LINE__; \ - __e.length = (len); \ - __e.hash = trace_adal_hash(descString, 0); \ - trace_adal_write2((des), TRACE_DEBUG, sizeof(trace_entry_head_t), &__e, \ - (uint32_t) (__e.length), (uint32_t *) (address)); \ - } while(0) - -#endif /* TRAC_DEBUG_OUT */ - -/** - @fn void TRACFCOMP0(des, printf_string) - @brief Defines all Field Component Traces - - The user can pass 0 to 9 parameters to the macro. These trace calls will - always be written to the trace memory buffer. - @note If you are passing parameters then make sure 'printf_string' has the - @note necessary parameter formatting - @note i.e. 'p1' = "hello" make sure 'printf_string' has "%s" somewhere in - @note it to corretcly format p1. - @return void The user will not be impacted by the failure of this function - @param des This is assigned by TRAC_INIT_BUFFER - @param printf_string string describing the trace entry and providing the formatting flags for any parameters passed. - @param p1,p2... Optional parameters -*/ - -/* a macro w/o the param number suffix. number is calculated from printf string */ -#define TRACFCOMP(des,printf_string,args...) \ - trace_adal_write_all((des),__ALL_HASH(printf_string,-1),__LINE__,TRACE_FIELD, ##args) - -/** - @fn void TRACSCOMP0(des, printf_string) - @brief Defines all Strace Component Traces - - The user can pass 0 to 9 parameters to the macro. These traces will be treated - as debug traces but will never be compiled out of the code so that they can always be - dynamically turned on/off. - - @note If you are passing parameters then make sure 'printf_string' has the - @note necessary parameter formatting i.e. 'p1' = "hello" make sure - @note 'printf_string' has '%s' somewhere in it to corretcly format p1. - @return void The user will not be impacted by the failure of this function - @param des This is assigned by TRAC_INIT_BUFFER - @param printf_string string describing the trace entry and providing the formatting flags for any parameters passed. - @param p1,p2... Optional parameters - - tracepp replaces trace_adal_hash() with hash value and reduced format string -*/ - -/* a macro w/o the param number suffix. number is calculated from printf string */ -#define TRACSCOMP(des,printf_string,args...) \ - trace_adal_write_all((des),__ALL_HASH(printf_string,-1),__LINE__,TRACE_DEBUG, ##args) - -/** - @fn void TRACFBIN(des,descString,address,length) - @brief Defines field binary trace - - The binary trace should be used to write out a section of memory. The field - binary trace will always be logged so use for important information. - When this is being written to a file, it will be displayed in hexidecimal. - @return void The user will not be impacted by the failure of this function - @param des This is assigned by TRAC_INIT_BUFFER - @param descString A string that will be put in front of the binary dump, developer assigns anything they want. - @param address Address of beginning of data to dump. - @param length lenght of the binary data. -*/ -#define TRACFBIN(des,descString,address,len) \ - do{ trace_entry_head_t __e; \ - __e.tag = TRACE_FIELDBIN; \ - __e.line = __LINE__; \ - __e.length = (len); \ - __e.hash = trace_adal_hash(descString, 0); \ - trace_adal_write2((des), TRACE_FIELD, sizeof(trace_entry_head_t), &__e, \ - (uint32_t) (__e.length), (uint32_t *) (address)); \ - } while(0) - - -/** - @fn void TRAC_INIT_BUFFER(des,comp_name, bufferSize) - @brief Initializes trace buffer for component - - This function must be called before any other trace calls. It - initializes a file for the calling component and returns a trace - descriptor which is used by the trace calls to find the correct file to write to. - @return void The user will not be impacted by the failure of this function. If des is a positive value, success. - @param des This is assigned by this function. - @param comp_name This is the four character name of the component requesting the trace buffer. - @param bufferSize Requested length of the buffer, if 0 is entered the user will get default buffer size. -*/ -#define TRAC_INIT_BUFFER(des,comp_name, bufferSize) \ - trace_adal_init_buffer((des), (comp_name), (bufferSize)) - - -class TracInit -{ - public: - - /*------------------------------------------------------------------------*/ - /* Constructor */ - /*------------------------------------------------------------------------*/ - - TracInit(tracDesc_t *o_td, const char *i_comp,const size_t i_size) - { - // printf("TracInit constructor called for %s, size %u\n",i_comp,i_size); - TRAC_INIT_BUFFER(o_td,i_comp,i_size); - } - - ~TracInit() - { - // printf("in the TracInit destructor\n"); - } - -}; - -/******************************************************************************* - TRAC_INIT: Class for creating trace descriptor object. - - About the macros. - TRAC_INIT -- Called by users, adds __LINE__ for uniqueness. - TRAC_INIT_LINE -- Translates __LINE__ into the line number. Using - macro expansion in this statement would result in - tracInit static g_trac_"__LINE__" - TRAC_INIT_UNIQ -- With line number translated, use the '##' operator to - append number in variable name. -*******************************************************************************/ - -#define TRAC_INIT_UNIQ(des, name, sz, ln) TracInit static g_trac_##ln(des, name, sz) -#define TRAC_INIT_LINE(des, name, sz, ln) TRAC_INIT_UNIQ(des, name, sz, ln) -#define TRAC_INIT(des, name, sz) TRAC_INIT_LINE(des, name, sz, __LINE__) - -#endif //! -- NFP Library -#endif //! -- !defined TRACINTERFACE_H diff --git a/src/include/usr/trace/interface.H b/src/include/usr/trace/interface.H new file mode 100644 index 000000000..6d62efca0 --- /dev/null +++ b/src/include/usr/trace/interface.H @@ -0,0 +1,350 @@ +/****************************************************************************** + * IBM Confidential + * + * Licensed Internal Code Source Materials + * + * IBM Flexible Support Processor Licensed Internal Code + * + * (c) Copyright IBM Corp. 2004, 2010 + * + * The source code is for this program is not published or otherwise divested + * of its trade secrets, irrespective of what has been deposited with the + * U.S. Copyright Office. + *****************************************************************************/ + +#ifndef __TRACE_INTERFACE_H +#define __TRACE_INTERFACE_H + +/*!@file interface.H + * @brief Contains macros for trace interface + * + * Note that this file was for the most parted ported in from the fsp-trace + * implementation. + * + * This header file provides a common interface for the Trace + * mechanism. + * + * There are two types of trace, debug and field, that you can use when tracing. + * Debug traces are not enabled by default, they must be enabled by the user. + * Field traces will always be enabled. +*/ + +/******************************************************************************/ +// Includes +/******************************************************************************/ +#include + +/******************************************************************************/ +// Globals/Constants +/******************************************************************************/ +#define ENTER_MRK ">>" +#define EXIT_MRK "<<" +#define ERR_MRK "E>" +#define INFO_MRK "I>" +#define ARG_MRK "A>" + +#define TRAC_COMP_SIZE 16 // Max component name size +#define TRAC_MAX_ARGS 9 // Max number of arguments in trace + + +#define TRACE_DEBUG 1 //Indicates trace is debug +#define TRACE_FIELD 0 //Indicates trace is field + +// check compatibility of header file/macros and preprocessor tracepp +// if tracepp was used +#define TRAC_MACROVER 1 +#ifdef TRAC_TRACEPP +#if !defined(TRAC_PPVER) +#warning fsptrace preprocessor version unknown, might be incompatible with header file +#elif TRAC_PPVER < TRAC_MACROVER +#error fsptrace header file version and preprocessor version dont fit +#endif +#endif + + +/* for any trace_adal_write_all call we need the printf_string in addition to + * the hash value. if tracepp is used it will add a (shortened) printf string, + * otherwise the macros has to add it + */ +#ifdef TRAC_TRACEPP +#define __ALL_HASH(printf_string,num) trace_adal_hash(printf_string,num) +#else +#define __ALL_HASH(printf_string,num) trace_adal_hash(printf_string,num),printf_string +#endif + +/******************************************************************************/ +// Macros +/******************************************************************************/ + +#ifdef TRAC_DEBUG_OUT /* compile out everyones debug traces */ + +#define TRACDCOMP(des,printf_string,args...) do {} while(0) +#define TRACDBIN(des,descString,address,length) do {} while(0) + +#else /* direct them to real function calls */ + +/** + * @fn void TRACDCOMP0(des, printf_string) + * @brief Defines all Debug Component Traces + * + * The user can pass 0 to 9 parameters to the macro. In the field environment, + * these trace calls will be compiled out of the code. Use these for early bringup + * needs. These trace calls are written to a memory buffer. + * + * @param des This is assigned by TRAC_INIT_BUFFER + * @param printf_string String describing the trace entry and providing the + * formatting flags for any parameters passed. + * @param p1,p2... Optional parameters + * + * @return void +*/ + +/* a macro w/o the param number suffix. number is calculated from printf string */ +#define TRACDCOMP(des,printf_string,args...) \ + TRACE::trace_adal_write_all((des),__ALL_HASH(printf_string,-1),__LINE__,TRACE_DEBUG, ##args) + +/** + * @fn void TRACDBIN(des,descString,address,length) + * @brief Defines debug binary trace + * + * The binary trace should be used to write out a section of memory. + * + * @param des This is assigned by TRAC_INIT_BUFFER + * @param descString A string that will be put in front of the binary dump, + * developer assigns anything they want. + * @param address Address of beginning of data to dump. + * @param length length of the binary data. + * + * @return void + +*/ +#define TRACDBIN(des,printf_string,address,len) \ + TRACE::trace_adal_write_bin(des,__ALL_HASH(printf_string,0), \ + __LINE__, \ + address, \ + len, \ + TRACE_DEBUG) +#endif /* TRAC_DEBUG_OUT */ + +/** + * @fn void TRACFCOMP0(des, printf_string) + * @brief Defines all Field Component Traces + * + * The user can pass 0 to 9 parameters to the macro. These trace calls will + * always be written to the trace memory buffer. + * + * @param des This is assigned by TRAC_INIT_BUFFER + * @param printf_string String describing the trace entry and providing the + * formatting flags for any parameters passed. + * @param p1,p2... Optional parameters + * + * @return void +*/ + +/* a macro w/o the param number suffix. number is calculated from printf string */ +#define TRACFCOMP(des,printf_string,args...) \ + TRACE::trace_adal_write_all((des),__ALL_HASH(printf_string,-1),__LINE__,TRACE_FIELD, ##args) + + +/** + * @fn void TRACFBIN(des,descString,address,len) + * @brief Defines field binary trace + * + * The binary trace should be used to write out a section of memory. + * + * @param des This is assigned by TRAC_INIT_BUFFER + * @param descString A string that will be put in front of the binary dump, + * developer assigns anything they want. + * @param address Address of beginning of data to dump. + * @param length lenght of the binary data. + * + * @return void +*/ +#define TRACFBIN(des,printf_string,address,len) \ + TRACE::trace_adal_write_bin(des,__ALL_HASH(printf_string,0), \ + __LINE__, \ + address, \ + len, \ + TRACE_FIELD) + +/** + * @fn void TRAC_INIT_BUFFER(des,comp_name, bufferSize) + * @brief Initializes trace buffer for component + * + * This function must be called before any other trace calls. It + * initializes a buffer for the calling component and returns a trace + * descriptor which is used by the trace calls to find the correct + * buffer to write to. + * + * @param des This is assigned by this function. + * @param comp_name This is the four character name of the component requesting + * the trace buffer. + * @param bufferSize Requested length of the buffer, if 0 is entered the user will + * get default buffer size. + * @return void +*/ +#define TRAC_INIT_BUFFER(des,comp_name, bufferSize) \ + TRACE::trace_adal_init_buffer((des), (comp_name), (bufferSize)) + +/******************************************************************************* + TRAC_INIT: Class for creating trace descriptor object. + + About the macros. + TRAC_INIT -- Called by users, adds __LINE__ for uniqueness. + TRAC_INIT_LINE -- Translates __LINE__ into the line number. Using + macro expansion in this statement would result in + tracInit static g_trac_"__LINE__" + TRAC_INIT_UNIQ -- With line number translated, use the '##' operator to + append number in variable name. +*******************************************************************************/ + +#define TRAC_INIT_UNIQ(des, name, sz, ln) TRACE::TracInit static g_trac_##ln(des, name, sz) +#define TRAC_INIT_LINE(des, name, sz, ln) TRAC_INIT_UNIQ(des, name, sz, ln) +#define TRAC_INIT(des, name, sz) TRAC_INIT_LINE(des, name, sz, __LINE__) + + +/******************************************************************************/ +// Internals - Not to be called or used directly by host boot code +/******************************************************************************/ + + +typedef uint32_t trace_hash_val; // Hash values are 32 bytes + +/* + * @brief Structure is put at beginning of all trace buffers + */ +typedef struct trace_buf_head { + unsigned char ver; /*!< version of this struct (1) */ + unsigned char hdr_len; /*!< size of this struct in bytes */ + unsigned char time_flg; /*!< meaning of timestamp entry field */ + unsigned char endian_flg; /*!< flag for big ('B') or little ('L') endian*/ + char comp[TRAC_COMP_SIZE]; /*!< the buffer name as specified in init call*/ + uint32_t size; /*!< size of buffer, including this struct */ + uint32_t times_wrap; /*!< how often the buffer wrapped */ + uint32_t next_free; /*!< offset of the byte behind the latest entry*/ + uint32_t te_count; /*!< Updated each time a trace is done */ + uint32_t extracted; /*!< Not currently used */ +}trace_buf_head_t; + +/*! + * @brief Timestamp and thread id for each trace entry. + */ +typedef struct trace_entry_stamp { + //uint32_t tbh; /*!< timestamp upper part */ + //uint32_t tbl; /*!< timestamp lower part */ + uint32_t tb[2]; + //uint64_t tb; + uint32_t tid; /*!< process/thread id */ +}trace_entry_stamp_t; + +/* + * @brief Structure is used by adal app. layer to fill in trace info. + */ +typedef struct trace_entry_head { + uint16_t length; /*!< size of trace entry */ + uint16_t tag; /*!< type of entry: xTRACE xDUMP, (un)packed */ + uint32_t hash; /*!< a value for the (format) string */ + uint32_t line; /*!< source file line number of trace call */ +}trace_entry_head_t; + +/* + * @brief Parameter traces can be all contained in one write. + */ +typedef struct trace_entire_entry { + trace_entry_stamp_t stamp; + trace_entry_head_t head; + uint64_t args[TRAC_MAX_ARGS + 1]; +} trace_entire_entry_t; + + +/* + * @brief Binary first writes header and time stamp. + */ +typedef struct trace_bin_entry { + trace_entry_stamp_t stamp; + trace_entry_head_t head; +} trace_bin_entry_t; + +/** + * @brief New version name of this typedef + */ +typedef trace_buf_head_t trace_desc_t; + +namespace TRACE +{ + +/** + * @brief Initialize a trace buffer + * + * @param o_td[out] Trace descriptor to initialize + * @param i_comp[in] Component name for trace buffer + * @param i_size[in] Size to allocate for trace buffer + * + * @return void + */ +void trace_adal_init_buffer(trace_desc_t **o_td, + const char* i_comp, + const size_t i_size ); + +/** + * @brief Write component trace out to input buffer + * + * @param io_td[inout] Trace descriptor of buffer to write to. + * @param i_hash[in] Descriptive string hash value + * @param i_fmt [in] Formatting string + * @param i_line[in] Line number trace was done at + * @param i_type[in] Type of trace (TRACE_DEBUG, TRACE_FIELD) + * + * @return void + */ +void trace_adal_write_all(trace_desc_t *io_td, + const trace_hash_val i_hash, + const char * i_fmt, + const uint32_t i_line, + const int32_t i_type, ...); + +/** + * @brief Write binary data out to trace buffer + * + * @param io_td[inout] Trace descriptor of buffer to write to. + * @param i_hash[in] Descriptive string hash value + * @param i_line[in] Line number trace was done at + * @param i_ptr[in] Pointer to binary data + * @param i_size[in] Size of binary data + * @param i_type[in] Type of trace (TRACE_DEBUG, TRACE_FIELD) + * + * @return void + */ +void trace_adal_write_bin(trace_desc_t * io_td, + const trace_hash_val i_hash, + const uint32_t i_line, + const void *i_ptr, + const uint32_t i_size, + const int32_t type); + + +/******************************************************************************/ +// Allow users to init trace buffer outside of a function +/******************************************************************************/ +class TracInit +{ + public: + + /*------------------------------------------------------------------------*/ + /* Constructor */ + /*------------------------------------------------------------------------*/ + + TracInit(trace_desc_t **o_td, const char *i_comp,const size_t i_size) + { + TRAC_INIT_BUFFER(o_td,i_comp,i_size); + } + + ~TracInit() + { + } + +}; + +}; // Namespace + +#endif //! -- !defined __TRACE_INTERFACE_H diff --git a/src/usr/example/example.C b/src/usr/example/example.C index 6aa188f3c..193bbb9d3 100644 --- a/src/usr/example/example.C +++ b/src/usr/example/example.C @@ -1,18 +1,44 @@ +/* + * Change Log ****************************************************************** + * Flag Defect/Feature User Date Description + * ------ -------------- ---------- ----------- ---------------------------- + * $ag000 andrewg 04/01/2011 Updated + * +*/ + #include #include #include #include -#include +#include //static mutex_t value = mutex_create(); - -trace_desc_t g_exampleTrace; -TRAC_INIT(&g_exampleTrace, "EXAMPLE", 4096); +trace_desc_t *g_trac_test = NULL; +TRAC_INIT(&g_trac_test, "EXAMPLE", 4096); extern "C" void _start(void*) { printk("Executing example module.\n"); - TRACFCOMP(g_exampleTrace, "Executing example module: %d", task_gettid()); + + // Component trace tests + //for(uint32_t i=0;i<100;i++) + //{ + uint32_t i=0; + TRACFCOMP(g_trac_test, "Executing example module: %d", task_gettid()); + TRACFCOMP(g_trac_test, "Test 2: %d %u %c", i,i+1,'a'); + TRACFCOMP(g_trac_test, "Test 3: %d %u 0x%X", i+2,i+3, + 0x123456789ABCDEF0); + //} + + // Pointer trace + //TRACFCOMP(g_trac_test, "Pointer Test: %llp",g_trac_test); + + // Binary Trace + TRACFBIN(g_trac_test,"Binary dump of trace descriptor", + g_trac_test,sizeof(trace_desc_t)); + + + task_end(); } diff --git a/src/usr/trace/trace.C b/src/usr/trace/trace.C index 38d9c5957..33a3de888 100644 --- a/src/usr/trace/trace.C +++ b/src/usr/trace/trace.C @@ -1,54 +1,685 @@ -#include -#include +/* TODO + * - Add support in for debug traces + * - Time support + * - FORMAT_PRINTF support + * + * + */ + +/******************************************************************************/ +// Includes +/******************************************************************************/ +#include #include #include +#include +#include +#include +#include +#include + +#include "trace.H" + +/******************************************************************************/ +// Namespace +/******************************************************************************/ +namespace TRACE +{ + +/******************************************************************************/ +// Globals/Constants +/******************************************************************************/ + +#define TRAC_TIME_REAL 0 // upper 32 = seconds, lower 32 = microseconds +#define TRAC_TIME_50MHZ 1 +#define TRAC_TIME_200MHZ 2 +#define TRAC_TIME_167MHZ 3 // 166666667Hz +#define COMP_NAME_SIZE 16 + +// Global value used as a "timer" to provide tracing point32_t of reference +uint32_t g_trac_time_high = 0; +uint32_t g_trac_time_low = 0; + +// Global Mutex +mutex_t g_trac_mutex; + +// Global buffer +trace_desc_t *g_trac_global = NULL; + -#include "tracebuffer.H" -int32_t trace_adal_init_buffer(trace_desc_t * td, const char* comp, - const size_t size ) +/******************************************************************************/ +// trace_adal_init_buffer +/******************************************************************************/ +void trace_adal_init_buffer(trace_desc_t **o_td, const char* i_comp, + const size_t i_size ) { - // For now, just store the component name. - *td = (trace_desc_t) comp; - return 0; + /*------------------------------------------------------------------------*/ + /* Local Variables */ + /*------------------------------------------------------------------------*/ + + /*------------------------------------------------------------------------*/ + /* Code */ + /*------------------------------------------------------------------------*/ + if(*o_td == NULL) + { + if(g_trac_global == NULL) + { + // TODO - How do I make this pre-emption/mutli-threading safe? + g_trac_mutex = mutex_create(); + + printk("Global trace buffer is NULL so create and init it!\n"); + + g_trac_global = (trace_desc_t *)(malloc(PAGE_SIZE)); + char l_g_comp[TRAC_COMP_SIZE] = "GLOBAL"; + trace_init_values_buffer(g_trac_global, + l_g_comp); + + } + + // Just assign it to the global buffer since we only have + // one buffer + *o_td = g_trac_global; + printk("Assigned input trace descriptor to global buffer\n"); + } + + printk("*td = %lu\n",(unsigned long int)*o_td); + + return; } -int32_t trace_adal_write_all(const trace_desc_t td, - const enum trace_hash_val hash, - const char * fmt, - const uint32_t line, - const int32_t type, ...) +/******************************************************************************/ +// trace_init_values_buffer +/******************************************************************************/ +void trace_init_values_buffer(trace_desc_t *o_buf,const char *i_comp) { + /*------------------------------------------------------------------------*/ + /* Local Variables */ + /*------------------------------------------------------------------------*/ + + /*------------------------------------------------------------------------*/ + /* Code */ + /*------------------------------------------------------------------------*/ + + // Initialize it to all 0's + memset(o_buf,0,(size_t)PAGE_SIZE); + + (o_buf)->ver = TRACE_BUF_VERSION; + (o_buf)->hdr_len = sizeof(trace_buf_head_t); + (o_buf)->time_flg = TRAC_TIME_167MHZ; + (o_buf)->endian_flg = 'B'; // Big Endian + memcpy((o_buf)->comp,i_comp,(size_t)COMP_NAME_SIZE); + (o_buf)->size = PAGE_SIZE; + (o_buf)->times_wrap = 0; + (o_buf)->next_free = sizeof(trace_buf_head_t); + + return; +} + +/******************************************************************************/ +// trace_adal_write_all +/******************************************************************************/ +void trace_adal_write_all(trace_desc_t *io_td, + const trace_hash_val i_hash, + const char * i_fmt, + const uint32_t i_line, + const int32_t i_type, ...) +{ + /*------------------------------------------------------------------------*/ + /* Local Variables */ + /*------------------------------------------------------------------------*/ + int64_t l_rc = 0; + uint32_t l_entry_size = 0; + trace_entire_entry_t l_entry; + + /*------------------------------------------------------------------------*/ + /* Code */ + /*------------------------------------------------------------------------*/ + // This code is incorrect for determining formatting but will work for now. - size_t size = 0; - const char* _fmt = fmt; + uint32_t num_args = 0; + const char* _fmt = i_fmt; while ('\0' != *_fmt) { if ('%' == *_fmt) - size++; + num_args++; _fmt++; } - traceEntry* entry = - Singleton::instance().claimEntry(sizeof(traceEntry) + - sizeof(uint64_t) * size); + if(num_args > TRAC_MAX_ARGS) + { + printk ("Too many arguments: %u",num_args); + } + else if(io_td != NULL) + { + + // Calculate total space needed + l_entry_size = sizeof(trace_entry_stamp_t); + l_entry_size += sizeof(trace_entry_head_t); + + // We always add the size of the entry at the end of the trace entry + // so the parsing tool can easily walk the trace buffer stack so we + // need to add that on to total size + l_entry_size += sizeof(uint32_t); + + // Now add on size for acutal number of arguments we're tracing + l_entry_size += (num_args * sizeof(uint64_t)); + + // Word align the entry + l_entry_size = (l_entry_size + 3) & ~3; + + // Fill in the entry structure + l_entry.stamp.tid = (uint32_t)task_gettid(); // What is response to this in AME code? + + // Length is equal to size of data + l_entry.head.length = (num_args * sizeof(uint64_t)); + l_entry.head.tag = TRACE_FIELDTRACE; + l_entry.head.hash = i_hash; + l_entry.head.line = i_line; - entry->component = (uint64_t) td; - entry->tid = task_gettid(); - entry->length = sizeof(uint64_t) * size; - entry->hash = hash; - entry->timestamp = getTB(); - entry->line = line; + // Time stamp + *(l_entry.stamp.tb) = getTB(); - uint64_t* data = &entry->values[0]; + uint64_t* data = &l_entry.args[0]; - va_list args; - va_start(args, type); - for (size_t i = 0; i < size; i++) + va_list args; + va_start(args, i_type); + for (size_t i = 0; i < num_args; i++) + { + *data = va_arg(args, uint64_t); + data++; + } + va_end(args); + + // Now put total size at end of buffer + // Note that fsp-trace assumes this to be a 32 bit long word + uint32_t *l_size = (uint32_t *)&(l_entry.args[num_args]); + *l_size = l_entry_size; + + printk("l_entry_size = %u ttid = %u\n",l_entry_size,l_entry.stamp.tid); + + // We now have total size and need to reserve a part of the trace + // buffer for this + + // CRITICAL REGION START + l_rc = mutex_lock(g_trac_mutex); + if(l_rc != 0) + { + printk("trace_adal_write_all: Failed to get mutex"); + } + else + { + // Update the entry count + io_td->te_count++; + + trace_write_data(io_td, + (void *)&l_entry, + l_entry_size); + + l_rc = mutex_unlock(g_trac_mutex); + if(l_rc != 0) + { + // Badness + printk("trace_adal_write_all: Failed to release mutex"); + } + } + // CRITICAL REGION END + } + else { - *data = va_arg(args, uint64_t); - data++; + printk("trace_adal_write_all: User passed invalid parameter"); } - va_end(args); - return 0; + + return; } + +/******************************************************************************/ +// trace_adal_write_bin +/******************************************************************************/ +void trace_adal_write_bin(trace_desc_t *io_td,const trace_hash_val i_hash, + const uint32_t i_line, + const void *i_ptr, + const uint32_t i_size, + const int32_t type) +{ + /*------------------------------------------------------------------------*/ + /* Local Variables */ + /*------------------------------------------------------------------------*/ + int64_t l_rc = 0; + uint32_t l_entry_size = 0; + trace_bin_entry_t l_entry; + + /*---------------------------------------------------------------------- --*/ + /* Code */ + /*------------------------------------------------------------------------*/ + do + { + + if((io_td == NULL) || (i_ptr == NULL) || (i_size == 0)) + { + break; + } + + // Calculate total space needed + l_entry_size = sizeof(trace_entry_stamp_t); + l_entry_size += sizeof(trace_entry_head_t); + + // We always add the size of the entry at the end of the trace entry + // so the parsing tool can easily walk the trace buffer stack so we + // need to add that on to total size + l_entry_size += sizeof(uint32_t); + + // Now add on size for acutal size of the binary data + l_entry_size += i_size; + + // Word align the entry + l_entry_size = (l_entry_size + 3) & ~3; + + // Fill in the entry structure + l_entry.stamp.tid = (uint32_t)task_gettid(); // What is response to this in AME code? + + // Length is equal to size of data + l_entry.head.length = i_size; + l_entry.head.tag = TRACE_FIELDBIN; + l_entry.head.hash = i_hash; + l_entry.head.line = i_line; + + // We now have total size and need to reserve a part of the trace + // buffer for this + + // Time stamp + *(l_entry.stamp.tb) = getTB(); + + // CRITICAL REGION START + l_rc = mutex_lock(g_trac_mutex); + if(l_rc != 0) + { + printk("trace_adal_write_bin: Failed to get mutex"); + } + else + { + + // Increment trace counter + io_td->te_count++;; + + // First write the header + trace_write_data(io_td, + (void *)&l_entry, + sizeof(l_entry)); + + // Now write the actual binary data + trace_write_data(io_td, + i_ptr, + i_size); + + // Now write the size at the end + trace_write_data(io_td, + (void *)&l_entry_size, + sizeof(l_entry_size)); + + // CRITICAL REGION END + l_rc = mutex_unlock(g_trac_mutex); + if(l_rc != 0) + { + // Badness + printk("trace_adal_write_bin: Failed to release mutex"); + } + } + + }while(0); + + return; +} + +/******************************************************************************/ +// trace_write_data +/******************************************************************************/ +void trace_write_data(trace_desc_t *io_td, + const void *i_ptr, + const uint32_t i_size) +{ + /*------------------------------------------------------------------------*/ + /* Local Variables */ + /*------------------------------------------------------------------------*/ + uint32_t l_total_size = i_size; + void *l_buf_ptr = NULL; + uint32_t l_offset = 0; + + /*------------------------------------------------------------------------*/ + /* Code */ + /*------------------------------------------------------------------------*/ + + do + { + + if(i_size > PAGE_SIZE) + { + printk("trace_write_data: Input size to large!"); + break; + } + + if((io_td->next_free + l_total_size) > PAGE_SIZE) + { + // copy what we can to end + l_buf_ptr = (char *)io_td + io_td->next_free; + l_buf_ptr = (void *) ( ((uint64_t) l_buf_ptr + 3) & ~3); + l_offset = PAGE_SIZE-io_td->next_free; + memcpy(l_buf_ptr,i_ptr,(size_t)l_offset); + + l_total_size -= l_offset; + + // Now adjust the main header of buffer + io_td->times_wrap++; + io_td->next_free = io_td->hdr_len; + } + + l_buf_ptr = (char *)io_td + io_td->next_free; + + // Word align the write - total size includes this allignment + l_buf_ptr = (void *) ( ((uint64_t) l_buf_ptr + 3) & ~3); + + memcpy(l_buf_ptr,(char *)i_ptr + l_offset,l_total_size); + + // Make sure size is correct for word allignment + // Note that this works with binary trace because only the binary data + // has the potential to be un-word aligned. If two parts of the binary + // trace had this problem then this code would not work. + l_total_size = (l_total_size + 3) & ~3; + io_td->next_free += l_total_size; + + }while(0); + + return; + +} + +/******************************************************************************/ +// TRAC_get_td - TODO +/******************************************************************************/ +trace_desc_t * trace_get_td(const char *i_comp) +{ + /*------------------------------------------------------------------------*/ + /* Local Variables */ + /*------------------------------------------------------------------------*/ + //uint32_t l_num_des = 0; + //uint32_t i=0; + //trace_desc_t * l_td = NULL; + + /*------------------------------------------------------------------------*/ + /* Code */ + /*------------------------------------------------------------------------*/ + +#if 0 + l_num_des = sizeof(g_des_array) / sizeof(trace_descriptor_array_t); + + for(i=0;icomp,(size_t)COMP_NAME_SIZE) == 0) + { + // Found the component + l_td = g_des_array[i].entry; + break; + } + } +#endif + // Only one trace buffer currently + return(g_trac_global); +} + +/******************************************************************************/ +// trace_get_buffer - TODO +/******************************************************************************/ +int32_t trace_get_buffer(const trace_desc_t *i_td_ptr, + void *o_data) +{ + /*------------------------------------------------------------------------*/ + /* Local Variables */ + /*------------------------------------------------------------------------*/ + int64_t l_rc = 0; + + /*------------------------------------------------------------------------*/ + /* Code */ + /*------------------------------------------------------------------------*/ + + if((i_td_ptr) && (o_data != NULL)) + { + // Get the lock + // TODO Mutex +#if 0 + l_rc = UTIL_MUTEX_GET(&g_trac_mutex,TRAC_INTF_MUTEX_TIMEOUT); + if(l_rc != 0) + { + // Badness + printk("TRAC_get_buffer: Failed to get mutex"); + } + else + { + l_rc = SUCCESS; + } +#endif + // Copy it's buffer into temp one + memcpy(o_data,i_td_ptr,(size_t)PAGE_SIZE); + + // Always try to release even if error above + // TODO - mutex + //UTIL_MUTEX_PUT(&g_trac_mutex); + } + else + { + printk("TRAC_get_buffer: Invalid parameter passed by caller"); + } + + return(l_rc); +} + +#if 0 +/******************************************************************************/ +// trace_get_buffer_partial - TODO +/******************************************************************************/ +// TODO +int32_t trace_get_buffer_partial(const trace_desc_t *i_td_ptr, + void *o_data, + uint32_t *io_size) +{ + /*------------------------------------------------------------------------*/ + /* Local Variables */ + /*------------------------------------------------------------------------*/ + int32_t l_rc = 0; + char *l_full_buf = NULL; + trace_desc_t *l_head = NULL; + uint32_t l_part_size = 0; + + /*------------------------------------------------------------------------*/ + /* Code */ + /*------------------------------------------------------------------------*/ + + do + { + + if((i_td_ptr == NULL) || (o_data == NULL) || (io_size == NULL)) + { + printk("trace_get_buffer_partial: Invalid parameter passed by caller"); + l_rc = TRAC_INVALID_PARM; + if(io_size != NULL) + { + *io_size = 0; + } + break; + } + + if(*io_size < sizeof(trace_buf_head_t)) + { + // Need to at least have enough space for the header + printk("trace_get_buffer_partial: *io_size to small"); + l_rc = TRAC_MEM_BUFF_TO_SMALL; + *io_size = 0; + break; + } + + // First get the full buffer + l_rc = tx_byte_allocate(&tpmd_trac_debug_byte_pool, + (void **)&l_full_buf, + TPMD_TRACE_BUFFER_SIZE, + TX_NO_WAIT); + if(l_rc != TX_SUCCESS) + { + printk("trace_get_buffer_partial: Failure allocating memory for temp buffer"); + *io_size = 0; + l_rc = TRAC_MEM_ALLOC_FAIL; + break; + } + + l_rc = trace_get_buffer(i_td_ptr, + l_full_buf); + if(l_rc != 0) + { + printk("trace_get_buffer_partial: Failure in call to TRAC_get_buffer()"); + *io_size = 0; + break; + } + + // Now that we have full buffer, adjust it to be requested size + memset(o_data,0,(size_t)*io_size); + + if(*io_size > TPMD_TRACE_BUFFER_SIZE) + { + // It fits + *io_size = TPMD_TRACE_BUFFER_SIZE; + memcpy(o_data,l_full_buf,(size_t)*io_size); + break; + } + + l_head = (trace_desc_t *)l_full_buf; + memcpy(o_data,l_full_buf,(size_t)(l_head->hdr_len)); + l_head = (trace_desc_t *)o_data; + l_head->size = *io_size; + + if((l_head->next_free == l_head->hdr_len) && (l_head->times_wrap == 0)) + { + // No data in buffer so just return what we have + break; + } + + if(l_head->next_free > *io_size) + { + // We can't even fit in first part of buffer + // Make sure data size is larger than header length + // Otherwise, we will be accessing beyond memory + if(*io_size < l_head->hdr_len) + { + l_rc = TRAC_DATA_SIZE_LESS_THAN_HEADER_SIZE; + break; + } + l_part_size = *io_size - l_head->hdr_len; + + memcpy((UCHAR *)o_data+l_head->hdr_len, + l_full_buf+l_head->next_free-l_part_size, + (size_t)l_part_size); + + // Set pointer at beginning because this will be a + // "just wrapped" buffer. + l_head->next_free = l_head->hdr_len; + + // Buffer is now wrapped because we copied max data into it. + if(!l_head->times_wrap) + { + l_head->times_wrap = 1; + } + } + else + { + // First part of buffer fits fine + memcpy((UCHAR *)o_data+l_head->hdr_len, + l_full_buf+l_head->hdr_len, + (size_t)(l_head->next_free - l_head->hdr_len)); + + + // If it's wrapped then pick up some more data + if(l_head->times_wrap) + { + // Figure out how much room we have left + l_part_size = *io_size - l_head->next_free; + + memcpy((UCHAR *)o_data+l_head->next_free, + l_full_buf+TPMD_TRACE_BUFFER_SIZE-l_part_size, + (size_t)l_part_size); + + } + else + { + // No more data to get, make buffer look as small + // as possible + // add '+4' to avoid the need to mark it as wrapped + // (if the last byte of the buffer is filled + // next_free has to pointer to the first byte) + + l_head->size = l_head->next_free + 4; + + } + + } + + *io_size = l_head->size; + + }while(0); + + if(l_full_buf != NULL) + { + tx_byte_release(l_full_buf); + } + + return(l_rc); +} +#endif + +/******************************************************************************/ +// trace_reset_buf - TODO +/******************************************************************************/ +int32_t trace_reset_buf() +{ + /*------------------------------------------------------------------------*/ + /* Local Variables */ + /*------------------------------------------------------------------------*/ + int64_t l_rc = 0; + //uint32_t l_num_des = 0; + //uint32_t i=0; + + /*------------------------------------------------------------------------*/ + /* Code */ + /*------------------------------------------------------------------------*/ + + // Get mutex so no one traces +#if 0 + // TODO + l_rc = UTIL_MUTEX_GET(&g_trac_mutex,TRAC_INTF_MUTEX_TIMEOUT); + if(l_rc != TX_SUCCESS) + { + printk("trace_reset_buf: Failure trying to get mutex"); + // Badness + } + else + { + l_num_des = sizeof(g_des_array) / sizeof(trace_descriptor_array_t); + + for(i=0;i +#include + +namespace TRACE +{ + +/******************************************************************************/ +// Globals/Constants +/******************************************************************************/ + +#define TRACE_BUF_VERSION 0x01; // Trace buffer version +#define TRACE_FIELDTRACE 0x4654 // Field Trace - "FT" +#define TRACE_FIELDBIN 0x4644 // Binary Field Trace - "FD" + +#define TRACE_DEBUG_ON 1 //Set to this when debug trace on +#define TRACE_DEBUG_OFF 0 //Set to this when debug trace off + + +/******************************************************************************/ +// Typedef/Enumerations +/******************************************************************************/ + +/******************************************************************************/ +// Function Prototypes +/******************************************************************************/ + +/** + * @brief Initialize a new trace buffer + * + * Internal function responsible setting up the defaults in a newly created + * trace buffer. + * + * @param[out] o_buf Trace descriptor of component buffer to initialize. + * @param[in] i_comp Component name + * + * @return void + * + */ +void trace_init_values_buffer(trace_desc_t *o_buf, + const char *i_comp); + + +/** + * @brief Write the trace data into the buffer + * + * Internal function responsible for copying the trace data into the appropriate + * buffer. + * + * @param[inout] io_td Trace descriptor of component buffer to write to. + * @param[in] i_ptr Pointer to data to copy into the trace buffer. + * @param[in] i_size Size of the i_ptr data to copy into the buffer. + * + * @return void + * + */ +void trace_write_data(trace_desc_t * io_td, + const void *i_ptr, + const uint32_t i_size); + + +/** + * @brief Retrieve full trace buffer for component i_comp + * + * This function assumes memory has already been allocated for + * the full trace buffer in o_data. + * + * @param i_td_ptr Trace descriptor of buffer to retrieve. + * @param o_data Pre-allocated pointer to where data will be stored. + * + * TODO - Not Supported Yet + * + * @return Non-zero return code on error + */ +int32_t trace_get_buffer(const trace_desc_t * i_td_ptr, + void *o_data); + +/** + * @brief Retrieve partial trace buffer for component i_comp + * + * This function assumes memory has already been allocated for + * the trace buffer (size io_size). This function will copy + * in up to io_size in bytes to the buffer and set io_size + * to the exact size that is copied in. + * + * TODO - Not Supported Yet + * + * @param i_td_ptr Trace descriptor of buffer to retrieve. + * @param o_data Pre-allocated pointer to where data will be stored. + * @param io_size Size of trace data to retrieve (input) + * Actual size of trace data stored (output) + * + * @return Non-zero return code on error + */ +int32_t trace_get_buffer_partial(const trace_desc_t * i_td_ptr, + void *o_data, + uint32_t *io_size); + +/** + * @brief Retrieve trace descriptor for input component name + * + * @param i_comp Component name to retrieve trace descriptor for. + * + * TODO - Not Supported Yet + * + * @return Valid trace descriptor on success, NULL on failure. + */ +trace_desc_t * trace_get_td(const char *i_comp); + +/** + * @brief Reset all trace buffers + * + * TODO - Not Supported Yet + * + * @return Non-zero return code on error + */ +int32_t trace_reset_buf(void); + +} // namespace TRACE + +#endif diff --git a/src/usr/trace/tracebuffer.C b/src/usr/trace/tracebuffer.C index 5e5b697a1..3a56fde7b 100644 --- a/src/usr/trace/tracebuffer.C +++ b/src/usr/trace/tracebuffer.C @@ -8,6 +8,8 @@ TracePage* TracePage::setNext(TracePage* new_next) traceEntry* TracePage::claimEntry(size_t size) { + // this->size will eventually wrap and it will suddenly look like there + // is free space? size_t position = __sync_fetch_and_add(&this->size, size); if (position > (PAGE_SIZE - sizeof(TracePage))) { -- cgit v1.2.1