Samuel Thibault, le Mon 25 Jun 2007 01:24:41 +0200, a écrit : > Samuel Thibault, le Sun 24 Jun 2007 21:29:50 +0200, a écrit : > > Samuel Thibault, le Sun 24 Jun 2007 17:51:25 +0200, a écrit : > > > I've uploaded some experimental TLS-enabled hurd and libc packages for > > > testing to > > > > > > http://dept-info.labri.fr/~thibault/debian-hurd/tls/ > > > > They need the gdt user_ldt.c update, so make sure to have gnumach >= > > 20070405. > > Note: though it works nicely on my box (I'm compiling glibc HEAD with it > right now), it looks like it fails completely on others (Thomas and > Olaf's at least), so please be careful :)
The problem I was having with Xen was when switch_ktss changes() the descriptors, because in an interrupt context, gs is still loaded with the user-level value. In january 2006, Jeroen made trap handlers load kernel data segments in fs and gs, here is a patch to do the same on interrupts (with it, I don't have issues on Xen any more). Could people try TLS with a patched gnumach? Note: there is still an issue with mach-defpager. Samuel
Index: i386/i386/db_interface.c =================================================================== RCS file: /cvsroot/hurd/gnumach/i386/i386/Attic/db_interface.c,v retrieving revision 1.2.2.3.2.1 diff -u -p -r1.2.2.3.2.1 db_interface.c --- i386/i386/db_interface.c 7 Jul 2007 17:21:19 -0000 1.2.2.3.2.1 +++ i386/i386/db_interface.c 8 Jul 2007 21:30:21 -0000 @@ -187,8 +187,6 @@ kdb_trap( * instead of those at its call to KDB. */ struct int_regs { - int gs; - int fs; int edi; int esi; int ebp; @@ -227,8 +225,8 @@ kdb_kentry( ddb_regs.edi = int_regs->edi; ddb_regs.ds = is->ds; ddb_regs.es = is->es; - ddb_regs.fs = int_regs->fs; - ddb_regs.gs = int_regs->gs; + ddb_regs.fs = is->fs; + ddb_regs.gs = is->gs; cnpollc(TRUE); db_task_trap(-1, 0, (ddb_regs.cs & 0x3) != 0); @@ -250,8 +248,8 @@ kdb_kentry( int_regs->edi = ddb_regs.edi; is->ds = ddb_regs.ds & 0xffff; is->es = ddb_regs.es & 0xffff; - int_regs->fs = ddb_regs.fs & 0xffff; - int_regs->gs = ddb_regs.gs & 0xffff; + is->fs = ddb_regs.fs & 0xffff; + is->gs = ddb_regs.gs & 0xffff; } #if NCPUS > 1 db_leave(); Index: i386/i386/kttd_interface.c =================================================================== RCS file: /cvsroot/hurd/gnumach/i386/i386/Attic/kttd_interface.c,v retrieving revision 1.2.2.3.2.1 diff -u -p -r1.2.2.3.2.1 kttd_interface.c --- i386/i386/kttd_interface.c 7 Jul 2007 17:21:19 -0000 1.2.2.3.2.1 +++ i386/i386/kttd_interface.c 8 Jul 2007 21:30:21 -0000 @@ -491,8 +491,6 @@ boolean_t kttd_trap(int type, int code, * instead of those at its call to KDB. */ struct int_regs { - int gs; - int fs; int edi; int esi; int ebp; @@ -541,8 +539,8 @@ kttd_netentry(int_regs) kttd_regs.edi = int_regs->edi; kttd_regs.ds = is->ds; kttd_regs.es = is->es; - kttd_regs.fs = int_regs->fs; - kttd_regs.gs = int_regs->gs; + kttd_regs.fs = is->fs; + kttd_regs.gs = is->gs; kttd_active++; kttd_task_trap(-1, 0, (kttd_regs.cs & 0x3) != 0); @@ -564,8 +562,8 @@ kttd_netentry(int_regs) int_regs->edi = kttd_regs.edi; is->ds = kttd_regs.ds & 0xffff; is->es = kttd_regs.es & 0xffff; - int_regs->fs = kttd_regs.fs & 0xffff; - int_regs->gs = kttd_regs.gs & 0xffff; + is->fs = kttd_regs.fs & 0xffff; + is->gs = kttd_regs.gs & 0xffff; if (kttd_run_status == RUNNING) printf("kttd_netentry: %%%%% run_status already RUNNING! %%%%%\n"); Index: i386/i386/locore.S =================================================================== RCS file: /cvsroot/hurd/gnumach/i386/i386/locore.S,v retrieving revision 1.6.2.7.2.3 diff -u -p -r1.6.2.7.2.3 locore.S --- i386/i386/locore.S 7 May 2007 22:54:50 -0000 1.6.2.7.2.3 +++ i386/i386/locore.S 8 Jul 2007 21:30:21 -0000 @@ -646,9 +646,13 @@ ENTRY(all_intrs) pushl %ds /* save segment registers */ pushl %es + pushl %fs + pushl %gs mov %ss,%dx /* switch to kernel segments */ mov %dx,%ds mov %dx,%es + mov %dx,%fs + mov %dx,%gs CPU_NUMBER(%edx) @@ -686,7 +690,9 @@ LEXT(return_to_iret) /* ( label for kd cmpl $0,CX(EXT(need_ast),%edx) jnz ast_from_interrupt /* take it if so */ 1: - pop %es /* restore segment regs */ + pop %gs /* restore segment regs */ + pop %fs + pop %es pop %ds pop %edx pop %ecx @@ -704,11 +710,13 @@ _return_to_iret_i: /* ( label for kdb_ /* * Take an AST from an interrupt. * On PCB stack. - * sp-> es -> edx - * ds -> ecx - * edx -> eax - * ecx -> trapno - * eax -> code + * sp-> gs -> edx + * fs -> ecx + * es -> eax + * ds -> trapno + * edx -> code + * ecx + * eax * eip * cs * efl @@ -716,7 +724,9 @@ _return_to_iret_i: /* ( label for kdb_ * ss */ ast_from_interrupt: - pop %es /* restore all registers ... */ + pop %gs /* restore all registers ... */ + pop %fs + pop %es pop %ds popl %edx popl %ecx @@ -731,6 +741,8 @@ ast_from_interrupt: mov %ss,%dx /* switch to kernel segments */ mov %dx,%ds mov %dx,%es + mov %dx,%fs + mov %dx,%gs CPU_NUMBER(%edx) TIME_TRAP_UENTRY @@ -768,7 +780,9 @@ ast_from_interrupt: * pointer to save area on old stack * [ saved %ebx, if accurate timing ] * - * old stack: saved %es + * old stack: saved %gs + * saved %fs + * saved %es * saved %ds * saved %edx * saved %ecx @@ -820,14 +834,10 @@ kdb_from_iret: pushl %ebp pushl %esi pushl %edi - push %fs - push %gs pushl %esp /* pass regs */ call EXT(kdb_kentry) /* to kdb */ addl $4,%esp /* pop parameters */ - pop %gs /* restore registers */ - pop %fs - popl %edi + popl %edi /* restore registers */ popl %esi popl %ebp #if STAT_TIME @@ -906,14 +916,10 @@ ttd_from_iret: pushl %ebp pushl %esi pushl %edi - push %fs - push %gs pushl %esp /* pass regs */ call _kttd_netentry /* to kdb */ addl $4,%esp /* pop parameters */ - pop %gs /* restore registers */ - pop %fs - popl %edi + popl %edi /* restore registers */ popl %esi popl %ebp #if STAT_TIME Index: i386/i386/thread.h =================================================================== RCS file: /cvsroot/hurd/gnumach/i386/i386/thread.h,v retrieving revision 1.3.2.1.2.1 diff -u -p -r1.3.2.1.2.1 thread.h --- i386/i386/thread.h 7 May 2007 22:54:50 -0000 1.3.2.1.2.1 +++ i386/i386/thread.h 8 Jul 2007 21:30:21 -0000 @@ -139,6 +139,8 @@ struct v86_assist_state { */ struct i386_interrupt_state { + int gs; + int fs; int es; int ds; int edx; Index: linux/src/include/asm-i386/irq.h =================================================================== RCS file: /cvsroot/hurd/gnumach/linux/src/include/asm-i386/Attic/irq.h,v retrieving revision 1.1 diff -u -p -r1.1 irq.h --- linux/src/include/asm-i386/irq.h 26 Apr 1999 05:55:48 -0000 1.1 +++ linux/src/include/asm-i386/irq.h 8 Jul 2007 21:30:21 -0000 @@ -38,6 +38,7 @@ extern void enable_irq(unsigned int); "movl $" STR(KERNEL_DS) ",%edx\n\t" \ "mov %dx,%ds\n\t" \ "mov %dx,%es\n\t" \ + "mov %dx,%gs\n\t" \ "movl $" STR(USER_DS) ",%edx\n\t" \ "mov %dx,%fs\n\t" \ "movl $0,%edx\n\t" \