91 auto dump_mcesa(
const arch::s390x::cpu::lowcore::zx_lowcore& lc)
noexcept
94 zxfoundation::sys::printk::pcrit(
95 "mcck: mcesa dump — psw={:#018x}:{:#018x}\n",
96 static_cast<u64>(lc.psw_save_area.mask),
97 static_cast<u64>(lc.psw_save_area.addr));
98 zxfoundation::sys::printk::pcrit(
99 "mcck: mcesa gprs:\n {:#018x} {:#018x} {:#018x} {:#018x}\n "
100 "{:#018x} {:#018x} {:#018x} {:#018x}\n "
101 "{:#018x} {:#018x} {:#018x} {:#018x}\n "
102 "{:#018x} {:#018x} {:#018x} {:#018x}\n",
103 lc.gpregs_save_area[0], lc.gpregs_save_area[1],
104 lc.gpregs_save_area[2], lc.gpregs_save_area[3],
105 lc.gpregs_save_area[4], lc.gpregs_save_area[5],
106 lc.gpregs_save_area[6], lc.gpregs_save_area[7],
107 lc.gpregs_save_area[8], lc.gpregs_save_area[9],
108 lc.gpregs_save_area[10], lc.gpregs_save_area[11],
109 lc.gpregs_save_area[12], lc.gpregs_save_area[13],
110 lc.gpregs_save_area[14], lc.gpregs_save_area[15]);
111 zxfoundation::sys::printk::pcrit(
112 "mcck: mcesa CRS:\n {:#018x} {:#018x} {:#018x} {:#018x}\n",
113 lc.cregs_save_area[0], lc.cregs_save_area[1],
114 lc.cregs_save_area[2], lc.cregs_save_area[3]);
115 zxfoundation::sys::printk::pcrit(
116 "mcck: mcesa — last_break={:#018x} prefix={:#010x} "
117 "fpc={:#010x} tod_pg={:#010x}\n",
118 lc.last_break_save_area, lc.prefixreg_save_area,
119 lc.fpt_creg_save_area, lc.tod_progreg_save_area);
120 zxfoundation::sys::printk::pcrit(
121 "mcck: mcesa — cpu_timer={:#010x}{:#010x} clock_comp="
122 "{:#010x}{:#010x}\n",
123 lc.cpu_timer_save_area[1], lc.cpu_timer_save_area[0],
124 lc.clock_comp_save_area[1], lc.clock_comp_save_area[0]);
140 auto handle(cpu::irq::irq_frame* frame)
noexcept ->
void {
141 auto* lc = cpu::lowcore::get_current();
142 const u64 mcic = lc->mcck_interruption_code;
143 if (mcic == 0ULL)
return;
145 lc->mcck_interruption_code = 0ULL;
147 if ((mcic & MCIC_BACKLOG) != 0ULL) {
148 zxfoundation::sys::syschk::syschk_warning(
149 ::lib::kernel_error::from_machine(
150 ::lib::machine_error::backlog),
151 "mcck: backlog set — stacked machine-check detected; "
152 "prior MCCK not fully processed before this interruption");
155 if ((mcic & MCIC_SD) != 0ULL) {
156 if ((mcic & MCIC_AP) != 0ULL)
157 zxfoundation::sys::printk::pnotice(
158 "mcck: ancillary-report (AP) available\n");
159 zxfoundation::sys::syschk::syschk_fatal(
160 ::lib::kernel_error::from_machine(::lib::machine_error::system_damage),
161 "mcck: system damage — unrecoverable");
164 if ((mcic & MCIC_CD) != 0ULL) {
165 zxfoundation::sys::syschk::syschk_fatal(
166 ::lib::kernel_error::from_machine(::lib::machine_error::timing_facility),
167 "mcck: timing-facility damage — TOD / clock comparator stale");
170 if ((mcic & MCIC_PD) != 0ULL) {
171 if ((mcic & MCIC_B) != 0ULL) {
172 auto& pcp = cpu::lowcore::this_cpu_percpu();
173 const u64 now =
static_cast<u64>(cpu::clock::stcke().tod);
174 if (detail::ipd_window_expired(pcp, now)) {
176 pcp.ipd_window_deadline = now + MAX_IPD_WINDOW_TOD;
179 if (pcp.ipd_count >= MAX_IPD_COUNT) {
180 zxfoundation::sys::syschk::syschk_critical(
181 ::lib::kernel_error::from_machine(
182 ::lib::machine_error::inst_process_damage),
183 "mcck: {} nullifying IPDs within 5 min — unrecoverable",
186 zxfoundation::sys::syschk::syschk_notice(
187 ::lib::kernel_error::from_machine(
188 ::lib::machine_error::inst_process_damage),
189 "mcck: nullifying IPD ({} of {}) — survived",
190 pcp.ipd_count, MAX_IPD_COUNT);
194 zxfoundation::sys::syschk::syschk_critical(
195 ::lib::kernel_error::from_machine(
196 ::lib::machine_error::inst_process_damage),
197 "mcck: instruction-processing damage — unrecoverable");
201 if ((mcic & MCIC_ED) != 0ULL && (mcic & MCIC_EC) != 0ULL) {
202 const u32 ext_code = lc->external_damage_code;
203 zxfoundation::sys::syschk::syschk_warning(
204 ::lib::kernel_error::from_machine(::lib::machine_error::external_damage),
205 "mcck: external damage code={:#010x}", ext_code);
206 zxfoundation::sys::irq::deferred_set(
207 zxfoundation::sys::irq::DEFERRED_MCCK_PENDING_BIT);
210 if ((mcic & MCIC_SE) != 0ULL) {
211 zxfoundation::sys::syschk::syschk_fatal(
212 ::lib::kernel_error::from_machine(
213 ::lib::machine_error::storage_error_uncorrected),
214 "mcck: storage error uncorrected");
216 if ((mcic & MCIC_KE) != 0ULL) {
217 zxfoundation::sys::syschk::syschk_fatal(
218 ::lib::kernel_error::from_machine(
219 ::lib::machine_error::storage_key_error),
220 "mcck: storage-key error uncorrected");
222 if ((mcic & MCIC_DS) != 0ULL && (mcic & MCIC_FA) != 0ULL) {
223 const u64 fsa = lc->failing_storage_address;
224 zxfoundation::sys::syschk::syschk_fatal(
225 ::lib::kernel_error::from_machine(
226 ::lib::machine_error::storage_degradation),
227 "mcck: storage degradation at fsa={:#018x}", fsa);
228 }
else if ((mcic & MCIC_DS) != 0ULL) {
232 zxfoundation::sys::syschk::syschk_fatal(
233 ::lib::kernel_error::from_machine(
234 ::lib::machine_error::storage_degradation),
235 "mcck: storage degradation — failing address unknown");
237 if ((mcic & MCIC_FA) != 0ULL) {
238 const u64 fsa = lc->failing_storage_address;
239 zxfoundation::sys::syschk::syschk_warning(
240 ::lib::kernel_error::from_machine(
241 ::lib::machine_error::failing_storage_addr),
242 "mcck: failing storage address={:#018x}", fsa);
243 zxfoundation::sys::irq::deferred_set(
244 zxfoundation::sys::irq::DEFERRED_MCCK_PENDING_BIT);
247 if ((mcic & MCIC_SR) != 0ULL) {
248 zxfoundation::sys::syschk::syschk_notice(
249 ::lib::kernel_error::from_machine(::lib::machine_error::system_recovery),
250 "mcck: system recovery completed");
252 if ((mcic & MCIC_DG) != 0ULL) {
253 zxfoundation::sys::syschk::syschk_warning(
254 ::lib::kernel_error::from_machine(::lib::machine_error::degradation),
255 "mcck: degradation reported");
256 zxfoundation::sys::irq::deferred_set(
257 zxfoundation::sys::irq::DEFERRED_MCCK_PENDING_BIT);
259 if ((mcic & MCIC_W) != 0ULL) {
260 zxfoundation::sys::syschk::syschk_notice(
261 ::lib::kernel_error::from_machine(::lib::machine_error::warning),
262 "mcck: warning pending");
263 zxfoundation::sys::irq::deferred_set(
264 zxfoundation::sys::irq::DEFERRED_MCCK_PENDING_BIT);
266 if ((mcic & MCIC_CP) != 0ULL) {
267 zxfoundation::sys::syschk::syschk_notice(
268 ::lib::kernel_error::from_machine(::lib::machine_error::channel_report_pending),
269 "mcck: channel-report pending — CRW handling armed");
270 zxfoundation::sys::irq::deferred_set(
271 zxfoundation::sys::irq::DEFERRED_MCCK_PENDING_BIT);
273 if ((mcic & MCIC_SP) != 0ULL) {
274 zxfoundation::sys::syschk::syschk_warning(
275 ::lib::kernel_error::from_machine(
276 ::lib::machine_error::service_processor_damage),
277 "mcck: service-processor damage");
279 if ((mcic & MCIC_CK) != 0ULL) {
280 zxfoundation::sys::syschk::syschk_warning(
281 ::lib::kernel_error::from_machine(
282 ::lib::machine_error::channel_subsystem_damage),
283 "mcck: channel-subsystem damage");
285 if ((mcic & MCIC_SC) != 0ULL) {
286 zxfoundation::sys::printk::pinfo(
287 "mcck: storage error corrected (informational)\n");
290 if (!detail::nmi_registers_valid(mcic)) {
292 (frame->psw_mask & cpu::psw::PSW_BIT_PSTATE) != 0;
294 detail::dump_mcesa(*lc);
295 zxfoundation::sys::syschk::syschk_fatal(
296 ::lib::kernel_error::from_machine(::lib::machine_error::system_damage),
297 "mcck: nmi registers invalid in nucleus — register state unreliable");
300 reinterpret_cast<zxfoundation::dgp::domain::domain*>(lc->current_domain);
302 zxfoundation::dgp::signal::signal_enqueue(
304 zxfoundation::dgp::signal::signal_kind::fault,
305 static_cast<u64>(lc->failing_storage_address));
306 zxfoundation::sched::sched_resched_current();
308 detail::dump_mcesa(*lc);
311 zxfoundation::sys::irq::irq_dispatch(
312 zxfoundation::sys::irq::IRQ_BASE_MCCK, frame,
313 arch::s390x::cpu::irq::ZX_IRQ_CLASS_MCCK);