Skip to contentSkip to conversation

AMD L3 cache index disable fixes for .35

PATCH In review Borislav Petkov 5 participants 21 messages Apr 22, 2010 – May 17, 2010

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

cover AMD L3 cache index disable fixes for .35

From: Borislav Petkov <[email protected]>

Hi,

here's the dynamic allocation version in 4/5. The small amount of NUM_NODES * 8 Bytes is not being freed because we don't have an exit callback but I guess this is ok since we want to free it only when shutting down anyway.

-v2:

Allocate l3_caches descriptor array dynamically.

-v1:

this is a small patchset of fixes for L3 CID which have accumulated over the last couple of weeks. They serve as a preparation for disabling L3 cache indices whenever an L3 MCE triggers, has been evaluated and the offending index thresholded and, if error rate is excessively high, disabled. Those patches will be coming up later though.

Patches 1,3,4 are cleanups and unifications which save us a little bit of percpu memory in favor of dynamic allocation. Also, we have an L3 cache descriptor per node now instead of having this information per CPU.

I triggered a lockdep warning in lockdep_trace_alloc() during testing due to the fact that we may run with disabled interrupts that early in the boot process. Therefore, I have a GFP_ATOMIC in patch 3 there allocating the cache descriptors. I'm open for suggestions in case this is undesired.

Patch 2 is a fix which triggers when we run as a guest on Xen due to Xen not exporting CPU PCI config space to the guests.

And finally #5 is a required fix.

The patchset is also available at
git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp.git l3-for-35

Please queue for .35,
thanks.

#1 lore raw

PATCH 1/5 x86, cacheinfo: Unify AMD L3 cache index disable checking

From: Borislav Petkov <[email protected]>

All F10h CPUs starting with model 8 resp. 9, stepping 1, support L3 cache index disable. Concentrate the family, model, stepping checking at one place and enable the feature implicitly on upcoming Fam10h models.

---
 arch/x86/kernel/cpu/intel_cacheinfo.c |   17 ++++++++++-------
 1 files changed, 10 insertions(+), 7 deletions(-)
arch/x86/kernel/cpu/intel_cacheinfo.c +10 -7
index b3eeb66..acfb083 100644
@@ -328,18 +328,22 @@ static unsigned int __cpuinit amd_calc_l3_indices(void)
 static void __cpuinit
 amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
 {
-	if (index < 3)
+	if (boot_cpu_data.x86 != 0x10)
 		return;
 
-	if (boot_cpu_data.x86 == 0x11)
+	if (index < 3)
 		return;
 
 	/* see errata #382 and #388 */
-	if ((boot_cpu_data.x86 == 0x10) &&
-	    ((boot_cpu_data.x86_model < 0x8) ||
-	     (boot_cpu_data.x86_mask  < 0x1)))
+	if (boot_cpu_data.x86_model < 0x8)
 		return;
 
+	if ((boot_cpu_data.x86_model == 0x8 ||
+	     boot_cpu_data.x86_model == 0x9)
+		&&
+	     boot_cpu_data.x86_mask < 0x1)
+			return;
+
 	this_leaf->can_disable = true;
 	this_leaf->l3_indices  = amd_calc_l3_indices();
 }
@@ -443,8 +447,7 @@ __cpuinit cpuid4_cache_lookup_regs(int index,
 
 	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
 		amd_cpuid4(index, &eax, &ebx, &ecx);
-		if (boot_cpu_data.x86 >= 0x10)
-			amd_check_l3_disable(index, this_leaf);
+		amd_check_l3_disable(index, this_leaf);
 	} else {
 		cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx);
 	}
Signature · 1 line
1.7.1.rc1
#2 lore raw

[tip:x86/cpu] x86, cacheinfo: Unify AMD L3 cache index disable checking

Commit-ID:  b1ab1b4d9ab9812c77843abec79030292ef0a544
Gitweb:     http://git.kernel.org/tip/b1ab1b4d9ab9812c77843abec79030292ef0a544
Author:     Borislav Petkov <[email protected]>
AuthorDate: Thu, 22 Apr 2010 16:06:58 +0200
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Thu, 22 Apr 2010 17:17:20 -0700

x86, cacheinfo: Unify AMD L3 cache index disable checking

All F10h CPUs starting with model 8 resp. 9, stepping 1, support L3 cache index disable. Concentrate the family, model, stepping checking at one place and enable the feature implicitly on upcoming Fam10h models.

LKML-Reference: <[email protected]>

---
 arch/x86/kernel/cpu/intel_cacheinfo.c |   17 ++++++++++-------
 1 files changed, 10 insertions(+), 7 deletions(-)
arch/x86/kernel/cpu/intel_cacheinfo.c +10 -7
index b3eeb66..acfb083 100644
@@ -328,18 +328,22 @@ static unsigned int __cpuinit amd_calc_l3_indices(void)
 static void __cpuinit
 amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
 {
-	if (index < 3)
+	if (boot_cpu_data.x86 != 0x10)
 		return;
 
-	if (boot_cpu_data.x86 == 0x11)
+	if (index < 3)
 		return;
 
 	/* see errata #382 and #388 */
-	if ((boot_cpu_data.x86 == 0x10) &&
-	    ((boot_cpu_data.x86_model < 0x8) ||
-	     (boot_cpu_data.x86_mask  < 0x1)))
+	if (boot_cpu_data.x86_model < 0x8)
 		return;
 
+	if ((boot_cpu_data.x86_model == 0x8 ||
+	     boot_cpu_data.x86_model == 0x9)
+		&&
+	     boot_cpu_data.x86_mask < 0x1)
+			return;
+
 	this_leaf->can_disable = true;
 	this_leaf->l3_indices  = amd_calc_l3_indices();
 }
@@ -443,8 +447,7 @@ __cpuinit cpuid4_cache_lookup_regs(int index,
 
 	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
 		amd_cpuid4(index, &eax, &ebx, &ecx);
-		if (boot_cpu_data.x86 >= 0x10)
-			amd_check_l3_disable(index, this_leaf);
+		amd_check_l3_disable(index, this_leaf);
 	} else {
 		cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx);
 	}
#3 lore raw

PATCH 2/5 x86, cacheinfo: Turn off L3 cache index disable feature in virtualized environments

In reply to Borislav Petkov

From: Frank Arnold <[email protected]>

When running a quest kernel on xen we get:

BUG: unable to handle kernel NULL pointer dereference at 0000000000000038
IP: [<ffffffff8142f2fb>] cpuid4_cache_lookup_regs+0x2ca/0x3df
PGD 0
Oops: 0000 [#1] SMP
last sysfs file:
CPU 0
Modules linked in:

Pid: 0, comm: swapper Tainted: G W 2.6.34-rc3 #1 /HVM domU

RIP: 0010:[<ffffffff8142f2fb>]  [<ffffffff8142f2fb>] cpuid4_cache_lookup_regs+0x
2ca/0x3df
RSP: 0018:ffff880002203e08  EFLAGS: 00010046
RAX: 0000000000000000 RBX: 0000000000000003 RCX: 0000000000000060
RDX: 0000000000000000 RSI: 0000000000000040 RDI: 0000000000000000
RBP: ffff880002203ed8 R08: 00000000000017c0 R09: ffff880002203e38
R10: ffff8800023d5d40 R11: ffffffff81a01e28 R12: ffff880187e6f5c0
R13: ffff880002203e34 R14: ffff880002203e58 R15: ffff880002203e68
FS:  0000000000000000(0000) GS:ffff880002200000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000038 CR3: 0000000001a3c000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process swapper (pid: 0, threadinfo ffffffff81a00000, task ffffffff81a44020)
Stack:
 ffffffff810d7ecb ffff880002203e20 ffffffff81059140 ffff880002203e30
<0> ffffffff810d7ec9 0000000002203e40 000000000050d140 ffff880002203e70
<0> 0000000002008140 0000000000000086 ffff880040020140 ffffffff81068b8b
Call Trace:
 <IRQ>
 [<ffffffff810d7ecb>] ? sync_supers_timer_fn+0x0/0x1c
 [<ffffffff81059140>] ? mod_timer+0x23/0x25
 [<ffffffff810d7ec9>] ? arm_supers_timer+0x34/0x36
 [<ffffffff81068b8b>] ? hrtimer_get_next_event+0xa7/0xc3
 [<ffffffff81058e85>] ? get_next_timer_interrupt+0x19a/0x20d
 [<ffffffff8142fa23>] get_cpu_leaves+0x5c/0x232
 [<ffffffff8106a7b1>] ? sched_clock_local+0x1c/0x82
 [<ffffffff8106a9a0>] ? sched_clock_tick+0x75/0x7a
 [<ffffffff8107748c>] generic_smp_call_function_single_interrupt+0xae/0xd0
 [<ffffffff8101f6ef>] smp_call_function_single_interrupt+0x18/0x27
 [<ffffffff8100a773>] call_function_single_interrupt+0x13/0x20
 <EOI>
 [<ffffffff8143c468>] ? notifier_call_chain+0x14/0x63
 [<ffffffff810295c6>] ? native_safe_halt+0xc/0xd
 [<ffffffff810114eb>] ? default_idle+0x36/0x53
 [<ffffffff81008c22>] cpu_idle+0xaa/0xe4
 [<ffffffff81423a9a>] rest_init+0x7e/0x80
 [<ffffffff81b10dd2>] start_kernel+0x40e/0x419
 [<ffffffff81b102c8>] x86_64_start_reservations+0xb3/0xb7
 [<ffffffff81b103c4>] x86_64_start_kernel+0xf8/0x107
Code: 14 d5 40 ff ae 81 8b 14 02 31 c0 3b 15 47 1c 8b 00 7d 0e 48 8b 05 36 1c 8b
 00 48 63 d2 48 8b 04 d0 c7 85 5c ff ff ff 00 00 00 00 <8b> 70 38 48 8d 8d 5c ff
 ff ff 48 8b 78 10 ba c4 01 00 00 e8 eb
RIP  [<ffffffff8142f2fb>] cpuid4_cache_lookup_regs+0x2ca/0x3df
 RSP <ffff880002203e08>
CR2: 0000000000000038
---[ end trace a7919e7f17c0a726 ]---

The L3 cache index disable feature of AMD CPUs has to be disabled if the kernel is running as guest on top of a hypervisor because northbridge devices are not available to the guest. Currently, this fixes a boot crash on top of Xen. In the future this will become an issue on KVM as well.

Check if northbridge devices are present and do not enable the feature if there are none.

---
 arch/x86/kernel/cpu/intel_cacheinfo.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
arch/x86/kernel/cpu/intel_cacheinfo.c +4 -0
index acfb083..5ab14c8 100644
@@ -344,6 +344,10 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
 	     boot_cpu_data.x86_mask < 0x1)
 			return;
 
+	/* not in virtualized environments */
+	if (num_k8_northbridges == 0)
+		return;
+
 	this_leaf->can_disable = true;
 	this_leaf->l3_indices  = amd_calc_l3_indices();
 }
Signature · 1 line
1.7.1.rc1
#4 lore raw

[tip:x86/cpu] x86, cacheinfo: Turn off L3 cache index disable feature in virtualized environments

Commit-ID:  f2b20e41407fccfcfacf927ff91ec888832a37af
Gitweb:     http://git.kernel.org/tip/f2b20e41407fccfcfacf927ff91ec888832a37af
Author:     Frank Arnold <[email protected]>
AuthorDate: Thu, 22 Apr 2010 16:06:59 +0200
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Thu, 22 Apr 2010 17:17:21 -0700

x86, cacheinfo: Turn off L3 cache index disable feature in virtualized environments

When running a quest kernel on xen we get:

BUG: unable to handle kernel NULL pointer dereference at 0000000000000038
IP: [<ffffffff8142f2fb>] cpuid4_cache_lookup_regs+0x2ca/0x3df
PGD 0
Oops: 0000 [#1] SMP
last sysfs file:
CPU 0
Modules linked in:

Pid: 0, comm: swapper Tainted: G W 2.6.34-rc3 #1 /HVM domU

RIP: 0010:[<ffffffff8142f2fb>]  [<ffffffff8142f2fb>] cpuid4_cache_lookup_regs+0x
2ca/0x3df
RSP: 0018:ffff880002203e08  EFLAGS: 00010046
RAX: 0000000000000000 RBX: 0000000000000003 RCX: 0000000000000060
RDX: 0000000000000000 RSI: 0000000000000040 RDI: 0000000000000000
RBP: ffff880002203ed8 R08: 00000000000017c0 R09: ffff880002203e38
R10: ffff8800023d5d40 R11: ffffffff81a01e28 R12: ffff880187e6f5c0
R13: ffff880002203e34 R14: ffff880002203e58 R15: ffff880002203e68
FS:  0000000000000000(0000) GS:ffff880002200000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000038 CR3: 0000000001a3c000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process swapper (pid: 0, threadinfo ffffffff81a00000, task ffffffff81a44020)
Stack:
 ffffffff810d7ecb ffff880002203e20 ffffffff81059140 ffff880002203e30
<0> ffffffff810d7ec9 0000000002203e40 000000000050d140 ffff880002203e70
<0> 0000000002008140 0000000000000086 ffff880040020140 ffffffff81068b8b
Call Trace:
 <IRQ>
 [<ffffffff810d7ecb>] ? sync_supers_timer_fn+0x0/0x1c
 [<ffffffff81059140>] ? mod_timer+0x23/0x25
 [<ffffffff810d7ec9>] ? arm_supers_timer+0x34/0x36
 [<ffffffff81068b8b>] ? hrtimer_get_next_event+0xa7/0xc3
 [<ffffffff81058e85>] ? get_next_timer_interrupt+0x19a/0x20d
 [<ffffffff8142fa23>] get_cpu_leaves+0x5c/0x232
 [<ffffffff8106a7b1>] ? sched_clock_local+0x1c/0x82
 [<ffffffff8106a9a0>] ? sched_clock_tick+0x75/0x7a
 [<ffffffff8107748c>] generic_smp_call_function_single_interrupt+0xae/0xd0
 [<ffffffff8101f6ef>] smp_call_function_single_interrupt+0x18/0x27
 [<ffffffff8100a773>] call_function_single_interrupt+0x13/0x20
 <EOI>
 [<ffffffff8143c468>] ? notifier_call_chain+0x14/0x63
 [<ffffffff810295c6>] ? native_safe_halt+0xc/0xd
 [<ffffffff810114eb>] ? default_idle+0x36/0x53
 [<ffffffff81008c22>] cpu_idle+0xaa/0xe4
 [<ffffffff81423a9a>] rest_init+0x7e/0x80
 [<ffffffff81b10dd2>] start_kernel+0x40e/0x419
 [<ffffffff81b102c8>] x86_64_start_reservations+0xb3/0xb7
 [<ffffffff81b103c4>] x86_64_start_kernel+0xf8/0x107
Code: 14 d5 40 ff ae 81 8b 14 02 31 c0 3b 15 47 1c 8b 00 7d 0e 48 8b 05 36 1c 8b
 00 48 63 d2 48 8b 04 d0 c7 85 5c ff ff ff 00 00 00 00 <8b> 70 38 48 8d 8d 5c ff
 ff ff 48 8b 78 10 ba c4 01 00 00 e8 eb
RIP  [<ffffffff8142f2fb>] cpuid4_cache_lookup_regs+0x2ca/0x3df
 RSP <ffff880002203e08>
CR2: 0000000000000038
---[ end trace a7919e7f17c0a726 ]---

The L3 cache index disable feature of AMD CPUs has to be disabled if the kernel is running as guest on top of a hypervisor because northbridge devices are not available to the guest. Currently, this fixes a boot crash on top of Xen. In the future this will become an issue on KVM as well.

Check if northbridge devices are present and do not enable the feature if there are none.

LKML-Reference: <[email protected]>

---
 arch/x86/kernel/cpu/intel_cacheinfo.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
arch/x86/kernel/cpu/intel_cacheinfo.c +4 -0
index acfb083..5ab14c8 100644
@@ -344,6 +344,10 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
 	     boot_cpu_data.x86_mask < 0x1)
 			return;
 
+	/* not in virtualized environments */
+	if (num_k8_northbridges == 0)
+		return;
+
 	this_leaf->can_disable = true;
 	this_leaf->l3_indices  = amd_calc_l3_indices();
 }
#5 lore raw

[tip:x86/urgent] x86, cacheinfo: Turn off L3 cache index disable feature in virtualized environments

In reply to Borislav Petkov
Commit-ID:  13ed79ffcd61dbdf797b0ab928c1738846ba5a97
Gitweb:     http://git.kernel.org/tip/13ed79ffcd61dbdf797b0ab928c1738846ba5a97
Author:     Frank Arnold <[email protected]>
AuthorDate: Thu, 22 Apr 2010 16:06:59 +0200
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Fri, 14 May 2010 11:46:03 -0700

x86, cacheinfo: Turn off L3 cache index disable feature in virtualized environments

When running a quest kernel on xen we get:

BUG: unable to handle kernel NULL pointer dereference at 0000000000000038
IP: [<ffffffff8142f2fb>] cpuid4_cache_lookup_regs+0x2ca/0x3df
PGD 0
Oops: 0000 [#1] SMP
last sysfs file:
CPU 0
Modules linked in:

Pid: 0, comm: swapper Tainted: G W 2.6.34-rc3 #1 /HVM domU

RIP: 0010:[<ffffffff8142f2fb>]  [<ffffffff8142f2fb>] cpuid4_cache_lookup_regs+0x
2ca/0x3df
RSP: 0018:ffff880002203e08  EFLAGS: 00010046
RAX: 0000000000000000 RBX: 0000000000000003 RCX: 0000000000000060
RDX: 0000000000000000 RSI: 0000000000000040 RDI: 0000000000000000
RBP: ffff880002203ed8 R08: 00000000000017c0 R09: ffff880002203e38
R10: ffff8800023d5d40 R11: ffffffff81a01e28 R12: ffff880187e6f5c0
R13: ffff880002203e34 R14: ffff880002203e58 R15: ffff880002203e68
FS:  0000000000000000(0000) GS:ffff880002200000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000038 CR3: 0000000001a3c000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process swapper (pid: 0, threadinfo ffffffff81a00000, task ffffffff81a44020)
Stack:
 ffffffff810d7ecb ffff880002203e20 ffffffff81059140 ffff880002203e30
<0> ffffffff810d7ec9 0000000002203e40 000000000050d140 ffff880002203e70
<0> 0000000002008140 0000000000000086 ffff880040020140 ffffffff81068b8b
Call Trace:
 <IRQ>
 [<ffffffff810d7ecb>] ? sync_supers_timer_fn+0x0/0x1c
 [<ffffffff81059140>] ? mod_timer+0x23/0x25
 [<ffffffff810d7ec9>] ? arm_supers_timer+0x34/0x36
 [<ffffffff81068b8b>] ? hrtimer_get_next_event+0xa7/0xc3
 [<ffffffff81058e85>] ? get_next_timer_interrupt+0x19a/0x20d
 [<ffffffff8142fa23>] get_cpu_leaves+0x5c/0x232
 [<ffffffff8106a7b1>] ? sched_clock_local+0x1c/0x82
 [<ffffffff8106a9a0>] ? sched_clock_tick+0x75/0x7a
 [<ffffffff8107748c>] generic_smp_call_function_single_interrupt+0xae/0xd0
 [<ffffffff8101f6ef>] smp_call_function_single_interrupt+0x18/0x27
 [<ffffffff8100a773>] call_function_single_interrupt+0x13/0x20
 <EOI>
 [<ffffffff8143c468>] ? notifier_call_chain+0x14/0x63
 [<ffffffff810295c6>] ? native_safe_halt+0xc/0xd
 [<ffffffff810114eb>] ? default_idle+0x36/0x53
 [<ffffffff81008c22>] cpu_idle+0xaa/0xe4
 [<ffffffff81423a9a>] rest_init+0x7e/0x80
 [<ffffffff81b10dd2>] start_kernel+0x40e/0x419
 [<ffffffff81b102c8>] x86_64_start_reservations+0xb3/0xb7
 [<ffffffff81b103c4>] x86_64_start_kernel+0xf8/0x107
Code: 14 d5 40 ff ae 81 8b 14 02 31 c0 3b 15 47 1c 8b 00 7d 0e 48 8b 05 36 1c 8b
 00 48 63 d2 48 8b 04 d0 c7 85 5c ff ff ff 00 00 00 00 <8b> 70 38 48 8d 8d 5c ff
 ff ff 48 8b 78 10 ba c4 01 00 00 e8 eb
RIP  [<ffffffff8142f2fb>] cpuid4_cache_lookup_regs+0x2ca/0x3df
 RSP <ffff880002203e08>
CR2: 0000000000000038
---[ end trace a7919e7f17c0a726 ]---

The L3 cache index disable feature of AMD CPUs has to be disabled if the kernel is running as guest on top of a hypervisor because northbridge devices are not available to the guest. Currently, this fixes a boot crash on top of Xen. In the future this will become an issue on KVM as well.

Check if northbridge devices are present and do not enable the feature if there are none.

[ hpa: backported to 2.6.34 ]

LKML-Reference: <[email protected]>

---
 arch/x86/kernel/cpu/intel_cacheinfo.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
arch/x86/kernel/cpu/intel_cacheinfo.c +4 -0
index b3eeb66..95962a9 100644
@@ -340,6 +340,10 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
 	     (boot_cpu_data.x86_mask  < 0x1)))
 		return;
 
+	/* not in virtualized environments */
+	if (num_k8_northbridges == 0)
+		return;
+
 	this_leaf->can_disable = true;
 	this_leaf->l3_indices  = amd_calc_l3_indices();
 }
#6 lore raw

[tip:x86/urgent] x86, cacheinfo: Turn off L3 cache index disable feature in virtualized environments

In reply to Borislav Petkov
Commit-ID:  7f284d3cc96e02468a42e045f77af11e5ff8b095
Gitweb:     http://git.kernel.org/tip/7f284d3cc96e02468a42e045f77af11e5ff8b095
Author:     Frank Arnold <[email protected]>
AuthorDate: Thu, 22 Apr 2010 16:06:59 +0200
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Fri, 14 May 2010 11:53:01 -0700

x86, cacheinfo: Turn off L3 cache index disable feature in virtualized environments

When running a quest kernel on xen we get:

BUG: unable to handle kernel NULL pointer dereference at 0000000000000038
IP: [<ffffffff8142f2fb>] cpuid4_cache_lookup_regs+0x2ca/0x3df
PGD 0
Oops: 0000 [#1] SMP
last sysfs file:
CPU 0
Modules linked in:

Pid: 0, comm: swapper Tainted: G W 2.6.34-rc3 #1 /HVM domU

RIP: 0010:[<ffffffff8142f2fb>]  [<ffffffff8142f2fb>] cpuid4_cache_lookup_regs+0x
2ca/0x3df
RSP: 0018:ffff880002203e08  EFLAGS: 00010046
RAX: 0000000000000000 RBX: 0000000000000003 RCX: 0000000000000060
RDX: 0000000000000000 RSI: 0000000000000040 RDI: 0000000000000000
RBP: ffff880002203ed8 R08: 00000000000017c0 R09: ffff880002203e38
R10: ffff8800023d5d40 R11: ffffffff81a01e28 R12: ffff880187e6f5c0
R13: ffff880002203e34 R14: ffff880002203e58 R15: ffff880002203e68
FS:  0000000000000000(0000) GS:ffff880002200000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000038 CR3: 0000000001a3c000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process swapper (pid: 0, threadinfo ffffffff81a00000, task ffffffff81a44020)
Stack:
 ffffffff810d7ecb ffff880002203e20 ffffffff81059140 ffff880002203e30
<0> ffffffff810d7ec9 0000000002203e40 000000000050d140 ffff880002203e70
<0> 0000000002008140 0000000000000086 ffff880040020140 ffffffff81068b8b
Call Trace:
 <IRQ>
 [<ffffffff810d7ecb>] ? sync_supers_timer_fn+0x0/0x1c
 [<ffffffff81059140>] ? mod_timer+0x23/0x25
 [<ffffffff810d7ec9>] ? arm_supers_timer+0x34/0x36
 [<ffffffff81068b8b>] ? hrtimer_get_next_event+0xa7/0xc3
 [<ffffffff81058e85>] ? get_next_timer_interrupt+0x19a/0x20d
 [<ffffffff8142fa23>] get_cpu_leaves+0x5c/0x232
 [<ffffffff8106a7b1>] ? sched_clock_local+0x1c/0x82
 [<ffffffff8106a9a0>] ? sched_clock_tick+0x75/0x7a
 [<ffffffff8107748c>] generic_smp_call_function_single_interrupt+0xae/0xd0
 [<ffffffff8101f6ef>] smp_call_function_single_interrupt+0x18/0x27
 [<ffffffff8100a773>] call_function_single_interrupt+0x13/0x20
 <EOI>
 [<ffffffff8143c468>] ? notifier_call_chain+0x14/0x63
 [<ffffffff810295c6>] ? native_safe_halt+0xc/0xd
 [<ffffffff810114eb>] ? default_idle+0x36/0x53
 [<ffffffff81008c22>] cpu_idle+0xaa/0xe4
 [<ffffffff81423a9a>] rest_init+0x7e/0x80
 [<ffffffff81b10dd2>] start_kernel+0x40e/0x419
 [<ffffffff81b102c8>] x86_64_start_reservations+0xb3/0xb7
 [<ffffffff81b103c4>] x86_64_start_kernel+0xf8/0x107
Code: 14 d5 40 ff ae 81 8b 14 02 31 c0 3b 15 47 1c 8b 00 7d 0e 48 8b 05 36 1c 8b
 00 48 63 d2 48 8b 04 d0 c7 85 5c ff ff ff 00 00 00 00 <8b> 70 38 48 8d 8d 5c ff
 ff ff 48 8b 78 10 ba c4 01 00 00 e8 eb
RIP  [<ffffffff8142f2fb>] cpuid4_cache_lookup_regs+0x2ca/0x3df
 RSP <ffff880002203e08>
CR2: 0000000000000038
---[ end trace a7919e7f17c0a726 ]---

The L3 cache index disable feature of AMD CPUs has to be disabled if the kernel is running as guest on top of a hypervisor because northbridge devices are not available to the guest. Currently, this fixes a boot crash on top of Xen. In the future this will become an issue on KVM as well.

Check if northbridge devices are present and do not enable the feature if there are none.

[ hpa: backported to 2.6.34 ]

LKML-Reference: <[email protected]>

---
 arch/x86/kernel/cpu/intel_cacheinfo.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
arch/x86/kernel/cpu/intel_cacheinfo.c +4 -0
index b3eeb66..95962a9 100644
@@ -340,6 +340,10 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
 	     (boot_cpu_data.x86_mask  < 0x1)))
 		return;
 
+	/* not in virtualized environments */
+	if (num_k8_northbridges == 0)
+		return;
+
 	this_leaf->can_disable = true;
 	this_leaf->l3_indices  = amd_calc_l3_indices();
 }
#7 lore raw

Re: [PATCH 2/5] x86, cacheinfo: Turn off L3 cache index disable feature in virtualized environments

In reply to Borislav Petkov

Hello Frank and Borislav,

Quoted 81 lines · Borislav Petkov

From: Frank Arnold <[email protected]>

When running a quest kernel on xen we get:

BUG: unable to handle kernel NULL pointer dereference at 0000000000000038
IP: [<ffffffff8142f2fb>] cpuid4_cache_lookup_regs+0x2ca/0x3df
PGD 0
Oops: 0000 [#1] SMP
last sysfs file:
CPU 0
Modules linked in:

Pid: 0, comm: swapper Tainted: G        W  2.6.34-rc3 #1 /HVM domU

RIP: 0010:[<ffffffff8142f2fb>]  [<ffffffff8142f2fb>] cpuid4_cache_lookup_regs+0x

2ca/0x3df
RSP: 0018:ffff880002203e08  EFLAGS: 00010046
RAX: 0000000000000000 RBX: 0000000000000003 RCX: 0000000000000060
RDX: 0000000000000000 RSI: 0000000000000040 RDI: 0000000000000000
RBP: ffff880002203ed8 R08: 00000000000017c0 R09: ffff880002203e38
R10: ffff8800023d5d40 R11: ffffffff81a01e28 R12: ffff880187e6f5c0
R13: ffff880002203e34 R14: ffff880002203e58 R15: ffff880002203e68
FS:  0000000000000000(0000) GS:ffff880002200000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000038 CR3: 0000000001a3c000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process swapper (pid: 0, threadinfo ffffffff81a00000, task ffffffff81a44020)

Stack:
 ffffffff810d7ecb ffff880002203e20 ffffffff81059140 ffff880002203e30
<0> ffffffff810d7ec9 0000000002203e40 000000000050d140 ffff880002203e70
<0> 0000000002008140 0000000000000086 ffff880040020140 ffffffff81068b8b
Call Trace:
 <IRQ>
 [<ffffffff810d7ecb>] ? sync_supers_timer_fn+0x0/0x1c
 [<ffffffff81059140>] ? mod_timer+0x23/0x25
 [<ffffffff810d7ec9>] ? arm_supers_timer+0x34/0x36
 [<ffffffff81068b8b>] ? hrtimer_get_next_event+0xa7/0xc3
 [<ffffffff81058e85>] ? get_next_timer_interrupt+0x19a/0x20d
 [<ffffffff8142fa23>] get_cpu_leaves+0x5c/0x232
 [<ffffffff8106a7b1>] ? sched_clock_local+0x1c/0x82
 [<ffffffff8106a9a0>] ? sched_clock_tick+0x75/0x7a
 [<ffffffff8107748c>] generic_smp_call_function_single_interrupt+0xae/0xd0
 [<ffffffff8101f6ef>] smp_call_function_single_interrupt+0x18/0x27
 [<ffffffff8100a773>] call_function_single_interrupt+0x13/0x20

 <EOI>
 [<ffffffff8143c468>] ? notifier_call_chain+0x14/0x63 [<ffffffff810295c6>] ? native_safe_halt+0xc/0xd [<ffffffff810114eb>] ? default_idle+0x36/0x53

 [<ffffffff81008c22>] cpu_idle+0xaa/0xe4
 [<ffffffff81423a9a>] rest_init+0x7e/0x80
 [<ffffffff81b10dd2>] start_kernel+0x40e/0x419
 [<ffffffff81b102c8>] x86_64_start_reservations+0xb3/0xb7
 [<ffffffff81b103c4>] x86_64_start_kernel+0xf8/0x107
Code: 14 d5 40 ff ae 81 8b 14 02 31 c0 3b 15 47 1c 8b 00 7d 0e 48 8b 05 36 1c 8b

 00 48 63 d2 48 8b 04 d0 c7 85 5c ff ff ff 00 00 00 00 <8b> 70 38 48 8d 8d 5c ff ff ff 48 8b 78 10 ba c4 01 00 00 e8 eb
RIP  [<ffffffff8142f2fb>] cpuid4_cache_lookup_regs+0x2ca/0x3df
 RSP <ffff880002203e08>
CR2: 0000000000000038

---[ end trace a7919e7f17c0a726 ]---

The L3 cache index disable feature of AMD CPUs has to be disabled if the kernel is running as guest on top of a hypervisor because northbridge devices are not available to the guest. Currently, this fixes a boot crash on top of Xen. In the future this will become an issue on KVM as well.

Check if northbridge devices are present and do not enable the feature if there are none.

---
 arch/x86/kernel/cpu/intel_cacheinfo.c |    4 ++++

 1 files changed, 4 insertions(+), 0 deletions(-)
arch/x86/kernel/cpu/intel_cacheinfo.c +0 -0
index acfb083..5ab14c8 100644

arch/x86/kernel/cpu/intel_cacheinfo.c amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) · line 353

Quoted 10 lines
arch/x86/kernel/cpu/intel_cacheinfo.c +4 -0
@@ -344,6 +344,10 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
             boot_cpu_data.x86_mask < 0x1)
                        return;
 
+       /* not in virtualized environments */
+       if (num_k8_northbridges == 0)
+               return;
+
        this_leaf->can_disable = true;
        this_leaf->l3_indices  = amd_calc_l3_indices();
  }

I think :

1. checking num_k8_northbridges is not sufficient as node_to_k8_nb_misc() of amd_calc_l3_indices() is almost doing the same thing.

2. num_k8_northbridges is CONFIG_K8_NB specific

Can you try this :

If you return from amd_calc_l3_indices() if dev == NULL.

Thanks,
--
Jaswinder Singh.

#8 lore raw

Re: [PATCH 2/5] x86, cacheinfo: Turn off L3 cache index disable feature in virtualized environments

Hello Frank and Borislav,

Quoted 101 lines · Jaswinder Singh Rajput

Hello Frank and Borislav,

Quoted 81 lines · Borislav Petkov

From: Frank Arnold <[email protected]>

When running a quest kernel on xen we get:

BUG: unable to handle kernel NULL pointer dereference at 0000000000000038
IP: [<ffffffff8142f2fb>] cpuid4_cache_lookup_regs+0x2ca/0x3df
PGD 0
Oops: 0000 [#1] SMP
last sysfs file:
CPU 0
Modules linked in:

Pid: 0, comm: swapper Tainted: G        W  2.6.34-rc3 #1 /HVM domU

RIP: 0010:[<ffffffff8142f2fb>]  [<ffffffff8142f2fb>] cpuid4_cache_lookup_regs+0x

2ca/0x3df
RSP: 0018:ffff880002203e08  EFLAGS: 00010046
RAX: 0000000000000000 RBX: 0000000000000003 RCX: 0000000000000060
RDX: 0000000000000000 RSI: 0000000000000040 RDI: 0000000000000000
RBP: ffff880002203ed8 R08: 00000000000017c0 R09: ffff880002203e38
R10: ffff8800023d5d40 R11: ffffffff81a01e28 R12: ffff880187e6f5c0
R13: ffff880002203e34 R14: ffff880002203e58 R15: ffff880002203e68
FS:  0000000000000000(0000) GS:ffff880002200000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000038 CR3: 0000000001a3c000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process swapper (pid: 0, threadinfo ffffffff81a00000, task ffffffff81a44020)

Stack:
 ffffffff810d7ecb ffff880002203e20 ffffffff81059140 ffff880002203e30
<0> ffffffff810d7ec9 0000000002203e40 000000000050d140 ffff880002203e70
<0> 0000000002008140 0000000000000086 ffff880040020140 ffffffff81068b8b
Call Trace:
 <IRQ>
 [<ffffffff810d7ecb>] ? sync_supers_timer_fn+0x0/0x1c
 [<ffffffff81059140>] ? mod_timer+0x23/0x25
 [<ffffffff810d7ec9>] ? arm_supers_timer+0x34/0x36
 [<ffffffff81068b8b>] ? hrtimer_get_next_event+0xa7/0xc3
 [<ffffffff81058e85>] ? get_next_timer_interrupt+0x19a/0x20d
 [<ffffffff8142fa23>] get_cpu_leaves+0x5c/0x232
 [<ffffffff8106a7b1>] ? sched_clock_local+0x1c/0x82
 [<ffffffff8106a9a0>] ? sched_clock_tick+0x75/0x7a
 [<ffffffff8107748c>] generic_smp_call_function_single_interrupt+0xae/0xd0
 [<ffffffff8101f6ef>] smp_call_function_single_interrupt+0x18/0x27
 [<ffffffff8100a773>] call_function_single_interrupt+0x13/0x20

 <EOI>
 [<ffffffff8143c468>] ? notifier_call_chain+0x14/0x63 [<ffffffff810295c6>] ? native_safe_halt+0xc/0xd [<ffffffff810114eb>] ? default_idle+0x36/0x53

 [<ffffffff81008c22>] cpu_idle+0xaa/0xe4
 [<ffffffff81423a9a>] rest_init+0x7e/0x80
 [<ffffffff81b10dd2>] start_kernel+0x40e/0x419
 [<ffffffff81b102c8>] x86_64_start_reservations+0xb3/0xb7
 [<ffffffff81b103c4>] x86_64_start_kernel+0xf8/0x107
Code: 14 d5 40 ff ae 81 8b 14 02 31 c0 3b 15 47 1c 8b 00 7d 0e 48 8b 05 36 1c 8b

 00 48 63 d2 48 8b 04 d0 c7 85 5c ff ff ff 00 00 00 00 <8b> 70 38 48 8d 8d 5c ff ff ff 48 8b 78 10 ba c4 01 00 00 e8 eb
RIP  [<ffffffff8142f2fb>] cpuid4_cache_lookup_regs+0x2ca/0x3df
 RSP <ffff880002203e08>
CR2: 0000000000000038

---[ end trace a7919e7f17c0a726 ]---

The L3 cache index disable feature of AMD CPUs has to be disabled if the kernel is running as guest on top of a hypervisor because northbridge devices are not available to the guest. Currently, this fixes a boot crash on top of Xen. In the future this will become an issue on KVM as well.

Check if northbridge devices are present and do not enable the feature if there are none.

---
 arch/x86/kernel/cpu/intel_cacheinfo.c |    4 ++++

 1 files changed, 4 insertions(+), 0 deletions(-)
arch/x86/kernel/cpu/intel_cacheinfo.c +0 -0
index acfb083..5ab14c8 100644

arch/x86/kernel/cpu/intel_cacheinfo.c amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) · line 353

Quoted 10 lines
arch/x86/kernel/cpu/intel_cacheinfo.c +4 -0
@@ -344,6 +344,10 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
             boot_cpu_data.x86_mask < 0x1)
                        return;
 
+       /* not in virtualized environments */
+       if (num_k8_northbridges == 0)
+               return;
+
        this_leaf->can_disable = true;
        this_leaf->l3_indices  = amd_calc_l3_indices();
  }

I think :

1. checking num_k8_northbridges is not sufficient as node_to_k8_nb_misc() of amd_calc_l3_indices() is almost doing the same thing.

Quoted 6 lines

2. num_k8_northbridges is CONFIG_K8_NB specific

Can you try this :

If you return from amd_calc_l3_indices() if dev == NULL.

In the amd_calc_l3_indices(), we are using dev without testing for NULL, it seems like a BUG to me.

In amd_check_l3_disable(), we are doing following checks :

1. boot_cpu_data.x86 == 0x11
2. errata #382 and #388
3. num_k8_northbridges == 0

I am wondering do we really need all three checking or it is the workaround of the amd_calc_l3_indices() BUG.

Unfortunately, I do not have access to hardware to test the changes. Do you mind testing this where I remove all the 3 checking conditions, can you also test individual case if this does not work.

Thanks.

(quoted diff) +0 -0

b/arch/x86/kernel/cpu/intel_cacheinfo.c
index 95962a9..514692c 100644

arch/x86/kernel/cpu/intel_cacheinfo.c +11 -15
@@ -302,17 +302,20 @@ struct _cache_attr {
 };
 
 #ifdef CONFIG_CPU_SUP_AMD
-static unsigned int __cpuinit amd_calc_l3_indices(void)
+static int __cpuinit amd_calc_l3_indices(void)
 {
        /*
         * We're called over smp_call_function_single() and therefore
         * are on the correct cpu.
         */
+       unsigned int sc0, sc1, sc2, sc3;
+       u32 val = 0;
        int cpu = smp_processor_id();
        int node = cpu_to_node(cpu);
        struct pci_dev *dev = node_to_k8_nb_misc(node);
-       unsigned int sc0, sc1, sc2, sc3;
-       u32 val = 0;
+
+       if (!dev)
+               return -1;
 
        pci_read_config_dword(dev, 0x1C4, &val);
 
@@ -328,24 +331,17 @@ static unsigned int __cpuinit amd_calc_l3_indices(void)
 static void __cpuinit
 amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
 {
-       if (index < 3)
-               return;
+       int indices;
 
-       if (boot_cpu_data.x86 == 0x11)
-               return;
-
-       /* see errata #382 and #388 */
-       if ((boot_cpu_data.x86 == 0x10) &&
-           ((boot_cpu_data.x86_model < 0x8) ||
-            (boot_cpu_data.x86_mask  < 0x1)))
+       if (index < 3)
                return;
 
-       /* not in virtualized environments */
-       if (num_k8_northbridges == 0)
+       indices = amd_calc_l3_indices();
+       if (indices < 0)
                return;
 
        this_leaf->can_disable = true;
-       this_leaf->l3_indices  = amd_calc_l3_indices();
+       this_leaf->l3_indices  = indices;
 }
 
 static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
arch/x86/kernel/cpu/intel_cacheinfo.c +11 -15
index 95962a9..514692c 100644
@@ -302,17 +302,20 @@ struct _cache_attr {
 };
 
 #ifdef CONFIG_CPU_SUP_AMD
-static unsigned int __cpuinit amd_calc_l3_indices(void)
+static int __cpuinit amd_calc_l3_indices(void)
 {
 	/*
 	 * We're called over smp_call_function_single() and therefore
 	 * are on the correct cpu.
 	 */
+	unsigned int sc0, sc1, sc2, sc3;
+	u32 val = 0;
 	int cpu = smp_processor_id();
 	int node = cpu_to_node(cpu);
 	struct pci_dev *dev = node_to_k8_nb_misc(node);
-	unsigned int sc0, sc1, sc2, sc3;
-	u32 val = 0;
+
+	if (!dev)
+		return -1;
 
 	pci_read_config_dword(dev, 0x1C4, &val);
 
@@ -328,24 +331,17 @@ static unsigned int __cpuinit amd_calc_l3_indices(void)
 static void __cpuinit
 amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
 {
-	if (index < 3)
-		return;
+	int indices;
 
-	if (boot_cpu_data.x86 == 0x11)
-		return;
-
-	/* see errata #382 and #388 */
-	if ((boot_cpu_data.x86 == 0x10) &&
-	    ((boot_cpu_data.x86_model < 0x8) ||
-	     (boot_cpu_data.x86_mask  < 0x1)))
+	if (index < 3)
 		return;
 
-	/* not in virtualized environments */
-	if (num_k8_northbridges == 0)
+	indices = amd_calc_l3_indices();
+	if (indices < 0)
 		return;
 
 	this_leaf->can_disable = true;
-	this_leaf->l3_indices  = amd_calc_l3_indices();
+	this_leaf->l3_indices  = indices;
 }
 
 static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
#9 lore raw

PATCH 3/5 x86, cacheinfo: Reorganize AMD L3 cache structure

In reply to Borislav Petkov

From: Borislav Petkov <[email protected]>

Add a struct representing L3 cache attributes (subcache sizes and indices count) and move the respective members out of _cpuid4_info. Also, stash the struct pci_dev ptr into the struct simplifying the code even more.

There should be no functionality change resulting from this patch except slightly slimming the _cpuid4_info per-cpu vars.

---
 arch/x86/kernel/cpu/intel_cacheinfo.c |   53 ++++++++++++++++++++-------------
 1 files changed, 32 insertions(+), 21 deletions(-)
arch/x86/kernel/cpu/intel_cacheinfo.c +32 -21
index 5ab14c8..ff663ca 100644
@@ -148,13 +148,19 @@ union _cpuid4_leaf_ecx {
 	u32 full;
 };
 
+struct amd_l3_cache {
+	struct	 pci_dev *dev;
+	bool	 can_disable;
+	unsigned indices;
+	u8	 subcaches[4];
+};
+
 struct _cpuid4_info {
 	union _cpuid4_leaf_eax eax;
 	union _cpuid4_leaf_ebx ebx;
 	union _cpuid4_leaf_ecx ecx;
 	unsigned long size;
-	bool can_disable;
-	unsigned int l3_indices;
+	struct amd_l3_cache *l3;
 	DECLARE_BITMAP(shared_cpu_map, NR_CPUS);
 };
 
@@ -164,8 +170,7 @@ struct _cpuid4_info_regs {
 	union _cpuid4_leaf_ebx ebx;
 	union _cpuid4_leaf_ecx ecx;
 	unsigned long size;
-	bool can_disable;
-	unsigned int l3_indices;
+	struct amd_l3_cache *l3;
 };
 
 unsigned short			num_cache_leaves;
@@ -302,7 +307,7 @@ struct _cache_attr {
 };
 
 #ifdef CONFIG_CPU_SUP_AMD
-static unsigned int __cpuinit amd_calc_l3_indices(void)
+static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3)
 {
 	/*
 	 * We're called over smp_call_function_single() and therefore
@@ -317,12 +322,14 @@ static unsigned int __cpuinit amd_calc_l3_indices(void)
 	pci_read_config_dword(dev, 0x1C4, &val);
 
 	/* calculate subcache sizes */
-	sc0 = !(val & BIT(0));
-	sc1 = !(val & BIT(4));
-	sc2 = !(val & BIT(8))  + !(val & BIT(9));
-	sc3 = !(val & BIT(12)) + !(val & BIT(13));
+	l3->subcaches[0] = sc0 = !(val & BIT(0));
+	l3->subcaches[1] = sc1 = !(val & BIT(4));
+	l3->subcaches[2] = sc2 = !(val & BIT(8))  + !(val & BIT(9));
+	l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13));
+
+	l3->indices = (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1;
 
-	return (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1;
+	l3->dev = dev;
 }
 
 static void __cpuinit
@@ -348,19 +355,23 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
 	if (num_k8_northbridges == 0)
 		return;
 
-	this_leaf->can_disable = true;
-	this_leaf->l3_indices  = amd_calc_l3_indices();
+	this_leaf->l3 = kzalloc(sizeof(struct amd_l3_cache), GFP_ATOMIC);
+	if (!this_leaf->l3) {
+		printk(KERN_WARNING "Error allocating L3 struct\n");
+		return;
+	}
+
+	this_leaf->l3->can_disable = true;
+	amd_calc_l3_indices(this_leaf->l3);
 }
 
 static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
 				  unsigned int index)
 {
-	int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
-	int node = amd_get_nb_id(cpu);
-	struct pci_dev *dev = node_to_k8_nb_misc(node);
+	struct pci_dev *dev = this_leaf->l3->dev;
 	unsigned int reg = 0;
 
-	if (!this_leaf->can_disable)
+	if (!this_leaf->l3 || !this_leaf->l3->can_disable)
 		return -EINVAL;
 
 	if (!dev)
@@ -382,15 +393,14 @@ SHOW_CACHE_DISABLE(1)
 static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
 	const char *buf, size_t count, unsigned int index)
 {
+	struct pci_dev *dev = this_leaf->l3->dev;
 	int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
-	int node = amd_get_nb_id(cpu);
-	struct pci_dev *dev = node_to_k8_nb_misc(node);
 	unsigned long val = 0;
 
 #define SUBCACHE_MASK	(3UL << 20)
 #define SUBCACHE_INDEX	0xfff
 
-	if (!this_leaf->can_disable)
+	if (!this_leaf->l3 || !this_leaf->l3->can_disable)
 		return -EINVAL;
 
 	if (!capable(CAP_SYS_ADMIN))
@@ -404,7 +414,7 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
 
 	/* do not allow writes outside of allowed bits */
 	if ((val & ~(SUBCACHE_MASK | SUBCACHE_INDEX)) ||
-	    ((val & SUBCACHE_INDEX) > this_leaf->l3_indices))
+	    ((val & SUBCACHE_INDEX) > this_leaf->l3->indices))
 		return -EINVAL;
 
 	val |= BIT(30);
@@ -708,6 +718,7 @@ static void __cpuinit free_cache_attributes(unsigned int cpu)
 	for (i = 0; i < num_cache_leaves; i++)
 		cache_remove_shared_cpu_map(cpu, i);
 
+	kfree(per_cpu(ici_cpuid4_info, cpu)->l3);
 	kfree(per_cpu(ici_cpuid4_info, cpu));
 	per_cpu(ici_cpuid4_info, cpu) = NULL;
 }
@@ -992,7 +1003,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
 
 		this_leaf = CPUID4_INFO_IDX(cpu, i);
 
-		if (this_leaf->can_disable)
+		if (this_leaf->l3 && this_leaf->l3->can_disable)
 			ktype_cache.default_attrs = default_l3_attrs;
 		else
 			ktype_cache.default_attrs = default_attrs;
Signature · 1 line
1.7.1.rc1
#10 lore raw

[tip:x86/cpu] x86, cacheinfo: Reorganize AMD L3 cache structure

Commit-ID:  9350f982e4fe539e83a2d4a13e9b53ad8253c4a8
Gitweb:     http://git.kernel.org/tip/9350f982e4fe539e83a2d4a13e9b53ad8253c4a8
Author:     Borislav Petkov <[email protected]>
AuthorDate: Thu, 22 Apr 2010 16:07:00 +0200
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Thu, 22 Apr 2010 17:17:23 -0700

x86, cacheinfo: Reorganize AMD L3 cache structure

Add a struct representing L3 cache attributes (subcache sizes and indices count) and move the respective members out of _cpuid4_info. Also, stash the struct pci_dev ptr into the struct simplifying the code even more.

There should be no functionality change resulting from this patch except slightly slimming the _cpuid4_info per-cpu vars.

LKML-Reference: <[email protected]>

---
 arch/x86/kernel/cpu/intel_cacheinfo.c |   53 ++++++++++++++++++++-------------
 1 files changed, 32 insertions(+), 21 deletions(-)
arch/x86/kernel/cpu/intel_cacheinfo.c +32 -21
index 5ab14c8..ff663ca 100644
@@ -148,13 +148,19 @@ union _cpuid4_leaf_ecx {
 	u32 full;
 };
 
+struct amd_l3_cache {
+	struct	 pci_dev *dev;
+	bool	 can_disable;
+	unsigned indices;
+	u8	 subcaches[4];
+};
+
 struct _cpuid4_info {
 	union _cpuid4_leaf_eax eax;
 	union _cpuid4_leaf_ebx ebx;
 	union _cpuid4_leaf_ecx ecx;
 	unsigned long size;
-	bool can_disable;
-	unsigned int l3_indices;
+	struct amd_l3_cache *l3;
 	DECLARE_BITMAP(shared_cpu_map, NR_CPUS);
 };
 
@@ -164,8 +170,7 @@ struct _cpuid4_info_regs {
 	union _cpuid4_leaf_ebx ebx;
 	union _cpuid4_leaf_ecx ecx;
 	unsigned long size;
-	bool can_disable;
-	unsigned int l3_indices;
+	struct amd_l3_cache *l3;
 };
 
 unsigned short			num_cache_leaves;
@@ -302,7 +307,7 @@ struct _cache_attr {
 };
 
 #ifdef CONFIG_CPU_SUP_AMD
-static unsigned int __cpuinit amd_calc_l3_indices(void)
+static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3)
 {
 	/*
 	 * We're called over smp_call_function_single() and therefore
@@ -317,12 +322,14 @@ static unsigned int __cpuinit amd_calc_l3_indices(void)
 	pci_read_config_dword(dev, 0x1C4, &val);
 
 	/* calculate subcache sizes */
-	sc0 = !(val & BIT(0));
-	sc1 = !(val & BIT(4));
-	sc2 = !(val & BIT(8))  + !(val & BIT(9));
-	sc3 = !(val & BIT(12)) + !(val & BIT(13));
+	l3->subcaches[0] = sc0 = !(val & BIT(0));
+	l3->subcaches[1] = sc1 = !(val & BIT(4));
+	l3->subcaches[2] = sc2 = !(val & BIT(8))  + !(val & BIT(9));
+	l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13));
+
+	l3->indices = (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1;
 
-	return (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1;
+	l3->dev = dev;
 }
 
 static void __cpuinit
@@ -348,19 +355,23 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
 	if (num_k8_northbridges == 0)
 		return;
 
-	this_leaf->can_disable = true;
-	this_leaf->l3_indices  = amd_calc_l3_indices();
+	this_leaf->l3 = kzalloc(sizeof(struct amd_l3_cache), GFP_ATOMIC);
+	if (!this_leaf->l3) {
+		printk(KERN_WARNING "Error allocating L3 struct\n");
+		return;
+	}
+
+	this_leaf->l3->can_disable = true;
+	amd_calc_l3_indices(this_leaf->l3);
 }
 
 static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
 				  unsigned int index)
 {
-	int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
-	int node = amd_get_nb_id(cpu);
-	struct pci_dev *dev = node_to_k8_nb_misc(node);
+	struct pci_dev *dev = this_leaf->l3->dev;
 	unsigned int reg = 0;
 
-	if (!this_leaf->can_disable)
+	if (!this_leaf->l3 || !this_leaf->l3->can_disable)
 		return -EINVAL;
 
 	if (!dev)
@@ -382,15 +393,14 @@ SHOW_CACHE_DISABLE(1)
 static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
 	const char *buf, size_t count, unsigned int index)
 {
+	struct pci_dev *dev = this_leaf->l3->dev;
 	int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
-	int node = amd_get_nb_id(cpu);
-	struct pci_dev *dev = node_to_k8_nb_misc(node);
 	unsigned long val = 0;
 
 #define SUBCACHE_MASK	(3UL << 20)
 #define SUBCACHE_INDEX	0xfff
 
-	if (!this_leaf->can_disable)
+	if (!this_leaf->l3 || !this_leaf->l3->can_disable)
 		return -EINVAL;
 
 	if (!capable(CAP_SYS_ADMIN))
@@ -404,7 +414,7 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
 
 	/* do not allow writes outside of allowed bits */
 	if ((val & ~(SUBCACHE_MASK | SUBCACHE_INDEX)) ||
-	    ((val & SUBCACHE_INDEX) > this_leaf->l3_indices))
+	    ((val & SUBCACHE_INDEX) > this_leaf->l3->indices))
 		return -EINVAL;
 
 	val |= BIT(30);
@@ -708,6 +718,7 @@ static void __cpuinit free_cache_attributes(unsigned int cpu)
 	for (i = 0; i < num_cache_leaves; i++)
 		cache_remove_shared_cpu_map(cpu, i);
 
+	kfree(per_cpu(ici_cpuid4_info, cpu)->l3);
 	kfree(per_cpu(ici_cpuid4_info, cpu));
 	per_cpu(ici_cpuid4_info, cpu) = NULL;
 }
@@ -992,7 +1003,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
 
 		this_leaf = CPUID4_INFO_IDX(cpu, i);
 
-		if (this_leaf->can_disable)
+		if (this_leaf->l3 && this_leaf->l3->can_disable)
 			ktype_cache.default_attrs = default_l3_attrs;
 		else
 			ktype_cache.default_attrs = default_attrs;
#11 lore raw

PATCH 4/5 x86, cacheinfo: Make L3 cache info per node

In reply to Borislav Petkov

From: Borislav Petkov <[email protected]>

Currently, we're allocating L3 cache info and calculating indices for each online cpu which is clearly superfluous. Instead, we need to do this per-node as is each L3 cache.

No functional change, only per-cpu memory savings.

-v2: Allocate L3 cache descriptors array dynamically.

---
 arch/x86/kernel/cpu/intel_cacheinfo.c |   59 +++++++++++++++++++++++++--------
 1 files changed, 45 insertions(+), 14 deletions(-)
arch/x86/kernel/cpu/intel_cacheinfo.c +45 -14
index ff663ca..1346e9c 100644
@@ -307,19 +307,18 @@ struct _cache_attr {
 };
 
 #ifdef CONFIG_CPU_SUP_AMD
+
+/*
+ * L3 cache descriptors
+ */
+static struct amd_l3_cache **__cpuinitdata l3_caches;
+
 static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3)
 {
-	/*
-	 * We're called over smp_call_function_single() and therefore
-	 * are on the correct cpu.
-	 */
-	int cpu = smp_processor_id();
-	int node = cpu_to_node(cpu);
-	struct pci_dev *dev = node_to_k8_nb_misc(node);
 	unsigned int sc0, sc1, sc2, sc3;
 	u32 val = 0;
 
-	pci_read_config_dword(dev, 0x1C4, &val);
+	pci_read_config_dword(l3->dev, 0x1C4, &val);
 
 	/* calculate subcache sizes */
 	l3->subcaches[0] = sc0 = !(val & BIT(0));
@@ -328,13 +327,31 @@ static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3)
 	l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13));
 
 	l3->indices = (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1;
+}
+
+static struct amd_l3_cache * __cpuinit amd_init_l3_cache(int node)
+{
+	struct amd_l3_cache *l3;
+	struct pci_dev *dev = node_to_k8_nb_misc(node);
+
+	l3 = kzalloc(sizeof(struct amd_l3_cache), GFP_ATOMIC);
+	if (!l3) {
+		printk(KERN_WARNING "Error allocating L3 struct\n");
+		return NULL;
+	}
 
 	l3->dev = dev;
+
+	amd_calc_l3_indices(l3);
+
+	return l3;
 }
 
 static void __cpuinit
 amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
 {
+	int node;
+
 	if (boot_cpu_data.x86 != 0x10)
 		return;
 
@@ -355,14 +372,28 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
 	if (num_k8_northbridges == 0)
 		return;
 
-	this_leaf->l3 = kzalloc(sizeof(struct amd_l3_cache), GFP_ATOMIC);
-	if (!this_leaf->l3) {
-		printk(KERN_WARNING "Error allocating L3 struct\n");
-		return;
+	/*
+	 * Strictly speaking, the amount in @size below is leaked since it is
+	 * never freed but this is done only on shutdown so it doesn't matter.
+	 */
+	if (!l3_caches) {
+		int size = num_k8_northbridges * sizeof(struct amd_l3_cache *);
+
+		l3_caches = kzalloc(size, GFP_ATOMIC);
+		if (!l3_caches)
+			return;
 	}
 
-	this_leaf->l3->can_disable = true;
-	amd_calc_l3_indices(this_leaf->l3);
+	node = amd_get_nb_id(smp_processor_id());
+
+	if (!l3_caches[node]) {
+		l3_caches[node] = amd_init_l3_cache(node);
+		l3_caches[node]->can_disable = true;
+	}
+
+	WARN_ON(!l3_caches[node]);
+
+	this_leaf->l3 = l3_caches[node];
 }
 
 static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
Signature · 1 line
1.7.1.rc1
#12 lore raw

[tip:x86/cpu] x86, cacheinfo: Make L3 cache info per node

Commit-ID:  ba06edb63f5ef2913aad37070eaec3c9d8ac73b8
Gitweb:     http://git.kernel.org/tip/ba06edb63f5ef2913aad37070eaec3c9d8ac73b8
Author:     Borislav Petkov <[email protected]>
AuthorDate: Thu, 22 Apr 2010 16:07:01 +0200
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Thu, 22 Apr 2010 17:17:23 -0700

x86, cacheinfo: Make L3 cache info per node

Currently, we're allocating L3 cache info and calculating indices for each online cpu which is clearly superfluous. Instead, we need to do this per-node as is each L3 cache.

No functional change, only per-cpu memory savings.

-v2: Allocate L3 cache descriptors array dynamically.

LKML-Reference: <[email protected]>

---
 arch/x86/kernel/cpu/intel_cacheinfo.c |   59 +++++++++++++++++++++++++--------
 1 files changed, 45 insertions(+), 14 deletions(-)
arch/x86/kernel/cpu/intel_cacheinfo.c +45 -14
index ff663ca..1346e9c 100644
@@ -307,19 +307,18 @@ struct _cache_attr {
 };
 
 #ifdef CONFIG_CPU_SUP_AMD
+
+/*
+ * L3 cache descriptors
+ */
+static struct amd_l3_cache **__cpuinitdata l3_caches;
+
 static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3)
 {
-	/*
-	 * We're called over smp_call_function_single() and therefore
-	 * are on the correct cpu.
-	 */
-	int cpu = smp_processor_id();
-	int node = cpu_to_node(cpu);
-	struct pci_dev *dev = node_to_k8_nb_misc(node);
 	unsigned int sc0, sc1, sc2, sc3;
 	u32 val = 0;
 
-	pci_read_config_dword(dev, 0x1C4, &val);
+	pci_read_config_dword(l3->dev, 0x1C4, &val);
 
 	/* calculate subcache sizes */
 	l3->subcaches[0] = sc0 = !(val & BIT(0));
@@ -328,13 +327,31 @@ static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3)
 	l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13));
 
 	l3->indices = (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1;
+}
+
+static struct amd_l3_cache * __cpuinit amd_init_l3_cache(int node)
+{
+	struct amd_l3_cache *l3;
+	struct pci_dev *dev = node_to_k8_nb_misc(node);
+
+	l3 = kzalloc(sizeof(struct amd_l3_cache), GFP_ATOMIC);
+	if (!l3) {
+		printk(KERN_WARNING "Error allocating L3 struct\n");
+		return NULL;
+	}
 
 	l3->dev = dev;
+
+	amd_calc_l3_indices(l3);
+
+	return l3;
 }
 
 static void __cpuinit
 amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
 {
+	int node;
+
 	if (boot_cpu_data.x86 != 0x10)
 		return;
 
@@ -355,14 +372,28 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
 	if (num_k8_northbridges == 0)
 		return;
 
-	this_leaf->l3 = kzalloc(sizeof(struct amd_l3_cache), GFP_ATOMIC);
-	if (!this_leaf->l3) {
-		printk(KERN_WARNING "Error allocating L3 struct\n");
-		return;
+	/*
+	 * Strictly speaking, the amount in @size below is leaked since it is
+	 * never freed but this is done only on shutdown so it doesn't matter.
+	 */
+	if (!l3_caches) {
+		int size = num_k8_northbridges * sizeof(struct amd_l3_cache *);
+
+		l3_caches = kzalloc(size, GFP_ATOMIC);
+		if (!l3_caches)
+			return;
 	}
 
-	this_leaf->l3->can_disable = true;
-	amd_calc_l3_indices(this_leaf->l3);
+	node = amd_get_nb_id(smp_processor_id());
+
+	if (!l3_caches[node]) {
+		l3_caches[node] = amd_init_l3_cache(node);
+		l3_caches[node]->can_disable = true;
+	}
+
+	WARN_ON(!l3_caches[node]);
+
+	this_leaf->l3 = l3_caches[node];
 }
 
 static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
#13 lore raw

PATCH 5/5 x86, cacheinfo: Disable index in all four subcaches

In reply to Borislav Petkov

From: Borislav Petkov <[email protected]>

When disabling an L3 cache index, make sure we disable that index in all four subcaches of the L3. Clarify nomenclature while at it, wrt to disable slots versus disable index and rename accordingly.

---
 arch/x86/kernel/cpu/intel_cacheinfo.c |   60 +++++++++++++++++++++++---------
 1 files changed, 43 insertions(+), 17 deletions(-)
arch/x86/kernel/cpu/intel_cacheinfo.c +43 -17
index 1346e9c..33eae20 100644
@@ -397,7 +397,7 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
 }
 
 static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
-				  unsigned int index)
+				  unsigned int slot)
 {
 	struct pci_dev *dev = this_leaf->l3->dev;
 	unsigned int reg = 0;
@@ -408,21 +408,53 @@ static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
 	if (!dev)
 		return -EINVAL;
 
-	pci_read_config_dword(dev, 0x1BC + index * 4, &reg);
+	pci_read_config_dword(dev, 0x1BC + slot * 4, &reg);
 	return sprintf(buf, "0x%08x\n", reg);
 }
 
-#define SHOW_CACHE_DISABLE(index)					\
+#define SHOW_CACHE_DISABLE(slot)					\
 static ssize_t								\
-show_cache_disable_##index(struct _cpuid4_info *this_leaf, char *buf)	\
+show_cache_disable_##slot(struct _cpuid4_info *this_leaf, char *buf)	\
 {									\
-	return show_cache_disable(this_leaf, buf, index);		\
+	return show_cache_disable(this_leaf, buf, slot);		\
 }
 SHOW_CACHE_DISABLE(0)
 SHOW_CACHE_DISABLE(1)
 
+static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu,
+				 unsigned slot, unsigned long idx)
+{
+	int i;
+
+	idx |= BIT(30);
+
+	/*
+	 *  disable index in all 4 subcaches
+	 */
+	for (i = 0; i < 4; i++) {
+		u32 reg = idx | (i << 20);
+
+		if (!l3->subcaches[i])
+			continue;
+
+		pci_write_config_dword(l3->dev, 0x1BC + slot * 4, reg);
+
+		/*
+		 * We need to WBINVD on a core on the node containing the L3
+		 * cache which indices we disable therefore a simple wbinvd()
+		 * is not sufficient.
+		 */
+		wbinvd_on_cpu(cpu);
+
+		reg |= BIT(31);
+		pci_write_config_dword(l3->dev, 0x1BC + slot * 4, reg);
+	}
+}
+
+
 static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
-	const char *buf, size_t count, unsigned int index)
+				   const char *buf, size_t count,
+				   unsigned int slot)
 {
 	struct pci_dev *dev = this_leaf->l3->dev;
 	int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
@@ -448,23 +480,17 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
 	    ((val & SUBCACHE_INDEX) > this_leaf->l3->indices))
 		return -EINVAL;
 
-	val |= BIT(30);
-	pci_write_config_dword(dev, 0x1BC + index * 4, val);
-	/*
-	 * We need to WBINVD on a core on the node containing the L3 cache which
-	 * indices we disable therefore a simple wbinvd() is not sufficient.
-	 */
-	wbinvd_on_cpu(cpu);
-	pci_write_config_dword(dev, 0x1BC + index * 4, val | BIT(31));
+	amd_l3_disable_index(this_leaf->l3, cpu, slot, val);
+
 	return count;
 }
 
-#define STORE_CACHE_DISABLE(index)					\
+#define STORE_CACHE_DISABLE(slot)					\
 static ssize_t								\
-store_cache_disable_##index(struct _cpuid4_info *this_leaf,		\
+store_cache_disable_##slot(struct _cpuid4_info *this_leaf,		\
 			    const char *buf, size_t count)		\
 {									\
-	return store_cache_disable(this_leaf, buf, count, index);	\
+	return store_cache_disable(this_leaf, buf, count, slot);	\
 }
 STORE_CACHE_DISABLE(0)
 STORE_CACHE_DISABLE(1)
Signature · 1 line
1.7.1.rc1
#14 lore raw

[tip:x86/cpu] x86, cacheinfo: Disable index in all four subcaches

Commit-ID:  59d3b388741cf1a5eb7ad27fd4e9ed72643164ae
Gitweb:     http://git.kernel.org/tip/59d3b388741cf1a5eb7ad27fd4e9ed72643164ae
Author:     Borislav Petkov <[email protected]>
AuthorDate: Thu, 22 Apr 2010 16:07:02 +0200
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Thu, 22 Apr 2010 17:17:27 -0700

x86, cacheinfo: Disable index in all four subcaches

When disabling an L3 cache index, make sure we disable that index in all four subcaches of the L3. Clarify nomenclature while at it, wrt to disable slots versus disable index and rename accordingly.

LKML-Reference: <[email protected]>

---
 arch/x86/kernel/cpu/intel_cacheinfo.c |   60 +++++++++++++++++++++++---------
 1 files changed, 43 insertions(+), 17 deletions(-)
arch/x86/kernel/cpu/intel_cacheinfo.c +43 -17
index 1346e9c..33eae20 100644
@@ -397,7 +397,7 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
 }
 
 static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
-				  unsigned int index)
+				  unsigned int slot)
 {
 	struct pci_dev *dev = this_leaf->l3->dev;
 	unsigned int reg = 0;
@@ -408,21 +408,53 @@ static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
 	if (!dev)
 		return -EINVAL;
 
-	pci_read_config_dword(dev, 0x1BC + index * 4, &reg);
+	pci_read_config_dword(dev, 0x1BC + slot * 4, &reg);
 	return sprintf(buf, "0x%08x\n", reg);
 }
 
-#define SHOW_CACHE_DISABLE(index)					\
+#define SHOW_CACHE_DISABLE(slot)					\
 static ssize_t								\
-show_cache_disable_##index(struct _cpuid4_info *this_leaf, char *buf)	\
+show_cache_disable_##slot(struct _cpuid4_info *this_leaf, char *buf)	\
 {									\
-	return show_cache_disable(this_leaf, buf, index);		\
+	return show_cache_disable(this_leaf, buf, slot);		\
 }
 SHOW_CACHE_DISABLE(0)
 SHOW_CACHE_DISABLE(1)
 
+static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu,
+				 unsigned slot, unsigned long idx)
+{
+	int i;
+
+	idx |= BIT(30);
+
+	/*
+	 *  disable index in all 4 subcaches
+	 */
+	for (i = 0; i < 4; i++) {
+		u32 reg = idx | (i << 20);
+
+		if (!l3->subcaches[i])
+			continue;
+
+		pci_write_config_dword(l3->dev, 0x1BC + slot * 4, reg);
+
+		/*
+		 * We need to WBINVD on a core on the node containing the L3
+		 * cache which indices we disable therefore a simple wbinvd()
+		 * is not sufficient.
+		 */
+		wbinvd_on_cpu(cpu);
+
+		reg |= BIT(31);
+		pci_write_config_dword(l3->dev, 0x1BC + slot * 4, reg);
+	}
+}
+
+
 static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
-	const char *buf, size_t count, unsigned int index)
+				   const char *buf, size_t count,
+				   unsigned int slot)
 {
 	struct pci_dev *dev = this_leaf->l3->dev;
 	int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
@@ -448,23 +480,17 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
 	    ((val & SUBCACHE_INDEX) > this_leaf->l3->indices))
 		return -EINVAL;
 
-	val |= BIT(30);
-	pci_write_config_dword(dev, 0x1BC + index * 4, val);
-	/*
-	 * We need to WBINVD on a core on the node containing the L3 cache which
-	 * indices we disable therefore a simple wbinvd() is not sufficient.
-	 */
-	wbinvd_on_cpu(cpu);
-	pci_write_config_dword(dev, 0x1BC + index * 4, val | BIT(31));
+	amd_l3_disable_index(this_leaf->l3, cpu, slot, val);
+
 	return count;
 }
 
-#define STORE_CACHE_DISABLE(index)					\
+#define STORE_CACHE_DISABLE(slot)					\
 static ssize_t								\
-store_cache_disable_##index(struct _cpuid4_info *this_leaf,		\
+store_cache_disable_##slot(struct _cpuid4_info *this_leaf,		\
 			    const char *buf, size_t count)		\
 {									\
-	return store_cache_disable(this_leaf, buf, count, index);	\
+	return store_cache_disable(this_leaf, buf, count, slot);	\
 }
 STORE_CACHE_DISABLE(0)
 STORE_CACHE_DISABLE(1)
#15 lore raw
In reply to Borislav Petkov

Hi Borislav,

I get compilation failures on tip:x86/cpu with this patchset:

arch/x86/built-in.o: In function `amd_check_l3_disable':
intel_cacheinfo.c:(.cpuinit.text+0x412): undefined reference to `num_k8_northbridges'

Both i386 and x86-64 "make allnoconfig".

-hpa

#16 lore raw

From: "H. Peter Anvin" <[email protected]>
Date: Thu, Apr 22, 2010 at 05:23:05PM -0700

Quoted 9 lines

Hi Borislav,

I get compilation failures on tip:x86/cpu with this patchset:

arch/x86/built-in.o: In function `amd_check_l3_disable':
intel_cacheinfo.c:(.cpuinit.text+0x412): undefined reference to `num_k8_northbridges'

Both i386 and x86-64 "make allnoconfig".

Yeah, this has bitten us already several times in the past. allnoconfig deselects CONFIG_PCI and num_k8_northbridges is under CONFIG_K8_NB which depends on CONFIG_PCI so there you go.

I'm thinking the k8.c facility is needed more and more for all the processor functionality control over the PCI config space so how about compile it in unconditionally on AMD? All the k8's and F10h's need it and the older ones will have it there but it won't hurt since the pci_get_device() won't match any on those.

allnoconfig build failure is fixed this way, albeit non-functional since CONFIG_PCI is off and pci_get_device() returns NULL but in that case almost all of the functionality (I guess raw PCI access would still work) depending on AMD northbridge PCI devices won't work anyway.

I'll prep something in a while.

Signature · 6 lines
Regards/Gruss,
Boris.

--
Advanced Micro Devices, Inc.
Operating Systems Research Center
#17 lore raw

From: Borislav Petkov <[email protected]>
Date: Fri, Apr 23, 2010 at 08:50:16AM +0200

Quoted 18 lines
Quoted 7 lines

I get compilation failures on tip:x86/cpu with this patchset:

arch/x86/built-in.o: In function `amd_check_l3_disable':
intel_cacheinfo.c:(.cpuinit.text+0x412): undefined reference to `num_k8_northbridges'

Both i386 and x86-64 "make allnoconfig".

Yeah, this has bitten us already several times in the past. allnoconfig deselects CONFIG_PCI and num_k8_northbridges is under CONFIG_K8_NB which depends on CONFIG_PCI so there you go.

I'm thinking the k8.c facility is needed more and more for all the processor functionality control over the PCI config space so how about compile it in unconditionally on AMD? All the k8's and F10h's need it and the older ones will have it there but it won't hurt since the pci_get_device() won't match any on those.

Quoted 6 lines

allnoconfig build failure is fixed this way, albeit non-functional since CONFIG_PCI is off and pci_get_device() returns NULL but in that case almost all of the functionality (I guess raw PCI access would still work) depending on AMD northbridge PCI devices won't work anyway.

I'll prep something in a while.

Ok, looking at the k8.o object it is 507 bytes so I don't think compiling it in would hurt embedded people too much:

   text    data     bss     dec     hex filename
    379     104      24     507     1fb arch/x86/kernel/k8.o

So how about the following? It should apply cleanly on top and it survived a bunch of randconfigs here so far.

---
From: Borislav Petkov <[email protected]>
Date: Fri, 23 Apr 2010 14:05:50 +0200
Subject: [PATCH] x86, AMD: Build in Northbridge PCI config devices support

A bunch of facilities in the kernel depend on accessing the processor's PCI config space in the northbridge for configuration and control. All K8 and F10h processors have that config space so build in the facility in k8.c which takes care of enumerating those PCI devices by default on AMD.

---
 arch/x86/Kconfig             |    6 +-----
 arch/x86/kernel/Makefile     |    1 -
 arch/x86/kernel/cpu/Makefile |    2 +-
 drivers/char/agp/Kconfig     |    2 +-
 drivers/edac/Kconfig         |    2 +-
 include/linux/pci.h          |    4 ++++
 6 files changed, 8 insertions(+), 9 deletions(-)
arch/x86/Kconfig +1 -5
index 9458685..9f80658 100644
@@ -662,7 +662,7 @@ config GART_IOMMU
 	bool "GART IOMMU support" if EMBEDDED
 	default y
 	select SWIOTLB
-	depends on X86_64 && PCI && K8_NB
+	depends on X86_64 && PCI
 	---help---
 	  Support for full DMA access of devices with 32bit memory access only
 	  on systems with more than 3GB. This is usually needed for USB,
@@ -2059,10 +2059,6 @@ config OLPC
 
 endif # X86_32
 
-config K8_NB
-	def_bool y
-	depends on CPU_SUP_AMD && PCI
-
 source "drivers/pcmcia/Kconfig"
 
 source "drivers/pci/hotplug/Kconfig"
arch/x86/kernel/Makefile +0 -1
index 4c58352..1afad06 100644
@@ -89,7 +89,6 @@ obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 obj-$(CONFIG_HPET_TIMER) 	+= hpet.o
 obj-$(CONFIG_APB_TIMER)		+= apb_timer.o
 
-obj-$(CONFIG_K8_NB)		+= k8.o
 obj-$(CONFIG_DEBUG_RODATA_TEST)	+= test_rodata.o
 obj-$(CONFIG_DEBUG_NX_TEST)	+= test_nx.o
 
arch/x86/kernel/cpu/Makefile +1 -1
index c202b62..78ef6c0 100644
@@ -20,7 +20,7 @@ obj-$(CONFIG_X86_32)	+= bugs.o cmpxchg.o
 obj-$(CONFIG_X86_64)	+= bugs_64.o
 
 obj-$(CONFIG_CPU_SUP_INTEL)		+= intel.o
-obj-$(CONFIG_CPU_SUP_AMD)		+= amd.o
+obj-$(CONFIG_CPU_SUP_AMD)		+= amd.o ../k8.o
 obj-$(CONFIG_CPU_SUP_CYRIX_32)		+= cyrix.o
 obj-$(CONFIG_CPU_SUP_CENTAUR)		+= centaur.o
 obj-$(CONFIG_CPU_SUP_TRANSMETA_32)	+= transmeta.o
drivers/char/agp/Kconfig +1 -1
index 4b66c69..2fb3a48 100644
@@ -57,7 +57,7 @@ config AGP_AMD
 
 config AGP_AMD64
 	tristate "AMD Opteron/Athlon64 on-CPU GART support"
-	depends on AGP && X86 && K8_NB
+	depends on AGP && X86
 	help
 	  This option gives you AGP support for the GLX component of
 	  X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs.
drivers/edac/Kconfig +1 -1
index 55c9c59..0812bbf 100644
@@ -71,7 +71,7 @@ config EDAC_MM_EDAC
 
 config EDAC_AMD64
 	tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h"
-	depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI && EDAC_DECODE_MCE
+	depends on EDAC_MM_EDAC && X86_64 && PCI && EDAC_DECODE_MCE
 	help
 	  Support for error detection and correction on the AMD 64
 	  Families of Memory Controllers (K8, F10h and F11h)
include/linux/pci.h +4 -0
index a788fa1..150dd65 100644
@@ -1199,6 +1199,10 @@ static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus,
 						unsigned int devfn)
 { return NULL; }
 
+static inline const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
+						       struct pci_dev *dev)
+{ return NULL; }
+
 #define dev_is_pci(d) (false)
 #define dev_is_pf(d) (false)
 #define dev_num_vf(d) (0)
Signature · 10 lines
1.6.4.4


-- 
Regards/Gruss,
Boris.

--
Advanced Micro Devices, Inc.
Operating Systems Research Center
#18 lore raw
Quoted 10 lines · Borislav Petkov

Ok, looking at the k8.o object it is 507 bytes so I don't think compiling it in would hurt embedded people too much:

   text    data     bss     dec     hex filename
    379     104      24     507     1fb arch/x86/kernel/k8.o

So how about the following? It should apply cleanly on top and it survived a bunch of randconfigs here so far.

I have to say I think that's pretty ridiculous for someone who cares so much about size that they have disabled CONFIG_PCI that they can just add another half-kilobyte of code that is going to do absolutely nothing. Think about the kind of x86 CPUs that could even consider disabling CONFIG_PCI -- we're talking pretty deep embedded by now.

So, no, I don't think this is an option. Force-enabling CONFIG_PCI on x86 would be a more realistic option, and I honestly don't know how many people would object to that, but not right now.

The obvious answer instead is to augment the list of stubs in <asm/k8.h>. In particular, move num_k8_northbridges into the #ifdef and just #define num_k8_northbridges 0 in the other clause.

-hpa

#19 lore raw

From: "H. Peter Anvin" <[email protected]>
Date: Fri, Apr 23, 2010 at 11:06:15AM -0700

Quoted 12 lines · Borislav Petkov
Quoted 10 lines

Ok, looking at the k8.o object it is 507 bytes so I don't think compiling it in would hurt embedded people too much:

   text    data     bss     dec     hex filename
    379     104      24     507     1fb arch/x86/kernel/k8.o

So how about the following? It should apply cleanly on top and it survived a bunch of randconfigs here so far.

Quoted 5 lines

I have to say I think that's pretty ridiculous for someone who cares so much about size that they have disabled CONFIG_PCI that they can just add another half-kilobyte of code that is going to do absolutely nothing. Think about the kind of x86 CPUs that could even consider disabling CONFIG_PCI -- we're talking pretty deep embedded by now.

Yep, true story.

Quoted 3 lines

So, no, I don't think this is an option. Force-enabling CONFIG_PCI on x86 would be a more realistic option, and I honestly don't know how many people would object to that, but not right now.

Well, after looking at 1ac97018169c5a13feaa90d9671f2d6ba2d9e86e, grepping for '!PCI' in arch/x86/ returns nothing now.

Quoted 1 line

From all the x86 flavors which didn't need PCI

1) There used to be a X86_VOYAGER MCA-based 32-bit arch from NCR which seems to be gone now

2) X86_VISWS "SGI 320/540 (Visual Workstation)" depended on !PCI but depends on PCI now, so which is it?

3) X86_VSMP ("ScaleMP vSMP") used to depend on !PCI but depends on PCI now, [/me puzzled].

all seem fine with PCI currently (especially the Voyager :)). So it really looks like we could enable it by default on x86. Maybe for the .35 merge window and see how much fallout we generate. Or at least put it up for a flamewar on lkml since we like those so much :).

Quoted 3 lines

The obvious answer instead is to augment the list of stubs in <asm/k8.h>. In particular, move num_k8_northbridges into the #ifdef and just #define num_k8_northbridges 0 in the other clause.

Right, it couldn't be simpler, see below. With it, the only warning I get doing randconfig builds is

arch/x86/kernel/cpu/intel_cacheinfo.c:498: warning: ‘cache_disable_0’ defined but not used arch/x86/kernel/cpu/intel_cacheinfo.c:500: warning: ‘cache_disable_1’ defined but not used

which is caused by !CONFIG_SYSFS but this is another senseless case.

---
From: Borislav Petkov <[email protected]>
Date: Sat, 24 Apr 2010 09:56:53 +0200
Subject: [PATCH] x86, k8-nb: Fix build error when K8_NB is disabled

K8_NB depends on PCI and when the last is disabled (allnoconfig) we fail at the final linking stage due to missing exported num_k8_northbridges. Add a header stub for that.

---
 arch/x86/include/asm/k8.h |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)
arch/x86/include/asm/k8.h +5 -0
index f70e600..af00bd1 100644
@@ -16,11 +16,16 @@ extern int k8_numa_init(unsigned long start_pfn, unsigned long end_pfn);
 extern int k8_scan_nodes(void);
 
 #ifdef CONFIG_K8_NB
+extern int num_k8_northbridges;
+
 static inline struct pci_dev *node_to_k8_nb_misc(int node)
 {
 	return (node < num_k8_northbridges) ? k8_northbridges[node] : NULL;
 }
+
 #else
+#define num_k8_northbridges 0
+
 static inline struct pci_dev *node_to_k8_nb_misc(int node)
 {
 	return NULL;
Signature · 10 lines
1.6.4.4


-- 
Regards/Gruss,
Boris.

--
Advanced Micro Devices, Inc.
Operating Systems Research Center
#20 lore raw

From: Borislav Petkov <[email protected]>
Date: Sat, Apr 24, 2010 at 04:21:05AM -0400

Hi Peter,

any progress here, do you want me to send an updated series or can you pick up the patchlet below?

Thanks.

Quoted 63 lines

From: "H. Peter Anvin" <[email protected]>
Date: Fri, Apr 23, 2010 at 11:06:15AM -0700

Quoted 12 lines · Borislav Petkov
Quoted 10 lines

Ok, looking at the k8.o object it is 507 bytes so I don't think compiling it in would hurt embedded people too much:

   text    data     bss     dec     hex filename
    379     104      24     507     1fb arch/x86/kernel/k8.o

So how about the following? It should apply cleanly on top and it survived a bunch of randconfigs here so far.

Quoted 5 lines

I have to say I think that's pretty ridiculous for someone who cares so much about size that they have disabled CONFIG_PCI that they can just add another half-kilobyte of code that is going to do absolutely nothing. Think about the kind of x86 CPUs that could even consider disabling CONFIG_PCI -- we're talking pretty deep embedded by now.

Yep, true story.

Quoted 3 lines

So, no, I don't think this is an option. Force-enabling CONFIG_PCI on x86 would be a more realistic option, and I honestly don't know how many people would object to that, but not right now.

Well, after looking at 1ac97018169c5a13feaa90d9671f2d6ba2d9e86e, grepping for '!PCI' in arch/x86/ returns nothing now.

From all the x86 flavors which didn't need PCI

1) There used to be a X86_VOYAGER MCA-based 32-bit arch from NCR which seems to be gone now

2) X86_VISWS "SGI 320/540 (Visual Workstation)" depended on !PCI but depends on PCI now, so which is it?

3) X86_VSMP ("ScaleMP vSMP") used to depend on !PCI but depends on PCI now, [/me puzzled].

all seem fine with PCI currently (especially the Voyager :)). So it really looks like we could enable it by default on x86. Maybe for the .35 merge window and see how much fallout we generate. Or at least put it up for a flamewar on lkml since we like those so much :).

Quoted 3 lines

The obvious answer instead is to augment the list of stubs in <asm/k8.h>. In particular, move num_k8_northbridges into the #ifdef and just #define num_k8_northbridges 0 in the other clause.

Right, it couldn't be simpler, see below. With it, the only warning I get doing randconfig builds is

arch/x86/kernel/cpu/intel_cacheinfo.c:498: warning: ‘cache_disable_0’ defined but not used arch/x86/kernel/cpu/intel_cacheinfo.c:500: warning: ‘cache_disable_1’ defined but not used

which is caused by !CONFIG_SYSFS but this is another senseless case.

---
From: Borislav Petkov <[email protected]>
Date: Sat, 24 Apr 2010 09:56:53 +0200
Subject: [PATCH] x86, k8-nb: Fix build error when K8_NB is disabled

Quoted 9 lines

K8_NB depends on PCI and when the last is disabled (allnoconfig) we fail at the final linking stage due to missing exported num_k8_northbridges. Add a header stub for that.

---
 arch/x86/include/asm/k8.h |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

--

Quoted 2 lines

1.6.4.4

Signature · 6 lines
Regards/Gruss,
Boris.

--
Advanced Micro Devices, Inc.
Operating Systems Research Center