Port-arm archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Are there known issues with earmhf?



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



Home | Main Index | Thread Index | Old Index