jkim at FreeBSD.org
Mon Oct 8 12:59:49 PDT 2007
On Monday 08 October 2007 02:35 pm, Mihai Donțu wrote:
> I have a "small" amd64 program that makes havy use of LDT (%GS to
> be more specific). The trouble is, in a multithreaded environment,
> the selector value gets lost (or reset?).
> The code *always* segfaults with this stack:
> 4 LWP 100126 0x0000000800dec07c in select () from /lib/libc.so.6
> * 3 Thread 0x517000 (runnable) 0x000000080055cfbc in ?? ()
> 2 Thread 0x517400 (LWP 100125) 0x0000000800c0d85c in
> pthread_testcancel () from /lib/libpthread.so.2 1 Thread 0x517800
> (runnable) 0x0000000800d5d000 in makecontext () from
> at this instruction:
> 0x000000080055cfbc: mov %gs:0x10,%r11
> (gdb) p $gs
> $1 = 0
> I've been reading on the net something about the kernel not
> preserving the GS across syscalls (or stmh). Is this true? and if
> so, is there a known workaround?
> I'm on a FreeBSD 6.2-STABLE-200706 (AMD64) machine.
Yes, you are correct. A short version is "don't do that". A long
version goes like this. %fs and %gs are not preserved while context
switching on amd64. In fact, you should not use amd64_set_gsbase()
directly. If you *really* have to mess up with base addresses, you
have to use sysarch(2) syscall, i.e., sysarch(AMD64_SET_GSBASE,
args). However, it only changes the base address via MSR, i.e., %gs
itself has no meaning.
More information about the freebsd-questions