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