Linux: invalid output size for constraint '=q' in arch/x86/events/amd/core.c

Created on 8 Oct 2018  路  22Comments  路  Source: ClangBuiltLinux/linux

In file included from arch/x86/events/amd/core.c:8:
arch/x86/events/amd/../perf_event.h:774:21: error: invalid output size for constraint '=q'
        u64 disable_mask = __this_cpu_read(cpu_hw_events.perf_ctr_virt_mask);
                           ^
./include/linux/percpu-defs.h:448:2: note: expanded from macro '__this_cpu_read'
        raw_cpu_read(pcp);                                              \
        ^
./include/linux/percpu-defs.h:422:28: note: expanded from macro 'raw_cpu_read'
#define raw_cpu_read(pcp)               __pcpu_size_call_return(raw_cpu_read_, pcp)
                                        ^
./include/linux/percpu-defs.h:323:23: note: expanded from macro '__pcpu_size_call_return'
        case 1: pscr_ret__ = stem##1(variable); break;                  \
                             ^
<scratch space>:99:1: note: expanded from here
raw_cpu_read_1
^
./arch/x86/include/asm/percpu.h:394:30: note: expanded from macro 'raw_cpu_read_1'
#define raw_cpu_read_1(pcp)             percpu_from_op("mov", pcp)
                                        ^
./arch/x86/include/asm/percpu.h:189:15: note: expanded from macro 'percpu_from_op'
                    : "=q" (pfo_ret__)                  \
                            ^
In file included from arch/x86/events/amd/core.c:8:
arch/x86/events/amd/../perf_event.h:774:21: error: invalid output size for constraint '=q'
./include/linux/percpu-defs.h:448:2: note: expanded from macro '__this_cpu_read'
        raw_cpu_read(pcp);                                              \
        ^
./include/linux/percpu-defs.h:422:28: note: expanded from macro 'raw_cpu_read'
#define raw_cpu_read(pcp)               __pcpu_size_call_return(raw_cpu_read_, pcp)
                                        ^
./include/linux/percpu-defs.h:324:23: note: expanded from macro '__pcpu_size_call_return'
        case 2: pscr_ret__ = stem##2(variable); break;                  \
                             ^
<scratch space>:108:1: note: expanded from here
raw_cpu_read_2
^
./arch/x86/include/asm/percpu.h:395:30: note: expanded from macro 'raw_cpu_read_2'
#define raw_cpu_read_2(pcp)             percpu_from_op("mov", pcp)
                                        ^
./arch/x86/include/asm/percpu.h:189:15: note: expanded from macro 'percpu_from_op'
                    : "=q" (pfo_ret__)                  \
                            ^
In file included from arch/x86/events/amd/core.c:8:
arch/x86/events/amd/../perf_event.h:774:21: error: invalid output size for constraint '=q'
./include/linux/percpu-defs.h:448:2: note: expanded from macro '__this_cpu_read'
        raw_cpu_read(pcp);                                              \
        ^
./include/linux/percpu-defs.h:422:28: note: expanded from macro 'raw_cpu_read'
#define raw_cpu_read(pcp)               __pcpu_size_call_return(raw_cpu_read_, pcp)
                                        ^
./include/linux/percpu-defs.h:325:23: note: expanded from macro '__pcpu_size_call_return'
        case 4: pscr_ret__ = stem##4(variable); break;                  \
                             ^
<scratch space>:117:1: note: expanded from here
raw_cpu_read_4
^
./arch/x86/include/asm/percpu.h:396:30: note: expanded from macro 'raw_cpu_read_4'
#define raw_cpu_read_4(pcp)             percpu_from_op("mov", pcp)
                                        ^
./arch/x86/include/asm/percpu.h:189:15: note: expanded from macro 'percpu_from_op'
                    : "=q" (pfo_ret__)                  \
                            ^
3 errors generated.
[ARCH] x86 [BUG] linux [FIXED][LINUX] 5.9

Most helpful comment

All 22 comments

arch/x86/kernel/cpu/intel.c:98:2: error: invalid input size for constraint 'qi'
        this_cpu_or(msr_misc_features_shadow,
        ^
./include/linux/percpu-defs.h:513:32: note: expanded from macro 'this_cpu_or'
#define this_cpu_or(pcp, val)           __pcpu_size_call(this_cpu_or_, pcp, val)
                                        ^
./include/linux/percpu-defs.h:379:11: note: expanded from macro '__pcpu_size_call'
                case 1: stem##1(variable, __VA_ARGS__);break;           \
                        ^
<scratch space>:305:1: note: expanded from here
this_cpu_or_1
^
./arch/x86/include/asm/percpu.h:426:34: note: expanded from macro 'this_cpu_or_1'
#define this_cpu_or_1(pcp, val)         percpu_to_op("or", (pcp), val)
                                        ^
./arch/x86/include/asm/percpu.h:102:15: note: expanded from macro 'percpu_to_op'
                    : "qi" ((pto_T__)(val)));           \
                            ^
arch/x86/kernel/cpu/intel.c:98:2: error: invalid input size for constraint 'qi'
./include/linux/percpu-defs.h:513:32: note: expanded from macro 'this_cpu_or'
#define this_cpu_or(pcp, val)           __pcpu_size_call(this_cpu_or_, pcp, val)
                                        ^
./include/linux/percpu-defs.h:380:11: note: expanded from macro '__pcpu_size_call'
                case 2: stem##2(variable, __VA_ARGS__);break;           \
                        ^
<scratch space>:314:1: note: expanded from here
this_cpu_or_2
^
./arch/x86/include/asm/percpu.h:427:34: note: expanded from macro 'this_cpu_or_2'
#define this_cpu_or_2(pcp, val)         percpu_to_op("or", (pcp), val)
                                        ^
./arch/x86/include/asm/percpu.h:102:15: note: expanded from macro 'percpu_to_op'
                    : "qi" ((pto_T__)(val)));           \
                            ^
arch/x86/kernel/cpu/intel.c:98:2: error: invalid input size for constraint 'qi'
./include/linux/percpu-defs.h:513:32: note: expanded from macro 'this_cpu_or'
#define this_cpu_or(pcp, val)           __pcpu_size_call(this_cpu_or_, pcp, val)
                                        ^
./include/linux/percpu-defs.h:381:11: note: expanded from macro '__pcpu_size_call'
                case 4: stem##4(variable, __VA_ARGS__);break;           \
                        ^
<scratch space>:323:1: note: expanded from here
this_cpu_or_4
^
./arch/x86/include/asm/percpu.h:428:34: note: expanded from macro 'this_cpu_or_4'
#define this_cpu_or_4(pcp, val)         percpu_to_op("or", (pcp), val)
                                        ^
./arch/x86/include/asm/percpu.h:102:15: note: expanded from macro 'percpu_to_op'
                    : "qi" ((pto_T__)(val)));           \
                            ^
arch/x86/kernel/cpu/intel.c:647:2: error: invalid input size for constraint 'qi'
        this_cpu_write(msr_misc_features_shadow, 0);
        ^
./include/linux/percpu-defs.h:510:34: note: expanded from macro 'this_cpu_write'
#define this_cpu_write(pcp, val)        __pcpu_size_call(this_cpu_write_, pcp, val)
                                        ^
./include/linux/percpu-defs.h:379:11: note: expanded from macro '__pcpu_size_call'
                case 1: stem##1(variable, __VA_ARGS__);break;           \
                        ^
<scratch space>:187:1: note: expanded from here
this_cpu_write_1
^
./arch/x86/include/asm/percpu.h:417:36: note: expanded from macro 'this_cpu_write_1'
#define this_cpu_write_1(pcp, val)      percpu_to_op("mov", (pcp), val)
                                        ^
./arch/x86/include/asm/percpu.h:102:15: note: expanded from macro 'percpu_to_op'
                    : "qi" ((pto_T__)(val)));           \
                            ^
arch/x86/kernel/cpu/intel.c:647:2: error: invalid input size for constraint 'qi'
./include/linux/percpu-defs.h:510:34: note: expanded from macro 'this_cpu_write'
#define this_cpu_write(pcp, val)        __pcpu_size_call(this_cpu_write_, pcp, val)
                                        ^
./include/linux/percpu-defs.h:380:11: note: expanded from macro '__pcpu_size_call'
                case 2: stem##2(variable, __VA_ARGS__);break;           \
                        ^
<scratch space>:196:1: note: expanded from here
this_cpu_write_2
^
./arch/x86/include/asm/percpu.h:418:36: note: expanded from macro 'this_cpu_write_2'
#define this_cpu_write_2(pcp, val)      percpu_to_op("mov", (pcp), val)
                                        ^
./arch/x86/include/asm/percpu.h:102:15: note: expanded from macro 'percpu_to_op'
                    : "qi" ((pto_T__)(val)));           \
                            ^
arch/x86/kernel/cpu/intel.c:647:2: error: invalid input size for constraint 'qi'
./include/linux/percpu-defs.h:510:34: note: expanded from macro 'this_cpu_write'
#define this_cpu_write(pcp, val)        __pcpu_size_call(this_cpu_write_, pcp, val)
                                        ^
./include/linux/percpu-defs.h:381:11: note: expanded from macro '__pcpu_size_call'
                case 4: stem##4(variable, __VA_ARGS__);break;           \
                        ^
<scratch space>:205:1: note: expanded from here
this_cpu_write_4
^
./arch/x86/include/asm/percpu.h:419:36: note: expanded from macro 'this_cpu_write_4'
#define this_cpu_write_4(pcp, val)      percpu_to_op("mov", (pcp), val)
                                        ^
./arch/x86/include/asm/percpu.h:102:15: note: expanded from macro 'percpu_to_op'
                    : "qi" ((pto_T__)(val)));           \
                            ^
6 errors generated.

I submitted it to LLVM bugzilla: https://bugs.llvm.org/show_bug.cgi?id=33587

It's already in this issue tracker as #3, should this now be closed as duplicate?

Reopening this to track linux patches fixing this problem. Currently, two independent solutions exist:

--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -99,7 +99,7 @@ do {                          \
    case 1:                     \
        asm qual (op "b %1,"__percpu_arg(0) \
            : "+m" (var)            \
-           : "qi" ((pto_T__)(val)));       \
+           : "ri" ((pto_T__)(val)));       \
        break;                  \
    case 2:                     \
        asm qual (op "w %1,"__percpu_arg(0) \
@@ -144,7 +144,7 @@ do {                                    \
        else                            \
            asm qual ("addb %1, "__percpu_arg(0)        \
                : "+m" (var)                \
-               : "qi" ((pao_T__)(val)));           \
+               : "ri" ((pao_T__)(val)));           \
        break;                          \
    case 2:                             \
        if (pao_ID__ == 1)                  \
@@ -186,7 +186,7 @@ do {                                    \
    switch (sizeof(var)) {              \
    case 1:                     \
        asm qual (op "b "__percpu_arg(1)",%0"   \
-           : "=q" (pfo_ret__)          \
+           : "=r" (pfo_ret__)          \
            : "m" (var));           \
        break;                  \
    case 2:                     \
@@ -215,7 +215,7 @@ do {                                    \
    switch (sizeof(var)) {              \
    case 1:                     \
        asm(op "b "__percpu_arg(P1)",%0"    \
-           : "=q" (pfo_ret__)          \
+           : "=r" (pfo_ret__)          \
            : "p" (&(var)));            \
        break;                  \
    case 2:                     \
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -99,7 +99,7 @@ do {                          \
    case 1:                     \
        asm qual (op "b %1,"__percpu_arg(0) \
            : "+m" (var)            \
-           : "qi" ((pto_T__)(val)));       \
+           : "qi" ((unsigned char)(unsigned long)(val))); \
        break;                  \
    case 2:                     \
        asm qual (op "w %1,"__percpu_arg(0) \
@@ -144,7 +144,7 @@ do {                                    \
        else                            \
            asm qual ("addb %1, "__percpu_arg(0)        \
                : "+m" (var)                \
-               : "qi" ((pao_T__)(val)));           \
+               : "qi" ((unsigned char)(unsigned long)(val))); \
        break;                          \
    case 2:                             \
        if (pao_ID__ == 1)                  \
@@ -182,12 +182,14 @@ do {                                  \

 #define percpu_from_op(qual, op, var)          \
 ({                         \
+   unsigned char pfo_u8__;             \
    typeof(var) pfo_ret__;              \
    switch (sizeof(var)) {              \
    case 1:                     \
        asm qual (op "b "__percpu_arg(1)",%0"   \
-           : "=q" (pfo_ret__)          \
+           : "=q" (pfo_u8__)           \
            : "m" (var));           \
+       pfo_ret__ = (typeof(var))(unsigned long)pfo_u8__;   \
        break;                  \
    case 2:                     \
        asm qual (op "w "__percpu_arg(1)",%0"   \
@@ -211,12 +213,14 @@ do {                                  \

 #define percpu_stable_op(op, var)          \
 ({                         \
+   unsigned char pfo_u8__;             \
    typeof(var) pfo_ret__;              \
    switch (sizeof(var)) {              \
    case 1:                     \
        asm(op "b "__percpu_arg(P1)",%0"    \
-           : "=q" (pfo_ret__)          \
+           : "=q" (pfo_u8__)           \
            : "p" (&(var)));            \
+       pfo_ret__ = (typeof(var))(unsigned long)pfo_u8__;   \
        break;                  \
    case 2:                     \
        asm(op "w "__percpu_arg(P1)",%0"    \

They both work equally good, but I can't tell which solution is better. Anyway I believe one of these patches should be resent to LKML to be included in the kernel.

Cool, thanks for finding and documenting both of these; I suspect we can start a discussion with both @arndb and dwm on LKML+x86 mailing list for thoughts.

technically a case of #3

The problem with my patch is that it does not work when the compiler picks register ESI/EDI/EBP on i386, as using the lower 8 bits only works on registers EAX/EBX/ECX/EDX. This causes occasional build failures in random files. @dwmw2's patch looks correct to me, I'll give it some more randconfig testing.

The whole series for this has landed in the percpu tree, scheduled for 5.9 (see 11 patches from Brian Gerst and myself): https://git.kernel.org/pub/scm/linux/kernel/git/dennis/percpu.git/log/?h=for-5.9

It's cool man.

How do I pass i386_defconfig to make in an x86-64 build-environment?
And which prerequirements do I need?
Here I have an x86 multiarch environment.

I tried this but did not a full i386_defconfig build:

MAKE_OPTS="HOSTCC=clang-11 HOSTCXX=clang++-11 HOSTLD=ld.lld-11 HOSTAR=llvm-ar-11 CC=clang-11 LD=ld.lld-11 AR=llvm-ar-11 NM=llvm-nm-11 OBJCOPY=llvm-objcopy-11 OBJDUMP=llvm-objdump-11 OBJSIZE=llvm-size-11 READELF=llvm-readelf-11 STRIP=llvm-strip-11 LLVM_IAS=1"

$ ARCH=x86 make V=1 -j3 $MAKE_OPTS i386_defconfig

$ ARCH=x86 make V=1 -j3 $MAKE_OPTS

i386_defconfig_config-generated.txt has:

# Linux/x86 5.8.0-rc6 Kernel Configuration
CONFIG_X86_32=y
CONFIG_X86=y
CONFIG_X86_32_SMP=y

Generated linux-config is attached.

i386_defconfig_config-generated.txt

IIUC, I think:

$ make ... i386_defconfig

and

$ ARCH=i386 make defconfig

are equivalent, though I haven't compared .configs from the two.

$ make allnoconfig

happens to be i386, too.

I usually test with make ... i386_defconfig.

Doing:

$ ARCH=i386 make V=1 -j3 $MAKE_OPTS i386_defconfig

...and looking at the diff:

$ diff -uprN ../i386_defconfig.config ../i386_defconfig.config-v2
--- ../i386_defconfig.config    2020-07-22 14:58:36.346842915 +0200
+++ ../i386_defconfig.config-v2 2020-07-22 20:37:00.265095068 +0200
@@ -1,6 +1,6 @@
 #
 # Automatically generated file; DO NOT EDIT.
-# Linux/x86 5.8.0-rc6 Kernel Configuration
+# Linux/i386 5.8.0-rc6 Kernel Configuration
 #
 CONFIG_CC_VERSION_TEXT="clang version 11.0.0 (https://github.com/llvm/llvm-project cebd637c88624dfd44520848cb1f43dc8a02ba80)"
 CONFIG_GCC_VERSION=0
@@ -241,7 +241,6 @@ CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
 # end of General setup

-# CONFIG_64BIT is not set
 CONFIG_X86_32=y
 CONFIG_X86=y
 CONFIG_INSTRUCTION_DECODER=y

Hmm, there is no CONFIG_64BIT - isn't that checked for in some places to distinguish with x86 (32bit) and/or x86_32?

Produces the same .config:

$ ARCH=x86 make V=1 -j3 $MAKE_OPTS i386_defconfig

$ make V=1 -j3 $MAKE_OPTS i386_defconfig

Both ARCH=i386 and ARCH=x86 let clang-11 compile with -march=i686 -mtune=generic.

So hat config should be named x86_defconfig not i386_defconfig (might be historical reasons).
AFAICS i386code was thrown out and is no more supported.

x86_defconfig would be consistent with x86_64_defconfig:

$ find arch/x86 -name '*defconfig'
arch/x86/configs/i386_defconfig
arch/x86/configs/x86_64_defconfig

This has nothing to do with i386 see CONFIG_CRYPTO_AES_586:

$ grep 86 arch/x86/configs/i386_defconfig
CONFIG_X86_GENERIC=y
CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y
CONFIG_X86_MCE=y
CONFIG_X86_REBOOTFIXUPS=y
CONFIG_X86_MSR=y
CONFIG_X86_CPUID=y
CONFIG_X86_CHECK_BIOS_CORRUPTION=y
CONFIG_X86_ACPI_CPUFREQ=y
CONFIG_CRYPTO_AES_586=y

That seems to be some old relicts?

$ git grep "ARCH=i386"
Documentation/kbuild/headers_install.rst:  make headers_install ARCH=i386 INSTALL_HDR_PATH=/usr
tools/testing/ktest/examples/crosstests.conf:MAKE_CMD = make ARCH=i386
tools/testing/ktest/sample.conf:#MAKE_CMD = CC=i386-gcc AS=i386-as make ARCH=i386

So minimum supported CPU is CONFIG_M486 - there is no CONFIG_M386.

Checked with gcc-9 - all generated .config file set CONFIG_M686=y.

Pah, that's also some old cruft:

$ git grep CRYPTO_AES_586
arch/x86/configs/i386_defconfig:CONFIG_CRYPTO_AES_586=y

As a side-note:

"x86/defconfigs: Remove CONFIG_CRYPTO_AES_586 from i386_defconfig" landed in <tip.git#x86/build>.

[1] https://git.kernel.org/tip/tip/c/6526b12de07588253a52577f42ec99fc7ca26a1f

A nice i386_defconfig cleanup:
"x86/defconfigs/32: Unset 64BIT"

[1] https://lore.kernel.org/patchwork/patch/1286107/

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nickdesaulniers picture nickdesaulniers  路  4Comments

nathanchance picture nathanchance  路  4Comments

nickdesaulniers picture nickdesaulniers  路  3Comments

nickdesaulniers picture nickdesaulniers  路  4Comments

tpgxyz picture tpgxyz  路  4Comments