blob: d2c7f77b743fb92fbc8d9172772456ecaf497530 [file] [log] [blame]
Jayanth Othayothdb8d46c2021-10-09 02:19:57 -05001/**
2 * Copyright (C) 2020 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "registration.hpp"
18
19extern "C"
20{
21#include <libpdbg.h>
22#include <libpdbg_sbe.h>
23}
24
25#include "extensions/phal/create_pel.hpp"
Jayanth Othayoth6aba83d2021-10-09 03:04:48 -050026#include "extensions/phal/dump_utils.hpp"
Jayanth Othayothdb8d46c2021-10-09 02:19:57 -050027
28#include <attributes_info.H>
29#include <fmt/format.h>
30#include <libphal.H>
31#include <phal_exception.H>
32#include <sys/wait.h>
33#include <unistd.h>
34
35#include <phosphor-logging/log.hpp>
36
37#include <system_error>
38#include <vector>
39
40namespace openpower
41{
42namespace misc
43{
44
45/**
46 * @brief Calls sbe_enter_mpipl on the SBE in the provided target.
47 * @return void
48 */
49void sbeEnterMpReboot(struct pdbg_target* tgt)
50{
51 using namespace openpower::pel;
52 using namespace openpower::phal;
53 using namespace openpower::phal::sbe;
54 using namespace openpower::phal::exception;
55 using namespace phosphor::logging;
56
57 try
58 {
59 mpiplEnter(tgt);
60 }
61 catch (const sbeError_t& sbeError)
62 {
63 log<level::ERR>(fmt::format("EnterMPIPL failed({}) on proc({})",
64 sbeError.what(), pdbg_target_index(tgt))
65 .c_str());
66
67 std::string event;
68 bool dumpIsRequired = false;
69
70 if (sbeError.errType() == SBE_CMD_TIMEOUT)
71 {
72 event = "org.open_power.Processor.Error.SbeChipOpTimeout";
73 dumpIsRequired = true;
74 }
75 else
76 {
77 event = "org.open_power.Processor.Error.SbeChipOpFailure";
78 }
79
80 // SRC6 : [0:15] chip position [16:23] command class, [24:31] Type
81 uint32_t index = pdbg_target_index(tgt);
82
83 // TODO Replace these consts with pdbg defines once it is exported.
84 // Ref : pdbg/libsbefifo/sbefifo_private.h
85 constexpr auto SBEFIFO_CMD_CLASS_MPIPL = 0xA900;
86 constexpr auto SBEFIFO_CMD_ENTER_MPIPL = 0x01;
87 uint32_t cmd = SBEFIFO_CMD_CLASS_MPIPL | SBEFIFO_CMD_ENTER_MPIPL;
88
89 // To store additional data about ffdc.
90 FFDCData pelAdditionalData;
91 pelAdditionalData.emplace_back("SRC6",
92 std::to_string((index << 16) | cmd));
Jayanth Othayoth6aba83d2021-10-09 03:04:48 -050093 auto logId = createSbeErrorPEL(event, sbeError, pelAdditionalData);
Jayanth Othayothdb8d46c2021-10-09 02:19:57 -050094
95 if (dumpIsRequired)
96 {
Jayanth Othayoth6aba83d2021-10-09 03:04:48 -050097 // Request SBE Dump
98 using namespace openpower::phal::dump;
99 DumpParameters dumpParameters = {logId, index, SBE_DUMP_TIMEOUT,
100 DumpType::SBE};
101 requestDump(dumpParameters);
Jayanth Othayothdb8d46c2021-10-09 02:19:57 -0500102 }
103 throw;
104 }
105 // Capture genaral libphal error
106 catch (const phalError_t& phalError)
107 {
108 // Failure reported
109 log<level::ERR>(fmt::format("captureFFDC: Exception({}) on proc({})",
110 phalError.what(), pdbg_target_index(tgt))
111 .c_str());
112 openpower::pel::createPEL(
113 "org.open_power.Processor.Error.SbeChipOpFailure");
114 throw;
115 }
116
117 log<level::INFO>(
118 fmt::format("Enter MPIPL completed on proc({})", pdbg_target_index(tgt))
119 .c_str());
120}
121
122/**
123 * @brief initiate memory preserving reboot on each SBE.
124 * @return void
125 */
126void enterMpReboot()
127{
128 using namespace phosphor::logging;
129 struct pdbg_target* target;
130 std::vector<pid_t> pidList;
131 bool failed = false;
132 pdbg_targets_init(NULL);
133 ATTR_HWAS_STATE_Type hwasState;
134
135 log<level::INFO>("Starting memory preserving reboot");
136 pdbg_for_each_class_target("proc", target)
137 {
138 if (DT_GET_PROP(ATTR_HWAS_STATE, target, hwasState))
139 {
140 log<level::ERR>("Could not read HWAS_STATE attribute");
141 }
142 if (!hwasState.functional)
143 {
144 continue;
145 }
146
147 pid_t pid = fork();
148
149 if (pid < 0)
150 {
151 log<level::ERR>("Fork failed while starting mp reboot");
152 failed = true;
153 }
154 else if (pid == 0)
155 {
156 sbeEnterMpReboot(target);
157 std::exit(EXIT_SUCCESS);
158 }
159 else
160 {
161 pidList.push_back(std::move(pid));
162 }
163 }
164
165 for (auto& p : pidList)
166 {
167 int status = 0;
168 waitpid(p, &status, 0);
169 if (WEXITSTATUS(status))
170 {
171 log<level::ERR>("Memory preserving reboot failed");
172 failed = true;
173 }
174 }
175
176 if (failed)
177 {
178 std::exit(EXIT_FAILURE);
179 }
180}
181
182REGISTER_PROCEDURE("enterMpReboot", enterMpReboot)
183
184} // namespace misc
185} // namespace openpower