On Sun, 1 Mar 2020 09:23:45 +0900
rgc <rgci...@disroot.org> wrote:

> 'time sleep 1' takes ages. painfully slow. 'date' after rebooting the
> test kernel is way way off. from the looks of things it never
> advanced.

ppc_mftb() in /sys/arch/powerpc/include/cpu.h is broken with clang.

My one macppc machine, the iMac G3, has hardware trouble, so I turned
it off.  My amd64 desktop has ports-clang (from pkg_add clang), which
includes the PowerPC backend, so I can copy ppc_mftb() into a file and
generate PowerPC assembly code.

$ alias pang='/usr/local/bin/clang -target ppc-openbsd'
$ cat exam.c
typedef unsigned long long u_int64_t;
typedef unsigned long u_long;

static __inline u_int64_t
ppc_mftb(void)
{
        u_long scratch;
        u_int64_t tb;

        __asm volatile ("1: mftbu %0; mftb %0+1; mftbu %1;"
            " cmpw 0,%0,%1; bne 1b" : "=r"(tb), "=r"(scratch));
        return tb;
}

u_int64_t
f(void)
{
        u_int64_t tb = ppc_mftb();
        return (tb >> 32) | (tb << 32);
}
$ pang -S -O2 exam.c

My function f() swaps the words in the time base, should return the
upper word (mftbu) in %r4 and the lower word in %r3.  The generated
code "exam.s" fails to set %r3; the inline __asm turned into,

.Ltmp1:
        mfspr 4, 269
        mfspr 5, 268
        mfspr 5, 269
        cmpw    4, 5
        bne     0, .Ltmp1

which is wrong because the lower word "mfspr %r5, 268" is lost when
the upper word "mfspr %r5, 269" clobbers %r5.  (The code loops until
the upper words in %r4 and %r5 are equal.)  If your clang kernel lost
the lower word of the time base, then time might stop.

I suspect that "mftb %0+1" fails because clang doesn't always choose
register %0+1 to hold the lower word of "=r"(tb).

This might work:

static __inline u_int64_t
ppc_mftb(void)
{
        u_long high, low, scratch;

        __asm volatile ("1: mftbu %0; mftb %1; mftbu %2;"
            " cmpw 0,%0,%2; bne 1b" : "=r"(high), "=r"(low), "=r"(scratch));
        return ((u_int64_t)high << 32) | low;
}

Reply via email to