| 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 chain | Assignee: | 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 | |
*** Bug 5167 has been marked as a duplicate of this bug. *** 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
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. 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. 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. And on core-image-lsb: root@nuc:~# ./test Expected not equal 0.0 Another data point - the issue is still present with QEMU 1.5.3. Also verified that when running qemu with kvm it works correctly. shot in dark but try http://sakrah.homelinux.org/files/fpip.patch and see if it helps ? 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. Fixed in master with http://git.yoctoproject.org/cgit.cgi/poky/commit/?id=0fe5d9d657446df695e8c810203da469e49ab553 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 |
*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*)ⅆ 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