From: Zwane Mwaikambo The 4/4 code right now is setup for 8k stacks, this patch should allow for arbitrary stack sizes. Some parts are rather ugly (e.g. STACK_PAGE_COUNT) so (abusive too) comments are welcome. I've tested it with 4k,8k and 16k stacks on UP and SMP, but i believe it diff -upN reference/arch/i386/kernel/entry_trampoline.c current/arch/i386/kernel/entry_trampoline.c --- reference/arch/i386/kernel/entry_trampoline.c 2004-04-29 10:39:15.000000000 -0700 +++ current/arch/i386/kernel/entry_trampoline.c 2004-04-29 10:39:17.000000000 -0700 @@ -21,7 +21,9 @@ extern char __entry_tramp_start, __entry void __init init_entry_mappings(void) { #ifdef CONFIG_X86_HIGH_ENTRY + void *tramp; + int p; /* * We need a high IDT and GDT for the 4G/4G split: @@ -37,7 +39,7 @@ void __init init_entry_mappings(void) /* * Virtual kernel stack: */ - BUG_ON(__kmap_atomic_vaddr(KM_VSTACK0) & (THREAD_SIZE-1)); + BUG_ON(__kmap_atomic_vaddr(KM_VSTACK_TOP) & (THREAD_SIZE-1)); BUG_ON(sizeof(struct desc_struct)*NR_CPUS*GDT_ENTRIES > 2*PAGE_SIZE); BUG_ON((unsigned int)&__entry_tramp_end - (unsigned int)&__entry_tramp_start > 2*PAGE_SIZE); @@ -45,15 +47,15 @@ void __init init_entry_mappings(void) * set up the initial thread's virtual stack related * fields: */ - current->thread.stack_page0 = virt_to_page((char *)current->thread_info); - current->thread.stack_page1 = virt_to_page((char *)current->thread_info + PAGE_SIZE); - current->thread_info->virtual_stack = (void *)__kmap_atomic_vaddr(KM_VSTACK0); - - __kunmap_atomic_type(KM_VSTACK0); - __kunmap_atomic_type(KM_VSTACK1); - __kmap_atomic(current->thread.stack_page0, KM_VSTACK0); - __kmap_atomic(current->thread.stack_page1, KM_VSTACK1); + for (p = 0; p < ARRAY_SIZE(current->thread.stack_page); p++) + current->thread.stack_page[p] = virt_to_page((char *)current->thread_info + (p*PAGE_SIZE)); + + current->thread_info->virtual_stack = (void *)__kmap_atomic_vaddr(KM_VSTACK_TOP); + for (p = 0; p < ARRAY_SIZE(current->thread.stack_page); p++) { + __kunmap_atomic_type(KM_VSTACK_TOP-p); + __kmap_atomic(current->thread.stack_page[p], KM_VSTACK_TOP-p); + } #endif current->thread_info->real_stack = (void *)current->thread_info; current->thread_info->user_pgd = NULL; diff -upN reference/arch/i386/kernel/process.c current/arch/i386/kernel/process.c --- reference/arch/i386/kernel/process.c 2004-04-29 10:39:15.000000000 -0700 +++ current/arch/i386/kernel/process.c 2004-04-29 10:39:17.000000000 -0700 @@ -345,7 +345,7 @@ int copy_thread(int nr, unsigned long cl { struct pt_regs * childregs; struct task_struct *tsk; - int err; + int err, i; childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; struct_cpy(childregs, regs); @@ -360,10 +360,11 @@ int copy_thread(int nr, unsigned long cl * get the two stack pages, for the virtual stack. * * IMPORTANT: this code relies on the fact that the task - * structure is an 8K aligned piece of physical memory. + * structure is an THREAD_SIZE aligned piece of physical memory. */ - p->thread.stack_page0 = virt_to_page((unsigned long)p->thread_info); - p->thread.stack_page1 = virt_to_page((unsigned long)p->thread_info + PAGE_SIZE); + for (i = 0; i < ARRAY_SIZE(p->thread.stack_page); i++) + p->thread.stack_page[i] = + virt_to_page((unsigned long)p->thread_info + (i*PAGE_SIZE)); p->thread.eip = (unsigned long) ret_from_fork; p->thread_info->real_stack = p->thread_info; @@ -519,22 +520,23 @@ struct task_struct fastcall * __switch_t __unlazy_fpu(prev_p); #ifdef CONFIG_X86_HIGH_ENTRY +{ + int i; /* * Set the ptes of the virtual stack. (NOTE: a one-page TLB flush is * needed because otherwise NMIs could interrupt the * user-return code with a virtual stack and stale TLBs.) */ - __kunmap_atomic_type(KM_VSTACK0); - __kunmap_atomic_type(KM_VSTACK1); - __kmap_atomic(next->stack_page0, KM_VSTACK0); - __kmap_atomic(next->stack_page1, KM_VSTACK1); - + for (i = 0; i < ARRAY_SIZE(next->stack_page); i++) { + __kunmap_atomic_type(KM_VSTACK_TOP-i); + __kmap_atomic(next->stack_page[i], KM_VSTACK_TOP-i); + } /* * NOTE: here we rely on the task being the stack as well */ next_p->thread_info->virtual_stack = - (void *)__kmap_atomic_vaddr(KM_VSTACK0); - + (void *)__kmap_atomic_vaddr(KM_VSTACK_TOP); +} #if defined(CONFIG_PREEMPT) && defined(CONFIG_SMP) /* * If next was preempted on entry from userspace to kernel, diff -upN reference/include/asm-i386/fixmap.h current/include/asm-i386/fixmap.h --- reference/include/asm-i386/fixmap.h 2004-04-29 10:39:15.000000000 -0700 +++ current/include/asm-i386/fixmap.h 2004-04-29 10:39:17.000000000 -0700 @@ -115,10 +115,10 @@ extern void __set_fixmap (enum fixed_add * Leave one empty page between vmalloc'ed areas and * the start of the fixmap. * - * IMPORTANT: dont change FIXADDR_TOP without adjusting KM_VSTACK0 - * and KM_VSTACK1 so that the virtual stack is 8K aligned. + * IMPORTANT: we have to align FIXADDR_TOP so that the virtual stack + * is THREAD_SIZE aligned. */ -#define FIXADDR_TOP (0xffffe000UL) +#define FIXADDR_TOP (0xffffe000UL & ~(THREAD_SIZE-1)) #define __FIXADDR_SIZE (__end_of_permanent_fixed_addresses << PAGE_SHIFT) #define FIXADDR_START (FIXADDR_TOP - __FIXADDR_SIZE) diff -upN reference/include/asm-i386/kmap_types.h current/include/asm-i386/kmap_types.h --- reference/include/asm-i386/kmap_types.h 2004-04-29 10:39:15.000000000 -0700 +++ current/include/asm-i386/kmap_types.h 2004-04-29 10:39:17.000000000 -0700 @@ -2,15 +2,16 @@ #define _ASM_KMAP_TYPES_H #include +#include enum km_type { /* - * IMPORTANT: don't move these 3 entries, and only add entries in - * pairs: the 4G/4G virtual stack must be 8K aligned on each cpu. + * IMPORTANT: don't move these 3 entries, be wary when adding entries, + * the 4G/4G virtual stack must be THREAD_SIZE aligned on each cpu. */ KM_BOUNCE_READ, - KM_VSTACK1, - KM_VSTACK0, + KM_VSTACK_BASE, + KM_VSTACK_TOP = KM_VSTACK_BASE + STACK_PAGE_COUNT-1, KM_LDT_PAGE15, KM_LDT_PAGE0 = KM_LDT_PAGE15 + 16-1, @@ -30,8 +31,8 @@ enum km_type { KM_SOFTIRQ1, KM_FILLER, /* - * Add new entries in pairs: - * the 4G/4G virtual stack must be 8K aligned on each cpu. + * Be wary when adding entries: + * the 4G/4G virtual stack must be THREAD_SIZE aligned on each cpu. */ KM_TYPE_NR }; diff -upN reference/include/asm-i386/processor.h current/include/asm-i386/processor.h --- reference/include/asm-i386/processor.h 2004-04-29 10:39:15.000000000 -0700 +++ current/include/asm-i386/processor.h 2004-04-29 10:39:17.000000000 -0700 @@ -398,10 +398,16 @@ struct tss_struct { unsigned long stack[64]; } __attribute__((packed)); +#ifdef CONFIG_4KSTACKS +#define STACK_PAGE_COUNT (4096/PAGE_SIZE) +#else +#define STACK_PAGE_COUNT (8192/PAGE_SIZE) /* THREAD_SIZE/PAGE_SIZE */ +#endif + struct thread_struct { /* cached TLS descriptors. */ struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES]; - void *stack_page0, *stack_page1; + void *stack_page[STACK_PAGE_COUNT]; unsigned long esp0; unsigned long sysenter_cs; unsigned long eip; diff -upN reference/include/asm-i386/thread_info.h current/include/asm-i386/thread_info.h --- reference/include/asm-i386/thread_info.h 2004-04-29 10:39:15.000000000 -0700 +++ current/include/asm-i386/thread_info.h 2004-04-29 10:39:17.000000000 -0700 @@ -49,8 +49,10 @@ struct thread_info { #endif #define PREEMPT_ACTIVE 0x4000000 + +/* if you change THREAD_SIZE here, don't forget to change STACK_PAGE_COUNT */ #ifdef CONFIG_4KSTACKS -#define THREAD_SIZE (4096) +#define THREAD_SIZE (4096) #else #define THREAD_SIZE (8192) #endif