On 31 Jul, 2013, at 13:46 , Matt Thomas <matt%3am-software.com@localhost> wrote: > On Jul 31, 2013, at 10:32 AM, Dennis Ferguson > <dennis.c.ferguson%gmail.com@localhost> wrote: > >> I was interested in using earmhf on the am335x processor since it >> makes a measurable difference (with Linux) for the application I'm >> trying to support and it is easy to pick an abi up front but harder >> to change one's mind later. What I've found is that while the system >> builds just fine this way, and the kernel boots, applications which >> use floating point misbehave. For a minimal example (it uses floating >> point only to handle time intervals), `ping xxx` or `ping -i 1 xxx` >> sends packets just as fast as it possibly can while `ping -i 2 xxx` sends >> a single packet and then waits forever. > > I wonder if something still think they are softfloat. BTW, for earm I've > fixed libc_vfp.so to adhere to the RTABI standard so it should work. > > export LD_PRELOAD=/usr/lib/libc_vfp.so.0 or use /etc/ld.so.conf to do it > automatically. > >> While I've looked at this briefly enough to only make a guess, it appears >> that floating point arithmetic done entirely within the application works >> okay, as do varargs function like printf(), but some other library function >> calls involving floating point values may be misbehaving. >> >> Beyond this I'm not sure where to look. Is this a known issue with earmhf >> and, if so, is it known what needs to be looked at? Is there an interesting >> place to look for code that is handling floating point function arguments >> and that may have built-in knowledge of the abi (e.g. assembly code)? > > There isn't really any assembly code that deals with floating point > except for setjmp/longjmp and getcontext/setcontext. > > It might be useful to use an earm userland and then use an earmhf chroot > tree and see if the program happens if more than 1 program uses FP as a time. > > I think the kernel lazy FP switching code is right but I haven't really > tested it. I looked at this again more carefully. The problem isn't the kernel, it is the earmhf gcc or user space libraries. I have two builds built from the same sources using the same arguments to build.sh except that one had a '-a earm' and the other had '-a earmhf'. I looked at two utilities which use a little bit of floating point, ping and vmstat. On the earmhf build ping fails as described above while vmstat prints all zeroes for the percentages in the three right hand columns (normally these three columns add to 100); those percentages are computed with floating point arithmetic. ping uses floating point for time intervals and makes explicit calls to two external floating point functions. It calls strtod() to process -i and -w option arguments, and it calls sqrt() at the end when computing the standard deviation. vmstat makes no explicit calls to any external floating point functions. If I copy the earmhf ping and vmstat binaries, which fail on the earmhf beagle, to the earm beagle, they both work. The earmhf vmstat works perfectly with earm libraries as is (it makes no explicit calls to external floating point functions). The earmhf ping fails to work on earm when the options are used, causing it to call strtod(), but otherwise works fine there (the result of the sqrt() even looks reasonable, though I don't know if it is correct). If I do LD_PRELOAD=/usr/lib/libc_vfp.so.0 ping ... then even the options work. earmhf binaries hence run with earm libraries, but not with earmhf libraries. I'm pretty sure the problem has nothing to do with the kernel since the kernels built with each build seem to be identical other than the strings, the earm kernel runs with the earmhf userland and vice versa, and the problems remain on the machine with the earmhf userland no matter which kernel is run there. What I did notice, however, is that the compiler is emitting calls to __aeabi_*() functions in both progams, including functions which do long long <-> double conversions. ping calls these U __aeabi_l2d 0000cdb0 T __aeabi_d2lz 0000cdf8 T __aeabi_d2ulz while vmstat calls this U __aeabi_ul2d The latter one is particularly interesting because the floating point arithmetic done in vmstat is limited and really simple. I'm pretty sure the only way that the three percentages vmstat prints could be zero is if the calls to __aeabi_ul2d() are failing on earmhf, while they clearly are working when the earmhf binary is run against earm libraries. So I wrote this test case to generate a call to __aeabi_ul2d(): #include <stdlib.h> #include <stdio.h> int main (int argc, char * const *argv) { unsigned long long ul; char *cp; if (argc > 1) { ul = strtoull(argv[1], &cp, 0); printf("%llu: %f\n", ul, (double) ul); } return (0); } This works as expected when compiled and run on earm, and it works as expected when compiled on earmhf and run on earm, but a binary compiled and run on earmhf always prints '0.0000' as the value of (double) ul no matter what ul is. Playing with the code a little and looking at the generated assembler for earmhf, it appears to me that gcc expects the result of calling __aeabi_ul2d() to be returned in the integer registers r0 and r1, which I'll bet is not what is supposed to happen for earmhf. Either gcc for earmhf is somehow misconfigured or it is just broken. Should I file a bug for this? Dennis Ferguson
Attachment:
signature.asc
Description: Message signed with OpenPGP using GPGMail