summaryrefslogtreecommitdiffstats
path: root/src/include/usr/hwas/common/hwasCommon.H
blob: 946d2c7a855c34dc47ec157e426938d5b400eb23 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/include/usr/hwas/common/hwasCommon.H $                    */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2012,2017                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/**
 *  @file hwasCommon.H
 *
 *  @brief Notes the HWAS common functions and the HWAS platform-specific
 *          interfaces that need to be defined and implemented.
 */

#ifndef HWASCOMMON_H_
#define HWASCOMMON_H_

// 'system' headers
#include <stdint.h>
#include <targeting/common/target.H>
#include <targeting/common/targetservice.H>
#include <hwas/common/hwasError.H>
#include <hwas/common/hwasCallout.H>

// platform specific headers

// following file needs to do
//  #define HWAS_DBG(_fmt_, _args_...)
//  #define HWAS_ERR(_fmt_, _args_...)
#include <hwas/hwasPlatTrace.H>

// following file needs to do
//  #define HWAS_ASSERT(_expr_...)
#include <hwas/hwasPlatAssert.H>

namespace HWAS
{

/**
 * @brief platform specific code to determine whether the System is at runtime.
 *
 * @return bool  Return true if the System is at runtime; false if not.
 */

bool platSystemIsAtRuntime();

/**
 * @brief platform specific code to determine if minimum hardware
 * check is allowed.
 *
 * @param[out] o_minHwCheckingAllowed   boolean:
 *             TRUE if minimum hardware checking is allowed
 *             FALSE if minimum hardware checking is not allowed
 *
 * @return errlHndl_t       valid errlHndl_t handle if there was an error
 *                          NULL if no errors;
 */
errlHndl_t platIsMinHwCheckingAllowed(bool &o_minHwCheckingAllowed);

/**
 * @brief platform specific code to determine if the targets in the
 *  input list are present or not. If a target is NOT present, it is erased
 *  from the list
 *
 * @param[in]  io_targets   TargetHandleList of targets to check for presence
 *
 * @return errlHndl_t       valid errlHndl_t handle if there was an error
 *                          NULL if no errors;
 */
errlHndl_t platPresenceDetect(TARGETING::TargetHandleList &io_targets);

/**
 * @brief platform specific code to determine the ID/EC of the input
 *  target. The platform specific code is responsible for setting the
 *  ATTR_EC and ATTR_CHIP_ID in each target.
 *
 * @param[in]  i_target    target to check for chip ID/EC
 *
 * @return errlHndl_t       valid errlHndl_t handle if there was an error
 *                          NULL if no errors;
 */
errlHndl_t platReadIDEC(const TARGETING::TargetHandle_t &i_target);

/**
 * @brief platform specific code to determine the PG vector of the input
 *  target. The platform specific code is responsible for returning the
 *  vector. The caller is responsible for allocating and de-allocating the
 *  space.
 *
 * @param[in]  i_target    target to read the Partial Good keyword from
 * @param[out] o_pgData    pointer to area that will hold the partialGood vector
 *                          read from VPD; must be malloc'ed by the caller,
 *                          and must be VPD_CP00_PG_DATA_LENGTH in size.
 *
 * @return errlHndl_t       valid errlHndl_t handle if there was an error
 *                          NULL if no errors;
 */
errlHndl_t platReadPartialGood(const TARGETING::TargetHandle_t &i_target,
                                void *o_pgData);

// constants the platReadPartialGood will use for looking at the VPD data
const uint32_t VPD_CP00_PG_DATA_LENGTH      = 128;
const uint32_t VPD_CP00_PG_HDR_LENGTH       = 1;
const uint32_t VPD_CP00_PG_DATA_ENTRIES     = VPD_CP00_PG_DATA_LENGTH / 2;

// components of the partial good vector
// * = region does not exist in Nimbus
// + = partial good region
// '0' = region is good (NOTE: opposite of P8 where '1' represented good)
// '1' = region is bad or does not exist

const uint32_t VPD_CP00_PG_FSI_INDEX        = 0;
// all good - 4:FSI0, 5:FSI1, 6:FSIa
const uint32_t VPD_CP00_PG_FSI_GOOD         = 0xF1FF;

const uint32_t VPD_CP00_PG_PERVASIVE_INDEX  = 1;
// all good - 3:VITAL, 4:PRV, 5:NET, 6:PIB, 7:OCC, 8:ANPERV, 14:PLLNEST
const uint32_t VPD_CP00_PG_PERVASIVE_GOOD   = 0xE07D;

const uint32_t VPD_CP00_PG_N0_INDEX         = 2;
// all good - 3:VITAL, 4:PRV, 5:NX, 6:CXA0, 7:PBIOE0, 8:PBIOE1, 9:PBIOE2
const uint32_t VPD_CP00_PG_N0_GOOD          = 0xE03F;

const uint32_t VPD_CP00_PG_N1_INDEX         = 3;
// all good - 3:VITAL, 4:PRV, 5:MCD, 6:VA, 7:PBIOO0+, 8:PBIOO1+, 9:MCS23+
const uint32_t VPD_CP00_PG_N1_GOOD          = 0xE03F;
const uint32_t VPD_CP00_PG_N1_PG_MASK       = 0x01C0;
const uint32_t VPD_CP00_PG_N1_PBIOO0        = 0x0100;
const uint32_t VPD_CP00_PG_N1_PBIOO1        = 0x0080;
const uint32_t VPD_CP00_PG_N1_MCS23         = 0x0040;

const uint32_t VPD_CP00_PG_N2_INDEX         = 4;
// all good - 3:VITAL, 4:PRV, 5:CXA1, 6:PCIS0, 7:PCIS1, 8:PCIS2, 9:IOPSI
const uint32_t VPD_CP00_PG_N2_GOOD          = 0xE03F;

const uint32_t VPD_CP00_PG_N3_INDEX         = 5;
// all good - 3:VITAL, 4:PRV, 5:PB, 6:BR, 7:NPU+, 8:MM, 9:INT, 10:MCS01+
const uint32_t VPD_CP00_PG_N3_GOOD          = 0xE01F;
const uint32_t VPD_CP00_PG_N3_PG_MASK       = 0x0120;
const uint32_t VPD_CP00_PG_N3_NPU           = 0x0100;
const uint32_t VPD_CP00_PG_N3_MCS01         = 0x0020;

const uint32_t VPD_CP00_PG_XBUS_INDEX       = 6;
// all good - 3:VITAL, 4:PRV, 5:IOX0*, 6:IOX1, 7:IOX2, 8:IOPPE
//            9:PBIOX0*+, 10:PBIOX1+, 11:PBIOX2+, 14:PLLIOX
// Nimbus doesn't physically have PBIOX0 and IOX0.  IOX0 is
// taken care of by xbus links, need to handle PBIOX0 as part of
// the full chiplet good, so full good is E40D instead of E44D
// Currently, there are two versions of the MVPD PG keyword:
// 0xE44D == XBUS0 bad
// 0xE45D and 0xE55D == XBUS 0,2 bad
// Spec indicates that both iox (second nibble) and pbiox
// (third nibble) are bad for sforza and monza type modules.
// We support generically the following cases:
// 0xE50D --> xbus chiplet good
// 0xE40D --> xbus chiplet good
// and rely solely on the pbiox as the Xbus target indicator
// (0x0040, 0x0020, 0x0010) for all types of chips.
const uint32_t VPD_CP00_PG_XBUS_GOOD_NIMBUS = 0xE40D;
const uint32_t VPD_CP00_PG_XBUS_GOOD_CUMULUS= 0xE00D;
const uint32_t VPD_CP00_PG_XBUS_PG_MASK     = 0x00170;
const uint32_t VPD_CP00_PG_XBUS_IOX[3] = {0x0040, 0x0020, 0x0010};

const uint32_t VPD_CP00_PG_MCxx_INDEX[4]    = {7, 7, 8, 8}; // by MCS
// Nimbus:
// all good - 3:VITAL, 4:PRV, 5:MC01, 6:IOM01+, 7:IOM23+, 14:PLLMEM
// all good - 3:VITAL, 4:PRV, 5:MC23, 6:IOM45+, 7:IOM67+, 14:PLLMEM
// Cumulus:
// all good - 3:VITAL, 4:PRV, 5:MC01, 6:IOM01, 7:IOM01PPE, 14:PLLMEM
// all good - 3:VITAL, 4:PRV, 5:MC23, 6:IOM23, 7:IOM23PPE, 14:PLLMEM
const uint32_t VPD_CP00_PG_MCxx_GOOD        = 0xE0FD;
const uint32_t VPD_CP00_PG_MCxx_PG_MASK     = 0x0300; // Nimbus only
// iom0 and iom4 need to be good for zqcal to work on any
// of the MCAs on that side
const uint32_t VPD_CP00_PG_MCA_MAGIC_PORT_MASK = 0x0200;
const uint32_t VPD_CP00_PG_MCxx_IOMyy[4]    = {0x0200, 0x0100, 0x0200, 0x0100};

const uint32_t VPD_CP00_PG_OB0_INDEX        = 9;
const uint32_t VPD_CP00_PG_OB3_INDEX        = 12;
// all good - 3:VITAL, 4:PRV, 5:PLIOOAx, 6:IOOx, 14:PLLIOO; x=0, 1*, 2*, 3
const uint32_t VPD_CP00_PG_OBUS_GOOD        = 0xE1FD;

const uint32_t VPD_CP00_PG_PCI0_INDEX       = 13;
// all good - 3:VITAL, 4:PRV, 5:PCI00, 6:IOPCI0, 14:PLLPCI0
// all good - 3:VITAL, 4:PRV, 5:PCI11, 6:PCI12, 7:IOPCI1, 14:PLLPCI1
// all good - 3:VITAL, 4:PRV, 5:PCI23, 6:PCI24, 7:PCI25, 8:IOPCI2, 14:PLLPCI2
const uint32_t VPD_CP00_PG_PCIx_GOOD[3]     = {0xE1FD, 0xE0FD, 0xE07D};

const uint32_t VPD_CP00_PG_EP0_INDEX        = 16;
const uint32_t VPD_CP00_PG_EP5_INDEX        = 21;
// all good - 3:VITAL, 4:PRV, 5:EQPB, 6:L30+, 7:L31+,
//            8:L20+, 9:L21+, 10:AN, 11:PBLEQ, 12:REFR0, 13:REFR1, 14:DPLL
const uint32_t VPD_CP00_PG_EPx_GOOD         = 0xE001;
const uint32_t VPD_CP00_PG_EPx_PG_MASK      = 0x03CC;
const uint32_t VPD_CP00_PG_EPx_L3L2REFR[2]  = {0x0288, 0x0144};

const uint32_t VPD_CP00_PG_EC00_INDEX       = 32;
// all good - 3:VITAL, 4:PRV, 5:C00, 6:C01
const uint32_t VPD_CP00_PG_ECxx_GOOD        = 0xE1FF;
const uint32_t VPD_CP00_PG_ECxx_MAX_ENTRIES = 24;

const uint32_t VPD_CP00_PG_MAX_USED_INDEX   = 55;
const uint32_t VPD_CP00_PG_xxx_VITAL        = 0x1000;
const uint32_t VPD_CP00_PG_xxx_PERV         = 0x0800;
const uint32_t VPD_CP00_PG_RESERVED_GOOD    = 0xFFFF;


/**
 * @brief Checks the PG keyword data to determine if the target chip is
 *  functional. The caller is responsible for allocating and de-allocating the
 *  PG keyword space.
 *
 * @param[in]  i_target    pointer to target that we're looking at
 * @param[in]  i_pgData    pointer to area holding the PG keyword read from
 *                          VPD; must be malloc'ed by the caller, and must be
 *                          VPD_CP00_PG_DATA_LENGTH in size.
 *
 * @return bool Return true if the chip is functional; false if not.
 *
 */
bool isChipFunctional(const TARGETING::TargetHandle_t &i_target,
                      const uint16_t i_pgData[VPD_CP00_PG_DATA_LENGTH]);


/**
 * @brief Checks the PG keyword data to determine if the descendant chiplet is
 *  functional. The caller is responsible for allocating and de-allocating the
 *  PG keyword space.
 *
 * @param[in]  i_desc      pointer to descendant of target we're looking at
 * @param[in]  i_pgData    pointer to area holding the PG keyword read from
 *                          VPD; must be malloc'ed by the caller, and must be
 *                          VPD_CP00_PG_DATA_LENGTH in size.
 *
 * @return bool Return true if the descendant is functional; false if not.
 *
 */
bool isDescFunctional(const TARGETING::TargetHandle_t &i_desc,
                      const uint16_t i_pgData[VPD_CP00_PG_DATA_LENGTH]);


/**
 * @deprecated
 * @brief platform specific code to determine the PR vector of the input
 *  target. The platform specific code is responsible for returning the
 *  vector. The caller is responsible for allocating and de-allocating the
 *  space.
 *
 * @param[in]  i_target    target to read the PR keyword from
 * @param[out] o_prData    pointer to area that will hold the PR keyword
 *                          read from VPD; must be malloc'ed by the caller,
 *                          and must be VPD_CP00_PR_DATA_LENGTH in size.
 *
 * @return errlHndl_t       valid errlHndl_t handle if there was an error
 *                          NULL if no errors;
 */
errlHndl_t platReadPR(const TARGETING::TargetHandle_t &i_target,
                                void *o_prData);

// constants the platReadPR will use for looking at the VPD data
const uint32_t VPD_VINI_PR_DATA_LENGTH      = 8; //@deprecrated


/**
 * @brief platform specific code to determine the Lx vector of the input
 *  target. The platform specific code is responsible for returning the
 *  vector. The caller is responsible for allocating and de-allocating the
 *  space.
 *
 * @param[in]  i_mca       MCA target indicating which Lx keyword to read
 * @param[out] o_lxData    pointer to area that will hold the Lx keyword
 *                          read from VPD; must be malloc'ed by the caller,
 *                          and must be VPD_CRP0_LX_DATA_LENGTH in size.
 *
 * @return errlHndl_t       valid errlHndl_t handle if there was an error
 *                          NULL if no errors;
 */
errlHndl_t platReadLx(const TARGETING::TargetHandle_t &i_mca,
                      void *o_lxData);

// constants the platReadLx will use for looking at the VPD data
const uint32_t VPD_CRP0_LX_HDR_DATA_LENGTH  = 256;

const uint32_t VPD_CRP0_LX_FREQ_INDEP_INDEX = 8;
const uint32_t VPD_CRP0_LX_PORT_DISABLED    = 0;

const uint8_t  VPD_CRP0_LX_MIN_X            = 1;
const uint8_t  VPD_CRP0_LX_MAX_X            = 8;


/**
 * @brief platform specific code to read the Field Core Override
 *
 * @param[in]   i_node      node target, where the FCO is stored
 * @param[out]  o_fco       field core override value
 *
 * @return errlHndl_t       valid errlHndl_t handle if there was an error
 *                          NULL if no errors;
 */
errlHndl_t platGetFCO(
        const TARGETING::TargetHandle_t &i_node,
        uint32_t &o_fco);

/**
 * @brief wrapper function to create new errlog in platform-specific manner.
 *
 * @param[in] i_sev        Severity
 * @param[in] i_modId      Module ID   (from HwasModuleID enum)
 * @param[in] i_reasonCode Reason Code (from HwasReasonCode enum)
 * @param[in] i_user1      User Data 1 (defaults to zero)
 * @param[in] i_user2      User Data 2 (defaults to zero)
 *
 * @return errlHndl_t handle pointing to newly created error log
 */
errlHndl_t hwasError(const uint8_t i_sev,
                     const uint8_t i_modId,
                     const uint16_t i_reasonCode,
                     const uint64_t i_user1 = 0,
                     const uint64_t i_user2 = 0);

/**
 * @brief wrapper function to add a procedure callout to an error log in a
 *  platform-specific manner.
 *
 * @param[io] io_errl     Reference to error log handle. Updated with callout
 * @param[in] i_procedure Procedure to callout
 * @param[in] i_priority  Callout Priority
 */
void hwasErrorAddProcedureCallout(errlHndl_t & io_errl,
                                  const HWAS::epubProcedureID i_procedure,
                                  const HWAS::callOutPriority i_priority);

/**
 * @brief wrapper function to add a procedure callout to an error log in a
 *  platform-specific manner.
 *
 */
void platHwasErrorAddHWCallout(errlHndl_t & io_errl,
                           const TARGETING::ConstTargetHandle_t i_target,
                           const HWAS::callOutPriority i_priority,
                           const HWAS::DeconfigEnum i_deconfigState,
                           const HWAS::GARD_ErrorType i_gardErrorType);

/**
 * @brief wrapper function to update the plid in a platform-specific manner.
 *
 * If io_plid is non-zero then io_errl is updated with io_plid
 * Else io_plid is updated with the plid in io_errl
 *
 * @param[io] io_errl Reference to error log handle.
 * @param[io] io_plid Reference to plid.
 */
void hwasErrorUpdatePlid(errlHndl_t & io_errl,
                         uint32_t & io_plid);

/**
 * @brief Platform-specific checks for minimum hardware.
 *  Verifies that the system has enough hardware to proceed through
 *  the IPL. If it does not, error log(s) will be created and committed
 *  for each problem.
 *
 * If io_plid is non-zero then any newly created Error Logs use io_plid
 * Else io_plid is updated with the plid used in the newly created Error Logs
 *
 * @param[io] io_plid Reference to plid.
 * @param[in] i_node  node target to restrict hw check
 * @param[out] o_bootable Indicates whether system is bootable with current
 *             configuratio, if a non NULL pointer is passed erros will not
 *             be logged if system cannot ipl and just return a true or false.
 */
void platCheckMinimumHardware(uint32_t & io_plid,
                            const TARGETING::ConstTargetHandle_t i_node = NULL,
                            bool *o_bootable = NULL);

} // namespace HWAS

#endif // HWASCOMMON_H_
OpenPOWER on IntegriCloud