aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2014-07-14 12:26:47 -0400
committerH. Peter Anvin <hpa@zytor.com>2014-07-14 12:27:25 -0400
commitcbd4ebcba16c31abc341e1810e6e0fb4c35117b3 (patch)
tree49a3b54c709d11efbee631a85cca5fb550515005
parent27c934158c5be0bebfb2970da521b9d9efc0058b (diff)
parent7c76bb5f7a3d052339b873374333dd0dcc35ce28 (diff)
Merge tag 'please-pull-extlog-trace' into x86/ras
Report extended error information ("extlog") using a trace/event. Provide a mechanism for a smart daemon collecting this information to tell the kernel to skip logging corrected errors to the console. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/acpi/Kconfig4
-rw-r--r--drivers/acpi/acpi_extlog.c46
-rw-r--r--drivers/edac/Kconfig1
-rw-r--r--drivers/edac/edac_mc.c3
-rw-r--r--drivers/firmware/efi/cper.c192
-rw-r--r--drivers/pci/pcie/aer/Kconfig1
-rw-r--r--drivers/pci/pcie/aer/aerdrv_errprint.c4
-rw-r--r--drivers/ras/Kconfig2
-rw-r--r--drivers/ras/Makefile1
-rw-r--r--drivers/ras/debugfs.c56
-rw-r--r--drivers/ras/ras.c29
-rw-r--r--include/linux/cper.h32
-rw-r--r--include/linux/ras.h14
-rw-r--r--include/ras/ras_event.h128
-rw-r--r--include/trace/events/ras.h77
-rw-r--r--include/trace/ftrace.h33
-rw-r--r--include/trace/syscall.h15
-rw-r--r--kernel/fork.c2
-rw-r--r--kernel/tracepoint.c26
-rw-r--r--samples/trace_events/trace-events-sample.h3
22 files changed, 506 insertions, 166 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 0e87a34b6472..4e6e66c3c8d6 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -176,4 +176,6 @@ source "drivers/powercap/Kconfig"
176 176
177source "drivers/mcb/Kconfig" 177source "drivers/mcb/Kconfig"
178 178
179source "drivers/ras/Kconfig"
180
179endmenu 181endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index f98b50d8251d..65c32b1cea3d 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -158,3 +158,4 @@ obj-$(CONFIG_NTB) += ntb/
158obj-$(CONFIG_FMC) += fmc/ 158obj-$(CONFIG_FMC) += fmc/
159obj-$(CONFIG_POWERCAP) += powercap/ 159obj-$(CONFIG_POWERCAP) += powercap/
160obj-$(CONFIG_MCB) += mcb/ 160obj-$(CONFIG_MCB) += mcb/
161obj-$(CONFIG_RAS) += ras/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index a34a22841002..206942b8d105 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -370,6 +370,7 @@ config ACPI_EXTLOG
370 tristate "Extended Error Log support" 370 tristate "Extended Error Log support"
371 depends on X86_MCE && X86_LOCAL_APIC 371 depends on X86_MCE && X86_LOCAL_APIC
372 select UEFI_CPER 372 select UEFI_CPER
373 select RAS
373 default n 374 default n
374 help 375 help
375 Certain usages such as Predictive Failure Analysis (PFA) require 376 Certain usages such as Predictive Failure Analysis (PFA) require
@@ -384,6 +385,7 @@ config ACPI_EXTLOG
384 385
385 Enhanced MCA Logging allows firmware to provide additional error 386 Enhanced MCA Logging allows firmware to provide additional error
386 information to system software, synchronous with MCE or CMCI. This 387 information to system software, synchronous with MCE or CMCI. This
387 driver adds support for that functionality. 388 driver adds support for that functionality with corresponding
389 tracepoint which carries that information to userspace.
388 390
389endif # ACPI 391endif # ACPI
diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c
index 185334114d71..0ad6f389d922 100644
--- a/drivers/acpi/acpi_extlog.c
+++ b/drivers/acpi/acpi_extlog.c
@@ -12,10 +12,12 @@
12#include <linux/cper.h> 12#include <linux/cper.h>
13#include <linux/ratelimit.h> 13#include <linux/ratelimit.h>
14#include <linux/edac.h> 14#include <linux/edac.h>
15#include <linux/ras.h>
15#include <asm/cpu.h> 16#include <asm/cpu.h>
16#include <asm/mce.h> 17#include <asm/mce.h>
17 18
18#include "apei/apei-internal.h" 19#include "apei/apei-internal.h"
20#include <ras/ras_event.h>
19 21
20#define EXT_ELOG_ENTRY_MASK GENMASK_ULL(51, 0) /* elog entry address mask */ 22#define EXT_ELOG_ENTRY_MASK GENMASK_ULL(51, 0) /* elog entry address mask */
21 23
@@ -137,8 +139,12 @@ static int extlog_print(struct notifier_block *nb, unsigned long val,
137 struct mce *mce = (struct mce *)data; 139 struct mce *mce = (struct mce *)data;
138 int bank = mce->bank; 140 int bank = mce->bank;
139 int cpu = mce->extcpu; 141 int cpu = mce->extcpu;
140 struct acpi_generic_status *estatus; 142 struct acpi_generic_status *estatus, *tmp;
141 int rc; 143 struct acpi_generic_data *gdata;
144 const uuid_le *fru_id = &NULL_UUID_LE;
145 char *fru_text = "";
146 uuid_le *sec_type;
147 static u32 err_seq;
142 148
143 estatus = extlog_elog_entry_check(cpu, bank); 149 estatus = extlog_elog_entry_check(cpu, bank);
144 if (estatus == NULL) 150 if (estatus == NULL)
@@ -148,8 +154,29 @@ static int extlog_print(struct notifier_block *nb, unsigned long val,
148 /* clear record status to enable BIOS to update it again */ 154 /* clear record status to enable BIOS to update it again */
149 estatus->block_status = 0; 155 estatus->block_status = 0;
150 156
151 rc = print_extlog_rcd(NULL, (struct acpi_generic_status *)elog_buf, cpu); 157 tmp = (struct acpi_generic_status *)elog_buf;
158
159 if (!ras_userspace_consumers()) {
160 print_extlog_rcd(NULL, tmp, cpu);
161 goto out;
162 }
163
164 /* log event via trace */
165 err_seq++;
166 gdata = (struct acpi_generic_data *)(tmp + 1);
167 if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID)
168 fru_id = (uuid_le *)gdata->fru_id;
169 if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT)
170 fru_text = gdata->fru_text;
171 sec_type = (uuid_le *)gdata->section_type;
172 if (!uuid_le_cmp(*sec_type, CPER_SEC_PLATFORM_MEM)) {
173 struct cper_sec_mem_err *mem = (void *)(gdata + 1);
174 if (gdata->error_data_length >= sizeof(*mem))
175 trace_extlog_mem_event(mem, err_seq, fru_id, fru_text,
176 (u8)gdata->error_severity);
177 }
152 178
179out:
153 return NOTIFY_STOP; 180 return NOTIFY_STOP;
154} 181}
155 182
@@ -196,19 +223,16 @@ static int __init extlog_init(void)
196 u64 cap; 223 u64 cap;
197 int rc; 224 int rc;
198 225
226 rdmsrl(MSR_IA32_MCG_CAP, cap);
227
228 if (!(cap & MCG_ELOG_P) || !extlog_get_l1addr())
229 return -ENODEV;
230
199 if (get_edac_report_status() == EDAC_REPORTING_FORCE) { 231 if (get_edac_report_status() == EDAC_REPORTING_FORCE) {
200 pr_warn("Not loading eMCA, error reporting force-enabled through EDAC.\n"); 232 pr_warn("Not loading eMCA, error reporting force-enabled through EDAC.\n");
201 return -EPERM; 233 return -EPERM;
202 } 234 }
203 235
204 rc = -ENODEV;
205 rdmsrl(MSR_IA32_MCG_CAP, cap);
206 if (!(cap & MCG_ELOG_P))
207 return rc;
208
209 if (!extlog_get_l1addr())
210 return rc;
211
212 rc = -EINVAL; 236 rc = -EINVAL;
213 /* get L1 header to fetch necessary information */ 237 /* get L1 header to fetch necessary information */
214 l1_hdr_size = sizeof(struct extlog_l1_head); 238 l1_hdr_size = sizeof(struct extlog_l1_head);
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 878f09005fad..d3c0465ba456 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -72,6 +72,7 @@ config EDAC_MCE_INJ
72 72
73config EDAC_MM_EDAC 73config EDAC_MM_EDAC
74 tristate "Main Memory EDAC (Error Detection And Correction) reporting" 74 tristate "Main Memory EDAC (Error Detection And Correction) reporting"
75 select RAS
75 help 76 help
76 Some systems are able to detect and correct errors in main 77 Some systems are able to detect and correct errors in main
77 memory. EDAC can report statistics on memory error 78 memory. EDAC can report statistics on memory error
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 2c694b5297cc..9f134823fa75 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -33,9 +33,6 @@
33#include <asm/edac.h> 33#include <asm/edac.h>
34#include "edac_core.h" 34#include "edac_core.h"
35#include "edac_module.h" 35#include "edac_module.h"
36
37#define CREATE_TRACE_POINTS
38#define TRACE_INCLUDE_PATH ../../include/ras
39#include <ras/ras_event.h> 36#include <ras/ras_event.h>
40 37
41/* lock to memory controller's control array */ 38/* lock to memory controller's control array */
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index 1491dd4f08f9..437e6fd47311 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -34,6 +34,9 @@
34#include <linux/aer.h> 34#include <linux/aer.h>
35 35
36#define INDENT_SP " " 36#define INDENT_SP " "
37
38static char rcd_decode_str[CPER_REC_LEN];
39
37/* 40/*
38 * CPER record ID need to be unique even after reboot, because record 41 * CPER record ID need to be unique even after reboot, because record
39 * ID is used as index for ERST storage, while CPER records from 42 * ID is used as index for ERST storage, while CPER records from
@@ -50,18 +53,19 @@ u64 cper_next_record_id(void)
50} 53}
51EXPORT_SYMBOL_GPL(cper_next_record_id); 54EXPORT_SYMBOL_GPL(cper_next_record_id);
52 55
53static const char *cper_severity_strs[] = { 56static const char * const severity_strs[] = {
54 "recoverable", 57 "recoverable",
55 "fatal", 58 "fatal",
56 "corrected", 59 "corrected",
57 "info", 60 "info",
58}; 61};
59 62
60static const char *cper_severity_str(unsigned int severity) 63const char *cper_severity_str(unsigned int severity)
61{ 64{
62 return severity < ARRAY_SIZE(cper_severity_strs) ? 65 return severity < ARRAY_SIZE(severity_strs) ?
63 cper_severity_strs[severity] : "unknown"; 66 severity_strs[severity] : "unknown";
64} 67}
68EXPORT_SYMBOL_GPL(cper_severity_str);
65 69
66/* 70/*
67 * cper_print_bits - print strings for set bits 71 * cper_print_bits - print strings for set bits
@@ -100,32 +104,32 @@ void cper_print_bits(const char *pfx, unsigned int bits,
100 printk("%s\n", buf); 104 printk("%s\n", buf);
101} 105}
102 106
103static const char * const cper_proc_type_strs[] = { 107static const char * const proc_type_strs[] = {
104 "IA32/X64", 108 "IA32/X64",
105 "IA64", 109 "IA64",
106}; 110};
107 111
108static const char * const cper_proc_isa_strs[] = { 112static const char * const proc_isa_strs[] = {
109 "IA32", 113 "IA32",
110 "IA64", 114 "IA64",
111 "X64", 115 "X64",
112}; 116};
113 117
114static const char * const cper_proc_error_type_strs[] = { 118static const char * const proc_error_type_strs[] = {
115 "cache error", 119 "cache error",
116 "TLB error", 120 "TLB error",
117 "bus error", 121 "bus error",
118 "micro-architectural error", 122 "micro-architectural error",
119}; 123};
120 124
121static const char * const cper_proc_op_strs[] = { 125static const char * const proc_op_strs[] = {
122 "unknown or generic", 126 "unknown or generic",
123 "data read", 127 "data read",
124 "data write", 128 "data write",
125 "instruction execution", 129 "instruction execution",
126}; 130};
127 131
128static const char * const cper_proc_flag_strs[] = { 132static const char * const proc_flag_strs[] = {
129 "restartable", 133 "restartable",
130 "precise IP", 134 "precise IP",
131 "overflow", 135 "overflow",
@@ -137,26 +141,26 @@ static void cper_print_proc_generic(const char *pfx,
137{ 141{
138 if (proc->validation_bits & CPER_PROC_VALID_TYPE) 142 if (proc->validation_bits & CPER_PROC_VALID_TYPE)
139 printk("%s""processor_type: %d, %s\n", pfx, proc->proc_type, 143 printk("%s""processor_type: %d, %s\n", pfx, proc->proc_type,
140 proc->proc_type < ARRAY_SIZE(cper_proc_type_strs) ? 144 proc->proc_type < ARRAY_SIZE(proc_type_strs) ?
141 cper_proc_type_strs[proc->proc_type] : "unknown"); 145 proc_type_strs[proc->proc_type] : "unknown");
142 if (proc->validation_bits & CPER_PROC_VALID_ISA) 146 if (proc->validation_bits & CPER_PROC_VALID_ISA)
143 printk("%s""processor_isa: %d, %s\n", pfx, proc->proc_isa, 147 printk("%s""processor_isa: %d, %s\n", pfx, proc->proc_isa,
144 proc->proc_isa < ARRAY_SIZE(cper_proc_isa_strs) ? 148 proc->proc_isa < ARRAY_SIZE(proc_isa_strs) ?
145 cper_proc_isa_strs[proc->proc_isa] : "unknown"); 149 proc_isa_strs[proc->proc_isa] : "unknown");
146 if (proc->validation_bits & CPER_PROC_VALID_ERROR_TYPE) { 150 if (proc->validation_bits & CPER_PROC_VALID_ERROR_TYPE) {
147 printk("%s""error_type: 0x%02x\n", pfx, proc->proc_error_type); 151 printk("%s""error_type: 0x%02x\n", pfx, proc->proc_error_type);
148 cper_print_bits(pfx, proc->proc_error_type, 152 cper_print_bits(pfx, proc->proc_error_type,
149 cper_proc_error_type_strs, 153 proc_error_type_strs,
150 ARRAY_SIZE(cper_proc_error_type_strs)); 154 ARRAY_SIZE(proc_error_type_strs));
151 } 155 }
152 if (proc->validation_bits & CPER_PROC_VALID_OPERATION) 156 if (proc->validation_bits & CPER_PROC_VALID_OPERATION)
153 printk("%s""operation: %d, %s\n", pfx, proc->operation, 157 printk("%s""operation: %d, %s\n", pfx, proc->operation,
154 proc->operation < ARRAY_SIZE(cper_proc_op_strs) ? 158 proc->operation < ARRAY_SIZE(proc_op_strs) ?
155 cper_proc_op_strs[proc->operation] : "unknown"); 159 proc_op_strs[proc->operation] : "unknown");
156 if (proc->validation_bits & CPER_PROC_VALID_FLAGS) { 160 if (proc->validation_bits & CPER_PROC_VALID_FLAGS) {
157 printk("%s""flags: 0x%02x\n", pfx, proc->flags); 161 printk("%s""flags: 0x%02x\n", pfx, proc->flags);
158 cper_print_bits(pfx, proc->flags, cper_proc_flag_strs, 162 cper_print_bits(pfx, proc->flags, proc_flag_strs,
159 ARRAY_SIZE(cper_proc_flag_strs)); 163 ARRAY_SIZE(proc_flag_strs));
160 } 164 }
161 if (proc->validation_bits & CPER_PROC_VALID_LEVEL) 165 if (proc->validation_bits & CPER_PROC_VALID_LEVEL)
162 printk("%s""level: %d\n", pfx, proc->level); 166 printk("%s""level: %d\n", pfx, proc->level);
@@ -177,7 +181,7 @@ static void cper_print_proc_generic(const char *pfx,
177 printk("%s""IP: 0x%016llx\n", pfx, proc->ip); 181 printk("%s""IP: 0x%016llx\n", pfx, proc->ip);
178} 182}
179 183
180static const char *cper_mem_err_type_strs[] = { 184static const char * const mem_err_type_strs[] = {
181 "unknown", 185 "unknown",
182 "no error", 186 "no error",
183 "single-bit ECC", 187 "single-bit ECC",
@@ -196,58 +200,136 @@ static const char *cper_mem_err_type_strs[] = {
196 "physical memory map-out event", 200 "physical memory map-out event",
197}; 201};
198 202
199static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem) 203const char *cper_mem_err_type_str(unsigned int etype)
200{ 204{
201 if (mem->validation_bits & CPER_MEM_VALID_ERROR_STATUS) 205 return etype < ARRAY_SIZE(mem_err_type_strs) ?
202 printk("%s""error_status: 0x%016llx\n", pfx, mem->error_status); 206 mem_err_type_strs[etype] : "unknown";
203 if (mem->validation_bits & CPER_MEM_VALID_PA) 207}
204 printk("%s""physical_address: 0x%016llx\n", 208EXPORT_SYMBOL_GPL(cper_mem_err_type_str);
205 pfx, mem->physical_addr); 209
206 if (mem->validation_bits & CPER_MEM_VALID_PA_MASK) 210static int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg)
207 printk("%s""physical_address_mask: 0x%016llx\n", 211{
208 pfx, mem->physical_addr_mask); 212 u32 len, n;
213
214 if (!msg)
215 return 0;
216
217 n = 0;
218 len = CPER_REC_LEN - 1;
209 if (mem->validation_bits & CPER_MEM_VALID_NODE) 219 if (mem->validation_bits & CPER_MEM_VALID_NODE)
210 pr_debug("node: %d\n", mem->node); 220 n += scnprintf(msg + n, len - n, "node: %d ", mem->node);
211 if (mem->validation_bits & CPER_MEM_VALID_CARD) 221 if (mem->validation_bits & CPER_MEM_VALID_CARD)
212 pr_debug("card: %d\n", mem->card); 222 n += scnprintf(msg + n, len - n, "card: %d ", mem->card);
213 if (mem->validation_bits & CPER_MEM_VALID_MODULE) 223 if (mem->validation_bits & CPER_MEM_VALID_MODULE)
214 pr_debug("module: %d\n", mem->module); 224 n += scnprintf(msg + n, len - n, "module: %d ", mem->module);
215 if (mem->validation_bits & CPER_MEM_VALID_RANK_NUMBER) 225 if (mem->validation_bits & CPER_MEM_VALID_RANK_NUMBER)
216 pr_debug("rank: %d\n", mem->rank); 226 n += scnprintf(msg + n, len - n, "rank: %d ", mem->rank);
217 if (mem->validation_bits & CPER_MEM_VALID_BANK) 227 if (mem->validation_bits & CPER_MEM_VALID_BANK)
218 pr_debug("bank: %d\n", mem->bank); 228 n += scnprintf(msg + n, len - n, "bank: %d ", mem->bank);
219 if (mem->validation_bits & CPER_MEM_VALID_DEVICE) 229 if (mem->validation_bits & CPER_MEM_VALID_DEVICE)
220 pr_debug("device: %d\n", mem->device); 230 n += scnprintf(msg + n, len - n, "device: %d ", mem->device);
221 if (mem->validation_bits & CPER_MEM_VALID_ROW) 231 if (mem->validation_bits & CPER_MEM_VALID_ROW)
222 pr_debug("row: %d\n", mem->row); 232 n += scnprintf(msg + n, len - n, "row: %d ", mem->row);
223 if (mem->validation_bits & CPER_MEM_VALID_COLUMN) 233 if (mem->validation_bits & CPER_MEM_VALID_COLUMN)
224 pr_debug("column: %d\n", mem->column); 234 n += scnprintf(msg + n, len - n, "column: %d ", mem->column);
225 if (mem->validation_bits & CPER_MEM_VALID_BIT_POSITION) 235 if (mem->validation_bits & CPER_MEM_VALID_BIT_POSITION)
226 pr_debug("bit_position: %d\n", mem->bit_pos); 236 n += scnprintf(msg + n, len - n, "bit_position: %d ",
237 mem->bit_pos);
227 if (mem->validation_bits & CPER_MEM_VALID_REQUESTOR_ID) 238 if (mem->validation_bits & CPER_MEM_VALID_REQUESTOR_ID)
228 pr_debug("requestor_id: 0x%016llx\n", mem->requestor_id); 239 n += scnprintf(msg + n, len - n, "requestor_id: 0x%016llx ",
240 mem->requestor_id);
229 if (mem->validation_bits & CPER_MEM_VALID_RESPONDER_ID) 241 if (mem->validation_bits & CPER_MEM_VALID_RESPONDER_ID)
230 pr_debug("responder_id: 0x%016llx\n", mem->responder_id); 242 n += scnprintf(msg + n, len - n, "responder_id: 0x%016llx ",
243 mem->responder_id);
231 if (mem->validation_bits & CPER_MEM_VALID_TARGET_ID) 244 if (mem->validation_bits & CPER_MEM_VALID_TARGET_ID)
232 pr_debug("target_id: 0x%016llx\n", mem->target_id); 245 scnprintf(msg + n, len - n, "target_id: 0x%016llx ",
246 mem->target_id);
247
248 msg[n] = '\0';
249 return n;
250}
251
252static int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg)
253{
254 u32 len, n;
255 const char *bank = NULL, *device = NULL;
256
257 if (!msg || !(mem->validation_bits & CPER_MEM_VALID_MODULE_HANDLE))
258 return 0;
259
260 n = 0;
261 len = CPER_REC_LEN - 1;
262 dmi_memdev_name(mem->mem_dev_handle, &bank, &device);
263 if (bank && device)
264 n = snprintf(msg, len, "DIMM location: %s %s ", bank, device);
265 else
266 n = snprintf(msg, len,
267 "DIMM location: not present. DMI handle: 0x%.4x ",
268 mem->mem_dev_handle);
269
270 msg[n] = '\0';
271 return n;
272}
273
274void cper_mem_err_pack(const struct cper_sec_mem_err *mem,
275 struct cper_mem_err_compact *cmem)
276{
277 cmem->validation_bits = mem->validation_bits;
278 cmem->node = mem->node;
279 cmem->card = mem->card;
280 cmem->module = mem->module;
281 cmem->bank = mem->bank;
282 cmem->device = mem->device;
283 cmem->row = mem->row;
284 cmem->column = mem->column;
285 cmem->bit_pos = mem->bit_pos;
286 cmem->requestor_id = mem->requestor_id;
287 cmem->responder_id = mem->responder_id;
288 cmem->target_id = mem->target_id;
289 cmem->rank = mem->rank;
290 cmem->mem_array_handle = mem->mem_array_handle;
291 cmem->mem_dev_handle = mem->mem_dev_handle;
292}
293
294const char *cper_mem_err_unpack(struct trace_seq *p,
295 struct cper_mem_err_compact *cmem)
296{
297 const char *ret = p->buffer + p->len;
298
299 if (cper_mem_err_location(cmem, rcd_decode_str))
300 trace_seq_printf(p, "%s", rcd_decode_str);
301 if (cper_dimm_err_location(cmem, rcd_decode_str))
302 trace_seq_printf(p, "%s", rcd_decode_str);
303 trace_seq_putc(p, '\0');
304
305 return ret;
306}
307
308static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem)
309{
310 struct cper_mem_err_compact cmem;
311
312 if (mem->validation_bits & CPER_MEM_VALID_ERROR_STATUS)
313 printk("%s""error_status: 0x%016llx\n", pfx, mem->error_status);
314 if (mem->validation_bits & CPER_MEM_VALID_PA)
315 printk("%s""physical_address: 0x%016llx\n",
316 pfx, mem->physical_addr);
317 if (mem->validation_bits & CPER_MEM_VALID_PA_MASK)
318 printk("%s""physical_address_mask: 0x%016llx\n",
319 pfx, mem->physical_addr_mask);
320 cper_mem_err_pack(mem, &cmem);
321 if (cper_mem_err_location(&cmem, rcd_decode_str))
322 printk("%s%s\n", pfx, rcd_decode_str);
233 if (mem->validation_bits & CPER_MEM_VALID_ERROR_TYPE) { 323 if (mem->validation_bits & CPER_MEM_VALID_ERROR_TYPE) {
234 u8 etype = mem->error_type; 324 u8 etype = mem->error_type;
235 printk("%s""error_type: %d, %s\n", pfx, etype, 325 printk("%s""error_type: %d, %s\n", pfx, etype,
236 etype < ARRAY_SIZE(cper_mem_err_type_strs) ? 326 cper_mem_err_type_str(etype));
237 cper_mem_err_type_strs[etype] : "unknown");
238 }
239 if (mem->validation_bits & CPER_MEM_VALID_MODULE_HANDLE) {
240 const char *bank = NULL, *device = NULL;
241 dmi_memdev_name(mem->mem_dev_handle, &bank, &device);
242 if (bank != NULL && device != NULL)
243 printk("%s""DIMM location: %s %s", pfx, bank, device);
244 else
245 printk("%s""DIMM DMI handle: 0x%.4x",
246 pfx, mem->mem_dev_handle);
247 } 327 }
328 if (cper_dimm_err_location(&cmem, rcd_decode_str))
329 printk("%s%s\n", pfx, rcd_decode_str);
248} 330}
249 331
250static const char *cper_pcie_port_type_strs[] = { 332static const char * const pcie_port_type_strs[] = {
251 "PCIe end point", 333 "PCIe end point",
252 "legacy PCI end point", 334 "legacy PCI end point",
253 "unknown", 335 "unknown",
@@ -266,8 +348,8 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
266{ 348{
267 if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE) 349 if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE)
268 printk("%s""port_type: %d, %s\n", pfx, pcie->port_type, 350 printk("%s""port_type: %d, %s\n", pfx, pcie->port_type,
269 pcie->port_type < ARRAY_SIZE(cper_pcie_port_type_strs) ? 351 pcie->port_type < ARRAY_SIZE(pcie_port_type_strs) ?
270 cper_pcie_port_type_strs[pcie->port_type] : "unknown"); 352 pcie_port_type_strs[pcie->port_type] : "unknown");
271 if (pcie->validation_bits & CPER_PCIE_VALID_VERSION) 353 if (pcie->validation_bits & CPER_PCIE_VALID_VERSION)
272 printk("%s""version: %d.%d\n", pfx, 354 printk("%s""version: %d.%d\n", pfx,
273 pcie->version.major, pcie->version.minor); 355 pcie->version.major, pcie->version.minor);
diff --git a/drivers/pci/pcie/aer/Kconfig b/drivers/pci/pcie/aer/Kconfig
index 50e94e02378a..389440228c1d 100644
--- a/drivers/pci/pcie/aer/Kconfig
+++ b/drivers/pci/pcie/aer/Kconfig
@@ -5,6 +5,7 @@
5config PCIEAER 5config PCIEAER
6 boolean "Root Port Advanced Error Reporting support" 6 boolean "Root Port Advanced Error Reporting support"
7 depends on PCIEPORTBUS 7 depends on PCIEPORTBUS
8 select RAS
8 default y 9 default y
9 help 10 help
10 This enables PCI Express Root Port Advanced Error Reporting 11 This enables PCI Express Root Port Advanced Error Reporting
diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c
index 36ed31b52198..35d06e177917 100644
--- a/drivers/pci/pcie/aer/aerdrv_errprint.c
+++ b/drivers/pci/pcie/aer/aerdrv_errprint.c
@@ -22,9 +22,7 @@
22#include <linux/cper.h> 22#include <linux/cper.h>
23 23
24#include "aerdrv.h" 24#include "aerdrv.h"
25 25#include <ras/ras_event.h>
26#define CREATE_TRACE_POINTS
27#include <trace/events/ras.h>
28 26
29#define AER_AGENT_RECEIVER 0 27#define AER_AGENT_RECEIVER 0
30#define AER_AGENT_REQUESTER 1 28#define AER_AGENT_REQUESTER 1
diff --git a/drivers/ras/Kconfig b/drivers/ras/Kconfig
new file mode 100644
index 000000000000..f9da613052c2
--- /dev/null
+++ b/drivers/ras/Kconfig
@@ -0,0 +1,2 @@
1config RAS
2 bool
diff --git a/drivers/ras/Makefile b/drivers/ras/Makefile
new file mode 100644
index 000000000000..d7f73341ced3
--- /dev/null
+++ b/drivers/ras/Makefile
@@ -0,0 +1 @@
obj-$(CONFIG_RAS) += ras.o debugfs.o
diff --git a/drivers/ras/debugfs.c b/drivers/ras/debugfs.c
new file mode 100644
index 000000000000..0322acf67ea5
--- /dev/null
+++ b/drivers/ras/debugfs.c
@@ -0,0 +1,56 @@
1#include <linux/debugfs.h>
2
3static struct dentry *ras_debugfs_dir;
4
5static atomic_t trace_count = ATOMIC_INIT(0);
6
7int ras_userspace_consumers(void)
8{
9 return atomic_read(&trace_count);
10}
11EXPORT_SYMBOL_GPL(ras_userspace_consumers);
12
13static int trace_show(struct seq_file *m, void *v)
14{
15 return atomic_read(&trace_count);
16}
17
18static int trace_open(struct inode *inode, struct file *file)
19{
20 atomic_inc(&trace_count);
21 return single_open(file, trace_show, NULL);
22}
23
24static int trace_release(struct inode *inode, struct file *file)
25{
26 atomic_dec(&trace_count);
27 return single_release(inode, file);
28}
29
30static const struct file_operations trace_fops = {
31 .open = trace_open,
32 .read = seq_read,
33 .llseek = seq_lseek,
34 .release = trace_release,
35};
36
37int __init ras_add_daemon_trace(void)
38{
39 struct dentry *fentry;
40
41 if (!ras_debugfs_dir)
42 return -ENOENT;
43
44 fentry = debugfs_create_file("daemon_active", S_IRUSR, ras_debugfs_dir,
45 NULL, &trace_fops);
46 if (!fentry)
47 return -ENODEV;
48
49 return 0;
50
51}
52
53void __init ras_debugfs_init(void)
54{
55 ras_debugfs_dir = debugfs_create_dir("ras", NULL);
56}
diff --git a/drivers/ras/ras.c b/drivers/ras/ras.c
new file mode 100644
index 000000000000..b67dd362b7b6
--- /dev/null
+++ b/drivers/ras/ras.c
@@ -0,0 +1,29 @@
1/*
2 * Copyright (C) 2014 Intel Corporation
3 *
4 * Authors:
5 * Chen, Gong <gong.chen@linux.intel.com>
6 */
7
8#include <linux/init.h>
9#include <linux/ras.h>
10
11#define CREATE_TRACE_POINTS
12#define TRACE_INCLUDE_PATH ../../include/ras
13#include <ras/ras_event.h>
14
15static int __init ras_init(void)
16{
17 int rc = 0;
18
19 ras_debugfs_init();
20 rc = ras_add_daemon_trace();
21
22 return rc;
23}
24subsys_initcall(ras_init);
25
26#if defined(CONFIG_ACPI_EXTLOG) || defined(CONFIG_ACPI_EXTLOG_MODULE)
27EXPORT_TRACEPOINT_SYMBOL_GPL(extlog_mem_event);
28#endif
29EXPORT_TRACEPOINT_SYMBOL_GPL(mc_event);
diff --git a/include/linux/cper.h b/include/linux/cper.h
index 2fc0ec3d89cc..76abba4b238e 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -22,6 +22,7 @@
22#define LINUX_CPER_H 22#define LINUX_CPER_H
23 23
24#include <linux/uuid.h> 24#include <linux/uuid.h>
25#include <linux/trace_seq.h>
25 26
26/* CPER record signature and the size */ 27/* CPER record signature and the size */
27#define CPER_SIG_RECORD "CPER" 28#define CPER_SIG_RECORD "CPER"
@@ -36,6 +37,13 @@
36#define CPER_RECORD_REV 0x0100 37#define CPER_RECORD_REV 0x0100
37 38
38/* 39/*
40 * CPER record length contains the CPER fields which are relevant for further
41 * handling of a memory error in userspace (we don't carry all the fields
42 * defined in the UEFI spec because some of them don't make any sense.)
43 * Currently, a length of 256 should be more than enough.
44 */
45#define CPER_REC_LEN 256
46/*
39 * Severity difinition for error_severity in struct cper_record_header 47 * Severity difinition for error_severity in struct cper_record_header
40 * and section_severity in struct cper_section_descriptor 48 * and section_severity in struct cper_section_descriptor
41 */ 49 */
@@ -356,6 +364,24 @@ struct cper_sec_mem_err {
356 __u16 mem_dev_handle; /* module handle in UEFI 2.4 */ 364 __u16 mem_dev_handle; /* module handle in UEFI 2.4 */
357}; 365};
358 366
367struct cper_mem_err_compact {
368 __u64 validation_bits;
369 __u16 node;
370 __u16 card;
371 __u16 module;
372 __u16 bank;
373 __u16 device;
374 __u16 row;
375 __u16 column;
376 __u16 bit_pos;
377 __u64 requestor_id;
378 __u64 responder_id;
379 __u64 target_id;
380 __u16 rank;
381 __u16 mem_array_handle;
382 __u16 mem_dev_handle;
383};
384
359struct cper_sec_pcie { 385struct cper_sec_pcie {
360 __u64 validation_bits; 386 __u64 validation_bits;
361 __u32 port_type; 387 __u32 port_type;
@@ -395,7 +421,13 @@ struct cper_sec_pcie {
395#pragma pack() 421#pragma pack()
396 422
397u64 cper_next_record_id(void); 423u64 cper_next_record_id(void);
424const char *cper_severity_str(unsigned int);
425const char *cper_mem_err_type_str(unsigned int);
398void cper_print_bits(const char *prefix, unsigned int bits, 426void cper_print_bits(const char *prefix, unsigned int bits,
399 const char * const strs[], unsigned int strs_size); 427 const char * const strs[], unsigned int strs_size);
428void cper_mem_err_pack(const struct cper_sec_mem_err *,
429 struct cper_mem_err_compact *);
430const char *cper_mem_err_unpack(struct trace_seq *,
431 struct cper_mem_err_compact *);
400 432
401#endif 433#endif
diff --git a/include/linux/ras.h b/include/linux/ras.h
new file mode 100644
index 000000000000..2aceeafd6fe5
--- /dev/null
+++ b/include/linux/ras.h
@@ -0,0 +1,14 @@
1#ifndef __RAS_H__
2#define __RAS_H__
3
4#ifdef CONFIG_DEBUG_FS
5int ras_userspace_consumers(void);
6void ras_debugfs_init(void);
7int ras_add_daemon_trace(void);
8#else
9static inline int ras_userspace_consumers(void) { return 0; }
10static inline void ras_debugfs_init(void) { return; }
11static inline int ras_add_daemon_trace(void) { return 0; }
12#endif
13
14#endif
diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
index 21cdb0b7b0fb..47da53c27ffa 100644
--- a/include/ras/ras_event.h
+++ b/include/ras/ras_event.h
@@ -8,6 +8,71 @@
8#include <linux/tracepoint.h> 8#include <linux/tracepoint.h>
9#include <linux/edac.h> 9#include <linux/edac.h>
10#include <linux/ktime.h> 10#include <linux/ktime.h>
11#include <linux/aer.h>
12#include <linux/cper.h>
13
14/*
15 * MCE Extended Error Log trace event
16 *
17 * These events are generated when hardware detects a corrected or
18 * uncorrected event.
19 */
20
21/* memory trace event */
22
23#if defined(CONFIG_ACPI_EXTLOG) || defined(CONFIG_ACPI_EXTLOG_MODULE)
24TRACE_EVENT(extlog_mem_event,
25 TP_PROTO(struct cper_sec_mem_err *mem,
26 u32 err_seq,
27 const uuid_le *fru_id,
28 const char *fru_text,
29 u8 sev),
30
31 TP_ARGS(mem, err_seq, fru_id, fru_text, sev),
32
33 TP_STRUCT__entry(
34 __field(u32, err_seq)
35 __field(u8, etype)
36 __field(u8, sev)
37 __field(u64, pa)
38 __field(u8, pa_mask_lsb)
39 __field_struct(uuid_le, fru_id)
40 __string(fru_text, fru_text)
41 __field_struct(struct cper_mem_err_compact, data)
42 ),
43
44 TP_fast_assign(
45 __entry->err_seq = err_seq;
46 if (mem->validation_bits & CPER_MEM_VALID_ERROR_TYPE)
47 __entry->etype = mem->error_type;
48 else
49 __entry->etype = ~0;
50 __entry->sev = sev;
51 if (mem->validation_bits & CPER_MEM_VALID_PA)
52 __entry->pa = mem->physical_addr;
53 else
54 __entry->pa = ~0ull;
55
56 if (mem->validation_bits & CPER_MEM_VALID_PA_MASK)
57 __entry->pa_mask_lsb = (u8)__ffs64(mem->physical_addr_mask);
58 else
59 __entry->pa_mask_lsb = ~0;
60 __entry->fru_id = *fru_id;
61 __assign_str(fru_text, fru_text);
62 cper_mem_err_pack(mem, &__entry->data);
63 ),
64
65 TP_printk("{%d} %s error: %s physical addr: %016llx (mask lsb: %x) %sFRU: %pUl %.20s",
66 __entry->err_seq,
67 cper_severity_str(__entry->sev),
68 cper_mem_err_type_str(__entry->etype),
69 __entry->pa,
70 __entry->pa_mask_lsb,
71 cper_mem_err_unpack(p, &__entry->data),
72 &__entry->fru_id,
73 __get_str(fru_text))
74);
75#endif
11 76
12/* 77/*
13 * Hardware Events Report 78 * Hardware Events Report
@@ -94,6 +159,69 @@ TRACE_EVENT(mc_event,
94 __get_str(driver_detail)) 159 __get_str(driver_detail))
95); 160);
96 161
162/*
163 * PCIe AER Trace event
164 *
165 * These events are generated when hardware detects a corrected or
166 * uncorrected event on a PCIe device. The event report has
167 * the following structure:
168 *
169 * char * dev_name - The name of the slot where the device resides
170 * ([domain:]bus:device.function).
171 * u32 status - Either the correctable or uncorrectable register
172 * indicating what error or errors have been seen
173 * u8 severity - error severity 0:NONFATAL 1:FATAL 2:CORRECTED
174 */
175
176#define aer_correctable_errors \
177 {BIT(0), "Receiver Error"}, \
178 {BIT(6), "Bad TLP"}, \
179 {BIT(7), "Bad DLLP"}, \
180 {BIT(8), "RELAY_NUM Rollover"}, \
181 {BIT(12), "Replay Timer Timeout"}, \
182 {BIT(13), "Advisory Non-Fatal"}
183
184#define aer_uncorrectable_errors \
185 {BIT(4), "Data Link Protocol"}, \
186 {BIT(12), "Poisoned TLP"}, \
187 {BIT(13), "Flow Control Protocol"}, \
188 {BIT(14), "Completion Timeout"}, \
189 {BIT(15), "Completer Abort"}, \
190 {BIT(16), "Unexpected Completion"}, \
191 {BIT(17), "Receiver Overflow"}, \
192 {BIT(18), "Malformed TLP"}, \
193 {BIT(19), "ECRC"}, \
194 {BIT(20), "Unsupported Request"}
195
196TRACE_EVENT(aer_event,
197 TP_PROTO(const char *dev_name,
198 const u32 status,
199 const u8 severity),
200
201 TP_ARGS(dev_name, status, severity),
202
203 TP_STRUCT__entry(
204 __string( dev_name, dev_name )
205 __field( u32, status )
206 __field( u8, severity )
207 ),
208
209 TP_fast_assign(
210 __assign_str(dev_name, dev_name);
211 __entry->status = status;
212 __entry->severity = severity;
213 ),
214
215 TP_printk("%s PCIe Bus Error: severity=%s, %s\n",
216 __get_str(dev_name),
217 __entry->severity == AER_CORRECTABLE ? "Corrected" :
218 __entry->severity == AER_FATAL ?
219 "Fatal" : "Uncorrected, non-fatal",
220 __entry->severity == AER_CORRECTABLE ?
221 __print_flags(__entry->status, "|", aer_correctable_errors) :
222 __print_flags(__entry->status, "|", aer_uncorrectable_errors))
223);
224
97#endif /* _TRACE_HW_EVENT_MC_H */ 225#endif /* _TRACE_HW_EVENT_MC_H */
98 226
99/* This part must be outside protection */ 227/* This part must be outside protection */
diff --git a/include/trace/events/ras.h b/include/trace/events/ras.h
deleted file mode 100644
index 1c875ad1ee5f..000000000000
--- a/include/trace/events/ras.h
+++ /dev/null
@@ -1,77 +0,0 @@
1#undef TRACE_SYSTEM
2#define TRACE_SYSTEM ras
3
4#if !defined(_TRACE_AER_H) || defined(TRACE_HEADER_MULTI_READ)
5#define _TRACE_AER_H
6
7#include <linux/tracepoint.h>
8#include <linux/aer.h>
9
10
11/*
12 * PCIe AER Trace event
13 *
14 * These events are generated when hardware detects a corrected or
15 * uncorrected event on a PCIe device. The event report has
16 * the following structure:
17 *
18 * char * dev_name - The name of the slot where the device resides
19 * ([domain:]bus:device.function).
20 * u32 status - Either the correctable or uncorrectable register
21 * indicating what error or errors have been seen
22 * u8 severity - error severity 0:NONFATAL 1:FATAL 2:CORRECTED
23 */
24
25#define aer_correctable_errors \
26 {BIT(0), "Receiver Error"}, \
27 {BIT(6), "Bad TLP"}, \
28 {BIT(7), "Bad DLLP"}, \
29 {BIT(8), "RELAY_NUM Rollover"}, \
30 {BIT(12), "Replay Timer Timeout"}, \
31 {BIT(13), "Advisory Non-Fatal"}
32
33#define aer_uncorrectable_errors \
34 {BIT(4), "Data Link Protocol"}, \
35 {BIT(12), "Poisoned TLP"}, \
36 {BIT(13), "Flow Control Protocol"}, \
37 {BIT(14), "Completion Timeout"}, \
38 {BIT(15), "Completer Abort"}, \
39 {BIT(16), "Unexpected Completion"}, \
40 {BIT(17), "Receiver Overflow"}, \
41 {BIT(18), "Malformed TLP"}, \
42 {BIT(19), "ECRC"}, \
43 {BIT(20), "Unsupported Request"}
44
45TRACE_EVENT(aer_event,
46 TP_PROTO(const char *dev_name,
47 const u32 status,
48 const u8 severity),
49
50 TP_ARGS(dev_name, status, severity),
51
52 TP_STRUCT__entry(
53 __string( dev_name, dev_name )
54 __field( u32, status )
55 __field( u8, severity )
56 ),
57
58 TP_fast_assign(
59 __assign_str(dev_name, dev_name);
60 __entry->status = status;
61 __entry->severity = severity;
62 ),
63
64 TP_printk("%s PCIe Bus Error: severity=%s, %s\n",
65 __get_str(dev_name),
66 __entry->severity == AER_CORRECTABLE ? "Corrected" :
67 __entry->severity == AER_FATAL ?
68 "Fatal" : "Uncorrected, non-fatal",
69 __entry->severity == AER_CORRECTABLE ?
70 __print_flags(__entry->status, "|", aer_correctable_errors) :
71 __print_flags(__entry->status, "|", aer_uncorrectable_errors))
72);
73
74#endif /* _TRACE_AER_H */
75
76/* This part must be outside protection */
77#include <trace/define_trace.h>
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index 0fd06fef9fac..26b4f2e13275 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -44,6 +44,12 @@
44#undef __field_ext 44#undef __field_ext
45#define __field_ext(type, item, filter_type) type item; 45#define __field_ext(type, item, filter_type) type item;
46 46
47#undef __field_struct
48#define __field_struct(type, item) type item;
49
50#undef __field_struct_ext
51#define __field_struct_ext(type, item, filter_type) type item;
52
47#undef __array 53#undef __array
48#define __array(type, item, len) type item[len]; 54#define __array(type, item, len) type item[len];
49 55
@@ -122,6 +128,12 @@
122#undef __field_ext 128#undef __field_ext
123#define __field_ext(type, item, filter_type) 129#define __field_ext(type, item, filter_type)
124 130
131#undef __field_struct
132#define __field_struct(type, item)
133
134#undef __field_struct_ext
135#define __field_struct_ext(type, item, filter_type)
136
125#undef __array 137#undef __array
126#define __array(type, item, len) 138#define __array(type, item, len)
127 139
@@ -315,9 +327,21 @@ static struct trace_event_functions ftrace_event_type_funcs_##call = { \
315 if (ret) \ 327 if (ret) \
316 return ret; 328 return ret;
317 329
330#undef __field_struct_ext
331#define __field_struct_ext(type, item, filter_type) \
332 ret = trace_define_field(event_call, #type, #item, \
333 offsetof(typeof(field), item), \
334 sizeof(field.item), \
335 0, filter_type); \
336 if (ret) \
337 return ret;
338
318#undef __field 339#undef __field
319#define __field(type, item) __field_ext(type, item, FILTER_OTHER) 340#define __field(type, item) __field_ext(type, item, FILTER_OTHER)
320 341
342#undef __field_struct
343#define __field_struct(type, item) __field_struct_ext(type, item, FILTER_OTHER)
344
321#undef __array 345#undef __array
322#define __array(type, item, len) \ 346#define __array(type, item, len) \
323 do { \ 347 do { \
@@ -379,6 +403,12 @@ ftrace_define_fields_##call(struct ftrace_event_call *event_call) \
379#undef __field_ext 403#undef __field_ext
380#define __field_ext(type, item, filter_type) 404#define __field_ext(type, item, filter_type)
381 405
406#undef __field_struct
407#define __field_struct(type, item)
408
409#undef __field_struct_ext
410#define __field_struct_ext(type, item, filter_type)
411
382#undef __array 412#undef __array
383#define __array(type, item, len) 413#define __array(type, item, len)
384 414
@@ -550,6 +580,9 @@ static inline notrace int ftrace_get_offsets_##call( \
550#undef __field 580#undef __field
551#define __field(type, item) 581#define __field(type, item)
552 582
583#undef __field_struct
584#define __field_struct(type, item)
585
553#undef __array 586#undef __array
554#define __array(type, item, len) 587#define __array(type, item, len)
555 588
diff --git a/include/trace/syscall.h b/include/trace/syscall.h
index fed853f3d7aa..9674145e2f6a 100644
--- a/include/trace/syscall.h
+++ b/include/trace/syscall.h
@@ -4,6 +4,7 @@
4#include <linux/tracepoint.h> 4#include <linux/tracepoint.h>
5#include <linux/unistd.h> 5#include <linux/unistd.h>
6#include <linux/ftrace_event.h> 6#include <linux/ftrace_event.h>
7#include <linux/thread_info.h>
7 8
8#include <asm/ptrace.h> 9#include <asm/ptrace.h>
9 10
@@ -32,4 +33,18 @@ struct syscall_metadata {
32 struct ftrace_event_call *exit_event; 33 struct ftrace_event_call *exit_event;
33}; 34};
34 35
36#if defined(CONFIG_TRACEPOINTS) && defined(CONFIG_HAVE_SYSCALL_TRACEPOINTS)
37static inline void syscall_tracepoint_update(struct task_struct *p)
38{
39 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
40 set_tsk_thread_flag(p, TIF_SYSCALL_TRACEPOINT);
41 else
42 clear_tsk_thread_flag(p, TIF_SYSCALL_TRACEPOINT);
43}
44#else
45static inline void syscall_tracepoint_update(struct task_struct *p)
46{
47}
48#endif
49
35#endif /* _TRACE_SYSCALL_H */ 50#endif /* _TRACE_SYSCALL_H */
diff --git a/kernel/fork.c b/kernel/fork.c
index d2799d1fc952..6a13c46cd87d 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1487,7 +1487,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1487 1487
1488 total_forks++; 1488 total_forks++;
1489 spin_unlock(&current->sighand->siglock); 1489 spin_unlock(&current->sighand->siglock);
1490 syscall_tracepoint_update(p);
1490 write_unlock_irq(&tasklist_lock); 1491 write_unlock_irq(&tasklist_lock);
1492
1491 proc_fork_connector(p); 1493 proc_fork_connector(p);
1492 cgroup_post_fork(p); 1494 cgroup_post_fork(p);
1493 if (clone_flags & CLONE_THREAD) 1495 if (clone_flags & CLONE_THREAD)
diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
index 33cbd8c203f8..3490407dc7b7 100644
--- a/kernel/tracepoint.c
+++ b/kernel/tracepoint.c
@@ -492,33 +492,29 @@ static int sys_tracepoint_refcount;
492 492
493void syscall_regfunc(void) 493void syscall_regfunc(void)
494{ 494{
495 unsigned long flags; 495 struct task_struct *p, *t;
496 struct task_struct *g, *t;
497 496
498 if (!sys_tracepoint_refcount) { 497 if (!sys_tracepoint_refcount) {
499 read_lock_irqsave(&tasklist_lock, flags); 498 read_lock(&tasklist_lock);
500 do_each_thread(g, t) { 499 for_each_process_thread(p, t) {
501 /* Skip kernel threads. */ 500 set_tsk_thread_flag(t, TIF_SYSCALL_TRACEPOINT);
502 if (t->mm) 501 }
503 set_tsk_thread_flag(t, TIF_SYSCALL_TRACEPOINT); 502 read_unlock(&tasklist_lock);
504 } while_each_thread(g, t);
505 read_unlock_irqrestore(&tasklist_lock, flags);
506 } 503 }
507 sys_tracepoint_refcount++; 504 sys_tracepoint_refcount++;
508} 505}
509 506
510void syscall_unregfunc(void) 507void syscall_unregfunc(void)
511{ 508{
512 unsigned long flags; 509 struct task_struct *p, *t;
513 struct task_struct *g, *t;
514 510
515 sys_tracepoint_refcount--; 511 sys_tracepoint_refcount--;
516 if (!sys_tracepoint_refcount) { 512 if (!sys_tracepoint_refcount) {
517 read_lock_irqsave(&tasklist_lock, flags); 513 read_lock(&tasklist_lock);
518 do_each_thread(g, t) { 514 for_each_process_thread(p, t) {
519 clear_tsk_thread_flag(t, TIF_SYSCALL_TRACEPOINT); 515 clear_tsk_thread_flag(t, TIF_SYSCALL_TRACEPOINT);
520 } while_each_thread(g, t); 516 }
521 read_unlock_irqrestore(&tasklist_lock, flags); 517 read_unlock(&tasklist_lock);
522 } 518 }
523} 519}
524#endif 520#endif
diff --git a/samples/trace_events/trace-events-sample.h b/samples/trace_events/trace-events-sample.h
index 6af373236d73..4b0113f73ee9 100644
--- a/samples/trace_events/trace-events-sample.h
+++ b/samples/trace_events/trace-events-sample.h
@@ -56,7 +56,8 @@
56 * struct: This defines the way the data will be stored in the ring buffer. 56 * struct: This defines the way the data will be stored in the ring buffer.
57 * There are currently two types of elements. __field and __array. 57 * There are currently two types of elements. __field and __array.
58 * a __field is broken up into (type, name). Where type can be any 58 * a __field is broken up into (type, name). Where type can be any
59 * type but an array. 59 * primitive type (integer, long or pointer). __field_struct() can
60 * be any static complex data value (struct, union, but not an array).
60 * For an array. there are three fields. (type, name, size). The 61 * For an array. there are three fields. (type, name, size). The
61 * type of elements in the array, the name of the field and the size 62 * type of elements in the array, the name of the field and the size
62 * of the array. 63 * of the array.