1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | list_for_each_entry_rcu(ghes, &ghes_nmi, list) { #ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG u32 len, node_len; struct ghes_estatus_node *estatus_node; struct acpi_hest_generic_status *estatus; #endif if (!(ghes->flags & GHES_TO_CLEAR)) continue; #ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG if (ghes_estatus_cached(ghes->estatus)) goto next; /* Save estatus for further processing in IRQ context */ len = apei_estatus_len(ghes->estatus); node_len = GHES_ESTATUS_NODE_LEN(len); estatus_node = (void *)gen_pool_alloc(ghes_estatus_pool, node_len); if (estatus_node) { estatus_node->generic = ghes->generic; estatus = GHES_ESTATUS_FROM_NODE(estatus_node); memcpy(estatus, ghes->estatus, len); llist_add(&estatus_node->llnode, &ghes_estatus_llist); } next: #endif ghes_clear_estatus(ghes); } #ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG irq_work_queue(&ghes_proc_irq_work); #endif out: raw_spin_unlock(&ghes_nmi_lock); return ret; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 在 drivers/acpi/apei/ghes.c 中 static void ghes_do_proc(const struct acpi_hest_generic_status *estatus) { int sev, sec_sev; struct acpi_hest_generic_data *gdata; sev = ghes_severity(estatus->error_severity); apei_estatus_for_each_section(estatus, gdata) { sec_sev = ghes_severity(gdata->error_severity); if (!uuid_le_cmp(*(uuid_le *)gdata->section_type, CPER_SEC_PLATFORM_MEM)) { struct cper_sec_mem_err *mem_err; mem_err = (struct cper_sec_mem_err *)(gdata+1); #ifdef CONFIG_X86_MCE apei_mce_report_mem_error(sev == GHES_SEV_CORRECTED, mem_err); #endif #ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE if (sev == GHES_SEV_RECOVERABLE && sec_sev == GHES_SEV_RECOVERABLE && mem_err->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS) { unsigned long pfn; pfn = mem_err->physical_addr >> PAGE_SHIFT; memory_failure_queue(pfn, 0, 0); } #endif } } } |
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) | Powered by Discuz! 7.0.0 |