Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 9 Oct 2007 01:00:58 +0300
From:      Mihai =?utf-8?q?Don=C8=9Bu?= <mihai.dontu@gmail.com>
To:        Jung-uk Kim <jkim@freebsd.org>
Cc:        freebsd-emulation@freebsd.org, freebsd-questions@freebsd.org
Subject:   Re: amd64_set_gsbase()
Message-ID:  <200710090100.58577.mihai.dontu@gmail.com>
In-Reply-To: <200710081537.03836.jkim@FreeBSD.org>
References:  <200710082135.58099.mihai.dontu@gmail.com> <200710081537.03836.jkim@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Monday 08 October 2007, Jung-uk Kim wrote:
> 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.

But this makes emulation software such as Wine a lost hope, doesn't it?
Because Windows apps access the Thread Information Block (TIB) via %gs
(%fs on ia32).

Anyway, my so called "small" program is actually a Win64 emulator and
I need the segment selector to "stay put" across syscalls. It works
like a charm on single threaded apps, but as soon as I spawn a thread,
all hell breaks loose :)

I've managed to come up with something that *kind of* works. It goes
like this:

void my_handler( int s )
{
    if ( s == SIGSEGV ) {
        if ( get_gs() == 0 ) {
            amd64_set_gsbase();
        } else {
            signal( SIGSEGV, SIG_DFL );
        }
    }
}

int my_init( void )
{
    /* alloc TIB memory and initialize */

    amd64_set_gsbase( lpTIB );
    signal( SIGSEGV, my_handler );

    return 0;
}

but after a series of dlopen()-s, my_handler() is called without %gs
being zero and without a valid fault (the handler does not get recalled
after signal( SIGSEGV, SIG_DFL ). I'm still working on this aspect ...

> 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).

I found this: /usr/src/lib/libc/amd64/sys/amd64_set_gsbase.c:32
"
int
amd64_set_gsbase(void *addr)
{
        return (sysarch(AMD64_SET_GSBASE, &addr));
}
"

and this (man 2 sysarch()): "The sysarch() system call should never be
called directly by user programs.  Instead, they should access its
functions using the architecture-dependent library."

Who am I suppose to believe? :)

> However, it only changes the base address via MSR, i.e., %gs  
> itself has no meaning.

Maybe, but the selector loaded in %gs *does* have meaning.

Anyway, the thing is I _have_ to make this work. I'll keep you posted ;)

-- 
Mihai Donțu



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200710090100.58577.mihai.dontu>