2009-03-02 15:43:30

by Jaswinder Singh Rajput

[permalink] [raw]
Subject: [git-pull -tip] x86: msr architecture debug code

The following changes since commit 1d10914bf2c8a1164aef6c341e6c3518a91b8374:
Ingo Molnar (1):
Merge branch 'core/percpu'

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/jaswinder/linux-2.6-tip-cpu.git master

Jaswinder Singh Rajput (1):
x86: msr architecture debug code

arch/x86/include/asm/msr_debug.h | 56 ++++++
arch/x86/kernel/cpu/Makefile | 2 +-
arch/x86/kernel/cpu/msr_debug.c | 362 ++++++++++++++++++++++++++++++++++++++
3 files changed, 419 insertions(+), 1 deletions(-)
create mode 100755 arch/x86/include/asm/msr_debug.h
create mode 100755 arch/x86/kernel/cpu/msr_debug.c

Complete diff:
diff --git a/arch/x86/include/asm/msr_debug.h b/arch/x86/include/asm/msr_debug.h
new file mode 100755
index 0000000..ddc4fe5
--- /dev/null
+++ b/arch/x86/include/asm/msr_debug.h
@@ -0,0 +1,56 @@
+#ifndef _ASM_X86_MSR_DEBUG_H
+#define _ASM_X86_MSR_DEBUG_H
+
+/*
+ * Model Specific Registers (MSR) x86 architecture debug
+ *
+ * Copyright(C) 2009 Jaswinder Singh Rajput
+ */
+
+#define MSR_ALL 0
+#define MSR_PMC 1 /* Performance Monitor counters */
+
+struct msr_debug_range {
+ unsigned min;
+ unsigned max;
+ unsigned model;
+};
+
+/* Intel MSRs Range */
+
+/* DisplayFamily_DisplayModel Processor Families/Processor Number Series */
+/* -------------------------- ------------------------------------------ */
+/* 05_01, 05_02, 05_04 Pentium, Pentium with MMX */
+#define MSR_INTEL_PENTIUM (1 << 0)
+
+/* 06_01 Pentium Pro */
+/* 06_03, 06_05 Pentium II Xeon, Pentium II */
+/* 06_07, 06_08, 06_0A, 06_0B Pentium III Xeon, Pentum III */
+#define MSR_INTEL_P6 (1 << 1)
+
+/* 06_09, 060D Pentium M */
+#define MSR_INTEL_PENTIUM_M (1 << 4)
+
+/* 06_0E Core Duo, Core Solo */
+#define MSR_INTEL_CORE (1 << 5)
+
+/* 06_0F Xeon 3000, 3200, 5100, 5300, 7300 series,
+ Core 2 Quad, Core 2 Extreme, Core 2 Duo,
+ Pentium dual-core */
+/* 06_17 Xeon 5200, 5400 series, Core 2 Quad Q9650 */
+#define MSR_INTEL_CORE_2 (1 << 6)
+
+/* 06_1C Atom */
+#define MSR_INTEL_ATOM (1 << 7)
+
+/* 0F_00, 0F_01, 0F_02 Xeon, Xeon MP, Pentium 4 */
+/* 0F_03, 0F_04 Xeon, Xeon MP, Pentium 4, Pentium D */
+#define MSR_INTEL_XEON (1 << 17)
+
+/* 0F_06 Xeon 7100, 5000 Series, Xeon MP,
+ Pentium 4, Pentium D */
+#define MSR_INTEL_XEON_MP (1 << 18)
+
+#define MSR_CPU_ALL (~0)
+
+#endif /* _ASM_X86_MSR_DEBUG_H */
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index c381330..b2452f3 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -8,7 +8,7 @@ CFLAGS_REMOVE_common.o = -pg
endif

obj-y := intel_cacheinfo.o addon_cpuid_features.o
-obj-y += proc.o capflags.o powerflags.o common.o
+obj-y += proc.o capflags.o powerflags.o common.o msr_debug.o
obj-y += vmware.o hypervisor.o

obj-$(CONFIG_X86_32) += bugs.o cmpxchg.o
diff --git a/arch/x86/kernel/cpu/msr_debug.c b/arch/x86/kernel/cpu/msr_debug.c
new file mode 100755
index 0000000..505f53f
--- /dev/null
+++ b/arch/x86/kernel/cpu/msr_debug.c
@@ -0,0 +1,362 @@
+/*
+ * Model Specific Registers (MSR) x86 architecture debug code
+ *
+ * Copyright(C) 2009 Jaswinder Singh Rajput
+ *
+ * For licencing details see kernel-base/COPYING
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <asm/msr_debug.h>
+
+static struct msr_debug_range msr_intel_range[] = {
+ { 0x00000000, 0x000006d0, MSR_CPU_ALL },
+ { 0x000107CC, 0x000107D4, MSR_INTEL_XEON_MP },
+};
+
+static struct msr_debug_range pmc_intel_range[] = {
+ { 0x00000010, 0x00000011, MSR_CPU_ALL }, /* TSC */
+ { 0x00000011, 0x00000014, MSR_INTEL_PENTIUM }, /* CESR, CTR */
+ { 0x0000001B, 0x0000001C, MSR_CPU_ALL }, /* APIC */
+ { 0x000000C1, 0x000000C3, MSR_INTEL_P6 }, /* PerfCtr */
+ { 0x00000186, 0x00000188, MSR_INTEL_P6 | MSR_INTEL_ATOM |
+ MSR_INTEL_CORE_2 }, /* EvtSel */
+ { 0x000001A0, 0x000001A1, MSR_CPU_ALL }, /* Misc Feature */
+ { 0x00000300, 0x00000312, MSR_INTEL_XEON }, /* Counter */
+ { 0x00000309, 0x0000030C, MSR_INTEL_P6 | MSR_INTEL_ATOM |
+ MSR_INTEL_CORE_2 }, /* Fixed */
+ { 0x00000360, 0x00000372, MSR_INTEL_XEON }, /* CCCR */
+ { 0x0000038D, 0x00000391, MSR_INTEL_P6 | MSR_INTEL_ATOM |
+ MSR_INTEL_CORE_2 }, /* Fixed & Global */
+ { 0x00000390, 0x00000391, MSR_INTEL_P6 | MSR_INTEL_ATOM |
+ MSR_INTEL_CORE_2 }, /* OVF */
+ { 0x000003A0, 0x000003F3, MSR_INTEL_XEON }, /* ESCR */
+ { 0x000003F1, 0x000003F2, MSR_INTEL_P6 | MSR_INTEL_ATOM |
+ MSR_INTEL_CORE_2 }, /* PEBS */
+ { 0x000107CC, 0x000107D4, MSR_INTEL_XEON_MP },
+};
+
+/* AMD MSRs Range */
+static struct msr_debug_range msr_amd_range[] = {
+ { 0x00000000, 0x00000418, MSR_CPU_ALL},
+ { 0xc0000000, 0xc000040b, MSR_CPU_ALL},
+ { 0xc0010000, 0xc0010142, MSR_CPU_ALL},
+ { 0xc0011000, 0xc001103b, MSR_CPU_ALL},
+};
+
+static struct msr_debug_range pmc_amd_range[] = {
+ { 0x00000010, 0x00000011, MSR_CPU_ALL }, /* TSC */
+ { 0x0000001B, 0x0000001C, MSR_CPU_ALL }, /* APIC */
+ { 0xc0010000, 0xc0010008, MSR_CPU_ALL},
+};
+
+
+static int get_msr_intel_bit(unsigned model)
+{
+ int ret = 0;
+
+ switch (model) {
+ case 0x0501:
+ case 0x0502:
+ case 0x0504:
+ ret = MSR_INTEL_PENTIUM;
+ break;
+ case 0x0601:
+ case 0x0603:
+ case 0x0605:
+ case 0x0607:
+ case 0x0608:
+ case 0x060A:
+ case 0x060B:
+ ret = MSR_INTEL_P6;
+ break;
+ case 0x0609:
+ case 0x060D:
+ ret = MSR_INTEL_PENTIUM_M;
+ break;
+ case 0x060E:
+ ret = MSR_INTEL_CORE;
+ break;
+ case 0x060F:
+ case 0x0617:
+ ret = MSR_INTEL_CORE_2;
+ break;
+ case 0x061C:
+ ret = MSR_INTEL_ATOM;
+ break;
+ case 0x0F00:
+ case 0x0F01:
+ case 0x0F02:
+ case 0x0F03:
+ case 0x0F04:
+ ret = MSR_INTEL_XEON;
+ break;
+ case 0x0F06:
+ ret = MSR_INTEL_XEON_MP;
+ break;
+ }
+
+ return ret;
+}
+
+static int get_msr_cpu_bit(unsigned model)
+{
+ unsigned vendor;
+
+ vendor = model >> 16;
+ if (vendor == X86_VENDOR_INTEL)
+ return get_msr_intel_bit(model & 0xffff);
+ else
+ return 0;
+}
+
+static int get_msr_range(unsigned *min, unsigned *max, int index,
+ unsigned flag, unsigned model)
+{
+ unsigned vendor, cpu_bit;
+ int err = 0;
+
+ vendor = model >> 16;
+ cpu_bit = get_msr_cpu_bit(model);
+ switch (flag) {
+ case MSR_ALL:
+ if (vendor == 0) {
+ if (msr_intel_range[index].model & cpu_bit) {
+ *min = msr_intel_range[index].min;
+ *max = msr_intel_range[index].max;
+ } else
+ err = -EINVAL;
+ } else if (vendor == X86_VENDOR_AMD) {
+ *min = msr_amd_range[index].min;
+ *max = msr_amd_range[index].max;
+ }
+ break;
+ case MSR_PMC:
+ if (vendor == 0) {
+ if (pmc_intel_range[index].model & cpu_bit) {
+ *min = pmc_intel_range[index].min;
+ *max = pmc_intel_range[index].max;
+ } else
+ err = -EINVAL;
+ } else if (vendor == X86_VENDOR_AMD) {
+ *min = pmc_amd_range[index].min;
+ *max = pmc_amd_range[index].max;
+ } else
+ err = -EINVAL;
+ break;
+ default:
+ err = -ENOSYS;
+ }
+
+ return err;
+}
+
+static int get_msr_range_count(unsigned flag, unsigned model)
+{
+ int index = 0;
+
+ model >>= 16;
+ switch (flag) {
+ case MSR_ALL:
+ if (model == X86_VENDOR_INTEL)
+ index = ARRAY_SIZE(msr_intel_range);
+ else if (model == X86_VENDOR_AMD)
+ index = ARRAY_SIZE(msr_amd_range);
+ break;
+ case MSR_PMC:
+ if (model == X86_VENDOR_INTEL)
+ index = ARRAY_SIZE(pmc_intel_range);
+ else if (model == X86_VENDOR_AMD)
+ index = ARRAY_SIZE(pmc_amd_range);
+ break;
+ }
+
+ return index;
+}
+
+static void print_intel_msr(struct seq_file *seq, unsigned int cpu,
+ unsigned flag, unsigned model)
+{
+ int i, range;
+ u32 low, high;
+ unsigned msr, msr_min, msr_max;
+
+ range = get_msr_range_count(flag, model);
+ seq_printf(seq, "processor: %u model 0x%x\n", cpu, model);
+
+ for (i = 0; i < range; i++) {
+ if (get_msr_range(&msr_min, &msr_max, i, flag, model))
+ continue;
+ for (msr = msr_min; msr < msr_max; msr++) {
+ if (rdmsr_safe_on_cpu(cpu, msr, &low, &high))
+ continue;
+ if (seq)
+ seq_printf(seq, " MSR_%08x: %08x_%08x\n",
+ msr, high, low);
+ else
+ printk(KERN_INFO " MSR_%08x: %08x_%08x\n",
+ msr, high, low);
+ }
+ }
+}
+
+static void print_amd_msr(struct seq_file *seq, unsigned flag, unsigned model)
+{
+ int i, range;
+ u64 val;
+ unsigned msr, msr_min, msr_max;
+
+ range = get_msr_range_count(flag, model);
+ seq_printf(seq, "processor: 0 model 0x%x\n", model);
+
+ for (i = 0; i < range; i++) {
+ if (get_msr_range(&msr_min, &msr_max, i, flag, model))
+ continue;
+ for (msr = msr_min; msr < msr_max; msr++) {
+ if (rdmsrl_amd_safe(msr, &val))
+ continue;
+ if (seq)
+ seq_printf(seq, " MSR_%08x: %016llx\n",
+ msr, val);
+ else
+ printk(KERN_INFO " MSR_%08x: %016llx\n",
+ msr, val);
+ }
+ }
+}
+
+static int msr_basic_show(struct seq_file *seq, void *v, unsigned flag)
+{
+ unsigned model;
+ struct cpuinfo_x86 *c = v;
+
+#ifdef CONFIG_SMP
+ /* We are only interested for core_id 0 */
+ if (c->cpu_core_id)
+ return 0;
+#endif
+ model = ((c->x86_vendor << 16) | (c->x86 << 8) | (c->x86_model));
+ if ((c->x86_max_cores * smp_num_siblings > 1) &&
+ (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL))
+ print_intel_msr(seq, c->phys_proc_id, flag, model);
+ else
+ print_amd_msr(seq, flag, model);
+
+
+ seq_printf(seq, "\n");
+
+ return 0;
+}
+
+static int msr_seq_show(struct seq_file *seq, void *v)
+{
+ return msr_basic_show(seq, v, MSR_ALL);
+}
+
+static int pmc_seq_show(struct seq_file *seq, void *v)
+{
+ return msr_basic_show(seq, v, MSR_PMC);
+}
+
+static void *msr_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ struct cpuinfo_x86 *c = NULL;
+
+ if (*pos == 0) /* just in case, cpu 0 is not the first */
+ *pos = first_cpu(cpu_online_map);
+ else
+ *pos = next_cpu_nr(*pos - 1, cpu_online_map);
+
+ if ((*pos) < nr_cpu_ids)
+ c = &cpu_data(*pos);
+
+ return c;
+}
+
+static void *msr_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ (*pos)++;
+
+ return msr_seq_start(seq, pos);
+}
+
+static void msr_seq_stop(struct seq_file *seq, void *v)
+{
+}
+
+static const struct seq_operations msr_seq_ops = {
+ .start = msr_seq_start,
+ .next = msr_seq_next,
+ .stop = msr_seq_stop,
+ .show = msr_seq_show,
+};
+
+static int msr_seq_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &msr_seq_ops);
+}
+
+static const struct file_operations msr_fops = {
+ .open = msr_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+/* Performance monitioring MSRs */
+static const struct seq_operations pmc_seq_ops = {
+ .start = msr_seq_start,
+ .next = msr_seq_next,
+ .stop = msr_seq_stop,
+ .show = pmc_seq_show,
+};
+
+static int pmc_seq_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &pmc_seq_ops);
+}
+
+static const struct file_operations pmc_fops = {
+ .open = pmc_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static struct dentry *msr_file, *pmc_file, *msr_dir;
+static int __init msr_debug_init(void)
+{
+ struct cpuinfo_x86 *cpu = &cpu_data(0);
+
+ if (!cpu_has(cpu, X86_FEATURE_MSR))
+ return -ENODEV;
+
+ msr_dir = debugfs_create_dir("msr", arch_debugfs_dir);
+
+ msr_file = debugfs_create_file("msr", S_IRUGO, msr_dir,
+ NULL, &msr_fops);
+ pmc_file = debugfs_create_file("pmc", S_IRUGO, msr_dir,
+ NULL, &pmc_fops);
+
+ return 0;
+}
+
+static void __exit msr_debug_exit(void)
+{
+ if (msr_file)
+ debugfs_remove(msr_file);
+ if (pmc_file)
+ debugfs_remove(pmc_file);
+ if (msr_dir)
+ debugfs_remove(msr_dir);
+}
+
+module_init(msr_debug_init);
+module_exit(msr_debug_exit);
+
+MODULE_AUTHOR("Jaswinder Singh Rajput");
+MODULE_DESCRIPTION("MSR debug module");
+MODULE_LICENSE("GPL");


2009-03-02 17:26:15

by Jaswinder Singh Rajput

[permalink] [raw]
Subject: Re: [git-pull -tip] x86: msr architecture debug code

On Mon, 2009-03-02 at 21:12 +0530, Jaswinder Singh Rajput wrote:
> The following changes since commit 1d10914bf2c8a1164aef6c341e6c3518a91b8374:
> Ingo Molnar (1):
> Merge branch 'core/percpu'
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/jaswinder/linux-2.6-tip-cpu.git master

Here is new request-pull with minor cleanup:

The following changes since commit 1d10914bf2c8a1164aef6c341e6c3518a91b8374:
Ingo Molnar (1):
Merge branch 'core/percpu'

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/jaswinder/linux-2.6-tip-cpu.git master

Jaswinder Singh Rajput (1):
x86: msr architecture debug code

arch/x86/include/asm/msr_debug.h | 54 ++++++
arch/x86/kernel/cpu/Makefile | 2 +-
arch/x86/kernel/cpu/msr_debug.c | 358 ++++++++++++++++++++++++++++++++++++++
3 files changed, 413 insertions(+), 1 deletions(-)
create mode 100755 arch/x86/include/asm/msr_debug.h
create mode 100755 arch/x86/kernel/cpu/msr_debug.c

Complete diff:
diff --git a/arch/x86/include/asm/msr_debug.h b/arch/x86/include/asm/msr_debug.h
new file mode 100755
index 0000000..edb3bb3
--- /dev/null
+++ b/arch/x86/include/asm/msr_debug.h
@@ -0,0 +1,54 @@
+#ifndef _ASM_X86_MSR_DEBUG_H
+#define _ASM_X86_MSR_DEBUG_H
+
+/*
+ * Model Specific Registers (MSR) x86 architecture debug
+ *
+ * Copyright(C) 2009 Jaswinder Singh Rajput
+ */
+
+#define MSR_ALL 0
+#define MSR_PMC 1 /* Performance Monitor counters */
+
+/* DisplayFamily_DisplayModel Processor Families/Processor Number Series */
+/* -------------------------- ------------------------------------------ */
+/* 05_01, 05_02, 05_04 Pentium, Pentium with MMX */
+#define MSR_INTEL_PENTIUM (1 << 0)
+
+/* 06_01 Pentium Pro */
+/* 06_03, 06_05 Pentium II Xeon, Pentium II */
+/* 06_07, 06_08, 06_0A, 06_0B Pentium III Xeon, Pentum III */
+#define MSR_INTEL_P6 (1 << 1)
+
+/* 06_09, 060D Pentium M */
+#define MSR_INTEL_PENTIUM_M (1 << 4)
+
+/* 06_0E Core Duo, Core Solo */
+#define MSR_INTEL_CORE (1 << 5)
+
+/* 06_0F Xeon 3000, 3200, 5100, 5300, 7300 series,
+ Core 2 Quad, Core 2 Extreme, Core 2 Duo,
+ Pentium dual-core */
+/* 06_17 Xeon 5200, 5400 series, Core 2 Quad Q9650 */
+#define MSR_INTEL_CORE_2 (1 << 6)
+
+/* 06_1C Atom */
+#define MSR_INTEL_ATOM (1 << 7)
+
+/* 0F_00, 0F_01, 0F_02 Xeon, Xeon MP, Pentium 4 */
+/* 0F_03, 0F_04 Xeon, Xeon MP, Pentium 4, Pentium D */
+#define MSR_INTEL_XEON (1 << 17)
+
+/* 0F_06 Xeon 7100, 5000 Series, Xeon MP,
+ Pentium 4, Pentium D */
+#define MSR_INTEL_XEON_MP (1 << 18)
+
+#define MSR_CPU_ALL (~0)
+
+struct msr_debug_range {
+ unsigned min;
+ unsigned max;
+ unsigned model;
+};
+
+#endif /* _ASM_X86_MSR_DEBUG_H */
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index c381330..b2452f3 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -8,7 +8,7 @@ CFLAGS_REMOVE_common.o = -pg
endif

obj-y := intel_cacheinfo.o addon_cpuid_features.o
-obj-y += proc.o capflags.o powerflags.o common.o
+obj-y += proc.o capflags.o powerflags.o common.o msr_debug.o
obj-y += vmware.o hypervisor.o

obj-$(CONFIG_X86_32) += bugs.o cmpxchg.o
diff --git a/arch/x86/kernel/cpu/msr_debug.c b/arch/x86/kernel/cpu/msr_debug.c
new file mode 100755
index 0000000..787cc82
--- /dev/null
+++ b/arch/x86/kernel/cpu/msr_debug.c
@@ -0,0 +1,358 @@
+/*
+ * Model Specific Registers (MSR) x86 architecture debug code
+ *
+ * Copyright(C) 2009 Jaswinder Singh Rajput
+ *
+ * For licencing details see kernel-base/COPYING
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <asm/msr_debug.h>
+
+/* Intel MSRs Range */
+static struct msr_debug_range msr_intel_range[] = {
+ { 0x00000000, 0x000006d0, MSR_CPU_ALL },
+ { 0x000107CC, 0x000107D4, MSR_INTEL_XEON_MP },
+};
+
+static struct msr_debug_range pmc_intel_range[] = {
+ { 0x00000010, 0x00000011, MSR_CPU_ALL }, /* TSC */
+ { 0x00000011, 0x00000014, MSR_INTEL_PENTIUM }, /* CESR, CTR */
+ { 0x0000001B, 0x0000001C, MSR_CPU_ALL }, /* APIC */
+ { 0x000000C1, 0x000000C3, MSR_INTEL_P6 }, /* PerfCtr */
+ { 0x00000186, 0x00000188, MSR_INTEL_P6 | MSR_INTEL_ATOM |
+ MSR_INTEL_CORE_2 }, /* EvtSel */
+ { 0x000001A0, 0x000001A1, MSR_CPU_ALL }, /* Misc Feature */
+ { 0x00000300, 0x00000312, MSR_INTEL_XEON }, /* Counter */
+ { 0x00000309, 0x0000030C, MSR_INTEL_P6 | MSR_INTEL_ATOM |
+ MSR_INTEL_CORE_2 }, /* Fixed */
+ { 0x00000360, 0x00000372, MSR_INTEL_XEON }, /* CCCR */
+ { 0x0000038D, 0x00000391, MSR_INTEL_P6 | MSR_INTEL_ATOM |
+ MSR_INTEL_CORE_2 }, /* Fixed & Global */
+ { 0x00000390, 0x00000391, MSR_INTEL_P6 | MSR_INTEL_ATOM |
+ MSR_INTEL_CORE_2 }, /* OVF */
+ { 0x000003A0, 0x000003F3, MSR_INTEL_XEON }, /* ESCR */
+ { 0x000003F1, 0x000003F2, MSR_INTEL_P6 | MSR_INTEL_ATOM |
+ MSR_INTEL_CORE_2 }, /* PEBS */
+ { 0x000107CC, 0x000107D4, MSR_INTEL_XEON_MP },
+};
+
+/* AMD MSRs Range */
+static struct msr_debug_range msr_amd_range[] = {
+ { 0x00000000, 0x00000418, MSR_CPU_ALL},
+ { 0xc0000000, 0xc000040b, MSR_CPU_ALL},
+ { 0xc0010000, 0xc0010142, MSR_CPU_ALL},
+ { 0xc0011000, 0xc001103b, MSR_CPU_ALL},
+};
+
+static struct msr_debug_range pmc_amd_range[] = {
+ { 0x00000010, 0x00000011, MSR_CPU_ALL }, /* TSC */
+ { 0x0000001B, 0x0000001C, MSR_CPU_ALL }, /* APIC */
+ { 0xc0010000, 0xc0010008, MSR_CPU_ALL},
+};
+
+
+static int get_msr_intel_bit(unsigned model)
+{
+ int ret = 0;
+
+ switch (model) {
+ case 0x0501:
+ case 0x0502:
+ case 0x0504:
+ ret = MSR_INTEL_PENTIUM;
+ break;
+ case 0x0601:
+ case 0x0603:
+ case 0x0605:
+ case 0x0607:
+ case 0x0608:
+ case 0x060A:
+ case 0x060B:
+ ret = MSR_INTEL_P6;
+ break;
+ case 0x0609:
+ case 0x060D:
+ ret = MSR_INTEL_PENTIUM_M;
+ break;
+ case 0x060E:
+ ret = MSR_INTEL_CORE;
+ break;
+ case 0x060F:
+ case 0x0617:
+ ret = MSR_INTEL_CORE_2;
+ break;
+ case 0x061C:
+ ret = MSR_INTEL_ATOM;
+ break;
+ case 0x0F00:
+ case 0x0F01:
+ case 0x0F02:
+ case 0x0F03:
+ case 0x0F04:
+ ret = MSR_INTEL_XEON;
+ break;
+ case 0x0F06:
+ ret = MSR_INTEL_XEON_MP;
+ break;
+ }
+
+ return ret;
+}
+
+static int get_msr_cpu_bit(unsigned model)
+{
+ unsigned vendor;
+
+ vendor = model >> 16;
+ if (vendor == X86_VENDOR_INTEL)
+ return get_msr_intel_bit(model & 0xffff);
+ else
+ return 0;
+}
+
+static unsigned get_msr_range(unsigned *min, unsigned *max, int index,
+ unsigned flag, unsigned model)
+{
+ unsigned vendor, cpu_bit;
+
+ vendor = model >> 16;
+ cpu_bit = get_msr_cpu_bit(model);
+ *max = 0;
+ switch (flag) {
+ case MSR_ALL:
+ if (vendor == X86_VENDOR_INTEL) {
+ if (msr_intel_range[index].model & cpu_bit) {
+ *min = msr_intel_range[index].min;
+ *max = msr_intel_range[index].max;
+ }
+ } else if (vendor == X86_VENDOR_AMD) {
+ *min = msr_amd_range[index].min;
+ *max = msr_amd_range[index].max;
+ }
+ break;
+ case MSR_PMC:
+ if (vendor == X86_VENDOR_INTEL) {
+ if (pmc_intel_range[index].model & cpu_bit) {
+ *min = pmc_intel_range[index].min;
+ *max = pmc_intel_range[index].max;
+ }
+ } else if (vendor == X86_VENDOR_AMD) {
+ *min = pmc_amd_range[index].min;
+ *max = pmc_amd_range[index].max;
+ }
+ break;
+ }
+
+ return *max;
+}
+
+static int get_msr_range_count(unsigned flag, unsigned model)
+{
+ int index = 0;
+
+ model >>= 16;
+ switch (flag) {
+ case MSR_ALL:
+ if (model == X86_VENDOR_INTEL)
+ index = ARRAY_SIZE(msr_intel_range);
+ else if (model == X86_VENDOR_AMD)
+ index = ARRAY_SIZE(msr_amd_range);
+ break;
+ case MSR_PMC:
+ if (model == X86_VENDOR_INTEL)
+ index = ARRAY_SIZE(pmc_intel_range);
+ else if (model == X86_VENDOR_AMD)
+ index = ARRAY_SIZE(pmc_amd_range);
+ break;
+ }
+
+ return index;
+}
+
+static void print_intel_msr(struct seq_file *seq, unsigned int cpu,
+ unsigned flag, unsigned model)
+{
+ int i, range;
+ u32 low, high;
+ unsigned msr, msr_min, msr_max;
+
+ range = get_msr_range_count(flag, model);
+ seq_printf(seq, "processor: %u model 0x%x\n", cpu, model);
+
+ for (i = 0; i < range; i++) {
+ if (!get_msr_range(&msr_min, &msr_max, i, flag, model))
+ continue;
+ for (msr = msr_min; msr < msr_max; msr++) {
+ if (rdmsr_safe_on_cpu(cpu, msr, &low, &high))
+ continue;
+ if (seq)
+ seq_printf(seq, " MSR_%08x: %08x_%08x\n",
+ msr, high, low);
+ else
+ printk(KERN_INFO " MSR_%08x: %08x_%08x\n",
+ msr, high, low);
+ }
+ }
+}
+
+static void print_amd_msr(struct seq_file *seq, unsigned flag, unsigned model)
+{
+ int i, range;
+ u64 val;
+ unsigned msr, msr_min, msr_max;
+
+ range = get_msr_range_count(flag, model);
+ seq_printf(seq, "processor: 0 model 0x%x\n", model);
+
+ for (i = 0; i < range; i++) {
+ if (!get_msr_range(&msr_min, &msr_max, i, flag, model))
+ continue;
+ for (msr = msr_min; msr < msr_max; msr++) {
+ if (rdmsrl_amd_safe(msr, &val))
+ continue;
+ if (seq)
+ seq_printf(seq, " MSR_%08x: %016llx\n",
+ msr, val);
+ else
+ printk(KERN_INFO " MSR_%08x: %016llx\n",
+ msr, val);
+ }
+ }
+}
+
+static int msr_basic_show(struct seq_file *seq, void *v, unsigned flag)
+{
+ unsigned model;
+ struct cpuinfo_x86 *c = v;
+
+#ifdef CONFIG_SMP
+ /* We are only interested for core_id 0 */
+ if (c->cpu_core_id)
+ return 0;
+#endif
+ model = ((c->x86_vendor << 16) | (c->x86 << 8) | (c->x86_model));
+ if ((c->x86_max_cores * smp_num_siblings > 1) &&
+ (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL))
+ print_intel_msr(seq, c->phys_proc_id, flag, model);
+ else
+ print_amd_msr(seq, flag, model);
+
+
+ seq_printf(seq, "\n");
+
+ return 0;
+}
+
+static int msr_seq_show(struct seq_file *seq, void *v)
+{
+ return msr_basic_show(seq, v, MSR_ALL);
+}
+
+static int pmc_seq_show(struct seq_file *seq, void *v)
+{
+ return msr_basic_show(seq, v, MSR_PMC);
+}
+
+static void *msr_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ struct cpuinfo_x86 *c = NULL;
+
+ if (*pos == 0) /* just in case, cpu 0 is not the first */
+ *pos = first_cpu(cpu_online_map);
+ else
+ *pos = next_cpu_nr(*pos - 1, cpu_online_map);
+
+ if ((*pos) < nr_cpu_ids)
+ c = &cpu_data(*pos);
+
+ return c;
+}
+
+static void *msr_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ (*pos)++;
+
+ return msr_seq_start(seq, pos);
+}
+
+static void msr_seq_stop(struct seq_file *seq, void *v)
+{
+}
+
+static const struct seq_operations msr_seq_ops = {
+ .start = msr_seq_start,
+ .next = msr_seq_next,
+ .stop = msr_seq_stop,
+ .show = msr_seq_show,
+};
+
+static int msr_seq_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &msr_seq_ops);
+}
+
+static const struct file_operations msr_fops = {
+ .open = msr_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+/* Performance monitioring MSRs */
+static const struct seq_operations pmc_seq_ops = {
+ .start = msr_seq_start,
+ .next = msr_seq_next,
+ .stop = msr_seq_stop,
+ .show = pmc_seq_show,
+};
+
+static int pmc_seq_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &pmc_seq_ops);
+}
+
+static const struct file_operations pmc_fops = {
+ .open = pmc_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static struct dentry *msr_file, *pmc_file, *msr_dir;
+static int __init msr_debug_init(void)
+{
+ struct cpuinfo_x86 *cpu = &cpu_data(0);
+
+ if (!cpu_has(cpu, X86_FEATURE_MSR))
+ return -ENODEV;
+
+ msr_dir = debugfs_create_dir("msr", arch_debugfs_dir);
+
+ msr_file = debugfs_create_file("msr", S_IRUGO, msr_dir,
+ NULL, &msr_fops);
+ pmc_file = debugfs_create_file("pmc", S_IRUGO, msr_dir,
+ NULL, &pmc_fops);
+
+ return 0;
+}
+
+static void __exit msr_debug_exit(void)
+{
+ if (msr_file)
+ debugfs_remove(msr_file);
+ if (pmc_file)
+ debugfs_remove(pmc_file);
+ if (msr_dir)
+ debugfs_remove(msr_dir);
+}
+
+module_init(msr_debug_init);
+module_exit(msr_debug_exit);
+
+MODULE_AUTHOR("Jaswinder Singh Rajput");
+MODULE_DESCRIPTION("MSR debug module");
+MODULE_LICENSE("GPL");

2009-03-02 20:55:01

by Ingo Molnar

[permalink] [raw]
Subject: Re: [git-pull -tip] x86: msr architecture debug code


* Jaswinder Singh Rajput <[email protected]> wrote:

> The following changes since commit 1d10914bf2c8a1164aef6c341e6c3518a91b8374:
> Ingo Molnar (1):
> Merge branch 'core/percpu'
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/jaswinder/linux-2.6-tip-cpu.git master
>
> Jaswinder Singh Rajput (1):
> x86: msr architecture debug code
>
> arch/x86/include/asm/msr_debug.h | 56 ++++++
> arch/x86/kernel/cpu/Makefile | 2 +-
> arch/x86/kernel/cpu/msr_debug.c | 362 ++++++++++++++++++++++++++++++++++++++
> 3 files changed, 419 insertions(+), 1 deletions(-)
> create mode 100755 arch/x86/include/asm/msr_debug.h
> create mode 100755 arch/x86/kernel/cpu/msr_debug.c
>
> Complete diff:
> diff --git a/arch/x86/include/asm/msr_debug.h b/arch/x86/include/asm/msr_debug.h
> new file mode 100755
> index 0000000..ddc4fe5
> --- /dev/null
> +++ b/arch/x86/include/asm/msr_debug.h
> @@ -0,0 +1,56 @@
> +#ifndef _ASM_X86_MSR_DEBUG_H
> +#define _ASM_X86_MSR_DEBUG_H
> +
> +/*
> + * Model Specific Registers (MSR) x86 architecture debug
> + *
> + * Copyright(C) 2009 Jaswinder Singh Rajput
> + */
> +
> +#define MSR_ALL 0
> +#define MSR_PMC 1 /* Performance Monitor counters */
> +
> +struct msr_debug_range {
> + unsigned min;
> + unsigned max;
> + unsigned model;
> +};

Please vertical-align structure field definitions, like you see
we do it elsewhere in the x86 code.

> +
> +/* Intel MSRs Range */
> +
> +/* DisplayFamily_DisplayModel Processor Families/Processor Number Series */
> +/* -------------------------- ------------------------------------------ */
> +/* 05_01, 05_02, 05_04 Pentium, Pentium with MMX */
> +#define MSR_INTEL_PENTIUM (1 << 0)
> +
> +/* 06_01 Pentium Pro */
> +/* 06_03, 06_05 Pentium II Xeon, Pentium II */
> +/* 06_07, 06_08, 06_0A, 06_0B Pentium III Xeon, Pentum III */
> +#define MSR_INTEL_P6 (1 << 1)
> +
> +/* 06_09, 060D Pentium M */
> +#define MSR_INTEL_PENTIUM_M (1 << 4)
> +
> +/* 06_0E Core Duo, Core Solo */
> +#define MSR_INTEL_CORE (1 << 5)
> +
> +/* 06_0F Xeon 3000, 3200, 5100, 5300, 7300 series,
> + Core 2 Quad, Core 2 Extreme, Core 2 Duo,
> + Pentium dual-core */
> +/* 06_17 Xeon 5200, 5400 series, Core 2 Quad Q9650 */
> +#define MSR_INTEL_CORE_2 (1 << 6)
> +
> +/* 06_1C Atom */
> +#define MSR_INTEL_ATOM (1 << 7)
> +
> +/* 0F_00, 0F_01, 0F_02 Xeon, Xeon MP, Pentium 4 */
> +/* 0F_03, 0F_04 Xeon, Xeon MP, Pentium 4, Pentium D */
> +#define MSR_INTEL_XEON (1 << 17)
> +
> +/* 0F_06 Xeon 7100, 5000 Series, Xeon MP,
> + Pentium 4, Pentium D */
> +#define MSR_INTEL_XEON_MP (1 << 18)
> +
> +#define MSR_CPU_ALL (~0)
> +
> +#endif /* _ASM_X86_MSR_DEBUG_H */
> diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
> index c381330..b2452f3 100644
> --- a/arch/x86/kernel/cpu/Makefile
> +++ b/arch/x86/kernel/cpu/Makefile
> @@ -8,7 +8,7 @@ CFLAGS_REMOVE_common.o = -pg
> endif
>
> obj-y := intel_cacheinfo.o addon_cpuid_features.o
> -obj-y += proc.o capflags.o powerflags.o common.o
> +obj-y += proc.o capflags.o powerflags.o common.o msr_debug.o
> obj-y += vmware.o hypervisor.o
>
> obj-$(CONFIG_X86_32) += bugs.o cmpxchg.o
> diff --git a/arch/x86/kernel/cpu/msr_debug.c b/arch/x86/kernel/cpu/msr_debug.c
> new file mode 100755
> index 0000000..505f53f
> --- /dev/null
> +++ b/arch/x86/kernel/cpu/msr_debug.c
> @@ -0,0 +1,362 @@
> +/*
> + * Model Specific Registers (MSR) x86 architecture debug code
> + *
> + * Copyright(C) 2009 Jaswinder Singh Rajput
> + *
> + * For licencing details see kernel-base/COPYING
> + */
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/debugfs.h>
> +#include <linux/seq_file.h>
> +#include <asm/msr_debug.h>

Please have a good look at what the standard include files
section look like - for example in
arch/x86/kernel/cpu/perf_counter.c or in arch/x86/mm/fault.c.
Please use that same ordering of the lines here too.

> +static struct msr_debug_range msr_intel_range[] = {
> + { 0x00000000, 0x000006d0, MSR_CPU_ALL },
> + { 0x000107CC, 0x000107D4, MSR_INTEL_XEON_MP },
> +};
> +
> +static struct msr_debug_range pmc_intel_range[] = {
> + { 0x00000010, 0x00000011, MSR_CPU_ALL }, /* TSC */
> + { 0x00000011, 0x00000014, MSR_INTEL_PENTIUM }, /* CESR, CTR */
> + { 0x0000001B, 0x0000001C, MSR_CPU_ALL }, /* APIC */
> + { 0x000000C1, 0x000000C3, MSR_INTEL_P6 }, /* PerfCtr */
> + { 0x00000186, 0x00000188, MSR_INTEL_P6 | MSR_INTEL_ATOM |
> + MSR_INTEL_CORE_2 }, /* EvtSel */
> + { 0x000001A0, 0x000001A1, MSR_CPU_ALL }, /* Misc Feature */
> + { 0x00000300, 0x00000312, MSR_INTEL_XEON }, /* Counter */
> + { 0x00000309, 0x0000030C, MSR_INTEL_P6 | MSR_INTEL_ATOM |
> + MSR_INTEL_CORE_2 }, /* Fixed */
> + { 0x00000360, 0x00000372, MSR_INTEL_XEON }, /* CCCR */
> + { 0x0000038D, 0x00000391, MSR_INTEL_P6 | MSR_INTEL_ATOM |
> + MSR_INTEL_CORE_2 }, /* Fixed & Global */
> + { 0x00000390, 0x00000391, MSR_INTEL_P6 | MSR_INTEL_ATOM |
> + MSR_INTEL_CORE_2 }, /* OVF */
> + { 0x000003A0, 0x000003F3, MSR_INTEL_XEON }, /* ESCR */
> + { 0x000003F1, 0x000003F2, MSR_INTEL_P6 | MSR_INTEL_ATOM |
> + MSR_INTEL_CORE_2 }, /* PEBS */
> + { 0x000107CC, 0x000107D4, MSR_INTEL_XEON_MP },
> +};
> +
> +/* AMD MSRs Range */
> +static struct msr_debug_range msr_amd_range[] = {
> + { 0x00000000, 0x00000418, MSR_CPU_ALL},
> + { 0xc0000000, 0xc000040b, MSR_CPU_ALL},
> + { 0xc0010000, 0xc0010142, MSR_CPU_ALL},
> + { 0xc0011000, 0xc001103b, MSR_CPU_ALL},
> +};
> +
> +static struct msr_debug_range pmc_amd_range[] = {
> + { 0x00000010, 0x00000011, MSR_CPU_ALL }, /* TSC */
> + { 0x0000001B, 0x0000001C, MSR_CPU_ALL }, /* APIC */
> + { 0xc0010000, 0xc0010008, MSR_CPU_ALL},
> +};
> +
> +
> +static int get_msr_intel_bit(unsigned model)
> +{
> + int ret = 0;
> +
> + switch (model) {
> + case 0x0501:
> + case 0x0502:
> + case 0x0504:
> + ret = MSR_INTEL_PENTIUM;
> + break;
> + case 0x0601:
> + case 0x0603:
> + case 0x0605:
> + case 0x0607:
> + case 0x0608:
> + case 0x060A:
> + case 0x060B:
> + ret = MSR_INTEL_P6;
> + break;
> + case 0x0609:
> + case 0x060D:
> + ret = MSR_INTEL_PENTIUM_M;
> + break;
> + case 0x060E:
> + ret = MSR_INTEL_CORE;
> + break;
> + case 0x060F:
> + case 0x0617:
> + ret = MSR_INTEL_CORE_2;
> + break;
> + case 0x061C:
> + ret = MSR_INTEL_ATOM;
> + break;
> + case 0x0F00:
> + case 0x0F01:
> + case 0x0F02:
> + case 0x0F03:
> + case 0x0F04:
> + ret = MSR_INTEL_XEON;
> + break;
> + case 0x0F06:
> + ret = MSR_INTEL_XEON_MP;
> + break;
> + }

all these magic constants open-coded look a bit ugly. Can it be
done cleaner?

> +
> + return ret;
> +}
> +
> +static int get_msr_cpu_bit(unsigned model)
> +{
> + unsigned vendor;
> +
> + vendor = model >> 16;
> + if (vendor == X86_VENDOR_INTEL)
> + return get_msr_intel_bit(model & 0xffff);
> + else
> + return 0;
> +}
> +
> +static int get_msr_range(unsigned *min, unsigned *max, int index,
> + unsigned flag, unsigned model)
> +{
> + unsigned vendor, cpu_bit;
> + int err = 0;
> +
> + vendor = model >> 16;
> + cpu_bit = get_msr_cpu_bit(model);
> + switch (flag) {
> + case MSR_ALL:
> + if (vendor == 0) {
> + if (msr_intel_range[index].model & cpu_bit) {
> + *min = msr_intel_range[index].min;
> + *max = msr_intel_range[index].max;
> + } else
> + err = -EINVAL;
> + } else if (vendor == X86_VENDOR_AMD) {
> + *min = msr_amd_range[index].min;
> + *max = msr_amd_range[index].max;
> + }
> + break;
> + case MSR_PMC:
> + if (vendor == 0) {
> + if (pmc_intel_range[index].model & cpu_bit) {
> + *min = pmc_intel_range[index].min;
> + *max = pmc_intel_range[index].max;
> + } else
> + err = -EINVAL;
> + } else if (vendor == X86_VENDOR_AMD) {
> + *min = pmc_amd_range[index].min;
> + *max = pmc_amd_range[index].max;
> + } else
> + err = -EINVAL;
> + break;
> + default:
> + err = -ENOSYS;
> + }
> +
> + return err;
> +}
> +
> +static int get_msr_range_count(unsigned flag, unsigned model)
> +{
> + int index = 0;
> +
> + model >>= 16;
> + switch (flag) {
> + case MSR_ALL:
> + if (model == X86_VENDOR_INTEL)
> + index = ARRAY_SIZE(msr_intel_range);
> + else if (model == X86_VENDOR_AMD)
> + index = ARRAY_SIZE(msr_amd_range);
> + break;
> + case MSR_PMC:
> + if (model == X86_VENDOR_INTEL)
> + index = ARRAY_SIZE(pmc_intel_range);
> + else if (model == X86_VENDOR_AMD)
> + index = ARRAY_SIZE(pmc_amd_range);
> + break;
> + }
> +
> + return index;
> +}
> +
> +static void print_intel_msr(struct seq_file *seq, unsigned int cpu,
> + unsigned flag, unsigned model)
> +{
> + int i, range;
> + u32 low, high;
> + unsigned msr, msr_min, msr_max;
> +
> + range = get_msr_range_count(flag, model);
> + seq_printf(seq, "processor: %u model 0x%x\n", cpu, model);
> +
> + for (i = 0; i < range; i++) {
> + if (get_msr_range(&msr_min, &msr_max, i, flag, model))
> + continue;
> + for (msr = msr_min; msr < msr_max; msr++) {
> + if (rdmsr_safe_on_cpu(cpu, msr, &low, &high))
> + continue;
> + if (seq)
> + seq_printf(seq, " MSR_%08x: %08x_%08x\n",
> + msr, high, low);
> + else
> + printk(KERN_INFO " MSR_%08x: %08x_%08x\n",
> + msr, high, low);
> + }
> + }
> +}
> +
> +static void print_amd_msr(struct seq_file *seq, unsigned flag, unsigned model)
> +{
> + int i, range;
> + u64 val;
> + unsigned msr, msr_min, msr_max;
> +
> + range = get_msr_range_count(flag, model);
> + seq_printf(seq, "processor: 0 model 0x%x\n", model);
> +
> + for (i = 0; i < range; i++) {
> + if (get_msr_range(&msr_min, &msr_max, i, flag, model))
> + continue;
> + for (msr = msr_min; msr < msr_max; msr++) {
> + if (rdmsrl_amd_safe(msr, &val))
> + continue;
> + if (seq)
> + seq_printf(seq, " MSR_%08x: %016llx\n",
> + msr, val);
> + else
> + printk(KERN_INFO " MSR_%08x: %016llx\n",
> + msr, val);
> + }
> + }
> +}
> +
> +static int msr_basic_show(struct seq_file *seq, void *v, unsigned flag)
> +{
> + unsigned model;
> + struct cpuinfo_x86 *c = v;
> +
> +#ifdef CONFIG_SMP
> + /* We are only interested for core_id 0 */
> + if (c->cpu_core_id)
> + return 0;
> +#endif
> + model = ((c->x86_vendor << 16) | (c->x86 << 8) | (c->x86_model));
> + if ((c->x86_max_cores * smp_num_siblings > 1) &&
> + (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL))
> + print_intel_msr(seq, c->phys_proc_id, flag, model);
> + else
> + print_amd_msr(seq, flag, model);
> +
> +
> + seq_printf(seq, "\n");
> +
> + return 0;
> +}
> +
> +static int msr_seq_show(struct seq_file *seq, void *v)
> +{
> + return msr_basic_show(seq, v, MSR_ALL);
> +}
> +
> +static int pmc_seq_show(struct seq_file *seq, void *v)
> +{
> + return msr_basic_show(seq, v, MSR_PMC);
> +}
> +
> +static void *msr_seq_start(struct seq_file *seq, loff_t *pos)
> +{
> + struct cpuinfo_x86 *c = NULL;
> +
> + if (*pos == 0) /* just in case, cpu 0 is not the first */
> + *pos = first_cpu(cpu_online_map);
> + else
> + *pos = next_cpu_nr(*pos - 1, cpu_online_map);
> +
> + if ((*pos) < nr_cpu_ids)
> + c = &cpu_data(*pos);
> +
> + return c;
> +}
> +
> +static void *msr_seq_next(struct seq_file *seq, void *v, loff_t *pos)
> +{
> + (*pos)++;
> +
> + return msr_seq_start(seq, pos);
> +}
> +
> +static void msr_seq_stop(struct seq_file *seq, void *v)
> +{
> +}
> +
> +static const struct seq_operations msr_seq_ops = {
> + .start = msr_seq_start,
> + .next = msr_seq_next,
> + .stop = msr_seq_stop,
> + .show = msr_seq_show,
> +};
> +
> +static int msr_seq_open(struct inode *inode, struct file *file)
> +{
> + return seq_open(file, &msr_seq_ops);
> +}
> +
> +static const struct file_operations msr_fops = {
> + .open = msr_seq_open,
> + .read = seq_read,
> + .llseek = seq_lseek,
> + .release = seq_release,
> +};
> +
> +/* Performance monitioring MSRs */
> +static const struct seq_operations pmc_seq_ops = {
> + .start = msr_seq_start,
> + .next = msr_seq_next,
> + .stop = msr_seq_stop,
> + .show = pmc_seq_show,
> +};
> +
> +static int pmc_seq_open(struct inode *inode, struct file *file)
> +{
> + return seq_open(file, &pmc_seq_ops);
> +}
> +
> +static const struct file_operations pmc_fops = {
> + .open = pmc_seq_open,
> + .read = seq_read,
> + .llseek = seq_lseek,
> + .release = seq_release,
> +};

Check how structure initializations are done in other places of
the x86 tree - for example perf_counters.c. Apply that style
here too please.

> +
> +static struct dentry *msr_file, *pmc_file, *msr_dir;
> +static int __init msr_debug_init(void)

missing newline after static variables.

> +{
> + struct cpuinfo_x86 *cpu = &cpu_data(0);
> +
> + if (!cpu_has(cpu, X86_FEATURE_MSR))
> + return -ENODEV;
> +
> + msr_dir = debugfs_create_dir("msr", arch_debugfs_dir);
> +
> + msr_file = debugfs_create_file("msr", S_IRUGO, msr_dir,
> + NULL, &msr_fops);
> + pmc_file = debugfs_create_file("pmc", S_IRUGO, msr_dir,
> + NULL, &pmc_fops);

I think it would be possible to have a much more intuitive file
layout under /debug/x86/msr/ than these two /debug/x86/msr/msr
and /debug/x86/msr/pmc files.

Firstly, it should move one level deeper, to /debug/x86/cpu/msr/
- because the MSR is really a property of the CPU, and there are
other properties of the CPU we might want to expose in the
future.

Secondly, the picking of debugfs (as opposed to sysfs) is a good
choice, because we probably want to tweak the layout a number of
times and want to keep flexibility, without being limited by the
sysfs ABI.

So i like the idea - but we really want to do even more and add
more structure to this. If we just want dumb msr enumeration we
already have /dev/msr.

Regarding the msr directory: one good approach would be to have
have several "topic" directories under /debug/x86/cpu/msr/.

One such topic would be the 'pmu', with a structure like:

/debug/x86/cpu/msr/pmu/
/debug/x86/cpu/msr/pmu/pmc_0/
/debug/x86/cpu/msr/pmu/pmc_0/counter
/debug/x86/cpu/msr/pmu/pmc_0/eventsel

There would also be a /debug/x86/cpu/msr/raw/ directory with all
MSR numbers we know about explicitly, for example:

/debug/x86/cpu/msr/raw/0x372/value
/debug/x86/cpu/msr/raw/0x372/width

Maybe a symlink pointing it back to the topic directory would be
useful as well. For example:

/debug/x86/cpu/msr/raw/0x372/topic_dir -> /debug/x86/cpu/msr/pmu/pmc_0/

Other "topic directories" are possible too: a
/debug/x86/cpu/msr/apic/ layout would be very useful and
informative as well, and so are some of the other MSRs we tweak
during bootup.

Ingo

2009-03-04 19:17:15

by Jaswinder Singh Rajput

[permalink] [raw]
Subject: Re: [git-pull -tip] x86: msr architecture debug code

On Mon, 2009-03-02 at 21:54 +0100, Ingo Molnar wrote:


> Please vertical-align structure field definitions, like you see
> we do it elsewhere in the x86 code.
>

done.

> > +
> > +#include <linux/module.h>
> > +#include <linux/kernel.h>
> > +#include <linux/debugfs.h>
> > +#include <linux/seq_file.h>
> > +#include <asm/msr_debug.h>
>
> Please have a good look at what the standard include files
> section look like - for example in
> arch/x86/kernel/cpu/perf_counter.c or in arch/x86/mm/fault.c.
> Please use that same ordering of the lines here too.
>

hmm, currently for my file these header files are more than enough, when
I will keep on add more stuff then header count will also increase and I
will do ordering.

> > +static int get_msr_intel_bit(unsigned model)
> > +{
> > + int ret = 0;
> > +
> > + switch (model) {
> > + case 0x0501:
> > + case 0x0502:
> > + case 0x0504:
> > + ret = MSR_INTEL_PENTIUM;
> > + break;
> > + case 0x0601:
> > + case 0x0603:
> > + case 0x0605:
> > + case 0x0607:
> > + case 0x0608:
> > + case 0x060A:
> > + case 0x060B:
> > + ret = MSR_INTEL_P6;
> > + break;
> > + case 0x0609:
> > + case 0x060D:
> > + ret = MSR_INTEL_PENTIUM_M;
> > + break;
> > + case 0x060E:
> > + ret = MSR_INTEL_CORE;
> > + break;
> > + case 0x060F:
> > + case 0x0617:
> > + ret = MSR_INTEL_CORE_2;
> > + break;
> > + case 0x061C:
> > + ret = MSR_INTEL_ATOM;
> > + break;
> > + case 0x0F00:
> > + case 0x0F01:
> > + case 0x0F02:
> > + case 0x0F03:
> > + case 0x0F04:
> > + ret = MSR_INTEL_XEON;
> > + break;
> > + case 0x0F06:
> > + ret = MSR_INTEL_XEON_MP;
> > + break;
> > + }
>
> all these magic constants open-coded look a bit ugly. Can it be
> done cleaner?
>

Then I need to do if-else and then it will become more ugly and every
time we need to add more magic numbers, it will also effect others.


> Check how structure initializations are done in other places of
> the x86 tree - for example perf_counters.c. Apply that style
> here too please.
>

I have made some changes. Please check is it OK.

> > +
> > +static struct dentry *msr_file, *pmc_file, *msr_dir;
> > +static int __init msr_debug_init(void)
>
> missing newline after static variables.
>
Done :-)

> > +{
> > + struct cpuinfo_x86 *cpu = &cpu_data(0);
> > +
> > + if (!cpu_has(cpu, X86_FEATURE_MSR))
> > + return -ENODEV;
> > +
> > + msr_dir = debugfs_create_dir("msr", arch_debugfs_dir);
> > +
> > + msr_file = debugfs_create_file("msr", S_IRUGO, msr_dir,
> > + NULL, &msr_fops);
> > + pmc_file = debugfs_create_file("pmc", S_IRUGO, msr_dir,
> > + NULL, &pmc_fops);
>
> I think it would be possible to have a much more intuitive file
> layout under /debug/x86/msr/ than these two /debug/x86/msr/msr
> and /debug/x86/msr/pmc files.
>
> Firstly, it should move one level deeper, to /debug/x86/cpu/msr/
> - because the MSR is really a property of the CPU, and there are
> other properties of the CPU we might want to expose in the
> future.
>

Done.

> Regarding the msr directory: one good approach would be to have
> have several "topic" directories under /debug/x86/cpu/msr/.
>
> One such topic would be the 'pmu', with a structure like:
>
> /debug/x86/cpu/msr/pmu/
> /debug/x86/cpu/msr/pmu/pmc_0/
> /debug/x86/cpu/msr/pmu/pmc_0/counter
> /debug/x86/cpu/msr/pmu/pmc_0/eventsel
>
> There would also be a /debug/x86/cpu/msr/raw/ directory with all
> MSR numbers we know about explicitly, for example:
>
> /debug/x86/cpu/msr/raw/0x372/value
> /debug/x86/cpu/msr/raw/0x372/width
>
> Maybe a symlink pointing it back to the topic directory would be
> useful as well. For example:
>
> /debug/x86/cpu/msr/raw/0x372/topic_dir -> /debug/x86/cpu/msr/pmu/pmc_0/
>

OK I like this, and I will do in next phase.

> Other "topic directories" are possible too: a
> /debug/x86/cpu/msr/apic/ layout would be very useful and
> informative as well, and so are some of the other MSRs we tweak
> during bootup.
>

Done.

Here is new request pull:

The following changes since commit 1d10914bf2c8a1164aef6c341e6c3518a91b8374:
Ingo Molnar (1):
Merge branch 'core/percpu'

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/jaswinder/linux-2.6-tip-cpu.git master

Jaswinder Singh Rajput (1):
x86: msr architecture debug code

arch/x86/include/asm/msr_debug.h | 163 ++++++++++++++
arch/x86/kernel/cpu/Makefile | 2 +-
arch/x86/kernel/cpu/msr_debug.c | 461 ++++++++++++++++++++++++++++++++++++++
arch/x86/kernel/kdebugfs.c | 7 +
4 files changed, 632 insertions(+), 1 deletions(-)
create mode 100755 arch/x86/include/asm/msr_debug.h
create mode 100755 arch/x86/kernel/cpu/msr_debug.c

diff --git a/arch/x86/include/asm/msr_debug.h b/arch/x86/include/asm/msr_debug.h
new file mode 100755
index 0000000..fd03923
--- /dev/null
+++ b/arch/x86/include/asm/msr_debug.h
@@ -0,0 +1,163 @@
+#ifndef _ASM_X86_MSR_DEBUG_H
+#define _ASM_X86_MSR_DEBUG_H
+
+/*
+ * Model Specific Registers (MSR) x86 architecture debug
+ *
+ * Copyright(C) 2009 Jaswinder Singh Rajput
+ */
+
+enum msr_debug_bit {
+ MSR_MC_BIT, /* Machine Check */
+ MSR_MONITOR_BIT, /* Monitor */
+ MSR_TIME_BIT, /* Time */
+ MSR_PMC_BIT, /* Performance Monitor */
+ MSR_PLATFORM_BIT, /* Platform */
+ MSR_APIC_BIT, /* APIC */
+ MSR_POWERON_BIT, /* Power-on */
+ MSR_CONTROL_BIT, /* Control */
+ MSR_FEATURES_BIT, /* Features control */
+ MSR_LBRANCH_BIT, /* Last Branch */
+ MSR_BIOS_BIT, /* BIOS */
+ MSR_FREQ_BIT, /* Frequency */
+ MSR_MTTR_BIT, /* MTRR */
+ MSR_PERF_BIT, /* Performance */
+ MSR_CACHE_BIT, /* Cache */
+ MSR_SYSENTER_BIT, /* Sysenter */
+ MSR_THERM_BIT, /* Thermal */
+ MSR_MISC_BIT, /* Miscellaneous */
+ MSR_DEBUG_BIT, /* Debug */
+ MSR_PAT_BIT, /* PAT */
+ MSR_VMX_BIT, /* VMX */
+ MSR_CALL_BIT, /* System Call */
+ MSR_BASE_BIT, /* BASE Address */
+ MSR_SMM_BIT, /* System mgmt mode */
+ MSR_SVM_BIT, /*Secure Virtual Machine*/
+ MSR_OSVM_BIT, /* OS-Visible Workaround*/
+ MSR_ALL_BIT, /* Select all MSRs */
+};
+
+#define MSR_ALL (~0) /* Select all MSRs */
+
+#define MSR_MC (1 << MSR_MC_BIT)
+#define MSR_MONITOR (1 << MSR_MONITOR_BIT)
+#define MSR_TIME (1 << MSR_TIME_BIT)
+#define MSR_PMC (1 << MSR_PMC_BIT)
+#define MSR_PLATFORM (1 << MSR_PLATFORM_BIT)
+#define MSR_APIC (1 << MSR_APIC_BIT)
+#define MSR_POWERON (1 << MSR_POWERON_BIT)
+#define MSR_CONTROL (1 << MSR_CONTROL_BIT)
+#define MSR_FEATURES (1 << MSR_FEATURES_BIT)
+#define MSR_LBRANCH (1 << MSR_LBRANCH_BIT)
+#define MSR_BIOS (1 << MSR_BIOS_BIT)
+#define MSR_FREQ (1 << MSR_FREQ_BIT)
+#define MSR_MTRR (1 << MSR_MTTR_BIT)
+#define MSR_PERF (1 << MSR_PERF_BIT)
+#define MSR_CACHE (1 << MSR_CACHE_BIT)
+#define MSR_SYSENTER (1 << MSR_SYSENTER_BIT)
+#define MSR_THERM (1 << MSR_THERM_BIT)
+#define MSR_MISC (1 << MSR_MISC_BIT)
+#define MSR_DEBUG (1 << MSR_DEBUG_BIT)
+#define MSR_PAT (1 << MSR_PAT_BIT)
+#define MSR_VMX (1 << MSR_VMX_BIT)
+#define MSR_CALL (1 << MSR_CALL_BIT)
+#define MSR_BASE (1 << MSR_BASE_BIT)
+#define MSR_SMM (1 << MSR_SMM_BIT)
+#define MSR_SVM (1 << MSR_SVM_BIT)
+#define MSR_OSVM (1 << MSR_OSVM_BIT)
+
+/*
+ * DisplayFamily_DisplayModel Processor Families/Processor Number Series
+ * -------------------------- ------------------------------------------
+ * 05_01, 05_02, 05_04 Pentium, Pentium with MMX
+ *
+ * 06_01 Pentium Pro
+ * 06_03, 06_05 Pentium II Xeon, Pentium II
+ * 06_07, 06_08, 06_0A, 06_0B Pentium III Xeon, Pentum III
+ *
+ * 06_09, 060D Pentium M
+ *
+ * 06_0E Core Duo, Core Solo
+ *
+ * 06_0F Xeon 3000, 3200, 5100, 5300, 7300 series,
+ * Core 2 Quad, Core 2 Extreme, Core 2 Duo,
+ * Pentium dual-core
+ * 06_17 Xeon 5200, 5400 series, Core 2 Quad Q9650
+ *
+ * 06_1C Atom
+ *
+ * 0F_00, 0F_01, 0F_02 Xeon, Xeon MP, Pentium 4
+ * 0F_03, 0F_04 Xeon, Xeon MP, Pentium 4, Pentium D
+ *
+ * 0F_06 Xeon 7100, 5000 Series, Xeon MP,
+ * Pentium 4, Pentium D
+ */
+
+/* MSR processors bits */
+enum msr_cpu_bit {
+/* Intel */
+ MSR_INTEL_PENTIUM_BIT,
+ MSR_INTEL_P6_BIT,
+ MSR_INTEL_PENTIUM_M_BIT,
+ MSR_INTEL_CORE_BIT,
+ MSR_INTEL_CORE2_BIT,
+ MSR_INTEL_ATOM_BIT,
+ MSR_INTEL_XEON_P4_BIT,
+ MSR_INTEL_XEON_MP_BIT,
+};
+
+#define MSR_CPU_ALL (~0) /* Select all CPUs */
+
+#define MSR_INTEL_PENTIUM (1 << MSR_INTEL_PENTIUM_BIT)
+#define MSR_INTEL_P6 (1 << MSR_INTEL_P6_BIT)
+#define MSR_INTEL_PENTIUM_M (1 << MSR_INTEL_PENTIUM_M_BIT)
+#define MSR_INTEL_CORE (1 << MSR_INTEL_CORE_BIT)
+#define MSR_INTEL_CORE2 (1 << MSR_INTEL_CORE2_BIT)
+#define MSR_INTEL_ATOM (1 << MSR_INTEL_ATOM_BIT)
+#define MSR_INTEL_XEON_P4 (1 << MSR_INTEL_XEON_P4_BIT)
+#define MSR_INTEL_XEON_MP (1 << MSR_INTEL_XEON_MP_BIT)
+
+#define MSR_INTEL_PX (MSR_INTEL_P6 | MSR_INTEL_PENTIUM_M)
+#define MSR_INTEL_COREX (MSR_INTEL_CORE | MSR_INTEL_CORE2)
+#define MSR_INTEL_XEON (MSR_INTEL_XEON_P4 | MSR_INTEL_XEON_MP)
+#define MSR_CO_AT (MSR_INTEL_CORE | MSR_INTEL_ATOM)
+#define MSR_C2_AT (MSR_INTEL_CORE2 | MSR_INTEL_ATOM)
+#define MSR_CX_AT (MSR_INTEL_COREX | MSR_INTEL_ATOM)
+#define MSR_CX_XE (MSR_INTEL_COREX | MSR_INTEL_XEON)
+#define MSR_P6_XE (MSR_INTEL_P6 | MSR_INTEL_XEON)
+#define MSR_PM_CO_AT (MSR_INTEL_PENTIUM_M | MSR_CO_AT)
+#define MSR_C2_AT_XE (MSR_C2_AT | MSR_INTEL_XEON)
+#define MSR_CX_AT_XE (MSR_CX_AT | MSR_INTEL_XEON)
+#define MSR_P6_CX_AT (MSR_INTEL_P6 | MSR_CX_AT)
+#define MSR_P6_CX_XE (MSR_P6_XE | MSR_INTEL_COREX)
+#define MSR_P6_CX_AT_XE (MSR_INTEL_P6 | MSR_CX_AT_XE)
+#define MSR_PM_CX_AT_XE (MSR_INTEL_PENTIUM_M | MSR_CX_AT_XE)
+#define MSR_PM_CX_AT (MSR_INTEL_PENTIUM_M | MSR_CX_AT)
+#define MSR_PM_CX_XE (MSR_INTEL_PENTIUM_M | MSR_CX_XE)
+#define MSR_PX_CX_AT (MSR_INTEL_PX | MSR_CX_AT)
+#define MSR_PX_CX_AT_XE (MSR_INTEL_PX | MSR_CX_AT_XE)
+
+/* Select all Intel CPUs*/
+#define MSR_INTEL_ALL (MSR_INTEL_PENTIUM | MSR_PX_CX_AT_XE)
+
+struct msr_debug_base {
+ char *name; /* MSR name */
+ unsigned flag; /* MSR flag */
+};
+
+struct msr_debug_range {
+ unsigned min; /* MSR range min */
+ unsigned max; /* MSR range max */
+ unsigned flag; /* Supported flags */
+ unsigned model; /* Supported models */
+};
+
+struct msr_private {
+ unsigned cpu;
+ unsigned msr;
+ unsigned count;
+};
+
+extern struct dentry *arch_cpu_debugfs_dir;
+
+#endif /* _ASM_X86_MSR_DEBUG_H */
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index c381330..6c9187a 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -9,7 +9,7 @@ endif

obj-y := intel_cacheinfo.o addon_cpuid_features.o
obj-y += proc.o capflags.o powerflags.o common.o
-obj-y += vmware.o hypervisor.o
+obj-y += vmware.o hypervisor.o msr_debug.o

obj-$(CONFIG_X86_32) += bugs.o cmpxchg.o
obj-$(CONFIG_X86_64) += bugs_64.o
diff --git a/arch/x86/kernel/cpu/msr_debug.c b/arch/x86/kernel/cpu/msr_debug.c
new file mode 100755
index 0000000..21808d0
--- /dev/null
+++ b/arch/x86/kernel/cpu/msr_debug.c
@@ -0,0 +1,461 @@
+/*
+ * Model Specific Registers (MSR) x86 architecture debug code
+ *
+ * Copyright(C) 2009 Jaswinder Singh Rajput
+ *
+ * For licencing details see kernel-base/COPYING
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <asm/msr_debug.h>
+
+static struct msr_debug_base msr_base[] = {
+ { "mc", MSR_MC }, /* Machine Check */
+ { "monitor", MSR_MONITOR }, /* Monitor */
+ { "time", MSR_TIME }, /* Time */
+ { "pmc", MSR_PMC }, /* Performance Monitor */
+ { "platform", MSR_PLATFORM }, /* Platform */
+ { "apic", MSR_APIC }, /* APIC */
+ { "poweron", MSR_POWERON }, /* Power-on */
+ { "control", MSR_CONTROL }, /* Control */
+ { "features", MSR_FEATURES }, /* Features control */
+ { "lastbranch", MSR_LBRANCH }, /* Last Branch */
+ { "bios", MSR_BIOS }, /* BIOS */
+ { "freq", MSR_FREQ }, /* Frequency */
+ { "mttr", MSR_MTRR }, /* MTRR */
+ { "perf", MSR_PERF }, /* Performance */
+ { "cache", MSR_CACHE }, /* Cache */
+ { "sysenter", MSR_SYSENTER }, /* Sysenter */
+ { "therm", MSR_THERM }, /* Thermal */
+ { "misc", MSR_MISC }, /* Miscellaneous */
+ { "debug", MSR_DEBUG }, /* Debug */
+ { "pat", MSR_PAT }, /* PAT */
+ { "vmx", MSR_VMX }, /* VMX */
+ { "call", MSR_CALL }, /* System Call */
+ { "base", MSR_BASE }, /* BASE Address */
+ { "smm", MSR_SMM }, /* System mgmt mode */
+ { "svm", MSR_SVM }, /*Secure Virtial Machine*/
+ { "osvm", MSR_OSVM }, /* OS-Visible Workaround*/
+ { "msr", MSR_ALL }, /* Select all MSRs */
+};
+
+static struct msr_debug_range msr_intel_range[] = {
+ { 0x00000000, 0x00000001, MSR_MC, MSR_INTEL_ALL },
+ { 0x00000006, 0x00000007, MSR_MONITOR, MSR_CX_AT_XE },
+ { 0x00000010, 0x00000010, MSR_TIME, MSR_INTEL_ALL },
+ { 0x00000011, 0x00000013, MSR_PMC, MSR_INTEL_PENTIUM },
+ { 0x00000017, 0x00000017, MSR_PLATFORM, MSR_PX_CX_AT_XE },
+ { 0x0000001B, 0x0000001B, MSR_APIC, MSR_P6_CX_AT_XE },
+
+ { 0x0000002A, 0x0000002A, MSR_POWERON, MSR_PX_CX_AT_XE },
+ { 0x0000002B, 0x0000002B, MSR_POWERON, MSR_INTEL_XEON },
+ { 0x0000002C, 0x0000002C, MSR_FREQ, MSR_INTEL_XEON },
+ { 0x0000003A, 0x0000003A, MSR_CONTROL, MSR_CX_AT_XE },
+
+ { 0x00000040, 0x00000043, MSR_LBRANCH, MSR_PM_CX_AT_XE },
+ { 0x00000044, 0x00000047, MSR_LBRANCH, MSR_PM_CO_AT },
+ { 0x00000060, 0x00000063, MSR_LBRANCH, MSR_C2_AT },
+ { 0x00000064, 0x00000067, MSR_LBRANCH, MSR_INTEL_ATOM },
+
+ { 0x00000079, 0x00000079, MSR_BIOS, MSR_P6_CX_AT_XE },
+ { 0x00000088, 0x0000008A, MSR_CACHE, MSR_INTEL_P6 },
+ { 0x0000008B, 0x0000008B, MSR_BIOS, MSR_P6_CX_AT_XE },
+ { 0x0000009B, 0x0000009B, MSR_MONITOR, MSR_INTEL_XEON },
+
+ { 0x000000C1, 0x000000C2, MSR_PMC, MSR_P6_CX_AT },
+ { 0x000000CD, 0x000000CD, MSR_FREQ, MSR_CX_AT },
+ { 0x000000E7, 0x000000E8, MSR_PERF, MSR_CX_AT },
+ { 0x000000FE, 0x000000FE, MSR_MTRR, MSR_P6_CX_XE },
+
+ { 0x00000116, 0x00000116, MSR_CACHE, MSR_INTEL_P6 },
+ { 0x00000118, 0x00000118, MSR_CACHE, MSR_INTEL_P6 },
+ { 0x00000119, 0x00000119, MSR_CACHE, MSR_INTEL_PX },
+ { 0x0000011A, 0x0000011B, MSR_CACHE, MSR_INTEL_P6 },
+ { 0x0000011E, 0x0000011E, MSR_CACHE, MSR_PX_CX_AT },
+
+ { 0x00000174, 0x00000176, MSR_SYSENTER, MSR_P6_CX_AT_XE },
+ { 0x00000179, 0x0000017A, MSR_MC, MSR_PX_CX_AT_XE },
+ { 0x0000017B, 0x0000017B, MSR_MC, MSR_P6_XE },
+ { 0x00000186, 0x00000187, MSR_PMC, MSR_P6_CX_AT },
+ { 0x00000198, 0x00000199, MSR_PERF, MSR_PM_CX_AT_XE },
+ { 0x0000019A, 0x0000019A, MSR_TIME, MSR_PM_CX_AT_XE },
+ { 0x0000019B, 0x0000019D, MSR_THERM, MSR_PM_CX_AT_XE },
+ { 0x000001A0, 0x000001A0, MSR_MISC, MSR_PM_CX_AT_XE },
+
+ { 0x000001C9, 0x000001C9, MSR_LBRANCH, MSR_PM_CX_AT },
+ { 0x000001D7, 0x000001D8, MSR_LBRANCH, MSR_INTEL_XEON },
+ { 0x000001D9, 0x000001D9, MSR_DEBUG, MSR_CX_AT_XE },
+ { 0x000001DA, 0x000001DA, MSR_LBRANCH, MSR_INTEL_XEON },
+ { 0x000001DB, 0x000001DB, MSR_LBRANCH, MSR_P6_XE },
+ { 0x000001DC, 0x000001DC, MSR_LBRANCH, MSR_INTEL_P6 },
+ { 0x000001DD, 0x000001DE, MSR_LBRANCH, MSR_PX_CX_AT_XE },
+ { 0x000001E0, 0x000001E0, MSR_LBRANCH, MSR_INTEL_P6 },
+
+ { 0x00000200, 0x0000020F, MSR_MTRR, MSR_P6_CX_XE },
+ { 0x00000250, 0x00000250, MSR_MTRR, MSR_P6_CX_XE },
+ { 0x00000258, 0x00000259, MSR_MTRR, MSR_P6_CX_XE },
+ { 0x00000268, 0x0000026F, MSR_MTRR, MSR_P6_CX_XE },
+ { 0x00000277, 0x00000277, MSR_PAT, MSR_C2_AT_XE },
+ { 0x000002FF, 0x000002FF, MSR_MTRR, MSR_P6_CX_XE },
+
+ { 0x00000300, 0x00000308, MSR_PMC, MSR_INTEL_XEON },
+ { 0x00000309, 0x0000030B, MSR_PMC, MSR_C2_AT_XE },
+ { 0x0000030C, 0x00000311, MSR_PMC, MSR_INTEL_XEON },
+ { 0x00000345, 0x00000345, MSR_PMC, MSR_C2_AT },
+ { 0x00000360, 0x00000371, MSR_PMC, MSR_INTEL_XEON },
+ { 0x0000038D, 0x00000390, MSR_PMC, MSR_C2_AT },
+ { 0x000003A0, 0x000003BE, MSR_PMC, MSR_INTEL_XEON },
+ { 0x000003C0, 0x000003CD, MSR_PMC, MSR_INTEL_XEON },
+ { 0x000003E0, 0x000003E1, MSR_PMC, MSR_INTEL_XEON },
+ { 0x000003F0, 0x000003F0, MSR_PMC, MSR_INTEL_XEON },
+ { 0x000003F1, 0x000003F1, MSR_PMC, MSR_C2_AT_XE },
+ { 0x000003F2, 0x000003F2, MSR_PMC, MSR_INTEL_XEON },
+
+ { 0x00000400, 0x00000402, MSR_MC, MSR_PM_CX_AT_XE },
+ { 0x00000403, 0x00000403, MSR_MC, MSR_INTEL_XEON },
+ { 0x00000404, 0x00000406, MSR_MC, MSR_PM_CX_AT_XE },
+ { 0x00000407, 0x00000407, MSR_MC, MSR_INTEL_XEON },
+ { 0x00000408, 0x0000040A, MSR_MC, MSR_PM_CX_AT_XE },
+ { 0x0000040B, 0x0000040B, MSR_MC, MSR_INTEL_XEON },
+ { 0x0000040C, 0x0000040E, MSR_MC, MSR_PM_CX_XE },
+ { 0x0000040F, 0x0000040F, MSR_MC, MSR_INTEL_XEON },
+ { 0x00000410, 0x00000412, MSR_MC, MSR_PM_CX_AT_XE },
+ { 0x00000413, 0x00000417, MSR_MC, MSR_CX_AT_XE },
+ { 0x00000480, 0x0000048B, MSR_VMX, MSR_CX_AT_XE },
+
+ { 0x00000600, 0x00000600, MSR_DEBUG, MSR_PM_CX_AT_XE },
+ { 0x00000680, 0x0000068F, MSR_LBRANCH, MSR_INTEL_XEON },
+ { 0x000006C0, 0x000006CF, MSR_LBRANCH, MSR_INTEL_XEON },
+
+ { 0x000107CC, 0x000107D3, MSR_PMC, MSR_INTEL_XEON_MP },
+
+ { 0xC0000080, 0xC0000080, MSR_FEATURES, MSR_INTEL_XEON },
+ { 0xC0000081, 0xC0000082, MSR_CALL, MSR_INTEL_XEON },
+ { 0xC0000084, 0xC0000084, MSR_CALL, MSR_INTEL_XEON },
+ { 0xC0000100, 0xC0000102, MSR_BASE, MSR_INTEL_XEON },
+};
+
+/* AMD MSRs Range */
+static struct msr_debug_range msr_amd_range[] = {
+ { 0x00000010, 0x00000010, MSR_TIME, MSR_CPU_ALL, },
+ { 0x0000001B, 0x0000001B, MSR_APIC, MSR_CPU_ALL, },
+ { 0x000000FE, 0x000000FE, MSR_MTRR, MSR_CPU_ALL, },
+
+ { 0x00000174, 0x00000176, MSR_SYSENTER, MSR_CPU_ALL, },
+ { 0x00000179, 0x0000017A, MSR_MC, MSR_CPU_ALL, },
+ { 0x0000017B, 0x0000017B, MSR_MC, MSR_CPU_ALL, },
+ { 0x000001D9, 0x000001D9, MSR_DEBUG, MSR_CPU_ALL, },
+ { 0x000001DB, 0x000001DE, MSR_LBRANCH, MSR_CPU_ALL, },
+
+ { 0x00000200, 0x0000020F, MSR_MTRR, MSR_CPU_ALL, },
+ { 0x00000250, 0x00000250, MSR_MTRR, MSR_CPU_ALL, },
+ { 0x00000258, 0x00000259, MSR_MTRR, MSR_CPU_ALL, },
+ { 0x00000268, 0x0000026F, MSR_MTRR, MSR_CPU_ALL, },
+ { 0x00000277, 0x00000277, MSR_PAT, MSR_CPU_ALL, },
+ { 0x000002FF, 0x000002FF, MSR_MTRR, MSR_CPU_ALL, },
+
+ { 0x00000400, 0x00000417, MSR_MC, MSR_CPU_ALL, },
+
+ { 0xC0000080, 0xC0000080, MSR_FEATURES, MSR_INTEL_XEON },
+ { 0xC0000081, 0xC0000084, MSR_CALL, MSR_INTEL_XEON },
+ { 0xC0000100, 0xC0000102, MSR_BASE, MSR_INTEL_XEON },
+ { 0xC0000103, 0xC0000103, MSR_TIME, MSR_INTEL_XEON },
+
+ { 0xC0000408, 0xC000040A, MSR_MC, MSR_CPU_ALL, },
+
+ { 0xc0010000, 0xc0010007, MSR_PMC, MSR_CPU_ALL },
+ { 0xc0010010, 0xc0010010, MSR_MTRR, MSR_CPU_ALL },
+ { 0xc0010016, 0xc001001A, MSR_MTRR, MSR_CPU_ALL },
+ { 0xc001001D, 0xc001001D, MSR_MTRR, MSR_CPU_ALL },
+ { 0xc0010030, 0xc0010035, MSR_BIOS, MSR_CPU_ALL },
+ { 0xc0010056, 0xc0010056, MSR_SMM, MSR_CPU_ALL },
+ { 0xc0010061, 0xc0010063, MSR_SMM, MSR_CPU_ALL },
+ { 0xc0010074, 0xc0010074, MSR_MC, MSR_CPU_ALL },
+ { 0xc0010111, 0xc0010113, MSR_SMM, MSR_CPU_ALL },
+ { 0xc0010114, 0xc0010118, MSR_SVM, MSR_CPU_ALL },
+ { 0xc0010119, 0xc001011A, MSR_SMM, MSR_CPU_ALL },
+ { 0xc0010140, 0xc0010141, MSR_OSVM, MSR_CPU_ALL },
+ { 0xc0010156, 0xc0010156, MSR_SMM, MSR_CPU_ALL },
+};
+
+static DEFINE_MUTEX(msr_debug_lock);
+
+static int get_msr_intel_bit(unsigned model)
+{
+ int ret = 0;
+
+ switch (model) {
+ case 0x0501:
+ case 0x0502:
+ case 0x0504:
+ ret = MSR_INTEL_PENTIUM;
+ break;
+ case 0x0601:
+ case 0x0603:
+ case 0x0605:
+ case 0x0607:
+ case 0x0608:
+ case 0x060A:
+ case 0x060B:
+ ret = MSR_INTEL_P6;
+ break;
+ case 0x0609:
+ case 0x060D:
+ ret = MSR_INTEL_PENTIUM_M;
+ break;
+ case 0x060E:
+ ret = MSR_INTEL_CORE;
+ break;
+ case 0x060F:
+ case 0x0617:
+ ret = MSR_INTEL_CORE2;
+ break;
+ case 0x061C:
+ ret = MSR_INTEL_ATOM;
+ break;
+ case 0x0F00:
+ case 0x0F01:
+ case 0x0F02:
+ case 0x0F03:
+ case 0x0F04:
+ ret = MSR_INTEL_XEON_P4;
+ break;
+ case 0x0F06:
+ ret = MSR_INTEL_XEON_MP;
+ break;
+ }
+
+ return ret;
+}
+
+static int get_msr_cpu_bit(unsigned model)
+{
+ unsigned vendor;
+
+ vendor = model >> 16;
+ if (vendor == X86_VENDOR_INTEL)
+ return get_msr_intel_bit(model & 0xffff);
+ else
+ return 0;
+}
+
+static unsigned get_msr_range(unsigned *min, unsigned *max, int index,
+ unsigned flag, unsigned model)
+{
+ unsigned vendor, cpu_bit;
+
+ vendor = model >> 16;
+ cpu_bit = get_msr_cpu_bit(model);
+ *max = 0;
+ if (vendor == X86_VENDOR_INTEL) {
+ if ((msr_intel_range[index].model & cpu_bit) &&
+ (msr_intel_range[index].flag & flag)) {
+ *min = msr_intel_range[index].min;
+ *max = msr_intel_range[index].max;
+ }
+ } else if (vendor == X86_VENDOR_AMD) {
+ if (msr_amd_range[index].flag & flag) {
+ *min = msr_amd_range[index].min;
+ *max = msr_amd_range[index].max;
+ }
+ }
+
+ return *max;
+}
+
+static int get_msr_range_count(unsigned flag, unsigned model)
+{
+ int index = 0;
+
+ model >>= 16;
+ if (model == X86_VENDOR_INTEL)
+ index = ARRAY_SIZE(msr_intel_range);
+ else if (model == X86_VENDOR_AMD)
+ index = ARRAY_SIZE(msr_amd_range);
+
+ return index;
+}
+
+static void print_intel_msr(struct seq_file *seq, unsigned int cpu,
+ unsigned flag, unsigned model)
+{
+ int i, range;
+ u32 low, high;
+ unsigned msr, msr_min, msr_max;
+
+ range = get_msr_range_count(flag, model);
+
+ for (i = 0; i < range; i++) {
+ if (!get_msr_range(&msr_min, &msr_max, i, flag, model))
+ continue;
+ for (msr = msr_min; msr <= msr_max; msr++) {
+ if (rdmsr_safe_on_cpu(cpu, msr, &low, &high))
+ continue;
+ if (seq)
+ seq_printf(seq, " MSR_%08x: %08x_%08x\n",
+ msr, high, low);
+ else
+ printk(KERN_INFO " MSR_%08x: %08x_%08x\n",
+ msr, high, low);
+ }
+ }
+}
+
+static void print_amd_msr(struct seq_file *seq, unsigned flag, unsigned model)
+{
+ int i, range;
+ u64 val;
+ unsigned msr, msr_min, msr_max;
+
+ range = get_msr_range_count(flag, model);
+
+ for (i = 0; i < range; i++) {
+ if (!get_msr_range(&msr_min, &msr_max, i, flag, model))
+ continue;
+ for (msr = msr_min; msr <= msr_max; msr++) {
+ if (rdmsrl_amd_safe(msr, &val))
+ continue;
+ if (seq)
+ seq_printf(seq, " MSR_%08x: %016llx\n",
+ msr, val);
+ else
+ printk(KERN_INFO " MSR_%08x: %016llx\n",
+ msr, val);
+ }
+ }
+}
+
+static int msr_seq_show(struct seq_file *seq, void *v)
+{
+ unsigned model, flag;
+ struct cpuinfo_x86 *cpu = &cpu_data(0);
+ struct msr_private *priv = seq->private;
+
+#ifdef CONFIG_SMP
+ /* We are only interested for core_id 0 */
+ if (cpu->cpu_core_id || cpu->apicid)
+ return 0;
+#endif
+ model = ((cpu->x86_vendor << 16) | (cpu->x86 << 8) | (cpu->x86_model));
+ flag = msr_base[priv->msr].flag;
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+ print_intel_msr(seq, cpu->phys_proc_id, flag, model);
+ else
+ print_amd_msr(seq, flag, model);
+
+ seq_printf(seq, "\n");
+
+ return 0;
+}
+
+static void *msr_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ struct cpuinfo_x86 *c = NULL;
+
+ if (*pos == 0) /* just in case, cpu 0 is not the first */
+ c = &cpu_data(*pos);
+
+ return c;
+}
+
+static void *msr_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ (*pos)++;
+
+ return msr_seq_start(seq, pos);
+}
+
+static void msr_seq_stop(struct seq_file *seq, void *v)
+{
+}
+
+static const struct seq_operations msr_seq_ops = {
+ .start = msr_seq_start,
+ .next = msr_seq_next,
+ .stop = msr_seq_stop,
+ .show = msr_seq_show,
+};
+
+static int msr_seq_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ struct msr_private *priv;
+ int err, private = inode->i_private;
+
+ err = seq_open(file, &msr_seq_ops);
+ mutex_lock(&msr_debug_lock);
+ if (!err) {
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (priv) {
+ seq = file->private_data;
+ priv->cpu = (private & 0xFF);
+ private >>= 8;
+ priv->msr = (private & 0xFF);
+ private >>= 8;
+ priv->count = (private & 0xFF);
+ seq->private = priv;
+ } else
+ err = -ENOMEM;
+
+ }
+ mutex_unlock(&msr_debug_lock);
+
+ return err;
+}
+
+static int msr_seq_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq = (struct seq_file *)file->private_data;
+ struct msr_private *priv = seq->private;
+
+ seq_release(inode, file);
+ kfree(priv);
+
+ return 0;
+}
+
+static const struct file_operations msr_fops = {
+ .open = msr_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = msr_seq_release,
+};
+
+static struct dentry *msr_debugfs_dir;
+
+static int __init msr_debug_init(void)
+{
+ int i;
+ unsigned priv_data;
+ struct dentry *msr_dentry;
+ struct cpuinfo_x86 *cpu = &cpu_data(0);
+
+ if (!cpu_has(cpu, X86_FEATURE_MSR))
+ return -ENODEV;
+
+ msr_debugfs_dir = debugfs_create_dir("msr", arch_cpu_debugfs_dir);
+ msr_dentry = debugfs_create_dir("cpu0", msr_debugfs_dir);
+
+ for (i = 0; i < ARRAY_SIZE(msr_base); i++) {
+ priv_data = i << 8;
+ debugfs_create_file(msr_base[i].name, S_IRUGO, msr_dentry,
+ (void *)priv_data, &msr_fops);
+ }
+ return 0;
+}
+
+static void __exit msr_debug_exit(void)
+{
+ if (msr_debugfs_dir)
+ debugfs_remove_recursive(msr_debugfs_dir);
+}
+
+module_init(msr_debug_init);
+module_exit(msr_debug_exit);
+
+MODULE_AUTHOR("Jaswinder Singh Rajput");
+MODULE_DESCRIPTION("MSR debug module");
+MODULE_LICENSE("GPL");
diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
index ff7d3b0..2fa3b08 100644
--- a/arch/x86/kernel/kdebugfs.c
+++ b/arch/x86/kernel/kdebugfs.c
@@ -19,6 +19,9 @@
struct dentry *arch_debugfs_dir;
EXPORT_SYMBOL(arch_debugfs_dir);

+struct dentry *arch_cpu_debugfs_dir;
+EXPORT_SYMBOL(arch_cpu_debugfs_dir);
+
#ifdef CONFIG_DEBUG_BOOT_PARAMS
struct setup_data_node {
u64 paddr;
@@ -218,6 +221,10 @@ static int __init arch_kdebugfs_init(void)
if (!arch_debugfs_dir)
return -ENOMEM;

+ arch_cpu_debugfs_dir = debugfs_create_dir("cpu", arch_debugfs_dir);
+ if (!arch_cpu_debugfs_dir)
+ return -ENOMEM;
+
#ifdef CONFIG_DEBUG_BOOT_PARAMS
error = boot_params_kdebugfs_init();
#endif

2009-03-04 20:51:13

by Jaswinder Singh Rajput

[permalink] [raw]
Subject: Re: [git-pull -tip V2] x86: msr architecture debug code

On Thu, 2009-03-05 at 00:46 +0530, Jaswinder Singh Rajput wrote:

> The following changes since commit 1d10914bf2c8a1164aef6c341e6c3518a91b8374:
> Ingo Molnar (1):
> Merge branch 'core/percpu'
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/jaswinder/linux-2.6-tip-cpu.git master
>
> Jaswinder Singh Rajput (1):
> x86: msr architecture debug code

Here is new request pull after minor fixes:

The following changes since commit 1d10914bf2c8a1164aef6c341e6c3518a91b8374:
Ingo Molnar (1):
Merge branch 'core/percpu'

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/jaswinder/linux-2.6-tip-cpu.git master

Jaswinder Singh Rajput (1):
x86: msr architecture debug code

arch/x86/include/asm/msr_debug.h | 163 +++++++++++++
arch/x86/kernel/cpu/Makefile | 2 +-
arch/x86/kernel/cpu/msr_debug.c | 463 ++++++++++++++++++++++++++++++++++++++
arch/x86/kernel/kdebugfs.c | 7 +
4 files changed, 634 insertions(+), 1 deletions(-)
create mode 100755 arch/x86/include/asm/msr_debug.h
create mode 100755 arch/x86/kernel/cpu/msr_debug.c

Complete diff:
diff --git a/arch/x86/include/asm/msr_debug.h b/arch/x86/include/asm/msr_debug.h
new file mode 100755
index 0000000..fd03923
--- /dev/null
+++ b/arch/x86/include/asm/msr_debug.h
@@ -0,0 +1,163 @@
+#ifndef _ASM_X86_MSR_DEBUG_H
+#define _ASM_X86_MSR_DEBUG_H
+
+/*
+ * Model Specific Registers (MSR) x86 architecture debug
+ *
+ * Copyright(C) 2009 Jaswinder Singh Rajput
+ */
+
+enum msr_debug_bit {
+ MSR_MC_BIT, /* Machine Check */
+ MSR_MONITOR_BIT, /* Monitor */
+ MSR_TIME_BIT, /* Time */
+ MSR_PMC_BIT, /* Performance Monitor */
+ MSR_PLATFORM_BIT, /* Platform */
+ MSR_APIC_BIT, /* APIC */
+ MSR_POWERON_BIT, /* Power-on */
+ MSR_CONTROL_BIT, /* Control */
+ MSR_FEATURES_BIT, /* Features control */
+ MSR_LBRANCH_BIT, /* Last Branch */
+ MSR_BIOS_BIT, /* BIOS */
+ MSR_FREQ_BIT, /* Frequency */
+ MSR_MTTR_BIT, /* MTRR */
+ MSR_PERF_BIT, /* Performance */
+ MSR_CACHE_BIT, /* Cache */
+ MSR_SYSENTER_BIT, /* Sysenter */
+ MSR_THERM_BIT, /* Thermal */
+ MSR_MISC_BIT, /* Miscellaneous */
+ MSR_DEBUG_BIT, /* Debug */
+ MSR_PAT_BIT, /* PAT */
+ MSR_VMX_BIT, /* VMX */
+ MSR_CALL_BIT, /* System Call */
+ MSR_BASE_BIT, /* BASE Address */
+ MSR_SMM_BIT, /* System mgmt mode */
+ MSR_SVM_BIT, /*Secure Virtual Machine*/
+ MSR_OSVM_BIT, /* OS-Visible Workaround*/
+ MSR_ALL_BIT, /* Select all MSRs */
+};
+
+#define MSR_ALL (~0) /* Select all MSRs */
+
+#define MSR_MC (1 << MSR_MC_BIT)
+#define MSR_MONITOR (1 << MSR_MONITOR_BIT)
+#define MSR_TIME (1 << MSR_TIME_BIT)
+#define MSR_PMC (1 << MSR_PMC_BIT)
+#define MSR_PLATFORM (1 << MSR_PLATFORM_BIT)
+#define MSR_APIC (1 << MSR_APIC_BIT)
+#define MSR_POWERON (1 << MSR_POWERON_BIT)
+#define MSR_CONTROL (1 << MSR_CONTROL_BIT)
+#define MSR_FEATURES (1 << MSR_FEATURES_BIT)
+#define MSR_LBRANCH (1 << MSR_LBRANCH_BIT)
+#define MSR_BIOS (1 << MSR_BIOS_BIT)
+#define MSR_FREQ (1 << MSR_FREQ_BIT)
+#define MSR_MTRR (1 << MSR_MTTR_BIT)
+#define MSR_PERF (1 << MSR_PERF_BIT)
+#define MSR_CACHE (1 << MSR_CACHE_BIT)
+#define MSR_SYSENTER (1 << MSR_SYSENTER_BIT)
+#define MSR_THERM (1 << MSR_THERM_BIT)
+#define MSR_MISC (1 << MSR_MISC_BIT)
+#define MSR_DEBUG (1 << MSR_DEBUG_BIT)
+#define MSR_PAT (1 << MSR_PAT_BIT)
+#define MSR_VMX (1 << MSR_VMX_BIT)
+#define MSR_CALL (1 << MSR_CALL_BIT)
+#define MSR_BASE (1 << MSR_BASE_BIT)
+#define MSR_SMM (1 << MSR_SMM_BIT)
+#define MSR_SVM (1 << MSR_SVM_BIT)
+#define MSR_OSVM (1 << MSR_OSVM_BIT)
+
+/*
+ * DisplayFamily_DisplayModel Processor Families/Processor Number Series
+ * -------------------------- ------------------------------------------
+ * 05_01, 05_02, 05_04 Pentium, Pentium with MMX
+ *
+ * 06_01 Pentium Pro
+ * 06_03, 06_05 Pentium II Xeon, Pentium II
+ * 06_07, 06_08, 06_0A, 06_0B Pentium III Xeon, Pentum III
+ *
+ * 06_09, 060D Pentium M
+ *
+ * 06_0E Core Duo, Core Solo
+ *
+ * 06_0F Xeon 3000, 3200, 5100, 5300, 7300 series,
+ * Core 2 Quad, Core 2 Extreme, Core 2 Duo,
+ * Pentium dual-core
+ * 06_17 Xeon 5200, 5400 series, Core 2 Quad Q9650
+ *
+ * 06_1C Atom
+ *
+ * 0F_00, 0F_01, 0F_02 Xeon, Xeon MP, Pentium 4
+ * 0F_03, 0F_04 Xeon, Xeon MP, Pentium 4, Pentium D
+ *
+ * 0F_06 Xeon 7100, 5000 Series, Xeon MP,
+ * Pentium 4, Pentium D
+ */
+
+/* MSR processors bits */
+enum msr_cpu_bit {
+/* Intel */
+ MSR_INTEL_PENTIUM_BIT,
+ MSR_INTEL_P6_BIT,
+ MSR_INTEL_PENTIUM_M_BIT,
+ MSR_INTEL_CORE_BIT,
+ MSR_INTEL_CORE2_BIT,
+ MSR_INTEL_ATOM_BIT,
+ MSR_INTEL_XEON_P4_BIT,
+ MSR_INTEL_XEON_MP_BIT,
+};
+
+#define MSR_CPU_ALL (~0) /* Select all CPUs */
+
+#define MSR_INTEL_PENTIUM (1 << MSR_INTEL_PENTIUM_BIT)
+#define MSR_INTEL_P6 (1 << MSR_INTEL_P6_BIT)
+#define MSR_INTEL_PENTIUM_M (1 << MSR_INTEL_PENTIUM_M_BIT)
+#define MSR_INTEL_CORE (1 << MSR_INTEL_CORE_BIT)
+#define MSR_INTEL_CORE2 (1 << MSR_INTEL_CORE2_BIT)
+#define MSR_INTEL_ATOM (1 << MSR_INTEL_ATOM_BIT)
+#define MSR_INTEL_XEON_P4 (1 << MSR_INTEL_XEON_P4_BIT)
+#define MSR_INTEL_XEON_MP (1 << MSR_INTEL_XEON_MP_BIT)
+
+#define MSR_INTEL_PX (MSR_INTEL_P6 | MSR_INTEL_PENTIUM_M)
+#define MSR_INTEL_COREX (MSR_INTEL_CORE | MSR_INTEL_CORE2)
+#define MSR_INTEL_XEON (MSR_INTEL_XEON_P4 | MSR_INTEL_XEON_MP)
+#define MSR_CO_AT (MSR_INTEL_CORE | MSR_INTEL_ATOM)
+#define MSR_C2_AT (MSR_INTEL_CORE2 | MSR_INTEL_ATOM)
+#define MSR_CX_AT (MSR_INTEL_COREX | MSR_INTEL_ATOM)
+#define MSR_CX_XE (MSR_INTEL_COREX | MSR_INTEL_XEON)
+#define MSR_P6_XE (MSR_INTEL_P6 | MSR_INTEL_XEON)
+#define MSR_PM_CO_AT (MSR_INTEL_PENTIUM_M | MSR_CO_AT)
+#define MSR_C2_AT_XE (MSR_C2_AT | MSR_INTEL_XEON)
+#define MSR_CX_AT_XE (MSR_CX_AT | MSR_INTEL_XEON)
+#define MSR_P6_CX_AT (MSR_INTEL_P6 | MSR_CX_AT)
+#define MSR_P6_CX_XE (MSR_P6_XE | MSR_INTEL_COREX)
+#define MSR_P6_CX_AT_XE (MSR_INTEL_P6 | MSR_CX_AT_XE)
+#define MSR_PM_CX_AT_XE (MSR_INTEL_PENTIUM_M | MSR_CX_AT_XE)
+#define MSR_PM_CX_AT (MSR_INTEL_PENTIUM_M | MSR_CX_AT)
+#define MSR_PM_CX_XE (MSR_INTEL_PENTIUM_M | MSR_CX_XE)
+#define MSR_PX_CX_AT (MSR_INTEL_PX | MSR_CX_AT)
+#define MSR_PX_CX_AT_XE (MSR_INTEL_PX | MSR_CX_AT_XE)
+
+/* Select all Intel CPUs*/
+#define MSR_INTEL_ALL (MSR_INTEL_PENTIUM | MSR_PX_CX_AT_XE)
+
+struct msr_debug_base {
+ char *name; /* MSR name */
+ unsigned flag; /* MSR flag */
+};
+
+struct msr_debug_range {
+ unsigned min; /* MSR range min */
+ unsigned max; /* MSR range max */
+ unsigned flag; /* Supported flags */
+ unsigned model; /* Supported models */
+};
+
+struct msr_private {
+ unsigned cpu;
+ unsigned msr;
+ unsigned count;
+};
+
+extern struct dentry *arch_cpu_debugfs_dir;
+
+#endif /* _ASM_X86_MSR_DEBUG_H */
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index c381330..6c9187a 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -9,7 +9,7 @@ endif

obj-y := intel_cacheinfo.o addon_cpuid_features.o
obj-y += proc.o capflags.o powerflags.o common.o
-obj-y += vmware.o hypervisor.o
+obj-y += vmware.o hypervisor.o msr_debug.o

obj-$(CONFIG_X86_32) += bugs.o cmpxchg.o
obj-$(CONFIG_X86_64) += bugs_64.o
diff --git a/arch/x86/kernel/cpu/msr_debug.c b/arch/x86/kernel/cpu/msr_debug.c
new file mode 100755
index 0000000..7ce60bf
--- /dev/null
+++ b/arch/x86/kernel/cpu/msr_debug.c
@@ -0,0 +1,463 @@
+/*
+ * Model Specific Registers (MSR) x86 architecture debug code
+ *
+ * Copyright(C) 2009 Jaswinder Singh Rajput
+ *
+ * For licencing details see kernel-base/COPYING
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <asm/msr_debug.h>
+
+static struct msr_debug_base msr_base[] = {
+ { "mc", MSR_MC }, /* Machine Check */
+ { "monitor", MSR_MONITOR }, /* Monitor */
+ { "time", MSR_TIME }, /* Time */
+ { "pmc", MSR_PMC }, /* Performance Monitor */
+ { "platform", MSR_PLATFORM }, /* Platform */
+ { "apic", MSR_APIC }, /* APIC */
+ { "poweron", MSR_POWERON }, /* Power-on */
+ { "control", MSR_CONTROL }, /* Control */
+ { "features", MSR_FEATURES }, /* Features control */
+ { "lastbranch", MSR_LBRANCH }, /* Last Branch */
+ { "bios", MSR_BIOS }, /* BIOS */
+ { "freq", MSR_FREQ }, /* Frequency */
+ { "mttr", MSR_MTRR }, /* MTRR */
+ { "perf", MSR_PERF }, /* Performance */
+ { "cache", MSR_CACHE }, /* Cache */
+ { "sysenter", MSR_SYSENTER }, /* Sysenter */
+ { "therm", MSR_THERM }, /* Thermal */
+ { "misc", MSR_MISC }, /* Miscellaneous */
+ { "debug", MSR_DEBUG }, /* Debug */
+ { "pat", MSR_PAT }, /* PAT */
+ { "vmx", MSR_VMX }, /* VMX */
+ { "call", MSR_CALL }, /* System Call */
+ { "base", MSR_BASE }, /* BASE Address */
+ { "smm", MSR_SMM }, /* System mgmt mode */
+ { "svm", MSR_SVM }, /*Secure Virtial Machine*/
+ { "osvm", MSR_OSVM }, /* OS-Visible Workaround*/
+ { "msr", MSR_ALL }, /* Select all MSRs */
+};
+
+/* Intel MSRs Range */
+static struct msr_debug_range msr_intel_range[] = {
+ { 0x00000000, 0x00000001, MSR_MC, MSR_INTEL_ALL },
+ { 0x00000006, 0x00000007, MSR_MONITOR, MSR_CX_AT_XE },
+ { 0x00000010, 0x00000010, MSR_TIME, MSR_INTEL_ALL },
+ { 0x00000011, 0x00000013, MSR_PMC, MSR_INTEL_PENTIUM },
+ { 0x00000017, 0x00000017, MSR_PLATFORM, MSR_PX_CX_AT_XE },
+ { 0x0000001B, 0x0000001B, MSR_APIC, MSR_P6_CX_AT_XE },
+
+ { 0x0000002A, 0x0000002A, MSR_POWERON, MSR_PX_CX_AT_XE },
+ { 0x0000002B, 0x0000002B, MSR_POWERON, MSR_INTEL_XEON },
+ { 0x0000002C, 0x0000002C, MSR_FREQ, MSR_INTEL_XEON },
+ { 0x0000003A, 0x0000003A, MSR_CONTROL, MSR_CX_AT_XE },
+
+ { 0x00000040, 0x00000043, MSR_LBRANCH, MSR_PM_CX_AT_XE },
+ { 0x00000044, 0x00000047, MSR_LBRANCH, MSR_PM_CO_AT },
+ { 0x00000060, 0x00000063, MSR_LBRANCH, MSR_C2_AT },
+ { 0x00000064, 0x00000067, MSR_LBRANCH, MSR_INTEL_ATOM },
+
+ { 0x00000079, 0x00000079, MSR_BIOS, MSR_P6_CX_AT_XE },
+ { 0x00000088, 0x0000008A, MSR_CACHE, MSR_INTEL_P6 },
+ { 0x0000008B, 0x0000008B, MSR_BIOS, MSR_P6_CX_AT_XE },
+ { 0x0000009B, 0x0000009B, MSR_MONITOR, MSR_INTEL_XEON },
+
+ { 0x000000C1, 0x000000C2, MSR_PMC, MSR_P6_CX_AT },
+ { 0x000000CD, 0x000000CD, MSR_FREQ, MSR_CX_AT },
+ { 0x000000E7, 0x000000E8, MSR_PERF, MSR_CX_AT },
+ { 0x000000FE, 0x000000FE, MSR_MTRR, MSR_P6_CX_XE },
+
+ { 0x00000116, 0x00000116, MSR_CACHE, MSR_INTEL_P6 },
+ { 0x00000118, 0x00000118, MSR_CACHE, MSR_INTEL_P6 },
+ { 0x00000119, 0x00000119, MSR_CACHE, MSR_INTEL_PX },
+ { 0x0000011A, 0x0000011B, MSR_CACHE, MSR_INTEL_P6 },
+ { 0x0000011E, 0x0000011E, MSR_CACHE, MSR_PX_CX_AT },
+
+ { 0x00000174, 0x00000176, MSR_SYSENTER, MSR_P6_CX_AT_XE },
+ { 0x00000179, 0x0000017A, MSR_MC, MSR_PX_CX_AT_XE },
+ { 0x0000017B, 0x0000017B, MSR_MC, MSR_P6_XE },
+ { 0x00000186, 0x00000187, MSR_PMC, MSR_P6_CX_AT },
+ { 0x00000198, 0x00000199, MSR_PERF, MSR_PM_CX_AT_XE },
+ { 0x0000019A, 0x0000019A, MSR_TIME, MSR_PM_CX_AT_XE },
+ { 0x0000019B, 0x0000019D, MSR_THERM, MSR_PM_CX_AT_XE },
+ { 0x000001A0, 0x000001A0, MSR_MISC, MSR_PM_CX_AT_XE },
+
+ { 0x000001C9, 0x000001C9, MSR_LBRANCH, MSR_PM_CX_AT },
+ { 0x000001D7, 0x000001D8, MSR_LBRANCH, MSR_INTEL_XEON },
+ { 0x000001D9, 0x000001D9, MSR_DEBUG, MSR_CX_AT_XE },
+ { 0x000001DA, 0x000001DA, MSR_LBRANCH, MSR_INTEL_XEON },
+ { 0x000001DB, 0x000001DB, MSR_LBRANCH, MSR_P6_XE },
+ { 0x000001DC, 0x000001DC, MSR_LBRANCH, MSR_INTEL_P6 },
+ { 0x000001DD, 0x000001DE, MSR_LBRANCH, MSR_PX_CX_AT_XE },
+ { 0x000001E0, 0x000001E0, MSR_LBRANCH, MSR_INTEL_P6 },
+
+ { 0x00000200, 0x0000020F, MSR_MTRR, MSR_P6_CX_XE },
+ { 0x00000250, 0x00000250, MSR_MTRR, MSR_P6_CX_XE },
+ { 0x00000258, 0x00000259, MSR_MTRR, MSR_P6_CX_XE },
+ { 0x00000268, 0x0000026F, MSR_MTRR, MSR_P6_CX_XE },
+ { 0x00000277, 0x00000277, MSR_PAT, MSR_C2_AT_XE },
+ { 0x000002FF, 0x000002FF, MSR_MTRR, MSR_P6_CX_XE },
+
+ { 0x00000300, 0x00000308, MSR_PMC, MSR_INTEL_XEON },
+ { 0x00000309, 0x0000030B, MSR_PMC, MSR_C2_AT_XE },
+ { 0x0000030C, 0x00000311, MSR_PMC, MSR_INTEL_XEON },
+ { 0x00000345, 0x00000345, MSR_PMC, MSR_C2_AT },
+ { 0x00000360, 0x00000371, MSR_PMC, MSR_INTEL_XEON },
+ { 0x0000038D, 0x00000390, MSR_PMC, MSR_C2_AT },
+ { 0x000003A0, 0x000003BE, MSR_PMC, MSR_INTEL_XEON },
+ { 0x000003C0, 0x000003CD, MSR_PMC, MSR_INTEL_XEON },
+ { 0x000003E0, 0x000003E1, MSR_PMC, MSR_INTEL_XEON },
+ { 0x000003F0, 0x000003F0, MSR_PMC, MSR_INTEL_XEON },
+ { 0x000003F1, 0x000003F1, MSR_PMC, MSR_C2_AT_XE },
+ { 0x000003F2, 0x000003F2, MSR_PMC, MSR_INTEL_XEON },
+
+ { 0x00000400, 0x00000402, MSR_MC, MSR_PM_CX_AT_XE },
+ { 0x00000403, 0x00000403, MSR_MC, MSR_INTEL_XEON },
+ { 0x00000404, 0x00000406, MSR_MC, MSR_PM_CX_AT_XE },
+ { 0x00000407, 0x00000407, MSR_MC, MSR_INTEL_XEON },
+ { 0x00000408, 0x0000040A, MSR_MC, MSR_PM_CX_AT_XE },
+ { 0x0000040B, 0x0000040B, MSR_MC, MSR_INTEL_XEON },
+ { 0x0000040C, 0x0000040E, MSR_MC, MSR_PM_CX_XE },
+ { 0x0000040F, 0x0000040F, MSR_MC, MSR_INTEL_XEON },
+ { 0x00000410, 0x00000412, MSR_MC, MSR_PM_CX_AT_XE },
+ { 0x00000413, 0x00000417, MSR_MC, MSR_CX_AT_XE },
+ { 0x00000480, 0x0000048B, MSR_VMX, MSR_CX_AT_XE },
+
+ { 0x00000600, 0x00000600, MSR_DEBUG, MSR_PM_CX_AT_XE },
+ { 0x00000680, 0x0000068F, MSR_LBRANCH, MSR_INTEL_XEON },
+ { 0x000006C0, 0x000006CF, MSR_LBRANCH, MSR_INTEL_XEON },
+
+ { 0x000107CC, 0x000107D3, MSR_PMC, MSR_INTEL_XEON_MP },
+
+ { 0xC0000080, 0xC0000080, MSR_FEATURES, MSR_INTEL_XEON },
+ { 0xC0000081, 0xC0000082, MSR_CALL, MSR_INTEL_XEON },
+ { 0xC0000084, 0xC0000084, MSR_CALL, MSR_INTEL_XEON },
+ { 0xC0000100, 0xC0000102, MSR_BASE, MSR_INTEL_XEON },
+};
+
+/* AMD MSRs Range */
+static struct msr_debug_range msr_amd_range[] = {
+ { 0x00000010, 0x00000010, MSR_TIME, MSR_CPU_ALL, },
+ { 0x0000001B, 0x0000001B, MSR_APIC, MSR_CPU_ALL, },
+ { 0x000000FE, 0x000000FE, MSR_MTRR, MSR_CPU_ALL, },
+
+ { 0x00000174, 0x00000176, MSR_SYSENTER, MSR_CPU_ALL, },
+ { 0x00000179, 0x0000017A, MSR_MC, MSR_CPU_ALL, },
+ { 0x0000017B, 0x0000017B, MSR_MC, MSR_CPU_ALL, },
+ { 0x000001D9, 0x000001D9, MSR_DEBUG, MSR_CPU_ALL, },
+ { 0x000001DB, 0x000001DE, MSR_LBRANCH, MSR_CPU_ALL, },
+
+ { 0x00000200, 0x0000020F, MSR_MTRR, MSR_CPU_ALL, },
+ { 0x00000250, 0x00000250, MSR_MTRR, MSR_CPU_ALL, },
+ { 0x00000258, 0x00000259, MSR_MTRR, MSR_CPU_ALL, },
+ { 0x00000268, 0x0000026F, MSR_MTRR, MSR_CPU_ALL, },
+ { 0x00000277, 0x00000277, MSR_PAT, MSR_CPU_ALL, },
+ { 0x000002FF, 0x000002FF, MSR_MTRR, MSR_CPU_ALL, },
+
+ { 0x00000400, 0x00000417, MSR_MC, MSR_CPU_ALL, },
+
+ { 0xC0000080, 0xC0000080, MSR_FEATURES, MSR_CPU_ALL },
+ { 0xC0000081, 0xC0000084, MSR_CALL, MSR_CPU_ALL },
+ { 0xC0000100, 0xC0000102, MSR_BASE, MSR_CPU_ALL },
+ { 0xC0000103, 0xC0000103, MSR_TIME, MSR_CPU_ALL },
+
+ { 0xC0000408, 0xC000040A, MSR_MC, MSR_CPU_ALL, },
+
+ { 0xc0010000, 0xc0010007, MSR_PMC, MSR_CPU_ALL },
+ { 0xc0010010, 0xc0010010, MSR_MTRR, MSR_CPU_ALL },
+ { 0xc0010016, 0xc001001A, MSR_MTRR, MSR_CPU_ALL },
+ { 0xc001001D, 0xc001001D, MSR_MTRR, MSR_CPU_ALL },
+ { 0xc0010030, 0xc0010035, MSR_BIOS, MSR_CPU_ALL },
+ { 0xc0010056, 0xc0010056, MSR_SMM, MSR_CPU_ALL },
+ { 0xc0010061, 0xc0010063, MSR_SMM, MSR_CPU_ALL },
+ { 0xc0010074, 0xc0010074, MSR_MC, MSR_CPU_ALL },
+ { 0xc0010111, 0xc0010113, MSR_SMM, MSR_CPU_ALL },
+ { 0xc0010114, 0xc0010118, MSR_SVM, MSR_CPU_ALL },
+ { 0xc0010119, 0xc001011A, MSR_SMM, MSR_CPU_ALL },
+ { 0xc0010140, 0xc0010141, MSR_OSVM, MSR_CPU_ALL },
+ { 0xc0010156, 0xc0010156, MSR_SMM, MSR_CPU_ALL },
+};
+
+static DEFINE_MUTEX(msr_debug_lock);
+
+static int get_msr_intel_bit(unsigned model)
+{
+ int ret = 0;
+
+ switch (model) {
+ case 0x0501:
+ case 0x0502:
+ case 0x0504:
+ ret = MSR_INTEL_PENTIUM;
+ break;
+ case 0x0601:
+ case 0x0603:
+ case 0x0605:
+ case 0x0607:
+ case 0x0608:
+ case 0x060A:
+ case 0x060B:
+ ret = MSR_INTEL_P6;
+ break;
+ case 0x0609:
+ case 0x060D:
+ ret = MSR_INTEL_PENTIUM_M;
+ break;
+ case 0x060E:
+ ret = MSR_INTEL_CORE;
+ break;
+ case 0x060F:
+ case 0x0617:
+ ret = MSR_INTEL_CORE2;
+ break;
+ case 0x061C:
+ ret = MSR_INTEL_ATOM;
+ break;
+ case 0x0F00:
+ case 0x0F01:
+ case 0x0F02:
+ case 0x0F03:
+ case 0x0F04:
+ ret = MSR_INTEL_XEON_P4;
+ break;
+ case 0x0F06:
+ ret = MSR_INTEL_XEON_MP;
+ break;
+ }
+
+ return ret;
+}
+
+static int get_msr_cpu_bit(unsigned model)
+{
+ unsigned vendor;
+
+ vendor = model >> 16;
+ if (vendor == X86_VENDOR_INTEL)
+ return get_msr_intel_bit(model & 0xffff);
+ else
+ return 0;
+}
+
+static unsigned get_msr_range(unsigned *min, unsigned *max, int index,
+ unsigned flag, unsigned model)
+{
+ unsigned vendor, cpu_bit;
+
+ vendor = model >> 16;
+ cpu_bit = get_msr_cpu_bit(model);
+ *max = 0;
+ if (vendor == X86_VENDOR_INTEL) {
+ if ((msr_intel_range[index].model & cpu_bit) &&
+ (msr_intel_range[index].flag & flag)) {
+ *min = msr_intel_range[index].min;
+ *max = msr_intel_range[index].max;
+ }
+ } else if (vendor == X86_VENDOR_AMD) {
+ if (msr_amd_range[index].flag & flag) {
+ *min = msr_amd_range[index].min;
+ *max = msr_amd_range[index].max;
+ }
+ }
+
+ return *max;
+}
+
+static int get_msr_range_count(unsigned flag, unsigned model)
+{
+ int index = 0;
+
+ model >>= 16;
+ if (model == X86_VENDOR_INTEL)
+ index = ARRAY_SIZE(msr_intel_range);
+ else if (model == X86_VENDOR_AMD)
+ index = ARRAY_SIZE(msr_amd_range);
+
+ return index;
+}
+
+static void print_intel_msr(struct seq_file *seq, unsigned int cpu,
+ unsigned flag, unsigned model)
+{
+ int i, range;
+ u32 low, high;
+ unsigned msr, msr_min, msr_max;
+
+ range = get_msr_range_count(flag, model);
+
+ for (i = 0; i < range; i++) {
+ if (!get_msr_range(&msr_min, &msr_max, i, flag, model))
+ continue;
+ for (msr = msr_min; msr <= msr_max; msr++) {
+ if (rdmsr_safe_on_cpu(cpu, msr, &low, &high))
+ continue;
+ if (seq)
+ seq_printf(seq, " MSR_%08x: %08x_%08x\n",
+ msr, high, low);
+ else
+ printk(KERN_INFO " MSR_%08x: %08x_%08x\n",
+ msr, high, low);
+ }
+ }
+}
+
+static void print_amd_msr(struct seq_file *seq, unsigned flag, unsigned model)
+{
+ int i, range;
+ u64 val;
+ unsigned msr, msr_min, msr_max;
+
+ range = get_msr_range_count(flag, model);
+
+ for (i = 0; i < range; i++) {
+ if (!get_msr_range(&msr_min, &msr_max, i, flag, model))
+ continue;
+ for (msr = msr_min; msr <= msr_max; msr++) {
+ if (rdmsrl_amd_safe(msr, &val))
+ continue;
+ if (seq)
+ seq_printf(seq, " MSR_%08x: %016llx\n",
+ msr, val);
+ else
+ printk(KERN_INFO " MSR_%08x: %016llx\n",
+ msr, val);
+ }
+ }
+}
+
+static int msr_seq_show(struct seq_file *seq, void *v)
+{
+ unsigned model, flag;
+ struct cpuinfo_x86 *cpu = &cpu_data(0);
+ struct msr_private *priv = seq->private;
+
+#ifdef CONFIG_SMP
+ /* We are only interested for core_id 0 */
+ if (cpu->cpu_core_id || cpu->apicid)
+ return 0;
+#endif
+ model = ((cpu->x86_vendor << 16) | (cpu->x86 << 8) | (cpu->x86_model));
+ flag = msr_base[priv->msr].flag;
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+ print_intel_msr(seq, cpu->phys_proc_id, flag, model);
+ else
+ print_amd_msr(seq, flag, model);
+
+ seq_printf(seq, "\n");
+
+ return 0;
+}
+
+static void *msr_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ struct cpuinfo_x86 *c = NULL;
+
+ if (*pos == 0) /* just in case, cpu 0 is not the first */
+ c = &cpu_data(*pos);
+
+ return c;
+}
+
+static void *msr_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ (*pos)++;
+
+ return msr_seq_start(seq, pos);
+}
+
+static void msr_seq_stop(struct seq_file *seq, void *v)
+{
+}
+
+static const struct seq_operations msr_seq_ops = {
+ .start = msr_seq_start,
+ .next = msr_seq_next,
+ .stop = msr_seq_stop,
+ .show = msr_seq_show,
+};
+
+static int msr_seq_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ struct msr_private *priv;
+ int err;
+ unsigned private = inode->i_private;
+
+ err = seq_open(file, &msr_seq_ops);
+ mutex_lock(&msr_debug_lock);
+ if (!err) {
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (priv) {
+ seq = file->private_data;
+ priv->cpu = (private & 0xFF);
+ private >>= 8;
+ priv->msr = (private & 0xFF);
+ private >>= 8;
+ priv->count = (private & 0xFF);
+ seq->private = priv;
+ } else
+ err = -ENOMEM;
+
+ }
+ mutex_unlock(&msr_debug_lock);
+
+ return err;
+}
+
+static int msr_seq_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq = (struct seq_file *)file->private_data;
+ struct msr_private *priv = seq->private;
+
+ seq_release(inode, file);
+ kfree(priv);
+
+ return 0;
+}
+
+static const struct file_operations msr_fops = {
+ .open = msr_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = msr_seq_release,
+};
+
+static struct dentry *msr_debugfs_dir;
+
+static int __init msr_debug_init(void)
+{
+ int i;
+ unsigned priv_data;
+ struct dentry *msr_dentry;
+ struct cpuinfo_x86 *cpu = &cpu_data(0);
+
+ if (!cpu_has(cpu, X86_FEATURE_MSR))
+ return -ENODEV;
+
+ msr_debugfs_dir = debugfs_create_dir("msr", arch_cpu_debugfs_dir);
+ msr_dentry = debugfs_create_dir("cpu0", msr_debugfs_dir);
+
+ for (i = 0; i < ARRAY_SIZE(msr_base); i++) {
+ priv_data = i << 8;
+ debugfs_create_file(msr_base[i].name, S_IRUGO, msr_dentry,
+ (void *)priv_data, &msr_fops);
+ }
+ return 0;
+}
+
+static void __exit msr_debug_exit(void)
+{
+ if (msr_debugfs_dir)
+ debugfs_remove_recursive(msr_debugfs_dir);
+}
+
+module_init(msr_debug_init);
+module_exit(msr_debug_exit);
+
+MODULE_AUTHOR("Jaswinder Singh Rajput");
+MODULE_DESCRIPTION("MSR debug module");
+MODULE_LICENSE("GPL");
diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
index ff7d3b0..2fa3b08 100644
--- a/arch/x86/kernel/kdebugfs.c
+++ b/arch/x86/kernel/kdebugfs.c
@@ -19,6 +19,9 @@
struct dentry *arch_debugfs_dir;
EXPORT_SYMBOL(arch_debugfs_dir);

+struct dentry *arch_cpu_debugfs_dir;
+EXPORT_SYMBOL(arch_cpu_debugfs_dir);
+
#ifdef CONFIG_DEBUG_BOOT_PARAMS
struct setup_data_node {
u64 paddr;
@@ -218,6 +221,10 @@ static int __init arch_kdebugfs_init(void)
if (!arch_debugfs_dir)
return -ENOMEM;

+ arch_cpu_debugfs_dir = debugfs_create_dir("cpu", arch_debugfs_dir);
+ if (!arch_cpu_debugfs_dir)
+ return -ENOMEM;
+
#ifdef CONFIG_DEBUG_BOOT_PARAMS
error = boot_params_kdebugfs_init();
#endif

Subject: Re: [git-pull -tip V2] x86: msr architecture debug code

On Thu, Mar 05, 2009 at 02:19:56AM +0530, Jaswinder Singh Rajput wrote:
> On Thu, 2009-03-05 at 00:46 +0530, Jaswinder Singh Rajput wrote:
>
> > The following changes since commit 1d10914bf2c8a1164aef6c341e6c3518a91b8374:
> > Ingo Molnar (1):
> > Merge branch 'core/percpu'
> >
> > are available in the git repository at:
> >
> > git://git.kernel.org/pub/scm/linux/kernel/git/jaswinder/linux-2.6-tip-cpu.git master
> >
> > Jaswinder Singh Rajput (1):
> > x86: msr architecture debug code

Hi,

Why do we need this in-kernel?
We have already access to MSRs via /dev/cpu/*/msr

Did you have a look at x86info. (see
http://www.codemonkey.org.uk/projects/x86info/)
Recent versions contain a tool called lsmsr -- which shows you MSRs
and also decodes some bits, e.g.

# lsmsr IntPendingMessage -V 3 -c 1
IntPendingMessage = 0x00000000082100b0
IOMsgAddr=0xb0
IOMsgData=0x21
IntrPndMsgDis=0
IntrPndMsg=0
IORd=0
SmiOnCmpHalt=0x1
C1eOnCmpHalt=0

The tool just lacks some detailed MSR definitions for non-AMD CPUs.
Feel free to add them ... (and to fix bugs if encountered ;-)

Of course I've applied your patch to do a sniff test and found the
following:

- I've just one directory in debugfs
x86/cpu/msr/cpu0
The system has a quad-core CPU. So I guess there should be 4
directories -- one for each core.

- The file showing MTRRs is misspelled (mttr instead of mtrr).


Regards,
Andreas


--
Operating | Advanced Micro Devices GmbH
System | Karl-Hammerschmidt-Str. 34, 85609 Dornach b. M?nchen, Germany
Research | Gesch?ftsf?hrer: Jochen Polster, Thomas M. McCoy, Giuliano Meroni
Center | Sitz: Dornach, Gemeinde Aschheim, Landkreis M?nchen
(OSRC) | Registergericht M?nchen, HRB Nr. 43632

2009-03-05 13:13:35

by Jaswinder Singh Rajput

[permalink] [raw]
Subject: Re: [git-pull -tip V2] x86: msr architecture debug code

Hello Andreas,

Thanks for your review.

On Thu, 2009-03-05 at 13:21 +0100, Andreas Herrmann wrote:
> On Thu, Mar 05, 2009 at 02:19:56AM +0530, Jaswinder Singh Rajput wrote:
> Hi,
>
> Why do we need this in-kernel?
> We have already access to MSRs via /dev/cpu/*/msr
>
> Did you have a look at x86info. (see
> http://www.codemonkey.org.uk/projects/x86info/)
> Recent versions contain a tool called lsmsr -- which shows you MSRs
> and also decodes some bits, e.g.
>

Its looks good but I have planning to add much more features in
msr_debug and also Ingo suggested to add more features (please check his
email in this thread)

I am planning to use msr_debug for my development and also want to do
System development by using it.

This is just a beginning. I am just making basic setup I will add
features from this point ;-)



> The tool just lacks some detailed MSR definitions for non-AMD CPUs.
> Feel free to add them ... (and to fix bugs if encountered ;-)
>

Sure I will also check it.
Can you please forward some links or Manuals of AMD to this email
address so that I can also do some magic with AMD or another Intel based
CPUs.

> Of course I've applied your patch to do a sniff test and found the
> following:
>
> - I've just one directory in debugfs
> x86/cpu/msr/cpu0
> The system has a quad-core CPU. So I guess there should be 4
> directories -- one for each core.
>

In this Version I just made for cpu0, in V1 I was doing it for each
cpu_core_id, I mean for each package.

I think, there is no point of showing MSR/cores It will show the same
information. Please correct me If I am wrong.

But if you guys want I can make for each core.

> - The file showing MTRRs is misspelled (mttr instead of mtrr).
>

Ok, I will fix it in next version.

Thanks,
--
JSR

2009-03-05 13:32:32

by Ingo Molnar

[permalink] [raw]
Subject: Re: [git-pull -tip V2] x86: msr architecture debug code


* Andreas Herrmann <[email protected]> wrote:

> On Thu, Mar 05, 2009 at 02:19:56AM +0530, Jaswinder Singh Rajput wrote:
> > On Thu, 2009-03-05 at 00:46 +0530, Jaswinder Singh Rajput wrote:
> >
> > > The following changes since commit 1d10914bf2c8a1164aef6c341e6c3518a91b8374:
> > > Ingo Molnar (1):
> > > Merge branch 'core/percpu'
> > >
> > > are available in the git repository at:
> > >
> > > git://git.kernel.org/pub/scm/linux/kernel/git/jaswinder/linux-2.6-tip-cpu.git master
> > >
> > > Jaswinder Singh Rajput (1):
> > > x86: msr architecture debug code
>
> Hi,
>
> Why do we need this in-kernel?
> We have already access to MSRs via /dev/cpu/*/msr
>
> Did you have a look at x86info. (see
> http://www.codemonkey.org.uk/projects/x86info/)
> Recent versions contain a tool called lsmsr -- which shows you MSRs
> and also decodes some bits, e.g.

Having debugfs access and a topical splitup of all MSRs (and
possibly other CPU data - not necessarily MSR accessible - such
as the CR bits, etc.) is a nice touch i think and allows the
quick inspection of various properties of a CPU.

> - I've just one directory in debugfs
> x86/cpu/msr/cpu0
> The system has a quad-core CPU. So I guess there should be 4
> directories -- one for each core.

Correct, most MSRs are per core - that needs to be fixed.

Ingo

2009-03-05 13:48:52

by Jaswinder Singh Rajput

[permalink] [raw]
Subject: Re: [git-pull -tip V2] x86: msr architecture debug code

On Thu, 2009-03-05 at 14:32 +0100, Ingo Molnar wrote:
> * Andreas Herrmann <[email protected]> wrote:
>
> > - I've just one directory in debugfs
> > x86/cpu/msr/cpu0
> > The system has a quad-core CPU. So I guess there should be 4
> > directories -- one for each core.
>
> Correct, most MSRs are per core - that needs to be fixed.

Ok I will support all cores in next Version.

Thanks,
--
JSR

Subject: Re: [git-pull -tip] x86: msr architecture debug code

On Mon, Mar 02, 2009 at 09:54:37PM +0100, Ingo Molnar wrote:
> * Jaswinder Singh Rajput <[email protected]> wrote:

Oops, didn't read this mail till the end.
Thus I missed this part.

> > +{
> > + struct cpuinfo_x86 *cpu = &cpu_data(0);
> > +
> > + if (!cpu_has(cpu, X86_FEATURE_MSR))
> > + return -ENODEV;
> > +
> > + msr_dir = debugfs_create_dir("msr", arch_debugfs_dir);
> > +
> > + msr_file = debugfs_create_file("msr", S_IRUGO, msr_dir,
> > + NULL, &msr_fops);
> > + pmc_file = debugfs_create_file("pmc", S_IRUGO, msr_dir,
> > + NULL, &pmc_fops);
>
> I think it would be possible to have a much more intuitive file
> layout under /debug/x86/msr/ than these two /debug/x86/msr/msr
> and /debug/x86/msr/pmc files.
>
> Firstly, it should move one level deeper, to /debug/x86/cpu/msr/
> - because the MSR is really a property of the CPU, and there are
> other properties of the CPU we might want to expose in the
> future.
>
> Secondly, the picking of debugfs (as opposed to sysfs) is a good
> choice, because we probably want to tweak the layout a number of
> times and want to keep flexibility, without being limited by the
> sysfs ABI.
>
> So i like the idea - but we really want to do even more and add
> more structure to this. If we just want dumb msr enumeration we
> already have /dev/msr.
>
> Regarding the msr directory: one good approach would be to have
> have several "topic" directories under /debug/x86/cpu/msr/.
>
> One such topic would be the 'pmu', with a structure like:
>
> /debug/x86/cpu/msr/pmu/
> /debug/x86/cpu/msr/pmu/pmc_0/
> /debug/x86/cpu/msr/pmu/pmc_0/counter
> /debug/x86/cpu/msr/pmu/pmc_0/eventsel
>
> There would also be a /debug/x86/cpu/msr/raw/ directory with all
> MSR numbers we know about explicitly, for example:
>
> /debug/x86/cpu/msr/raw/0x372/value
> /debug/x86/cpu/msr/raw/0x372/width

Having this stuff in the kernel unnecessarily bloats up kernel code.
What the kernel needs to provide is a reliable interface to access
MSRs -- to pass the data to userspace. This interface is already there.

IMHO all kind of parsing and grouping of that data belongs in user
space.

One exception are MSRs that need to be checked early during boot
(e.g. MTRRs). For debugging purposes you might want to dump certain
MSRs early. But then you will use printk and not debugfs.

> Maybe a symlink pointing it back to the topic directory would be
> useful as well. For example:
>
> /debug/x86/cpu/msr/raw/0x372/topic_dir -> /debug/x86/cpu/msr/pmu/pmc_0/
>
> Other "topic directories" are possible too: a
> /debug/x86/cpu/msr/apic/ layout would be very useful and
> informative as well, and so are some of the other MSRs we tweak
> during bootup.

All nice suggestions but why in-kernel?

Just hack some script to do this. This is much more maintainable.
You don't need a kernel update to add support for new CPUs or to fix
bugs in this code itself -- you just have to tweak your script.


Regards,
Andreas

2009-03-05 14:08:34

by Ingo Molnar

[permalink] [raw]
Subject: Re: [git-pull -tip] x86: msr architecture debug code


* Andreas Herrmann <[email protected]> wrote:

> On Mon, Mar 02, 2009 at 09:54:37PM +0100, Ingo Molnar wrote:
> > * Jaswinder Singh Rajput <[email protected]> wrote:
>
> Oops, didn't read this mail till the end.
> Thus I missed this part.
>
> > > +{
> > > + struct cpuinfo_x86 *cpu = &cpu_data(0);
> > > +
> > > + if (!cpu_has(cpu, X86_FEATURE_MSR))
> > > + return -ENODEV;
> > > +
> > > + msr_dir = debugfs_create_dir("msr", arch_debugfs_dir);
> > > +
> > > + msr_file = debugfs_create_file("msr", S_IRUGO, msr_dir,
> > > + NULL, &msr_fops);
> > > + pmc_file = debugfs_create_file("pmc", S_IRUGO, msr_dir,
> > > + NULL, &pmc_fops);
> >
> > I think it would be possible to have a much more intuitive file
> > layout under /debug/x86/msr/ than these two /debug/x86/msr/msr
> > and /debug/x86/msr/pmc files.
> >
> > Firstly, it should move one level deeper, to /debug/x86/cpu/msr/
> > - because the MSR is really a property of the CPU, and there are
> > other properties of the CPU we might want to expose in the
> > future.
> >
> > Secondly, the picking of debugfs (as opposed to sysfs) is a good
> > choice, because we probably want to tweak the layout a number of
> > times and want to keep flexibility, without being limited by the
> > sysfs ABI.
> >
> > So i like the idea - but we really want to do even more and add
> > more structure to this. If we just want dumb msr enumeration we
> > already have /dev/msr.
> >
> > Regarding the msr directory: one good approach would be to have
> > have several "topic" directories under /debug/x86/cpu/msr/.
> >
> > One such topic would be the 'pmu', with a structure like:
> >
> > /debug/x86/cpu/msr/pmu/
> > /debug/x86/cpu/msr/pmu/pmc_0/
> > /debug/x86/cpu/msr/pmu/pmc_0/counter
> > /debug/x86/cpu/msr/pmu/pmc_0/eventsel
> >
> > There would also be a /debug/x86/cpu/msr/raw/ directory with all
> > MSR numbers we know about explicitly, for example:
> >
> > /debug/x86/cpu/msr/raw/0x372/value
> > /debug/x86/cpu/msr/raw/0x372/width
>
> Having this stuff in the kernel unnecessarily bloats up kernel code.

it should be a default-off Kconfig option and it is in debugfs
so there's no real bloat issue here.

> What the kernel needs to provide is a reliable interface to
> access MSRs -- to pass the data to userspace. This interface
> is already there.
>
> IMHO all kind of parsing and grouping of that data belongs in
> user space.
>
> One exception are MSRs that need to be checked early during
> boot (e.g. MTRRs). For debugging purposes you might want to
> dump certain MSRs early. But then you will use printk and not
> debugfs.

Well it's really nice to know the _kernel's_ enumeration of MSRs
and its knowledge about the structure of those MSRs.

Sure, we can and do export the flat MSR space to user-space, but
the kernel also enumerates them internally, in various places.
The debugfs interface shows them in one way - and as such also
acts as a central force to keep these things tidy.

a VFS namespace is also pretty educative. You can see which MSRs
matter to the lapic for example, you can see their symbolic
names, their current state, etc. etc.

> > Maybe a symlink pointing it back to the topic directory
> > would be useful as well. For example:
> >
> > /debug/x86/cpu/msr/raw/0x372/topic_dir -> /debug/x86/cpu/msr/pmu/pmc_0/
> >
> > Other "topic directories" are possible too: a
> > /debug/x86/cpu/msr/apic/ layout would be very useful and
> > informative as well, and so are some of the other MSRs we
> > tweak during bootup.
>
> All nice suggestions but why in-kernel?
>
> Just hack some script to do this. This is much more
> maintainable. You don't need a kernel update to add support
> for new CPUs or to fix bugs in this code itself -- you just
> have to tweak your script.

the kernel tends to know a lot about these MSRs already so we
just provide that information in a more structured form as well.

Such more structured form, beyond the debugging and
education/development advantages, also acts as a counter-force
back to the MSR enumeration code of the kernel and makes them
more structured. It will no doubt also extend the kernel's
knowledge of MSRs - read-only MSRs we dont normally read.

There's also a few other things like the IRR readout in the APIC
code or the perfcounters status dump can also be done cleanly
via /debug/x86/cpu/msr/.

Eventually i'd like /debug/x86/ to become a full CPU state dump:
the kernel pagetable dumping code could go there, we could show
control registers, we could show the GDT and IDT settings and
contents, etc. etc.

Ingo

2009-03-05 14:11:49

by Ingo Molnar

[permalink] [raw]
Subject: Re: [git-pull -tip V2] x86: msr architecture debug code


* Jaswinder Singh Rajput <[email protected]> wrote:

> On Thu, 2009-03-05 at 14:32 +0100, Ingo Molnar wrote:
> > * Andreas Herrmann <[email protected]> wrote:
> >
> > > - I've just one directory in debugfs
> > > x86/cpu/msr/cpu0
> > > The system has a quad-core CPU. So I guess there should be 4
> > > directories -- one for each core.
> >
> > Correct, most MSRs are per core - that needs to be fixed.
>
> Ok I will support all cores in next Version.

the VFS structure should be something like:

/debug/x86/cpu/cpu0/msr/...

I.e. first we have the CPU, then a specific CPU, and MSRs are
attributes of that CPU (core).

Maybe the topical setup shouldnt even include 'msr' in its name
- that way we'll be able to add non-MSR information too. I.e.
we'd have:

/debug/x86/cpu/cpu0/apic/...
/debug/x86/cpu/cpu0/pmu/...
/debug/x86/cpu/cpu0/cpu_features/...

Populated with symbolic MSR entries for the time being.

Another detail: there are MSRs that are shared between
cores/CPUs/sockets on certain models - but that's not a big
issue, the readouts will be mirrored.

Ingo

2009-03-05 14:13:18

by Jaswinder Singh Rajput

[permalink] [raw]
Subject: Re: [git-pull -tip] x86: msr architecture debug code

On Thu, 2009-03-05 at 14:54 +0100, Andreas Herrmann wrote:

> All nice suggestions but why in-kernel?
>

In Kernel Space:

We can read/write MSRs and can change the bits and see it effect without
writing any code.

And we can also dump these value if something goes wrong in thats
sections for kernel that's why I am also using printk.

Thanks,
--
JSR


2009-03-05 14:32:18

by Jaswinder Singh Rajput

[permalink] [raw]
Subject: Re: [git-pull -tip V2] x86: msr architecture debug code

On Thu, 2009-03-05 at 15:11 +0100, Ingo Molnar wrote:
> * Jaswinder Singh Rajput <[email protected]> wrote:
>
> > On Thu, 2009-03-05 at 14:32 +0100, Ingo Molnar wrote:
> > > * Andreas Herrmann <[email protected]> wrote:
> > >
> > > > - I've just one directory in debugfs
> > > > x86/cpu/msr/cpu0
> > > > The system has a quad-core CPU. So I guess there should be 4
> > > > directories -- one for each core.
> > >
> > > Correct, most MSRs are per core - that needs to be fixed.
> >
> > Ok I will support all cores in next Version.
>
> the VFS structure should be something like:
>
> /debug/x86/cpu/cpu0/msr/...
>
> I.e. first we have the CPU, then a specific CPU, and MSRs are
> attributes of that CPU (core).
>

I am also planning to add other CPU registers beside MSRs so msr will
differentiate that it is MSRs or normal register.

And we can move architecture independent code in kernel/* so that
another architectures will also take benefit from it.

--
JSR

Subject: Re: [git-pull -tip] x86: msr architecture debug code

On Thu, Mar 05, 2009 at 07:42:26PM +0530, Jaswinder Singh Rajput wrote:
> On Thu, 2009-03-05 at 14:54 +0100, Andreas Herrmann wrote:
>
> > All nice suggestions but why in-kernel?
> >
>
> In Kernel Space:
>
> We can read/write MSRs and can change the bits and see it effect without
> writing any code.

Sorry, I can't (or maybe I don't like to) follow.

(BTW, you don't even need to write C-code. You can use a one-liner in perl
or python to seek and read any MSR using /dev/cpu/*/msr.)

> And we can also dump these value if something goes wrong in thats
> sections for kernel that's why I am also using printk.

Just some example how to do this today. (I've recently used this for
debugging.) Using a kernel with msr module loaded or built-in plus using
x86info/lsmsr and hpa's msr-tools.

# lsmsr MTRRfix -c 0
MTRRfix64K_00000 = 0x0606060606060606
MTRRfix16K_80000 = 0x0606060606060606
MTRRfix16K_A0000 = 0x0000000000000000
MTRRfix4K_C0000 = 0x0505050505050505
MTRRfix4K_C8000 = 0x0505050505050505
MTRRfix4K_D0000 = 0x0000000000000000
MTRRfix4K_D8000 = 0x0000000000000000
MTRRfix4K_E0000 = 0x0505050500000000
MTRRfix4K_E8000 = 0x0505050505050505
MTRRfix4K_F0000 = 0x0505050505050505
MTRRfix4K_F8000 = 0x0505050505050505
# lsmsr SYS_CFG
SYS_CFG = 0x0000000000160600
# lsmsr SYS_CFG -l -V3
SYS_CFG : 0xc0010010
8-8:SetDirtyEnE
9-9:SetDirtyEnS
10-10:SetDirtyEnO
16-16:ChxToDirtyDis
17-17:SysUcLockEn
18-18:MtrrFixDramEn
19-19:MtrrFixDramModEn
20-20:MtrrVarDramEn
21-21:MtrrTom2En
22-22:Tom2ForceMemTypeWB
# wrmsr -p 0 0xc0010010 0x00000000001e0600
# lsmsr SYS_CFG
SYS_CFG = 0x00000000001e0600
# lsmsr MTRRfix -c 0
MTRRfix64K_00000 = 0x1e1e1e1e1e1e1e1e
MTRRfix16K_80000 = 0x1e1e1e1e1e1e1e1e
MTRRfix16K_A0000 = 0x0000000000000000
MTRRfix4K_C0000 = 0x1515151515151515
MTRRfix4K_C8000 = 0x1515151515151515
MTRRfix4K_D0000 = 0x0000000000000000
MTRRfix4K_D8000 = 0x0000000000000000
MTRRfix4K_E0000 = 0x1515151500000000
MTRRfix4K_E8000 = 0x1515151515151515
MTRRfix4K_F0000 = 0x1515151515151515
MTRRfix4K_F8000 = 0x1515151515151515


IMHO, there is no need to do this in-kernel.


Regards,

Andreas

--
Operating | Advanced Micro Devices GmbH
System | Karl-Hammerschmidt-Str. 34, 85609 Dornach b. M?nchen, Germany
Research | Gesch?ftsf?hrer: Jochen Polster, Thomas M. McCoy, Giuliano Meroni
Center | Sitz: Dornach, Gemeinde Aschheim, Landkreis M?nchen
(OSRC) | Registergericht M?nchen, HRB Nr. 43632

2009-03-05 15:17:47

by Jaswinder Singh Rajput

[permalink] [raw]
Subject: Re: [git-pull -tip] x86: msr architecture debug code

On Thu, 2009-03-05 at 15:37 +0100, Andreas Herrmann wrote:

>
> IMHO, there is no need to do this in-kernel.
>

Ingo already replied to this comment in his previous emails.

Thanks,

--
JSR

2009-03-05 15:48:19

by Jaswinder Singh Rajput

[permalink] [raw]
Subject: Re: [git-pull -tip] x86: msr architecture debug code


On Thu, 2009-03-05 at 15:37 +0100, Andreas Herrmann wrote:
> On Thu, Mar 05, 2009 at 07:42:26PM +0530, Jaswinder Singh Rajput wrote:
> > On Thu, 2009-03-05 at 14:54 +0100, Andreas Herrmann wrote:
> >
> > > All nice suggestions but why in-kernel?
> > >
> >
> > In Kernel Space:
> >
> > We can read/write MSRs and can change the bits and see it effect without
> > writing any code.
>
> Sorry, I can't (or maybe I don't like to) follow.
>
> (BTW, you don't even need to write C-code. You can use a one-liner in perl
> or python to seek and read any MSR using /dev/cpu/*/msr.)
>

You are running these commands on shell when every thing is working.

What you will do if you are not getting the shell and kernel is dumping
or rebooting before that.

--
JSR

Subject: Re: [git-pull -tip] x86: msr architecture debug code

On Thu, Mar 05, 2009 at 03:08:09PM +0100, Ingo Molnar wrote:
> * Andreas Herrmann <[email protected]> wrote:
> > Having this stuff in the kernel unnecessarily bloats up kernel code.
>
> it should be a default-off Kconfig option and it is in debugfs
> so there's no real bloat issue here.

I attached parts of an autogenerated file which contains MSR
definitions for AMD family 10h in some condensed format. I stripped off
some lines -- the file had 487 lines and is about 30k.
You really like to have similar stuff for all x86 CPUs in-kernel?

> > What the kernel needs to provide is a reliable interface to
> > access MSRs -- to pass the data to userspace. This interface
> > is already there.
> >
> > IMHO all kind of parsing and grouping of that data belongs in
> > user space.
> >
> > One exception are MSRs that need to be checked early during
> > boot (e.g. MTRRs). For debugging purposes you might want to
> > dump certain MSRs early. But then you will use printk and not
> > debugfs.
>
> Well it's really nice to know the _kernel's_ enumeration of MSRs
> and its knowledge about the structure of those MSRs.
>
> Sure, we can and do export the flat MSR space to user-space, but
> the kernel also enumerates them internally, in various places.
> The debugfs interface shows them in one way - and as such also
> acts as a central force to keep these things tidy.
>
> a VFS namespace is also pretty educative. You can see which MSRs
> matter to the lapic for example, you can see their symbolic
> names, their current state, etc. etc.

> > > Maybe a symlink pointing it back to the topic directory
> > > would be useful as well. For example:
> > >
> > > /debug/x86/cpu/msr/raw/0x372/topic_dir -> /debug/x86/cpu/msr/pmu/pmc_0/
> > >
> > > Other "topic directories" are possible too: a
> > > /debug/x86/cpu/msr/apic/ layout would be very useful and
> > > informative as well, and so are some of the other MSRs we
> > > tweak during bootup.
> >
> > All nice suggestions but why in-kernel?
> >
> > Just hack some script to do this. This is much more
> > maintainable. You don't need a kernel update to add support
> > for new CPUs or to fix bugs in this code itself -- you just
> > have to tweak your script.
>
> the kernel tends to know a lot about these MSRs already so we
> just provide that information in a more structured form as well.
>
> Such more structured form, beyond the debugging and
> education/development advantages, also acts as a counter-force
> back to the MSR enumeration code of the kernel and makes them
> more structured. It will no doubt also extend the kernel's
> knowledge of MSRs - read-only MSRs we dont normally read.

If we don't read them
we don't need them --
in kernel code.

The knowledge of MSRs is usually required by certain code, drivers or
subsystems. I think, we should only add MSR information if it is
needed for real kernel functionality. Some examples are

- MCA MSRs for mce
- Pstate and FIDVID MSRs for powernow-k8
- MTRRs for cpu/mtrr code

We don't have interfaces for PCI devices to show all their config
space register values in decoded form. The kernel provides the
interface to retrieve that information from userspace and usually you
call lspci to decode some standard information and to dump all the
rest.

For MSRs we have an interface, too. There is a lack of a standard
tool to do the decoding. (As a start you can use lsmsr.)

> There's also a few other things like the IRR readout in the APIC
> code or the perfcounters status dump can also be done cleanly
> via /debug/x86/cpu/msr/.
>
> Eventually i'd like /debug/x86/ to become a full CPU state dump:
> the kernel pagetable dumping code could go there, we could show
> control registers, we could show the GDT and IDT settings and
> contents, etc. etc.

Yes, we could do a lot in the kernel. But should we?

I second that dumping and decoding MSRs (and also CPU config space
registers for AMD CPUs) is sometimes needed for debugging. But doing
all of this in-kernel -- I think, that's not cool.


Regards,
Andreas

--
/*
* Licensed under the terms of the GNU GENERAL PUBLIC LICENSE version 2.
* See file COPYING for details.
*/

#ifndef fam10h_h
#define fam10h_h

#include "../msr.h"

_RANGE(fam10h_LSMCAaddr,48,16,0);
_NAMES(fam10h_LSMCAaddr,"ADDR",0);
_RANGE(fam10h_LSMCAstatus,16,4,25,1,1,8,2,1,1,1,1,1,1,1,0);
_NAMES(fam10h_LSMCAstatus,"ErrorCode","ErrorCodeExt",0,"UECC","CECC","SYND",0,"PCC","ADDRV","MISCV","EN","UC","OVER","VAL");
_RANGE(fam10h_TSC,64,0);
_NAMES(fam10h_TSC,"TSC");
_RANGE(fam10h_APIC_BASE,8,1,2,1,36,16,0);
_NAMES(fam10h_APIC_BASE,0,"BSC",0,"ApicEn","ApicBar",0);
_RANGE(fam10h_EBL_CR_POWERON,16,2,46,0);
_NAMES(fam10h_EBL_CR_POWERON,0,"ClusterID",0);
_RANGE(fam10h_PATCH_LEVEL,32,32,0);
_NAMES(fam10h_PATCH_LEVEL,"PATCH_LEVEL",0);
_RANGE(fam10h_MTRRcap,8,1,1,1,53,0);
_NAMES(fam10h_MTRRcap,"MtrrCapVCnt","MtrrCapFix",0,"MtrrCapWc",0);
_RANGE(fam10h_SYSENTER_CS,16,48,0);
_NAMES(fam10h_SYSENTER_CS,"SYSENTER_CS",0);
_RANGE(fam10h_SYSENTER_ESP,32,32,0);
_NAMES(fam10h_SYSENTER_ESP,"SYSENTER_ESP",0);
_RANGE(fam10h_SYSENTER_EIP,32,32,0);
_NAMES(fam10h_SYSENTER_EIP,"SYSENTER_EIP",0);
_RANGE(fam10h_MCG_CAP,8,1,55,0);
_NAMES(fam10h_MCG_CAP,"Count","MCG_CTL_P",0);
_RANGE(fam10h_MCG_STAT,1,1,1,61,0);
_NAMES(fam10h_MCG_STAT,"RIPV","EIPV","MCIP",0);
_RANGE(fam10h_MCG_CTL,1,1,1,1,1,1,58,0);
_NAMES(fam10h_MCG_CTL,"DCE","ICE","BUE","LSE","NBE","FRE",0);
_RANGE(fam10h_DBG_CTL_MSR,1,1,1,1,1,1,58,0);
_NAMES(fam10h_DBG_CTL_MSR,"LBR","BTF","PB0","PB1","PB2","PB3",0);
_RANGE(fam10h_BR_FROM,64,0);
_NAMES(fam10h_BR_FROM,"LastBranchFromIP");

...

_RANGE(fam10h_MC5_CTL,1,63,0);
_NAMES(fam10h_MC5_CTL,"CPUWDT",0);
_RANGE(fam10h_MC5_STATUS,16,4,4,8,8,1,4,1,1,8,2,1,1,1,1,1,1,1,0);
_NAMES(fam10h_MC5_STATUS,"ErrorCode","ErrorCodeExt",0,"Syndrome",0,"Scrub",0,"UECC","CECC","Syndrome",0,"PCC","AddrV","MiscV","En","UC","OVER","VAL");
_RANGE(fam10h_MC5_ADDR,48,16,0);
_NAMES(fam10h_MC5_ADDR,"ADDR",0);
_RANGE(fam10h_MC5_MISC,12,52,0);
_NAMES(fam10h_MC5_MISC,"State",0);
_RANGE(fam10h_EFER,1,7,1,1,1,1,1,1,1,49,0);
_NAMES(fam10h_EFER,"SYSCALL",0,"LME",0,"LMA","NXE","SVME","LMSLE","FFXSE",0);
_RANGE(fam10h_STAR,32,16,16,0);
_NAMES(fam10h_STAR,"Target","SysCallSel","SysRetSel");
_RANGE(fam10h_STAR64,64,0);
_NAMES(fam10h_STAR64,"LSTAR");
_RANGE(fam10h_STARCOMPAT,64,0);
_NAMES(fam10h_STARCOMPAT,"CSTAR");
_RANGE(fam10h_SYSCALL_FLAG_MASK,32,32,0);
_NAMES(fam10h_SYSCALL_FLAG_MASK,"MASK",0);
_RANGE(fam10h_FS_BASE,64,0);
_NAMES(fam10h_FS_BASE,"FS_BASE");
_RANGE(fam10h_GS_BASE,64,0);
_NAMES(fam10h_GS_BASE,"GS_BASE");
_RANGE(fam10h_KernelGSbase,64,0);
_NAMES(fam10h_KernelGSbase,"KernelGSBase");
_RANGE(fam10h_TSC_AUX,32,32,0);
_NAMES(fam10h_TSC_AUX,"TscAux",0);
_RANGE(fam10h_MC4_MISC1,24,8,12,4,1,2,1,4,5,1,1,1,0);
_NAMES(fam10h_MC4_MISC1,0,"BlkPtr","ErrCnt",0,"Ovrflw","IntType","CntEn","LvtOffset",0,"Locked","CntP","Valid");
_RANGE(fam10h_MC4_MISC2,24,8,12,4,1,2,1,4,5,1,1,1,0);
_NAMES(fam10h_MC4_MISC2,0,"BlkPtr","ErrCnt",0,"Ovrflw","IntType","CntEn","LvtOffset",0,"Locked","CntP","Valid");
_RANGE(fam10h_MC4_MISC3,24,8,32,0);
_NAMES(fam10h_MC4_MISC3,0,"BlkPtr",0);
_RANGE(fam10h_PERF_CTL0,8,8,1,1,1,1,1,1,1,1,8,4,4,1,1,22,0);
_NAMES(fam10h_PERF_CTL0,"EventSelect","UnitMask","User","OS","Edge",0,"Int",0,"En","Inv","CntMask","EventSelect",0,"GuestOnly","HostOnly",0);
_RANGE(fam10h_PERF_CTL1,8,8,1,1,1,1,1,1,1,1,8,4,4,1,1,22,0);
_NAMES(fam10h_PERF_CTL1,"EventSelect","UnitMask","User","OS","Edge",0,"Int",0,"En","Inv","CntMask","EventSelect",0,"GuestOnly","HostOnly",0);
_RANGE(fam10h_PERF_CTL2,8,8,1,1,1,1,1,1,1,1,8,4,4,1,1,22,0);
_NAMES(fam10h_PERF_CTL2,"EventSelect","UnitMask","User","OS","Edge",0,"Int",0,"En","Inv","CntMask","EventSelect",0,"GuestOnly","HostOnly",0);
_RANGE(fam10h_PERF_CTL3,8,8,1,1,1,1,1,1,1,1,8,4,4,1,1,22,0);
_NAMES(fam10h_PERF_CTL3,"EventSelect","UnitMask","User","OS","Edge",0,"Int",0,"En","Inv","CntMask","EventSelect",0,"GuestOnly","HostOnly",0);
_RANGE(fam10h_PERF_CTR0,48,16,0);
_NAMES(fam10h_PERF_CTR0,"CTR",0);

...

_RANGE(fam10h_IbsFetchCtl,16,16,16,1,1,1,1,1,2,1,1,1,6,0);
_NAMES(fam10h_IbsFetchCtl,"IbsFetchMaxCnt","IbsFetchCnt","IbsFetchLat","IbsFetchEn","IbsFetchVal","IbsFetchComp","IbsIcMiss","IbsPhyAddrValid","IbsL1TlbPgSz","IbsL1TlbMiss","IbsL2TlbMiss","IbsRandEn",0);
_RANGE(fam10h_IbsFetchLinAd,64,0);
_NAMES(fam10h_IbsFetchLinAd,"IbsFetchLinAd");
_RANGE(fam10h_IbsFetchPhysAd,64,0);
_NAMES(fam10h_IbsFetchPhysAd,"IbsFetchPhysAd");
_RANGE(fam10h_IbsOpCtl,16,1,1,1,45,0);
_NAMES(fam10h_IbsOpCtl,"IbsOpMaxCnt",0,"IbsOpEn","IbsOpVal",0);
_RANGE(fam10h_IbsOpRip,64,0);
_NAMES(fam10h_IbsOpRip,"IbsOpRip");
_RANGE(fam10h_IbsOpData,16,16,1,1,1,1,1,1,26,0);
_NAMES(fam10h_IbsOpData,"IbsCompToRetCtr","IbsTagToRetCtr","IbsOpBrnResync","IbsOpMispReturn","IbsOpReturn","IbsOpBrnTaken","IbsOpBrnMisp","IbsOpBrnRet",0);
_RANGE(fam10h_IbsOpData2,3,1,1,1,58,0);
_NAMES(fam10h_IbsOpData2,"NbIbsReqSrc",0,"NbIbsReqDstProc","NbIbsReqCacheHitSt",0);
_RANGE(fam10h_IbsOpData3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,13,16,16,0);
_NAMES(fam10h_IbsOpData3,"IbsLdOp","IbsStOp","IbsDcL1tlbMiss","IbsDcL2tlbMiss","IbsDcL1tlbHit2M","IbsDcL1tlbHit1G","IbsDcL2tlbHit2M","IbsDcMiss","IbsDcMisAcc","IbsDcLdBnkCon","IbsDcStBnkCon","IbsDcStToLdFwd","IbsDcStToLdCan","IbsDcUcMemAcc","IbsDcWcMemAcc","IbsDcLockedOp","IbsDcMabHit","IbsDcLinAddrValid","IbsDcPhyAddrValid",0,"IbsDcMissLat",0);
_RANGE(fam10h_IbsDcLinAd,64,0);
_NAMES(fam10h_IbsDcLinAd,"IbsDcLinAd");
_RANGE(fam10h_IbsDcPhysAd,64,0);
_NAMES(fam10h_IbsDcPhysAd,"IbsDcPhysAd");
_RANGE(fam10h_IbsControl,4,4,1,55,0);
_NAMES(fam10h_IbsControl,"LvtOffset",0,"LvtOffsetVal",0);

struct reg_spec fam10h_spec [] = {
_SPEC(0x0000, LSMCAaddr, "load-store MCA address", fam10h_),
_SPEC(0x0001, LSMCAstatus, "load-store MCE status", fam10h_),
_SPEC(0x0010, TSC, "time-stamp counter", fam10h_),
_SPEC(0x001b, APIC_BASE, "APIC base address", fam10h_),
_SPEC(0x002a, EBL_CR_POWERON, "cluster ID", fam10h_),
_SPEC(0x008b, PATCH_LEVEL, "microcode patch level", fam10h_),
_SPEC(0x00fe, MTRRcap, "MTRR capabilities", fam10h_),
_SPEC(0x0174, SYSENTER_CS, "SYSENTER/SYSEXIT code segment selector", fam10h_),
_SPEC(0x0175, SYSENTER_ESP, "SYSENTER/SYSEXIT stack pointer", fam10h_),
_SPEC(0x0176, SYSENTER_EIP, "SYSENTER/SYSEXIT instruction pointer", fam10h_),
_SPEC(0x0179, MCG_CAP, "global MC capabilities", fam10h_),
_SPEC(0x017a, MCG_STAT, "global MC status", fam10h_),
_SPEC(0x017b, MCG_CTL, "global MC control", fam10h_),
_SPEC(0x01d9, DBG_CTL_MSR, "debug control", fam10h_),
_SPEC(0x01db, BR_FROM, "last branch from IP", fam10h_),
_SPEC(0x01dc, BR_TO, "last branch to IP", fam10h_),
_SPEC(0x01dd, LastExceptionFromIP, "last exception from IP", fam10h_),
_SPEC(0x01de, LastExceptionToIP, "last exception to IP", fam10h_),
_SPEC(0x0200, MTRRphysBase0, "base of variable-size MTRR (0)", fam10h_),
_SPEC(0x0201, MTRRphysMask0, "mask of variable-size MTRR (0)", fam10h_),

...

_SPEC(0xc0011023, BU_CFG, "bus unit configuration", fam10h_),
_SPEC(0xc001102A, BU_CFG2, "bus unit configuration 2", fam10h_),
_SPEC(0xc0011030, IbsFetchCtl, "IBS fetch control", fam10h_),
_SPEC(0xc0011031, IbsFetchLinAd, "IBS fetch linear address", fam10h_),
_SPEC(0xc0011032, IbsFetchPhysAd, "IBS fetch physical address", fam10h_),
_SPEC(0xc0011033, IbsOpCtl, "IBS execution control", fam10h_),
_SPEC(0xc0011034, IbsOpRip, "IBS Op logical address", fam10h_),
_SPEC(0xc0011035, IbsOpData, "IBS Op data", fam10h_),
_SPEC(0xc0011036, IbsOpData2, "IBS Op data 2", fam10h_),
_SPEC(0xc0011037, IbsOpData3, "IBS Op data 3", fam10h_),
_SPEC(0xc0011038, IbsDcLinAd, "IBS DC linear address", fam10h_),
_SPEC(0xc0011039, IbsDcPhysAd, "IBS DC physical address", fam10h_),
_SPEC(0xc001103a, IbsControl, "IBS control", fam10h_),
{0, NULL, NULL, NULL, NULL},
};

#endif /* fam10h_h */

Subject: Re: [git-pull -tip] x86: msr architecture debug code

On Thu, Mar 05, 2009 at 09:17:37PM +0530, Jaswinder Singh Rajput wrote:
>
> On Thu, 2009-03-05 at 15:37 +0100, Andreas Herrmann wrote:
> > On Thu, Mar 05, 2009 at 07:42:26PM +0530, Jaswinder Singh Rajput wrote:
> > > On Thu, 2009-03-05 at 14:54 +0100, Andreas Herrmann wrote:
> > >
> > > > All nice suggestions but why in-kernel?
> > > >
> > >
> > > In Kernel Space:
> > >
> > > We can read/write MSRs and can change the bits and see it effect without
> > > writing any code.
> >
> > Sorry, I can't (or maybe I don't like to) follow.
> >
> > (BTW, you don't even need to write C-code. You can use a one-liner in perl
> > or python to seek and read any MSR using /dev/cpu/*/msr.)
> >
>
> You are running these commands on shell when every thing is working.
>
> What you will do if you are not getting the shell and kernel is dumping
> or rebooting before that.

In this case a deep debugfs tree with all the MSR details is not of
use either.


Andreas

--
Operating | Advanced Micro Devices GmbH
System | Karl-Hammerschmidt-Str. 34, 85609 Dornach b. M?nchen, Germany
Research | Gesch?ftsf?hrer: Jochen Polster, Thomas M. McCoy, Giuliano Meroni
Center | Sitz: Dornach, Gemeinde Aschheim, Landkreis M?nchen
(OSRC) | Registergericht M?nchen, HRB Nr. 43632

2009-03-05 18:40:44

by Jaswinder Singh Rajput

[permalink] [raw]
Subject: Re: [git-pull -tip] x86: msr architecture debug code

On Thu, 2009-03-05 at 19:23 +0100, Andreas Herrmann wrote:
> On Thu, Mar 05, 2009 at 09:17:37PM +0530, Jaswinder Singh Rajput wrote:
> >
> > You are running these commands on shell when every thing is working.
> >
> > What you will do if you are not getting the shell and kernel is dumping
> > or rebooting before that.
>
> In this case a deep debugfs tree with all the MSR details is not of
> use either.
>

Yes, then functions from msr_debug.c will dump the details on screen if
seq is NULL (thats why I am also using printk ;-)

Cheers,
--
JSR

Subject: Re: [git-pull -tip] x86: msr architecture debug code

On Fri, Mar 06, 2009 at 12:10:12AM +0530, Jaswinder Singh Rajput wrote:
> On Thu, 2009-03-05 at 19:23 +0100, Andreas Herrmann wrote:
> > On Thu, Mar 05, 2009 at 09:17:37PM +0530, Jaswinder Singh Rajput wrote:
> > >
> > > You are running these commands on shell when every thing is working.
> > >
> > > What you will do if you are not getting the shell and kernel is dumping
> > > or rebooting before that.
> >
> > In this case a deep debugfs tree with all the MSR details is not of
> > use either.
> >
>
> Yes, then functions from msr_debug.c will dump the details on screen if
> seq is NULL (thats why I am also using printk ;-)

There is no corresponding caller in your patch -- or did I miss it?
Where will you add it?
Maybe you are even suggesting to dump all MSRs on panic?
This wouldn't be helpful at all. Who should sort out the flood of
information when you've dumped more than 100 MSRs per core on a 16
core machine?

In contrary to that it makes sense to evaluate and print certain MSRs, e.g.
- when kernel panics due to uncorrectable MCE or
- when you are debugging specific stuff and know exactly when to check
which MSR

In the latter case you patch the kernel anyway and then it's no burden
to add a printk directly in the debug code.


Andreas

--
Operating | Advanced Micro Devices GmbH
System | Karl-Hammerschmidt-Str. 34, 85609 Dornach b. M?nchen, Germany
Research | Gesch?ftsf?hrer: Jochen Polster, Thomas M. McCoy, Giuliano Meroni
Center | Sitz: Dornach, Gemeinde Aschheim, Landkreis M?nchen
(OSRC) | Registergericht M?nchen, HRB Nr. 43632