summaryrefslogtreecommitdiffstats
path: root/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaCeTable.C
blob: 539df11abca3ba7719ab6b8fcae17f3eb0eb9b04 (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
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaCeTable.C $   */
/*                                                                        */
/* IBM CONFIDENTIAL                                                       */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2013,2014              */
/*                                                                        */
/* p1                                                                     */
/*                                                                        */
/* Object Code Only (OCO) source materials                                */
/* Licensed Internal Code Source Materials                                */
/* IBM HostBoot Licensed Internal Code                                    */
/*                                                                        */
/* The source code for this program is not published or otherwise         */
/* divested of its trade secrets, irrespective of what has been           */
/* deposited with the U.S. Copyright Office.                              */
/*                                                                        */
/* Origin: 30                                                             */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#include <prdfCenMbaCeTable.H>

#include <algorithm>

// Framwork includes
#include <iipServiceDataCollector.h>
#include <prdfPlatServices.H>
#include <UtilHash.H>

// Pegasus includes
#include <prdfCenMarkstore.H>

using namespace TARGETING;

namespace PRDF
{

using namespace PlatServices;
using namespace CE_TABLE;

//------------------------------------------------------------------------------

bool CenMbaCeTable::addEntry( const CenAddr & i_addr,
                              const CenSymbol & i_symbol, bool i_isHard )
{
    bool o_doTps = false;

    TableData data ( i_addr, i_symbol.getDram(), i_symbol.getDramPins(),
                     i_symbol.getPortSlct(), i_symbol.getWiringType(),
                     i_isHard, i_symbol.isDramSpared(),
                     i_symbol.isEccSpared() );

    // First, check if the entry already exists. If so, increment its count and
    // move it to the end of the queue.
    CeTable::iterator it = std::find( iv_table.begin(), iv_table.end(), data );
    if ( iv_table.end() != it )
    {
        // Update the count only if the entry is active. Otherwise, use the
        // reset count from the contructor.
        if ( it->active )
            data.count = it->count + 1;

        // Update the DRAM pins
        data.dramPins |= it->dramPins;

        // Check the hard CE status
        if ( it->isHard ) data.isHard = true;

        // Remove the old entry
        iv_table.erase( it );
    }

    // Add the new entry to the end of the list.
    iv_table.push_back( data );

    // Check the new entry's count for single entry threshold.
    if ( TPS_ENTRY_COUNT_TH <= data.count )
    {
        o_doTps = true;
    }

    // Get number of entries in this table on the same rank as the new entry and
    // threshold if needed.
    if ( !o_doTps ) // no point iterating the table if o_doTps is already true
    {
        CenRank thisRank = data.addr.getRank();
        uint32_t rankCount = 0;
        for ( CeTable::iterator it = iv_table.begin();
              it != iv_table.end(); it++ )
        {
            if ( it->active && (it->addr.getRank() == thisRank) )
                rankCount++;
        }

        if ( TPS_RANK_ENTRY_TH <= rankCount )
            o_doTps = true;
    }

    // Note that we intentially checked the entries-per-rank threshold before
    // removing any entries, if the table is full. This is to catch the corner
    // case where the oldest entry is on the same rank as the new entry.

    // If the table is full, remove the oldest inactive entry
    if ( MAX_ENTRIES < iv_table.size() )
    {
        for ( CeTable::iterator it = iv_table.begin();
              it != iv_table.end(); it++ )
        {
            if ( !it->active )
            {
                iv_table.erase( it );
                break;
            }
        }
    }

    // If the table is still full, all entries are active. Pop off the oldest
    // active entry.
    if ( MAX_ENTRIES < iv_table.size() )
        iv_table.pop_front();

    // Do TPS if the table is full.
    if ( MAX_ENTRIES == iv_table.size() )
        o_doTps = true;

    return o_doTps;
}

//------------------------------------------------------------------------------

void CenMbaCeTable::deactivateAll()
{
    // NOTE: We don't want to reset the count here because it will be used for
    //       FFDC. Instead the count will be reset in addEntry() if the entry is
    //       not active.
    for ( CeTable::iterator it = iv_table.begin(); it != iv_table.end(); it++ )
        it->active = false;
}

//------------------------------------------------------------------------------

void CenMbaCeTable::deactivateRank( const CenRank & i_rank )
{
    // NOTE: We don't want to reset the count here because it will be used for
    //       FFDC. Instead the count will be reset in addEntry() if the entry is
    //       not active.
    for ( CeTable::iterator it = iv_table.begin(); it != iv_table.end(); it++ )
    {
        if ( it->addr.getRank() == i_rank )
            it->active = false;
    }
}

//------------------------------------------------------------------------------

void CenMbaCeTable::getMnfgCounts( const CenRank & i_rank,
                                   const CenSymbol & i_symbol,
                                   uint32_t & o_dramCount,
                                   uint32_t & o_hrCount,
                                   uint32_t & o_dimmCount )
{
    o_dramCount = 0; o_hrCount = 0; o_dimmCount = 0;

    const uint32_t dram = i_symbol.getDram();
    const uint32_t ps   = i_symbol.getPortSlct();
    const uint32_t ds   = i_rank.getDimmSlct();

    for ( CeTable::iterator it = iv_table.begin(); it != iv_table.end(); it++ )
    {
        if ( ps != it->portSlct ) continue;

        CenRank itRank = it->addr.getRank();

        if ( ds == itRank.getDimmSlct() )
        {
            o_dimmCount++;

            if ( i_rank == itRank )
            {
                o_hrCount++;

                if ( dram == it->dram )
                    o_dramCount++;
            }
        }
    }
}

//------------------------------------------------------------------------------

void CenMbaCeTable::addCapData( CaptureData & io_cd )
{
    static const size_t sz_word = sizeof(CPU_WORD);

    // Get the maximum capture data size and adjust the size for endianess.
    static const size_t sz_maxData = ((MAX_SIZE+sz_word-1) / sz_word) * sz_word;

    // Initialize to 0.
    uint8_t data[sz_maxData];
    memset( data, 0x00, sz_maxData );

    size_t sz_actData = 0;

    uint32_t mbaPos = getTargetPosition( iv_mbaTrgt );

    for ( CeTable::iterator it = iv_table.begin(); it != iv_table.end(); it++ )
    {
        uint32_t mrnk = it->addr.getRank().getMaster();            //  3-bit
        uint32_t srnk = it->addr.getRank().getSlave();             //  3-bit
        uint32_t svld = it->addr.getRank().isSlaveValid() ? 1 : 0; //  1-bit
        uint32_t bnk  = it->addr.getBank();                        //  4-bit
        uint32_t row  = it->addr.getRow();                         // 17-bit
        uint32_t col  = it->addr.getCol();                         // 12-bit

        uint8_t row0    = (row & 0x10000) >> 16;
        uint8_t row1_8  = (row & 0x0ff00) >>  8;
        uint8_t row9_16 =  row & 0x000ff;

        uint8_t col0_3  = (col & 0xf00) >> 8;
        uint8_t col4_11 =  col & 0x0ff;

        uint8_t active = it->active ? 1 : 0;
        uint8_t isHard = it->isHard ? 1 : 0;
        uint8_t isSp   = it->isDramSpared ? 1 : 0;
        uint8_t isEcc  = it->isEccSpared  ? 1 : 0;

        data[sz_actData  ] = it->count;
        data[sz_actData+1] = (it->type << 5) |
                             (mbaPos << 4) | (it->portSlct << 3) |
                             (isSp << 2) | (isEcc << 1);  // 1 spare bit
        data[sz_actData+2] = (isHard << 7) | (active << 6) | (it->dram & 0x3f);
        data[sz_actData+3] = it->dramPins;
        data[sz_actData+4] = (mrnk << 5) | (srnk << 2) | (svld << 1) | row0;
        data[sz_actData+5] = row1_8;
        data[sz_actData+6] = row9_16;
        data[sz_actData+7] = (bnk << 4) | col0_3;
        data[sz_actData+8] = col4_11;

        sz_actData += ENTRY_SIZE;
    }

    if ( 0 != sz_actData )
    {
        // Fix endianess issues with non PPC machines.
        sz_actData = ((sz_actData + sz_word-1) / sz_word) * sz_word;
        for ( uint32_t i = 0; i < (sz_actData/sz_word); i++ )
            ((CPU_WORD*)data)[i] = htonl(((CPU_WORD*)data)[i]);

        // Add data to capture data.
        BIT_STRING_ADDRESS_CLASS bs ( 0, sz_actData*8, (CPU_WORD *) &data );
        io_cd.Add( iv_mbaTrgt, Util::hashString("MEM_CE_TABLE"), bs );
    }
}

} // end namespace PRDF

OpenPOWER on IntegriCloud