From owner-p4-projects@FreeBSD.ORG Wed Apr 14 14:30:11 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 7A7B01065673; Wed, 14 Apr 2010 14:30:11 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 26B78106566C for ; Wed, 14 Apr 2010 14:30:11 +0000 (UTC) (envelope-from attilio@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 1464F8FC0C for ; Wed, 14 Apr 2010 14:30:11 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id o3EEUA1T041370 for ; Wed, 14 Apr 2010 14:30:10 GMT (envelope-from attilio@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id o3EEUAbX041368 for perforce@freebsd.org; Wed, 14 Apr 2010 14:30:10 GMT (envelope-from attilio@FreeBSD.org) Date: Wed, 14 Apr 2010 14:30:10 GMT Message-Id: <201004141430.o3EEUAbX041368@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to attilio@FreeBSD.org using -f From: Attilio Rao To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 176894 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 14 Apr 2010 14:30:11 -0000 http://p4web.freebsd.org/@@176894?ac=10 Change 176894 by attilio@attilio_pavilion on 2010/04/14 14:30:04 Fix TLS handling within i386 by passing a correct LDT location for any thread rather than using always the same one. Submitted by: stass Affected files ... .. //depot/projects/valgrind/coregrind/m_syswrap/syswrap-x86-freebsd.c#17 edit Differences ... ==== //depot/projects/valgrind/coregrind/m_syswrap/syswrap-x86-freebsd.c#17 (text+ko) ==== @@ -409,10 +409,10 @@ } #endif - -static SysRes sys_set_thread_area ( ThreadId tid, Int idx, void* base ) +static SysRes sys_set_thread_area ( ThreadId tid, Int *idxptr, void *base) { VexGuestX86SegDescr* gdt; + Int idx; vg_assert(8 == sizeof(VexGuestX86SegDescr)); vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*)); @@ -425,12 +425,31 @@ VG_(threads)[tid].arch.vex.guest_GDT = (HWord)gdt; } + idx = *idxptr; + if (idx == -1) { + /* Find and use the first free entry. Don't allocate entry + zero, because the hardware will never do that, and apparently + doing so confuses some code (perhaps stuff running on + Wine). */ + for (idx = 1; idx < VEX_GUEST_X86_GDT_NENT; idx++) { + if (gdt[idx].LdtEnt.Words.word1 == 0 + && gdt[idx].LdtEnt.Words.word2 == 0) + break; + } + + if (idx == VEX_GUEST_X86_GDT_NENT) + return VG_(mk_SysRes_Error)( VKI_ESRCH ); + } else if (idx < 0 || idx == 0 || idx >= VEX_GUEST_X86_GDT_NENT) { + /* Similarly, reject attempts to use GDT[0]. */ + return VG_(mk_SysRes_Error)( VKI_EINVAL ); + } + translate_to_hw_format(base, &gdt[idx]); + *idxptr = idx; return VG_(mk_SysRes_Success)( 0 ); } - static SysRes sys_get_thread_area ( ThreadId tid, Int idx, void ** basep ) { VexGuestX86SegDescr* gdt; @@ -532,6 +551,7 @@ SysRes res; vki_sigset_t blockall, savedmask; struct vki_thr_param tp; + Int idx = -1; Addr stk; PRINT("thr_new ( %#lx, %ld )",ARG1,ARG2); @@ -596,8 +616,8 @@ if (debug) VG_(printf)("clone child has SETTLS: tls at %#lx\n", (Addr)tp.tls_base); - sys_set_thread_area( ctid, 2, tp.tls_base ); - ctst->arch.vex.guest_GS = (2 << 3) | 3; /* GSEL(GUGS_SEL, SEL_UPL) */ + sys_set_thread_area( ctid, &idx, tp.tls_base ); + ctst->arch.vex.guest_GS = (idx << 3) | 3; /* GSEL(GUGS_SEL, SEL_UPL) */ tp.tls_base = 0; /* Don't have the kernel do it too */ /* start the thread with everything blocked */ @@ -908,6 +928,7 @@ PRE(sys_sysarch) { ThreadState *tst; + Int idx; void **p; PRINT("sys_sysarch ( %ld, %#lx )", ARG1, ARG2); @@ -921,9 +942,10 @@ /* On FreeBSD, the syscall loads the %gs selector for us, so do it now. */ tst = VG_(get_ThreadState)(tid); p = (void**)ARG2; - tst->arch.vex.guest_GS = (2 << 3) | 3; /* GSEL(GUGS_SEL, SEL_UPL) */ + tst->arch.vex.guest_GS = (1 << 3) | 3; /* GSEL(GUGS_SEL, SEL_UPL) */ /* "do" the syscall ourselves; the kernel never sees it */ - SET_STATUS_from_SysRes( sys_set_thread_area( tid, 2, *p ) ); + idx = 1; + SET_STATUS_from_SysRes( sys_set_thread_area( tid, &idx, *p ) ); break; case VKI_I386_GET_GSBASE: