Skip to content

Commit 553e252

Browse files
committed
PRD: fixed structure alignment in firdata code
Change-Id: Ie6e8b1d86640fdf5392c59e7d7b76b3f1edc87d5 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/43294 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: Caleb N. Palmer <cnpalmer@us.ibm.com> Reviewed-by: Benjamin J. Weisenbeck <bweisenb@us.ibm.com> Reviewed-by: Zane C. Shelley <zshelle@us.ibm.com> Squashed: I3af463929b2c284ffe9c62172e92adf9af102403 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/43358 Reviewed-by: Brian J. Stegmiller <bjs@us.ibm.com> Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
1 parent f81330e commit 553e252

File tree

4 files changed

+124
-63
lines changed

4 files changed

+124
-63
lines changed

src/usr/diag/prdf/occ_firdata/homerData_common.h

Lines changed: 44 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,21 @@
5252
* - Register address lists - These lists vary in size depending on the number
5353
* of register addresses needed in each list. The list counts are stored in
5454
* HOMER_Data_t::regCounts. Order of the lists must match the array indexes
55-
* HOMER_Data_t::regCounts, which are specified in TrgtType_t and
55+
* of HOMER_Data_t::regCounts, which are specified in TrgtType_t and
5656
* RegType_t.
5757
*
58+
* - Chip specific address list - This is a list of HOMER_ChipSpecAddr_t
59+
* structs and will vary in size depending on the number of register
60+
* addresses that are specific to a certain chip or DD level. The number of
61+
* entries in this list is stored in HOMER_Data_t::ecDepCounts.
62+
*
63+
* IMPORTANT NOTE: All of the structs used here are packed. Therefore, we must
64+
* ensure the variables within the struct are byte aligned. Meaning each
65+
* uint32_t within the struct must be 4-byte aligned and each uint16_t must
66+
* be 2-byte aligned. This also means the structs must always start on a
67+
* 4-bye word boundary to maintain alignment. This is required due to the
68+
* limitations of the PPE42/SRAM hardware.
69+
*
5870
* Note that FIRs and indirect-SCOM FIRs characterize a set of registers to
5971
* capture. In addition to capturing the FIR (or ID FIR), the OCC will need to
6072
* capture the following addresses for each type:
@@ -79,6 +91,7 @@ typedef enum
7991
} HOMER_Version_t;
8092

8193
/** PNOR information contained within the HOMER data. */
94+
/* NOTE: This structure is 4-byte word aligned. */
8295
typedef struct __attribute__((packed))
8396
{
8497
uint32_t pnorOffset; /** Physical offset of FIRDATA in PNOR */
@@ -90,25 +103,26 @@ typedef struct __attribute__((packed))
90103

91104
/** HOMER data header information containing hardware configurations and
92105
* register counts. */
106+
/* NOTE: This structure may, or may not, be 4-byte word aligned. It all depends
107+
* on the size of regCounts, which will change based on the number of
108+
* target types and register types we support. When reading/writing this
109+
* data ensure that proper padding has been added after this structure so
110+
* that subsequent structures are 4-byte word aligned. */
93111
typedef struct __attribute__((packed))
94112
{
95113
uint32_t header; /** Magic number to indicate valid data and version */
96114

97-
uint8_t chipCount; /** Number of configured chips per node */
115+
uint32_t chipCount : 8; /** Number of configured chips per node */
116+
uint32_t ecDepCounts : 8; /** Number of regs that are EC dependent */
117+
uint32_t iplState : 1; /** See IplState_t. */
118+
uint32_t reserved : 15;
98119

99-
uint8_t iplState : 1; /** See IplState_t. */
100-
uint8_t reserved : 7;
120+
/** Information regarding the PNOR location and size. */
121+
HOMER_PnorInfo_t pnorInfo;
101122

102123
/** Contains number of registers per type for each target type. */
103124
uint8_t regCounts[TRGT_MAX][REG_MAX];
104125

105-
/** Number of regs that are dependent on EC level **/
106-
/** (these registers follow the normal register list) **/
107-
uint8_t ecDepCounts;
108-
109-
/** Information regarding the PNOR location and size. */
110-
HOMER_PnorInfo_t pnorInfo;
111-
112126
} HOMER_Data_t;
113127

114128
/** @return An initialized HOMER_Data_t struct. */
@@ -133,20 +147,20 @@ typedef enum
133147
} HOMER_ChipType_t;
134148

135149
/** Information for each configured chip. */
150+
/* NOTE: This structure is 4-byte word aligned. */
136151
typedef struct __attribute__((packed))
137152
{
138153
uint32_t fsiBaseAddr; /** FSI base address for the chip. */
139154

140-
uint16_t chipType : 4; /** Chip type (see HOMER_ChipType_t) */
141-
uint16_t chipPos : 6; /** Chip position relative to the node. */
142-
uint16_t reserved : 6;
143-
144-
uint8_t chipEcLevel; /** EC level for this chip */
155+
uint32_t chipType : 4; /** Chip type (see HOMER_ChipType_t) */
156+
uint32_t chipPos : 6; /** Chip position relative to the node. */
157+
uint32_t chipEcLevel : 8; /** EC level for this chip */
158+
uint32_t reserved : 14;
145159

146160
} HOMER_Chip_t;
147161

148-
149162
/** Used for Registers that have EC level dependencies */
163+
/* NOTE: This structure is 4-byte word aligned. */
150164
typedef struct __attribute__((packed))
151165
{
152166
uint32_t chipType : 4; /** See HOMER_ChipType_t. */
@@ -160,7 +174,6 @@ typedef struct __attribute__((packed))
160174

161175
} HOMER_ChipSpecAddr_t;
162176

163-
164177
/** @return An initialized HOMER_Chip_t struct. */
165178
static inline HOMER_Chip_t HOMER_getChip( HOMER_ChipType_t i_type )
166179
{
@@ -175,6 +188,7 @@ static inline HOMER_Chip_t HOMER_getChip( HOMER_ChipType_t i_type )
175188
/*----------------------------------------------------------------------------*/
176189

177190
/** Information specific to a P9 Nimbus processor chip. */
191+
/* NOTE: This structure is 4-byte word aligned. */
178192
typedef struct __attribute__((packed))
179193
{
180194
uint32_t isMaster : 1; /** 1 if this is the master PROC, 0 otherwise */
@@ -188,10 +202,10 @@ typedef struct __attribute__((packed))
188202
uint32_t mcsMask : 4; /** Mask of configured MCS units (0-3) */
189203
uint32_t mcaMask : 8; /** Mask of configured MCA units (0-7) */
190204

191-
uint16_t cappMask : 2; /** Mask of configured CAPP units (0-1) */
192-
uint16_t pecMask : 3; /** Mask of configured PEC units (0-2) */
193-
uint16_t phbMask : 6; /** Mask of configured PHB units (0-5) */
194-
uint16_t reserved : 5;
205+
uint32_t cappMask : 2; /** Mask of configured CAPP units (0-1) */
206+
uint32_t pecMask : 3; /** Mask of configured PEC units (0-2) */
207+
uint32_t phbMask : 6; /** Mask of configured PHB units (0-5) */
208+
uint32_t reserved : 21;
195209

196210
} HOMER_ChipNimbus_t;
197211

@@ -206,6 +220,7 @@ static inline HOMER_ChipNimbus_t HOMER_initChipNimbus()
206220
/*----------------------------------------------------------------------------*/
207221

208222
/** Information specific to a P9 Cumulus processor chip. */
223+
/* NOTE: This structure is 4-byte word aligned. */
209224
typedef struct __attribute__((packed))
210225
{
211226
uint32_t isMaster : 1; /** 1 if this is the master PROC, 0 otherwise */
@@ -219,10 +234,10 @@ typedef struct __attribute__((packed))
219234
uint32_t miMask : 4; /** Mask of configured MI units (0-3) */
220235
uint32_t dmiMask : 8; /** Mask of configured DMI units (0-7) */
221236

222-
uint16_t cappMask : 2; /** Mask of configured CAPP units (0-1) */
223-
uint16_t pecMask : 3; /** Mask of configured PEC units (0-2) */
224-
uint16_t phbMask : 6; /** Mask of configured PHB units (0-5) */
225-
uint16_t reserved : 5;
237+
uint32_t cappMask : 2; /** Mask of configured CAPP units (0-1) */
238+
uint32_t pecMask : 3; /** Mask of configured PEC units (0-2) */
239+
uint32_t phbMask : 6; /** Mask of configured PHB units (0-5) */
240+
uint32_t reserved : 21;
226241

227242
} HOMER_ChipCumulus_t;
228243

@@ -237,10 +252,11 @@ static inline HOMER_ChipCumulus_t HOMER_initChipCumulus()
237252
/*----------------------------------------------------------------------------*/
238253

239254
/** Information specific to a Centaur memory buffer chip. */
255+
/* NOTE: This structure is 4-byte word aligned. */
240256
typedef struct __attribute__((packed))
241257
{
242-
uint8_t mbaMask : 2; /** Mask of configured MBA units (0-1) */
243-
uint8_t reserved : 6;
258+
uint32_t mbaMask : 2; /** Mask of configured MBA units (0-1) */
259+
uint32_t reserved : 30;
244260

245261
} HOMER_ChipCentaur_t;
246262

@@ -252,23 +268,4 @@ static inline HOMER_ChipCentaur_t HOMER_initChipCentaur()
252268
return c;
253269
}
254270

255-
/** @brief Chip information inserted into HOMER data section after header
256-
*
257-
* There is basically an array of these after the initial HOMER
258-
* section (HOMER_Data_t). The register info then follows.
259-
*/
260-
typedef struct __attribute__((packed))
261-
{
262-
HOMER_Chip_t hChipType; /* Nimbus, Centaur, EC Level, etc...*/
263-
264-
union
265-
{
266-
HOMER_ChipNimbus_t hChipN;
267-
HOMER_ChipCumulus_t hChipC;
268-
HOMER_ChipCentaur_t hChipM;
269-
};
270-
271-
} HOMER_ChipInfo_t;
272-
273-
274271
#endif /* __homerData_common_h */

src/usr/diag/prdf/occ_firdata/pnorData_common.h

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@
4444
* - A list of all regular registers (PNOR_Reg_t).
4545
* - A list of all indirect-SCOM registers (PNOR_IdReg_t).
4646
*
47+
* IMPORTANT NOTE: All of the structs used here are packed. Therefore, we must
48+
* ensure the variables within the struct are byte aligned. Meaning each
49+
* uint32_t within the struct must be 4-byte aligned and each uint16_t must
50+
* be 2-byte aligned. This also means the structs must always start on a
51+
* 4-bye word boundary to maintain alignment. This is required due to the
52+
* limitations of the PPE42/SRAM hardware.
53+
*
4754
* The PNOR has limited data space. So the following rules will apply:
4855
* - Any registers with the value of zero will not be captured.
4956
* - Registers with SCOM errors will not be captured, however, the number
@@ -70,14 +77,15 @@ typedef enum
7077
} PNOR_Version_t;
7178

7279
/** PNOR data header information. */
80+
/* NOTE: This structure is 4-byte word aligned. */
7381
typedef struct __attribute__((packed))
7482
{
7583
uint32_t header; /** Magic number to indicate valid data and version */
7684

77-
uint16_t trgts : 12; /** Number of targets with register data */
78-
uint16_t full : 1; /** 1 if PNOR data is full and data incomplete */
79-
uint16_t iplState : 1; /** See enum IplState_t */
80-
uint16_t reserved : 2;
85+
uint32_t trgts : 12; /** Number of targets with register data */
86+
uint32_t full : 1; /** 1 if PNOR data is full and data incomplete */
87+
uint32_t iplState : 1; /** See enum IplState_t */
88+
uint32_t reserved : 18;
8189

8290
} PNOR_Data_t;
8391

@@ -101,16 +109,17 @@ typedef enum
101109
} PNOR_Trgt_RegLimits_t;
102110

103111
/** Information for each target with SCOM data. */
112+
/* NOTE: This structure is 4-byte word aligned. */
104113
typedef struct __attribute__((packed))
105114
{
106-
uint32_t chipPos : 6; /** Parent chip position relative to the node */
107-
uint32_t unitPos : 5; /** Unit position relative to the parent chip */
108-
uint32_t regs : 9; /** Number of normal registers */
109-
uint32_t idRegs : 4; /** Number of indirect-SCOM registers */
110-
uint32_t scomErrs : 8; /** Number of SCOM errors detected */
115+
uint32_t chipPos : 6; /** Parent chip position relative to the node */
116+
uint32_t unitPos : 5; /** Unit position relative to the parent chip */
117+
uint32_t regs : 9; /** Number of normal registers */
118+
uint32_t idRegs : 4; /** Number of indirect-SCOM registers */
119+
uint32_t scomErrs : 8; /** Number of SCOM errors detected */
111120

112-
uint8_t trgtType : 6; /** Target type. See enum TrgtType_t */
113-
uint8_t reserved : 2;
121+
uint32_t trgtType : 6; /** Target type. See enum TrgtType_t */
122+
uint32_t reserved : 26;
114123

115124
} PNOR_Trgt_t;
116125

@@ -132,6 +141,7 @@ static inline PNOR_Trgt_t PNOR_getTrgt( uint32_t i_trgtType, uint32_t i_chipPos,
132141
};
133142

134143
/** Information for a normal register. */
144+
/* NOTE: This structure is 4-byte word aligned. */
135145
typedef struct __attribute__((packed))
136146
{
137147
uint32_t addr; /** 32-bit address */
@@ -140,6 +150,7 @@ typedef struct __attribute__((packed))
140150
} PNOR_Reg_t;
141151

142152
/** Information for an indirect-SCOM register. */
153+
/* NOTE: This structure is 4-byte word aligned. */
143154
typedef struct __attribute__((packed))
144155
{
145156
uint64_t addr; /** 64-bit address */

src/usr/diag/prdf/occ_firdata/prdfWriteHomerFirData.C

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,26 @@ errlHndl_t getPnorInfo( HOMER_Data_t & o_data )
695695
}
696696

697697
//------------------------------------------------------------------------------
698+
699+
/* Helper struct for chip information inserted into HOMER data section after the
700+
* header. There is basically an array of these after the initial HOMER section
701+
* (HOMER_Data_t). The register info then follows.
702+
*/
703+
typedef struct __attribute__((packed))
704+
{
705+
HOMER_Chip_t hChipType; /* Nimbus, Centaur, EC Level, etc...*/
706+
707+
union
708+
{
709+
HOMER_ChipNimbus_t hChipN;
710+
HOMER_ChipCumulus_t hChipC;
711+
HOMER_ChipCentaur_t hChipM;
712+
};
713+
714+
} HOMER_ChipInfo_t;
715+
716+
//------------------------------------------------------------------------------
717+
698718
errlHndl_t getHwConfig( std::vector<HOMER_ChipInfo_t> &io_chipInfVector,
699719
const HwInitialized_t i_curHw )
700720
{
@@ -720,7 +740,6 @@ errlHndl_t getHwConfig( std::vector<HOMER_ChipInfo_t> &io_chipInfVector,
720740
l_procModelType = (MODEL_CUMULUS == getChipModel(masterProc)) ?
721741
HOMER_CHIP_CUMULUS : HOMER_CHIP_NIMBUS;
722742

723-
724743
// Iterate the list of functional PROCs.
725744
TargetHandleList procList = getFunctionalTargetList( TYPE_PROC );
726745
for ( TargetHandleList::iterator procIt = procList.begin();
@@ -965,6 +984,9 @@ errlHndl_t writeData( uint8_t * i_hBuf, size_t i_hBufSize,
965984
errlHndl_t errl = NULL;
966985
TrgtMap_t l_targMap;
967986

987+
const size_t u32 = sizeof(uint32_t);
988+
const size_t u64 = sizeof(uint64_t);
989+
968990
do
969991
{
970992
size_t sz_hBuf = 0;
@@ -973,10 +995,12 @@ errlHndl_t writeData( uint8_t * i_hBuf, size_t i_hBufSize,
973995
size_t sz_data = sizeof(io_homerData);
974996
sz_hBuf += sz_data;
975997

998+
// The HOMER_Data_t struct may have an uneven size. Add some padding to
999+
// ensure the subsequent HOMER_Chip_t structs are word aligned. */
1000+
const size_t padding = (u32 - (sizeof(HOMER_Data_t) % u32)) % u32;
1001+
sz_hBuf += padding;
9761002

9771003
// Add register counts to the data.
978-
const size_t u32 = sizeof(uint32_t);
979-
const size_t u64 = sizeof(uint64_t);
9801004
// initialize SCOM addresses for all targets & regs
9811005
getAddresses(l_targMap);
9821006

@@ -1025,6 +1049,9 @@ errlHndl_t writeData( uint8_t * i_hBuf, size_t i_hBufSize,
10251049
// Fill the input buffer with chipcount, regcount, pnor info
10261050
memcpy( &i_hBuf[idx], &io_homerData, sz_data ); idx += sz_data;
10271051

1052+
// Add the padding at the end of the HOMER_Data_t struct.
1053+
idx += padding;
1054+
10281055
// We want a list of chips next
10291056
if (0 != io_homerData.chipCount)
10301057
{

src/usr/diag/prdf/test/prdfTest_WriteHomerFir.H

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,24 @@
5151

5252
namespace PRDF
5353
{
54+
55+
/* Helper struct for chip information inserted into HOMER data section after the
56+
* header. There is basically an array of these after the initial HOMER section
57+
* (HOMER_Data_t). The register info then follows.
58+
*/
59+
typedef struct __attribute__((packed))
60+
{
61+
HOMER_Chip_t hChipType; /* Nimbus, Centaur, EC Level, etc...*/
62+
63+
union
64+
{
65+
HOMER_ChipNimbus_t hChipN;
66+
HOMER_ChipCumulus_t hChipC;
67+
HOMER_ChipCentaur_t hChipM;
68+
};
69+
70+
} HOMER_ChipInfo_t;
71+
5472
// these functions from prdfWriteHomerFirData.C are needed for the
5573
// fakeWriteHomerFirData() function
5674
errlHndl_t getHwConfig( std::vector<HOMER_ChipInfo_t> &io_chipInfVector,
@@ -129,6 +147,9 @@ private:
129147
{
130148
using namespace PRDF;
131149

150+
const size_t sz_u32 = sizeof(uint32_t);
151+
const size_t sz_hd = sizeof(HOMER_Data_t);
152+
132153
if (MASTER_PROC_CORE == i_curHw || ALL_PROC_MASTER_CORE == i_curHw)
133154
{
134155
// Should have at least one processor chip
@@ -138,10 +159,15 @@ private:
138159
} // end if no chips
139160
else
140161
{
141-
uint8_t *l_bytePtr = (reinterpret_cast<uint8_t *>(d)) +
142-
sizeof(HOMER_Data_t);
162+
uint8_t *l_bytePtr = (reinterpret_cast<uint8_t *>(d)) + sz_hd;
143163
HOMER_Chip_t *l_chipPtr = NULL;
144164

165+
// The HOMER_Data_t struct may have an uneven size. Add some
166+
// padding to ensure the subsequent HOMER_Chip_t structs are
167+
// word aligned.
168+
const size_t padding = (sz_u32 - (sz_hd % sz_u32)) % sz_u32;
169+
l_bytePtr += padding;
170+
145171
// Have a chip or more to look thru
146172
for ( uint32_t l_chipNum=0;
147173
(l_chipNum < d->chipCount); l_chipNum++ )

0 commit comments

Comments
 (0)