summaryrefslogtreecommitdiffstats
path: root/src/import/generic/memory/lib/utils/mss_generic_check.H
blob: f31440e14bc7f6eb094046ff2de6f7e744d10dd7 (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
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/generic/memory/lib/utils/mss_generic_check.H $     */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2018,2019                        */
/* [+] 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 mss_generic_check.H
/// @brief Checker functions for generic API
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: HB:FSP

#ifndef _MSS_GENERIC_CHECK_H_
#define _MSS_GENERIC_CHECK_H_

#include <fapi2.H>
#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
#include <generic/memory/lib/utils/scom.H>
#include <generic/memory/lib/utils/c_str.H>

namespace mss
{
namespace check
{

///
/// @brief Checks whether any FIRs have lit up on a target
/// @tparam MC MC type for which to check FIR's
/// @tparam T the fapi2::TargetType which hold the FIR bits
/// @param[in] i_target - the target on which to operate
/// @param[in,out] io_rc - the return code for the function
/// @param[out] o_fir_error - true iff a FIR was hit
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok
///
template< mss::mc_type MC, fapi2::TargetType T >
fapi2::ReturnCode bad_fir_bits( const fapi2::Target<T>& i_target, fapi2::ReturnCode& io_rc, bool& o_fir_error );

///
/// @brief Checks whether the passed in FIRs have any un-masked errors set
/// @tparam MC MC type for which to check FIR's
/// @tparam T the fapi2::TargetType which hold the FIR bits
/// @param[in] i_target - the target on which to operate
/// @param[in] i_fir_regs - FIR register and mask register
/// @param[out] o_fir_error - true iff a FIR was hit
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok
///
template< mss::mc_type MC, fapi2::TargetType T >
inline fapi2::ReturnCode fir_with_mask( const fapi2::Target<T>& i_target,
                                        const std::pair<uint64_t, uint64_t>& i_fir_regs,
                                        bool& o_fir_error )
{
    // Temporary variables to make the code a bit more readable
    const auto FIR_REG = i_fir_regs.first;
    const auto FIR_MASK = i_fir_regs.second;

    fapi2::buffer<uint64_t> l_fir;
    fapi2::buffer<uint64_t> l_fir_mask;

    // Read the registers
    FAPI_TRY(mss::getScom(i_target, FIR_REG, l_fir));
    FAPI_TRY(mss::getScom(i_target, FIR_MASK, l_fir_mask));


    // The mask register will need to be inverted as a 0 in the mask register means the FIR is legit
    // A bitwise and works the opposite way
    l_fir_mask.invert();

    // If we have any unmasked bit, set that we have a FIR error and exit out with success
    // Note: we want to set success here as PRD will find the FIR as "new" and retrigger the procedure this way
    o_fir_error = ((l_fir & l_fir_mask) != 0);

    // And print the information for debuggability
    FAPI_INF("%s %s on reg 0x%016lx value 0x%016lx and mask 0x%016lx value 0x%016lx", mss::c_str(i_target),
             o_fir_error ? "has FIR's set" : "has no FIR's set", FIR_REG, l_fir, FIR_MASK, l_fir_mask.invert());

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Checks whether a FIR or unlocked PLL could be the root cause of another failure
/// @tparam MC MC type for which to check FIR's
/// @tparam T the fapi2::TargetType which hold the FIR bits
/// @param[in] i_target - the target on which to operate
/// @param[in,out] io_rc - the return code for the function
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok
/// @note This is a helper function to enable unit testing
///
template< mss::mc_type MC, fapi2::TargetType T >
fapi2::ReturnCode hostboot_fir_or_pll_fail( const fapi2::Target<T>& i_target, fapi2::ReturnCode& io_rc)
{
    // We didn't have an error, so return success
    if(io_rc == fapi2::FAPI2_RC_SUCCESS)
    {
        FAPI_INF("%s has a good return code, returning success", mss::c_str(i_target));
        return fapi2::FAPI2_RC_SUCCESS;
    }

    fapi2::ReturnCode l_fircheck_scom_err(fapi2::FAPI2_RC_SUCCESS);
    bool l_fir_error = false;

    FAPI_ERR("%s has a bad return code, time to check some firs!", mss::c_str(i_target));

    l_fircheck_scom_err = bad_fir_bits<MC>(i_target, io_rc, l_fir_error);

    FAPI_ERR("%s took a fail. FIR was %s", mss::c_str(i_target),
             l_fir_error ? "set - returning FIR RC" : "unset - returning inputted RC");

    // If we had a FIR error, log the original error and return success
    // PRD will handle the original error
    if(l_fir_error)
    {
        fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
    }
    else
    {
        fapi2::current_err = io_rc;
    }

    return fapi2::current_err;
}

///
/// @brief Checks whether a FIR or unlocked PLL could be the root cause of another failure, if a check fir boolean is passed in
/// @tparam MC MC type for which to check FIR's
/// @tparam T the fapi2::TargetType which hold the FIR bits
/// @param[in] i_target - the target on which to operate
/// @param[in,out] io_rc - the return code for the function
/// @param[in] i_check_fir - true IFF the FIR needs to be checked - defaults to true
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok
///
template< mss::mc_type MC, fapi2::TargetType T >
fapi2::ReturnCode fir_or_pll_fail( const fapi2::Target<T>& i_target,
                                   fapi2::ReturnCode& io_rc,
                                   const bool i_check_fir = true)
{
#ifdef __HOSTBOOT_MODULE

    fapi2::ReturnCode l_rc(io_rc);

    // If need be, check the FIR below
    if(i_check_fir)
    {
        // Handle any issues according to PRD FIR scheme, as a FIR could have caused this issue
        l_rc = hostboot_fir_or_pll_fail<MC>(i_target, l_rc);
    }

    return l_rc;

#else
    return io_rc;
#endif
}

///
/// @brief Checks conditional passes and implements traces & exits if it fails
/// @tparam T fapi2 target type
/// @tparam IT input data type
/// @tparam FFDC error callout code type
/// @param[in] i_target fapi2 target
/// @param[in] i_conditional conditional that we are testing against
/// @param[in] i_byte_index byte index
/// @param[in] i_data debug data
/// @param[in] i_ffdc_codes FFDC code
/// @param[in] i_err_str error string - defaulted to ""
/// @return FAPI2_RC_SUCCESS iff okay
///
template< fapi2::TargetType T, typename IT , typename FFDC >
inline fapi2::ReturnCode invalid_value(const fapi2::Target<T>& i_target,
                                       const bool i_conditional,
                                       const size_t i_byte_index,
                                       const IT i_data,
                                       const FFDC i_ffdc_codes,
                                       const char* i_err_str = "")
{
    FAPI_ASSERT(i_conditional,
                fapi2::MSS_FAILED_DATA_INTEGRITY_CHECK().
                set_VALUE(i_data).
                set_BYTE(i_byte_index).
                set_TARGET(i_target).
                set_FFDC_CODE(i_ffdc_codes),
                "%s %s Byte %d, Data returned: %d.",
                spd::c_str(i_target),
                i_err_str,
                i_byte_index,
                i_data);

    return fapi2::FAPI2_RC_SUCCESS;

fapi_try_exit:
    return fapi2::current_err;

} // fail_for_invalid_value

} // check
}// mss

#endif
OpenPOWER on IntegriCloud