public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] (1/3) cleanup thread info on x86
@ 2002-10-18 22:07 Dave Hansen
  0 siblings, 0 replies; 8+ messages in thread
From: Dave Hansen @ 2002-10-18 22:07 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 368 bytes --]

This is a port of work Ben LaHaise did around 2.5.20 time.  I split it
up and updated it for the new preempt_count semantics.

* clean thread info infrastructure (1/3)
    - take out all instances of things like (8191&esp) to get
      current stack address.

Has a few unused things that will be used in the following two patches.
-- 
Dave Hansen
haveblue@us.ibm.com

[-- Attachment #2: A-thread_info_cleanup-2.5.43+bk-1.patch --]
[-- Type: text/plain, Size: 4888 bytes --]

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.857   -> 1.858  
#	arch/i386/kernel/head.S	1.17    -> 1.18   
#	include/asm-i386/thread_info.h	1.7     -> 1.8    
#	include/asm-i386/page.h	1.19    -> 1.20   
#	arch/i386/kernel/entry.S	1.37.1.1 -> 1.38.1.1
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/10/15	haveblue@elm3b96.(none)	1.858
# Merge elm3b96.(none):/work/dave/bk/linux-2.5
# into elm3b96.(none):/work/dave/bk/linux-2.5-thread_info_infra
# --------------------------------------------
#
diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
--- a/arch/i386/kernel/entry.S	Wed Oct 16 14:12:29 2002
+++ b/arch/i386/kernel/entry.S	Wed Oct 16 14:12:29 2002
@@ -136,7 +136,7 @@
 	movl %ecx,CS(%esp)	#
 	movl %esp, %ebx
 	pushl %ebx
-	andl $-8192, %ebx	# GET_THREAD_INFO
+	GET_THREAD_INFO_WITH_ESP(%ebx)	# GET_THREAD_INFO
 	movl TI_EXEC_DOMAIN(%ebx), %edx	# Get the execution domain
 	movl 4(%edx), %edx	# Get the lcall7 handler for the domain
 	pushl $0x7
@@ -158,7 +158,7 @@
 	movl %ecx,CS(%esp)	#
 	movl %esp, %ebx
 	pushl %ebx
-	andl $-8192, %ebx	# GET_THREAD_INFO
+	GET_THREAD_INFO_WITH_ESP(%ebx)  # GET_THREAD_INFO
 	movl TI_EXEC_DOMAIN(%ebx), %edx	# Get the execution domain
 	movl 4(%edx), %edx	# Get the lcall7 handler for the domain
 	pushl $0x27
diff -Nru a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
--- a/arch/i386/kernel/head.S	Wed Oct 16 14:12:29 2002
+++ b/arch/i386/kernel/head.S	Wed Oct 16 14:12:29 2002
@@ -15,6 +15,7 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/desc.h>
+#include <asm/thread_info.h>
 
 #define OLD_CL_MAGIC_ADDR	0x90020
 #define OLD_CL_MAGIC		0xA33F
@@ -305,7 +306,7 @@
 	ret
 
 ENTRY(stack_start)
-	.long init_thread_union+8192
+	.long init_thread_union+THREAD_SIZE
 	.long __KERNEL_DS
 
 /* This is the default interrupt "handler" :-) */
diff -Nru a/include/asm-i386/page.h b/include/asm-i386/page.h
--- a/include/asm-i386/page.h	Wed Oct 16 14:12:29 2002
+++ b/include/asm-i386/page.h	Wed Oct 16 14:12:29 2002
@@ -3,7 +3,11 @@
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT	12
-#define PAGE_SIZE	(1UL << PAGE_SHIFT)
+#ifndef __ASSEMBLY__
+#define PAGE_SIZE      (1UL << PAGE_SHIFT)
+#else
+#define PAGE_SIZE      (1 << PAGE_SHIFT)
+#endif
 #define PAGE_MASK	(~(PAGE_SIZE-1))
 
 #define LARGE_PAGE_MASK (~(LARGE_PAGE_SIZE-1))
diff -Nru a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
--- a/include/asm-i386/thread_info.h	Wed Oct 16 14:12:29 2002
+++ b/include/asm-i386/thread_info.h	Wed Oct 16 14:12:29 2002
@@ -9,6 +9,7 @@
 
 #ifdef __KERNEL__
 
+#include <asm/page.h>
 #ifndef __ASSEMBLY__
 #include <asm/processor.h>
 #endif
@@ -54,10 +55,13 @@
  *
  * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
+#define THREAD_ORDER 1 
+#define INIT_THREAD_SIZE       THREAD_SIZE
+
 #ifndef __ASSEMBLY__
 #define INIT_THREAD_INFO(tsk)			\
 {						\
-	.task		= &tsk,			\
+	.task		= &tsk,         	\
 	.exec_domain	= &default_exec_domain,	\
 	.flags		= 0,			\
 	.cpu		= 0,			\
@@ -68,30 +72,36 @@
 #define init_thread_info	(init_thread_union.thread_info)
 #define init_stack		(init_thread_union.stack)
 
+/* thread information allocation */
+#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
+#define alloc_thread_info() ((struct thread_info *) __get_free_pages(GFP_KERNEL,THREAD_ORDER))
+#define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_ORDER)
+#define get_thread_info(ti) get_task_struct((ti)->task)
+#define put_thread_info(ti) put_task_struct((ti)->task)
+
 /* how to get the thread information struct from C */
 static inline struct thread_info *current_thread_info(void)
 {
 	struct thread_info *ti;
-	__asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~8191UL));
+	__asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~(THREAD_SIZE - 1)));
 	return ti;
 }
 
-/* thread information allocation */
-#define THREAD_SIZE (2*PAGE_SIZE)
-#define alloc_thread_info() ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
-#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
-
 #else /* !__ASSEMBLY__ */
 
+#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
+
 /* how to get the thread information struct from ASM */
 #define GET_THREAD_INFO(reg) \
-	movl $-8192, reg; \
+	movl $-THREAD_SIZE, reg; \
 	andl %esp, reg
 
-#endif
+/* use this one if reg already contains %esp */
+#define GET_THREAD_INFO_WITH_ESP(reg) \
+	andl $-THREAD_SIZE, reg
 
+#endif
+	 
 /*
  * thread information flags
  * - these are process state flags that various assembly files may need to access

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH] (1/3) cleanup thread info on x86
@ 2002-10-31 19:18 David C. Hansen
  2002-10-31 19:20 ` [PATCH] (2/3) per-cpu interrupt stacks for x86 David C. Hansen
  2002-10-31 19:20 ` [PATCH] (3/3) stack overflow checking " David C. Hansen
  0 siblings, 2 replies; 8+ messages in thread
From: David C. Hansen @ 2002-10-31 19:18 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: lkml

[-- Attachment #1: Type: text/plain, Size: 442 bytes --]

These patches have been in Alan's tree for the last week with no
problems.

This is a port of work Ben LaHaise did around 2.5.20 time.  I split it
up and updated it for the new preempt_count semantics.

* clean thread info infrastructure (1/3)
   - take out all instances of things like (8191&esp) to get
     current stack address.

Has a few unused things that will be used in the following two patches.
-- 
Dave Hansen
haveblue@us.ibm.com

[-- Attachment #2: A-thread_info_cleanup-2.5.45-4.patch --]
[-- Type: text/plain, Size: 5035 bytes --]

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.855   -> 1.856  
#	arch/i386/kernel/head.S	1.17    -> 1.18   
#	include/asm-i386/thread_info.h	1.7     -> 1.8    
#	include/asm-i386/page.h	1.19    -> 1.20   
#	arch/i386/kernel/entry.S	1.37.1.2 -> 1.38.2.1
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/10/31	haveblue@elm3b96.(none)	1.856
# Merge elm3b96.(none):/work/dave/bk/linux-2.5
# into elm3b96.(none):/work/dave/bk/linux-2.5-thread_info_infra
# --------------------------------------------
#
diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
--- a/arch/i386/kernel/entry.S	Thu Oct 31 11:10:55 2002
+++ b/arch/i386/kernel/entry.S	Thu Oct 31 11:10:55 2002
@@ -136,7 +136,7 @@
 	movl %ecx,CS(%esp)	#
 	movl %esp, %ebx
 	pushl %ebx
-	andl $-8192, %ebx	# GET_THREAD_INFO
+	GET_THREAD_INFO_WITH_ESP(%ebx)	# GET_THREAD_INFO
 	movl TI_EXEC_DOMAIN(%ebx), %edx	# Get the execution domain
 	movl 4(%edx), %edx	# Get the lcall7 handler for the domain
 	pushl $0x7
@@ -158,7 +158,7 @@
 	movl %ecx,CS(%esp)	#
 	movl %esp, %ebx
 	pushl %ebx
-	andl $-8192, %ebx	# GET_THREAD_INFO
+	GET_THREAD_INFO_WITH_ESP(%ebx)  # GET_THREAD_INFO
 	movl TI_EXEC_DOMAIN(%ebx), %edx	# Get the execution domain
 	movl 4(%edx), %edx	# Get the lcall7 handler for the domain
 	pushl $0x27
diff -Nru a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
--- a/arch/i386/kernel/head.S	Thu Oct 31 11:10:55 2002
+++ b/arch/i386/kernel/head.S	Thu Oct 31 11:10:55 2002
@@ -15,6 +15,7 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/desc.h>
+#include <asm/thread_info.h>
 
 #define OLD_CL_MAGIC_ADDR	0x90020
 #define OLD_CL_MAGIC		0xA33F
@@ -305,7 +306,7 @@
 	ret
 
 ENTRY(stack_start)
-	.long init_thread_union+8192
+	.long init_thread_union+THREAD_SIZE
 	.long __KERNEL_DS
 
 /* This is the default interrupt "handler" :-) */
diff -Nru a/include/asm-i386/page.h b/include/asm-i386/page.h
--- a/include/asm-i386/page.h	Thu Oct 31 11:10:55 2002
+++ b/include/asm-i386/page.h	Thu Oct 31 11:10:55 2002
@@ -3,7 +3,11 @@
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT	12
-#define PAGE_SIZE	(1UL << PAGE_SHIFT)
+#ifndef __ASSEMBLY__
+#define PAGE_SIZE      (1UL << PAGE_SHIFT)
+#else
+#define PAGE_SIZE      (1 << PAGE_SHIFT)
+#endif
 #define PAGE_MASK	(~(PAGE_SIZE-1))
 
 #define LARGE_PAGE_MASK (~(LARGE_PAGE_SIZE-1))
diff -Nru a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
--- a/include/asm-i386/thread_info.h	Thu Oct 31 11:10:55 2002
+++ b/include/asm-i386/thread_info.h	Thu Oct 31 11:10:55 2002
@@ -9,6 +9,7 @@
 
 #ifdef __KERNEL__
 
+#include <asm/page.h>
 #ifndef __ASSEMBLY__
 #include <asm/processor.h>
 #endif
@@ -54,10 +55,13 @@
  *
  * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
+#define THREAD_ORDER 1 
+#define INIT_THREAD_SIZE       THREAD_SIZE
+
 #ifndef __ASSEMBLY__
 #define INIT_THREAD_INFO(tsk)			\
 {						\
-	.task		= &tsk,			\
+	.task		= &tsk,         	\
 	.exec_domain	= &default_exec_domain,	\
 	.flags		= 0,			\
 	.cpu		= 0,			\
@@ -68,30 +72,36 @@
 #define init_thread_info	(init_thread_union.thread_info)
 #define init_stack		(init_thread_union.stack)
 
+/* thread information allocation */
+#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
+#define alloc_thread_info() ((struct thread_info *) __get_free_pages(GFP_KERNEL,THREAD_ORDER))
+#define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_ORDER)
+#define get_thread_info(ti) get_task_struct((ti)->task)
+#define put_thread_info(ti) put_task_struct((ti)->task)
+
 /* how to get the thread information struct from C */
 static inline struct thread_info *current_thread_info(void)
 {
 	struct thread_info *ti;
-	__asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~8191UL));
+	__asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~(THREAD_SIZE - 1)));
 	return ti;
 }
 
-/* thread information allocation */
-#define THREAD_SIZE (2*PAGE_SIZE)
-#define alloc_thread_info() ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
-#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
-
 #else /* !__ASSEMBLY__ */
 
+#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
+
 /* how to get the thread information struct from ASM */
 #define GET_THREAD_INFO(reg) \
-	movl $-8192, reg; \
+	movl $-THREAD_SIZE, reg; \
 	andl %esp, reg
 
-#endif
+/* use this one if reg already contains %esp */
+#define GET_THREAD_INFO_WITH_ESP(reg) \
+	andl $-THREAD_SIZE, reg
 
+#endif
+	 
 /*
  * thread information flags
  * - these are process state flags that various assembly files may need to access

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH] (2/3) per-cpu interrupt stacks for x86
  2002-10-31 19:18 [PATCH] (1/3) cleanup thread info on x86 David C. Hansen
@ 2002-10-31 19:20 ` David C. Hansen
  2002-10-31 19:20 ` [PATCH] (3/3) stack overflow checking " David C. Hansen
  1 sibling, 0 replies; 8+ messages in thread
From: David C. Hansen @ 2002-10-31 19:20 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: lkml

[-- Attachment #1: Type: text/plain, Size: 316 bytes --]

* interrupt stacks (2/3)
   - allocate per-cpu interrupt stacks.  upon entry to
     common_interrupt, switch to the current cpu's stack.
   - inherit the interrupted task's preempt count, and pass
     back relevant task flags

Depends on the previously sent thread_info cleanup
-- 
Dave Hansen
haveblue@us.ibm.com

[-- Attachment #2: B-interrupt_stacks-2.5.45-4.patch --]
[-- Type: text/plain, Size: 7329 bytes --]

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.856   -> 1.857  
#	arch/i386/kernel/process.c	1.32    -> 1.32.1.1
#	arch/i386/kernel/irq.c	1.21.1.2 -> 1.23.1.1
#	include/asm-i386/thread_info.h	1.8     -> 1.10   
#	arch/i386/kernel/entry.S	1.38.2.1 -> 1.38.1.3
#	arch/i386/kernel/smpboot.c	1.36    -> 1.37   
#	arch/i386/kernel/init_task.c	1.6     -> 1.6.1.1
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/10/31	haveblue@elm3b96.(none)	1.857
# Merge
# --------------------------------------------
#
diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
--- a/arch/i386/kernel/entry.S	Thu Oct 31 11:12:05 2002
+++ b/arch/i386/kernel/entry.S	Thu Oct 31 11:12:05 2002
@@ -334,7 +334,45 @@
 	ALIGN
 common_interrupt:
 	SAVE_ALL
+
+
+	GET_THREAD_INFO(%ebx)
+	movl TI_IRQ_STACK(%ebx),%ecx
+	movl TI_TASK(%ebx),%edx
+	movl %esp,%eax
+	leal (THREAD_SIZE-4)(%ecx),%esi # %ecx+THREAD_SIZE is next stack
+	                                # -4 keeps us in the right one
+	testl %ecx,%ecx                 # is there a valid irq_stack?
+
+	# switch to the irq stack
+#ifdef CONFIG_X86_HAVE_CMOV
+	cmovnz %esi,%esp
+#else
+	jz 1f
+	mov %esi,%esp
+1:
+#endif
+	
+	# update the task pointer in the irq stack
+	GET_THREAD_INFO(%esi)
+	movl %edx,TI_TASK(%esi)
+
+	# update the preempt count in the irq stack
+	movl TI_PRE_COUNT(%ebx),%ecx
+	movl %ecx,TI_PRE_COUNT(%esi)
+		
 	call do_IRQ
+
+	movl %eax,%esp                  # potentially restore non-irq stack
+	
+	# copy flags from the irq stack back into the task's thread_info
+	# %esi is saved over the do_IRQ call and contains the irq stack
+	# thread_info pointer
+	# %ebx contains the original thread_info pointer
+	movl TI_FLAGS(%esi),%eax
+	movl $0,TI_FLAGS(%esi)
+	LOCK orl %eax,TI_FLAGS(%ebx)
+
 	jmp ret_from_intr
 
 #define BUILD_INTERRUPT(name, nr)	\
diff -Nru a/arch/i386/kernel/init_task.c b/arch/i386/kernel/init_task.c
--- a/arch/i386/kernel/init_task.c	Thu Oct 31 11:12:05 2002
+++ b/arch/i386/kernel/init_task.c	Thu Oct 31 11:12:05 2002
@@ -13,6 +13,10 @@
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
 struct mm_struct init_mm = INIT_MM(init_mm);
 
+union thread_union init_irq_union
+	__attribute__((__section__(".data.init_task")));
+
+
 /*
  * Initial thread structure.
  *
diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
--- a/arch/i386/kernel/irq.c	Thu Oct 31 11:12:05 2002
+++ b/arch/i386/kernel/irq.c	Thu Oct 31 11:12:05 2002
@@ -311,7 +311,8 @@
  * SMP cross-CPU interrupts have their own specific
  * handlers).
  */
-asmlinkage unsigned int do_IRQ(struct pt_regs regs)
+struct pt_regs *do_IRQ(struct pt_regs *regs) __attribute__((regparm(1)));
+struct pt_regs *do_IRQ(struct pt_regs *regs)
 {	
 	/* 
 	 * We ack quickly, we don't want the irq controller
@@ -323,7 +324,7 @@
 	 * 0 return value means that this irq is already being
 	 * handled by some other CPU. (or is disabled)
 	 */
-	int irq = regs.orig_eax & 0xff; /* high bits used in ret_from_ code  */
+	int irq = regs->orig_eax & 0xff; /* high bits used in ret_from_ code  */
 	int cpu = smp_processor_id();
 	irq_desc_t *desc = irq_desc + irq;
 	struct irqaction * action;
@@ -388,7 +389,7 @@
 	 */
 	for (;;) {
 		spin_unlock(&desc->lock);
-		handle_IRQ_event(irq, &regs, action);
+		handle_IRQ_event(irq, regs, action);
 		spin_lock(&desc->lock);
 		
 		if (likely(!(desc->status & IRQ_PENDING)))
@@ -407,7 +408,7 @@
 
 	irq_exit();
 
-	return 1;
+	return regs;
 }
 
 /**
diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
--- a/arch/i386/kernel/process.c	Thu Oct 31 11:12:05 2002
+++ b/arch/i386/kernel/process.c	Thu Oct 31 11:12:05 2002
@@ -413,6 +413,7 @@
 
 	/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
 
+	next_p->thread_info->irq_stack = prev_p->thread_info->irq_stack;
 	unlazy_fpu(prev_p);
 
 	/*
diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
--- a/arch/i386/kernel/smpboot.c	Thu Oct 31 11:12:05 2002
+++ b/arch/i386/kernel/smpboot.c	Thu Oct 31 11:12:05 2002
@@ -70,6 +70,11 @@
 /* Per CPU bogomips and other parameters */
 struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
 
+/* Per CPU interrupt stacks */
+extern union thread_union init_irq_union;
+union thread_union *irq_stacks[NR_CPUS] __cacheline_aligned =
+	{ &init_irq_union, };
+
 /* Set when the idlers are all forked */
 int smp_threads_ready;
 
@@ -764,6 +769,28 @@
 	return (send_status | accept_status);
 }
 
+static void __init setup_irq_stack(struct task_struct *p, int cpu)
+{
+	unsigned long stk;
+
+	stk = __get_free_pages(GFP_KERNEL, THREAD_ORDER+1);
+	if (!stk)
+		panic("I can't seem to allocate my irq stack.  Oh well, giving up.");
+
+	irq_stacks[cpu] = (void *)stk;
+	memset(irq_stacks[cpu], 0, THREAD_SIZE);
+	irq_stacks[cpu]->thread_info.cpu = cpu;
+	irq_stacks[cpu]->thread_info.preempt_count = 1;
+					/* interrupts are not preemptable */
+	p->thread_info->irq_stack = irq_stacks[cpu];
+
+	/* If we want to make the irq stack more than one unit
+	 * deep, we can chain then off of the irq_stack pointer
+	 * here.
+	 */
+}
+
+
 extern unsigned long cpu_initialized;
 
 static void __init do_boot_cpu (int apicid) 
@@ -787,6 +814,8 @@
 	if (IS_ERR(idle))
 		panic("failed fork for CPU %d", cpu);
 
+	setup_irq_stack(idle, cpu);
+
 	/*
 	 * We remove it from the pidhash and the runqueue
 	 * once we got the process:
@@ -804,7 +833,13 @@
 
 	/* So we see what's up   */
 	printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip);
-	stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle->thread_info);
+
+	/* The -4 is to correct for the fact that the stack pointer
+	 * is used to find the location of the thread_info structure
+	 * by masking off several of the LSBs.  Without the -4, esp
+	 * is pointing to the page after the one the stack is on.
+	 */
+	stack_start.esp = (void *)(THREAD_SIZE - 4 + (char *)idle->thread_info);
 
 	/*
 	 * This grunge runs the startup process for
diff -Nru a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
--- a/include/asm-i386/thread_info.h	Thu Oct 31 11:12:05 2002
+++ b/include/asm-i386/thread_info.h	Thu Oct 31 11:12:05 2002
@@ -29,9 +29,11 @@
 	__s32			preempt_count; /* 0 => preemptable, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
+						   0 for interrupts: illegal
 					 	   0-0xBFFFFFFF for user-thead
 						   0-0xFFFFFFFF for kernel-thread
 						*/
+	struct thread_info	*irq_stack;	/* pointer to cpu irq stack */
 
 	__u8			supervisor_stack[0];
 };
@@ -45,6 +47,7 @@
 #define TI_CPU		0x0000000C
 #define TI_PRE_COUNT	0x00000010
 #define TI_ADDR_LIMIT	0x00000014
+#define TI_IRQ_STACK	0x00000018
 
 #endif
 
@@ -67,6 +70,7 @@
 	.cpu		= 0,			\
 	.preempt_count	= 1,			\
 	.addr_limit	= KERNEL_DS,		\
+	.irq_stack	= &init_irq_union	\
 }
 
 #define init_thread_info	(init_thread_union.thread_info)

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH] (3/3) stack overflow checking for x86
  2002-10-31 19:18 [PATCH] (1/3) cleanup thread info on x86 David C. Hansen
  2002-10-31 19:20 ` [PATCH] (2/3) per-cpu interrupt stacks for x86 David C. Hansen
@ 2002-10-31 19:20 ` David C. Hansen
  2002-10-31 21:30   ` Dave Jones
  1 sibling, 1 reply; 8+ messages in thread
From: David C. Hansen @ 2002-10-31 19:20 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: lkml

[-- Attachment #1: Type: text/plain, Size: 424 bytes --]

* stack checking (3/3)
   - use gcc's profiling features to check for stack overflows upon
     entry to functions.
   - Warn if the task goes over 4k.
   - Panic if the stack gets within 512 bytes of overflowing.
   - use kksymoops information, if available

This won't apply cleanly without the irqstack patch, but the conflict is
easy to resolve.  It requires the thread_info cleanup.
-- 
Dave Hansen
haveblue@us.ibm.com

[-- Attachment #2: C-stack_usage_check-2.5.45-4.patch --]
[-- Type: text/plain, Size: 6119 bytes --]

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.857.1.1 -> 1.859  
#	arch/i386/kernel/process.c	1.32.1.1 -> 1.36   
#	arch/i386/kernel/irq.c	1.23.1.1 -> 1.25   
#	            Makefile	1.326.2.11 -> 1.329  
#	include/asm-i386/thread_info.h	1.10    -> 1.11   
#	arch/i386/kernel/entry.S	1.38.1.3 -> 1.46   
#	  arch/i386/Makefile	1.24.2.3 -> 1.27   
#	arch/i386/boot/compressed/misc.c	1.9     -> 1.10   
#	arch/i386/kernel/init_task.c	1.6.1.1 -> 1.8    
#	arch/i386/kernel/i386_ksyms.c	1.36.2.3 -> 1.39   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/10/31	haveblue@elm3b96.(none)	1.859
# Merge elm3b96.(none):/work/dave/bk/linux-2.5-irq-stack
# into elm3b96.(none):/work/dave/bk/linux-2.5-irq-stack+overflow-detect
# --------------------------------------------
#
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Thu Oct 31 11:13:28 2002
+++ b/Makefile	Thu Oct 31 11:13:28 2002
@@ -168,7 +168,8 @@
 
 CPPFLAGS	:= -D__KERNEL__ -Iinclude
 CFLAGS 		:= $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \
-	  	   -fomit-frame-pointer -fno-strict-aliasing -fno-common
+	  	   -fno-strict-aliasing -fno-common
+
 AFLAGS		:= -D__ASSEMBLY__ $(CPPFLAGS)
 
 export	VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION KERNELRELEASE ARCH \
@@ -254,6 +255,10 @@
 
 ifdef CONFIG_MODULES
 export EXPORT_FLAGS := -DEXPORT_SYMTAB
+endif
+
+ifneq ($(CONFIG_FRAME_POINTER),y)
+CFLAGS          += -fomit-frame-pointer
 endif
 
 #
diff -Nru a/arch/i386/Makefile b/arch/i386/Makefile
--- a/arch/i386/Makefile	Thu Oct 31 11:13:28 2002
+++ b/arch/i386/Makefile	Thu Oct 31 11:13:28 2002
@@ -51,6 +51,10 @@
 MACHINE	:= mach-generic
 endif
 
+ifdef CONFIG_X86_STACK_CHECK
+CFLAGS += -p
+endif
+
 HEAD := arch/i386/kernel/head.o arch/i386/kernel/init_task.o
 
 libs-y 					+= arch/i386/lib/
diff -Nru a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c
--- a/arch/i386/boot/compressed/misc.c	Thu Oct 31 11:13:28 2002
+++ b/arch/i386/boot/compressed/misc.c	Thu Oct 31 11:13:28 2002
@@ -377,3 +377,7 @@
 	if (high_loaded) close_output_buffer_if_we_run_high(mv);
 	return high_loaded;
 }
+
+/* We don't actually check for stack overflows this early. */
+__asm__(".globl mcount ; mcount: ret\n");
+
diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
--- a/arch/i386/kernel/entry.S	Thu Oct 31 11:13:28 2002
+++ b/arch/i386/kernel/entry.S	Thu Oct 31 11:13:28 2002
@@ -519,6 +519,61 @@
 	pushl $do_spurious_interrupt_bug
 	jmp error_code
 
+
+#ifdef CONFIG_X86_STACK_CHECK
+.data
+	.globl	stack_overflowed
+stack_overflowed:
+	.long	0
+.text
+
+ENTRY(mcount)
+	push %eax
+	movl $(THREAD_SIZE - 1),%eax
+	andl %esp,%eax
+	cmpl $STACK_WARN,%eax	/* more than half the stack is used*/
+	jle 1f
+2:
+	popl %eax
+	ret
+1:	
+	lock;   btsl    $0,stack_overflowed
+	jc      2b
+	
+	# switch to overflow stack
+	movl	%esp,%eax
+	movl	$(stack_overflow_stack + THREAD_SIZE - 4),%esp
+
+	pushf
+	cli
+	pushl	%eax
+
+	# push eip then esp of error for stack_overflow_panic
+	pushl	4(%eax)
+	pushl	%eax
+
+	# update the task pointer and cpu in the overflow stack's thread_info.
+	GET_THREAD_INFO_WITH_ESP(%eax)
+	movl	TI_TASK(%eax),%ebx
+	movl	%ebx,stack_overflow_stack+TI_TASK
+	movl	TI_CPU(%eax),%ebx
+	movl	%ebx,stack_overflow_stack+TI_CPU
+
+	call	stack_overflow
+
+	# pop off call arguments
+	addl	$8,%esp 
+
+	popl	%eax
+	popf
+	movl	%eax,%esp
+	popl	%eax
+	movl	$0,stack_overflowed
+	ret
+
+#warning stack check enabled
+#endif
+
 .data
 ENTRY(sys_call_table)
 	.long sys_ni_syscall	/* 0 - old "setup()" system call*/
diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
--- a/arch/i386/kernel/i386_ksyms.c	Thu Oct 31 11:13:28 2002
+++ b/arch/i386/kernel/i386_ksyms.c	Thu Oct 31 11:13:28 2002
@@ -211,3 +211,8 @@
 EXPORT_SYMBOL(edd);
 EXPORT_SYMBOL(eddnr);
 #endif
+
+#ifdef CONFIG_X86_STACK_CHECK
+extern void mcount(void);
+EXPORT_SYMBOL(mcount);
+#endif
diff -Nru a/arch/i386/kernel/init_task.c b/arch/i386/kernel/init_task.c
--- a/arch/i386/kernel/init_task.c	Thu Oct 31 11:13:28 2002
+++ b/arch/i386/kernel/init_task.c	Thu Oct 31 11:13:28 2002
@@ -16,6 +16,10 @@
 union thread_union init_irq_union
 	__attribute__((__section__(".data.init_task")));
 
+#ifdef CONFIG_X86_STACK_CHECK
+union thread_union stack_overflow_stack
+	__attribute__((__section__(".data.init_task")));
+#endif
 
 /*
  * Initial thread structure.
diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
--- a/arch/i386/kernel/process.c	Thu Oct 31 11:13:28 2002
+++ b/arch/i386/kernel/process.c	Thu Oct 31 11:13:28 2002
@@ -156,7 +156,25 @@
 
 __setup("idle=", idle_setup);
 
-void show_regs(struct pt_regs * regs)
+void stack_overflow(unsigned long esp, unsigned long eip)
+{
+	int panicing = ((esp&(THREAD_SIZE-1)) <= STACK_PANIC);
+
+	printk( "esp: 0x%x masked: 0x%x STACK_PANIC:0x%x %d %d\n", 
+		esp, (esp&(THREAD_SIZE-1)), STACK_PANIC, (((esp&(THREAD_SIZE-1)) <= STACK_PANIC)), panicing );
+	
+	if (panicing)
+		print_symbol("stack overflow from %s\n", eip);
+	else
+		print_symbol("excessive stack use from %s\n", eip);
+	printk("esp: %p\n", (void*)esp);
+	show_trace((void*)esp);
+	
+	if (panicing)
+		panic("stack overflow\n");
+}
+
+asmlinkage void show_regs(struct pt_regs * regs)
 {
 	unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
 
diff -Nru a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
--- a/include/asm-i386/thread_info.h	Thu Oct 31 11:13:28 2002
+++ b/include/asm-i386/thread_info.h	Thu Oct 31 11:13:28 2002
@@ -60,6 +60,8 @@
  */
 #define THREAD_ORDER 1 
 #define INIT_THREAD_SIZE       THREAD_SIZE
+#define STACK_PANIC		0x200ul
+#define STACK_WARN		((THREAD_SIZE)>>1)
 
 #ifndef __ASSEMBLY__
 #define INIT_THREAD_INFO(tsk)			\

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] (3/3) stack overflow checking for x86
  2002-10-31 19:20 ` [PATCH] (3/3) stack overflow checking " David C. Hansen
@ 2002-10-31 21:30   ` Dave Jones
  2002-10-31 22:08     ` David C. Hansen
  2002-11-01 12:59     ` Alan Cox
  0 siblings, 2 replies; 8+ messages in thread
From: Dave Jones @ 2002-10-31 21:30 UTC (permalink / raw)
  To: David C. Hansen; +Cc: Linus Torvalds, lkml

On Thu, Oct 31, 2002 at 11:20:52AM -0800, David C. Hansen wrote:
 > * stack checking (3/3)
 >    - use gcc's profiling features to check for stack overflows upon
 >      entry to functions.
 >    - Warn if the task goes over 4k.
 >    - Panic if the stack gets within 512 bytes of overflowing.
 >    - use kksymoops information, if available
 > 
 > This won't apply cleanly without the irqstack patch, but the conflict is
 > easy to resolve.  It requires the thread_info cleanup.

I'm wondering about interaction between this patch and the
already merged CONFIG_DEBUG_STACKOVERFLOW ?

		Dave

-- 
| Dave Jones.        http://www.codemonkey.org.uk

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] (3/3) stack overflow checking for x86
  2002-10-31 21:30   ` Dave Jones
@ 2002-10-31 22:08     ` David C. Hansen
  2002-11-01 12:59     ` Alan Cox
  1 sibling, 0 replies; 8+ messages in thread
From: David C. Hansen @ 2002-10-31 22:08 UTC (permalink / raw)
  To: Dave Jones; +Cc: Linus Torvalds, lkml

On Thu, 2002-10-31 at 13:30, Dave Jones wrote:
> On Thu, Oct 31, 2002 at 11:20:52AM -0800, David C. Hansen wrote:
>  > * stack checking (3/3)
>  >    - use gcc's profiling features to check for stack overflows upon
>  >      entry to functions.
>  >    - Warn if the task goes over 4k.
>  >    - Panic if the stack gets within 512 bytes of overflowing.
>  >    - use kksymoops information, if available
>  > 
>  > This won't apply cleanly without the irqstack patch, but the conflict is
>  > easy to resolve.  It requires the thread_info cleanup.
> 
> I'm wondering about interaction between this patch and the
> already merged CONFIG_DEBUG_STACKOVERFLOW ?

The currently merged one is very, very simple, but relatively worthless.
There are no guarantees about catching an overflow, especially if it
happens in a long call chain _after_ do_IRQ with interrupts disabled.  
Ben's version checks on entrance to every function, making it _much_
more likely to be caught, even during an interrupt.  But, the currently
merged one doesn't have any strange compiler requirements, like adding
the -p option.

The irq stack patch would make the current check pretty worthless
because the check happens just after the switch to a fresh irqstack
would have happened.

But, if they both get in, it can be cleaned up later because even if
both are turned on, nothing will blow up.  
-- 
Dave Hansen
haveblue@us.ibm.com


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] (3/3) stack overflow checking for x86
  2002-10-31 21:30   ` Dave Jones
  2002-10-31 22:08     ` David C. Hansen
@ 2002-11-01 12:59     ` Alan Cox
  2002-11-01 13:42       ` Dave Jones
  1 sibling, 1 reply; 8+ messages in thread
From: Alan Cox @ 2002-11-01 12:59 UTC (permalink / raw)
  To: Dave Jones; +Cc: David C. Hansen, Linus Torvalds, lkml

On Thu, 2002-10-31 at 21:30, Dave Jones wrote:
>  > This won't apply cleanly without the irqstack patch, but the conflict is
>  > easy to resolve.  It requires the thread_info cleanup.
> 
> I'm wondering about interaction between this patch and the
> already merged CONFIG_DEBUG_STACKOVERFLOW ?

It replaces it and actually makes it useful since IRQ usage is now
bounded and defined relative to non IRQ usage. Without IRQ stacks you
don't have a hope in hell of catching overflows that depend on an irq
occuring at the right moment


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] (3/3) stack overflow checking for x86
  2002-11-01 12:59     ` Alan Cox
@ 2002-11-01 13:42       ` Dave Jones
  0 siblings, 0 replies; 8+ messages in thread
From: Dave Jones @ 2002-11-01 13:42 UTC (permalink / raw)
  To: Alan Cox; +Cc: David C. Hansen, Linus Torvalds, lkml

On Fri, Nov 01, 2002 at 12:59:06PM +0000, Alan Cox wrote:
 > On Thu, 2002-10-31 at 21:30, Dave Jones wrote:
 > >  > This won't apply cleanly without the irqstack patch, but the conflict is
 > >  > easy to resolve.  It requires the thread_info cleanup.
 > > 
 > > I'm wondering about interaction between this patch and the
 > > already merged CONFIG_DEBUG_STACKOVERFLOW ?
 > 
 > It replaces it and actually makes it useful since IRQ usage is now
 > bounded and defined relative to non IRQ usage. Without IRQ stacks you
 > don't have a hope in hell of catching overflows that depend on an irq
 > occuring at the right moment

 Yeah, I figured it worked better, but wondered why the patch didn't
 remove the existing implementation.

		Dave

-- 
| Dave Jones.        http://www.codemonkey.org.uk

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2002-11-01 13:37 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-10-31 19:18 [PATCH] (1/3) cleanup thread info on x86 David C. Hansen
2002-10-31 19:20 ` [PATCH] (2/3) per-cpu interrupt stacks for x86 David C. Hansen
2002-10-31 19:20 ` [PATCH] (3/3) stack overflow checking " David C. Hansen
2002-10-31 21:30   ` Dave Jones
2002-10-31 22:08     ` David C. Hansen
2002-11-01 12:59     ` Alan Cox
2002-11-01 13:42       ` Dave Jones
  -- strict thread matches above, loose matches on Subject: below --
2002-10-18 22:07 [PATCH] (1/3) cleanup thread info on x86 Dave Hansen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox