Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 96 additions & 7 deletions sofia-ovp/FI.sh
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,93 @@ function generateFaultList2 {
fi
# Not generating faults =register
if [[ "$FAULT_TYPE" == "memory" ]]; then
CMD_FAULT_LIST="$CMD_FAULT_LIST --memlowaddress=$TARGET_MEM_BASE --memhighaddress=$TARGET_MEM_SIZE"
# Get the memory range from a target ELF section
if [[ "$WORKLOAD_TYPE" == "WORKLOAD_BAREMETAL" ]] && [[ -n "$APPLICATIONS_NAME" ]] && [[ -n "$TARGET_MEM_SECTION" ]]; then
echo "Target section: [$TARGET_MEM_SECTION]"

# Select appropriate readelf based on architecture
if [[ "$ARCHITECTURE" =~ ^RISCV.* ]]; then
TARGET_READELF=$RISCV_TOOLCHAIN_BAREMETAL'/bin/'$RISCV_TOOLCHAIN_BAREMETAL_PREFIX'-readelf'
else
TARGET_READELF=$AARCH64_TOOLCHAIN_BAREMETAL'/bin/aarch64-none-elf-readelf'
fi

if ! $TARGET_READELF -S "$APPLICATIONS_NAME" > applicationSections 2>/dev/null; then
echo "Error: Failed to read ELF sections from $APPLICATIONS_NAME"
exit 1
fi

# Function to extract section information
extract_section_info() {
local section_name="$1"
local section_info=$(grep -A 1 "\\.${section_name#.} " applicationSections)

if [[ -n "$section_info" ]]; then
local address=$(echo "$section_info" | head -n1 | tr -s ' ' | cut -d' ' -f6)
local size=$(echo "$section_info" | tail -n1 | tr -s ' ' | cut -d' ' -f2)
echo "Found $section_name section at address: $address, size: $size"

# Return values via global variables
SECTION_ADDRESS="$address"
SECTION_SIZE="$size"
return 0
else
echo "Warning: Section $section_name not found"
SECTION_ADDRESS=""
SECTION_SIZE=""
return 1
fi
}

# Extract section information
if [[ "$TARGET_MEM_SECTION" == ".stack" ]]; then
# Stack range comes from golden run SP tracking, not from ELF
if [[ ! -f goldinformation ]]; then
echo "Error: goldinformation not found. Run golden first."
exit 1
fi
SP_MIN=$(grep "Stack SP Min=" goldinformation | cut -d'=' -f2)
SP_INITIAL=$(grep "Stack SP Initial=" goldinformation | cut -d'=' -f2)
if [[ -z "$SP_MIN" || -z "$SP_INITIAL" ]]; then
echo "Error: Stack range not found in goldinformation."
echo " Re-run golden with updated faultInjector/intercept."
exit 1
fi
MEM_LOW="$SP_MIN"
MEM_HIGH="$SP_INITIAL"
STACK_SIZE=$((MEM_HIGH - MEM_LOW))
echo "Stack range: [$MEM_LOW] to [$MEM_HIGH] ($STACK_SIZE bytes)"
CMD_FAULT_LIST="$CMD_FAULT_LIST --memlowaddress=$MEM_LOW --memhighaddress=$MEM_HIGH"
elif extract_section_info "$TARGET_MEM_SECTION"; then
ADDRESS="$SECTION_ADDRESS"
SIZE="$SECTION_SIZE"

# Calculate the final memory range
# Start: beginning of the section
# End: end of the section (address + size)
MEM_START_HEX="$ADDRESS"
MEM_END_HEX=$(printf "%016x" $((0x$ADDRESS + 0x$SIZE)))

echo "Memory range calculated:"
echo " Final range: 0x$MEM_START_HEX to 0x$MEM_END_HEX"

# Convert addresses to decimal for the fault list generator
MEM_LOW=$(echo "ibase=16;obase=A; $(echo "$MEM_START_HEX" | tr "a-z" "A-Z")" | bc)
MEM_HIGH=$(echo "ibase=16;obase=A; $(echo "$MEM_END_HEX" | tr "a-z" "A-Z")" | bc)

# Log memory details
echo "$CURRENT_APPLICATION Memory Range for Physical Memory Fault Injection on $ARCHITECTURE" >> memory_details.log
echo "application, section, mem_start, mem_end, range_size_bytes" >> memory_details.log
echo "$CURRENT_APPLICATION, $TARGET_MEM_SECTION, $MEM_LOW, $MEM_HIGH, $((MEM_HIGH - MEM_LOW))" >> memory_details.log
CMD_FAULT_LIST="$CMD_FAULT_LIST --memlowaddress=$MEM_LOW --memhighaddress=$MEM_HIGH"
else
echo "Error: Could not find section $TARGET_MEM_SECTION"
exit 1
fi
else
# Use provided TARGET_MEM_BASE and TARGET_MEM_SIZE for non-baremetal or when not extracting from ELF
CMD_FAULT_LIST="$CMD_FAULT_LIST --memlowaddress=$TARGET_MEM_BASE --memhighaddress=$TARGET_MEM_SIZE"
fi
GENERATE_FAULT_LIST_DISTR=0 # Don't necessary
fi

Expand Down Expand Up @@ -503,12 +589,15 @@ function configureCommands {
[[ "$ARCHITECTURE" = 'ARM_CORTEX_M33F' ]] ; then
CMD_OVP="$CMD_OVP --override compatibility=nopBKPT "
fi
#~ elif [[ "$ARCHITECTURE" = 'ARM_CORTEX_A53' ]] || [[ "$ARCHITECTURE" = 'ARM_CORTEX_A57' ]] || [[ "$ARCHITECTURE" = 'ARM_CORTEX_A72' ]]; then
#~ CMD_OVP="$CMD_OVP"
#~ elif [[ "$ARCHITECTURE" = 'ARM_CORTEX_M0' ]]; then
#~ CMD_OVP="$CMD_OVP --override compatibility=nopSVC "
#~ fi


# Enable floating-point for RISC-V variants with an FPU
if [[ "$ARCHITECTURE" = 'RISCV32GC' ]] || \
[[ "$ARCHITECTURE" = 'RISCV64GC' ]] || \
[[ "$ARCHITECTURE" =~ RISCV.*F.* ]] || \
[[ "$ARCHITECTURE" =~ RISCV.*D.* ]]; then
CMD_OVP="$CMD_OVP --override mstatus_FS=1 "
fi

;; # End baremetal
WORKLOAD_LINUX)
case "$ARCHITECTURE" in
Expand Down
9 changes: 8 additions & 1 deletion sofia-ovp/gui/classification.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,14 @@ def possibleregisters(self,environment):
elif environment==environmentsE.ovpmips.name:
self.listOfpossibleRegisters = ["at","v0","v1","a0","a1","a2","a3","t0","t1","t2","t3","t4","t5","t6","t7","s0","s1","s2","s3","s4","s5","s6","s7","t8","t9","k0","k1","gp","sp","s8","ra","pc"]
elif environment==environmentsE.riscv.name:
self.listOfpossibleRegisters = ["ra","sp","gp","tp","t0","t1","t2","s0","s1","a0","a1","a2","a3","a4","a5","a6","a7","s2","s3","s4","s5","s6","s7","s8","s9","s10","s11","t3","t4","t5","t6","pc"]
self.listOfpossibleRegisters = [
# integer ABI
"ra","sp","gp","tp","t0","t1","t2","s0","s1","a0","a1","a2","a3","a4","a5","a6","a7",
"s2","s3","s4","s5","s6","s7","s8","s9","s10","s11","t3","t4","t5","t6","pc",
# floating-point ABI
"ft0","ft1","ft2","ft3","ft4","ft5","ft6","ft7","fs0","fs1",
"fa0","fa1","fa2","fa3","fa4","fa5","fa6","fa7",
"fs2","fs3","fs4","fs5","fs6","fs7","fs8","fs9","fs10","fs11","ft8","ft9","ft10","ft11"]
else:
parser.error("One environment is required")

Expand Down
12 changes: 11 additions & 1 deletion sofia-ovp/gui/faultlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,17 @@ def createfaultlist(self):
possibletargetcores.remove(faultCore)

# insertion time -- each core has a different instruction count
faultTime = randint(0, int(int(coreinstcount[faultCore]) - int(corebegin[faultCore])) ) + int(corebegin[faultCore])
# Apply minimum fault time if specified (skip early initialization)
minFaultTime = int(corebegin[faultCore])
if hasattr(self.options, 'minfaulttime') and self.options.minfaulttime > 0:
minFaultTime = max(minFaultTime, int(corebegin[faultCore]) + self.options.minfaulttime)

maxFaultTime = int(coreinstcount[faultCore])
if minFaultTime >= maxFaultTime:
# If min time exceeds execution, use the last 10% of execution
minFaultTime = int(maxFaultTime * 0.9)

faultTime = randint(minFaultTime, maxFaultTime)

#
# Fault target and mask for each fault type
Expand Down
3 changes: 2 additions & 1 deletion sofia-ovp/gui/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ def __init__(self):
self.options.append(optionsFIM(name="Trace Symbol", buttom="string", buttomobj=None, entry=None, module="TR", command="--tracesymbol", action="store", type="string", dest="tracesymbol", default="", help="Trace:"))
self.options.append(optionsFIM(name="Number of Bit Flips", buttom="string", buttomobj=None, entry=None, module="FI", command="--bitflips", action="store", type="int", dest="bitFlips", default=1, help="Number of bits to flip"))
self.options.append(optionsFIM(name="Sequential Bit Flips", buttom="tick", buttomobj=None, entry=None, module="FI", command="--seqflip", action="store_true", dest="sequentialBits", default=False, help="Flip n sequential bits"))

self.options.append(optionsFIM(name="Min Fault Time", buttom="string", buttomobj=None, entry=None, module="FI", command="--minfaulttime", action="store", type="int", dest="minfaulttime", default="0", help="Fault generation: minimum instruction count before starting fault injection (skip early initialization)"))

def getOptionL(self):
return self.options

Expand Down
18 changes: 16 additions & 2 deletions sofia-ovp/platformOP/commonStructsAndEnumerators.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,25 @@
/////////////////////////////////////////////////////////////////////////

#define END_LIST "EndList@"
char possibleRegisters[50][10];
// Working buffer that holds the active arch's register list (copied in faultInjector.c).
// Must cover the largest list: ARMv8 int(33)+SIMD(32)+END = 66 entries already exceed 50.
// MAX_REGISTERS gives headroom; bump it if a longer list is ever added.
#define MAX_REGISTERS 80
#define MAX_REGISTER_NAME_LEN 10
char possibleRegisters[MAX_REGISTERS][MAX_REGISTER_NAME_LEN];
int numberOfRegistersToCompare;
const char possibleRegistersV7[][10] ={"r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12","sp","lr","pc","d0","d1","d2","d3","d4","d5","d6","d7","d8","d9","d10","d11","d12","d13","d14","d15",END_LIST};
const char possibleRegistersV8[][10] ={"x0","x1","x2","x3","x4","x5","x6","x7","x8","x9","x10","x11","x12","x13","x14","x15","x16","x17","x18","x19","x20","x21","x22","x23","x24","x25","x26","x27","x28","x29","x30","sp","pc","v0","v1","v2","v3","v4","v5","v6","v7","v8","v9","v10","v11","v12","v13","v14","v15","v16","v17","v18","v19","v20","v21","v22","v23","v24","v25","v26","v27","v28","v29","v30","v31",END_LIST};
const char possibleRegistersRV[][10] ={"ra","sp","gp","tp","t0","t1","t2","s0","s1","a0","a1","a2","a3","a4","a5","a6","a7","s2","s3","s4","s5","s6","s7","s8","s9","s10","s11","t3","t4","t5","t6","pc",END_LIST};
// RISC-V: integer ABI (RV64I) + floating-point ABI (RV64D/F)
const char possibleRegistersRV[][10] ={
// Integer
"ra","sp","gp","tp","t0","t1","t2","s0","s1","a0","a1","a2","a3","a4","a5","a6","a7",
"s2","s3","s4","s5","s6","s7","s8","s9","s10","s11","t3","t4","t5","t6","pc",
// Floating-point
"ft0","ft1","ft2","ft3","ft4","ft5","ft6","ft7","fs0","fs1",
"fa0","fa1","fa2","fa3","fa4","fa5","fa6","fa7",
"fs2","fs3","fs4","fs5","fs6","fs7","fs8","fs9","fs10","fs11","ft8","ft9","ft10","ft11",
END_LIST};

#include "options.h"

Expand Down
78 changes: 74 additions & 4 deletions sofia-ovp/platformOP/harness/faultInjector.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,17 @@ void initialize() {
do {numberOfRegistersToCompare++;}
while(strcmp(END_LIST,possibleRegistersV7[numberOfRegistersToCompare]) != 0 );

if(numberOfRegistersToCompare > MAX_REGISTERS) numberOfRegistersToCompare = MAX_REGISTERS;

for(int i=0; i<numberOfRegistersToCompare; i++)
strcpy(possibleRegisters[i],possibleRegistersV7[i]);
} else if(!strcmp(options.environment,"ovparmv8")) {
numberOfRegistersToCompare=-2;
do {numberOfRegistersToCompare++;}
while(strcmp(END_LIST,possibleRegistersV8[numberOfRegistersToCompare]) != 0 );

if(numberOfRegistersToCompare > MAX_REGISTERS) numberOfRegistersToCompare = MAX_REGISTERS;

for(int i=0; i<numberOfRegistersToCompare; i++)
strcpy(possibleRegisters[i],possibleRegistersV8[i]);
}
Expand All @@ -202,6 +206,8 @@ void initialize() {
do {numberOfRegistersToCompare++;}
while(strcmp(END_LIST,possibleRegistersRV[numberOfRegistersToCompare]) != 0 );

if(numberOfRegistersToCompare > MAX_REGISTERS) numberOfRegistersToCompare = MAX_REGISTERS;

for(int i=0; i<numberOfRegistersToCompare; i++)
strcpy(possibleRegisters[i],possibleRegistersRV[i]);
}
Expand Down Expand Up @@ -681,6 +687,22 @@ void dumpGoldInformation() {
/// gem5 compatibility
fprintf(filePointer,"Kernel Boot # of instructions=0\n");
fprintf(filePointer,"Number of Ticks=0\n");

/// Append stack range from intercept library (if available)
{
char stackRangeFile[STRING_SIZE];
sprintf(stackRangeFile, "%s/%s/stack_range.txt", MACRO_APPLICATION_FOLDER, FOLDER_DUMPS);
FILE *stackFile = fopen(stackRangeFile, "r");
if (stackFile) {
char line[STRING_SIZE];
while (fgets(line, sizeof(line), stackFile)) {
fputs(line, filePointer);
}
fclose(stackFile);
opMessage("I", PREFIX_FIM, "Stack range appended to goldinformation\n");
}
}

fclose (filePointer);
}

Expand Down Expand Up @@ -748,6 +770,50 @@ fprintf(filePointer,"\n");
return regCmp;
}

//
// Compare the gold and fault dumps of the traced variable
//
void compareTracedVariable(Uns32 processorNumber, char* inconsistencyStatus) {
char goldName[STRING_SIZE];
char dumpName[STRING_SIZE];
char cmpReturn[STRING_SIZE];
FILE* filePointer;

// Default value
strcpy(inconsistencyStatus, "N/A");

// Check if variable tracing was enabled
if(PE.options.tracevariable) {
opMessage("I", PREFIX_FIM, "Comparing traced variable: %s", PE.options.tracevariable);

// Compare gold and fault variable dumps
sprintf(goldName, "%s/%s/trace_gold_variable-%d", MACRO_APPLICATION_FOLDER, FOLDER_DUMPS, 0);
sprintf(dumpName, "%s/%s/trace_fault_variable-%d", MACRO_APPLICATION_FOLDER, FOLDER_DUMPS, MACRO_PLATFORM_ID);

// Debug output
opMessage("I", PREFIX_FIM, "%s", goldName);
opMessage("I", PREFIX_FIM, "%s", dumpName);

// Compare the files
strcpy(cmpReturn, "Null");
sprintf(tempString, "cmp %s %s ", goldName, dumpName);
filePointer = popen(tempString, "r");
if(fgets(cmpReturn, STRING_SIZE, filePointer)) {
opMessage("E", PREFIX_FIM, "Command execution error (var cmp)\n");
}
pclose(filePointer);

// Set variable inconsistency status
if(strcmp(cmpReturn, "Null") == 0) {
strcpy(inconsistencyStatus, "No");
} else {
strcpy(inconsistencyStatus, "Yes");
opMessage("I", PREFIX_FIM, "Variable inconsistency detected");
}
}

}

//
// Analyses the fault injection and create a report
//
Expand All @@ -765,6 +831,7 @@ void createFaultInjectionReport() {
char Self_MemInconsistency [STRING_SIZE];
char self_correctCheckpoint [STRING_SIZE];
char self_TraceReport [STRING_SIZE];
char Self_VarInconsistency [STRING_SIZE];

int code = FIM_SR_UNIDENTIFIED;
int memCmp,regCmp,processorNumber;
Expand All @@ -783,10 +850,10 @@ void createFaultInjectionReport() {
FILE * pFile = fopen (reportFile,"w");

/// create file header
fprintf(pFile,"%8s %14s %10s %4s %18s %18s %28s %7s %25s %22s %18s %15s %15s\n",
fprintf(pFile,"%8s %14s %10s %4s %18s %18s %28s %7s %25s %22s %18s %15s %15s %18s\n",
"Index","Type","Target","i","Insertion Time","Mask","Fault Injection Result",
"Code", "Execution Time (Ticks)", "Executed Instructions", "Mem Inconsistency",
"Checkpoint", "Trace Variable");
"Checkpoint", "Trace Variable", "Var Inconsistency");

/********************************************/
/// PE (DUT) processing
Expand All @@ -797,6 +864,8 @@ void createFaultInjectionReport() {
count = 0;
goldCount = 0;

compareTracedVariable(processorNumber, Self_VarInconsistency);

/// acquire the gold count and the actual instruction count
for (int i=0;i<MACRO_NUMBER_OF_CORES;i++) {
count += opProcessorICount(PE.childrens[i]);
Expand Down Expand Up @@ -993,7 +1062,7 @@ void createFaultInjectionReport() {
//sprintf(self_MemInconsistency,"%s");
sprintf(self_correctCheckpoint, ""FMT_64u"",checkpointLoaded+PE.instructionsToNormalExit);

fprintf(pFile,"%8s %14s %10s %4s %18s %18s %28s %7s %25s %22s %18s %15s %15s\n",
fprintf(pFile,"%8s %14s %10s %4s %18s %18s %28s %7s %25s %22s %18s %15s %15s %18s\n",
self_faultIndex,
self_faultType,
self_faultRegister,
Expand All @@ -1006,7 +1075,8 @@ void createFaultInjectionReport() {
self_ExecutedInstructions,
Self_MemInconsistency,
self_correctCheckpoint,
self_TraceReport);
self_TraceReport,
Self_VarInconsistency);
}
fclose (pFile);
}
Expand Down
Loading