From kettenis@elgar.kettenis.dyndns.org  Fri Sep 26 07:12:03 2003
Return-Path: <kettenis@elgar.kettenis.dyndns.org>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id C587416A4B3
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 26 Sep 2003 07:12:03 -0700 (PDT)
Received: from walton.kettenis.dyndns.org (e115144.upc-e.chello.nl [213.93.115.144])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 12A154400B
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 26 Sep 2003 07:12:02 -0700 (PDT)
	(envelope-from kettenis@elgar.kettenis.dyndns.org)
Received: from elgar.kettenis.dyndns.org (elgar.kettenis.dyndns.org [192.168.0.2])
	by walton.kettenis.dyndns.org (8.12.6p3/8.12.5) with ESMTP id h8QEC1aM000349
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 26 Sep 2003 16:12:01 +0200 (CEST)
	(envelope-from kettenis@elgar.kettenis.dyndns.org)
Received: from elgar.kettenis.dyndns.org (localhost [127.0.0.1])
	by elgar.kettenis.dyndns.org (8.12.6p3/8.12.6) with ESMTP id h8QEBsoN012104
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 26 Sep 2003 16:11:54 +0200 (CEST)
	(envelope-from kettenis@elgar.kettenis.dyndns.org)
Received: (from kettenis@localhost)
	by elgar.kettenis.dyndns.org (8.12.6p3/8.12.6/Submit) id h8QEBrKY012055;
	Fri, 26 Sep 2003 16:11:53 +0200 (CEST)
Message-Id: <200309261411.h8QEBrKY012055@elgar.kettenis.dyndns.org>
Date: Fri, 26 Sep 2003 16:11:53 +0200 (CEST)
From: Mark Kettenis <kettenis@gnu.nl>
Reply-To: Mark Kettenis <kettenis@gnu.org>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: Broken PTRACE_GETFPREGS and PTRACE_SETFPREGS
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         57250
>Category:       amd64
>Synopsis:       [amd64] [patch] Broken PTRACE_GETFPREGS and PTRACE_SETFPREGS
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-amd64
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Sep 26 07:20:01 PDT 2003
>Closed-Date:    Sun Dec 05 14:27:22 UTC 2010
>Last-Modified:  Sun Dec  5 14:30:14 UTC 2010
>Originator:     Mark Kettenis
>Release:        FreeBSD 5.1-CURRENT amd64
>Organization:
>Environment:
System: FreeBSD delius.kettenis.dyndns.org 5.1-CURRENT FreeBSD 5.1-CURRENT #0: Sun Sep 21 23:09:00 CEST 2003 kettenis@delius.kettenis.dyndns.org:/usr/obj/usr/src/sys/GENERIC amd64

>Description:
The PTRACE_GETFPREGS and PTRACE_SETFPREGS requests are broken on
FreeBSD/amd64.  In particular, using PTRACE_SETFPREGS is pointless
until the program beging traced has executed its first floating-point
instruction; that floating-point instruction will reinitialize the
precess' floating-point state, overwriting the values set by
PTRACE_SETFPREGS.

I traced this back to src/sys/amd64/amd64/machdep.c:fill_fpregs()
where we read the floating-point state from the pcb, regardless of
whether PCB_NPXINITDONE has been set, and set_fpregs() where we don't
set PCB_NPXINITDONE, and fail to properly set the floating-point
registers if the current process "owns" the FPU.  This probably means
that /proc is broken too.

What puzzles me is that the amd64 code is pretty much identical to the
i386, and that everything appears to be working fine there, at least
with GDB.  The only thing I can think of is that every process
executes a floating-point instruction before reaching main().
However, I haven't been able to find such an instruction.  Anyway, I
think the code is incorrect on the i386 too, and that we just happen
not to notice where it matters.

>How-To-Repeat:

Using GDB, in a function that returns a floating-point value, type
"return 3.1415".  The caller of this function will see garbage instead
of this value.

>Fix:
The attached patch fixes things for me.  The functions
fill_fpregs_xmm() and set_fpregs_xmm() can probably be eliminated
passing fpregs directly to npxgetregs and npxsetregs.


--- src/sys/amd64/amd64/machdep.c.orig	Tue Sep  9 21:32:09 2003
+++ src/sys/amd64/amd64/machdep.c	Sat Sep 20 11:47:19 2003
@@ -1413,8 +1413,10 @@ set_fpregs_xmm(struct fpreg *fpregs, str
 int
 fill_fpregs(struct thread *td, struct fpreg *fpregs)
 {
+	struct savefpu sv_xmm;
 
-	fill_fpregs_xmm(&td->td_pcb->pcb_save, fpregs);
+  	npxgetregs(td, &sv_xmm);
+	fill_fpregs_xmm(&sv_xmm, fpregs);
 	return (0);
 }
 
@@ -1422,8 +1424,10 @@ fill_fpregs(struct thread *td, struct fp
 int
 set_fpregs(struct thread *td, struct fpreg *fpregs)
 {
+	struct savefpu sv_xmm;
 
-	set_fpregs_xmm(fpregs, &td->td_pcb->pcb_save);
+	set_fpregs_xmm(fpregs, &sv_xmm);
+  	npxsetregs(td, &sv_xmm);
 	return (0);
 }
 
--- src/sys/amd64/isa/npx.c.orig	Fri Jul 25 23:18:52 2003
+++ src/sys/amd64/isa/npx.c	Sat Sep 20 11:47:19 2003
@@ -646,7 +646,7 @@ npxsetregs(td, addr)
 		intr_restore(s);
 		bcopy(addr, &td->td_pcb->pcb_save, sizeof(*addr));
 	}
-	curthread->td_pcb->pcb_flags |= PCB_NPXINITDONE;
+	td->td_pcb->pcb_flags |= PCB_NPXINITDONE;
 }
 
 static device_method_t npx_methods[] = {



>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-amd64->obrien 
Responsible-Changed-By: obrien 
Responsible-Changed-When: Tue Oct 28 12:05:52 PST 2003 
Responsible-Changed-Why:  
I'll take this one. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=57250 

From: Mark Kettenis <kettenis@chello.nl>
To: freebsd-gnats-submit@FreeBSD.org, kettenis@gnu.org
Cc:  
Subject: Re: amd64/57250: Broken PTRACE_GETFPREGS and PTRACE_SETFPREGS
Date: Thu, 30 Oct 2003 21:01:07 +0100 (CET)

 The patch I submitted is broken.  The GDB testsuite has gained a new
 test which makes my kernel (which includes the patch) panic:
 
 kernel trap with interrupts disabled
 
 npxgetregs+0x5c
 
 Mark

From: Mark Kettenis <kettenis@chello.nl>
To: freebsd-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: amd64/57250: Broken PTRACE_GETFPREGS and PTRACE_SETFPREGS
Date: Sun, 28 Dec 2003 22:21:17 +0100 (CET)

 Here's a new patch.  It fixes the problem for me and doesn't seem to
 cause any ill effects.  It does things a little different than my
 earlier patch; when setting the FP registers I now simply drop the
 FPU, and copy the new register state into the pcb.  That way I avoid
 generating floating point exceptions with interrupts disabled.  Any
 pending exceptions will be generated when the program continues and
 loads the FPU upon execution of its first FP instruction.  This seems
 the right approach for setcontext() too.
 
 Mark
 
 --- src/sys/amd64/amd64/fpu.c.orig	Mon Dec 15 18:54:23 2003
 +++ src/sys/amd64/amd64/fpu.c	Sat Dec 20 22:28:16 2003
 @@ -510,13 +510,12 @@ fpusetregs(struct thread *td, struct sav
  
  	s = intr_disable();
  	if (td == PCPU_GET(fpcurthread)) {
 -		fxrstor(addr);
 -		intr_restore(s);
 -	} else {
 -		intr_restore(s);
 -		bcopy(addr, &td->td_pcb->pcb_save, sizeof(*addr));
 +		PCPU_SET(fpcurthread, NULL);
 +		start_emulating();
  	}
 -	curthread->td_pcb->pcb_flags |= PCB_FPUINITDONE;
 +	intr_restore(s);
 +	bcopy(addr, &td->td_pcb->pcb_save, sizeof(*addr));
 +	td->td_pcb->pcb_flags |= PCB_FPUINITDONE;
  }
  
  /*
 --- src/sys/amd64/amd64/machdep.c.orig	Sun Dec  7 00:19:47 2003
 +++ src/sys/amd64/amd64/machdep.c	Sat Dec 20 23:09:02 2003
 @@ -1403,8 +1403,10 @@ set_fpregs_xmm(struct fpreg *fpregs, str
  int
  fill_fpregs(struct thread *td, struct fpreg *fpregs)
  {
 +	struct savefpu sv_xmm;
  
 -	fill_fpregs_xmm(&td->td_pcb->pcb_save, fpregs);
 +	fpugetregs(td, &sv_xmm);
 +	fill_fpregs_xmm(&sv_xmm, fpregs);
  	return (0);
  }
  
 @@ -1412,8 +1414,10 @@ fill_fpregs(struct thread *td, struct fp
  int
  set_fpregs(struct thread *td, struct fpreg *fpregs)
  {
 +	struct savefpu sv_xmm;
  
 -	set_fpregs_xmm(fpregs, &td->td_pcb->pcb_save);
 +	set_fpregs_xmm(fpregs, &sv_xmm);
 +	fpusetregs(td, &sv_xmm);
  	return (0);
  }
  
State-Changed-From-To: open->feedback 
State-Changed-By: kmacy 
State-Changed-When: Fri Nov 16 22:42:16 UTC 2007 
State-Changed-Why:  

Am I correct in assuming that this is still an issue? 


Responsible-Changed-From-To: obrien->kmacy 
Responsible-Changed-By: kmacy 
Responsible-Changed-When: Fri Nov 16 22:42:16 UTC 2007 
Responsible-Changed-Why:  

Am I correct in assuming that this is still an issue?  

http://www.freebsd.org/cgi/query-pr.cgi?pr=57250 
State-Changed-From-To: feedback->suspended 
State-Changed-By: linimon 
State-Changed-When: Sat Mar 1 20:14:06 UTC 2008 
State-Changed-Why:  
No feedback received, but it sounds like this could still be an issue. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=57250 
Responsible-Changed-From-To: kmacy->freebsd-amd64 
Responsible-Changed-By: avg 
Responsible-Changed-When: Sun Dec 5 13:37:09 UTC 2010 
Responsible-Changed-Why:  
No activity for quite a while, release back to the pool. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=57250 

From: Andriy Gapon <avg@freebsd.org>
To: bug-followup@freebsd.org, kettenis@gnu.org,
        Konstantin Belousov <kib@freebsd.org>
Cc:  
Subject: Re: amd64/57250: [amd64] [patch] Broken PTRACE_GETFPREGS and PTRACE_SETFPREGS
Date: Sun, 05 Dec 2010 15:38:12 +0200

 Kostik,
 
 could you please assess the status of this issue?
 Thanks!
 -- 
 Andriy Gapon

From: Kostik Belousov <kostikbel@gmail.com>
To: Andriy Gapon <avg@freebsd.org>
Cc: bug-followup@freebsd.org, kettenis@gnu.org
Subject: Re: amd64/57250: [amd64] [patch] Broken PTRACE_GETFPREGS and PTRACE_SETFPREGS
Date: Sun, 5 Dec 2010 16:11:36 +0200

 --AhhlLboLdkugWU4S
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable
 
 On Sun, Dec 05, 2010 at 03:38:12PM +0200, Andriy Gapon wrote:
 >=20
 > Kostik,
 >=20
 > could you please assess the status of this issue?
 > Thanks!
 > --=20
 > Andriy Gapon
 Amuzingly enough, I fixed this in r215865 on 2010-11-26, that was
 merged to stable/8 in r216162 on 2010-12-03, even forgetting mentioning
 this in the commit message.
 
 --AhhlLboLdkugWU4S
 Content-Type: application/pgp-signature
 Content-Disposition: inline
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (FreeBSD)
 
 iEYEARECAAYFAkz7nZcACgkQC3+MBN1Mb4jasACbBJwjt8SXTOllADFh6IOHJuM1
 8LcAnRB9U8GCutnqnYY+BdM7VSoaeBC8
 =1Y3Q
 -----END PGP SIGNATURE-----
 
 --AhhlLboLdkugWU4S--
State-Changed-From-To: suspended->closed 
State-Changed-By: avg 
State-Changed-When: Sun Dec 5 14:26:46 UTC 2010 
State-Changed-Why:  
This should be resolved now in head and stable/8. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=57250 

From: Andriy Gapon <avg@freebsd.org>
To: Kostik Belousov <kostikbel@gmail.com>
Cc: bug-followup@freebsd.org, kettenis@gnu.org
Subject: Re: amd64/57250: [amd64] [patch] Broken PTRACE_GETFPREGS and PTRACE_SETFPREGS
Date: Sun, 05 Dec 2010 16:26:30 +0200

 on 05/12/2010 16:11 Kostik Belousov said the following:
 > On Sun, Dec 05, 2010 at 03:38:12PM +0200, Andriy Gapon wrote:
 >>
 >> Kostik,
 >>
 >> could you please assess the status of this issue?
 >> Thanks!
 >> -- 
 >> Andriy Gapon
 > Amuzingly enough, I fixed this in r215865 on 2010-11-26, that was
 > merged to stable/8 in r216162 on 2010-12-03, even forgetting mentioning
 > this in the commit message.
 
 I suspected something like that :-)
 Thanks a lot!
 
 -- 
 Andriy Gapon
>Unformatted:
