summaryrefslogtreecommitdiffstats
path: root/src/usr/diag/attn/common/attnmem.C
blob: 524262f672e2e4fd478c9d879ea7aa560798dbe0 (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
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/attn/common/attnmem.C $                          */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2014,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 attnmem.C
 *
 * @brief HBATTN Memory attention operations function definitions.
 */

#include <errl/errlmanager.H>
#include <targeting/common/targetservice.H>
#include "common/attnmem.H"
#include "common/attnlist.H"
#include "common/attntarget.H"
#include "attntrace.H"
#include <targeting/common/utilFilter.H>

using namespace std;
using namespace PRDF;
using namespace TARGETING;
using namespace ERRORLOG;

namespace ATTN
{

typedef struct
{
    uint32_t              chipletFir;
    uint32_t              chipletFirMask;
    ATTENTION_VALUE_TYPE  attnType;

    // First of four bits to check
    // (2 bits apart)
    uint64_t              intrBitToChk;
} attnMemoryFirs_t;


const attnMemoryFirs_t  ATTN_MEM_CHIPLET_FIRS[] =
{
    { 0x07040009, 0x0704001A,
          HOST_ATTN,   0x4000000000000000ull },  // Host    1,3,5,7
    { 0x07040018, 0x07040019,
          UNIT_CS,     0x4000000000000000ull },  // unit CS  1,3,5,7
    { 0x07040001, 0x07040002,
          RECOVERABLE, 0x0800000000000000ull },  // Recov   4,6,8,10
    { 0x07040000, 0x07040002,
          CHECK_STOP,  0x0800000000000000ull }   // chkstop  4,6,8,10
};

// 4 DMI units per MC
const uint32_t  ATTN_MAX_DMI_INTRS = 4;

// Processor FIR set when MemBuffer raises attention
const uint32_t  ATTN_ADDR_CHIFIR_DATA = 0x07010900;
const uint32_t  ATTN_ADDR_CHIFIR_MASK = 0x07010903;

// Attention bit positions in CHIFIR 16, 19,20,21
const uint64_t  ATTN_CEN_CHECKSTOP = 0x0000800000000000ull ;
const uint64_t  ATTN_CEN_RECOV     = 0x0000100000000000ull ;
const uint64_t  ATTN_CEN_SPECIAL   = 0x0000080000000000ull ;
const uint64_t  ATTN_CEN_MAINT_CMD = 0x0000040000000000ull ;



// @TODO RTC: 180469
//  Move to target services part and then update all the CXX testing
TargetHandle_t attnGetMembuf( const TargetHandle_t &i_mc,
                              const uint32_t i_dmi,
                              const ATTENTION_VALUE_TYPE i_attnType )
{
    // where i_dmi is 0:7 value
    TargetHandle_t    membuf   = NULL;
    TargetHandleList  l_dmiList;
    errlHndl_t        l_err = NULL;
    uint64_t          l_chifirData = 0;
    uint64_t          l_chifirMask = 0;
    uint64_t          l_chifirIntr = 0;


    // Get the list of DMI units for MC unit passed in
    getChildChiplets(l_dmiList, i_mc, TYPE_DMI);

    for ( auto  l_dmiTarg : l_dmiList )
    {
        ATTN_TRACE("   MemRes(%d) - DMI:%d chiplet from MC",
                   i_dmi, l_dmiTarg->getAttr<ATTR_CHIP_UNIT>() );

        if ( i_dmi == l_dmiTarg->getAttr<ATTR_CHIP_UNIT>() )
        {
            ATTN_SLOW("    MemOps::resolve - DMI Match:%d",
                      i_dmi  );

            // Get mem buffer associated with the DMI chiplet
            TargetHandleList  l_memBufList;
            getChildAffinityTargets( l_memBufList, l_dmiTarg,
                                     CLASS_CHIP, TYPE_MEMBUF );

            if (l_memBufList.size() == 1)
            {
                // Validate Centaur actually raised attention
                l_err = getScom( l_dmiTarg,
                                 ATTN_ADDR_CHIFIR_DATA,
                                 l_chifirData );

                if (NULL == l_err)
                {
                    l_err = getScom( l_dmiTarg,
                                     ATTN_ADDR_CHIFIR_MASK,
                                     l_chifirMask );
                } // end if no error on getscom CHIFIR

                if (NULL == l_err)
                {
                    // Check for active attention
                    l_chifirIntr = l_chifirData & ~l_chifirMask;

                    ATTN_SLOW("    MemOps::res - CenAttn:%016llx ::%X",
                               l_chifirIntr, i_attnType );

                    // Is it attn we are looking for ?
                    if ( ( (i_attnType == HOST_ATTN) &&
                           ((l_chifirIntr & ATTN_CEN_SPECIAL) ||
                            (l_chifirIntr & ATTN_CEN_MAINT_CMD)
                           )
                         )  ||

                         ( (i_attnType == RECOVERABLE) &&
                           (l_chifirIntr & ATTN_CEN_RECOV)
                         )  ||
                         ( (i_attnType == CHECK_STOP) &&
                           (l_chifirIntr & ATTN_CEN_CHECKSTOP)
                         )  ||

                         ( (i_attnType == UNIT_CS) &&
                           (l_chifirIntr & ATTN_CEN_CHECKSTOP)
                         )
                       )
                    {
                        membuf = l_memBufList[0];
                        // Found right DMI and memory buffer
                        // so stop loooping
                        break;
                    } // end if matching attention in membuf

                } // end if no error on getscom CHIFIR Mask


                // Handle any elog
                if (NULL != l_err)
                {
                    errlCommit(l_err, ATTN_COMP_ID);
                }  // if elog

            } // end one membuf found

        } // end if correct DMI target

    } // end for on DMI targets


    return(membuf);

} // end attnGetMembuf


bool MemOps::resolve(
        PRDF::AttnData &  i_AttnData,
        const uint32_t  i_mcNumber,
        TARGETING::TargetHandle_t  i_procTarg )
{
    errlHndl_t  l_err = 0;
    bool        l_attnFound = false;
    uint64_t    l_firData  = 0;
    uint64_t    l_maskData = 0;
    uint64_t    l_intData  = 0;
    uint32_t    l_mcNum    = 0;
    uint32_t    l_dmi_0to7 = 0;


    TargetHandleList l_mcTargetList;

    // predicate of functional MC units
    PredicateCTM           l_unitMatch(CLASS_UNIT, TYPE_MC);
    PredicateIsFunctional  l_functional;
    PredicatePostfixExpr   l_pred;

    l_pred.push(&l_unitMatch).push(&l_functional).And();

    // Get all MC units associated with input processor
    targetService().getAssociated(
            l_mcTargetList,
            i_procTarg,
            TARGETING::TargetService::CHILD_BY_AFFINITY,
            TARGETING::TargetService::ALL,
            &l_pred);


    // Find correct MC chiplet
    for ( auto  l_mc : l_mcTargetList )
    {
        ATTN_TRACE("MemOps::resolve - MC chiplet:%d", i_mcNumber);
        l_mcNum = l_mc->getAttr<ATTR_CHIP_UNIT>();

        if (l_mcNum == i_mcNumber)
        {
            // Check for attention using chiplet summary registers
            uint32_t  l_numFirs = sizeof(ATTN_MEM_CHIPLET_FIRS) /
                                  sizeof(attnMemoryFirs_t);

            for ( uint32_t l_cFir=0; (l_cFir < l_numFirs); l_cFir++ )
            {
                // Verify the attention type
                if (i_AttnData.attnType ==
                               ATTN_MEM_CHIPLET_FIRS[l_cFir].attnType)
                {
                    // get chiplet FIR data
                    l_err = getScom(l_mc,
                                    ATTN_MEM_CHIPLET_FIRS[l_cFir].chipletFir,
                                    l_firData);

                    if (NULL == l_err)
                    {
                        // Get chiplet MASK
                        l_err = getScom(l_mc,
                                  ATTN_MEM_CHIPLET_FIRS[l_cFir].chipletFirMask,
                                  l_maskData);

                        ATTN_SLOW(
                           "...MemRes:cAddr:%016llx cFir:%016llx cMask:%016llx",
                           ATTN_MEM_CHIPLET_FIRS[l_cFir].chipletFir,
                           l_firData, l_maskData );

                        if (NULL == l_err)
                        {
                            // Recoverable FIR & MASK are 2 bits off
                            // so need to handle this here
                            if (RECOVERABLE == i_AttnData.attnType)
                            {
                                l_firData = l_firData >> 2;
                            } // end if recoverable

                            // Check for active attention
                            l_intData  = l_firData & ~l_maskData;

                            ATTN_TRACE("...resolve - IntrActive::%016llx ",
                                        l_intData );

                            // Interrupts are in various bit positions,
                            // so will shift a mask 2 bit positions for each DMI
                            for ( uint32_t l_intNum=0;
                                   (l_intNum < ATTN_MAX_DMI_INTRS); l_intNum++)
                            {
                                // Check for active DMI interrupt
                                if ( l_intData &
                                     (ATTN_MEM_CHIPLET_FIRS[l_cFir].intrBitToChk
                                                            >> (l_intNum*2)) )
                                {
                                    // Heirarchy:  MC -> MI -> DMI -> Centaur
                                    // Valid active interrupt on DMI Bus
                                    // Need  membuf targ for passing to PRD

                                    // Determine DMI chiplet - 0 thru 7 value
                                    l_dmi_0to7 = (l_mcNum * ATTN_MAX_DMI_INTRS)
                                                  + l_intNum;

                                    AttnData d;
                                    // add membuf target if found
                                    d.targetHndl = attnGetMembuf(l_mc,
                                                          l_dmi_0to7,
                                                          i_AttnData.attnType);

                                    if (NULL != d.targetHndl)
                                    {
                                        ATTN_TRACE(
                                           "     MemOpsRes -Got membuf Attn:%d",
                                        ATTN_MEM_CHIPLET_FIRS[l_cFir].attnType);

                                        i_AttnData.targetHndl = d.targetHndl;
                                        l_attnFound = true;
                                        // handle the one attention
                                        break;
                                    } // end if valid memory buffer target

                                } // end if active DMI Interrupt

                            } // end for loop thru all potential DMI interrupts

                        } // if ok reading mask data
                        else
                        {
                            ATTN_ERR("Mem:Resolve FirMask Fail Addr:%08X",
                                 ATTN_MEM_CHIPLET_FIRS[l_cFir].chipletFirMask);
                        } // end else failed reading mask

                    } // if ok reading FIR data
                    else
                    {
                        ATTN_ERR("Mem:Resolve Fir Fail Addr:%08X",
                                 ATTN_MEM_CHIPLET_FIRS[l_cFir].chipletFir);
                    } // end else failed reading FIR

                    // Handle any elog
                    if (NULL != l_err)
                    {
                        errlCommit(l_err, ATTN_COMP_ID);
                    }  // if elog

                    // Found attn match so get out
                    break;
                } // end if attention matches

            } // end for thru chiplet FIRs

            // We handle attns one at a time
            break;
        } // end if found MC chiplet

    } // end for on MC chiplets


    return l_attnFound;
}

MemOps::MemOps()
{

}

MemOps::~MemOps()
{

}
}
OpenPOWER on IntegriCloud