https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91111

            Bug ID: 91111
           Summary: arm64 Linux kernel panics at boot due to unexpected
                    register assignment in inline asm
           Product: gcc
           Version: 8.3.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: inline-asm
          Assignee: unassigned at gcc dot gnu.org
          Reporter: will.deacon at arm dot com
  Target Milestone: ---

Created attachment 46578
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=46578&action=edit
Output of -save-temps

When compiling the Linux kernel for arm64 with CONFIG_OPTIMIZE_INLINING=y
(which effectively removes the use of __attribute__((__always_inline__)) for
functions marked as inline), the atomic64 selftest fails due to a local
register variable being assigned to a different register from the one specified
when used in an inline asm block.

While I appreciate that we're treading on thin ice here, my reading of the
docs at:

 
https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html#Local-Register-Variables

suggests that this should work.

To be more precise, this kernel code:


static inline long arch_atomic64_dec_if_positive(atomic64_t *v)
{
        register long x0 asm ("x0") = (long)v;

        asm volatile(ARM64_LSE_ATOMIC_INSN(
        /* LL/SC */
        __LL_SC_ATOMIC64(dec_if_positive)
        __nops(6),
        /* LSE atomics */
        "1:     ldr     x30, %[v]\n"
        "       subs    %[ret], x30, #1\n"
        "       b.lt    2f\n"
        "       casal   x30, %[ret], %[v]\n"
        "       sub     x30, x30, #1\n"
        "       sub     x30, x30, %[ret]\n"
        "       cbnz    x30, 1b\n"
        "2:")
        : [ret] "+&r" (x0), [v] "+Q" (v->counter)
        :
        : __LL_SC_CLOBBERS, "cc", "memory");

        return x0;
}


requires that %[ret] expands to register x0, whereas it is instead expanding to 
register x1. You can see this in the assembly code for the function:


        .align  2
        .type   arch_atomic64_dec_if_positive, %function
arch_atomic64_dec_if_positive:
.LVL0:
.LFB244:
        .file 1 "./arch/arm64/include/asm/atomic_lse.h"
        .loc 1 411 1 view -0
        .cfi_startproc
        .loc 1 412 2 view .LVU1
        .loc 1 414 2 view .LVU2
        .loc 1 411 1 is_stmt 0 view .LVU3
        stp     x29, x30, [sp, -16]!
        .cfi_def_cfa_offset 16
        .cfi_offset 29, -16
        .cfi_offset 30, -8
.LVL1:
        .loc 1 414 2 view .LVU4
        mov     x1, x0
        .loc 1 411 1 view .LVU5
        mov     x29, sp
        .loc 1 414 2 view .LVU6
#APP
// 414 "./arch/arm64/include/asm/atomic_lse.h" 1
        .if 1 == 1
661:
        bl      __ll_sc_arch_atomic64_dec_if_positive
.rept   6
nop
.endr

662:
.pushsection .altinstructions,"a"
 .word 661b - .
 .if 0 == 0
 .word 663f - .
 .else
 .word 0- .
 .endif
 .hword 5
 .byte 662b-661b
 .byte 664f-663f
.popsection
 .if 0 == 0
.pushsection .altinstr_replacement, "a"
663:
        1:      ldr     x30, [x0]
        subs    x1, x30, #1
        b.lt    2f
        casal   x30, x1, [x0]
        sub     x30, x30, #1
        sub     x30, x30, x1
        cbnz    x30, 1b
2:
664:
        .popsection
        .org    . - (664b-663b) + (662b-661b)
        .org    . - (662b-661b) + (664b-663b)
.else
        663:
        664:
        .endif
.endif

// 0 "" 2
.LVL2:
        .loc 1 414 2 view .LVU7
#NO_APP
        mov     x0, x1
.LVL3:
        .loc 1 431 2 is_stmt 1 view .LVU8
        .loc 1 432 1 is_stmt 0 view .LVU9
        ldp     x29, x30, [sp], 16
        .cfi_restore 30
        .cfi_restore 29
        .cfi_def_cfa_offset 0
        ret
        .cfi_endproc
.LFE244:
        .size   arch_atomic64_dec_if_positive, .-arch_atomic64_dec_if_positive


I've attached the .i/.s files output by:

aarch64-linux-gnu-gcc -save-temps -Wp,-MD,lib/.atomic64_test.o.d  -nostdinc
-isystem
/home/will/system/aarch64/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/8.3.0/include
-I./arch/arm64/include -I./arch/arm64/include/generated  -I./include
-I./arch/arm64/include/uapi -I./arch/arm64/include/generated/uapi
-I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h
-include ./include/linux/compiler_types.h -D__KERNEL__ -mlittle-endian
-DKASAN_SHADOW_SCALE_SHIFT=3 -Wall -Wundef -Werror=strict-prototypes
-Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE
-Werror=implicit-function-declaration -Werror=implicit-int -Wno-format-security
-std=gnu89 -mgeneral-regs-only -DCONFIG_AS_LSE=1
-fno-asynchronous-unwind-tables -Wno-psabi -mabi=lp64
-DKASAN_SHADOW_SCALE_SHIFT=3 -fno-delete-null-pointer-checks -Wno-frame-address
-Wno-format-truncation -Wno-format-overflow -O2
--param=allow-store-data-races=0 -Wframe-larger-than=2048
-fstack-protector-strong -Wno-unused-but-set-variable
-Wno-unused-const-variable -fno-omit-frame-pointer -fno-optimize-sibling-calls
-fno-var-tracking-assignments -g -Wdeclaration-after-statement -Wvla
-Wno-pointer-sign -Wno-stringop-truncation -fno-strict-overflow
-fno-merge-all-constants -fmerge-constants -fno-stack-check -fconserve-stack
-Werror=date-time -Werror=incompatible-pointer-types -Werror=designated-init
-fmacro-prefix-map=./= -Wno-packed-not-aligned   
-DKBUILD_BASENAME='"atomic64_test"' -DKBUILD_MODNAME='"atomic64_test"' -c -o
lib/atomic64_test.o lib/atomic64_test.c

Reply via email to