lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <1244910436.11733.14.camel@ht.satnam>
Date:	Sat, 13 Jun 2009 21:57:16 +0530
From:	Jaswinder Singh Rajput <jaswinder@...nel.org>
To:	Ingo Molnar <mingo@...e.hu>, "H. Peter Anvin" <hpa@...nel.org>,
	x86 maintainers <x86@...nel.org>,
	Andreas Herrmann <andreas.herrmann3@....com>,
	Andrew Morton <akpm@...ux-foundation.org>,
	Andi Kleen <andi@...stfloor.org>,
	LKML <linux-kernel@...r.kernel.org>,
	Yinghai Lu <yinghai@...nel.org>, Dave Jones <davej@...hat.com>,
	Linus Torvalds <torvalds@...ux-foundation.org>,
	Thomas Gleixner <tglx@...utronix.de>,
	Robert Richter <robert.richter@....com>
Subject: [RFC][GIT PULL][PATCH 0/10 -tip] cpu_debug patches 20090613

By adding these patches, cpu_debug will support :

1. Standard Registers
2. Control Registers
3. Debug Registers
4. Descriptor Tables
5. APIC Registers
6. Model specific Register (MSRs)
7. PCI configuration registers (for AMD)
8. Basic cpuinfo
9. CPUID Functions

Please let me know how we can improve it and add more features so it
becomes more useful.

For example on AMD 64 Laptop :

1. Standard Registers
---------------------

a. access complete state

# cat /sys/kernel/debug/x86/cpu/cpu0/tss/state
 RAX	: ffffffff81789fe8
 RBX	: 000000000007e000
 RCX	: ffffffff8179437f
 RDX	: 0000000000000000
 RSI	: 0000000000000000
 RDI	: 81798e0000104136
 RBP	: 000000000000001f
 ESP	: 0000000000000000
 R08	: 00000000000932d0
 R09	: 0000000000000000
 R10	: ffffffff8179429a
 R11	: ffffffff81789fa8
 R12	: 00000000afc723ac
 R13	: 00000000018e4f80
 R14	: ffffffff817cee80
 R15	: ffffffff81789f88
 CS	:             0010
 DS	:             0018
 SS	:             0000
 ES	:             0018
 FS	:             0000
 GS	:             0000
 EFLAGS	: 0000000000000000
 EIP	: 0000000000000000

2. Control Registers
--------------------

a. access complete state

# cat /sys/kernel/debug/x86/cpu/cpu0/cr/state
 cr0	: 000000008005003b
 cr2	: 0000000000429040
 cr3	: 0000000001001000
 cr4	: 00000000000006b0
 cr8	: 0000000000000000

3. Debug Registers
------------------

a. access complete state

# cat /sys/kernel/debug/x86/cpu/cpu0/debug/state
 dr0	: 0000000000000000
 dr1	: 0000000000000000
 dr2	: 0000000000000000
 dr3	: 0000000000000000
 dr6	: 00000000ffff0ff0
 dr7	: 0000000000000400

 MSR	:
 000001d9: 00000000_00000000

4. Descriptor Tables
--------------------

a. access complete state

# cat /sys/kernel/debug/x86/cpu/cpu0/dt/state
 IDT	: ffffffff81820fff
 GDT	: ffff88002802607f
 LDT	: ffffffff810b0000
 TR	: 0000000000000040

5. APIC Registers
-----------------

a. access complete state

# cat /sys/kernel/debug/x86/cpu/cpu0/apic/state
 LAPIC	:
 ID		: 00000000
 LVR		: 80050010
 TASKPRI	: 00000000
 ARBPRI		: 00000000
 PROCPRI	: 00000000
 LDR		: 01000000
 DFR		: ffffffff
 SPIV		: 000001ff
 ISR		: 00000000
 ESR		: 00000004
 ICR		: 000208fd
 ICR2		: 02000000
 LVTT		: 000300ef
 LVTTHMR	: 00010000
 LVTPC		: 00000400
 LVT0		: 00010700
 LVT1		: 00000400
 LVTERR		: 000000fe
 TMICT		: ffffffff
 TMCCT		: 8d52660d
 TDCR		: 00000003
 EFEAT		: 00040007
 ECTRL		: 00000000
 EILVT0		: 00010000
 EILVT1		: 00010000
 EILVT2		: 00010000
 EILVT3		: 00010000

 MSR	:
 0000001b: 00000000_fee00900

b. access individual APIC register :

# cat /sys/kernel/debug/x86/cpu/cpu0/apic/APIC_EFEAT/value 
0x40007

# cat /sys/kernel/debug/x86/cpu/cpu0/apic/MSR_1b/value
0xfee00900

6. Model specific Register (MSRs)
---------------------------------

a. access complete state, say performance monitor counter (pmc)

# cat /sys/kernel/debug/x86/cpu/cpu0/pmc/state
 MSR	:
 c0010000: 00000000_00430076
 c0010001: 00000000_3d179f6b
 c0010002: 00000000_7993feae
 c0010003: 00000000_f69637fe
 c0010004: 0000000f_4c47618a
 c0010005: 0000f0db_ffc3e9c3
 c0010006: 0000834f_15f5610e
 c0010007: 00006ade_595d2c95

b. access individual MSR :

# cat /sys/kernel/debug/x86/cpu/cpu0/pmc/MSR_c0010006/value 
0x834f15f5610e

c. write individual MSR :
# echo 2 >  /sys/kernel/debug/x86/cpu/cpu0/pmc/MSR_c0010006/value

# cat /sys/kernel/debug/x86/cpu/cpu0/pmc/MSR_c0010006/value 
0x2

7. PCI configuration registers (for AMD)
----------------------------------------

a. access complete state

 PCI configuration regsiters :
 function : 0
 000	: 13001022
 004	: 00100000
 008	: 06000040
 00c	: 00800000
 034	: 00000080
 040	: 00000000
 044	: 00000000
 048	: 00000000
 04c	: 00000000
 050	: 00000000
 054	: 00000000
 058	: 00000000
 05c	: 00000000
 060	: 00000000
 064	: 00000000
 068	: 012e4820
 06c	: 00000030
 080	: 21010008
 084	: 11112020
 088	: 1ff50a60
 08c	: 00000003
 090	: 001005b6
 094	: 00000000
 098	: 00000007
 0a0	: 00000000
 0a4	: 00000000
 0a8	: 00000000
 0ac	: 00000000
 0b0	: 00000000
 0b4	: 00000000
 0b8	: 00000000
 0c0	: 00000000
 0c4	: 00000000
 0c8	: 00000000
 0cc	: 00000000
 0d0	: 00000000
 0d4	: 00000000
 0d8	: 00000000
 0e0	: 00000000
 0e4	: 00000000
 0e8	: 00000000
 0ec	: 00000000
 0f0	: 00000000
 0f4	: 00000000
 0f8	: 00000000
 110	: 00000000
 114	: 00000000
 118	: 00000000
 11c	: 00000000
 120	: 00000000
 124	: 00000000
 128	: 00000000
 12c	: 00000000
 130	: 000000c1
 134	: 00000000
 138	: 00000000
 13c	: 00000000
 140	: 00000000
 144	: 00000000
 148	: 00000000
 14c	: 00000000
 150	: 00070000
 164	: 00000000
 168	: 00000000
 16c	: 0074e026
 170	: 07c00109
 174	: 00000000
 178	: 00000000
 17c	: 00000000
 180	: 00000000
 184	: 00000000
 188	: 00000000
 18c	: 00000000
 1a0	: 00000000
 1a4	: 00002824
 1d0	: 00000400
 1d4	: 00000051

 function : 1
 000	: 13011022
 004	: 00000000
 008	: 06000000
 00c	: 00800000
 034	: 00000000
 040	: 00000003
 044	: 013f0000
 048	: 00000000
 04c	: 00000000
 050	: 00000000
 054	: 00000000
 058	: 00000000
 05c	: 00000000
 060	: 00000000
 064	: 00000000
 068	: 00000000
 06c	: 00000000
 070	: 00000000
 074	: 00000000
 078	: 00000000
 07c	: 00000000
 080	: 00000000
 084	: 00000000
 088	: 00000a03
 08c	: 00000b00
 090	: 00c00003
 094	: 00cfff80
 098	: 00d00003
 09c	: 00d21f00
 0a0	: 00d22003
 0a4	: 00d22f80
 0a8	: 00d23003
 0ac	: 00dfff00
 0b0	: 00e00003
 0b4	: 00e3ff80
 0b8	: 00e40003
 0bc	: 00ffff00
 0c0	: 00000013
 0c4	: 00fff000
 0c8	: 00000000
 0cc	: 00000000
 0d0	: 00000000
 0d4	: 00000000
 0d8	: 00000000
 0dc	: 00000000
 0e0	: 00000000
 0e4	: 00000000
 0e8	: 00000000
 0ec	: 00000000
 0f0	: c0004001
 0f4	: 00000000
 110	: 00000000
 114	: 00000000
 120	: 00000000
 124	: 00000000
 140	: 00000000
 144	: 00000000
 148	: 00000000
 14c	: 00000000
 150	: 00000000
 154	: 00000000
 158	: 00000000
 15c	: 00000000
 160	: 00000000
 164	: 00000000
 168	: 00000000
 16c	: 00000000
 170	: 00000000
 174	: 00000000
 178	: 00000000
 17c	: 00000000
 180	: e0000011
 184	: 00000000

 function : 2
 000	: 13021022
 004	: 00000000
 008	: 06000000
 00c	: 00800000
 034	: 00000000
 040	: 00000001
 044	: 00000101
 048	: 00000000
 04c	: 00000000
 050	: 00000000
 054	: 00000000
 058	: 00000000
 05c	: 00000000
 060	: 00783ee0
 064	: 00000000
 068	: 00000000
 06c	: 00000000
 070	: 00000000
 074	: 00000000
 078	: 00000036
 07c	: 00000000
 080	: 00000005
 084	: 00000000
 088	: 7d7dfb35
 08c	: 0022173f
 090	: 00600020
 094	: 7e51806b
 098	: 80000013
 09c	: 0000003a
 0a0	: 000000a8
 0a4	: 00000000
 10c	: 00000000
 110	: 00000584
 114	: 00000000
 118	: 1441b4a4
 11c	: 00402064
 140	: 00000001
 144	: 00000101
 148	: 00000000
 14c	: 00000000
 150	: 00000000
 154	: 00000000
 158	: 00000000
 15c	: 00000000
 160	: 00783ee0
 164	: 00000000
 168	: 00000000
 16c	: 00000000
 178	: 00000036
 17c	: 00000000
 180	: 00000005
 184	: 00000000
 188	: 4d7dfb35
 18c	: 0022173f
 190	: 00600020
 194	: 7e51806b
 198	: 80000013
 19c	: 0000003c
 1a0	: 00000008
 1b0	: 00000000

 function : 3
 000	: 13031022
 004	: 00100000
 008	: 06000000
 00c	: 00800000
 034	: 000000f0
 040	: 00000100
 044	: 0a100040
 048	: 00000000
 04c	: 00000000
 050	: 00000000
 054	: 00000000
 058	: 00000000
 05c	: 00000000
 060	: 00000000
 064	: 1a600000
 068	: 100000c0
 06c	: 08000808
 070	: 00000000
 074	: 30000876
 078	: 00000000
 07c	: 85001101
 080	: ff00f300
 084	: 80e600ee
 088	: 00000000
 08c	: 00000000
 090	: 00000000
 094	: 00000000
 098	: 00000000
 09c	: 00000000
 0a0	: 800402bc
 0a4	: 3b201800
 0b0	: 00000000
 0d4	: 0005024d
 0d8	: 03000025
 0dc	: 00034240
 0e4	: 00000520
 0e8	: 00001f81
 0f0	: 0010000f
 0f4	: 00000000
 0f8	: 00000000
 0fc	: 00200f31
 140	: 00000000
 144	: 00000000
 148	: 00000000
 14c	: 00000000
 150	: 00000000
 154	: 00000000
 158	: 00000000
 15c	: 00000000
 160	: 00000000
 164	: 00000000
 168	: 00000000
 16c	: 00000000
 170	: 00000000
 174	: 00000000
 178	: 00000000
 17c	: 00000000
 180	: 00400002
 188	: 1b000438
 190	: 00000000
 1a0	: 00000000
 1cc	: 00000000
 1e4	: 80000000
 1e8	: 00000000
 1ec	: 00000000
 1f0	: 000f0500
 1fc	: 00000000

 function : 4
 000	: 13041022
 004	: 00000000
 008	: 06000000
 00c	: 00800000
 034	: 00000000
 080	: 00000000
 084	: 00000000
 088	: 00000000
 08c	: 00000000
 090	: 00000000
 094	: 00000000
 098	: 00000000
 09c	: 00000000
 0a0	: 00000000
 0a4	: 00000000
 0a8	: 00000000
 0ac	: 00000000
 0b0	: 00000000
 0b4	: 00000000
 0b8	: 00000000
 0bc	: 00000000
 0c0	: 00000000
 0c4	: 00000000
 0c8	: 00000000
 0cc	: 00000000
 0d0	: 00000000
 0d4	: 00000000
 0d8	: 00000000
 0dc	: 00000000
 0e0	: 00000000
 0e4	: 00000000
 0e8	: 00000000
 0ec	: 00000000
 0f0	: 00000000
 0f4	: 00000000
 0f8	: 00000000
 170	: 00000006
 174	: 0a3cdfe6
 180	: 800000c4
 184	: 00006400
 188	: 00000000
 18c	: 00000000
 190	: 00000000
 194	: 00000000
 198	: 00000000
 19c	: 00000000
 1c4	: 00000000
 1e0	: 00000000
 1e4	: 00000000
 1e8	: 00000000
 1ec	: 00000000
 1f0	: 00000000

b. access individual PCI configuration :

# cat /sys/kernel/debug/x86/cpu/cpu0/pci/PCI0_000/value 
0x13001022

# cat /sys/kernel/debug/x86/cpu/cpu0/therm/PCI3_0a4/value 
0x3c001800

8. Basic cpuinfo
----------------

a. access complete state

# cat /sys/kernel/debug/x86/cpu/cpu0/cpuinfo/state 
 CPUINFO	:
 processor		: 0
 family			: 17
 vendor			: 2
 model			: 3
 mask			: 1
 TLB size		: 1024 4K pages
 virtual bits		: 48
 physical bits		: 40
 extended cpuid level	: 8000001a (8000001a)
 cpuid level		: 1
 flags			: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt rdtscp lm 3dnowext 3dnow constant_tsc rep_good nonstop_tsc pni cx16 lahf_lm cmp_legacy svm extapic cr8_legacy 3dnowprefetch osvw skinit
 vendor id		: AuthenticAMD
 model id		: AMD Turion(tm) X2 Ultra Dual-Core Mobile ZM-80
 cache size		: 1024 KB
 cache alignment	: 64
 power management	: ts ttp tm stc 100mhzsteps hwpstate
 loops per jiffy	: 2098811
 bogomips		: 4197.62
 max cores		: 2
 apic id		: 0
 intial apic id		: 0
 clflush size		: 64
 cpu cores		: 2
 physical id		: 0
 core id		: 0
 cpu index		: 0
 hyper vendor		: 0

9. CPUID Functions
------------------

a. access complete state

# cat /sys/kernel/debug/x86/cpu/cpu0/cpuid/state
 CPUID	:
              eax       ebx       ecx       edx
 00000000  00000001  68747541  444d4163  69746e65
 00000001  00200f31  00020800  00002001  178bfbff
 80000000  8000001a  68747541  444d4163  69746e65
 80000001  00200f31  20000500  0000131f  ebd3fbff
 80000002  20444d41  69727554  74286e6f  5820296d
 80000003  6c552032  20617274  6c617544  726f432d
 80000004  6f4d2065  656c6962  2d4d5a20  00003038
 80000005  ff08ff08  ff20ff20  40020140  40020140
 80000006  00000000  42004200  04008140  00000000
 80000007  00000000  00000000  00000000  000001f9
 80000008  00003028  00000000  00001001  00000000
 80000009  00000000  00000000  00000000  00000000
 8000000a  00000001  00000040  00000000  0000000e
 8000000b  00000000  00000000  00000000  00000000
 8000000c  00000000  00000000  00000000  00000000
 8000000d  00000000  00000000  00000000  00000000
 8000000e  00000000  00000000  00000000  00000000
 8000000f  00000000  00000000  00000000  00000000
 80000010  00000000  00000000  00000000  00000000
 80000011  00000000  00000000  00000000  00000000
 80000012  00000000  00000000  00000000  00000000
 80000013  00000000  00000000  00000000  00000000
 80000014  00000000  00000000  00000000  00000000
 80000015  00000000  00000000  00000000  00000000
 80000016  00000000  00000000  00000000  00000000
 80000017  00000000  00000000  00000000  00000000
 80000018  00000000  00000000  00000000  00000000
 80000019  00000000  00000000  00000000  00000000
 8000001a  00000000  00000000  00000000  00000000

The following changes since commit 50149b2db7be15514079089d0c4efa4c7a2676bb:
  Ingo Molnar (1):
        Merge branch 'linus'

are available in the git repository at:

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

Jaswinder Singh Rajput (10):
      x86: cpu_debug update Kconfig entry
      x86: cpu_debug.c remove some not required header files
      x86: cpu_debug.c use a WARN_ONCE() instead of a pr_err()
      x86: cpu_debug make room to support more categories
      x86: cpu_debug update MSR list to support new architectures
      x86: cpu_debug make room for more cpu registers
      x86: cpu_debug support APIC_register_name with directory structure
      x86: cpu_debug display PCI configuration registers for AMD
      x86: cpu_debug display cpuid functions
      x86: cpu_debug display basic cpuinfo

 arch/x86/Kconfig                 |   12 +-
 arch/x86/include/asm/cpu_debug.h |  125 ++++----
 arch/x86/kernel/cpu/cpu_debug.c  |  681 +++++++++++++++++++++++++++++++++-----
 3 files changed, 666 insertions(+), 152 deletions(-)

Complete diff :

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 0c2321d..e5e26b3 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -994,9 +994,19 @@ config X86_CPUID
 
 config X86_CPU_DEBUG
 	tristate "/sys/kernel/debug/x86/cpu/* - CPU Debug support"
+	select DEBUG_FS
 	---help---
 	  If you select this option, this will provide various x86 CPUs
-	  information through debugfs.
+	  information through debugfs. Any user can read these file but writing
+	  needs root privilege.
+
+	  Note: 1. If you compile cpu_debug as a module, it will _not_ be loaded
+	  automatically (like usual drivers). You will need to load it manually
+	  (or add it to list of modules loaded during boot).
+
+	  2. You need debugfs, if you want to mount debugfs automatically
+	  append this line in /etc/fstab:
+	  debugfs	/sys/kernel/debug	debugfs	defaults	0 0
 
 choice
 	prompt "High Memory Support"
diff --git a/arch/x86/include/asm/cpu_debug.h b/arch/x86/include/asm/cpu_debug.h
index d96c1ee..b75758e 100644
--- a/arch/x86/include/asm/cpu_debug.h
+++ b/arch/x86/include/asm/cpu_debug.h
@@ -10,91 +10,80 @@
 /* Register flags */
 enum cpu_debug_bit {
 /* Model Specific Registers (MSRs)					*/
-	CPU_MC_BIT,				/* Machine Check	*/
-	CPU_MONITOR_BIT,			/* Monitor		*/
-	CPU_TIME_BIT,				/* Time			*/
-	CPU_PMC_BIT,				/* Performance Monitor	*/
-	CPU_PLATFORM_BIT,			/* Platform		*/
-	CPU_APIC_BIT,				/* APIC			*/
-	CPU_POWERON_BIT,			/* Power-on		*/
-	CPU_CONTROL_BIT,			/* Control		*/
-	CPU_FEATURES_BIT,			/* Features control	*/
-	CPU_LBRANCH_BIT,			/* Last Branch		*/
-	CPU_BIOS_BIT,				/* BIOS			*/
-	CPU_FREQ_BIT,				/* Frequency		*/
-	CPU_MTTR_BIT,				/* MTRR			*/
-	CPU_PERF_BIT,				/* Performance		*/
-	CPU_CACHE_BIT,				/* Cache		*/
-	CPU_SYSENTER_BIT,			/* Sysenter		*/
-	CPU_THERM_BIT,				/* Thermal		*/
-	CPU_MISC_BIT,				/* Miscellaneous	*/
-	CPU_DEBUG_BIT,				/* Debug		*/
-	CPU_PAT_BIT,				/* PAT			*/
-	CPU_VMX_BIT,				/* VMX			*/
-	CPU_CALL_BIT,				/* System Call		*/
-	CPU_BASE_BIT,				/* BASE Address		*/
-	CPU_VER_BIT,				/* Version ID		*/
-	CPU_CONF_BIT,				/* Configuration	*/
-	CPU_SMM_BIT,				/* System mgmt mode	*/
-	CPU_SVM_BIT,				/*Secure Virtual Machine*/
-	CPU_OSVM_BIT,				/* OS-Visible Workaround*/
+	CPU_MC,					/* Machine Check	*/
+	CPU_MONITOR,				/* Monitor		*/
+	CPU_TIME,				/* Time			*/
+	CPU_PMC,				/* Performance Monitor	*/
+	CPU_PLATFORM,				/* Platform		*/
+	CPU_APIC,				/* APIC			*/
+	CPU_POWERON,				/* Power-on		*/
+	CPU_CONTROL,				/* Control		*/
+	CPU_FEATURES,				/* Features control	*/
+	CPU_LBRANCH,				/* Last Branch		*/
+	CPU_BIOS,				/* BIOS			*/
+	CPU_FREQ,				/* Frequency		*/
+	CPU_MTRR,				/* MTRR			*/
+	CPU_PERF,				/* Performance		*/
+	CPU_CACHE,				/* Cache		*/
+	CPU_SYSENTER,				/* Sysenter		*/
+	CPU_THERM,				/* Thermal		*/
+	CPU_MISC,				/* Miscellaneous	*/
+	CPU_DEBUG,				/* Debug		*/
+	CPU_PAT,				/* PAT			*/
+	CPU_VMX,				/* VMX			*/
+	CPU_CALL,				/* System Call		*/
+	CPU_BASE,				/* BASE Address		*/
+	CPU_VER,				/* Version ID		*/
+	CPU_CONF,				/* Configuration	*/
+	CPU_SMM,				/* System mgmt mode	*/
+	CPU_POWER,				/* Power mgmt		*/
+	CPU_PNAME,				/* Processor name	*/
+	CPU_IBS,				/* IBS			*/
+	CPU_SVM,				/*Secure Virtual Machine*/
+	CPU_OSVM,				/* OS-Visible Workaround*/
+	CPU_NB,					/* North Bridge		*/
+	CPU_DRAM,				/* DRAM			*/
+	CPU_MMIO,				/* Memory based IO	*/
+	CPU_DISPLAY,				/* Display/VGA		*/
+	CPU_LINK,				/* HyperTransport	*/
 /* Standard Registers							*/
-	CPU_TSS_BIT,				/* Task Stack Segment	*/
-	CPU_CR_BIT,				/* Control Registers	*/
-	CPU_DT_BIT,				/* Descriptor Table	*/
+	CPU_TSS,				/* Task Stack Segment	*/
+	CPU_CR,					/* Control Registers	*/
+	CPU_DT,					/* Descriptor Table	*/
+	CPU_CPUID,				/* CPUID		*/
+	CPU_CPUINFO,				/* struct cpuinfo_x86	*/
+	CPU_PCI,				/* PCI configuration	*/
 /* End of Registers flags						*/
-	CPU_REG_ALL_BIT,			/* Select all Registers	*/
+	CPU_REG_MAX,				/* Max Registers flags	*/
 };
 
 #define	CPU_REG_ALL		(~0)		/* Select all Registers	*/
 
-#define	CPU_MC			(1 << CPU_MC_BIT)
-#define	CPU_MONITOR		(1 << CPU_MONITOR_BIT)
-#define	CPU_TIME		(1 << CPU_TIME_BIT)
-#define	CPU_PMC			(1 << CPU_PMC_BIT)
-#define	CPU_PLATFORM		(1 << CPU_PLATFORM_BIT)
-#define	CPU_APIC		(1 << CPU_APIC_BIT)
-#define	CPU_POWERON		(1 << CPU_POWERON_BIT)
-#define	CPU_CONTROL		(1 << CPU_CONTROL_BIT)
-#define	CPU_FEATURES		(1 << CPU_FEATURES_BIT)
-#define	CPU_LBRANCH		(1 << CPU_LBRANCH_BIT)
-#define	CPU_BIOS		(1 << CPU_BIOS_BIT)
-#define	CPU_FREQ		(1 << CPU_FREQ_BIT)
-#define	CPU_MTRR		(1 << CPU_MTTR_BIT)
-#define	CPU_PERF		(1 << CPU_PERF_BIT)
-#define	CPU_CACHE		(1 << CPU_CACHE_BIT)
-#define	CPU_SYSENTER		(1 << CPU_SYSENTER_BIT)
-#define	CPU_THERM		(1 << CPU_THERM_BIT)
-#define	CPU_MISC		(1 << CPU_MISC_BIT)
-#define	CPU_DEBUG		(1 << CPU_DEBUG_BIT)
-#define	CPU_PAT			(1 << CPU_PAT_BIT)
-#define	CPU_VMX			(1 << CPU_VMX_BIT)
-#define	CPU_CALL		(1 << CPU_CALL_BIT)
-#define	CPU_BASE		(1 << CPU_BASE_BIT)
-#define	CPU_VER			(1 << CPU_VER_BIT)
-#define	CPU_CONF		(1 << CPU_CONF_BIT)
-#define	CPU_SMM			(1 << CPU_SMM_BIT)
-#define	CPU_SVM			(1 << CPU_SVM_BIT)
-#define	CPU_OSVM		(1 << CPU_OSVM_BIT)
-#define	CPU_TSS			(1 << CPU_TSS_BIT)
-#define	CPU_CR			(1 << CPU_CR_BIT)
-#define	CPU_DT			(1 << CPU_DT_BIT)
-
 /* Register file flags */
 enum cpu_file_bit {
-	CPU_INDEX_BIT,				/* index		*/
-	CPU_VALUE_BIT,				/* value		*/
+	CPU_INDEX,				/* index		*/
+	CPU_VALUE,				/* value		*/
+};
+
+/* Register category flags */
+enum cpu_cat_bit {
+	CPU_REG_STD,				/* Standard registers	*/
+	CPU_REG_MSR,				/* MSRs			*/
+	CPU_REG_APIC,				/* APIC registers	*/
+	CPU_REG_PCI,				/* PCI conf registers	*/
 };
 
-#define	CPU_FILE_VALUE		(1 << CPU_VALUE_BIT)
+#define MAX_CPU_FILES		768		/* Max CPU debug files	*/
+#define MAX_CPU_PCI		5		/* AMD supports func 0-4*/
 
-#define MAX_CPU_FILES		512
+#define CPUID_MASK		0xffff0000
 
 struct cpu_private {
 	unsigned		cpu;
 	unsigned		type;
 	unsigned		reg;
 	unsigned		file;
+	unsigned		cat;
 };
 
 struct cpu_debug_base {
diff --git a/arch/x86/kernel/cpu/cpu_debug.c b/arch/x86/kernel/cpu/cpu_debug.c
index 6b2a52d..993a5bc 100644
--- a/arch/x86/kernel/cpu/cpu_debug.c
+++ b/arch/x86/kernel/cpu/cpu_debug.c
@@ -6,32 +6,34 @@
  * For licencing details see kernel-base/COPYING
  */
 
-#include <linux/interrupt.h>
-#include <linux/compiler.h>
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
-#include <linux/kprobes.h>
 #include <linux/uaccess.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/percpu.h>
-#include <linux/signal.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/pci.h>
 #include <linux/smp.h>
 
 #include <asm/cpu_debug.h>
 #include <asm/paravirt.h>
 #include <asm/system.h>
-#include <asm/traps.h>
 #include <asm/apic.h>
 #include <asm/desc.h>
 
-static DEFINE_PER_CPU(struct cpu_cpuX_base, cpu_arr[CPU_REG_ALL_BIT]);
+#ifdef MODULE
+#include "capflags.c"
+#include "powerflags.c"
+#endif
+
+static DEFINE_PER_CPU(struct cpu_cpuX_base, cpu_arr[CPU_REG_MAX]);
 static DEFINE_PER_CPU(struct cpu_private *, priv_arr[MAX_CPU_FILES]);
+static DEFINE_PER_CPU(struct pci_dev *, pci_arr[MAX_CPU_PCI]);
 static DEFINE_PER_CPU(int, cpu_priv_count);
 
 static DEFINE_MUTEX(cpu_debug_lock);
@@ -65,21 +67,63 @@ static struct cpu_debug_base cpu_base[] = {
 	{ "ver",	CPU_VER,	0	},
 	{ "conf",	CPU_CONF,	0	},
 	{ "smm",	CPU_SMM,	0	},
+	{ "power",	CPU_POWER,	0	},
+	{ "pname",	CPU_PNAME,	0	},
+	{ "ibs",	CPU_IBS,	0	},
 	{ "svm",	CPU_SVM,	0	},
 	{ "osvm",	CPU_OSVM,	0	},
+	{ "nbridge",	CPU_NB,		0	},
+	{ "dram",	CPU_DRAM,	0	},
+	{ "mmio",	CPU_MMIO,	0	},
+	{ "display",	CPU_DISPLAY,	0	},
+	{ "link",	CPU_LINK,	0	},
 	{ "tss",	CPU_TSS,	0	},
 	{ "cr",		CPU_CR,		0	},
 	{ "dt",		CPU_DT,		0	},
+	{ "cpuid",	CPU_CPUID,	0	},
+	{ "cpuinfo",	CPU_CPUINFO,	0	},
+	{ "pci",	CPU_PCI,	0	},
 	{ "registers",	CPU_REG_ALL,	0	},
 };
 
+#ifdef CONFIG_X86_LOCAL_APIC
+static struct cpu_debug_base cpu_apic[] = {
+	{ "ID",		APIC_ID,	0	},
+	{ "LVR",	APIC_LVR,	0	},
+	{ "TASKPRI",	APIC_TASKPRI,	0	},
+	{ "ARBPRI",	APIC_ARBPRI,	0	},
+	{ "PROCPRI",	APIC_PROCPRI,	0	},
+	{ "LDR",	APIC_LDR,	0	},
+	{ "DFR",	APIC_DFR,	0	},
+	{ "SPIV",	APIC_SPIV,	0	},
+	{ "ISR",	APIC_ISR,	0	},
+	{ "ESR",	APIC_ESR,	0	},
+	{ "ICR",	APIC_ICR,	0	},
+	{ "ICR2",	APIC_ICR2,	0	},
+	{ "LVTT",	APIC_LVTT,	0	},
+	{ "LVTTHMR",	APIC_LVTTHMR,	0	},
+	{ "LVTPC",	APIC_LVTPC,	0	},
+	{ "LVT0",	APIC_LVT0,	0	},
+	{ "LVT1",	APIC_LVT1,	0	},
+	{ "LVTERR",	APIC_LVTERR,	0	},
+	{ "TMICT",	APIC_TMICT,	0	},
+	{ "TMCCT",	APIC_TMCCT,	0	},
+	{ "TDCR",	APIC_TDCR,	0	},
+};
+
+static struct cpu_debug_base cpu_xapic[] = {
+	{ "EFEAT",	APIC_EFEAT,	0	},
+	{ "ECTRL",	APIC_ECTRL,	0	},
+};
+#endif
+
 static struct cpu_file_base cpu_file[] = {
-	{ "index",	CPU_REG_ALL,	0	},
+	{ "state",	CPU_REG_ALL,	0	},
 	{ "value",	CPU_REG_ALL,	1	},
 };
 
 /* CPU Registers Range */
-static struct cpu_debug_range cpu_reg_range[] = {
+static struct cpu_debug_range cpu_msr_range[] = {
 	{ 0x00000000, 0x00000001, CPU_MC,	},
 	{ 0x00000006, 0x00000007, CPU_MONITOR,	},
 	{ 0x00000010, 0x00000010, CPU_TIME,	},
@@ -95,6 +139,7 @@ static struct cpu_debug_range cpu_reg_range[] = {
 	{ 0x00000088, 0x0000008A, CPU_CACHE,	},
 	{ 0x0000008B, 0x0000008B, CPU_BIOS,	},
 	{ 0x0000009B, 0x0000009B, CPU_MONITOR,	},
+	{ 0x000000A0, 0x000000A1, CPU_SMM,	},
 	{ 0x000000C1, 0x000000C4, CPU_PMC,	},
 	{ 0x000000CD, 0x000000CD, CPU_FREQ,	},
 	{ 0x000000E7, 0x000000E8, CPU_PERF,	},
@@ -103,40 +148,49 @@ static struct cpu_debug_range cpu_reg_range[] = {
 	{ 0x00000116, 0x0000011E, CPU_CACHE,	},
 	{ 0x00000174, 0x00000176, CPU_SYSENTER,	},
 	{ 0x00000179, 0x0000017B, CPU_MC,	},
+	{ 0x00000180, 0x00000185, CPU_MC,	},
 	{ 0x00000186, 0x00000189, CPU_PMC,	},
 	{ 0x00000198, 0x00000199, CPU_PERF,	},
 	{ 0x0000019A, 0x0000019A, CPU_TIME,	},
 	{ 0x0000019B, 0x0000019D, CPU_THERM,	},
 	{ 0x000001A0, 0x000001A0, CPU_MISC,	},
-	{ 0x000001C9, 0x000001C9, CPU_LBRANCH,	},
+	{ 0x000001A1, 0x000001A1, CPU_PLATFORM,	},
+	{ 0x000001A2, 0x000001A2, CPU_THERM,	},
+	{ 0x000001A6, 0x000001A6, CPU_PMC,	},
+	{ 0x000001AD, 0x000001AD, CPU_FREQ,	},
+	{ 0x000001C8, 0x000001C9, CPU_LBRANCH,	},
 	{ 0x000001D7, 0x000001D8, CPU_LBRANCH,	},
 	{ 0x000001D9, 0x000001D9, CPU_DEBUG,	},
 	{ 0x000001DA, 0x000001E0, CPU_LBRANCH,	},
+	{ 0x000001F2, 0x000001F3, CPU_SMM,	},
 
 	{ 0x00000200, 0x0000020F, CPU_MTRR,	},
 	{ 0x00000250, 0x00000250, CPU_MTRR,	},
 	{ 0x00000258, 0x00000259, CPU_MTRR,	},
 	{ 0x00000268, 0x0000026F, CPU_MTRR,	},
 	{ 0x00000277, 0x00000277, CPU_PAT,	},
+	{ 0x00000280, 0x00000288, CPU_MC,	},
 	{ 0x000002FF, 0x000002FF, CPU_MTRR,	},
 
 	{ 0x00000300, 0x00000311, CPU_PMC,	},
 	{ 0x00000345, 0x00000345, CPU_PMC,	},
 	{ 0x00000360, 0x00000371, CPU_PMC,	},
-	{ 0x0000038D, 0x00000390, CPU_PMC,	},
+	{ 0x0000038D, 0x00000396, CPU_PMC,	},
 	{ 0x000003A0, 0x000003BE, CPU_PMC,	},
 	{ 0x000003C0, 0x000003CD, CPU_PMC,	},
 	{ 0x000003E0, 0x000003E1, CPU_PMC,	},
-	{ 0x000003F0, 0x000003F2, CPU_PMC,	},
+	{ 0x000003F0, 0x000003FD, CPU_PMC,	},
 
-	{ 0x00000400, 0x00000417, CPU_MC,	},
+	{ 0x00000400, 0x00000421, CPU_MC,	},
 	{ 0x00000480, 0x0000048B, CPU_VMX,	},
 
 	{ 0x00000600, 0x00000600, CPU_DEBUG,	},
 	{ 0x00000680, 0x0000068F, CPU_LBRANCH,	},
 	{ 0x000006C0, 0x000006CF, CPU_LBRANCH,	},
 
-	{ 0x000107CC, 0x000107D3, CPU_PMC,	},
+	{ 0x00000800, 0x0000083F, CPU_APIC,	},
+
+	{ 0x000107CC, 0x000107D8, CPU_PMC,	},
 
 	{ 0xC0000080, 0xC0000080, CPU_FEATURES,	},
 	{ 0xC0000081, 0xC0000084, CPU_CALL,	},
@@ -149,20 +203,120 @@ static struct cpu_debug_range cpu_reg_range[] = {
 	{ 0xC0010016, 0xC001001A, CPU_MTRR,	},
 	{ 0xC001001D, 0xC001001D, CPU_MTRR,	},
 	{ 0xC001001F, 0xC001001F, CPU_CONF,	},
-	{ 0xC0010030, 0xC0010035, CPU_BIOS,	},
-	{ 0xC0010044, 0xC0010048, CPU_MC,	},
+	{ 0xC0010022, 0xC0010022, CPU_MC,	},
+	{ 0xC0010030, 0xC0010035, CPU_PNAME,	},
+	{ 0xC0010044, 0xC0010049, CPU_MC,	},
 	{ 0xC0010050, 0xC0010056, CPU_SMM,	},
 	{ 0xC0010058, 0xC0010058, CPU_CONF,	},
 	{ 0xC0010060, 0xC0010060, CPU_CACHE,	},
-	{ 0xC0010061, 0xC0010068, CPU_SMM,	},
-	{ 0xC0010069, 0xC001006B, CPU_SMM,	},
+	{ 0xC0010061, 0xC001006B, CPU_POWER,	},
 	{ 0xC0010070, 0xC0010071, CPU_SMM,	},
+	{ 0xC0010074, 0xC0010074, CPU_TIME,	},
 	{ 0xC0010111, 0xC0010113, CPU_SMM,	},
 	{ 0xC0010114, 0xC0010118, CPU_SVM,	},
 	{ 0xC0010140, 0xC0010141, CPU_OSVM,	},
+
+	{ 0xC0011004, 0xC0011005, CPU_FEATURES,	},
 	{ 0xC0011022, 0xC0011023, CPU_CONF,	},
+	{ 0xC001102A, 0xC001102A, CPU_CONF,	},
+	{ 0xC0011030, 0xC001103A, CPU_IBS,	},
+};
+
+/* PCI-defined configurations registers		*/
+
+/* Function 0 Link Configuration Registers	*/
+static struct cpu_debug_range cpu_amd_pci0[] = {
+	{ 0x000,	0x00C,	CPU_PCI		},
+	{ 0x034,	0x034,	CPU_PCI		},
+	{ 0x040,	0x06C,	CPU_LINK	},
+	{ 0x080,	0x098,	CPU_LINK	},
+	{ 0x0A0,	0x0B8,	CPU_LINK	},
+	{ 0x0C0,	0x0D8,	CPU_LINK	},
+	{ 0x0E0,	0x0F8,	CPU_LINK	},
+	{ 0x110,	0x150,	CPU_LINK	},
+	{ 0x164,	0x18C,	CPU_LINK	},
+	{ 0x1A0,	0x1A0,	CPU_LINK	},
+	{ 0x1A4,	0x1A4,	CPU_DISPLAY	},
+	{ 0x1D0,	0x1D4,	CPU_DISPLAY	},
+};
+
+/* Function 1 Address Map Registers		*/
+static struct cpu_debug_range cpu_amd_pci1[] = {
+	{ 0x000,	0x00C,	CPU_PCI		},
+	{ 0x034,	0x034,	CPU_PCI		},
+	{ 0x040,	0x07C,	CPU_DRAM	},
+	{ 0x080,	0x0BC,	CPU_MMIO	},
+	{ 0x0C0,	0x0DC,	CPU_PCI		},
+	{ 0x0E0,	0x0EC,	CPU_CONF	},
+	{ 0x0F0,	0x0F0,	CPU_DRAM	},
+	{ 0x0F4,	0x0F4,	CPU_DISPLAY	},
+	{ 0x110,	0x114,	CPU_MMIO	},
+	{ 0x120,	0x124,	CPU_DRAM	},
+	{ 0x140,	0x17C,	CPU_DRAM	},
+	{ 0x180,	0x184,	CPU_NB		},
+};
+
+/* Function 2 DRAM Controller Registers		*/
+static struct cpu_debug_range cpu_amd_pci2[] = {
+	{ 0x000,	0x00C,	CPU_PCI		},
+	{ 0x034,	0x034,	CPU_PCI		},
+	{ 0x040,	0x0A4,	CPU_DRAM	},
+	{ 0x10C,	0x11C,	CPU_DRAM	},
+	{ 0x140,	0x16C,	CPU_DRAM	},
+	{ 0x178,	0x1A0,	CPU_DRAM	},
+	{ 0x1B0,	0x1B0,	CPU_DRAM	},
+};
+
+/* Function 3 Misc. Configuration Registers	*/
+static struct cpu_debug_range cpu_amd_pci3[] = {
+	{ 0x000,	0x00C,	CPU_PCI		},
+	{ 0x034,	0x034,	CPU_PCI		},
+	{ 0x040,	0x054,	CPU_NB		},
+	{ 0x058,	0x060,	CPU_DRAM	},
+	{ 0x064,	0x068,	CPU_THERM	},
+	{ 0x06C,	0x06C,	CPU_POWER	},
+	{ 0x070,	0x07C,	CPU_DISPLAY	},
+	{ 0x080,	0x084,	CPU_POWER	},
+	{ 0x088,	0x08C,	CPU_NB		},
+	{ 0x090,	0x09C,	CPU_DISPLAY	},
+	{ 0x0A0,	0x0A0,	CPU_POWER	},
+	{ 0x0A4,	0x0A4,	CPU_THERM	},
+	{ 0x0B0,	0x0B0,	CPU_DISPLAY	},
+	{ 0x0D4,	0x0DC,	CPU_POWER	},
+	{ 0x0E4,	0x0E4,	CPU_THERM	},
+	{ 0x0E8,	0x0E8,	CPU_NB		},
+	{ 0x0F0,	0x0F0,	CPU_PCI		},
+	{ 0x0F4,	0x0F8,	CPU_PCI		},
+	{ 0x0FC,	0x0FC,	CPU_CPUID	},
+	{ 0x140,	0x180,	CPU_NB		},
+	{ 0x188,	0x188,	CPU_NB		},
+	{ 0x190,	0x190,	CPU_CONTROL	},
+	{ 0x1A0,	0x1A0,	CPU_CACHE	},
+	{ 0x1CC,	0x1CC,	CPU_IBS		},
+	{ 0x1E4,	0x1EC,	CPU_THERM	},
+	{ 0x1F0,	0x1F0,	CPU_CPUID	},
+	{ 0x1FC,	0x1FC,	CPU_NB		},
 };
 
+/* Function 4 Link Configuration Registers	*/
+static struct cpu_debug_range cpu_amd_pci4[] = {
+	{ 0x000,	0x00C,	CPU_PCI		},
+	{ 0x034,	0x034,	CPU_PCI		},
+	{ 0x080,	0x0F8,	CPU_LINK	},
+	{ 0x170,	0x174,	CPU_POWER	},
+	{ 0x180,	0x19C,	CPU_LINK	},
+	{ 0x1C4,	0x1C4,	CPU_POWER	},
+	{ 0x1E0,	0x1F0,	CPU_POWER	},
+};
+
+/* Extended CPUID base address			*/
+static u32 cpu_ext_cpuid[] = {
+	0x80000000,		/* Intel, AMD	*/
+	0x80860000,		/* Transmeta	*/
+	0xC0000000,		/* Centaur	*/
+};
+
+/* Check validity of cpu debug flag */
 static int is_typeflag_valid(unsigned cpu, unsigned flag)
 {
 	int i;
@@ -171,8 +325,9 @@ static int is_typeflag_valid(unsigned cpu, unsigned flag)
 	if (flag >= CPU_TSS)
 		return 1;
 
-	for (i = 0; i < ARRAY_SIZE(cpu_reg_range); i++) {
-		if (cpu_reg_range[i].flag == flag)
+	/* check MSR range */
+	for (i = 0; i < ARRAY_SIZE(cpu_msr_range); i++) {
+		if (cpu_msr_range[i].flag == flag)
 			return 1;
 	}
 
@@ -180,12 +335,13 @@ static int is_typeflag_valid(unsigned cpu, unsigned flag)
 	return 0;
 }
 
-static unsigned get_cpu_range(unsigned cpu, unsigned *min, unsigned *max,
+/* get MSR range */
+static unsigned get_msr_range(unsigned cpu, unsigned *min, unsigned *max,
 			      int index, unsigned flag)
 {
-	if (cpu_reg_range[index].flag == flag) {
-		*min = cpu_reg_range[index].min;
-		*max = cpu_reg_range[index].max;
+	if (cpu_msr_range[index].flag == flag) {
+		*min = cpu_msr_range[index].min;
+		*max = cpu_msr_range[index].max;
 	} else
 		*max = 0;
 
@@ -226,11 +382,12 @@ static void print_msr(struct seq_file *seq, unsigned cpu, unsigned flag)
 					       &low, &high))
 				print_cpu_data(seq, priv->reg, low, high);
 			return;
-		}
+		} else
+			seq_printf(seq, " MSR\t:\n");
 	}
 
-	for (i = 0; i < ARRAY_SIZE(cpu_reg_range); i++) {
-		if (!get_cpu_range(cpu, &msr_min, &msr_max, i, flag))
+	for (i = 0; i < ARRAY_SIZE(cpu_msr_range); i++) {
+		if (!get_msr_range(cpu, &msr_min, &msr_max, i, flag))
 			continue;
 
 		for (msr = msr_min; msr <= msr_max; msr++) {
@@ -339,7 +496,7 @@ static void print_dr(void *arg)
 		seq_printf(seq, " dr%d\t: %016lx\n", i, dr);
 	}
 
-	seq_printf(seq, "\n MSR\t:\n");
+	seq_printf(seq, "\n");
 }
 
 static void print_apic(void *arg)
@@ -347,43 +504,251 @@ static void print_apic(void *arg)
 	struct seq_file *seq = arg;
 
 #ifdef CONFIG_X86_LOCAL_APIC
+	unsigned int i;
+
 	seq_printf(seq, " LAPIC\t:\n");
-	seq_printf(seq, " ID\t\t: %08x\n",  apic_read(APIC_ID) >> 24);
-	seq_printf(seq, " LVR\t\t: %08x\n",  apic_read(APIC_LVR));
-	seq_printf(seq, " TASKPRI\t: %08x\n",  apic_read(APIC_TASKPRI));
-	seq_printf(seq, " ARBPRI\t\t: %08x\n",  apic_read(APIC_ARBPRI));
-	seq_printf(seq, " PROCPRI\t: %08x\n",  apic_read(APIC_PROCPRI));
-	seq_printf(seq, " LDR\t\t: %08x\n",  apic_read(APIC_LDR));
-	seq_printf(seq, " DFR\t\t: %08x\n",  apic_read(APIC_DFR));
-	seq_printf(seq, " SPIV\t\t: %08x\n",  apic_read(APIC_SPIV));
-	seq_printf(seq, " ISR\t\t: %08x\n",  apic_read(APIC_ISR));
-	seq_printf(seq, " ESR\t\t: %08x\n",  apic_read(APIC_ESR));
-	seq_printf(seq, " ICR\t\t: %08x\n",  apic_read(APIC_ICR));
-	seq_printf(seq, " ICR2\t\t: %08x\n",  apic_read(APIC_ICR2));
-	seq_printf(seq, " LVTT\t\t: %08x\n",  apic_read(APIC_LVTT));
-	seq_printf(seq, " LVTTHMR\t: %08x\n",  apic_read(APIC_LVTTHMR));
-	seq_printf(seq, " LVTPC\t\t: %08x\n",  apic_read(APIC_LVTPC));
-	seq_printf(seq, " LVT0\t\t: %08x\n",  apic_read(APIC_LVT0));
-	seq_printf(seq, " LVT1\t\t: %08x\n",  apic_read(APIC_LVT1));
-	seq_printf(seq, " LVTERR\t\t: %08x\n",  apic_read(APIC_LVTERR));
-	seq_printf(seq, " TMICT\t\t: %08x\n",  apic_read(APIC_TMICT));
-	seq_printf(seq, " TMCCT\t\t: %08x\n",  apic_read(APIC_TMCCT));
-	seq_printf(seq, " TDCR\t\t: %08x\n",  apic_read(APIC_TDCR));
+	for (i = 0; i < ARRAY_SIZE(cpu_apic); i++) {
+		if (strlen(cpu_apic[i].name) < 7)
+			seq_printf(seq, " %s\t\t: %08x\n",  cpu_apic[i].name,
+				   apic_read(cpu_apic[i].flag));
+		else
+			seq_printf(seq, " %s\t: %08x\n",  cpu_apic[i].name,
+				   apic_read(cpu_apic[i].flag));
+	}
 	if (boot_cpu_has(X86_FEATURE_EXTAPIC)) {
-		unsigned int i, v, maxeilvt;
+		unsigned int maxeilvt;
 
-		v = apic_read(APIC_EFEAT);
-		maxeilvt = (v >> 16) & 0xff;
-		seq_printf(seq, " EFEAT\t\t: %08x\n", v);
-		seq_printf(seq, " ECTRL\t\t: %08x\n", apic_read(APIC_ECTRL));
+		for (i = 0; i < ARRAY_SIZE(cpu_xapic); i++)
+			seq_printf(seq, " %s\t\t: %08x\n",  cpu_xapic[i].name,
+				   apic_read(cpu_xapic[i].flag));
 
-		for (i = 0; i < maxeilvt; i++) {
-			v = apic_read(APIC_EILVTn(i));
-			seq_printf(seq, " EILVT%d\t\t: %08x\n", i, v);
+		maxeilvt = (apic_read(APIC_EFEAT) >> 16) & 0xff;
+		for (i = 0; i < maxeilvt; i++)
+			seq_printf(seq, " EILVT%d\t\t: %08x\n",
+				   i, apic_read(APIC_EILVTn(i)));
+	}
+	seq_printf(seq, "\n");
+#endif
+}
+
+/* Get extended CPUID level */
+static u32 get_extended_cpuid(void)
+{
+	u32 i, level;
+
+	for (i = 0; i < ARRAY_SIZE(cpu_ext_cpuid); i++) {
+		level = cpuid_eax(cpu_ext_cpuid[i]);
+		if ((level & CPUID_MASK) == cpu_ext_cpuid[i])
+			return level;
+	}
+
+	return 0;		/* Not found */
+}
+
+static void print_cpuidabcd(struct seq_file *seq, u32 min, u32 max)
+{
+	u32 i, eax, ebx, ecx, edx;
+
+	for (i = min; i <= max; i++) {
+		cpuid(i, &eax, &ebx, &ecx, &edx);
+		seq_printf(seq, " %08x  %08x  %08x  %08x  %08x\n",
+			   i, eax, ebx, ecx, edx);
+	}
+}
+
+static void print_cpuid(void *arg)
+{
+	struct seq_file *seq = arg;
+	u32 level;
+
+	seq_printf(seq, " CPUID\t:\n");
+	seq_printf(seq, "              eax       ebx       ecx       edx\n");
+
+	/* Standard CPUID functions */
+	level = cpuid_eax(0);
+	print_cpuidabcd(seq, 0, level);
+
+	/* Extended CPUID functions */
+	level = get_extended_cpuid();
+	if (level)
+		print_cpuidabcd(seq, (level & CPUID_MASK), level);
+}
+
+/* dump struct cpuinfo_x86 */
+static void print_cpuinfo(void *arg)
+{
+	struct seq_file *seq = arg;
+	struct cpu_private *priv = seq->private;
+	struct cpuinfo_x86 *cpui;
+	unsigned int i;
+
+	cpui = &cpu_data(priv->cpu);
+	seq_printf(seq, " CPUINFO\t:\n");
+	seq_printf(seq, " processor\t\t: %u\n", priv->cpu);
+
+	seq_printf(seq, " family\t\t\t: %u\n", cpui->x86);
+	seq_printf(seq, " vendor\t\t\t: %u\n", cpui->x86_vendor);
+	seq_printf(seq, " model\t\t\t: %u\n", cpui->x86_model);
+	seq_printf(seq, " mask\t\t\t: %u\n", cpui->x86_mask);
+#ifdef CONFIG_X86_32
+	seq_printf(seq, " wp_works_ok\t\t: %u\n", cpui->wp_works_ok);
+	seq_printf(seq, " halt_works_ok\t\t: %u\n", cpui->hlt_works_ok);
+	seq_printf(seq, " hard_math\t\t: %u\n", cpui->hard_math);
+	seq_printf(seq, " rfu\t\t\t: %u\n", cpui->rfu);
+	seq_printf(seq, " fdiv_bug\t\t: %u\n", cpui->fdiv_bug);
+	seq_printf(seq, " f00f_bug\t\t: %u\n", cpui->f00f_bug);
+	seq_printf(seq, " coma_bug\t\t: %u\n", cpui->coma_bug);
+#else
+	seq_printf(seq, " TLB size\t\t: %d 4K pages\n", cpui->x86_tlbsize);
+#endif
+	seq_printf(seq, " virtual bits\t\t: %u\n", cpui->x86_virt_bits);
+	seq_printf(seq, " physical bits\t\t: %u\n", cpui->x86_phys_bits);
+
+	seq_printf(seq, " extended cpuid level\t: %08x (%08x)\n",
+		   cpui->extended_cpuid_level, get_extended_cpuid());
+	seq_printf(seq, " cpuid level\t\t: %d\n", cpui->cpuid_level);
+
+	seq_printf(seq, " flags\t\t\t:");
+	for (i = 0; i < 32 * NCAPINTS; i++)
+		if (cpu_has(cpui, i) && x86_cap_flags[i] != NULL)
+			seq_printf(seq, " %s", x86_cap_flags[i]);
+
+	seq_printf(seq, "\n vendor id\t\t: %s\n",
+		   cpui->x86_vendor_id[0] ? cpui->x86_vendor_id : "unknown");
+	seq_printf(seq, " model id\t\t: %s\n",
+		   cpui->x86_model_id[0] ? cpui->x86_model_id : "unknown");
+
+	seq_printf(seq, " cache size\t\t: %d KB\n", cpui->x86_cache_size);
+	seq_printf(seq, " cache alignment\t: %d\n", cpui->x86_cache_alignment);
+
+	seq_printf(seq, " power management\t:");
+	for (i = 0; i < 32; i++) {
+		if (cpui->x86_power & (1 << i)) {
+			if (i < ARRAY_SIZE(x86_power_flags) &&
+			    x86_power_flags[i])
+				seq_printf(seq, "%s%s",
+					   x86_power_flags[i][0] ? " " : "",
+					   x86_power_flags[i]);
+			else
+				seq_printf(seq, " [%d]", i);
 		}
 	}
-#endif /* CONFIG_X86_LOCAL_APIC */
-	seq_printf(seq, "\n MSR\t:\n");
+
+	seq_printf(seq, "\n loops per jiffy\t: %lu\n", cpui->loops_per_jiffy);
+	seq_printf(seq, " bogomips\t\t: %lu.%02lu\n",
+		   cpui->loops_per_jiffy/(500000/HZ),
+		   (cpui->loops_per_jiffy/(5000/HZ)) % 100);
+
+	seq_printf(seq, " max cores\t\t: %d\n", cpui->x86_max_cores);
+	seq_printf(seq, " apic id\t\t: %d\n", cpui->apicid);
+	seq_printf(seq, " intial apic id\t\t: %d\n", cpui->initial_apicid);
+	seq_printf(seq, " clflush size\t\t: %u\n", cpui->x86_clflush_size);
+
+#ifdef CONFIG_SMP
+	seq_printf(seq, " cpu cores\t\t: %d\n", cpui->booted_cores);
+	seq_printf(seq, " physical id\t\t: %d\n", cpui->phys_proc_id);
+	seq_printf(seq, " core id\t\t: %d\n", cpui->cpu_core_id);
+	seq_printf(seq, " cpu index\t\t: %d\n", cpui->cpu_index);
+#endif
+
+	seq_printf(seq, " hyper vendor\t\t: %d\n", cpui->x86_hyper_vendor);
+}
+
+static void print_apicval(void *arg)
+{
+	struct seq_file *seq = arg;
+
+#ifdef CONFIG_X86_LOCAL_APIC
+	struct cpu_private *priv = seq->private;
+
+	seq_printf(seq, "0x%x\n", apic_read(priv->reg));
+#endif
+}
+
+static void print_pcival(void *arg)
+{
+	struct seq_file *seq = arg;
+	struct cpu_private *priv = seq->private;
+	struct pci_dev *dev;
+	u32 data = (priv->reg & 0xf0000) >> 16;
+
+	if (data >= MAX_CPU_PCI)
+		return;
+
+	dev = per_cpu(pci_arr[data], priv->cpu);
+	if (!pci_read_config_dword(dev, priv->reg & 0x0fff, &data))
+		seq_printf(seq, "0x%x\n", data);
+}
+
+#define PRINT_AMD_PCI(func) \
+static void print_amd_pci##func(struct seq_file *seq, struct pci_dev *dev) \
+{									\
+	unsigned int reg, i;						\
+	u32 data;							\
+									\
+	for (i = 0; i < ARRAY_SIZE(cpu_amd_pci##func); i++) {		\
+		for (reg = cpu_amd_pci##func[i].min; 			\
+		     reg <= cpu_amd_pci##func[i].max; reg++) {		\
+			if (!pci_read_config_dword(dev, reg, &data)) {	\
+				seq_printf(seq, " %03x\t: %08x\n", 	\
+					   reg, data);			\
+			}						\
+		}							\
+	}								\
+	seq_printf(seq, "\n");						\
+}
+
+PRINT_AMD_PCI(0)
+PRINT_AMD_PCI(1)
+PRINT_AMD_PCI(2)
+PRINT_AMD_PCI(3)
+PRINT_AMD_PCI(4)
+
+static void print_amd_pci(struct seq_file *seq)
+{
+	struct cpu_private *priv = seq->private;
+	struct pci_dev *dev;
+	unsigned int func;
+
+	for (func = 0; func < MAX_CPU_PCI; func++) {
+		dev = per_cpu(pci_arr[func], priv->cpu);
+		if (dev == NULL)
+			continue;
+
+		seq_printf(seq, " function : %d\n", func);
+
+		switch (func) {
+		case 0:
+			print_amd_pci0(seq, dev);
+			break;
+		case 1:
+			print_amd_pci1(seq, dev);
+			break;
+		case 2:
+			print_amd_pci2(seq, dev);
+			break;
+		case 3:
+			print_amd_pci3(seq, dev);
+			break;
+		case 4:
+			print_amd_pci4(seq, dev);
+			break;
+		}
+	}
+}
+
+static void print_pci(void *arg)
+{
+	struct seq_file *seq = arg;
+
+	seq_printf(seq, " PCI configuration regsiters :\n");
+	switch (boot_cpu_data.x86_vendor) {
+	case X86_VENDOR_AMD:
+		print_amd_pci(seq);
+		break;
+	default:
+		return;
+	}
 }
 
 static int cpu_seq_show(struct seq_file *seq, void *v)
@@ -403,19 +768,46 @@ static int cpu_seq_show(struct seq_file *seq, void *v)
 	case CPU_DT:
 		smp_call_function_single(priv->cpu, print_dt, seq, 1);
 		break;
+	case CPU_CPUID:
+		if (priv->file == CPU_INDEX)
+			smp_call_function_single(priv->cpu, print_cpuid,
+						 seq, 1);
+		else
+			smp_call_function_single(priv->cpu, print_pcival,
+						 seq, 1);
+		break;
+	case CPU_CPUINFO:
+		smp_call_function_single(priv->cpu, print_cpuinfo, seq, 1);
+		break;
+	case CPU_PCI:
+		if (priv->file == CPU_INDEX)
+			smp_call_function_single(priv->cpu, print_pci, seq, 1);
+		else
+			smp_call_function_single(priv->cpu, print_pcival,
+						 seq, 1);
+		break;
 	case CPU_DEBUG:
-		if (priv->file == CPU_INDEX_BIT)
+		if (priv->file == CPU_INDEX)
 			smp_call_function_single(priv->cpu, print_dr, seq, 1);
-		print_msr(seq, priv->cpu, cpu_base[priv->type].flag);
+		if (priv->cat == CPU_REG_MSR)
+			print_msr(seq, priv->cpu, cpu_base[priv->type].flag);
 		break;
 	case CPU_APIC:
-		if (priv->file == CPU_INDEX_BIT)
+		if (priv->file == CPU_INDEX)
 			smp_call_function_single(priv->cpu, print_apic, seq, 1);
-		print_msr(seq, priv->cpu, cpu_base[priv->type].flag);
+		if (priv->cat == CPU_REG_MSR)
+			print_msr(seq, priv->cpu, cpu_base[priv->type].flag);
+		else if (priv->cat == CPU_REG_APIC)
+			smp_call_function_single(priv->cpu, print_apicval,
+						 seq, 1);
 		break;
 
 	default:
-		print_msr(seq, priv->cpu, cpu_base[priv->type].flag);
+		if (priv->cat == CPU_REG_MSR)
+			print_msr(seq, priv->cpu, cpu_base[priv->type].flag);
+		else if (priv->cat == CPU_REG_PCI)
+			smp_call_function_single(priv->cpu, print_pcival,
+						 seq, 1);
 		break;
 	}
 	seq_printf(seq, "\n");
@@ -487,7 +879,7 @@ static int write_cpu_register(struct cpu_private *priv, const char *buf)
 		return ret;
 
 	/* Supporting only MSRs */
-	if (priv->type < CPU_TSS_BIT)
+	if (priv->type < CPU_TSS)
 		return write_msr(priv, val);
 
 	return ret;
@@ -525,12 +917,12 @@ static const struct file_operations cpu_fops = {
 };
 
 static int cpu_create_file(unsigned cpu, unsigned type, unsigned reg,
-			   unsigned file, struct dentry *dentry)
+			   unsigned file, unsigned cat, struct dentry *dentry)
 {
 	struct cpu_private *priv = NULL;
 
 	/* Already intialized */
-	if (file == CPU_INDEX_BIT)
+	if (file == CPU_INDEX)
 		if (per_cpu(cpu_arr[type].init, cpu))
 			return 0;
 
@@ -542,6 +934,7 @@ static int cpu_create_file(unsigned cpu, unsigned type, unsigned reg,
 	priv->type = type;
 	priv->reg = reg;
 	priv->file = file;
+	priv->cat = cat;
 	mutex_lock(&cpu_debug_lock);
 	per_cpu(priv_arr[type], cpu) = priv;
 	per_cpu(cpu_priv_count, cpu)++;
@@ -551,7 +944,7 @@ static int cpu_create_file(unsigned cpu, unsigned type, unsigned reg,
 		debugfs_create_file(cpu_file[file].name, S_IRUGO,
 				    dentry, (void *)priv, &cpu_fops);
 	else {
-		debugfs_create_file(cpu_base[type].name, S_IRUGO,
+		debugfs_create_file(cpu_file[file].name, S_IRUGO,
 				    per_cpu(cpu_arr[type].dentry, cpu),
 				    (void *)priv, &cpu_fops);
 		mutex_lock(&cpu_debug_lock);
@@ -563,13 +956,13 @@ static int cpu_create_file(unsigned cpu, unsigned type, unsigned reg,
 }
 
 static int cpu_init_regfiles(unsigned cpu, unsigned int type, unsigned reg,
-			     struct dentry *dentry)
+			     unsigned cat, struct dentry *dentry)
 {
 	unsigned file;
 	int err = 0;
 
-	for (file = 0; file <  ARRAY_SIZE(cpu_file); file++) {
-		err = cpu_create_file(cpu, type, reg, file, dentry);
+	for (file = 0; file < ARRAY_SIZE(cpu_file); file++) {
+		err = cpu_create_file(cpu, type, reg, file, cat, dentry);
 		if (err)
 			return err;
 	}
@@ -585,8 +978,8 @@ static int cpu_init_msr(unsigned cpu, unsigned type, struct dentry *dentry)
 	char reg_dir[12];
 	u32 low, high;
 
-	for (i = 0; i < ARRAY_SIZE(cpu_reg_range); i++) {
-		if (!get_cpu_range(cpu, &reg_min, &reg_max, i,
+	for (i = 0; i < ARRAY_SIZE(cpu_msr_range); i++) {
+		if (!get_msr_range(cpu, &reg_min, &reg_max, i,
 				   cpu_base[type].flag))
 			continue;
 
@@ -594,9 +987,10 @@ static int cpu_init_msr(unsigned cpu, unsigned type, struct dentry *dentry)
 			if (rdmsr_safe_on_cpu(cpu, reg, &low, &high))
 				continue;
 
-			sprintf(reg_dir, "0x%x", reg);
+			sprintf(reg_dir, "MSR_%x", reg);
 			cpu_dentry = debugfs_create_dir(reg_dir, dentry);
-			err = cpu_init_regfiles(cpu, type, reg, cpu_dentry);
+			err = cpu_init_regfiles(cpu, type, reg, CPU_REG_MSR,
+						cpu_dentry);
 			if (err)
 				return err;
 		}
@@ -605,23 +999,144 @@ static int cpu_init_msr(unsigned cpu, unsigned type, struct dentry *dentry)
 	return err;
 }
 
+static void cpu_init_apic(unsigned cpu, struct dentry *dentry)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+	struct dentry *cpu_dentry;
+	char reg_dir[16];
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(cpu_apic); i++) {
+		sprintf(reg_dir, "APIC_%s", cpu_apic[i].name);
+		cpu_dentry = debugfs_create_dir(reg_dir, dentry);
+		cpu_create_file(cpu, CPU_APIC, cpu_apic[i].flag, CPU_VALUE,
+				CPU_REG_APIC, cpu_dentry);
+	}
+
+	if (boot_cpu_has(X86_FEATURE_EXTAPIC)) {
+		unsigned int maxeilvt;
+
+		for (i = 0; i < ARRAY_SIZE(cpu_xapic); i++) {
+			sprintf(reg_dir, "APIC_%s", cpu_xapic[i].name);
+			cpu_dentry = debugfs_create_dir(reg_dir, dentry);
+			cpu_create_file(cpu, CPU_APIC, cpu_xapic[i].flag,
+					CPU_VALUE, CPU_REG_APIC, cpu_dentry);
+		}
+
+		maxeilvt = (apic_read(APIC_EFEAT) >> 16) & 0xff;
+		for (i = 0; i < maxeilvt; i++) {
+			sprintf(reg_dir, "APIC_EILVT%d", i);
+			cpu_dentry = debugfs_create_dir(reg_dir, dentry);
+			cpu_create_file(cpu, CPU_APIC, APIC_EILVTn(i),
+					CPU_VALUE, CPU_REG_APIC, cpu_dentry);
+		}
+	}
+#endif
+}
+
+#define INIT_AMD_PCI(func) \
+static void init_amd_pci##func(unsigned cpu, struct dentry *dentry, 	\
+				struct pci_dev *dev)			\
+{									\
+	struct dentry *cdentry;						\
+	unsigned int reg, i, id;					\
+	char reg_dir[10];						\
+	u32 data;							\
+									\
+	for (i = 0; i < ARRAY_SIZE(cpu_amd_pci##func); i++) {		\
+		for (reg = cpu_amd_pci##func[i].min;			\
+		     reg <= cpu_amd_pci##func[i].max; reg++) {		\
+			if (!pci_read_config_dword(dev, reg, &data)) {	\
+				sprintf(reg_dir, "PCI%d_%03x",		\
+					func, reg);			\
+				id = cpu_amd_pci##func[i].flag;		\
+				cdentry = debugfs_create_dir(reg_dir,	\
+					per_cpu(cpu_arr[id].dentry, cpu)); \
+				cpu_create_file(cpu, 			\
+						cpu_amd_pci##func[i].flag, \
+						(func << 16) | reg,	\
+						CPU_VALUE, CPU_REG_PCI, \
+						cdentry);		\
+			}						\
+		}							\
+	}								\
+}
+
+/* AMD supports five functions, 0 through 4 */
+INIT_AMD_PCI(0)
+INIT_AMD_PCI(1)
+INIT_AMD_PCI(2)
+INIT_AMD_PCI(3)
+INIT_AMD_PCI(4)
+
+static void init_amd_pci(unsigned cpu, struct dentry *dentry)
+{
+	struct pci_dev *dev = NULL;
+	unsigned int func;
+
+	while ((dev = pci_get_device(PCI_VENDOR_ID_AMD, PCI_ANY_ID, dev))
+	       != NULL) {
+		if ((dev->device >= 0x1100) && (dev->device < 0x2000)) {
+			func = dev->device & 0xff;
+			if (func >= MAX_CPU_PCI)
+				continue;
+
+			per_cpu(pci_arr[func], cpu) = dev;
+			switch (func) {
+			case 0:
+				init_amd_pci0(cpu, dentry, dev);
+				break;
+			case 1:
+				init_amd_pci1(cpu, dentry, dev);
+				break;
+			case 2:
+				init_amd_pci2(cpu, dentry, dev);
+				break;
+			case 3:
+				init_amd_pci3(cpu, dentry, dev);
+				break;
+			case 4:
+				init_amd_pci4(cpu, dentry, dev);
+				break;
+			}
+		}
+	}
+}
+
+static void cpu_init_pci(unsigned cpu, struct dentry *dentry)
+{
+	switch (boot_cpu_data.x86_vendor) {
+	case X86_VENDOR_AMD:
+		init_amd_pci(cpu, dentry);
+		break;
+	default:
+		return;
+	}
+}
+
 static int cpu_init_allreg(unsigned cpu, struct dentry *dentry)
 {
 	struct dentry *cpu_dentry = NULL;
 	unsigned type;
 	int err = 0;
 
-	for (type = 0; type <  ARRAY_SIZE(cpu_base) - 1; type++) {
-		if (!is_typeflag_valid(cpu, cpu_base[type].flag))
-			continue;
+	for (type = 0; type < ARRAY_SIZE(cpu_base) - 1; type++) {
 		cpu_dentry = debugfs_create_dir(cpu_base[type].name, dentry);
 		per_cpu(cpu_arr[type].dentry, cpu) = cpu_dentry;
 
-		if (type < CPU_TSS_BIT)
+		/* check before preparing "state" file */
+		if (!is_typeflag_valid(cpu, cpu_base[type].flag))
+			continue;
+
+		if (type == CPU_APIC)
+			cpu_init_apic(cpu, cpu_dentry);
+		if (type == CPU_PCI)
+			cpu_init_pci(cpu, cpu_dentry);
+		if (type < CPU_TSS)
 			err = cpu_init_msr(cpu, type, cpu_dentry);
 		else
-			err = cpu_create_file(cpu, type, 0, CPU_INDEX_BIT,
-					      cpu_dentry);
+			err = cpu_create_file(cpu, type, 0, CPU_INDEX,
+					      CPU_REG_STD, cpu_dentry);
 		if (err)
 			return err;
 	}
@@ -649,8 +1164,8 @@ static int cpu_init_cpu(void)
 		pr_info("cpu%d(%d) debug files %d\n",
 			cpu, nr_cpu_ids, per_cpu(cpu_priv_count, cpu));
 		if (per_cpu(cpu_priv_count, cpu) > MAX_CPU_FILES) {
-			pr_err("Register files count %d exceeds limit %d\n",
-				per_cpu(cpu_priv_count, cpu), MAX_CPU_FILES);
+			WARN_ONCE(1, "debug files count %d exceeds limit %d\n",
+				  per_cpu(cpu_priv_count, cpu), MAX_CPU_FILES);
 			per_cpu(cpu_priv_count, cpu) = MAX_CPU_FILES;
 			err = -ENFILE;
 		}
@@ -683,6 +1198,6 @@ static void __exit cpu_debug_exit(void)
 module_init(cpu_debug_init);
 module_exit(cpu_debug_exit);
 
-MODULE_AUTHOR("Jaswinder Singh Rajput");
+MODULE_AUTHOR("Jaswinder Singh Rajput <jaswinder@...nel.org>");
 MODULE_DESCRIPTION("CPU Debug module");
 MODULE_LICENSE("GPL");


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ