Skip to content
Permalink
Browse files

arm64: bitops: fix test_and_set_bit

When compiling code using aarch64 poky gcc 8.2, met the warning:
"
  CC      hypervisor/printk.o
/tmp/cclKpFV2.s: Assembler messages:
/tmp/cclKpFV2.s:1306: Warning: unpredictable: identical transfer and status registers --`stxr w4,x5,[x4]'
"

According to DDI0487D_a_armv8_arm, section "C6.2.285 STXR",
"
if s == n && n != 31 then
    Constraint c = ConstrainUnpredictable();
    assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
    case c of
        when Constraint_UNKNOWN rn_unknown = TRUE; // address is UNKNOWN
        when Constraint_NONE rn_unknown = FALSE; // address is original base
        when Constraint_UNDEF UNDEFINED;
        when Constraint_NOP EndOfInstruction();
"
And ConstrainUnpredictable means:
"
shared/functions/unpredictable/ConstrainUnpredictable
// Return the appropriate Constraint result to control the caller's behavior. The return value
// is IMPLEMENTATION DEFINED within a permitted list for each UNPREDICTABLE case.
// (The permitted list is determined by an assert or case statement at the call site.)
"

So we need to avoid the situation that s == n returns true.

Without this patch, the asm code as following in panic_prink

    ffffc0207ac0:       91006024        add     x4, x1, #0x18
    ffffc0207ac4:       c85f7c85        ldxr    x5, [x4]
    ffffc0207ac8:       ea0200a3        ands    x3, x5, x2
    ffffc0207acc:       54000041        b.ne    ffffc0207ad4 <panic_printk+0x40>  // b.any
    ffffc0207ad0:       aa0200a5        orr     x5, x5, x2
    ffffc0207ad4:       c8047c85        stxr    w4, x5, [x4]
    ffffc0207ad8:       d5033bbf        dmb     ish
    ffffc0207adc:       35ffff24        cbnz    w4, ffffc0207ac0 <panic_printk+0x2c>

when read and write a register operand, we need to ensure that these
operands are annotated as "early clobber" if the register is written
before all of the input operands have been consumed. So need to add
early clobber for op3 to force it into a different register from op4.
Also need an early-clobber on op0 to force it into a different register
from op2 (which for purposes of register assignment is an input operand
holding an address).

With this patch, the asm code as following:
    ffffc0207a0c:       91006026        add     x6, x1, #0x18
    ffffc0207a10:       c85f7cc5        ldxr    x5, [x6]
    ffffc0207a14:       ea0200a3        ands    x3, x5, x2
    ffffc0207a18:       54000041        b.ne    ffffc0207a20 <panic_printk+0x40>  // b.any
    ffffc0207a1c:       aa0200a5        orr     x5, x5, x2
    ffffc0207a20:       c8047cc5        stxr    w4, x5, [x6]
    ffffc0207a24:       d5033bbf        dmb     ish
    ffffc0207a28:       35ffff24        cbnz    w4, ffffc0207a0c <panic_printk+0x2c>

mail: https://www.mail-archive.com/gcc@gcc.gnu.org/msg87351.html

Signed-off-by: Peng Fan <peng.fan@nxp.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
  • Loading branch information...
MrVan authored and jan-kiszka committed Feb 14, 2019
1 parent 58786d1 commit 2b9a200d6dbacccc3d58113ec26e003d24f52dc2
Showing with 2 additions and 2 deletions.
  1. +2 −2 hypervisor/arch/arm64/include/asm/bitops.h
@@ -93,9 +93,9 @@ static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
"1:\n\t"
"stxr %w0, %3, %2\n\t"
"dmb ish\n\t"
: "=r" (ret), "=&r" (test),
: "=&r" (ret), "=&r" (test),
"+Q" (*(volatile unsigned long *)addr),
"=r" (tmp)
"=&r" (tmp)
: "r" (1ul << nr));
} while (ret);
return !!(test);

0 comments on commit 2b9a200

Please sign in to comment.
You can’t perform that action at this time.