Re: 2.6.23 regression: accessing invalid mmap'ed memory from gdb causes unkillable spinning

!MAILaRCHIVE_VOTE_RePLACE
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
To: David Miller <davem@...>
Cc: <duaneg@...>, <mingo@...>, <linux-kernel@...>
Date: Friday, November 2, 2007 - 6:45 am

On Thu, Nov 01, 2007 at 10:02:04PM -0700, David Miller wrote:

That's really sweet. I'd better put my code where my mouth is as well...
this patch seems to be about the best we can do as a generic fallback
without getting a dedicated vector (which has to be done in arch
code anyway).

Maybe it can be improved, I don't know... I also don't know if I'm doing
exactly the right thing with pt_regs, but it seems to work.

One thing I'm doing is just dumping a single CPU, on a rotational basis. 
Don't know whether that's better or worse, but just an idea.

Now I don't know what's the best way for an arch to override this with
their own enhanced handler (an ARCH_HAVE ifdef?)

Index: linux-2.6/arch/x86/kernel/smp_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/smp_64.c
+++ linux-2.6/arch/x86/kernel/smp_64.c
@@ -504,8 +504,10 @@ asmlinkage void smp_reschedule_interrupt
 	add_pda(irq_resched_count, 1);
 }
 
-asmlinkage void smp_call_function_interrupt(void)
+asmlinkage void smp_call_function_interrupt(struct pt_regs *regs)
 {
+	struct pt_regs *old_regs = set_irq_regs(regs);
+
 	void (*func) (void *info) = call_data->func;
 	void *info = call_data->info;
 	int wait = call_data->wait;
@@ -515,7 +517,7 @@ asmlinkage void smp_call_function_interr
 	 * Notify initiating CPU that I've grabbed the data and am
 	 * about to execute the function
 	 */
-	mb();
+	smp_rmb();
 	atomic_inc(&call_data->started);
 	/*
 	 * At this point the info structure may be out of scope unless wait==1
@@ -526,8 +528,10 @@ asmlinkage void smp_call_function_interr
 	add_pda(irq_call_count, 1);
 	irq_exit();
 	if (wait) {
-		mb();
+		smp_mb();
 		atomic_inc(&call_data->finished);
 	}
+
+	set_irq_regs(old_regs);
 }
 
Index: linux-2.6/drivers/char/sysrq.c
===================================================================
--- linux-2.6.orig/drivers/char/sysrq.c
+++ linux-2.6/drivers/char/sysrq.c
@@ -196,12 +196,72 @@ static struct sysrq_key_op sysrq_showloc
 #define sysrq_showlocks_op (*(struct sysrq_key_op *)0)
 #endif
 
-static void sysrq_handle_showregs(int key, struct tty_struct *tty)
+static void show_registers(struct pt_regs *regs)
 {
-	struct pt_regs *regs = get_irq_regs();
 	if (regs)
 		show_regs(regs);
 }
+
+static void show_cpu_registers(void)
+{
+	show_registers(get_irq_regs());
+}
+
+static void show_global_regs(void *arg)
+{
+	show_cpu_registers();
+}
+
+static DEFINE_SPINLOCK(global_rotate_lock);
+static cpumask_t global_rotate_cpu;
+
+static void sysrq_handle_global_showregs_work_fn(struct work_struct *work)
+{
+	int cpu, next, thiscpu;
+
+	spin_lock(&global_rotate_lock);
+	if (cpus_weight(global_rotate_cpu) == 0)
+		cpu = smp_processor_id();
+	else
+		cpu = first_cpu(global_rotate_cpu);
+
+	next = next_cpu(cpu, cpu_online_map);
+	if (next == NR_CPUS)
+		next = first_cpu(cpu_online_map);
+	cpu_clear(cpu, global_rotate_cpu);
+	cpu_set(next, global_rotate_cpu);
+	BUG_ON(cpus_weight(global_rotate_cpu) != 1);
+	spin_unlock(&global_rotate_lock);
+
+	thiscpu = get_cpu();
+	if (cpu == thiscpu)
+		show_registers(task_pt_regs(current));
+	else {
+		if (smp_call_function_single(cpu, show_global_regs, NULL, 1, 1)
+				== -1) {
+			printk("Could not interrogate CPU registers\n");
+			return;
+		}
+	}
+	put_cpu();
+}
+static DECLARE_WORK(global_showregs_work, sysrq_handle_global_showregs_work_fn);
+static void sysrq_handle_global_showregs(int key, struct tty_struct *tty)
+{
+	schedule_work(&global_showregs_work);
+}
+static struct sysrq_key_op sysrq_global_showregs_op = {
+	.handler	= sysrq_handle_global_showregs,
+	.help_msg	= "showGlobalPc",
+	.action_msg	= "Show Global CPU Regs",
+	.enable_mask	= SYSRQ_ENABLE_DUMP,
+};
+
+
+static void sysrq_handle_showregs(int key, struct tty_struct *tty)
+{
+	show_cpu_registers();
+}
 static struct sysrq_key_op sysrq_showregs_op = {
 	.handler	= sysrq_handle_showregs,
 	.help_msg	= "showPc",
@@ -336,7 +396,7 @@ static struct sysrq_key_op *sysrq_key_ta
 	&sysrq_term_op,			/* e */
 	&sysrq_moom_op,			/* f */
 	/* g: May be registered by ppc for kgdb */
-	NULL,				/* g */
+	&sysrq_global_showregs_op,	/* g */
 	NULL,				/* h */
 	&sysrq_kill_op,			/* i */
 	NULL,				/* j */
-
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
Re: 2.6.23 regression: accessing invalid mmap'ed memory from..., Nick Piggin, (Fri Nov 2, 6:45 am)