1db8d46c0SJayanth Othayoth /**
2db8d46c0SJayanth Othayoth * Copyright (C) 2020 IBM Corporation
3db8d46c0SJayanth Othayoth *
4db8d46c0SJayanth Othayoth * Licensed under the Apache License, Version 2.0 (the "License");
5db8d46c0SJayanth Othayoth * you may not use this file except in compliance with the License.
6db8d46c0SJayanth Othayoth * You may obtain a copy of the License at
7db8d46c0SJayanth Othayoth *
8db8d46c0SJayanth Othayoth * http://www.apache.org/licenses/LICENSE-2.0
9db8d46c0SJayanth Othayoth *
10db8d46c0SJayanth Othayoth * Unless required by applicable law or agreed to in writing, software
11db8d46c0SJayanth Othayoth * distributed under the License is distributed on an "AS IS" BASIS,
12db8d46c0SJayanth Othayoth * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13db8d46c0SJayanth Othayoth * See the License for the specific language governing permissions and
14db8d46c0SJayanth Othayoth * limitations under the License.
15db8d46c0SJayanth Othayoth */
16db8d46c0SJayanth Othayoth
17db8d46c0SJayanth Othayoth #include "registration.hpp"
18db8d46c0SJayanth Othayoth
19db8d46c0SJayanth Othayoth extern "C"
20db8d46c0SJayanth Othayoth {
21db8d46c0SJayanth Othayoth #include <libpdbg.h>
22db8d46c0SJayanth Othayoth #include <libpdbg_sbe.h>
23db8d46c0SJayanth Othayoth }
24db8d46c0SJayanth Othayoth
25db8d46c0SJayanth Othayoth #include "extensions/phal/create_pel.hpp"
266aba83d2SJayanth Othayoth #include "extensions/phal/dump_utils.hpp"
27db8d46c0SJayanth Othayoth
28db8d46c0SJayanth Othayoth #include <attributes_info.H>
29db8d46c0SJayanth Othayoth #include <libphal.H>
30db8d46c0SJayanth Othayoth #include <phal_exception.H>
31db8d46c0SJayanth Othayoth #include <sys/wait.h>
32db8d46c0SJayanth Othayoth #include <unistd.h>
33db8d46c0SJayanth Othayoth
34db8d46c0SJayanth Othayoth #include <phosphor-logging/log.hpp>
35db8d46c0SJayanth Othayoth
36*e0dd7af4SJayanth Othayoth #include <format>
37db8d46c0SJayanth Othayoth #include <system_error>
38db8d46c0SJayanth Othayoth #include <vector>
39db8d46c0SJayanth Othayoth
40db8d46c0SJayanth Othayoth namespace openpower
41db8d46c0SJayanth Othayoth {
42db8d46c0SJayanth Othayoth namespace misc
43db8d46c0SJayanth Othayoth {
44db8d46c0SJayanth Othayoth
45db8d46c0SJayanth Othayoth /**
46db8d46c0SJayanth Othayoth * @brief Calls sbe_enter_mpipl on the SBE in the provided target.
47db8d46c0SJayanth Othayoth * @return void
48db8d46c0SJayanth Othayoth */
sbeEnterMpReboot(struct pdbg_target * tgt)49db8d46c0SJayanth Othayoth void sbeEnterMpReboot(struct pdbg_target* tgt)
50db8d46c0SJayanth Othayoth {
51db8d46c0SJayanth Othayoth using namespace openpower::pel;
52db8d46c0SJayanth Othayoth using namespace openpower::phal;
53db8d46c0SJayanth Othayoth using namespace openpower::phal::sbe;
54db8d46c0SJayanth Othayoth using namespace openpower::phal::exception;
55db8d46c0SJayanth Othayoth using namespace phosphor::logging;
56db8d46c0SJayanth Othayoth
57db8d46c0SJayanth Othayoth try
58db8d46c0SJayanth Othayoth {
59db8d46c0SJayanth Othayoth mpiplEnter(tgt);
60db8d46c0SJayanth Othayoth }
61db8d46c0SJayanth Othayoth catch (const sbeError_t& sbeError)
62db8d46c0SJayanth Othayoth {
6362638200SJayanth Othayoth if (sbeError.errType() == SBE_CHIPOP_NOT_ALLOWED)
6462638200SJayanth Othayoth {
6562638200SJayanth Othayoth // SBE is not ready to accept chip-ops,
6662638200SJayanth Othayoth // Skip the request, no additional error handling required.
6762638200SJayanth Othayoth log<level::INFO>(
68*e0dd7af4SJayanth Othayoth std::format("EnterMPIPL: Skipping ({}) on proc({})",
6962638200SJayanth Othayoth sbeError.what(), pdbg_target_index(tgt))
7062638200SJayanth Othayoth .c_str());
7162638200SJayanth Othayoth return;
7262638200SJayanth Othayoth }
7362638200SJayanth Othayoth
74*e0dd7af4SJayanth Othayoth log<level::ERR>(std::format("EnterMPIPL failed({}) on proc({})",
75db8d46c0SJayanth Othayoth sbeError.what(), pdbg_target_index(tgt))
76db8d46c0SJayanth Othayoth .c_str());
77db8d46c0SJayanth Othayoth
78db8d46c0SJayanth Othayoth std::string event;
79db8d46c0SJayanth Othayoth bool dumpIsRequired = false;
80db8d46c0SJayanth Othayoth
81db8d46c0SJayanth Othayoth if (sbeError.errType() == SBE_CMD_TIMEOUT)
82db8d46c0SJayanth Othayoth {
83db8d46c0SJayanth Othayoth event = "org.open_power.Processor.Error.SbeChipOpTimeout";
84db8d46c0SJayanth Othayoth dumpIsRequired = true;
85db8d46c0SJayanth Othayoth }
86db8d46c0SJayanth Othayoth else
87db8d46c0SJayanth Othayoth {
88db8d46c0SJayanth Othayoth event = "org.open_power.Processor.Error.SbeChipOpFailure";
89db8d46c0SJayanth Othayoth }
90db8d46c0SJayanth Othayoth
91db8d46c0SJayanth Othayoth // SRC6 : [0:15] chip position [16:23] command class, [24:31] Type
92db8d46c0SJayanth Othayoth uint32_t index = pdbg_target_index(tgt);
93db8d46c0SJayanth Othayoth
94db8d46c0SJayanth Othayoth // TODO Replace these consts with pdbg defines once it is exported.
95db8d46c0SJayanth Othayoth // Ref : pdbg/libsbefifo/sbefifo_private.h
96db8d46c0SJayanth Othayoth constexpr auto SBEFIFO_CMD_CLASS_MPIPL = 0xA900;
97db8d46c0SJayanth Othayoth constexpr auto SBEFIFO_CMD_ENTER_MPIPL = 0x01;
98db8d46c0SJayanth Othayoth uint32_t cmd = SBEFIFO_CMD_CLASS_MPIPL | SBEFIFO_CMD_ENTER_MPIPL;
99db8d46c0SJayanth Othayoth
100db8d46c0SJayanth Othayoth // To store additional data about ffdc.
101db8d46c0SJayanth Othayoth FFDCData pelAdditionalData;
102db8d46c0SJayanth Othayoth pelAdditionalData.emplace_back("SRC6",
103db8d46c0SJayanth Othayoth std::to_string((index << 16) | cmd));
104e5ba5fd0SJayanth Othayoth auto logId = createSbeErrorPEL(event, sbeError, pelAdditionalData, tgt);
105db8d46c0SJayanth Othayoth
106db8d46c0SJayanth Othayoth if (dumpIsRequired)
107db8d46c0SJayanth Othayoth {
1086aba83d2SJayanth Othayoth // Request SBE Dump
1096aba83d2SJayanth Othayoth using namespace openpower::phal::dump;
1106aba83d2SJayanth Othayoth DumpParameters dumpParameters = {logId, index, SBE_DUMP_TIMEOUT,
1116aba83d2SJayanth Othayoth DumpType::SBE};
1126aba83d2SJayanth Othayoth requestDump(dumpParameters);
113db8d46c0SJayanth Othayoth }
114db8d46c0SJayanth Othayoth throw;
115db8d46c0SJayanth Othayoth }
116db8d46c0SJayanth Othayoth // Capture genaral libphal error
117db8d46c0SJayanth Othayoth catch (const phalError_t& phalError)
118db8d46c0SJayanth Othayoth {
119db8d46c0SJayanth Othayoth // Failure reported
120*e0dd7af4SJayanth Othayoth log<level::ERR>(std::format("captureFFDC: Exception({}) on proc({})",
121db8d46c0SJayanth Othayoth phalError.what(), pdbg_target_index(tgt))
122db8d46c0SJayanth Othayoth .c_str());
123db8d46c0SJayanth Othayoth openpower::pel::createPEL(
124db8d46c0SJayanth Othayoth "org.open_power.Processor.Error.SbeChipOpFailure");
125db8d46c0SJayanth Othayoth throw;
126db8d46c0SJayanth Othayoth }
127db8d46c0SJayanth Othayoth
128db8d46c0SJayanth Othayoth log<level::INFO>(
129*e0dd7af4SJayanth Othayoth std::format("Enter MPIPL completed on proc({})", pdbg_target_index(tgt))
130db8d46c0SJayanth Othayoth .c_str());
131db8d46c0SJayanth Othayoth }
132db8d46c0SJayanth Othayoth
133db8d46c0SJayanth Othayoth /**
134db8d46c0SJayanth Othayoth * @brief initiate memory preserving reboot on each SBE.
135db8d46c0SJayanth Othayoth * @return void
136db8d46c0SJayanth Othayoth */
enterMpReboot()137db8d46c0SJayanth Othayoth void enterMpReboot()
138db8d46c0SJayanth Othayoth {
139db8d46c0SJayanth Othayoth using namespace phosphor::logging;
140db8d46c0SJayanth Othayoth struct pdbg_target* target;
141db8d46c0SJayanth Othayoth std::vector<pid_t> pidList;
142db8d46c0SJayanth Othayoth bool failed = false;
143db8d46c0SJayanth Othayoth pdbg_targets_init(NULL);
144db8d46c0SJayanth Othayoth ATTR_HWAS_STATE_Type hwasState;
145db8d46c0SJayanth Othayoth
146db8d46c0SJayanth Othayoth log<level::INFO>("Starting memory preserving reboot");
147db8d46c0SJayanth Othayoth pdbg_for_each_class_target("proc", target)
148db8d46c0SJayanth Othayoth {
149db8d46c0SJayanth Othayoth if (DT_GET_PROP(ATTR_HWAS_STATE, target, hwasState))
150db8d46c0SJayanth Othayoth {
151db8d46c0SJayanth Othayoth log<level::ERR>("Could not read HWAS_STATE attribute");
152db8d46c0SJayanth Othayoth }
153db8d46c0SJayanth Othayoth if (!hwasState.functional)
154db8d46c0SJayanth Othayoth {
155db8d46c0SJayanth Othayoth continue;
156db8d46c0SJayanth Othayoth }
157db8d46c0SJayanth Othayoth
158db8d46c0SJayanth Othayoth pid_t pid = fork();
159db8d46c0SJayanth Othayoth
160db8d46c0SJayanth Othayoth if (pid < 0)
161db8d46c0SJayanth Othayoth {
162db8d46c0SJayanth Othayoth log<level::ERR>("Fork failed while starting mp reboot");
163db8d46c0SJayanth Othayoth failed = true;
164db8d46c0SJayanth Othayoth }
165db8d46c0SJayanth Othayoth else if (pid == 0)
166db8d46c0SJayanth Othayoth {
167db8d46c0SJayanth Othayoth sbeEnterMpReboot(target);
168db8d46c0SJayanth Othayoth std::exit(EXIT_SUCCESS);
169db8d46c0SJayanth Othayoth }
170db8d46c0SJayanth Othayoth else
171db8d46c0SJayanth Othayoth {
172db8d46c0SJayanth Othayoth pidList.push_back(std::move(pid));
173db8d46c0SJayanth Othayoth }
174db8d46c0SJayanth Othayoth }
175db8d46c0SJayanth Othayoth
17662c8c93eSMarri Devender Rao // if no functional proc found exit with failure
17762c8c93eSMarri Devender Rao if (pidList.size() == 0)
17862c8c93eSMarri Devender Rao {
17962c8c93eSMarri Devender Rao log<level::ERR>("EnterMPReboot is not executed on any processors");
18062c8c93eSMarri Devender Rao openpower::pel::createPEL("org.open_power.PHAL.Error.MPReboot");
18162c8c93eSMarri Devender Rao std::exit(EXIT_FAILURE);
18262c8c93eSMarri Devender Rao }
18362c8c93eSMarri Devender Rao
184db8d46c0SJayanth Othayoth for (auto& p : pidList)
185db8d46c0SJayanth Othayoth {
186db8d46c0SJayanth Othayoth int status = 0;
187db8d46c0SJayanth Othayoth waitpid(p, &status, 0);
188db8d46c0SJayanth Othayoth if (WEXITSTATUS(status))
189db8d46c0SJayanth Othayoth {
190db8d46c0SJayanth Othayoth log<level::ERR>("Memory preserving reboot failed");
191db8d46c0SJayanth Othayoth failed = true;
192db8d46c0SJayanth Othayoth }
193db8d46c0SJayanth Othayoth }
194db8d46c0SJayanth Othayoth
195db8d46c0SJayanth Othayoth if (failed)
196db8d46c0SJayanth Othayoth {
197db8d46c0SJayanth Othayoth std::exit(EXIT_FAILURE);
198db8d46c0SJayanth Othayoth }
199db8d46c0SJayanth Othayoth }
200db8d46c0SJayanth Othayoth
201db8d46c0SJayanth Othayoth REGISTER_PROCEDURE("enterMpReboot", enterMpReboot)
202db8d46c0SJayanth Othayoth
203db8d46c0SJayanth Othayoth } // namespace misc
204db8d46c0SJayanth Othayoth } // namespace openpower
205