svn commit: r238669 - head/sys/amd64/amd64

Konstantin Belousov kib at FreeBSD.org
Sat Jul 21 13:06:38 UTC 2012


Author: kib
Date: Sat Jul 21 13:06:37 2012
New Revision: 238669
URL: http://svn.freebsd.org/changeset/base/238669

Log:
  The PT_I386_{GET,SET}XMMREGS and PT_{GET,SET}XSTATE operate on the
  stopped threads. Implementation assumes that the thread's FPU context
  is spilled into the PCB due to stop. This is mostly true, except when
  FPU state for the thread is not initialized. Then the requests operate
  on the garbage state which is currently left in the PCB, causing
  confusion.
  
  The situation is indeed observed after a signal delivery and before
  #NM fault on execution of any FPU instruction in the signal handler,
  since sendsig(9) drops FPU state for current thread, clearing
  PCB_FPUINITDONE. When inspecting context state for the signal handler,
  debugger sees the FPU state of the main program context instead of the
  clear state supposed to be provided to handler.
  
  Fix this by forcing clean FPU state in PCB user FPU save area by
  performing getfpuregs(9) before accessing user FPU save area in
  ptrace_machdep.c.
  
  Note: this change will be merged to i386 kernel as well, where it is
  much more important, since e.g. gdb on i386 uses PT_I386_GETXMMREGS to
  inspect FPU context on CPUs that support SSE. Amd64 version of gdb
  uses PT_GETFPREGS to inspect both 64 and 32 bit processes, which does
  not exhibit the bug.
  
  Reported by:	bde
  MFC after:	1 week

Modified:
  head/sys/amd64/amd64/ptrace_machdep.c

Modified: head/sys/amd64/amd64/ptrace_machdep.c
==============================================================================
--- head/sys/amd64/amd64/ptrace_machdep.c	Sat Jul 21 13:05:34 2012	(r238668)
+++ head/sys/amd64/amd64/ptrace_machdep.c	Sat Jul 21 13:06:37 2012	(r238669)
@@ -50,6 +50,7 @@ cpu_ptrace_xstate(struct thread *td, int
 
 	switch (req) {
 	case PT_GETXSTATE:
+		fpugetregs(td);
 		savefpu = (char *)(get_pcb_user_save_td(td) + 1);
 		error = copyout(savefpu, addr,
 		    cpu_max_ext_state_size - sizeof(struct savefpu));
@@ -62,8 +63,10 @@ cpu_ptrace_xstate(struct thread *td, int
 		}
 		savefpu = malloc(data, M_TEMP, M_WAITOK);
 		error = copyin(addr, savefpu, data);
-		if (error == 0)
+		if (error == 0) {
+			fpugetregs(td);
 			error = fpusetxstate(td, savefpu, data);
+		}
 		free(savefpu, M_TEMP);
 		break;
 
@@ -89,11 +92,13 @@ cpu32_ptrace(struct thread *td, int req,
 
 	switch (req) {
 	case PT_I386_GETXMMREGS:
+		fpugetregs(td);
 		error = copyout(get_pcb_user_save_td(td), addr,
 		    sizeof(*fpstate));
 		break;
 
 	case PT_I386_SETXMMREGS:
+		fpugetregs(td);
 		fpstate = get_pcb_user_save_td(td);
 		error = copyin(addr, fpstate, sizeof(*fpstate));
 		fpstate->sv_env.en_mxcsr &= cpu_mxcsr_mask;


More information about the svn-src-head mailing list