thread_info and kernel mode stack

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,
I am trying to work in a special configuration where the thread_info is
above the stack pointer. The SP though, start from the 
base stack address + THREAD_SIZE - THREAD_INFO_SECTION_SIZE (that is 128
bytes). 
The INIT_TSS macro looks like:
.esp0           = sizeof(init_stack)-THREAD_INFO_SECTION_SIZE +
(long)&init_stack,      \
So far it works.


When I am trying to move the init_thread_info to the top of the stack
the computer restart itself. What I am doing is replacing the union of
the init_thread_info with the following structure:

-union thread_union {
-        struct thread_info thread_info;
-        unsigned long stack[THREAD_SIZE/sizeof(long)];
-};

+struct thread_union {
+unsigned stack[(THREAD_SIZE-THREAD_INFO_SECTION_SIZE)/sizeof(long)];
+        struct thread_info thread_info;
+};

it means that when I am referencing the thread_info it is in offset
(THREAD_SIZE-THREAD_INFO_SECTION_SIZE)/sizeof(long) and not the base
address as it was when declared with a union.

I have changed other relevant places as in fork.c and so, although the
computer even doesn't start, I think its related to the init thread.
any clues?

-- 
Eliad
diff -urNp linux-2.6.9.orig/arch/i386/kernel/head.S linux-2.6.9.changes/arch/i386/kernel/head.S
--- linux-2.6.9.orig/arch/i386/kernel/head.S	2004-10-18 23:53:13.000000000 +0200
+++ linux-2.6.9.changes/arch/i386/kernel/head.S	2005-07-26 15:42:20.000000000 +0300
@@ -425,7 +425,7 @@ ENTRY(empty_zero_page)
 .data
 
 ENTRY(stack_start)
-	.long init_thread_union+THREAD_SIZE
+        .long init_thread_union+THREAD_SIZE-THREAD_INFO_SECTION_SIZE
 	.long __BOOT_DS
 
 ready:	.byte 0
diff -urNp linux-2.6.9.orig/arch/i386/kernel/init_task.c linux-2.6.9.changes/arch/i386/kernel/init_task.c
--- linux-2.6.9.orig/arch/i386/kernel/init_task.c	2004-10-18 23:55:28.000000000 +0200
+++ linux-2.6.9.changes/arch/i386/kernel/init_task.c	2005-07-26 22:56:29.036709328 +0300
@@ -25,9 +25,7 @@ EXPORT_SYMBOL(init_mm);
  * way process stacks are handled. This is done by having a special
  * "init_task" linker map entry..
  */
-union thread_union init_thread_union 
-	__attribute__((__section__(".data.init_task"))) =
-		{ INIT_THREAD_INFO(init_task) };
+struct thread_union init_thread_union = { {0}, INIT_THREAD_INFO(init_task) };
 
 /*
  * Initial task structure.
diff -urNp linux-2.6.9.orig/arch/i386/kernel/process.c linux-2.6.9.changes/arch/i386/kernel/process.c
--- linux-2.6.9.orig/arch/i386/kernel/process.c	2004-10-18 23:53:05.000000000 +0200
+++ linux-2.6.9.changes/arch/i386/kernel/process.c	2005-07-26 22:55:42.853730208 +0300
@@ -364,7 +364,7 @@ int copy_thread(int nr, unsigned long cl
 	struct task_struct *tsk;
 	int err;
 
-	childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
+        childregs = ((struct pt_regs *) ((THREAD_SIZE-THREAD_INFO_SECTION_SIZE) + (unsigned long) p->thread_info)) - 1;
 	*childregs = *regs;
 	childregs->eax = 0;
 	childregs->esp = esp;
@@ -665,8 +665,8 @@ out:
 	return error;
 }
 
-#define top_esp                (THREAD_SIZE - sizeof(unsigned long))
-#define top_ebp                (THREAD_SIZE - 2*sizeof(unsigned long))
+#define top_esp                ((THREAD_SIZE-THREAD_INFO_SECTION_SIZE) - sizeof(unsigned long))
+#define top_ebp                ((THREAD_SIZE-THREAD_INFO_SECTION_SIZE) - 2*sizeof(unsigned long))
 
 unsigned long get_wchan(struct task_struct *p)
 {
diff -urNp linux-2.6.9.orig/drivers/char/ip2main.c linux-2.6.9.changes/drivers/char/ip2main.c
--- linux-2.6.9.orig/drivers/char/ip2main.c	2004-10-18 23:55:36.000000000 +0200
+++ linux-2.6.9.changes/drivers/char/ip2main.c	2004-10-18 23:55:36.000000000 +0200
@@ -1179,7 +1179,7 @@ ip2_interrupt_bh(i2eBordStrPtr pB)
 /* Parameters: irq - interrupt number                                         */
 /*             pointer to optional device ID structure                        */
 /*             pointer to register structure                                  */
-/* Returns:    Nothing              $                                         */
+/* Returns:    Nothing                                                        */
 /*                                                                            */
 /* Description:                                                               */
 /*                                                                            */
diff -urNp linux-2.6.9.orig/include/asm-i386/processor.h linux-2.6.9.changes/include/asm-i386/processor.h
--- linux-2.6.9.orig/include/asm-i386/processor.h	2004-10-18 23:53:07.000000000 +0200
+++ linux-2.6.9.changes/include/asm-i386/processor.h	2005-07-26 15:43:30.000000000 +0300
@@ -450,7 +450,7 @@ struct thread_struct {
  * be within the limit.
  */
 #define INIT_TSS  {							\
-	.esp0		= sizeof(init_stack) + (long)&init_stack,	\
+	.esp0		= sizeof(init_stack)-THREAD_INFO_SECTION_SIZE + (long)&init_stack,	\
 	.ss0		= __KERNEL_DS,					\
 	.ss1		= __KERNEL_CS,					\
 	.ldt		= GDT_ENTRY_LDT,				\
diff -urNp linux-2.6.9.orig/include/asm-i386/thread_info.h linux-2.6.9.changes/include/asm-i386/thread_info.h
--- linux-2.6.9.orig/include/asm-i386/thread_info.h	2004-10-18 23:53:21.000000000 +0200
+++ linux-2.6.9.changes/include/asm-i386/thread_info.h	2005-07-26 23:08:59.000000000 +0300
@@ -51,11 +51,13 @@ struct thread_info {
 
 #endif
 
+#define THREAD_INFO_SECTION_SIZE	128
+
 #define PREEMPT_ACTIVE		0x4000000
 #ifdef CONFIG_4KSTACKS
 #define THREAD_SIZE            (4096)
 #else
-#define THREAD_SIZE		(8192)
+#define THREAD_SIZE		(4096)
 #endif
 
 #define STACK_WARN             (THREAD_SIZE/8)
@@ -88,6 +90,7 @@ static inline struct thread_info *curren
 {
 	struct thread_info *ti;
 	__asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~(THREAD_SIZE - 1)));
+	ti = (struct thread_info *)((char*)(ti)+(THREAD_SIZE-THREAD_INFO_SECTION_SIZE));
 	return ti;
 }
 
diff -urNp linux-2.6.9.orig/include/linux/sched.h linux-2.6.9.changes/include/linux/sched.h
--- linux-2.6.9.orig/include/linux/sched.h	2004-10-18 23:53:13.000000000 +0200
+++ linux-2.6.9.changes/include/linux/sched.h	2005-07-26 23:07:30.000000000 +0300
@@ -654,9 +654,9 @@ void yield(void);
  */
 extern struct exec_domain	default_exec_domain;
 
-union thread_union {
+struct thread_union {
+	unsigned long stack[(THREAD_SIZE-THREAD_INFO_SECTION_SIZE)/sizeof(long)];
 	struct thread_info thread_info;
-	unsigned long stack[THREAD_SIZE/sizeof(long)];
 };
 
 #ifndef __HAVE_ARCH_KSTACK_END
@@ -669,7 +669,7 @@ static inline int kstack_end(void *addr)
 }
 #endif
 
-extern union thread_union init_thread_union;
+extern struct thread_union init_thread_union;
 extern struct task_struct init_task;
 
 extern struct   mm_struct init_mm;
diff -urNp linux-2.6.9.orig/kernel/fork.c linux-2.6.9.changes/kernel/fork.c
--- linux-2.6.9.orig/kernel/fork.c	2004-10-18 23:53:13.000000000 +0200
+++ linux-2.6.9.changes/kernel/fork.c	2005-07-26 23:06:24.000000000 +0300
@@ -79,7 +79,9 @@ static kmem_cache_t *task_struct_cachep;
 
 void free_task(struct task_struct *tsk)
 {
-	free_thread_info(tsk->thread_info);
+	void * tmp = (void*)(tsk->thread_info);
+	tmp -= (THREAD_SIZE - THREAD_INFO_SECTION_SIZE);
+	free_thread_info(tmp);
 	free_task_struct(tsk);
 }
 EXPORT_SYMBOL(free_task);
@@ -270,6 +272,8 @@ static struct task_struct *dup_task_stru
 		return NULL;
 	}
 
+        ti = (struct thread_info*)((char*)ti + (THREAD_SIZE-THREAD_INFO_SECTION_SIZE));
+
 	*ti = *orig->thread_info;
 	*tsk = *orig;
 	tsk->thread_info = ti;

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]
  Powered by Linux