From owner-freebsd-emulation@FreeBSD.ORG Mon Jan 22 21:26:27 2007 Return-Path: X-Original-To: freebsd-emulation@freebsd.org Delivered-To: freebsd-emulation@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 35F5416A484; Mon, 22 Jan 2007 21:26:27 +0000 (UTC) (envelope-from xdivac02@stud.fit.vutbr.cz) Received: from eva.fit.vutbr.cz (eva.fit.vutbr.cz [147.229.176.14]) by mx1.freebsd.org (Postfix) with ESMTP id BD21313C43E; Mon, 22 Jan 2007 21:26:26 +0000 (UTC) (envelope-from xdivac02@stud.fit.vutbr.cz) Received: from eva.fit.vutbr.cz (localhost [127.0.0.1]) by eva.fit.vutbr.cz (envelope-from xdivac02@eva.fit.vutbr.cz) (8.13.8/8.13.7) with ESMTP id l0MLQPZF051666 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 22 Jan 2007 22:26:25 +0100 (CET) Received: (from xdivac02@localhost) by eva.fit.vutbr.cz (8.13.8/8.13.3/Submit) id l0MLQO9o051665; Mon, 22 Jan 2007 22:26:24 +0100 (CET) Date: Mon, 22 Jan 2007 22:26:24 +0100 From: Divacky Roman To: Tijl Coosemans Message-ID: <20070122212624.GA49466@stud.fit.vutbr.cz> References: <790a9fff0701211041j1176d00gd6dd75d0989cf4ec@mail.gmail.com> <200701220001.22404.tijl@ulyssis.org> <20070122081810.GA42976@stud.fit.vutbr.cz> <200701221752.21628.tijl@ulyssis.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <200701221752.21628.tijl@ulyssis.org> User-Agent: Mutt/1.4.2.2i X-Scanned-By: MIMEDefang 2.57 on 147.229.176.14 Cc: freebsd-emulation@freebsd.org, jkim@freebsd.org Subject: Re: linuxolator: tls_test results amd64 X-BeenThere: freebsd-emulation@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Development of Emulators of other operating systems List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 22 Jan 2007 21:26:27 -0000 > > 1) why the first test succeeds? > > Segment registers have a hidden part that contains base address and > limit (and some more flags I guess). When you load a value into a > segment register, this hidden part is updated with the info contained > in the descriptor (entry in GDT/LDT). On amd64 the base address of FS > and GS (in this hidden part) can also be changed directly using the > wrmsr instruction. > > The first test requests base address 0x00000000. set_thread_area > sets GS.base (in hidden part) to 0x00000000 and returns 4 as descriptor > entry number. This is the user data segment descriptor, which base > address is also 0x00000000 (I think). So when you next load 4<<3|3 in > FS, FS.base also ends up being 0x00000000 and the test succeeds. > > The second test requests a different base address. GS.base is set to > this address, but when you then load 4<<3|3 into FS, FS.base ends up > with 0x00000000 and so your second read test fails (NULL pointer > dereference). understood > > 2) why real apps (ie. using %gs) show the very same behaviour (first > > program works then it doesnt) > > Hmm, can you point me to the source of such a program? I would expect > programs that use glibc to always fail. Glibc expects set_thread_area > to setup a GDT entry and return the entry number. Then glibc loads > that entry number into GS which sets up GS.base. Because of this, I > would expect GS.base to always end up being 0x00000000 just as FS.base > above. > > Wine on Linux does the same. It calls set_thread_area and loads the > returned entry number in FS. (On Windows, FS is used for tls.) > > The reason setting GS.base directly with a wrmsr works on FreeBSD is > because i386 user land code doesn't write to GS. i386_set_gsbase what do you mean by "writing to GS" ? > already sets up GS on i386, so the compatibility code on amd64 can > use the wrmsr trick and leave GS itself and the descriptor it points > to untouched. As far as I understand things, this won't work for > linux32 compatibility on amd64. lookin at the code it looks like: i386_set_gsbase = sysarch(I386_SET_GSBASE, &addr); and sysarch for that looks like: wrmsr(MSR_KGSBASE, i386base); pcb->pcb_gsbase = i386base; where is the setting up of the GS? I dont get it... overall you are saying that to support linux32 tls we have to 1) load an unused segment with proper values 2) return the number of the segment from the set_thread_syscall 3) make the automatic loading/unloading of that segment to happen on every context switch (just like its done for segment 3 on i386) do I get it right? anyway thnx for the explanation you finally shed some light to it. roman