From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
To: Nathan Chancellor <nathan@kernel.org>
Cc: Jiri Kosina <jikos@kernel.org>,
Benjamin Tissoires <bentiss@kernel.org>,
linux-input@vger.kernel.org, linux-kernel@vger.kernel.org,
llvm@lists.linux.dev, paulmck@kernel.org, sfr@canb.auug.org.au,
jpoimboe@kernel.org, linux-toolchains@vger.kernel.org
Subject: Re: [PATCH] HID: simplify code in fetch_item()
Date: Tue, 15 Oct 2024 11:28:26 -0700 [thread overview]
Message-ID: <Zw60Sj-iFh1KWwWG@google.com> (raw)
In-Reply-To: <20241010222451.GA3571761@thelio-3990X>
Hi Nathan,
On Thu, Oct 10, 2024 at 03:24:51PM -0700, Nathan Chancellor wrote:
> Hi Dmitry,
>
> On Tue, Oct 01, 2024 at 08:42:36AM -0700, Dmitry Torokhov wrote:
> > We can easily calculate the size of the item using arithmetic (shifts).
> > This allows to pull duplicated code out of the switch statement, making
> > it cleaner.
> >
> > Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> > ---
> > drivers/hid/hid-core.c | 31 ++++++++++++++-----------------
> > 1 file changed, 14 insertions(+), 17 deletions(-)
> >
> > diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
> > index 988d0acbdf04..00942d40fe08 100644
> > --- a/drivers/hid/hid-core.c
> > +++ b/drivers/hid/hid-core.c
> > @@ -754,35 +754,32 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
> > }
> >
> > item->format = HID_ITEM_FORMAT_SHORT;
> > - item->size = b & 3;
> > + item->size = BIT(b & 3) >> 1; /* 0, 1, 2, 3 -> 0, 1, 2, 4 */
> > +
> > + if (end - start < item->size)
> > + return NULL;
> >
> > switch (item->size) {
> > case 0:
> > - return start;
> > + break;
> >
> > case 1:
> > - if ((end - start) < 1)
> > - return NULL;
> > - item->data.u8 = *start++;
> > - return start;
> > + item->data.u8 = *start;
> > + break;
> >
> > case 2:
> > - if ((end - start) < 2)
> > - return NULL;
> > item->data.u16 = get_unaligned_le16(start);
> > - start = (__u8 *)((__le16 *)start + 1);
> > - return start;
> > + break;
> >
> > - case 3:
> > - item->size++;
> > - if ((end - start) < 4)
> > - return NULL;
> > + case 4:
> > item->data.u32 = get_unaligned_le32(start);
> > - start = (__u8 *)((__le32 *)start + 1);
> > - return start;
> > + break;
> > +
> > + default:
> > + unreachable();
> > }
> >
> > - return NULL;
> > + return start + item->size;
> > }
>
> I am noticing some interesting behavior when building with clang, namely
> some objtool warnings and a failed boot when LTO is enabled, which I
> bisected to this change as commit 61595012f280 ("HID: simplify code in
> fetch_item()"), such as:
>
> $ make -skj"$(nproc)" ARCH=x86_64 LLVM=1 mrproper defconfig vmlinux
> vmlinux.o: warning: objtool: hid_open_report() falls through to next function hid_parser_main()
> vmlinux.o: warning: objtool: hid_scan_report() falls through to next function hid_allocate_device()
>
> With LTO enabled, the warning becomes:
>
> vmlinux.o: warning: objtool: hid_open_report+0x21b: can't find jump dest instruction at .text.hid_open_report+0x40f
>
> A bare unreachable(), especially in the default case of a switch
> statement, is generally considered harmful in my experience, as it can
> introduce undefined behavior, which can mess up how a compiler might
> optimize a function. Commit d652d5f1eeeb ("drm/edid: fix objtool warning
> in drm_cvt_modes()") and commit 3764647b255a ("bcachefs: Remove
> undefined behavior in bch2_dev_buckets_reserved()") have some good
> commit messages talking about it.
>
> Getting rid of the unreachable() in some way resolves the issue. I
> tested using BUG() in lieu of unreachable() like the second change I
> mentioned above, which resolves the issue cleanly, as the default case
> clearly cannot happen. Another option I tested was some sort of printk
> statement and returning NULL, which some maintainers prefer, even in
> spite of impossible conditions. I am happy to send a patch with one of
> those changes or open to other suggestions.
Oh well, if our toolchain does not like "unreachable()" then we can
simply remove it - the switch does cover all possible values and the
"return" statement should be valid even if compiler somehow decides that
"switch" statement can be skipped.
If you can send a patch that would be great.
I'm adding Paul and a few others to CC who apparently seeing the same
issue.
Thanks.
--
Dmitry
next prev parent reply other threads:[~2024-10-15 18:28 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-01 15:42 [PATCH] HID: simplify code in fetch_item() Dmitry Torokhov
2024-10-04 12:05 ` Benjamin Tissoires
2024-10-10 22:24 ` Nathan Chancellor
2024-10-15 18:28 ` Dmitry Torokhov [this message]
2024-10-15 18:56 ` Paul E. McKenney
2024-10-15 19:26 ` Nathan Chancellor
2024-10-15 20:59 ` Segher Boessenkool
2025-04-14 6:30 ` Andy Shevchenko
2025-04-15 0:33 ` Nathan Chancellor
2025-04-15 6:45 ` Andy Shevchenko
2025-04-15 15:21 ` Nathan Chancellor
2025-04-16 6:48 ` Andy Shevchenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Zw60Sj-iFh1KWwWG@google.com \
--to=dmitry.torokhov@gmail.com \
--cc=bentiss@kernel.org \
--cc=jikos@kernel.org \
--cc=jpoimboe@kernel.org \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-toolchains@vger.kernel.org \
--cc=llvm@lists.linux.dev \
--cc=nathan@kernel.org \
--cc=paulmck@kernel.org \
--cc=sfr@canb.auug.org.au \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.