linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Borislav Petkov <bp@alien8.de>
To: Ingo Molnar <mingo@kernel.org>
Cc: "Luck, Tony" <tony.luck@intel.com>,
	"H. Peter Anvin" <hpa@zytor.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Andy Lutomirski <luto@amacapital.net>,
	Peter Zijlstra <peterz@infradead.org>,
	Steven Rostedt <rostedt@goodmis.org>,
	Brian Gerst <brgerst@gmail.com>,
	lkml <linux-kernel@vger.kernel.org>
Subject: [PATCH -v2] x86: Add an archinfo dumper module
Date: Thu, 4 Feb 2016 16:22:35 +0100	[thread overview]
Message-ID: <20160204152235.GB5343@pd.tnic> (raw)
In-Reply-To: <20160203110052.GA20682@pd.tnic>

Here's v2 with the stuff we talked about, implemented. I've added
'control_regs' file too so that you can do:

$ cat /sys/kernel/debug/x86/archinfo/control_regs
CR4: [-|-|SMEP|OSXSAVE|-|-|-|-|OSXMMEXCPT|OSFXSR|-|PGE|MCE|PAE|PSE|-|-|-|-]: 0x1406f0

for example. Yeah, only CR4 right now.

Off the top of my head, we would need "msrs" which dumps EFER and a
bunch of other interesting MSRs along with the names of the set bits.

---
From: Borislav Petkov <bp@suse.de>
Date: Mon, 30 Nov 2015 13:53:36 +0100
Subject: [PATCH -v2] x86: Add an archinfo dumper module

Dump interesting/valuable information related to the x86 architecture of
the current CPU and platform.

Signed-off-by: Borislav Petkov <bp@suse.de>
---
 arch/x86/Kconfig.debug     |   5 ++
 arch/x86/kernel/Makefile   |   1 +
 arch/x86/kernel/archinfo.c | 215 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 221 insertions(+)
 create mode 100644 arch/x86/kernel/archinfo.c

diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 9b18ed97a8a2..c757d1ee9a7a 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -383,4 +383,9 @@ config PUNIT_ATOM_DEBUG
 	  The current power state can be read from
 	  /sys/kernel/debug/punit_atom/dev_power_state
 
+config ARCHINFO
+	tristate "x86 archinfo dumper module"
+	---help---
+	  Dump interesting x86 arch stuff.
+
 endmenu
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index b1b78ffe01d0..89972c1b9de6 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -109,6 +109,7 @@ obj-$(CONFIG_EFI)			+= sysfb_efi.o
 
 obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o
 obj-$(CONFIG_TRACING)			+= tracepoint.o
+obj-$(CONFIG_ARCHINFO)			+= archinfo.o
 
 ###
 # 64 bit specific files
diff --git a/arch/x86/kernel/archinfo.c b/arch/x86/kernel/archinfo.c
new file mode 100644
index 000000000000..c04e98625565
--- /dev/null
+++ b/arch/x86/kernel/archinfo.c
@@ -0,0 +1,215 @@
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/cpu.h>
+
+#include <asm/desc.h>
+
+static const char * const system_desc_types[] = {
+	[0] = "Reserved (illegal)",
+	[1] = "Available 16-bit TSS",
+	[2] = "LDT",
+	[3] = "Busy 16-bit TSS",
+	[4] = "16-bit Call Gate",
+	[5] = "Task Gate",
+	[6] = "16-bit Interrupt Gate",
+	[7] = "16-bit Trap Gate",
+	[8] = "Reserved (illegal)",
+	[9] = "Available 32-bit TSS",
+	[10] = "Reserved (illegal)",
+	[11] = "Busy 32-bit TSS",
+	[12] = "32-bit Call Gate",
+	[13] = "Reserved (illegal)",
+	[14] = "32-bit Interrupt Gate",
+	[15] = "32-bit Trap Gate",
+};
+
+static const char * const user_desc_types[] = {
+	[0] = "Read-Only",
+	[1] = "Read-only - Accessed",
+	[2] = "Read/Write",
+	[3] = "Read/Write - Accessed",
+	[4] = "Expand-down, Read-Only",
+	[5] = "Expand-down, Read-Only - Accessed",
+	[6] = "Expand-down, Read-Write",
+	[7] = "Expand-down, Read-Write - Accessed",
+	[8] = "Execute-Only",
+	[9] = "Execute-Only - Accessed",
+	[10] = "Execute/Readable",
+	[11] = "Execute/Readable - Accessed",
+	[12] = "Conforming, Execute-Only",
+	[13] = "Conforming, Execute-Only - Accessed",
+	[14] = "Conforming, Execute/Readable",
+	[15] = "Conforming, Execute/Readable - Accessed",
+};
+
+static void print_seg_desc(struct seq_file *m, struct desc_struct *d, int num)
+{
+	seq_printf(m, "%02d:\n", num);
+	seq_printf(m, "[ base[31:24]:%02x G:%x D:%x L:%x AVL:%x lim[19:16]:%x |",
+		   d->base2, d->g, d->d, d->l, d->avl, d->limit);
+	seq_printf(m, " P:%x DPL:%x S:%x C:%x base[23:16]:%02x ]\n",
+		   d->p, d->dpl, d->s, !!(d->type & BIT(2)), d->base1);
+	seq_printf(m, "[ base[15:00]:%04x | lim[15:00]:%04x ]: ",
+		   d->base0, d->limit0);
+
+	if (d->s)
+		seq_printf(m, "User: (0x%x) %s, %s\n",
+			    d->type,
+			   (d->type > 7 ? "Code" : "Data"),
+			   (user_desc_types[d->type]));
+	else
+		seq_printf(m, "System: (0x%x) %s\n", d->type, system_desc_types[d->type]);
+
+	seq_printf(m, "\n");
+}
+
+static void dump_gdt(void *info)
+{
+	struct gdt_page *g = this_cpu_ptr(&gdt_page);
+	struct seq_file *m = (struct seq_file *)info;
+	int i;
+
+	seq_printf(m, "CPU%d, GDT %p:\n", smp_processor_id(), &g->gdt);
+
+	for (i = 0; i < GDT_ENTRIES; i++)
+		print_seg_desc(m, &g->gdt[i], i);
+
+	seq_printf(m, "----\n");
+
+}
+
+static int gdt_show(struct seq_file *m, void *v)
+{
+	int c;
+
+	/*
+	 * Using on_each_cpu() here fudges the output and we want it nicely
+	 * sorted by CPU.
+	 */
+	get_online_cpus();
+		for_each_online_cpu(c)
+			smp_call_function_single(c, dump_gdt, m, 1);
+	put_online_cpus();
+
+	seq_printf(m,
+		   "\nInfo:\n"
+		   "base,limit,A,G,R: ignored in 64-bit mode.\n"
+		   "G: granularity bit (23):\n"
+			"\t- 0b: segment limit is not scaled.\n"
+			"\t- 1b: segment limit scaled by 4K.\n"
+		   "D/B: CS default operand size bit (22):\n"
+			"\t- 0b: 16-bit.\n"
+			"\t- 1b: 32-bit.\n"
+			"\tD=0b is the only allowed setting in long mode (L=1b).\n"
+			"\tCalled B in stack segments.\n"
+		   "L: long mode bit (21):\n"
+			"\t- 0b: CPU in compat mode. Enables segmentation.\n"
+			"\t- 1b: CPU in long mode.\n"
+		   "AVL: bit available to software (20).\n"
+		   "P: present bit (15):\n"
+			"\t- 0b: seg. not present in mem => #NP.\n"
+			"\t- 1b: seg is present in memory.\n"
+		   "DPL: Descriptor Privilege Level [14:13]:\n"
+			"\t- 0b: highest privilege level.\n"
+			"    ...\n"
+			"\t- 3b: lowest privilege level.\n"
+		   "S+Type: decriptor types [12,11:8]:\n"
+			"\t Specify descriptor type and access characteristics.\n"
+		   " S:\n"
+			"\t- 0b: System descriptor.\n"
+			"\t- 1b: User descriptor.\n"
+		   " R: readable bit (9):\n"
+			"\t- 0b: code seg is executable, reads -> #GP\n"
+			"\t- 1b: code seg is both read/exec\n"
+		   " A: accessed bit (8): set by CPU when desc copied into %%cs; cleared only by sw.\n"
+			);
+
+	return 0;
+}
+
+static int gdt_open(struct inode *inode, struct file *filp)
+{
+	return single_open(filp, gdt_show, NULL);
+}
+
+static int cr_show(struct seq_file *m, void *v)
+{
+	unsigned long cr4 = __read_cr4();
+
+	seq_printf(m, "CR4: [%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s]: 0x%lx\n",
+		      (cr4 & BIT(22) ? "PKE"		: "-"),
+		      (cr4 & BIT(21) ? "SMAP"		: "-"),
+		      (cr4 & BIT(20) ? "SMEP"		: "-"),
+		      (cr4 & BIT(18) ? "OSXSAVE"	: "-"),
+		      (cr4 & BIT(17) ? "PCIDE"		: "-"),
+		      (cr4 & BIT(16) ? "FSGSBASE"	: "-"),
+		      (cr4 & BIT(14) ? "SMXE"		: "-"),
+		      (cr4 & BIT(13) ? "VMXE"		: "-"),
+		      (cr4 & BIT(10) ? "OSXMMEXCPT"	: "-"),
+		      (cr4 & BIT(9)  ? "OSFXSR"		: "-"),
+		      (cr4 & BIT(8)  ? "PCE"		: "-"),
+		      (cr4 & BIT(7)  ? "PGE"		: "-"),
+		      (cr4 & BIT(6)  ? "MCE"		: "-"),
+		      (cr4 & BIT(5)  ? "PAE"		: "-"),
+		      (cr4 & BIT(4)  ? "PSE"		: "-"),
+		      (cr4 & BIT(3)  ? "DE"		: "-"),
+		      (cr4 & BIT(2)  ? "TSD"		: "-"),
+		      (cr4 & BIT(1)  ? "PVI"		: "-"),
+		      (cr4 & BIT(0)  ? "VME"		: "-"),
+		      cr4);
+
+	return 0;
+}
+
+static int cr_open(struct inode *inode, struct file *filp)
+{
+	return single_open(filp, cr_show, NULL);
+}
+
+static const struct file_operations cr_fops = {
+	.owner	 = THIS_MODULE,
+	.open	 = cr_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = single_release,
+};
+
+static const struct file_operations gdt_fops = {
+	.owner	 = THIS_MODULE,
+	.open	 = gdt_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = single_release,
+};
+
+static struct dentry *dfs_entry;
+
+static int __init archinfo_init(void)
+{
+	dfs_entry = debugfs_create_dir("archinfo", arch_debugfs_dir);
+	if (IS_ERR_OR_NULL(dfs_entry))
+		return -EINVAL;
+
+	if (!debugfs_create_file("gdt", S_IRUSR, dfs_entry, NULL, &gdt_fops)) {
+		debugfs_remove_recursive(dfs_entry);
+		return -EINVAL;
+	}
+
+	if (!debugfs_create_file("control_regs", S_IRUSR, dfs_entry, NULL, &cr_fops)) {
+		debugfs_remove_recursive(dfs_entry);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void __exit archinfo_exit(void)
+{
+	debugfs_remove_recursive(dfs_entry);
+}
+
+module_init(archinfo_init);
+module_exit(archinfo_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Borislav Petkov <bp@alien8.de>");
+MODULE_DESCRIPTION("x86 arch info dumper");
-- 
2.3.5


-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

  reply	other threads:[~2016-02-04 15:22 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-01 11:56 [RFC] Dump interesting arch/platform info Borislav Petkov
2016-02-01 23:29 ` Luck, Tony
2016-02-02  9:41   ` Borislav Petkov
2016-02-03 10:48     ` Ingo Molnar
2016-02-03 11:00       ` Borislav Petkov
2016-02-04 15:22         ` Borislav Petkov [this message]
2016-02-04 19:07           ` [PATCH -v2] x86: Add an archinfo dumper module Luck, Tony
2016-02-07 10:51             ` Borislav Petkov
2016-02-09 19:17               ` Luck, Tony
2016-02-09 19:46                 ` Borislav Petkov
2016-02-05 19:51           ` Luck, Tony
2016-02-05 22:24             ` Luck, Tony
2016-02-08  0:01           ` H. Peter Anvin
2016-02-08  7:50             ` Boris Petkov
2016-02-09 12:23             ` Ingo Molnar
2016-02-09 14:01               ` Borislav Petkov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160204152235.GB5343@pd.tnic \
    --to=bp@alien8.de \
    --cc=brgerst@gmail.com \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@amacapital.net \
    --cc=mingo@kernel.org \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=tglx@linutronix.de \
    --cc=tony.luck@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).