diff options
Diffstat (limited to 'src/usr/targeting')
-rw-r--r-- | src/usr/targeting/target.C | 39 | ||||
-rw-r--r-- | src/usr/targeting/test/targetingtest.H | 124 | ||||
-rw-r--r-- | src/usr/targeting/xmltohb/attribute_types.xml | 13 | ||||
-rw-r--r-- | src/usr/targeting/xmltohb/target_types.xml | 1 | ||||
-rwxr-xr-x | src/usr/targeting/xmltohb/xmltohb.pl | 104 |
5 files changed, 267 insertions, 14 deletions
diff --git a/src/usr/targeting/target.C b/src/usr/targeting/target.C index f4950c1e7..d6946e050 100644 --- a/src/usr/targeting/target.C +++ b/src/usr/targeting/target.C @@ -125,6 +125,45 @@ void Target::_getAttrPtr( } //****************************************************************************** +// Target::_getHbMutexAttr +//****************************************************************************** + +mutex_t* Target::_getHbMutexAttr( + const ATTRIBUTE_ID i_attribute) const +{ + #define TARG_FN "_getHbMutexAttr()" + + void* l_pAttr = NULL; + (void)_getAttrPtr(i_attribute,l_pAttr); + + //@TODO Remove assert once release has stablized + assert(l_pAttr,"TARGETING::Target::_getHbMutexAttr<%d>: _getAttrPtr " + "returned NULL",i_attribute); + + return static_cast<mutex_t*>(l_pAttr); + + #undef TARG_FN +} + +//****************************************************************************** +// Target::_tryGetHbMutexAttr +//****************************************************************************** + +bool Target::_tryGetHbMutexAttr( + const ATTRIBUTE_ID i_attribute, + mutex_t*& o_pMutex) const +{ + #define TARG_FN "_tryGetHbMutexAttr()" + + void* l_pAttr = NULL; + (void)_getAttrPtr(i_attribute,l_pAttr); + o_pMutex = static_cast<mutex_t*>(l_pAttr); + return (l_pAttr != NULL); + + #undef TARG_FN +} + +//****************************************************************************** // Target::Target //****************************************************************************** diff --git a/src/usr/targeting/test/targetingtest.H b/src/usr/targeting/test/targetingtest.H index a2a25ab34..c6d732cee 100644 --- a/src/usr/targeting/test/targetingtest.H +++ b/src/usr/targeting/test/targetingtest.H @@ -44,6 +44,9 @@ #include <fapiAttributeIds.H> #include <fapiAttributeService.H> #include <errl/errlmanager.H> +#include <sys/sync.h> +#include <sys/task.h> +#include <sys/time.h> // This component #include <targeting/attributes.H> @@ -54,6 +57,31 @@ #include <targeting/predicates/predicatectm.H> #include <targeting/predicates/predicatepostfixexpr.H> +/** + * @brief Struct to hold pointers to a mutex / protected value + */ +struct MutexTestData_t +{ + mutex_t* pMutex; // Pointer to mutex + volatile uint32_t* pVar; // Pointer to value protected by mutex +}; + +/** + * @brief Function which attempts to write a protected variable + * + * @param[in] i_pData Pointer to mutex pointer/value pointer structure + * + * @return N/A + */ +void funcTestMutex(void* i_pData) +{ + MutexTestData_t* l_pData = static_cast<MutexTestData_t*>(i_pData); + mutex_lock(l_pData->pMutex); + *(l_pData->pVar) = 1; + mutex_unlock(l_pData->pMutex); + task_end(); +} + class TargetingTestSuite: public CxxTest::TestSuite { public: @@ -1336,6 +1364,102 @@ class TargetingTestSuite: public CxxTest::TestSuite TS_TRACE(EXIT_MRK "testCentaurs" ); } + + void testHbMutexAttr() + { + TS_TRACE(ENTER_MRK "testHbMutexAttr" ); + + using namespace TARGETING; + using namespace fapi; + + do { + + // Get a reference to the target service + TargetService& l_targetService = targetService(); + + // Get the system target containing the test mutex + TARGETING::Target* l_pTarget = NULL; + (void) l_targetService.getTopLevelTarget(l_pTarget); + if (l_pTarget == NULL) + { + TS_FAIL("Top level target handle is NULL"); + break; + } + + // Get the mutex attribute (actually a mutex_t* which points to + // a mutex) + HB_MUTEX_TEST_LOCK_ATTR l_pLock + = l_pTarget->getHbMutexAttr<TARGETING::ATTR_HB_MUTEX_TEST_LOCK>(); + + // Test: Verify the value pointed to by the mutex_t* is zero + if ( (*reinterpret_cast<uint64_t*>(l_pLock)) != 0) + { + TS_FAIL("Mutex attribute must be initialized to zero, but got %ld", + *reinterpret_cast<uint64_t*>(l_pLock)); + break; + } + + // Try to get the attribute, and ensure it's the same + HB_MUTEX_TEST_LOCK_ATTR l_pLockTry = NULL; + if(l_pTarget->tryGetHbMutexAttr<TARGETING::ATTR_HB_MUTEX_TEST_LOCK> + (l_pLockTry)) + { + if(l_pLockTry != l_pLock) + { + TS_FAIL("Mutex attributes should match, but dont. " + "l_pLockTry = %ld, l_pLock = %ld",l_pLockTry, + l_pLock); + break; + } + } + else + { + TS_FAIL("Mutex attribute tryGet failed, even though it exists"); + break; + } + + // Create a structue holding pointers to the mutex and a protected value + volatile uint32_t l_var = 0; + (void)mutex_lock(l_pLock); + MutexTestData_t l_mutexTestData = { l_pLock, &l_var }; + + // Spawn off a function which tries to write the protected value to + // something unexpected. If the mutex is working, the for loop will + // always poll the expected value. + task_create(funcTestMutex, static_cast<void*>(&l_mutexTestData)); + + // Guarantee the child process runs and blocks on the mutex prior to + // modifying the protected value. isync to ensure the processor doesn't + // speculatively perform the comparison prior to the sleep completing + nanosleep(0,TEN_CTX_SWITCHES_NS); isync(); + + if(l_var != 0) + { + TS_FAIL("Protected value must be 0, was %d instead",l_var); + break; + } + + // Now unlock the mutex, allowing the other thread to overwrite the + // protected value; which should happen within 100,000 reads of the + // var. This will confirm the other thread was actively trying to + // write the controlled value + (void)mutex_unlock(l_pLock); + + // Guarantee the child process acquires the mutex and modifies the + // protected value; isync to ensure the processor doesn't speculatively + // perform the comparison prior to the sleep completing + nanosleep(0,TEN_CTX_SWITCHES_NS); isync(); + + if(l_var != 1) + { + TS_FAIL("Protected value must now be 1, was %d instead",l_var); + break; + } + + } while(0); + + TS_TRACE(EXIT_MRK "testHbMutexAttr"); + } }; #endif // End __TESTTARGETING_H diff --git a/src/usr/targeting/xmltohb/attribute_types.xml b/src/usr/targeting/xmltohb/attribute_types.xml index 8c0f7dbf8..c7f1d42c9 100644 --- a/src/usr/targeting/xmltohb/attribute_types.xml +++ b/src/usr/targeting/xmltohb/attribute_types.xml @@ -951,5 +951,18 @@ <readable/> </attribute> +<attribute> + <id>HB_MUTEX_TEST_LOCK</id> + <description>Host boot mutex for testing</description> + <simpleType> + <hbmutex> + <default>0</default> + </hbmutex> + </simpleType> + <persistency>volatile-zeroed</persistency> + <readable/> + <writeable/> +</attribute> + </attributes> diff --git a/src/usr/targeting/xmltohb/target_types.xml b/src/usr/targeting/xmltohb/target_types.xml index fe44b7970..1b97633c3 100644 --- a/src/usr/targeting/xmltohb/target_types.xml +++ b/src/usr/targeting/xmltohb/target_types.xml @@ -64,6 +64,7 @@ <attribute><id>SCRATCH_UINT64_ARRAY_1</id></attribute> <attribute><id>SCRATCH_UINT64_ARRAY_2</id></attribute> <attribute><id>NUMERIC_POD_TYPE_TEST</id></attribute> + <attribute><id>HB_MUTEX_TEST_LOCK</id></attribute> <attribute><id>DUMMY_RW</id></attribute> <attribute> <id>XSCOM_BASE_ADDRESS</id> diff --git a/src/usr/targeting/xmltohb/xmltohb.pl b/src/usr/targeting/xmltohb/xmltohb.pl index b067e0e8e..c4443b0bb 100755 --- a/src/usr/targeting/xmltohb/xmltohb.pl +++ b/src/usr/targeting/xmltohb/xmltohb.pl @@ -1162,6 +1162,18 @@ sub writeTraitFileTraits { $traits .= " $trait,"; } } + + # Mark the attribute as being a host boot mutex or non-host boot mutex + if( (exists $attribute->{simpleType}) + && (exists $attribute->{simpleType}->{hbmutex}) ) + { + $traits .= " hbMutex,"; + } + else + { + $traits .= " notHbMutex,"; + } + chop($traits); # Build value type @@ -1461,6 +1473,34 @@ sub defaultEnum { } ################################################################################ +# Do nothing +################################################################################ + +sub null { + +} + +################################################################################ +# Enforce special host boot mutex restrictions +################################################################################ + +sub enforceHbMutex { + my($attribute,$value) = @_; + + if($value != 0) + { + fatal("HB mutex attribute default must always be 0, " + . "was $value instead."); + } + + if($attribute->{persistency} ne "volatile-zeroed") + { + fatal("HB mutex attribute persistency must be volatile-zeroed, " + . "was $attribute->{persistency} instead"); + } +} + +################################################################################ # Get hash ref to supported simple types and their properties ################################################################################ @@ -1470,15 +1510,16 @@ sub simpleTypeProperties { # Intentionally didn't wrap these to 80 columns to keep them lined up and # more readable/editable - $typesHoH{"int8_t"} = { supportsArray => 1, canBeHex => 1, complexTypeSupport => 1, typeName => "int8_t" , bytes => 1, bits => 8 , default => \&defaultZero, packfmt => "C" }; - $typesHoH{"int16_t"} = { supportsArray => 1, canBeHex => 1, complexTypeSupport => 1, typeName => "int16_t" , bytes => 2, bits => 16, default => \&defaultZero, packfmt => "n" }; - $typesHoH{"int32_t"} = { supportsArray => 1, canBeHex => 1, complexTypeSupport => 1, typeName => "int32_t" , bytes => 4, bits => 32, default => \&defaultZero, packfmt => "N" }; - $typesHoH{"int64_t"} = { supportsArray => 1, canBeHex => 1, complexTypeSupport => 1, typeName => "int64_t" , bytes => 8, bits => 64, default => \&defaultZero, packfmt =>\&packQuad}; - $typesHoH{"uint8_t"} = { supportsArray => 1, canBeHex => 1, complexTypeSupport => 1, typeName => "uint8_t" , bytes => 1, bits => 8 , default => \&defaultZero, packfmt => "C" }; - $typesHoH{"uint16_t"} = { supportsArray => 1, canBeHex => 1, complexTypeSupport => 1, typeName => "uint16_t" , bytes => 2, bits => 16, default => \&defaultZero, packfmt => "n" }; - $typesHoH{"uint32_t"} = { supportsArray => 1, canBeHex => 1, complexTypeSupport => 1, typeName => "uint32_t" , bytes => 4, bits => 32, default => \&defaultZero, packfmt => "N" }; - $typesHoH{"uint64_t"} = { supportsArray => 1, canBeHex => 1, complexTypeSupport => 1, typeName => "uint64_t" , bytes => 8, bits => 64, default => \&defaultZero, packfmt =>\&packQuad}; - $typesHoH{"enumeration"} = { supportsArray => 1, canBeHex => 1, complexTypeSupport => 0, typeName => "XMLTOHB_USE_PARENT_ATTR_ID" , bytes => 0, bits => 0 , default => \&defaultEnum, packfmt => "packEnumeration"}; + $typesHoH{"int8_t"} = { supportsArray => 1, canBeHex => 1, complexTypeSupport => 1, typeName => "int8_t" , bytes => 1, bits => 8 , default => \&defaultZero, alignment => 1, specialPolicies =>\&null, packfmt => "C" }; + $typesHoH{"int16_t"} = { supportsArray => 1, canBeHex => 1, complexTypeSupport => 1, typeName => "int16_t" , bytes => 2, bits => 16, default => \&defaultZero, alignment => 1, specialPolicies =>\&null, packfmt => "n" }; + $typesHoH{"int32_t"} = { supportsArray => 1, canBeHex => 1, complexTypeSupport => 1, typeName => "int32_t" , bytes => 4, bits => 32, default => \&defaultZero, alignment => 1, specialPolicies =>\&null, packfmt => "N" }; + $typesHoH{"int64_t"} = { supportsArray => 1, canBeHex => 1, complexTypeSupport => 1, typeName => "int64_t" , bytes => 8, bits => 64, default => \&defaultZero, alignment => 1, specialPolicies =>\&null, packfmt =>\&packQuad}; + $typesHoH{"uint8_t"} = { supportsArray => 1, canBeHex => 1, complexTypeSupport => 1, typeName => "uint8_t" , bytes => 1, bits => 8 , default => \&defaultZero, alignment => 1, specialPolicies =>\&null, packfmt => "C" }; + $typesHoH{"uint16_t"} = { supportsArray => 1, canBeHex => 1, complexTypeSupport => 1, typeName => "uint16_t" , bytes => 2, bits => 16, default => \&defaultZero, alignment => 1, specialPolicies =>\&null, packfmt => "n" }; + $typesHoH{"uint32_t"} = { supportsArray => 1, canBeHex => 1, complexTypeSupport => 1, typeName => "uint32_t" , bytes => 4, bits => 32, default => \&defaultZero, alignment => 1, specialPolicies =>\&null, packfmt => "N" }; + $typesHoH{"uint64_t"} = { supportsArray => 1, canBeHex => 1, complexTypeSupport => 1, typeName => "uint64_t" , bytes => 8, bits => 64, default => \&defaultZero, alignment => 1, specialPolicies =>\&null, packfmt =>\&packQuad}; + $typesHoH{"enumeration"} = { supportsArray => 1, canBeHex => 1, complexTypeSupport => 0, typeName => "XMLTOHB_USE_PARENT_ATTR_ID" , bytes => 0, bits => 0 , default => \&defaultEnum, alignment => 1, specialPolicies =>\&null, packfmt => "packEnumeration"}; + $typesHoH{"hbmutex"} = { supportsArray => 1, canBeHex => 1, complexTypeSupport => 0, typeName => "mutex_t*" , bytes => 8, bits => 64, default => \&defaultZero, alignment => 8, specialPolicies =>\&enforceHbMutex, packfmt =>\&packQuad}; return \%typesHoH; } @@ -1959,6 +2000,7 @@ sub packAttribute { my $binaryData; + my $alignment = 1; if(exists $attribute->{simpleType}) { my $simpleType = $attribute->{simpleType}; @@ -1968,6 +2010,8 @@ sub packAttribute { { if(exists $simpleTypeProperties->{$typeName}) { + $alignment = $simpleTypeProperties->{$typeName}{alignment}; + if($typeName eq "enumeration") { my $enumeration = getEnumerationType($attributes,$simpleType->{enumeration}->{id}); @@ -1982,6 +2026,10 @@ sub packAttribute { { $value = unhexify($value); } + + # Apply special policy enforcement, if any + $simpleTypeProperties-> + {$typeName}{specialPolicies}->($attribute,$value); if(ref ($simpleTypeProperties->{$typeName}{packfmt}) eq "CODE") { @@ -2056,7 +2104,7 @@ sub packAttribute { fatal("Serialization failed for attribute ID = $attribute->{id}."); } - return $binaryData; + return ($binaryData,$alignment); } ################################################################################ @@ -2302,8 +2350,15 @@ sub writeTargetingImage { if($section eq "pnor-ro") { - my $rodata = packAttribute($attributes,$attributeDef, + my ($rodata,$alignment) = packAttribute($attributes, + $attributeDef, $attrhash{$attributeId}->{default}); + + # Align the data as necessary + my $pads = ($alignment - ($offset % $alignment)) + % $alignment; + $roAttrBinData .= pack ("@".$pads); + $offset += $pads; $attributePointerBinData .= packQuad( $offset + $pnorRoBaseAddress); @@ -2314,11 +2369,18 @@ sub writeTargetingImage { } elsif($section eq "pnor-rw") { - my $rwdata = packAttribute($attributes,$attributeDef, + my ($rwdata,$alignment) = packAttribute($attributes, + $attributeDef, $attrhash{$attributeId}->{default}); #print "Wrote to pnor-rw value ",$attributeDef->{id}, ", #", $attrhash{$attributeId}->{default}," \n"; + + # Align the data as necessary + my $pads = ($alignment - ($rwOffset % $alignment)) + % $alignment; + $rwAttrBinData .= pack ("@".$pads); + $rwOffset += $pads; $attributePointerBinData .= packQuad( $rwOffset + $pnorRwBaseAddress); @@ -2330,8 +2392,15 @@ sub writeTargetingImage { } elsif($section eq "heap-zero-initialized") { - my $heapZeroInitData = packAttribute($attributes, + my ($heapZeroInitData,$alignment) = packAttribute( + $attributes, $attributeDef,$attrhash{$attributeId}->{default}); + + # Align the data as necessary + my $pads = ($alignment - ($heapZeroInitOffset + % $alignment)) % $alignment; + $heapZeroInitBinData .= pack ("@".$pads); + $heapZeroInitOffset += $pads; $attributePointerBinData .= packQuad( $heapZeroInitOffset + $heapZeroInitBaseAddr); @@ -2343,9 +2412,16 @@ sub writeTargetingImage { } elsif($section eq "heap-pnor-initialized") { - my $heapPnorInitData = packAttribute($attributes, + my ($heapPnorInitData,$alignment) = packAttribute( + $attributes, $attributeDef,$attrhash{$attributeId}->{default}); + # Align the data as necessary + my $pads = ($alignment - ($heapPnorInitOffset + % $alignment)) % $alignment; + $heapPnorInitBinData .= pack ("@".$pads); + $heapPnorInitOffset += $pads; + $attributePointerBinData .= packQuad( $heapPnorInitOffset + $heapPnorInitBaseAddr); |