574 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * GHES/EDAC Linux driver4 *5 * Copyright (c) 2013 by Mauro Carvalho Chehab6 *7 * Red Hat Inc. https://www.redhat.com8 */9 10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt11 12#include <acpi/ghes.h>13#include <linux/edac.h>14#include <linux/dmi.h>15#include "edac_module.h"16#include <ras/ras_event.h>17#include <linux/notifier.h>18 19#define OTHER_DETAIL_LEN 40020 21struct ghes_pvt {22 struct mem_ctl_info *mci;23 24 /* Buffers for the error handling routine */25 char other_detail[OTHER_DETAIL_LEN];26 char msg[80];27};28 29static refcount_t ghes_refcount = REFCOUNT_INIT(0);30 31/*32 * Access to ghes_pvt must be protected by ghes_lock. The spinlock33 * also provides the necessary (implicit) memory barrier for the SMP34 * case to make the pointer visible on another CPU.35 */36static struct ghes_pvt *ghes_pvt;37 38/*39 * This driver's representation of the system hardware, as collected40 * from DMI.41 */42static struct ghes_hw_desc {43 int num_dimms;44 struct dimm_info *dimms;45} ghes_hw;46 47/* GHES registration mutex */48static DEFINE_MUTEX(ghes_reg_mutex);49 50/*51 * Sync with other, potentially concurrent callers of52 * ghes_edac_report_mem_error(). We don't know what the53 * "inventive" firmware would do.54 */55static DEFINE_SPINLOCK(ghes_lock);56 57static bool system_scanned;58 59static struct list_head *ghes_devs;60 61/* Memory Device - Type 17 of SMBIOS spec */62struct memdev_dmi_entry {63 u8 type;64 u8 length;65 u16 handle;66 u16 phys_mem_array_handle;67 u16 mem_err_info_handle;68 u16 total_width;69 u16 data_width;70 u16 size;71 u8 form_factor;72 u8 device_set;73 u8 device_locator;74 u8 bank_locator;75 u8 memory_type;76 u16 type_detail;77 u16 speed;78 u8 manufacturer;79 u8 serial_number;80 u8 asset_tag;81 u8 part_number;82 u8 attributes;83 u32 extended_size;84 u16 conf_mem_clk_speed;85} __attribute__((__packed__));86 87static struct dimm_info *find_dimm_by_handle(struct mem_ctl_info *mci, u16 handle)88{89 struct dimm_info *dimm;90 91 mci_for_each_dimm(mci, dimm) {92 if (dimm->smbios_handle == handle)93 return dimm;94 }95 96 return NULL;97}98 99static void dimm_setup_label(struct dimm_info *dimm, u16 handle)100{101 const char *bank = NULL, *device = NULL;102 103 dmi_memdev_name(handle, &bank, &device);104 105 /*106 * Set to a NULL string when both bank and device are zero. In this case,107 * the label assigned by default will be preserved.108 */109 snprintf(dimm->label, sizeof(dimm->label), "%s%s%s",110 (bank && *bank) ? bank : "",111 (bank && *bank && device && *device) ? " " : "",112 (device && *device) ? device : "");113}114 115static void assign_dmi_dimm_info(struct dimm_info *dimm, struct memdev_dmi_entry *entry)116{117 u16 rdr_mask = BIT(7) | BIT(13);118 119 if (entry->size == 0xffff) {120 pr_info("Can't get DIMM%i size\n", dimm->idx);121 dimm->nr_pages = MiB_TO_PAGES(32);/* Unknown */122 } else if (entry->size == 0x7fff) {123 dimm->nr_pages = MiB_TO_PAGES(entry->extended_size);124 } else {125 if (entry->size & BIT(15))126 dimm->nr_pages = MiB_TO_PAGES((entry->size & 0x7fff) << 10);127 else128 dimm->nr_pages = MiB_TO_PAGES(entry->size);129 }130 131 switch (entry->memory_type) {132 case 0x12:133 if (entry->type_detail & BIT(13))134 dimm->mtype = MEM_RDDR;135 else136 dimm->mtype = MEM_DDR;137 break;138 case 0x13:139 if (entry->type_detail & BIT(13))140 dimm->mtype = MEM_RDDR2;141 else142 dimm->mtype = MEM_DDR2;143 break;144 case 0x14:145 dimm->mtype = MEM_FB_DDR2;146 break;147 case 0x18:148 if (entry->type_detail & BIT(12))149 dimm->mtype = MEM_NVDIMM;150 else if (entry->type_detail & BIT(13))151 dimm->mtype = MEM_RDDR3;152 else153 dimm->mtype = MEM_DDR3;154 break;155 case 0x1a:156 if (entry->type_detail & BIT(12))157 dimm->mtype = MEM_NVDIMM;158 else if (entry->type_detail & BIT(13))159 dimm->mtype = MEM_RDDR4;160 else161 dimm->mtype = MEM_DDR4;162 break;163 default:164 if (entry->type_detail & BIT(6))165 dimm->mtype = MEM_RMBS;166 else if ((entry->type_detail & rdr_mask) == rdr_mask)167 dimm->mtype = MEM_RDR;168 else if (entry->type_detail & BIT(7))169 dimm->mtype = MEM_SDR;170 else if (entry->type_detail & BIT(9))171 dimm->mtype = MEM_EDO;172 else173 dimm->mtype = MEM_UNKNOWN;174 }175 176 /*177 * Actually, we can only detect if the memory has bits for178 * checksum or not179 */180 if (entry->total_width == entry->data_width)181 dimm->edac_mode = EDAC_NONE;182 else183 dimm->edac_mode = EDAC_SECDED;184 185 dimm->dtype = DEV_UNKNOWN;186 dimm->grain = 128; /* Likely, worse case */187 188 dimm_setup_label(dimm, entry->handle);189 190 if (dimm->nr_pages) {191 edac_dbg(1, "DIMM%i: %s size = %d MB%s\n",192 dimm->idx, edac_mem_types[dimm->mtype],193 PAGES_TO_MiB(dimm->nr_pages),194 (dimm->edac_mode != EDAC_NONE) ? "(ECC)" : "");195 edac_dbg(2, "\ttype %d, detail 0x%02x, width %d(total %d)\n",196 entry->memory_type, entry->type_detail,197 entry->total_width, entry->data_width);198 }199 200 dimm->smbios_handle = entry->handle;201}202 203static void enumerate_dimms(const struct dmi_header *dh, void *arg)204{205 struct memdev_dmi_entry *entry = (struct memdev_dmi_entry *)dh;206 struct ghes_hw_desc *hw = (struct ghes_hw_desc *)arg;207 struct dimm_info *d;208 209 if (dh->type != DMI_ENTRY_MEM_DEVICE)210 return;211 212 /* Enlarge the array with additional 16 */213 if (!hw->num_dimms || !(hw->num_dimms % 16)) {214 struct dimm_info *new;215 216 new = krealloc_array(hw->dimms, hw->num_dimms + 16,217 sizeof(struct dimm_info), GFP_KERNEL);218 if (!new) {219 WARN_ON_ONCE(1);220 return;221 }222 223 hw->dimms = new;224 }225 226 d = &hw->dimms[hw->num_dimms];227 d->idx = hw->num_dimms;228 229 assign_dmi_dimm_info(d, entry);230 231 hw->num_dimms++;232}233 234static void ghes_scan_system(void)235{236 if (system_scanned)237 return;238 239 dmi_walk(enumerate_dimms, &ghes_hw);240 241 system_scanned = true;242}243 244static int print_mem_error_other_detail(const struct cper_sec_mem_err *mem, char *msg,245 const char *location, unsigned int len)246{247 u32 n;248 249 if (!msg)250 return 0;251 252 n = 0;253 len -= 1;254 255 n += scnprintf(msg + n, len - n, "APEI location: %s ", location);256 257 if (!(mem->validation_bits & CPER_MEM_VALID_ERROR_STATUS))258 goto out;259 260 n += scnprintf(msg + n, len - n, "status(0x%016llx): ", mem->error_status);261 n += scnprintf(msg + n, len - n, "%s ", cper_mem_err_status_str(mem->error_status));262 263out:264 msg[n] = '\0';265 266 return n;267}268 269static int ghes_edac_report_mem_error(struct notifier_block *nb,270 unsigned long val, void *data)271{272 struct cper_sec_mem_err *mem_err = (struct cper_sec_mem_err *)data;273 struct cper_mem_err_compact cmem;274 struct edac_raw_error_desc *e;275 struct mem_ctl_info *mci;276 unsigned long sev = val;277 struct ghes_pvt *pvt;278 unsigned long flags;279 char *p;280 281 /*282 * We can do the locking below because GHES defers error processing283 * from NMI to IRQ context. Whenever that changes, we'd at least284 * know.285 */286 if (WARN_ON_ONCE(in_nmi()))287 return NOTIFY_OK;288 289 spin_lock_irqsave(&ghes_lock, flags);290 291 pvt = ghes_pvt;292 if (!pvt)293 goto unlock;294 295 mci = pvt->mci;296 e = &mci->error_desc;297 298 /* Cleans the error report buffer */299 memset(e, 0, sizeof (*e));300 e->error_count = 1;301 e->grain = 1;302 e->msg = pvt->msg;303 e->other_detail = pvt->other_detail;304 e->top_layer = -1;305 e->mid_layer = -1;306 e->low_layer = -1;307 *pvt->other_detail = '\0';308 *pvt->msg = '\0';309 310 switch (sev) {311 case GHES_SEV_CORRECTED:312 e->type = HW_EVENT_ERR_CORRECTED;313 break;314 case GHES_SEV_RECOVERABLE:315 e->type = HW_EVENT_ERR_UNCORRECTED;316 break;317 case GHES_SEV_PANIC:318 e->type = HW_EVENT_ERR_FATAL;319 break;320 default:321 case GHES_SEV_NO:322 e->type = HW_EVENT_ERR_INFO;323 }324 325 edac_dbg(1, "error validation_bits: 0x%08llx\n",326 (long long)mem_err->validation_bits);327 328 /* Error type, mapped on e->msg */329 if (mem_err->validation_bits & CPER_MEM_VALID_ERROR_TYPE) {330 u8 etype = mem_err->error_type;331 332 p = pvt->msg;333 p += snprintf(p, sizeof(pvt->msg), "%s", cper_mem_err_type_str(etype));334 } else {335 strcpy(pvt->msg, "unknown error");336 }337 338 /* Error address */339 if (mem_err->validation_bits & CPER_MEM_VALID_PA) {340 e->page_frame_number = PHYS_PFN(mem_err->physical_addr);341 e->offset_in_page = offset_in_page(mem_err->physical_addr);342 }343 344 /* Error grain */345 if (mem_err->validation_bits & CPER_MEM_VALID_PA_MASK)346 e->grain = ~mem_err->physical_addr_mask + 1;347 348 /* Memory error location, mapped on e->location */349 p = e->location;350 cper_mem_err_pack(mem_err, &cmem);351 p += cper_mem_err_location(&cmem, p);352 353 if (mem_err->validation_bits & CPER_MEM_VALID_MODULE_HANDLE) {354 struct dimm_info *dimm;355 356 p += cper_dimm_err_location(&cmem, p);357 dimm = find_dimm_by_handle(mci, mem_err->mem_dev_handle);358 if (dimm) {359 e->top_layer = dimm->idx;360 strcpy(e->label, dimm->label);361 }362 }363 if (p > e->location)364 *(p - 1) = '\0';365 366 if (!*e->label)367 strcpy(e->label, "unknown memory");368 369 /* All other fields are mapped on e->other_detail */370 p = pvt->other_detail;371 p += print_mem_error_other_detail(mem_err, p, e->location, OTHER_DETAIL_LEN);372 if (p > pvt->other_detail)373 *(p - 1) = '\0';374 375 edac_raw_mc_handle_error(e);376 377unlock:378 spin_unlock_irqrestore(&ghes_lock, flags);379 380 return NOTIFY_OK;381}382 383static struct notifier_block ghes_edac_mem_err_nb = {384 .notifier_call = ghes_edac_report_mem_error,385 .priority = 0,386};387 388static int ghes_edac_register(struct device *dev)389{390 bool fake = false;391 struct mem_ctl_info *mci;392 struct ghes_pvt *pvt;393 struct edac_mc_layer layers[1];394 unsigned long flags;395 int rc = 0;396 397 /* finish another registration/unregistration instance first */398 mutex_lock(&ghes_reg_mutex);399 400 /*401 * We have only one logical memory controller to which all DIMMs belong.402 */403 if (refcount_inc_not_zero(&ghes_refcount))404 goto unlock;405 406 ghes_scan_system();407 408 /* Check if we've got a bogus BIOS */409 if (!ghes_hw.num_dimms) {410 fake = true;411 ghes_hw.num_dimms = 1;412 }413 414 layers[0].type = EDAC_MC_LAYER_ALL_MEM;415 layers[0].size = ghes_hw.num_dimms;416 layers[0].is_virt_csrow = true;417 418 mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(struct ghes_pvt));419 if (!mci) {420 pr_info("Can't allocate memory for EDAC data\n");421 rc = -ENOMEM;422 goto unlock;423 }424 425 pvt = mci->pvt_info;426 pvt->mci = mci;427 428 mci->pdev = dev;429 mci->mtype_cap = MEM_FLAG_EMPTY;430 mci->edac_ctl_cap = EDAC_FLAG_NONE;431 mci->edac_cap = EDAC_FLAG_NONE;432 mci->mod_name = "ghes_edac.c";433 mci->ctl_name = "ghes_edac";434 mci->dev_name = "ghes";435 436 if (fake) {437 pr_info("This system has a very crappy BIOS: It doesn't even list the DIMMS.\n");438 pr_info("Its SMBIOS info is wrong. It is doubtful that the error report would\n");439 pr_info("work on such system. Use this driver with caution\n");440 }441 442 pr_info("This system has %d DIMM sockets.\n", ghes_hw.num_dimms);443 444 if (!fake) {445 struct dimm_info *src, *dst;446 int i = 0;447 448 mci_for_each_dimm(mci, dst) {449 src = &ghes_hw.dimms[i];450 451 dst->idx = src->idx;452 dst->smbios_handle = src->smbios_handle;453 dst->nr_pages = src->nr_pages;454 dst->mtype = src->mtype;455 dst->edac_mode = src->edac_mode;456 dst->dtype = src->dtype;457 dst->grain = src->grain;458 459 /*460 * If no src->label, preserve default label assigned461 * from EDAC core.462 */463 if (strlen(src->label))464 memcpy(dst->label, src->label, sizeof(src->label));465 466 i++;467 }468 469 } else {470 struct dimm_info *dimm = edac_get_dimm(mci, 0, 0, 0);471 472 dimm->nr_pages = 1;473 dimm->grain = 128;474 dimm->mtype = MEM_UNKNOWN;475 dimm->dtype = DEV_UNKNOWN;476 dimm->edac_mode = EDAC_SECDED;477 }478 479 rc = edac_mc_add_mc(mci);480 if (rc < 0) {481 pr_info("Can't register with the EDAC core\n");482 edac_mc_free(mci);483 rc = -ENODEV;484 goto unlock;485 }486 487 spin_lock_irqsave(&ghes_lock, flags);488 ghes_pvt = pvt;489 spin_unlock_irqrestore(&ghes_lock, flags);490 491 ghes_register_report_chain(&ghes_edac_mem_err_nb);492 493 /* only set on success */494 refcount_set(&ghes_refcount, 1);495 496unlock:497 498 /* Not needed anymore */499 kfree(ghes_hw.dimms);500 ghes_hw.dimms = NULL;501 502 mutex_unlock(&ghes_reg_mutex);503 504 return rc;505}506 507static void ghes_edac_unregister(struct ghes *ghes)508{509 struct mem_ctl_info *mci;510 unsigned long flags;511 512 mutex_lock(&ghes_reg_mutex);513 514 system_scanned = false;515 memset(&ghes_hw, 0, sizeof(struct ghes_hw_desc));516 517 if (!refcount_dec_and_test(&ghes_refcount))518 goto unlock;519 520 /*521 * Wait for the irq handler being finished.522 */523 spin_lock_irqsave(&ghes_lock, flags);524 mci = ghes_pvt ? ghes_pvt->mci : NULL;525 ghes_pvt = NULL;526 spin_unlock_irqrestore(&ghes_lock, flags);527 528 if (!mci)529 goto unlock;530 531 mci = edac_mc_del_mc(mci->pdev);532 if (mci)533 edac_mc_free(mci);534 535 ghes_unregister_report_chain(&ghes_edac_mem_err_nb);536 537unlock:538 mutex_unlock(&ghes_reg_mutex);539}540 541static int __init ghes_edac_init(void)542{543 struct ghes *g, *g_tmp;544 545 ghes_devs = ghes_get_devices();546 if (!ghes_devs)547 return -ENODEV;548 549 if (list_empty(ghes_devs)) {550 pr_info("GHES probing device list is empty\n");551 return -ENODEV;552 }553 554 list_for_each_entry_safe(g, g_tmp, ghes_devs, elist) {555 ghes_edac_register(g->dev);556 }557 558 return 0;559}560module_init(ghes_edac_init);561 562static void __exit ghes_edac_exit(void)563{564 struct ghes *g, *g_tmp;565 566 list_for_each_entry_safe(g, g_tmp, ghes_devs, elist) {567 ghes_edac_unregister(g);568 }569}570module_exit(ghes_edac_exit);571 572MODULE_LICENSE("GPL");573MODULE_DESCRIPTION("Output ACPI APEI/GHES BIOS detected errors via EDAC");574