2022-07-05 13:26:30

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 00/58] 5.4.204-rc1 review

This is the start of the stable review cycle for the 5.4.204 release.
There are 58 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.

Responses should be made by Thu, 07 Jul 2022 11:55:56 +0000.
Anything received after that time might be too late.

The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.4.204-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.4.y
and the diffstat can be found below.

thanks,

greg k-h

-------------
Pseudo-Shortlog of commits:

Greg Kroah-Hartman <[email protected]>
Linux 5.4.204-rc1

Greg Kroah-Hartman <[email protected]>
clocksource/drivers/ixp4xx: remove EXPORT_SYMBOL_GPL from ixp4xx_timer_setup()

Daniele Palmas <[email protected]>
net: usb: qmi_wwan: add Telit 0x1070 composition

Carlo Lobrano <[email protected]>
net: usb: qmi_wwan: add Telit 0x1060 composition

Oleksandr Tyshchenko <[email protected]>
xen/arm: Fix race in RB-tree based P2M accounting

Roger Pau Monne <[email protected]>
xen/blkfront: force data bouncing when backend is untrusted

Roger Pau Monne <[email protected]>
xen/netfront: force data bouncing when backend is untrusted

Roger Pau Monne <[email protected]>
xen/netfront: fix leaking data in shared pages

Roger Pau Monne <[email protected]>
xen/blkfront: fix leaking data in shared pages

Mathieu Desnoyers <[email protected]>
selftests/rseq: Change type of rseq_offset to ptrdiff_t

Mathieu Desnoyers <[email protected]>
selftests/rseq: x86-32: use %gs segment selector for accessing rseq thread area

Mathieu Desnoyers <[email protected]>
selftests/rseq: x86-64: use %fs segment selector for accessing rseq thread area

Mathieu Desnoyers <[email protected]>
selftests/rseq: Fix: work-around asm goto compiler bugs

Mathieu Desnoyers <[email protected]>
selftests/rseq: Remove arm/mips asm goto compiler work-around

Mathieu Desnoyers <[email protected]>
selftests/rseq: Fix warnings about #if checks of undefined tokens

Mathieu Desnoyers <[email protected]>
selftests/rseq: Fix ppc32 offsets by using long rather than off_t

Mathieu Desnoyers <[email protected]>
selftests/rseq: Fix ppc32 missing instruction selection "u" and "x" for load/store

Mathieu Desnoyers <[email protected]>
selftests/rseq: Fix ppc32: wrong rseq_cs 32-bit field pointer on big endian

Mathieu Desnoyers <[email protected]>
selftests/rseq: Uplift rseq selftests for compatibility with glibc-2.35

Mathieu Desnoyers <[email protected]>
selftests/rseq: Introduce thread pointer getters

Mathieu Desnoyers <[email protected]>
selftests/rseq: Introduce rseq_get_abi() helper

Mathieu Desnoyers <[email protected]>
selftests/rseq: Remove volatile from __rseq_abi

Mathieu Desnoyers <[email protected]>
selftests/rseq: Remove useless assignment to cpu variable

Mathieu Desnoyers <[email protected]>
selftests/rseq: introduce own copy of rseq uapi header

Shuah Khan <[email protected]>
selftests/rseq: remove ARRAY_SIZE define from individual tests

Peter Oskolkov <[email protected]>
rseq/selftests,x86_64: Add rseq_offset_deref_addv()

katrinzhou <[email protected]>
ipv6/sit: fix ipip6_tunnel_get_prl return value

kernel test robot <[email protected]>
sit: use min

Doug Berger <[email protected]>
net: dsa: bcm_sf2: force pause link settings

Yang Yingliang <[email protected]>
hwmon: (ibmaem) don't call platform_device_del() if platform_device_add() fails

Demi Marie Obenour <[email protected]>
xen/gntdev: Avoid blocking in unmap_grant_pages()

Jakub Kicinski <[email protected]>
net: tun: avoid disabling NAPI twice

Michael Walle <[email protected]>
NFC: nxp-nci: Don't issue a zero length i2c_master_read()

Krzysztof Kozlowski <[email protected]>
nfc: nfcmrvl: Fix irq_of_parse_and_map() return value

Yevhen Orlov <[email protected]>
net: bonding: fix use-after-free after 802.3ad slave unbind

Eric Dumazet <[email protected]>
net: bonding: fix possible NULL deref in rlb code

Victor Nogueira <[email protected]>
net/sched: act_api: Notify user space if any actions were flushed before error

Pablo Neira Ayuso <[email protected]>
netfilter: nft_dynset: restore set element counter when failing to update

Masahiro Yamada <[email protected]>
s390: remove unneeded 'select BUILD_BIN2C'

Miaoqian Lin <[email protected]>
PM / devfreq: exynos-ppmu: Fix refcount leak in of_get_devfreq_events

Jason Wang <[email protected]>
caif_virtio: fix race between virtio_device_ready() and ndo_open()

YueHaibing <[email protected]>
net: ipv6: unexport __init-annotated seg6_hmac_net_init()

Oliver Neukum <[email protected]>
usbnet: fix memory allocation in helpers

Tao Liu <[email protected]>
linux/dim: Fix divide by 0 in RDMA DIM

Kamal Heib <[email protected]>
RDMA/qedr: Fix reporting QP timeout attribute

Jakub Kicinski <[email protected]>
net: tun: stop NAPI when detaching queues

Jakub Kicinski <[email protected]>
net: tun: unlink NAPI from device on destruction

Dimitris Michailidis <[email protected]>
selftests/net: pass ipv6_args to udpgso_bench's IPv6 TCP test

Jason Wang <[email protected]>
virtio-net: fix race between ndo_open() and virtio_device_ready()

Jose Alonso <[email protected]>
net: usb: ax88179_178a: Fix packet receiving

Duoming Zhou <[email protected]>
net: rose: fix UAF bugs caused by timer handler

Chuck Lever <[email protected]>
SUNRPC: Fix READ_PLUS crasher

Jason A. Donenfeld <[email protected]>
s390/archrandom: simplify back to earlier design and initialize earlier

Mikulas Patocka <[email protected]>
dm raid: fix KASAN warning in raid5_add_disks

Heinz Mauelshagen <[email protected]>
dm raid: fix accesses beyond end of raid member array

Naveen N. Rao <[email protected]>
powerpc/bpf: Fix use of user_pt_regs in uapi

Liam Howlett <[email protected]>
powerpc/prom_init: Fix kernel config grep

Chris Ye <[email protected]>
nvdimm: Fix badblocks clear off-by-one error

Nicolas Dichtel <[email protected]>
ipv6: take care of disable_policy when restoring routes


-------------

Diffstat:

Makefile | 4 +-
arch/arm/xen/p2m.c | 6 +-
arch/powerpc/include/asm/bpf_perf_event.h | 9 +
arch/powerpc/include/uapi/asm/bpf_perf_event.h | 9 -
arch/powerpc/kernel/prom_init_check.sh | 2 +-
arch/s390/Kconfig | 1 -
arch/s390/crypto/arch_random.c | 111 +--------
arch/s390/include/asm/archrandom.h | 21 +-
arch/s390/kernel/setup.c | 5 +
drivers/block/xen-blkfront.c | 56 +++--
drivers/clocksource/timer-ixp4xx.c | 1 -
drivers/devfreq/event/exynos-ppmu.c | 8 +-
drivers/hwmon/ibmaem.c | 12 +-
drivers/infiniband/hw/qedr/qedr.h | 1 +
drivers/infiniband/hw/qedr/verbs.c | 4 +-
drivers/md/dm-raid.c | 34 +--
drivers/md/raid5.c | 1 +
drivers/net/bonding/bond_3ad.c | 3 +-
drivers/net/bonding/bond_alb.c | 2 +-
drivers/net/caif/caif_virtio.c | 10 +-
drivers/net/dsa/bcm_sf2.c | 5 +
drivers/net/tun.c | 15 +-
drivers/net/usb/ax88179_178a.c | 101 ++++++---
drivers/net/usb/qmi_wwan.c | 2 +
drivers/net/usb/usbnet.c | 4 +-
drivers/net/virtio_net.c | 8 +-
drivers/net/xen-netfront.c | 52 ++++-
drivers/nfc/nfcmrvl/i2c.c | 6 +-
drivers/nfc/nfcmrvl/spi.c | 6 +-
drivers/nfc/nxp-nci/i2c.c | 3 +
drivers/nvdimm/bus.c | 4 +-
drivers/xen/gntdev-common.h | 8 +
drivers/xen/gntdev.c | 147 ++++++++----
include/linux/dim.h | 2 +-
net/ipv6/addrconf.c | 4 -
net/ipv6/route.c | 9 +-
net/ipv6/seg6_hmac.c | 1 -
net/ipv6/sit.c | 10 +-
net/netfilter/nft_set_hash.c | 2 +
net/rose/rose_timer.c | 34 +--
net/sched/act_api.c | 22 +-
net/sunrpc/xdr.c | 2 +-
tools/testing/selftests/net/udpgso_bench.sh | 2 +-
tools/testing/selftests/rseq/Makefile | 2 +-
.../testing/selftests/rseq/basic_percpu_ops_test.c | 5 +-
tools/testing/selftests/rseq/compiler.h | 30 +++
tools/testing/selftests/rseq/param_test.c | 8 +-
tools/testing/selftests/rseq/rseq-abi.h | 151 +++++++++++++
tools/testing/selftests/rseq/rseq-arm.h | 110 ++++-----
tools/testing/selftests/rseq/rseq-arm64.h | 79 +++++--
.../selftests/rseq/rseq-generic-thread-pointer.h | 25 +++
tools/testing/selftests/rseq/rseq-mips.h | 71 ++----
.../selftests/rseq/rseq-ppc-thread-pointer.h | 30 +++
tools/testing/selftests/rseq/rseq-ppc.h | 128 +++++++----
tools/testing/selftests/rseq/rseq-s390.h | 55 +++--
tools/testing/selftests/rseq/rseq-skip.h | 2 +-
tools/testing/selftests/rseq/rseq-thread-pointer.h | 19 ++
.../selftests/rseq/rseq-x86-thread-pointer.h | 40 ++++
tools/testing/selftests/rseq/rseq-x86.h | 247 ++++++++++++++++-----
tools/testing/selftests/rseq/rseq.c | 165 +++++++-------
tools/testing/selftests/rseq/rseq.h | 30 ++-
61 files changed, 1290 insertions(+), 656 deletions(-)



2022-07-05 13:26:38

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 57/58] net: usb: qmi_wwan: add Telit 0x1070 composition

From: Daniele Palmas <[email protected]>

commit 94f2a444f28a649926c410eb9a38afb13a83ebe0 upstream.

Add the following Telit FN990 composition:

0x1070: tty, adb, rmnet, tty, tty, tty, tty

Signed-off-by: Daniele Palmas <[email protected]>
Acked-by: Bjørn Mork <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Jakub Kicinski <[email protected]>
Cc: Fabio Porcedda <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/usb/qmi_wwan.c | 1 +
1 file changed, 1 insertion(+)

--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -1316,6 +1316,7 @@ static const struct usb_device_id produc
{QMI_QUIRK_SET_DTR(0x1bc7, 0x1040, 2)}, /* Telit LE922A */
{QMI_QUIRK_SET_DTR(0x1bc7, 0x1050, 2)}, /* Telit FN980 */
{QMI_QUIRK_SET_DTR(0x1bc7, 0x1060, 2)}, /* Telit LN920 */
+ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1070, 2)}, /* Telit FN990 */
{QMI_FIXED_INTF(0x1bc7, 0x1100, 3)}, /* Telit ME910 */
{QMI_FIXED_INTF(0x1bc7, 0x1101, 3)}, /* Telit ME910 dual modem */
{QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */


2022-07-05 13:27:07

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 34/58] rseq/selftests,x86_64: Add rseq_offset_deref_addv()

From: Peter Oskolkov <[email protected]>

commit ea366dd79c05fcd4cf5e225d2de8a3a7c293160c upstream.

This patch adds rseq_offset_deref_addv() function to
tools/testing/selftests/rseq/rseq-x86.h, to be used in a selftest in
the next patch in the patchset.

Once an architecture adds support for this function they should define
"RSEQ_ARCH_HAS_OFFSET_DEREF_ADDV".

Signed-off-by: Peter Oskolkov <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Acked-by: Mathieu Desnoyers <[email protected]>
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
tools/testing/selftests/rseq/rseq-x86.h | 57 ++++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)

--- a/tools/testing/selftests/rseq/rseq-x86.h
+++ b/tools/testing/selftests/rseq/rseq-x86.h
@@ -279,6 +279,63 @@ error1:
#endif
}

+#define RSEQ_ARCH_HAS_OFFSET_DEREF_ADDV
+
+/*
+ * pval = *(ptr+off)
+ * *pval += inc;
+ */
+static inline __attribute__((always_inline))
+int rseq_offset_deref_addv(intptr_t *ptr, off_t off, intptr_t inc, int cpu)
+{
+ RSEQ_INJECT_C(9)
+
+ __asm__ __volatile__ goto (
+ RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+#ifdef RSEQ_COMPARE_TWICE
+ RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+#endif
+ /* Start rseq by storing table entry pointer into rseq_cs. */
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_INJECT_ASM(3)
+#ifdef RSEQ_COMPARE_TWICE
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+#endif
+ /* get p+v */
+ "movq %[ptr], %%rbx\n\t"
+ "addq %[off], %%rbx\n\t"
+ /* get pv */
+ "movq (%%rbx), %%rcx\n\t"
+ /* *pv += inc */
+ "addq %[inc], (%%rcx)\n\t"
+ "2:\n\t"
+ RSEQ_INJECT_ASM(4)
+ RSEQ_ASM_DEFINE_ABORT(4, "", abort)
+ : /* gcc asm goto does not allow outputs */
+ : [cpu_id] "r" (cpu),
+ [rseq_abi] "r" (&__rseq_abi),
+ /* final store input */
+ [ptr] "m" (*ptr),
+ [off] "er" (off),
+ [inc] "er" (inc)
+ : "memory", "cc", "rax", "rbx", "rcx"
+ RSEQ_INJECT_CLOBBER
+ : abort
+#ifdef RSEQ_COMPARE_TWICE
+ , error1
+#endif
+ );
+ return 0;
+abort:
+ RSEQ_INJECT_FAILED
+ return -1;
+#ifdef RSEQ_COMPARE_TWICE
+error1:
+ rseq_bug("cpu_id comparison failed");
+#endif
+}
+
static inline __attribute__((always_inline))
int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
intptr_t *v2, intptr_t newv2,


2022-07-05 13:27:20

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 40/58] selftests/rseq: Introduce thread pointer getters

From: Mathieu Desnoyers <[email protected]>

commit 886ddfba933f5ce9d76c278165d834d114ba4ffc upstream.

This is done in preparation for the selftest uplift to become compatible
with glibc-2.35.

glibc-2.35 exposes the rseq per-thread data in the TCB, accessible
at an offset from the thread pointer.

The toolchains do not implement accessing the thread pointer on all
architectures. Provide thread pointer getters for ppc and x86 which
lack (or lacked until recently) toolchain support.

Signed-off-by: Mathieu Desnoyers <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
tools/testing/selftests/rseq/rseq-generic-thread-pointer.h | 25 ++++++++
tools/testing/selftests/rseq/rseq-ppc-thread-pointer.h | 30 +++++++++
tools/testing/selftests/rseq/rseq-thread-pointer.h | 19 ++++++
tools/testing/selftests/rseq/rseq-x86-thread-pointer.h | 40 +++++++++++++
4 files changed, 114 insertions(+)
create mode 100644 tools/testing/selftests/rseq/rseq-generic-thread-pointer.h
create mode 100644 tools/testing/selftests/rseq/rseq-ppc-thread-pointer.h
create mode 100644 tools/testing/selftests/rseq/rseq-thread-pointer.h
create mode 100644 tools/testing/selftests/rseq/rseq-x86-thread-pointer.h

--- /dev/null
+++ b/tools/testing/selftests/rseq/rseq-generic-thread-pointer.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: LGPL-2.1-only OR MIT */
+/*
+ * rseq-generic-thread-pointer.h
+ *
+ * (C) Copyright 2021 - Mathieu Desnoyers <[email protected]>
+ */
+
+#ifndef _RSEQ_GENERIC_THREAD_POINTER
+#define _RSEQ_GENERIC_THREAD_POINTER
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Use gcc builtin thread pointer. */
+static inline void *rseq_thread_pointer(void)
+{
+ return __builtin_thread_pointer();
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+++ b/tools/testing/selftests/rseq/rseq-ppc-thread-pointer.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: LGPL-2.1-only OR MIT */
+/*
+ * rseq-ppc-thread-pointer.h
+ *
+ * (C) Copyright 2021 - Mathieu Desnoyers <[email protected]>
+ */
+
+#ifndef _RSEQ_PPC_THREAD_POINTER
+#define _RSEQ_PPC_THREAD_POINTER
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline void *rseq_thread_pointer(void)
+{
+#ifdef __powerpc64__
+ register void *__result asm ("r13");
+#else
+ register void *__result asm ("r2");
+#endif
+ asm ("" : "=r" (__result));
+ return __result;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+++ b/tools/testing/selftests/rseq/rseq-thread-pointer.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: LGPL-2.1-only OR MIT */
+/*
+ * rseq-thread-pointer.h
+ *
+ * (C) Copyright 2021 - Mathieu Desnoyers <[email protected]>
+ */
+
+#ifndef _RSEQ_THREAD_POINTER
+#define _RSEQ_THREAD_POINTER
+
+#if defined(__x86_64__) || defined(__i386__)
+#include "rseq-x86-thread-pointer.h"
+#elif defined(__PPC__)
+#include "rseq-ppc-thread-pointer.h"
+#else
+#include "rseq-generic-thread-pointer.h"
+#endif
+
+#endif
--- /dev/null
+++ b/tools/testing/selftests/rseq/rseq-x86-thread-pointer.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: LGPL-2.1-only OR MIT */
+/*
+ * rseq-x86-thread-pointer.h
+ *
+ * (C) Copyright 2021 - Mathieu Desnoyers <[email protected]>
+ */
+
+#ifndef _RSEQ_X86_THREAD_POINTER
+#define _RSEQ_X86_THREAD_POINTER
+
+#include <features.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if __GNUC_PREREQ (11, 1)
+static inline void *rseq_thread_pointer(void)
+{
+ return __builtin_thread_pointer();
+}
+#else
+static inline void *rseq_thread_pointer(void)
+{
+ void *__result;
+
+# ifdef __x86_64__
+ __asm__ ("mov %%fs:0, %0" : "=r" (__result));
+# else
+ __asm__ ("mov %%gs:0, %0" : "=r" (__result));
+# endif
+ return __result;
+}
+#endif /* !GCC 11 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif


2022-07-05 13:27:31

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 03/58] powerpc/prom_init: Fix kernel config grep

From: Liam Howlett <[email protected]>

commit 6886da5f49e6d86aad76807a93f3eef5e4f01b10 upstream.

When searching for config options, use the KCONFIG_CONFIG shell variable
so that builds using non-standard config locations work.

Fixes: 26deb04342e3 ("powerpc: prepare string/mem functions for KASAN")
Cc: [email protected] # v5.2+
Signed-off-by: Liam R. Howlett <[email protected]>
Signed-off-by: Michael Ellerman <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/powerpc/kernel/prom_init_check.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

--- a/arch/powerpc/kernel/prom_init_check.sh
+++ b/arch/powerpc/kernel/prom_init_check.sh
@@ -13,7 +13,7 @@
# If you really need to reference something from prom_init.o add
# it to the list below:

-grep "^CONFIG_KASAN=y$" .config >/dev/null
+grep "^CONFIG_KASAN=y$" ${KCONFIG_CONFIG} >/dev/null
if [ $? -eq 0 ]
then
MEM_FUNCS="__memcpy __memset"


2022-07-05 13:27:34

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 36/58] selftests/rseq: introduce own copy of rseq uapi header

From: Mathieu Desnoyers <[email protected]>

commit 5c105d55a9dc9e01535116ccfc26e703168a574f upstream.

The Linux kernel rseq uapi header has a broken layout for the
rseq_cs.ptr field on 32-bit little endian architectures. The entire
rseq_cs.ptr field is planned for removal, leaving only the 64-bit
rseq_cs.ptr64 field available.

Both glibc and librseq use their own copy of the Linux kernel uapi
header, where they introduce proper union fields to access to the 32-bit
low order bits of the rseq_cs pointer on 32-bit architectures.

Introduce a copy of the Linux kernel uapi headers in the Linux kernel
selftests.

Signed-off-by: Mathieu Desnoyers <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
tools/testing/selftests/rseq/rseq-abi.h | 151 ++++++++++++++++++++++++++++++++
tools/testing/selftests/rseq/rseq.c | 14 +-
tools/testing/selftests/rseq/rseq.h | 10 --
3 files changed, 161 insertions(+), 14 deletions(-)
create mode 100644 tools/testing/selftests/rseq/rseq-abi.h

--- /dev/null
+++ b/tools/testing/selftests/rseq/rseq-abi.h
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+#ifndef _RSEQ_ABI_H
+#define _RSEQ_ABI_H
+
+/*
+ * rseq-abi.h
+ *
+ * Restartable sequences system call API
+ *
+ * Copyright (c) 2015-2022 Mathieu Desnoyers <[email protected]>
+ */
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+enum rseq_abi_cpu_id_state {
+ RSEQ_ABI_CPU_ID_UNINITIALIZED = -1,
+ RSEQ_ABI_CPU_ID_REGISTRATION_FAILED = -2,
+};
+
+enum rseq_abi_flags {
+ RSEQ_ABI_FLAG_UNREGISTER = (1 << 0),
+};
+
+enum rseq_abi_cs_flags_bit {
+ RSEQ_ABI_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT = 0,
+ RSEQ_ABI_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT = 1,
+ RSEQ_ABI_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT = 2,
+};
+
+enum rseq_abi_cs_flags {
+ RSEQ_ABI_CS_FLAG_NO_RESTART_ON_PREEMPT =
+ (1U << RSEQ_ABI_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT),
+ RSEQ_ABI_CS_FLAG_NO_RESTART_ON_SIGNAL =
+ (1U << RSEQ_ABI_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT),
+ RSEQ_ABI_CS_FLAG_NO_RESTART_ON_MIGRATE =
+ (1U << RSEQ_ABI_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT),
+};
+
+/*
+ * struct rseq_abi_cs is aligned on 4 * 8 bytes to ensure it is always
+ * contained within a single cache-line. It is usually declared as
+ * link-time constant data.
+ */
+struct rseq_abi_cs {
+ /* Version of this structure. */
+ __u32 version;
+ /* enum rseq_abi_cs_flags */
+ __u32 flags;
+ __u64 start_ip;
+ /* Offset from start_ip. */
+ __u64 post_commit_offset;
+ __u64 abort_ip;
+} __attribute__((aligned(4 * sizeof(__u64))));
+
+/*
+ * struct rseq_abi is aligned on 4 * 8 bytes to ensure it is always
+ * contained within a single cache-line.
+ *
+ * A single struct rseq_abi per thread is allowed.
+ */
+struct rseq_abi {
+ /*
+ * Restartable sequences cpu_id_start field. Updated by the
+ * kernel. Read by user-space with single-copy atomicity
+ * semantics. This field should only be read by the thread which
+ * registered this data structure. Aligned on 32-bit. Always
+ * contains a value in the range of possible CPUs, although the
+ * value may not be the actual current CPU (e.g. if rseq is not
+ * initialized). This CPU number value should always be compared
+ * against the value of the cpu_id field before performing a rseq
+ * commit or returning a value read from a data structure indexed
+ * using the cpu_id_start value.
+ */
+ __u32 cpu_id_start;
+ /*
+ * Restartable sequences cpu_id field. Updated by the kernel.
+ * Read by user-space with single-copy atomicity semantics. This
+ * field should only be read by the thread which registered this
+ * data structure. Aligned on 32-bit. Values
+ * RSEQ_CPU_ID_UNINITIALIZED and RSEQ_CPU_ID_REGISTRATION_FAILED
+ * have a special semantic: the former means "rseq uninitialized",
+ * and latter means "rseq initialization failed". This value is
+ * meant to be read within rseq critical sections and compared
+ * with the cpu_id_start value previously read, before performing
+ * the commit instruction, or read and compared with the
+ * cpu_id_start value before returning a value loaded from a data
+ * structure indexed using the cpu_id_start value.
+ */
+ __u32 cpu_id;
+ /*
+ * Restartable sequences rseq_cs field.
+ *
+ * Contains NULL when no critical section is active for the current
+ * thread, or holds a pointer to the currently active struct rseq_cs.
+ *
+ * Updated by user-space, which sets the address of the currently
+ * active rseq_cs at the beginning of assembly instruction sequence
+ * block, and set to NULL by the kernel when it restarts an assembly
+ * instruction sequence block, as well as when the kernel detects that
+ * it is preempting or delivering a signal outside of the range
+ * targeted by the rseq_cs. Also needs to be set to NULL by user-space
+ * before reclaiming memory that contains the targeted struct rseq_cs.
+ *
+ * Read and set by the kernel. Set by user-space with single-copy
+ * atomicity semantics. This field should only be updated by the
+ * thread which registered this data structure. Aligned on 64-bit.
+ */
+ union {
+ __u64 ptr64;
+
+ /*
+ * The "arch" field provides architecture accessor for
+ * the ptr field based on architecture pointer size and
+ * endianness.
+ */
+ struct {
+#ifdef __LP64__
+ __u64 ptr;
+#elif defined(__BYTE_ORDER) ? (__BYTE_ORDER == __BIG_ENDIAN) : defined(__BIG_ENDIAN)
+ __u32 padding; /* Initialized to zero. */
+ __u32 ptr;
+#else
+ __u32 ptr;
+ __u32 padding; /* Initialized to zero. */
+#endif
+ } arch;
+ } rseq_cs;
+
+ /*
+ * Restartable sequences flags field.
+ *
+ * This field should only be updated by the thread which
+ * registered this data structure. Read by the kernel.
+ * Mainly used for single-stepping through rseq critical sections
+ * with debuggers.
+ *
+ * - RSEQ_ABI_CS_FLAG_NO_RESTART_ON_PREEMPT
+ * Inhibit instruction sequence block restart on preemption
+ * for this thread.
+ * - RSEQ_ABI_CS_FLAG_NO_RESTART_ON_SIGNAL
+ * Inhibit instruction sequence block restart on signal
+ * delivery for this thread.
+ * - RSEQ_ABI_CS_FLAG_NO_RESTART_ON_MIGRATE
+ * Inhibit instruction sequence block restart on migration for
+ * this thread.
+ */
+ __u32 flags;
+} __attribute__((aligned(4 * sizeof(__u64))));
+
+#endif /* _RSEQ_ABI_H */
--- a/tools/testing/selftests/rseq/rseq.c
+++ b/tools/testing/selftests/rseq/rseq.c
@@ -30,8 +30,8 @@
#include "../kselftest.h"
#include "rseq.h"

-__thread volatile struct rseq __rseq_abi = {
- .cpu_id = RSEQ_CPU_ID_UNINITIALIZED,
+__thread volatile struct rseq_abi __rseq_abi = {
+ .cpu_id = RSEQ_ABI_CPU_ID_UNINITIALIZED,
};

/*
@@ -66,7 +66,7 @@ static void signal_restore(sigset_t olds
abort();
}

-static int sys_rseq(volatile struct rseq *rseq_abi, uint32_t rseq_len,
+static int sys_rseq(volatile struct rseq_abi *rseq_abi, uint32_t rseq_len,
int flags, uint32_t sig)
{
return syscall(__NR_rseq, rseq_abi, rseq_len, flags, sig);
@@ -86,13 +86,13 @@ int rseq_register_current_thread(void)
}
if (__rseq_refcount++)
goto end;
- rc = sys_rseq(&__rseq_abi, sizeof(struct rseq), 0, RSEQ_SIG);
+ rc = sys_rseq(&__rseq_abi, sizeof(struct rseq_abi), 0, RSEQ_SIG);
if (!rc) {
assert(rseq_current_cpu_raw() >= 0);
goto end;
}
if (errno != EBUSY)
- __rseq_abi.cpu_id = RSEQ_CPU_ID_REGISTRATION_FAILED;
+ __rseq_abi.cpu_id = RSEQ_ABI_CPU_ID_REGISTRATION_FAILED;
ret = -1;
__rseq_refcount--;
end:
@@ -114,8 +114,8 @@ int rseq_unregister_current_thread(void)
}
if (--__rseq_refcount)
goto end;
- rc = sys_rseq(&__rseq_abi, sizeof(struct rseq),
- RSEQ_FLAG_UNREGISTER, RSEQ_SIG);
+ rc = sys_rseq(&__rseq_abi, sizeof(struct rseq_abi),
+ RSEQ_ABI_FLAG_UNREGISTER, RSEQ_SIG);
if (!rc)
goto end;
__rseq_refcount = 1;
--- a/tools/testing/selftests/rseq/rseq.h
+++ b/tools/testing/selftests/rseq/rseq.h
@@ -16,7 +16,7 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
-#include <linux/rseq.h>
+#include "rseq-abi.h"

/*
* Empty code injection macros, override when testing.
@@ -43,7 +43,7 @@
#define RSEQ_INJECT_FAILED
#endif

-extern __thread volatile struct rseq __rseq_abi;
+extern __thread volatile struct rseq_abi __rseq_abi;
extern int __rseq_handled;

#define rseq_likely(x) __builtin_expect(!!(x), 1)
@@ -139,11 +139,7 @@ static inline uint32_t rseq_current_cpu(

static inline void rseq_clear_rseq_cs(void)
{
-#ifdef __LP64__
- __rseq_abi.rseq_cs.ptr = 0;
-#else
- __rseq_abi.rseq_cs.ptr.ptr32 = 0;
-#endif
+ __rseq_abi.rseq_cs.arch.ptr = 0;
}

/*


2022-07-05 13:27:38

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 45/58] selftests/rseq: Fix warnings about #if checks of undefined tokens

From: Mathieu Desnoyers <[email protected]>

commit d7ed99ade3e62b755584eea07b4e499e79240527 upstream.

Signed-off-by: Mathieu Desnoyers <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
tools/testing/selftests/rseq/param_test.c | 2 +-
tools/testing/selftests/rseq/rseq-x86.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

--- a/tools/testing/selftests/rseq/param_test.c
+++ b/tools/testing/selftests/rseq/param_test.c
@@ -159,7 +159,7 @@ unsigned int yield_mod_cnt, nr_abort;
" cbnz " INJECT_ASM_REG ", 222b\n" \
"333:\n"

-#elif __PPC__
+#elif defined(__PPC__)

#define RSEQ_INJECT_INPUT \
, [loop_cnt_1]"m"(loop_cnt[1]) \
--- a/tools/testing/selftests/rseq/rseq-x86.h
+++ b/tools/testing/selftests/rseq/rseq-x86.h
@@ -600,7 +600,7 @@ int rseq_cmpeqv_trymemcpy_storev_release

#endif /* !RSEQ_SKIP_FASTPATH */

-#elif __i386__
+#elif defined(__i386__)

#define rseq_smp_mb() \
__asm__ __volatile__ ("lock; addl $0,-128(%%esp)" ::: "memory", "cc")


2022-07-05 13:28:57

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 14/58] net: tun: stop NAPI when detaching queues

From: Jakub Kicinski <[email protected]>

commit a8fc8cb5692aebb9c6f7afd4265366d25dcd1d01 upstream.

While looking at a syzbot report I noticed the NAPI only gets
disabled before it's deleted. I think that user can detach
the queue before destroying the device and the NAPI will never
be stopped.

Fixes: 943170998b20 ("tun: enable NAPI for TUN/TAP driver")
Acked-by: Petar Penkov <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Jakub Kicinski <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/tun.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)

--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -327,6 +327,12 @@ static void tun_napi_init(struct tun_str
}
}

+static void tun_napi_enable(struct tun_file *tfile)
+{
+ if (tfile->napi_enabled)
+ napi_enable(&tfile->napi);
+}
+
static void tun_napi_disable(struct tun_file *tfile)
{
if (tfile->napi_enabled)
@@ -709,8 +715,10 @@ static void __tun_detach(struct tun_file
if (clean) {
RCU_INIT_POINTER(tfile->tun, NULL);
sock_put(&tfile->sk);
- } else
+ } else {
tun_disable_queue(tun, tfile);
+ tun_napi_disable(tfile);
+ }

synchronize_net();
tun_flow_delete_by_queue(tun, tun->numqueues + 1);
@@ -864,6 +872,7 @@ static int tun_attach(struct tun_struct

if (tfile->detached) {
tun_enable_queue(tfile);
+ tun_napi_enable(tfile);
} else {
sock_hold(&tfile->sk);
tun_napi_init(tun, tfile, napi, napi_frags);


2022-07-05 13:29:14

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 26/58] nfc: nfcmrvl: Fix irq_of_parse_and_map() return value

From: Krzysztof Kozlowski <[email protected]>

commit 5a478a653b4cca148d5c89832f007ec0809d7e6d upstream.

The irq_of_parse_and_map() returns 0 on failure, not a negative ERRNO.

Reported-by: Lv Ruyi <[email protected]>
Fixes: caf6e49bf6d0 ("NFC: nfcmrvl: add spi driver")
Signed-off-by: Krzysztof Kozlowski <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Jakub Kicinski <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/nfc/nfcmrvl/i2c.c | 6 +++---
drivers/nfc/nfcmrvl/spi.c | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)

--- a/drivers/nfc/nfcmrvl/i2c.c
+++ b/drivers/nfc/nfcmrvl/i2c.c
@@ -186,9 +186,9 @@ static int nfcmrvl_i2c_parse_dt(struct d
pdata->irq_polarity = IRQF_TRIGGER_RISING;

ret = irq_of_parse_and_map(node, 0);
- if (ret < 0) {
- pr_err("Unable to get irq, error: %d\n", ret);
- return ret;
+ if (!ret) {
+ pr_err("Unable to get irq\n");
+ return -EINVAL;
}
pdata->irq = ret;

--- a/drivers/nfc/nfcmrvl/spi.c
+++ b/drivers/nfc/nfcmrvl/spi.c
@@ -129,9 +129,9 @@ static int nfcmrvl_spi_parse_dt(struct d
}

ret = irq_of_parse_and_map(node, 0);
- if (ret < 0) {
- pr_err("Unable to get irq, error: %d\n", ret);
- return ret;
+ if (!ret) {
+ pr_err("Unable to get irq\n");
+ return -EINVAL;
}
pdata->irq = ret;



2022-07-05 13:30:05

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 48/58] selftests/rseq: x86-64: use %fs segment selector for accessing rseq thread area

From: Mathieu Desnoyers <[email protected]>

commit 4e15bb766b6c6e963a4d33629034d0ec3b7637df upstream.

Rather than use rseq_get_abi() and pass its result through a register to
the inline assembler, directly access the per-thread rseq area through a
memory reference combining the %fs segment selector, the constant offset
of the field in struct rseq, and the rseq_offset value (in a register).

Signed-off-by: Mathieu Desnoyers <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
tools/testing/selftests/rseq/rseq-x86.h | 58 ++++++++++++++++----------------
1 file changed, 30 insertions(+), 28 deletions(-)

--- a/tools/testing/selftests/rseq/rseq-x86.h
+++ b/tools/testing/selftests/rseq/rseq-x86.h
@@ -28,6 +28,8 @@

#ifdef __x86_64__

+#define RSEQ_ASM_TP_SEGMENT %%fs
+
#define rseq_smp_mb() \
__asm__ __volatile__ ("lock; addl $0,-128(%%rsp)" ::: "memory", "cc")
#define rseq_smp_rmb() rseq_barrier()
@@ -123,14 +125,14 @@ int rseq_cmpeqv_storev(intptr_t *v, intp
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"cmpq %[v], %[expect]\n\t"
"jnz %l[cmpfail]\n\t"
RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
"cmpq %[v], %[expect]\n\t"
"jnz %l[error2]\n\t"
#endif
@@ -141,7 +143,7 @@ int rseq_cmpeqv_storev(intptr_t *v, intp
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (rseq_get_abi()),
+ [rseq_offset] "r" ((long)rseq_offset),
[v] "m" (*v),
[expect] "r" (expect),
[newv] "r" (newv)
@@ -189,15 +191,15 @@ int rseq_cmpnev_storeoffp_load(intptr_t
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"movq %[v], %%rbx\n\t"
"cmpq %%rbx, %[expectnot]\n\t"
"je %l[cmpfail]\n\t"
RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
"movq %[v], %%rbx\n\t"
"cmpq %%rbx, %[expectnot]\n\t"
"je %l[error2]\n\t"
@@ -212,7 +214,7 @@ int rseq_cmpnev_storeoffp_load(intptr_t
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (rseq_get_abi()),
+ [rseq_offset] "r" ((long)rseq_offset),
/* final store input */
[v] "m" (*v),
[expectnot] "r" (expectnot),
@@ -255,11 +257,11 @@ int rseq_addv(intptr_t *v, intptr_t coun
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
#endif
/* final store */
"addq %[count], %[v]\n\t"
@@ -268,7 +270,7 @@ int rseq_addv(intptr_t *v, intptr_t coun
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (rseq_get_abi()),
+ [rseq_offset] "r" ((long)rseq_offset),
/* final store input */
[v] "m" (*v),
[count] "er" (count)
@@ -309,11 +311,11 @@ int rseq_offset_deref_addv(intptr_t *ptr
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
#endif
/* get p+v */
"movq %[ptr], %%rbx\n\t"
@@ -327,7 +329,7 @@ int rseq_offset_deref_addv(intptr_t *ptr
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (rseq_get_abi()),
+ [rseq_offset] "r" ((long)rseq_offset),
/* final store input */
[ptr] "m" (*ptr),
[off] "er" (off),
@@ -364,14 +366,14 @@ int rseq_cmpeqv_trystorev_storev(intptr_
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"cmpq %[v], %[expect]\n\t"
"jnz %l[cmpfail]\n\t"
RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
"cmpq %[v], %[expect]\n\t"
"jnz %l[error2]\n\t"
#endif
@@ -385,7 +387,7 @@ int rseq_cmpeqv_trystorev_storev(intptr_
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (rseq_get_abi()),
+ [rseq_offset] "r" ((long)rseq_offset),
/* try store input */
[v2] "m" (*v2),
[newv2] "r" (newv2),
@@ -444,8 +446,8 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"cmpq %[v], %[expect]\n\t"
"jnz %l[cmpfail]\n\t"
@@ -454,7 +456,7 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *
"jnz %l[cmpfail]\n\t"
RSEQ_INJECT_ASM(5)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
"cmpq %[v], %[expect]\n\t"
"jnz %l[error2]\n\t"
"cmpq %[v2], %[expect2]\n\t"
@@ -467,7 +469,7 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (rseq_get_abi()),
+ [rseq_offset] "r" ((long)rseq_offset),
/* cmp2 input */
[v2] "m" (*v2),
[expect2] "r" (expect2),
@@ -524,14 +526,14 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_
"movq %[dst], %[rseq_scratch1]\n\t"
"movq %[len], %[rseq_scratch2]\n\t"
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"cmpq %[v], %[expect]\n\t"
"jnz 5f\n\t"
RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 6f)
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 6f)
"cmpq %[v], %[expect]\n\t"
"jnz 7f\n\t"
#endif
@@ -579,7 +581,7 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_
#endif
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (rseq_get_abi()),
+ [rseq_offset] "r" ((long)rseq_offset),
/* final store input */
[v] "m" (*v),
[expect] "r" (expect),


2022-07-05 13:30:37

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 30/58] hwmon: (ibmaem) dont call platform_device_del() if platform_device_add() fails

From: Yang Yingliang <[email protected]>

[ Upstream commit d0e51022a025ca5350fafb8e413a6fe5d4baf833 ]

If platform_device_add() fails, it no need to call platform_device_del(), split
platform_device_unregister() into platform_device_del/put(), so platform_device_put()
can be called separately.

Fixes: 8808a793f052 ("ibmaem: new driver for power/energy/temp meters in IBM System X hardware")
Reported-by: Hulk Robot <[email protected]>
Signed-off-by: Yang Yingliang <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Guenter Roeck <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
---
drivers/hwmon/ibmaem.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)

--- a/drivers/hwmon/ibmaem.c
+++ b/drivers/hwmon/ibmaem.c
@@ -550,7 +550,7 @@ static int aem_init_aem1_inst(struct aem

res = platform_device_add(data->pdev);
if (res)
- goto ipmi_err;
+ goto dev_add_err;

platform_set_drvdata(data->pdev, data);

@@ -598,7 +598,9 @@ hwmon_reg_err:
ipmi_destroy_user(data->ipmi.user);
ipmi_err:
platform_set_drvdata(data->pdev, NULL);
- platform_device_unregister(data->pdev);
+ platform_device_del(data->pdev);
+dev_add_err:
+ platform_device_put(data->pdev);
dev_err:
ida_simple_remove(&aem_ida, data->id);
id_err:
@@ -690,7 +692,7 @@ static int aem_init_aem2_inst(struct aem

res = platform_device_add(data->pdev);
if (res)
- goto ipmi_err;
+ goto dev_add_err;

platform_set_drvdata(data->pdev, data);

@@ -738,7 +740,9 @@ hwmon_reg_err:
ipmi_destroy_user(data->ipmi.user);
ipmi_err:
platform_set_drvdata(data->pdev, NULL);
- platform_device_unregister(data->pdev);
+ platform_device_del(data->pdev);
+dev_add_err:
+ platform_device_put(data->pdev);
dev_err:
ida_simple_remove(&aem_ida, data->id);
id_err:


2022-07-05 13:30:38

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 46/58] selftests/rseq: Remove arm/mips asm goto compiler work-around

From: Mathieu Desnoyers <[email protected]>

commit 94c5cf2a0e193afffef8de48ddc42de6df7cac93 upstream.

The arm and mips work-around for asm goto size guess issues are not
properly documented, and lack reference to specific compiler versions,
upstream compiler bug tracker entry, and reproducer.

I can only find a loosely documented patch in my original LKML rseq post
refering to gcc < 7 on ARM, but it does not appear to be sufficient to
track the exact issue. Also, I am not sure MIPS really has the same
limitation.

Therefore, remove the work-around until we can properly document this.

Signed-off-by: Mathieu Desnoyers <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Link: https://lore.kernel.org/lkml/[email protected]/
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
tools/testing/selftests/rseq/rseq-arm.h | 37 -------------------------------
tools/testing/selftests/rseq/rseq-mips.h | 37 -------------------------------
2 files changed, 74 deletions(-)

--- a/tools/testing/selftests/rseq/rseq-arm.h
+++ b/tools/testing/selftests/rseq/rseq-arm.h
@@ -147,14 +147,11 @@ do { \
teardown \
"b %l[" __rseq_str(cmpfail_label) "]\n\t"

-#define rseq_workaround_gcc_asm_size_guess() __asm__ __volatile__("")
-
static inline __attribute__((always_inline))
int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
{
RSEQ_INJECT_C(9)

- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -198,14 +195,11 @@ int rseq_cmpeqv_storev(intptr_t *v, intp
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
@@ -221,7 +215,6 @@ int rseq_cmpnev_storeoffp_load(intptr_t
{
RSEQ_INJECT_C(9)

- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -270,14 +263,11 @@ int rseq_cmpnev_storeoffp_load(intptr_t
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
@@ -292,7 +282,6 @@ int rseq_addv(intptr_t *v, intptr_t coun
{
RSEQ_INJECT_C(9)

- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
#ifdef RSEQ_COMPARE_TWICE
@@ -328,10 +317,8 @@ int rseq_addv(intptr_t *v, intptr_t coun
, error1
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
#ifdef RSEQ_COMPARE_TWICE
@@ -347,7 +334,6 @@ int rseq_cmpeqv_trystorev_storev(intptr_
{
RSEQ_INJECT_C(9)

- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -398,14 +384,11 @@ int rseq_cmpeqv_trystorev_storev(intptr_
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
@@ -422,7 +405,6 @@ int rseq_cmpeqv_trystorev_storev_release
{
RSEQ_INJECT_C(9)

- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -474,14 +456,11 @@ int rseq_cmpeqv_trystorev_storev_release
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
@@ -498,7 +477,6 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *
{
RSEQ_INJECT_C(9)

- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -554,14 +532,11 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *
, error1, error2, error3
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
@@ -582,7 +557,6 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_

RSEQ_INJECT_C(9)

- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -678,21 +652,16 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
- rseq_workaround_gcc_asm_size_guess();
rseq_bug("cpu_id comparison failed");
error2:
- rseq_workaround_gcc_asm_size_guess();
rseq_bug("expected value comparison failed");
#endif
}
@@ -706,7 +675,6 @@ int rseq_cmpeqv_trymemcpy_storev_release

RSEQ_INJECT_C(9)

- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -803,21 +771,16 @@ int rseq_cmpeqv_trymemcpy_storev_release
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
- rseq_workaround_gcc_asm_size_guess();
rseq_bug("cpu_id comparison failed");
error2:
- rseq_workaround_gcc_asm_size_guess();
rseq_bug("expected value comparison failed");
#endif
}
--- a/tools/testing/selftests/rseq/rseq-mips.h
+++ b/tools/testing/selftests/rseq/rseq-mips.h
@@ -154,14 +154,11 @@ do { \
teardown \
"b %l[" __rseq_str(cmpfail_label) "]\n\t"

-#define rseq_workaround_gcc_asm_size_guess() __asm__ __volatile__("")
-
static inline __attribute__((always_inline))
int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
{
RSEQ_INJECT_C(9)

- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -203,14 +200,11 @@ int rseq_cmpeqv_storev(intptr_t *v, intp
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
@@ -226,7 +220,6 @@ int rseq_cmpnev_storeoffp_load(intptr_t
{
RSEQ_INJECT_C(9)

- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -273,14 +266,11 @@ int rseq_cmpnev_storeoffp_load(intptr_t
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
@@ -295,7 +285,6 @@ int rseq_addv(intptr_t *v, intptr_t coun
{
RSEQ_INJECT_C(9)

- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
#ifdef RSEQ_COMPARE_TWICE
@@ -331,10 +320,8 @@ int rseq_addv(intptr_t *v, intptr_t coun
, error1
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
#ifdef RSEQ_COMPARE_TWICE
@@ -350,7 +337,6 @@ int rseq_cmpeqv_trystorev_storev(intptr_
{
RSEQ_INJECT_C(9)

- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -399,14 +385,11 @@ int rseq_cmpeqv_trystorev_storev(intptr_
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
@@ -423,7 +406,6 @@ int rseq_cmpeqv_trystorev_storev_release
{
RSEQ_INJECT_C(9)

- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -473,14 +455,11 @@ int rseq_cmpeqv_trystorev_storev_release
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
@@ -497,7 +476,6 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *
{
RSEQ_INJECT_C(9)

- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -549,14 +527,11 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *
, error1, error2, error3
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
@@ -577,7 +552,6 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_

RSEQ_INJECT_C(9)

- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -670,21 +644,16 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
- rseq_workaround_gcc_asm_size_guess();
rseq_bug("cpu_id comparison failed");
error2:
- rseq_workaround_gcc_asm_size_guess();
rseq_bug("expected value comparison failed");
#endif
}
@@ -698,7 +667,6 @@ int rseq_cmpeqv_trymemcpy_storev_release

RSEQ_INJECT_C(9)

- rseq_workaround_gcc_asm_size_guess();
__asm__ __volatile__ goto (
RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
@@ -792,21 +760,16 @@ int rseq_cmpeqv_trymemcpy_storev_release
, error1, error2
#endif
);
- rseq_workaround_gcc_asm_size_guess();
return 0;
abort:
- rseq_workaround_gcc_asm_size_guess();
RSEQ_INJECT_FAILED
return -1;
cmpfail:
- rseq_workaround_gcc_asm_size_guess();
return 1;
#ifdef RSEQ_COMPARE_TWICE
error1:
- rseq_workaround_gcc_asm_size_guess();
rseq_bug("cpu_id comparison failed");
error2:
- rseq_workaround_gcc_asm_size_guess();
rseq_bug("expected value comparison failed");
#endif
}


2022-07-05 13:30:49

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 49/58] selftests/rseq: x86-32: use %gs segment selector for accessing rseq thread area

From: Mathieu Desnoyers <[email protected]>

commit 127b6429d235ab7c358223bbfd8a8b8d8cc799b6 upstream.

Rather than use rseq_get_abi() and pass its result through a register to
the inline assembler, directly access the per-thread rseq area through a
memory reference combining the %gs segment selector, the constant offset
of the field in struct rseq, and the rseq_offset value (in a register).

Signed-off-by: Mathieu Desnoyers <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
tools/testing/selftests/rseq/rseq-x86.h | 66 ++++++++++++++++----------------
1 file changed, 34 insertions(+), 32 deletions(-)

--- a/tools/testing/selftests/rseq/rseq-x86.h
+++ b/tools/testing/selftests/rseq/rseq-x86.h
@@ -633,6 +633,8 @@ int rseq_cmpeqv_trymemcpy_storev_release

#elif defined(__i386__)

+#define RSEQ_ASM_TP_SEGMENT %%gs
+
#define rseq_smp_mb() \
__asm__ __volatile__ ("lock; addl $0,-128(%%esp)" ::: "memory", "cc")
#define rseq_smp_rmb() \
@@ -732,14 +734,14 @@ int rseq_cmpeqv_storev(intptr_t *v, intp
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"cmpl %[v], %[expect]\n\t"
"jnz %l[cmpfail]\n\t"
RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
"cmpl %[v], %[expect]\n\t"
"jnz %l[error2]\n\t"
#endif
@@ -750,7 +752,7 @@ int rseq_cmpeqv_storev(intptr_t *v, intp
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (rseq_get_abi()),
+ [rseq_offset] "r" (rseq_offset),
[v] "m" (*v),
[expect] "r" (expect),
[newv] "r" (newv)
@@ -798,15 +800,15 @@ int rseq_cmpnev_storeoffp_load(intptr_t
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"movl %[v], %%ebx\n\t"
"cmpl %%ebx, %[expectnot]\n\t"
"je %l[cmpfail]\n\t"
RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
"movl %[v], %%ebx\n\t"
"cmpl %%ebx, %[expectnot]\n\t"
"je %l[error2]\n\t"
@@ -821,7 +823,7 @@ int rseq_cmpnev_storeoffp_load(intptr_t
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (rseq_get_abi()),
+ [rseq_offset] "r" (rseq_offset),
/* final store input */
[v] "m" (*v),
[expectnot] "r" (expectnot),
@@ -864,11 +866,11 @@ int rseq_addv(intptr_t *v, intptr_t coun
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
#endif
/* final store */
"addl %[count], %[v]\n\t"
@@ -877,7 +879,7 @@ int rseq_addv(intptr_t *v, intptr_t coun
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (rseq_get_abi()),
+ [rseq_offset] "r" (rseq_offset),
/* final store input */
[v] "m" (*v),
[count] "ir" (count)
@@ -916,14 +918,14 @@ int rseq_cmpeqv_trystorev_storev(intptr_
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"cmpl %[v], %[expect]\n\t"
"jnz %l[cmpfail]\n\t"
RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
"cmpl %[v], %[expect]\n\t"
"jnz %l[error2]\n\t"
#endif
@@ -938,7 +940,7 @@ int rseq_cmpeqv_trystorev_storev(intptr_
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (rseq_get_abi()),
+ [rseq_offset] "r" (rseq_offset),
/* try store input */
[v2] "m" (*v2),
[newv2] "m" (newv2),
@@ -987,15 +989,15 @@ int rseq_cmpeqv_trystorev_storev_release
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"movl %[expect], %%eax\n\t"
"cmpl %[v], %%eax\n\t"
"jnz %l[cmpfail]\n\t"
RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
"movl %[expect], %%eax\n\t"
"cmpl %[v], %%eax\n\t"
"jnz %l[error2]\n\t"
@@ -1011,7 +1013,7 @@ int rseq_cmpeqv_trystorev_storev_release
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (rseq_get_abi()),
+ [rseq_offset] "r" (rseq_offset),
/* try store input */
[v2] "m" (*v2),
[newv2] "r" (newv2),
@@ -1062,8 +1064,8 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *
RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3])
#endif
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"cmpl %[v], %[expect]\n\t"
"jnz %l[cmpfail]\n\t"
@@ -1072,7 +1074,7 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *
"jnz %l[cmpfail]\n\t"
RSEQ_INJECT_ASM(5)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), %l[error1])
"cmpl %[v], %[expect]\n\t"
"jnz %l[error2]\n\t"
"cmpl %[expect2], %[v2]\n\t"
@@ -1086,7 +1088,7 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *
RSEQ_ASM_DEFINE_ABORT(4, "", abort)
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (rseq_get_abi()),
+ [rseq_offset] "r" (rseq_offset),
/* cmp2 input */
[v2] "m" (*v2),
[expect2] "r" (expect2),
@@ -1144,15 +1146,15 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_
"movl %[dst], %[rseq_scratch1]\n\t"
"movl %[len], %[rseq_scratch2]\n\t"
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"movl %[expect], %%eax\n\t"
"cmpl %%eax, %[v]\n\t"
"jnz 5f\n\t"
RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 6f)
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 6f)
"movl %[expect], %%eax\n\t"
"cmpl %%eax, %[v]\n\t"
"jnz 7f\n\t"
@@ -1202,7 +1204,7 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_
#endif
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (rseq_get_abi()),
+ [rseq_offset] "r" (rseq_offset),
/* final store input */
[v] "m" (*v),
[expect] "m" (expect),
@@ -1261,15 +1263,15 @@ int rseq_cmpeqv_trymemcpy_storev_release
"movl %[dst], %[rseq_scratch1]\n\t"
"movl %[len], %[rseq_scratch2]\n\t"
/* Start rseq by storing table entry pointer into rseq_cs. */
- RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_ASM_TP_SEGMENT:RSEQ_CS_OFFSET(%[rseq_offset]))
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 4f)
RSEQ_INJECT_ASM(3)
"movl %[expect], %%eax\n\t"
"cmpl %%eax, %[v]\n\t"
"jnz 5f\n\t"
RSEQ_INJECT_ASM(4)
#ifdef RSEQ_COMPARE_TWICE
- RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 6f)
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_ASM_TP_SEGMENT:RSEQ_CPU_ID_OFFSET(%[rseq_offset]), 6f)
"movl %[expect], %%eax\n\t"
"cmpl %%eax, %[v]\n\t"
"jnz 7f\n\t"
@@ -1320,7 +1322,7 @@ int rseq_cmpeqv_trymemcpy_storev_release
#endif
: /* gcc asm goto does not allow outputs */
: [cpu_id] "r" (cpu),
- [rseq_abi] "r" (rseq_get_abi()),
+ [rseq_offset] "r" (rseq_offset),
/* final store input */
[v] "m" (*v),
[expect] "m" (expect),


2022-07-05 13:30:57

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 16/58] linux/dim: Fix divide by 0 in RDMA DIM

From: Tao Liu <[email protected]>

commit 0fe3dbbefb74a8575f61d7801b08dbc50523d60d upstream.

Fix a divide 0 error in rdma_dim_stats_compare() when prev->cpe_ratio ==
0.

CallTrace:
Hardware name: H3C R4900 G3/RS33M2C9S, BIOS 2.00.37P21 03/12/2020
task: ffff880194b78000 task.stack: ffffc90006714000
RIP: 0010:backport_rdma_dim+0x10e/0x240 [mlx_compat]
RSP: 0018:ffff880c10e83ec0 EFLAGS: 00010202
RAX: 0000000000002710 RBX: ffff88096cd7f780 RCX: 0000000000000064
RDX: 0000000000000000 RSI: 0000000000000002 RDI: 0000000000000001
RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000000 R12: 000000001d7c6c09
R13: ffff88096cd7f780 R14: ffff880b174fe800 R15: 0000000000000000
FS: 0000000000000000(0000) GS:ffff880c10e80000(0000)
knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00000000a0965b00 CR3: 000000000200a003 CR4: 00000000007606e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
PKRU: 55555554
Call Trace:
<IRQ>
ib_poll_handler+0x43/0x80 [ib_core]
irq_poll_softirq+0xae/0x110
__do_softirq+0xd1/0x28c
irq_exit+0xde/0xf0
do_IRQ+0x54/0xe0
common_interrupt+0x8f/0x8f
</IRQ>
? cpuidle_enter_state+0xd9/0x2a0
? cpuidle_enter_state+0xc7/0x2a0
? do_idle+0x170/0x1d0
? cpu_startup_entry+0x6f/0x80
? start_secondary+0x1b9/0x210
? secondary_startup_64+0xa5/0xb0
Code: 0f 87 e1 00 00 00 8b 4c 24 14 44 8b 43 14 89 c8 4d 63 c8 44 29 c0 99 31 d0 29 d0 31 d2 48 98 48 8d 04 80 48 8d 04 80 48 c1 e0 02 <49> f7 f1 48 83 f8 0a 0f 86 c1 00 00 00 44 39 c1 7f 10 48 89 df
RIP: backport_rdma_dim+0x10e/0x240 [mlx_compat] RSP: ffff880c10e83ec0

Fixes: f4915455dcf0 ("linux/dim: Implement RDMA adaptive moderation (DIM)")
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Tao Liu <[email protected]>
Reviewed-by: Max Gurtovoy <[email protected]>
Acked-by: Leon Romanovsky <[email protected]>
Signed-off-by: Jason Gunthorpe <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/dim.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

--- a/include/linux/dim.h
+++ b/include/linux/dim.h
@@ -17,7 +17,7 @@
* We consider 10% difference as significant.
*/
#define IS_SIGNIFICANT_DIFF(val, ref) \
- (((100UL * abs((val) - (ref))) / (ref)) > 10)
+ ((ref) && (((100UL * abs((val) - (ref))) / (ref)) > 10))

/**
* Calculate the gap between two values.


2022-07-05 13:31:08

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 19/58] caif_virtio: fix race between virtio_device_ready() and ndo_open()

From: Jason Wang <[email protected]>

commit 11a37eb66812ce6a06b79223ad530eb0e1d7294d upstream.

We currently depend on probe() calling virtio_device_ready() -
which happens after netdev
registration. Since ndo_open() can be called immediately
after register_netdev, this means there exists a race between
ndo_open() and virtio_device_ready(): the driver may start to use the
device (e.g. TX) before DRIVER_OK which violates the spec.

Fix this by switching to use register_netdevice() and protect the
virtio_device_ready() with rtnl_lock() to make sure ndo_open() can
only be called after virtio_device_ready().

Fixes: 0d2e1a2926b18 ("caif_virtio: Introduce caif over virtio")
Signed-off-by: Jason Wang <[email protected]>
Message-Id: <[email protected]>
Signed-off-by: Michael S. Tsirkin <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/caif/caif_virtio.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)

--- a/drivers/net/caif/caif_virtio.c
+++ b/drivers/net/caif/caif_virtio.c
@@ -723,13 +723,21 @@ static int cfv_probe(struct virtio_devic
/* Carrier is off until netdevice is opened */
netif_carrier_off(netdev);

+ /* serialize netdev register + virtio_device_ready() with ndo_open() */
+ rtnl_lock();
+
/* register Netdev */
- err = register_netdev(netdev);
+ err = register_netdevice(netdev);
if (err) {
+ rtnl_unlock();
dev_err(&vdev->dev, "Unable to register netdev (%d)\n", err);
goto err;
}

+ virtio_device_ready(vdev);
+
+ rtnl_unlock();
+
debugfs_init(cfv);

return 0;


2022-07-05 13:31:13

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 38/58] selftests/rseq: Remove volatile from __rseq_abi

From: Mathieu Desnoyers <[email protected]>

commit 94b80a19ebfe347a01301d750040a61c38200e2b upstream.

This is done in preparation for the selftest uplift to become compatible
with glibc-2.35.

All accesses to the __rseq_abi fields are volatile, but remove the
volatile from the TLS variable declaration, otherwise we are stuck with
volatile for the upcoming rseq_get_abi() helper.

Signed-off-by: Mathieu Desnoyers <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
tools/testing/selftests/rseq/rseq.c | 4 ++--
tools/testing/selftests/rseq/rseq.h | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)

--- a/tools/testing/selftests/rseq/rseq.c
+++ b/tools/testing/selftests/rseq/rseq.c
@@ -30,7 +30,7 @@
#include "../kselftest.h"
#include "rseq.h"

-__thread volatile struct rseq_abi __rseq_abi = {
+__thread struct rseq_abi __rseq_abi = {
.cpu_id = RSEQ_ABI_CPU_ID_UNINITIALIZED,
};

@@ -92,7 +92,7 @@ int rseq_register_current_thread(void)
goto end;
}
if (errno != EBUSY)
- __rseq_abi.cpu_id = RSEQ_ABI_CPU_ID_REGISTRATION_FAILED;
+ RSEQ_WRITE_ONCE(__rseq_abi.cpu_id, RSEQ_ABI_CPU_ID_REGISTRATION_FAILED);
ret = -1;
__rseq_refcount--;
end:
--- a/tools/testing/selftests/rseq/rseq.h
+++ b/tools/testing/selftests/rseq/rseq.h
@@ -43,7 +43,7 @@
#define RSEQ_INJECT_FAILED
#endif

-extern __thread volatile struct rseq_abi __rseq_abi;
+extern __thread struct rseq_abi __rseq_abi;
extern int __rseq_handled;

#define rseq_likely(x) __builtin_expect(!!(x), 1)
@@ -139,7 +139,7 @@ static inline uint32_t rseq_current_cpu(

static inline void rseq_clear_rseq_cs(void)
{
- __rseq_abi.rseq_cs.arch.ptr = 0;
+ RSEQ_WRITE_ONCE(__rseq_abi.rseq_cs.arch.ptr, 0);
}

/*


2022-07-05 13:57:09

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 53/58] xen/netfront: force data bouncing when backend is untrusted

From: Roger Pau Monne <[email protected]>

commit 4491001c2e0fa69efbb748c96ec96b100a5cdb7e upstream.

Bounce all data on the skbs to be transmitted into zeroed pages if the
backend is untrusted. This avoids leaking data present in the pages
shared with the backend but not part of the skb fragments. This
requires introducing a new helper in order to allocate skbs with a
size multiple of XEN_PAGE_SIZE so we don't leak contiguous data on the
granted pages.

Reporting whether the backend is to be trusted can be done using a
module parameter, or from the xenstore frontend path as set by the
toolstack when adding the device.

This is CVE-2022-33741, part of XSA-403.

Signed-off-by: Roger Pau Monné <[email protected]>
Reviewed-by: Juergen Gross <[email protected]>
Signed-off-by: Juergen Gross <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/xen-netfront.c | 50 +++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 48 insertions(+), 2 deletions(-)

--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -63,6 +63,10 @@ module_param_named(max_queues, xennet_ma
MODULE_PARM_DESC(max_queues,
"Maximum number of queues per virtual interface");

+static bool __read_mostly xennet_trusted = true;
+module_param_named(trusted, xennet_trusted, bool, 0644);
+MODULE_PARM_DESC(trusted, "Is the backend trusted");
+
#define XENNET_TIMEOUT (5 * HZ)

static const struct ethtool_ops xennet_ethtool_ops;
@@ -163,6 +167,9 @@ struct netfront_info {
/* Is device behaving sane? */
bool broken;

+ /* Should skbs be bounced into a zeroed buffer? */
+ bool bounce;
+
atomic_t rx_gso_checksum_fixup;
};

@@ -590,6 +597,34 @@ static void xennet_mark_tx_pending(struc
queue->tx_link[i] = TX_PENDING;
}

+struct sk_buff *bounce_skb(const struct sk_buff *skb)
+{
+ unsigned int headerlen = skb_headroom(skb);
+ /* Align size to allocate full pages and avoid contiguous data leaks */
+ unsigned int size = ALIGN(skb_end_offset(skb) + skb->data_len,
+ XEN_PAGE_SIZE);
+ struct sk_buff *n = alloc_skb(size, GFP_ATOMIC | __GFP_ZERO);
+
+ if (!n)
+ return NULL;
+
+ if (!IS_ALIGNED((uintptr_t)n->head, XEN_PAGE_SIZE)) {
+ WARN_ONCE(1, "misaligned skb allocated\n");
+ kfree_skb(n);
+ return NULL;
+ }
+
+ /* Set the data pointer */
+ skb_reserve(n, headerlen);
+ /* Set the tail pointer and length */
+ skb_put(n, skb->len);
+
+ BUG_ON(skb_copy_bits(skb, -headerlen, n->head, headerlen + skb->len));
+
+ skb_copy_header(n, skb);
+ return n;
+}
+
#define MAX_XEN_SKB_FRAGS (65536 / XEN_PAGE_SIZE + 1)

static netdev_tx_t xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -642,9 +677,13 @@ static netdev_tx_t xennet_start_xmit(str

/* The first req should be at least ETH_HLEN size or the packet will be
* dropped by netback.
+ *
+ * If the backend is not trusted bounce all data to zeroed pages to
+ * avoid exposing contiguous data on the granted page not belonging to
+ * the skb.
*/
- if (unlikely(PAGE_SIZE - offset < ETH_HLEN)) {
- nskb = skb_copy(skb, GFP_ATOMIC);
+ if (np->bounce || unlikely(PAGE_SIZE - offset < ETH_HLEN)) {
+ nskb = bounce_skb(skb);
if (!nskb)
goto drop;
dev_consume_skb_any(skb);
@@ -1950,6 +1989,10 @@ static int talk_to_netback(struct xenbus

info->netdev->irq = 0;

+ /* Check if backend is trusted. */
+ info->bounce = !xennet_trusted ||
+ !xenbus_read_unsigned(dev->nodename, "trusted", 1);
+
/* Check if backend supports multiple queues */
max_queues = xenbus_read_unsigned(info->xbdev->otherend,
"multi-queue-max-queues", 1);
@@ -2103,6 +2146,9 @@ static int xennet_connect(struct net_dev
err = talk_to_netback(np->xbdev, np);
if (err)
return err;
+ if (np->bounce)
+ dev_info(&np->xbdev->dev,
+ "bouncing transmitted data to zeroed pages\n");

/* talk_to_netback() sets the correct number of queues */
num_queues = dev->real_num_tx_queues;


2022-07-05 14:01:50

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 41/58] selftests/rseq: Uplift rseq selftests for compatibility with glibc-2.35

From: Mathieu Desnoyers <[email protected]>

commit 233e667e1ae3e348686bd9dd0172e62a09d852e1 upstream.

glibc-2.35 (upcoming release date 2022-02-01) exposes the rseq per-thread
data in the TCB, accessible at an offset from the thread pointer, rather
than through an actual Thread-Local Storage (TLS) variable, as the
Linux kernel selftests initially expected.

The __rseq_abi TLS and glibc-2.35's ABI for per-thread data cannot
actively coexist in a process, because the kernel supports only a single
rseq registration per thread.

Here is the scheme introduced to ensure selftests can work both with an
older glibc and with glibc-2.35+:

- librseq exposes its own "rseq_offset, rseq_size, rseq_flags" ABI.

- librseq queries for glibc rseq ABI (__rseq_offset, __rseq_size,
__rseq_flags) using dlsym() in a librseq library constructor. If those
are found, copy their values into rseq_offset, rseq_size, and
rseq_flags.

- Else, if those glibc symbols are not found, handle rseq registration
from librseq and use its own IE-model TLS to implement the rseq ABI
per-thread storage.

Signed-off-by: Mathieu Desnoyers <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
tools/testing/selftests/rseq/Makefile | 2
tools/testing/selftests/rseq/rseq.c | 161 ++++++++++++++++------------------
tools/testing/selftests/rseq/rseq.h | 13 ++
3 files changed, 88 insertions(+), 88 deletions(-)

--- a/tools/testing/selftests/rseq/Makefile
+++ b/tools/testing/selftests/rseq/Makefile
@@ -6,7 +6,7 @@ endif

CFLAGS += -O2 -Wall -g -I./ -I../../../../usr/include/ -L$(OUTPUT) -Wl,-rpath=./ \
$(CLANG_FLAGS)
-LDLIBS += -lpthread
+LDLIBS += -lpthread -ldl

# Own dependencies because we only want to build against 1st prerequisite, but
# still track changes to header files and depend on shared object.
--- a/tools/testing/selftests/rseq/rseq.c
+++ b/tools/testing/selftests/rseq/rseq.c
@@ -26,103 +26,113 @@
#include <assert.h>
#include <signal.h>
#include <limits.h>
+#include <dlfcn.h>

#include "../kselftest.h"
#include "rseq.h"

-__thread struct rseq_abi __rseq_abi = {
- .cpu_id = RSEQ_ABI_CPU_ID_UNINITIALIZED,
-};
+static const int *libc_rseq_offset_p;
+static const unsigned int *libc_rseq_size_p;
+static const unsigned int *libc_rseq_flags_p;
+
+/* Offset from the thread pointer to the rseq area. */
+int rseq_offset;
+
+/* Size of the registered rseq area. 0 if the registration was
+ unsuccessful. */
+unsigned int rseq_size = -1U;

-/*
- * Shared with other libraries. This library may take rseq ownership if it is
- * still 0 when executing the library constructor. Set to 1 by library
- * constructor when handling rseq. Set to 0 in destructor if handling rseq.
- */
-int __rseq_handled;
+/* Flags used during rseq registration. */
+unsigned int rseq_flags;

-/* Whether this library have ownership of rseq registration. */
static int rseq_ownership;

-static __thread volatile uint32_t __rseq_refcount;
+static
+__thread struct rseq_abi __rseq_abi __attribute__((tls_model("initial-exec"))) = {
+ .cpu_id = RSEQ_ABI_CPU_ID_UNINITIALIZED,
+};

-static void signal_off_save(sigset_t *oldset)
+static int sys_rseq(struct rseq_abi *rseq_abi, uint32_t rseq_len,
+ int flags, uint32_t sig)
{
- sigset_t set;
- int ret;
-
- sigfillset(&set);
- ret = pthread_sigmask(SIG_BLOCK, &set, oldset);
- if (ret)
- abort();
+ return syscall(__NR_rseq, rseq_abi, rseq_len, flags, sig);
}

-static void signal_restore(sigset_t oldset)
+int rseq_available(void)
{
- int ret;
+ int rc;

- ret = pthread_sigmask(SIG_SETMASK, &oldset, NULL);
- if (ret)
+ rc = sys_rseq(NULL, 0, 0, 0);
+ if (rc != -1)
abort();
-}
-
-static int sys_rseq(volatile struct rseq_abi *rseq_abi, uint32_t rseq_len,
- int flags, uint32_t sig)
-{
- return syscall(__NR_rseq, rseq_abi, rseq_len, flags, sig);
+ switch (errno) {
+ case ENOSYS:
+ return 0;
+ case EINVAL:
+ return 1;
+ default:
+ abort();
+ }
}

int rseq_register_current_thread(void)
{
- int rc, ret = 0;
- sigset_t oldset;
+ int rc;

- if (!rseq_ownership)
+ if (!rseq_ownership) {
+ /* Treat libc's ownership as a successful registration. */
return 0;
- signal_off_save(&oldset);
- if (__rseq_refcount == UINT_MAX) {
- ret = -1;
- goto end;
}
- if (__rseq_refcount++)
- goto end;
rc = sys_rseq(&__rseq_abi, sizeof(struct rseq_abi), 0, RSEQ_SIG);
- if (!rc) {
- assert(rseq_current_cpu_raw() >= 0);
- goto end;
- }
- if (errno != EBUSY)
- RSEQ_WRITE_ONCE(__rseq_abi.cpu_id, RSEQ_ABI_CPU_ID_REGISTRATION_FAILED);
- ret = -1;
- __rseq_refcount--;
-end:
- signal_restore(oldset);
- return ret;
+ if (rc)
+ return -1;
+ assert(rseq_current_cpu_raw() >= 0);
+ return 0;
}

int rseq_unregister_current_thread(void)
{
- int rc, ret = 0;
- sigset_t oldset;
+ int rc;

- if (!rseq_ownership)
+ if (!rseq_ownership) {
+ /* Treat libc's ownership as a successful unregistration. */
return 0;
- signal_off_save(&oldset);
- if (!__rseq_refcount) {
- ret = -1;
- goto end;
}
- if (--__rseq_refcount)
- goto end;
- rc = sys_rseq(&__rseq_abi, sizeof(struct rseq_abi),
- RSEQ_ABI_FLAG_UNREGISTER, RSEQ_SIG);
- if (!rc)
- goto end;
- __rseq_refcount = 1;
- ret = -1;
-end:
- signal_restore(oldset);
- return ret;
+ rc = sys_rseq(&__rseq_abi, sizeof(struct rseq_abi), RSEQ_ABI_FLAG_UNREGISTER, RSEQ_SIG);
+ if (rc)
+ return -1;
+ return 0;
+}
+
+static __attribute__((constructor))
+void rseq_init(void)
+{
+ libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset");
+ libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size");
+ libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags");
+ if (libc_rseq_size_p && libc_rseq_offset_p && libc_rseq_flags_p) {
+ /* rseq registration owned by glibc */
+ rseq_offset = *libc_rseq_offset_p;
+ rseq_size = *libc_rseq_size_p;
+ rseq_flags = *libc_rseq_flags_p;
+ return;
+ }
+ if (!rseq_available())
+ return;
+ rseq_ownership = 1;
+ rseq_offset = (void *)&__rseq_abi - rseq_thread_pointer();
+ rseq_size = sizeof(struct rseq_abi);
+ rseq_flags = 0;
+}
+
+static __attribute__((destructor))
+void rseq_exit(void)
+{
+ if (!rseq_ownership)
+ return;
+ rseq_offset = 0;
+ rseq_size = -1U;
+ rseq_ownership = 0;
}

int32_t rseq_fallback_current_cpu(void)
@@ -136,20 +146,3 @@ int32_t rseq_fallback_current_cpu(void)
}
return cpu;
}
-
-void __attribute__((constructor)) rseq_init(void)
-{
- /* Check whether rseq is handled by another library. */
- if (__rseq_handled)
- return;
- __rseq_handled = 1;
- rseq_ownership = 1;
-}
-
-void __attribute__((destructor)) rseq_fini(void)
-{
- if (!rseq_ownership)
- return;
- __rseq_handled = 0;
- rseq_ownership = 0;
-}
--- a/tools/testing/selftests/rseq/rseq.h
+++ b/tools/testing/selftests/rseq/rseq.h
@@ -43,12 +43,19 @@
#define RSEQ_INJECT_FAILED
#endif

-extern __thread struct rseq_abi __rseq_abi;
-extern int __rseq_handled;
+#include "rseq-thread-pointer.h"
+
+/* Offset from the thread pointer to the rseq area. */
+extern int rseq_offset;
+/* Size of the registered rseq area. 0 if the registration was
+ unsuccessful. */
+extern unsigned int rseq_size;
+/* Flags used during rseq registration. */
+extern unsigned int rseq_flags;

static inline struct rseq_abi *rseq_get_abi(void)
{
- return &__rseq_abi;
+ return (struct rseq_abi *) ((uintptr_t) rseq_thread_pointer() + rseq_offset);
}

#define rseq_likely(x) __builtin_expect(!!(x), 1)


2022-07-05 17:05:39

by Florian Fainelli

[permalink] [raw]
Subject: Re: [PATCH 5.4 00/58] 5.4.204-rc1 review

On 7/5/22 04:57, Greg Kroah-Hartman wrote:
> This is the start of the stable review cycle for the 5.4.204 release.
> There are 58 patches in this series, all will be posted as a response
> to this one. If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Thu, 07 Jul 2022 11:55:56 +0000.
> Anything received after that time might be too late.
>
> The whole patch series can be found in one patch at:
> https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.4.204-rc1.gz
> or in the git tree and branch at:
> git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.4.y
> and the diffstat can be found below.
>
> thanks,
>
> greg k-h

On ARCH_BRCMSTB using 32-bit and 64-bit ARM kernels:

Tested-by: Florian Fainelli <[email protected]>
--
Florian

2022-07-06 06:58:17

by Naresh Kamboju

[permalink] [raw]
Subject: Re: [PATCH 5.4 00/58] 5.4.204-rc1 review

On Tue, 5 Jul 2022 at 17:34, Greg Kroah-Hartman
<[email protected]> wrote:
>
> This is the start of the stable review cycle for the 5.4.204 release.
> There are 58 patches in this series, all will be posted as a response
> to this one. If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Thu, 07 Jul 2022 11:55:56 +0000.
> Anything received after that time might be too late.
>
> The whole patch series can be found in one patch at:
> https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.4.204-rc1.gz
> or in the git tree and branch at:
> git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.4.y
> and the diffstat can be found below.
>
> thanks,
>
> greg k-h


Results from Linaro’s test farm.
No regressions on arm64, arm, x86_64, and i386.

Tested-by: Linux Kernel Functional Testing <[email protected]>

## Build
* kernel: 5.4.204-rc1
* git: https://gitlab.com/Linaro/lkft/mirrors/stable/linux-stable-rc
* git branch: linux-5.4.y
* git commit: 0f4cd7014f4101204454b404e03101579ef33481
* git describe: v5.4.203-59-g0f4cd7014f41
* test details:
https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-5.4.y/build/v5.4.203-59-g0f4cd7014f41

## Test Regressions (compared to v5.4.203)
No test regressions found.

## Metric Regressions (compared to v5.4.203)
No metric regressions found.

## Test Fixes (compared to v5.4.203)
No test fixes found.

## Metric Fixes (compared to v5.4.203)
No metric fixes found.

## Test result summary
total: 122576, pass: 108899, fail: 260, skip: 12381, xfail: 1036

## Build Summary
* arc: 10 total, 10 passed, 0 failed
* arm: 307 total, 307 passed, 0 failed
* arm64: 61 total, 59 passed, 2 failed
* i386: 28 total, 25 passed, 3 failed
* mips: 48 total, 48 passed, 0 failed
* parisc: 12 total, 12 passed, 0 failed
* powerpc: 54 total, 54 passed, 0 failed
* riscv: 27 total, 27 passed, 0 failed
* s390: 12 total, 12 passed, 0 failed
* sh: 24 total, 24 passed, 0 failed
* sparc: 12 total, 12 passed, 0 failed
* x86_64: 55 total, 54 passed, 1 failed

## Test suites summary
* fwts
* igt-gpu-tools
* kunit
* kvm-unit-tests
* libgpiod
* libhugetlbfs
* log-parser-boot
* log-parser-test
* ltp-cap_bounds
* ltp-commands
* ltp-containers
* ltp-controllers
* ltp-cpuhotplug
* ltp-crypto
* ltp-cve
* ltp-dio
* ltp-fcntl-locktests
* ltp-filecap[
* ltp-filecaps
* ltp-fs
* ltp-fs_bind
* ltp-fs_perms_simple
* ltp-fsx
* ltp-hugetlb
* ltp-io
* ltp-ipc
* ltp-math
* ltp-mm
* ltp-nptl
* ltp-open-posix-tests
* ltp-pty
* ltp-sched
* ltp-securebits
* ltp-smoke
* ltp-syscalls
* ltp-tracing
* network-basic-tests
* packetdrill
* perf
* perf/Zstd-perf.data-compression
* rcutorture
* ssuite
* v4l2-compliance
* vdso

--
Linaro LKFT
https://lkft.linaro.org

2022-07-06 10:22:31

by Sudip Mukherjee

[permalink] [raw]
Subject: Re: [PATCH 5.4 00/58] 5.4.204-rc1 review

Hi Greg,

On Tue, Jul 05, 2022 at 01:57:36PM +0200, Greg Kroah-Hartman wrote:
> This is the start of the stable review cycle for the 5.4.204 release.
> There are 58 patches in this series, all will be posted as a response
> to this one. If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Thu, 07 Jul 2022 11:55:56 +0000.
> Anything received after that time might be too late.

Build test (gcc version 11.3.1 20220627):
mips: 65 configs -> no failure
arm: 106 configs -> no failure
arm64: 2 configs -> no failure
x86_64: 4 configs -> no failure
alpha allmodconfig -> no failure
powerpc allmodconfig -> no failure
riscv allmodconfig -> no failure
s390 allmodconfig -> no failure
xtensa allmodconfig -> no failure


Boot test:
x86_64: Booted on my test laptop. No regression.
x86_64: Booted on qemu. No regression. [1]

[1]. https://openqa.qa.codethink.co.uk/tests/1456


Tested-by: Sudip Mukherjee <[email protected]>

--
Regards
Sudip

2022-07-06 13:52:34

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH 5.4 00/58] 5.4.204-rc1 review

On Tue, Jul 05, 2022 at 01:57:36PM +0200, Greg Kroah-Hartman wrote:
> This is the start of the stable review cycle for the 5.4.204 release.
> There are 58 patches in this series, all will be posted as a response
> to this one. If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Thu, 07 Jul 2022 11:55:56 +0000.
> Anything received after that time might be too late.
>

Build results:
total: 161 pass: 161 fail: 0
Qemu test results:
total: 449 pass: 449 fail: 0

Tested-by: Guenter Roeck <[email protected]>

Guenter

2022-07-07 00:15:57

by Shuah Khan

[permalink] [raw]
Subject: Re: [PATCH 5.4 00/58] 5.4.204-rc1 review

On 7/5/22 5:57 AM, Greg Kroah-Hartman wrote:
> This is the start of the stable review cycle for the 5.4.204 release.
> There are 58 patches in this series, all will be posted as a response
> to this one. If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Thu, 07 Jul 2022 11:55:56 +0000.
> Anything received after that time might be too late.
>
> The whole patch series can be found in one patch at:
> https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.4.204-rc1.gz
> or in the git tree and branch at:
> git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.4.y
> and the diffstat can be found below.
>
> thanks,
>
> greg k-h
>

Compiled and booted on my test system. No dmesg regressions.

Tested-by: Shuah Khan <[email protected]>

thanks,
-- Shuah