diff options
author | Huang Ying <ying.huang@intel.com> | 2009-05-27 15:56:57 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-06-03 17:45:34 -0400 |
commit | 4611a6fa4b37cf6b8b6066ed0d605c994c62a1a0 (patch) | |
tree | 5a653d42248914cb38ab6b1f3b319abe39f4e2cd /arch | |
parent | ed7290d0ee8f81aa78bfe816f01b012f208cafc5 (diff) |
x86, mce: export MCE severities coverage via debugfs
The MCE severity judgement code is data-driven, so code coverage tools
such as gcov can not be used for measuring coverage. Instead a dedicated
coverage mechanism is implemented. The kernel keeps track of rules
executed and reports them in debugfs.
This is useful for increasing coverage of the mce-test testsuite.
Right now it's unconditionally enabled because it's very little code.
Signed-off-by: Huang Ying <ying.huang@intel.com>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce-severity.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c index 4f4d2caf4043..ff0807f97056 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-severity.c +++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c | |||
@@ -10,6 +10,9 @@ | |||
10 | * Author: Andi Kleen | 10 | * Author: Andi Kleen |
11 | */ | 11 | */ |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/seq_file.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/debugfs.h> | ||
13 | #include <asm/mce.h> | 16 | #include <asm/mce.h> |
14 | 17 | ||
15 | #include "mce-internal.h" | 18 | #include "mce-internal.h" |
@@ -37,6 +40,7 @@ static struct severity { | |||
37 | unsigned char mcgres; | 40 | unsigned char mcgres; |
38 | unsigned char ser; | 41 | unsigned char ser; |
39 | unsigned char context; | 42 | unsigned char context; |
43 | unsigned char covered; | ||
40 | char *msg; | 44 | char *msg; |
41 | } severities[] = { | 45 | } severities[] = { |
42 | #define KERNEL .context = IN_KERNEL | 46 | #define KERNEL .context = IN_KERNEL |
@@ -126,6 +130,7 @@ int mce_severity(struct mce *a, int tolerant, char **msg) | |||
126 | continue; | 130 | continue; |
127 | if (msg) | 131 | if (msg) |
128 | *msg = s->msg; | 132 | *msg = s->msg; |
133 | s->covered = 1; | ||
129 | if (s->sev >= MCE_UC_SEVERITY && ctx == IN_KERNEL) { | 134 | if (s->sev >= MCE_UC_SEVERITY && ctx == IN_KERNEL) { |
130 | if (panic_on_oops || tolerant < 1) | 135 | if (panic_on_oops || tolerant < 1) |
131 | return MCE_PANIC_SEVERITY; | 136 | return MCE_PANIC_SEVERITY; |
@@ -133,3 +138,81 @@ int mce_severity(struct mce *a, int tolerant, char **msg) | |||
133 | return s->sev; | 138 | return s->sev; |
134 | } | 139 | } |
135 | } | 140 | } |
141 | |||
142 | static void *s_start(struct seq_file *f, loff_t *pos) | ||
143 | { | ||
144 | if (*pos >= ARRAY_SIZE(severities)) | ||
145 | return NULL; | ||
146 | return &severities[*pos]; | ||
147 | } | ||
148 | |||
149 | static void *s_next(struct seq_file *f, void *data, loff_t *pos) | ||
150 | { | ||
151 | if (++(*pos) >= ARRAY_SIZE(severities)) | ||
152 | return NULL; | ||
153 | return &severities[*pos]; | ||
154 | } | ||
155 | |||
156 | static void s_stop(struct seq_file *f, void *data) | ||
157 | { | ||
158 | } | ||
159 | |||
160 | static int s_show(struct seq_file *f, void *data) | ||
161 | { | ||
162 | struct severity *ser = data; | ||
163 | seq_printf(f, "%d\t%s\n", ser->covered, ser->msg); | ||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static const struct seq_operations severities_seq_ops = { | ||
168 | .start = s_start, | ||
169 | .next = s_next, | ||
170 | .stop = s_stop, | ||
171 | .show = s_show, | ||
172 | }; | ||
173 | |||
174 | static int severities_coverage_open(struct inode *inode, struct file *file) | ||
175 | { | ||
176 | return seq_open(file, &severities_seq_ops); | ||
177 | } | ||
178 | |||
179 | static ssize_t severities_coverage_write(struct file *file, | ||
180 | const char __user *ubuf, | ||
181 | size_t count, loff_t *ppos) | ||
182 | { | ||
183 | int i; | ||
184 | for (i = 0; i < ARRAY_SIZE(severities); i++) | ||
185 | severities[i].covered = 0; | ||
186 | return count; | ||
187 | } | ||
188 | |||
189 | static const struct file_operations severities_coverage_fops = { | ||
190 | .open = severities_coverage_open, | ||
191 | .release = seq_release, | ||
192 | .read = seq_read, | ||
193 | .write = severities_coverage_write, | ||
194 | }; | ||
195 | |||
196 | static int __init severities_debugfs_init(void) | ||
197 | { | ||
198 | struct dentry *dmce = NULL, *fseverities_coverage = NULL; | ||
199 | |||
200 | dmce = debugfs_create_dir("mce", NULL); | ||
201 | if (dmce == NULL) | ||
202 | goto err_out; | ||
203 | fseverities_coverage = debugfs_create_file("severities-coverage", | ||
204 | 0444, dmce, NULL, | ||
205 | &severities_coverage_fops); | ||
206 | if (fseverities_coverage == NULL) | ||
207 | goto err_out; | ||
208 | |||
209 | return 0; | ||
210 | |||
211 | err_out: | ||
212 | if (fseverities_coverage) | ||
213 | debugfs_remove(fseverities_coverage); | ||
214 | if (dmce) | ||
215 | debugfs_remove(dmce); | ||
216 | return -ENOMEM; | ||
217 | } | ||
218 | late_initcall(severities_debugfs_init); | ||