| 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* |
| 3 | * Machine check handler |
| 4 | * |
| 5 | * Copyright IBM Corp. 2000, 2009 |
| 6 | * Author(s): Ingo Adlung <adlung@de.ibm.com>, |
| 7 | * Martin Schwidefsky <schwidefsky@de.ibm.com>, |
| 8 | * Cornelia Huck <cornelia.huck@de.ibm.com>, |
| 9 | */ |
| 10 | |
| 11 | #include <linux/kernel_stat.h> |
| 12 | #include <linux/utsname.h> |
| 13 | #include <linux/cpufeature.h> |
| 14 | #include <linux/init.h> |
| 15 | #include <linux/errno.h> |
| 16 | #include <linux/entry-common.h> |
| 17 | #include <linux/hardirq.h> |
| 18 | #include <linux/log2.h> |
| 19 | #include <linux/kprobes.h> |
| 20 | #include <linux/kmemleak.h> |
| 21 | #include <linux/time.h> |
| 22 | #include <linux/module.h> |
| 23 | #include <linux/sched/signal.h> |
| 24 | #include <linux/kvm_host.h> |
| 25 | #include <asm/lowcore.h> |
| 26 | #include <asm/ctlreg.h> |
| 27 | #include <asm/fpu.h> |
| 28 | #include <asm/smp.h> |
| 29 | #include <asm/stp.h> |
| 30 | #include <asm/cputime.h> |
| 31 | #include <asm/nmi.h> |
| 32 | #include <asm/crw.h> |
| 33 | #include <asm/asm-offsets.h> |
| 34 | #include <asm/pai.h> |
| 35 | #include <asm/vtime.h> |
| 36 | |
| 37 | struct mcck_struct { |
| 38 | unsigned int kill_task : 1; |
| 39 | unsigned int channel_report : 1; |
| 40 | unsigned int warning : 1; |
| 41 | unsigned int stp_queue : 1; |
| 42 | unsigned long mcck_code; |
| 43 | }; |
| 44 | |
| 45 | static DEFINE_PER_CPU(struct mcck_struct, cpu_mcck); |
| 46 | |
| 47 | static inline int nmi_needs_mcesa(void) |
| 48 | { |
| 49 | return cpu_has_vx() || cpu_has_gs(); |
| 50 | } |
| 51 | |
| 52 | /* |
| 53 | * The initial machine check extended save area for the boot CPU. |
| 54 | * It will be replaced on the boot CPU reinit with an allocated |
| 55 | * structure. The structure is required for machine check happening |
| 56 | * early in the boot process. |
| 57 | */ |
| 58 | static struct mcesa boot_mcesa __aligned(MCESA_MAX_SIZE); |
| 59 | |
| 60 | void __init nmi_alloc_mcesa_early(u64 *mcesad) |
| 61 | { |
| 62 | if (!nmi_needs_mcesa()) |
| 63 | return; |
| 64 | *mcesad = __pa(&boot_mcesa); |
| 65 | if (cpu_has_gs()) |
| 66 | *mcesad |= ilog2(MCESA_MAX_SIZE); |
| 67 | } |
| 68 | |
| 69 | int nmi_alloc_mcesa(u64 *mcesad) |
| 70 | { |
| 71 | unsigned long size; |
| 72 | void *origin; |
| 73 | |
| 74 | *mcesad = 0; |
| 75 | if (!nmi_needs_mcesa()) |
| 76 | return 0; |
| 77 | size = cpu_has_gs() ? MCESA_MAX_SIZE : MCESA_MIN_SIZE; |
| 78 | origin = kmalloc(size, GFP_KERNEL); |
| 79 | if (!origin) |
| 80 | return -ENOMEM; |
| 81 | /* The pointer is stored with mcesa_bits ORed in */ |
| 82 | kmemleak_not_leak(ptr: origin); |
| 83 | *mcesad = __pa(origin); |
| 84 | if (cpu_has_gs()) |
| 85 | *mcesad |= ilog2(MCESA_MAX_SIZE); |
| 86 | return 0; |
| 87 | } |
| 88 | |
| 89 | void nmi_free_mcesa(u64 *mcesad) |
| 90 | { |
| 91 | if (!nmi_needs_mcesa()) |
| 92 | return; |
| 93 | kfree(__va(*mcesad & MCESA_ORIGIN_MASK)); |
| 94 | } |
| 95 | |
| 96 | static __always_inline char *nmi_puts(char *dest, const char *src) |
| 97 | { |
| 98 | while (*src) |
| 99 | *dest++ = *src++; |
| 100 | *dest = 0; |
| 101 | return dest; |
| 102 | } |
| 103 | |
| 104 | static __always_inline char *u64_to_hex(char *dest, u64 val) |
| 105 | { |
| 106 | int i, num; |
| 107 | |
| 108 | for (i = 1; i <= 16; i++) { |
| 109 | num = (val >> (64 - 4 * i)) & 0xf; |
| 110 | if (num >= 10) |
| 111 | *dest++ = 'A' + num - 10; |
| 112 | else |
| 113 | *dest++ = '0' + num; |
| 114 | } |
| 115 | *dest = 0; |
| 116 | return dest; |
| 117 | } |
| 118 | |
| 119 | static notrace void nmi_print_info(void) |
| 120 | { |
| 121 | struct lowcore *lc = get_lowcore(); |
| 122 | char message[100]; |
| 123 | char *ptr; |
| 124 | int i; |
| 125 | |
| 126 | ptr = nmi_puts(dest: message, src: "Unrecoverable machine check, code: " ); |
| 127 | ptr = u64_to_hex(dest: ptr, val: lc->mcck_interruption_code); |
| 128 | ptr = nmi_puts(dest: ptr, src: "\n" ); |
| 129 | sclp_emergency_printk(message); |
| 130 | |
| 131 | ptr = nmi_puts(dest: message, src: init_utsname()->release); |
| 132 | ptr = nmi_puts(dest: ptr, src: "\n" ); |
| 133 | sclp_emergency_printk(message); |
| 134 | |
| 135 | ptr = nmi_puts(dest: message, src: arch_hw_string); |
| 136 | ptr = nmi_puts(dest: ptr, src: "\n" ); |
| 137 | sclp_emergency_printk(message); |
| 138 | |
| 139 | ptr = nmi_puts(dest: message, src: "PSW: " ); |
| 140 | ptr = u64_to_hex(dest: ptr, val: lc->mcck_old_psw.mask); |
| 141 | ptr = nmi_puts(dest: ptr, src: " " ); |
| 142 | ptr = u64_to_hex(dest: ptr, val: lc->mcck_old_psw.addr); |
| 143 | ptr = nmi_puts(dest: ptr, src: " PFX: " ); |
| 144 | ptr = u64_to_hex(dest: ptr, val: (u64)get_lowcore()); |
| 145 | ptr = nmi_puts(dest: ptr, src: "\n" ); |
| 146 | sclp_emergency_printk(message); |
| 147 | |
| 148 | ptr = nmi_puts(dest: message, src: "LBA: " ); |
| 149 | ptr = u64_to_hex(dest: ptr, val: lc->last_break_save_area); |
| 150 | ptr = nmi_puts(dest: ptr, src: " EDC: " ); |
| 151 | ptr = u64_to_hex(dest: ptr, val: lc->external_damage_code); |
| 152 | ptr = nmi_puts(dest: ptr, src: " FSA: " ); |
| 153 | ptr = u64_to_hex(dest: ptr, val: lc->failing_storage_address); |
| 154 | ptr = nmi_puts(dest: ptr, src: "\n" ); |
| 155 | sclp_emergency_printk(message); |
| 156 | |
| 157 | ptr = nmi_puts(dest: message, src: "CRS:\n" ); |
| 158 | sclp_emergency_printk(message); |
| 159 | ptr = message; |
| 160 | for (i = 0; i < 16; i++) { |
| 161 | ptr = u64_to_hex(dest: ptr, val: lc->cregs_save_area[i].val); |
| 162 | ptr = nmi_puts(dest: ptr, src: " " ); |
| 163 | if ((i + 1) % 4 == 0) { |
| 164 | ptr = nmi_puts(dest: ptr, src: "\n" ); |
| 165 | sclp_emergency_printk(message); |
| 166 | ptr = message; |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | ptr = nmi_puts(dest: message, src: "GPRS:\n" ); |
| 171 | sclp_emergency_printk(message); |
| 172 | ptr = message; |
| 173 | for (i = 0; i < 16; i++) { |
| 174 | ptr = u64_to_hex(dest: ptr, val: lc->gpregs_save_area[i]); |
| 175 | ptr = nmi_puts(dest: ptr, src: " " ); |
| 176 | if ((i + 1) % 4 == 0) { |
| 177 | ptr = nmi_puts(dest: ptr, src: "\n" ); |
| 178 | sclp_emergency_printk(message); |
| 179 | ptr = message; |
| 180 | } |
| 181 | } |
| 182 | |
| 183 | ptr = nmi_puts(dest: message, src: "System stopped\n" ); |
| 184 | sclp_emergency_printk(message); |
| 185 | } |
| 186 | |
| 187 | static notrace void __noreturn s390_handle_damage(void) |
| 188 | { |
| 189 | struct lowcore *lc = get_lowcore(); |
| 190 | union ctlreg0 cr0, cr0_new; |
| 191 | psw_t psw_save; |
| 192 | |
| 193 | smp_emergency_stop(); |
| 194 | diag_amode31_ops.diag308_reset(); |
| 195 | |
| 196 | /* |
| 197 | * Disable low address protection and make machine check new PSW a |
| 198 | * disabled wait PSW. Any additional machine check cannot be handled. |
| 199 | */ |
| 200 | local_ctl_store(0, &cr0.reg); |
| 201 | cr0_new = cr0; |
| 202 | cr0_new.lap = 0; |
| 203 | local_ctl_load(0, &cr0_new.reg); |
| 204 | psw_save = lc->mcck_new_psw; |
| 205 | psw_bits(lc->mcck_new_psw).io = 0; |
| 206 | psw_bits(lc->mcck_new_psw).ext = 0; |
| 207 | psw_bits(lc->mcck_new_psw).wait = 1; |
| 208 | nmi_print_info(); |
| 209 | |
| 210 | /* |
| 211 | * Restore machine check new PSW and control register 0 to original |
| 212 | * values. This makes possible system dump analysis easier. |
| 213 | */ |
| 214 | lc->mcck_new_psw = psw_save; |
| 215 | local_ctl_load(0, &cr0.reg); |
| 216 | disabled_wait(); |
| 217 | } |
| 218 | NOKPROBE_SYMBOL(s390_handle_damage); |
| 219 | |
| 220 | /* |
| 221 | * Main machine check handler function. Will be called with interrupts disabled |
| 222 | * and machine checks enabled. |
| 223 | */ |
| 224 | void s390_handle_mcck(void) |
| 225 | { |
| 226 | struct mcck_struct mcck; |
| 227 | unsigned long mflags; |
| 228 | |
| 229 | /* |
| 230 | * Disable machine checks and get the current state of accumulated |
| 231 | * machine checks. Afterwards delete the old state and enable machine |
| 232 | * checks again. |
| 233 | */ |
| 234 | local_mcck_save(mflags); |
| 235 | mcck = *this_cpu_ptr(&cpu_mcck); |
| 236 | memset(this_cpu_ptr(&cpu_mcck), 0, sizeof(mcck)); |
| 237 | local_mcck_restore(mflags); |
| 238 | |
| 239 | if (mcck.channel_report) |
| 240 | crw_handle_channel_report(); |
| 241 | /* |
| 242 | * A warning may remain for a prolonged period on the bare iron. |
| 243 | * (actually until the machine is powered off, or the problem is gone) |
| 244 | * So we just stop listening for the WARNING MCH and avoid continuously |
| 245 | * being interrupted. One caveat is however, that we must do this per |
| 246 | * processor and cannot use the smp version of ctl_clear_bit(). |
| 247 | * On VM we only get one interrupt per virtally presented machinecheck. |
| 248 | * Though one suffices, we may get one interrupt per (virtual) cpu. |
| 249 | */ |
| 250 | if (mcck.warning) { /* WARNING pending ? */ |
| 251 | static int mchchk_wng_posted = 0; |
| 252 | |
| 253 | /* Use single cpu clear, as we cannot handle smp here. */ |
| 254 | local_ctl_clear_bit(14, CR14_WARNING_SUBMASK_BIT); |
| 255 | if (xchg(&mchchk_wng_posted, 1) == 0) |
| 256 | kill_cad_pid(SIGPWR, priv: 1); |
| 257 | } |
| 258 | if (mcck.stp_queue) |
| 259 | stp_queue_work(); |
| 260 | if (mcck.kill_task) { |
| 261 | printk(KERN_EMERG "mcck: Terminating task because of machine " |
| 262 | "malfunction (code 0x%016lx).\n" , mcck.mcck_code); |
| 263 | printk(KERN_EMERG "mcck: task: %s, pid: %d.\n" , |
| 264 | current->comm, current->pid); |
| 265 | if (is_global_init(current)) |
| 266 | panic(fmt: "mcck: Attempting to kill init!\n" ); |
| 267 | do_send_sig_info(SIGKILL, SEND_SIG_PRIV, current, type: PIDTYPE_PID); |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | /** |
| 272 | * nmi_registers_valid - verify if registers are valid |
| 273 | * @mci: machine check interruption code |
| 274 | * |
| 275 | * Inspect a machine check interruption code and verify if all required |
| 276 | * registers are valid. For some registers the corresponding validity bit is |
| 277 | * ignored and the registers are set to the expected value. |
| 278 | * Returns true if all registers are valid, otherwise false. |
| 279 | */ |
| 280 | static bool notrace nmi_registers_valid(union mci mci) |
| 281 | { |
| 282 | union ctlreg2 cr2; |
| 283 | |
| 284 | /* |
| 285 | * The getcpu vdso syscall reads the CPU number from the programmable |
| 286 | * field of the TOD clock. Disregard the TOD programmable register |
| 287 | * validity bit and load the CPU number into the TOD programmable field |
| 288 | * unconditionally. |
| 289 | */ |
| 290 | set_tod_programmable_field(raw_smp_processor_id()); |
| 291 | /* |
| 292 | * Set the clock comparator register to the next expected value. |
| 293 | */ |
| 294 | set_clock_comparator(get_lowcore()->clock_comparator); |
| 295 | if (!mci.gr || !mci.fp || !mci.fc) |
| 296 | return false; |
| 297 | /* |
| 298 | * The vector validity must only be checked if not running a |
| 299 | * KVM guest. For KVM guests the machine check is forwarded by |
| 300 | * KVM and it is the responsibility of the guest to take |
| 301 | * appropriate actions. The host vector or FPU values have been |
| 302 | * saved by KVM and will be restored by KVM. |
| 303 | */ |
| 304 | if (!mci.vr && !test_cpu_flag(CIF_MCCK_GUEST)) |
| 305 | return false; |
| 306 | if (!mci.ar) |
| 307 | return false; |
| 308 | /* |
| 309 | * Two cases for guarded storage registers: |
| 310 | * - machine check in kernel or userspace |
| 311 | * - machine check while running SIE (KVM guest) |
| 312 | * For kernel or userspace the userspace values of guarded storage |
| 313 | * control can not be recreated, the process must be terminated. |
| 314 | * For SIE the guest values of guarded storage can not be recreated. |
| 315 | * This is either due to a bug or due to GS being disabled in the |
| 316 | * guest. The guest will be notified by KVM code and the guests machine |
| 317 | * check handling must take care of this. The host values are saved by |
| 318 | * KVM and are not affected. |
| 319 | */ |
| 320 | cr2.reg = get_lowcore()->cregs_save_area[2]; |
| 321 | if (cr2.gse && !mci.gs && !test_cpu_flag(CIF_MCCK_GUEST)) |
| 322 | return false; |
| 323 | if (!mci.ms || !mci.pm || !mci.ia) |
| 324 | return false; |
| 325 | return true; |
| 326 | } |
| 327 | NOKPROBE_SYMBOL(nmi_registers_valid); |
| 328 | |
| 329 | /* |
| 330 | * Backup the guest's machine check info to its description block |
| 331 | */ |
| 332 | static void notrace s390_backup_mcck_info(struct pt_regs *regs) |
| 333 | { |
| 334 | struct mcck_volatile_info *mcck_backup; |
| 335 | struct sie_page *sie_page; |
| 336 | |
| 337 | /* r14 contains the sie block, which was set in sie64a */ |
| 338 | struct kvm_s390_sie_block *sie_block = phys_to_virt(address: regs->gprs[14]); |
| 339 | |
| 340 | if (sie_block == NULL) |
| 341 | /* Something's seriously wrong, stop system. */ |
| 342 | s390_handle_damage(); |
| 343 | |
| 344 | sie_page = container_of(sie_block, struct sie_page, sie_block); |
| 345 | mcck_backup = &sie_page->mcck_info; |
| 346 | mcck_backup->mcic = get_lowcore()->mcck_interruption_code & |
| 347 | ~(MCCK_CODE_CP | MCCK_CODE_EXT_DAMAGE); |
| 348 | mcck_backup->ext_damage_code = get_lowcore()->external_damage_code; |
| 349 | mcck_backup->failing_storage_address = get_lowcore()->failing_storage_address; |
| 350 | } |
| 351 | NOKPROBE_SYMBOL(s390_backup_mcck_info); |
| 352 | |
| 353 | #define MAX_IPD_COUNT 29 |
| 354 | #define MAX_IPD_TIME (5 * 60 * USEC_PER_SEC) /* 5 minutes */ |
| 355 | |
| 356 | #define ED_STP_ISLAND 6 /* External damage STP island check */ |
| 357 | #define ED_STP_SYNC 7 /* External damage STP sync check */ |
| 358 | |
| 359 | #define MCCK_CODE_NO_GUEST (MCCK_CODE_CP | MCCK_CODE_EXT_DAMAGE) |
| 360 | |
| 361 | /* |
| 362 | * machine check handler. |
| 363 | */ |
| 364 | void notrace s390_do_machine_check(struct pt_regs *regs) |
| 365 | { |
| 366 | static int ipd_count; |
| 367 | static DEFINE_SPINLOCK(ipd_lock); |
| 368 | static unsigned long long last_ipd; |
| 369 | struct lowcore *lc = get_lowcore(); |
| 370 | struct mcck_struct *mcck; |
| 371 | unsigned long long tmp; |
| 372 | irqentry_state_t irq_state; |
| 373 | union mci mci; |
| 374 | unsigned long mcck_dam_code; |
| 375 | int mcck_pending = 0; |
| 376 | |
| 377 | irq_state = irqentry_nmi_enter(regs); |
| 378 | |
| 379 | if (user_mode(regs)) |
| 380 | update_timer_mcck(); |
| 381 | inc_irq_stat(NMI_NMI); |
| 382 | mci.val = lc->mcck_interruption_code; |
| 383 | mcck = this_cpu_ptr(&cpu_mcck); |
| 384 | |
| 385 | /* |
| 386 | * Reinject the instruction processing damages' machine checks |
| 387 | * including Delayed Access Exception into the guest |
| 388 | * instead of damaging the host if they happen in the guest. |
| 389 | */ |
| 390 | if (mci.pd && !test_cpu_flag(CIF_MCCK_GUEST)) { |
| 391 | if (mci.b) { |
| 392 | /* Processing backup -> verify if we can survive this */ |
| 393 | u64 z_mcic, o_mcic, t_mcic; |
| 394 | z_mcic = (1ULL<<63 | 1ULL<<59 | 1ULL<<29); |
| 395 | o_mcic = (1ULL<<43 | 1ULL<<42 | 1ULL<<41 | 1ULL<<40 | |
| 396 | 1ULL<<36 | 1ULL<<35 | 1ULL<<34 | 1ULL<<32 | |
| 397 | 1ULL<<30 | 1ULL<<21 | 1ULL<<20 | 1ULL<<17 | |
| 398 | 1ULL<<16); |
| 399 | t_mcic = mci.val; |
| 400 | |
| 401 | if (((t_mcic & z_mcic) != 0) || |
| 402 | ((t_mcic & o_mcic) != o_mcic)) { |
| 403 | s390_handle_damage(); |
| 404 | } |
| 405 | |
| 406 | /* |
| 407 | * Nullifying exigent condition, therefore we might |
| 408 | * retry this instruction. |
| 409 | */ |
| 410 | spin_lock(lock: &ipd_lock); |
| 411 | tmp = get_tod_clock(); |
| 412 | if (((tmp - last_ipd) >> 12) < MAX_IPD_TIME) |
| 413 | ipd_count++; |
| 414 | else |
| 415 | ipd_count = 1; |
| 416 | last_ipd = tmp; |
| 417 | if (ipd_count == MAX_IPD_COUNT) |
| 418 | s390_handle_damage(); |
| 419 | spin_unlock(lock: &ipd_lock); |
| 420 | } else { |
| 421 | /* Processing damage -> stopping machine */ |
| 422 | s390_handle_damage(); |
| 423 | } |
| 424 | } |
| 425 | if (!nmi_registers_valid(mci: mci)) { |
| 426 | if (!user_mode(regs)) |
| 427 | s390_handle_damage(); |
| 428 | /* |
| 429 | * Couldn't restore all register contents for the |
| 430 | * user space process -> mark task for termination. |
| 431 | */ |
| 432 | mcck->kill_task = 1; |
| 433 | mcck->mcck_code = mci.val; |
| 434 | mcck_pending = 1; |
| 435 | } |
| 436 | |
| 437 | /* |
| 438 | * Backup the machine check's info if it happens when the guest |
| 439 | * is running. |
| 440 | */ |
| 441 | if (test_cpu_flag(CIF_MCCK_GUEST)) |
| 442 | s390_backup_mcck_info(regs); |
| 443 | |
| 444 | if (mci.cd) { |
| 445 | /* Timing facility damage */ |
| 446 | s390_handle_damage(); |
| 447 | } |
| 448 | if (mci.ed && mci.ec) { |
| 449 | /* External damage */ |
| 450 | if (lc->external_damage_code & (1U << ED_STP_SYNC)) |
| 451 | mcck->stp_queue |= stp_sync_check(); |
| 452 | if (lc->external_damage_code & (1U << ED_STP_ISLAND)) |
| 453 | mcck->stp_queue |= stp_island_check(); |
| 454 | mcck_pending = 1; |
| 455 | } |
| 456 | /* |
| 457 | * Reinject storage related machine checks into the guest if they |
| 458 | * happen when the guest is running. |
| 459 | */ |
| 460 | if (!test_cpu_flag(CIF_MCCK_GUEST)) { |
| 461 | /* Storage error uncorrected */ |
| 462 | if (mci.se) |
| 463 | s390_handle_damage(); |
| 464 | /* Storage key-error uncorrected */ |
| 465 | if (mci.ke) |
| 466 | s390_handle_damage(); |
| 467 | /* Storage degradation */ |
| 468 | if (mci.ds && mci.fa) |
| 469 | s390_handle_damage(); |
| 470 | } |
| 471 | if (mci.cp) { |
| 472 | /* Channel report word pending */ |
| 473 | mcck->channel_report = 1; |
| 474 | mcck_pending = 1; |
| 475 | } |
| 476 | if (mci.w) { |
| 477 | /* Warning pending */ |
| 478 | mcck->warning = 1; |
| 479 | mcck_pending = 1; |
| 480 | } |
| 481 | |
| 482 | /* |
| 483 | * If there are only Channel Report Pending and External Damage |
| 484 | * machine checks, they will not be reinjected into the guest |
| 485 | * because they refer to host conditions only. |
| 486 | */ |
| 487 | mcck_dam_code = (mci.val & MCIC_SUBCLASS_MASK); |
| 488 | if (test_cpu_flag(CIF_MCCK_GUEST) && |
| 489 | (mcck_dam_code & MCCK_CODE_NO_GUEST) != mcck_dam_code) { |
| 490 | /* Set exit reason code for host's later handling */ |
| 491 | *((long *)(regs->gprs[15] + __SF_SIE_REASON)) = -EINTR; |
| 492 | } |
| 493 | clear_cpu_flag(CIF_MCCK_GUEST); |
| 494 | |
| 495 | if (mcck_pending) |
| 496 | schedule_mcck_handler(); |
| 497 | |
| 498 | irqentry_nmi_exit(regs, irq_state); |
| 499 | } |
| 500 | NOKPROBE_SYMBOL(s390_do_machine_check); |
| 501 | |
| 502 | static int __init machine_check_init(void) |
| 503 | { |
| 504 | system_ctl_set_bit(14, CR14_EXTERNAL_DAMAGE_SUBMASK_BIT); |
| 505 | system_ctl_set_bit(14, CR14_RECOVERY_SUBMASK_BIT); |
| 506 | system_ctl_set_bit(14, CR14_WARNING_SUBMASK_BIT); |
| 507 | return 0; |
| 508 | } |
| 509 | early_initcall(machine_check_init); |
| 510 | |