| From foo@baz Wed Nov 21 18:50:25 CET 2018 |
| From: Mark Rutland <mark.rutland@arm.com> |
| Date: Wed, 3 May 2017 16:09:38 +0100 |
| Subject: arm64: uaccess: suppress spurious clang warning |
| |
| From: Mark Rutland <mark.rutland@arm.com> |
| |
| commit d135b8b5060ea91dd751ff172d179eb4eab1e966 upstream. |
| |
| Clang tries to warn when there's a mismatch between an operand's size, |
| and the size of the register it is held in, as this may indicate a bug. |
| Specifically, clang warns when the operand's type is less than 64 bits |
| wide, and the register is used unqualified (i.e. %N rather than %xN or |
| %wN). |
| |
| Unfortunately clang can generate these warnings for unreachable code. |
| For example, for code like: |
| |
| do { \ |
| typeof(*(ptr)) __v = (v); \ |
| switch(sizeof(*(ptr))) { \ |
| case 1: \ |
| // assume __v is 1 byte wide \ |
| asm ("{op}b %w0" : : "r" (v)); \ |
| break; \ |
| case 8: \ |
| // assume __v is 8 bytes wide \ |
| asm ("{op} %0" : : "r" (v)); \ |
| break; \ |
| } |
| while (0) |
| |
| ... if op() were passed a char value and pointer to char, clang may |
| produce a warning for the unreachable case where sizeof(*(ptr)) is 8. |
| |
| For the same reasons, clang produces warnings when __put_user_err() is |
| used for types that are less than 64 bits wide. |
| |
| We could avoid this with a cast to a fixed-width type in each of the |
| cases. However, GCC will then warn that pointer types are being cast to |
| mismatched integer sizes (in unreachable paths). |
| |
| Another option would be to use the same union trickery as we do for |
| __smp_store_release() and __smp_load_acquire(), but this is fairly |
| invasive. |
| |
| Instead, this patch suppresses the clang warning by using an x modifier |
| in the assembly for the 8 byte case of __put_user_err(). No additional |
| work is necessary as the value has been cast to typeof(*(ptr)), so the |
| compiler will have performed any necessary extension for the reachable |
| case. |
| |
| For consistency, __get_user_err() is also updated to use the x modifier |
| for its 8 byte case. |
| |
| Acked-by: Will Deacon <will.deacon@arm.com> |
| Signed-off-by: Mark Rutland <mark.rutland@arm.com> |
| Reported-by: Matthias Kaehlcke <mka@chromium.org> |
| Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> |
| Signed-off-by: Nick Desaulniers <ndesaulniers@google.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| arch/arm64/include/asm/uaccess.h | 4 ++-- |
| 1 file changed, 2 insertions(+), 2 deletions(-) |
| |
| --- a/arch/arm64/include/asm/uaccess.h |
| +++ b/arch/arm64/include/asm/uaccess.h |
| @@ -198,7 +198,7 @@ do { \ |
| (err), ARM64_HAS_UAO); \ |
| break; \ |
| case 8: \ |
| - __get_user_asm("ldr", "ldtr", "%", __gu_val, (ptr), \ |
| + __get_user_asm("ldr", "ldtr", "%x", __gu_val, (ptr), \ |
| (err), ARM64_HAS_UAO); \ |
| break; \ |
| default: \ |
| @@ -272,7 +272,7 @@ do { \ |
| (err), ARM64_HAS_UAO); \ |
| break; \ |
| case 8: \ |
| - __put_user_asm("str", "sttr", "%", __pu_val, (ptr), \ |
| + __put_user_asm("str", "sttr", "%x", __pu_val, (ptr), \ |
| (err), ARM64_HAS_UAO); \ |
| break; \ |
| default: \ |