Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 1860

kernel-2.6.18-128.1.10.el5.src.rpm

From: Brad Peters <bpeters@redhat.com>
Date: Thu, 31 Jul 2008 14:52:38 -0400
Subject:  [ppc64] missed hw breakpoints across multiple threads
Message-id: 20080731185238.10238.3682.sendpatchset@squad5-lp1.lab.bos.redhat.com
O-Subject: [PATCH RHEL5.3] Kernel missing triggers of hw watchpoints using DABR registers with multi-threaded apps
Bugzilla: 444076
RH-Acked-by: Pete Zaitcev <zaitcev@redhat.com>

RHBZ#:
======
https://bugzilla.redhat.com/show_bug.cgi?id=444076

Description:
===========
Upon estabilishing a hardware watchpoint to monitor a variable on PPC64 64-bit
threaded binary, sometimes GDB does not receive signals back from the kernel
even though the monitored variable's been changed.

The patch does the following.  We keep a per-cpu cache of the current
DABR value, and only write to the DABR register if the current process
has a different DABR value. In one place we were forgetting to update
the cache, and so we would incorrectly skip a write to the register.
The patch just moves the cache management into the set_dabr() function
so the cache always reflects reality.

RHEL Version Found:
================
RHEL 5.2

kABI Status:
============
No symbols were harmed.

Brew:
=====
Built on all platforms.
http://brewweb.devel.redhat.com/brew/taskinfo?taskID=1389146

Upstream Status:
================
Committed here:
http://lkml.org/lkml/2008/3/28/127

Test Status:
============
Using test case attached to BZ, repeating 250 times did not witness
a single failure.
Brad Peters, 7/31/08

===============================================================

Proposed Patch:
===============
This patch is based on 2.6.18-95

diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index e96fa97..f4169c3 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -221,8 +221,17 @@ void discard_lazy_cpu_state(void)
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_PPC_MERGE		/* XXX for now */
+
+#ifdef CONFIG_PPC64
+static DEFINE_PER_CPU(unsigned long, current_dabr);
+#endif
+
 int set_dabr(unsigned long dabr)
 {
+#ifdef CONFIG_PPC64
+	__get_cpu_var(current_dabr) = dabr;
+#endif
+
 	if (ppc_md.set_dabr)
 		return ppc_md.set_dabr(dabr);
 
@@ -233,7 +242,6 @@ int set_dabr(unsigned long dabr)
 
 #ifdef CONFIG_PPC64
 DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
-static DEFINE_PER_CPU(unsigned long, current_dabr);
 #endif
 
 struct task_struct *__switch_to(struct task_struct *prev,
@@ -301,10 +309,8 @@ struct task_struct *__switch_to(struct task_struct *prev,
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_PPC64	/* for now */
-	if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) {
+	if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr))
 		set_dabr(new->thread.dabr);
-		__get_cpu_var(current_dabr) = new->thread.dabr;
-	}
 
 	flush_tlb_pending();
 #endif