From: Anders E. C \(KI/EAB\) <and...@er...> - 2006-08-25 16:46:11
|
Hi Wang, =20 There're really nothing magical to it. =20 I took the big kernel diff and split it up in feature chunks and started to use quilt to manage them. (Henry uses quilt these days too..) =20 Then I've got myself a copy of git (the version management tool used by the kernel devels), and merge the colinux patch to each version resolving issues as they arise. Usin git means that you can pinpoint the exact commit to the kernel source which cause a problem for colinux, thus increasing the information you have available when cooking up changes. =20 Right now I'm addressing a problem in 2.6.16-rc4 with GDT handling, and git-isect has identified this commit as the thing that causes w2k to reboot immediately: =20 2b932f6cf052920fb3a6281499e08209b08f5086 is first bad commit commit 2b932f6cf052920fb3a6281499e08209b08f5086 Author: James Bottomley <James.Bottomley@SteelEye.com> Date: Fri Feb 24 13:04:14 2006 -0800 =20 [PATCH] x86: fix broken SMP boot sequence =20 Recent GDT changes broke the SMP boot sequence if the booting CPU is numbered anything other than zero. There's also a subtle source of error in that the boot time CPU now uses cpu_gdt_table (which is actually the GDT for booting CPUs in head.S). This patch fixes both problems by making GDT descriptors themselves allocated from a per_cpu area and switching to them in cpu_init(), which now means that cpu_gdt_table is exclusively used for booting CPUs again. =20 Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com> Cc: Zachary Amsden <za...@vm...> Cc: Matt Tolentino <met...@sn...> Signed-off-by: Andrew Morton <ak...@os...> Signed-off-by: Linus Torvalds <tor...@os...> =20 :040000 040000 df9714527dfeb229d1d476adff92a6d5124d8cc6 223e49e8300b3f972713d10ea1c97c94cb7bfd76 M arch :040000 040000 b3a802e3dba3091e446a472b6e0a7393560327ec 14b42476ee5714fa1968ed192a1d1c9bd70e2124 M include =20 =20 That particular commit, in patch form, looks like: =20 ~/src/colinux-devel/build/linux-git $ git-diff-tree -p 2b932f6cf052920fb3a6281499e08209b08f5086=20 2b932f6cf052920fb3a6281499e08209b08f5086 diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 7eb9213..4ecd4b3 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -4,6 +4,7 @@ #include <linux/delay.h> #include <linux/smp.h> #include <linux/module.h> #include <linux/percpu.h> +#include <linux/bootmem.h> #include <asm/semaphore.h> #include <asm/processor.h> #include <asm/i387.h> @@ -18,6 +19,9 @@ #endif =20 #include "cpu.h" =20 +DEFINE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr); +EXPORT_PER_CPU_SYMBOL(cpu_gdt_descr); + DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]); EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack); =20 @@ -571,8 +575,9 @@ void __devinit cpu_init(void) int cpu =3D smp_processor_id(); struct tss_struct * t =3D &per_cpu(init_tss, cpu); struct thread_struct *thread =3D ¤t->thread; - struct desc_struct *gdt =3D get_cpu_gdt_table(cpu); + struct desc_struct *gdt; __u32 stk16_off =3D (__u32)&per_cpu(cpu_16bit_stack, cpu); + struct Xgt_desc_struct *cpu_gdt_descr =3D = &per_cpu(cpu_gdt_descr, cpu); =20 if (cpu_test_and_set(cpu, cpu_initialized)) { printk(KERN_WARNING "CPU#%d already initialized!\n", cpu); @@ -590,6 +595,25 @@ void __devinit cpu_init(void) } =20 /* + * This is a horrible hack to allocate the GDT. The problem + * is that cpu_init() is called really early for the boot CPU + * (and hence needs bootmem) but much later for the secondary + * CPUs, when bootmem will have gone away + */ + if (NODE_DATA(0)->bdata->node_bootmem_map) { + gdt =3D (struct desc_struct *)alloc_bootmem_pages(PAGE_SIZE); + /* alloc_bootmem_pages panics on failure, so no check */ + memset(gdt, 0, PAGE_SIZE); + } else { + gdt =3D (struct desc_struct = *)get_zeroed_page(GFP_KERNEL); + if (unlikely(!gdt)) { + printk(KERN_CRIT "CPU%d failed to allocate GDT\n", cpu); + for (;;) + local_irq_enable(); + } + } + + /* * Initialize the per-CPU GDT with the boot GDT, * and set up the GDT descriptor: */ @@ -601,10 +625,10 @@ void __devinit cpu_init(void) ((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) | (CPU_16BIT_STACK_SIZE - 1); =20 - cpu_gdt_descr[cpu].size =3D GDT_SIZE - 1; - cpu_gdt_descr[cpu].address =3D (unsigned long)gdt; + cpu_gdt_descr->size =3D GDT_SIZE - 1; + cpu_gdt_descr->address =3D (unsigned long)gdt; =20 - load_gdt(&cpu_gdt_descr[cpu]); + load_gdt(cpu_gdt_descr); load_idt(&idt_descr); =20 /* diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c index ecad519..e3e42fd 100644 --- a/arch/i386/kernel/efi.c +++ b/arch/i386/kernel/efi.c @@ -103,17 +103,19 @@ static void efi_call_phys_prelog(void) */ local_flush_tlb(); =20 - cpu_gdt_descr[0].address =3D __pa(cpu_gdt_descr[0].address); - load_gdt((struct Xgt_desc_struct *) __pa(&cpu_gdt_descr[0])); + per_cpu(cpu_gdt_descr, 0).address =3D + __pa(per_cpu(cpu_gdt_descr, 0).address); + load_gdt((struct Xgt_desc_struct *)__pa(&per_cpu(cpu_gdt_descr, 0))); } =20 static void efi_call_phys_epilog(void) { unsigned long cr4; =20 - cpu_gdt_descr[0].address =3D - (unsigned long) __va(cpu_gdt_descr[0].address); - load_gdt(&cpu_gdt_descr[0]); + per_cpu(cpu_gdt_descr, 0).address =3D + (unsigned long)__va(per_cpu(cpu_gdt_descr, 0).address); + load_gdt((struct Xgt_desc_struct *)__va(&per_cpu(cpu_gdt_descr, 0))); + cr4 =3D read_cr4(); =20 if (cr4 & X86_CR4_PSE) { diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index 2bee649..e0b7c63 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -534,5 +534,3 @@ ENTRY(cpu_gdt_table) .quad 0x0000000000000000 /* 0xf0 - unused */ .quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */ =20 - /* Be sure this is zeroed to avoid false validations in Xen */ - .fill PAGE_SIZE_asm / 8 - GDT_ENTRIES,8,0 diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c index 3999bec..0553250 100644 --- a/arch/i386/kernel/i386_ksyms.c +++ b/arch/i386/kernel/i386_ksyms.c @@ -3,8 +3,6 @@ #include <linux/module.h> #include <asm/checksum.h> #include <asm/desc.h> =20 -EXPORT_SYMBOL_GPL(cpu_gdt_descr); - EXPORT_SYMBOL(__down_failed); EXPORT_SYMBOL(__down_failed_interruptible); EXPORT_SYMBOL(__down_failed_trylock); diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index fb00ab7..eba7f53 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -898,12 +898,6 @@ static int __devinit do_boot_cpu(int api unsigned long start_eip; unsigned short nmi_high =3D 0, nmi_low =3D 0; =20 - if (!cpu_gdt_descr[cpu].address && - !(cpu_gdt_descr[cpu].address =3D = get_zeroed_page(GFP_KERNEL))) { - printk("Failed to allocate GDT for CPU %d\n", cpu); - return 1; - } - ++cpucount; =20 /* diff --git a/include/asm-i386/desc.h b/include/asm-i386/desc.h index 494e73b..89b8b82 100644 --- a/include/asm-i386/desc.h +++ b/include/asm-i386/desc.h @@ -24,11 +24,13 @@ struct Xgt_desc_struct { unsigned short pad; } __attribute__ ((packed)); =20 -extern struct Xgt_desc_struct idt_descr, cpu_gdt_descr[NR_CPUS]; +extern struct Xgt_desc_struct idt_descr; +DECLARE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr); + =20 static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu) { - return ((struct desc_struct *)cpu_gdt_descr[cpu].address); + return (struct desc_struct *)per_cpu(cpu_gdt_descr, cpu).address; } =20 #define load_TR_desc() __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8)) =20 So, now I'm considering what on earth happened with the cpu_gdt_descr stuff, and how we can get around it. I still don't have a grip on all the memory handling stuff, and I was planning on getting clued up on that after we got to -current. =20 Ideas? =20 Cheers, /Anders =20 ________________________________ From: wang lianwei [mailto:lia...@gm...]=20 Sent: den 24 augusti 2006 14:34 To: Anders Eriksson C (KI/EAB) Cc: Cooperative Linux Development; Henry Nestler Subject: Re: [coLinux-devel] 1st take at 2.6.{13,14,15} =09 =09 Hi Anders, =20 You do a greak work, and it is more useful if you can give a document about how to do this work.=20 =09 =20 2006/7/24, Anders Eriksson C (KI/EAB) <and...@er...>:=20 Hi all, =09 Working with Henry, I've taken a stab at moving the kernel forward in a step-by-step manner and made some=20 progress. If we could get some more devel attention to this effort, the chances of actually getting to -current in a timely manner would grow significantly. So, the more eyeballs the better! =09 There are patches for 2.6.{13,14,15} at http://www.henrynestler.com/colinux/patches/devel/ =09 Status: =09 2.6.13 Used for a couple of weeks with no issues. =09 2.6.14=20 Completed yesterday, and just BSODed on me with a PAGE FAULT IN UNPAGED AREA message during an rsync run. =09 2.6.15 Completed today, but my gentoo userland doesn't populate /dev/* at all with this kernel so the=20 boot process hangs at fsck / =09 I'm mostly offline for the coming weeks, but if we could get some developer attention and comments/fixes to the list that would be much appreciated... =09 /Anders =09 =09 ------------------------------------------------------------------------ -=20 Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys -- and earn cash =09 http://www.techsay.com/default.php?page=3Djoin.php&p=3Dsourceforge&CID=3D= DEVDE V _______________________________________________ coLinux-devel mailing list coL...@li... =09 https://lists.sourceforge.net/lists/listinfo/colinux-devel =09 |