summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp/ffdc/p9_collect_ppe_state.C
blob: 0f13a87096b82a25306a6d98954b18f2ea3b68a9 (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
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/ffdc/p9_collect_ppe_state.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2017,2018                        */
/* [+] 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   p9_collect_ppe_state.C
///
/// *HWP HW Owner        : Greg Still <stillgs@us.ibm.com>
/// *HWP HW Backup Owner : Brian Vanderpool <vanderp@us.ibm.com>
/// *HWP FW Owner        : Amit Tendolkar <amit.tendolkar@in.ibm.com>
/// *HWP Team            : PM
/// *HWP Level           : 3
/// *HWP Consumed by     : HB


#include <fapi2.H>
#include <hwp_error_info.H>
#include <p9_const_common.H>

#include <p9_collect_ppe_state.H>
#include <p9_ppe_state.H>

extern "C"
{
    uint32_t addFfdcDataSprs ( std::vector<PPERegValue_t>& i_sprList,
                               fapi2::ReturnCode& o_rc )
    {
        FAPI_INF (">>addFfdcDataSprs: input list count %d", i_sprList.size());
        uint32_t l_regCount = 0;

        // Init FFDC to a detault pattern
        uint32_t l_defaultVal = 0xDEADC0DE;
        fapi2::ffdc_t REG_DEFAULT;
        REG_DEFAULT.ptr() = static_cast<void*>(&l_defaultVal);
        REG_DEFAULT.size() = sizeof (l_defaultVal);

        fapi2::ffdc_t REG_MSR = REG_DEFAULT;
        fapi2::ffdc_t REG_CR = REG_DEFAULT;
        fapi2::ffdc_t REG_CTR = REG_DEFAULT;
        fapi2::ffdc_t REG_LR = REG_DEFAULT;
        fapi2::ffdc_t REG_ISR = REG_DEFAULT;
        fapi2::ffdc_t REG_SRR0 = REG_DEFAULT;
        fapi2::ffdc_t REG_SRR1 = REG_DEFAULT;
        fapi2::ffdc_t REG_TCR = REG_DEFAULT;
        fapi2::ffdc_t REG_TSR = REG_DEFAULT;
        fapi2::ffdc_t REG_DACR = REG_DEFAULT;
        fapi2::ffdc_t REG_DBCR = REG_DEFAULT;
        fapi2::ffdc_t REG_DEC = REG_DEFAULT;
        fapi2::ffdc_t REG_IVPR = REG_DEFAULT;
        fapi2::ffdc_t REG_PIR = REG_DEFAULT;
        fapi2::ffdc_t REG_PVR = REG_DEFAULT;
        fapi2::ffdc_t REG_XER = REG_DEFAULT;

        for (auto& it : i_sprList)
        {
            ++l_regCount;

            switch (it.number)
            {
                // Special SPRs
                case MSR:
                    REG_MSR.ptr() = static_cast<void*>(&it.value);
                    REG_MSR.size() = sizeof (it.value);
                    break;

                case CR:
                    REG_CR.ptr() = static_cast<void*>(&it.value);
                    REG_CR.size() = sizeof (it.value);
                    break;

                // Major SPRs
                case CTR:
                    REG_CTR.ptr() = static_cast<void*>(&it.value);
                    REG_CTR.size() = sizeof (it.value);
                    break;

                case LR:
                    REG_LR.ptr() = static_cast<void*>(&it.value);
                    REG_LR.size() = sizeof (it.value);
                    break;

                case ISR:
                    REG_ISR.ptr() = static_cast<void*>(&it.value);
                    REG_ISR.size() = sizeof (it.value);
                    break;

                case SRR0:
                    REG_SRR0.ptr() = static_cast<void*>(&it.value);
                    REG_SRR0.size() = sizeof (it.value);
                    break;

                case SRR1:
                    REG_SRR1.ptr() = static_cast<void*>(&it.value);
                    REG_SRR1.size() = sizeof (it.value);
                    break;

                case TCR:
                    REG_TCR.ptr() = static_cast<void*>(&it.value);
                    REG_TCR.size() = sizeof (it.value);
                    break;

                case TSR:
                    REG_TSR.ptr() = static_cast<void*>(&it.value);
                    REG_TSR.size() = sizeof (it.value);
                    break;

                // Minor SPRs
                case DACR:
                    REG_DACR.ptr() = static_cast<void*>(&it.value);
                    REG_DACR.size() = sizeof (it.value);
                    break;

                case DBCR:
                    REG_DBCR.ptr() = static_cast<void*>(&it.value);
                    REG_DBCR.size() = sizeof (it.value);
                    break;

                case DEC:
                    REG_DEC.ptr() = static_cast<void*>(&it.value);
                    REG_DEC.size() = sizeof (it.value);
                    break;

                case IVPR:
                    REG_IVPR.ptr() = static_cast<void*>(&it.value);
                    REG_IVPR.size() = sizeof (it.value);
                    break;

                case PIR:
                    REG_PIR.ptr() = static_cast<void*>(&it.value);
                    REG_PIR.size() = sizeof (it.value);
                    break;

                case PVR:
                    REG_PVR.ptr() = static_cast<void*>(&it.value);
                    REG_PVR.size() = sizeof (it.value);
                    break;

                case XER:
                    REG_XER.ptr() = static_cast<void*>(&it.value);
                    REG_XER.size() = sizeof (it.value);
                    break;

                default:
                    l_regCount--;
                    FAPI_ERR ("Unknown PPE SPR %d", it.number);
                    break;
            }
        }

        // add data to ffdc only something was collected
        if (i_sprList.size() != 0)
        {
            FAPI_ADD_INFO_TO_HWP_ERROR (o_rc, RC_PPE_STATE_DATA_SPR);
            FAPI_INF ("<< addFfdcDataSprs: %d SPRs added to FFDC", l_regCount);
            i_sprList.clear ();
        }

        return l_regCount;
    }

    uint32_t addFfdcDataXirs ( std::vector<PPERegValue_t>& i_xirList,
                               fapi2::ReturnCode& o_rc )
    {
        FAPI_INF (">> addFfdcDataXirs: input list count %d", i_xirList.size());
        uint32_t l_regCount = 0;

        // Init FFDC to a detault pattern
        uint32_t l_defaultVal = 0xDEADC0DE;
        fapi2::ffdc_t REG_DEFAULT;
        REG_DEFAULT.ptr() = static_cast<void*>(&l_defaultVal);
        REG_DEFAULT.size() = sizeof (l_defaultVal);

        fapi2::ffdc_t REG_XSR = REG_DEFAULT;
        fapi2::ffdc_t REG_IAR = REG_DEFAULT;
        fapi2::ffdc_t REG_IR = REG_DEFAULT;
        fapi2::ffdc_t REG_EDR = REG_DEFAULT;
        fapi2::ffdc_t REG_SPRG0 = REG_DEFAULT;

        for (auto& it : i_xirList)
        {
            ++l_regCount;

            switch (it.number)
            {
                case XSR:
                    REG_XSR.ptr() = static_cast<void*>(&it.value);
                    REG_XSR.size() = sizeof (it.value);
                    break;

                case IAR:
                    REG_IAR.ptr() = static_cast<void*>(&it.value);
                    REG_IAR.size() = sizeof (it.value);
                    break;

                case IR:
                    REG_IR.ptr() = static_cast<void*>(&it.value);
                    REG_IR.size() = sizeof (it.value);
                    break;

                case EDR:
                    REG_EDR.ptr() = static_cast<void*>(&it.value);
                    REG_EDR.size() = sizeof (it.value);
                    break;

                case SPRG0:
                    REG_SPRG0.ptr() = static_cast<void*>(&it.value);
                    REG_SPRG0.size() = sizeof (it.value);
                    break;

                default:
                    l_regCount--;
                    FAPI_ERR ("Unknown PPE XIR %d", it.number);
                    break;
            }
        }

        // add data to ffdc only something was collected
        if ( i_xirList.size() != 0 )
        {
            FAPI_ADD_INFO_TO_HWP_ERROR (o_rc, RC_PPE_STATE_DATA_XIR);
            FAPI_INF ("<< addFfdcDataXirs: %d XIRs added to FFDC", l_regCount);
            i_xirList.clear ();
        }

        return l_regCount;
    }


    uint32_t addFfdcDataGprs ( std::vector<PPERegValue_t>& i_gprList,
                               fapi2::ReturnCode& o_rc )
    {
        FAPI_INF (">> addFfdcDataGprs: input list count %d", i_gprList.size());
        uint32_t l_regCount = 0;

        // Init FFDC to a detault pattern
        uint32_t l_defaultVal = 0xDEADC0DE;
        fapi2::ffdc_t REG_DEFAULT;
        REG_DEFAULT.ptr() = static_cast<void*>(&l_defaultVal);
        REG_DEFAULT.size() = sizeof (l_defaultVal);

        fapi2::ffdc_t REG_R0 = REG_DEFAULT;
        fapi2::ffdc_t REG_R1 = REG_DEFAULT;
        fapi2::ffdc_t REG_R2 = REG_DEFAULT;
        fapi2::ffdc_t REG_R3 = REG_DEFAULT;
        fapi2::ffdc_t REG_R4 = REG_DEFAULT;
        fapi2::ffdc_t REG_R5 = REG_DEFAULT;
        fapi2::ffdc_t REG_R6 = REG_DEFAULT;
        fapi2::ffdc_t REG_R7 = REG_DEFAULT;
        fapi2::ffdc_t REG_R8 = REG_DEFAULT;
        fapi2::ffdc_t REG_R9 = REG_DEFAULT;
        fapi2::ffdc_t REG_R10 = REG_DEFAULT;
        fapi2::ffdc_t REG_R13 = REG_DEFAULT;
        fapi2::ffdc_t REG_R28 = REG_DEFAULT;
        fapi2::ffdc_t REG_R29 = REG_DEFAULT;
        fapi2::ffdc_t REG_R30 = REG_DEFAULT;
        fapi2::ffdc_t REG_R31 = REG_DEFAULT;

        for (auto& it : i_gprList)
        {
            ++l_regCount;

            switch (it.number)
            {
                case R0:
                    REG_R0.ptr() = static_cast<void*>(&it.value);
                    REG_R0.size() = sizeof (it.value);
                    break;

                case R1:
                    REG_R1.ptr() = static_cast<void*>(&it.value);
                    REG_R1.size() = sizeof (it.value);
                    break;

                case R2:
                    REG_R2.ptr() = static_cast<void*>(&it.value);
                    REG_R2.size() = sizeof (it.value);
                    break;

                case R3:
                    REG_R3.ptr() = static_cast<void*>(&it.value);
                    REG_R3.size() = sizeof (it.value);
                    break;

                case R4:
                    REG_R4.ptr() = static_cast<void*>(&it.value);
                    REG_R4.size() = sizeof (it.value);
                    break;

                case R5:
                    REG_R5.ptr() = static_cast<void*>(&it.value);
                    REG_R5.size() = sizeof (it.value);
                    break;

                case R6:
                    REG_R6.ptr() = static_cast<void*>(&it.value);
                    REG_R6.size() = sizeof (it.value);
                    break;

                case R7:
                    REG_R7.ptr() = static_cast<void*>(&it.value);
                    REG_R7.size() = sizeof (it.value);
                    break;

                case R8:
                    REG_R8.ptr() = static_cast<void*>(&it.value);
                    REG_R8.size() = sizeof (it.value);
                    break;

                case R9:
                    REG_R9.ptr() = static_cast<void*>(&it.value);
                    REG_R9.size() = sizeof (it.value);
                    break;

                case R10:
                    REG_R10.ptr() = static_cast<void*>(&it.value);
                    REG_R10.size() = sizeof (it.value);
                    break;

                case R13:
                    REG_R13.ptr() = static_cast<void*>(&it.value);
                    REG_R13.size() = sizeof (it.value);
                    break;

                case R28:
                    REG_R28.ptr() = static_cast<void*>(&it.value);
                    REG_R28.size() = sizeof (it.value);
                    break;

                case R29:
                    REG_R29.ptr() = static_cast<void*>(&it.value);
                    REG_R29.size() = sizeof (it.value);
                    break;

                case R30:
                    REG_R30.ptr() = static_cast<void*>(&it.value);
                    REG_R30.size() = sizeof (it.value);
                    break;

                case R31:
                    REG_R31.ptr() = static_cast<void*>(&it.value);
                    REG_R31.size() = sizeof (it.value);
                    break;

                default:
                    l_regCount--;
                    FAPI_ERR ("Unknown PPE GPR %d", it.number);
                    break;
            }
        }

        // add data to ffdc only something was collected
        if (i_gprList.size () != 0)
        {
            FAPI_ADD_INFO_TO_HWP_ERROR (o_rc, RC_PPE_STATE_DATA_GPR);
            FAPI_INF ("<< addFfdcDataGprs: %d GPRs added to FFDC", l_regCount);
            i_gprList.clear ();
        }

        return l_regCount;
    }

    fapi2::ReturnCode
    p9_collect_ppe_state ( const fapi2::ffdc_t& i_target,
                           const fapi2::ffdc_t& i_mode,
                           const fapi2::ffdc_t& i_v_ppe_addresses,
                           fapi2::ReturnCode& o_rc )
    {
        FAPI_INF (">> p9_collect_ppe_state");
        fapi2::ReturnCode l_rc;
        bool l_limitToXIRs = false;

        fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM;
        fapi2::ATTR_INITIATED_PM_RESET_Type l_pm_reset_active;
        fapi2::ATTR_EXECUTION_PLATFORM_Type l_plat = 0;
        fapi2::ffdc_t PPE_BASE_ADDR;

        fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_proc_chip =
            *(reinterpret_cast<const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> *>
              (i_target.ptr()));

        std::vector<uint64_t> l_ppe_addresses =
            *(reinterpret_cast<const std::vector<uint64_t>*>
              (i_v_ppe_addresses.ptr()));

        PPE_DUMP_MODE l_mode = *(reinterpret_cast<const PPE_DUMP_MODE*>(i_mode.ptr()));

        // If call to this HWP is in PM Reset flow then just collect XIRs.
        // Full PPE state will be collected as a part of PM Recovery in
        // later part of PM reset flow. Do not want to artifically HALT for debug
        FAPI_ATTR_GET(fapi2::ATTR_INITIATED_PM_RESET,
                      l_proc_chip,
                      l_pm_reset_active);

        // On FSP, Ramming PPE Regs is blacklisted, collect only XIRs
        FAPI_ATTR_GET(fapi2::ATTR_EXECUTION_PLATFORM, FAPI_SYSTEM, l_plat);

        if ((fapi2::ENUM_ATTR_INITIATED_PM_RESET_ACTIVE == l_pm_reset_active) ||
            (fapi2::ENUM_ATTR_EXECUTION_PLATFORM_FSP == l_plat))
        {
            l_limitToXIRs = true;
        }

        std::vector<PPERegValue_t> l_v_sprs;
        std::vector<PPERegValue_t> l_v_xirs;
        std::vector<PPERegValue_t> l_v_gprs;

        for (auto& it1 : l_ppe_addresses )
        {
            fapi2::ReturnCode l_rc_tmp = fapi2::current_err;
            uint64_t l_addr = it1;
            bool l_isHalted = false;

            // Override l_mode dynamically to decide what gets collected
            if (l_limitToXIRs == true)
            {
                // Either on a FSP or in PM Reset, avoid halting & RAMming the PPE
                l_mode = XIRS; // Override #1
            }
            else
            {
                // Neither on a FSP, not in PM Reset, read PPE Halt State and decide
                l_rc = ppe_isHalted (l_proc_chip, it1, &l_isHalted);

                if (l_rc == fapi2::FAPI2_RC_SUCCESS)
                {
                    if (l_isHalted == true)
                    {
                        // Already halted, so go ahead and get everything possible
                        // the l_mode here set just to steer the code to do that
                        l_mode = HALT; // Override #2
                    }
                    else if (l_mode != FORCE_HALT)
                    {
                        // Not halted & User not requested to FORCE a HALT for FFDC
                        // Avoid halting the PPE
                        l_mode = XIRS; // Override #3
                    }
                    else
                    {
                        // mode remains the user supplied FORCE_HALT, that hits the big
                        // hammer to try to reset the PPE bypassing completion of any
                        // in-flight instructions or sync or reset operations. PPE may
                        // need a hard reset to recover fomr a force halt.
                    }
                }
                else
                {
                    // Unable to read PPE Halt State, avoid halting the PPE
                    l_mode = XIRS; // Override #4
                }
            }

            FAPI_INF ("p9_collect_ppe_state: PPE Base Addr 0x%.16llX, 0x%.8X",
                      it1, l_mode);
            FAPI_EXEC_HWP (l_rc, p9_ppe_state, l_proc_chip, it1, l_mode,
                           l_v_sprs, l_v_xirs, l_v_gprs);

            // Ignore l_rc and continue adding whatever was collected

            fapi2::current_err = l_rc_tmp;

            FAPI_INF ("Adding PPE Addr: 0x%.16llX, SPRs: %d XIRs: %d GPRs: %d",
                      it1, l_v_sprs.size(), l_v_xirs.size(), l_v_gprs.size());

            // since this accepts multiple PPE addresses, log which PPE Addr the
            // FFDC Data belongs to, to the FFDC info

            PPE_BASE_ADDR.ptr() = static_cast<void*>(&l_addr);
            PPE_BASE_ADDR.size() = sizeof (l_addr);
            FAPI_ADD_INFO_TO_HWP_ERROR (o_rc, RC_PPE_BASE_ADDR_XIXCR);

            // Add all the PPE State Registers to the FFDC
            addFfdcDataXirs (l_v_xirs, o_rc);
            addFfdcDataSprs (l_v_sprs, o_rc);
            addFfdcDataGprs (l_v_gprs, o_rc);
        }

        FAPI_INF ("<< p9_collect_ppe_state");
        return fapi2::FAPI2_RC_SUCCESS; // always return success
    }
}
OpenPOWER on IntegriCloud