Skip to content

"invalid output constraint '+Q' in asm" when building RISCV allyesconfig #999

@nathanchance

Description

@nathanchance

On mainline RISCV allyesconfig:

$ make -j$(nproc) -s ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- LD=riscv64-linux-gnu-ld LLVM=1 LLVM_IAS=1 O=out/riscv64 distclean allyesconfig drivers/crypto/hisilicon/qm.o
drivers/crypto/hisilicon/qm.c:355:10: error: invalid output constraint '+Q' in asm
                       "+Q" (*((char __iomem *)fun_base))
                       ^

A look at the function:

/* 128 bit should be written to hardware at one time to trigger a mailbox */
static void qm_mb_write(struct hisi_qm *qm, const void *src)
{
	void __iomem *fun_base = qm->io_base + QM_MB_CMD_SEND_BASE;
	unsigned long tmp0 = 0, tmp1 = 0;

	if (!IS_ENABLED(CONFIG_ARM64)) {
		memcpy_toio(fun_base, src, 16);
		wmb();
		return;
	}

	asm volatile("ldp %0, %1, %3\n"
		     "stp %0, %1, %2\n"
		     "dsb sy\n"
		     : "=&r" (tmp0),
		       "=&r" (tmp1),
		       "+Q" (*((char __iomem *)fun_base))
		     : "Q" (*((char *)src))
		     : "memory");
}

GCC would have the same error but it does not evaluate the inline asm because it realizes that it is dead code due to the !IS_ENABLE(CONFIG_ARM64) (byproduct of #3, even though we are using the integrated assembler). If you remove that if block, GCC throws the same error:

drivers/crypto/hisilicon/qm.c: In function 'qm_mb':
drivers/crypto/hisilicon/qm.c:344:2: error: impossible constraint in 'asm'
  344 |  asm volatile("ldp %0, %1, %3\n"
      |  ^~~

This driver does not actually run on anything other than ARM64 but it gets selected by COMPILE_TEST, which was added by @arndb in a7174f9. I know that IS_ENABLED(CONFIG_...) is preferred to #ifdef CONFIG_... but there is no point in evaluating asm code that is specific to one architecture.

diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c
index f795fb557630..fbbe14b6e92c 100644
--- a/drivers/crypto/hisilicon/qm.c
+++ b/drivers/crypto/hisilicon/qm.c
@@ -341,12 +341,7 @@ static void qm_mb_write(struct hisi_qm *qm, const void *src)
        void __iomem *fun_base = qm->io_base + QM_MB_CMD_SEND_BASE;
        unsigned long tmp0 = 0, tmp1 = 0;

-       if (!IS_ENABLED(CONFIG_ARM64)) {
-               memcpy_toio(fun_base, src, 16);
-               wmb();
-               return;
-       }
-
+#ifdef CONFIG_ARM64
        asm volatile("ldp %0, %1, %3\n"
                     "stp %0, %1, %2\n"
                     "dsb sy\n"
@@ -355,6 +350,10 @@ static void qm_mb_write(struct hisi_qm *qm, const void *src)
                       "+Q" (*((char __iomem *)fun_base))
                     : "Q" (*((char *)src))
                     : "memory");
+#else
+       memcpy_toio(fun_base, src, 16);
+       wmb();
+#endif
 }

 static int qm_mb(struct hisi_qm *qm, u8 cmd, dma_addr_t dma_addr, u16 queue,

Open to other ideas though.

Metadata

Metadata

Assignees

No one assigned

    Labels

    [ARCH] risc-vThis bug impacts ARCH=riscv[BUG] linuxA bug that should be fixed in the mainline kernel.[CONFIG] allyesconfigIssue affects allyesconfig on certain architecturesunreproducibleNot or no longer reproducible

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions