root/arch/x86/kernel/cpu/mce/severity.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. error_context
  2. mce_severity_amd_smca
  3. mce_severity_amd
  4. mce_severity_intel
  5. mcheck_vendor_init_severity
  6. s_start
  7. s_next
  8. s_stop
  9. s_show
  10. severities_coverage_open
  11. severities_coverage_write
  12. severities_debugfs_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * MCE grading rules.
   4  * Copyright 2008, 2009 Intel Corporation.
   5  *
   6  * Author: Andi Kleen
   7  */
   8 #include <linux/kernel.h>
   9 #include <linux/seq_file.h>
  10 #include <linux/init.h>
  11 #include <linux/debugfs.h>
  12 #include <asm/mce.h>
  13 #include <linux/uaccess.h>
  14 
  15 #include "internal.h"
  16 
  17 /*
  18  * Grade an mce by severity. In general the most severe ones are processed
  19  * first. Since there are quite a lot of combinations test the bits in a
  20  * table-driven way. The rules are simply processed in order, first
  21  * match wins.
  22  *
  23  * Note this is only used for machine check exceptions, the corrected
  24  * errors use much simpler rules. The exceptions still check for the corrected
  25  * errors, but only to leave them alone for the CMCI handler (except for
  26  * panic situations)
  27  */
  28 
  29 enum context { IN_KERNEL = 1, IN_USER = 2, IN_KERNEL_RECOV = 3 };
  30 enum ser { SER_REQUIRED = 1, NO_SER = 2 };
  31 enum exception { EXCP_CONTEXT = 1, NO_EXCP = 2 };
  32 
  33 static struct severity {
  34         u64 mask;
  35         u64 result;
  36         unsigned char sev;
  37         unsigned char mcgmask;
  38         unsigned char mcgres;
  39         unsigned char ser;
  40         unsigned char context;
  41         unsigned char excp;
  42         unsigned char covered;
  43         char *msg;
  44 } severities[] = {
  45 #define MCESEV(s, m, c...) { .sev = MCE_ ## s ## _SEVERITY, .msg = m, ## c }
  46 #define  KERNEL         .context = IN_KERNEL
  47 #define  USER           .context = IN_USER
  48 #define  KERNEL_RECOV   .context = IN_KERNEL_RECOV
  49 #define  SER            .ser = SER_REQUIRED
  50 #define  NOSER          .ser = NO_SER
  51 #define  EXCP           .excp = EXCP_CONTEXT
  52 #define  NOEXCP         .excp = NO_EXCP
  53 #define  BITCLR(x)      .mask = x, .result = 0
  54 #define  BITSET(x)      .mask = x, .result = x
  55 #define  MCGMASK(x, y)  .mcgmask = x, .mcgres = y
  56 #define  MASK(x, y)     .mask = x, .result = y
  57 #define MCI_UC_S (MCI_STATUS_UC|MCI_STATUS_S)
  58 #define MCI_UC_AR (MCI_STATUS_UC|MCI_STATUS_AR)
  59 #define MCI_UC_SAR (MCI_STATUS_UC|MCI_STATUS_S|MCI_STATUS_AR)
  60 #define MCI_ADDR (MCI_STATUS_ADDRV|MCI_STATUS_MISCV)
  61 
  62         MCESEV(
  63                 NO, "Invalid",
  64                 BITCLR(MCI_STATUS_VAL)
  65                 ),
  66         MCESEV(
  67                 NO, "Not enabled",
  68                 EXCP, BITCLR(MCI_STATUS_EN)
  69                 ),
  70         MCESEV(
  71                 PANIC, "Processor context corrupt",
  72                 BITSET(MCI_STATUS_PCC)
  73                 ),
  74         /* When MCIP is not set something is very confused */
  75         MCESEV(
  76                 PANIC, "MCIP not set in MCA handler",
  77                 EXCP, MCGMASK(MCG_STATUS_MCIP, 0)
  78                 ),
  79         /* Neither return not error IP -- no chance to recover -> PANIC */
  80         MCESEV(
  81                 PANIC, "Neither restart nor error IP",
  82                 EXCP, MCGMASK(MCG_STATUS_RIPV|MCG_STATUS_EIPV, 0)
  83                 ),
  84         MCESEV(
  85                 PANIC, "In kernel and no restart IP",
  86                 EXCP, KERNEL, MCGMASK(MCG_STATUS_RIPV, 0)
  87                 ),
  88         MCESEV(
  89                 PANIC, "In kernel and no restart IP",
  90                 EXCP, KERNEL_RECOV, MCGMASK(MCG_STATUS_RIPV, 0)
  91                 ),
  92         MCESEV(
  93                 DEFERRED, "Deferred error",
  94                 NOSER, MASK(MCI_STATUS_UC|MCI_STATUS_DEFERRED|MCI_STATUS_POISON, MCI_STATUS_DEFERRED)
  95                 ),
  96         MCESEV(
  97                 KEEP, "Corrected error",
  98                 NOSER, BITCLR(MCI_STATUS_UC)
  99                 ),
 100 
 101         /*
 102          * known AO MCACODs reported via MCE or CMC:
 103          *
 104          * SRAO could be signaled either via a machine check exception or
 105          * CMCI with the corresponding bit S 1 or 0. So we don't need to
 106          * check bit S for SRAO.
 107          */
 108         MCESEV(
 109                 AO, "Action optional: memory scrubbing error",
 110                 SER, MASK(MCI_UC_AR|MCACOD_SCRUBMSK, MCI_STATUS_UC|MCACOD_SCRUB)
 111                 ),
 112         MCESEV(
 113                 AO, "Action optional: last level cache writeback error",
 114                 SER, MASK(MCI_UC_AR|MCACOD, MCI_STATUS_UC|MCACOD_L3WB)
 115                 ),
 116 
 117         /* ignore OVER for UCNA */
 118         MCESEV(
 119                 UCNA, "Uncorrected no action required",
 120                 SER, MASK(MCI_UC_SAR, MCI_STATUS_UC)
 121                 ),
 122         MCESEV(
 123                 PANIC, "Illegal combination (UCNA with AR=1)",
 124                 SER,
 125                 MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_STATUS_UC|MCI_STATUS_AR)
 126                 ),
 127         MCESEV(
 128                 KEEP, "Non signalled machine check",
 129                 SER, BITCLR(MCI_STATUS_S)
 130                 ),
 131 
 132         MCESEV(
 133                 PANIC, "Action required with lost events",
 134                 SER, BITSET(MCI_STATUS_OVER|MCI_UC_SAR)
 135                 ),
 136 
 137         /* known AR MCACODs: */
 138 #ifdef  CONFIG_MEMORY_FAILURE
 139         MCESEV(
 140                 KEEP, "Action required but unaffected thread is continuable",
 141                 SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR, MCI_UC_SAR|MCI_ADDR),
 142                 MCGMASK(MCG_STATUS_RIPV|MCG_STATUS_EIPV, MCG_STATUS_RIPV)
 143                 ),
 144         MCESEV(
 145                 AR, "Action required: data load in error recoverable area of kernel",
 146                 SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_DATA),
 147                 KERNEL_RECOV
 148                 ),
 149         MCESEV(
 150                 AR, "Action required: data load error in a user process",
 151                 SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_DATA),
 152                 USER
 153                 ),
 154         MCESEV(
 155                 AR, "Action required: instruction fetch error in a user process",
 156                 SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_INSTR),
 157                 USER
 158                 ),
 159         MCESEV(
 160                 PANIC, "Data load in unrecoverable area of kernel",
 161                 SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_DATA),
 162                 KERNEL
 163                 ),
 164         MCESEV(
 165                 PANIC, "Instruction fetch error in kernel",
 166                 SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_INSTR),
 167                 KERNEL
 168                 ),
 169 #endif
 170         MCESEV(
 171                 PANIC, "Action required: unknown MCACOD",
 172                 SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_UC_SAR)
 173                 ),
 174 
 175         MCESEV(
 176                 SOME, "Action optional: unknown MCACOD",
 177                 SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_UC_S)
 178                 ),
 179         MCESEV(
 180                 SOME, "Action optional with lost events",
 181                 SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_STATUS_OVER|MCI_UC_S)
 182                 ),
 183 
 184         MCESEV(
 185                 PANIC, "Overflowed uncorrected",
 186                 BITSET(MCI_STATUS_OVER|MCI_STATUS_UC)
 187                 ),
 188         MCESEV(
 189                 UC, "Uncorrected",
 190                 BITSET(MCI_STATUS_UC)
 191                 ),
 192         MCESEV(
 193                 SOME, "No match",
 194                 BITSET(0)
 195                 )       /* always matches. keep at end */
 196 };
 197 
 198 #define mc_recoverable(mcg) (((mcg) & (MCG_STATUS_RIPV|MCG_STATUS_EIPV)) == \
 199                                 (MCG_STATUS_RIPV|MCG_STATUS_EIPV))
 200 
 201 /*
 202  * If mcgstatus indicated that ip/cs on the stack were
 203  * no good, then "m->cs" will be zero and we will have
 204  * to assume the worst case (IN_KERNEL) as we actually
 205  * have no idea what we were executing when the machine
 206  * check hit.
 207  * If we do have a good "m->cs" (or a faked one in the
 208  * case we were executing in VM86 mode) we can use it to
 209  * distinguish an exception taken in user from from one
 210  * taken in the kernel.
 211  */
 212 static int error_context(struct mce *m)
 213 {
 214         if ((m->cs & 3) == 3)
 215                 return IN_USER;
 216         if (mc_recoverable(m->mcgstatus) && ex_has_fault_handler(m->ip))
 217                 return IN_KERNEL_RECOV;
 218         return IN_KERNEL;
 219 }
 220 
 221 static int mce_severity_amd_smca(struct mce *m, enum context err_ctx)
 222 {
 223         u32 addr = MSR_AMD64_SMCA_MCx_CONFIG(m->bank);
 224         u32 low, high;
 225 
 226         /*
 227          * We need to look at the following bits:
 228          * - "succor" bit (data poisoning support), and
 229          * - TCC bit (Task Context Corrupt)
 230          * in MCi_STATUS to determine error severity.
 231          */
 232         if (!mce_flags.succor)
 233                 return MCE_PANIC_SEVERITY;
 234 
 235         if (rdmsr_safe(addr, &low, &high))
 236                 return MCE_PANIC_SEVERITY;
 237 
 238         /* TCC (Task context corrupt). If set and if IN_KERNEL, panic. */
 239         if ((low & MCI_CONFIG_MCAX) &&
 240             (m->status & MCI_STATUS_TCC) &&
 241             (err_ctx == IN_KERNEL))
 242                 return MCE_PANIC_SEVERITY;
 243 
 244          /* ...otherwise invoke hwpoison handler. */
 245         return MCE_AR_SEVERITY;
 246 }
 247 
 248 /*
 249  * See AMD Error Scope Hierarchy table in a newer BKDG. For example
 250  * 49125_15h_Models_30h-3Fh_BKDG.pdf, section "RAS Features"
 251  */
 252 static int mce_severity_amd(struct mce *m, int tolerant, char **msg, bool is_excp)
 253 {
 254         enum context ctx = error_context(m);
 255 
 256         /* Processor Context Corrupt, no need to fumble too much, die! */
 257         if (m->status & MCI_STATUS_PCC)
 258                 return MCE_PANIC_SEVERITY;
 259 
 260         if (m->status & MCI_STATUS_UC) {
 261 
 262                 if (ctx == IN_KERNEL)
 263                         return MCE_PANIC_SEVERITY;
 264 
 265                 /*
 266                  * On older systems where overflow_recov flag is not present, we
 267                  * should simply panic if an error overflow occurs. If
 268                  * overflow_recov flag is present and set, then software can try
 269                  * to at least kill process to prolong system operation.
 270                  */
 271                 if (mce_flags.overflow_recov) {
 272                         if (mce_flags.smca)
 273                                 return mce_severity_amd_smca(m, ctx);
 274 
 275                         /* kill current process */
 276                         return MCE_AR_SEVERITY;
 277                 } else {
 278                         /* at least one error was not logged */
 279                         if (m->status & MCI_STATUS_OVER)
 280                                 return MCE_PANIC_SEVERITY;
 281                 }
 282 
 283                 /*
 284                  * For any other case, return MCE_UC_SEVERITY so that we log the
 285                  * error and exit #MC handler.
 286                  */
 287                 return MCE_UC_SEVERITY;
 288         }
 289 
 290         /*
 291          * deferred error: poll handler catches these and adds to mce_ring so
 292          * memory-failure can take recovery actions.
 293          */
 294         if (m->status & MCI_STATUS_DEFERRED)
 295                 return MCE_DEFERRED_SEVERITY;
 296 
 297         /*
 298          * corrected error: poll handler catches these and passes responsibility
 299          * of decoding the error to EDAC
 300          */
 301         return MCE_KEEP_SEVERITY;
 302 }
 303 
 304 static int mce_severity_intel(struct mce *m, int tolerant, char **msg, bool is_excp)
 305 {
 306         enum exception excp = (is_excp ? EXCP_CONTEXT : NO_EXCP);
 307         enum context ctx = error_context(m);
 308         struct severity *s;
 309 
 310         for (s = severities;; s++) {
 311                 if ((m->status & s->mask) != s->result)
 312                         continue;
 313                 if ((m->mcgstatus & s->mcgmask) != s->mcgres)
 314                         continue;
 315                 if (s->ser == SER_REQUIRED && !mca_cfg.ser)
 316                         continue;
 317                 if (s->ser == NO_SER && mca_cfg.ser)
 318                         continue;
 319                 if (s->context && ctx != s->context)
 320                         continue;
 321                 if (s->excp && excp != s->excp)
 322                         continue;
 323                 if (msg)
 324                         *msg = s->msg;
 325                 s->covered = 1;
 326                 if (s->sev >= MCE_UC_SEVERITY && ctx == IN_KERNEL) {
 327                         if (tolerant < 1)
 328                                 return MCE_PANIC_SEVERITY;
 329                 }
 330                 return s->sev;
 331         }
 332 }
 333 
 334 /* Default to mce_severity_intel */
 335 int (*mce_severity)(struct mce *m, int tolerant, char **msg, bool is_excp) =
 336                     mce_severity_intel;
 337 
 338 void __init mcheck_vendor_init_severity(void)
 339 {
 340         if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
 341             boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
 342                 mce_severity = mce_severity_amd;
 343 }
 344 
 345 #ifdef CONFIG_DEBUG_FS
 346 static void *s_start(struct seq_file *f, loff_t *pos)
 347 {
 348         if (*pos >= ARRAY_SIZE(severities))
 349                 return NULL;
 350         return &severities[*pos];
 351 }
 352 
 353 static void *s_next(struct seq_file *f, void *data, loff_t *pos)
 354 {
 355         if (++(*pos) >= ARRAY_SIZE(severities))
 356                 return NULL;
 357         return &severities[*pos];
 358 }
 359 
 360 static void s_stop(struct seq_file *f, void *data)
 361 {
 362 }
 363 
 364 static int s_show(struct seq_file *f, void *data)
 365 {
 366         struct severity *ser = data;
 367         seq_printf(f, "%d\t%s\n", ser->covered, ser->msg);
 368         return 0;
 369 }
 370 
 371 static const struct seq_operations severities_seq_ops = {
 372         .start  = s_start,
 373         .next   = s_next,
 374         .stop   = s_stop,
 375         .show   = s_show,
 376 };
 377 
 378 static int severities_coverage_open(struct inode *inode, struct file *file)
 379 {
 380         return seq_open(file, &severities_seq_ops);
 381 }
 382 
 383 static ssize_t severities_coverage_write(struct file *file,
 384                                          const char __user *ubuf,
 385                                          size_t count, loff_t *ppos)
 386 {
 387         int i;
 388         for (i = 0; i < ARRAY_SIZE(severities); i++)
 389                 severities[i].covered = 0;
 390         return count;
 391 }
 392 
 393 static const struct file_operations severities_coverage_fops = {
 394         .open           = severities_coverage_open,
 395         .release        = seq_release,
 396         .read           = seq_read,
 397         .write          = severities_coverage_write,
 398         .llseek         = seq_lseek,
 399 };
 400 
 401 static int __init severities_debugfs_init(void)
 402 {
 403         struct dentry *dmce;
 404 
 405         dmce = mce_get_debugfs_dir();
 406 
 407         debugfs_create_file("severities-coverage", 0444, dmce, NULL,
 408                             &severities_coverage_fops);
 409         return 0;
 410 }
 411 late_initcall(severities_debugfs_init);
 412 #endif /* CONFIG_DEBUG_FS */

/* [<][>][^][v][top][bottom][index][help] */