1 #include "extensions/phal/create_pel.hpp"
2 #include "extensions/phal/dump_utils.hpp"
3 #include "registration.hpp"
4 
5 #include <attributes_info.H>
6 #include <fmt/format.h>
7 #include <libipl.H>
8 #include <libphal.H>
9 #include <phal_exception.H>
10 extern "C"
11 {
12 #include <libpdbg.h>
13 }
14 #include <phosphor-logging/log.hpp>
15 
16 namespace openpower
17 {
18 namespace phal
19 {
20 using namespace openpower::pel;
21 using namespace openpower::phal::exception;
22 using namespace phosphor::logging;
23 
24 /**
25  * @brief Stop instruction executions on all functional threads in the
26  *        host processors.
27  *        This procedure is used to stop all threads in the system in
28  *        Attempt best case approch. Like issue processor level stopall
29  *        chip-op with ignore hardware error mode. Since this function
30  *        is used in power-off/error path, ignore the internal error now.
31  */
32 void threadStopAll(void)
33 {
34     // CMD details based on SBE spec, used for logging purpose
35     constexpr auto SBEFIFO_CMD_CLASS_INSTRUCTION = 0xA700;
36     constexpr auto SBEFIFO_CMD_CONTROL_INSN = 0x01;
37     uint32_t cmd = SBEFIFO_CMD_CLASS_INSTRUCTION | SBEFIFO_CMD_CONTROL_INSN;
38 
39     try
40     {
41         // initialize the pdbg.
42         openpower::phal::pdbg::init();
43 
44         // Check Host is started.
45         if (!openpower::phal::sbe::isPrimaryIplDone())
46         {
47             log<level::INFO>("threadStopAll : skipping, Host is not running");
48             return;
49         }
50 
51         struct pdbg_target* procTarget;
52         ATTR_HWAS_STATE_Type hwasState;
53         pdbg_for_each_class_target("proc", procTarget)
54         {
55             if (DT_GET_PROP(ATTR_HWAS_STATE, procTarget, hwasState))
56             {
57                 log<level::ERR>(
58                     fmt::format("({})Could not read HWAS_STATE attribute",
59                                 pdbg_target_path(procTarget))
60                         .c_str());
61                 continue;
62             }
63             if (!hwasState.functional)
64             {
65                 continue;
66             }
67 
68             try
69             {
70                 openpower::phal::sbe::threadStopProc(procTarget);
71             }
72             catch (const sbeError_t& sbeError)
73             {
74                 auto errType = sbeError.errType();
75 
76                 // Create PEL only for  valid SBE reported failures
77                 if (errType == SBE_CMD_FAILED)
78                 {
79                     log<level::ERR>(
80                         fmt::format(
81                             "threadStopAll failed({}) on proc({})",
82                             static_cast<
83                                 std::underlying_type<ipl_error_type>::type>(
84                                 errType),
85                             pdbg_target_index(procTarget))
86                             .c_str());
87 
88                     uint32_t index = pdbg_target_index(procTarget);
89                     // To store additional data about ffdc.
90                     FFDCData pelAdditionalData;
91 
92                     // SRC6 : [0:15] chip position
93                     //        [16:23] command class,  [24:31] Type
94                     pelAdditionalData.emplace_back(
95                         "SRC6", std::to_string((index << 16) | cmd));
96 
97                     // Create informational error log.
98                     createSbeErrorPEL(
99                         "org.open_power.Processor.Error.SbeChipOpFailure",
100                         sbeError, pelAdditionalData, procTarget,
101                         Severity::Informational);
102                 }
103                 else
104                 {
105                     // SBE is not ready to accept chip-ops,
106                     // Skip the request, no additional error handling required.
107                     log<level::INFO>(
108                         fmt::format("threadStopAll: Skipping ({}) on proc({})",
109                                     sbeError.what(),
110                                     pdbg_target_index(procTarget))
111                             .c_str());
112                 }
113                 continue;
114             }
115             log<level::INFO>(
116                 fmt::format("Processor thread stopall completed on proc({})",
117                             pdbg_target_index(procTarget))
118                     .c_str());
119         }
120     }
121     // Capture general exception
122     catch (const std::exception& ex)
123     {
124         // This failure could be related to BMC firmware
125         // Dont throw exception on failure because, need to proceed
126         // further to complete power-off/reboot.
127         log<level::ERR>(
128             fmt::format("threadStopAll: Exception({})", ex.what()).c_str());
129 
130         // To store additional data about ffdc.
131         FFDCData pelAdditionalData;
132 
133         // SRC6 : [0:15] chip position, setting 0xFF to indicate generic fail
134         //        [16:23] command class,  [24:31] Type
135         pelAdditionalData.emplace_back("SRC6",
136                                        std::to_string((0xFF << 16) | cmd));
137         json jsonCalloutDataList;
138         jsonCalloutDataList = json::array();
139         json jsonCalloutData;
140         jsonCalloutData["Procedure"] = "BMC0001";
141         jsonCalloutData["Priority"] = "H";
142         jsonCalloutDataList.emplace_back(jsonCalloutData);
143         openpower::pel::createErrorPEL(
144             "org.open_power.Processor.Error.SbeChipOpFailure",
145             jsonCalloutDataList, pelAdditionalData, Severity::Informational);
146         return;
147     }
148 }
149 
150 REGISTER_PROCEDURE("threadStopAll", threadStopAll)
151 
152 } // namespace phal
153 } // namespace openpower
154