* Re: [PATCH v3 1/3] crypto: atmel-sha204a - fix memory leak at non-blocking RNG work_data
From: Thorsten Blum @ 2026-04-26 13:33 UTC (permalink / raw)
To: Lothar Rubusch
Cc: herbert, davem, nicolas.ferre, alexandre.belloni, claudiu.beznea,
ardb, linusw, linux-crypto, linux-arm-kernel, linux-kernel
In-Reply-To: <20260422210936.20095-2-l.rubusch@gmail.com>
On Wed, Apr 22, 2026 at 09:09:34PM +0000, Lothar Rubusch wrote:
> The driver allocated memory for work_data in the non-blocking read
> path but never free'd it again.
Yes, 'work_data' is allocated once on the first nonblocking RNG request
and reused for subsequent requests, but the memory is eventually freed
on device removal in atmel_sha204a_remove().
The memory might be retained unnecessarily after use when the device is
idle (probably negligible), but it's not a memory leak.
Best,
Thorsten
^ permalink raw reply
* [PATCH] media: sun4i-csi: Clean up media device on probe errors
From: Myeonghun Pak @ 2026-04-26 13:58 UTC (permalink / raw)
To: Maxime Ripard, Mauro Carvalho Chehab
Cc: Myeonghun Pak, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
Ijae Kim
sun4i_csi_probe() initializes the media device before acquiring the
MMIO resource, IRQ, clocks, reset control and media entity pads.
Several of those failure paths return directly.
media_device_cleanup() is still required after media_device_init(),
and a failed probe does not run the driver remove callback. Route
those errors through the existing media-device cleanup path before
returning.
Co-developed-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
---
drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c | 32 ++++++++++++++--------
1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
index e53a07b770..a504a1c78e 100644
--- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
+++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
@@ -187,37 +187,45 @@ static int sun4i_csi_probe(struct platform_device *pdev)
csi->v4l.mdev = &csi->mdev;
csi->regs = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(csi->regs))
- return PTR_ERR(csi->regs);
+ if (IS_ERR(csi->regs)) {
+ ret = PTR_ERR(csi->regs);
+ goto err_clean_mdev;
+ }
irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- return irq;
+ if (irq < 0) {
+ ret = irq;
+ goto err_clean_mdev;
+ }
csi->bus_clk = devm_clk_get(&pdev->dev, "bus");
if (IS_ERR(csi->bus_clk)) {
dev_err(&pdev->dev, "Couldn't get our bus clock\n");
- return PTR_ERR(csi->bus_clk);
+ ret = PTR_ERR(csi->bus_clk);
+ goto err_clean_mdev;
}
if (csi->traits->has_isp) {
csi->isp_clk = devm_clk_get(&pdev->dev, "isp");
if (IS_ERR(csi->isp_clk)) {
dev_err(&pdev->dev, "Couldn't get our ISP clock\n");
- return PTR_ERR(csi->isp_clk);
+ ret = PTR_ERR(csi->isp_clk);
+ goto err_clean_mdev;
}
}
csi->ram_clk = devm_clk_get(&pdev->dev, "ram");
if (IS_ERR(csi->ram_clk)) {
dev_err(&pdev->dev, "Couldn't get our ram clock\n");
- return PTR_ERR(csi->ram_clk);
+ ret = PTR_ERR(csi->ram_clk);
+ goto err_clean_mdev;
}
csi->rst = devm_reset_control_get(&pdev->dev, NULL);
if (IS_ERR(csi->rst)) {
dev_err(&pdev->dev, "Couldn't get our reset line\n");
- return PTR_ERR(csi->rst);
+ ret = PTR_ERR(csi->rst);
+ goto err_clean_mdev;
}
/* Initialize subdev */
@@ -236,17 +244,17 @@ static int sun4i_csi_probe(struct platform_device *pdev)
ret = media_entity_pads_init(&subdev->entity, CSI_SUBDEV_PADS,
csi->subdev_pads);
if (ret < 0)
- return ret;
+ goto err_clean_mdev;
csi->vdev_pad.flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
vdev->entity.ops = &sun4i_csi_video_entity_ops;
ret = media_entity_pads_init(&vdev->entity, 1, &csi->vdev_pad);
if (ret < 0)
- return ret;
+ goto err_clean_mdev;
ret = sun4i_csi_dma_register(csi, irq);
if (ret)
- goto err_clean_pad;
+ goto err_clean_mdev;
ret = sun4i_csi_notifier_init(csi);
if (ret)
@@ -266,7 +274,7 @@ static int sun4i_csi_probe(struct platform_device *pdev)
media_device_unregister(&csi->mdev);
sun4i_csi_dma_unregister(csi);
-err_clean_pad:
+err_clean_mdev:
media_device_cleanup(&csi->mdev);
return ret;
^ permalink raw reply related
* Re: [PATCH v4 35/49] KVM: arm64: GICv3: nv: Plug L1 LR sync into deactivation primitive
From: Marc Zyngier @ 2026-04-26 14:07 UTC (permalink / raw)
To: Vishnu Pajjuri
Cc: Fuad Tabba, Joey Gouly, Suzuki K Poulose, Oliver Upton,
Zenghui Yu, Christoffer Dall, Mark Brown, kvm, linux-arm-kernel,
kvmarm, Darren Hart
In-Reply-To: <861pg213to.wl-maz@kernel.org>
On Sun, 26 Apr 2026 10:14:11 +0100,
Marc Zyngier <maz@kernel.org> wrote:
>
> On Wed, 22 Apr 2026 15:57:44 +0100,
> Vishnu Pajjuri <vishnu@os.amperecomputing.com> wrote:
> >
> > Hi Marc,
> >
> > On 22-04-2026 12:25, Marc Zyngier wrote:
> > >
> > > Have you made progress on this? I can't reproduce it at all despite my
> > > best effort. I'm perfectly happy to help, but you need to give me
> > > *something* to go on.
> >
> >
> > Thanks for your support!!
> >
> > The issue is triggered as soon as the timer interrupt (IRQ 27) is
> > deactivated. Preventing the deactivation of IRQ 27 during nested VGIC
> > state transitions prevents the failure from reproducing.
>
> Which level of deactivation? From L2 to L1? Or L1 to L0? The former
> should just be a an update to the irq structure, while the latter is
> effectively a write to ICC_DIR_EL1, and *that* is a new behaviour
> introduced by this patch.
>
> I wonder if your implementation is such that ICC_DIR_EL1 is trapped by
> ICH_HCR_EL2.TDIR, which is allowed by the architecture, but that none
> of the two implementations I have actually enforce (the trap only
> applies to ICV_DIR_EL1). Can you try the hack below which disables the
> traps much earlier, and let me know if that helps?
>
> Even if that's the case, this should result in an EL2->EL2 exception,
> and that should be caught as an unhandled exception in entry-common.c,
> so something else is afoot.
Actually, this should never happen. ICH_HCR_EL2.TDIR is constructed
like all the other GICv3 trap bits, in the sense that it only traps
accesses from EL1, not EL2 (for sanity reasons, I'm not considering
the possibility of a trap to EL3...).
Still, I'm interested in finding out if that hack helps at all.
Thanks,
M.
--
Jazz isn't dead. It just smells funny.
^ permalink raw reply
* Re: [PATCH v2] interconnect: imx: fix use-after-free in imx_icc_node_init_qos()
From: kernel test robot @ 2026-04-26 14:19 UTC (permalink / raw)
To: Wentao Liang, Georgi Djakov, Shawn Guo, Sascha Hauer
Cc: llvm, oe-kbuild-all, Pengutronix Kernel Team, Fabio Estevam,
Wentao Liang, linux-pm, imx, linux-arm-kernel, linux-kernel,
stable
In-Reply-To: <20260408153022.401123-1-vulab@iscas.ac.cn>
Hi Wentao,
kernel test robot noticed the following build errors:
[auto build test ERROR on amd-pstate/linux-next]
[also build test ERROR on amd-pstate/bleeding-edge linus/master shawnguo/for-next v7.0 next-20260424]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Wentao-Liang/interconnect-imx-fix-use-after-free-in-imx_icc_node_init_qos/20260424-225513
base: https://git.kernel.org/pub/scm/linux/kernel/git/superm1/linux.git linux-next
patch link: https://lore.kernel.org/r/20260408153022.401123-1-vulab%40iscas.ac.cn
patch subject: [PATCH v2] interconnect: imx: fix use-after-free in imx_icc_node_init_qos()
config: sparc64-allmodconfig (https://download.01.org/0day-ci/archive/20260426/202604262216.MLuzg6nl-lkp@intel.com/config)
compiler: clang version 23.0.0git (https://github.com/llvm/llvm-project 5bac06718f502014fade905512f1d26d578a18f3)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260426/202604262216.MLuzg6nl-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202604262216.MLuzg6nl-lkp@intel.com/
All errors (new ones prefixed by >>):
>> drivers/interconnect/imx/imx.c:123:22: error: use of undeclared identifier '__free_device_nod'; did you mean '__free_device_node'?
123 | struct device_node *__free(device_nod) dn = of_parse_phandle(dev->of_node,
| ^~~~~~~~~~~~~~~~~~
include/linux/cleanup.h:213:33: note: expanded from macro '__free'
213 | #define __free(_name) __cleanup(__free_##_name)
| ^~~~~~~~~~~~~~
<scratch space>:42:1: note: expanded from here
42 | __free_device_nod
| ^~~~~~~~~~~~~~~~~
include/linux/of.h:138:1: note: '__free_device_node' declared here
138 | DEFINE_FREE(device_node, struct device_node *, if (_T) of_node_put(_T))
| ^
include/linux/cleanup.h:211:30: note: expanded from macro 'DEFINE_FREE'
211 | static __always_inline void __free_##_name(void *p) { _type _T = *(_type *)p; _free; }
| ^
<scratch space>:227:1: note: expanded from here
227 | __free_device_node
| ^
1 error generated.
vim +123 drivers/interconnect/imx/imx.c
116
117 static int imx_icc_node_init_qos(struct icc_provider *provider,
118 struct icc_node *node)
119 {
120 struct imx_icc_node *node_data = node->data;
121 const struct imx_icc_node_adj_desc *adj = node_data->desc->adj;
122 struct device *dev = provider->dev;
> 123 struct device_node *__free(device_nod) dn = of_parse_phandle(dev->of_node,
124 adj->phandle_name, 0);
125 struct platform_device *pdev;
126
127 if (adj->main_noc) {
128 node_data->qos_dev = dev;
129 dev_dbg(dev, "icc node %s[%d] is main noc itself\n",
130 node->name, node->id);
131 } else {
132 if (!dn) {
133 dev_warn(dev, "Failed to parse %s\n",
134 adj->phandle_name);
135 return -ENODEV;
136 }
137 /* Allow scaling to be disabled on a per-node basis */
138 if (!of_device_is_available(dn)) {
139 dev_warn(dev, "Missing property %s, skip scaling %s\n",
140 adj->phandle_name, node->name);
141 return 0;
142 }
143
144 pdev = of_find_device_by_node(dn);
145 if (!pdev) {
146 dev_warn(dev, "node %s[%d] missing device for %pOF\n",
147 node->name, node->id, dn);
148 return -EPROBE_DEFER;
149 }
150 node_data->qos_dev = &pdev->dev;
151 dev_dbg(dev, "node %s[%d] has device node %pOF\n",
152 node->name, node->id, dn);
153 }
154
155 return dev_pm_qos_add_request(node_data->qos_dev,
156 &node_data->qos_req,
157 DEV_PM_QOS_MIN_FREQUENCY, 0);
158 }
159
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* [PATCH] wifi: mt76: mt7925: clean up DMA on probe failure
From: 박명훈 @ 2026-04-26 14:33 UTC (permalink / raw)
To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Shayne Chen,
Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno, Ijae Kim
Cc: linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek,
Myeonghun Pak
From: Myeonghun Pak <mhun512@gmail.com>
mt7925_pci_probe() initializes DMA before registering the device. If
mt7925_register_device() fails, probe returns through err_free_irq without
tearing down DMA state.
That leaves the TX NAPI instance enabled and skips the DMA queue cleanup
that the normal remove path performs through mt7925e_unregister_device().
Add a dedicated unwind label for failures after mt7925_dma_init() succeeds.
Fixes: c948b5da6bbe ("wifi: mt76: mt7925: add Mediatek Wi-Fi7 driver for mt7925 chips")
Co-developed-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
---
drivers/net/wireless/mediatek/mt76/mt7925/pci.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
index c4161754c0..4883772302 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
@@ -415,10 +415,12 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
ret = mt7925_register_device(dev);
if (ret)
- goto err_free_irq;
+ goto err_free_dma;
return 0;
+err_free_dma:
+ mt792x_dma_cleanup(dev);
err_free_irq:
devm_free_irq(&pdev->dev, pdev->irq, dev);
err_free_dev:
--
2.39.5
^ permalink raw reply related
* Re: [PATCH] iio: adc: meson-saradc: fix calibration buffer leak on error
From: Felix Gu @ 2026-04-26 15:26 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Rosen Penev, David Lechner, Nuno Sá, Andy Shevchenko,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
linux-iio, linux-arm-kernel, linux-amlogic, linux-kernel
In-Reply-To: <20260426114118.7ad8b130@jic23-huawei>
On Sun, Apr 26, 2026 at 6:41 PM Jonathan Cameron <jic23@kernel.org> wrote:
>
> That is the minimal fix, so we should probably do that first
> even if we then circle back to consider if __free() magic is worth using here.
>
> J
Hi Jonathan,
You prefer a minimal fix here?
Best regards,
Felix
^ permalink raw reply
* [PATCH v4 1/1] crypto: atmel-sha204a - fix non-blocking read logic
From: Lothar Rubusch @ 2026-04-26 15:49 UTC (permalink / raw)
To: herbert, thorsten.blum, davem, nicolas.ferre, alexandre.belloni,
claudiu.beznea, ardb, linusw
Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch
In-Reply-To: <20260426154940.24375-1-l.rubusch@gmail.com>
The blocking and non-blocking paths were failing to provide valid entropy
due to improper buffer management. Read the buffer starting from bit 1,
only fetch the 32 bytes of random data of the return message.
Tested on a Atmel SHA204a device.
Before (here for blocking) tests showed repeadetly reading reduced bytes of
entropy:
$ head -c 32 /dev/hwrng | hexdump -C
00000000 02 28 85 b3 47 40 f2 ee 00 00 00 00 00 00 00 00 |.(..G@..........|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020
After, the result will be similar to the following:
$ head -c 32 /dev/hwrng | hexdump -C
00000000 5a fc 3f 13 14 68 fe 06 68 0a bd 04 83 6e 09 69 |Z.?..h..h....n.i|
00000010 75 ff cf 87 10 84 3b c9 c1 df ae eb 45 53 4c c3 |u.....;.....ESL.|
00000020
Fixes: da001fb651b0 ("crypto: atmel-i2c - add support for SHA204A random number generator")
Suggested-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
drivers/crypto/atmel-sha204a.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c
index dbb39ed0cea1..39a229086a84 100644
--- a/drivers/crypto/atmel-sha204a.c
+++ b/drivers/crypto/atmel-sha204a.c
@@ -48,8 +48,8 @@ static int atmel_sha204a_rng_read_nonblocking(struct hwrng *rng, void *data,
if (rng->priv) {
work_data = (struct atmel_i2c_work_data *)rng->priv;
- max = min(sizeof(work_data->cmd.data), max);
- memcpy(data, &work_data->cmd.data, max);
+ max = min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max);
+ memcpy(data, &work_data->cmd.data[1], max);
rng->priv = 0;
} else {
work_data = kmalloc_obj(*work_data, GFP_ATOMIC);
@@ -87,8 +87,8 @@ static int atmel_sha204a_rng_read(struct hwrng *rng, void *data, size_t max,
if (ret)
return ret;
- max = min(sizeof(cmd.data), max);
- memcpy(data, cmd.data, max);
+ max = min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max);
+ memcpy(data, &cmd.data[1], max);
return max;
}
--
2.39.5
^ permalink raw reply related
* [PATCH v4 0/1] crypto: atmel-sha204a - multiple RNG fixes
From: Lothar Rubusch @ 2026-04-26 15:49 UTC (permalink / raw)
To: herbert, thorsten.blum, davem, nicolas.ferre, alexandre.belloni,
claudiu.beznea, ardb, linusw
Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch
When testing the RNG functionality on the Atmel SHA204a hardware, rngtest
reported failures. Fix start of reading and size of fetched data.
I verified and applied Ard's solution (tagged it with sugtgested-by, pls
tell me if I used the wrong tag).
Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
v3 -> v4: Reduce seet and set focus on RNG fix, blocking and nonblocking
v2 -> v3: Removal blank line, rebased
v1 -> v2: Removal of C++ style comment
---
Lothar Rubusch (1):
crypto: atmel-sha204a - fix non-blocking read logic
drivers/crypto/atmel-sha204a.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
base-commit: 5db6ef9847717329f12c5ea8aba7e9f588a980c0
--
2.39.5
^ permalink raw reply
* Re: [PATCH v3 1/3] crypto: atmel-sha204a - fix memory leak at non-blocking RNG work_data
From: Lothar Rubusch @ 2026-04-26 16:16 UTC (permalink / raw)
To: Thorsten Blum
Cc: herbert, davem, nicolas.ferre, alexandre.belloni, claudiu.beznea,
ardb, linusw, linux-crypto, linux-arm-kernel, linux-kernel
In-Reply-To: <ae4UD-JGUarmSMiK@linux.dev>
Hi Thorsten and Ard & ML,
This is just two general questions on some details of this driver.
Perhaps you could
give me some insights here.
On Sun, Apr 26, 2026 at 3:33 PM Thorsten Blum <thorsten.blum@linux.dev> wrote:
>
> On Wed, Apr 22, 2026 at 09:09:34PM +0000, Lothar Rubusch wrote:
> > The driver allocated memory for work_data in the non-blocking read
> > path but never free'd it again.
>
> Yes, 'work_data' is allocated once on the first nonblocking RNG request
> and reused for subsequent requests, but the memory is eventually freed
> on device removal in atmel_sha204a_remove().
>
> The memory might be retained unnecessarily after use when the device is
> idle (probably negligible), but it's not a memory leak.
>
> Best,
> Thorsten
1. Actually, having `work_data` allocated once/rarely and usually re-used.
Stupid question: could it be allocated also with managed device memory? I
usually use devm_ allocs rather in probe for related general instances,
here I'm a bit in doubt. Could it be used here as well, or why not?
2. In `atmel_sha204a_rng_read()` there is the function variable
`struct atmel_i2c_cmd cmd;`.
AFAIR allocation on the heap is preferable to stack variables, particularly
for structs and any non-primitive types. So, wouldn't it be better to have
`*cmd` as a pointer, dynamically allocate memory at the beginning of this
function and free it at the end of this function again?
Best,
L
^ permalink raw reply
* Re: [PATCH v4 1/1] crypto: atmel-sha204a - fix non-blocking read logic
From: Thorsten Blum @ 2026-04-26 16:43 UTC (permalink / raw)
To: Lothar Rubusch
Cc: herbert, davem, nicolas.ferre, alexandre.belloni, claudiu.beznea,
ardb, linusw, linux-crypto, linux-arm-kernel, linux-kernel
In-Reply-To: <20260426154940.24375-2-l.rubusch@gmail.com>
On Sun, Apr 26, 2026 at 03:49:40PM +0000, Lothar Rubusch wrote:
> The blocking and non-blocking paths were failing to provide valid entropy
> due to improper buffer management. Read the buffer starting from bit 1,
> only fetch the 32 bytes of random data of the return message.
>
> Tested on a Atmel SHA204a device.
>
> Before (here for blocking) tests showed repeadetly reading reduced bytes of
s/repeadetly/repeatedly/
> entropy:
> $ head -c 32 /dev/hwrng | hexdump -C
> 00000000 02 28 85 b3 47 40 f2 ee 00 00 00 00 00 00 00 00 |.(..G@..........|
> 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
> 00000020
>
> After, the result will be similar to the following:
> $ head -c 32 /dev/hwrng | hexdump -C
> 00000000 5a fc 3f 13 14 68 fe 06 68 0a bd 04 83 6e 09 69 |Z.?..h..h....n.i|
> 00000010 75 ff cf 87 10 84 3b c9 c1 df ae eb 45 53 4c c3 |u.....;.....ESL.|
> 00000020
>
> Fixes: da001fb651b0 ("crypto: atmel-i2c - add support for SHA204A random number generator")
> Suggested-by: Ard Biesheuvel <ardb@kernel.org>
> Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
> ---
> drivers/crypto/atmel-sha204a.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c
> index dbb39ed0cea1..39a229086a84 100644
> --- a/drivers/crypto/atmel-sha204a.c
> +++ b/drivers/crypto/atmel-sha204a.c
> @@ -48,8 +48,8 @@ static int atmel_sha204a_rng_read_nonblocking(struct hwrng *rng, void *data,
>
> if (rng->priv) {
> work_data = (struct atmel_i2c_work_data *)rng->priv;
> - max = min(sizeof(work_data->cmd.data), max);
> - memcpy(data, &work_data->cmd.data, max);
> + max = min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max);
> + memcpy(data, &work_data->cmd.data[1], max);
Please use RSP_DATA_IDX instead of 1 as the index.
> rng->priv = 0;
> } else {
> work_data = kmalloc_obj(*work_data, GFP_ATOMIC);
> @@ -87,8 +87,8 @@ static int atmel_sha204a_rng_read(struct hwrng *rng, void *data, size_t max,
> if (ret)
> return ret;
>
> - max = min(sizeof(cmd.data), max);
> - memcpy(data, cmd.data, max);
> + max = min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max);
> + memcpy(data, &cmd.data[1], max);
Same here.
Thanks,
Thorsten
^ permalink raw reply
* Re: [PATCH RFC v2 1/2] arm64: vdso: Prepare for robust futex unlock support
From: Thomas Weißschuh @ 2026-04-26 18:07 UTC (permalink / raw)
To: André Almeida
Cc: Catalin Marinas, Will Deacon, Thomas Gleixner, Mark Rutland,
Mathieu Desnoyers, Sebastian Andrzej Siewior, Carlos O'Donell,
Peter Zijlstra, Florian Weimer, Rich Felker, Torvald Riegel,
Darren Hart, Ingo Molnar, Davidlohr Bueso, Arnd Bergmann,
Liam R . Howlett, Uros Bizjak, linux-arm-kernel, linux-kernel,
linux-arch, kernel-dev
In-Reply-To: <20260424-tonyk-robust_arm-v2-1-db4e46f752cf@igalia.com>
Hi André,
Some more comments, after doing an actual proper review.
On 2026-04-24 15:56:00-0300, André Almeida wrote:
> There will be a VDSO function to unlock non-contended robust futexes in
> user space. The unlock sequence is racy vs. clearing the list_pending_op
> pointer in the task's robust list head. To plug this race the kernel needs
> to know the critical section window so it can clear the pointer when the
> task is interrupted within that race window. The window is determined by
> labels in the inline assembly.
>
> Signed-off-by: André Almeida <andrealmeid@igalia.com>
> ---
> Changes from v1:
> - Fixed linker not finding VDSO symbols
> ---
> arch/arm64/kernel/vdso.c | 30 ++++++++++++++++++++++++++++++
> arch/arm64/kernel/vdso/vdso.lds.S | 7 +++++++
> 2 files changed, 37 insertions(+)
What is the reason for splitting the series into two patches?
To me it looks like it should be one patch.
> diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
> index 592dd8668de4..f9c520a1c942 100644
> --- a/arch/arm64/kernel/vdso.c
> +++ b/arch/arm64/kernel/vdso.c
> @@ -11,6 +11,7 @@
> #include <linux/clocksource.h>
> #include <linux/elf.h>
> #include <linux/err.h>
> +#include <linux/futex.h>
> #include <linux/errno.h>
> #include <linux/gfp.h>
> #include <linux/kernel.h>
> @@ -57,6 +58,33 @@ static struct vdso_abi_info vdso_info[] __ro_after_init = {
> #endif /* CONFIG_COMPAT_VDSO */
> };
>
> +#ifdef CONFIG_FUTEX_ROBUST_UNLOCK
> +static void vdso_futex_robust_unlock_update_ips(enum vdso_abi abi, struct mm_struct *mm)
> +{
> + unsigned long vdso = (unsigned long) mm->context.vdso;
> + struct futex_mm_data *fd = &mm->futex;
> + uintptr_t success, end;
> +
> + if (abi == VDSO_ABI_AA64) {
> + success = (uintptr_t) VDSO_SYMBOL(vdso, futex_list64_try_unlock_cs_success);
> + end = (uintptr_t) VDSO_SYMBOL(vdso, futex_list64_try_unlock_cs_end);
> +
> + futex_set_vdso_cs_range(fd, 0, vdso, success, end, false);
Both VDSO_SYMBOL() and futex_set_vdso_cs_range() add the vdso base
address to the symbol offsets. The value stored in .start_ip will be
wrong. The fact that futex_set_vdso_cs_range() does the addition looks
like an artifact of it being written for x86 first. IMO its interface
should be changed not to do the addition internally.
> + }
> +
> +#ifdef CONFIG_COMPAT_VDSO
> + if (abi == VDSO_ABI_AA32) {
> + success = (uintptr_t) VDSO_SYMBOL(vdso, futex_list32_try_unlock_cs_success);
> + end = (uintptr_t) VDSO_SYMBOL(vdso, futex_list32_try_unlock_cs_end);
> +
> + futex_set_vdso_cs_range(fd, 1, vdso, success, end, true);
> + }
> +#endif
> +}
> +#else
> +static inline void vdso_futex_robust_unlock_update_ips(enum vdso_abi abi, struct mm_struct *mm) { }
> +#endif /* CONFIG_FUTEX_ROBUST_UNLOCK */
> +
> static int vdso_mremap(const struct vm_special_mapping *sm,
> struct vm_area_struct *new_vma)
> {
(...)
^ permalink raw reply
* Re: [PATCH RFC v2 2/2] arm64: vdso: Implement __vdso_futex_robust_try_unlock()
From: Thomas Weißschuh @ 2026-04-26 18:30 UTC (permalink / raw)
To: André Almeida
Cc: Catalin Marinas, Will Deacon, Thomas Gleixner, Mark Rutland,
Mathieu Desnoyers, Sebastian Andrzej Siewior, Carlos O'Donell,
Peter Zijlstra, Florian Weimer, Rich Felker, Torvald Riegel,
Darren Hart, Ingo Molnar, Davidlohr Bueso, Arnd Bergmann,
Liam R . Howlett, Uros Bizjak, linux-arm-kernel, linux-kernel,
linux-arch, kernel-dev
In-Reply-To: <20260424-tonyk-robust_arm-v2-2-db4e46f752cf@igalia.com>
On 2026-04-24 15:56:01-0300, André Almeida wrote:
(...)
> Signed-off-by: André Almeida <andrealmeid@igalia.com>
> ---
> RFC:
> - Should I duplicate the explanation found in the x86 commit or can I just
> point to it?
> - Only LL/SC for now but I can add LSE later if this looks good
> - It the objdump I see that op_pending is store at x2. But how stable is this,
> how can I write it in a way that's always x2?
> ---
> arch/arm64/Kconfig | 1 +
> arch/arm64/include/asm/futex_robust.h | 35 +++++++++++++
> arch/arm64/kernel/vdso/Makefile | 9 +++-
> arch/arm64/kernel/vdso/vdso.lds.S | 4 ++
> .../kernel/vdso/vfutex_robust_list_try_unlock.c | 59 ++++++++++++++++++++++
> 5 files changed, 107 insertions(+), 1 deletion(-)
What about the actual 32-bit vDSO in arch/arm64/kernel/vdso32/ ?
(...)
> diff --git a/arch/arm64/kernel/vdso/vfutex_robust_list_try_unlock.c b/arch/arm64/kernel/vdso/vfutex_robust_list_try_unlock.c
> new file mode 100644
> index 000000000000..e8a8fb22a2fa
> --- /dev/null
> +++ b/arch/arm64/kernel/vdso/vfutex_robust_list_try_unlock.c
> @@ -0,0 +1,59 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +#include <vdso/futex.h>
> +#include <linux/stringify.h>
> +
> +#define LABEL(name, sz) __stringify(__futex_list##sz##_try_unlock_cs_##name)
We should have some defines for these symbols. While they are not
userspace ABI, they will be used by the selftests.
> +#define GLOBLS(sz) ".globl " LABEL(start, sz) ", " LABEL(success, sz) ", " LABEL(end, sz) "\n"
> +
> +__u32 __vdso_futex_robust_list64_try_unlock(__u32 *lock, __u32 tid, __u64 *pop)
> +{
> + __u32 val, result;
> +
> + asm volatile (
> + GLOBLS(64)
> + " prfm pstl1strm, %[lock] \n"
> + LABEL(start, 64)": \n"
> + " ldxr %[val], %[lock] \n"
> + " cmp %[tid], %[val] \n"
> + " bne " LABEL(end, 64)" \n"
> + " stlxr %w[result], xzr, %[lock] \n"
> + " cbnz %w[result], " LABEL(start, 64)" \n"
> + LABEL(success, 64)": \n"
> + " str xzr, %[pop] \n"
> + LABEL(end, 64)": \n"
> +
> + : [val] "=&r" (val), [result] "=r" (result)
> + : [tid] "r" (tid), [lock] "Q" (*lock), [pop] "Q" (*pop)
> + : "memory"
> + );
My clang 22.1.3 chokes on the assembly in this patch.
> +
> + return val;
> +}
> +
> +#ifdef CONFIG_COMPAT_VDSO
I am wondering about the CONFIG_COMPAT{,_VDSO} dependency here.
As far as I know the list32 variant is meant to be used by code
emulators which run 32-bit code on a 64-bit kernel, for example FEX.
But these emulators don't actually seem to need CONFIG_COMPAT.
So the dependency does not look correct.
The space savings also should be irrelevant.
The x86 series from Thomas does the same, maybe he will read this
comment, otherwise I'll bring it up on his series, too.
> +__u32 __vdso_futex_robust_list32_try_unlock(__u32 *lock, __u32 tid, __u32 *pop)
> +{
> + __u32 val, result;
> +
> + asm volatile (
> + GLOBLS(32)
> + " prfm pstl1strm, %[lock] \n"
> + LABEL(start, 32)": \n"
> + " ldxr %w[val], %[lock] \n"
> + " cmp %w[tid], %w[val] \n"
> + " bne " LABEL(end, 32)" \n"
> + " stlxr %w[result], wzr, %w[lock] \n"
> + " cbnz %w[result], " LABEL(start, 32)" \n"
> + LABEL(success, 32)": \n"
> + " str wzr, %w[pop] \n"
> + LABEL(end, 32)": \n"
> +
> + : [val] "=&r" (val), [result] "=r" (result)
> + : [tid] "r" (tid), [lock] "Q" (*lock), [pop] "Q" (*pop)
> + : "memory"
> + );
> +
> + return val;
> +}
> +#endif
^ permalink raw reply
* Re: [PATCH RFC v2 1/2] arm64: vdso: Prepare for robust futex unlock support
From: Thomas Weißschuh @ 2026-04-26 19:04 UTC (permalink / raw)
To: André Almeida
Cc: Catalin Marinas, Will Deacon, Thomas Gleixner, Mark Rutland,
Mathieu Desnoyers, Sebastian Andrzej Siewior, Carlos O'Donell,
Peter Zijlstra, Florian Weimer, Rich Felker, Torvald Riegel,
Darren Hart, Ingo Molnar, Davidlohr Bueso, Arnd Bergmann,
Liam R . Howlett, Uros Bizjak, linux-arm-kernel, linux-kernel,
linux-arch, kernel-dev
In-Reply-To: <20260424-tonyk-robust_arm-v2-1-db4e46f752cf@igalia.com>
One more thing, sorry for the spam.
On 2026-04-24 15:56:00-0300, André Almeida wrote:
(...)
> +#ifdef CONFIG_FUTEX_ROBUST_UNLOCK
> +static void vdso_futex_robust_unlock_update_ips(enum vdso_abi abi, struct mm_struct *mm)
> +{
> + unsigned long vdso = (unsigned long) mm->context.vdso;
> + struct futex_mm_data *fd = &mm->futex;
> + uintptr_t success, end;
> +
> + if (abi == VDSO_ABI_AA64) {
> + success = (uintptr_t) VDSO_SYMBOL(vdso, futex_list64_try_unlock_cs_success);
> + end = (uintptr_t) VDSO_SYMBOL(vdso, futex_list64_try_unlock_cs_end);
> +
> + futex_set_vdso_cs_range(fd, 0, vdso, success, end, false);
> + }
> +
> +#ifdef CONFIG_COMPAT_VDSO
> + if (abi == VDSO_ABI_AA32) {
> + success = (uintptr_t) VDSO_SYMBOL(vdso, futex_list32_try_unlock_cs_success);
> + end = (uintptr_t) VDSO_SYMBOL(vdso, futex_list32_try_unlock_cs_end);
The futex_list32_ symbols here are in the 64-bit vDSO. They are not
applicable for VDSO_ABI_AA32 processes.
> +
> + futex_set_vdso_cs_range(fd, 1, vdso, success, end, true);
> + }
> +#endif
> +}
(...)
^ permalink raw reply
* Re: [PATCH 3/3] spi: rockchip: Drop dead zero-check on fifo_len
From: Mark Brown @ 2026-04-26 20:36 UTC (permalink / raw)
To: John Madieu
Cc: heiko, jon.lin, linux-spi, linux-arm-kernel, linux-rockchip,
linux-kernel
In-Reply-To: <20260425092936.2590132-4-john.madieu@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 641 bytes --]
On Sat, Apr 25, 2026 at 09:29:36AM +0000, John Madieu wrote:
> rs->fifo_len is assigned from get_fifo_len(), which returns 64 for the
> two known SPI controller versions and 32 for everything else - never 0.
> The subsequent
> if (!rs->fifo_len)
> return dev_err_probe(...);
> is therefore unreachable.
> Drop the check. If unknown controller versions ever need to fail probe
> explicitly, that should be expressed in get_fifo_len() itself, not
> through an impossible post-condition.
That looks like it's intended as a "you added a new hardware type and
forgot to fill in this field" type check intended to never fire in
production?
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* [PATCH] firmware: samsung: fix stale response flag in acpm_prepare_xfer()
From: Titouan Ameline de Cadeville @ 2026-04-26 21:02 UTC (permalink / raw)
To: tudor.ambarus
Cc: krzk, alim.akhtar, linux-kernel, linux-samsung-soc,
linux-arm-kernel, Titouan Ameline de Cadeville
acpm_prepare_xfer() only ever set rx_data->response to true, never
false. A reused sequence number slot could therefore inherit a stale
true from a previous transfer that expected a response, causing
acpm_get_rx() to enter the response-copy path for a fire-and-forget
transfer whose rxd is NULL.
Unconditionally assign the correct boolean value so the slot is fully
reset on every reuse.
Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver")
Signed-off-by: Titouan Ameline de Cadeville <titouan.ameline@gmail.com>
---
drivers/firmware/samsung/exynos-acpm.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
index 16c46ed60837..2fee6bb60efc 100644
--- a/drivers/firmware/samsung/exynos-acpm.c
+++ b/drivers/firmware/samsung/exynos-acpm.c
@@ -380,8 +380,7 @@ static void acpm_prepare_xfer(struct acpm_chan *achan,
/* Clear data for upcoming responses */
rx_data = &achan->rx_data[achan->seqnum - 1];
memset(rx_data->cmd, 0, sizeof(*rx_data->cmd) * rx_data->n_cmd);
- if (xfer->rxd)
- rx_data->response = true;
+ rx_data->response = !!xfer->rxd;
/* Flag the index based on seqnum. (seqnum: 1~63, bitmap: 0~62) */
set_bit(achan->seqnum - 1, achan->bitmap_seqnum);
--
2.44.2
^ permalink raw reply related
* Re: [PATCH 3/3] spi: rockchip: Drop dead zero-check on fifo_len
From: Mark Brown @ 2026-04-26 21:03 UTC (permalink / raw)
To: john madieu
Cc: heiko, jon.lin, linux-spi, linux-arm-kernel, linux-rockchip,
linux-kernel
In-Reply-To: <CAM9Qs9B8SSGXrR47toj9P+_EUHzrwKwHnu9askVhGxm9WFzQCQ@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 460 bytes --]
On Sun, Apr 26, 2026 at 10:57:31PM +0200, john madieu wrote:
> Le dim. 26 avr. 2026 à 22:36, Mark Brown <broonie@kernel.org> a écrit :
> > That looks like it's intended as a "you added a new hardware type and
> > forgot to fill in this field" type check intended to never fire in
> > production?
> Yes, that's a fair reading. I missed that angle.
> Should I drop this patch and resend the series (v2) with just 1/3 and 2/3 ?
No need to resend.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* [PATCH v2 0/3]: fix unnecessary includes and add missing ones across multiple drivers
From: Caio Morais @ 2026-04-26 21:17 UTC (permalink / raw)
To: andy, dlechner, jic23, michal.simek, nuno.sa
Cc: Caio Morais, linux-arm-kernel, linux-iio
From: Caio Morais <caiomorais@usp.br>
This series removes unnecessary includes and adds missing ones as reported
by the include-what-you-use (IWYU) tool across different IIO drivers.
Caio Morais (3):
iio: adc: xilinx-xadc: remove unnecessary includes and add missing
ones
iio: buffer: industrialio-triggered-buffer: fix includes with IWYU
iio: common: st_sensors: fix includes with IWYU
drivers/iio/adc/xilinx-xadc-events.c | 6 +++++-
drivers/iio/buffer/industrialio-triggered-buffer.c | 6 ++++--
drivers/iio/common/st_sensors/st_sensors_i2c.c | 7 +++++--
drivers/iio/common/st_sensors/st_sensors_spi.c | 9 +++++++--
4 files changed, 21 insertions(+), 7 deletions(-)
--
2.54.0
^ permalink raw reply
* [PATCH 1/3] iio: adc: xilinx-xadc: remove unnecessary includes and add missing ones
From: Caio Morais @ 2026-04-26 21:18 UTC (permalink / raw)
To: andy, dlechner, jic23, michal.simek, nuno.sa
Cc: Caio Morais, linux-arm-kernel, linux-iio
In-Reply-To: <20260426211834.3318306-1-caiomorais@usp.br>
From: Caio Morais <caiomorais@usp.br>
Signed-off-by: Caio Morais <caiomorais@usp.br>
---
drivers/iio/adc/xilinx-xadc-events.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/iio/adc/xilinx-xadc-events.c b/drivers/iio/adc/xilinx-xadc-events.c
index c188d3dca..31cda8e69 100644
--- a/drivers/iio/adc/xilinx-xadc-events.c
+++ b/drivers/iio/adc/xilinx-xadc-events.c
@@ -6,9 +6,13 @@
* Author: Lars-Peter Clausen <lars@metafoo.de>
*/
+#include <linux/bitmap.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+
#include <linux/iio/events.h>
#include <linux/iio/iio.h>
-#include <linux/kernel.h>
#include "xilinx-xadc.h"
--
2.54.0
^ permalink raw reply related
* [PATCH 2/3] iio: buffer: industrialio-triggered-buffer: fix includes with IWYU
From: Caio Morais @ 2026-04-26 21:18 UTC (permalink / raw)
To: andy, dlechner, jic23, michal.simek, nuno.sa
Cc: Caio Morais, linux-arm-kernel, linux-iio
In-Reply-To: <20260426211834.3318306-1-caiomorais@usp.br>
From: Caio Morais <caiomorais@usp.br>
Signed-off-by: Caio Morais <caiomorais@usp.br>
---
drivers/iio/buffer/industrialio-triggered-buffer.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/buffer/industrialio-triggered-buffer.c b/drivers/iio/buffer/industrialio-triggered-buffer.c
index 9bf75dee7..a91d439d7 100644
--- a/drivers/iio/buffer/industrialio-triggered-buffer.c
+++ b/drivers/iio/buffer/industrialio-triggered-buffer.c
@@ -4,9 +4,11 @@
* Author: Lars-Peter Clausen <lars@metafoo.de>
*/
-#include <linux/kernel.h>
-#include <linux/export.h>
+#include <linux/errno.h>
+#include <linux/linkage.h>
#include <linux/module.h>
+#include <linux/stddef.h>
+
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/buffer_impl.h>
--
2.54.0
^ permalink raw reply related
* [PATCH 3/3] iio: common: st_sensors: fix includes with IWYU
From: Caio Morais @ 2026-04-26 21:18 UTC (permalink / raw)
To: andy, dlechner, jic23, michal.simek, nuno.sa
Cc: Caio Morais, linux-arm-kernel, linux-iio
In-Reply-To: <20260426211834.3318306-1-caiomorais@usp.br>
From: Caio Morais <caiomorais@usp.br>
Signed-off-by: Caio Morais <caiomorais@usp.br>
---
drivers/iio/common/st_sensors/st_sensors_i2c.c | 7 +++++--
drivers/iio/common/st_sensors/st_sensors_spi.c | 9 +++++++--
2 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/drivers/iio/common/st_sensors/st_sensors_i2c.c b/drivers/iio/common/st_sensors/st_sensors_i2c.c
index 7156302fe..04d106def 100644
--- a/drivers/iio/common/st_sensors/st_sensors_i2c.c
+++ b/drivers/iio/common/st_sensors/st_sensors_i2c.c
@@ -7,12 +7,15 @@
* Denis Ciocca <denis.ciocca@st.com>
*/
+#include <linux/device.h>
+#include <linux/err.h>
#include <linux/i2c.h>
-#include <linux/kernel.h>
+#include <linux/linkage.h>
#include <linux/module.h>
-#include <linux/iio/iio.h>
#include <linux/regmap.h>
+#include <linux/iio/iio.h>
+
#include <linux/iio/common/st_sensors_i2c.h>
#define ST_SENSORS_I2C_MULTIREAD 0x80
diff --git a/drivers/iio/common/st_sensors/st_sensors_spi.c b/drivers/iio/common/st_sensors/st_sensors_spi.c
index 0da270139..884077d51 100644
--- a/drivers/iio/common/st_sensors/st_sensors_spi.c
+++ b/drivers/iio/common/st_sensors/st_sensors_spi.c
@@ -7,12 +7,17 @@
* Denis Ciocca <denis.ciocca@st.com>
*/
-#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/linkage.h>
#include <linux/module.h>
-#include <linux/iio/iio.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
+#include <linux/stddef.h>
+#include <linux/types.h>
+
+#include <linux/iio/iio.h>
#include <linux/iio/common/st_sensors_spi.h>
--
2.54.0
^ permalink raw reply related
* [PATCH v5 0/1] crypto: atmel-sha204a - multiple RNG fixes
From: Lothar Rubusch @ 2026-04-26 21:29 UTC (permalink / raw)
To: herbert, thorsten.blum, davem, nicolas.ferre, alexandre.belloni,
claudiu.beznea, ardb, linusw
Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch
When testing the RNG functionality on the Atmel SHA204a hardware, rngtest
reported failures. Fix start of reading and size of fetched data.
I verified and applied Ard's solution (tagged it with sugtgested-by, pls
tell me if I used the wrong tag).
Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
v3 -> v4: rephrase commit title; fix typos in commit message;
replace index literal by `RSP_DATA_IDX`
v3 -> v4: Reduce seet and set focus on RNG fix, blocking and nonblocking
v2 -> v3: Removal blank line, rebased
v1 -> v2: Removal of C++ style comment
---
Lothar Rubusch (1):
crypto: atmel-sha204a - fix blocking and non-blocking rng logic
drivers/crypto/atmel-sha204a.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
base-commit: 5db6ef9847717329f12c5ea8aba7e9f588a980c0
--
2.53.0
^ permalink raw reply
* [PATCH v5 1/1] crypto: atmel-sha204a - fix blocking and non-blocking rng logic
From: Lothar Rubusch @ 2026-04-26 21:29 UTC (permalink / raw)
To: herbert, thorsten.blum, davem, nicolas.ferre, alexandre.belloni,
claudiu.beznea, ardb, linusw
Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch
In-Reply-To: <20260426212947.24757-1-l.rubusch@gmail.com>
The blocking and non-blocking paths were failing to provide valid entropy
due to improper buffer management. Reading the buffer starting from byte 1,
only fetch the 32 bytes of random data from the return message.
Tested on an Atmel SHA204A device.
Before (here for blocking), tests showed repeatedly reading reduced bytes.
$ head -c 32 /dev/hwrng | hexdump -C
00000000 02 28 85 b3 47 40 f2 ee 00 00 00 00 00 00 00 00 |.(..G@..........|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020
After, the result will be similar to the following:
$ head -c 32 /dev/hwrng | hexdump -C
00000000 5a fc 3f 13 14 68 fe 06 68 0a bd 04 83 6e 09 69 |Z.?..h..h....n.i|
00000010 75 ff cf 87 10 84 3b c9 c1 df ae eb 45 53 4c c3 |u.....;.....ESL.|
00000020
Fixes: da001fb651b0 ("crypto: atmel-i2c - add support for SHA204A random number generator")
Suggested-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
drivers/crypto/atmel-sha204a.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c
index dbb39ed0cea1..5699bb532325 100644
--- a/drivers/crypto/atmel-sha204a.c
+++ b/drivers/crypto/atmel-sha204a.c
@@ -48,8 +48,8 @@ static int atmel_sha204a_rng_read_nonblocking(struct hwrng *rng, void *data,
if (rng->priv) {
work_data = (struct atmel_i2c_work_data *)rng->priv;
- max = min(sizeof(work_data->cmd.data), max);
- memcpy(data, &work_data->cmd.data, max);
+ max = min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max);
+ memcpy(data, &work_data->cmd.data[RSP_DATA_IDX], max);
rng->priv = 0;
} else {
work_data = kmalloc_obj(*work_data, GFP_ATOMIC);
@@ -87,8 +87,8 @@ static int atmel_sha204a_rng_read(struct hwrng *rng, void *data, size_t max,
if (ret)
return ret;
- max = min(sizeof(cmd.data), max);
- memcpy(data, cmd.data, max);
+ max = min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max);
+ memcpy(data, &cmd.data[RSP_DATA_IDX], max);
return max;
}
--
2.53.0
^ permalink raw reply related
* [PATCH v2] serial: mxs-auart: replace hardcoded 1 with predefined macro GPIO_LINE_DIRECTION_IN
From: Nikola Z. Ivanov @ 2026-04-26 21:42 UTC (permalink / raw)
To: gregkh, jirislaby, Frank.Li, s.hauer, kernel, festevam
Cc: linux-kernel, linux-serial, imx, linux-arm-kernel,
Nikola Z. Ivanov
The GPIO_LINE_DIRECTION_* definitions have just recently been exposed to
gpio consumers.h by breaking them out in a separate defs.h file.
Use this to validate the gpio direction instead of the hard-coded literal.
Signed-off-by: Nikola Z. Ivanov <zlatistiv@gmail.com>
---
Changes since v1:
- Commit title change
https://lore.kernel.org/all/26cd0656-ca76-4cb7-9f1e-b8c042a7e2cb@gmail.com/
drivers/tty/serial/mxs-auart.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 693b491f1e75..697318dbb146 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -1520,7 +1520,7 @@ static int mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev)
for (i = 0; i < UART_GPIO_MAX; i++) {
gpiod = mctrl_gpio_to_gpiod(s->gpios, i);
- if (gpiod && (gpiod_get_direction(gpiod) == 1))
+ if (gpiod && (gpiod_get_direction(gpiod) == GPIO_LINE_DIRECTION_IN))
s->gpio_irq[i] = gpiod_to_irq(gpiod);
else
s->gpio_irq[i] = -EINVAL;
--
2.53.0
^ permalink raw reply related
* Re: [REGRESSION] rseq: refactoring in v6.19 broke everyone on arm64 and tcmalloc everywhere
From: Thomas Gleixner @ 2026-04-26 22:04 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Mathias Stearn, Dmitry Vyukov, Jinjie Ruan, linux-man,
Mark Rutland, Mathieu Desnoyers, Catalin Marinas, Will Deacon,
Boqun Feng, Paul E. McKenney, Chris Kennelly, regressions,
linux-kernel, linux-arm-kernel, Ingo Molnar, Blake Oler,
Dmitry Vyukov, Florian Weimer, Rich Felker, Matthew Wilcox,
Greg Kroah-Hartman, Linus Torvalds
In-Reply-To: <87se8kywhb.ffs@tglx>
On Fri, Apr 24 2026 at 21:44, Thomas Gleixner wrote:
> On Fri, Apr 24 2026 at 17:03, Peter Zijlstra wrote:
>> On Fri, Apr 24, 2026 at 04:16:08PM +0200, Thomas Gleixner wrote:
>>> > I was really hoping that we would only need to do the "redundant"
>>> > cpu_id_start writes would only be needed on membarrier_rseq IPIs where
>>> > it really is a pay-for-what-you-use functionality,
>>>
>>> That's fine and can be solved without adding this sequence overhead into
>>> the scheduler hotpath.
>>
>> Something like so? (probably needs help for !GENERIC bits)
>
> Yes and yes :)
>
> Let me stare at that !generic tif bits case.
I stared at it and finally gave up because all of this is in a
completely FUBAR'ed state and ends up in a horrible pile of hacks and
duct tape with a way larger than zero probability that we chase the
nasty corner cases for quite some time just to add more duct tape and
hacks.
Contrary to that it's rather trivial to cleanly separate the behavioral
cases and guarantees without a masssive runtime overhead and without a
pile of hard to maintain TCMalloc specific hacks.
All required code is already available to support the architectures
which do not utilize the generic entry code and therefore can't neither
use the optimized mode nor time slice extensions. So instead of letting
the compiler optimize that code out for the generic entry code users, we
can keep it around and utilize one or the other depending on the
requested mode. I managed to get the required run-time conditionals down
to a minimum so that they are in the noise when analysing it with perf.
The real question is how to differentiate between the legacy and the
optimized mode. I have two working variants to achieve that:
1) The fully safe option requires a new flag for RSEQ
registration. It obviously requires a glibc update. (Suggested by
PeterZ)
2) Determine the requirements of the registering task via the size of
the registered RSEQ area.
The original implementation, which TCMalloc depends on, registers
a 32 byte region (ORIG_RSEG_SIZE). This region has 32 byte
alignment requirement.
The extension safe newer variant exposes the kernel RSEQ feature
size via getauxval(AT_RSEQ_FEATURE_SIZE) and the alignment
requirement via getauxval(AT_RSEQ_ALIGN). The alignment
requirement is that the registered rseq region is aligned to the
next power of two of the feature size. The kernel currently has a
feature size of 33 bytes, which means the alignment requirement is
64 bytes.
The TCMalloc RSEQ region is embedded into a cache line aligned
data structure starting at offset 32 bytes so that bytes 28-31 and
the cpu_id_start field at bytes 32-35 form a 64-bit little endian
pointer with the top-most bit (63 set) to check whether the kernel
has overwritten cpu_id_start with an actual CPU id value, which is
guaranteed to not have the top most bit set.
As this is part of their performance tuned magic, it's a pretty
safe assumption, that TCMalloc won't use a larger RSEQ size, which
allows to select optimized mode for registrations with a size
greater than 32 bytes.
That does not require any changes to glibc and works out of the
box. (Suggested by Mathieu)
In both cases the legacy non-optimized mode exposes the original
behaviour up to the mm_cid field and does not provide support for time
slice extensions. Optimized mode restores the performance gains and
enables support for time slice extensions.
I have no strong preference either way and have working code for both
variants. Though obviously avoiding to update the libc world has a
charme. If that unexpectedly would turn out to be not sufficient, then
disabling that would be a trivial one-liner and as a consequence require
to add the flag and update the libc world.
Combo patch for the auto-detection based on the registered size below as
that allows to immediately test without glibc dependencies. It applies
cleanly on Linus tree and 7.0. 6.19 would need some fixups, but I
learned today that it's already EOL.
In the final version that's three separate patches plus a set of
selftest changes which validate legacy behaviour and run the full param
test suite in both legacy and optimized mode.
Thoughts, preferences?
Thanks,
tglx
---
Documentation/userspace-api/rseq.rst | 77 ++++++++++++++
include/linux/rseq.h | 20 +++
include/linux/rseq_entry.h | 110 ++++++++++-----------
include/linux/rseq_types.h | 3
kernel/rseq.c | 183 ++++++++++++++++++++++-------------
kernel/sched/membarrier.c | 11 +-
6 files changed, 280 insertions(+), 124 deletions(-)
---
--- a/include/linux/rseq.h
+++ b/include/linux/rseq.h
@@ -9,6 +9,11 @@
void __rseq_handle_slowpath(struct pt_regs *regs);
+static __always_inline bool rseq_optimized(struct task_struct *t)
+{
+ return IS_ENABLED(CONFIG_GENERIC_IRQ_ENTRY) && likely(t->rseq.event.optimized);
+}
+
/* Invoked from resume_user_mode_work() */
static inline void rseq_handle_slowpath(struct pt_regs *regs)
{
@@ -30,7 +35,7 @@ void __rseq_signal_deliver(int sig, stru
*/
static inline void rseq_signal_deliver(struct ksignal *ksig, struct pt_regs *regs)
{
- if (IS_ENABLED(CONFIG_GENERIC_IRQ_ENTRY)) {
+ if (IS_ENABLED(CONFIG_GENERIC_IRQ_ENTRY) && rseq_optimized(current)) {
/* '&' is intentional to spare one conditional branch */
if (current->rseq.event.has_rseq & current->rseq.event.user_irq)
__rseq_signal_deliver(ksig->sig, regs);
@@ -50,15 +55,21 @@ static __always_inline void rseq_sched_s
{
struct rseq_event *ev = &t->rseq.event;
- if (IS_ENABLED(CONFIG_GENERIC_IRQ_ENTRY)) {
+ /*
+ * Only apply the user_irq optimization for RSEQ ABI V2
+ * registrations. Legacy users like TCMalloc rely on the historical ABI
+ * V1 behaviour which updates IDs on every context swtich.
+ */
+ if (IS_ENABLED(CONFIG_GENERIC_IRQ_ENTRY) && rseq_optimized(t)) {
/*
* Avoid a boat load of conditionals by using simple logic
* to determine whether NOTIFY_RESUME needs to be raised.
*
* It's required when the CPU or MM CID has changed or
- * the entry was from user space.
+ * the entry was from user space. ev->has_rseq does not
+ * have to be evaluated because optimized implies has_rseq.
*/
- bool raise = (ev->user_irq | ev->ids_changed) & ev->has_rseq;
+ bool raise = ev->user_irq | ev->ids_changed;
if (raise) {
ev->sched_switch = true;
@@ -66,6 +77,7 @@ static __always_inline void rseq_sched_s
}
} else {
if (ev->has_rseq) {
+ t->rseq.event.ids_changed = true;
t->rseq.event.sched_switch = true;
rseq_raise_notify_resume(t);
}
--- a/include/linux/rseq_entry.h
+++ b/include/linux/rseq_entry.h
@@ -111,6 +111,20 @@ static __always_inline void rseq_slice_c
t->rseq.slice.state.granted = false;
}
+/*
+ * Open coded, so it can be invoked within a user access region.
+ *
+ * This clears the user space state of the time slice extensions field only when
+ * the task has registered the optimized RSEQ_ABI V2. Some legacy registrations,
+ * e.g. TCMalloc, have conflicting non-ABI fields in struct RSEQ, which would be
+ * overwritten by an unconditional write.
+ */
+#define rseq_slice_clear_user(rseq, efault) \
+do { \
+ if (rseq_slice_extension_enabled()) \
+ unsafe_put_user(0U, &rseq->slice_ctrl.all, efault); \
+} while (0)
+
static __always_inline bool __rseq_grant_slice_extension(bool work_pending)
{
struct task_struct *curr = current;
@@ -230,10 +244,10 @@ static __always_inline bool rseq_slice_e
static __always_inline bool rseq_arm_slice_extension_timer(void) { return false; }
static __always_inline void rseq_slice_clear_grant(struct task_struct *t) { }
static __always_inline bool rseq_grant_slice_extension(unsigned long ti_work, unsigned long mask) { return false; }
+#define rseq_slice_clear_user(rseq, efault) do { } while (0)
#endif /* !CONFIG_RSEQ_SLICE_EXTENSION */
bool rseq_debug_update_user_cs(struct task_struct *t, struct pt_regs *regs, unsigned long csaddr);
-bool rseq_debug_validate_ids(struct task_struct *t);
static __always_inline void rseq_note_user_irq_entry(void)
{
@@ -353,43 +367,6 @@ bool rseq_debug_update_user_cs(struct ta
return false;
}
-/*
- * On debug kernels validate that user space did not mess with it if the
- * debug branch is enabled.
- */
-bool rseq_debug_validate_ids(struct task_struct *t)
-{
- struct rseq __user *rseq = t->rseq.usrptr;
- u32 cpu_id, uval, node_id;
-
- /*
- * On the first exit after registering the rseq region CPU ID is
- * RSEQ_CPU_ID_UNINITIALIZED and node_id in user space is 0!
- */
- node_id = t->rseq.ids.cpu_id != RSEQ_CPU_ID_UNINITIALIZED ?
- cpu_to_node(t->rseq.ids.cpu_id) : 0;
-
- scoped_user_read_access(rseq, efault) {
- unsafe_get_user(cpu_id, &rseq->cpu_id_start, efault);
- if (cpu_id != t->rseq.ids.cpu_id)
- goto die;
- unsafe_get_user(uval, &rseq->cpu_id, efault);
- if (uval != cpu_id)
- goto die;
- unsafe_get_user(uval, &rseq->node_id, efault);
- if (uval != node_id)
- goto die;
- unsafe_get_user(uval, &rseq->mm_cid, efault);
- if (uval != t->rseq.ids.mm_cid)
- goto die;
- }
- return true;
-die:
- t->rseq.event.fatal = true;
-efault:
- return false;
-}
-
#endif /* RSEQ_BUILD_SLOW_PATH */
/*
@@ -504,12 +481,32 @@ bool rseq_set_ids_get_csaddr(struct task
{
struct rseq __user *rseq = t->rseq.usrptr;
- if (static_branch_unlikely(&rseq_debug_enabled)) {
- if (!rseq_debug_validate_ids(t))
- return false;
- }
-
scoped_user_rw_access(rseq, efault) {
+ /* Validate the R/O fields for debug and optimized mode */
+ if (static_branch_unlikely(&rseq_debug_enabled) || rseq_optimized(t)) {
+ u32 cpu_id, uval, node_id;
+
+ /*
+ * On the first exit after registering the rseq region CPU ID is
+ * RSEQ_CPU_ID_UNINITIALIZED and node_id in user space is 0!
+ */
+ node_id = t->rseq.ids.cpu_id != RSEQ_CPU_ID_UNINITIALIZED ?
+ cpu_to_node(t->rseq.ids.cpu_id) : 0;
+
+ unsafe_get_user(cpu_id, &rseq->cpu_id_start, efault);
+ if (cpu_id != t->rseq.ids.cpu_id)
+ goto die;
+ unsafe_get_user(uval, &rseq->cpu_id, efault);
+ if (uval != cpu_id)
+ goto die;
+ unsafe_get_user(uval, &rseq->node_id, efault);
+ if (uval != node_id)
+ goto die;
+ unsafe_get_user(uval, &rseq->mm_cid, efault);
+ if (uval != t->rseq.ids.mm_cid)
+ goto die;
+ }
+
unsafe_put_user(ids->cpu_id, &rseq->cpu_id_start, efault);
unsafe_put_user(ids->cpu_id, &rseq->cpu_id, efault);
unsafe_put_user(node_id, &rseq->node_id, efault);
@@ -517,11 +514,9 @@ bool rseq_set_ids_get_csaddr(struct task
if (csaddr)
unsafe_get_user(*csaddr, &rseq->rseq_cs, efault);
- /* Open coded, so it's in the same user access region */
- if (rseq_slice_extension_enabled()) {
- /* Unconditionally clear it, no point in conditionals */
- unsafe_put_user(0U, &rseq->slice_ctrl.all, efault);
- }
+ /* RSEQ ABI V2 only operations */
+ if (rseq_optimized(t))
+ rseq_slice_clear_user(rseq, efault);
}
rseq_slice_clear_grant(t);
@@ -530,6 +525,9 @@ bool rseq_set_ids_get_csaddr(struct task
rseq_stat_inc(rseq_stats.ids);
rseq_trace_update(t, ids);
return true;
+
+die:
+ t->rseq.event.fatal = true;
efault:
return false;
}
@@ -612,6 +610,14 @@ static __always_inline bool rseq_exit_us
* interrupts disabled
*/
guard(pagefault)();
+ /*
+ * This optimization is only valid when the task registered for the
+ * optimized RSEQ_ABI_V2 variant. Some legacy users rely on the original
+ * RSEQ implementation behaviour which unconditionally updated the IDs.
+ * rseq_sched_switch_event() ensures that legacy registrations always
+ * have both sched_switch and ids_changed set, which is compatible with
+ * the historical TIF_NOTIFY_RESUME behaviour.
+ */
if (likely(!t->rseq.event.ids_changed)) {
struct rseq __user *rseq = t->rseq.usrptr;
/*
@@ -623,11 +629,9 @@ static __always_inline bool rseq_exit_us
scoped_user_rw_access(rseq, efault) {
unsafe_get_user(csaddr, &rseq->rseq_cs, efault);
- /* Open coded, so it's in the same user access region */
- if (rseq_slice_extension_enabled()) {
- /* Unconditionally clear it, no point in conditionals */
- unsafe_put_user(0U, &rseq->slice_ctrl.all, efault);
- }
+ /* RSEQ ABI V2 only operations */
+ if (rseq_optimized(t))
+ rseq_slice_clear_user(rseq, efault);
}
rseq_slice_clear_grant(t);
--- a/include/linux/rseq_types.h
+++ b/include/linux/rseq_types.h
@@ -18,6 +18,7 @@ struct rseq;
* @ids_changed: Indicator that IDs need to be updated
* @user_irq: True on interrupt entry from user mode
* @has_rseq: True if the task has a rseq pointer installed
+ * @optimized: RSEQ ABI V2 optimized mode
* @error: Compound error code for the slow path to analyze
* @fatal: User space data corrupted or invalid
* @slowpath: Indicator that slow path processing via TIF_NOTIFY_RESUME
@@ -41,7 +42,7 @@ struct rseq_event {
};
u8 has_rseq;
- u8 __pad;
+ u8 optimized;
union {
u16 error;
struct {
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -258,11 +258,15 @@ static bool rseq_handle_cs(struct task_s
static void rseq_slowpath_update_usr(struct pt_regs *regs)
{
/*
- * Preserve rseq state and user_irq state. The generic entry code
- * clears user_irq on the way out, the non-generic entry
- * architectures are not having user_irq.
- */
- const struct rseq_event evt_mask = { .has_rseq = true, .user_irq = true, };
+ * Preserve has_rseq, optimized and user_irq state. The generic entry
+ * code clears user_irq on the way out, the non-generic entry
+ * architectures are not setting user_irq.
+ */
+ const struct rseq_event evt_mask = {
+ .has_rseq = true,
+ .user_irq = true,
+ .optimized = true,
+ };
struct task_struct *t = current;
struct rseq_ids ids;
u32 node_id;
@@ -335,8 +339,9 @@ void __rseq_handle_slowpath(struct pt_re
void __rseq_signal_deliver(int sig, struct pt_regs *regs)
{
rseq_stat_inc(rseq_stats.signal);
+
/*
- * Don't update IDs, they are handled on exit to user if
+ * Don't update IDs yet, they are handled on exit to user if
* necessary. The important thing is to abort a critical section of
* the interrupted context as after this point the instruction
* pointer in @regs points to the signal handler.
@@ -349,6 +354,13 @@ void __rseq_signal_deliver(int sig, stru
current->rseq.event.error = 0;
force_sigsegv(sig);
}
+
+ /*
+ * In legacy mode, force the update of IDs before returning to user
+ * space to stay compatible.
+ */
+ if (!rseq_optimized(current))
+ rseq_force_update();
}
/*
@@ -404,66 +416,19 @@ static bool rseq_reset_ids(void)
/* The original rseq structure size (including padding) is 32 bytes. */
#define ORIG_RSEQ_SIZE 32
-/*
- * sys_rseq - setup restartable sequences for caller thread.
- */
-SYSCALL_DEFINE4(rseq, struct rseq __user *, rseq, u32, rseq_len, int, flags, u32, sig)
+static long rseq_register(struct rseq __user * rseq, u32 rseq_len, int flags, u32 sig)
{
+ bool optimized = IS_ENABLED(CONFIG_GENERIC_IRQ_ENTRY) && rseq_len > ORIG_RSEQ_SIZE;
u32 rseqfl = 0;
- if (flags & RSEQ_FLAG_UNREGISTER) {
- if (flags & ~RSEQ_FLAG_UNREGISTER)
- return -EINVAL;
- /* Unregister rseq for current thread. */
- if (current->rseq.usrptr != rseq || !current->rseq.usrptr)
- return -EINVAL;
- if (rseq_len != current->rseq.len)
- return -EINVAL;
- if (current->rseq.sig != sig)
- return -EPERM;
- if (!rseq_reset_ids())
- return -EFAULT;
- rseq_reset(current);
- return 0;
- }
-
- if (unlikely(flags & ~(RSEQ_FLAG_SLICE_EXT_DEFAULT_ON)))
- return -EINVAL;
-
- if (current->rseq.usrptr) {
- /*
- * If rseq is already registered, check whether
- * the provided address differs from the prior
- * one.
- */
- if (current->rseq.usrptr != rseq || rseq_len != current->rseq.len)
- return -EINVAL;
- if (current->rseq.sig != sig)
- return -EPERM;
- /* Already registered. */
- return -EBUSY;
- }
-
- /*
- * If there was no rseq previously registered, ensure the provided rseq
- * is properly aligned, as communcated to user-space through the ELF
- * auxiliary vector AT_RSEQ_ALIGN. If rseq_len is the original rseq
- * size, the required alignment is the original struct rseq alignment.
- *
- * The rseq_len is required to be greater or equal to the original rseq
- * size. In order to be valid, rseq_len is either the original rseq size,
- * or large enough to contain all supported fields, as communicated to
- * user-space through the ELF auxiliary vector AT_RSEQ_FEATURE_SIZE.
- */
- if (rseq_len < ORIG_RSEQ_SIZE ||
- (rseq_len == ORIG_RSEQ_SIZE && !IS_ALIGNED((unsigned long)rseq, ORIG_RSEQ_SIZE)) ||
- (rseq_len != ORIG_RSEQ_SIZE && (!IS_ALIGNED((unsigned long)rseq, rseq_alloc_align()) ||
- rseq_len < offsetof(struct rseq, end))))
- return -EINVAL;
if (!access_ok(rseq, rseq_len))
return -EFAULT;
- if (IS_ENABLED(CONFIG_RSEQ_SLICE_EXTENSION)) {
+ /*
+ * The optimized check disables time slice extensions for legacy
+ * registrations.
+ */
+ if (IS_ENABLED(CONFIG_RSEQ_SLICE_EXTENSION) && optimized) {
rseqfl |= RSEQ_CS_FLAG_SLICE_EXT_AVAILABLE;
if (rseq_slice_extension_enabled() &&
(flags & RSEQ_FLAG_SLICE_EXT_DEFAULT_ON))
@@ -485,7 +450,15 @@ SYSCALL_DEFINE4(rseq, struct rseq __user
unsafe_put_user(RSEQ_CPU_ID_UNINITIALIZED, &rseq->cpu_id, efault);
unsafe_put_user(0U, &rseq->node_id, efault);
unsafe_put_user(0U, &rseq->mm_cid, efault);
- unsafe_put_user(0U, &rseq->slice_ctrl.all, efault);
+
+ /*
+ * All fields past mm_cid are only valid for non-legacy registrations
+ * which register with rseq_len > ORIG_RSEQ_SIZE.
+ */
+ if (optimized) {
+ if (IS_ENABLED(CONFIG_RSEQ_SLICE_EXTENSION))
+ unsafe_put_user(0U, &rseq->slice_ctrl.all, efault);
+ }
}
/*
@@ -501,11 +474,11 @@ SYSCALL_DEFINE4(rseq, struct rseq __user
#endif
/*
- * If rseq was previously inactive, and has just been
- * registered, ensure the cpu_id_start and cpu_id fields
- * are updated before returning to user-space.
+ * Ensure the cpu_id_start and cpu_id fields are updated before
+ * returning to user-space.
*/
current->rseq.event.has_rseq = true;
+ current->rseq.event.optimized = optimized;
rseq_force_update();
return 0;
@@ -513,6 +486,86 @@ SYSCALL_DEFINE4(rseq, struct rseq __user
return -EFAULT;
}
+static long rseq_unregister(struct rseq __user * rseq, u32 rseq_len, int flags, u32 sig)
+{
+ if (flags & ~RSEQ_FLAG_UNREGISTER)
+ return -EINVAL;
+ if (current->rseq.usrptr != rseq || !current->rseq.usrptr)
+ return -EINVAL;
+ if (rseq_len != current->rseq.len)
+ return -EINVAL;
+ if (current->rseq.sig != sig)
+ return -EPERM;
+ if (!rseq_reset_ids())
+ return -EFAULT;
+ rseq_reset(current);
+ return 0;
+}
+
+static long rseq_reregister(struct rseq __user * rseq, u32 rseq_len, u32 sig)
+{
+ /*
+ * If rseq is already registered, check whether the provided address
+ * differs from the prior one.
+ */
+ if (current->rseq.usrptr != rseq || rseq_len != current->rseq.len)
+ return -EINVAL;
+ if (current->rseq.sig != sig)
+ return -EPERM;
+ /* Already registered. */
+ return -EBUSY;
+}
+
+static bool rseq_length_valid(struct rseq __user *rseq, unsigned int rseq_len)
+{
+ if (rseq_len < ORIG_RSEQ_SIZE)
+ return false;
+
+ /*
+ * Ensure the provided rseq is properly aligned, as communicated to
+ * user-space through the ELF auxiliary vector AT_RSEQ_ALIGN. If
+ * rseq_len is the original rseq size, the required alignment is the
+ * original struct rseq alignment.
+ *
+ * The rseq_len is required to be greater or equal than the original
+ * rseq size.
+ *
+ * In order to be valid, rseq_len is either the original rseq size, or
+ * large enough to contain all supported fields, as communicated to
+ * user-space through the ELF auxiliary vector AT_RSEQ_FEATURE_SIZE.
+ */
+ if (rseq_len < ORIG_RSEQ_SIZE)
+ return false;
+
+ if (rseq_len == ORIG_RSEQ_SIZE)
+ return IS_ALIGNED((unsigned long)rseq, ORIG_RSEQ_SIZE);
+
+ return IS_ALIGNED((unsigned long)rseq, rseq_alloc_align()) &&
+ rseq_len >= offsetof(struct rseq, end);
+}
+
+#define RSEQ_FLAGS_SUPPORTED (RSEQ_FLAG_SLICE_EXT_DEFAULT_ON)
+
+/*
+ * sys_rseq - Register or unregister restartable sequences for the caller thread.
+ */
+SYSCALL_DEFINE4(rseq, struct rseq __user *, rseq, u32, rseq_len, int, flags, u32, sig)
+{
+ if (flags & RSEQ_FLAG_UNREGISTER)
+ return rseq_unregister(rseq, rseq_len, flags, sig);
+
+ if (unlikely(flags & ~RSEQ_FLAGS_SUPPORTED))
+ return -EINVAL;
+
+ if (current->rseq.usrptr)
+ return rseq_reregister(rseq, rseq_len, sig);
+
+ if (!rseq_length_valid(rseq, rseq_len))
+ return -EINVAL;
+
+ return rseq_register(rseq, rseq_len, flags, sig);
+}
+
#ifdef CONFIG_RSEQ_SLICE_EXTENSION
struct slice_timer {
struct hrtimer timer;
@@ -713,6 +766,8 @@ int rseq_slice_extension_prctl(unsigned
return -ENOTSUPP;
if (!current->rseq.usrptr)
return -ENXIO;
+ if (!current->rseq.event.optimized)
+ return -ENOTSUPP;
/* No change? */
if (enable == !!current->rseq.slice.state.enabled)
--- a/kernel/sched/membarrier.c
+++ b/kernel/sched/membarrier.c
@@ -199,7 +199,16 @@ static void ipi_rseq(void *info)
* is negligible.
*/
smp_mb();
- rseq_sched_switch_event(current);
+ /*
+ * Legacy mode requires that IDs are written and the critical section is
+ * evaluated. Optimized mode handles the critical section and IDs are
+ * only updated if they change as a consequence of preemption after
+ * return from this IPI.
+ */
+ if (rseq_optimized(current))
+ rseq_sched_switch_event(current);
+ else
+ rseq_force_update();
}
static void ipi_sync_rq_state(void *info)
--- a/Documentation/userspace-api/rseq.rst
+++ b/Documentation/userspace-api/rseq.rst
@@ -24,6 +24,80 @@ Quick access to CPU number, node ID
Allows to implement per CPU data efficiently. Documentation is in code and
selftests. :(
+Optimized RSEQ V2
+-----------------
+
+On architectures which utilize the generic entry code and generic TIF bits
+the kernel supports runtime optimizations for RSEQ, which also enable
+enhanced features like scheduler time slice extensions.
+
+To enable them a task has to register the RSEQ region with at least the
+length advertised by getauxval(AT_RSEQ_FEATURE_SIZE).
+
+If existing binaries register with RSEQ_ORIG_SIZE (32 bytes), the kernel
+keeps the legacy low performance mode enabled to fulfil the expectations
+existing users regarding the original RSEQ implementation behaviour.
+
+The following table documents the ABI and behavioral guarantees of the
+legacy and the optimized V2 mode.
+
+.. list-table:: RSEQ modes
+ :header-rows: 1
+
+ * - Nr
+ - What
+ - Legacy
+ - Optimized V2
+ * - 1
+ - The cpu_id_start, cpu_id, node_id and mm_cid fields (User mode read
+ only)
+ - Updated by the kernel unconditionally after each context switch and
+ before signal delivery
+ - Updated by the kernel if and only if they change, i.e. if the task
+ is migrated or mm_cid changes
+ * - 2
+ - The rseq_cs critical section field
+ - Evaluated and handled unconditionally after each context switch and
+ before signal delivery
+ - Evaluated and handled conditionally only when user space was
+ interrupted. Either after being preempted or before signal delivery
+ in the interrupted context.
+ * - 3
+ - Read only fields
+ - No strict enforcement except in debug mode
+ - Strict enforcement
+ * - 4
+ - membarrier(...RSEQ)
+ - All running threads of the process are interrupted and the ID fields
+ are rewritten and eventually active critical sections are aborted
+ before they return to user space. All threads which are scheduled
+ out whether voluntary or not are covered by #1/#2 above.
+ - All running threads of the process are interrupted and eventually
+ active critical sections are aborted before these threads return to
+ user space. The ID fields are only updated if changed as a
+ consequence of the interrupt. All threads which are scheduled out
+ whether voluntary not are covered by #1/#2 above.
+ * - 5
+ - Time slice extensions
+ - Not supported
+ - Supported
+
+The legacy mode is obviously less performant as it does unconditional
+updates and critical section checks even if not strictly required by the
+ABI contract. That can't be changed anymore as some users depend on that
+observed behavior, which in turn enables them to violate the ABI and
+overwrite the cpu_id_start field for their own purposes. This is obviously
+discouraged as it renders RSEQ incompatible with the intended usage and
+breaks the expectation of other libraries in the same application.
+
+The ABI compliant optimized mode, which respects the read only fields, does
+not require unconditional updates and therefore is way more performant. The
+kernel validates the read only fields for compliance. If user space
+modifies them, the process is killed. Compliant usage allows multiple
+libraries in the same application to benefit from the RSEQ functionality
+without disturbing each other.
+
+
Scheduler time slice extensions
-------------------------------
@@ -37,7 +111,8 @@ scheduled out inside of the critical sec
* Enabled at boot time (default is enabled)
- * A rseq userspace pointer has been registered for the thread
+ * A rseq userspace pointer has been registered for the thread in
+ optimized V2 mode
The thread has to enable the functionality via prctl(2)::
^ permalink raw reply
* [GIT PULL] Mailbox changes for v7.1
From: Jassi Brar @ 2026-04-26 22:51 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-arm-kernel, Linux Kernel Mailing List
Hi Linus,
The following changes since commit 11439c4635edd669ae435eec308f4ab8a0804808:
Linux 7.0-rc2 (2026-03-01 15:39:31 -0800)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/jassibrar/mailbox.git
tags/mailbox-v7.1
for you to fetch changes up to 6e937f4e769e60947909e3525965f0137b9039e8:
mailbox: mailbox-test: make data_ready a per-instance variable
(2026-04-18 13:10:14 -0500)
----------------------------------------------------------------
mailbox: updates for v7.1
- core: fix NULL message handling and add API to query TX queue slots
- test: resolve concurrency bugs, dangling IRQs, and memory leaks
- dt-bindings: qcom: add Eliza IPCC
- mtk: fix address calculation and pointer handling bugs
- cix: resolve SCMI suspend timeouts
- misc memory allocation optimizations and cleanups
----------------------------------------------------------------
Abel Vesa (1):
dt-bindings: mailbox: qcom-ipcc: Document the Eliza
Inter-Processor Communication Controller
Dylan Wu (1):
mailbox: cix: Add IRQF_NO_SUSPEND to mailbox interrupt
Felix Gu (1):
mailbox: mtk-vcp-mailbox: Fix the return value in mtk_vcp_mbox_xlate()
Jason-JH Lin (1):
mailbox: mtk-cmdq: Fix CURR and END addr for task insert case
Jassi Brar (2):
mailbox: add API to query available TX queue slots
mailbox: Fix NULL message support in mbox_send_message()
Rosen Penev (2):
mailbox: rockchip: kzalloc + kcalloc to kzalloc
mailbox: hi6220: kzalloc + kcalloc to kzalloc
Wolfram Sang (12):
mailbox: exynos: drop superfluous mbox setting per channel
mailbox: test: really ignore optional memory resources
mailbox: correct kdoc title for mbox_bind_client
mailbox: remove superfluous internal header
mailbox: prefix new constants with MBOX_
mailbox: mailbox-test: free channels on probe error
mailbox: add sanity check for channel array
mailbox: update kdoc for struct mbox_controller
mailbox: mailbox-test: handle channel errors consistently
mailbox: mailbox-test: don't free the reused channel
mailbox: mailbox-test: initialize struct earlier
mailbox: mailbox-test: make data_ready a per-instance variable
.../devicetree/bindings/mailbox/qcom-ipcc.yaml | 1 +
drivers/mailbox/cix-mailbox.c | 6 +-
drivers/mailbox/exynos-mailbox.c | 4 --
drivers/mailbox/hi3660-mailbox.c | 2 -
drivers/mailbox/hi6220-mailbox.c | 14 ++--
drivers/mailbox/imx-mailbox.c | 4 +-
drivers/mailbox/mailbox-sti.c | 2 -
drivers/mailbox/mailbox-test.c | 80 +++++++++++++---------
drivers/mailbox/mailbox.c | 67 +++++++++++-------
drivers/mailbox/mailbox.h | 12 ----
drivers/mailbox/mtk-cmdq-mailbox.c | 10 +--
drivers/mailbox/mtk-vcp-mailbox.c | 2 +-
drivers/mailbox/omap-mailbox.c | 4 +-
drivers/mailbox/pcc.c | 2 -
drivers/mailbox/rockchip-mailbox.c | 9 +--
drivers/mailbox/tegra-hsp.c | 6 +-
include/linux/mailbox_client.h | 1 +
include/linux/mailbox_controller.h | 17 +++--
18 files changed, 124 insertions(+), 119 deletions(-)
delete mode 100644 drivers/mailbox/mailbox.h
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox