aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/cpu/cpu_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/cpu/cpu_debug.c')
-rwxr-xr-xarch/x86/kernel/cpu/cpu_debug.c268
1 files changed, 192 insertions, 76 deletions
diff --git a/arch/x86/kernel/cpu/cpu_debug.c b/arch/x86/kernel/cpu/cpu_debug.c
index 9abbcbd933c..46e29ab96c6 100755
--- a/arch/x86/kernel/cpu/cpu_debug.c
+++ b/arch/x86/kernel/cpu/cpu_debug.c
@@ -11,6 +11,7 @@
11#include <linux/seq_file.h> 11#include <linux/seq_file.h>
12#include <linux/debugfs.h> 12#include <linux/debugfs.h>
13#include <linux/kprobes.h> 13#include <linux/kprobes.h>
14#include <linux/uaccess.h>
14#include <linux/kernel.h> 15#include <linux/kernel.h>
15#include <linux/module.h> 16#include <linux/module.h>
16#include <linux/percpu.h> 17#include <linux/percpu.h>
@@ -40,41 +41,43 @@ static DEFINE_MUTEX(cpu_debug_lock);
40static struct dentry *cpu_debugfs_dir; 41static struct dentry *cpu_debugfs_dir;
41 42
42static struct cpu_debug_base cpu_base[] = { 43static struct cpu_debug_base cpu_base[] = {
43 { "mc", CPU_MC }, /* Machine Check */ 44 { "mc", CPU_MC, 0 },
44 { "monitor", CPU_MONITOR }, /* Monitor */ 45 { "monitor", CPU_MONITOR, 0 },
45 { "time", CPU_TIME }, /* Time */ 46 { "time", CPU_TIME, 0 },
46 { "pmc", CPU_PMC }, /* Performance Monitor */ 47 { "pmc", CPU_PMC, 1 },
47 { "platform", CPU_PLATFORM }, /* Platform */ 48 { "platform", CPU_PLATFORM, 0 },
48 { "apic", CPU_APIC }, /* APIC */ 49 { "apic", CPU_APIC, 0 },
49 { "poweron", CPU_POWERON }, /* Power-on */ 50 { "poweron", CPU_POWERON, 0 },
50 { "control", CPU_CONTROL }, /* Control */ 51 { "control", CPU_CONTROL, 0 },
51 { "features", CPU_FEATURES }, /* Features control */ 52 { "features", CPU_FEATURES, 0 },
52 { "lastbranch", CPU_LBRANCH }, /* Last Branch */ 53 { "lastbranch", CPU_LBRANCH, 0 },
53 { "bios", CPU_BIOS }, /* BIOS */ 54 { "bios", CPU_BIOS, 0 },
54 { "freq", CPU_FREQ }, /* Frequency */ 55 { "freq", CPU_FREQ, 0 },
55 { "mtrr", CPU_MTRR }, /* MTRR */ 56 { "mtrr", CPU_MTRR, 0 },
56 { "perf", CPU_PERF }, /* Performance */ 57 { "perf", CPU_PERF, 0 },
57 { "cache", CPU_CACHE }, /* Cache */ 58 { "cache", CPU_CACHE, 0 },
58 { "sysenter", CPU_SYSENTER }, /* Sysenter */ 59 { "sysenter", CPU_SYSENTER, 0 },
59 { "therm", CPU_THERM }, /* Thermal */ 60 { "therm", CPU_THERM, 0 },
60 { "misc", CPU_MISC }, /* Miscellaneous */ 61 { "misc", CPU_MISC, 0 },
61 { "debug", CPU_DEBUG }, /* Debug */ 62 { "debug", CPU_DEBUG, 0 },
62 { "pat", CPU_PAT }, /* PAT */ 63 { "pat", CPU_PAT, 0 },
63 { "vmx", CPU_VMX }, /* VMX */ 64 { "vmx", CPU_VMX, 0 },
64 { "call", CPU_CALL }, /* System Call */ 65 { "call", CPU_CALL, 0 },
65 { "base", CPU_BASE }, /* BASE Address */ 66 { "base", CPU_BASE, 0 },
66 { "smm", CPU_SMM }, /* System mgmt mode */ 67 { "ver", CPU_VER, 0 },
67 { "svm", CPU_SVM }, /*Secure Virtial Machine*/ 68 { "conf", CPU_CONF, 0 },
68 { "osvm", CPU_OSVM }, /* OS-Visible Workaround*/ 69 { "smm", CPU_SMM, 0 },
69 { "tss", CPU_TSS }, /* Task Stack Segment */ 70 { "svm", CPU_SVM, 0 },
70 { "cr", CPU_CR }, /* Control Registers */ 71 { "osvm", CPU_OSVM, 0 },
71 { "dt", CPU_DT }, /* Descriptor Table */ 72 { "tss", CPU_TSS, 0 },
72 { "registers", CPU_REG_ALL }, /* Select all Registers */ 73 { "cr", CPU_CR, 0 },
74 { "dt", CPU_DT, 0 },
75 { "registers", CPU_REG_ALL, 0 },
73}; 76};
74 77
75static struct cpu_file_base cpu_file[] = { 78static struct cpu_file_base cpu_file[] = {
76 { "index", CPU_REG_ALL }, /* index */ 79 { "index", CPU_REG_ALL, 0 },
77 { "value", CPU_REG_ALL }, /* value */ 80 { "value", CPU_REG_ALL, 1 },
78}; 81};
79 82
80/* Intel Registers Range */ 83/* Intel Registers Range */
@@ -176,54 +179,59 @@ static struct cpu_debug_range cpu_intel_range[] = {
176 179
177/* AMD Registers Range */ 180/* AMD Registers Range */
178static struct cpu_debug_range cpu_amd_range[] = { 181static struct cpu_debug_range cpu_amd_range[] = {
179 { 0x00000010, 0x00000010, CPU_TIME, CPU_ALL, }, 182 { 0x00000000, 0x00000001, CPU_MC, CPU_K10_PLUS, },
180 { 0x0000001B, 0x0000001B, CPU_APIC, CPU_ALL, }, 183 { 0x00000010, 0x00000010, CPU_TIME, CPU_K8_PLUS, },
181 { 0x000000FE, 0x000000FE, CPU_MTRR, CPU_ALL, }, 184 { 0x0000001B, 0x0000001B, CPU_APIC, CPU_K8_PLUS, },
182 185 { 0x0000002A, 0x0000002A, CPU_POWERON, CPU_K7_PLUS },
183 { 0x00000174, 0x00000176, CPU_SYSENTER, CPU_ALL, }, 186 { 0x0000008B, 0x0000008B, CPU_VER, CPU_K8_PLUS },
184 { 0x00000179, 0x0000017A, CPU_MC, CPU_ALL, }, 187 { 0x000000FE, 0x000000FE, CPU_MTRR, CPU_K8_PLUS, },
185 { 0x0000017B, 0x0000017B, CPU_MC, CPU_ALL, }, 188
186 { 0x000001D9, 0x000001D9, CPU_DEBUG, CPU_ALL, }, 189 { 0x00000174, 0x00000176, CPU_SYSENTER, CPU_K8_PLUS, },
187 { 0x000001DB, 0x000001DE, CPU_LBRANCH, CPU_ALL, }, 190 { 0x00000179, 0x0000017B, CPU_MC, CPU_K8_PLUS, },
188 191 { 0x000001D9, 0x000001D9, CPU_DEBUG, CPU_K8_PLUS, },
189 { 0x00000200, 0x0000020F, CPU_MTRR, CPU_ALL, }, 192 { 0x000001DB, 0x000001DE, CPU_LBRANCH, CPU_K8_PLUS, },
190 { 0x00000250, 0x00000250, CPU_MTRR, CPU_ALL, }, 193
191 { 0x00000258, 0x00000259, CPU_MTRR, CPU_ALL, }, 194 { 0x00000200, 0x0000020F, CPU_MTRR, CPU_K8_PLUS, },
192 { 0x00000268, 0x0000026F, CPU_MTRR, CPU_ALL, }, 195 { 0x00000250, 0x00000250, CPU_MTRR, CPU_K8_PLUS, },
193 { 0x00000277, 0x00000277, CPU_PAT, CPU_ALL, }, 196 { 0x00000258, 0x00000259, CPU_MTRR, CPU_K8_PLUS, },
194 { 0x000002FF, 0x000002FF, CPU_MTRR, CPU_ALL, }, 197 { 0x00000268, 0x0000026F, CPU_MTRR, CPU_K8_PLUS, },
195 198 { 0x00000277, 0x00000277, CPU_PAT, CPU_K8_PLUS, },
196 { 0x00000400, 0x00000417, CPU_MC, CPU_ALL, }, 199 { 0x000002FF, 0x000002FF, CPU_MTRR, CPU_K8_PLUS, },
197 200
198 { 0xC0000080, 0xC0000080, CPU_FEATURES, CPU_ALL, }, 201 { 0x00000400, 0x00000413, CPU_MC, CPU_K8_PLUS, },
199 { 0xC0000081, 0xC0000084, CPU_CALL, CPU_ALL, }, 202
200 { 0xC0000100, 0xC0000102, CPU_BASE, CPU_ALL, }, 203 { 0xC0000080, 0xC0000080, CPU_FEATURES, CPU_AMD_ALL, },
201 { 0xC0000103, 0xC0000103, CPU_TIME, CPU_ALL, }, 204 { 0xC0000081, 0xC0000084, CPU_CALL, CPU_K8_PLUS, },
202 205 { 0xC0000100, 0xC0000102, CPU_BASE, CPU_K8_PLUS, },
203 { 0xC0000408, 0xC000040A, CPU_MC, CPU_ALL, }, 206 { 0xC0000103, 0xC0000103, CPU_TIME, CPU_K10_PLUS, },
204 207
205 { 0xc0010000, 0xc0010007, CPU_PMC, CPU_ALL, }, 208 { 0xC0010000, 0xC0010007, CPU_PMC, CPU_K8_PLUS, },
206 { 0xc0010010, 0xc0010010, CPU_MTRR, CPU_ALL, }, 209 { 0xC0010010, 0xC0010010, CPU_CONF, CPU_K7_PLUS, },
207 { 0xc0010016, 0xc001001A, CPU_MTRR, CPU_ALL, }, 210 { 0xC0010015, 0xC0010015, CPU_CONF, CPU_K7_PLUS, },
208 { 0xc001001D, 0xc001001D, CPU_MTRR, CPU_ALL, }, 211 { 0xC0010016, 0xC001001A, CPU_MTRR, CPU_K8_PLUS, },
209 { 0xc0010030, 0xc0010035, CPU_BIOS, CPU_ALL, }, 212 { 0xC001001D, 0xC001001D, CPU_MTRR, CPU_K8_PLUS, },
210 { 0xc0010056, 0xc0010056, CPU_SMM, CPU_ALL, }, 213 { 0xC001001F, 0xC001001F, CPU_CONF, CPU_K8_PLUS, },
211 { 0xc0010061, 0xc0010063, CPU_SMM, CPU_ALL, }, 214 { 0xC0010030, 0xC0010035, CPU_BIOS, CPU_K8_PLUS, },
212 { 0xc0010074, 0xc0010074, CPU_MC, CPU_ALL, }, 215 { 0xC0010044, 0xC0010048, CPU_MC, CPU_K8_PLUS, },
213 { 0xc0010111, 0xc0010113, CPU_SMM, CPU_ALL, }, 216 { 0xC0010050, 0xC0010056, CPU_SMM, CPU_K0F_PLUS, },
214 { 0xc0010114, 0xc0010118, CPU_SVM, CPU_ALL, }, 217 { 0xC0010058, 0xC0010058, CPU_CONF, CPU_K10_PLUS, },
215 { 0xc0010119, 0xc001011A, CPU_SMM, CPU_ALL, }, 218 { 0xC0010060, 0xC0010060, CPU_CACHE, CPU_AMD_11, },
216 { 0xc0010140, 0xc0010141, CPU_OSVM, CPU_ALL, }, 219 { 0xC0010061, 0xC0010068, CPU_SMM, CPU_K10_PLUS, },
217 { 0xc0010156, 0xc0010156, CPU_SMM, CPU_ALL, }, 220 { 0xC0010069, 0xC001006B, CPU_SMM, CPU_AMD_11, },
221 { 0xC0010070, 0xC0010071, CPU_SMM, CPU_K10_PLUS, },
222 { 0xC0010111, 0xC0010113, CPU_SMM, CPU_K8_PLUS, },
223 { 0xC0010114, 0xC0010118, CPU_SVM, CPU_K10_PLUS, },
224 { 0xC0010140, 0xC0010141, CPU_OSVM, CPU_K10_PLUS, },
225 { 0xC0011022, 0xC0011023, CPU_CONF, CPU_K10_PLUS, },
218}; 226};
219 227
220 228
221static int get_cpu_modelflag(unsigned cpu) 229/* Intel */
230static int get_intel_modelflag(unsigned model)
222{ 231{
223 int flag; 232 int flag;
224 233
225 switch (per_cpu(cpu_model, cpu)) { 234 switch (model) {
226 /* Intel */
227 case 0x0501: 235 case 0x0501:
228 case 0x0502: 236 case 0x0502:
229 case 0x0504: 237 case 0x0504:
@@ -270,6 +278,59 @@ static int get_cpu_modelflag(unsigned cpu)
270 return flag; 278 return flag;
271} 279}
272 280
281/* AMD */
282static int get_amd_modelflag(unsigned model)
283{
284 int flag;
285
286 switch (model >> 8) {
287 case 0x6:
288 flag = CPU_AMD_K6;
289 break;
290 case 0x7:
291 flag = CPU_AMD_K7;
292 break;
293 case 0x8:
294 flag = CPU_AMD_K8;
295 break;
296 case 0xf:
297 flag = CPU_AMD_0F;
298 break;
299 case 0x10:
300 flag = CPU_AMD_10;
301 break;
302 case 0x11:
303 flag = CPU_AMD_11;
304 break;
305 default:
306 flag = CPU_NONE;
307 break;
308 }
309
310 return flag;
311}
312
313static int get_cpu_modelflag(unsigned cpu)
314{
315 int flag;
316
317 flag = per_cpu(cpu_model, cpu);
318
319 switch (flag >> 16) {
320 case X86_VENDOR_INTEL:
321 flag = get_intel_modelflag(flag);
322 break;
323 case X86_VENDOR_AMD:
324 flag = get_amd_modelflag(flag & 0xffff);
325 break;
326 default:
327 flag = CPU_NONE;
328 break;
329 }
330
331 return flag;
332}
333
273static int get_cpu_range_count(unsigned cpu) 334static int get_cpu_range_count(unsigned cpu)
274{ 335{
275 int index; 336 int index;
@@ -310,7 +371,8 @@ static int is_typeflag_valid(unsigned cpu, unsigned flag)
310 return 1; 371 return 1;
311 break; 372 break;
312 case X86_VENDOR_AMD: 373 case X86_VENDOR_AMD:
313 if (cpu_amd_range[i].flag & flag) 374 if ((cpu_amd_range[i].model & modelflag) &&
375 (cpu_amd_range[i].flag & flag))
314 return 1; 376 return 1;
315 break; 377 break;
316 } 378 }
@@ -336,7 +398,8 @@ static unsigned get_cpu_range(unsigned cpu, unsigned *min, unsigned *max,
336 } 398 }
337 break; 399 break;
338 case X86_VENDOR_AMD: 400 case X86_VENDOR_AMD:
339 if (cpu_amd_range[index].flag & flag) { 401 if ((cpu_amd_range[index].model & modelflag) &&
402 (cpu_amd_range[index].flag & flag)) {
340 *min = cpu_amd_range[index].min; 403 *min = cpu_amd_range[index].min;
341 *max = cpu_amd_range[index].max; 404 *max = cpu_amd_range[index].max;
342 } 405 }
@@ -608,9 +671,62 @@ static int cpu_seq_open(struct inode *inode, struct file *file)
608 return err; 671 return err;
609} 672}
610 673
674static int write_msr(struct cpu_private *priv, u64 val)
675{
676 u32 low, high;
677
678 high = (val >> 32) & 0xffffffff;
679 low = val & 0xffffffff;
680
681 if (!wrmsr_safe_on_cpu(priv->cpu, priv->reg, low, high))
682 return 0;
683
684 return -EPERM;
685}
686
687static int write_cpu_register(struct cpu_private *priv, const char *buf)
688{
689 int ret = -EPERM;
690 u64 val;
691
692 ret = strict_strtoull(buf, 0, &val);
693 if (ret < 0)
694 return ret;
695
696 /* Supporting only MSRs */
697 if (priv->type < CPU_TSS_BIT)
698 return write_msr(priv, val);
699
700 return ret;
701}
702
703static ssize_t cpu_write(struct file *file, const char __user *ubuf,
704 size_t count, loff_t *off)
705{
706 struct seq_file *seq = file->private_data;
707 struct cpu_private *priv = seq->private;
708 char buf[19];
709
710 if ((priv == NULL) || (count >= sizeof(buf)))
711 return -EINVAL;
712
713 if (copy_from_user(&buf, ubuf, count))
714 return -EFAULT;
715
716 buf[count] = 0;
717
718 if ((cpu_base[priv->type].write) && (cpu_file[priv->file].write))
719 if (!write_cpu_register(priv, buf))
720 return count;
721
722 return -EACCES;
723}
724
611static const struct file_operations cpu_fops = { 725static const struct file_operations cpu_fops = {
726 .owner = THIS_MODULE,
612 .open = cpu_seq_open, 727 .open = cpu_seq_open,
613 .read = seq_read, 728 .read = seq_read,
729 .write = cpu_write,
614 .llseek = seq_lseek, 730 .llseek = seq_lseek,
615 .release = seq_release, 731 .release = seq_release,
616}; 732};