Message ID | CACRpkdZtVNZFWSUgb4=gUE2mQRb=aT_3=zRv1U71Vsq0Mm34eg@mail.gmail.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:a5a7:0:b0:403:3b70:6f57 with SMTP id d7csp290307vqn; Wed, 29 Nov 2023 04:09:23 -0800 (PST) X-Google-Smtp-Source: AGHT+IG2IjiAR5QjEe8fr1uz2DgIZk2FYPIzAFEEtpasufxSGtIi2Kr7UOJF4Xjpxnn9AfBhLcDv X-Received: by 2002:a05:6a20:3ca0:b0:18d:c72:63b3 with SMTP id b32-20020a056a203ca000b0018d0c7263b3mr1737726pzj.16.1701259763152; Wed, 29 Nov 2023 04:09:23 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1701259763; cv=none; d=google.com; s=arc-20160816; b=A40KH42CnZwF7jAvd4Q3yEXKlvyE8lA2GdfIup4Ci/S3T/+6cKWVWzVW63bazo9xCj kaKQi1hRZR3aV72La8+EO7X6Sr8zNJLm41WxmnumHnY7R8kVxtBAhvTen8nEPzQ74LZP YLkAsCvZ3GV/rurmuGtX3rT5bYWFgWK8VFV41R4OWvGMRrmkljLPvu3qh9s/Cj9rvEyY wSIv/GkT+x8ZqSTJv45/9DpZ/mcaM1HBja+2jr5idyNwmpThTKmPSqFEa74Weh1tQJ5N tA9z+iLMz9f3kHM+RkysDRdb+Onv8xJagey4NEK3iJBhf1txPaynii7jQvQQTXdYpIe9 m50Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:subject:message-id:date:from:mime-version :dkim-signature; bh=ZSr6rQHau8MO7tZUGmumMJZcmC8BlwDTZpr5Z2aRZIc=; fh=n+gQ2bUUqmKiUN2zTAA+nnVTHhn0gjXJAIWutM9B4Cs=; b=WGtOY0CbgfgxcijgJu6J/nqQhAogmKx6SKWHWNvUmvngS7JHzlwRVeoS8HHJdH3bTb U6oyop2LGGWOzxBFgO5q6g3Wd2EjN16EbKE7TpbtqxkM8Z6nN9QxWHHzSsvRER6SH17v 5iJOwrGVCkKUo8Oouk1sH87RTSCv3T1iKmdQ4SakHyrNemmWLxJASqNXdEWMhNGufb5w XrkyTZz6QzNWQMHlJSvaCl2S4rqycVcZrdotP0btrnGMTG1gqmTcaYz4E56wNimrLgLR zQ/p4ujDFTLkxI0rObEwRIbBbuFvGf2BVVJY9+Xx3QUMAkFXhyhE0ldn+G42xZ1aVgdK 2CTA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=N1qIwRk7; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from snail.vger.email (snail.vger.email. [23.128.96.37]) by mx.google.com with ESMTPS id y18-20020aa79e12000000b006be08015248si13561530pfq.294.2023.11.29.04.09.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Nov 2023 04:09:23 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) client-ip=23.128.96.37; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=N1qIwRk7; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by snail.vger.email (Postfix) with ESMTP id A31858031B35; Wed, 29 Nov 2023 04:09:19 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at snail.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233203AbjK2MJK (ORCPT <rfc822;toshivichauhan@gmail.com> + 99 others); Wed, 29 Nov 2023 07:09:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43718 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233160AbjK2MJJ (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Wed, 29 Nov 2023 07:09:09 -0500 Received: from mail-yw1-x1136.google.com (mail-yw1-x1136.google.com [IPv6:2607:f8b0:4864:20::1136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E9F3EDE for <linux-kernel@vger.kernel.org>; Wed, 29 Nov 2023 04:09:15 -0800 (PST) Received: by mail-yw1-x1136.google.com with SMTP id 00721157ae682-5d279bcce64so4796647b3.3 for <linux-kernel@vger.kernel.org>; Wed, 29 Nov 2023 04:09:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1701259755; x=1701864555; darn=vger.kernel.org; h=cc:to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=ZSr6rQHau8MO7tZUGmumMJZcmC8BlwDTZpr5Z2aRZIc=; b=N1qIwRk7DcQkI2LeJc/AIAkNCSvXncBESWESRvTdWPOqxXlre170ruoDAZzOZh755D Wznh06qBPIBUMcp+HvFa8Ei+le3c522MpHt/vaR/kKuTIOE39Q28d9wFXrGKiL2+mWl5 aSMEN6yKCS9SngtnjpqaZvd2rJcwD8VZVprYT7aM9ejyjy4Cpe8XMAqTSiDsraE3gAQY 4PfqdLFvTa/2Dj750LkH79FMo2xCrYigdAM4pw10wYBpY9Ew+Yegiaw2wuSIDi1h8dYa wZ9EI88N+NHW9Ytg9l/OM2Yrloyw85Cxk+oFpMTqGU5G4M9Kc4Df+zVZOf0PM2xqcESr BOGQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701259755; x=1701864555; h=cc:to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=ZSr6rQHau8MO7tZUGmumMJZcmC8BlwDTZpr5Z2aRZIc=; b=QfMy1Vru/DWFTkwBvopAX+CPDbZZ1nW2qczojOqKS0ea1lpMIcor7nJ9Oj5eHGUrL1 Q34bquupMYHT1yRLXohb/sWQFpIurpIGeOeY+qmSibNCmKCgHWdPssTuBh6tYXA8/Uxo bRbHuCoBLlQELeGQhYbFrlFGa/vRnV5XwY/fV3u/MWXi7xVrnff3DCHfVHqHoMeo+z1l CPcZu+vXNSB30aYV8RWSY7UJDiIagx/r5NmJ08FRu6nBRrnGlD0tJP/Jw2UE4E+tnE3G 5z2qZnb5n8J3Hxrox7SEKVide35wSerYW9Z5tj61Ctj1KHfi+E4H/VpTVyfCLfY36YtC 1asA== X-Gm-Message-State: AOJu0Yyqi58wCRZCwRjJ1SBB5ghdq0vO9iG6hflhK5+OcWNBRjJaND+s C7MeSSzhTrwWc2WZsRrQ5QVZM8XDo4UyJyb268d4sg== X-Received: by 2002:a05:690c:4613:b0:5d0:1d51:2e10 with SMTP id gw19-20020a05690c461300b005d01d512e10mr9159385ywb.23.1701259755133; Wed, 29 Nov 2023 04:09:15 -0800 (PST) MIME-Version: 1.0 From: Linus Walleij <linus.walleij@linaro.org> Date: Wed, 29 Nov 2023 13:09:03 +0100 Message-ID: <CACRpkdZtVNZFWSUgb4=gUE2mQRb=aT_3=zRv1U71Vsq0Mm34eg@mail.gmail.com> Subject: [GIT PULL] Pin control fixes for v6.7 To: Linus Torvalds <torvalds@linux-foundation.org> Cc: "open list:GPIO SUBSYSTEM" <linux-gpio@vger.kernel.org>, linux-kernel <linux-kernel@vger.kernel.org>, Maria Yu <quic_aiquny@quicinc.com>, Charles Keepax <ckeepax@opensource.cirrus.com>, Chester Lin <clin@suse.com> Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (snail.vger.email [0.0.0.0]); Wed, 29 Nov 2023 04:09:19 -0800 (PST) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1783900157000612823 X-GMAIL-MSGID: 1783900157000612823 |
Series |
[GIT,PULL] Pin control fixes for v6.7
|
|
Pull-request
git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git tags/pinctrl-v6.7-2Message
Linus Walleij
Nov. 29, 2023, 12:09 p.m. UTC
Hi Linus, this is a first belated round of pin control fixes for the v6.7 series.. The most interesting patch is the list iterator fix in the core by Maria Yu, it took a while for me to realize what was going on there. Some details on the fixes are in the tag. Please pull them in! Yours, Linus Walleij The following changes since commit b85ea95d086471afb4ad062012a4d73cd328fa86: Linux 6.7-rc1 (2023-11-12 16:19:07 -0800) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git tags/pinctrl-v6.7-2 for you to fetch changes up to 90785ea8158b6923c5d6a024f2b1c076110577b5: dt-bindings: pinctrl: s32g2: change a maintainer email address (2023-11-24 11:21:55 +0100) ---------------------------------------------------------------- Some pin control fixes for the v6.7 cycle: - Fix a really interesting potential core bug in the list iterator requireing the use of READ_ONCE() discovered when testing kernel compiles with clang. - Check devm_kcalloc() return value and an array bounds in the STM32 driver. - Fix an exotic string truncation issue in the s32cc driver, found by the kernel test robot (impressive!) - Fix an undocumented struct member in the cy8c95x0 driver. - Fix a symbol overlap with MIPS in the Lochnagar driver, MIPS defines a global symbol "RST" which is a bit too generic and collide with stuff. OK this one should be renamed too, we will fix that as well. - Fix erroneous branch taking in the Realtek driver. - Fix the mail address in MAINTAINERS for the s32g2 driver. ---------------------------------------------------------------- Antonio Borneo (1): pinctrl: stm32: fix array read out of bound Charles Keepax (1): pinctrl: lochnagar: Don't build on MIPS Chen Ni (1): pinctrl: stm32: Add check for devm_kcalloc Chester Lin (2): pinctrl: s32cc: Avoid possible string truncation dt-bindings: pinctrl: s32g2: change a maintainer email address Linus Walleij (1): pinctrl: cy8c95x0: Fix doc warning Maria Yu (1): pinctrl: avoid reload of p state in list iteration Tzuyi Chang (1): pinctrl: realtek: Fix logical error when finding descriptor .../bindings/pinctrl/nxp,s32g2-siul2-pinctrl.yaml | 2 +- drivers/pinctrl/cirrus/Kconfig | 3 ++- drivers/pinctrl/core.c | 6 +++--- drivers/pinctrl/nxp/pinctrl-s32cc.c | 4 ++-- drivers/pinctrl/pinctrl-cy8c95x0.c | 1 + drivers/pinctrl/realtek/pinctrl-rtd.c | 4 ++-- drivers/pinctrl/stm32/pinctrl-stm32.c | 13 ++++++++++--- 7 files changed, 21 insertions(+), 12 deletions(-)
Comments
On Wed, 29 Nov 2023 at 04:09, Linus Walleij <linus.walleij@linaro.org> wrote: > > The most interesting patch is the list iterator fix in the core by Maria > Yu, it took a while for me to realize what was going on there. That commit message still doesn't explain what the problem was. Why is p->state volatile there? It seems to be a serious locking bug if p->state can randomly change there, and the READ_ONCE() looks like a "this hides the problem" rather than an actual real fix. Linus
On Wed, Nov 29, 2023 at 3:56 PM Linus Torvalds <torvalds@linux-foundation.org> wrote: > On Wed, 29 Nov 2023 at 04:09, Linus Walleij <linus.walleij@linaro.org> wrote: > > > > The most interesting patch is the list iterator fix in the core by Maria > > Yu, it took a while for me to realize what was going on there. > > That commit message still doesn't explain what the problem was. > > Why is p->state volatile there? It seems to be a serious locking bug > if p->state can randomly change there, and the READ_ONCE() looks like > a "this hides the problem" rather than an actual real fix. Thanks for looking into it Linus, Maria can you look closer at this and try to pinpoint exactly what happens? Is the bug never manifesting with GCC for example? In the meantime I'll cook a fixes branch without this one commit. Yours, Linus Walleij
The pull request you sent on Wed, 29 Nov 2023 13:09:03 +0100:
> git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git tags/pinctrl-v6.7-2
has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/3b47bc037bd44f142ac09848e8d3ecccc726be99
Thank you!
On 11/29/2023 11:08 PM, Linus Walleij wrote: > On Wed, Nov 29, 2023 at 3:56 PM Linus Torvalds > <torvalds@linux-foundation.org> wrote: >> On Wed, 29 Nov 2023 at 04:09, Linus Walleij <linus.walleij@linaro.org> wrote: >>> >>> The most interesting patch is the list iterator fix in the core by Maria >>> Yu, it took a while for me to realize what was going on there. >> >> That commit message still doesn't explain what the problem was. >> >> Why is p->state volatile there? It seems to be a serious locking bug >> if p->state can randomly change there, and the READ_ONCE() looks like >> a "this hides the problem" rather than an actual real fix. This is indeed an interesting issue. Thx for the comment, Linus. **Let me explain how: "p->state becomes volatile in the list iterator", and "why READ_ONCE is suggested". The current critical code is: list_for_each_entry(setting, &p->state->settings, node) after elaborating the define list_for_each_entry, so above critical code will be: for (setting = list_head(&p->state->settings, typeof(*setting), node); \ &setting->node != (&p->state->settings); \ setting = list_next(setting , node)) The asm code(refer result from Clang version 10.0) can cleared explain the step of p->state reload actions: loop: ldr x22,[x22] ; x22=list_next(setting , node)) add x9,x8,#0x18 ; x9=&p->state->setting cmp x22,x9 ; setting,x9 b.eq 0xFFFFFF9B24483530 ldr w9,[x22,#0x10] ; w9,[setting,#16] cmp w9,#0x2 ; w9,#2 b.ne 0xFFFFFF9B24483504 mov x0,x22 ; x0,setting bl 0xFFFFFF9B24486048 ; pinmux_disable_setting ldr x8,[x19,#0x28] ; x19=p, x8=[p->state], *reload p->state* b loop The *reload p->state* inside the loop for checking is not needed and can cause possible infinite loop. So READ_ONCE is highly suggested even if p->state is not randomly changed. And then unnecessary "ldr x8,[x19,#0x28]" can be removed from above loop code. **Comments about the locking bug: currently pinctrl_select_state is an export symbol and don't have effective reentrance protect design. That's why current infinite loop issue was observed with customer's multi thread call with pinctrl_select_state without lock protection. pinctrl_select_state totally rely on driver module user side to ensure the reentrant state. Usually the suggested usage from driver side who are using pinctrl would be: LOCK; pinctrl_select_state(); gpio pulling; udelay(); check state; other hardware behaviors; UNLOCK; So the locking bug fix I have told customer side to fix from their own driver part. Since usually not only a simple pinctrl_select_state call can finish the hardware state transaction. I myself also is fine to have a small per pinctrl lock to only protect the current pinctrl_select_state->pinctrl_commit_state reentrance issues. Pls any pinctrl maintainer help to comment to suggest or not and I can prepare a change as well. > > Thanks for looking into it Linus, Maria can you look closer at this and > try to pinpoint exactly what happens? Sure, I am trying to explain from my end. If there is other thoughts pls feel free to chime in. > > Is the bug never manifesting with GCC for example? > > In the meantime I'll cook a fixes branch without this one commit. > > Yours, > Linus Walleij
Hi Nathan, Nick, (just picking some LLVM compiler people I know of... and trust) Context is this patch: https://lore.kernel.org/linux-gpio/20231115102824.23727-1-quic_aiquny@quicinc.com/ On Thu, Nov 30, 2023 at 6:37 AM Aiqun(Maria) Yu <quic_aiquny@quicinc.com> wrote: > On 11/29/2023 11:08 PM, Linus Walleij wrote: > > On Wed, Nov 29, 2023 at 3:56 PM Linus Torvalds > > <torvalds@linux-foundation.org> wrote: > >> On Wed, 29 Nov 2023 at 04:09, Linus Walleij <linus.walleij@linaro.org> wrote: > >>> > >>> The most interesting patch is the list iterator fix in the core by Maria > >>> Yu, it took a while for me to realize what was going on there. > >> > >> That commit message still doesn't explain what the problem was. > >> > >> Why is p->state volatile there? It seems to be a serious locking bug > >> if p->state can randomly change there, and the READ_ONCE() looks like > >> a "this hides the problem" rather than an actual real fix. > > This is indeed an interesting issue. Thx for the comment, Linus. > **Let me explain how: "p->state becomes volatile in the list iterator", > and "why READ_ONCE is suggested". > > The current critical code is: > list_for_each_entry(setting, &p->state->settings, node) > > after elaborating the define list_for_each_entry, so above critical code > will be: > for (setting = list_head(&p->state->settings, typeof(*setting), node); \ > &setting->node != (&p->state->settings); \ > setting = list_next(setting , node)) > > The asm code(refer result from Clang version 10.0) can cleared explain > the step of p->state reload actions: > loop: > ldr x22,[x22] ; x22=list_next(setting , node)) > add x9,x8,#0x18 ; x9=&p->state->setting > cmp x22,x9 ; setting,x9 > b.eq 0xFFFFFF9B24483530 > > ldr w9,[x22,#0x10] ; w9,[setting,#16] > cmp w9,#0x2 ; w9,#2 > b.ne 0xFFFFFF9B24483504 > > mov x0,x22 ; x0,setting > bl 0xFFFFFF9B24486048 ; pinmux_disable_setting > > ldr x8,[x19,#0x28] ; x19=p, x8=[p->state], *reload p->state* > b loop > > The *reload p->state* inside the loop for checking is not needed and can > cause possible infinite loop. So READ_ONCE is highly suggested even if > p->state is not randomly changed. And then unnecessary "ldr > x8,[x19,#0x28]" can be removed from above loop code. > > **Comments about the locking bug: > currently pinctrl_select_state is an export symbol and don't have > effective reentrance protect design. That's why current infinite loop > issue was observed with customer's multi thread call with > pinctrl_select_state without lock protection. pinctrl_select_state > totally rely on driver module user side to ensure the reentrant state. > > Usually the suggested usage from driver side who are using pinctrl would be: > LOCK; > pinctrl_select_state(); > gpio pulling; > udelay(); > check state; > other hardware behaviors; > UNLOCK; > > So the locking bug fix I have told customer side to fix from their own > driver part. Since usually not only a simple pinctrl_select_state call > can finish the hardware state transaction. > > I myself also is fine to have a small per pinctrl lock to only protect > the current pinctrl_select_state->pinctrl_commit_state reentrance > issues. Pls any pinctrl maintainer help to comment to suggest or not and > I can prepare a change as well. Luckily I am the pin control maintainer :D And I also ha my morning coffee and looked over the patch again. So tilting the compiler to generate code that is less prone to race conditions with READ_ONCE() isn't really the solution is it? We need to introduce a proper lock that stops this from happening if it is a problem people are facing. Can you try to make a patch that removes READ_ONCE() and introduce a lock instead? Racing is rarely an issue in pin control for reasons explained in another context here: https://lore.kernel.org/linux-gpio/CACRpkdZ0cnJpYuzU=47-oW-7N_YGMo2vXpKOeXeNi5PhPY7QMA@mail.gmail.com/ ...but if people still manage to run into it, we better have a lock there. Just make sure it is not just an issue with outoftree code, but a real problem? The change that changes the code to use the old_state variable should stay in, it makes the code more readable, it's just the READ_ONCE() macro which is dubious. Yours, Linus Walleij
On Fri, Dec 1, 2023 at 9:10 AM Linus Walleij <linus.walleij@linaro.org> wrote: > Hi Nathan, Nick, > > (just picking some LLVM compiler people I know of... and trust) Forget that part of the mail, written out-of-context when I was running different disassembly of GCC vs LLVM code. I figured it out and concluded that the compilers are fine and doing the right thing, it's a none-issue in that regard. Yours, Linus Walleij
On 12/1/2023 4:10 PM, Linus Walleij wrote: > Hi Nathan, Nick, > > (just picking some LLVM compiler people I know of... and trust) > > Context is this patch: > https://lore.kernel.org/linux-gpio/20231115102824.23727-1-quic_aiquny@quicinc.com/ > > On Thu, Nov 30, 2023 at 6:37 AM Aiqun(Maria) Yu <quic_aiquny@quicinc.com> wrote: >> On 11/29/2023 11:08 PM, Linus Walleij wrote: >>> On Wed, Nov 29, 2023 at 3:56 PM Linus Torvalds >>> <torvalds@linux-foundation.org> wrote: >>>> On Wed, 29 Nov 2023 at 04:09, Linus Walleij <linus.walleij@linaro.org> wrote: >>>>> >>>>> The most interesting patch is the list iterator fix in the core by Maria >>>>> Yu, it took a while for me to realize what was going on there. >>>> >>>> That commit message still doesn't explain what the problem was. >>>> >>>> Why is p->state volatile there? It seems to be a serious locking bug >>>> if p->state can randomly change there, and the READ_ONCE() looks like >>>> a "this hides the problem" rather than an actual real fix. >> >> This is indeed an interesting issue. Thx for the comment, Linus. >> **Let me explain how: "p->state becomes volatile in the list iterator", >> and "why READ_ONCE is suggested". >> >> The current critical code is: >> list_for_each_entry(setting, &p->state->settings, node) >> >> after elaborating the define list_for_each_entry, so above critical code >> will be: >> for (setting = list_head(&p->state->settings, typeof(*setting), node); \ >> &setting->node != (&p->state->settings); \ >> setting = list_next(setting , node)) >> >> The asm code(refer result from Clang version 10.0) can cleared explain >> the step of p->state reload actions: >> loop: >> ldr x22,[x22] ; x22=list_next(setting , node)) >> add x9,x8,#0x18 ; x9=&p->state->setting >> cmp x22,x9 ; setting,x9 >> b.eq 0xFFFFFF9B24483530 >> >> ldr w9,[x22,#0x10] ; w9,[setting,#16] >> cmp w9,#0x2 ; w9,#2 >> b.ne 0xFFFFFF9B24483504 >> >> mov x0,x22 ; x0,setting >> bl 0xFFFFFF9B24486048 ; pinmux_disable_setting >> >> ldr x8,[x19,#0x28] ; x19=p, x8=[p->state], *reload p->state* >> b loop >> >> The *reload p->state* inside the loop for checking is not needed and can >> cause possible infinite loop. So READ_ONCE is highly suggested even if >> p->state is not randomly changed. And then unnecessary "ldr >> x8,[x19,#0x28]" can be removed from above loop code. >> >> **Comments about the locking bug: >> currently pinctrl_select_state is an export symbol and don't have >> effective reentrance protect design. That's why current infinite loop >> issue was observed with customer's multi thread call with >> pinctrl_select_state without lock protection. pinctrl_select_state >> totally rely on driver module user side to ensure the reentrant state. >> >> Usually the suggested usage from driver side who are using pinctrl would be: >> LOCK; >> pinctrl_select_state(); >> gpio pulling; >> udelay(); >> check state; >> other hardware behaviors; >> UNLOCK; >> >> So the locking bug fix I have told customer side to fix from their own >> driver part. Since usually not only a simple pinctrl_select_state call >> can finish the hardware state transaction. >> >> I myself also is fine to have a small per pinctrl lock to only protect >> the current pinctrl_select_state->pinctrl_commit_state reentrance >> issues. Pls any pinctrl maintainer help to comment to suggest or not and >> I can prepare a change as well. > > Luckily I am the pin control maintainer :D > And I also ha my morning coffee and looked over the patch again. > > So tilting the compiler to generate code that is less prone to race > conditions with READ_ONCE() isn't really the solution is it? We need > to introduce a proper lock that stops this from happening if it is > a problem people are facing. > > Can you try to make a patch that removes READ_ONCE() > and introduce a lock instead? > > Racing is rarely an issue in pin control for reasons explained > in another context here: > https://lore.kernel.org/linux-gpio/CACRpkdZ0cnJpYuzU=47-oW-7N_YGMo2vXpKOeXeNi5PhPY7QMA@mail.gmail.com/ > > ...but if people still manage to run into it, we better have a lock > there. Just make sure it is not just an issue with outoftree code, > but a real problem? > > The change that changes the code to use the old_state variable > should stay in, it makes the code more readable, it's just the > READ_ONCE() macro which is dubious. Thx for confirm. I am preparing the new change now. :) READ_ONCE can only avoid the possible infinite loop and not crash the whole kernel, while the lock is needed to protect the multi parallel call of pinctrl_commit_state api have a consistent atomic hardware result as well. > > Yours, > Linus Walleij
On 12/1/2023 6:06 PM, Aiqun(Maria) Yu wrote: > On 12/1/2023 4:10 PM, Linus Walleij wrote: >> Hi Nathan, Nick, >> >> (just picking some LLVM compiler people I know of... and trust) >> >> Context is this patch: >> https://lore.kernel.org/linux-gpio/20231115102824.23727-1-quic_aiquny@quicinc.com/ >> >> On Thu, Nov 30, 2023 at 6:37 AM Aiqun(Maria) Yu >> <quic_aiquny@quicinc.com> wrote: >>> On 11/29/2023 11:08 PM, Linus Walleij wrote: >>>> On Wed, Nov 29, 2023 at 3:56 PM Linus Torvalds >>>> <torvalds@linux-foundation.org> wrote: >>>>> On Wed, 29 Nov 2023 at 04:09, Linus Walleij >>>>> <linus.walleij@linaro.org> wrote: >>>>>> >>>>>> The most interesting patch is the list iterator fix in the core by >>>>>> Maria >>>>>> Yu, it took a while for me to realize what was going on there. >>>>> >>>>> That commit message still doesn't explain what the problem was. >>>>> >>>>> Why is p->state volatile there? It seems to be a serious locking bug >>>>> if p->state can randomly change there, and the READ_ONCE() looks like >>>>> a "this hides the problem" rather than an actual real fix. >>> >>> This is indeed an interesting issue. Thx for the comment, Linus. >>> **Let me explain how: "p->state becomes volatile in the list iterator", >>> and "why READ_ONCE is suggested". >>> >>> The current critical code is: >>> list_for_each_entry(setting, &p->state->settings, node) >>> >>> after elaborating the define list_for_each_entry, so above critical code >>> will be: >>> for (setting = list_head(&p->state->settings, typeof(*setting), >>> node); \ >>> &setting->node != (&p->state->settings); \ >>> setting = list_next(setting , node)) >>> >>> The asm code(refer result from Clang version 10.0) can cleared explain >>> the step of p->state reload actions: >>> loop: >>> ldr x22,[x22] ; x22=list_next(setting , node)) >>> add x9,x8,#0x18 ; x9=&p->state->setting >>> cmp x22,x9 ; setting,x9 >>> b.eq 0xFFFFFF9B24483530 >>> >>> ldr w9,[x22,#0x10] ; w9,[setting,#16] >>> cmp w9,#0x2 ; w9,#2 >>> b.ne 0xFFFFFF9B24483504 >>> >>> mov x0,x22 ; x0,setting >>> bl 0xFFFFFF9B24486048 ; pinmux_disable_setting >>> >>> ldr x8,[x19,#0x28] ; x19=p, x8=[p->state], *reload p->state* >>> b loop >>> >>> The *reload p->state* inside the loop for checking is not needed and can >>> cause possible infinite loop. So READ_ONCE is highly suggested even if >>> p->state is not randomly changed. And then unnecessary "ldr >>> x8,[x19,#0x28]" can be removed from above loop code. >>> >>> **Comments about the locking bug: >>> currently pinctrl_select_state is an export symbol and don't have >>> effective reentrance protect design. That's why current infinite loop >>> issue was observed with customer's multi thread call with >>> pinctrl_select_state without lock protection. pinctrl_select_state >>> totally rely on driver module user side to ensure the reentrant state. >>> >>> Usually the suggested usage from driver side who are using pinctrl >>> would be: >>> LOCK; >>> pinctrl_select_state(); >>> gpio pulling; >>> udelay(); >>> check state; >>> other hardware behaviors; >>> UNLOCK; >>> >>> So the locking bug fix I have told customer side to fix from their own >>> driver part. Since usually not only a simple pinctrl_select_state call >>> can finish the hardware state transaction. >>> >>> I myself also is fine to have a small per pinctrl lock to only protect >>> the current pinctrl_select_state->pinctrl_commit_state reentrance >>> issues. Pls any pinctrl maintainer help to comment to suggest or not and >>> I can prepare a change as well. >> >> Luckily I am the pin control maintainer :D >> And I also ha my morning coffee and looked over the patch again. >> >> So tilting the compiler to generate code that is less prone to race >> conditions with READ_ONCE() isn't really the solution is it? We need >> to introduce a proper lock that stops this from happening if it is >> a problem people are facing. >> >> Can you try to make a patch that removes READ_ONCE() >> and introduce a lock instead? >> >> Racing is rarely an issue in pin control for reasons explained >> in another context here: >> https://lore.kernel.org/linux-gpio/CACRpkdZ0cnJpYuzU=47-oW-7N_YGMo2vXpKOeXeNi5PhPY7QMA@mail.gmail.com/ >> >> ...but if people still manage to run into it, we better have a lock >> there. Just make sure it is not just an issue with outoftree code, >> but a real problem? >> >> The change that changes the code to use the old_state variable >> should stay in, it makes the code more readable, it's just the >> READ_ONCE() macro which is dubious. > Thx for confirm. I am preparing the new change now. :) change uploaded link here: https://lore.kernel.org/linux-gpio/20231201152931.31161-1-quic_aiquny@quicinc.com/ > > READ_ONCE can only avoid the possible infinite loop and not crash the > whole kernel, while the lock is needed to protect the multi parallel > call of pinctrl_commit_state api have a consistent atomic hardware > result as well. >> >> Yours, >> Linus Walleij >