From: Greg Kroah-Hartman Date: Mon, 29 Jul 2024 12:19:29 +0000 (+0200) Subject: 5.15-stable patches X-Git-Tag: v6.1.103~59 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a01cb1711e90d2a7313ec13f59be51aa81fbdc40;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches added patches: binder-fix-hang-of-unregistered-readers.patch dev-parport-fix-the-array-out-of-bounds-risk.patch hwrng-amd-convert-pcibios_-return-codes-to-errnos.patch pci-dw-rockchip-fix-initial-perst-gpio-value.patch pci-hv-return-zero-not-garbage-when-reading-pci_interrupt_pin.patch pci-rockchip-use-gpiod_out_low-flag-while-requesting-ep_gpio.patch tools-memory-model-fix-bug-in-lock.cat.patch --- diff --git a/queue-5.15/binder-fix-hang-of-unregistered-readers.patch b/queue-5.15/binder-fix-hang-of-unregistered-readers.patch new file mode 100644 index 00000000000..8fe56dbbe6e --- /dev/null +++ b/queue-5.15/binder-fix-hang-of-unregistered-readers.patch @@ -0,0 +1,51 @@ +From 31643d84b8c3d9c846aa0e20bc033e46c68c7e7d Mon Sep 17 00:00:00 2001 +From: Carlos Llamas +Date: Thu, 11 Jul 2024 20:14:51 +0000 +Subject: binder: fix hang of unregistered readers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Carlos Llamas + +commit 31643d84b8c3d9c846aa0e20bc033e46c68c7e7d upstream. + +With the introduction of binder_available_for_proc_work_ilocked() in +commit 1b77e9dcc3da ("ANDROID: binder: remove proc waitqueue") a binder +thread can only "wait_for_proc_work" after its thread->looper has been +marked as BINDER_LOOPER_STATE_{ENTERED|REGISTERED}. + +This means an unregistered reader risks waiting indefinitely for work +since it never gets added to the proc->waiting_threads. If there are no +further references to its waitqueue either the task will hang. The same +applies to readers using the (e)poll interface. + +I couldn't find the rationale behind this restriction. So this patch +restores the previous behavior of allowing unregistered threads to +"wait_for_proc_work". Note that an error message for this scenario, +which had previously become unreachable, is now re-enabled. + +Fixes: 1b77e9dcc3da ("ANDROID: binder: remove proc waitqueue") +Cc: stable@vger.kernel.org +Cc: Martijn Coenen +Cc: Arve Hjønnevåg +Signed-off-by: Carlos Llamas +Link: https://lore.kernel.org/r/20240711201452.2017543-1-cmllamas@google.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/android/binder.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/android/binder.c ++++ b/drivers/android/binder.c +@@ -542,9 +542,7 @@ static bool binder_has_work(struct binde + static bool binder_available_for_proc_work_ilocked(struct binder_thread *thread) + { + return !thread->transaction_stack && +- binder_worklist_empty_ilocked(&thread->todo) && +- (thread->looper & (BINDER_LOOPER_STATE_ENTERED | +- BINDER_LOOPER_STATE_REGISTERED)); ++ binder_worklist_empty_ilocked(&thread->todo); + } + + static void binder_wakeup_poll_threads_ilocked(struct binder_proc *proc, diff --git a/queue-5.15/dev-parport-fix-the-array-out-of-bounds-risk.patch b/queue-5.15/dev-parport-fix-the-array-out-of-bounds-risk.patch new file mode 100644 index 00000000000..08e437f1ac2 --- /dev/null +++ b/queue-5.15/dev-parport-fix-the-array-out-of-bounds-risk.patch @@ -0,0 +1,125 @@ +From ab11dac93d2d568d151b1918d7b84c2d02bacbd5 Mon Sep 17 00:00:00 2001 +From: tuhaowen +Date: Mon, 8 Jul 2024 16:04:30 +0800 +Subject: dev/parport: fix the array out-of-bounds risk + +From: tuhaowen + +commit ab11dac93d2d568d151b1918d7b84c2d02bacbd5 upstream. + +Fixed array out-of-bounds issues caused by sprintf +by replacing it with snprintf for safer data copying, +ensuring the destination buffer is not overflowed. + +Below is the stack trace I encountered during the actual issue: + +[ 66.575408s] [pid:5118,cpu4,QThread,4]Kernel panic - not syncing: stack-protector: +Kernel stack is corrupted in: do_hardware_base_addr+0xcc/0xd0 [parport] +[ 66.575408s] [pid:5118,cpu4,QThread,5]CPU: 4 PID: 5118 Comm: +QThread Tainted: G S W O 5.10.97-arm64-desktop #7100.57021.2 +[ 66.575439s] [pid:5118,cpu4,QThread,6]TGID: 5087 Comm: EFileApp +[ 66.575439s] [pid:5118,cpu4,QThread,7]Hardware name: HUAWEI HUAWEI QingYun +PGUX-W515x-B081/SP1PANGUXM, BIOS 1.00.07 04/29/2024 +[ 66.575439s] [pid:5118,cpu4,QThread,8]Call trace: +[ 66.575469s] [pid:5118,cpu4,QThread,9] dump_backtrace+0x0/0x1c0 +[ 66.575469s] [pid:5118,cpu4,QThread,0] show_stack+0x14/0x20 +[ 66.575469s] [pid:5118,cpu4,QThread,1] dump_stack+0xd4/0x10c +[ 66.575500s] [pid:5118,cpu4,QThread,2] panic+0x1d8/0x3bc +[ 66.575500s] [pid:5118,cpu4,QThread,3] __stack_chk_fail+0x2c/0x38 +[ 66.575500s] [pid:5118,cpu4,QThread,4] do_hardware_base_addr+0xcc/0xd0 [parport] + +Signed-off-by: tuhaowen +Cc: stable +Link: https://lore.kernel.org/r/20240708080430.8221-1-tuhaowen@uniontech.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/parport/procfs.c | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +--- a/drivers/parport/procfs.c ++++ b/drivers/parport/procfs.c +@@ -51,12 +51,12 @@ static int do_active_device(struct ctl_t + + for (dev = port->devices; dev ; dev = dev->next) { + if(dev == port->cad) { +- len += sprintf(buffer, "%s\n", dev->name); ++ len += snprintf(buffer, sizeof(buffer), "%s\n", dev->name); + } + } + + if(!len) { +- len += sprintf(buffer, "%s\n", "none"); ++ len += snprintf(buffer, sizeof(buffer), "%s\n", "none"); + } + + if (len > *lenp) +@@ -87,19 +87,19 @@ static int do_autoprobe(struct ctl_table + } + + if ((str = info->class_name) != NULL) +- len += sprintf (buffer + len, "CLASS:%s;\n", str); ++ len += snprintf (buffer + len, sizeof(buffer) - len, "CLASS:%s;\n", str); + + if ((str = info->model) != NULL) +- len += sprintf (buffer + len, "MODEL:%s;\n", str); ++ len += snprintf (buffer + len, sizeof(buffer) - len, "MODEL:%s;\n", str); + + if ((str = info->mfr) != NULL) +- len += sprintf (buffer + len, "MANUFACTURER:%s;\n", str); ++ len += snprintf (buffer + len, sizeof(buffer) - len, "MANUFACTURER:%s;\n", str); + + if ((str = info->description) != NULL) +- len += sprintf (buffer + len, "DESCRIPTION:%s;\n", str); ++ len += snprintf (buffer + len, sizeof(buffer) - len, "DESCRIPTION:%s;\n", str); + + if ((str = info->cmdset) != NULL) +- len += sprintf (buffer + len, "COMMAND SET:%s;\n", str); ++ len += snprintf (buffer + len, sizeof(buffer) - len, "COMMAND SET:%s;\n", str); + + if (len > *lenp) + len = *lenp; +@@ -117,7 +117,7 @@ static int do_hardware_base_addr(struct + void *result, size_t *lenp, loff_t *ppos) + { + struct parport *port = (struct parport *)table->extra1; +- char buffer[20]; ++ char buffer[64]; + int len = 0; + + if (*ppos) { +@@ -128,7 +128,7 @@ static int do_hardware_base_addr(struct + if (write) /* permissions prevent this anyway */ + return -EACCES; + +- len += sprintf (buffer, "%lu\t%lu\n", port->base, port->base_hi); ++ len += snprintf (buffer, sizeof(buffer), "%lu\t%lu\n", port->base, port->base_hi); + + if (len > *lenp) + len = *lenp; +@@ -155,7 +155,7 @@ static int do_hardware_irq(struct ctl_ta + if (write) /* permissions prevent this anyway */ + return -EACCES; + +- len += sprintf (buffer, "%d\n", port->irq); ++ len += snprintf (buffer, sizeof(buffer), "%d\n", port->irq); + + if (len > *lenp) + len = *lenp; +@@ -182,7 +182,7 @@ static int do_hardware_dma(struct ctl_ta + if (write) /* permissions prevent this anyway */ + return -EACCES; + +- len += sprintf (buffer, "%d\n", port->dma); ++ len += snprintf (buffer, sizeof(buffer), "%d\n", port->dma); + + if (len > *lenp) + len = *lenp; +@@ -213,7 +213,7 @@ static int do_hardware_modes(struct ctl_ + #define printmode(x) \ + do { \ + if (port->modes & PARPORT_MODE_##x) \ +- len += sprintf(buffer + len, "%s%s", f++ ? "," : "", #x); \ ++ len += snprintf(buffer + len, sizeof(buffer) - len, "%s%s", f++ ? "," : "", #x); \ + } while (0) + int f = 0; + printmode(PCSPP); diff --git a/queue-5.15/hwrng-amd-convert-pcibios_-return-codes-to-errnos.patch b/queue-5.15/hwrng-amd-convert-pcibios_-return-codes-to-errnos.patch new file mode 100644 index 00000000000..08953a85bad --- /dev/null +++ b/queue-5.15/hwrng-amd-convert-pcibios_-return-codes-to-errnos.patch @@ -0,0 +1,42 @@ +From 14cba6ace79627a57fb9058582b03f0ed3832390 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= +Date: Mon, 27 May 2024 16:26:15 +0300 +Subject: hwrng: amd - Convert PCIBIOS_* return codes to errnos +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +commit 14cba6ace79627a57fb9058582b03f0ed3832390 upstream. + +amd_rng_mod_init() uses pci_read_config_dword() that returns PCIBIOS_* +codes. The return code is then returned as is but amd_rng_mod_init() is +a module_init() function that should return normal errnos. + +Convert PCIBIOS_* returns code using pcibios_err_to_errno() into normal +errno before returning it. + +Fixes: 96d63c0297cc ("[PATCH] Add AMD HW RNG driver") +Cc: stable@vger.kernel.org +Signed-off-by: Ilpo Järvinen +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/char/hw_random/amd-rng.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/char/hw_random/amd-rng.c ++++ b/drivers/char/hw_random/amd-rng.c +@@ -142,8 +142,10 @@ static int __init amd_rng_mod_init(void) + + found: + err = pci_read_config_dword(pdev, 0x58, &pmbase); +- if (err) ++ if (err) { ++ err = pcibios_err_to_errno(err); + goto put_dev; ++ } + + pmbase &= 0x0000FF00; + if (pmbase == 0) { diff --git a/queue-5.15/pci-dw-rockchip-fix-initial-perst-gpio-value.patch b/queue-5.15/pci-dw-rockchip-fix-initial-perst-gpio-value.patch new file mode 100644 index 00000000000..7b0e13278e9 --- /dev/null +++ b/queue-5.15/pci-dw-rockchip-fix-initial-perst-gpio-value.patch @@ -0,0 +1,81 @@ +From 28b8d7793b8573563b3d45321376f36168d77b1e Mon Sep 17 00:00:00 2001 +From: Niklas Cassel +Date: Wed, 17 Apr 2024 18:42:26 +0200 +Subject: PCI: dw-rockchip: Fix initial PERST# GPIO value +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Niklas Cassel + +commit 28b8d7793b8573563b3d45321376f36168d77b1e upstream. + +PERST# is active low according to the PCIe specification. + +However, the existing pcie-dw-rockchip.c driver does: + + gpiod_set_value(..., 0); msleep(100); gpiod_set_value(..., 1); + +when asserting + deasserting PERST#. + +This is of course wrong, but because all the device trees for this +compatible string have also incorrectly marked this GPIO as ACTIVE_HIGH: + + $ git grep -B 10 reset-gpios arch/arm64/boot/dts/rockchip/rk3568* + $ git grep -B 10 reset-gpios arch/arm64/boot/dts/rockchip/rk3588* + +The actual toggling of PERST# is correct, and we cannot change it anyway, +since that would break device tree compatibility. + +However, this driver does request the GPIO to be initialized as +GPIOD_OUT_HIGH, which does cause a silly sequence where PERST# gets +toggled back and forth for no good reason. + +Fix this by requesting the GPIO to be initialized as GPIOD_OUT_LOW (which +for this driver means PERST# asserted). + +This will avoid an unnecessary signal change where PERST# gets deasserted +(by devm_gpiod_get_optional()) and then gets asserted (by +rockchip_pcie_start_link()) just a few instructions later. + +Before patch, debug prints on EP side, when booting RC: + + [ 845.606810] pci: PERST# asserted by host! + [ 852.483985] pci: PERST# de-asserted by host! + [ 852.503041] pci: PERST# asserted by host! + [ 852.610318] pci: PERST# de-asserted by host! + +After patch, debug prints on EP side, when booting RC: + + [ 125.107921] pci: PERST# asserted by host! + [ 132.111429] pci: PERST# de-asserted by host! + +This extra, very short, PERST# assertion + deassertion has been reported to +cause issues with certain WLAN controllers, e.g. RTL8822CE. + +Fixes: 0e898eb8df4e ("PCI: rockchip-dwc: Add Rockchip RK356X host controller driver") +Link: https://lore.kernel.org/linux-pci/20240417164227.398901-1-cassel@kernel.org +Tested-by: Heiko Stuebner +Tested-by: Jianfeng Liu +Signed-off-by: Niklas Cassel +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Bjorn Helgaas +Reviewed-by: Heiko Stuebner +Reviewed-by: Manivannan Sadhasivam +Cc: stable@vger.kernel.org # v5.15+ +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/controller/dwc/pcie-dw-rockchip.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c ++++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c +@@ -148,7 +148,7 @@ static int rockchip_pcie_resource_get(st + return PTR_ERR(rockchip->apb_base); + + rockchip->rst_gpio = devm_gpiod_get_optional(&pdev->dev, "reset", +- GPIOD_OUT_HIGH); ++ GPIOD_OUT_LOW); + if (IS_ERR(rockchip->rst_gpio)) + return PTR_ERR(rockchip->rst_gpio); + diff --git a/queue-5.15/pci-hv-return-zero-not-garbage-when-reading-pci_interrupt_pin.patch b/queue-5.15/pci-hv-return-zero-not-garbage-when-reading-pci_interrupt_pin.patch new file mode 100644 index 00000000000..54e112b1508 --- /dev/null +++ b/queue-5.15/pci-hv-return-zero-not-garbage-when-reading-pci_interrupt_pin.patch @@ -0,0 +1,48 @@ +From fea93a3e5d5e6a09eb153866d2ce60ea3287a70d Mon Sep 17 00:00:00 2001 +From: Wei Liu +Date: Mon, 1 Jul 2024 20:26:05 +0000 +Subject: PCI: hv: Return zero, not garbage, when reading PCI_INTERRUPT_PIN +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Wei Liu + +commit fea93a3e5d5e6a09eb153866d2ce60ea3287a70d upstream. + +The intent of the code snippet is to always return 0 for both +PCI_INTERRUPT_LINE and PCI_INTERRUPT_PIN. + +The check misses PCI_INTERRUPT_PIN. This patch fixes that. + +This is discovered by this call in VFIO: + + pci_read_config_byte(vdev->pdev, PCI_INTERRUPT_PIN, &pin); + +The old code does not set *val to 0 because it misses the check for +PCI_INTERRUPT_PIN. Garbage is returned in that case. + +Fixes: 4daace0d8ce8 ("PCI: hv: Add paravirtual PCI front-end for Microsoft Hyper-V VMs") +Link: https://lore.kernel.org/linux-pci/20240701202606.129606-1-wei.liu@kernel.org +Signed-off-by: Wei Liu +Signed-off-by: Krzysztof Wilczyński +Reviewed-by: Michael Kelley +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/controller/pci-hyperv.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/pci/controller/pci-hyperv.c ++++ b/drivers/pci/controller/pci-hyperv.c +@@ -707,8 +707,8 @@ static void _hv_pcifront_read_config(str + PCI_CAPABILITY_LIST) { + /* ROM BARs are unimplemented */ + *val = 0; +- } else if (where >= PCI_INTERRUPT_LINE && where + size <= +- PCI_INTERRUPT_PIN) { ++ } else if ((where >= PCI_INTERRUPT_LINE && where + size <= PCI_INTERRUPT_PIN) || ++ (where >= PCI_INTERRUPT_PIN && where + size <= PCI_MIN_GNT)) { + /* + * Interrupt Line and Interrupt PIN are hard-wired to zero + * because this front-end only supports message-signaled diff --git a/queue-5.15/pci-rockchip-use-gpiod_out_low-flag-while-requesting-ep_gpio.patch b/queue-5.15/pci-rockchip-use-gpiod_out_low-flag-while-requesting-ep_gpio.patch new file mode 100644 index 00000000000..015523b367c --- /dev/null +++ b/queue-5.15/pci-rockchip-use-gpiod_out_low-flag-while-requesting-ep_gpio.patch @@ -0,0 +1,83 @@ +From 840b7a5edf88fe678c60dee88a135647c0ea4375 Mon Sep 17 00:00:00 2001 +From: Manivannan Sadhasivam +Date: Tue, 16 Apr 2024 11:12:35 +0530 +Subject: PCI: rockchip: Use GPIOD_OUT_LOW flag while requesting ep_gpio +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Manivannan Sadhasivam + +commit 840b7a5edf88fe678c60dee88a135647c0ea4375 upstream. + +Rockchip platforms use 'GPIO_ACTIVE_HIGH' flag in the devicetree definition +for ep_gpio. This means, whatever the logical value set by the driver for +the ep_gpio, physical line will output the same logic level. + +For instance, + + gpiod_set_value_cansleep(rockchip->ep_gpio, 0); --> Level low + gpiod_set_value_cansleep(rockchip->ep_gpio, 1); --> Level high + +But while requesting the ep_gpio, GPIOD_OUT_HIGH flag is currently used. +Now, this also causes the physical line to output 'high' creating trouble +for endpoint devices during host reboot. + +When host reboot happens, the ep_gpio will initially output 'low' due to +the GPIO getting reset to its POR value. Then during host controller probe, +it will output 'high' due to GPIOD_OUT_HIGH flag. Then during +rockchip_pcie_host_init_port(), it will first output 'low' and then 'high' +indicating the completion of controller initialization. + +On the endpoint side, each output 'low' of ep_gpio is accounted for PERST# +assert and 'high' for PERST# deassert. With the above mentioned flow during +host reboot, endpoint will witness below state changes for PERST#: + + (1) PERST# assert - GPIO POR state + (2) PERST# deassert - GPIOD_OUT_HIGH while requesting GPIO + (3) PERST# assert - rockchip_pcie_host_init_port() + (4) PERST# deassert - rockchip_pcie_host_init_port() + +Now the time interval between (2) and (3) is very short as both happen +during the driver probe(), and this results in a race in the endpoint. +Because, before completing the PERST# deassertion in (2), endpoint got +another PERST# assert in (3). + +A proper way to fix this issue is to change the GPIOD_OUT_HIGH flag in (2) +to GPIOD_OUT_LOW. Because the usual convention is to request the GPIO with +a state corresponding to its 'initial/default' value and let the driver +change the state of the GPIO when required. + +As per that, the ep_gpio should be requested with GPIOD_OUT_LOW as it +corresponds to the POR value of '0' (PERST# assert in the endpoint). Then +the driver can change the state of the ep_gpio later in +rockchip_pcie_host_init_port() as per the initialization sequence. + +This fixes the firmware crash issue in Qcom based modems connected to +Rockpro64 based board. + +Fixes: e77f847df54c ("PCI: rockchip: Add Rockchip PCIe controller support") +Closes: https://lore.kernel.org/mhi/20240402045647.GG2933@thinkpad/ +Link: https://lore.kernel.org/linux-pci/20240416-pci-rockchip-perst-fix-v1-1-4800b1d4d954@linaro.org +Reported-by: Slark Xiao +Signed-off-by: Manivannan Sadhasivam +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Bjorn Helgaas +Reviewed-by: Niklas Cassel +Cc: stable@vger.kernel.org # v4.9 +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/controller/pcie-rockchip.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/pci/controller/pcie-rockchip.c ++++ b/drivers/pci/controller/pcie-rockchip.c +@@ -120,7 +120,7 @@ int rockchip_pcie_parse_dt(struct rockch + + if (rockchip->is_rc) { + rockchip->ep_gpio = devm_gpiod_get_optional(dev, "ep", +- GPIOD_OUT_HIGH); ++ GPIOD_OUT_LOW); + if (IS_ERR(rockchip->ep_gpio)) + return dev_err_probe(dev, PTR_ERR(rockchip->ep_gpio), + "failed to get ep GPIO\n"); diff --git a/queue-5.15/series b/queue-5.15/series index c33c854f095..fd3a1b022bf 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -200,3 +200,10 @@ kvm-vmx-split-out-the-non-virtualization-part-of-vmx_interrupt_blocked.patch alsa-usb-audio-fix-microphone-sound-on-hd-webcam.patch alsa-usb-audio-move-hd-webcam-quirk-to-the-right-place.patch alsa-usb-audio-add-a-quirk-for-sonix-hd-usb-camera.patch +tools-memory-model-fix-bug-in-lock.cat.patch +hwrng-amd-convert-pcibios_-return-codes-to-errnos.patch +pci-hv-return-zero-not-garbage-when-reading-pci_interrupt_pin.patch +pci-dw-rockchip-fix-initial-perst-gpio-value.patch +pci-rockchip-use-gpiod_out_low-flag-while-requesting-ep_gpio.patch +binder-fix-hang-of-unregistered-readers.patch +dev-parport-fix-the-array-out-of-bounds-risk.patch diff --git a/queue-5.15/tools-memory-model-fix-bug-in-lock.cat.patch b/queue-5.15/tools-memory-model-fix-bug-in-lock.cat.patch new file mode 100644 index 00000000000..e66fde3ce8d --- /dev/null +++ b/queue-5.15/tools-memory-model-fix-bug-in-lock.cat.patch @@ -0,0 +1,98 @@ +From 4c830eef806679dc243e191f962c488dd9d00708 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Thu, 6 Jun 2024 09:57:55 -0400 +Subject: tools/memory-model: Fix bug in lock.cat + +From: Alan Stern + +commit 4c830eef806679dc243e191f962c488dd9d00708 upstream. + +Andrea reported that the following innocuous litmus test: + +C T + +{} + +P0(spinlock_t *x) +{ + int r0; + + spin_lock(x); + spin_unlock(x); + r0 = spin_is_locked(x); +} + +gives rise to a nonsensical empty result with no executions: + +$ herd7 -conf linux-kernel.cfg T.litmus +Test T Required +States 0 +Ok +Witnesses +Positive: 0 Negative: 0 +Condition forall (true) +Observation T Never 0 0 +Time T 0.00 +Hash=6fa204e139ddddf2cb6fa963bad117c0 + +The problem is caused by a bug in the lock.cat part of the LKMM. Its +computation of the rf relation for RU (read-unlocked) events is +faulty; it implicitly assumes that every RU event must read from +either a UL (unlock) event in another thread or from the lock's +initial state. Neither is true in the litmus test above, so the +computation yields no possible executions. + +The lock.cat code tries to make up for this deficiency by allowing RU +events outside of critical sections to read from the last po-previous +UL event. But it does this incorrectly, trying to keep these rfi links +separate from the rfe links that might also be needed, and passing only +the latter to herd7's cross() macro. + +The problem is fixed by merging the two sets of possible rf links for +RU events and using them all in the call to cross(). + +Signed-off-by: Alan Stern +Reported-by: Andrea Parri +Closes: https://lore.kernel.org/linux-arch/ZlC0IkzpQdeGj+a3@andrea/ +Tested-by: Andrea Parri +Acked-by: Andrea Parri +Fixes: 15553dcbca06 ("tools/memory-model: Add model support for spin_is_locked()") +CC: +Signed-off-by: Paul E. McKenney +Signed-off-by: Greg Kroah-Hartman +--- + tools/memory-model/lock.cat | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +--- a/tools/memory-model/lock.cat ++++ b/tools/memory-model/lock.cat +@@ -102,19 +102,19 @@ let rf-lf = rfe-lf | rfi-lf + * within one of the lock's critical sections returns False. + *) + +-(* rfi for RU events: an RU may read from the last po-previous UL *) +-let rfi-ru = ([UL] ; po-loc ; [RU]) \ ([UL] ; po-loc ; [LKW] ; po-loc) +- +-(* rfe for RU events: an RU may read from an external UL or the initial write *) +-let all-possible-rfe-ru = +- let possible-rfe-ru r = ++(* ++ * rf for RU events: an RU may read from an external UL or the initial write, ++ * or from the last po-previous UL ++ *) ++let all-possible-rf-ru = ++ let possible-rf-ru r = + let pair-to-relation p = p ++ 0 +- in map pair-to-relation (((UL | IW) * {r}) & loc & ext) +- in map possible-rfe-ru RU ++ in map pair-to-relation ((((UL | IW) * {r}) & loc & ext) | ++ (((UL * {r}) & po-loc) \ ([UL] ; po-loc ; [LKW] ; po-loc))) ++ in map possible-rf-ru RU + + (* Generate all rf relations for RU events *) +-with rfe-ru from cross(all-possible-rfe-ru) +-let rf-ru = rfe-ru | rfi-ru ++with rf-ru from cross(all-possible-rf-ru) + + (* Final rf relation *) + let rf = rf | rf-lf | rf-ru