From e1b708897ea547f25fbc5fc1f73bb2b0738c5757 Mon Sep 17 00:00:00 2001 From: jhb Date: Thu, 5 Mar 2009 19:42:11 +0000 Subject: A better fix for handling different FPU initial control words for different ABIs: - Store the FPU initial control word in the pcb for each thread. - When first using the FPU, load the initial control word after restoring the clean state if it is not the standard control word. - Provide a correct control word for Linux/i386 binaries under FreeBSD/amd64. - Adjust the control word returned for fpugetregs()/npxgetregs() when a thread hasn't used the FPU yet to reflect the real initial control word for the current ABI. - The Linux/i386 ABI for FreeBSD/i386 now properly sets the right control word instead of trashing whatever the current state of the FPU is. Reviewed by: bde --- sys/i386/linux/linux_sysvec.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'sys/i386/linux') diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index c98fe14..4efd496 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -89,9 +89,6 @@ MALLOC_DEFINE(M_LINUX, "linux", "Linux mode structures"); #define LINUX_SYS_linux_rt_sendsig 0 #define LINUX_SYS_linux_sendsig 0 -#define fldcw(addr) __asm("fldcw %0" : : "m" (*(addr))) -#define __LINUX_NPXCW__ 0x37f - extern char linux_sigcode[]; extern int linux_szsigcode; @@ -930,16 +927,15 @@ static void exec_linux_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) { - static const u_short control = __LINUX_NPXCW__; struct pcb *pcb = td->td_pcb; exec_setregs(td, entry, stack, ps_strings); /* Linux sets %gs to 0, we default to _udatasel */ - pcb->pcb_gs = 0; load_gs(0); + pcb->pcb_gs = 0; + load_gs(0); - /* Linux sets the i387 to extended precision. */ - fldcw(&control); + pcb->pcb_initial_npxcw = __LINUX_NPXCW__; } static void -- cgit v1.1