Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'ras_core_for_v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull RAS updates from Borislav Petkov:

- Log and handle twp new AMD-specific MCA registers: SYND1 and SYND2
and report the Field Replaceable Unit text info reported through them

- Add support for handling variable-sized SMCA BERT records

- Add the capability for reporting vendor-specific RAS error info
without adding vendor-specific fields to struct mce

- Cleanups

* tag 'ras_core_for_v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
EDAC/mce_amd: Add support for FRU text in MCA
x86/mce/apei: Handle variable SMCA BERT record size
x86/MCE/AMD: Add support for new MCA_SYND{1,2} registers
tracing: Add __print_dynamic_array() helper
x86/mce: Add wrapper for struct mce to export vendor specific info
x86/mce/intel: Use MCG_BANKCNT_MASK instead of 0xff
x86/mce/mcelog: Use xchg() to get and clear the flags

+329 -191
+34 -2
arch/x86/include/asm/mce.h
··· 61 61 * - TCC bit is present in MCx_STATUS. 62 62 */ 63 63 #define MCI_CONFIG_MCAX 0x1 64 + #define MCI_CONFIG_FRUTEXT BIT_ULL(9) 64 65 #define MCI_IPID_MCATYPE 0xFFFF0000 65 66 #define MCI_IPID_HWID 0xFFF 66 67 ··· 123 122 #define MSR_AMD64_SMCA_MC0_DESTAT 0xc0002008 124 123 #define MSR_AMD64_SMCA_MC0_DEADDR 0xc0002009 125 124 #define MSR_AMD64_SMCA_MC0_MISC1 0xc000200a 125 + /* Registers MISC2 to MISC4 are at offsets B to D. */ 126 + #define MSR_AMD64_SMCA_MC0_SYND1 0xc000200e 127 + #define MSR_AMD64_SMCA_MC0_SYND2 0xc000200f 126 128 #define MSR_AMD64_SMCA_MCx_CTL(x) (MSR_AMD64_SMCA_MC0_CTL + 0x10*(x)) 127 129 #define MSR_AMD64_SMCA_MCx_STATUS(x) (MSR_AMD64_SMCA_MC0_STATUS + 0x10*(x)) 128 130 #define MSR_AMD64_SMCA_MCx_ADDR(x) (MSR_AMD64_SMCA_MC0_ADDR + 0x10*(x)) ··· 136 132 #define MSR_AMD64_SMCA_MCx_DESTAT(x) (MSR_AMD64_SMCA_MC0_DESTAT + 0x10*(x)) 137 133 #define MSR_AMD64_SMCA_MCx_DEADDR(x) (MSR_AMD64_SMCA_MC0_DEADDR + 0x10*(x)) 138 134 #define MSR_AMD64_SMCA_MCx_MISCy(x, y) ((MSR_AMD64_SMCA_MC0_MISC1 + y) + (0x10*(x))) 135 + #define MSR_AMD64_SMCA_MCx_SYND1(x) (MSR_AMD64_SMCA_MC0_SYND1 + 0x10*(x)) 136 + #define MSR_AMD64_SMCA_MCx_SYND2(x) (MSR_AMD64_SMCA_MC0_SYND2 + 0x10*(x)) 139 137 140 138 #define XEC(x, mask) (((x) >> 16) & mask) 141 139 ··· 193 187 MCE_PRIO_HIGHEST = MCE_PRIO_CEC 194 188 }; 195 189 190 + /** 191 + * struct mce_hw_err - Hardware Error Record. 192 + * @m: Machine Check record. 193 + * @vendor: Vendor-specific error information. 194 + * 195 + * Vendor-specific fields should not be added to struct mce. Instead, vendors 196 + * should export their vendor-specific data through their structure in the 197 + * vendor union below. 198 + * 199 + * AMD's vendor data is parsed by error decoding tools for supplemental error 200 + * information. Thus, current offsets of existing fields must be maintained. 201 + * Only add new fields at the end of AMD's vendor structure. 202 + */ 203 + struct mce_hw_err { 204 + struct mce m; 205 + 206 + union vendor_info { 207 + struct { 208 + u64 synd1; /* MCA_SYND1 MSR */ 209 + u64 synd2; /* MCA_SYND2 MSR */ 210 + } amd; 211 + } vendor; 212 + }; 213 + 214 + #define to_mce_hw_err(mce) container_of(mce, struct mce_hw_err, m) 215 + 196 216 struct notifier_block; 197 217 extern void mce_register_decode_chain(struct notifier_block *nb); 198 218 extern void mce_unregister_decode_chain(struct notifier_block *nb); ··· 253 221 u64 lapic_id) { return -EINVAL; } 254 222 #endif 255 223 256 - void mce_prep_record(struct mce *m); 257 - void mce_log(struct mce *m); 224 + void mce_prep_record(struct mce_hw_err *err); 225 + void mce_log(struct mce_hw_err *err); 258 226 DECLARE_PER_CPU(struct device *, mce_device); 259 227 260 228 /* Maximum number of MCA banks per CPU. */
+2 -1
arch/x86/include/uapi/asm/mce.h
··· 8 8 /* 9 9 * Fields are zero when not available. Also, this struct is shared with 10 10 * userspace mcelog and thus must keep existing fields at current offsets. 11 - * Only add new fields to the end of the structure 11 + * Only add new, shared fields to the end of the structure. 12 + * Do not add vendor-specific fields. 12 13 */ 13 14 struct mce { 14 15 __u64 status; /* Bank's MCi_STATUS MSR */
+17 -13
arch/x86/kernel/cpu/mce/amd.c
··· 778 778 779 779 static void __log_error(unsigned int bank, u64 status, u64 addr, u64 misc) 780 780 { 781 - struct mce m; 781 + struct mce_hw_err err; 782 + struct mce *m = &err.m; 782 783 783 - mce_prep_record(&m); 784 + mce_prep_record(&err); 784 785 785 - m.status = status; 786 - m.misc = misc; 787 - m.bank = bank; 788 - m.tsc = rdtsc(); 786 + m->status = status; 787 + m->misc = misc; 788 + m->bank = bank; 789 + m->tsc = rdtsc(); 789 790 790 - if (m.status & MCI_STATUS_ADDRV) { 791 - m.addr = addr; 791 + if (m->status & MCI_STATUS_ADDRV) { 792 + m->addr = addr; 792 793 793 - smca_extract_err_addr(&m); 794 + smca_extract_err_addr(m); 794 795 } 795 796 796 797 if (mce_flags.smca) { 797 - rdmsrl(MSR_AMD64_SMCA_MCx_IPID(bank), m.ipid); 798 + rdmsrl(MSR_AMD64_SMCA_MCx_IPID(bank), m->ipid); 798 799 799 - if (m.status & MCI_STATUS_SYNDV) 800 - rdmsrl(MSR_AMD64_SMCA_MCx_SYND(bank), m.synd); 800 + if (m->status & MCI_STATUS_SYNDV) { 801 + rdmsrl(MSR_AMD64_SMCA_MCx_SYND(bank), m->synd); 802 + rdmsrl(MSR_AMD64_SMCA_MCx_SYND1(bank), err.vendor.amd.synd1); 803 + rdmsrl(MSR_AMD64_SMCA_MCx_SYND2(bank), err.vendor.amd.synd2); 804 + } 801 805 } 802 806 803 - mce_log(&m); 807 + mce_log(&err); 804 808 } 805 809 806 810 DEFINE_IDTENTRY_SYSVEC(sysvec_deferred_error)
+78 -29
arch/x86/kernel/cpu/mce/apei.c
··· 28 28 29 29 void apei_mce_report_mem_error(int severity, struct cper_sec_mem_err *mem_err) 30 30 { 31 - struct mce m; 31 + struct mce_hw_err err; 32 + struct mce *m; 32 33 int lsb; 33 34 34 35 if (!(mem_err->validation_bits & CPER_MEM_VALID_PA)) ··· 45 44 else 46 45 lsb = PAGE_SHIFT; 47 46 48 - mce_prep_record(&m); 49 - m.bank = -1; 47 + mce_prep_record(&err); 48 + m = &err.m; 49 + m->bank = -1; 50 50 /* Fake a memory read error with unknown channel */ 51 - m.status = MCI_STATUS_VAL | MCI_STATUS_EN | MCI_STATUS_ADDRV | MCI_STATUS_MISCV | 0x9f; 52 - m.misc = (MCI_MISC_ADDR_PHYS << 6) | lsb; 51 + m->status = MCI_STATUS_VAL | MCI_STATUS_EN | MCI_STATUS_ADDRV | MCI_STATUS_MISCV | 0x9f; 52 + m->misc = (MCI_MISC_ADDR_PHYS << 6) | lsb; 53 53 54 54 if (severity >= GHES_SEV_RECOVERABLE) 55 - m.status |= MCI_STATUS_UC; 55 + m->status |= MCI_STATUS_UC; 56 56 57 57 if (severity >= GHES_SEV_PANIC) { 58 - m.status |= MCI_STATUS_PCC; 59 - m.tsc = rdtsc(); 58 + m->status |= MCI_STATUS_PCC; 59 + m->tsc = rdtsc(); 60 60 } 61 61 62 - m.addr = mem_err->physical_addr; 63 - mce_log(&m); 62 + m->addr = mem_err->physical_addr; 63 + mce_log(&err); 64 64 } 65 65 EXPORT_SYMBOL_GPL(apei_mce_report_mem_error); 66 66 67 67 int apei_smca_report_x86_error(struct cper_ia_proc_ctx *ctx_info, u64 lapic_id) 68 68 { 69 69 const u64 *i_mce = ((const u64 *) (ctx_info + 1)); 70 + unsigned int cpu, num_regs; 70 71 bool apicid_found = false; 71 - unsigned int cpu; 72 - struct mce m; 72 + struct mce_hw_err err; 73 + struct mce *m; 73 74 74 75 if (!boot_cpu_has(X86_FEATURE_SMCA)) 75 76 return -EINVAL; ··· 89 86 return -EINVAL; 90 87 91 88 /* 92 - * The register array size must be large enough to include all the 93 - * SMCA registers which need to be extracted. 94 - * 95 89 * The number of registers in the register array is determined by 96 90 * Register Array Size/8 as defined in UEFI spec v2.8, sec N.2.4.2.2. 97 - * The register layout is fixed and currently the raw data in the 98 - * register array includes 6 SMCA registers which the kernel can 99 - * extract. 91 + * Sanity-check registers array size. 100 92 */ 101 - if (ctx_info->reg_arr_size < 48) 93 + num_regs = ctx_info->reg_arr_size >> 3; 94 + if (!num_regs) 102 95 return -EINVAL; 103 96 104 97 for_each_possible_cpu(cpu) { ··· 107 108 if (!apicid_found) 108 109 return -EINVAL; 109 110 110 - mce_prep_record_common(&m); 111 - mce_prep_record_per_cpu(cpu, &m); 111 + m = &err.m; 112 + memset(&err, 0, sizeof(struct mce_hw_err)); 113 + mce_prep_record_common(m); 114 + mce_prep_record_per_cpu(cpu, m); 112 115 113 - m.bank = (ctx_info->msr_addr >> 4) & 0xFF; 114 - m.status = *i_mce; 115 - m.addr = *(i_mce + 1); 116 - m.misc = *(i_mce + 2); 117 - /* Skipping MCA_CONFIG */ 118 - m.ipid = *(i_mce + 4); 119 - m.synd = *(i_mce + 5); 116 + m->bank = (ctx_info->msr_addr >> 4) & 0xFF; 120 117 121 - mce_log(&m); 118 + /* 119 + * The SMCA register layout is fixed and includes 16 registers. 120 + * The end of the array may be variable, but the beginning is known. 121 + * Cap the number of registers to expected max (15). 122 + */ 123 + if (num_regs > 15) 124 + num_regs = 15; 125 + 126 + switch (num_regs) { 127 + /* MCA_SYND2 */ 128 + case 15: 129 + err.vendor.amd.synd2 = *(i_mce + 14); 130 + fallthrough; 131 + /* MCA_SYND1 */ 132 + case 14: 133 + err.vendor.amd.synd1 = *(i_mce + 13); 134 + fallthrough; 135 + /* MCA_MISC4 */ 136 + case 13: 137 + /* MCA_MISC3 */ 138 + case 12: 139 + /* MCA_MISC2 */ 140 + case 11: 141 + /* MCA_MISC1 */ 142 + case 10: 143 + /* MCA_DEADDR */ 144 + case 9: 145 + /* MCA_DESTAT */ 146 + case 8: 147 + /* reserved */ 148 + case 7: 149 + /* MCA_SYND */ 150 + case 6: 151 + m->synd = *(i_mce + 5); 152 + fallthrough; 153 + /* MCA_IPID */ 154 + case 5: 155 + m->ipid = *(i_mce + 4); 156 + fallthrough; 157 + /* MCA_CONFIG */ 158 + case 4: 159 + /* MCA_MISC0 */ 160 + case 3: 161 + m->misc = *(i_mce + 2); 162 + fallthrough; 163 + /* MCA_ADDR */ 164 + case 2: 165 + m->addr = *(i_mce + 1); 166 + fallthrough; 167 + /* MCA_STATUS */ 168 + case 1: 169 + m->status = *i_mce; 170 + } 171 + 172 + mce_log(&err); 122 173 123 174 return 0; 124 175 }
+123 -93
arch/x86/kernel/cpu/mce/core.c
··· 88 88 .monarch_timeout = -1 89 89 }; 90 90 91 - static DEFINE_PER_CPU(struct mce, mces_seen); 91 + static DEFINE_PER_CPU(struct mce_hw_err, hw_errs_seen); 92 92 static unsigned long mce_need_notify; 93 93 94 94 /* ··· 119 119 120 120 void mce_prep_record_common(struct mce *m) 121 121 { 122 - memset(m, 0, sizeof(struct mce)); 123 - 124 122 m->cpuid = cpuid_eax(1); 125 123 m->cpuvendor = boot_cpu_data.x86_vendor; 126 124 m->mcgcap = __rdmsr(MSR_IA32_MCG_CAP); ··· 136 138 m->socketid = topology_physical_package_id(cpu); 137 139 } 138 140 139 - /* Do initial initialization of a struct mce */ 140 - void mce_prep_record(struct mce *m) 141 + /* Do initial initialization of struct mce_hw_err */ 142 + void mce_prep_record(struct mce_hw_err *err) 141 143 { 144 + struct mce *m = &err->m; 145 + 146 + memset(err, 0, sizeof(struct mce_hw_err)); 142 147 mce_prep_record_common(m); 143 148 mce_prep_record_per_cpu(smp_processor_id(), m); 144 149 } ··· 149 148 DEFINE_PER_CPU(struct mce, injectm); 150 149 EXPORT_PER_CPU_SYMBOL_GPL(injectm); 151 150 152 - void mce_log(struct mce *m) 151 + void mce_log(struct mce_hw_err *err) 153 152 { 154 - if (!mce_gen_pool_add(m)) 153 + if (!mce_gen_pool_add(err)) 155 154 irq_work_queue(&mce_irq_work); 156 155 } 157 156 EXPORT_SYMBOL_GPL(mce_log); ··· 172 171 } 173 172 EXPORT_SYMBOL_GPL(mce_unregister_decode_chain); 174 173 175 - static void __print_mce(struct mce *m) 174 + static void __print_mce(struct mce_hw_err *err) 176 175 { 176 + struct mce *m = &err->m; 177 + 177 178 pr_emerg(HW_ERR "CPU %d: Machine Check%s: %Lx Bank %d: %016Lx\n", 178 179 m->extcpu, 179 180 (m->mcgstatus & MCG_STATUS_MCIP ? " Exception" : ""), ··· 202 199 if (mce_flags.smca) { 203 200 if (m->synd) 204 201 pr_cont("SYND %llx ", m->synd); 202 + if (err->vendor.amd.synd1) 203 + pr_cont("SYND1 %llx ", err->vendor.amd.synd1); 204 + if (err->vendor.amd.synd2) 205 + pr_cont("SYND2 %llx ", err->vendor.amd.synd2); 205 206 if (m->ipid) 206 207 pr_cont("IPID %llx ", m->ipid); 207 208 } ··· 221 214 m->microcode); 222 215 } 223 216 224 - static void print_mce(struct mce *m) 217 + static void print_mce(struct mce_hw_err *err) 225 218 { 226 - __print_mce(m); 219 + struct mce *m = &err->m; 220 + 221 + __print_mce(err); 227 222 228 223 if (m->cpuvendor != X86_VENDOR_AMD && m->cpuvendor != X86_VENDOR_HYGON) 229 224 pr_emerg_ratelimited(HW_ERR "Run the above through 'mcelog --ascii'\n"); ··· 260 251 return NULL; 261 252 } 262 253 263 - static noinstr void mce_panic(const char *msg, struct mce *final, char *exp) 254 + static noinstr void mce_panic(const char *msg, struct mce_hw_err *final, char *exp) 264 255 { 265 256 struct llist_node *pending; 266 257 struct mce_evt_llist *l; ··· 291 282 pending = mce_gen_pool_prepare_records(); 292 283 /* First print corrected ones that are still unlogged */ 293 284 llist_for_each_entry(l, pending, llnode) { 294 - struct mce *m = &l->mce; 285 + struct mce_hw_err *err = &l->err; 286 + struct mce *m = &err->m; 295 287 if (!(m->status & MCI_STATUS_UC)) { 296 - print_mce(m); 288 + print_mce(err); 297 289 if (!apei_err) 298 290 apei_err = apei_write_mce(m); 299 291 } 300 292 } 301 293 /* Now print uncorrected but with the final one last */ 302 294 llist_for_each_entry(l, pending, llnode) { 303 - struct mce *m = &l->mce; 295 + struct mce_hw_err *err = &l->err; 296 + struct mce *m = &err->m; 304 297 if (!(m->status & MCI_STATUS_UC)) 305 298 continue; 306 - if (!final || mce_cmp(m, final)) { 307 - print_mce(m); 299 + if (!final || mce_cmp(m, &final->m)) { 300 + print_mce(err); 308 301 if (!apei_err) 309 302 apei_err = apei_write_mce(m); 310 303 } ··· 314 303 if (final) { 315 304 print_mce(final); 316 305 if (!apei_err) 317 - apei_err = apei_write_mce(final); 306 + apei_err = apei_write_mce(&final->m); 318 307 } 319 308 if (exp) 320 309 pr_emerg(HW_ERR "Machine check: %s\n", exp); 321 310 322 - memmsg = mce_dump_aux_info(final); 311 + memmsg = mce_dump_aux_info(&final->m); 323 312 if (memmsg) 324 313 pr_emerg(HW_ERR "Machine check: %s\n", memmsg); 325 314 ··· 334 323 * panic. 335 324 */ 336 325 if (kexec_crash_loaded()) { 337 - if (final && (final->status & MCI_STATUS_ADDRV)) { 326 + if (final && (final->m.status & MCI_STATUS_ADDRV)) { 338 327 struct page *p; 339 - p = pfn_to_online_page(final->addr >> PAGE_SHIFT); 328 + p = pfn_to_online_page(final->m.addr >> PAGE_SHIFT); 340 329 if (p) 341 330 SetPageHWPoison(p); 342 331 } ··· 456 445 * check into our "mce" struct so that we can use it later to assess 457 446 * the severity of the problem as we read per-bank specific details. 458 447 */ 459 - static noinstr void mce_gather_info(struct mce *m, struct pt_regs *regs) 448 + static noinstr void mce_gather_info(struct mce_hw_err *err, struct pt_regs *regs) 460 449 { 450 + struct mce *m; 461 451 /* 462 452 * Enable instrumentation around mce_prep_record() which calls external 463 453 * facilities. 464 454 */ 465 455 instrumentation_begin(); 466 - mce_prep_record(m); 456 + mce_prep_record(err); 467 457 instrumentation_end(); 468 458 459 + m = &err->m; 469 460 m->mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS); 470 461 if (regs) { 471 462 /* ··· 587 574 static int mce_early_notifier(struct notifier_block *nb, unsigned long val, 588 575 void *data) 589 576 { 590 - struct mce *m = (struct mce *)data; 577 + struct mce_hw_err *err = to_mce_hw_err(data); 591 578 592 - if (!m) 579 + if (!err) 593 580 return NOTIFY_DONE; 594 581 595 582 /* Emit the trace record: */ 596 - trace_mce_record(m); 583 + trace_mce_record(err); 597 584 598 585 set_bit(0, &mce_need_notify); 599 586 ··· 637 624 static int mce_default_notifier(struct notifier_block *nb, unsigned long val, 638 625 void *data) 639 626 { 640 - struct mce *m = (struct mce *)data; 627 + struct mce_hw_err *err = to_mce_hw_err(data); 641 628 642 - if (!m) 629 + if (!err) 643 630 return NOTIFY_DONE; 644 631 645 - if (mca_cfg.print_all || !m->kflags) 646 - __print_mce(m); 632 + if (mca_cfg.print_all || !(err->m.kflags)) 633 + __print_mce(err); 647 634 648 635 return NOTIFY_DONE; 649 636 } ··· 657 644 /* 658 645 * Read ADDR and MISC registers. 659 646 */ 660 - static noinstr void mce_read_aux(struct mce *m, int i) 647 + static noinstr void mce_read_aux(struct mce_hw_err *err, int i) 661 648 { 649 + struct mce *m = &err->m; 650 + 662 651 if (m->status & MCI_STATUS_MISCV) 663 652 m->misc = mce_rdmsrl(mca_msr_reg(i, MCA_MISC)); 664 653 ··· 682 667 if (mce_flags.smca) { 683 668 m->ipid = mce_rdmsrl(MSR_AMD64_SMCA_MCx_IPID(i)); 684 669 685 - if (m->status & MCI_STATUS_SYNDV) 670 + if (m->status & MCI_STATUS_SYNDV) { 686 671 m->synd = mce_rdmsrl(MSR_AMD64_SMCA_MCx_SYND(i)); 672 + err->vendor.amd.synd1 = mce_rdmsrl(MSR_AMD64_SMCA_MCx_SYND1(i)); 673 + err->vendor.amd.synd2 = mce_rdmsrl(MSR_AMD64_SMCA_MCx_SYND2(i)); 674 + } 687 675 } 688 676 } 689 677 ··· 710 692 void machine_check_poll(enum mcp_flags flags, mce_banks_t *b) 711 693 { 712 694 struct mce_bank *mce_banks = this_cpu_ptr(mce_banks_array); 713 - struct mce m; 695 + struct mce_hw_err err; 696 + struct mce *m; 714 697 int i; 715 698 716 699 this_cpu_inc(mce_poll_count); 717 700 718 - mce_gather_info(&m, NULL); 701 + mce_gather_info(&err, NULL); 702 + m = &err.m; 719 703 720 704 if (flags & MCP_TIMESTAMP) 721 - m.tsc = rdtsc(); 705 + m->tsc = rdtsc(); 722 706 723 707 for (i = 0; i < this_cpu_read(mce_num_banks); i++) { 724 708 if (!mce_banks[i].ctl || !test_bit(i, *b)) 725 709 continue; 726 710 727 - m.misc = 0; 728 - m.addr = 0; 729 - m.bank = i; 711 + m->misc = 0; 712 + m->addr = 0; 713 + m->bank = i; 730 714 731 715 barrier(); 732 - m.status = mce_rdmsrl(mca_msr_reg(i, MCA_STATUS)); 716 + m->status = mce_rdmsrl(mca_msr_reg(i, MCA_STATUS)); 733 717 734 718 /* 735 719 * Update storm tracking here, before checking for the ··· 741 721 * storm status. 742 722 */ 743 723 if (!mca_cfg.cmci_disabled) 744 - mce_track_storm(&m); 724 + mce_track_storm(m); 745 725 746 726 /* If this entry is not valid, ignore it */ 747 - if (!(m.status & MCI_STATUS_VAL)) 727 + if (!(m->status & MCI_STATUS_VAL)) 748 728 continue; 749 729 750 730 /* 751 731 * If we are logging everything (at CPU online) or this 752 732 * is a corrected error, then we must log it. 753 733 */ 754 - if ((flags & MCP_UC) || !(m.status & MCI_STATUS_UC)) 734 + if ((flags & MCP_UC) || !(m->status & MCI_STATUS_UC)) 755 735 goto log_it; 756 736 757 737 /* ··· 761 741 * everything else. 762 742 */ 763 743 if (!mca_cfg.ser) { 764 - if (m.status & MCI_STATUS_UC) 744 + if (m->status & MCI_STATUS_UC) 765 745 continue; 766 746 goto log_it; 767 747 } 768 748 769 749 /* Log "not enabled" (speculative) errors */ 770 - if (!(m.status & MCI_STATUS_EN)) 750 + if (!(m->status & MCI_STATUS_EN)) 771 751 goto log_it; 772 752 773 753 /* 774 754 * Log UCNA (SDM: 15.6.3 "UCR Error Classification") 775 755 * UC == 1 && PCC == 0 && S == 0 776 756 */ 777 - if (!(m.status & MCI_STATUS_PCC) && !(m.status & MCI_STATUS_S)) 757 + if (!(m->status & MCI_STATUS_PCC) && !(m->status & MCI_STATUS_S)) 778 758 goto log_it; 779 759 780 760 /* ··· 788 768 if (flags & MCP_DONTLOG) 789 769 goto clear_it; 790 770 791 - mce_read_aux(&m, i); 792 - m.severity = mce_severity(&m, NULL, NULL, false); 771 + mce_read_aux(&err, i); 772 + m->severity = mce_severity(m, NULL, NULL, false); 793 773 /* 794 774 * Don't get the IP here because it's unlikely to 795 775 * have anything to do with the actual error location. 796 776 */ 797 777 798 - if (mca_cfg.dont_log_ce && !mce_usable_address(&m)) 778 + if (mca_cfg.dont_log_ce && !mce_usable_address(m)) 799 779 goto clear_it; 800 780 801 781 if (flags & MCP_QUEUE_LOG) 802 - mce_gen_pool_add(&m); 782 + mce_gen_pool_add(&err); 803 783 else 804 - mce_log(&m); 784 + mce_log(&err); 805 785 806 786 clear_it: 807 787 /* ··· 925 905 * Do a quick check if any of the events requires a panic. 926 906 * This decides if we keep the events around or clear them. 927 907 */ 928 - static __always_inline int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp, 908 + static __always_inline int mce_no_way_out(struct mce_hw_err *err, char **msg, unsigned long *validp, 929 909 struct pt_regs *regs) 930 910 { 911 + struct mce *m = &err->m; 931 912 char *tmp = *msg; 932 913 int i; 933 914 ··· 946 925 947 926 m->bank = i; 948 927 if (mce_severity(m, regs, &tmp, true) >= MCE_PANIC_SEVERITY) { 949 - mce_read_aux(m, i); 928 + mce_read_aux(err, i); 950 929 *msg = tmp; 951 930 return 1; 952 931 } ··· 1037 1016 */ 1038 1017 static void mce_reign(void) 1039 1018 { 1040 - int cpu; 1019 + struct mce_hw_err *err = NULL; 1041 1020 struct mce *m = NULL; 1042 1021 int global_worst = 0; 1043 1022 char *msg = NULL; 1023 + int cpu; 1044 1024 1045 1025 /* 1046 1026 * This CPU is the Monarch and the other CPUs have run ··· 1049 1027 * Grade the severity of the errors of all the CPUs. 1050 1028 */ 1051 1029 for_each_possible_cpu(cpu) { 1052 - struct mce *mtmp = &per_cpu(mces_seen, cpu); 1030 + struct mce_hw_err *etmp = &per_cpu(hw_errs_seen, cpu); 1031 + struct mce *mtmp = &etmp->m; 1053 1032 1054 1033 if (mtmp->severity > global_worst) { 1055 1034 global_worst = mtmp->severity; 1056 - m = &per_cpu(mces_seen, cpu); 1035 + err = &per_cpu(hw_errs_seen, cpu); 1036 + m = &err->m; 1057 1037 } 1058 1038 } 1059 1039 ··· 1067 1043 if (m && global_worst >= MCE_PANIC_SEVERITY) { 1068 1044 /* call mce_severity() to get "msg" for panic */ 1069 1045 mce_severity(m, NULL, &msg, true); 1070 - mce_panic("Fatal machine check", m, msg); 1046 + mce_panic("Fatal machine check", err, msg); 1071 1047 } 1072 1048 1073 1049 /* ··· 1084 1060 mce_panic("Fatal machine check from unknown source", NULL, NULL); 1085 1061 1086 1062 /* 1087 - * Now clear all the mces_seen so that they don't reappear on 1063 + * Now clear all the hw_errs_seen so that they don't reappear on 1088 1064 * the next mce. 1089 1065 */ 1090 1066 for_each_possible_cpu(cpu) 1091 - memset(&per_cpu(mces_seen, cpu), 0, sizeof(struct mce)); 1067 + memset(&per_cpu(hw_errs_seen, cpu), 0, sizeof(struct mce_hw_err)); 1092 1068 } 1093 1069 1094 1070 static atomic_t global_nwo; ··· 1292 1268 } 1293 1269 1294 1270 static __always_inline int 1295 - __mc_scan_banks(struct mce *m, struct pt_regs *regs, struct mce *final, 1296 - unsigned long *toclear, unsigned long *valid_banks, int no_way_out, 1297 - int *worst) 1271 + __mc_scan_banks(struct mce_hw_err *err, struct pt_regs *regs, 1272 + struct mce_hw_err *final, unsigned long *toclear, 1273 + unsigned long *valid_banks, int no_way_out, int *worst) 1298 1274 { 1299 1275 struct mce_bank *mce_banks = this_cpu_ptr(mce_banks_array); 1300 1276 struct mca_config *cfg = &mca_cfg; 1301 1277 int severity, i, taint = 0; 1278 + struct mce *m = &err->m; 1302 1279 1303 1280 for (i = 0; i < this_cpu_read(mce_num_banks); i++) { 1304 1281 arch___clear_bit(i, toclear); ··· 1344 1319 if (severity == MCE_NO_SEVERITY) 1345 1320 continue; 1346 1321 1347 - mce_read_aux(m, i); 1322 + mce_read_aux(err, i); 1348 1323 1349 1324 /* assuming valid severity level != 0 */ 1350 1325 m->severity = severity; ··· 1354 1329 * done in #MC context, where instrumentation is disabled. 1355 1330 */ 1356 1331 instrumentation_begin(); 1357 - mce_log(m); 1332 + mce_log(err); 1358 1333 instrumentation_end(); 1359 1334 1360 1335 if (severity > *worst) { 1361 - *final = *m; 1336 + *final = *err; 1362 1337 *worst = severity; 1363 1338 } 1364 1339 } 1365 1340 1366 1341 /* mce_clear_state will clear *final, save locally for use later */ 1367 - *m = *final; 1342 + *err = *final; 1368 1343 1369 1344 return taint; 1370 1345 } ··· 1424 1399 set_mce_nospec(pfn); 1425 1400 } 1426 1401 1427 - static void queue_task_work(struct mce *m, char *msg, void (*func)(struct callback_head *)) 1402 + static void queue_task_work(struct mce_hw_err *err, char *msg, void (*func)(struct callback_head *)) 1428 1403 { 1429 1404 int count = ++current->mce_count; 1405 + struct mce *m = &err->m; 1430 1406 1431 1407 /* First call, save all the details */ 1432 1408 if (count == 1) { ··· 1440 1414 1441 1415 /* Ten is likely overkill. Don't expect more than two faults before task_work() */ 1442 1416 if (count > 10) 1443 - mce_panic("Too many consecutive machine checks while accessing user data", m, msg); 1417 + mce_panic("Too many consecutive machine checks while accessing user data", 1418 + err, msg); 1444 1419 1445 1420 /* Second or later call, make sure page address matches the one from first call */ 1446 1421 if (count > 1 && (current->mce_addr >> PAGE_SHIFT) != (m->addr >> PAGE_SHIFT)) 1447 - mce_panic("Consecutive machine checks to different user pages", m, msg); 1422 + mce_panic("Consecutive machine checks to different user pages", err, msg); 1448 1423 1449 1424 /* Do not call task_work_add() more than once */ 1450 1425 if (count > 1) ··· 1494 1467 int worst = 0, order, no_way_out, kill_current_task, lmce, taint = 0; 1495 1468 DECLARE_BITMAP(valid_banks, MAX_NR_BANKS) = { 0 }; 1496 1469 DECLARE_BITMAP(toclear, MAX_NR_BANKS) = { 0 }; 1497 - struct mce m, *final; 1470 + struct mce_hw_err *final; 1471 + struct mce_hw_err err; 1498 1472 char *msg = NULL; 1473 + struct mce *m; 1499 1474 1500 1475 if (unlikely(mce_flags.p5)) 1501 1476 return pentium_machine_check(regs); ··· 1535 1506 1536 1507 this_cpu_inc(mce_exception_count); 1537 1508 1538 - mce_gather_info(&m, regs); 1539 - m.tsc = rdtsc(); 1509 + mce_gather_info(&err, regs); 1510 + m = &err.m; 1511 + m->tsc = rdtsc(); 1540 1512 1541 - final = this_cpu_ptr(&mces_seen); 1542 - *final = m; 1513 + final = this_cpu_ptr(&hw_errs_seen); 1514 + *final = err; 1543 1515 1544 - no_way_out = mce_no_way_out(&m, &msg, valid_banks, regs); 1516 + no_way_out = mce_no_way_out(&err, &msg, valid_banks, regs); 1545 1517 1546 1518 barrier(); 1547 1519 ··· 1551 1521 * Assume the worst for now, but if we find the 1552 1522 * severity is MCE_AR_SEVERITY we have other options. 1553 1523 */ 1554 - if (!(m.mcgstatus & MCG_STATUS_RIPV)) 1524 + if (!(m->mcgstatus & MCG_STATUS_RIPV)) 1555 1525 kill_current_task = 1; 1556 1526 /* 1557 1527 * Check if this MCE is signaled to only this logical processor, 1558 1528 * on Intel, Zhaoxin only. 1559 1529 */ 1560 - if (m.cpuvendor == X86_VENDOR_INTEL || 1561 - m.cpuvendor == X86_VENDOR_ZHAOXIN) 1562 - lmce = m.mcgstatus & MCG_STATUS_LMCES; 1530 + if (m->cpuvendor == X86_VENDOR_INTEL || 1531 + m->cpuvendor == X86_VENDOR_ZHAOXIN) 1532 + lmce = m->mcgstatus & MCG_STATUS_LMCES; 1563 1533 1564 1534 /* 1565 1535 * Local machine check may already know that we have to panic. ··· 1570 1540 */ 1571 1541 if (lmce) { 1572 1542 if (no_way_out) 1573 - mce_panic("Fatal local machine check", &m, msg); 1543 + mce_panic("Fatal local machine check", &err, msg); 1574 1544 } else { 1575 1545 order = mce_start(&no_way_out); 1576 1546 } 1577 1547 1578 - taint = __mc_scan_banks(&m, regs, final, toclear, valid_banks, no_way_out, &worst); 1548 + taint = __mc_scan_banks(&err, regs, final, toclear, valid_banks, no_way_out, &worst); 1579 1549 1580 1550 if (!no_way_out) 1581 1551 mce_clear_state(toclear); ··· 1590 1560 no_way_out = worst >= MCE_PANIC_SEVERITY; 1591 1561 1592 1562 if (no_way_out) 1593 - mce_panic("Fatal machine check on current CPU", &m, msg); 1563 + mce_panic("Fatal machine check on current CPU", &err, msg); 1594 1564 } 1595 1565 } else { 1596 1566 /* ··· 1602 1572 * make sure we have the right "msg". 1603 1573 */ 1604 1574 if (worst >= MCE_PANIC_SEVERITY) { 1605 - mce_severity(&m, regs, &msg, true); 1606 - mce_panic("Local fatal machine check!", &m, msg); 1575 + mce_severity(m, regs, &msg, true); 1576 + mce_panic("Local fatal machine check!", &err, msg); 1607 1577 } 1608 1578 } 1609 1579 ··· 1621 1591 goto out; 1622 1592 1623 1593 /* Fault was in user mode and we need to take some action */ 1624 - if ((m.cs & 3) == 3) { 1594 + if ((m->cs & 3) == 3) { 1625 1595 /* If this triggers there is no way to recover. Die hard. */ 1626 1596 BUG_ON(!on_thread_stack() || !user_mode(regs)); 1627 1597 1628 - if (!mce_usable_address(&m)) 1629 - queue_task_work(&m, msg, kill_me_now); 1598 + if (!mce_usable_address(m)) 1599 + queue_task_work(&err, msg, kill_me_now); 1630 1600 else 1631 - queue_task_work(&m, msg, kill_me_maybe); 1601 + queue_task_work(&err, msg, kill_me_maybe); 1632 1602 1633 - } else if (m.mcgstatus & MCG_STATUS_SEAM_NR) { 1603 + } else if (m->mcgstatus & MCG_STATUS_SEAM_NR) { 1634 1604 /* 1635 1605 * Saved RIP on stack makes it look like the machine check 1636 1606 * was taken in the kernel on the instruction following ··· 1642 1612 * not occur there. Mark the page as poisoned so it won't 1643 1613 * be added to free list when the guest is terminated. 1644 1614 */ 1645 - if (mce_usable_address(&m)) { 1646 - struct page *p = pfn_to_online_page(m.addr >> PAGE_SHIFT); 1615 + if (mce_usable_address(m)) { 1616 + struct page *p = pfn_to_online_page(m->addr >> PAGE_SHIFT); 1647 1617 1648 1618 if (p) 1649 1619 SetPageHWPoison(p); ··· 1658 1628 * corresponding exception handler which would do that is the 1659 1629 * proper one. 1660 1630 */ 1661 - if (m.kflags & MCE_IN_KERNEL_RECOV) { 1631 + if (m->kflags & MCE_IN_KERNEL_RECOV) { 1662 1632 if (!fixup_exception(regs, X86_TRAP_MC, 0, 0)) 1663 - mce_panic("Failed kernel mode recovery", &m, msg); 1633 + mce_panic("Failed kernel mode recovery", &err, msg); 1664 1634 } 1665 1635 1666 - if (m.kflags & MCE_IN_KERNEL_COPYIN) 1667 - queue_task_work(&m, msg, kill_me_never); 1636 + if (m->kflags & MCE_IN_KERNEL_COPYIN) 1637 + queue_task_work(&err, msg, kill_me_never); 1668 1638 } 1669 1639 1670 1640 out:
+2 -9
arch/x86/kernel/cpu/mce/dev-mcelog.c
··· 264 264 return put_user(sizeof(struct mce), p); 265 265 case MCE_GET_LOG_LEN: 266 266 return put_user(mcelog->len, p); 267 - case MCE_GETCLEAR_FLAGS: { 268 - unsigned flags; 269 - 270 - do { 271 - flags = mcelog->flags; 272 - } while (cmpxchg(&mcelog->flags, flags, 0) != flags); 273 - 274 - return put_user(flags, p); 275 - } 267 + case MCE_GETCLEAR_FLAGS: 268 + return put_user(xchg(&mcelog->flags, 0), p); 276 269 default: 277 270 return -ENOTTY; 278 271 }
+9 -9
arch/x86/kernel/cpu/mce/genpool.c
··· 31 31 */ 32 32 static bool is_duplicate_mce_record(struct mce_evt_llist *t, struct mce_evt_llist *l) 33 33 { 34 + struct mce_hw_err *err1, *err2; 34 35 struct mce_evt_llist *node; 35 - struct mce *m1, *m2; 36 36 37 - m1 = &t->mce; 37 + err1 = &t->err; 38 38 39 39 llist_for_each_entry(node, &l->llnode, llnode) { 40 - m2 = &node->mce; 40 + err2 = &node->err; 41 41 42 - if (!mce_cmp(m1, m2)) 42 + if (!mce_cmp(&err1->m, &err2->m)) 43 43 return true; 44 44 } 45 45 return false; ··· 73 73 74 74 void mce_gen_pool_process(struct work_struct *__unused) 75 75 { 76 - struct llist_node *head; 77 76 struct mce_evt_llist *node, *tmp; 77 + struct llist_node *head; 78 78 struct mce *mce; 79 79 80 80 head = llist_del_all(&mce_event_llist); ··· 83 83 84 84 head = llist_reverse_order(head); 85 85 llist_for_each_entry_safe(node, tmp, head, llnode) { 86 - mce = &node->mce; 86 + mce = &node->err.m; 87 87 blocking_notifier_call_chain(&x86_mce_decoder_chain, 0, mce); 88 88 gen_pool_free(mce_evt_pool, (unsigned long)node, sizeof(*node)); 89 89 } ··· 94 94 return llist_empty(&mce_event_llist); 95 95 } 96 96 97 - int mce_gen_pool_add(struct mce *mce) 97 + int mce_gen_pool_add(struct mce_hw_err *err) 98 98 { 99 99 struct mce_evt_llist *node; 100 100 101 - if (filter_mce(mce)) 101 + if (filter_mce(&err->m)) 102 102 return -EINVAL; 103 103 104 104 if (!mce_evt_pool) ··· 110 110 return -ENOMEM; 111 111 } 112 112 113 - memcpy(&node->mce, mce, sizeof(*mce)); 113 + memcpy(&node->err, err, sizeof(*err)); 114 114 llist_add(&node->llnode, &mce_event_llist); 115 115 116 116 return 0;
+4 -2
arch/x86/kernel/cpu/mce/inject.c
··· 502 502 503 503 static void do_inject(void) 504 504 { 505 - u64 mcg_status = 0; 506 505 unsigned int cpu = i_mce.extcpu; 506 + struct mce_hw_err err; 507 + u64 mcg_status = 0; 507 508 u8 b = i_mce.bank; 508 509 509 510 i_mce.tsc = rdtsc_ordered(); ··· 518 517 i_mce.status |= MCI_STATUS_SYNDV; 519 518 520 519 if (inj_type == SW_INJ) { 521 - mce_log(&i_mce); 520 + err.m = i_mce; 521 + mce_log(&err); 522 522 return; 523 523 } 524 524
+1 -1
arch/x86/kernel/cpu/mce/intel.c
··· 94 94 if (!boot_cpu_has(X86_FEATURE_APIC) || lapic_get_maxlvt() < 6) 95 95 return 0; 96 96 rdmsrl(MSR_IA32_MCG_CAP, cap); 97 - *banks = min_t(unsigned, MAX_NR_BANKS, cap & 0xff); 97 + *banks = min_t(unsigned, MAX_NR_BANKS, cap & MCG_BANKCNT_MASK); 98 98 return !!(cap & MCG_CMCI_P); 99 99 } 100 100
+2 -2
arch/x86/kernel/cpu/mce/internal.h
··· 26 26 27 27 struct mce_evt_llist { 28 28 struct llist_node llnode; 29 - struct mce mce; 29 + struct mce_hw_err err; 30 30 }; 31 31 32 32 void mce_gen_pool_process(struct work_struct *__unused); 33 33 bool mce_gen_pool_empty(void); 34 - int mce_gen_pool_add(struct mce *mce); 34 + int mce_gen_pool_add(struct mce_hw_err *err); 35 35 int mce_gen_pool_init(void); 36 36 struct llist_node *mce_gen_pool_prepare_records(void); 37 37
+16 -6
drivers/edac/mce_amd.c
··· 793 793 amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data) 794 794 { 795 795 struct mce *m = (struct mce *)data; 796 + struct mce_hw_err *err = to_mce_hw_err(m); 796 797 unsigned int fam = x86_family(m->cpuid); 798 + u32 mca_config_lo = 0, dummy; 797 799 int ecc; 798 800 799 801 if (m->kflags & MCE_HANDLED_CEC) ··· 815 813 ((m->status & MCI_STATUS_PCC) ? "PCC" : "-")); 816 814 817 815 if (boot_cpu_has(X86_FEATURE_SMCA)) { 818 - u32 low, high; 819 - u32 addr = MSR_AMD64_SMCA_MCx_CONFIG(m->bank); 816 + rdmsr_safe(MSR_AMD64_SMCA_MCx_CONFIG(m->bank), &mca_config_lo, &dummy); 820 817 821 - if (!rdmsr_safe(addr, &low, &high) && 822 - (low & MCI_CONFIG_MCAX)) 818 + if (mca_config_lo & MCI_CONFIG_MCAX) 823 819 pr_cont("|%s", ((m->status & MCI_STATUS_TCC) ? "TCC" : "-")); 824 820 825 821 pr_cont("|%s", ((m->status & MCI_STATUS_SYNDV) ? "SyndV" : "-")); ··· 850 850 if (boot_cpu_has(X86_FEATURE_SMCA)) { 851 851 pr_emerg(HW_ERR "IPID: 0x%016llx", m->ipid); 852 852 853 - if (m->status & MCI_STATUS_SYNDV) 854 - pr_cont(", Syndrome: 0x%016llx", m->synd); 853 + if (m->status & MCI_STATUS_SYNDV) { 854 + pr_cont(", Syndrome: 0x%016llx\n", m->synd); 855 + if (mca_config_lo & MCI_CONFIG_FRUTEXT) { 856 + char frutext[17]; 857 + 858 + frutext[16] = '\0'; 859 + memcpy(&frutext[0], &err->vendor.amd.synd1, 8); 860 + memcpy(&frutext[8], &err->vendor.amd.synd2, 8); 861 + 862 + pr_emerg(HW_ERR "FRU Text: %s", frutext); 863 + } 864 + } 855 865 856 866 pr_cont("\n"); 857 867
+26 -23
include/trace/events/mce.h
··· 19 19 20 20 TRACE_EVENT(mce_record, 21 21 22 - TP_PROTO(struct mce *m), 22 + TP_PROTO(struct mce_hw_err *err), 23 23 24 - TP_ARGS(m), 24 + TP_ARGS(err), 25 25 26 26 TP_STRUCT__entry( 27 27 __field( u64, mcgcap ) ··· 43 43 __field( u8, bank ) 44 44 __field( u8, cpuvendor ) 45 45 __field( u32, microcode ) 46 + __dynamic_array(u8, v_data, sizeof(err->vendor)) 46 47 ), 47 48 48 49 TP_fast_assign( 49 - __entry->mcgcap = m->mcgcap; 50 - __entry->mcgstatus = m->mcgstatus; 51 - __entry->status = m->status; 52 - __entry->addr = m->addr; 53 - __entry->misc = m->misc; 54 - __entry->synd = m->synd; 55 - __entry->ipid = m->ipid; 56 - __entry->ip = m->ip; 57 - __entry->tsc = m->tsc; 58 - __entry->ppin = m->ppin; 59 - __entry->walltime = m->time; 60 - __entry->cpu = m->extcpu; 61 - __entry->cpuid = m->cpuid; 62 - __entry->apicid = m->apicid; 63 - __entry->socketid = m->socketid; 64 - __entry->cs = m->cs; 65 - __entry->bank = m->bank; 66 - __entry->cpuvendor = m->cpuvendor; 67 - __entry->microcode = m->microcode; 50 + __entry->mcgcap = err->m.mcgcap; 51 + __entry->mcgstatus = err->m.mcgstatus; 52 + __entry->status = err->m.status; 53 + __entry->addr = err->m.addr; 54 + __entry->misc = err->m.misc; 55 + __entry->synd = err->m.synd; 56 + __entry->ipid = err->m.ipid; 57 + __entry->ip = err->m.ip; 58 + __entry->tsc = err->m.tsc; 59 + __entry->ppin = err->m.ppin; 60 + __entry->walltime = err->m.time; 61 + __entry->cpu = err->m.extcpu; 62 + __entry->cpuid = err->m.cpuid; 63 + __entry->apicid = err->m.apicid; 64 + __entry->socketid = err->m.socketid; 65 + __entry->cs = err->m.cs; 66 + __entry->bank = err->m.bank; 67 + __entry->cpuvendor = err->m.cpuvendor; 68 + __entry->microcode = err->m.microcode; 69 + memcpy(__get_dynamic_array(v_data), &err->vendor, sizeof(err->vendor)); 68 70 ), 69 71 70 - TP_printk("CPU: %d, MCGc/s: %llx/%llx, MC%d: %016Lx, IPID: %016Lx, ADDR: %016Lx, MISC: %016Lx, SYND: %016Lx, RIP: %02x:<%016Lx>, TSC: %llx, PPIN: %llx, vendor: %u, CPUID: %x, time: %llu, socket: %u, APIC: %x, microcode: %x", 72 + TP_printk("CPU: %d, MCGc/s: %llx/%llx, MC%d: %016llx, IPID: %016llx, ADDR: %016llx, MISC: %016llx, SYND: %016llx, RIP: %02x:<%016llx>, TSC: %llx, PPIN: %llx, vendor: %u, CPUID: %x, time: %llu, socket: %u, APIC: %x, microcode: %x, vendor data: %s", 71 73 __entry->cpu, 72 74 __entry->mcgcap, __entry->mcgstatus, 73 75 __entry->bank, __entry->status, ··· 85 83 __entry->walltime, 86 84 __entry->socketid, 87 85 __entry->apicid, 88 - __entry->microcode) 86 + __entry->microcode, 87 + __print_dynamic_array(v_data, sizeof(u8))) 89 88 ); 90 89 91 90 #endif /* _TRACE_MCE_H */
+8
include/trace/stages/stage3_trace_output.h
··· 119 119 trace_print_array_seq(p, array, count, el_size); \ 120 120 }) 121 121 122 + #undef __print_dynamic_array 123 + #define __print_dynamic_array(array, el_size) \ 124 + ({ \ 125 + __print_array(__get_dynamic_array(array), \ 126 + __get_dynamic_array_len(array) / (el_size), \ 127 + (el_size)); \ 128 + }) 129 + 122 130 #undef __print_hex_dump 123 131 #define __print_hex_dump(prefix_str, prefix_type, \ 124 132 rowsize, groupsize, buf, len, ascii) \
+1
include/trace/stages/stage7_class_define.h
··· 22 22 #undef __get_rel_cpumask 23 23 #undef __get_rel_sockaddr 24 24 #undef __print_array 25 + #undef __print_dynamic_array 25 26 #undef __print_hex_dump 26 27 #undef __get_buf 27 28
+6 -1
samples/trace_events/trace-events-sample.h
··· 319 319 __assign_cpumask(cpum, cpumask_bits(mask)); 320 320 ), 321 321 322 - TP_printk("foo %s %d %s %s %s %s %s (%s) (%s) %s", __entry->foo, __entry->bar, 322 + TP_printk("foo %s %d %s %s %s %s %s %s (%s) (%s) %s", __entry->foo, __entry->bar, 323 323 324 324 /* 325 325 * Notice here the use of some helper functions. This includes: ··· 363 363 __print_array(__get_dynamic_array(list), 364 364 __get_dynamic_array_len(list) / sizeof(int), 365 365 sizeof(int)), 366 + 367 + /* A shortcut is to use __print_dynamic_array for dynamic arrays */ 368 + 369 + __print_dynamic_array(list, sizeof(int)), 370 + 366 371 __get_str(str), __get_str(lstr), 367 372 __get_bitmask(cpus), __get_cpumask(cpum), 368 373 __get_str(vstr))