Bug 5248

Summary: core-image-lsb: FPU doesn't work correctly on qemux86-64
Product: [Build System, Metadata & Runtime] OE-Core Reporter: Hongxu Jia <hongxu.jia>
Component: devtools / tool chainAssignee: Saul Wold <sgw>
Status: VERIFIED FIXED QA Contact:
Severity: normal    
Priority: Medium+ CC: bluelightning, dvhart, hongxu.jia, liezhi.yang, mark.hatle, meta.mr.watcher, meta.watcher, Qi.Chen, raj.khem, richard.purdie, rongqing.li, ross.burton, sgw, tom.zanussi, yi.zhao
Version: 1.5   
Target Milestone: 1.5 M5   
Hardware: x86   
OS: Multiple   
Whiteboard:
OS type for building Yocto: --- Type of Regression: ---
Verified: Documentation change: Don't know

Description Hongxu Jia 2013-09-23 08:37:57 UTC
*Preparation
1, vim local.conf
...
DISTRO ?= "poky-lsb"
MACHINE ?= "qemux86-64"
...

*Problem
1, Build core-image-lsb
..
bitbake core-image-lsb
..

2, Start qemux86-64, there are 21 LSB tcl test failures on
qemux86-64[YOCTO #5167], you could reproduce it by tcl interpreter:
  1, On qemux86-64's terminal, start tcl interpreter
  root@qemux86-64:~# $ tclsh
  %

  2, Run 'binary scan' to assign ieeeValues(-Subnormal)
  % binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d ieeeValues(-Subnormal) 
  1

  3, Run 'puts' to output ieeeValues(-Subnormal), the result is '0.0'
  % puts $ieeeValues(-Subnormal)
  -0.0

  Expected:
  -1.1125369292536007e-308

*Analysis
1, On the previous environment, add IMAGE_INSTALL_append = " tcl" to
local.conf and build core-image-sato, the result is expected.

2, Trace tcl's source code, you could also reproduce the issue by
compiling and executing the following C codes on core-image-lsb-sdk.

  1) Build core-image-lsb-sdk, and Run qemux86-64.
  2) On target's terminal, create a C source file:
     root@qemux86-64:~# cat >> test.c << EOF
#include <stdio.h>

int main(int argc, char *argv[])
{
  double dd = 0;
  char *p = (char*)&dd;
  p[0] = 0x00;
  p[1] = 0x00;
  p[2] = 0x00;
  p[3] = 0x00;
  p[4] = 0x00;
  p[5] = 0x00;
  p[6] = 0x08;
  p[7] = 0x00;

  if (dd == 0.0)
    printf("Incorrect equal 0.0\n");
  else
    printf("Expected not equal 0.0\n");

  return 0;
}
EOF

  2) Compile test.c
    root@qemux86-64:~# gcc test.c -o test

  3, Execute test
  $ root@qemux86-64:~# ./test
    Incorrect equal 0.0

  Expected:
    Expected not equal 0.0

3, It's about x86-64's FPU: the SSE MXCSR register.

  If you invoke 'feenableexcept(FE_INEXACT);' or
  'feclearexcept(FE_INEXACT);' in the above C test,
  the issue will be fixed.

  In these two functions, the SSE MXCSR register has
  been handled.

http://en.wikipedia.org/wiki/Double-precision_floating-point_format
http://wiki.osdev.org/SSE
Comment 1 Hongxu Jia 2013-09-23 08:39:58 UTC
*** Bug 5167 has been marked as a duplicate of this bug. ***
Comment 2 Saul Wold 2013-09-29 20:10:28 UTC
Well it took sometime and sleuthing via smaller and smaller build, but I 
tracked it down to the full version of procps and more specifically the running 
of sysctl at startup time.  Our base (non-lsb) images don't have a sysctl.conf 
by default, so it does not get run normally.  The LSB version has both a 
sysctl.conf and the sysctl.procps linked to sysctl, so syctl is run from 
bootmisc.sh.  I tested both busybox and sysctl.procps,   It seems running 
sysctl.procps causes the issue, but not the busybox version.  I can reproduce 
it without even passing any parameters to sysctl.procps

strace shows it doing very little:

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 
0x7f1070cc4000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 
0x7f1070cc3000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 
0x7f1070cc2000
arch_prctl(ARCH_SET_FS, 0x7f1070cc3700) = 0
mprotect(0x7f1070882000, 16384, PROT_READ) = 0
mprotect(0x7f1070ccf000, 4096, PROT_READ) = 0
munmap(0x7f1070cc5000, 36714)           = 0
brk(0)                                  = 0x603000
brk(0x624000)                           = 0x624000
open("/proc/version", O_RDONLY)         = 3
fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 
0x7f1070ccd000
read(3, "Linux version 3.10.11-yocto-stan"..., 1024) = 120
close(3)                                = 0
munmap(0x7f1070ccd000, 4096)            = 0
open("/sys/devices/system/cpu/online", O_RDONLY|O_CLOEXEC) = 3
read(3, "0\n", 8192)                    = 2
close(3)                                = 0
fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(4, 64), ...}) = 0
ioctl(1, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, 
{B115200 opost isig icanon echo ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 
0x7f1070ccd000

Opens 2 /proc/version and /sys/devices/system/cpu/online, this issue seems to 
have something to do with the init_libproc() constructor
Comment 3 Saul Wold 2013-09-30 06:38:17 UTC
I narrowed this down a little further to the libgcc fast_math code (I think), 
not sure why it triggers with the procps but not other code yet.  It looks like 
it might be executing i386 code on the x86-64 machine, I need to check this 
furhter tommorow.
Comment 4 Saul Wold 2013-09-30 06:43:05 UTC
I have added the following to local.conf and then mounted the 
core-image-minimal image and mv'ed the /etc/sysctl.conf to /etc/sysctl.save 
(also mv /sbin/sysctl to /sbin/sysctl-), then try do debug /sbin/sysctl.psproc. 
 running the float program before and after will show correct and then 
incorrect.
Comment 5 Ross Burton 2013-09-30 11:05:44 UTC
A data point from the test case on a NUC in 64-bit mode on core-image-sato.

root@nuc:~# uname -a
Linux nuc 3.10.11-yocto-standard #1 SMP PREEMPT Fri Sep 27 05:38:43 BST 2013 x86_64 GNU/Linux
root@nuc:~# ./test 
Expected not equal 0.0

After installing procps and rebooting:

root@nuc:~# ./test 
Expected not equal 0.0

I'm doing a LSB build now, but does appear this is qemu-specific.
Comment 6 Ross Burton 2013-09-30 13:43:43 UTC
And on core-image-lsb:

root@nuc:~# ./test 
Expected not equal 0.0
Comment 7 Paul Eggleton 2013-09-30 16:14:34 UTC
Another data point - the issue is still present with QEMU 1.5.3.
Comment 8 Saul Wold 2013-09-30 17:19:40 UTC
Also verified that when running qemu with kvm it works correctly.
Comment 9 Khem Raj 2013-09-30 17:57:03 UTC
shot in dark but try 

http://sakrah.homelinux.org/files/fpip.patch

and see if it helps ?
Comment 10 Richard Purdie 2013-09-30 18:54:32 UTC
I found the problem: http://git.yoctoproject.org/cgit.cgi/poky-contrib/commit/?h=rpurdie/t2&id=7eea15e10cb56b51aa27e246daac78d39d1b452a

Basically FXRSTOR was updating MXCSR but not the internal qemu status bits that need to change when that register changes.
Comment 12 Hongxu Jia 2013-10-08 06:02:38 UTC
Verified on master 5445f71fc812a5fcf9bd67a26a500284af16ad39


root@qemux86-64:~# tclsh
% binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d ieeeValues(-Subnormal) 
1
% puts $ieeeValues(-Subnormal)
-1.1125369292536007e-308